Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/pkcs11/P11TlsPrfGenerator.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.security.*;28import java.security.spec.AlgorithmParameterSpec;2930import javax.crypto.*;31import javax.crypto.spec.*;3233import sun.security.internal.spec.TlsPrfParameterSpec;3435import static sun.security.pkcs11.TemplateManager.*;36import sun.security.pkcs11.wrapper.*;37import static sun.security.pkcs11.wrapper.PKCS11Constants.*;3839/**40* KeyGenerator for the TLS PRF. Note that although the PRF is used in a number41* of places during the handshake, this class is usually only used to calculate42* the Finished messages. The reason is that for those other uses more specific43* PKCS#11 mechanisms have been defined (CKM_SSL3_MASTER_KEY_DERIVE, etc.).44*45* <p>This class supports the CKM_TLS_PRF mechanism from PKCS#11 v2.20 and46* the older NSS private mechanism.47*48* @author Andreas Sterbenz49* @since 1.650*/51final class P11TlsPrfGenerator extends KeyGeneratorSpi {5253private final static String MSG =54"TlsPrfGenerator must be initialized using a TlsPrfParameterSpec";5556// token instance57private final Token token;5859// algorithm name60private final String algorithm;6162// mechanism id63private final long mechanism;6465private TlsPrfParameterSpec spec;6667private P11Key p11Key;6869P11TlsPrfGenerator(Token token, String algorithm, long mechanism)70throws PKCS11Exception {71super();72this.token = token;73this.algorithm = algorithm;74this.mechanism = mechanism;75}7677protected void engineInit(SecureRandom random) {78throw new InvalidParameterException(MSG);79}8081protected void engineInit(AlgorithmParameterSpec params,82SecureRandom random) throws InvalidAlgorithmParameterException {83if (params instanceof TlsPrfParameterSpec == false) {84throw new InvalidAlgorithmParameterException(MSG);85}86this.spec = (TlsPrfParameterSpec)params;87SecretKey key = spec.getSecret();88if (key == null) {89key = NULL_KEY;90}91try {92p11Key = P11SecretKeyFactory.convertKey(token, key, null);93} catch (InvalidKeyException e) {94throw new InvalidAlgorithmParameterException("init() failed", e);95}96}9798// SecretKeySpec does not allow zero length keys, so we define our99// own class.100//101// As an anonymous class cannot make any guarantees about serialization102// compatibility, it is nonsensical for an anonymous class to define a103// serialVersionUID. Suppress warnings relative to missing serialVersionUID104// field in the anonymous subclass of serializable SecretKey.105@SuppressWarnings("serial")106private static final SecretKey NULL_KEY = new SecretKey() {107public byte[] getEncoded() {108return new byte[0];109}110public String getFormat() {111return "RAW";112}113public String getAlgorithm() {114return "Generic";115}116};117118protected void engineInit(int keysize, SecureRandom random) {119throw new InvalidParameterException(MSG);120}121122protected SecretKey engineGenerateKey() {123if (spec == null) {124throw new IllegalStateException("TlsPrfGenerator must be initialized");125}126byte[] seed = spec.getSeed();127128// TLS 1.2129if (mechanism == CKM_TLS_MAC) {130SecretKey k = null;131int ulServerOrClient = 0;132if (spec.getLabel().equals("server finished")) {133ulServerOrClient = 1;134}135if (spec.getLabel().equals("client finished")) {136ulServerOrClient = 2;137}138139if (ulServerOrClient != 0) {140// Finished message141CK_TLS_MAC_PARAMS params = new CK_TLS_MAC_PARAMS(142Functions.getHashMechId(spec.getPRFHashAlg()),143spec.getOutputLength(), ulServerOrClient);144Session session = null;145long keyID = p11Key.getKeyID();146try {147session = token.getOpSession();148token.p11.C_SignInit(session.id(),149new CK_MECHANISM(mechanism, params), keyID);150token.p11.C_SignUpdate(session.id(), 0, seed, 0, seed.length);151byte[] out = token.p11.C_SignFinal152(session.id(), spec.getOutputLength());153return new SecretKeySpec(out, "TlsPrf");154} catch (PKCS11Exception e) {155throw new ProviderException("Could not calculate PRF", e);156} finally {157p11Key.releaseKeyID();158token.releaseSession(session);159}160} else {161throw new ProviderException("Only Finished message authentication code"+162" generation supported for TLS 1.2.");163}164}165166byte[] label = P11Util.getBytesUTF8(spec.getLabel());167168if (mechanism == CKM_NSS_TLS_PRF_GENERAL) {169Session session = null;170long keyID = p11Key.getKeyID();171try {172session = token.getOpSession();173token.p11.C_SignInit174(session.id(), new CK_MECHANISM(mechanism), keyID);175token.p11.C_SignUpdate(session.id(), 0, label, 0, label.length);176token.p11.C_SignUpdate(session.id(), 0, seed, 0, seed.length);177byte[] out = token.p11.C_SignFinal178(session.id(), spec.getOutputLength());179return new SecretKeySpec(out, "TlsPrf");180} catch (PKCS11Exception e) {181throw new ProviderException("Could not calculate PRF", e);182} finally {183p11Key.releaseKeyID();184token.releaseSession(session);185}186}187188// mechanism == CKM_TLS_PRF189190byte[] out = new byte[spec.getOutputLength()];191CK_TLS_PRF_PARAMS params = new CK_TLS_PRF_PARAMS(seed, label, out);192193Session session = null;194long keyID = p11Key.getKeyID();195try {196session = token.getOpSession();197token.p11.C_DeriveKey(session.id(),198new CK_MECHANISM(mechanism, params), keyID, null);199return new SecretKeySpec(out, "TlsPrf");200} catch (PKCS11Exception e) {201throw new ProviderException("Could not calculate PRF", e);202} finally {203p11Key.releaseKeyID();204token.releaseSession(session);205}206}207208}209210211