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