Signing using a PKCS15 smartcard does work. How to create such a card
[gnupg.git] / agent / divert-scd.c
1 /* divert-scd.c - divert operations to the scdaemon 
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 <ctype.h>
27 #include <assert.h>
28 #include <unistd.h>
29 #include <sys/stat.h>
30
31 #include "agent.h"
32 #include "sexp-parse.h"
33
34
35
36 static int
37 ask_for_card (const unsigned char *shadow_info, char **r_kid)
38 {
39   int rc, i;
40   const unsigned char *s;
41   size_t n;
42   char *serialno;
43   int no_card = 0;
44   char *desc;
45   char *want_sn, *want_kid;
46
47   *r_kid = NULL;
48   s = shadow_info;
49   if (*s != '(')
50     return GNUPG_Invalid_Sexp;
51   s++;
52   n = snext (&s);
53   if (!n)
54     return GNUPG_Invalid_Sexp;
55   want_sn = xtrymalloc (n+1);
56   if (!want_sn)
57     return GNUPG_Out_Of_Core;
58   memcpy (want_sn, s, n);
59   want_sn[n] = 0;
60   s += n;
61
62   n = snext (&s);
63   if (!n)
64     return GNUPG_Invalid_Sexp;
65   want_kid = xtrymalloc (n+1);
66   if (!want_kid)
67     {
68       xfree (want_sn);
69       return GNUPG_Out_Of_Core;
70     }
71   memcpy (want_kid, s, n);
72   want_kid[n] = 0;
73
74   for (;;)
75     {
76       rc = agent_card_serialno (&serialno);
77       if (!rc)
78         {
79           log_debug ("detected card with S/N %s\n", serialno);
80           i = strcmp (serialno, want_sn);
81           xfree (serialno);
82           serialno = NULL;
83           if (!i)
84             {
85               xfree (want_sn);
86               *r_kid = want_kid;
87               return 0; /* yes, we have the correct card */
88             }
89         }
90       else if (rc == GNUPG_Card_Not_Present)
91         {
92           log_debug ("no card present\n");
93           rc = 0;
94           no_card = 1;
95         }
96       else
97         {
98           log_error ("error accesing card: %s\n", gnupg_strerror (rc));
99         }
100
101       if (!rc)
102         {
103           if (asprintf (&desc,
104                     "%s:%%0A%%0A"
105                     "  \"%s\"",
106                     no_card? "Please insert the card with serial number" 
107                     : "Please remove the current card and "
108                     "insert the one with serial number",
109                     want_sn) < 0)
110             {
111               rc = GNUPG_Out_Of_Core;
112             }
113           else
114             {
115               rc = agent_get_confirmation (desc, NULL);
116               free (desc);
117             }
118         }
119       if (rc)
120         {
121           xfree (want_sn);
122           xfree (want_kid);
123           return rc;
124         }
125     }
126 }
127
128
129 /* fixme: this should be moved to libgcrypt and only be used if the
130    smartcard does not support pkcs-1 itself */
131 static int
132 encode_md_for_card (const unsigned char *digest, size_t digestlen, int algo,
133                     unsigned int nbits, unsigned char **r_val, size_t *r_len)
134 {
135   int nframe = (nbits+7) / 8;
136   byte *frame;
137   int i, n;
138   byte asn[100];
139   size_t asnlen;
140
141   asnlen = DIM(asn);
142   if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen))
143     {
144       log_error ("no object identifier for algo %d\n", algo);
145       return GNUPG_Internal_Error;
146     }
147
148   if (digestlen + asnlen + 4  > nframe )
149     {
150       log_error ("can't encode a %d bit MD into a %d bits frame\n",
151                  (int)(digestlen*8), (int)nbits);
152       return GNUPG_Internal_Error;
153     }
154   
155   /* We encode the MD in this way:
156    *
157    *       0  1 PAD(n bytes)   0  ASN(asnlen bytes)  MD(len bytes)
158    *
159    * PAD consists of FF bytes.
160    */
161   frame = xtrymalloc (nframe);
162   if (!frame)
163     return GNUPG_Out_Of_Core;
164   n = 0;
165   frame[n++] = 0;
166   frame[n++] = 1; /* block type */
167   i = nframe - digestlen - asnlen -3 ;
168   assert ( i > 1 );
169   memset ( frame+n, 0xff, i ); n += i;
170   frame[n++] = 0;
171   memcpy ( frame+n, asn, asnlen ); n += asnlen;
172   memcpy ( frame+n, digest, digestlen ); n += digestlen;
173   assert ( n == nframe );
174   if (DBG_CRYPTO)
175     log_printhex ("encoded hash:", frame, nframe);
176       
177   *r_val = frame;
178   *r_len = nframe;
179   return 0;
180 }
181
182
183 /* Callback used to ask for the PIN which should be set into BUF.  The
184    buf has been allocated by the caller and is of size MAXBUF which
185    includes the terminating null.  The function should return an UTF-8
186    string with the passphrase, the buffer may optioanlly be padded
187    with arbitrary characters */
188 static int 
189 getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
190 {
191   struct pin_entry_info_s *pi;
192   int rc;
193   int tries = 0;
194   const char *errtext;
195   
196   assert (!opaque);
197
198   if (maxbuf < 2)
199     return GNUPG_Invalid_Value;
200
201   /* FIXME: keep PI and TRIES in OPAQUE */
202   pi = gcry_calloc_secure (1, sizeof (*pi) + 100);
203   pi->max_length = maxbuf-1;
204   pi->min_digits = 0;  /* we want a real passphrase */
205   pi->max_digits = 8;
206   pi->max_tries = 3;
207
208   errtext = NULL;
209   do
210     {
211       rc = agent_askpin (info, errtext, pi);
212       if (!rc)
213         {
214           strncpy (buf, pi->pin, maxbuf-1);
215           buf[maxbuf-1] = 0;
216           xfree (pi);
217           return 0;
218         }
219       errtext = pi->min_digits? trans ("Bad PIN") : trans ("Bad Passphrase");
220     }
221   while ((rc == GNUPG_Bad_Passphrase || rc == GNUPG_Bad_PIN)
222          && tries++ < 3);
223   xfree (pi);
224   return rc;
225 }
226
227
228
229
230 int
231 divert_pksign (const unsigned char *digest, size_t digestlen, int algo,
232                const char *shadow_info, unsigned char **r_sig)
233 {
234   int rc;
235   char *kid;
236   size_t siglen;
237   char *sigval;
238   unsigned char *data;
239   size_t ndata;
240
241   rc = ask_for_card (shadow_info, &kid);
242   if (rc)
243     return rc;
244
245   rc = encode_md_for_card (digest, digestlen, algo, 1024 /* fixme*/,
246                            &data, &ndata);
247   if (rc)
248     return rc;
249
250   rc = agent_card_pksign (kid, getpin_cb, NULL,
251                           data, ndata, &sigval, &siglen);
252   if (!rc)
253     *r_sig = sigval;
254   xfree (data);
255   xfree (kid);
256   
257   return rc;
258 }
259
260
261 int 
262 divert_pkdecrypt (GCRY_SEXP *s_plain, GCRY_SEXP s_cipher,
263                   const char *shadow_info)
264 {
265   int rc;
266   char *kid;
267
268   rc = ask_for_card (shadow_info, &kid);
269   if (rc)
270     return rc;
271
272  
273   xfree (kid);
274   return GNUPG_Not_Implemented;
275 }
276
277
278