blob: 482a866f32a50138a1642cc87b288e4c0a1b0fa4 [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>
63#include <openssl/engine.h>
64#include <openssl/err.h>
65#include <openssl/ex_data.h>
66#include <openssl/mem.h>
67#include <openssl/obj.h>
Brian Smith054e6822015-03-27 21:12:01 -100068#include <openssl/thread.h>
Adam Langley95c29f32014-06-20 12:00:00 -070069
70#include "internal.h"
Adam Langley683d7bd2015-04-13 11:04:14 -070071#include "../internal.h"
Adam Langley95c29f32014-06-20 12:00:00 -070072
73
David Benjamin9f33fc62015-04-15 17:29:53 -040074static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT;
75
Adam Langley95c29f32014-06-20 12:00:00 -070076RSA *RSA_new(void) { return RSA_new_method(NULL); }
77
78RSA *RSA_new_method(const ENGINE *engine) {
79 RSA *rsa = (RSA *)OPENSSL_malloc(sizeof(RSA));
80 if (rsa == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -040081 OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
Adam Langley95c29f32014-06-20 12:00:00 -070082 return NULL;
83 }
84
85 memset(rsa, 0, sizeof(RSA));
86
87 if (engine) {
88 rsa->meth = ENGINE_get_RSA_method(engine);
89 }
90
91 if (rsa->meth == NULL) {
92 rsa->meth = (RSA_METHOD*) &RSA_default_method;
93 }
94 METHOD_ref(rsa->meth);
95
96 rsa->references = 1;
97 rsa->flags = rsa->meth->flags;
Adam Langley683d7bd2015-04-13 11:04:14 -070098 CRYPTO_MUTEX_init(&rsa->lock);
Adam Langley95c29f32014-06-20 12:00:00 -070099
David Benjamin9f33fc62015-04-15 17:29:53 -0400100 if (!CRYPTO_new_ex_data(&g_ex_data_class, rsa, &rsa->ex_data)) {
David Benjamin79680ff2015-10-23 18:46:16 -0400101 CRYPTO_MUTEX_cleanup(&rsa->lock);
Adam Langley95c29f32014-06-20 12:00:00 -0700102 METHOD_unref(rsa->meth);
103 OPENSSL_free(rsa);
104 return NULL;
105 }
106
107 if (rsa->meth->init && !rsa->meth->init(rsa)) {
David Benjamin9f33fc62015-04-15 17:29:53 -0400108 CRYPTO_free_ex_data(&g_ex_data_class, rsa, &rsa->ex_data);
David Benjamin79680ff2015-10-23 18:46:16 -0400109 CRYPTO_MUTEX_cleanup(&rsa->lock);
Adam Langley95c29f32014-06-20 12:00:00 -0700110 METHOD_unref(rsa->meth);
111 OPENSSL_free(rsa);
112 return NULL;
113 }
114
115 return rsa;
116}
117
Adam Langley839b8812015-05-26 11:36:46 -0700118void RSA_additional_prime_free(RSA_additional_prime *ap) {
119 if (ap == NULL) {
120 return;
121 }
122
123 BN_clear_free(ap->prime);
124 BN_clear_free(ap->exp);
125 BN_clear_free(ap->coeff);
126 BN_clear_free(ap->r);
127 OPENSSL_free(ap);
128}
129
Adam Langley95c29f32014-06-20 12:00:00 -0700130void RSA_free(RSA *rsa) {
131 unsigned u;
132
133 if (rsa == NULL) {
134 return;
135 }
136
Adam Langley0da323a2015-05-15 12:49:30 -0700137 if (!CRYPTO_refcount_dec_and_test_zero(&rsa->references)) {
Adam Langley95c29f32014-06-20 12:00:00 -0700138 return;
139 }
140
141 if (rsa->meth->finish) {
142 rsa->meth->finish(rsa);
143 }
144 METHOD_unref(rsa->meth);
145
David Benjamin9f33fc62015-04-15 17:29:53 -0400146 CRYPTO_free_ex_data(&g_ex_data_class, rsa, &rsa->ex_data);
Adam Langley95c29f32014-06-20 12:00:00 -0700147
David Benjamind8b65c82015-04-22 16:09:09 -0400148 BN_clear_free(rsa->n);
149 BN_clear_free(rsa->e);
150 BN_clear_free(rsa->d);
151 BN_clear_free(rsa->p);
152 BN_clear_free(rsa->q);
153 BN_clear_free(rsa->dmp1);
154 BN_clear_free(rsa->dmq1);
155 BN_clear_free(rsa->iqmp);
Adam Langley95c29f32014-06-20 12:00:00 -0700156 for (u = 0; u < rsa->num_blindings; u++) {
157 BN_BLINDING_free(rsa->blindings[u]);
158 }
David Benjamind8b65c82015-04-22 16:09:09 -0400159 OPENSSL_free(rsa->blindings);
160 OPENSSL_free(rsa->blindings_inuse);
Adam Langley839b8812015-05-26 11:36:46 -0700161 if (rsa->additional_primes != NULL) {
162 sk_RSA_additional_prime_pop_free(rsa->additional_primes,
163 RSA_additional_prime_free);
164 }
Adam Langley683d7bd2015-04-13 11:04:14 -0700165 CRYPTO_MUTEX_cleanup(&rsa->lock);
Adam Langley95c29f32014-06-20 12:00:00 -0700166 OPENSSL_free(rsa);
167}
168
169int RSA_up_ref(RSA *rsa) {
Adam Langley0da323a2015-05-15 12:49:30 -0700170 CRYPTO_refcount_inc(&rsa->references);
Adam Langley95c29f32014-06-20 12:00:00 -0700171 return 1;
172}
173
174int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) {
175 if (rsa->meth->keygen) {
176 return rsa->meth->keygen(rsa, bits, e_value, cb);
177 }
178
David Benjamind93831d2015-10-29 13:19:12 -0400179 return rsa_default_keygen(rsa, bits, e_value, cb);
Adam Langley95c29f32014-06-20 12:00:00 -0700180}
181
Adam Langley839b8812015-05-26 11:36:46 -0700182int RSA_generate_multi_prime_key(RSA *rsa, int bits, int num_primes,
183 BIGNUM *e_value, BN_GENCB *cb) {
184 if (rsa->meth->multi_prime_keygen) {
185 return rsa->meth->multi_prime_keygen(rsa, bits, num_primes, e_value, cb);
186 }
187
David Benjamind93831d2015-10-29 13:19:12 -0400188 return rsa_default_multi_prime_keygen(rsa, bits, num_primes, e_value, cb);
Adam Langley839b8812015-05-26 11:36:46 -0700189}
190
Adam Langley95c29f32014-06-20 12:00:00 -0700191int RSA_encrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
192 const uint8_t *in, size_t in_len, int padding) {
193 if (rsa->meth->encrypt) {
194 return rsa->meth->encrypt(rsa, out_len, out, max_out, in, in_len, padding);
195 }
196
David Benjamind93831d2015-10-29 13:19:12 -0400197 return rsa_default_encrypt(rsa, out_len, out, max_out, in, in_len, padding);
Adam Langley95c29f32014-06-20 12:00:00 -0700198}
199
Matt Braithwaite978f16e2015-10-19 13:38:36 -0700200int RSA_public_encrypt(size_t flen, const uint8_t *from, uint8_t *to, RSA *rsa,
Adam Langley95c29f32014-06-20 12:00:00 -0700201 int padding) {
202 size_t out_len;
203
204 if (!RSA_encrypt(rsa, &out_len, to, RSA_size(rsa), from, flen, padding)) {
205 return -1;
206 }
207
Matt Braithwaite978f16e2015-10-19 13:38:36 -0700208 if (out_len > INT_MAX) {
209 OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW);
210 return -1;
211 }
Adam Langley95c29f32014-06-20 12:00:00 -0700212 return out_len;
213}
214
215int RSA_sign_raw(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
216 const uint8_t *in, size_t in_len, int padding) {
217 if (rsa->meth->sign_raw) {
218 return rsa->meth->sign_raw(rsa, out_len, out, max_out, in, in_len, padding);
219 }
220
David Benjamind93831d2015-10-29 13:19:12 -0400221 return rsa_default_sign_raw(rsa, out_len, out, max_out, in, in_len, padding);
Adam Langley95c29f32014-06-20 12:00:00 -0700222}
223
Matt Braithwaite978f16e2015-10-19 13:38:36 -0700224int RSA_private_encrypt(size_t flen, const uint8_t *from, uint8_t *to, RSA *rsa,
Adam Langley95c29f32014-06-20 12:00:00 -0700225 int padding) {
226 size_t out_len;
227
228 if (!RSA_sign_raw(rsa, &out_len, to, RSA_size(rsa), from, flen, padding)) {
229 return -1;
230 }
231
Matt Braithwaite978f16e2015-10-19 13:38:36 -0700232 if (out_len > INT_MAX) {
233 OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW);
234 return -1;
235 }
Adam Langley95c29f32014-06-20 12:00:00 -0700236 return out_len;
237}
238
239int RSA_decrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
240 const uint8_t *in, size_t in_len, int padding) {
241 if (rsa->meth->decrypt) {
242 return rsa->meth->decrypt(rsa, out_len, out, max_out, in, in_len, padding);
243 }
244
David Benjamind93831d2015-10-29 13:19:12 -0400245 return rsa_default_decrypt(rsa, out_len, out, max_out, in, in_len, padding);
Adam Langley95c29f32014-06-20 12:00:00 -0700246}
247
David Benjamin79c59a32015-09-19 13:35:39 -0400248int RSA_private_decrypt(size_t flen, const uint8_t *from, uint8_t *to, RSA *rsa,
Adam Langley95c29f32014-06-20 12:00:00 -0700249 int padding) {
250 size_t out_len;
251
252 if (!RSA_decrypt(rsa, &out_len, to, RSA_size(rsa), from, flen, padding)) {
253 return -1;
254 }
255
David Benjamin79c59a32015-09-19 13:35:39 -0400256 if (out_len > INT_MAX) {
257 OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW);
258 return -1;
259 }
Adam Langley95c29f32014-06-20 12:00:00 -0700260 return out_len;
261}
262
263int RSA_verify_raw(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
264 const uint8_t *in, size_t in_len, int padding) {
265 if (rsa->meth->verify_raw) {
266 return rsa->meth->verify_raw(rsa, out_len, out, max_out, in, in_len, padding);
267 }
268
David Benjamind93831d2015-10-29 13:19:12 -0400269 return rsa_default_verify_raw(rsa, out_len, out, max_out, in, in_len,
270 padding);
Adam Langley95c29f32014-06-20 12:00:00 -0700271}
272
Matt Braithwaite978f16e2015-10-19 13:38:36 -0700273int RSA_public_decrypt(size_t flen, const uint8_t *from, uint8_t *to, RSA *rsa,
Adam Langley95c29f32014-06-20 12:00:00 -0700274 int padding) {
275 size_t out_len;
276
277 if (!RSA_verify_raw(rsa, &out_len, to, RSA_size(rsa), from, flen, padding)) {
278 return -1;
279 }
280
Matt Braithwaite978f16e2015-10-19 13:38:36 -0700281 if (out_len > INT_MAX) {
282 OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW);
283 return -1;
284 }
Adam Langley95c29f32014-06-20 12:00:00 -0700285 return out_len;
286}
287
288unsigned RSA_size(const RSA *rsa) {
David Benjamin925fee32014-07-11 14:14:08 -0400289 if (rsa->meth->size) {
290 return rsa->meth->size(rsa);
291 }
292
David Benjamind93831d2015-10-29 13:19:12 -0400293 return rsa_default_size(rsa);
Adam Langley95c29f32014-06-20 12:00:00 -0700294}
295
David Benjaminecc0ce72014-07-18 18:39:42 -0400296int RSA_is_opaque(const RSA *rsa) {
297 return rsa->meth && (rsa->meth->flags & RSA_FLAG_OPAQUE);
298}
299
David Benjaminc20febe2014-11-11 23:47:50 -0500300int RSA_supports_digest(const RSA *rsa, const EVP_MD *md) {
301 if (rsa->meth && rsa->meth->supports_digest) {
302 return rsa->meth->supports_digest(rsa, md);
303 }
304 return 1;
305}
306
Adam Langley95c29f32014-06-20 12:00:00 -0700307int RSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
308 CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) {
David Benjamin9f33fc62015-04-15 17:29:53 -0400309 int index;
310 if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, new_func,
311 dup_func, free_func)) {
312 return -1;
313 }
314 return index;
Adam Langley95c29f32014-06-20 12:00:00 -0700315}
316
317int RSA_set_ex_data(RSA *d, int idx, void *arg) {
318 return CRYPTO_set_ex_data(&d->ex_data, idx, arg);
319}
320
321void *RSA_get_ex_data(const RSA *d, int idx) {
322 return CRYPTO_get_ex_data(&d->ex_data, idx);
323}
324
325/* SSL_SIG_LENGTH is the size of an SSL/TLS (prior to TLS 1.2) signature: it's
326 * the length of an MD5 and SHA1 hash. */
327static const unsigned SSL_SIG_LENGTH = 36;
328
329/* pkcs1_sig_prefix contains the ASN.1, DER encoded prefix for a hash that is
330 * to be signed with PKCS#1. */
331struct pkcs1_sig_prefix {
332 /* nid identifies the hash function. */
333 int nid;
334 /* len is the number of bytes of |bytes| which are valid. */
335 uint8_t len;
336 /* bytes contains the DER bytes. */
337 uint8_t bytes[19];
338};
339
340/* kPKCS1SigPrefixes contains the ASN.1 prefixes for PKCS#1 signatures with
341 * different hash functions. */
342static const struct pkcs1_sig_prefix kPKCS1SigPrefixes[] = {
343 {
344 NID_md5,
345 18,
346 {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
347 0x02, 0x05, 0x05, 0x00, 0x04, 0x10},
348 },
349 {
350 NID_sha1,
351 15,
352 {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05,
353 0x00, 0x04, 0x14},
354 },
355 {
356 NID_sha224,
357 19,
358 {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
359 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c},
360 },
361 {
362 NID_sha256,
363 19,
364 {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
365 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20},
366 },
367 {
368 NID_sha384,
369 19,
370 {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
371 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30},
372 },
373 {
374 NID_sha512,
375 19,
376 {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
377 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40},
378 },
379 {
Adam Langley95c29f32014-06-20 12:00:00 -0700380 NID_undef, 0, {0},
381 },
382};
383
David Benjaminb0acb772015-05-28 16:53:31 -0400384int RSA_add_pkcs1_prefix(uint8_t **out_msg, size_t *out_msg_len,
385 int *is_alloced, int hash_nid, const uint8_t *msg,
386 size_t msg_len) {
Adam Langley95c29f32014-06-20 12:00:00 -0700387 unsigned i;
Adam Langley95c29f32014-06-20 12:00:00 -0700388
389 if (hash_nid == NID_md5_sha1) {
390 /* Special case: SSL signature, just check the length. */
391 if (msg_len != SSL_SIG_LENGTH) {
David Benjamin3570d732015-06-29 00:28:17 -0400392 OPENSSL_PUT_ERROR(RSA, RSA_R_INVALID_MESSAGE_LENGTH);
Adam Langley95c29f32014-06-20 12:00:00 -0700393 return 0;
394 }
395
396 *out_msg = (uint8_t*) msg;
397 *out_msg_len = SSL_SIG_LENGTH;
398 *is_alloced = 0;
399 return 1;
400 }
401
402 for (i = 0; kPKCS1SigPrefixes[i].nid != NID_undef; i++) {
403 const struct pkcs1_sig_prefix *sig_prefix = &kPKCS1SigPrefixes[i];
Brian Smitha039d702015-01-29 15:03:18 -0800404 if (sig_prefix->nid != hash_nid) {
405 continue;
Adam Langley95c29f32014-06-20 12:00:00 -0700406 }
Brian Smitha039d702015-01-29 15:03:18 -0800407
408 const uint8_t* prefix = sig_prefix->bytes;
409 unsigned prefix_len = sig_prefix->len;
410 unsigned signed_msg_len;
411 uint8_t *signed_msg;
412
413 signed_msg_len = prefix_len + msg_len;
414 if (signed_msg_len < prefix_len) {
David Benjamin3570d732015-06-29 00:28:17 -0400415 OPENSSL_PUT_ERROR(RSA, RSA_R_TOO_LONG);
Brian Smitha039d702015-01-29 15:03:18 -0800416 return 0;
417 }
418
419 signed_msg = OPENSSL_malloc(signed_msg_len);
420 if (!signed_msg) {
David Benjamin3570d732015-06-29 00:28:17 -0400421 OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
Brian Smitha039d702015-01-29 15:03:18 -0800422 return 0;
423 }
424
425 memcpy(signed_msg, prefix, prefix_len);
426 memcpy(signed_msg + prefix_len, msg, msg_len);
427
428 *out_msg = signed_msg;
429 *out_msg_len = signed_msg_len;
430 *is_alloced = 1;
431
432 return 1;
Adam Langley95c29f32014-06-20 12:00:00 -0700433 }
434
David Benjamin3570d732015-06-29 00:28:17 -0400435 OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_ALGORITHM_TYPE);
Brian Smitha039d702015-01-29 15:03:18 -0800436 return 0;
Adam Langley95c29f32014-06-20 12:00:00 -0700437}
438
439int RSA_sign(int hash_nid, const uint8_t *in, unsigned in_len, uint8_t *out,
440 unsigned *out_len, RSA *rsa) {
441 const unsigned rsa_size = RSA_size(rsa);
442 int ret = 0;
443 uint8_t *signed_msg;
444 size_t signed_msg_len;
445 int signed_msg_is_alloced = 0;
446 size_t size_t_out_len;
447
448 if (rsa->meth->sign) {
449 return rsa->meth->sign(hash_nid, in, in_len, out, out_len, rsa);
450 }
451
David Benjaminb0acb772015-05-28 16:53:31 -0400452 if (!RSA_add_pkcs1_prefix(&signed_msg, &signed_msg_len,
453 &signed_msg_is_alloced, hash_nid, in, in_len)) {
Adam Langley95c29f32014-06-20 12:00:00 -0700454 return 0;
455 }
456
457 if (rsa_size < RSA_PKCS1_PADDING_SIZE ||
458 signed_msg_len > rsa_size - RSA_PKCS1_PADDING_SIZE) {
David Benjamin3570d732015-06-29 00:28:17 -0400459 OPENSSL_PUT_ERROR(RSA, RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY);
Adam Langley95c29f32014-06-20 12:00:00 -0700460 goto finish;
461 }
462
463 if (RSA_sign_raw(rsa, &size_t_out_len, out, rsa_size, signed_msg,
464 signed_msg_len, RSA_PKCS1_PADDING)) {
465 *out_len = size_t_out_len;
466 ret = 1;
467 }
468
469finish:
470 if (signed_msg_is_alloced) {
471 OPENSSL_free(signed_msg);
472 }
473 return ret;
474}
475
476int RSA_verify(int hash_nid, const uint8_t *msg, size_t msg_len,
477 const uint8_t *sig, size_t sig_len, RSA *rsa) {
478 const size_t rsa_size = RSA_size(rsa);
479 uint8_t *buf = NULL;
480 int ret = 0;
481 uint8_t *signed_msg = NULL;
482 size_t signed_msg_len, len;
483 int signed_msg_is_alloced = 0;
484
485 if (rsa->meth->verify) {
486 return rsa->meth->verify(hash_nid, msg, msg_len, sig, sig_len, rsa);
487 }
488
489 if (sig_len != rsa_size) {
David Benjamin3570d732015-06-29 00:28:17 -0400490 OPENSSL_PUT_ERROR(RSA, RSA_R_WRONG_SIGNATURE_LENGTH);
Adam Langley95c29f32014-06-20 12:00:00 -0700491 return 0;
492 }
493
494 if (hash_nid == NID_md5_sha1 && msg_len != SSL_SIG_LENGTH) {
David Benjamin3570d732015-06-29 00:28:17 -0400495 OPENSSL_PUT_ERROR(RSA, RSA_R_INVALID_MESSAGE_LENGTH);
Adam Langley95c29f32014-06-20 12:00:00 -0700496 return 0;
497 }
498
499 buf = OPENSSL_malloc(rsa_size);
500 if (!buf) {
David Benjamin3570d732015-06-29 00:28:17 -0400501 OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
Adam Langley95c29f32014-06-20 12:00:00 -0700502 return 0;
503 }
504
505 if (!RSA_verify_raw(rsa, &len, buf, rsa_size, sig, sig_len,
506 RSA_PKCS1_PADDING)) {
507 goto out;
508 }
509
David Benjaminb0acb772015-05-28 16:53:31 -0400510 if (!RSA_add_pkcs1_prefix(&signed_msg, &signed_msg_len,
511 &signed_msg_is_alloced, hash_nid, msg, msg_len)) {
Adam Langley95c29f32014-06-20 12:00:00 -0700512 goto out;
513 }
514
515 if (len != signed_msg_len || CRYPTO_memcmp(buf, signed_msg, len) != 0) {
David Benjamin3570d732015-06-29 00:28:17 -0400516 OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_SIGNATURE);
Adam Langley95c29f32014-06-20 12:00:00 -0700517 goto out;
518 }
519
520 ret = 1;
521
522out:
David Benjamind8b65c82015-04-22 16:09:09 -0400523 OPENSSL_free(buf);
Adam Langley95c29f32014-06-20 12:00:00 -0700524 if (signed_msg_is_alloced) {
525 OPENSSL_free(signed_msg);
526 }
527 return ret;
528}
Adam Langley409766d2014-06-20 12:00:00 -0700529
530static void bn_free_and_null(BIGNUM **bn) {
Adam Langley409766d2014-06-20 12:00:00 -0700531 BN_free(*bn);
532 *bn = NULL;
533}
534
Adam Langley05b73772014-07-25 12:03:51 -0700535int RSA_check_key(const RSA *key) {
536 BIGNUM n, pm1, qm1, lcm, gcd, de, dmp1, dmq1, iqmp;
537 BN_CTX *ctx;
538 int ok = 0, has_crt_values;
539
540 if (RSA_is_opaque(key)) {
541 /* Opaque keys can't be checked. */
542 return 1;
543 }
544
545 if ((key->p != NULL) != (key->q != NULL)) {
David Benjamin3570d732015-06-29 00:28:17 -0400546 OPENSSL_PUT_ERROR(RSA, RSA_R_ONLY_ONE_OF_P_Q_GIVEN);
Adam Langley05b73772014-07-25 12:03:51 -0700547 return 0;
548 }
549
550 if (!key->n || !key->e) {
David Benjamin3570d732015-06-29 00:28:17 -0400551 OPENSSL_PUT_ERROR(RSA, RSA_R_VALUE_MISSING);
Adam Langley05b73772014-07-25 12:03:51 -0700552 return 0;
553 }
554
555 if (!key->d || !key->p) {
556 /* For a public key, or without p and q, there's nothing that can be
557 * checked. */
558 return 1;
559 }
560
561 ctx = BN_CTX_new();
562 if (ctx == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400563 OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
Adam Langley05b73772014-07-25 12:03:51 -0700564 return 0;
565 }
566
567 BN_init(&n);
568 BN_init(&pm1);
569 BN_init(&qm1);
570 BN_init(&lcm);
571 BN_init(&gcd);
572 BN_init(&de);
573 BN_init(&dmp1);
574 BN_init(&dmq1);
575 BN_init(&iqmp);
576
Adam Langley839b8812015-05-26 11:36:46 -0700577 if (!BN_mul(&n, key->p, key->q, ctx) ||
578 /* lcm = lcm(prime-1, for all primes) */
Adam Langley05b73772014-07-25 12:03:51 -0700579 !BN_sub(&pm1, key->p, BN_value_one()) ||
580 !BN_sub(&qm1, key->q, BN_value_one()) ||
581 !BN_mul(&lcm, &pm1, &qm1, ctx) ||
Adam Langley839b8812015-05-26 11:36:46 -0700582 !BN_gcd(&gcd, &pm1, &qm1, ctx)) {
David Benjamin3570d732015-06-29 00:28:17 -0400583 OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN);
Adam Langley839b8812015-05-26 11:36:46 -0700584 goto out;
585 }
586
587 size_t num_additional_primes = 0;
588 if (key->additional_primes != NULL) {
589 num_additional_primes = sk_RSA_additional_prime_num(key->additional_primes);
590 }
591
592 size_t i;
593 for (i = 0; i < num_additional_primes; i++) {
594 const RSA_additional_prime *ap =
595 sk_RSA_additional_prime_value(key->additional_primes, i);
596 if (!BN_mul(&n, &n, ap->prime, ctx) ||
597 !BN_sub(&pm1, ap->prime, BN_value_one()) ||
598 !BN_mul(&lcm, &lcm, &pm1, ctx) ||
599 !BN_gcd(&gcd, &gcd, &pm1, ctx)) {
David Benjamin3570d732015-06-29 00:28:17 -0400600 OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN);
Adam Langley839b8812015-05-26 11:36:46 -0700601 goto out;
602 }
603 }
604
605 if (!BN_div(&lcm, NULL, &lcm, &gcd, ctx) ||
Adam Langley05b73772014-07-25 12:03:51 -0700606 !BN_gcd(&gcd, &pm1, &qm1, ctx) ||
Adam Langley839b8812015-05-26 11:36:46 -0700607 /* de = d*e mod lcm(prime-1, for all primes). */
Adam Langley05b73772014-07-25 12:03:51 -0700608 !BN_mod_mul(&de, key->d, key->e, &lcm, ctx)) {
David Benjamin3570d732015-06-29 00:28:17 -0400609 OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN);
Adam Langley05b73772014-07-25 12:03:51 -0700610 goto out;
611 }
612
613 if (BN_cmp(&n, key->n) != 0) {
David Benjamin3570d732015-06-29 00:28:17 -0400614 OPENSSL_PUT_ERROR(RSA, RSA_R_N_NOT_EQUAL_P_Q);
Adam Langley05b73772014-07-25 12:03:51 -0700615 goto out;
616 }
617
618 if (!BN_is_one(&de)) {
David Benjamin3570d732015-06-29 00:28:17 -0400619 OPENSSL_PUT_ERROR(RSA, RSA_R_D_E_NOT_CONGRUENT_TO_1);
Adam Langley05b73772014-07-25 12:03:51 -0700620 goto out;
621 }
622
623 has_crt_values = key->dmp1 != NULL;
624 if (has_crt_values != (key->dmq1 != NULL) ||
625 has_crt_values != (key->iqmp != NULL)) {
David Benjamin3570d732015-06-29 00:28:17 -0400626 OPENSSL_PUT_ERROR(RSA, RSA_R_INCONSISTENT_SET_OF_CRT_VALUES);
Adam Langley05b73772014-07-25 12:03:51 -0700627 goto out;
628 }
629
Adam Langley839b8812015-05-26 11:36:46 -0700630 if (has_crt_values && num_additional_primes == 0) {
Adam Langley05b73772014-07-25 12:03:51 -0700631 if (/* dmp1 = d mod (p-1) */
632 !BN_mod(&dmp1, key->d, &pm1, ctx) ||
633 /* dmq1 = d mod (q-1) */
634 !BN_mod(&dmq1, key->d, &qm1, ctx) ||
635 /* iqmp = q^-1 mod p */
636 !BN_mod_inverse(&iqmp, key->q, key->p, ctx)) {
David Benjamin3570d732015-06-29 00:28:17 -0400637 OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN);
Adam Langley05b73772014-07-25 12:03:51 -0700638 goto out;
639 }
640
641 if (BN_cmp(&dmp1, key->dmp1) != 0 ||
642 BN_cmp(&dmq1, key->dmq1) != 0 ||
643 BN_cmp(&iqmp, key->iqmp) != 0) {
David Benjamin3570d732015-06-29 00:28:17 -0400644 OPENSSL_PUT_ERROR(RSA, RSA_R_CRT_VALUES_INCORRECT);
Adam Langley05b73772014-07-25 12:03:51 -0700645 goto out;
646 }
647 }
648
649 ok = 1;
650
651out:
652 BN_free(&n);
653 BN_free(&pm1);
654 BN_free(&qm1);
655 BN_free(&lcm);
656 BN_free(&gcd);
657 BN_free(&de);
658 BN_free(&dmp1);
659 BN_free(&dmq1);
660 BN_free(&iqmp);
661 BN_CTX_free(ctx);
662
663 return ok;
664}
665
Adam Langley409766d2014-06-20 12:00:00 -0700666int RSA_recover_crt_params(RSA *rsa) {
667 BN_CTX *ctx;
668 BIGNUM *totient, *rem, *multiple, *p_plus_q, *p_minus_q;
669 int ok = 0;
670
671 if (rsa->n == NULL || rsa->e == NULL || rsa->d == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400672 OPENSSL_PUT_ERROR(RSA, RSA_R_EMPTY_PUBLIC_KEY);
Adam Langley409766d2014-06-20 12:00:00 -0700673 return 0;
674 }
675
676 if (rsa->p || rsa->q || rsa->dmp1 || rsa->dmq1 || rsa->iqmp) {
David Benjamin3570d732015-06-29 00:28:17 -0400677 OPENSSL_PUT_ERROR(RSA, RSA_R_CRT_PARAMS_ALREADY_GIVEN);
Adam Langley409766d2014-06-20 12:00:00 -0700678 return 0;
679 }
680
Adam Langley839b8812015-05-26 11:36:46 -0700681 if (rsa->additional_primes != NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400682 OPENSSL_PUT_ERROR(RSA, RSA_R_CANNOT_RECOVER_MULTI_PRIME_KEY);
Adam Langley839b8812015-05-26 11:36:46 -0700683 return 0;
684 }
685
Adam Langley409766d2014-06-20 12:00:00 -0700686 /* This uses the algorithm from section 9B of the RSA paper:
687 * http://people.csail.mit.edu/rivest/Rsapaper.pdf */
688
689 ctx = BN_CTX_new();
690 if (ctx == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400691 OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
Adam Langley409766d2014-06-20 12:00:00 -0700692 return 0;
693 }
694
695 BN_CTX_start(ctx);
696 totient = BN_CTX_get(ctx);
697 rem = BN_CTX_get(ctx);
698 multiple = BN_CTX_get(ctx);
699 p_plus_q = BN_CTX_get(ctx);
700 p_minus_q = BN_CTX_get(ctx);
701
702 if (totient == NULL || rem == NULL || multiple == NULL || p_plus_q == NULL ||
703 p_minus_q == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400704 OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
Adam Langley409766d2014-06-20 12:00:00 -0700705 goto err;
706 }
707
708 /* ed-1 is a small multiple of φ(n). */
709 if (!BN_mul(totient, rsa->e, rsa->d, ctx) ||
710 !BN_sub_word(totient, 1) ||
711 /* φ(n) =
712 * pq - p - q + 1 =
713 * n - (p + q) + 1
714 *
715 * Thus n is a reasonable estimate for φ(n). So, (ed-1)/n will be very
716 * close. But, when we calculate the quotient, we'll be truncating it
717 * because we discard the remainder. Thus (ed-1)/multiple will be >= n,
718 * which the totient cannot be. So we add one to the estimate.
719 *
720 * Consider ed-1 as:
721 *
722 * multiple * (n - (p+q) + 1) =
723 * multiple*n - multiple*(p+q) + multiple
724 *
725 * When we divide by n, the first term becomes multiple and, since
726 * multiple and p+q is tiny compared to n, the second and third terms can
727 * be ignored. Thus I claim that subtracting one from the estimate is
728 * sufficient. */
729 !BN_div(multiple, NULL, totient, rsa->n, ctx) ||
730 !BN_add_word(multiple, 1) ||
731 !BN_div(totient, rem, totient, multiple, ctx)) {
David Benjamin3570d732015-06-29 00:28:17 -0400732 OPENSSL_PUT_ERROR(RSA, ERR_R_BN_LIB);
Adam Langley409766d2014-06-20 12:00:00 -0700733 goto err;
734 }
735
736 if (!BN_is_zero(rem)) {
David Benjamin3570d732015-06-29 00:28:17 -0400737 OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_RSA_PARAMETERS);
Adam Langley409766d2014-06-20 12:00:00 -0700738 goto err;
739 }
740
741 rsa->p = BN_new();
742 rsa->q = BN_new();
743 rsa->dmp1 = BN_new();
744 rsa->dmq1 = BN_new();
745 rsa->iqmp = BN_new();
746 if (rsa->p == NULL || rsa->q == NULL || rsa->dmp1 == NULL || rsa->dmq1 ==
747 NULL || rsa->iqmp == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400748 OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
Adam Langley409766d2014-06-20 12:00:00 -0700749 goto err;
750 }
751
752 /* φ(n) = n - (p + q) + 1 =>
753 * n - totient + 1 = p + q */
754 if (!BN_sub(p_plus_q, rsa->n, totient) ||
755 !BN_add_word(p_plus_q, 1) ||
756 /* p - q = sqrt((p+q)^2 - 4n) */
757 !BN_sqr(rem, p_plus_q, ctx) ||
758 !BN_lshift(multiple, rsa->n, 2) ||
759 !BN_sub(rem, rem, multiple) ||
760 !BN_sqrt(p_minus_q, rem, ctx) ||
761 /* q is 1/2 (p+q)-(p-q) */
762 !BN_sub(rsa->q, p_plus_q, p_minus_q) ||
763 !BN_rshift1(rsa->q, rsa->q) ||
764 !BN_div(rsa->p, NULL, rsa->n, rsa->q, ctx) ||
765 !BN_mul(multiple, rsa->p, rsa->q, ctx)) {
David Benjamin3570d732015-06-29 00:28:17 -0400766 OPENSSL_PUT_ERROR(RSA, ERR_R_BN_LIB);
Adam Langley409766d2014-06-20 12:00:00 -0700767 goto err;
768 }
769
770 if (BN_cmp(multiple, rsa->n) != 0) {
David Benjamin3570d732015-06-29 00:28:17 -0400771 OPENSSL_PUT_ERROR(RSA, RSA_R_INTERNAL_ERROR);
Adam Langley409766d2014-06-20 12:00:00 -0700772 goto err;
773 }
774
775 if (!BN_sub(rem, rsa->p, BN_value_one()) ||
776 !BN_mod(rsa->dmp1, rsa->d, rem, ctx) ||
777 !BN_sub(rem, rsa->q, BN_value_one()) ||
778 !BN_mod(rsa->dmq1, rsa->d, rem, ctx) ||
779 !BN_mod_inverse(rsa->iqmp, rsa->q, rsa->p, ctx)) {
David Benjamin3570d732015-06-29 00:28:17 -0400780 OPENSSL_PUT_ERROR(RSA, ERR_R_BN_LIB);
Adam Langley409766d2014-06-20 12:00:00 -0700781 goto err;
782 }
783
784 ok = 1;
785
786err:
787 BN_CTX_end(ctx);
788 BN_CTX_free(ctx);
789 if (!ok) {
790 bn_free_and_null(&rsa->p);
791 bn_free_and_null(&rsa->q);
792 bn_free_and_null(&rsa->dmp1);
793 bn_free_and_null(&rsa->dmq1);
794 bn_free_and_null(&rsa->iqmp);
795 }
796 return ok;
797}
Adam Langley6bc658d2014-08-18 13:29:45 -0700798
799int RSA_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in,
800 size_t len) {
801 if (rsa->meth->private_transform) {
802 return rsa->meth->private_transform(rsa, out, in, len);
803 }
804
David Benjamind93831d2015-10-29 13:19:12 -0400805 return rsa_default_private_transform(rsa, out, in, len);
Adam Langley6bc658d2014-08-18 13:29:45 -0700806}
Adam Langleyc3ef76f2015-04-13 14:34:17 -0700807
808int RSA_blinding_on(RSA *rsa, BN_CTX *ctx) {
809 return 1;
810}