Path: blob/master/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java
41154 views
/*1* Copyright (c) 2005, 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.AlgorithmParameterSpec;3132import javax.crypto.*;33import javax.crypto.spec.*;3435import sun.security.internal.spec.*;36import sun.security.internal.interfaces.TlsMasterSecret;3738import static sun.security.pkcs11.TemplateManager.*;39import sun.security.pkcs11.wrapper.*;4041import static sun.security.pkcs11.wrapper.PKCS11Constants.*;4243/**44* KeyGenerator to calculate the SSL/TLS key material (cipher keys and ivs,45* mac keys) from the master secret.46*47* @author Andreas Sterbenz48* @since 1.649*/50public final class P11TlsKeyMaterialGenerator extends KeyGeneratorSpi {5152private static final String MSG = "TlsKeyMaterialGenerator must be "53+ "initialized using a TlsKeyMaterialParameterSpec";5455// token instance56private final Token token;5758// algorithm name59private final String algorithm;6061// mechanism id62private long mechanism;6364private int tlsVersion;6566// parameter spec67@SuppressWarnings("deprecation")68private TlsKeyMaterialParameterSpec spec;6970// master secret as a P11Key71private P11Key p11Key;7273// whether SSLv3 is supported74private final boolean supportSSLv3;7576P11TlsKeyMaterialGenerator(Token token, String algorithm, long mechanism)77throws PKCS11Exception {78super();79this.token = token;80this.algorithm = algorithm;81this.mechanism = mechanism;8283// Given the current lookup order specified in SunPKCS11.java,84// if CKM_SSL3_KEY_AND_MAC_DERIVE is not used to construct this object,85// it means that this mech is disabled or unsupported.86this.supportSSLv3 = (mechanism == CKM_SSL3_KEY_AND_MAC_DERIVE);87}8889protected void engineInit(SecureRandom random) {90throw new InvalidParameterException(MSG);91}9293@SuppressWarnings("deprecation")94protected void engineInit(AlgorithmParameterSpec params,95SecureRandom random) throws InvalidAlgorithmParameterException {96if (params instanceof TlsKeyMaterialParameterSpec == false) {97throw new InvalidAlgorithmParameterException(MSG);98}99100TlsKeyMaterialParameterSpec spec = (TlsKeyMaterialParameterSpec)params;101tlsVersion = (spec.getMajorVersion() << 8) | spec.getMinorVersion();102103if ((tlsVersion == 0x0300 && !supportSSLv3) ||104(tlsVersion < 0x0300) || (tlsVersion > 0x0303)) {105throw new InvalidAlgorithmParameterException106("Only" + (supportSSLv3? " SSL 3.0,": "") +107" TLS 1.0, TLS 1.1 and TLS 1.2 are supported (" +108tlsVersion + ")");109}110try {111p11Key = P11SecretKeyFactory.convertKey112(token, spec.getMasterSecret(), "TlsMasterSecret");113} catch (InvalidKeyException e) {114throw new InvalidAlgorithmParameterException("init() failed", e);115}116this.spec = spec;117if (tlsVersion == 0x0300) {118mechanism = CKM_SSL3_KEY_AND_MAC_DERIVE;119} else if (tlsVersion == 0x0301 || tlsVersion == 0x0302) {120mechanism = CKM_TLS_KEY_AND_MAC_DERIVE;121}122}123124protected void engineInit(int keysize, SecureRandom random) {125throw new InvalidParameterException(MSG);126}127128@SuppressWarnings("deprecation")129protected SecretKey engineGenerateKey() {130if (spec == null) {131throw new IllegalStateException132("TlsKeyMaterialGenerator must be initialized");133}134int macBits = spec.getMacKeyLength() << 3;135int ivBits = spec.getIvLength() << 3;136137int expandedKeyBits = spec.getExpandedCipherKeyLength() << 3;138int keyBits = spec.getCipherKeyLength() << 3;139boolean isExportable;140if (expandedKeyBits != 0) {141isExportable = true;142} else {143isExportable = false;144expandedKeyBits = keyBits;145}146147CK_SSL3_RANDOM_DATA random = new CK_SSL3_RANDOM_DATA148(spec.getClientRandom(), spec.getServerRandom());149Object params = null;150CK_MECHANISM ckMechanism = null;151if (tlsVersion < 0x0303) {152params = new CK_SSL3_KEY_MAT_PARAMS153(macBits, keyBits, ivBits, isExportable, random);154ckMechanism = new CK_MECHANISM(mechanism, (CK_SSL3_KEY_MAT_PARAMS)params);155} else if (tlsVersion == 0x0303) {156params = new CK_TLS12_KEY_MAT_PARAMS157(macBits, keyBits, ivBits, isExportable, random,158Functions.getHashMechId(spec.getPRFHashAlg()));159ckMechanism = new CK_MECHANISM(mechanism, (CK_TLS12_KEY_MAT_PARAMS)params);160}161162String cipherAlgorithm = spec.getCipherAlgorithm();163long keyType = P11SecretKeyFactory.getKeyType(cipherAlgorithm);164if (keyType < 0) {165if (keyBits != 0) {166throw new ProviderException167("Unknown algorithm: " + spec.getCipherAlgorithm());168} else {169// NULL encryption ciphersuites170keyType = CKK_GENERIC_SECRET;171}172}173174Session session = null;175try {176session = token.getObjSession();177CK_ATTRIBUTE[] attributes;178if (keyBits != 0) {179attributes = new CK_ATTRIBUTE[] {180new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),181new CK_ATTRIBUTE(CKA_KEY_TYPE, keyType),182new CK_ATTRIBUTE(CKA_VALUE_LEN, expandedKeyBits >> 3),183};184} else {185// ciphersuites with NULL ciphers186attributes = new CK_ATTRIBUTE[0];187}188attributes = token.getAttributes189(O_GENERATE, CKO_SECRET_KEY, keyType, attributes);190// the returned keyID is a dummy, ignore191long p11KeyID = p11Key.getKeyID();192try {193token.p11.C_DeriveKey(session.id(),194ckMechanism, p11KeyID, attributes);195} finally {196p11Key.releaseKeyID();197}198199CK_SSL3_KEY_MAT_OUT out = null;200if (params instanceof CK_SSL3_KEY_MAT_PARAMS) {201out = ((CK_SSL3_KEY_MAT_PARAMS)params).pReturnedKeyMaterial;202} else if (params instanceof CK_TLS12_KEY_MAT_PARAMS) {203out = ((CK_TLS12_KEY_MAT_PARAMS)params).pReturnedKeyMaterial;204}205// Note that the MAC keys do not inherit all attributes from the206// template, but they do inherit the sensitive/extractable/token207// flags, which is all P11Key cares about.208SecretKey clientMacKey, serverMacKey;209210// The MAC size may be zero for GCM mode.211//212// PKCS11 does not support GCM mode as the author made the comment,213// so the macBits is unlikely to be zero. It's only a place holder.214if (macBits != 0) {215clientMacKey = P11Key.secretKey216(session, out.hClientMacSecret, "MAC", macBits, attributes);217serverMacKey = P11Key.secretKey218(session, out.hServerMacSecret, "MAC", macBits, attributes);219} else {220clientMacKey = null;221serverMacKey = null;222}223224SecretKey clientCipherKey, serverCipherKey;225if (keyBits != 0) {226clientCipherKey = P11Key.secretKey(session, out.hClientKey,227cipherAlgorithm, expandedKeyBits, attributes);228serverCipherKey = P11Key.secretKey(session, out.hServerKey,229cipherAlgorithm, expandedKeyBits, attributes);230} else {231clientCipherKey = null;232serverCipherKey = null;233}234IvParameterSpec clientIv = (out.pIVClient == null)235? null : new IvParameterSpec(out.pIVClient);236IvParameterSpec serverIv = (out.pIVServer == null)237? null : new IvParameterSpec(out.pIVServer);238239return new TlsKeyMaterialSpec(clientMacKey, serverMacKey,240clientCipherKey, clientIv, serverCipherKey, serverIv);241242} catch (Exception e) {243throw new ProviderException("Could not generate key", e);244} finally {245token.releaseSession(session);246}247}248249}250251252