* scdaemon.c: New option --debug-sc N.
[gnupg.git] / scd / card-p15.c
1 /* card-p15.c - PKCS-15 based card access
2  *      Copyright (C) 2002 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <errno.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <time.h>
27
28 #include <opensc-pkcs15.h>
29 #include <ksba.h>
30
31 #include "scdaemon.h"
32 #include "card-common.h"
33
34
35 /* See card.c for interface description */
36 static int
37 p15_enum_keypairs (CARD card, int idx,
38                    unsigned char *keygrip, char **keyid)
39 {
40   int rc;
41   KsbaError krc;
42   struct sc_pkcs15_object *objs[32], *tmpobj;
43   int nobjs;
44   struct sc_pkcs15_prkey_info *pinfo;
45   struct sc_pkcs15_cert_info *certinfo;
46   struct sc_pkcs15_cert      *certder;
47   KsbaCert cert;
48
49   rc = sc_pkcs15_get_objects (card->p15card, SC_PKCS15_TYPE_PRKEY_RSA, 
50                               objs, DIM (objs));
51   if (rc < 0) 
52     {
53       log_error ("private keys enumeration failed: %s\n", sc_strerror (rc));
54       return GNUPG_Card_Error;
55     }
56   nobjs = rc;
57   rc = 0;
58   if (idx >= nobjs)
59     return -1;
60   pinfo = objs[idx]->data;
61   
62   /* now we need to read the certificate so that we can calculate the
63      keygrip */
64   rc = sc_pkcs15_find_cert_by_id (card->p15card, &pinfo->id, &tmpobj);
65   if (rc)
66     {
67       log_info ("certificate for private key %d not found: %s\n",
68                 idx, sc_strerror (rc));
69       /* note, that we return the ID anyway */
70       rc = GNUPG_Missing_Certificate;
71       goto return_keyid;
72     }
73   certinfo = tmpobj->data;
74   rc = sc_pkcs15_read_certificate (card->p15card, certinfo, &certder);
75   if (rc)
76     {
77       log_info ("failed to read certificate for private key %d: %s\n",
78                 idx, sc_strerror (rc));
79       return GNUPG_Card_Error;
80     }
81
82   cert = ksba_cert_new ();
83   if (!cert)
84     {
85       sc_pkcs15_free_certificate (certder);
86       return GNUPG_Out_Of_Core;
87     }
88   krc = ksba_cert_init_from_mem (cert, certder->data, certder->data_len);
89   sc_pkcs15_free_certificate (certder);
90   if (krc)
91     {
92       log_error ("failed to parse the certificate for private key %d: %s\n",
93                  idx, ksba_strerror (krc));
94       ksba_cert_release (cert);
95       return GNUPG_Card_Error;
96     }
97   if (card_help_get_keygrip (cert, keygrip))
98     {
99       log_error ("failed to calculate the keygrip of private key %d\n", idx);
100       ksba_cert_release (cert);
101       return GNUPG_Card_Error;
102     }      
103   ksba_cert_release (cert);
104
105   rc = 0;
106  return_keyid:
107   if (keyid)
108     {
109       char *p;
110       int i;
111
112       *keyid = p = xtrymalloc (9+pinfo->id.len*2+1);
113       if (!*keyid)
114         return GNUPG_Out_Of_Core;
115       p = stpcpy (p, "P15-5015.");
116       for (i=0; i < pinfo->id.len; i++, p += 2)
117         sprintf (p, "%02X", pinfo->id.value[i]);
118       *p = 0;
119     }
120   
121   return rc;
122 }
123
124
125 \f
126 static int
127 idstr_to_id (const char *idstr, struct sc_pkcs15_id *id)
128 {
129   const char *s;
130   int n;
131
132   /* For now we only support the standard DF */
133   if (strncmp (idstr, "P15-5015.", 9) ) 
134     return GNUPG_Invalid_Id;
135   for (s=idstr+9, n=0; hexdigitp (s); s++, n++)
136     ;
137   if (*s || (n&1))
138     return GNUPG_Invalid_Id; /* invalid or odd number of digits */
139   n /= 2;
140   if (!n || n > SC_PKCS15_MAX_ID_SIZE)
141     return GNUPG_Invalid_Id; /* empty or too large */
142   for (s=idstr+9, n=0; *s; s += 2, n++)
143     id->value[n] = xtoi_2 (s);
144   id->len = n;
145   return 0;
146 }
147
148
149 /* See card.c for interface description */
150 static int
151 p15_read_cert (CARD card, const char *certidstr,
152                unsigned char **cert, size_t *ncert)
153 {
154   struct sc_pkcs15_object *tmpobj;
155   struct sc_pkcs15_id certid;
156   struct sc_pkcs15_cert_info *certinfo;
157   struct sc_pkcs15_cert      *certder;
158   int rc;
159
160   if (!card || !certidstr || !cert || !ncert)
161     return GNUPG_Invalid_Value;
162   if (!card->p15card)
163     return GNUPG_No_PKCS15_App;
164
165   rc = idstr_to_id (certidstr, &certid);
166   if (rc)
167     return rc;
168
169   rc = sc_pkcs15_find_cert_by_id (card->p15card, &certid, &tmpobj);
170   if (rc)
171     {
172       log_info ("certificate '%s' not found: %s\n", 
173                 certidstr, sc_strerror (rc));
174       return -1;
175     }
176   certinfo = tmpobj->data;
177   rc = sc_pkcs15_read_certificate (card->p15card, certinfo, &certder);
178   if (rc)
179     {
180       log_info ("failed to read certificate '%s': %s\n",
181                 certidstr, sc_strerror (rc));
182       return GNUPG_Card_Error;
183     }
184
185   *cert = xtrymalloc (certder->data_len);
186   if (!*cert)
187     {
188       sc_pkcs15_free_certificate (certder);
189       return GNUPG_Out_Of_Core;
190     }
191   memcpy (*cert, certder->data, certder->data_len);
192   *ncert = certder->data_len;
193   sc_pkcs15_free_certificate (certder);
194   return 0;
195 }
196
197
198
199
200 \f
201 static int
202 p15_prepare_key (CARD card, const char *keyidstr,
203                  int (pincb)(void*, const char *, char **),
204                  void *pincb_arg, struct sc_pkcs15_object **r_keyobj)
205 {
206   struct sc_pkcs15_id keyid;
207   struct sc_pkcs15_pin_info *pin;
208   struct sc_pkcs15_object *keyobj, *pinobj;
209   char *pinvalue;
210   int rc;
211
212   rc = idstr_to_id (keyidstr, &keyid);
213   if (rc)
214     return rc;
215
216   rc = sc_pkcs15_find_prkey_by_id (card->p15card, &keyid, &keyobj);
217   if (rc < 0)
218     {
219       log_error ("private key not found: %s\n", sc_strerror(rc));
220       return GNUPG_No_Secret_Key;
221     }
222
223   rc = sc_pkcs15_find_pin_by_auth_id (card->p15card,
224                                       &keyobj->auth_id, &pinobj);
225   if (rc)
226     {
227       log_error ("failed to find PIN by auth ID: %s\n", sc_strerror (rc));
228       return GNUPG_Bad_PIN_Method;
229     }
230   pin = pinobj->data;
231
232   /* Fixme: pack this into a verification loop */
233   /* Fixme: we might want to pass pin->min_length and 
234      pin->stored_length */
235   rc = pincb (pincb_arg, pinobj->label, &pinvalue);
236   if (rc)
237     {
238       log_info ("PIN callback returned error: %s\n", gnupg_strerror (rc));
239       return rc;
240     }
241
242   rc = sc_pkcs15_verify_pin (card->p15card, pin,
243                              pinvalue, strlen (pinvalue));
244   xfree (pinvalue);
245   if (rc)
246     {
247       log_info ("PIN verification failed: %s\n", sc_strerror (rc));
248       return GNUPG_Bad_PIN;
249     }
250
251   /* fixme: check wheter we need to release KEYOBJ in case of an error */
252   *r_keyobj = keyobj;
253   return 0;
254 }
255
256
257 /* See card.c for interface description */
258 static int 
259 p15_sign (CARD card, const char *keyidstr, int hashalgo,
260           int (pincb)(void*, const char *, char **),
261           void *pincb_arg,
262           const void *indata, size_t indatalen,
263           void **outdata, size_t *outdatalen )
264 {
265   unsigned int cryptflags;
266   struct sc_pkcs15_object *keyobj;
267   int rc;
268   unsigned char *outbuf = NULL;
269   size_t outbuflen;
270
271   if (hashalgo != GCRY_MD_SHA1)
272     return GNUPG_Unsupported_Algorithm;
273
274   rc = p15_prepare_key (card, keyidstr, pincb, pincb_arg, &keyobj);
275   if (rc)
276     return rc;
277
278   cryptflags = SC_ALGORITHM_RSA_PAD_PKCS1;
279
280   outbuflen = 1024; 
281   outbuf = xtrymalloc (outbuflen);
282   if (!outbuf)
283     return GNUPG_Out_Of_Core;
284   
285   rc = sc_pkcs15_compute_signature (card->p15card, keyobj,
286                                     cryptflags,
287                                     indata, indatalen,
288                                     outbuf, outbuflen );
289   if (rc < 0)
290     {
291       log_error ("failed to create signature: %s\n", sc_strerror (rc));
292       rc = GNUPG_Card_Error;
293     }
294   else
295     {
296       *outdatalen = rc;
297       *outdata = outbuf;
298       outbuf = NULL;
299       rc = 0;
300     }
301
302   xfree (outbuf);
303   return rc;
304 }
305
306
307 /* See card.c for description */
308 static int 
309 p15_decipher (CARD card, const char *keyidstr,
310               int (pincb)(void*, const char *, char **),
311               void *pincb_arg,
312               const void *indata, size_t indatalen,
313               void **outdata, size_t *outdatalen )
314 {
315   struct sc_pkcs15_object *keyobj;
316   int rc;
317   unsigned char *outbuf = NULL;
318   size_t outbuflen;
319
320   rc = p15_prepare_key (card, keyidstr, pincb, pincb_arg, &keyobj);
321   if (rc)
322     return rc;
323
324   if (card && card->scard && card->scard->driver
325       && !strcasecmp (card->scard->driver->short_name, "tcos"))
326     {
327       /* very ugly hack to force the use of a local key.  We need this
328          until we have fixed the initialization code for TCOS cards */
329       struct sc_pkcs15_prkey_info *prkey = keyobj->data;
330       if ( !(prkey->key_reference & 0x80))
331         {
332           prkey->key_reference |= 0x80;
333           log_debug ("using TCOS hack to force the use of local keys\n");
334         }
335       if (*keyidstr && keyidstr[strlen(keyidstr)-1] == '6')
336         {
337           prkey->key_reference |= 1;
338           log_debug ("warning: using even more TCOS hacks\n");
339         }
340     }
341
342   outbuflen = indatalen < 256? 256 : indatalen; 
343   outbuf = xtrymalloc (outbuflen);
344   if (!outbuf)
345     return GNUPG_Out_Of_Core;
346
347   rc = sc_pkcs15_decipher (card->p15card, keyobj, 
348                            indata, indatalen, 
349                            outbuf, outbuflen); 
350   if (rc < 0)
351     {
352       log_error ("failed to decipher the data: %s\n", sc_strerror (rc));
353       rc = GNUPG_Card_Error;
354     }
355   else
356     {
357       *outdatalen = rc;
358       *outdata = outbuf;
359       outbuf = NULL;
360       rc = 0;
361     }
362
363   xfree (outbuf);
364   return rc;
365 }
366
367
368
369 /* Bind our operations to the card */
370 void
371 card_p15_bind (CARD card)
372 {
373   card->fnc.enum_keypairs = p15_enum_keypairs;
374   card->fnc.read_cert     = p15_read_cert;
375   card->fnc.sign          = p15_sign;
376   card->fnc.decipher      = p15_decipher;
377 }