xref: /freebsd/crypto/openssl/crypto/rsa/rsa_pmeth.c (revision aa7957345732816fb0ba8308798d2f79f45597f9)
16f9291ceSJung-uk Kim /*
2*aa795734SPierre Pronchery  * Copyright 2006-2023 The OpenSSL Project Authors. All Rights Reserved.
31f13597dSJung-uk Kim  *
4b077aed3SPierre Pronchery  * Licensed under the Apache License 2.0 (the "License").  You may not use
5e71b7053SJung-uk Kim  * this file except in compliance with the License.  You can obtain a copy
6e71b7053SJung-uk Kim  * in the file LICENSE in the source distribution or at
7e71b7053SJung-uk Kim  * https://www.openssl.org/source/license.html
81f13597dSJung-uk Kim  */
91f13597dSJung-uk Kim 
10b077aed3SPierre Pronchery /*
11b077aed3SPierre Pronchery  * RSA low level APIs are deprecated for public use, but still ok for
12b077aed3SPierre Pronchery  * internal use.
13b077aed3SPierre Pronchery  */
14b077aed3SPierre Pronchery #include "internal/deprecated.h"
15b077aed3SPierre Pronchery 
1617f01e99SJung-uk Kim #include "internal/constant_time.h"
17610a21fdSJung-uk Kim 
181f13597dSJung-uk Kim #include <stdio.h>
19e71b7053SJung-uk Kim #include "internal/cryptlib.h"
201f13597dSJung-uk Kim #include <openssl/asn1t.h>
211f13597dSJung-uk Kim #include <openssl/x509.h>
221f13597dSJung-uk Kim #include <openssl/rsa.h>
231f13597dSJung-uk Kim #include <openssl/bn.h>
241f13597dSJung-uk Kim #include <openssl/evp.h>
257bded2dbSJung-uk Kim #include <openssl/x509v3.h>
261f13597dSJung-uk Kim #include <openssl/cms.h>
2717f01e99SJung-uk Kim #include "crypto/evp.h"
28b077aed3SPierre Pronchery #include "crypto/rsa.h"
2917f01e99SJung-uk Kim #include "rsa_local.h"
301f13597dSJung-uk Kim 
311f13597dSJung-uk Kim /* RSA pkey context structure */
321f13597dSJung-uk Kim 
336f9291ceSJung-uk Kim typedef struct {
341f13597dSJung-uk Kim     /* Key gen parameters */
351f13597dSJung-uk Kim     int nbits;
361f13597dSJung-uk Kim     BIGNUM *pub_exp;
37e71b7053SJung-uk Kim     int primes;
381f13597dSJung-uk Kim     /* Keygen callback info */
391f13597dSJung-uk Kim     int gentmp[2];
401f13597dSJung-uk Kim     /* RSA padding mode */
411f13597dSJung-uk Kim     int pad_mode;
421f13597dSJung-uk Kim     /* message digest */
431f13597dSJung-uk Kim     const EVP_MD *md;
441f13597dSJung-uk Kim     /* message digest for MGF1 */
451f13597dSJung-uk Kim     const EVP_MD *mgf1md;
467bded2dbSJung-uk Kim     /* PSS salt length */
471f13597dSJung-uk Kim     int saltlen;
48e71b7053SJung-uk Kim     /* Minimum salt length or -1 if no PSS parameter restriction */
49e71b7053SJung-uk Kim     int min_saltlen;
501f13597dSJung-uk Kim     /* Temp buffer */
511f13597dSJung-uk Kim     unsigned char *tbuf;
527bded2dbSJung-uk Kim     /* OAEP label */
537bded2dbSJung-uk Kim     unsigned char *oaep_label;
547bded2dbSJung-uk Kim     size_t oaep_labellen;
551f13597dSJung-uk Kim } RSA_PKEY_CTX;
561f13597dSJung-uk Kim 
57e71b7053SJung-uk Kim /* True if PSS parameters are restricted */
58e71b7053SJung-uk Kim #define rsa_pss_restricted(rctx) (rctx->min_saltlen != -1)
59e71b7053SJung-uk Kim 
pkey_rsa_init(EVP_PKEY_CTX * ctx)601f13597dSJung-uk Kim static int pkey_rsa_init(EVP_PKEY_CTX *ctx)
611f13597dSJung-uk Kim {
62e71b7053SJung-uk Kim     RSA_PKEY_CTX *rctx = OPENSSL_zalloc(sizeof(*rctx));
63e71b7053SJung-uk Kim 
64e71b7053SJung-uk Kim     if (rctx == NULL)
651f13597dSJung-uk Kim         return 0;
66610a21fdSJung-uk Kim     rctx->nbits = 2048;
67e71b7053SJung-uk Kim     rctx->primes = RSA_DEFAULT_PRIME_NUM;
68e71b7053SJung-uk Kim     if (pkey_ctx_is_pss(ctx))
69e71b7053SJung-uk Kim         rctx->pad_mode = RSA_PKCS1_PSS_PADDING;
70e71b7053SJung-uk Kim     else
711f13597dSJung-uk Kim         rctx->pad_mode = RSA_PKCS1_PADDING;
72e71b7053SJung-uk Kim     /* Maximum for sign, auto for verify */
73e71b7053SJung-uk Kim     rctx->saltlen = RSA_PSS_SALTLEN_AUTO;
74e71b7053SJung-uk Kim     rctx->min_saltlen = -1;
751f13597dSJung-uk Kim     ctx->data = rctx;
761f13597dSJung-uk Kim     ctx->keygen_info = rctx->gentmp;
771f13597dSJung-uk Kim     ctx->keygen_info_count = 2;
781f13597dSJung-uk Kim 
791f13597dSJung-uk Kim     return 1;
801f13597dSJung-uk Kim }
811f13597dSJung-uk Kim 
pkey_rsa_copy(EVP_PKEY_CTX * dst,const EVP_PKEY_CTX * src)82b077aed3SPierre Pronchery static int pkey_rsa_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src)
831f13597dSJung-uk Kim {
841f13597dSJung-uk Kim     RSA_PKEY_CTX *dctx, *sctx;
85e71b7053SJung-uk Kim 
861f13597dSJung-uk Kim     if (!pkey_rsa_init(dst))
871f13597dSJung-uk Kim         return 0;
881f13597dSJung-uk Kim     sctx = src->data;
891f13597dSJung-uk Kim     dctx = dst->data;
901f13597dSJung-uk Kim     dctx->nbits = sctx->nbits;
916f9291ceSJung-uk Kim     if (sctx->pub_exp) {
921f13597dSJung-uk Kim         dctx->pub_exp = BN_dup(sctx->pub_exp);
931f13597dSJung-uk Kim         if (!dctx->pub_exp)
941f13597dSJung-uk Kim             return 0;
951f13597dSJung-uk Kim     }
961f13597dSJung-uk Kim     dctx->pad_mode = sctx->pad_mode;
971f13597dSJung-uk Kim     dctx->md = sctx->md;
987bded2dbSJung-uk Kim     dctx->mgf1md = sctx->mgf1md;
99b077aed3SPierre Pronchery     dctx->saltlen = sctx->saltlen;
1007bded2dbSJung-uk Kim     if (sctx->oaep_label) {
1017bded2dbSJung-uk Kim         OPENSSL_free(dctx->oaep_label);
102e71b7053SJung-uk Kim         dctx->oaep_label = OPENSSL_memdup(sctx->oaep_label, sctx->oaep_labellen);
1037bded2dbSJung-uk Kim         if (!dctx->oaep_label)
1047bded2dbSJung-uk Kim             return 0;
1057bded2dbSJung-uk Kim         dctx->oaep_labellen = sctx->oaep_labellen;
1067bded2dbSJung-uk Kim     }
1071f13597dSJung-uk Kim     return 1;
1081f13597dSJung-uk Kim }
1091f13597dSJung-uk Kim 
setup_tbuf(RSA_PKEY_CTX * ctx,EVP_PKEY_CTX * pk)1101f13597dSJung-uk Kim static int setup_tbuf(RSA_PKEY_CTX *ctx, EVP_PKEY_CTX *pk)
1111f13597dSJung-uk Kim {
112e71b7053SJung-uk Kim     if (ctx->tbuf != NULL)
1131f13597dSJung-uk Kim         return 1;
114b077aed3SPierre Pronchery     if ((ctx->tbuf =
115b077aed3SPierre Pronchery             OPENSSL_malloc(RSA_size(EVP_PKEY_get0_RSA(pk->pkey)))) == NULL) {
116b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
1171f13597dSJung-uk Kim         return 0;
118e71b7053SJung-uk Kim     }
1191f13597dSJung-uk Kim     return 1;
1201f13597dSJung-uk Kim }
1211f13597dSJung-uk Kim 
pkey_rsa_cleanup(EVP_PKEY_CTX * ctx)1221f13597dSJung-uk Kim static void pkey_rsa_cleanup(EVP_PKEY_CTX *ctx)
1231f13597dSJung-uk Kim {
1241f13597dSJung-uk Kim     RSA_PKEY_CTX *rctx = ctx->data;
1256f9291ceSJung-uk Kim     if (rctx) {
1261f13597dSJung-uk Kim         BN_free(rctx->pub_exp);
1271f13597dSJung-uk Kim         OPENSSL_free(rctx->tbuf);
1287bded2dbSJung-uk Kim         OPENSSL_free(rctx->oaep_label);
1291f13597dSJung-uk Kim         OPENSSL_free(rctx);
1301f13597dSJung-uk Kim     }
1311f13597dSJung-uk Kim }
1326f9291ceSJung-uk Kim 
pkey_rsa_sign(EVP_PKEY_CTX * ctx,unsigned char * sig,size_t * siglen,const unsigned char * tbs,size_t tbslen)1336f9291ceSJung-uk Kim static int pkey_rsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig,
1346f9291ceSJung-uk Kim                          size_t *siglen, const unsigned char *tbs,
1356f9291ceSJung-uk Kim                          size_t tbslen)
1361f13597dSJung-uk Kim {
1371f13597dSJung-uk Kim     int ret;
1381f13597dSJung-uk Kim     RSA_PKEY_CTX *rctx = ctx->data;
139b077aed3SPierre Pronchery     /*
140b077aed3SPierre Pronchery      * Discard const. Its marked as const because this may be a cached copy of
141b077aed3SPierre Pronchery      * the "real" key. These calls don't make any modifications that need to
142b077aed3SPierre Pronchery      * be reflected back in the "original" key.
143b077aed3SPierre Pronchery      */
144b077aed3SPierre Pronchery     RSA *rsa = (RSA *)EVP_PKEY_get0_RSA(ctx->pkey);
1451f13597dSJung-uk Kim 
146e71b7053SJung-uk Kim     if (rctx->md) {
147b077aed3SPierre Pronchery         if (tbslen != (size_t)EVP_MD_get_size(rctx->md)) {
148b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_DIGEST_LENGTH);
1491f13597dSJung-uk Kim             return -1;
1501f13597dSJung-uk Kim         }
1511f13597dSJung-uk Kim 
152b077aed3SPierre Pronchery         if (EVP_MD_get_type(rctx->md) == NID_mdc2) {
1531f13597dSJung-uk Kim             unsigned int sltmp;
1541f13597dSJung-uk Kim             if (rctx->pad_mode != RSA_PKCS1_PADDING)
1551f13597dSJung-uk Kim                 return -1;
156b077aed3SPierre Pronchery             ret = RSA_sign_ASN1_OCTET_STRING(0, tbs, tbslen, sig, &sltmp, rsa);
1571f13597dSJung-uk Kim 
1581f13597dSJung-uk Kim             if (ret <= 0)
1591f13597dSJung-uk Kim                 return ret;
1601f13597dSJung-uk Kim             ret = sltmp;
1616f9291ceSJung-uk Kim         } else if (rctx->pad_mode == RSA_X931_PADDING) {
162b077aed3SPierre Pronchery             if ((size_t)RSA_size(rsa) < tbslen + 1) {
163b077aed3SPierre Pronchery                 ERR_raise(ERR_LIB_RSA, RSA_R_KEY_SIZE_TOO_SMALL);
1641f13597dSJung-uk Kim                 return -1;
165ed6b93beSJung-uk Kim             }
166ed6b93beSJung-uk Kim             if (!setup_tbuf(rctx, ctx)) {
167b077aed3SPierre Pronchery                 ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
168ed6b93beSJung-uk Kim                 return -1;
169ed6b93beSJung-uk Kim             }
1701f13597dSJung-uk Kim             memcpy(rctx->tbuf, tbs, tbslen);
171b077aed3SPierre Pronchery             rctx->tbuf[tbslen] = RSA_X931_hash_id(EVP_MD_get_type(rctx->md));
1721f13597dSJung-uk Kim             ret = RSA_private_encrypt(tbslen + 1, rctx->tbuf,
1731f13597dSJung-uk Kim                                       sig, rsa, RSA_X931_PADDING);
1746f9291ceSJung-uk Kim         } else if (rctx->pad_mode == RSA_PKCS1_PADDING) {
1751f13597dSJung-uk Kim             unsigned int sltmp;
176b077aed3SPierre Pronchery             ret = RSA_sign(EVP_MD_get_type(rctx->md),
177e71b7053SJung-uk Kim                            tbs, tbslen, sig, &sltmp, rsa);
1781f13597dSJung-uk Kim             if (ret <= 0)
1791f13597dSJung-uk Kim                 return ret;
1801f13597dSJung-uk Kim             ret = sltmp;
1816f9291ceSJung-uk Kim         } else if (rctx->pad_mode == RSA_PKCS1_PSS_PADDING) {
1821f13597dSJung-uk Kim             if (!setup_tbuf(rctx, ctx))
1831f13597dSJung-uk Kim                 return -1;
184e71b7053SJung-uk Kim             if (!RSA_padding_add_PKCS1_PSS_mgf1(rsa,
185e71b7053SJung-uk Kim                                                 rctx->tbuf, tbs,
186e71b7053SJung-uk Kim                                                 rctx->md, rctx->mgf1md,
187e71b7053SJung-uk Kim                                                 rctx->saltlen))
1881f13597dSJung-uk Kim                 return -1;
1891f13597dSJung-uk Kim             ret = RSA_private_encrypt(RSA_size(rsa), rctx->tbuf,
1901f13597dSJung-uk Kim                                       sig, rsa, RSA_NO_PADDING);
191e71b7053SJung-uk Kim         } else {
1921f13597dSJung-uk Kim             return -1;
193e71b7053SJung-uk Kim         }
194e71b7053SJung-uk Kim     } else {
195b077aed3SPierre Pronchery         ret = RSA_private_encrypt(tbslen, tbs, sig, rsa, rctx->pad_mode);
196e71b7053SJung-uk Kim     }
1971f13597dSJung-uk Kim     if (ret < 0)
1981f13597dSJung-uk Kim         return ret;
1991f13597dSJung-uk Kim     *siglen = ret;
2001f13597dSJung-uk Kim     return 1;
2011f13597dSJung-uk Kim }
2021f13597dSJung-uk Kim 
pkey_rsa_verifyrecover(EVP_PKEY_CTX * ctx,unsigned char * rout,size_t * routlen,const unsigned char * sig,size_t siglen)2031f13597dSJung-uk Kim static int pkey_rsa_verifyrecover(EVP_PKEY_CTX *ctx,
2041f13597dSJung-uk Kim                                   unsigned char *rout, size_t *routlen,
2051f13597dSJung-uk Kim                                   const unsigned char *sig, size_t siglen)
2061f13597dSJung-uk Kim {
2071f13597dSJung-uk Kim     int ret;
2081f13597dSJung-uk Kim     RSA_PKEY_CTX *rctx = ctx->data;
209b077aed3SPierre Pronchery     /*
210b077aed3SPierre Pronchery      * Discard const. Its marked as const because this may be a cached copy of
211b077aed3SPierre Pronchery      * the "real" key. These calls don't make any modifications that need to
212b077aed3SPierre Pronchery      * be reflected back in the "original" key.
213b077aed3SPierre Pronchery      */
214b077aed3SPierre Pronchery     RSA *rsa = (RSA *)EVP_PKEY_get0_RSA(ctx->pkey);
2151f13597dSJung-uk Kim 
2166f9291ceSJung-uk Kim     if (rctx->md) {
2176f9291ceSJung-uk Kim         if (rctx->pad_mode == RSA_X931_PADDING) {
2181f13597dSJung-uk Kim             if (!setup_tbuf(rctx, ctx))
2191f13597dSJung-uk Kim                 return -1;
220b077aed3SPierre Pronchery             ret = RSA_public_decrypt(siglen, sig, rctx->tbuf, rsa,
2211f13597dSJung-uk Kim                                      RSA_X931_PADDING);
2221f13597dSJung-uk Kim             if (ret < 1)
2231f13597dSJung-uk Kim                 return 0;
2241f13597dSJung-uk Kim             ret--;
225b077aed3SPierre Pronchery             if (rctx->tbuf[ret] != RSA_X931_hash_id(EVP_MD_get_type(rctx->md))) {
226b077aed3SPierre Pronchery                 ERR_raise(ERR_LIB_RSA, RSA_R_ALGORITHM_MISMATCH);
2271f13597dSJung-uk Kim                 return 0;
2281f13597dSJung-uk Kim             }
229b077aed3SPierre Pronchery             if (ret != EVP_MD_get_size(rctx->md)) {
230b077aed3SPierre Pronchery                 ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_DIGEST_LENGTH);
2311f13597dSJung-uk Kim                 return 0;
2321f13597dSJung-uk Kim             }
2331f13597dSJung-uk Kim             if (rout)
2341f13597dSJung-uk Kim                 memcpy(rout, rctx->tbuf, ret);
2356f9291ceSJung-uk Kim         } else if (rctx->pad_mode == RSA_PKCS1_PADDING) {
2361f13597dSJung-uk Kim             size_t sltmp;
237b077aed3SPierre Pronchery             ret = ossl_rsa_verify(EVP_MD_get_type(rctx->md),
2381f13597dSJung-uk Kim                                   NULL, 0, rout, &sltmp,
239b077aed3SPierre Pronchery                                   sig, siglen, rsa);
2401f13597dSJung-uk Kim             if (ret <= 0)
2411f13597dSJung-uk Kim                 return 0;
2421f13597dSJung-uk Kim             ret = sltmp;
243e71b7053SJung-uk Kim         } else {
2441f13597dSJung-uk Kim             return -1;
245e71b7053SJung-uk Kim         }
246e71b7053SJung-uk Kim     } else {
247b077aed3SPierre Pronchery         ret = RSA_public_decrypt(siglen, sig, rout, rsa, rctx->pad_mode);
248e71b7053SJung-uk Kim     }
2491f13597dSJung-uk Kim     if (ret < 0)
2501f13597dSJung-uk Kim         return ret;
2511f13597dSJung-uk Kim     *routlen = ret;
2521f13597dSJung-uk Kim     return 1;
2531f13597dSJung-uk Kim }
2541f13597dSJung-uk Kim 
pkey_rsa_verify(EVP_PKEY_CTX * ctx,const unsigned char * sig,size_t siglen,const unsigned char * tbs,size_t tbslen)2551f13597dSJung-uk Kim static int pkey_rsa_verify(EVP_PKEY_CTX *ctx,
2561f13597dSJung-uk Kim                            const unsigned char *sig, size_t siglen,
2571f13597dSJung-uk Kim                            const unsigned char *tbs, size_t tbslen)
2581f13597dSJung-uk Kim {
2591f13597dSJung-uk Kim     RSA_PKEY_CTX *rctx = ctx->data;
260b077aed3SPierre Pronchery     /*
261b077aed3SPierre Pronchery      * Discard const. Its marked as const because this may be a cached copy of
262b077aed3SPierre Pronchery      * the "real" key. These calls don't make any modifications that need to
263b077aed3SPierre Pronchery      * be reflected back in the "original" key.
264b077aed3SPierre Pronchery      */
265b077aed3SPierre Pronchery     RSA *rsa = (RSA *)EVP_PKEY_get0_RSA(ctx->pkey);
2661f13597dSJung-uk Kim     size_t rslen;
26747902a71SJung-uk Kim 
268e71b7053SJung-uk Kim     if (rctx->md) {
2691f13597dSJung-uk Kim         if (rctx->pad_mode == RSA_PKCS1_PADDING)
270b077aed3SPierre Pronchery             return RSA_verify(EVP_MD_get_type(rctx->md), tbs, tbslen,
2711f13597dSJung-uk Kim                               sig, siglen, rsa);
272b077aed3SPierre Pronchery         if (tbslen != (size_t)EVP_MD_get_size(rctx->md)) {
273b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_DIGEST_LENGTH);
2746cf8931aSJung-uk Kim             return -1;
2756cf8931aSJung-uk Kim         }
2766f9291ceSJung-uk Kim         if (rctx->pad_mode == RSA_X931_PADDING) {
2776f9291ceSJung-uk Kim             if (pkey_rsa_verifyrecover(ctx, NULL, &rslen, sig, siglen) <= 0)
2781f13597dSJung-uk Kim                 return 0;
2796f9291ceSJung-uk Kim         } else if (rctx->pad_mode == RSA_PKCS1_PSS_PADDING) {
2801f13597dSJung-uk Kim             int ret;
2811f13597dSJung-uk Kim             if (!setup_tbuf(rctx, ctx))
2821f13597dSJung-uk Kim                 return -1;
2831f13597dSJung-uk Kim             ret = RSA_public_decrypt(siglen, sig, rctx->tbuf,
2841f13597dSJung-uk Kim                                      rsa, RSA_NO_PADDING);
2851f13597dSJung-uk Kim             if (ret <= 0)
2861f13597dSJung-uk Kim                 return 0;
287e71b7053SJung-uk Kim             ret = RSA_verify_PKCS1_PSS_mgf1(rsa, tbs,
288e71b7053SJung-uk Kim                                             rctx->md, rctx->mgf1md,
2891f13597dSJung-uk Kim                                             rctx->tbuf, rctx->saltlen);
2901f13597dSJung-uk Kim             if (ret <= 0)
2911f13597dSJung-uk Kim                 return 0;
2921f13597dSJung-uk Kim             return 1;
293e71b7053SJung-uk Kim         } else {
2941f13597dSJung-uk Kim             return -1;
295e71b7053SJung-uk Kim         }
2966f9291ceSJung-uk Kim     } else {
2971f13597dSJung-uk Kim         if (!setup_tbuf(rctx, ctx))
2981f13597dSJung-uk Kim             return -1;
2991f13597dSJung-uk Kim         rslen = RSA_public_decrypt(siglen, sig, rctx->tbuf,
3001f13597dSJung-uk Kim                                    rsa, rctx->pad_mode);
3011f13597dSJung-uk Kim         if (rslen == 0)
3021f13597dSJung-uk Kim             return 0;
3031f13597dSJung-uk Kim     }
3041f13597dSJung-uk Kim 
3051f13597dSJung-uk Kim     if ((rslen != tbslen) || memcmp(tbs, rctx->tbuf, rslen))
3061f13597dSJung-uk Kim         return 0;
3071f13597dSJung-uk Kim 
3081f13597dSJung-uk Kim     return 1;
3091f13597dSJung-uk Kim 
3101f13597dSJung-uk Kim }
3111f13597dSJung-uk Kim 
pkey_rsa_encrypt(EVP_PKEY_CTX * ctx,unsigned char * out,size_t * outlen,const unsigned char * in,size_t inlen)3121f13597dSJung-uk Kim static int pkey_rsa_encrypt(EVP_PKEY_CTX *ctx,
3131f13597dSJung-uk Kim                             unsigned char *out, size_t *outlen,
3141f13597dSJung-uk Kim                             const unsigned char *in, size_t inlen)
3151f13597dSJung-uk Kim {
3161f13597dSJung-uk Kim     int ret;
3171f13597dSJung-uk Kim     RSA_PKEY_CTX *rctx = ctx->data;
318b077aed3SPierre Pronchery     /*
319b077aed3SPierre Pronchery      * Discard const. Its marked as const because this may be a cached copy of
320b077aed3SPierre Pronchery      * the "real" key. These calls don't make any modifications that need to
321b077aed3SPierre Pronchery      * be reflected back in the "original" key.
322b077aed3SPierre Pronchery      */
323b077aed3SPierre Pronchery     RSA *rsa = (RSA *)EVP_PKEY_get0_RSA(ctx->pkey);
324e71b7053SJung-uk Kim 
3257bded2dbSJung-uk Kim     if (rctx->pad_mode == RSA_PKCS1_OAEP_PADDING) {
326b077aed3SPierre Pronchery         int klen = RSA_size(rsa);
3277bded2dbSJung-uk Kim         if (!setup_tbuf(rctx, ctx))
3287bded2dbSJung-uk Kim             return -1;
3297bded2dbSJung-uk Kim         if (!RSA_padding_add_PKCS1_OAEP_mgf1(rctx->tbuf, klen,
3307bded2dbSJung-uk Kim                                              in, inlen,
3317bded2dbSJung-uk Kim                                              rctx->oaep_label,
3327bded2dbSJung-uk Kim                                              rctx->oaep_labellen,
3337bded2dbSJung-uk Kim                                              rctx->md, rctx->mgf1md))
3347bded2dbSJung-uk Kim             return -1;
335b077aed3SPierre Pronchery         ret = RSA_public_encrypt(klen, rctx->tbuf, out, rsa, RSA_NO_PADDING);
336e71b7053SJung-uk Kim     } else {
337b077aed3SPierre Pronchery         ret = RSA_public_encrypt(inlen, in, out, rsa, rctx->pad_mode);
338e71b7053SJung-uk Kim     }
3391f13597dSJung-uk Kim     if (ret < 0)
3401f13597dSJung-uk Kim         return ret;
3411f13597dSJung-uk Kim     *outlen = ret;
3421f13597dSJung-uk Kim     return 1;
3431f13597dSJung-uk Kim }
3441f13597dSJung-uk Kim 
pkey_rsa_decrypt(EVP_PKEY_CTX * ctx,unsigned char * out,size_t * outlen,const unsigned char * in,size_t inlen)3451f13597dSJung-uk Kim static int pkey_rsa_decrypt(EVP_PKEY_CTX *ctx,
3461f13597dSJung-uk Kim                             unsigned char *out, size_t *outlen,
3471f13597dSJung-uk Kim                             const unsigned char *in, size_t inlen)
3481f13597dSJung-uk Kim {
3491f13597dSJung-uk Kim     int ret;
3501f13597dSJung-uk Kim     RSA_PKEY_CTX *rctx = ctx->data;
351b077aed3SPierre Pronchery     /*
352b077aed3SPierre Pronchery      * Discard const. Its marked as const because this may be a cached copy of
353b077aed3SPierre Pronchery      * the "real" key. These calls don't make any modifications that need to
354b077aed3SPierre Pronchery      * be reflected back in the "original" key.
355b077aed3SPierre Pronchery      */
356b077aed3SPierre Pronchery     RSA *rsa = (RSA *)EVP_PKEY_get0_RSA(ctx->pkey);
357e71b7053SJung-uk Kim 
3587bded2dbSJung-uk Kim     if (rctx->pad_mode == RSA_PKCS1_OAEP_PADDING) {
3597bded2dbSJung-uk Kim         if (!setup_tbuf(rctx, ctx))
3607bded2dbSJung-uk Kim             return -1;
361b077aed3SPierre Pronchery         ret = RSA_private_decrypt(inlen, in, rctx->tbuf, rsa, RSA_NO_PADDING);
3627bded2dbSJung-uk Kim         if (ret <= 0)
3637bded2dbSJung-uk Kim             return ret;
364ed7112f0SJung-uk Kim         ret = RSA_padding_check_PKCS1_OAEP_mgf1(out, ret, rctx->tbuf,
365ed7112f0SJung-uk Kim                                                 ret, ret,
3667bded2dbSJung-uk Kim                                                 rctx->oaep_label,
3677bded2dbSJung-uk Kim                                                 rctx->oaep_labellen,
3687bded2dbSJung-uk Kim                                                 rctx->md, rctx->mgf1md);
369e71b7053SJung-uk Kim     } else {
370b077aed3SPierre Pronchery         ret = RSA_private_decrypt(inlen, in, out, rsa, rctx->pad_mode);
371e71b7053SJung-uk Kim     }
372610a21fdSJung-uk Kim     *outlen = constant_time_select_s(constant_time_msb_s(ret), *outlen, ret);
373610a21fdSJung-uk Kim     ret = constant_time_select_int(constant_time_msb(ret), ret, 1);
3741f13597dSJung-uk Kim     return ret;
3751f13597dSJung-uk Kim }
3761f13597dSJung-uk Kim 
check_padding_md(const EVP_MD * md,int padding)3771f13597dSJung-uk Kim static int check_padding_md(const EVP_MD *md, int padding)
3781f13597dSJung-uk Kim {
379e71b7053SJung-uk Kim     int mdnid;
380e71b7053SJung-uk Kim 
3811f13597dSJung-uk Kim     if (!md)
3821f13597dSJung-uk Kim         return 1;
3831f13597dSJung-uk Kim 
384b077aed3SPierre Pronchery     mdnid = EVP_MD_get_type(md);
385e71b7053SJung-uk Kim 
3866f9291ceSJung-uk Kim     if (padding == RSA_NO_PADDING) {
387b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_PADDING_MODE);
3881f13597dSJung-uk Kim         return 0;
3891f13597dSJung-uk Kim     }
3901f13597dSJung-uk Kim 
3916f9291ceSJung-uk Kim     if (padding == RSA_X931_PADDING) {
392e71b7053SJung-uk Kim         if (RSA_X931_hash_id(mdnid) == -1) {
393b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_X931_DIGEST);
3941f13597dSJung-uk Kim             return 0;
3951f13597dSJung-uk Kim         }
396e71b7053SJung-uk Kim     } else {
397e71b7053SJung-uk Kim         switch(mdnid) {
398e71b7053SJung-uk Kim         /* List of all supported RSA digests */
399e71b7053SJung-uk Kim         case NID_sha1:
400e71b7053SJung-uk Kim         case NID_sha224:
401e71b7053SJung-uk Kim         case NID_sha256:
402e71b7053SJung-uk Kim         case NID_sha384:
403e71b7053SJung-uk Kim         case NID_sha512:
404b077aed3SPierre Pronchery         case NID_sha512_224:
405b077aed3SPierre Pronchery         case NID_sha512_256:
406e71b7053SJung-uk Kim         case NID_md5:
407e71b7053SJung-uk Kim         case NID_md5_sha1:
408e71b7053SJung-uk Kim         case NID_md2:
409e71b7053SJung-uk Kim         case NID_md4:
410e71b7053SJung-uk Kim         case NID_mdc2:
411e71b7053SJung-uk Kim         case NID_ripemd160:
412e71b7053SJung-uk Kim         case NID_sha3_224:
413e71b7053SJung-uk Kim         case NID_sha3_256:
414e71b7053SJung-uk Kim         case NID_sha3_384:
415e71b7053SJung-uk Kim         case NID_sha3_512:
4161f13597dSJung-uk Kim             return 1;
417e71b7053SJung-uk Kim 
418e71b7053SJung-uk Kim         default:
419b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_DIGEST);
420e71b7053SJung-uk Kim             return 0;
421e71b7053SJung-uk Kim 
422e71b7053SJung-uk Kim         }
4231f13597dSJung-uk Kim     }
4241f13597dSJung-uk Kim 
4251f13597dSJung-uk Kim     return 1;
4261f13597dSJung-uk Kim }
4271f13597dSJung-uk Kim 
pkey_rsa_ctrl(EVP_PKEY_CTX * ctx,int type,int p1,void * p2)4281f13597dSJung-uk Kim static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
4291f13597dSJung-uk Kim {
4301f13597dSJung-uk Kim     RSA_PKEY_CTX *rctx = ctx->data;
431e71b7053SJung-uk Kim 
4326f9291ceSJung-uk Kim     switch (type) {
4331f13597dSJung-uk Kim     case EVP_PKEY_CTRL_RSA_PADDING:
4346f9291ceSJung-uk Kim         if ((p1 >= RSA_PKCS1_PADDING) && (p1 <= RSA_PKCS1_PSS_PADDING)) {
4351f13597dSJung-uk Kim             if (!check_padding_md(rctx->md, p1))
4361f13597dSJung-uk Kim                 return 0;
4376f9291ceSJung-uk Kim             if (p1 == RSA_PKCS1_PSS_PADDING) {
4381f13597dSJung-uk Kim                 if (!(ctx->operation &
4391f13597dSJung-uk Kim                       (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY)))
4401f13597dSJung-uk Kim                     goto bad_pad;
4411f13597dSJung-uk Kim                 if (!rctx->md)
4421f13597dSJung-uk Kim                     rctx->md = EVP_sha1();
443e71b7053SJung-uk Kim             } else if (pkey_ctx_is_pss(ctx)) {
444e71b7053SJung-uk Kim                 goto bad_pad;
4451f13597dSJung-uk Kim             }
4466f9291ceSJung-uk Kim             if (p1 == RSA_PKCS1_OAEP_PADDING) {
4471f13597dSJung-uk Kim                 if (!(ctx->operation & EVP_PKEY_OP_TYPE_CRYPT))
4481f13597dSJung-uk Kim                     goto bad_pad;
4491f13597dSJung-uk Kim                 if (!rctx->md)
4501f13597dSJung-uk Kim                     rctx->md = EVP_sha1();
4511f13597dSJung-uk Kim             }
4521f13597dSJung-uk Kim             rctx->pad_mode = p1;
4531f13597dSJung-uk Kim             return 1;
4541f13597dSJung-uk Kim         }
4551f13597dSJung-uk Kim  bad_pad:
456b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_RSA, RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE);
4571f13597dSJung-uk Kim         return -2;
4581f13597dSJung-uk Kim 
4591f13597dSJung-uk Kim     case EVP_PKEY_CTRL_GET_RSA_PADDING:
4601f13597dSJung-uk Kim         *(int *)p2 = rctx->pad_mode;
4611f13597dSJung-uk Kim         return 1;
4621f13597dSJung-uk Kim 
4631f13597dSJung-uk Kim     case EVP_PKEY_CTRL_RSA_PSS_SALTLEN:
4641f13597dSJung-uk Kim     case EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN:
4656f9291ceSJung-uk Kim         if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING) {
466b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_PSS_SALTLEN);
4671f13597dSJung-uk Kim             return -2;
4681f13597dSJung-uk Kim         }
469e71b7053SJung-uk Kim         if (type == EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN) {
4701f13597dSJung-uk Kim             *(int *)p2 = rctx->saltlen;
471e71b7053SJung-uk Kim         } else {
472e71b7053SJung-uk Kim             if (p1 < RSA_PSS_SALTLEN_MAX)
4731f13597dSJung-uk Kim                 return -2;
474e71b7053SJung-uk Kim             if (rsa_pss_restricted(rctx)) {
475e71b7053SJung-uk Kim                 if (p1 == RSA_PSS_SALTLEN_AUTO
476e71b7053SJung-uk Kim                     && ctx->operation == EVP_PKEY_OP_VERIFY) {
477b077aed3SPierre Pronchery                     ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_PSS_SALTLEN);
478e71b7053SJung-uk Kim                     return -2;
479e71b7053SJung-uk Kim                 }
480e71b7053SJung-uk Kim                 if ((p1 == RSA_PSS_SALTLEN_DIGEST
481b077aed3SPierre Pronchery                      && rctx->min_saltlen > EVP_MD_get_size(rctx->md))
482e71b7053SJung-uk Kim                     || (p1 >= 0 && p1 < rctx->min_saltlen)) {
483b077aed3SPierre Pronchery                     ERR_raise(ERR_LIB_RSA, RSA_R_PSS_SALTLEN_TOO_SMALL);
484e71b7053SJung-uk Kim                     return 0;
485e71b7053SJung-uk Kim                 }
486e71b7053SJung-uk Kim             }
4871f13597dSJung-uk Kim             rctx->saltlen = p1;
4881f13597dSJung-uk Kim         }
4891f13597dSJung-uk Kim         return 1;
4901f13597dSJung-uk Kim 
4911f13597dSJung-uk Kim     case EVP_PKEY_CTRL_RSA_KEYGEN_BITS:
492e71b7053SJung-uk Kim         if (p1 < RSA_MIN_MODULUS_BITS) {
493b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_RSA, RSA_R_KEY_SIZE_TOO_SMALL);
4941f13597dSJung-uk Kim             return -2;
4951f13597dSJung-uk Kim         }
4961f13597dSJung-uk Kim         rctx->nbits = p1;
4971f13597dSJung-uk Kim         return 1;
4981f13597dSJung-uk Kim 
4991f13597dSJung-uk Kim     case EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP:
500aeb5019cSJung-uk Kim         if (p2 == NULL || !BN_is_odd((BIGNUM *)p2) || BN_is_one((BIGNUM *)p2)) {
501b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_RSA, RSA_R_BAD_E_VALUE);
5021f13597dSJung-uk Kim             return -2;
503aeb5019cSJung-uk Kim         }
5047bded2dbSJung-uk Kim         BN_free(rctx->pub_exp);
5051f13597dSJung-uk Kim         rctx->pub_exp = p2;
5061f13597dSJung-uk Kim         return 1;
5071f13597dSJung-uk Kim 
508e71b7053SJung-uk Kim     case EVP_PKEY_CTRL_RSA_KEYGEN_PRIMES:
509e71b7053SJung-uk Kim         if (p1 < RSA_DEFAULT_PRIME_NUM || p1 > RSA_MAX_PRIME_NUM) {
510b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_RSA, RSA_R_KEY_PRIME_NUM_INVALID);
511e71b7053SJung-uk Kim             return -2;
512e71b7053SJung-uk Kim         }
513e71b7053SJung-uk Kim         rctx->primes = p1;
514e71b7053SJung-uk Kim         return 1;
515e71b7053SJung-uk Kim 
5167bded2dbSJung-uk Kim     case EVP_PKEY_CTRL_RSA_OAEP_MD:
5177bded2dbSJung-uk Kim     case EVP_PKEY_CTRL_GET_RSA_OAEP_MD:
5187bded2dbSJung-uk Kim         if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
519b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_PADDING_MODE);
5207bded2dbSJung-uk Kim             return -2;
5217bded2dbSJung-uk Kim         }
5227bded2dbSJung-uk Kim         if (type == EVP_PKEY_CTRL_GET_RSA_OAEP_MD)
5237bded2dbSJung-uk Kim             *(const EVP_MD **)p2 = rctx->md;
5247bded2dbSJung-uk Kim         else
5257bded2dbSJung-uk Kim             rctx->md = p2;
5267bded2dbSJung-uk Kim         return 1;
5277bded2dbSJung-uk Kim 
5281f13597dSJung-uk Kim     case EVP_PKEY_CTRL_MD:
5291f13597dSJung-uk Kim         if (!check_padding_md(p2, rctx->pad_mode))
5301f13597dSJung-uk Kim             return 0;
531e71b7053SJung-uk Kim         if (rsa_pss_restricted(rctx)) {
532b077aed3SPierre Pronchery             if (EVP_MD_get_type(rctx->md) == EVP_MD_get_type(p2))
533e71b7053SJung-uk Kim                 return 1;
534b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_RSA, RSA_R_DIGEST_NOT_ALLOWED);
535e71b7053SJung-uk Kim             return 0;
536e71b7053SJung-uk Kim         }
5371f13597dSJung-uk Kim         rctx->md = p2;
5381f13597dSJung-uk Kim         return 1;
5391f13597dSJung-uk Kim 
5407bded2dbSJung-uk Kim     case EVP_PKEY_CTRL_GET_MD:
5417bded2dbSJung-uk Kim         *(const EVP_MD **)p2 = rctx->md;
5427bded2dbSJung-uk Kim         return 1;
5437bded2dbSJung-uk Kim 
5441f13597dSJung-uk Kim     case EVP_PKEY_CTRL_RSA_MGF1_MD:
5451f13597dSJung-uk Kim     case EVP_PKEY_CTRL_GET_RSA_MGF1_MD:
5467bded2dbSJung-uk Kim         if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING
5477bded2dbSJung-uk Kim             && rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
548b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_MGF1_MD);
5491f13597dSJung-uk Kim             return -2;
5501f13597dSJung-uk Kim         }
5516f9291ceSJung-uk Kim         if (type == EVP_PKEY_CTRL_GET_RSA_MGF1_MD) {
5521f13597dSJung-uk Kim             if (rctx->mgf1md)
5531f13597dSJung-uk Kim                 *(const EVP_MD **)p2 = rctx->mgf1md;
5541f13597dSJung-uk Kim             else
5551f13597dSJung-uk Kim                 *(const EVP_MD **)p2 = rctx->md;
556e71b7053SJung-uk Kim         } else {
557e71b7053SJung-uk Kim             if (rsa_pss_restricted(rctx)) {
558b077aed3SPierre Pronchery                 if (EVP_MD_get_type(rctx->mgf1md) == EVP_MD_get_type(p2))
559e71b7053SJung-uk Kim                     return 1;
560b077aed3SPierre Pronchery                 ERR_raise(ERR_LIB_RSA, RSA_R_MGF1_DIGEST_NOT_ALLOWED);
561e71b7053SJung-uk Kim                 return 0;
562e71b7053SJung-uk Kim             }
5631f13597dSJung-uk Kim             rctx->mgf1md = p2;
564e71b7053SJung-uk Kim         }
5651f13597dSJung-uk Kim         return 1;
5661f13597dSJung-uk Kim 
5677bded2dbSJung-uk Kim     case EVP_PKEY_CTRL_RSA_OAEP_LABEL:
5687bded2dbSJung-uk Kim         if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
569b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_PADDING_MODE);
5707bded2dbSJung-uk Kim             return -2;
5717bded2dbSJung-uk Kim         }
5727bded2dbSJung-uk Kim         OPENSSL_free(rctx->oaep_label);
5737bded2dbSJung-uk Kim         if (p2 && p1 > 0) {
5747bded2dbSJung-uk Kim             rctx->oaep_label = p2;
5757bded2dbSJung-uk Kim             rctx->oaep_labellen = p1;
5767bded2dbSJung-uk Kim         } else {
5777bded2dbSJung-uk Kim             rctx->oaep_label = NULL;
5787bded2dbSJung-uk Kim             rctx->oaep_labellen = 0;
5797bded2dbSJung-uk Kim         }
5807bded2dbSJung-uk Kim         return 1;
5817bded2dbSJung-uk Kim 
5827bded2dbSJung-uk Kim     case EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL:
5837bded2dbSJung-uk Kim         if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
584b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_PADDING_MODE);
5857bded2dbSJung-uk Kim             return -2;
5867bded2dbSJung-uk Kim         }
587*aa795734SPierre Pronchery         if (p2 == NULL) {
588*aa795734SPierre Pronchery             ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
589*aa795734SPierre Pronchery             return 0;
590*aa795734SPierre Pronchery         }
5917bded2dbSJung-uk Kim         *(unsigned char **)p2 = rctx->oaep_label;
5927bded2dbSJung-uk Kim         return rctx->oaep_labellen;
5937bded2dbSJung-uk Kim 
5941f13597dSJung-uk Kim     case EVP_PKEY_CTRL_DIGESTINIT:
595e71b7053SJung-uk Kim     case EVP_PKEY_CTRL_PKCS7_SIGN:
596e71b7053SJung-uk Kim #ifndef OPENSSL_NO_CMS
597e71b7053SJung-uk Kim     case EVP_PKEY_CTRL_CMS_SIGN:
598e71b7053SJung-uk Kim #endif
599e71b7053SJung-uk Kim     return 1;
600e71b7053SJung-uk Kim 
6011f13597dSJung-uk Kim     case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
6021f13597dSJung-uk Kim     case EVP_PKEY_CTRL_PKCS7_DECRYPT:
6031f13597dSJung-uk Kim #ifndef OPENSSL_NO_CMS
6041f13597dSJung-uk Kim     case EVP_PKEY_CTRL_CMS_DECRYPT:
6051f13597dSJung-uk Kim     case EVP_PKEY_CTRL_CMS_ENCRYPT:
6061f13597dSJung-uk Kim #endif
607e71b7053SJung-uk Kim     if (!pkey_ctx_is_pss(ctx))
608e71b7053SJung-uk Kim         return 1;
609e71b7053SJung-uk Kim     /* fall through */
6101f13597dSJung-uk Kim     case EVP_PKEY_CTRL_PEER_KEY:
611b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_RSA, RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
6121f13597dSJung-uk Kim         return -2;
6131f13597dSJung-uk Kim 
6141f13597dSJung-uk Kim     default:
6151f13597dSJung-uk Kim         return -2;
6161f13597dSJung-uk Kim 
6171f13597dSJung-uk Kim     }
6181f13597dSJung-uk Kim }
6191f13597dSJung-uk Kim 
pkey_rsa_ctrl_str(EVP_PKEY_CTX * ctx,const char * type,const char * value)6201f13597dSJung-uk Kim static int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx,
6211f13597dSJung-uk Kim                              const char *type, const char *value)
6221f13597dSJung-uk Kim {
623e71b7053SJung-uk Kim     if (value == NULL) {
624b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_RSA, RSA_R_VALUE_MISSING);
6251f13597dSJung-uk Kim         return 0;
6261f13597dSJung-uk Kim     }
627e71b7053SJung-uk Kim     if (strcmp(type, "rsa_padding_mode") == 0) {
6281f13597dSJung-uk Kim         int pm;
629e71b7053SJung-uk Kim 
630e71b7053SJung-uk Kim         if (strcmp(value, "pkcs1") == 0) {
6311f13597dSJung-uk Kim             pm = RSA_PKCS1_PADDING;
632e71b7053SJung-uk Kim         } else if (strcmp(value, "none") == 0) {
6331f13597dSJung-uk Kim             pm = RSA_NO_PADDING;
634e71b7053SJung-uk Kim         } else if (strcmp(value, "oeap") == 0) {
6351f13597dSJung-uk Kim             pm = RSA_PKCS1_OAEP_PADDING;
636e71b7053SJung-uk Kim         } else if (strcmp(value, "oaep") == 0) {
637de78d5d8SJung-uk Kim             pm = RSA_PKCS1_OAEP_PADDING;
638e71b7053SJung-uk Kim         } else if (strcmp(value, "x931") == 0) {
6391f13597dSJung-uk Kim             pm = RSA_X931_PADDING;
640e71b7053SJung-uk Kim         } else if (strcmp(value, "pss") == 0) {
6411f13597dSJung-uk Kim             pm = RSA_PKCS1_PSS_PADDING;
642e71b7053SJung-uk Kim         } else {
643b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_RSA, RSA_R_UNKNOWN_PADDING_TYPE);
6441f13597dSJung-uk Kim             return -2;
6451f13597dSJung-uk Kim         }
6461f13597dSJung-uk Kim         return EVP_PKEY_CTX_set_rsa_padding(ctx, pm);
6471f13597dSJung-uk Kim     }
6481f13597dSJung-uk Kim 
649e71b7053SJung-uk Kim     if (strcmp(type, "rsa_pss_saltlen") == 0) {
6501f13597dSJung-uk Kim         int saltlen;
651e71b7053SJung-uk Kim 
652e71b7053SJung-uk Kim         if (!strcmp(value, "digest"))
653e71b7053SJung-uk Kim             saltlen = RSA_PSS_SALTLEN_DIGEST;
654e71b7053SJung-uk Kim         else if (!strcmp(value, "max"))
655e71b7053SJung-uk Kim             saltlen = RSA_PSS_SALTLEN_MAX;
656e71b7053SJung-uk Kim         else if (!strcmp(value, "auto"))
657e71b7053SJung-uk Kim             saltlen = RSA_PSS_SALTLEN_AUTO;
658e71b7053SJung-uk Kim         else
6591f13597dSJung-uk Kim             saltlen = atoi(value);
6601f13597dSJung-uk Kim         return EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, saltlen);
6611f13597dSJung-uk Kim     }
6621f13597dSJung-uk Kim 
663e71b7053SJung-uk Kim     if (strcmp(type, "rsa_keygen_bits") == 0) {
664e71b7053SJung-uk Kim         int nbits = atoi(value);
665e71b7053SJung-uk Kim 
6661f13597dSJung-uk Kim         return EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, nbits);
6671f13597dSJung-uk Kim     }
6681f13597dSJung-uk Kim 
669e71b7053SJung-uk Kim     if (strcmp(type, "rsa_keygen_pubexp") == 0) {
6701f13597dSJung-uk Kim         int ret;
671e71b7053SJung-uk Kim 
6721f13597dSJung-uk Kim         BIGNUM *pubexp = NULL;
6731f13597dSJung-uk Kim         if (!BN_asc2bn(&pubexp, value))
6741f13597dSJung-uk Kim             return 0;
675b077aed3SPierre Pronchery         ret = EVP_PKEY_CTX_set1_rsa_keygen_pubexp(ctx, pubexp);
6761f13597dSJung-uk Kim         BN_free(pubexp);
6771f13597dSJung-uk Kim         return ret;
6781f13597dSJung-uk Kim     }
6791f13597dSJung-uk Kim 
680e71b7053SJung-uk Kim     if (strcmp(type, "rsa_keygen_primes") == 0) {
681e71b7053SJung-uk Kim         int nprimes = atoi(value);
682e71b7053SJung-uk Kim 
683e71b7053SJung-uk Kim         return EVP_PKEY_CTX_set_rsa_keygen_primes(ctx, nprimes);
6847bded2dbSJung-uk Kim     }
6857bded2dbSJung-uk Kim 
686e71b7053SJung-uk Kim     if (strcmp(type, "rsa_mgf1_md") == 0)
687e71b7053SJung-uk Kim         return EVP_PKEY_CTX_md(ctx,
688e71b7053SJung-uk Kim                                EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT,
689e71b7053SJung-uk Kim                                EVP_PKEY_CTRL_RSA_MGF1_MD, value);
690e71b7053SJung-uk Kim 
691e71b7053SJung-uk Kim     if (pkey_ctx_is_pss(ctx)) {
692e71b7053SJung-uk Kim 
693e71b7053SJung-uk Kim         if (strcmp(type, "rsa_pss_keygen_mgf1_md") == 0)
694e71b7053SJung-uk Kim             return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_KEYGEN,
695e71b7053SJung-uk Kim                                    EVP_PKEY_CTRL_RSA_MGF1_MD, value);
696e71b7053SJung-uk Kim 
697e71b7053SJung-uk Kim         if (strcmp(type, "rsa_pss_keygen_md") == 0)
698e71b7053SJung-uk Kim             return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_KEYGEN,
699e71b7053SJung-uk Kim                                    EVP_PKEY_CTRL_MD, value);
700e71b7053SJung-uk Kim 
701e71b7053SJung-uk Kim         if (strcmp(type, "rsa_pss_keygen_saltlen") == 0) {
702e71b7053SJung-uk Kim             int saltlen = atoi(value);
703e71b7053SJung-uk Kim 
704e71b7053SJung-uk Kim             return EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen(ctx, saltlen);
7057bded2dbSJung-uk Kim         }
7067bded2dbSJung-uk Kim     }
707e71b7053SJung-uk Kim 
708e71b7053SJung-uk Kim     if (strcmp(type, "rsa_oaep_md") == 0)
709e71b7053SJung-uk Kim         return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_TYPE_CRYPT,
710e71b7053SJung-uk Kim                                EVP_PKEY_CTRL_RSA_OAEP_MD, value);
711e71b7053SJung-uk Kim 
712e71b7053SJung-uk Kim     if (strcmp(type, "rsa_oaep_label") == 0) {
7137bded2dbSJung-uk Kim         unsigned char *lab;
7147bded2dbSJung-uk Kim         long lablen;
7157bded2dbSJung-uk Kim         int ret;
716e71b7053SJung-uk Kim 
717e71b7053SJung-uk Kim         lab = OPENSSL_hexstr2buf(value, &lablen);
7187bded2dbSJung-uk Kim         if (!lab)
7197bded2dbSJung-uk Kim             return 0;
7207bded2dbSJung-uk Kim         ret = EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, lab, lablen);
7217bded2dbSJung-uk Kim         if (ret <= 0)
7227bded2dbSJung-uk Kim             OPENSSL_free(lab);
7237bded2dbSJung-uk Kim         return ret;
7247bded2dbSJung-uk Kim     }
7257bded2dbSJung-uk Kim 
7261f13597dSJung-uk Kim     return -2;
7271f13597dSJung-uk Kim }
7281f13597dSJung-uk Kim 
729e71b7053SJung-uk Kim /* Set PSS parameters when generating a key, if necessary */
rsa_set_pss_param(RSA * rsa,EVP_PKEY_CTX * ctx)730e71b7053SJung-uk Kim static int rsa_set_pss_param(RSA *rsa, EVP_PKEY_CTX *ctx)
731e71b7053SJung-uk Kim {
732e71b7053SJung-uk Kim     RSA_PKEY_CTX *rctx = ctx->data;
733e71b7053SJung-uk Kim 
734e71b7053SJung-uk Kim     if (!pkey_ctx_is_pss(ctx))
735e71b7053SJung-uk Kim         return 1;
736e71b7053SJung-uk Kim     /* If all parameters are default values don't set pss */
737e71b7053SJung-uk Kim     if (rctx->md == NULL && rctx->mgf1md == NULL && rctx->saltlen == -2)
738e71b7053SJung-uk Kim         return 1;
739b077aed3SPierre Pronchery     rsa->pss = ossl_rsa_pss_params_create(rctx->md, rctx->mgf1md,
740b077aed3SPierre Pronchery                                           rctx->saltlen == -2
741b077aed3SPierre Pronchery                                           ? 0 : rctx->saltlen);
742e71b7053SJung-uk Kim     if (rsa->pss == NULL)
743e71b7053SJung-uk Kim         return 0;
744e71b7053SJung-uk Kim     return 1;
745e71b7053SJung-uk Kim }
746e71b7053SJung-uk Kim 
pkey_rsa_keygen(EVP_PKEY_CTX * ctx,EVP_PKEY * pkey)7471f13597dSJung-uk Kim static int pkey_rsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
7481f13597dSJung-uk Kim {
7491f13597dSJung-uk Kim     RSA *rsa = NULL;
7501f13597dSJung-uk Kim     RSA_PKEY_CTX *rctx = ctx->data;
751e71b7053SJung-uk Kim     BN_GENCB *pcb;
7521f13597dSJung-uk Kim     int ret;
753e71b7053SJung-uk Kim 
754e71b7053SJung-uk Kim     if (rctx->pub_exp == NULL) {
7551f13597dSJung-uk Kim         rctx->pub_exp = BN_new();
756e71b7053SJung-uk Kim         if (rctx->pub_exp == NULL || !BN_set_word(rctx->pub_exp, RSA_F4))
7571f13597dSJung-uk Kim             return 0;
7581f13597dSJung-uk Kim     }
7591f13597dSJung-uk Kim     rsa = RSA_new();
760e71b7053SJung-uk Kim     if (rsa == NULL)
7611f13597dSJung-uk Kim         return 0;
7626f9291ceSJung-uk Kim     if (ctx->pkey_gencb) {
763e71b7053SJung-uk Kim         pcb = BN_GENCB_new();
764e71b7053SJung-uk Kim         if (pcb == NULL) {
765e71b7053SJung-uk Kim             RSA_free(rsa);
766e71b7053SJung-uk Kim             return 0;
767e71b7053SJung-uk Kim         }
7681f13597dSJung-uk Kim         evp_pkey_set_cb_translate(pcb, ctx);
769e71b7053SJung-uk Kim     } else {
7701f13597dSJung-uk Kim         pcb = NULL;
771e71b7053SJung-uk Kim     }
772e71b7053SJung-uk Kim     ret = RSA_generate_multi_prime_key(rsa, rctx->nbits, rctx->primes,
773e71b7053SJung-uk Kim                                        rctx->pub_exp, pcb);
774e71b7053SJung-uk Kim     BN_GENCB_free(pcb);
775e71b7053SJung-uk Kim     if (ret > 0 && !rsa_set_pss_param(rsa, ctx)) {
776e71b7053SJung-uk Kim         RSA_free(rsa);
777e71b7053SJung-uk Kim         return 0;
778e71b7053SJung-uk Kim     }
7791f13597dSJung-uk Kim     if (ret > 0)
780e71b7053SJung-uk Kim         EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, rsa);
7811f13597dSJung-uk Kim     else
7821f13597dSJung-uk Kim         RSA_free(rsa);
7831f13597dSJung-uk Kim     return ret;
7841f13597dSJung-uk Kim }
7851f13597dSJung-uk Kim 
786b077aed3SPierre Pronchery static const EVP_PKEY_METHOD rsa_pkey_meth = {
7871f13597dSJung-uk Kim     EVP_PKEY_RSA,
7881f13597dSJung-uk Kim     EVP_PKEY_FLAG_AUTOARGLEN,
7891f13597dSJung-uk Kim     pkey_rsa_init,
7901f13597dSJung-uk Kim     pkey_rsa_copy,
7911f13597dSJung-uk Kim     pkey_rsa_cleanup,
7921f13597dSJung-uk Kim 
7931f13597dSJung-uk Kim     0, 0,
7941f13597dSJung-uk Kim 
7951f13597dSJung-uk Kim     0,
7961f13597dSJung-uk Kim     pkey_rsa_keygen,
7971f13597dSJung-uk Kim 
7981f13597dSJung-uk Kim     0,
7991f13597dSJung-uk Kim     pkey_rsa_sign,
8001f13597dSJung-uk Kim 
8011f13597dSJung-uk Kim     0,
8021f13597dSJung-uk Kim     pkey_rsa_verify,
8031f13597dSJung-uk Kim 
8041f13597dSJung-uk Kim     0,
8051f13597dSJung-uk Kim     pkey_rsa_verifyrecover,
8061f13597dSJung-uk Kim 
8071f13597dSJung-uk Kim     0, 0, 0, 0,
8081f13597dSJung-uk Kim 
8091f13597dSJung-uk Kim     0,
8101f13597dSJung-uk Kim     pkey_rsa_encrypt,
8111f13597dSJung-uk Kim 
8121f13597dSJung-uk Kim     0,
8131f13597dSJung-uk Kim     pkey_rsa_decrypt,
8141f13597dSJung-uk Kim 
8151f13597dSJung-uk Kim     0, 0,
8161f13597dSJung-uk Kim 
8171f13597dSJung-uk Kim     pkey_rsa_ctrl,
8181f13597dSJung-uk Kim     pkey_rsa_ctrl_str
8191f13597dSJung-uk Kim };
820e71b7053SJung-uk Kim 
ossl_rsa_pkey_method(void)821b077aed3SPierre Pronchery const EVP_PKEY_METHOD *ossl_rsa_pkey_method(void)
822b077aed3SPierre Pronchery {
823b077aed3SPierre Pronchery     return &rsa_pkey_meth;
824b077aed3SPierre Pronchery }
825b077aed3SPierre Pronchery 
826e71b7053SJung-uk Kim /*
827e71b7053SJung-uk Kim  * Called for PSS sign or verify initialisation: checks PSS parameter
828e71b7053SJung-uk Kim  * sanity and sets any restrictions on key usage.
829e71b7053SJung-uk Kim  */
830e71b7053SJung-uk Kim 
pkey_pss_init(EVP_PKEY_CTX * ctx)831e71b7053SJung-uk Kim static int pkey_pss_init(EVP_PKEY_CTX *ctx)
832e71b7053SJung-uk Kim {
833b077aed3SPierre Pronchery     const RSA *rsa;
834e71b7053SJung-uk Kim     RSA_PKEY_CTX *rctx = ctx->data;
835e71b7053SJung-uk Kim     const EVP_MD *md;
836e71b7053SJung-uk Kim     const EVP_MD *mgf1md;
837e71b7053SJung-uk Kim     int min_saltlen, max_saltlen;
838e71b7053SJung-uk Kim 
839e71b7053SJung-uk Kim     /* Should never happen */
840e71b7053SJung-uk Kim     if (!pkey_ctx_is_pss(ctx))
841e71b7053SJung-uk Kim         return 0;
842b077aed3SPierre Pronchery     rsa = EVP_PKEY_get0_RSA(ctx->pkey);
843e71b7053SJung-uk Kim     /* If no restrictions just return */
844e71b7053SJung-uk Kim     if (rsa->pss == NULL)
845e71b7053SJung-uk Kim         return 1;
846e71b7053SJung-uk Kim     /* Get and check parameters */
847b077aed3SPierre Pronchery     if (!ossl_rsa_pss_get_param(rsa->pss, &md, &mgf1md, &min_saltlen))
848e71b7053SJung-uk Kim         return 0;
849e71b7053SJung-uk Kim 
850e71b7053SJung-uk Kim     /* See if minimum salt length exceeds maximum possible */
851b077aed3SPierre Pronchery     max_saltlen = RSA_size(rsa) - EVP_MD_get_size(md);
852e71b7053SJung-uk Kim     if ((RSA_bits(rsa) & 0x7) == 1)
853e71b7053SJung-uk Kim         max_saltlen--;
854e71b7053SJung-uk Kim     if (min_saltlen > max_saltlen) {
855b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_SALT_LENGTH);
856e71b7053SJung-uk Kim         return 0;
857e71b7053SJung-uk Kim     }
858e71b7053SJung-uk Kim 
859e71b7053SJung-uk Kim     rctx->min_saltlen = min_saltlen;
860e71b7053SJung-uk Kim 
861e71b7053SJung-uk Kim     /*
862e71b7053SJung-uk Kim      * Set PSS restrictions as defaults: we can then block any attempt to
863e71b7053SJung-uk Kim      * use invalid values in pkey_rsa_ctrl
864e71b7053SJung-uk Kim      */
865e71b7053SJung-uk Kim 
866e71b7053SJung-uk Kim     rctx->md = md;
867e71b7053SJung-uk Kim     rctx->mgf1md = mgf1md;
868e71b7053SJung-uk Kim     rctx->saltlen = min_saltlen;
869e71b7053SJung-uk Kim 
870e71b7053SJung-uk Kim     return 1;
871e71b7053SJung-uk Kim }
872e71b7053SJung-uk Kim 
873b077aed3SPierre Pronchery static const EVP_PKEY_METHOD rsa_pss_pkey_meth = {
874e71b7053SJung-uk Kim     EVP_PKEY_RSA_PSS,
875e71b7053SJung-uk Kim     EVP_PKEY_FLAG_AUTOARGLEN,
876e71b7053SJung-uk Kim     pkey_rsa_init,
877e71b7053SJung-uk Kim     pkey_rsa_copy,
878e71b7053SJung-uk Kim     pkey_rsa_cleanup,
879e71b7053SJung-uk Kim 
880e71b7053SJung-uk Kim     0, 0,
881e71b7053SJung-uk Kim 
882e71b7053SJung-uk Kim     0,
883e71b7053SJung-uk Kim     pkey_rsa_keygen,
884e71b7053SJung-uk Kim 
885e71b7053SJung-uk Kim     pkey_pss_init,
886e71b7053SJung-uk Kim     pkey_rsa_sign,
887e71b7053SJung-uk Kim 
888e71b7053SJung-uk Kim     pkey_pss_init,
889e71b7053SJung-uk Kim     pkey_rsa_verify,
890e71b7053SJung-uk Kim 
891e71b7053SJung-uk Kim     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
892e71b7053SJung-uk Kim 
893e71b7053SJung-uk Kim     pkey_rsa_ctrl,
894e71b7053SJung-uk Kim     pkey_rsa_ctrl_str
895e71b7053SJung-uk Kim };
896b077aed3SPierre Pronchery 
ossl_rsa_pss_pkey_method(void)897b077aed3SPierre Pronchery const EVP_PKEY_METHOD *ossl_rsa_pss_pkey_method(void)
898b077aed3SPierre Pronchery {
899b077aed3SPierre Pronchery     return &rsa_pss_pkey_meth;
900b077aed3SPierre Pronchery }
901