1 /*
   2  * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.crypto.provider;
  27 
  28 import java.security.*;
  29 import java.security.spec.AlgorithmParameterSpec;
  30 
  31 import javax.crypto.*;
  32 
  33 import sun.security.internal.interfaces.TlsMasterSecret;
  34 import sun.security.internal.spec.TlsMasterSecretParameterSpec;
  35 
  36 import static com.sun.crypto.provider.TlsPrfGenerator.*;
  37 
  38 /**
  39  * KeyGenerator implementation for the SSL/TLS master secret derivation.
  40  *
  41  * @author  Andreas Sterbenz
  42  * @since   1.6
  43  */
  44 public final class TlsMasterSecretGenerator extends KeyGeneratorSpi {
  45 
  46     private final static String MSG = "TlsMasterSecretGenerator must be "
  47         + "initialized using a TlsMasterSecretParameterSpec";
  48 
  49     private TlsMasterSecretParameterSpec spec;
  50 
  51     private int protocolVersion;
  52 
  53     public TlsMasterSecretGenerator() {
  54     }
  55 
  56     protected void engineInit(SecureRandom random) {
  57         throw new InvalidParameterException(MSG);
  58     }
  59 
  60     protected void engineInit(AlgorithmParameterSpec params,
  61             SecureRandom random) throws InvalidAlgorithmParameterException {
  62         if (params instanceof TlsMasterSecretParameterSpec == false) {
  63             throw new InvalidAlgorithmParameterException(MSG);
  64         }
  65         this.spec = (TlsMasterSecretParameterSpec)params;
  66         if ("RAW".equals(spec.getPremasterSecret().getFormat()) == false) {
  67             throw new InvalidAlgorithmParameterException(
  68                 "Key format must be RAW");
  69         }
  70         protocolVersion = (spec.getMajorVersion() << 8)
  71             | spec.getMinorVersion();
  72         if ((protocolVersion < 0x0300) || (protocolVersion > 0x0303)) {
  73             throw new InvalidAlgorithmParameterException(
  74                 "Only SSL 3.0, TLS 1.0/1.1/1.2 supported");
  75         }
  76     }
  77 
  78     protected void engineInit(int keysize, SecureRandom random) {
  79         throw new InvalidParameterException(MSG);
  80     }
  81 
  82     protected SecretKey engineGenerateKey() {
  83         if (spec == null) {
  84             throw new IllegalStateException(
  85                 "TlsMasterSecretGenerator must be initialized");
  86         }
  87         SecretKey premasterKey = spec.getPremasterSecret();
  88         byte[] premaster = premasterKey.getEncoded();
  89 
  90         int premasterMajor, premasterMinor;
  91         if (premasterKey.getAlgorithm().equals("TlsRsaPremasterSecret")) {
  92             // RSA
  93             premasterMajor = premaster[0] & 0xff;
  94             premasterMinor = premaster[1] & 0xff;
  95         } else {
  96             // DH, KRB5, others
  97             premasterMajor = -1;
  98             premasterMinor = -1;
  99         }
 100 
 101         try {
 102             byte[] master;
 103             byte[] clientRandom = spec.getClientRandom();
 104             byte[] serverRandom = spec.getServerRandom();
 105 
 106             if (protocolVersion >= 0x0301) {
 107                 byte[] seed = concat(clientRandom, serverRandom);
 108                 master = ((protocolVersion >= 0x0303) ?
 109                     doTLS12PRF(premaster, LABEL_MASTER_SECRET, seed, 48,
 110                         spec.getPRFHashAlg(), spec.getPRFHashLength(),
 111                         spec.getPRFBlockSize()) :
 112                     doTLS10PRF(premaster, LABEL_MASTER_SECRET, seed, 48));
 113             } else {
 114                 master = new byte[48];
 115                 MessageDigest md5 = MessageDigest.getInstance("MD5");
 116                 MessageDigest sha = MessageDigest.getInstance("SHA");
 117 
 118                 byte[] tmp = new byte[20];
 119                 for (int i = 0; i < 3; i++) {
 120                     sha.update(SSL3_CONST[i]);
 121                     sha.update(premaster);
 122                     sha.update(clientRandom);
 123                     sha.update(serverRandom);
 124                     sha.digest(tmp, 0, 20);
 125 
 126                     md5.update(premaster);
 127                     md5.update(tmp);
 128                     md5.digest(master, i << 4, 16);
 129                 }
 130 
 131             }
 132 
 133             return new TlsMasterSecretKey(master, premasterMajor,
 134                 premasterMinor);
 135         } catch (NoSuchAlgorithmException e) {
 136             throw new ProviderException(e);
 137         } catch (DigestException e) {
 138             throw new ProviderException(e);
 139         }
 140     }
 141 
 142     private static final class TlsMasterSecretKey implements TlsMasterSecret {
 143         private static final long serialVersionUID = 1019571680375368880L;
 144 
 145         private byte[] key;
 146         private final int majorVersion, minorVersion;
 147 
 148         TlsMasterSecretKey(byte[] key, int majorVersion, int minorVersion) {
 149             this.key = key;
 150             this.majorVersion = majorVersion;
 151             this.minorVersion = minorVersion;
 152         }
 153 
 154         public int getMajorVersion() {
 155             return majorVersion;
 156         }
 157 
 158         public int getMinorVersion() {
 159             return minorVersion;
 160         }
 161 
 162         public String getAlgorithm() {
 163             return "TlsMasterSecret";
 164         }
 165 
 166         public String getFormat() {
 167             return "RAW";
 168         }
 169 
 170         public byte[] getEncoded() {
 171             return key.clone();
 172         }
 173 
 174     }
 175 
 176 }