1 /* 2 * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.security.ec; 27 28 import java.util.*; 29 import java.security.*; 30 import java.util.regex.Pattern; 31 import sun.security.util.CurveDB; 32 import sun.security.util.NamedCurve; 33 import sun.security.util.ECParameters; 34 import static sun.security.util.SecurityConstants.PROVIDER_VER; 35 36 /** 37 * Provider class for the Elliptic Curve provider. 38 * Supports EC keypair and parameter generation, ECDSA signing and 39 * ECDH key agreement. 40 * 41 * IMPLEMENTATION NOTE: 42 * The Java classes in this provider access a native ECC implementation 43 * via JNI to a C++ wrapper class which in turn calls C functions. 44 * The Java classes are packaged into the jdk.crypto.sunec module and the 45 * C++ and C functions are packaged into libsunec.so or sunec.dll in the 46 * JRE native libraries directory. If the native library is not present 47 * then this provider is registered with support for fewer ECC algorithms 48 * (KeyPairGenerator, Signature and KeyAgreement are omitted). 49 * 50 * @since 1.7 51 */ 52 public final class SunEC extends Provider { 53 54 private static final long serialVersionUID = -2279741672933606418L; 55 56 // flag indicating whether the full EC implementation is present 57 // (when native library is absent then fewer EC algorithms are available) 58 private static boolean useFullImplementation = true; 59 static { 60 try { 61 AccessController.doPrivileged(new PrivilegedAction<Void>() { 62 public Void run() { 63 System.loadLibrary("sunec"); // check for native library 64 return null; 65 } 66 }); 67 } catch (UnsatisfiedLinkError e) { 68 useFullImplementation = false; 69 } 70 } 71 72 private static class ProviderService extends Provider.Service { 73 74 ProviderService(Provider p, String type, String algo, String cn) { 75 super(p, type, algo, cn, null, null); 76 } 77 78 ProviderService(Provider p, String type, String algo, String cn, 79 String[] aliases, HashMap<String, String> attrs) { 80 super(p, type, algo, cn, 81 (aliases == null? null : Arrays.asList(aliases)), attrs); 82 } 83 84 @Override 85 public Object newInstance(Object ctrParamObj) 86 throws NoSuchAlgorithmException { 87 String type = getType(); 88 if (ctrParamObj != null) { 89 throw new InvalidParameterException 90 ("constructorParameter not used with " + type + " engines"); 91 } 92 93 String algo = getAlgorithm(); 94 try { 95 if (type.equals("Signature")) { 96 boolean inP1363 = algo.endsWith("inP1363Format"); 97 if (inP1363) { 98 algo = algo.substring(0, algo.length() - 13); 99 } 100 if (algo.equals("SHA1withECDSA")) { 101 return (inP1363? new ECDSASignature.SHA1inP1363Format() : 102 new ECDSASignature.SHA1()); 103 } else if (algo.equals("SHA224withECDSA")) { 104 return (inP1363? new ECDSASignature.SHA224inP1363Format() : 105 new ECDSASignature.SHA224()); 106 } else if (algo.equals("SHA256withECDSA")) { 107 return (inP1363? new ECDSASignature.SHA256inP1363Format() : 108 new ECDSASignature.SHA256()); 109 } else if (algo.equals("SHA384withECDSA")) { 110 return (inP1363? new ECDSASignature.SHA384inP1363Format() : 111 new ECDSASignature.SHA384()); 112 } else if (algo.equals("SHA512withECDSA")) { 113 return (inP1363? new ECDSASignature.SHA512inP1363Format() : 114 new ECDSASignature.SHA512()); 115 } else if (algo.equals("NONEwithECDSA")) { 116 return (inP1363? new ECDSASignature.RawinP1363Format() : 117 new ECDSASignature.Raw()); 118 } 119 } else if (type.equals("KeyFactory")) { 120 if (algo.equals("EC")) { 121 return new ECKeyFactory(); 122 } 123 } else if (type.equals("AlgorithmParameters")) { 124 if (algo.equals("EC")) { 125 return new sun.security.util.ECParameters(); 126 } 127 } else if (type.equals("KeyPairGenerator")) { 128 if (algo.equals("EC")) { 129 return new ECKeyPairGenerator(); 130 } 131 } else if (type.equals("KeyAgreement")) { 132 if (algo.equals("ECDH")) { 133 return new ECDHKeyAgreement(); 134 } 135 } 136 } catch (Exception ex) { 137 throw new NoSuchAlgorithmException("Error constructing " + 138 type + " for " + algo + " using SunEC", ex); 139 } 140 throw new ProviderException("No impl for " + algo + 141 " " + type); 142 } 143 } 144 145 public SunEC() { 146 super("SunEC", PROVIDER_VER, 147 "Sun Elliptic Curve provider (EC, ECDSA, ECDH)"); 148 AccessController.doPrivileged(new PrivilegedAction<Void>() { 149 public Void run() { 150 putEntries(useFullImplementation); 151 return null; 152 } 153 }); 154 } 155 156 void putEntries(boolean useFullImplementation) { 157 HashMap<String, String> ATTRS = new HashMap<>(3); 158 ATTRS.put("ImplementedIn", "Software"); 159 String ecKeyClasses = "java.security.interfaces.ECPublicKey" + 160 "|java.security.interfaces.ECPrivateKey"; 161 ATTRS.put("SupportedKeyClasses", ecKeyClasses); 162 ATTRS.put("KeySize", "256"); 163 164 /* 165 * Key Factory engine 166 */ 167 putService(new ProviderService(this, "KeyFactory", 168 "EC", "sun.security.ec.ECKeyFactory", 169 new String[] { "EllipticCurve" }, ATTRS)); 170 171 /* 172 * Algorithm Parameter engine 173 */ 174 // "AlgorithmParameters.EC SupportedCurves" prop used by unit test 175 boolean firstCurve = true; 176 StringBuilder names = new StringBuilder(); 177 Pattern nameSplitPattern = Pattern.compile(CurveDB.SPLIT_PATTERN); 178 179 Collection<? extends NamedCurve> supportedCurves = 180 CurveDB.getSupportedCurves(); 181 for (NamedCurve namedCurve : supportedCurves) { 182 if (!firstCurve) { 183 names.append("|"); 184 } else { 185 firstCurve = false; 186 } 187 188 names.append("["); 189 190 String[] commonNames = nameSplitPattern.split(namedCurve.getName()); 191 for (String commonName : commonNames) { 192 names.append(commonName.trim()); 193 names.append(","); 194 } 195 196 names.append(namedCurve.getObjectId()); 197 names.append("]"); 198 } 199 200 HashMap<String, String> apAttrs = new HashMap<>(ATTRS); 201 apAttrs.put("SupportedCurves", names.toString()); 202 203 putService(new ProviderService(this, "AlgorithmParameters", 204 "EC", "sun.security.util.ECParameters", 205 new String[] { "EllipticCurve", "1.2.840.10045.2.1", "OID.1.2.840.10045.2.1" }, 206 apAttrs)); 207 208 /* 209 * Register the algorithms below only when the full ECC implementation 210 * is available 211 */ 212 if (!useFullImplementation) { 213 return; 214 } 215 216 /* 217 * Signature engines 218 */ 219 putService(new ProviderService(this, "Signature", 220 "NONEwithECDSA", "sun.security.ec.ECDSASignature$Raw", 221 null, ATTRS)); 222 putService(new ProviderService(this, "Signature", 223 "SHA1withECDSA", "sun.security.ec.ECDSASignature$SHA1", 224 new String[] { "1.2.840.10045.4.1", "OID.1.2.840.10045.4.1" }, 225 ATTRS)); 226 putService(new ProviderService(this, "Signature", 227 "SHA224withECDSA", "sun.security.ec.ECDSASignature$SHA224", 228 new String[] { "1.2.840.10045.4.3.1", "OID.1.2.840.10045.4.3.1"}, 229 ATTRS)); 230 putService(new ProviderService(this, "Signature", 231 "SHA256withECDSA", "sun.security.ec.ECDSASignature$SHA256", 232 new String[] { "1.2.840.10045.4.3.2", "OID.1.2.840.10045.4.3.2"}, 233 ATTRS)); 234 putService(new ProviderService(this, "Signature", 235 "SHA384withECDSA", "sun.security.ec.ECDSASignature$SHA384", 236 new String[] { "1.2.840.10045.4.3.3", "OID.1.2.840.10045.4.3.3" }, 237 ATTRS)); 238 putService(new ProviderService(this, "Signature", 239 "SHA512withECDSA", "sun.security.ec.ECDSASignature$SHA512", 240 new String[] { "1.2.840.10045.4.3.4", "OID.1.2.840.10045.4.3.4" }, 241 ATTRS)); 242 243 putService(new ProviderService(this, "Signature", 244 "NONEwithECDSAinP1363Format", 245 "sun.security.ec.ECDSASignature$RawinP1363Format")); 246 putService(new ProviderService(this, "Signature", 247 "SHA1withECDSAinP1363Format", 248 "sun.security.ec.ECDSASignature$SHA1inP1363Format")); 249 putService(new ProviderService(this, "Signature", 250 "SHA224withECDSAinP1363Format", 251 "sun.security.ec.ECDSASignature$SHA224inP1363Format")); 252 putService(new ProviderService(this, "Signature", 253 "SHA256withECDSAinP1363Format", 254 "sun.security.ec.ECDSASignature$SHA256inP1363Format")); 255 putService(new ProviderService(this, "Signature", 256 "SHA384withECDSAinP1363Format", 257 "sun.security.ec.ECDSASignature$SHA384inP1363Format")); 258 putService(new ProviderService(this, "Signature", 259 "SHA512withECDSAinP1363Format", 260 "sun.security.ec.ECDSASignature$SHA512inP1363Format")); 261 262 /* 263 * Key Pair Generator engine 264 */ 265 putService(new ProviderService(this, "KeyPairGenerator", 266 "EC", "sun.security.ec.ECKeyPairGenerator", 267 new String[] { "EllipticCurve" }, ATTRS)); 268 269 /* 270 * Key Agreement engine 271 */ 272 putService(new ProviderService(this, "KeyAgreement", 273 "ECDH", "sun.security.ec.ECDHKeyAgreement", null, ATTRS)); 274 } 275 }