Tizen 2.0 Release
[external/libgnutls26.git] / lib / gcrypt / pk.c
1 /*
2  * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2009, 2010
3  * Free Software Foundation, Inc.
4  *
5  * Author: Nikos Mavrogiannopoulos
6  *
7  * This file is part of GnuTLS.
8  *
9  * The GnuTLS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1 of
12  * the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22  * USA
23  *
24  */
25
26 /* This file contains the functions needed for RSA/DSA public key
27  * encryption and signatures. 
28  */
29
30 #include <gnutls_int.h>
31 #include <gnutls_mpi.h>
32 #include <gnutls_pk.h>
33 #include <gnutls_errors.h>
34 #include <gnutls_datum.h>
35 #include <gnutls_global.h>
36 #include <gnutls_num.h>
37 #include <x509/x509_int.h>
38 #include <x509/common.h>
39 #include <random.h>
40 #include <gnutls_pk.h>
41 #include <gcrypt.h>
42
43 /* this is based on code from old versions of libgcrypt (centuries ago)
44  */
45
46 int (*generate) (gnutls_pk_algorithm_t, unsigned int level /*bits */ ,
47                  gnutls_pk_params_st *);
48
49 static int
50 _wrap_gcry_pk_encrypt (gnutls_pk_algorithm_t algo,
51                        gnutls_datum_t * ciphertext,
52                        const gnutls_datum_t * plaintext,
53                        const gnutls_pk_params_st * pk_params)
54 {
55   gcry_sexp_t s_ciph = NULL, s_data = NULL, s_pkey = NULL;
56   int rc = -1;
57   int ret;
58   bigint_t data, res;
59   gcry_sexp_t list;
60
61   if (_gnutls_mpi_scan_nz (&data, plaintext->data, plaintext->size) != 0)
62     {
63       gnutls_assert ();
64       return GNUTLS_E_MPI_SCAN_FAILED;
65     }
66
67   /* make a sexp from pkey */
68   switch (algo)
69     {
70     case GNUTLS_PK_RSA:
71       if (pk_params->params_nr >= 2)
72         rc = gcry_sexp_build (&s_pkey, NULL,
73                               "(public-key(rsa(n%m)(e%m)))",
74                               pk_params->params[0], pk_params->params[1]);
75       break;
76
77     default:
78       gnutls_assert ();
79       ret = GNUTLS_E_INTERNAL_ERROR;
80       goto cleanup;
81     }
82
83   if (rc != 0)
84     {
85       gnutls_assert ();
86       ret = GNUTLS_E_INTERNAL_ERROR;
87       goto cleanup;
88     }
89
90   /* put the data into a simple list */
91   if (gcry_sexp_build (&s_data, NULL, "%m", data))
92     {
93       gnutls_assert ();
94       ret = GNUTLS_E_MEMORY_ERROR;
95       goto cleanup;
96     }
97
98   /* pass it to libgcrypt */
99   rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey);
100   if (rc != 0)
101     {
102       gnutls_assert ();
103       ret = GNUTLS_E_PK_ENCRYPTION_FAILED;
104       goto cleanup;
105     }
106
107   list = gcry_sexp_find_token (s_ciph, "a", 0);
108   if (list == NULL)
109     {
110       gnutls_assert ();
111       ret = GNUTLS_E_INTERNAL_ERROR;
112       goto cleanup;
113     }
114
115   res = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
116   gcry_sexp_release (list);
117   if (res == NULL)
118     {
119       gnutls_assert ();
120       ret = GNUTLS_E_INTERNAL_ERROR;
121       goto cleanup;
122     }
123
124   ret = _gnutls_mpi_dprint_size (res, ciphertext, plaintext->size);
125   _gnutls_mpi_release (&res);
126   if (ret < 0)
127     {
128       gnutls_assert ();
129       goto cleanup;
130     }
131
132   ret = 0;
133
134 cleanup:
135   _gnutls_mpi_release (&data);
136   if (s_ciph)
137     gcry_sexp_release (s_ciph);
138   if (s_data)
139     gcry_sexp_release (s_data);
140   if (s_pkey)
141     gcry_sexp_release (s_pkey);
142
143   return ret;
144 }
145
146 static int
147 _wrap_gcry_pk_decrypt (gnutls_pk_algorithm_t algo,
148                        gnutls_datum_t * plaintext,
149                        const gnutls_datum_t * ciphertext,
150                        const gnutls_pk_params_st * pk_params)
151 {
152   gcry_sexp_t s_plain = NULL, s_data = NULL, s_pkey = NULL;
153   int rc = -1;
154   int ret;
155   bigint_t data, res;
156
157   if (_gnutls_mpi_scan_nz (&data, ciphertext->data, ciphertext->size) != 0)
158     {
159       gnutls_assert ();
160       return GNUTLS_E_MPI_SCAN_FAILED;
161     }
162
163   /* make a sexp from pkey */
164   switch (algo)
165     {
166     case GNUTLS_PK_RSA:
167       if (pk_params->params_nr >= 6)
168         rc = gcry_sexp_build (&s_pkey, NULL,
169                               "(private-key(rsa((n%m)(e%m)(d%m)(p%m)(q%m)(u%m))))",
170                               pk_params->params[0], pk_params->params[1],
171                               pk_params->params[2], pk_params->params[3],
172                               pk_params->params[4], pk_params->params[5]);
173       break;
174
175     default:
176       gnutls_assert ();
177       ret = GNUTLS_E_INTERNAL_ERROR;
178       goto cleanup;
179     }
180
181   if (rc != 0)
182     {
183       gnutls_assert ();
184       ret = GNUTLS_E_INTERNAL_ERROR;
185       goto cleanup;
186     }
187
188   /* put the data into a simple list */
189   if (gcry_sexp_build (&s_data, NULL, "(enc-val(rsa(a%m)))", data))
190     {
191       gnutls_assert ();
192       ret = GNUTLS_E_INTERNAL_ERROR;
193       goto cleanup;
194     }
195
196   /* pass it to libgcrypt */
197   rc = gcry_pk_decrypt (&s_plain, s_data, s_pkey);
198   if (rc != 0)
199     {
200       gnutls_assert ();
201       ret = GNUTLS_E_PK_DECRYPTION_FAILED;
202       goto cleanup;
203     }
204
205   res = gcry_sexp_nth_mpi (s_plain, 0, GCRYMPI_FMT_USG);
206   if (res == NULL)
207     {
208       gnutls_assert ();
209       ret = GNUTLS_E_INTERNAL_ERROR;
210       goto cleanup;
211     }
212
213   ret = _gnutls_mpi_dprint_size (res, plaintext, ciphertext->size);
214   _gnutls_mpi_release (&res);
215   if (ret < 0)
216     {
217       gnutls_assert ();
218       goto cleanup;
219     }
220
221   ret = 0;
222
223 cleanup:
224   _gnutls_mpi_release (&data);
225   if (s_plain)
226     gcry_sexp_release (s_plain);
227   if (s_data)
228     gcry_sexp_release (s_data);
229   if (s_pkey)
230     gcry_sexp_release (s_pkey);
231
232   return ret;
233
234 }
235
236
237 /* in case of DSA puts into data, r,s
238  */
239 static int
240 _wrap_gcry_pk_sign (gnutls_pk_algorithm_t algo, gnutls_datum_t * signature,
241                     const gnutls_datum_t * vdata,
242                     const gnutls_pk_params_st * pk_params)
243 {
244   gcry_sexp_t s_hash = NULL, s_key = NULL, s_sig = NULL;
245   gcry_sexp_t list = NULL;
246   int rc = -1, ret;
247   bigint_t hash;
248   bigint_t res[2] = { NULL, NULL };
249
250   if (_gnutls_mpi_scan_nz (&hash, vdata->data, vdata->size) != 0)
251     {
252       gnutls_assert ();
253       return GNUTLS_E_MPI_SCAN_FAILED;
254     }
255
256   /* make a sexp from pkey */
257   switch (algo)
258     {
259     case GNUTLS_PK_DSA:
260       if (pk_params->params_nr >= 5)
261         rc = gcry_sexp_build (&s_key, NULL,
262                               "(private-key(dsa(p%m)(q%m)(g%m)(y%m)(x%m)))",
263                               pk_params->params[0], pk_params->params[1],
264                               pk_params->params[2], pk_params->params[3],
265                               pk_params->params[4]);
266       else
267         {
268           gnutls_assert ();
269         }
270
271       break;
272     case GNUTLS_PK_RSA:
273       if (pk_params->params_nr >= 6)
274         rc = gcry_sexp_build (&s_key, NULL,
275                               "(private-key(rsa((n%m)(e%m)(d%m)(p%m)(q%m)(u%m))))",
276                               pk_params->params[0], pk_params->params[1],
277                               pk_params->params[2], pk_params->params[3],
278                               pk_params->params[4], pk_params->params[5]);
279       else
280         {
281           gnutls_assert ();
282         }
283       break;
284
285     default:
286       gnutls_assert ();
287       ret = GNUTLS_E_INTERNAL_ERROR;
288       goto cleanup;
289     }
290
291   if (rc != 0)
292     {
293       gnutls_assert ();
294       ret = GNUTLS_E_INTERNAL_ERROR;
295       goto cleanup;
296     }
297
298   /* put the data into a simple list */
299   if (gcry_sexp_build (&s_hash, NULL, "%m", hash))
300     {
301       gnutls_assert ();
302       ret = GNUTLS_E_INTERNAL_ERROR;
303       goto cleanup;
304     }
305
306
307   /* pass it to libgcrypt */
308   rc = gcry_pk_sign (&s_sig, s_hash, s_key);
309   if (rc != 0)
310     {
311       gnutls_assert ();
312       ret = GNUTLS_E_PK_SIGN_FAILED;
313       goto cleanup;
314     }
315
316   ret = GNUTLS_E_INTERNAL_ERROR;
317
318   switch (algo)
319     {
320     case GNUTLS_PK_DSA:
321       {
322         list = gcry_sexp_find_token (s_sig, "r", 0);
323         if (list == NULL)
324           {
325             gnutls_assert ();
326             ret = GNUTLS_E_INTERNAL_ERROR;
327             goto cleanup;
328           }
329
330         res[0] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
331         gcry_sexp_release (list);
332
333         list = gcry_sexp_find_token (s_sig, "s", 0);
334         if (list == NULL)
335           {
336             gnutls_assert ();
337             ret = GNUTLS_E_INTERNAL_ERROR;
338             goto cleanup;
339           }
340
341         res[1] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
342         gcry_sexp_release (list);
343
344         ret = _gnutls_encode_ber_rs (signature, res[0], res[1]);
345         if (ret < 0)
346           {
347             gnutls_assert ();
348             goto cleanup;
349           }
350       }
351       break;
352
353     case GNUTLS_PK_RSA:
354       {
355         list = gcry_sexp_find_token (s_sig, "s", 0);
356         if (list == NULL)
357           {
358             gnutls_assert ();
359             ret = GNUTLS_E_INTERNAL_ERROR;
360             goto cleanup;
361           }
362
363         res[0] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
364         gcry_sexp_release (list);
365
366         ret = _gnutls_mpi_dprint (res[0], signature);
367         if (ret < 0)
368           {
369             gnutls_assert ();
370             goto cleanup;
371           }
372       }
373       break;
374
375     default:
376       gnutls_assert ();
377       ret = GNUTLS_E_INTERNAL_ERROR;
378       goto cleanup;
379     }
380
381   ret = 0;
382
383 cleanup:
384   _gnutls_mpi_release (&hash);
385   if (res[0])
386     _gnutls_mpi_release (&res[0]);
387   if (res[1])
388     _gnutls_mpi_release (&res[1]);
389   if (s_sig)
390     gcry_sexp_release (s_sig);
391   if (s_hash)
392     gcry_sexp_release (s_hash);
393   if (s_key)
394     gcry_sexp_release (s_key);
395
396   return ret;
397 }
398
399 static int
400 _wrap_gcry_pk_verify (gnutls_pk_algorithm_t algo,
401                       const gnutls_datum_t * vdata,
402                       const gnutls_datum_t * signature,
403                       const gnutls_pk_params_st * pk_params)
404 {
405   gcry_sexp_t s_sig = NULL, s_hash = NULL, s_pkey = NULL;
406   int rc = -1, ret;
407   bigint_t hash;
408   bigint_t tmp[2] = { NULL, NULL };
409
410   if (_gnutls_mpi_scan_nz (&hash, vdata->data, vdata->size) != 0)
411     {
412       gnutls_assert ();
413       return GNUTLS_E_MPI_SCAN_FAILED;
414     }
415
416   /* make a sexp from pkey */
417   switch (algo)
418     {
419     case GNUTLS_PK_DSA:
420       if (pk_params->params_nr >= 4)
421         rc = gcry_sexp_build (&s_pkey, NULL,
422                               "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))",
423                               pk_params->params[0], pk_params->params[1],
424                               pk_params->params[2], pk_params->params[3]);
425       break;
426     case GNUTLS_PK_RSA:
427       if (pk_params->params_nr >= 2)
428         rc = gcry_sexp_build (&s_pkey, NULL,
429                               "(public-key(rsa(n%m)(e%m)))",
430                               pk_params->params[0], pk_params->params[1]);
431       break;
432
433     default:
434       gnutls_assert ();
435       ret = GNUTLS_E_INTERNAL_ERROR;
436       goto cleanup;
437     }
438
439   if (rc != 0)
440     {
441       gnutls_assert ();
442       ret = GNUTLS_E_INTERNAL_ERROR;
443       goto cleanup;
444     }
445
446   /* put the data into a simple list */
447   if (gcry_sexp_build (&s_hash, NULL, "%m", hash))
448     {
449       gnutls_assert ();
450       ret = GNUTLS_E_INTERNAL_ERROR;
451       goto cleanup;
452     }
453
454   switch (algo)
455     {
456     case GNUTLS_PK_DSA:
457       ret = _gnutls_decode_ber_rs (signature, &tmp[0], &tmp[1]);
458       if (ret < 0)
459         {
460           gnutls_assert ();
461           goto cleanup;
462         }
463       rc = gcry_sexp_build (&s_sig, NULL,
464                             "(sig-val(dsa(r%m)(s%m)))", tmp[0], tmp[1]);
465       _gnutls_mpi_release (&tmp[0]);
466       _gnutls_mpi_release (&tmp[1]);
467       break;
468
469     case GNUTLS_PK_RSA:
470       ret = _gnutls_mpi_scan_nz (&tmp[0], signature->data, signature->size);
471       if (ret < 0)
472         {
473           gnutls_assert ();
474           goto cleanup;
475         }
476       rc = gcry_sexp_build (&s_sig, NULL, "(sig-val(rsa(s%m)))", tmp[0]);
477       _gnutls_mpi_release (&tmp[0]);
478       break;
479
480     default:
481       gnutls_assert ();
482       ret = GNUTLS_E_INTERNAL_ERROR;
483       goto cleanup;
484     }
485
486   if (rc != 0)
487     {
488       gnutls_assert ();
489       ret = GNUTLS_E_INTERNAL_ERROR;
490       goto cleanup;
491     }
492
493   rc = gcry_pk_verify (s_sig, s_hash, s_pkey);
494
495   if (rc != 0)
496     {
497       gnutls_assert ();
498       ret = GNUTLS_E_PK_SIG_VERIFY_FAILED;
499       goto cleanup;
500     }
501
502   ret = 0;
503
504 cleanup:
505   _gnutls_mpi_release (&hash);
506   if (s_sig)
507     gcry_sexp_release (s_sig);
508   if (s_hash)
509     gcry_sexp_release (s_hash);
510   if (s_pkey)
511     gcry_sexp_release (s_pkey);
512
513   return ret;
514 }
515
516 static int
517 _dsa_generate_params (bigint_t * resarr, int *resarr_len, int bits)
518 {
519
520   int ret;
521   gcry_sexp_t parms, key, list;
522
523   /* FIXME: Remove me once we depend on 1.3.1 */
524   if (bits > 1024 && gcry_check_version ("1.3.1") == NULL)
525     {
526       gnutls_assert ();
527       return GNUTLS_E_INVALID_REQUEST;
528     }
529
530   if (bits < 512)
531     {
532       gnutls_assert ();
533       return GNUTLS_E_INVALID_REQUEST;
534     }
535
536   ret = gcry_sexp_build (&parms, NULL, "(genkey(dsa(nbits %d)))", bits);
537   if (ret != 0)
538     {
539       gnutls_assert ();
540       return GNUTLS_E_INTERNAL_ERROR;
541     }
542
543   /* generate the DSA key 
544    */
545   ret = gcry_pk_genkey (&key, parms);
546   gcry_sexp_release (parms);
547
548   if (ret != 0)
549     {
550       gnutls_assert ();
551       return GNUTLS_E_INTERNAL_ERROR;
552     }
553
554   list = gcry_sexp_find_token (key, "p", 0);
555   if (list == NULL)
556     {
557       gnutls_assert ();
558       gcry_sexp_release (key);
559       return GNUTLS_E_INTERNAL_ERROR;
560     }
561
562   resarr[0] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
563   gcry_sexp_release (list);
564
565   list = gcry_sexp_find_token (key, "q", 0);
566   if (list == NULL)
567     {
568       gnutls_assert ();
569       gcry_sexp_release (key);
570       return GNUTLS_E_INTERNAL_ERROR;
571     }
572
573   resarr[1] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
574   gcry_sexp_release (list);
575
576   list = gcry_sexp_find_token (key, "g", 0);
577   if (list == NULL)
578     {
579       gnutls_assert ();
580       gcry_sexp_release (key);
581       return GNUTLS_E_INTERNAL_ERROR;
582     }
583
584   resarr[2] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
585   gcry_sexp_release (list);
586
587   list = gcry_sexp_find_token (key, "y", 0);
588   if (list == NULL)
589     {
590       gnutls_assert ();
591       gcry_sexp_release (key);
592       return GNUTLS_E_INTERNAL_ERROR;
593     }
594
595   resarr[3] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
596   gcry_sexp_release (list);
597
598
599   list = gcry_sexp_find_token (key, "x", 0);
600   if (list == NULL)
601     {
602       gnutls_assert ();
603       gcry_sexp_release (key);
604       return GNUTLS_E_INTERNAL_ERROR;
605     }
606
607   resarr[4] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
608
609   gcry_sexp_release (list);
610   gcry_sexp_release (key);
611
612   _gnutls_mpi_log ("p: ", resarr[0]);
613   _gnutls_mpi_log ("q: ", resarr[1]);
614   _gnutls_mpi_log ("g: ", resarr[2]);
615   _gnutls_mpi_log ("y: ", resarr[3]);
616   _gnutls_mpi_log ("x: ", resarr[4]);
617
618   *resarr_len = 5;
619
620   return 0;
621
622 }
623
624 static int
625 _rsa_generate_params (bigint_t * resarr, int *resarr_len, int bits)
626 {
627
628   int ret, i;
629   gcry_sexp_t parms, key, list;
630
631   if (*resarr_len < RSA_PRIVATE_PARAMS)
632     {
633       gnutls_assert ();
634       return GNUTLS_E_INTERNAL_ERROR;
635     }
636
637   ret = gcry_sexp_build (&parms, NULL, "(genkey(rsa(nbits %d)))", bits);
638   if (ret != 0)
639     {
640       gnutls_assert ();
641       return GNUTLS_E_INTERNAL_ERROR;
642     }
643
644   /* generate the RSA key */
645   ret = gcry_pk_genkey (&key, parms);
646   gcry_sexp_release (parms);
647
648   if (ret != 0)
649     {
650       gnutls_assert ();
651       return GNUTLS_E_INTERNAL_ERROR;
652     }
653
654   list = gcry_sexp_find_token (key, "n", 0);
655   if (list == NULL)
656     {
657       gnutls_assert ();
658       gcry_sexp_release (key);
659       return GNUTLS_E_INTERNAL_ERROR;
660     }
661
662   resarr[0] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
663   gcry_sexp_release (list);
664
665   list = gcry_sexp_find_token (key, "e", 0);
666   if (list == NULL)
667     {
668       gnutls_assert ();
669       gcry_sexp_release (key);
670       return GNUTLS_E_INTERNAL_ERROR;
671     }
672
673   resarr[1] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
674   gcry_sexp_release (list);
675
676   list = gcry_sexp_find_token (key, "d", 0);
677   if (list == NULL)
678     {
679       gnutls_assert ();
680       gcry_sexp_release (key);
681       return GNUTLS_E_INTERNAL_ERROR;
682     }
683
684   resarr[2] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
685   gcry_sexp_release (list);
686
687   list = gcry_sexp_find_token (key, "p", 0);
688   if (list == NULL)
689     {
690       gnutls_assert ();
691       gcry_sexp_release (key);
692       return GNUTLS_E_INTERNAL_ERROR;
693     }
694
695   resarr[3] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
696   gcry_sexp_release (list);
697
698
699   list = gcry_sexp_find_token (key, "q", 0);
700   if (list == NULL)
701     {
702       gnutls_assert ();
703       gcry_sexp_release (key);
704       return GNUTLS_E_INTERNAL_ERROR;
705     }
706
707   resarr[4] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
708   gcry_sexp_release (list);
709
710
711   list = gcry_sexp_find_token (key, "u", 0);
712   if (list == NULL)
713     {
714       gnutls_assert ();
715       gcry_sexp_release (key);
716       return GNUTLS_E_INTERNAL_ERROR;
717     }
718
719   resarr[5] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
720
721   gcry_sexp_release (list);
722   gcry_sexp_release (key);
723
724   _gnutls_mpi_log ("n: ", resarr[0]);
725   _gnutls_mpi_log ("e: ", resarr[1]);
726   _gnutls_mpi_log ("d: ", resarr[2]);
727   _gnutls_mpi_log ("p: ", resarr[3]);
728   _gnutls_mpi_log ("q: ", resarr[4]);
729   _gnutls_mpi_log ("u: ", resarr[5]);
730
731   /* generate e1 and e2 */
732
733   *resarr_len = 6;
734
735   ret = _gnutls_calc_rsa_exp (resarr, 2 + *resarr_len);
736   if (ret < 0)
737     {
738       gnutls_assert ();
739       ret = GNUTLS_E_MEMORY_ERROR;
740       goto cleanup;
741     }
742
743   (*resarr_len) += 2;
744
745   return 0;
746
747 cleanup:
748   for (i = 0; i < *resarr_len; i++)
749     _gnutls_mpi_release (&resarr[i]);
750
751   return ret;
752 }
753
754
755 static int
756 wrap_gcry_pk_generate_params (gnutls_pk_algorithm_t algo,
757                               unsigned int level /*bits */ ,
758                               gnutls_pk_params_st * params)
759 {
760
761   switch (algo)
762     {
763
764     case GNUTLS_PK_DSA:
765       params->params_nr = DSA_PRIVATE_PARAMS;
766       if (params->params_nr > GNUTLS_MAX_PK_PARAMS)
767         {
768           gnutls_assert ();
769           return GNUTLS_E_INTERNAL_ERROR;
770         }
771       return _dsa_generate_params (params->params, &params->params_nr, level);
772
773     case GNUTLS_PK_RSA:
774       params->params_nr = RSA_PRIVATE_PARAMS;
775       if (params->params_nr > GNUTLS_MAX_PK_PARAMS)
776         {
777           gnutls_assert ();
778           return GNUTLS_E_INTERNAL_ERROR;
779         }
780       return _rsa_generate_params (params->params, &params->params_nr, level);
781
782     default:
783       gnutls_assert ();
784       return GNUTLS_E_INVALID_REQUEST;
785     }
786 }
787
788
789 static int
790 wrap_gcry_pk_fixup (gnutls_pk_algorithm_t algo,
791                     gnutls_direction_t direction,
792                     gnutls_pk_params_st * params)
793 {
794   int ret, result;
795
796   /* only for RSA we invert the coefficient --pgp type */
797
798   if (algo != GNUTLS_PK_RSA)
799     return 0;
800
801   if (params->params[5] == NULL)
802     params->params[5] =
803       _gnutls_mpi_new (_gnutls_mpi_get_nbits (params->params[0]));
804
805   if (params->params[5] == NULL)
806     {
807       gnutls_assert ();
808       return GNUTLS_E_MEMORY_ERROR;
809     }
810
811   ret = 1;
812   if (direction == GNUTLS_IMPORT)
813     {
814       /* calculate exp1 [6] and exp2 [7] */
815       _gnutls_mpi_release (&params->params[6]);
816       _gnutls_mpi_release (&params->params[7]);
817       result = _gnutls_calc_rsa_exp (params->params, RSA_PRIVATE_PARAMS);
818       if (result < 0)
819         {
820           gnutls_assert ();
821           return result;
822         }
823
824       ret =
825         gcry_mpi_invm (params->params[5], params->params[3],
826                        params->params[4]);
827
828       params->params_nr = RSA_PRIVATE_PARAMS;
829     }
830   else if (direction == GNUTLS_EXPORT)
831     ret =
832       gcry_mpi_invm (params->params[5], params->params[4], params->params[3]);
833   if (ret == 0)
834     {
835       gnutls_assert ();
836       return GNUTLS_E_INVALID_REQUEST;
837     }
838
839   return 0;
840 }
841
842 int crypto_pk_prio = INT_MAX;
843
844 gnutls_crypto_pk_st _gnutls_pk_ops = {
845   .encrypt = _wrap_gcry_pk_encrypt,
846   .decrypt = _wrap_gcry_pk_decrypt,
847   .sign = _wrap_gcry_pk_sign,
848   .verify = _wrap_gcry_pk_verify,
849   .generate = wrap_gcry_pk_generate_params,
850   .pk_fixup_private_params = wrap_gcry_pk_fixup,
851 };