* card.c (card_open, card_close): Adjusted for changes in OpenSC.
[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_ALGORITHM_RSA_PAD_PKCS1;
266
267   outbuflen = 1024; 
268   outbuf = xtrymalloc (outbuflen);
269   if (!outbuf)
270     return GNUPG_Out_Of_Core;
271   
272   rc = sc_pkcs15_compute_signature (card->p15card, keyobj,
273                                     cryptflags,
274                                     indata, indatalen,
275                                     outbuf, outbuflen );
276   if (rc < 0)
277     {
278       log_error ("failed to create signature: %s\n", sc_strerror (rc));
279       rc = GNUPG_Card_Error;
280     }
281   else
282     {
283       *outdatalen = rc;
284       *outdata = outbuf;
285       outbuf = NULL;
286       rc = 0;
287     }
288
289
290 leave:
291   xfree (outbuf);
292   return rc;
293 }
294
295
296 /* See card.c for description */
297 static int 
298 p15_decipher (CARD card, const char *keyidstr,
299               int (pincb)(void*, const char *, char **),
300               void *pincb_arg,
301               const void *indata, size_t indatalen,
302               void **outdata, size_t *outdatalen )
303 {
304   struct sc_pkcs15_id keyid;
305   struct sc_pkcs15_pin_info *pin;
306   struct sc_pkcs15_object *keyobj, *pinobj;
307   char *pinvalue;
308   int rc;
309   unsigned char *outbuf = NULL;
310   size_t outbuflen;
311
312   rc = idstr_to_id (keyidstr, &keyid);
313   if (rc)
314     return rc;
315
316   rc = sc_pkcs15_find_prkey_by_id (card->p15card, &keyid, &keyobj);
317   if (rc < 0)
318     {
319       log_error ("private key not found: %s\n", sc_strerror(rc));
320       rc = GNUPG_No_Secret_Key;
321       goto leave;
322     }
323   rc = 0;
324
325   rc = sc_pkcs15_find_pin_by_auth_id (card->p15card,
326                                       &keyobj->auth_id, &pinobj);
327   if (rc)
328     {
329       log_error ("failed to find PIN by auth ID: %s\n", sc_strerror (rc));
330       rc = GNUPG_Bad_PIN_Method;
331       goto leave;
332     }
333   pin = pinobj->data;
334
335   /* Fixme: pack this into a verification loop */
336   /* Fixme: we might want to pass pin->min_length and 
337      pin->stored_length */
338   rc = pincb (pincb_arg, pinobj->label, &pinvalue);
339   if (rc)
340     {
341       log_info ("PIN callback returned error: %s\n", gnupg_strerror (rc));
342       goto leave;
343     }
344
345   rc = sc_pkcs15_verify_pin (card->p15card, pin,
346                              pinvalue, strlen (pinvalue));
347   xfree (pinvalue);
348   if (rc)
349     {
350       log_info ("PIN verification failed: %s\n", sc_strerror (rc));
351       rc = GNUPG_Bad_PIN;
352       goto leave;
353     }
354
355   outbuflen = indatalen < 256? 256 : indatalen; 
356   outbuf = xtrymalloc (outbuflen);
357   if (!outbuf)
358     return GNUPG_Out_Of_Core;
359
360   /* OpenSC does not yet support decryption for cryptflex cards */  
361 /*    rc = sc_pkcs15_decipher (card->p15card, key, */
362 /*                             indata, indatalen, */
363 /*                             outbuf, outbuflen); */
364   rc = sc_pkcs15_compute_signature (card->p15card, keyobj,
365                                     0,
366                                     indata, indatalen,
367                                     outbuf, outbuflen );
368   if (rc < 0)
369     {
370       log_error ("failed to decipger the data: %s\n", sc_strerror (rc));
371       rc = GNUPG_Card_Error;
372     }
373   else
374     {
375       *outdatalen = rc;
376       *outdata = outbuf;
377       outbuf = NULL;
378       rc = 0;
379     }
380
381
382 leave:
383   xfree (outbuf);
384   return rc;
385 }
386
387
388
389
390 /* Bind our operations to the card */
391 void
392 card_p15_bind (CARD card)
393 {
394   card->fnc.enum_keypairs = p15_enum_keypairs;
395   card->fnc.read_cert     = p15_read_cert;
396   card->fnc.sign          = p15_sign;
397   card->fnc.decipher      = p15_decipher;
398 }