Rewrite RSA_verify_PKCS1_PSS_mgf1 with size_t.

Splitting this out from most of the -Wshorten-64-to-32 fixes since it
non-trivially rewrites the function. While I'm here, move variable
declarations slightly closer to their use and document how the salt
check differs from the spec.

Bug: 516
Change-Id: I2e53afecb8ba720fd8c02da504b56c829c20c93b
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/54206
Commit-Queue: David Benjamin <davidben@google.com>
Auto-Submit: David Benjamin <davidben@google.com>
Reviewed-by: Bob Beck <bbe@google.com>
diff --git a/crypto/fipsmodule/rsa/padding.c b/crypto/fipsmodule/rsa/padding.c
index 605647a..0dafed4 100644
--- a/crypto/fipsmodule/rsa/padding.c
+++ b/crypto/fipsmodule/rsa/padding.c
@@ -489,29 +489,23 @@
 int RSA_verify_PKCS1_PSS_mgf1(const RSA *rsa, const uint8_t *mHash,
                               const EVP_MD *Hash, const EVP_MD *mgf1Hash,
                               const uint8_t *EM, int sLen) {
-  int i;
-  int ret = 0;
-  int maskedDBLen, MSBits, emLen;
-  size_t hLen;
-  const uint8_t *H;
-  uint8_t *DB = NULL;
-  EVP_MD_CTX ctx;
-  uint8_t H_[EVP_MAX_MD_SIZE];
-  EVP_MD_CTX_init(&ctx);
-
   if (mgf1Hash == NULL) {
     mgf1Hash = Hash;
   }
 
-  hLen = EVP_MD_size(Hash);
+  int ret = 0;
+  uint8_t *DB = NULL;
+  EVP_MD_CTX ctx;
+  EVP_MD_CTX_init(&ctx);
   FIPS_service_indicator_lock_state();
 
   // Negative sLen has special meanings:
   //	-1	sLen == hLen
   //	-2	salt length is autorecovered from signature
   //	-N	reserved
+  size_t hLen = EVP_MD_size(Hash);
   if (sLen == -1) {
-    sLen = hLen;
+    sLen = (int)hLen;
   } else if (sLen == -2) {
     sLen = -2;
   } else if (sLen < -2) {
@@ -519,8 +513,8 @@
     goto err;
   }
 
-  MSBits = (BN_num_bits(rsa->n) - 1) & 0x7;
-  emLen = RSA_size(rsa);
+  unsigned MSBits = (BN_num_bits(rsa->n) - 1) & 0x7;
+  size_t emLen = RSA_size(rsa);
   if (EM[0] & (0xFF << MSBits)) {
     OPENSSL_PUT_ERROR(RSA, RSA_R_FIRST_OCTET_INVALID);
     goto err;
@@ -529,8 +523,9 @@
     EM++;
     emLen--;
   }
-  if (emLen < (int)hLen + 2 || emLen < ((int)hLen + sLen + 2)) {
-    // sLen can be small negative
+  // |sLen| may be -2 for the non-standard salt length recovery mode.
+  if (emLen < hLen + 2 ||
+      (sLen >= 0 && emLen < hLen + (size_t)sLen + 2)) {
     OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE);
     goto err;
   }
@@ -538,8 +533,8 @@
     OPENSSL_PUT_ERROR(RSA, RSA_R_LAST_OCTET_INVALID);
     goto err;
   }
-  maskedDBLen = emLen - hLen - 1;
-  H = EM + maskedDBLen;
+  size_t maskedDBLen = emLen - hLen - 1;
+  const uint8_t *H = EM + maskedDBLen;
   DB = OPENSSL_malloc(maskedDBLen);
   if (!DB) {
     OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
@@ -548,42 +543,49 @@
   if (!PKCS1_MGF1(DB, maskedDBLen, H, hLen, mgf1Hash)) {
     goto err;
   }
-  for (i = 0; i < maskedDBLen; i++) {
+  for (size_t i = 0; i < maskedDBLen; i++) {
     DB[i] ^= EM[i];
   }
   if (MSBits) {
     DB[0] &= 0xFF >> (8 - MSBits);
   }
-  for (i = 0; DB[i] == 0 && i < (maskedDBLen - 1); i++) {
+  // This step differs slightly from EMSA-PSS-VERIFY (RFC 8017) step 10 because
+  // it accepts a non-standard salt recovery flow. DB should be some number of
+  // zeros, a one, then the salt.
+  size_t salt_start;
+  for (salt_start = 0; DB[salt_start] == 0 && salt_start < maskedDBLen - 1;
+       salt_start++) {
     ;
   }
-  if (DB[i++] != 0x1) {
+  if (DB[salt_start] != 0x1) {
     OPENSSL_PUT_ERROR(RSA, RSA_R_SLEN_RECOVERY_FAILED);
     goto err;
   }
-  if (sLen >= 0 && (maskedDBLen - i) != sLen) {
+  salt_start++;
+  // If a salt length was specified, check it matches.
+  if (sLen >= 0 && maskedDBLen - salt_start != (size_t)sLen) {
     OPENSSL_PUT_ERROR(RSA, RSA_R_SLEN_CHECK_FAILED);
     goto err;
   }
+  uint8_t H_[EVP_MAX_MD_SIZE];
   if (!EVP_DigestInit_ex(&ctx, Hash, NULL) ||
       !EVP_DigestUpdate(&ctx, kPSSZeroes, sizeof(kPSSZeroes)) ||
       !EVP_DigestUpdate(&ctx, mHash, hLen) ||
-      !EVP_DigestUpdate(&ctx, DB + i, maskedDBLen - i) ||
+      !EVP_DigestUpdate(&ctx, DB + salt_start, maskedDBLen - salt_start) ||
       !EVP_DigestFinal_ex(&ctx, H_, NULL)) {
     goto err;
   }
-  if (OPENSSL_memcmp(H_, H, hLen)) {
+  if (OPENSSL_memcmp(H_, H, hLen) != 0) {
     OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_SIGNATURE);
-    ret = 0;
-  } else {
-    ret = 1;
+    goto err;
   }
 
+  ret = 1;
+
 err:
   OPENSSL_free(DB);
   EVP_MD_CTX_cleanup(&ctx);
   FIPS_service_indicator_unlock_state();
-
   return ret;
 }