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