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)
This commit is contained in:
Paul Yang 2017-08-02 02:19:43 +08:00
parent b000470873
commit 665d899fa6
29 changed files with 1560 additions and 100 deletions

View File

@ -9,6 +9,9 @@
Changes between 1.1.0f and 1.1.1 [xx XXX xxxx]
*) Add multi-prime RSA (RFC 8017) support.
[Paul Yang]
*) Add SM3 implemented according to GB/T 32905-2016
[ Jack Lloyd <jack.lloyd@ribose.com>,
Ronald Tse <ronald.tse@ribose.com>,

View File

@ -27,13 +27,14 @@ NON_EMPTY_TRANSLATION_UNIT
# include <openssl/rand.h>
# define DEFBITS 2048
# define DEFPRIMES 2
static int genrsa_cb(int p, int n, BN_GENCB *cb);
typedef enum OPTION_choice {
OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
OPT_3, OPT_F4, OPT_ENGINE,
OPT_OUT, OPT_PASSOUT, OPT_CIPHER,
OPT_OUT, OPT_PASSOUT, OPT_CIPHER, OPT_PRIMES,
OPT_R_ENUM
} OPTION_CHOICE;
@ -49,6 +50,7 @@ const OPTIONS genrsa_options[] = {
# ifndef OPENSSL_NO_ENGINE
{"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
# endif
{"primes", OPT_PRIMES, 'p', "Specify number of primes"},
{NULL}
};
@ -62,7 +64,7 @@ int genrsa_main(int argc, char **argv)
const BIGNUM *e;
RSA *rsa = NULL;
const EVP_CIPHER *enc = NULL;
int ret = 1, num = DEFBITS, private = 0;
int ret = 1, num = DEFBITS, private = 0, primes = DEFPRIMES;
unsigned long f4 = RSA_F4;
char *outfile = NULL, *passoutarg = NULL, *passout = NULL;
char *prog, *hexe, *dece;
@ -108,6 +110,10 @@ opthelp:
if (!opt_cipher(opt_unknown(), &enc))
goto end;
break;
case OPT_PRIMES:
if (!opt_int(opt_arg(), &primes))
goto end;
break;
}
}
argc = opt_num_rest();
@ -131,13 +137,14 @@ opthelp:
if (out == NULL)
goto end;
BIO_printf(bio_err, "Generating RSA private key, %d bit long modulus\n",
num);
BIO_printf(bio_err, "Generating RSA private key, %d bit long modulus (%d primes)\n",
num, primes);
rsa = eng ? RSA_new_method(eng) : RSA_new();
if (rsa == NULL)
goto end;
if (!BN_set_word(bn, f4) || !RSA_generate_key_ex(rsa, num, bn, cb))
if (!BN_set_word(bn, f4)
|| !RSA_generate_multi_prime_key(rsa, num, primes, bn, cb))
goto end;
RSA_get0_key(rsa, NULL, &e, NULL);

View File

@ -339,7 +339,8 @@ static int found(const char *name, const OPT_PAIR *pairs, int *result)
typedef enum OPTION_choice {
OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
OPT_ELAPSED, OPT_EVP, OPT_DECRYPT, OPT_ENGINE, OPT_MULTI,
OPT_MR, OPT_MB, OPT_MISALIGN, OPT_ASYNCJOBS, OPT_R_ENUM
OPT_MR, OPT_MB, OPT_MISALIGN, OPT_ASYNCJOBS, OPT_R_ENUM,
OPT_PRIMES
} OPTION_CHOICE;
const OPTIONS speed_options[] = {
@ -366,6 +367,7 @@ const OPTIONS speed_options[] = {
#ifndef OPENSSL_NO_ENGINE
{"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
#endif
{"primes", OPT_PRIMES, 'p', "Specify number of primes (for RSA only)"},
{NULL},
};
@ -1325,6 +1327,7 @@ int speed_main(int argc, char **argv)
sizeof(test15360)
};
int rsa_doit[RSA_NUM] = { 0 };
int primes = RSA_DEFAULT_PRIME_NUM;
#endif
#ifndef OPENSSL_NO_DSA
static const unsigned int dsa_bits[DSA_NUM] = { 512, 1024, 2048 };
@ -1459,6 +1462,10 @@ int speed_main(int argc, char **argv)
if (!opt_rand(o))
goto end;
break;
case OPT_PRIMES:
if (!opt_int(opt_arg(), &primes))
goto end;
break;
}
}
argc = opt_num_rest();
@ -1615,6 +1622,10 @@ int speed_main(int argc, char **argv)
#ifndef OPENSSL_NO_RSA
for (i = 0; i < loopargs_len; i++) {
if (primes > RSA_DEFAULT_PRIME_NUM) {
/* for multi-prime RSA, skip this */
break;
}
for (k = 0; k < RSA_NUM; k++) {
const unsigned char *p;
@ -2395,6 +2406,34 @@ int speed_main(int argc, char **argv)
if (!rsa_doit[testnum])
continue;
for (i = 0; i < loopargs_len; i++) {
if (primes > 2) {
/* we haven't set keys yet, generate multi-prime RSA keys */
BIGNUM *bn = BN_new();
if (bn == NULL)
goto end;
if (!BN_set_word(bn, RSA_F4)) {
BN_free(bn);
goto end;
}
BIO_printf(bio_err, "Generate multi-prime RSA key for %s\n",
rsa_choices[testnum].name);
loopargs[i].rsa_key[testnum] = RSA_new();
if (loopargs[i].rsa_key[testnum] == NULL) {
BN_free(bn);
goto end;
}
if (!RSA_generate_multi_prime_key(loopargs[i].rsa_key[testnum],
rsa_bits[testnum],
primes, bn, NULL)) {
BN_free(bn);
goto end;
}
BN_free(bn);
}
st = RSA_sign(NID_md5_sha1, loopargs[i].buf, 36, loopargs[i].buf2,
&loopargs[i].siglen, loopargs[i].rsa_key[testnum]);
if (st == 0)

View File

@ -2224,6 +2224,7 @@ RSA_R_INVALID_HEADER:137:invalid header
RSA_R_INVALID_LABEL:160:invalid label
RSA_R_INVALID_MESSAGE_LENGTH:131:invalid message length
RSA_R_INVALID_MGF1_MD:156:invalid mgf1 md
RSA_R_INVALID_MULTI_PRIME_KEY:167:invalid multi prime key
RSA_R_INVALID_OAEP_PARAMETERS:161:invalid oaep parameters
RSA_R_INVALID_PADDING:138:invalid padding
RSA_R_INVALID_PADDING_MODE:141:invalid padding mode
@ -2233,12 +2234,17 @@ RSA_R_INVALID_SALT_LENGTH:150:invalid salt length
RSA_R_INVALID_TRAILER:139:invalid trailer
RSA_R_INVALID_X931_DIGEST:142:invalid x931 digest
RSA_R_IQMP_NOT_INVERSE_OF_Q:126:iqmp not inverse of q
RSA_R_KEY_PRIME_NUM_INVALID:165:key prime num invalid
RSA_R_KEY_SIZE_TOO_SMALL:120:key size too small
RSA_R_LAST_OCTET_INVALID:134:last octet invalid
RSA_R_MGF1_DIGEST_NOT_ALLOWED:152:mgf1 digest not allowed
RSA_R_MODULUS_TOO_LARGE:105:modulus too large
RSA_R_MP_COEFFICIENT_NOT_INVERSE_OF_R:168:mp coefficient not inverse of r
RSA_R_MP_EXPONENT_NOT_CONGRUENT_TO_D:169:mp exponent not congruent to d
RSA_R_MP_R_NOT_PRIME:170:mp r not prime
RSA_R_NO_PUBLIC_EXPONENT:140:no public exponent
RSA_R_NULL_BEFORE_BLOCK_MISSING:113:null before block missing
RSA_R_N_DOES_NOT_EQUAL_PRODUCT_OF_PRIMES:172:n does not equal product of primes
RSA_R_N_DOES_NOT_EQUAL_P_Q:127:n does not equal p q
RSA_R_OAEP_DECODING_ERROR:121:oaep decoding error
RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE:148:\

View File

@ -3,4 +3,4 @@ SOURCE[../../libcrypto]=\
rsa_ossl.c rsa_gen.c rsa_lib.c rsa_sign.c rsa_saos.c rsa_err.c \
rsa_pk1.c rsa_ssl.c rsa_none.c rsa_oaep.c rsa_chk.c \
rsa_pss.c rsa_x931.c rsa_asn1.c rsa_depr.c rsa_ameth.c rsa_prn.c \
rsa_pmeth.c rsa_crpt.c rsa_x931g.c rsa_meth.c
rsa_pmeth.c rsa_crpt.c rsa_x931g.c rsa_meth.c rsa_mp.c

View File

@ -316,10 +316,11 @@ static int pkey_rsa_print(BIO *bp, const EVP_PKEY *pkey, int off, int priv)
const RSA *x = pkey->pkey.rsa;
char *str;
const char *s;
int ret = 0, mod_len = 0;
int ret = 0, mod_len = 0, ex_primes;
if (x->n != NULL)
mod_len = BN_num_bits(x->n);
ex_primes = sk_RSA_PRIME_INFO_num(x->prime_infos);
if (!BIO_indent(bp, off, 128))
goto err;
@ -328,7 +329,8 @@ static int pkey_rsa_print(BIO *bp, const EVP_PKEY *pkey, int off, int priv)
goto err;
if (priv && x->d) {
if (BIO_printf(bp, "Private-Key: (%d bit)\n", mod_len) <= 0)
if (BIO_printf(bp, "Private-Key: (%d bit, %d primes)\n",
mod_len, ex_primes <= 0 ? 2 : ex_primes + 2) <= 0)
goto err;
str = "modulus:";
s = "publicExponent:";
@ -343,6 +345,8 @@ static int pkey_rsa_print(BIO *bp, const EVP_PKEY *pkey, int off, int priv)
if (!ASN1_bn_print(bp, s, x->e, NULL, off))
goto err;
if (priv) {
int i;
if (!ASN1_bn_print(bp, "privateExponent:", x->d, NULL, off))
goto err;
if (!ASN1_bn_print(bp, "prime1:", x->p, NULL, off))
@ -355,6 +359,39 @@ static int pkey_rsa_print(BIO *bp, const EVP_PKEY *pkey, int off, int priv)
goto err;
if (!ASN1_bn_print(bp, "coefficient:", x->iqmp, NULL, off))
goto err;
for (i = 0; i < sk_RSA_PRIME_INFO_num(x->prime_infos); i++) {
/* print multi-prime info */
BIGNUM *bn = NULL;
RSA_PRIME_INFO *pinfo;
int j;
pinfo = sk_RSA_PRIME_INFO_value(x->prime_infos, i);
for (j = 0; j < 3; j++) {
if (!BIO_indent(bp, off, 128))
goto err;
switch (j) {
case 0:
if (BIO_printf(bp, "prime%d:", i + 3) <= 0)
goto err;
bn = pinfo->r;
break;
case 1:
if (BIO_printf(bp, "exponent%d:", i + 3) <= 0)
goto err;
bn = pinfo->d;
break;
case 2:
if (BIO_printf(bp, "coefficient%d:", i + 3) <= 0)
goto err;
bn = pinfo->t;
break;
default:
break;
}
if (!ASN1_bn_print(bp, "", bn, NULL, off))
goto err;
}
}
}
if (pkey_is_pss(pkey) && !rsa_pss_param_print(bp, 1, x->pss, off))
goto err;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2000-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
@ -14,7 +14,11 @@
#include <openssl/asn1t.h>
#include "rsa_locl.h"
/* Override the default free and new methods */
/*
* Override the default free and new methods,
* and calculate helper products for multi-prime
* RSA keys.
*/
static int rsa_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
void *exarg)
{
@ -27,10 +31,23 @@ static int rsa_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
RSA_free((RSA *)*pval);
*pval = NULL;
return 2;
} else if (operation == ASN1_OP_D2I_POST) {
if (((RSA *)*pval)->version != RSA_ASN1_VERSION_MULTI) {
/* not a multi-prime key, skip */
return 1;
}
return (rsa_multip_calc_product((RSA *)*pval) == 1) ? 2 : 0;
}
return 1;
}
/* Based on definitions in RFC 8017 appendix A.1.2 */
ASN1_SEQUENCE(RSA_PRIME_INFO) = {
ASN1_SIMPLE(RSA_PRIME_INFO, r, CBIGNUM),
ASN1_SIMPLE(RSA_PRIME_INFO, d, CBIGNUM),
ASN1_SIMPLE(RSA_PRIME_INFO, t, CBIGNUM),
} ASN1_SEQUENCE_END(RSA_PRIME_INFO)
ASN1_SEQUENCE_cb(RSAPrivateKey, rsa_cb) = {
ASN1_EMBED(RSA, version, INT32),
ASN1_SIMPLE(RSA, n, BIGNUM),
@ -40,7 +57,8 @@ ASN1_SEQUENCE_cb(RSAPrivateKey, rsa_cb) = {
ASN1_SIMPLE(RSA, q, CBIGNUM),
ASN1_SIMPLE(RSA, dmp1, CBIGNUM),
ASN1_SIMPLE(RSA, dmq1, CBIGNUM),
ASN1_SIMPLE(RSA, iqmp, CBIGNUM)
ASN1_SIMPLE(RSA, iqmp, CBIGNUM),
ASN1_SEQUENCE_OF_OPT(RSA, prime_infos, RSA_PRIME_INFO)
} ASN1_SEQUENCE_END_cb(RSA, RSAPrivateKey)

View File

@ -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);

View File

@ -147,6 +147,8 @@ static const ERR_STRING_DATA RSA_str_reasons[] = {
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_MESSAGE_LENGTH),
"invalid message length"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_MGF1_MD), "invalid mgf1 md"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_MULTI_PRIME_KEY),
"invalid multi prime key"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_OAEP_PARAMETERS),
"invalid oaep parameters"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_PADDING), "invalid padding"},
@ -163,14 +165,23 @@ static const ERR_STRING_DATA RSA_str_reasons[] = {
"invalid x931 digest"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_IQMP_NOT_INVERSE_OF_Q),
"iqmp not inverse of q"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_KEY_PRIME_NUM_INVALID),
"key prime num invalid"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_KEY_SIZE_TOO_SMALL), "key size too small"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_LAST_OCTET_INVALID), "last octet invalid"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_MGF1_DIGEST_NOT_ALLOWED),
"mgf1 digest not allowed"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_MODULUS_TOO_LARGE), "modulus too large"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_MP_COEFFICIENT_NOT_INVERSE_OF_R),
"mp coefficient not inverse of r"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_MP_EXPONENT_NOT_CONGRUENT_TO_D),
"mp exponent not congruent to d"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_MP_R_NOT_PRIME), "mp r not prime"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_NO_PUBLIC_EXPONENT), "no public exponent"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_NULL_BEFORE_BLOCK_MISSING),
"null before block missing"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_N_DOES_NOT_EQUAL_PRODUCT_OF_PRIMES),
"n does not equal product of primes"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_N_DOES_NOT_EQUAL_P_Q),
"n does not equal p q"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_OAEP_DECODING_ERROR),

View File

@ -1,5 +1,5 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-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
@ -19,7 +19,7 @@
#include <openssl/bn.h>
#include "rsa_locl.h"
static int rsa_builtin_keygen(RSA *rsa, int bits, BIGNUM *e_value,
static int rsa_builtin_keygen(RSA *rsa, int bits, int primes, BIGNUM *e_value,
BN_GENCB *cb);
/*
@ -31,17 +31,43 @@ static int rsa_builtin_keygen(RSA *rsa, int bits, BIGNUM *e_value,
*/
int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb)
{
if (rsa->meth->rsa_keygen)
if (rsa->meth->rsa_keygen != NULL)
return rsa->meth->rsa_keygen(rsa, bits, e_value, cb);
return rsa_builtin_keygen(rsa, bits, e_value, cb);
return RSA_generate_multi_prime_key(rsa, bits, RSA_DEFAULT_PRIME_NUM,
e_value, cb);
}
static int rsa_builtin_keygen(RSA *rsa, int bits, BIGNUM *e_value,
int RSA_generate_multi_prime_key(RSA *rsa, int bits, int primes,
BIGNUM *e_value, BN_GENCB *cb)
{
/* multi-prime is only supported with the builtin key generation */
if (rsa->meth->rsa_multi_prime_keygen != NULL)
return rsa->meth->rsa_multi_prime_keygen(rsa, bits, primes,
e_value, cb);
return rsa_builtin_keygen(rsa, bits, primes, e_value, cb);
}
static int rsa_builtin_keygen(RSA *rsa, int bits, int primes, BIGNUM *e_value,
BN_GENCB *cb)
{
BIGNUM *r0 = NULL, *r1 = NULL, *r2 = NULL, *r3 = NULL, *tmp;
int bitsp, bitsq, ok = -1, n = 0;
BIGNUM *r0 = NULL, *r1 = NULL, *r2 = NULL, *tmp, *prime;
int ok = -1, n = 0, bitsr[RSA_MAX_PRIME_NUM], bitse = 0;
int i = 0, quo = 0, rmd = 0, adj = 0, retries = 0;
RSA_PRIME_INFO *pinfo = NULL;
STACK_OF(RSA_PRIME_INFO) *prime_infos = NULL;
BN_CTX *ctx = NULL;
BN_ULONG bitst = 0;
/*
* From Github pull request #4241:
*
* We are in disagreement on how to handle security trade-off, in other
* words:
*
* mechanical-check-for-maximum-of-16-prime-factors vs.
* limiting-number-depending-on-length-less-factors-for-shorter-keys.
*/
/*
* When generating ridiculously small keys, we can get stuck
@ -53,6 +79,12 @@ static int rsa_builtin_keygen(RSA *rsa, int bits, BIGNUM *e_value,
goto err;
}
if (primes < RSA_DEFAULT_PRIME_NUM
|| primes > RSA_MAX_PRIME_NUM || bits <= primes) {
RSAerr(RSA_F_RSA_BUILTIN_KEYGEN, RSA_R_KEY_PRIME_NUM_INVALID);
goto err;
}
ctx = BN_CTX_new();
if (ctx == NULL)
goto err;
@ -60,12 +92,29 @@ static int rsa_builtin_keygen(RSA *rsa, int bits, BIGNUM *e_value,
r0 = BN_CTX_get(ctx);
r1 = BN_CTX_get(ctx);
r2 = BN_CTX_get(ctx);
r3 = BN_CTX_get(ctx);
if (r3 == NULL)
if (r2 == NULL)
goto err;
bitsp = (bits + 1) / 2;
bitsq = bits - bitsp;
/* divide bits into 'primes' pieces evenly */
quo = bits / primes;
rmd = bits % primes;
if (primes > RSA_DEFAULT_PRIME_NUM && quo < RSA_MIN_PRIME_SIZE) {
/*
* this means primes are too many for the key bits.
*
* This only affects multi-prime keys. For normal RSA,
* it's limited above (bits >= 16, hence each prime >= 8).
*
* This is done in this way because the original normal
* RSA's behavior should not alter at least in OpenSSL 1.1.1.
*/
RSAerr(RSA_F_RSA_BUILTIN_KEYGEN, RSA_R_KEY_PRIME_NUM_INVALID);
goto err;
}
for (i = 0; i < primes; i++)
bitsr[i] = (i < rmd) ? quo + 1 : quo;
/* We need the RSA components non-NULL */
if (!rsa->n && ((rsa->n = BN_new()) == NULL))
@ -85,62 +134,191 @@ static int rsa_builtin_keygen(RSA *rsa, int bits, BIGNUM *e_value,
if (!rsa->iqmp && ((rsa->iqmp = BN_secure_new()) == NULL))
goto err;
/* initialize multi-prime components */
if (primes > RSA_DEFAULT_PRIME_NUM) {
rsa->version = RSA_ASN1_VERSION_MULTI;
prime_infos = sk_RSA_PRIME_INFO_new_reserve(NULL, primes - 2);
if (prime_infos == NULL)
goto err;
if (rsa->prime_infos != NULL) {
/* could this happen? */
sk_RSA_PRIME_INFO_pop_free(rsa->prime_infos, rsa_multip_info_free);
}
rsa->prime_infos = prime_infos;
/* prime_info from 2 to |primes| -1 */
for (i = 2; i < primes; i++) {
pinfo = rsa_multip_info_new();
if (pinfo == NULL)
goto err;
(void)sk_RSA_PRIME_INFO_push(prime_infos, pinfo);
}
}
if (BN_copy(rsa->e, e_value) == NULL)
goto err;
/* generate p and q */
for (;;) {
if (!BN_generate_prime_ex(rsa->p, bitsp, 0, NULL, NULL, cb))
goto err;
if (!BN_sub(r2, rsa->p, BN_value_one()))
goto err;
if (!BN_gcd(r1, r2, rsa->e, ctx))
goto err;
if (BN_is_one(r1))
break;
if (!BN_GENCB_call(cb, 2, n++))
goto err;
}
if (!BN_GENCB_call(cb, 3, 0))
goto err;
for (;;) {
do {
if (!BN_generate_prime_ex(rsa->q, bitsq, 0, NULL, NULL, cb))
/* generate p, q and other primes (if any) */
for (i = 0; i < primes; i++) {
adj = 0;
retries = 0;
if (i == 0) {
prime = rsa->p;
} else if (i == 1) {
prime = rsa->q;
} else {
pinfo = sk_RSA_PRIME_INFO_value(prime_infos, i - 2);
prime = pinfo->r;
}
for (;;) {
redo:
if (!BN_generate_prime_ex(prime, bitsr[i] + adj, 0, NULL, NULL, cb))
goto err;
} while (BN_cmp(rsa->p, rsa->q) == 0);
if (!BN_sub(r2, rsa->q, BN_value_one()))
/*
* prime should not be equal to p, q, r_3...
* (those primes prior to this one)
*/
{
int j;
for (j = 0; j < i; j++) {
BIGNUM *prev_prime;
if (j == 0)
prev_prime = rsa->p;
else if (j == 1)
prev_prime = rsa->q;
else
prev_prime = sk_RSA_PRIME_INFO_value(prime_infos,
j - 2)->r;
if (!BN_cmp(prime, prev_prime)) {
goto redo;
}
}
}
if (!BN_sub(r2, prime, BN_value_one()))
goto err;
if (!BN_gcd(r1, r2, rsa->e, ctx))
goto err;
if (BN_is_one(r1))
break;
if (!BN_GENCB_call(cb, 2, n++))
goto err;
}
bitse += bitsr[i];
/* calculate n immediately to see if it's sufficient */
if (i == 1) {
/* we get at least 2 primes */
if (!BN_mul(r1, rsa->p, rsa->q, ctx))
goto err;
} else if (i != 0) {
/* modulus n = p * q * r_3 * r_4 ... */
if (!BN_mul(r1, rsa->n, prime, ctx))
goto err;
} else {
/* i == 0, do nothing */
if (!BN_GENCB_call(cb, 3, i))
goto err;
continue;
}
/*
* if |r1|, product of factors so far, is not as long as expected
* (by checking the first 4 bits are less than 0x9 or greater than
* 0xF). If so, re-generate the last prime.
*
* NOTE: This actually can't happen in two-prime case, because of
* the way factors are generated.
*
* Besides, another consideration is, for multi-prime case, even the
* length modulus is as long as expected, the modulus could start at
* 0x8, which could be utilized to distinguish a multi-prime private
* key by using the modulus in a certificate. This is also covered
* by checking the length should not be less than 0x9.
*/
if (!BN_rshift(r2, r1, bitse - 4))
goto err;
if (!BN_gcd(r1, r2, rsa->e, ctx))
bitst = BN_get_word(r2);
if (bitst < 0x9 || bitst > 0xF) {
/*
* For keys with more than 4 primes, we attempt longer factor to
* meet length requirement.
*
* Otherwise, we just re-generate the prime with the same length.
*
* This strategy has the following goals:
*
* 1. 1024-bit factors are effcient when using 3072 and 4096-bit key
* 2. stay the same logic with normal 2-prime key
*/
bitse -= bitsr[i];
if (!BN_GENCB_call(cb, 2, n++))
goto err;
if (primes > 4) {
if (bitst < 0x9)
adj++;
else
adj--;
} else if (retries == 4) {
/*
* re-generate all primes from scratch, mainly used
* in 4 prime case to avoid long loop. Max retry times
* is set to 4.
*/
i = -1;
bitse = 0;
continue;
}
retries++;
goto redo;
}
/* save product of primes for further use, for multi-prime only */
if (i > 1 && BN_copy(pinfo->pp, rsa->n) == NULL)
goto err;
if (BN_is_one(r1))
break;
if (!BN_GENCB_call(cb, 2, n++))
if (BN_copy(rsa->n, r1) == NULL)
goto err;
if (!BN_GENCB_call(cb, 3, i))
goto err;
}
if (!BN_GENCB_call(cb, 3, 1))
goto err;
if (BN_cmp(rsa->p, rsa->q) < 0) {
tmp = rsa->p;
rsa->p = rsa->q;
rsa->q = tmp;
}
/* calculate n */
if (!BN_mul(rsa->n, rsa->p, rsa->q, ctx))
goto err;
/* calculate d */
/* p - 1 */
if (!BN_sub(r1, rsa->p, BN_value_one()))
goto err; /* p-1 */
goto err;
/* q - 1 */
if (!BN_sub(r2, rsa->q, BN_value_one()))
goto err; /* q-1 */
goto err;
/* (p - 1)(q - 1) */
if (!BN_mul(r0, r1, r2, ctx))
goto err; /* (p-1)(q-1) */
goto err;
/* multi-prime */
for (i = 2; i < primes; i++) {
pinfo = sk_RSA_PRIME_INFO_value(prime_infos, i - 2);
/* save r_i - 1 to pinfo->d temporarily */
if (!BN_sub(pinfo->d, pinfo->r, BN_value_one()))
goto err;
if (!BN_mul(r0, r0, pinfo->d, ctx))
goto err;
}
{
BIGNUM *pr0 = BN_new();
if (pr0 == NULL)
goto err;
BN_with_flags(pr0, r0, BN_FLG_CONSTTIME);
if (!BN_mod_inverse(rsa->d, rsa->e, pr0, ctx)) {
BN_free(pr0);
@ -155,15 +333,26 @@ static int rsa_builtin_keygen(RSA *rsa, int bits, BIGNUM *e_value,
if (d == NULL)
goto err;
BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
if ( /* calculate d mod (p-1) */
!BN_mod(rsa->dmp1, d, r1, ctx)
/* calculate d mod (q-1) */
/* calculate d mod (p-1) and d mod (q - 1) */
if (!BN_mod(rsa->dmp1, d, r1, ctx)
|| !BN_mod(rsa->dmq1, d, r2, ctx)) {
BN_free(d);
goto err;
}
/* calculate CRT exponents */
for (i = 2; i < primes; i++) {
pinfo = sk_RSA_PRIME_INFO_value(prime_infos, i - 2);
/* pinfo->d == r_i - 1 */
if (!BN_mod(pinfo->d, d, pinfo->d, ctx)) {
BN_free(d);
goto err;
}
}
/* We MUST free d before any further use of rsa->d */
BN_free(d);
}
@ -180,6 +369,17 @@ static int rsa_builtin_keygen(RSA *rsa, int bits, BIGNUM *e_value,
BN_free(p);
goto err;
}
/* calculate CRT coefficient for other primes */
for (i = 2; i < primes; i++) {
pinfo = sk_RSA_PRIME_INFO_value(prime_infos, i - 2);
BN_with_flags(p, pinfo->r, BN_FLG_CONSTTIME);
if (!BN_mod_inverse(pinfo->t, pinfo->pp, p, ctx)) {
BN_free(p);
goto err;
}
}
/* We MUST free p before any further use of rsa->p */
BN_free(p);
}
@ -193,6 +393,5 @@ static int rsa_builtin_keygen(RSA *rsa, int bits, BIGNUM *e_value,
if (ctx != NULL)
BN_CTX_end(ctx);
BN_CTX_free(ctx);
return ok;
}

View File

@ -134,6 +134,7 @@ void RSA_free(RSA *r)
BN_clear_free(r->dmq1);
BN_clear_free(r->iqmp);
RSA_PSS_PARAMS_free(r->pss);
sk_RSA_PRIME_INFO_pop_free(r->prime_infos, rsa_multip_info_free);
BN_BLINDING_free(r->blinding);
BN_BLINDING_free(r->mt_blinding);
OPENSSL_free(r->bignum_data);
@ -240,6 +241,71 @@ int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp)
return 1;
}
/*
* Is it better to export RSA_PRIME_INFO structure
* and related functions to let user pass a triplet?
*/
int RSA_set0_multi_prime_params(RSA *r, BIGNUM *primes[], BIGNUM *exps[],
BIGNUM *coeffs[], int pnum)
{
STACK_OF(RSA_PRIME_INFO) *prime_infos, *old = NULL;
RSA_PRIME_INFO *pinfo;
int i;
if (primes == NULL || exps == NULL || coeffs == NULL || pnum == 0)
return 0;
prime_infos = sk_RSA_PRIME_INFO_new_reserve(NULL, pnum);
if (prime_infos == NULL)
return 0;
if (r->prime_infos != NULL)
old = r->prime_infos;
for (i = 0; i < pnum; i++) {
pinfo = rsa_multip_info_new();
if (pinfo == NULL)
goto err;
if (primes[i] != NULL && exps[i] != NULL && coeffs[i] != NULL) {
BN_free(pinfo->r);
BN_free(pinfo->d);
BN_free(pinfo->t);
pinfo->r = primes[i];
pinfo->d = exps[i];
pinfo->t = coeffs[i];
} else {
rsa_multip_info_free(pinfo);
goto err;
}
(void)sk_RSA_PRIME_INFO_push(prime_infos, pinfo);
}
r->prime_infos = prime_infos;
if (!rsa_multip_calc_product(r)) {
r->prime_infos = old;
goto err;
}
if (old != NULL) {
/*
* This is hard to deal with, since the old infos could
* also be set by this function and r, d, t should not
* be freed in that case. So currently, stay consistent
* with other *set0* functions: just free it...
*/
sk_RSA_PRIME_INFO_pop_free(old, rsa_multip_info_free);
}
r->version = RSA_ASN1_VERSION_MULTI;
return 1;
err:
/* r, d, t should not be freed */
sk_RSA_PRIME_INFO_pop_free(prime_infos, rsa_multip_info_free_ex);
return 0;
}
void RSA_get0_key(const RSA *r,
const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
{
@ -259,6 +325,36 @@ void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q)
*q = r->q;
}
int RSA_get_multi_prime_extra_count(const RSA *r)
{
int pnum;
pnum = sk_RSA_PRIME_INFO_num(r->prime_infos);
if (pnum <= 0)
pnum = 0;
return pnum;
}
int RSA_get0_multi_prime_factors(const RSA *r, const BIGNUM *primes[])
{
int pnum, i;
RSA_PRIME_INFO *pinfo;
if ((pnum = RSA_get_multi_prime_extra_count(r)) == 0)
return 0;
/*
* return other primes
* it's caller's responsibility to allocate oth_primes[pnum]
*/
for (i = 0; i < pnum; i++) {
pinfo = sk_RSA_PRIME_INFO_value(r->prime_infos, i);
primes[i] = pinfo->r;
}
return 1;
}
void RSA_get0_crt_params(const RSA *r,
const BIGNUM **dmp1, const BIGNUM **dmq1,
const BIGNUM **iqmp)
@ -271,6 +367,32 @@ void RSA_get0_crt_params(const RSA *r,
*iqmp = r->iqmp;
}
int RSA_get0_multi_prime_crt_params(const RSA *r, const BIGNUM *exps[],
const BIGNUM *coeffs[])
{
int pnum;
if ((pnum = RSA_get_multi_prime_extra_count(r)) == 0)
return 0;
/* return other primes */
if (exps != NULL || coeffs != NULL) {
RSA_PRIME_INFO *pinfo;
int i;
/* it's the user's job to guarantee the buffer length */
for (i = 0; i < pnum; i++) {
pinfo = sk_RSA_PRIME_INFO_value(r->prime_infos, i);
if (exps != NULL)
exps[i] = pinfo->d;
if (coeffs != NULL)
coeffs[i] = pinfo->t;
}
}
return 1;
}
void RSA_clear_flags(RSA *r, int flags)
{
r->flags &= ~flags;
@ -286,6 +408,12 @@ void RSA_set_flags(RSA *r, int flags)
r->flags |= flags;
}
int RSA_get_version(RSA *r)
{
/* { two-prime(0), multi(1) } */
return r->version;
}
ENGINE *RSA_get0_engine(const RSA *r)
{
return r->engine;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2006-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
@ -10,6 +10,21 @@
#include <openssl/rsa.h>
#include "internal/refcount.h"
#define RSA_MAX_PRIME_NUM 16
#define RSA_MIN_PRIME_SIZE 64
typedef struct rsa_prime_info_st {
BIGNUM *r;
BIGNUM *d;
BIGNUM *t;
/* save product of primes prior to this one */
BIGNUM *pp;
BN_MONT_CTX *m;
} RSA_PRIME_INFO;
DECLARE_ASN1_ITEM(RSA_PRIME_INFO)
DEFINE_STACK_OF(RSA_PRIME_INFO)
struct rsa_st {
/*
* The first parameter is used to pickup errors where this is passed
@ -28,6 +43,8 @@ struct rsa_st {
BIGNUM *dmp1;
BIGNUM *dmq1;
BIGNUM *iqmp;
/* for multi-prime RSA, defined in RFC 8017 */
STACK_OF(RSA_PRIME_INFO) *prime_infos;
/* If a PSS only key this contains the parameter restrictions */
RSA_PSS_PARAMS *pss;
/* be careful using this if the RSA structure is shared */
@ -91,6 +108,8 @@ struct rsa_meth_st {
* things as "builtin software" implementations.
*/
int (*rsa_keygen) (RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
int (*rsa_multi_prime_keygen) (RSA *rsa, int bits, int primes,
BIGNUM *e, BN_GENCB *cb);
};
extern int int_rsa_verify(int dtype, const unsigned char *m,
@ -105,3 +124,8 @@ RSA_PSS_PARAMS *rsa_pss_params_create(const EVP_MD *sigmd,
const EVP_MD *mgf1md, int saltlen);
int rsa_pss_get_param(const RSA_PSS_PARAMS *pss, const EVP_MD **pmd,
const EVP_MD **pmgf1md, int *psaltlen);
/* internal function to clear and free multi-prime parameters */
void rsa_multip_info_free_ex(RSA_PRIME_INFO *pinfo);
void rsa_multip_info_free(RSA_PRIME_INFO *pinfo);
RSA_PRIME_INFO *rsa_multip_info_new(void);
int rsa_multip_calc_product(RSA *rsa);

View File

@ -271,3 +271,17 @@ int RSA_meth_set_keygen(RSA_METHOD *meth,
return 1;
}
int (*RSA_meth_get_multi_prime_keygen(const RSA_METHOD *meth))
(RSA *rsa, int bits, int primes, BIGNUM *e, BN_GENCB *cb)
{
return meth->rsa_multi_prime_keygen;
}
int RSA_meth_set_multi_prime_keygen(RSA_METHOD *meth,
int (*keygen) (RSA *rsa, int bits,
int primes, BIGNUM *e,
BN_GENCB *cb))
{
meth->rsa_multi_prime_keygen = keygen;
return 1;
}

95
crypto/rsa/rsa_mp.c Normal file
View File

@ -0,0 +1,95 @@
/*
* Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2017 BaishanCloud. 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
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/bn.h>
#include "rsa_locl.h"
void rsa_multip_info_free_ex(RSA_PRIME_INFO *pinfo)
{
/* free pp and pinfo only */
BN_clear_free(pinfo->pp);
OPENSSL_free(pinfo);
}
void rsa_multip_info_free(RSA_PRIME_INFO *pinfo)
{
/* free a RSA_PRIME_INFO structure */
BN_clear_free(pinfo->r);
BN_clear_free(pinfo->d);
BN_clear_free(pinfo->t);
rsa_multip_info_free_ex(pinfo);
}
RSA_PRIME_INFO *rsa_multip_info_new(void)
{
RSA_PRIME_INFO *pinfo;
/* create a RSA_PRIME_INFO structure */
pinfo = OPENSSL_zalloc(sizeof(RSA_PRIME_INFO));
if (pinfo == NULL)
return NULL;
if ((pinfo->r = BN_secure_new()) == NULL)
goto err;
if ((pinfo->d = BN_secure_new()) == NULL)
goto err;
if ((pinfo->t = BN_secure_new()) == NULL)
goto err;
if ((pinfo->pp = BN_secure_new()) == NULL)
goto err;
return pinfo;
err:
BN_free(pinfo->r);
BN_free(pinfo->d);
BN_free(pinfo->t);
BN_free(pinfo->pp);
return NULL;
}
/* Refill products of primes */
int rsa_multip_calc_product(RSA *rsa)
{
RSA_PRIME_INFO *pinfo;
BIGNUM *p1 = NULL, *p2 = NULL;
BN_CTX *ctx = NULL;
int i, rv = 0, ex_primes;
if ((ex_primes = sk_RSA_PRIME_INFO_num(rsa->prime_infos)) <= 0) {
/* invalid */
goto err;
}
if ((ctx = BN_CTX_new()) == NULL)
goto err;
/* calculate pinfo->pp = p * q for first 'extra' prime */
p1 = rsa->p;
p2 = rsa->q;
for (i = 0; i < ex_primes; i++) {
pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i);
if (pinfo->pp == NULL) {
pinfo->pp = BN_secure_new();
if (pinfo->pp == NULL)
goto err;
}
if (!BN_mul(pinfo->pp, p1, p2, ctx))
goto err;
/* save previous one */
p1 = pinfo->pp;
p2 = pinfo->r;
}
rv = 1;
err:
BN_CTX_free(ctx);
return rv;
}

View File

@ -38,7 +38,8 @@ static RSA_METHOD rsa_pkcs1_ossl_meth = {
NULL,
0, /* rsa_sign */
0, /* rsa_verify */
NULL /* rsa_keygen */
NULL, /* rsa_keygen */
NULL /* rsa_multi_prime_keygen */
};
static const RSA_METHOD *default_RSA_meth = &rsa_pkcs1_ossl_meth;
@ -308,6 +309,7 @@ static int rsa_ossl_private_encrypt(int flen, const unsigned char *from,
}
if ((rsa->flags & RSA_FLAG_EXT_PKEY) ||
(rsa->version == RSA_ASN1_VERSION_MULTI) ||
((rsa->p != NULL) &&
(rsa->q != NULL) &&
(rsa->dmp1 != NULL) && (rsa->dmq1 != NULL) && (rsa->iqmp != NULL))) {
@ -437,6 +439,7 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from,
/* do the decrypt */
if ((rsa->flags & RSA_FLAG_EXT_PKEY) ||
(rsa->version == RSA_ASN1_VERSION_MULTI) ||
((rsa->p != NULL) &&
(rsa->q != NULL) &&
(rsa->dmp1 != NULL) && (rsa->dmq1 != NULL) && (rsa->iqmp != NULL))) {
@ -601,17 +604,23 @@ static int rsa_ossl_public_decrypt(int flen, const unsigned char *from,
static int rsa_ossl_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
{
BIGNUM *r1, *m1, *vrfy;
int ret = 0;
BIGNUM *r1, *m1, *vrfy, *r2, *m[RSA_MAX_PRIME_NUM];
int ret = 0, i, ex_primes = 0;
RSA_PRIME_INFO *pinfo;
BN_CTX_start(ctx);
r1 = BN_CTX_get(ctx);
r2 = BN_CTX_get(ctx);
m1 = BN_CTX_get(ctx);
vrfy = BN_CTX_get(ctx);
if (vrfy == NULL)
goto err;
if (rsa->version == RSA_ASN1_VERSION_MULTI
&& (ex_primes = sk_RSA_PRIME_INFO_num(rsa->prime_infos)) <= 0)
goto err;
{
BIGNUM *p = BN_new(), *q = BN_new();
@ -636,6 +645,28 @@ static int rsa_ossl_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
BN_free(q);
goto err;
}
if (ex_primes > 0) {
/* cache BN_MONT_CTX for other primes */
BIGNUM *r = BN_new();
if (r == NULL) {
BN_free(p);
BN_free(q);
goto err;
}
for (i = 0; i < ex_primes; i++) {
pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i);
BN_with_flags(r, pinfo->r, BN_FLG_CONSTTIME);
if (!BN_MONT_CTX_set_locked(&pinfo->m, rsa->lock, r, ctx)) {
BN_free(p);
BN_free(q);
BN_free(r);
goto err;
}
}
BN_free(r);
}
}
/*
* We MUST free p and q before any further use of rsa->p and rsa->q
@ -705,6 +736,56 @@ static int rsa_ossl_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
BN_free(dmp1);
}
/*
* calculate m_i in multi-prime case
*
* TODO:
* 1. squash the following two loops and calculate |m_i| there.
* 2. remove cc and reuse |c|.
* 3. remove |dmq1| and |dmp1| in previous block and use |di|.
*
* If these things are done, the code will be more readable.
*/
if (ex_primes > 0) {
BIGNUM *di = BN_new(), *cc = BN_new();
if (cc == NULL || di == NULL) {
BN_free(cc);
BN_free(di);
goto err;
}
for (i = 0; i < ex_primes; i++) {
/* prepare m_i */
if ((m[i] = BN_CTX_get(ctx)) == NULL) {
BN_free(cc);
BN_free(di);
goto err;
}
pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i);
/* prepare c and d_i */
BN_with_flags(cc, I, BN_FLG_CONSTTIME);
BN_with_flags(di, pinfo->d, BN_FLG_CONSTTIME);
if (!BN_mod(r1, cc, pinfo->r, ctx)) {
BN_free(cc);
BN_free(di);
goto err;
}
/* compute r1 ^ d_i mod r_i */
if (!rsa->meth->bn_mod_exp(m[i], r1, di, pinfo->r, ctx, pinfo->m)) {
BN_free(cc);
BN_free(di);
goto err;
}
}
BN_free(cc);
BN_free(di);
}
if (!BN_sub(r0, r0, m1))
goto err;
/*
@ -747,6 +828,49 @@ static int rsa_ossl_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
if (!BN_add(r0, r1, m1))
goto err;
/* add m_i to m in multi-prime case */
if (ex_primes > 0) {
BIGNUM *pr2 = BN_new();
if (pr2 == NULL)
goto err;
for (i = 0; i < ex_primes; i++) {
pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i);
if (!BN_sub(r1, m[i], r0)) {
BN_free(pr2);
goto err;
}
if (!BN_mul(r2, r1, pinfo->t, ctx)) {
BN_free(pr2);
goto err;
}
BN_with_flags(pr2, r2, BN_FLG_CONSTTIME);
if (!BN_mod(r1, pr2, pinfo->r, ctx)) {
BN_free(pr2);
goto err;
}
if (BN_is_negative(r1))
if (!BN_add(r1, r1, pinfo->r)) {
BN_free(pr2);
goto err;
}
if (!BN_mul(r1, r1, pinfo->pp, ctx)) {
BN_free(pr2);
goto err;
}
if (!BN_add(r0, r0, r1)) {
BN_free(pr2);
goto err;
}
}
BN_free(pr2);
}
if (rsa->e && rsa->n) {
if (!rsa->meth->bn_mod_exp(vrfy, r0, rsa->e, rsa->n, ctx,
rsa->_method_mod_n))
@ -799,8 +923,15 @@ static int rsa_ossl_init(RSA *rsa)
static int rsa_ossl_finish(RSA *rsa)
{
int i;
RSA_PRIME_INFO *pinfo;
BN_MONT_CTX_free(rsa->_method_mod_n);
BN_MONT_CTX_free(rsa->_method_mod_p);
BN_MONT_CTX_free(rsa->_method_mod_q);
for (i = 0; i < sk_RSA_PRIME_INFO_num(rsa->prime_infos); i++) {
pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i);
BN_MONT_CTX_free(pinfo->m);
}
return 1;
}

View File

@ -25,6 +25,7 @@ typedef struct {
/* Key gen parameters */
int nbits;
BIGNUM *pub_exp;
int primes;
/* Keygen callback info */
int gentmp[2];
/* RSA padding mode */
@ -54,6 +55,7 @@ static int pkey_rsa_init(EVP_PKEY_CTX *ctx)
if (rctx == NULL)
return 0;
rctx->nbits = 1024;
rctx->primes = RSA_DEFAULT_PRIME_NUM;
if (pkey_ctx_is_pss(ctx))
rctx->pad_mode = RSA_PKCS1_PSS_PADDING;
else
@ -473,6 +475,14 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
rctx->pub_exp = p2;
return 1;
case EVP_PKEY_CTRL_RSA_KEYGEN_PRIMES:
if (p1 < RSA_DEFAULT_PRIME_NUM || p1 > RSA_MAX_PRIME_NUM) {
RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_KEY_PRIME_NUM_INVALID);
return -2;
}
rctx->primes = p1;
return 1;
case EVP_PKEY_CTRL_RSA_OAEP_MD:
case EVP_PKEY_CTRL_GET_RSA_OAEP_MD:
if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
@ -583,6 +593,7 @@ static int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx,
}
if (strcmp(type, "rsa_padding_mode") == 0) {
int pm;
if (strcmp(value, "pkcs1") == 0) {
pm = RSA_PKCS1_PADDING;
} else if (strcmp(value, "sslv23") == 0) {
@ -606,6 +617,7 @@ static int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx,
if (strcmp(type, "rsa_pss_saltlen") == 0) {
int saltlen;
if (!strcmp(value, "digest"))
saltlen = RSA_PSS_SALTLEN_DIGEST;
else if (!strcmp(value, "max"))
@ -618,13 +630,14 @@ static int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx,
}
if (strcmp(type, "rsa_keygen_bits") == 0) {
int nbits;
nbits = atoi(value);
int nbits = atoi(value);
return EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, nbits);
}
if (strcmp(type, "rsa_keygen_pubexp") == 0) {
int ret;
BIGNUM *pubexp = NULL;
if (!BN_asc2bn(&pubexp, value))
return 0;
@ -634,6 +647,12 @@ static int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx,
return ret;
}
if (strcmp(type, "rsa_keygen_primes") == 0) {
int nprimes = atoi(value);
return EVP_PKEY_CTX_set_rsa_keygen_primes(ctx, nprimes);
}
if (strcmp(type, "rsa_mgf1_md") == 0)
return EVP_PKEY_CTX_md(ctx,
EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT,
@ -664,6 +683,7 @@ static int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx,
unsigned char *lab;
long lablen;
int ret;
lab = OPENSSL_hexstr2buf(value, &lablen);
if (!lab)
return 0;
@ -718,7 +738,8 @@ static int pkey_rsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
} else {
pcb = NULL;
}
ret = RSA_generate_key_ex(rsa, rctx->nbits, rctx->pub_exp, pcb);
ret = RSA_generate_multi_prime_key(rsa, rctx->nbits, rctx->primes,
rctx->pub_exp, pcb);
BN_GENCB_free(pcb);
if (ret > 0 && !rsa_set_pss_param(rsa, ctx)) {
RSA_free(rsa);

View File

@ -105,6 +105,29 @@ below.
The number of bits in the generated key. If not specified 1024 is used.
=item B<rsa_keygen_primes:numprimes>
The number of primes in the generated key. If not specified 2 is used.
=item B<rsa_keygen_pubexp:value>
The RSA public exponent value. This can be a large decimal or
hexadecimal value if preceded by B<0x>. Default value is 65537.
=back
=head1 RSA-PSS KEY GENERATION OPTIONS
Note: by default an B<RSA-PSS> key has no parameter restrictions.
=over 4
=item B<rsa_keygen_bits:numbits>, B<rsa_keygen_pubexp:value>
These options have the same meaning as the B<RSA> algorithm.
=item B<rsa_pss_keygen_md:digest>
=item B<rsa_keygen_pubexp:value>
The RSA public exponent value. This can be a large decimal or

View File

@ -28,6 +28,7 @@ B<openssl> B<genrsa>
[B<-rand file...>]
[B<-writerand file>]
[B<-engine id>]
[B<-primes num>]
[B<numbits>]
=head1 DESCRIPTION
@ -83,6 +84,13 @@ to attempt to obtain a functional reference to the specified engine,
thus initialising it if needed. The engine will then be set as the default
for all available algorithms.
=item B<-primes num>
Specify the number of primes to use while generating the RSA key. The B<num>
parameter must be a positive integer that is greater than 1 and less than 16.
If B<num> is greater than 2, then the generated key is called a 'multi-prime'
RSA key, which is defined in RFC 8017.
=item B<numbits>
The size of the private key to generate in bits. This must be the last option
@ -92,15 +100,17 @@ specified. The default is 2048.
=head1 NOTES
RSA private key generation essentially involves the generation of two prime
numbers. When generating a private key various symbols will be output to
RSA private key generation essentially involves the generation of two or more
prime numbers. When generating a private key various symbols will be output to
indicate the progress of the generation. A B<.> represents each number which
has passed an initial sieve test, B<+> means a number has passed a single
round of the Miller-Rabin primality test. A newline means that the number has
passed all the prime tests (the actual number depends on the key size).
round of the Miller-Rabin primality test, B<*> means the current prime starts
a regenerating progress due to some failed tests. A newline means that the number
has passed all the prime tests (the actual number depends on the key size).
Because key generation is a random process the time taken to generate a key
may vary somewhat.
may vary somewhat. But in general, more primes lead to less generation time
of a key.
=head1 BUGS

View File

@ -15,6 +15,7 @@ B<openssl speed>
[B<-decrypt>]
[B<-rand file...>]
[B<-writerand file>]
[B<-primes num>]
[B<algorithm...>]
=head1 DESCRIPTION
@ -65,6 +66,11 @@ all others.
Writes random data to the specified I<file> upon exit.
This can be used with a subsequent B<-rand> flag.
=item B<-primes num>
Generate a B<num>-prime RSA key and use it to run the benchmarks. This option
is only effective if RSA algorithm is specified to test.
=item B<[zero or more test algorithms]>
If any options are given, B<speed> tests those algorithms, otherwise all of

View File

@ -2,13 +2,15 @@
=head1 NAME
RSA_generate_key_ex, RSA_generate_key - generate RSA key pair
RSA_generate_key_ex, RSA_generate_key,
RSA_generate_multi_prime_key - generate RSA key pair
=head1 SYNOPSIS
#include <openssl/rsa.h>
int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
int RSA_generate_multi_prime_key(RSA *rsa, int bits, int primes, BIGNUM *e, BN_GENCB *cb);
Deprecated:
@ -19,13 +21,19 @@ Deprecated:
=head1 DESCRIPTION
RSA_generate_key_ex() generates a key pair and stores it in the B<RSA>
structure provided in B<rsa>. The pseudo-random number generator must
RSA_generate_key_ex() generates a 2-prime RSA key pair and stores it in the
B<RSA> structure provided in B<rsa>. The pseudo-random number generator must
be seeded prior to calling RSA_generate_key_ex().
The modulus size will be of length B<bits>, and the public exponent will be
B<e>. Key sizes with B<num> E<lt> 1024 should be considered insecure.
The exponent is an odd number, typically 3, 17 or 65537.
RSA_generate_multi_prime_key() generates a multi-prime RSA key pair and stores
it in the B<RSA> structure provided in B<rsa>. The number of primes is given by
the B<primes> parameter. The pseudo-random number generator must be seeded prior
to calling RSA_generate_multi_prime_key().
The modulus size will be of length B<bits>, the number of primes to form the
modulus will be B<primes>, and the public exponent will be B<e>. Key sizes
with B<num> E<lt> 1024 should be considered insecure. The exponent is an odd
number, typically 3, 17 or 65537.
A callback function may be used to provide feedback about the
progress of the key generation. If B<cb> is not B<NULL>, it
@ -55,10 +63,12 @@ it is called as B<BN_GENCB_call(cb, 3, 0)>.
=back
The process is then repeated for prime q with B<BN_GENCB_call(cb, 3, 1)>.
The process is then repeated for prime q and other primes (if any)
with B<BN_GENCB_call(cb, 3, i)> where B<i> indicates the i-th prime.
=head1 RETURN VALUE
RSA_generate_multi_prime_key() returns 1 on success or 0 on error.
RSA_generate_key_ex() returns 1 on success or 0 on error.
The error codes can be obtained by L<ERR_get_error(3)>.
@ -81,7 +91,7 @@ RSA_generate_key_ex() intsead.
=head1 COPYRIGHT
Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
Copyright 2000-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

View File

@ -4,8 +4,10 @@
RSA_set0_key, RSA_set0_factors, RSA_set0_crt_params, RSA_get0_key,
RSA_get0_factors, RSA_get0_crt_params, RSA_clear_flags,
RSA_test_flags, RSA_set_flags, RSA_get0_engine - Routines for getting
and setting data in an RSA object
RSA_test_flags, RSA_set_flags, RSA_get0_engine, 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
- Routines for getting and setting data in an RSA object
=head1 SYNOPSIS
@ -24,6 +26,13 @@ and setting data in an RSA object
int RSA_test_flags(const RSA *r, int flags);
void RSA_set_flags(RSA *r, int flags);
ENGINE *RSA_get0_engine(RSA *r);
int RSA_get_multi_prime_extra_count(const RSA *r);
int RSA_get0_multi_prime_factors(const RSA *r, const BIGNUM *primes[]);
int RSA_get0_multi_prime_crt_params(const RSA *r, const BIGNUM *exps[],
const BIGNUM *coeffs[]);
int RSA_set0_multi_prime_params(RSA *r, BIGNUM *primes[], BIGNUM *exps[],
BIGNUM *coeffs[], int pnum);
int RSA_get_version(RSA *r);
=head1 DESCRIPTION
@ -36,6 +45,11 @@ private key (see PKCS#1 section 3 Key Types), where B<p> and B<q> are
the first and second factor of B<n> and B<dmp1>, B<dmq1> and B<iqmp>
are the exponents and coefficient for CRT calculations.
For multi-prime RSA (defined in RFC 8017), there are also one or more
'triplet' in an RSA object. A triplet contains three members, B<r>, B<d>
and B<t>. B<r> is the additional prime besides B<p> and B<q>. B<d> and
B<t> are the exponent and coefficient for CRT calculations.
The B<n>, B<e> and B<d> parameters can be obtained by calling
RSA_get0_key(). If they have not been set yet, then B<*n>, B<*e> and
B<*d> will be set to NULL. Otherwise, they are set to pointers to
@ -59,9 +73,15 @@ B<dmq1> and B<iqmp> parameters can be obtained and set with
RSA_get0_crt_params() and RSA_set0_crt_params().
For RSA_get0_key(), RSA_get0_factors(), and RSA_get0_crt_params(),
NULL value BIGNUM ** output parameters are permitted. The functions
NULL value BIGNUM ** output parameters are permitted. The functions
ignore NULL parameters but return values for other, non-NULL, parameters.
For multi-prime RSA, RSA_get0_multi_prime_factors() and RSA_get0_multi_prime_params()
can be used to obtain other primes and related CRT parameters. The
return values are stored in an array of B<BIGNUM *>. RSA_set0_multi_prime_params()
sets a collect of multi-prime 'triplet' members (prime, exponent and coefficient)
into an RSA object.
RSA_set_flags() sets the flags in the B<flags> parameter on the RSA
object. Multiple flags can be passed in one go (bitwise ORed together).
Any flags that are already set are left set. RSA_test_flags() tests to
@ -74,6 +94,8 @@ RSA object.
RSA_get0_engine() returns a handle to the ENGINE that has been set for
this RSA object, or NULL if no such ENGINE has been set.
RSA_get_version() returns the version of an RSA object B<r>.
=head1 NOTES
Values retrieved with RSA_get0_key() are owned by the RSA object used
@ -82,10 +104,27 @@ needed, duplicate the received value using BN_dup() and pass the
duplicate. The same applies to RSA_get0_factors() and RSA_set0_factors()
as well as RSA_get0_crt_params() and RSA_set0_crt_params().
The caller should obtain the size by calling RSA_get_multi_prime_extra_count()
in advance and allocate sufficient buffer to store the return values before
calling RSA_get0_multi_prime_factors() and RSA_get0_multi_prime_params().
RSA_set0_multi_prime_params() always clears the original multi-prime
triplets in RSA object B<r> and assign the new set of triplets into it.
=head1 RETURN VALUES
RSA_set0_key(), RSA_set0_factors and RSA_set0_crt_params() return 1 on
success or 0 on failure.
RSA_set0_key(), RSA_set0_factors(), RSA_set0_crt_params() and
RSA_set0_multi_prime_params() return 1 on success or 0 on failure.
RSA_get0_multi_prime_factors() and RSA_get0_multi_prime_crt_params() return
1 on success or 0 on failure.
RSA_get_multi_prime_extra_count() returns two less than the number of primes
in use, which is 0 for traditional RSA and the number of extra primes for
multi-prime RSA.
RSA_get_version() returns B<RSA_ASN1_VERSION_MULTI> for multi-prime RSA and
B<RSA_ASN1_VERSION_DEFAULT> for normal two-prime RSA, as defined in RFC 8017.
RSA_test_flags() returns the current state of the flags in the RSA object.
@ -98,11 +137,15 @@ L<RSA_new(3)>, L<RSA_size(3)>
=head1 HISTORY
The functions described here were added in OpenSSL 1.1.0.
RSA_get_multi_prime_extra_count(), RSA_get0_multi_prime_factors(),
RSA_get0_multi_prime_crt_params(), RSA_set0_multi_prime_params(),
and RSA_get_version() functions were added in OpenSSL 1.1.1.
Other functions described here were added in OpenSSL 1.1.0.
=head1 COPYRIGHT
Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
Copyright 2016-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

View File

@ -12,7 +12,8 @@ RSA_meth_set_priv_dec, RSA_meth_get_mod_exp, RSA_meth_set_mod_exp,
RSA_meth_get_bn_mod_exp, RSA_meth_set_bn_mod_exp, RSA_meth_get_init,
RSA_meth_set_init, RSA_meth_get_finish, RSA_meth_set_finish,
RSA_meth_get_sign, RSA_meth_set_sign, RSA_meth_get_verify,
RSA_meth_set_verify, RSA_meth_get_keygen, RSA_meth_set_keygen
RSA_meth_set_verify, RSA_meth_get_keygen, RSA_meth_set_keygen,
RSA_meth_get_multi_prime_keygen, RSA_meth_set_multi_prime_keygen
- Routines to build up RSA methods
=head1 SYNOPSIS
@ -111,6 +112,15 @@ RSA_meth_set_verify, RSA_meth_get_keygen, RSA_meth_set_keygen
int (*keygen)(RSA *rsa, int bits, BIGNUM *e,
BN_GENCB *cb));
int (*RSA_meth_get_multi_prime_keygen(const RSA_METHOD *meth))(RSA *rsa, int bits,
int primes, BIGNUM *e,
BN_GENCB *cb);
int RSA_meth_set_multi_prime_keygen(RSA_METHOD *meth,
int (*keygen) (RSA *rsa, int bits,
int primes, BIGNUM *e,
BN_GENCB *cb));
=head1 DESCRIPTION
The B<RSA_METHOD> type is a structure used for the provision of custom
@ -193,8 +203,14 @@ by this function. This function may be NULL.
RSA_meth_get_keygen() and RSA_meth_set_keygen() get and set the
function used for generating a new RSA key pair respectively. This
function will be called in response to the application calling
RSA_generate_key(). The parameter for the function has the same
meaning as for RSA_generate_key().
RSA_generate_key_ex(). The parameter for the function has the same
meaning as for RSA_generate_key_ex().
RSA_meth_get_multi_prime_keygen() and RSA_meth_set_multi_prime_keygen() get
and set the function used for generating a new multi-prime RSA key pair
respectively. This function will be called in response to the application calling
RSA_generate_multi_prime_key(). The parameter for the function has the same
meaning as for RSA_generate_multi_prime_key().
RSA_meth_get_pub_enc(), RSA_meth_set_pub_enc(),
RSA_meth_get_pub_dec(), RSA_meth_set_pub_dec(),
@ -223,12 +239,16 @@ success or 0 on failure.
=head1 SEE ALSO
L<RSA_new(3)>, L<RSA_generate_key(3)>, L<RSA_sign(3)>,
L<RSA_set_method(3)>, L<RSA_size(3)>, L<RSA_get0_key(3)>
L<RSA_new(3)>, L<RSA_generate_key_ex(3)>, L<RSA_sign(3)>,
L<RSA_set_method(3)>, L<RSA_size(3)>, L<RSA_get0_key(3)>,
L<RSA_generate_multi_prime_key(3)>
=head1 HISTORY
The functions described here were added in OpenSSL 1.1.0.
RSA_meth_get_multi_prime_keygen() and RSA_meth_set_multi_prime_keygen() were
added in OpenSSL 1.1.1.
Other functions described here were added in OpenSSL 1.1.0.
=head1 COPYRIGHT

View File

@ -45,6 +45,12 @@ extern "C" {
# define RSA_3 0x3L
# define RSA_F4 0x10001L
/* based on RFC 8017 appendix A.1.2 */
# define RSA_ASN1_VERSION_DEFAULT 0
# define RSA_ASN1_VERSION_MULTI 1
# define RSA_DEFAULT_PRIME_NUM 2
# define RSA_METHOD_FLAG_NO_CHECK 0x0001/* don't check pub/private
* match */
@ -120,6 +126,10 @@ extern "C" {
RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_KEYGEN, \
EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP, 0, pubexp)
# define EVP_PKEY_CTX_set_rsa_keygen_primes(ctx, primes) \
RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_KEYGEN, \
EVP_PKEY_CTRL_RSA_KEYGEN_PRIMES, primes, NULL)
# define EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, md) \
RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT, \
EVP_PKEY_CTRL_RSA_MGF1_MD, 0, (void *)(md))
@ -170,6 +180,8 @@ extern "C" {
# define EVP_PKEY_CTRL_GET_RSA_OAEP_MD (EVP_PKEY_ALG_CTRL + 11)
# define EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL (EVP_PKEY_ALG_CTRL + 12)
# define EVP_PKEY_CTRL_RSA_KEYGEN_PRIMES (EVP_PKEY_ALG_CTRL + 13)
# define RSA_PKCS1_PADDING 1
# define RSA_SSLV23_PADDING 2
# define RSA_NO_PADDING 3
@ -192,15 +204,22 @@ int RSA_security_bits(const RSA *rsa);
int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d);
int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q);
int RSA_set0_crt_params(RSA *r,BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp);
int RSA_set0_multi_prime_params(RSA *r, BIGNUM *primes[], BIGNUM *exps[],
BIGNUM *coeffs[], int pnum);
void RSA_get0_key(const RSA *r,
const BIGNUM **n, const BIGNUM **e, const BIGNUM **d);
void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q);
int RSA_get_multi_prime_extra_count(const RSA *r);
int RSA_get0_multi_prime_factors(const RSA *r, const BIGNUM *primes[]);
void RSA_get0_crt_params(const RSA *r,
const BIGNUM **dmp1, const BIGNUM **dmq1,
const BIGNUM **iqmp);
int RSA_get0_multi_prime_crt_params(const RSA *r, const BIGNUM *exps[],
const BIGNUM *coeffs[]);
void RSA_clear_flags(RSA *r, int flags);
int RSA_test_flags(const RSA *r, int flags);
void RSA_set_flags(RSA *r, int flags);
int RSA_get_version(RSA *r);
ENGINE *RSA_get0_engine(const RSA *r);
/* Deprecated version */
@ -210,6 +229,9 @@ DEPRECATEDIN_0_9_8(RSA *RSA_generate_key(int bits, unsigned long e, void
/* New version */
int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
/* Multi-prime version */
int RSA_generate_multi_prime_key(RSA *rsa, int bits, int primes,
BIGNUM *e, BN_GENCB *cb);
int RSA_X931_derive_ex(RSA *rsa, BIGNUM *p1, BIGNUM *p2, BIGNUM *q1,
BIGNUM *q2, const BIGNUM *Xp1, const BIGNUM *Xp2,
@ -468,6 +490,12 @@ int (*RSA_meth_get_keygen(const RSA_METHOD *meth))
int RSA_meth_set_keygen(RSA_METHOD *rsa,
int (*keygen) (RSA *rsa, int bits, BIGNUM *e,
BN_GENCB *cb));
int (*RSA_meth_get_multi_prime_keygen(const RSA_METHOD *meth))
(RSA *rsa, int bits, int primes, BIGNUM *e, BN_GENCB *cb);
int RSA_meth_set_multi_prime_keygen(RSA_METHOD *meth,
int (*keygen) (RSA *rsa, int bits,
int primes, BIGNUM *e,
BN_GENCB *cb));
int ERR_load_RSA_strings(void);
# ifdef __cplusplus

View File

@ -114,6 +114,7 @@ int ERR_load_RSA_strings(void);
# define RSA_R_INVALID_LABEL 160
# define RSA_R_INVALID_MESSAGE_LENGTH 131
# define RSA_R_INVALID_MGF1_MD 156
# define RSA_R_INVALID_MULTI_PRIME_KEY 167
# define RSA_R_INVALID_OAEP_PARAMETERS 161
# define RSA_R_INVALID_PADDING 138
# define RSA_R_INVALID_PADDING_MODE 141
@ -123,12 +124,17 @@ int ERR_load_RSA_strings(void);
# define RSA_R_INVALID_TRAILER 139
# define RSA_R_INVALID_X931_DIGEST 142
# define RSA_R_IQMP_NOT_INVERSE_OF_Q 126
# define RSA_R_KEY_PRIME_NUM_INVALID 165
# define RSA_R_KEY_SIZE_TOO_SMALL 120
# define RSA_R_LAST_OCTET_INVALID 134
# define RSA_R_MGF1_DIGEST_NOT_ALLOWED 152
# define RSA_R_MODULUS_TOO_LARGE 105
# define RSA_R_MP_COEFFICIENT_NOT_INVERSE_OF_R 168
# define RSA_R_MP_EXPONENT_NOT_CONGRUENT_TO_D 169
# define RSA_R_MP_R_NOT_PRIME 170
# define RSA_R_NO_PUBLIC_EXPONENT 140
# define RSA_R_NULL_BEFORE_BLOCK_MISSING 113
# define RSA_R_N_DOES_NOT_EQUAL_PRODUCT_OF_PRIMES 172
# define RSA_R_N_DOES_NOT_EQUAL_P_Q 127
# define RSA_R_OAEP_DECODING_ERROR 121
# define RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE 148

View File

@ -46,7 +46,7 @@ INCLUDE_MAIN___test_libtestutil_OLB = /INCLUDE=MAIN
x509_time_test x509_dup_cert_test x509_check_cert_pkey_test \
recordlentest drbgtest sslbuffertest \
time_offset_test pemtest ssl_cert_table_internal_test ciphername_test \
servername_test ocspapitest
servername_test ocspapitest rsa_mp_test
SOURCE[aborttest]=aborttest.c
INCLUDE[aborttest]=../include
@ -152,6 +152,10 @@ INCLUDE_MAIN___test_libtestutil_OLB = /INCLUDE=MAIN
INCLUDE[rsa_test]=.. ../include
DEPEND[rsa_test]=../libcrypto libtestutil.a
SOURCE[rsa_mp_test]=rsa_mp_test.c
INCLUDE[rsa_mp_test]=.. ../include
DEPEND[rsa_mp_test]=../libcrypto libtestutil.a
SOURCE[evp_test]=evp_test.c
INCLUDE[evp_test]=../include
DEPEND[evp_test]=../libcrypto libtestutil.a

View File

@ -0,0 +1,126 @@
#! /usr/bin/env perl
# Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
# Copyright 2017 BaishanCloud. 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
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
use strict;
use warnings;
use File::Spec;
use OpenSSL::Test qw/:DEFAULT data_file/;
use OpenSSL::Test::Utils;
setup("test_mp_rsa");
plan tests => 61;
ok(run(test(["rsa_mp_test"])), "running rsa multi prime test");
my $cleartext = data_file("plain_text");
my @test_param = (
# 3 primes, 2048-bit
{
primes => '3',
bits => '2048',
},
# 4 primes, 2048-bit
{
primes => '4',
bits => '2048',
},
# 8 primes, 2048-bit
{
primes => '8',
bits => '2048',
},
# 15 primes, 2048-bit
{
primes => '15',
bits => '2048',
},
# 8 primes, 15360-bit (3 & 4 primes for 15360 bit is too long to gen a key)
{
primes => '8',
bits => '15360',
},
# 15 primes, 15360-bit
{
primes => '15',
bits => '15360',
},
);
# genrsa
run_mp_tests(0);
# evp
run_mp_tests(1);
sub run_mp_tests {
my $evp = shift;
foreach my $param (@test_param) {
my $primes = $param->{primes};
my $bits = $param->{bits};
my $name = ($evp ? "evp" : "") . "${bits}p${primes}";
if ($evp) {
ok(run(app([ 'openssl', 'genpkey', '-out', 'rsamptest.pem',
'-algorithm', 'RSA', '-pkeyopt', "rsa_keygen_primes:$primes",
'-pkeyopt', "rsa_keygen_bits:$bits"])), "genrsa $name");
} else {
ok(run(app([ 'openssl', 'genrsa', '-out', 'rsamptest.pem',
'-primes', $primes, $bits])), "genrsa $name");
}
ok(run(app([ 'openssl', 'rsa', '-check', '-in', 'rsamptest.pem',
'-noout'])), "rsa -check $name");
if ($evp) {
ok(run(app([ 'openssl', 'pkeyutl', '-inkey', 'rsamptest.pem',
'-encrypt', '-in', $cleartext,
'-out', 'rsamptest.enc' ])), "rsa $name encrypt");
ok(run(app([ 'openssl', 'pkeyutl', '-inkey', 'rsamptest.pem',
'-decrypt', '-in', 'rsamptest.enc',
'-out', 'rsamptest.dec' ])), "rsa $name decrypt");
} else {
ok(run(app([ 'openssl', 'rsautl', '-inkey', 'rsamptest.pem',
'-encrypt', '-in', $cleartext,
'-out', 'rsamptest.enc' ])), "rsa $name encrypt");
ok(run(app([ 'openssl', 'rsautl', '-inkey', 'rsamptest.pem',
'-decrypt', '-in', 'rsamptest.enc',
'-out', 'rsamptest.dec' ])), "rsa $name decrypt");
}
ok(check_msg(), "rsa $name check result");
# clean up temp files
unlink 'rsamptest.pem';
unlink 'rsamptest.enc';
unlink 'rsamptest.dec';
}
}
sub check_msg {
my $msg;
my $dec;
open(my $fh, "<", $cleartext) or return 0;
binmode $fh;
read($fh, $msg, 10240);
close $fh;
open($fh, "<", "rsamptest.dec") or return 0;
binmode $fh;
read($fh, $dec, 10240);
close $fh;
if ($msg ne $dec) {
print STDERR "cleartext and decrypted are not the same";
return 0;
}
return 1;
}

View File

@ -0,0 +1,4 @@
It was the best of times, it was the worst of times,
it was the age of wisdom, it was the age of foolishness,
it was the epoch of belief, it was the epoch of incredulity,
it was the season of Light, it was the season of Darkness.

370
test/rsa_mp_test.c Normal file
View File

@ -0,0 +1,370 @@
/*
* Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2017 BaishanCloud. 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
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/* This aims to test the setting functions */
#include <stdio.h>
#include <string.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/bn.h>
#include "testutil.h"
#ifndef OPENSSL_NO_RSA
# include <openssl/rsa.h>
#define NUM_EXTRA_PRIMES 5
static int key4096p7(RSA *key)
{
/* C90 requires string should <= 509 bytes */
static unsigned char n1[] =
"\x00\xeb\xa2\x2b\x74\x76\x32\x33\xbf\xb9\x9a\xe4\xb0\x84\xac"
"\x9a\x20\x1b\xe6\x1a\x22\x3f\xcd\x13\xe1\x42\xee\xd8\x1a\x6e"
"\xe3\xd5\x91\x1e\xee\x32\x5c\x78\x76\x8b\x5d\x82\x6f\xd0\xaf"
"\xa3\x56\xd6\x15\x5f\x64\xb3\x5a\xcf\xc8\x7d\xa3\xb1\x3d\x10"
"\xbf\x47\x00\xa9\xc9\x96\x9d\xfd\x7c\x82\x4f\xb5\x70\x39\xd4"
"\xd9\x0f\xd7\xd9\x86\xd4\xd4\x35\x06\x35\x07\xa3\x1b\x8c\xf4"
"\x35\xb8\xb2\xd4\xa3\xbe\x6c\x64\x7d\x74\x17\x88\x36\x07\x32"
"\x6f\x84\x48\xd4\xb8\x4a\x12\xba\xe8\x40\x5b\xc6\xa5\xa4\x11"
"\x0d\x8a\xa6\x60\x3d\x98\x8b\xf8\x11\x8f\x43\xab\x2f\x95\x0f"
"\x3b\x20\x3f\x48\x88\xaa\x3d\x20\xa6\xaf\x6a\xdf\xc0\x95\x38"
"\xff\x47\x7c\x8a\x8b\xec\x76\x45\x43\xd0\x06\x7c\x71\x76\x5f"
"\x0d\x11\x58\x0a\xa9\x0e\x7e\x07\xe9\x89\xc1\x9e\x56\x6d\x08"
"\xe4\xe3\x16\xb4\xa0\x03\x7a\x49\x96\xa8\x88\xcf\x89\xe3\xdb"
"\x47\x0c\xd2\x1b\x6f\x67\x4d\xc8\xee\x53\xe9\x0b\x3d\xe5\x11"
"\x9d\x85\x75\xfe\x26\x4a\x99\x58\x79\x28\x91\x03\x8b\xe4\xbf"
"\x49\xd3\xfa\x8e\x25\xe3\xb1\xb2\xc2\x33\xd9\x8b\xe0\x9d\x1b"
"\xa4\xa0\xcf\x05\x5f\xb9\x19\x65\x74\x24\xae\x2e\x33\xc8\xd9";
static unsigned char n2[] =
"\x55\xae\xcb\x37\xa1\x3b\x95\xf7\x5f\xff\x1f\x06\x4a\xab\x85"
"\x94\x37\x15\x6f\xf2\xc8\x9b\x73\xb9\x1d\x8e\x30\x63\x5a\xa1"
"\x84\x31\xa8\xbe\x7e\x4f\xeb\xa0\xe6\x73\xc7\xbe\xd4\x5e\xe7"
"\x5e\xae\x5d\xfd\xf7\xf5\xa4\xb6\xb8\x3c\x15\xac\x1b\xcd\x3a"
"\xb6\xbd\xa9\x11\xd0\x44\xa5\x08\x7e\x60\x1d\x1d\x4d\xa6\xd7"
"\x06\xe5\x4f\x37\x0d\x5c\xbd\xad\x8d\x40\x18\xbd\xc7\x58\x20"
"\xed\xa8\x4d\xd8\x29\xdc\x42\x4f\x50\xa6\x03\xf0\xa5\xa2\x18"
"\x2b\xdd\x1c\x0e\x89\x3f\xbc\x5d\x35\xac\xa8\x55\x6d\x17\x28"
"\xae\xee\x78\xeb\x6d\x7a\x21\xd6\x6c\xdd\x21\x1d\xcc\xe5\xb0"
"\xf2\xef\x7f\x1d\x8a\xb7\x95\xaf\x40\xb5\x5c\x8b\x0d\x59\x45"
"\x21\x86\x34\x6d\x13\xd7\x14\xa5\x0e\xca\x88\x32\x57\xfe\x2d"
"\xd1\xcb\xad\x14\xbe\x30\xb1\x69\x9b\x72\x82\xad\x47\xb5\x45"
"\xc8\x65\x83\xce\x07\x21\x15\x6b\x65\x9d\xf3\x4d\x92\x19\xbe"
"\x67\x73\xd0\x60\x9f\xc7\xef\xee\xfa\xb0\xd3\xa4\x95\x81\xb0"
"\xbd\x4b\xd5\xf8\xbd\xbd\x9f\x41\x41\xc0\xfd\xe9\x17\xe3\x16"
"\xd3\xdc\xc8\xe2\xa5\xca\xff\xea\x91\xf4\x33\xc0\xfb\xdc\x02"
"\x62\x0a\x4e\x26\x92\xb5\x13\xec\x43\xd2\x25\x19\xe2\x6d\xef"
"\xea\x38\x75";
static unsigned char e[] = "\x01\x00\x01";
static unsigned char d1[] =
"\x60\x43\x92\x69\x33\xd8\x72\x97\xc3\x25\xea\x83\xca\xd0\x10"
"\xef\x49\x36\x8a\x3a\xaf\xc2\x02\x7b\x26\xb3\x19\x0a\x43\x7f"
"\x44\xc2\xd2\xd6\x11\x31\x01\xed\xbc\x25\xe9\xa1\xf0\xa9\xb0"
"\x9b\x4b\x3e\xd4\x07\xf9\xd6\x01\xc9\x30\xba\xed\x2f\xbb\x65"
"\xc9\x86\x15\xd7\x4b\x77\x24\x15\xf7\xce\xc4\x9b\x21\x62\x4d"
"\xde\x77\xf0\x1e\x62\x49\x54\xda\xda\xcd\xdd\x0f\x53\xe2\xd2"
"\x39\x4f\x60\x8e\xec\xe3\x49\x1b\xe7\x9a\x3e\x17\x8e\x5a\x77"
"\x4a\x15\xf6\x57\xc5\xfe\x2b\xa5\x94\x04\x94\x9c\xe7\xa8\xcc"
"\x07\x4b\xd8\xb8\x55\xaa\xdf\x33\xca\x2c\x8c\xee\x61\x1a\x89"
"\x0d\x3b\xcd\x16\x28\xb5\x50\x62\x2f\xb1\x9e\x61\x27\xd7\xf1"
"\xe1\x22\x58\x84\xcd\x18\xc3\xbf\xde\x52\x25\xdd\xc1\xcd\x2a"
"\x20\x78\x5e\xde\x65\x6a\x25\x12\x2d\x78\x28\xdb\x2c\x6f\x1b"
"\x65\x71\x1b\x2e\x1c\x18\x62\xf6\x71\x82\xdc\xa8\x80\x0e\xb5"
"\x8b\x09\x97\xc3\x81\xe1\x23\x2e\x40\x75\xbf\xd3\x78\xdc\xd5"
"\xc3\xe6\x75\x8b\xb0\x48\x7a\x78\x7d\xfe\xcc\x4c\xa1\x40\x11"
"\x20\xbe\x2a\xc1\xaf\x18\x53\x45\x6a\xb4\x2a\x0a\xc9\x01\x36"
"\x60\xf1\x61\x97\x73\xde\xac\x3e\x24\xff\x5b\x25\xdb\x93\x97";
static unsigned char d2[] =
"\x03\xf4\xef\x4a\x73\x47\xa8\x31\xd1\x63\x5b\xba\xa6\xe2\x7a"
"\xd8\xef\xea\x2f\x04\x76\x3c\x7a\x8d\x4e\xc1\x81\xc5\x39\x4f"
"\x09\xc4\xb1\xfb\x75\xd0\xae\x32\x2e\x44\xa3\xb6\xdc\x60\xc6"
"\x60\x1e\x40\x6f\x04\xc2\x7a\xd3\x0f\x8a\xa4\x23\x8f\x0e\x2e"
"\x2a\xcd\x65\x2a\x6e\x97\xa8\xe5\x01\x96\xd1\x41\x27\xa5\x16"
"\x2f\xb0\x15\x0a\x33\x06\x72\x40\xa5\xe4\x74\xbe\x4a\x87\x28"
"\x8a\x68\xea\x39\x42\x08\x47\xff\x9d\x9e\x06\x03\xfa\x4a\x6a"
"\xbb\xe5\x6f\x97\x05\x5f\xae\x47\xe6\xc4\xe0\x48\x62\x65\x9b"
"\x91\x50\xda\x84\xcf\xa3\xb2\x9d\x51\x84\x02\x4b\xe6\x12\xa2"
"\x87\x6e\x1f\x43\x2f\x90\x36\xb1\x15\xc6\xf6\xe0\xde\x52\x39"
"\x8e\x22\x39\x8c\x4f\x1c\x08\xac\x55\x5c\xa9\x69\x4e\x77\x8d"
"\x74\x6e\x0b\x06\xda\x61\xcd\xe2\xc8\xc6\x02\x54\x70\x05\xc1"
"\x50\x6d\x5e\x3e\x66\x7d\x41\x3c\x57\x68\x8a\x16\xb9\xd8\x29"
"\xfb\xeb\x05\x57\x87\xdc\x88\xc6\x91\x67\x3c\xcc\x19\x28\xa1"
"\x23\x54\xc3\x88\xc4\x28\x63\xca\xf7\xb2\xea\x34\xa1\x9e\xc1"
"\xca\x9b\x96\xe7\x4d\x82\x22\xf9\xcb\xc3\x2a\x3f\x19\xe3\x7c"
"\xce\x8c\x66\x45\xfe\xe6\x31\x31\x66\xd4\x1a\xb5\x47\x98\xea"
"\x80\x01";
static unsigned char p[] =
"\x03\xf5\x90\x21\xf3\xa6\x13\xdd\x33\x2a\x4c\x1f\x53\xd6\x9e"
"\x64\x1d\xfc\xed\xfb\xa1\xe6\xd0\x80\xd1\x6a\xcd\x20\x68\xea"
"\x75\x72\x59\x24\x8b\x1b\x28\x37\xbd\x8f\xc4\xc9\xb6\xda\xef"
"\x55\xb9\x0e\x26\x93\x8a\x8a\xec\x2f\x47\xe6\x4e\xa9\x42\xfb"
"\x02\x28\x5e\x37\xb7\x5a\x61\xfa\x39\xab\x63\x61\x1b\xbb";
static unsigned char q[] =
"\x01\xea\x64\x6e\x7d\xaa\xd7\x6a\xfa\x0c\x52\xfa\x2b\x00\x51"
"\x7d\x4d\xc3\x9f\x1d\x21\xb2\x62\x11\xd4\x7d\x0e\xc2\xe7\xdf"
"\xd0\x04\xd6\x30\x02\x54\xb2\xa5\xb7\x85\xd5\x96\xc7\x24\x83"
"\x8e\x3d\x60\xc3\x42\xa5\xa3\x76\xdd\x6e\x60\xa0\xbf\x85\x05"
"\xb6\x52\x32\xeb\x41\x6f\x08\xc8\x56\x43\xd8\x80\x06\xf7";
static unsigned char dmp1[] =
"\x03\xcc\x5c\xe7\x45\x91\x49\xb3\x47\x77\xc7\xa9\xb2\x4b\xce"
"\x8e\xab\xfa\x4f\xf1\xbd\x63\xeb\x19\xfa\x4e\x64\xd6\x37\xf0"
"\xde\x95\xc2\x11\x7d\xe6\xa2\xd1\xbe\xe9\x23\x58\x85\x35\x4a"
"\xb0\xc9\xa5\x5a\xba\xe7\x09\xda\x06\x8e\x0a\xd3\xe2\x2c\x61"
"\x14\xb3\xd7\x97\xca\x2e\x4a\x9a\xbd\x22\xc0\x67\x94\x2b";
static unsigned char dmq1[] =
"\x01\x66\x28\x8d\xce\x38\x8d\x76\xb3\x43\x77\x03\x01\x8f\x0c"
"\xf5\x40\x6b\x84\x75\x69\x5b\xf8\x66\x5f\x54\x2b\x08\xcd\x03"
"\x58\xd1\x7f\x81\xb6\xe2\x17\x4c\x13\x3a\xab\x21\xa1\x36\x98"
"\xe2\xb5\x0f\x4b\xed\x0c\x3e\xd4\x1c\xab\x75\xe5\x51\x9b\x9c"
"\xed\x69\x21\x89\x52\xd3\xfe\x8d\x1a\xfc\x18\x4e\x81\x47";
static unsigned char iqmp[] =
"\x02\x31\xad\xe8\xa5\xa9\x5d\x52\x70\x68\xc1\x6e\x6b\x4e\xb5"
"\x0b\xc2\xd9\x89\xe5\xbc\x46\xca\xac\xac\x04\xe2\x39\x7f\xc4"
"\xa0\xe4\x9e\x8a\xb8\x1e\x67\x66\x85\xb8\x3e\x42\x7c\xc7\x2c"
"\x02\x64\x7c\xd3\x40\xda\x5d\x9f\x38\xa7\x7c\x30\xcd\x6b\x7d"
"\x4d\xd0\x77\x2d\x9b\xd1\xc3\x55\x03\x69\x3d\xda\x48\xe2";
static char *primes[] = {
"\x01\xb2\xe2\xf7\x3b\x29\xdc\x90\xf9\xc4\x5a\x75\x09\x00\xbe"
"\xec\xa6\x97\xbc\x47\x89\x24\x71\x48\xa7\xc9\xc8\xed\x9c\x88"
"\xb9\x9f\xcd\x79\xc9\x2d\xb1\x78\xf7\x54\x2c\x28\x01\x37\x01"
"\xa0\xff\xf2\x69\x52\x93\xf0\x16\x08\xaa\x2f\xff\x35\x14\x2d"
"\x65\x8d\x21\x05\x30\x84\x9b\xcb\x58\x42\xc6\x9b\xa7\xb5",
"\x01\xb7\x66\xfe\xb5\x94\xf8\x46\xcb\x06\x2a\x7a\xd4\x35\xe4"
"\x68\x6d\xcf\x58\x0b\xb3\x12\xe6\x7b\x66\xee\x36\xf5\x1f\x79"
"\x8f\x82\x1e\xd9\x97\x33\x45\x37\xa3\x84\x54\xab\x4b\x12\x96"
"\x76\x9f\xf9\x98\x02\xf1\x5e\xcb\x97\xe8\x13\xde\x91\x0b\xd5"
"\xec\x7f\x2b\x27\x55\xc1\x69\x58\xad\x8b\xaa\xce\x68\xc5",
"\x01\xbe\xdf\xa5\x33\xfb\xa1\xfa\xf6\xd2\x43\xcd\x76\x3e\x23"
"\xa2\xf7\x29\xeb\x65\xe5\xae\xe8\xfc\xfd\xca\x55\x16\x01\x57"
"\xcd\xca\x9e\x83\xf9\x61\x6a\x17\xac\x61\xec\x04\x32\x9f\x69"
"\xb8\x6d\x66\x33\x9b\xef\xf4\x91\xf1\x99\x02\xc2\xea\x58\x6e"
"\xad\x3d\x0e\xa9\x87\x17\x7c\x9b\x72\xcc\xab\x1c\x93\x2b",
"\x03\x2f\x4a\x9c\x49\x66\x9d\xbc\xae\xec\x54\x7d\xe6\x07\x52"
"\xc2\x9a\x09\xf5\xa7\x56\xa6\x68\x45\x38\x75\x7d\xb0\x0e\xee"
"\xf3\x23\xec\x74\x1e\x3b\xc0\x58\x1d\x43\xd9\x35\x15\x7e\x2f"
"\x28\xff\x08\x7a\x79\x44\xfc\x24\x06\xc5\x3f\xaa\xe0\xfa\xb2"
"\x1f\xd9\x4e\xd8\xc8\xda\xed\x1f\xaa\x77\x64\xae\xb3\xe3",
"\x01\xea\xaa\x9d\x90\x67\x3b\x2f\x9a\xe3\x7b\x56\x5c\x35\x9f"
"\x65\x0b\x0c\x3b\xa6\x60\x5f\x98\x36\x2c\xb6\xaa\xdb\xb2\x86"
"\x8b\x20\xba\xa4\x85\x7b\xa8\x80\x41\xee\x22\x1c\x7a\x92\xf5"
"\x39\x4e\x4a\x0b\x29\x0b\xe7\xdd\x3c\xb6\x51\xec\xc3\x26\xbc"
"\x33\x11\xbc\x29\x7a\x10\x68\x32\x55\xb4\x15\xd9\x8e\xc1"
};
static int primes_len[] = { 74, 74, 74, 74, 74 };
static char *exponents[] = {
"\x01\xa4\x49\xb7\x57\xc5\x50\x36\x08\x3c\xdc\x93\x29\x1d\x40"
"\x67\x63\x65\x57\x7f\xe7\x29\x82\x16\x0e\x9a\x74\x06\x37\x76"
"\xe7\xb6\x6a\x15\x5d\xf9\x3c\x00\x45\x3f\x62\xe1\x52\xb3\x3f"
"\x6e\xc2\x8d\x1b\x7e\xc4\x1c\x8e\x9e\xd7\x23\x45\xc8\x9d\x74"
"\x76\x25\x5b\x99\x31\x57\xa7\x5d\x71\x32\x2f\xd1\x74\xd5",
"\x01\x3a\xa4\x6d\x05\xf7\xeb\xa5\x3d\xe2\x67\x6e\xd7\x20\xd4"
"\x33\x17\x56\xdf\x34\x59\x81\xd2\x3b\x51\x64\x89\x44\x13\xca"
"\xc7\x41\xa4\xf7\xa8\xf6\xd4\xbc\xd7\xc1\x7d\xa3\xbf\x39\x4b"
"\x37\x1c\xac\xec\xf6\x46\x82\xdc\x05\x25\xf1\x7c\x71\x9e\xe9"
"\x0b\xd5\xb0\x40\x15\x7f\x4f\x01\x6a\x1c\x56\x2e\x42\x05",
"\x00\x9b\xd7\x14\x9e\xcf\x47\x4a\xe5\x1e\xa8\xc4\x93\x52\xd2"
"\x4c\xb7\xd3\x67\xa3\x4e\x79\x34\x09\x5e\x5c\x5c\x55\xe3\x3c"
"\x02\xa9\x81\xa4\x56\xa8\xb1\x3d\xf6\x40\xe3\xf5\x06\xce\x6f"
"\x29\x01\x05\xde\x43\xa8\x67\xeb\x29\x8d\x09\xd8\x7d\xaf\x3f"
"\x51\xac\xf4\x5b\x0c\xa0\x95\x35\x04\xd0\xf9\x6f\x6a\xa7",
"\x02\xfd\x38\x42\x48\x82\x90\x3a\xb0\xd4\x10\xd9\xba\x35\xd5"
"\x6f\xe1\xb4\xc7\x65\x30\xe7\x2f\xa7\x08\xbe\xfe\x21\x69\x62"
"\xcd\xc3\x42\x04\x1a\xfc\x6a\x24\x4a\x13\x8c\xa3\x4e\x71\x09"
"\x42\xa9\x5d\x03\xd7\x1e\xf0\xa9\xbf\xd1\x13\x59\x07\xa1\x45"
"\xde\xae\xd0\x5a\x98\xeb\x22\xf5\x3d\xc2\xa2\x35\x77\x91",
"\x13\x1d\x2c\x60\x28\xb5\x54\x88\x6b\x1e\x2d\xe2\x0f\xb0\xb2"
"\xe5\xf8\x47\x06\x97\x30\x82\x24\x72\x1f\x77\x8e\x71\x68\xee"
"\x58\x8b\x0c\xc7\xaa\x66\x89\x00\x88\x7f\x49\xae\xb8\xb4\xd6"
"\xd3\xa6\xec\xc2\x5f\x95\x5b\xb7\xf6\xbe\x40\x43\xe5\xe9\x64"
"\xef\xe6\xed\x92\xb4\xba\xea\x63\x0e\x4d\xdf\x98\xc1"
};
static int exps_len[] = { 74, 74, 74, 74, 73 };
static char *coefficients[] = {
"\x18\x19\x50\xc2\x69\x6a\x63\x66\x40\x6a\x43\xa6\x7d\x0d\x12"
"\x0f\x04\x3a\xe7\xb2\x1c\xe3\xfc\x6f\xa7\x8b\x5e\x99\xe3\x43"
"\x97\x68\x10\xee\x68\x73\x01\xc6\xaf\x5e\x26\xaf\xcc\x1f\x39"
"\x9c\x8d\xa9\x06\x80\x21\x7a\xaa\x29\x8a\x4b\x71\x03\xb0\x9a"
"\x2f\xd6\x6b\xb0\x0b\x93\xc9\x4d\x0b\x9d\x3f\xe6\x21",
"\x00\xa4\x80\x6e\xef\x34\xba\x3f\xe7\x96\xec\x25\x16\x25\xe9"
"\x77\x5f\x61\xb1\x48\xdb\x03\xfa\x80\xf3\xbd\x20\xd1\x60\x9a"
"\x10\x9d\xf0\x1b\xff\xb8\x50\x14\x54\x75\x53\x2b\x89\x9f\x39"
"\x96\x63\x05\x89\xfb\xfb\x7f\x59\x93\xdc\x61\xe2\x8c\xfc\x5a"
"\x6f\x2c\x6a\xcf\xd4\xac\xa5\x81\xf2\xdd\x68\x75\xd4\x48",
"\x00\xf6\xec\xd6\x98\x10\x42\x38\x94\x30\x2c\xd4\xe7\xb1\x5f"
"\xa2\xfd\xc9\xc4\x92\x78\xf6\x31\x34\xb7\x26\xa1\x7f\x0b\xa3"
"\xc3\xf6\x4f\xd0\x05\x4e\x98\x1b\xa5\x98\xde\x26\xb8\xc2\x14"
"\x12\xa4\xae\x2f\xd8\x48\x39\x1b\x33\x1d\x0f\x72\xaf\xd3\x8d"
"\xd8\xb0\x9f\x52\x42\x5d\xae\xf6\x3c\xe1\xd2\x09\xd8\x53",
"\x00\xb3\xce\x4b\x87\x41\x21\x34\x7b\xe3\x64\x74\xef\x9f\x71"
"\xcc\x01\x19\x50\x69\xbb\x5f\x69\xc8\xbc\x62\x8b\x4d\xa9\x73"
"\x23\x7f\xc6\xce\xfa\xe7\x96\xa7\x22\x44\x33\x32\x47\x60\x23"
"\xb4\xd2\x5e\xa4\xa1\xbd\x31\x1f\x04\x1a\xdf\xdb\x05\xe9\x4c"
"\x44\xfb\x9b\x73\xfe\x25\x3d\x7a\x61\xc2\x22\x9a\xd6\x18",
"\x01\x8d\x43\x63\x89\x6d\x97\xf3\x4a\x3e\x10\xa0\x94\x46\x1a"
"\x1c\x34\x22\xb3\xe3\x21\xff\xad\xf2\x1b\x56\x74\x32\xdc\xd2"
"\x0e\xd7\x3a\x9c\xe9\x87\xcc\xf1\x9c\x56\xfe\xff\x2f\x3d\xec"
"\x70\xba\xfb\x5d\x37\xa8\x57\xd1\xc4\xa9\x1b\xc9\xdc\x76\x68"
"\xca\x7d\x39\x59\x97\x2d\x07\x03\x52\xf6\x8d\xb6\x0e\x24"
};
static int coeffs_len[] = { 73, 74, 74, 74, 74 };
BIGNUM **pris = NULL, **exps = NULL, **coeffs = NULL;
int i, rv = 512;
unsigned char *n, *d;
size_t len_n, len_d;
len_n = sizeof(n1) + sizeof(n2) - 2;
n = OPENSSL_zalloc(len_n);
if (n == NULL)
return 0;
memcpy(n, n1, sizeof(n1) - 1);
memcpy(n + sizeof(n1) - 1, n2, sizeof(n2) - 1);
len_d = sizeof(d1) + sizeof(d2) - 2;
d = OPENSSL_zalloc(len_d);
if (d == NULL)
goto err;
memcpy(d, d1, sizeof(d1) - 1);
memcpy(d + sizeof(d1) - 1, d2, sizeof(d2) - 1);
if (!TEST_int_eq(RSA_set0_key(key,
BN_bin2bn(n, len_n, NULL),
BN_bin2bn(e, sizeof(e) - 1, NULL),
BN_bin2bn(d, len_d, NULL)), 1))
goto err;
if (!TEST_int_eq(RSA_set0_factors(key,
BN_bin2bn(p, sizeof(p) - 1, NULL),
BN_bin2bn(q, sizeof(q) - 1, NULL)), 1))
goto err;
if (!TEST_int_eq(RSA_set0_crt_params(key,
BN_bin2bn(dmp1, sizeof(dmp1) - 1, NULL),
BN_bin2bn(dmq1, sizeof(dmq1) - 1, NULL),
BN_bin2bn(iqmp, sizeof(iqmp) - 1,
NULL)), 1))
return 0;
pris = OPENSSL_zalloc(sizeof(BIGNUM *) * NUM_EXTRA_PRIMES);
exps = OPENSSL_zalloc(sizeof(BIGNUM *) * NUM_EXTRA_PRIMES);
coeffs = OPENSSL_zalloc(sizeof(BIGNUM *) * NUM_EXTRA_PRIMES);
if (!TEST_ptr(pris) || !TEST_ptr(exps) || !TEST_ptr(coeffs))
goto err;
for (i = 0; i < NUM_EXTRA_PRIMES; i++) {
pris[i] = BN_bin2bn((unsigned char *)primes[i], primes_len[i], NULL);
exps[i] = BN_bin2bn((unsigned char *)exponents[i], exps_len[i], NULL);
coeffs[i] = BN_bin2bn((unsigned char *)coefficients[i],
coeffs_len[i], NULL);
if (!TEST_ptr(pris[i]) || !TEST_ptr(exps[i]) || !TEST_ptr(coeffs[i]))
goto err;
}
if (!TEST_true(RSA_set0_multi_prime_params(key, pris, exps,
coeffs, NUM_EXTRA_PRIMES)))
goto err;
ret:
OPENSSL_free(pris);
OPENSSL_free(exps);
OPENSSL_free(coeffs);
OPENSSL_free(n);
OPENSSL_free(d);
return rv;
err:
for (i = 0; i < 5; i++) {
if (pris != NULL)
BN_free(pris[i]);
if (exps != NULL)
BN_free(exps[i]);
if (coeffs != NULL)
BN_free(coeffs[i]);
}
rv = 0;
goto ret;
}
static int test_rsa_mp(void)
{
int ret = 0;
RSA *key;
unsigned char ptext[512];
unsigned char ctext[512];
static unsigned char ptext_ex[] = "\x54\x85\x9b\x34\x2c\x49\xea\x2a";
int plen;
int clen = 0;
int num;
plen = sizeof(ptext_ex) - 1;
key = RSA_new();
if (!TEST_ptr(key))
goto err;
clen = key4096p7(key);
if (!TEST_int_eq(clen, 512))
goto err;
if (!TEST_true(RSA_check_key_ex(key, NULL)))
goto err;
num = RSA_public_encrypt(plen, ptext_ex, ctext, key,
RSA_PKCS1_PADDING);
if (!TEST_int_eq(num, clen))
goto err;
num = RSA_private_decrypt(num, ctext, ptext, key, RSA_PKCS1_PADDING);
if (!TEST_mem_eq(ptext, num, ptext_ex, plen))
goto err;
ret = 1;
err:
RSA_free(key);
return ret;
}
#endif
int setup_tests(void)
{
#ifndef OPENSSL_NO_RSA
ADD_TEST(test_rsa_mp);
#endif
return 1;
}

View File

@ -4438,3 +4438,11 @@ EVP_PKEY_asn1_set_param_check 4382 1_1_1 EXIST::FUNCTION:
DH_check_ex 4383 1_1_1 EXIST::FUNCTION:DH
DH_check_pub_key_ex 4384 1_1_1 EXIST::FUNCTION:DH
DH_check_params_ex 4385 1_1_1 EXIST::FUNCTION:DH
RSA_generate_multi_prime_key 4386 1_1_1 EXIST::FUNCTION:RSA
RSA_get_multi_prime_extra_count 4387 1_1_1 EXIST::FUNCTION:RSA
RSA_get0_multi_prime_factors 4388 1_1_1 EXIST::FUNCTION:RSA
RSA_get0_multi_prime_crt_params 4389 1_1_1 EXIST::FUNCTION:RSA
RSA_set0_multi_prime_params 4390 1_1_1 EXIST::FUNCTION:RSA
RSA_get_version 4391 1_1_1 EXIST::FUNCTION:RSA
RSA_meth_get_multi_prime_keygen 4392 1_1_1 EXIST::FUNCTION:RSA
RSA_meth_set_multi_prime_keygen 4393 1_1_1 EXIST::FUNCTION:RSA