From f58a9e81e9e9a8130fa2cff3a8548bc9acb95d4c Mon Sep 17 00:00:00 2001
From: Tesfa Mael <tesfa@wolfssl.com>
Date: Mon, 30 Dec 2019 11:08:22 -0800
Subject: [PATCH] Cryptocell rsa improvements to sign/verify more digest types

---
 wolfcrypt/src/port/arm/cryptoCell.c     | 17 ++++----
 wolfcrypt/src/rsa.c                     | 23 ++++------
 wolfcrypt/src/signature.c               | 56 ++++++++++++++++++++++++-
 wolfssl/wolfcrypt/port/arm/cryptoCell.h |  2 +-
 4 files changed, 73 insertions(+), 25 deletions(-)

diff --git a/wolfcrypt/src/port/arm/cryptoCell.c b/wolfcrypt/src/port/arm/cryptoCell.c
index d6dd17b00..3a6e12513 100644
--- a/wolfcrypt/src/port/arm/cryptoCell.c
+++ b/wolfcrypt/src/port/arm/cryptoCell.c
@@ -146,34 +146,37 @@ CRYS_ECPKI_DomainID_t cc310_mapCurve(int curve_id)
 #endif /* HAVE_ECC */
 
 #ifndef NO_RSA
-CRYS_RSA_HASH_OpMode_t cc310_hashModeRSA(enum wc_HashType hash_type)
+CRYS_RSA_HASH_OpMode_t cc310_hashModeRSA(enum wc_HashType hash_type, int isHashed)
 {
     switch(hash_type)
     {
         case WC_HASH_TYPE_MD5:
         #ifndef NO_MD5
-            return CRYS_RSA_HASH_MD5_mode;
+            return isHashed? CRYS_RSA_After_MD5_mode : CRYS_RSA_HASH_MD5_mode;
         #endif
         case WC_HASH_TYPE_SHA:
         #ifndef NO_SHA
-            return CRYS_RSA_HASH_SHA1_mode;
+            return isHashed? CRYS_RSA_After_SHA1_mode : CRYS_RSA_HASH_SHA1_mode;
         #endif
         case WC_HASH_TYPE_SHA224:
         #ifdef WOLFSSL_SHA224
-            return CRYS_RSA_HASH_SHA224_mode;
+            return isHashed? CRYS_RSA_After_SHA224_mode : CRYS_RSA_HASH_SHA224_mode;
         #endif
         case WC_HASH_TYPE_SHA256:
         #ifndef NO_SHA256
-            return CRYS_RSA_HASH_SHA256_mode;
+            return isHashed? CRYS_RSA_After_SHA256_mode : CRYS_RSA_HASH_SHA256_mode;
         #endif
         case WC_HASH_TYPE_SHA384:
         #ifdef WOLFSSL_SHA384
-            return CRYS_RSA_HASH_SHA384_mode;
+            return isHashed? CRYS_RSA_After_SHA384_mode : CRYS_RSA_HASH_SHA384_mode;
         #endif
         case WC_HASH_TYPE_SHA512:
         #ifdef WOLFSSL_SHA512
-            return CRYS_RSA_HASH_SHA512_mode;
+            return isHashed? CRYS_RSA_After_SHA512_mode : CRYS_RSA_HASH_SHA512_mode;
         #endif
+        case WC_HASH_TYPE_NONE:
+            /* default to SHA256 */
+            return isHashed? CRYS_RSA_After_SHA256_mode : CRYS_RSA_HASH_SHA256_mode;
         default:
             return CRYS_RSA_After_HASH_NOT_KNOWN_mode;
     }
diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c
index 023fb1d66..f3d606899 100644
--- a/wolfcrypt/src/rsa.c
+++ b/wolfcrypt/src/rsa.c
@@ -2522,17 +2522,12 @@ static int cc310_RsaPublicDecrypt(const byte* in, word32 inLen, byte* out,
     return actualOutLen;
 }
 
-static int cc310_RsaSSL_Sign(const byte* in, word32 inLen, byte* out,
-                            word32 outLen, RsaKey* key, enum wc_HashType hash)
+int cc310_RsaSSL_Sign(const byte* in, word32 inLen, byte* out,
+                  word32 outLen, RsaKey* key, CRYS_RSA_HASH_OpMode_t mode)
 {
     CRYSError_t ret = 0;
     uint16_t actualOutLen = outLen*sizeof(byte);
     CRYS_RSAPrivUserContext_t  contextPrivate;
-    CRYS_RSA_HASH_OpMode_t mode = cc310_hashModeRSA(hash);
-
-    if (mode == CRYS_RSA_After_HASH_NOT_KNOWN_mode) {
-        mode = CRYS_RSA_HASH_SHA256_mode;
-    }
 
     ret =  CRYS_RSA_PKCS1v15_Sign(&wc_rndState,
                 wc_rndGenVectFunc,
@@ -2551,16 +2546,12 @@ static int cc310_RsaSSL_Sign(const byte* in, word32 inLen, byte* out,
     return actualOutLen;
 }
 
-static int cc310_RsaSSL_Verify(const byte* in, word32 inLen, byte* sig,
-                               RsaKey* key, enum wc_HashType hash)
+int cc310_RsaSSL_Verify(const byte* in, word32 inLen, byte* sig,
+                               RsaKey* key, CRYS_RSA_HASH_OpMode_t mode)
 {
     CRYSError_t ret = 0;
     CRYS_RSAPubUserContext_t contextPub;
-    CRYS_RSA_HASH_OpMode_t mode = cc310_hashModeRSA(hash);
 
-    if (mode == CRYS_RSA_After_HASH_NOT_KNOWN_mode) {
-        mode = CRYS_RSA_HASH_SHA256_mode;
-    }
     /* verify the signature in the sig pointer */
     ret =  CRYS_RSA_PKCS1v15_Verify(&contextPub,
                 &key->ctx.pubKey,
@@ -2765,7 +2756,8 @@ static int RsaPublicEncryptEx(const byte* in, word32 inLen, byte* out,
         }
         else if (rsa_type == RSA_PRIVATE_ENCRYPT &&
                                          pad_value == RSA_BLOCK_TYPE_1) {
-         return cc310_RsaSSL_Sign(in, inLen, out, outLen, key, hash);
+         return cc310_RsaSSL_Sign(in, inLen, out, outLen, key,
+                                  cc310_hashModeRSA(hash, 0));
         }
     #endif /* WOLFSSL_CRYPTOCELL */
 
@@ -2887,7 +2879,8 @@ static int RsaPrivateDecryptEx(byte* in, word32 inLen, byte* out,
         }
         else if (rsa_type == RSA_PUBLIC_DECRYPT &&
                                             pad_value == RSA_BLOCK_TYPE_1) {
-            return cc310_RsaSSL_Verify(in, inLen, out, key, hash);
+            return cc310_RsaSSL_Verify(in, inLen, out, key,
+                                       cc310_hashModeRSA(hash, 0));
         }
     #endif /* WOLFSSL_CRYPTOCELL */
 
diff --git a/wolfcrypt/src/signature.c b/wolfcrypt/src/signature.c
index 9256eb290..0c260100c 100644
--- a/wolfcrypt/src/signature.c
+++ b/wolfcrypt/src/signature.c
@@ -178,7 +178,15 @@ int wc_SignatureVerifyHash(
 #ifndef NO_RSA
 #if defined(WOLFSSL_CRYPTOCELL)
         /* the signature must propagate to the cryptocell to get verfied */
-        ret = wc_RsaSSL_Verify(hash_data, hash_len, (byte*)sig, sig_len, (RsaKey*)key);
+        if (sig_type == WC_SIGNATURE_TYPE_RSA_W_ENC) {
+            ret = cc310_RsaSSL_Verify(hash_data, hash_len,(byte*)sig, key,
+                                      CRYS_RSA_HASH_SHA256_mode);
+        }
+        else {
+            ret = cc310_RsaSSL_Verify(hash_data, hash_len,(byte*)sig, key,
+                                      CRYS_RSA_After_SHA256_mode);
+        }
+
         if (ret != 0) {
             WOLFSSL_MSG("RSA Signature Verify difference!");
             ret = SIG_VERIFY_E;
@@ -300,9 +308,23 @@ int wc_SignatureVerify(
         }
 
         if (ret == 0) {
+#if defined(WOLFSSL_CRYPTOCELL)
+            if ((sig_type == WC_SIGNATURE_TYPE_RSA)
+                || (sig_type == WC_SIGNATURE_TYPE_RSA_W_ENC)) {
+                if (sig_type == WC_SIGNATURE_TYPE_RSA_W_ENC) {
+                    ret = cc310_RsaSSL_Verify(hash_data, hash_len, sig, key,
+                                              cc310_hashModeRSA(hash_type, 0));
+                }
+                else {
+                    ret = cc310_RsaSSL_Verify(hash_data, hash_len, sig, key,
+                                              cc310_hashModeRSA(hash_type, 1));
+                }
+            }
+#else
             /* Verify signature using hash */
             ret = wc_SignatureVerifyHash(hash_type, sig_type,
                 hash_data, hash_enc_len, sig, sig_len, key, key_len);
+#endif /* WOLFSSL_CRYPTOCELL */
         }
     }
 
@@ -378,6 +400,16 @@ int wc_SignatureGenerateHash_ex(
         case WC_SIGNATURE_TYPE_RSA_W_ENC:
         case WC_SIGNATURE_TYPE_RSA:
 #if !defined(NO_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)
+    #if defined(WOLFSSL_CRYPTOCELL)
+        if (sig_type == WC_SIGNATURE_TYPE_RSA_W_ENC) {
+            ret = cc310_RsaSSL_Sign(hash_data, hash_len, sig, *sig_len, key,
+                                    cc310_hashModeRSA(hash_type, 0));
+            }
+        else {
+            ret = cc310_RsaSSL_Sign(hash_data, hash_len, sig, *sig_len, key,
+                                    cc310_hashModeRSA(hash_type, 1));
+        }
+    #else
             /* Create signature using provided RSA key */
             do {
             #ifdef WOLFSSL_ASYNC_CRYPT
@@ -388,6 +420,7 @@ int wc_SignatureGenerateHash_ex(
                     ret = wc_RsaSSL_Sign(hash_data, hash_len, sig, *sig_len,
                         (RsaKey*)key, rng);
             } while (ret == WC_PENDING_E);
+     #endif /* WOLFSSL_CRYPTOCELL */
             if (ret >= 0) {
                 *sig_len = ret;
                 ret = 0; /* Success */
@@ -484,8 +517,26 @@ int wc_SignatureGenerate_ex(
                 &hash_enc_len);
         #endif
         }
-
         if (ret == 0) {
+#if defined(WOLFSSL_CRYPTOCELL)
+            if ((sig_type == WC_SIGNATURE_TYPE_RSA)
+                || (sig_type == WC_SIGNATURE_TYPE_RSA_W_ENC)) {
+                if (sig_type == WC_SIGNATURE_TYPE_RSA_W_ENC) {
+                    ret = cc310_RsaSSL_Sign(hash_data, hash_len, sig, *sig_len,
+                                         key, cc310_hashModeRSA(hash_type, 0));
+                }
+                else {
+                    ret = cc310_RsaSSL_Sign(hash_data, hash_len, sig, *sig_len,
+                                         key, cc310_hashModeRSA(hash_type, 1));
+                }
+
+                if (ret == *sig_len) {
+                    ret = 0;
+                }
+             }
+        }
+     }
+#else
             /* Generate signature using hash */
             ret = wc_SignatureGenerateHash(hash_type, sig_type,
                 hash_data, hash_enc_len, sig, sig_len, key, key_len, rng);
@@ -496,6 +547,7 @@ int wc_SignatureGenerate_ex(
         ret = wc_SignatureVerifyHash(hash_type, sig_type, hash_data,
             hash_enc_len, sig, *sig_len, key, key_len);
     }
+#endif /* WOLFSSL_CRYPTOCELL */
 
 #ifdef WOLFSSL_SMALL_STACK
     XFREE(hash_data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
diff --git a/wolfssl/wolfcrypt/port/arm/cryptoCell.h b/wolfssl/wolfcrypt/port/arm/cryptoCell.h
index a1bd03115..ac92606ce 100644
--- a/wolfssl/wolfcrypt/port/arm/cryptoCell.h
+++ b/wolfssl/wolfcrypt/port/arm/cryptoCell.h
@@ -78,7 +78,7 @@ extern "C" {
         CRYS_RSAUserPrivKey_t privKey;
         CRYS_RSAUserPubKey_t  pubKey;
     } rsa_context_t;
-CRYS_RSA_HASH_OpMode_t cc310_hashModeRSA(enum wc_HashType hash_type);
+CRYS_RSA_HASH_OpMode_t cc310_hashModeRSA(enum wc_HashType hash_type, int isHashed);
 #endif
 
 #ifdef HAVE_ECC