~ubuntu-branches/ubuntu/precise/gnupg2/precise-proposed

« back to all changes in this revision

Viewing changes to scd/app-nks.c

  • Committer: Bazaar Package Importer
  • Author(s): Eric Dorland
  • Date: 2009-03-08 22:46:47 UTC
  • mfrom: (1.1.11 upstream)
  • Revision ID: james.westby@ubuntu.com-20090308224647-gq17gatcl71lrc2k
Tags: 2.0.11-1
* New upstream release. (Closes: #496663)
* debian/control: Make the description a little more distinctive than
  gnupg v1's. Thanks Jari Aalto. (Closes: #496323)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* app-nks.c - The Telesec NKS 2.0 card application.
2
 
 * Copyright (C) 2004, 2007 Free Software Foundation, Inc.
 
1
/* app-nks.c - The Telesec NKS card application.
 
2
 * Copyright (C) 2004, 2007, 2008, 2009 Free Software Foundation, Inc.
3
3
 *
4
4
 * This file is part of GnuPG.
5
5
 *
34
34
static struct
35
35
{
36
36
  int fid;       /* File ID. */
 
37
  int nks_ver;   /* 0 for NKS version 2, 3 for version 3. */
37
38
  int certtype;  /* Type of certificate or 0 if it is not a certificate. */
38
39
  int iskeypair; /* If true has the FID of the correspoding certificate. */
39
40
  int issignkey; /* True if file is a key usable for signing. */
40
41
  int isenckey;  /* True if file is a key usable for decryption. */
41
42
} filelist[] = {
42
 
  { 0x4531, 0,  0xC000, 1, 0 }, 
43
 
  { 0xC000, 101 },
44
 
  { 0x4331, 100 },
45
 
  { 0x4332, 100 },
46
 
  { 0xB000, 110 },
47
 
  { 0x45B1, 0,  0xC200, 0, 1 },
48
 
  { 0xC200, 101 },
49
 
  { 0x43B1, 100 },
50
 
  { 0x43B2, 100 },
51
 
  { 0, 0 }
52
 
};
53
 
 
 
43
  { 0x4531, 0, 0,  0xC000, 1, 0 }, /* EF_PK.NKS.SIG */
 
44
  { 0xC000, 0, 101 },              /* EF_C.NKS.SIG  */
 
45
  { 0x4331, 0, 100 },
 
46
  { 0x4332, 0, 100 },
 
47
  { 0xB000, 0, 110 },              /* EF_PK.RCA.NKS */
 
48
  { 0x45B1, 0, 0,  0xC200, 0, 1 }, /* EF_PK.NKS.ENC */
 
49
  { 0xC200, 0, 101 },              /* EF_C.NKS.ENC  */
 
50
  { 0x43B1, 0, 100 },
 
51
  { 0x43B2, 0, 100 },
 
52
  { 0x4571, 3, 0,  0xc500, 0, 0 }, /* EF_PK.NKS.AUT */
 
53
  { 0xC500, 3, 101 },              /* EF_C.NKS.AUT  */
 
54
  { 0x45B2, 3, 0,  0xC201, 0, 1 }, /* EF_PK.NKS.ENC1024 */
 
55
  { 0xC201, 3, 101 },              /* EF_C.NKS.ENC1024  */
 
56
  { 0 }
 
57
};
 
58
 
 
59
 
 
60
 
 
61
/* Object with application (i.e. NKS) specific data.  */
 
62
struct app_local_s {
 
63
  int nks_version;  /* NKS version.  */
 
64
 
 
65
};
 
66
 
 
67
 
 
68
 
 
69
 
 
70
/* Release local data. */
 
71
static void
 
72
do_deinit (app_t app)
 
73
{
 
74
  if (app && app->app_local)
 
75
    {
 
76
      xfree (app->app_local);
 
77
      app->app_local = NULL;
 
78
    }
 
79
}
54
80
 
55
81
 
56
82
/* Read the file with FID, assume it contains a public key and return
57
83
   its keygrip in the caller provided 41 byte buffer R_GRIPSTR. */
58
84
static gpg_error_t
59
 
keygripstr_from_pk_file (int slot, int fid, char *r_gripstr)
 
85
keygripstr_from_pk_file (app_t app, int fid, char *r_gripstr)
60
86
{
61
87
  gpg_error_t err;
62
88
  unsigned char grip[20];
65
91
  gcry_sexp_t sexp;
66
92
  int i;
67
93
  
68
 
  err = iso7816_select_file (slot, fid, 0, NULL, NULL);
69
 
  if (err)
70
 
    return err;
71
 
  err = iso7816_read_record (slot, 1, 1, 0, &buffer[0], &buflen[0]);
72
 
  if (err)
73
 
    return err;
74
 
  err = iso7816_read_record (slot, 2, 1, 0, &buffer[1], &buflen[1]);
 
94
  err = iso7816_select_file (app->slot, fid, 0, NULL, NULL);
 
95
  if (err)
 
96
    return err;
 
97
  err = iso7816_read_record (app->slot, 1, 1, 0, &buffer[0], &buflen[0]);
 
98
  if (err)
 
99
    return err;
 
100
  err = iso7816_read_record (app->slot, 2, 1, 0, &buffer[1], &buflen[1]);
75
101
  if (err)
76
102
    {
77
103
      xfree (buffer[0]);
78
104
      return err;
79
105
    }
80
106
  
81
 
  for (i=0; i < 2; i++)
 
107
  if (app->app_local->nks_version < 3)
82
108
    {
83
 
      /* Check that the value appears like an integer encoded as
84
 
         Simple-TLV.  We don't check the tag because the tests cards I
85
 
         have use 1 for both, the modulus and the exponent - the
86
 
         example in the documentation gives 2 for the exponent. */
87
 
      if (buflen[i] < 3)
88
 
        err = gpg_error (GPG_ERR_TOO_SHORT);
89
 
      else if (buffer[i][1] != buflen[i]-2 )
90
 
        err = gpg_error (GPG_ERR_INV_OBJ);
 
109
      /* Old versions of NKS store the values in a TLV encoded format.
 
110
         We need to do some checks.  */
 
111
      for (i=0; i < 2; i++)
 
112
        {
 
113
          /* Check that the value appears like an integer encoded as
 
114
             Simple-TLV.  We don't check the tag because the tests cards I
 
115
             have use 1 for both, the modulus and the exponent - the
 
116
             example in the documentation gives 2 for the exponent. */
 
117
          if (buflen[i] < 3)
 
118
            err = gpg_error (GPG_ERR_TOO_SHORT);
 
119
          else if (buffer[i][1] != buflen[i]-2 )
 
120
            err = gpg_error (GPG_ERR_INV_OBJ);
 
121
        }
91
122
    }
92
123
 
93
124
  if (!err)
108
139
    }
109
140
  else
110
141
    {
111
 
      for (i=0; i < 20; i++)
112
 
        sprintf (r_gripstr+i*2, "%02X", grip[i]);
 
142
      bin2hex (grip, 20, r_gripstr);
113
143
    }
114
144
  gcry_sexp_release (sexp);
115
145
  return err;
127
157
  /* Output information about all useful objects. */
128
158
  for (i=0; filelist[i].fid; i++)
129
159
    {
 
160
      if (filelist[i].nks_ver > app->app_local->nks_version)
 
161
        continue;
 
162
 
130
163
      if (filelist[i].certtype)
131
164
        {
132
165
          size_t len;
150
183
        {
151
184
          char gripstr[40+1];
152
185
 
153
 
          err = keygripstr_from_pk_file (app->slot, filelist[i].fid, gripstr);
 
186
          err = keygripstr_from_pk_file (app, filelist[i].fid, gripstr);
154
187
          if (err)
155
188
            log_error ("can't get keygrip from FID 0x%04X: %s\n",
156
189
                       filelist[i].fid, gpg_strerror (err));
414
447
  if (indatalen != 20 && indatalen != 16 && indatalen != 35)
415
448
    return gpg_error (GPG_ERR_INV_VALUE);
416
449
 
417
 
  /* Check that the provided ID is vaid.  This is not really needed
 
450
  /* Check that the provided ID is valid.  This is not really needed
418
451
     but we do it to enforce correct usage by the caller. */
419
452
  if (strncmp (keyidstr, "NKS-DF01.", 9) ) 
420
453
    return gpg_error (GPG_ERR_INV_ID);
517
550
}
518
551
 
519
552
 
520
 
 
521
 
/* Select the NKS 2.0 application.  */
 
553
/* Handle the PASSWD command.  CHVNOSTR is currently ignored; we
 
554
   always use VHV0.  RESET_MODE is not yet implemented.  */
 
555
static gpg_error_t 
 
556
do_change_pin (app_t app, ctrl_t ctrl,  const char *chvnostr, 
 
557
               unsigned int flags,
 
558
               gpg_error_t (*pincb)(void*, const char *, char **),
 
559
               void *pincb_arg)
 
560
{
 
561
  gpg_error_t err;
 
562
  char *pinvalue;
 
563
  const char *oldpin;
 
564
  size_t oldpinlen;
 
565
 
 
566
  (void)ctrl;
 
567
  (void)chvnostr;
 
568
 
 
569
  if ((flags & APP_CHANGE_FLAG_RESET))
 
570
    return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
 
571
 
 
572
  if ((flags & APP_CHANGE_FLAG_NULLPIN))
 
573
    {
 
574
      /* With the nullpin flag, we do not verify the PIN - it would fail
 
575
         if the Nullpin is still set.  */
 
576
      oldpin = "\0\0\0\0\0";
 
577
      oldpinlen = 6;
 
578
    }
 
579
  else
 
580
    {
 
581
      err = verify_pin (app, pincb, pincb_arg);
 
582
      if (err)
 
583
        return err;
 
584
      oldpin = NULL;
 
585
      oldpinlen = 0;
 
586
    }
 
587
 
 
588
  /* TRANSLATORS: Do not translate the "|*|" prefixes but
 
589
     keep it at the start of the string.  We need this elsewhere
 
590
     to get some infos on the string. */
 
591
  err = pincb (pincb_arg, _("|N|New PIN"), &pinvalue); 
 
592
  if (err)
 
593
    {
 
594
      log_error (_("error getting new PIN: %s\n"), gpg_strerror (err));
 
595
      return err;
 
596
    }
 
597
 
 
598
  err = iso7816_change_reference_data (app->slot, 0x00, 
 
599
                                       oldpin, oldpinlen,
 
600
                                       pinvalue, strlen (pinvalue));
 
601
  xfree (pinvalue);
 
602
  return err;
 
603
}
 
604
 
 
605
 
 
606
/* Perform a simple verify operation.  KEYIDSTR should be NULL or empty.  */
 
607
static gpg_error_t 
 
608
do_check_pin (app_t app, const char *keyidstr,
 
609
              gpg_error_t (*pincb)(void*, const char *, char **),
 
610
              void *pincb_arg)
 
611
{
 
612
  (void)keyidstr;
 
613
  return verify_pin (app, pincb, pincb_arg);
 
614
}
 
615
 
 
616
 
 
617
/* Return the version of the NKS application.  */
 
618
static int
 
619
get_nks_version (int slot)
 
620
{
 
621
  unsigned char *result = NULL;
 
622
  size_t resultlen;
 
623
  int type;
 
624
 
 
625
  if (iso7816_apdu_direct (slot, "\x80\xaa\x06\x00\x00", 5, 0, 
 
626
                           &result, &resultlen))
 
627
    return 2; /* NKS 2 does not support this command.  */
 
628
  
 
629
  /* Example value:    04 11 19 22 21 6A 20 80 03 03 01 01 01 00 00 00
 
630
                       vv tt ccccccccccccccccc aa bb cc vvvvvvvvvvv xx
 
631
     vendor (Philips) -+  |  |                 |  |  |  |           |
 
632
     chip type -----------+  |                 |  |  |  |           |
 
633
     chip id ----------------+                 |  |  |  |           |
 
634
     card type (3 - tcos 3) -------------------+  |  |  |           |
 
635
     OS version of card type ---------------------+  |  |           |
 
636
     OS release of card type ------------------------+  |           |
 
637
     OS vendor internal version ------------------------+           |
 
638
     RFU -----------------------------------------------------------+
 
639
  */
 
640
  if (resultlen < 16)
 
641
    type = 0;  /* Invalid data returned.  */
 
642
  else
 
643
    type = result[8];
 
644
  xfree (result);
 
645
 
 
646
  return type;
 
647
}
 
648
 
 
649
 
 
650
/* Select the NKS application.  */
522
651
gpg_error_t
523
652
app_select_nks (app_t app)
524
653
{
531
660
    {
532
661
      app->apptype = "NKS";
533
662
 
 
663
      app->app_local = xtrycalloc (1, sizeof *app->app_local);
 
664
      if (!app->app_local)
 
665
        {
 
666
          rc = gpg_error (gpg_err_code_from_errno (errno));
 
667
          goto leave;
 
668
        }
 
669
 
 
670
      app->app_local->nks_version = get_nks_version (slot);
 
671
      if (opt.verbose)
 
672
        log_info ("Detected NKS version: %d\n", app->app_local->nks_version);
 
673
 
 
674
      app->fnc.deinit = do_deinit;
534
675
      app->fnc.learn_status = do_learn_status;
535
676
      app->fnc.readcert = do_readcert;
536
677
      app->fnc.getattr = NULL;
539
680
      app->fnc.sign = do_sign;
540
681
      app->fnc.auth = NULL;
541
682
      app->fnc.decipher = do_decipher;
542
 
      app->fnc.change_pin = NULL;
543
 
      app->fnc.check_pin = NULL;
 
683
      app->fnc.change_pin = do_change_pin;
 
684
      app->fnc.check_pin = do_check_pin;
544
685
   }
545
686
 
 
687
 leave:
 
688
  if (rc)
 
689
    do_deinit (app);
546
690
  return rc;
547
691
}
548
692