diff options
author | Vadim Sukhomlinov <sukhomlinov@google.com> | 2021-10-05 18:34:26 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2021-10-06 02:56:18 +0000 |
commit | 0fe84e193c648d30a0e45b2332bd4854a3e1d8bb (patch) | |
tree | adcbb17b592dbea0723ba493824ac36e1d77ca7c /board/cr50 | |
parent | 7f5d2a30a4add6125d2ecf33e14efdbccc0e8087 (diff) | |
download | chrome-ec-0fe84e193c648d30a0e45b2332bd4854a3e1d8bb.tar.gz |
cr50: update RSA public API to block access on FIPS errors
1. Switched RSA public and internal functions to use enum dcrypto_result
2. Added checks for FIPS errors.
3. Updated call sites to properly handle result values.
BUG=b:197893750
TEST=make BOARD=cr50 CRYPTO_TEST=1; test/tpm_test/tpm_test.py
TCG tests:
---------------------- Test Result Summary -----------------------------
Test executed on: Mon Oct 5 18:26:07 2021
Performed Tests: 248
Passed Tests: 248
Failed Tests: 0
Errors: 0
Warnings: 0
========================================================================
Signed-off-by: Vadim Sukhomlinov <sukhomlinov@google.com>
Change-Id: I23d391322e55b541d72388b2a4661991a61dd020
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3207348
Reviewed-by: Vadim Sukhomlinov <sukhomlinov@chromium.org>
Reviewed-by: Andrey Pronin <apronin@chromium.org>
Commit-Queue: Vadim Sukhomlinov <sukhomlinov@chromium.org>
Commit-Queue: Andrey Pronin <apronin@chromium.org>
Tested-by: Vadim Sukhomlinov <sukhomlinov@chromium.org>
Diffstat (limited to 'board/cr50')
-rw-r--r-- | board/cr50/dcrypto/bn.c | 40 | ||||
-rw-r--r-- | board/cr50/dcrypto/dcrypto.h | 56 | ||||
-rw-r--r-- | board/cr50/dcrypto/dcrypto_bn.c | 25 | ||||
-rw-r--r-- | board/cr50/dcrypto/fips.c | 13 | ||||
-rw-r--r-- | board/cr50/dcrypto/internal.h | 57 | ||||
-rw-r--r-- | board/cr50/dcrypto/rsa.c | 170 | ||||
-rw-r--r-- | board/cr50/dcrypto/x509.c | 19 | ||||
-rw-r--r-- | board/cr50/tpm2/endorsement.c | 10 | ||||
-rw-r--r-- | board/cr50/tpm2/rsa.c | 26 |
9 files changed, 230 insertions, 186 deletions
diff --git a/board/cr50/dcrypto/bn.c b/board/cr50/dcrypto/bn.c index 6949eb0a0c..e92f366aeb 100644 --- a/board/cr50/dcrypto/bn.c +++ b/board/cr50/dcrypto/bn.c @@ -397,8 +397,10 @@ static void bn_modexp_internal(struct LITE_BIGNUM *output, } /* output = input ^ exp % N */ -int bn_modexp(struct LITE_BIGNUM *output, const struct LITE_BIGNUM *input, - const struct LITE_BIGNUM *exp, const struct LITE_BIGNUM *N) +enum dcrypto_result bn_modexp(struct LITE_BIGNUM *output, + const struct LITE_BIGNUM *input, + const struct LITE_BIGNUM *exp, + const struct LITE_BIGNUM *N) { #ifndef CR50_NO_BN_ASM if ((bn_bits(N) & 255) == 0) { @@ -407,12 +409,13 @@ int bn_modexp(struct LITE_BIGNUM *output, const struct LITE_BIGNUM *input, } #endif bn_modexp_internal(output, input, exp, N); - return 1; + return DCRYPTO_OK; } /* output = input ^ exp % N */ -int bn_modexp_word(struct LITE_BIGNUM *output, const struct LITE_BIGNUM *input, - uint32_t exp, const struct LITE_BIGNUM *N) +enum dcrypto_result bn_modexp_word(struct LITE_BIGNUM *output, + const struct LITE_BIGNUM *input, + uint32_t exp, const struct LITE_BIGNUM *N) { #ifndef CR50_NO_BN_ASM if ((bn_bits(N) & 255) == 0) { @@ -421,16 +424,16 @@ int bn_modexp_word(struct LITE_BIGNUM *output, const struct LITE_BIGNUM *input, } #endif { - struct LITE_BIGNUM pubexp; + struct LITE_BIGNUM pubexp; - DCRYPTO_bn_wrap(&pubexp, &exp, sizeof(exp)); - bn_modexp_internal(output, input, &pubexp, N); - return 1; + DCRYPTO_bn_wrap(&pubexp, &exp, sizeof(exp)); + bn_modexp_internal(output, input, &pubexp, N); + return DCRYPTO_OK; } } /* output = input ^ exp % N */ -int bn_modexp_blinded(struct LITE_BIGNUM *output, +enum dcrypto_result bn_modexp_blinded(struct LITE_BIGNUM *output, const struct LITE_BIGNUM *input, const struct LITE_BIGNUM *exp, const struct LITE_BIGNUM *N, @@ -443,7 +446,7 @@ int bn_modexp_blinded(struct LITE_BIGNUM *output, } #endif bn_modexp_internal(output, input, exp, N); - return 1; + return DCRYPTO_OK; } /* c[] += a * b[] */ @@ -795,8 +798,9 @@ int DCRYPTO_bn_div(struct LITE_BIGNUM *quotient, * if t < 0 then t := t + n * return t */ -int bn_modinv_vartime(struct LITE_BIGNUM *dst, const struct LITE_BIGNUM *src, - const struct LITE_BIGNUM *mod) +enum dcrypto_result bn_modinv_vartime(struct LITE_BIGNUM *dst, + const struct LITE_BIGNUM *src, + const struct LITE_BIGNUM *mod) { struct LITE_BIGNUM R; struct LITE_BIGNUM nR; @@ -907,7 +911,7 @@ int bn_modinv_vartime(struct LITE_BIGNUM *dst, const struct LITE_BIGNUM *src, if (r_len != 1 || BN_DIGIT(pR, 0) != 1) { /* gcd not 1; no direct inverse */ - return 0; + return DCRYPTO_FAIL; } if (t_neg) @@ -915,7 +919,7 @@ int bn_modinv_vartime(struct LITE_BIGNUM *dst, const struct LITE_BIGNUM *src, bn_set_bn(dst, pT, bn_digits(pT)); - return 1; + return DCRYPTO_OK; } #define PRIME1 3 @@ -1289,7 +1293,7 @@ static void print_primes(uint16_t prime) #endif } -int DCRYPTO_bn_generate_prime(struct LITE_BIGNUM *p) +enum dcrypto_result DCRYPTO_bn_generate_prime(struct LITE_BIGNUM *p) { size_t i; size_t j; @@ -1355,10 +1359,10 @@ int DCRYPTO_bn_generate_prime(struct LITE_BIGNUM *p) /* Make sure prime will work with F4 public exponent. */ if (bn_mod_f4(p) >= 2) { if (bn_probable_prime(p)) - return 1; + return DCRYPTO_OK; } } always_memset(composites_buf, 0, sizeof(composites_buf)); - return 0; + return DCRYPTO_FAIL; } diff --git a/board/cr50/dcrypto/dcrypto.h b/board/cr50/dcrypto/dcrypto.h index bd87c1efe9..c162b1c66c 100644 --- a/board/cr50/dcrypto/dcrypto.h +++ b/board/cr50/dcrypto/dcrypto.h @@ -777,38 +777,46 @@ enum padding_mode { /* RSA support, FIPS PUB 186-4 * * Calculate r = m ^ e mod N */ -int DCRYPTO_rsa_encrypt(struct RSA *rsa, uint8_t *out, size_t *out_len, - const uint8_t *in, size_t in_len, - enum padding_mode padding, enum hashing_mode hashing, - const char *label); +enum dcrypto_result DCRYPTO_rsa_encrypt(struct RSA *rsa, uint8_t *out, + size_t *out_len, const uint8_t *in, + size_t in_len, + enum padding_mode padding, + enum hashing_mode hashing, + const char *label); /* Calculate r = m ^ d mod N - * return 0 if error + * return DCRYPTO_OK if success */ -int DCRYPTO_rsa_decrypt(struct RSA *rsa, uint8_t *out, size_t *out_len, - const uint8_t *in, const size_t in_len, - enum padding_mode padding, enum hashing_mode hashing, - const char *label); +enum dcrypto_result DCRYPTO_rsa_decrypt(struct RSA *rsa, uint8_t *out, + size_t *out_len, const uint8_t *in, + const size_t in_len, + enum padding_mode padding, + enum hashing_mode hashing, + const char *label); /* Calculate r = m ^ d mod N - * return 0 if error + * return DCRYPTO_OK if success */ -int DCRYPTO_rsa_sign(struct RSA *rsa, uint8_t *out, size_t *out_len, - const uint8_t *in, const size_t in_len, - enum padding_mode padding, enum hashing_mode hashing); +enum dcrypto_result DCRYPTO_rsa_sign(struct RSA *rsa, uint8_t *out, + size_t *out_len, const uint8_t *in, + const size_t in_len, + enum padding_mode padding, + enum hashing_mode hashing); /* Calculate r = m ^ e mod N - * return 0 if error + * return DCRYPTO_OK if success */ -int DCRYPTO_rsa_verify(const struct RSA *rsa, const uint8_t *digest, - size_t digest_len, const uint8_t *sig, - const size_t sig_len, enum padding_mode padding, - enum hashing_mode hashing); +enum dcrypto_result DCRYPTO_rsa_verify(const struct RSA *rsa, + const uint8_t *digest, size_t digest_len, + const uint8_t *sig, const size_t sig_len, + enum padding_mode padding, + enum hashing_mode hashing); /* Calculate n = p * q, d = e ^ -1 mod phi. */ -int DCRYPTO_rsa_key_compute(struct LITE_BIGNUM *N, struct LITE_BIGNUM *d, - struct LITE_BIGNUM *p, struct LITE_BIGNUM *q, - uint32_t e); +enum dcrypto_result DCRYPTO_rsa_key_compute(struct LITE_BIGNUM *N, + struct LITE_BIGNUM *d, + struct LITE_BIGNUM *p, + struct LITE_BIGNUM *q, uint32_t e); /* * EC. @@ -990,9 +998,9 @@ int DCRYPTO_hkdf(uint8_t *OKM, size_t OKM_len, const uint8_t *salt, */ /* Apply Miller-Rabin test for prime candidate p. - * Returns 1 if test passed, 0 otherwise + * Returns DCRYPTO_OK if test passed, DCRYPTO_FAIL otherwise */ -int DCRYPTO_bn_generate_prime(struct LITE_BIGNUM *p); +enum dcrypto_result DCRYPTO_bn_generate_prime(struct LITE_BIGNUM *p); void DCRYPTO_bn_wrap(struct LITE_BIGNUM *b, void *buf, size_t len); void DCRYPTO_bn_mul(struct LITE_BIGNUM *c, const struct LITE_BIGNUM *a, const struct LITE_BIGNUM *b); @@ -1029,7 +1037,7 @@ size_t DCRYPTO_asn1_pubp(uint8_t *buf, const p256_int *x, const p256_int *y); * Accepts only certs with OID: sha256WithRSAEncryption: * 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 */ -int DCRYPTO_x509_verify(const uint8_t *cert, size_t len, +enum dcrypto_result DCRYPTO_x509_verify(const uint8_t *cert, size_t len, const struct RSA *ca_pub_key); /* Generate U2F Certificate and sign it diff --git a/board/cr50/dcrypto/dcrypto_bn.c b/board/cr50/dcrypto/dcrypto_bn.c index 009f92332e..9679b8b238 100644 --- a/board/cr50/dcrypto/dcrypto_bn.c +++ b/board/cr50/dcrypto/dcrypto_bn.c @@ -1280,7 +1280,7 @@ static int modexp(struct DMEM_ctx *ctx, uint32_t adr, uint32_t rr, uint32_t pIn, } /* output = input ** exp % N. */ -int dcrypto_modexp_blinded(struct LITE_BIGNUM *output, +enum dcrypto_result dcrypto_modexp_blinded(struct LITE_BIGNUM *output, const struct LITE_BIGNUM *input, const struct LITE_BIGNUM *exp, const struct LITE_BIGNUM *N, uint32_t pubexp) @@ -1304,7 +1304,7 @@ int dcrypto_modexp_blinded(struct LITE_BIGNUM *output, * We cannot tolerate risk of 0 since 0 breaks computation. */ if (!rand64(r_buf)) - return 0; + return DCRYPTO_FAIL; /* * compute 1/r mod N @@ -1320,7 +1320,7 @@ int dcrypto_modexp_blinded(struct LITE_BIGNUM *output, /* Pick !0 64-bit random for exponent blinding */ if (!rand64(ctx->rnd)) - return 0; + return DCRYPTO_FAIL; result = setup_and_lock(N, input); @@ -1353,12 +1353,14 @@ int dcrypto_modexp_blinded(struct LITE_BIGNUM *output, memcpy(output->d, ctx->out, bn_size(output)); dcrypto_unlock(); - return result == 0; + return dcrypto_ok_if_zero(result); } /* output = input ** exp % N. */ -int dcrypto_modexp(struct LITE_BIGNUM *output, const struct LITE_BIGNUM *input, - const struct LITE_BIGNUM *exp, const struct LITE_BIGNUM *N) +enum dcrypto_result dcrypto_modexp(struct LITE_BIGNUM *output, + const struct LITE_BIGNUM *input, + const struct LITE_BIGNUM *exp, + const struct LITE_BIGNUM *N) { int result; size_t i; @@ -1386,11 +1388,11 @@ int dcrypto_modexp(struct LITE_BIGNUM *output, const struct LITE_BIGNUM *input, memcpy(output->d, ctx->out, bn_size(output)); dcrypto_unlock(); - return result == 0; + return dcrypto_ok_if_zero(result); } /* output = input ** exp % N. */ -int dcrypto_modexp_word(struct LITE_BIGNUM *output, +enum dcrypto_result dcrypto_modexp_word(struct LITE_BIGNUM *output, const struct LITE_BIGNUM *input, uint32_t exp, const struct LITE_BIGNUM *N) { @@ -1429,7 +1431,7 @@ int dcrypto_modexp_word(struct LITE_BIGNUM *output, memcpy(output->d, ctx->out, bn_size(output)); dcrypto_unlock(); - return result == 0; + return dcrypto_ok_if_zero(result); } #ifndef CRYPTO_TEST_CMD_GENP @@ -1457,8 +1459,9 @@ static int genp_core(void) DCRYPTO_bn_wrap(&prime, &prime_buf, sizeof(prime_buf)); genp_start = get_time(); - result = (DCRYPTO_bn_generate_prime(&prime) != 0) ? EC_SUCCESS - : EC_ERROR_UNKNOWN; + result = (DCRYPTO_bn_generate_prime(&prime) == DCRYPTO_OK) ? + EC_SUCCESS : + EC_ERROR_UNKNOWN; genp_end = get_time(); return result; diff --git a/board/cr50/dcrypto/fips.c b/board/cr50/dcrypto/fips.c index 7e70146522..5e9422d2c3 100644 --- a/board/cr50/dcrypto/fips.c +++ b/board/cr50/dcrypto/fips.c @@ -605,20 +605,17 @@ static bool fips_rsa2048_verify_kat(void) .d = (struct access_helper *)pub } }; - int passed; - SHA256_hw_hash(msg, sizeof(msg), &digest); - passed = DCRYPTO_rsa_verify(&rsa, digest.b8, sizeof(digest), sig, - sizeof(sig), PADDING_MODE_PKCS1, - HASH_SHA256); - if (!passed) + if (DCRYPTO_rsa_verify(&rsa, digest.b8, sizeof(digest), sig, + sizeof(sig), PADDING_MODE_PKCS1, + HASH_SHA256) != DCRYPTO_OK) return false; SHA256_hw_hash(bad_msg, sizeof(bad_msg), &digest); /* now signature should fail */ - return !DCRYPTO_rsa_verify(&rsa, digest.b8, sizeof(digest), sig, + return DCRYPTO_rsa_verify(&rsa, digest.b8, sizeof(digest), sig, sizeof(sig), PADDING_MODE_PKCS1, - HASH_SHA256); + HASH_SHA256) == DCRYPTO_OK; } #endif diff --git a/board/cr50/dcrypto/internal.h b/board/cr50/dcrypto/internal.h index 696ad2de9d..fc3a0a5d30 100644 --- a/board/cr50/dcrypto/internal.h +++ b/board/cr50/dcrypto/internal.h @@ -207,41 +207,42 @@ void bn_init(struct LITE_BIGNUM *bn, void *buf, size_t len); int bn_eq(const struct LITE_BIGNUM *a, const struct LITE_BIGNUM *b); int bn_check_topbit(const struct LITE_BIGNUM *N); -int bn_modexp(struct LITE_BIGNUM *output, - const struct LITE_BIGNUM *input, - const struct LITE_BIGNUM *exp, - const struct LITE_BIGNUM *N); -int bn_modexp_word(struct LITE_BIGNUM *output, - const struct LITE_BIGNUM *input, - uint32_t pubexp, - const struct LITE_BIGNUM *N); -int bn_modexp_blinded(struct LITE_BIGNUM *output, - const struct LITE_BIGNUM *input, - const struct LITE_BIGNUM *exp, - const struct LITE_BIGNUM *N, - uint32_t pubexp); +enum dcrypto_result bn_modexp(struct LITE_BIGNUM *output, + const struct LITE_BIGNUM *input, + const struct LITE_BIGNUM *exp, + const struct LITE_BIGNUM *N); +enum dcrypto_result bn_modexp_word(struct LITE_BIGNUM *output, + const struct LITE_BIGNUM *input, + uint32_t pubexp, + const struct LITE_BIGNUM *N); +enum dcrypto_result bn_modexp_blinded(struct LITE_BIGNUM *output, + const struct LITE_BIGNUM *input, + const struct LITE_BIGNUM *exp, + const struct LITE_BIGNUM *N, + uint32_t pubexp); uint32_t bn_add(struct LITE_BIGNUM *c, const struct LITE_BIGNUM *a); int32_t bn_sub(struct LITE_BIGNUM *c, const struct LITE_BIGNUM *a); -int bn_modinv_vartime(struct LITE_BIGNUM *r, const struct LITE_BIGNUM *e, - const struct LITE_BIGNUM *MOD); +enum dcrypto_result bn_modinv_vartime(struct LITE_BIGNUM *r, + const struct LITE_BIGNUM *e, + const struct LITE_BIGNUM *MOD); int bn_is_bit_set(const struct LITE_BIGNUM *a, size_t n); /* * Accelerated bn. */ -int dcrypto_modexp(struct LITE_BIGNUM *output, - const struct LITE_BIGNUM *input, - const struct LITE_BIGNUM *exp, - const struct LITE_BIGNUM *N); -int dcrypto_modexp_word(struct LITE_BIGNUM *output, - const struct LITE_BIGNUM *input, - uint32_t pubexp, - const struct LITE_BIGNUM *N); -int dcrypto_modexp_blinded(struct LITE_BIGNUM *output, - const struct LITE_BIGNUM *input, - const struct LITE_BIGNUM *exp, - const struct LITE_BIGNUM *N, - uint32_t pubexp); +enum dcrypto_result dcrypto_modexp(struct LITE_BIGNUM *output, + const struct LITE_BIGNUM *input, + const struct LITE_BIGNUM *exp, + const struct LITE_BIGNUM *N); +enum dcrypto_result dcrypto_modexp_word(struct LITE_BIGNUM *output, + const struct LITE_BIGNUM *input, + uint32_t pubexp, + const struct LITE_BIGNUM *N); +enum dcrypto_result dcrypto_modexp_blinded(struct LITE_BIGNUM *output, + const struct LITE_BIGNUM *input, + const struct LITE_BIGNUM *exp, + const struct LITE_BIGNUM *N, + uint32_t pubexp); /** * NIST SP 800-90A HMAC_DRBG_SHA2-256. diff --git a/board/cr50/dcrypto/rsa.c b/board/cr50/dcrypto/rsa.c index 3a9a7b10be..d0259ebaf1 100644 --- a/board/cr50/dcrypto/rsa.c +++ b/board/cr50/dcrypto/rsa.c @@ -530,10 +530,12 @@ static enum dcrypto_result check_modulus_params(const struct RSA *rsa, return DCRYPTO_OK; } -int DCRYPTO_rsa_encrypt(struct RSA *rsa, uint8_t *out, size_t *out_len, - const uint8_t *in, size_t in_len, - enum padding_mode padding, enum hashing_mode hashing, - const char *label) +enum dcrypto_result DCRYPTO_rsa_encrypt(struct RSA *rsa, uint8_t *out, + size_t *out_len, const uint8_t *in, + size_t in_len, + enum padding_mode padding, + enum hashing_mode hashing, + const char *label) { uint8_t *p; size_t n_len; @@ -541,10 +543,14 @@ int DCRYPTO_rsa_encrypt(struct RSA *rsa, uint8_t *out, size_t *out_len, struct LITE_BIGNUM padded; struct LITE_BIGNUM encrypted; - int ret; + enum dcrypto_result ret; - if (check_modulus_params(rsa, out_len) != DCRYPTO_OK) - return 0; + if (!fips_crypto_allowed()) + return DCRYPTO_FAIL; + + ret = check_modulus_params(rsa, out_len); + if (ret != DCRYPTO_OK) + return ret; n_len = bn_size(&rsa->N); padded_buf = alloca(n_len); @@ -554,22 +560,20 @@ int DCRYPTO_rsa_encrypt(struct RSA *rsa, uint8_t *out, size_t *out_len, switch (padding) { case PADDING_MODE_OAEP: - if (oaep_pad((uint8_t *)padded.d, bn_size(&padded), + ret = oaep_pad((uint8_t *)padded.d, bn_size(&padded), (const uint8_t *)in, in_len, hashing, - label) != DCRYPTO_OK) - return 0; + label); break; case PADDING_MODE_PKCS1: - if (pkcs1_type2_pad((uint8_t *)padded.d, bn_size(&padded), - (const uint8_t *)in, in_len) != DCRYPTO_OK) - return 0; + ret = pkcs1_type2_pad((uint8_t *)padded.d, bn_size(&padded), + (const uint8_t *)in, in_len); break; case PADDING_MODE_NULL: /* Input is allowed to have more bytes than N, in * which case the excess must be zero. */ for (; in_len > bn_size(&padded); in_len--) if (*in++ != 0) - return 0; + return DCRYPTO_FAIL; p = (uint8_t *) padded.d; /* If in_len < bn_size(&padded), padded will * have leading zero bytes. */ @@ -578,9 +582,12 @@ int DCRYPTO_rsa_encrypt(struct RSA *rsa, uint8_t *out, size_t *out_len, * handle this case. */ break; default: - return 0; /* Unsupported padding mode. */ + /* Unsupported padding mode. */ + ret = DCRYPTO_FAIL; + break; } - + if (ret != DCRYPTO_OK) + return ret; /* Reverse from big-endian to little-endian notation. */ reverse((uint8_t *) padded.d, bn_size(&padded)); ret = bn_modexp_word(&encrypted, &padded, rsa->e, &rsa->N); @@ -592,21 +599,27 @@ int DCRYPTO_rsa_encrypt(struct RSA *rsa, uint8_t *out, size_t *out_len, return ret; } -int DCRYPTO_rsa_decrypt(struct RSA *rsa, uint8_t *out, size_t *out_len, - const uint8_t *in, const size_t in_len, - enum padding_mode padding, enum hashing_mode hashing, - const char *label) +enum dcrypto_result DCRYPTO_rsa_decrypt(struct RSA *rsa, uint8_t *out, + size_t *out_len, const uint8_t *in, + const size_t in_len, + enum padding_mode padding, + enum hashing_mode hashing, + const char *label) { uint8_t *buf = NULL; struct LITE_BIGNUM encrypted; struct LITE_BIGNUM padded; - int ret; + enum dcrypto_result ret; - if (check_modulus_params(rsa, NULL) != DCRYPTO_OK) - return 0; - if (in_len != bn_size(&rsa->N)) - return 0; /* Invalid input length. */ + if (!fips_crypto_allowed()) + return DCRYPTO_FAIL; + + ret = check_modulus_params(rsa, NULL); + if (ret != DCRYPTO_OK) + return ret; + if (in_len != bn_size(&rsa->N)) /* Invalid input length. */ + return DCRYPTO_FAIL; buf = alloca(in_len * 2); /* TODO: this copy can be eliminated if input may be modified. */ bn_init(&encrypted, buf, in_len); @@ -621,20 +634,18 @@ int DCRYPTO_rsa_decrypt(struct RSA *rsa, uint8_t *out, size_t *out_len, switch (padding) { case PADDING_MODE_OAEP: - if (check_oaep_pad(out, out_len, (uint8_t *)padded.d, + ret |= check_oaep_pad(out, out_len, (uint8_t *)padded.d, bn_size(&padded), hashing, - label) != DCRYPTO_OK) - ret = 0; + label); break; case PADDING_MODE_PKCS1: - if (check_pkcs1_type2_pad(out, out_len, + ret |= check_pkcs1_type2_pad(out, out_len, (const uint8_t *)padded.d, - bn_size(&padded)) != DCRYPTO_OK) - ret = 0; + bn_size(&padded)); break; case PADDING_MODE_NULL: if (*out_len < bn_size(&padded)) { - ret = 0; + ret = DCRYPTO_FAIL; } else { *out_len = bn_size(&padded); memcpy(out, padded.d, *out_len); @@ -642,27 +653,34 @@ int DCRYPTO_rsa_decrypt(struct RSA *rsa, uint8_t *out, size_t *out_len, break; default: /* Unsupported padding mode. */ - ret = 0; + ret = DCRYPTO_FAIL; break; } - + if (ret != DCRYPTO_OK) + ret = DCRYPTO_FAIL; always_memset(buf, 0, in_len * 2); return ret; } -int DCRYPTO_rsa_sign(struct RSA *rsa, uint8_t *out, size_t *out_len, - const uint8_t *in, const size_t in_len, - enum padding_mode padding, enum hashing_mode hashing) +enum dcrypto_result DCRYPTO_rsa_sign(struct RSA *rsa, uint8_t *out, + size_t *out_len, const uint8_t *in, + const size_t in_len, + enum padding_mode padding, + enum hashing_mode hashing) { uint8_t *padded_buf; size_t n_len; struct LITE_BIGNUM padded; struct LITE_BIGNUM signature; - int ret; + enum dcrypto_result ret; + + if (!fips_crypto_allowed()) + return DCRYPTO_FAIL; - if (check_modulus_params(rsa, out_len) != DCRYPTO_OK) - return 0; + ret = check_modulus_params(rsa, out_len); + if (ret != DCRYPTO_OK) + return ret; n_len = bn_size(&rsa->N); padded_buf = alloca(n_len); @@ -671,20 +689,20 @@ int DCRYPTO_rsa_sign(struct RSA *rsa, uint8_t *out, size_t *out_len, switch (padding) { case PADDING_MODE_PKCS1: - if (pkcs1_type1_pad((uint8_t *)padded.d, bn_size(&padded), + ret = pkcs1_type1_pad((uint8_t *)padded.d, bn_size(&padded), (const uint8_t *)in, in_len, - hashing) != DCRYPTO_OK) - return 0; + hashing); break; case PADDING_MODE_PSS: - if (pkcs1_pss_pad((uint8_t *)padded.d, bn_size(&padded), + ret = pkcs1_pss_pad((uint8_t *)padded.d, bn_size(&padded), (const uint8_t *)in, in_len, - hashing) != DCRYPTO_OK) - return 0; + hashing); break; default: - return 0; + ret = DCRYPTO_FAIL; } + if (ret != DCRYPTO_OK) + return ret; /* Reverse from big-endian to little-endian notation. */ reverse((uint8_t *) padded.d, bn_size(&padded)); @@ -697,21 +715,26 @@ int DCRYPTO_rsa_sign(struct RSA *rsa, uint8_t *out, size_t *out_len, return ret; } -int DCRYPTO_rsa_verify(const struct RSA *rsa, const uint8_t *digest, - size_t digest_len, const uint8_t *sig, - const size_t sig_len, enum padding_mode padding, - enum hashing_mode hashing) +enum dcrypto_result DCRYPTO_rsa_verify(const struct RSA *rsa, + const uint8_t *digest, size_t digest_len, + const uint8_t *sig, const size_t sig_len, + enum padding_mode padding, + enum hashing_mode hashing) { uint8_t *buf; struct LITE_BIGNUM padded; struct LITE_BIGNUM signature; - int ret; + enum dcrypto_result ret; - if (check_modulus_params(rsa, NULL) != DCRYPTO_OK) - return 0; + if (!fips_crypto_allowed()) + return DCRYPTO_FAIL; + + ret = check_modulus_params(rsa, NULL); + if (ret != DCRYPTO_OK) + return ret; if (sig_len != bn_size(&rsa->N)) - return 0; /* Invalid input length. */ + return DCRYPTO_FAIL; /* Invalid input length. */ buf = alloca(sig_len * 2); bn_init(&signature, buf, sig_len); @@ -719,27 +742,25 @@ int DCRYPTO_rsa_verify(const struct RSA *rsa, const uint8_t *digest, bn_init(&padded, buf + sig_len, sig_len); /* Reverse from big-endian to little-endian notation. */ - reverse((uint8_t *) signature.d, bn_size(&signature)); + reverse((uint8_t *)signature.d, bn_size(&signature)); ret = bn_modexp_word(&padded, &signature, rsa->e, &rsa->N); /* Back to big-endian notation. */ - reverse((uint8_t *) padded.d, bn_size(&padded)); + reverse((uint8_t *)padded.d, bn_size(&padded)); switch (padding) { case PADDING_MODE_PKCS1: - if (check_pkcs1_type1_pad(digest, digest_len, - (uint8_t *)padded.d, bn_size(&padded), - hashing) != DCRYPTO_OK) - ret = 0; + ret = check_pkcs1_type1_pad(digest, digest_len, + (uint8_t *)padded.d, + bn_size(&padded), hashing); break; case PADDING_MODE_PSS: - if (check_pkcs1_pss_pad(digest, digest_len, (uint8_t *)padded.d, - bn_size(&padded), - hashing) != DCRYPTO_OK) - ret = 0; + ret = check_pkcs1_pss_pad(digest, digest_len, + (uint8_t *)padded.d, bn_size(&padded), + hashing); break; default: /* Unsupported padding mode. */ - ret = 0; + ret = DCRYPTO_FAIL; break; } @@ -747,9 +768,11 @@ int DCRYPTO_rsa_verify(const struct RSA *rsa, const uint8_t *digest, return ret; } -int DCRYPTO_rsa_key_compute(struct LITE_BIGNUM *N, struct LITE_BIGNUM *d, - struct LITE_BIGNUM *p, struct LITE_BIGNUM *q, - uint32_t e_buf) +enum dcrypto_result DCRYPTO_rsa_key_compute(struct LITE_BIGNUM *N, + struct LITE_BIGNUM *d, + struct LITE_BIGNUM *p, + struct LITE_BIGNUM *q, + uint32_t e_buf) { uint32_t ONE_buf = 1; uint8_t *buf; @@ -759,11 +782,14 @@ int DCRYPTO_rsa_key_compute(struct LITE_BIGNUM *N, struct LITE_BIGNUM *d, struct LITE_BIGNUM phi; struct LITE_BIGNUM q_local; + if (!fips_crypto_allowed()) + return DCRYPTO_FAIL; + n_len = bn_size(N); p_len = bn_size(p); if (n_len > RSA_BYTES_4K || p_len > RSA_BYTES_2K || !(e_buf & 1)) - return 0; + return DCRYPTO_FAIL; buf = alloca(n_len + p_len); DCRYPTO_bn_wrap(&ONE, &ONE_buf, sizeof(ONE_buf)); @@ -774,12 +800,12 @@ int DCRYPTO_rsa_key_compute(struct LITE_BIGNUM *N, struct LITE_BIGNUM *d, q = &q_local; if (!DCRYPTO_bn_div(q, NULL, N, p)) - return 0; + return DCRYPTO_FAIL; /* Check that p * q == N */ DCRYPTO_bn_mul(&phi, p, q); if (!bn_eq(N, &phi)) - return 0; + return DCRYPTO_FAIL; } else { DCRYPTO_bn_mul(N, p, q); memcpy(phi.d, N->d, n_len); diff --git a/board/cr50/dcrypto/x509.c b/board/cr50/dcrypto/x509.c index a4bcdf2630..2094f8dad4 100644 --- a/board/cr50/dcrypto/x509.c +++ b/board/cr50/dcrypto/x509.c @@ -355,8 +355,8 @@ static size_t asn1_parse_signature_value(const uint8_t **p, size_t *available, * where signatureValue = SIGN(HASH(tbsCertificate)), with SIGN and * HASH specified by signatureAlgorithm. */ -int DCRYPTO_x509_verify(const uint8_t *cert, size_t len, - const struct RSA *ca_pub_key) +enum dcrypto_result DCRYPTO_x509_verify(const uint8_t *cert, size_t len, + const struct RSA *ca_pub_key) { const uint8_t *p = cert; const uint8_t *tbs; @@ -366,32 +366,35 @@ int DCRYPTO_x509_verify(const uint8_t *cert, size_t len, struct sha256_digest digest; + if (!fips_crypto_allowed()) + return DCRYPTO_FAIL; + /* Read Certificate SEQUENCE. */ if (!asn1_parse_certificate(&p, &len)) - return 0; + return DCRYPTO_FAIL; /* Read tbsCertificate SEQUENCE. */ tbs = p; if (!asn1_parse_tbs(&p, &len, &tbs_len)) - return 0; + return DCRYPTO_FAIL; /* Read signatureAlgorithm SEQUENCE. */ if (!asn1_parse_signature_algorithm(&p, &len)) - return 0; + return DCRYPTO_FAIL; /* Read signatureValue BIT STRING. */ if (!asn1_parse_signature_value(&p, &len, &sig, &sig_len)) - return 0; + return DCRYPTO_FAIL; /* Check that the signature length corresponds to the issuer's * public key size. */ if (sig_len != bn_size(&ca_pub_key->N) && sig_len != bn_size(&ca_pub_key->N) + 1) - return 0; + return DCRYPTO_FAIL; /* Check that leading signature bytes (if any) are zero. */ if (sig_len == bn_size(&ca_pub_key->N) + 1) { if (sig[0] != 0) - return 0; + return DCRYPTO_FAIL; sig++; sig_len--; } diff --git a/board/cr50/tpm2/endorsement.c b/board/cr50/tpm2/endorsement.c index b4d2b91775..fe4434bbec 100644 --- a/board/cr50/tpm2/endorsement.c +++ b/board/cr50/tpm2/endorsement.c @@ -364,10 +364,12 @@ static int validate_cert( * certificates serve as roots for the installed endorsement * certificate. */ - return DCRYPTO_x509_verify(cert->cert, cert->cert_len, - &PROD_ENDORSEMENT_CA_RSA_PUB) || - DCRYPTO_x509_verify(cert->cert, cert->cert_len, - &TEST_ENDORSEMENT_CA_RSA_PUB); + return (DCRYPTO_x509_verify(cert->cert, cert->cert_len, + &PROD_ENDORSEMENT_CA_RSA_PUB) == + DCRYPTO_OK) || + (DCRYPTO_x509_verify(cert->cert, cert->cert_len, + &TEST_ENDORSEMENT_CA_RSA_PUB) == + DCRYPTO_OK); } static int store_cert(enum cros_perso_component_type component_type, diff --git a/board/cr50/tpm2/rsa.c b/board/cr50/tpm2/rsa.c index 97797d440a..9fc7f3b085 100644 --- a/board/cr50/tpm2/rsa.c +++ b/board/cr50/tpm2/rsa.c @@ -94,7 +94,7 @@ CRYPT_RESULT _cpri__EncryptRSA(uint32_t *out_len, uint8_t *out, struct RSA rsa; enum padding_mode padding; enum hashing_mode hashing; - int result; + enum dcrypto_result result; if (!check_key(key)) return CRYPT_FAIL; @@ -113,7 +113,7 @@ CRYPT_RESULT _cpri__EncryptRSA(uint32_t *out_len, uint8_t *out, reverse_tpm2b(key->publicKey); - if (result) + if (result == DCRYPTO_OK) return CRYPT_SUCCESS; else return CRYPT_FAIL; @@ -127,7 +127,7 @@ CRYPT_RESULT _cpri__DecryptRSA(uint32_t *out_len, uint8_t *out, struct RSA rsa; enum padding_mode padding; enum hashing_mode hashing; - int result; + enum dcrypto_result result; if (!check_key(key)) return CRYPT_FAIL; @@ -149,7 +149,7 @@ CRYPT_RESULT _cpri__DecryptRSA(uint32_t *out_len, uint8_t *out, reverse_tpm2b(key->publicKey); reverse_tpm2b(key->privateKey); - if (result) + if (result == DCRYPTO_OK) return CRYPT_SUCCESS; else return CRYPT_FAIL; @@ -162,7 +162,7 @@ CRYPT_RESULT _cpri__SignRSA(uint32_t *out_len, uint8_t *out, struct RSA rsa; enum padding_mode padding; enum hashing_mode hashing; - int result; + enum dcrypto_result result; if (!check_key(key)) return CRYPT_FAIL; @@ -186,7 +186,7 @@ CRYPT_RESULT _cpri__SignRSA(uint32_t *out_len, uint8_t *out, reverse_tpm2b(key->publicKey); reverse_tpm2b(key->privateKey); - if (result) + if (result == DCRYPTO_OK) return CRYPT_SUCCESS; else return CRYPT_FAIL; @@ -200,7 +200,7 @@ CRYPT_RESULT _cpri__ValidateSignatureRSA( struct RSA rsa; enum padding_mode padding; enum hashing_mode hashing; - int result; + enum dcrypto_result result; if (!check_key(key)) return CRYPT_FAIL; @@ -220,7 +220,7 @@ CRYPT_RESULT _cpri__ValidateSignatureRSA( reverse_tpm2b(key->publicKey); - if (result) + if (result == DCRYPTO_OK) return CRYPT_SUCCESS; else return CRYPT_FAIL; @@ -233,7 +233,7 @@ CRYPT_RESULT _cpri__TestKeyRSA(TPM2B *d_buf, uint32_t e, struct LITE_BIGNUM p; struct LITE_BIGNUM q; struct LITE_BIGNUM d; - int result; + enum dcrypto_result result; if (!p_buf) return CRYPT_PARAMETER; @@ -262,7 +262,7 @@ CRYPT_RESULT _cpri__TestKeyRSA(TPM2B *d_buf, uint32_t e, if (q_buf) reverse_tpm2b(q_buf); - if (result) { + if (result == DCRYPTO_OK) { d_buf->size = N_buf->size; reverse_tpm2b(d_buf); return CRYPT_SUCCESS; @@ -290,7 +290,7 @@ static int generate_prime(struct LITE_BIGNUM *b, TPM_ALG_ID hashing, bn_bits(b), (uint8_t *) b->d, NULL, FALSE); (*counter)++; /* Mark as used. */ - if (DCRYPTO_bn_generate_prime(b)) + if (DCRYPTO_bn_generate_prime(b) == DCRYPTO_OK) return 1; } @@ -1132,7 +1132,7 @@ static void rsa_command_handler(void *cmd_body, } DCRYPTO_bn_wrap(&bn, bn_buf, in_len); memcpy(bn_buf, in, in_len); - if (DCRYPTO_bn_generate_prime(&bn)) { + if (DCRYPTO_bn_generate_prime(&bn) == DCRYPTO_OK) { memcpy(out, bn.d, bn_size(&bn)); *response_size = bn_size(&bn); } else { @@ -1160,7 +1160,7 @@ static void rsa_command_handler(void *cmd_body, sizeof(RSA_2048_CERT), &rsa); reverse_tpm2b(key.publicKey); - if (!result) { + if (result != DCRYPTO_OK) { *response_size = 0; return; } |