More stuff for SCs - don't expect them to work.
[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 \f
36
37
38 /* See card.c for interface description */
39 static int
40 p15_enum_keypairs (CARD card, int idx,
41                    unsigned char *keygrip, char **keyid)
42 {
43   int rc;
44   KsbaError krc;
45   struct sc_pkcs15_object *objs[32], *tmpobj;
46   int nobjs;
47   struct sc_pkcs15_prkey_info *pinfo;
48   struct sc_pkcs15_cert_info *certinfo;
49   struct sc_pkcs15_cert      *certder;
50   KsbaCert cert;
51
52   rc = sc_pkcs15_get_objects (card->p15card, SC_PKCS15_TYPE_PRKEY_RSA, 
53                               objs, DIM (objs));
54   if (rc < 0) 
55     {
56       log_error ("private keys enumeration failed: %s\n", sc_strerror (rc));
57       return GNUPG_Card_Error;
58     }
59   nobjs = rc;
60   rc = 0;
61   if (idx >= nobjs)
62     return -1;
63   pinfo = objs[idx]->data;
64   
65   /* now we need to read the certificate so that we can calculate the
66      keygrip */
67   rc = sc_pkcs15_find_cert_by_id (card->p15card, &pinfo->id, &tmpobj);
68   if (rc)
69     {
70       log_info ("certificate for private key %d not found: %s\n",
71                 idx, sc_strerror (rc));
72       /* note, that we return the ID anyway */
73       rc = GNUPG_Missing_Certificate;
74       goto return_keyid;
75     }
76   certinfo = tmpobj->data;
77   rc = sc_pkcs15_read_certificate (card->p15card, certinfo, &certder);
78   if (rc)
79     {
80       log_info ("failed to read certificate for private key %d: %s\n",
81                 idx, sc_strerror (rc));
82       return GNUPG_Card_Error;
83     }
84
85   cert = ksba_cert_new ();
86   if (!cert)
87     {
88       sc_pkcs15_free_certificate (certder);
89       return GNUPG_Out_Of_Core;
90     }
91   krc = ksba_cert_init_from_mem (cert, certder->data, certder->data_len);
92   sc_pkcs15_free_certificate (certder);
93   if (krc)
94     {
95       log_error ("failed to parse the certificate for private key %d: %s\n",
96                  idx, ksba_strerror (krc));
97       ksba_cert_release (cert);
98       return GNUPG_Card_Error;
99     }
100   if (card_help_get_keygrip (cert, keygrip))
101     {
102       log_error ("failed to calculate the keygrip of private key %d\n", idx);
103       ksba_cert_release (cert);
104       return GNUPG_Card_Error;
105     }      
106   ksba_cert_release (cert);
107
108   rc = 0;
109  return_keyid:
110   if (keyid)
111     {
112       char *p;
113       int i;
114
115       *keyid = p = xtrymalloc (9+pinfo->id.len*2+1);
116       if (!*keyid)
117         return GNUPG_Out_Of_Core;
118       p = stpcpy (p, "P15-5015.");
119       for (i=0; i < pinfo->id.len; i++, p += 2)
120         sprintf (p, "%02X", pinfo->id.value[i]);
121       *p = 0;
122     }
123   
124   return rc;
125 }
126
127
128 \f
129 static int
130 idstr_to_id (const char *idstr, struct sc_pkcs15_id *id)
131 {
132   const char *s;
133   int n;
134
135   /* For now we only support the standard DF */
136   if (strncmp (idstr, "P15-5015.", 9) ) 
137     return GNUPG_Invalid_Id;
138   for (s=idstr+9, n=0; hexdigitp (s); s++, n++)
139     ;
140   if (*s || (n&1))
141     return GNUPG_Invalid_Id; /* invalid or odd number of digits */
142   n /= 2;
143   if (!n || n > SC_PKCS15_MAX_ID_SIZE)
144     return GNUPG_Invalid_Id; /* empty or too large */
145   for (s=idstr+9, n=0; *s; s += 2, n++)
146     id->value[n] = xtoi_2 (s);
147   id->len = n;
148   return 0;
149 }
150
151
152 /* See card.c for interface description */
153 static int
154 p15_read_cert (CARD card, const char *certidstr,
155                unsigned char **cert, size_t *ncert)
156 {
157   struct sc_pkcs15_object *tmpobj;
158   struct sc_pkcs15_id certid;
159   struct sc_pkcs15_cert_info *certinfo;
160   struct sc_pkcs15_cert      *certder;
161   int rc;
162
163   if (!card || !certidstr || !cert || !ncert)
164     return GNUPG_Invalid_Value;
165   if (!card->p15card)
166     return GNUPG_No_PKCS15_App;
167
168   rc = idstr_to_id (certidstr, &certid);
169   if (rc)
170     return rc;
171
172   rc = sc_pkcs15_find_cert_by_id (card->p15card, &certid, &tmpobj);
173   if (rc)
174     {
175       log_info ("certificate '%s' not found: %s\n", 
176                 certidstr, sc_strerror (rc));
177       return -1;
178     }
179   certinfo = tmpobj->data;
180   rc = sc_pkcs15_read_certificate (card->p15card, certinfo, &certder);
181   if (rc)
182     {
183       log_info ("failed to read certificate '%s': %s\n",
184                 certidstr, sc_strerror (rc));
185       return GNUPG_Card_Error;
186     }
187
188   *cert = xtrymalloc (certder->data_len);
189   if (!*cert)
190     {
191       sc_pkcs15_free_certificate (certder);
192       return GNUPG_Out_Of_Core;
193     }
194   memcpy (*cert, certder->data, certder->data_len);
195   *ncert = certder->data_len;
196   sc_pkcs15_free_certificate (certder);
197   return 0;
198 }
199
200
201 \f
202 /* See card.c for interface description */
203 static int 
204 p15_sign (CARD card, const char *keyidstr, int hashalgo,
205           int (pincb)(void*, const char *, char **),
206           void *pincb_arg,
207           const void *indata, size_t indatalen,
208           void **outdata, size_t *outdatalen )
209 {
210   unsigned int cryptflags = 0;
211   struct sc_pkcs15_id keyid;
212   struct sc_pkcs15_pin_info *pin;
213   struct sc_pkcs15_object *keyobj, *pinobj;
214   char *pinvalue;
215   int rc;
216   unsigned char *outbuf = NULL;
217   size_t outbuflen;
218
219   if (hashalgo != GCRY_MD_SHA1)
220     return GNUPG_Unsupported_Algorithm;
221
222   rc = idstr_to_id (keyidstr, &keyid);
223   if (rc)
224     return rc;
225
226   rc = sc_pkcs15_find_prkey_by_id (card->p15card, &keyid, &keyobj);
227   if (rc < 0)
228     {
229       log_error ("private key not found: %s\n", sc_strerror(rc));
230       rc = GNUPG_No_Secret_Key;
231       goto leave;
232     }
233   rc = 0;
234
235   rc = sc_pkcs15_find_pin_by_auth_id (card->p15card,
236                                       &keyobj->auth_id, &pinobj);
237   if (rc)
238     {
239       log_error ("failed to find PIN by auth ID: %s\n", sc_strerror (rc));
240       rc = GNUPG_Bad_PIN_Method;
241       goto leave;
242     }
243   pin = pinobj->data;
244
245   /* Fixme: pack this into a verification loop */
246   /* Fixme: we might want to pass pin->min_length and 
247      pin->stored_length */
248   rc = pincb (pincb_arg, pinobj->label, &pinvalue);
249   if (rc)
250     {
251       log_info ("PIN callback returned error: %s\n", gnupg_strerror (rc));
252       goto leave;
253     }
254
255   rc = sc_pkcs15_verify_pin (card->p15card, pin,
256                              pinvalue, strlen (pinvalue));
257   xfree (pinvalue);
258   if (rc)
259     {
260       log_info ("PIN verification failed: %s\n", sc_strerror (rc));
261       rc = GNUPG_Bad_PIN;
262       goto leave;
263     }
264
265 /*    cryptflags |= SC_PKCS15_HASH_SHA1; */
266 /*    cryptflags |= SC_PKCS15_PAD_PKCS1_V1_5; */
267
268   outbuflen = 1024; 
269   outbuf = xtrymalloc (outbuflen);
270   if (!outbuf)
271     return GNUPG_Out_Of_Core;
272   
273   rc = sc_pkcs15_compute_signature (card->p15card, keyobj,
274                                     cryptflags,
275                                     indata, indatalen,
276                                     outbuf, outbuflen );
277   if (rc < 0)
278     {
279       log_error ("failed to create signature: %s\n", sc_strerror (rc));
280       rc = GNUPG_Card_Error;
281     }
282   else
283     {
284       *outdatalen = rc;
285       *outdata = outbuf;
286       outbuf = NULL;
287       rc = 0;
288     }
289
290
291 leave:
292   xfree (outbuf);
293   return rc;
294 }
295
296
297 /* See card.c for description */
298 static int 
299 p15_decipher (CARD card, const char *keyidstr,
300               int (pincb)(void*, const char *, char **),
301               void *pincb_arg,
302               const void *indata, size_t indatalen,
303               void **outdata, size_t *outdatalen )
304 {
305   struct sc_pkcs15_id keyid;
306   struct sc_pkcs15_pin_info *pin;
307   struct sc_pkcs15_object *keyobj, *pinobj;
308   char *pinvalue;
309   int rc;
310   unsigned char *outbuf = NULL;
311   size_t outbuflen;
312
313   rc = idstr_to_id (keyidstr, &keyid);
314   if (rc)
315     return rc;
316
317   rc = sc_pkcs15_find_prkey_by_id (card->p15card, &keyid, &keyobj);
318   if (rc < 0)
319     {
320       log_error ("private key not found: %s\n", sc_strerror(rc));
321       rc = GNUPG_No_Secret_Key;
322       goto leave;
323     }
324   rc = 0;
325
326   rc = sc_pkcs15_find_pin_by_auth_id (card->p15card,
327                                       &keyobj->auth_id, &pinobj);
328   if (rc)
329     {
330       log_error ("failed to find PIN by auth ID: %s\n", sc_strerror (rc));
331       rc = GNUPG_Bad_PIN_Method;
332       goto leave;
333     }
334   pin = pinobj->data;
335
336   /* Fixme: pack this into a verification loop */
337   /* Fixme: we might want to pass pin->min_length and 
338      pin->stored_length */
339   rc = pincb (pincb_arg, pinobj->label, &pinvalue);
340   if (rc)
341     {
342       log_info ("PIN callback returned error: %s\n", gnupg_strerror (rc));
343       goto leave;
344     }
345
346   rc = sc_pkcs15_verify_pin (card->p15card, pin,
347                              pinvalue, strlen (pinvalue));
348   xfree (pinvalue);
349   if (rc)
350     {
351       log_info ("PIN verification failed: %s\n", sc_strerror (rc));
352       rc = GNUPG_Bad_PIN;
353       goto leave;
354     }
355
356   outbuflen = indatalen < 256? 256 : indatalen; 
357   outbuf = xtrymalloc (outbuflen);
358   if (!outbuf)
359     return GNUPG_Out_Of_Core;
360
361   /* OpenSC does not yet support decryption for cryptflex cards */  
362 /*    rc = sc_pkcs15_decipher (card->p15card, key, */
363 /*                             indata, indatalen, */
364 /*                             outbuf, outbuflen); */
365   rc = sc_pkcs15_compute_signature (card->p15card, keyobj,
366                                     0,
367                                     indata, indatalen,
368                                     outbuf, outbuflen );
369   if (rc < 0)
370     {
371       log_error ("failed to decipger the data: %s\n", sc_strerror (rc));
372       rc = GNUPG_Card_Error;
373     }
374   else
375     {
376       *outdatalen = rc;
377       *outdata = outbuf;
378       outbuf = NULL;
379       rc = 0;
380     }
381
382
383 leave:
384   xfree (outbuf);
385   return rc;
386 }
387
388
389
390
391 /* Bind our operations to the card */
392 void
393 card_p15_bind (CARD card)
394 {
395   card->fnc.enum_keypairs = p15_enum_keypairs;
396   card->fnc.read_cert     = p15_read_cert;
397   card->fnc.sign          = p15_sign;
398   card->fnc.decipher      = p15_decipher;
399 }