diff --git a/closed/src/jdk.crypto.ec/share/classes/sun/security/ec/NativeECDHKeyAgreement.java b/closed/src/jdk.crypto.ec/share/classes/sun/security/ec/NativeECDHKeyAgreement.java index 0e7cd3388e8..fca12007b63 100644 --- a/closed/src/jdk.crypto.ec/share/classes/sun/security/ec/NativeECDHKeyAgreement.java +++ b/closed/src/jdk.crypto.ec/share/classes/sun/security/ec/NativeECDHKeyAgreement.java @@ -40,6 +40,7 @@ import java.security.ProviderException; import java.security.SecureRandom; import java.security.interfaces.ECKey; +import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPublicKey; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.ECParameterSpec; @@ -74,13 +75,19 @@ public final class NativeECDHKeyAgreement extends KeyAgreementSpi { private static final Map curveSupported = new ConcurrentHashMap<>(); /* private key, if initialized */ - private ECPrivateKeyImpl privateKey; + private ECPrivateKey privateKey; + + /* pointer to native private key, if initialized */ + private long nativePrivateKey; /* operations associated with private key, if initialized */ private ECOperations privateKeyOps; /* public key, non-null between doPhase() & generateSecret() only */ - private ECPublicKeyImpl publicKey; + private ECPublicKey publicKey; + + /* pointer to native public key, if initialized */ + private long nativePublicKey; /* the type of EC curve */ private String curve; @@ -109,16 +116,26 @@ private void init(Key key) } /* attempt to translate the key if it is not an ECKey */ ECKey ecKey = ECKeyFactory.toECKey(key); - if (ecKey instanceof ECPrivateKeyImpl keyImpl) { + if (ecKey instanceof ECPrivateKey ecPrivateKey) { Optional opsOpt = - ECOperations.forParameters(keyImpl.getParams()); + ECOperations.forParameters(ecPrivateKey.getParams()); if (opsOpt.isEmpty()) { - NamedCurve nc = CurveDB.lookup(keyImpl.getParams()); + NamedCurve nc = CurveDB.lookup(ecPrivateKey.getParams()); throw new InvalidAlgorithmParameterException( "Curve not supported: " + ((nc != null) ? nc.toString() : "unknown")); } - this.privateKey = keyImpl; + + this.privateKey = ecPrivateKey; + this.nativePrivateKey = NativeECUtil.getPrivateKeyNativePtr(ecPrivateKey); + if (this.nativePrivateKey == -1) { + if (nativeCryptTrace) { + System.err.println("Init: Could not create a pointer to a native private key." + + " Using Java implementation."); + } + this.initializeJavaImplementation(key); + return; + } this.privateKeyOps = opsOpt.get(); ECParameterSpec params = this.privateKey.getParams(); @@ -132,8 +149,8 @@ private void init(Key key) boolean absent = NativeECUtil.putCurveIfAbsent("ECKeyImpl", Boolean.FALSE); /* only print the first time a curve is used */ if (absent && nativeCryptTrace) { - System.err.println("Only ECPrivateKeyImpl and ECPublicKeyImpl" + - " are supported by the native implementation, " + + System.err.println("Only ECPrivateKey" + + " is supported by the native implementation, " + "using Java crypto implementation for key agreement."); } this.initializeJavaImplementation(key); @@ -184,24 +201,26 @@ protected Key engineDoPhase(Key key, boolean lastPhase) // Validate public key. validate(privateKeyOps, ecKey); - if (ecKey instanceof ECPublicKeyImpl keyImpl) { - this.publicKey = keyImpl; - - int keyLenBits = this.publicKey.getParams().getCurve().getField().getFieldSize(); - this.secretLen = (keyLenBits + 7) >> 3; - - return null; - } else { - boolean absent = NativeECUtil.putCurveIfAbsent("ECKeyImpl", Boolean.FALSE); - /* only print the first time a curve is used */ - if (absent && nativeCryptTrace) { - System.err.println("Only ECPrivateKeyImpl and ECPublicKeyImpl" + - " are supported by the native implementation, " + - "using Java crypto implementation for key agreement."); + this.publicKey = ecKey; + this.nativePublicKey = NativeECUtil.getPublicKeyNativePtr(ecKey); + if (this.nativePublicKey == -1) { + if (nativeCryptTrace) { + System.err.println("DoPhase: Could not create a pointer to a native public key." + + " Using Java implementation."); + } + try { + this.initializeJavaImplementation(this.privateKey); + this.javaImplementation.engineDoPhase(ecKey, true); + } catch (InvalidKeyException e) { + /* should not happen */ + throw new InternalError(e); } - this.initializeJavaImplementation(this.privateKey); - return this.javaImplementation.engineDoPhase(key, lastPhase); } + + int keyLenBits = this.publicKey.getParams().getCurve().getField().getFieldSize(); + this.secretLen = (keyLenBits + 7) >> 3; + + return null; } // Verify that x and y are integers in the interval [0, p - 1]. @@ -297,27 +316,7 @@ protected int engineGenerateSecret(byte[] sharedSecret, int offset) if ((this.privateKey == null) || (this.publicKey == null)) { throw new IllegalStateException("Not initialized correctly"); } - long nativePublicKey = this.publicKey.getNativePtr(); - long nativePrivateKey = this.privateKey.getNativePtr(); - if ((nativePublicKey == -1) || (nativePrivateKey == -1)) { - absent = NativeECUtil.putCurveIfAbsent(this.curve, Boolean.FALSE); - if (!absent) { - throw new ProviderException("Could not convert keys to native format"); - } - /* only print the first time a curve is used */ - if (nativeCryptTrace) { - System.err.println(this.curve + - " is not supported by OpenSSL, using Java crypto implementation for preparing agreement."); - } - try { - this.initializeJavaImplementation(this.privateKey); - this.javaImplementation.engineDoPhase(this.publicKey, true); - } catch (InvalidKeyException e) { - /* should not happen */ - throw new InternalError(e); - } - return this.javaImplementation.engineGenerateSecret(sharedSecret, offset); - } + absent = NativeECUtil.putCurveIfAbsent(this.curve, Boolean.TRUE); if (absent && nativeCryptTrace) { System.err.println(this.curve + diff --git a/closed/src/jdk.crypto.ec/share/classes/sun/security/ec/NativeECDSASignature.java b/closed/src/jdk.crypto.ec/share/classes/sun/security/ec/NativeECDSASignature.java index e028e50813b..0b999df3feb 100644 --- a/closed/src/jdk.crypto.ec/share/classes/sun/security/ec/NativeECDSASignature.java +++ b/closed/src/jdk.crypto.ec/share/classes/sun/security/ec/NativeECDSASignature.java @@ -102,14 +102,14 @@ abstract class NativeECDSASignature extends SignatureSpi { // private key, if initialized for signing private ECPrivateKey privateKey; - // private key impl, if initialized for signing - private ECPrivateKeyImpl privateKeyImpl; + // native private key pointer, if initialized for signing + private long nativePrivateKey; // public key, if initialized for verifying private ECPublicKey publicKey; - // public key impl, if initialized for verifying - private ECPublicKeyImpl publicKeyImpl; + // native public key pointer, if initialized for verifying + private long nativePublicKey; // signature parameters private ECParameterSpec sigParams; @@ -118,7 +118,7 @@ abstract class NativeECDSASignature extends SignatureSpi { private final boolean p1363Format; // the Java implementation, if needed - private ECDSASignature javaImplementation; + ECDSASignature javaImplementation; /** * Constructs a new NativeECDSASignature. @@ -182,51 +182,62 @@ static class RawECDSA extends NativeECDSASignature { // Stores the precomputed message digest value. @Override protected void engineUpdate(byte b) throws SignatureException { - if (offset >= precomputedDigest.length) { - offset = RAW_ECDSA_MAX + 1; - return; + if (this.javaImplementation != null) { + this.javaImplementation.engineUpdate(b); + } else { + if (offset >= precomputedDigest.length) { + offset = RAW_ECDSA_MAX + 1; + return; + } + precomputedDigest[offset++] = b; } - precomputedDigest[offset++] = b; } // Stores the precomputed message digest value. @Override protected void engineUpdate(byte[] b, int off, int len) throws SignatureException { - if (offset >= precomputedDigest.length) { - offset = RAW_ECDSA_MAX + 1; - return; + if (this.javaImplementation != null) { + this.javaImplementation.engineUpdate(b, off, len); + } else { + if (offset >= precomputedDigest.length) { + offset = RAW_ECDSA_MAX + 1; + return; + } + System.arraycopy(b, off, precomputedDigest, offset, len); + offset += len; } - System.arraycopy(b, off, precomputedDigest, offset, len); - offset += len; } // Stores the precomputed message digest value. @Override protected void engineUpdate(ByteBuffer byteBuffer) { - int len = byteBuffer.remaining(); - if (len <= 0) { - return; - } - if (len >= (precomputedDigest.length - offset)) { - offset = RAW_ECDSA_MAX + 1; - return; + if (this.javaImplementation != null) { + this.javaImplementation.engineUpdate(byteBuffer); + } else { + int len = byteBuffer.remaining(); + if (len <= 0) { + return; + } + if (len >= (precomputedDigest.length - offset)) { + offset = RAW_ECDSA_MAX + 1; + return; + } + byteBuffer.get(precomputedDigest, offset, len); + offset += len; } - byteBuffer.get(precomputedDigest, offset, len); - offset += len; } @Override - protected void resetDigest() { + void resetDigest() { offset = 0; } // Returns the precomputed message digest value. @Override - protected byte[] getDigestValue() throws SignatureException { + byte[] getDigestValue() throws SignatureException { if (offset > RAW_ECDSA_MAX) { throw new SignatureException("Message digest is too long"); - } byte[] result = new byte[offset]; System.arraycopy(precomputedDigest, 0, result, 0, offset); @@ -391,16 +402,19 @@ protected void engineInitVerify(PublicKey publicKey) this.privateKey = null; resetDigest(); - if (key instanceof ECPublicKeyImpl keyImpl) { - this.publicKeyImpl = keyImpl; - this.privateKeyImpl = null; - this.javaImplementation = null; - if (nativeCryptTrace) { - System.err.println("InitVerify: Using native crypto implementation for verifying signature."); - } - } else { + this.nativePublicKey = NativeECUtil.getPublicKeyNativePtr(key); + if (this.nativePublicKey == -1) { this.javaImplementation = getJavaInstance(); this.javaImplementation.engineInitVerify(publicKey); + if (nativeCryptTrace) { + System.err.println("InitVerify: Could not create a pointer to a native key." + + " Using Java implementation."); + } + return; + } + this.javaImplementation = null; + if (nativeCryptTrace) { + System.err.println("InitVerify: Keys were successfully converted to native OpenSSL format."); } } @@ -449,23 +463,26 @@ protected void engineInitSign(PrivateKey privateKey, SecureRandom random) this.random = random; resetDigest(); - if (key instanceof ECPrivateKeyImpl keyImpl) { - this.publicKeyImpl = null; - this.privateKeyImpl = keyImpl; - this.javaImplementation = null; - if (nativeCryptTrace) { - System.err.println("InitSign: Using native crypto implementation for verifying signature."); - } - } else { + this.nativePrivateKey = NativeECUtil.getPrivateKeyNativePtr(key); + if (this.nativePrivateKey == -1) { this.javaImplementation = getJavaInstance(); this.javaImplementation.engineInitSign(privateKey, random); + if (nativeCryptTrace) { + System.err.println("InitSign: Could not create a pointer to a native key." + + " Using Java implementation."); + } + return; + } + this.javaImplementation = null; + if (nativeCryptTrace) { + System.err.println("InitSign: Keys were successfully converted to native OpenSSL format."); } } /** * Resets the message digest if needed. */ - protected void resetDigest() { + void resetDigest() { if (needsReset) { if (messageDigest != null) { messageDigest.reset(); @@ -477,7 +494,7 @@ protected void resetDigest() { /** * Returns the message digest value. */ - protected byte[] getDigestValue() throws SignatureException { + byte[] getDigestValue() throws SignatureException { needsReset = false; return messageDigest.digest(); } @@ -537,7 +554,6 @@ protected byte[] engineSign() throws SignatureException { return this.javaImplementation.engineSign(); } - long nativePrivateKey = privateKeyImpl.getNativePtr(); byte[] digest = getDigestValue(); int digestLen = digest.length; ECParameterSpec params = privateKey.getParams(); @@ -547,13 +563,6 @@ protected byte[] engineSign() throws SignatureException { ECDSAOperations.forParameters(params) .orElseThrow(() -> new SignatureException("Curve not supported: " + params)); - if (nativePrivateKey == -1) { - throw new ProviderException("Keys could not be converted to native OpenSSL format"); - } - if (nativeCryptTrace) { - System.err.println("Sign: Keys were successfully converted to native OpenSSL format."); - } - if (nativeCrypto == null) { nativeCrypto = NativeCrypto.getNativeCrypto(); } @@ -604,14 +613,6 @@ protected boolean engineVerify(byte[] signature) throws SignatureException { } } - long nativePublicKey = publicKeyImpl.getNativePtr(); - if (nativePublicKey == -1) { - throw new ProviderException("Could not convert keys to native format"); - } - if (nativeCryptTrace) { - System.err.println("Verify: Keys were successfully converted to native OpenSSL format."); - } - if (nativeCrypto == null) { nativeCrypto = NativeCrypto.getNativeCrypto(); } diff --git a/closed/src/jdk.crypto.ec/share/classes/sun/security/ec/NativeECUtil.java b/closed/src/jdk.crypto.ec/share/classes/sun/security/ec/NativeECUtil.java index 0e4fb7575c6..4476dbb2c0f 100644 --- a/closed/src/jdk.crypto.ec/share/classes/sun/security/ec/NativeECUtil.java +++ b/closed/src/jdk.crypto.ec/share/classes/sun/security/ec/NativeECUtil.java @@ -25,7 +25,7 @@ /* * =========================================================================== - * (c) Copyright IBM Corp. 2022, 2023 All Rights Reserved + * (c) Copyright IBM Corp. 2022, 2024 All Rights Reserved * =========================================================================== */ @@ -35,6 +35,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.math.BigInteger; import java.security.ProviderException; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; import java.security.NoSuchAlgorithmException; import java.security.spec.InvalidParameterSpecException; import java.security.spec.ECPoint; @@ -158,4 +160,61 @@ static long encodeGroup(ECParameterSpec params) { n, n.length, h, h.length); } + + /** + * Returns the native pointer for the provided EC public key. + * + * @param key the EC public key + * @return the native EC public key context pointer or -1 on error + */ + static long getPublicKeyNativePtr(ECPublicKey key) { + synchronized (key) { + long nativePointer = encodeGroup(key.getParams()); + if (nativePointer != -1) { + try { + byte[] x = key.getW().getAffineX().toByteArray(); + byte[] y = key.getW().getAffineY().toByteArray(); + int fieldType = NativeCrypto.ECField_Fp; + if (key.getParams().getCurve().getField() instanceof ECFieldF2m) { + fieldType = NativeCrypto.ECField_F2m; + } + if (nativeCrypto.ECCreatePublicKey(nativePointer, x, x.length, y, y.length, fieldType) == -1) { + nativeCrypto.ECDestroyKey(nativePointer); + nativePointer = -1; + } + } finally { + if (nativePointer != -1) { + nativeCrypto.createECKeyCleaner(key, nativePointer); + } + } + } + return nativePointer; + } + } + + /** + * Returns the native pointer for the provided EC private key. + * + * @param key the EC private key + * @return the native EC private key context pointer or -1 on error + */ + static long getPrivateKeyNativePtr(ECPrivateKey key) { + synchronized (key) { + long nativePointer = encodeGroup(key.getParams()); + if (nativePointer != -1) { + try { + byte[] value = key.getS().toByteArray(); + if (nativeCrypto.ECCreatePrivateKey(nativePointer, value, value.length) == -1) { + nativeCrypto.ECDestroyKey(nativePointer); + nativePointer = -1; + } + } finally { + if (nativePointer != -1) { + nativeCrypto.createECKeyCleaner(key, nativePointer); + } + } + } + return nativePointer; + } + } } diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECPrivateKeyImpl.java b/src/jdk.crypto.ec/share/classes/sun/security/ec/ECPrivateKeyImpl.java index 411abfe91b8..88cde0c55df 100644 --- a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECPrivateKeyImpl.java +++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/ECPrivateKeyImpl.java @@ -23,12 +23,6 @@ * questions. */ -/* - * =========================================================================== - * (c) Copyright IBM Corp. 2022, 2023 All Rights Reserved - * =========================================================================== - */ - package sun.security.ec; import java.io.IOException; @@ -41,8 +35,6 @@ import java.security.spec.*; import java.util.Arrays; -import jdk.crypto.jniprovider.NativeCrypto; - import sun.security.util.*; import sun.security.x509.AlgorithmId; import sun.security.pkcs.PKCS8Key; @@ -74,12 +66,10 @@ public final class ECPrivateKeyImpl extends PKCS8Key implements ECPrivateKey { @java.io.Serial private static final long serialVersionUID = 88695385615075129L; - private static NativeCrypto nativeCrypto; private BigInteger s; // private value private byte[] arrayS; // private value as a little-endian array private ECParameterSpec params; - private long nativeECKey; /** * Construct a key from its encoding. Called by the ECKeyFactory. @@ -234,36 +224,4 @@ private void readObject(ObjectInputStream stream) throw new InvalidObjectException( "ECPrivateKeyImpl keys are not directly deserializable"); } - - /** - * Returns the native EC public key context pointer. - * @return the native EC public key context pointer or -1 on error - */ - long getNativePtr() { - if (this.nativeECKey == 0x0) { - synchronized (this) { - if (this.nativeECKey == 0x0) { - if (nativeCrypto == null) { - nativeCrypto = NativeCrypto.getNativeCrypto(); - } - long nativePointer = NativeECUtil.encodeGroup(this.params); - try { - if (nativePointer != -1) { - byte[] value = this.getS().toByteArray(); - if (nativeCrypto.ECCreatePrivateKey(nativePointer, value, value.length) == -1) { - nativeCrypto.ECDestroyKey(nativePointer); - nativePointer = -1; - } - } - } finally { - if (nativePointer != -1) { - nativeCrypto.createECKeyCleaner(this, nativePointer); - } - } - this.nativeECKey = nativePointer; - } - } - } - return this.nativeECKey; - } } diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECPublicKeyImpl.java b/src/jdk.crypto.ec/share/classes/sun/security/ec/ECPublicKeyImpl.java index b2d11514328..c88fa450734 100644 --- a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECPublicKeyImpl.java +++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/ECPublicKeyImpl.java @@ -23,16 +23,9 @@ * questions. */ -/* - * =========================================================================== - * (c) Copyright IBM Corp. 2022, 2023 All Rights Reserved - * =========================================================================== - */ - package sun.security.ec; import java.io.IOException; -import java.math.BigInteger; import java.io.InvalidObjectException; import java.io.ObjectInputStream; @@ -40,8 +33,6 @@ import java.security.interfaces.*; import java.security.spec.*; -import jdk.crypto.jniprovider.NativeCrypto; - import sun.security.util.ECParameters; import sun.security.util.ECUtil; @@ -57,11 +48,9 @@ public final class ECPublicKeyImpl extends X509Key implements ECPublicKey { @java.io.Serial private static final long serialVersionUID = -2462037275160462289L; - private static NativeCrypto nativeCrypto; private ECPoint w; private ECParameterSpec params; - private long nativeECKey; /** * Construct a key from its components. Used by the @@ -159,41 +148,4 @@ private void readObject(ObjectInputStream stream) throw new InvalidObjectException( "ECPublicKeyImpl keys are not directly deserializable"); } - - /** - * Returns the native EC public key context pointer. - * @return the native EC public key context pointer or -1 on error - */ - long getNativePtr() { - if (this.nativeECKey == 0x0) { - synchronized (this) { - if (this.nativeECKey == 0x0) { - if (nativeCrypto == null) { - nativeCrypto = NativeCrypto.getNativeCrypto(); - } - long nativePointer = NativeECUtil.encodeGroup(this.params); - try { - if (nativePointer != -1) { - byte[] x = this.w.getAffineX().toByteArray(); - byte[] y = this.w.getAffineY().toByteArray(); - int fieldType = NativeCrypto.ECField_Fp; - if (this.params.getCurve().getField() instanceof ECFieldF2m) { - fieldType = NativeCrypto.ECField_F2m; - } - if (nativeCrypto.ECCreatePublicKey(nativePointer, x, x.length, y, y.length, fieldType) == -1) { - nativeCrypto.ECDestroyKey(nativePointer); - nativePointer = -1; - } - } - } finally { - if (nativePointer != -1) { - nativeCrypto.createECKeyCleaner(this, nativePointer); - } - } - this.nativeECKey = nativePointer; - } - } - } - return this.nativeECKey; - } -} +} \ No newline at end of file