Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/pkcs11/Config.java
38919 views
1
/*
2
* Copyright (c) 2003, 2017, 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. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package sun.security.pkcs11;
27
28
import java.io.*;
29
import static java.io.StreamTokenizer.*;
30
import java.math.BigInteger;
31
import java.nio.charset.StandardCharsets;
32
import java.util.*;
33
34
import java.security.*;
35
36
import sun.security.action.GetPropertyAction;
37
import sun.security.util.PropertyExpander;
38
39
import sun.security.pkcs11.wrapper.*;
40
import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
41
import static sun.security.pkcs11.wrapper.CK_ATTRIBUTE.*;
42
43
import static sun.security.pkcs11.TemplateManager.*;
44
45
/**
46
* Configuration container and file parsing.
47
*
48
* @author Andreas Sterbenz
49
* @since 1.5
50
*/
51
final class Config {
52
53
static final int ERR_HALT = 1;
54
static final int ERR_IGNORE_ALL = 2;
55
static final int ERR_IGNORE_LIB = 3;
56
57
// same as allowSingleThreadedModules but controlled via a system property
58
// and applied to all providers. if set to false, no SunPKCS11 instances
59
// will accept single threaded modules regardless of the setting in their
60
// config files.
61
private static final boolean staticAllowSingleThreadedModules;
62
63
static {
64
String p = "sun.security.pkcs11.allowSingleThreadedModules";
65
String s = AccessController.doPrivileged(new GetPropertyAction(p));
66
if ("false".equalsIgnoreCase(s)) {
67
staticAllowSingleThreadedModules = false;
68
} else {
69
staticAllowSingleThreadedModules = true;
70
}
71
}
72
73
// temporary storage for configurations
74
// needed because the SunPKCS11 needs to call the superclass constructor
75
// in provider before accessing any instance variables
76
private final static Map<String,Config> configMap =
77
new HashMap<String,Config>();
78
79
static Config getConfig(final String name, final InputStream stream) {
80
Config config = configMap.get(name);
81
if (config != null) {
82
return config;
83
}
84
try {
85
config = new Config(name, stream);
86
configMap.put(name, config);
87
return config;
88
} catch (Exception e) {
89
throw new ProviderException("Error parsing configuration", e);
90
}
91
}
92
93
static Config removeConfig(String name) {
94
return configMap.remove(name);
95
}
96
97
private final static boolean DEBUG = false;
98
99
private static void debug(Object o) {
100
if (DEBUG) {
101
System.out.println(o);
102
}
103
}
104
105
// Reader and StringTokenizer used during parsing
106
private Reader reader;
107
108
private StreamTokenizer st;
109
110
private Set<String> parsedKeywords;
111
112
// name suffix of the provider
113
private String name;
114
115
// name of the PKCS#11 library
116
private String library;
117
118
// description to pass to the provider class
119
private String description;
120
121
// slotID of the slot to use
122
private int slotID = -1;
123
124
// slot to use, specified as index in the slotlist
125
private int slotListIndex = -1;
126
127
// set of enabled mechanisms (or null to use default)
128
private Set<Long> enabledMechanisms;
129
130
// set of disabled mechanisms
131
private Set<Long> disabledMechanisms;
132
133
// whether to print debug info during startup
134
private boolean showInfo = false;
135
136
// template manager, initialized from parsed attributes
137
private TemplateManager templateManager;
138
139
// how to handle error during startup, one of ERR_
140
private int handleStartupErrors = ERR_HALT;
141
142
// flag indicating whether the P11KeyStore should
143
// be more tolerant of input parameters
144
private boolean keyStoreCompatibilityMode = true;
145
146
// flag indicating whether we need to explicitly cancel operations
147
// see Token
148
private boolean explicitCancel = true;
149
150
// how often to test for token insertion, if no token is present
151
private int insertionCheckInterval = 2000;
152
153
// flag inidicating whether to omit the call to C_Initialize()
154
// should be used only if we are running within a process that
155
// has already called it (e.g. Plugin inside of Mozilla/NSS)
156
private boolean omitInitialize = false;
157
158
// whether to allow modules that only support single threaded access.
159
// they cannot be used safely from multiple PKCS#11 consumers in the
160
// same process, for example NSS and SunPKCS11
161
private boolean allowSingleThreadedModules = true;
162
163
// name of the C function that returns the PKCS#11 functionlist
164
// This option primarily exists for the deprecated
165
// Secmod.Module.getProvider() method.
166
private String functionList = "C_GetFunctionList";
167
168
// whether to use NSS secmod mode. Implicitly set if nssLibraryDirectory,
169
// nssSecmodDirectory, or nssModule is specified.
170
private boolean nssUseSecmod;
171
172
// location of the NSS library files (libnss3.so, etc.)
173
private String nssLibraryDirectory;
174
175
// location of secmod.db
176
private String nssSecmodDirectory;
177
178
// which NSS module to use
179
private String nssModule;
180
181
private Secmod.DbMode nssDbMode = Secmod.DbMode.READ_WRITE;
182
183
// Whether the P11KeyStore should specify the CKA_NETSCAPE_DB attribute
184
// when creating private keys. Only valid if nssUseSecmod is true.
185
private boolean nssNetscapeDbWorkaround = true;
186
187
// Special init argument string for the NSS softtoken.
188
// This is used when using the NSS softtoken directly without secmod mode.
189
private String nssArgs;
190
191
// whether to use NSS trust attributes for the KeyStore of this provider
192
// this option is for internal use by the SunPKCS11 code only and
193
// works only for NSS providers created via the Secmod API
194
private boolean nssUseSecmodTrust = false;
195
196
// Flag to indicate whether the X9.63 encoding for EC points shall be used
197
// (true) or whether that encoding shall be wrapped in an ASN.1 OctetString
198
// (false).
199
private boolean useEcX963Encoding = false;
200
201
// Flag to indicate whether NSS should favour performance (false) or
202
// memory footprint (true).
203
private boolean nssOptimizeSpace = false;
204
205
private Config(String filename, InputStream in) throws IOException {
206
if (in == null) {
207
if (filename.startsWith("--")) {
208
// inline config
209
String config = filename.substring(2).replace("\\n", "\n");
210
reader = new StringReader(config);
211
} else {
212
in = new FileInputStream(expand(filename));
213
}
214
}
215
if (reader == null) {
216
reader = new BufferedReader(new InputStreamReader(in,
217
StandardCharsets.ISO_8859_1));
218
}
219
parsedKeywords = new HashSet<String>();
220
st = new StreamTokenizer(reader);
221
setupTokenizer();
222
parse();
223
}
224
225
String getName() {
226
return name;
227
}
228
229
String getLibrary() {
230
return library;
231
}
232
233
String getDescription() {
234
if (description != null) {
235
return description;
236
}
237
return "SunPKCS11-" + name + " using library " + library;
238
}
239
240
int getSlotID() {
241
return slotID;
242
}
243
244
int getSlotListIndex() {
245
if ((slotID == -1) && (slotListIndex == -1)) {
246
// if neither is set, default to first slot
247
return 0;
248
} else {
249
return slotListIndex;
250
}
251
}
252
253
boolean getShowInfo() {
254
return (SunPKCS11.debug != null) || showInfo;
255
}
256
257
TemplateManager getTemplateManager() {
258
if (templateManager == null) {
259
templateManager = new TemplateManager();
260
}
261
return templateManager;
262
}
263
264
boolean isEnabled(long m) {
265
if (enabledMechanisms != null) {
266
return enabledMechanisms.contains(Long.valueOf(m));
267
}
268
if (disabledMechanisms != null) {
269
return !disabledMechanisms.contains(Long.valueOf(m));
270
}
271
return true;
272
}
273
274
int getHandleStartupErrors() {
275
return handleStartupErrors;
276
}
277
278
boolean getKeyStoreCompatibilityMode() {
279
return keyStoreCompatibilityMode;
280
}
281
282
boolean getExplicitCancel() {
283
return explicitCancel;
284
}
285
286
int getInsertionCheckInterval() {
287
return insertionCheckInterval;
288
}
289
290
boolean getOmitInitialize() {
291
return omitInitialize;
292
}
293
294
boolean getAllowSingleThreadedModules() {
295
return staticAllowSingleThreadedModules && allowSingleThreadedModules;
296
}
297
298
String getFunctionList() {
299
return functionList;
300
}
301
302
boolean getNssUseSecmod() {
303
return nssUseSecmod;
304
}
305
306
String getNssLibraryDirectory() {
307
return nssLibraryDirectory;
308
}
309
310
String getNssSecmodDirectory() {
311
return nssSecmodDirectory;
312
}
313
314
String getNssModule() {
315
return nssModule;
316
}
317
318
Secmod.DbMode getNssDbMode() {
319
return nssDbMode;
320
}
321
322
public boolean getNssNetscapeDbWorkaround() {
323
return nssUseSecmod && nssNetscapeDbWorkaround;
324
}
325
326
String getNssArgs() {
327
return nssArgs;
328
}
329
330
boolean getNssUseSecmodTrust() {
331
return nssUseSecmodTrust;
332
}
333
334
boolean getUseEcX963Encoding() {
335
return useEcX963Encoding;
336
}
337
338
boolean getNssOptimizeSpace() {
339
return nssOptimizeSpace;
340
}
341
342
private static String expand(final String s) throws IOException {
343
try {
344
return PropertyExpander.expand(s);
345
} catch (Exception e) {
346
throw new RuntimeException(e.getMessage());
347
}
348
}
349
350
private void setupTokenizer() {
351
st.resetSyntax();
352
st.wordChars('a', 'z');
353
st.wordChars('A', 'Z');
354
st.wordChars('0', '9');
355
st.wordChars(':', ':');
356
st.wordChars('.', '.');
357
st.wordChars('_', '_');
358
st.wordChars('-', '-');
359
st.wordChars('/', '/');
360
st.wordChars('\\', '\\');
361
st.wordChars('$', '$');
362
st.wordChars('{', '{'); // need {} for property subst
363
st.wordChars('}', '}');
364
st.wordChars('*', '*');
365
st.wordChars('+', '+');
366
st.wordChars('~', '~');
367
// XXX check ASCII table and add all other characters except special
368
369
// special: #="(),
370
st.whitespaceChars(0, ' ');
371
st.commentChar('#');
372
st.eolIsSignificant(true);
373
st.quoteChar('\"');
374
}
375
376
private ConfigurationException excToken(String msg) {
377
return new ConfigurationException(msg + " " + st);
378
}
379
380
private ConfigurationException excLine(String msg) {
381
return new ConfigurationException(msg + ", line " + st.lineno());
382
}
383
384
private void parse() throws IOException {
385
while (true) {
386
int token = nextToken();
387
if (token == TT_EOF) {
388
break;
389
}
390
if (token == TT_EOL) {
391
continue;
392
}
393
if (token != TT_WORD) {
394
throw excToken("Unexpected token:");
395
}
396
String word = st.sval;
397
if (word.equals("name")) {
398
name = parseStringEntry(word);
399
} else if (word.equals("library")) {
400
library = parseLibrary(word);
401
} else if (word.equals("description")) {
402
parseDescription(word);
403
} else if (word.equals("slot")) {
404
parseSlotID(word);
405
} else if (word.equals("slotListIndex")) {
406
parseSlotListIndex(word);
407
} else if (word.equals("enabledMechanisms")) {
408
parseEnabledMechanisms(word);
409
} else if (word.equals("disabledMechanisms")) {
410
parseDisabledMechanisms(word);
411
} else if (word.equals("attributes")) {
412
parseAttributes(word);
413
} else if (word.equals("handleStartupErrors")) {
414
parseHandleStartupErrors(word);
415
} else if (word.endsWith("insertionCheckInterval")) {
416
insertionCheckInterval = parseIntegerEntry(word);
417
if (insertionCheckInterval < 100) {
418
throw excLine(word + " must be at least 100 ms");
419
}
420
} else if (word.equals("showInfo")) {
421
showInfo = parseBooleanEntry(word);
422
} else if (word.equals("keyStoreCompatibilityMode")) {
423
keyStoreCompatibilityMode = parseBooleanEntry(word);
424
} else if (word.equals("explicitCancel")) {
425
explicitCancel = parseBooleanEntry(word);
426
} else if (word.equals("omitInitialize")) {
427
omitInitialize = parseBooleanEntry(word);
428
} else if (word.equals("allowSingleThreadedModules")) {
429
allowSingleThreadedModules = parseBooleanEntry(word);
430
} else if (word.equals("functionList")) {
431
functionList = parseStringEntry(word);
432
} else if (word.equals("nssUseSecmod")) {
433
nssUseSecmod = parseBooleanEntry(word);
434
} else if (word.equals("nssLibraryDirectory")) {
435
nssLibraryDirectory = parseLibrary(word);
436
nssUseSecmod = true;
437
} else if (word.equals("nssSecmodDirectory")) {
438
nssSecmodDirectory = expand(parseStringEntry(word));
439
nssUseSecmod = true;
440
} else if (word.equals("nssModule")) {
441
nssModule = parseStringEntry(word);
442
nssUseSecmod = true;
443
} else if (word.equals("nssDbMode")) {
444
String mode = parseStringEntry(word);
445
if (mode.equals("readWrite")) {
446
nssDbMode = Secmod.DbMode.READ_WRITE;
447
} else if (mode.equals("readOnly")) {
448
nssDbMode = Secmod.DbMode.READ_ONLY;
449
} else if (mode.equals("noDb")) {
450
nssDbMode = Secmod.DbMode.NO_DB;
451
} else {
452
throw excToken("nssDbMode must be one of readWrite, readOnly, and noDb:");
453
}
454
nssUseSecmod = true;
455
} else if (word.equals("nssNetscapeDbWorkaround")) {
456
nssNetscapeDbWorkaround = parseBooleanEntry(word);
457
nssUseSecmod = true;
458
} else if (word.equals("nssArgs")) {
459
parseNSSArgs(word);
460
} else if (word.equals("nssUseSecmodTrust")) {
461
nssUseSecmodTrust = parseBooleanEntry(word);
462
} else if (word.equals("useEcX963Encoding")) {
463
useEcX963Encoding = parseBooleanEntry(word);
464
} else if (word.equals("nssOptimizeSpace")) {
465
nssOptimizeSpace = parseBooleanEntry(word);
466
} else {
467
throw new ConfigurationException
468
("Unknown keyword '" + word + "', line " + st.lineno());
469
}
470
parsedKeywords.add(word);
471
}
472
reader.close();
473
reader = null;
474
st = null;
475
parsedKeywords = null;
476
if (name == null) {
477
throw new ConfigurationException("name must be specified");
478
}
479
if (nssUseSecmod == false) {
480
if (library == null) {
481
throw new ConfigurationException("library must be specified");
482
}
483
} else {
484
if (library != null) {
485
throw new ConfigurationException
486
("library must not be specified in NSS mode");
487
}
488
if ((slotID != -1) || (slotListIndex != -1)) {
489
throw new ConfigurationException
490
("slot and slotListIndex must not be specified in NSS mode");
491
}
492
if (nssArgs != null) {
493
throw new ConfigurationException
494
("nssArgs must not be specified in NSS mode");
495
}
496
if (nssUseSecmodTrust != false) {
497
throw new ConfigurationException("nssUseSecmodTrust is an "
498
+ "internal option and must not be specified in NSS mode");
499
}
500
}
501
}
502
503
//
504
// Parsing helper methods
505
//
506
507
private int nextToken() throws IOException {
508
int token = st.nextToken();
509
debug(st);
510
return token;
511
}
512
513
private void parseEquals() throws IOException {
514
int token = nextToken();
515
if (token != '=') {
516
throw excToken("Expected '=', read");
517
}
518
}
519
520
private void parseOpenBraces() throws IOException {
521
while (true) {
522
int token = nextToken();
523
if (token == TT_EOL) {
524
continue;
525
}
526
if ((token == TT_WORD) && st.sval.equals("{")) {
527
return;
528
}
529
throw excToken("Expected '{', read");
530
}
531
}
532
533
private boolean isCloseBraces(int token) {
534
return (token == TT_WORD) && st.sval.equals("}");
535
}
536
537
private String parseWord() throws IOException {
538
int token = nextToken();
539
if (token != TT_WORD) {
540
throw excToken("Unexpected value:");
541
}
542
return st.sval;
543
}
544
545
private String parseStringEntry(String keyword) throws IOException {
546
checkDup(keyword);
547
parseEquals();
548
549
int token = nextToken();
550
if (token != TT_WORD && token != '\"') {
551
// not a word token nor a string enclosed by double quotes
552
throw excToken("Unexpected value:");
553
}
554
String value = st.sval;
555
556
debug(keyword + ": " + value);
557
return value;
558
}
559
560
private boolean parseBooleanEntry(String keyword) throws IOException {
561
checkDup(keyword);
562
parseEquals();
563
boolean value = parseBoolean();
564
debug(keyword + ": " + value);
565
return value;
566
}
567
568
private int parseIntegerEntry(String keyword) throws IOException {
569
checkDup(keyword);
570
parseEquals();
571
int value = decodeNumber(parseWord());
572
debug(keyword + ": " + value);
573
return value;
574
}
575
576
private boolean parseBoolean() throws IOException {
577
String val = parseWord();
578
switch (val) {
579
case "true":
580
return true;
581
case "false":
582
return false;
583
default:
584
throw excToken("Expected boolean value, read:");
585
}
586
}
587
588
private String parseLine() throws IOException {
589
// allow quoted string as part of line
590
String s = null;
591
while (true) {
592
int token = nextToken();
593
if ((token == TT_EOL) || (token == TT_EOF)) {
594
break;
595
}
596
if (token != TT_WORD && token != '\"') {
597
throw excToken("Unexpected value");
598
}
599
if (s == null) {
600
s = st.sval;
601
} else {
602
s = s + " " + st.sval;
603
}
604
}
605
if (s == null) {
606
throw excToken("Unexpected empty line");
607
}
608
return s;
609
}
610
611
private int decodeNumber(String str) throws IOException {
612
try {
613
if (str.startsWith("0x") || str.startsWith("0X")) {
614
return Integer.parseInt(str.substring(2), 16);
615
} else {
616
return Integer.parseInt(str);
617
}
618
} catch (NumberFormatException e) {
619
throw excToken("Expected number, read");
620
}
621
}
622
623
private static boolean isNumber(String s) {
624
if (s.length() == 0) {
625
return false;
626
}
627
char ch = s.charAt(0);
628
return ((ch >= '0') && (ch <= '9'));
629
}
630
631
private void parseComma() throws IOException {
632
int token = nextToken();
633
if (token != ',') {
634
throw excToken("Expected ',', read");
635
}
636
}
637
638
private static boolean isByteArray(String val) {
639
return val.startsWith("0h");
640
}
641
642
private byte[] decodeByteArray(String str) throws IOException {
643
if (str.startsWith("0h") == false) {
644
throw excToken("Expected byte array value, read");
645
}
646
str = str.substring(2);
647
// XXX proper hex parsing
648
try {
649
return new BigInteger(str, 16).toByteArray();
650
} catch (NumberFormatException e) {
651
throw excToken("Expected byte array value, read");
652
}
653
}
654
655
private void checkDup(String keyword) throws IOException {
656
if (parsedKeywords.contains(keyword)) {
657
throw excLine(keyword + " must only be specified once");
658
}
659
}
660
661
//
662
// individual entry parsing methods
663
//
664
665
private String parseLibrary(String keyword) throws IOException {
666
checkDup(keyword);
667
parseEquals();
668
String lib = parseLine();
669
lib = expand(lib);
670
int i = lib.indexOf("/$ISA/");
671
if (i != -1) {
672
// replace "/$ISA/" with "/sparcv9/" on 64-bit Solaris SPARC
673
// and with "/amd64/" on Solaris AMD64.
674
// On all other platforms, just turn it into a "/"
675
String osName = System.getProperty("os.name", "");
676
String osArch = System.getProperty("os.arch", "");
677
String prefix = lib.substring(0, i);
678
String suffix = lib.substring(i + 5);
679
if (osName.equals("SunOS") && osArch.equals("sparcv9")) {
680
lib = prefix + "/sparcv9" + suffix;
681
} else if (osName.equals("SunOS") && osArch.equals("amd64")) {
682
lib = prefix + "/amd64" + suffix;
683
} else {
684
lib = prefix + suffix;
685
}
686
}
687
debug(keyword + ": " + lib);
688
689
// Check to see if full path is specified to prevent the DLL
690
// preloading attack
691
if (!(new File(lib)).isAbsolute()) {
692
throw new ConfigurationException(
693
"Absolute path required for library value: " + lib);
694
}
695
return lib;
696
}
697
698
private void parseDescription(String keyword) throws IOException {
699
checkDup(keyword);
700
parseEquals();
701
description = parseLine();
702
debug("description: " + description);
703
}
704
705
private void parseSlotID(String keyword) throws IOException {
706
if (slotID >= 0) {
707
throw excLine("Duplicate slot definition");
708
}
709
if (slotListIndex >= 0) {
710
throw excLine
711
("Only one of slot and slotListIndex must be specified");
712
}
713
parseEquals();
714
String slotString = parseWord();
715
slotID = decodeNumber(slotString);
716
debug("slot: " + slotID);
717
}
718
719
private void parseSlotListIndex(String keyword) throws IOException {
720
if (slotListIndex >= 0) {
721
throw excLine("Duplicate slotListIndex definition");
722
}
723
if (slotID >= 0) {
724
throw excLine
725
("Only one of slot and slotListIndex must be specified");
726
}
727
parseEquals();
728
String slotString = parseWord();
729
slotListIndex = decodeNumber(slotString);
730
debug("slotListIndex: " + slotListIndex);
731
}
732
733
private void parseEnabledMechanisms(String keyword) throws IOException {
734
enabledMechanisms = parseMechanisms(keyword);
735
}
736
737
private void parseDisabledMechanisms(String keyword) throws IOException {
738
disabledMechanisms = parseMechanisms(keyword);
739
}
740
741
private Set<Long> parseMechanisms(String keyword) throws IOException {
742
checkDup(keyword);
743
Set<Long> mechs = new HashSet<Long>();
744
parseEquals();
745
parseOpenBraces();
746
while (true) {
747
int token = nextToken();
748
if (isCloseBraces(token)) {
749
break;
750
}
751
if (token == TT_EOL) {
752
continue;
753
}
754
if (token != TT_WORD) {
755
throw excToken("Expected mechanism, read");
756
}
757
long mech = parseMechanism(st.sval);
758
mechs.add(Long.valueOf(mech));
759
}
760
if (DEBUG) {
761
System.out.print("mechanisms: [");
762
for (Long mech : mechs) {
763
System.out.print(Functions.getMechanismName(mech));
764
System.out.print(", ");
765
}
766
System.out.println("]");
767
}
768
return mechs;
769
}
770
771
private long parseMechanism(String mech) throws IOException {
772
if (isNumber(mech)) {
773
return decodeNumber(mech);
774
} else {
775
try {
776
return Functions.getMechanismId(mech);
777
} catch (IllegalArgumentException e) {
778
throw excLine("Unknown mechanism: " + mech);
779
}
780
}
781
}
782
783
private void parseAttributes(String keyword) throws IOException {
784
if (templateManager == null) {
785
templateManager = new TemplateManager();
786
}
787
int token = nextToken();
788
if (token == '=') {
789
String s = parseWord();
790
if (s.equals("compatibility") == false) {
791
throw excLine("Expected 'compatibility', read " + s);
792
}
793
setCompatibilityAttributes();
794
return;
795
}
796
if (token != '(') {
797
throw excToken("Expected '(' or '=', read");
798
}
799
String op = parseOperation();
800
parseComma();
801
long objectClass = parseObjectClass();
802
parseComma();
803
long keyAlg = parseKeyAlgorithm();
804
token = nextToken();
805
if (token != ')') {
806
throw excToken("Expected ')', read");
807
}
808
parseEquals();
809
parseOpenBraces();
810
List<CK_ATTRIBUTE> attributes = new ArrayList<CK_ATTRIBUTE>();
811
while (true) {
812
token = nextToken();
813
if (isCloseBraces(token)) {
814
break;
815
}
816
if (token == TT_EOL) {
817
continue;
818
}
819
if (token != TT_WORD) {
820
throw excToken("Expected mechanism, read");
821
}
822
String attributeName = st.sval;
823
long attributeId = decodeAttributeName(attributeName);
824
parseEquals();
825
String attributeValue = parseWord();
826
attributes.add(decodeAttributeValue(attributeId, attributeValue));
827
}
828
templateManager.addTemplate
829
(op, objectClass, keyAlg, attributes.toArray(CK_A0));
830
}
831
832
private void setCompatibilityAttributes() {
833
// all secret keys
834
templateManager.addTemplate(O_ANY, CKO_SECRET_KEY, PCKK_ANY,
835
new CK_ATTRIBUTE[] {
836
TOKEN_FALSE,
837
SENSITIVE_FALSE,
838
EXTRACTABLE_TRUE,
839
ENCRYPT_TRUE,
840
DECRYPT_TRUE,
841
WRAP_TRUE,
842
UNWRAP_TRUE,
843
});
844
845
// generic secret keys are special
846
// They are used as MAC keys plus for the SSL/TLS (pre)master secrets
847
templateManager.addTemplate(O_ANY, CKO_SECRET_KEY, CKK_GENERIC_SECRET,
848
new CK_ATTRIBUTE[] {
849
SIGN_TRUE,
850
VERIFY_TRUE,
851
ENCRYPT_NULL,
852
DECRYPT_NULL,
853
WRAP_NULL,
854
UNWRAP_NULL,
855
DERIVE_TRUE,
856
});
857
858
// all private and public keys
859
templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, PCKK_ANY,
860
new CK_ATTRIBUTE[] {
861
TOKEN_FALSE,
862
SENSITIVE_FALSE,
863
EXTRACTABLE_TRUE,
864
});
865
templateManager.addTemplate(O_ANY, CKO_PUBLIC_KEY, PCKK_ANY,
866
new CK_ATTRIBUTE[] {
867
TOKEN_FALSE,
868
});
869
870
// additional attributes for RSA private keys
871
templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, CKK_RSA,
872
new CK_ATTRIBUTE[] {
873
DECRYPT_TRUE,
874
SIGN_TRUE,
875
SIGN_RECOVER_TRUE,
876
UNWRAP_TRUE,
877
});
878
// additional attributes for RSA public keys
879
templateManager.addTemplate(O_ANY, CKO_PUBLIC_KEY, CKK_RSA,
880
new CK_ATTRIBUTE[] {
881
ENCRYPT_TRUE,
882
VERIFY_TRUE,
883
VERIFY_RECOVER_TRUE,
884
WRAP_TRUE,
885
});
886
887
// additional attributes for DSA private keys
888
templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, CKK_DSA,
889
new CK_ATTRIBUTE[] {
890
SIGN_TRUE,
891
});
892
// additional attributes for DSA public keys
893
templateManager.addTemplate(O_ANY, CKO_PUBLIC_KEY, CKK_DSA,
894
new CK_ATTRIBUTE[] {
895
VERIFY_TRUE,
896
});
897
898
// additional attributes for DH private keys
899
templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, CKK_DH,
900
new CK_ATTRIBUTE[] {
901
DERIVE_TRUE,
902
});
903
904
// additional attributes for EC private keys
905
templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, CKK_EC,
906
new CK_ATTRIBUTE[] {
907
SIGN_TRUE,
908
DERIVE_TRUE,
909
});
910
// additional attributes for EC public keys
911
templateManager.addTemplate(O_ANY, CKO_PUBLIC_KEY, CKK_EC,
912
new CK_ATTRIBUTE[] {
913
VERIFY_TRUE,
914
});
915
}
916
917
private final static CK_ATTRIBUTE[] CK_A0 = new CK_ATTRIBUTE[0];
918
919
private String parseOperation() throws IOException {
920
String op = parseWord();
921
switch (op) {
922
case "*":
923
return TemplateManager.O_ANY;
924
case "generate":
925
return TemplateManager.O_GENERATE;
926
case "import":
927
return TemplateManager.O_IMPORT;
928
default:
929
throw excLine("Unknown operation " + op);
930
}
931
}
932
933
private long parseObjectClass() throws IOException {
934
String name = parseWord();
935
try {
936
return Functions.getObjectClassId(name);
937
} catch (IllegalArgumentException e) {
938
throw excLine("Unknown object class " + name);
939
}
940
}
941
942
private long parseKeyAlgorithm() throws IOException {
943
String name = parseWord();
944
if (isNumber(name)) {
945
return decodeNumber(name);
946
} else {
947
try {
948
return Functions.getKeyId(name);
949
} catch (IllegalArgumentException e) {
950
throw excLine("Unknown key algorithm " + name);
951
}
952
}
953
}
954
955
private long decodeAttributeName(String name) throws IOException {
956
if (isNumber(name)) {
957
return decodeNumber(name);
958
} else {
959
try {
960
return Functions.getAttributeId(name);
961
} catch (IllegalArgumentException e) {
962
throw excLine("Unknown attribute name " + name);
963
}
964
}
965
}
966
967
private CK_ATTRIBUTE decodeAttributeValue(long id, String value)
968
throws IOException {
969
if (value.equals("null")) {
970
return new CK_ATTRIBUTE(id);
971
} else if (value.equals("true")) {
972
return new CK_ATTRIBUTE(id, true);
973
} else if (value.equals("false")) {
974
return new CK_ATTRIBUTE(id, false);
975
} else if (isByteArray(value)) {
976
return new CK_ATTRIBUTE(id, decodeByteArray(value));
977
} else if (isNumber(value)) {
978
return new CK_ATTRIBUTE(id, Integer.valueOf(decodeNumber(value)));
979
} else {
980
throw excLine("Unknown attribute value " + value);
981
}
982
}
983
984
private void parseNSSArgs(String keyword) throws IOException {
985
checkDup(keyword);
986
parseEquals();
987
int token = nextToken();
988
if (token != '"') {
989
throw excToken("Expected quoted string");
990
}
991
nssArgs = expand(st.sval);
992
debug("nssArgs: " + nssArgs);
993
}
994
995
private void parseHandleStartupErrors(String keyword) throws IOException {
996
checkDup(keyword);
997
parseEquals();
998
String val = parseWord();
999
if (val.equals("ignoreAll")) {
1000
handleStartupErrors = ERR_IGNORE_ALL;
1001
} else if (val.equals("ignoreMissingLibrary")) {
1002
handleStartupErrors = ERR_IGNORE_LIB;
1003
} else if (val.equals("halt")) {
1004
handleStartupErrors = ERR_HALT;
1005
} else {
1006
throw excToken("Invalid value for handleStartupErrors:");
1007
}
1008
debug("handleStartupErrors: " + handleStartupErrors);
1009
}
1010
1011
}
1012
1013
class ConfigurationException extends IOException {
1014
private static final long serialVersionUID = 254492758807673194L;
1015
ConfigurationException(String msg) {
1016
super(msg);
1017
}
1018
}
1019
1020