Commit 665d899f authored by Paul Yang's avatar Paul Yang
Browse files

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: default avatarTim Hudson <tjh@openssl.org>
Reviewed-by: default avatarBernd Edlinger <bernd.edlinger@hotmail.de>
(Merged from https://github.com/openssl/openssl/pull/4241)
parent b0004708
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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>,
+12 −5
Original line number Diff line number Diff line
@@ -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);
+40 −1
Original line number Diff line number Diff line
@@ -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)
+6 −0
Original line number Diff line number Diff line
@@ -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:\
+1 −1
Original line number Diff line number Diff line
@@ -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
Loading