xref: /freebsd-src/crypto/openssl/providers/implementations/signature/rsa_sig.c (revision e0c4386e7e71d93b0edc0c8fa156263fc4a8b0b6)
1b077aed3SPierre Pronchery /*
2b077aed3SPierre Pronchery  * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
3b077aed3SPierre Pronchery  *
4b077aed3SPierre Pronchery  * Licensed under the Apache License 2.0 (the "License").  You may not use
5b077aed3SPierre Pronchery  * this file except in compliance with the License.  You can obtain a copy
6b077aed3SPierre Pronchery  * in the file LICENSE in the source distribution or at
7b077aed3SPierre Pronchery  * https://www.openssl.org/source/license.html
8b077aed3SPierre Pronchery  */
9b077aed3SPierre Pronchery 
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 
16b077aed3SPierre Pronchery #include <string.h>
17b077aed3SPierre Pronchery #include <openssl/crypto.h>
18b077aed3SPierre Pronchery #include <openssl/core_dispatch.h>
19b077aed3SPierre Pronchery #include <openssl/core_names.h>
20b077aed3SPierre Pronchery #include <openssl/err.h>
21b077aed3SPierre Pronchery #include <openssl/rsa.h>
22b077aed3SPierre Pronchery #include <openssl/params.h>
23b077aed3SPierre Pronchery #include <openssl/evp.h>
24b077aed3SPierre Pronchery #include <openssl/proverr.h>
25b077aed3SPierre Pronchery #include "internal/cryptlib.h"
26b077aed3SPierre Pronchery #include "internal/nelem.h"
27b077aed3SPierre Pronchery #include "internal/sizes.h"
28b077aed3SPierre Pronchery #include "crypto/rsa.h"
29b077aed3SPierre Pronchery #include "prov/providercommon.h"
30b077aed3SPierre Pronchery #include "prov/implementations.h"
31b077aed3SPierre Pronchery #include "prov/provider_ctx.h"
32b077aed3SPierre Pronchery #include "prov/der_rsa.h"
33b077aed3SPierre Pronchery #include "prov/securitycheck.h"
34b077aed3SPierre Pronchery 
35b077aed3SPierre Pronchery #define RSA_DEFAULT_DIGEST_NAME OSSL_DIGEST_NAME_SHA1
36b077aed3SPierre Pronchery 
37b077aed3SPierre Pronchery static OSSL_FUNC_signature_newctx_fn rsa_newctx;
38b077aed3SPierre Pronchery static OSSL_FUNC_signature_sign_init_fn rsa_sign_init;
39b077aed3SPierre Pronchery static OSSL_FUNC_signature_verify_init_fn rsa_verify_init;
40b077aed3SPierre Pronchery static OSSL_FUNC_signature_verify_recover_init_fn rsa_verify_recover_init;
41b077aed3SPierre Pronchery static OSSL_FUNC_signature_sign_fn rsa_sign;
42b077aed3SPierre Pronchery static OSSL_FUNC_signature_verify_fn rsa_verify;
43b077aed3SPierre Pronchery static OSSL_FUNC_signature_verify_recover_fn rsa_verify_recover;
44b077aed3SPierre Pronchery static OSSL_FUNC_signature_digest_sign_init_fn rsa_digest_sign_init;
45b077aed3SPierre Pronchery static OSSL_FUNC_signature_digest_sign_update_fn rsa_digest_signverify_update;
46b077aed3SPierre Pronchery static OSSL_FUNC_signature_digest_sign_final_fn rsa_digest_sign_final;
47b077aed3SPierre Pronchery static OSSL_FUNC_signature_digest_verify_init_fn rsa_digest_verify_init;
48b077aed3SPierre Pronchery static OSSL_FUNC_signature_digest_verify_update_fn rsa_digest_signverify_update;
49b077aed3SPierre Pronchery static OSSL_FUNC_signature_digest_verify_final_fn rsa_digest_verify_final;
50b077aed3SPierre Pronchery static OSSL_FUNC_signature_freectx_fn rsa_freectx;
51b077aed3SPierre Pronchery static OSSL_FUNC_signature_dupctx_fn rsa_dupctx;
52b077aed3SPierre Pronchery static OSSL_FUNC_signature_get_ctx_params_fn rsa_get_ctx_params;
53b077aed3SPierre Pronchery static OSSL_FUNC_signature_gettable_ctx_params_fn rsa_gettable_ctx_params;
54b077aed3SPierre Pronchery static OSSL_FUNC_signature_set_ctx_params_fn rsa_set_ctx_params;
55b077aed3SPierre Pronchery static OSSL_FUNC_signature_settable_ctx_params_fn rsa_settable_ctx_params;
56b077aed3SPierre Pronchery static OSSL_FUNC_signature_get_ctx_md_params_fn rsa_get_ctx_md_params;
57b077aed3SPierre Pronchery static OSSL_FUNC_signature_gettable_ctx_md_params_fn rsa_gettable_ctx_md_params;
58b077aed3SPierre Pronchery static OSSL_FUNC_signature_set_ctx_md_params_fn rsa_set_ctx_md_params;
59b077aed3SPierre Pronchery static OSSL_FUNC_signature_settable_ctx_md_params_fn rsa_settable_ctx_md_params;
60b077aed3SPierre Pronchery 
61b077aed3SPierre Pronchery static OSSL_ITEM padding_item[] = {
62b077aed3SPierre Pronchery     { RSA_PKCS1_PADDING,        OSSL_PKEY_RSA_PAD_MODE_PKCSV15 },
63b077aed3SPierre Pronchery     { RSA_NO_PADDING,           OSSL_PKEY_RSA_PAD_MODE_NONE },
64b077aed3SPierre Pronchery     { RSA_X931_PADDING,         OSSL_PKEY_RSA_PAD_MODE_X931 },
65b077aed3SPierre Pronchery     { RSA_PKCS1_PSS_PADDING,    OSSL_PKEY_RSA_PAD_MODE_PSS },
66b077aed3SPierre Pronchery     { 0,                        NULL     }
67b077aed3SPierre Pronchery };
68b077aed3SPierre Pronchery 
69b077aed3SPierre Pronchery /*
70b077aed3SPierre Pronchery  * What's passed as an actual key is defined by the KEYMGMT interface.
71b077aed3SPierre Pronchery  * We happen to know that our KEYMGMT simply passes RSA structures, so
72b077aed3SPierre Pronchery  * we use that here too.
73b077aed3SPierre Pronchery  */
74b077aed3SPierre Pronchery 
75b077aed3SPierre Pronchery typedef struct {
76b077aed3SPierre Pronchery     OSSL_LIB_CTX *libctx;
77b077aed3SPierre Pronchery     char *propq;
78b077aed3SPierre Pronchery     RSA *rsa;
79b077aed3SPierre Pronchery     int operation;
80b077aed3SPierre Pronchery 
81b077aed3SPierre Pronchery     /*
82b077aed3SPierre Pronchery      * Flag to determine if the hash function can be changed (1) or not (0)
83b077aed3SPierre Pronchery      * Because it's dangerous to change during a DigestSign or DigestVerify
84b077aed3SPierre Pronchery      * operation, this flag is cleared by their Init function, and set again
85b077aed3SPierre Pronchery      * by their Final function.
86b077aed3SPierre Pronchery      */
87b077aed3SPierre Pronchery     unsigned int flag_allow_md : 1;
88b077aed3SPierre Pronchery     unsigned int mgf1_md_set : 1;
89b077aed3SPierre Pronchery 
90b077aed3SPierre Pronchery     /* main digest */
91b077aed3SPierre Pronchery     EVP_MD *md;
92b077aed3SPierre Pronchery     EVP_MD_CTX *mdctx;
93b077aed3SPierre Pronchery     int mdnid;
94b077aed3SPierre Pronchery     char mdname[OSSL_MAX_NAME_SIZE]; /* Purely informational */
95b077aed3SPierre Pronchery 
96b077aed3SPierre Pronchery     /* RSA padding mode */
97b077aed3SPierre Pronchery     int pad_mode;
98b077aed3SPierre Pronchery     /* message digest for MGF1 */
99b077aed3SPierre Pronchery     EVP_MD *mgf1_md;
100b077aed3SPierre Pronchery     int mgf1_mdnid;
101b077aed3SPierre Pronchery     char mgf1_mdname[OSSL_MAX_NAME_SIZE]; /* Purely informational */
102b077aed3SPierre Pronchery     /* PSS salt length */
103b077aed3SPierre Pronchery     int saltlen;
104b077aed3SPierre Pronchery     /* Minimum salt length or -1 if no PSS parameter restriction */
105b077aed3SPierre Pronchery     int min_saltlen;
106b077aed3SPierre Pronchery 
107b077aed3SPierre Pronchery     /* Temp buffer */
108b077aed3SPierre Pronchery     unsigned char *tbuf;
109b077aed3SPierre Pronchery 
110b077aed3SPierre Pronchery } PROV_RSA_CTX;
111b077aed3SPierre Pronchery 
112b077aed3SPierre Pronchery /* True if PSS parameters are restricted */
113b077aed3SPierre Pronchery #define rsa_pss_restricted(prsactx) (prsactx->min_saltlen != -1)
114b077aed3SPierre Pronchery 
rsa_get_md_size(const PROV_RSA_CTX * prsactx)115b077aed3SPierre Pronchery static size_t rsa_get_md_size(const PROV_RSA_CTX *prsactx)
116b077aed3SPierre Pronchery {
117b077aed3SPierre Pronchery     if (prsactx->md != NULL)
118b077aed3SPierre Pronchery         return EVP_MD_get_size(prsactx->md);
119b077aed3SPierre Pronchery     return 0;
120b077aed3SPierre Pronchery }
121b077aed3SPierre Pronchery 
rsa_check_padding(const PROV_RSA_CTX * prsactx,const char * mdname,const char * mgf1_mdname,int mdnid)122b077aed3SPierre Pronchery static int rsa_check_padding(const PROV_RSA_CTX *prsactx,
123b077aed3SPierre Pronchery                              const char *mdname, const char *mgf1_mdname,
124b077aed3SPierre Pronchery                              int mdnid)
125b077aed3SPierre Pronchery {
126b077aed3SPierre Pronchery     switch(prsactx->pad_mode) {
127b077aed3SPierre Pronchery         case RSA_NO_PADDING:
128b077aed3SPierre Pronchery             if (mdname != NULL || mdnid != NID_undef) {
129b077aed3SPierre Pronchery                 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE);
130b077aed3SPierre Pronchery                 return 0;
131b077aed3SPierre Pronchery             }
132b077aed3SPierre Pronchery             break;
133b077aed3SPierre Pronchery         case RSA_X931_PADDING:
134b077aed3SPierre Pronchery             if (RSA_X931_hash_id(mdnid) == -1) {
135b077aed3SPierre Pronchery                 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_X931_DIGEST);
136b077aed3SPierre Pronchery                 return 0;
137b077aed3SPierre Pronchery             }
138b077aed3SPierre Pronchery             break;
139b077aed3SPierre Pronchery         case RSA_PKCS1_PSS_PADDING:
140b077aed3SPierre Pronchery             if (rsa_pss_restricted(prsactx))
141b077aed3SPierre Pronchery                 if ((mdname != NULL && !EVP_MD_is_a(prsactx->md, mdname))
142b077aed3SPierre Pronchery                     || (mgf1_mdname != NULL
143b077aed3SPierre Pronchery                         && !EVP_MD_is_a(prsactx->mgf1_md, mgf1_mdname))) {
144b077aed3SPierre Pronchery                     ERR_raise(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED);
145b077aed3SPierre Pronchery                     return 0;
146b077aed3SPierre Pronchery                 }
147b077aed3SPierre Pronchery             break;
148b077aed3SPierre Pronchery         default:
149b077aed3SPierre Pronchery             break;
150b077aed3SPierre Pronchery     }
151b077aed3SPierre Pronchery 
152b077aed3SPierre Pronchery     return 1;
153b077aed3SPierre Pronchery }
154b077aed3SPierre Pronchery 
rsa_check_parameters(PROV_RSA_CTX * prsactx,int min_saltlen)155b077aed3SPierre Pronchery static int rsa_check_parameters(PROV_RSA_CTX *prsactx, int min_saltlen)
156b077aed3SPierre Pronchery {
157b077aed3SPierre Pronchery     if (prsactx->pad_mode == RSA_PKCS1_PSS_PADDING) {
158b077aed3SPierre Pronchery         int max_saltlen;
159b077aed3SPierre Pronchery 
160b077aed3SPierre Pronchery         /* See if minimum salt length exceeds maximum possible */
161b077aed3SPierre Pronchery         max_saltlen = RSA_size(prsactx->rsa) - EVP_MD_get_size(prsactx->md);
162b077aed3SPierre Pronchery         if ((RSA_bits(prsactx->rsa) & 0x7) == 1)
163b077aed3SPierre Pronchery             max_saltlen--;
164b077aed3SPierre Pronchery         if (min_saltlen < 0 || min_saltlen > max_saltlen) {
165b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH);
166b077aed3SPierre Pronchery             return 0;
167b077aed3SPierre Pronchery         }
168b077aed3SPierre Pronchery         prsactx->min_saltlen = min_saltlen;
169b077aed3SPierre Pronchery     }
170b077aed3SPierre Pronchery     return 1;
171b077aed3SPierre Pronchery }
172b077aed3SPierre Pronchery 
rsa_newctx(void * provctx,const char * propq)173b077aed3SPierre Pronchery static void *rsa_newctx(void *provctx, const char *propq)
174b077aed3SPierre Pronchery {
175b077aed3SPierre Pronchery     PROV_RSA_CTX *prsactx = NULL;
176b077aed3SPierre Pronchery     char *propq_copy = NULL;
177b077aed3SPierre Pronchery 
178b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
179b077aed3SPierre Pronchery         return NULL;
180b077aed3SPierre Pronchery 
181b077aed3SPierre Pronchery     if ((prsactx = OPENSSL_zalloc(sizeof(PROV_RSA_CTX))) == NULL
182b077aed3SPierre Pronchery         || (propq != NULL
183b077aed3SPierre Pronchery             && (propq_copy = OPENSSL_strdup(propq)) == NULL)) {
184b077aed3SPierre Pronchery         OPENSSL_free(prsactx);
185b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
186b077aed3SPierre Pronchery         return NULL;
187b077aed3SPierre Pronchery     }
188b077aed3SPierre Pronchery 
189b077aed3SPierre Pronchery     prsactx->libctx = PROV_LIBCTX_OF(provctx);
190b077aed3SPierre Pronchery     prsactx->flag_allow_md = 1;
191b077aed3SPierre Pronchery     prsactx->propq = propq_copy;
192b077aed3SPierre Pronchery     /* Maximum for sign, auto for verify */
193b077aed3SPierre Pronchery     prsactx->saltlen = RSA_PSS_SALTLEN_AUTO;
194b077aed3SPierre Pronchery     prsactx->min_saltlen = -1;
195b077aed3SPierre Pronchery     return prsactx;
196b077aed3SPierre Pronchery }
197b077aed3SPierre Pronchery 
rsa_pss_compute_saltlen(PROV_RSA_CTX * ctx)198b077aed3SPierre Pronchery static int rsa_pss_compute_saltlen(PROV_RSA_CTX *ctx)
199b077aed3SPierre Pronchery {
200b077aed3SPierre Pronchery     int saltlen = ctx->saltlen;
201b077aed3SPierre Pronchery 
202b077aed3SPierre Pronchery     if (saltlen == RSA_PSS_SALTLEN_DIGEST) {
203b077aed3SPierre Pronchery         saltlen = EVP_MD_get_size(ctx->md);
204b077aed3SPierre Pronchery     } else if (saltlen == RSA_PSS_SALTLEN_AUTO || saltlen == RSA_PSS_SALTLEN_MAX) {
205b077aed3SPierre Pronchery         saltlen = RSA_size(ctx->rsa) - EVP_MD_get_size(ctx->md) - 2;
206b077aed3SPierre Pronchery         if ((RSA_bits(ctx->rsa) & 0x7) == 1)
207b077aed3SPierre Pronchery             saltlen--;
208b077aed3SPierre Pronchery     }
209b077aed3SPierre Pronchery     if (saltlen < 0) {
210b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
211b077aed3SPierre Pronchery         return -1;
212b077aed3SPierre Pronchery     } else if (saltlen < ctx->min_saltlen) {
213b077aed3SPierre Pronchery         ERR_raise_data(ERR_LIB_PROV, PROV_R_PSS_SALTLEN_TOO_SMALL,
214b077aed3SPierre Pronchery                        "minimum salt length: %d, actual salt length: %d",
215b077aed3SPierre Pronchery                        ctx->min_saltlen, saltlen);
216b077aed3SPierre Pronchery         return -1;
217b077aed3SPierre Pronchery     }
218b077aed3SPierre Pronchery     return saltlen;
219b077aed3SPierre Pronchery }
220b077aed3SPierre Pronchery 
rsa_generate_signature_aid(PROV_RSA_CTX * ctx,unsigned char * aid_buf,size_t buf_len,size_t * aid_len)221b077aed3SPierre Pronchery static unsigned char *rsa_generate_signature_aid(PROV_RSA_CTX *ctx,
222b077aed3SPierre Pronchery                                                  unsigned char *aid_buf,
223b077aed3SPierre Pronchery                                                  size_t buf_len,
224b077aed3SPierre Pronchery                                                  size_t *aid_len)
225b077aed3SPierre Pronchery {
226b077aed3SPierre Pronchery     WPACKET pkt;
227b077aed3SPierre Pronchery     unsigned char *aid = NULL;
228b077aed3SPierre Pronchery     int saltlen;
229b077aed3SPierre Pronchery     RSA_PSS_PARAMS_30 pss_params;
230b077aed3SPierre Pronchery     int ret;
231b077aed3SPierre Pronchery 
232b077aed3SPierre Pronchery     if (!WPACKET_init_der(&pkt, aid_buf, buf_len)) {
233b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
234b077aed3SPierre Pronchery         return NULL;
235b077aed3SPierre Pronchery     }
236b077aed3SPierre Pronchery 
237b077aed3SPierre Pronchery     switch(ctx->pad_mode) {
238b077aed3SPierre Pronchery     case RSA_PKCS1_PADDING:
239b077aed3SPierre Pronchery         ret = ossl_DER_w_algorithmIdentifier_MDWithRSAEncryption(&pkt, -1,
240b077aed3SPierre Pronchery                                                                  ctx->mdnid);
241b077aed3SPierre Pronchery 
242b077aed3SPierre Pronchery         if (ret > 0) {
243b077aed3SPierre Pronchery             break;
244b077aed3SPierre Pronchery         } else if (ret == 0) {
245b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
246b077aed3SPierre Pronchery             goto cleanup;
247b077aed3SPierre Pronchery         }
248b077aed3SPierre Pronchery         ERR_raise_data(ERR_LIB_PROV, ERR_R_UNSUPPORTED,
249b077aed3SPierre Pronchery                        "Algorithm ID generation - md NID: %d",
250b077aed3SPierre Pronchery                        ctx->mdnid);
251b077aed3SPierre Pronchery         goto cleanup;
252b077aed3SPierre Pronchery     case RSA_PKCS1_PSS_PADDING:
253b077aed3SPierre Pronchery         saltlen = rsa_pss_compute_saltlen(ctx);
254b077aed3SPierre Pronchery         if (saltlen < 0)
255b077aed3SPierre Pronchery             goto cleanup;
256b077aed3SPierre Pronchery         if (!ossl_rsa_pss_params_30_set_defaults(&pss_params)
257b077aed3SPierre Pronchery             || !ossl_rsa_pss_params_30_set_hashalg(&pss_params, ctx->mdnid)
258b077aed3SPierre Pronchery             || !ossl_rsa_pss_params_30_set_maskgenhashalg(&pss_params,
259b077aed3SPierre Pronchery                                                           ctx->mgf1_mdnid)
260b077aed3SPierre Pronchery             || !ossl_rsa_pss_params_30_set_saltlen(&pss_params, saltlen)
261b077aed3SPierre Pronchery             || !ossl_DER_w_algorithmIdentifier_RSA_PSS(&pkt, -1,
262b077aed3SPierre Pronchery                                                        RSA_FLAG_TYPE_RSASSAPSS,
263b077aed3SPierre Pronchery                                                        &pss_params)) {
264b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
265b077aed3SPierre Pronchery             goto cleanup;
266b077aed3SPierre Pronchery         }
267b077aed3SPierre Pronchery         break;
268b077aed3SPierre Pronchery     default:
269b077aed3SPierre Pronchery         ERR_raise_data(ERR_LIB_PROV, ERR_R_UNSUPPORTED,
270b077aed3SPierre Pronchery                        "Algorithm ID generation - pad mode: %d",
271b077aed3SPierre Pronchery                        ctx->pad_mode);
272b077aed3SPierre Pronchery         goto cleanup;
273b077aed3SPierre Pronchery     }
274b077aed3SPierre Pronchery     if (WPACKET_finish(&pkt)) {
275b077aed3SPierre Pronchery         WPACKET_get_total_written(&pkt, aid_len);
276b077aed3SPierre Pronchery         aid = WPACKET_get_curr(&pkt);
277b077aed3SPierre Pronchery     }
278b077aed3SPierre Pronchery  cleanup:
279b077aed3SPierre Pronchery     WPACKET_cleanup(&pkt);
280b077aed3SPierre Pronchery     return aid;
281b077aed3SPierre Pronchery }
282b077aed3SPierre Pronchery 
rsa_setup_md(PROV_RSA_CTX * ctx,const char * mdname,const char * mdprops)283b077aed3SPierre Pronchery static int rsa_setup_md(PROV_RSA_CTX *ctx, const char *mdname,
284b077aed3SPierre Pronchery                         const char *mdprops)
285b077aed3SPierre Pronchery {
286b077aed3SPierre Pronchery     if (mdprops == NULL)
287b077aed3SPierre Pronchery         mdprops = ctx->propq;
288b077aed3SPierre Pronchery 
289b077aed3SPierre Pronchery     if (mdname != NULL) {
290b077aed3SPierre Pronchery         EVP_MD *md = EVP_MD_fetch(ctx->libctx, mdname, mdprops);
291b077aed3SPierre Pronchery         int sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN);
292b077aed3SPierre Pronchery         int md_nid = ossl_digest_rsa_sign_get_md_nid(ctx->libctx, md,
293b077aed3SPierre Pronchery                                                      sha1_allowed);
294b077aed3SPierre Pronchery         size_t mdname_len = strlen(mdname);
295b077aed3SPierre Pronchery 
296b077aed3SPierre Pronchery         if (md == NULL
297b077aed3SPierre Pronchery             || md_nid <= 0
298b077aed3SPierre Pronchery             || !rsa_check_padding(ctx, mdname, NULL, md_nid)
299b077aed3SPierre Pronchery             || mdname_len >= sizeof(ctx->mdname)) {
300b077aed3SPierre Pronchery             if (md == NULL)
301b077aed3SPierre Pronchery                 ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
302b077aed3SPierre Pronchery                                "%s could not be fetched", mdname);
303b077aed3SPierre Pronchery             if (md_nid <= 0)
304b077aed3SPierre Pronchery                 ERR_raise_data(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED,
305b077aed3SPierre Pronchery                                "digest=%s", mdname);
306b077aed3SPierre Pronchery             if (mdname_len >= sizeof(ctx->mdname))
307b077aed3SPierre Pronchery                 ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
308b077aed3SPierre Pronchery                                "%s exceeds name buffer length", mdname);
309b077aed3SPierre Pronchery             EVP_MD_free(md);
310b077aed3SPierre Pronchery             return 0;
311b077aed3SPierre Pronchery         }
312b077aed3SPierre Pronchery 
313b077aed3SPierre Pronchery         if (!ctx->flag_allow_md) {
314b077aed3SPierre Pronchery             if (ctx->mdname[0] != '\0' && !EVP_MD_is_a(md, ctx->mdname)) {
315b077aed3SPierre Pronchery                 ERR_raise_data(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED,
316b077aed3SPierre Pronchery                                "digest %s != %s", mdname, ctx->mdname);
317b077aed3SPierre Pronchery                 EVP_MD_free(md);
318b077aed3SPierre Pronchery                 return 0;
319b077aed3SPierre Pronchery             }
320b077aed3SPierre Pronchery             EVP_MD_free(md);
321b077aed3SPierre Pronchery             return 1;
322b077aed3SPierre Pronchery         }
323b077aed3SPierre Pronchery 
324b077aed3SPierre Pronchery         if (!ctx->mgf1_md_set) {
325b077aed3SPierre Pronchery             if (!EVP_MD_up_ref(md)) {
326b077aed3SPierre Pronchery                 EVP_MD_free(md);
327b077aed3SPierre Pronchery                 return 0;
328b077aed3SPierre Pronchery             }
329b077aed3SPierre Pronchery             EVP_MD_free(ctx->mgf1_md);
330b077aed3SPierre Pronchery             ctx->mgf1_md = md;
331b077aed3SPierre Pronchery             ctx->mgf1_mdnid = md_nid;
332b077aed3SPierre Pronchery             OPENSSL_strlcpy(ctx->mgf1_mdname, mdname, sizeof(ctx->mgf1_mdname));
333b077aed3SPierre Pronchery         }
334b077aed3SPierre Pronchery 
335b077aed3SPierre Pronchery         EVP_MD_CTX_free(ctx->mdctx);
336b077aed3SPierre Pronchery         EVP_MD_free(ctx->md);
337b077aed3SPierre Pronchery 
338b077aed3SPierre Pronchery         ctx->mdctx = NULL;
339b077aed3SPierre Pronchery         ctx->md = md;
340b077aed3SPierre Pronchery         ctx->mdnid = md_nid;
341b077aed3SPierre Pronchery         OPENSSL_strlcpy(ctx->mdname, mdname, sizeof(ctx->mdname));
342b077aed3SPierre Pronchery     }
343b077aed3SPierre Pronchery 
344b077aed3SPierre Pronchery     return 1;
345b077aed3SPierre Pronchery }
346b077aed3SPierre Pronchery 
rsa_setup_mgf1_md(PROV_RSA_CTX * ctx,const char * mdname,const char * mdprops)347b077aed3SPierre Pronchery static int rsa_setup_mgf1_md(PROV_RSA_CTX *ctx, const char *mdname,
348b077aed3SPierre Pronchery                              const char *mdprops)
349b077aed3SPierre Pronchery {
350b077aed3SPierre Pronchery     size_t len;
351b077aed3SPierre Pronchery     EVP_MD *md = NULL;
352b077aed3SPierre Pronchery     int mdnid;
353b077aed3SPierre Pronchery 
354b077aed3SPierre Pronchery     if (mdprops == NULL)
355b077aed3SPierre Pronchery         mdprops = ctx->propq;
356b077aed3SPierre Pronchery 
357b077aed3SPierre Pronchery     if ((md = EVP_MD_fetch(ctx->libctx, mdname, mdprops)) == NULL) {
358b077aed3SPierre Pronchery         ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
359b077aed3SPierre Pronchery                        "%s could not be fetched", mdname);
360b077aed3SPierre Pronchery         return 0;
361b077aed3SPierre Pronchery     }
362b077aed3SPierre Pronchery     /* The default for mgf1 is SHA1 - so allow SHA1 */
363b077aed3SPierre Pronchery     if ((mdnid = ossl_digest_rsa_sign_get_md_nid(ctx->libctx, md, 1)) <= 0
364b077aed3SPierre Pronchery         || !rsa_check_padding(ctx, NULL, mdname, mdnid)) {
365b077aed3SPierre Pronchery         if (mdnid <= 0)
366b077aed3SPierre Pronchery             ERR_raise_data(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED,
367b077aed3SPierre Pronchery                            "digest=%s", mdname);
368b077aed3SPierre Pronchery         EVP_MD_free(md);
369b077aed3SPierre Pronchery         return 0;
370b077aed3SPierre Pronchery     }
371b077aed3SPierre Pronchery     len = OPENSSL_strlcpy(ctx->mgf1_mdname, mdname, sizeof(ctx->mgf1_mdname));
372b077aed3SPierre Pronchery     if (len >= sizeof(ctx->mgf1_mdname)) {
373b077aed3SPierre Pronchery         ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
374b077aed3SPierre Pronchery                        "%s exceeds name buffer length", mdname);
375b077aed3SPierre Pronchery         EVP_MD_free(md);
376b077aed3SPierre Pronchery         return 0;
377b077aed3SPierre Pronchery     }
378b077aed3SPierre Pronchery 
379b077aed3SPierre Pronchery     EVP_MD_free(ctx->mgf1_md);
380b077aed3SPierre Pronchery     ctx->mgf1_md = md;
381b077aed3SPierre Pronchery     ctx->mgf1_mdnid = mdnid;
382b077aed3SPierre Pronchery     ctx->mgf1_md_set = 1;
383b077aed3SPierre Pronchery     return 1;
384b077aed3SPierre Pronchery }
385b077aed3SPierre Pronchery 
rsa_signverify_init(void * vprsactx,void * vrsa,const OSSL_PARAM params[],int operation)386b077aed3SPierre Pronchery static int rsa_signverify_init(void *vprsactx, void *vrsa,
387b077aed3SPierre Pronchery                                const OSSL_PARAM params[], int operation)
388b077aed3SPierre Pronchery {
389b077aed3SPierre Pronchery     PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
390b077aed3SPierre Pronchery 
391b077aed3SPierre Pronchery     if (!ossl_prov_is_running() || prsactx == NULL)
392b077aed3SPierre Pronchery         return 0;
393b077aed3SPierre Pronchery 
394b077aed3SPierre Pronchery     if (vrsa == NULL && prsactx->rsa == NULL) {
395b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET);
396b077aed3SPierre Pronchery         return 0;
397b077aed3SPierre Pronchery     }
398b077aed3SPierre Pronchery 
399b077aed3SPierre Pronchery     if (vrsa != NULL) {
400b077aed3SPierre Pronchery         if (!ossl_rsa_check_key(prsactx->libctx, vrsa, operation))
401b077aed3SPierre Pronchery             return 0;
402b077aed3SPierre Pronchery 
403b077aed3SPierre Pronchery         if (!RSA_up_ref(vrsa))
404b077aed3SPierre Pronchery             return 0;
405b077aed3SPierre Pronchery         RSA_free(prsactx->rsa);
406b077aed3SPierre Pronchery         prsactx->rsa = vrsa;
407b077aed3SPierre Pronchery     }
408b077aed3SPierre Pronchery 
409b077aed3SPierre Pronchery     prsactx->operation = operation;
410b077aed3SPierre Pronchery 
411b077aed3SPierre Pronchery     /* Maximum for sign, auto for verify */
412b077aed3SPierre Pronchery     prsactx->saltlen = RSA_PSS_SALTLEN_AUTO;
413b077aed3SPierre Pronchery     prsactx->min_saltlen = -1;
414b077aed3SPierre Pronchery 
415b077aed3SPierre Pronchery     switch (RSA_test_flags(prsactx->rsa, RSA_FLAG_TYPE_MASK)) {
416b077aed3SPierre Pronchery     case RSA_FLAG_TYPE_RSA:
417b077aed3SPierre Pronchery         prsactx->pad_mode = RSA_PKCS1_PADDING;
418b077aed3SPierre Pronchery         break;
419b077aed3SPierre Pronchery     case RSA_FLAG_TYPE_RSASSAPSS:
420b077aed3SPierre Pronchery         prsactx->pad_mode = RSA_PKCS1_PSS_PADDING;
421b077aed3SPierre Pronchery 
422b077aed3SPierre Pronchery         {
423b077aed3SPierre Pronchery             const RSA_PSS_PARAMS_30 *pss =
424b077aed3SPierre Pronchery                 ossl_rsa_get0_pss_params_30(prsactx->rsa);
425b077aed3SPierre Pronchery 
426b077aed3SPierre Pronchery             if (!ossl_rsa_pss_params_30_is_unrestricted(pss)) {
427b077aed3SPierre Pronchery                 int md_nid = ossl_rsa_pss_params_30_hashalg(pss);
428b077aed3SPierre Pronchery                 int mgf1md_nid = ossl_rsa_pss_params_30_maskgenhashalg(pss);
429b077aed3SPierre Pronchery                 int min_saltlen = ossl_rsa_pss_params_30_saltlen(pss);
430b077aed3SPierre Pronchery                 const char *mdname, *mgf1mdname;
431b077aed3SPierre Pronchery                 size_t len;
432b077aed3SPierre Pronchery 
433b077aed3SPierre Pronchery                 mdname = ossl_rsa_oaeppss_nid2name(md_nid);
434b077aed3SPierre Pronchery                 mgf1mdname = ossl_rsa_oaeppss_nid2name(mgf1md_nid);
435b077aed3SPierre Pronchery 
436b077aed3SPierre Pronchery                 if (mdname == NULL) {
437b077aed3SPierre Pronchery                     ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
438b077aed3SPierre Pronchery                                    "PSS restrictions lack hash algorithm");
439b077aed3SPierre Pronchery                     return 0;
440b077aed3SPierre Pronchery                 }
441b077aed3SPierre Pronchery                 if (mgf1mdname == NULL) {
442b077aed3SPierre Pronchery                     ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
443b077aed3SPierre Pronchery                                    "PSS restrictions lack MGF1 hash algorithm");
444b077aed3SPierre Pronchery                     return 0;
445b077aed3SPierre Pronchery                 }
446b077aed3SPierre Pronchery 
447b077aed3SPierre Pronchery                 len = OPENSSL_strlcpy(prsactx->mdname, mdname,
448b077aed3SPierre Pronchery                                       sizeof(prsactx->mdname));
449b077aed3SPierre Pronchery                 if (len >= sizeof(prsactx->mdname)) {
450b077aed3SPierre Pronchery                     ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
451b077aed3SPierre Pronchery                                    "hash algorithm name too long");
452b077aed3SPierre Pronchery                     return 0;
453b077aed3SPierre Pronchery                 }
454b077aed3SPierre Pronchery                 len = OPENSSL_strlcpy(prsactx->mgf1_mdname, mgf1mdname,
455b077aed3SPierre Pronchery                                       sizeof(prsactx->mgf1_mdname));
456b077aed3SPierre Pronchery                 if (len >= sizeof(prsactx->mgf1_mdname)) {
457b077aed3SPierre Pronchery                     ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
458b077aed3SPierre Pronchery                                    "MGF1 hash algorithm name too long");
459b077aed3SPierre Pronchery                     return 0;
460b077aed3SPierre Pronchery                 }
461b077aed3SPierre Pronchery                 prsactx->saltlen = min_saltlen;
462b077aed3SPierre Pronchery 
463b077aed3SPierre Pronchery                 /* call rsa_setup_mgf1_md before rsa_setup_md to avoid duplication */
464b077aed3SPierre Pronchery                 if (!rsa_setup_mgf1_md(prsactx, mgf1mdname, prsactx->propq)
465b077aed3SPierre Pronchery                     || !rsa_setup_md(prsactx, mdname, prsactx->propq)
466b077aed3SPierre Pronchery                     || !rsa_check_parameters(prsactx, min_saltlen))
467b077aed3SPierre Pronchery                     return 0;
468b077aed3SPierre Pronchery             }
469b077aed3SPierre Pronchery         }
470b077aed3SPierre Pronchery 
471b077aed3SPierre Pronchery         break;
472b077aed3SPierre Pronchery     default:
473b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_RSA, PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
474b077aed3SPierre Pronchery         return 0;
475b077aed3SPierre Pronchery     }
476b077aed3SPierre Pronchery 
477b077aed3SPierre Pronchery     if (!rsa_set_ctx_params(prsactx, params))
478b077aed3SPierre Pronchery         return 0;
479b077aed3SPierre Pronchery 
480b077aed3SPierre Pronchery     return 1;
481b077aed3SPierre Pronchery }
482b077aed3SPierre Pronchery 
setup_tbuf(PROV_RSA_CTX * ctx)483b077aed3SPierre Pronchery static int setup_tbuf(PROV_RSA_CTX *ctx)
484b077aed3SPierre Pronchery {
485b077aed3SPierre Pronchery     if (ctx->tbuf != NULL)
486b077aed3SPierre Pronchery         return 1;
487b077aed3SPierre Pronchery     if ((ctx->tbuf = OPENSSL_malloc(RSA_size(ctx->rsa))) == NULL) {
488b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
489b077aed3SPierre Pronchery         return 0;
490b077aed3SPierre Pronchery     }
491b077aed3SPierre Pronchery     return 1;
492b077aed3SPierre Pronchery }
493b077aed3SPierre Pronchery 
clean_tbuf(PROV_RSA_CTX * ctx)494b077aed3SPierre Pronchery static void clean_tbuf(PROV_RSA_CTX *ctx)
495b077aed3SPierre Pronchery {
496b077aed3SPierre Pronchery     if (ctx->tbuf != NULL)
497b077aed3SPierre Pronchery         OPENSSL_cleanse(ctx->tbuf, RSA_size(ctx->rsa));
498b077aed3SPierre Pronchery }
499b077aed3SPierre Pronchery 
free_tbuf(PROV_RSA_CTX * ctx)500b077aed3SPierre Pronchery static void free_tbuf(PROV_RSA_CTX *ctx)
501b077aed3SPierre Pronchery {
502b077aed3SPierre Pronchery     clean_tbuf(ctx);
503b077aed3SPierre Pronchery     OPENSSL_free(ctx->tbuf);
504b077aed3SPierre Pronchery     ctx->tbuf = NULL;
505b077aed3SPierre Pronchery }
506b077aed3SPierre Pronchery 
rsa_sign_init(void * vprsactx,void * vrsa,const OSSL_PARAM params[])507b077aed3SPierre Pronchery static int rsa_sign_init(void *vprsactx, void *vrsa, const OSSL_PARAM params[])
508b077aed3SPierre Pronchery {
509b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
510b077aed3SPierre Pronchery         return 0;
511b077aed3SPierre Pronchery     return rsa_signverify_init(vprsactx, vrsa, params, EVP_PKEY_OP_SIGN);
512b077aed3SPierre Pronchery }
513b077aed3SPierre Pronchery 
rsa_sign(void * vprsactx,unsigned char * sig,size_t * siglen,size_t sigsize,const unsigned char * tbs,size_t tbslen)514b077aed3SPierre Pronchery static int rsa_sign(void *vprsactx, unsigned char *sig, size_t *siglen,
515b077aed3SPierre Pronchery                     size_t sigsize, const unsigned char *tbs, size_t tbslen)
516b077aed3SPierre Pronchery {
517b077aed3SPierre Pronchery     PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
518b077aed3SPierre Pronchery     int ret;
519b077aed3SPierre Pronchery     size_t rsasize = RSA_size(prsactx->rsa);
520b077aed3SPierre Pronchery     size_t mdsize = rsa_get_md_size(prsactx);
521b077aed3SPierre Pronchery 
522b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
523b077aed3SPierre Pronchery         return 0;
524b077aed3SPierre Pronchery 
525b077aed3SPierre Pronchery     if (sig == NULL) {
526b077aed3SPierre Pronchery         *siglen = rsasize;
527b077aed3SPierre Pronchery         return 1;
528b077aed3SPierre Pronchery     }
529b077aed3SPierre Pronchery 
530b077aed3SPierre Pronchery     if (sigsize < rsasize) {
531b077aed3SPierre Pronchery         ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_SIGNATURE_SIZE,
532b077aed3SPierre Pronchery                        "is %zu, should be at least %zu", sigsize, rsasize);
533b077aed3SPierre Pronchery         return 0;
534b077aed3SPierre Pronchery     }
535b077aed3SPierre Pronchery 
536b077aed3SPierre Pronchery     if (mdsize != 0) {
537b077aed3SPierre Pronchery         if (tbslen != mdsize) {
538b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH);
539b077aed3SPierre Pronchery             return 0;
540b077aed3SPierre Pronchery         }
541b077aed3SPierre Pronchery 
542b077aed3SPierre Pronchery #ifndef FIPS_MODULE
543b077aed3SPierre Pronchery         if (EVP_MD_is_a(prsactx->md, OSSL_DIGEST_NAME_MDC2)) {
544b077aed3SPierre Pronchery             unsigned int sltmp;
545b077aed3SPierre Pronchery 
546b077aed3SPierre Pronchery             if (prsactx->pad_mode != RSA_PKCS1_PADDING) {
547b077aed3SPierre Pronchery                 ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE,
548b077aed3SPierre Pronchery                                "only PKCS#1 padding supported with MDC2");
549b077aed3SPierre Pronchery                 return 0;
550b077aed3SPierre Pronchery             }
551b077aed3SPierre Pronchery             ret = RSA_sign_ASN1_OCTET_STRING(0, tbs, tbslen, sig, &sltmp,
552b077aed3SPierre Pronchery                                              prsactx->rsa);
553b077aed3SPierre Pronchery 
554b077aed3SPierre Pronchery             if (ret <= 0) {
555b077aed3SPierre Pronchery                 ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB);
556b077aed3SPierre Pronchery                 return 0;
557b077aed3SPierre Pronchery             }
558b077aed3SPierre Pronchery             ret = sltmp;
559b077aed3SPierre Pronchery             goto end;
560b077aed3SPierre Pronchery         }
561b077aed3SPierre Pronchery #endif
562b077aed3SPierre Pronchery         switch (prsactx->pad_mode) {
563b077aed3SPierre Pronchery         case RSA_X931_PADDING:
564b077aed3SPierre Pronchery             if ((size_t)RSA_size(prsactx->rsa) < tbslen + 1) {
565b077aed3SPierre Pronchery                 ERR_raise_data(ERR_LIB_PROV, PROV_R_KEY_SIZE_TOO_SMALL,
566b077aed3SPierre Pronchery                                "RSA key size = %d, expected minimum = %d",
567b077aed3SPierre Pronchery                                RSA_size(prsactx->rsa), tbslen + 1);
568b077aed3SPierre Pronchery                 return 0;
569b077aed3SPierre Pronchery             }
570b077aed3SPierre Pronchery             if (!setup_tbuf(prsactx)) {
571b077aed3SPierre Pronchery                 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
572b077aed3SPierre Pronchery                 return 0;
573b077aed3SPierre Pronchery             }
574b077aed3SPierre Pronchery             memcpy(prsactx->tbuf, tbs, tbslen);
575b077aed3SPierre Pronchery             prsactx->tbuf[tbslen] = RSA_X931_hash_id(prsactx->mdnid);
576b077aed3SPierre Pronchery             ret = RSA_private_encrypt(tbslen + 1, prsactx->tbuf,
577b077aed3SPierre Pronchery                                       sig, prsactx->rsa, RSA_X931_PADDING);
578b077aed3SPierre Pronchery             clean_tbuf(prsactx);
579b077aed3SPierre Pronchery             break;
580b077aed3SPierre Pronchery 
581b077aed3SPierre Pronchery         case RSA_PKCS1_PADDING:
582b077aed3SPierre Pronchery             {
583b077aed3SPierre Pronchery                 unsigned int sltmp;
584b077aed3SPierre Pronchery 
585b077aed3SPierre Pronchery                 ret = RSA_sign(prsactx->mdnid, tbs, tbslen, sig, &sltmp,
586b077aed3SPierre Pronchery                                prsactx->rsa);
587b077aed3SPierre Pronchery                 if (ret <= 0) {
588b077aed3SPierre Pronchery                     ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB);
589b077aed3SPierre Pronchery                     return 0;
590b077aed3SPierre Pronchery                 }
591b077aed3SPierre Pronchery                 ret = sltmp;
592b077aed3SPierre Pronchery             }
593b077aed3SPierre Pronchery             break;
594b077aed3SPierre Pronchery 
595b077aed3SPierre Pronchery         case RSA_PKCS1_PSS_PADDING:
596b077aed3SPierre Pronchery             /* Check PSS restrictions */
597b077aed3SPierre Pronchery             if (rsa_pss_restricted(prsactx)) {
598b077aed3SPierre Pronchery                 switch (prsactx->saltlen) {
599b077aed3SPierre Pronchery                 case RSA_PSS_SALTLEN_DIGEST:
600b077aed3SPierre Pronchery                     if (prsactx->min_saltlen > EVP_MD_get_size(prsactx->md)) {
601b077aed3SPierre Pronchery                         ERR_raise_data(ERR_LIB_PROV,
602b077aed3SPierre Pronchery                                        PROV_R_PSS_SALTLEN_TOO_SMALL,
603b077aed3SPierre Pronchery                                        "minimum salt length set to %d, "
604b077aed3SPierre Pronchery                                        "but the digest only gives %d",
605b077aed3SPierre Pronchery                                        prsactx->min_saltlen,
606b077aed3SPierre Pronchery                                        EVP_MD_get_size(prsactx->md));
607b077aed3SPierre Pronchery                         return 0;
608b077aed3SPierre Pronchery                     }
609b077aed3SPierre Pronchery                     /* FALLTHRU */
610b077aed3SPierre Pronchery                 default:
611b077aed3SPierre Pronchery                     if (prsactx->saltlen >= 0
612b077aed3SPierre Pronchery                         && prsactx->saltlen < prsactx->min_saltlen) {
613b077aed3SPierre Pronchery                         ERR_raise_data(ERR_LIB_PROV,
614b077aed3SPierre Pronchery                                        PROV_R_PSS_SALTLEN_TOO_SMALL,
615b077aed3SPierre Pronchery                                        "minimum salt length set to %d, but the"
616b077aed3SPierre Pronchery                                        "actual salt length is only set to %d",
617b077aed3SPierre Pronchery                                        prsactx->min_saltlen,
618b077aed3SPierre Pronchery                                        prsactx->saltlen);
619b077aed3SPierre Pronchery                         return 0;
620b077aed3SPierre Pronchery                     }
621b077aed3SPierre Pronchery                     break;
622b077aed3SPierre Pronchery                 }
623b077aed3SPierre Pronchery             }
624b077aed3SPierre Pronchery             if (!setup_tbuf(prsactx))
625b077aed3SPierre Pronchery                 return 0;
626b077aed3SPierre Pronchery             if (!RSA_padding_add_PKCS1_PSS_mgf1(prsactx->rsa,
627b077aed3SPierre Pronchery                                                 prsactx->tbuf, tbs,
628b077aed3SPierre Pronchery                                                 prsactx->md, prsactx->mgf1_md,
629b077aed3SPierre Pronchery                                                 prsactx->saltlen)) {
630b077aed3SPierre Pronchery                 ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB);
631b077aed3SPierre Pronchery                 return 0;
632b077aed3SPierre Pronchery             }
633b077aed3SPierre Pronchery             ret = RSA_private_encrypt(RSA_size(prsactx->rsa), prsactx->tbuf,
634b077aed3SPierre Pronchery                                       sig, prsactx->rsa, RSA_NO_PADDING);
635b077aed3SPierre Pronchery             clean_tbuf(prsactx);
636b077aed3SPierre Pronchery             break;
637b077aed3SPierre Pronchery 
638b077aed3SPierre Pronchery         default:
639b077aed3SPierre Pronchery             ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE,
640b077aed3SPierre Pronchery                            "Only X.931, PKCS#1 v1.5 or PSS padding allowed");
641b077aed3SPierre Pronchery             return 0;
642b077aed3SPierre Pronchery         }
643b077aed3SPierre Pronchery     } else {
644b077aed3SPierre Pronchery         ret = RSA_private_encrypt(tbslen, tbs, sig, prsactx->rsa,
645b077aed3SPierre Pronchery                                   prsactx->pad_mode);
646b077aed3SPierre Pronchery     }
647b077aed3SPierre Pronchery 
648b077aed3SPierre Pronchery #ifndef FIPS_MODULE
649b077aed3SPierre Pronchery  end:
650b077aed3SPierre Pronchery #endif
651b077aed3SPierre Pronchery     if (ret <= 0) {
652b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB);
653b077aed3SPierre Pronchery         return 0;
654b077aed3SPierre Pronchery     }
655b077aed3SPierre Pronchery 
656b077aed3SPierre Pronchery     *siglen = ret;
657b077aed3SPierre Pronchery     return 1;
658b077aed3SPierre Pronchery }
659b077aed3SPierre Pronchery 
rsa_verify_recover_init(void * vprsactx,void * vrsa,const OSSL_PARAM params[])660b077aed3SPierre Pronchery static int rsa_verify_recover_init(void *vprsactx, void *vrsa,
661b077aed3SPierre Pronchery                                    const OSSL_PARAM params[])
662b077aed3SPierre Pronchery {
663b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
664b077aed3SPierre Pronchery         return 0;
665b077aed3SPierre Pronchery     return rsa_signverify_init(vprsactx, vrsa, params,
666b077aed3SPierre Pronchery                                EVP_PKEY_OP_VERIFYRECOVER);
667b077aed3SPierre Pronchery }
668b077aed3SPierre Pronchery 
rsa_verify_recover(void * vprsactx,unsigned char * rout,size_t * routlen,size_t routsize,const unsigned char * sig,size_t siglen)669b077aed3SPierre Pronchery static int rsa_verify_recover(void *vprsactx,
670b077aed3SPierre Pronchery                               unsigned char *rout,
671b077aed3SPierre Pronchery                               size_t *routlen,
672b077aed3SPierre Pronchery                               size_t routsize,
673b077aed3SPierre Pronchery                               const unsigned char *sig,
674b077aed3SPierre Pronchery                               size_t siglen)
675b077aed3SPierre Pronchery {
676b077aed3SPierre Pronchery     PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
677b077aed3SPierre Pronchery     int ret;
678b077aed3SPierre Pronchery 
679b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
680b077aed3SPierre Pronchery         return 0;
681b077aed3SPierre Pronchery 
682b077aed3SPierre Pronchery     if (rout == NULL) {
683b077aed3SPierre Pronchery         *routlen = RSA_size(prsactx->rsa);
684b077aed3SPierre Pronchery         return 1;
685b077aed3SPierre Pronchery     }
686b077aed3SPierre Pronchery 
687b077aed3SPierre Pronchery     if (prsactx->md != NULL) {
688b077aed3SPierre Pronchery         switch (prsactx->pad_mode) {
689b077aed3SPierre Pronchery         case RSA_X931_PADDING:
690b077aed3SPierre Pronchery             if (!setup_tbuf(prsactx))
691b077aed3SPierre Pronchery                 return 0;
692b077aed3SPierre Pronchery             ret = RSA_public_decrypt(siglen, sig, prsactx->tbuf, prsactx->rsa,
693b077aed3SPierre Pronchery                                      RSA_X931_PADDING);
694b077aed3SPierre Pronchery             if (ret < 1) {
695b077aed3SPierre Pronchery                 ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB);
696b077aed3SPierre Pronchery                 return 0;
697b077aed3SPierre Pronchery             }
698b077aed3SPierre Pronchery             ret--;
699b077aed3SPierre Pronchery             if (prsactx->tbuf[ret] != RSA_X931_hash_id(prsactx->mdnid)) {
700b077aed3SPierre Pronchery                 ERR_raise(ERR_LIB_PROV, PROV_R_ALGORITHM_MISMATCH);
701b077aed3SPierre Pronchery                 return 0;
702b077aed3SPierre Pronchery             }
703b077aed3SPierre Pronchery             if (ret != EVP_MD_get_size(prsactx->md)) {
704b077aed3SPierre Pronchery                 ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH,
705b077aed3SPierre Pronchery                                "Should be %d, but got %d",
706b077aed3SPierre Pronchery                                EVP_MD_get_size(prsactx->md), ret);
707b077aed3SPierre Pronchery                 return 0;
708b077aed3SPierre Pronchery             }
709b077aed3SPierre Pronchery 
710b077aed3SPierre Pronchery             *routlen = ret;
711b077aed3SPierre Pronchery             if (rout != prsactx->tbuf) {
712b077aed3SPierre Pronchery                 if (routsize < (size_t)ret) {
713b077aed3SPierre Pronchery                     ERR_raise_data(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL,
714b077aed3SPierre Pronchery                                    "buffer size is %d, should be %d",
715b077aed3SPierre Pronchery                                    routsize, ret);
716b077aed3SPierre Pronchery                     return 0;
717b077aed3SPierre Pronchery                 }
718b077aed3SPierre Pronchery                 memcpy(rout, prsactx->tbuf, ret);
719b077aed3SPierre Pronchery             }
720b077aed3SPierre Pronchery             break;
721b077aed3SPierre Pronchery 
722b077aed3SPierre Pronchery         case RSA_PKCS1_PADDING:
723b077aed3SPierre Pronchery             {
724b077aed3SPierre Pronchery                 size_t sltmp;
725b077aed3SPierre Pronchery 
726b077aed3SPierre Pronchery                 ret = ossl_rsa_verify(prsactx->mdnid, NULL, 0, rout, &sltmp,
727b077aed3SPierre Pronchery                                       sig, siglen, prsactx->rsa);
728b077aed3SPierre Pronchery                 if (ret <= 0) {
729b077aed3SPierre Pronchery                     ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB);
730b077aed3SPierre Pronchery                     return 0;
731b077aed3SPierre Pronchery                 }
732b077aed3SPierre Pronchery                 ret = sltmp;
733b077aed3SPierre Pronchery             }
734b077aed3SPierre Pronchery             break;
735b077aed3SPierre Pronchery 
736b077aed3SPierre Pronchery         default:
737b077aed3SPierre Pronchery             ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE,
738b077aed3SPierre Pronchery                            "Only X.931 or PKCS#1 v1.5 padding allowed");
739b077aed3SPierre Pronchery             return 0;
740b077aed3SPierre Pronchery         }
741b077aed3SPierre Pronchery     } else {
742b077aed3SPierre Pronchery         ret = RSA_public_decrypt(siglen, sig, rout, prsactx->rsa,
743b077aed3SPierre Pronchery                                  prsactx->pad_mode);
744b077aed3SPierre Pronchery         if (ret < 0) {
745b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB);
746b077aed3SPierre Pronchery             return 0;
747b077aed3SPierre Pronchery         }
748b077aed3SPierre Pronchery     }
749b077aed3SPierre Pronchery     *routlen = ret;
750b077aed3SPierre Pronchery     return 1;
751b077aed3SPierre Pronchery }
752b077aed3SPierre Pronchery 
rsa_verify_init(void * vprsactx,void * vrsa,const OSSL_PARAM params[])753b077aed3SPierre Pronchery static int rsa_verify_init(void *vprsactx, void *vrsa,
754b077aed3SPierre Pronchery                            const OSSL_PARAM params[])
755b077aed3SPierre Pronchery {
756b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
757b077aed3SPierre Pronchery         return 0;
758b077aed3SPierre Pronchery     return rsa_signverify_init(vprsactx, vrsa, params, EVP_PKEY_OP_VERIFY);
759b077aed3SPierre Pronchery }
760b077aed3SPierre Pronchery 
rsa_verify(void * vprsactx,const unsigned char * sig,size_t siglen,const unsigned char * tbs,size_t tbslen)761b077aed3SPierre Pronchery static int rsa_verify(void *vprsactx, const unsigned char *sig, size_t siglen,
762b077aed3SPierre Pronchery                       const unsigned char *tbs, size_t tbslen)
763b077aed3SPierre Pronchery {
764b077aed3SPierre Pronchery     PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
765b077aed3SPierre Pronchery     size_t rslen;
766b077aed3SPierre Pronchery 
767b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
768b077aed3SPierre Pronchery         return 0;
769b077aed3SPierre Pronchery     if (prsactx->md != NULL) {
770b077aed3SPierre Pronchery         switch (prsactx->pad_mode) {
771b077aed3SPierre Pronchery         case RSA_PKCS1_PADDING:
772b077aed3SPierre Pronchery             if (!RSA_verify(prsactx->mdnid, tbs, tbslen, sig, siglen,
773b077aed3SPierre Pronchery                             prsactx->rsa)) {
774b077aed3SPierre Pronchery                 ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB);
775b077aed3SPierre Pronchery                 return 0;
776b077aed3SPierre Pronchery             }
777b077aed3SPierre Pronchery             return 1;
778b077aed3SPierre Pronchery         case RSA_X931_PADDING:
779b077aed3SPierre Pronchery             if (!setup_tbuf(prsactx))
780b077aed3SPierre Pronchery                 return 0;
781b077aed3SPierre Pronchery             if (rsa_verify_recover(prsactx, prsactx->tbuf, &rslen, 0,
782b077aed3SPierre Pronchery                                    sig, siglen) <= 0)
783b077aed3SPierre Pronchery                 return 0;
784b077aed3SPierre Pronchery             break;
785b077aed3SPierre Pronchery         case RSA_PKCS1_PSS_PADDING:
786b077aed3SPierre Pronchery             {
787b077aed3SPierre Pronchery                 int ret;
788b077aed3SPierre Pronchery                 size_t mdsize;
789b077aed3SPierre Pronchery 
790b077aed3SPierre Pronchery                 /*
791b077aed3SPierre Pronchery                  * We need to check this for the RSA_verify_PKCS1_PSS_mgf1()
792b077aed3SPierre Pronchery                  * call
793b077aed3SPierre Pronchery                  */
794b077aed3SPierre Pronchery                 mdsize = rsa_get_md_size(prsactx);
795b077aed3SPierre Pronchery                 if (tbslen != mdsize) {
796b077aed3SPierre Pronchery                     ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH,
797b077aed3SPierre Pronchery                                    "Should be %d, but got %d",
798b077aed3SPierre Pronchery                                    mdsize, tbslen);
799b077aed3SPierre Pronchery                     return 0;
800b077aed3SPierre Pronchery                 }
801b077aed3SPierre Pronchery 
802b077aed3SPierre Pronchery                 if (!setup_tbuf(prsactx))
803b077aed3SPierre Pronchery                     return 0;
804b077aed3SPierre Pronchery                 ret = RSA_public_decrypt(siglen, sig, prsactx->tbuf,
805b077aed3SPierre Pronchery                                          prsactx->rsa, RSA_NO_PADDING);
806b077aed3SPierre Pronchery                 if (ret <= 0) {
807b077aed3SPierre Pronchery                     ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB);
808b077aed3SPierre Pronchery                     return 0;
809b077aed3SPierre Pronchery                 }
810b077aed3SPierre Pronchery                 ret = RSA_verify_PKCS1_PSS_mgf1(prsactx->rsa, tbs,
811b077aed3SPierre Pronchery                                                 prsactx->md, prsactx->mgf1_md,
812b077aed3SPierre Pronchery                                                 prsactx->tbuf,
813b077aed3SPierre Pronchery                                                 prsactx->saltlen);
814b077aed3SPierre Pronchery                 if (ret <= 0) {
815b077aed3SPierre Pronchery                     ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB);
816b077aed3SPierre Pronchery                     return 0;
817b077aed3SPierre Pronchery                 }
818b077aed3SPierre Pronchery                 return 1;
819b077aed3SPierre Pronchery             }
820b077aed3SPierre Pronchery         default:
821b077aed3SPierre Pronchery             ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE,
822b077aed3SPierre Pronchery                            "Only X.931, PKCS#1 v1.5 or PSS padding allowed");
823b077aed3SPierre Pronchery             return 0;
824b077aed3SPierre Pronchery         }
825b077aed3SPierre Pronchery     } else {
826b077aed3SPierre Pronchery         int ret;
827b077aed3SPierre Pronchery 
828b077aed3SPierre Pronchery         if (!setup_tbuf(prsactx))
829b077aed3SPierre Pronchery             return 0;
830b077aed3SPierre Pronchery         ret = RSA_public_decrypt(siglen, sig, prsactx->tbuf, prsactx->rsa,
831b077aed3SPierre Pronchery                                  prsactx->pad_mode);
832b077aed3SPierre Pronchery         if (ret <= 0) {
833b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB);
834b077aed3SPierre Pronchery             return 0;
835b077aed3SPierre Pronchery         }
836b077aed3SPierre Pronchery         rslen = (size_t)ret;
837b077aed3SPierre Pronchery     }
838b077aed3SPierre Pronchery 
839b077aed3SPierre Pronchery     if ((rslen != tbslen) || memcmp(tbs, prsactx->tbuf, rslen))
840b077aed3SPierre Pronchery         return 0;
841b077aed3SPierre Pronchery 
842b077aed3SPierre Pronchery     return 1;
843b077aed3SPierre Pronchery }
844b077aed3SPierre Pronchery 
rsa_digest_signverify_init(void * vprsactx,const char * mdname,void * vrsa,const OSSL_PARAM params[],int operation)845b077aed3SPierre Pronchery static int rsa_digest_signverify_init(void *vprsactx, const char *mdname,
846b077aed3SPierre Pronchery                                       void *vrsa, const OSSL_PARAM params[],
847b077aed3SPierre Pronchery                                       int operation)
848b077aed3SPierre Pronchery {
849b077aed3SPierre Pronchery     PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
850b077aed3SPierre Pronchery 
851b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
852b077aed3SPierre Pronchery         return 0;
853b077aed3SPierre Pronchery 
854b077aed3SPierre Pronchery     if (!rsa_signverify_init(vprsactx, vrsa, params, operation))
855b077aed3SPierre Pronchery         return 0;
856b077aed3SPierre Pronchery 
857b077aed3SPierre Pronchery     if (mdname != NULL
858b077aed3SPierre Pronchery         /* was rsa_setup_md already called in rsa_signverify_init()? */
859b077aed3SPierre Pronchery         && (mdname[0] == '\0' || OPENSSL_strcasecmp(prsactx->mdname, mdname) != 0)
860b077aed3SPierre Pronchery         && !rsa_setup_md(prsactx, mdname, prsactx->propq))
861b077aed3SPierre Pronchery         return 0;
862b077aed3SPierre Pronchery 
863b077aed3SPierre Pronchery     prsactx->flag_allow_md = 0;
864b077aed3SPierre Pronchery 
865b077aed3SPierre Pronchery     if (prsactx->mdctx == NULL) {
866b077aed3SPierre Pronchery         prsactx->mdctx = EVP_MD_CTX_new();
867b077aed3SPierre Pronchery         if (prsactx->mdctx == NULL)
868b077aed3SPierre Pronchery             goto error;
869b077aed3SPierre Pronchery     }
870b077aed3SPierre Pronchery 
871b077aed3SPierre Pronchery     if (!EVP_DigestInit_ex2(prsactx->mdctx, prsactx->md, params))
872b077aed3SPierre Pronchery         goto error;
873b077aed3SPierre Pronchery 
874b077aed3SPierre Pronchery     return 1;
875b077aed3SPierre Pronchery 
876b077aed3SPierre Pronchery  error:
877b077aed3SPierre Pronchery     EVP_MD_CTX_free(prsactx->mdctx);
878b077aed3SPierre Pronchery     prsactx->mdctx = NULL;
879b077aed3SPierre Pronchery     return 0;
880b077aed3SPierre Pronchery }
881b077aed3SPierre Pronchery 
rsa_digest_signverify_update(void * vprsactx,const unsigned char * data,size_t datalen)882b077aed3SPierre Pronchery static int rsa_digest_signverify_update(void *vprsactx,
883b077aed3SPierre Pronchery                                         const unsigned char *data,
884b077aed3SPierre Pronchery                                         size_t datalen)
885b077aed3SPierre Pronchery {
886b077aed3SPierre Pronchery     PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
887b077aed3SPierre Pronchery 
888b077aed3SPierre Pronchery     if (prsactx == NULL || prsactx->mdctx == NULL)
889b077aed3SPierre Pronchery         return 0;
890b077aed3SPierre Pronchery 
891b077aed3SPierre Pronchery     return EVP_DigestUpdate(prsactx->mdctx, data, datalen);
892b077aed3SPierre Pronchery }
893b077aed3SPierre Pronchery 
rsa_digest_sign_init(void * vprsactx,const char * mdname,void * vrsa,const OSSL_PARAM params[])894b077aed3SPierre Pronchery static int rsa_digest_sign_init(void *vprsactx, const char *mdname,
895b077aed3SPierre Pronchery                                 void *vrsa, const OSSL_PARAM params[])
896b077aed3SPierre Pronchery {
897b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
898b077aed3SPierre Pronchery         return 0;
899b077aed3SPierre Pronchery     return rsa_digest_signverify_init(vprsactx, mdname, vrsa,
900b077aed3SPierre Pronchery                                       params, EVP_PKEY_OP_SIGN);
901b077aed3SPierre Pronchery }
902b077aed3SPierre Pronchery 
rsa_digest_sign_final(void * vprsactx,unsigned char * sig,size_t * siglen,size_t sigsize)903b077aed3SPierre Pronchery static int rsa_digest_sign_final(void *vprsactx, unsigned char *sig,
904b077aed3SPierre Pronchery                                  size_t *siglen, size_t sigsize)
905b077aed3SPierre Pronchery {
906b077aed3SPierre Pronchery     PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
907b077aed3SPierre Pronchery     unsigned char digest[EVP_MAX_MD_SIZE];
908b077aed3SPierre Pronchery     unsigned int dlen = 0;
909b077aed3SPierre Pronchery 
910b077aed3SPierre Pronchery     if (!ossl_prov_is_running() || prsactx == NULL)
911b077aed3SPierre Pronchery         return 0;
912b077aed3SPierre Pronchery     prsactx->flag_allow_md = 1;
913b077aed3SPierre Pronchery     if (prsactx->mdctx == NULL)
914b077aed3SPierre Pronchery         return 0;
915b077aed3SPierre Pronchery     /*
916b077aed3SPierre Pronchery      * If sig is NULL then we're just finding out the sig size. Other fields
917b077aed3SPierre Pronchery      * are ignored. Defer to rsa_sign.
918b077aed3SPierre Pronchery      */
919b077aed3SPierre Pronchery     if (sig != NULL) {
920b077aed3SPierre Pronchery         /*
921b077aed3SPierre Pronchery          * The digests used here are all known (see rsa_get_md_nid()), so they
922b077aed3SPierre Pronchery          * should not exceed the internal buffer size of EVP_MAX_MD_SIZE.
923b077aed3SPierre Pronchery          */
924b077aed3SPierre Pronchery         if (!EVP_DigestFinal_ex(prsactx->mdctx, digest, &dlen))
925b077aed3SPierre Pronchery             return 0;
926b077aed3SPierre Pronchery     }
927b077aed3SPierre Pronchery 
928b077aed3SPierre Pronchery     return rsa_sign(vprsactx, sig, siglen, sigsize, digest, (size_t)dlen);
929b077aed3SPierre Pronchery }
930b077aed3SPierre Pronchery 
rsa_digest_verify_init(void * vprsactx,const char * mdname,void * vrsa,const OSSL_PARAM params[])931b077aed3SPierre Pronchery static int rsa_digest_verify_init(void *vprsactx, const char *mdname,
932b077aed3SPierre Pronchery                                   void *vrsa, const OSSL_PARAM params[])
933b077aed3SPierre Pronchery {
934b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
935b077aed3SPierre Pronchery         return 0;
936b077aed3SPierre Pronchery     return rsa_digest_signverify_init(vprsactx, mdname, vrsa,
937b077aed3SPierre Pronchery                                       params, EVP_PKEY_OP_VERIFY);
938b077aed3SPierre Pronchery }
939b077aed3SPierre Pronchery 
rsa_digest_verify_final(void * vprsactx,const unsigned char * sig,size_t siglen)940b077aed3SPierre Pronchery int rsa_digest_verify_final(void *vprsactx, const unsigned char *sig,
941b077aed3SPierre Pronchery                             size_t siglen)
942b077aed3SPierre Pronchery {
943b077aed3SPierre Pronchery     PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
944b077aed3SPierre Pronchery     unsigned char digest[EVP_MAX_MD_SIZE];
945b077aed3SPierre Pronchery     unsigned int dlen = 0;
946b077aed3SPierre Pronchery 
947b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
948b077aed3SPierre Pronchery         return 0;
949b077aed3SPierre Pronchery 
950b077aed3SPierre Pronchery     if (prsactx == NULL)
951b077aed3SPierre Pronchery         return 0;
952b077aed3SPierre Pronchery     prsactx->flag_allow_md = 1;
953b077aed3SPierre Pronchery     if (prsactx->mdctx == NULL)
954b077aed3SPierre Pronchery         return 0;
955b077aed3SPierre Pronchery 
956b077aed3SPierre Pronchery     /*
957b077aed3SPierre Pronchery      * The digests used here are all known (see rsa_get_md_nid()), so they
958b077aed3SPierre Pronchery      * should not exceed the internal buffer size of EVP_MAX_MD_SIZE.
959b077aed3SPierre Pronchery      */
960b077aed3SPierre Pronchery     if (!EVP_DigestFinal_ex(prsactx->mdctx, digest, &dlen))
961b077aed3SPierre Pronchery         return 0;
962b077aed3SPierre Pronchery 
963b077aed3SPierre Pronchery     return rsa_verify(vprsactx, sig, siglen, digest, (size_t)dlen);
964b077aed3SPierre Pronchery }
965b077aed3SPierre Pronchery 
rsa_freectx(void * vprsactx)966b077aed3SPierre Pronchery static void rsa_freectx(void *vprsactx)
967b077aed3SPierre Pronchery {
968b077aed3SPierre Pronchery     PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
969b077aed3SPierre Pronchery 
970b077aed3SPierre Pronchery     if (prsactx == NULL)
971b077aed3SPierre Pronchery         return;
972b077aed3SPierre Pronchery 
973b077aed3SPierre Pronchery     EVP_MD_CTX_free(prsactx->mdctx);
974b077aed3SPierre Pronchery     EVP_MD_free(prsactx->md);
975b077aed3SPierre Pronchery     EVP_MD_free(prsactx->mgf1_md);
976b077aed3SPierre Pronchery     OPENSSL_free(prsactx->propq);
977b077aed3SPierre Pronchery     free_tbuf(prsactx);
978b077aed3SPierre Pronchery     RSA_free(prsactx->rsa);
979b077aed3SPierre Pronchery 
980b077aed3SPierre Pronchery     OPENSSL_clear_free(prsactx, sizeof(*prsactx));
981b077aed3SPierre Pronchery }
982b077aed3SPierre Pronchery 
rsa_dupctx(void * vprsactx)983b077aed3SPierre Pronchery static void *rsa_dupctx(void *vprsactx)
984b077aed3SPierre Pronchery {
985b077aed3SPierre Pronchery     PROV_RSA_CTX *srcctx = (PROV_RSA_CTX *)vprsactx;
986b077aed3SPierre Pronchery     PROV_RSA_CTX *dstctx;
987b077aed3SPierre Pronchery 
988b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
989b077aed3SPierre Pronchery         return NULL;
990b077aed3SPierre Pronchery 
991b077aed3SPierre Pronchery     dstctx = OPENSSL_zalloc(sizeof(*srcctx));
992b077aed3SPierre Pronchery     if (dstctx == NULL) {
993b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
994b077aed3SPierre Pronchery         return NULL;
995b077aed3SPierre Pronchery     }
996b077aed3SPierre Pronchery 
997b077aed3SPierre Pronchery     *dstctx = *srcctx;
998b077aed3SPierre Pronchery     dstctx->rsa = NULL;
999b077aed3SPierre Pronchery     dstctx->md = NULL;
1000*e0c4386eSCy Schubert     dstctx->mgf1_md = NULL;
1001b077aed3SPierre Pronchery     dstctx->mdctx = NULL;
1002b077aed3SPierre Pronchery     dstctx->tbuf = NULL;
1003b077aed3SPierre Pronchery     dstctx->propq = NULL;
1004b077aed3SPierre Pronchery 
1005b077aed3SPierre Pronchery     if (srcctx->rsa != NULL && !RSA_up_ref(srcctx->rsa))
1006b077aed3SPierre Pronchery         goto err;
1007b077aed3SPierre Pronchery     dstctx->rsa = srcctx->rsa;
1008b077aed3SPierre Pronchery 
1009b077aed3SPierre Pronchery     if (srcctx->md != NULL && !EVP_MD_up_ref(srcctx->md))
1010b077aed3SPierre Pronchery         goto err;
1011b077aed3SPierre Pronchery     dstctx->md = srcctx->md;
1012b077aed3SPierre Pronchery 
1013b077aed3SPierre Pronchery     if (srcctx->mgf1_md != NULL && !EVP_MD_up_ref(srcctx->mgf1_md))
1014b077aed3SPierre Pronchery         goto err;
1015b077aed3SPierre Pronchery     dstctx->mgf1_md = srcctx->mgf1_md;
1016b077aed3SPierre Pronchery 
1017b077aed3SPierre Pronchery     if (srcctx->mdctx != NULL) {
1018b077aed3SPierre Pronchery         dstctx->mdctx = EVP_MD_CTX_new();
1019b077aed3SPierre Pronchery         if (dstctx->mdctx == NULL
1020b077aed3SPierre Pronchery                 || !EVP_MD_CTX_copy_ex(dstctx->mdctx, srcctx->mdctx))
1021b077aed3SPierre Pronchery             goto err;
1022b077aed3SPierre Pronchery     }
1023b077aed3SPierre Pronchery 
1024b077aed3SPierre Pronchery     if (srcctx->propq != NULL) {
1025b077aed3SPierre Pronchery         dstctx->propq = OPENSSL_strdup(srcctx->propq);
1026b077aed3SPierre Pronchery         if (dstctx->propq == NULL)
1027b077aed3SPierre Pronchery             goto err;
1028b077aed3SPierre Pronchery     }
1029b077aed3SPierre Pronchery 
1030b077aed3SPierre Pronchery     return dstctx;
1031b077aed3SPierre Pronchery  err:
1032b077aed3SPierre Pronchery     rsa_freectx(dstctx);
1033b077aed3SPierre Pronchery     return NULL;
1034b077aed3SPierre Pronchery }
1035b077aed3SPierre Pronchery 
rsa_get_ctx_params(void * vprsactx,OSSL_PARAM * params)1036b077aed3SPierre Pronchery static int rsa_get_ctx_params(void *vprsactx, OSSL_PARAM *params)
1037b077aed3SPierre Pronchery {
1038b077aed3SPierre Pronchery     PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
1039b077aed3SPierre Pronchery     OSSL_PARAM *p;
1040b077aed3SPierre Pronchery 
1041b077aed3SPierre Pronchery     if (prsactx == NULL)
1042b077aed3SPierre Pronchery         return 0;
1043b077aed3SPierre Pronchery 
1044b077aed3SPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID);
1045b077aed3SPierre Pronchery     if (p != NULL) {
1046b077aed3SPierre Pronchery         /* The Algorithm Identifier of the combined signature algorithm */
1047b077aed3SPierre Pronchery         unsigned char aid_buf[128];
1048b077aed3SPierre Pronchery         unsigned char *aid;
1049b077aed3SPierre Pronchery         size_t  aid_len;
1050b077aed3SPierre Pronchery 
1051b077aed3SPierre Pronchery         aid = rsa_generate_signature_aid(prsactx, aid_buf,
1052b077aed3SPierre Pronchery                                          sizeof(aid_buf), &aid_len);
1053b077aed3SPierre Pronchery         if (aid == NULL || !OSSL_PARAM_set_octet_string(p, aid, aid_len))
1054b077aed3SPierre Pronchery             return 0;
1055b077aed3SPierre Pronchery     }
1056b077aed3SPierre Pronchery 
1057b077aed3SPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_PAD_MODE);
1058b077aed3SPierre Pronchery     if (p != NULL)
1059b077aed3SPierre Pronchery         switch (p->data_type) {
1060b077aed3SPierre Pronchery         case OSSL_PARAM_INTEGER:
1061b077aed3SPierre Pronchery             if (!OSSL_PARAM_set_int(p, prsactx->pad_mode))
1062b077aed3SPierre Pronchery                 return 0;
1063b077aed3SPierre Pronchery             break;
1064b077aed3SPierre Pronchery         case OSSL_PARAM_UTF8_STRING:
1065b077aed3SPierre Pronchery             {
1066b077aed3SPierre Pronchery                 int i;
1067b077aed3SPierre Pronchery                 const char *word = NULL;
1068b077aed3SPierre Pronchery 
1069b077aed3SPierre Pronchery                 for (i = 0; padding_item[i].id != 0; i++) {
1070b077aed3SPierre Pronchery                     if (prsactx->pad_mode == (int)padding_item[i].id) {
1071b077aed3SPierre Pronchery                         word = padding_item[i].ptr;
1072b077aed3SPierre Pronchery                         break;
1073b077aed3SPierre Pronchery                     }
1074b077aed3SPierre Pronchery                 }
1075b077aed3SPierre Pronchery 
1076b077aed3SPierre Pronchery                 if (word != NULL) {
1077b077aed3SPierre Pronchery                     if (!OSSL_PARAM_set_utf8_string(p, word))
1078b077aed3SPierre Pronchery                         return 0;
1079b077aed3SPierre Pronchery                 } else {
1080b077aed3SPierre Pronchery                     ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
1081b077aed3SPierre Pronchery                 }
1082b077aed3SPierre Pronchery             }
1083b077aed3SPierre Pronchery             break;
1084b077aed3SPierre Pronchery         default:
1085b077aed3SPierre Pronchery             return 0;
1086b077aed3SPierre Pronchery         }
1087b077aed3SPierre Pronchery 
1088b077aed3SPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST);
1089b077aed3SPierre Pronchery     if (p != NULL && !OSSL_PARAM_set_utf8_string(p, prsactx->mdname))
1090b077aed3SPierre Pronchery         return 0;
1091b077aed3SPierre Pronchery 
1092b077aed3SPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_MGF1_DIGEST);
1093b077aed3SPierre Pronchery     if (p != NULL && !OSSL_PARAM_set_utf8_string(p, prsactx->mgf1_mdname))
1094b077aed3SPierre Pronchery         return 0;
1095b077aed3SPierre Pronchery 
1096b077aed3SPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_PSS_SALTLEN);
1097b077aed3SPierre Pronchery     if (p != NULL) {
1098b077aed3SPierre Pronchery         if (p->data_type == OSSL_PARAM_INTEGER) {
1099b077aed3SPierre Pronchery             if (!OSSL_PARAM_set_int(p, prsactx->saltlen))
1100b077aed3SPierre Pronchery                 return 0;
1101b077aed3SPierre Pronchery         } else if (p->data_type == OSSL_PARAM_UTF8_STRING) {
1102b077aed3SPierre Pronchery             const char *value = NULL;
1103b077aed3SPierre Pronchery 
1104b077aed3SPierre Pronchery             switch (prsactx->saltlen) {
1105b077aed3SPierre Pronchery             case RSA_PSS_SALTLEN_DIGEST:
1106b077aed3SPierre Pronchery                 value = OSSL_PKEY_RSA_PSS_SALT_LEN_DIGEST;
1107b077aed3SPierre Pronchery                 break;
1108b077aed3SPierre Pronchery             case RSA_PSS_SALTLEN_MAX:
1109b077aed3SPierre Pronchery                 value = OSSL_PKEY_RSA_PSS_SALT_LEN_MAX;
1110b077aed3SPierre Pronchery                 break;
1111b077aed3SPierre Pronchery             case RSA_PSS_SALTLEN_AUTO:
1112b077aed3SPierre Pronchery                 value = OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO;
1113b077aed3SPierre Pronchery                 break;
1114b077aed3SPierre Pronchery             default:
1115b077aed3SPierre Pronchery                 {
1116b077aed3SPierre Pronchery                     int len = BIO_snprintf(p->data, p->data_size, "%d",
1117b077aed3SPierre Pronchery                                            prsactx->saltlen);
1118b077aed3SPierre Pronchery 
1119b077aed3SPierre Pronchery                     if (len <= 0)
1120b077aed3SPierre Pronchery                         return 0;
1121b077aed3SPierre Pronchery                     p->return_size = len;
1122b077aed3SPierre Pronchery                     break;
1123b077aed3SPierre Pronchery                 }
1124b077aed3SPierre Pronchery             }
1125b077aed3SPierre Pronchery             if (value != NULL
1126b077aed3SPierre Pronchery                 && !OSSL_PARAM_set_utf8_string(p, value))
1127b077aed3SPierre Pronchery                 return 0;
1128b077aed3SPierre Pronchery         }
1129b077aed3SPierre Pronchery     }
1130b077aed3SPierre Pronchery 
1131b077aed3SPierre Pronchery     return 1;
1132b077aed3SPierre Pronchery }
1133b077aed3SPierre Pronchery 
1134b077aed3SPierre Pronchery static const OSSL_PARAM known_gettable_ctx_params[] = {
1135b077aed3SPierre Pronchery     OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0),
1136b077aed3SPierre Pronchery     OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PAD_MODE, NULL, 0),
1137b077aed3SPierre Pronchery     OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0),
1138b077aed3SPierre Pronchery     OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_DIGEST, NULL, 0),
1139b077aed3SPierre Pronchery     OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, NULL, 0),
1140b077aed3SPierre Pronchery     OSSL_PARAM_END
1141b077aed3SPierre Pronchery };
1142b077aed3SPierre Pronchery 
rsa_gettable_ctx_params(ossl_unused void * vprsactx,ossl_unused void * provctx)1143b077aed3SPierre Pronchery static const OSSL_PARAM *rsa_gettable_ctx_params(ossl_unused void *vprsactx,
1144b077aed3SPierre Pronchery                                                  ossl_unused void *provctx)
1145b077aed3SPierre Pronchery {
1146b077aed3SPierre Pronchery     return known_gettable_ctx_params;
1147b077aed3SPierre Pronchery }
1148b077aed3SPierre Pronchery 
rsa_set_ctx_params(void * vprsactx,const OSSL_PARAM params[])1149b077aed3SPierre Pronchery static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[])
1150b077aed3SPierre Pronchery {
1151b077aed3SPierre Pronchery     PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
1152b077aed3SPierre Pronchery     const OSSL_PARAM *p;
1153b077aed3SPierre Pronchery     int pad_mode;
1154b077aed3SPierre Pronchery     int saltlen;
1155b077aed3SPierre Pronchery     char mdname[OSSL_MAX_NAME_SIZE] = "", *pmdname = NULL;
1156b077aed3SPierre Pronchery     char mdprops[OSSL_MAX_PROPQUERY_SIZE] = "", *pmdprops = NULL;
1157b077aed3SPierre Pronchery     char mgf1mdname[OSSL_MAX_NAME_SIZE] = "", *pmgf1mdname = NULL;
1158b077aed3SPierre Pronchery     char mgf1mdprops[OSSL_MAX_PROPQUERY_SIZE] = "", *pmgf1mdprops = NULL;
1159b077aed3SPierre Pronchery 
1160b077aed3SPierre Pronchery     if (prsactx == NULL)
1161b077aed3SPierre Pronchery         return 0;
1162b077aed3SPierre Pronchery     if (params == NULL)
1163b077aed3SPierre Pronchery         return 1;
1164b077aed3SPierre Pronchery 
1165b077aed3SPierre Pronchery     pad_mode = prsactx->pad_mode;
1166b077aed3SPierre Pronchery     saltlen = prsactx->saltlen;
1167b077aed3SPierre Pronchery 
1168b077aed3SPierre Pronchery     p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST);
1169b077aed3SPierre Pronchery     if (p != NULL) {
1170b077aed3SPierre Pronchery         const OSSL_PARAM *propsp =
1171b077aed3SPierre Pronchery             OSSL_PARAM_locate_const(params,
1172b077aed3SPierre Pronchery                                     OSSL_SIGNATURE_PARAM_PROPERTIES);
1173b077aed3SPierre Pronchery 
1174b077aed3SPierre Pronchery         pmdname = mdname;
1175b077aed3SPierre Pronchery         if (!OSSL_PARAM_get_utf8_string(p, &pmdname, sizeof(mdname)))
1176b077aed3SPierre Pronchery             return 0;
1177b077aed3SPierre Pronchery 
1178b077aed3SPierre Pronchery         if (propsp != NULL) {
1179b077aed3SPierre Pronchery             pmdprops = mdprops;
1180b077aed3SPierre Pronchery             if (!OSSL_PARAM_get_utf8_string(propsp,
1181b077aed3SPierre Pronchery                                             &pmdprops, sizeof(mdprops)))
1182b077aed3SPierre Pronchery                 return 0;
1183b077aed3SPierre Pronchery         }
1184b077aed3SPierre Pronchery     }
1185b077aed3SPierre Pronchery 
1186b077aed3SPierre Pronchery     p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_PAD_MODE);
1187b077aed3SPierre Pronchery     if (p != NULL) {
1188b077aed3SPierre Pronchery         const char *err_extra_text = NULL;
1189b077aed3SPierre Pronchery 
1190b077aed3SPierre Pronchery         switch (p->data_type) {
1191b077aed3SPierre Pronchery         case OSSL_PARAM_INTEGER: /* Support for legacy pad mode number */
1192b077aed3SPierre Pronchery             if (!OSSL_PARAM_get_int(p, &pad_mode))
1193b077aed3SPierre Pronchery                 return 0;
1194b077aed3SPierre Pronchery             break;
1195b077aed3SPierre Pronchery         case OSSL_PARAM_UTF8_STRING:
1196b077aed3SPierre Pronchery             {
1197b077aed3SPierre Pronchery                 int i;
1198b077aed3SPierre Pronchery 
1199b077aed3SPierre Pronchery                 if (p->data == NULL)
1200b077aed3SPierre Pronchery                     return 0;
1201b077aed3SPierre Pronchery 
1202b077aed3SPierre Pronchery                 for (i = 0; padding_item[i].id != 0; i++) {
1203b077aed3SPierre Pronchery                     if (strcmp(p->data, padding_item[i].ptr) == 0) {
1204b077aed3SPierre Pronchery                         pad_mode = padding_item[i].id;
1205b077aed3SPierre Pronchery                         break;
1206b077aed3SPierre Pronchery                     }
1207b077aed3SPierre Pronchery                 }
1208b077aed3SPierre Pronchery             }
1209b077aed3SPierre Pronchery             break;
1210b077aed3SPierre Pronchery         default:
1211b077aed3SPierre Pronchery             return 0;
1212b077aed3SPierre Pronchery         }
1213b077aed3SPierre Pronchery 
1214b077aed3SPierre Pronchery         switch (pad_mode) {
1215b077aed3SPierre Pronchery         case RSA_PKCS1_OAEP_PADDING:
1216b077aed3SPierre Pronchery             /*
1217b077aed3SPierre Pronchery              * OAEP padding is for asymmetric cipher only so is not compatible
1218b077aed3SPierre Pronchery              * with signature use.
1219b077aed3SPierre Pronchery              */
1220b077aed3SPierre Pronchery             err_extra_text = "OAEP padding not allowed for signing / verifying";
1221b077aed3SPierre Pronchery             goto bad_pad;
1222b077aed3SPierre Pronchery         case RSA_PKCS1_PSS_PADDING:
1223b077aed3SPierre Pronchery             if ((prsactx->operation
1224b077aed3SPierre Pronchery                  & (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY)) == 0) {
1225b077aed3SPierre Pronchery                 err_extra_text =
1226b077aed3SPierre Pronchery                     "PSS padding only allowed for sign and verify operations";
1227b077aed3SPierre Pronchery                 goto bad_pad;
1228b077aed3SPierre Pronchery             }
1229b077aed3SPierre Pronchery             break;
1230b077aed3SPierre Pronchery         case RSA_PKCS1_PADDING:
1231b077aed3SPierre Pronchery             err_extra_text = "PKCS#1 padding not allowed with RSA-PSS";
1232b077aed3SPierre Pronchery             goto cont;
1233b077aed3SPierre Pronchery         case RSA_NO_PADDING:
1234b077aed3SPierre Pronchery             err_extra_text = "No padding not allowed with RSA-PSS";
1235b077aed3SPierre Pronchery             goto cont;
1236b077aed3SPierre Pronchery         case RSA_X931_PADDING:
1237b077aed3SPierre Pronchery             err_extra_text = "X.931 padding not allowed with RSA-PSS";
1238b077aed3SPierre Pronchery         cont:
1239b077aed3SPierre Pronchery             if (RSA_test_flags(prsactx->rsa,
1240b077aed3SPierre Pronchery                                RSA_FLAG_TYPE_MASK) == RSA_FLAG_TYPE_RSA)
1241b077aed3SPierre Pronchery                 break;
1242b077aed3SPierre Pronchery             /* FALLTHRU */
1243b077aed3SPierre Pronchery         default:
1244b077aed3SPierre Pronchery         bad_pad:
1245b077aed3SPierre Pronchery             if (err_extra_text == NULL)
1246b077aed3SPierre Pronchery                 ERR_raise(ERR_LIB_PROV,
1247b077aed3SPierre Pronchery                           PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE);
1248b077aed3SPierre Pronchery             else
1249b077aed3SPierre Pronchery                 ERR_raise_data(ERR_LIB_PROV,
1250b077aed3SPierre Pronchery                                PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE,
1251b077aed3SPierre Pronchery                                err_extra_text);
1252b077aed3SPierre Pronchery             return 0;
1253b077aed3SPierre Pronchery         }
1254b077aed3SPierre Pronchery     }
1255b077aed3SPierre Pronchery 
1256b077aed3SPierre Pronchery     p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_PSS_SALTLEN);
1257b077aed3SPierre Pronchery     if (p != NULL) {
1258b077aed3SPierre Pronchery         if (pad_mode != RSA_PKCS1_PSS_PADDING) {
1259b077aed3SPierre Pronchery             ERR_raise_data(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED,
1260b077aed3SPierre Pronchery                            "PSS saltlen can only be specified if "
1261b077aed3SPierre Pronchery                            "PSS padding has been specified first");
1262b077aed3SPierre Pronchery             return 0;
1263b077aed3SPierre Pronchery         }
1264b077aed3SPierre Pronchery 
1265b077aed3SPierre Pronchery         switch (p->data_type) {
1266b077aed3SPierre Pronchery         case OSSL_PARAM_INTEGER: /* Support for legacy pad mode number */
1267b077aed3SPierre Pronchery             if (!OSSL_PARAM_get_int(p, &saltlen))
1268b077aed3SPierre Pronchery                 return 0;
1269b077aed3SPierre Pronchery             break;
1270b077aed3SPierre Pronchery         case OSSL_PARAM_UTF8_STRING:
1271b077aed3SPierre Pronchery             if (strcmp(p->data, OSSL_PKEY_RSA_PSS_SALT_LEN_DIGEST) == 0)
1272b077aed3SPierre Pronchery                 saltlen = RSA_PSS_SALTLEN_DIGEST;
1273b077aed3SPierre Pronchery             else if (strcmp(p->data, OSSL_PKEY_RSA_PSS_SALT_LEN_MAX) == 0)
1274b077aed3SPierre Pronchery                 saltlen = RSA_PSS_SALTLEN_MAX;
1275b077aed3SPierre Pronchery             else if (strcmp(p->data, OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO) == 0)
1276b077aed3SPierre Pronchery                 saltlen = RSA_PSS_SALTLEN_AUTO;
1277b077aed3SPierre Pronchery             else
1278b077aed3SPierre Pronchery                 saltlen = atoi(p->data);
1279b077aed3SPierre Pronchery             break;
1280b077aed3SPierre Pronchery         default:
1281b077aed3SPierre Pronchery             return 0;
1282b077aed3SPierre Pronchery         }
1283b077aed3SPierre Pronchery 
1284b077aed3SPierre Pronchery         /*
1285b077aed3SPierre Pronchery          * RSA_PSS_SALTLEN_MAX seems curiously named in this check.
1286b077aed3SPierre Pronchery          * Contrary to what it's name suggests, it's the currently
1287b077aed3SPierre Pronchery          * lowest saltlen number possible.
1288b077aed3SPierre Pronchery          */
1289b077aed3SPierre Pronchery         if (saltlen < RSA_PSS_SALTLEN_MAX) {
1290b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH);
1291b077aed3SPierre Pronchery             return 0;
1292b077aed3SPierre Pronchery         }
1293b077aed3SPierre Pronchery 
1294b077aed3SPierre Pronchery         if (rsa_pss_restricted(prsactx)) {
1295b077aed3SPierre Pronchery             switch (saltlen) {
1296b077aed3SPierre Pronchery             case RSA_PSS_SALTLEN_AUTO:
1297b077aed3SPierre Pronchery                 if (prsactx->operation == EVP_PKEY_OP_VERIFY) {
1298b077aed3SPierre Pronchery                     ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH,
1299b077aed3SPierre Pronchery                                    "Cannot use autodetected salt length");
1300b077aed3SPierre Pronchery                     return 0;
1301b077aed3SPierre Pronchery                 }
1302b077aed3SPierre Pronchery                 break;
1303b077aed3SPierre Pronchery             case RSA_PSS_SALTLEN_DIGEST:
1304b077aed3SPierre Pronchery                 if (prsactx->min_saltlen > EVP_MD_get_size(prsactx->md)) {
1305b077aed3SPierre Pronchery                     ERR_raise_data(ERR_LIB_PROV,
1306b077aed3SPierre Pronchery                                    PROV_R_PSS_SALTLEN_TOO_SMALL,
1307b077aed3SPierre Pronchery                                    "Should be more than %d, but would be "
1308b077aed3SPierre Pronchery                                    "set to match digest size (%d)",
1309b077aed3SPierre Pronchery                                    prsactx->min_saltlen,
1310b077aed3SPierre Pronchery                                    EVP_MD_get_size(prsactx->md));
1311b077aed3SPierre Pronchery                     return 0;
1312b077aed3SPierre Pronchery                 }
1313b077aed3SPierre Pronchery                 break;
1314b077aed3SPierre Pronchery             default:
1315b077aed3SPierre Pronchery                 if (saltlen >= 0 && saltlen < prsactx->min_saltlen) {
1316b077aed3SPierre Pronchery                     ERR_raise_data(ERR_LIB_PROV,
1317b077aed3SPierre Pronchery                                    PROV_R_PSS_SALTLEN_TOO_SMALL,
1318b077aed3SPierre Pronchery                                    "Should be more than %d, "
1319b077aed3SPierre Pronchery                                    "but would be set to %d",
1320b077aed3SPierre Pronchery                                    prsactx->min_saltlen, saltlen);
1321b077aed3SPierre Pronchery                     return 0;
1322b077aed3SPierre Pronchery                 }
1323b077aed3SPierre Pronchery             }
1324b077aed3SPierre Pronchery         }
1325b077aed3SPierre Pronchery     }
1326b077aed3SPierre Pronchery 
1327b077aed3SPierre Pronchery     p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_MGF1_DIGEST);
1328b077aed3SPierre Pronchery     if (p != NULL) {
1329b077aed3SPierre Pronchery         const OSSL_PARAM *propsp =
1330b077aed3SPierre Pronchery             OSSL_PARAM_locate_const(params,
1331b077aed3SPierre Pronchery                                     OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES);
1332b077aed3SPierre Pronchery 
1333b077aed3SPierre Pronchery         pmgf1mdname = mgf1mdname;
1334b077aed3SPierre Pronchery         if (!OSSL_PARAM_get_utf8_string(p, &pmgf1mdname, sizeof(mgf1mdname)))
1335b077aed3SPierre Pronchery             return 0;
1336b077aed3SPierre Pronchery 
1337b077aed3SPierre Pronchery         if (propsp != NULL) {
1338b077aed3SPierre Pronchery             pmgf1mdprops = mgf1mdprops;
1339b077aed3SPierre Pronchery             if (!OSSL_PARAM_get_utf8_string(propsp,
1340b077aed3SPierre Pronchery                                             &pmgf1mdprops, sizeof(mgf1mdprops)))
1341b077aed3SPierre Pronchery                 return 0;
1342b077aed3SPierre Pronchery         }
1343b077aed3SPierre Pronchery 
1344b077aed3SPierre Pronchery         if (pad_mode != RSA_PKCS1_PSS_PADDING) {
1345b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MGF1_MD);
1346b077aed3SPierre Pronchery             return  0;
1347b077aed3SPierre Pronchery         }
1348b077aed3SPierre Pronchery     }
1349b077aed3SPierre Pronchery 
1350b077aed3SPierre Pronchery     prsactx->saltlen = saltlen;
1351b077aed3SPierre Pronchery     prsactx->pad_mode = pad_mode;
1352b077aed3SPierre Pronchery 
1353b077aed3SPierre Pronchery     if (prsactx->md == NULL && pmdname == NULL
1354b077aed3SPierre Pronchery         && pad_mode == RSA_PKCS1_PSS_PADDING)
1355b077aed3SPierre Pronchery         pmdname = RSA_DEFAULT_DIGEST_NAME;
1356b077aed3SPierre Pronchery 
1357b077aed3SPierre Pronchery     if (pmgf1mdname != NULL
1358b077aed3SPierre Pronchery         && !rsa_setup_mgf1_md(prsactx, pmgf1mdname, pmgf1mdprops))
1359b077aed3SPierre Pronchery         return 0;
1360b077aed3SPierre Pronchery 
1361b077aed3SPierre Pronchery     if (pmdname != NULL) {
1362b077aed3SPierre Pronchery         if (!rsa_setup_md(prsactx, pmdname, pmdprops))
1363b077aed3SPierre Pronchery             return 0;
1364b077aed3SPierre Pronchery     } else {
1365b077aed3SPierre Pronchery         if (!rsa_check_padding(prsactx, NULL, NULL, prsactx->mdnid))
1366b077aed3SPierre Pronchery             return 0;
1367b077aed3SPierre Pronchery     }
1368b077aed3SPierre Pronchery     return 1;
1369b077aed3SPierre Pronchery }
1370b077aed3SPierre Pronchery 
1371b077aed3SPierre Pronchery static const OSSL_PARAM settable_ctx_params[] = {
1372b077aed3SPierre Pronchery     OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0),
1373b077aed3SPierre Pronchery     OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PROPERTIES, NULL, 0),
1374b077aed3SPierre Pronchery     OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PAD_MODE, NULL, 0),
1375b077aed3SPierre Pronchery     OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_DIGEST, NULL, 0),
1376b077aed3SPierre Pronchery     OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES, NULL, 0),
1377b077aed3SPierre Pronchery     OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, NULL, 0),
1378b077aed3SPierre Pronchery     OSSL_PARAM_END
1379b077aed3SPierre Pronchery };
1380b077aed3SPierre Pronchery 
1381b077aed3SPierre Pronchery static const OSSL_PARAM settable_ctx_params_no_digest[] = {
1382b077aed3SPierre Pronchery     OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PAD_MODE, NULL, 0),
1383b077aed3SPierre Pronchery     OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_DIGEST, NULL, 0),
1384b077aed3SPierre Pronchery     OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES, NULL, 0),
1385b077aed3SPierre Pronchery     OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, NULL, 0),
1386b077aed3SPierre Pronchery     OSSL_PARAM_END
1387b077aed3SPierre Pronchery };
1388b077aed3SPierre Pronchery 
rsa_settable_ctx_params(void * vprsactx,ossl_unused void * provctx)1389b077aed3SPierre Pronchery static const OSSL_PARAM *rsa_settable_ctx_params(void *vprsactx,
1390b077aed3SPierre Pronchery                                                  ossl_unused void *provctx)
1391b077aed3SPierre Pronchery {
1392b077aed3SPierre Pronchery     PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
1393b077aed3SPierre Pronchery 
1394b077aed3SPierre Pronchery     if (prsactx != NULL && !prsactx->flag_allow_md)
1395b077aed3SPierre Pronchery         return settable_ctx_params_no_digest;
1396b077aed3SPierre Pronchery     return settable_ctx_params;
1397b077aed3SPierre Pronchery }
1398b077aed3SPierre Pronchery 
rsa_get_ctx_md_params(void * vprsactx,OSSL_PARAM * params)1399b077aed3SPierre Pronchery static int rsa_get_ctx_md_params(void *vprsactx, OSSL_PARAM *params)
1400b077aed3SPierre Pronchery {
1401b077aed3SPierre Pronchery     PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
1402b077aed3SPierre Pronchery 
1403b077aed3SPierre Pronchery     if (prsactx->mdctx == NULL)
1404b077aed3SPierre Pronchery         return 0;
1405b077aed3SPierre Pronchery 
1406b077aed3SPierre Pronchery     return EVP_MD_CTX_get_params(prsactx->mdctx, params);
1407b077aed3SPierre Pronchery }
1408b077aed3SPierre Pronchery 
rsa_gettable_ctx_md_params(void * vprsactx)1409b077aed3SPierre Pronchery static const OSSL_PARAM *rsa_gettable_ctx_md_params(void *vprsactx)
1410b077aed3SPierre Pronchery {
1411b077aed3SPierre Pronchery     PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
1412b077aed3SPierre Pronchery 
1413b077aed3SPierre Pronchery     if (prsactx->md == NULL)
1414b077aed3SPierre Pronchery         return 0;
1415b077aed3SPierre Pronchery 
1416b077aed3SPierre Pronchery     return EVP_MD_gettable_ctx_params(prsactx->md);
1417b077aed3SPierre Pronchery }
1418b077aed3SPierre Pronchery 
rsa_set_ctx_md_params(void * vprsactx,const OSSL_PARAM params[])1419b077aed3SPierre Pronchery static int rsa_set_ctx_md_params(void *vprsactx, const OSSL_PARAM params[])
1420b077aed3SPierre Pronchery {
1421b077aed3SPierre Pronchery     PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
1422b077aed3SPierre Pronchery 
1423b077aed3SPierre Pronchery     if (prsactx->mdctx == NULL)
1424b077aed3SPierre Pronchery         return 0;
1425b077aed3SPierre Pronchery 
1426b077aed3SPierre Pronchery     return EVP_MD_CTX_set_params(prsactx->mdctx, params);
1427b077aed3SPierre Pronchery }
1428b077aed3SPierre Pronchery 
rsa_settable_ctx_md_params(void * vprsactx)1429b077aed3SPierre Pronchery static const OSSL_PARAM *rsa_settable_ctx_md_params(void *vprsactx)
1430b077aed3SPierre Pronchery {
1431b077aed3SPierre Pronchery     PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
1432b077aed3SPierre Pronchery 
1433b077aed3SPierre Pronchery     if (prsactx->md == NULL)
1434b077aed3SPierre Pronchery         return 0;
1435b077aed3SPierre Pronchery 
1436b077aed3SPierre Pronchery     return EVP_MD_settable_ctx_params(prsactx->md);
1437b077aed3SPierre Pronchery }
1438b077aed3SPierre Pronchery 
1439b077aed3SPierre Pronchery const OSSL_DISPATCH ossl_rsa_signature_functions[] = {
1440b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))rsa_newctx },
1441b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_SIGN_INIT, (void (*)(void))rsa_sign_init },
1442b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))rsa_sign },
1443b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_VERIFY_INIT, (void (*)(void))rsa_verify_init },
1444b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_VERIFY, (void (*)(void))rsa_verify },
1445b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_VERIFY_RECOVER_INIT,
1446b077aed3SPierre Pronchery       (void (*)(void))rsa_verify_recover_init },
1447b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_VERIFY_RECOVER,
1448b077aed3SPierre Pronchery       (void (*)(void))rsa_verify_recover },
1449b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,
1450b077aed3SPierre Pronchery       (void (*)(void))rsa_digest_sign_init },
1451b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE,
1452b077aed3SPierre Pronchery       (void (*)(void))rsa_digest_signverify_update },
1453b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL,
1454b077aed3SPierre Pronchery       (void (*)(void))rsa_digest_sign_final },
1455b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,
1456b077aed3SPierre Pronchery       (void (*)(void))rsa_digest_verify_init },
1457b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE,
1458b077aed3SPierre Pronchery       (void (*)(void))rsa_digest_signverify_update },
1459b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL,
1460b077aed3SPierre Pronchery       (void (*)(void))rsa_digest_verify_final },
1461b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))rsa_freectx },
1462b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))rsa_dupctx },
1463b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))rsa_get_ctx_params },
1464b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,
1465b077aed3SPierre Pronchery       (void (*)(void))rsa_gettable_ctx_params },
1466b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void (*)(void))rsa_set_ctx_params },
1467b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS,
1468b077aed3SPierre Pronchery       (void (*)(void))rsa_settable_ctx_params },
1469b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS,
1470b077aed3SPierre Pronchery       (void (*)(void))rsa_get_ctx_md_params },
1471b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS,
1472b077aed3SPierre Pronchery       (void (*)(void))rsa_gettable_ctx_md_params },
1473b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS,
1474b077aed3SPierre Pronchery       (void (*)(void))rsa_set_ctx_md_params },
1475b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS,
1476b077aed3SPierre Pronchery       (void (*)(void))rsa_settable_ctx_md_params },
1477b077aed3SPierre Pronchery     { 0, NULL }
1478b077aed3SPierre Pronchery };
1479