1 /* 2 * Copyright (c) 2009, 2020, 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.security.AccessController; 29 import java.security.InvalidParameterException; 30 import java.security.NoSuchAlgorithmException; 31 import java.security.PrivilegedAction; 32 import java.security.Provider; 33 import java.security.ProviderException; 34 import java.util.Collection; 35 import java.util.Collections; 36 import java.util.HashMap; 37 import java.util.List; 38 39 import sun.security.ec.ed.EdDSAAlgorithmParameters; 40 import sun.security.ec.ed.EdDSAKeyFactory; 41 import sun.security.ec.ed.EdDSAKeyPairGenerator; 42 import sun.security.ec.ed.EdDSASignature; 43 import sun.security.util.CurveDB; 44 import sun.security.util.NamedCurve; 45 46 import static sun.security.util.SecurityConstants.PROVIDER_VER; 47 import static sun.security.util.SecurityProviderConstants.*; 48 49 /** 50 * Provider class for the Elliptic Curve provider. 51 * Supports EC keypair and parameter generation, ECDSA signing and 52 * ECDH key agreement. 53 * 54 * IMPLEMENTATION NOTE: 55 * The Java classes in this provider access a native ECC implementation 56 * via JNI to a C++ wrapper class which in turn calls C functions. 57 * The Java classes are packaged into the jdk.crypto.sunec module and the 58 * C++ and C functions are packaged into libsunec.so or sunec.dll in the 59 * JRE native libraries directory. If the native library is not present 60 * then this provider is registered with support for fewer ECC algorithms 61 * (KeyPairGenerator, Signature and KeyAgreement are omitted). 62 * 63 * @since 1.7 64 */ 65 public final class SunEC extends Provider { 66 67 private static final long serialVersionUID = -2279741672933606418L; 68 69 // This flag is true if the native library is disabled or not loaded. 70 private static boolean disableNative = true; 71 72 static { 73 String s = sun.security.action.GetPropertyAction.privilegedGetProperty( 74 "jdk.sunec.disableNative"); 75 if (s != null && s.equalsIgnoreCase("false")) { 76 disableNative = false; 77 } 78 79 // If native is enabled, verify the library is available. 80 if (!disableNative) { 81 try { 82 AccessController.doPrivileged(new PrivilegedAction<Void>() { 83 public Void run() { 84 System.loadLibrary("sunec"); // check for native library 85 return null; 86 } 87 }); 88 } catch (UnsatisfiedLinkError e) { 89 disableNative = true; 90 } 91 } 92 } 93 94 // Check if native library support is disabled. 95 static boolean isNativeDisabled() { 96 return SunEC.disableNative; 97 } 98 99 private static class ProviderServiceA extends ProviderService { 100 ProviderServiceA(Provider p, String type, String algo, String cn, 101 HashMap<String, String> attrs) { 102 super(p, type, algo, cn, getAliases(algo), attrs); 103 } 104 } 105 106 private static class ProviderService extends Provider.Service { 107 108 ProviderService(Provider p, String type, String algo, String cn) { 109 super(p, type, algo, cn, null, null); 110 } 111 112 ProviderService(Provider p, String type, String algo, String cn, 113 List<String> aliases, HashMap<String, String> attrs) { 114 super(p, type, algo, cn, aliases, attrs); 115 } 116 117 @Override 118 public Object newInstance(Object ctrParamObj) 119 throws NoSuchAlgorithmException { 120 String type = getType(); 121 if (ctrParamObj != null) { 122 throw new InvalidParameterException 123 ("constructorParameter not used with " + type + " engines"); 124 } 125 126 String algo = getAlgorithm(); 127 try { 128 if (type.equals("Signature")) { 129 130 if (algo.equalsIgnoreCase("EdDSA")) { 131 return new EdDSASignature(); 132 } else if (algo.equalsIgnoreCase("Ed25519")) { 133 return new EdDSASignature.Ed25519(); 134 } else if (algo.equalsIgnoreCase("Ed448")) { 135 return new EdDSASignature.Ed448(); 136 } 137 138 boolean inP1363 = algo.endsWith("inP1363Format"); 139 if (inP1363) { 140 algo = algo.substring(0, algo.length() - 13); 141 } 142 if (algo.equals("SHA1withECDSA")) { 143 return (inP1363? new ECDSASignature.SHA1inP1363Format() : 144 new ECDSASignature.SHA1()); 145 } else if (algo.equals("SHA224withECDSA")) { 146 return (inP1363? new ECDSASignature.SHA224inP1363Format() : 147 new ECDSASignature.SHA224()); 148 } else if (algo.equals("SHA256withECDSA")) { 149 return (inP1363? new ECDSASignature.SHA256inP1363Format() : 150 new ECDSASignature.SHA256()); 151 } else if (algo.equals("SHA384withECDSA")) { 152 return (inP1363? new ECDSASignature.SHA384inP1363Format() : 153 new ECDSASignature.SHA384()); 154 } else if (algo.equals("SHA512withECDSA")) { 155 return (inP1363? new ECDSASignature.SHA512inP1363Format() : 156 new ECDSASignature.SHA512()); 157 } else if (algo.equals("NONEwithECDSA")) { 158 return (inP1363? new ECDSASignature.RawinP1363Format() : 159 new ECDSASignature.Raw()); 160 } 161 } else if (type.equals("KeyFactory")) { 162 if (algo.equals("EC")) { 163 return new ECKeyFactory(); 164 } else if (algo.equals("XDH")) { 165 return new XDHKeyFactory(); 166 } else if (algo.equals("X25519")) { 167 return new XDHKeyFactory.X25519(); 168 } else if (algo.equals("X448")) { 169 return new XDHKeyFactory.X448(); 170 } else if (algo.equalsIgnoreCase("EdDSA")) { 171 return new EdDSAKeyFactory(); 172 } else if (algo.equalsIgnoreCase("Ed25519")) { 173 return new EdDSAKeyFactory.Ed25519(); 174 } else if (algo.equalsIgnoreCase("Ed448")) { 175 return new EdDSAKeyFactory.Ed448(); 176 } 177 } else if (type.equals("AlgorithmParameters")) { 178 if (algo.equals("EC")) { 179 return new sun.security.util.ECParameters(); 180 } 181 } else if (type.equals("KeyPairGenerator")) { 182 if (algo.equals("EC")) { 183 return new ECKeyPairGenerator(); 184 } else if (algo.equals("XDH")) { 185 return new XDHKeyPairGenerator(); 186 } else if (algo.equals("X25519")) { 187 return new XDHKeyPairGenerator.X25519(); 188 } else if (algo.equals("X448")) { 189 return new XDHKeyPairGenerator.X448(); 190 } else if (algo.equalsIgnoreCase("EdDSA")) { 191 return new EdDSAKeyPairGenerator(); 192 } else if (algo.equalsIgnoreCase("Ed25519")) { 193 return new EdDSAKeyPairGenerator.Ed25519(); 194 } else if (algo.equalsIgnoreCase("Ed448")) { 195 return new EdDSAKeyPairGenerator.Ed448(); 196 } 197 } else if (type.equals("KeyAgreement")) { 198 if (algo.equals("ECDH")) { 199 return new ECDHKeyAgreement(); 200 } else if (algo.equals("XDH")) { 201 return new XDHKeyAgreement(); 202 } else if (algo.equals("X25519")) { 203 return new XDHKeyAgreement.X25519(); 204 } else if (algo.equals("X448")) { 205 return new XDHKeyAgreement.X448(); 206 } 207 } 208 } catch (Exception ex) { 209 throw new NoSuchAlgorithmException("Error constructing " + 210 type + " for " + algo + " using SunEC", ex); 211 } 212 throw new ProviderException("No impl for " + algo + 213 " " + type); 214 } 215 } 216 217 public SunEC() { 218 super("SunEC", PROVIDER_VER, "Sun Elliptic Curve provider"); 219 AccessController.doPrivileged(new PrivilegedAction<Void>() { 220 public Void run() { 221 putEntries(); 222 return null; 223 } 224 }); 225 } 226 227 void putEntries() { 228 HashMap<String, String> ATTRS = new HashMap<>(3); 229 ATTRS.put("ImplementedIn", "Software"); 230 String ecKeyClasses = "java.security.interfaces.ECPublicKey" + 231 "|java.security.interfaces.ECPrivateKey"; 232 ATTRS.put("SupportedKeyClasses", ecKeyClasses); 233 ATTRS.put("KeySize", "256"); 234 235 /* 236 * Key Factory engine 237 */ 238 putService(new ProviderService(this, "KeyFactory", 239 "EC", "sun.security.ec.ECKeyFactory", 240 List.of("EllipticCurve"), ATTRS)); 241 242 /* 243 * Algorithm Parameter engine 244 */ 245 // "AlgorithmParameters.EC SupportedCurves" prop used by unit test 246 boolean firstCurve = true; 247 StringBuilder names = new StringBuilder(); 248 249 Collection<? extends NamedCurve> supportedCurves; 250 if (SunEC.isNativeDisabled()) { 251 supportedCurves = Collections.unmodifiableList(List.of( 252 CurveDB.lookup("secp256r1"), 253 CurveDB.lookup("secp384r1"), 254 CurveDB.lookup("secp521r1"))); 255 } else { 256 supportedCurves = CurveDB.getSupportedCurves(); 257 } 258 259 for (NamedCurve namedCurve : supportedCurves) { 260 if (!firstCurve) { 261 names.append("|"); 262 } else { 263 firstCurve = false; 264 } 265 266 names.append("["); 267 String[] commonNames = namedCurve.getNameAndAliases(); 268 for (String commonName : commonNames) { 269 names.append(commonName); 270 names.append(","); 271 } 272 273 names.append(namedCurve.getObjectId()); 274 names.append("]"); 275 } 276 277 HashMap<String, String> apAttrs = new HashMap<>(ATTRS); 278 apAttrs.put("SupportedCurves", names.toString()); 279 280 putService(new ProviderServiceA(this, "AlgorithmParameters", 281 "EC", "sun.security.util.ECParameters", apAttrs)); 282 283 putXDHEntries(); 284 putEdDSAEntries(); 285 286 /* 287 * Signature engines 288 */ 289 putService(new ProviderService(this, "Signature", 290 "NONEwithECDSA", "sun.security.ec.ECDSASignature$Raw", 291 null, ATTRS)); 292 putService(new ProviderServiceA(this, "Signature", 293 "SHA1withECDSA", "sun.security.ec.ECDSASignature$SHA1", 294 ATTRS)); 295 putService(new ProviderServiceA(this, "Signature", 296 "SHA224withECDSA", "sun.security.ec.ECDSASignature$SHA224", 297 ATTRS)); 298 putService(new ProviderServiceA(this, "Signature", 299 "SHA256withECDSA", "sun.security.ec.ECDSASignature$SHA256", 300 ATTRS)); 301 putService(new ProviderServiceA(this, "Signature", 302 "SHA384withECDSA", "sun.security.ec.ECDSASignature$SHA384", 303 ATTRS)); 304 putService(new ProviderServiceA(this, "Signature", 305 "SHA512withECDSA", "sun.security.ec.ECDSASignature$SHA512", 306 ATTRS)); 307 308 putService(new ProviderService(this, "Signature", 309 "NONEwithECDSAinP1363Format", 310 "sun.security.ec.ECDSASignature$RawinP1363Format")); 311 putService(new ProviderService(this, "Signature", 312 "SHA1withECDSAinP1363Format", 313 "sun.security.ec.ECDSASignature$SHA1inP1363Format")); 314 putService(new ProviderService(this, "Signature", 315 "SHA224withECDSAinP1363Format", 316 "sun.security.ec.ECDSASignature$SHA224inP1363Format")); 317 putService(new ProviderService(this, "Signature", 318 "SHA256withECDSAinP1363Format", 319 "sun.security.ec.ECDSASignature$SHA256inP1363Format")); 320 putService(new ProviderService(this, "Signature", 321 "SHA384withECDSAinP1363Format", 322 "sun.security.ec.ECDSASignature$SHA384inP1363Format")); 323 putService(new ProviderService(this, "Signature", 324 "SHA512withECDSAinP1363Format", 325 "sun.security.ec.ECDSASignature$SHA512inP1363Format")); 326 327 /* 328 * Key Pair Generator engine 329 */ 330 putService(new ProviderService(this, "KeyPairGenerator", 331 "EC", "sun.security.ec.ECKeyPairGenerator", 332 List.of("EllipticCurve"), ATTRS)); 333 334 /* 335 * Key Agreement engine 336 */ 337 putService(new ProviderService(this, "KeyAgreement", 338 "ECDH", "sun.security.ec.ECDHKeyAgreement", null, ATTRS)); 339 } 340 341 private void putXDHEntries() { 342 343 HashMap<String, String> ATTRS = new HashMap<>(1); 344 ATTRS.put("ImplementedIn", "Software"); 345 346 /* XDH does not require native implementation */ 347 putService(new ProviderService(this, "KeyFactory", 348 "XDH", "sun.security.ec.XDHKeyFactory", null, ATTRS)); 349 putService(new ProviderServiceA(this, "KeyFactory", 350 "X25519", "sun.security.ec.XDHKeyFactory.X25519", 351 ATTRS)); 352 putService(new ProviderServiceA(this, "KeyFactory", 353 "X448", "sun.security.ec.XDHKeyFactory.X448", 354 ATTRS)); 355 356 putService(new ProviderService(this, "KeyPairGenerator", 357 "XDH", "sun.security.ec.XDHKeyPairGenerator", null, ATTRS)); 358 putService(new ProviderServiceA(this, "KeyPairGenerator", 359 "X25519", "sun.security.ec.XDHKeyPairGenerator.X25519", 360 ATTRS)); 361 putService(new ProviderServiceA(this, "KeyPairGenerator", 362 "X448", "sun.security.ec.XDHKeyPairGenerator.X448", 363 ATTRS)); 364 365 putService(new ProviderService(this, "KeyAgreement", 366 "XDH", "sun.security.ec.XDHKeyAgreement", null, ATTRS)); 367 putService(new ProviderServiceA(this, "KeyAgreement", 368 "X25519", "sun.security.ec.XDHKeyAgreement.X25519", 369 ATTRS)); 370 putService(new ProviderServiceA(this, "KeyAgreement", 371 "X448", "sun.security.ec.XDHKeyAgreement.X448", 372 ATTRS)); 373 } 374 375 private void putEdDSAEntries() { 376 377 HashMap<String, String> ATTRS = new HashMap<>(1); 378 ATTRS.put("ImplementedIn", "Software"); 379 380 /* EdDSA does not require native implementation */ 381 putService(new ProviderService(this, "KeyFactory", 382 "EdDSA", "sun.security.ec.ed.EdDSAKeyFactory", null, ATTRS)); 383 putService(new ProviderServiceA(this, "KeyFactory", 384 "Ed25519", "sun.security.ec.ed.EdDSAKeyFactory.Ed25519", ATTRS)); 385 putService(new ProviderServiceA(this, "KeyFactory", 386 "Ed448", "sun.security.ec.ed.EdDSAKeyFactory.Ed448", ATTRS)); 387 388 putService(new ProviderService(this, "KeyPairGenerator", 389 "EdDSA", "sun.security.ec.ed.EdDSAKeyPairGenerator", null, ATTRS)); 390 putService(new ProviderServiceA(this, "KeyPairGenerator", 391 "Ed25519", "sun.security.ec.ed.EdDSAKeyPairGenerator.Ed25519", 392 ATTRS)); 393 putService(new ProviderServiceA(this, "KeyPairGenerator", 394 "Ed448", "sun.security.ec.ed.EdDSAKeyPairGenerator.Ed448", 395 ATTRS)); 396 397 putService(new ProviderService(this, "Signature", 398 "EdDSA", "sun.security.ec.ed.EdDSASignature", null, ATTRS)); 399 putService(new ProviderServiceA(this, "Signature", 400 "Ed25519", "sun.security.ec.ed.EdDSASignature.Ed25519", ATTRS)); 401 putService(new ProviderServiceA(this, "Signature", 402 "Ed448", "sun.security.ec.ed.EdDSASignature.Ed448", ATTRS)); 403 404 } 405 }