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