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