Skip to content

Commit 85e5a5c

Browse files
committed
8335288: SunPKCS11 initialization will call C_GetMechanismInfo on unsupported mechanisms
Reviewed-by: mdoerr Backport-of: fdfe503d016086cf78b5a8c27dbe45f0261c68ab
1 parent bf86b34 commit 85e5a5c

File tree

3 files changed

+150
-12
lines changed

3 files changed

+150
-12
lines changed

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

+20-12
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727

2828
import java.io.*;
2929
import java.util.*;
30-
30+
import java.util.stream.Collectors;
3131
import java.security.*;
3232
import java.security.interfaces.*;
3333

@@ -1235,7 +1235,11 @@ private void initToken(CK_SLOT_INFO slotInfo) throws PKCS11Exception {
12351235
("Token info for token in slot " + slotID + ":");
12361236
System.out.println(token.tokenInfo);
12371237
}
1238+
12381239
long[] supportedMechanisms = p11.C_GetMechanismList(slotID);
1240+
Set<Long> supportedMechSet =
1241+
Arrays.stream(supportedMechanisms).boxed().collect
1242+
(Collectors.toCollection(HashSet::new));
12391243

12401244
// Create a map from the various Descriptors to the "most
12411245
// preferred" mechanism that was defined during the
@@ -1244,10 +1248,9 @@ private void initToken(CK_SLOT_INFO slotInfo) throws PKCS11Exception {
12441248
// the earliest entry. When asked for "DES/CBC/PKCS5Padding", we
12451249
// return a CKM_DES_CBC_PAD.
12461250
final Map<Descriptor,Integer> supportedAlgs =
1247-
new HashMap<Descriptor,Integer>();
1251+
new HashMap<Descriptor,Integer>();
12481252

1249-
for (int i = 0; i < supportedMechanisms.length; i++) {
1250-
long longMech = supportedMechanisms[i];
1253+
for (long longMech : supportedMechanisms) {
12511254
CK_MECHANISM_INFO mechInfo = token.getMechanismInfo(longMech);
12521255
if (showInfo) {
12531256
System.out.println("Mechanism " +
@@ -1281,13 +1284,19 @@ private void initToken(CK_SLOT_INFO slotInfo) throws PKCS11Exception {
12811284
for (Descriptor d : ds) {
12821285
Integer oldMech = supportedAlgs.get(d);
12831286
if (oldMech == null) {
1287+
// check all required mechs are supported
12841288
if (d.requiredMechs != null) {
1285-
// Check that other mechanisms required for the
1286-
// service are supported before listing it as
1287-
// available for the first time.
1288-
for (int requiredMech : d.requiredMechs) {
1289-
if (token.getMechanismInfo(
1290-
requiredMech & 0xFFFFFFFFL) == null) {
1289+
for (int reqMech : d.requiredMechs) {
1290+
long longReqMech = reqMech & 0xFFFFFFFFL;
1291+
if (!config.isEnabled(longReqMech) ||
1292+
!supportedMechSet.contains(longReqMech) /*||
1293+
brokenMechanisms.contains(longReqMech)*/) {
1294+
if (showInfo) {
1295+
System.out.println("DISABLED " + d.type +
1296+
" " + d.algorithm +
1297+
" due to no support for req'd mech " +
1298+
Functions.getMechanismName(longReqMech));
1299+
}
12911300
continue descLoop;
12921301
}
12931302
}
@@ -1300,7 +1309,7 @@ private void initToken(CK_SLOT_INFO slotInfo) throws PKCS11Exception {
13001309
(d.type == SIG &&
13011310
(mechInfo.flags & CKF_SIGN) == 0)) {
13021311
if (showInfo) {
1303-
System.out.println("DISABLED " + d.type +
1312+
System.out.println("DISABLED " + d.type +
13041313
" " + d.algorithm +
13051314
" due to partial support");
13061315
}
@@ -1324,7 +1333,6 @@ private void initToken(CK_SLOT_INFO slotInfo) throws PKCS11Exception {
13241333
}
13251334
}
13261335
}
1327-
13281336
}
13291337

13301338
// register algorithms in provider
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
name = NSS
2+
3+
showInfo = true
4+
5+
slot = 1
6+
7+
library = ${pkcs11test.nss.lib}
8+
9+
disabledMechanisms = {
10+
CKM_SHA224_HMAC
11+
CKM_SHA256_HMAC
12+
}
13+
14+
nssArgs = "configdir='${pkcs11test.nss.db}' certPrefix='' keyPrefix=''"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/*
2+
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/*
25+
* @test
26+
* @bug 8335288
27+
* @library /test/lib ..
28+
* @modules jdk.crypto.cryptoki
29+
* @summary check that if any required mech is unavailable, then the
30+
* mechanism will be unavailable as well.
31+
* @run testng/othervm RequiredMechCheck
32+
*/
33+
import java.nio.file.Path;
34+
import java.security.Provider;
35+
import java.security.NoSuchAlgorithmException;
36+
import javax.crypto.Cipher;
37+
import javax.crypto.Mac;
38+
import javax.crypto.SecretKeyFactory;
39+
40+
import jtreg.SkippedException;
41+
import org.testng.SkipException;
42+
import org.testng.annotations.BeforeClass;
43+
import org.testng.annotations.Test;
44+
45+
public class RequiredMechCheck extends PKCS11Test {
46+
47+
private static record TestData(String serviceType, String algo,
48+
boolean disabled) {}
49+
50+
private static TestData[] testValues = {
51+
new TestData("MAC", "HmacPBESHA1", false),
52+
new TestData("MAC", "HmacPBESHA224", true),
53+
new TestData("MAC", "HmacPBESHA256", true),
54+
new TestData("MAC", "HmacPBESHA384", false),
55+
new TestData("MAC", "HmacPBESHA512", false),
56+
new TestData("SKF", "PBEWithHmacSHA1AndAES_128", false),
57+
new TestData("SKF", "PBEWithHmacSHA224AndAES_128", true),
58+
new TestData("SKF", "PBEWithHmacSHA256AndAES_128", true),
59+
new TestData("SKF", "PBEWithHmacSHA384AndAES_128", false),
60+
new TestData("SKF", "PBEWithHmacSHA512AndAES_128", false),
61+
new TestData("CIP", "PBEWithHmacSHA1AndAES_128", false),
62+
new TestData("CIP", "PBEWithHmacSHA224AndAES_128", true),
63+
new TestData("CIP", "PBEWithHmacSHA256AndAES_128", true),
64+
new TestData("CIP", "PBEWithHmacSHA384AndAES_128", false),
65+
new TestData("CIP", "PBEWithHmacSHA512AndAES_128", false),
66+
};
67+
68+
@BeforeClass
69+
public void setUp() throws Exception {
70+
Path configPath = Path.of(BASE).resolve("RequiredMechCheck.cfg");
71+
System.setProperty("CUSTOM_P11_CONFIG", configPath.toString());
72+
}
73+
74+
@Test
75+
public void test() throws Exception {
76+
try {
77+
main(new RequiredMechCheck());
78+
} catch (SkippedException se) {
79+
throw new SkipException("One or more tests are skipped");
80+
}
81+
}
82+
83+
public void main(Provider p) throws Exception {
84+
for (TestData td : testValues) {
85+
String desc = td.serviceType + " " + td.algo;
86+
Object t;
87+
try {
88+
switch (td.serviceType) {
89+
case "MAC":
90+
t = Mac.getInstance(td.algo, p);
91+
break;
92+
case "SKF":
93+
t = SecretKeyFactory.getInstance(td.algo, p);
94+
break;
95+
case "CIP":
96+
t = Cipher.getInstance(td.algo, p);
97+
break;
98+
default:
99+
throw new RuntimeException("Unsupported Test Type!");
100+
}
101+
102+
if (td.disabled) {
103+
throw new RuntimeException("Fail, no NSAE for " + desc);
104+
} else {
105+
System.out.println("Ok, getInstance() works for " + desc);
106+
}
107+
} catch (NoSuchAlgorithmException e) {
108+
if (td.disabled) {
109+
System.out.println("Ok, NSAE thrown for " + desc);
110+
} else {
111+
throw new RuntimeException("Unexpected Ex for " + desc, e);
112+
}
113+
}
114+
}
115+
}
116+
}

0 commit comments

Comments
 (0)