jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/TemplateManager.java
changeset 42693 6645de32a866
parent 42692 97247477b481
child 42694 53aaff453c11
equal deleted inserted replaced
42692:97247477b481 42693:6645de32a866
     1 /*
       
     2  * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 package sun.security.pkcs11;
       
    27 
       
    28 import java.util.*;
       
    29 import java.util.concurrent.*;
       
    30 
       
    31 import sun.security.pkcs11.wrapper.*;
       
    32 import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
       
    33 
       
    34 /**
       
    35  * TemplateManager class.
       
    36  *
       
    37  * Not all PKCS#11 tokens are created equal. One token may require that one
       
    38  * value is specified when creating a certain type of object. Another token
       
    39  * may require a different value. Yet another token may only work if the
       
    40  * attribute is not specified at all.
       
    41  *
       
    42  * In order to allow an application to work unmodified with all those
       
    43  * different tokens, the SunPKCS11 provider makes the attributes that are
       
    44  * specified and their value configurable. Hence, only the SunPKCS11
       
    45  * configuration file has to be tweaked at deployment time to allow all
       
    46  * existing applications to be used.
       
    47  *
       
    48  * The template manager is responsible for reading the attribute configuration
       
    49  * information and to make it available to the various internal components
       
    50  * of the SunPKCS11 provider.
       
    51  *
       
    52  * @author  Andreas Sterbenz
       
    53  * @since   1.5
       
    54  */
       
    55 final class TemplateManager {
       
    56 
       
    57     private final static boolean DEBUG = false;
       
    58 
       
    59     // constant for any operation (either O_IMPORT or O_GENERATE)
       
    60     final static String O_ANY      = "*";
       
    61     // constant for operation create ("importing" existing key material)
       
    62     final static String O_IMPORT   = "import";
       
    63     // constant for operation generate (generating new key material)
       
    64     final static String O_GENERATE = "generate";
       
    65 
       
    66     private static class KeyAndTemplate {
       
    67         final TemplateKey key;
       
    68         final Template template;
       
    69 
       
    70         KeyAndTemplate(TemplateKey key, Template template) {
       
    71             this.key = key;
       
    72             this.template = template;
       
    73         }
       
    74     }
       
    75 
       
    76     // primitive templates contains the individual template configuration
       
    77     // entries from the configuration file
       
    78     private final List<KeyAndTemplate> primitiveTemplates;
       
    79 
       
    80     // composite templates is a cache of the exact configuration template for
       
    81     // each specific TemplateKey (no wildcards). the entries are created
       
    82     // on demand during first use by compositing all applicable
       
    83     // primitive template entries. the result is then stored in this map
       
    84     // for performance
       
    85     private final Map<TemplateKey,Template> compositeTemplates;
       
    86 
       
    87     TemplateManager() {
       
    88         primitiveTemplates = new ArrayList<KeyAndTemplate>();
       
    89         compositeTemplates = new ConcurrentHashMap<TemplateKey,Template>();
       
    90     }
       
    91 
       
    92     // add a template. Called by Config.
       
    93     void addTemplate(String op, long objectClass, long keyAlgorithm,
       
    94             CK_ATTRIBUTE[] attrs) {
       
    95         TemplateKey key = new TemplateKey(op, objectClass, keyAlgorithm);
       
    96         Template template = new Template(attrs);
       
    97         if (DEBUG) {
       
    98             System.out.println("Adding " + key + " -> " + template);
       
    99         }
       
   100         primitiveTemplates.add(new KeyAndTemplate(key, template));
       
   101     }
       
   102 
       
   103     private Template getTemplate(TemplateKey key) {
       
   104         Template template = compositeTemplates.get(key);
       
   105         if (template == null) {
       
   106             template = buildCompositeTemplate(key);
       
   107             compositeTemplates.put(key, template);
       
   108         }
       
   109         return template;
       
   110     }
       
   111 
       
   112     // Get the attributes for the requested op and combine them with attrs.
       
   113     // This is the method called by the implementation to obtain the
       
   114     // attributes.
       
   115     CK_ATTRIBUTE[] getAttributes(String op, long type, long alg,
       
   116             CK_ATTRIBUTE[] attrs) {
       
   117         TemplateKey key = new TemplateKey(op, type, alg);
       
   118         Template template = getTemplate(key);
       
   119         CK_ATTRIBUTE[] newAttrs = template.getAttributes(attrs);
       
   120         if (DEBUG) {
       
   121             System.out.println(key + " -> " + Arrays.asList(newAttrs));
       
   122         }
       
   123         return newAttrs;
       
   124     }
       
   125 
       
   126     // build a composite template for the given key
       
   127     private Template buildCompositeTemplate(TemplateKey key) {
       
   128         Template comp = new Template();
       
   129         // iterate through primitive templates and add all that apply
       
   130         for (KeyAndTemplate entry : primitiveTemplates) {
       
   131             if (entry.key.appliesTo(key)) {
       
   132                 comp.add(entry.template);
       
   133             }
       
   134         }
       
   135         return comp;
       
   136     }
       
   137 
       
   138     /**
       
   139      * Nested class representing a template identifier.
       
   140      */
       
   141     private static final class TemplateKey {
       
   142         final String operation;
       
   143         final long keyType;
       
   144         final long keyAlgorithm;
       
   145         TemplateKey(String operation, long keyType, long keyAlgorithm) {
       
   146             this.operation = operation;
       
   147             this.keyType = keyType;
       
   148             this.keyAlgorithm = keyAlgorithm;
       
   149         }
       
   150         public boolean equals(Object obj) {
       
   151             if (this == obj) {
       
   152                 return true;
       
   153             }
       
   154             if (obj instanceof TemplateKey == false) {
       
   155                 return false;
       
   156             }
       
   157             TemplateKey other = (TemplateKey)obj;
       
   158             boolean match = this.operation.equals(other.operation)
       
   159                         && (this.keyType == other.keyType)
       
   160                         && (this.keyAlgorithm == other.keyAlgorithm);
       
   161             return match;
       
   162         }
       
   163         public int hashCode() {
       
   164             return operation.hashCode() + (int)keyType + (int)keyAlgorithm;
       
   165         }
       
   166         boolean appliesTo(TemplateKey key) {
       
   167             if (operation.equals(O_ANY) || operation.equals(key.operation)) {
       
   168                 if ((keyType == PCKO_ANY) || (keyType == key.keyType)) {
       
   169                     if ((keyAlgorithm == PCKK_ANY)
       
   170                                 || (keyAlgorithm == key.keyAlgorithm)) {
       
   171                         return true;
       
   172                     }
       
   173                 }
       
   174             }
       
   175             return false;
       
   176         }
       
   177         public String toString() {
       
   178             return "(" + operation + ","
       
   179                 + Functions.getObjectClassName(keyType)
       
   180                 + "," + Functions.getKeyName(keyAlgorithm) + ")";
       
   181         }
       
   182     }
       
   183 
       
   184     /**
       
   185      * Nested class representing template attributes.
       
   186      */
       
   187     private static final class Template {
       
   188 
       
   189         private final static CK_ATTRIBUTE[] A0 = new CK_ATTRIBUTE[0];
       
   190 
       
   191         private CK_ATTRIBUTE[] attributes;
       
   192 
       
   193         Template() {
       
   194             attributes = A0;
       
   195         }
       
   196 
       
   197         Template(CK_ATTRIBUTE[] attributes) {
       
   198             this.attributes = attributes;
       
   199         }
       
   200 
       
   201         void add(Template template) {
       
   202             attributes = getAttributes(template.attributes);
       
   203         }
       
   204 
       
   205         CK_ATTRIBUTE[] getAttributes(CK_ATTRIBUTE[] attrs) {
       
   206             return combine(attributes, attrs);
       
   207         }
       
   208 
       
   209         /**
       
   210          * Combine two sets of attributes. The second set has precedence
       
   211          * over the first and overrides its settings.
       
   212          */
       
   213         private static CK_ATTRIBUTE[] combine(CK_ATTRIBUTE[] attrs1,
       
   214                 CK_ATTRIBUTE[] attrs2) {
       
   215             List<CK_ATTRIBUTE> attrs = new ArrayList<CK_ATTRIBUTE>();
       
   216             for (CK_ATTRIBUTE attr : attrs1) {
       
   217                 if (attr.pValue != null) {
       
   218                     attrs.add(attr);
       
   219                 }
       
   220             }
       
   221             for (CK_ATTRIBUTE attr2 : attrs2) {
       
   222                 long type = attr2.type;
       
   223                 for (CK_ATTRIBUTE attr1 : attrs1) {
       
   224                     if (attr1.type == type) {
       
   225                         attrs.remove(attr1);
       
   226                     }
       
   227                 }
       
   228                 if (attr2.pValue != null) {
       
   229                     attrs.add(attr2);
       
   230                 }
       
   231             }
       
   232             return attrs.toArray(A0);
       
   233         }
       
   234 
       
   235         public String toString() {
       
   236             return Arrays.asList(attributes).toString();
       
   237         }
       
   238 
       
   239     }
       
   240 
       
   241 }