--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/com/sun/crypto/provider/TlsMasterSecretGenerator.java Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2005-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.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() {
+ SunJCE.ensureIntegrity(getClass());
+ }
+
+ 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 > 0x0302)) {
+ throw new InvalidAlgorithmParameterException
+ ("Only SSL 3.0, TLS 1.0, and TLS 1.1 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 = doPRF(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();
+ }
+
+ }
+
+}