--- old/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/Config.java 2016-12-13 21:43:56.000000000 -0800 +++ /dev/null 2016-12-13 21:43:56.000000000 -0800 @@ -1,1008 +0,0 @@ -/* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.security.pkcs11; - -import java.io.*; -import static java.io.StreamTokenizer.*; -import java.math.BigInteger; -import java.util.*; - -import java.security.*; - -import sun.security.util.PropertyExpander; - -import sun.security.pkcs11.wrapper.*; -import static sun.security.pkcs11.wrapper.PKCS11Constants.*; -import static sun.security.pkcs11.wrapper.CK_ATTRIBUTE.*; - -import static sun.security.pkcs11.TemplateManager.*; - -/** - * Configuration container and file parsing. - * - * @author Andreas Sterbenz - * @since 1.5 - */ -final class Config { - - static final int ERR_HALT = 1; - static final int ERR_IGNORE_ALL = 2; - static final int ERR_IGNORE_LIB = 3; - - // same as allowSingleThreadedModules but controlled via a system property - // and applied to all providers. if set to false, no SunPKCS11 instances - // will accept single threaded modules regardless of the setting in their - // config files. - private static final boolean staticAllowSingleThreadedModules; - private static final String osName; - private static final String osArch; - - static { - List props = AccessController.doPrivileged( - new PrivilegedAction<>() { - @Override - public List run() { - return List.of( - System.getProperty( - "sun.security.pkcs11.allowSingleThreadedModules", - "true"), - System.getProperty("os.name"), - System.getProperty("os.arch")); - } - } - ); - if ("false".equalsIgnoreCase(props.get(0))) { - staticAllowSingleThreadedModules = false; - } else { - staticAllowSingleThreadedModules = true; - } - osName = props.get(1); - osArch = props.get(2); - } - - private final static boolean DEBUG = false; - - private static void debug(Object o) { - if (DEBUG) { - System.out.println(o); - } - } - - // file name containing this configuration - private String filename; - - // Reader and StringTokenizer used during parsing - private Reader reader; - - private StreamTokenizer st; - - private Set parsedKeywords; - - // name suffix of the provider - private String name; - - // name of the PKCS#11 library - private String library; - - // description to pass to the provider class - private String description; - - // slotID of the slot to use - private int slotID = -1; - - // slot to use, specified as index in the slotlist - private int slotListIndex = -1; - - // set of enabled mechanisms (or null to use default) - private Set enabledMechanisms; - - // set of disabled mechanisms - private Set disabledMechanisms; - - // whether to print debug info during startup - private boolean showInfo = false; - - // template manager, initialized from parsed attributes - private TemplateManager templateManager; - - // how to handle error during startup, one of ERR_ - private int handleStartupErrors = ERR_HALT; - - // flag indicating whether the P11KeyStore should - // be more tolerant of input parameters - private boolean keyStoreCompatibilityMode = true; - - // flag indicating whether we need to explicitly cancel operations - // see Token - private boolean explicitCancel = true; - - // how often to test for token insertion, if no token is present - private int insertionCheckInterval = 2000; - - // flag inidicating whether to omit the call to C_Initialize() - // should be used only if we are running within a process that - // has already called it (e.g. Plugin inside of Mozilla/NSS) - private boolean omitInitialize = false; - - // whether to allow modules that only support single threaded access. - // they cannot be used safely from multiple PKCS#11 consumers in the - // same process, for example NSS and SunPKCS11 - private boolean allowSingleThreadedModules = true; - - // name of the C function that returns the PKCS#11 functionlist - // This option primarily exists for the deprecated - // Secmod.Module.getProvider() method. - private String functionList = "C_GetFunctionList"; - - // whether to use NSS secmod mode. Implicitly set if nssLibraryDirectory, - // nssSecmodDirectory, or nssModule is specified. - private boolean nssUseSecmod; - - // location of the NSS library files (libnss3.so, etc.) - private String nssLibraryDirectory; - - // location of secmod.db - private String nssSecmodDirectory; - - // which NSS module to use - private String nssModule; - - private Secmod.DbMode nssDbMode = Secmod.DbMode.READ_WRITE; - - // Whether the P11KeyStore should specify the CKA_NETSCAPE_DB attribute - // when creating private keys. Only valid if nssUseSecmod is true. - private boolean nssNetscapeDbWorkaround = true; - - // Special init argument string for the NSS softtoken. - // This is used when using the NSS softtoken directly without secmod mode. - private String nssArgs; - - // whether to use NSS trust attributes for the KeyStore of this provider - // this option is for internal use by the SunPKCS11 code only and - // works only for NSS providers created via the Secmod API - private boolean nssUseSecmodTrust = false; - - // Flag to indicate whether the X9.63 encoding for EC points shall be used - // (true) or whether that encoding shall be wrapped in an ASN.1 OctetString - // (false). - private boolean useEcX963Encoding = false; - - // Flag to indicate whether NSS should favour performance (false) or - // memory footprint (true). - private boolean nssOptimizeSpace = false; - - Config(String fn) throws IOException { - this.filename = fn; - if (filename.startsWith("--")) { - // inline config - String config = filename.substring(2).replace("\\n", "\n"); - reader = new StringReader(config); - } else { - reader = new BufferedReader(new InputStreamReader - (new FileInputStream(expand(filename)))); - } - parsedKeywords = new HashSet(); - st = new StreamTokenizer(reader); - setupTokenizer(); - parse(); - } - - String getFileName() { - return filename; - } - - String getName() { - return name; - } - - String getLibrary() { - return library; - } - - String getDescription() { - if (description != null) { - return description; - } - return "SunPKCS11-" + name + " using library " + library; - } - - int getSlotID() { - return slotID; - } - - int getSlotListIndex() { - if ((slotID == -1) && (slotListIndex == -1)) { - // if neither is set, default to first slot - return 0; - } else { - return slotListIndex; - } - } - - boolean getShowInfo() { - return (SunPKCS11.debug != null) || showInfo; - } - - TemplateManager getTemplateManager() { - if (templateManager == null) { - templateManager = new TemplateManager(); - } - return templateManager; - } - - boolean isEnabled(long m) { - if (enabledMechanisms != null) { - return enabledMechanisms.contains(Long.valueOf(m)); - } - if (disabledMechanisms != null) { - return !disabledMechanisms.contains(Long.valueOf(m)); - } - return true; - } - - int getHandleStartupErrors() { - return handleStartupErrors; - } - - boolean getKeyStoreCompatibilityMode() { - return keyStoreCompatibilityMode; - } - - boolean getExplicitCancel() { - return explicitCancel; - } - - int getInsertionCheckInterval() { - return insertionCheckInterval; - } - - boolean getOmitInitialize() { - return omitInitialize; - } - - boolean getAllowSingleThreadedModules() { - return staticAllowSingleThreadedModules && allowSingleThreadedModules; - } - - String getFunctionList() { - return functionList; - } - - boolean getNssUseSecmod() { - return nssUseSecmod; - } - - String getNssLibraryDirectory() { - return nssLibraryDirectory; - } - - String getNssSecmodDirectory() { - return nssSecmodDirectory; - } - - String getNssModule() { - return nssModule; - } - - Secmod.DbMode getNssDbMode() { - return nssDbMode; - } - - public boolean getNssNetscapeDbWorkaround() { - return nssUseSecmod && nssNetscapeDbWorkaround; - } - - String getNssArgs() { - return nssArgs; - } - - boolean getNssUseSecmodTrust() { - return nssUseSecmodTrust; - } - - boolean getUseEcX963Encoding() { - return useEcX963Encoding; - } - - boolean getNssOptimizeSpace() { - return nssOptimizeSpace; - } - - private static String expand(final String s) throws IOException { - try { - return PropertyExpander.expand(s); - } catch (Exception e) { - throw new RuntimeException(e.getMessage()); - } - } - - private void setupTokenizer() { - st.resetSyntax(); - st.wordChars('a', 'z'); - st.wordChars('A', 'Z'); - st.wordChars('0', '9'); - st.wordChars(':', ':'); - st.wordChars('.', '.'); - st.wordChars('_', '_'); - st.wordChars('-', '-'); - st.wordChars('/', '/'); - st.wordChars('\\', '\\'); - st.wordChars('$', '$'); - st.wordChars('{', '{'); // need {} for property subst - st.wordChars('}', '}'); - st.wordChars('*', '*'); - st.wordChars('+', '+'); - st.wordChars('~', '~'); - // XXX check ASCII table and add all other characters except special - - // special: #="(), - st.whitespaceChars(0, ' '); - st.commentChar('#'); - st.eolIsSignificant(true); - st.quoteChar('\"'); - } - - private ConfigurationException excToken(String msg) { - return new ConfigurationException(msg + " " + st); - } - - private ConfigurationException excLine(String msg) { - return new ConfigurationException(msg + ", line " + st.lineno()); - } - - private void parse() throws IOException { - while (true) { - int token = nextToken(); - if (token == TT_EOF) { - break; - } - if (token == TT_EOL) { - continue; - } - if (token != TT_WORD) { - throw excToken("Unexpected token:"); - } - String word = st.sval; - if (word.equals("name")) { - name = parseStringEntry(word); - } else if (word.equals("library")) { - library = parseLibrary(word); - } else if (word.equals("description")) { - parseDescription(word); - } else if (word.equals("slot")) { - parseSlotID(word); - } else if (word.equals("slotListIndex")) { - parseSlotListIndex(word); - } else if (word.equals("enabledMechanisms")) { - parseEnabledMechanisms(word); - } else if (word.equals("disabledMechanisms")) { - parseDisabledMechanisms(word); - } else if (word.equals("attributes")) { - parseAttributes(word); - } else if (word.equals("handleStartupErrors")) { - parseHandleStartupErrors(word); - } else if (word.endsWith("insertionCheckInterval")) { - insertionCheckInterval = parseIntegerEntry(word); - if (insertionCheckInterval < 100) { - throw excLine(word + " must be at least 100 ms"); - } - } else if (word.equals("showInfo")) { - showInfo = parseBooleanEntry(word); - } else if (word.equals("keyStoreCompatibilityMode")) { - keyStoreCompatibilityMode = parseBooleanEntry(word); - } else if (word.equals("explicitCancel")) { - explicitCancel = parseBooleanEntry(word); - } else if (word.equals("omitInitialize")) { - omitInitialize = parseBooleanEntry(word); - } else if (word.equals("allowSingleThreadedModules")) { - allowSingleThreadedModules = parseBooleanEntry(word); - } else if (word.equals("functionList")) { - functionList = parseStringEntry(word); - } else if (word.equals("nssUseSecmod")) { - nssUseSecmod = parseBooleanEntry(word); - } else if (word.equals("nssLibraryDirectory")) { - nssLibraryDirectory = parseLibrary(word); - nssUseSecmod = true; - } else if (word.equals("nssSecmodDirectory")) { - nssSecmodDirectory = expand(parseStringEntry(word)); - nssUseSecmod = true; - } else if (word.equals("nssModule")) { - nssModule = parseStringEntry(word); - nssUseSecmod = true; - } else if (word.equals("nssDbMode")) { - String mode = parseStringEntry(word); - if (mode.equals("readWrite")) { - nssDbMode = Secmod.DbMode.READ_WRITE; - } else if (mode.equals("readOnly")) { - nssDbMode = Secmod.DbMode.READ_ONLY; - } else if (mode.equals("noDb")) { - nssDbMode = Secmod.DbMode.NO_DB; - } else { - throw excToken("nssDbMode must be one of readWrite, readOnly, and noDb:"); - } - nssUseSecmod = true; - } else if (word.equals("nssNetscapeDbWorkaround")) { - nssNetscapeDbWorkaround = parseBooleanEntry(word); - nssUseSecmod = true; - } else if (word.equals("nssArgs")) { - parseNSSArgs(word); - } else if (word.equals("nssUseSecmodTrust")) { - nssUseSecmodTrust = parseBooleanEntry(word); - } else if (word.equals("useEcX963Encoding")) { - useEcX963Encoding = parseBooleanEntry(word); - } else if (word.equals("nssOptimizeSpace")) { - nssOptimizeSpace = parseBooleanEntry(word); - } else { - throw new ConfigurationException - ("Unknown keyword '" + word + "', line " + st.lineno()); - } - parsedKeywords.add(word); - } - reader.close(); - reader = null; - st = null; - parsedKeywords = null; - if (name == null) { - throw new ConfigurationException("name must be specified"); - } - if (nssUseSecmod == false) { - if (library == null) { - throw new ConfigurationException("library must be specified"); - } - } else { - if (library != null) { - throw new ConfigurationException - ("library must not be specified in NSS mode"); - } - if ((slotID != -1) || (slotListIndex != -1)) { - throw new ConfigurationException - ("slot and slotListIndex must not be specified in NSS mode"); - } - if (nssArgs != null) { - throw new ConfigurationException - ("nssArgs must not be specified in NSS mode"); - } - if (nssUseSecmodTrust != false) { - throw new ConfigurationException("nssUseSecmodTrust is an " - + "internal option and must not be specified in NSS mode"); - } - } - } - - // - // Parsing helper methods - // - - private int nextToken() throws IOException { - int token = st.nextToken(); - debug(st); - return token; - } - - private void parseEquals() throws IOException { - int token = nextToken(); - if (token != '=') { - throw excToken("Expected '=', read"); - } - } - - private void parseOpenBraces() throws IOException { - while (true) { - int token = nextToken(); - if (token == TT_EOL) { - 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(); - switch (val) { - case "true": - return true; - case "false": - return false; - default: - throw excToken("Expected boolean value, read:"); - } - } - - private String parseLine() throws IOException { - // allow quoted string as part of line - String s = null; - while (true) { - int token = nextToken(); - if ((token == TT_EOL) || (token == TT_EOF)) { - break; - } - if (token != TT_WORD && token != '\"') { - throw excToken("Unexpected value"); - } - if (s == null) { - s = st.sval; - } else { - s = s + " " + st.sval; - } - } - if (s == null) { - throw excToken("Unexpected empty line"); - } - 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 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 parseMechanisms(String keyword) throws IOException { - checkDup(keyword); - Set mechs = new HashSet(); - 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 attributes = new ArrayList(); - 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(); - switch (op) { - case "*": - return TemplateManager.O_ANY; - case "generate": - return TemplateManager.O_GENERATE; - case "import": - return TemplateManager.O_IMPORT; - default: - 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 { - private static final long serialVersionUID = 254492758807673194L; - ConfigurationException(String msg) { - super(msg); - } -} --- /dev/null 2016-12-13 21:43:56.000000000 -0800 +++ new/jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/Config.java 2016-12-13 21:43:56.000000000 -0800 @@ -0,0 +1,1008 @@ +/* + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.security.pkcs11; + +import java.io.*; +import static java.io.StreamTokenizer.*; +import java.math.BigInteger; +import java.util.*; + +import java.security.*; + +import sun.security.util.PropertyExpander; + +import sun.security.pkcs11.wrapper.*; +import static sun.security.pkcs11.wrapper.PKCS11Constants.*; +import static sun.security.pkcs11.wrapper.CK_ATTRIBUTE.*; + +import static sun.security.pkcs11.TemplateManager.*; + +/** + * Configuration container and file parsing. + * + * @author Andreas Sterbenz + * @since 1.5 + */ +final class Config { + + static final int ERR_HALT = 1; + static final int ERR_IGNORE_ALL = 2; + static final int ERR_IGNORE_LIB = 3; + + // same as allowSingleThreadedModules but controlled via a system property + // and applied to all providers. if set to false, no SunPKCS11 instances + // will accept single threaded modules regardless of the setting in their + // config files. + private static final boolean staticAllowSingleThreadedModules; + private static final String osName; + private static final String osArch; + + static { + List props = AccessController.doPrivileged( + new PrivilegedAction<>() { + @Override + public List run() { + return List.of( + System.getProperty( + "sun.security.pkcs11.allowSingleThreadedModules", + "true"), + System.getProperty("os.name"), + System.getProperty("os.arch")); + } + } + ); + if ("false".equalsIgnoreCase(props.get(0))) { + staticAllowSingleThreadedModules = false; + } else { + staticAllowSingleThreadedModules = true; + } + osName = props.get(1); + osArch = props.get(2); + } + + private final static boolean DEBUG = false; + + private static void debug(Object o) { + if (DEBUG) { + System.out.println(o); + } + } + + // file name containing this configuration + private String filename; + + // Reader and StringTokenizer used during parsing + private Reader reader; + + private StreamTokenizer st; + + private Set parsedKeywords; + + // name suffix of the provider + private String name; + + // name of the PKCS#11 library + private String library; + + // description to pass to the provider class + private String description; + + // slotID of the slot to use + private int slotID = -1; + + // slot to use, specified as index in the slotlist + private int slotListIndex = -1; + + // set of enabled mechanisms (or null to use default) + private Set enabledMechanisms; + + // set of disabled mechanisms + private Set disabledMechanisms; + + // whether to print debug info during startup + private boolean showInfo = false; + + // template manager, initialized from parsed attributes + private TemplateManager templateManager; + + // how to handle error during startup, one of ERR_ + private int handleStartupErrors = ERR_HALT; + + // flag indicating whether the P11KeyStore should + // be more tolerant of input parameters + private boolean keyStoreCompatibilityMode = true; + + // flag indicating whether we need to explicitly cancel operations + // see Token + private boolean explicitCancel = true; + + // how often to test for token insertion, if no token is present + private int insertionCheckInterval = 2000; + + // flag inidicating whether to omit the call to C_Initialize() + // should be used only if we are running within a process that + // has already called it (e.g. Plugin inside of Mozilla/NSS) + private boolean omitInitialize = false; + + // whether to allow modules that only support single threaded access. + // they cannot be used safely from multiple PKCS#11 consumers in the + // same process, for example NSS and SunPKCS11 + private boolean allowSingleThreadedModules = true; + + // name of the C function that returns the PKCS#11 functionlist + // This option primarily exists for the deprecated + // Secmod.Module.getProvider() method. + private String functionList = "C_GetFunctionList"; + + // whether to use NSS secmod mode. Implicitly set if nssLibraryDirectory, + // nssSecmodDirectory, or nssModule is specified. + private boolean nssUseSecmod; + + // location of the NSS library files (libnss3.so, etc.) + private String nssLibraryDirectory; + + // location of secmod.db + private String nssSecmodDirectory; + + // which NSS module to use + private String nssModule; + + private Secmod.DbMode nssDbMode = Secmod.DbMode.READ_WRITE; + + // Whether the P11KeyStore should specify the CKA_NETSCAPE_DB attribute + // when creating private keys. Only valid if nssUseSecmod is true. + private boolean nssNetscapeDbWorkaround = true; + + // Special init argument string for the NSS softtoken. + // This is used when using the NSS softtoken directly without secmod mode. + private String nssArgs; + + // whether to use NSS trust attributes for the KeyStore of this provider + // this option is for internal use by the SunPKCS11 code only and + // works only for NSS providers created via the Secmod API + private boolean nssUseSecmodTrust = false; + + // Flag to indicate whether the X9.63 encoding for EC points shall be used + // (true) or whether that encoding shall be wrapped in an ASN.1 OctetString + // (false). + private boolean useEcX963Encoding = false; + + // Flag to indicate whether NSS should favour performance (false) or + // memory footprint (true). + private boolean nssOptimizeSpace = false; + + Config(String fn) throws IOException { + this.filename = fn; + if (filename.startsWith("--")) { + // inline config + String config = filename.substring(2).replace("\\n", "\n"); + reader = new StringReader(config); + } else { + reader = new BufferedReader(new InputStreamReader + (new FileInputStream(expand(filename)))); + } + parsedKeywords = new HashSet(); + st = new StreamTokenizer(reader); + setupTokenizer(); + parse(); + } + + String getFileName() { + return filename; + } + + String getName() { + return name; + } + + String getLibrary() { + return library; + } + + String getDescription() { + if (description != null) { + return description; + } + return "SunPKCS11-" + name + " using library " + library; + } + + int getSlotID() { + return slotID; + } + + int getSlotListIndex() { + if ((slotID == -1) && (slotListIndex == -1)) { + // if neither is set, default to first slot + return 0; + } else { + return slotListIndex; + } + } + + boolean getShowInfo() { + return (SunPKCS11.debug != null) || showInfo; + } + + TemplateManager getTemplateManager() { + if (templateManager == null) { + templateManager = new TemplateManager(); + } + return templateManager; + } + + boolean isEnabled(long m) { + if (enabledMechanisms != null) { + return enabledMechanisms.contains(Long.valueOf(m)); + } + if (disabledMechanisms != null) { + return !disabledMechanisms.contains(Long.valueOf(m)); + } + return true; + } + + int getHandleStartupErrors() { + return handleStartupErrors; + } + + boolean getKeyStoreCompatibilityMode() { + return keyStoreCompatibilityMode; + } + + boolean getExplicitCancel() { + return explicitCancel; + } + + int getInsertionCheckInterval() { + return insertionCheckInterval; + } + + boolean getOmitInitialize() { + return omitInitialize; + } + + boolean getAllowSingleThreadedModules() { + return staticAllowSingleThreadedModules && allowSingleThreadedModules; + } + + String getFunctionList() { + return functionList; + } + + boolean getNssUseSecmod() { + return nssUseSecmod; + } + + String getNssLibraryDirectory() { + return nssLibraryDirectory; + } + + String getNssSecmodDirectory() { + return nssSecmodDirectory; + } + + String getNssModule() { + return nssModule; + } + + Secmod.DbMode getNssDbMode() { + return nssDbMode; + } + + public boolean getNssNetscapeDbWorkaround() { + return nssUseSecmod && nssNetscapeDbWorkaround; + } + + String getNssArgs() { + return nssArgs; + } + + boolean getNssUseSecmodTrust() { + return nssUseSecmodTrust; + } + + boolean getUseEcX963Encoding() { + return useEcX963Encoding; + } + + boolean getNssOptimizeSpace() { + return nssOptimizeSpace; + } + + private static String expand(final String s) throws IOException { + try { + return PropertyExpander.expand(s); + } catch (Exception e) { + throw new RuntimeException(e.getMessage()); + } + } + + private void setupTokenizer() { + st.resetSyntax(); + st.wordChars('a', 'z'); + st.wordChars('A', 'Z'); + st.wordChars('0', '9'); + st.wordChars(':', ':'); + st.wordChars('.', '.'); + st.wordChars('_', '_'); + st.wordChars('-', '-'); + st.wordChars('/', '/'); + st.wordChars('\\', '\\'); + st.wordChars('$', '$'); + st.wordChars('{', '{'); // need {} for property subst + st.wordChars('}', '}'); + st.wordChars('*', '*'); + st.wordChars('+', '+'); + st.wordChars('~', '~'); + // XXX check ASCII table and add all other characters except special + + // special: #="(), + st.whitespaceChars(0, ' '); + st.commentChar('#'); + st.eolIsSignificant(true); + st.quoteChar('\"'); + } + + private ConfigurationException excToken(String msg) { + return new ConfigurationException(msg + " " + st); + } + + private ConfigurationException excLine(String msg) { + return new ConfigurationException(msg + ", line " + st.lineno()); + } + + private void parse() throws IOException { + while (true) { + int token = nextToken(); + if (token == TT_EOF) { + break; + } + if (token == TT_EOL) { + continue; + } + if (token != TT_WORD) { + throw excToken("Unexpected token:"); + } + String word = st.sval; + if (word.equals("name")) { + name = parseStringEntry(word); + } else if (word.equals("library")) { + library = parseLibrary(word); + } else if (word.equals("description")) { + parseDescription(word); + } else if (word.equals("slot")) { + parseSlotID(word); + } else if (word.equals("slotListIndex")) { + parseSlotListIndex(word); + } else if (word.equals("enabledMechanisms")) { + parseEnabledMechanisms(word); + } else if (word.equals("disabledMechanisms")) { + parseDisabledMechanisms(word); + } else if (word.equals("attributes")) { + parseAttributes(word); + } else if (word.equals("handleStartupErrors")) { + parseHandleStartupErrors(word); + } else if (word.endsWith("insertionCheckInterval")) { + insertionCheckInterval = parseIntegerEntry(word); + if (insertionCheckInterval < 100) { + throw excLine(word + " must be at least 100 ms"); + } + } else if (word.equals("showInfo")) { + showInfo = parseBooleanEntry(word); + } else if (word.equals("keyStoreCompatibilityMode")) { + keyStoreCompatibilityMode = parseBooleanEntry(word); + } else if (word.equals("explicitCancel")) { + explicitCancel = parseBooleanEntry(word); + } else if (word.equals("omitInitialize")) { + omitInitialize = parseBooleanEntry(word); + } else if (word.equals("allowSingleThreadedModules")) { + allowSingleThreadedModules = parseBooleanEntry(word); + } else if (word.equals("functionList")) { + functionList = parseStringEntry(word); + } else if (word.equals("nssUseSecmod")) { + nssUseSecmod = parseBooleanEntry(word); + } else if (word.equals("nssLibraryDirectory")) { + nssLibraryDirectory = parseLibrary(word); + nssUseSecmod = true; + } else if (word.equals("nssSecmodDirectory")) { + nssSecmodDirectory = expand(parseStringEntry(word)); + nssUseSecmod = true; + } else if (word.equals("nssModule")) { + nssModule = parseStringEntry(word); + nssUseSecmod = true; + } else if (word.equals("nssDbMode")) { + String mode = parseStringEntry(word); + if (mode.equals("readWrite")) { + nssDbMode = Secmod.DbMode.READ_WRITE; + } else if (mode.equals("readOnly")) { + nssDbMode = Secmod.DbMode.READ_ONLY; + } else if (mode.equals("noDb")) { + nssDbMode = Secmod.DbMode.NO_DB; + } else { + throw excToken("nssDbMode must be one of readWrite, readOnly, and noDb:"); + } + nssUseSecmod = true; + } else if (word.equals("nssNetscapeDbWorkaround")) { + nssNetscapeDbWorkaround = parseBooleanEntry(word); + nssUseSecmod = true; + } else if (word.equals("nssArgs")) { + parseNSSArgs(word); + } else if (word.equals("nssUseSecmodTrust")) { + nssUseSecmodTrust = parseBooleanEntry(word); + } else if (word.equals("useEcX963Encoding")) { + useEcX963Encoding = parseBooleanEntry(word); + } else if (word.equals("nssOptimizeSpace")) { + nssOptimizeSpace = parseBooleanEntry(word); + } else { + throw new ConfigurationException + ("Unknown keyword '" + word + "', line " + st.lineno()); + } + parsedKeywords.add(word); + } + reader.close(); + reader = null; + st = null; + parsedKeywords = null; + if (name == null) { + throw new ConfigurationException("name must be specified"); + } + if (nssUseSecmod == false) { + if (library == null) { + throw new ConfigurationException("library must be specified"); + } + } else { + if (library != null) { + throw new ConfigurationException + ("library must not be specified in NSS mode"); + } + if ((slotID != -1) || (slotListIndex != -1)) { + throw new ConfigurationException + ("slot and slotListIndex must not be specified in NSS mode"); + } + if (nssArgs != null) { + throw new ConfigurationException + ("nssArgs must not be specified in NSS mode"); + } + if (nssUseSecmodTrust != false) { + throw new ConfigurationException("nssUseSecmodTrust is an " + + "internal option and must not be specified in NSS mode"); + } + } + } + + // + // Parsing helper methods + // + + private int nextToken() throws IOException { + int token = st.nextToken(); + debug(st); + return token; + } + + private void parseEquals() throws IOException { + int token = nextToken(); + if (token != '=') { + throw excToken("Expected '=', read"); + } + } + + private void parseOpenBraces() throws IOException { + while (true) { + int token = nextToken(); + if (token == TT_EOL) { + 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(); + switch (val) { + case "true": + return true; + case "false": + return false; + default: + throw excToken("Expected boolean value, read:"); + } + } + + private String parseLine() throws IOException { + // allow quoted string as part of line + String s = null; + while (true) { + int token = nextToken(); + if ((token == TT_EOL) || (token == TT_EOF)) { + break; + } + if (token != TT_WORD && token != '\"') { + throw excToken("Unexpected value"); + } + if (s == null) { + s = st.sval; + } else { + s = s + " " + st.sval; + } + } + if (s == null) { + throw excToken("Unexpected empty line"); + } + 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 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 parseMechanisms(String keyword) throws IOException { + checkDup(keyword); + Set mechs = new HashSet(); + 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 attributes = new ArrayList(); + 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(); + switch (op) { + case "*": + return TemplateManager.O_ANY; + case "generate": + return TemplateManager.O_GENERATE; + case "import": + return TemplateManager.O_IMPORT; + default: + 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 { + private static final long serialVersionUID = 254492758807673194L; + ConfigurationException(String msg) { + super(msg); + } +}