ssl/tls: add proper const attributes to functions, context members
[tropicssl.git] / library / rsa.c
blobb8d16a5a43f5ef0dc2faddf451996ce6d3991d46
1 /*
2 * The RSA public-key cryptosystem
4 * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
6 * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
8 * All rights reserved.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
14 * * Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * * Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * * Neither the names of PolarSSL or XySSL nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 * RSA was designed by Ron Rivest, Adi Shamir and Len Adleman.
38 * http://theory.lcs.mit.edu/~rivest/rsapaper.pdf
39 * http://www.cacr.math.uwaterloo.ca/hac/about/chap8.pdf
42 #include "tropicssl/config.h"
44 #if defined(TROPICSSL_RSA_C)
46 #include "tropicssl/rsa.h"
48 #include <stdlib.h>
49 #include <string.h>
50 #include <stdio.h>
53 * Initialize an RSA context
55 void rsa_init(rsa_context * ctx,
56 int padding, int hash_id, int (*f_rng) (void *), void *p_rng)
58 memset(ctx, 0, sizeof(rsa_context));
60 ctx->padding = padding;
61 ctx->hash_id = hash_id;
63 ctx->f_rng = f_rng;
64 ctx->p_rng = p_rng;
67 #if defined(TROPICSSL_GENPRIME)
70 * Generate an RSA keypair
72 int rsa_gen_key(rsa_context * ctx, int nbits, int exponent)
74 int ret;
75 mpi P1, Q1, H, G;
77 if (ctx->f_rng == NULL || nbits < 128 || exponent < 3)
78 return (TROPICSSL_ERR_RSA_BAD_INPUT_DATA);
80 mpi_init(&P1, &Q1, &H, &G, NULL);
83 * find primes P and Q with Q < P so that:
84 * GCD( E, (P-1)*(Q-1) ) == 1
86 MPI_CHK(mpi_lset(&ctx->E, exponent));
88 do {
89 MPI_CHK(mpi_gen_prime(&ctx->P, (nbits + 1) >> 1, 0,
90 ctx->f_rng, ctx->p_rng));
92 MPI_CHK(mpi_gen_prime(&ctx->Q, (nbits + 1) >> 1, 0,
93 ctx->f_rng, ctx->p_rng));
95 if (mpi_cmp_mpi(&ctx->P, &ctx->Q) < 0)
96 mpi_swap(&ctx->P, &ctx->Q);
98 if (mpi_cmp_mpi(&ctx->P, &ctx->Q) == 0)
99 continue;
101 MPI_CHK(mpi_mul_mpi(&ctx->N, &ctx->P, &ctx->Q));
102 if (mpi_msb(&ctx->N) != nbits)
103 continue;
105 MPI_CHK(mpi_sub_int(&P1, &ctx->P, 1));
106 MPI_CHK(mpi_sub_int(&Q1, &ctx->Q, 1));
107 MPI_CHK(mpi_mul_mpi(&H, &P1, &Q1));
108 MPI_CHK(mpi_gcd(&G, &ctx->E, &H));
109 } while (mpi_cmp_int(&G, 1) != 0);
112 * D = E^-1 mod ((P-1)*(Q-1))
113 * DP = D mod (P - 1)
114 * DQ = D mod (Q - 1)
115 * QP = Q^-1 mod P
117 MPI_CHK(mpi_inv_mod(&ctx->D, &ctx->E, &H));
118 MPI_CHK(mpi_mod_mpi(&ctx->DP, &ctx->D, &P1));
119 MPI_CHK(mpi_mod_mpi(&ctx->DQ, &ctx->D, &Q1));
120 MPI_CHK(mpi_inv_mod(&ctx->QP, &ctx->Q, &ctx->P));
122 ctx->len = (mpi_msb(&ctx->N) + 7) >> 3;
124 cleanup:
126 mpi_free(&G, &H, &Q1, &P1, NULL);
128 if (ret != 0) {
129 rsa_free(ctx);
130 return (TROPICSSL_ERR_RSA_KEY_GEN_FAILED | ret);
133 return (0);
136 #endif
139 * Check a public RSA key
141 int rsa_check_pubkey(const rsa_context * ctx)
143 if ((ctx->N.p[0] & 1) == 0 || (ctx->E.p[0] & 1) == 0)
144 return (TROPICSSL_ERR_RSA_KEY_CHECK_FAILED);
146 if (mpi_msb(&ctx->N) < 128 || mpi_msb(&ctx->N) > 4096)
147 return (TROPICSSL_ERR_RSA_KEY_CHECK_FAILED);
149 if (mpi_msb(&ctx->E) < 2 || mpi_msb(&ctx->E) > 64)
150 return (TROPICSSL_ERR_RSA_KEY_CHECK_FAILED);
152 return (0);
156 * Check a private RSA key
158 int rsa_check_privkey(const rsa_context * ctx)
160 int ret;
161 mpi PQ, DE, P1, Q1, H, I, G;
163 if ((ret = rsa_check_pubkey(ctx)) != 0)
164 return (ret);
166 mpi_init(&PQ, &DE, &P1, &Q1, &H, &I, &G, NULL);
168 MPI_CHK(mpi_mul_mpi(&PQ, &ctx->P, &ctx->Q));
169 MPI_CHK(mpi_mul_mpi(&DE, &ctx->D, &ctx->E));
170 MPI_CHK(mpi_sub_int(&P1, &ctx->P, 1));
171 MPI_CHK(mpi_sub_int(&Q1, &ctx->Q, 1));
172 MPI_CHK(mpi_mul_mpi(&H, &P1, &Q1));
173 MPI_CHK(mpi_mod_mpi(&I, &DE, &H));
174 MPI_CHK(mpi_gcd(&G, &ctx->E, &H));
176 if (mpi_cmp_mpi(&PQ, &ctx->N) == 0 &&
177 mpi_cmp_int(&I, 1) == 0 && mpi_cmp_int(&G, 1) == 0) {
178 mpi_free(&G, &I, &H, &Q1, &P1, &DE, &PQ, NULL);
179 return (0);
182 cleanup:
184 mpi_free(&G, &I, &H, &Q1, &P1, &DE, &PQ, NULL);
185 return (TROPICSSL_ERR_RSA_KEY_CHECK_FAILED | ret);
189 * Do an RSA public key operation
191 int rsa_public(rsa_context * ctx, const unsigned char *input, unsigned char *output)
193 int ret, olen;
194 mpi T;
196 mpi_init(&T, NULL);
198 MPI_CHK(mpi_read_binary(&T, input, ctx->len));
200 if (mpi_cmp_mpi(&T, &ctx->N) >= 0) {
201 mpi_free(&T, NULL);
202 return (TROPICSSL_ERR_RSA_BAD_INPUT_DATA);
205 olen = ctx->len;
206 MPI_CHK(mpi_exp_mod(&T, &T, &ctx->E, &ctx->N, &ctx->RN));
207 MPI_CHK(mpi_write_binary(&T, output, olen));
209 cleanup:
211 mpi_free(&T, NULL);
213 if (ret != 0)
214 return (TROPICSSL_ERR_RSA_PUBLIC_FAILED | ret);
216 return (0);
220 * Do an RSA private key operation
222 int rsa_private(rsa_context * ctx, const unsigned char *input, unsigned char *output)
224 int ret, olen;
225 mpi T, T1, T2;
227 mpi_init(&T, &T1, &T2, NULL);
229 MPI_CHK(mpi_read_binary(&T, input, ctx->len));
231 if (mpi_cmp_mpi(&T, &ctx->N) >= 0) {
232 mpi_free(&T, NULL);
233 return (TROPICSSL_ERR_RSA_BAD_INPUT_DATA);
235 #if 0
236 MPI_CHK(mpi_exp_mod(&T, &T, &ctx->D, &ctx->N, &ctx->RN));
237 #else
239 * faster decryption using the CRT
241 * T1 = input ^ dP mod P
242 * T2 = input ^ dQ mod Q
244 MPI_CHK(mpi_exp_mod(&T1, &T, &ctx->DP, &ctx->P, &ctx->RP));
245 MPI_CHK(mpi_exp_mod(&T2, &T, &ctx->DQ, &ctx->Q, &ctx->RQ));
248 * T = (T1 - T2) * (Q^-1 mod P) mod P
250 MPI_CHK(mpi_sub_mpi(&T, &T1, &T2));
251 MPI_CHK(mpi_mul_mpi(&T1, &T, &ctx->QP));
252 MPI_CHK(mpi_mod_mpi(&T, &T1, &ctx->P));
255 * output = T2 + T * Q
257 MPI_CHK(mpi_mul_mpi(&T1, &T, &ctx->Q));
258 MPI_CHK(mpi_add_mpi(&T, &T2, &T1));
259 #endif
261 olen = ctx->len;
262 MPI_CHK(mpi_write_binary(&T, output, olen));
264 cleanup:
266 mpi_free(&T, &T1, &T2, NULL);
268 if (ret != 0)
269 return (TROPICSSL_ERR_RSA_PRIVATE_FAILED | ret);
271 return (0);
275 * Add the message padding, then do an RSA operation
277 int rsa_pkcs1_encrypt(rsa_context * ctx,
278 int mode, int ilen,
279 const unsigned char *input,
280 unsigned char *output)
282 int nb_pad, olen;
283 unsigned char *p = output;
285 olen = ctx->len;
287 switch (ctx->padding) {
288 case RSA_PKCS_V15:
290 if (ilen < 0 || olen < ilen + 11)
291 return (TROPICSSL_ERR_RSA_BAD_INPUT_DATA);
293 nb_pad = olen - 3 - ilen;
295 *p++ = 0;
296 *p++ = RSA_CRYPT;
298 while (nb_pad-- > 0) {
299 do {
300 *p = (unsigned char)rand();
301 } while (*p == 0);
302 p++;
304 *p++ = 0;
305 memcpy(p, input, ilen);
306 break;
308 default:
310 return (TROPICSSL_ERR_RSA_INVALID_PADDING);
313 return ((mode == RSA_PUBLIC)
314 ? rsa_public(ctx, output, output)
315 : rsa_private(ctx, output, output));
319 * Do an RSA operation, then remove the message padding
321 int rsa_pkcs1_decrypt(rsa_context * ctx,
322 int mode, int *olen,
323 const unsigned char *input,
324 unsigned char *output,
325 int output_max_len)
327 int ret, ilen;
328 unsigned char *p;
329 unsigned char buf[512];
331 ilen = ctx->len;
333 if (ilen < 16 || ilen > (int)sizeof(buf))
334 return (TROPICSSL_ERR_RSA_BAD_INPUT_DATA);
336 ret = (mode == RSA_PUBLIC)
337 ? rsa_public(ctx, input, buf)
338 : rsa_private(ctx, input, buf);
340 if (ret != 0)
341 return (ret);
343 p = buf;
345 switch (ctx->padding) {
346 case RSA_PKCS_V15:
348 if (*p++ != 0 || *p++ != RSA_CRYPT)
349 return (TROPICSSL_ERR_RSA_INVALID_PADDING);
351 while (*p != 0) {
352 if (p >= buf + ilen - 1)
353 return (TROPICSSL_ERR_RSA_INVALID_PADDING);
354 p++;
356 p++;
357 break;
359 default:
361 return (TROPICSSL_ERR_RSA_INVALID_PADDING);
364 if (ilen - (int)(p - buf) > output_max_len)
365 return (TROPICSSL_ERR_RSA_OUTPUT_TO_LARGE);
367 *olen = ilen - (int)(p - buf);
368 memcpy(output, p, *olen);
370 return (0);
374 * Do an RSA operation to sign the message digest
376 int rsa_pkcs1_sign(rsa_context * ctx,
377 int mode,
378 int hash_id,
379 int hashlen,
380 const unsigned char *hash,
381 unsigned char *sig)
383 int nb_pad, olen;
384 unsigned char *p = sig;
386 olen = ctx->len;
388 switch (ctx->padding) {
389 case RSA_PKCS_V15:
391 switch (hash_id) {
392 case RSA_RAW:
393 nb_pad = olen - 3 - hashlen;
394 break;
396 case RSA_MD2:
397 case RSA_MD4:
398 case RSA_MD5:
399 nb_pad = olen - 3 - 34;
400 break;
402 case RSA_SHA1:
403 nb_pad = olen - 3 - 35;
404 break;
406 default:
407 return (TROPICSSL_ERR_RSA_BAD_INPUT_DATA);
410 if (nb_pad < 8)
411 return (TROPICSSL_ERR_RSA_BAD_INPUT_DATA);
413 *p++ = 0;
414 *p++ = RSA_SIGN;
415 memset(p, 0xFF, nb_pad);
416 p += nb_pad;
417 *p++ = 0;
418 break;
420 default:
422 return (TROPICSSL_ERR_RSA_INVALID_PADDING);
425 switch (hash_id) {
426 case RSA_RAW:
427 memcpy(p, hash, hashlen);
428 break;
430 case RSA_MD2:
431 memcpy(p, ASN1_HASH_MDX, 18);
432 memcpy(p + 18, hash, 16);
433 p[13] = 2;
434 break;
436 case RSA_MD4:
437 memcpy(p, ASN1_HASH_MDX, 18);
438 memcpy(p + 18, hash, 16);
439 p[13] = 4;
440 break;
442 case RSA_MD5:
443 memcpy(p, ASN1_HASH_MDX, 18);
444 memcpy(p + 18, hash, 16);
445 p[13] = 5;
446 break;
448 case RSA_SHA1:
449 memcpy(p, ASN1_HASH_SHA1, 15);
450 memcpy(p + 15, hash, 20);
451 break;
453 default:
454 return (TROPICSSL_ERR_RSA_BAD_INPUT_DATA);
457 return ((mode == RSA_PUBLIC)
458 ? rsa_public(ctx, sig, sig)
459 : rsa_private(ctx, sig, sig));
463 * Do an RSA operation and check the message digest
465 int rsa_pkcs1_verify(rsa_context * ctx,
466 int mode,
467 int hash_id,
468 int hashlen,
469 const unsigned char *hash,
470 const unsigned char *sig)
472 int ret, len, siglen;
473 unsigned char *p, c;
474 unsigned char buf[512];
476 siglen = ctx->len;
478 if (siglen < 16 || siglen > (int)sizeof(buf))
479 return (TROPICSSL_ERR_RSA_BAD_INPUT_DATA);
481 ret = (mode == RSA_PUBLIC)
482 ? rsa_public(ctx, sig, buf)
483 : rsa_private(ctx, sig, buf);
485 if (ret != 0)
486 return (ret);
488 p = buf;
490 switch (ctx->padding) {
491 case RSA_PKCS_V15:
493 if (*p++ != 0 || *p++ != RSA_SIGN)
494 return (TROPICSSL_ERR_RSA_INVALID_PADDING);
496 while (*p != 0) {
497 if (p >= buf + siglen - 1 || *p != 0xFF)
498 return (TROPICSSL_ERR_RSA_INVALID_PADDING);
499 p++;
501 p++;
502 break;
504 default:
506 return (TROPICSSL_ERR_RSA_INVALID_PADDING);
509 len = siglen - (int)(p - buf);
511 if (len == 34) {
512 c = p[13];
513 p[13] = 0;
515 if (memcmp(p, ASN1_HASH_MDX, 18) != 0)
516 return (TROPICSSL_ERR_RSA_VERIFY_FAILED);
518 if ((c == 2 && hash_id == RSA_MD2) ||
519 (c == 4 && hash_id == RSA_MD4) ||
520 (c == 5 && hash_id == RSA_MD5)) {
521 if (memcmp(p + 18, hash, 16) == 0)
522 return (0);
523 else
524 return (TROPICSSL_ERR_RSA_VERIFY_FAILED);
528 if (len == 35 && hash_id == RSA_SHA1) {
529 if (memcmp(p, ASN1_HASH_SHA1, 15) == 0 &&
530 memcmp(p + 15, hash, 20) == 0)
531 return (0);
532 else
533 return (TROPICSSL_ERR_RSA_VERIFY_FAILED);
536 if (len == hashlen && hash_id == RSA_RAW) {
537 if (memcmp(p, hash, hashlen) == 0)
538 return (0);
539 else
540 return (TROPICSSL_ERR_RSA_VERIFY_FAILED);
543 return (TROPICSSL_ERR_RSA_INVALID_PADDING);
547 * Free the components of an RSA key
549 void rsa_free(rsa_context * ctx)
551 mpi_free(&ctx->RQ, &ctx->RP, &ctx->RN,
552 &ctx->QP, &ctx->DQ, &ctx->DP,
553 &ctx->Q, &ctx->P, &ctx->D, &ctx->E, &ctx->N, NULL);
556 #if defined(TROPICSSL_SELF_TEST)
558 #include "tropicssl/sha1.h"
561 * Example RSA-1024 keypair, for test purposes
563 #define KEY_LEN 128
565 #define RSA_N "9292758453063D803DD603D5E777D788" \
566 "8ED1D5BF35786190FA2F23EBC0848AEA" \
567 "DDA92CA6C3D80B32C4D109BE0F36D6AE" \
568 "7130B9CED7ACDF54CFC7555AC14EEBAB" \
569 "93A89813FBF3C4F8066D2D800F7C38A8" \
570 "1AE31942917403FF4946B0A83D3D3E05" \
571 "EE57C6F5F5606FB5D4BC6CD34EE0801A" \
572 "5E94BB77B07507233A0BC7BAC8F90F79"
574 #define RSA_E "10001"
576 #define RSA_D "24BF6185468786FDD303083D25E64EFC" \
577 "66CA472BC44D253102F8B4A9D3BFA750" \
578 "91386C0077937FE33FA3252D28855837" \
579 "AE1B484A8A9A45F7EE8C0C634F99E8CD" \
580 "DF79C5CE07EE72C7F123142198164234" \
581 "CABB724CF78B8173B9F880FC86322407" \
582 "AF1FEDFDDE2BEB674CA15F3E81A1521E" \
583 "071513A1E85B5DFA031F21ECAE91A34D"
585 #define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \
586 "2C01CAD19EA484A87EA4377637E75500" \
587 "FCB2005C5C7DD6EC4AC023CDA285D796" \
588 "C3D9E75E1EFC42488BB4F1D13AC30A57"
590 #define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \
591 "E211C2B9E5DB1ED0BF61D0D9899620F4" \
592 "910E4168387E3C30AA1E00C339A79508" \
593 "8452DD96A9A5EA5D9DCA68DA636032AF"
595 #define RSA_DP "C1ACF567564274FB07A0BBAD5D26E298" \
596 "3C94D22288ACD763FD8E5600ED4A702D" \
597 "F84198A5F06C2E72236AE490C93F07F8" \
598 "3CC559CD27BC2D1CA488811730BB5725"
600 #define RSA_DQ "4959CBF6F8FEF750AEE6977C155579C7" \
601 "D8AAEA56749EA28623272E4F7D0592AF" \
602 "7C1F1313CAC9471B5C523BFE592F517B" \
603 "407A1BD76C164B93DA2D32A383E58357"
605 #define RSA_QP "9AE7FBC99546432DF71896FC239EADAE" \
606 "F38D18D2B2F0E2DD275AA977E2BF4411" \
607 "F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \
608 "A74206CEC169D74BF5A8C50D6F48EA08"
610 #define PT_LEN 24
611 #define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \
612 "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD"
615 * Checkup routine
617 int rsa_self_test(int verbose)
619 int len;
620 rsa_context rsa;
621 unsigned char sha1sum[20];
622 unsigned char rsa_plaintext[PT_LEN];
623 unsigned char rsa_decrypted[PT_LEN];
624 unsigned char rsa_ciphertext[KEY_LEN];
626 memset(&rsa, 0, sizeof(rsa_context));
628 rsa.len = KEY_LEN;
629 mpi_read_string(&rsa.N, 16, RSA_N);
630 mpi_read_string(&rsa.E, 16, RSA_E);
631 mpi_read_string(&rsa.D, 16, RSA_D);
632 mpi_read_string(&rsa.P, 16, RSA_P);
633 mpi_read_string(&rsa.Q, 16, RSA_Q);
634 mpi_read_string(&rsa.DP, 16, RSA_DP);
635 mpi_read_string(&rsa.DQ, 16, RSA_DQ);
636 mpi_read_string(&rsa.QP, 16, RSA_QP);
638 if (verbose != 0)
639 printf(" RSA key validation: ");
641 if (rsa_check_pubkey(&rsa) != 0 || rsa_check_privkey(&rsa) != 0) {
642 if (verbose != 0)
643 printf("failed\n");
645 return (1);
648 if (verbose != 0)
649 printf("passed\n PKCS#1 encryption : ");
651 memcpy(rsa_plaintext, RSA_PT, PT_LEN);
653 if (rsa_pkcs1_encrypt(&rsa, RSA_PUBLIC, PT_LEN,
654 rsa_plaintext, rsa_ciphertext) != 0) {
655 if (verbose != 0)
656 printf("failed\n");
658 return (1);
661 if (verbose != 0)
662 printf("passed\n PKCS#1 decryption : ");
664 if (rsa_pkcs1_decrypt(&rsa, RSA_PRIVATE, &len,
665 rsa_ciphertext, rsa_decrypted,
666 sizeof(rsa_decrypted)) != 0) {
667 if (verbose != 0)
668 printf("failed\n");
670 return (1);
673 if (memcmp(rsa_decrypted, rsa_plaintext, len) != 0) {
674 if (verbose != 0)
675 printf("failed\n");
677 return (1);
680 if (verbose != 0)
681 printf("passed\n PKCS#1 data sign : ");
683 sha1(rsa_plaintext, PT_LEN, sha1sum);
685 if (rsa_pkcs1_sign(&rsa, RSA_PRIVATE, RSA_SHA1, 20,
686 sha1sum, rsa_ciphertext) != 0) {
687 if (verbose != 0)
688 printf("failed\n");
690 return (1);
693 if (verbose != 0)
694 printf("passed\n PKCS#1 sig. verify: ");
696 if (rsa_pkcs1_verify(&rsa, RSA_PUBLIC, RSA_SHA1, 20,
697 sha1sum, rsa_ciphertext) != 0) {
698 if (verbose != 0)
699 printf("failed\n");
701 return (1);
704 if (verbose != 0)
705 printf("passed\n\n");
707 rsa_free(&rsa);
709 return (0);
712 #endif
714 #endif