P11KeyGenerator.java revision 0
0N/A/*
0N/A * Copyright 2003-2007 Sun Microsystems, Inc. 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
0N/A * published by the Free Software Foundation. Sun designates this
0N/A * particular file as subject to the "Classpath" exception as provided
0N/A * by Sun 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 *
0N/A * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0N/A * CA 95054 USA or visit www.sun.com if you need additional information or
0N/A * have any questions.
0N/A */
0N/A
0N/Apackage sun.security.pkcs11;
0N/A
0N/Aimport java.security.*;
0N/Aimport java.security.spec.AlgorithmParameterSpec;
0N/A
0N/Aimport javax.crypto.*;
0N/A
0N/Aimport static sun.security.pkcs11.TemplateManager.*;
0N/Aimport sun.security.pkcs11.wrapper.*;
0N/Aimport static sun.security.pkcs11.wrapper.PKCS11Constants.*;
0N/A
0N/A/**
0N/A * KeyGenerator implementation class. This class currently supports
0N/A * DES, DESede, AES, ARCFOUR, and Blowfish.
0N/A *
0N/A * @author Andreas Sterbenz
0N/A * @since 1.5
0N/A */
0N/Afinal class P11KeyGenerator extends KeyGeneratorSpi {
0N/A
0N/A // token instance
0N/A private final Token token;
0N/A
0N/A // algorithm name
0N/A private final String algorithm;
0N/A
0N/A // mechanism id
0N/A private long mechanism;
0N/A
0N/A // raw key size in bits, e.g. 64 for DES. Always valid.
0N/A private int keySize;
0N/A
0N/A // bits of entropy in the key, e.g. 56 for DES. Always valid.
0N/A private int significantKeySize;
0N/A
0N/A // keyType (CKK_*), needed for TemplateManager call only.
0N/A private long keyType;
0N/A
0N/A // for determining if both 112 and 168 bits of DESede key lengths
0N/A // are supported.
0N/A private boolean supportBothKeySizes;
0N/A
0N/A // min and max key sizes (in bits) for variable-key-length
0N/A // algorithms, e.g. RC4 and Blowfish
0N/A private int minKeySize;
0N/A private int maxKeySize;
0N/A
0N/A P11KeyGenerator(Token token, String algorithm, long mechanism)
0N/A throws PKCS11Exception {
0N/A super();
0N/A this.token = token;
0N/A this.algorithm = algorithm;
0N/A this.mechanism = mechanism;
0N/A
0N/A if (this.mechanism == CKM_DES3_KEY_GEN) {
0N/A /* Given the current lookup order specified in SunPKCS11.java,
0N/A if CKM_DES2_KEY_GEN is used to construct this object, it
0N/A means that CKM_DES3_KEY_GEN is disabled or unsupported.
0N/A */
0N/A supportBothKeySizes =
0N/A (token.provider.config.isEnabled(CKM_DES2_KEY_GEN) &&
0N/A (token.getMechanismInfo(CKM_DES2_KEY_GEN) != null));
0N/A } else if (this.mechanism == CKM_RC4_KEY_GEN) {
0N/A CK_MECHANISM_INFO info = token.getMechanismInfo(mechanism);
0N/A // Although PKCS#11 spec documented that these are in bits,
0N/A // NSS, for one, uses bytes. Multiple by 8 if the number seems
0N/A // unreasonably small.
0N/A if (info.ulMinKeySize < 8) {
0N/A minKeySize = (int)info.ulMinKeySize << 3;
0N/A maxKeySize = (int)info.ulMaxKeySize << 3;
0N/A } else {
0N/A minKeySize = (int)info.ulMinKeySize;
0N/A maxKeySize = (int)info.ulMaxKeySize;
0N/A }
0N/A // Explicitly disallow keys shorter than 40-bits for security
0N/A if (minKeySize < 40) minKeySize = 40;
0N/A } else if (this.mechanism == CKM_BLOWFISH_KEY_GEN) {
0N/A CK_MECHANISM_INFO info = token.getMechanismInfo(mechanism);
0N/A maxKeySize = (int)info.ulMaxKeySize << 3;
0N/A minKeySize = (int)info.ulMinKeySize << 3;
0N/A // Explicitly disallow keys shorter than 40-bits for security
0N/A if (minKeySize < 40) minKeySize = 40;
0N/A }
0N/A
0N/A setDefaultKeySize();
0N/A }
0N/A
0N/A // set default keysize and also initialize keyType
0N/A private void setDefaultKeySize() {
0N/A // whether to check default key size against the min and max value
0N/A boolean validateKeySize = false;
0N/A switch ((int)mechanism) {
0N/A case (int)CKM_DES_KEY_GEN:
0N/A keySize = 64;
0N/A significantKeySize = 56;
0N/A keyType = CKK_DES;
0N/A break;
0N/A case (int)CKM_DES2_KEY_GEN:
0N/A keySize = 128;
0N/A significantKeySize = 112;
0N/A keyType = CKK_DES2;
0N/A break;
0N/A case (int)CKM_DES3_KEY_GEN:
0N/A keySize = 192;
0N/A significantKeySize = 168;
0N/A keyType = CKK_DES3;
0N/A break;
0N/A case (int)CKM_AES_KEY_GEN:
0N/A keyType = CKK_AES;
0N/A keySize = 128;
0N/A significantKeySize = 128;
0N/A break;
0N/A case (int)CKM_RC4_KEY_GEN:
0N/A keyType = CKK_RC4;
0N/A keySize = 128;
0N/A validateKeySize = true;
0N/A break;
0N/A case (int)CKM_BLOWFISH_KEY_GEN:
0N/A keyType = CKK_BLOWFISH;
0N/A keySize = 128;
0N/A validateKeySize = true;
0N/A break;
0N/A default:
0N/A throw new ProviderException("Unknown mechanism " + mechanism);
0N/A }
0N/A if (validateKeySize &&
0N/A ((keySize > maxKeySize) || (keySize < minKeySize))) {
0N/A throw new ProviderException("Unsupported key size");
0N/A }
0N/A }
0N/A
0N/A // see JCE spec
0N/A protected void engineInit(SecureRandom random) {
0N/A token.ensureValid();
0N/A setDefaultKeySize();
0N/A }
0N/A
0N/A // see JCE spec
0N/A protected void engineInit(AlgorithmParameterSpec params,
0N/A SecureRandom random) throws InvalidAlgorithmParameterException {
0N/A throw new InvalidAlgorithmParameterException
0N/A ("AlgorithmParameterSpec not supported");
0N/A }
0N/A
0N/A // see JCE spec
0N/A protected void engineInit(int keySize, SecureRandom random) {
0N/A token.ensureValid();
0N/A switch ((int)mechanism) {
0N/A case (int)CKM_DES_KEY_GEN:
0N/A if ((keySize != this.keySize) &&
0N/A (keySize != this.significantKeySize)) {
0N/A throw new InvalidParameterException
0N/A ("DES key length must be 56 bits");
0N/A }
0N/A break;
0N/A case (int)CKM_DES2_KEY_GEN:
0N/A case (int)CKM_DES3_KEY_GEN:
0N/A long newMechanism;
0N/A if ((keySize == 112) || (keySize == 128)) {
0N/A newMechanism = CKM_DES2_KEY_GEN;
0N/A } else if ((keySize == 168) || (keySize == 192)) {
0N/A newMechanism = CKM_DES3_KEY_GEN;
0N/A } else {
0N/A throw new InvalidParameterException
0N/A ("DESede key length must be 112, or 168 bits");
0N/A }
0N/A if (mechanism != newMechanism) {
0N/A if (supportBothKeySizes) {
0N/A mechanism = newMechanism;
0N/A setDefaultKeySize();
0N/A } else {
0N/A throw new InvalidParameterException
0N/A ("Only " + significantKeySize +
0N/A "-bit DESede key length is supported");
0N/A }
0N/A }
0N/A break;
0N/A case (int)CKM_AES_KEY_GEN:
0N/A if ((keySize != 128) && (keySize != 192) && (keySize != 256)) {
0N/A throw new InvalidParameterException
0N/A ("AES key length must be 128, 192, or 256 bits");
0N/A }
0N/A this.keySize = keySize;
0N/A significantKeySize = keySize;
0N/A break;
0N/A case (int)CKM_RC4_KEY_GEN:
0N/A case (int)CKM_BLOWFISH_KEY_GEN:
0N/A if ((keySize < minKeySize) || (keySize > maxKeySize)) {
0N/A throw new InvalidParameterException
0N/A (algorithm + " key length must be between " +
0N/A minKeySize + " and " + maxKeySize + " bits");
0N/A }
0N/A this.keySize = keySize;
0N/A this.significantKeySize = keySize;
0N/A break;
0N/A default:
0N/A throw new ProviderException("Unknown mechanism " + mechanism);
0N/A }
0N/A }
0N/A
0N/A // see JCE spec
0N/A protected SecretKey engineGenerateKey() {
0N/A Session session = null;
0N/A try {
0N/A session = token.getObjSession();
0N/A CK_ATTRIBUTE[] attributes;
0N/A switch ((int)keyType) {
0N/A case (int)CKK_DES:
0N/A case (int)CKK_DES2:
0N/A case (int)CKK_DES3:
0N/A // fixed length, do not specify CKA_VALUE_LEN
0N/A attributes = new CK_ATTRIBUTE[] {
0N/A new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
0N/A };
0N/A break;
0N/A default:
0N/A attributes = new CK_ATTRIBUTE[] {
0N/A new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
0N/A new CK_ATTRIBUTE(CKA_VALUE_LEN, keySize >> 3),
0N/A };
0N/A break;
0N/A }
0N/A attributes = token.getAttributes
0N/A (O_GENERATE, CKO_SECRET_KEY, keyType, attributes);
0N/A long keyID = token.p11.C_GenerateKey
0N/A (session.id(), new CK_MECHANISM(mechanism), attributes);
0N/A return P11Key.secretKey
0N/A (session, keyID, algorithm, significantKeySize, attributes);
0N/A } catch (PKCS11Exception e) {
0N/A throw new ProviderException("Could not generate key", e);
0N/A } finally {
0N/A token.releaseSession(session);
0N/A }
0N/A }
0N/A
0N/A}