xref: /third_party/openssl/crypto/rsa/rsa_pmeth.c (revision e1051a39)
1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ci/*
11e1051a39Sopenharmony_ci * RSA low level APIs are deprecated for public use, but still ok for
12e1051a39Sopenharmony_ci * internal use.
13e1051a39Sopenharmony_ci */
14e1051a39Sopenharmony_ci#include "internal/deprecated.h"
15e1051a39Sopenharmony_ci
16e1051a39Sopenharmony_ci#include "internal/constant_time.h"
17e1051a39Sopenharmony_ci
18e1051a39Sopenharmony_ci#include <stdio.h>
19e1051a39Sopenharmony_ci#include "internal/cryptlib.h"
20e1051a39Sopenharmony_ci#include <openssl/asn1t.h>
21e1051a39Sopenharmony_ci#include <openssl/x509.h>
22e1051a39Sopenharmony_ci#include <openssl/rsa.h>
23e1051a39Sopenharmony_ci#include <openssl/bn.h>
24e1051a39Sopenharmony_ci#include <openssl/evp.h>
25e1051a39Sopenharmony_ci#include <openssl/x509v3.h>
26e1051a39Sopenharmony_ci#include <openssl/cms.h>
27e1051a39Sopenharmony_ci#include "crypto/evp.h"
28e1051a39Sopenharmony_ci#include "crypto/rsa.h"
29e1051a39Sopenharmony_ci#include "rsa_local.h"
30e1051a39Sopenharmony_ci
31e1051a39Sopenharmony_ci/* RSA pkey context structure */
32e1051a39Sopenharmony_ci
33e1051a39Sopenharmony_citypedef struct {
34e1051a39Sopenharmony_ci    /* Key gen parameters */
35e1051a39Sopenharmony_ci    int nbits;
36e1051a39Sopenharmony_ci    BIGNUM *pub_exp;
37e1051a39Sopenharmony_ci    int primes;
38e1051a39Sopenharmony_ci    /* Keygen callback info */
39e1051a39Sopenharmony_ci    int gentmp[2];
40e1051a39Sopenharmony_ci    /* RSA padding mode */
41e1051a39Sopenharmony_ci    int pad_mode;
42e1051a39Sopenharmony_ci    /* message digest */
43e1051a39Sopenharmony_ci    const EVP_MD *md;
44e1051a39Sopenharmony_ci    /* message digest for MGF1 */
45e1051a39Sopenharmony_ci    const EVP_MD *mgf1md;
46e1051a39Sopenharmony_ci    /* PSS salt length */
47e1051a39Sopenharmony_ci    int saltlen;
48e1051a39Sopenharmony_ci    /* Minimum salt length or -1 if no PSS parameter restriction */
49e1051a39Sopenharmony_ci    int min_saltlen;
50e1051a39Sopenharmony_ci    /* Temp buffer */
51e1051a39Sopenharmony_ci    unsigned char *tbuf;
52e1051a39Sopenharmony_ci    /* OAEP label */
53e1051a39Sopenharmony_ci    unsigned char *oaep_label;
54e1051a39Sopenharmony_ci    size_t oaep_labellen;
55e1051a39Sopenharmony_ci} RSA_PKEY_CTX;
56e1051a39Sopenharmony_ci
57e1051a39Sopenharmony_ci/* True if PSS parameters are restricted */
58e1051a39Sopenharmony_ci#define rsa_pss_restricted(rctx) (rctx->min_saltlen != -1)
59e1051a39Sopenharmony_ci
60e1051a39Sopenharmony_cistatic int pkey_rsa_init(EVP_PKEY_CTX *ctx)
61e1051a39Sopenharmony_ci{
62e1051a39Sopenharmony_ci    RSA_PKEY_CTX *rctx = OPENSSL_zalloc(sizeof(*rctx));
63e1051a39Sopenharmony_ci
64e1051a39Sopenharmony_ci    if (rctx == NULL)
65e1051a39Sopenharmony_ci        return 0;
66e1051a39Sopenharmony_ci    rctx->nbits = 2048;
67e1051a39Sopenharmony_ci    rctx->primes = RSA_DEFAULT_PRIME_NUM;
68e1051a39Sopenharmony_ci    if (pkey_ctx_is_pss(ctx))
69e1051a39Sopenharmony_ci        rctx->pad_mode = RSA_PKCS1_PSS_PADDING;
70e1051a39Sopenharmony_ci    else
71e1051a39Sopenharmony_ci        rctx->pad_mode = RSA_PKCS1_PADDING;
72e1051a39Sopenharmony_ci    /* Maximum for sign, auto for verify */
73e1051a39Sopenharmony_ci    rctx->saltlen = RSA_PSS_SALTLEN_AUTO;
74e1051a39Sopenharmony_ci    rctx->min_saltlen = -1;
75e1051a39Sopenharmony_ci    ctx->data = rctx;
76e1051a39Sopenharmony_ci    ctx->keygen_info = rctx->gentmp;
77e1051a39Sopenharmony_ci    ctx->keygen_info_count = 2;
78e1051a39Sopenharmony_ci
79e1051a39Sopenharmony_ci    return 1;
80e1051a39Sopenharmony_ci}
81e1051a39Sopenharmony_ci
82e1051a39Sopenharmony_cistatic int pkey_rsa_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src)
83e1051a39Sopenharmony_ci{
84e1051a39Sopenharmony_ci    RSA_PKEY_CTX *dctx, *sctx;
85e1051a39Sopenharmony_ci
86e1051a39Sopenharmony_ci    if (!pkey_rsa_init(dst))
87e1051a39Sopenharmony_ci        return 0;
88e1051a39Sopenharmony_ci    sctx = src->data;
89e1051a39Sopenharmony_ci    dctx = dst->data;
90e1051a39Sopenharmony_ci    dctx->nbits = sctx->nbits;
91e1051a39Sopenharmony_ci    if (sctx->pub_exp) {
92e1051a39Sopenharmony_ci        dctx->pub_exp = BN_dup(sctx->pub_exp);
93e1051a39Sopenharmony_ci        if (!dctx->pub_exp)
94e1051a39Sopenharmony_ci            return 0;
95e1051a39Sopenharmony_ci    }
96e1051a39Sopenharmony_ci    dctx->pad_mode = sctx->pad_mode;
97e1051a39Sopenharmony_ci    dctx->md = sctx->md;
98e1051a39Sopenharmony_ci    dctx->mgf1md = sctx->mgf1md;
99e1051a39Sopenharmony_ci    dctx->saltlen = sctx->saltlen;
100e1051a39Sopenharmony_ci    if (sctx->oaep_label) {
101e1051a39Sopenharmony_ci        OPENSSL_free(dctx->oaep_label);
102e1051a39Sopenharmony_ci        dctx->oaep_label = OPENSSL_memdup(sctx->oaep_label, sctx->oaep_labellen);
103e1051a39Sopenharmony_ci        if (!dctx->oaep_label)
104e1051a39Sopenharmony_ci            return 0;
105e1051a39Sopenharmony_ci        dctx->oaep_labellen = sctx->oaep_labellen;
106e1051a39Sopenharmony_ci    }
107e1051a39Sopenharmony_ci    return 1;
108e1051a39Sopenharmony_ci}
109e1051a39Sopenharmony_ci
110e1051a39Sopenharmony_cistatic int setup_tbuf(RSA_PKEY_CTX *ctx, EVP_PKEY_CTX *pk)
111e1051a39Sopenharmony_ci{
112e1051a39Sopenharmony_ci    if (ctx->tbuf != NULL)
113e1051a39Sopenharmony_ci        return 1;
114e1051a39Sopenharmony_ci    if ((ctx->tbuf =
115e1051a39Sopenharmony_ci            OPENSSL_malloc(RSA_size(EVP_PKEY_get0_RSA(pk->pkey)))) == NULL) {
116e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
117e1051a39Sopenharmony_ci        return 0;
118e1051a39Sopenharmony_ci    }
119e1051a39Sopenharmony_ci    return 1;
120e1051a39Sopenharmony_ci}
121e1051a39Sopenharmony_ci
122e1051a39Sopenharmony_cistatic void pkey_rsa_cleanup(EVP_PKEY_CTX *ctx)
123e1051a39Sopenharmony_ci{
124e1051a39Sopenharmony_ci    RSA_PKEY_CTX *rctx = ctx->data;
125e1051a39Sopenharmony_ci    if (rctx) {
126e1051a39Sopenharmony_ci        BN_free(rctx->pub_exp);
127e1051a39Sopenharmony_ci        OPENSSL_free(rctx->tbuf);
128e1051a39Sopenharmony_ci        OPENSSL_free(rctx->oaep_label);
129e1051a39Sopenharmony_ci        OPENSSL_free(rctx);
130e1051a39Sopenharmony_ci    }
131e1051a39Sopenharmony_ci}
132e1051a39Sopenharmony_ci
133e1051a39Sopenharmony_cistatic int pkey_rsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig,
134e1051a39Sopenharmony_ci                         size_t *siglen, const unsigned char *tbs,
135e1051a39Sopenharmony_ci                         size_t tbslen)
136e1051a39Sopenharmony_ci{
137e1051a39Sopenharmony_ci    int ret;
138e1051a39Sopenharmony_ci    RSA_PKEY_CTX *rctx = ctx->data;
139e1051a39Sopenharmony_ci    /*
140e1051a39Sopenharmony_ci     * Discard const. Its marked as const because this may be a cached copy of
141e1051a39Sopenharmony_ci     * the "real" key. These calls don't make any modifications that need to
142e1051a39Sopenharmony_ci     * be reflected back in the "original" key.
143e1051a39Sopenharmony_ci     */
144e1051a39Sopenharmony_ci    RSA *rsa = (RSA *)EVP_PKEY_get0_RSA(ctx->pkey);
145e1051a39Sopenharmony_ci
146e1051a39Sopenharmony_ci    if (rctx->md) {
147e1051a39Sopenharmony_ci        if (tbslen != (size_t)EVP_MD_get_size(rctx->md)) {
148e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_DIGEST_LENGTH);
149e1051a39Sopenharmony_ci            return -1;
150e1051a39Sopenharmony_ci        }
151e1051a39Sopenharmony_ci
152e1051a39Sopenharmony_ci        if (EVP_MD_get_type(rctx->md) == NID_mdc2) {
153e1051a39Sopenharmony_ci            unsigned int sltmp;
154e1051a39Sopenharmony_ci            if (rctx->pad_mode != RSA_PKCS1_PADDING)
155e1051a39Sopenharmony_ci                return -1;
156e1051a39Sopenharmony_ci            ret = RSA_sign_ASN1_OCTET_STRING(0, tbs, tbslen, sig, &sltmp, rsa);
157e1051a39Sopenharmony_ci
158e1051a39Sopenharmony_ci            if (ret <= 0)
159e1051a39Sopenharmony_ci                return ret;
160e1051a39Sopenharmony_ci            ret = sltmp;
161e1051a39Sopenharmony_ci        } else if (rctx->pad_mode == RSA_X931_PADDING) {
162e1051a39Sopenharmony_ci            if ((size_t)RSA_size(rsa) < tbslen + 1) {
163e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_RSA, RSA_R_KEY_SIZE_TOO_SMALL);
164e1051a39Sopenharmony_ci                return -1;
165e1051a39Sopenharmony_ci            }
166e1051a39Sopenharmony_ci            if (!setup_tbuf(rctx, ctx)) {
167e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
168e1051a39Sopenharmony_ci                return -1;
169e1051a39Sopenharmony_ci            }
170e1051a39Sopenharmony_ci            memcpy(rctx->tbuf, tbs, tbslen);
171e1051a39Sopenharmony_ci            rctx->tbuf[tbslen] = RSA_X931_hash_id(EVP_MD_get_type(rctx->md));
172e1051a39Sopenharmony_ci            ret = RSA_private_encrypt(tbslen + 1, rctx->tbuf,
173e1051a39Sopenharmony_ci                                      sig, rsa, RSA_X931_PADDING);
174e1051a39Sopenharmony_ci        } else if (rctx->pad_mode == RSA_PKCS1_PADDING) {
175e1051a39Sopenharmony_ci            unsigned int sltmp;
176e1051a39Sopenharmony_ci            ret = RSA_sign(EVP_MD_get_type(rctx->md),
177e1051a39Sopenharmony_ci                           tbs, tbslen, sig, &sltmp, rsa);
178e1051a39Sopenharmony_ci            if (ret <= 0)
179e1051a39Sopenharmony_ci                return ret;
180e1051a39Sopenharmony_ci            ret = sltmp;
181e1051a39Sopenharmony_ci        } else if (rctx->pad_mode == RSA_PKCS1_PSS_PADDING) {
182e1051a39Sopenharmony_ci            if (!setup_tbuf(rctx, ctx))
183e1051a39Sopenharmony_ci                return -1;
184e1051a39Sopenharmony_ci            if (!RSA_padding_add_PKCS1_PSS_mgf1(rsa,
185e1051a39Sopenharmony_ci                                                rctx->tbuf, tbs,
186e1051a39Sopenharmony_ci                                                rctx->md, rctx->mgf1md,
187e1051a39Sopenharmony_ci                                                rctx->saltlen))
188e1051a39Sopenharmony_ci                return -1;
189e1051a39Sopenharmony_ci            ret = RSA_private_encrypt(RSA_size(rsa), rctx->tbuf,
190e1051a39Sopenharmony_ci                                      sig, rsa, RSA_NO_PADDING);
191e1051a39Sopenharmony_ci        } else {
192e1051a39Sopenharmony_ci            return -1;
193e1051a39Sopenharmony_ci        }
194e1051a39Sopenharmony_ci    } else {
195e1051a39Sopenharmony_ci        ret = RSA_private_encrypt(tbslen, tbs, sig, rsa, rctx->pad_mode);
196e1051a39Sopenharmony_ci    }
197e1051a39Sopenharmony_ci    if (ret < 0)
198e1051a39Sopenharmony_ci        return ret;
199e1051a39Sopenharmony_ci    *siglen = ret;
200e1051a39Sopenharmony_ci    return 1;
201e1051a39Sopenharmony_ci}
202e1051a39Sopenharmony_ci
203e1051a39Sopenharmony_cistatic int pkey_rsa_verifyrecover(EVP_PKEY_CTX *ctx,
204e1051a39Sopenharmony_ci                                  unsigned char *rout, size_t *routlen,
205e1051a39Sopenharmony_ci                                  const unsigned char *sig, size_t siglen)
206e1051a39Sopenharmony_ci{
207e1051a39Sopenharmony_ci    int ret;
208e1051a39Sopenharmony_ci    RSA_PKEY_CTX *rctx = ctx->data;
209e1051a39Sopenharmony_ci    /*
210e1051a39Sopenharmony_ci     * Discard const. Its marked as const because this may be a cached copy of
211e1051a39Sopenharmony_ci     * the "real" key. These calls don't make any modifications that need to
212e1051a39Sopenharmony_ci     * be reflected back in the "original" key.
213e1051a39Sopenharmony_ci     */
214e1051a39Sopenharmony_ci    RSA *rsa = (RSA *)EVP_PKEY_get0_RSA(ctx->pkey);
215e1051a39Sopenharmony_ci
216e1051a39Sopenharmony_ci    if (rctx->md) {
217e1051a39Sopenharmony_ci        if (rctx->pad_mode == RSA_X931_PADDING) {
218e1051a39Sopenharmony_ci            if (!setup_tbuf(rctx, ctx))
219e1051a39Sopenharmony_ci                return -1;
220e1051a39Sopenharmony_ci            ret = RSA_public_decrypt(siglen, sig, rctx->tbuf, rsa,
221e1051a39Sopenharmony_ci                                     RSA_X931_PADDING);
222e1051a39Sopenharmony_ci            if (ret < 1)
223e1051a39Sopenharmony_ci                return 0;
224e1051a39Sopenharmony_ci            ret--;
225e1051a39Sopenharmony_ci            if (rctx->tbuf[ret] != RSA_X931_hash_id(EVP_MD_get_type(rctx->md))) {
226e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_RSA, RSA_R_ALGORITHM_MISMATCH);
227e1051a39Sopenharmony_ci                return 0;
228e1051a39Sopenharmony_ci            }
229e1051a39Sopenharmony_ci            if (ret != EVP_MD_get_size(rctx->md)) {
230e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_DIGEST_LENGTH);
231e1051a39Sopenharmony_ci                return 0;
232e1051a39Sopenharmony_ci            }
233e1051a39Sopenharmony_ci            if (rout)
234e1051a39Sopenharmony_ci                memcpy(rout, rctx->tbuf, ret);
235e1051a39Sopenharmony_ci        } else if (rctx->pad_mode == RSA_PKCS1_PADDING) {
236e1051a39Sopenharmony_ci            size_t sltmp;
237e1051a39Sopenharmony_ci            ret = ossl_rsa_verify(EVP_MD_get_type(rctx->md),
238e1051a39Sopenharmony_ci                                  NULL, 0, rout, &sltmp,
239e1051a39Sopenharmony_ci                                  sig, siglen, rsa);
240e1051a39Sopenharmony_ci            if (ret <= 0)
241e1051a39Sopenharmony_ci                return 0;
242e1051a39Sopenharmony_ci            ret = sltmp;
243e1051a39Sopenharmony_ci        } else {
244e1051a39Sopenharmony_ci            return -1;
245e1051a39Sopenharmony_ci        }
246e1051a39Sopenharmony_ci    } else {
247e1051a39Sopenharmony_ci        ret = RSA_public_decrypt(siglen, sig, rout, rsa, rctx->pad_mode);
248e1051a39Sopenharmony_ci    }
249e1051a39Sopenharmony_ci    if (ret < 0)
250e1051a39Sopenharmony_ci        return ret;
251e1051a39Sopenharmony_ci    *routlen = ret;
252e1051a39Sopenharmony_ci    return 1;
253e1051a39Sopenharmony_ci}
254e1051a39Sopenharmony_ci
255e1051a39Sopenharmony_cistatic int pkey_rsa_verify(EVP_PKEY_CTX *ctx,
256e1051a39Sopenharmony_ci                           const unsigned char *sig, size_t siglen,
257e1051a39Sopenharmony_ci                           const unsigned char *tbs, size_t tbslen)
258e1051a39Sopenharmony_ci{
259e1051a39Sopenharmony_ci    RSA_PKEY_CTX *rctx = ctx->data;
260e1051a39Sopenharmony_ci    /*
261e1051a39Sopenharmony_ci     * Discard const. Its marked as const because this may be a cached copy of
262e1051a39Sopenharmony_ci     * the "real" key. These calls don't make any modifications that need to
263e1051a39Sopenharmony_ci     * be reflected back in the "original" key.
264e1051a39Sopenharmony_ci     */
265e1051a39Sopenharmony_ci    RSA *rsa = (RSA *)EVP_PKEY_get0_RSA(ctx->pkey);
266e1051a39Sopenharmony_ci    size_t rslen;
267e1051a39Sopenharmony_ci
268e1051a39Sopenharmony_ci    if (rctx->md) {
269e1051a39Sopenharmony_ci        if (rctx->pad_mode == RSA_PKCS1_PADDING)
270e1051a39Sopenharmony_ci            return RSA_verify(EVP_MD_get_type(rctx->md), tbs, tbslen,
271e1051a39Sopenharmony_ci                              sig, siglen, rsa);
272e1051a39Sopenharmony_ci        if (tbslen != (size_t)EVP_MD_get_size(rctx->md)) {
273e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_DIGEST_LENGTH);
274e1051a39Sopenharmony_ci            return -1;
275e1051a39Sopenharmony_ci        }
276e1051a39Sopenharmony_ci        if (rctx->pad_mode == RSA_X931_PADDING) {
277e1051a39Sopenharmony_ci            if (pkey_rsa_verifyrecover(ctx, NULL, &rslen, sig, siglen) <= 0)
278e1051a39Sopenharmony_ci                return 0;
279e1051a39Sopenharmony_ci        } else if (rctx->pad_mode == RSA_PKCS1_PSS_PADDING) {
280e1051a39Sopenharmony_ci            int ret;
281e1051a39Sopenharmony_ci            if (!setup_tbuf(rctx, ctx))
282e1051a39Sopenharmony_ci                return -1;
283e1051a39Sopenharmony_ci            ret = RSA_public_decrypt(siglen, sig, rctx->tbuf,
284e1051a39Sopenharmony_ci                                     rsa, RSA_NO_PADDING);
285e1051a39Sopenharmony_ci            if (ret <= 0)
286e1051a39Sopenharmony_ci                return 0;
287e1051a39Sopenharmony_ci            ret = RSA_verify_PKCS1_PSS_mgf1(rsa, tbs,
288e1051a39Sopenharmony_ci                                            rctx->md, rctx->mgf1md,
289e1051a39Sopenharmony_ci                                            rctx->tbuf, rctx->saltlen);
290e1051a39Sopenharmony_ci            if (ret <= 0)
291e1051a39Sopenharmony_ci                return 0;
292e1051a39Sopenharmony_ci            return 1;
293e1051a39Sopenharmony_ci        } else {
294e1051a39Sopenharmony_ci            return -1;
295e1051a39Sopenharmony_ci        }
296e1051a39Sopenharmony_ci    } else {
297e1051a39Sopenharmony_ci        if (!setup_tbuf(rctx, ctx))
298e1051a39Sopenharmony_ci            return -1;
299e1051a39Sopenharmony_ci        rslen = RSA_public_decrypt(siglen, sig, rctx->tbuf,
300e1051a39Sopenharmony_ci                                   rsa, rctx->pad_mode);
301e1051a39Sopenharmony_ci        if (rslen == 0)
302e1051a39Sopenharmony_ci            return 0;
303e1051a39Sopenharmony_ci    }
304e1051a39Sopenharmony_ci
305e1051a39Sopenharmony_ci    if ((rslen != tbslen) || memcmp(tbs, rctx->tbuf, rslen))
306e1051a39Sopenharmony_ci        return 0;
307e1051a39Sopenharmony_ci
308e1051a39Sopenharmony_ci    return 1;
309e1051a39Sopenharmony_ci
310e1051a39Sopenharmony_ci}
311e1051a39Sopenharmony_ci
312e1051a39Sopenharmony_cistatic int pkey_rsa_encrypt(EVP_PKEY_CTX *ctx,
313e1051a39Sopenharmony_ci                            unsigned char *out, size_t *outlen,
314e1051a39Sopenharmony_ci                            const unsigned char *in, size_t inlen)
315e1051a39Sopenharmony_ci{
316e1051a39Sopenharmony_ci    int ret;
317e1051a39Sopenharmony_ci    RSA_PKEY_CTX *rctx = ctx->data;
318e1051a39Sopenharmony_ci    /*
319e1051a39Sopenharmony_ci     * Discard const. Its marked as const because this may be a cached copy of
320e1051a39Sopenharmony_ci     * the "real" key. These calls don't make any modifications that need to
321e1051a39Sopenharmony_ci     * be reflected back in the "original" key.
322e1051a39Sopenharmony_ci     */
323e1051a39Sopenharmony_ci    RSA *rsa = (RSA *)EVP_PKEY_get0_RSA(ctx->pkey);
324e1051a39Sopenharmony_ci
325e1051a39Sopenharmony_ci    if (rctx->pad_mode == RSA_PKCS1_OAEP_PADDING) {
326e1051a39Sopenharmony_ci        int klen = RSA_size(rsa);
327e1051a39Sopenharmony_ci        if (!setup_tbuf(rctx, ctx))
328e1051a39Sopenharmony_ci            return -1;
329e1051a39Sopenharmony_ci        if (!RSA_padding_add_PKCS1_OAEP_mgf1(rctx->tbuf, klen,
330e1051a39Sopenharmony_ci                                             in, inlen,
331e1051a39Sopenharmony_ci                                             rctx->oaep_label,
332e1051a39Sopenharmony_ci                                             rctx->oaep_labellen,
333e1051a39Sopenharmony_ci                                             rctx->md, rctx->mgf1md))
334e1051a39Sopenharmony_ci            return -1;
335e1051a39Sopenharmony_ci        ret = RSA_public_encrypt(klen, rctx->tbuf, out, rsa, RSA_NO_PADDING);
336e1051a39Sopenharmony_ci    } else {
337e1051a39Sopenharmony_ci        ret = RSA_public_encrypt(inlen, in, out, rsa, rctx->pad_mode);
338e1051a39Sopenharmony_ci    }
339e1051a39Sopenharmony_ci    if (ret < 0)
340e1051a39Sopenharmony_ci        return ret;
341e1051a39Sopenharmony_ci    *outlen = ret;
342e1051a39Sopenharmony_ci    return 1;
343e1051a39Sopenharmony_ci}
344e1051a39Sopenharmony_ci
345e1051a39Sopenharmony_cistatic int pkey_rsa_decrypt(EVP_PKEY_CTX *ctx,
346e1051a39Sopenharmony_ci                            unsigned char *out, size_t *outlen,
347e1051a39Sopenharmony_ci                            const unsigned char *in, size_t inlen)
348e1051a39Sopenharmony_ci{
349e1051a39Sopenharmony_ci    int ret;
350e1051a39Sopenharmony_ci    RSA_PKEY_CTX *rctx = ctx->data;
351e1051a39Sopenharmony_ci    /*
352e1051a39Sopenharmony_ci     * Discard const. Its marked as const because this may be a cached copy of
353e1051a39Sopenharmony_ci     * the "real" key. These calls don't make any modifications that need to
354e1051a39Sopenharmony_ci     * be reflected back in the "original" key.
355e1051a39Sopenharmony_ci     */
356e1051a39Sopenharmony_ci    RSA *rsa = (RSA *)EVP_PKEY_get0_RSA(ctx->pkey);
357e1051a39Sopenharmony_ci
358e1051a39Sopenharmony_ci    if (rctx->pad_mode == RSA_PKCS1_OAEP_PADDING) {
359e1051a39Sopenharmony_ci        if (!setup_tbuf(rctx, ctx))
360e1051a39Sopenharmony_ci            return -1;
361e1051a39Sopenharmony_ci        ret = RSA_private_decrypt(inlen, in, rctx->tbuf, rsa, RSA_NO_PADDING);
362e1051a39Sopenharmony_ci        if (ret <= 0)
363e1051a39Sopenharmony_ci            return ret;
364e1051a39Sopenharmony_ci        ret = RSA_padding_check_PKCS1_OAEP_mgf1(out, ret, rctx->tbuf,
365e1051a39Sopenharmony_ci                                                ret, ret,
366e1051a39Sopenharmony_ci                                                rctx->oaep_label,
367e1051a39Sopenharmony_ci                                                rctx->oaep_labellen,
368e1051a39Sopenharmony_ci                                                rctx->md, rctx->mgf1md);
369e1051a39Sopenharmony_ci    } else {
370e1051a39Sopenharmony_ci        ret = RSA_private_decrypt(inlen, in, out, rsa, rctx->pad_mode);
371e1051a39Sopenharmony_ci    }
372e1051a39Sopenharmony_ci    *outlen = constant_time_select_s(constant_time_msb_s(ret), *outlen, ret);
373e1051a39Sopenharmony_ci    ret = constant_time_select_int(constant_time_msb(ret), ret, 1);
374e1051a39Sopenharmony_ci    return ret;
375e1051a39Sopenharmony_ci}
376e1051a39Sopenharmony_ci
377e1051a39Sopenharmony_cistatic int check_padding_md(const EVP_MD *md, int padding)
378e1051a39Sopenharmony_ci{
379e1051a39Sopenharmony_ci    int mdnid;
380e1051a39Sopenharmony_ci
381e1051a39Sopenharmony_ci    if (!md)
382e1051a39Sopenharmony_ci        return 1;
383e1051a39Sopenharmony_ci
384e1051a39Sopenharmony_ci    mdnid = EVP_MD_get_type(md);
385e1051a39Sopenharmony_ci
386e1051a39Sopenharmony_ci    if (padding == RSA_NO_PADDING) {
387e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_PADDING_MODE);
388e1051a39Sopenharmony_ci        return 0;
389e1051a39Sopenharmony_ci    }
390e1051a39Sopenharmony_ci
391e1051a39Sopenharmony_ci    if (padding == RSA_X931_PADDING) {
392e1051a39Sopenharmony_ci        if (RSA_X931_hash_id(mdnid) == -1) {
393e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_X931_DIGEST);
394e1051a39Sopenharmony_ci            return 0;
395e1051a39Sopenharmony_ci        }
396e1051a39Sopenharmony_ci    } else {
397e1051a39Sopenharmony_ci        switch(mdnid) {
398e1051a39Sopenharmony_ci        /* List of all supported RSA digests */
399e1051a39Sopenharmony_ci        case NID_sha1:
400e1051a39Sopenharmony_ci        case NID_sha224:
401e1051a39Sopenharmony_ci        case NID_sha256:
402e1051a39Sopenharmony_ci        case NID_sha384:
403e1051a39Sopenharmony_ci        case NID_sha512:
404e1051a39Sopenharmony_ci        case NID_sha512_224:
405e1051a39Sopenharmony_ci        case NID_sha512_256:
406e1051a39Sopenharmony_ci        case NID_md5:
407e1051a39Sopenharmony_ci        case NID_md5_sha1:
408e1051a39Sopenharmony_ci        case NID_md2:
409e1051a39Sopenharmony_ci        case NID_md4:
410e1051a39Sopenharmony_ci        case NID_mdc2:
411e1051a39Sopenharmony_ci        case NID_ripemd160:
412e1051a39Sopenharmony_ci        case NID_sha3_224:
413e1051a39Sopenharmony_ci        case NID_sha3_256:
414e1051a39Sopenharmony_ci        case NID_sha3_384:
415e1051a39Sopenharmony_ci        case NID_sha3_512:
416e1051a39Sopenharmony_ci            return 1;
417e1051a39Sopenharmony_ci
418e1051a39Sopenharmony_ci        default:
419e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_DIGEST);
420e1051a39Sopenharmony_ci            return 0;
421e1051a39Sopenharmony_ci
422e1051a39Sopenharmony_ci        }
423e1051a39Sopenharmony_ci    }
424e1051a39Sopenharmony_ci
425e1051a39Sopenharmony_ci    return 1;
426e1051a39Sopenharmony_ci}
427e1051a39Sopenharmony_ci
428e1051a39Sopenharmony_cistatic int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
429e1051a39Sopenharmony_ci{
430e1051a39Sopenharmony_ci    RSA_PKEY_CTX *rctx = ctx->data;
431e1051a39Sopenharmony_ci
432e1051a39Sopenharmony_ci    switch (type) {
433e1051a39Sopenharmony_ci    case EVP_PKEY_CTRL_RSA_PADDING:
434e1051a39Sopenharmony_ci        if ((p1 >= RSA_PKCS1_PADDING) && (p1 <= RSA_PKCS1_PSS_PADDING)) {
435e1051a39Sopenharmony_ci            if (!check_padding_md(rctx->md, p1))
436e1051a39Sopenharmony_ci                return 0;
437e1051a39Sopenharmony_ci            if (p1 == RSA_PKCS1_PSS_PADDING) {
438e1051a39Sopenharmony_ci                if (!(ctx->operation &
439e1051a39Sopenharmony_ci                      (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY)))
440e1051a39Sopenharmony_ci                    goto bad_pad;
441e1051a39Sopenharmony_ci                if (!rctx->md)
442e1051a39Sopenharmony_ci                    rctx->md = EVP_sha1();
443e1051a39Sopenharmony_ci            } else if (pkey_ctx_is_pss(ctx)) {
444e1051a39Sopenharmony_ci                goto bad_pad;
445e1051a39Sopenharmony_ci            }
446e1051a39Sopenharmony_ci            if (p1 == RSA_PKCS1_OAEP_PADDING) {
447e1051a39Sopenharmony_ci                if (!(ctx->operation & EVP_PKEY_OP_TYPE_CRYPT))
448e1051a39Sopenharmony_ci                    goto bad_pad;
449e1051a39Sopenharmony_ci                if (!rctx->md)
450e1051a39Sopenharmony_ci                    rctx->md = EVP_sha1();
451e1051a39Sopenharmony_ci            }
452e1051a39Sopenharmony_ci            rctx->pad_mode = p1;
453e1051a39Sopenharmony_ci            return 1;
454e1051a39Sopenharmony_ci        }
455e1051a39Sopenharmony_ci bad_pad:
456e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_RSA, RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE);
457e1051a39Sopenharmony_ci        return -2;
458e1051a39Sopenharmony_ci
459e1051a39Sopenharmony_ci    case EVP_PKEY_CTRL_GET_RSA_PADDING:
460e1051a39Sopenharmony_ci        *(int *)p2 = rctx->pad_mode;
461e1051a39Sopenharmony_ci        return 1;
462e1051a39Sopenharmony_ci
463e1051a39Sopenharmony_ci    case EVP_PKEY_CTRL_RSA_PSS_SALTLEN:
464e1051a39Sopenharmony_ci    case EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN:
465e1051a39Sopenharmony_ci        if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING) {
466e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_PSS_SALTLEN);
467e1051a39Sopenharmony_ci            return -2;
468e1051a39Sopenharmony_ci        }
469e1051a39Sopenharmony_ci        if (type == EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN) {
470e1051a39Sopenharmony_ci            *(int *)p2 = rctx->saltlen;
471e1051a39Sopenharmony_ci        } else {
472e1051a39Sopenharmony_ci            if (p1 < RSA_PSS_SALTLEN_MAX)
473e1051a39Sopenharmony_ci                return -2;
474e1051a39Sopenharmony_ci            if (rsa_pss_restricted(rctx)) {
475e1051a39Sopenharmony_ci                if (p1 == RSA_PSS_SALTLEN_AUTO
476e1051a39Sopenharmony_ci                    && ctx->operation == EVP_PKEY_OP_VERIFY) {
477e1051a39Sopenharmony_ci                    ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_PSS_SALTLEN);
478e1051a39Sopenharmony_ci                    return -2;
479e1051a39Sopenharmony_ci                }
480e1051a39Sopenharmony_ci                if ((p1 == RSA_PSS_SALTLEN_DIGEST
481e1051a39Sopenharmony_ci                     && rctx->min_saltlen > EVP_MD_get_size(rctx->md))
482e1051a39Sopenharmony_ci                    || (p1 >= 0 && p1 < rctx->min_saltlen)) {
483e1051a39Sopenharmony_ci                    ERR_raise(ERR_LIB_RSA, RSA_R_PSS_SALTLEN_TOO_SMALL);
484e1051a39Sopenharmony_ci                    return 0;
485e1051a39Sopenharmony_ci                }
486e1051a39Sopenharmony_ci            }
487e1051a39Sopenharmony_ci            rctx->saltlen = p1;
488e1051a39Sopenharmony_ci        }
489e1051a39Sopenharmony_ci        return 1;
490e1051a39Sopenharmony_ci
491e1051a39Sopenharmony_ci    case EVP_PKEY_CTRL_RSA_KEYGEN_BITS:
492e1051a39Sopenharmony_ci        if (p1 < RSA_MIN_MODULUS_BITS) {
493e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_RSA, RSA_R_KEY_SIZE_TOO_SMALL);
494e1051a39Sopenharmony_ci            return -2;
495e1051a39Sopenharmony_ci        }
496e1051a39Sopenharmony_ci        rctx->nbits = p1;
497e1051a39Sopenharmony_ci        return 1;
498e1051a39Sopenharmony_ci
499e1051a39Sopenharmony_ci    case EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP:
500e1051a39Sopenharmony_ci        if (p2 == NULL || !BN_is_odd((BIGNUM *)p2) || BN_is_one((BIGNUM *)p2)) {
501e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_RSA, RSA_R_BAD_E_VALUE);
502e1051a39Sopenharmony_ci            return -2;
503e1051a39Sopenharmony_ci        }
504e1051a39Sopenharmony_ci        BN_free(rctx->pub_exp);
505e1051a39Sopenharmony_ci        rctx->pub_exp = p2;
506e1051a39Sopenharmony_ci        return 1;
507e1051a39Sopenharmony_ci
508e1051a39Sopenharmony_ci    case EVP_PKEY_CTRL_RSA_KEYGEN_PRIMES:
509e1051a39Sopenharmony_ci        if (p1 < RSA_DEFAULT_PRIME_NUM || p1 > RSA_MAX_PRIME_NUM) {
510e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_RSA, RSA_R_KEY_PRIME_NUM_INVALID);
511e1051a39Sopenharmony_ci            return -2;
512e1051a39Sopenharmony_ci        }
513e1051a39Sopenharmony_ci        rctx->primes = p1;
514e1051a39Sopenharmony_ci        return 1;
515e1051a39Sopenharmony_ci
516e1051a39Sopenharmony_ci    case EVP_PKEY_CTRL_RSA_OAEP_MD:
517e1051a39Sopenharmony_ci    case EVP_PKEY_CTRL_GET_RSA_OAEP_MD:
518e1051a39Sopenharmony_ci        if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
519e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_PADDING_MODE);
520e1051a39Sopenharmony_ci            return -2;
521e1051a39Sopenharmony_ci        }
522e1051a39Sopenharmony_ci        if (type == EVP_PKEY_CTRL_GET_RSA_OAEP_MD)
523e1051a39Sopenharmony_ci            *(const EVP_MD **)p2 = rctx->md;
524e1051a39Sopenharmony_ci        else
525e1051a39Sopenharmony_ci            rctx->md = p2;
526e1051a39Sopenharmony_ci        return 1;
527e1051a39Sopenharmony_ci
528e1051a39Sopenharmony_ci    case EVP_PKEY_CTRL_MD:
529e1051a39Sopenharmony_ci        if (!check_padding_md(p2, rctx->pad_mode))
530e1051a39Sopenharmony_ci            return 0;
531e1051a39Sopenharmony_ci        if (rsa_pss_restricted(rctx)) {
532e1051a39Sopenharmony_ci            if (EVP_MD_get_type(rctx->md) == EVP_MD_get_type(p2))
533e1051a39Sopenharmony_ci                return 1;
534e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_RSA, RSA_R_DIGEST_NOT_ALLOWED);
535e1051a39Sopenharmony_ci            return 0;
536e1051a39Sopenharmony_ci        }
537e1051a39Sopenharmony_ci        rctx->md = p2;
538e1051a39Sopenharmony_ci        return 1;
539e1051a39Sopenharmony_ci
540e1051a39Sopenharmony_ci    case EVP_PKEY_CTRL_GET_MD:
541e1051a39Sopenharmony_ci        *(const EVP_MD **)p2 = rctx->md;
542e1051a39Sopenharmony_ci        return 1;
543e1051a39Sopenharmony_ci
544e1051a39Sopenharmony_ci    case EVP_PKEY_CTRL_RSA_MGF1_MD:
545e1051a39Sopenharmony_ci    case EVP_PKEY_CTRL_GET_RSA_MGF1_MD:
546e1051a39Sopenharmony_ci        if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING
547e1051a39Sopenharmony_ci            && rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
548e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_MGF1_MD);
549e1051a39Sopenharmony_ci            return -2;
550e1051a39Sopenharmony_ci        }
551e1051a39Sopenharmony_ci        if (type == EVP_PKEY_CTRL_GET_RSA_MGF1_MD) {
552e1051a39Sopenharmony_ci            if (rctx->mgf1md)
553e1051a39Sopenharmony_ci                *(const EVP_MD **)p2 = rctx->mgf1md;
554e1051a39Sopenharmony_ci            else
555e1051a39Sopenharmony_ci                *(const EVP_MD **)p2 = rctx->md;
556e1051a39Sopenharmony_ci        } else {
557e1051a39Sopenharmony_ci            if (rsa_pss_restricted(rctx)) {
558e1051a39Sopenharmony_ci                if (EVP_MD_get_type(rctx->mgf1md) == EVP_MD_get_type(p2))
559e1051a39Sopenharmony_ci                    return 1;
560e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_RSA, RSA_R_MGF1_DIGEST_NOT_ALLOWED);
561e1051a39Sopenharmony_ci                return 0;
562e1051a39Sopenharmony_ci            }
563e1051a39Sopenharmony_ci            rctx->mgf1md = p2;
564e1051a39Sopenharmony_ci        }
565e1051a39Sopenharmony_ci        return 1;
566e1051a39Sopenharmony_ci
567e1051a39Sopenharmony_ci    case EVP_PKEY_CTRL_RSA_OAEP_LABEL:
568e1051a39Sopenharmony_ci        if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
569e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_PADDING_MODE);
570e1051a39Sopenharmony_ci            return -2;
571e1051a39Sopenharmony_ci        }
572e1051a39Sopenharmony_ci        OPENSSL_free(rctx->oaep_label);
573e1051a39Sopenharmony_ci        if (p2 && p1 > 0) {
574e1051a39Sopenharmony_ci            rctx->oaep_label = p2;
575e1051a39Sopenharmony_ci            rctx->oaep_labellen = p1;
576e1051a39Sopenharmony_ci        } else {
577e1051a39Sopenharmony_ci            rctx->oaep_label = NULL;
578e1051a39Sopenharmony_ci            rctx->oaep_labellen = 0;
579e1051a39Sopenharmony_ci        }
580e1051a39Sopenharmony_ci        return 1;
581e1051a39Sopenharmony_ci
582e1051a39Sopenharmony_ci    case EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL:
583e1051a39Sopenharmony_ci        if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
584e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_PADDING_MODE);
585e1051a39Sopenharmony_ci            return -2;
586e1051a39Sopenharmony_ci        }
587e1051a39Sopenharmony_ci        *(unsigned char **)p2 = rctx->oaep_label;
588e1051a39Sopenharmony_ci        return rctx->oaep_labellen;
589e1051a39Sopenharmony_ci
590e1051a39Sopenharmony_ci    case EVP_PKEY_CTRL_DIGESTINIT:
591e1051a39Sopenharmony_ci    case EVP_PKEY_CTRL_PKCS7_SIGN:
592e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_CMS
593e1051a39Sopenharmony_ci    case EVP_PKEY_CTRL_CMS_SIGN:
594e1051a39Sopenharmony_ci#endif
595e1051a39Sopenharmony_ci    return 1;
596e1051a39Sopenharmony_ci
597e1051a39Sopenharmony_ci    case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
598e1051a39Sopenharmony_ci    case EVP_PKEY_CTRL_PKCS7_DECRYPT:
599e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_CMS
600e1051a39Sopenharmony_ci    case EVP_PKEY_CTRL_CMS_DECRYPT:
601e1051a39Sopenharmony_ci    case EVP_PKEY_CTRL_CMS_ENCRYPT:
602e1051a39Sopenharmony_ci#endif
603e1051a39Sopenharmony_ci    if (!pkey_ctx_is_pss(ctx))
604e1051a39Sopenharmony_ci        return 1;
605e1051a39Sopenharmony_ci    /* fall through */
606e1051a39Sopenharmony_ci    case EVP_PKEY_CTRL_PEER_KEY:
607e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_RSA, RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
608e1051a39Sopenharmony_ci        return -2;
609e1051a39Sopenharmony_ci
610e1051a39Sopenharmony_ci    default:
611e1051a39Sopenharmony_ci        return -2;
612e1051a39Sopenharmony_ci
613e1051a39Sopenharmony_ci    }
614e1051a39Sopenharmony_ci}
615e1051a39Sopenharmony_ci
616e1051a39Sopenharmony_cistatic int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx,
617e1051a39Sopenharmony_ci                             const char *type, const char *value)
618e1051a39Sopenharmony_ci{
619e1051a39Sopenharmony_ci    if (value == NULL) {
620e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_RSA, RSA_R_VALUE_MISSING);
621e1051a39Sopenharmony_ci        return 0;
622e1051a39Sopenharmony_ci    }
623e1051a39Sopenharmony_ci    if (strcmp(type, "rsa_padding_mode") == 0) {
624e1051a39Sopenharmony_ci        int pm;
625e1051a39Sopenharmony_ci
626e1051a39Sopenharmony_ci        if (strcmp(value, "pkcs1") == 0) {
627e1051a39Sopenharmony_ci            pm = RSA_PKCS1_PADDING;
628e1051a39Sopenharmony_ci        } else if (strcmp(value, "none") == 0) {
629e1051a39Sopenharmony_ci            pm = RSA_NO_PADDING;
630e1051a39Sopenharmony_ci        } else if (strcmp(value, "oeap") == 0) {
631e1051a39Sopenharmony_ci            pm = RSA_PKCS1_OAEP_PADDING;
632e1051a39Sopenharmony_ci        } else if (strcmp(value, "oaep") == 0) {
633e1051a39Sopenharmony_ci            pm = RSA_PKCS1_OAEP_PADDING;
634e1051a39Sopenharmony_ci        } else if (strcmp(value, "x931") == 0) {
635e1051a39Sopenharmony_ci            pm = RSA_X931_PADDING;
636e1051a39Sopenharmony_ci        } else if (strcmp(value, "pss") == 0) {
637e1051a39Sopenharmony_ci            pm = RSA_PKCS1_PSS_PADDING;
638e1051a39Sopenharmony_ci        } else {
639e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_RSA, RSA_R_UNKNOWN_PADDING_TYPE);
640e1051a39Sopenharmony_ci            return -2;
641e1051a39Sopenharmony_ci        }
642e1051a39Sopenharmony_ci        return EVP_PKEY_CTX_set_rsa_padding(ctx, pm);
643e1051a39Sopenharmony_ci    }
644e1051a39Sopenharmony_ci
645e1051a39Sopenharmony_ci    if (strcmp(type, "rsa_pss_saltlen") == 0) {
646e1051a39Sopenharmony_ci        int saltlen;
647e1051a39Sopenharmony_ci
648e1051a39Sopenharmony_ci        if (!strcmp(value, "digest"))
649e1051a39Sopenharmony_ci            saltlen = RSA_PSS_SALTLEN_DIGEST;
650e1051a39Sopenharmony_ci        else if (!strcmp(value, "max"))
651e1051a39Sopenharmony_ci            saltlen = RSA_PSS_SALTLEN_MAX;
652e1051a39Sopenharmony_ci        else if (!strcmp(value, "auto"))
653e1051a39Sopenharmony_ci            saltlen = RSA_PSS_SALTLEN_AUTO;
654e1051a39Sopenharmony_ci        else
655e1051a39Sopenharmony_ci            saltlen = atoi(value);
656e1051a39Sopenharmony_ci        return EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, saltlen);
657e1051a39Sopenharmony_ci    }
658e1051a39Sopenharmony_ci
659e1051a39Sopenharmony_ci    if (strcmp(type, "rsa_keygen_bits") == 0) {
660e1051a39Sopenharmony_ci        int nbits = atoi(value);
661e1051a39Sopenharmony_ci
662e1051a39Sopenharmony_ci        return EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, nbits);
663e1051a39Sopenharmony_ci    }
664e1051a39Sopenharmony_ci
665e1051a39Sopenharmony_ci    if (strcmp(type, "rsa_keygen_pubexp") == 0) {
666e1051a39Sopenharmony_ci        int ret;
667e1051a39Sopenharmony_ci
668e1051a39Sopenharmony_ci        BIGNUM *pubexp = NULL;
669e1051a39Sopenharmony_ci        if (!BN_asc2bn(&pubexp, value))
670e1051a39Sopenharmony_ci            return 0;
671e1051a39Sopenharmony_ci        ret = EVP_PKEY_CTX_set1_rsa_keygen_pubexp(ctx, pubexp);
672e1051a39Sopenharmony_ci        BN_free(pubexp);
673e1051a39Sopenharmony_ci        return ret;
674e1051a39Sopenharmony_ci    }
675e1051a39Sopenharmony_ci
676e1051a39Sopenharmony_ci    if (strcmp(type, "rsa_keygen_primes") == 0) {
677e1051a39Sopenharmony_ci        int nprimes = atoi(value);
678e1051a39Sopenharmony_ci
679e1051a39Sopenharmony_ci        return EVP_PKEY_CTX_set_rsa_keygen_primes(ctx, nprimes);
680e1051a39Sopenharmony_ci    }
681e1051a39Sopenharmony_ci
682e1051a39Sopenharmony_ci    if (strcmp(type, "rsa_mgf1_md") == 0)
683e1051a39Sopenharmony_ci        return EVP_PKEY_CTX_md(ctx,
684e1051a39Sopenharmony_ci                               EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT,
685e1051a39Sopenharmony_ci                               EVP_PKEY_CTRL_RSA_MGF1_MD, value);
686e1051a39Sopenharmony_ci
687e1051a39Sopenharmony_ci    if (pkey_ctx_is_pss(ctx)) {
688e1051a39Sopenharmony_ci
689e1051a39Sopenharmony_ci        if (strcmp(type, "rsa_pss_keygen_mgf1_md") == 0)
690e1051a39Sopenharmony_ci            return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_KEYGEN,
691e1051a39Sopenharmony_ci                                   EVP_PKEY_CTRL_RSA_MGF1_MD, value);
692e1051a39Sopenharmony_ci
693e1051a39Sopenharmony_ci        if (strcmp(type, "rsa_pss_keygen_md") == 0)
694e1051a39Sopenharmony_ci            return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_KEYGEN,
695e1051a39Sopenharmony_ci                                   EVP_PKEY_CTRL_MD, value);
696e1051a39Sopenharmony_ci
697e1051a39Sopenharmony_ci        if (strcmp(type, "rsa_pss_keygen_saltlen") == 0) {
698e1051a39Sopenharmony_ci            int saltlen = atoi(value);
699e1051a39Sopenharmony_ci
700e1051a39Sopenharmony_ci            return EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen(ctx, saltlen);
701e1051a39Sopenharmony_ci        }
702e1051a39Sopenharmony_ci    }
703e1051a39Sopenharmony_ci
704e1051a39Sopenharmony_ci    if (strcmp(type, "rsa_oaep_md") == 0)
705e1051a39Sopenharmony_ci        return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_TYPE_CRYPT,
706e1051a39Sopenharmony_ci                               EVP_PKEY_CTRL_RSA_OAEP_MD, value);
707e1051a39Sopenharmony_ci
708e1051a39Sopenharmony_ci    if (strcmp(type, "rsa_oaep_label") == 0) {
709e1051a39Sopenharmony_ci        unsigned char *lab;
710e1051a39Sopenharmony_ci        long lablen;
711e1051a39Sopenharmony_ci        int ret;
712e1051a39Sopenharmony_ci
713e1051a39Sopenharmony_ci        lab = OPENSSL_hexstr2buf(value, &lablen);
714e1051a39Sopenharmony_ci        if (!lab)
715e1051a39Sopenharmony_ci            return 0;
716e1051a39Sopenharmony_ci        ret = EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, lab, lablen);
717e1051a39Sopenharmony_ci        if (ret <= 0)
718e1051a39Sopenharmony_ci            OPENSSL_free(lab);
719e1051a39Sopenharmony_ci        return ret;
720e1051a39Sopenharmony_ci    }
721e1051a39Sopenharmony_ci
722e1051a39Sopenharmony_ci    return -2;
723e1051a39Sopenharmony_ci}
724e1051a39Sopenharmony_ci
725e1051a39Sopenharmony_ci/* Set PSS parameters when generating a key, if necessary */
726e1051a39Sopenharmony_cistatic int rsa_set_pss_param(RSA *rsa, EVP_PKEY_CTX *ctx)
727e1051a39Sopenharmony_ci{
728e1051a39Sopenharmony_ci    RSA_PKEY_CTX *rctx = ctx->data;
729e1051a39Sopenharmony_ci
730e1051a39Sopenharmony_ci    if (!pkey_ctx_is_pss(ctx))
731e1051a39Sopenharmony_ci        return 1;
732e1051a39Sopenharmony_ci    /* If all parameters are default values don't set pss */
733e1051a39Sopenharmony_ci    if (rctx->md == NULL && rctx->mgf1md == NULL && rctx->saltlen == -2)
734e1051a39Sopenharmony_ci        return 1;
735e1051a39Sopenharmony_ci    rsa->pss = ossl_rsa_pss_params_create(rctx->md, rctx->mgf1md,
736e1051a39Sopenharmony_ci                                          rctx->saltlen == -2
737e1051a39Sopenharmony_ci                                          ? 0 : rctx->saltlen);
738e1051a39Sopenharmony_ci    if (rsa->pss == NULL)
739e1051a39Sopenharmony_ci        return 0;
740e1051a39Sopenharmony_ci    return 1;
741e1051a39Sopenharmony_ci}
742e1051a39Sopenharmony_ci
743e1051a39Sopenharmony_cistatic int pkey_rsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
744e1051a39Sopenharmony_ci{
745e1051a39Sopenharmony_ci    RSA *rsa = NULL;
746e1051a39Sopenharmony_ci    RSA_PKEY_CTX *rctx = ctx->data;
747e1051a39Sopenharmony_ci    BN_GENCB *pcb;
748e1051a39Sopenharmony_ci    int ret;
749e1051a39Sopenharmony_ci
750e1051a39Sopenharmony_ci    if (rctx->pub_exp == NULL) {
751e1051a39Sopenharmony_ci        rctx->pub_exp = BN_new();
752e1051a39Sopenharmony_ci        if (rctx->pub_exp == NULL || !BN_set_word(rctx->pub_exp, RSA_F4))
753e1051a39Sopenharmony_ci            return 0;
754e1051a39Sopenharmony_ci    }
755e1051a39Sopenharmony_ci    rsa = RSA_new();
756e1051a39Sopenharmony_ci    if (rsa == NULL)
757e1051a39Sopenharmony_ci        return 0;
758e1051a39Sopenharmony_ci    if (ctx->pkey_gencb) {
759e1051a39Sopenharmony_ci        pcb = BN_GENCB_new();
760e1051a39Sopenharmony_ci        if (pcb == NULL) {
761e1051a39Sopenharmony_ci            RSA_free(rsa);
762e1051a39Sopenharmony_ci            return 0;
763e1051a39Sopenharmony_ci        }
764e1051a39Sopenharmony_ci        evp_pkey_set_cb_translate(pcb, ctx);
765e1051a39Sopenharmony_ci    } else {
766e1051a39Sopenharmony_ci        pcb = NULL;
767e1051a39Sopenharmony_ci    }
768e1051a39Sopenharmony_ci    ret = RSA_generate_multi_prime_key(rsa, rctx->nbits, rctx->primes,
769e1051a39Sopenharmony_ci                                       rctx->pub_exp, pcb);
770e1051a39Sopenharmony_ci    BN_GENCB_free(pcb);
771e1051a39Sopenharmony_ci    if (ret > 0 && !rsa_set_pss_param(rsa, ctx)) {
772e1051a39Sopenharmony_ci        RSA_free(rsa);
773e1051a39Sopenharmony_ci        return 0;
774e1051a39Sopenharmony_ci    }
775e1051a39Sopenharmony_ci    if (ret > 0)
776e1051a39Sopenharmony_ci        EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, rsa);
777e1051a39Sopenharmony_ci    else
778e1051a39Sopenharmony_ci        RSA_free(rsa);
779e1051a39Sopenharmony_ci    return ret;
780e1051a39Sopenharmony_ci}
781e1051a39Sopenharmony_ci
782e1051a39Sopenharmony_cistatic const EVP_PKEY_METHOD rsa_pkey_meth = {
783e1051a39Sopenharmony_ci    EVP_PKEY_RSA,
784e1051a39Sopenharmony_ci    EVP_PKEY_FLAG_AUTOARGLEN,
785e1051a39Sopenharmony_ci    pkey_rsa_init,
786e1051a39Sopenharmony_ci    pkey_rsa_copy,
787e1051a39Sopenharmony_ci    pkey_rsa_cleanup,
788e1051a39Sopenharmony_ci
789e1051a39Sopenharmony_ci    0, 0,
790e1051a39Sopenharmony_ci
791e1051a39Sopenharmony_ci    0,
792e1051a39Sopenharmony_ci    pkey_rsa_keygen,
793e1051a39Sopenharmony_ci
794e1051a39Sopenharmony_ci    0,
795e1051a39Sopenharmony_ci    pkey_rsa_sign,
796e1051a39Sopenharmony_ci
797e1051a39Sopenharmony_ci    0,
798e1051a39Sopenharmony_ci    pkey_rsa_verify,
799e1051a39Sopenharmony_ci
800e1051a39Sopenharmony_ci    0,
801e1051a39Sopenharmony_ci    pkey_rsa_verifyrecover,
802e1051a39Sopenharmony_ci
803e1051a39Sopenharmony_ci    0, 0, 0, 0,
804e1051a39Sopenharmony_ci
805e1051a39Sopenharmony_ci    0,
806e1051a39Sopenharmony_ci    pkey_rsa_encrypt,
807e1051a39Sopenharmony_ci
808e1051a39Sopenharmony_ci    0,
809e1051a39Sopenharmony_ci    pkey_rsa_decrypt,
810e1051a39Sopenharmony_ci
811e1051a39Sopenharmony_ci    0, 0,
812e1051a39Sopenharmony_ci
813e1051a39Sopenharmony_ci    pkey_rsa_ctrl,
814e1051a39Sopenharmony_ci    pkey_rsa_ctrl_str
815e1051a39Sopenharmony_ci};
816e1051a39Sopenharmony_ci
817e1051a39Sopenharmony_ciconst EVP_PKEY_METHOD *ossl_rsa_pkey_method(void)
818e1051a39Sopenharmony_ci{
819e1051a39Sopenharmony_ci    return &rsa_pkey_meth;
820e1051a39Sopenharmony_ci}
821e1051a39Sopenharmony_ci
822e1051a39Sopenharmony_ci/*
823e1051a39Sopenharmony_ci * Called for PSS sign or verify initialisation: checks PSS parameter
824e1051a39Sopenharmony_ci * sanity and sets any restrictions on key usage.
825e1051a39Sopenharmony_ci */
826e1051a39Sopenharmony_ci
827e1051a39Sopenharmony_cistatic int pkey_pss_init(EVP_PKEY_CTX *ctx)
828e1051a39Sopenharmony_ci{
829e1051a39Sopenharmony_ci    const RSA *rsa;
830e1051a39Sopenharmony_ci    RSA_PKEY_CTX *rctx = ctx->data;
831e1051a39Sopenharmony_ci    const EVP_MD *md;
832e1051a39Sopenharmony_ci    const EVP_MD *mgf1md;
833e1051a39Sopenharmony_ci    int min_saltlen, max_saltlen;
834e1051a39Sopenharmony_ci
835e1051a39Sopenharmony_ci    /* Should never happen */
836e1051a39Sopenharmony_ci    if (!pkey_ctx_is_pss(ctx))
837e1051a39Sopenharmony_ci        return 0;
838e1051a39Sopenharmony_ci    rsa = EVP_PKEY_get0_RSA(ctx->pkey);
839e1051a39Sopenharmony_ci    /* If no restrictions just return */
840e1051a39Sopenharmony_ci    if (rsa->pss == NULL)
841e1051a39Sopenharmony_ci        return 1;
842e1051a39Sopenharmony_ci    /* Get and check parameters */
843e1051a39Sopenharmony_ci    if (!ossl_rsa_pss_get_param(rsa->pss, &md, &mgf1md, &min_saltlen))
844e1051a39Sopenharmony_ci        return 0;
845e1051a39Sopenharmony_ci
846e1051a39Sopenharmony_ci    /* See if minimum salt length exceeds maximum possible */
847e1051a39Sopenharmony_ci    max_saltlen = RSA_size(rsa) - EVP_MD_get_size(md);
848e1051a39Sopenharmony_ci    if ((RSA_bits(rsa) & 0x7) == 1)
849e1051a39Sopenharmony_ci        max_saltlen--;
850e1051a39Sopenharmony_ci    if (min_saltlen > max_saltlen) {
851e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_SALT_LENGTH);
852e1051a39Sopenharmony_ci        return 0;
853e1051a39Sopenharmony_ci    }
854e1051a39Sopenharmony_ci
855e1051a39Sopenharmony_ci    rctx->min_saltlen = min_saltlen;
856e1051a39Sopenharmony_ci
857e1051a39Sopenharmony_ci    /*
858e1051a39Sopenharmony_ci     * Set PSS restrictions as defaults: we can then block any attempt to
859e1051a39Sopenharmony_ci     * use invalid values in pkey_rsa_ctrl
860e1051a39Sopenharmony_ci     */
861e1051a39Sopenharmony_ci
862e1051a39Sopenharmony_ci    rctx->md = md;
863e1051a39Sopenharmony_ci    rctx->mgf1md = mgf1md;
864e1051a39Sopenharmony_ci    rctx->saltlen = min_saltlen;
865e1051a39Sopenharmony_ci
866e1051a39Sopenharmony_ci    return 1;
867e1051a39Sopenharmony_ci}
868e1051a39Sopenharmony_ci
869e1051a39Sopenharmony_cistatic const EVP_PKEY_METHOD rsa_pss_pkey_meth = {
870e1051a39Sopenharmony_ci    EVP_PKEY_RSA_PSS,
871e1051a39Sopenharmony_ci    EVP_PKEY_FLAG_AUTOARGLEN,
872e1051a39Sopenharmony_ci    pkey_rsa_init,
873e1051a39Sopenharmony_ci    pkey_rsa_copy,
874e1051a39Sopenharmony_ci    pkey_rsa_cleanup,
875e1051a39Sopenharmony_ci
876e1051a39Sopenharmony_ci    0, 0,
877e1051a39Sopenharmony_ci
878e1051a39Sopenharmony_ci    0,
879e1051a39Sopenharmony_ci    pkey_rsa_keygen,
880e1051a39Sopenharmony_ci
881e1051a39Sopenharmony_ci    pkey_pss_init,
882e1051a39Sopenharmony_ci    pkey_rsa_sign,
883e1051a39Sopenharmony_ci
884e1051a39Sopenharmony_ci    pkey_pss_init,
885e1051a39Sopenharmony_ci    pkey_rsa_verify,
886e1051a39Sopenharmony_ci
887e1051a39Sopenharmony_ci    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
888e1051a39Sopenharmony_ci
889e1051a39Sopenharmony_ci    pkey_rsa_ctrl,
890e1051a39Sopenharmony_ci    pkey_rsa_ctrl_str
891e1051a39Sopenharmony_ci};
892e1051a39Sopenharmony_ci
893e1051a39Sopenharmony_ciconst EVP_PKEY_METHOD *ossl_rsa_pss_pkey_method(void)
894e1051a39Sopenharmony_ci{
895e1051a39Sopenharmony_ci    return &rsa_pss_pkey_meth;
896e1051a39Sopenharmony_ci}
897