aboutsummaryrefslogtreecommitdiff
path: root/src/share/classes/sun/security/ec/ECKeyPairGenerator.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/share/classes/sun/security/ec/ECKeyPairGenerator.java')
-rw-r--r--src/share/classes/sun/security/ec/ECKeyPairGenerator.java124
1 files changed, 92 insertions, 32 deletions
diff --git a/src/share/classes/sun/security/ec/ECKeyPairGenerator.java b/src/share/classes/sun/security/ec/ECKeyPairGenerator.java
index 91e1c7366b..f8eacdad33 100644
--- a/src/share/classes/sun/security/ec/ECKeyPairGenerator.java
+++ b/src/share/classes/sun/security/ec/ECKeyPairGenerator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -33,14 +33,15 @@ import java.security.spec.ECGenParameterSpec;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.InvalidParameterSpecException;
+import java.util.Optional;
import sun.security.ec.NamedCurve;
-import sun.security.ec.ECParameters;
-import sun.security.ec.ECPrivateKeyImpl;
-import sun.security.ec.ECPublicKeyImpl;
import sun.security.jca.JCAUtil;
import sun.security.util.ECUtil;
+import sun.security.util.math.*;
+import sun.security.ec.point.*;
import static sun.security.util.SecurityProviderConstants.DEF_EC_KEY_SIZE;
+import static sun.security.ec.ECOperations.IntermediateValueException;
/**
* EC keypair generator.
@@ -91,14 +92,14 @@ public final class ECKeyPairGenerator extends KeyPairGeneratorSpi {
ECParameterSpec ecSpec = null;
if (params instanceof ECParameterSpec) {
- ecSpec = ECUtil.getECParameterSpec(null,
- (ECParameterSpec)params);
+ ECParameterSpec ecParams = (ECParameterSpec) params;
+ ecSpec = ECUtil.getECParameterSpec(null, ecParams);
if (ecSpec == null) {
throw new InvalidAlgorithmParameterException(
"Unsupported curve: " + params);
}
} else if (params instanceof ECGenParameterSpec) {
- String name = ((ECGenParameterSpec)params).getName();
+ String name = ((ECGenParameterSpec) params).getName();
ecSpec = ECUtil.getECParameterSpec(null, name);
if (ecSpec == null) {
throw new InvalidAlgorithmParameterException(
@@ -113,8 +114,7 @@ public final class ECKeyPairGenerator extends KeyPairGeneratorSpi {
ensureCurveIsSupported(ecSpec);
this.params = ecSpec;
- this.keySize =
- ((ECParameterSpec)this.params).getCurve().getField().getFieldSize();
+ this.keySize = ecSpec.getCurve().getField().getFieldSize();
this.random = random;
}
@@ -142,39 +142,97 @@ public final class ECKeyPairGenerator extends KeyPairGeneratorSpi {
@Override
public KeyPair generateKeyPair() {
- byte[] encodedParams =
- ECUtil.encodeECParameterSpec(null, (ECParameterSpec)params);
-
- // seed is twice the key size (in bytes) plus 1
- byte[] seed = new byte[(((keySize + 7) >> 3) + 1) * 2];
if (random == null) {
random = JCAUtil.getSecureRandom();
}
- random.nextBytes(seed);
try {
+ Optional<KeyPair> kp = generateKeyPairImpl(random);
+ if (kp.isPresent()) {
+ return kp.get();
+ }
+ return generateKeyPairNative(random);
+ } catch (Exception ex) {
+ throw new ProviderException(ex);
+ }
+ }
- Object[] keyBytes = generateECKeyPair(keySize, encodedParams, seed);
-
- // The 'params' object supplied above is equivalent to the native
- // one so there is no need to fetch it.
- // keyBytes[0] is the encoding of the native private key
- BigInteger s = new BigInteger(1, (byte[])keyBytes[0]);
+ private byte[] generatePrivateScalar(SecureRandom random,
+ ECOperations ecOps, int seedSize) {
+ // Attempt to create the private scalar in a loop that uses new random
+ // input each time. The chance of failure is very small assuming the
+ // implementation derives the nonce using extra bits
+ int numAttempts = 128;
+ byte[] seedArr = new byte[seedSize];
+ for (int i = 0; i < numAttempts; i++) {
+ random.nextBytes(seedArr);
+ try {
+ return ecOps.seedToScalar(seedArr);
+ } catch (IntermediateValueException ex) {
+ // try again in the next iteration
+ }
+ }
- PrivateKey privateKey =
- new ECPrivateKeyImpl(s, (ECParameterSpec)params);
+ throw new ProviderException("Unable to produce private key after "
+ + numAttempts + " attempts");
+ }
- // keyBytes[1] is the encoding of the native public key
- ECPoint w = ECUtil.decodePoint((byte[])keyBytes[1],
- ((ECParameterSpec)params).getCurve());
- PublicKey publicKey =
- new ECPublicKeyImpl(w, (ECParameterSpec)params);
+ private Optional<KeyPair> generateKeyPairImpl(SecureRandom random)
+ throws InvalidKeyException {
- return new KeyPair(publicKey, privateKey);
+ ECParameterSpec ecParams = (ECParameterSpec) params;
- } catch (Exception e) {
- throw new ProviderException(e);
+ Optional<ECOperations> opsOpt = ECOperations.forParameters(ecParams);
+ if (!opsOpt.isPresent()) {
+ return Optional.empty();
}
+ ECOperations ops = opsOpt.get();
+ IntegerFieldModuloP field = ops.getField();
+ int numBits = ecParams.getOrder().bitLength();
+ int seedBits = numBits + 64;
+ int seedSize = (seedBits + 7) / 8;
+ byte[] privArr = generatePrivateScalar(random, ops, seedSize);
+
+ ECPoint genPoint = ecParams.getGenerator();
+ ImmutableIntegerModuloP x = field.getElement(genPoint.getAffineX());
+ ImmutableIntegerModuloP y = field.getElement(genPoint.getAffineY());
+ AffinePoint affGen = new AffinePoint(x, y);
+ Point pub = ops.multiply(affGen, privArr);
+ AffinePoint affPub = pub.asAffine();
+
+ PrivateKey privateKey = new ECPrivateKeyImpl(privArr, ecParams);
+
+ ECPoint w = new ECPoint(affPub.getX().asBigInteger(),
+ affPub.getY().asBigInteger());
+ PublicKey publicKey = new ECPublicKeyImpl(w, ecParams);
+
+ return Optional.of(new KeyPair(publicKey, privateKey));
+ }
+
+ private KeyPair generateKeyPairNative(SecureRandom random)
+ throws Exception {
+
+ ECParameterSpec ecParams = (ECParameterSpec) params;
+ byte[] encodedParams = ECUtil.encodeECParameterSpec(null, ecParams);
+
+ // seed is twice the key size (in bytes) plus 1
+ byte[] seed = new byte[(((keySize + 7) >> 3) + 1) * 2];
+ random.nextBytes(seed);
+ Object[] keyBytes = generateECKeyPair(keySize, encodedParams, seed);
+
+ // The 'params' object supplied above is equivalent to the native
+ // one so there is no need to fetch it.
+ // keyBytes[0] is the encoding of the native private key
+ BigInteger s = new BigInteger(1, (byte[]) keyBytes[0]);
+
+ PrivateKey privateKey = new ECPrivateKeyImpl(s, ecParams);
+
+ // keyBytes[1] is the encoding of the native public key
+ byte[] pubKey = (byte[]) keyBytes[1];
+ ECPoint w = ECUtil.decodePoint(pubKey, ecParams.getCurve());
+ PublicKey publicKey = new ECPublicKeyImpl(w, ecParams);
+
+ return new KeyPair(publicKey, privateKey);
}
private void checkKeySize(int keySize) throws InvalidParameterException {
@@ -191,7 +249,9 @@ public final class ECKeyPairGenerator extends KeyPairGeneratorSpi {
/**
* Checks whether the curve in the encoded parameters is supported by the
- * native implementation.
+ * native implementation. Some curve operations will be performed by the
+ * Java implementation, but not all of them. So native support is still
+ * required for all curves.
*
* @param encodedParams encoded parameters in the same form accepted
* by generateECKeyPair