changeset 8868:d15ed96035d0

8223511: Extended AES support Reviewed-by: phh, mbalao, bae
author andrew
date Thu, 04 Jul 2019 18:20:08 +0100
parents 7b69b8066dbe
children a32dc7400435
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	Mon Jul 15 05:45:27 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	Mon Jul 15 05:45:27 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	Mon Jul 15 05:45:27 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	Mon Jul 15 05:45:27 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	Mon Jul 15 05:45:27 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	Mon Jul 15 05:45:27 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++) {