1 /*
   2  * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.crypto.provider;
  27 
  28 import java.util.Arrays;
  29 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      * Sets the padding mechanism of this cipher.
 258      *
 259      * @param paddingScheme the padding mechanism
 260      *
 261      * @exception NoSuchPaddingException if the requested padding mechanism
 262      * does not exist
 263      */
 264     void setPadding(String paddingScheme)
 265         throws NoSuchPaddingException
 266     {
 267         if (paddingScheme == null) {
 268             throw new NoSuchPaddingException("null padding");
 269         }
 270         if (paddingScheme.equalsIgnoreCase("NoPadding")) {
 271             padding = null;
 272         } else if (paddingScheme.equalsIgnoreCase("ISO10126Padding")) {
 273             padding = new ISO10126Padding(blockSize);
 274         } else if (paddingScheme.equalsIgnoreCase("PKCS5Padding")) {
 275             padding = new PKCS5Padding(blockSize);
 276         } else {
 277             throw new NoSuchPaddingException("Padding: " + paddingScheme
 278                                              + " not implemented");
 279         }
 280         if ((padding != null) &&
 281             ((cipherMode == CTR_MODE) || (cipherMode == CTS_MODE)
 282              || (cipherMode == GCM_MODE))) {
 283             padding = null;
 284             String modeStr = null;
 285             switch (cipherMode) {
 286             case CTR_MODE:
 287                 modeStr = "CTR";
 288                 break;
 289             case GCM_MODE:
 290                 modeStr = "GCM";
 291                 break;
 292             case CTS_MODE:
 293                 modeStr = "CTS";
 294                 break;
 295             default:
 296                 // should never happen
 297             }
 298             if (modeStr != null) {
 299                 throw new NoSuchPaddingException
 300                     (modeStr + " mode must be used with NoPadding");
 301             }
 302         }
 303     }
 304 
 305     /**
 306      * Returns the length in bytes that an output buffer would need to be in
 307      * order to hold the result of the next <code>update</code> or
 308      * <code>doFinal</code> operation, given the input length
 309      * <code>inputLen</code> (in bytes).
 310      *
 311      * <p>This call takes into account any unprocessed (buffered) data from a
 312      * previous <code>update</code> call, padding, and AEAD tagging.
 313      *
 314      * <p>The actual output length of the next <code>update</code> or
 315      * <code>doFinal</code> call may be smaller than the length returned by
 316      * this method.
 317      *
 318      * @param inputLen the input length (in bytes)
 319      *
 320      * @return the required output buffer size (in bytes)
 321      */
 322     int getOutputSize(int inputLen) {
 323         // estimate based on the maximum
 324         return getOutputSizeByOperation(inputLen, true);
 325     }
 326 
 327     private int getOutputSizeByOperation(int inputLen, boolean isDoFinal) {
 328         int totalLen = Math.addExact(buffered, cipher.getBufferedLength());
 329         totalLen = Math.addExact(totalLen, inputLen);
 330         switch (cipherMode) {
 331         case GCM_MODE:
 332             if (isDoFinal) {
 333                 int tagLen = ((GaloisCounterMode) cipher).getTagLen();
 334                 if (!decrypting) {
 335                     totalLen = Math.addExact(totalLen, tagLen);
 336                 } else {
 337                     totalLen -= tagLen;
 338                 }
 339             }
 340             if (totalLen < 0) {
 341                 totalLen = 0;
 342             }
 343             break;
 344         default:
 345             if (padding != null && !decrypting) {
 346                 if (unitBytes != blockSize) {
 347                     if (totalLen < diffBlocksize) {
 348                         totalLen = diffBlocksize;
 349                     } else {
 350                         int residue = (totalLen - diffBlocksize) % blockSize;
 351                         totalLen = Math.addExact(totalLen, (blockSize - residue));
 352                     }
 353                 } else {
 354                     totalLen = Math.addExact(totalLen, padding.padLength(totalLen));
 355                 }
 356             }
 357             break;
 358         }
 359         return totalLen;
 360     }
 361 
 362     /**
 363      * Returns the initialization vector (IV) in a new buffer.
 364      *
 365      * <p>This is useful in the case where a random IV has been created
 366      * (see <a href = "#init">init</a>),
 367      * or in the context of password-based encryption or
 368      * decryption, where the IV is derived from a user-provided password.
 369      *
 370      * @return the initialization vector in a new buffer, or null if the
 371      * underlying algorithm does not use an IV, or if the IV has not yet
 372      * been set.
 373      */
 374     byte[] getIV() {
 375         byte[] iv = cipher.getIV();
 376         return (iv == null) ? null : iv.clone();
 377     }
 378 
 379     /**
 380      * Returns the parameters used with this cipher.
 381      *
 382      * <p>The returned parameters may be the same that were used to initialize
 383      * this cipher, or may contain the default set of parameters or a set of
 384      * randomly generated parameters used by the underlying cipher
 385      * implementation (provided that the underlying cipher implementation
 386      * uses a default set of parameters or creates new parameters if it needs
 387      * parameters but was not initialized with any).
 388      *
 389      * @return the parameters used with this cipher, or null if this cipher
 390      * does not use any parameters.
 391      */
 392     AlgorithmParameters getParameters(String algName) {
 393         if (cipherMode == ECB_MODE) {
 394             return null;
 395         }
 396         AlgorithmParameters params = null;
 397         AlgorithmParameterSpec spec;
 398         byte[] iv = getIV();
 399         if (iv == null) {
 400             // generate spec using default value
 401             if (cipherMode == GCM_MODE) {
 402                 iv = new byte[GaloisCounterMode.DEFAULT_IV_LEN];
 403             } else {
 404                 iv = new byte[blockSize];
 405             }
 406             SunJCE.getRandom().nextBytes(iv);
 407         }
 408         if (cipherMode == GCM_MODE) {
 409             algName = "GCM";
 410             spec = new GCMParameterSpec
 411                 (((GaloisCounterMode) cipher).getTagLen()*8, iv);
 412         } else {
 413            if (algName.equals("RC2")) {
 414                RC2Crypt rawImpl = (RC2Crypt) cipher.getEmbeddedCipher();
 415                spec = new RC2ParameterSpec
 416                    (rawImpl.getEffectiveKeyBits(), iv);
 417            } else {
 418                spec = new IvParameterSpec(iv);
 419            }
 420         }
 421         try {
 422             params = AlgorithmParameters.getInstance(algName,
 423                     SunJCE.getInstance());
 424             params.init(spec);
 425         } catch (NoSuchAlgorithmException nsae) {
 426             // should never happen
 427             throw new RuntimeException("Cannot find " + algName +
 428                 " AlgorithmParameters implementation in SunJCE provider");
 429         } catch (InvalidParameterSpecException ipse) {
 430             // should never happen
 431             throw new RuntimeException(spec.getClass() + " not supported");
 432         }
 433         return params;
 434     }
 435 
 436     /**
 437      * Initializes this cipher with a key and a source of randomness.
 438      *
 439      * <p>The cipher is initialized for one of the following four operations:
 440      * encryption, decryption, key wrapping or key unwrapping, depending on
 441      * the value of <code>opmode</code>.
 442      *
 443      * <p>If this cipher requires an initialization vector (IV), it will get
 444      * it from <code>random</code>.
 445      * This behaviour should only be used in encryption or key wrapping
 446      * mode, however.
 447      * When initializing a cipher that requires an IV for decryption or
 448      * key unwrapping, the IV
 449      * (same IV that was used for encryption or key wrapping) must be provided
 450      * explicitly as a
 451      * parameter, in order to get the correct result.
 452      *
 453      * <p>This method also cleans existing buffer and other related state
 454      * information.
 455      *
 456      * @param opmode the operation mode of this cipher (this is one of
 457      * the following:
 458      * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
 459      * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
 460      * @param key the secret key
 461      * @param random the source of randomness
 462      *
 463      * @exception InvalidKeyException if the given key is inappropriate for
 464      * initializing this cipher
 465      */
 466     void init(int opmode, Key key, SecureRandom random)
 467             throws InvalidKeyException {
 468         try {
 469             init(opmode, key, (AlgorithmParameterSpec)null, random);
 470         } catch (InvalidAlgorithmParameterException e) {
 471             throw new InvalidKeyException(e.getMessage());
 472         }
 473     }
 474 
 475     /**
 476      * Initializes this cipher with a key, a set of
 477      * algorithm parameters, and a source of randomness.
 478      *
 479      * <p>The cipher is initialized for one of the following four operations:
 480      * encryption, decryption, key wrapping or key unwrapping, depending on
 481      * the value of <code>opmode</code>.
 482      *
 483      * <p>If this cipher (including its underlying feedback or padding scheme)
 484      * requires any random bytes, it will get them from <code>random</code>.
 485      *
 486      * @param opmode the operation mode of this cipher (this is one of
 487      * the following:
 488      * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
 489      * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
 490      * @param key the encryption key
 491      * @param params the algorithm parameters
 492      * @param random the source of randomness
 493      *
 494      * @exception InvalidKeyException if the given key is inappropriate for
 495      * initializing this cipher
 496      * @exception InvalidAlgorithmParameterException if the given algorithm
 497      * parameters are inappropriate for this cipher
 498      */
 499     void init(int opmode, Key key, AlgorithmParameterSpec params,
 500             SecureRandom random)
 501             throws InvalidKeyException, InvalidAlgorithmParameterException {
 502         decrypting = (opmode == Cipher.DECRYPT_MODE)
 503                   || (opmode == Cipher.UNWRAP_MODE);
 504 
 505         byte[] keyBytes = getKeyBytes(key);
 506         int tagLen = -1;
 507         byte[] ivBytes = null;
 508         if (params != null) {
 509             if (cipherMode == GCM_MODE) {
 510                 if (params instanceof GCMParameterSpec) {
 511                     tagLen = ((GCMParameterSpec)params).getTLen();
 512                     if (tagLen < 96 || tagLen > 128 || ((tagLen & 0x07) != 0)) {
 513                         throw new InvalidAlgorithmParameterException
 514                             ("Unsupported TLen value; must be one of " +
 515                              "{128, 120, 112, 104, 96}");
 516                     }
 517                     tagLen = tagLen >> 3;
 518                     ivBytes = ((GCMParameterSpec)params).getIV();
 519                 } else {
 520                     throw new InvalidAlgorithmParameterException
 521                         ("Unsupported parameter: " + params);
 522                }
 523             } else {
 524                 if (params instanceof IvParameterSpec) {
 525                     ivBytes = ((IvParameterSpec)params).getIV();
 526                     if ((ivBytes == null) || (ivBytes.length != blockSize)) {
 527                         throw new InvalidAlgorithmParameterException
 528                             ("Wrong IV length: must be " + blockSize +
 529                              " bytes long");
 530                     }
 531                 } else if (params instanceof RC2ParameterSpec) {
 532                     ivBytes = ((RC2ParameterSpec)params).getIV();
 533                     if ((ivBytes != null) && (ivBytes.length != blockSize)) {
 534                         throw new InvalidAlgorithmParameterException
 535                             ("Wrong IV length: must be " + blockSize +
 536                              " bytes long");
 537                     }
 538                 } else {
 539                     throw new InvalidAlgorithmParameterException
 540                         ("Unsupported parameter: " + params);
 541                 }
 542             }
 543         }
 544         if (cipherMode == ECB_MODE) {
 545             if (ivBytes != null) {
 546                 throw new InvalidAlgorithmParameterException
 547                                                 ("ECB mode cannot use IV");
 548             }
 549         } else if (ivBytes == null)  {
 550             if (decrypting) {
 551                 throw new InvalidAlgorithmParameterException("Parameters "
 552                                                              + "missing");
 553             }
 554 
 555             if (random == null) {
 556                 random = SunJCE.getRandom();
 557             }
 558             if (cipherMode == GCM_MODE) {
 559                 ivBytes = new byte[GaloisCounterMode.DEFAULT_IV_LEN];
 560             } else {
 561                 ivBytes = new byte[blockSize];
 562             }
 563             random.nextBytes(ivBytes);
 564         }
 565 
 566         buffered = 0;
 567         diffBlocksize = blockSize;
 568 
 569         String algorithm = key.getAlgorithm();
 570 
 571         // GCM mode needs additional handling
 572         if (cipherMode == GCM_MODE) {
 573             if(tagLen == -1) {
 574                 tagLen = GaloisCounterMode.DEFAULT_TAG_LEN;
 575             }
 576             if (decrypting) {
 577                 minBytes = tagLen;
 578             } else {
 579                 // check key+iv for encryption in GCM mode
 580                 requireReinit =
 581                     Arrays.equals(ivBytes, lastEncIv) &&
 582                     MessageDigest.isEqual(keyBytes, lastEncKey);
 583                 if (requireReinit) {
 584                     throw new InvalidAlgorithmParameterException
 585                         ("Cannot reuse iv for GCM encryption");
 586                 }
 587                 lastEncIv = ivBytes;
 588                 lastEncKey = keyBytes;
 589             }
 590             ((GaloisCounterMode) cipher).init
 591                 (decrypting, algorithm, keyBytes, ivBytes, tagLen);
 592         } else {
 593             cipher.init(decrypting, algorithm, keyBytes, ivBytes);
 594         }
 595         // skip checking key+iv from now on until after doFinal()
 596         requireReinit = false;
 597     }
 598 
 599     void init(int opmode, Key key, AlgorithmParameters params,
 600               SecureRandom random)
 601         throws InvalidKeyException, InvalidAlgorithmParameterException {
 602         AlgorithmParameterSpec spec = null;
 603         String paramType = null;
 604         if (params != null) {
 605             try {
 606                 if (cipherMode == GCM_MODE) {
 607                     paramType = "GCM";
 608                     spec = params.getParameterSpec(GCMParameterSpec.class);
 609                 } else {
 610                     // NOTE: RC2 parameters are always handled through
 611                     // init(..., AlgorithmParameterSpec,...) method, so
 612                     // we can assume IvParameterSpec type here.
 613                     paramType = "IV";
 614                     spec = params.getParameterSpec(IvParameterSpec.class);
 615                 }
 616             } catch (InvalidParameterSpecException ipse) {
 617                 throw new InvalidAlgorithmParameterException
 618                     ("Wrong parameter type: " + paramType + " expected");
 619             }
 620         }
 621         init(opmode, key, spec, random);
 622     }
 623 
 624     /**
 625      * Return the key bytes of the specified key. Throw an InvalidKeyException
 626      * if the key is not usable.
 627      */
 628     static byte[] getKeyBytes(Key key) throws InvalidKeyException {
 629         if (key == null) {
 630             throw new InvalidKeyException("No key given");
 631         }
 632         // note: key.getFormat() may return null
 633         if (!"RAW".equalsIgnoreCase(key.getFormat())) {
 634             throw new InvalidKeyException("Wrong format: RAW bytes needed");
 635         }
 636         byte[] keyBytes = key.getEncoded();
 637         if (keyBytes == null) {
 638             throw new InvalidKeyException("RAW key bytes missing");
 639         }
 640         return keyBytes;
 641     }
 642 
 643 
 644     /**
 645      * Continues a multiple-part encryption or decryption operation
 646      * (depending on how this cipher was initialized), processing another data
 647      * part.
 648      *
 649      * <p>The first <code>inputLen</code> bytes in the <code>input</code>
 650      * buffer, starting at <code>inputOffset</code>, are processed, and the
 651      * result is stored in a new buffer.
 652      *
 653      * @param input the input buffer
 654      * @param inputOffset the offset in <code>input</code> where the input
 655      * starts
 656      * @param inputLen the input length
 657      *
 658      * @return the new buffer with the result
 659      *
 660      * @exception IllegalStateException if this cipher is in a wrong state
 661      * (e.g., has not been initialized)
 662      */
 663     byte[] update(byte[] input, int inputOffset, int inputLen) {
 664         checkReinit();
 665 
 666         byte[] output = null;
 667         try {
 668             output = new byte[getOutputSizeByOperation(inputLen, false)];
 669             int len = update(input, inputOffset, inputLen, output,
 670                              0);
 671             if (len == output.length) {
 672                 return output;
 673             } else {
 674                 byte[] copy = Arrays.copyOf(output, len);
 675                 if (decrypting) {
 676                     // Zero out internal buffer which is no longer required
 677                     Arrays.fill(output, (byte) 0x00);
 678                 }
 679                 return copy;
 680             }
 681         } catch (ShortBufferException e) {
 682             // should never happen
 683             throw new ProviderException("Unexpected exception", e);
 684         }
 685     }
 686 
 687     /**
 688      * Continues a multiple-part encryption or decryption operation
 689      * (depending on how this cipher was initialized), processing another data
 690      * part.
 691      *
 692      * <p>The first <code>inputLen</code> bytes in the <code>input</code>
 693      * buffer, starting at <code>inputOffset</code>, are processed, and the
 694      * result is stored in the <code>output</code> buffer, starting at
 695      * <code>outputOffset</code>.
 696      *
 697      * @param input the input buffer
 698      * @param inputOffset the offset in <code>input</code> where the input
 699      * starts
 700      * @param inputLen the input length
 701      * @param output the buffer for the result
 702      * @param outputOffset the offset in <code>output</code> where the result
 703      * is stored
 704      *
 705      * @return the number of bytes stored in <code>output</code>
 706      *
 707      * @exception ShortBufferException if the given output buffer is too small
 708      * to hold the result
 709      */
 710     int update(byte[] input, int inputOffset, int inputLen, byte[] output,
 711                int outputOffset) throws ShortBufferException {
 712         checkReinit();
 713 
 714         // figure out how much can be sent to crypto function
 715         int len = Math.addExact(buffered, inputLen);
 716         len -= minBytes;
 717         if (padding != null && decrypting) {
 718             // do not include the padding bytes when decrypting
 719             len -= blockSize;
 720         }
 721         // do not count the trailing bytes which do not make up a unit
 722         len = (len > 0 ? (len - (len % unitBytes)) : 0);
 723 
 724         // check output buffer capacity
 725         if ((output == null) ||
 726             ((output.length - outputOffset) < len)) {
 727             throw new ShortBufferException("Output buffer must be "
 728                                            + "(at least) " + len
 729                                            + " bytes long");
 730         }
 731 
 732         int outLen = 0;
 733         if (len != 0) { // there is some work to do
 734             if ((input == output)
 735                  && (outputOffset - inputOffset < inputLen)
 736                  && (inputOffset - outputOffset < buffer.length)) {
 737                 // copy 'input' out to avoid its content being
 738                 // overwritten prematurely.
 739                 input = Arrays.copyOfRange(input, inputOffset,
 740                     Math.addExact(inputOffset, inputLen));
 741                 inputOffset = 0;
 742             }
 743             if (len <= buffered) {
 744                 // all to-be-processed data are from 'buffer'
 745                 if (decrypting) {
 746                     outLen = cipher.decrypt(buffer, 0, len, output, outputOffset);
 747                 } else {
 748                     outLen = cipher.encrypt(buffer, 0, len, output, outputOffset);
 749                 }
 750                 buffered -= len;
 751                 if (buffered != 0) {
 752                     System.arraycopy(buffer, len, buffer, 0, buffered);
 753                 }
 754             } else { // len > buffered
 755                 int inputConsumed = len - buffered;
 756                 int temp;
 757                 if (buffered > 0) {
 758                     int bufferCapacity = buffer.length - buffered;
 759                     if (bufferCapacity != 0) {
 760                         temp = Math.min(bufferCapacity, inputConsumed);
 761                         if (unitBytes != blockSize) {
 762                             temp -= (Math.addExact(buffered, temp) % unitBytes);
 763                         }
 764                         System.arraycopy(input, inputOffset, buffer, buffered, temp);
 765                         inputOffset = Math.addExact(inputOffset, temp);
 766                         inputConsumed -= temp;
 767                         inputLen -= temp;
 768                         buffered = Math.addExact(buffered, temp);
 769                     }
 770                     // process 'buffer'. When finished we can null out 'buffer'
 771                     // Only necessary to null out if buffer holds data for encryption
 772                     if (decrypting) {
 773                          outLen = cipher.decrypt(buffer, 0, buffered, output, outputOffset);
 774                     } else {
 775                          outLen = cipher.encrypt(buffer, 0, buffered, output, outputOffset);
 776                          //encrypt mode. Zero out internal (input) buffer
 777                          Arrays.fill(buffer, (byte) 0x00);
 778                     }
 779                     outputOffset = Math.addExact(outputOffset, outLen);
 780                     buffered = 0;
 781                 }
 782                 if (inputConsumed > 0) { // still has input to process
 783                     if (decrypting) {
 784                         outLen += cipher.decrypt(input, inputOffset, inputConsumed,
 785                             output, outputOffset);
 786                     } else {
 787                         outLen += cipher.encrypt(input, inputOffset, inputConsumed,
 788                             output, outputOffset);
 789                     }
 790                     inputOffset += inputConsumed;
 791                     inputLen -= inputConsumed;
 792                 }
 793             }
 794             // Let's keep track of how many bytes are needed to make
 795             // the total input length a multiple of blocksize when
 796             // padding is applied
 797             if (unitBytes != blockSize) {
 798                 if (len < diffBlocksize) {
 799                     diffBlocksize -= len;
 800                 } else {
 801                     diffBlocksize = blockSize -
 802                         ((len - diffBlocksize) % blockSize);
 803                 }
 804             }
 805         }
 806         // Store remaining input into 'buffer' again
 807         if (inputLen > 0) {
 808             System.arraycopy(input, inputOffset, buffer, buffered,
 809                              inputLen);
 810             buffered = Math.addExact(buffered, inputLen);
 811         }
 812         return outLen;
 813     }
 814 
 815     /**
 816      * Encrypts or decrypts data in a single-part operation,
 817      * or finishes a multiple-part operation.
 818      * The data is encrypted or decrypted, depending on how this cipher was
 819      * initialized.
 820      *
 821      * <p>The first <code>inputLen</code> bytes in the <code>input</code>
 822      * buffer, starting at <code>inputOffset</code>, and any input bytes that
 823      * may have been buffered during a previous <code>update</code> operation,
 824      * are processed, with padding (if requested) being applied.
 825      * The result is stored in a new buffer.
 826      *
 827      * <p>The cipher is reset to its initial state (uninitialized) after this
 828      * call.
 829      *
 830      * @param input the input buffer
 831      * @param inputOffset the offset in <code>input</code> where the input
 832      * starts
 833      * @param inputLen the input length
 834      *
 835      * @return the new buffer with the result
 836      *
 837      * @exception IllegalBlockSizeException if this cipher is a block cipher,
 838      * no padding has been requested (only in encryption mode), and the total
 839      * input length of the data processed by this cipher is not a multiple of
 840      * block size
 841      * @exception BadPaddingException if this cipher is in decryption mode,
 842      * and (un)padding has been requested, but the decrypted data is not
 843      * bounded by the appropriate padding bytes
 844      */
 845     byte[] doFinal(byte[] input, int inputOffset, int inputLen)
 846         throws IllegalBlockSizeException, BadPaddingException {
 847         try {
 848             checkReinit();
 849             byte[] output = new byte[getOutputSizeByOperation(inputLen, true)];
 850             byte[] finalBuf = prepareInputBuffer(input, inputOffset,
 851                     inputLen, output, 0);
 852             int finalOffset = (finalBuf == input) ? inputOffset : 0;
 853             int finalBufLen = (finalBuf == input) ? inputLen : finalBuf.length;
 854 
 855             int outLen = fillOutputBuffer(finalBuf, finalOffset, output, 0,
 856                     finalBufLen, input);
 857 
 858             endDoFinal();
 859             if (outLen < output.length) {
 860                 byte[] copy = Arrays.copyOf(output, outLen);
 861                 if (decrypting) {
 862                     // Zero out internal (ouput) array
 863                     Arrays.fill(output, (byte) 0x00);
 864                 }
 865                 return copy;
 866             } else {
 867                 return output;
 868             }
 869         } catch (ShortBufferException e) {
 870             // never thrown
 871             throw new ProviderException("Unexpected exception", e);
 872         }
 873     }
 874 
 875     /**
 876      * Encrypts or decrypts data in a single-part operation,
 877      * or finishes a multiple-part operation.
 878      * The data is encrypted or decrypted, depending on how this cipher was
 879      * initialized.
 880      *
 881      * <p>The first <code>inputLen</code> bytes in the <code>input</code>
 882      * buffer, starting at <code>inputOffset</code>, and any input bytes that
 883      * may have been buffered during a previous <code>update</code> operation,
 884      * are processed, with padding (if requested) being applied.
 885      * The result is stored in the <code>output</code> buffer, starting at
 886      * <code>outputOffset</code>.
 887      *
 888      * <p>The cipher is reset to its initial state (uninitialized) after this
 889      * call.
 890      *
 891      * @param input the input buffer
 892      * @param inputOffset the offset in <code>input</code> where the input
 893      * starts
 894      * @param inputLen the input length
 895      * @param output the buffer for the result
 896      * @param outputOffset the offset in <code>output</code> where the result
 897      * is stored
 898      *
 899      * @return the number of bytes stored in <code>output</code>
 900      *
 901      * @exception IllegalBlockSizeException if this cipher is a block cipher,
 902      * no padding has been requested (only in encryption mode), and the total
 903      * input length of the data processed by this cipher is not a multiple of
 904      * block size
 905      * @exception ShortBufferException if the given output buffer is too small
 906      * to hold the result
 907      * @exception BadPaddingException if this cipher is in decryption mode,
 908      * and (un)padding has been requested, but the decrypted data is not
 909      * bounded by the appropriate padding bytes
 910      */
 911     int doFinal(byte[] input, int inputOffset, int inputLen, byte[] output,
 912                 int outputOffset)
 913         throws IllegalBlockSizeException, ShortBufferException,
 914                BadPaddingException {
 915         checkReinit();
 916 
 917         int estOutSize = getOutputSizeByOperation(inputLen, true);
 918         int outputCapacity = checkOutputCapacity(output, outputOffset,
 919                 estOutSize);
 920         int offset = decrypting ? 0 : outputOffset; // 0 for decrypting
 921         byte[] finalBuf = prepareInputBuffer(input, inputOffset,
 922                 inputLen, output, outputOffset);
 923         byte[] outWithPadding = null; // for decrypting only
 924 
 925         int finalOffset = (finalBuf == input) ? inputOffset : 0;
 926         int finalBufLen = (finalBuf == input) ? inputLen : finalBuf.length;
 927 
 928         if (decrypting) {
 929             // if the size of specified output buffer is less than
 930             // the length of the cipher text, then the current
 931             // content of cipher has to be preserved in order for
 932             // users to retry the call with a larger buffer in the
 933             // case of ShortBufferException.
 934             if (outputCapacity < estOutSize) {
 935                 cipher.save();
 936             }
 937             // create temporary output buffer so that only "real"
 938             // data bytes are passed to user's output buffer.
 939             outWithPadding = new byte[estOutSize];
 940         }
 941         byte[] outBuffer = decrypting ? outWithPadding : output;
 942 
 943         int outLen = fillOutputBuffer(finalBuf, finalOffset, outBuffer,
 944                 offset, finalBufLen, input);
 945 
 946         if (decrypting) {
 947 
 948             if (outputCapacity < outLen) {
 949                 // restore so users can retry with a larger buffer
 950                 cipher.restore();
 951                 throw new ShortBufferException("Output buffer too short: "
 952                                                + (outputCapacity)
 953                                                + " bytes given, " + outLen
 954                                                + " bytes needed");
 955             }
 956             // copy the result into user-supplied output buffer
 957             System.arraycopy(outWithPadding, 0, output, outputOffset, outLen);
 958             // decrypt mode. Zero out output data that's not required
 959             Arrays.fill(outWithPadding, (byte) 0x00);
 960         }
 961         endDoFinal();
 962         return outLen;
 963     }
 964 
 965     private void endDoFinal() {
 966         buffered = 0;
 967         diffBlocksize = blockSize;
 968         if (cipherMode != ECB_MODE) {
 969             cipher.reset();
 970         }
 971     }
 972 
 973     private int unpad(int outLen, byte[] outWithPadding)
 974             throws BadPaddingException {
 975         int padStart = padding.unpad(outWithPadding, 0, outLen);
 976         if (padStart < 0) {
 977             throw new BadPaddingException("Given final block not " +
 978             "properly padded. Such issues can arise if a bad key " +
 979             "is used during decryption.");
 980         }
 981         outLen = padStart;
 982         return outLen;
 983     }
 984 
 985     private byte[] prepareInputBuffer(byte[] input, int inputOffset,
 986                       int inputLen, byte[] output, int outputOffset)
 987                       throws IllegalBlockSizeException, ShortBufferException {
 988         // calculate total input length
 989         int len = Math.addExact(buffered, inputLen);
 990         // calculate padding length
 991         int totalLen = Math.addExact(len, cipher.getBufferedLength());
 992         int paddingLen = 0;
 993         // will the total input length be a multiple of blockSize?
 994         if (unitBytes != blockSize) {
 995             if (totalLen < diffBlocksize) {
 996                 paddingLen = diffBlocksize - totalLen;
 997             } else {
 998                 paddingLen = blockSize -
 999                     ((totalLen - diffBlocksize) % blockSize);
1000             }
1001         } else if (padding != null) {
1002             paddingLen = padding.padLength(totalLen);
1003         }
1004 
1005         if (decrypting && (padding != null) &&
1006             (paddingLen > 0) && (paddingLen != blockSize)) {
1007             throw new IllegalBlockSizeException
1008                 ("Input length must be multiple of " + blockSize +
1009                  " when decrypting with padded cipher");
1010         }
1011 
1012         /*
1013          * prepare the final input, assemble a new buffer if any
1014          * of the following is true:
1015          *  - 'input' and 'output' are the same buffer
1016          *  - there are internally buffered bytes
1017          *  - doing encryption and padding is needed
1018          */
1019         if ((buffered != 0) || (!decrypting && padding != null) ||
1020             ((input == output)
1021               && (outputOffset - inputOffset < inputLen)
1022               && (inputOffset - outputOffset < buffer.length))) {
1023             byte[] finalBuf;
1024             if (decrypting || padding == null) {
1025                 paddingLen = 0;
1026             }
1027             finalBuf = new byte[Math.addExact(len, paddingLen)];
1028             if (buffered != 0) {
1029                 System.arraycopy(buffer, 0, finalBuf, 0, buffered);
1030                 if (!decrypting) {
1031                     // done with input buffer. We should zero out the
1032                     // data if we're in encrypt mode.
1033                     Arrays.fill(buffer, (byte) 0x00);
1034                 }
1035             }
1036             if (inputLen != 0) {
1037                 System.arraycopy(input, inputOffset, finalBuf,
1038                         buffered, inputLen);
1039             }
1040             if (paddingLen != 0) {
1041                 padding.padWithLen(finalBuf, Math.addExact(buffered, inputLen), paddingLen);
1042             }
1043             return finalBuf;
1044         }
1045         return input;
1046     }
1047 
1048     private int fillOutputBuffer(byte[] finalBuf, int finalOffset,
1049                                  byte[] output, int outOfs, int finalBufLen,
1050                                  byte[] input)
1051             throws ShortBufferException, BadPaddingException,
1052             IllegalBlockSizeException {
1053         int len;
1054         try {
1055             len = finalNoPadding(finalBuf, finalOffset, output,
1056                     outOfs, finalBufLen);
1057             if (decrypting && padding != null) {
1058                 len = unpad(len, output);
1059             }
1060             return len;
1061         } finally {
1062             if (!decrypting) {
1063                 // reset after doFinal() for GCM encryption
1064                 requireReinit = (cipherMode == GCM_MODE);
1065                 if (finalBuf != input) {
1066                     // done with internal finalBuf array. Copied to output
1067                     Arrays.fill(finalBuf, (byte) 0x00);
1068                 }
1069             }
1070         }
1071     }
1072 
1073     private int checkOutputCapacity(byte[] output, int outputOffset,
1074                             int estOutSize) throws ShortBufferException {
1075         // check output buffer capacity.
1076         // if we are decrypting with padding applied, we can perform this
1077         // check only after we have determined how many padding bytes there
1078         // are.
1079         int outputCapacity = output.length - outputOffset;
1080         int minOutSize = decrypting ? (estOutSize - blockSize) : estOutSize;
1081         if ((output == null) || (outputCapacity < minOutSize)) {
1082             throw new ShortBufferException("Output buffer must be "
1083                 + "(at least) " + minOutSize + " bytes long");
1084         }
1085         return outputCapacity;
1086     }
1087 
1088     private void checkReinit() {
1089         if (requireReinit) {
1090             throw new IllegalStateException
1091                 ("Must use either different key or iv for GCM encryption");
1092         }
1093     }
1094 
1095     private int finalNoPadding(byte[] in, int inOfs, byte[] out, int outOfs,
1096                                int len)
1097         throws IllegalBlockSizeException, AEADBadTagException,
1098         ShortBufferException {
1099 
1100         if ((cipherMode != GCM_MODE) && (in == null || len == 0)) {
1101             return 0;
1102         }
1103         if ((cipherMode != CFB_MODE) && (cipherMode != OFB_MODE) &&
1104             (cipherMode != GCM_MODE) &&
1105             ((len % unitBytes) != 0) && (cipherMode != CTS_MODE)) {
1106                 if (padding != null) {
1107                     throw new IllegalBlockSizeException
1108                         ("Input length (with padding) not multiple of " +
1109                          unitBytes + " bytes");
1110                 } else {
1111                     throw new IllegalBlockSizeException
1112                         ("Input length not multiple of " + unitBytes
1113                          + " bytes");
1114                 }
1115         }
1116         int outLen = 0;
1117         if (decrypting) {
1118             outLen = cipher.decryptFinal(in, inOfs, len, out, outOfs);
1119         } else {
1120             outLen = cipher.encryptFinal(in, inOfs, len, out, outOfs);
1121         }
1122         return outLen;
1123     }
1124 
1125     // Note: Wrap() and Unwrap() are the same in
1126     // each of SunJCE CipherSpi implementation classes.
1127     // They are duplicated due to export control requirements:
1128     // All CipherSpi implementation must be final.
1129     /**
1130      * Wrap a key.
1131      *
1132      * @param key the key to be wrapped.
1133      *
1134      * @return the wrapped key.
1135      *
1136      * @exception IllegalBlockSizeException if this cipher is a block
1137      * cipher, no padding has been requested, and the length of the
1138      * encoding of the key to be wrapped is not a
1139      * multiple of the block size.
1140      *
1141      * @exception InvalidKeyException if it is impossible or unsafe to
1142      * wrap the key with this cipher (e.g., a hardware protected key is
1143      * being passed to a software only cipher).
1144      */
1145     byte[] wrap(Key key)
1146         throws IllegalBlockSizeException, InvalidKeyException {
1147         byte[] result = null;
1148 
1149         try {
1150             byte[] encodedKey = key.getEncoded();
1151             if ((encodedKey == null) || (encodedKey.length == 0)) {
1152                 throw new InvalidKeyException("Cannot get an encoding of " +
1153                                               "the key to be wrapped");
1154             }
1155             result = doFinal(encodedKey, 0, encodedKey.length);
1156         } catch (BadPaddingException e) {
1157             // Should never happen
1158         }
1159         return result;
1160     }
1161 
1162     /**
1163      * Unwrap a previously wrapped key.
1164      *
1165      * @param wrappedKey the key to be unwrapped.
1166      *
1167      * @param wrappedKeyAlgorithm the algorithm the wrapped key is for.
1168      *
1169      * @param wrappedKeyType the type of the wrapped key.
1170      * This is one of <code>Cipher.SECRET_KEY</code>,
1171      * <code>Cipher.PRIVATE_KEY</code>, or <code>Cipher.PUBLIC_KEY</code>.
1172      *
1173      * @return the unwrapped key.
1174      *
1175      * @exception NoSuchAlgorithmException if no installed providers
1176      * can create keys of type <code>wrappedKeyType</code> for the
1177      * <code>wrappedKeyAlgorithm</code>.
1178      *
1179      * @exception InvalidKeyException if <code>wrappedKey</code> does not
1180      * represent a wrapped key of type <code>wrappedKeyType</code> for
1181      * the <code>wrappedKeyAlgorithm</code>.
1182      */
1183     Key unwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
1184                int wrappedKeyType)
1185         throws InvalidKeyException, NoSuchAlgorithmException {
1186         byte[] encodedKey;
1187         try {
1188             encodedKey = doFinal(wrappedKey, 0, wrappedKey.length);
1189         } catch (BadPaddingException ePadding) {
1190             throw new InvalidKeyException("The wrapped key is not padded " +
1191                                           "correctly");
1192         } catch (IllegalBlockSizeException eBlockSize) {
1193             throw new InvalidKeyException("The wrapped key does not have " +
1194                                           "the correct length");
1195         }
1196         return ConstructKeys.constructKey(encodedKey, wrappedKeyAlgorithm,
1197                                           wrappedKeyType);
1198     }
1199 
1200     /**
1201      * Continues a multi-part update of the Additional Authentication
1202      * Data (AAD), using a subset of the provided buffer.
1203      * <p>
1204      * Calls to this method provide AAD to the cipher when operating in
1205      * modes such as AEAD (GCM/CCM).  If this cipher is operating in
1206      * either GCM or CCM mode, all AAD must be supplied before beginning
1207      * operations on the ciphertext (via the {@code update} and {@code
1208      * doFinal} methods).
1209      *
1210      * @param src the buffer containing the AAD
1211      * @param offset the offset in {@code src} where the AAD input starts
1212      * @param len the number of AAD bytes
1213      *
1214      * @throws IllegalStateException if this cipher is in a wrong state
1215      * (e.g., has not been initialized), does not accept AAD, or if
1216      * operating in either GCM or CCM mode and one of the {@code update}
1217      * methods has already been called for the active
1218      * encryption/decryption operation
1219      * @throws UnsupportedOperationException if this method
1220      * has not been overridden by an implementation
1221      *
1222      * @since 1.8
1223      */
1224     void updateAAD(byte[] src, int offset, int len) {
1225         checkReinit();
1226         cipher.updateAAD(src, offset, len);
1227     }
1228 }