Skip to content

Commit 1e26894

Browse files
franferraxmartinuy
andauthored
RH2048582: Support PKCS#12 keystores (#2)
* RH2048582: Support PKCS#12 keystores v16 * Change default keystore type for FIPS Align it with the non-FIPS keystore type (pkcs12) now that it is supported * Register new SunPKCS11 algorithms only for FIPS mode This is: RHEL is in FIPS mode (non default), and the OpenJDK has been configured to align with it (default) Co-authored-by: Martin Balao <[email protected]> Reviewed-by: @gnu-andrew
1 parent bb46af0 commit 1e26894

File tree

25 files changed

+2168
-301
lines changed

25 files changed

+2168
-301
lines changed

src/java.base/share/classes/com/sun/crypto/provider/HmacPKCS12PBECore.java

Lines changed: 8 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,12 @@
2525

2626
package com.sun.crypto.provider;
2727

28-
import java.util.Arrays;
29-
3028
import javax.crypto.SecretKey;
3129
import javax.crypto.spec.SecretKeySpec;
32-
import javax.crypto.spec.PBEParameterSpec;
30+
import javax.crypto.spec.PBEKeySpec;
3331
import java.security.*;
3432
import java.security.spec.*;
33+
import sun.security.util.PBEUtil;
3534

3635
/**
3736
* This is an implementation of the HMAC algorithms as defined
@@ -108,79 +107,15 @@ public HmacPKCS12PBECore(String algorithm, int bl) throws NoSuchAlgorithmExcepti
108107
*/
109108
protected void engineInit(Key key, AlgorithmParameterSpec params)
110109
throws InvalidKeyException, InvalidAlgorithmParameterException {
111-
char[] passwdChars;
112-
byte[] salt = null;
113-
int iCount = 0;
114-
if (key instanceof javax.crypto.interfaces.PBEKey) {
115-
javax.crypto.interfaces.PBEKey pbeKey =
116-
(javax.crypto.interfaces.PBEKey) key;
117-
passwdChars = pbeKey.getPassword();
118-
salt = pbeKey.getSalt(); // maybe null if unspecified
119-
iCount = pbeKey.getIterationCount(); // maybe 0 if unspecified
120-
} else if (key instanceof SecretKey) {
121-
byte[] passwdBytes;
122-
if (!(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3)) ||
123-
(passwdBytes = key.getEncoded()) == null) {
124-
throw new InvalidKeyException("Missing password");
125-
}
126-
passwdChars = new char[passwdBytes.length];
127-
for (int i=0; i<passwdChars.length; i++) {
128-
passwdChars[i] = (char) (passwdBytes[i] & 0x7f);
129-
}
130-
Arrays.fill(passwdBytes, (byte)0x00);
131-
} else {
132-
throw new InvalidKeyException("SecretKey of PBE type required");
133-
}
134-
110+
PBEKeySpec keySpec = PBEUtil.getPBAKeySpec(key, params);
135111
byte[] derivedKey;
136112
try {
137-
if (params == null) {
138-
// should not auto-generate default values since current
139-
// javax.crypto.Mac api does not have any method for caller to
140-
// retrieve the generated defaults.
141-
if ((salt == null) || (iCount == 0)) {
142-
throw new InvalidAlgorithmParameterException
143-
("PBEParameterSpec required for salt and iteration count");
144-
}
145-
} else if (!(params instanceof PBEParameterSpec)) {
146-
throw new InvalidAlgorithmParameterException
147-
("PBEParameterSpec type required");
148-
} else {
149-
PBEParameterSpec pbeParams = (PBEParameterSpec) params;
150-
// make sure the parameter values are consistent
151-
if (salt != null) {
152-
if (!Arrays.equals(salt, pbeParams.getSalt())) {
153-
throw new InvalidAlgorithmParameterException
154-
("Inconsistent value of salt between key and params");
155-
}
156-
} else {
157-
salt = pbeParams.getSalt();
158-
}
159-
if (iCount != 0) {
160-
if (iCount != pbeParams.getIterationCount()) {
161-
throw new InvalidAlgorithmParameterException
162-
("Different iteration count between key and params");
163-
}
164-
} else {
165-
iCount = pbeParams.getIterationCount();
166-
}
167-
}
168-
// For security purpose, we need to enforce a minimum length
169-
// for salt; just require the minimum salt length to be 8-byte
170-
// which is what PKCS#5 recommends and openssl does.
171-
if (salt.length < 8) {
172-
throw new InvalidAlgorithmParameterException
173-
("Salt must be at least 8 bytes long");
174-
}
175-
if (iCount <= 0) {
176-
throw new InvalidAlgorithmParameterException
177-
("IterationCount must be a positive number");
178-
}
179-
derivedKey = PKCS12PBECipherCore.derive(passwdChars, salt,
180-
iCount, engineGetMacLength(), PKCS12PBECipherCore.MAC_KEY,
181-
algorithm, bl);
113+
derivedKey = PKCS12PBECipherCore.derive(
114+
keySpec.getPassword(), keySpec.getSalt(),
115+
keySpec.getIterationCount(), engineGetMacLength(),
116+
PKCS12PBECipherCore.MAC_KEY, algorithm, bl);
182117
} finally {
183-
Arrays.fill(passwdChars, '\0');
118+
keySpec.clearPassword();
184119
}
185120
SecretKey cipherKey = new SecretKeySpec(derivedKey, "HmacSHA1");
186121
super.engineInit(cipherKey, null);

src/java.base/share/classes/com/sun/crypto/provider/PBES2Core.java

Lines changed: 11 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,11 @@
2727

2828
import java.security.*;
2929
import java.security.spec.*;
30-
import java.util.Arrays;
3130
import javax.crypto.*;
3231
import javax.crypto.spec.*;
3332

33+
import sun.security.util.PBEUtil;
34+
3435
/**
3536
* This class represents password-based encryption as defined by the PKCS #5
3637
* standard.
@@ -54,9 +55,8 @@ abstract class PBES2Core extends CipherSpi {
5455
private final PBKDF2Core kdf;
5556
private final String pbeAlgo;
5657
private final String cipherAlgo;
57-
private int iCount = DEFAULT_COUNT;
58-
private byte[] salt = null;
59-
private IvParameterSpec ivSpec = null;
58+
private final PBEUtil.PBES2Helper pbes2Helper = new PBEUtil.PBES2Helper(
59+
DEFAULT_SALT_LENGTH, DEFAULT_COUNT);
6060

6161
/**
6262
* Creates an instance of PBE Scheme 2 according to the selected
@@ -129,32 +129,8 @@ protected byte[] engineGetIV() {
129129
}
130130

131131
protected AlgorithmParameters engineGetParameters() {
132-
AlgorithmParameters params = null;
133-
if (salt == null) {
134-
// generate random salt and use default iteration count
135-
salt = new byte[DEFAULT_SALT_LENGTH];
136-
SunJCE.getRandom().nextBytes(salt);
137-
iCount = DEFAULT_COUNT;
138-
}
139-
if (ivSpec == null) {
140-
// generate random IV
141-
byte[] ivBytes = new byte[blkSize];
142-
SunJCE.getRandom().nextBytes(ivBytes);
143-
ivSpec = new IvParameterSpec(ivBytes);
144-
}
145-
PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, iCount, ivSpec);
146-
try {
147-
params = AlgorithmParameters.getInstance(pbeAlgo,
148-
SunJCE.getInstance());
149-
params.init(pbeSpec);
150-
} catch (NoSuchAlgorithmException nsae) {
151-
// should never happen
152-
throw new RuntimeException("SunJCE called, but not configured");
153-
} catch (InvalidParameterSpecException ipse) {
154-
// should never happen
155-
throw new RuntimeException("PBEParameterSpec not supported");
156-
}
157-
return params;
132+
return pbes2Helper.getAlgorithmParameters(
133+
blkSize, pbeAlgo, SunJCE.getInstance(), SunJCE.getRandom());
158134
}
159135

160136
protected void engineInit(int opmode, Key key, SecureRandom random)
@@ -174,105 +150,8 @@ protected void engineInit(int opmode, Key key,
174150
SecureRandom random)
175151
throws InvalidKeyException, InvalidAlgorithmParameterException {
176152

177-
if (key == null) {
178-
throw new InvalidKeyException("Null key");
179-
}
180-
181-
byte[] passwdBytes = key.getEncoded();
182-
char[] passwdChars = null;
183-
PBEKeySpec pbeSpec;
184-
try {
185-
if ((passwdBytes == null) ||
186-
!(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) {
187-
throw new InvalidKeyException("Missing password");
188-
}
189-
190-
// TBD: consolidate the salt, ic and IV parameter checks below
191-
192-
// Extract salt and iteration count from the key, if present
193-
if (key instanceof javax.crypto.interfaces.PBEKey) {
194-
salt = ((javax.crypto.interfaces.PBEKey)key).getSalt();
195-
if (salt != null && salt.length < 8) {
196-
throw new InvalidAlgorithmParameterException(
197-
"Salt must be at least 8 bytes long");
198-
}
199-
iCount = ((javax.crypto.interfaces.PBEKey)key).getIterationCount();
200-
if (iCount == 0) {
201-
iCount = DEFAULT_COUNT;
202-
} else if (iCount < 0) {
203-
throw new InvalidAlgorithmParameterException(
204-
"Iteration count must be a positive number");
205-
}
206-
}
207-
208-
// Extract salt, iteration count and IV from the params, if present
209-
if (params == null) {
210-
if (salt == null) {
211-
// generate random salt and use default iteration count
212-
salt = new byte[DEFAULT_SALT_LENGTH];
213-
random.nextBytes(salt);
214-
iCount = DEFAULT_COUNT;
215-
}
216-
if ((opmode == Cipher.ENCRYPT_MODE) ||
217-
(opmode == Cipher.WRAP_MODE)) {
218-
// generate random IV
219-
byte[] ivBytes = new byte[blkSize];
220-
random.nextBytes(ivBytes);
221-
ivSpec = new IvParameterSpec(ivBytes);
222-
}
223-
} else {
224-
if (!(params instanceof PBEParameterSpec)) {
225-
throw new InvalidAlgorithmParameterException
226-
("Wrong parameter type: PBE expected");
227-
}
228-
// salt and iteration count from the params take precedence
229-
byte[] specSalt = ((PBEParameterSpec) params).getSalt();
230-
if (specSalt != null && specSalt.length < 8) {
231-
throw new InvalidAlgorithmParameterException(
232-
"Salt must be at least 8 bytes long");
233-
}
234-
salt = specSalt;
235-
int specICount = ((PBEParameterSpec) params).getIterationCount();
236-
if (specICount == 0) {
237-
specICount = DEFAULT_COUNT;
238-
} else if (specICount < 0) {
239-
throw new InvalidAlgorithmParameterException(
240-
"Iteration count must be a positive number");
241-
}
242-
iCount = specICount;
243-
244-
AlgorithmParameterSpec specParams =
245-
((PBEParameterSpec) params).getParameterSpec();
246-
if (specParams != null) {
247-
if (specParams instanceof IvParameterSpec) {
248-
ivSpec = (IvParameterSpec)specParams;
249-
} else {
250-
throw new InvalidAlgorithmParameterException(
251-
"Wrong parameter type: IV expected");
252-
}
253-
} else if ((opmode == Cipher.ENCRYPT_MODE) ||
254-
(opmode == Cipher.WRAP_MODE)) {
255-
// generate random IV
256-
byte[] ivBytes = new byte[blkSize];
257-
random.nextBytes(ivBytes);
258-
ivSpec = new IvParameterSpec(ivBytes);
259-
} else {
260-
throw new InvalidAlgorithmParameterException(
261-
"Missing parameter type: IV expected");
262-
}
263-
}
264-
265-
passwdChars = new char[passwdBytes.length];
266-
for (int i = 0; i < passwdChars.length; i++)
267-
passwdChars[i] = (char) (passwdBytes[i] & 0x7f);
268-
269-
pbeSpec = new PBEKeySpec(passwdChars, salt, iCount, keyLength);
270-
// password char[] was cloned in PBEKeySpec constructor,
271-
// so we can zero it out here
272-
} finally {
273-
if (passwdChars != null) Arrays.fill(passwdChars, '\0');
274-
if (passwdBytes != null) Arrays.fill(passwdBytes, (byte)0x00);
275-
}
153+
PBEKeySpec pbeSpec = pbes2Helper.getPBEKeySpec(blkSize, keyLength,
154+
opmode, key, params, random);
276155

277156
PBKDF2KeyImpl s;
278157

@@ -291,22 +170,14 @@ protected void engineInit(int opmode, Key key,
291170
SecretKeySpec cipherKey = new SecretKeySpec(derivedKey, cipherAlgo);
292171

293172
// initialize the underlying cipher
294-
cipher.init(opmode, cipherKey, ivSpec, random);
173+
cipher.init(opmode, cipherKey, pbes2Helper.getIvSpec(), random);
295174
}
296175

297176
protected void engineInit(int opmode, Key key, AlgorithmParameters params,
298177
SecureRandom random)
299178
throws InvalidKeyException, InvalidAlgorithmParameterException {
300-
AlgorithmParameterSpec pbeSpec = null;
301-
if (params != null) {
302-
try {
303-
pbeSpec = params.getParameterSpec(PBEParameterSpec.class);
304-
} catch (InvalidParameterSpecException ipse) {
305-
throw new InvalidAlgorithmParameterException(
306-
"Wrong parameter type: PBE expected");
307-
}
308-
}
309-
engineInit(opmode, key, pbeSpec, random);
179+
engineInit(opmode, key, PBEUtil.PBES2Helper.getParameterSpec(params),
180+
random);
310181
}
311182

312183
protected byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) {

0 commit comments

Comments
 (0)