Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
bef6ba0
Add missing trace in p11_util.c
franferrax Oct 4, 2022
7efaec5
Rename internal helper method
franferrax Oct 4, 2022
7e3ef9b
Implement sun.security.pkcs11.P11Key.P11PBEKey
franferrax Nov 4, 2022
25d53d4
P11SKF: preserve the algorithm of PBKDF2* keys
franferrax Oct 4, 2022
8ee2c3c
Introduce itCount and keySize checks
franferrax Oct 4, 2022
11358d3
Remove P11Util.KDFData.Operation.GENERIC
franferrax Oct 18, 2022
94006d9
Replace Operation enum with direct attributes
franferrax Oct 18, 2022
d5fe023
Make P11Util.KDFData instances immutable
franferrax Oct 18, 2022
d1638c2
Improve and align PBAMac and PBECipher tests
franferrax Oct 20, 2022
8ce6438
Extend PBAMac and PBECipher tests
franferrax Oct 20, 2022
58da09b
Reorder code
franferrax Oct 25, 2022
f65221e
Use proper key types when deriving
franferrax Oct 25, 2022
a6b72f0
Make P11SecretKeyFactory usable with PBE
franferrax Oct 25, 2022
0bbfa0b
Implement TestPBKD translation cases
franferrax Oct 26, 2022
cfa2649
Rename printByteArray() method
franferrax Nov 3, 2022
c5ea3db
Implement SunPKCS11's SKF.getKeySpec()
franferrax Nov 4, 2022
8b675d8
Review: fix P11PBEKey, rename PBES2Helper
franferrax Dec 13, 2022
6041151
Review: implement AlgorithmParameterSpec check
franferrax Dec 13, 2022
6b5e4a7
Review: integrate KDFData into P11SecretKeyFactory
franferrax Dec 13, 2022
2cda36a
Review: minor tests adjustments
franferrax Dec 13, 2022
1687d37
Review: improve tests assertion data
franferrax Dec 13, 2022
326482d
Review: increase P11SecretKeyFactory coverage
franferrax Dec 13, 2022
c430dc4
Review: add P11SecretKeyFactory invalid cases
franferrax Dec 13, 2022
709f49e
Fix broken Mac tests outside PBE new ones
franferrax Dec 16, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 5 additions & 10 deletions src/java.base/share/classes/com/sun/crypto/provider/PBES2Core.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,19 +44,14 @@
* @see javax.crypto.Cipher
*/
abstract class PBES2Core extends CipherSpi {

private static final int DEFAULT_SALT_LENGTH = 20;
private static final int DEFAULT_COUNT = 4096;

// the encapsulated cipher
private final CipherCore cipher;
private final int keyLength; // in bits
private final int blkSize; // in bits
private final PBKDF2Core kdf;
private final String pbeAlgo;
private final String cipherAlgo;
private final PBEUtil.PBES2Helper pbes2Helper = new PBEUtil.PBES2Helper(
DEFAULT_SALT_LENGTH, DEFAULT_COUNT);
private final PBEUtil.PBES2Params pbes2Params = new PBEUtil.PBES2Params();

/**
* Creates an instance of PBE Scheme 2 according to the selected
Expand Down Expand Up @@ -129,7 +124,7 @@ protected byte[] engineGetIV() {
}

protected AlgorithmParameters engineGetParameters() {
return pbes2Helper.getAlgorithmParameters(
return pbes2Params.getAlgorithmParameters(
blkSize, pbeAlgo, SunJCE.getInstance(), SunJCE.getRandom());
}

Expand All @@ -150,7 +145,7 @@ protected void engineInit(int opmode, Key key,
SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException {

PBEKeySpec pbeSpec = pbes2Helper.getPBEKeySpec(blkSize, keyLength,
PBEKeySpec pbeSpec = pbes2Params.getPBEKeySpec(blkSize, keyLength,
opmode, key, params, random);

PBKDF2KeyImpl s;
Expand All @@ -170,13 +165,13 @@ protected void engineInit(int opmode, Key key,
SecretKeySpec cipherKey = new SecretKeySpec(derivedKey, cipherAlgo);

// initialize the underlying cipher
cipher.init(opmode, cipherKey, pbes2Helper.getIvSpec(), random);
cipher.init(opmode, cipherKey, pbes2Params.getIvSpec(), random);
}

protected void engineInit(int opmode, Key key, AlgorithmParameters params,
SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException {
engineInit(opmode, key, PBEUtil.PBES2Helper.getParameterSpec(params),
engineInit(opmode, key, PBEUtil.PBES2Params.getParameterSpec(params),
random);
}

Expand Down
92 changes: 56 additions & 36 deletions src/java.base/share/classes/sun/security/util/PBEUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,30 +44,26 @@
public final class PBEUtil {

// Used by SunJCE and SunPKCS11
public final static class PBES2Helper {
public final static class PBES2Params {
private static final int DEFAULT_SALT_LENGTH = 20;
private static final int DEFAULT_ITERATIONS = 4096;

private int iCount;
private byte[] salt;
private IvParameterSpec ivSpec;
private final int defaultSaltLength;
private final int defaultCount;

public PBES2Helper(int defaultSaltLength, int defaultCount) {
this.defaultSaltLength = defaultSaltLength;
this.defaultCount = defaultCount;
}

public IvParameterSpec getIvSpec() {
return ivSpec;
}

public AlgorithmParameters getAlgorithmParameters(
int blkSize, String pbeAlgo, Provider p, SecureRandom random) {
public AlgorithmParameters getAlgorithmParameters(int blkSize,
String pbeAlgo, Provider p, SecureRandom random) {
AlgorithmParameters params = null;
if (salt == null) {
// generate random salt and use default iteration count
salt = new byte[defaultSaltLength];
salt = new byte[DEFAULT_SALT_LENGTH];
random.nextBytes(salt);
iCount = defaultCount;
iCount = DEFAULT_ITERATIONS;
}
if (ivSpec == null) {
// generate random IV
Expand All @@ -93,11 +89,9 @@ public AlgorithmParameters getAlgorithmParameters(
return params;
}

public PBEKeySpec getPBEKeySpec(
int blkSize, int keyLength, int opmode, Key key,
AlgorithmParameterSpec params, SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException {

public PBEKeySpec getPBEKeySpec(int blkSize, int keyLength, int opmode,
Key key, AlgorithmParameterSpec params, SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException {
if (key == null) {
throw new InvalidKeyException("Null key");
}
Expand All @@ -123,7 +117,7 @@ public PBEKeySpec getPBEKeySpec(
iCount = ((javax.crypto.interfaces.PBEKey)key)
.getIterationCount();
if (iCount == 0) {
iCount = defaultCount;
iCount = DEFAULT_ITERATIONS;
} else if (iCount < 0) {
throw new InvalidAlgorithmParameterException(
"Iteration count must be a positive number");
Expand All @@ -135,9 +129,9 @@ public PBEKeySpec getPBEKeySpec(
if (params == null) {
if (salt == null) {
// generate random salt and use default iteration count
salt = new byte[defaultSaltLength];
salt = new byte[DEFAULT_SALT_LENGTH];
random.nextBytes(salt);
iCount = defaultCount;
iCount = DEFAULT_ITERATIONS;
}
if ((opmode == Cipher.ENCRYPT_MODE) ||
(opmode == Cipher.WRAP_MODE)) {
Expand All @@ -148,8 +142,8 @@ public PBEKeySpec getPBEKeySpec(
}
} else {
if (!(params instanceof PBEParameterSpec)) {
throw new InvalidAlgorithmParameterException
("Wrong parameter type: PBE expected");
throw new InvalidAlgorithmParameterException(
"Wrong parameter type: PBE expected");
}
// salt and iteration count from the params take precedence
byte[] specSalt = ((PBEParameterSpec) params).getSalt();
Expand All @@ -161,7 +155,7 @@ public PBEKeySpec getPBEKeySpec(
int specICount = ((PBEParameterSpec) params)
.getIterationCount();
if (specICount == 0) {
specICount = defaultCount;
specICount = DEFAULT_ITERATIONS;
} else if (specICount < 0) {
throw new InvalidAlgorithmParameterException(
"Iteration count must be a positive number");
Expand Down Expand Up @@ -220,7 +214,8 @@ public static AlgorithmParameterSpec getParameterSpec(
}

// Used by SunJCE and SunPKCS11
public static PBEKeySpec getPBAKeySpec(Key key, AlgorithmParameterSpec params)
public static PBEKeySpec getPBAKeySpec(Key key,
AlgorithmParameterSpec params)
throws InvalidKeyException, InvalidAlgorithmParameterException {
char[] passwdChars;
byte[] salt = null;
Expand Down Expand Up @@ -252,27 +247,30 @@ public static PBEKeySpec getPBAKeySpec(Key key, AlgorithmParameterSpec params)
// javax.crypto.Mac api does not have any method for caller to
// retrieve the generated defaults.
if ((salt == null) || (iCount == 0)) {
throw new InvalidAlgorithmParameterException
("PBEParameterSpec required for salt and iteration count");
throw new InvalidAlgorithmParameterException(
"PBEParameterSpec required for salt " +
"and iteration count");
}
} else if (!(params instanceof PBEParameterSpec)) {
throw new InvalidAlgorithmParameterException
("PBEParameterSpec type required");
throw new InvalidAlgorithmParameterException(
"PBEParameterSpec type required");
} else {
PBEParameterSpec pbeParams = (PBEParameterSpec) params;
// make sure the parameter values are consistent
if (salt != null) {
if (!Arrays.equals(salt, pbeParams.getSalt())) {
throw new InvalidAlgorithmParameterException
("Inconsistent value of salt between key and params");
throw new InvalidAlgorithmParameterException(
"Inconsistent value of salt " +
"between key and params");
}
} else {
salt = pbeParams.getSalt();
}
if (iCount != 0) {
if (iCount != pbeParams.getIterationCount()) {
throw new InvalidAlgorithmParameterException
("Different iteration count between key and params");
throw new InvalidAlgorithmParameterException(
"Different iteration count " +
"between key and params");
}
} else {
iCount = pbeParams.getIterationCount();
Expand All @@ -282,16 +280,38 @@ public static PBEKeySpec getPBAKeySpec(Key key, AlgorithmParameterSpec params)
// for salt; just require the minimum salt length to be 8-byte
// which is what PKCS#5 recommends and openssl does.
if (salt.length < 8) {
throw new InvalidAlgorithmParameterException
("Salt must be at least 8 bytes long");
throw new InvalidAlgorithmParameterException(
"Salt must be at least 8 bytes long");
}
if (iCount <= 0) {
throw new InvalidAlgorithmParameterException
("IterationCount must be a positive number");
throw new InvalidAlgorithmParameterException(
"IterationCount must be a positive number");
}
return new PBEKeySpec(passwdChars, salt, iCount);
} finally {
Arrays.fill(passwdChars, '\0');
}
}

public static AlgorithmParameterSpec checkKeyParams(Key key,
AlgorithmParameterSpec params, String algorithm)
throws InvalidKeyException, InvalidAlgorithmParameterException {
if (key instanceof javax.crypto.interfaces.PBEKey pbeKey) {
if (params instanceof PBEParameterSpec pbeParams) {
if (pbeParams.getIterationCount() !=
pbeKey.getIterationCount() ||
!Arrays.equals(pbeParams.getSalt(), pbeKey.getSalt())) {
throw new InvalidAlgorithmParameterException(
"Salt or iteration count parameters are " +
"not consistent with PBE key");
}
return pbeParams.getParameterSpec();
}
} else {
throw new InvalidKeyException(
"Cannot use a " + algorithm + " service with a key that " +
"does not implement javax.crypto.interfaces.PBEKey");
}
return params;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,18 @@ static SecretKey secretKey(Session session, long keyID, String algorithm,
attributes);
}

static SecretKey pbeKey(Session session, long keyID, String algorithm,
int keyLength, CK_ATTRIBUTE[] attributes,
char[] password, byte[] salt, int iterationCount) {
attributes = getAttributes(session, keyID, attributes, new CK_ATTRIBUTE[] {
new CK_ATTRIBUTE(CKA_TOKEN),
new CK_ATTRIBUTE(CKA_SENSITIVE),
new CK_ATTRIBUTE(CKA_EXTRACTABLE),
});
return new P11PBEKey(session, keyID, algorithm, keyLength,
attributes, password, salt, iterationCount);
}

static SecretKey masterSecretKey(Session session, long keyID, String algorithm,
int keyLength, CK_ATTRIBUTE[] attributes, int major, int minor) {
attributes = getAttributes(session, keyID, attributes, new CK_ATTRIBUTE[] {
Expand Down Expand Up @@ -507,6 +519,37 @@ byte[] getEncodedInternal() {
}
}

private static final class P11PBEKey extends P11SecretKey
implements PBEKey {
private static final long serialVersionUID = 6847576994253634876L;
private final char[] password;
private final byte[] salt;
private final int iterationCount;
P11PBEKey(Session session, long keyID, String algorithm,
int keyLength, CK_ATTRIBUTE[] attributes,
char[] password, byte[] salt, int iterationCount) {
super(session, keyID, algorithm, keyLength, attributes);
this.password = password;
this.salt = salt;
this.iterationCount = iterationCount;
}

@Override
public char[] getPassword() {
return password.clone();
}

@Override
public byte[] getSalt() {
return salt.clone();
}

@Override
public int getIterationCount() {
return iterationCount;
}
}

@SuppressWarnings("deprecation")
private static class P11TlsMasterSecretKey extends P11SecretKey
implements TlsMasterSecret {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ final class P11Mac extends MacSpi {
// algorithm name
private final String algorithm;

// PBEKeyInfo if algorithm is PBE
private final P11SecretKeyFactory.PBEKeyInfo svcPbeKi;

// whether the algorithm is a PBE one
private final boolean isPbeAlg;

// mechanism object
private final CK_MECHANISM ckMechanism;

Expand All @@ -87,6 +93,8 @@ final class P11Mac extends MacSpi {
super();
this.token = token;
this.algorithm = algorithm;
this.svcPbeKi = P11SecretKeyFactory.getPBEKeyInfo(algorithm);
this.isPbeAlg = this.svcPbeKi != null;
Long params = null;
switch ((int)mechanism) {
case (int)CKM_MD5_HMAC:
Expand Down Expand Up @@ -205,21 +213,27 @@ protected void engineReset() {
// see JCE spec
protected void engineInit(Key key, AlgorithmParameterSpec params)
throws InvalidKeyException, InvalidAlgorithmParameterException {
if (algorithm.startsWith("HmacPBE")) {
PBEKeySpec pbeSpec = PBEUtil.getPBAKeySpec(key, params);
reset(true);
try {
p11Key = P11SecretKeyFactory.derivePBEKey(
token, pbeSpec, algorithm);
} catch (InvalidKeySpecException e) {
throw new InvalidKeyException(e);
reset(true);
if (isPbeAlg) {
if (key instanceof P11Key) {
params = PBEUtil.checkKeyParams(key, params, algorithm);
} else {
// The key is a plain password. Use SunPKCS11's PBE
// key derivation mechanism to obtain a P11Key.
PBEKeySpec pbeSpec = PBEUtil.getPBAKeySpec(key, params);
try {
p11Key = P11SecretKeyFactory.derivePBEKey(
token, pbeSpec, svcPbeKi);
} catch (InvalidKeySpecException e) {
throw new InvalidKeyException(e);
}
}
} else {
}
if (!isPbeAlg || key instanceof P11Key) {
if (params != null) {
throw new InvalidAlgorithmParameterException
("Parameters not supported");
}
reset(true);
p11Key = P11SecretKeyFactory.convertKey(token, key, algorithm);
}
try {
Expand Down
Loading