Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/pkcs11/P11KeyGenerator.java
38919 views
/*1* Copyright (c) 2003, 2008, 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.security.*;28import java.security.spec.AlgorithmParameterSpec;2930import javax.crypto.*;3132import static sun.security.pkcs11.TemplateManager.*;33import sun.security.pkcs11.wrapper.*;34import static sun.security.pkcs11.wrapper.PKCS11Constants.*;3536/**37* KeyGenerator implementation class. This class currently supports38* DES, DESede, AES, ARCFOUR, and Blowfish.39*40* @author Andreas Sterbenz41* @since 1.542*/43final class P11KeyGenerator extends KeyGeneratorSpi {4445// token instance46private final Token token;4748// algorithm name49private final String algorithm;5051// mechanism id52private long mechanism;5354// raw key size in bits, e.g. 64 for DES. Always valid.55private int keySize;5657// bits of entropy in the key, e.g. 56 for DES. Always valid.58private int significantKeySize;5960// keyType (CKK_*), needed for TemplateManager call only.61private long keyType;6263// for determining if both 112 and 168 bits of DESede key lengths64// are supported.65private boolean supportBothKeySizes;6667/**68* Utility method for checking if the specified key size is valid69* and within the supported range. Return the significant key size70* upon successful validation.71* @param keyGenMech the PKCS#11 key generation mechanism.72* @param keySize the to-be-checked key size for this mechanism.73* @param token token which provides this mechanism.74* @return the significant key size (in bits) corresponding to the75* specified key size.76* @throws InvalidParameterException if the specified key size is invalid.77* @throws ProviderException if this mechanism isn't supported by SunPKCS1178* or underlying native impl.79*/80static int checkKeySize(long keyGenMech, int keySize, Token token)81throws InvalidAlgorithmParameterException, ProviderException {82int sigKeySize;83switch ((int)keyGenMech) {84case (int)CKM_DES_KEY_GEN:85if ((keySize != 64) && (keySize != 56)) {86throw new InvalidAlgorithmParameterException87("DES key length must be 56 bits");88}89sigKeySize = 56;90break;91case (int)CKM_DES2_KEY_GEN:92case (int)CKM_DES3_KEY_GEN:93if ((keySize == 112) || (keySize == 128)) {94sigKeySize = 112;95} else if ((keySize == 168) || (keySize == 192)) {96sigKeySize = 168;97} else {98throw new InvalidAlgorithmParameterException99("DESede key length must be 112, or 168 bits");100}101break;102default:103// Handle all variable-key-length algorithms here104CK_MECHANISM_INFO info = null;105try {106info = token.getMechanismInfo(keyGenMech);107} catch (PKCS11Exception p11e) {108// Should never happen109throw new ProviderException110("Cannot retrieve mechanism info", p11e);111}112if (info == null) {113// XXX Unable to retrieve the supported key length from114// the underlying native impl. Skip the checking for now.115return keySize;116}117// PKCS#11 defines these to be in number of bytes except for118// RC4 which is in bits. However, some PKCS#11 impls still use119// bytes for all mechs, e.g. NSS. We try to detect this120// inconsistency if the minKeySize seems unreasonably small.121int minKeySize = (int)info.ulMinKeySize;122int maxKeySize = (int)info.ulMaxKeySize;123if (keyGenMech != CKM_RC4_KEY_GEN || minKeySize < 8) {124minKeySize = (int)info.ulMinKeySize << 3;125maxKeySize = (int)info.ulMaxKeySize << 3;126}127// Explicitly disallow keys shorter than 40-bits for security128if (minKeySize < 40) minKeySize = 40;129if (keySize < minKeySize || keySize > maxKeySize) {130throw new InvalidAlgorithmParameterException131("Key length must be between " + minKeySize +132" and " + maxKeySize + " bits");133}134if (keyGenMech == CKM_AES_KEY_GEN) {135if ((keySize != 128) && (keySize != 192) &&136(keySize != 256)) {137throw new InvalidAlgorithmParameterException138("AES key length must be " + minKeySize +139(maxKeySize >= 192? ", 192":"") +140(maxKeySize >= 256? ", or 256":"") + " bits");141}142}143sigKeySize = keySize;144}145return sigKeySize;146}147148P11KeyGenerator(Token token, String algorithm, long mechanism)149throws PKCS11Exception {150super();151this.token = token;152this.algorithm = algorithm;153this.mechanism = mechanism;154155if (this.mechanism == CKM_DES3_KEY_GEN) {156/* Given the current lookup order specified in SunPKCS11.java,157if CKM_DES2_KEY_GEN is used to construct this object, it158means that CKM_DES3_KEY_GEN is disabled or unsupported.159*/160supportBothKeySizes =161(token.provider.config.isEnabled(CKM_DES2_KEY_GEN) &&162(token.getMechanismInfo(CKM_DES2_KEY_GEN) != null));163}164setDefaultKeySize();165}166167// set default keysize and also initialize keyType168private void setDefaultKeySize() {169switch ((int)mechanism) {170case (int)CKM_DES_KEY_GEN:171keySize = 64;172keyType = CKK_DES;173break;174case (int)CKM_DES2_KEY_GEN:175keySize = 128;176keyType = CKK_DES2;177break;178case (int)CKM_DES3_KEY_GEN:179keySize = 192;180keyType = CKK_DES3;181break;182case (int)CKM_AES_KEY_GEN:183keySize = 128;184keyType = CKK_AES;185break;186case (int)CKM_RC4_KEY_GEN:187keySize = 128;188keyType = CKK_RC4;189break;190case (int)CKM_BLOWFISH_KEY_GEN:191keySize = 128;192keyType = CKK_BLOWFISH;193break;194default:195throw new ProviderException("Unknown mechanism " + mechanism);196}197try {198significantKeySize = checkKeySize(mechanism, keySize, token);199} catch (InvalidAlgorithmParameterException iape) {200throw new ProviderException("Unsupported default key size", iape);201}202}203204// see JCE spec205protected void engineInit(SecureRandom random) {206token.ensureValid();207setDefaultKeySize();208}209210// see JCE spec211protected void engineInit(AlgorithmParameterSpec params,212SecureRandom random) throws InvalidAlgorithmParameterException {213throw new InvalidAlgorithmParameterException214("AlgorithmParameterSpec not supported");215}216217// see JCE spec218protected void engineInit(int keySize, SecureRandom random) {219token.ensureValid();220int newSignificantKeySize;221try {222newSignificantKeySize = checkKeySize(mechanism, keySize, token);223} catch (InvalidAlgorithmParameterException iape) {224throw (InvalidParameterException)225(new InvalidParameterException().initCause(iape));226}227if ((mechanism == CKM_DES2_KEY_GEN) ||228(mechanism == CKM_DES3_KEY_GEN)) {229long newMechanism = (newSignificantKeySize == 112 ?230CKM_DES2_KEY_GEN : CKM_DES3_KEY_GEN);231if (mechanism != newMechanism) {232if (supportBothKeySizes) {233mechanism = newMechanism;234// Adjust keyType to reflect the mechanism change235keyType = (mechanism == CKM_DES2_KEY_GEN ?236CKK_DES2 : CKK_DES3);237} else {238throw new InvalidParameterException239("Only " + significantKeySize +240"-bit DESede is supported");241}242}243}244this.keySize = keySize;245this.significantKeySize = newSignificantKeySize;246}247248// see JCE spec249protected SecretKey engineGenerateKey() {250Session session = null;251try {252session = token.getObjSession();253CK_ATTRIBUTE[] attributes;254switch ((int)keyType) {255case (int)CKK_DES:256case (int)CKK_DES2:257case (int)CKK_DES3:258// fixed length, do not specify CKA_VALUE_LEN259attributes = new CK_ATTRIBUTE[] {260new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),261};262break;263default:264attributes = new CK_ATTRIBUTE[] {265new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),266new CK_ATTRIBUTE(CKA_VALUE_LEN, keySize >> 3),267};268break;269}270attributes = token.getAttributes271(O_GENERATE, CKO_SECRET_KEY, keyType, attributes);272long keyID = token.p11.C_GenerateKey273(session.id(), new CK_MECHANISM(mechanism), attributes);274return P11Key.secretKey275(session, keyID, algorithm, significantKeySize, attributes);276} catch (PKCS11Exception e) {277throw new ProviderException("Could not generate key", e);278} finally {279token.releaseSession(session);280}281}282283}284285286