1 /* 2 * Copyright (c) 2009, 2015, 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 35 /** 36 * Provider class for the Elliptic Curve provider. 37 * Supports EC keypair and parameter generation, ECDSA signing and 38 * ECDH key agreement. 39 * 40 * IMPLEMENTATION NOTE: 41 * The Java classes in this provider access a native ECC implementation 42 * via JNI to a C++ wrapper class which in turn calls C functions. 43 * The Java classes are packaged into the jdk.crypto.sunec module and the 44 * C++ and C functions are packaged into libsunec.so or sunec.dll in the 45 * JRE native libraries directory. If the native library is not present 46 * then this provider is registered with support for fewer ECC algorithms 47 * (KeyPairGenerator, Signature and KeyAgreement are omitted). 48 * 49 * @since 1.7 50 */ 51 public final class SunEC extends Provider { 52 53 private static final long serialVersionUID = -2279741672933606418L; 54 55 // flag indicating whether the full EC implementation is present 56 // (when native library is absent then fewer EC algorithms are available) 57 private static boolean useFullImplementation = true; 58 static { 59 try { 60 AccessController.doPrivileged(new PrivilegedAction<Void>() { 61 public Void run() { 62 System.loadLibrary("sunec"); // check for native library 63 return null; 64 } 65 }); 66 } catch (UnsatisfiedLinkError e) { 67 useFullImplementation = false; 68 } 69 } 70 71 private static class ProviderService extends Provider.Service { 72 73 ProviderService(Provider p, String type, String algo, String cn) { 74 super(p, type, algo, cn, null, null); 75 } 76 77 ProviderService(Provider p, String type, String algo, String cn, 78 String[] aliases, HashMap<String, String> attrs) { 79 super(p, type, algo, cn, 80 (aliases == null? null : Arrays.asList(aliases)), attrs); 81 } 82 83 @Override 84 public Object newInstance(Object ctrParamObj) 85 throws NoSuchAlgorithmException { 86 String type = getType(); 87 if (ctrParamObj != null) { 88 throw new InvalidParameterException 89 ("constructorParameter not used with " + type + " engines"); 90 } 91 92 String algo = getAlgorithm(); 93 try { 94 if (type.equals("Signature")) { 95 boolean inP1363 = algo.endsWith("inP1363Format"); 96 if (inP1363) { 97 algo = algo.substring(0, algo.length() - 13); 98 } 99 if (algo.equals("SHA1withECDSA")) { 100 return (inP1363? new ECDSASignature.SHA1inP1363Format() : 101 new ECDSASignature.SHA1()); 102 } else if (algo.equals("SHA224withECDSA")) { 103 return (inP1363? new ECDSASignature.SHA224inP1363Format() : 104 new ECDSASignature.SHA224()); 105 } else if (algo.equals("SHA256withECDSA")) { 106 return (inP1363? new ECDSASignature.SHA256inP1363Format() : 107 new ECDSASignature.SHA256()); 108 } else if (algo.equals("SHA384withECDSA")) { 109 return (inP1363? new ECDSASignature.SHA384inP1363Format() : 110 new ECDSASignature.SHA384()); 111 } else if (algo.equals("SHA512withECDSA")) { 112 return (inP1363? new ECDSASignature.SHA512inP1363Format() : 113 new ECDSASignature.SHA512()); 114 } else if (algo.equals("NONEwithECDSA")) { 115 return (inP1363? new ECDSASignature.RawinP1363Format() : 116 new ECDSASignature.Raw()); 117 } 118 } else if (type.equals("KeyFactory")) { 119 if (algo.equals("EC")) { 120 return new ECKeyFactory(); 121 } 122 } else if (type.equals("AlgorithmParameters")) { 123 if (algo.equals("EC")) { 124 return new sun.security.util.ECParameters(); 125 } 126 } else if (type.equals("KeyPairGenerator")) { 127 if (algo.equals("EC")) { 128 return new ECKeyPairGenerator(); 129 } 130 } else if (type.equals("KeyAgreement")) { 131 if (algo.equals("ECDH")) { 132 return new ECDHKeyAgreement(); 133 } 134 } 135 } catch (Exception ex) { 136 throw new NoSuchAlgorithmException("Error constructing " + 137 type + " for " + algo + " using SunEC", ex); 138 } 139 throw new ProviderException("No impl for " + algo + 140 " " + type); 141 } 142 } 143 144 public SunEC() { 145 super("SunEC", 1.9d, "Sun Elliptic Curve provider (EC, ECDSA, ECDH)"); 146 AccessController.doPrivileged(new PrivilegedAction<Void>() { 147 public Void run() { 148 putEntries(useFullImplementation); 149 return null; 150 } 151 }); 152 } 153 154 void putEntries(boolean useFullImplementation) { 155 HashMap<String, String> ATTRS = new HashMap<>(3); 156 ATTRS.put("ImplementedIn", "Software"); 157 String ecKeyClasses = "java.security.interfaces.ECPublicKey" + 158 "|java.security.interfaces.ECPrivateKey"; 159 ATTRS.put("SupportedKeyClasses", ecKeyClasses); 160 ATTRS.put("KeySize", "256"); 161 162 /* 163 * Key Factory engine 164 */ 165 putService(new ProviderService(this, "KeyFactory", 166 "EC", "sun.security.ec.ECKeyFactory", 167 new String[] { "EllipticCurve" }, ATTRS)); 168 169 /* 170 * Algorithm Parameter engine 171 */ 172 // "AlgorithmParameters.EC SupportedCurves" prop used by unit test 173 boolean firstCurve = true; 174 StringBuilder names = new StringBuilder(); 175 Pattern nameSplitPattern = Pattern.compile(CurveDB.SPLIT_PATTERN); 176 177 Collection<? extends NamedCurve> supportedCurves = 178 CurveDB.getSupportedCurves(); 179 for (NamedCurve namedCurve : supportedCurves) { 180 if (!firstCurve) { 181 names.append("|"); 182 } else { 183 firstCurve = false; 184 } 185 186 names.append("["); 187 188 String[] commonNames = nameSplitPattern.split(namedCurve.getName()); 189 for (String commonName : commonNames) { 190 names.append(commonName.trim()); 191 names.append(","); 192 } 193 194 names.append(namedCurve.getObjectId()); 195 names.append("]"); 196 } 197 198 HashMap<String, String> apAttrs = new HashMap<>(ATTRS); 199 apAttrs.put("SupportedCurves", names.toString()); 200 201 putService(new ProviderService(this, "AlgorithmParameters", 202 "EC", "sun.security.util.ECParameters", 203 new String[] { "EllipticCurve", "1.2.840.10045.2.1", "OID.1.2.840.10045.2.1" }, 204 apAttrs)); 205 206 /* 207 * Register the algorithms below only when the full ECC implementation 208 * is available 209 */ 210 if (!useFullImplementation) { 211 return; 212 } 213 214 /* 215 * Signature engines 216 */ 217 putService(new ProviderService(this, "Signature", 218 "NONEwithECDSA", "sun.security.ec.ECDSASignature$Raw", 219 null, ATTRS)); 220 putService(new ProviderService(this, "Signature", 221 "SHA1withECDSA", "sun.security.ec.ECDSASignature$SHA1", 222 new String[] { "1.2.840.10045.4.1", "OID.1.2.840.10045.4.1" }, 223 ATTRS)); 224 putService(new ProviderService(this, "Signature", 225 "SHA224withECDSA", "sun.security.ec.ECDSASignature$SHA224", 226 new String[] { "1.2.840.10045.4.3.1", "OID.1.2.840.10045.4.3.1"}, 227 ATTRS)); 228 putService(new ProviderService(this, "Signature", 229 "SHA256withECDSA", "sun.security.ec.ECDSASignature$SHA256", 230 new String[] { "1.2.840.10045.4.3.2", "OID.1.2.840.10045.4.3.2"}, 231 ATTRS)); 232 putService(new ProviderService(this, "Signature", 233 "SHA384withECDSA", "sun.security.ec.ECDSASignature$SHA384", 234 new String[] { "1.2.840.10045.4.3.3", "OID.1.2.840.10045.4.3.3" }, 235 ATTRS)); 236 putService(new ProviderService(this, "Signature", 237 "SHA512withECDSA", "sun.security.ec.ECDSASignature$SHA512", 238 new String[] { "1.2.840.10045.4.3.4", "OID.1.2.840.10045.4.3.4" }, 239 ATTRS)); 240 241 putService(new ProviderService(this, "Signature", 242 "NONEwithECDSAinP1363Format", 243 "sun.security.ec.ECDSASignature$RawinP1363Format")); 244 putService(new ProviderService(this, "Signature", 245 "SHA1withECDSAinP1363Format", 246 "sun.security.ec.ECDSASignature$SHA1inP1363Format")); 247 putService(new ProviderService(this, "Signature", 248 "SHA224withECDSAinP1363Format", 249 "sun.security.ec.ECDSASignature$SHA224inP1363Format")); 250 putService(new ProviderService(this, "Signature", 251 "SHA256withECDSAinP1363Format", 252 "sun.security.ec.ECDSASignature$SHA256inP1363Format")); 253 putService(new ProviderService(this, "Signature", 254 "SHA384withECDSAinP1363Format", 255 "sun.security.ec.ECDSASignature$SHA384inP1363Format")); 256 putService(new ProviderService(this, "Signature", 257 "SHA512withECDSAinP1363Format", 258 "sun.security.ec.ECDSASignature$SHA512inP1363Format")); 259 260 /* 261 * Key Pair Generator engine 262 */ 263 putService(new ProviderService(this, "KeyPairGenerator", 264 "EC", "sun.security.ec.ECKeyPairGenerator", 265 new String[] { "EllipticCurve" }, ATTRS)); 266 267 /* 268 * Key Agreement engine 269 */ 270 putService(new ProviderService(this, "KeyAgreement", 271 "ECDH", "sun.security.ec.ECDHKeyAgreement", null, ATTRS)); 272 } 273 }