< prev index next >

src/share/classes/com/sun/crypto/provider/CipherCore.java

Print this page
rev 12526 : 8171252: Improve exception checking
8158517: Minor optimizations to ISO10126PADDING
Reviewed-by: ascarpino, mschoene
   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


 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() {


 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


 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) {


   1 /*
   2  * Copyright (c) 2002, 2017, 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


 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 = Math.addExact(buffered, cipher.getBufferedLength());
 328         totalLen = Math.addExact(totalLen, inputLen);
 329         switch (cipherMode) {
 330         case GCM_MODE:
 331             if (isDoFinal) {
 332                 int tagLen = ((GaloisCounterMode) cipher).getTagLen();
 333                 if (!decrypting) {
 334                     totalLen = Math.addExact(totalLen, tagLen);
 335                 } else {
 336                     totalLen -= tagLen;
 337                 }
 338             }
 339             if (totalLen < 0) {
 340                 totalLen = 0;
 341             }
 342             break;
 343         default:
 344             if (padding != null && !decrypting) {
 345                 if (unitBytes != blockSize) {
 346                     if (totalLen < diffBlocksize) {
 347                         totalLen = diffBlocksize;
 348                     } else {
 349                         int residue = (totalLen - diffBlocksize) % blockSize;
 350                         totalLen = Math.addExact(totalLen, (blockSize - residue));
 351                     }
 352                 } else {
 353                     totalLen = Math.addExact(totalLen, padding.padLength(totalLen));
 354                 }
 355             }
 356             break;
 357         }
 358         return totalLen;
 359     }
 360 
 361     /**
 362      * Returns the initialization vector (IV) in a new buffer.
 363      *
 364      * <p>This is useful in the case where a random IV has been created
 365      * (see <a href = "#init">init</a>),
 366      * or in the context of password-based encryption or
 367      * decryption, where the IV is derived from a user-provided password.
 368      *
 369      * @return the initialization vector in a new buffer, or null if the
 370      * underlying algorithm does not use an IV, or if the IV has not yet
 371      * been set.
 372      */
 373     byte[] getIV() {


 695      * @param inputOffset the offset in <code>input</code> where the input
 696      * starts
 697      * @param inputLen the input length
 698      * @param output the buffer for the result
 699      * @param outputOffset the offset in <code>output</code> where the result
 700      * is stored
 701      *
 702      * @return the number of bytes stored in <code>output</code>
 703      *
 704      * @exception ShortBufferException if the given output buffer is too small
 705      * to hold the result
 706      */
 707     int update(byte[] input, int inputOffset, int inputLen, byte[] output,
 708                int outputOffset) throws ShortBufferException {
 709         if (requireReinit) {
 710             throw new IllegalStateException
 711                 ("Must use either different key or iv for GCM encryption");
 712         }
 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'
 771                     if (decrypting) {
 772                          outLen = cipher.decrypt(buffer, 0, buffered, output, outputOffset);
 773                     } else {
 774                          outLen = cipher.encrypt(buffer, 0, buffered, output, outputOffset);
 775                     }
 776                     outputOffset = Math.addExact(outputOffset, outLen);
 777                     buffered = 0;
 778                 }
 779                 if (inputConsumed > 0) { // still has input to process
 780                     if (decrypting) {
 781                         outLen += cipher.decrypt(input, inputOffset, inputConsumed,
 782                             output, outputOffset);
 783                     } else {
 784                         outLen += cipher.encrypt(input, inputOffset, inputConsumed,
 785                             output, outputOffset);
 786                     }
 787                     inputOffset += inputConsumed;
 788                     inputLen -= inputConsumed;
 789                 }
 790             }
 791             // Let's keep track of how many bytes are needed to make
 792             // the total input length a multiple of blocksize when
 793             // padding is applied
 794             if (unitBytes != blockSize) {
 795                 if (len < diffBlocksize) {
 796                     diffBlocksize -= len;
 797                 } else {
 798                     diffBlocksize = blockSize -
 799                         ((len - diffBlocksize) % blockSize);
 800                 }
 801             }
 802         }
 803         // Store remaining input into 'buffer' again
 804         if (inputLen > 0) {
 805             System.arraycopy(input, inputOffset, buffer, buffered,
 806                              inputLen);
 807             buffered = Math.addExact(buffered, inputLen);
 808         }
 809         return outLen;
 810     }
 811 
 812     /**
 813      * Encrypts or decrypts data in a single-part operation,
 814      * or finishes a multiple-part operation.
 815      * The data is encrypted or decrypted, depending on how this cipher was
 816      * initialized.
 817      *
 818      * <p>The first <code>inputLen</code> bytes in the <code>input</code>
 819      * buffer, starting at <code>inputOffset</code>, and any input bytes that
 820      * may have been buffered during a previous <code>update</code> operation,
 821      * are processed, with padding (if requested) being applied.
 822      * The result is stored in a new buffer.
 823      *
 824      * <p>The cipher is reset to its initial state (uninitialized) after this
 825      * call.
 826      *
 827      * @param input the input buffer


 897         throws IllegalBlockSizeException, ShortBufferException,
 898                BadPaddingException {
 899         if (requireReinit) {
 900             throw new IllegalStateException
 901                 ("Must use either different key or iv for GCM encryption");
 902         }
 903 
 904         int estOutSize = getOutputSizeByOperation(inputLen, true);
 905         // check output buffer capacity.
 906         // if we are decrypting with padding applied, we can perform this
 907         // check only after we have determined how many padding bytes there
 908         // are.
 909         int outputCapacity = output.length - outputOffset;
 910         int minOutSize = (decrypting? (estOutSize - blockSize):estOutSize);
 911         if ((output == null) || (outputCapacity < minOutSize)) {
 912             throw new ShortBufferException("Output buffer must be "
 913                 + "(at least) " + minOutSize + " bytes long");
 914         }
 915 
 916         // calculate total input length
 917         int len = Math.addExact(buffered, inputLen);
 918 
 919         // calculate padding length
 920         int totalLen = Math.addExact(len, cipher.getBufferedLength());
 921         int paddingLen = 0;
 922         // will the total input length be a multiple of blockSize?
 923         if (unitBytes != blockSize) {
 924             if (totalLen < diffBlocksize) {
 925                 paddingLen = diffBlocksize - totalLen;
 926             } else {
 927                 paddingLen = blockSize -
 928                     ((totalLen - diffBlocksize) % blockSize);
 929             }
 930         } else if (padding != null) {
 931             paddingLen = padding.padLength(totalLen);
 932         }
 933 
 934         if (decrypting && (padding != null) &&
 935             (paddingLen > 0) && (paddingLen != blockSize)) {
 936             throw new IllegalBlockSizeException
 937                 ("Input length must be multiple of " + blockSize +
 938                  " when decrypting with padded cipher");
 939         }
 940 
 941         /*
 942          * prepare the final input, assemble a new buffer if any
 943          * of the following is true:
 944          *  - 'input' and 'output' are the same buffer
 945          *  - there are internally buffered bytes
 946          *  - doing encryption and padding is needed
 947          */
 948         byte[] finalBuf = input;
 949         int finalOffset = inputOffset;
 950         int finalBufLen = inputLen;
 951         if ((buffered != 0) || (!decrypting && padding != null) ||
 952             ((input == output)
 953               && (outputOffset - inputOffset < inputLen)
 954               && (inputOffset - outputOffset < buffer.length))) {
 955             if (decrypting || padding == null) {
 956                 paddingLen = 0;
 957             }
 958             finalBuf = new byte[Math.addExact(len, paddingLen)];
 959             finalOffset = 0;
 960             if (buffered != 0) {
 961                 System.arraycopy(buffer, 0, finalBuf, 0, buffered);
 962             }
 963             if (inputLen != 0) {
 964                 System.arraycopy(input, inputOffset, finalBuf,
 965                                  buffered, inputLen);
 966             }
 967             if (paddingLen != 0) {
 968                 padding.padWithLen(finalBuf, Math.addExact(buffered, inputLen), paddingLen);
 969             }
 970             finalBufLen = finalBuf.length;
 971         }
 972         int outLen = 0;
 973         if (decrypting) {
 974             // if the size of specified output buffer is less than
 975             // the length of the cipher text, then the current
 976             // content of cipher has to be preserved in order for
 977             // users to retry the call with a larger buffer in the
 978             // case of ShortBufferException.
 979             if (outputCapacity < estOutSize) {
 980                 cipher.save();
 981             }
 982             // create temporary output buffer so that only "real"
 983             // data bytes are passed to user's output buffer.
 984             byte[] outWithPadding = new byte[estOutSize];
 985             outLen = finalNoPadding(finalBuf, finalOffset, outWithPadding,
 986                                     0, finalBufLen);
 987 
 988             if (padding != null) {


< prev index next >