Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/sun/security/pkcs11/PKCS11Test.java
38840 views
1
/*
2
* Copyright (c) 2003, 2018, 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
// common infrastructure for SunPKCS11 tests
26
27
import java.io.BufferedReader;
28
import java.io.ByteArrayOutputStream;
29
import java.io.File;
30
import java.io.FileInputStream;
31
import java.io.IOException;
32
import java.io.InputStreamReader;
33
import java.io.StringReader;
34
import java.lang.reflect.Constructor;
35
import java.nio.charset.StandardCharsets;
36
import java.security.AlgorithmParameters;
37
import java.security.InvalidAlgorithmParameterException;
38
import java.security.KeyPairGenerator;
39
import java.security.NoSuchProviderException;
40
import java.security.Provider;
41
import java.security.ProviderException;
42
import java.security.Security;
43
44
import java.security.spec.ECGenParameterSpec;
45
import java.security.spec.ECParameterSpec;
46
import java.util.ArrayList;
47
import java.util.Arrays;
48
import java.util.HashMap;
49
import java.util.Iterator;
50
import java.util.List;
51
import java.util.Map;
52
import java.util.Properties;
53
import java.util.ServiceLoader;
54
import java.util.Set;
55
56
public abstract class PKCS11Test {
57
58
private boolean enableSM = false;
59
60
static final Properties props = System.getProperties();
61
62
static final String PKCS11 = "PKCS11";
63
64
// directory of the test source
65
static final String BASE = System.getProperty("test.src", ".");
66
67
static final char SEP = File.separatorChar;
68
69
private static final String DEFAULT_POLICY =
70
BASE + SEP + ".." + SEP + "policy";
71
72
// directory corresponding to BASE in the /closed hierarchy
73
static final String CLOSED_BASE;
74
75
static {
76
// hack
77
String absBase = new File(BASE).getAbsolutePath();
78
int k = absBase.indexOf(SEP + "test" + SEP + "sun" + SEP);
79
if (k < 0) k = 0;
80
String p1 = absBase.substring(0, k + 6);
81
String p2 = absBase.substring(k + 5);
82
CLOSED_BASE = p1 + "closed" + p2;
83
84
// set it as a system property to make it available in policy file
85
System.setProperty("closed.base", CLOSED_BASE);
86
}
87
88
static String NSPR_PREFIX = "";
89
90
// NSS version info
91
public static enum ECCState { None, Basic, Extended };
92
static double nss_version = -1;
93
static ECCState nss_ecc_status = ECCState.Extended;
94
95
// The NSS library we need to search for in getNSSLibDir()
96
// Default is "libsoftokn3.so", listed as "softokn3"
97
// The other is "libnss3.so", listed as "nss3".
98
static String nss_library = "softokn3";
99
100
// NSS versions of each library. It is simplier to keep nss_version
101
// for quick checking for generic testing than many if-else statements.
102
static double softoken3_version = -1;
103
static double nss3_version = -1;
104
105
static Provider getSunPKCS11(String config) throws Exception {
106
Class clazz = Class.forName("sun.security.pkcs11.SunPKCS11");
107
Constructor cons = clazz.getConstructor(new Class[] {String.class});
108
Object obj = cons.newInstance(new Object[] {config});
109
return (Provider)obj;
110
}
111
112
public abstract void main(Provider p) throws Exception;
113
114
private void premain(Provider p) throws Exception {
115
// set a security manager and policy before a test case runs,
116
// and disable them after the test case finished
117
try {
118
if (enableSM) {
119
System.setSecurityManager(new SecurityManager());
120
}
121
long start = System.currentTimeMillis();
122
System.out.printf(
123
"Running test with provider %s (security manager %s) ...%n",
124
p.getName(), enableSM ? "enabled" : "disabled");
125
main(p);
126
long stop = System.currentTimeMillis();
127
System.out.println("Completed test with provider " + p.getName() +
128
" (" + (stop - start) + " ms).");
129
} finally {
130
if (enableSM) {
131
System.setSecurityManager(null);
132
}
133
}
134
}
135
136
public static void main(PKCS11Test test) throws Exception {
137
main(test, null);
138
}
139
140
public static void main(PKCS11Test test, String[] args) throws Exception {
141
if (args != null) {
142
if (args.length > 0 && "sm".equals(args[0])) {
143
test.enableSM = true;
144
}
145
if (test.enableSM) {
146
System.setProperty("java.security.policy",
147
(args.length > 1) ? BASE + SEP + args[1]
148
: DEFAULT_POLICY);
149
}
150
}
151
152
Provider[] oldProviders = Security.getProviders();
153
try {
154
System.out.println("Beginning test run " + test.getClass().getName() + "...");
155
testDefault(test);
156
testNSS(test);
157
testDeimos(test);
158
} finally {
159
// NOTE: Do not place a 'return' in any finally block
160
// as it will suppress exceptions and hide test failures.
161
Provider[] newProviders = Security.getProviders();
162
boolean found = true;
163
// Do not restore providers if nothing changed. This is especailly
164
// useful for ./Provider/Login.sh, where a SecurityManager exists.
165
if (oldProviders.length == newProviders.length) {
166
found = false;
167
for (int i = 0; i<oldProviders.length; i++) {
168
if (oldProviders[i] != newProviders[i]) {
169
found = true;
170
break;
171
}
172
}
173
}
174
if (found) {
175
for (Provider p: newProviders) {
176
Security.removeProvider(p.getName());
177
}
178
for (Provider p: oldProviders) {
179
Security.addProvider(p);
180
}
181
}
182
}
183
}
184
185
public static void testDeimos(PKCS11Test test) throws Exception {
186
if (new File("/opt/SUNWconn/lib/libpkcs11.so").isFile() == false ||
187
"true".equals(System.getProperty("NO_DEIMOS"))) {
188
return;
189
}
190
String base = getBase();
191
String p11config = base + SEP + "nss" + SEP + "p11-deimos.txt";
192
Provider p = getSunPKCS11(p11config);
193
test.premain(p);
194
}
195
196
public static void testDefault(PKCS11Test test) throws Exception {
197
// run test for default configured PKCS11 providers (if any)
198
199
if ("true".equals(System.getProperty("NO_DEFAULT"))) {
200
return;
201
}
202
203
Provider[] providers = Security.getProviders();
204
for (int i = 0; i < providers.length; i++) {
205
Provider p = providers[i];
206
if (p.getName().startsWith("SunPKCS11-")) {
207
test.premain(p);
208
}
209
}
210
}
211
212
private static String PKCS11_BASE;
213
static {
214
try {
215
PKCS11_BASE = getBase();
216
} catch (Exception e) {
217
// ignore
218
}
219
}
220
221
private final static String PKCS11_REL_PATH = "sun/security/pkcs11";
222
223
public static String getBase() throws Exception {
224
if (PKCS11_BASE != null) {
225
return PKCS11_BASE;
226
}
227
File cwd = new File(System.getProperty("test.src", ".")).getCanonicalFile();
228
while (true) {
229
File file = new File(cwd, "TEST.ROOT");
230
if (file.isFile()) {
231
break;
232
}
233
cwd = cwd.getParentFile();
234
if (cwd == null) {
235
throw new Exception("Test root directory not found");
236
}
237
}
238
PKCS11_BASE = new File(cwd, PKCS11_REL_PATH.replace('/', SEP)).getAbsolutePath();
239
return PKCS11_BASE;
240
}
241
242
public static String getNSSLibDir() throws Exception {
243
return getNSSLibDir(nss_library);
244
}
245
246
static String getNSSLibDir(String library) throws Exception {
247
String osName = props.getProperty("os.name");
248
if (osName.startsWith("Win")) {
249
osName = "Windows";
250
NSPR_PREFIX = "lib";
251
}
252
String osid = osName + "-"
253
+ props.getProperty("os.arch") + "-" + props.getProperty("sun.arch.data.model");
254
String[] nssLibDirs = osMap.get(osid);
255
if (nssLibDirs == null) {
256
System.out.println("Unsupported OS, skipping: " + osid);
257
return null;
258
}
259
if (nssLibDirs.length == 0) {
260
System.out.println("NSS not supported on this platform, skipping test");
261
return null;
262
}
263
String nssLibDir = null;
264
for (String dir : nssLibDirs) {
265
if (new File(dir).exists() &&
266
new File(dir + System.mapLibraryName(library)).exists()) {
267
nssLibDir = dir;
268
System.setProperty("pkcs11test.nss.libdir", nssLibDir);
269
break;
270
}
271
}
272
return nssLibDir;
273
}
274
275
static boolean isBadNSSVersion(Provider p) {
276
if (isNSS(p) && badNSSVersion) {
277
System.out.println("NSS 3.11 has a DER issue that recent " +
278
"version do not.");
279
return true;
280
}
281
return false;
282
}
283
284
protected static void safeReload(String lib) throws Exception {
285
try {
286
System.load(lib);
287
} catch (UnsatisfiedLinkError e) {
288
if (e.getMessage().contains("already loaded")) {
289
return;
290
}
291
}
292
}
293
294
static boolean loadNSPR(String libdir) throws Exception {
295
// load NSS softoken dependencies in advance to avoid resolver issues
296
safeReload(libdir + System.mapLibraryName(NSPR_PREFIX + "nspr4"));
297
safeReload(libdir + System.mapLibraryName(NSPR_PREFIX + "plc4"));
298
safeReload(libdir + System.mapLibraryName(NSPR_PREFIX + "plds4"));
299
safeReload(libdir + System.mapLibraryName("sqlite3"));
300
safeReload(libdir + System.mapLibraryName("nssutil3"));
301
return true;
302
}
303
304
// Check the provider being used is NSS
305
public static boolean isNSS(Provider p) {
306
return p.getName().toUpperCase().equals("SUNPKCS11-NSS");
307
}
308
309
static double getNSSVersion() {
310
if (nss_version == -1)
311
getNSSInfo();
312
return nss_version;
313
}
314
315
static ECCState getNSSECC() {
316
if (nss_version == -1)
317
getNSSInfo();
318
return nss_ecc_status;
319
}
320
321
public static double getLibsoftokn3Version() {
322
if (softoken3_version == -1)
323
return getNSSInfo("softokn3");
324
return softoken3_version;
325
}
326
327
public static double getLibnss3Version() {
328
if (nss3_version == -1)
329
return getNSSInfo("nss3");
330
return nss3_version;
331
}
332
333
/* Read the library to find out the verison */
334
static void getNSSInfo() {
335
getNSSInfo(nss_library);
336
}
337
338
// Try to parse the version for the specified library.
339
// Assuming the library contains either of the following patterns:
340
// $Header: NSS <version>
341
// Version: NSS <version>
342
// Here, <version> stands for NSS version.
343
static double getNSSInfo(String library) {
344
// look for two types of headers in NSS libraries
345
String nssHeader1 = "$Header: NSS";
346
String nssHeader2 = "Version: NSS";
347
boolean found = false;
348
String s = null;
349
int i = 0;
350
String libfile = "";
351
352
if (library.compareTo("softokn3") == 0 && softoken3_version > -1)
353
return softoken3_version;
354
if (library.compareTo("nss3") == 0 && nss3_version > -1)
355
return nss3_version;
356
357
try {
358
String libdir = getNSSLibDir();
359
if (libdir == null) {
360
return 0.0;
361
}
362
libfile = libdir + System.mapLibraryName(library);
363
try (FileInputStream is = new FileInputStream(libfile)) {
364
byte[] data = new byte[1000];
365
int read = 0;
366
367
while (is.available() > 0) {
368
if (read == 0) {
369
read = is.read(data, 0, 1000);
370
} else {
371
// Prepend last 100 bytes in case the header was split
372
// between the reads.
373
System.arraycopy(data, 900, data, 0, 100);
374
read = 100 + is.read(data, 100, 900);
375
}
376
377
s = new String(data, 0, read, StandardCharsets.US_ASCII);
378
i = s.indexOf(nssHeader1);
379
if (i > 0 || (i = s.indexOf(nssHeader2)) > 0) {
380
found = true;
381
// If the nssHeader is before 920 we can break, otherwise
382
// we may not have the whole header so do another read. If
383
// no bytes are in the stream, that is ok, found is true.
384
if (i < 920) {
385
break;
386
}
387
}
388
}
389
}
390
} catch (Exception e) {
391
e.printStackTrace();
392
}
393
394
if (!found) {
395
System.out.println("lib" + library +
396
" version not found, set to 0.0: " + libfile);
397
nss_version = 0.0;
398
return nss_version;
399
}
400
401
// the index after whitespace after nssHeader
402
int afterheader = s.indexOf("NSS", i) + 4;
403
String version = String.valueOf(s.charAt(afterheader));
404
for (char c = s.charAt(++afterheader);
405
c == '.' || (c >= '0' && c <= '9');
406
c = s.charAt(++afterheader)) {
407
version += c;
408
}
409
410
// If a "dot dot" release, strip the extra dots for double parsing
411
String[] dot = version.split("\\.");
412
if (dot.length > 2) {
413
version = dot[0]+"."+dot[1];
414
for (int j = 2; dot.length > j; j++) {
415
version += dot[j];
416
}
417
}
418
419
// Convert to double for easier version value checking
420
try {
421
nss_version = Double.parseDouble(version);
422
} catch (NumberFormatException e) {
423
System.out.println("===== Content start =====");
424
System.out.println(s);
425
System.out.println("===== Content end =====");
426
System.out.println("Failed to parse lib" + library +
427
" version. Set to 0.0");
428
e.printStackTrace();
429
}
430
431
System.out.print("lib" + library + " version = "+version+". ");
432
433
// Check for ECC
434
if (s.indexOf("Basic") > 0) {
435
nss_ecc_status = ECCState.Basic;
436
System.out.println("ECC Basic.");
437
} else if (s.indexOf("Extended") > 0) {
438
nss_ecc_status = ECCState.Extended;
439
System.out.println("ECC Extended.");
440
} else {
441
System.out.println("ECC None.");
442
}
443
444
if (library.compareTo("softokn3") == 0) {
445
softoken3_version = nss_version;
446
} else if (library.compareTo("nss3") == 0) {
447
nss3_version = nss_version;
448
}
449
450
return nss_version;
451
}
452
453
// Used to set the nss_library file to search for libsoftokn3.so
454
public static void useNSS() {
455
nss_library = "nss3";
456
}
457
458
public static void testNSS(PKCS11Test test) throws Exception {
459
String libdir = getNSSLibDir();
460
if (libdir == null) {
461
return;
462
}
463
String base = getBase();
464
465
if (loadNSPR(libdir) == false) {
466
return;
467
}
468
469
String libfile = libdir + System.mapLibraryName(nss_library);
470
471
String customDBdir = System.getProperty("CUSTOM_DB_DIR");
472
String dbdir = (customDBdir != null) ?
473
customDBdir :
474
base + SEP + "nss" + SEP + "db";
475
// NSS always wants forward slashes for the config path
476
dbdir = dbdir.replace('\\', '/');
477
478
String customConfig = System.getProperty("CUSTOM_P11_CONFIG");
479
String customConfigName = System.getProperty("CUSTOM_P11_CONFIG_NAME", "p11-nss.txt");
480
String p11config = (customConfig != null) ?
481
customConfig :
482
base + SEP + "nss" + SEP + customConfigName;
483
484
System.setProperty("pkcs11test.nss.lib", libfile);
485
System.setProperty("pkcs11test.nss.db", dbdir);
486
Provider p = getSunPKCS11(p11config);
487
test.premain(p);
488
}
489
490
// Generate a vector of supported elliptic curves of a given provider
491
static List<ECParameterSpec> getKnownCurves(Provider p) throws Exception {
492
int index;
493
int begin;
494
int end;
495
String curve;
496
497
List<ECParameterSpec> results = new ArrayList<>();
498
// Get Curves to test from SunEC.
499
String kcProp = Security.getProvider("SunEC").
500
getProperty("AlgorithmParameters.EC SupportedCurves");
501
502
if (kcProp == null) {
503
throw new RuntimeException(
504
"\"AlgorithmParameters.EC SupportedCurves property\" not found");
505
}
506
507
System.out.println("Finding supported curves using list from SunEC\n");
508
index = 0;
509
for (;;) {
510
// Each set of curve names is enclosed with brackets.
511
begin = kcProp.indexOf('[', index);
512
end = kcProp.indexOf(']', index);
513
if (begin == -1 || end == -1) {
514
break;
515
}
516
517
/*
518
* Each name is separated by a comma.
519
* Just get the first name in the set.
520
*/
521
index = end + 1;
522
begin++;
523
end = kcProp.indexOf(',', begin);
524
if (end == -1) {
525
// Only one name in the set.
526
end = index -1;
527
}
528
529
curve = kcProp.substring(begin, end);
530
ECParameterSpec e = getECParameterSpec(p, curve);
531
System.out.print("\t "+ curve + ": ");
532
try {
533
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", p);
534
kpg.initialize(e);
535
kpg.generateKeyPair();
536
results.add(e);
537
System.out.println("Supported");
538
} catch (ProviderException ex) {
539
System.out.println("Unsupported: PKCS11: " +
540
ex.getCause().getMessage());
541
} catch (InvalidAlgorithmParameterException ex) {
542
System.out.println("Unsupported: Key Length: " +
543
ex.getMessage());
544
}
545
}
546
547
if (results.size() == 0) {
548
throw new RuntimeException("No supported EC curves found");
549
}
550
551
return results;
552
}
553
554
private static ECParameterSpec getECParameterSpec(Provider p, String name)
555
throws Exception {
556
557
AlgorithmParameters parameters =
558
AlgorithmParameters.getInstance("EC", p);
559
560
parameters.init(new ECGenParameterSpec(name));
561
562
return parameters.getParameterSpec(ECParameterSpec.class);
563
}
564
565
// Check support for a curve with a provided Vector of EC support
566
boolean checkSupport(List<ECParameterSpec> supportedEC,
567
ECParameterSpec curve) {
568
for (ECParameterSpec ec: supportedEC) {
569
if (ec.equals(curve)) {
570
return true;
571
}
572
}
573
return false;
574
}
575
576
private static final Map<String,String[]> osMap;
577
578
// Location of the NSS libraries on each supported platform
579
static {
580
osMap = new HashMap<>();
581
osMap.put("SunOS-sparc-32", new String[]{"/usr/lib/mps/"});
582
osMap.put("SunOS-sparcv9-64", new String[]{"/usr/lib/mps/64/"});
583
osMap.put("SunOS-x86-32", new String[]{"/usr/lib/mps/"});
584
osMap.put("SunOS-amd64-64", new String[]{"/usr/lib/mps/64/"});
585
osMap.put("Linux-i386-32", new String[]{
586
"/usr/lib/i386-linux-gnu/", "/usr/lib32/", "/usr/lib/"});
587
osMap.put("Linux-amd64-64", new String[]{
588
"/usr/lib/x86_64-linux-gnu/", "/usr/lib/x86_64-linux-gnu/nss/",
589
"/usr/lib64/"});
590
osMap.put("Linux-ppc64-64", new String[]{"/usr/lib64/"});
591
osMap.put("Linux-ppc64le-64", new String[]{"/usr/lib64/"});
592
osMap.put("Windows-x86-32", new String[]{
593
PKCS11_BASE + "/nss/lib/windows-i586/".replace('/', SEP)});
594
osMap.put("Windows-amd64-64", new String[]{
595
PKCS11_BASE + "/nss/lib/windows-amd64/".replace('/', SEP)});
596
osMap.put("MacOSX-x86_64-64", new String[]{
597
PKCS11_BASE + "/nss/lib/macosx-x86_64/"});
598
}
599
600
private final static char[] hexDigits = "0123456789abcdef".toCharArray();
601
602
static final boolean badNSSVersion =
603
getNSSVersion() >= 3.11 && getNSSVersion() < 3.12;
604
605
public static String toString(byte[] b) {
606
if (b == null) {
607
return "(null)";
608
}
609
StringBuilder sb = new StringBuilder(b.length * 3);
610
for (int i = 0; i < b.length; i++) {
611
int k = b[i] & 0xff;
612
if (i != 0) {
613
sb.append(':');
614
}
615
sb.append(hexDigits[k >>> 4]);
616
sb.append(hexDigits[k & 0xf]);
617
}
618
return sb.toString();
619
}
620
621
public static byte[] parse(String s) {
622
if (s.equals("(null)")) {
623
return null;
624
}
625
try {
626
int n = s.length();
627
ByteArrayOutputStream out = new ByteArrayOutputStream(n / 3);
628
StringReader r = new StringReader(s);
629
while (true) {
630
int b1 = nextNibble(r);
631
if (b1 < 0) {
632
break;
633
}
634
int b2 = nextNibble(r);
635
if (b2 < 0) {
636
throw new RuntimeException("Invalid string " + s);
637
}
638
int b = (b1 << 4) | b2;
639
out.write(b);
640
}
641
return out.toByteArray();
642
} catch (IOException e) {
643
throw new RuntimeException(e);
644
}
645
}
646
647
private static int nextNibble(StringReader r) throws IOException {
648
while (true) {
649
int ch = r.read();
650
if (ch == -1) {
651
return -1;
652
} else if ((ch >= '0') && (ch <= '9')) {
653
return ch - '0';
654
} else if ((ch >= 'a') && (ch <= 'f')) {
655
return ch - 'a' + 10;
656
} else if ((ch >= 'A') && (ch <= 'F')) {
657
return ch - 'A' + 10;
658
}
659
}
660
}
661
662
static byte[] generateData(int length) {
663
byte data[] = new byte[length];
664
for (int i=0; i<data.length; i++) {
665
data[i] = (byte) (i % 256);
666
}
667
return data;
668
}
669
670
<T> T[] concat(T[] a, T[] b) {
671
if ((b == null) || (b.length == 0)) {
672
return a;
673
}
674
T[] r = (T[])java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), a.length + b.length);
675
System.arraycopy(a, 0, r, 0, a.length);
676
System.arraycopy(b, 0, r, a.length, b.length);
677
return r;
678
}
679
680
/**
681
* Returns supported algorithms of specified type.
682
*/
683
static List<String> getSupportedAlgorithms(String type, String alg,
684
Provider p) {
685
// prepare a list of supported algorithms
686
List<String> algorithms = new ArrayList<>();
687
Set<Provider.Service> services = p.getServices();
688
for (Provider.Service service : services) {
689
if (service.getType().equals(type)
690
&& service.getAlgorithm().startsWith(alg)) {
691
algorithms.add(service.getAlgorithm());
692
}
693
}
694
return algorithms;
695
}
696
697
}
698
699