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 }