Mercurial > hg > openjdk > bsd-port > jdk
changeset 8760:fe4dc42365db
8012900: CICO ignores AAD in GCM mode (with refactoring from 6996769)
Summary: Change GCM decryption to not return result until tag verification passed
Reviewed-by: xuelei
line wrap: on
line diff
--- a/src/share/classes/com/sun/crypto/provider/CipherBlockChaining.java Thu Nov 09 06:45:25 2017 +0000 +++ b/src/share/classes/com/sun/crypto/provider/CipherBlockChaining.java Fri Nov 10 04:05:13 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -135,9 +135,10 @@ * @param plainLen the length of the input data * @param cipher the buffer for the result * @param cipherOffset the offset in <code>cipher</code> + * @return the length of the encrypted data */ - void encrypt(byte[] plain, int plainOffset, int plainLen, - byte[] cipher, int cipherOffset) + int encrypt(byte[] plain, int plainOffset, int plainLen, + byte[] cipher, int cipherOffset) { int i; int endIndex = plainOffset + plainLen; @@ -150,6 +151,7 @@ embeddedCipher.encryptBlock(k, 0, cipher, cipherOffset); System.arraycopy(cipher, cipherOffset, r, 0, blockSize); } + return plainLen; } /** @@ -174,13 +176,14 @@ * @param cipherLen the length of the input data * @param plain the buffer for the result * @param plainOffset the offset in <code>plain</code> + * @return the length of the decrypted data * * @exception IllegalBlockSizeException if input data whose length does * not correspond to the embedded cipher's block size is passed to the * embedded cipher */ - void decrypt(byte[] cipher, int cipherOffset, int cipherLen, - byte[] plain, int plainOffset) + int decrypt(byte[] cipher, int cipherOffset, int cipherLen, + byte[] plain, int plainOffset) { int i; byte[] cipherOrig=null; @@ -195,7 +198,6 @@ // the plaintext result. cipherOrig = cipher.clone(); } - for (; cipherOffset < endIndex; cipherOffset += blockSize, plainOffset += blockSize) { embeddedCipher.decryptBlock(cipher, cipherOffset, k, 0); @@ -208,5 +210,6 @@ System.arraycopy(cipherOrig, cipherOffset, r, 0, blockSize); } } + return cipherLen; } }
--- a/src/share/classes/com/sun/crypto/provider/CipherCore.java Thu Nov 09 06:45:25 2017 +0000 +++ b/src/share/classes/com/sun/crypto/provider/CipherCore.java Fri Nov 10 04:05:13 2017 +0000 @@ -25,6 +25,7 @@ package com.sun.crypto.provider; +import java.util.Arrays; import java.util.Locale; import java.security.*; @@ -59,7 +60,7 @@ private byte[] buffer = null; /* - * internal buffer + * block size of cipher in bytes */ private int blockSize = 0; @@ -76,7 +77,7 @@ /* * minimum number of bytes in the buffer required for * FeedbackCipher.encryptFinal()/decryptFinal() call. - * update() must buffer this many bytes before before starting + * update() must buffer this many bytes before starting * to encrypt/decrypt data. * currently, only CTS mode has a non-zero value due to its special * handling on the last two blocks (the last one may be incomplete). @@ -149,7 +150,7 @@ * @param mode the cipher mode * * @exception NoSuchAlgorithmException if the requested cipher mode does - * not exist + * not exist for this cipher */ void setMode(String mode) throws NoSuchAlgorithmException { if (mode == null) @@ -165,30 +166,25 @@ if (modeUpperCase.equals("CBC")) { cipherMode = CBC_MODE; cipher = new CipherBlockChaining(rawImpl); - } - else if (modeUpperCase.equals("CTS")) { + } else if (modeUpperCase.equals("CTS")) { cipherMode = CTS_MODE; cipher = new CipherTextStealing(rawImpl); minBytes = blockSize+1; padding = null; - } - else if (modeUpperCase.equals("CTR")) { + } else if (modeUpperCase.equals("CTR")) { cipherMode = CTR_MODE; cipher = new CounterMode(rawImpl); unitBytes = 1; padding = null; - } - else if (modeUpperCase.startsWith("CFB")) { + } else if (modeUpperCase.startsWith("CFB")) { cipherMode = CFB_MODE; unitBytes = getNumOfUnit(mode, "CFB".length(), blockSize); cipher = new CipherFeedback(rawImpl, unitBytes); - } - else if (modeUpperCase.startsWith("OFB")) { + } else if (modeUpperCase.startsWith("OFB")) { cipherMode = OFB_MODE; unitBytes = getNumOfUnit(mode, "OFB".length(), blockSize); cipher = new OutputFeedback(rawImpl, unitBytes); - } - else if (modeUpperCase.equals("PCBC")) { + } else if (modeUpperCase.equals("PCBC")) { cipherMode = PCBC_MODE; cipher = new PCBC(rawImpl); } @@ -219,6 +215,7 @@ return result; } + /** * Sets the padding mechanism of this cipher. * @@ -268,23 +265,29 @@ * @return the required output buffer size (in bytes) */ int getOutputSize(int inputLen) { - int totalLen = buffered + inputLen; - - if (padding == null) - return totalLen; - - if (decrypting) - return totalLen; + // estimate based on the maximum + return getOutputSizeByOperation(inputLen, true); + } - if (unitBytes != blockSize) { - if (totalLen < diffBlocksize) - return diffBlocksize; - else - return (totalLen + blockSize - - ((totalLen - diffBlocksize) % blockSize)); - } else { - return totalLen + padding.padLength(totalLen); + private int getOutputSizeByOperation(int inputLen, boolean isDoFinal) { + int totalLen = buffered + inputLen + cipher.getBufferedLength(); + switch (cipherMode) { + default: + if (padding != null && !decrypting) { + if (unitBytes != blockSize) { + if (totalLen < diffBlocksize) { + totalLen = diffBlocksize; + } else { + int residue = (totalLen - diffBlocksize) % blockSize; + totalLen += (blockSize - residue); + } + } else { + totalLen += padding.padLength(totalLen); + } + } + break; } + return totalLen; } /** @@ -318,34 +321,39 @@ * does not use any parameters. */ AlgorithmParameters getParameters(String algName) { + if (cipherMode == ECB_MODE) { + return null; + } AlgorithmParameters params = null; - if (cipherMode == ECB_MODE) return null; + AlgorithmParameterSpec spec; byte[] iv = getIV(); - if (iv != null) { - AlgorithmParameterSpec ivSpec; - if (algName.equals("RC2")) { - RC2Crypt rawImpl = (RC2Crypt) cipher.getEmbeddedCipher(); - ivSpec = new RC2ParameterSpec(rawImpl.getEffectiveKeyBits(), - iv); - } else { - ivSpec = new IvParameterSpec(iv); - } - try { - params = AlgorithmParameters.getInstance(algName, "SunJCE"); - } catch (NoSuchAlgorithmException nsae) { - // should never happen - throw new RuntimeException("Cannot find " + algName + - " AlgorithmParameters implementation in SunJCE provider"); - } catch (NoSuchProviderException nspe) { - // should never happen - throw new RuntimeException("Cannot find SunJCE provider"); - } - try { - params.init(ivSpec); - } catch (InvalidParameterSpecException ipse) { - // should never happen - throw new RuntimeException("IvParameterSpec not supported"); - } + if (iv == null) { + // generate spec using default value + iv = new byte[blockSize]; + SunJCE.RANDOM.nextBytes(iv); + } + if (algName.equals("RC2")) { + RC2Crypt rawImpl = (RC2Crypt) cipher.getEmbeddedCipher(); + spec = new RC2ParameterSpec + (rawImpl.getEffectiveKeyBits(), iv); + } else { + spec = new IvParameterSpec(iv); + } + try { + params = AlgorithmParameters.getInstance(algName, "SunJCE"); + } catch (NoSuchAlgorithmException nsae) { + // should never happen + throw new RuntimeException("Cannot find " + algName + + " AlgorithmParameters implementation in SunJCE provider"); + } catch (NoSuchProviderException nspe) { + // should never happen + throw new RuntimeException("Cannot find SunJCE provider"); + } + try { + params.init(spec); + } catch (InvalidParameterSpecException ipse) { + // should never happen + throw new RuntimeException(spec.getClass() + " not supported"); } return params; } @@ -420,40 +428,39 @@ || (opmode == Cipher.UNWRAP_MODE); byte[] keyBytes = getKeyBytes(key); - - byte[] ivBytes; - if (params == null) { - ivBytes = null; - } else if (params instanceof IvParameterSpec) { - ivBytes = ((IvParameterSpec)params).getIV(); - if ((ivBytes == null) || (ivBytes.length != blockSize)) { + int tagLen = -1; + byte[] ivBytes = null; + if (params != null) { + if (params instanceof IvParameterSpec) { + ivBytes = ((IvParameterSpec)params).getIV(); + if ((ivBytes == null) || (ivBytes.length != blockSize)) { + throw new InvalidAlgorithmParameterException + ("Wrong IV length: must be " + blockSize + + " bytes long"); + } + } else if (params instanceof RC2ParameterSpec) { + ivBytes = ((RC2ParameterSpec)params).getIV(); + if ((ivBytes != null) && (ivBytes.length != blockSize)) { + throw new InvalidAlgorithmParameterException + ("Wrong IV length: must be " + blockSize + + " bytes long"); + } + } else { throw new InvalidAlgorithmParameterException - ("Wrong IV length: must be " + blockSize + - " bytes long"); + ("Unsupported parameter: " + params); } - } else if (params instanceof RC2ParameterSpec) { - ivBytes = ((RC2ParameterSpec)params).getIV(); - if ((ivBytes != null) && (ivBytes.length != blockSize)) { - throw new InvalidAlgorithmParameterException - ("Wrong IV length: must be " + blockSize + - " bytes long"); - } - } else { - throw new InvalidAlgorithmParameterException("Wrong parameter " - + "type: IV " - + "expected"); } - if (cipherMode == ECB_MODE) { if (ivBytes != null) { throw new InvalidAlgorithmParameterException ("ECB mode cannot use IV"); } - } else if (ivBytes == null) { + } else if (ivBytes == null) { if (decrypting) { throw new InvalidAlgorithmParameterException("Parameters " + "missing"); } + if (random == null) { random = SunJCE.RANDOM; } @@ -472,17 +479,21 @@ void init(int opmode, Key key, AlgorithmParameters params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { - IvParameterSpec ivSpec = null; + AlgorithmParameterSpec spec = null; + String paramType = null; if (params != null) { try { - ivSpec = params.getParameterSpec(IvParameterSpec.class); + // NOTE: RC2 parameters are always handled through + // init(..., AlgorithmParameterSpec,...) method, so + // we can assume IvParameterSpec type here. + paramType = "IV"; + spec = params.getParameterSpec(IvParameterSpec.class); } catch (InvalidParameterSpecException ipse) { - throw new InvalidAlgorithmParameterException("Wrong parameter " - + "type: IV " - + "expected"); + throw new InvalidAlgorithmParameterException + ("Wrong parameter type: " + paramType + " expected"); } } - init(opmode, key, ivSpec, random); + init(opmode, key, spec, random); } /** @@ -504,6 +515,7 @@ return keyBytes; } + /** * Continues a multiple-part encryption or decryption operation * (depending on how this cipher was initialized), processing another data @@ -525,21 +537,19 @@ */ byte[] update(byte[] input, int inputOffset, int inputLen) { byte[] output = null; - byte[] out = null; try { - output = new byte[getOutputSize(inputLen)]; + output = new byte[getOutputSizeByOperation(inputLen, false)]; int len = update(input, inputOffset, inputLen, output, 0); if (len == output.length) { - out = output; + return output; } else { - out = new byte[len]; - System.arraycopy(output, 0, out, 0, len); + return Arrays.copyOf(output, len); } } catch (ShortBufferException e) { - // never thrown + // should never happen + throw new ProviderException("Unexpected exception", e); } - return out; } /** @@ -577,63 +587,72 @@ len = (len > 0 ? (len - (len%unitBytes)) : 0); // check output buffer capacity - if ((output == null) || ((output.length - outputOffset) < len)) { + if ((output == null) || + ((output.length - outputOffset) < len)) { throw new ShortBufferException("Output buffer must be " + "(at least) " + len + " bytes long"); } - if (len != 0) { - // there is some work to do - byte[] in = new byte[len]; - int inputConsumed = len - buffered; - int bufferedConsumed = buffered; - if (inputConsumed < 0) { - inputConsumed = 0; - bufferedConsumed = len; - } - - if (buffered != 0) { - System.arraycopy(buffer, 0, in, 0, bufferedConsumed); - } - if (inputConsumed > 0) { - System.arraycopy(input, inputOffset, in, - bufferedConsumed, inputConsumed); - } - - if (decrypting) { - cipher.decrypt(in, 0, len, output, outputOffset); - } else { - cipher.encrypt(in, 0, len, output, outputOffset); + int outLen = 0; + if (len != 0) { // there is some work to do + if (len <= buffered) { + // all to-be-processed data are from 'buffer' + if (decrypting) { + outLen = cipher.decrypt(buffer, 0, len, output, outputOffset); + } else { + outLen = cipher.encrypt(buffer, 0, len, output, outputOffset); + } + buffered -= len; + if (buffered != 0) { + System.arraycopy(buffer, len, buffer, 0, buffered); + } + } else { // len > buffered + if (buffered == 0) { + // all to-be-processed data are from 'input' + if (decrypting) { + outLen = cipher.decrypt(input, inputOffset, len, output, outputOffset); + } else { + outLen = cipher.encrypt(input, inputOffset, len, output, outputOffset); + } + inputOffset += len; + inputLen -= len; + } else { + // assemble the data using both 'buffer' and 'input' + byte[] in = new byte[len]; + System.arraycopy(buffer, 0, in, 0, buffered); + int inConsumed = len - buffered; + System.arraycopy(input, inputOffset, in, buffered, inConsumed); + buffered = 0; + inputOffset += inConsumed; + inputLen -= inConsumed; + if (decrypting) { + outLen = cipher.decrypt(in, 0, len, output, outputOffset); + } else { + outLen = cipher.encrypt(in, 0, len, output, outputOffset); + } + } } // Let's keep track of how many bytes are needed to make // the total input length a multiple of blocksize when // padding is applied if (unitBytes != blockSize) { - if (len < diffBlocksize) + if (len < diffBlocksize) { diffBlocksize -= len; - else + } else { diffBlocksize = blockSize - ((len - diffBlocksize) % blockSize); - } - - inputLen -= inputConsumed; - inputOffset += inputConsumed; - outputOffset += len; - buffered -= bufferedConsumed; - if (buffered > 0) { - System.arraycopy(buffer, bufferedConsumed, buffer, 0, - buffered); + } } } - // left over again + // Store remaining input into 'buffer' again if (inputLen > 0) { System.arraycopy(input, inputOffset, buffer, buffered, inputLen); + buffered += inputLen; } - buffered += inputLen; - return len; + return outLen; } /** @@ -669,21 +688,18 @@ byte[] doFinal(byte[] input, int inputOffset, int inputLen) throws IllegalBlockSizeException, BadPaddingException { byte[] output = null; - byte[] out = null; try { - output = new byte[getOutputSize(inputLen)]; + output = new byte[getOutputSizeByOperation(inputLen, true)]; int len = doFinal(input, inputOffset, inputLen, output, 0); if (len < output.length) { - out = new byte[len]; - if (len != 0) - System.arraycopy(output, 0, out, 0, len); + return Arrays.copyOf(output, len); } else { - out = output; + return output; } } catch (ShortBufferException e) { // never thrown + throw new ProviderException("Unexpected exception", e); } - return out; } /** @@ -727,11 +743,24 @@ throws IllegalBlockSizeException, ShortBufferException, BadPaddingException { - // calculate the total input length - int totalLen = buffered + inputLen; - int paddedLen = totalLen; + int estOutSize = getOutputSizeByOperation(inputLen, true); + // check output buffer capacity. + // if we are decrypting with padding applied, we can perform this + // check only after we have determined how many padding bytes there + // are. + int outputCapacity = output.length - outputOffset; + int minOutSize = (decrypting? (estOutSize - blockSize):estOutSize); + if ((output == null) || (outputCapacity < minOutSize)) { + throw new ShortBufferException("Output buffer must be " + + "(at least) " + minOutSize + " bytes long"); + } + + // calculate total input length + int len = buffered + inputLen; + + // calculate padding length + int totalLen = len + cipher.getBufferedLength(); int paddingLen = 0; - // will the total input length be a multiple of blockSize? if (unitBytes != blockSize) { if (totalLen < diffBlocksize) { @@ -744,39 +773,23 @@ paddingLen = padding.padLength(totalLen); } - if ((paddingLen > 0) && (paddingLen != blockSize) && - (padding != null) && decrypting) { + if (decrypting && (padding != null) && + (paddingLen > 0) && (paddingLen != blockSize)) { throw new IllegalBlockSizeException ("Input length must be multiple of " + blockSize + " when decrypting with padded cipher"); } - // if encrypting and padding not null, add padding - if (!decrypting && padding != null) - paddedLen += paddingLen; - - // check output buffer capacity. - // if we are decrypting with padding applied, we can perform this - // check only after we have determined how many padding bytes there - // are. - if (output == null) { - throw new ShortBufferException("Output buffer is null"); - } - int outputCapacity = output.length - outputOffset; - if (((!decrypting) || (padding == null)) && - (outputCapacity < paddedLen) || - (decrypting && (outputCapacity < (paddedLen - blockSize)))) { - throw new ShortBufferException("Output buffer too short: " - + outputCapacity + " bytes given, " - + paddedLen + " bytes needed"); - } - // prepare the final input avoiding copying if possible byte[] finalBuf = input; int finalOffset = inputOffset; + int finalBufLen = inputLen; if ((buffered != 0) || (!decrypting && padding != null)) { + if (decrypting || padding == null) { + paddingLen = 0; + } + finalBuf = new byte[len + paddingLen]; finalOffset = 0; - finalBuf = new byte[paddedLen]; if (buffered != 0) { System.arraycopy(buffer, 0, finalBuf, 0, buffered); } @@ -784,48 +797,49 @@ System.arraycopy(input, inputOffset, finalBuf, buffered, inputLen); } - if (!decrypting && padding != null) { - padding.padWithLen(finalBuf, totalLen, paddingLen); + if (paddingLen != 0) { + padding.padWithLen(finalBuf, (buffered+inputLen), paddingLen); } + finalBufLen = finalBuf.length; } + int outLen = 0; if (decrypting) { // if the size of specified output buffer is less than // the length of the cipher text, then the current // content of cipher has to be preserved in order for // users to retry the call with a larger buffer in the // case of ShortBufferException. - if (outputCapacity < paddedLen) { + if (outputCapacity < estOutSize) { cipher.save(); } // create temporary output buffer so that only "real" // data bytes are passed to user's output buffer. - byte[] outWithPadding = new byte[totalLen]; - totalLen = finalNoPadding(finalBuf, finalOffset, outWithPadding, - 0, totalLen); + byte[] outWithPadding = new byte[estOutSize]; + outLen = finalNoPadding(finalBuf, finalOffset, outWithPadding, + 0, finalBufLen); if (padding != null) { - int padStart = padding.unpad(outWithPadding, 0, totalLen); + int padStart = padding.unpad(outWithPadding, 0, outLen); if (padStart < 0) { throw new BadPaddingException("Given final block not " + "properly padded"); } - totalLen = padStart; + outLen = padStart; } - if ((output.length - outputOffset) < totalLen) { + if (outputCapacity < outLen) { // restore so users can retry with a larger buffer cipher.restore(); throw new ShortBufferException("Output buffer too short: " - + (output.length-outputOffset) - + " bytes given, " + totalLen + + (outputCapacity) + + " bytes given, " + outLen + " bytes needed"); } - for (int i = 0; i < totalLen; i++) { - output[outputOffset + i] = outWithPadding[i]; - } + // copy the result into user-supplied output buffer + System.arraycopy(outWithPadding, 0, output, outputOffset, outLen); } else { // encrypting - totalLen = finalNoPadding(finalBuf, finalOffset, output, - outputOffset, paddedLen); + outLen = finalNoPadding(finalBuf, finalOffset, output, + outputOffset, finalBufLen); } buffered = 0; @@ -833,12 +847,12 @@ if (cipherMode != ECB_MODE) { cipher.reset(); } - return totalLen; + return outLen; } - private int finalNoPadding(byte[] in, int inOff, byte[] out, int outOff, + private int finalNoPadding(byte[] in, int inOfs, byte[] out, int outOfs, int len) - throws IllegalBlockSizeException + throws IllegalBlockSizeException, ShortBufferException { if (in == null || len == 0) return 0; @@ -855,14 +869,13 @@ + " bytes"); } } - + int outLen = 0; if (decrypting) { - cipher.decryptFinal(in, inOff, len, out, outOff); + outLen = cipher.decryptFinal(in, inOfs, len, out, outOfs); } else { - cipher.encryptFinal(in, inOff, len, out, outOff); + outLen = cipher.encryptFinal(in, inOfs, len, out, outOfs); } - - return len; + return outLen; } // Note: Wrap() and Unwrap() are the same in
--- a/src/share/classes/com/sun/crypto/provider/CipherFeedback.java Thu Nov 09 06:45:25 2017 +0000 +++ b/src/share/classes/com/sun/crypto/provider/CipherFeedback.java Fri Nov 10 04:05:13 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -150,9 +150,10 @@ * @param plainLen the length of the input data * @param cipher the buffer for the result * @param cipherOffset the offset in <code>cipher</code> + * @return the length of the encrypted data */ - void encrypt(byte[] plain, int plainOffset, int plainLen, - byte[] cipher, int cipherOffset) + int encrypt(byte[] plain, int plainOffset, int plainLen, + byte[] cipher, int cipherOffset) { int i, len; len = blockSize - numBytes; @@ -194,6 +195,7 @@ } } } + return plainLen; } /** @@ -218,9 +220,10 @@ * @param cipherLen the length of the input data * @param plain the buffer for the result * @param plainOffset the offset in <code>plain</code> + * @return the length of the decrypted data */ - void decrypt(byte[] cipher, int cipherOffset, int cipherLen, - byte[] plain, int plainOffset) + int decrypt(byte[] cipher, int cipherOffset, int cipherLen, + byte[] plain, int plainOffset) { int i, len; len = blockSize - numBytes; @@ -268,5 +271,6 @@ } } } + return cipherLen; } }
--- a/src/share/classes/com/sun/crypto/provider/CipherTextStealing.java Thu Nov 09 06:45:25 2017 +0000 +++ b/src/share/classes/com/sun/crypto/provider/CipherTextStealing.java Fri Nov 10 04:05:13 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -83,9 +83,10 @@ * @param plainLen the length of the input data * @param cipher the buffer for the result * @param cipherOffset the offset in <code>cipher</code> + * @return the number of bytes placed into <code>cipher</code> */ - void encryptFinal(byte[] plain, int plainOffset, int plainLen, - byte[] cipher, int cipherOffset) + int encryptFinal(byte[] plain, int plainOffset, int plainLen, + byte[] cipher, int cipherOffset) throws IllegalBlockSizeException { if (plainLen < blockSize) { @@ -134,6 +135,7 @@ embeddedCipher.encryptBlock(tmp2, 0, cipher, cipherOffset); } } + return plainLen; } /** @@ -158,9 +160,10 @@ * @param cipherLen the length of the input data * @param plain the buffer for the result * @param plainOffset the offset in <code>plain</code> + * @return the number of bytes placed into <code>plain</code> */ - void decryptFinal(byte[] cipher, int cipherOffset, int cipherLen, - byte[] plain, int plainOffset) + int decryptFinal(byte[] cipher, int cipherOffset, int cipherLen, + byte[] plain, int plainOffset) throws IllegalBlockSizeException { if (cipherLen < blockSize) { throw new IllegalBlockSizeException("input is too short!"); @@ -211,5 +214,6 @@ } } } + return cipherLen; } }
--- a/src/share/classes/com/sun/crypto/provider/CounterMode.java Thu Nov 09 06:45:25 2017 +0000 +++ b/src/share/classes/com/sun/crypto/provider/CounterMode.java Fri Nov 10 04:05:13 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 201313, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -149,9 +149,10 @@ * @param len the length of the input data * @param out the buffer for the result * @param outOff the offset in <code>cipher</code> + * @return the length of the encrypted data */ - void encrypt(byte[] in, int inOff, int len, byte[] out, int outOff) { - crypt(in, inOff, len, out, outOff); + int encrypt(byte[] in, int inOff, int len, byte[] out, int outOff) { + return crypt(in, inOff, len, out, outOff); } /** @@ -176,9 +177,10 @@ * @param len the length of the input data * @param out the buffer for the result * @param outOff the offset in <code>plain</code> + * @return the length of the decrypted data */ - void decrypt(byte[] in, int inOff, int len, byte[] out, int outOff) { - crypt(in, inOff, len, out, outOff); + int decrypt(byte[] in, int inOff, int len, byte[] out, int outOff) { + return crypt(in, inOff, len, out, outOff); } /** @@ -197,7 +199,8 @@ * keystream generated by encrypting the counter values. Counter values * are encrypted on demand. */ - private void crypt(byte[] in, int inOff, int len, byte[] out, int outOff) { + private int crypt(byte[] in, int inOff, int len, byte[] out, int outOff) { + int result = len; while (len-- > 0) { if (used >= blockSize) { embeddedCipher.encryptBlock(counter, 0, encryptedCounter, 0); @@ -206,5 +209,6 @@ } out[outOff++] = (byte)(in[inOff++] ^ encryptedCounter[used++]); } + return result; } }
--- a/src/share/classes/com/sun/crypto/provider/ElectronicCodeBook.java Thu Nov 09 06:45:25 2017 +0000 +++ b/src/share/classes/com/sun/crypto/provider/ElectronicCodeBook.java Fri Nov 10 04:05:13 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -115,14 +115,15 @@ * @param len the length of the input data * @param out the buffer for the result * @param outOff the offset in <code>cipher</code> + * @return the length of the encrypted data */ - void encrypt(byte[] in, int inOff, int len, byte[] out, int outOff) { - while (len >= blockSize) { + int encrypt(byte[] in, int inOff, int len, byte[] out, int outOff) { + for (int i = len; i >= blockSize; i -= blockSize) { embeddedCipher.encryptBlock(in, inOff, out, outOff); - len -= blockSize; inOff += blockSize; outOff += blockSize; } + return len; } /** @@ -147,14 +148,14 @@ * @param len the length of the input data * @param out the buffer for the result * @param outOff the offset in <code>plain</code> + * @return the length of the decrypted data */ - void decrypt(byte[] in, int inOff, int len, byte[] out, int outOff) { - while (len >= blockSize) { + int decrypt(byte[] in, int inOff, int len, byte[] out, int outOff) { + for (int i = len; i >= blockSize; i -= blockSize) { embeddedCipher.decryptBlock(in, inOff, out, outOff); - len -= blockSize; inOff += blockSize; outOff += blockSize; } + return len; } - }
--- a/src/share/classes/com/sun/crypto/provider/FeedbackCipher.java Thu Nov 09 06:45:25 2017 +0000 +++ b/src/share/classes/com/sun/crypto/provider/FeedbackCipher.java Fri Nov 10 04:05:13 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ import java.security.InvalidKeyException; import javax.crypto.IllegalBlockSizeException; +import javax.crypto.ShortBufferException; /** * This class represents a block cipher in one of its modes. It wraps @@ -111,6 +112,17 @@ } /** + * @return the number of bytes that are buffered internally inside + * this FeedbackCipher instance. + * @since 1.8 + */ + int getBufferedLength() { + // Currently only AEAD cipher impl, e.g. GCM, buffers data + // internally during decryption mode + return 0; + } + + /** * Resets the iv to its original value. * This is used when doFinal is called in the Cipher class, so that the * cipher can be reused (with its original iv). @@ -133,9 +145,10 @@ * @param plainLen the length of the input data * @param cipher the buffer for the encryption result * @param cipherOffset the offset in <code>cipher</code> + * @return the number of bytes placed into <code>cipher</code> */ - abstract void encrypt(byte[] plain, int plainOffset, int plainLen, - byte[] cipher, int cipherOffset); + abstract int encrypt(byte[] plain, int plainOffset, int plainLen, + byte[] cipher, int cipherOffset); /** * Performs encryption operation for the last time. * @@ -150,12 +163,13 @@ * @param plainLen the length of the input data * @param cipher the buffer for the encryption result * @param cipherOffset the offset in <code>cipher</code> + * @return the number of bytes placed into <code>cipher</code> */ - void encryptFinal(byte[] plain, int plainOffset, int plainLen, - byte[] cipher, int cipherOffset) - throws IllegalBlockSizeException { - encrypt(plain, plainOffset, plainLen, cipher, cipherOffset); - } + int encryptFinal(byte[] plain, int plainOffset, int plainLen, + byte[] cipher, int cipherOffset) + throws IllegalBlockSizeException, ShortBufferException { + return encrypt(plain, plainOffset, plainLen, cipher, cipherOffset); + } /** * Performs decryption operation. * @@ -172,9 +186,10 @@ * @param cipherLen the length of the input data * @param plain the buffer for the decryption result * @param plainOffset the offset in <code>plain</code> + * @return the number of bytes placed into <code>plain</code> */ - abstract void decrypt(byte[] cipher, int cipherOffset, int cipherLen, - byte[] plain, int plainOffset); + abstract int decrypt(byte[] cipher, int cipherOffset, int cipherLen, + byte[] plain, int plainOffset); /** * Performs decryption operation for the last time. @@ -190,10 +205,11 @@ * @param cipherLen the length of the input data * @param plain the buffer for the decryption result * @param plainOffset the offset in <code>plain</code> + * @return the number of bytes placed into <code>plain</code> */ - void decryptFinal(byte[] cipher, int cipherOffset, int cipherLen, - byte[] plain, int plainOffset) - throws IllegalBlockSizeException { - decrypt(cipher, cipherOffset, cipherLen, plain, plainOffset); + int decryptFinal(byte[] cipher, int cipherOffset, int cipherLen, + byte[] plain, int plainOffset) + throws IllegalBlockSizeException, ShortBufferException { + return decrypt(cipher, cipherOffset, cipherLen, plain, plainOffset); } }
--- a/src/share/classes/com/sun/crypto/provider/OutputFeedback.java Thu Nov 09 06:45:25 2017 +0000 +++ b/src/share/classes/com/sun/crypto/provider/OutputFeedback.java Fri Nov 10 04:05:13 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -149,9 +149,10 @@ * @param plainLen the length of the input data * @param cipher the buffer for the result * @param cipherOffset the offset in <code>cipher</code> + * @return the length of the encrypted data */ - void encrypt(byte[] plain, int plainOffset, int plainLen, - byte[] cipher, int cipherOffset) + int encrypt(byte[] plain, int plainOffset, int plainLen, + byte[] cipher, int cipherOffset) { int i; int len = blockSize - numBytes; @@ -195,6 +196,7 @@ System.arraycopy(k, 0, register, len, numBytes); } } + return plainLen; } /** @@ -219,11 +221,12 @@ * @param cipherLen the length of the input data * @param plain the buffer for the result * @param plainOffset the offset in <code>plain</code> + * @return the length of the decrypted data */ - void decrypt(byte[] cipher, int cipherOffset, int cipherLen, + int decrypt(byte[] cipher, int cipherOffset, int cipherLen, byte[] plain, int plainOffset) { // OFB encrypt and decrypt are identical - encrypt(cipher, cipherOffset, cipherLen, plain, plainOffset); + return encrypt(cipher, cipherOffset, cipherLen, plain, plainOffset); } }
--- a/src/share/classes/com/sun/crypto/provider/PCBC.java Thu Nov 09 06:45:25 2017 +0000 +++ b/src/share/classes/com/sun/crypto/provider/PCBC.java Fri Nov 10 04:05:13 2017 +0000 @@ -136,8 +136,8 @@ * @param cipher the buffer for the result * @param cipherOffset the offset in <code>cipher</code> */ - void encrypt(byte[] plain, int plainOffset, int plainLen, - byte[] cipher, int cipherOffset) + int encrypt(byte[] plain, int plainOffset, int plainLen, + byte[] cipher, int cipherOffset) { int i; int endIndex = plainOffset + plainLen; @@ -152,6 +152,7 @@ k[i] = (byte)(plain[i+plainOffset] ^ cipher[i+cipherOffset]); } } + return plainLen; } /** @@ -177,8 +178,8 @@ * @param plain the buffer for the result * @param plainOffset the offset in <code>plain</code> */ - void decrypt(byte[] cipher, int cipherOffset, int cipherLen, - byte[] plain, int plainOffset) + int decrypt(byte[] cipher, int cipherOffset, int cipherLen, + byte[] plain, int plainOffset) { int i; int endIndex = cipherOffset + cipherLen; @@ -194,5 +195,6 @@ k[i] = (byte)(plain[i+plainOffset] ^ cipher[i+cipherOffset]); } } + return cipherLen; } }
--- a/src/share/classes/javax/crypto/CipherSpi.java Thu Nov 09 06:45:25 2017 +0000 +++ b/src/share/classes/javax/crypto/CipherSpi.java Fri Nov 10 04:05:13 2017 +0000 @@ -777,7 +777,9 @@ int total = 0; do { int chunk = Math.min(inLen, inArray.length); - input.get(inArray, 0, chunk); + if (chunk > 0) { + input.get(inArray, 0, chunk); + } int n; if (isUpdate || (inLen != chunk)) { n = engineUpdate(inArray, 0, chunk, outArray, outOfs); @@ -805,8 +807,9 @@ int total = 0; boolean resized = false; do { - int chunk = Math.min(inLen, outSize); - if ((a1 == false) && (resized == false)) { + int chunk = + Math.min(inLen, (outSize == 0? inArray.length : outSize)); + if (!a1 && !resized && chunk > 0) { input.get(inArray, 0, chunk); inOfs = 0; } @@ -820,8 +823,10 @@ resized = false; inOfs += chunk; inLen -= chunk; - output.put(outArray, 0, n); - total += n; + if (n > 0) { + output.put(outArray, 0, n); + total += n; + } } catch (ShortBufferException e) { if (resized) { // we just resized the output buffer, but it still @@ -831,11 +836,13 @@ } // output buffer is too small, realloc and try again resized = true; - int newOut = engineGetOutputSize(chunk); - outArray = new byte[newOut]; + outSize = engineGetOutputSize(chunk); + outArray = new byte[outSize]; } } while (inLen > 0); - input.position(inLimit); + if (a1) { + input.position(inLimit); + } return total; } }