~ubuntu-branches/ubuntu/oneiric/gnupg2/oneiric-updates

« back to all changes in this revision

Viewing changes to agent/protect.c

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Viehmann
  • Date: 2008-10-04 10:25:53 UTC
  • mfrom: (5.1.15 intrepid)
  • Revision ID: james.westby@ubuntu.com-20081004102553-fv62pp8dsitxli47
Tags: 2.0.9-3.1
* Non-maintainer upload.
* agent/gpg-agent.c: Deinit the threading library before exec'ing
  the command to run in --daemon mode. And because that still doesn't
  restore the sigprocmask, do that manually. Closes: #499569

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* protect.c - Un/Protect a secret key
2
2
 * Copyright (C) 1998, 1999, 2000, 2001, 2002,
3
 
 *               2003 Free Software Foundation, Inc.
 
3
 *               2003, 2007 Free Software Foundation, Inc.
4
4
 *
5
5
 * This file is part of GnuPG.
6
6
 *
7
7
 * GnuPG is free software; you can redistribute it and/or modify
8
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
 
9
 * the Free Software Foundation; either version 3 of the License, or
10
10
 * (at your option) any later version.
11
11
 *
12
12
 * GnuPG is distributed in the hope that it will be useful,
15
15
 * GNU General Public License for more details.
16
16
 *
17
17
 * You should have received a copy of the GNU General Public License
18
 
 * along with this program; if not, write to the Free Software
19
 
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 
18
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20
19
 */
21
20
 
22
21
#include <config.h>
164
163
     ((<parameter_list>)(4:hash4:sha120:<hashvalue>)) + padding
165
164
 
166
165
     We always append a full block of random bytes as padding but
167
 
     encrypt only what is needed for a full blocksize */
 
166
     encrypt only what is needed for a full blocksize.  */
168
167
  blklen = gcry_cipher_get_algo_blklen (PROT_CIPHER);
169
168
  outlen = 2 + protlen + 2 + 6 + 6 + 23 + 2 + blklen;
170
169
  enclen = outlen/blklen * blklen;
230
229
       encrypted_octet_string)
231
230
       
232
231
     in canoncical format of course.  We use asprintf and %n modifier
233
 
     and spaces as palceholders.  */
234
 
  asprintf (&p,
235
 
            "(9:protected%d:%s((4:sha18:%n_8bytes_2:96)%d:%n%*s)%d:%n%*s)",
236
 
            (int)strlen (modestr), modestr,
237
 
            &saltpos, 
238
 
            blklen, &ivpos, blklen, "",
239
 
            enclen, &encpos, enclen, "");
240
 
  if (p)
241
 
    { /* asprintf does not use our malloc system */
242
 
      char *psave = p;
243
 
      p = xtrymalloc (strlen (psave)+1);
244
 
      if (p)
245
 
        strcpy (p, psave);
246
 
      free (psave);
247
 
    }
 
232
     and dummy values as placeholders.  */
 
233
  p = xtryasprintf
 
234
    ("(9:protected%d:%s((4:sha18:%n_8bytes_2:96)%d:%n%*s)%d:%n%*s)",
 
235
     (int)strlen (modestr), modestr,
 
236
     &saltpos, 
 
237
     blklen, &ivpos, blklen, "",
 
238
     enclen, &encpos, enclen, "");
248
239
  if (!p)
249
240
    {
250
241
      gpg_error_t tmperr = out_of_core ();
277
268
  size_t n;
278
269
  int c, infidx, i;
279
270
  unsigned char hashvalue[20];
 
271
  char timestamp_exp[35];
280
272
  unsigned char *protected;
281
273
  size_t protectedlen;
282
274
  int depth = 0;
283
275
  unsigned char *p;
284
 
 
 
276
  gcry_md_hd_t md;
 
277
 
 
278
  /* Create an S-expression with the procted-at timestamp.  */
 
279
  memcpy (timestamp_exp, "(12:protected-at15:", 19);
 
280
  gnupg_get_isotime (timestamp_exp+19);
 
281
  timestamp_exp[19+15] = ')';
 
282
 
 
283
  /* Parse original key.  */
285
284
  s = plainkey;
286
285
  if (*s != '(')
287
286
    return gpg_error (GPG_ERR_INV_SEXP);
346
345
  assert (!depth);
347
346
  real_end = s-1;
348
347
 
349
 
  gcry_md_hash_buffer (GCRY_MD_SHA1, hashvalue,
350
 
                       hash_begin, hash_end - hash_begin + 1);
 
348
  
 
349
  /* Hash the stuff.  Because the timestamp_exp won't get protected,
 
350
     we can't simply hash a continuous buffer but need to use several
 
351
     md_writes.  */ 
 
352
  rc = gcry_md_open (&md, GCRY_MD_SHA1, 0 );
 
353
  if (rc)
 
354
    return rc;
 
355
  gcry_md_write (md, hash_begin, hash_end - hash_begin);
 
356
  gcry_md_write (md, timestamp_exp, 35);
 
357
  gcry_md_write (md, ")", 1);
 
358
  memcpy (hashvalue, gcry_md_read (md, GCRY_MD_SHA1), 20);
 
359
  gcry_md_close (md);
351
360
 
352
361
  rc = do_encryption (prot_begin, prot_end - prot_begin + 1,
353
362
                      passphrase,  hashvalue,
357
366
 
358
367
  /* Now create the protected version of the key.  Note that the 10
359
368
     extra bytes are for for the inserted "protected-" string (the
360
 
     beginning of the plaintext reads: "((11:private-key(" ). */
 
369
     beginning of the plaintext reads: "((11:private-key(" ).  The 35
 
370
     term is the space for (12:protected-at15:<timestamp>).  */
361
371
  *resultlen = (10
362
372
                + (prot_begin-plainkey)
363
373
                + protectedlen
 
374
                + 35
364
375
                + (real_end-prot_end));
365
376
  *result = p = xtrymalloc (*resultlen);
366
377
  if (!p)
375
386
  p += prot_begin - plainkey - 4;
376
387
  memcpy (p, protected, protectedlen);
377
388
  p += protectedlen;
 
389
 
 
390
  memcpy (p, timestamp_exp, 35);
 
391
  p += 35;
 
392
 
378
393
  memcpy (p, prot_end+1, real_end - prot_end);
379
394
  p += real_end - prot_end;
380
395
  assert ( p - *result == *resultlen);
381
396
  xfree (protected);
 
397
 
382
398
  return 0;
383
399
}
384
400
 
458
474
/* Merge the parameter list contained in CLEARTEXT with the original
459
475
   protect lists PROTECTEDKEY by replacing the list at REPLACEPOS.
460
476
   Return the new list in RESULT and the MIC value in the 20 byte
461
 
   buffer SHA1HASH. */
 
477
   buffer SHA1HASH.  CUTOFF and CUTLEN will receive the offset and the
 
478
   length of the resulting list which should go into the MIC
 
479
   calculation but then be removed.  */
462
480
static int
463
481
merge_lists (const unsigned char *protectedkey,
464
482
             size_t replacepos, 
465
483
             const unsigned char *cleartext,
466
484
             unsigned char *sha1hash,
467
 
             unsigned char **result, size_t *resultlen)
 
485
             unsigned char **result, size_t *resultlen,
 
486
             size_t *cutoff, size_t *cutlen)
468
487
{
469
488
  size_t n, newlistlen;
470
489
  unsigned char *newlist, *p;
474
493
  
475
494
  *result = NULL;
476
495
  *resultlen = 0;
 
496
  *cutoff = 0;
 
497
  *cutlen = 0;
477
498
 
478
499
  if (replacepos < 26)
479
500
    return gpg_error (GPG_ERR_BUG);
523
544
    goto invalid_sexp;
524
545
  endpos = s;
525
546
  s++;
526
 
  /* short intermezzo: Get the MIC */
 
547
  /* Intermezzo: Get the MIC */
527
548
  if (*s != '(')
528
549
    goto invalid_sexp;
529
550
  s++;
540
561
  s += n;
541
562
  if (*s != ')')
542
563
    goto invalid_sexp;
543
 
  /* end intermezzo */
 
564
  /* End intermezzo */
544
565
 
545
566
  /* append the parameter list */
546
567
  memcpy (p, startpos, endpos - startpos);
547
568
  p += endpos - startpos;
548
569
  
549
 
  /* skip overt the protected list element in the original list */
 
570
  /* Skip over the protected list element in the original list.  */
550
571
  s = protectedkey + replacepos;
551
572
  assert (*s == '(');
552
573
  s++;
554
575
  rc = sskip (&s, &i);
555
576
  if (rc)
556
577
    goto failure;
 
578
  /* Record the position of the optional protected-at expression.  */
 
579
  if (*s == '(')
 
580
    {
 
581
      const unsigned char *save_s = s;
 
582
      s++;
 
583
      n = snext (&s);
 
584
      if (smatch (&s, n, "protected-at"))
 
585
        {
 
586
          i = 1;
 
587
          rc = sskip (&s, &i);
 
588
          if (rc)
 
589
            goto failure;
 
590
          *cutlen = s - save_s;
 
591
        }
 
592
      s = save_s;
 
593
    }
557
594
  startpos = s;
558
595
  i = 2; /* we are inside this level */
559
596
  rc = sskip (&s, &i);
562
599
  assert (s[-1] == ')');
563
600
  endpos = s; /* one behind the end of the list */
564
601
 
565
 
  /* append the rest */
 
602
  /* Append the rest. */
 
603
  if (*cutlen)
 
604
    *cutoff = p - newlist;
566
605
  memcpy (p, startpos, endpos - startpos);
567
606
  p += endpos - startpos;
 
607
  
568
608
 
569
609
  /* ready */
570
610
  *result = newlist;
585
625
 
586
626
 
587
627
/* Unprotect the key encoded in canonical format.  We assume a valid
588
 
   S-Exp here. */
 
628
   S-Exp here.  If a protected-at item is available, its value will
 
629
   be stored at protocted_at unless this is NULL.  */
589
630
int 
590
631
agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
 
632
                 gnupg_isotime_t protected_at, 
591
633
                 unsigned char **result, size_t *resultlen)
592
634
{
593
635
  int rc;
594
636
  const unsigned char *s;
 
637
  const unsigned char *protect_list; 
595
638
  size_t n;
596
639
  int infidx, i;
597
640
  unsigned char sha1hash[20], sha1hash2[20];
602
645
  unsigned char *cleartext;
603
646
  unsigned char *final;
604
647
  size_t finallen;
 
648
  size_t cutoff, cutlen;
 
649
 
 
650
  if (protected_at)
 
651
    *protected_at = 0;
605
652
 
606
653
  s = protectedkey;
607
654
  if (*s != '(')
625
672
  if (!protect_info[infidx].algo)
626
673
    return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); 
627
674
 
 
675
 
 
676
  /* See wether we have a protected-at timestamp.  */
 
677
  protect_list = s;  /* Save for later.  */
 
678
  if (protected_at)
 
679
    {
 
680
      while (*s == '(')
 
681
        {
 
682
          prot_begin = s;
 
683
          s++;
 
684
          n = snext (&s);
 
685
          if (!n)
 
686
            return gpg_error (GPG_ERR_INV_SEXP);
 
687
          if (smatch (&s, n, "protected-at"))
 
688
            {
 
689
              n = snext (&s);
 
690
              if (!n)
 
691
                return gpg_error (GPG_ERR_INV_SEXP);
 
692
              if (n != 15)
 
693
                return gpg_error (GPG_ERR_UNKNOWN_SEXP);
 
694
              memcpy (protected_at, s, 15);
 
695
              protected_at[15] = 0;
 
696
              break;
 
697
            }
 
698
          s += n;
 
699
          i = 1;
 
700
          rc = sskip (&s, &i);
 
701
          if (rc)
 
702
            return rc;
 
703
        }
 
704
    }
 
705
 
628
706
  /* Now find the list with the protected information.  Here is an
629
707
     example for such a list:
630
708
     (protected openpgp-s2k3-sha1-aes-cbc 
631
709
        ((sha1 <salt> <count>) <Initialization_Vector>)
632
710
        <encrypted_data>)
633
711
   */
 
712
  s = protect_list;
634
713
  for (;;)
635
714
    {
636
715
      if (*s != '(')
701
780
    return rc;
702
781
 
703
782
  rc = merge_lists (protectedkey, prot_begin-protectedkey, cleartext,
704
 
                    sha1hash, &final, &finallen);
 
783
                    sha1hash, &final, &finallen, &cutoff, &cutlen);
705
784
  /* Albeit cleartext has been allocated in secure memory and thus
706
785
     xfree will wipe it out, we do an extra wipe just in case
707
786
     somethings goes badly wrong. */
719
798
      xfree (final);
720
799
      return rc;
721
800
    }
 
801
  /* Now remove tha part which is included in the MIC but should not
 
802
     go into the final thing.  */
 
803
  if (cutlen)
 
804
    {
 
805
      memmove (final+cutoff, final+cutoff+cutlen, finallen-cutoff-cutlen);
 
806
      finallen -= cutlen;
 
807
    }
722
808
 
723
809
  *result = final;
724
810
  *resultlen = gcry_sexp_canon_len (final, 0, NULL, NULL);
845
931
{
846
932
  const char *s;
847
933
  char *info, *p;
848
 
  char numbuf[21];
849
 
  int n;
 
934
  char numbuf[20];
 
935
  size_t n;
850
936
 
851
937
  for (s=serialno, n=0; *s && s[1]; s += 2)
852
938
    n++;
853
939
 
854
 
  info = p = xtrymalloc (1 + 21 + n
855
 
                           + 21 + strlen (idstring) + 1 + 1);
 
940
  info = p = xtrymalloc (1 + sizeof numbuf + n
 
941
                           + sizeof numbuf + strlen (idstring) + 1 + 1);
856
942
  if (!info)
857
943
    return NULL;
858
944
  *p++ = '(';
859
 
  sprintf (numbuf, "%d:", n);
860
 
  p = stpcpy (p, numbuf);
 
945
  p = stpcpy (p, smklen (numbuf, sizeof numbuf, n, NULL));
861
946
  for (s=serialno; *s && s[1]; s += 2)
862
947
    *(unsigned char *)p++ = xtoi_2 (s);
863
 
  sprintf (numbuf, "%d:", strlen (idstring));
864
 
  p = stpcpy (p, numbuf);
 
948
  p = stpcpy (p, smklen (numbuf, sizeof numbuf, strlen (idstring), NULL));
865
949
  p = stpcpy (p, idstring);
866
950
  *p++ = ')';
867
951
  *p = 0;