summaryrefslogtreecommitdiff
path: root/board/cr50/dcrypto/rsa.c
diff options
context:
space:
mode:
Diffstat (limited to 'board/cr50/dcrypto/rsa.c')
-rw-r--r--board/cr50/dcrypto/rsa.c170
1 files changed, 98 insertions, 72 deletions
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);