1 /*
   2  * Copyright (c) 2005, 2013, 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.util.Arrays;
  29 
  30 import java.security.*;
  31 import java.security.spec.AlgorithmParameterSpec;
  32 
  33 import javax.crypto.*;
  34 import javax.crypto.spec.SecretKeySpec;
  35 
  36 import sun.security.internal.spec.TlsPrfParameterSpec;
  37 
  38 /**
  39  * KeyGenerator implementation for the TLS PRF function.
  40  * <p>
  41  * This class duplicates the HMAC functionality (RFC 2104) with
  42  * performance optimizations (e.g. XOR'ing keys with padding doesn't
  43  * need to be redone for each HMAC operation).
  44  *
  45  * @author  Andreas Sterbenz
  46  * @since   1.6
  47  */
  48 abstract class TlsPrfGenerator extends KeyGeneratorSpi {
  49 
  50     // magic constants and utility functions, also used by other files
  51     // in this package
  52 
  53     private static final byte[] B0 = new byte[0];
  54 
  55     static final byte[] LABEL_MASTER_SECRET = // "master secret"
  56         { 109, 97, 115, 116, 101, 114, 32, 115, 101, 99, 114, 101, 116 };
  57 
  58     static final byte[] LABEL_EXTENDED_MASTER_SECRET = // "extended master secret"
  59         { 101, 120, 116, 101, 110, 100, 101, 100, 32, 109, 97, 115, 116,
  60           101, 114, 32, 115, 101, 99, 114, 101, 116 };
  61 
  62     static final byte[] LABEL_KEY_EXPANSION = // "key expansion"
  63         { 107, 101, 121, 32, 101, 120, 112, 97, 110, 115, 105, 111, 110 };
  64 
  65     static final byte[] LABEL_CLIENT_WRITE_KEY = // "client write key"
  66         { 99, 108, 105, 101, 110, 116, 32, 119, 114, 105, 116, 101, 32,
  67           107, 101, 121 };
  68 
  69     static final byte[] LABEL_SERVER_WRITE_KEY = // "server write key"
  70         { 115, 101, 114, 118, 101, 114, 32, 119, 114, 105, 116, 101, 32,
  71           107, 101, 121 };
  72 
  73     static final byte[] LABEL_IV_BLOCK = // "IV block"
  74         { 73, 86, 32, 98, 108, 111, 99, 107 };
  75 
  76     /*
  77      * TLS HMAC "inner" and "outer" padding.  This isn't a function
  78      * of the digest algorithm.
  79      */
  80     private static final byte[] HMAC_ipad64  = genPad((byte)0x36, 64);
  81     private static final byte[] HMAC_ipad128 = genPad((byte)0x36, 128);
  82     private static final byte[] HMAC_opad64  = genPad((byte)0x5c, 64);
  83     private static final byte[] HMAC_opad128 = genPad((byte)0x5c, 128);
  84 
  85     // SSL3 magic mix constants ("A", "BB", "CCC", ...)
  86     static final byte[][] SSL3_CONST = genConst();
  87 
  88     static byte[] genPad(byte b, int count) {
  89         byte[] padding = new byte[count];
  90         Arrays.fill(padding, b);
  91         return padding;
  92     }
  93 
  94     static byte[] concat(byte[] b1, byte[] b2) {
  95         int n1 = b1.length;
  96         int n2 = b2.length;
  97         byte[] b = new byte[n1 + n2];
  98         System.arraycopy(b1, 0, b, 0, n1);
  99         System.arraycopy(b2, 0, b, n1, n2);
 100         return b;
 101     }
 102 
 103     private static byte[][] genConst() {
 104         int n = 10;
 105         byte[][] arr = new byte[n][];
 106         for (int i = 0; i < n; i++) {
 107             byte[] b = new byte[i + 1];
 108             Arrays.fill(b, (byte)('A' + i));
 109             arr[i] = b;
 110         }
 111         return arr;
 112     }
 113 
 114     // PRF implementation
 115 
 116     private static final String MSG = "TlsPrfGenerator must be "
 117         + "initialized using a TlsPrfParameterSpec";
 118 
 119     @SuppressWarnings("deprecation")
 120     private TlsPrfParameterSpec spec;
 121 
 122     public TlsPrfGenerator() {
 123     }
 124 
 125     protected void engineInit(SecureRandom random) {
 126         throw new InvalidParameterException(MSG);
 127     }
 128 
 129     @SuppressWarnings("deprecation")
 130     protected void engineInit(AlgorithmParameterSpec params,
 131             SecureRandom random) throws InvalidAlgorithmParameterException {
 132         if (params instanceof TlsPrfParameterSpec == false) {
 133             throw new InvalidAlgorithmParameterException(MSG);
 134         }
 135         this.spec = (TlsPrfParameterSpec)params;
 136         SecretKey key = spec.getSecret();
 137         if ((key != null) && ("RAW".equals(key.getFormat()) == false)) {
 138             throw new InvalidAlgorithmParameterException(
 139                 "Key encoding format must be RAW");
 140         }
 141     }
 142 
 143     protected void engineInit(int keysize, SecureRandom random) {
 144         throw new InvalidParameterException(MSG);
 145     }
 146 
 147     SecretKey engineGenerateKey0(boolean tls12) {
 148         if (spec == null) {
 149             throw new IllegalStateException(
 150                 "TlsPrfGenerator must be initialized");
 151         }
 152         SecretKey key = spec.getSecret();
 153         byte[] secret = (key == null) ? null : key.getEncoded();
 154         try {
 155             byte[] labelBytes = spec.getLabel().getBytes("UTF8");
 156             int n = spec.getOutputLength();
 157             byte[] prfBytes = (tls12 ?
 158                 doTLS12PRF(secret, labelBytes, spec.getSeed(), n,
 159                     spec.getPRFHashAlg(), spec.getPRFHashLength(),
 160                     spec.getPRFBlockSize()) :
 161                 doTLS10PRF(secret, labelBytes, spec.getSeed(), n));
 162             return new SecretKeySpec(prfBytes, "TlsPrf");
 163         } catch (GeneralSecurityException e) {
 164             throw new ProviderException("Could not generate PRF", e);
 165         } catch (java.io.UnsupportedEncodingException e) {
 166             throw new ProviderException("Could not generate PRF", e);
 167         }
 168     }
 169 
 170     static byte[] doTLS12PRF(byte[] secret, byte[] labelBytes,
 171             byte[] seed, int outputLength,
 172             String prfHash, int prfHashLength, int prfBlockSize)
 173             throws NoSuchAlgorithmException, DigestException {
 174         if (prfHash == null) {
 175             throw new NoSuchAlgorithmException("Unspecified PRF algorithm");
 176         }
 177         MessageDigest prfMD = MessageDigest.getInstance(prfHash);
 178         return doTLS12PRF(secret, labelBytes, seed, outputLength,
 179             prfMD, prfHashLength, prfBlockSize);
 180     }
 181 
 182     static byte[] doTLS12PRF(byte[] secret, byte[] labelBytes,
 183             byte[] seed, int outputLength,
 184             MessageDigest mdPRF, int mdPRFLen, int mdPRFBlockSize)
 185             throws DigestException {
 186 
 187         if (secret == null) {
 188             secret = B0;
 189         }
 190 
 191         // If we have a long secret, digest it first.
 192         if (secret.length > mdPRFBlockSize) {
 193             secret = mdPRF.digest(secret);
 194         }
 195 
 196         byte[] output = new byte[outputLength];
 197         byte [] ipad;
 198         byte [] opad;
 199 
 200         switch (mdPRFBlockSize) {
 201         case 64:
 202             ipad = HMAC_ipad64.clone();
 203             opad = HMAC_opad64.clone();
 204             break;
 205         case 128:
 206             ipad = HMAC_ipad128.clone();
 207             opad = HMAC_opad128.clone();
 208             break;
 209         default:
 210             throw new DigestException("Unexpected block size.");
 211         }
 212 
 213         // P_HASH(Secret, label + seed)
 214         expand(mdPRF, mdPRFLen, secret, 0, secret.length, labelBytes,
 215             seed, output, ipad, opad);
 216 
 217         return output;
 218     }
 219 
 220     static byte[] doTLS10PRF(byte[] secret, byte[] labelBytes,
 221             byte[] seed, int outputLength) throws NoSuchAlgorithmException,
 222             DigestException {
 223         MessageDigest md5 = MessageDigest.getInstance("MD5");
 224         MessageDigest sha = MessageDigest.getInstance("SHA1");
 225         return doTLS10PRF(secret, labelBytes, seed, outputLength, md5, sha);
 226     }
 227 
 228     static byte[] doTLS10PRF(byte[] secret, byte[] labelBytes,
 229             byte[] seed, int outputLength, MessageDigest md5,
 230             MessageDigest sha) throws DigestException {
 231         /*
 232          * Split the secret into two halves S1 and S2 of same length.
 233          * S1 is taken from the first half of the secret, S2 from the
 234          * second half.
 235          * Their length is created by rounding up the length of the
 236          * overall secret divided by two; thus, if the original secret
 237          * is an odd number of bytes long, the last byte of S1 will be
 238          * the same as the first byte of S2.
 239          *
 240          * Note: Instead of creating S1 and S2, we determine the offset into
 241          * the overall secret where S2 starts.
 242          */
 243 
 244         if (secret == null) {
 245             secret = B0;
 246         }
 247         int off = secret.length >> 1;
 248         int seclen = off + (secret.length & 1);
 249 
 250         byte[] secKey = secret;
 251         int keyLen = seclen;
 252         byte[] output = new byte[outputLength];
 253 
 254         // P_MD5(S1, label + seed)
 255         // If we have a long secret, digest it first.
 256         if (seclen > 64) {              // 64: block size of HMAC-MD5
 257             md5.update(secret, 0, seclen);
 258             secKey = md5.digest();
 259             keyLen = secKey.length;
 260         }
 261         expand(md5, 16, secKey, 0, keyLen, labelBytes, seed, output,
 262             HMAC_ipad64.clone(), HMAC_opad64.clone());
 263 
 264         // P_SHA-1(S2, label + seed)
 265         // If we have a long secret, digest it first.
 266         if (seclen > 64) {              // 64: block size of HMAC-SHA1
 267             sha.update(secret, off, seclen);
 268             secKey = sha.digest();
 269             keyLen = secKey.length;
 270             off = 0;
 271         }
 272         expand(sha, 20, secKey, off, keyLen, labelBytes, seed, output,
 273             HMAC_ipad64.clone(), HMAC_opad64.clone());
 274 
 275         return output;
 276     }
 277 
 278     /*
 279      * @param digest the MessageDigest to produce the HMAC
 280      * @param hmacSize the HMAC size
 281      * @param secret the secret
 282      * @param secOff the offset into the secret
 283      * @param secLen the secret length
 284      * @param label the label
 285      * @param seed the seed
 286      * @param output the output array
 287      */
 288     private static void expand(MessageDigest digest, int hmacSize,
 289             byte[] secret, int secOff, int secLen, byte[] label, byte[] seed,
 290             byte[] output, byte[] pad1, byte[] pad2) throws DigestException {
 291         /*
 292          * modify the padding used, by XORing the key into our copy of that
 293          * padding.  That's to avoid doing that for each HMAC computation.
 294          */
 295         for (int i = 0; i < secLen; i++) {
 296             pad1[i] ^= secret[i + secOff];
 297             pad2[i] ^= secret[i + secOff];
 298         }
 299 
 300         byte[] tmp = new byte[hmacSize];
 301         byte[] aBytes = null;
 302 
 303         /*
 304          * compute:
 305          *
 306          *     P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) +
 307          *                            HMAC_hash(secret, A(2) + seed) +
 308          *                            HMAC_hash(secret, A(3) + seed) + ...
 309          * A() is defined as:
 310          *
 311          *     A(0) = seed
 312          *     A(i) = HMAC_hash(secret, A(i-1))
 313          */
 314         int remaining = output.length;
 315         int ofs = 0;
 316         while (remaining > 0) {
 317             /*
 318              * compute A() ...
 319              */
 320             // inner digest
 321             digest.update(pad1);
 322             if (aBytes == null) {
 323                 digest.update(label);
 324                 digest.update(seed);
 325             } else {
 326                 digest.update(aBytes);
 327             }
 328             digest.digest(tmp, 0, hmacSize);
 329 
 330             // outer digest
 331             digest.update(pad2);
 332             digest.update(tmp);
 333             if (aBytes == null) {
 334                 aBytes = new byte[hmacSize];
 335             }
 336             digest.digest(aBytes, 0, hmacSize);
 337 
 338             /*
 339              * compute HMAC_hash() ...
 340              */
 341             // inner digest
 342             digest.update(pad1);
 343             digest.update(aBytes);
 344             digest.update(label);
 345             digest.update(seed);
 346             digest.digest(tmp, 0, hmacSize);
 347 
 348             // outer digest
 349             digest.update(pad2);
 350             digest.update(tmp);
 351             digest.digest(tmp, 0, hmacSize);
 352 
 353             int k = Math.min(hmacSize, remaining);
 354             for (int i = 0; i < k; i++) {
 355                 output[ofs++] ^= tmp[i];
 356             }
 357             remaining -= k;
 358         }
 359     }
 360 
 361     /**
 362      * A KeyGenerator implementation that supports TLS 1.2.
 363      * <p>
 364      * TLS 1.2 uses a different hash algorithm than 1.0/1.1 for the PRF
 365      * calculations.  As of 2010, there is no PKCS11-level support for TLS
 366      * 1.2 PRF calculations, and no known OS's have an internal variant
 367      * we could use.  Therefore for TLS 1.2, we are updating JSSE to request
 368      * a different provider algorithm:  "SunTls12Prf".  If we reused the
 369      * name "SunTlsPrf", the PKCS11 provider would need be updated to
 370      * fail correctly when presented with the wrong version number
 371      * (via Provider.Service.supportsParameters()), and add the
 372      * appropriate supportsParamters() checks into KeyGenerators (not
 373      * currently there).
 374      */
 375     public static class V12 extends TlsPrfGenerator {
 376         protected SecretKey engineGenerateKey() {
 377             return engineGenerateKey0(true);
 378         }
 379     }
 380 
 381     /**
 382      * A KeyGenerator implementation that supports TLS 1.0/1.1.
 383      */
 384     public static class V10 extends TlsPrfGenerator {
 385         protected SecretKey engineGenerateKey() {
 386             return engineGenerateKey0(false);
 387         }
 388     }
 389 }