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