[11u] RFR: 8208698: Improved ECC Implementation

Doerr, Martin martin.doerr at sap.com
Fri May 31 12:39:34 UTC 2019


Hi Christoph,

looks like quite some manual resolution just because of a small conflicting change in one file.
Backport looks good, but please backport it together with JDK-8217344.
After that, ECDHKeyAgreement.java should be identical to the jdk13 version.

Best regards,
Martin


> -----Original Message-----
> From: jdk-updates-dev <jdk-updates-dev-bounces at openjdk.java.net> On
> Behalf Of Langer, Christoph
> Sent: Dienstag, 28. Mai 2019 09:21
> To: jdk-updates-dev at openjdk.java.net
> Cc: security-dev <security-dev at openjdk.java.net>
> Subject: [11u] RFR: 8208698: Improved ECC Implementation
> 
> Hi,
> 
> please review this backport of JDK-8208698: Improved ECC Implementation.
> 
> Bug: https://bugs.openjdk.java.net/browse/JDK-8208698
> Original Change: http://hg.openjdk.java.net/jdk/jdk/rev/752e57845ad2
> Webrev: http://cr.openjdk.java.net/~clanger/webrevs/8208698.11u/
> 
> The patch did not apply cleanly because there were conflicts in
> src/jdk.crypto.ec/share/classes/sun/security/ec/ECDHKeyAgreement.java
> due to JDK-8205476 which is part of jdk/jdk but not of jdk11u-dev.
> Unfortunately, JDK-8205476 can not be downported as prerequisite because
> it brings a behavioral change and is associated with a CSR. So I resolved the
> rejects manually. I add the rejects below.
> 
> Thanks
> Christoph
> 
> 
> --- ECDHKeyAgreement.java
> +++ ECDHKeyAgreement.java
> @@ -99,42 +104,74 @@
>                  ("Key must be a PublicKey with algorithm EC");
>          }
> -        ECPublicKey ecKey = (ECPublicKey)key;
> -        ECParameterSpec params = ecKey.getParams();
> +        this.publicKey = (ECPublicKey) key;
> -        if (ecKey instanceof ECPublicKeyImpl) {
> -            publicValue = ((ECPublicKeyImpl)ecKey).getEncodedPublicValue();
> -        } else { // instanceof ECPublicKey
> -            publicValue =
> -                ECUtil.encodePoint(ecKey.getW(), params.getCurve());
> -        }
> +        ECParameterSpec params = publicKey.getParams();
>          int keyLenBits = params.getCurve().getField().getFieldSize();
>          secretLen = (keyLenBits + 7) >> 3;
>          return null;
>      }
> +    private static void validateCoordinate(BigInteger c, BigInteger mod) {
> +        if (c.compareTo(BigInteger.ZERO) < 0) {
> +            throw new ProviderException("invalid coordinate");
> +        }
> +
> +        if (c.compareTo(mod) >= 0) {
> +            throw new ProviderException("invalid coordinate");
> +        }
> +    }
> +
> +    /*
> +     * Check whether a public key is valid. Throw ProviderException
> +     * if it is not valid or could not be validated.
> +     */
> +    private static void validate(ECOperations ops, ECPublicKey key) {
> +
> +        // ensure that integers are in proper range
> +        BigInteger x = key.getW().getAffineX();
> +        BigInteger y = key.getW().getAffineY();
> +
> +        BigInteger p = ops.getField().getSize();
> +        validateCoordinate(x, p);
> +        validateCoordinate(y, p);
> +
> +        // ensure the point is on the curve
> +        EllipticCurve curve = key.getParams().getCurve();
> +        BigInteger rhs = x.modPow(BigInteger.valueOf(3), p).add(curve.getA()
> +            .multiply(x)).add(curve.getB()).mod(p);
> +        BigInteger lhs = y.modPow(BigInteger.valueOf(2), p).mod(p);
> +        if (!rhs.equals(lhs)) {
> +            throw new ProviderException("point is not on curve");
> +        }
> +
> +        // check the order of the point
> +        ImmutableIntegerModuloP xElem = ops.getField().getElement(x);
> +        ImmutableIntegerModuloP yElem = ops.getField().getElement(y);
> +        AffinePoint affP = new AffinePoint(xElem, yElem);
> +        byte[] order = key.getParams().getOrder().toByteArray();
> +        ArrayUtil.reverse(order);
> +        Point product = ops.multiply(affP, order);
> +        if (!ops.isNeutral(product)) {
> +            throw new ProviderException("point has incorrect order");
> +        }
> +
> +    }
> +
>      // see JCE spec
>      @Override
>      protected byte[] engineGenerateSecret() throws IllegalStateException {
> -        if ((privateKey == null) || (publicValue == null)) {
> +        if ((privateKey == null) || (publicKey == null)) {
>              throw new IllegalStateException("Not initialized correctly");
>          }
> -        byte[] s = privateKey.getS().toByteArray();
> -        byte[] encodedParams =                   // DER OID
> -            ECUtil.encodeECParameterSpec(null, privateKey.getParams());
> -
> -        try {
> -
> -            byte[] result = deriveKey(s, publicValue, encodedParams);
> -            publicValue = null;
> -            return result;
> -
> -        } catch (GeneralSecurityException e) {
> -            throw new ProviderException("Could not derive key", e);
> -        }
> -
> +        Optional<byte[]> resultOpt = deriveKeyImpl(privateKey, publicKey);
> +        byte[] result = resultOpt.orElseGet(
> +            () -> deriveKeyNative(privateKey, publicKey)
> +        );
> +        publicKey = null;
> +        return result;
>      }
>      // see JCE spec



More information about the security-dev mailing list