Implemented transient-key flag as requested by the GNUNet folks.
[libgcrypt.git] / cipher / rsa.c
1 /* rsa.c  -  RSA function
2  * Copyright (C) 1997, 1998, 1999 by Werner Koch (dd9jn)
3  * Copyright (C) 2000, 2001, 2002, 2003, 2008 Free Software Foundation, Inc.
4  *
5  * This file is part of Libgcrypt.
6  *
7  * Libgcrypt is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * Libgcrypt is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 /* This code uses an algorithm protected by U.S. Patent #4,405,829
22    which expired on September 20, 2000.  The patent holder placed that
23    patent into the public domain on Sep 6th, 2000.
24 */
25
26 #include <config.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <errno.h>
31
32 #include "g10lib.h"
33 #include "mpi.h"
34 #include "cipher.h"
35
36
37 typedef struct
38 {
39   gcry_mpi_t n;     /* modulus */
40   gcry_mpi_t e;     /* exponent */
41 } RSA_public_key;
42
43
44 typedef struct
45 {
46   gcry_mpi_t n;     /* public modulus */
47   gcry_mpi_t e;     /* public exponent */
48   gcry_mpi_t d;     /* exponent */
49   gcry_mpi_t p;     /* prime  p. */
50   gcry_mpi_t q;     /* prime  q. */
51   gcry_mpi_t u;     /* inverse of p mod q. */
52 } RSA_secret_key;
53
54
55 static void test_keys (RSA_secret_key *sk, unsigned nbits);
56 static gpg_err_code_t generate (RSA_secret_key *sk,
57                                 unsigned int nbits, unsigned long use_e,
58                                 int transient_key);
59 static int  check_secret_key (RSA_secret_key *sk);
60 static void public (gcry_mpi_t output, gcry_mpi_t input, RSA_public_key *skey);
61 static void secret (gcry_mpi_t output, gcry_mpi_t input, RSA_secret_key *skey);
62
63
64 static void
65 test_keys( RSA_secret_key *sk, unsigned nbits )
66 {
67   RSA_public_key pk;
68   gcry_mpi_t test = gcry_mpi_new ( nbits );
69   gcry_mpi_t out1 = gcry_mpi_new ( nbits );
70   gcry_mpi_t out2 = gcry_mpi_new ( nbits );
71
72   pk.n = sk->n;
73   pk.e = sk->e;
74   gcry_mpi_randomize( test, nbits, GCRY_WEAK_RANDOM );
75
76   public( out1, test, &pk );
77   secret( out2, out1, sk );
78   if( mpi_cmp( test, out2 ) )
79     log_fatal("RSA operation: public, secret failed\n");
80   secret( out1, test, sk );
81   public( out2, out1, &pk );
82   if( mpi_cmp( test, out2 ) )
83     log_fatal("RSA operation: secret, public failed\n");
84   gcry_mpi_release ( test );
85   gcry_mpi_release ( out1 );
86   gcry_mpi_release ( out2 );
87 }
88
89
90 /* Callback used by the prime generation to test whether the exponent
91    is suitable. Returns 0 if the test has been passed. */
92 static int
93 check_exponent (void *arg, gcry_mpi_t a)
94 {
95   gcry_mpi_t e = arg;
96   gcry_mpi_t tmp;
97   int result;
98   
99   mpi_sub_ui (a, a, 1);
100   tmp = _gcry_mpi_alloc_like (a);
101   result = !gcry_mpi_gcd(tmp, e, a); /* GCD is not 1. */
102   gcry_mpi_release (tmp);
103   mpi_add_ui (a, a, 1);
104   return result;
105 }
106
107 /****************
108  * Generate a key pair with a key of size NBITS.  
109  * USE_E = 0 let Libcgrypt decide what exponent to use.
110  *       = 1 request the use of a "secure" exponent; this is required by some 
111  *           specification to be 65537.
112  *       > 2 Try starting at this value until a working exponent is found.
113  * TRANSIENT_KEY:  If true, generate the primes using the standard RNG.
114  * Returns: 2 structures filled with all needed values
115  */
116 static gpg_err_code_t
117 generate (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e,
118           int transient_key)
119 {
120   gcry_mpi_t p, q; /* the two primes */
121   gcry_mpi_t d;    /* the private key */
122   gcry_mpi_t u;
123   gcry_mpi_t t1, t2;
124   gcry_mpi_t n;    /* the public key */
125   gcry_mpi_t e;    /* the exponent */
126   gcry_mpi_t phi;  /* helper: (p-1)(q-1) */
127   gcry_mpi_t g;
128   gcry_mpi_t f;
129   gcry_random_level_t random_level;
130
131   if (fips_mode ())
132   {
133     if (nbits < 1024)
134       return GPG_ERR_INV_VALUE;
135     if (transient_key)
136       return GPG_ERR_INV_VALUE;
137   }
138
139   /* The random quality depends on the transient_key flag.  */
140   random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM;
141
142   /* Make sure that nbits is even so that we generate p, q of equal size. */
143   if ( (nbits&1) )
144     nbits++; 
145
146   if (use_e == 1)   /* Alias for a secure value. */
147     use_e = 65537;  /* as demanded by Spinx. */
148
149   /* Public exponent:
150      In general we use 41 as this is quite fast and more secure than the
151      commonly used 17.  Benchmarking the RSA verify function
152      with a 1024 bit key yields (2001-11-08): 
153      e=17    0.54 ms
154      e=41    0.75 ms
155      e=257   0.95 ms
156      e=65537 1.80 ms
157   */
158   e = mpi_alloc( (32+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB );
159   if (!use_e)
160     mpi_set_ui (e, 41);     /* This is a reasonable secure and fast value */
161   else 
162     {
163       use_e |= 1; /* make sure this is odd */
164       mpi_set_ui (e, use_e); 
165     }
166     
167   n = gcry_mpi_new (nbits);
168
169   p = q = NULL;
170   do
171     {
172       /* select two (very secret) primes */
173       if (p)
174         gcry_mpi_release (p);
175       if (q)
176         gcry_mpi_release (q);
177       if (use_e)
178         { /* Do an extra test to ensure that the given exponent is
179              suitable. */
180           p = _gcry_generate_secret_prime (nbits/2, random_level,
181                                            check_exponent, e);
182           q = _gcry_generate_secret_prime (nbits/2, random_level,
183                                            check_exponent, e);
184         }
185       else
186         { /* We check the exponent later. */
187           p = _gcry_generate_secret_prime (nbits/2, random_level, NULL, NULL);
188           q = _gcry_generate_secret_prime (nbits/2, random_level, NULL, NULL);
189         }
190       if (mpi_cmp (p, q) > 0 ) /* p shall be smaller than q (for calc of u)*/
191         mpi_swap(p,q);
192       /* calculate the modulus */
193       mpi_mul( n, p, q );
194     }
195   while ( mpi_get_nbits(n) != nbits );
196
197   /* calculate Euler totient: phi = (p-1)(q-1) */
198   t1 = mpi_alloc_secure( mpi_get_nlimbs(p) );
199   t2 = mpi_alloc_secure( mpi_get_nlimbs(p) );
200   phi = gcry_mpi_snew ( nbits );
201   g     = gcry_mpi_snew ( nbits );
202   f     = gcry_mpi_snew ( nbits );
203   mpi_sub_ui( t1, p, 1 );
204   mpi_sub_ui( t2, q, 1 );
205   mpi_mul( phi, t1, t2 );
206   gcry_mpi_gcd(g, t1, t2);
207   mpi_fdiv_q(f, phi, g);
208
209   while (!gcry_mpi_gcd(t1, e, phi)) /* (while gcd is not 1) */
210     {
211       if (use_e)
212         BUG (); /* The prime generator already made sure that we
213                    never can get to here. */
214       mpi_add_ui (e, e, 2);
215     }
216
217   /* calculate the secret key d = e^1 mod phi */
218   d = gcry_mpi_snew ( nbits );
219   mpi_invm(d, e, f );
220   /* calculate the inverse of p and q (used for chinese remainder theorem)*/
221   u = gcry_mpi_snew ( nbits );
222   mpi_invm(u, p, q );
223
224   if( DBG_CIPHER )
225     {
226       log_mpidump("  p= ", p );
227       log_mpidump("  q= ", q );
228       log_mpidump("phi= ", phi );
229       log_mpidump("  g= ", g );
230       log_mpidump("  f= ", f );
231       log_mpidump("  n= ", n );
232       log_mpidump("  e= ", e );
233       log_mpidump("  d= ", d );
234       log_mpidump("  u= ", u );
235     }
236
237   gcry_mpi_release (t1);
238   gcry_mpi_release (t2);
239   gcry_mpi_release (phi);
240   gcry_mpi_release (f);
241   gcry_mpi_release (g);
242
243   sk->n = n;
244   sk->e = e;
245   sk->p = p;
246   sk->q = q;
247   sk->d = d;
248   sk->u = u;
249
250   /* now we can test our keys (this should never fail!) */
251   test_keys( sk, nbits - 64 );
252
253   return 0;
254 }
255
256
257 /****************
258  * Test wether the secret key is valid.
259  * Returns: true if this is a valid key.
260  */
261 static int
262 check_secret_key( RSA_secret_key *sk )
263 {
264   int rc;
265   gcry_mpi_t temp = mpi_alloc( mpi_get_nlimbs(sk->p)*2 );
266   
267   mpi_mul(temp, sk->p, sk->q );
268   rc = mpi_cmp( temp, sk->n );
269   mpi_free(temp);
270   return !rc;
271 }
272
273
274
275 /****************
276  * Public key operation. Encrypt INPUT with PKEY and put result into OUTPUT.
277  *
278  *      c = m^e mod n
279  *
280  * Where c is OUTPUT, m is INPUT and e,n are elements of PKEY.
281  */
282 static void
283 public(gcry_mpi_t output, gcry_mpi_t input, RSA_public_key *pkey )
284 {
285   if( output == input )  /* powm doesn't like output and input the same */
286     {
287       gcry_mpi_t x = mpi_alloc( mpi_get_nlimbs(input)*2 );
288       mpi_powm( x, input, pkey->e, pkey->n );
289       mpi_set(output, x);
290       mpi_free(x);
291     }
292   else
293     mpi_powm( output, input, pkey->e, pkey->n );
294 }
295
296 #if 0
297 static void
298 stronger_key_check ( RSA_secret_key *skey )
299 {
300   gcry_mpi_t t = mpi_alloc_secure ( 0 );
301   gcry_mpi_t t1 = mpi_alloc_secure ( 0 );
302   gcry_mpi_t t2 = mpi_alloc_secure ( 0 );
303   gcry_mpi_t phi = mpi_alloc_secure ( 0 );
304
305   /* check that n == p * q */
306   mpi_mul( t, skey->p, skey->q);
307   if (mpi_cmp( t, skey->n) )
308     log_info ( "RSA Oops: n != p * q\n" );
309
310   /* check that p is less than q */
311   if( mpi_cmp( skey->p, skey->q ) > 0 )
312     {
313       log_info ("RSA Oops: p >= q - fixed\n");
314       _gcry_mpi_swap ( skey->p, skey->q);
315     }
316
317     /* check that e divides neither p-1 nor q-1 */
318     mpi_sub_ui(t, skey->p, 1 );
319     mpi_fdiv_r(t, t, skey->e );
320     if ( !mpi_cmp_ui( t, 0) )
321         log_info ( "RSA Oops: e divides p-1\n" );
322     mpi_sub_ui(t, skey->q, 1 );
323     mpi_fdiv_r(t, t, skey->e );
324     if ( !mpi_cmp_ui( t, 0) )
325         log_info ( "RSA Oops: e divides q-1\n" );
326
327     /* check that d is correct */
328     mpi_sub_ui( t1, skey->p, 1 );
329     mpi_sub_ui( t2, skey->q, 1 );
330     mpi_mul( phi, t1, t2 );
331     gcry_mpi_gcd(t, t1, t2);
332     mpi_fdiv_q(t, phi, t);
333     mpi_invm(t, skey->e, t );
334     if ( mpi_cmp(t, skey->d ) )
335       {
336         log_info ( "RSA Oops: d is wrong - fixed\n");
337         mpi_set (skey->d, t);
338         _gcry_log_mpidump ("  fixed d", skey->d);
339       }
340
341     /* check for correctness of u */
342     mpi_invm(t, skey->p, skey->q );
343     if ( mpi_cmp(t, skey->u ) )
344       {
345         log_info ( "RSA Oops: u is wrong - fixed\n");
346         mpi_set (skey->u, t);
347         _gcry_log_mpidump ("  fixed u", skey->u);
348       }
349
350     log_info ( "RSA secret key check finished\n");
351
352     mpi_free (t);
353     mpi_free (t1);
354     mpi_free (t2);
355     mpi_free (phi);
356 }
357 #endif
358
359
360
361 /****************
362  * Secret key operation. Encrypt INPUT with SKEY and put result into OUTPUT.
363  *
364  *      m = c^d mod n
365  *
366  * Or faster:
367  *
368  *      m1 = c ^ (d mod (p-1)) mod p 
369  *      m2 = c ^ (d mod (q-1)) mod q 
370  *      h = u * (m2 - m1) mod q 
371  *      m = m1 + h * p
372  *
373  * Where m is OUTPUT, c is INPUT and d,n,p,q,u are elements of SKEY.
374  */
375 static void
376 secret(gcry_mpi_t output, gcry_mpi_t input, RSA_secret_key *skey )
377 {
378   if (!skey->p || !skey->q || !skey->u)
379     {
380       mpi_powm (output, input, skey->d, skey->n);
381     }
382   else
383     {
384       gcry_mpi_t m1 = mpi_alloc_secure( mpi_get_nlimbs(skey->n)+1 );
385       gcry_mpi_t m2 = mpi_alloc_secure( mpi_get_nlimbs(skey->n)+1 );
386       gcry_mpi_t h  = mpi_alloc_secure( mpi_get_nlimbs(skey->n)+1 );
387       
388       /* m1 = c ^ (d mod (p-1)) mod p */
389       mpi_sub_ui( h, skey->p, 1  );
390       mpi_fdiv_r( h, skey->d, h );   
391       mpi_powm( m1, input, h, skey->p );
392       /* m2 = c ^ (d mod (q-1)) mod q */
393       mpi_sub_ui( h, skey->q, 1  );
394       mpi_fdiv_r( h, skey->d, h );
395       mpi_powm( m2, input, h, skey->q );
396       /* h = u * ( m2 - m1 ) mod q */
397       mpi_sub( h, m2, m1 );
398       if ( mpi_is_neg( h ) ) 
399         mpi_add ( h, h, skey->q );
400       mpi_mulm( h, skey->u, h, skey->q ); 
401       /* m = m2 + h * p */
402       mpi_mul ( h, h, skey->p );
403       mpi_add ( output, m1, h );
404     
405       mpi_free ( h );
406       mpi_free ( m1 );
407       mpi_free ( m2 );
408     }
409 }
410
411
412
413 /* Perform RSA blinding.  */
414 static gcry_mpi_t
415 rsa_blind (gcry_mpi_t x, gcry_mpi_t r, gcry_mpi_t e, gcry_mpi_t n)
416 {
417   /* A helper.  */
418   gcry_mpi_t a;
419
420   /* Result.  */
421   gcry_mpi_t y;
422
423   a = gcry_mpi_snew (gcry_mpi_get_nbits (n));
424   y = gcry_mpi_snew (gcry_mpi_get_nbits (n));
425   
426   /* Now we calculate: y = (x * r^e) mod n, where r is the random
427      number, e is the public exponent, x is the non-blinded data and n
428      is the RSA modulus.  */
429   gcry_mpi_powm (a, r, e, n);
430   gcry_mpi_mulm (y, a, x, n);
431
432   gcry_mpi_release (a);
433
434   return y;
435 }
436
437 /* Undo RSA blinding.  */
438 static gcry_mpi_t
439 rsa_unblind (gcry_mpi_t x, gcry_mpi_t ri, gcry_mpi_t n)
440 {
441   gcry_mpi_t y;
442
443   y = gcry_mpi_snew (gcry_mpi_get_nbits (n));
444
445   /* Here we calculate: y = (x * r^-1) mod n, where x is the blinded
446      decrypted data, ri is the modular multiplicative inverse of r and
447      n is the RSA modulus.  */
448
449   gcry_mpi_mulm (y, ri, x, n);
450
451   return y;
452 }
453
454 /*********************************************
455  **************  interface  ******************
456  *********************************************/
457
458 static gcry_err_code_t
459 rsa_generate (int algo, unsigned int nbits, unsigned long use_e,
460               unsigned int keygen_flags,
461               gcry_mpi_t *skey, gcry_mpi_t **retfactors)
462 {
463   RSA_secret_key sk;
464   gpg_err_code_t ec;
465   int i;
466
467   (void)algo;
468
469   ec = generate (&sk, nbits, use_e,
470                  !!(keygen_flags & PUBKEY_FLAG_TRANSIENT_KEY) );
471   if (!ec)
472     {
473       skey[0] = sk.n;
474       skey[1] = sk.e;
475       skey[2] = sk.d;
476       skey[3] = sk.p;
477       skey[4] = sk.q;
478       skey[5] = sk.u;
479   
480       /* Make an empty list of factors.  */
481       *retfactors = gcry_calloc ( 1, sizeof **retfactors );
482       if (!*retfactors)
483         {
484           ec = gpg_err_code_from_syserror ();
485           for (i=0; i <= 5; i++)
486             {
487               gcry_mpi_release (skey[i]);
488               skey[i] = NULL;
489             }
490         }
491       else
492         ec = 0;
493     }
494   
495   return ec;
496 }
497
498
499 gcry_err_code_t
500 _gcry_rsa_generate (int algo, unsigned int nbits, unsigned long use_e,
501                     gcry_mpi_t *skey, gcry_mpi_t **retfactors)
502 {
503   return rsa_generate (algo, nbits, use_e, 0, skey, retfactors);
504 }
505
506
507 gcry_err_code_t
508 _gcry_rsa_check_secret_key( int algo, gcry_mpi_t *skey )
509 {
510   gcry_err_code_t err = GPG_ERR_NO_ERROR;
511   RSA_secret_key sk;
512
513   (void)algo;
514
515   sk.n = skey[0];
516   sk.e = skey[1];
517   sk.d = skey[2];
518   sk.p = skey[3];
519   sk.q = skey[4];
520   sk.u = skey[5];
521
522   if (!sk.p || !sk.q || !sk.u)
523     err = GPG_ERR_NO_OBJ;  /* To check the key we need the optional
524                               parameters. */
525   else if (!check_secret_key (&sk))
526     err = GPG_ERR_PUBKEY_ALGO;
527
528   return err;
529 }
530
531
532 gcry_err_code_t
533 _gcry_rsa_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data,
534                    gcry_mpi_t *pkey, int flags)
535 {
536   RSA_public_key pk;
537
538   (void)algo;
539   (void)flags;
540   
541   pk.n = pkey[0];
542   pk.e = pkey[1];
543   resarr[0] = mpi_alloc (mpi_get_nlimbs (pk.n));
544   public (resarr[0], data, &pk);
545   
546   return GPG_ERR_NO_ERROR;
547 }
548
549 gcry_err_code_t
550 _gcry_rsa_decrypt (int algo, gcry_mpi_t *result, gcry_mpi_t *data,
551                    gcry_mpi_t *skey, int flags)
552 {
553   RSA_secret_key sk;
554   gcry_mpi_t r = MPI_NULL;      /* Random number needed for blinding.  */
555   gcry_mpi_t ri = MPI_NULL;     /* Modular multiplicative inverse of
556                                    r.  */
557   gcry_mpi_t x = MPI_NULL;      /* Data to decrypt.  */
558   gcry_mpi_t y;                 /* Result.  */
559
560   (void)algo;
561
562   /* Extract private key.  */
563   sk.n = skey[0];
564   sk.e = skey[1];
565   sk.d = skey[2];
566   sk.p = skey[3]; /* Optional. */
567   sk.q = skey[4]; /* Optional. */
568   sk.u = skey[5]; /* Optional. */
569
570   y = gcry_mpi_snew (gcry_mpi_get_nbits (sk.n));
571
572   /* We use blinding by default to mitigate timing attacks which can
573      be practically mounted over the network as shown by Brumley and
574      Boney in 2003.  */ 
575   if (! (flags & PUBKEY_FLAG_NO_BLINDING))
576     {
577       /* Initialize blinding.  */
578       
579       /* First, we need a random number r between 0 and n - 1, which
580          is relatively prime to n (i.e. it is neither p nor q).  */
581       r = gcry_mpi_snew (gcry_mpi_get_nbits (sk.n));
582       ri = gcry_mpi_snew (gcry_mpi_get_nbits (sk.n));
583       
584       gcry_mpi_randomize (r, gcry_mpi_get_nbits (sk.n),
585                           GCRY_STRONG_RANDOM);
586       gcry_mpi_mod (r, r, sk.n);
587
588       /* Actually it should be okay to skip the check for equality
589          with either p or q here.  */
590
591       /* Calculate inverse of r.  */
592       if (! gcry_mpi_invm (ri, r, sk.n))
593         BUG ();
594     }
595
596   if (! (flags & PUBKEY_FLAG_NO_BLINDING))
597     x = rsa_blind (data[0], r, sk.e, sk.n);
598   else
599     x = data[0];
600
601   /* Do the encryption.  */
602   secret (y, x, &sk);
603
604   if (! (flags & PUBKEY_FLAG_NO_BLINDING))
605     {
606       /* Undo blinding.  */
607       gcry_mpi_t a = gcry_mpi_copy (y);
608       
609       gcry_mpi_release (y);
610       y = rsa_unblind (a, ri, sk.n);
611
612       gcry_mpi_release (a);
613     }
614
615   if (! (flags & PUBKEY_FLAG_NO_BLINDING))
616     {
617       /* Deallocate resources needed for blinding.  */
618       gcry_mpi_release (x);
619       gcry_mpi_release (r);
620       gcry_mpi_release (ri);
621     }
622
623   /* Copy out result.  */
624   *result = y;
625   
626   return GPG_ERR_NO_ERROR;
627 }
628
629 gcry_err_code_t
630 _gcry_rsa_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey)
631 {
632   RSA_secret_key sk;
633
634   (void)algo;
635   
636   sk.n = skey[0];
637   sk.e = skey[1];
638   sk.d = skey[2];
639   sk.p = skey[3];
640   sk.q = skey[4];
641   sk.u = skey[5];
642   resarr[0] = mpi_alloc( mpi_get_nlimbs (sk.n));
643   secret (resarr[0], data, &sk);
644
645   return GPG_ERR_NO_ERROR;
646 }
647
648 gcry_err_code_t
649 _gcry_rsa_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey,
650                   int (*cmp) (void *opaque, gcry_mpi_t tmp),
651                   void *opaquev)
652 {
653   RSA_public_key pk;
654   gcry_mpi_t result;
655   gcry_err_code_t rc;
656
657   (void)algo;
658   (void)cmp;
659   (void)opaquev;
660
661   pk.n = pkey[0];
662   pk.e = pkey[1];
663   result = gcry_mpi_new ( 160 );
664   public( result, data[0], &pk );
665 #ifdef IS_DEVELOPMENT_VERSION
666   if (DBG_CIPHER)
667     {
668       log_mpidump ("rsa verify result:", result );
669       log_mpidump ("             hash:", hash );
670     }
671 #endif /*IS_DEVELOPMENT_VERSION*/
672   /*rc = (*cmp)( opaquev, result );*/
673   rc = mpi_cmp (result, hash) ? GPG_ERR_BAD_SIGNATURE : GPG_ERR_NO_ERROR;
674   gcry_mpi_release (result);
675   
676   return rc;
677 }
678
679
680 unsigned int
681 _gcry_rsa_get_nbits (int algo, gcry_mpi_t *pkey)
682 {
683   (void)algo;
684
685   return mpi_get_nbits (pkey[0]);
686 }
687
688
689
690 \f
691 /* 
692      Self-test section.
693  */
694
695
696 static gpg_err_code_t
697 selftests_rsa (selftest_report_func_t report)
698 {
699   const char *what;
700   const char *errtxt;
701   
702   what = "low-level";
703   errtxt = NULL; /*selftest ();*/
704   if (errtxt)
705     goto failed;
706
707   /* FIXME:  need more tests.  */
708
709   return 0; /* Succeeded. */
710
711  failed:
712   if (report)
713     report ("pubkey", GCRY_PK_RSA, what, errtxt);
714   return GPG_ERR_SELFTEST_FAILED;
715 }
716
717
718 /* Run a full self-test for ALGO and return 0 on success.  */
719 static gpg_err_code_t
720 run_selftests (int algo, selftest_report_func_t report)
721 {
722   gpg_err_code_t ec;
723
724   switch (algo)
725     {
726     case GCRY_PK_RSA:
727       ec = selftests_rsa (report);
728       break;
729     default:
730       ec = GPG_ERR_PUBKEY_ALGO;
731       break;
732         
733     }
734   return ec;
735 }
736
737
738
739 \f
740 static const char *rsa_names[] =
741   {
742     "rsa",
743     "openpgp-rsa",
744     "oid.1.2.840.113549.1.1.1",
745     NULL,
746   };
747
748 gcry_pk_spec_t _gcry_pubkey_spec_rsa =
749   {
750     "RSA", rsa_names,
751     "ne", "nedpqu", "a", "s", "n",
752     GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR,
753     _gcry_rsa_generate,
754     _gcry_rsa_check_secret_key,
755     _gcry_rsa_encrypt,
756     _gcry_rsa_decrypt,
757     _gcry_rsa_sign,
758     _gcry_rsa_verify,
759     _gcry_rsa_get_nbits,
760   };
761 pk_extra_spec_t _gcry_pubkey_extraspec_rsa = 
762   {
763     run_selftests,
764     rsa_generate
765   };
766