~ubuntu-branches/ubuntu/trusty/gnutls26/trusty

« back to all changes in this revision

Viewing changes to lib/gcrypt/pk.c

  • Committer: Package Import Robot
  • Author(s): Andreas Metzler
  • Date: 2011-10-01 15:28:13 UTC
  • mfrom: (12.1.20 sid)
  • Revision ID: package-import@ubuntu.com-20111001152813-yygm1c4cxonfxhzy
* New upstream version.
  + Allow CA importing of 0 certificates to succeed. Closes: #640639
* Add libp11-kit-dev to libgnutls-dev dependencies. (see #643811)
* [20_guiledocstring.diff] guile: Fix docstring extraction with CPP 4.5+.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
  bigint_t tmp;
 
631
 
 
632
  if (*resarr_len < RSA_PRIVATE_PARAMS)
 
633
    {
 
634
      gnutls_assert ();
 
635
      return GNUTLS_E_INTERNAL_ERROR;
 
636
    }
 
637
 
 
638
  ret = gcry_sexp_build (&parms, NULL, "(genkey(rsa(nbits %d)))", bits);
 
639
  if (ret != 0)
 
640
    {
 
641
      gnutls_assert ();
 
642
      return GNUTLS_E_INTERNAL_ERROR;
 
643
    }
 
644
 
 
645
  /* generate the RSA key */
 
646
  ret = gcry_pk_genkey (&key, parms);
 
647
  gcry_sexp_release (parms);
 
648
 
 
649
  if (ret != 0)
 
650
    {
 
651
      gnutls_assert ();
 
652
      return GNUTLS_E_INTERNAL_ERROR;
 
653
    }
 
654
 
 
655
  list = gcry_sexp_find_token (key, "n", 0);
 
656
  if (list == NULL)
 
657
    {
 
658
      gnutls_assert ();
 
659
      gcry_sexp_release (key);
 
660
      return GNUTLS_E_INTERNAL_ERROR;
 
661
    }
 
662
 
 
663
  resarr[0] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
 
664
  gcry_sexp_release (list);
 
665
 
 
666
  list = gcry_sexp_find_token (key, "e", 0);
 
667
  if (list == NULL)
 
668
    {
 
669
      gnutls_assert ();
 
670
      gcry_sexp_release (key);
 
671
      return GNUTLS_E_INTERNAL_ERROR;
 
672
    }
 
673
 
 
674
  resarr[1] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
 
675
  gcry_sexp_release (list);
 
676
 
 
677
  list = gcry_sexp_find_token (key, "d", 0);
 
678
  if (list == NULL)
 
679
    {
 
680
      gnutls_assert ();
 
681
      gcry_sexp_release (key);
 
682
      return GNUTLS_E_INTERNAL_ERROR;
 
683
    }
 
684
 
 
685
  resarr[2] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
 
686
  gcry_sexp_release (list);
 
687
 
 
688
  list = gcry_sexp_find_token (key, "p", 0);
 
689
  if (list == NULL)
 
690
    {
 
691
      gnutls_assert ();
 
692
      gcry_sexp_release (key);
 
693
      return GNUTLS_E_INTERNAL_ERROR;
 
694
    }
 
695
 
 
696
  resarr[3] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
 
697
  gcry_sexp_release (list);
 
698
 
 
699
 
 
700
  list = gcry_sexp_find_token (key, "q", 0);
 
701
  if (list == NULL)
 
702
    {
 
703
      gnutls_assert ();
 
704
      gcry_sexp_release (key);
 
705
      return GNUTLS_E_INTERNAL_ERROR;
 
706
    }
 
707
 
 
708
  resarr[4] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
 
709
  gcry_sexp_release (list);
 
710
 
 
711
 
 
712
  list = gcry_sexp_find_token (key, "u", 0);
 
713
  if (list == NULL)
 
714
    {
 
715
      gnutls_assert ();
 
716
      gcry_sexp_release (key);
 
717
      return GNUTLS_E_INTERNAL_ERROR;
 
718
    }
 
719
 
 
720
  resarr[5] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
 
721
 
 
722
  gcry_sexp_release (list);
 
723
  gcry_sexp_release (key);
 
724
 
 
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]);
 
731
 
 
732
  /* generate e1 and e2 */
 
733
 
 
734
  *resarr_len = 6;
 
735
 
 
736
  tmp = _gnutls_mpi_alloc_like (resarr[0]);
 
737
  if (tmp == NULL)
 
738
    {
 
739
      gnutls_assert ();
 
740
      ret = GNUTLS_E_MEMORY_ERROR;
 
741
      goto cleanup;
 
742
    }
 
743
 
 
744
  ret = _gnutls_calc_rsa_exp (resarr, 2 + *resarr_len);
 
745
  if (ret < 0)
 
746
    {
 
747
      gnutls_assert ();
 
748
      ret = GNUTLS_E_MEMORY_ERROR;
 
749
      goto cleanup;
 
750
    }
 
751
 
 
752
  (*resarr_len) += 2;
 
753
 
 
754
  return 0;
 
755
 
 
756
cleanup:
 
757
  for (i = 0; i < *resarr_len; i++)
 
758
    _gnutls_mpi_release (&resarr[i]);
 
759
 
 
760
  return ret;
 
761
}
 
762
 
 
763
 
 
764
static int
 
765
wrap_gcry_pk_generate_params (gnutls_pk_algorithm_t algo,
 
766
                              unsigned int level /*bits */ ,
 
767
                              gnutls_pk_params_st * params)
 
768
{
 
769
 
 
770
  switch (algo)
 
771
    {
 
772
 
 
773
    case GNUTLS_PK_DSA:
 
774
      params->params_nr = DSA_PRIVATE_PARAMS;
 
775
      if (params->params_nr > GNUTLS_MAX_PK_PARAMS)
 
776
        {
 
777
          gnutls_assert ();
 
778
          return GNUTLS_E_INTERNAL_ERROR;
 
779
        }
 
780
      return _dsa_generate_params (params->params, &params->params_nr, level);
 
781
 
 
782
    case GNUTLS_PK_RSA:
 
783
      params->params_nr = RSA_PRIVATE_PARAMS;
 
784
      if (params->params_nr > GNUTLS_MAX_PK_PARAMS)
 
785
        {
 
786
          gnutls_assert ();
 
787
          return GNUTLS_E_INTERNAL_ERROR;
 
788
        }
 
789
      return _rsa_generate_params (params->params, &params->params_nr, level);
 
790
 
 
791
    default:
 
792
      gnutls_assert ();
 
793
      return GNUTLS_E_INVALID_REQUEST;
 
794
    }
 
795
}
 
796
 
 
797
 
 
798
static int
 
799
wrap_gcry_pk_fixup (gnutls_pk_algorithm_t algo,
 
800
                    gnutls_direction_t direction,
 
801
                    gnutls_pk_params_st * params)
 
802
{
 
803
  int ret, result;
 
804
 
 
805
  /* only for RSA we invert the coefficient --pgp type */
 
806
 
 
807
  if (algo != GNUTLS_PK_RSA)
 
808
    return 0;
 
809
 
 
810
  if (params->params[5] == NULL)
 
811
    params->params[5] =
 
812
      _gnutls_mpi_new (_gnutls_mpi_get_nbits (params->params[0]));
 
813
 
 
814
  if (params->params[5] == NULL)
 
815
    {
 
816
      gnutls_assert ();
 
817
      return GNUTLS_E_MEMORY_ERROR;
 
818
    }
 
819
 
 
820
  ret = 1;
 
821
  if (direction == GNUTLS_IMPORT)
 
822
    {
 
823
      /* calculate exp1 [6] and exp2 [7] */
 
824
      _gnutls_mpi_release (&params->params[6]);
 
825
      _gnutls_mpi_release (&params->params[7]);
 
826
      result = _gnutls_calc_rsa_exp (params->params, RSA_PRIVATE_PARAMS);
 
827
      if (result < 0)
 
828
        {
 
829
          gnutls_assert ();
 
830
          return result;
 
831
        }
 
832
 
 
833
      ret =
 
834
        gcry_mpi_invm (params->params[5], params->params[3],
 
835
                       params->params[4]);
 
836
 
 
837
      params->params_nr = RSA_PRIVATE_PARAMS;
 
838
    }
 
839
  else if (direction == GNUTLS_EXPORT)
 
840
    ret =
 
841
      gcry_mpi_invm (params->params[5], params->params[4], params->params[3]);
 
842
  if (ret == 0)
 
843
    {
 
844
      gnutls_assert ();
 
845
      return GNUTLS_E_INVALID_REQUEST;
 
846
    }
 
847
 
 
848
  return 0;
 
849
}
 
850
 
 
851
int crypto_pk_prio = INT_MAX;
 
852
 
 
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,
 
860
};