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