Path: blob/master/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11TlsPrfGenerator.java
41154 views
/*1* Copyright (c) 2005, 2019, 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.*;31import javax.crypto.spec.*;3233import static java.nio.charset.StandardCharsets.UTF_8;3435import sun.security.internal.spec.TlsPrfParameterSpec;3637import static sun.security.pkcs11.TemplateManager.*;38import sun.security.pkcs11.wrapper.*;39import static sun.security.pkcs11.wrapper.PKCS11Constants.*;4041/**42* KeyGenerator for the TLS PRF. Note that although the PRF is used in a number43* of places during the handshake, this class is usually only used to calculate44* the Finished messages. The reason is that for those other uses more specific45* PKCS#11 mechanisms have been defined (CKM_SSL3_MASTER_KEY_DERIVE, etc.).46*47* <p>This class supports the CKM_TLS_PRF mechanism from PKCS#11 v2.20 and48* the older NSS private mechanism.49*50* @author Andreas Sterbenz51* @since 1.652*/53final class P11TlsPrfGenerator extends KeyGeneratorSpi {5455private static final String MSG =56"TlsPrfGenerator must be initialized using a TlsPrfParameterSpec";5758// token instance59private final Token token;6061// algorithm name62private final String algorithm;6364// mechanism id65private final long mechanism;6667@SuppressWarnings("deprecation")68private TlsPrfParameterSpec spec;6970private P11Key p11Key;7172P11TlsPrfGenerator(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}8384@SuppressWarnings("deprecation")85protected void engineInit(AlgorithmParameterSpec params,86SecureRandom random) throws InvalidAlgorithmParameterException {87if (params instanceof TlsPrfParameterSpec == false) {88throw new InvalidAlgorithmParameterException(MSG);89}90this.spec = (TlsPrfParameterSpec)params;91SecretKey key = spec.getSecret();92if (key == null) {93key = NULL_KEY;94}95try {96p11Key = P11SecretKeyFactory.convertKey(token, key, null);97} catch (InvalidKeyException e) {98throw new InvalidAlgorithmParameterException("init() failed", e);99}100}101102// SecretKeySpec does not allow zero length keys, so we define our103// own class.104//105// As an anonymous class cannot make any guarantees about serialization106// compatibility, it is nonsensical for an anonymous class to define a107// serialVersionUID. Suppress warnings relative to missing serialVersionUID108// field in the anonymous subclass of serializable SecretKey.109@SuppressWarnings("serial")110private static final SecretKey NULL_KEY = new SecretKey() {111public byte[] getEncoded() {112return new byte[0];113}114public String getFormat() {115return "RAW";116}117public String getAlgorithm() {118return "Generic";119}120};121122protected void engineInit(int keysize, SecureRandom random) {123throw new InvalidParameterException(MSG);124}125126protected SecretKey engineGenerateKey() {127if (spec == null) {128throw new IllegalStateException("TlsPrfGenerator must be initialized");129}130131byte[] seed = spec.getSeed();132133// TLS 1.2134if (mechanism == CKM_TLS_MAC) {135SecretKey k = null;136int ulServerOrClient = 0;137if (spec.getLabel().equals("server finished")) {138ulServerOrClient = 1;139}140if (spec.getLabel().equals("client finished")) {141ulServerOrClient = 2;142}143144if (ulServerOrClient != 0) {145// Finished message146CK_TLS_MAC_PARAMS params = new CK_TLS_MAC_PARAMS(147Functions.getHashMechId(spec.getPRFHashAlg()),148spec.getOutputLength(), ulServerOrClient);149Session session = null;150long keyID = p11Key.getKeyID();151try {152session = token.getOpSession();153token.p11.C_SignInit(session.id(),154new CK_MECHANISM(mechanism, params), keyID);155token.p11.C_SignUpdate(session.id(), 0, seed, 0, seed.length);156byte[] out = token.p11.C_SignFinal157(session.id(), spec.getOutputLength());158return new SecretKeySpec(out, "TlsPrf");159} catch (PKCS11Exception e) {160throw new ProviderException("Could not calculate PRF", e);161} finally {162p11Key.releaseKeyID();163token.releaseSession(session);164}165} else {166throw new ProviderException("Only Finished message authentication code"+167" generation supported for TLS 1.2.");168}169}170171byte[] label = spec.getLabel().getBytes(UTF_8);172173if (mechanism == CKM_NSS_TLS_PRF_GENERAL) {174Session session = null;175long keyID = p11Key.getKeyID();176try {177session = token.getOpSession();178token.p11.C_SignInit179(session.id(), new CK_MECHANISM(mechanism), keyID);180token.p11.C_SignUpdate(session.id(), 0, label, 0, label.length);181token.p11.C_SignUpdate(session.id(), 0, seed, 0, seed.length);182byte[] out = token.p11.C_SignFinal183(session.id(), spec.getOutputLength());184return new SecretKeySpec(out, "TlsPrf");185} catch (PKCS11Exception e) {186throw new ProviderException("Could not calculate PRF", e);187} finally {188p11Key.releaseKeyID();189token.releaseSession(session);190}191}192193// mechanism == CKM_TLS_PRF194195byte[] out = new byte[spec.getOutputLength()];196CK_TLS_PRF_PARAMS params = new CK_TLS_PRF_PARAMS(seed, label, out);197198Session session = null;199long keyID = p11Key.getKeyID();200try {201session = token.getOpSession();202token.p11.C_DeriveKey(session.id(),203new CK_MECHANISM(mechanism, params), keyID, null);204return new SecretKeySpec(out, "TlsPrf");205} catch (PKCS11Exception e) {206throw new ProviderException("Could not calculate PRF", e);207} finally {208p11Key.releaseKeyID();209token.releaseSession(session);210}211}212213}214215216