Skip to content

Commit 5264d80

Browse files
committed
8350661: PKCS11 HKDF throws ProviderException when requesting a 31-byte AES key
Reviewed-by: fferrari, valeriep, djelinski
1 parent f2587d9 commit 5264d80

File tree

5 files changed

+200
-72
lines changed

5 files changed

+200
-72
lines changed

src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11HKDF.java

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import static sun.security.pkcs11.TemplateManager.*;
3939
import sun.security.pkcs11.wrapper.*;
4040
import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
41+
import static sun.security.pkcs11.wrapper.PKCS11Exception.RV.CKR_KEY_SIZE_RANGE;
4142

4243
final class P11HKDF extends KDFSpi {
4344
private final Token token;
@@ -157,6 +158,15 @@ private <T> T derive(String alg, AlgorithmParameterSpec derivationSpec,
157158
" instance, instead of " + derivationSpec.getClass());
158159
}
159160

161+
P11SecretKeyFactory.KeyInfo ki = P11SecretKeyFactory.getKeyInfo(alg);
162+
if (ki == null) {
163+
throw new InvalidAlgorithmParameterException("A PKCS #11 key " +
164+
"type (CKK_*) was not found for a key of the algorithm '" +
165+
alg + "'.");
166+
}
167+
checkDerivedKeyType(ki, alg);
168+
P11KeyGenerator.checkKeySize(ki.keyGenMech, outLen * 8, token);
169+
160170
P11Key p11BaseKey = convertKey(baseKey, (isExtract ? "IKM" : "PRK") +
161171
" could not be converted to a token key for HKDF derivation.");
162172

@@ -174,17 +184,10 @@ private <T> T derive(String alg, AlgorithmParameterSpec derivationSpec,
174184
"token as service.";
175185
}
176186

177-
P11SecretKeyFactory.KeyInfo ki = P11SecretKeyFactory.getKeyInfo(alg);
178-
if (ki == null) {
179-
throw new InvalidAlgorithmParameterException("A PKCS #11 key " +
180-
"type (CKK_*) was not found for a key of the algorithm '" +
181-
alg + "'.");
182-
}
183-
long derivedKeyType = ki.keyType;
184187
long derivedKeyClass = isData ? CKO_DATA : CKO_SECRET_KEY;
185188
CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
186189
new CK_ATTRIBUTE(CKA_CLASS, derivedKeyClass),
187-
new CK_ATTRIBUTE(CKA_KEY_TYPE, derivedKeyType),
190+
new CK_ATTRIBUTE(CKA_KEY_TYPE, ki.keyType),
188191
new CK_ATTRIBUTE(CKA_VALUE_LEN, outLen)
189192
};
190193
Session session = null;
@@ -195,7 +198,7 @@ private <T> T derive(String alg, AlgorithmParameterSpec derivationSpec,
195198
svcKi.hmacMech, saltType, saltBytes, p11SaltKey != null ?
196199
p11SaltKey.getKeyID() : 0L, info);
197200
attrs = token.getAttributes(O_GENERATE, derivedKeyClass,
198-
derivedKeyType, attrs);
201+
ki.keyType, attrs);
199202
long derivedObjectID = token.p11.C_DeriveKey(session.id(),
200203
new CK_MECHANISM(mechanism, params), baseKeyID, attrs);
201204
Object ret;
@@ -216,6 +219,11 @@ private <T> T derive(String alg, AlgorithmParameterSpec derivationSpec,
216219
}
217220
return retType.cast(ret);
218221
} catch (PKCS11Exception e) {
222+
if (e.match(CKR_KEY_SIZE_RANGE)) {
223+
throw new InvalidAlgorithmParameterException("Invalid key " +
224+
"size (" + outLen + " bytes) for algorithm '" + alg +
225+
"'.", e);
226+
}
219227
throw new ProviderException("HKDF derivation for algorithm '" +
220228
alg + "' failed.", e);
221229
} finally {
@@ -227,6 +235,23 @@ private <T> T derive(String alg, AlgorithmParameterSpec derivationSpec,
227235
}
228236
}
229237

238+
private static boolean canDeriveKeyInfoType(long t) {
239+
return (t == CKK_DES || t == CKK_DES3 || t == CKK_AES ||
240+
t == CKK_RC4 || t == CKK_BLOWFISH || t == CKK_CHACHA20 ||
241+
t == CKK_GENERIC_SECRET);
242+
}
243+
244+
private void checkDerivedKeyType(P11SecretKeyFactory.KeyInfo ki, String alg)
245+
throws InvalidAlgorithmParameterException {
246+
Class<?> kiClass = ki.getClass();
247+
if (!kiClass.equals(P11SecretKeyFactory.TLSKeyInfo.class) &&
248+
!(kiClass.equals(P11SecretKeyFactory.KeyInfo.class) &&
249+
canDeriveKeyInfoType(ki.keyType))) {
250+
throw new InvalidAlgorithmParameterException("A key of algorithm " +
251+
"'" + alg + "' is not valid for derivation.");
252+
}
253+
}
254+
230255
private P11Key.P11SecretKey convertKey(SecretKey key, String errorMessage) {
231256
try {
232257
return (P11Key.P11SecretKey) P11SecretKeyFactory.convertKey(token,

src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyGenerator.java

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -75,9 +75,10 @@ final class P11KeyGenerator extends KeyGeneratorSpi {
7575
// java-specific lower limit; returned values are in bits
7676
private static CK_MECHANISM_INFO getSupportedRange(Token token,
7777
long mech) throws ProviderException {
78-
// No need to query for fix-length algorithms
79-
if (mech == CKM_DES_KEY_GEN || mech == CKM_DES2_KEY_GEN ||
80-
mech == CKM_DES3_KEY_GEN) {
78+
// No need to query if the mechanism is not available or for
79+
// fix-length algorithms
80+
if (mech == CK_UNAVAILABLE_INFORMATION || mech == CKM_DES_KEY_GEN ||
81+
mech == CKM_DES2_KEY_GEN || mech == CKM_DES3_KEY_GEN) {
8182
return null;
8283
}
8384

@@ -115,15 +116,15 @@ private static CK_MECHANISM_INFO getSupportedRange(Token token,
115116
* and within the supported range. Return the significant key size
116117
* upon successful validation.
117118
* @param keyGenMech the PKCS#11 key generation mechanism.
118-
* @param keySize the to-be-checked key size for this mechanism.
119+
* @param keySize the to-be-checked key size (in bits) for this mechanism.
119120
* @param token token which provides this mechanism.
120121
* @return the significant key size (in bits) corresponding to the
121122
* specified key size.
122123
* @throws InvalidParameterException if the specified key size is invalid.
123124
* @throws ProviderException if this mechanism isn't supported by SunPKCS11
124125
* or underlying native impl.
125126
*/
126-
// called by P11SecretKeyFactory to check key size
127+
// called by P11SecretKeyFactory and P11HKDF to check key size
127128
static int checkKeySize(long keyGenMech, int keySize, Token token)
128129
throws InvalidAlgorithmParameterException, ProviderException {
129130
CK_MECHANISM_INFO range = getSupportedRange(token, keyGenMech);
@@ -136,8 +137,8 @@ private static int checkKeySize(long keyGenMech, int keySize,
136137
switch ((int)keyGenMech) {
137138
case (int)CKM_DES_KEY_GEN:
138139
if ((keySize != 64) && (keySize != 56)) {
139-
throw new InvalidAlgorithmParameterException
140-
("DES key length must be 56 bits");
140+
throw new InvalidAlgorithmParameterException("DES key " +
141+
"length was " + keySize + " but must be 56 bits");
141142
}
142143
sigKeySize = 56;
143144
break;
@@ -148,23 +149,26 @@ private static int checkKeySize(long keyGenMech, int keySize,
148149
} else if ((keySize == 168) || (keySize == 192)) {
149150
sigKeySize = 168;
150151
} else {
151-
throw new InvalidAlgorithmParameterException
152-
("DESede key length must be 112, or 168 bits");
152+
throw new InvalidAlgorithmParameterException("DESede key " +
153+
"length was " + keySize + " but must be 112, or " +
154+
"168 bits");
153155
}
154156
break;
155157
default:
156158
// Handle all variable-key-length algorithms here
157-
if (range != null && keySize < range.iMinKeySize
158-
|| keySize > range.iMaxKeySize) {
159-
throw new InvalidAlgorithmParameterException
160-
("Key length must be between " + range.iMinKeySize +
161-
" and " + range.iMaxKeySize + " bits");
159+
if (range != null && (keySize < range.iMinKeySize
160+
|| keySize > range.iMaxKeySize)) {
161+
throw new InvalidAlgorithmParameterException("Key length " +
162+
"was " + keySize + " but must be between " +
163+
range.iMinKeySize + " and " + range.iMaxKeySize +
164+
" bits");
162165
}
163166
if (keyGenMech == CKM_AES_KEY_GEN) {
164167
if ((keySize != 128) && (keySize != 192) &&
165168
(keySize != 256)) {
166-
throw new InvalidAlgorithmParameterException
167-
("AES key length must be 128, 192, or 256 bits");
169+
throw new InvalidAlgorithmParameterException("AES key" +
170+
" length was " + keySize + " but must be 128," +
171+
" 192, or 256 bits");
168172
}
169173
}
170174
sigKeySize = keySize;

src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11SecretKeyFactory.java

Lines changed: 96 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -103,13 +103,37 @@ private static void putKeyInfo(KeyInfo ki) {
103103
keyInfo.put(ki.algo.toUpperCase(Locale.ENGLISH), ki);
104104
}
105105

106-
static sealed class KeyInfo permits PBEKeyInfo, HMACKeyInfo, HKDFKeyInfo {
106+
/*
107+
* The KeyInfo class represents information about a symmetric PKCS #11 key
108+
* type or about the output of a key-based computation (e.g. HMAC). A
109+
* KeyInfo instance may describe the key/output itself, or the type of
110+
* key/output that a service accepts/produces. Used by P11SecretKeyFactory,
111+
* P11PBECipher, P11Mac, and P11HKDF.
112+
*/
113+
static sealed class KeyInfo permits PBEKeyInfo, HMACKeyInfo, HKDFKeyInfo,
114+
TLSKeyInfo {
115+
// Java Standard Algorithm Name.
107116
public final String algo;
117+
118+
// Key type (CKK_*).
108119
public final long keyType;
109120

121+
// Mechanism for C_GenerateKey to generate a key of this type (CKM_*).
122+
// While keys may be generated with other APIs and mechanisms (e.g. AES
123+
// key generated with C_DeriveKey and CKM_HKDF_DERIVE instead of
124+
// C_GenerateKey and CKM_AES_KEY_GEN), this information is used by
125+
// P11KeyGenerator::checkKeySize in a best-effort attempt to validate
126+
// that the key size is within a valid range (see CK_MECHANISM_INFO).
127+
public final long keyGenMech;
128+
110129
KeyInfo(String algo, long keyType) {
130+
this(algo, keyType, CK_UNAVAILABLE_INFORMATION);
131+
}
132+
133+
KeyInfo(String algo, long keyType, long keyGenMech) {
111134
this.algo = algo;
112135
this.keyType = keyType;
136+
this.keyGenMech = keyGenMech;
113137
}
114138

115139
// The P11SecretKeyFactory::convertKey method needs to know if a service
@@ -134,8 +158,26 @@ static boolean checkUse(KeyInfo ki, KeyInfo si) {
134158
}
135159
}
136160

161+
/*
162+
* KeyInfo specialization for keys that are either input or result of a TLS
163+
* key derivation. Keys of this type are typically handled by JSSE and their
164+
* algorithm name start with "Tls". Used by P11HKDF.
165+
*/
166+
static final class TLSKeyInfo extends KeyInfo {
167+
TLSKeyInfo(String algo) {
168+
super(algo, CKK_GENERIC_SECRET);
169+
}
170+
}
171+
172+
/*
173+
* KeyInfo specialization for outputs of a HMAC computation. Used by
174+
* P11SecretKeyFactory and P11Mac.
175+
*/
137176
static final class HMACKeyInfo extends KeyInfo {
177+
// HMAC mechanism (CKM_*) to generate the output.
138178
public final long mech;
179+
180+
// HMAC output length (in bits).
139181
public final int keyLen;
140182

141183
HMACKeyInfo(String algo, long mech, int keyLen) {
@@ -145,6 +187,10 @@ static final class HMACKeyInfo extends KeyInfo {
145187
}
146188
}
147189

190+
/*
191+
* KeyInfo specialization for HKDF key derivation. Used by
192+
* P11SecretKeyFactory and P11HKDF.
193+
*/
148194
static final class HKDFKeyInfo extends KeyInfo {
149195
public static final long UNKNOWN_KEY_TYPE = -1;
150196
public final long hmacMech;
@@ -157,6 +203,10 @@ static final class HKDFKeyInfo extends KeyInfo {
157203
}
158204
}
159205

206+
/*
207+
* KeyInfo specialization for PBE key derivation. Used by
208+
* P11SecretKeyFactory, P11PBECipher and P11Mac.
209+
*/
160210
abstract static sealed class PBEKeyInfo extends KeyInfo
161211
permits AESPBEKeyInfo, PBKDF2KeyInfo, P12MacPBEKeyInfo {
162212
public static final long INVALID_PRF = -1;
@@ -204,24 +254,39 @@ static final class P12MacPBEKeyInfo extends PBEKeyInfo {
204254
}
205255

206256
static {
207-
putKeyInfo(new KeyInfo("RC4", CKK_RC4));
208-
putKeyInfo(new KeyInfo("ARCFOUR", CKK_RC4));
209-
putKeyInfo(new KeyInfo("DES", CKK_DES));
210-
putKeyInfo(new KeyInfo("DESede", CKK_DES3));
211-
putKeyInfo(new KeyInfo("AES", CKK_AES));
212-
putKeyInfo(new KeyInfo("Blowfish", CKK_BLOWFISH));
213-
putKeyInfo(new KeyInfo("ChaCha20", CKK_CHACHA20));
214-
putKeyInfo(new KeyInfo("ChaCha20-Poly1305", CKK_CHACHA20));
257+
putKeyInfo(new KeyInfo("RC4", CKK_RC4, CKM_RC4_KEY_GEN));
258+
putKeyInfo(new KeyInfo("ARCFOUR", CKK_RC4, CKM_RC4_KEY_GEN));
259+
putKeyInfo(new KeyInfo("DES", CKK_DES, CKM_DES_KEY_GEN));
260+
putKeyInfo(new KeyInfo("DESede", CKK_DES3, CKM_DES3_KEY_GEN));
261+
putKeyInfo(new KeyInfo("AES", CKK_AES, CKM_AES_KEY_GEN));
262+
putKeyInfo(new KeyInfo("Blowfish", CKK_BLOWFISH, CKM_BLOWFISH_KEY_GEN));
263+
putKeyInfo(new KeyInfo("ChaCha20", CKK_CHACHA20, CKM_CHACHA20_KEY_GEN));
264+
putKeyInfo(new KeyInfo("ChaCha20-Poly1305", CKK_CHACHA20,
265+
CKM_CHACHA20_KEY_GEN));
215266

216267
// we don't implement RC2 or IDEA, but we want to be able to generate
217268
// keys for those SSL/TLS ciphersuites.
218-
putKeyInfo(new KeyInfo("RC2", CKK_RC2));
219-
putKeyInfo(new KeyInfo("IDEA", CKK_IDEA));
220-
221-
putKeyInfo(new KeyInfo("TlsPremasterSecret", PCKK_TLSPREMASTER));
222-
putKeyInfo(new KeyInfo("TlsRsaPremasterSecret", PCKK_TLSRSAPREMASTER));
223-
putKeyInfo(new KeyInfo("TlsMasterSecret", PCKK_TLSMASTER));
224-
putKeyInfo(new KeyInfo("Generic", CKK_GENERIC_SECRET));
269+
putKeyInfo(new KeyInfo("RC2", CKK_RC2, CKM_RC2_KEY_GEN));
270+
putKeyInfo(new KeyInfo("IDEA", CKK_IDEA, CKM_IDEA_KEY_GEN));
271+
272+
putKeyInfo(new TLSKeyInfo("TlsPremasterSecret"));
273+
putKeyInfo(new TLSKeyInfo("TlsRsaPremasterSecret"));
274+
putKeyInfo(new TLSKeyInfo("TlsMasterSecret"));
275+
putKeyInfo(new TLSKeyInfo("TlsBinderKey"));
276+
putKeyInfo(new TLSKeyInfo("TlsClientAppTrafficSecret"));
277+
putKeyInfo(new TLSKeyInfo("TlsClientHandshakeTrafficSecret"));
278+
putKeyInfo(new TLSKeyInfo("TlsEarlySecret"));
279+
putKeyInfo(new TLSKeyInfo("TlsFinishedSecret"));
280+
putKeyInfo(new TLSKeyInfo("TlsHandshakeSecret"));
281+
putKeyInfo(new TLSKeyInfo("TlsKey"));
282+
putKeyInfo(new TLSKeyInfo("TlsResumptionMasterSecret"));
283+
putKeyInfo(new TLSKeyInfo("TlsSaltSecret"));
284+
putKeyInfo(new TLSKeyInfo("TlsServerAppTrafficSecret"));
285+
putKeyInfo(new TLSKeyInfo("TlsServerHandshakeTrafficSecret"));
286+
putKeyInfo(new TLSKeyInfo("TlsUpdateNplus1"));
287+
288+
putKeyInfo(new KeyInfo("Generic", CKK_GENERIC_SECRET,
289+
CKM_GENERIC_SECRET_KEY_GEN));
225290

226291
HMACKeyInfo hmacSHA1 =
227292
new HMACKeyInfo("HmacSHA1", CKM_SHA_1_HMAC, 160);
@@ -549,34 +614,23 @@ private static P11Key createKey(Token token, byte[] encoded,
549614
long keyType = ki.keyType;
550615
try {
551616
switch ((int) keyType) {
552-
case (int) CKK_DES -> {
553-
keyLength =
554-
P11KeyGenerator.checkKeySize(CKM_DES_KEY_GEN, n, token);
555-
fixDESParity(encoded, 0);
556-
}
557-
case (int) CKK_DES3 -> {
558-
keyLength =
559-
P11KeyGenerator.checkKeySize(CKM_DES3_KEY_GEN, n, token);
560-
fixDESParity(encoded, 0);
561-
fixDESParity(encoded, 8);
562-
if (keyLength == 112) {
563-
keyType = CKK_DES2;
564-
} else {
565-
keyType = CKK_DES3;
566-
fixDESParity(encoded, 16);
617+
case (int) CKK_DES, (int) CKK_DES3, (int) CKK_AES, (int) CKK_RC4,
618+
(int) CKK_BLOWFISH, (int) CKK_CHACHA20 -> {
619+
keyLength = P11KeyGenerator.checkKeySize(ki.keyGenMech, n,
620+
token);
621+
if (keyType == CKK_DES || keyType == CKK_DES3) {
622+
fixDESParity(encoded, 0);
623+
if (keyType == CKK_DES3) {
624+
fixDESParity(encoded, 8);
625+
if (keyLength == 112) {
626+
keyType = CKK_DES2;
627+
} else {
628+
fixDESParity(encoded, 16);
629+
}
630+
}
567631
}
568632
}
569-
case (int) CKK_AES -> keyLength =
570-
P11KeyGenerator.checkKeySize(CKM_AES_KEY_GEN, n, token);
571-
case (int) CKK_RC4 -> keyLength =
572-
P11KeyGenerator.checkKeySize(CKM_RC4_KEY_GEN, n, token);
573-
case (int) CKK_BLOWFISH -> keyLength =
574-
P11KeyGenerator.checkKeySize(CKM_BLOWFISH_KEY_GEN, n,
575-
token);
576-
case (int) CKK_CHACHA20 -> keyLength = P11KeyGenerator.checkKeySize(
577-
CKM_CHACHA20_KEY_GEN, n, token);
578-
case (int) CKK_GENERIC_SECRET, (int) PCKK_TLSPREMASTER, (int) PCKK_TLSRSAPREMASTER, (int) PCKK_TLSMASTER ->
579-
keyType = CKK_GENERIC_SECRET;
633+
case (int) CKK_GENERIC_SECRET -> {}
580634
default -> throw new InvalidKeyException("Unknown algorithm " +
581635
algorithm);
582636
}

src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11Constants.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -311,10 +311,6 @@ public interface PKCS11Constants {
311311
// pseudo key type ANY (for template manager)
312312
public static final long PCKK_ANY = 0x7FFFFF22L;
313313

314-
public static final long PCKK_TLSPREMASTER = 0x7FFFFF25L;
315-
public static final long PCKK_TLSRSAPREMASTER = 0x7FFFFF26L;
316-
public static final long PCKK_TLSMASTER = 0x7FFFFF27L;
317-
318314
/* Uncomment when actually used
319315
public static final long CK_CERTIFICATE_CATEGORY_UNSPECIFIED = 0L;
320316
public static final long CK_CERTIFICATE_CATEGORY_TOKEN_USER = 1L;

0 commit comments

Comments
 (0)