From: lizhi <lizhi206@huawei.com> Add RSA input length validation to ensure input data size is less than modulus. Remove unsupported RSA-PSS padding mode in encryption/decryption scenarios. Signed-off-by: lizhi <lizhi206@huawei.com> --- src/uadk_prov_rsa.c | 46 +++++++++++++++++++++-- src/uadk_prov_rsa.h | 4 +- src/uadk_prov_rsa_enc.c | 25 ++++++++----- src/uadk_prov_rsa_kmgmt.c | 2 +- src/uadk_prov_rsa_sign.c | 14 ++++++- src/uadk_rsa.c | 78 +++++++++++++++++++++++++++++++++------ 6 files changed, 141 insertions(+), 28 deletions(-) diff --git a/src/uadk_prov_rsa.c b/src/uadk_prov_rsa.c index 4fe415f..386f7b5 100644 --- a/src/uadk_prov_rsa.c +++ b/src/uadk_prov_rsa.c @@ -401,12 +401,10 @@ int uadk_rsa_size(const RSA *r) return BN_num_bytes(r->n); } -int rsa_check_bit_useful(const int bits, int flen) +int rsa_check_bit_useful(const int bits) { if (bits < RSA_MIN_MODULUS_BITS) return UADK_P_FAIL; - if (flen > (bits >> BIT_BYTES_SHIFT)) - return UADK_DO_SOFT; switch (bits) { case RSA1024BITS: @@ -423,6 +421,46 @@ int rsa_check_bit_useful(const int bits, int flen) } } +int is_valid_rsa_pub_key(const RSA *rsa) +{ + const BIGNUM *n; + const BIGNUM *e; + + RSA_get0_key(rsa, &n, &e, NULL); + if (BN_ucmp(n, e) <= 0) { + UADK_ERR("invalid: e is a bad value\n"); + return UADK_P_FAIL; + } + + return UADK_P_SUCCESS; +} + +int is_valid_rsa_input(const unsigned char *in, int inlen, const RSA *rsa) +{ + int ret = UADK_P_SUCCESS; + const BIGNUM *n; + BIGNUM *f; + int n_len; + + RSA_get0_key(rsa, &n, NULL, NULL); + n_len = BN_num_bytes(n); + if (inlen < n_len) + return UADK_P_SUCCESS; + if (inlen > n_len) { + UADK_ERR("data too large for rsa modulus\n"); + return UADK_P_FAIL; + } + + f = BN_bin2bn(in, inlen, NULL); + if (f == NULL || BN_ucmp(f, n) >= 0) { + UADK_ERR("data too large for rsa modulus\n"); + ret = UADK_P_FAIL; + } + + BN_free(f); + return ret; +} + int check_rsa_input_para(const int flen, const unsigned char *from, unsigned char *to, RSA *rsa) { @@ -431,7 +469,7 @@ int check_rsa_input_para(const int flen, const unsigned char *from, return UADK_P_FAIL; } - return rsa_check_bit_useful(uadk_rsa_bits(rsa), flen); + return rsa_check_bit_useful(uadk_rsa_bits(rsa)); } int rsa_pkey_param_alloc(struct rsa_pubkey_param **pub, diff --git a/src/uadk_prov_rsa.h b/src/uadk_prov_rsa.h index 279f64a..4d2b00a 100644 --- a/src/uadk_prov_rsa.h +++ b/src/uadk_prov_rsa.h @@ -162,7 +162,9 @@ struct uadk_rsa_sess *rsa_get_eng_session(RSA *rsa, unsigned int bits, int rsa_do_crypto(struct uadk_rsa_sess *rsa_sess); int uadk_rsa_bits(const RSA *r); int uadk_rsa_size(const RSA *r); -int rsa_check_bit_useful(const int bits, int flen); +int rsa_check_bit_useful(const int bits); +int is_valid_rsa_input(const unsigned char *in, int inlen, const RSA *rsa); +int is_valid_rsa_pub_key(const RSA *rsa); int check_rsa_input_para(const int flen, const unsigned char *from, unsigned char *to, RSA *rsa); int rsa_pkey_param_alloc(struct rsa_pubkey_param **pub, diff --git a/src/uadk_prov_rsa_enc.c b/src/uadk_prov_rsa_enc.c index aa36420..c0da4c9 100644 --- a/src/uadk_prov_rsa_enc.c +++ b/src/uadk_prov_rsa_enc.c @@ -220,6 +220,10 @@ static int uadk_prov_rsa_public_encrypt(int flen, const unsigned char *from, if (ret != UADK_P_SUCCESS) return ret; + ret = is_valid_rsa_pub_key(rsa); + if (!ret) + return UADK_P_FAIL; + ret = rsa_pkey_param_alloc(&pub_enc, NULL); if (ret == -ENOMEM) return UADK_P_FAIL; @@ -239,16 +243,16 @@ static int uadk_prov_rsa_public_encrypt(int flen, const unsigned char *from, } ret = add_rsa_pubenc_padding(flen, from, from_buf, num_bytes, padding); - if (!ret) { - ret = UADK_P_FAIL; + if (!ret) + goto free_buf; + + ret = is_valid_rsa_input(from_buf, num_bytes, rsa); + if (!ret) goto free_buf; - } ret = rsa_fill_pubkey(pub_enc, rsa_sess, from_buf, to); - if (!ret) { - ret = UADK_P_FAIL; + if (!ret) goto free_buf; - } ret = rsa_do_crypto(rsa_sess); if (!ret || rsa_sess->req.status) { @@ -279,6 +283,10 @@ static int uadk_prov_rsa_private_decrypt(int flen, const unsigned char *from, if (ret != UADK_P_SUCCESS) return ret; + ret = is_valid_rsa_input(from, flen, rsa); + if (!ret) + return UADK_P_FAIL; + ret = rsa_pkey_param_alloc(NULL, &pri); if (ret == -ENOMEM) return UADK_P_FAIL; @@ -350,9 +358,6 @@ static int uadk_rsa_asym_init(void *vprsactx, void *vrsa, case RSA_FLAG_TYPE_RSA: priv->pad_mode = RSA_PKCS1_PADDING; break; - case RSA_FLAG_TYPE_RSASSAPSS: - priv->pad_mode = RSA_PKCS1_PSS_PADDING; - break; default: UADK_ERR("rsa asym operation not supported this keytype!\n"); return UADK_P_FAIL; @@ -361,7 +366,7 @@ static int uadk_rsa_asym_init(void *vprsactx, void *vrsa, if (uadk_prov_rsa_init()) priv->soft = 1; - return UADK_P_SUCCESS; + return uadk_asym_cipher_rsa_set_ctx_params(vprsactx, params); } static void *uadk_asym_cipher_rsa_newctx(void *provctx) diff --git a/src/uadk_prov_rsa_kmgmt.c b/src/uadk_prov_rsa_kmgmt.c index fe87493..3e5b0bf 100644 --- a/src/uadk_prov_rsa_kmgmt.c +++ b/src/uadk_prov_rsa_kmgmt.c @@ -732,7 +732,7 @@ static int uadk_prov_rsa_keygen(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb) int is_crt = 1; int ret; - ret = rsa_check_bit_useful(bits, 0); + ret = rsa_check_bit_useful(bits); if (ret != UADK_P_SUCCESS) return ret; diff --git a/src/uadk_prov_rsa_sign.c b/src/uadk_prov_rsa_sign.c index 8278610..e2b7073 100644 --- a/src/uadk_prov_rsa_sign.c +++ b/src/uadk_prov_rsa_sign.c @@ -293,6 +293,10 @@ static int uadk_prov_rsa_private_sign(int flen, const unsigned char *from, goto free_buf; } + ret = is_valid_rsa_input(from_buf, num_bytes, rsa); + if (!ret) + return UADK_P_FAIL; + ret = rsa_fill_prikey(rsa, rsa_sess, prik, from_buf, to); if (!ret) { ret = UADK_P_FAIL; @@ -353,6 +357,14 @@ static int uadk_prov_rsa_public_verify(int flen, const unsigned char *from, if (ret != UADK_P_SUCCESS) return ret; + ret = is_valid_rsa_pub_key(rsa); + if (!ret) + return UADK_P_FAIL; + + ret = is_valid_rsa_input(from, flen, rsa); + if (!ret) + return UADK_P_FAIL; + ret = rsa_pkey_param_alloc(&pub, NULL); if (ret == -ENOMEM) return UADK_P_FAIL; @@ -366,7 +378,7 @@ static int uadk_prov_rsa_public_verify(int flen, const unsigned char *from, } ret = rsa_create_pub_bn_ctx(rsa, pub, &from_buf, &num_bytes); - if (ret <= 0 || flen > num_bytes) { + if (ret <= 0) { ret = UADK_P_FAIL; goto free_sess; } diff --git a/src/uadk_rsa.c b/src/uadk_rsa.c index 11663d8..8aa4757 100644 --- a/src/uadk_rsa.c +++ b/src/uadk_rsa.c @@ -151,11 +151,8 @@ enum { static int uadk_e_rsa_keygen(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb); -static int rsa_check_bit_useful(const int bits, int flen) +static int rsa_check_bit_useful(const int bits) { - if (flen > bits) - return SOFT; - if (bits < RSA_MIN_MODULUS_BITS) return UADK_E_FAIL; @@ -174,6 +171,46 @@ static int rsa_check_bit_useful(const int bits, int flen) } } +static int is_valid_rsa_pub_key(const RSA *rsa) +{ + const BIGNUM *n; + const BIGNUM *e; + + RSA_get0_key(rsa, &n, &e, NULL); + if (BN_ucmp(n, e) <= 0) { + fprintf(stderr, "invalid: e is a bad value\n"); + return UADK_E_FAIL; + } + + return UADK_E_SUCCESS; +} + +static int is_valid_rsa_input(const unsigned char *in, int inlen, const RSA *rsa) +{ + int ret = UADK_E_SUCCESS; + const BIGNUM *n; + BIGNUM *f; + int n_len; + + RSA_get0_key(rsa, &n, NULL, NULL); + n_len = BN_num_bytes(n); + if (inlen < n_len) + return UADK_E_SUCCESS; + if (inlen > n_len) { + fprintf(stderr, "data too large for rsa modulus\n"); + return UADK_E_FAIL; + } + + f = BN_bin2bn(in, inlen, NULL); + if (f == NULL || BN_ucmp(f, n) >= 0) { + fprintf(stderr, "data too large for rsa modulus\n"); + ret = UADK_E_FAIL; + } + + BN_free(f); + return ret; +} + static int rsa_prime_mul_res(int num, struct rsa_prime_param *param, BN_CTX *ctx, BN_GENCB *cb) { @@ -629,7 +666,7 @@ static int check_rsa_input_para(const int flen, const unsigned char *from, return UADK_E_FAIL; } - return rsa_check_bit_useful(RSA_bits(rsa), flen); + return rsa_check_bit_useful(RSA_bits(rsa)); } static BN_ULONG *bn_get_words(const BIGNUM *a) @@ -1462,7 +1499,7 @@ static int uadk_e_rsa_keygen(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb) int is_crt = 1; int ret; - ret = rsa_check_bit_useful(bits, 0); + ret = rsa_check_bit_useful(bits); if (!ret) return UADK_E_FAIL; else if (ret == SOFT) @@ -1538,6 +1575,10 @@ static int uadk_e_rsa_public_encrypt(int flen, const unsigned char *from, else if (ret == SOFT) goto soft_log; + ret = is_valid_rsa_pub_key(rsa); + if (!ret) + return UADK_E_FAIL; + ret = uadk_e_rsa_init(); if (ret != UADK_INIT_SUCCESS) goto exe_soft; @@ -1571,6 +1612,10 @@ static int uadk_e_rsa_public_encrypt(int flen, const unsigned char *from, goto free_buf; } + ret = is_valid_rsa_input(from_buf, num_bytes, rsa); + if (!ret) + goto free_buf; + ret = rsa_fill_pubkey(pub_enc, rsa_sess, from_buf, to); if (!ret) { ret = UADK_DO_SOFT; @@ -1626,6 +1671,10 @@ static int uadk_e_rsa_private_decrypt(int flen, const unsigned char *from, else if (ret == SOFT) goto soft_log; + ret = is_valid_rsa_input(from, flen, rsa); + if (!ret) + return UADK_E_FAIL; + ret = uadk_e_rsa_init(); if (ret != UADK_INIT_SUCCESS) goto exe_soft; @@ -1741,6 +1790,10 @@ static int uadk_e_rsa_private_sign(int flen, const unsigned char *from, goto free_buf; } + ret = is_valid_rsa_input(from_buf, num_bytes, rsa); + if (!ret) + goto free_buf; + ret = rsa_fill_prikey(rsa, rsa_sess, pri, from_buf, to); if (!ret) { ret = UADK_DO_SOFT; @@ -1808,6 +1861,14 @@ static int uadk_e_rsa_public_verify(int flen, const unsigned char *from, else if (ret == SOFT) goto soft_log; + ret = is_valid_rsa_pub_key(rsa); + if (!ret) + return UADK_E_FAIL; + + ret = is_valid_rsa_input(from, flen, rsa); + if (!ret) + return UADK_E_FAIL; + ret = uadk_e_rsa_init(); if (ret != UADK_INIT_SUCCESS) goto exe_soft; @@ -1830,11 +1891,6 @@ static int uadk_e_rsa_public_verify(int flen, const unsigned char *from, goto free_sess; } - if (flen > num_bytes) { - ret = UADK_DO_SOFT; - goto free_buf; - } - ret = rsa_fill_pubkey(pub, rsa_sess, from_buf, to); if (!ret) { ret = UADK_DO_SOFT; -- 2.43.0