1 package org.bouncycastle.jce.provider.asymmetric.ec; 2 3 import java.math.BigInteger; 4 import java.security.InvalidAlgorithmParameterException; 5 import java.security.InvalidParameterException; 6 import java.security.KeyPair; 7 import java.security.SecureRandom; 8 import java.security.spec.AlgorithmParameterSpec; 9 import java.security.spec.ECGenParameterSpec; 10 import java.util.Hashtable; 11 12 import org.bouncycastle.asn1.DERObjectIdentifier; 13 // BEGIN android-removed 14 // import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves; 15 // END android-removed 16 import org.bouncycastle.asn1.nist.NISTNamedCurves; 17 import org.bouncycastle.asn1.sec.SECNamedCurves; 18 // BEGIN android-removed 19 // import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves; 20 // END android-removed 21 import org.bouncycastle.asn1.x9.X962NamedCurves; 22 import org.bouncycastle.asn1.x9.X9ECParameters; 23 import org.bouncycastle.crypto.AsymmetricCipherKeyPair; 24 import org.bouncycastle.crypto.generators.ECKeyPairGenerator; 25 import org.bouncycastle.crypto.params.ECDomainParameters; 26 import org.bouncycastle.crypto.params.ECKeyGenerationParameters; 27 import org.bouncycastle.crypto.params.ECPrivateKeyParameters; 28 import org.bouncycastle.crypto.params.ECPublicKeyParameters; 29 import org.bouncycastle.jce.provider.JCEECPrivateKey; 30 import org.bouncycastle.jce.provider.JCEECPublicKey; 31 import org.bouncycastle.jce.provider.JDKKeyPairGenerator; 32 import org.bouncycastle.jce.provider.ProviderUtil; 33 import org.bouncycastle.jce.spec.ECNamedCurveSpec; 34 import org.bouncycastle.jce.spec.ECParameterSpec; 35 import org.bouncycastle.math.ec.ECCurve; 36 import org.bouncycastle.math.ec.ECPoint; 37 38 public abstract class KeyPairGenerator 39 extends JDKKeyPairGenerator 40 { 41 public KeyPairGenerator(String algorithmName) 42 { 43 super(algorithmName); 44 } 45 46 public static class EC 47 extends KeyPairGenerator 48 { 49 ECKeyGenerationParameters param; 50 ECKeyPairGenerator engine = new ECKeyPairGenerator(); 51 Object ecParams = null; 52 int strength = 239; 53 int certainty = 50; 54 SecureRandom random = new SecureRandom(); 55 boolean initialised = false; 56 String algorithm; 57 58 static private Hashtable ecParameters; 59 60 static { 61 ecParameters = new Hashtable(); 62 63 // BEGIN android-changed 64 ecParameters.put(Integer.valueOf(192), new ECGenParameterSpec("prime192v1")); // a.k.a P-192 65 ecParameters.put(Integer.valueOf(239), new ECGenParameterSpec("prime239v1")); 66 ecParameters.put(Integer.valueOf(256), new ECGenParameterSpec("prime256v1")); // a.k.a P-256 67 68 ecParameters.put(Integer.valueOf(224), new ECGenParameterSpec("P-224")); 69 ecParameters.put(Integer.valueOf(384), new ECGenParameterSpec("P-384")); 70 ecParameters.put(Integer.valueOf(521), new ECGenParameterSpec("P-521")); 71 // END android-changed 72 } 73 74 public EC() 75 { 76 super("EC"); 77 this.algorithm = "EC"; 78 } 79 80 public EC( 81 String algorithm) 82 { 83 super(algorithm); 84 this.algorithm = algorithm; 85 } 86 87 public void initialize( 88 int strength, 89 SecureRandom random) 90 { 91 this.strength = strength; 92 // BEGIN android-added 93 if (random != null) { 94 // END android-added 95 this.random = random; 96 // BEGIN android-added 97 } 98 // END android-added 99 // BEGIN android-changed 100 this.ecParams = ecParameters.get(Integer.valueOf(strength)); 101 // END android-changed 102 103 if (ecParams != null) 104 { 105 try 106 { 107 initialize((ECGenParameterSpec)ecParams, random); 108 } 109 catch (InvalidAlgorithmParameterException e) 110 { 111 throw new InvalidParameterException("key size not configurable."); 112 } 113 } 114 else 115 { 116 throw new InvalidParameterException("unknown key size."); 117 } 118 } 119 120 public void initialize( 121 AlgorithmParameterSpec params, 122 SecureRandom random) 123 throws InvalidAlgorithmParameterException 124 { 125 // BEGIN android-added 126 if (random == null) { 127 random = this.random; 128 } 129 // END android-added 130 if (params instanceof ECParameterSpec) 131 { 132 ECParameterSpec p = (ECParameterSpec)params; 133 this.ecParams = params; 134 135 param = new ECKeyGenerationParameters(new ECDomainParameters(p.getCurve(), p.getG(), p.getN()), random); 136 137 engine.init(param); 138 initialised = true; 139 } 140 else if (params instanceof java.security.spec.ECParameterSpec) 141 { 142 java.security.spec.ECParameterSpec p = (java.security.spec.ECParameterSpec)params; 143 this.ecParams = params; 144 145 ECCurve curve = EC5Util.convertCurve(p.getCurve()); 146 ECPoint g = EC5Util.convertPoint(curve, p.getGenerator(), false); 147 148 param = new ECKeyGenerationParameters(new ECDomainParameters(curve, g, p.getOrder(), BigInteger.valueOf(p.getCofactor())), random); 149 150 engine.init(param); 151 initialised = true; 152 } 153 else if (params instanceof ECGenParameterSpec) 154 { 155 final String curveName = ((ECGenParameterSpec)params).getName(); 156 157 // BEGIN android-removed 158 // if (this.algorithm.equals("ECGOST3410")) 159 // { 160 // ECDomainParameters ecP = ECGOST3410NamedCurves.getByName(curveName); 161 // if (ecP == null) 162 // { 163 // throw new InvalidAlgorithmParameterException("unknown curve name: " + curveName); 164 // } 165 // 166 // this.ecParams = new ECNamedCurveSpec( 167 // curveName, 168 // ecP.getCurve(), 169 // ecP.getG(), 170 // ecP.getN(), 171 // ecP.getH(), 172 // ecP.getSeed()); 173 // } 174 // else 175 // END android-removed 176 { 177 X9ECParameters ecP = X962NamedCurves.getByName(curveName); 178 if (ecP == null) 179 { 180 ecP = SECNamedCurves.getByName(curveName); 181 if (ecP == null) 182 { 183 ecP = NISTNamedCurves.getByName(curveName); 184 } 185 // BEGIN android-removed 186 // if (ecP == null) 187 // { 188 // ecP = TeleTrusTNamedCurves.getByName(curveName); 189 // } 190 // END android-removed 191 if (ecP == null) 192 { 193 // See if it's actually an OID string (SunJSSE ServerHandshaker setupEphemeralECDHKeys bug) 194 try 195 { 196 DERObjectIdentifier oid = new DERObjectIdentifier(curveName); 197 ecP = X962NamedCurves.getByOID(oid); 198 if (ecP == null) 199 { 200 ecP = SECNamedCurves.getByOID(oid); 201 } 202 if (ecP == null) 203 { 204 ecP = NISTNamedCurves.getByOID(oid); 205 } 206 // BEGIN android-removed 207 // if (ecP == null) 208 // { 209 // ecP = TeleTrusTNamedCurves.getByOID(oid); 210 // } 211 // END android-removed 212 if (ecP == null) 213 { 214 throw new InvalidAlgorithmParameterException("unknown curve OID: " + curveName); 215 } 216 } 217 catch (IllegalArgumentException ex) 218 { 219 throw new InvalidAlgorithmParameterException("unknown curve name: " + curveName); 220 } 221 } 222 } 223 224 this.ecParams = new ECNamedCurveSpec( 225 curveName, 226 ecP.getCurve(), 227 ecP.getG(), 228 ecP.getN(), 229 ecP.getH(), 230 null); // ecP.getSeed()); Work-around JDK bug -- it won't look up named curves properly if seed is present 231 } 232 233 java.security.spec.ECParameterSpec p = (java.security.spec.ECParameterSpec)ecParams; 234 235 ECCurve curve = EC5Util.convertCurve(p.getCurve()); 236 ECPoint g = EC5Util.convertPoint(curve, p.getGenerator(), false); 237 238 param = new ECKeyGenerationParameters(new ECDomainParameters(curve, g, p.getOrder(), BigInteger.valueOf(p.getCofactor())), random); 239 240 engine.init(param); 241 initialised = true; 242 } 243 else if (params == null && ProviderUtil.getEcImplicitlyCa() != null) 244 { 245 ECParameterSpec p = ProviderUtil.getEcImplicitlyCa(); 246 this.ecParams = params; 247 248 param = new ECKeyGenerationParameters(new ECDomainParameters(p.getCurve(), p.getG(), p.getN()), random); 249 250 engine.init(param); 251 initialised = true; 252 } 253 else if (params == null && ProviderUtil.getEcImplicitlyCa() == null) 254 { 255 throw new InvalidAlgorithmParameterException("null parameter passed but no implicitCA set"); 256 } 257 else 258 { 259 throw new InvalidAlgorithmParameterException("parameter object not a ECParameterSpec"); 260 } 261 } 262 263 public KeyPair generateKeyPair() 264 { 265 if (!initialised) 266 { 267 // BEGIN android-removed 268 // throw new IllegalStateException("EC Key Pair Generator not initialised"); 269 // END android-removed 270 // BEGIN android-added 271 /* 272 * KeyPairGenerator documentation says that a default initialization must be provided 273 */ 274 initialize(192, random); 275 // END android-added 276 } 277 278 AsymmetricCipherKeyPair pair = engine.generateKeyPair(); 279 ECPublicKeyParameters pub = (ECPublicKeyParameters)pair.getPublic(); 280 ECPrivateKeyParameters priv = (ECPrivateKeyParameters)pair.getPrivate(); 281 282 if (ecParams instanceof ECParameterSpec) 283 { 284 ECParameterSpec p = (ECParameterSpec)ecParams; 285 286 JCEECPublicKey pubKey = new JCEECPublicKey(algorithm, pub, p); 287 return new KeyPair(pubKey, 288 new JCEECPrivateKey(algorithm, priv, pubKey, p)); 289 } 290 else if (ecParams == null) 291 { 292 return new KeyPair(new JCEECPublicKey(algorithm, pub), 293 new JCEECPrivateKey(algorithm, priv)); 294 } 295 else 296 { 297 java.security.spec.ECParameterSpec p = (java.security.spec.ECParameterSpec)ecParams; 298 299 JCEECPublicKey pubKey = new JCEECPublicKey(algorithm, pub, p); 300 301 return new KeyPair(pubKey, new JCEECPrivateKey(algorithm, priv, pubKey, p)); 302 } 303 } 304 } 305 306 public static class ECDSA 307 extends EC 308 { 309 public ECDSA() 310 { 311 super("ECDSA"); 312 } 313 } 314 315 // BEGIN android-removed 316 // public static class ECGOST3410 317 // extends EC 318 // { 319 // public ECGOST3410() 320 // { 321 // super("ECGOST3410"); 322 // } 323 // } 324 // END android-removed 325 326 public static class ECDH 327 extends EC 328 { 329 public ECDH() 330 { 331 super("ECDH"); 332 } 333 } 334 335 public static class ECDHC 336 extends EC 337 { 338 public ECDHC() 339 { 340 super("ECDHC"); 341 } 342 } 343 344 public static class ECMQV 345 extends EC 346 { 347 public ECMQV() 348 { 349 super("ECMQV"); 350 } 351 } 352 } 353