rsaenh: fix buffer overrun in RSAENH_CPVerifySignature and add parameters validity checks in RSAENH_CPEncrypt, RSAENH_CPDecrypt and RSAENH_CPSignHash

Mounir IDRASSI mounir.idrassi at idrix.fr
Sat May 12 11:56:26 CDT 2007


Hi,
This patch fixes the following issues :
    - RSAENH_CPVerifySignature: the signature length was not checked.
This leads to a buffer overrun when the signature is smaller than the
key length.
    - RSAENH_CPEncrypt and RSAENH_CPSignHash: some parameters are not
validated before being used. This leads to crashes when invalid input is
given.
    - RSAENH_CPDecrypt: some parameters are not validated before being
used. Padding in case of block ciphers was removed whithout beeing
checked: In case of corrupted ciphered input, no error is reported and
output data length is set to an invalid value.

Mounir IDRASSI
IDRIX - Cryptography and IT Security Experts
http://www.idrix.fr

-------------- next part --------------
>From 346e62d41d03aa546ba6fa66db38638812026706 Mon Sep 17 00:00:00 2001
From: Mounir IDRASSI <mounir.idrassi at idrix.fr>
Date: Sat, 12 May 2007 18:04:45 +0200
Subject: rsaenh: fix buffer overrun in RSAENH_CPVerifySignature and add parameters validity checks in RSAENH_CPEncrypt, RSAENH_CPDecrypt and RSAENH_CPSignHash

---
 dlls/rsaenh/rsaenh.c |  103 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 102 insertions(+), 1 deletions(-)

diff --git a/dlls/rsaenh/rsaenh.c b/dlls/rsaenh/rsaenh.c
index 3e7ac8e..1857b1b 100644
--- a/dlls/rsaenh/rsaenh.c
+++ b/dlls/rsaenh/rsaenh.c
@@ -1883,6 +1883,12 @@ BOOL WINAPI RSAENH_CPEncrypt(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash,
         return FALSE;
     }
 
+    if (!pdwDataLen)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
     if (pCryptKey->dwState == RSAENH_KEYSTATE_IDLE) 
         pCryptKey->dwState = RSAENH_KEYSTATE_ENCRYPTING;
 
@@ -2035,6 +2041,12 @@ BOOL WINAPI RSAENH_CPDecrypt(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash,
         return FALSE;
     }
 
+    if (!pdwDataLen)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
     if (pCryptKey->dwState == RSAENH_KEYSTATE_IDLE) 
         pCryptKey->dwState = RSAENH_KEYSTATE_DECRYPTING;
 
@@ -2047,6 +2059,32 @@ BOOL WINAPI RSAENH_CPDecrypt(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash,
     dwMax=*pdwDataLen;
 
     if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_BLOCK) {
+        if (dwMax % pCryptKey->dwBlockLen)
+        {
+            SetLastError(NTE_BAD_DATA);
+            return FALSE;
+        }
+        
+        if (Final)
+        {
+            if (!dwMax)
+            {
+                SetLastError(NTE_BAD_LEN);
+                return FALSE;
+            }
+
+            if (!pbData)
+            {
+                SetLastError(NTE_BAD_DATA);
+                return FALSE;
+            }
+        }
+        else if (!pbData && dwMax)
+        {
+            SetLastError(ERROR_INVALID_PARAMETER);
+            return FALSE;
+        }
+
         for (i=0, in=pbData; i<*pdwDataLen; i+=pCryptKey->dwBlockLen, in+=pCryptKey->dwBlockLen) {
             switch (pCryptKey->dwMode) {
                 case CRYPT_MODE_ECB:
@@ -2078,7 +2116,33 @@ BOOL WINAPI RSAENH_CPDecrypt(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash,
             }
             memcpy(in, out, pCryptKey->dwBlockLen);
         }
-        if (Final) *pdwDataLen -= pbData[*pdwDataLen-1]; 
+        
+        if (Final)
+        {
+            /* check that the padding is correct */
+            LPBYTE pbPaddedData = &pbData[*pdwDataLen-1];
+            BYTE bPadByte = *pbPaddedData;
+
+            if (bPadByte > 0x08)
+            {
+                SetLastError(NTE_BAD_DATA);
+                return FALSE;
+            }
+
+            i = 1;
+            while (i < bPadByte)
+            {    
+                pbPaddedData--;
+                if (*pbPaddedData != bPadByte)
+                {
+                    SetLastError(NTE_BAD_DATA);
+                    return FALSE;
+                }
+                i++;
+            }
+            /* everything is ok. write the output length*/    
+            *pdwDataLen -= bPadByte;
+        }
 
     } else if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_STREAM) {
         encrypt_stream_impl(pCryptKey->aiAlgid, &pCryptKey->context, pbData, *pdwDataLen);
@@ -2087,6 +2151,25 @@ BOOL WINAPI RSAENH_CPDecrypt(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash,
             SetLastError(NTE_BAD_KEY);
             return FALSE;
         }
+
+        if (!dwMax)
+        {
+            SetLastError(NTE_BAD_LEN);
+            return FALSE;
+        }
+
+        if (!pbData)
+        {
+            SetLastError(ERROR_INVALID_PARAMETER);
+            return FALSE;
+        }
+
+        if (dwMax != pCryptKey->dwBlockLen)
+        {
+            SetLastError(NTE_BAD_DATA);
+            return FALSE;
+        }
+
         encrypt_block_impl(pCryptKey->aiAlgid, PK_PRIVATE, &pCryptKey->context, pbData, pbData, RSAENH_DECRYPT);
         if (!unpad_data(pbData, pCryptKey->dwBlockLen, pbData, pdwDataLen, dwFlags)) return FALSE;
         Final = TRUE;
@@ -3526,6 +3609,12 @@ BOOL WINAPI RSAENH_CPSignHash(HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwKeySpe
         return FALSE;
     }
 
+    if (!hHash)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
     if (!pbSignature) {
         *pdwSigLen = pCryptKey->dwKeyLen;
         return TRUE;
@@ -3611,6 +3700,18 @@ BOOL WINAPI RSAENH_CPVerifySignature(HCRYPTPROV hProv, HCRYPTHASH hHash, CONST B
         return FALSE;
     }
 
+    if (!hHash || !pbSignature)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    if (dwSigLen != pCryptKey->dwKeyLen)
+    {
+        SetLastError(NTE_BAD_SIGNATURE);
+        return FALSE;
+    }
+
     if (sDescription) {
         if (!RSAENH_CPHashData(hProv, hHash, (CONST BYTE*)sDescription, 
                                 (DWORD)lstrlenW(sDescription)*sizeof(WCHAR), 0))
-- 
1.4.4.2



More information about the wine-patches mailing list