Handle "too small" success from CNG and clear out decryption residuals
authorJeremy Barton <jbarton@microsoft.com>
Tue, 8 Oct 2019 20:37:58 +0000 (13:37 -0700)
committerGitHub <noreply@github.com>
Tue, 8 Oct 2019 20:37:58 +0000 (13:37 -0700)
* When NCryptEncrypt or NCryptDecrypt reports success with a cbResult value that doesn't make sense, normalize the error to NTE_BUFFER_TOO_SMALL.
* When resizing arrays for the array-returning implementation, clear out the temporary arrays to reduce the amount of time they're sitting in memory before the GC clears the memory for reissuance.

Commit migrated from https://github.com/dotnet/corefx/commit/7c586d32edce94c910fc8b402f4adedaa3cf05fd

src/libraries/Common/src/System/Security/Cryptography/RSACng.EncryptDecrypt.cs

index 66b636c..30f92d4 100644 (file)
@@ -241,6 +241,7 @@ namespace System.Security.Cryptography
 
             if (errorCode == ErrorCode.NTE_BUFFER_TOO_SMALL)
             {
+                CryptographicOperations.ZeroMemory(output);
                 output = new byte[numBytesNeeded];
 
                 for (int i = 0; i <= StatusUnsuccessfulRetryCount; i++)
@@ -260,7 +261,13 @@ namespace System.Security.Cryptography
                 throw errorCode.ToCryptographicException();
             }
 
-            Array.Resize(ref output, numBytesNeeded);
+            if (numBytesNeeded != output.Length)
+            {
+                byte[] ret = output.AsSpan(0, numBytesNeeded).ToArray();
+                CryptographicOperations.ZeroMemory(output);
+                output = ret;
+            }
+
             return output;
         }
 
@@ -300,9 +307,17 @@ namespace System.Security.Cryptography
             bool encrypt,
             out int bytesNeeded)
         {
-            return encrypt ?
+            ErrorCode errorCode = encrypt ?
                 Interop.NCrypt.NCryptEncrypt(key, input, input.Length, paddingInfo, output, output.Length, out bytesNeeded, paddingMode) :
                 Interop.NCrypt.NCryptDecrypt(key, input, input.Length, paddingInfo, output, output.Length, out bytesNeeded, paddingMode);
+
+            // Windows 10.1903 can return success when it meant NTE_BUFFER_TOO_SMALL.
+            if (errorCode == ErrorCode.ERROR_SUCCESS && bytesNeeded > output.Length)
+            {
+                errorCode = ErrorCode.NTE_BUFFER_TOO_SMALL;
+            }
+
+            return errorCode;
         }
     }
 #if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS