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; }