removed gnutls_pubkey_get_verify_algorithm() and unnecessary internal APIs
[gnutls:gnutls.git] / lib / nettle / pk.c
1 /*
2  * Copyright (C) 2010-2012 Free Software Foundation, Inc.
3  * Copyright (C) 2013 Nikos Mavrogiannopoulos
4  *
5  * Author: Nikos Mavrogiannopoulos
6  *
7  * This file is part of GNUTLS.
8  *
9  * The GNUTLS library 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 License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>
21  *
22  */
23
24 /* This file contains the functions needed for RSA/DSA public key
25  * encryption and signatures. 
26  */
27
28 #include <gnutls_int.h>
29 #include <gnutls_mpi.h>
30 #include <gnutls_pk.h>
31 #include <gnutls_errors.h>
32 #include <gnutls_datum.h>
33 #include <gnutls_global.h>
34 #include <gnutls_sig.h>
35 #include <gnutls_num.h>
36 #include <x509/x509_int.h>
37 #include <x509/common.h>
38 #include <random.h>
39 #include <gnutls_pk.h>
40 #include <nettle/dsa.h>
41 #ifdef ENABLE_FIPS140
42 # include <dsa-fips.h>
43 # include <rsa-fips.h>
44 #endif
45 #include <nettle/rsa.h>
46 #include <gnutls/crypto.h>
47 #include <nettle/bignum.h>
48 #include <nettle/ecc.h>
49 #include <nettle/ecdsa.h>
50 #include <nettle/ecc-curve.h>
51 #include <gnettle.h>
52 #include <fips.h>
53
54 static inline const struct ecc_curve *get_supported_curve(int curve);
55
56 static void rnd_func(void *_ctx, size_t length, uint8_t * data)
57 {
58         if (_gnutls_rnd(GNUTLS_RND_RANDOM, data, length) < 0) {
59 #ifdef ENABLE_FIPS140
60                 _gnutls_switch_lib_state(LIB_STATE_ERROR);
61 #else
62                 abort();
63 #endif
64         }
65 }
66
67 static void
68 ecc_scalar_zclear (struct ecc_scalar *s)
69 {
70         zeroize_key(s->p, ecc_size(s->ecc)*sizeof(mp_limb_t));
71         ecc_scalar_clear(s);
72 }
73
74 static void 
75 ecc_point_zclear (struct ecc_point *p)
76 {
77         zeroize_key(p->p, ecc_size_a(p->ecc)*sizeof(mp_limb_t));
78         ecc_point_clear(p);
79 }
80   
81 static void
82 _dsa_params_get(const gnutls_pk_params_st * pk_params,
83                 struct dsa_params *pub)
84 {
85         memcpy(pub->p, pk_params->params[DSA_P], SIZEOF_MPZT);
86
87         if (pk_params->params[DSA_Q])
88                 memcpy(&pub->q, pk_params->params[DSA_Q], sizeof(mpz_t));
89         memcpy(pub->g, pk_params->params[DSA_G], SIZEOF_MPZT);
90 }
91
92 static void
93 _rsa_params_to_privkey(const gnutls_pk_params_st * pk_params,
94                        struct rsa_private_key *priv)
95 {
96         memcpy(priv->d, pk_params->params[2], SIZEOF_MPZT);
97         memcpy(priv->p, pk_params->params[3], SIZEOF_MPZT);
98         memcpy(priv->q, pk_params->params[4], SIZEOF_MPZT);
99         memcpy(priv->c, pk_params->params[5], SIZEOF_MPZT);
100         memcpy(priv->a, pk_params->params[6], SIZEOF_MPZT);
101         memcpy(priv->b, pk_params->params[7], SIZEOF_MPZT);
102         priv->size =
103             nettle_mpz_sizeinbase_256_u(TOMPZ
104                                         (pk_params->params[RSA_MODULUS]));
105 }
106
107 static void
108 _rsa_params_to_pubkey(const gnutls_pk_params_st * pk_params,
109                       struct rsa_public_key *pub)
110 {
111         memcpy(pub->n, pk_params->params[RSA_MODULUS], SIZEOF_MPZT);
112         memcpy(pub->e, pk_params->params[RSA_PUB], SIZEOF_MPZT);
113         pub->size = nettle_mpz_sizeinbase_256_u(pub->n);
114 }
115
116 static int
117 _ecc_params_to_privkey(const gnutls_pk_params_st * pk_params,
118                        struct ecc_scalar *priv,
119                        const struct ecc_curve *curve)
120 {
121         ecc_scalar_init(priv, curve);
122         if (ecc_scalar_set(priv, pk_params->params[ECC_K]) == 0) {
123                 ecc_scalar_clear(priv);
124                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
125         }
126
127         return 0;
128 }
129
130 static int
131 _ecc_params_to_pubkey(const gnutls_pk_params_st * pk_params,
132                       struct ecc_point *pub, const struct ecc_curve *curve)
133 {
134         ecc_point_init(pub, curve);
135         if (ecc_point_set
136             (pub, pk_params->params[ECC_X], pk_params->params[ECC_Y]) == 0) {
137                 ecc_point_clear(pub);
138                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
139         }
140
141         return 0;
142 }
143
144 static void
145 ecc_shared_secret(struct ecc_scalar *private_key,
146                   struct ecc_point *public_key, void *out, unsigned size)
147 {
148         struct ecc_point r;
149         mpz_t x;
150
151         mpz_init(x);
152         ecc_point_init(&r, public_key->ecc);
153
154         ecc_point_mul(&r, private_key, public_key);
155
156         ecc_point_get(&r, x, NULL);
157         nettle_mpz_get_str_256(size, out, x);
158
159         mpz_clear(x);
160         ecc_point_clear(&r);
161
162         return;
163 }
164
165 #define MAX_DH_BITS DEFAULT_MAX_VERIFY_BITS
166 /* This is used when we have no idea on the structure
167  * of p-1 used by the peer. It is still a conservative
168  * choice, but small than what we've been using before.
169  */
170 #define DH_EXPONENT_SIZE(p_size) (2*_gnutls_pk_bits_to_subgroup_bits(p_size))
171
172 /* This is used for DH or ECDH key derivation. In DH for example
173  * it is given the peers Y and our x, and calculates Y^x 
174  */
175 static int _wrap_nettle_pk_derive(gnutls_pk_algorithm_t algo,
176                                   gnutls_datum_t * out,
177                                   const gnutls_pk_params_st * priv,
178                                   const gnutls_pk_params_st * pub)
179 {
180         int ret;
181
182         switch (algo) {
183         case GNUTLS_PK_DH: {
184                 bigint_t f, x, prime;
185                 bigint_t k = NULL, ff = NULL;
186                 unsigned int bits;
187
188                 f = pub->params[DH_Y];
189                 x = priv->params[DH_X];
190                 prime = priv->params[DH_P];
191
192                 ret = _gnutls_mpi_init_multi(&k, &ff, NULL);
193                 if (ret < 0)
194                         return gnutls_assert_val(ret);
195
196                 ret = _gnutls_mpi_modm(ff, f, prime);
197                 if (ret < 0) {
198                         gnutls_assert();
199                         goto dh_cleanup;
200                 }
201
202                 ret = _gnutls_mpi_add_ui(ff, ff, 1);
203                 if (ret < 0) {
204                         gnutls_assert();
205                         goto dh_cleanup;
206                 }
207
208                 /* check if f==0,1,p-1. 
209                  * or (ff=f+1) equivalently ff==1,2,p */
210                 if ((_gnutls_mpi_cmp_ui(ff, 2) == 0)
211                     || (_gnutls_mpi_cmp_ui(ff, 1) == 0)
212                     || (_gnutls_mpi_cmp(ff, prime) == 0)) {
213                         gnutls_assert();
214                         ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
215                         goto dh_cleanup;
216                 }
217
218                 /* prevent denial of service */
219                 bits = _gnutls_mpi_get_nbits(prime);
220                 if (bits == 0 || bits > MAX_DH_BITS) {
221                         gnutls_assert();
222                         ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
223                         goto dh_cleanup;
224                 }
225
226
227                 ret = _gnutls_mpi_powm(k, f, x, prime);
228                 if (ret < 0) {
229                         gnutls_assert();
230                         goto dh_cleanup;
231                 }
232
233                 ret = _gnutls_mpi_dprint(k, out);
234                 if (ret < 0) {
235                         gnutls_assert();
236                         goto dh_cleanup;
237                 }
238
239                 ret = 0;
240 dh_cleanup:
241                 _gnutls_mpi_release(&ff);
242                 zrelease_temp_mpi_key(&k);
243                 if (ret < 0)
244                         goto cleanup;
245
246                 break;
247         }
248         case GNUTLS_PK_EC:
249                 {
250                         struct ecc_scalar ecc_priv;
251                         struct ecc_point ecc_pub;
252                         const struct ecc_curve *curve;
253
254                         out->data = NULL;
255
256                         curve = get_supported_curve(priv->flags);
257                         if (curve == NULL)
258                                 return
259                                     gnutls_assert_val
260                                     (GNUTLS_E_ECC_UNSUPPORTED_CURVE);
261
262                         ret = _ecc_params_to_pubkey(pub, &ecc_pub, curve);
263                         if (ret < 0)
264                                 return gnutls_assert_val(ret);
265
266                         ret =
267                             _ecc_params_to_privkey(priv, &ecc_priv, curve);
268                         if (ret < 0) {
269                                 ecc_point_clear(&ecc_pub);
270                                 return gnutls_assert_val(ret);
271                         }
272
273                         out->size = gnutls_ecc_curve_get_size(priv->flags);
274                         /*ecc_size(curve)*sizeof(mp_limb_t); */
275                         out->data = gnutls_malloc(out->size);
276                         if (out->data == NULL) {
277                                 ret =
278                                     gnutls_assert_val
279                                     (GNUTLS_E_MEMORY_ERROR);
280                                 goto ecc_cleanup;
281                         }
282
283                         ecc_shared_secret(&ecc_priv, &ecc_pub, out->data,
284                                           out->size);
285
286                       ecc_cleanup:
287                         ecc_point_clear(&ecc_pub);
288                         ecc_scalar_zclear(&ecc_priv);
289                         if (ret < 0)
290                                 goto cleanup;
291                         break;
292                 }
293         default:
294                 gnutls_assert();
295                 ret = GNUTLS_E_INTERNAL_ERROR;
296                 goto cleanup;
297         }
298
299         ret = 0;
300
301       cleanup:
302
303         return ret;
304 }
305
306 static int
307 _wrap_nettle_pk_encrypt(gnutls_pk_algorithm_t algo,
308                         gnutls_datum_t * ciphertext,
309                         const gnutls_datum_t * plaintext,
310                         const gnutls_pk_params_st * pk_params)
311 {
312         int ret;
313         mpz_t p;
314
315         mpz_init(p);
316
317         switch (algo) {
318         case GNUTLS_PK_RSA:
319                 {
320                         struct rsa_public_key pub;
321
322                         _rsa_params_to_pubkey(pk_params, &pub);
323
324                         ret =
325                             rsa_encrypt(&pub, NULL, rnd_func,
326                                         plaintext->size, plaintext->data,
327                                         p);
328                         if (ret == 0) {
329                                 ret =
330                                     gnutls_assert_val
331                                     (GNUTLS_E_ENCRYPTION_FAILED);
332                                 goto cleanup;
333                         }
334
335                         ret =
336                             _gnutls_mpi_dprint_size(p, ciphertext,
337                                                     pub.size);
338                         if (ret < 0) {
339                                 gnutls_assert();
340                                 goto cleanup;
341                         }
342
343                         break;
344                 }
345         default:
346                 gnutls_assert();
347                 ret = GNUTLS_E_INTERNAL_ERROR;
348                 goto cleanup;
349         }
350
351         ret = 0;
352
353       cleanup:
354         mpz_clear(p);
355
356         FAIL_IF_LIB_ERROR;
357         return ret;
358 }
359
360 static int
361 _wrap_nettle_pk_decrypt(gnutls_pk_algorithm_t algo,
362                         gnutls_datum_t * plaintext,
363                         const gnutls_datum_t * ciphertext,
364                         const gnutls_pk_params_st * pk_params)
365 {
366         int ret;
367
368         plaintext->data = NULL;
369
370         /* make a sexp from pkey */
371         switch (algo) {
372         case GNUTLS_PK_RSA:
373                 {
374                         struct rsa_private_key priv;
375                         struct rsa_public_key pub;
376                         size_t length;
377                         bigint_t c;
378
379                         _rsa_params_to_privkey(pk_params, &priv);
380                         _rsa_params_to_pubkey(pk_params, &pub);
381
382                         if (ciphertext->size != pub.size)
383                                 return
384                                     gnutls_assert_val
385                                     (GNUTLS_E_DECRYPTION_FAILED);
386
387                         if (_gnutls_mpi_init_scan_nz
388                             (&c, ciphertext->data,
389                              ciphertext->size) != 0) {
390                                 ret =
391                                     gnutls_assert_val
392                                     (GNUTLS_E_MPI_SCAN_FAILED);
393                                 goto cleanup;
394                         }
395
396                         length = pub.size;
397                         plaintext->data = gnutls_malloc(length);
398                         if (plaintext->data == NULL) {
399                                 ret =
400                                     gnutls_assert_val
401                                     (GNUTLS_E_MEMORY_ERROR);
402                                 goto cleanup;
403                         }
404
405                         ret =
406                             rsa_decrypt_tr(&pub, &priv, NULL, rnd_func,
407                                            &length, plaintext->data,
408                                            TOMPZ(c));
409                         _gnutls_mpi_release(&c);
410                         plaintext->size = length;
411
412                         if (ret == 0) {
413                                 ret =
414                                     gnutls_assert_val
415                                     (GNUTLS_E_DECRYPTION_FAILED);
416                                 goto cleanup;
417                         }
418
419                         break;
420                 }
421         default:
422                 gnutls_assert();
423                 ret = GNUTLS_E_INTERNAL_ERROR;
424                 goto cleanup;
425         }
426
427         ret = 0;
428
429       cleanup:
430         if (ret < 0)
431                 gnutls_free(plaintext->data);
432
433         FAIL_IF_LIB_ERROR;
434         return ret;
435 }
436
437 /* in case of DSA puts into data, r,s
438  */
439 static int
440 _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
441                      gnutls_datum_t * signature,
442                      const gnutls_datum_t * vdata,
443                      const gnutls_pk_params_st * pk_params)
444 {
445         int ret;
446         unsigned int hash_len;
447         const mac_entry_st *me;
448
449         switch (algo) {
450         case GNUTLS_PK_EC:      /* we do ECDSA */
451                 {
452                         struct ecc_scalar priv;
453                         struct dsa_signature sig;
454                         int curve_id = pk_params->flags;
455                         const struct ecc_curve *curve;
456
457                         curve = get_supported_curve(curve_id);
458                         if (curve == NULL)
459                                 return
460                                     gnutls_assert_val
461                                     (GNUTLS_E_ECC_UNSUPPORTED_CURVE);
462
463                         ret =
464                             _ecc_params_to_privkey(pk_params, &priv,
465                                                    curve);
466                         if (ret < 0)
467                                 return gnutls_assert_val(ret);
468
469                         dsa_signature_init(&sig);
470
471                         me = _gnutls_dsa_q_to_hash(algo, pk_params,
472                                                    &hash_len);
473
474                         if (hash_len > vdata->size) {
475                                 gnutls_assert();
476                                 _gnutls_debug_log
477                                     ("Security level of algorithm requires hash %s(%d) or better\n",
478                                      _gnutls_mac_get_name(me), hash_len);
479                                 hash_len = vdata->size;
480                         }
481
482                         ecdsa_sign(&priv, NULL, rnd_func, hash_len,
483                                    vdata->data, &sig);
484
485                         ret =
486                             _gnutls_encode_ber_rs(signature, &sig.r,
487                                                   &sig.s);
488
489                         dsa_signature_clear(&sig);
490                         ecc_scalar_zclear(&priv);
491
492                         if (ret < 0) {
493                                 gnutls_assert();
494                                 goto cleanup;
495                         }
496                         break;
497                 }
498         case GNUTLS_PK_DSA:
499                 {
500                         struct dsa_params pub;
501                         bigint_t priv;
502                         struct dsa_signature sig;
503
504                         memset(&priv, 0, sizeof(priv));
505                         memset(&pub, 0, sizeof(pub));
506                         _dsa_params_get(pk_params, &pub);
507
508                         priv = pk_params->params[DSA_X];
509
510                         dsa_signature_init(&sig);
511
512                         me = _gnutls_dsa_q_to_hash(algo, pk_params,
513                                                    &hash_len);
514
515                         if (hash_len > vdata->size) {
516                                 gnutls_assert();
517                                 _gnutls_debug_log
518                                     ("Security level of algorithm requires hash %s(%d) or better (have: %d)\n",
519                                      _gnutls_mac_get_name(me), hash_len, (int)vdata->size);
520                                 hash_len = vdata->size;
521                         }
522
523                         ret =
524                             dsa_sign(&pub, TOMPZ(priv), NULL, rnd_func,
525                                      hash_len, vdata->data, &sig);
526                         if (ret == 0) {
527                                 gnutls_assert();
528                                 ret = GNUTLS_E_PK_SIGN_FAILED;
529                                 goto dsa_fail;
530                         }
531
532                         ret =
533                             _gnutls_encode_ber_rs(signature, &sig.r,
534                                                   &sig.s);
535
536                       dsa_fail:
537                         dsa_signature_clear(&sig);
538
539                         if (ret < 0) {
540                                 gnutls_assert();
541                                 goto cleanup;
542                         }
543                         break;
544                 }
545         case GNUTLS_PK_RSA:
546                 {
547                         struct rsa_private_key priv;
548                         struct rsa_public_key pub;
549                         mpz_t s;
550
551                         _rsa_params_to_privkey(pk_params, &priv);
552                         _rsa_params_to_pubkey(pk_params, &pub);
553
554                         mpz_init(s);
555
556                         ret =
557                             rsa_pkcs1_sign_tr(&pub, &priv, NULL, rnd_func,
558                                               vdata->size, vdata->data, s);
559                         if (ret == 0) {
560                                 gnutls_assert();
561                                 ret = GNUTLS_E_PK_SIGN_FAILED;
562                                 goto rsa_fail;
563                         }
564
565                         ret =
566                             _gnutls_mpi_dprint_size(s, signature,
567                                                     pub.size);
568
569                       rsa_fail:
570                         mpz_clear(s);
571
572                         if (ret < 0) {
573                                 gnutls_assert();
574                                 goto cleanup;
575                         }
576
577                         break;
578                 }
579         default:
580                 gnutls_assert();
581                 ret = GNUTLS_E_INTERNAL_ERROR;
582                 goto cleanup;
583         }
584
585         ret = 0;
586
587       cleanup:
588
589         FAIL_IF_LIB_ERROR;
590         return ret;
591 }
592
593 static int
594 _wrap_nettle_pk_verify(gnutls_pk_algorithm_t algo,
595                        const gnutls_datum_t * vdata,
596                        const gnutls_datum_t * signature,
597                        const gnutls_pk_params_st * pk_params)
598 {
599         int ret;
600         unsigned int hash_len;
601         bigint_t tmp[2] = { NULL, NULL };
602
603         switch (algo) {
604         case GNUTLS_PK_EC:      /* ECDSA */
605                 {
606                         struct ecc_point pub;
607                         struct dsa_signature sig;
608                         int curve_id = pk_params->flags;
609                         const struct ecc_curve *curve;
610
611                         curve = get_supported_curve(curve_id);
612                         if (curve == NULL)
613                                 return
614                                     gnutls_assert_val
615                                     (GNUTLS_E_ECC_UNSUPPORTED_CURVE);
616
617                         ret =
618                             _gnutls_decode_ber_rs(signature, &tmp[0],
619                                                   &tmp[1]);
620                         if (ret < 0)
621                                 return gnutls_assert_val(ret);
622
623                         ret =
624                             _ecc_params_to_pubkey(pk_params, &pub, curve);
625                         if (ret < 0) {
626                                 gnutls_assert();
627                                 goto cleanup;
628                         }
629
630                         memcpy(sig.r, tmp[0], SIZEOF_MPZT);
631                         memcpy(sig.s, tmp[1], SIZEOF_MPZT);
632
633                         _gnutls_dsa_q_to_hash(algo, pk_params, &hash_len);
634
635                         if (hash_len > vdata->size)
636                                 hash_len = vdata->size;
637
638                         ret =
639                             ecdsa_verify(&pub, hash_len, vdata->data,
640                                          &sig);
641                         if (ret == 0) {
642                                 gnutls_assert();
643                                 ret = GNUTLS_E_PK_SIG_VERIFY_FAILED;
644                         } else
645                                 ret = 0;
646
647                         ecc_point_clear(&pub);
648                         break;
649                 }
650         case GNUTLS_PK_DSA:
651                 {
652                         struct dsa_params pub;
653                         struct dsa_signature sig;
654                         bigint_t y;
655
656                         ret =
657                             _gnutls_decode_ber_rs(signature, &tmp[0],
658                                                   &tmp[1]);
659                         if (ret < 0) {
660                                 gnutls_assert();
661                                 goto cleanup;
662                         }
663                         memset(&pub, 0, sizeof(pub));
664                         _dsa_params_get(pk_params, &pub);
665                         y = pk_params->params[DSA_Y];
666
667                         memcpy(sig.r, tmp[0], SIZEOF_MPZT);
668                         memcpy(sig.s, tmp[1], SIZEOF_MPZT);
669
670                         _gnutls_dsa_q_to_hash(algo, pk_params, &hash_len);
671
672                         if (hash_len > vdata->size)
673                                 hash_len = vdata->size;
674
675                         ret =
676                             dsa_verify(&pub, TOMPZ(y), hash_len, vdata->data, &sig);
677                         if (ret == 0) {
678                                 gnutls_assert();
679                                 ret = GNUTLS_E_PK_SIG_VERIFY_FAILED;
680                         } else
681                                 ret = 0;
682
683                         break;
684                 }
685         case GNUTLS_PK_RSA:
686                 {
687                         struct rsa_public_key pub;
688
689                         _rsa_params_to_pubkey(pk_params, &pub);
690
691                         if (signature->size != pub.size)
692                                 return
693                                     gnutls_assert_val
694                                     (GNUTLS_E_PK_SIG_VERIFY_FAILED);
695
696                         ret =
697                             _gnutls_mpi_init_scan_nz(&tmp[0], signature->data,
698                                                 signature->size);
699                         if (ret < 0) {
700                                 gnutls_assert();
701                                 goto cleanup;
702                         }
703
704                         ret =
705                             rsa_pkcs1_verify(&pub, vdata->size,
706                                              vdata->data, TOMPZ(tmp[0]));
707                         if (ret == 0)
708                                 ret =
709                                     gnutls_assert_val
710                                     (GNUTLS_E_PK_SIG_VERIFY_FAILED);
711                         else
712                                 ret = 0;
713
714                         break;
715                 }
716         default:
717                 gnutls_assert();
718                 ret = GNUTLS_E_INTERNAL_ERROR;
719                 goto cleanup;
720         }
721
722       cleanup:
723
724         _gnutls_mpi_release(&tmp[0]);
725         _gnutls_mpi_release(&tmp[1]);
726         return ret;
727 }
728
729 static inline const struct ecc_curve *get_supported_curve(int curve)
730 {
731         switch (curve) {
732 #ifdef ENABLE_NON_SUITEB_CURVES
733         case GNUTLS_ECC_CURVE_SECP192R1:
734                 return &nettle_secp_192r1;
735         case GNUTLS_ECC_CURVE_SECP224R1:
736                 return &nettle_secp_224r1;
737 #endif
738         case GNUTLS_ECC_CURVE_SECP256R1:
739                 return &nettle_secp_256r1;
740         case GNUTLS_ECC_CURVE_SECP384R1:
741                 return &nettle_secp_384r1;
742         case GNUTLS_ECC_CURVE_SECP521R1:
743                 return &nettle_secp_521r1;
744         default:
745                 return NULL;
746         }
747 }
748
749 static int _wrap_nettle_pk_curve_exists(gnutls_ecc_curve_t curve)
750 {
751         return ((get_supported_curve(curve)!=NULL)?1:0);
752 }
753
754 /* Generates algorithm's parameters. That is:
755  *  For DSA: p, q, and g are generated.
756  *  For RSA: nothing
757  *  For ECDSA: just checks the curve is ok
758  */
759 static int
760 wrap_nettle_pk_generate_params(gnutls_pk_algorithm_t algo,
761                                unsigned int level /*bits or curve*/ ,
762                                gnutls_pk_params_st * params)
763 {
764         int ret;
765         unsigned int i, q_bits;
766
767         params->algo = algo;
768
769         switch (algo) {
770         case GNUTLS_PK_DSA:
771         case GNUTLS_PK_DH:
772                 {
773                         struct dsa_params pub;
774 #ifdef ENABLE_FIPS140
775                         struct dss_params_validation_seeds cert;
776                         unsigned index;
777 #endif
778
779                         dsa_params_init(&pub);
780
781                         if (GNUTLS_BITS_HAVE_SUBGROUP(level)) {
782                                 q_bits = GNUTLS_BITS_TO_SUBGROUP(level);
783                                 level = GNUTLS_BITS_TO_GROUP(level);
784                         } else {
785                                 q_bits = _gnutls_pk_bits_to_subgroup_bits(level);
786                         }
787
788                         if (q_bits == 0)
789                                 return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
790
791 #ifdef ENABLE_FIPS140
792                         if (_gnutls_fips_mode_enabled() != 0) {
793                                 if (algo==GNUTLS_PK_DSA)
794                                         index = 1;
795                                 else
796                                         index = 2;
797
798                                 ret =
799                                     dsa_generate_dss_pqg(&pub, &cert,
800                                                  index,
801                                                  NULL, rnd_func, 
802                                                  NULL, NULL,
803                                                  level, q_bits);
804                                 if (ret != 1) {
805                                         gnutls_assert();
806                                         ret = GNUTLS_E_PK_GENERATION_ERROR;
807                                         goto dsa_fail;
808                                 }
809
810                                 /* verify the generated parameters */
811                                 ret = dsa_validate_dss_pqg(&pub, &cert, index);
812                                 if (ret != 1) {
813                                         gnutls_assert();
814                                         ret = GNUTLS_E_PK_GENERATION_ERROR;
815                                         goto dsa_fail;
816                                 }
817                         } else 
818 #endif
819                         {
820                                 if (q_bits < 160)
821                                         q_bits = 160;
822
823                                 ret = dsa_generate_params(&pub, NULL, rnd_func,
824                                                           NULL, NULL, level, q_bits);
825                                 if (ret != 1) {
826                                         gnutls_assert();
827                                         ret = GNUTLS_E_PK_GENERATION_ERROR;
828                                         goto dsa_fail;
829                                 }
830                         }
831
832                         params->params_nr = 0;
833
834                         ret = _gnutls_mpi_init_multi(&params->params[DSA_P], &params->params[DSA_Q],
835                                         &params->params[DSA_G], NULL);
836                         if (ret < 0) {
837                                 gnutls_assert();
838                                 goto dsa_fail;
839                         }
840                         params->params_nr = 3;
841
842                         mpz_set(TOMPZ(params->params[DSA_P]), pub.p);
843                         mpz_set(TOMPZ(params->params[DSA_Q]), pub.q);
844                         mpz_set(TOMPZ(params->params[DSA_G]), pub.g);
845
846                         ret = 0;
847
848                       dsa_fail:
849                         dsa_params_clear(&pub);
850
851                         if (ret < 0)
852                                 goto fail;
853
854                         break;
855                 }
856         case GNUTLS_PK_RSA:
857         case GNUTLS_PK_EC:
858                 ret = 0;
859                 break;
860         default:
861                 gnutls_assert();
862                 return GNUTLS_E_INVALID_REQUEST;
863         }
864
865         FAIL_IF_LIB_ERROR;
866         return 0;
867
868       fail:
869
870         for (i = 0; i < params->params_nr; i++) {
871                 _gnutls_mpi_release(&params->params[i]);
872         }
873         params->params_nr = 0;
874
875         FAIL_IF_LIB_ERROR;
876         return ret;
877 }
878
879 #ifdef ENABLE_FIPS140
880 int _gnutls_dh_generate_key(gnutls_dh_params_t dh_params,
881                             gnutls_datum_t *priv_key, gnutls_datum_t *pub_key);
882
883 int _gnutls_dh_compute_key(gnutls_dh_params_t dh_params,
884                            const gnutls_datum_t *priv_key, const gnutls_datum_t *pub_key,
885                            const gnutls_datum_t *peer_key, gnutls_datum_t *Z);
886
887 int _gnutls_ecdh_compute_key(gnutls_ecc_curve_t curve,
888                            const gnutls_datum_t *x, const gnutls_datum_t *y,
889                            const gnutls_datum_t *k,
890                            const gnutls_datum_t *peer_x, const gnutls_datum_t *peer_y,
891                            gnutls_datum_t *Z);
892
893 int _gnutls_ecdh_generate_key(gnutls_ecc_curve_t curve,
894                               gnutls_datum_t *x, gnutls_datum_t *y,
895                               gnutls_datum_t *k);
896
897
898 int _gnutls_dh_generate_key(gnutls_dh_params_t dh_params,
899                             gnutls_datum_t *priv_key, gnutls_datum_t *pub_key)
900 {
901         gnutls_pk_params_st params;
902         int ret;
903
904         gnutls_pk_params_init(&params);
905         params.params[DH_P] = _gnutls_mpi_copy(dh_params->params[0]);
906         params.params[DH_G] = _gnutls_mpi_copy(dh_params->params[1]);
907
908         params.params_nr = 3; /* include empty q */
909         params.algo = GNUTLS_PK_DH;
910
911         priv_key->data = NULL;
912         pub_key->data = NULL;
913
914         ret = _gnutls_pk_generate_keys(GNUTLS_PK_DH, dh_params->q_bits, &params);
915         if (ret < 0) {
916                 return gnutls_assert_val(ret);
917         }
918
919         ret =
920             _gnutls_mpi_dprint_lz(params.params[DH_X], priv_key);
921         if (ret < 0) {
922                 gnutls_assert();
923                 goto fail;
924         }
925
926         ret =
927             _gnutls_mpi_dprint_lz(params.params[DH_Y], pub_key);
928         if (ret < 0) {
929                 gnutls_assert();
930                 goto fail;
931         }
932
933         ret = 0;
934         goto cleanup;
935  fail:
936         gnutls_free(pub_key->data);
937         gnutls_free(priv_key->data);
938  cleanup:
939         gnutls_pk_params_clear(&params);
940         return ret;
941 }
942
943 int _gnutls_dh_compute_key(gnutls_dh_params_t dh_params,
944                            const gnutls_datum_t *priv_key, const gnutls_datum_t *pub_key,
945                            const gnutls_datum_t *peer_key, gnutls_datum_t *Z)
946 {
947         gnutls_pk_params_st pub, priv;
948         int ret;
949
950         gnutls_pk_params_init(&pub);
951         gnutls_pk_params_init(&priv);
952         pub.algo = GNUTLS_PK_DH;
953
954         if (_gnutls_mpi_init_scan_nz
955                     (&pub.params[DH_Y], peer_key->data,
956                      peer_key->size) != 0) {
957                 ret =
958                     gnutls_assert_val(GNUTLS_E_MPI_SCAN_FAILED);
959                 goto cleanup;
960         }
961
962         priv.params[DH_P] = _gnutls_mpi_copy(dh_params->params[0]);
963         priv.params[DH_G] = _gnutls_mpi_copy(dh_params->params[1]);
964
965         if (_gnutls_mpi_init_scan_nz
966                     (&priv.params[DH_X], priv_key->data,
967                      priv_key->size) != 0) {
968                 ret =
969                     gnutls_assert_val(GNUTLS_E_MPI_SCAN_FAILED);
970                 goto cleanup;
971         }
972
973         priv.params_nr = 3; /* include empty q */
974         priv.algo = GNUTLS_PK_DH;
975
976         Z->data = NULL;
977
978         ret = _gnutls_pk_derive(GNUTLS_PK_DH, Z, &priv, &pub);
979         if (ret < 0) {
980                 gnutls_assert();
981                 goto cleanup;
982         }
983
984         ret = 0;
985  cleanup:
986         gnutls_pk_params_clear(&pub);
987         gnutls_pk_params_clear(&priv);
988         return ret;
989 }
990
991 int _gnutls_ecdh_generate_key(gnutls_ecc_curve_t curve,
992                               gnutls_datum_t *x, gnutls_datum_t *y,
993                               gnutls_datum_t *k)
994 {
995         gnutls_pk_params_st params;
996         int ret;
997
998         gnutls_pk_params_init(&params);
999         params.flags = curve;
1000         params.algo = GNUTLS_PK_EC;
1001
1002         x->data = NULL;
1003         y->data = NULL;
1004         k->data = NULL;
1005
1006         ret = _gnutls_pk_generate_keys(GNUTLS_PK_EC, curve, &params);
1007         if (ret < 0) {
1008                 return gnutls_assert_val(ret);
1009         }
1010
1011         ret =
1012             _gnutls_mpi_dprint_lz(params.params[ECC_X], x);
1013         if (ret < 0) {
1014                 gnutls_assert();
1015                 goto fail;
1016         }
1017
1018         ret =
1019             _gnutls_mpi_dprint_lz(params.params[ECC_Y], y);
1020         if (ret < 0) {
1021                 gnutls_assert();
1022                 goto fail;
1023         }
1024
1025         ret =
1026             _gnutls_mpi_dprint_lz(params.params[ECC_K], k);
1027         if (ret < 0) {
1028                 gnutls_assert();
1029                 goto fail;
1030         }
1031
1032         ret = 0;
1033         goto cleanup;
1034  fail:
1035         gnutls_free(y->data);
1036         gnutls_free(x->data);
1037         gnutls_free(k->data);
1038  cleanup:
1039         gnutls_pk_params_clear(&params);
1040         return ret;
1041 }
1042
1043 int _gnutls_ecdh_compute_key(gnutls_ecc_curve_t curve,
1044                            const gnutls_datum_t *x, const gnutls_datum_t *y,
1045                            const gnutls_datum_t *k,
1046                            const gnutls_datum_t *peer_x, const gnutls_datum_t *peer_y,
1047                            gnutls_datum_t *Z)
1048 {
1049         gnutls_pk_params_st pub, priv;
1050         int ret;
1051
1052         gnutls_pk_params_init(&pub);
1053         gnutls_pk_params_init(&priv);
1054
1055         pub.algo = GNUTLS_PK_EC;
1056         pub.flags = curve;
1057
1058         if (_gnutls_mpi_init_scan_nz
1059                     (&pub.params[ECC_Y], peer_y->data,
1060                      peer_y->size) != 0) {
1061                 ret =
1062                     gnutls_assert_val(GNUTLS_E_MPI_SCAN_FAILED);
1063                 goto cleanup;
1064         }
1065
1066         if (_gnutls_mpi_init_scan_nz
1067                     (&pub.params[ECC_X], peer_x->data,
1068                      peer_x->size) != 0) {
1069                 ret =
1070                     gnutls_assert_val(GNUTLS_E_MPI_SCAN_FAILED);
1071                 goto cleanup;
1072         }
1073
1074         pub.params_nr = 2;
1075
1076         if (_gnutls_mpi_init_scan_nz
1077                     (&priv.params[ECC_Y], y->data,
1078                      y->size) != 0) {
1079                 ret =
1080                     gnutls_assert_val(GNUTLS_E_MPI_SCAN_FAILED);
1081                 goto cleanup;
1082         }
1083
1084         if (_gnutls_mpi_init_scan_nz
1085                     (&priv.params[ECC_X], x->data,
1086                      x->size) != 0) {
1087                 ret =
1088                     gnutls_assert_val(GNUTLS_E_MPI_SCAN_FAILED);
1089                 goto cleanup;
1090         }
1091
1092         if (_gnutls_mpi_init_scan_nz
1093                     (&priv.params[ECC_K], k->data,
1094                      k->size) != 0) {
1095                 ret =
1096                     gnutls_assert_val(GNUTLS_E_MPI_SCAN_FAILED);
1097                 goto cleanup;
1098         }
1099
1100
1101         priv.params_nr = 3;
1102         priv.algo = GNUTLS_PK_EC;
1103         priv.flags = curve;
1104
1105         Z->data = NULL;
1106
1107         ret = _gnutls_pk_derive(GNUTLS_PK_EC, Z, &priv, &pub);
1108         if (ret < 0) {
1109                 gnutls_assert();
1110                 goto cleanup;
1111         }
1112
1113         ret = 0;
1114  cleanup:
1115         gnutls_pk_params_clear(&pub);
1116         gnutls_pk_params_clear(&priv);
1117         return ret;
1118 }
1119 #endif
1120
1121
1122 /* To generate a DH key either q must be set in the params or
1123  * level should be set to the number of required bits.
1124  */
1125 static int
1126 wrap_nettle_pk_generate_keys(gnutls_pk_algorithm_t algo,
1127                                unsigned int level /*bits */ ,
1128                                gnutls_pk_params_st * params)
1129 {
1130         int ret;
1131         unsigned int i;
1132
1133         switch (algo) {
1134         case GNUTLS_PK_DSA:
1135 #ifdef ENABLE_FIPS140
1136                 if (_gnutls_fips_mode_enabled() != 0) {
1137                         struct dsa_params pub;
1138                         mpz_t x, y;
1139
1140                         if (params->params[DSA_Q] == NULL)
1141                                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1142
1143                         _dsa_params_get(params, &pub);
1144
1145                         mpz_init(x);
1146                         mpz_init(y);
1147
1148                         ret =
1149                             dsa_generate_dss_keypair(&pub, y, x,
1150                                                  NULL, rnd_func, 
1151                                                  NULL, NULL);
1152                         if (ret != 1) {
1153                                 gnutls_assert();
1154                                 ret = GNUTLS_E_PK_GENERATION_ERROR;
1155                                 goto dsa_fail;
1156                         }
1157
1158                         ret = _gnutls_mpi_init_multi(&params->params[DSA_Y], &params->params[DSA_X], NULL);
1159                         if (ret < 0) {
1160                                 gnutls_assert();
1161                                 goto dsa_fail;
1162                         }
1163
1164                         mpz_set(TOMPZ(params->params[DSA_Y]), y);
1165                         mpz_set(TOMPZ(params->params[DSA_X]), x);
1166                         params->params_nr += 2;
1167
1168                       dsa_fail:
1169                         mpz_clear(x);
1170                         mpz_clear(y);
1171
1172                         if (ret < 0)
1173                                 goto fail;
1174
1175                         break;
1176                 }
1177 #endif
1178         case GNUTLS_PK_DH:
1179                 {
1180                         struct dsa_params pub;
1181                         mpz_t r;
1182                         mpz_t x, y;
1183                         int max_tries;
1184                         unsigned have_q = 0;
1185
1186                         if (algo != params->algo)
1187                                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1188
1189                         _dsa_params_get(params, &pub);
1190
1191                         if (params->params[DSA_Q] != NULL)
1192                                 have_q = 1;
1193
1194                         /* This check is for the case !ENABLE_FIPS140 */
1195                         if (algo == GNUTLS_PK_DSA && have_q == 0)
1196                                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1197
1198                         mpz_init(r);
1199                         mpz_init(x);
1200                         mpz_init(y);
1201
1202                         max_tries = 3;
1203                         do {
1204                                 if (have_q) {
1205                                         mpz_set(r, pub.q);
1206                                         mpz_sub_ui(r, r, 2);
1207                                         nettle_mpz_random(x, NULL, rnd_func, r);
1208                                         mpz_add_ui(x, x, 1);
1209                                 } else {
1210                                         unsigned size = mpz_sizeinbase(pub.p, 2);
1211                                         if (level == 0)
1212                                                 level = MIN(size, DH_EXPONENT_SIZE(size));
1213                                         nettle_mpz_random_size(x, NULL, rnd_func, level);
1214
1215                                         if (level >= size)
1216                                                 mpz_mod(x, x, pub.p);
1217                                 }
1218
1219                                 mpz_powm(y, pub.g, x, pub.p);
1220
1221                                 max_tries--;
1222                                 if (max_tries <= 0) {
1223                                         gnutls_assert();
1224                                         ret = GNUTLS_E_RANDOM_FAILED;
1225                                         goto dh_fail;
1226                                 }
1227                         } while(mpz_cmp_ui(y, 1) == 0);
1228
1229                         ret = _gnutls_mpi_init_multi(&params->params[DSA_Y], &params->params[DSA_X], NULL);
1230                         if (ret < 0) {
1231                                 gnutls_assert();
1232                                 goto dh_fail;
1233                         }
1234
1235                         mpz_set(TOMPZ(params->params[DSA_Y]), y);
1236                         mpz_set(TOMPZ(params->params[DSA_X]), x);
1237                         params->params_nr += 2;
1238
1239                         ret = 0;
1240
1241                       dh_fail:
1242                         mpz_clear(r);
1243                         mpz_clear(x);
1244                         mpz_clear(y);
1245
1246                         if (ret < 0)
1247                                 goto fail;
1248
1249                         break;
1250                 }
1251         case GNUTLS_PK_RSA:
1252                 {
1253                         struct rsa_public_key pub;
1254                         struct rsa_private_key priv;
1255
1256                         rsa_public_key_init(&pub);
1257                         rsa_private_key_init(&priv);
1258
1259                         mpz_set_ui(pub.e, 65537);
1260
1261 #ifdef ENABLE_FIPS140
1262                         if (_gnutls_fips_mode_enabled() != 0) {
1263                                 ret =
1264                                     rsa_generate_fips186_4_keypair(&pub, &priv, NULL,
1265                                                  rnd_func, NULL, NULL,
1266                                                  level);
1267                         } else
1268 #endif
1269                         {
1270                                 ret =
1271                                     rsa_generate_keypair(&pub, &priv, NULL,
1272                                                  rnd_func, NULL, NULL,
1273                                                  level, 0);
1274                         }
1275                         if (ret != 1) {
1276                                 gnutls_assert();
1277                                 ret = GNUTLS_E_PK_GENERATION_ERROR;
1278                                 goto rsa_fail;
1279                         }
1280
1281                         params->params_nr = 0;
1282                         for (i = 0; i < RSA_PRIVATE_PARAMS; i++) {
1283                                 ret = _gnutls_mpi_init(&params->params[i]);
1284                                 if (ret < 0) {
1285                                         gnutls_assert();
1286                                         goto rsa_fail;
1287                                 }
1288                                 params->params_nr++;
1289                         }
1290
1291                         mpz_set(TOMPZ(params->params[0]), pub.n);
1292                         mpz_set(TOMPZ(params->params[1]), pub.e);
1293                         mpz_set(TOMPZ(params->params[2]), priv.d);
1294                         mpz_set(TOMPZ(params->params[3]), priv.p);
1295                         mpz_set(TOMPZ(params->params[4]), priv.q);
1296                         mpz_set(TOMPZ(params->params[5]), priv.c);
1297                         mpz_set(TOMPZ(params->params[6]), priv.a);
1298                         mpz_set(TOMPZ(params->params[7]), priv.b);
1299
1300                         ret = 0;
1301
1302                       rsa_fail:
1303                         rsa_private_key_clear(&priv);
1304                         rsa_public_key_clear(&pub);
1305
1306                         if (ret < 0)
1307                                 goto fail;
1308
1309                         break;
1310                 }
1311         case GNUTLS_PK_EC:
1312                 {
1313                         struct ecc_scalar key;
1314                         struct ecc_point pub;
1315                         const struct ecc_curve *curve;
1316
1317                         curve = get_supported_curve(level);
1318                         if (curve == NULL)
1319                                 return
1320                                     gnutls_assert_val
1321                                     (GNUTLS_E_ECC_UNSUPPORTED_CURVE);
1322
1323                         ecc_scalar_init(&key, curve);
1324                         ecc_point_init(&pub, curve);
1325
1326                         ecdsa_generate_keypair(&pub, &key, NULL, rnd_func);
1327
1328                         ret = _gnutls_mpi_init_multi(&params->params[ECC_X], &params->params[ECC_Y], 
1329                                         &params->params[ECC_K], NULL);
1330                         if (ret < 0) {
1331                                 gnutls_assert();
1332                                 goto ecc_fail;
1333                         }
1334
1335                         params->flags = level;
1336                         params->params_nr = ECC_PRIVATE_PARAMS;
1337
1338                         ecc_point_get(&pub, TOMPZ(params->params[ECC_X]),
1339                                       TOMPZ(params->params[ECC_Y]));
1340                         ecc_scalar_get(&key, TOMPZ(params->params[ECC_K]));
1341
1342                         ret = 0;
1343
1344                       ecc_fail:
1345                         ecc_point_clear(&pub);
1346                         ecc_scalar_clear(&key);
1347
1348                         if (ret < 0)
1349                                 goto fail;
1350
1351                         break;
1352                 }
1353         default:
1354                 gnutls_assert();
1355                 return GNUTLS_E_INVALID_REQUEST;
1356         }
1357
1358         FAIL_IF_LIB_ERROR;
1359         return 0;
1360
1361       fail:
1362
1363         for (i = 0; i < params->params_nr; i++) {
1364                 _gnutls_mpi_release(&params->params[i]);
1365         }
1366         params->params_nr = 0;
1367
1368         FAIL_IF_LIB_ERROR;
1369         return ret;
1370 }
1371
1372 static int
1373 wrap_nettle_pk_verify_priv_params(gnutls_pk_algorithm_t algo,
1374                              const gnutls_pk_params_st * params)
1375 {
1376         int ret;
1377
1378         switch (algo) {
1379         case GNUTLS_PK_RSA:
1380                 {
1381                         bigint_t t1 = NULL, t2 = NULL;
1382
1383                         if (params->params_nr != RSA_PRIVATE_PARAMS)
1384                                 return
1385                                     gnutls_assert_val
1386                                     (GNUTLS_E_INVALID_REQUEST);
1387
1388                         ret = _gnutls_mpi_init_multi(&t1, &t2, NULL);
1389                         if (ret < 0)
1390                                 return
1391                                     gnutls_assert_val(ret);
1392
1393                         _gnutls_mpi_mulm(t1, params->params[RSA_PRIME1],
1394                                          params->params[RSA_PRIME2],
1395                                          params->params[RSA_MODULUS]);
1396                         if (_gnutls_mpi_cmp_ui(t1, 0) != 0) {
1397                                 ret =
1398                                     gnutls_assert_val
1399                                     (GNUTLS_E_ILLEGAL_PARAMETER);
1400                                 goto rsa_cleanup;
1401                         }
1402
1403                         mpz_invert(TOMPZ(t1),
1404                                    TOMPZ(params->params[RSA_PRIME2]),
1405                                    TOMPZ(params->params[RSA_PRIME1]));
1406                         if (_gnutls_mpi_cmp(t1, params->params[RSA_COEF])
1407                             != 0) {
1408                                 ret =
1409                                     gnutls_assert_val
1410                                     (GNUTLS_E_ILLEGAL_PARAMETER);
1411                                 goto rsa_cleanup;
1412                         }
1413
1414                         /* [RSA_PRIME1] = d % p-1, [RSA_PRIME2] = d % q-1 */
1415                         _gnutls_mpi_sub_ui(t1, params->params[RSA_PRIME1],
1416                                            1);
1417                         ret = _gnutls_mpi_modm(t2, params->params[RSA_PRIV], t1);
1418                         if (ret < 0) {
1419                                 ret =
1420                                     gnutls_assert_val
1421                                     (GNUTLS_E_MEMORY_ERROR);
1422                                 goto rsa_cleanup;
1423                         }
1424
1425                         if (_gnutls_mpi_cmp(params->params[RSA_E1], t2) !=
1426                             0) {
1427                                 ret =
1428                                     gnutls_assert_val
1429                                     (GNUTLS_E_ILLEGAL_PARAMETER);
1430                                 goto rsa_cleanup;
1431                         }
1432
1433                         _gnutls_mpi_sub_ui(t1, params->params[RSA_PRIME2],
1434                                            1);
1435
1436                         ret = _gnutls_mpi_modm(t2, params->params[RSA_PRIV], t1);
1437                         if (ret < 0) {
1438                                 ret =
1439                                     gnutls_assert_val
1440                                     (GNUTLS_E_MEMORY_ERROR);
1441                                 goto rsa_cleanup;
1442                         }
1443
1444                         if (_gnutls_mpi_cmp(params->params[RSA_E2], t2) !=
1445                             0) {
1446                                 ret =
1447                                     gnutls_assert_val
1448                                     (GNUTLS_E_ILLEGAL_PARAMETER);
1449                                 goto rsa_cleanup;
1450                         }
1451
1452                         ret = 0;
1453
1454                       rsa_cleanup:
1455                         zrelease_mpi_key(&t1);
1456                         zrelease_mpi_key(&t2);
1457                 }
1458
1459                 break;
1460         case GNUTLS_PK_DSA:
1461                 {
1462                         bigint_t t1 = NULL;
1463
1464                         if (params->params_nr != DSA_PRIVATE_PARAMS)
1465                                 return
1466                                     gnutls_assert_val
1467                                     (GNUTLS_E_INVALID_REQUEST);
1468
1469                         ret = _gnutls_mpi_init(&t1);
1470                         if (ret < 0)
1471                                 return
1472                                     gnutls_assert_val(ret);
1473
1474                         ret = _gnutls_mpi_powm(t1, params->params[DSA_G],
1475                                          params->params[DSA_X],
1476                                          params->params[DSA_P]);
1477                         if (ret < 0) {
1478                                 gnutls_assert();
1479                                 goto dsa_cleanup;
1480                         }
1481
1482                         if (_gnutls_mpi_cmp(t1, params->params[DSA_Y]) !=
1483                             0) {
1484                                 ret =
1485                                     gnutls_assert_val
1486                                     (GNUTLS_E_ILLEGAL_PARAMETER);
1487                                 goto dsa_cleanup;
1488                         }
1489
1490                         ret = 0;
1491
1492                       dsa_cleanup:
1493                         zrelease_mpi_key(&t1);
1494                 }
1495
1496                 break;
1497         case GNUTLS_PK_EC:
1498                 {
1499                         struct ecc_point r, pub;
1500                         struct ecc_scalar priv;
1501                         mpz_t x1, y1, x2, y2;
1502                         const struct ecc_curve *curve;
1503
1504                         if (params->params_nr != ECC_PRIVATE_PARAMS)
1505                                 return
1506                                     gnutls_assert_val
1507                                     (GNUTLS_E_INVALID_REQUEST);
1508
1509                         curve = get_supported_curve(params->flags);
1510                         if (curve == NULL)
1511                                 return
1512                                     gnutls_assert_val
1513                                     (GNUTLS_E_ECC_UNSUPPORTED_CURVE);
1514
1515                         ret = _ecc_params_to_pubkey(params, &pub, curve);
1516                         if (ret < 0)
1517                                 return gnutls_assert_val(ret);
1518
1519                         ret = _ecc_params_to_privkey(params, &priv, curve);
1520                         if (ret < 0) {
1521                                 ecc_point_clear(&pub);
1522                                 return gnutls_assert_val(ret);
1523                         }
1524
1525                         ecc_point_init(&r, curve);
1526                         /* verify that x,y lie on the curve */
1527                         ret =
1528                             ecc_point_set(&r, TOMPZ(params->params[ECC_X]),
1529                                           TOMPZ(params->params[ECC_Y]));
1530                         if (ret == 0) {
1531                                 ret =
1532                                     gnutls_assert_val
1533                                     (GNUTLS_E_ILLEGAL_PARAMETER);
1534                                 goto ecc_cleanup;
1535                         }
1536                         ecc_point_clear(&r);
1537
1538                         ecc_point_init(&r, curve);
1539                         ecc_point_mul_g(&r, &priv);
1540
1541                         mpz_init(x1);
1542                         mpz_init(y1);
1543                         ecc_point_get(&r, x1, y1);
1544                         ecc_point_zclear(&r);
1545
1546                         mpz_init(x2);
1547                         mpz_init(y2);
1548                         ecc_point_get(&pub, x2, y2);
1549
1550                         /* verify that k*(Gx,Gy)=(x,y) */
1551                         if (mpz_cmp(x1, x2) != 0 || mpz_cmp(y1, y2) != 0) {
1552                                 ret =
1553                                     gnutls_assert_val
1554                                     (GNUTLS_E_ILLEGAL_PARAMETER);
1555                                 goto ecc_cleanup;
1556                         }
1557
1558                         ret = 0;
1559
1560                       ecc_cleanup:
1561                         ecc_scalar_zclear(&priv);
1562                         ecc_point_clear(&pub);
1563                 }
1564                 break;
1565         default:
1566                 ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1567         }
1568
1569         return ret;
1570 }
1571
1572 static int
1573 wrap_nettle_pk_verify_pub_params(gnutls_pk_algorithm_t algo,
1574                              const gnutls_pk_params_st * params)
1575 {
1576         int ret;
1577
1578         switch (algo) {
1579         case GNUTLS_PK_RSA:
1580         case GNUTLS_PK_DSA:
1581                 return 0;
1582         case GNUTLS_PK_EC:
1583                 {
1584                         /* just verify that x and y lie on the curve */
1585                         struct ecc_point r, pub;
1586                         const struct ecc_curve *curve;
1587
1588                         if (params->params_nr != ECC_PUBLIC_PARAMS)
1589                                 return
1590                                     gnutls_assert_val
1591                                     (GNUTLS_E_INVALID_REQUEST);
1592
1593                         curve = get_supported_curve(params->flags);
1594                         if (curve == NULL)
1595                                 return
1596                                     gnutls_assert_val
1597                                     (GNUTLS_E_ECC_UNSUPPORTED_CURVE);
1598
1599                         ret = _ecc_params_to_pubkey(params, &pub, curve);
1600                         if (ret < 0)
1601                                 return gnutls_assert_val(ret);
1602
1603                         ecc_point_init(&r, curve);
1604                         /* verify that x,y lie on the curve */
1605                         ret =
1606                             ecc_point_set(&r, TOMPZ(params->params[ECC_X]),
1607                                           TOMPZ(params->params[ECC_Y]));
1608                         if (ret == 0) {
1609                                 ret =
1610                                     gnutls_assert_val
1611                                     (GNUTLS_E_ILLEGAL_PARAMETER);
1612                                 goto ecc_cleanup;
1613                         }
1614                         ecc_point_clear(&r);
1615
1616                         ret = 0;
1617
1618                       ecc_cleanup:
1619                         ecc_point_clear(&pub);
1620                 }
1621                 break;
1622         default:
1623                 ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1624         }
1625
1626         return ret;
1627 }
1628
1629 static int calc_rsa_exp(gnutls_pk_params_st * params)
1630 {
1631         bigint_t tmp;
1632         int ret;
1633
1634         if (params->params_nr < RSA_PRIVATE_PARAMS - 2) {
1635                 gnutls_assert();
1636                 return GNUTLS_E_INTERNAL_ERROR;
1637         }
1638
1639         params->params[6] = params->params[7] = NULL;
1640
1641         ret = _gnutls_mpi_init_multi(&tmp, &params->params[6], &params->params[7], NULL);
1642         if (ret < 0)
1643                 return gnutls_assert_val(ret);
1644
1645         /* [6] = d % p-1, [7] = d % q-1 */
1646         _gnutls_mpi_sub_ui(tmp, params->params[3], 1);
1647         ret =
1648             _gnutls_mpi_modm(params->params[6], params->params[2] /*d */ , tmp);
1649         if (ret < 0)
1650                 goto fail;
1651
1652         _gnutls_mpi_sub_ui(tmp, params->params[4], 1);
1653         ret =
1654             _gnutls_mpi_modm(params->params[7], params->params[2] /*d */ , tmp);
1655         if (ret < 0)
1656                 goto fail;
1657
1658         zrelease_mpi_key(&tmp);
1659
1660         return 0;
1661
1662 fail:
1663         zrelease_mpi_key(&tmp);
1664         zrelease_mpi_key(&params->params[6]);
1665         zrelease_mpi_key(&params->params[7]);
1666
1667         return ret;
1668 }
1669
1670
1671 static int
1672 wrap_nettle_pk_fixup(gnutls_pk_algorithm_t algo,
1673                      gnutls_direction_t direction,
1674                      gnutls_pk_params_st * params)
1675 {
1676         int ret;
1677
1678         if (direction == GNUTLS_IMPORT && algo == GNUTLS_PK_RSA) {
1679                 /* do not trust the generated values. Some old private keys
1680                  * generated by us have mess on the values. Those were very
1681                  * old but it seemed some of the shipped example private
1682                  * keys were as old.
1683                  */
1684                 if (params->params_nr < RSA_PRIVATE_PARAMS - 3)
1685                         return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1686
1687                 if (params->params[RSA_COEF] == NULL) {
1688                         ret = _gnutls_mpi_init(&params->params[RSA_COEF]);
1689                         if (ret < 0)
1690                                 return gnutls_assert_val(ret);
1691                 }
1692                 mpz_invert(TOMPZ(params->params[RSA_COEF]),
1693                            TOMPZ(params->params[RSA_PRIME2]),
1694                            TOMPZ(params->params[RSA_PRIME1]));
1695
1696                 /* calculate exp1 [6] and exp2 [7] */
1697                 zrelease_mpi_key(&params->params[RSA_E1]);
1698                 zrelease_mpi_key(&params->params[RSA_E2]);
1699
1700                 ret = calc_rsa_exp(params);
1701                 if (ret < 0)
1702                         return gnutls_assert_val(ret);
1703
1704                 params->params_nr = RSA_PRIVATE_PARAMS;
1705         }
1706
1707         return 0;
1708 }
1709
1710 static int
1711 extract_digest_info(const struct rsa_public_key *key,
1712                     gnutls_datum_t * di, uint8_t ** rdi,
1713                     const mpz_t signature)
1714 {
1715         unsigned i;
1716         int ret;
1717         mpz_t m;
1718         uint8_t *em;
1719
1720         if (key->size == 0)
1721                 return 0;
1722
1723         em = gnutls_malloc(key->size);
1724         if (em == NULL)
1725                 return 0;
1726
1727         mpz_init(m);
1728
1729         mpz_powm(m, signature, key->e, key->n);
1730
1731         nettle_mpz_get_str_256(key->size, em, m);
1732         mpz_clear(m);
1733
1734         if (em[0] != 0 || em[1] != 1) {
1735                 ret = 0;
1736                 goto cleanup;
1737         }
1738
1739         for (i = 2; i < key->size; i++) {
1740                 if (em[i] == 0 && i > 2)
1741                         break;
1742
1743                 if (em[i] != 0xff) {
1744                         ret = 0;
1745                         goto cleanup;
1746                 }
1747         }
1748
1749         i++;
1750
1751         *rdi = em;
1752
1753         di->data = &em[i];
1754         di->size = key->size - i;
1755
1756         return 1;
1757
1758 cleanup:
1759         memset(em, 0, sizeof(key->size));
1760         gnutls_free(em);
1761
1762         return ret;
1763 }
1764
1765 int crypto_pk_prio = INT_MAX;
1766
1767 gnutls_crypto_pk_st _gnutls_pk_ops = {
1768         .encrypt = _wrap_nettle_pk_encrypt,
1769         .decrypt = _wrap_nettle_pk_decrypt,
1770         .sign = _wrap_nettle_pk_sign,
1771         .verify = _wrap_nettle_pk_verify,
1772         .verify_priv_params = wrap_nettle_pk_verify_priv_params,
1773         .verify_pub_params = wrap_nettle_pk_verify_pub_params,
1774         .generate_params = wrap_nettle_pk_generate_params,
1775         .generate_keys = wrap_nettle_pk_generate_keys,
1776         .pk_fixup_private_params = wrap_nettle_pk_fixup,
1777         .derive = _wrap_nettle_pk_derive,
1778         .curve_exists = _wrap_nettle_pk_curve_exists,
1779 };