blob: 3b674cdac92dc1ff9dde51f263ce485ae765bb00 [file] [log] [blame]
Adam Langleyd9e397b2015-01-22 14:27:53 -08001/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
2 * project 2006.
3 */
4/* ====================================================================
5 * Copyright (c) 2006 The OpenSSL Project. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 *
19 * 3. All advertising materials mentioning features or use of this
20 * software must display the following acknowledgment:
21 * "This product includes software developed by the OpenSSL Project
22 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
23 *
24 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
25 * endorse or promote products derived from this software without
26 * prior written permission. For written permission, please contact
27 * licensing@OpenSSL.org.
28 *
29 * 5. Products derived from this software may not be called "OpenSSL"
30 * nor may "OpenSSL" appear in their names without prior written
31 * permission of the OpenSSL Project.
32 *
33 * 6. Redistributions of any form whatsoever must retain the following
34 * acknowledgment:
35 * "This product includes software developed by the OpenSSL Project
36 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
37 *
38 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
39 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
41 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
42 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
47 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
49 * OF THE POSSIBILITY OF SUCH DAMAGE.
50 * ====================================================================
51 *
52 * This product includes cryptographic software written by Eric Young
53 * (eay@cryptsoft.com). This product includes software written by Tim
54 * Hudson (tjh@cryptsoft.com). */
55
56#include <openssl/evp.h>
57
Adam Langleye9ada862015-05-11 17:20:37 -070058#include <limits.h>
Adam Langleyd9e397b2015-01-22 14:27:53 -080059#include <string.h>
60
61#include <openssl/bn.h>
62#include <openssl/buf.h>
Adam Langleye9ada862015-05-11 17:20:37 -070063#include <openssl/bytestring.h>
Adam Langleyd9e397b2015-01-22 14:27:53 -080064#include <openssl/digest.h>
65#include <openssl/err.h>
66#include <openssl/mem.h>
David Benjamin4969cc92016-04-22 15:02:23 -040067#include <openssl/nid.h>
Adam Langleyd9e397b2015-01-22 14:27:53 -080068#include <openssl/rsa.h>
69
Robert Sloan69939df2017-01-09 10:53:07 -080070#include "../internal.h"
Adam Langleyd9e397b2015-01-22 14:27:53 -080071#include "../rsa/internal.h"
72#include "internal.h"
73
74
75typedef struct {
76 /* Key gen parameters */
77 int nbits;
78 BIGNUM *pub_exp;
79 /* RSA padding mode */
80 int pad_mode;
81 /* message digest */
82 const EVP_MD *md;
83 /* message digest for MGF1 */
84 const EVP_MD *mgf1md;
85 /* PSS salt length */
86 int saltlen;
87 /* tbuf is a buffer which is either NULL, or is the size of the RSA modulus.
88 * It's used to store the output of RSA operations. */
89 uint8_t *tbuf;
90 /* OAEP label */
91 uint8_t *oaep_label;
92 size_t oaep_labellen;
93} RSA_PKEY_CTX;
94
95static int pkey_rsa_init(EVP_PKEY_CTX *ctx) {
96 RSA_PKEY_CTX *rctx;
97 rctx = OPENSSL_malloc(sizeof(RSA_PKEY_CTX));
98 if (!rctx) {
99 return 0;
100 }
Robert Sloan69939df2017-01-09 10:53:07 -0800101 OPENSSL_memset(rctx, 0, sizeof(RSA_PKEY_CTX));
Adam Langleyd9e397b2015-01-22 14:27:53 -0800102
103 rctx->nbits = 2048;
104 rctx->pad_mode = RSA_PKCS1_PADDING;
105 rctx->saltlen = -2;
106
107 ctx->data = rctx;
108
109 return 1;
110}
111
112static int pkey_rsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) {
113 RSA_PKEY_CTX *dctx, *sctx;
114 if (!pkey_rsa_init(dst)) {
115 return 0;
116 }
117 sctx = src->data;
118 dctx = dst->data;
119 dctx->nbits = sctx->nbits;
120 if (sctx->pub_exp) {
121 dctx->pub_exp = BN_dup(sctx->pub_exp);
122 if (!dctx->pub_exp) {
123 return 0;
124 }
125 }
126
127 dctx->pad_mode = sctx->pad_mode;
128 dctx->md = sctx->md;
129 dctx->mgf1md = sctx->mgf1md;
130 if (sctx->oaep_label) {
Adam Langleye9ada862015-05-11 17:20:37 -0700131 OPENSSL_free(dctx->oaep_label);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800132 dctx->oaep_label = BUF_memdup(sctx->oaep_label, sctx->oaep_labellen);
133 if (!dctx->oaep_label) {
134 return 0;
135 }
136 dctx->oaep_labellen = sctx->oaep_labellen;
137 }
138
139 return 1;
140}
141
142static void pkey_rsa_cleanup(EVP_PKEY_CTX *ctx) {
143 RSA_PKEY_CTX *rctx = ctx->data;
144
145 if (rctx == NULL) {
146 return;
147 }
148
Adam Langleye9ada862015-05-11 17:20:37 -0700149 BN_free(rctx->pub_exp);
150 OPENSSL_free(rctx->tbuf);
151 OPENSSL_free(rctx->oaep_label);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800152 OPENSSL_free(rctx);
153}
154
155static int setup_tbuf(RSA_PKEY_CTX *ctx, EVP_PKEY_CTX *pk) {
156 if (ctx->tbuf) {
157 return 1;
158 }
159 ctx->tbuf = OPENSSL_malloc(EVP_PKEY_size(pk->pkey));
160 if (!ctx->tbuf) {
161 return 0;
162 }
163 return 1;
164}
165
166static int pkey_rsa_sign(EVP_PKEY_CTX *ctx, uint8_t *sig, size_t *siglen,
167 const uint8_t *tbs, size_t tbslen) {
168 RSA_PKEY_CTX *rctx = ctx->data;
169 RSA *rsa = ctx->pkey->pkey.rsa;
170 const size_t key_len = EVP_PKEY_size(ctx->pkey);
171
172 if (!sig) {
173 *siglen = key_len;
174 return 1;
175 }
176
177 if (*siglen < key_len) {
Kenny Rootb8494592015-09-25 02:29:14 +0000178 OPENSSL_PUT_ERROR(EVP, EVP_R_BUFFER_TOO_SMALL);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800179 return 0;
180 }
181
182 if (rctx->md) {
183 unsigned int out_len;
184
185 if (tbslen != EVP_MD_size(rctx->md)) {
Kenny Rootb8494592015-09-25 02:29:14 +0000186 OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_DIGEST_LENGTH);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800187 return 0;
188 }
189
190 if (EVP_MD_type(rctx->md) == NID_mdc2) {
Kenny Rootb8494592015-09-25 02:29:14 +0000191 OPENSSL_PUT_ERROR(EVP, EVP_R_NO_MDC2_SUPPORT);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800192 return 0;
193 }
194
195 switch (rctx->pad_mode) {
196 case RSA_PKCS1_PADDING:
197 if (!RSA_sign(EVP_MD_type(rctx->md), tbs, tbslen, sig, &out_len, rsa)) {
198 return 0;
199 }
200 *siglen = out_len;
201 return 1;
202
203 case RSA_PKCS1_PSS_PADDING:
204 if (!setup_tbuf(rctx, ctx) ||
205 !RSA_padding_add_PKCS1_PSS_mgf1(rsa, rctx->tbuf, tbs, rctx->md,
206 rctx->mgf1md, rctx->saltlen) ||
207 !RSA_sign_raw(rsa, siglen, sig, *siglen, rctx->tbuf, key_len,
208 RSA_NO_PADDING)) {
209 return 0;
210 }
211 return 1;
212
213 default:
214 return 0;
215 }
216 }
217
218 return RSA_sign_raw(rsa, siglen, sig, *siglen, tbs, tbslen, rctx->pad_mode);
219}
220
221static int pkey_rsa_verify(EVP_PKEY_CTX *ctx, const uint8_t *sig,
222 size_t siglen, const uint8_t *tbs,
223 size_t tbslen) {
224 RSA_PKEY_CTX *rctx = ctx->data;
225 RSA *rsa = ctx->pkey->pkey.rsa;
226 size_t rslen;
227 const size_t key_len = EVP_PKEY_size(ctx->pkey);
228
229 if (rctx->md) {
230 switch (rctx->pad_mode) {
231 case RSA_PKCS1_PADDING:
232 return RSA_verify(EVP_MD_type(rctx->md), tbs, tbslen, sig, siglen, rsa);
233
234 case RSA_PKCS1_PSS_PADDING:
Robert Sloan69939df2017-01-09 10:53:07 -0800235 if (tbslen != EVP_MD_size(rctx->md)) {
236 OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_DIGEST_LENGTH);
237 return 0;
238 }
239
Adam Langleyd9e397b2015-01-22 14:27:53 -0800240 if (!setup_tbuf(rctx, ctx) ||
241 !RSA_verify_raw(rsa, &rslen, rctx->tbuf, key_len, sig, siglen,
242 RSA_NO_PADDING) ||
243 !RSA_verify_PKCS1_PSS_mgf1(rsa, tbs, rctx->md, rctx->mgf1md,
244 rctx->tbuf, rctx->saltlen)) {
245 return 0;
246 }
247 return 1;
248
249 default:
250 return 0;
251 }
252 }
253
254 if (!setup_tbuf(rctx, ctx) ||
255 !RSA_verify_raw(rsa, &rslen, rctx->tbuf, key_len, sig, siglen,
256 rctx->pad_mode) ||
257 rslen != tbslen ||
258 CRYPTO_memcmp(tbs, rctx->tbuf, rslen) != 0) {
259 return 0;
260 }
261
262 return 1;
263}
264
David Benjamin4969cc92016-04-22 15:02:23 -0400265static int pkey_rsa_verify_recover(EVP_PKEY_CTX *ctx, uint8_t *out,
266 size_t *out_len, const uint8_t *sig,
267 size_t sig_len) {
268 RSA_PKEY_CTX *rctx = ctx->data;
269 RSA *rsa = ctx->pkey->pkey.rsa;
270 const size_t key_len = EVP_PKEY_size(ctx->pkey);
271
272 if (out == NULL) {
273 *out_len = key_len;
274 return 1;
275 }
276
277 if (*out_len < key_len) {
278 OPENSSL_PUT_ERROR(EVP, EVP_R_BUFFER_TOO_SMALL);
279 return 0;
280 }
281
282 if (!setup_tbuf(rctx, ctx)) {
283 return 0;
284 }
285
286 if (rctx->md == NULL) {
287 const int ret = RSA_public_decrypt(sig_len, sig, rctx->tbuf,
288 ctx->pkey->pkey.rsa, rctx->pad_mode);
289 if (ret < 0) {
290 return 0;
291 }
292 *out_len = ret;
Robert Sloan69939df2017-01-09 10:53:07 -0800293 OPENSSL_memcpy(out, rctx->tbuf, *out_len);
David Benjamin4969cc92016-04-22 15:02:23 -0400294 return 1;
295 }
296
297 if (rctx->pad_mode != RSA_PKCS1_PADDING) {
298 return 0;
299 }
300
301 uint8_t *asn1_prefix;
302 size_t asn1_prefix_len;
303 int asn1_prefix_allocated;
304 if (!RSA_add_pkcs1_prefix(&asn1_prefix, &asn1_prefix_len,
305 &asn1_prefix_allocated, EVP_MD_type(rctx->md), NULL,
306 0)) {
307 return 0;
308 }
309
310 size_t rslen;
311 int ok = 1;
312 if (!RSA_verify_raw(rsa, &rslen, rctx->tbuf, key_len, sig, sig_len,
313 RSA_PKCS1_PADDING) ||
314 rslen < asn1_prefix_len ||
315 CRYPTO_memcmp(rctx->tbuf, asn1_prefix, asn1_prefix_len) != 0) {
316 ok = 0;
317 }
318
319 if (asn1_prefix_allocated) {
320 OPENSSL_free(asn1_prefix);
321 }
322
323 if (!ok) {
324 return 0;
325 }
326
327 const size_t result_len = rslen - asn1_prefix_len;
328 if (result_len != EVP_MD_size(rctx->md)) {
329 return 0;
330 }
331
332 if (out != NULL) {
Robert Sloan69939df2017-01-09 10:53:07 -0800333 OPENSSL_memcpy(out, rctx->tbuf + asn1_prefix_len, result_len);
David Benjamin4969cc92016-04-22 15:02:23 -0400334 }
335 *out_len = result_len;
336
337 return 1;
338}
339
Adam Langleyd9e397b2015-01-22 14:27:53 -0800340static int pkey_rsa_encrypt(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *outlen,
341 const uint8_t *in, size_t inlen) {
342 RSA_PKEY_CTX *rctx = ctx->data;
343 RSA *rsa = ctx->pkey->pkey.rsa;
344 const size_t key_len = EVP_PKEY_size(ctx->pkey);
345
346 if (!out) {
347 *outlen = key_len;
348 return 1;
349 }
350
351 if (*outlen < key_len) {
Kenny Rootb8494592015-09-25 02:29:14 +0000352 OPENSSL_PUT_ERROR(EVP, EVP_R_BUFFER_TOO_SMALL);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800353 return 0;
354 }
355
356 if (rctx->pad_mode == RSA_PKCS1_OAEP_PADDING) {
357 if (!setup_tbuf(rctx, ctx) ||
358 !RSA_padding_add_PKCS1_OAEP_mgf1(rctx->tbuf, key_len, in, inlen,
359 rctx->oaep_label, rctx->oaep_labellen,
360 rctx->md, rctx->mgf1md) ||
361 !RSA_encrypt(rsa, outlen, out, *outlen, rctx->tbuf, key_len,
362 RSA_NO_PADDING)) {
363 return 0;
364 }
365 return 1;
366 }
367
368 return RSA_encrypt(rsa, outlen, out, *outlen, in, inlen, rctx->pad_mode);
369}
370
371static int pkey_rsa_decrypt(EVP_PKEY_CTX *ctx, uint8_t *out,
372 size_t *outlen, const uint8_t *in,
373 size_t inlen) {
374 RSA_PKEY_CTX *rctx = ctx->data;
375 RSA *rsa = ctx->pkey->pkey.rsa;
376 const size_t key_len = EVP_PKEY_size(ctx->pkey);
377
378 if (!out) {
379 *outlen = key_len;
380 return 1;
381 }
382
383 if (*outlen < key_len) {
Kenny Rootb8494592015-09-25 02:29:14 +0000384 OPENSSL_PUT_ERROR(EVP, EVP_R_BUFFER_TOO_SMALL);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800385 return 0;
386 }
387
388 if (rctx->pad_mode == RSA_PKCS1_OAEP_PADDING) {
Robert Sloan6f79a502017-04-03 09:16:40 -0700389 size_t padded_len;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800390 if (!setup_tbuf(rctx, ctx) ||
Robert Sloan6f79a502017-04-03 09:16:40 -0700391 !RSA_decrypt(rsa, &padded_len, rctx->tbuf, key_len, in, inlen,
392 RSA_NO_PADDING) ||
393 !RSA_padding_check_PKCS1_OAEP_mgf1(
394 out, outlen, key_len, rctx->tbuf, padded_len, rctx->oaep_label,
395 rctx->oaep_labellen, rctx->md, rctx->mgf1md)) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800396 return 0;
397 }
Adam Langleyd9e397b2015-01-22 14:27:53 -0800398 return 1;
399 }
400
401 return RSA_decrypt(rsa, outlen, out, key_len, in, inlen, rctx->pad_mode);
402}
403
404static int check_padding_md(const EVP_MD *md, int padding) {
405 if (!md) {
406 return 1;
407 }
408
409 if (padding == RSA_NO_PADDING) {
Kenny Rootb8494592015-09-25 02:29:14 +0000410 OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PADDING_MODE);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800411 return 0;
412 }
413
414 return 1;
415}
416
417static int is_known_padding(int padding_mode) {
418 switch (padding_mode) {
419 case RSA_PKCS1_PADDING:
420 case RSA_NO_PADDING:
421 case RSA_PKCS1_OAEP_PADDING:
422 case RSA_PKCS1_PSS_PADDING:
423 return 1;
424 default:
425 return 0;
426 }
427}
428
429static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) {
430 RSA_PKEY_CTX *rctx = ctx->data;
431 switch (type) {
432 case EVP_PKEY_CTRL_RSA_PADDING:
433 if (!is_known_padding(p1) || !check_padding_md(rctx->md, p1) ||
434 (p1 == RSA_PKCS1_PSS_PADDING &&
435 0 == (ctx->operation & (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY))) ||
436 (p1 == RSA_PKCS1_OAEP_PADDING &&
437 0 == (ctx->operation & EVP_PKEY_OP_TYPE_CRYPT))) {
Kenny Rootb8494592015-09-25 02:29:14 +0000438 OPENSSL_PUT_ERROR(EVP, EVP_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE);
Adam Langleye9ada862015-05-11 17:20:37 -0700439 return 0;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800440 }
441 if ((p1 == RSA_PKCS1_PSS_PADDING || p1 == RSA_PKCS1_OAEP_PADDING) &&
442 rctx->md == NULL) {
443 rctx->md = EVP_sha1();
444 }
445 rctx->pad_mode = p1;
446 return 1;
447
448 case EVP_PKEY_CTRL_GET_RSA_PADDING:
449 *(int *)p2 = rctx->pad_mode;
450 return 1;
451
452 case EVP_PKEY_CTRL_RSA_PSS_SALTLEN:
453 case EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN:
454 if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING) {
Kenny Rootb8494592015-09-25 02:29:14 +0000455 OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PSS_SALTLEN);
Adam Langleye9ada862015-05-11 17:20:37 -0700456 return 0;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800457 }
458 if (type == EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN) {
459 *(int *)p2 = rctx->saltlen;
460 } else {
461 if (p1 < -2) {
Adam Langleye9ada862015-05-11 17:20:37 -0700462 return 0;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800463 }
464 rctx->saltlen = p1;
465 }
466 return 1;
467
468 case EVP_PKEY_CTRL_RSA_KEYGEN_BITS:
469 if (p1 < 256) {
Kenny Rootb8494592015-09-25 02:29:14 +0000470 OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_KEYBITS);
Adam Langleye9ada862015-05-11 17:20:37 -0700471 return 0;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800472 }
473 rctx->nbits = p1;
474 return 1;
475
476 case EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP:
477 if (!p2) {
Adam Langleye9ada862015-05-11 17:20:37 -0700478 return 0;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800479 }
480 BN_free(rctx->pub_exp);
481 rctx->pub_exp = p2;
482 return 1;
483
484 case EVP_PKEY_CTRL_RSA_OAEP_MD:
485 case EVP_PKEY_CTRL_GET_RSA_OAEP_MD:
486 if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
Kenny Rootb8494592015-09-25 02:29:14 +0000487 OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PADDING_MODE);
Adam Langleye9ada862015-05-11 17:20:37 -0700488 return 0;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800489 }
490 if (type == EVP_PKEY_CTRL_GET_RSA_OAEP_MD) {
491 *(const EVP_MD **)p2 = rctx->md;
492 } else {
493 rctx->md = p2;
494 }
495 return 1;
496
497 case EVP_PKEY_CTRL_MD:
498 if (!check_padding_md(p2, rctx->pad_mode)) {
499 return 0;
500 }
501 rctx->md = p2;
502 return 1;
503
504 case EVP_PKEY_CTRL_GET_MD:
505 *(const EVP_MD **)p2 = rctx->md;
506 return 1;
507
508 case EVP_PKEY_CTRL_RSA_MGF1_MD:
509 case EVP_PKEY_CTRL_GET_RSA_MGF1_MD:
510 if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING &&
511 rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
Kenny Rootb8494592015-09-25 02:29:14 +0000512 OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_MGF1_MD);
Adam Langleye9ada862015-05-11 17:20:37 -0700513 return 0;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800514 }
515 if (type == EVP_PKEY_CTRL_GET_RSA_MGF1_MD) {
516 if (rctx->mgf1md) {
517 *(const EVP_MD **)p2 = rctx->mgf1md;
518 } else {
519 *(const EVP_MD **)p2 = rctx->md;
520 }
521 } else {
522 rctx->mgf1md = p2;
523 }
524 return 1;
525
526 case EVP_PKEY_CTRL_RSA_OAEP_LABEL:
527 if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
Kenny Rootb8494592015-09-25 02:29:14 +0000528 OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PADDING_MODE);
Adam Langleye9ada862015-05-11 17:20:37 -0700529 return 0;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800530 }
Adam Langleye9ada862015-05-11 17:20:37 -0700531 OPENSSL_free(rctx->oaep_label);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800532 if (p2 && p1 > 0) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800533 rctx->oaep_label = p2;
534 rctx->oaep_labellen = p1;
535 } else {
536 rctx->oaep_label = NULL;
537 rctx->oaep_labellen = 0;
538 }
539 return 1;
540
541 case EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL:
542 if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
Kenny Rootb8494592015-09-25 02:29:14 +0000543 OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PADDING_MODE);
Adam Langleye9ada862015-05-11 17:20:37 -0700544 return 0;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800545 }
Adam Langleye9ada862015-05-11 17:20:37 -0700546 CBS_init((CBS *)p2, rctx->oaep_label, rctx->oaep_labellen);
547 return 1;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800548
Adam Langleyd9e397b2015-01-22 14:27:53 -0800549 default:
Kenny Rootb8494592015-09-25 02:29:14 +0000550 OPENSSL_PUT_ERROR(EVP, EVP_R_COMMAND_NOT_SUPPORTED);
Adam Langleye9ada862015-05-11 17:20:37 -0700551 return 0;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800552 }
553}
554
555static int pkey_rsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) {
556 RSA *rsa = NULL;
557 RSA_PKEY_CTX *rctx = ctx->data;
558
559 if (!rctx->pub_exp) {
560 rctx->pub_exp = BN_new();
Adam Langleye9ada862015-05-11 17:20:37 -0700561 if (!rctx->pub_exp || !BN_set_word(rctx->pub_exp, RSA_F4)) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800562 return 0;
Adam Langleye9ada862015-05-11 17:20:37 -0700563 }
Adam Langleyd9e397b2015-01-22 14:27:53 -0800564 }
565 rsa = RSA_new();
566 if (!rsa) {
567 return 0;
568 }
569
570 if (!RSA_generate_key_ex(rsa, rctx->nbits, rctx->pub_exp, NULL)) {
571 RSA_free(rsa);
572 return 0;
573 }
574
575 EVP_PKEY_assign_RSA(pkey, rsa);
576 return 1;
577}
578
579const EVP_PKEY_METHOD rsa_pkey_meth = {
David Benjamin4969cc92016-04-22 15:02:23 -0400580 EVP_PKEY_RSA,
581 pkey_rsa_init,
582 pkey_rsa_copy,
583 pkey_rsa_cleanup,
584 pkey_rsa_keygen,
585 pkey_rsa_sign,
Robert Sloan572a4e22017-04-17 10:52:19 -0700586 NULL /* sign_message */,
David Benjamin4969cc92016-04-22 15:02:23 -0400587 pkey_rsa_verify,
Robert Sloan572a4e22017-04-17 10:52:19 -0700588 NULL /* verify_message */,
David Benjamin4969cc92016-04-22 15:02:23 -0400589 pkey_rsa_verify_recover,
590 pkey_rsa_encrypt,
591 pkey_rsa_decrypt,
592 0 /* derive */,
593 pkey_rsa_ctrl,
Adam Langleyd9e397b2015-01-22 14:27:53 -0800594};
595
596int EVP_PKEY_CTX_set_rsa_padding(EVP_PKEY_CTX *ctx, int padding) {
597 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -1, EVP_PKEY_CTRL_RSA_PADDING,
598 padding, NULL);
599}
600
601int EVP_PKEY_CTX_get_rsa_padding(EVP_PKEY_CTX *ctx, int *out_padding) {
602 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -1, EVP_PKEY_CTRL_GET_RSA_PADDING,
603 0, out_padding);
604}
605
606int EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int salt_len) {
607 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA,
608 (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY),
609 EVP_PKEY_CTRL_RSA_PSS_SALTLEN, salt_len, NULL);
610}
611
612int EVP_PKEY_CTX_get_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int *out_salt_len) {
613 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA,
614 (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY),
615 EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN, 0, out_salt_len);
616}
617
618int EVP_PKEY_CTX_set_rsa_keygen_bits(EVP_PKEY_CTX *ctx, int bits) {
619 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_KEYGEN,
620 EVP_PKEY_CTRL_RSA_KEYGEN_BITS, bits, NULL);
621}
622
623int EVP_PKEY_CTX_set_rsa_keygen_pubexp(EVP_PKEY_CTX *ctx, BIGNUM *e) {
624 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_KEYGEN,
625 EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP, 0, e);
626}
627
628int EVP_PKEY_CTX_set_rsa_oaep_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) {
629 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT,
630 EVP_PKEY_CTRL_RSA_OAEP_MD, 0, (void *)md);
631}
632
633int EVP_PKEY_CTX_get_rsa_oaep_md(EVP_PKEY_CTX *ctx, const EVP_MD **out_md) {
634 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT,
635 EVP_PKEY_CTRL_GET_RSA_OAEP_MD, 0, (void*) out_md);
636}
637
638int EVP_PKEY_CTX_set_rsa_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) {
639 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA,
640 EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT,
641 EVP_PKEY_CTRL_RSA_MGF1_MD, 0, (void*) md);
642}
643
644int EVP_PKEY_CTX_get_rsa_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD **out_md) {
645 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA,
646 EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT,
647 EVP_PKEY_CTRL_GET_RSA_MGF1_MD, 0, (void*) out_md);
648}
649
David Benjamin4969cc92016-04-22 15:02:23 -0400650int EVP_PKEY_CTX_set0_rsa_oaep_label(EVP_PKEY_CTX *ctx, uint8_t *label,
Adam Langleyd9e397b2015-01-22 14:27:53 -0800651 size_t label_len) {
David Benjamin4969cc92016-04-22 15:02:23 -0400652 if (label_len > INT_MAX) {
Adam Langleye9ada862015-05-11 17:20:37 -0700653 return 0;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800654 }
655
656 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT,
David Benjamin4969cc92016-04-22 15:02:23 -0400657 EVP_PKEY_CTRL_RSA_OAEP_LABEL, (int)label_len,
Adam Langleyd9e397b2015-01-22 14:27:53 -0800658 (void *)label);
659}
660
661int EVP_PKEY_CTX_get0_rsa_oaep_label(EVP_PKEY_CTX *ctx,
662 const uint8_t **out_label) {
Adam Langleye9ada862015-05-11 17:20:37 -0700663 CBS label;
664 if (!EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT,
665 EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL, 0, &label)) {
666 return -1;
667 }
668 if (CBS_len(&label) > INT_MAX) {
Kenny Rootb8494592015-09-25 02:29:14 +0000669 OPENSSL_PUT_ERROR(EVP, ERR_R_OVERFLOW);
Adam Langleye9ada862015-05-11 17:20:37 -0700670 return -1;
671 }
672 *out_label = CBS_data(&label);
673 return (int)CBS_len(&label);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800674}