2
* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2009, 2010
3
* Free Software Foundation, Inc.
5
* Author: Nikos Mavrogiannopoulos
7
* This file is part of GnuTLS.
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.
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.
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,
26
/* This file contains the functions needed for RSA/DSA public key
27
* encryption and signatures.
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>
40
#include <gnutls_pk.h>
43
/* this is based on code from old versions of libgcrypt (centuries ago)
46
int (*generate) (gnutls_pk_algorithm_t, unsigned int level /*bits */ ,
47
gnutls_pk_params_st *);
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)
55
gcry_sexp_t s_ciph = NULL, s_data = NULL, s_pkey = NULL;
61
if (_gnutls_mpi_scan_nz (&data, plaintext->data, plaintext->size) != 0)
64
return GNUTLS_E_MPI_SCAN_FAILED;
67
/* make a sexp from pkey */
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]);
79
ret = GNUTLS_E_INTERNAL_ERROR;
86
ret = GNUTLS_E_INTERNAL_ERROR;
90
/* put the data into a simple list */
91
if (gcry_sexp_build (&s_data, NULL, "%m", data))
94
ret = GNUTLS_E_MEMORY_ERROR;
98
/* pass it to libgcrypt */
99
rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey);
103
ret = GNUTLS_E_PK_ENCRYPTION_FAILED;
107
list = gcry_sexp_find_token (s_ciph, "a", 0);
111
ret = GNUTLS_E_INTERNAL_ERROR;
115
res = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
116
gcry_sexp_release (list);
120
ret = GNUTLS_E_INTERNAL_ERROR;
124
ret = _gnutls_mpi_dprint_size (res, ciphertext, plaintext->size);
125
_gnutls_mpi_release (&res);
135
_gnutls_mpi_release (&data);
137
gcry_sexp_release (s_ciph);
139
gcry_sexp_release (s_data);
141
gcry_sexp_release (s_pkey);
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)
152
gcry_sexp_t s_plain = NULL, s_data = NULL, s_pkey = NULL;
157
if (_gnutls_mpi_scan_nz (&data, ciphertext->data, ciphertext->size) != 0)
160
return GNUTLS_E_MPI_SCAN_FAILED;
163
/* make a sexp from pkey */
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]);
177
ret = GNUTLS_E_INTERNAL_ERROR;
184
ret = GNUTLS_E_INTERNAL_ERROR;
188
/* put the data into a simple list */
189
if (gcry_sexp_build (&s_data, NULL, "(enc-val(rsa(a%m)))", data))
192
ret = GNUTLS_E_INTERNAL_ERROR;
196
/* pass it to libgcrypt */
197
rc = gcry_pk_decrypt (&s_plain, s_data, s_pkey);
201
ret = GNUTLS_E_PK_DECRYPTION_FAILED;
205
res = gcry_sexp_nth_mpi (s_plain, 0, GCRYMPI_FMT_USG);
209
ret = GNUTLS_E_INTERNAL_ERROR;
213
ret = _gnutls_mpi_dprint_size (res, plaintext, ciphertext->size);
214
_gnutls_mpi_release (&res);
224
_gnutls_mpi_release (&data);
226
gcry_sexp_release (s_plain);
228
gcry_sexp_release (s_data);
230
gcry_sexp_release (s_pkey);
237
/* in case of DSA puts into data, r,s
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)
244
gcry_sexp_t s_hash = NULL, s_key = NULL, s_sig = NULL;
245
gcry_sexp_t list = NULL;
248
bigint_t res[2] = { NULL, NULL };
250
if (_gnutls_mpi_scan_nz (&hash, vdata->data, vdata->size) != 0)
253
return GNUTLS_E_MPI_SCAN_FAILED;
256
/* make a sexp from pkey */
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]);
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]);
287
ret = GNUTLS_E_INTERNAL_ERROR;
294
ret = GNUTLS_E_INTERNAL_ERROR;
298
/* put the data into a simple list */
299
if (gcry_sexp_build (&s_hash, NULL, "%m", hash))
302
ret = GNUTLS_E_INTERNAL_ERROR;
307
/* pass it to libgcrypt */
308
rc = gcry_pk_sign (&s_sig, s_hash, s_key);
312
ret = GNUTLS_E_PK_SIGN_FAILED;
316
ret = GNUTLS_E_INTERNAL_ERROR;
322
list = gcry_sexp_find_token (s_sig, "r", 0);
326
ret = GNUTLS_E_INTERNAL_ERROR;
330
res[0] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
331
gcry_sexp_release (list);
333
list = gcry_sexp_find_token (s_sig, "s", 0);
337
ret = GNUTLS_E_INTERNAL_ERROR;
341
res[1] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
342
gcry_sexp_release (list);
344
ret = _gnutls_encode_ber_rs (signature, res[0], res[1]);
355
list = gcry_sexp_find_token (s_sig, "s", 0);
359
ret = GNUTLS_E_INTERNAL_ERROR;
363
res[0] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
364
gcry_sexp_release (list);
366
ret = _gnutls_mpi_dprint (res[0], signature);
377
ret = GNUTLS_E_INTERNAL_ERROR;
384
_gnutls_mpi_release (&hash);
386
_gnutls_mpi_release (&res[0]);
388
_gnutls_mpi_release (&res[1]);
390
gcry_sexp_release (s_sig);
392
gcry_sexp_release (s_hash);
394
gcry_sexp_release (s_key);
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)
405
gcry_sexp_t s_sig = NULL, s_hash = NULL, s_pkey = NULL;
408
bigint_t tmp[2] = { NULL, NULL };
410
if (_gnutls_mpi_scan_nz (&hash, vdata->data, vdata->size) != 0)
413
return GNUTLS_E_MPI_SCAN_FAILED;
416
/* make a sexp from pkey */
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]);
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]);
435
ret = GNUTLS_E_INTERNAL_ERROR;
442
ret = GNUTLS_E_INTERNAL_ERROR;
446
/* put the data into a simple list */
447
if (gcry_sexp_build (&s_hash, NULL, "%m", hash))
450
ret = GNUTLS_E_INTERNAL_ERROR;
457
ret = _gnutls_decode_ber_rs (signature, &tmp[0], &tmp[1]);
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]);
470
ret = _gnutls_mpi_scan_nz (&tmp[0], signature->data, signature->size);
476
rc = gcry_sexp_build (&s_sig, NULL, "(sig-val(rsa(s%m)))", tmp[0]);
477
_gnutls_mpi_release (&tmp[0]);
482
ret = GNUTLS_E_INTERNAL_ERROR;
489
ret = GNUTLS_E_INTERNAL_ERROR;
493
rc = gcry_pk_verify (s_sig, s_hash, s_pkey);
498
ret = GNUTLS_E_PK_SIG_VERIFY_FAILED;
505
_gnutls_mpi_release (&hash);
507
gcry_sexp_release (s_sig);
509
gcry_sexp_release (s_hash);
511
gcry_sexp_release (s_pkey);
517
_dsa_generate_params (bigint_t * resarr, int *resarr_len, int bits)
521
gcry_sexp_t parms, key, list;
523
/* FIXME: Remove me once we depend on 1.3.1 */
524
if (bits > 1024 && gcry_check_version ("1.3.1") == NULL)
527
return GNUTLS_E_INVALID_REQUEST;
533
return GNUTLS_E_INVALID_REQUEST;
536
ret = gcry_sexp_build (&parms, NULL, "(genkey(dsa(nbits %d)))", bits);
540
return GNUTLS_E_INTERNAL_ERROR;
543
/* generate the DSA key
545
ret = gcry_pk_genkey (&key, parms);
546
gcry_sexp_release (parms);
551
return GNUTLS_E_INTERNAL_ERROR;
554
list = gcry_sexp_find_token (key, "p", 0);
558
gcry_sexp_release (key);
559
return GNUTLS_E_INTERNAL_ERROR;
562
resarr[0] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
563
gcry_sexp_release (list);
565
list = gcry_sexp_find_token (key, "q", 0);
569
gcry_sexp_release (key);
570
return GNUTLS_E_INTERNAL_ERROR;
573
resarr[1] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
574
gcry_sexp_release (list);
576
list = gcry_sexp_find_token (key, "g", 0);
580
gcry_sexp_release (key);
581
return GNUTLS_E_INTERNAL_ERROR;
584
resarr[2] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
585
gcry_sexp_release (list);
587
list = gcry_sexp_find_token (key, "y", 0);
591
gcry_sexp_release (key);
592
return GNUTLS_E_INTERNAL_ERROR;
595
resarr[3] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
596
gcry_sexp_release (list);
599
list = gcry_sexp_find_token (key, "x", 0);
603
gcry_sexp_release (key);
604
return GNUTLS_E_INTERNAL_ERROR;
607
resarr[4] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
609
gcry_sexp_release (list);
610
gcry_sexp_release (key);
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]);
625
_rsa_generate_params (bigint_t * resarr, int *resarr_len, int bits)
629
gcry_sexp_t parms, key, list;
632
if (*resarr_len < RSA_PRIVATE_PARAMS)
635
return GNUTLS_E_INTERNAL_ERROR;
638
ret = gcry_sexp_build (&parms, NULL, "(genkey(rsa(nbits %d)))", bits);
642
return GNUTLS_E_INTERNAL_ERROR;
645
/* generate the RSA key */
646
ret = gcry_pk_genkey (&key, parms);
647
gcry_sexp_release (parms);
652
return GNUTLS_E_INTERNAL_ERROR;
655
list = gcry_sexp_find_token (key, "n", 0);
659
gcry_sexp_release (key);
660
return GNUTLS_E_INTERNAL_ERROR;
663
resarr[0] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
664
gcry_sexp_release (list);
666
list = gcry_sexp_find_token (key, "e", 0);
670
gcry_sexp_release (key);
671
return GNUTLS_E_INTERNAL_ERROR;
674
resarr[1] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
675
gcry_sexp_release (list);
677
list = gcry_sexp_find_token (key, "d", 0);
681
gcry_sexp_release (key);
682
return GNUTLS_E_INTERNAL_ERROR;
685
resarr[2] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
686
gcry_sexp_release (list);
688
list = gcry_sexp_find_token (key, "p", 0);
692
gcry_sexp_release (key);
693
return GNUTLS_E_INTERNAL_ERROR;
696
resarr[3] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
697
gcry_sexp_release (list);
700
list = gcry_sexp_find_token (key, "q", 0);
704
gcry_sexp_release (key);
705
return GNUTLS_E_INTERNAL_ERROR;
708
resarr[4] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
709
gcry_sexp_release (list);
712
list = gcry_sexp_find_token (key, "u", 0);
716
gcry_sexp_release (key);
717
return GNUTLS_E_INTERNAL_ERROR;
720
resarr[5] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
722
gcry_sexp_release (list);
723
gcry_sexp_release (key);
725
_gnutls_mpi_log ("n: ", resarr[0]);
726
_gnutls_mpi_log ("e: ", resarr[1]);
727
_gnutls_mpi_log ("d: ", resarr[2]);
728
_gnutls_mpi_log ("p: ", resarr[3]);
729
_gnutls_mpi_log ("q: ", resarr[4]);
730
_gnutls_mpi_log ("u: ", resarr[5]);
732
/* generate e1 and e2 */
736
tmp = _gnutls_mpi_alloc_like (resarr[0]);
740
ret = GNUTLS_E_MEMORY_ERROR;
744
ret = _gnutls_calc_rsa_exp (resarr, 2 + *resarr_len);
748
ret = GNUTLS_E_MEMORY_ERROR;
757
for (i = 0; i < *resarr_len; i++)
758
_gnutls_mpi_release (&resarr[i]);
765
wrap_gcry_pk_generate_params (gnutls_pk_algorithm_t algo,
766
unsigned int level /*bits */ ,
767
gnutls_pk_params_st * params)
774
params->params_nr = DSA_PRIVATE_PARAMS;
775
if (params->params_nr > GNUTLS_MAX_PK_PARAMS)
778
return GNUTLS_E_INTERNAL_ERROR;
780
return _dsa_generate_params (params->params, ¶ms->params_nr, level);
783
params->params_nr = RSA_PRIVATE_PARAMS;
784
if (params->params_nr > GNUTLS_MAX_PK_PARAMS)
787
return GNUTLS_E_INTERNAL_ERROR;
789
return _rsa_generate_params (params->params, ¶ms->params_nr, level);
793
return GNUTLS_E_INVALID_REQUEST;
799
wrap_gcry_pk_fixup (gnutls_pk_algorithm_t algo,
800
gnutls_direction_t direction,
801
gnutls_pk_params_st * params)
805
/* only for RSA we invert the coefficient --pgp type */
807
if (algo != GNUTLS_PK_RSA)
810
if (params->params[5] == NULL)
812
_gnutls_mpi_new (_gnutls_mpi_get_nbits (params->params[0]));
814
if (params->params[5] == NULL)
817
return GNUTLS_E_MEMORY_ERROR;
821
if (direction == GNUTLS_IMPORT)
823
/* calculate exp1 [6] and exp2 [7] */
824
_gnutls_mpi_release (¶ms->params[6]);
825
_gnutls_mpi_release (¶ms->params[7]);
826
result = _gnutls_calc_rsa_exp (params->params, RSA_PRIVATE_PARAMS);
834
gcry_mpi_invm (params->params[5], params->params[3],
837
params->params_nr = RSA_PRIVATE_PARAMS;
839
else if (direction == GNUTLS_EXPORT)
841
gcry_mpi_invm (params->params[5], params->params[4], params->params[3]);
845
return GNUTLS_E_INVALID_REQUEST;
851
int crypto_pk_prio = INT_MAX;
853
gnutls_crypto_pk_st _gnutls_pk_ops = {
854
.encrypt = _wrap_gcry_pk_encrypt,
855
.decrypt = _wrap_gcry_pk_decrypt,
856
.sign = _wrap_gcry_pk_sign,
857
.verify = _wrap_gcry_pk_verify,
858
.generate = wrap_gcry_pk_generate_params,
859
.pk_fixup_private_params = wrap_gcry_pk_fixup,