Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/pkcs11/P11SecretKeyFactory.java
38919 views
/*1* Copyright (c) 2003, 2018, 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.util.*;2829import java.security.*;30import java.security.spec.*;3132import javax.crypto.*;33import javax.crypto.spec.*;3435import static sun.security.pkcs11.TemplateManager.*;36import sun.security.pkcs11.wrapper.*;37import static sun.security.pkcs11.wrapper.PKCS11Constants.*;3839/**40* SecretKeyFactory implementation class. This class currently supports41* DES, DESede, AES, ARCFOUR, and Blowfish.42*43* @author Andreas Sterbenz44* @since 1.545*/46final class P11SecretKeyFactory extends SecretKeyFactorySpi {4748// token instance49private final Token token;5051// algorithm name52private final String algorithm;5354P11SecretKeyFactory(Token token, String algorithm) {55super();56this.token = token;57this.algorithm = algorithm;58}5960private static final Map<String,Long> keyTypes;6162static {63keyTypes = new HashMap<String,Long>();64addKeyType("RC4", CKK_RC4);65addKeyType("ARCFOUR", CKK_RC4);66addKeyType("DES", CKK_DES);67addKeyType("DESede", CKK_DES3);68addKeyType("AES", CKK_AES);69addKeyType("Blowfish", CKK_BLOWFISH);7071// we don't implement RC2 or IDEA, but we want to be able to generate72// keys for those SSL/TLS ciphersuites.73addKeyType("RC2", CKK_RC2);74addKeyType("IDEA", CKK_IDEA);7576addKeyType("TlsPremasterSecret", PCKK_TLSPREMASTER);77addKeyType("TlsRsaPremasterSecret", PCKK_TLSRSAPREMASTER);78addKeyType("TlsMasterSecret", PCKK_TLSMASTER);79addKeyType("Generic", CKK_GENERIC_SECRET);80}8182private static void addKeyType(String name, long id) {83Long l = Long.valueOf(id);84keyTypes.put(name, l);85keyTypes.put(name.toUpperCase(Locale.ENGLISH), l);86}8788static long getKeyType(String algorithm) {89Long l = keyTypes.get(algorithm);90if (l == null) {91algorithm = algorithm.toUpperCase(Locale.ENGLISH);92l = keyTypes.get(algorithm);93if (l == null) {94if (algorithm.startsWith("HMAC")) {95return PCKK_HMAC;96} else if (algorithm.startsWith("SSLMAC")) {97return PCKK_SSLMAC;98}99}100}101return (l != null) ? l.longValue() : -1;102}103104/**105* Convert an arbitrary key of algorithm into a P11Key of provider.106* Used in engineTranslateKey(), P11Cipher.init(), and P11Mac.init().107*/108static P11Key convertKey(Token token, Key key, String algo)109throws InvalidKeyException {110return convertKey(token, key, algo, null);111}112113/**114* Convert an arbitrary key of algorithm w/ custom attributes into a115* P11Key of provider.116* Used in P11KeyStore.storeSkey.117*/118static P11Key convertKey(Token token, Key key, String algo,119CK_ATTRIBUTE[] extraAttrs)120throws InvalidKeyException {121token.ensureValid();122if (key == null) {123throw new InvalidKeyException("Key must not be null");124}125if (key instanceof SecretKey == false) {126throw new InvalidKeyException("Key must be a SecretKey");127}128long algoType;129if (algo == null) {130algo = key.getAlgorithm();131algoType = getKeyType(algo);132} else {133algoType = getKeyType(algo);134long keyAlgorithmType = getKeyType(key.getAlgorithm());135if (algoType != keyAlgorithmType) {136if ((algoType == PCKK_HMAC) || (algoType == PCKK_SSLMAC)) {137// ignore key algorithm for MACs138} else {139throw new InvalidKeyException140("Key algorithm must be " + algo);141}142}143}144if (key instanceof P11Key) {145P11Key p11Key = (P11Key)key;146if (p11Key.token == token) {147if (extraAttrs != null) {148P11Key newP11Key = null;149Session session = null;150long p11KeyID = p11Key.getKeyID();151try {152session = token.getObjSession();153long newKeyID = token.p11.C_CopyObject(session.id(),154p11KeyID, extraAttrs);155newP11Key = (P11Key) (P11Key.secretKey(session,156newKeyID, p11Key.algorithm, p11Key.keyLength,157extraAttrs));158} catch (PKCS11Exception p11e) {159throw new InvalidKeyException160("Cannot duplicate the PKCS11 key", p11e);161} finally {162p11Key.releaseKeyID();163token.releaseSession(session);164}165p11Key = newP11Key;166}167return p11Key;168}169}170P11Key p11Key = token.secretCache.get(key);171if (p11Key != null) {172return p11Key;173}174if ("RAW".equalsIgnoreCase(key.getFormat()) == false) {175throw new InvalidKeyException("Encoded format must be RAW");176}177byte[] encoded = key.getEncoded();178p11Key = createKey(token, encoded, algo, algoType, extraAttrs);179token.secretCache.put(key, p11Key);180return p11Key;181}182183static void fixDESParity(byte[] key, int offset) {184for (int i = 0; i < 8; i++) {185int b = key[offset] & 0xfe;186b |= (Integer.bitCount(b) & 1) ^ 1;187key[offset++] = (byte)b;188}189}190191private static P11Key createKey(Token token, byte[] encoded,192String algorithm, long keyType, CK_ATTRIBUTE[] extraAttrs)193throws InvalidKeyException {194int n = encoded.length << 3;195int keyLength = n;196try {197switch ((int)keyType) {198case (int)CKK_DES:199keyLength =200P11KeyGenerator.checkKeySize(CKM_DES_KEY_GEN, n, token);201fixDESParity(encoded, 0);202break;203case (int)CKK_DES3:204keyLength =205P11KeyGenerator.checkKeySize(CKM_DES3_KEY_GEN, n, token);206fixDESParity(encoded, 0);207fixDESParity(encoded, 8);208if (keyLength == 112) {209keyType = CKK_DES2;210} else {211keyType = CKK_DES3;212fixDESParity(encoded, 16);213}214break;215case (int)CKK_AES:216keyLength =217P11KeyGenerator.checkKeySize(CKM_AES_KEY_GEN, n, token);218break;219case (int)CKK_RC4:220keyLength =221P11KeyGenerator.checkKeySize(CKM_RC4_KEY_GEN, n, token);222break;223case (int)CKK_BLOWFISH:224keyLength =225P11KeyGenerator.checkKeySize(CKM_BLOWFISH_KEY_GEN, n,226token);227break;228case (int)CKK_GENERIC_SECRET:229case (int)PCKK_TLSPREMASTER:230case (int)PCKK_TLSRSAPREMASTER:231case (int)PCKK_TLSMASTER:232keyType = CKK_GENERIC_SECRET;233break;234case (int)PCKK_SSLMAC:235case (int)PCKK_HMAC:236if (n == 0) {237throw new InvalidKeyException238("MAC keys must not be empty");239}240keyType = CKK_GENERIC_SECRET;241break;242default:243throw new InvalidKeyException("Unknown algorithm " +244algorithm);245}246} catch (InvalidAlgorithmParameterException iape) {247throw new InvalidKeyException("Invalid key for " + algorithm,248iape);249} catch (ProviderException pe) {250throw new InvalidKeyException("Could not create key", pe);251}252Session session = null;253try {254CK_ATTRIBUTE[] attributes;255if (extraAttrs != null) {256attributes = new CK_ATTRIBUTE[3 + extraAttrs.length];257System.arraycopy(extraAttrs, 0, attributes, 3,258extraAttrs.length);259} else {260attributes = new CK_ATTRIBUTE[3];261}262attributes[0] = new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY);263attributes[1] = new CK_ATTRIBUTE(CKA_KEY_TYPE, keyType);264attributes[2] = new CK_ATTRIBUTE(CKA_VALUE, encoded);265attributes = token.getAttributes266(O_IMPORT, CKO_SECRET_KEY, keyType, attributes);267session = token.getObjSession();268long keyID = token.p11.C_CreateObject(session.id(), attributes);269P11Key p11Key = (P11Key)P11Key.secretKey270(session, keyID, algorithm, keyLength, attributes);271return p11Key;272} catch (PKCS11Exception e) {273throw new InvalidKeyException("Could not create key", e);274} finally {275token.releaseSession(session);276}277}278279// see JCE spec280protected SecretKey engineGenerateSecret(KeySpec keySpec)281throws InvalidKeySpecException {282token.ensureValid();283if (keySpec == null) {284throw new InvalidKeySpecException("KeySpec must not be null");285}286if (keySpec instanceof SecretKeySpec) {287try {288Key key = convertKey(token, (SecretKey)keySpec, algorithm);289return (SecretKey)key;290} catch (InvalidKeyException e) {291throw new InvalidKeySpecException(e);292}293} else if (algorithm.equalsIgnoreCase("DES")) {294if (keySpec instanceof DESKeySpec) {295byte[] keyBytes = ((DESKeySpec)keySpec).getKey();296keySpec = new SecretKeySpec(keyBytes, "DES");297return engineGenerateSecret(keySpec);298}299} else if (algorithm.equalsIgnoreCase("DESede")) {300if (keySpec instanceof DESedeKeySpec) {301byte[] keyBytes = ((DESedeKeySpec)keySpec).getKey();302keySpec = new SecretKeySpec(keyBytes, "DESede");303return engineGenerateSecret(keySpec);304}305}306throw new InvalidKeySpecException307("Unsupported spec: " + keySpec.getClass().getName());308}309310private byte[] getKeyBytes(SecretKey key) throws InvalidKeySpecException {311try {312key = engineTranslateKey(key);313if ("RAW".equalsIgnoreCase(key.getFormat()) == false) {314throw new InvalidKeySpecException315("Could not obtain key bytes");316}317byte[] k = key.getEncoded();318return k;319} catch (InvalidKeyException e) {320throw new InvalidKeySpecException(e);321}322}323324// see JCE spec325protected KeySpec engineGetKeySpec(SecretKey key, Class<?> keySpec)326throws InvalidKeySpecException {327token.ensureValid();328if ((key == null) || (keySpec == null)) {329throw new InvalidKeySpecException330("key and keySpec must not be null");331}332if (SecretKeySpec.class.isAssignableFrom(keySpec)) {333return new SecretKeySpec(getKeyBytes(key), algorithm);334} else if (algorithm.equalsIgnoreCase("DES")) {335try {336if (DESKeySpec.class.isAssignableFrom(keySpec)) {337return new DESKeySpec(getKeyBytes(key));338}339} catch (InvalidKeyException e) {340throw new InvalidKeySpecException(e);341}342} else if (algorithm.equalsIgnoreCase("DESede")) {343try {344if (DESedeKeySpec.class.isAssignableFrom(keySpec)) {345return new DESedeKeySpec(getKeyBytes(key));346}347} catch (InvalidKeyException e) {348throw new InvalidKeySpecException(e);349}350}351throw new InvalidKeySpecException352("Unsupported spec: " + keySpec.getName());353}354355// see JCE spec356protected SecretKey engineTranslateKey(SecretKey key)357throws InvalidKeyException {358return (SecretKey)convertKey(token, key, algorithm);359}360361}362363364