changeset 14434:472688d32092

8258419: RSA cipher buffer cleanup Reviewed-by: phh, sgehwolf
author andrew
date Tue, 04 May 2021 05:52:35 +0100
parents 01352c9f8c07
children 73584fe56769
files src/share/classes/com/sun/crypto/provider/RSACipher.java src/share/classes/sun/security/rsa/RSACore.java src/share/classes/sun/security/rsa/RSAPadding.java
diffstat 3 files changed, 70 insertions(+), 53 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/crypto/provider/RSACipher.java	Thu Jun 21 10:15:41 2018 +0800
+++ b/src/share/classes/com/sun/crypto/provider/RSACipher.java	Tue May 04 05:52:35 2021 +0100
@@ -25,6 +25,7 @@
 
 package com.sun.crypto.provider;
 
+import java.util.Arrays;
 import java.util.Locale;
 
 import java.security.*;
@@ -346,28 +347,40 @@
             throw new IllegalBlockSizeException("Data must not be longer "
                 + "than " + buffer.length + " bytes");
         }
+        byte[] paddingCopy = null;
+        byte[] result = null;
         try {
-            byte[] data;
             switch (mode) {
             case MODE_SIGN:
-                data = padding.pad(buffer, 0, bufOfs);
-                return RSACore.rsa(data, privateKey, true);
+                paddingCopy = padding.pad(buffer, 0, bufOfs);
+                result = RSACore.rsa(paddingCopy, privateKey, true);
+                break;
             case MODE_VERIFY:
                 byte[] verifyBuffer = RSACore.convert(buffer, 0, bufOfs);
-                data = RSACore.rsa(verifyBuffer, publicKey);
-                return padding.unpad(data);
+                paddingCopy = RSACore.rsa(verifyBuffer, publicKey);
+                result = padding.unpad(paddingCopy);
+                break;
             case MODE_ENCRYPT:
-                data = padding.pad(buffer, 0, bufOfs);
-                return RSACore.rsa(data, publicKey);
+                paddingCopy = padding.pad(buffer, 0, bufOfs);
+                result = RSACore.rsa(paddingCopy, publicKey);
+                break;
             case MODE_DECRYPT:
                 byte[] decryptBuffer = RSACore.convert(buffer, 0, bufOfs);
-                data = RSACore.rsa(decryptBuffer, privateKey, false);
-                return padding.unpad(data);
+                paddingCopy = RSACore.rsa(decryptBuffer, privateKey, false);
+                result = padding.unpad(paddingCopy);
+                break;
             default:
                 throw new AssertionError("Internal error");
             }
+            return result;
         } finally {
+            Arrays.fill(buffer, 0, bufOfs, (byte)0);
             bufOfs = 0;
+            if (paddingCopy != null             // will not happen
+                    && paddingCopy != buffer    // already cleaned
+                    && paddingCopy != result) { // DO NOT CLEAN, THIS IS RESULT!
+                Arrays.fill(paddingCopy, (byte)0);
+            }
         }
     }
 
@@ -403,6 +416,7 @@
         byte[] result = doFinal();
         int n = result.length;
         System.arraycopy(result, 0, out, outOfs, n);
+        Arrays.fill(result, (byte)0);
         return n;
     }
 
@@ -413,15 +427,19 @@
         if ((encoded == null) || (encoded.length == 0)) {
             throw new InvalidKeyException("Could not obtain encoded key");
         }
-        if (encoded.length > buffer.length) {
-            throw new InvalidKeyException("Key is too long for wrapping");
-        }
-        update(encoded, 0, encoded.length);
         try {
-            return doFinal();
-        } catch (BadPaddingException e) {
-            // should not occur
-            throw new InvalidKeyException("Wrapping failed", e);
+            if (encoded.length > buffer.length) {
+                throw new InvalidKeyException("Key is too long for wrapping");
+            }
+            update(encoded, 0, encoded.length);
+            try {
+                return doFinal();
+            } catch (BadPaddingException e) {
+                // should not occur
+                throw new InvalidKeyException("Wrapping failed", e);
+            }
+        } finally {
+            Arrays.fill(encoded, (byte)0);
         }
     }
 
@@ -451,20 +469,26 @@
             throw new InvalidKeyException("Unwrapping failed", e);
         }
 
-        if (isTlsRsaPremasterSecret) {
-            if (!(spec instanceof TlsRsaPremasterSecretParameterSpec)) {
-                throw new IllegalStateException(
-                        "No TlsRsaPremasterSecretParameterSpec specified");
+        try {
+            if (isTlsRsaPremasterSecret) {
+                if (!(spec instanceof TlsRsaPremasterSecretParameterSpec)) {
+                    throw new IllegalStateException(
+                            "No TlsRsaPremasterSecretParameterSpec specified");
+                }
+
+                // polish the TLS premaster secret
+                encoded = KeyUtil.checkTlsPreMasterSecretKey(
+                        ((TlsRsaPremasterSecretParameterSpec) spec).getClientVersion(),
+                        ((TlsRsaPremasterSecretParameterSpec) spec).getServerVersion(),
+                        random, encoded, (failover != null));
             }
 
-            // polish the TLS premaster secret
-            encoded = KeyUtil.checkTlsPreMasterSecretKey(
-                ((TlsRsaPremasterSecretParameterSpec)spec).getClientVersion(),
-                ((TlsRsaPremasterSecretParameterSpec)spec).getServerVersion(),
-                random, encoded, (failover != null));
+            return ConstructKeys.constructKey(encoded, algorithm, type);
+        } finally {
+            if (encoded != null) {
+                Arrays.fill(encoded, (byte) 0);
+            }
         }
-
-        return ConstructKeys.constructKey(encoded, algorithm, type);
     }
 
     // see JCE spec
--- a/src/share/classes/sun/security/rsa/RSACore.java	Thu Jun 21 10:15:41 2018 +0800
+++ b/src/share/classes/sun/security/rsa/RSACore.java	Tue May 04 05:52:35 2021 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2020, 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
@@ -231,12 +231,14 @@
         if ((n == len + 1) && (b[0] == 0)) {
             byte[] t = new byte[len];
             System.arraycopy(b, 1, t, 0, len);
+            Arrays.fill(b, (byte)0);
             return t;
         }
         // must be smaller
         assert (n < len);
         byte[] t = new byte[len];
         System.arraycopy(b, 0, t, (len - n), n);
+        Arrays.fill(b, (byte)0);
         return t;
     }
 
--- a/src/share/classes/sun/security/rsa/RSAPadding.java	Thu Jun 21 10:15:41 2018 +0800
+++ b/src/share/classes/sun/security/rsa/RSAPadding.java	Tue May 04 05:52:35 2021 +0100
@@ -238,28 +238,28 @@
     /**
      * Pad the data and return the padded block.
      */
-    public byte[] pad(byte[] data, int ofs, int len)
-            throws BadPaddingException {
-        return pad(RSACore.convert(data, ofs, len));
+    public byte[] pad(byte[] data) throws BadPaddingException {
+        return pad(data, 0, data.length);
     }
 
     /**
      * Pad the data and return the padded block.
      */
-    public byte[] pad(byte[] data) throws BadPaddingException {
-        if (data.length > maxDataSize) {
+    public byte[] pad(byte[] data, int ofs, int len)
+            throws BadPaddingException {
+        if (len > maxDataSize) {
             throw new BadPaddingException("Data must be shorter than "
                 + (maxDataSize + 1) + " bytes but received "
-                + data.length + " bytes.");
+                + len + " bytes.");
         }
         switch (type) {
         case PAD_NONE:
-            return data;
+            return RSACore.convert(data, ofs, len);
         case PAD_BLOCKTYPE_1:
         case PAD_BLOCKTYPE_2:
-            return padV15(data);
+            return padV15(data, ofs, len);
         case PAD_OAEP_MGF1:
-            return padOAEP(data);
+            return padOAEP(data, ofs, len);
         default:
             throw new AssertionError();
         }
@@ -268,14 +268,6 @@
     /**
      * Unpad the padded block and return the data.
      */
-    public byte[] unpad(byte[] padded, int ofs, int len)
-            throws BadPaddingException {
-        return unpad(RSACore.convert(padded, ofs, len));
-    }
-
-    /**
-     * Unpad the padded block and return the data.
-     */
     public byte[] unpad(byte[] padded) throws BadPaddingException {
         if (padded.length != paddedSize) {
             throw new BadPaddingException("Decryption error." +
@@ -298,11 +290,10 @@
     /**
      * PKCS#1 v1.5 padding (blocktype 1 and 2).
      */
-    private byte[] padV15(byte[] data) throws BadPaddingException {
+    private byte[] padV15(byte[] data, int ofs, int len) throws BadPaddingException {
         byte[] padded = new byte[paddedSize];
-        System.arraycopy(data, 0, padded, paddedSize - data.length,
-            data.length);
-        int psSize = paddedSize - 3 - data.length;
+        System.arraycopy(data, ofs, padded, paddedSize - len, len);
+        int psSize = paddedSize - 3 - len;
         int k = 0;
         padded[k++] = 0;
         padded[k++] = (byte)type;
@@ -389,7 +380,7 @@
      * PKCS#1 v2.0 OAEP padding (MGF1).
      * Paragraph references refer to PKCS#1 v2.1 (June 14, 2002)
      */
-    private byte[] padOAEP(byte[] M) throws BadPaddingException {
+    private byte[] padOAEP(byte[] M, int ofs, int len) throws BadPaddingException {
         if (random == null) {
             random = JCAUtil.getSecureRandom();
         }
@@ -416,7 +407,7 @@
         int dbLen = EM.length - dbStart;
 
         // start of message M in EM
-        int mStart = paddedSize - M.length;
+        int mStart = paddedSize - len;
 
         // build DB
         // 2.b: Concatenate lHash, PS, a single octet with hexadecimal value
@@ -425,7 +416,7 @@
         // (note that PS is all zeros)
         System.arraycopy(lHash, 0, EM, dbStart, hLen);
         EM[mStart - 1] = 1;
-        System.arraycopy(M, 0, EM, mStart, M.length);
+        System.arraycopy(M, ofs, EM, mStart, len);
 
         // produce maskedDB
         mgf.generateAndXor(EM, seedStart, seedLen, dbLen, EM, dbStart);