~ubuntu-branches/ubuntu/lucid/gnutls26/lucid-proposed

« back to all changes in this revision

Viewing changes to libextra/opencdk/pubkey.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Metzler
  • Date: 2008-06-24 19:13:25 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20080624191325-33rewwn0p11jzdvq
Tags: 2.4.0-2
* Standards version 3.8.0. Rename README.source_and_patches to README.source.
* Upload to unstable.
* Point watchfile to stable releases again.
* Merge experimental and unstable changelog.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* pubkey.c - Public key API
2
 
 *        Copyright (C) 2007 Free Software Foundation, Inc.
3
 
 *        Copyright (C) 2002, 2003, 2007 Timo Schulz
4
 
 *
5
 
 * This file is part of OpenCDK.
6
 
 *
7
 
 * OpenCDK is free software; you can redistribute it and/or modify
8
 
 * it under the terms of the GNU General Public License as published by
9
 
 * the Free Software Foundation; either version 2 of the License, or
10
 
 * (at your option) any later version.
11
 
 *
12
 
 * OpenCDK is distributed in the hope that it will be useful,
13
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 
 * GNU General Public License for more details.
16
 
 */
17
 
#ifdef HAVE_CONFIG_H
18
 
#include <config.h>
19
 
#endif
20
 
#include <stdio.h>
21
 
#include <gcrypt.h>
22
 
 
23
 
#include "opencdk.h"
24
 
#include "main.h"
25
 
#include "packet.h"
26
 
 
27
 
 
28
 
/* Convert the given secret key into a gcrypt SEXP object. */
29
 
static int
30
 
seckey_to_sexp (gcry_sexp_t *r_skey, cdk_seckey_t sk)
31
 
{
32
 
  gcry_sexp_t sexp = NULL;
33
 
  gcry_mpi_t *mpk = NULL, *msk = NULL;
34
 
  gcry_error_t err;
35
 
  cdk_pubkey_t pk;
36
 
  const char *fmt;
37
 
 
38
 
  if (!r_skey || !sk || !sk->pk)
39
 
    return CDK_Inv_Value;
40
 
 
41
 
  pk = sk->pk;
42
 
  mpk = pk->mpi;
43
 
  msk = sk->mpi;
44
 
  
45
 
  *r_skey = NULL;
46
 
  if (is_RSA (sk->pubkey_algo))
47
 
    {      
48
 
      fmt = "(private-key(openpgp-rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))";
49
 
      err = gcry_sexp_build (&sexp, NULL, fmt, mpk[0], mpk[1],
50
 
                             msk[0], msk[1], msk[2], msk[3]);      
51
 
    }
52
 
  else if (is_ELG (sk->pubkey_algo))
53
 
    {
54
 
      fmt = "(private-key(openpgp-elg(p%m)(g%m)(y%m)(x%m)))";
55
 
      err = gcry_sexp_build (&sexp, NULL, fmt, mpk[0], mpk[1],
56
 
                             mpk[2], msk[0]);
57
 
    }
58
 
  else if (is_DSA (sk->pubkey_algo))
59
 
    {
60
 
      fmt = "(private-key(openpgp-dsa(p%m)(q%m)(g%m)(y%m)(x%m)))";
61
 
      err = gcry_sexp_build (&sexp, NULL, fmt, mpk[0], mpk[1], mpk[2],
62
 
                             mpk[3], msk[0]);
63
 
    }
64
 
  else
65
 
    return CDK_Inv_Algo;
66
 
  if (err)
67
 
    return map_gcry_error (err);
68
 
  *r_skey = sexp;
69
 
  return 0;
70
 
}
71
 
 
72
 
 
73
 
/* Convert the given public key to a gcrypt SEXP object. */
74
 
static cdk_error_t
75
 
pubkey_to_sexp (gcry_sexp_t *r_key_sexp, cdk_pubkey_t pk)
76
 
{
77
 
  gcry_mpi_t *m;
78
 
  gcry_error_t err;
79
 
  const char *fmt = NULL;
80
 
  cdk_error_t rc = 0;
81
 
  
82
 
  if (!r_key_sexp || !pk)
83
 
    return CDK_Inv_Value;
84
 
 
85
 
  m = pk->mpi;
86
 
  if (is_RSA (pk->pubkey_algo))
87
 
    {
88
 
      fmt = "(public-key(openpgp-rsa(n%m)(e%m)))";
89
 
      err = gcry_sexp_build (r_key_sexp, NULL, fmt, m[0], m[1]);
90
 
      if (err)
91
 
        rc = map_gcry_error (err);
92
 
    }
93
 
  else if (is_ELG (pk->pubkey_algo)) 
94
 
    {
95
 
      fmt = "(public-key(openpgp-elg(p%m)(g%m)(y%m)))";
96
 
      err = gcry_sexp_build (r_key_sexp, NULL, fmt, m[0], m[1], m[2]);
97
 
      if (err)
98
 
        rc = map_gcry_error (err);
99
 
    }
100
 
  else if (is_DSA (pk->pubkey_algo)) 
101
 
    {
102
 
      fmt = "(public-key(openpgp-dsa(p%m)(q%m)(g%m)(y%m)))";
103
 
      err = gcry_sexp_build (r_key_sexp, NULL, fmt, m[0], m[1], m[2], m[3]);
104
 
      if (err)
105
 
        rc = map_gcry_error (err);
106
 
    }
107
 
  else
108
 
    rc = CDK_Inv_Algo;
109
 
  return rc;
110
 
}
111
 
 
112
 
 
113
 
static cdk_error_t
114
 
enckey_to_sexp (gcry_sexp_t *r_sexp, gcry_mpi_t esk)
115
 
{
116
 
  gcry_error_t err;
117
 
  
118
 
  if (!r_sexp || !esk)
119
 
    return CDK_Inv_Value;
120
 
  err = gcry_sexp_build (r_sexp, NULL, "%m", esk);
121
 
  if (err)
122
 
    return map_gcry_error (err);
123
 
  return 0;
124
 
}
125
 
 
126
 
 
127
 
static cdk_error_t
128
 
digest_to_sexp (gcry_sexp_t *r_md_sexp, int digest_algo, 
129
 
                const byte *md, size_t mdlen)
130
 
{
131
 
  gcry_mpi_t m;
132
 
  gcry_error_t err;
133
 
  
134
 
  if (!r_md_sexp || !md)
135
 
    return CDK_Inv_Value;
136
 
 
137
 
  if (!mdlen)
138
 
    mdlen = gcry_md_get_algo_dlen (digest_algo);
139
 
  if (!mdlen)
140
 
    return CDK_Inv_Algo;
141
 
  
142
 
  err = gcry_mpi_scan (&m, GCRYMPI_FMT_USG, md, mdlen, &mdlen);
143
 
  if (err)
144
 
    return map_gcry_error (err);
145
 
  
146
 
  err = gcry_sexp_build (r_md_sexp, NULL, "%m", m);
147
 
  gcry_mpi_release (m);
148
 
  if (err)
149
 
    return map_gcry_error (err);
150
 
  return 0;
151
 
}
152
 
 
153
 
 
154
 
static cdk_error_t
155
 
sexp_to_mpi (gcry_sexp_t sexp, const char *val, gcry_mpi_t *ret_buf)
156
 
{
157
 
  gcry_sexp_t list;
158
 
  
159
 
  if (!sexp || !val || !ret_buf)
160
 
    return CDK_Inv_Value;
161
 
  
162
 
  list = gcry_sexp_find_token (sexp, val, 0);
163
 
  if (!list)
164
 
    return CDK_Inv_Value;
165
 
  
166
 
  *ret_buf = gcry_sexp_nth_mpi (list, 1, 0);
167
 
  gcry_sexp_release (list);
168
 
  if (! *ret_buf)
169
 
    return CDK_Inv_Value;
170
 
  return 0;
171
 
}
172
 
 
173
 
 
174
 
static cdk_error_t
175
 
sexp_to_sig (cdk_pkt_signature_t sig, gcry_sexp_t sexp)
176
 
{
177
 
  if (!sig || !sexp)
178
 
    return CDK_Inv_Value;
179
 
 
180
 
  /* ElGamal signatures are not supported any longer. */
181
 
  if (is_ELG (sig->pubkey_algo))
182
 
    {
183
 
      _cdk_log_debug ("sexp_to_sig: unsupported signature type (ElGamal)\n");
184
 
      return CDK_Not_Implemented;
185
 
    }  
186
 
  
187
 
  if (is_RSA (sig->pubkey_algo))
188
 
    return sexp_to_mpi (sexp, "s", &sig->mpi[0]);
189
 
  else if (is_DSA (sig->pubkey_algo))
190
 
    {
191
 
      cdk_error_t rc;
192
 
      
193
 
      rc = sexp_to_mpi (sexp, "r", &sig->mpi[0]);
194
 
      if (!rc)
195
 
        rc = sexp_to_mpi (sexp, "s", &sig->mpi[1]);
196
 
      return rc;
197
 
    }
198
 
  return CDK_Inv_Algo;
199
 
}
200
 
 
201
 
 
202
 
static cdk_error_t
203
 
sig_to_sexp (gcry_sexp_t *r_sig_sexp, cdk_pkt_signature_t sig)
204
 
{
205
 
  gcry_error_t err;
206
 
  cdk_error_t rc;
207
 
  const char *fmt;
208
 
  
209
 
  if (!r_sig_sexp || !sig)
210
 
    return CDK_Inv_Value;  
211
 
  if (is_ELG (sig->pubkey_algo))
212
 
    return CDK_Not_Implemented;
213
 
  
214
 
  rc = 0;
215
 
  if (is_RSA (sig->pubkey_algo)) 
216
 
    {
217
 
      fmt = "(sig-val(openpgp-rsa(s%m)))";
218
 
      err = gcry_sexp_build (r_sig_sexp, NULL, fmt, sig->mpi[0]);
219
 
      if (err)
220
 
        rc = map_gcry_error (err);
221
 
    }
222
 
  else if (is_DSA (sig->pubkey_algo))
223
 
    {
224
 
      fmt = "(sig-val(openpgp-dsa(r%m)(s%m)))";
225
 
      err = gcry_sexp_build (r_sig_sexp, NULL, fmt, sig->mpi[0], sig->mpi[1]);
226
 
      if (err)
227
 
        rc = map_gcry_error (err);
228
 
    }
229
 
  else
230
 
    rc = CDK_Inv_Algo;
231
 
  return rc;
232
 
}
233
 
 
234
 
 
235
 
static cdk_error_t
236
 
sexp_to_pubenc (cdk_pkt_pubkey_enc_t enc, gcry_sexp_t sexp)
237
 
{
238
 
  if (!sexp || !enc)
239
 
    return CDK_Inv_Value;
240
 
  
241
 
  if (is_RSA (enc->pubkey_algo))
242
 
    return sexp_to_mpi (sexp, "a", &enc->mpi[0]);
243
 
  else if (is_ELG (enc->pubkey_algo))
244
 
    {
245
 
      cdk_error_t rc = sexp_to_mpi (sexp, "a", &enc->mpi[0]);
246
 
      if (!rc)
247
 
        rc = sexp_to_mpi (sexp, "b", &enc->mpi[1]);
248
 
      return rc;
249
 
    }
250
 
  return CDK_Inv_Algo;
251
 
}
252
 
 
253
 
 
254
 
static cdk_error_t
255
 
pubenc_to_sexp (gcry_sexp_t * r_sexp, cdk_pkt_pubkey_enc_t enc)
256
 
{
257
 
  gcry_sexp_t sexp = NULL;
258
 
  gcry_error_t err;
259
 
  const char *fmt;
260
 
  
261
 
  if (!r_sexp || !enc)
262
 
    return CDK_Inv_Value;
263
 
  
264
 
  *r_sexp = NULL;
265
 
  if (is_RSA (enc->pubkey_algo))
266
 
    {
267
 
      fmt = "(enc-val(openpgp-rsa((a%m))))";
268
 
      err = gcry_sexp_build (&sexp, NULL, fmt, enc->mpi[0]);
269
 
    }
270
 
  else if (is_ELG (enc->pubkey_algo))
271
 
    {
272
 
      fmt = "(enc-val(openpgp-elg((a%m)(b%m))))";
273
 
      err = gcry_sexp_build (&sexp, NULL, fmt, enc->mpi[0], enc->mpi[1]);      
274
 
    }
275
 
  else
276
 
    return CDK_Inv_Algo;
277
 
  if (err)
278
 
    return map_gcry_error (err);
279
 
  *r_sexp = sexp;
280
 
  return 0;
281
 
}
282
 
 
283
 
 
284
 
static int
285
 
is_unprotected (cdk_seckey_t sk)
286
 
{
287
 
  if (sk->is_protected && !sk->mpi[0])
288
 
    return 0;
289
 
  return 1;
290
 
}
291
 
 
292
 
 
293
 
/**
294
 
 * cdk_pk_encrypt:
295
 
 * @pk: the public key
296
 
 * @pke: the public key encrypted packet
297
 
 * @esk: the actual session key
298
 
 *
299
 
 * Encrypt the session key in @esk and write its encrypted content
300
 
 * into the @pke struct.
301
 
 **/
302
 
cdk_error_t
303
 
cdk_pk_encrypt (cdk_pubkey_t pk, cdk_pkt_pubkey_enc_t pke,
304
 
                gcry_mpi_t esk)
305
 
{
306
 
  gcry_sexp_t s_data = NULL, s_pkey = NULL, s_ciph = NULL;
307
 
  gcry_error_t err;
308
 
  cdk_error_t rc;
309
 
  
310
 
  if (!pk || !esk || !pke)
311
 
    return CDK_Inv_Value;
312
 
  
313
 
  if (!KEY_CAN_ENCRYPT (pk->pubkey_algo))
314
 
    return CDK_Inv_Algo;
315
 
 
316
 
  rc = enckey_to_sexp (&s_data, esk);
317
 
  if (!rc)
318
 
    rc = pubkey_to_sexp (&s_pkey, pk);
319
 
  if (!rc)
320
 
    {     
321
 
      err = gcry_pk_encrypt (&s_ciph, s_data, s_pkey);
322
 
      if (err)
323
 
        return map_gcry_error (err);
324
 
    }
325
 
  if (!rc)
326
 
    rc = sexp_to_pubenc (pke, s_ciph);
327
 
  
328
 
  gcry_sexp_release (s_data);
329
 
  gcry_sexp_release (s_pkey);
330
 
  gcry_sexp_release (s_ciph);
331
 
  return rc;
332
 
}
333
 
 
334
 
 
335
 
/**
336
 
 * cdk_pk_decrypt:
337
 
 * @sk: the secret key
338
 
 * @pke: public key encrypted packet
339
 
 * @r_sk: the object to store the plain session key
340
 
 *
341
 
 * Decrypt the encrypted session key from @pke into @r_sk.
342
 
 **/
343
 
cdk_error_t
344
 
cdk_pk_decrypt (cdk_seckey_t sk, cdk_pkt_pubkey_enc_t pke,
345
 
                gcry_mpi_t *r_sk)
346
 
{
347
 
  gcry_sexp_t s_data = NULL, s_skey = NULL, s_plain = NULL;
348
 
  cdk_error_t rc;
349
 
  gcry_error_t err;
350
 
  
351
 
  if (!sk || !r_sk || !pke)
352
 
    return CDK_Inv_Value;
353
 
  
354
 
  if (!is_unprotected (sk))
355
 
    return CDK_Inv_Mode;
356
 
  
357
 
  *r_sk = NULL;
358
 
  rc = seckey_to_sexp (&s_skey, sk);
359
 
  if (rc)
360
 
    return rc;
361
 
 
362
 
  rc = pubenc_to_sexp (&s_data, pke);
363
 
  if (rc)
364
 
    {
365
 
      gcry_sexp_release (s_skey);
366
 
      return rc;
367
 
    }
368
 
  
369
 
  err = gcry_pk_decrypt (&s_plain, s_data, s_skey);
370
 
  if (err)
371
 
    rc = map_gcry_error (err);
372
 
  else
373
 
    *r_sk  = gcry_sexp_nth_mpi (s_plain, 0, 0);
374
 
 
375
 
  gcry_sexp_release (s_data);
376
 
  gcry_sexp_release (s_skey);
377
 
  gcry_sexp_release (s_plain);
378
 
  return rc;
379
 
}
380
 
 
381
 
 
382
 
/**
383
 
 * cdk_pk_sign:
384
 
 * @sk: secret key
385
 
 * @sig: signature
386
 
 * @md: the message digest
387
 
 *
388
 
 * Sign the message digest from @md and write the result into @sig.
389
 
 **/
390
 
cdk_error_t
391
 
cdk_pk_sign (cdk_seckey_t sk, cdk_pkt_signature_t sig, const byte *md)
392
 
{
393
 
  gcry_sexp_t s_skey = NULL, s_sig = NULL, s_hash = NULL;
394
 
  byte *encmd = NULL;
395
 
  size_t enclen = 0;
396
 
  int nbits;
397
 
  cdk_error_t rc;
398
 
  gcry_error_t err;
399
 
  
400
 
  if (!sk || !sk->pk || !sig || !md)
401
 
    return CDK_Inv_Value;
402
 
  
403
 
  if (!is_unprotected (sk))
404
 
    return CDK_Inv_Mode;
405
 
  
406
 
  if (!KEY_CAN_SIGN (sig->pubkey_algo))
407
 
    return CDK_Inv_Algo;
408
 
  
409
 
  nbits = cdk_pk_get_nbits (sk->pk);
410
 
  rc = _cdk_digest_encode_pkcs1 (&encmd, &enclen, sk->pk->pubkey_algo, md,
411
 
                                 sig->digest_algo, nbits);
412
 
  if (rc)
413
 
    return rc;
414
 
 
415
 
  rc = seckey_to_sexp (&s_skey, sk);
416
 
  if (!rc)
417
 
    rc = digest_to_sexp (&s_hash, sig->digest_algo, encmd, enclen);
418
 
  if (rc)
419
 
    {
420
 
      cdk_free (encmd);
421
 
      gcry_sexp_release (s_skey);
422
 
      return rc;
423
 
    }  
424
 
  
425
 
  err = gcry_pk_sign (&s_sig, s_hash, s_skey);
426
 
  if (err)
427
 
    rc = map_gcry_error (err);
428
 
  else
429
 
    {      
430
 
      rc = sexp_to_sig (sig, s_sig);
431
 
      if (!rc)
432
 
        {
433
 
          sig->digest_start[0] = md[0];
434
 
          sig->digest_start[1] = md[1];
435
 
        }
436
 
    }
437
 
  
438
 
  gcry_sexp_release (s_skey);
439
 
  gcry_sexp_release (s_hash);
440
 
  gcry_sexp_release (s_sig);
441
 
  cdk_free (encmd);
442
 
  return rc;
443
 
}
444
 
 
445
 
 
446
 
/**
447
 
 * cdk_pk_verify:
448
 
 * @pk: the public key
449
 
 * @sig: signature
450
 
 * @md: the message digest
451
 
 *
452
 
 * Verify the signature in @sig and compare it with the message digest in @md.
453
 
 **/
454
 
cdk_error_t
455
 
cdk_pk_verify (cdk_pubkey_t pk, cdk_pkt_signature_t sig, const byte *md)
456
 
{
457
 
  gcry_sexp_t s_pkey = NULL, s_sig = NULL, s_hash = NULL;
458
 
  byte *encmd = NULL;
459
 
  size_t enclen;
460
 
  cdk_error_t rc;
461
 
  
462
 
  if (!pk || !sig || !md)
463
 
    return CDK_Inv_Value;
464
 
  
465
 
  rc = pubkey_to_sexp (&s_pkey, pk);
466
 
  if (rc)
467
 
    return rc;
468
 
  
469
 
  rc = sig_to_sexp (&s_sig, sig);
470
 
  if (rc)
471
 
    goto leave;
472
 
  
473
 
  rc = _cdk_digest_encode_pkcs1 (&encmd, &enclen, pk->pubkey_algo, md,
474
 
                                 sig->digest_algo, cdk_pk_get_nbits (pk));
475
 
  if (rc)
476
 
    goto leave;
477
 
  
478
 
  rc = digest_to_sexp (&s_hash, sig->digest_algo, encmd, enclen);
479
 
  if (rc)
480
 
    goto leave;
481
 
  
482
 
  if (gcry_pk_verify (s_sig, s_hash, s_pkey))
483
 
    rc = CDK_Bad_Sig;
484
 
 
485
 
  leave:
486
 
  gcry_sexp_release (s_sig);
487
 
  gcry_sexp_release (s_hash);
488
 
  gcry_sexp_release (s_pkey);
489
 
  cdk_free (encmd);
490
 
  return rc;
491
 
}
492
 
 
493
 
 
494
 
/**
495
 
 * cdk_pk_get_nbits:
496
 
 * @pk: the public key
497
 
 * 
498
 
 * Return the length of the public key in bits.
499
 
 * The meaning of length is actually the size of the 'prime'
500
 
 * object in the key. For RSA keys the modulus, for ElG/DSA
501
 
 * the size of the public prime.
502
 
 **/
503
 
int
504
 
cdk_pk_get_nbits (cdk_pubkey_t pk)
505
 
{
506
 
  if (!pk || !pk->mpi[0])
507
 
    return 0;
508
 
  return gcry_mpi_get_nbits (pk->mpi[0]);
509
 
}
510
 
 
511
 
 
512
 
/**
513
 
 * cdk_pk_get_npkey:
514
 
 * @algo: The public key algorithm.
515
 
 * 
516
 
 * Return the number of multiprecison integer forming an public
517
 
 * key with the given algorithm.
518
 
 */
519
 
int
520
 
cdk_pk_get_npkey (int algo)
521
 
{
522
 
  size_t bytes;
523
 
  
524
 
  if (algo == 16)
525
 
    algo = 20; /* FIXME: libgcrypt returns 0 for 16 */
526
 
  if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NPKEY, NULL, &bytes))
527
 
    return 0;  
528
 
  return bytes;
529
 
}
530
 
 
531
 
 
532
 
/**
533
 
 * cdk_pk_get_nskey:
534
 
 * @algo: the public key algorithm
535
 
 * 
536
 
 * Return the number of multiprecision integers forming an
537
 
 * secret key with the given algorithm.
538
 
 **/
539
 
int
540
 
cdk_pk_get_nskey (int algo)
541
 
{  
542
 
  size_t bytes;
543
 
  
544
 
  if (gcry_pk_algo_info (algo, GCRYCTL_GET_ALGO_NSKEY, NULL, &bytes))
545
 
    return 0;  
546
 
  bytes -= cdk_pk_get_npkey (algo);
547
 
  return bytes;  
548
 
}
549
 
 
550
 
 
551
 
/**
552
 
 * cdk_pk_get_nbits:
553
 
 * @algo: the public key algorithm
554
 
 * 
555
 
 * Return the number of MPIs a signature consists of.
556
 
 **/
557
 
int
558
 
cdk_pk_get_nsig (int algo)
559
 
{
560
 
  size_t bytes;
561
 
  
562
 
  if (gcry_pk_algo_info (algo, GCRYCTL_GET_ALGO_NSIGN, NULL, &bytes))
563
 
    return 0;
564
 
  return bytes;  
565
 
}
566
 
 
567
 
 
568
 
/**
569
 
 * cdk_pk_get_nenc: 
570
 
 * @algo: the public key algorithm
571
 
 * 
572
 
 * Return the number of MPI's the encrypted data consists of.
573
 
 **/
574
 
int
575
 
cdk_pk_get_nenc (int algo)
576
 
{
577
 
  size_t bytes;
578
 
  
579
 
  if (gcry_pk_algo_info (algo, GCRYCTL_GET_ALGO_NENCR, NULL, &bytes))
580
 
    return 0;
581
 
  return bytes;  
582
 
}
583
 
 
584
 
 
585
 
int
586
 
_cdk_pk_algo_usage (int algo)
587
 
{
588
 
  int usage;
589
 
 
590
 
  /* The ElGamal sign+encrypt algorithm is not supported any longer. */
591
 
  switch (algo)
592
 
    {
593
 
    case CDK_PK_RSA  : usage = CDK_KEY_USG_SIGN | CDK_KEY_USG_ENCR; break;
594
 
    case CDK_PK_RSA_E: usage = CDK_KEY_USG_ENCR; break;
595
 
    case CDK_PK_RSA_S: usage = CDK_KEY_USG_SIGN; break;
596
 
    case CDK_PK_ELG_E: usage = CDK_KEY_USG_ENCR; break;
597
 
    case CDK_PK_DSA  : usage = CDK_KEY_USG_SIGN; break;
598
 
    default: usage = 0;
599
 
    }
600
 
  return usage;  
601
 
}
602
 
 
603
 
 
604
 
static cdk_error_t
605
 
mpi_to_buffer (gcry_mpi_t a, byte *buf, size_t buflen,
606
 
               size_t *r_nwritten, size_t *r_nbits)
607
 
{
608
 
  size_t nbits;
609
 
  
610
 
  if (!a || !buf || !r_nwritten)
611
 
    return CDK_Inv_Value;
612
 
  
613
 
  nbits = gcry_mpi_get_nbits (a);
614
 
  if (r_nbits)
615
 
    *r_nbits = nbits;
616
 
  if ((nbits+7)/8+2 > buflen)
617
 
    return CDK_Too_Short;
618
 
  *r_nwritten = (nbits+7)/8+2;
619
 
  if (gcry_mpi_print (GCRYMPI_FMT_PGP, buf, buflen, r_nwritten, a))
620
 
    return CDK_Wrong_Format;
621
 
  return 0;
622
 
}
623
 
 
624
 
 
625
 
/**
626
 
 * cdk_pk_get_mpi:
627
 
 * @pk: public key
628
 
 * @idx: index of the MPI to retrieve
629
 
 * @buf: buffer to hold the raw data
630
 
 * @r_nwritten: output how large the raw data is
631
 
 * @r_nbits: size of the MPI in bits.
632
 
 * 
633
 
 * Return the MPI with the given index of the public key.
634
 
 **/
635
 
cdk_error_t
636
 
cdk_pk_get_mpi (cdk_pubkey_t pk, size_t idx,
637
 
                byte *buf, size_t buflen, size_t *r_nwritten, size_t *r_nbits)
638
 
{
639
 
  if (!pk || !r_nwritten)
640
 
    return CDK_Inv_Value;
641
 
  if (idx > cdk_pk_get_npkey (pk->pubkey_algo))
642
 
    return CDK_Inv_Value;
643
 
  return mpi_to_buffer (pk->mpi[idx], buf, buflen, r_nwritten, r_nbits);
644
 
}
645
 
 
646
 
 
647
 
/**
648
 
 * cdk_sk_get_mpi:
649
 
 * @sk: secret key
650
 
 * @idx: index of the MPI to retrieve
651
 
 * @buf: buffer to hold the raw data
652
 
 * @r_nwritten: output length of the raw data
653
 
 * @r_nbits: length of the MPI data in bits.
654
 
 * 
655
 
 * Return the MPI of the given secret key with the
656
 
 * index @idx. It is important to check if the key
657
 
 * is protected and thus no real MPI data will be returned then.
658
 
 **/
659
 
cdk_error_t
660
 
cdk_sk_get_mpi (cdk_pkt_seckey_t sk, size_t idx,
661
 
                byte *buf, size_t buflen, size_t *r_nwritten, size_t *r_nbits)
662
 
{
663
 
  if (!sk || !r_nwritten)
664
 
    return CDK_Inv_Value;
665
 
  if (idx > cdk_pk_get_nskey (sk->pubkey_algo))
666
 
    return CDK_Inv_Value;
667
 
  return mpi_to_buffer (sk->mpi[idx], buf, buflen, r_nwritten, r_nbits);
668
 
}
669
 
 
670
 
 
671
 
static u16
672
 
checksum_mpi (gcry_mpi_t m)
673
 
{
674
 
  byte buf[MAX_MPI_BYTES+2];
675
 
  size_t nread;
676
 
  int i;
677
 
  u16 chksum = 0;
678
 
 
679
 
  if (!m)
680
 
    return 0;
681
 
  if (gcry_mpi_print (GCRYMPI_FMT_PGP, buf, DIM (buf), &nread, m))
682
 
    return 0;
683
 
  for (i=0; i < nread; i++)
684
 
    chksum += buf[i];
685
 
  return chksum;
686
 
}
687
 
 
688
 
 
689
 
/**
690
 
 * cdk_sk_unprotect:
691
 
 * @sk: the secret key
692
 
 * @pw: the passphrase
693
 
 * 
694
 
 * Unprotect the given secret key with the passphrase.
695
 
 **/
696
 
cdk_error_t
697
 
cdk_sk_unprotect (cdk_pkt_seckey_t sk, const char *pw)
698
 
{
699
 
  gcry_cipher_hd_t hd;
700
 
  cdk_dek_t dek = NULL;
701
 
  byte *data = NULL;
702
 
  u16 chksum = 0;
703
 
  size_t ndata, nbits, nbytes;
704
 
  int i, dlen, pos = 0, nskey;
705
 
  cdk_error_t rc;
706
 
  gcry_error_t err;
707
 
  
708
 
  if (!sk)
709
 
    return CDK_Inv_Value;
710
 
  
711
 
  nskey = cdk_pk_get_nskey (sk->pubkey_algo);
712
 
  if (!sk->is_protected)
713
 
    {
714
 
      chksum = 0;
715
 
      for (i = 0; i < nskey; i++)
716
 
        chksum += checksum_mpi (sk->mpi[i]);
717
 
      if (chksum != sk->csum)
718
 
        return CDK_Chksum_Error;
719
 
    } 
720
 
      
721
 
  rc = cdk_dek_from_passphrase (&dek, sk->protect.algo,
722
 
                                sk->protect.s2k, 0, pw);
723
 
  if (rc)
724
 
    return rc;
725
 
  err = gcry_cipher_open (&hd, sk->protect.algo, GCRY_CIPHER_MODE_CFB, 
726
 
                          GCRY_CIPHER_ENABLE_SYNC);
727
 
  if (!err)
728
 
    err = gcry_cipher_setiv (hd, sk->protect.iv, sk->protect.ivlen);
729
 
  if (!err)
730
 
    err = gcry_cipher_setkey (hd, dek->key, dek->keylen);
731
 
  if (err)
732
 
    {
733
 
      cdk_free (dek);
734
 
      return map_gcry_error (err);
735
 
    }
736
 
  cdk_dek_free (dek);
737
 
  chksum = 0;
738
 
  if (sk->version == 4) 
739
 
    {
740
 
      ndata = sk->enclen;
741
 
      data = cdk_salloc (ndata, 1);
742
 
      if (!data)
743
 
        return CDK_Out_Of_Core;
744
 
      gcry_cipher_decrypt (hd, data, ndata, sk->encdata, ndata);
745
 
      if (sk->protect.sha1chk) 
746
 
        {
747
 
          /* This is the new SHA1 checksum method to detect tampering
748
 
             with the key as used by the Klima/Rosa attack */
749
 
          sk->csum = 0;
750
 
          chksum = 1;
751
 
          dlen = gcry_md_get_algo_dlen (GCRY_MD_SHA1);
752
 
          if (ndata < dlen) 
753
 
            {
754
 
              cdk_free (data);
755
 
              return CDK_Inv_Packet;
756
 
            }
757
 
          else 
758
 
            {
759
 
              byte mdcheck[20];
760
 
              
761
 
              gcry_md_hash_buffer (GCRY_MD_SHA1, 
762
 
                                   mdcheck, data, ndata-dlen);
763
 
              if (!memcmp (mdcheck, data + ndata - dlen, dlen))
764
 
                chksum = 0;     /* Digest does match */
765
 
            }
766
 
        }
767
 
      else 
768
 
        {
769
 
          for (i = 0; i < ndata - 2; i++)
770
 
            chksum += data[i];
771
 
          sk->csum = data[ndata - 2] << 8 | data[ndata - 1];
772
 
        }
773
 
      if (sk->csum == chksum) 
774
 
        {
775
 
          for (i = 0; i < nskey; i++) 
776
 
            {
777
 
              nbits = data[pos] << 8 | data[pos + 1];
778
 
              
779
 
              if (gcry_mpi_scan (&sk->mpi[i], GCRYMPI_FMT_PGP, data,
780
 
                             (nbits+7)/8+2, &nbytes))
781
 
                {
782
 
                  wipemem (data, sk->enclen);
783
 
                  cdk_free (data);
784
 
                  return CDK_Wrong_Format;
785
 
                }            
786
 
              gcry_mpi_set_flag (sk->mpi[i], GCRYMPI_FLAG_SECURE);
787
 
              pos += (nbits+7)/8+2;
788
 
            }
789
 
        }
790
 
      wipemem (data, sk->enclen);
791
 
      cdk_free (data);
792
 
    }
793
 
  else 
794
 
    {
795
 
      byte buf[MAX_MPI_BYTES+2];
796
 
      
797
 
      chksum = 0;
798
 
      for (i = 0; i < nskey; i++)
799
 
        {
800
 
          gcry_cipher_sync (hd);
801
 
          gcry_mpi_print (GCRYMPI_FMT_PGP, buf, DIM (buf), 
802
 
                          &nbytes, sk->mpi[i]);
803
 
          gcry_cipher_decrypt (hd, buf+2, nbytes-2, NULL, 0);
804
 
          gcry_mpi_release (sk->mpi[i]);
805
 
          if (gcry_mpi_scan (&sk->mpi[i], GCRYMPI_FMT_PGP,
806
 
                             buf, nbytes, &nbytes))
807
 
            return CDK_Wrong_Format;
808
 
          chksum += checksum_mpi (sk->mpi[i]);
809
 
        }
810
 
    }
811
 
  gcry_cipher_close (hd);
812
 
  if (chksum != sk->csum)
813
 
    return CDK_Chksum_Error;
814
 
  sk->is_protected = 0;
815
 
  return 0;
816
 
}
817
 
 
818
 
 
819
 
/**
820
 
 * cdk_sk_protect:
821
 
 * @sk: the secret key
822
 
 * @pw: the passphrase to use
823
 
 * 
824
 
 * Protect the given secret key with a passphrase.
825
 
 **/
826
 
cdk_error_t
827
 
cdk_sk_protect (cdk_pkt_seckey_t sk, const char *pw)
828
 
{
829
 
  gcry_cipher_hd_t hd = NULL;
830
 
  cdk_dek_t dek = NULL;
831
 
  cdk_s2k_t s2k;
832
 
  byte *p = NULL, buf[MAX_MPI_BYTES+2];
833
 
  size_t enclen = 0, nskey, i, nbytes;
834
 
  size_t dlen = gcry_md_get_algo_dlen (GCRY_MD_SHA1);
835
 
  gcry_error_t err;
836
 
  cdk_error_t rc;
837
 
  
838
 
  nskey = cdk_pk_get_nskey (sk->pubkey_algo);
839
 
  if (!nskey)
840
 
    return CDK_Inv_Algo;
841
 
  
842
 
  rc = cdk_s2k_new (&s2k, CDK_S2K_ITERSALTED, GCRY_MD_SHA256, NULL);
843
 
  if (!rc)
844
 
    rc = cdk_dek_from_passphrase (&dek, GCRY_CIPHER_AES, s2k, 1, pw);
845
 
  if (rc) 
846
 
    {
847
 
      cdk_s2k_free (s2k);
848
 
      return rc;
849
 
    }
850
 
  
851
 
  for (i = 0; i < nskey; i++)
852
 
    {
853
 
      enclen += 2;
854
 
      enclen += (gcry_mpi_get_nbits (sk->mpi[i])+7)/8;
855
 
    }
856
 
  p = sk->encdata = cdk_calloc (1, enclen + dlen + 1);
857
 
  if (!p)
858
 
    {
859
 
      cdk_s2k_free (s2k);
860
 
      return CDK_Out_Of_Core;
861
 
    }
862
 
  
863
 
  enclen = 0;
864
 
  for (i = 0; i < nskey; i++) 
865
 
    {
866
 
      if (gcry_mpi_print (GCRYMPI_FMT_PGP, buf, 
867
 
                          DIM (buf), &nbytes, sk->mpi[i]))
868
 
        {
869
 
          cdk_free (p);
870
 
          cdk_s2k_free (s2k);
871
 
          return CDK_Wrong_Format;
872
 
        }     
873
 
      memcpy (p + enclen, buf, nbytes);
874
 
      enclen += nbytes;
875
 
    }
876
 
  
877
 
  enclen += dlen;
878
 
  sk->enclen = enclen;
879
 
  sk->protect.s2k = s2k;
880
 
  sk->protect.algo = GCRY_CIPHER_AES;
881
 
  sk->protect.ivlen = gcry_cipher_get_algo_blklen (sk->protect.algo);
882
 
  gcry_randomize (sk->protect.iv, sk->protect.ivlen, GCRY_STRONG_RANDOM);
883
 
  err = gcry_cipher_open (&hd, sk->protect.algo, GCRY_CIPHER_MODE_CFB, 
884
 
                          GCRY_CIPHER_ENABLE_SYNC);
885
 
  if (err)
886
 
    {
887
 
      cdk_dek_free (dek);
888
 
      rc = map_gcry_error (err);
889
 
      goto leave;
890
 
    }
891
 
  
892
 
  err = gcry_cipher_setkey (hd, dek->key, dek->keylen);
893
 
  if (!err)
894
 
    err = gcry_cipher_setiv (hd, sk->protect.iv, sk->protect.ivlen);
895
 
  cdk_dek_free (dek);
896
 
  if (err)
897
 
    {
898
 
      rc = map_gcry_error (err);
899
 
      goto leave;
900
 
    }
901
 
  
902
 
  sk->protect.sha1chk = 1;
903
 
  sk->is_protected = 1;
904
 
  sk->csum = 0;
905
 
  
906
 
  gcry_md_hash_buffer (GCRY_MD_SHA1, buf, p, enclen-dlen);
907
 
  memcpy (p + enclen - dlen, buf, dlen);
908
 
  gcry_cipher_encrypt (hd, p, enclen, NULL, 0);
909
 
  
910
 
  /* FIXME: We should release all MPI's and set the elements to NULL. */
911
 
  
912
 
  leave:
913
 
  gcry_cipher_close (hd);
914
 
  return rc;
915
 
}
916
 
 
917
 
 
918
 
/**
919
 
 * cdk_pk_from_secret_key:
920
 
 * @sk: the secret key
921
 
 * @ret_pk: the new public key
922
 
 *
923
 
 * Create a new public key from a secret key.
924
 
 **/
925
 
cdk_error_t
926
 
cdk_pk_from_secret_key (cdk_pkt_seckey_t sk, cdk_pubkey_t *ret_pk)
927
 
{
928
 
  if (!sk)
929
 
    return CDK_Inv_Value;
930
 
  return _cdk_copy_pubkey (ret_pk, sk->pk);
931
 
}
932
 
 
933
 
 
934
 
#if 0 /* FIXME: Code is not finished yet. */
935
 
cdk_error_t
936
 
cdk_pk_revoke_cert_create (cdk_pkt_seckey_t sk, int code, const char *inf,
937
 
                           char **ret_revcert)
938
 
{
939
 
  gcry_md_hd_t md;
940
 
  cdk_subpkt_t node;
941
 
  cdk_pkt_signature_t sig;
942
 
  char *p = NULL, *dat;
943
 
  gcry_error_t err;
944
 
  cdk_error_t rc = 0;
945
 
  size_t n;
946
 
  
947
 
  if (!sk || !ret_revcert)
948
 
    return CDK_Inv_Value;
949
 
  if(code < 0 || code > 3)
950
 
    return CDK_Inv_Value;
951
 
  
952
 
  sig = cdk_calloc (1, sizeof *sig);
953
 
  if (!sig)
954
 
    return CDK_Out_Of_Core;
955
 
  _cdk_sig_create (sk->pk, sig);
956
 
  n = 1;
957
 
  if (inf) 
958
 
    {
959
 
      n += strlen (p);
960
 
      p = cdk_utf8_encode (inf);
961
 
    }
962
 
  dat = cdk_calloc (1, n+1);
963
 
  if (!dat)
964
 
    {
965
 
      _cdk_free_signature (sig);
966
 
      return CDK_Out_Of_Core;
967
 
    }
968
 
  dat[0] = code;
969
 
  if (inf)
970
 
    memcpy (dat+1, p, strlen (p));
971
 
  cdk_free (p);
972
 
  
973
 
  node = cdk_subpkt_new (n);
974
 
  if (node)
975
 
    {
976
 
      cdk_subpkt_init (node, CDK_SIGSUBPKT_REVOC_REASON, dat, n);
977
 
      cdk_subpkt_add (sig->hashed, node);
978
 
    }
979
 
  cdk_free (dat);
980
 
  
981
 
  err = gcry_md_open (&md, GCRY_MD_SHA1, 0);
982
 
  if (err)
983
 
    rc = map_gcry_error (err);
984
 
  else
985
 
    _cdk_hash_pubkey (sk->pk, md, 0);
986
 
  _cdk_free_signature (sig);
987
 
  
988
 
  return rc;
989
 
}
990
 
#endif
991
 
 
992
 
int
993
 
_cdk_sk_get_csum (cdk_pkt_seckey_t sk)
994
 
{
995
 
  u16 csum = 0, i;
996
 
  
997
 
  if (!sk)
998
 
    return 0;
999
 
  for (i = 0; i < cdk_pk_get_nskey (sk->pubkey_algo); i++)
1000
 
    csum += checksum_mpi (sk->mpi[i]);
1001
 
  return csum;
1002
 
}
1003
 
 
1004
 
 
1005
 
/**
1006
 
 * cdk_pk_get_fingerprint:
1007
 
 * @pk: the public key
1008
 
 * @fpr: the buffer to hold the fingerprint
1009
 
 * 
1010
 
 * Return the fingerprint of the given public key.
1011
 
 * The buffer must be at least 20 octets.
1012
 
 * This function should be considered deprecated and
1013
 
 * the new cdk_pk_to_fingerprint() should be used whenever
1014
 
 * possible to avoid overflows.
1015
 
 **/
1016
 
cdk_error_t
1017
 
cdk_pk_get_fingerprint (cdk_pubkey_t pk, byte *fpr)
1018
 
{
1019
 
  gcry_md_hd_t hd;
1020
 
  int md_algo;
1021
 
  int dlen = 0;
1022
 
  gcry_error_t err;
1023
 
 
1024
 
  if (!pk || !fpr)
1025
 
    return CDK_Inv_Value;
1026
 
  
1027
 
  if (pk->version < 4 && is_RSA (pk->pubkey_algo))
1028
 
    md_algo = GCRY_MD_MD5; /* special */
1029
 
  else
1030
 
    md_algo = GCRY_MD_SHA1;
1031
 
  dlen = gcry_md_get_algo_dlen (md_algo);
1032
 
  err = gcry_md_open (&hd, md_algo, 0);
1033
 
  if (err)
1034
 
    return map_gcry_error (err);
1035
 
  _cdk_hash_pubkey (pk, hd, 1);
1036
 
  gcry_md_final (hd);
1037
 
  memcpy (fpr, gcry_md_read (hd, md_algo), dlen);
1038
 
  gcry_md_close (hd);
1039
 
  if (dlen == 16)
1040
 
    memset (fpr + 16, 0, 4);
1041
 
  return 0;
1042
 
}
1043
 
 
1044
 
 
1045
 
/**
1046
 
 * cdk_pk_to_fingerprint:
1047
 
 * @pk: the public key
1048
 
 * @fprbuf: buffer to save the fingerprint
1049
 
 * @fprbuflen: buffer size
1050
 
 * @r_nout: actual length of the fingerprint.
1051
 
 * 
1052
 
 * Calculate a fingerprint of the given key and
1053
 
 * return it in the given byte array.
1054
 
 **/
1055
 
cdk_error_t
1056
 
cdk_pk_to_fingerprint (cdk_pubkey_t pk, 
1057
 
                       byte *fprbuf, size_t fprbuflen, size_t *r_nout)
1058
 
{
1059
 
  size_t key_fprlen;
1060
 
  cdk_error_t err;
1061
 
  
1062
 
  if (!pk)
1063
 
    return CDK_Inv_Value;
1064
 
    
1065
 
  if (pk->version < 4)
1066
 
    key_fprlen = 16;
1067
 
  else
1068
 
    key_fprlen = 20;
1069
 
  
1070
 
  /* Only return the required buffer size for the fingerprint. */
1071
 
  if (!fprbuf && !fprbuflen && r_nout)
1072
 
    {      
1073
 
      *r_nout = key_fprlen;
1074
 
      return 0;
1075
 
    }
1076
 
  
1077
 
  if (!fprbuf || key_fprlen > fprbuflen)
1078
 
    return CDK_Too_Short;
1079
 
 
1080
 
  err = cdk_pk_get_fingerprint (pk, fprbuf);
1081
 
  if (r_nout)
1082
 
    *r_nout = key_fprlen;
1083
 
  
1084
 
  return err;
1085
 
}
1086
 
 
1087
 
 
1088
 
/**
1089
 
 * cdk_pk_fingerprint_get_keyid:
1090
 
 * @fpr: the key fingerprint
1091
 
 * @fprlen: the length of the fingerprint
1092
 
 * 
1093
 
 * Derive the key ID from the key fingerprint.
1094
 
 * For version 3 keys, this is not working.
1095
 
 **/
1096
 
u32
1097
 
cdk_pk_fingerprint_get_keyid (const byte *fpr, size_t fprlen, u32 *keyid)
1098
 
{
1099
 
    u32 lowbits = 0;
1100
 
 
1101
 
  /* In this case we say the key is a V3 RSA key and we can't
1102
 
     use the fingerprint to get the keyid. */
1103
 
  if (fpr && fprlen == 16)
1104
 
    {
1105
 
      keyid[0] = 0;
1106
 
      keyid[1] = 0;
1107
 
      return 0;
1108
 
    }
1109
 
  else if (keyid && fpr)
1110
 
    {
1111
 
      keyid[0] = _cdk_buftou32 (fpr + 12);
1112
 
      keyid[1] = _cdk_buftou32 (fpr + 16);
1113
 
      lowbits = keyid[1];
1114
 
    }
1115
 
  else if (fpr)
1116
 
    lowbits = _cdk_buftou32 (fpr + 16);
1117
 
  return lowbits;
1118
 
}
1119
 
 
1120
 
 
1121
 
/**
1122
 
 * cdk_pk_get_keyid:
1123
 
 * @pk: the public key
1124
 
 * @keyid: buffer to store the key ID
1125
 
 * 
1126
 
 * Calculate the key ID of the given public key.
1127
 
 **/
1128
 
u32
1129
 
cdk_pk_get_keyid (cdk_pubkey_t pk, u32 *keyid)
1130
 
{
1131
 
  u32 lowbits = 0;
1132
 
  byte buf[24];
1133
 
  
1134
 
  if (pk && (!pk->keyid[0] || !pk->keyid[1])) 
1135
 
    {
1136
 
      if (pk->version < 4 && is_RSA (pk->pubkey_algo)) 
1137
 
        {
1138
 
          byte p[MAX_MPI_BYTES];
1139
 
          size_t n;
1140
 
          
1141
 
          gcry_mpi_print (GCRYMPI_FMT_USG, p, MAX_MPI_BYTES, &n, pk->mpi[0]);
1142
 
          pk->keyid[0] = p[n-8] << 24 | p[n-7] << 16 | p[n-6] << 8 | p[n-5];
1143
 
          pk->keyid[1] = p[n-4] << 24 | p[n-3] << 16 | p[n-2] << 8 | p[n-1];
1144
 
        }
1145
 
      else if (pk->version == 4)
1146
 
        {
1147
 
          cdk_pk_get_fingerprint (pk, buf);
1148
 
          pk->keyid[0] = _cdk_buftou32 (buf + 12);
1149
 
          pk->keyid[1] = _cdk_buftou32 (buf + 16);
1150
 
        }
1151
 
    }
1152
 
  lowbits = pk ? pk->keyid[1] : 0;
1153
 
  if (keyid && pk)
1154
 
    {
1155
 
      keyid[0] = pk->keyid[0];
1156
 
      keyid[1] = pk->keyid[1];
1157
 
    }
1158
 
  
1159
 
  return lowbits;
1160
 
}
1161
 
 
1162
 
 
1163
 
/**
1164
 
 * cdk_sk_get_keyid:
1165
 
 * @sk: the secret key
1166
 
 * @keyid: buffer to hold the key ID
1167
 
 * 
1168
 
 * Calculate the key ID of the secret key, actually the public key.
1169
 
 **/
1170
 
u32
1171
 
cdk_sk_get_keyid (cdk_pkt_seckey_t sk, u32 *keyid)
1172
 
{
1173
 
  u32 lowbits = 0;
1174
 
  
1175
 
  if (sk && sk->pk)
1176
 
    {
1177
 
      lowbits = cdk_pk_get_keyid (sk->pk, keyid);
1178
 
      sk->keyid[0] = sk->pk->keyid[0];
1179
 
      sk->keyid[1] = sk->pk->keyid[1];
1180
 
    }
1181
 
  
1182
 
  return lowbits;
1183
 
}
1184
 
 
1185
 
 
1186
 
/**
1187
 
 * cdk_sig_get_keyid:
1188
 
 * @sig: the signature
1189
 
 * @keyid: buffer to hold the key ID
1190
 
 * 
1191
 
 * Retrieve the key ID from the given signature.
1192
 
 **/
1193
 
u32
1194
 
cdk_sig_get_keyid (cdk_pkt_signature_t sig, u32 *keyid)
1195
 
{
1196
 
  u32 lowbits = sig ? sig->keyid[1] : 0;
1197
 
  
1198
 
  if (keyid && sig)
1199
 
    {
1200
 
      keyid[0] = sig->keyid[0];
1201
 
      keyid[1] = sig->keyid[1];
1202
 
    }
1203
 
  return lowbits;
1204
 
}
1205
 
 
1206
 
 
1207
 
/* Return the key ID from the given packet.
1208
 
   If this is not possible, 0 is returned */
1209
 
u32
1210
 
_cdk_pkt_get_keyid (cdk_packet_t pkt, u32 *keyid)
1211
 
{
1212
 
  u32 lowbits;
1213
 
  
1214
 
  if (!pkt)
1215
 
    return 0;
1216
 
  
1217
 
  switch (pkt->pkttype)
1218
 
    {
1219
 
    case CDK_PKT_PUBLIC_KEY:
1220
 
    case CDK_PKT_PUBLIC_SUBKEY:
1221
 
      lowbits = cdk_pk_get_keyid (pkt->pkt.public_key, keyid);
1222
 
      break;
1223
 
      
1224
 
    case CDK_PKT_SECRET_KEY:
1225
 
    case CDK_PKT_SECRET_SUBKEY:
1226
 
      lowbits = cdk_sk_get_keyid (pkt->pkt.secret_key, keyid);
1227
 
      break;
1228
 
      
1229
 
    case CDK_PKT_SIGNATURE:
1230
 
      lowbits = cdk_sig_get_keyid (pkt->pkt.signature, keyid);
1231
 
      break;
1232
 
      
1233
 
    default:
1234
 
      lowbits = 0;
1235
 
      break;
1236
 
    }
1237
 
  
1238
 
  return lowbits;
1239
 
}
1240
 
 
1241
 
 
1242
 
/* Get the fingerprint of the packet if possible. */
1243
 
int
1244
 
_cdk_pkt_get_fingerprint (cdk_packet_t pkt, byte *fpr)
1245
 
{
1246
 
  if (!pkt || !fpr)
1247
 
    return CDK_Inv_Value;
1248
 
  
1249
 
  switch (pkt->pkttype)
1250
 
    {
1251
 
    case CDK_PKT_PUBLIC_KEY:
1252
 
    case CDK_PKT_PUBLIC_SUBKEY:
1253
 
      return cdk_pk_get_fingerprint (pkt->pkt.public_key, fpr);
1254
 
      
1255
 
    case CDK_PKT_SECRET_KEY:
1256
 
    case CDK_PKT_SECRET_SUBKEY:
1257
 
      return cdk_pk_get_fingerprint (pkt->pkt.secret_key->pk, fpr);
1258
 
      
1259
 
    default:
1260
 
      return CDK_Inv_Mode;
1261
 
    }
1262
 
  return 0;
1263
 
}
1264
 
 
1265
 
 
1266
 
/**
1267
 
 * cdk_pubkey_to_sexp:
1268
 
 * @pk: the public key
1269
 
 * @sexp: where to store the S-expression
1270
 
 * @len: the length of sexp
1271
 
 *
1272
 
 * Convert a public key to an S-expression. sexp is allocated by this
1273
 
 * function, but you have to cdk_free() it yourself.  The S-expression
1274
 
 * is stored in canonical format as used by libgcrypt
1275
 
 * (GCRYSEXP_FMT_CANON).
1276
 
 **/
1277
 
cdk_error_t
1278
 
cdk_pubkey_to_sexp (cdk_pubkey_t pk, char **sexp, size_t * len)
1279
 
{
1280
 
  char *buf;
1281
 
  size_t sexp_len;
1282
 
  gcry_sexp_t pk_sexp;
1283
 
  cdk_error_t rc;
1284
 
 
1285
 
  if (!pk || !sexp)
1286
 
    return CDK_Inv_Value;
1287
 
 
1288
 
  rc = pubkey_to_sexp (&pk_sexp, pk);
1289
 
  if (rc)
1290
 
    return rc;
1291
 
 
1292
 
  sexp_len = gcry_sexp_sprint (pk_sexp, GCRYSEXP_FMT_CANON, NULL, 0);
1293
 
  if (!sexp_len)
1294
 
    return CDK_Wrong_Format;
1295
 
 
1296
 
  buf = (char *)cdk_malloc (sexp_len);
1297
 
  if (!buf)
1298
 
    {
1299
 
      gcry_sexp_release (pk_sexp);
1300
 
      return CDK_Out_Of_Core;
1301
 
    }
1302
 
  
1303
 
  sexp_len = gcry_sexp_sprint (pk_sexp, GCRYSEXP_FMT_CANON, buf, sexp_len);  
1304
 
  gcry_sexp_release (pk_sexp);
1305
 
  if (!sexp_len)
1306
 
    {
1307
 
      cdk_free (buf);
1308
 
      return CDK_Wrong_Format;
1309
 
    }
1310
 
 
1311
 
  if (len)
1312
 
    *len = sexp_len;
1313
 
  *sexp = buf;
1314
 
  return CDK_Success;
1315
 
}
1316
 
 
1317
 
 
1318
 
/**
1319
 
 * cdk_seckey_to_sexp:
1320
 
 * @sk: the secret key
1321
 
 * @sexp: where to store the S-expression
1322
 
 * @len: the length of sexp
1323
 
 *
1324
 
 * Convert a public key to an S-expression. sexp is allocated by this
1325
 
 * function, but you have to cdk_free() it yourself.  The S-expression
1326
 
 * is stored in canonical format as used by libgcrypt
1327
 
 * (GCRYSEXP_FMT_CANON).
1328
 
 **/
1329
 
cdk_error_t
1330
 
cdk_seckey_to_sexp (cdk_pkt_seckey_t sk, char **sexp, size_t * len)
1331
 
{
1332
 
  char *buf;
1333
 
  size_t sexp_len;
1334
 
  gcry_sexp_t sk_sexp;
1335
 
  cdk_error_t rc;
1336
 
 
1337
 
  if (!sk || !sexp)
1338
 
    return CDK_Inv_Value;
1339
 
  
1340
 
  rc = seckey_to_sexp (&sk_sexp, sk);
1341
 
  if (rc)
1342
 
    return rc;
1343
 
 
1344
 
  sexp_len = gcry_sexp_sprint (sk_sexp, GCRYSEXP_FMT_CANON, NULL, 0);
1345
 
  if (!sexp_len)
1346
 
    return CDK_Wrong_Format;
1347
 
 
1348
 
  buf = (char *) cdk_malloc (sexp_len);
1349
 
  if (!buf)
1350
 
    {
1351
 
      gcry_sexp_release (sk_sexp);
1352
 
      return CDK_Out_Of_Core;
1353
 
    }
1354
 
 
1355
 
  sexp_len = gcry_sexp_sprint (sk_sexp, GCRYSEXP_FMT_CANON, buf, sexp_len);    
1356
 
  gcry_sexp_release (sk_sexp);
1357
 
  if (!sexp_len)
1358
 
    {
1359
 
      cdk_free (buf);
1360
 
      return CDK_Wrong_Format;
1361
 
    }
1362
 
 
1363
 
  if (len)
1364
 
    *len = sexp_len;
1365
 
  *sexp = buf;
1366
 
 
1367
 
  return CDK_Success;
1368
 
}