blob: 92d4853ce8a98903a8ebe80eacfd27f36c2fd02c [file] [log] [blame]
Adam Langley95c29f32014-06-20 12:00:00 -07001/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2 * All rights reserved.
3 *
4 * This package is an SSL implementation written
5 * by Eric Young (eay@cryptsoft.com).
6 * The implementation was written so as to conform with Netscapes SSL.
7 *
8 * This library is free for commercial and non-commercial use as long as
9 * the following conditions are aheared to. The following conditions
10 * apply to all code found in this distribution, be it the RC4, RSA,
11 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
12 * included with this distribution is covered by the same copyright terms
13 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14 *
15 * Copyright remains Eric Young's, and as such any Copyright notices in
16 * the code are not to be removed.
17 * If this package is used in a product, Eric Young should be given attribution
18 * as the author of the parts of the library used.
19 * This can be in the form of a textual message at program startup or
20 * in documentation (online or textual) provided with the package.
21 *
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
24 * are met:
25 * 1. Redistributions of source code must retain the copyright
26 * notice, this list of conditions and the following disclaimer.
27 * 2. Redistributions in binary form must reproduce the above copyright
28 * notice, this list of conditions and the following disclaimer in the
29 * documentation and/or other materials provided with the distribution.
30 * 3. All advertising materials mentioning features or use of this software
31 * must display the following acknowledgement:
32 * "This product includes cryptographic software written by
33 * Eric Young (eay@cryptsoft.com)"
34 * The word 'cryptographic' can be left out if the rouines from the library
35 * being used are not cryptographic related :-).
36 * 4. If you include any Windows specific code (or a derivative thereof) from
37 * the apps directory (application code) you must include an acknowledgement:
38 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39 *
40 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50 * SUCH DAMAGE.
51 *
52 * The licence and distribution terms for any publically available version or
53 * derivative of this code cannot be changed. i.e. this code cannot simply be
54 * copied and put under another distribution licence
55 * [including the GNU Public Licence.] */
56
57#include <openssl/rsa.h>
58
David Benjamin79c59a32015-09-19 13:35:39 -040059#include <limits.h>
Adam Langley2b2d66d2015-01-30 17:08:37 -080060#include <string.h>
61
Adam Langley95c29f32014-06-20 12:00:00 -070062#include <openssl/bn.h>
David Benjamin79d18bc2017-05-02 14:34:09 -040063#include <openssl/digest.h>
Adam Langley95c29f32014-06-20 12:00:00 -070064#include <openssl/engine.h>
65#include <openssl/err.h>
66#include <openssl/ex_data.h>
David Benjamin05821b02017-05-02 14:15:21 -040067#include <openssl/md5.h>
Adam Langley95c29f32014-06-20 12:00:00 -070068#include <openssl/mem.h>
David Benjamin98193672016-03-25 18:07:11 -040069#include <openssl/nid.h>
David Benjamin05821b02017-05-02 14:15:21 -040070#include <openssl/sha.h>
Brian Smith054e6822015-03-27 21:12:01 -100071#include <openssl/thread.h>
Adam Langley95c29f32014-06-20 12:00:00 -070072
Adam Langley96dec442017-05-03 11:50:51 -070073#include "../bn/internal.h"
74#include "../delocate.h"
75#include "../../internal.h"
Adam Langley95c29f32014-06-20 12:00:00 -070076#include "internal.h"
77
78
Adam Langley96dec442017-05-03 11:50:51 -070079DEFINE_STATIC_EX_DATA_CLASS(g_rsa_ex_data_class);
David Benjamin9f33fc62015-04-15 17:29:53 -040080
Adam Langley95c29f32014-06-20 12:00:00 -070081RSA *RSA_new(void) { return RSA_new_method(NULL); }
82
83RSA *RSA_new_method(const ENGINE *engine) {
Brian Smith5ba06892016-02-07 09:36:04 -100084 RSA *rsa = OPENSSL_malloc(sizeof(RSA));
Adam Langley95c29f32014-06-20 12:00:00 -070085 if (rsa == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -040086 OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
Adam Langley95c29f32014-06-20 12:00:00 -070087 return NULL;
88 }
89
David Benjamin17cf2cb2016-12-13 01:07:13 -050090 OPENSSL_memset(rsa, 0, sizeof(RSA));
Adam Langley95c29f32014-06-20 12:00:00 -070091
92 if (engine) {
93 rsa->meth = ENGINE_get_RSA_method(engine);
94 }
95
96 if (rsa->meth == NULL) {
Adam Langley96dec442017-05-03 11:50:51 -070097 rsa->meth = (RSA_METHOD *) RSA_default_method();
Adam Langley95c29f32014-06-20 12:00:00 -070098 }
99 METHOD_ref(rsa->meth);
100
101 rsa->references = 1;
102 rsa->flags = rsa->meth->flags;
Adam Langley683d7bd2015-04-13 11:04:14 -0700103 CRYPTO_MUTEX_init(&rsa->lock);
David Benjamin8a589332015-12-04 23:14:35 -0500104 CRYPTO_new_ex_data(&rsa->ex_data);
Adam Langley95c29f32014-06-20 12:00:00 -0700105
106 if (rsa->meth->init && !rsa->meth->init(rsa)) {
Adam Langley96dec442017-05-03 11:50:51 -0700107 CRYPTO_free_ex_data(g_rsa_ex_data_class_bss_get(), rsa, &rsa->ex_data);
David Benjamin79680ff2015-10-23 18:46:16 -0400108 CRYPTO_MUTEX_cleanup(&rsa->lock);
Adam Langley95c29f32014-06-20 12:00:00 -0700109 METHOD_unref(rsa->meth);
110 OPENSSL_free(rsa);
111 return NULL;
112 }
113
114 return rsa;
115}
116
117void RSA_free(RSA *rsa) {
118 unsigned u;
119
120 if (rsa == NULL) {
121 return;
122 }
123
Adam Langley0da323a2015-05-15 12:49:30 -0700124 if (!CRYPTO_refcount_dec_and_test_zero(&rsa->references)) {
Adam Langley95c29f32014-06-20 12:00:00 -0700125 return;
126 }
127
David Benjamin8fb0f522015-11-03 18:24:07 -0500128 if (rsa->meth->finish) {
Adam Langley95c29f32014-06-20 12:00:00 -0700129 rsa->meth->finish(rsa);
130 }
131 METHOD_unref(rsa->meth);
132
Adam Langley96dec442017-05-03 11:50:51 -0700133 CRYPTO_free_ex_data(g_rsa_ex_data_class_bss_get(), rsa, &rsa->ex_data);
Adam Langley95c29f32014-06-20 12:00:00 -0700134
David Benjamind8b65c82015-04-22 16:09:09 -0400135 BN_clear_free(rsa->n);
136 BN_clear_free(rsa->e);
137 BN_clear_free(rsa->d);
138 BN_clear_free(rsa->p);
139 BN_clear_free(rsa->q);
140 BN_clear_free(rsa->dmp1);
141 BN_clear_free(rsa->dmq1);
142 BN_clear_free(rsa->iqmp);
David Benjamin8fb0f522015-11-03 18:24:07 -0500143 BN_MONT_CTX_free(rsa->mont_n);
144 BN_MONT_CTX_free(rsa->mont_p);
145 BN_MONT_CTX_free(rsa->mont_q);
Adam Langley95c29f32014-06-20 12:00:00 -0700146 for (u = 0; u < rsa->num_blindings; u++) {
147 BN_BLINDING_free(rsa->blindings[u]);
148 }
David Benjamind8b65c82015-04-22 16:09:09 -0400149 OPENSSL_free(rsa->blindings);
150 OPENSSL_free(rsa->blindings_inuse);
Adam Langley683d7bd2015-04-13 11:04:14 -0700151 CRYPTO_MUTEX_cleanup(&rsa->lock);
Adam Langley95c29f32014-06-20 12:00:00 -0700152 OPENSSL_free(rsa);
153}
154
155int RSA_up_ref(RSA *rsa) {
Adam Langley0da323a2015-05-15 12:49:30 -0700156 CRYPTO_refcount_inc(&rsa->references);
Adam Langley95c29f32014-06-20 12:00:00 -0700157 return 1;
158}
159
David Benjamin5a915032016-08-09 11:04:24 -0400160void RSA_get0_key(const RSA *rsa, const BIGNUM **out_n, const BIGNUM **out_e,
161 const BIGNUM **out_d) {
162 if (out_n != NULL) {
163 *out_n = rsa->n;
164 }
165 if (out_e != NULL) {
166 *out_e = rsa->e;
167 }
168 if (out_d != NULL) {
169 *out_d = rsa->d;
170 }
171}
172
173void RSA_get0_factors(const RSA *rsa, const BIGNUM **out_p,
174 const BIGNUM **out_q) {
175 if (out_p != NULL) {
176 *out_p = rsa->p;
177 }
178 if (out_q != NULL) {
179 *out_q = rsa->q;
180 }
181}
182
183void RSA_get0_crt_params(const RSA *rsa, const BIGNUM **out_dmp1,
184 const BIGNUM **out_dmq1, const BIGNUM **out_iqmp) {
185 if (out_dmp1 != NULL) {
186 *out_dmp1 = rsa->dmp1;
187 }
188 if (out_dmq1 != NULL) {
189 *out_dmq1 = rsa->dmq1;
190 }
191 if (out_iqmp != NULL) {
192 *out_iqmp = rsa->iqmp;
193 }
194}
195
Matt Braithwaite978f16e2015-10-19 13:38:36 -0700196int RSA_public_encrypt(size_t flen, const uint8_t *from, uint8_t *to, RSA *rsa,
Adam Langley95c29f32014-06-20 12:00:00 -0700197 int padding) {
198 size_t out_len;
199
200 if (!RSA_encrypt(rsa, &out_len, to, RSA_size(rsa), from, flen, padding)) {
201 return -1;
202 }
203
Matt Braithwaite978f16e2015-10-19 13:38:36 -0700204 if (out_len > INT_MAX) {
205 OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW);
206 return -1;
207 }
Adam Langley95c29f32014-06-20 12:00:00 -0700208 return out_len;
209}
210
211int RSA_sign_raw(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
212 const uint8_t *in, size_t in_len, int padding) {
213 if (rsa->meth->sign_raw) {
214 return rsa->meth->sign_raw(rsa, out_len, out, max_out, in, in_len, padding);
215 }
216
David Benjamind93831d2015-10-29 13:19:12 -0400217 return rsa_default_sign_raw(rsa, out_len, out, max_out, in, in_len, padding);
Adam Langley95c29f32014-06-20 12:00:00 -0700218}
219
Matt Braithwaite978f16e2015-10-19 13:38:36 -0700220int RSA_private_encrypt(size_t flen, const uint8_t *from, uint8_t *to, RSA *rsa,
Adam Langley95c29f32014-06-20 12:00:00 -0700221 int padding) {
222 size_t out_len;
223
224 if (!RSA_sign_raw(rsa, &out_len, to, RSA_size(rsa), from, flen, padding)) {
225 return -1;
226 }
227
Matt Braithwaite978f16e2015-10-19 13:38:36 -0700228 if (out_len > INT_MAX) {
229 OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW);
230 return -1;
231 }
Adam Langley95c29f32014-06-20 12:00:00 -0700232 return out_len;
233}
234
235int RSA_decrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
236 const uint8_t *in, size_t in_len, int padding) {
237 if (rsa->meth->decrypt) {
238 return rsa->meth->decrypt(rsa, out_len, out, max_out, in, in_len, padding);
239 }
240
David Benjamind93831d2015-10-29 13:19:12 -0400241 return rsa_default_decrypt(rsa, out_len, out, max_out, in, in_len, padding);
Adam Langley95c29f32014-06-20 12:00:00 -0700242}
243
David Benjamin79c59a32015-09-19 13:35:39 -0400244int RSA_private_decrypt(size_t flen, const uint8_t *from, uint8_t *to, RSA *rsa,
Adam Langley95c29f32014-06-20 12:00:00 -0700245 int padding) {
246 size_t out_len;
247
248 if (!RSA_decrypt(rsa, &out_len, to, RSA_size(rsa), from, flen, padding)) {
249 return -1;
250 }
251
David Benjamin79c59a32015-09-19 13:35:39 -0400252 if (out_len > INT_MAX) {
253 OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW);
254 return -1;
255 }
Adam Langley95c29f32014-06-20 12:00:00 -0700256 return out_len;
257}
258
Matt Braithwaite978f16e2015-10-19 13:38:36 -0700259int RSA_public_decrypt(size_t flen, const uint8_t *from, uint8_t *to, RSA *rsa,
Adam Langley95c29f32014-06-20 12:00:00 -0700260 int padding) {
261 size_t out_len;
262
263 if (!RSA_verify_raw(rsa, &out_len, to, RSA_size(rsa), from, flen, padding)) {
264 return -1;
265 }
266
Matt Braithwaite978f16e2015-10-19 13:38:36 -0700267 if (out_len > INT_MAX) {
268 OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW);
269 return -1;
270 }
Adam Langley95c29f32014-06-20 12:00:00 -0700271 return out_len;
272}
273
274unsigned RSA_size(const RSA *rsa) {
David Benjamin925fee32014-07-11 14:14:08 -0400275 if (rsa->meth->size) {
276 return rsa->meth->size(rsa);
277 }
278
David Benjamind93831d2015-10-29 13:19:12 -0400279 return rsa_default_size(rsa);
Adam Langley95c29f32014-06-20 12:00:00 -0700280}
281
David Benjaminecc0ce72014-07-18 18:39:42 -0400282int RSA_is_opaque(const RSA *rsa) {
283 return rsa->meth && (rsa->meth->flags & RSA_FLAG_OPAQUE);
284}
285
David Benjamin8a589332015-12-04 23:14:35 -0500286int RSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused,
Adam Langley95c29f32014-06-20 12:00:00 -0700287 CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) {
David Benjamin9f33fc62015-04-15 17:29:53 -0400288 int index;
Adam Langley96dec442017-05-03 11:50:51 -0700289 if (!CRYPTO_get_ex_new_index(g_rsa_ex_data_class_bss_get(), &index, argl,
290 argp, dup_func, free_func)) {
David Benjamin9f33fc62015-04-15 17:29:53 -0400291 return -1;
292 }
293 return index;
Adam Langley95c29f32014-06-20 12:00:00 -0700294}
295
296int RSA_set_ex_data(RSA *d, int idx, void *arg) {
297 return CRYPTO_set_ex_data(&d->ex_data, idx, arg);
298}
299
300void *RSA_get_ex_data(const RSA *d, int idx) {
301 return CRYPTO_get_ex_data(&d->ex_data, idx);
302}
303
304/* SSL_SIG_LENGTH is the size of an SSL/TLS (prior to TLS 1.2) signature: it's
305 * the length of an MD5 and SHA1 hash. */
306static const unsigned SSL_SIG_LENGTH = 36;
307
308/* pkcs1_sig_prefix contains the ASN.1, DER encoded prefix for a hash that is
309 * to be signed with PKCS#1. */
310struct pkcs1_sig_prefix {
311 /* nid identifies the hash function. */
312 int nid;
David Benjamin05821b02017-05-02 14:15:21 -0400313 /* hash_len is the expected length of the hash function. */
314 uint8_t hash_len;
Adam Langley95c29f32014-06-20 12:00:00 -0700315 /* len is the number of bytes of |bytes| which are valid. */
316 uint8_t len;
317 /* bytes contains the DER bytes. */
318 uint8_t bytes[19];
319};
320
321/* kPKCS1SigPrefixes contains the ASN.1 prefixes for PKCS#1 signatures with
322 * different hash functions. */
323static const struct pkcs1_sig_prefix kPKCS1SigPrefixes[] = {
324 {
325 NID_md5,
David Benjamin05821b02017-05-02 14:15:21 -0400326 MD5_DIGEST_LENGTH,
Adam Langley95c29f32014-06-20 12:00:00 -0700327 18,
328 {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
329 0x02, 0x05, 0x05, 0x00, 0x04, 0x10},
330 },
331 {
332 NID_sha1,
David Benjamin05821b02017-05-02 14:15:21 -0400333 SHA_DIGEST_LENGTH,
Adam Langley95c29f32014-06-20 12:00:00 -0700334 15,
335 {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05,
336 0x00, 0x04, 0x14},
337 },
338 {
339 NID_sha224,
David Benjamin05821b02017-05-02 14:15:21 -0400340 SHA224_DIGEST_LENGTH,
Adam Langley95c29f32014-06-20 12:00:00 -0700341 19,
342 {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
343 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c},
344 },
345 {
346 NID_sha256,
David Benjamin05821b02017-05-02 14:15:21 -0400347 SHA256_DIGEST_LENGTH,
Adam Langley95c29f32014-06-20 12:00:00 -0700348 19,
349 {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
350 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20},
351 },
352 {
353 NID_sha384,
David Benjamin05821b02017-05-02 14:15:21 -0400354 SHA384_DIGEST_LENGTH,
Adam Langley95c29f32014-06-20 12:00:00 -0700355 19,
356 {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
357 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30},
358 },
359 {
360 NID_sha512,
David Benjamin05821b02017-05-02 14:15:21 -0400361 SHA512_DIGEST_LENGTH,
Adam Langley95c29f32014-06-20 12:00:00 -0700362 19,
363 {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
364 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40},
365 },
366 {
David Benjamin05821b02017-05-02 14:15:21 -0400367 NID_undef, 0, 0, {0},
Adam Langley95c29f32014-06-20 12:00:00 -0700368 },
369};
370
David Benjaminb0acb772015-05-28 16:53:31 -0400371int RSA_add_pkcs1_prefix(uint8_t **out_msg, size_t *out_msg_len,
372 int *is_alloced, int hash_nid, const uint8_t *msg,
373 size_t msg_len) {
Adam Langley95c29f32014-06-20 12:00:00 -0700374 unsigned i;
Adam Langley95c29f32014-06-20 12:00:00 -0700375
376 if (hash_nid == NID_md5_sha1) {
377 /* Special case: SSL signature, just check the length. */
378 if (msg_len != SSL_SIG_LENGTH) {
David Benjamin3570d732015-06-29 00:28:17 -0400379 OPENSSL_PUT_ERROR(RSA, RSA_R_INVALID_MESSAGE_LENGTH);
Adam Langley95c29f32014-06-20 12:00:00 -0700380 return 0;
381 }
382
383 *out_msg = (uint8_t*) msg;
384 *out_msg_len = SSL_SIG_LENGTH;
385 *is_alloced = 0;
386 return 1;
387 }
388
389 for (i = 0; kPKCS1SigPrefixes[i].nid != NID_undef; i++) {
390 const struct pkcs1_sig_prefix *sig_prefix = &kPKCS1SigPrefixes[i];
Brian Smitha039d702015-01-29 15:03:18 -0800391 if (sig_prefix->nid != hash_nid) {
392 continue;
Adam Langley95c29f32014-06-20 12:00:00 -0700393 }
Brian Smitha039d702015-01-29 15:03:18 -0800394
David Benjamin05821b02017-05-02 14:15:21 -0400395 if (msg_len != sig_prefix->hash_len) {
396 OPENSSL_PUT_ERROR(RSA, RSA_R_INVALID_MESSAGE_LENGTH);
397 return 0;
398 }
399
Brian Smitha039d702015-01-29 15:03:18 -0800400 const uint8_t* prefix = sig_prefix->bytes;
401 unsigned prefix_len = sig_prefix->len;
402 unsigned signed_msg_len;
403 uint8_t *signed_msg;
404
405 signed_msg_len = prefix_len + msg_len;
406 if (signed_msg_len < prefix_len) {
David Benjamin3570d732015-06-29 00:28:17 -0400407 OPENSSL_PUT_ERROR(RSA, RSA_R_TOO_LONG);
Brian Smitha039d702015-01-29 15:03:18 -0800408 return 0;
409 }
410
411 signed_msg = OPENSSL_malloc(signed_msg_len);
412 if (!signed_msg) {
David Benjamin3570d732015-06-29 00:28:17 -0400413 OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
Brian Smitha039d702015-01-29 15:03:18 -0800414 return 0;
415 }
416
David Benjamin17cf2cb2016-12-13 01:07:13 -0500417 OPENSSL_memcpy(signed_msg, prefix, prefix_len);
418 OPENSSL_memcpy(signed_msg + prefix_len, msg, msg_len);
Brian Smitha039d702015-01-29 15:03:18 -0800419
420 *out_msg = signed_msg;
421 *out_msg_len = signed_msg_len;
422 *is_alloced = 1;
423
424 return 1;
Adam Langley95c29f32014-06-20 12:00:00 -0700425 }
426
David Benjamin3570d732015-06-29 00:28:17 -0400427 OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_ALGORITHM_TYPE);
Brian Smitha039d702015-01-29 15:03:18 -0800428 return 0;
Adam Langley95c29f32014-06-20 12:00:00 -0700429}
430
431int RSA_sign(int hash_nid, const uint8_t *in, unsigned in_len, uint8_t *out,
432 unsigned *out_len, RSA *rsa) {
433 const unsigned rsa_size = RSA_size(rsa);
434 int ret = 0;
David Benjamin5eb75e22017-05-02 17:21:15 -0400435 uint8_t *signed_msg = NULL;
436 size_t signed_msg_len = 0;
Adam Langley95c29f32014-06-20 12:00:00 -0700437 int signed_msg_is_alloced = 0;
438 size_t size_t_out_len;
439
440 if (rsa->meth->sign) {
441 return rsa->meth->sign(hash_nid, in, in_len, out, out_len, rsa);
442 }
443
David Benjaminb0acb772015-05-28 16:53:31 -0400444 if (!RSA_add_pkcs1_prefix(&signed_msg, &signed_msg_len,
David Benjaminddd5ba72017-04-11 12:54:06 -0400445 &signed_msg_is_alloced, hash_nid, in, in_len) ||
446 !RSA_sign_raw(rsa, &size_t_out_len, out, rsa_size, signed_msg,
447 signed_msg_len, RSA_PKCS1_PADDING)) {
448 goto err;
Adam Langley95c29f32014-06-20 12:00:00 -0700449 }
450
David Benjaminddd5ba72017-04-11 12:54:06 -0400451 *out_len = size_t_out_len;
452 ret = 1;
Adam Langley95c29f32014-06-20 12:00:00 -0700453
David Benjaminddd5ba72017-04-11 12:54:06 -0400454err:
Adam Langley95c29f32014-06-20 12:00:00 -0700455 if (signed_msg_is_alloced) {
456 OPENSSL_free(signed_msg);
457 }
458 return ret;
459}
460
David Benjamin79d18bc2017-05-02 14:34:09 -0400461int RSA_sign_pss_mgf1(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
462 const uint8_t *in, size_t in_len, const EVP_MD *md,
463 const EVP_MD *mgf1_md, int salt_len) {
464 if (in_len != EVP_MD_size(md)) {
465 OPENSSL_PUT_ERROR(RSA, RSA_R_INVALID_MESSAGE_LENGTH);
466 return 0;
467 }
468
469 size_t padded_len = RSA_size(rsa);
470 uint8_t *padded = OPENSSL_malloc(padded_len);
471 if (padded == NULL) {
472 OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
473 return 0;
474 }
475
476 int ret =
477 RSA_padding_add_PKCS1_PSS_mgf1(rsa, padded, in, md, mgf1_md, salt_len) &&
478 RSA_sign_raw(rsa, out_len, out, max_out, padded, padded_len,
479 RSA_NO_PADDING);
480 OPENSSL_free(padded);
481 return ret;
482}
483
Adam Langley95c29f32014-06-20 12:00:00 -0700484int RSA_verify(int hash_nid, const uint8_t *msg, size_t msg_len,
485 const uint8_t *sig, size_t sig_len, RSA *rsa) {
Brian Smithc0b196d2016-03-04 08:54:07 -1000486 if (rsa->n == NULL || rsa->e == NULL) {
487 OPENSSL_PUT_ERROR(RSA, RSA_R_VALUE_MISSING);
488 return 0;
489 }
490
Adam Langley95c29f32014-06-20 12:00:00 -0700491 const size_t rsa_size = RSA_size(rsa);
492 uint8_t *buf = NULL;
493 int ret = 0;
494 uint8_t *signed_msg = NULL;
David Benjamin5eb75e22017-05-02 17:21:15 -0400495 size_t signed_msg_len = 0, len;
Adam Langley95c29f32014-06-20 12:00:00 -0700496 int signed_msg_is_alloced = 0;
497
Adam Langley95c29f32014-06-20 12:00:00 -0700498 if (hash_nid == NID_md5_sha1 && msg_len != SSL_SIG_LENGTH) {
David Benjamin3570d732015-06-29 00:28:17 -0400499 OPENSSL_PUT_ERROR(RSA, RSA_R_INVALID_MESSAGE_LENGTH);
Adam Langley95c29f32014-06-20 12:00:00 -0700500 return 0;
501 }
502
503 buf = OPENSSL_malloc(rsa_size);
504 if (!buf) {
David Benjamin3570d732015-06-29 00:28:17 -0400505 OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
Adam Langley95c29f32014-06-20 12:00:00 -0700506 return 0;
507 }
508
509 if (!RSA_verify_raw(rsa, &len, buf, rsa_size, sig, sig_len,
510 RSA_PKCS1_PADDING)) {
511 goto out;
512 }
513
David Benjaminb0acb772015-05-28 16:53:31 -0400514 if (!RSA_add_pkcs1_prefix(&signed_msg, &signed_msg_len,
515 &signed_msg_is_alloced, hash_nid, msg, msg_len)) {
Adam Langley95c29f32014-06-20 12:00:00 -0700516 goto out;
517 }
518
Steven Valdezc1966802017-04-10 15:52:19 -0400519 /* Check that no other information follows the hash value (FIPS 186-4 Section
520 * 5.5) and it matches the expected hash. */
David Benjamin17cf2cb2016-12-13 01:07:13 -0500521 if (len != signed_msg_len || OPENSSL_memcmp(buf, signed_msg, len) != 0) {
David Benjamin3570d732015-06-29 00:28:17 -0400522 OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_SIGNATURE);
Adam Langley95c29f32014-06-20 12:00:00 -0700523 goto out;
524 }
525
526 ret = 1;
527
528out:
David Benjamind8b65c82015-04-22 16:09:09 -0400529 OPENSSL_free(buf);
Adam Langley95c29f32014-06-20 12:00:00 -0700530 if (signed_msg_is_alloced) {
531 OPENSSL_free(signed_msg);
532 }
533 return ret;
534}
Adam Langley409766d2014-06-20 12:00:00 -0700535
David Benjamin79d18bc2017-05-02 14:34:09 -0400536int RSA_verify_pss_mgf1(RSA *rsa, const uint8_t *msg, size_t msg_len,
537 const EVP_MD *md, const EVP_MD *mgf1_md, int salt_len,
538 const uint8_t *sig, size_t sig_len) {
539 if (msg_len != EVP_MD_size(md)) {
540 OPENSSL_PUT_ERROR(RSA, RSA_R_INVALID_MESSAGE_LENGTH);
541 return 0;
542 }
543
544 size_t em_len = RSA_size(rsa);
545 uint8_t *em = OPENSSL_malloc(em_len);
546 if (em == NULL) {
547 OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
548 return 0;
549 }
550
551 int ret = 0;
552 if (!RSA_verify_raw(rsa, &em_len, em, em_len, sig, sig_len, RSA_NO_PADDING)) {
553 goto err;
554 }
555
556 if (em_len != RSA_size(rsa)) {
557 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
558 goto err;
559 }
560
561 ret = RSA_verify_PKCS1_PSS_mgf1(rsa, msg, md, mgf1_md, em, salt_len);
562
563err:
564 OPENSSL_free(em);
565 return ret;
566}
567
Adam Langley05b73772014-07-25 12:03:51 -0700568int RSA_check_key(const RSA *key) {
Brian Smith7241ca52016-07-25 16:01:10 -1000569 BIGNUM n, pm1, qm1, lcm, gcd, de, dmp1, dmq1, iqmp_times_q;
Adam Langley05b73772014-07-25 12:03:51 -0700570 BN_CTX *ctx;
571 int ok = 0, has_crt_values;
572
573 if (RSA_is_opaque(key)) {
574 /* Opaque keys can't be checked. */
575 return 1;
576 }
577
578 if ((key->p != NULL) != (key->q != NULL)) {
David Benjamin3570d732015-06-29 00:28:17 -0400579 OPENSSL_PUT_ERROR(RSA, RSA_R_ONLY_ONE_OF_P_Q_GIVEN);
Adam Langley05b73772014-07-25 12:03:51 -0700580 return 0;
581 }
582
583 if (!key->n || !key->e) {
David Benjamin3570d732015-06-29 00:28:17 -0400584 OPENSSL_PUT_ERROR(RSA, RSA_R_VALUE_MISSING);
Adam Langley05b73772014-07-25 12:03:51 -0700585 return 0;
586 }
587
588 if (!key->d || !key->p) {
589 /* For a public key, or without p and q, there's nothing that can be
590 * checked. */
591 return 1;
592 }
593
594 ctx = BN_CTX_new();
595 if (ctx == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400596 OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
Adam Langley05b73772014-07-25 12:03:51 -0700597 return 0;
598 }
599
600 BN_init(&n);
601 BN_init(&pm1);
602 BN_init(&qm1);
603 BN_init(&lcm);
604 BN_init(&gcd);
605 BN_init(&de);
606 BN_init(&dmp1);
607 BN_init(&dmq1);
Brian Smith7241ca52016-07-25 16:01:10 -1000608 BN_init(&iqmp_times_q);
Adam Langley05b73772014-07-25 12:03:51 -0700609
Adam Langley839b8812015-05-26 11:36:46 -0700610 if (!BN_mul(&n, key->p, key->q, ctx) ||
David Benjamin61ae41f2017-05-04 13:50:39 -0400611 /* lcm = lcm(p, q) */
Adam Langley05b73772014-07-25 12:03:51 -0700612 !BN_sub(&pm1, key->p, BN_value_one()) ||
613 !BN_sub(&qm1, key->q, BN_value_one()) ||
614 !BN_mul(&lcm, &pm1, &qm1, ctx) ||
Adam Langley839b8812015-05-26 11:36:46 -0700615 !BN_gcd(&gcd, &pm1, &qm1, ctx)) {
David Benjamin3570d732015-06-29 00:28:17 -0400616 OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN);
Adam Langley839b8812015-05-26 11:36:46 -0700617 goto out;
618 }
619
Adam Langley839b8812015-05-26 11:36:46 -0700620 if (!BN_div(&lcm, NULL, &lcm, &gcd, ctx) ||
Adam Langley05b73772014-07-25 12:03:51 -0700621 !BN_gcd(&gcd, &pm1, &qm1, ctx) ||
David Benjamin61ae41f2017-05-04 13:50:39 -0400622 /* de = d*e mod lcm(p, q). */
Adam Langley05b73772014-07-25 12:03:51 -0700623 !BN_mod_mul(&de, key->d, key->e, &lcm, ctx)) {
David Benjamin3570d732015-06-29 00:28:17 -0400624 OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN);
Adam Langley05b73772014-07-25 12:03:51 -0700625 goto out;
626 }
627
628 if (BN_cmp(&n, key->n) != 0) {
David Benjamin3570d732015-06-29 00:28:17 -0400629 OPENSSL_PUT_ERROR(RSA, RSA_R_N_NOT_EQUAL_P_Q);
Adam Langley05b73772014-07-25 12:03:51 -0700630 goto out;
631 }
632
633 if (!BN_is_one(&de)) {
David Benjamin3570d732015-06-29 00:28:17 -0400634 OPENSSL_PUT_ERROR(RSA, RSA_R_D_E_NOT_CONGRUENT_TO_1);
Adam Langley05b73772014-07-25 12:03:51 -0700635 goto out;
636 }
637
638 has_crt_values = key->dmp1 != NULL;
639 if (has_crt_values != (key->dmq1 != NULL) ||
640 has_crt_values != (key->iqmp != NULL)) {
David Benjamin3570d732015-06-29 00:28:17 -0400641 OPENSSL_PUT_ERROR(RSA, RSA_R_INCONSISTENT_SET_OF_CRT_VALUES);
Adam Langley05b73772014-07-25 12:03:51 -0700642 goto out;
643 }
644
David Benjamin82b2b852017-04-12 18:28:48 -0400645 if (has_crt_values) {
Adam Langley05b73772014-07-25 12:03:51 -0700646 if (/* dmp1 = d mod (p-1) */
647 !BN_mod(&dmp1, key->d, &pm1, ctx) ||
648 /* dmq1 = d mod (q-1) */
649 !BN_mod(&dmq1, key->d, &qm1, ctx) ||
650 /* iqmp = q^-1 mod p */
Brian Smith7241ca52016-07-25 16:01:10 -1000651 !BN_mod_mul(&iqmp_times_q, key->iqmp, key->q, key->p, ctx)) {
David Benjamin3570d732015-06-29 00:28:17 -0400652 OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN);
Adam Langley05b73772014-07-25 12:03:51 -0700653 goto out;
654 }
655
656 if (BN_cmp(&dmp1, key->dmp1) != 0 ||
657 BN_cmp(&dmq1, key->dmq1) != 0 ||
Brian Smith7241ca52016-07-25 16:01:10 -1000658 BN_cmp(key->iqmp, key->p) >= 0 ||
659 !BN_is_one(&iqmp_times_q)) {
David Benjamin3570d732015-06-29 00:28:17 -0400660 OPENSSL_PUT_ERROR(RSA, RSA_R_CRT_VALUES_INCORRECT);
Adam Langley05b73772014-07-25 12:03:51 -0700661 goto out;
662 }
663 }
664
665 ok = 1;
666
667out:
668 BN_free(&n);
669 BN_free(&pm1);
670 BN_free(&qm1);
671 BN_free(&lcm);
672 BN_free(&gcd);
673 BN_free(&de);
674 BN_free(&dmp1);
675 BN_free(&dmq1);
Brian Smith7241ca52016-07-25 16:01:10 -1000676 BN_free(&iqmp_times_q);
Adam Langley05b73772014-07-25 12:03:51 -0700677 BN_CTX_free(ctx);
678
679 return ok;
680}
681
Steven Valdezd0b98822017-04-11 12:46:03 -0400682
683/* This is the product of the 132 smallest odd primes, from 3 to 751. */
684static const BN_ULONG kSmallFactorsLimbs[] = {
685 TOBN(0xc4309333, 0x3ef4e3e1), TOBN(0x71161eb6, 0xcd2d655f),
686 TOBN(0x95e2238c, 0x0bf94862), TOBN(0x3eb233d3, 0x24f7912b),
687 TOBN(0x6b55514b, 0xbf26c483), TOBN(0x0a84d817, 0x5a144871),
688 TOBN(0x77d12fee, 0x9b82210a), TOBN(0xdb5b93c2, 0x97f050b3),
689 TOBN(0x4acad6b9, 0x4d6c026b), TOBN(0xeb7751f3, 0x54aec893),
690 TOBN(0xdba53368, 0x36bc85c4), TOBN(0xd85a1b28, 0x7f5ec78e),
691 TOBN(0x2eb072d8, 0x6b322244), TOBN(0xbba51112, 0x5e2b3aea),
692 TOBN(0x36ed1a6c, 0x0e2486bf), TOBN(0x5f270460, 0xec0c5727),
693 0x000017b1
694};
Adam Langley96dec442017-05-03 11:50:51 -0700695
696DEFINE_LOCAL_DATA(BIGNUM, g_small_factors) {
697 out->d = (BN_ULONG *) kSmallFactorsLimbs;
698 out->top = OPENSSL_ARRAY_SIZE(kSmallFactorsLimbs);
699 out->dmax = out->top;
700 out->neg = 0;
701 out->flags = BN_FLG_STATIC_DATA;
702}
Steven Valdezd0b98822017-04-11 12:46:03 -0400703
Steven Valdez400d0b72017-04-06 14:55:18 -0400704int RSA_check_fips(RSA *key) {
Steven Valdezd0b98822017-04-11 12:46:03 -0400705 if (RSA_is_opaque(key)) {
706 /* Opaque keys can't be checked. */
707 OPENSSL_PUT_ERROR(RSA, RSA_R_PUBLIC_KEY_VALIDATION_FAILED);
708 return 0;
709 }
710
711 if (!RSA_check_key(key)) {
712 return 0;
713 }
714
715 BN_CTX *ctx = BN_CTX_new();
716 if (ctx == NULL) {
717 OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
718 return 0;
719 }
720
721 BIGNUM small_gcd;
722 BN_init(&small_gcd);
723
724 int ret = 1;
725
726 /* Perform partial public key validation of RSA keys (SP 800-89 5.3.3). */
Steven Valdezb1ffe0b2017-04-20 10:45:25 -0400727 enum bn_primality_result_t primality_result;
Adam Langleya54ebff2017-04-20 12:36:18 -0700728 if (BN_num_bits(key->e) <= 16 ||
Steven Valdezd0b98822017-04-11 12:46:03 -0400729 BN_num_bits(key->e) > 256 ||
730 !BN_is_odd(key->n) ||
731 !BN_is_odd(key->e) ||
Adam Langley96dec442017-05-03 11:50:51 -0700732 !BN_gcd(&small_gcd, key->n, g_small_factors(), ctx) ||
Steven Valdezb1ffe0b2017-04-20 10:45:25 -0400733 !BN_is_one(&small_gcd) ||
734 !BN_enhanced_miller_rabin_primality_test(&primality_result, key->n,
735 BN_prime_checks, ctx, NULL) ||
736 primality_result != bn_non_prime_power_composite) {
Steven Valdezd0b98822017-04-11 12:46:03 -0400737 OPENSSL_PUT_ERROR(RSA, RSA_R_PUBLIC_KEY_VALIDATION_FAILED);
738 ret = 0;
739 }
740
741 BN_free(&small_gcd);
742 BN_CTX_free(ctx);
743
Steven Valdezb15143f2017-04-13 13:14:12 -0400744 if (!ret || key->d == NULL || key->p == NULL) {
745 /* On a failure or on only a public key, there's nothing else can be
746 * checked. */
Steven Valdez400d0b72017-04-06 14:55:18 -0400747 return ret;
748 }
749
750 /* FIPS pairwise consistency test (FIPS 140-2 4.9.2). Per FIPS 140-2 IG,
751 * section 9.9, it is not known whether |rsa| will be used for signing or
752 * encryption, so either pair-wise consistency self-test is acceptable. We
753 * perform a signing test. */
754 uint8_t data[32] = {0};
755 unsigned sig_len = RSA_size(key);
756 uint8_t *sig = OPENSSL_malloc(sig_len);
757 if (sig == NULL) {
Steven Valdezb15143f2017-04-13 13:14:12 -0400758 OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
Steven Valdez400d0b72017-04-06 14:55:18 -0400759 return 0;
760 }
761
762 if (!RSA_sign(NID_sha256, data, sizeof(data), sig, &sig_len, key) ||
763 !RSA_verify(NID_sha256, data, sizeof(data), sig, sig_len, key)) {
Steven Valdezb15143f2017-04-13 13:14:12 -0400764 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
Steven Valdez400d0b72017-04-06 14:55:18 -0400765 ret = 0;
766 }
767
768 OPENSSL_free(sig);
769
Steven Valdezd0b98822017-04-11 12:46:03 -0400770 return ret;
771}
772
Adam Langley6bc658d2014-08-18 13:29:45 -0700773int RSA_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in,
774 size_t len) {
775 if (rsa->meth->private_transform) {
776 return rsa->meth->private_transform(rsa, out, in, len);
777 }
778
David Benjamind93831d2015-10-29 13:19:12 -0400779 return rsa_default_private_transform(rsa, out, in, len);
Adam Langley6bc658d2014-08-18 13:29:45 -0700780}
Adam Langleyc3ef76f2015-04-13 14:34:17 -0700781
782int RSA_blinding_on(RSA *rsa, BN_CTX *ctx) {
783 return 1;
784}