jdk/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyGenerator.java
changeset 43248 5e15de85a1a0
parent 42693 6645de32a866
equal deleted inserted replaced
43247:8d242299a219 43248:5e15de85a1a0
       
     1 /*
       
     2  * Copyright (c) 2003, 2008, 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.security.*;
       
    29 import java.security.spec.AlgorithmParameterSpec;
       
    30 
       
    31 import javax.crypto.*;
       
    32 
       
    33 import static sun.security.pkcs11.TemplateManager.*;
       
    34 import sun.security.pkcs11.wrapper.*;
       
    35 import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
       
    36 
       
    37 /**
       
    38  * KeyGenerator implementation class. This class currently supports
       
    39  * DES, DESede, AES, ARCFOUR, and Blowfish.
       
    40  *
       
    41  * @author  Andreas Sterbenz
       
    42  * @since   1.5
       
    43  */
       
    44 final class P11KeyGenerator extends KeyGeneratorSpi {
       
    45 
       
    46     // token instance
       
    47     private final Token token;
       
    48 
       
    49     // algorithm name
       
    50     private final String algorithm;
       
    51 
       
    52     // mechanism id
       
    53     private long mechanism;
       
    54 
       
    55     // raw key size in bits, e.g. 64 for DES. Always valid.
       
    56     private int keySize;
       
    57 
       
    58     // bits of entropy in the key, e.g. 56 for DES. Always valid.
       
    59     private int significantKeySize;
       
    60 
       
    61     // keyType (CKK_*), needed for TemplateManager call only.
       
    62     private long keyType;
       
    63 
       
    64     // for determining if both 112 and 168 bits of DESede key lengths
       
    65     // are supported.
       
    66     private boolean supportBothKeySizes;
       
    67 
       
    68     /**
       
    69      * Utility method for checking if the specified key size is valid
       
    70      * and within the supported range. Return the significant key size
       
    71      * upon successful validation.
       
    72      * @param keyGenMech the PKCS#11 key generation mechanism.
       
    73      * @param keySize the to-be-checked key size for this mechanism.
       
    74      * @param token token which provides this mechanism.
       
    75      * @return the significant key size (in bits) corresponding to the
       
    76      * specified key size.
       
    77      * @throws InvalidParameterException if the specified key size is invalid.
       
    78      * @throws ProviderException if this mechanism isn't supported by SunPKCS11
       
    79      * or underlying native impl.
       
    80      */
       
    81     static int checkKeySize(long keyGenMech, int keySize, Token token)
       
    82         throws InvalidAlgorithmParameterException, ProviderException {
       
    83         int sigKeySize;
       
    84         switch ((int)keyGenMech) {
       
    85             case (int)CKM_DES_KEY_GEN:
       
    86                 if ((keySize != 64) && (keySize != 56)) {
       
    87                     throw new InvalidAlgorithmParameterException
       
    88                             ("DES key length must be 56 bits");
       
    89                 }
       
    90                 sigKeySize = 56;
       
    91                 break;
       
    92             case (int)CKM_DES2_KEY_GEN:
       
    93             case (int)CKM_DES3_KEY_GEN:
       
    94                 if ((keySize == 112) || (keySize == 128)) {
       
    95                     sigKeySize = 112;
       
    96                 } else if ((keySize == 168) || (keySize == 192)) {
       
    97                     sigKeySize = 168;
       
    98                 } else {
       
    99                     throw new InvalidAlgorithmParameterException
       
   100                             ("DESede key length must be 112, or 168 bits");
       
   101                 }
       
   102                 break;
       
   103             default:
       
   104                 // Handle all variable-key-length algorithms here
       
   105                 CK_MECHANISM_INFO info = null;
       
   106                 try {
       
   107                     info = token.getMechanismInfo(keyGenMech);
       
   108                 } catch (PKCS11Exception p11e) {
       
   109                     // Should never happen
       
   110                     throw new ProviderException
       
   111                             ("Cannot retrieve mechanism info", p11e);
       
   112                 }
       
   113                 if (info == null) {
       
   114                     // XXX Unable to retrieve the supported key length from
       
   115                     // the underlying native impl. Skip the checking for now.
       
   116                     return keySize;
       
   117                 }
       
   118                 // PKCS#11 defines these to be in number of bytes except for
       
   119                 // RC4 which is in bits. However, some PKCS#11 impls still use
       
   120                 // bytes for all mechs, e.g. NSS. We try to detect this
       
   121                 // inconsistency if the minKeySize seems unreasonably small.
       
   122                 int minKeySize = (int)info.ulMinKeySize;
       
   123                 int maxKeySize = (int)info.ulMaxKeySize;
       
   124                 if (keyGenMech != CKM_RC4_KEY_GEN || minKeySize < 8) {
       
   125                     minKeySize = (int)info.ulMinKeySize << 3;
       
   126                     maxKeySize = (int)info.ulMaxKeySize << 3;
       
   127                 }
       
   128                 // Explicitly disallow keys shorter than 40-bits for security
       
   129                 if (minKeySize < 40) minKeySize = 40;
       
   130                 if (keySize < minKeySize || keySize > maxKeySize) {
       
   131                     throw new InvalidAlgorithmParameterException
       
   132                             ("Key length must be between " + minKeySize +
       
   133                             " and " + maxKeySize + " bits");
       
   134                 }
       
   135                 if (keyGenMech == CKM_AES_KEY_GEN) {
       
   136                     if ((keySize != 128) && (keySize != 192) &&
       
   137                         (keySize != 256)) {
       
   138                         throw new InvalidAlgorithmParameterException
       
   139                                 ("AES key length must be " + minKeySize +
       
   140                                 (maxKeySize >= 192? ", 192":"") +
       
   141                                 (maxKeySize >= 256? ", or 256":"") + " bits");
       
   142                     }
       
   143                 }
       
   144                 sigKeySize = keySize;
       
   145         }
       
   146         return sigKeySize;
       
   147     }
       
   148 
       
   149     P11KeyGenerator(Token token, String algorithm, long mechanism)
       
   150             throws PKCS11Exception {
       
   151         super();
       
   152         this.token = token;
       
   153         this.algorithm = algorithm;
       
   154         this.mechanism = mechanism;
       
   155 
       
   156         if (this.mechanism == CKM_DES3_KEY_GEN) {
       
   157             /* Given the current lookup order specified in SunPKCS11.java,
       
   158                if CKM_DES2_KEY_GEN is used to construct this object, it
       
   159                means that CKM_DES3_KEY_GEN is disabled or unsupported.
       
   160             */
       
   161             supportBothKeySizes =
       
   162                 (token.provider.config.isEnabled(CKM_DES2_KEY_GEN) &&
       
   163                  (token.getMechanismInfo(CKM_DES2_KEY_GEN) != null));
       
   164         }
       
   165         setDefaultKeySize();
       
   166     }
       
   167 
       
   168     // set default keysize and also initialize keyType
       
   169     private void setDefaultKeySize() {
       
   170         switch ((int)mechanism) {
       
   171         case (int)CKM_DES_KEY_GEN:
       
   172             keySize = 64;
       
   173             keyType = CKK_DES;
       
   174             break;
       
   175         case (int)CKM_DES2_KEY_GEN:
       
   176             keySize = 128;
       
   177             keyType = CKK_DES2;
       
   178             break;
       
   179         case (int)CKM_DES3_KEY_GEN:
       
   180             keySize = 192;
       
   181             keyType = CKK_DES3;
       
   182             break;
       
   183         case (int)CKM_AES_KEY_GEN:
       
   184             keySize = 128;
       
   185             keyType = CKK_AES;
       
   186             break;
       
   187         case (int)CKM_RC4_KEY_GEN:
       
   188             keySize = 128;
       
   189             keyType = CKK_RC4;
       
   190             break;
       
   191         case (int)CKM_BLOWFISH_KEY_GEN:
       
   192             keySize = 128;
       
   193             keyType = CKK_BLOWFISH;
       
   194             break;
       
   195         default:
       
   196             throw new ProviderException("Unknown mechanism " + mechanism);
       
   197         }
       
   198         try {
       
   199             significantKeySize = checkKeySize(mechanism, keySize, token);
       
   200         } catch (InvalidAlgorithmParameterException iape) {
       
   201             throw new ProviderException("Unsupported default key size", iape);
       
   202         }
       
   203     }
       
   204 
       
   205     // see JCE spec
       
   206     protected void engineInit(SecureRandom random) {
       
   207         token.ensureValid();
       
   208         setDefaultKeySize();
       
   209     }
       
   210 
       
   211     // see JCE spec
       
   212     protected void engineInit(AlgorithmParameterSpec params,
       
   213             SecureRandom random) throws InvalidAlgorithmParameterException {
       
   214         throw new InvalidAlgorithmParameterException
       
   215                 ("AlgorithmParameterSpec not supported");
       
   216     }
       
   217 
       
   218     // see JCE spec
       
   219     protected void engineInit(int keySize, SecureRandom random) {
       
   220         token.ensureValid();
       
   221         int newSignificantKeySize;
       
   222         try {
       
   223             newSignificantKeySize = checkKeySize(mechanism, keySize, token);
       
   224         } catch (InvalidAlgorithmParameterException iape) {
       
   225             throw (InvalidParameterException)
       
   226                     (new InvalidParameterException().initCause(iape));
       
   227         }
       
   228         if ((mechanism == CKM_DES2_KEY_GEN) ||
       
   229             (mechanism == CKM_DES3_KEY_GEN))  {
       
   230             long newMechanism = (newSignificantKeySize == 112 ?
       
   231                 CKM_DES2_KEY_GEN : CKM_DES3_KEY_GEN);
       
   232             if (mechanism != newMechanism) {
       
   233                 if (supportBothKeySizes) {
       
   234                     mechanism = newMechanism;
       
   235                     // Adjust keyType to reflect the mechanism change
       
   236                     keyType = (mechanism == CKM_DES2_KEY_GEN ?
       
   237                         CKK_DES2 : CKK_DES3);
       
   238                 } else {
       
   239                     throw new InvalidParameterException
       
   240                             ("Only " + significantKeySize +
       
   241                              "-bit DESede is supported");
       
   242                 }
       
   243             }
       
   244         }
       
   245         this.keySize = keySize;
       
   246         this.significantKeySize = newSignificantKeySize;
       
   247     }
       
   248 
       
   249     // see JCE spec
       
   250     protected SecretKey engineGenerateKey() {
       
   251         Session session = null;
       
   252         try {
       
   253             session = token.getObjSession();
       
   254             CK_ATTRIBUTE[] attributes;
       
   255             switch ((int)keyType) {
       
   256             case (int)CKK_DES:
       
   257             case (int)CKK_DES2:
       
   258             case (int)CKK_DES3:
       
   259                 // fixed length, do not specify CKA_VALUE_LEN
       
   260                 attributes = new CK_ATTRIBUTE[] {
       
   261                     new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
       
   262                 };
       
   263                 break;
       
   264             default:
       
   265                 attributes = new CK_ATTRIBUTE[] {
       
   266                     new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
       
   267                     new CK_ATTRIBUTE(CKA_VALUE_LEN, keySize >> 3),
       
   268                 };
       
   269                 break;
       
   270             }
       
   271             attributes = token.getAttributes
       
   272                 (O_GENERATE, CKO_SECRET_KEY, keyType, attributes);
       
   273             long keyID = token.p11.C_GenerateKey
       
   274                 (session.id(), new CK_MECHANISM(mechanism), attributes);
       
   275             return P11Key.secretKey
       
   276                 (session, keyID, algorithm, significantKeySize, attributes);
       
   277         } catch (PKCS11Exception e) {
       
   278             throw new ProviderException("Could not generate key", e);
       
   279         } finally {
       
   280             token.releaseSession(session);
       
   281         }
       
   282     }
       
   283 
       
   284 }