1480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org/* crypto/rsa/rsa_pmeth.c */
2480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * project 2006.
4480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org */
5480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org/* ====================================================================
6480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
7480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *
8480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * Redistribution and use in source and binary forms, with or without
9480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * modification, are permitted provided that the following conditions
10480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * are met:
11480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *
12480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * 1. Redistributions of source code must retain the above copyright
13480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *    notice, this list of conditions and the following disclaimer.
14480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *
15480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * 2. Redistributions in binary form must reproduce the above copyright
16480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *    notice, this list of conditions and the following disclaimer in
17480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *    the documentation and/or other materials provided with the
18480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *    distribution.
19480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *
20480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * 3. All advertising materials mentioning features or use of this
21480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *    software must display the following acknowledgment:
22480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *    "This product includes software developed by the OpenSSL Project
23480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *
25480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *    endorse or promote products derived from this software without
27480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *    prior written permission. For written permission, please contact
28480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *    licensing@OpenSSL.org.
29480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *
30480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * 5. Products derived from this software may not be called "OpenSSL"
31480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *    nor may "OpenSSL" appear in their names without prior written
32480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *    permission of the OpenSSL Project.
33480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *
34480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * 6. Redistributions of any form whatsoever must retain the following
35480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *    acknowledgment:
36480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *    "This product includes software developed by the OpenSSL Project
37480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *
39480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * OF THE POSSIBILITY OF SUCH DAMAGE.
51480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * ====================================================================
52480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *
53480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * This product includes cryptographic software written by Eric Young
54480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * (eay@cryptsoft.com).  This product includes software written by Tim
55480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * Hudson (tjh@cryptsoft.com).
56480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *
57480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org */
58480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
59480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#include <stdio.h>
60480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#include "cryptlib.h"
61480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#include <openssl/asn1t.h>
62480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#include <openssl/x509.h>
63480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#include <openssl/rsa.h>
64480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#include <openssl/bn.h>
65480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#include <openssl/evp.h>
662c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifndef OPENSSL_NO_CMS
672c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#include <openssl/cms.h>
682c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
692c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifdef OPENSSL_FIPS
702c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#include <openssl/fips.h>
712c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
72480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#include "evp_locl.h"
73480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#include "rsa_locl.h"
74480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
75480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org/* RSA pkey context structure */
76480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
77480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.orgtypedef struct
78480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	{
79480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	/* Key gen parameters */
80480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	int nbits;
81480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	BIGNUM *pub_exp;
82480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	/* Keygen callback info */
83480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	int gentmp[2];
84480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	/* RSA padding mode */
85480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	int pad_mode;
86480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	/* message digest */
87480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	const EVP_MD *md;
882c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	/* message digest for MGF1 */
892c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	const EVP_MD *mgf1md;
90480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	/* PSS/OAEP salt length */
91480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	int saltlen;
92480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	/* Temp buffer */
93480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	unsigned char *tbuf;
94480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	} RSA_PKEY_CTX;
95480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
96480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.orgstatic int pkey_rsa_init(EVP_PKEY_CTX *ctx)
97480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	{
98480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	RSA_PKEY_CTX *rctx;
99480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	rctx = OPENSSL_malloc(sizeof(RSA_PKEY_CTX));
100480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (!rctx)
101480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return 0;
102480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	rctx->nbits = 1024;
103480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	rctx->pub_exp = NULL;
104480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	rctx->pad_mode = RSA_PKCS1_PADDING;
105480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	rctx->md = NULL;
1062c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	rctx->mgf1md = NULL;
107480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	rctx->tbuf = NULL;
108480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
109480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	rctx->saltlen = -2;
110480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
111480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	ctx->data = rctx;
112480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	ctx->keygen_info = rctx->gentmp;
113480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	ctx->keygen_info_count = 2;
114480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
115480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	return 1;
116480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	}
117480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
118480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.orgstatic int pkey_rsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
119480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	{
120480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	RSA_PKEY_CTX *dctx, *sctx;
121480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (!pkey_rsa_init(dst))
122480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return 0;
123480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org       	sctx = src->data;
124480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	dctx = dst->data;
125480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	dctx->nbits = sctx->nbits;
126480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (sctx->pub_exp)
127480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
128480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		dctx->pub_exp = BN_dup(sctx->pub_exp);
129480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (!dctx->pub_exp)
130480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return 0;
131480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
132480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	dctx->pad_mode = sctx->pad_mode;
133480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	dctx->md = sctx->md;
134480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	return 1;
135480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	}
136480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
137480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.orgstatic int setup_tbuf(RSA_PKEY_CTX *ctx, EVP_PKEY_CTX *pk)
138480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	{
139480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (ctx->tbuf)
140480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return 1;
141480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	ctx->tbuf = OPENSSL_malloc(EVP_PKEY_size(pk->pkey));
142480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (!ctx->tbuf)
143480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return 0;
144480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	return 1;
145480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	}
146480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
147480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.orgstatic void pkey_rsa_cleanup(EVP_PKEY_CTX *ctx)
148480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	{
149480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	RSA_PKEY_CTX *rctx = ctx->data;
150480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (rctx)
151480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
152480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (rctx->pub_exp)
153480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			BN_free(rctx->pub_exp);
154480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (rctx->tbuf)
155480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			OPENSSL_free(rctx->tbuf);
156480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		OPENSSL_free(rctx);
157480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
158480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	}
1592c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifdef OPENSSL_FIPS
1602c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org/* FIP checker. Return value indicates status of context parameters:
1612c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * 1  : redirect to FIPS.
1622c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * 0  : don't redirect to FIPS.
1632c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * -1 : illegal operation in FIPS mode.
1642c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org */
1652c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
1662c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgstatic int pkey_fips_check_ctx(EVP_PKEY_CTX *ctx)
1672c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	{
1682c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	RSA_PKEY_CTX *rctx = ctx->data;
1692c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	RSA *rsa = ctx->pkey->pkey.rsa;
1702c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	int rv = -1;
1712c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	if (!FIPS_mode())
1722c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		return 0;
1732c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	if (rsa->flags & RSA_FLAG_NON_FIPS_ALLOW)
1742c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		rv = 0;
1752c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	if (!(rsa->meth->flags & RSA_FLAG_FIPS_METHOD) && rv)
1762c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		return -1;
1772c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	if (rctx->md && !(rctx->md->flags & EVP_MD_FLAG_FIPS))
1782c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		return rv;
1792c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	if (rctx->mgf1md && !(rctx->mgf1md->flags & EVP_MD_FLAG_FIPS))
1802c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		return rv;
1812c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	return 1;
1822c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	}
1832c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
184480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
185480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.orgstatic int pkey_rsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
186480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					const unsigned char *tbs, size_t tbslen)
187480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	{
188480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	int ret;
189480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	RSA_PKEY_CTX *rctx = ctx->data;
190480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	RSA *rsa = ctx->pkey->pkey.rsa;
191480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
1922c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifdef OPENSSL_FIPS
1932c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	ret = pkey_fips_check_ctx(ctx);
1942c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	if (ret < 0)
1952c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		{
1962c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		RSAerr(RSA_F_PKEY_RSA_SIGN, RSA_R_OPERATION_NOT_ALLOWED_IN_FIPS_MODE);
1972c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		return -1;
1982c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		}
1992c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
2002c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
201480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (rctx->md)
202480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
203480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (tbslen != (size_t)EVP_MD_size(rctx->md))
204480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
205480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			RSAerr(RSA_F_PKEY_RSA_SIGN,
206480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					RSA_R_INVALID_DIGEST_LENGTH);
207480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return -1;
208480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
2092c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifdef OPENSSL_FIPS
2102c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (ret > 0)
2112c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			{
2122c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			unsigned int slen;
2132c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			ret = FIPS_rsa_sign_digest(rsa, tbs, tbslen, rctx->md,
2142c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org							rctx->pad_mode,
2152c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org							rctx->saltlen,
2162c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org							rctx->mgf1md,
2172c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org							sig, &slen);
2182c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			if (ret > 0)
2192c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				*siglen = slen;
2202c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			else
2212c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				*siglen = 0;
2222c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			return ret;
2232c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			}
2242c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
2252c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
2262c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (EVP_MD_type(rctx->md) == NID_mdc2)
2272c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			{
2282c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			unsigned int sltmp;
2292c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			if (rctx->pad_mode != RSA_PKCS1_PADDING)
2302c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				return -1;
2312c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			ret = RSA_sign_ASN1_OCTET_STRING(NID_mdc2,
2322c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org						tbs, tbslen, sig, &sltmp, rsa);
2332c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
2342c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			if (ret <= 0)
2352c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				return ret;
2362c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			ret = sltmp;
2372c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			}
2382c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		else if (rctx->pad_mode == RSA_X931_PADDING)
239480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
240480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (!setup_tbuf(rctx, ctx))
241480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				return -1;
242480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			memcpy(rctx->tbuf, tbs, tbslen);
243480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			rctx->tbuf[tbslen] =
244480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				RSA_X931_hash_id(EVP_MD_type(rctx->md));
245480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			ret = RSA_private_encrypt(tbslen + 1, rctx->tbuf,
246480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org						sig, rsa, RSA_X931_PADDING);
247480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
248480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else if (rctx->pad_mode == RSA_PKCS1_PADDING)
249480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
250480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			unsigned int sltmp;
251480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			ret = RSA_sign(EVP_MD_type(rctx->md),
252480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org						tbs, tbslen, sig, &sltmp, rsa);
253480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (ret <= 0)
254480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				return ret;
255480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			ret = sltmp;
256480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
257480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else if (rctx->pad_mode == RSA_PKCS1_PSS_PADDING)
258480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
259480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (!setup_tbuf(rctx, ctx))
260480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				return -1;
2612c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			if (!RSA_padding_add_PKCS1_PSS_mgf1(rsa,
2622c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org						rctx->tbuf, tbs,
2632c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org						rctx->md, rctx->mgf1md,
2642c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org						rctx->saltlen))
265480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				return -1;
266480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			ret = RSA_private_encrypt(RSA_size(rsa), rctx->tbuf,
267480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org						sig, rsa, RSA_NO_PADDING);
268480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
269480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else
270480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return -1;
271480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
272480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	else
273480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		ret = RSA_private_encrypt(tbslen, tbs, sig, ctx->pkey->pkey.rsa,
274480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org							rctx->pad_mode);
275480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (ret < 0)
276480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return ret;
277480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	*siglen = ret;
278480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	return 1;
279480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	}
280480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
281480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
282480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.orgstatic int pkey_rsa_verifyrecover(EVP_PKEY_CTX *ctx,
283480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					unsigned char *rout, size_t *routlen,
284480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					const unsigned char *sig, size_t siglen)
285480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	{
286480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	int ret;
287480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	RSA_PKEY_CTX *rctx = ctx->data;
288480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
289480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (rctx->md)
290480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
291480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (rctx->pad_mode == RSA_X931_PADDING)
292480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
293480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (!setup_tbuf(rctx, ctx))
294480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				return -1;
295480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			ret = RSA_public_decrypt(siglen, sig,
296480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org						rctx->tbuf, ctx->pkey->pkey.rsa,
297480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org						RSA_X931_PADDING);
298480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (ret < 1)
299480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				return 0;
300480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			ret--;
301480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (rctx->tbuf[ret] !=
302480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				RSA_X931_hash_id(EVP_MD_type(rctx->md)))
303480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				{
304480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				RSAerr(RSA_F_PKEY_RSA_VERIFYRECOVER,
305480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org						RSA_R_ALGORITHM_MISMATCH);
306480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				return 0;
307480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				}
308480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (ret != EVP_MD_size(rctx->md))
309480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				{
310480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				RSAerr(RSA_F_PKEY_RSA_VERIFYRECOVER,
311480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					RSA_R_INVALID_DIGEST_LENGTH);
312480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				return 0;
313480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				}
314480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (rout)
315480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				memcpy(rout, rctx->tbuf, ret);
316480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
317480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else if (rctx->pad_mode == RSA_PKCS1_PADDING)
318480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
319480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			size_t sltmp;
320480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			ret = int_rsa_verify(EVP_MD_type(rctx->md),
321480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org						NULL, 0, rout, &sltmp,
322480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					sig, siglen, ctx->pkey->pkey.rsa);
323480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (ret <= 0)
324480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				return 0;
325480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			ret = sltmp;
326480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
327480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else
328480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return -1;
329480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
330480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	else
331480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		ret = RSA_public_decrypt(siglen, sig, rout, ctx->pkey->pkey.rsa,
332480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org							rctx->pad_mode);
333480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (ret < 0)
334480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return ret;
335480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	*routlen = ret;
336480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	return 1;
337480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	}
338480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
339480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.orgstatic int pkey_rsa_verify(EVP_PKEY_CTX *ctx,
340480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					const unsigned char *sig, size_t siglen,
341480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					const unsigned char *tbs, size_t tbslen)
342480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	{
343480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	RSA_PKEY_CTX *rctx = ctx->data;
344480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	RSA *rsa = ctx->pkey->pkey.rsa;
345480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	size_t rslen;
3462c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifdef OPENSSL_FIPS
3472c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	int rv;
3482c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	rv = pkey_fips_check_ctx(ctx);
3492c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	if (rv < 0)
3502c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		{
3512c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		RSAerr(RSA_F_PKEY_RSA_VERIFY, RSA_R_OPERATION_NOT_ALLOWED_IN_FIPS_MODE);
3522c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		return -1;
3532c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		}
3542c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
355480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (rctx->md)
356480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
3572c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifdef OPENSSL_FIPS
3582c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (rv > 0)
3592c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			{
3602c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			return FIPS_rsa_verify_digest(rsa,
3612c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org							tbs, tbslen,
3622c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org							rctx->md,
3632c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org							rctx->pad_mode,
3642c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org							rctx->saltlen,
3652c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org							rctx->mgf1md,
3662c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org							sig, siglen);
3672c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
3682c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			}
3692c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
370480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (rctx->pad_mode == RSA_PKCS1_PADDING)
371480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return RSA_verify(EVP_MD_type(rctx->md), tbs, tbslen,
372480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					sig, siglen, rsa);
373480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (rctx->pad_mode == RSA_X931_PADDING)
374480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
375480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (pkey_rsa_verifyrecover(ctx, NULL, &rslen,
376480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					sig, siglen) <= 0)
377480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				return 0;
378480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
379480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else if (rctx->pad_mode == RSA_PKCS1_PSS_PADDING)
380480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
381480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			int ret;
382480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (!setup_tbuf(rctx, ctx))
383480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				return -1;
384480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			ret = RSA_public_decrypt(siglen, sig, rctx->tbuf,
385480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org							rsa, RSA_NO_PADDING);
386480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (ret <= 0)
387480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				return 0;
3882c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			ret = RSA_verify_PKCS1_PSS_mgf1(rsa, tbs,
3892c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org						rctx->md, rctx->mgf1md,
390480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org						rctx->tbuf, rctx->saltlen);
391480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (ret <= 0)
392480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				return 0;
393480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return 1;
394480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
395480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else
396480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return -1;
397480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
398480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	else
399480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
400480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (!setup_tbuf(rctx, ctx))
401480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return -1;
402480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		rslen = RSA_public_decrypt(siglen, sig, rctx->tbuf,
403480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org						rsa, rctx->pad_mode);
404480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (rslen == 0)
405480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return 0;
406480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
407480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
408480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if ((rslen != tbslen) || memcmp(tbs, rctx->tbuf, rslen))
409480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return 0;
410480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
411480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	return 1;
412480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
413480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	}
414480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
415480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
416480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.orgstatic int pkey_rsa_encrypt(EVP_PKEY_CTX *ctx,
417480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					unsigned char *out, size_t *outlen,
418480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					const unsigned char *in, size_t inlen)
419480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	{
420480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	int ret;
421480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	RSA_PKEY_CTX *rctx = ctx->data;
422480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	ret = RSA_public_encrypt(inlen, in, out, ctx->pkey->pkey.rsa,
423480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org							rctx->pad_mode);
424480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (ret < 0)
425480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return ret;
426480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	*outlen = ret;
427480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	return 1;
428480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	}
429480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
430480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.orgstatic int pkey_rsa_decrypt(EVP_PKEY_CTX *ctx,
431480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					unsigned char *out, size_t *outlen,
432480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					const unsigned char *in, size_t inlen)
433480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	{
434480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	int ret;
435480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	RSA_PKEY_CTX *rctx = ctx->data;
436480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	ret = RSA_private_decrypt(inlen, in, out, ctx->pkey->pkey.rsa,
437480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org							rctx->pad_mode);
438480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (ret < 0)
439480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return ret;
440480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	*outlen = ret;
441480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	return 1;
442480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	}
443480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
444480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.orgstatic int check_padding_md(const EVP_MD *md, int padding)
445480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	{
446480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (!md)
447480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return 1;
448480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
449480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (padding == RSA_NO_PADDING)
450480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
451480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		RSAerr(RSA_F_CHECK_PADDING_MD, RSA_R_INVALID_PADDING_MODE);
452480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return 0;
453480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
454480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
455480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (padding == RSA_X931_PADDING)
456480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
457480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (RSA_X931_hash_id(EVP_MD_type(md)) == -1)
458480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
459480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			RSAerr(RSA_F_CHECK_PADDING_MD,
460480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org						RSA_R_INVALID_X931_DIGEST);
461480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return 0;
462480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
463480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return 1;
464480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
465480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
466480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	return 1;
467480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	}
468480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
469480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
470480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.orgstatic int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
471480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	{
472480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	RSA_PKEY_CTX *rctx = ctx->data;
473480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	switch (type)
474480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
475480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		case EVP_PKEY_CTRL_RSA_PADDING:
476480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if ((p1 >= RSA_PKCS1_PADDING) && (p1 <= RSA_PKCS1_PSS_PADDING))
477480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
478480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (!check_padding_md(rctx->md, p1))
479480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				return 0;
480480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (p1 == RSA_PKCS1_PSS_PADDING)
481480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				{
482480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				if (!(ctx->operation &
483480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				     (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY)))
484480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					goto bad_pad;
485480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				if (!rctx->md)
486480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					rctx->md = EVP_sha1();
487480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				}
488480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (p1 == RSA_PKCS1_OAEP_PADDING)
489480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				{
490480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				if (!(ctx->operation & EVP_PKEY_OP_TYPE_CRYPT))
491480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					goto bad_pad;
492480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				if (!rctx->md)
493480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					rctx->md = EVP_sha1();
494480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				}
495480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			rctx->pad_mode = p1;
496480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return 1;
497480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
498480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		bad_pad:
499480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		RSAerr(RSA_F_PKEY_RSA_CTRL,
500480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE);
501480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return -2;
502480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
5032c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		case EVP_PKEY_CTRL_GET_RSA_PADDING:
5042c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		*(int *)p2 = rctx->pad_mode;
5052c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		return 1;
5062c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
507480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		case EVP_PKEY_CTRL_RSA_PSS_SALTLEN:
5082c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		case EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN:
509480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING)
510480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
511480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_PSS_SALTLEN);
512480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return -2;
513480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
5142c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (type == EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN)
5152c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			*(int *)p2 = rctx->saltlen;
5162c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		else
5172c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			{
5182c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			if (p1 < -2)
5192c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				return -2;
5202c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			rctx->saltlen = p1;
5212c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			}
522480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return 1;
523480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
524480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		case EVP_PKEY_CTRL_RSA_KEYGEN_BITS:
525480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (p1 < 256)
526480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
527480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_KEYBITS);
528480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return -2;
529480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
530480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		rctx->nbits = p1;
531480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return 1;
532480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
533480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		case EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP:
534480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (!p2)
535480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return -2;
536480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		rctx->pub_exp = p2;
537480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return 1;
538480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
539480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		case EVP_PKEY_CTRL_MD:
540480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (!check_padding_md(p2, rctx->pad_mode))
541480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return 0;
542480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		rctx->md = p2;
543480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return 1;
544480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
5452c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		case EVP_PKEY_CTRL_RSA_MGF1_MD:
5462c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		case EVP_PKEY_CTRL_GET_RSA_MGF1_MD:
5472c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING)
5482c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			{
5492c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_MGF1_MD);
5502c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			return -2;
5512c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			}
5522c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (type == EVP_PKEY_CTRL_GET_RSA_MGF1_MD)
5532c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			{
5542c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			if (rctx->mgf1md)
5552c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				*(const EVP_MD **)p2 = rctx->mgf1md;
5562c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			else
5572c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				*(const EVP_MD **)p2 = rctx->md;
5582c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			}
5592c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		else
5602c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			rctx->mgf1md = p2;
5612c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		return 1;
5622c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
563480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		case EVP_PKEY_CTRL_DIGESTINIT:
564480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
565480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		case EVP_PKEY_CTRL_PKCS7_DECRYPT:
566480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		case EVP_PKEY_CTRL_PKCS7_SIGN:
5672c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		return 1;
568480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#ifndef OPENSSL_NO_CMS
569480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		case EVP_PKEY_CTRL_CMS_DECRYPT:
5702c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		{
5712c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		X509_ALGOR *alg = NULL;
5722c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		ASN1_OBJECT *encalg = NULL;
5732c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (p2)
5742c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			CMS_RecipientInfo_ktri_get0_algs(p2, NULL, NULL, &alg);
5752c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (alg)
5762c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			X509_ALGOR_get0(&encalg, NULL, NULL, alg);
5772c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (encalg && OBJ_obj2nid(encalg) == NID_rsaesOaep)
5782c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			rctx->pad_mode = RSA_PKCS1_OAEP_PADDING;
5792c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		}
5802c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		case EVP_PKEY_CTRL_CMS_ENCRYPT:
581480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		case EVP_PKEY_CTRL_CMS_SIGN:
582480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return 1;
5832c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
584480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		case EVP_PKEY_CTRL_PEER_KEY:
585480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			RSAerr(RSA_F_PKEY_RSA_CTRL,
586480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
587480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return -2;
588480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
589480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		default:
590480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return -2;
591480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
592480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
593480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	}
594480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
595480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.orgstatic int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx,
596480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			const char *type, const char *value)
597480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	{
598480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (!value)
599480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
600480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		RSAerr(RSA_F_PKEY_RSA_CTRL_STR, RSA_R_VALUE_MISSING);
601480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return 0;
602480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
603480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (!strcmp(type, "rsa_padding_mode"))
604480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
605480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		int pm;
606480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (!strcmp(value, "pkcs1"))
607480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			pm = RSA_PKCS1_PADDING;
608480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else if (!strcmp(value, "sslv23"))
609480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			pm = RSA_SSLV23_PADDING;
610480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else if (!strcmp(value, "none"))
611480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			pm = RSA_NO_PADDING;
612480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else if (!strcmp(value, "oeap"))
613480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			pm = RSA_PKCS1_OAEP_PADDING;
614480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else if (!strcmp(value, "x931"))
615480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			pm = RSA_X931_PADDING;
616480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else if (!strcmp(value, "pss"))
617480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			pm = RSA_PKCS1_PSS_PADDING;
618480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else
619480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
620480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			RSAerr(RSA_F_PKEY_RSA_CTRL_STR,
621480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org						RSA_R_UNKNOWN_PADDING_TYPE);
622480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return -2;
623480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
624480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return EVP_PKEY_CTX_set_rsa_padding(ctx, pm);
625480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
626480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
627480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (!strcmp(type, "rsa_pss_saltlen"))
628480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
629480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		int saltlen;
630480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		saltlen = atoi(value);
631480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, saltlen);
632480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
633480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
634480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (!strcmp(type, "rsa_keygen_bits"))
635480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
636480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		int nbits;
637480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		nbits = atoi(value);
638480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, nbits);
639480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
640480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
641480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (!strcmp(type, "rsa_keygen_pubexp"))
642480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
643480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		int ret;
644480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		BIGNUM *pubexp = NULL;
645480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (!BN_asc2bn(&pubexp, value))
646480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return 0;
647480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		ret = EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, pubexp);
648480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (ret <= 0)
649480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			BN_free(pubexp);
650480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return ret;
651480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
652480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
653480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	return -2;
654480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	}
655480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
656480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.orgstatic int pkey_rsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
657480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	{
658480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	RSA *rsa = NULL;
659480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	RSA_PKEY_CTX *rctx = ctx->data;
660480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	BN_GENCB *pcb, cb;
661480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	int ret;
662480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (!rctx->pub_exp)
663480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
664480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		rctx->pub_exp = BN_new();
665480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (!rctx->pub_exp || !BN_set_word(rctx->pub_exp, RSA_F4))
666480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return 0;
667480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
668480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	rsa = RSA_new();
669480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (!rsa)
670480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return 0;
671480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (ctx->pkey_gencb)
672480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
673480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		pcb = &cb;
674480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		evp_pkey_set_cb_translate(pcb, ctx);
675480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
676480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	else
677480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		pcb = NULL;
678480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	ret = RSA_generate_key_ex(rsa, rctx->nbits, rctx->pub_exp, pcb);
679480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (ret > 0)
680480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		EVP_PKEY_assign_RSA(pkey, rsa);
681480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	else
682480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		RSA_free(rsa);
683480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	return ret;
684480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	}
685480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
686480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.orgconst EVP_PKEY_METHOD rsa_pkey_meth =
687480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	{
688480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	EVP_PKEY_RSA,
689480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	EVP_PKEY_FLAG_AUTOARGLEN,
690480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	pkey_rsa_init,
691480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	pkey_rsa_copy,
692480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	pkey_rsa_cleanup,
693480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
694480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	0,0,
695480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
696480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	0,
697480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	pkey_rsa_keygen,
698480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
699480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	0,
700480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	pkey_rsa_sign,
701480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
702480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	0,
703480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	pkey_rsa_verify,
704480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
705480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	0,
706480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	pkey_rsa_verifyrecover,
707480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
708480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
709480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	0,0,0,0,
710480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
711480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	0,
712480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	pkey_rsa_encrypt,
713480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
714480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	0,
715480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	pkey_rsa_decrypt,
716480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
717480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	0,0,
718480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
719480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	pkey_rsa_ctrl,
720480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	pkey_rsa_ctrl_str
721480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
722480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
723480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	};
724