diff --git a/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java b/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java index 6ea08796d8b..d09e0adc4cb 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java @@ -22,6 +22,11 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ +/* + * =========================================================================== + * (c) Copyright IBM Corp. 2023, 2023 All Rights Reserved + * =========================================================================== + */ package com.sun.crypto.provider; @@ -113,7 +118,7 @@ private static byte[] getPasswordBytes(char[] passwd) { } else if (keyLength < 0) { throw new InvalidKeySpecException("Key length is negative"); } - this.prf = Mac.getInstance(prfAlgo, SunJCE.getInstance()); + this.prf = Mac.getInstance(prfAlgo); this.key = deriveKey(prf, passwdBytes, salt, iterCount, keyLength); } catch (NoSuchAlgorithmException nsae) { // not gonna happen; re-throw just in case diff --git a/src/java.base/share/conf/security/java.security b/src/java.base/share/conf/security/java.security index 6d8eccbd812..aec184b2772 100644 --- a/src/java.base/share/conf/security/java.security +++ b/src/java.base/share/conf/security/java.security @@ -137,7 +137,8 @@ RestrictedSecurity1.jce.provider.2 = SUN [{CertificateFactory, X.509, Implemente {CertStore, com.sun.security.IndexedCollection, ImplementedIn=Software}, \ {Policy, JavaPolicy, *}, {Configuration, JavaLoginConfig, *}, \ {CertPathBuilder, PKIX, ValidationAlgorithm=RFC5280:ImplementedIn=Software}, \ - {CertPathValidator, PKIX, ValidationAlgorithm=RFC5280:ImplementedIn=Software}] + {CertPathValidator, PKIX, ValidationAlgorithm=RFC5280:ImplementedIn=Software}, \ + {KeyStore, PKCS12, *}] RestrictedSecurity1.jce.provider.3 = SunEC [{KeyFactory, EC, ImplementedIn=Software: \ SupportedKeyClasses=java.security.interfaces.ECPublicKey|java.security.interfaces.ECPrivateKey: \ KeySize=256}, {AlgorithmParameters, EC, *}] diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java index 91dd20e1600..950f0ed2474 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java @@ -54,6 +54,7 @@ import static sun.security.pkcs11.TemplateManager.O_GENERATE; import static sun.security.pkcs11.wrapper.PKCS11Constants.*; +import sun.security.util.Debug; import sun.security.util.DerValue; import sun.security.util.Length; import sun.security.util.ECUtil; @@ -77,6 +78,8 @@ abstract class P11Key implements Key, Length { private static final long serialVersionUID = -2575874101938349339L; + private static final Debug debug = Debug.getInstance("p11key"); + private final static String PUBLIC = "public"; private final static String PRIVATE = "private"; private final static String SECRET = "secret"; @@ -384,21 +387,40 @@ static PrivateKey privateKey(Session session, long keyID, String algorithm, new CK_ATTRIBUTE(CKA_SENSITIVE), new CK_ATTRIBUTE(CKA_EXTRACTABLE), }); - if ((SunPKCS11.mysunpkcs11 != null) && "RSA".equals(algorithm)) { - if (attributes[0].getBoolean() || attributes[1].getBoolean() || (attributes[2].getBoolean() == false)) { - try { - byte[] key = SunPKCS11.mysunpkcs11.exportKey(session.id(), attributes, keyID); - RSAPrivateKey rsaPrivKey = RSAPrivateCrtKeyImpl.newKey(key); - if (rsaPrivKey instanceof RSAPrivateCrtKeyImpl) { - return new P11RSAPrivateKeyFIPS(session, keyID, algorithm, keyLength, attributes, (RSAPrivateCrtKeyImpl)rsaPrivKey); - } else { - return new P11RSAPrivateNonCRTKeyFIPS(session, keyID, algorithm, keyLength, attributes, rsaPrivKey); - } - } catch (PKCS11Exception | InvalidKeyException e) { - // Attempt failed, create a P11PrivateKey object. + + boolean keySensitive = (attributes[0].getBoolean() || + attributes[1].getBoolean() || !attributes[2].getBoolean()); + + if (keySensitive && (SunPKCS11.mysunpkcs11 != null) && "RSA".equals(algorithm)) { + try { + byte[] key = SunPKCS11.mysunpkcs11.exportKey(session.id(), attributes, keyID); + RSAPrivateKey rsaPrivKey = RSAPrivateCrtKeyImpl.newKey(key); + if (rsaPrivKey instanceof RSAPrivateCrtKeyImpl) { + return new P11RSAPrivateKeyFIPS(session, keyID, algorithm, keyLength, attributes, (RSAPrivateCrtKeyImpl)rsaPrivKey); + } else { + return new P11RSAPrivateNonCRTKeyFIPS(session, keyID, algorithm, keyLength, attributes, rsaPrivKey); + } + } catch (PKCS11Exception | InvalidKeyException e) { + // Attempt failed, create a P11PrivateKey object. + if (debug != null) { + debug.println("Attempt failed, creating a P11PrivateKey object for RSA"); } } } + + if (keySensitive && (SunPKCS11.mysunpkcs11 != null) && "EC".equals(algorithm)) { + try { + byte[] key = SunPKCS11.mysunpkcs11.exportKey(session.id(), attributes, keyID); + ECPrivateKey ecPrivKey = ECUtil.decodePKCS8ECPrivateKey(key); + return new P11ECPrivateKeyFIPS(session, keyID, algorithm, keyLength, attributes, ecPrivKey); + } catch (PKCS11Exception | InvalidKeySpecException e) { + // Attempt failed, create a P11PrivateKey object. + if (debug != null) { + debug.println("Attempt failed, creating a P11PrivateKey object for EC"); + } + } + } + if (attributes[1].getBoolean() || (attributes[2].getBoolean() == false)) { return new P11PrivateKey (session, keyID, algorithm, keyLength, attributes); @@ -1126,6 +1148,39 @@ public boolean equals(Object obj) { } } + // EC private key when in FIPS mode + private static final class P11ECPrivateKeyFIPS extends P11Key + implements ECPrivateKey { + private static final long serialVersionUID = -7786054399510515515L; + private final ECPrivateKey key; + + P11ECPrivateKeyFIPS(Session session, long keyID, String algorithm, + int keyLength, CK_ATTRIBUTE[] attributes, ECPrivateKey key) { + super(PRIVATE, session, keyID, algorithm, keyLength, attributes); + this.key = key; + } + + @Override + public String getFormat() { + return "PKCS#8"; + } + + @Override + synchronized byte[] getEncodedInternal() { + return key.getEncoded(); + } + + @Override + public BigInteger getS() { + return key.getS(); + } + + @Override + public ECParameterSpec getParams() { + return key.getParams(); + } + } + private static final class P11ECPrivateKey extends P11Key implements ECPrivateKey { private static final long serialVersionUID = -7786054399510515515L; diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java index 04873345e1f..2176ee12fe3 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java @@ -33,9 +33,11 @@ import java.io.*; import java.util.*; +import java.math.BigInteger; import java.security.*; import java.security.interfaces.*; +import java.security.spec.InvalidKeySpecException; import java.util.function.Consumer; import javax.crypto.BadPaddingException; @@ -56,13 +58,16 @@ import jdk.internal.misc.InnocuousThread; import openj9.internal.security.RestrictedSecurity; +import sun.security.rsa.RSAUtil.KeyType; import sun.security.util.Debug; +import sun.security.util.ECUtil; import sun.security.util.ResourcesMgr; import static sun.security.util.SecurityConstants.PROVIDER_VER; import sun.security.pkcs11.Secmod.*; import sun.security.pkcs11.TemplateManager; import sun.security.pkcs11.wrapper.*; +import sun.security.rsa.RSAPrivateCrtKeyImpl; import static sun.security.pkcs11.wrapper.PKCS11Constants.*; /** @@ -524,10 +529,17 @@ byte[] exportKey(long hSession, CK_ATTRIBUTE[] attributes, long keyId) throws PK } } + private static BigInteger getBigIntegerOrZero(Map ckAttrsMap, long attributeType) { + CK_ATTRIBUTE attribute = ckAttrsMap.get(attributeType); + return (attribute != null) ? attribute.getBigInteger() : BigInteger.ZERO; + } + public long importKey(long hSession, CK_ATTRIBUTE[] attributes) throws PKCS11Exception { long keyClass = 0; long keyType = 0; byte[] keyBytes = null; + Map ckAttrsMap = new HashMap<>(); + // Extract key information. for (CK_ATTRIBUTE attr : attributes) { if (attr.type == CKA_CLASS) { @@ -536,12 +548,60 @@ public long importKey(long hSession, CK_ATTRIBUTE[] attributes) throws PKCS11Exc if (attr.type == CKA_KEY_TYPE) { keyType = attr.getLong(); } - if (attr.type == CKA_VALUE) { - keyBytes = attr.getByteArray(); + ckAttrsMap.put(attr.type, attr); + } + + if (keyClass == CKO_PRIVATE_KEY) { + if (keyType == CKK_RSA) { + try { + keyBytes = RSAPrivateCrtKeyImpl.newKey( + KeyType.RSA, + null, + getBigIntegerOrZero(ckAttrsMap, CKA_MODULUS), + getBigIntegerOrZero(ckAttrsMap, CKA_PUBLIC_EXPONENT), + getBigIntegerOrZero(ckAttrsMap, CKA_PRIVATE_EXPONENT), + getBigIntegerOrZero(ckAttrsMap, CKA_PRIME_1), + getBigIntegerOrZero(ckAttrsMap, CKA_PRIME_2), + getBigIntegerOrZero(ckAttrsMap, CKA_EXPONENT_1), + getBigIntegerOrZero(ckAttrsMap, CKA_EXPONENT_2), + getBigIntegerOrZero(ckAttrsMap, CKA_COEFFICIENT) + ).getEncoded(); + } catch (InvalidKeyException e) { + throw new PKCS11Exception(CKR_GENERAL_ERROR); + } + } else if (keyType == CKK_EC) { + CK_ATTRIBUTE ckaECParams = ckAttrsMap.get(CKA_EC_PARAMS); + if (ckaECParams == null) { + throw new PKCS11Exception(CKR_GENERAL_ERROR); + } + try { + keyBytes = ECUtil.generateECPrivateKey( + ckAttrsMap.getOrDefault(CKA_VALUE, new CK_ATTRIBUTE(CKA_VALUE, BigInteger.ZERO)).getBigInteger(), + ECUtil.getECParameterSpec( + Security.getProvider("SunEC"), + ckaECParams.getByteArray()) + ).getEncoded(); + // If key is private and of EC type, NSS may require CKA_NETSCAPE_DB + // attribute to unwrap it. Otherwise, C_UnwrapKey will produce an Exception. + if (token.config.getNssNetscapeDbWorkaround() && !ckAttrsMap.containsKey(CKA_NETSCAPE_DB)) { + ckAttrsMap.put(CKA_NETSCAPE_DB, new CK_ATTRIBUTE(CKA_NETSCAPE_DB, BigInteger.ZERO)); + } + } catch (IOException | InvalidKeySpecException e) { + throw new PKCS11Exception(CKR_GENERAL_ERROR); + } + } + } else if (keyClass == CKO_SECRET_KEY) { + CK_ATTRIBUTE ckaValue = ckAttrsMap.get(CKA_VALUE); + if (ckaValue == null) { + throw new PKCS11Exception(CKR_GENERAL_ERROR); } + keyBytes = ckaValue.getByteArray(); } - if ((keyClass == CKO_SECRET_KEY) && (keyBytes != null) && (keyBytes.length > 0)) { + if ((keyBytes != null) && (keyBytes.length > 0) + && ((keyClass == CKO_SECRET_KEY) + || ((keyClass == CKO_PRIVATE_KEY) && ((keyType == CKK_EC) || (keyType == CKK_RSA)))) + ) { // Generate key used for wrapping and unwrapping of the secret key. CK_ATTRIBUTE[] wrapKeyAttributes = token.getAttributes(TemplateManager.O_GENERATE, CKO_SECRET_KEY, CKK_AES, new CK_ATTRIBUTE[] { new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY), new CK_ATTRIBUTE(CKA_VALUE_LEN, 256 >> 3)}); Session wrapKeyGenSession = token.getObjSession(); @@ -565,7 +625,12 @@ public long importKey(long hSession, CK_ATTRIBUTE[] attributes) throws PKCS11Exc byte[] wrappedBytes = wrapCipher.doFinal(keyBytes); // Unwrap the secret key. - CK_ATTRIBUTE[] unwrapAttributes = token.getAttributes(TemplateManager.O_IMPORT, keyClass, keyType, attributes); + // Need additional attributes for EC private key. + CK_ATTRIBUTE[] unwrapAttributes = token.getAttributes( + TemplateManager.O_IMPORT, + keyClass, + keyType, + ckAttrsMap.values().toArray(new CK_ATTRIBUTE[ckAttrsMap.size()])); return token.p11.C_UnwrapKey(hSession, wrapMechanism, wrapKeyId, wrappedBytes, unwrapAttributes); } catch (PKCS11Exception | NoSuchPaddingException | NoSuchAlgorithmException | BadPaddingException | InvalidAlgorithmParameterException | InvalidKeyException | IllegalBlockSizeException e) { throw new PKCS11Exception(CKR_GENERAL_ERROR); diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java index 1876ec4a776..218ef61f5fb 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java @@ -143,12 +143,25 @@ public static void loadNative() { new HashMap(); static boolean isKey(CK_ATTRIBUTE[] attrs) { + boolean isPrivateKey = false; + boolean hasKey = false; + for (CK_ATTRIBUTE attr : attrs) { - if ((attr.type == CKA_CLASS) && (attr.getLong() == CKO_SECRET_KEY)) { - return true; + if (attr.type == CKA_CLASS) { + if (attr.getLong() == CKO_SECRET_KEY) { + return true; + } else if (attr.getLong() == CKO_PRIVATE_KEY) { + isPrivateKey = true; + } + } else if (attr.type == CKA_KEY_TYPE) { + hasKey = true; + if (!((attr.getLong() == CKK_RSA) || (attr.getLong() == CKK_EC))) { + isPrivateKey = false; + } } } - return false; + + return isPrivateKey && hasKey; } // This is the SunPKCS11 provider instance