OpenJDK / jdk8u / jdk8u / jdk
changeset 13608:bdf644065d87
8223511: Extended AES support
Reviewed-by: phh, mbalao, bae
author | andrew |
---|---|
date | Thu, 04 Jul 2019 18:20:08 +0100 |
parents | 1b6a956e362f |
children | 0da125166b2b |
files | src/share/classes/com/sun/crypto/provider/AESCrypt.java src/share/classes/com/sun/crypto/provider/CipherBlockChaining.java src/share/classes/sun/security/provider/DigestBase.java src/share/classes/sun/security/provider/SHA.java src/share/classes/sun/security/provider/SHA2.java src/share/classes/sun/security/provider/SHA5.java |
diffstat | 6 files changed, 163 insertions(+), 14 deletions(-) [+] |
line wrap: on
line diff
--- a/src/share/classes/com/sun/crypto/provider/AESCrypt.java Thu Jul 04 18:18:04 2019 +0100 +++ b/src/share/classes/com/sun/crypto/provider/AESCrypt.java Thu Jul 04 18:20:08 2019 +0100 @@ -38,6 +38,7 @@ import java.security.InvalidKeyException; import java.security.MessageDigest; +import java.util.Objects; /** * Rijndael --pronounced Reindaal-- is a symmetric cipher with a 128-bit @@ -346,7 +347,15 @@ * Encrypt exactly one block of plaintext. */ void encryptBlock(byte[] in, int inOffset, - byte[] out, int outOffset) + byte[] out, int outOffset) { + cryptBlockCheck(in, inOffset); + cryptBlockCheck(out, outOffset); + implEncryptBlock(in, inOffset, out, outOffset); + } + + // Encryption operation. Possibly replaced with a compiler intrinsic. + private void implEncryptBlock(byte[] in, int inOffset, + byte[] out, int outOffset) { int keyOffset = 0; int t0 = ((in[inOffset++] ) << 24 | @@ -412,12 +421,19 @@ out[outOffset ] = (byte)(S[(t2 ) & 0xFF] ^ (tt )); } - /** * Decrypt exactly one block of plaintext. */ void decryptBlock(byte[] in, int inOffset, - byte[] out, int outOffset) + byte[] out, int outOffset) { + cryptBlockCheck(in, inOffset); + cryptBlockCheck(out, outOffset); + implDecryptBlock(in, inOffset, out, outOffset); + } + + // Decrypt operation. Possibly replaced with a compiler intrinsic. + private void implDecryptBlock(byte[] in, int inOffset, + byte[] out, int outOffset) { int keyOffset = 4; int t0 = ((in[inOffset++] ) << 24 | @@ -572,6 +588,25 @@ out[outOffset ] = (byte)(Si[(a0 ) & 0xFF] ^ (t1 )); } + // Used to perform all checks required by the Java semantics + // (i.e., null checks and bounds checks) on the input parameters + // to encryptBlock and to decryptBlock. + // Normally, the Java Runtime performs these checks, however, as + // encryptBlock and decryptBlock are possibly replaced with + // compiler intrinsics, the JDK performs the required checks instead. + // Does not check accesses to class-internal (private) arrays. + private static void cryptBlockCheck(byte[] array, int offset) { + Objects.requireNonNull(array); + + if (offset < 0 || offset >= array.length) { + throw new ArrayIndexOutOfBoundsException(offset); + } + + int largestIndex = offset + AES_BLOCK_SIZE - 1; + if (largestIndex < 0 || largestIndex >= array.length) { + throw new ArrayIndexOutOfBoundsException(largestIndex); + } + } /** * Expand a user-supplied key material into a session key.
--- a/src/share/classes/com/sun/crypto/provider/CipherBlockChaining.java Thu Jul 04 18:18:04 2019 +0100 +++ b/src/share/classes/com/sun/crypto/provider/CipherBlockChaining.java Thu Jul 04 18:20:08 2019 +0100 @@ -27,6 +27,7 @@ import java.security.InvalidKeyException; import java.security.ProviderException; +import java.util.Objects; /** @@ -138,18 +139,24 @@ * @return the length of the encrypted data */ int encrypt(byte[] plain, int plainOffset, int plainLen, - byte[] cipher, int cipherOffset) - { + byte[] cipher, int cipherOffset) { if (plainLen <= 0) { return plainLen; } - if ((plainLen % blockSize) != 0) { - throw new ProviderException("Internal error in input buffering"); - } + cryptBlockSizeCheck(plainLen); + cryptNullAndBoundsCheck(plain, plainOffset, plainLen); + cryptNullAndBoundsCheck(cipher, cipherOffset, plainLen); + return implEncrypt(plain, plainOffset, plainLen, + cipher, cipherOffset); + } + + private int implEncrypt(byte[] plain, int plainOffset, int plainLen, + byte[] cipher, int cipherOffset) + { int endIndex = plainOffset + plainLen; for (; plainOffset < endIndex; - plainOffset+=blockSize, cipherOffset += blockSize) { + plainOffset += blockSize, cipherOffset += blockSize) { for (int i = 0; i < blockSize; i++) { k[i] = (byte)(plain[i + plainOffset] ^ r[i]); } @@ -182,14 +189,19 @@ * @return the length of the decrypted data */ int decrypt(byte[] cipher, int cipherOffset, int cipherLen, - byte[] plain, int plainOffset) - { + byte[] plain, int plainOffset) { if (cipherLen <= 0) { return cipherLen; } - if ((cipherLen % blockSize) != 0) { - throw new ProviderException("Internal error in input buffering"); - } + cryptBlockSizeCheck(cipherLen); + cryptNullAndBoundsCheck(cipher, cipherOffset, cipherLen); + cryptNullAndBoundsCheck(plain, plainOffset, cipherLen); + return implDecrypt(cipher, cipherOffset, cipherLen, plain, plainOffset); + } + + private int implDecrypt(byte[] cipher, int cipherOffset, int cipherLen, + byte[] plain, int plainOffset) + { int endIndex = cipherOffset + cipherLen; for (; cipherOffset < endIndex; @@ -202,4 +214,23 @@ } return cipherLen; } + + private void cryptBlockSizeCheck(int len) { + if ((len % blockSize) != 0) { + throw new ProviderException("Internal error in input buffering"); + } + } + + private static void cryptNullAndBoundsCheck(byte[] array, int offset, int len) { + Objects.requireNonNull(array); + + if (offset < 0 || offset >= array.length) { + throw new ArrayIndexOutOfBoundsException(offset); + } + + int endIndex = offset + len - 1; + if (endIndex < 0 || endIndex >= array.length) { + throw new ArrayIndexOutOfBoundsException(endIndex); + } + } }
--- a/src/share/classes/sun/security/provider/DigestBase.java Thu Jul 04 18:18:04 2019 +0100 +++ b/src/share/classes/sun/security/provider/DigestBase.java Thu Jul 04 18:20:08 2019 +0100 @@ -29,6 +29,7 @@ import java.security.DigestException; import java.security.ProviderException; import java.util.Arrays; +import java.util.Objects; /** * Common base message digest implementation for the Sun provider. @@ -137,12 +138,35 @@ // compress complete blocks private int implCompressMultiBlock(byte[] b, int ofs, int limit) { + implCompressMultiBlockCheck(b, ofs, limit); + return implCompressMultiBlock0(b, ofs, limit); + } + + private int implCompressMultiBlock0(byte[] b, int ofs, int limit) { for (; ofs <= limit; ofs += blockSize) { implCompress(b, ofs); } return ofs; } + private void implCompressMultiBlockCheck(byte[] b, int ofs, int limit) { + if (limit < 0) { + return; // not an error because implCompressMultiBlockImpl won't execute if limit < 0 + // and an exception is thrown if ofs < 0. + } + + Objects.requireNonNull(b); + + if (ofs < 0 || ofs >= b.length) { + throw new ArrayIndexOutOfBoundsException(ofs); + } + + int endIndex = (limit / blockSize) * blockSize + blockSize - 1; + if (endIndex >= b.length) { + throw new ArrayIndexOutOfBoundsException(endIndex); + } + } + // reset this object. See JCA doc. protected final void engineReset() { if (bytesProcessed == 0) {
--- a/src/share/classes/sun/security/provider/SHA.java Thu Jul 04 18:18:04 2019 +0100 +++ b/src/share/classes/sun/security/provider/SHA.java Thu Jul 04 18:20:08 2019 +0100 @@ -27,6 +27,8 @@ import java.util.Arrays; +import java.util.Objects; + import static sun.security.provider.ByteArrayAccess.*; /** @@ -123,8 +125,26 @@ * "old" NIST Secure Hash Algorithm. */ void implCompress(byte[] buf, int ofs) { + implCompressCheck(buf, ofs); + implCompress0(buf, ofs); + } + + private void implCompressCheck(byte[] buf, int ofs) { + Objects.requireNonNull(buf); + + // The checks performed by the method 'b2iBig64' + // are sufficient for the case when the method + // 'implCompressImpl' is replaced with a compiler + // intrinsic. b2iBig64(buf, ofs, W); + } + // The method 'implCompressImpl seems not to use its parameters. + // The method can, however, be replaced with a compiler intrinsic + // that operates directly on the array 'buf' (starting from + // offset 'ofs') and not on array 'W', therefore 'buf' and 'ofs' + // must be passed as parameter to the method. + private void implCompress0(byte[] buf, int ofs) { // The first 16 ints have the byte stream, compute the rest of // the buffer for (int t = 16; t <= 79; t++) {
--- a/src/share/classes/sun/security/provider/SHA2.java Thu Jul 04 18:18:04 2019 +0100 +++ b/src/share/classes/sun/security/provider/SHA2.java Thu Jul 04 18:20:08 2019 +0100 @@ -27,6 +27,8 @@ import java.util.Arrays; +import java.util.Objects; + import static sun.security.provider.ByteArrayAccess.*; /** @@ -193,8 +195,26 @@ * Process the current block to update the state variable state. */ void implCompress(byte[] buf, int ofs) { + implCompressCheck(buf, ofs); + implCompress0(buf, ofs); + } + + private void implCompressCheck(byte[] buf, int ofs) { + Objects.requireNonNull(buf); + + // The checks performed by the method 'b2iBig64' + // are sufficient for the case when the method + // 'implCompressImpl' is replaced with a compiler + // intrinsic. b2iBig64(buf, ofs, W); + } + // The method 'implCompressImpl' seems not to use its parameters. + // The method can, however, be replaced with a compiler intrinsic + // that operates directly on the array 'buf' (starting from + // offset 'ofs') and not on array 'W', therefore 'buf' and 'ofs' + // must be passed as parameter to the method. + private void implCompress0(byte[] buf, int ofs) { // The first 16 ints are from the byte stream, compute the rest of // the W[]'s for (int t = 16; t < ITERATION; t++) {
--- a/src/share/classes/sun/security/provider/SHA5.java Thu Jul 04 18:18:04 2019 +0100 +++ b/src/share/classes/sun/security/provider/SHA5.java Thu Jul 04 18:20:08 2019 +0100 @@ -26,6 +26,7 @@ package sun.security.provider; import java.util.Arrays; +import java.util.Objects; import static sun.security.provider.ByteArrayAccess.*; @@ -209,8 +210,26 @@ * "old" NIST Secure Hash Algorithm. */ final void implCompress(byte[] buf, int ofs) { + implCompressCheck(buf, ofs); + implCompress0(buf, ofs); + } + + private void implCompressCheck(byte[] buf, int ofs) { + Objects.requireNonNull(buf); + + // The checks performed by the method 'b2iBig128' + // are sufficient for the case when the method + // 'implCompressImpl' is replaced with a compiler + // intrinsic. b2lBig128(buf, ofs, W); + } + // The method 'implCompressImpl' seems not to use its parameters. + // The method can, however, be replaced with a compiler intrinsic + // that operates directly on the array 'buf' (starting from + // offset 'ofs') and not on array 'W', therefore 'buf' and 'ofs' + // must be passed as parameter to the method. + private final void implCompress0(byte[] buf, int ofs) { // The first 16 longs are from the byte stream, compute the rest of // the W[]'s for (int t = 16; t < ITERATION; t++) {