Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java
38919 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.*;40import static sun.security.pkcs11.wrapper.PKCS11Constants.*;4142/**43* KeyGenerator to calculate the SSL/TLS key material (cipher keys and ivs,44* mac keys) from the master secret.45*46* @author Andreas Sterbenz47* @since 1.648*/49public final class P11TlsKeyMaterialGenerator extends KeyGeneratorSpi {5051private final static String MSG = "TlsKeyMaterialGenerator must be "52+ "initialized using a TlsKeyMaterialParameterSpec";5354// token instance55private final Token token;5657// algorithm name58private final String algorithm;5960// mechanism id61private long mechanism;6263// parameter spec64private TlsKeyMaterialParameterSpec spec;6566// master secret as a P11Key67private P11Key p11Key;6869// version, e.g. 0x030170private int version;7172P11TlsKeyMaterialGenerator(Token token, String algorithm, long mechanism)73throws PKCS11Exception {74super();75this.token = token;76this.algorithm = algorithm;77this.mechanism = mechanism;78}7980protected void engineInit(SecureRandom random) {81throw new InvalidParameterException(MSG);82}8384protected void engineInit(AlgorithmParameterSpec params,85SecureRandom random) throws InvalidAlgorithmParameterException {86if (params instanceof TlsKeyMaterialParameterSpec == false) {87throw new InvalidAlgorithmParameterException(MSG);88}89this.spec = (TlsKeyMaterialParameterSpec)params;90try {91p11Key = P11SecretKeyFactory.convertKey92(token, spec.getMasterSecret(), "TlsMasterSecret");93} catch (InvalidKeyException e) {94throw new InvalidAlgorithmParameterException("init() failed", e);95}96version = (spec.getMajorVersion() << 8) | spec.getMinorVersion();97if ((version < 0x0300) && (version > 0x0303)) {98throw new InvalidAlgorithmParameterException("Only SSL 3.0," +99" TLS 1.0, TLS 1.1, and TLS 1.2 are supported");100}101// we assume the token supports both the CKM_SSL3_* and the CKM_TLS_*102// mechanisms103}104105protected void engineInit(int keysize, SecureRandom random) {106throw new InvalidParameterException(MSG);107}108109protected SecretKey engineGenerateKey() {110if (spec == null) {111throw new IllegalStateException112("TlsKeyMaterialGenerator must be initialized");113}114if (version == 0x0300) {115mechanism = CKM_SSL3_KEY_AND_MAC_DERIVE;116} else if (version == 0x0301 || version == 0x0302) {117mechanism = CKM_TLS_KEY_AND_MAC_DERIVE;118}119int macBits = spec.getMacKeyLength() << 3;120int ivBits = spec.getIvLength() << 3;121122int expandedKeyBits = spec.getExpandedCipherKeyLength() << 3;123int keyBits = spec.getCipherKeyLength() << 3;124boolean isExportable;125if (expandedKeyBits != 0) {126isExportable = true;127} else {128isExportable = false;129expandedKeyBits = keyBits;130}131132CK_SSL3_RANDOM_DATA random = new CK_SSL3_RANDOM_DATA133(spec.getClientRandom(), spec.getServerRandom());134Object params = null;135CK_MECHANISM ckMechanism = null;136if (version < 0x0303) {137params = new CK_SSL3_KEY_MAT_PARAMS138(macBits, keyBits, ivBits, isExportable, random);139ckMechanism = new CK_MECHANISM(mechanism, (CK_SSL3_KEY_MAT_PARAMS)params);140} else if (version == 0x0303) {141params = new CK_TLS12_KEY_MAT_PARAMS142(macBits, keyBits, ivBits, isExportable, random,143Functions.getHashMechId(spec.getPRFHashAlg()));144ckMechanism = new CK_MECHANISM(mechanism, (CK_TLS12_KEY_MAT_PARAMS)params);145}146147String cipherAlgorithm = spec.getCipherAlgorithm();148long keyType = P11SecretKeyFactory.getKeyType(cipherAlgorithm);149if (keyType < 0) {150if (keyBits != 0) {151throw new ProviderException152("Unknown algorithm: " + spec.getCipherAlgorithm());153} else {154// NULL encryption ciphersuites155keyType = CKK_GENERIC_SECRET;156}157}158159Session session = null;160try {161session = token.getObjSession();162CK_ATTRIBUTE[] attributes;163if (keyBits != 0) {164attributes = new CK_ATTRIBUTE[] {165new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),166new CK_ATTRIBUTE(CKA_KEY_TYPE, keyType),167new CK_ATTRIBUTE(CKA_VALUE_LEN, expandedKeyBits >> 3),168};169} else {170// ciphersuites with NULL ciphers171attributes = new CK_ATTRIBUTE[0];172}173attributes = token.getAttributes174(O_GENERATE, CKO_SECRET_KEY, keyType, attributes);175long p11KeyID = p11Key.getKeyID();176try {177token.p11.C_DeriveKey(session.id(),178ckMechanism, p11KeyID, attributes);179} finally {180p11Key.releaseKeyID();181}182183CK_SSL3_KEY_MAT_OUT out = null;184if (params instanceof CK_SSL3_KEY_MAT_PARAMS) {185out = ((CK_SSL3_KEY_MAT_PARAMS)params).pReturnedKeyMaterial;186} else if (params instanceof CK_TLS12_KEY_MAT_PARAMS) {187out = ((CK_TLS12_KEY_MAT_PARAMS)params).pReturnedKeyMaterial;188}189// Note that the MAC keys do not inherit all attributes from the190// template, but they do inherit the sensitive/extractable/token191// flags, which is all P11Key cares about.192SecretKey clientMacKey, serverMacKey;193194// The MAC size may be zero for GCM mode.195//196// PKCS11 does not support GCM mode as the author made the comment,197// so the macBits is unlikely to be zero. It's only a place holder.198if (macBits != 0) {199clientMacKey = P11Key.secretKey200(session, out.hClientMacSecret, "MAC", macBits, attributes);201serverMacKey = P11Key.secretKey202(session, out.hServerMacSecret, "MAC", macBits, attributes);203} else {204clientMacKey = null;205serverMacKey = null;206}207208SecretKey clientCipherKey, serverCipherKey;209if (keyBits != 0) {210clientCipherKey = P11Key.secretKey(session, out.hClientKey,211cipherAlgorithm, expandedKeyBits, attributes);212serverCipherKey = P11Key.secretKey(session, out.hServerKey,213cipherAlgorithm, expandedKeyBits, attributes);214} else {215clientCipherKey = null;216serverCipherKey = null;217}218IvParameterSpec clientIv = (out.pIVClient == null)219? null : new IvParameterSpec(out.pIVClient);220IvParameterSpec serverIv = (out.pIVServer == null)221? null : new IvParameterSpec(out.pIVServer);222223return new TlsKeyMaterialSpec(clientMacKey, serverMacKey,224clientCipherKey, clientIv, serverCipherKey, serverIv);225226} catch (Exception e) {227throw new ProviderException("Could not generate key", e);228} finally {229token.releaseSession(session);230}231}232233}234235236