continue; } if ((token == TT_WORD) && st.sval.equals("{")) { return; } throw excToken("Expected '{', read"); } } private boolean isCloseBraces(int token) { return (token == TT_WORD) && st.sval.equals("}"); } private String parseWord() throws IOException { int token = nextToken(); if (token != TT_WORD) { throw excToken("Unexpected value:"); } return st.sval; } private String parseStringEntry(String keyword) throws IOException { checkDup(keyword); parseEquals(); int token = nextToken(); if (token != TT_WORD && token != '\"') { // not a word token nor a string enclosed by double quotes throw excToken("Unexpected value:"); } String value = st.sval; debug(keyword + ": " + value); return value; } private boolean parseBooleanEntry(String keyword) throws IOException { checkDup(keyword); parseEquals(); boolean value = parseBoolean(); debug(keyword + ": " + value); return value; } private int parseIntegerEntry(String keyword) throws IOException { checkDup(keyword); parseEquals(); int value = decodeNumber(parseWord()); debug(keyword + ": " + value); return value; } private boolean parseBoolean() throws IOException { String val = parseWord(); if (val.equals("true")) { return true; } else if (val.equals("false")) { return false; } else { throw excToken("Expected boolean value, read:"); } } private String parseLine() throws IOException { String s = parseWord(); while (true) { int token = nextToken(); if ((token == TT_EOL) || (token == TT_EOF)) { break; } if (token != TT_WORD) { throw excToken("Unexpected value"); } s = s + " " + st.sval; } return s; } private int decodeNumber(String str) throws IOException { try { if (str.startsWith("0x") || str.startsWith("0X")) { return Integer.parseInt(str.substring(2), 16); } else { return Integer.parseInt(str); } } catch (NumberFormatException e) { throw excToken("Expected number, read"); } } private static boolean isNumber(String s) { if (s.length() == 0) { return false; } char ch = s.charAt(0); return ((ch >= '0') && (ch <= '9')); } private void parseComma() throws IOException { int token = nextToken(); if (token != ',') { throw excToken("Expected ',', read"); } } private static boolean isByteArray(String val) { return val.startsWith("0h"); } private byte[] decodeByteArray(String str) throws IOException { if (str.startsWith("0h") == false) { throw excToken("Expected byte array value, read"); } str = str.substring(2); // XXX proper hex parsing try { return new BigInteger(str, 16).toByteArray(); } catch (NumberFormatException e) { throw excToken("Expected byte array value, read"); } } private void checkDup(String keyword) throws IOException { if (parsedKeywords.contains(keyword)) { throw excLine(keyword + " must only be specified once"); } } // // individual entry parsing methods // private String parseLibrary(String keyword) throws IOException { checkDup(keyword); parseEquals(); String lib = parseLine(); lib = expand(lib); int i = lib.indexOf("/$ISA/"); if (i != -1) { // replace "/$ISA/" with "/sparcv9/" on 64-bit Solaris SPARC // and with "/amd64/" on Solaris AMD64. // On all other platforms, just turn it into a "/" String osName = System.getProperty("os.name", ""); String osArch = System.getProperty("os.arch", ""); String prefix = lib.substring(0, i); String suffix = lib.substring(i + 5); if (osName.equals("SunOS") && osArch.equals("sparcv9")) { lib = prefix + "/sparcv9" + suffix; } else if (osName.equals("SunOS") && osArch.equals("amd64")) { lib = prefix + "/amd64" + suffix; } else { lib = prefix + suffix; } } debug(keyword + ": " + lib); // Check to see if full path is specified to prevent the DLL // preloading attack if (!(new File(lib)).isAbsolute()) { throw new ConfigurationException( "Absolute path required for library value: " + lib); } return lib; } private void parseDescription(String keyword) throws IOException { checkDup(keyword); parseEquals(); description = parseLine(); debug("description: " + description); } private void parseSlotID(String keyword) throws IOException { if (slotID >= 0) { throw excLine("Duplicate slot definition"); } if (slotListIndex >= 0) { throw excLine ("Only one of slot and slotListIndex must be specified"); } parseEquals(); String slotString = parseWord(); slotID = decodeNumber(slotString); debug("slot: " + slotID); } private void parseSlotListIndex(String keyword) throws IOException { if (slotListIndex >= 0) { throw excLine("Duplicate slotListIndex definition"); } if (slotID >= 0) { throw excLine ("Only one of slot and slotListIndex must be specified"); } parseEquals(); String slotString = parseWord(); slotListIndex = decodeNumber(slotString); debug("slotListIndex: " + slotListIndex); } private void parseEnabledMechanisms(String keyword) throws IOException { enabledMechanisms = parseMechanisms(keyword); } private void parseDisabledMechanisms(String keyword) throws IOException { disabledMechanisms = parseMechanisms(keyword); } private Set<Long> parseMechanisms(String keyword) throws IOException { checkDup(keyword); Set<Long> mechs = new HashSet<Long>(); parseEquals(); parseOpenBraces(); while (true) { int token = nextToken(); if (isCloseBraces(token)) { break; } if (token == TT_EOL) { continue; } if (token != TT_WORD) { throw excToken("Expected mechanism, read"); } long mech = parseMechanism(st.sval); mechs.add(Long.valueOf(mech)); } if (DEBUG) { System.out.print("mechanisms: ["); for (Long mech : mechs) { System.out.print(Functions.getMechanismName(mech)); System.out.print(", "); } System.out.println("]"); } return mechs; } private long parseMechanism(String mech) throws IOException { if (isNumber(mech)) { return decodeNumber(mech); } else { try { return Functions.getMechanismId(mech); } catch (IllegalArgumentException e) { throw excLine("Unknown mechanism: " + mech); } } } private void parseAttributes(String keyword) throws IOException { if (templateManager == null) { templateManager = new TemplateManager(); } int token = nextToken(); if (token == '=') { String s = parseWord(); if (s.equals("compatibility") == false) { throw excLine("Expected 'compatibility', read " + s); } setCompatibilityAttributes(); return; } if (token != '(') { throw excToken("Expected '(' or '=', read"); } String op = parseOperation(); parseComma(); long objectClass = parseObjectClass(); parseComma(); long keyAlg = parseKeyAlgorithm(); token = nextToken(); if (token != ')') { throw excToken("Expected ')', read"); } parseEquals(); parseOpenBraces(); List<CK_ATTRIBUTE> attributes = new ArrayList<CK_ATTRIBUTE>(); while (true) { token = nextToken(); if (isCloseBraces(token)) { break; } if (token == TT_EOL) { continue; } if (token != TT_WORD) { throw excToken("Expected mechanism, read"); } String attributeName = st.sval; long attributeId = decodeAttributeName(attributeName); parseEquals(); String attributeValue = parseWord(); attributes.add(decodeAttributeValue(attributeId, attributeValue)); } templateManager.addTemplate (op, objectClass, keyAlg, attributes.toArray(CK_A0)); } private void setCompatibilityAttributes() { // all secret keys templateManager.addTemplate(O_ANY, CKO_SECRET_KEY, PCKK_ANY, new CK_ATTRIBUTE[] { TOKEN_FALSE, SENSITIVE_FALSE, EXTRACTABLE_TRUE, ENCRYPT_TRUE, DECRYPT_TRUE, WRAP_TRUE, UNWRAP_TRUE, }); // generic secret keys are special // They are used as MAC keys plus for the SSL/TLS (pre)master secrets templateManager.addTemplate(O_ANY, CKO_SECRET_KEY, CKK_GENERIC_SECRET, new CK_ATTRIBUTE[] { SIGN_TRUE, VERIFY_TRUE, ENCRYPT_NULL, DECRYPT_NULL, WRAP_NULL, UNWRAP_NULL, DERIVE_TRUE, }); // all private and public keys templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, PCKK_ANY, new CK_ATTRIBUTE[] { TOKEN_FALSE, SENSITIVE_FALSE, EXTRACTABLE_TRUE, }); templateManager.addTemplate(O_ANY, CKO_PUBLIC_KEY, PCKK_ANY, new CK_ATTRIBUTE[] { TOKEN_FALSE, }); // additional attributes for RSA private keys templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, CKK_RSA, new CK_ATTRIBUTE[] { DECRYPT_TRUE, SIGN_TRUE, SIGN_RECOVER_TRUE, UNWRAP_TRUE, }); // additional attributes for RSA public keys templateManager.addTemplate(O_ANY, CKO_PUBLIC_KEY, CKK_RSA, new CK_ATTRIBUTE[] { ENCRYPT_TRUE, VERIFY_TRUE, VERIFY_RECOVER_TRUE, WRAP_TRUE, }); // additional attributes for DSA private keys templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, CKK_DSA, new CK_ATTRIBUTE[] { SIGN_TRUE, }); // additional attributes for DSA public keys templateManager.addTemplate(O_ANY, CKO_PUBLIC_KEY, CKK_DSA, new CK_ATTRIBUTE[] { VERIFY_TRUE, }); // additional attributes for DH private keys templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, CKK_DH, new CK_ATTRIBUTE[] { DERIVE_TRUE, }); // additional attributes for EC private keys templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, CKK_EC, new CK_ATTRIBUTE[] { SIGN_TRUE, DERIVE_TRUE, }); // additional attributes for EC public keys templateManager.addTemplate(O_ANY, CKO_PUBLIC_KEY, CKK_EC, new CK_ATTRIBUTE[] { VERIFY_TRUE, }); } private final static CK_ATTRIBUTE[] CK_A0 = new CK_ATTRIBUTE[0]; private String parseOperation() throws IOException { String op = parseWord(); if (op.equals("*")) { return TemplateManager.O_ANY; } else if (op.equals("generate")) { return TemplateManager.O_GENERATE; } else if (op.equals("import")) { return TemplateManager.O_IMPORT; } else { throw excLine("Unknown operation " + op); } } private long parseObjectClass() throws IOException { String name = parseWord(); try { return Functions.getObjectClassId(name); } catch (IllegalArgumentException e) { throw excLine("Unknown object class " + name); } } private long parseKeyAlgorithm() throws IOException { String name = parseWord(); if (isNumber(name)) { return decodeNumber(name); } else { try { return Functions.getKeyId(name); } catch (IllegalArgumentException e) { throw excLine("Unknown key algorithm " + name); } } } private long decodeAttributeName(String name) throws IOException { if (isNumber(name)) { return decodeNumber(name); } else { try { return Functions.getAttributeId(name); } catch (IllegalArgumentException e) { throw excLine("Unknown attribute name " + name); } } } private CK_ATTRIBUTE decodeAttributeValue(long id, String value) throws IOException { if (value.equals("null")) { return new CK_ATTRIBUTE(id); } else if (value.equals("true")) { return new CK_ATTRIBUTE(id, true); } else if (value.equals("false")) { return new CK_ATTRIBUTE(id, false); } else if (isByteArray(value)) { return new CK_ATTRIBUTE(id, decodeByteArray(value)); } else if (isNumber(value)) { return new CK_ATTRIBUTE(id, Integer.valueOf(decodeNumber(value))); } else { throw excLine("Unknown attribute value " + value); } } private void parseNSSArgs(String keyword) throws IOException { checkDup(keyword); parseEquals(); int token = nextToken(); if (token != '"') { throw excToken("Expected quoted string"); } nssArgs = expand(st.sval); debug("nssArgs: " + nssArgs); } private void parseHandleStartupErrors(String keyword) throws IOException { checkDup(keyword); parseEquals(); String val = parseWord(); if (val.equals("ignoreAll")) { handleStartupErrors = ERR_IGNORE_ALL; } else if (val.equals("ignoreMissingLibrary")) { handleStartupErrors = ERR_IGNORE_LIB; } else if (val.equals("halt")) { handleStartupErrors = ERR_HALT; } else { throw excToken("Invalid value for handleStartupErrors:"); } debug("handleStartupErrors: " + handleStartupErrors); } } class ConfigurationException extends IOException { ConfigurationException(String msg) { super(msg); }}Lines 501–984 of 984. Previous lines
continue; } if ((token == TT_WORD) && st.sval.equals("{")) { return; } throw excToken("Expected '{', read"); } } private boolean isCloseBraces(int token) { return (token == TT_WORD) && st.sval.equals("}"); } private String parseWord() throws IOException { int token = nextToken(); if (token != TT_WORD) { throw excToken("Unexpected value:"); } return st.sval; } private String parseStringEntry(String keyword) throws IOException { checkDup(keyword); parseEquals(); int token = nextToken(); if (token != TT_WORD && token != '\"') { // not a word token nor a string enclosed by double quotes throw excToken("Unexpected value:"); } String value = st.sval; debug(keyword + ": " + value); return value; } private boolean parseBooleanEntry(String keyword) throws IOException { checkDup(keyword); parseEquals(); boolean value = parseBoolean(); debug(keyword + ": " + value); return value; } private int parseIntegerEntry(String keyword) throws IOException { checkDup(keyword); parseEquals(); int value = decodeNumber(parseWord()); debug(keyword + ": " + value); return value; } private boolean parseBoolean() throws IOException { String val = parseWord(); if (val.equals("true")) { return true; } else if (val.equals("false")) { return false; } else { throw excToken("Expected boolean value, read:"); } } private String parseLine() throws IOException { String s = parseWord(); while (true) { int token = nextToken(); if ((token == TT_EOL) || (token == TT_EOF)) { break; } if (token != TT_WORD) { throw excToken("Unexpected value"); } s = s + " " + st.sval; } return s; } private int decodeNumber(String str) throws IOException { try { if (str.startsWith("0x") || str.startsWith("0X")) { return Integer.parseInt(str.substring(2), 16); } else { return Integer.parseInt(str); } } catch (NumberFormatException e) { throw excToken("Expected number, read"); } } private static boolean isNumber(String s) { if (s.length() == 0) { return false; } char ch = s.charAt(0); return ((ch >= '0') && (ch <= '9')); } private void parseComma() throws IOException { int token = nextToken(); if (token != ',') { throw excToken("Expected ',', read"); } } private static boolean isByteArray(String val) { return val.startsWith("0h"); } private byte[] decodeByteArray(String str) throws IOException { if (str.startsWith("0h") == false) { throw excToken("Expected byte array value, read"); } str = str.substring(2); // XXX proper hex parsing try { return new BigInteger(str, 16).toByteArray(); } catch (NumberFormatException e) { throw excToken("Expected byte array value, read"); } } private void checkDup(String keyword) throws IOException { if (parsedKeywords.contains(keyword)) { throw excLine(keyword + " must only be specified once"); } } // // individual entry parsing methods // private String parseLibrary(String keyword) throws IOException { checkDup(keyword); parseEquals(); String lib = parseLine(); lib = expand(lib); int i = lib.indexOf("/$ISA/"); if (i != -1) { // replace "/$ISA/" with "/sparcv9/" on 64-bit Solaris SPARC // and with "/amd64/" on Solaris AMD64. // On all other platforms, just turn it into a "/" String osName = System.getProperty("os.name", ""); String osArch = System.getProperty("os.arch", ""); String prefix = lib.substring(0, i); String suffix = lib.substring(i + 5); if (osName.equals("SunOS") && osArch.equals("sparcv9")) { lib = prefix + "/sparcv9" + suffix; } else if (osName.equals("SunOS") && osArch.equals("amd64")) { lib = prefix + "/amd64" + suffix; } else { lib = prefix + suffix; } } debug(keyword + ": " + lib); // Check to see if full path is specified to prevent the DLL // preloading attack if (!(new File(lib)).isAbsolute()) { throw new ConfigurationException( "Absolute path required for library value: " + lib); } return lib; } private void parseDescription(String keyword) throws IOException { checkDup(keyword); parseEquals(); description = parseLine(); debug("description: " + description); } private void parseSlotID(String keyword) throws IOException { if (slotID >= 0) { throw excLine("Duplicate slot definition"); } if (slotListIndex >= 0) { throw excLine ("Only one of slot and slotListIndex must be specified"); } parseEquals(); String slotString = parseWord(); slotID = decodeNumber(slotString); debug("slot: " + slotID); } private void parseSlotListIndex(String keyword) throws IOException { if (slotListIndex >= 0) { throw excLine("Duplicate slotListIndex definition"); } if (slotID >= 0) { throw excLine ("Only one of slot and slotListIndex must be specified"); } parseEquals(); String slotString = parseWord(); slotListIndex = decodeNumber(slotString); debug("slotListIndex: " + slotListIndex); } private void parseEnabledMechanisms(String keyword) throws IOException { enabledMechanisms = parseMechanisms(keyword); } private void parseDisabledMechanisms(String keyword) throws IOException { disabledMechanisms = parseMechanisms(keyword); } private Set<Long> parseMechanisms(String keyword) throws IOException { checkDup(keyword); Set<Long> mechs = new HashSet<Long>(); parseEquals(); parseOpenBraces(); while (true) { int token = nextToken(); if (isCloseBraces(token)) { break; } if (token == TT_EOL) { continue; } if (token != TT_WORD) { throw excToken("Expected mechanism, read"); } long mech = parseMechanism(st.sval); mechs.add(Long.valueOf(mech)); } if (DEBUG) { System.out.print("mechanisms: ["); for (Long mech : mechs) { System.out.print(Functions.getMechanismName(mech)); System.out.print(", "); } System.out.println("]"); } return mechs; } private long parseMechanism(String mech) throws IOException { if (isNumber(mech)) { return decodeNumber(mech); } else { try { return Functions.getMechanismId(mech); } catch (IllegalArgumentException e) { throw excLine("Unknown mechanism: " + mech); } } } private void parseAttributes(String keyword) throws IOException { if (templateManager == null) { templateManager = new TemplateManager(); } int token = nextToken(); if (token == '=') { String s = parseWord(); if (s.equals("compatibility") == false) { throw excLine("Expected 'compatibility', read " + s); } setCompatibilityAttributes(); return; } if (token != '(') { throw excToken("Expected '(' or '=', read"); } String op = parseOperation(); parseComma(); long objectClass = parseObjectClass(); parseComma(); long keyAlg = parseKeyAlgorithm(); token = nextToken(); if (token != ')') { throw excToken("Expected ')', read"); } parseEquals(); parseOpenBraces(); List<CK_ATTRIBUTE> attributes = new ArrayList<CK_ATTRIBUTE>(); while (true) { token = nextToken(); if (isCloseBraces(token)) { break; } if (token == TT_EOL) { continue; } if (token != TT_WORD) { throw excToken("Expected mechanism, read"); } String attributeName = st.sval; long attributeId = decodeAttributeName(attributeName); parseEquals(); String attributeValue = parseWord(); attributes.add(decodeAttributeValue(attributeId, attributeValue)); } templateManager.addTemplate (op, objectClass, keyAlg, attributes.toArray(CK_A0)); } private void setCompatibilityAttributes() { // all secret keys templateManager.addTemplate(O_ANY, CKO_SECRET_KEY, PCKK_ANY, new CK_ATTRIBUTE[] { TOKEN_FALSE, SENSITIVE_FALSE, EXTRACTABLE_TRUE, ENCRYPT_TRUE, DECRYPT_TRUE, WRAP_TRUE, UNWRAP_TRUE, }); // generic secret keys are special // They are used as MAC keys plus for the SSL/TLS (pre)master secrets templateManager.addTemplate(O_ANY, CKO_SECRET_KEY, CKK_GENERIC_SECRET, new CK_ATTRIBUTE[] { SIGN_TRUE, VERIFY_TRUE, ENCRYPT_NULL, DECRYPT_NULL, WRAP_NULL, UNWRAP_NULL, DERIVE_TRUE, }); // all private and public keys templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, PCKK_ANY, new CK_ATTRIBUTE[] { TOKEN_FALSE, SENSITIVE_FALSE, EXTRACTABLE_TRUE, }); templateManager.addTemplate(O_ANY, CKO_PUBLIC_KEY, PCKK_ANY, new CK_ATTRIBUTE[] { TOKEN_FALSE, }); // additional attributes for RSA private keys templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, CKK_RSA, new CK_ATTRIBUTE[] { DECRYPT_TRUE, SIGN_TRUE, SIGN_RECOVER_TRUE, UNWRAP_TRUE, }); // additional attributes for RSA public keys templateManager.addTemplate(O_ANY, CKO_PUBLIC_KEY, CKK_RSA, new CK_ATTRIBUTE[] { ENCRYPT_TRUE, VERIFY_TRUE, VERIFY_RECOVER_TRUE, WRAP_TRUE, }); // additional attributes for DSA private keys templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, CKK_DSA, new CK_ATTRIBUTE[] { SIGN_TRUE, }); // additional attributes for DSA public keys templateManager.addTemplate(O_ANY, CKO_PUBLIC_KEY, CKK_DSA, new CK_ATTRIBUTE[] { VERIFY_TRUE, }); // additional attributes for DH private keys templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, CKK_DH, new CK_ATTRIBUTE[] { DERIVE_TRUE, }); // additional attributes for EC private keys templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, CKK_EC, new CK_ATTRIBUTE[] { SIGN_TRUE, DERIVE_TRUE, }); // additional attributes for EC public keys templateManager.addTemplate(O_ANY, CKO_PUBLIC_KEY, CKK_EC, new CK_ATTRIBUTE[] { VERIFY_TRUE, }); } private final static CK_ATTRIBUTE[] CK_A0 = new CK_ATTRIBUTE[0]; private String parseOperation() throws IOException { String op = parseWord(); if (op.equals("*")) { return TemplateManager.O_ANY; } else if (op.equals("generate")) { return TemplateManager.O_GENERATE; } else if (op.equals("import")) { return TemplateManager.O_IMPORT; } else { throw excLine("Unknown operation " + op); } } private long parseObjectClass() throws IOException { String name = parseWord(); try { return Functions.getObjectClassId(name); } catch (IllegalArgumentException e) { throw excLine("Unknown object class " + name); } } private long parseKeyAlgorithm() throws IOException { String name = parseWord(); if (isNumber(name)) { return decodeNumber(name); } else { try { return Functions.getKeyId(name); } catch (IllegalArgumentException e) { throw excLine("Unknown key algorithm " + name); } } } private long decodeAttributeName(String name) throws IOException { if (isNumber(name)) { return decodeNumber(name); } else { try { return Functions.getAttributeId(name); } catch (IllegalArgumentException e) { throw excLine("Unknown attribute name " + name); } } } private CK_ATTRIBUTE decodeAttributeValue(long id, String value) throws IOException { if (value.equals("null")) { return new CK_ATTRIBUTE(id); } else if (value.equals("true")) { return new CK_ATTRIBUTE(id, true); } else if (value.equals("false")) { return new CK_ATTRIBUTE(id, false); } else if (isByteArray(value)) { return new CK_ATTRIBUTE(id, decodeByteArray(value)); } else if (isNumber(value)) { return new CK_ATTRIBUTE(id, Integer.valueOf(decodeNumber(value))); } else { throw excLine("Unknown attribute value " + value); } } private void parseNSSArgs(String keyword) throws IOException { checkDup(keyword); parseEquals(); int token = nextToken(); if (token != '"') { throw excToken("Expected quoted string"); } nssArgs = expand(st.sval); debug("nssArgs: " + nssArgs); } private void parseHandleStartupErrors(String keyword) throws IOException { checkDup(keyword); parseEquals(); String val = parseWord(); if (val.equals("ignoreAll")) { handleStartupErrors = ERR_IGNORE_ALL; } else if (val.equals("ignoreMissingLibrary")) { handleStartupErrors = ERR_IGNORE_LIB; } else if (val.equals("halt")) { handleStartupErrors = ERR_HALT; } else { throw excToken("Invalid value for handleStartupErrors:"); } debug("handleStartupErrors: " + handleStartupErrors); } } class ConfigurationException extends IOException { ConfigurationException(String msg) { super(msg); } }