1 /* 2 * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.crypto.provider; 27 28 import java.util.Arrays; 29 import java.util.Locale; 30 31 import java.security.*; 32 import java.security.spec.*; 33 import javax.crypto.*; 34 import javax.crypto.spec.*; 35 import javax.crypto.BadPaddingException; 36 37 /** 38 * This class represents the symmetric algorithms in its various modes 39 * (<code>ECB</code>, <code>CFB</code>, <code>OFB</code>, <code>CBC</code>, 40 * <code>PCBC</code>, <code>CTR</code>, and <code>CTS</code>) and 41 * padding schemes (<code>PKCS5Padding</code>, <code>NoPadding</code>, 42 * <code>ISO10126Padding</code>). 43 * 44 * @author Gigi Ankeny 45 * @author Jan Luehe 46 * @see ElectronicCodeBook 47 * @see CipherFeedback 48 * @see OutputFeedback 49 * @see CipherBlockChaining 50 * @see PCBC 51 * @see CounterMode 52 * @see CipherTextStealing 53 */ 54 55 final class CipherCore { 56 57 /* 58 * internal buffer 59 */ 60 private byte[] buffer = null; 61 62 /* 63 * block size of cipher in bytes 64 */ 65 private int blockSize = 0; 66 67 /* 68 * unit size (number of input bytes that can be processed at a time) 69 */ 70 private int unitBytes = 0; 71 72 /* 73 * index of the content size left in the buffer 74 */ 75 private int buffered = 0; 76 77 /* 78 * minimum number of bytes in the buffer required for 79 * FeedbackCipher.encryptFinal()/decryptFinal() call. 80 * update() must buffer this many bytes before starting 81 * to encrypt/decrypt data. 82 * currently, only the following cases have non-zero values: 83 * 1) CTS mode - due to its special handling on the last two blocks 84 * (the last one may be incomplete). 85 * 2) GCM mode + decryption - due to its trailing tag bytes 86 */ 87 private int minBytes = 0; 88 89 /* 90 * number of bytes needed to make the total input length a multiple 91 * of the blocksize (this is used in feedback mode, when the number of 92 * input bytes that are processed at a time is different from the block 93 * size) 94 */ 95 private int diffBlocksize = 0; 96 97 /* 98 * padding class 99 */ 100 private Padding padding = null; 101 102 /* 103 * internal cipher engine 104 */ 105 private FeedbackCipher cipher = null; 106 107 /* 108 * the cipher mode 109 */ 110 private int cipherMode = ECB_MODE; 111 112 /* 113 * are we encrypting or decrypting? 114 */ 115 private boolean decrypting = false; 116 117 /* 118 * Block Mode constants 119 */ 120 private static final int ECB_MODE = 0; 121 private static final int CBC_MODE = 1; 122 private static final int CFB_MODE = 2; 123 private static final int OFB_MODE = 3; 124 private static final int PCBC_MODE = 4; 125 private static final int CTR_MODE = 5; 126 private static final int CTS_MODE = 6; 127 static final int GCM_MODE = 7; 128 129 /* 130 * variables used for performing the GCM (key+iv) uniqueness check. 131 * To use GCM mode safely, the cipher object must be re-initialized 132 * with a different combination of key + iv values for each 133 * encryption operation. However, checking all past key + iv values 134 * isn't feasible. Thus, we only do a per-instance check of the 135 * key + iv values used in previous encryption. 136 * For decryption operations, no checking is necessary. 137 * NOTE: this key+iv check have to be done inside CipherCore class 138 * since CipherCore class buffers potential tag bytes in GCM mode 139 * and may not call GaloisCounterMode when there isn't sufficient 140 * input to process. 141 */ 142 private boolean requireReinit = false; 143 private byte[] lastEncKey = null; 144 private byte[] lastEncIv = null; 145 146 /** 147 * Creates an instance of CipherCore with default ECB mode and 148 * PKCS5Padding. 149 */ 150 CipherCore(SymmetricCipher impl, int blkSize) { 151 blockSize = blkSize; 152 unitBytes = blkSize; 153 diffBlocksize = blkSize; 154 155 /* 156 * The buffer should be usable for all cipher mode and padding 157 * schemes. Thus, it has to be at least (blockSize+1) for CTS. 158 * In decryption mode, it also hold the possible padding block. 159 */ 160 buffer = new byte[blockSize*2]; 161 162 // set mode and padding 163 cipher = new ElectronicCodeBook(impl); 164 padding = new PKCS5Padding(blockSize); 165 } 166 167 /** 168 * Sets the mode of this cipher. 169 * 170 * @param mode the cipher mode 171 * 172 * @exception NoSuchAlgorithmException if the requested cipher mode does 173 * not exist for this cipher 174 */ 175 void setMode(String mode) throws NoSuchAlgorithmException { 176 if (mode == null) 177 throw new NoSuchAlgorithmException("null mode"); 178 179 String modeUpperCase = mode.toUpperCase(Locale.ENGLISH); 180 181 if (modeUpperCase.equals("ECB")) { 182 return; 183 } 184 185 SymmetricCipher rawImpl = cipher.getEmbeddedCipher(); 186 if (modeUpperCase.equals("CBC")) { 187 cipherMode = CBC_MODE; 188 cipher = new CipherBlockChaining(rawImpl); 189 } else if (modeUpperCase.equals("CTS")) { 190 cipherMode = CTS_MODE; 191 cipher = new CipherTextStealing(rawImpl); 192 minBytes = blockSize+1; 193 padding = null; 194 } else if (modeUpperCase.equals("CTR")) { 195 cipherMode = CTR_MODE; 196 cipher = new CounterMode(rawImpl); 197 unitBytes = 1; 198 padding = null; 199 } else if (modeUpperCase.equals("GCM")) { 200 // can only be used for block ciphers w/ 128-bit block size 201 if (blockSize != 16) { 202 throw new NoSuchAlgorithmException 203 ("GCM mode can only be used for AES cipher"); 204 } 205 cipherMode = GCM_MODE; 206 cipher = new GaloisCounterMode(rawImpl); 207 padding = null; 208 } else if (modeUpperCase.startsWith("CFB")) { 209 cipherMode = CFB_MODE; 210 unitBytes = getNumOfUnit(mode, "CFB".length(), blockSize); 211 cipher = new CipherFeedback(rawImpl, unitBytes); 212 } else if (modeUpperCase.startsWith("OFB")) { 213 cipherMode = OFB_MODE; 214 unitBytes = getNumOfUnit(mode, "OFB".length(), blockSize); 215 cipher = new OutputFeedback(rawImpl, unitBytes); 216 } else if (modeUpperCase.equals("PCBC")) { 217 cipherMode = PCBC_MODE; 218 cipher = new PCBC(rawImpl); 219 } 220 else { 221 throw new NoSuchAlgorithmException("Cipher mode: " + mode 222 + " not found"); 223 } 224 } 225 226 /** 227 * Returns the mode of this cipher. 228 * 229 * @return the parsed cipher mode 230 */ 231 int getMode() { 232 return cipherMode; 233 } 234 235 private static int getNumOfUnit(String mode, int offset, int blockSize) 236 throws NoSuchAlgorithmException { 237 int result = blockSize; // use blockSize as default value 238 if (mode.length() > offset) { 239 int numInt; 240 try { 241 Integer num = Integer.valueOf(mode.substring(offset)); 242 numInt = num.intValue(); 243 result = numInt >> 3; 244 } catch (NumberFormatException e) { 245 throw new NoSuchAlgorithmException 246 ("Algorithm mode: " + mode + " not implemented"); 247 } 248 if ((numInt % 8 != 0) || (result > blockSize)) { 249 throw new NoSuchAlgorithmException 250 ("Invalid algorithm mode: " + mode); 251 } 252 } 253 return result; 254 } 255 256 257 /** 258 * Sets the padding mechanism of this cipher. 259 * 260 * @param padding the padding mechanism 261 * 262 * @exception NoSuchPaddingException if the requested padding mechanism 263 * does not exist 264 */ 265 void setPadding(String paddingScheme) 266 throws NoSuchPaddingException 267 { 268 if (paddingScheme == null) { 269 throw new NoSuchPaddingException("null padding"); 270 } 271 if (paddingScheme.equalsIgnoreCase("NoPadding")) { 272 padding = null; 273 } else if (paddingScheme.equalsIgnoreCase("ISO10126Padding")) { 274 padding = new ISO10126Padding(blockSize); 275 } else if (!paddingScheme.equalsIgnoreCase("PKCS5Padding")) { 276 throw new NoSuchPaddingException("Padding: " + paddingScheme 277 + " not implemented"); 278 } 279 if ((padding != null) && 280 ((cipherMode == CTR_MODE) || (cipherMode == CTS_MODE) 281 || (cipherMode == GCM_MODE))) { 282 padding = null; 283 String modeStr = null; 284 switch (cipherMode) { 285 case CTR_MODE: 286 modeStr = "CTR"; 287 break; 288 case GCM_MODE: 289 modeStr = "GCM"; 290 break; 291 case CTS_MODE: 292 modeStr = "CTS"; 293 break; 294 default: 295 // should never happen 296 } 297 if (modeStr != null) { 298 throw new NoSuchPaddingException 299 (modeStr + " mode must be used with NoPadding"); 300 } 301 } 302 } 303 304 /** 305 * Returns the length in bytes that an output buffer would need to be in 306 * order to hold the result of the next <code>update</code> or 307 * <code>doFinal</code> operation, given the input length 308 * <code>inputLen</code> (in bytes). 309 * 310 * <p>This call takes into account any unprocessed (buffered) data from a 311 * previous <code>update</code> call, padding, and AEAD tagging. 312 * 313 * <p>The actual output length of the next <code>update</code> or 314 * <code>doFinal</code> call may be smaller than the length returned by 315 * this method. 316 * 317 * @param inputLen the input length (in bytes) 318 * 319 * @return the required output buffer size (in bytes) 320 */ 321 int getOutputSize(int inputLen) { 322 // estimate based on the maximum 323 return getOutputSizeByOperation(inputLen, true); 324 } 325 326 private int getOutputSizeByOperation(int inputLen, boolean isDoFinal) { 327 int totalLen = buffered + inputLen + cipher.getBufferedLength(); 328 switch (cipherMode) { 329 case GCM_MODE: 330 if (isDoFinal) { 331 int tagLen = ((GaloisCounterMode) cipher).getTagLen(); 332 if (!decrypting) { 333 totalLen += tagLen; 334 } else { 335 totalLen -= tagLen; 336 } 337 } 338 if (totalLen < 0) { 339 totalLen = 0; 340 } 341 break; 342 default: 343 if (padding != null && !decrypting) { 344 if (unitBytes != blockSize) { 345 if (totalLen < diffBlocksize) { 346 totalLen = diffBlocksize; 347 } else { 348 int residue = (totalLen - diffBlocksize) % blockSize; 349 totalLen += (blockSize - residue); 350 } 351 } else { 352 totalLen += padding.padLength(totalLen); 353 } 354 } 355 break; 356 } 357 return totalLen; 358 } 359 360 /** 361 * Returns the initialization vector (IV) in a new buffer. 362 * 363 * <p>This is useful in the case where a random IV has been created 364 * (see <a href = "#init">init</a>), 365 * or in the context of password-based encryption or 366 * decryption, where the IV is derived from a user-provided password. 367 * 368 * @return the initialization vector in a new buffer, or null if the 369 * underlying algorithm does not use an IV, or if the IV has not yet 370 * been set. 371 */ 372 byte[] getIV() { 373 byte[] iv = cipher.getIV(); 374 return (iv == null) ? null : iv.clone(); 375 } 376 377 /** 378 * Returns the parameters used with this cipher. 379 * 380 * <p>The returned parameters may be the same that were used to initialize 381 * this cipher, or may contain the default set of parameters or a set of 382 * randomly generated parameters used by the underlying cipher 383 * implementation (provided that the underlying cipher implementation 384 * uses a default set of parameters or creates new parameters if it needs 385 * parameters but was not initialized with any). 386 * 387 * @return the parameters used with this cipher, or null if this cipher 388 * does not use any parameters. 389 */ 390 AlgorithmParameters getParameters(String algName) { 391 if (cipherMode == ECB_MODE) { 392 return null; 393 } 394 AlgorithmParameters params = null; 395 AlgorithmParameterSpec spec; 396 byte[] iv = getIV(); 397 if (iv == null) { 398 // generate spec using default value 399 if (cipherMode == GCM_MODE) { 400 iv = new byte[GaloisCounterMode.DEFAULT_IV_LEN]; 401 } else { 402 iv = new byte[blockSize]; 403 } 404 SunJCE.getRandom().nextBytes(iv); 405 } 406 if (cipherMode == GCM_MODE) { 407 algName = "GCM"; 408 spec = new GCMParameterSpec 409 (((GaloisCounterMode) cipher).getTagLen()*8, iv); 410 } else { 411 if (algName.equals("RC2")) { 412 RC2Crypt rawImpl = (RC2Crypt) cipher.getEmbeddedCipher(); 413 spec = new RC2ParameterSpec 414 (rawImpl.getEffectiveKeyBits(), iv); 415 } else { 416 spec = new IvParameterSpec(iv); 417 } 418 } 419 try { 420 params = AlgorithmParameters.getInstance(algName, 421 SunJCE.getInstance()); 422 params.init(spec); 423 } catch (NoSuchAlgorithmException nsae) { 424 // should never happen 425 throw new RuntimeException("Cannot find " + algName + 426 " AlgorithmParameters implementation in SunJCE provider"); 427 } catch (InvalidParameterSpecException ipse) { 428 // should never happen 429 throw new RuntimeException(spec.getClass() + " not supported"); 430 } 431 return params; 432 } 433 434 /** 435 * Initializes this cipher with a key and a source of randomness. 436 * 437 * <p>The cipher is initialized for one of the following four operations: 438 * encryption, decryption, key wrapping or key unwrapping, depending on 439 * the value of <code>opmode</code>. 440 * 441 * <p>If this cipher requires an initialization vector (IV), it will get 442 * it from <code>random</code>. 443 * This behaviour should only be used in encryption or key wrapping 444 * mode, however. 445 * When initializing a cipher that requires an IV for decryption or 446 * key unwrapping, the IV 447 * (same IV that was used for encryption or key wrapping) must be provided 448 * explicitly as a 449 * parameter, in order to get the correct result. 450 * 451 * <p>This method also cleans existing buffer and other related state 452 * information. 453 * 454 * @param opmode the operation mode of this cipher (this is one of 455 * the following: 456 * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>, 457 * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>) 458 * @param key the secret key 459 * @param random the source of randomness 460 * 461 * @exception InvalidKeyException if the given key is inappropriate for 462 * initializing this cipher 463 */ 464 void init(int opmode, Key key, SecureRandom random) 465 throws InvalidKeyException { 466 try { 467 init(opmode, key, (AlgorithmParameterSpec)null, random); 468 } catch (InvalidAlgorithmParameterException e) { 469 throw new InvalidKeyException(e.getMessage()); 470 } 471 } 472 473 /** 474 * Initializes this cipher with a key, a set of 475 * algorithm parameters, and a source of randomness. 476 * 477 * <p>The cipher is initialized for one of the following four operations: 478 * encryption, decryption, key wrapping or key unwrapping, depending on 479 * the value of <code>opmode</code>. 480 * 481 * <p>If this cipher (including its underlying feedback or padding scheme) 482 * requires any random bytes, it will get them from <code>random</code>. 483 * 484 * @param opmode the operation mode of this cipher (this is one of 485 * the following: 486 * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>, 487 * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>) 488 * @param key the encryption key 489 * @param params the algorithm parameters 490 * @param random the source of randomness 491 * 492 * @exception InvalidKeyException if the given key is inappropriate for 493 * initializing this cipher 494 * @exception InvalidAlgorithmParameterException if the given algorithm 495 * parameters are inappropriate for this cipher 496 */ 497 void init(int opmode, Key key, AlgorithmParameterSpec params, 498 SecureRandom random) 499 throws InvalidKeyException, InvalidAlgorithmParameterException { 500 decrypting = (opmode == Cipher.DECRYPT_MODE) 501 || (opmode == Cipher.UNWRAP_MODE); 502 503 byte[] keyBytes = getKeyBytes(key); 504 int tagLen = -1; 505 byte[] ivBytes = null; 506 if (params != null) { 507 if (cipherMode == GCM_MODE) { 508 if (params instanceof GCMParameterSpec) { 509 tagLen = ((GCMParameterSpec)params).getTLen(); 510 if (tagLen < 96 || tagLen > 128 || ((tagLen & 0x07) != 0)) { 511 throw new InvalidAlgorithmParameterException 512 ("Unsupported TLen value; must be one of " + 513 "{128, 120, 112, 104, 96}"); 514 } 515 tagLen = tagLen >> 3; 516 ivBytes = ((GCMParameterSpec)params).getIV(); 517 } else { 518 throw new InvalidAlgorithmParameterException 519 ("Unsupported parameter: " + params); 520 } 521 } else { 522 if (params instanceof IvParameterSpec) { 523 ivBytes = ((IvParameterSpec)params).getIV(); 524 if ((ivBytes == null) || (ivBytes.length != blockSize)) { 525 throw new InvalidAlgorithmParameterException 526 ("Wrong IV length: must be " + blockSize + 527 " bytes long"); 528 } 529 } else if (params instanceof RC2ParameterSpec) { 530 ivBytes = ((RC2ParameterSpec)params).getIV(); 531 if ((ivBytes != null) && (ivBytes.length != blockSize)) { 532 throw new InvalidAlgorithmParameterException 533 ("Wrong IV length: must be " + blockSize + 534 " bytes long"); 535 } 536 } else { 537 throw new InvalidAlgorithmParameterException 538 ("Unsupported parameter: " + params); 539 } 540 } 541 } 542 if (cipherMode == ECB_MODE) { 543 if (ivBytes != null) { 544 throw new InvalidAlgorithmParameterException 545 ("ECB mode cannot use IV"); 546 } 547 } else if (ivBytes == null) { 548 if (decrypting) { 549 throw new InvalidAlgorithmParameterException("Parameters " 550 + "missing"); 551 } 552 553 if (random == null) { 554 random = SunJCE.getRandom(); 555 } 556 if (cipherMode == GCM_MODE) { 557 ivBytes = new byte[GaloisCounterMode.DEFAULT_IV_LEN]; 558 } else { 559 ivBytes = new byte[blockSize]; 560 } 561 random.nextBytes(ivBytes); 562 } 563 564 buffered = 0; 565 diffBlocksize = blockSize; 566 567 String algorithm = key.getAlgorithm(); 568 569 // GCM mode needs additional handling 570 if (cipherMode == GCM_MODE) { 571 if(tagLen == -1) { 572 tagLen = GaloisCounterMode.DEFAULT_TAG_LEN; 573 } 574 if (decrypting) { 575 minBytes = tagLen; 576 } else { 577 // check key+iv for encryption in GCM mode 578 requireReinit = 579 Arrays.equals(ivBytes, lastEncIv) && 580 MessageDigest.isEqual(keyBytes, lastEncKey); 581 if (requireReinit) { 582 throw new InvalidAlgorithmParameterException 583 ("Cannot reuse iv for GCM encryption"); 584 } 585 lastEncIv = ivBytes; 586 lastEncKey = keyBytes; 587 } 588 ((GaloisCounterMode) cipher).init 589 (decrypting, algorithm, keyBytes, ivBytes, tagLen); 590 } else { 591 cipher.init(decrypting, algorithm, keyBytes, ivBytes); 592 } 593 // skip checking key+iv from now on until after doFinal() 594 requireReinit = false; 595 } 596 597 void init(int opmode, Key key, AlgorithmParameters params, 598 SecureRandom random) 599 throws InvalidKeyException, InvalidAlgorithmParameterException { 600 AlgorithmParameterSpec spec = null; 601 String paramType = null; 602 if (params != null) { 603 try { 604 if (cipherMode == GCM_MODE) { 605 paramType = "GCM"; 606 spec = params.getParameterSpec(GCMParameterSpec.class); 607 } else { 608 // NOTE: RC2 parameters are always handled through 609 // init(..., AlgorithmParameterSpec,...) method, so 610 // we can assume IvParameterSpec type here. 611 paramType = "IV"; 612 spec = params.getParameterSpec(IvParameterSpec.class); 613 } 614 } catch (InvalidParameterSpecException ipse) { 615 throw new InvalidAlgorithmParameterException 616 ("Wrong parameter type: " + paramType + " expected"); 617 } 618 } 619 init(opmode, key, spec, random); 620 } 621 622 /** 623 * Return the key bytes of the specified key. Throw an InvalidKeyException 624 * if the key is not usable. 625 */ 626 static byte[] getKeyBytes(Key key) throws InvalidKeyException { 627 if (key == null) { 628 throw new InvalidKeyException("No key given"); 629 } 630 // note: key.getFormat() may return null 631 if (!"RAW".equalsIgnoreCase(key.getFormat())) { 632 throw new InvalidKeyException("Wrong format: RAW bytes needed"); 633 } 634 byte[] keyBytes = key.getEncoded(); 635 if (keyBytes == null) { 636 throw new InvalidKeyException("RAW key bytes missing"); 637 } 638 return keyBytes; 639 } 640 641 642 /** 643 * Continues a multiple-part encryption or decryption operation 644 * (depending on how this cipher was initialized), processing another data 645 * part. 646 * 647 * <p>The first <code>inputLen</code> bytes in the <code>input</code> 648 * buffer, starting at <code>inputOffset</code>, are processed, and the 649 * result is stored in a new buffer. 650 * 651 * @param input the input buffer 652 * @param inputOffset the offset in <code>input</code> where the input 653 * starts 654 * @param inputLen the input length 655 * 656 * @return the new buffer with the result 657 * 658 * @exception IllegalStateException if this cipher is in a wrong state 659 * (e.g., has not been initialized) 660 */ 661 byte[] update(byte[] input, int inputOffset, int inputLen) { 662 if (requireReinit) { 663 throw new IllegalStateException 664 ("Must use either different key or iv for GCM encryption"); 665 } 666 667 byte[] output = null; 668 try { 669 output = new byte[getOutputSizeByOperation(inputLen, false)]; 670 int len = update(input, inputOffset, inputLen, output, 671 0); 672 if (len == output.length) { 673 return output; 674 } else { 675 return Arrays.copyOf(output, len); 676 } 677 } catch (ShortBufferException e) { 678 // should never happen 679 throw new ProviderException("Unexpected exception", e); 680 } 681 } 682 683 /** 684 * Continues a multiple-part encryption or decryption operation 685 * (depending on how this cipher was initialized), processing another data 686 * part. 687 * 688 * <p>The first <code>inputLen</code> bytes in the <code>input</code> 689 * buffer, starting at <code>inputOffset</code>, are processed, and the 690 * result is stored in the <code>output</code> buffer, starting at 691 * <code>outputOffset</code>. 692 * 693 * @param input the input buffer 694 * @param inputOffset the offset in <code>input</code> where the input 695 * starts 696 * @param inputLen the input length 697 * @param output the buffer for the result 698 * @param outputOffset the offset in <code>output</code> where the result 699 * is stored 700 * 701 * @return the number of bytes stored in <code>output</code> 702 * 703 * @exception ShortBufferException if the given output buffer is too small 704 * to hold the result 705 */ 706 int update(byte[] input, int inputOffset, int inputLen, byte[] output, 707 int outputOffset) throws ShortBufferException { 708 if (requireReinit) { 709 throw new IllegalStateException 710 ("Must use either different key or iv for GCM encryption"); 711 } 712 713 // figure out how much can be sent to crypto function 714 int len = buffered + inputLen - minBytes; 715 if (padding != null && decrypting) { 716 // do not include the padding bytes when decrypting 717 len -= blockSize; 718 } 719 // do not count the trailing bytes which do not make up a unit 720 len = (len > 0 ? (len - (len % unitBytes)) : 0); 721 722 // check output buffer capacity 723 if ((output == null) || 724 ((output.length - outputOffset) < len)) { 725 throw new ShortBufferException("Output buffer must be " 726 + "(at least) " + len 727 + " bytes long"); 728 } 729 730 int outLen = 0; 731 if (len != 0) { // there is some work to do 732 if ((input == output) 733 && (outputOffset < (inputOffset + inputLen)) 734 && (inputOffset < (outputOffset + buffer.length))) { 735 // copy 'input' out to avoid its content being 736 // overwritten prematurely. 737 input = Arrays.copyOfRange(input, inputOffset, 738 inputOffset + inputLen); 739 inputOffset = 0; 740 } 741 if (len <= buffered) { 742 // all to-be-processed data are from 'buffer' 743 if (decrypting) { 744 outLen = cipher.decrypt(buffer, 0, len, output, outputOffset); 745 } else { 746 outLen = cipher.encrypt(buffer, 0, len, output, outputOffset); 747 } 748 buffered -= len; 749 if (buffered != 0) { 750 System.arraycopy(buffer, len, buffer, 0, buffered); 751 } 752 } else { // len > buffered 753 int inputConsumed = len - buffered; 754 int temp; 755 if (buffered > 0) { 756 int bufferCapacity = buffer.length - buffered; 757 if (bufferCapacity != 0) { 758 temp = Math.min(bufferCapacity, inputConsumed); 759 if (unitBytes != blockSize) { 760 temp -= ((buffered + temp) % unitBytes); 761 } 762 System.arraycopy(input, inputOffset, buffer, buffered, temp); 763 inputOffset += temp; 764 inputConsumed -= temp; 765 inputLen -= temp; 766 buffered += temp; 767 } 768 // process 'buffer' 769 if (decrypting) { 770 outLen = cipher.decrypt(buffer, 0, buffered, output, outputOffset); 771 } else { 772 outLen = cipher.encrypt(buffer, 0, buffered, output, outputOffset); 773 } 774 outputOffset += outLen; 775 buffered = 0; 776 } 777 if (inputConsumed > 0) { // still has input to process 778 if (decrypting) { 779 outLen += cipher.decrypt(input, inputOffset, inputConsumed, 780 output, outputOffset); 781 } else { 782 outLen += cipher.encrypt(input, inputOffset, inputConsumed, 783 output, outputOffset); 784 } 785 inputOffset += inputConsumed; 786 inputLen -= inputConsumed; 787 } 788 } 789 // Let's keep track of how many bytes are needed to make 790 // the total input length a multiple of blocksize when 791 // padding is applied 792 if (unitBytes != blockSize) { 793 if (len < diffBlocksize) { 794 diffBlocksize -= len; 795 } else { 796 diffBlocksize = blockSize - 797 ((len - diffBlocksize) % blockSize); 798 } 799 } 800 } 801 // Store remaining input into 'buffer' again 802 if (inputLen > 0) { 803 System.arraycopy(input, inputOffset, buffer, buffered, 804 inputLen); 805 buffered += inputLen; 806 } 807 return outLen; 808 } 809 810 /** 811 * Encrypts or decrypts data in a single-part operation, 812 * or finishes a multiple-part operation. 813 * The data is encrypted or decrypted, depending on how this cipher was 814 * initialized. 815 * 816 * <p>The first <code>inputLen</code> bytes in the <code>input</code> 817 * buffer, starting at <code>inputOffset</code>, and any input bytes that 818 * may have been buffered during a previous <code>update</code> operation, 819 * are processed, with padding (if requested) being applied. 820 * The result is stored in a new buffer. 821 * 822 * <p>The cipher is reset to its initial state (uninitialized) after this 823 * call. 824 * 825 * @param input the input buffer 826 * @param inputOffset the offset in <code>input</code> where the input 827 * starts 828 * @param inputLen the input length 829 * 830 * @return the new buffer with the result 831 * 832 * @exception IllegalBlockSizeException if this cipher is a block cipher, 833 * no padding has been requested (only in encryption mode), and the total 834 * input length of the data processed by this cipher is not a multiple of 835 * block size 836 * @exception BadPaddingException if this cipher is in decryption mode, 837 * and (un)padding has been requested, but the decrypted data is not 838 * bounded by the appropriate padding bytes 839 */ 840 byte[] doFinal(byte[] input, int inputOffset, int inputLen) 841 throws IllegalBlockSizeException, BadPaddingException { 842 byte[] output = null; 843 try { 844 output = new byte[getOutputSizeByOperation(inputLen, true)]; 845 int len = doFinal(input, inputOffset, inputLen, output, 0); 846 if (len < output.length) { 847 return Arrays.copyOf(output, len); 848 } else { 849 return output; 850 } 851 } catch (ShortBufferException e) { 852 // never thrown 853 throw new ProviderException("Unexpected exception", e); 854 } 855 } 856 857 /** 858 * Encrypts or decrypts data in a single-part operation, 859 * or finishes a multiple-part operation. 860 * The data is encrypted or decrypted, depending on how this cipher was 861 * initialized. 862 * 863 * <p>The first <code>inputLen</code> bytes in the <code>input</code> 864 * buffer, starting at <code>inputOffset</code>, and any input bytes that 865 * may have been buffered during a previous <code>update</code> operation, 866 * are processed, with padding (if requested) being applied. 867 * The result is stored in the <code>output</code> buffer, starting at 868 * <code>outputOffset</code>. 869 * 870 * <p>The cipher is reset to its initial state (uninitialized) after this 871 * call. 872 * 873 * @param input the input buffer 874 * @param inputOffset the offset in <code>input</code> where the input 875 * starts 876 * @param inputLen the input length 877 * @param output the buffer for the result 878 * @param outputOffset the offset in <code>output</code> where the result 879 * is stored 880 * 881 * @return the number of bytes stored in <code>output</code> 882 * 883 * @exception IllegalBlockSizeException if this cipher is a block cipher, 884 * no padding has been requested (only in encryption mode), and the total 885 * input length of the data processed by this cipher is not a multiple of 886 * block size 887 * @exception ShortBufferException if the given output buffer is too small 888 * to hold the result 889 * @exception BadPaddingException if this cipher is in decryption mode, 890 * and (un)padding has been requested, but the decrypted data is not 891 * bounded by the appropriate padding bytes 892 */ 893 int doFinal(byte[] input, int inputOffset, int inputLen, byte[] output, 894 int outputOffset) 895 throws IllegalBlockSizeException, ShortBufferException, 896 BadPaddingException { 897 if (requireReinit) { 898 throw new IllegalStateException 899 ("Must use either different key or iv for GCM encryption"); 900 } 901 902 int estOutSize = getOutputSizeByOperation(inputLen, true); 903 // check output buffer capacity. 904 // if we are decrypting with padding applied, we can perform this 905 // check only after we have determined how many padding bytes there 906 // are. 907 int outputCapacity = output.length - outputOffset; 908 int minOutSize = (decrypting? (estOutSize - blockSize):estOutSize); 909 if ((output == null) || (outputCapacity < minOutSize)) { 910 throw new ShortBufferException("Output buffer must be " 911 + "(at least) " + minOutSize + " bytes long"); 912 } 913 914 // calculate total input length 915 int len = buffered + inputLen; 916 917 // calculate padding length 918 int totalLen = len + cipher.getBufferedLength(); 919 int paddingLen = 0; 920 // will the total input length be a multiple of blockSize? 921 if (unitBytes != blockSize) { 922 if (totalLen < diffBlocksize) { 923 paddingLen = diffBlocksize - totalLen; 924 } else { 925 paddingLen = blockSize - 926 ((totalLen - diffBlocksize) % blockSize); 927 } 928 } else if (padding != null) { 929 paddingLen = padding.padLength(totalLen); 930 } 931 932 if (decrypting && (padding != null) && 933 (paddingLen > 0) && (paddingLen != blockSize)) { 934 throw new IllegalBlockSizeException 935 ("Input length must be multiple of " + blockSize + 936 " when decrypting with padded cipher"); 937 } 938 939 /* 940 * prepare the final input, assemble a new buffer if any 941 * of the following is true: 942 * - 'input' and 'output' are the same buffer 943 * - there are internally buffered bytes 944 * - doing encryption and padding is needed 945 */ 946 byte[] finalBuf = input; 947 int finalOffset = inputOffset; 948 int finalBufLen = inputLen; 949 if ((buffered != 0) || (!decrypting && padding != null) || 950 ((input == output) 951 && (outputOffset < (inputOffset + inputLen)) 952 && (inputOffset < (outputOffset + buffer.length)))) { 953 if (decrypting || padding == null) { 954 paddingLen = 0; 955 } 956 finalBuf = new byte[len + paddingLen]; 957 finalOffset = 0; 958 if (buffered != 0) { 959 System.arraycopy(buffer, 0, finalBuf, 0, buffered); 960 } 961 if (inputLen != 0) { 962 System.arraycopy(input, inputOffset, finalBuf, 963 buffered, inputLen); 964 } 965 if (paddingLen != 0) { 966 padding.padWithLen(finalBuf, (buffered+inputLen), paddingLen); 967 } 968 finalBufLen = finalBuf.length; 969 } 970 int outLen = 0; 971 if (decrypting) { 972 // if the size of specified output buffer is less than 973 // the length of the cipher text, then the current 974 // content of cipher has to be preserved in order for 975 // users to retry the call with a larger buffer in the 976 // case of ShortBufferException. 977 if (outputCapacity < estOutSize) { 978 cipher.save(); 979 } 980 // create temporary output buffer so that only "real" 981 // data bytes are passed to user's output buffer. 982 byte[] outWithPadding = new byte[estOutSize]; 983 outLen = finalNoPadding(finalBuf, finalOffset, outWithPadding, 984 0, finalBufLen); 985 986 if (padding != null) { 987 int padStart = padding.unpad(outWithPadding, 0, outLen); 988 if (padStart < 0) { 989 throw new BadPaddingException("Given final block not " 990 + "properly padded"); 991 } 992 outLen = padStart; 993 } 994 995 if (outputCapacity < outLen) { 996 // restore so users can retry with a larger buffer 997 cipher.restore(); 998 throw new ShortBufferException("Output buffer too short: " 999 + (outputCapacity) 1000 + " bytes given, " + outLen 1001 + " bytes needed"); 1002 } 1003 // copy the result into user-supplied output buffer 1004 System.arraycopy(outWithPadding, 0, output, outputOffset, outLen); 1005 } else { // encrypting 1006 try { 1007 outLen = finalNoPadding(finalBuf, finalOffset, output, 1008 outputOffset, finalBufLen); 1009 } finally { 1010 // reset after doFinal() for GCM encryption 1011 requireReinit = (cipherMode == GCM_MODE); 1012 } 1013 } 1014 1015 buffered = 0; 1016 diffBlocksize = blockSize; 1017 if (cipherMode != ECB_MODE) { 1018 cipher.reset(); 1019 } 1020 return outLen; 1021 } 1022 1023 private int finalNoPadding(byte[] in, int inOfs, byte[] out, int outOfs, 1024 int len) 1025 throws IllegalBlockSizeException, AEADBadTagException, 1026 ShortBufferException { 1027 1028 if ((cipherMode != GCM_MODE) && (in == null || len == 0)) { 1029 return 0; 1030 } 1031 if ((cipherMode != CFB_MODE) && (cipherMode != OFB_MODE) && 1032 (cipherMode != GCM_MODE) && 1033 ((len % unitBytes) != 0) && (cipherMode != CTS_MODE)) { 1034 if (padding != null) { 1035 throw new IllegalBlockSizeException 1036 ("Input length (with padding) not multiple of " + 1037 unitBytes + " bytes"); 1038 } else { 1039 throw new IllegalBlockSizeException 1040 ("Input length not multiple of " + unitBytes 1041 + " bytes"); 1042 } 1043 } 1044 int outLen = 0; 1045 if (decrypting) { 1046 outLen = cipher.decryptFinal(in, inOfs, len, out, outOfs); 1047 } else { 1048 outLen = cipher.encryptFinal(in, inOfs, len, out, outOfs); 1049 } 1050 return outLen; 1051 } 1052 1053 // Note: Wrap() and Unwrap() are the same in 1054 // each of SunJCE CipherSpi implementation classes. 1055 // They are duplicated due to export control requirements: 1056 // All CipherSpi implementation must be final. 1057 /** 1058 * Wrap a key. 1059 * 1060 * @param key the key to be wrapped. 1061 * 1062 * @return the wrapped key. 1063 * 1064 * @exception IllegalBlockSizeException if this cipher is a block 1065 * cipher, no padding has been requested, and the length of the 1066 * encoding of the key to be wrapped is not a 1067 * multiple of the block size. 1068 * 1069 * @exception InvalidKeyException if it is impossible or unsafe to 1070 * wrap the key with this cipher (e.g., a hardware protected key is 1071 * being passed to a software only cipher). 1072 */ 1073 byte[] wrap(Key key) 1074 throws IllegalBlockSizeException, InvalidKeyException { 1075 byte[] result = null; 1076 1077 try { 1078 byte[] encodedKey = key.getEncoded(); 1079 if ((encodedKey == null) || (encodedKey.length == 0)) { 1080 throw new InvalidKeyException("Cannot get an encoding of " + 1081 "the key to be wrapped"); 1082 } 1083 result = doFinal(encodedKey, 0, encodedKey.length); 1084 } catch (BadPaddingException e) { 1085 // Should never happen 1086 } 1087 return result; 1088 } 1089 1090 /** 1091 * Unwrap a previously wrapped key. 1092 * 1093 * @param wrappedKey the key to be unwrapped. 1094 * 1095 * @param wrappedKeyAlgorithm the algorithm the wrapped key is for. 1096 * 1097 * @param wrappedKeyType the type of the wrapped key. 1098 * This is one of <code>Cipher.SECRET_KEY</code>, 1099 * <code>Cipher.PRIVATE_KEY</code>, or <code>Cipher.PUBLIC_KEY</code>. 1100 * 1101 * @return the unwrapped key. 1102 * 1103 * @exception NoSuchAlgorithmException if no installed providers 1104 * can create keys of type <code>wrappedKeyType</code> for the 1105 * <code>wrappedKeyAlgorithm</code>. 1106 * 1107 * @exception InvalidKeyException if <code>wrappedKey</code> does not 1108 * represent a wrapped key of type <code>wrappedKeyType</code> for 1109 * the <code>wrappedKeyAlgorithm</code>. 1110 */ 1111 Key unwrap(byte[] wrappedKey, String wrappedKeyAlgorithm, 1112 int wrappedKeyType) 1113 throws InvalidKeyException, NoSuchAlgorithmException { 1114 byte[] encodedKey; 1115 try { 1116 encodedKey = doFinal(wrappedKey, 0, wrappedKey.length); 1117 } catch (BadPaddingException ePadding) { 1118 throw new InvalidKeyException("The wrapped key is not padded " + 1119 "correctly"); 1120 } catch (IllegalBlockSizeException eBlockSize) { 1121 throw new InvalidKeyException("The wrapped key does not have " + 1122 "the correct length"); 1123 } 1124 return ConstructKeys.constructKey(encodedKey, wrappedKeyAlgorithm, 1125 wrappedKeyType); 1126 } 1127 1128 /** 1129 * Continues a multi-part update of the Additional Authentication 1130 * Data (AAD), using a subset of the provided buffer. 1131 * <p> 1132 * Calls to this method provide AAD to the cipher when operating in 1133 * modes such as AEAD (GCM/CCM). If this cipher is operating in 1134 * either GCM or CCM mode, all AAD must be supplied before beginning 1135 * operations on the ciphertext (via the {@code update} and {@code 1136 * doFinal} methods). 1137 * 1138 * @param src the buffer containing the AAD 1139 * @param offset the offset in {@code src} where the AAD input starts 1140 * @param len the number of AAD bytes 1141 * 1142 * @throws IllegalStateException if this cipher is in a wrong state 1143 * (e.g., has not been initialized), does not accept AAD, or if 1144 * operating in either GCM or CCM mode and one of the {@code update} 1145 * methods has already been called for the active 1146 * encryption/decryption operation 1147 * @throws UnsupportedOperationException if this method 1148 * has not been overridden by an implementation 1149 * 1150 * @since 1.8 1151 */ 1152 void updateAAD(byte[] src, int offset, int len) { 1153 if (requireReinit) { 1154 throw new IllegalStateException 1155 ("Must use either different key or iv for GCM encryption"); 1156 } 1157 cipher.updateAAD(src, offset, len); 1158 } 1159 }