summaryrefslogtreecommitdiff
path: root/crypto/rsa/rsa_chk.c
diff options
context:
space:
mode:
authorPaul Yang <yang.yang@baishancloud.com>2017-08-02 02:19:43 +0800
committerPaul Yang <yang.yang@baishancloud.com>2017-11-21 14:38:42 +0800
commit665d899fa6d3571da016925067ebcf1789d7d19c (patch)
tree1674f352dc0feee9e68e6221d21c5d79bd1935ab /crypto/rsa/rsa_chk.c
parentb0004708730f300a2e5c6a11c887caab50b6c42a (diff)
downloadopenssl-new-665d899fa6d3571da016925067ebcf1789d7d19c.tar.gz
Support multi-prime RSA (RFC 8017)
* Introduce RSA_generate_multi_prime_key to generate multi-prime RSA private key. As well as the following functions: RSA_get_multi_prime_extra_count RSA_get0_multi_prime_factors RSA_get0_multi_prime_crt_params RSA_set0_multi_prime_params RSA_get_version * Support EVP operations for multi-prime RSA * Support ASN.1 operations for multi-prime RSA * Support multi-prime check in RSA_check_key_ex * Support multi-prime RSA in apps/genrsa and apps/speed * Support multi-prime RSA manipulation functions * Test cases and documentation are added * CHANGES is updated Reviewed-by: Tim Hudson <tjh@openssl.org> Reviewed-by: Bernd Edlinger <bernd.edlinger@hotmail.de> (Merged from https://github.com/openssl/openssl/pull/4241)
Diffstat (limited to 'crypto/rsa/rsa_chk.c')
-rw-r--r--crypto/rsa/rsa_chk.c81
1 files changed, 75 insertions, 6 deletions
diff --git a/crypto/rsa/rsa_chk.c b/crypto/rsa/rsa_chk.c
index 00260fb18e..4cf682258b 100644
--- a/crypto/rsa/rsa_chk.c
+++ b/crypto/rsa/rsa_chk.c
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -20,7 +20,8 @@ int RSA_check_key_ex(const RSA *key, BN_GENCB *cb)
{
BIGNUM *i, *j, *k, *l, *m;
BN_CTX *ctx;
- int ret = 1;
+ int ret = 1, ex_primes = 0, idx;
+ RSA_PRIME_INFO *pinfo;
if (key->p == NULL || key->q == NULL || key->n == NULL
|| key->e == NULL || key->d == NULL) {
@@ -28,6 +29,13 @@ int RSA_check_key_ex(const RSA *key, BN_GENCB *cb)
return 0;
}
+ /* multi-prime? */
+ if (key->version == RSA_ASN1_VERSION_MULTI
+ && (ex_primes = sk_RSA_PRIME_INFO_num(key->prime_infos)) <= 0) {
+ RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_INVALID_MULTI_PRIME_KEY);
+ return 0;
+ }
+
i = BN_new();
j = BN_new();
k = BN_new();
@@ -62,17 +70,37 @@ int RSA_check_key_ex(const RSA *key, BN_GENCB *cb)
RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_Q_NOT_PRIME);
}
- /* n = p*q? */
+ /* r_i prime? */
+ for (idx = 0; idx < ex_primes; idx++) {
+ pinfo = sk_RSA_PRIME_INFO_value(key->prime_infos, idx);
+ if (BN_is_prime_ex(pinfo->r, BN_prime_checks, NULL, cb) != 1) {
+ ret = 0;
+ RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_MP_R_NOT_PRIME);
+ }
+ }
+
+ /* n = p*q * r_3...r_i? */
if (!BN_mul(i, key->p, key->q, ctx)) {
ret = -1;
goto err;
}
+ for (idx = 0; idx < ex_primes; idx++) {
+ pinfo = sk_RSA_PRIME_INFO_value(key->prime_infos, idx);
+ if (!BN_mul(i, i, pinfo->r, ctx)) {
+ ret = -1;
+ goto err;
+ }
+ }
if (BN_cmp(i, key->n) != 0) {
ret = 0;
- RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_N_DOES_NOT_EQUAL_P_Q);
+ if (ex_primes)
+ RSAerr(RSA_F_RSA_CHECK_KEY_EX,
+ RSA_R_N_DOES_NOT_EQUAL_PRODUCT_OF_PRIMES);
+ else
+ RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_N_DOES_NOT_EQUAL_P_Q);
}
- /* d*e = 1 mod lcm(p-1,q-1)? */
+ /* d*e = 1 mod \lambda(n)? */
if (!BN_sub(i, key->p, BN_value_one())) {
ret = -1;
goto err;
@@ -82,7 +110,7 @@ int RSA_check_key_ex(const RSA *key, BN_GENCB *cb)
goto err;
}
- /* now compute k = lcm(i,j) */
+ /* now compute k = \lambda(n) = LCM(i, j, r_3 - 1...) */
if (!BN_mul(l, i, j, ctx)) {
ret = -1;
goto err;
@@ -91,6 +119,21 @@ int RSA_check_key_ex(const RSA *key, BN_GENCB *cb)
ret = -1;
goto err;
}
+ for (idx = 0; idx < ex_primes; idx++) {
+ pinfo = sk_RSA_PRIME_INFO_value(key->prime_infos, idx);
+ if (!BN_sub(k, pinfo->r, BN_value_one())) {
+ ret = -1;
+ goto err;
+ }
+ if (!BN_mul(l, l, k, ctx)) {
+ ret = -1;
+ goto err;
+ }
+ if (!BN_gcd(m, m, k, ctx)) {
+ ret = -1;
+ goto err;
+ }
+ }
if (!BN_div(k, NULL, l, m, ctx)) { /* remainder is 0 */
ret = -1;
goto err;
@@ -145,6 +188,32 @@ int RSA_check_key_ex(const RSA *key, BN_GENCB *cb)
}
}
+ for (idx = 0; idx < ex_primes; idx++) {
+ pinfo = sk_RSA_PRIME_INFO_value(key->prime_infos, idx);
+ /* d_i = d mod (r_i - 1)? */
+ if (!BN_sub(i, pinfo->r, BN_value_one())) {
+ ret = -1;
+ goto err;
+ }
+ if (!BN_mod(j, key->d, i, ctx)) {
+ ret = -1;
+ goto err;
+ }
+ if (BN_cmp(j, pinfo->d) != 0) {
+ ret = 0;
+ RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_MP_EXPONENT_NOT_CONGRUENT_TO_D);
+ }
+ /* t_i = R_i ^ -1 mod r_i ? */
+ if (!BN_mod_inverse(i, pinfo->pp, pinfo->r, ctx)) {
+ ret = -1;
+ goto err;
+ }
+ if (BN_cmp(i, pinfo->t) != 0) {
+ ret = 0;
+ RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_MP_COEFFICIENT_NOT_INVERSE_OF_R);
+ }
+ }
+
err:
BN_free(i);
BN_free(j);