0N/A/*
2362N/A * Copyright (c) 2003, 2008, 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.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
150N/A /**
150N/A * Utility method for checking if the specified key size is valid
150N/A * and within the supported range. Return the significant key size
150N/A * upon successful validation.
150N/A * @param keyGenMech the PKCS#11 key generation mechanism.
150N/A * @param keySize the to-be-checked key size for this mechanism.
150N/A * @param token token which provides this mechanism.
150N/A * @return the significant key size (in bits) corresponding to the
150N/A * specified key size.
150N/A * @throws InvalidParameterException if the specified key size is invalid.
150N/A * @throws ProviderException if this mechanism isn't supported by SunPKCS11
150N/A * or underlying native impl.
150N/A */
150N/A static int checkKeySize(long keyGenMech, int keySize, Token token)
150N/A throws InvalidAlgorithmParameterException, ProviderException {
150N/A int sigKeySize;
150N/A switch ((int)keyGenMech) {
150N/A case (int)CKM_DES_KEY_GEN:
150N/A if ((keySize != 64) && (keySize != 56)) {
150N/A throw new InvalidAlgorithmParameterException
150N/A ("DES key length must be 56 bits");
150N/A }
150N/A sigKeySize = 56;
150N/A break;
150N/A case (int)CKM_DES2_KEY_GEN:
150N/A case (int)CKM_DES3_KEY_GEN:
150N/A if ((keySize == 112) || (keySize == 128)) {
150N/A sigKeySize = 112;
150N/A } else if ((keySize == 168) || (keySize == 192)) {
150N/A sigKeySize = 168;
150N/A } else {
150N/A throw new InvalidAlgorithmParameterException
150N/A ("DESede key length must be 112, or 168 bits");
150N/A }
150N/A break;
150N/A default:
150N/A // Handle all variable-key-length algorithms here
150N/A CK_MECHANISM_INFO info = null;
150N/A try {
150N/A info = token.getMechanismInfo(keyGenMech);
150N/A } catch (PKCS11Exception p11e) {
150N/A // Should never happen
150N/A throw new ProviderException
150N/A ("Cannot retrieve mechanism info", p11e);
150N/A }
150N/A if (info == null) {
150N/A // XXX Unable to retrieve the supported key length from
150N/A // the underlying native impl. Skip the checking for now.
150N/A return keySize;
150N/A }
150N/A // PKCS#11 defines these to be in number of bytes except for
150N/A // RC4 which is in bits. However, some PKCS#11 impls still use
150N/A // bytes for all mechs, e.g. NSS. We try to detect this
150N/A // inconsistency if the minKeySize seems unreasonably small.
150N/A int minKeySize = (int)info.ulMinKeySize;
150N/A int maxKeySize = (int)info.ulMaxKeySize;
150N/A if (keyGenMech != CKM_RC4_KEY_GEN || minKeySize < 8) {
150N/A minKeySize = (int)info.ulMinKeySize << 3;
150N/A maxKeySize = (int)info.ulMaxKeySize << 3;
150N/A }
150N/A // Explicitly disallow keys shorter than 40-bits for security
150N/A if (minKeySize < 40) minKeySize = 40;
150N/A if (keySize < minKeySize || keySize > maxKeySize) {
150N/A throw new InvalidAlgorithmParameterException
150N/A ("Key length must be between " + minKeySize +
150N/A " and " + maxKeySize + " bits");
150N/A }
150N/A if (keyGenMech == CKM_AES_KEY_GEN) {
150N/A if ((keySize != 128) && (keySize != 192) &&
150N/A (keySize != 256)) {
150N/A throw new InvalidAlgorithmParameterException
150N/A ("AES key length must be " + minKeySize +
150N/A (maxKeySize >= 192? ", 192":"") +
150N/A (maxKeySize >= 256? ", or 256":"") + " bits");
150N/A }
150N/A }
150N/A sigKeySize = keySize;
150N/A }
150N/A return sigKeySize;
150N/A }
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 }
0N/A setDefaultKeySize();
0N/A }
0N/A
0N/A // set default keysize and also initialize keyType
0N/A private void setDefaultKeySize() {
0N/A switch ((int)mechanism) {
0N/A case (int)CKM_DES_KEY_GEN:
0N/A keySize = 64;
0N/A keyType = CKK_DES;
0N/A break;
0N/A case (int)CKM_DES2_KEY_GEN:
0N/A keySize = 128;
0N/A keyType = CKK_DES2;
0N/A break;
0N/A case (int)CKM_DES3_KEY_GEN:
0N/A keySize = 192;
0N/A keyType = CKK_DES3;
0N/A break;
0N/A case (int)CKM_AES_KEY_GEN:
150N/A keySize = 128;
0N/A keyType = CKK_AES;
0N/A break;
0N/A case (int)CKM_RC4_KEY_GEN:
150N/A keySize = 128;
0N/A keyType = CKK_RC4;
0N/A break;
0N/A case (int)CKM_BLOWFISH_KEY_GEN:
150N/A keySize = 128;
0N/A keyType = CKK_BLOWFISH;
0N/A break;
0N/A default:
0N/A throw new ProviderException("Unknown mechanism " + mechanism);
0N/A }
150N/A try {
150N/A significantKeySize = checkKeySize(mechanism, keySize, token);
150N/A } catch (InvalidAlgorithmParameterException iape) {
150N/A throw new ProviderException("Unsupported default key size", iape);
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();
150N/A int newSignificantKeySize;
150N/A try {
150N/A newSignificantKeySize = checkKeySize(mechanism, keySize, token);
150N/A } catch (InvalidAlgorithmParameterException iape) {
150N/A throw (InvalidParameterException)
150N/A (new InvalidParameterException().initCause(iape));
150N/A }
150N/A if ((mechanism == CKM_DES2_KEY_GEN) ||
150N/A (mechanism == CKM_DES3_KEY_GEN)) {
150N/A long newMechanism = (newSignificantKeySize == 112 ?
150N/A CKM_DES2_KEY_GEN : CKM_DES3_KEY_GEN);
0N/A if (mechanism != newMechanism) {
0N/A if (supportBothKeySizes) {
0N/A mechanism = newMechanism;
150N/A // Adjust keyType to reflect the mechanism change
150N/A keyType = (mechanism == CKM_DES2_KEY_GEN ?
150N/A CKK_DES2 : CKK_DES3);
0N/A } else {
0N/A throw new InvalidParameterException
150N/A ("Only " + significantKeySize +
150N/A "-bit DESede is supported");
0N/A }
0N/A }
0N/A }
150N/A this.keySize = keySize;
150N/A this.significantKeySize = newSignificantKeySize;
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}