Skip to content

Commit 914b44e

Browse files
committed
8368694: PKCS11-NSS generic keys generated by DH have leading zeroes stripped
Reviewed-by: valeriep
1 parent 0b81db1 commit 914b44e

File tree

3 files changed

+63
-36
lines changed

3 files changed

+63
-36
lines changed

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

Lines changed: 19 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ protected byte[] engineGenerateSecret() throws IllegalStateException {
200200
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
201201
new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
202202
new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_GENERIC_SECRET),
203+
new CK_ATTRIBUTE(CKA_VALUE_LEN, secretLen),
203204
};
204205
attributes = token.getAttributes
205206
(O_GENERATE, CKO_SECRET_KEY, CKK_GENERIC_SECRET, attributes);
@@ -213,22 +214,11 @@ protected byte[] engineGenerateSecret() throws IllegalStateException {
213214
token.p11.C_GetAttributeValue(session.id(), keyID, attributes);
214215
byte[] secret = attributes[0].getByteArray();
215216
token.p11.C_DestroyObject(session.id(), keyID);
216-
// Some vendors, e.g. NSS, trim off the leading 0x00 byte(s) from
217-
// the generated secret. Thus, we need to check the secret length
218-
// and trim/pad it so the returned value has the same length as
219-
// the modulus size
220-
if (secret.length == secretLen) {
221-
return secret;
222-
} else {
223-
if (secret.length > secretLen) {
224-
// Shouldn't happen; but check just in case
225-
throw new ProviderException("generated secret is out-of-range");
226-
}
227-
byte[] newSecret = new byte[secretLen];
228-
System.arraycopy(secret, 0, newSecret, secretLen - secret.length,
229-
secret.length);
230-
return newSecret;
217+
if (secret.length != secretLen) {
218+
// Shouldn't happen; but check just in case
219+
throw new ProviderException("generated secret is out-of-range");
231220
}
221+
return secret;
232222
} catch (PKCS11Exception e) {
233223
throw new ProviderException("Could not derive key", e);
234224
} finally {
@@ -321,10 +311,20 @@ private SecretKey nativeGenerateSecret(String algorithm)
321311
long privKeyID = privateKey.getKeyID();
322312
try {
323313
session = token.getObjSession();
324-
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
325-
new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
326-
new CK_ATTRIBUTE(CKA_KEY_TYPE, keyType),
327-
};
314+
CK_ATTRIBUTE[] attributes;
315+
if ("TlsPremasterSecret".equalsIgnoreCase(algorithm)) {
316+
attributes = new CK_ATTRIBUTE[]{
317+
new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
318+
new CK_ATTRIBUTE(CKA_KEY_TYPE, keyType),
319+
};
320+
} else {
321+
// keep the leading zeroes
322+
attributes = new CK_ATTRIBUTE[]{
323+
new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
324+
new CK_ATTRIBUTE(CKA_KEY_TYPE, keyType),
325+
new CK_ATTRIBUTE(CKA_VALUE_LEN, secretLen),
326+
};
327+
}
328328
attributes = token.getAttributes
329329
(O_GENERATE, CKO_SECRET_KEY, keyType, attributes);
330330
long keyID = token.p11.C_DeriveKey(session.id(),
@@ -337,19 +337,6 @@ private SecretKey nativeGenerateSecret(String algorithm)
337337
int keyLen = (int)lenAttributes[0].getLong();
338338
SecretKey key = P11Key.secretKey
339339
(session, keyID, algorithm, keyLen << 3, attributes);
340-
if ("RAW".equals(key.getFormat())
341-
&& algorithm.equalsIgnoreCase("TlsPremasterSecret")) {
342-
// Workaround for Solaris bug 6318543.
343-
// Strip leading zeroes ourselves if possible (key not sensitive).
344-
// This should be removed once the Solaris fix is available
345-
// as here we always retrieve the CKA_VALUE even for tokens
346-
// that do not have that bug.
347-
byte[] keyBytes = key.getEncoded();
348-
byte[] newBytes = KeyUtil.trimZeroes(keyBytes);
349-
if (keyBytes != newBytes) {
350-
key = new SecretKeySpec(newBytes, algorithm);
351-
}
352-
}
353340
return key;
354341
} catch (PKCS11Exception e) {
355342
throw new InvalidKeyException("Could not derive key", e);

test/jdk/com/sun/crypto/provider/TLS/TestLeadingZeroes.java

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2013, 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
@@ -23,7 +23,7 @@
2323

2424
/*
2525
* @test
26-
* @bug 8014618
26+
* @bug 8014618 8368694
2727
* @summary Need to strip leading zeros in TlsPremasterSecret of DHKeyAgreement
2828
* @author Pasi Eronen
2929
*/
@@ -88,6 +88,26 @@ private void run() throws Exception {
8888
throw new Exception("First byte is not zero as expected");
8989
}
9090

91+
// generate generic shared secret
92+
aliceKeyAgree.init(alicePrivKey);
93+
aliceKeyAgree.doPhase(bobPubKey, true);
94+
byte[] genericSecret =
95+
aliceKeyAgree.generateSecret("Generic").getEncoded();
96+
System.out.println("generic secret:\n" + HEX_FORMATTER.formatHex(genericSecret));
97+
98+
// verify that leading zero is present
99+
if (genericSecret.length != 256) {
100+
throw new Exception("Unexpected generic secret length");
101+
}
102+
if (genericSecret[0] != 0) {
103+
throw new Exception("First byte is not zero as expected");
104+
}
105+
for (int i = 0; i < genericSecret.length; i++) {
106+
if (genericSecret[i] != sharedSecret[i]) {
107+
throw new Exception("Shared secrets differ");
108+
}
109+
}
110+
91111
// now, test TLS premaster secret
92112
aliceKeyAgree.init(alicePrivKey);
93113
aliceKeyAgree.doPhase(bobPubKey, true);

test/jdk/sun/security/pkcs11/tls/TestLeadingZeroesP11.java

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2013, 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
@@ -23,7 +23,7 @@
2323

2424
/*
2525
* @test
26-
* @bug 8014618
26+
* @bug 8014618 8368694
2727
* @summary Need to strip leading zeros in TlsPremasterSecret of DHKeyAgreement
2828
* @library /test/lib ..
2929
* @author Pasi Eronen
@@ -87,6 +87,26 @@ public void main(Provider p) throws Exception {
8787
throw new Exception("First byte is not zero as expected");
8888
}
8989

90+
// generate generic shared secret
91+
aliceKeyAgree.init(alicePrivKey);
92+
aliceKeyAgree.doPhase(bobPubKey, true);
93+
byte[] genericSecret =
94+
aliceKeyAgree.generateSecret("Generic").getEncoded();
95+
System.out.println("generic secret:\n" + HEX.formatHex(genericSecret));
96+
97+
// verify that leading zero is present
98+
if (genericSecret.length != 128) {
99+
throw new Exception("Unexpected generic secret length");
100+
}
101+
if (genericSecret[0] != 0) {
102+
throw new Exception("First byte is not zero as expected");
103+
}
104+
for (int i = 0; i < genericSecret.length; i++) {
105+
if (genericSecret[i] != sharedSecret[i]) {
106+
throw new Exception("Shared secrets differ");
107+
}
108+
}
109+
90110
// now, test TLS premaster secret
91111
aliceKeyAgree.init(alicePrivKey);
92112
aliceKeyAgree.doPhase(bobPubKey, true);

0 commit comments

Comments
 (0)