Path: blob/master/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/TemplateManager.java
41154 views
/*1* Copyright (c) 2003, 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.util.*;28import java.util.concurrent.*;2930import sun.security.pkcs11.wrapper.*;31import static sun.security.pkcs11.wrapper.PKCS11Constants.*;3233/**34* TemplateManager class.35*36* Not all PKCS#11 tokens are created equal. One token may require that one37* value is specified when creating a certain type of object. Another token38* may require a different value. Yet another token may only work if the39* attribute is not specified at all.40*41* In order to allow an application to work unmodified with all those42* different tokens, the SunPKCS11 provider makes the attributes that are43* specified and their value configurable. Hence, only the SunPKCS1144* configuration file has to be tweaked at deployment time to allow all45* existing applications to be used.46*47* The template manager is responsible for reading the attribute configuration48* information and to make it available to the various internal components49* of the SunPKCS11 provider.50*51* @author Andreas Sterbenz52* @since 1.553*/54final class TemplateManager {5556private static final boolean DEBUG = false;5758// constant for any operation (either O_IMPORT or O_GENERATE)59static final String O_ANY = "*";60// constant for operation create ("importing" existing key material)61static final String O_IMPORT = "import";62// constant for operation generate (generating new key material)63static final String O_GENERATE = "generate";6465private static class KeyAndTemplate {66final TemplateKey key;67final Template template;6869KeyAndTemplate(TemplateKey key, Template template) {70this.key = key;71this.template = template;72}73}7475// primitive templates contains the individual template configuration76// entries from the configuration file77private final List<KeyAndTemplate> primitiveTemplates;7879// composite templates is a cache of the exact configuration template for80// each specific TemplateKey (no wildcards). the entries are created81// on demand during first use by compositing all applicable82// primitive template entries. the result is then stored in this map83// for performance84private final Map<TemplateKey,Template> compositeTemplates;8586TemplateManager() {87primitiveTemplates = new ArrayList<KeyAndTemplate>();88compositeTemplates = new ConcurrentHashMap<TemplateKey,Template>();89}9091// add a template. Called by Config.92void addTemplate(String op, long objectClass, long keyAlgorithm,93CK_ATTRIBUTE[] attrs) {94TemplateKey key = new TemplateKey(op, objectClass, keyAlgorithm);95Template template = new Template(attrs);96if (DEBUG) {97System.out.println("Adding " + key + " -> " + template);98}99primitiveTemplates.add(new KeyAndTemplate(key, template));100}101102private Template getTemplate(TemplateKey key) {103Template template = compositeTemplates.get(key);104if (template == null) {105template = buildCompositeTemplate(key);106compositeTemplates.put(key, template);107}108return template;109}110111// Get the attributes for the requested op and combine them with attrs.112// This is the method called by the implementation to obtain the113// attributes.114CK_ATTRIBUTE[] getAttributes(String op, long type, long alg,115CK_ATTRIBUTE[] attrs) {116TemplateKey key = new TemplateKey(op, type, alg);117Template template = getTemplate(key);118CK_ATTRIBUTE[] newAttrs = template.getAttributes(attrs);119if (DEBUG) {120System.out.println(key + " -> " + Arrays.asList(newAttrs));121}122return newAttrs;123}124125// build a composite template for the given key126private Template buildCompositeTemplate(TemplateKey key) {127Template comp = new Template();128// iterate through primitive templates and add all that apply129for (KeyAndTemplate entry : primitiveTemplates) {130if (entry.key.appliesTo(key)) {131comp.add(entry.template);132}133}134return comp;135}136137/**138* Nested class representing a template identifier.139*/140private static final class TemplateKey {141final String operation;142final long keyType;143final long keyAlgorithm;144TemplateKey(String operation, long keyType, long keyAlgorithm) {145this.operation = operation;146this.keyType = keyType;147this.keyAlgorithm = keyAlgorithm;148}149public boolean equals(Object obj) {150if (this == obj) {151return true;152}153if (obj instanceof TemplateKey == false) {154return false;155}156TemplateKey other = (TemplateKey)obj;157boolean match = this.operation.equals(other.operation)158&& (this.keyType == other.keyType)159&& (this.keyAlgorithm == other.keyAlgorithm);160return match;161}162public int hashCode() {163return operation.hashCode() + (int)keyType + (int)keyAlgorithm;164}165boolean appliesTo(TemplateKey key) {166if (operation.equals(O_ANY) || operation.equals(key.operation)) {167if ((keyType == PCKO_ANY) || (keyType == key.keyType)) {168if ((keyAlgorithm == PCKK_ANY)169|| (keyAlgorithm == key.keyAlgorithm)) {170return true;171}172}173}174return false;175}176public String toString() {177return "(" + operation + ","178+ Functions.getObjectClassName(keyType)179+ "," + Functions.getKeyName(keyAlgorithm) + ")";180}181}182183/**184* Nested class representing template attributes.185*/186private static final class Template {187188private static final CK_ATTRIBUTE[] A0 = new CK_ATTRIBUTE[0];189190private CK_ATTRIBUTE[] attributes;191192Template() {193attributes = A0;194}195196Template(CK_ATTRIBUTE[] attributes) {197this.attributes = attributes;198}199200void add(Template template) {201attributes = getAttributes(template.attributes);202}203204CK_ATTRIBUTE[] getAttributes(CK_ATTRIBUTE[] attrs) {205return combine(attributes, attrs);206}207208/**209* Combine two sets of attributes. The second set has precedence210* over the first and overrides its settings.211*/212private static CK_ATTRIBUTE[] combine(CK_ATTRIBUTE[] attrs1,213CK_ATTRIBUTE[] attrs2) {214List<CK_ATTRIBUTE> attrs = new ArrayList<CK_ATTRIBUTE>();215for (CK_ATTRIBUTE attr : attrs1) {216if (attr.pValue != null) {217attrs.add(attr);218}219}220for (CK_ATTRIBUTE attr2 : attrs2) {221long type = attr2.type;222for (CK_ATTRIBUTE attr1 : attrs1) {223if (attr1.type == type) {224attrs.remove(attr1);225}226}227if (attr2.pValue != null) {228attrs.add(attr2);229}230}231return attrs.toArray(A0);232}233234public String toString() {235return Arrays.asList(attributes).toString();236}237238}239240}241242243