0N/A/*
4320N/A * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage sun.security.pkcs11;
0N/A
0N/Aimport java.io.*;
0N/Aimport static java.io.StreamTokenizer.*;
0N/Aimport java.math.BigInteger;
0N/Aimport java.util.*;
0N/A
0N/Aimport java.security.*;
0N/A
0N/Aimport sun.security.action.GetPropertyAction;
0N/Aimport sun.security.util.PropertyExpander;
0N/A
0N/Aimport sun.security.pkcs11.wrapper.*;
0N/Aimport static sun.security.pkcs11.wrapper.PKCS11Constants.*;
0N/Aimport static sun.security.pkcs11.wrapper.CK_ATTRIBUTE.*;
0N/A
0N/Aimport static sun.security.pkcs11.TemplateManager.*;
0N/A
0N/A/**
0N/A * Configuration container and file parsing.
0N/A *
0N/A * @author Andreas Sterbenz
0N/A * @since 1.5
0N/A */
0N/Afinal class Config {
0N/A
0N/A static final int ERR_HALT = 1;
0N/A static final int ERR_IGNORE_ALL = 2;
0N/A static final int ERR_IGNORE_LIB = 3;
0N/A
0N/A // same as allowSingleThreadedModules but controlled via a system property
0N/A // and applied to all providers. if set to false, no SunPKCS11 instances
0N/A // will accept single threaded modules regardless of the setting in their
0N/A // config files.
0N/A private static final boolean staticAllowSingleThreadedModules;
0N/A
0N/A static {
0N/A String p = "sun.security.pkcs11.allowSingleThreadedModules";
0N/A String s = AccessController.doPrivileged(new GetPropertyAction(p));
0N/A if ("false".equalsIgnoreCase(s)) {
0N/A staticAllowSingleThreadedModules = false;
0N/A } else {
0N/A staticAllowSingleThreadedModules = true;
0N/A }
0N/A }
0N/A
0N/A // temporary storage for configurations
0N/A // needed because the SunPKCS11 needs to call the superclass constructor
0N/A // in provider before accessing any instance variables
0N/A private final static Map<String,Config> configMap =
0N/A new HashMap<String,Config>();
0N/A
0N/A static Config getConfig(final String name, final InputStream stream) {
0N/A Config config = configMap.get(name);
0N/A if (config != null) {
0N/A return config;
0N/A }
0N/A try {
0N/A config = new Config(name, stream);
0N/A configMap.put(name, config);
0N/A return config;
0N/A } catch (Exception e) {
0N/A throw new ProviderException("Error parsing configuration", e);
0N/A }
0N/A }
0N/A
0N/A static Config removeConfig(String name) {
0N/A return configMap.remove(name);
0N/A }
0N/A
0N/A private final static boolean DEBUG = false;
0N/A
0N/A private static void debug(Object o) {
0N/A if (DEBUG) {
0N/A System.out.println(o);
0N/A }
0N/A }
0N/A
0N/A // Reader and StringTokenizer used during parsing
0N/A private Reader reader;
0N/A
0N/A private StreamTokenizer st;
0N/A
0N/A private Set<String> parsedKeywords;
0N/A
0N/A // name suffix of the provider
0N/A private String name;
0N/A
0N/A // name of the PKCS#11 library
0N/A private String library;
0N/A
0N/A // description to pass to the provider class
0N/A private String description;
0N/A
0N/A // slotID of the slot to use
0N/A private int slotID = -1;
0N/A
0N/A // slot to use, specified as index in the slotlist
0N/A private int slotListIndex = -1;
0N/A
0N/A // set of enabled mechanisms (or null to use default)
0N/A private Set<Long> enabledMechanisms;
0N/A
0N/A // set of disabled mechanisms
0N/A private Set<Long> disabledMechanisms;
0N/A
0N/A // whether to print debug info during startup
0N/A private boolean showInfo = false;
0N/A
0N/A // template manager, initialized from parsed attributes
0N/A private TemplateManager templateManager;
0N/A
0N/A // how to handle error during startup, one of ERR_
0N/A private int handleStartupErrors = ERR_HALT;
0N/A
0N/A // flag indicating whether the P11KeyStore should
0N/A // be more tolerant of input parameters
0N/A private boolean keyStoreCompatibilityMode = true;
0N/A
0N/A // flag indicating whether we need to explicitly cancel operations
0N/A // see Token
0N/A private boolean explicitCancel = true;
0N/A
0N/A // how often to test for token insertion, if no token is present
0N/A private int insertionCheckInterval = 2000;
0N/A
0N/A // flag inidicating whether to omit the call to C_Initialize()
0N/A // should be used only if we are running within a process that
0N/A // has already called it (e.g. Plugin inside of Mozilla/NSS)
0N/A private boolean omitInitialize = false;
0N/A
0N/A // whether to allow modules that only support single threaded access.
0N/A // they cannot be used safely from multiple PKCS#11 consumers in the
0N/A // same process, for example NSS and SunPKCS11
0N/A private boolean allowSingleThreadedModules = true;
0N/A
0N/A // name of the C function that returns the PKCS#11 functionlist
0N/A // This option primarily exists for the deprecated
0N/A // Secmod.Module.getProvider() method.
0N/A private String functionList = "C_GetFunctionList";
0N/A
0N/A // whether to use NSS secmod mode. Implicitly set if nssLibraryDirectory,
0N/A // nssSecmodDirectory, or nssModule is specified.
0N/A private boolean nssUseSecmod;
0N/A
0N/A // location of the NSS library files (libnss3.so, etc.)
0N/A private String nssLibraryDirectory;
0N/A
0N/A // location of secmod.db
0N/A private String nssSecmodDirectory;
0N/A
0N/A // which NSS module to use
0N/A private String nssModule;
0N/A
0N/A private Secmod.DbMode nssDbMode = Secmod.DbMode.READ_WRITE;
0N/A
0N/A // Whether the P11KeyStore should specify the CKA_NETSCAPE_DB attribute
0N/A // when creating private keys. Only valid if nssUseSecmod is true.
0N/A private boolean nssNetscapeDbWorkaround = true;
0N/A
0N/A // Special init argument string for the NSS softtoken.
0N/A // This is used when using the NSS softtoken directly without secmod mode.
0N/A private String nssArgs;
0N/A
0N/A // whether to use NSS trust attributes for the KeyStore of this provider
0N/A // this option is for internal use by the SunPKCS11 code only and
0N/A // works only for NSS providers created via the Secmod API
0N/A private boolean nssUseSecmodTrust = false;
0N/A
4426N/A // Flag to indicate whether the X9.63 encoding for EC points shall be used
4426N/A // (true) or whether that encoding shall be wrapped in an ASN.1 OctetString
4426N/A // (false).
4426N/A private boolean useEcX963Encoding = false;
4426N/A
0N/A private Config(String filename, InputStream in) throws IOException {
0N/A if (in == null) {
0N/A if (filename.startsWith("--")) {
0N/A // inline config
0N/A String config = filename.substring(2).replace("\\n", "\n");
0N/A reader = new StringReader(config);
0N/A } else {
0N/A in = new FileInputStream(expand(filename));
0N/A }
0N/A }
0N/A if (reader == null) {
0N/A reader = new BufferedReader(new InputStreamReader(in));
0N/A }
0N/A parsedKeywords = new HashSet<String>();
0N/A st = new StreamTokenizer(reader);
0N/A setupTokenizer();
0N/A parse();
0N/A }
0N/A
0N/A String getName() {
0N/A return name;
0N/A }
0N/A
0N/A String getLibrary() {
0N/A return library;
0N/A }
0N/A
0N/A String getDescription() {
0N/A if (description != null) {
0N/A return description;
0N/A }
0N/A return "SunPKCS11-" + name + " using library " + library;
0N/A }
0N/A
0N/A int getSlotID() {
0N/A return slotID;
0N/A }
0N/A
0N/A int getSlotListIndex() {
0N/A if ((slotID == -1) && (slotListIndex == -1)) {
0N/A // if neither is set, default to first slot
0N/A return 0;
0N/A } else {
0N/A return slotListIndex;
0N/A }
0N/A }
0N/A
0N/A boolean getShowInfo() {
0N/A return (SunPKCS11.debug != null) || showInfo;
0N/A }
0N/A
0N/A TemplateManager getTemplateManager() {
0N/A if (templateManager == null) {
0N/A templateManager = new TemplateManager();
0N/A }
0N/A return templateManager;
0N/A }
0N/A
0N/A boolean isEnabled(long m) {
0N/A if (enabledMechanisms != null) {
0N/A return enabledMechanisms.contains(Long.valueOf(m));
0N/A }
0N/A if (disabledMechanisms != null) {
0N/A return !disabledMechanisms.contains(Long.valueOf(m));
0N/A }
0N/A return true;
0N/A }
0N/A
0N/A int getHandleStartupErrors() {
0N/A return handleStartupErrors;
0N/A }
0N/A
0N/A boolean getKeyStoreCompatibilityMode() {
0N/A return keyStoreCompatibilityMode;
0N/A }
0N/A
0N/A boolean getExplicitCancel() {
0N/A return explicitCancel;
0N/A }
0N/A
0N/A int getInsertionCheckInterval() {
0N/A return insertionCheckInterval;
0N/A }
0N/A
0N/A boolean getOmitInitialize() {
0N/A return omitInitialize;
0N/A }
0N/A
0N/A boolean getAllowSingleThreadedModules() {
0N/A return staticAllowSingleThreadedModules && allowSingleThreadedModules;
0N/A }
0N/A
0N/A String getFunctionList() {
0N/A return functionList;
0N/A }
0N/A
0N/A boolean getNssUseSecmod() {
0N/A return nssUseSecmod;
0N/A }
0N/A
0N/A String getNssLibraryDirectory() {
0N/A return nssLibraryDirectory;
0N/A }
0N/A
0N/A String getNssSecmodDirectory() {
0N/A return nssSecmodDirectory;
0N/A }
0N/A
0N/A String getNssModule() {
0N/A return nssModule;
0N/A }
0N/A
0N/A Secmod.DbMode getNssDbMode() {
0N/A return nssDbMode;
0N/A }
0N/A
0N/A public boolean getNssNetscapeDbWorkaround() {
0N/A return nssUseSecmod && nssNetscapeDbWorkaround;
0N/A }
0N/A
0N/A String getNssArgs() {
0N/A return nssArgs;
0N/A }
0N/A
0N/A boolean getNssUseSecmodTrust() {
0N/A return nssUseSecmodTrust;
0N/A }
0N/A
4426N/A boolean getUseEcX963Encoding() {
4426N/A return useEcX963Encoding;
4426N/A }
4426N/A
0N/A private static String expand(final String s) throws IOException {
0N/A try {
0N/A return PropertyExpander.expand(s);
0N/A } catch (Exception e) {
0N/A throw new RuntimeException(e.getMessage());
0N/A }
0N/A }
0N/A
0N/A private void setupTokenizer() {
0N/A st.resetSyntax();
0N/A st.wordChars('a', 'z');
0N/A st.wordChars('A', 'Z');
0N/A st.wordChars('0', '9');
0N/A st.wordChars(':', ':');
0N/A st.wordChars('.', '.');
0N/A st.wordChars('_', '_');
0N/A st.wordChars('-', '-');
0N/A st.wordChars('/', '/');
0N/A st.wordChars('\\', '\\');
0N/A st.wordChars('$', '$');
0N/A st.wordChars('{', '{'); // need {} for property subst
0N/A st.wordChars('}', '}');
0N/A st.wordChars('*', '*');
4003N/A st.wordChars('+', '+');
3328N/A st.wordChars('~', '~');
0N/A // XXX check ASCII table and add all other characters except special
0N/A
0N/A // special: #="(),
0N/A st.whitespaceChars(0, ' ');
0N/A st.commentChar('#');
0N/A st.eolIsSignificant(true);
0N/A st.quoteChar('\"');
0N/A }
0N/A
0N/A private ConfigurationException excToken(String msg) {
0N/A return new ConfigurationException(msg + " " + st);
0N/A }
0N/A
0N/A private ConfigurationException excLine(String msg) {
0N/A return new ConfigurationException(msg + ", line " + st.lineno());
0N/A }
0N/A
0N/A private void parse() throws IOException {
0N/A while (true) {
0N/A int token = nextToken();
0N/A if (token == TT_EOF) {
0N/A break;
0N/A }
0N/A if (token == TT_EOL) {
0N/A continue;
0N/A }
0N/A if (token != TT_WORD) {
0N/A throw excToken("Unexpected token:");
0N/A }
0N/A String word = st.sval;
0N/A if (word.equals("name")) {
0N/A name = parseStringEntry(word);
0N/A } else if (word.equals("library")) {
0N/A library = parseLibrary(word);
0N/A } else if (word.equals("description")) {
0N/A parseDescription(word);
0N/A } else if (word.equals("slot")) {
0N/A parseSlotID(word);
0N/A } else if (word.equals("slotListIndex")) {
0N/A parseSlotListIndex(word);
0N/A } else if (word.equals("enabledMechanisms")) {
0N/A parseEnabledMechanisms(word);
0N/A } else if (word.equals("disabledMechanisms")) {
0N/A parseDisabledMechanisms(word);
0N/A } else if (word.equals("attributes")) {
0N/A parseAttributes(word);
0N/A } else if (word.equals("handleStartupErrors")) {
0N/A parseHandleStartupErrors(word);
0N/A } else if (word.endsWith("insertionCheckInterval")) {
0N/A insertionCheckInterval = parseIntegerEntry(word);
0N/A if (insertionCheckInterval < 100) {
0N/A throw excLine(word + " must be at least 100 ms");
0N/A }
0N/A } else if (word.equals("showInfo")) {
0N/A showInfo = parseBooleanEntry(word);
0N/A } else if (word.equals("keyStoreCompatibilityMode")) {
0N/A keyStoreCompatibilityMode = parseBooleanEntry(word);
0N/A } else if (word.equals("explicitCancel")) {
0N/A explicitCancel = parseBooleanEntry(word);
0N/A } else if (word.equals("omitInitialize")) {
0N/A omitInitialize = parseBooleanEntry(word);
0N/A } else if (word.equals("allowSingleThreadedModules")) {
0N/A allowSingleThreadedModules = parseBooleanEntry(word);
0N/A } else if (word.equals("functionList")) {
0N/A functionList = parseStringEntry(word);
0N/A } else if (word.equals("nssUseSecmod")) {
0N/A nssUseSecmod = parseBooleanEntry(word);
0N/A } else if (word.equals("nssLibraryDirectory")) {
0N/A nssLibraryDirectory = parseLibrary(word);
0N/A nssUseSecmod = true;
0N/A } else if (word.equals("nssSecmodDirectory")) {
0N/A nssSecmodDirectory = expand(parseStringEntry(word));
0N/A nssUseSecmod = true;
0N/A } else if (word.equals("nssModule")) {
0N/A nssModule = parseStringEntry(word);
0N/A nssUseSecmod = true;
0N/A } else if (word.equals("nssDbMode")) {
0N/A String mode = parseStringEntry(word);
0N/A if (mode.equals("readWrite")) {
0N/A nssDbMode = Secmod.DbMode.READ_WRITE;
0N/A } else if (mode.equals("readOnly")) {
0N/A nssDbMode = Secmod.DbMode.READ_ONLY;
0N/A } else if (mode.equals("noDb")) {
0N/A nssDbMode = Secmod.DbMode.NO_DB;
0N/A } else {
0N/A throw excToken("nssDbMode must be one of readWrite, readOnly, and noDb:");
0N/A }
0N/A nssUseSecmod = true;
0N/A } else if (word.equals("nssNetscapeDbWorkaround")) {
0N/A nssNetscapeDbWorkaround = parseBooleanEntry(word);
0N/A nssUseSecmod = true;
0N/A } else if (word.equals("nssArgs")) {
0N/A parseNSSArgs(word);
0N/A } else if (word.equals("nssUseSecmodTrust")) {
0N/A nssUseSecmodTrust = parseBooleanEntry(word);
4426N/A } else if (word.equals("useEcX963Encoding")) {
4426N/A useEcX963Encoding = parseBooleanEntry(word);
0N/A } else {
0N/A throw new ConfigurationException
0N/A ("Unknown keyword '" + word + "', line " + st.lineno());
0N/A }
0N/A parsedKeywords.add(word);
0N/A }
0N/A reader.close();
0N/A reader = null;
0N/A st = null;
0N/A parsedKeywords = null;
0N/A if (name == null) {
0N/A throw new ConfigurationException("name must be specified");
0N/A }
0N/A if (nssUseSecmod == false) {
0N/A if (library == null) {
0N/A throw new ConfigurationException("library must be specified");
0N/A }
0N/A } else {
0N/A if (library != null) {
0N/A throw new ConfigurationException
0N/A ("library must not be specified in NSS mode");
0N/A }
0N/A if ((slotID != -1) || (slotListIndex != -1)) {
0N/A throw new ConfigurationException
0N/A ("slot and slotListIndex must not be specified in NSS mode");
0N/A }
0N/A if (nssArgs != null) {
0N/A throw new ConfigurationException
0N/A ("nssArgs must not be specified in NSS mode");
0N/A }
0N/A if (nssUseSecmodTrust != false) {
0N/A throw new ConfigurationException("nssUseSecmodTrust is an "
0N/A + "internal option and must not be specified in NSS mode");
0N/A }
0N/A }
0N/A }
0N/A
0N/A //
0N/A // Parsing helper methods
0N/A //
0N/A
0N/A private int nextToken() throws IOException {
0N/A int token = st.nextToken();
0N/A debug(st);
0N/A return token;
0N/A }
0N/A
0N/A private void parseEquals() throws IOException {
0N/A int token = nextToken();
0N/A if (token != '=') {
0N/A throw excToken("Expected '=', read");
0N/A }
0N/A }
0N/A
0N/A private void parseOpenBraces() throws IOException {
0N/A while (true) {
0N/A int token = nextToken();
0N/A if (token == TT_EOL) {
0N/A continue;
0N/A }
0N/A if ((token == TT_WORD) && st.sval.equals("{")) {
0N/A return;
0N/A }
0N/A throw excToken("Expected '{', read");
0N/A }
0N/A }
0N/A
0N/A private boolean isCloseBraces(int token) {
0N/A return (token == TT_WORD) && st.sval.equals("}");
0N/A }
0N/A
0N/A private String parseWord() throws IOException {
0N/A int token = nextToken();
0N/A if (token != TT_WORD) {
0N/A throw excToken("Unexpected value:");
0N/A }
0N/A return st.sval;
0N/A }
0N/A
0N/A private String parseStringEntry(String keyword) throws IOException {
0N/A checkDup(keyword);
0N/A parseEquals();
0N/A
0N/A int token = nextToken();
0N/A if (token != TT_WORD && token != '\"') {
0N/A // not a word token nor a string enclosed by double quotes
0N/A throw excToken("Unexpected value:");
0N/A }
0N/A String value = st.sval;
0N/A
0N/A debug(keyword + ": " + value);
0N/A return value;
0N/A }
0N/A
0N/A private boolean parseBooleanEntry(String keyword) throws IOException {
0N/A checkDup(keyword);
0N/A parseEquals();
0N/A boolean value = parseBoolean();
0N/A debug(keyword + ": " + value);
0N/A return value;
0N/A }
0N/A
0N/A private int parseIntegerEntry(String keyword) throws IOException {
0N/A checkDup(keyword);
0N/A parseEquals();
0N/A int value = decodeNumber(parseWord());
0N/A debug(keyword + ": " + value);
0N/A return value;
0N/A }
0N/A
0N/A private boolean parseBoolean() throws IOException {
0N/A String val = parseWord();
0N/A if (val.equals("true")) {
0N/A return true;
0N/A } else if (val.equals("false")) {
0N/A return false;
0N/A } else {
0N/A throw excToken("Expected boolean value, read:");
0N/A }
0N/A }
0N/A
0N/A private String parseLine() throws IOException {
0N/A String s = parseWord();
0N/A while (true) {
0N/A int token = nextToken();
0N/A if ((token == TT_EOL) || (token == TT_EOF)) {
0N/A break;
0N/A }
0N/A if (token != TT_WORD) {
0N/A throw excToken("Unexpected value");
0N/A }
0N/A s = s + " " + st.sval;
0N/A }
0N/A return s;
0N/A }
0N/A
0N/A private int decodeNumber(String str) throws IOException {
0N/A try {
0N/A if (str.startsWith("0x") || str.startsWith("0X")) {
0N/A return Integer.parseInt(str.substring(2), 16);
0N/A } else {
0N/A return Integer.parseInt(str);
0N/A }
0N/A } catch (NumberFormatException e) {
0N/A throw excToken("Expected number, read");
0N/A }
0N/A }
0N/A
0N/A private static boolean isNumber(String s) {
0N/A if (s.length() == 0) {
0N/A return false;
0N/A }
0N/A char ch = s.charAt(0);
0N/A return ((ch >= '0') && (ch <= '9'));
0N/A }
0N/A
0N/A private void parseComma() throws IOException {
0N/A int token = nextToken();
0N/A if (token != ',') {
0N/A throw excToken("Expected ',', read");
0N/A }
0N/A }
0N/A
0N/A private static boolean isByteArray(String val) {
0N/A return val.startsWith("0h");
0N/A }
0N/A
0N/A private byte[] decodeByteArray(String str) throws IOException {
0N/A if (str.startsWith("0h") == false) {
0N/A throw excToken("Expected byte array value, read");
0N/A }
0N/A str = str.substring(2);
0N/A // XXX proper hex parsing
0N/A try {
0N/A return new BigInteger(str, 16).toByteArray();
0N/A } catch (NumberFormatException e) {
0N/A throw excToken("Expected byte array value, read");
0N/A }
0N/A }
0N/A
0N/A private void checkDup(String keyword) throws IOException {
0N/A if (parsedKeywords.contains(keyword)) {
0N/A throw excLine(keyword + " must only be specified once");
0N/A }
0N/A }
0N/A
0N/A //
0N/A // individual entry parsing methods
0N/A //
0N/A
0N/A private String parseLibrary(String keyword) throws IOException {
0N/A checkDup(keyword);
0N/A parseEquals();
0N/A String lib = parseLine();
0N/A lib = expand(lib);
0N/A int i = lib.indexOf("/$ISA/");
0N/A if (i != -1) {
0N/A // replace "/$ISA/" with "/sparcv9/" on 64-bit Solaris SPARC
0N/A // and with "/amd64/" on Solaris AMD64.
0N/A // On all other platforms, just turn it into a "/"
0N/A String osName = System.getProperty("os.name", "");
0N/A String osArch = System.getProperty("os.arch", "");
0N/A String prefix = lib.substring(0, i);
0N/A String suffix = lib.substring(i + 5);
0N/A if (osName.equals("SunOS") && osArch.equals("sparcv9")) {
0N/A lib = prefix + "/sparcv9" + suffix;
0N/A } else if (osName.equals("SunOS") && osArch.equals("amd64")) {
0N/A lib = prefix + "/amd64" + suffix;
0N/A } else {
0N/A lib = prefix + suffix;
0N/A }
0N/A }
0N/A debug(keyword + ": " + lib);
4320N/A
4320N/A // Check to see if full path is specified to prevent the DLL
4320N/A // preloading attack
4320N/A if (!(new File(lib)).isAbsolute()) {
4320N/A throw new ConfigurationException(
4320N/A "Absolute path required for library value: " + lib);
4320N/A }
0N/A return lib;
0N/A }
0N/A
0N/A private void parseDescription(String keyword) throws IOException {
0N/A checkDup(keyword);
0N/A parseEquals();
0N/A description = parseLine();
0N/A debug("description: " + description);
0N/A }
0N/A
0N/A private void parseSlotID(String keyword) throws IOException {
0N/A if (slotID >= 0) {
0N/A throw excLine("Duplicate slot definition");
0N/A }
0N/A if (slotListIndex >= 0) {
0N/A throw excLine
0N/A ("Only one of slot and slotListIndex must be specified");
0N/A }
0N/A parseEquals();
0N/A String slotString = parseWord();
0N/A slotID = decodeNumber(slotString);
0N/A debug("slot: " + slotID);
0N/A }
0N/A
0N/A private void parseSlotListIndex(String keyword) throws IOException {
0N/A if (slotListIndex >= 0) {
0N/A throw excLine("Duplicate slotListIndex definition");
0N/A }
0N/A if (slotID >= 0) {
0N/A throw excLine
0N/A ("Only one of slot and slotListIndex must be specified");
0N/A }
0N/A parseEquals();
0N/A String slotString = parseWord();
0N/A slotListIndex = decodeNumber(slotString);
0N/A debug("slotListIndex: " + slotListIndex);
0N/A }
0N/A
0N/A private void parseEnabledMechanisms(String keyword) throws IOException {
0N/A enabledMechanisms = parseMechanisms(keyword);
0N/A }
0N/A
0N/A private void parseDisabledMechanisms(String keyword) throws IOException {
0N/A disabledMechanisms = parseMechanisms(keyword);
0N/A }
0N/A
0N/A private Set<Long> parseMechanisms(String keyword) throws IOException {
0N/A checkDup(keyword);
0N/A Set<Long> mechs = new HashSet<Long>();
0N/A parseEquals();
0N/A parseOpenBraces();
0N/A while (true) {
0N/A int token = nextToken();
0N/A if (isCloseBraces(token)) {
0N/A break;
0N/A }
0N/A if (token == TT_EOL) {
0N/A continue;
0N/A }
0N/A if (token != TT_WORD) {
0N/A throw excToken("Expected mechanism, read");
0N/A }
0N/A long mech = parseMechanism(st.sval);
0N/A mechs.add(Long.valueOf(mech));
0N/A }
0N/A if (DEBUG) {
0N/A System.out.print("mechanisms: [");
0N/A for (Long mech : mechs) {
0N/A System.out.print(Functions.getMechanismName(mech));
0N/A System.out.print(", ");
0N/A }
0N/A System.out.println("]");
0N/A }
0N/A return mechs;
0N/A }
0N/A
0N/A private long parseMechanism(String mech) throws IOException {
0N/A if (isNumber(mech)) {
0N/A return decodeNumber(mech);
0N/A } else {
0N/A try {
0N/A return Functions.getMechanismId(mech);
0N/A } catch (IllegalArgumentException e) {
0N/A throw excLine("Unknown mechanism: " + mech);
0N/A }
0N/A }
0N/A }
0N/A
0N/A private void parseAttributes(String keyword) throws IOException {
0N/A if (templateManager == null) {
0N/A templateManager = new TemplateManager();
0N/A }
0N/A int token = nextToken();
0N/A if (token == '=') {
0N/A String s = parseWord();
0N/A if (s.equals("compatibility") == false) {
0N/A throw excLine("Expected 'compatibility', read " + s);
0N/A }
0N/A setCompatibilityAttributes();
0N/A return;
0N/A }
0N/A if (token != '(') {
0N/A throw excToken("Expected '(' or '=', read");
0N/A }
0N/A String op = parseOperation();
0N/A parseComma();
0N/A long objectClass = parseObjectClass();
0N/A parseComma();
0N/A long keyAlg = parseKeyAlgorithm();
0N/A token = nextToken();
0N/A if (token != ')') {
0N/A throw excToken("Expected ')', read");
0N/A }
0N/A parseEquals();
0N/A parseOpenBraces();
0N/A List<CK_ATTRIBUTE> attributes = new ArrayList<CK_ATTRIBUTE>();
0N/A while (true) {
0N/A token = nextToken();
0N/A if (isCloseBraces(token)) {
0N/A break;
0N/A }
0N/A if (token == TT_EOL) {
0N/A continue;
0N/A }
0N/A if (token != TT_WORD) {
0N/A throw excToken("Expected mechanism, read");
0N/A }
0N/A String attributeName = st.sval;
0N/A long attributeId = decodeAttributeName(attributeName);
0N/A parseEquals();
0N/A String attributeValue = parseWord();
0N/A attributes.add(decodeAttributeValue(attributeId, attributeValue));
0N/A }
0N/A templateManager.addTemplate
0N/A (op, objectClass, keyAlg, attributes.toArray(CK_A0));
0N/A }
0N/A
0N/A private void setCompatibilityAttributes() {
0N/A // all secret keys
0N/A templateManager.addTemplate(O_ANY, CKO_SECRET_KEY, PCKK_ANY,
0N/A new CK_ATTRIBUTE[] {
0N/A TOKEN_FALSE,
0N/A SENSITIVE_FALSE,
0N/A EXTRACTABLE_TRUE,
0N/A ENCRYPT_TRUE,
0N/A DECRYPT_TRUE,
0N/A WRAP_TRUE,
0N/A UNWRAP_TRUE,
0N/A });
0N/A
0N/A // generic secret keys are special
0N/A // They are used as MAC keys plus for the SSL/TLS (pre)master secrets
0N/A templateManager.addTemplate(O_ANY, CKO_SECRET_KEY, CKK_GENERIC_SECRET,
0N/A new CK_ATTRIBUTE[] {
0N/A SIGN_TRUE,
0N/A VERIFY_TRUE,
0N/A ENCRYPT_NULL,
0N/A DECRYPT_NULL,
0N/A WRAP_NULL,
0N/A UNWRAP_NULL,
0N/A DERIVE_TRUE,
0N/A });
0N/A
0N/A // all private and public keys
0N/A templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, PCKK_ANY,
0N/A new CK_ATTRIBUTE[] {
0N/A TOKEN_FALSE,
0N/A SENSITIVE_FALSE,
0N/A EXTRACTABLE_TRUE,
0N/A });
0N/A templateManager.addTemplate(O_ANY, CKO_PUBLIC_KEY, PCKK_ANY,
0N/A new CK_ATTRIBUTE[] {
0N/A TOKEN_FALSE,
0N/A });
0N/A
0N/A // additional attributes for RSA private keys
0N/A templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, CKK_RSA,
0N/A new CK_ATTRIBUTE[] {
0N/A DECRYPT_TRUE,
0N/A SIGN_TRUE,
0N/A SIGN_RECOVER_TRUE,
0N/A UNWRAP_TRUE,
0N/A });
0N/A // additional attributes for RSA public keys
0N/A templateManager.addTemplate(O_ANY, CKO_PUBLIC_KEY, CKK_RSA,
0N/A new CK_ATTRIBUTE[] {
0N/A ENCRYPT_TRUE,
0N/A VERIFY_TRUE,
0N/A VERIFY_RECOVER_TRUE,
0N/A WRAP_TRUE,
0N/A });
0N/A
0N/A // additional attributes for DSA private keys
0N/A templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, CKK_DSA,
0N/A new CK_ATTRIBUTE[] {
0N/A SIGN_TRUE,
0N/A });
0N/A // additional attributes for DSA public keys
0N/A templateManager.addTemplate(O_ANY, CKO_PUBLIC_KEY, CKK_DSA,
0N/A new CK_ATTRIBUTE[] {
0N/A VERIFY_TRUE,
0N/A });
0N/A
0N/A // additional attributes for DH private keys
0N/A templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, CKK_DH,
0N/A new CK_ATTRIBUTE[] {
0N/A DERIVE_TRUE,
0N/A });
0N/A
0N/A // additional attributes for EC private keys
0N/A templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, CKK_EC,
0N/A new CK_ATTRIBUTE[] {
0N/A SIGN_TRUE,
0N/A DERIVE_TRUE,
0N/A });
0N/A // additional attributes for EC public keys
0N/A templateManager.addTemplate(O_ANY, CKO_PUBLIC_KEY, CKK_EC,
0N/A new CK_ATTRIBUTE[] {
0N/A VERIFY_TRUE,
0N/A });
0N/A }
0N/A
0N/A private final static CK_ATTRIBUTE[] CK_A0 = new CK_ATTRIBUTE[0];
0N/A
0N/A private String parseOperation() throws IOException {
0N/A String op = parseWord();
0N/A if (op.equals("*")) {
0N/A return TemplateManager.O_ANY;
0N/A } else if (op.equals("generate")) {
0N/A return TemplateManager.O_GENERATE;
0N/A } else if (op.equals("import")) {
0N/A return TemplateManager.O_IMPORT;
0N/A } else {
0N/A throw excLine("Unknown operation " + op);
0N/A }
0N/A }
0N/A
0N/A private long parseObjectClass() throws IOException {
0N/A String name = parseWord();
0N/A try {
0N/A return Functions.getObjectClassId(name);
0N/A } catch (IllegalArgumentException e) {
0N/A throw excLine("Unknown object class " + name);
0N/A }
0N/A }
0N/A
0N/A private long parseKeyAlgorithm() throws IOException {
0N/A String name = parseWord();
0N/A if (isNumber(name)) {
0N/A return decodeNumber(name);
0N/A } else {
0N/A try {
0N/A return Functions.getKeyId(name);
0N/A } catch (IllegalArgumentException e) {
0N/A throw excLine("Unknown key algorithm " + name);
0N/A }
0N/A }
0N/A }
0N/A
0N/A private long decodeAttributeName(String name) throws IOException {
0N/A if (isNumber(name)) {
0N/A return decodeNumber(name);
0N/A } else {
0N/A try {
0N/A return Functions.getAttributeId(name);
0N/A } catch (IllegalArgumentException e) {
0N/A throw excLine("Unknown attribute name " + name);
0N/A }
0N/A }
0N/A }
0N/A
0N/A private CK_ATTRIBUTE decodeAttributeValue(long id, String value)
0N/A throws IOException {
0N/A if (value.equals("null")) {
0N/A return new CK_ATTRIBUTE(id);
0N/A } else if (value.equals("true")) {
0N/A return new CK_ATTRIBUTE(id, true);
0N/A } else if (value.equals("false")) {
0N/A return new CK_ATTRIBUTE(id, false);
0N/A } else if (isByteArray(value)) {
0N/A return new CK_ATTRIBUTE(id, decodeByteArray(value));
0N/A } else if (isNumber(value)) {
0N/A return new CK_ATTRIBUTE(id, Integer.valueOf(decodeNumber(value)));
0N/A } else {
0N/A throw excLine("Unknown attribute value " + value);
0N/A }
0N/A }
0N/A
0N/A private void parseNSSArgs(String keyword) throws IOException {
0N/A checkDup(keyword);
0N/A parseEquals();
0N/A int token = nextToken();
0N/A if (token != '"') {
0N/A throw excToken("Expected quoted string");
0N/A }
0N/A nssArgs = expand(st.sval);
0N/A debug("nssArgs: " + nssArgs);
0N/A }
0N/A
0N/A private void parseHandleStartupErrors(String keyword) throws IOException {
0N/A checkDup(keyword);
0N/A parseEquals();
0N/A String val = parseWord();
0N/A if (val.equals("ignoreAll")) {
0N/A handleStartupErrors = ERR_IGNORE_ALL;
0N/A } else if (val.equals("ignoreMissingLibrary")) {
0N/A handleStartupErrors = ERR_IGNORE_LIB;
0N/A } else if (val.equals("halt")) {
0N/A handleStartupErrors = ERR_HALT;
0N/A } else {
0N/A throw excToken("Invalid value for handleStartupErrors:");
0N/A }
0N/A debug("handleStartupErrors: " + handleStartupErrors);
0N/A }
0N/A
0N/A}
0N/A
0N/Aclass ConfigurationException extends IOException {
0N/A ConfigurationException(String msg) {
0N/A super(msg);
0N/A }
0N/A}