~ubuntu-branches/ubuntu/quantal/gnupg2/quantal-updates

« back to all changes in this revision

Viewing changes to .pc/encode-s2k.patch/agent/protect.c

  • Committer: Bazaar Package Importer
  • Author(s): Marc Deslauriers
  • Date: 2010-11-16 11:30:31 UTC
  • mfrom: (7.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20101116113031-3y0603x6m3bw78s1
Tags: 2.0.14-2ubuntu1
* Merge from debian unstable.  Remaining changes:
  - Add udev rules to give gpg access to some smartcard readers;
    Debian #543217.
    . debian/gnupg2.dev: udev rules to set ACLs on SCM smartcard readers.
    . debian/rules: Call dh_installudev.
  - debian/control: Rename Vcs-* to XS-Debian-Vcs-*.
* debian/patches/CVE-2010-2547.patch: dropped, now in
  03-gpgsm-realloc.diff.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* protect.c - Un/Protect a secret key
2
 
 * Copyright (C) 1998, 1999, 2000, 2001, 2002,
3
 
 *               2003, 2007, 2009 Free Software Foundation, Inc.
4
 
 *
5
 
 * This file is part of GnuPG.
6
 
 *
7
 
 * GnuPG 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 3 of the License, or
10
 
 * (at your option) any later version.
11
 
 *
12
 
 * GnuPG 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
 
 * You should have received a copy of the GNU General Public License
18
 
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19
 
 */
20
 
 
21
 
#include <config.h>
22
 
#include <errno.h>
23
 
#include <stdio.h>
24
 
#include <stdlib.h>
25
 
#include <string.h>
26
 
#include <ctype.h>
27
 
#include <assert.h>
28
 
#include <unistd.h>
29
 
#include <sys/stat.h>
30
 
#ifdef HAVE_W32_SYSTEM
31
 
# include <windows.h>
32
 
#else
33
 
# include <sys/times.h>
34
 
#endif
35
 
 
36
 
#include "agent.h"
37
 
 
38
 
#include "sexp-parse.h"
39
 
 
40
 
#define PROT_CIPHER        GCRY_CIPHER_AES
41
 
#define PROT_CIPHER_STRING "aes"
42
 
#define PROT_CIPHER_KEYLEN (128/8)
43
 
 
44
 
 
45
 
/* A table containing the information needed to create a protected
46
 
   private key */
47
 
static struct {
48
 
  const char *algo;
49
 
  const char *parmlist;
50
 
  int prot_from, prot_to;
51
 
} protect_info[] = {
52
 
  { "rsa",  "nedpqu", 2, 5 },
53
 
  { "dsa",  "pqgyx", 4, 4 },
54
 
  { "elg",  "pgyx", 3, 3 },
55
 
  { NULL }
56
 
};
57
 
 
58
 
 
59
 
/* A helper object for time measurement.  */
60
 
struct calibrate_time_s
61
 
{
62
 
#ifdef HAVE_W32_SYSTEM
63
 
  FILETIME creation_time, exit_time, kernel_time, user_time;
64
 
#else
65
 
  clock_t ticks;
66
 
#endif
67
 
};
68
 
 
69
 
 
70
 
static int
71
 
hash_passphrase (const char *passphrase, int hashalgo,
72
 
                 int s2kmode,
73
 
                 const unsigned char *s2ksalt, unsigned long s2kcount,
74
 
                 unsigned char *key, size_t keylen);
75
 
 
76
 
/* Get the process time and store it in DATA.  */
77
 
static void
78
 
calibrate_get_time (struct calibrate_time_s *data)
79
 
{
80
 
#ifdef HAVE_W32_SYSTEM
81
 
  GetProcessTimes (GetCurrentProcess (),
82
 
                   &data->creation_time, &data->exit_time,
83
 
                   &data->kernel_time, &data->user_time);
84
 
#else
85
 
  struct tms tmp;
86
 
  
87
 
  times (&tmp);
88
 
  data->ticks = tmp.tms_utime;
89
 
#endif
90
 
}
91
 
 
92
 
 
93
 
static unsigned long
94
 
calibrate_elapsed_time (struct calibrate_time_s *starttime)
95
 
{
96
 
  struct calibrate_time_s stoptime;
97
 
  
98
 
  calibrate_get_time (&stoptime);
99
 
#ifdef HAVE_W32_SYSTEM
100
 
  {
101
 
    unsigned long long t1, t2;
102
 
    
103
 
    t1 = (((unsigned long long)starttime->kernel_time.dwHighDateTime << 32)
104
 
          + starttime->kernel_time.dwLowDateTime);
105
 
    t1 += (((unsigned long long)starttime->user_time.dwHighDateTime << 32)
106
 
           + starttime->user_time.dwLowDateTime);
107
 
    t2 = (((unsigned long long)stoptime.kernel_time.dwHighDateTime << 32)
108
 
          + stoptime.kernel_time.dwLowDateTime);
109
 
    t2 += (((unsigned long long)stoptime.user_time.dwHighDateTime << 32)
110
 
           + stoptime.user_time.dwLowDateTime);
111
 
    return (unsigned long)((t2 - t1)/10000);
112
 
  }
113
 
#else
114
 
  return (unsigned long)((((double) (stoptime.ticks - starttime->ticks))
115
 
                          /CLOCKS_PER_SEC)*10000000);
116
 
#endif
117
 
}
118
 
 
119
 
 
120
 
/* Run a test hashing for COUNT and return the time required in
121
 
   milliseconds.  */
122
 
static unsigned long
123
 
calibrate_s2k_count_one (unsigned long count)
124
 
{
125
 
  int rc;
126
 
  char keybuf[PROT_CIPHER_KEYLEN];
127
 
  struct calibrate_time_s starttime;
128
 
 
129
 
  calibrate_get_time (&starttime);
130
 
  rc = hash_passphrase ("123456789abcdef0", GCRY_MD_SHA1,
131
 
                        3, "saltsalt", count, keybuf, sizeof keybuf);
132
 
  if (rc)
133
 
    BUG ();
134
 
  return calibrate_elapsed_time (&starttime);
135
 
}
136
 
 
137
 
 
138
 
/* Measure the time we need to do the hash operations and deduce an
139
 
   S2K count which requires about 100ms of time.  */ 
140
 
static unsigned long
141
 
calibrate_s2k_count (void)
142
 
{
143
 
  unsigned long count;
144
 
  unsigned long ms;
145
 
 
146
 
  for (count = 65536; count; count *= 2)
147
 
    {
148
 
      ms = calibrate_s2k_count_one (count);
149
 
      if (opt.verbose > 1)
150
 
        log_info ("S2K calibration: %lu -> %lums\n", count, ms);
151
 
      if (ms > 100)
152
 
        break;
153
 
    }
154
 
 
155
 
  count = (unsigned long)(((double)count / ms) * 100);
156
 
  count /= 1024;
157
 
  count *= 1024;
158
 
  if (count < 65536)
159
 
    count = 65536;
160
 
 
161
 
  if (opt.verbose)
162
 
    {
163
 
      ms = calibrate_s2k_count_one (count);
164
 
      log_info ("S2K calibration: %lu iterations for %lums\n", count, ms);
165
 
    }
166
 
 
167
 
  return count;
168
 
}
169
 
 
170
 
 
171
 
 
172
 
/* Return the standard S2K count.  */
173
 
unsigned long
174
 
get_standard_s2k_count (void)
175
 
{
176
 
  static unsigned long count;
177
 
 
178
 
  if (!count)
179
 
    count = calibrate_s2k_count ();
180
 
 
181
 
  /* Enforce a lower limit.  */
182
 
  return count < 65536 ? 65536 : count;
183
 
}
184
 
 
185
 
 
186
 
 
187
 
 
188
 
/* Calculate the MIC for a private key S-Exp. SHA1HASH should point to
189
 
   a 20 byte buffer.  This function is suitable for any algorithms. */
190
 
static int 
191
 
calculate_mic (const unsigned char *plainkey, unsigned char *sha1hash)
192
 
{
193
 
  const unsigned char *hash_begin, *hash_end;
194
 
  const unsigned char *s;
195
 
  size_t n;
196
 
 
197
 
  s = plainkey;
198
 
  if (*s != '(')
199
 
    return gpg_error (GPG_ERR_INV_SEXP);
200
 
  s++;
201
 
  n = snext (&s);
202
 
  if (!n)
203
 
    return gpg_error (GPG_ERR_INV_SEXP); 
204
 
  if (!smatch (&s, n, "private-key"))
205
 
    return gpg_error (GPG_ERR_UNKNOWN_SEXP); 
206
 
  if (*s != '(')
207
 
    return gpg_error (GPG_ERR_UNKNOWN_SEXP);
208
 
  hash_begin = s;
209
 
  s++;
210
 
  n = snext (&s);
211
 
  if (!n)
212
 
    return gpg_error (GPG_ERR_INV_SEXP); 
213
 
  s += n; /* skip over the algorithm name */
214
 
 
215
 
  while (*s == '(')
216
 
    {
217
 
      s++;
218
 
      n = snext (&s);
219
 
      if (!n)
220
 
        return gpg_error (GPG_ERR_INV_SEXP); 
221
 
      s += n;
222
 
      n = snext (&s);
223
 
      if (!n)
224
 
        return gpg_error (GPG_ERR_INV_SEXP); 
225
 
      s += n;
226
 
      if ( *s != ')' )
227
 
        return gpg_error (GPG_ERR_INV_SEXP); 
228
 
      s++;
229
 
    }
230
 
  if (*s != ')')
231
 
    return gpg_error (GPG_ERR_INV_SEXP); 
232
 
  s++;
233
 
  hash_end = s;
234
 
 
235
 
  gcry_md_hash_buffer (GCRY_MD_SHA1, sha1hash,
236
 
                       hash_begin, hash_end - hash_begin);
237
 
 
238
 
  return 0;
239
 
}
240
 
 
241
 
 
242
 
 
243
 
/* Encrypt the parameter block starting at PROTBEGIN with length
244
 
   PROTLEN using the utf8 encoded key PASSPHRASE and return the entire
245
 
   encrypted block in RESULT or return with an error code.  SHA1HASH
246
 
   is the 20 byte SHA-1 hash required for the integrity code.
247
 
 
248
 
   The parameter block is expected to be an incomplete S-Expression of
249
 
   the form (example in advanced format):
250
 
 
251
 
     (d #046129F..[some bytes not shown]..81#)
252
 
     (p #00e861b..[some bytes not shown]..f1#)
253
 
     (q #00f7a7c..[some bytes not shown]..61#)
254
 
     (u #304559a..[some bytes not shown]..9b#) 
255
 
 
256
 
   the returned block is the S-Expression:
257
 
 
258
 
    (protected mode (parms) encrypted_octet_string)
259
 
 
260
 
*/
261
 
static int
262
 
do_encryption (const unsigned char *protbegin, size_t protlen, 
263
 
               const char *passphrase,  const unsigned char *sha1hash,
264
 
               unsigned char **result, size_t *resultlen)
265
 
{
266
 
  gcry_cipher_hd_t hd;
267
 
  const char *modestr = "openpgp-s2k3-sha1-" PROT_CIPHER_STRING "-cbc";
268
 
  int blklen, enclen, outlen;
269
 
  unsigned char *iv = NULL;
270
 
  int rc;
271
 
  char *outbuf = NULL;
272
 
  char *p;
273
 
  int saltpos, ivpos, encpos;
274
 
 
275
 
  *resultlen = 0;
276
 
  *result = NULL;
277
 
 
278
 
  rc = gcry_cipher_open (&hd, PROT_CIPHER, GCRY_CIPHER_MODE_CBC,
279
 
                         GCRY_CIPHER_SECURE);
280
 
  if (rc)
281
 
    return rc;
282
 
 
283
 
 
284
 
  /* We need to work on a copy of the data because this makes it
285
 
     easier to add the trailer and the padding and more important we
286
 
     have to prefix the text with 2 parenthesis, so we have to
287
 
     allocate enough space for:
288
 
 
289
 
     ((<parameter_list>)(4:hash4:sha120:<hashvalue>)) + padding
290
 
 
291
 
     We always append a full block of random bytes as padding but
292
 
     encrypt only what is needed for a full blocksize.  */
293
 
  blklen = gcry_cipher_get_algo_blklen (PROT_CIPHER);
294
 
  outlen = 2 + protlen + 2 + 6 + 6 + 23 + 2 + blklen;
295
 
  enclen = outlen/blklen * blklen;
296
 
  outbuf = gcry_malloc_secure (outlen);
297
 
  if (!outbuf)
298
 
    rc = out_of_core ();
299
 
  if (!rc)
300
 
    {
301
 
      /* Allocate random bytes to be used as IV, padding and s2k salt. */
302
 
      iv = xtrymalloc (blklen*2+8);
303
 
      if (!iv)
304
 
        rc = gpg_error (GPG_ERR_ENOMEM);
305
 
      else
306
 
        {
307
 
          gcry_create_nonce (iv, blklen*2+8);
308
 
          rc = gcry_cipher_setiv (hd, iv, blklen);
309
 
        }
310
 
    }
311
 
  if (!rc)
312
 
    {
313
 
      unsigned char *key;
314
 
      size_t keylen = PROT_CIPHER_KEYLEN;
315
 
      
316
 
      key = gcry_malloc_secure (keylen);
317
 
      if (!key)
318
 
        rc = out_of_core ();
319
 
      else
320
 
        {
321
 
          rc = hash_passphrase (passphrase, GCRY_MD_SHA1,
322
 
                                3, iv+2*blklen, 
323
 
                                get_standard_s2k_count (), key, keylen);
324
 
          if (!rc)
325
 
            rc = gcry_cipher_setkey (hd, key, keylen);
326
 
          xfree (key);
327
 
        }
328
 
    }
329
 
  if (!rc)
330
 
    {
331
 
      p = outbuf;
332
 
      *p++ = '(';
333
 
      *p++ = '(';
334
 
      memcpy (p, protbegin, protlen);
335
 
      p += protlen;
336
 
      memcpy (p, ")(4:hash4:sha120:", 17);
337
 
      p += 17;
338
 
      memcpy (p, sha1hash, 20);
339
 
      p += 20;
340
 
      *p++ = ')';
341
 
      *p++ = ')';
342
 
      memcpy (p, iv+blklen, blklen); 
343
 
      p += blklen;
344
 
      assert ( p - outbuf == outlen);
345
 
      rc = gcry_cipher_encrypt (hd, outbuf, enclen, NULL, 0);
346
 
    }
347
 
  gcry_cipher_close (hd);
348
 
  if (rc)
349
 
    {
350
 
      xfree (iv);
351
 
      xfree (outbuf);
352
 
      return rc;
353
 
    }
354
 
 
355
 
  /* Now allocate the buffer we want to return.  This is
356
 
 
357
 
     (protected openpgp-s2k3-sha1-aes-cbc
358
 
       ((sha1 salt no_of_iterations) 16byte_iv)
359
 
       encrypted_octet_string)
360
 
       
361
 
     in canoncical format of course.  We use asprintf and %n modifier
362
 
     and dummy values as placeholders.  */
363
 
  p = xtryasprintf
364
 
    ("(9:protected%d:%s((4:sha18:%n_8bytes_2:96)%d:%n%*s)%d:%n%*s)",
365
 
     (int)strlen (modestr), modestr,
366
 
     &saltpos, 
367
 
     blklen, &ivpos, blklen, "",
368
 
     enclen, &encpos, enclen, "");
369
 
  if (!p)
370
 
    {
371
 
      gpg_error_t tmperr = out_of_core ();
372
 
      xfree (iv);
373
 
      xfree (outbuf);
374
 
      return tmperr;
375
 
    }
376
 
  *resultlen = strlen (p);
377
 
  *result = (unsigned char*)p;
378
 
  memcpy (p+saltpos, iv+2*blklen, 8);
379
 
  memcpy (p+ivpos, iv, blklen);
380
 
  memcpy (p+encpos, outbuf, enclen);
381
 
  xfree (iv);
382
 
  xfree (outbuf);
383
 
  return 0;
384
 
}
385
 
 
386
 
 
387
 
 
388
 
/* Protect the key encoded in canonical format in PLAINKEY.  We assume
389
 
   a valid S-Exp here. */
390
 
int 
391
 
agent_protect (const unsigned char *plainkey, const char *passphrase,
392
 
               unsigned char **result, size_t *resultlen)
393
 
{
394
 
  int rc;
395
 
  const unsigned char *s;
396
 
  const unsigned char *hash_begin, *hash_end;
397
 
  const unsigned char *prot_begin, *prot_end, *real_end;
398
 
  size_t n;
399
 
  int c, infidx, i;
400
 
  unsigned char hashvalue[20];
401
 
  char timestamp_exp[35];
402
 
  unsigned char *protected;
403
 
  size_t protectedlen;
404
 
  int depth = 0;
405
 
  unsigned char *p;
406
 
  gcry_md_hd_t md;
407
 
 
408
 
  /* Create an S-expression with the procted-at timestamp.  */
409
 
  memcpy (timestamp_exp, "(12:protected-at15:", 19);
410
 
  gnupg_get_isotime (timestamp_exp+19);
411
 
  timestamp_exp[19+15] = ')';
412
 
 
413
 
  /* Parse original key.  */
414
 
  s = plainkey;
415
 
  if (*s != '(')
416
 
    return gpg_error (GPG_ERR_INV_SEXP);
417
 
  depth++;
418
 
  s++;
419
 
  n = snext (&s);
420
 
  if (!n)
421
 
    return gpg_error (GPG_ERR_INV_SEXP); 
422
 
  if (!smatch (&s, n, "private-key"))
423
 
    return gpg_error (GPG_ERR_UNKNOWN_SEXP); 
424
 
  if (*s != '(')
425
 
    return gpg_error (GPG_ERR_UNKNOWN_SEXP);
426
 
  depth++;
427
 
  hash_begin = s;
428
 
  s++;
429
 
  n = snext (&s);
430
 
  if (!n)
431
 
    return gpg_error (GPG_ERR_INV_SEXP); 
432
 
 
433
 
  for (infidx=0; protect_info[infidx].algo
434
 
              && !smatch (&s, n, protect_info[infidx].algo); infidx++)
435
 
    ;
436
 
  if (!protect_info[infidx].algo)
437
 
    return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); 
438
 
 
439
 
  prot_begin = prot_end = NULL;
440
 
  for (i=0; (c=protect_info[infidx].parmlist[i]); i++)
441
 
    {
442
 
      if (i == protect_info[infidx].prot_from)
443
 
        prot_begin = s;
444
 
      if (*s != '(')
445
 
        return gpg_error (GPG_ERR_INV_SEXP);
446
 
      depth++;
447
 
      s++;
448
 
      n = snext (&s);
449
 
      if (!n)
450
 
        return gpg_error (GPG_ERR_INV_SEXP); 
451
 
      if (n != 1 || c != *s)
452
 
        return gpg_error (GPG_ERR_INV_SEXP); 
453
 
      s += n;
454
 
      n = snext (&s);
455
 
      if (!n)
456
 
        return gpg_error (GPG_ERR_INV_SEXP); 
457
 
      s +=n; /* skip value */
458
 
      if (*s != ')')
459
 
        return gpg_error (GPG_ERR_INV_SEXP); 
460
 
      depth--;
461
 
      if (i == protect_info[infidx].prot_to)
462
 
        prot_end = s;
463
 
      s++;
464
 
    }
465
 
  if (*s != ')' || !prot_begin || !prot_end )
466
 
    return gpg_error (GPG_ERR_INV_SEXP); 
467
 
  depth--;
468
 
  hash_end = s;
469
 
  s++;
470
 
  /* skip to the end of the S-exp */
471
 
  assert (depth == 1);
472
 
  rc = sskip (&s, &depth);
473
 
  if (rc)
474
 
    return rc;
475
 
  assert (!depth);
476
 
  real_end = s-1;
477
 
 
478
 
  
479
 
  /* Hash the stuff.  Because the timestamp_exp won't get protected,
480
 
     we can't simply hash a continuous buffer but need to use several
481
 
     md_writes.  */ 
482
 
  rc = gcry_md_open (&md, GCRY_MD_SHA1, 0 );
483
 
  if (rc)
484
 
    return rc;
485
 
  gcry_md_write (md, hash_begin, hash_end - hash_begin);
486
 
  gcry_md_write (md, timestamp_exp, 35);
487
 
  gcry_md_write (md, ")", 1);
488
 
  memcpy (hashvalue, gcry_md_read (md, GCRY_MD_SHA1), 20);
489
 
  gcry_md_close (md);
490
 
 
491
 
  rc = do_encryption (prot_begin, prot_end - prot_begin + 1,
492
 
                      passphrase,  hashvalue,
493
 
                      &protected, &protectedlen);
494
 
  if (rc)
495
 
    return rc;
496
 
 
497
 
  /* Now create the protected version of the key.  Note that the 10
498
 
     extra bytes are for for the inserted "protected-" string (the
499
 
     beginning of the plaintext reads: "((11:private-key(" ).  The 35
500
 
     term is the space for (12:protected-at15:<timestamp>).  */
501
 
  *resultlen = (10
502
 
                + (prot_begin-plainkey)
503
 
                + protectedlen
504
 
                + 35
505
 
                + (real_end-prot_end));
506
 
  *result = p = xtrymalloc (*resultlen);
507
 
  if (!p)
508
 
    {
509
 
      gpg_error_t tmperr = out_of_core ();
510
 
      xfree (protected);
511
 
      return tmperr;
512
 
    }
513
 
  memcpy (p, "(21:protected-", 14);
514
 
  p += 14;
515
 
  memcpy (p, plainkey+4, prot_begin - plainkey - 4);
516
 
  p += prot_begin - plainkey - 4;
517
 
  memcpy (p, protected, protectedlen);
518
 
  p += protectedlen;
519
 
 
520
 
  memcpy (p, timestamp_exp, 35);
521
 
  p += 35;
522
 
 
523
 
  memcpy (p, prot_end+1, real_end - prot_end);
524
 
  p += real_end - prot_end;
525
 
  assert ( p - *result == *resultlen);
526
 
  xfree (protected);
527
 
 
528
 
  return 0;
529
 
}
530
 
 
531
 
 
532
 
/* Do the actual decryption and check the return list for consistency.  */
533
 
static int
534
 
do_decryption (const unsigned char *protected, size_t protectedlen, 
535
 
               const char *passphrase, 
536
 
               const unsigned char *s2ksalt, unsigned long s2kcount,
537
 
               const unsigned char *iv, size_t ivlen,
538
 
               unsigned char **result)
539
 
{
540
 
  int rc = 0;
541
 
  int blklen;
542
 
  gcry_cipher_hd_t hd;
543
 
  unsigned char *outbuf;
544
 
  size_t reallen;
545
 
 
546
 
  blklen = gcry_cipher_get_algo_blklen (PROT_CIPHER);
547
 
  if (protectedlen < 4 || (protectedlen%blklen))
548
 
    return gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
549
 
 
550
 
  rc = gcry_cipher_open (&hd, PROT_CIPHER, GCRY_CIPHER_MODE_CBC,
551
 
                         GCRY_CIPHER_SECURE);
552
 
  if (rc)
553
 
    return rc;
554
 
 
555
 
  outbuf = gcry_malloc_secure (protectedlen);
556
 
  if (!outbuf)
557
 
    rc = out_of_core ();
558
 
  if (!rc)
559
 
    rc = gcry_cipher_setiv (hd, iv, ivlen);
560
 
  if (!rc)
561
 
    {
562
 
      unsigned char *key;
563
 
      size_t keylen = PROT_CIPHER_KEYLEN;
564
 
      
565
 
      key = gcry_malloc_secure (keylen);
566
 
      if (!key)
567
 
        rc = out_of_core ();
568
 
      else
569
 
        {
570
 
          rc = hash_passphrase (passphrase, GCRY_MD_SHA1,
571
 
                                3, s2ksalt, s2kcount, key, keylen);
572
 
          if (!rc)
573
 
            rc = gcry_cipher_setkey (hd, key, keylen);
574
 
          xfree (key);
575
 
        }
576
 
    }
577
 
  if (!rc)
578
 
    rc = gcry_cipher_decrypt (hd, outbuf, protectedlen,
579
 
                              protected, protectedlen);
580
 
  gcry_cipher_close (hd);
581
 
  if (rc)
582
 
    {
583
 
      xfree (outbuf);
584
 
      return rc;
585
 
    }
586
 
  /* Do a quick check first. */
587
 
  if (*outbuf != '(' && outbuf[1] != '(')
588
 
    {
589
 
      xfree (outbuf);
590
 
      return gpg_error (GPG_ERR_BAD_PASSPHRASE);
591
 
    }
592
 
  /* Check that we have a consistent S-Exp. */
593
 
  reallen = gcry_sexp_canon_len (outbuf, protectedlen, NULL, NULL);
594
 
  if (!reallen || (reallen + blklen < protectedlen) )
595
 
    {
596
 
      xfree (outbuf);
597
 
      return gpg_error (GPG_ERR_BAD_PASSPHRASE);
598
 
    }
599
 
  *result = outbuf;
600
 
  return 0;
601
 
}
602
 
 
603
 
 
604
 
/* Merge the parameter list contained in CLEARTEXT with the original
605
 
   protect lists PROTECTEDKEY by replacing the list at REPLACEPOS.
606
 
   Return the new list in RESULT and the MIC value in the 20 byte
607
 
   buffer SHA1HASH.  CUTOFF and CUTLEN will receive the offset and the
608
 
   length of the resulting list which should go into the MIC
609
 
   calculation but then be removed.  */
610
 
static int
611
 
merge_lists (const unsigned char *protectedkey,
612
 
             size_t replacepos, 
613
 
             const unsigned char *cleartext,
614
 
             unsigned char *sha1hash,
615
 
             unsigned char **result, size_t *resultlen,
616
 
             size_t *cutoff, size_t *cutlen)
617
 
{
618
 
  size_t n, newlistlen;
619
 
  unsigned char *newlist, *p;
620
 
  const unsigned char *s;
621
 
  const unsigned char *startpos, *endpos;
622
 
  int i, rc;
623
 
  
624
 
  *result = NULL;
625
 
  *resultlen = 0;
626
 
  *cutoff = 0;
627
 
  *cutlen = 0;
628
 
 
629
 
  if (replacepos < 26)
630
 
    return gpg_error (GPG_ERR_BUG);
631
 
 
632
 
  /* Estimate the required size of the resulting list.  We have a large
633
 
     safety margin of >20 bytes (MIC hash from CLEARTEXT and the
634
 
     removed "protected-" */
635
 
  newlistlen = gcry_sexp_canon_len (protectedkey, 0, NULL, NULL);
636
 
  if (!newlistlen)
637
 
    return gpg_error (GPG_ERR_BUG);
638
 
  n = gcry_sexp_canon_len (cleartext, 0, NULL, NULL);
639
 
  if (!n)
640
 
    return gpg_error (GPG_ERR_BUG);
641
 
  newlistlen += n;
642
 
  newlist = gcry_malloc_secure (newlistlen);
643
 
  if (!newlist)
644
 
    return out_of_core ();
645
 
 
646
 
  /* Copy the initial segment */
647
 
  strcpy ((char*)newlist, "(11:private-key");
648
 
  p = newlist + 15;
649
 
  memcpy (p, protectedkey+15+10, replacepos-15-10);
650
 
  p += replacepos-15-10;
651
 
 
652
 
  /* copy the cleartext */
653
 
  s = cleartext;
654
 
  if (*s != '(' && s[1] != '(')
655
 
    return gpg_error (GPG_ERR_BUG);  /*we already checked this */
656
 
  s += 2;
657
 
  startpos = s;
658
 
  while ( *s == '(' )
659
 
    {
660
 
      s++;
661
 
      n = snext (&s);
662
 
      if (!n)
663
 
        goto invalid_sexp;
664
 
      s += n;
665
 
      n = snext (&s);
666
 
      if (!n)
667
 
        goto invalid_sexp;
668
 
      s += n;
669
 
      if ( *s != ')' )
670
 
        goto invalid_sexp;
671
 
      s++;
672
 
    }
673
 
  if ( *s != ')' )
674
 
    goto invalid_sexp;
675
 
  endpos = s;
676
 
  s++;
677
 
  /* Intermezzo: Get the MIC */
678
 
  if (*s != '(')
679
 
    goto invalid_sexp;
680
 
  s++;
681
 
  n = snext (&s);
682
 
  if (!smatch (&s, n, "hash"))
683
 
    goto invalid_sexp;
684
 
  n = snext (&s);
685
 
  if (!smatch (&s, n, "sha1"))
686
 
    goto invalid_sexp; 
687
 
  n = snext (&s);
688
 
  if (n != 20)
689
 
    goto invalid_sexp;
690
 
  memcpy (sha1hash, s, 20);
691
 
  s += n;
692
 
  if (*s != ')')
693
 
    goto invalid_sexp;
694
 
  /* End intermezzo */
695
 
 
696
 
  /* append the parameter list */
697
 
  memcpy (p, startpos, endpos - startpos);
698
 
  p += endpos - startpos;
699
 
  
700
 
  /* Skip over the protected list element in the original list.  */
701
 
  s = protectedkey + replacepos;
702
 
  assert (*s == '(');
703
 
  s++;
704
 
  i = 1;
705
 
  rc = sskip (&s, &i);
706
 
  if (rc)
707
 
    goto failure;
708
 
  /* Record the position of the optional protected-at expression.  */
709
 
  if (*s == '(')
710
 
    {
711
 
      const unsigned char *save_s = s;
712
 
      s++;
713
 
      n = snext (&s);
714
 
      if (smatch (&s, n, "protected-at"))
715
 
        {
716
 
          i = 1;
717
 
          rc = sskip (&s, &i);
718
 
          if (rc)
719
 
            goto failure;
720
 
          *cutlen = s - save_s;
721
 
        }
722
 
      s = save_s;
723
 
    }
724
 
  startpos = s;
725
 
  i = 2; /* we are inside this level */
726
 
  rc = sskip (&s, &i);
727
 
  if (rc)
728
 
    goto failure;
729
 
  assert (s[-1] == ')');
730
 
  endpos = s; /* one behind the end of the list */
731
 
 
732
 
  /* Append the rest. */
733
 
  if (*cutlen)
734
 
    *cutoff = p - newlist;
735
 
  memcpy (p, startpos, endpos - startpos);
736
 
  p += endpos - startpos;
737
 
  
738
 
 
739
 
  /* ready */
740
 
  *result = newlist;
741
 
  *resultlen = newlistlen;
742
 
  return 0;
743
 
 
744
 
 failure:
745
 
  wipememory (newlist, newlistlen);
746
 
  xfree (newlist);
747
 
  return rc;
748
 
 
749
 
 invalid_sexp:
750
 
  wipememory (newlist, newlistlen);
751
 
  xfree (newlist);
752
 
  return gpg_error (GPG_ERR_INV_SEXP);
753
 
}
754
 
 
755
 
 
756
 
 
757
 
/* Unprotect the key encoded in canonical format.  We assume a valid
758
 
   S-Exp here.  If a protected-at item is available, its value will
759
 
   be stored at protocted_at unless this is NULL.  */
760
 
int 
761
 
agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
762
 
                 gnupg_isotime_t protected_at, 
763
 
                 unsigned char **result, size_t *resultlen)
764
 
{
765
 
  int rc;
766
 
  const unsigned char *s;
767
 
  const unsigned char *protect_list; 
768
 
  size_t n;
769
 
  int infidx, i;
770
 
  unsigned char sha1hash[20], sha1hash2[20];
771
 
  const unsigned char *s2ksalt;
772
 
  unsigned long s2kcount;
773
 
  const unsigned char *iv;
774
 
  const unsigned char *prot_begin;
775
 
  unsigned char *cleartext;
776
 
  unsigned char *final;
777
 
  size_t finallen;
778
 
  size_t cutoff, cutlen;
779
 
 
780
 
  if (protected_at)
781
 
    *protected_at = 0;
782
 
 
783
 
  s = protectedkey;
784
 
  if (*s != '(')
785
 
    return gpg_error (GPG_ERR_INV_SEXP);
786
 
  s++;
787
 
  n = snext (&s);
788
 
  if (!n)
789
 
    return gpg_error (GPG_ERR_INV_SEXP); 
790
 
  if (!smatch (&s, n, "protected-private-key"))
791
 
    return gpg_error (GPG_ERR_UNKNOWN_SEXP); 
792
 
  if (*s != '(')
793
 
    return gpg_error (GPG_ERR_UNKNOWN_SEXP);
794
 
  s++;
795
 
  n = snext (&s);
796
 
  if (!n)
797
 
    return gpg_error (GPG_ERR_INV_SEXP); 
798
 
 
799
 
  for (infidx=0; protect_info[infidx].algo
800
 
              && !smatch (&s, n, protect_info[infidx].algo); infidx++)
801
 
    ;
802
 
  if (!protect_info[infidx].algo)
803
 
    return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); 
804
 
 
805
 
 
806
 
  /* See wether we have a protected-at timestamp.  */
807
 
  protect_list = s;  /* Save for later.  */
808
 
  if (protected_at)
809
 
    {
810
 
      while (*s == '(')
811
 
        {
812
 
          prot_begin = s;
813
 
          s++;
814
 
          n = snext (&s);
815
 
          if (!n)
816
 
            return gpg_error (GPG_ERR_INV_SEXP);
817
 
          if (smatch (&s, n, "protected-at"))
818
 
            {
819
 
              n = snext (&s);
820
 
              if (!n)
821
 
                return gpg_error (GPG_ERR_INV_SEXP);
822
 
              if (n != 15)
823
 
                return gpg_error (GPG_ERR_UNKNOWN_SEXP);
824
 
              memcpy (protected_at, s, 15);
825
 
              protected_at[15] = 0;
826
 
              break;
827
 
            }
828
 
          s += n;
829
 
          i = 1;
830
 
          rc = sskip (&s, &i);
831
 
          if (rc)
832
 
            return rc;
833
 
        }
834
 
    }
835
 
 
836
 
  /* Now find the list with the protected information.  Here is an
837
 
     example for such a list:
838
 
     (protected openpgp-s2k3-sha1-aes-cbc 
839
 
        ((sha1 <salt> <count>) <Initialization_Vector>)
840
 
        <encrypted_data>)
841
 
   */
842
 
  s = protect_list;
843
 
  for (;;)
844
 
    {
845
 
      if (*s != '(')
846
 
        return gpg_error (GPG_ERR_INV_SEXP);
847
 
      prot_begin = s;
848
 
      s++;
849
 
      n = snext (&s);
850
 
      if (!n)
851
 
        return gpg_error (GPG_ERR_INV_SEXP); 
852
 
      if (smatch (&s, n, "protected"))
853
 
        break;
854
 
      s += n;
855
 
      i = 1;
856
 
      rc = sskip (&s, &i);
857
 
      if (rc)
858
 
        return rc;
859
 
    }
860
 
  /* found */
861
 
  n = snext (&s);
862
 
  if (!n)
863
 
    return gpg_error (GPG_ERR_INV_SEXP); 
864
 
  if (!smatch (&s, n, "openpgp-s2k3-sha1-" PROT_CIPHER_STRING "-cbc"))
865
 
    return gpg_error (GPG_ERR_UNSUPPORTED_PROTECTION);
866
 
  if (*s != '(' || s[1] != '(')
867
 
    return gpg_error (GPG_ERR_INV_SEXP);
868
 
  s += 2;
869
 
  n = snext (&s);
870
 
  if (!n)
871
 
    return gpg_error (GPG_ERR_INV_SEXP); 
872
 
  if (!smatch (&s, n, "sha1"))
873
 
    return gpg_error (GPG_ERR_UNSUPPORTED_PROTECTION);
874
 
  n = snext (&s);
875
 
  if (n != 8)
876
 
    return gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
877
 
  s2ksalt = s;
878
 
  s += n;
879
 
  n = snext (&s);
880
 
  if (!n)
881
 
    return gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
882
 
  /* We expect a list close as next, so we can simply use strtoul()
883
 
     here.  We might want to check that we only have digits - but this
884
 
     is nothing we should worry about */
885
 
  if (s[n] != ')' )
886
 
    return gpg_error (GPG_ERR_INV_SEXP);
887
 
  
888
 
  /* Old versions of gpg-agent used the funny floating point number in
889
 
     a byte encoding as specified by OpenPGP.  However this is not
890
 
     needed and thus we now store it as a plain unsigned integer.  We
891
 
     can easily distinguish the old format by looking at its value:
892
 
     Less than 256 is an old-style encoded number; other values are
893
 
     plain integers.  In any case we check that they are at least
894
 
     65536 because we never used a lower value in the past and we
895
 
     should have a lower limit.  */
896
 
  s2kcount = strtoul ((const char*)s, NULL, 10);
897
 
  if (!s2kcount)
898
 
    return gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
899
 
  if (s2kcount < 256)
900
 
    s2kcount = (16ul + (s2kcount & 15)) << ((s2kcount >> 4) + 6);
901
 
  if (s2kcount < 65536)
902
 
    return gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
903
 
 
904
 
  s += n;
905
 
  s++; /* skip list end */
906
 
 
907
 
  n = snext (&s);
908
 
  if (n != 16) /* Wrong blocksize for IV (we support only aes-128). */
909
 
    return gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
910
 
  iv = s;
911
 
  s += n;
912
 
  if (*s != ')' )
913
 
    return gpg_error (GPG_ERR_INV_SEXP);
914
 
  s++;
915
 
  n = snext (&s);
916
 
  if (!n)
917
 
    return gpg_error (GPG_ERR_INV_SEXP); 
918
 
  
919
 
  rc = do_decryption (s, n,
920
 
                      passphrase, s2ksalt, s2kcount,
921
 
                      iv, 16,
922
 
                      &cleartext);
923
 
  if (rc)
924
 
    return rc;
925
 
 
926
 
  rc = merge_lists (protectedkey, prot_begin-protectedkey, cleartext,
927
 
                    sha1hash, &final, &finallen, &cutoff, &cutlen);
928
 
  /* Albeit cleartext has been allocated in secure memory and thus
929
 
     xfree will wipe it out, we do an extra wipe just in case
930
 
     somethings goes badly wrong. */
931
 
  wipememory (cleartext, n);
932
 
  xfree (cleartext);
933
 
  if (rc)
934
 
    return rc;
935
 
 
936
 
  rc = calculate_mic (final, sha1hash2);
937
 
  if (!rc && memcmp (sha1hash, sha1hash2, 20))
938
 
    rc = gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
939
 
  if (rc)
940
 
    {
941
 
      wipememory (final, finallen);
942
 
      xfree (final);
943
 
      return rc;
944
 
    }
945
 
  /* Now remove tha part which is included in the MIC but should not
946
 
     go into the final thing.  */
947
 
  if (cutlen)
948
 
    {
949
 
      memmove (final+cutoff, final+cutoff+cutlen, finallen-cutoff-cutlen);
950
 
      finallen -= cutlen;
951
 
    }
952
 
 
953
 
  *result = final;
954
 
  *resultlen = gcry_sexp_canon_len (final, 0, NULL, NULL);
955
 
  return 0;
956
 
}
957
 
 
958
 
/* Check the type of the private key, this is one of the constants:
959
 
   PRIVATE_KEY_UNKNOWN if we can't figure out the type (this is the
960
 
   value 0), PRIVATE_KEY_CLEAR for an unprotected private key.
961
 
   PRIVATE_KEY_PROTECTED for an protected private key or
962
 
   PRIVATE_KEY_SHADOWED for a sub key where the secret parts are stored
963
 
   elsewhere. */
964
 
int
965
 
agent_private_key_type (const unsigned char *privatekey)
966
 
{
967
 
  const unsigned char *s;
968
 
  size_t n;
969
 
 
970
 
  s = privatekey;
971
 
  if (*s != '(')
972
 
    return PRIVATE_KEY_UNKNOWN;
973
 
  s++;
974
 
  n = snext (&s);
975
 
  if (!n)
976
 
    return PRIVATE_KEY_UNKNOWN;
977
 
  if (smatch (&s, n, "protected-private-key"))
978
 
    return PRIVATE_KEY_PROTECTED;
979
 
  if (smatch (&s, n, "shadowed-private-key"))
980
 
    return PRIVATE_KEY_SHADOWED;
981
 
  if (smatch (&s, n, "private-key"))
982
 
    return PRIVATE_KEY_CLEAR;
983
 
  return PRIVATE_KEY_UNKNOWN;
984
 
}
985
 
 
986
 
 
987
 
 
988
 
/* Transform a passphrase into a suitable key of length KEYLEN and
989
 
   store this key in the caller provided buffer KEY.  The caller must
990
 
   provide an HASHALGO, a valid S2KMODE (see rfc-2440) and depending on
991
 
   that mode an S2KSALT of 8 random bytes and an S2KCOUNT.
992
 
  
993
 
   Returns an error code on failure.  */
994
 
static int
995
 
hash_passphrase (const char *passphrase, int hashalgo,
996
 
                 int s2kmode,
997
 
                 const unsigned char *s2ksalt,
998
 
                 unsigned long s2kcount,
999
 
                 unsigned char *key, size_t keylen)
1000
 
{
1001
 
  int rc;
1002
 
  gcry_md_hd_t md;
1003
 
  int pass, i;
1004
 
  int used = 0;
1005
 
  int pwlen = strlen (passphrase);
1006
 
 
1007
 
  if ( (s2kmode != 0 && s2kmode != 1 && s2kmode != 3)
1008
 
      || !hashalgo || !keylen || !key || !passphrase)
1009
 
    return gpg_error (GPG_ERR_INV_VALUE);
1010
 
  if ((s2kmode == 1 ||s2kmode == 3) && !s2ksalt)
1011
 
    return gpg_error (GPG_ERR_INV_VALUE);
1012
 
  
1013
 
  rc = gcry_md_open (&md, hashalgo, GCRY_MD_FLAG_SECURE);
1014
 
  if (rc)
1015
 
    return rc;
1016
 
 
1017
 
  for (pass=0; used < keylen; pass++)
1018
 
    {
1019
 
      if (pass)
1020
 
        {
1021
 
          gcry_md_reset (md);
1022
 
          for (i=0; i < pass; i++) /* preset the hash context */
1023
 
            gcry_md_putc (md, 0);
1024
 
        }
1025
 
 
1026
 
      if (s2kmode == 1 || s2kmode == 3)
1027
 
        {
1028
 
          int len2 = pwlen + 8;
1029
 
          unsigned long count = len2;
1030
 
 
1031
 
          if (s2kmode == 3)
1032
 
            {
1033
 
              count = s2kcount;
1034
 
              if (count < len2)
1035
 
                count = len2;
1036
 
            }
1037
 
 
1038
 
          while (count > len2)
1039
 
            {
1040
 
              gcry_md_write (md, s2ksalt, 8);
1041
 
              gcry_md_write (md, passphrase, pwlen);
1042
 
              count -= len2;
1043
 
            }
1044
 
          if (count < 8)
1045
 
            gcry_md_write (md, s2ksalt, count);
1046
 
          else 
1047
 
            {
1048
 
              gcry_md_write (md, s2ksalt, 8);
1049
 
              count -= 8;
1050
 
              gcry_md_write (md, passphrase, count);
1051
 
            }
1052
 
        }
1053
 
      else
1054
 
        gcry_md_write (md, passphrase, pwlen);
1055
 
      
1056
 
      gcry_md_final (md);
1057
 
      i = gcry_md_get_algo_dlen (hashalgo);
1058
 
      if (i > keylen - used)
1059
 
        i = keylen - used;
1060
 
      memcpy  (key+used, gcry_md_read (md, hashalgo), i);
1061
 
      used += i;
1062
 
    }
1063
 
  gcry_md_close(md);
1064
 
  return 0;
1065
 
}
1066
 
 
1067
 
 
1068
 
 
1069
 
 
1070
 
/* Create an canonical encoded S-expression with the shadow info from
1071
 
   a card's SERIALNO and the IDSTRING.  */
1072
 
unsigned char *
1073
 
make_shadow_info (const char *serialno, const char *idstring)
1074
 
{
1075
 
  const char *s;
1076
 
  char *info, *p;
1077
 
  char numbuf[20];
1078
 
  size_t n;
1079
 
 
1080
 
  for (s=serialno, n=0; *s && s[1]; s += 2)
1081
 
    n++;
1082
 
 
1083
 
  info = p = xtrymalloc (1 + sizeof numbuf + n
1084
 
                           + sizeof numbuf + strlen (idstring) + 1 + 1);
1085
 
  if (!info)
1086
 
    return NULL;
1087
 
  *p++ = '(';
1088
 
  p = stpcpy (p, smklen (numbuf, sizeof numbuf, n, NULL));
1089
 
  for (s=serialno; *s && s[1]; s += 2)
1090
 
    *(unsigned char *)p++ = xtoi_2 (s);
1091
 
  p = stpcpy (p, smklen (numbuf, sizeof numbuf, strlen (idstring), NULL));
1092
 
  p = stpcpy (p, idstring);
1093
 
  *p++ = ')';
1094
 
  *p = 0;
1095
 
  return (unsigned char *)info;
1096
 
}
1097
 
 
1098
 
 
1099
 
 
1100
 
/* Create a shadow key from a public key.  We use the shadow protocol
1101
 
  "ti-v1" and insert the S-expressionn SHADOW_INFO.  The resulting
1102
 
  S-expression is returned in an allocated buffer RESULT will point
1103
 
  to. The input parameters are expected to be valid canonicalized
1104
 
  S-expressions */
1105
 
int 
1106
 
agent_shadow_key (const unsigned char *pubkey,
1107
 
                  const unsigned char *shadow_info,
1108
 
                  unsigned char **result)
1109
 
{
1110
 
  const unsigned char *s;
1111
 
  const unsigned char *point;
1112
 
  size_t n;
1113
 
  int depth = 0;
1114
 
  char *p;
1115
 
  size_t pubkey_len = gcry_sexp_canon_len (pubkey, 0, NULL,NULL);
1116
 
  size_t shadow_info_len = gcry_sexp_canon_len (shadow_info, 0, NULL,NULL);
1117
 
 
1118
 
  if (!pubkey_len || !shadow_info_len)
1119
 
    return gpg_error (GPG_ERR_INV_VALUE);
1120
 
  s = pubkey;
1121
 
  if (*s != '(')
1122
 
    return gpg_error (GPG_ERR_INV_SEXP);
1123
 
  depth++;
1124
 
  s++;
1125
 
  n = snext (&s);
1126
 
  if (!n)
1127
 
    return gpg_error (GPG_ERR_INV_SEXP); 
1128
 
  if (!smatch (&s, n, "public-key"))
1129
 
    return gpg_error (GPG_ERR_UNKNOWN_SEXP); 
1130
 
  if (*s != '(')
1131
 
    return gpg_error (GPG_ERR_UNKNOWN_SEXP);
1132
 
  depth++;
1133
 
  s++;
1134
 
  n = snext (&s); 
1135
 
  if (!n)
1136
 
    return gpg_error (GPG_ERR_INV_SEXP); 
1137
 
  s += n; /* skip over the algorithm name */
1138
 
 
1139
 
  while (*s != ')')
1140
 
    {
1141
 
      if (*s != '(')
1142
 
        return gpg_error (GPG_ERR_INV_SEXP);
1143
 
      depth++;
1144
 
      s++;
1145
 
      n = snext (&s);
1146
 
      if (!n) 
1147
 
        return gpg_error (GPG_ERR_INV_SEXP); 
1148
 
      s += n;
1149
 
      n = snext (&s);
1150
 
      if (!n)
1151
 
        return gpg_error (GPG_ERR_INV_SEXP); 
1152
 
      s +=n; /* skip value */
1153
 
      if (*s != ')')
1154
 
        return gpg_error (GPG_ERR_INV_SEXP); 
1155
 
      depth--;
1156
 
      s++;
1157
 
    }
1158
 
  point = s; /* insert right before the point */
1159
 
  depth--;
1160
 
  s++;
1161
 
  assert (depth == 1);
1162
 
 
1163
 
  /* Calculate required length by taking in account: the "shadowed-"
1164
 
     prefix, the "shadowed", "t1-v1" as well as some parenthesis */
1165
 
  n = 12 + pubkey_len + 1 + 3+8 + 2+5 + shadow_info_len + 1;
1166
 
  *result = xtrymalloc (n);
1167
 
  p = (char*)*result;
1168
 
  if (!p)
1169
 
      return out_of_core ();
1170
 
  p = stpcpy (p, "(20:shadowed-private-key");
1171
 
  /* (10:public-key ...)*/
1172
 
  memcpy (p, pubkey+14, point - (pubkey+14));
1173
 
  p += point - (pubkey+14);
1174
 
  p = stpcpy (p, "(8:shadowed5:t1-v1");
1175
 
  memcpy (p, shadow_info, shadow_info_len);
1176
 
  p += shadow_info_len;
1177
 
  *p++ = ')';
1178
 
  memcpy (p, point, pubkey_len - (point - pubkey));
1179
 
  p += pubkey_len - (point - pubkey);
1180
 
 
1181
 
  return 0;
1182
 
}
1183
 
 
1184
 
/* Parse a canonical encoded shadowed key and return a pointer to the
1185
 
   inner list with the shadow_info */
1186
 
int 
1187
 
agent_get_shadow_info (const unsigned char *shadowkey,
1188
 
                       unsigned char const **shadow_info)
1189
 
{
1190
 
  const unsigned char *s;
1191
 
  size_t n;
1192
 
  int depth = 0;
1193
 
 
1194
 
  s = shadowkey;
1195
 
  if (*s != '(')
1196
 
    return gpg_error (GPG_ERR_INV_SEXP);
1197
 
  depth++;
1198
 
  s++;
1199
 
  n = snext (&s);
1200
 
  if (!n)
1201
 
    return gpg_error (GPG_ERR_INV_SEXP); 
1202
 
  if (!smatch (&s, n, "shadowed-private-key"))
1203
 
    return gpg_error (GPG_ERR_UNKNOWN_SEXP); 
1204
 
  if (*s != '(')
1205
 
    return gpg_error (GPG_ERR_UNKNOWN_SEXP);
1206
 
  depth++;
1207
 
  s++;
1208
 
  n = snext (&s); 
1209
 
  if (!n)
1210
 
    return gpg_error (GPG_ERR_INV_SEXP); 
1211
 
  s += n; /* skip over the algorithm name */
1212
 
 
1213
 
  for (;;)
1214
 
    {
1215
 
      if (*s == ')')
1216
 
        return gpg_error (GPG_ERR_UNKNOWN_SEXP);
1217
 
      if (*s != '(')
1218
 
        return gpg_error (GPG_ERR_INV_SEXP);
1219
 
      depth++;
1220
 
      s++;
1221
 
      n = snext (&s);
1222
 
      if (!n) 
1223
 
        return gpg_error (GPG_ERR_INV_SEXP); 
1224
 
      if (smatch (&s, n, "shadowed"))
1225
 
        break;
1226
 
      s += n;
1227
 
      n = snext (&s);
1228
 
      if (!n)
1229
 
        return gpg_error (GPG_ERR_INV_SEXP); 
1230
 
      s +=n; /* skip value */
1231
 
      if (*s != ')')
1232
 
        return gpg_error (GPG_ERR_INV_SEXP); 
1233
 
      depth--;
1234
 
      s++;
1235
 
    }
1236
 
  /* Found the shadowed list, S points to the protocol */
1237
 
  n = snext (&s);
1238
 
  if (!n) 
1239
 
    return gpg_error (GPG_ERR_INV_SEXP); 
1240
 
  if (smatch (&s, n, "t1-v1"))
1241
 
    {
1242
 
      if (*s != '(')
1243
 
        return gpg_error (GPG_ERR_INV_SEXP);
1244
 
      *shadow_info = s;
1245
 
    }
1246
 
  else
1247
 
    return gpg_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
1248
 
  return 0;
1249
 
}
1250
 
 
1251
 
 
1252
 
/* Parse the canonical encoded SHADOW_INFO S-expression.  On success
1253
 
   the hex encoded serial number is returned as a malloced strings at
1254
 
   R_HEXSN and the Id string as a malloced string at R_IDSTR.  On
1255
 
   error an error code is returned and NULL is stored at the result
1256
 
   parameters addresses.  If the serial number or the ID string is not
1257
 
   required, NULL may be passed for them.  */
1258
 
gpg_error_t
1259
 
parse_shadow_info (const unsigned char *shadow_info, 
1260
 
                   char **r_hexsn, char **r_idstr)
1261
 
{
1262
 
  const unsigned char *s;
1263
 
  size_t n;
1264
 
 
1265
 
  if (r_hexsn)
1266
 
    *r_hexsn = NULL;
1267
 
  if (r_idstr)
1268
 
    *r_idstr = NULL;
1269
 
 
1270
 
  s = shadow_info;
1271
 
  if (*s != '(')
1272
 
    return gpg_error (GPG_ERR_INV_SEXP);
1273
 
  s++;
1274
 
  n = snext (&s);
1275
 
  if (!n)
1276
 
    return gpg_error (GPG_ERR_INV_SEXP);
1277
 
 
1278
 
  if (r_hexsn)
1279
 
    {
1280
 
      *r_hexsn = bin2hex (s, n, NULL);
1281
 
      if (!*r_hexsn)
1282
 
        return gpg_error_from_syserror ();
1283
 
    }
1284
 
  s += n;
1285
 
 
1286
 
  n = snext (&s);
1287
 
  if (!n)
1288
 
    {
1289
 
      if (r_hexsn)
1290
 
        {
1291
 
          xfree (*r_hexsn);
1292
 
          *r_hexsn = NULL;
1293
 
        }
1294
 
      return gpg_error (GPG_ERR_INV_SEXP);
1295
 
    }
1296
 
  
1297
 
  if (r_idstr)
1298
 
    {
1299
 
      *r_idstr = xtrymalloc (n+1);
1300
 
      if (!*r_idstr)
1301
 
        {
1302
 
          if (r_hexsn)
1303
 
            {
1304
 
              xfree (*r_hexsn);
1305
 
              *r_hexsn = NULL;
1306
 
            }
1307
 
          return gpg_error_from_syserror ();
1308
 
        }
1309
 
      memcpy (*r_idstr, s, n);
1310
 
      (*r_idstr)[n] = 0;
1311
 
    }
1312
 
 
1313
 
  return 0;
1314
 
}
1315