blob: 9d54032ca1fdf8599258f32869376dc0bed9ef32 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * The RSA public-key cryptosystem
3 *
4 * Copyright (C) 2006-2007 Christophe Devine
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20/*
21 * RSA was designed by Ron Rivest, Adi Shamir and Len Adleman.
22 *
23 * http://theory.lcs.mit.edu/~rivest/rsapaper.pdf
24 * http://www.cacr.math.uwaterloo.ca/hac/about/chap8.pdf
25 */
26
27#include "xyssl/config.h"
28
29#if defined(XYSSL_RSA_C)
30
31#include "xyssl/rsa.h"
32
33#include <stdlib.h>
34#include <string.h>
35#include <stdio.h>
36
37/*
38 * Initialize an RSA context
39 */
40void rsa_init( rsa_context *ctx,
41 int padding,
42 int hash_id,
43 int (*f_rng)(void *),
44 void *p_rng )
45{
46 memset( ctx, 0, sizeof( rsa_context ) );
47
48 ctx->padding = padding;
49 ctx->hash_id = hash_id;
50
51 ctx->f_rng = f_rng;
52 ctx->p_rng = p_rng;
53}
54
55#if defined(XYSSL_GENPRIME)
56
57/*
58 * Generate an RSA keypair
59 */
60int rsa_gen_key( rsa_context *ctx, int nbits, int exponent )
61{
62 int ret;
63 mpi P1, Q1, H, G;
64
65 if( ctx->f_rng == NULL || nbits < 128 || exponent < 3 )
66 return( XYSSL_ERR_RSA_BAD_INPUT_DATA );
67
68 mpi_init( &P1, &Q1, &H, &G, NULL );
69
70 /*
71 * find primes P and Q with Q < P so that:
72 * GCD( E, (P-1)*(Q-1) ) == 1
73 */
74 MPI_CHK( mpi_lset( &ctx->E, exponent ) );
75
76 do
77 {
78 MPI_CHK( mpi_gen_prime( &ctx->P, ( nbits + 1 ) >> 1, 0,
79 ctx->f_rng, ctx->p_rng ) );
80
81 MPI_CHK( mpi_gen_prime( &ctx->Q, ( nbits + 1 ) >> 1, 0,
82 ctx->f_rng, ctx->p_rng ) );
83
84 if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 )
85 mpi_swap( &ctx->P, &ctx->Q );
86
87 if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 )
88 continue;
89
90 MPI_CHK( mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) );
91 if( mpi_msb( &ctx->N ) != nbits )
92 continue;
93
94 MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) );
95 MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) );
96 MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) );
97 MPI_CHK( mpi_gcd( &G, &ctx->E, &H ) );
98 }
99 while( mpi_cmp_int( &G, 1 ) != 0 );
100
101 /*
102 * D = E^-1 mod ((P-1)*(Q-1))
103 * DP = D mod (P - 1)
104 * DQ = D mod (Q - 1)
105 * QP = Q^-1 mod P
106 */
107 MPI_CHK( mpi_inv_mod( &ctx->D , &ctx->E, &H ) );
108 MPI_CHK( mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) );
109 MPI_CHK( mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) );
110 MPI_CHK( mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) );
111
112 ctx->len = ( mpi_msb( &ctx->N ) + 7 ) >> 3;
113
114cleanup:
115
116 mpi_free( &G, &H, &Q1, &P1, NULL );
117
118 if( ret != 0 )
119 {
120 rsa_free( ctx );
121 return( XYSSL_ERR_RSA_KEY_GEN_FAILED | ret );
122 }
123
124 return( 0 );
125}
126
127#endif
128
129/*
130 * Check a public RSA key
131 */
132int rsa_check_pubkey( rsa_context *ctx )
133{
134 if( ( ctx->N.p[0] & 1 ) == 0 ||
135 ( ctx->E.p[0] & 1 ) == 0 )
136 return( XYSSL_ERR_RSA_KEY_CHECK_FAILED );
137
138 if( mpi_msb( &ctx->N ) < 128 ||
139 mpi_msb( &ctx->N ) > 4096 )
140 return( XYSSL_ERR_RSA_KEY_CHECK_FAILED );
141
142 if( mpi_msb( &ctx->E ) < 2 ||
143 mpi_msb( &ctx->E ) > 64 )
144 return( XYSSL_ERR_RSA_KEY_CHECK_FAILED );
145
146 return( 0 );
147}
148
149/*
150 * Check a private RSA key
151 */
152int rsa_check_privkey( rsa_context *ctx )
153{
154 int ret;
155 mpi PQ, DE, P1, Q1, H, I, G;
156
157 if( ( ret = rsa_check_pubkey( ctx ) ) != 0 )
158 return( ret );
159
160 mpi_init( &PQ, &DE, &P1, &Q1, &H, &I, &G, NULL );
161
162 MPI_CHK( mpi_mul_mpi( &PQ, &ctx->P, &ctx->Q ) );
163 MPI_CHK( mpi_mul_mpi( &DE, &ctx->D, &ctx->E ) );
164 MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) );
165 MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) );
166 MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) );
167 MPI_CHK( mpi_mod_mpi( &I, &DE, &H ) );
168 MPI_CHK( mpi_gcd( &G, &ctx->E, &H ) );
169
170 if( mpi_cmp_mpi( &PQ, &ctx->N ) == 0 &&
171 mpi_cmp_int( &I, 1 ) == 0 &&
172 mpi_cmp_int( &G, 1 ) == 0 )
173 {
174 mpi_free( &G, &I, &H, &Q1, &P1, &DE, &PQ, NULL );
175 return( 0 );
176 }
177
178cleanup:
179
180 mpi_free( &G, &I, &H, &Q1, &P1, &DE, &PQ, NULL );
181 return( XYSSL_ERR_RSA_KEY_CHECK_FAILED | ret );
182}
183
184/*
185 * Do an RSA public key operation
186 */
187int rsa_public( rsa_context *ctx,
188 unsigned char *input,
189 unsigned char *output )
190{
191 int ret, olen;
192 mpi T;
193
194 mpi_init( &T, NULL );
195
196 MPI_CHK( mpi_read_binary( &T, input, ctx->len ) );
197
198 if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
199 {
200 mpi_free( &T, NULL );
201 return( XYSSL_ERR_RSA_BAD_INPUT_DATA );
202 }
203
204 olen = ctx->len;
205 MPI_CHK( mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) );
206 MPI_CHK( mpi_write_binary( &T, output, olen ) );
207
208cleanup:
209
210 mpi_free( &T, NULL );
211
212 if( ret != 0 )
213 return( XYSSL_ERR_RSA_PUBLIC_FAILED | ret );
214
215 return( 0 );
216}
217
218/*
219 * Do an RSA private key operation
220 */
221int rsa_private( rsa_context *ctx,
222 unsigned char *input,
223 unsigned char *output )
224{
225 int ret, olen;
226 mpi T, T1, T2;
227
228 mpi_init( &T, &T1, &T2, NULL );
229
230 MPI_CHK( mpi_read_binary( &T, input, ctx->len ) );
231
232 if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
233 {
234 mpi_free( &T, NULL );
235 return( XYSSL_ERR_RSA_BAD_INPUT_DATA );
236 }
237
238#if 0
239 MPI_CHK( mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) );
240#else
241 /*
242 * faster decryption using the CRT
243 *
244 * T1 = input ^ dP mod P
245 * T2 = input ^ dQ mod Q
246 */
247 MPI_CHK( mpi_exp_mod( &T1, &T, &ctx->DP, &ctx->P, &ctx->RP ) );
248 MPI_CHK( mpi_exp_mod( &T2, &T, &ctx->DQ, &ctx->Q, &ctx->RQ ) );
249
250 /*
251 * T = (T1 - T2) * (Q^-1 mod P) mod P
252 */
253 MPI_CHK( mpi_sub_mpi( &T, &T1, &T2 ) );
254 MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->QP ) );
255 MPI_CHK( mpi_mod_mpi( &T, &T1, &ctx->P ) );
256
257 /*
258 * output = T2 + T * Q
259 */
260 MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->Q ) );
261 MPI_CHK( mpi_add_mpi( &T, &T2, &T1 ) );
262#endif
263
264 olen = ctx->len;
265 MPI_CHK( mpi_write_binary( &T, output, olen ) );
266
267cleanup:
268
269 mpi_free( &T, &T1, &T2, NULL );
270
271 if( ret != 0 )
272 return( XYSSL_ERR_RSA_PRIVATE_FAILED | ret );
273
274 return( 0 );
275}
276
277/*
278 * Add the message padding, then do an RSA operation
279 */
280int rsa_pkcs1_encrypt( rsa_context *ctx,
281 int mode, int ilen,
282 unsigned char *input,
283 unsigned char *output )
284{
285 int nb_pad, olen;
286 unsigned char *p = output;
287
288 olen = ctx->len;
289
290 switch( ctx->padding )
291 {
292 case RSA_PKCS_V15:
293
294 if( ilen < 0 || olen < ilen + 11 )
295 return( XYSSL_ERR_RSA_BAD_INPUT_DATA );
296
297 nb_pad = olen - 3 - ilen;
298
299 *p++ = 0;
300 *p++ = RSA_CRYPT;
301
302 while( nb_pad-- > 0 )
303 {
304 do {
305 *p = (unsigned char) rand();
306 } while( *p == 0 );
307 p++;
308 }
309 *p++ = 0;
310 memcpy( p, input, ilen );
311 break;
312
313 default:
314
315 return( XYSSL_ERR_RSA_INVALID_PADDING );
316 }
317
318 return( ( mode == RSA_PUBLIC )
319 ? rsa_public( ctx, output, output )
320 : rsa_private( ctx, output, output ) );
321}
322
323/*
324 * Do an RSA operation, then remove the message padding
325 */
326int rsa_pkcs1_decrypt( rsa_context *ctx,
327 int mode, int *olen,
328 unsigned char *input,
329 unsigned char *output )
330{
331 int ret, ilen;
332 unsigned char *p;
333 unsigned char buf[512];
334
335 ilen = ctx->len;
336
337 if( ilen < 16 || ilen > (int) sizeof( buf ) )
338 return( XYSSL_ERR_RSA_BAD_INPUT_DATA );
339
340 ret = ( mode == RSA_PUBLIC )
341 ? rsa_public( ctx, input, buf )
342 : rsa_private( ctx, input, buf );
343
344 if( ret != 0 )
345 return( ret );
346
347 p = buf;
348
349 switch( ctx->padding )
350 {
351 case RSA_PKCS_V15:
352
353 if( *p++ != 0 || *p++ != RSA_CRYPT )
354 return( XYSSL_ERR_RSA_INVALID_PADDING );
355
356 while( *p != 0 )
357 {
358 if( p >= buf + ilen - 1 )
359 return( XYSSL_ERR_RSA_INVALID_PADDING );
360 p++;
361 }
362 p++;
363 break;
364
365 default:
366
367 return( XYSSL_ERR_RSA_INVALID_PADDING );
368 }
369
370 *olen = ilen - (int)(p - buf);
371 memcpy( output, p, *olen );
372
373 return( 0 );
374}
375
376/*
377 * Do an RSA operation to sign the message digest
378 */
379int rsa_pkcs1_sign( rsa_context *ctx,
380 int mode,
381 int hash_id,
382 int hashlen,
383 unsigned char *hash,
384 unsigned char *sig )
385{
386 int nb_pad, olen;
387 unsigned char *p = sig;
388
389 olen = ctx->len;
390
391 switch( ctx->padding )
392 {
393 case RSA_PKCS_V15:
394
395 switch( hash_id )
396 {
397 case RSA_RAW:
398 nb_pad = olen - 3 - hashlen;
399 break;
400
401 case RSA_MD2:
402 case RSA_MD4:
403 case RSA_MD5:
404 nb_pad = olen - 3 - 34;
405 break;
406
407 case RSA_SHA1:
408 nb_pad = olen - 3 - 35;
409 break;
410
411 default:
412 return( XYSSL_ERR_RSA_BAD_INPUT_DATA );
413 }
414
415 if( nb_pad < 8 )
416 return( XYSSL_ERR_RSA_BAD_INPUT_DATA );
417
418 *p++ = 0;
419 *p++ = RSA_SIGN;
420 memset( p, 0xFF, nb_pad );
421 p += nb_pad;
422 *p++ = 0;
423 break;
424
425 default:
426
427 return( XYSSL_ERR_RSA_INVALID_PADDING );
428 }
429
430 switch( hash_id )
431 {
432 case RSA_RAW:
433 memcpy( p, hash, hashlen );
434 break;
435
436 case RSA_MD2:
437 memcpy( p, ASN1_HASH_MDX, 18 );
438 memcpy( p + 18, hash, 16 );
439 p[13] = 2; break;
440
441 case RSA_MD4:
442 memcpy( p, ASN1_HASH_MDX, 18 );
443 memcpy( p + 18, hash, 16 );
444 p[13] = 4; break;
445
446 case RSA_MD5:
447 memcpy( p, ASN1_HASH_MDX, 18 );
448 memcpy( p + 18, hash, 16 );
449 p[13] = 5; break;
450
451 case RSA_SHA1:
452 memcpy( p, ASN1_HASH_SHA1, 15 );
453 memcpy( p + 15, hash, 20 );
454 break;
455
456 default:
457 return( XYSSL_ERR_RSA_BAD_INPUT_DATA );
458 }
459
460 return( ( mode == RSA_PUBLIC )
461 ? rsa_public( ctx, sig, sig )
462 : rsa_private( ctx, sig, sig ) );
463}
464
465/*
466 * Do an RSA operation and check the message digest
467 */
468int rsa_pkcs1_verify( rsa_context *ctx,
469 int mode,
470 int hash_id,
471 int hashlen,
472 unsigned char *hash,
473 unsigned char *sig )
474{
475 int ret, len, siglen;
476 unsigned char *p, c;
477 unsigned char buf[512];
478
479 siglen = ctx->len;
480
481 if( siglen < 16 || siglen > (int) sizeof( buf ) )
482 return( XYSSL_ERR_RSA_BAD_INPUT_DATA );
483
484 ret = ( mode == RSA_PUBLIC )
485 ? rsa_public( ctx, sig, buf )
486 : rsa_private( ctx, sig, buf );
487
488 if( ret != 0 )
489 return( ret );
490
491 p = buf;
492
493 switch( ctx->padding )
494 {
495 case RSA_PKCS_V15:
496
497 if( *p++ != 0 || *p++ != RSA_SIGN )
498 return( XYSSL_ERR_RSA_INVALID_PADDING );
499
500 while( *p != 0 )
501 {
502 if( p >= buf + siglen - 1 || *p != 0xFF )
503 return( XYSSL_ERR_RSA_INVALID_PADDING );
504 p++;
505 }
506 p++;
507 break;
508
509 default:
510
511 return( XYSSL_ERR_RSA_INVALID_PADDING );
512 }
513
514 len = siglen - (int)( p - buf );
515
516 if( len == 34 )
517 {
518 c = p[13];
519 p[13] = 0;
520
521 if( memcmp( p, ASN1_HASH_MDX, 18 ) != 0 )
522 return( XYSSL_ERR_RSA_VERIFY_FAILED );
523
524 if( ( c == 2 && hash_id == RSA_MD2 ) ||
525 ( c == 4 && hash_id == RSA_MD4 ) ||
526 ( c == 5 && hash_id == RSA_MD5 ) )
527 {
528 if( memcmp( p + 18, hash, 16 ) == 0 )
529 return( 0 );
530 else
531 return( XYSSL_ERR_RSA_VERIFY_FAILED );
532 }
533 }
534
535 if( len == 35 && hash_id == RSA_SHA1 )
536 {
537 if( memcmp( p, ASN1_HASH_SHA1, 15 ) == 0 &&
538 memcmp( p + 15, hash, 20 ) == 0 )
539 return( 0 );
540 else
541 return( XYSSL_ERR_RSA_VERIFY_FAILED );
542 }
543
544 if( len == hashlen && hash_id == RSA_RAW )
545 {
546 if( memcmp( p, hash, hashlen ) == 0 )
547 return( 0 );
548 else
549 return( XYSSL_ERR_RSA_VERIFY_FAILED );
550 }
551
552 return( XYSSL_ERR_RSA_INVALID_PADDING );
553}
554
555/*
556 * Free the components of an RSA key
557 */
558void rsa_free( rsa_context *ctx )
559{
560 mpi_free( &ctx->RQ, &ctx->RP, &ctx->RN,
561 &ctx->QP, &ctx->DQ, &ctx->DP,
562 &ctx->Q, &ctx->P, &ctx->D,
563 &ctx->E, &ctx->N, NULL );
564}
565
566#if defined(XYSSL_SELF_TEST)
567
568#include "xyssl/sha1.h"
569
570/*
571 * Example RSA-1024 keypair, for test purposes
572 */
573#define KEY_LEN 128
574
575#define RSA_N "9292758453063D803DD603D5E777D788" \
576 "8ED1D5BF35786190FA2F23EBC0848AEA" \
577 "DDA92CA6C3D80B32C4D109BE0F36D6AE" \
578 "7130B9CED7ACDF54CFC7555AC14EEBAB" \
579 "93A89813FBF3C4F8066D2D800F7C38A8" \
580 "1AE31942917403FF4946B0A83D3D3E05" \
581 "EE57C6F5F5606FB5D4BC6CD34EE0801A" \
582 "5E94BB77B07507233A0BC7BAC8F90F79"
583
584#define RSA_E "10001"
585
586#define RSA_D "24BF6185468786FDD303083D25E64EFC" \
587 "66CA472BC44D253102F8B4A9D3BFA750" \
588 "91386C0077937FE33FA3252D28855837" \
589 "AE1B484A8A9A45F7EE8C0C634F99E8CD" \
590 "DF79C5CE07EE72C7F123142198164234" \
591 "CABB724CF78B8173B9F880FC86322407" \
592 "AF1FEDFDDE2BEB674CA15F3E81A1521E" \
593 "071513A1E85B5DFA031F21ECAE91A34D"
594
595#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \
596 "2C01CAD19EA484A87EA4377637E75500" \
597 "FCB2005C5C7DD6EC4AC023CDA285D796" \
598 "C3D9E75E1EFC42488BB4F1D13AC30A57"
599
600#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \
601 "E211C2B9E5DB1ED0BF61D0D9899620F4" \
602 "910E4168387E3C30AA1E00C339A79508" \
603 "8452DD96A9A5EA5D9DCA68DA636032AF"
604
605#define RSA_DP "C1ACF567564274FB07A0BBAD5D26E298" \
606 "3C94D22288ACD763FD8E5600ED4A702D" \
607 "F84198A5F06C2E72236AE490C93F07F8" \
608 "3CC559CD27BC2D1CA488811730BB5725"
609
610#define RSA_DQ "4959CBF6F8FEF750AEE6977C155579C7" \
611 "D8AAEA56749EA28623272E4F7D0592AF" \
612 "7C1F1313CAC9471B5C523BFE592F517B" \
613 "407A1BD76C164B93DA2D32A383E58357"
614
615#define RSA_QP "9AE7FBC99546432DF71896FC239EADAE" \
616 "F38D18D2B2F0E2DD275AA977E2BF4411" \
617 "F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \
618 "A74206CEC169D74BF5A8C50D6F48EA08"
619
620#define PT_LEN 24
621#define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \
622 "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD"
623
624/*
625 * Checkup routine
626 */
627int rsa_self_test( int verbose )
628{
629 int len;
630 rsa_context rsa;
631 unsigned char sha1sum[20];
632 unsigned char rsa_plaintext[PT_LEN];
633 unsigned char rsa_decrypted[PT_LEN];
634 unsigned char rsa_ciphertext[KEY_LEN];
635
636 memset( &rsa, 0, sizeof( rsa_context ) );
637
638 rsa.len = KEY_LEN;
639 mpi_read_string( &rsa.N , 16, RSA_N );
640 mpi_read_string( &rsa.E , 16, RSA_E );
641 mpi_read_string( &rsa.D , 16, RSA_D );
642 mpi_read_string( &rsa.P , 16, RSA_P );
643 mpi_read_string( &rsa.Q , 16, RSA_Q );
644 mpi_read_string( &rsa.DP, 16, RSA_DP );
645 mpi_read_string( &rsa.DQ, 16, RSA_DQ );
646 mpi_read_string( &rsa.QP, 16, RSA_QP );
647
648 if( verbose != 0 )
649 printf( " RSA key validation: " );
650
651 if( rsa_check_pubkey( &rsa ) != 0 ||
652 rsa_check_privkey( &rsa ) != 0 )
653 {
654 if( verbose != 0 )
655 printf( "failed\n" );
656
657 return( 1 );
658 }
659
660 if( verbose != 0 )
661 printf( "passed\n PKCS#1 encryption : " );
662
663 memcpy( rsa_plaintext, RSA_PT, PT_LEN );
664
665 if( rsa_pkcs1_encrypt( &rsa, RSA_PUBLIC, PT_LEN,
666 rsa_plaintext, rsa_ciphertext ) != 0 )
667 {
668 if( verbose != 0 )
669 printf( "failed\n" );
670
671 return( 1 );
672 }
673
674 if( verbose != 0 )
675 printf( "passed\n PKCS#1 decryption : " );
676
677 if( rsa_pkcs1_decrypt( &rsa, RSA_PRIVATE, &len,
678 rsa_ciphertext, rsa_decrypted ) != 0 )
679 {
680 if( verbose != 0 )
681 printf( "failed\n" );
682
683 return( 1 );
684 }
685
686 if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 )
687 {
688 if( verbose != 0 )
689 printf( "failed\n" );
690
691 return( 1 );
692 }
693
694 if( verbose != 0 )
695 printf( "passed\n PKCS#1 data sign : " );
696
697 sha1( rsa_plaintext, PT_LEN, sha1sum );
698
699 if( rsa_pkcs1_sign( &rsa, RSA_PRIVATE, RSA_SHA1, 20,
700 sha1sum, rsa_ciphertext ) != 0 )
701 {
702 if( verbose != 0 )
703 printf( "failed\n" );
704
705 return( 1 );
706 }
707
708 if( verbose != 0 )
709 printf( "passed\n PKCS#1 sig. verify: " );
710
711 if( rsa_pkcs1_verify( &rsa, RSA_PUBLIC, RSA_SHA1, 20,
712 sha1sum, rsa_ciphertext ) != 0 )
713 {
714 if( verbose != 0 )
715 printf( "failed\n" );
716
717 return( 1 );
718 }
719
720 if( verbose != 0 )
721 printf( "passed\n\n" );
722
723 rsa_free( &rsa );
724
725 return( 0 );
726}
727
728#endif
729
730#endif