Path: blob/master/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java
41154 views
/*1* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.security.pkcs11;2627import java.io.*;28import static java.io.StreamTokenizer.*;29import java.math.BigInteger;30import java.nio.charset.StandardCharsets;31import java.util.*;3233import java.security.*;3435import sun.security.util.PropertyExpander;3637import sun.security.pkcs11.wrapper.*;38import static sun.security.pkcs11.wrapper.PKCS11Constants.*;39import static sun.security.pkcs11.wrapper.CK_ATTRIBUTE.*;4041import static sun.security.pkcs11.TemplateManager.*;4243/**44* Configuration container and file parsing.45*46* @author Andreas Sterbenz47* @since 1.548*/49final class Config {5051static final int ERR_HALT = 1;52static final int ERR_IGNORE_ALL = 2;53static final int ERR_IGNORE_LIB = 3;5455// same as allowSingleThreadedModules but controlled via a system property56// and applied to all providers. if set to false, no SunPKCS11 instances57// will accept single threaded modules regardless of the setting in their58// config files.59private static final boolean staticAllowSingleThreadedModules;60private static final String osName;61private static final String osArch;6263static {64@SuppressWarnings("removal")65List<String> props = AccessController.doPrivileged(66new PrivilegedAction<>() {67@Override68public List<String> run() {69return List.of(70System.getProperty(71"sun.security.pkcs11.allowSingleThreadedModules",72"true"),73System.getProperty("os.name"),74System.getProperty("os.arch"));75}76}77);78if ("false".equalsIgnoreCase(props.get(0))) {79staticAllowSingleThreadedModules = false;80} else {81staticAllowSingleThreadedModules = true;82}83osName = props.get(1);84osArch = props.get(2);85}8687private static final boolean DEBUG = false;8889private static void debug(Object o) {90if (DEBUG) {91System.out.println(o);92}93}9495// file name containing this configuration96private String filename;9798// Reader and StringTokenizer used during parsing99private Reader reader;100101private StreamTokenizer st;102103private Set<String> parsedKeywords;104105// name suffix of the provider106private String name;107108// name of the PKCS#11 library109private String library;110111// description to pass to the provider class112private String description;113114// slotID of the slot to use115private int slotID = -1;116117// slot to use, specified as index in the slotlist118private int slotListIndex = -1;119120// set of enabled mechanisms (or null to use default)121private Set<Long> enabledMechanisms;122123// set of disabled mechanisms124private Set<Long> disabledMechanisms;125126// whether to print debug info during startup127private boolean showInfo = false;128129// template manager, initialized from parsed attributes130private TemplateManager templateManager;131132// how to handle error during startup, one of ERR_133private int handleStartupErrors = ERR_HALT;134135// flag indicating whether the P11KeyStore should136// be more tolerant of input parameters137private boolean keyStoreCompatibilityMode = true;138139// flag indicating whether we need to explicitly cancel operations140// see Token141private boolean explicitCancel = true;142143// how often to test for token insertion, if no token is present144private int insertionCheckInterval = 2000;145146// short ms value to indicate how often native cleaner thread is called147private int resourceCleanerShortInterval = 2_000;148// long ms value to indicate how often native cleaner thread is called149private int resourceCleanerLongInterval = 60_000;150151// should Token be destroyed after logout()152private boolean destroyTokenAfterLogout;153154// flag indicating whether to omit the call to C_Initialize()155// should be used only if we are running within a process that156// has already called it (e.g. Plugin inside of Mozilla/NSS)157private boolean omitInitialize = false;158159// whether to allow modules that only support single threaded access.160// they cannot be used safely from multiple PKCS#11 consumers in the161// same process, for example NSS and SunPKCS11162private boolean allowSingleThreadedModules = true;163164// name of the C function that returns the PKCS#11 functionlist165// This option primarily exists for the deprecated166// Secmod.Module.getProvider() method.167private String functionList = "C_GetFunctionList";168169// whether to use NSS secmod mode. Implicitly set if nssLibraryDirectory,170// nssSecmodDirectory, or nssModule is specified.171private boolean nssUseSecmod;172173// location of the NSS library files (libnss3.so, etc.)174private String nssLibraryDirectory;175176// location of secmod.db177private String nssSecmodDirectory;178179// which NSS module to use180private String nssModule;181182private Secmod.DbMode nssDbMode = Secmod.DbMode.READ_WRITE;183184// Whether the P11KeyStore should specify the CKA_NETSCAPE_DB attribute185// when creating private keys. Only valid if nssUseSecmod is true.186private boolean nssNetscapeDbWorkaround = true;187188// Special init argument string for the NSS softtoken.189// This is used when using the NSS softtoken directly without secmod mode.190private String nssArgs;191192// whether to use NSS trust attributes for the KeyStore of this provider193// this option is for internal use by the SunPKCS11 code only and194// works only for NSS providers created via the Secmod API195private boolean nssUseSecmodTrust = false;196197// Flag to indicate whether the X9.63 encoding for EC points shall be used198// (true) or whether that encoding shall be wrapped in an ASN.1 OctetString199// (false).200private boolean useEcX963Encoding = false;201202// Flag to indicate whether NSS should favour performance (false) or203// memory footprint (true).204private boolean nssOptimizeSpace = false;205206Config(String fn) throws IOException {207this.filename = fn;208if (filename.startsWith("--")) {209// inline config210String config = filename.substring(2).replace("\\n", "\n");211reader = new StringReader(config);212} else {213reader = new BufferedReader(new InputStreamReader214(new FileInputStream(expand(filename)),215StandardCharsets.ISO_8859_1));216}217parsedKeywords = new HashSet<String>();218st = new StreamTokenizer(reader);219setupTokenizer();220parse();221}222223String getFileName() {224return filename;225}226227String getName() {228return name;229}230231String getLibrary() {232return library;233}234235String getDescription() {236if (description != null) {237return description;238}239return "SunPKCS11-" + name + " using library " + library;240}241242int getSlotID() {243return slotID;244}245246int getSlotListIndex() {247if ((slotID == -1) && (slotListIndex == -1)) {248// if neither is set, default to first slot249return 0;250} else {251return slotListIndex;252}253}254255boolean getShowInfo() {256return (SunPKCS11.debug != null) || showInfo;257}258259TemplateManager getTemplateManager() {260if (templateManager == null) {261templateManager = new TemplateManager();262}263return templateManager;264}265266boolean isEnabled(long m) {267if (enabledMechanisms != null) {268return enabledMechanisms.contains(Long.valueOf(m));269}270if (disabledMechanisms != null) {271return !disabledMechanisms.contains(Long.valueOf(m));272}273return true;274}275276int getHandleStartupErrors() {277return handleStartupErrors;278}279280boolean getKeyStoreCompatibilityMode() {281return keyStoreCompatibilityMode;282}283284boolean getExplicitCancel() {285return explicitCancel;286}287288boolean getDestroyTokenAfterLogout() {289return destroyTokenAfterLogout;290}291292int getResourceCleanerShortInterval() {293return resourceCleanerShortInterval;294}295296int getResourceCleanerLongInterval() {297return resourceCleanerLongInterval;298}299300int getInsertionCheckInterval() {301return insertionCheckInterval;302}303304boolean getOmitInitialize() {305return omitInitialize;306}307308boolean getAllowSingleThreadedModules() {309return staticAllowSingleThreadedModules && allowSingleThreadedModules;310}311312String getFunctionList() {313return functionList;314}315316boolean getNssUseSecmod() {317return nssUseSecmod;318}319320String getNssLibraryDirectory() {321return nssLibraryDirectory;322}323324String getNssSecmodDirectory() {325return nssSecmodDirectory;326}327328String getNssModule() {329return nssModule;330}331332Secmod.DbMode getNssDbMode() {333return nssDbMode;334}335336public boolean getNssNetscapeDbWorkaround() {337return nssUseSecmod && nssNetscapeDbWorkaround;338}339340String getNssArgs() {341return nssArgs;342}343344boolean getNssUseSecmodTrust() {345return nssUseSecmodTrust;346}347348boolean getUseEcX963Encoding() {349return useEcX963Encoding;350}351352boolean getNssOptimizeSpace() {353return nssOptimizeSpace;354}355356private static String expand(final String s) throws IOException {357try {358return PropertyExpander.expand(s);359} catch (Exception e) {360throw new RuntimeException(e.getMessage());361}362}363364private void setupTokenizer() {365st.resetSyntax();366st.wordChars('a', 'z');367st.wordChars('A', 'Z');368st.wordChars('0', '9');369st.wordChars(':', ':');370st.wordChars('.', '.');371st.wordChars('_', '_');372st.wordChars('-', '-');373st.wordChars('/', '/');374st.wordChars('\\', '\\');375st.wordChars('$', '$');376st.wordChars('{', '{'); // need {} for property subst377st.wordChars('}', '}');378st.wordChars('*', '*');379st.wordChars('+', '+');380st.wordChars('~', '~');381// XXX check ASCII table and add all other characters except special382383// special: #="(),384st.whitespaceChars(0, ' ');385st.commentChar('#');386st.eolIsSignificant(true);387st.quoteChar('\"');388}389390private ConfigurationException excToken(String msg) {391return new ConfigurationException(msg + " " + st);392}393394private ConfigurationException excLine(String msg) {395return new ConfigurationException(msg + ", line " + st.lineno());396}397398private void parse() throws IOException {399while (true) {400int token = nextToken();401if (token == TT_EOF) {402break;403}404if (token == TT_EOL) {405continue;406}407if (token != TT_WORD) {408throw excToken("Unexpected token:");409}410String word = st.sval;411if (word.equals("name")) {412name = parseStringEntry(word);413} else if (word.equals("library")) {414library = parseLibrary(word);415} else if (word.equals("description")) {416parseDescription(word);417} else if (word.equals("slot")) {418parseSlotID(word);419} else if (word.equals("slotListIndex")) {420parseSlotListIndex(word);421} else if (word.equals("enabledMechanisms")) {422parseEnabledMechanisms(word);423} else if (word.equals("disabledMechanisms")) {424parseDisabledMechanisms(word);425} else if (word.equals("attributes")) {426parseAttributes(word);427} else if (word.equals("handleStartupErrors")) {428parseHandleStartupErrors(word);429} else if (word.endsWith("insertionCheckInterval")) {430insertionCheckInterval = parseIntegerEntry(word);431if (insertionCheckInterval < 100) {432throw excLine(word + " must be at least 100 ms");433}434} else if (word.equals("cleaner.shortInterval")) {435resourceCleanerShortInterval = parseIntegerEntry(word);436if (resourceCleanerShortInterval < 1_000) {437throw excLine(word + " must be at least 1000 ms");438}439} else if (word.equals("cleaner.longInterval")) {440resourceCleanerLongInterval = parseIntegerEntry(word);441if (resourceCleanerLongInterval < 1_000) {442throw excLine(word + " must be at least 1000 ms");443}444} else if (word.equals("destroyTokenAfterLogout")) {445destroyTokenAfterLogout = parseBooleanEntry(word);446} else if (word.equals("showInfo")) {447showInfo = parseBooleanEntry(word);448} else if (word.equals("keyStoreCompatibilityMode")) {449keyStoreCompatibilityMode = parseBooleanEntry(word);450} else if (word.equals("explicitCancel")) {451explicitCancel = parseBooleanEntry(word);452} else if (word.equals("omitInitialize")) {453omitInitialize = parseBooleanEntry(word);454} else if (word.equals("allowSingleThreadedModules")) {455allowSingleThreadedModules = parseBooleanEntry(word);456} else if (word.equals("functionList")) {457functionList = parseStringEntry(word);458} else if (word.equals("nssUseSecmod")) {459nssUseSecmod = parseBooleanEntry(word);460} else if (word.equals("nssLibraryDirectory")) {461nssLibraryDirectory = parseLibrary(word);462nssUseSecmod = true;463} else if (word.equals("nssSecmodDirectory")) {464nssSecmodDirectory = expand(parseStringEntry(word));465nssUseSecmod = true;466} else if (word.equals("nssModule")) {467nssModule = parseStringEntry(word);468nssUseSecmod = true;469} else if (word.equals("nssDbMode")) {470String mode = parseStringEntry(word);471if (mode.equals("readWrite")) {472nssDbMode = Secmod.DbMode.READ_WRITE;473} else if (mode.equals("readOnly")) {474nssDbMode = Secmod.DbMode.READ_ONLY;475} else if (mode.equals("noDb")) {476nssDbMode = Secmod.DbMode.NO_DB;477} else {478throw excToken("nssDbMode must be one of readWrite, readOnly, and noDb:");479}480nssUseSecmod = true;481} else if (word.equals("nssNetscapeDbWorkaround")) {482nssNetscapeDbWorkaround = parseBooleanEntry(word);483nssUseSecmod = true;484} else if (word.equals("nssArgs")) {485parseNSSArgs(word);486} else if (word.equals("nssUseSecmodTrust")) {487nssUseSecmodTrust = parseBooleanEntry(word);488} else if (word.equals("useEcX963Encoding")) {489useEcX963Encoding = parseBooleanEntry(word);490} else if (word.equals("nssOptimizeSpace")) {491nssOptimizeSpace = parseBooleanEntry(word);492} else {493throw new ConfigurationException494("Unknown keyword '" + word + "', line " + st.lineno());495}496parsedKeywords.add(word);497}498reader.close();499reader = null;500st = null;501parsedKeywords = null;502if (name == null) {503throw new ConfigurationException("name must be specified");504}505if (nssUseSecmod == false) {506if (library == null) {507throw new ConfigurationException("library must be specified");508}509} else {510if (library != null) {511throw new ConfigurationException512("library must not be specified in NSS mode");513}514if ((slotID != -1) || (slotListIndex != -1)) {515throw new ConfigurationException516("slot and slotListIndex must not be specified in NSS mode");517}518if (nssArgs != null) {519throw new ConfigurationException520("nssArgs must not be specified in NSS mode");521}522if (nssUseSecmodTrust != false) {523throw new ConfigurationException("nssUseSecmodTrust is an "524+ "internal option and must not be specified in NSS mode");525}526}527}528529//530// Parsing helper methods531//532533private int nextToken() throws IOException {534int token = st.nextToken();535debug(st);536return token;537}538539private void parseEquals() throws IOException {540int token = nextToken();541if (token != '=') {542throw excToken("Expected '=', read");543}544}545546private void parseOpenBraces() throws IOException {547while (true) {548int token = nextToken();549if (token == TT_EOL) {550continue;551}552if ((token == TT_WORD) && st.sval.equals("{")) {553return;554}555throw excToken("Expected '{', read");556}557}558559private boolean isCloseBraces(int token) {560return (token == TT_WORD) && st.sval.equals("}");561}562563private String parseWord() throws IOException {564int token = nextToken();565if (token != TT_WORD) {566throw excToken("Unexpected value:");567}568return st.sval;569}570571private String parseStringEntry(String keyword) throws IOException {572checkDup(keyword);573parseEquals();574575int token = nextToken();576if (token != TT_WORD && token != '\"') {577// not a word token nor a string enclosed by double quotes578throw excToken("Unexpected value:");579}580String value = st.sval;581582debug(keyword + ": " + value);583return value;584}585586private boolean parseBooleanEntry(String keyword) throws IOException {587checkDup(keyword);588parseEquals();589boolean value = parseBoolean();590debug(keyword + ": " + value);591return value;592}593594private int parseIntegerEntry(String keyword) throws IOException {595checkDup(keyword);596parseEquals();597int value = decodeNumber(parseWord());598debug(keyword + ": " + value);599return value;600}601602private boolean parseBoolean() throws IOException {603String val = parseWord();604switch (val) {605case "true":606return true;607case "false":608return false;609default:610throw excToken("Expected boolean value, read:");611}612}613614private String parseLine() throws IOException {615// allow quoted string as part of line616String s = null;617while (true) {618int token = nextToken();619if ((token == TT_EOL) || (token == TT_EOF)) {620break;621}622if (token != TT_WORD && token != '\"') {623throw excToken("Unexpected value");624}625if (s == null) {626s = st.sval;627} else {628s = s + " " + st.sval;629}630}631if (s == null) {632throw excToken("Unexpected empty line");633}634return s;635}636637private int decodeNumber(String str) throws IOException {638try {639if (str.startsWith("0x") || str.startsWith("0X")) {640return Integer.parseInt(str.substring(2), 16);641} else {642return Integer.parseInt(str);643}644} catch (NumberFormatException e) {645throw excToken("Expected number, read");646}647}648649private static boolean isNumber(String s) {650if (s.length() == 0) {651return false;652}653char ch = s.charAt(0);654return ((ch >= '0') && (ch <= '9'));655}656657private void parseComma() throws IOException {658int token = nextToken();659if (token != ',') {660throw excToken("Expected ',', read");661}662}663664private static boolean isByteArray(String val) {665return val.startsWith("0h");666}667668private byte[] decodeByteArray(String str) throws IOException {669if (str.startsWith("0h") == false) {670throw excToken("Expected byte array value, read");671}672str = str.substring(2);673// XXX proper hex parsing674try {675return new BigInteger(str, 16).toByteArray();676} catch (NumberFormatException e) {677throw excToken("Expected byte array value, read");678}679}680681private void checkDup(String keyword) throws IOException {682if (parsedKeywords.contains(keyword)) {683throw excLine(keyword + " must only be specified once");684}685}686687//688// individual entry parsing methods689//690691private String parseLibrary(String keyword) throws IOException {692checkDup(keyword);693parseEquals();694String lib = parseLine();695lib = expand(lib);696int i = lib.indexOf("/$ISA/");697if (i != -1) {698// replace "/$ISA/" with "/"699String prefix = lib.substring(0, i);700String suffix = lib.substring(i + 5);701lib = prefix + suffix;702}703debug(keyword + ": " + lib);704705// Check to see if full path is specified to prevent the DLL706// preloading attack707if (!(new File(lib)).isAbsolute()) {708throw new ConfigurationException(709"Absolute path required for library value: " + lib);710}711return lib;712}713714private void parseDescription(String keyword) throws IOException {715checkDup(keyword);716parseEquals();717description = parseLine();718debug("description: " + description);719}720721private void parseSlotID(String keyword) throws IOException {722if (slotID >= 0) {723throw excLine("Duplicate slot definition");724}725if (slotListIndex >= 0) {726throw excLine727("Only one of slot and slotListIndex must be specified");728}729parseEquals();730String slotString = parseWord();731slotID = decodeNumber(slotString);732debug("slot: " + slotID);733}734735private void parseSlotListIndex(String keyword) throws IOException {736if (slotListIndex >= 0) {737throw excLine("Duplicate slotListIndex definition");738}739if (slotID >= 0) {740throw excLine741("Only one of slot and slotListIndex must be specified");742}743parseEquals();744String slotString = parseWord();745slotListIndex = decodeNumber(slotString);746debug("slotListIndex: " + slotListIndex);747}748749private void parseEnabledMechanisms(String keyword) throws IOException {750enabledMechanisms = parseMechanisms(keyword);751}752753private void parseDisabledMechanisms(String keyword) throws IOException {754disabledMechanisms = parseMechanisms(keyword);755}756757private Set<Long> parseMechanisms(String keyword) throws IOException {758checkDup(keyword);759Set<Long> mechs = new HashSet<Long>();760parseEquals();761parseOpenBraces();762while (true) {763int token = nextToken();764if (isCloseBraces(token)) {765break;766}767if (token == TT_EOL) {768continue;769}770if (token != TT_WORD) {771throw excToken("Expected mechanism, read");772}773long mech = parseMechanism(st.sval);774mechs.add(Long.valueOf(mech));775}776if (DEBUG) {777System.out.print("mechanisms: [");778for (Long mech : mechs) {779System.out.print(Functions.getMechanismName(mech));780System.out.print(", ");781}782System.out.println("]");783}784return mechs;785}786787private long parseMechanism(String mech) throws IOException {788if (isNumber(mech)) {789return decodeNumber(mech);790} else {791try {792return Functions.getMechanismId(mech);793} catch (IllegalArgumentException e) {794throw excLine("Unknown mechanism: " + mech);795}796}797}798799private void parseAttributes(String keyword) throws IOException {800if (templateManager == null) {801templateManager = new TemplateManager();802}803int token = nextToken();804if (token == '=') {805String s = parseWord();806if (s.equals("compatibility") == false) {807throw excLine("Expected 'compatibility', read " + s);808}809setCompatibilityAttributes();810return;811}812if (token != '(') {813throw excToken("Expected '(' or '=', read");814}815String op = parseOperation();816parseComma();817long objectClass = parseObjectClass();818parseComma();819long keyAlg = parseKeyAlgorithm();820token = nextToken();821if (token != ')') {822throw excToken("Expected ')', read");823}824parseEquals();825parseOpenBraces();826List<CK_ATTRIBUTE> attributes = new ArrayList<CK_ATTRIBUTE>();827while (true) {828token = nextToken();829if (isCloseBraces(token)) {830break;831}832if (token == TT_EOL) {833continue;834}835if (token != TT_WORD) {836throw excToken("Expected mechanism, read");837}838String attributeName = st.sval;839long attributeId = decodeAttributeName(attributeName);840parseEquals();841String attributeValue = parseWord();842attributes.add(decodeAttributeValue(attributeId, attributeValue));843}844templateManager.addTemplate845(op, objectClass, keyAlg, attributes.toArray(CK_A0));846}847848private void setCompatibilityAttributes() {849// all secret keys850templateManager.addTemplate(O_ANY, CKO_SECRET_KEY, PCKK_ANY,851new CK_ATTRIBUTE[] {852TOKEN_FALSE,853SENSITIVE_FALSE,854EXTRACTABLE_TRUE,855ENCRYPT_TRUE,856DECRYPT_TRUE,857WRAP_TRUE,858UNWRAP_TRUE,859});860861// generic secret keys are special862// They are used as MAC keys plus for the SSL/TLS (pre)master secrets863templateManager.addTemplate(O_ANY, CKO_SECRET_KEY, CKK_GENERIC_SECRET,864new CK_ATTRIBUTE[] {865SIGN_TRUE,866VERIFY_TRUE,867ENCRYPT_NULL,868DECRYPT_NULL,869WRAP_NULL,870UNWRAP_NULL,871DERIVE_TRUE,872});873874// all private and public keys875templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, PCKK_ANY,876new CK_ATTRIBUTE[] {877TOKEN_FALSE,878SENSITIVE_FALSE,879EXTRACTABLE_TRUE,880});881templateManager.addTemplate(O_ANY, CKO_PUBLIC_KEY, PCKK_ANY,882new CK_ATTRIBUTE[] {883TOKEN_FALSE,884});885886// additional attributes for RSA private keys887templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, CKK_RSA,888new CK_ATTRIBUTE[] {889DECRYPT_TRUE,890SIGN_TRUE,891SIGN_RECOVER_TRUE,892UNWRAP_TRUE,893});894// additional attributes for RSA public keys895templateManager.addTemplate(O_ANY, CKO_PUBLIC_KEY, CKK_RSA,896new CK_ATTRIBUTE[] {897ENCRYPT_TRUE,898VERIFY_TRUE,899VERIFY_RECOVER_TRUE,900WRAP_TRUE,901});902903// additional attributes for DSA private keys904templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, CKK_DSA,905new CK_ATTRIBUTE[] {906SIGN_TRUE,907});908// additional attributes for DSA public keys909templateManager.addTemplate(O_ANY, CKO_PUBLIC_KEY, CKK_DSA,910new CK_ATTRIBUTE[] {911VERIFY_TRUE,912});913914// additional attributes for DH private keys915templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, CKK_DH,916new CK_ATTRIBUTE[] {917DERIVE_TRUE,918});919920// additional attributes for EC private keys921templateManager.addTemplate(O_ANY, CKO_PRIVATE_KEY, CKK_EC,922new CK_ATTRIBUTE[] {923SIGN_TRUE,924DERIVE_TRUE,925});926// additional attributes for EC public keys927templateManager.addTemplate(O_ANY, CKO_PUBLIC_KEY, CKK_EC,928new CK_ATTRIBUTE[] {929VERIFY_TRUE,930});931}932933private static final CK_ATTRIBUTE[] CK_A0 = new CK_ATTRIBUTE[0];934935private String parseOperation() throws IOException {936String op = parseWord();937switch (op) {938case "*":939return TemplateManager.O_ANY;940case "generate":941return TemplateManager.O_GENERATE;942case "import":943return TemplateManager.O_IMPORT;944default:945throw excLine("Unknown operation " + op);946}947}948949private long parseObjectClass() throws IOException {950String name = parseWord();951try {952return Functions.getObjectClassId(name);953} catch (IllegalArgumentException e) {954throw excLine("Unknown object class " + name);955}956}957958private long parseKeyAlgorithm() throws IOException {959String name = parseWord();960if (isNumber(name)) {961return decodeNumber(name);962} else {963try {964return Functions.getKeyId(name);965} catch (IllegalArgumentException e) {966throw excLine("Unknown key algorithm " + name);967}968}969}970971private long decodeAttributeName(String name) throws IOException {972if (isNumber(name)) {973return decodeNumber(name);974} else {975try {976return Functions.getAttributeId(name);977} catch (IllegalArgumentException e) {978throw excLine("Unknown attribute name " + name);979}980}981}982983private CK_ATTRIBUTE decodeAttributeValue(long id, String value)984throws IOException {985if (value.equals("null")) {986return new CK_ATTRIBUTE(id);987} else if (value.equals("true")) {988return new CK_ATTRIBUTE(id, true);989} else if (value.equals("false")) {990return new CK_ATTRIBUTE(id, false);991} else if (isByteArray(value)) {992return new CK_ATTRIBUTE(id, decodeByteArray(value));993} else if (isNumber(value)) {994return new CK_ATTRIBUTE(id, Integer.valueOf(decodeNumber(value)));995} else {996throw excLine("Unknown attribute value " + value);997}998}9991000private void parseNSSArgs(String keyword) throws IOException {1001checkDup(keyword);1002parseEquals();1003int token = nextToken();1004if (token != '"') {1005throw excToken("Expected quoted string");1006}1007nssArgs = expand(st.sval);1008debug("nssArgs: " + nssArgs);1009}10101011private void parseHandleStartupErrors(String keyword) throws IOException {1012checkDup(keyword);1013parseEquals();1014String val = parseWord();1015if (val.equals("ignoreAll")) {1016handleStartupErrors = ERR_IGNORE_ALL;1017} else if (val.equals("ignoreMissingLibrary")) {1018handleStartupErrors = ERR_IGNORE_LIB;1019} else if (val.equals("halt")) {1020handleStartupErrors = ERR_HALT;1021} else {1022throw excToken("Invalid value for handleStartupErrors:");1023}1024debug("handleStartupErrors: " + handleStartupErrors);1025}10261027}10281029class ConfigurationException extends IOException {1030private static final long serialVersionUID = 254492758807673194L;1031ConfigurationException(String msg) {1032super(msg);1033}1034}103510361037