po/
[gnupg.git] / scd / card-p15.c
blob34a88f7141c8ab0cbd38a0cb92446174857e4ac2
1 /* card-p15.c - PKCS-15 based card access
2 * Copyright (C) 2002 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
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 3 of the License, or
9 * (at your option) any later version.
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.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include <config.h>
21 #include <errno.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <time.h>
27 #ifdef HAVE_OPENSC
28 #include <opensc/pkcs15.h>
30 #include "scdaemon.h"
31 #include <ksba.h>
32 #include "card-common.h"
35 struct p15private_s {
36 int n_prkey_rsa_objs;
37 struct sc_pkcs15_object *prkey_rsa_objs[32];
38 int n_cert_objs;
39 struct sc_pkcs15_object *cert_objs[32];
43 /* Allocate private data. */
44 static int
45 init_private_data (CARD card)
47 struct p15private_s *priv;
48 int rc;
50 if (card->p15priv)
51 return 0; /* already done. */
53 priv = xtrycalloc (1, sizeof *priv);
54 if (!priv)
55 return gpg_error (gpg_err_code_from_errno (errno));
57 /* OpenSC (0.7.0) is a bit strange in that the get_objects functions
58 tries to be a bit too clever and implicitly does an enumeration
59 which eventually leads to the fact that every call to this
60 fucntion returns one more macthing object. The old code in
61 p15_enum_keypairs assume that it would alwyas return the same
62 numer of objects and used this to figure out what the last object
63 enumerated is. We now do an enum_objects just once and keep it
64 in the private data. */
65 rc = sc_pkcs15_get_objects (card->p15card, SC_PKCS15_TYPE_PRKEY_RSA,
66 priv->prkey_rsa_objs,
67 DIM (priv->prkey_rsa_objs));
68 if (rc < 0)
70 log_error ("private keys enumeration failed: %s\n", sc_strerror (rc));
71 xfree (priv);
72 return gpg_error (GPG_ERR_CARD);
74 priv->n_prkey_rsa_objs = rc;
76 /* Read all certificate objects. */
77 rc = sc_pkcs15_get_objects (card->p15card, SC_PKCS15_TYPE_CERT_X509,
78 priv->cert_objs,
79 DIM (priv->cert_objs));
80 if (rc < 0)
82 log_error ("private keys enumeration failed: %s\n", sc_strerror (rc));
83 xfree (priv);
84 return gpg_error (GPG_ERR_CARD);
86 priv->n_cert_objs = rc;
88 card->p15priv = priv;
89 return 0;
93 /* Release private data used in this module. */
94 void
95 p15_release_private_data (CARD card)
97 if (!card->p15priv)
98 return;
99 xfree (card->p15priv);
100 card->p15priv = NULL;
105 /* See card.c for interface description */
106 static int
107 p15_enum_keypairs (CARD card, int idx,
108 unsigned char *keygrip, char **keyid)
110 int rc;
111 struct p15private_s *priv;
112 struct sc_pkcs15_object *tmpobj;
113 int nobjs;
114 struct sc_pkcs15_prkey_info *pinfo;
115 struct sc_pkcs15_cert_info *certinfo;
116 struct sc_pkcs15_cert *certder;
117 ksba_cert_t cert;
119 rc = init_private_data (card);
120 if (rc)
121 return rc;
122 priv = card->p15priv;
123 nobjs = priv->n_prkey_rsa_objs;
124 rc = 0;
125 if (idx >= nobjs)
126 return -1;
127 pinfo = priv->prkey_rsa_objs[idx]->data;
129 /* now we need to read the certificate so that we can calculate the
130 keygrip */
131 rc = sc_pkcs15_find_cert_by_id (card->p15card, &pinfo->id, &tmpobj);
132 if (rc)
134 log_info ("certificate for private key %d not found: %s\n",
135 idx, sc_strerror (rc));
136 /* note, that we return the ID anyway */
137 rc = gpg_error (GPG_ERR_MISSING_CERT);
138 goto return_keyid;
140 certinfo = tmpobj->data;
141 rc = sc_pkcs15_read_certificate (card->p15card, certinfo, &certder);
142 if (rc)
144 log_info ("failed to read certificate for private key %d: %s\n",
145 idx, sc_strerror (rc));
146 return gpg_error (GPG_ERR_CARD);
149 rc = ksba_cert_new (&cert);
150 if (rc)
152 sc_pkcs15_free_certificate (certder);
153 return rc;
155 rc = ksba_cert_init_from_mem (cert, certder->data, certder->data_len);
156 sc_pkcs15_free_certificate (certder);
157 if (rc)
159 log_error ("failed to parse the certificate for private key %d: %s\n",
160 idx, gpg_strerror (rc));
161 ksba_cert_release (cert);
162 return rc;
164 if (card_help_get_keygrip (cert, keygrip))
166 log_error ("failed to calculate the keygrip of private key %d\n", idx);
167 ksba_cert_release (cert);
168 return gpg_error (GPG_ERR_CARD);
170 ksba_cert_release (cert);
172 rc = 0;
173 return_keyid:
174 if (keyid)
176 char *p;
178 *keyid = p = xtrymalloc (9+pinfo->id.len*2+1);
179 if (!*keyid)
180 return gpg_error (gpg_err_code_from_errno (errno));
181 p = stpcpy (p, "P15-5015.");
182 bin2hex (pinfo->id.value, pinfo->id.len, p);
185 return rc;
188 /* See card.c for interface description */
189 static int
190 p15_enum_certs (CARD card, int idx, char **certid, int *type)
192 int rc;
193 struct p15private_s *priv;
194 struct sc_pkcs15_object *obj;
195 struct sc_pkcs15_cert_info *cinfo;
196 int nobjs;
198 rc = init_private_data (card);
199 if (rc)
200 return rc;
201 priv = card->p15priv;
202 nobjs = priv->n_cert_objs;
203 rc = 0;
204 if (idx >= nobjs)
205 return -1;
206 obj = priv->cert_objs[idx];
207 cinfo = obj->data;
209 if (certid)
211 char *p;
212 int i;
214 *certid = p = xtrymalloc (9+cinfo->id.len*2+1);
215 if (!*certid)
216 return gpg_error (gpg_err_code_from_errno (errno));
217 p = stpcpy (p, "P15-5015.");
218 bin2hex (cinfo->id.value, cinfo->id.len, p);
220 if (type)
222 if (!obj->df)
223 *type = 0; /* unknown */
224 else if (obj->df->type == SC_PKCS15_CDF)
225 *type = 100;
226 else if (obj->df->type == SC_PKCS15_CDF_TRUSTED)
227 *type = 101;
228 else if (obj->df->type == SC_PKCS15_CDF_USEFUL)
229 *type = 102;
230 else
231 *type = 0; /* error -> unknown */
234 return rc;
239 static int
240 idstr_to_id (const char *idstr, struct sc_pkcs15_id *id)
242 const char *s;
243 int n;
245 /* For now we only support the standard DF */
246 if (strncmp (idstr, "P15-5015.", 9) )
247 return gpg_error (GPG_ERR_INV_ID);
248 for (s=idstr+9, n=0; hexdigitp (s); s++, n++)
250 if (*s || (n&1))
251 return gpg_error (GPG_ERR_INV_ID); /*invalid or odd number of digits*/
252 n /= 2;
253 if (!n || n > SC_PKCS15_MAX_ID_SIZE)
254 return gpg_error (GPG_ERR_INV_ID); /* empty or too large */
255 for (s=idstr+9, n=0; *s; s += 2, n++)
256 id->value[n] = xtoi_2 (s);
257 id->len = n;
258 return 0;
262 /* See card.c for interface description */
263 static int
264 p15_read_cert (CARD card, const char *certidstr,
265 unsigned char **cert, size_t *ncert)
267 struct sc_pkcs15_object *tmpobj;
268 struct sc_pkcs15_id certid;
269 struct sc_pkcs15_cert_info *certinfo;
270 struct sc_pkcs15_cert *certder;
271 int rc;
273 if (!card || !certidstr || !cert || !ncert)
274 return gpg_error (GPG_ERR_INV_VALUE);
275 if (!card->p15card)
276 return gpg_error (GPG_ERR_NO_PKCS15_APP);
278 rc = idstr_to_id (certidstr, &certid);
279 if (rc)
280 return rc;
282 rc = sc_pkcs15_find_cert_by_id (card->p15card, &certid, &tmpobj);
283 if (rc)
285 log_info ("certificate '%s' not found: %s\n",
286 certidstr, sc_strerror (rc));
287 return -1;
289 certinfo = tmpobj->data;
290 rc = sc_pkcs15_read_certificate (card->p15card, certinfo, &certder);
291 if (rc)
293 log_info ("failed to read certificate '%s': %s\n",
294 certidstr, sc_strerror (rc));
295 return gpg_error (GPG_ERR_CARD);
298 *cert = xtrymalloc (certder->data_len);
299 if (!*cert)
301 gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
302 sc_pkcs15_free_certificate (certder);
303 return tmperr;
305 memcpy (*cert, certder->data, certder->data_len);
306 *ncert = certder->data_len;
307 sc_pkcs15_free_certificate (certder);
308 return 0;
315 static int
316 p15_prepare_key (CARD card, const char *keyidstr,
317 int (pincb)(void*, const char *, char **),
318 void *pincb_arg, struct sc_pkcs15_object **r_keyobj)
320 struct sc_pkcs15_id keyid;
321 struct sc_pkcs15_pin_info *pin;
322 struct sc_pkcs15_object *keyobj, *pinobj;
323 char *pinvalue;
324 int rc;
326 rc = idstr_to_id (keyidstr, &keyid);
327 if (rc)
328 return rc;
330 rc = sc_pkcs15_find_prkey_by_id (card->p15card, &keyid, &keyobj);
331 if (rc < 0)
333 log_error ("private key not found: %s\n", sc_strerror(rc));
334 return gpg_error (GPG_ERR_NO_SECKEY);
337 rc = sc_pkcs15_find_pin_by_auth_id (card->p15card,
338 &keyobj->auth_id, &pinobj);
339 if (rc)
341 log_error ("failed to find PIN by auth ID: %s\n", sc_strerror (rc));
342 return gpg_error (GPG_ERR_BAD_PIN_METHOD);
344 pin = pinobj->data;
346 /* Fixme: pack this into a verification loop */
347 /* Fixme: we might want to pass pin->min_length and
348 pin->stored_length */
349 rc = pincb (pincb_arg, pinobj->label, &pinvalue);
350 if (rc)
352 log_info ("PIN callback returned error: %s\n", gpg_strerror (rc));
353 return rc;
356 rc = sc_pkcs15_verify_pin (card->p15card, pin,
357 pinvalue, strlen (pinvalue));
358 xfree (pinvalue);
359 if (rc)
361 log_info ("PIN verification failed: %s\n", sc_strerror (rc));
362 return gpg_error (GPG_ERR_BAD_PIN);
365 /* fixme: check wheter we need to release KEYOBJ in case of an error */
366 *r_keyobj = keyobj;
367 return 0;
371 /* See card.c for interface description */
372 static int
373 p15_sign (CARD card, const char *keyidstr, int hashalgo,
374 int (pincb)(void*, const char *, char **),
375 void *pincb_arg,
376 const void *indata, size_t indatalen,
377 unsigned char **outdata, size_t *outdatalen )
379 unsigned int cryptflags;
380 struct sc_pkcs15_object *keyobj;
381 int rc;
382 unsigned char *outbuf = NULL;
383 size_t outbuflen;
385 if (hashalgo != GCRY_MD_SHA1)
386 return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
388 rc = p15_prepare_key (card, keyidstr, pincb, pincb_arg, &keyobj);
389 if (rc)
390 return rc;
392 cryptflags = SC_ALGORITHM_RSA_PAD_PKCS1;
394 outbuflen = 1024;
395 outbuf = xtrymalloc (outbuflen);
396 if (!outbuf)
397 return gpg_error (gpg_err_code_from_errno (errno));
399 rc = sc_pkcs15_compute_signature (card->p15card, keyobj,
400 cryptflags,
401 indata, indatalen,
402 outbuf, outbuflen );
403 if (rc < 0)
405 log_error ("failed to create signature: %s\n", sc_strerror (rc));
406 rc = gpg_error (GPG_ERR_CARD);
408 else
410 *outdatalen = rc;
411 *outdata = outbuf;
412 outbuf = NULL;
413 rc = 0;
416 xfree (outbuf);
417 return rc;
421 /* See card.c for description */
422 static int
423 p15_decipher (CARD card, const char *keyidstr,
424 int (pincb)(void*, const char *, char **),
425 void *pincb_arg,
426 const void *indata, size_t indatalen,
427 unsigned char **outdata, size_t *outdatalen )
429 struct sc_pkcs15_object *keyobj;
430 int rc;
431 unsigned char *outbuf = NULL;
432 size_t outbuflen;
434 rc = p15_prepare_key (card, keyidstr, pincb, pincb_arg, &keyobj);
435 if (rc)
436 return rc;
438 if (card && card->scard && card->scard->driver
439 && !strcasecmp (card->scard->driver->short_name, "tcos"))
441 /* very ugly hack to force the use of a local key. We need this
442 until we have fixed the initialization code for TCOS cards */
443 struct sc_pkcs15_prkey_info *prkey = keyobj->data;
444 if ( !(prkey->key_reference & 0x80))
446 prkey->key_reference |= 0x80;
447 log_debug ("using TCOS hack to force the use of local keys\n");
449 if (*keyidstr && keyidstr[strlen(keyidstr)-1] == '6')
451 prkey->key_reference |= 1;
452 log_debug ("warning: using even more TCOS hacks\n");
456 outbuflen = indatalen < 256? 256 : indatalen;
457 outbuf = xtrymalloc (outbuflen);
458 if (!outbuf)
459 return gpg_error (gpg_err_code_from_errno (errno));
461 rc = sc_pkcs15_decipher (card->p15card, keyobj,
463 indata, indatalen,
464 outbuf, outbuflen);
465 if (rc < 0)
467 log_error ("failed to decipher the data: %s\n", sc_strerror (rc));
468 rc = gpg_error (GPG_ERR_CARD);
470 else
472 *outdatalen = rc;
473 *outdata = outbuf;
474 outbuf = NULL;
475 rc = 0;
478 xfree (outbuf);
479 return rc;
484 /* Bind our operations to the card */
485 void
486 card_p15_bind (CARD card)
488 card->fnc.enum_keypairs = p15_enum_keypairs;
489 card->fnc.enum_certs = p15_enum_certs;
490 card->fnc.read_cert = p15_read_cert;
491 card->fnc.sign = p15_sign;
492 card->fnc.decipher = p15_decipher;
494 #endif /*HAVE_OPENSC*/