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