* call-scd.c (inq_needpin): Skip leading spaces in of PIN
[gnupg.git] / agent / divert-scd.c
1 /* divert-scd.c - divert operations to the scdaemon 
2  *      Copyright (C) 2002, 2003 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 #include "i18n.h"
34
35
36 static int
37 ask_for_card (CTRL ctrl, 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   int want_sn_displen;
47
48   *r_kid = NULL;
49   s = shadow_info;
50   if (*s != '(')
51     return gpg_error (GPG_ERR_INV_SEXP);
52   s++;
53   n = snext (&s);
54   if (!n)
55     return gpg_error (GPG_ERR_INV_SEXP);
56   want_sn = xtrymalloc (n*2+1);
57   if (!want_sn)
58     return out_of_core ();
59   for (i=0; i < n; i++)
60     sprintf (want_sn+2*i, "%02X", s[i]);
61   s += n;
62   /* We assume that a 20 byte serial number is a standard one which
63      seems to have the property to have a zero in the last nibble.  We
64      don't display this '0' because it may confuse the user */
65   want_sn_displen = strlen (want_sn);
66   if (want_sn_displen == 20 && want_sn[19] == '0')
67     want_sn_displen--;
68
69   n = snext (&s);
70   if (!n)
71     return gpg_error (GPG_ERR_INV_SEXP);
72   want_kid = xtrymalloc (n+1);
73   if (!want_kid)
74     {
75       gpg_error_t tmperr = out_of_core ();
76       xfree (want_sn);
77       return tmperr;
78     }
79   memcpy (want_kid, s, n);
80   want_kid[n] = 0;
81
82   for (;;)
83     {
84       rc = agent_card_serialno (ctrl, &serialno);
85       if (!rc)
86         {
87           log_debug ("detected card with S/N %s\n", serialno);
88           i = strcmp (serialno, want_sn);
89           xfree (serialno);
90           serialno = NULL;
91           if (!i)
92             {
93               xfree (want_sn);
94               *r_kid = want_kid;
95               return 0; /* yes, we have the correct card */
96             }
97         }
98       else if (gpg_err_code (rc) == GPG_ERR_CARD_NOT_PRESENT)
99         {
100           log_debug ("no card present\n");
101           rc = 0;
102           no_card = 1;
103         }
104       else
105         {
106           log_error ("error accesing card: %s\n", gpg_strerror (rc));
107         }
108
109       if (!rc)
110         {
111           if (asprintf (&desc,
112                     "%s:%%0A%%0A"
113                     "  \"%.*s\"",
114                     no_card? "Please insert the card with serial number" 
115                     : "Please remove the current card and "
116                     "insert the one with serial number",
117                     want_sn_displen, want_sn) < 0)
118             {
119               rc = out_of_core ();
120             }
121           else
122             {
123               rc = agent_get_confirmation (ctrl, desc, NULL, NULL);
124               free (desc);
125             }
126         }
127       if (rc)
128         {
129           xfree (want_sn);
130           xfree (want_kid);
131           return rc;
132         }
133     }
134 }
135
136
137 /* Put the DIGEST into an DER encoded container and return it in R_VAL. */
138 static int
139 encode_md_for_card (const unsigned char *digest, size_t digestlen, int algo,
140                     unsigned char **r_val, size_t *r_len)
141 {
142   byte *frame;
143   byte asn[100];
144   size_t asnlen;
145
146   asnlen = DIM(asn);
147   if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen))
148     {
149       log_error ("no object identifier for algo %d\n", algo);
150       return gpg_error (GPG_ERR_INTERNAL);
151     }
152
153   frame = xtrymalloc (asnlen + digestlen);
154   if (!frame)
155     return out_of_core ();
156   memcpy (frame, asn, asnlen);
157   memcpy (frame+asnlen, digest, digestlen);
158   if (DBG_CRYPTO)
159     log_printhex ("encoded hash:", frame, asnlen+digestlen);
160       
161   *r_val = frame;
162   *r_len = asnlen+digestlen;
163   return 0;
164 }
165
166
167 /* Callback used to ask for the PIN which should be set into BUF.  The
168    buf has been allocated by the caller and is of size MAXBUF which
169    includes the terminating null.  The function should return an UTF-8
170    string with the passphrase, the buffer may optionally be padded
171    with arbitrary characters.
172
173    INFO gets displayed as part of a generic string.  However if the
174    first character of INFO is a vertical bar all up to the next
175    verical bar are considered flags and only everything after the
176    second vertical bar gets displayed as the full prompt.
177
178    Flags:
179
180       'N' = New PIN, this requests a second prompt to repeat the the
181             PIN.  If the PIN is not correctly repeated it starts from
182             all over.
183       'A' = The PIN is an Admin PIN, SO-PIN, PUK or alike.
184
185    Example:
186
187      "|AN|Please enter the new security officer's PIN"
188      
189    The text "Please ..." will get displayed and the flags 'A' and 'N'
190    are considered.
191  */
192 static int 
193 getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
194 {
195   struct pin_entry_info_s *pi;
196   int rc;
197   ctrl_t ctrl = opaque;
198   const char *ends, *s;
199   int any_flags = 0;
200   int newpin = 0;
201   const char *again_text = NULL;
202   const char *prompt = "PIN";
203
204   if (maxbuf < 2)
205     return gpg_error (GPG_ERR_INV_VALUE);
206
207   /* Parse the flags. */
208   if (info && *info =='|' && (ends=strchr (info+1, '|')))
209     {
210       for (s=info+1; s < ends; s++)
211         {
212           if (*s == 'A')
213             prompt = _("Admin PIN");
214           else if (*s == 'N')
215             newpin = 1;
216         }
217       info = ends+1;
218       any_flags = 1;
219     }
220   else if (info && *info == '|')
221     log_debug ("pin_cb called without proper PIN info hack\n");
222
223
224   /* FIXME: keep PI and TRIES in OPAQUE.  Frankly this is a whole
225      mess because we should call the card's verify function from the
226      pinentry check pin CB. */
227  again:
228   pi = gcry_calloc_secure (1, sizeof (*pi) + maxbuf + 10);
229   if (!pi)
230     return gpg_error_from_errno (errno);
231   pi->max_length = maxbuf-1;
232   pi->min_digits = 0;  /* we want a real passphrase */
233   pi->max_digits = 8;
234   pi->max_tries = 3;
235
236   if (any_flags)
237     {
238       rc = agent_askpin (ctrl, info, prompt, again_text, pi);
239       again_text = NULL;
240       if (!rc && newpin)
241         {
242           struct pin_entry_info_s *pi2;
243           pi2 = gcry_calloc_secure (1, sizeof (*pi) + maxbuf + 10);
244           if (!pi2)
245             {
246               rc = gpg_error_from_errno (errno);
247               xfree (pi);
248               return rc;
249             }
250           pi2->max_length = maxbuf-1;
251           pi2->min_digits = 0;
252           pi2->max_digits = 8;
253           pi2->max_tries = 1;
254           rc = agent_askpin (ctrl, _("Repeat this PIN"), prompt, NULL, pi2);
255           if (!rc && strcmp (pi->pin, pi2->pin))
256             {
257               again_text = N_("PIN not correctly repeated; try again");
258               xfree (pi2);
259               xfree (pi);
260               goto again;
261             }
262           xfree (pi2);
263         }
264     }
265   else
266     {
267       char *desc;
268       if ( asprintf (&desc,
269                      _("Please enter the PIN%s%s%s to unlock the card"), 
270                      info? " (`":"",
271                      info? info:"",
272                      info? "')":"") < 0)
273         desc = NULL;
274       rc = agent_askpin (ctrl, desc?desc:info, prompt, NULL, pi);
275       free (desc);
276     }
277
278   if (!rc)
279     {
280       strncpy (buf, pi->pin, maxbuf-1);
281       buf[maxbuf-1] = 0;
282     }
283   xfree (pi);
284   return rc;
285 }
286
287
288
289
290 int
291 divert_pksign (CTRL ctrl, 
292                const unsigned char *digest, size_t digestlen, int algo,
293                const unsigned char *shadow_info, unsigned char **r_sig)
294 {
295   int rc;
296   char *kid;
297   size_t siglen;
298   char *sigval;
299   unsigned char *data;
300   size_t ndata;
301
302   rc = ask_for_card (ctrl, shadow_info, &kid);
303   if (rc)
304     return rc;
305
306   rc = encode_md_for_card (digest, digestlen, algo, 
307                            &data, &ndata);
308   if (rc)
309     return rc;
310
311   rc = agent_card_pksign (ctrl, kid, getpin_cb, ctrl,
312                           data, ndata, &sigval, &siglen);
313   if (!rc)
314     *r_sig = sigval;
315   xfree (data);
316   xfree (kid);
317   
318   return rc;
319 }
320
321
322 /* Decrypt the the value given asn an S-expression in CIPHER using the
323    key identified by SHADOW_INFO and return the plaintext in an
324    allocated buffer in R_BUF.  */
325 int  
326 divert_pkdecrypt (CTRL ctrl,
327                   const unsigned char *cipher,
328                   const unsigned char *shadow_info,
329                   char **r_buf, size_t *r_len)
330 {
331   int rc;
332   char *kid;
333   const unsigned char *s;
334   size_t n;
335   const unsigned char *ciphertext;
336   size_t ciphertextlen;
337   char *plaintext;
338   size_t plaintextlen;
339
340   s = cipher;
341   if (*s != '(')
342     return gpg_error (GPG_ERR_INV_SEXP);
343   s++;
344   n = snext (&s);
345   if (!n)
346     return gpg_error (GPG_ERR_INV_SEXP); 
347   if (!smatch (&s, n, "enc-val"))
348     return gpg_error (GPG_ERR_UNKNOWN_SEXP); 
349   if (*s != '(')
350     return gpg_error (GPG_ERR_UNKNOWN_SEXP);
351   s++;
352   n = snext (&s);
353   if (!n)
354     return gpg_error (GPG_ERR_INV_SEXP); 
355   if (!smatch (&s, n, "rsa"))
356     return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); 
357   if (*s != '(')
358     return gpg_error (GPG_ERR_UNKNOWN_SEXP);
359   s++;
360   n = snext (&s);
361   if (!n)
362     return gpg_error (GPG_ERR_INV_SEXP); 
363   if (!smatch (&s, n, "a"))
364     return gpg_error (GPG_ERR_UNKNOWN_SEXP);
365   n = snext (&s);
366   if (!n)
367     return gpg_error (GPG_ERR_UNKNOWN_SEXP); 
368   ciphertext = s;
369   ciphertextlen = n;
370
371   rc = ask_for_card (ctrl, shadow_info, &kid);
372   if (rc)
373     return rc;
374
375   rc = agent_card_pkdecrypt (ctrl, kid, getpin_cb, ctrl,
376                              ciphertext, ciphertextlen,
377                              &plaintext, &plaintextlen);
378   if (!rc)
379     {
380       *r_buf = plaintext;
381       *r_len = plaintextlen;
382     }
383   xfree (kid);
384   return rc;
385 }
386
387
388 int  
389 divert_generic_cmd (CTRL ctrl, const char *cmdline, void *assuan_context)
390 {
391   return agent_card_scd (ctrl, cmdline, getpin_cb, ctrl, assuan_context);
392 }
393
394
395
396
397