/*
 * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.security.ec;

import java.util.*;
import java.security.*;
import java.util.regex.Pattern;
import sun.security.util.CurveDB;
import sun.security.util.NamedCurve;

import static sun.security.util.SecurityConstants.PROVIDER_VER;

Provider class for the Elliptic Curve provider. Supports EC keypair and parameter generation, ECDSA signing and ECDH key agreement. IMPLEMENTATION NOTE: The Java classes in this provider access a native ECC implementation via JNI to a C++ wrapper class which in turn calls C functions. The Java classes are packaged into the jdk.crypto.sunec module and the C++ and C functions are packaged into libsunec.so or sunec.dll in the JRE native libraries directory. If the native library is not present then this provider is registered with support for fewer ECC algorithms (KeyPairGenerator, Signature and KeyAgreement are omitted).
Since: 1.7
/** * Provider class for the Elliptic Curve provider. * Supports EC keypair and parameter generation, ECDSA signing and * ECDH key agreement. * * IMPLEMENTATION NOTE: * The Java classes in this provider access a native ECC implementation * via JNI to a C++ wrapper class which in turn calls C functions. * The Java classes are packaged into the jdk.crypto.sunec module and the * C++ and C functions are packaged into libsunec.so or sunec.dll in the * JRE native libraries directory. If the native library is not present * then this provider is registered with support for fewer ECC algorithms * (KeyPairGenerator, Signature and KeyAgreement are omitted). * * @since 1.7 */
public final class SunEC extends Provider { private static final long serialVersionUID = -2279741672933606418L; // flag indicating whether the full EC implementation is present // (when native library is absent then fewer EC algorithms are available) private static boolean useFullImplementation = true; static { try { AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run() { System.loadLibrary("sunec"); // check for native library return null; } }); } catch (UnsatisfiedLinkError e) { useFullImplementation = false; } } private static class ProviderService extends Provider.Service { ProviderService(Provider p, String type, String algo, String cn) { super(p, type, algo, cn, null, null); } ProviderService(Provider p, String type, String algo, String cn, String[] aliases, HashMap<String, String> attrs) { super(p, type, algo, cn, (aliases == null? null : Arrays.asList(aliases)), attrs); } @Override public Object newInstance(Object ctrParamObj) throws NoSuchAlgorithmException { String type = getType(); if (ctrParamObj != null) { throw new InvalidParameterException ("constructorParameter not used with " + type + " engines"); } String algo = getAlgorithm(); try { if (type.equals("Signature")) { boolean inP1363 = algo.endsWith("inP1363Format"); if (inP1363) { algo = algo.substring(0, algo.length() - 13); } if (algo.equals("SHA1withECDSA")) { return (inP1363? new ECDSASignature.SHA1inP1363Format() : new ECDSASignature.SHA1()); } else if (algo.equals("SHA224withECDSA")) { return (inP1363? new ECDSASignature.SHA224inP1363Format() : new ECDSASignature.SHA224()); } else if (algo.equals("SHA256withECDSA")) { return (inP1363? new ECDSASignature.SHA256inP1363Format() : new ECDSASignature.SHA256()); } else if (algo.equals("SHA384withECDSA")) { return (inP1363? new ECDSASignature.SHA384inP1363Format() : new ECDSASignature.SHA384()); } else if (algo.equals("SHA512withECDSA")) { return (inP1363? new ECDSASignature.SHA512inP1363Format() : new ECDSASignature.SHA512()); } else if (algo.equals("NONEwithECDSA")) { return (inP1363? new ECDSASignature.RawinP1363Format() : new ECDSASignature.Raw()); } } else if (type.equals("KeyFactory")) { if (algo.equals("EC")) { return new ECKeyFactory(); } else if (algo.equals("XDH")) { return new XDHKeyFactory(); } else if (algo.equals("X25519")) { return new XDHKeyFactory.X25519(); } else if (algo.equals("X448")) { return new XDHKeyFactory.X448(); } } else if (type.equals("AlgorithmParameters")) { if (algo.equals("EC")) { return new sun.security.util.ECParameters(); } } else if (type.equals("KeyPairGenerator")) { if (algo.equals("EC")) { return new ECKeyPairGenerator(); } else if (algo.equals("XDH")) { return new XDHKeyPairGenerator(); } else if (algo.equals("X25519")) { return new XDHKeyPairGenerator.X25519(); } else if (algo.equals("X448")) { return new XDHKeyPairGenerator.X448(); } } else if (type.equals("KeyAgreement")) { if (algo.equals("ECDH")) { return new ECDHKeyAgreement(); } else if (algo.equals("XDH")) { return new XDHKeyAgreement(); } else if (algo.equals("X25519")) { return new XDHKeyAgreement.X25519(); } else if (algo.equals("X448")) { return new XDHKeyAgreement.X448(); } } } catch (Exception ex) { throw new NoSuchAlgorithmException("Error constructing " + type + " for " + algo + " using SunEC", ex); } throw new ProviderException("No impl for " + algo + " " + type); } } public SunEC() { super("SunEC", PROVIDER_VER, "Sun Elliptic Curve provider (EC, ECDSA, ECDH)"); AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run() { putEntries(useFullImplementation); return null; } }); } void putEntries(boolean useFullImplementation) { HashMap<String, String> ATTRS = new HashMap<>(3); ATTRS.put("ImplementedIn", "Software"); String ecKeyClasses = "java.security.interfaces.ECPublicKey" + "|java.security.interfaces.ECPrivateKey"; ATTRS.put("SupportedKeyClasses", ecKeyClasses); ATTRS.put("KeySize", "256"); /* * Key Factory engine */ putService(new ProviderService(this, "KeyFactory", "EC", "sun.security.ec.ECKeyFactory", new String[] { "EllipticCurve" }, ATTRS)); /* * Algorithm Parameter engine */ // "AlgorithmParameters.EC SupportedCurves" prop used by unit test boolean firstCurve = true; StringBuilder names = new StringBuilder(); Pattern nameSplitPattern = Pattern.compile(CurveDB.SPLIT_PATTERN); Collection<? extends NamedCurve> supportedCurves = CurveDB.getSupportedCurves(); for (NamedCurve namedCurve : supportedCurves) { if (!firstCurve) { names.append("|"); } else { firstCurve = false; } names.append("["); String[] commonNames = nameSplitPattern.split(namedCurve.getName()); for (String commonName : commonNames) { names.append(commonName.trim()); names.append(","); } names.append(namedCurve.getObjectId()); names.append("]"); } HashMap<String, String> apAttrs = new HashMap<>(ATTRS); apAttrs.put("SupportedCurves", names.toString()); putService(new ProviderService(this, "AlgorithmParameters", "EC", "sun.security.util.ECParameters", new String[] { "EllipticCurve", "1.2.840.10045.2.1", "OID.1.2.840.10045.2.1" }, apAttrs)); putXDHEntries(); /* * Register the algorithms below only when the full ECC implementation * is available */ if (!useFullImplementation) { return; } /* * Signature engines */ putService(new ProviderService(this, "Signature", "NONEwithECDSA", "sun.security.ec.ECDSASignature$Raw", null, ATTRS)); putService(new ProviderService(this, "Signature", "SHA1withECDSA", "sun.security.ec.ECDSASignature$SHA1", new String[] { "1.2.840.10045.4.1", "OID.1.2.840.10045.4.1" }, ATTRS)); putService(new ProviderService(this, "Signature", "SHA224withECDSA", "sun.security.ec.ECDSASignature$SHA224", new String[] { "1.2.840.10045.4.3.1", "OID.1.2.840.10045.4.3.1"}, ATTRS)); putService(new ProviderService(this, "Signature", "SHA256withECDSA", "sun.security.ec.ECDSASignature$SHA256", new String[] { "1.2.840.10045.4.3.2", "OID.1.2.840.10045.4.3.2"}, ATTRS)); putService(new ProviderService(this, "Signature", "SHA384withECDSA", "sun.security.ec.ECDSASignature$SHA384", new String[] { "1.2.840.10045.4.3.3", "OID.1.2.840.10045.4.3.3" }, ATTRS)); putService(new ProviderService(this, "Signature", "SHA512withECDSA", "sun.security.ec.ECDSASignature$SHA512", new String[] { "1.2.840.10045.4.3.4", "OID.1.2.840.10045.4.3.4" }, ATTRS)); putService(new ProviderService(this, "Signature", "NONEwithECDSAinP1363Format", "sun.security.ec.ECDSASignature$RawinP1363Format")); putService(new ProviderService(this, "Signature", "SHA1withECDSAinP1363Format", "sun.security.ec.ECDSASignature$SHA1inP1363Format")); putService(new ProviderService(this, "Signature", "SHA224withECDSAinP1363Format", "sun.security.ec.ECDSASignature$SHA224inP1363Format")); putService(new ProviderService(this, "Signature", "SHA256withECDSAinP1363Format", "sun.security.ec.ECDSASignature$SHA256inP1363Format")); putService(new ProviderService(this, "Signature", "SHA384withECDSAinP1363Format", "sun.security.ec.ECDSASignature$SHA384inP1363Format")); putService(new ProviderService(this, "Signature", "SHA512withECDSAinP1363Format", "sun.security.ec.ECDSASignature$SHA512inP1363Format")); /* * Key Pair Generator engine */ putService(new ProviderService(this, "KeyPairGenerator", "EC", "sun.security.ec.ECKeyPairGenerator", new String[] { "EllipticCurve" }, ATTRS)); /* * Key Agreement engine */ putService(new ProviderService(this, "KeyAgreement", "ECDH", "sun.security.ec.ECDHKeyAgreement", null, ATTRS)); } private void putXDHEntries() { HashMap<String, String> ATTRS = new HashMap<>(1); ATTRS.put("ImplementedIn", "Software"); /* XDH does not require native implementation */ putService(new ProviderService(this, "KeyFactory", "XDH", "sun.security.ec.XDHKeyFactory", null, ATTRS)); putService(new ProviderService(this, "KeyFactory", "X25519", "sun.security.ec.XDHKeyFactory.X25519", new String[]{"1.3.101.110", "OID.1.3.101.110"}, ATTRS)); putService(new ProviderService(this, "KeyFactory", "X448", "sun.security.ec.XDHKeyFactory.X448", new String[]{"1.3.101.111", "OID.1.3.101.111"}, ATTRS)); putService(new ProviderService(this, "KeyPairGenerator", "XDH", "sun.security.ec.XDHKeyPairGenerator", null, ATTRS)); putService(new ProviderService(this, "KeyPairGenerator", "X25519", "sun.security.ec.XDHKeyPairGenerator.X25519", new String[]{"1.3.101.110", "OID.1.3.101.110"}, ATTRS)); putService(new ProviderService(this, "KeyPairGenerator", "X448", "sun.security.ec.XDHKeyPairGenerator.X448", new String[]{"1.3.101.111", "OID.1.3.101.111"}, ATTRS)); putService(new ProviderService(this, "KeyAgreement", "XDH", "sun.security.ec.XDHKeyAgreement", null, ATTRS)); putService(new ProviderService(this, "KeyAgreement", "X25519", "sun.security.ec.XDHKeyAgreement.X25519", new String[]{"1.3.101.110", "OID.1.3.101.110"}, ATTRS)); putService(new ProviderService(this, "KeyAgreement", "X448", "sun.security.ec.XDHKeyAgreement.X448", new String[]{"1.3.101.111", "OID.1.3.101.111"}, ATTRS)); } }