1 /* 2 * Copyright (c) 2018, 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 sun.security.ssl; 27 28 import java.nio.ByteBuffer; 29 import java.security.AccessController; 30 import java.security.GeneralSecurityException; 31 import java.security.InvalidAlgorithmParameterException; 32 import java.security.InvalidKeyException; 33 import java.security.Key; 34 import java.security.NoSuchAlgorithmException; 35 import java.security.PrivilegedAction; 36 import java.security.SecureRandom; 37 import java.security.Security; 38 import java.security.spec.AlgorithmParameterSpec; 39 import java.util.AbstractMap.SimpleImmutableEntry; 40 import java.util.Arrays; 41 import java.util.HashMap; 42 import java.util.Map; 43 import javax.crypto.BadPaddingException; 44 import javax.crypto.Cipher; 45 import javax.crypto.IllegalBlockSizeException; 46 import javax.crypto.SecretKey; 47 import javax.crypto.ShortBufferException; 48 import javax.crypto.spec.GCMParameterSpec; 49 import javax.crypto.spec.IvParameterSpec; 50 import sun.security.ssl.Authenticator.MAC; 51 import static sun.security.ssl.CipherType.*; 52 import static sun.security.ssl.JsseJce.*; 53 54 enum SSLCipher { 55 // exportable ciphers 56 @SuppressWarnings({"unchecked", "rawtypes"}) 57 B_NULL("NULL", NULL_CIPHER, 0, 0, 0, 0, true, true, 58 (Map.Entry<ReadCipherGenerator, 59 ProtocolVersion[]>[])(new Map.Entry[] { 60 new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>( 61 new NullReadCipherGenerator(), 62 ProtocolVersion.PROTOCOLS_OF_NONE 63 ), 64 new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>( 65 new NullReadCipherGenerator(), 66 ProtocolVersion.PROTOCOLS_TO_13 67 ) 68 }), 69 (Map.Entry<WriteCipherGenerator, 70 ProtocolVersion[]>[])(new Map.Entry[] { 71 new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>( 72 new NullWriteCipherGenerator(), 73 ProtocolVersion.PROTOCOLS_OF_NONE 74 ), 75 new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>( 76 new NullWriteCipherGenerator(), 77 ProtocolVersion.PROTOCOLS_TO_13 78 ) 79 })), 80 81 @SuppressWarnings({"unchecked", "rawtypes"}) 82 B_RC4_40(CIPHER_RC4, STREAM_CIPHER, 5, 16, 0, 0, true, true, 83 (Map.Entry<ReadCipherGenerator, 84 ProtocolVersion[]>[])(new Map.Entry[] { 85 new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>( 86 new StreamReadCipherGenerator(), 87 ProtocolVersion.PROTOCOLS_TO_10 88 ) 89 }), 90 (Map.Entry<WriteCipherGenerator, 91 ProtocolVersion[]>[])(new Map.Entry[] { 92 new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>( 93 new StreamWriteCipherGenerator(), 94 ProtocolVersion.PROTOCOLS_TO_10 95 ) 96 })), 97 98 @SuppressWarnings({"unchecked", "rawtypes"}) 99 B_RC2_40("RC2", BLOCK_CIPHER, 5, 16, 8, 0, false, true, 100 (Map.Entry<ReadCipherGenerator, 101 ProtocolVersion[]>[])(new Map.Entry[] { 102 new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>( 103 new StreamReadCipherGenerator(), 104 ProtocolVersion.PROTOCOLS_TO_10 105 ) 106 }), 107 (Map.Entry<WriteCipherGenerator, 108 ProtocolVersion[]>[])(new Map.Entry[] { 109 new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>( 110 new StreamWriteCipherGenerator(), 111 ProtocolVersion.PROTOCOLS_TO_10 112 ) 113 })), 114 115 @SuppressWarnings({"unchecked", "rawtypes"}) 116 B_DES_40(CIPHER_DES, BLOCK_CIPHER, 5, 8, 8, 0, true, true, 117 (Map.Entry<ReadCipherGenerator, 118 ProtocolVersion[]>[])(new Map.Entry[] { 119 new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>( 120 new T10BlockReadCipherGenerator(), 121 ProtocolVersion.PROTOCOLS_TO_10 122 ) 123 }), 124 (Map.Entry<WriteCipherGenerator, 125 ProtocolVersion[]>[])(new Map.Entry[] { 126 new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>( 127 new T10BlockWriteCipherGenerator(), 128 ProtocolVersion.PROTOCOLS_TO_10 129 ) 130 })), 131 132 // domestic strength ciphers 133 @SuppressWarnings({"unchecked", "rawtypes"}) 134 B_RC4_128(CIPHER_RC4, STREAM_CIPHER, 16, 16, 0, 0, true, false, 135 (Map.Entry<ReadCipherGenerator, 136 ProtocolVersion[]>[])(new Map.Entry[] { 137 new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>( 138 new StreamReadCipherGenerator(), 139 ProtocolVersion.PROTOCOLS_TO_12 140 ) 141 }), 142 (Map.Entry<WriteCipherGenerator, 143 ProtocolVersion[]>[])(new Map.Entry[] { 144 new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>( 145 new StreamWriteCipherGenerator(), 146 ProtocolVersion.PROTOCOLS_TO_12 147 ) 148 })), 149 150 @SuppressWarnings({"unchecked", "rawtypes"}) 151 B_DES(CIPHER_DES, BLOCK_CIPHER, 8, 8, 8, 0, true, false, 152 (Map.Entry<ReadCipherGenerator, 153 ProtocolVersion[]>[])(new Map.Entry[] { 154 new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>( 155 new T10BlockReadCipherGenerator(), 156 ProtocolVersion.PROTOCOLS_TO_10 157 ), 158 new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>( 159 new T11BlockReadCipherGenerator(), 160 ProtocolVersion.PROTOCOLS_OF_11 161 ) 162 }), 163 (Map.Entry<WriteCipherGenerator, 164 ProtocolVersion[]>[])(new Map.Entry[] { 165 new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>( 166 new T10BlockWriteCipherGenerator(), 167 ProtocolVersion.PROTOCOLS_TO_10 168 ), 169 new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>( 170 new T11BlockWriteCipherGenerator(), 171 ProtocolVersion.PROTOCOLS_OF_11 172 ) 173 })), 174 175 @SuppressWarnings({"unchecked", "rawtypes"}) 176 B_3DES(CIPHER_3DES, BLOCK_CIPHER, 24, 24, 8, 0, true, false, 177 (Map.Entry<ReadCipherGenerator, 178 ProtocolVersion[]>[])(new Map.Entry[] { 179 new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>( 180 new T10BlockReadCipherGenerator(), 181 ProtocolVersion.PROTOCOLS_TO_10 182 ), 183 new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>( 184 new T11BlockReadCipherGenerator(), 185 ProtocolVersion.PROTOCOLS_11_12 186 ) 187 }), 188 (Map.Entry<WriteCipherGenerator, 189 ProtocolVersion[]>[])(new Map.Entry[] { 190 new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>( 191 new T10BlockWriteCipherGenerator(), 192 ProtocolVersion.PROTOCOLS_TO_10 193 ), 194 new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>( 195 new T11BlockWriteCipherGenerator(), 196 ProtocolVersion.PROTOCOLS_11_12 197 ) 198 })), 199 200 @SuppressWarnings({"unchecked", "rawtypes"}) 201 B_IDEA("IDEA", BLOCK_CIPHER, 16, 16, 8, 0, false, false, 202 (Map.Entry<ReadCipherGenerator, 203 ProtocolVersion[]>[])(new Map.Entry[] { 204 new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>( 205 null, 206 ProtocolVersion.PROTOCOLS_TO_12 207 ) 208 }), 209 (Map.Entry<WriteCipherGenerator, 210 ProtocolVersion[]>[])(new Map.Entry[] { 211 new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>( 212 null, 213 ProtocolVersion.PROTOCOLS_TO_12 214 ) 215 })), 216 217 @SuppressWarnings({"unchecked", "rawtypes"}) 218 B_AES_128(CIPHER_AES, BLOCK_CIPHER, 16, 16, 16, 0, true, false, 219 (Map.Entry<ReadCipherGenerator, 220 ProtocolVersion[]>[])(new Map.Entry[] { 221 new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>( 222 new T10BlockReadCipherGenerator(), 223 ProtocolVersion.PROTOCOLS_TO_10 224 ), 225 new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>( 226 new T11BlockReadCipherGenerator(), 227 ProtocolVersion.PROTOCOLS_11_12 228 ) 229 }), 230 (Map.Entry<WriteCipherGenerator, 231 ProtocolVersion[]>[])(new Map.Entry[] { 232 new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>( 233 new T10BlockWriteCipherGenerator(), 234 ProtocolVersion.PROTOCOLS_TO_10 235 ), 236 new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>( 237 new T11BlockWriteCipherGenerator(), 238 ProtocolVersion.PROTOCOLS_11_12 239 ) 240 })), 241 242 @SuppressWarnings({"unchecked", "rawtypes"}) 243 B_AES_256(CIPHER_AES, BLOCK_CIPHER, 32, 32, 16, 0, true, false, 244 (Map.Entry<ReadCipherGenerator, 245 ProtocolVersion[]>[])(new Map.Entry[] { 246 new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>( 247 new T10BlockReadCipherGenerator(), 248 ProtocolVersion.PROTOCOLS_TO_10 249 ), 250 new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>( 251 new T11BlockReadCipherGenerator(), 252 ProtocolVersion.PROTOCOLS_11_12 253 ) 254 }), 255 (Map.Entry<WriteCipherGenerator, 256 ProtocolVersion[]>[])(new Map.Entry[] { 257 new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>( 258 new T10BlockWriteCipherGenerator(), 259 ProtocolVersion.PROTOCOLS_TO_10 260 ), 261 new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>( 262 new T11BlockWriteCipherGenerator(), 263 ProtocolVersion.PROTOCOLS_11_12 264 ) 265 })), 266 267 @SuppressWarnings({"unchecked", "rawtypes"}) 268 B_AES_128_GCM(CIPHER_AES_GCM, AEAD_CIPHER, 16, 16, 12, 4, true, false, 269 (Map.Entry<ReadCipherGenerator, 270 ProtocolVersion[]>[])(new Map.Entry[] { 271 new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>( 272 new T12GcmReadCipherGenerator(), 273 ProtocolVersion.PROTOCOLS_OF_12 274 ) 275 }), 276 (Map.Entry<WriteCipherGenerator, 277 ProtocolVersion[]>[])(new Map.Entry[] { 278 new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>( 279 new T12GcmWriteCipherGenerator(), 280 ProtocolVersion.PROTOCOLS_OF_12 281 ) 282 })), 283 284 @SuppressWarnings({"unchecked", "rawtypes"}) 285 B_AES_256_GCM(CIPHER_AES_GCM, AEAD_CIPHER, 32, 32, 12, 4, true, false, 286 (Map.Entry<ReadCipherGenerator, 287 ProtocolVersion[]>[])(new Map.Entry[] { 288 new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>( 289 new T12GcmReadCipherGenerator(), 290 ProtocolVersion.PROTOCOLS_OF_12 291 ) 292 }), 293 (Map.Entry<WriteCipherGenerator, 294 ProtocolVersion[]>[])(new Map.Entry[] { 295 new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>( 296 new T12GcmWriteCipherGenerator(), 297 ProtocolVersion.PROTOCOLS_OF_12 298 ) 299 })), 300 301 @SuppressWarnings({"unchecked", "rawtypes"}) 302 B_AES_128_GCM_IV(CIPHER_AES_GCM, AEAD_CIPHER, 16, 16, 12, 0, true, false, 303 (Map.Entry<ReadCipherGenerator, 304 ProtocolVersion[]>[])(new Map.Entry[] { 305 new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>( 306 new T13GcmReadCipherGenerator(), 307 ProtocolVersion.PROTOCOLS_OF_13 308 ) 309 }), 310 (Map.Entry<WriteCipherGenerator, 311 ProtocolVersion[]>[])(new Map.Entry[] { 312 new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>( 313 new T13GcmWriteCipherGenerator(), 314 ProtocolVersion.PROTOCOLS_OF_13 315 ) 316 })), 317 318 @SuppressWarnings({"unchecked", "rawtypes"}) 319 B_AES_256_GCM_IV(CIPHER_AES_GCM, AEAD_CIPHER, 32, 32, 12, 0, true, false, 320 (Map.Entry<ReadCipherGenerator, 321 ProtocolVersion[]>[])(new Map.Entry[] { 322 new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>( 323 new T13GcmReadCipherGenerator(), 324 ProtocolVersion.PROTOCOLS_OF_13 325 ) 326 }), 327 (Map.Entry<WriteCipherGenerator, 328 ProtocolVersion[]>[])(new Map.Entry[] { 329 new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>( 330 new T13GcmWriteCipherGenerator(), 331 ProtocolVersion.PROTOCOLS_OF_13 332 ) 333 })); 334 335 // descriptive name including key size, e.g. AES/128 336 final String description; 337 338 // JCE cipher transformation string, e.g. AES/CBC/NoPadding 339 final String transformation; 340 341 // algorithm name, e.g. AES 342 final String algorithm; 343 344 // supported and compile time enabled. Also see isAvailable() 345 final boolean allowed; 346 347 // number of bytes of entropy in the key 348 final int keySize; 349 350 // length of the actual cipher key in bytes. 351 // for non-exportable ciphers, this is the same as keySize 352 final int expandedKeySize; 353 354 // size of the IV 355 final int ivSize; 356 357 // size of fixed IV 358 // 359 // record_iv_length = ivSize - fixedIvSize 360 final int fixedIvSize; 361 362 // exportable under 512/40 bit rules 363 final boolean exportable; 364 365 // Is the cipher algorithm of Cipher Block Chaining (CBC) mode? 366 final CipherType cipherType; 367 368 // size of the authentication tag, only applicable to cipher suites in 369 // Galois Counter Mode (GCM) 370 // 371 // As far as we know, all supported GCM cipher suites use 128-bits 372 // authentication tags. 373 final int tagSize = 16; 374 375 // runtime availability 376 private final boolean isAvailable; 377 378 private final Map.Entry<ReadCipherGenerator, 379 ProtocolVersion[]>[] readCipherGenerators; 380 private final Map.Entry<WriteCipherGenerator, 381 ProtocolVersion[]>[] writeCipherGenerators; 382 383 // Map of Ciphers listed in jdk.tls.keyLimits 384 private static final HashMap<String, Long> cipherLimits = new HashMap<>(); 385 386 // Keywords found on the jdk.tls.keyLimits security property. 387 final static String tag[] = {"KEYUPDATE"}; 388 389 static { 390 final long max = 4611686018427387904L; // 2^62 391 String prop = AccessController.doPrivileged( 392 new PrivilegedAction<String>() { 393 @Override 394 public String run() { 395 return Security.getProperty("jdk.tls.keyLimits"); 396 } 397 }); 398 399 if (prop != null) { 400 String propvalue[] = prop.split(","); 401 402 for (String entry : propvalue) { 403 int index; 404 // If this is not a UsageLimit, goto to next entry. 405 String values[] = entry.trim().toUpperCase().split(" "); 406 407 if (values[1].contains(tag[0])) { 408 index = 0; 409 } else { 410 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { 411 SSLLogger.fine("jdk.tls.keyLimits: Unknown action: " + 412 entry); 413 } 414 continue; 415 } 416 417 long size; 418 int i = values[2].indexOf("^"); 419 try { 420 if (i >= 0) { 421 size = (long) Math.pow(2, 422 Integer.parseInt(values[2].substring(i + 1))); 423 } else { 424 size = Long.parseLong(values[2]); 425 } 426 if (size < 1 || size > max) { 427 throw new NumberFormatException( 428 "Length exceeded limits"); 429 } 430 } catch (NumberFormatException e) { 431 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { 432 SSLLogger.fine("jdk.tls.keyLimits: " + e.getMessage() + 433 ": " + entry); 434 } 435 continue; 436 } 437 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { 438 SSLLogger.fine("jdk.tls.keyLimits: entry = " + entry + 439 ". " + values[0] + ":" + tag[index] + " = " + size); 440 } 441 cipherLimits.put(values[0] + ":" + tag[index], size); 442 } 443 } 444 } 445 SSLCipher(String transformation, CipherType cipherType, int keySize, int expandedKeySize, int ivSize, int fixedIvSize, boolean allowed, boolean exportable, Map.Entry<ReadCipherGenerator, ProtocolVersion[]>[] readCipherGenerators, Map.Entry<WriteCipherGenerator, ProtocolVersion[]>[] writeCipherGenerators)446 private SSLCipher(String transformation, 447 CipherType cipherType, int keySize, 448 int expandedKeySize, int ivSize, 449 int fixedIvSize, boolean allowed, boolean exportable, 450 Map.Entry<ReadCipherGenerator, 451 ProtocolVersion[]>[] readCipherGenerators, 452 Map.Entry<WriteCipherGenerator, 453 ProtocolVersion[]>[] writeCipherGenerators) { 454 this.transformation = transformation; 455 String[] splits = transformation.split("/"); 456 this.algorithm = splits[0]; 457 this.cipherType = cipherType; 458 this.description = this.algorithm + "/" + (keySize << 3); 459 this.keySize = keySize; 460 this.ivSize = ivSize; 461 this.fixedIvSize = fixedIvSize; 462 this.allowed = allowed; 463 464 this.expandedKeySize = expandedKeySize; 465 this.exportable = exportable; 466 467 // availability of this bulk cipher 468 // 469 // AES/256 is unavailable when the default JCE policy jurisdiction files 470 // are installed because of key length restrictions. 471 this.isAvailable = allowed && isUnlimited(keySize, transformation) && 472 isTransformationAvailable(transformation); 473 474 this.readCipherGenerators = readCipherGenerators; 475 this.writeCipherGenerators = writeCipherGenerators; 476 } 477 isTransformationAvailable(String transformation)478 private static boolean isTransformationAvailable(String transformation) { 479 if (transformation.equals("NULL")) { 480 return true; 481 } 482 try { 483 JsseJce.getCipher(transformation); 484 return true; 485 } catch (NoSuchAlgorithmException e) { 486 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { 487 SSLLogger.fine("Transformation " + transformation + " is" + 488 " not available."); 489 } 490 } 491 return false; 492 } 493 createReadCipher(Authenticator authenticator, ProtocolVersion protocolVersion, SecretKey key, IvParameterSpec iv, SecureRandom random)494 SSLReadCipher createReadCipher(Authenticator authenticator, 495 ProtocolVersion protocolVersion, 496 SecretKey key, IvParameterSpec iv, 497 SecureRandom random) throws GeneralSecurityException { 498 if (readCipherGenerators.length == 0) { 499 return null; 500 } 501 502 ReadCipherGenerator rcg = null; 503 for (Map.Entry<ReadCipherGenerator, 504 ProtocolVersion[]> me : readCipherGenerators) { 505 for (ProtocolVersion pv : me.getValue()) { 506 if (protocolVersion == pv) { 507 rcg = me.getKey(); 508 } 509 } 510 } 511 512 if (rcg != null) { 513 return rcg.createCipher(this, authenticator, 514 protocolVersion, transformation, key, iv, random); 515 } 516 return null; 517 } 518 createWriteCipher(Authenticator authenticator, ProtocolVersion protocolVersion, SecretKey key, IvParameterSpec iv, SecureRandom random)519 SSLWriteCipher createWriteCipher(Authenticator authenticator, 520 ProtocolVersion protocolVersion, 521 SecretKey key, IvParameterSpec iv, 522 SecureRandom random) throws GeneralSecurityException { 523 if (writeCipherGenerators.length == 0) { 524 return null; 525 } 526 527 WriteCipherGenerator wcg = null; 528 for (Map.Entry<WriteCipherGenerator, 529 ProtocolVersion[]> me : writeCipherGenerators) { 530 for (ProtocolVersion pv : me.getValue()) { 531 if (protocolVersion == pv) { 532 wcg = me.getKey(); 533 } 534 } 535 } 536 537 if (wcg != null) { 538 return wcg.createCipher(this, authenticator, 539 protocolVersion, transformation, key, iv, random); 540 } 541 return null; 542 } 543 544 /** 545 * Test if this bulk cipher is available. For use by CipherSuite. 546 */ isAvailable()547 boolean isAvailable() { 548 return this.isAvailable; 549 } 550 isUnlimited(int keySize, String transformation)551 private static boolean isUnlimited(int keySize, String transformation) { 552 int keySizeInBits = keySize * 8; 553 if (keySizeInBits > 128) { // need the JCE unlimited 554 // strength jurisdiction policy 555 try { 556 if (Cipher.getMaxAllowedKeyLength( 557 transformation) < keySizeInBits) { 558 return false; 559 } 560 } catch (Exception e) { 561 return false; 562 } 563 } 564 565 return true; 566 } 567 568 @Override toString()569 public String toString() { 570 return description; 571 } 572 573 interface ReadCipherGenerator { createCipher(SSLCipher sslCipher, Authenticator authenticator, ProtocolVersion protocolVersion, String algorithm, Key key, AlgorithmParameterSpec params, SecureRandom random)574 SSLReadCipher createCipher(SSLCipher sslCipher, 575 Authenticator authenticator, 576 ProtocolVersion protocolVersion, String algorithm, 577 Key key, AlgorithmParameterSpec params, 578 SecureRandom random) throws GeneralSecurityException; 579 } 580 581 abstract static class SSLReadCipher { 582 final Authenticator authenticator; 583 final ProtocolVersion protocolVersion; 584 boolean keyLimitEnabled = false; 585 long keyLimitCountdown = 0; 586 SecretKey baseSecret; 587 SSLReadCipher(Authenticator authenticator, ProtocolVersion protocolVersion)588 SSLReadCipher(Authenticator authenticator, 589 ProtocolVersion protocolVersion) { 590 this.authenticator = authenticator; 591 this.protocolVersion = protocolVersion; 592 } 593 nullTlsReadCipher()594 static final SSLReadCipher nullTlsReadCipher() { 595 try { 596 return B_NULL.createReadCipher( 597 Authenticator.nullTlsMac(), 598 ProtocolVersion.NONE, null, null, null); 599 } catch (GeneralSecurityException gse) { 600 // unlikely 601 throw new RuntimeException("Cannot create NULL SSLCipher", gse); 602 } 603 } 604 decrypt(byte contentType, ByteBuffer bb, byte[] sequence)605 abstract Plaintext decrypt(byte contentType, ByteBuffer bb, 606 byte[] sequence) throws GeneralSecurityException; 607 dispose()608 void dispose() { 609 // blank 610 } 611 estimateFragmentSize(int packetSize, int headerSize)612 abstract int estimateFragmentSize(int packetSize, int headerSize); 613 isNullCipher()614 boolean isNullCipher() { 615 return false; 616 } 617 618 /** 619 * Check if processed bytes have reached the key usage limit. 620 * If key usage limit is not be monitored, return false. 621 */ atKeyLimit()622 public boolean atKeyLimit() { 623 if (keyLimitCountdown >= 0) { 624 return false; 625 } 626 627 // Turn off limit checking as KeyUpdate will be occurring 628 keyLimitEnabled = false; 629 return true; 630 } 631 } 632 633 interface WriteCipherGenerator { createCipher(SSLCipher sslCipher, Authenticator authenticator, ProtocolVersion protocolVersion, String algorithm, Key key, AlgorithmParameterSpec params, SecureRandom random)634 SSLWriteCipher createCipher(SSLCipher sslCipher, 635 Authenticator authenticator, 636 ProtocolVersion protocolVersion, String algorithm, 637 Key key, AlgorithmParameterSpec params, 638 SecureRandom random) throws GeneralSecurityException; 639 } 640 641 abstract static class SSLWriteCipher { 642 final Authenticator authenticator; 643 final ProtocolVersion protocolVersion; 644 boolean keyLimitEnabled = false; 645 long keyLimitCountdown = 0; 646 SecretKey baseSecret; 647 SSLWriteCipher(Authenticator authenticator, ProtocolVersion protocolVersion)648 SSLWriteCipher(Authenticator authenticator, 649 ProtocolVersion protocolVersion) { 650 this.authenticator = authenticator; 651 this.protocolVersion = protocolVersion; 652 } 653 encrypt(byte contentType, ByteBuffer bb)654 abstract int encrypt(byte contentType, ByteBuffer bb); 655 nullTlsWriteCipher()656 static final SSLWriteCipher nullTlsWriteCipher() { 657 try { 658 return B_NULL.createWriteCipher( 659 Authenticator.nullTlsMac(), 660 ProtocolVersion.NONE, null, null, null); 661 } catch (GeneralSecurityException gse) { 662 // unlikely 663 throw new RuntimeException( 664 "Cannot create NULL SSL write Cipher", gse); 665 } 666 } 667 dispose()668 void dispose() { 669 // blank 670 } 671 getExplicitNonceSize()672 abstract int getExplicitNonceSize(); calculateFragmentSize(int packetLimit, int headerSize)673 abstract int calculateFragmentSize(int packetLimit, int headerSize); calculatePacketSize(int fragmentSize, int headerSize)674 abstract int calculatePacketSize(int fragmentSize, int headerSize); 675 isCBCMode()676 boolean isCBCMode() { 677 return false; 678 } 679 isNullCipher()680 boolean isNullCipher() { 681 return false; 682 } 683 684 /** 685 * Check if processed bytes have reached the key usage limit. 686 * If key usage limit is not be monitored, return false. 687 */ atKeyLimit()688 public boolean atKeyLimit() { 689 if (keyLimitCountdown >= 0) { 690 return false; 691 } 692 693 // Turn off limit checking as KeyUpdate will be occurring 694 keyLimitEnabled = false; 695 return true; 696 } 697 } 698 699 private static final 700 class NullReadCipherGenerator implements ReadCipherGenerator { 701 @Override createCipher(SSLCipher sslCipher, Authenticator authenticator, ProtocolVersion protocolVersion, String algorithm, Key key, AlgorithmParameterSpec params, SecureRandom random)702 public SSLReadCipher createCipher(SSLCipher sslCipher, 703 Authenticator authenticator, 704 ProtocolVersion protocolVersion, String algorithm, 705 Key key, AlgorithmParameterSpec params, 706 SecureRandom random) throws GeneralSecurityException { 707 return new NullReadCipher(authenticator, protocolVersion); 708 } 709 710 static final class NullReadCipher extends SSLReadCipher { NullReadCipher(Authenticator authenticator, ProtocolVersion protocolVersion)711 NullReadCipher(Authenticator authenticator, 712 ProtocolVersion protocolVersion) { 713 super(authenticator, protocolVersion); 714 } 715 716 @Override decrypt(byte contentType, ByteBuffer bb, byte[] sequence)717 public Plaintext decrypt(byte contentType, ByteBuffer bb, 718 byte[] sequence) throws GeneralSecurityException { 719 MAC signer = (MAC)authenticator; 720 if (signer.macAlg().size != 0) { 721 checkStreamMac(signer, bb, contentType, sequence); 722 } else { 723 authenticator.increaseSequenceNumber(); 724 } 725 726 return new Plaintext(contentType, 727 ProtocolVersion.NONE.major, ProtocolVersion.NONE.minor, 728 -1, -1L, bb.slice()); 729 } 730 731 @Override estimateFragmentSize(int packetSize, int headerSize)732 int estimateFragmentSize(int packetSize, int headerSize) { 733 int macLen = ((MAC)authenticator).macAlg().size; 734 return packetSize - headerSize - macLen; 735 } 736 737 @Override isNullCipher()738 boolean isNullCipher() { 739 return true; 740 } 741 } 742 } 743 744 private static final 745 class NullWriteCipherGenerator implements WriteCipherGenerator { 746 @Override createCipher(SSLCipher sslCipher, Authenticator authenticator, ProtocolVersion protocolVersion, String algorithm, Key key, AlgorithmParameterSpec params, SecureRandom random)747 public SSLWriteCipher createCipher(SSLCipher sslCipher, 748 Authenticator authenticator, 749 ProtocolVersion protocolVersion, String algorithm, 750 Key key, AlgorithmParameterSpec params, 751 SecureRandom random) throws GeneralSecurityException { 752 return new NullWriteCipher(authenticator, protocolVersion); 753 } 754 755 static final class NullWriteCipher extends SSLWriteCipher { NullWriteCipher(Authenticator authenticator, ProtocolVersion protocolVersion)756 NullWriteCipher(Authenticator authenticator, 757 ProtocolVersion protocolVersion) { 758 super(authenticator, protocolVersion); 759 } 760 761 @Override encrypt(byte contentType, ByteBuffer bb)762 public int encrypt(byte contentType, ByteBuffer bb) { 763 // add message authentication code 764 MAC signer = (MAC)authenticator; 765 if (signer.macAlg().size != 0) { 766 addMac(signer, bb, contentType); 767 } else { 768 authenticator.increaseSequenceNumber(); 769 } 770 771 int len = bb.remaining(); 772 bb.position(bb.limit()); 773 return len; 774 } 775 776 777 @Override getExplicitNonceSize()778 int getExplicitNonceSize() { 779 return 0; 780 } 781 782 @Override calculateFragmentSize(int packetLimit, int headerSize)783 int calculateFragmentSize(int packetLimit, int headerSize) { 784 int macLen = ((MAC)authenticator).macAlg().size; 785 return packetLimit - headerSize - macLen; 786 } 787 788 @Override calculatePacketSize(int fragmentSize, int headerSize)789 int calculatePacketSize(int fragmentSize, int headerSize) { 790 int macLen = ((MAC)authenticator).macAlg().size; 791 return fragmentSize + headerSize + macLen; 792 } 793 794 @Override isNullCipher()795 boolean isNullCipher() { 796 return true; 797 } 798 } 799 } 800 801 private static final 802 class StreamReadCipherGenerator implements ReadCipherGenerator { 803 @Override createCipher(SSLCipher sslCipher, Authenticator authenticator, ProtocolVersion protocolVersion, String algorithm, Key key, AlgorithmParameterSpec params, SecureRandom random)804 public SSLReadCipher createCipher(SSLCipher sslCipher, 805 Authenticator authenticator, 806 ProtocolVersion protocolVersion, String algorithm, 807 Key key, AlgorithmParameterSpec params, 808 SecureRandom random) throws GeneralSecurityException { 809 return new StreamReadCipher(authenticator, protocolVersion, 810 algorithm, key, params, random); 811 } 812 813 static final class StreamReadCipher extends SSLReadCipher { 814 private final Cipher cipher; 815 StreamReadCipher(Authenticator authenticator, ProtocolVersion protocolVersion, String algorithm, Key key, AlgorithmParameterSpec params, SecureRandom random)816 StreamReadCipher(Authenticator authenticator, 817 ProtocolVersion protocolVersion, String algorithm, 818 Key key, AlgorithmParameterSpec params, 819 SecureRandom random) throws GeneralSecurityException { 820 super(authenticator, protocolVersion); 821 this.cipher = JsseJce.getCipher(algorithm); 822 cipher.init(Cipher.DECRYPT_MODE, key, params, random); 823 } 824 825 @Override decrypt(byte contentType, ByteBuffer bb, byte[] sequence)826 public Plaintext decrypt(byte contentType, ByteBuffer bb, 827 byte[] sequence) throws GeneralSecurityException { 828 int len = bb.remaining(); 829 int pos = bb.position(); 830 ByteBuffer dup = bb.duplicate(); 831 try { 832 if (len != cipher.update(dup, bb)) { 833 // catch BouncyCastle buffering error 834 throw new RuntimeException( 835 "Unexpected number of plaintext bytes"); 836 } 837 if (bb.position() != dup.position()) { 838 throw new RuntimeException( 839 "Unexpected ByteBuffer position"); 840 } 841 } catch (ShortBufferException sbe) { 842 // catch BouncyCastle buffering error 843 throw new RuntimeException("Cipher buffering error in " + 844 "JCE provider " + cipher.getProvider().getName(), sbe); 845 } 846 bb.position(pos); 847 if (SSLLogger.isOn && SSLLogger.isOn("plaintext")) { 848 SSLLogger.fine( 849 "Plaintext after DECRYPTION", bb.duplicate()); 850 } 851 852 MAC signer = (MAC)authenticator; 853 if (signer.macAlg().size != 0) { 854 checkStreamMac(signer, bb, contentType, sequence); 855 } else { 856 authenticator.increaseSequenceNumber(); 857 } 858 859 return new Plaintext(contentType, 860 ProtocolVersion.NONE.major, ProtocolVersion.NONE.minor, 861 -1, -1L, bb.slice()); 862 } 863 864 @Override dispose()865 void dispose() { 866 if (cipher != null) { 867 try { 868 cipher.doFinal(); 869 } catch (Exception e) { 870 // swallow all types of exceptions. 871 } 872 } 873 } 874 875 @Override estimateFragmentSize(int packetSize, int headerSize)876 int estimateFragmentSize(int packetSize, int headerSize) { 877 int macLen = ((MAC)authenticator).macAlg().size; 878 return packetSize - headerSize - macLen; 879 } 880 } 881 } 882 883 private static final 884 class StreamWriteCipherGenerator implements WriteCipherGenerator { 885 @Override createCipher(SSLCipher sslCipher, Authenticator authenticator, ProtocolVersion protocolVersion, String algorithm, Key key, AlgorithmParameterSpec params, SecureRandom random)886 public SSLWriteCipher createCipher(SSLCipher sslCipher, 887 Authenticator authenticator, 888 ProtocolVersion protocolVersion, String algorithm, 889 Key key, AlgorithmParameterSpec params, 890 SecureRandom random) throws GeneralSecurityException { 891 return new StreamWriteCipher(authenticator, 892 protocolVersion, algorithm, key, params, random); 893 } 894 895 static final class StreamWriteCipher extends SSLWriteCipher { 896 private final Cipher cipher; 897 StreamWriteCipher(Authenticator authenticator, ProtocolVersion protocolVersion, String algorithm, Key key, AlgorithmParameterSpec params, SecureRandom random)898 StreamWriteCipher(Authenticator authenticator, 899 ProtocolVersion protocolVersion, String algorithm, 900 Key key, AlgorithmParameterSpec params, 901 SecureRandom random) throws GeneralSecurityException { 902 super(authenticator, protocolVersion); 903 this.cipher = JsseJce.getCipher(algorithm); 904 cipher.init(Cipher.ENCRYPT_MODE, key, params, random); 905 } 906 907 @Override encrypt(byte contentType, ByteBuffer bb)908 public int encrypt(byte contentType, ByteBuffer bb) { 909 // add message authentication code 910 MAC signer = (MAC)authenticator; 911 if (signer.macAlg().size != 0) { 912 addMac(signer, bb, contentType); 913 } else { 914 authenticator.increaseSequenceNumber(); 915 } 916 917 if (SSLLogger.isOn && SSLLogger.isOn("plaintext")) { 918 SSLLogger.finest( 919 "Padded plaintext before ENCRYPTION", bb.duplicate()); 920 } 921 922 int len = bb.remaining(); 923 ByteBuffer dup = bb.duplicate(); 924 try { 925 if (len != cipher.update(dup, bb)) { 926 // catch BouncyCastle buffering error 927 throw new RuntimeException( 928 "Unexpected number of plaintext bytes"); 929 } 930 if (bb.position() != dup.position()) { 931 throw new RuntimeException( 932 "Unexpected ByteBuffer position"); 933 } 934 } catch (ShortBufferException sbe) { 935 // catch BouncyCastle buffering error 936 throw new RuntimeException("Cipher buffering error in " + 937 "JCE provider " + cipher.getProvider().getName(), sbe); 938 } 939 940 return len; 941 } 942 943 @Override dispose()944 void dispose() { 945 if (cipher != null) { 946 try { 947 cipher.doFinal(); 948 } catch (Exception e) { 949 // swallow all types of exceptions. 950 } 951 } 952 } 953 954 @Override getExplicitNonceSize()955 int getExplicitNonceSize() { 956 return 0; 957 } 958 959 @Override calculateFragmentSize(int packetLimit, int headerSize)960 int calculateFragmentSize(int packetLimit, int headerSize) { 961 int macLen = ((MAC)authenticator).macAlg().size; 962 return packetLimit - headerSize - macLen; 963 } 964 965 @Override calculatePacketSize(int fragmentSize, int headerSize)966 int calculatePacketSize(int fragmentSize, int headerSize) { 967 int macLen = ((MAC)authenticator).macAlg().size; 968 return fragmentSize + headerSize + macLen; 969 } 970 } 971 } 972 973 private static final 974 class T10BlockReadCipherGenerator implements ReadCipherGenerator { 975 @Override createCipher(SSLCipher sslCipher, Authenticator authenticator, ProtocolVersion protocolVersion, String algorithm, Key key, AlgorithmParameterSpec params, SecureRandom random)976 public SSLReadCipher createCipher(SSLCipher sslCipher, 977 Authenticator authenticator, 978 ProtocolVersion protocolVersion, String algorithm, 979 Key key, AlgorithmParameterSpec params, 980 SecureRandom random) throws GeneralSecurityException { 981 return new BlockReadCipher(authenticator, 982 protocolVersion, algorithm, key, params, random); 983 } 984 985 static final class BlockReadCipher extends SSLReadCipher { 986 private final Cipher cipher; 987 BlockReadCipher(Authenticator authenticator, ProtocolVersion protocolVersion, String algorithm, Key key, AlgorithmParameterSpec params, SecureRandom random)988 BlockReadCipher(Authenticator authenticator, 989 ProtocolVersion protocolVersion, String algorithm, 990 Key key, AlgorithmParameterSpec params, 991 SecureRandom random) throws GeneralSecurityException { 992 super(authenticator, protocolVersion); 993 this.cipher = JsseJce.getCipher(algorithm); 994 cipher.init(Cipher.DECRYPT_MODE, key, params, random); 995 } 996 997 @Override decrypt(byte contentType, ByteBuffer bb, byte[] sequence)998 public Plaintext decrypt(byte contentType, ByteBuffer bb, 999 byte[] sequence) throws GeneralSecurityException { 1000 BadPaddingException reservedBPE = null; 1001 1002 // sanity check length of the ciphertext 1003 MAC signer = (MAC)authenticator; 1004 int cipheredLength = bb.remaining(); 1005 int tagLen = signer.macAlg().size; 1006 if (tagLen != 0) { 1007 if (!sanityCheck(tagLen, bb.remaining())) { 1008 reservedBPE = new BadPaddingException( 1009 "ciphertext sanity check failed"); 1010 } 1011 } 1012 // decryption 1013 int len = bb.remaining(); 1014 int pos = bb.position(); 1015 ByteBuffer dup = bb.duplicate(); 1016 try { 1017 if (len != cipher.update(dup, bb)) { 1018 // catch BouncyCastle buffering error 1019 throw new RuntimeException( 1020 "Unexpected number of plaintext bytes"); 1021 } 1022 1023 if (bb.position() != dup.position()) { 1024 throw new RuntimeException( 1025 "Unexpected ByteBuffer position"); 1026 } 1027 } catch (ShortBufferException sbe) { 1028 // catch BouncyCastle buffering error 1029 throw new RuntimeException("Cipher buffering error in " + 1030 "JCE provider " + cipher.getProvider().getName(), sbe); 1031 } 1032 1033 if (SSLLogger.isOn && SSLLogger.isOn("plaintext")) { 1034 SSLLogger.fine( 1035 "Padded plaintext after DECRYPTION", 1036 bb.duplicate().position(pos)); 1037 } 1038 1039 // remove the block padding 1040 int blockSize = cipher.getBlockSize(); 1041 bb.position(pos); 1042 try { 1043 removePadding(bb, tagLen, blockSize, protocolVersion); 1044 } catch (BadPaddingException bpe) { 1045 if (reservedBPE == null) { 1046 reservedBPE = bpe; 1047 } 1048 } 1049 1050 // Requires message authentication code for null, stream and 1051 // block cipher suites. 1052 try { 1053 if (tagLen != 0) { 1054 checkCBCMac(signer, bb, 1055 contentType, cipheredLength, sequence); 1056 } else { 1057 authenticator.increaseSequenceNumber(); 1058 } 1059 } catch (BadPaddingException bpe) { 1060 if (reservedBPE == null) { 1061 reservedBPE = bpe; 1062 } 1063 } 1064 1065 // Is it a failover? 1066 if (reservedBPE != null) { 1067 throw reservedBPE; 1068 } 1069 1070 return new Plaintext(contentType, 1071 ProtocolVersion.NONE.major, ProtocolVersion.NONE.minor, 1072 -1, -1L, bb.slice()); 1073 } 1074 1075 @Override dispose()1076 void dispose() { 1077 if (cipher != null) { 1078 try { 1079 cipher.doFinal(); 1080 } catch (Exception e) { 1081 // swallow all types of exceptions. 1082 } 1083 } 1084 } 1085 1086 @Override estimateFragmentSize(int packetSize, int headerSize)1087 int estimateFragmentSize(int packetSize, int headerSize) { 1088 int macLen = ((MAC)authenticator).macAlg().size; 1089 1090 // No padding for a maximum fragment. 1091 // 1092 // 1 byte padding length field: 0x00 1093 return packetSize - headerSize - macLen - 1; 1094 } 1095 1096 /** 1097 * Sanity check the length of a fragment before decryption. 1098 * 1099 * In CBC mode, check that the fragment length is one or multiple 1100 * times of the block size of the cipher suite, and is at least 1101 * one (one is the smallest size of padding in CBC mode) bigger 1102 * than the tag size of the MAC algorithm except the explicit IV 1103 * size for TLS 1.1 or later. 1104 * 1105 * In non-CBC mode, check that the fragment length is not less than 1106 * the tag size of the MAC algorithm. 1107 * 1108 * @return true if the length of a fragment matches above 1109 * requirements 1110 */ sanityCheck(int tagLen, int fragmentLen)1111 private boolean sanityCheck(int tagLen, int fragmentLen) { 1112 int blockSize = cipher.getBlockSize(); 1113 if ((fragmentLen % blockSize) == 0) { 1114 int minimal = tagLen + 1; 1115 minimal = (minimal >= blockSize) ? minimal : blockSize; 1116 1117 return (fragmentLen >= minimal); 1118 } 1119 1120 return false; 1121 } 1122 } 1123 } 1124 1125 private static final 1126 class T10BlockWriteCipherGenerator implements WriteCipherGenerator { 1127 @Override createCipher(SSLCipher sslCipher, Authenticator authenticator, ProtocolVersion protocolVersion, String algorithm, Key key, AlgorithmParameterSpec params, SecureRandom random)1128 public SSLWriteCipher createCipher(SSLCipher sslCipher, 1129 Authenticator authenticator, 1130 ProtocolVersion protocolVersion, String algorithm, 1131 Key key, AlgorithmParameterSpec params, 1132 SecureRandom random) throws GeneralSecurityException { 1133 return new BlockWriteCipher(authenticator, 1134 protocolVersion, algorithm, key, params, random); 1135 } 1136 1137 static final class BlockWriteCipher extends SSLWriteCipher { 1138 private final Cipher cipher; 1139 BlockWriteCipher(Authenticator authenticator, ProtocolVersion protocolVersion, String algorithm, Key key, AlgorithmParameterSpec params, SecureRandom random)1140 BlockWriteCipher(Authenticator authenticator, 1141 ProtocolVersion protocolVersion, String algorithm, 1142 Key key, AlgorithmParameterSpec params, 1143 SecureRandom random) throws GeneralSecurityException { 1144 super(authenticator, protocolVersion); 1145 this.cipher = JsseJce.getCipher(algorithm); 1146 cipher.init(Cipher.ENCRYPT_MODE, key, params, random); 1147 } 1148 1149 @Override encrypt(byte contentType, ByteBuffer bb)1150 public int encrypt(byte contentType, ByteBuffer bb) { 1151 int pos = bb.position(); 1152 1153 // add message authentication code 1154 MAC signer = (MAC)authenticator; 1155 if (signer.macAlg().size != 0) { 1156 addMac(signer, bb, contentType); 1157 } else { 1158 authenticator.increaseSequenceNumber(); 1159 } 1160 1161 int blockSize = cipher.getBlockSize(); 1162 int len = addPadding(bb, blockSize); 1163 bb.position(pos); 1164 1165 if (SSLLogger.isOn && SSLLogger.isOn("plaintext")) { 1166 SSLLogger.fine( 1167 "Padded plaintext before ENCRYPTION", 1168 bb.duplicate()); 1169 } 1170 1171 ByteBuffer dup = bb.duplicate(); 1172 try { 1173 if (len != cipher.update(dup, bb)) { 1174 // catch BouncyCastle buffering error 1175 throw new RuntimeException( 1176 "Unexpected number of plaintext bytes"); 1177 } 1178 1179 if (bb.position() != dup.position()) { 1180 throw new RuntimeException( 1181 "Unexpected ByteBuffer position"); 1182 } 1183 } catch (ShortBufferException sbe) { 1184 // catch BouncyCastle buffering error 1185 throw new RuntimeException("Cipher buffering error in " + 1186 "JCE provider " + cipher.getProvider().getName(), sbe); 1187 } 1188 1189 return len; 1190 } 1191 1192 @Override dispose()1193 void dispose() { 1194 if (cipher != null) { 1195 try { 1196 cipher.doFinal(); 1197 } catch (Exception e) { 1198 // swallow all types of exceptions. 1199 } 1200 } 1201 } 1202 1203 @Override getExplicitNonceSize()1204 int getExplicitNonceSize() { 1205 return 0; 1206 } 1207 1208 @Override calculateFragmentSize(int packetLimit, int headerSize)1209 int calculateFragmentSize(int packetLimit, int headerSize) { 1210 int macLen = ((MAC)authenticator).macAlg().size; 1211 int blockSize = cipher.getBlockSize(); 1212 int fragLen = packetLimit - headerSize; 1213 fragLen -= (fragLen % blockSize); // cannot hold a block 1214 // No padding for a maximum fragment. 1215 fragLen -= 1; // 1 byte padding length field: 0x00 1216 fragLen -= macLen; 1217 return fragLen; 1218 } 1219 1220 @Override calculatePacketSize(int fragmentSize, int headerSize)1221 int calculatePacketSize(int fragmentSize, int headerSize) { 1222 int macLen = ((MAC)authenticator).macAlg().size; 1223 int blockSize = cipher.getBlockSize(); 1224 int paddedLen = fragmentSize + macLen + 1; 1225 if ((paddedLen % blockSize) != 0) { 1226 paddedLen += blockSize - 1; 1227 paddedLen -= paddedLen % blockSize; 1228 } 1229 1230 return headerSize + paddedLen; 1231 } 1232 1233 @Override isCBCMode()1234 boolean isCBCMode() { 1235 return true; 1236 } 1237 } 1238 } 1239 1240 // For TLS 1.1 and 1.2 1241 private static final 1242 class T11BlockReadCipherGenerator implements ReadCipherGenerator { 1243 @Override createCipher(SSLCipher sslCipher, Authenticator authenticator, ProtocolVersion protocolVersion, String algorithm, Key key, AlgorithmParameterSpec params, SecureRandom random)1244 public SSLReadCipher createCipher(SSLCipher sslCipher, 1245 Authenticator authenticator, ProtocolVersion protocolVersion, 1246 String algorithm, Key key, AlgorithmParameterSpec params, 1247 SecureRandom random) throws GeneralSecurityException { 1248 return new BlockReadCipher(authenticator, protocolVersion, 1249 sslCipher, algorithm, key, params, random); 1250 } 1251 1252 static final class BlockReadCipher extends SSLReadCipher { 1253 private final Cipher cipher; 1254 BlockReadCipher(Authenticator authenticator, ProtocolVersion protocolVersion, SSLCipher sslCipher, String algorithm, Key key, AlgorithmParameterSpec params, SecureRandom random)1255 BlockReadCipher(Authenticator authenticator, 1256 ProtocolVersion protocolVersion, 1257 SSLCipher sslCipher, String algorithm, 1258 Key key, AlgorithmParameterSpec params, 1259 SecureRandom random) throws GeneralSecurityException { 1260 super(authenticator, protocolVersion); 1261 this.cipher = JsseJce.getCipher(algorithm); 1262 if (params == null) { 1263 params = new IvParameterSpec(new byte[sslCipher.ivSize]); 1264 } 1265 cipher.init(Cipher.DECRYPT_MODE, key, params, random); 1266 } 1267 1268 @Override decrypt(byte contentType, ByteBuffer bb, byte[] sequence)1269 public Plaintext decrypt(byte contentType, ByteBuffer bb, 1270 byte[] sequence) throws GeneralSecurityException { 1271 BadPaddingException reservedBPE = null; 1272 1273 // sanity check length of the ciphertext 1274 MAC signer = (MAC)authenticator; 1275 int cipheredLength = bb.remaining(); 1276 int tagLen = signer.macAlg().size; 1277 if (tagLen != 0) { 1278 if (!sanityCheck(tagLen, bb.remaining())) { 1279 reservedBPE = new BadPaddingException( 1280 "ciphertext sanity check failed"); 1281 } 1282 } 1283 1284 // decryption 1285 int len = bb.remaining(); 1286 int pos = bb.position(); 1287 ByteBuffer dup = bb.duplicate(); 1288 try { 1289 if (len != cipher.update(dup, bb)) { 1290 // catch BouncyCastle buffering error 1291 throw new RuntimeException( 1292 "Unexpected number of plaintext bytes"); 1293 } 1294 1295 if (bb.position() != dup.position()) { 1296 throw new RuntimeException( 1297 "Unexpected ByteBuffer position"); 1298 } 1299 } catch (ShortBufferException sbe) { 1300 // catch BouncyCastle buffering error 1301 throw new RuntimeException("Cipher buffering error in " + 1302 "JCE provider " + cipher.getProvider().getName(), sbe); 1303 } 1304 1305 if (SSLLogger.isOn && SSLLogger.isOn("plaintext")) { 1306 SSLLogger.fine( 1307 "Padded plaintext after DECRYPTION", 1308 bb.duplicate().position(pos)); 1309 } 1310 1311 // Ignore the explicit nonce. 1312 bb.position(pos + cipher.getBlockSize()); 1313 pos = bb.position(); 1314 1315 // remove the block padding 1316 int blockSize = cipher.getBlockSize(); 1317 bb.position(pos); 1318 try { 1319 removePadding(bb, tagLen, blockSize, protocolVersion); 1320 } catch (BadPaddingException bpe) { 1321 if (reservedBPE == null) { 1322 reservedBPE = bpe; 1323 } 1324 } 1325 1326 // Requires message authentication code for null, stream and 1327 // block cipher suites. 1328 try { 1329 if (tagLen != 0) { 1330 checkCBCMac(signer, bb, 1331 contentType, cipheredLength, sequence); 1332 } else { 1333 authenticator.increaseSequenceNumber(); 1334 } 1335 } catch (BadPaddingException bpe) { 1336 if (reservedBPE == null) { 1337 reservedBPE = bpe; 1338 } 1339 } 1340 1341 // Is it a failover? 1342 if (reservedBPE != null) { 1343 throw reservedBPE; 1344 } 1345 1346 return new Plaintext(contentType, 1347 ProtocolVersion.NONE.major, ProtocolVersion.NONE.minor, 1348 -1, -1L, bb.slice()); 1349 } 1350 1351 @Override dispose()1352 void dispose() { 1353 if (cipher != null) { 1354 try { 1355 cipher.doFinal(); 1356 } catch (Exception e) { 1357 // swallow all types of exceptions. 1358 } 1359 } 1360 } 1361 1362 @Override estimateFragmentSize(int packetSize, int headerSize)1363 int estimateFragmentSize(int packetSize, int headerSize) { 1364 int macLen = ((MAC)authenticator).macAlg().size; 1365 1366 // No padding for a maximum fragment. 1367 // 1368 // 1 byte padding length field: 0x00 1369 int nonceSize = cipher.getBlockSize(); 1370 return packetSize - headerSize - nonceSize - macLen - 1; 1371 } 1372 1373 /** 1374 * Sanity check the length of a fragment before decryption. 1375 * 1376 * In CBC mode, check that the fragment length is one or multiple 1377 * times of the block size of the cipher suite, and is at least 1378 * one (one is the smallest size of padding in CBC mode) bigger 1379 * than the tag size of the MAC algorithm except the explicit IV 1380 * size for TLS 1.1 or later. 1381 * 1382 * In non-CBC mode, check that the fragment length is not less than 1383 * the tag size of the MAC algorithm. 1384 * 1385 * @return true if the length of a fragment matches above 1386 * requirements 1387 */ sanityCheck(int tagLen, int fragmentLen)1388 private boolean sanityCheck(int tagLen, int fragmentLen) { 1389 int blockSize = cipher.getBlockSize(); 1390 if ((fragmentLen % blockSize) == 0) { 1391 int minimal = tagLen + 1; 1392 minimal = (minimal >= blockSize) ? minimal : blockSize; 1393 minimal += blockSize; 1394 1395 return (fragmentLen >= minimal); 1396 } 1397 1398 return false; 1399 } 1400 } 1401 } 1402 1403 // For TLS 1.1 and 1.2 1404 private static final 1405 class T11BlockWriteCipherGenerator implements WriteCipherGenerator { 1406 @Override createCipher(SSLCipher sslCipher, Authenticator authenticator, ProtocolVersion protocolVersion, String algorithm, Key key, AlgorithmParameterSpec params, SecureRandom random)1407 public SSLWriteCipher createCipher(SSLCipher sslCipher, 1408 Authenticator authenticator, ProtocolVersion protocolVersion, 1409 String algorithm, Key key, AlgorithmParameterSpec params, 1410 SecureRandom random) throws GeneralSecurityException { 1411 return new BlockWriteCipher(authenticator, protocolVersion, 1412 sslCipher, algorithm, key, params, random); 1413 } 1414 1415 static final class BlockWriteCipher extends SSLWriteCipher { 1416 private final Cipher cipher; 1417 private final SecureRandom random; 1418 BlockWriteCipher(Authenticator authenticator, ProtocolVersion protocolVersion, SSLCipher sslCipher, String algorithm, Key key, AlgorithmParameterSpec params, SecureRandom random)1419 BlockWriteCipher(Authenticator authenticator, 1420 ProtocolVersion protocolVersion, 1421 SSLCipher sslCipher, String algorithm, 1422 Key key, AlgorithmParameterSpec params, 1423 SecureRandom random) throws GeneralSecurityException { 1424 super(authenticator, protocolVersion); 1425 this.cipher = JsseJce.getCipher(algorithm); 1426 this.random = random; 1427 if (params == null) { 1428 params = new IvParameterSpec(new byte[sslCipher.ivSize]); 1429 } 1430 cipher.init(Cipher.ENCRYPT_MODE, key, params, random); 1431 } 1432 1433 @Override encrypt(byte contentType, ByteBuffer bb)1434 public int encrypt(byte contentType, ByteBuffer bb) { 1435 // To be unique and aware of overflow-wrap, sequence number 1436 // is used as the nonce_explicit of block cipher suites. 1437 int pos = bb.position(); 1438 1439 // add message authentication code 1440 MAC signer = (MAC)authenticator; 1441 if (signer.macAlg().size != 0) { 1442 addMac(signer, bb, contentType); 1443 } else { 1444 authenticator.increaseSequenceNumber(); 1445 } 1446 1447 // DON'T WORRY, the nonce spaces are considered already. 1448 byte[] nonce = new byte[cipher.getBlockSize()]; 1449 random.nextBytes(nonce); 1450 pos = pos - nonce.length; 1451 bb.position(pos); 1452 bb.put(nonce); 1453 bb.position(pos); 1454 1455 int blockSize = cipher.getBlockSize(); 1456 int len = addPadding(bb, blockSize); 1457 bb.position(pos); 1458 1459 if (SSLLogger.isOn && SSLLogger.isOn("plaintext")) { 1460 SSLLogger.fine( 1461 "Padded plaintext before ENCRYPTION", 1462 bb.duplicate()); 1463 } 1464 1465 ByteBuffer dup = bb.duplicate(); 1466 try { 1467 if (len != cipher.update(dup, bb)) { 1468 // catch BouncyCastle buffering error 1469 throw new RuntimeException( 1470 "Unexpected number of plaintext bytes"); 1471 } 1472 1473 if (bb.position() != dup.position()) { 1474 throw new RuntimeException( 1475 "Unexpected ByteBuffer position"); 1476 } 1477 } catch (ShortBufferException sbe) { 1478 // catch BouncyCastle buffering error 1479 throw new RuntimeException("Cipher buffering error in " + 1480 "JCE provider " + cipher.getProvider().getName(), sbe); 1481 } 1482 1483 return len; 1484 } 1485 1486 @Override dispose()1487 void dispose() { 1488 if (cipher != null) { 1489 try { 1490 cipher.doFinal(); 1491 } catch (Exception e) { 1492 // swallow all types of exceptions. 1493 } 1494 } 1495 } 1496 1497 @Override getExplicitNonceSize()1498 int getExplicitNonceSize() { 1499 return cipher.getBlockSize(); 1500 } 1501 1502 @Override calculateFragmentSize(int packetLimit, int headerSize)1503 int calculateFragmentSize(int packetLimit, int headerSize) { 1504 int macLen = ((MAC)authenticator).macAlg().size; 1505 int blockSize = cipher.getBlockSize(); 1506 int fragLen = packetLimit - headerSize - blockSize; 1507 fragLen -= (fragLen % blockSize); // cannot hold a block 1508 // No padding for a maximum fragment. 1509 fragLen -= 1; // 1 byte padding length field: 0x00 1510 fragLen -= macLen; 1511 return fragLen; 1512 } 1513 1514 @Override calculatePacketSize(int fragmentSize, int headerSize)1515 int calculatePacketSize(int fragmentSize, int headerSize) { 1516 int macLen = ((MAC)authenticator).macAlg().size; 1517 int blockSize = cipher.getBlockSize(); 1518 int paddedLen = fragmentSize + macLen + 1; 1519 if ((paddedLen % blockSize) != 0) { 1520 paddedLen += blockSize - 1; 1521 paddedLen -= paddedLen % blockSize; 1522 } 1523 1524 return headerSize + blockSize + paddedLen; 1525 } 1526 1527 @Override isCBCMode()1528 boolean isCBCMode() { 1529 return true; 1530 } 1531 } 1532 } 1533 1534 private static final 1535 class T12GcmReadCipherGenerator implements ReadCipherGenerator { 1536 @Override createCipher(SSLCipher sslCipher, Authenticator authenticator, ProtocolVersion protocolVersion, String algorithm, Key key, AlgorithmParameterSpec params, SecureRandom random)1537 public SSLReadCipher createCipher(SSLCipher sslCipher, 1538 Authenticator authenticator, 1539 ProtocolVersion protocolVersion, String algorithm, 1540 Key key, AlgorithmParameterSpec params, 1541 SecureRandom random) throws GeneralSecurityException { 1542 return new GcmReadCipher(authenticator, protocolVersion, sslCipher, 1543 algorithm, key, params, random); 1544 } 1545 1546 static final class GcmReadCipher extends SSLReadCipher { 1547 private final Cipher cipher; 1548 private final int tagSize; 1549 private final Key key; 1550 private final byte[] fixedIv; 1551 private final int recordIvSize; 1552 private final SecureRandom random; 1553 GcmReadCipher(Authenticator authenticator, ProtocolVersion protocolVersion, SSLCipher sslCipher, String algorithm, Key key, AlgorithmParameterSpec params, SecureRandom random)1554 GcmReadCipher(Authenticator authenticator, 1555 ProtocolVersion protocolVersion, 1556 SSLCipher sslCipher, String algorithm, 1557 Key key, AlgorithmParameterSpec params, 1558 SecureRandom random) throws GeneralSecurityException { 1559 super(authenticator, protocolVersion); 1560 this.cipher = JsseJce.getCipher(algorithm); 1561 this.tagSize = sslCipher.tagSize; 1562 this.key = key; 1563 this.fixedIv = ((IvParameterSpec)params).getIV(); 1564 this.recordIvSize = sslCipher.ivSize - sslCipher.fixedIvSize; 1565 this.random = random; 1566 1567 // DON'T initialize the cipher for AEAD! 1568 } 1569 1570 @Override decrypt(byte contentType, ByteBuffer bb, byte[] sequence)1571 public Plaintext decrypt(byte contentType, ByteBuffer bb, 1572 byte[] sequence) throws GeneralSecurityException { 1573 if (bb.remaining() < (recordIvSize + tagSize)) { 1574 throw new BadPaddingException( 1575 "Insufficient buffer remaining for AEAD cipher " + 1576 "fragment (" + bb.remaining() + "). Needs to be " + 1577 "more than or equal to IV size (" + recordIvSize + 1578 ") + tag size (" + tagSize + ")"); 1579 } 1580 1581 // initialize the AEAD cipher for the unique IV 1582 byte[] iv = Arrays.copyOf(fixedIv, 1583 fixedIv.length + recordIvSize); 1584 bb.get(iv, fixedIv.length, recordIvSize); 1585 GCMParameterSpec spec = new GCMParameterSpec(tagSize * 8, iv); 1586 try { 1587 cipher.init(Cipher.DECRYPT_MODE, key, spec, random); 1588 } catch (InvalidKeyException | 1589 InvalidAlgorithmParameterException ikae) { 1590 // unlikely to happen 1591 throw new RuntimeException( 1592 "invalid key or spec in GCM mode", ikae); 1593 } 1594 1595 // update the additional authentication data 1596 byte[] aad = authenticator.acquireAuthenticationBytes( 1597 contentType, bb.remaining() - tagSize, 1598 sequence); 1599 cipher.updateAAD(aad); 1600 1601 // DON'T decrypt the nonce_explicit for AEAD mode. The buffer 1602 // position has moved out of the nonce_explicit range. 1603 int len, pos = bb.position(); 1604 ByteBuffer dup = bb.duplicate(); 1605 try { 1606 len = cipher.doFinal(dup, bb); 1607 } catch (IllegalBlockSizeException ibse) { 1608 // unlikely to happen 1609 throw new RuntimeException( 1610 "Cipher error in AEAD mode \"" + ibse.getMessage() + 1611 " \"in JCE provider " + cipher.getProvider().getName()); 1612 } catch (ShortBufferException sbe) { 1613 // catch BouncyCastle buffering error 1614 throw new RuntimeException("Cipher buffering error in " + 1615 "JCE provider " + cipher.getProvider().getName(), sbe); 1616 } 1617 // reset the limit to the end of the decrypted data 1618 bb.position(pos); 1619 bb.limit(pos + len); 1620 1621 if (SSLLogger.isOn && SSLLogger.isOn("plaintext")) { 1622 SSLLogger.fine( 1623 "Plaintext after DECRYPTION", bb.duplicate()); 1624 } 1625 1626 return new Plaintext(contentType, 1627 ProtocolVersion.NONE.major, ProtocolVersion.NONE.minor, 1628 -1, -1L, bb.slice()); 1629 } 1630 1631 @Override dispose()1632 void dispose() { 1633 if (cipher != null) { 1634 try { 1635 cipher.doFinal(); 1636 } catch (Exception e) { 1637 // swallow all types of exceptions. 1638 } 1639 } 1640 } 1641 1642 @Override estimateFragmentSize(int packetSize, int headerSize)1643 int estimateFragmentSize(int packetSize, int headerSize) { 1644 return packetSize - headerSize - recordIvSize - tagSize; 1645 } 1646 } 1647 } 1648 1649 private static final 1650 class T12GcmWriteCipherGenerator implements WriteCipherGenerator { 1651 @Override createCipher(SSLCipher sslCipher, Authenticator authenticator, ProtocolVersion protocolVersion, String algorithm, Key key, AlgorithmParameterSpec params, SecureRandom random)1652 public SSLWriteCipher createCipher(SSLCipher sslCipher, 1653 Authenticator authenticator, 1654 ProtocolVersion protocolVersion, String algorithm, 1655 Key key, AlgorithmParameterSpec params, 1656 SecureRandom random) throws GeneralSecurityException { 1657 return new GcmWriteCipher(authenticator, protocolVersion, sslCipher, 1658 algorithm, key, params, random); 1659 } 1660 1661 private static final class GcmWriteCipher extends SSLWriteCipher { 1662 private final Cipher cipher; 1663 private final int tagSize; 1664 private final Key key; 1665 private final byte[] fixedIv; 1666 private final int recordIvSize; 1667 private final SecureRandom random; 1668 GcmWriteCipher(Authenticator authenticator, ProtocolVersion protocolVersion, SSLCipher sslCipher, String algorithm, Key key, AlgorithmParameterSpec params, SecureRandom random)1669 GcmWriteCipher(Authenticator authenticator, 1670 ProtocolVersion protocolVersion, 1671 SSLCipher sslCipher, String algorithm, 1672 Key key, AlgorithmParameterSpec params, 1673 SecureRandom random) throws GeneralSecurityException { 1674 super(authenticator, protocolVersion); 1675 this.cipher = JsseJce.getCipher(algorithm); 1676 this.tagSize = sslCipher.tagSize; 1677 this.key = key; 1678 this.fixedIv = ((IvParameterSpec)params).getIV(); 1679 this.recordIvSize = sslCipher.ivSize - sslCipher.fixedIvSize; 1680 this.random = random; 1681 1682 // DON'T initialize the cipher for AEAD! 1683 } 1684 1685 @Override encrypt(byte contentType, ByteBuffer bb)1686 public int encrypt(byte contentType, 1687 ByteBuffer bb) { 1688 // To be unique and aware of overflow-wrap, sequence number 1689 // is used as the nonce_explicit of AEAD cipher suites. 1690 byte[] nonce = authenticator.sequenceNumber(); 1691 1692 // initialize the AEAD cipher for the unique IV 1693 byte[] iv = Arrays.copyOf(fixedIv, 1694 fixedIv.length + nonce.length); 1695 System.arraycopy(nonce, 0, iv, fixedIv.length, nonce.length); 1696 1697 GCMParameterSpec spec = new GCMParameterSpec(tagSize * 8, iv); 1698 try { 1699 cipher.init(Cipher.ENCRYPT_MODE, key, spec, random); 1700 } catch (InvalidKeyException | 1701 InvalidAlgorithmParameterException ikae) { 1702 // unlikely to happen 1703 throw new RuntimeException( 1704 "invalid key or spec in GCM mode", ikae); 1705 } 1706 1707 // Update the additional authentication data, using the 1708 // implicit sequence number of the authenticator. 1709 byte[] aad = authenticator.acquireAuthenticationBytes( 1710 contentType, bb.remaining(), null); 1711 cipher.updateAAD(aad); 1712 1713 // DON'T WORRY, the nonce spaces are considered already. 1714 bb.position(bb.position() - nonce.length); 1715 bb.put(nonce); 1716 1717 // DON'T encrypt the nonce for AEAD mode. 1718 int len, pos = bb.position(); 1719 if (SSLLogger.isOn && SSLLogger.isOn("plaintext")) { 1720 SSLLogger.fine( 1721 "Plaintext before ENCRYPTION", 1722 bb.duplicate()); 1723 } 1724 1725 ByteBuffer dup = bb.duplicate(); 1726 int outputSize = cipher.getOutputSize(dup.remaining()); 1727 if (outputSize > bb.remaining()) { 1728 // Need to expand the limit of the output buffer for 1729 // the authentication tag. 1730 // 1731 // DON'T worry about the buffer's capacity, we have 1732 // reserved space for the authentication tag. 1733 bb.limit(pos + outputSize); 1734 } 1735 1736 try { 1737 len = cipher.doFinal(dup, bb); 1738 } catch (IllegalBlockSizeException | 1739 BadPaddingException | ShortBufferException ibse) { 1740 // unlikely to happen 1741 throw new RuntimeException( 1742 "Cipher error in AEAD mode in JCE provider " + 1743 cipher.getProvider().getName(), ibse); 1744 } 1745 1746 if (len != outputSize) { 1747 throw new RuntimeException( 1748 "Cipher buffering error in JCE provider " + 1749 cipher.getProvider().getName()); 1750 } 1751 1752 return len + nonce.length; 1753 } 1754 1755 @Override dispose()1756 void dispose() { 1757 if (cipher != null) { 1758 try { 1759 cipher.doFinal(); 1760 } catch (Exception e) { 1761 // swallow all types of exceptions. 1762 } 1763 } 1764 } 1765 1766 @Override getExplicitNonceSize()1767 int getExplicitNonceSize() { 1768 return recordIvSize; 1769 } 1770 1771 @Override calculateFragmentSize(int packetLimit, int headerSize)1772 int calculateFragmentSize(int packetLimit, int headerSize) { 1773 return packetLimit - headerSize - recordIvSize - tagSize; 1774 } 1775 1776 @Override calculatePacketSize(int fragmentSize, int headerSize)1777 int calculatePacketSize(int fragmentSize, int headerSize) { 1778 return fragmentSize + headerSize + recordIvSize + tagSize; 1779 } 1780 } 1781 } 1782 1783 private static final 1784 class T13GcmReadCipherGenerator implements ReadCipherGenerator { 1785 1786 @Override createCipher(SSLCipher sslCipher, Authenticator authenticator, ProtocolVersion protocolVersion, String algorithm, Key key, AlgorithmParameterSpec params, SecureRandom random)1787 public SSLReadCipher createCipher(SSLCipher sslCipher, 1788 Authenticator authenticator, ProtocolVersion protocolVersion, 1789 String algorithm, Key key, AlgorithmParameterSpec params, 1790 SecureRandom random) throws GeneralSecurityException { 1791 return new GcmReadCipher(authenticator, protocolVersion, sslCipher, 1792 algorithm, key, params, random); 1793 } 1794 1795 static final class GcmReadCipher extends SSLReadCipher { 1796 private final Cipher cipher; 1797 private final int tagSize; 1798 private final Key key; 1799 private final byte[] iv; 1800 private final SecureRandom random; 1801 GcmReadCipher(Authenticator authenticator, ProtocolVersion protocolVersion, SSLCipher sslCipher, String algorithm, Key key, AlgorithmParameterSpec params, SecureRandom random)1802 GcmReadCipher(Authenticator authenticator, 1803 ProtocolVersion protocolVersion, 1804 SSLCipher sslCipher, String algorithm, 1805 Key key, AlgorithmParameterSpec params, 1806 SecureRandom random) throws GeneralSecurityException { 1807 super(authenticator, protocolVersion); 1808 this.cipher = JsseJce.getCipher(algorithm); 1809 this.tagSize = sslCipher.tagSize; 1810 this.key = key; 1811 this.iv = ((IvParameterSpec)params).getIV(); 1812 this.random = random; 1813 1814 keyLimitCountdown = cipherLimits.getOrDefault( 1815 algorithm.toUpperCase() + ":" + tag[0], 0L); 1816 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { 1817 SSLLogger.fine("KeyLimit read side: algorithm = " + 1818 algorithm.toUpperCase() + ":" + tag[0] + 1819 "\ncountdown value = " + keyLimitCountdown); 1820 } 1821 if (keyLimitCountdown > 0) { 1822 keyLimitEnabled = true; 1823 } 1824 // DON'T initialize the cipher for AEAD! 1825 } 1826 1827 @Override decrypt(byte contentType, ByteBuffer bb, byte[] sequence)1828 public Plaintext decrypt(byte contentType, ByteBuffer bb, 1829 byte[] sequence) throws GeneralSecurityException { 1830 // An implementation may receive an unencrypted record of type 1831 // change_cipher_spec consisting of the single byte value 0x01 1832 // at any time after the first ClientHello message has been 1833 // sent or received and before the peer's Finished message has 1834 // been received and MUST simply drop it without further 1835 // processing. 1836 if (contentType == ContentType.CHANGE_CIPHER_SPEC.id) { 1837 return new Plaintext(contentType, 1838 ProtocolVersion.NONE.major, ProtocolVersion.NONE.minor, 1839 -1, -1L, bb.slice()); 1840 } 1841 1842 if (bb.remaining() <= tagSize) { 1843 throw new BadPaddingException( 1844 "Insufficient buffer remaining for AEAD cipher " + 1845 "fragment (" + bb.remaining() + "). Needs to be " + 1846 "more than tag size (" + tagSize + ")"); 1847 } 1848 1849 byte[] sn = sequence; 1850 if (sn == null) { 1851 sn = authenticator.sequenceNumber(); 1852 } 1853 byte[] nonce = iv.clone(); 1854 int offset = nonce.length - sn.length; 1855 for (int i = 0; i < sn.length; i++) { 1856 nonce[offset + i] ^= sn[i]; 1857 } 1858 1859 // initialize the AEAD cipher for the unique IV 1860 GCMParameterSpec spec = 1861 new GCMParameterSpec(tagSize * 8, nonce); 1862 try { 1863 cipher.init(Cipher.DECRYPT_MODE, key, spec, random); 1864 } catch (InvalidKeyException | 1865 InvalidAlgorithmParameterException ikae) { 1866 // unlikely to happen 1867 throw new RuntimeException( 1868 "invalid key or spec in GCM mode", ikae); 1869 } 1870 1871 // Update the additional authentication data, using the 1872 // implicit sequence number of the authenticator. 1873 byte[] aad = authenticator.acquireAuthenticationBytes( 1874 contentType, bb.remaining(), sn); 1875 cipher.updateAAD(aad); 1876 1877 int len, pos = bb.position(); 1878 ByteBuffer dup = bb.duplicate(); 1879 try { 1880 len = cipher.doFinal(dup, bb); 1881 } catch (IllegalBlockSizeException ibse) { 1882 // unlikely to happen 1883 throw new RuntimeException( 1884 "Cipher error in AEAD mode \"" + ibse.getMessage() + 1885 " \"in JCE provider " + cipher.getProvider().getName()); 1886 } catch (ShortBufferException sbe) { 1887 // catch BouncyCastle buffering error 1888 throw new RuntimeException("Cipher buffering error in " + 1889 "JCE provider " + cipher.getProvider().getName(), sbe); 1890 } 1891 // reset the limit to the end of the decrypted data 1892 bb.position(pos); 1893 bb.limit(pos + len); 1894 1895 // remove inner plaintext padding 1896 int i = bb.limit() - 1; 1897 for (; i > 0 && bb.get(i) == 0; i--) { 1898 // blank 1899 } 1900 if (i < (pos + 1)) { 1901 throw new BadPaddingException( 1902 "Incorrect inner plaintext: no content type"); 1903 } 1904 contentType = bb.get(i); 1905 bb.limit(i); 1906 1907 if (SSLLogger.isOn && SSLLogger.isOn("plaintext")) { 1908 SSLLogger.fine( 1909 "Plaintext after DECRYPTION", bb.duplicate()); 1910 } 1911 if (keyLimitEnabled) { 1912 keyLimitCountdown -= len; 1913 } 1914 1915 return new Plaintext(contentType, 1916 ProtocolVersion.NONE.major, ProtocolVersion.NONE.minor, 1917 -1, -1L, bb.slice()); 1918 } 1919 1920 @Override dispose()1921 void dispose() { 1922 if (cipher != null) { 1923 try { 1924 cipher.doFinal(); 1925 } catch (Exception e) { 1926 // swallow all types of exceptions. 1927 } 1928 } 1929 } 1930 1931 @Override estimateFragmentSize(int packetSize, int headerSize)1932 int estimateFragmentSize(int packetSize, int headerSize) { 1933 return packetSize - headerSize - tagSize; 1934 } 1935 } 1936 } 1937 1938 private static final 1939 class T13GcmWriteCipherGenerator implements WriteCipherGenerator { 1940 @Override createCipher(SSLCipher sslCipher, Authenticator authenticator, ProtocolVersion protocolVersion, String algorithm, Key key, AlgorithmParameterSpec params, SecureRandom random)1941 public SSLWriteCipher createCipher(SSLCipher sslCipher, 1942 Authenticator authenticator, ProtocolVersion protocolVersion, 1943 String algorithm, Key key, AlgorithmParameterSpec params, 1944 SecureRandom random) throws GeneralSecurityException { 1945 return new GcmWriteCipher(authenticator, protocolVersion, sslCipher, 1946 algorithm, key, params, random); 1947 } 1948 1949 private static final class GcmWriteCipher extends SSLWriteCipher { 1950 private final Cipher cipher; 1951 private final int tagSize; 1952 private final Key key; 1953 private final byte[] iv; 1954 private final SecureRandom random; 1955 GcmWriteCipher(Authenticator authenticator, ProtocolVersion protocolVersion, SSLCipher sslCipher, String algorithm, Key key, AlgorithmParameterSpec params, SecureRandom random)1956 GcmWriteCipher(Authenticator authenticator, 1957 ProtocolVersion protocolVersion, 1958 SSLCipher sslCipher, String algorithm, 1959 Key key, AlgorithmParameterSpec params, 1960 SecureRandom random) throws GeneralSecurityException { 1961 super(authenticator, protocolVersion); 1962 this.cipher = JsseJce.getCipher(algorithm); 1963 this.tagSize = sslCipher.tagSize; 1964 this.key = key; 1965 this.iv = ((IvParameterSpec)params).getIV(); 1966 this.random = random; 1967 1968 keyLimitCountdown = cipherLimits.getOrDefault( 1969 algorithm.toUpperCase() + ":" + tag[0], 0L); 1970 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { 1971 SSLLogger.fine("KeyLimit write side: algorithm = " 1972 + algorithm.toUpperCase() + ":" + tag[0] + 1973 "\ncountdown value = " + keyLimitCountdown); 1974 } 1975 if (keyLimitCountdown > 0) { 1976 keyLimitEnabled = true; 1977 } 1978 1979 // DON'T initialize the cipher for AEAD! 1980 } 1981 1982 @Override encrypt(byte contentType, ByteBuffer bb)1983 public int encrypt(byte contentType, 1984 ByteBuffer bb) { 1985 byte[] sn = authenticator.sequenceNumber(); 1986 byte[] nonce = iv.clone(); 1987 int offset = nonce.length - sn.length; 1988 for (int i = 0; i < sn.length; i++) { 1989 nonce[offset + i] ^= sn[i]; 1990 } 1991 1992 // initialize the AEAD cipher for the unique IV 1993 GCMParameterSpec spec = 1994 new GCMParameterSpec(tagSize * 8, nonce); 1995 try { 1996 cipher.init(Cipher.ENCRYPT_MODE, key, spec, random); 1997 } catch (InvalidKeyException | 1998 InvalidAlgorithmParameterException ikae) { 1999 // unlikely to happen 2000 throw new RuntimeException( 2001 "invalid key or spec in GCM mode", ikae); 2002 } 2003 2004 // Update the additional authentication data, using the 2005 // implicit sequence number of the authenticator. 2006 int outputSize = cipher.getOutputSize(bb.remaining()); 2007 byte[] aad = authenticator.acquireAuthenticationBytes( 2008 contentType, outputSize, sn); 2009 cipher.updateAAD(aad); 2010 2011 int len, pos = bb.position(); 2012 if (SSLLogger.isOn && SSLLogger.isOn("plaintext")) { 2013 SSLLogger.fine( 2014 "Plaintext before ENCRYPTION", 2015 bb.duplicate()); 2016 } 2017 2018 ByteBuffer dup = bb.duplicate(); 2019 if (outputSize > bb.remaining()) { 2020 // Need to expand the limit of the output buffer for 2021 // the authentication tag. 2022 // 2023 // DON'T worry about the buffer's capacity, we have 2024 // reserved space for the authentication tag. 2025 bb.limit(pos + outputSize); 2026 } 2027 2028 try { 2029 len = cipher.doFinal(dup, bb); 2030 } catch (IllegalBlockSizeException | 2031 BadPaddingException | ShortBufferException ibse) { 2032 // unlikely to happen 2033 throw new RuntimeException( 2034 "Cipher error in AEAD mode in JCE provider " + 2035 cipher.getProvider().getName(), ibse); 2036 } 2037 2038 if (len != outputSize) { 2039 throw new RuntimeException( 2040 "Cipher buffering error in JCE provider " + 2041 cipher.getProvider().getName()); 2042 } 2043 2044 if (keyLimitEnabled) { 2045 keyLimitCountdown -= len; 2046 } 2047 return len; 2048 } 2049 2050 @Override dispose()2051 void dispose() { 2052 if (cipher != null) { 2053 try { 2054 cipher.doFinal(); 2055 } catch (Exception e) { 2056 // swallow all types of exceptions. 2057 } 2058 } 2059 } 2060 2061 @Override getExplicitNonceSize()2062 int getExplicitNonceSize() { 2063 return 0; 2064 } 2065 2066 @Override calculateFragmentSize(int packetLimit, int headerSize)2067 int calculateFragmentSize(int packetLimit, int headerSize) { 2068 return packetLimit - headerSize - tagSize; 2069 } 2070 2071 @Override calculatePacketSize(int fragmentSize, int headerSize)2072 int calculatePacketSize(int fragmentSize, int headerSize) { 2073 return fragmentSize + headerSize + tagSize; 2074 } 2075 } 2076 } 2077 addMac(MAC signer, ByteBuffer destination, byte contentType)2078 private static void addMac(MAC signer, 2079 ByteBuffer destination, byte contentType) { 2080 if (signer.macAlg().size != 0) { 2081 int dstContent = destination.position(); 2082 byte[] hash = signer.compute(contentType, destination, false); 2083 2084 /* 2085 * position was advanced to limit in MAC compute above. 2086 * 2087 * Mark next area as writable (above layers should have 2088 * established that we have plenty of room), then write 2089 * out the hash. 2090 */ 2091 destination.limit(destination.limit() + hash.length); 2092 destination.put(hash); 2093 2094 // reset the position and limit 2095 destination.position(dstContent); 2096 } 2097 } 2098 2099 // for null and stream cipher checkStreamMac(MAC signer, ByteBuffer bb, byte contentType, byte[] sequence)2100 private static void checkStreamMac(MAC signer, ByteBuffer bb, 2101 byte contentType, byte[] sequence) throws BadPaddingException { 2102 int tagLen = signer.macAlg().size; 2103 2104 // Requires message authentication code for null, stream and 2105 // block cipher suites. 2106 if (tagLen != 0) { 2107 int contentLen = bb.remaining() - tagLen; 2108 if (contentLen < 0) { 2109 throw new BadPaddingException("bad record"); 2110 } 2111 2112 // Run MAC computation and comparison on the payload. 2113 // 2114 // MAC data would be stripped off during the check. 2115 if (checkMacTags(contentType, bb, signer, sequence, false)) { 2116 throw new BadPaddingException("bad record MAC"); 2117 } 2118 } 2119 } 2120 2121 // for CBC cipher checkCBCMac(MAC signer, ByteBuffer bb, byte contentType, int cipheredLength, byte[] sequence)2122 private static void checkCBCMac(MAC signer, ByteBuffer bb, 2123 byte contentType, int cipheredLength, 2124 byte[] sequence) throws BadPaddingException { 2125 BadPaddingException reservedBPE = null; 2126 int tagLen = signer.macAlg().size; 2127 int pos = bb.position(); 2128 2129 if (tagLen != 0) { 2130 int contentLen = bb.remaining() - tagLen; 2131 if (contentLen < 0) { 2132 reservedBPE = new BadPaddingException("bad record"); 2133 2134 // set offset of the dummy MAC 2135 contentLen = cipheredLength - tagLen; 2136 bb.limit(pos + cipheredLength); 2137 } 2138 2139 // Run MAC computation and comparison on the payload. 2140 // 2141 // MAC data would be stripped off during the check. 2142 if (checkMacTags(contentType, bb, signer, sequence, false)) { 2143 if (reservedBPE == null) { 2144 reservedBPE = 2145 new BadPaddingException("bad record MAC"); 2146 } 2147 } 2148 2149 // Run MAC computation and comparison on the remainder. 2150 int remainingLen = calculateRemainingLen( 2151 signer, cipheredLength, contentLen); 2152 2153 // NOTE: remainingLen may be bigger (less than 1 block of the 2154 // hash algorithm of the MAC) than the cipheredLength. 2155 // 2156 // Is it possible to use a static buffer, rather than allocate 2157 // it dynamically? 2158 remainingLen += signer.macAlg().size; 2159 ByteBuffer temporary = ByteBuffer.allocate(remainingLen); 2160 2161 // Won't need to worry about the result on the remainder. And 2162 // then we won't need to worry about what's actual data to 2163 // check MAC tag on. We start the check from the header of the 2164 // buffer so that we don't need to construct a new byte buffer. 2165 checkMacTags(contentType, temporary, signer, sequence, true); 2166 } 2167 2168 // Is it a failover? 2169 if (reservedBPE != null) { 2170 throw reservedBPE; 2171 } 2172 } 2173 2174 /* 2175 * Run MAC computation and comparison 2176 */ checkMacTags(byte contentType, ByteBuffer bb, MAC signer, byte[] sequence, boolean isSimulated)2177 private static boolean checkMacTags(byte contentType, ByteBuffer bb, 2178 MAC signer, byte[] sequence, boolean isSimulated) { 2179 int tagLen = signer.macAlg().size; 2180 int position = bb.position(); 2181 int lim = bb.limit(); 2182 int macOffset = lim - tagLen; 2183 2184 bb.limit(macOffset); 2185 byte[] hash = signer.compute(contentType, bb, sequence, isSimulated); 2186 if (hash == null || tagLen != hash.length) { 2187 // Something is wrong with MAC implementation. 2188 throw new RuntimeException("Internal MAC error"); 2189 } 2190 2191 bb.position(macOffset); 2192 bb.limit(lim); 2193 try { 2194 int[] results = compareMacTags(bb, hash); 2195 return (results[0] != 0); 2196 } finally { 2197 // reset to the data 2198 bb.position(position); 2199 bb.limit(macOffset); 2200 } 2201 } 2202 2203 /* 2204 * A constant-time comparison of the MAC tags. 2205 * 2206 * Please DON'T change the content of the ByteBuffer parameter! 2207 */ compareMacTags(ByteBuffer bb, byte[] tag)2208 private static int[] compareMacTags(ByteBuffer bb, byte[] tag) { 2209 // An array of hits is used to prevent Hotspot optimization for 2210 // the purpose of a constant-time check. 2211 int[] results = {0, 0}; // {missed #, matched #} 2212 2213 // The caller ensures there are enough bytes available in the buffer. 2214 // So we won't need to check the remaining of the buffer. 2215 for (byte t : tag) { 2216 if (bb.get() != t) { 2217 results[0]++; // mismatched bytes 2218 } else { 2219 results[1]++; // matched bytes 2220 } 2221 } 2222 2223 return results; 2224 } 2225 2226 /* 2227 * Calculate the length of a dummy buffer to run MAC computation 2228 * and comparison on the remainder. 2229 * 2230 * The caller MUST ensure that the fullLen is not less than usedLen. 2231 */ calculateRemainingLen( MAC signer, int fullLen, int usedLen)2232 private static int calculateRemainingLen( 2233 MAC signer, int fullLen, int usedLen) { 2234 2235 int blockLen = signer.macAlg().hashBlockSize; 2236 int minimalPaddingLen = signer.macAlg().minimalPaddingSize; 2237 2238 // (blockLen - minimalPaddingLen) is the maximum message size of 2239 // the last block of hash function operation. See FIPS 180-4, or 2240 // MD5 specification. 2241 fullLen += 13 - (blockLen - minimalPaddingLen); 2242 usedLen += 13 - (blockLen - minimalPaddingLen); 2243 2244 // Note: fullLen is always not less than usedLen, and blockLen 2245 // is always bigger than minimalPaddingLen, so we don't worry 2246 // about negative values. 0x01 is added to the result to ensure 2247 // that the return value is positive. The extra one byte does 2248 // not impact the overall MAC compression function evaluations. 2249 return 0x01 + (int)(Math.ceil(fullLen/(1.0d * blockLen)) - 2250 Math.ceil(usedLen/(1.0d * blockLen))) * blockLen; 2251 } 2252 addPadding(ByteBuffer bb, int blockSize)2253 private static int addPadding(ByteBuffer bb, int blockSize) { 2254 2255 int len = bb.remaining(); 2256 int offset = bb.position(); 2257 2258 int newlen = len + 1; 2259 byte pad; 2260 int i; 2261 2262 if ((newlen % blockSize) != 0) { 2263 newlen += blockSize - 1; 2264 newlen -= newlen % blockSize; 2265 } 2266 pad = (byte) (newlen - len); 2267 2268 /* 2269 * Update the limit to what will be padded. 2270 */ 2271 bb.limit(newlen + offset); 2272 2273 /* 2274 * TLS version of the padding works for both SSLv3 and TLSv1 2275 */ 2276 for (i = 0, offset += len; i < pad; i++) { 2277 bb.put(offset++, (byte) (pad - 1)); 2278 } 2279 2280 bb.position(offset); 2281 bb.limit(offset); 2282 2283 return newlen; 2284 } 2285 removePadding(ByteBuffer bb, int tagLen, int blockSize, ProtocolVersion protocolVersion)2286 private static int removePadding(ByteBuffer bb, 2287 int tagLen, int blockSize, 2288 ProtocolVersion protocolVersion) throws BadPaddingException { 2289 int len = bb.remaining(); 2290 int offset = bb.position(); 2291 2292 // last byte is length byte (i.e. actual padding length - 1) 2293 int padOffset = offset + len - 1; 2294 int padLen = bb.get(padOffset) & 0xFF; 2295 2296 int newLen = len - (padLen + 1); 2297 if ((newLen - tagLen) < 0) { 2298 // If the buffer is not long enough to contain the padding plus 2299 // a MAC tag, do a dummy constant-time padding check. 2300 // 2301 // Note that it is a dummy check, so we won't care about what is 2302 // the actual padding data. 2303 checkPadding(bb.duplicate(), (byte)(padLen & 0xFF)); 2304 2305 throw new BadPaddingException("Invalid Padding length: " + padLen); 2306 } 2307 2308 // The padding data should be filled with the padding length value. 2309 int[] results = checkPadding( 2310 (ByteBuffer)(bb.duplicate()).position(offset + newLen), 2311 (byte)(padLen & 0xFF)); 2312 if (protocolVersion.useTLS10PlusSpec()) { 2313 if (results[0] != 0) { // padding data has invalid bytes 2314 throw new BadPaddingException("Invalid TLS padding data"); 2315 } 2316 } else { // SSLv3 2317 // SSLv3 requires 0 <= length byte < block size 2318 // some implementations do 1 <= length byte <= block size, 2319 // so accept that as well 2320 // v3 does not require any particular value for the other bytes 2321 if (padLen > blockSize) { 2322 throw new BadPaddingException("Padding length (" + 2323 padLen + ") of SSLv3 message should not be bigger " + 2324 "than the block size (" + blockSize + ")"); 2325 } 2326 } 2327 2328 // Reset buffer limit to remove padding. 2329 bb.limit(offset + newLen); 2330 2331 return newLen; 2332 } 2333 2334 /* 2335 * A constant-time check of the padding. 2336 * 2337 * NOTE that we are checking both the padding and the padLen bytes here. 2338 * 2339 * The caller MUST ensure that the bb parameter has remaining. 2340 */ checkPadding(ByteBuffer bb, byte pad)2341 private static int[] checkPadding(ByteBuffer bb, byte pad) { 2342 if (!bb.hasRemaining()) { 2343 throw new RuntimeException("hasRemaining() must be positive"); 2344 } 2345 2346 // An array of hits is used to prevent Hotspot optimization for 2347 // the purpose of a constant-time check. 2348 int[] results = {0, 0}; // {missed #, matched #} 2349 bb.mark(); 2350 for (int i = 0; i <= 256; bb.reset()) { 2351 for (; bb.hasRemaining() && i <= 256; i++) { 2352 if (bb.get() != pad) { 2353 results[0]++; // mismatched padding data 2354 } else { 2355 results[1]++; // matched padding data 2356 } 2357 } 2358 } 2359 2360 return results; 2361 } 2362 } 2363 2364