175 lines · 5.9 KB · Java
RawDownload
/* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.crypto.provider; import java.security.*;import java.security.spec.AlgorithmParameterSpec; import javax.crypto.*; import sun.security.internal.interfaces.TlsMasterSecret;import sun.security.internal.spec.TlsMasterSecretParameterSpec; import static com.sun.crypto.provider.TlsPrfGenerator.*; /** * KeyGenerator implementation for the SSL/TLS master secret derivation. * * @author  Andreas Sterbenz * @since   1.6 */public final class TlsMasterSecretGenerator extends KeyGeneratorSpi {     private final static String MSG = "TlsMasterSecretGenerator must be "        + "initialized using a TlsMasterSecretParameterSpec";     private TlsMasterSecretParameterSpec spec;     private int protocolVersion;     public TlsMasterSecretGenerator() {    }     protected void engineInit(SecureRandom random) {        throw new InvalidParameterException(MSG);    }     protected void engineInit(AlgorithmParameterSpec params,            SecureRandom random) throws InvalidAlgorithmParameterException {        if (params instanceof TlsMasterSecretParameterSpec == false) {            throw new InvalidAlgorithmParameterException(MSG);        }        this.spec = (TlsMasterSecretParameterSpec)params;        if ("RAW".equals(spec.getPremasterSecret().getFormat()) == false) {            throw new InvalidAlgorithmParameterException(                "Key format must be RAW");        }        protocolVersion = (spec.getMajorVersion() << 8)            | spec.getMinorVersion();        if ((protocolVersion < 0x0300) || (protocolVersion > 0x0303)) {            throw new InvalidAlgorithmParameterException(                "Only SSL 3.0, TLS 1.0/1.1/1.2 supported");        }    }     protected void engineInit(int keysize, SecureRandom random) {        throw new InvalidParameterException(MSG);    }     protected SecretKey engineGenerateKey() {        if (spec == null) {            throw new IllegalStateException(                "TlsMasterSecretGenerator must be initialized");        }        SecretKey premasterKey = spec.getPremasterSecret();        byte[] premaster = premasterKey.getEncoded();         int premasterMajor, premasterMinor;        if (premasterKey.getAlgorithm().equals("TlsRsaPremasterSecret")) {            // RSA            premasterMajor = premaster[0] & 0xff;            premasterMinor = premaster[1] & 0xff;        } else {            // DH, KRB5, others            premasterMajor = -1;            premasterMinor = -1;        }         try {            byte[] master;            byte[] clientRandom = spec.getClientRandom();            byte[] serverRandom = spec.getServerRandom();             if (protocolVersion >= 0x0301) {                byte[] seed = concat(clientRandom, serverRandom);                master = ((protocolVersion >= 0x0303) ?                    doTLS12PRF(premaster, LABEL_MASTER_SECRET, seed, 48,                        spec.getPRFHashAlg(), spec.getPRFHashLength(),                        spec.getPRFBlockSize()) :                    doTLS10PRF(premaster, LABEL_MASTER_SECRET, seed, 48));            } else {                master = new byte[48];                MessageDigest md5 = MessageDigest.getInstance("MD5");                MessageDigest sha = MessageDigest.getInstance("SHA");                 byte[] tmp = new byte[20];                for (int i = 0; i < 3; i++) {                    sha.update(SSL3_CONST[i]);                    sha.update(premaster);                    sha.update(clientRandom);                    sha.update(serverRandom);                    sha.digest(tmp, 0, 20);                     md5.update(premaster);                    md5.update(tmp);                    md5.digest(master, i << 4, 16);                }             }             return new TlsMasterSecretKey(master, premasterMajor,                premasterMinor);        } catch (NoSuchAlgorithmException e) {            throw new ProviderException(e);        } catch (DigestException e) {            throw new ProviderException(e);        }    }     private static final class TlsMasterSecretKey implements TlsMasterSecret {         private byte[] key;        private final int majorVersion, minorVersion;         TlsMasterSecretKey(byte[] key, int majorVersion, int minorVersion) {            this.key = key;            this.majorVersion = majorVersion;            this.minorVersion = minorVersion;        }         public int getMajorVersion() {            return majorVersion;        }         public int getMinorVersion() {            return minorVersion;        }         public String getAlgorithm() {            return "TlsMasterSecret";        }         public String getFormat() {            return "RAW";        }         public byte[] getEncoded() {            return key.clone();        }     } }