0N/A/*
2362N/A * Copyright (c) 2003, 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.util.*;
0N/Aimport java.util.concurrent.*;
0N/A
0N/Aimport sun.security.pkcs11.wrapper.*;
0N/Aimport static sun.security.pkcs11.wrapper.PKCS11Constants.*;
0N/A
0N/A/**
0N/A * TemplateManager class.
0N/A *
0N/A * Not all PKCS#11 tokens are created equal. One token may require that one
0N/A * value is specified when creating a certain type of object. Another token
0N/A * may require a different value. Yet another token may only work if the
0N/A * attribute is not specified at all.
0N/A *
0N/A * In order to allow an application to work unmodified with all those
0N/A * different tokens, the SunPKCS11 provider makes the attributes that are
0N/A * specified and their value configurable. Hence, only the SunPKCS11
0N/A * configuration file has to be tweaked at deployment time to allow all
0N/A * existing applications to be used.
0N/A *
0N/A * The template manager is responsible for reading the attribute configuration
0N/A * information and to make it available to the various internal components
0N/A * of the SunPKCS11 provider.
0N/A *
0N/A * @author Andreas Sterbenz
0N/A * @since 1.5
0N/A */
0N/Afinal class TemplateManager {
0N/A
0N/A private final static boolean DEBUG = false;
0N/A
0N/A // constant for any operation (either O_IMPORT or O_GENERATE)
0N/A final static String O_ANY = "*";
0N/A // constant for operation create ("importing" existing key material)
0N/A final static String O_IMPORT = "import";
0N/A // constant for operation generate (generating new key material)
0N/A final static String O_GENERATE = "generate";
0N/A
0N/A private static class KeyAndTemplate {
0N/A final TemplateKey key;
0N/A final Template template;
0N/A
0N/A KeyAndTemplate(TemplateKey key, Template template) {
0N/A this.key = key;
0N/A this.template = template;
0N/A }
0N/A }
0N/A
0N/A // primitive templates contains the individual template configuration
0N/A // entries from the configuration file
0N/A private final List<KeyAndTemplate> primitiveTemplates;
0N/A
0N/A // composite templates is a cache of the exact configuration template for
0N/A // each specific TemplateKey (no wildcards). the entries are created
0N/A // on demand during first use by compositing all applicable
0N/A // primitive template entries. the result is then stored in this map
0N/A // for performance
0N/A private final Map<TemplateKey,Template> compositeTemplates;
0N/A
0N/A TemplateManager() {
0N/A primitiveTemplates = new ArrayList<KeyAndTemplate>();
0N/A compositeTemplates = new ConcurrentHashMap<TemplateKey,Template>();
0N/A }
0N/A
0N/A // add a template. Called by Config.
0N/A void addTemplate(String op, long objectClass, long keyAlgorithm,
0N/A CK_ATTRIBUTE[] attrs) {
0N/A TemplateKey key = new TemplateKey(op, objectClass, keyAlgorithm);
0N/A Template template = new Template(attrs);
0N/A if (DEBUG) {
0N/A System.out.println("Adding " + key + " -> " + template);
0N/A }
0N/A primitiveTemplates.add(new KeyAndTemplate(key, template));
0N/A }
0N/A
0N/A private Template getTemplate(TemplateKey key) {
0N/A Template template = compositeTemplates.get(key);
0N/A if (template == null) {
0N/A template = buildCompositeTemplate(key);
0N/A compositeTemplates.put(key, template);
0N/A }
0N/A return template;
0N/A }
0N/A
0N/A // Get the attributes for the requested op and combine them with attrs.
0N/A // This is the method called by the implementation to obtain the
0N/A // attributes.
0N/A CK_ATTRIBUTE[] getAttributes(String op, long type, long alg,
0N/A CK_ATTRIBUTE[] attrs) {
0N/A TemplateKey key = new TemplateKey(op, type, alg);
0N/A Template template = getTemplate(key);
0N/A CK_ATTRIBUTE[] newAttrs = template.getAttributes(attrs);
0N/A if (DEBUG) {
0N/A System.out.println(key + " -> " + Arrays.asList(newAttrs));
0N/A }
0N/A return newAttrs;
0N/A }
0N/A
0N/A // build a composite template for the given key
0N/A private Template buildCompositeTemplate(TemplateKey key) {
0N/A Template comp = new Template();
0N/A // iterate through primitive templates and add all that apply
0N/A for (KeyAndTemplate entry : primitiveTemplates) {
0N/A if (entry.key.appliesTo(key)) {
0N/A comp.add(entry.template);
0N/A }
0N/A }
0N/A return comp;
0N/A }
0N/A
0N/A /**
0N/A * Nested class representing a template identifier.
0N/A */
0N/A private static final class TemplateKey {
0N/A final String operation;
0N/A final long keyType;
0N/A final long keyAlgorithm;
0N/A TemplateKey(String operation, long keyType, long keyAlgorithm) {
0N/A this.operation = operation;
0N/A this.keyType = keyType;
0N/A this.keyAlgorithm = keyAlgorithm;
0N/A }
0N/A public boolean equals(Object obj) {
0N/A if (this == obj) {
0N/A return true;
0N/A }
0N/A if (obj instanceof TemplateKey == false) {
0N/A return false;
0N/A }
0N/A TemplateKey other = (TemplateKey)obj;
0N/A boolean match = this.operation.equals(other.operation)
0N/A && (this.keyType == other.keyType)
0N/A && (this.keyAlgorithm == other.keyAlgorithm);
0N/A return match;
0N/A }
0N/A public int hashCode() {
0N/A return operation.hashCode() + (int)keyType + (int)keyAlgorithm;
0N/A }
0N/A boolean appliesTo(TemplateKey key) {
0N/A if (operation.equals(O_ANY) || operation.equals(key.operation)) {
0N/A if ((keyType == PCKO_ANY) || (keyType == key.keyType)) {
0N/A if ((keyAlgorithm == PCKK_ANY)
0N/A || (keyAlgorithm == key.keyAlgorithm)) {
0N/A return true;
0N/A }
0N/A }
0N/A }
0N/A return false;
0N/A }
0N/A public String toString() {
0N/A return "(" + operation + ","
0N/A + Functions.getObjectClassName(keyType)
0N/A + "," + Functions.getKeyName(keyAlgorithm) + ")";
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Nested class representing template attributes.
0N/A */
0N/A private static final class Template {
0N/A
0N/A private final static CK_ATTRIBUTE[] A0 = new CK_ATTRIBUTE[0];
0N/A
0N/A private CK_ATTRIBUTE[] attributes;
0N/A
0N/A Template() {
0N/A attributes = A0;
0N/A }
0N/A
0N/A Template(CK_ATTRIBUTE[] attributes) {
0N/A this.attributes = attributes;
0N/A }
0N/A
0N/A void add(Template template) {
0N/A attributes = getAttributes(template.attributes);
0N/A }
0N/A
0N/A CK_ATTRIBUTE[] getAttributes(CK_ATTRIBUTE[] attrs) {
0N/A return combine(attributes, attrs);
0N/A }
0N/A
0N/A /**
0N/A * Combine two sets of attributes. The second set has precedence
0N/A * over the first and overrides its settings.
0N/A */
0N/A private static CK_ATTRIBUTE[] combine(CK_ATTRIBUTE[] attrs1,
0N/A CK_ATTRIBUTE[] attrs2) {
0N/A List<CK_ATTRIBUTE> attrs = new ArrayList<CK_ATTRIBUTE>();
0N/A for (CK_ATTRIBUTE attr : attrs1) {
0N/A if (attr.pValue != null) {
0N/A attrs.add(attr);
0N/A }
0N/A }
0N/A for (CK_ATTRIBUTE attr2 : attrs2) {
0N/A long type = attr2.type;
0N/A for (CK_ATTRIBUTE attr1 : attrs1) {
0N/A if (attr1.type == type) {
0N/A attrs.remove(attr1);
0N/A }
0N/A }
0N/A if (attr2.pValue != null) {
0N/A attrs.add(attr2);
0N/A }
0N/A }
0N/A return attrs.toArray(A0);
0N/A }
0N/A
0N/A public String toString() {
0N/A return Arrays.asList(attributes).toString();
0N/A }
0N/A
0N/A }
0N/A
0N/A}