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