agent: Prepare to pass an additional parameter to the getpin callback.
[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 <https://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, NULL);
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, want_sn);
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_ENODEV)
76         {
77           log_debug ("no device present\n");
78           rc = 0;
79           no_card = 1;
80         }
81       else if (gpg_err_code (rc) == GPG_ERR_CARD_NOT_PRESENT)
82         {
83           log_debug ("no card present\n");
84           rc = 0;
85           no_card = 2;
86         }
87       else
88         {
89           log_error ("error accessing card: %s\n", gpg_strerror (rc));
90         }
91
92       if (!rc)
93         {
94           if (asprintf (&desc,
95                     "%s:%%0A%%0A"
96                     "  \"%.*s\"",
97                         no_card
98                         ? L_("Please insert the card with serial number")
99                         : L_("Please remove the current card and "
100                              "insert the one with serial number"),
101                     want_sn_displen, want_sn) < 0)
102             {
103               rc = out_of_core ();
104             }
105           else
106             {
107               rc = agent_get_confirmation (ctrl, desc, NULL, NULL, 0);
108               if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK &&
109                   gpg_err_code (rc) == GPG_ERR_NO_PIN_ENTRY)
110                 rc = gpg_error (GPG_ERR_CARD_NOT_PRESENT);
111
112               xfree (desc);
113             }
114         }
115       if (rc)
116         {
117           xfree (want_sn);
118           xfree (want_kid);
119           return rc;
120         }
121     }
122 }
123
124
125 /* Put the DIGEST into an DER encoded container and return it in R_VAL. */
126 static int
127 encode_md_for_card (const unsigned char *digest, size_t digestlen, int algo,
128                     unsigned char **r_val, size_t *r_len)
129 {
130   unsigned char *frame;
131   unsigned char asn[100];
132   size_t asnlen;
133
134   *r_val = NULL;
135   *r_len = 0;
136
137   asnlen = DIM(asn);
138   if (!algo || gcry_md_test_algo (algo))
139     return gpg_error (GPG_ERR_DIGEST_ALGO);
140   if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen))
141     {
142       log_error ("no object identifier for algo %d\n", algo);
143       return gpg_error (GPG_ERR_INTERNAL);
144     }
145
146   frame = xtrymalloc (asnlen + digestlen);
147   if (!frame)
148     return out_of_core ();
149   memcpy (frame, asn, asnlen);
150   memcpy (frame+asnlen, digest, digestlen);
151   if (DBG_CRYPTO)
152     log_printhex ("encoded hash:", frame, asnlen+digestlen);
153
154   *r_val = frame;
155   *r_len = asnlen+digestlen;
156   return 0;
157 }
158
159
160 /* Callback used to ask for the PIN which should be set into BUF.  The
161    buf has been allocated by the caller and is of size MAXBUF which
162    includes the terminating null.  The function should return an UTF-8
163    string with the passphrase, the buffer may optionally be padded
164    with arbitrary characters.
165
166    If DESC_TEXT is not NULL it can be used as further informtion shown
167    atop of the INFO message.
168
169    INFO gets displayed as part of a generic string.  However if the
170    first character of INFO is a vertical bar all up to the next
171    verical bar are considered flags and only everything after the
172    second vertical bar gets displayed as the full prompt.
173
174    Flags:
175
176       'N' = New PIN, this requests a second prompt to repeat the
177             PIN.  If the PIN is not correctly repeated it starts from
178             all over.
179       'A' = The PIN is an Admin PIN, SO-PIN or alike.
180       'P' = The PIN is a PUK (Personal Unblocking Key).
181       'R' = The PIN is a Reset Code.
182
183    Example:
184
185      "|AN|Please enter the new security officer's PIN"
186
187    The text "Please ..." will get displayed and the flags 'A' and 'N'
188    are considered.
189  */
190 static int
191 getpin_cb (void *opaque, const char *desc_text, const char *info,
192            char *buf, size_t maxbuf)
193 {
194   struct pin_entry_info_s *pi;
195   int rc;
196   ctrl_t ctrl = opaque;
197   const char *ends, *s;
198   int any_flags = 0;
199   int newpin = 0;
200   int resetcode = 0;
201   int is_puk = 0;
202   const char *again_text = NULL;
203   const char *prompt = "PIN";
204
205   if (buf && maxbuf < 2)
206     return gpg_error (GPG_ERR_INV_VALUE);
207
208   /* Parse the flags. */
209   if (info && *info =='|' && (ends=strchr (info+1, '|')))
210     {
211       for (s=info+1; s < ends; s++)
212         {
213           if (*s == 'A')
214             prompt = L_("Admin PIN");
215           else if (*s == 'P')
216             {
217               /* TRANSLATORS: A PUK is the Personal Unblocking Code
218                  used to unblock a PIN. */
219               prompt = L_("PUK");
220               is_puk = 1;
221             }
222           else if (*s == 'N')
223             newpin = 1;
224           else if (*s == 'R')
225             {
226               prompt = L_("Reset Code");
227               resetcode = 1;
228             }
229         }
230       info = ends+1;
231       any_flags = 1;
232     }
233   else if (info && *info == '|')
234     log_debug ("pin_cb called without proper PIN info hack\n");
235
236   /* If BUF has been passed as NULL, we are in pinpad mode: The
237      callback opens the popup and immediately returns. */
238   if (!buf)
239     {
240       if (maxbuf == 0) /* Close the pinentry. */
241         {
242           agent_popup_message_stop (ctrl);
243           rc = 0;
244         }
245       else if (maxbuf == 1)  /* Open the pinentry. */
246         {
247           if (info)
248             {
249               char *desc;
250
251               if ( asprintf (&desc,
252                              L_("%s%%0A%%0AUse the reader's pinpad for input."),
253                              info) < 0 )
254                 rc = gpg_error_from_syserror ();
255               else
256                 {
257                   rc = agent_popup_message_start (ctrl, desc, NULL);
258                   xfree (desc);
259                 }
260             }
261           else
262             rc = agent_popup_message_start (ctrl, NULL, NULL);
263         }
264       else
265         rc = gpg_error (GPG_ERR_INV_VALUE);
266       return rc;
267     }
268
269   /* FIXME: keep PI and TRIES in OPAQUE.  Frankly this is a whole
270      mess because we should call the card's verify function from the
271      pinentry check pin CB. */
272  again:
273   pi = gcry_calloc_secure (1, sizeof (*pi) + maxbuf + 10);
274   if (!pi)
275     return gpg_error_from_syserror ();
276   pi->max_length = maxbuf-1;
277   pi->min_digits = 0;  /* we want a real passphrase */
278   pi->max_digits = 16;
279   pi->max_tries = 3;
280
281   if (any_flags)
282     {
283       rc = agent_askpin (ctrl, info, prompt, again_text, pi, NULL, 0);
284       again_text = NULL;
285       if (!rc && newpin)
286         {
287           struct pin_entry_info_s *pi2;
288           pi2 = gcry_calloc_secure (1, sizeof (*pi) + maxbuf + 10);
289           if (!pi2)
290             {
291               rc = gpg_error_from_syserror ();
292               xfree (pi);
293               return rc;
294             }
295           pi2->max_length = maxbuf-1;
296           pi2->min_digits = 0;
297           pi2->max_digits = 16;
298           pi2->max_tries = 1;
299           rc = agent_askpin (ctrl,
300                              (resetcode?
301                               L_("Repeat this Reset Code"):
302                               is_puk?
303                               L_("Repeat this PUK"):
304                               L_("Repeat this PIN")),
305                              prompt, NULL, pi2, NULL, 0);
306           if (!rc && strcmp (pi->pin, pi2->pin))
307             {
308               again_text = (resetcode?
309                             L_("Reset Code not correctly repeated; try again"):
310                             is_puk?
311                             L_("PUK not correctly repeated; try again"):
312                             L_("PIN not correctly repeated; try again"));
313               xfree (pi2);
314               xfree (pi);
315               goto again;
316             }
317           xfree (pi2);
318         }
319     }
320   else
321     {
322       char *desc;
323       if ( asprintf (&desc,
324                      L_("Please enter the PIN%s%s%s to unlock the card"),
325                      info? " (":"",
326                      info? info:"",
327                      info? ")":"") < 0)
328         desc = NULL;
329       rc = agent_askpin (ctrl, desc?desc:info, prompt, NULL, pi, NULL, 0);
330       xfree (desc);
331     }
332
333   if (!rc)
334     {
335       strncpy (buf, pi->pin, maxbuf-1);
336       buf[maxbuf-1] = 0;
337     }
338   xfree (pi);
339   return rc;
340 }
341
342
343
344 /* This function is used when a sign operation has been diverted to a
345  * smartcard.  DESC_TEXT is the original text for a prompt has send by
346  * gpg to gpg-agent.
347  *
348  * FIXME: Explain the other args.  */
349 int
350 divert_pksign (ctrl_t ctrl, const char *desc_text,
351                const unsigned char *digest, size_t digestlen, int algo,
352                const unsigned char *shadow_info, unsigned char **r_sig,
353                size_t *r_siglen)
354 {
355   int rc;
356   char *kid;
357   size_t siglen;
358   unsigned char *sigval = NULL;
359
360   rc = ask_for_card (ctrl, shadow_info, &kid);
361   if (rc)
362     return rc;
363
364   if (algo == MD_USER_TLS_MD5SHA1)
365     {
366       int save = ctrl->use_auth_call;
367       ctrl->use_auth_call = 1;
368       rc = agent_card_pksign (ctrl, kid, getpin_cb, ctrl, desc_text,
369                               algo, digest, digestlen, &sigval, &siglen);
370       ctrl->use_auth_call = save;
371     }
372   else
373     {
374       unsigned char *data;
375       size_t ndata;
376
377       rc = encode_md_for_card (digest, digestlen, algo, &data, &ndata);
378       if (!rc)
379         {
380           rc = agent_card_pksign (ctrl, kid, getpin_cb, ctrl, desc_text,
381                                   algo, data, ndata, &sigval, &siglen);
382           xfree (data);
383         }
384     }
385
386   if (!rc)
387     {
388       *r_sig = sigval;
389       *r_siglen = siglen;
390     }
391
392   xfree (kid);
393
394   return rc;
395 }
396
397
398 /* Decrypt the value given asn an S-expression in CIPHER using the
399    key identified by SHADOW_INFO and return the plaintext in an
400    allocated buffer in R_BUF.  The padding information is stored at
401    R_PADDING with -1 for not known.  */
402 int
403 divert_pkdecrypt (ctrl_t ctrl, const char *desc_text,
404                   const unsigned char *cipher,
405                   const unsigned char *shadow_info,
406                   char **r_buf, size_t *r_len, int *r_padding)
407 {
408   int rc;
409   char *kid;
410   const unsigned char *s;
411   size_t n;
412   const unsigned char *ciphertext;
413   size_t ciphertextlen;
414   char *plaintext;
415   size_t plaintextlen;
416
417   *r_padding = -1;
418
419   s = cipher;
420   if (*s != '(')
421     return gpg_error (GPG_ERR_INV_SEXP);
422   s++;
423   n = snext (&s);
424   if (!n)
425     return gpg_error (GPG_ERR_INV_SEXP);
426   if (!smatch (&s, n, "enc-val"))
427     return gpg_error (GPG_ERR_UNKNOWN_SEXP);
428   if (*s != '(')
429     return gpg_error (GPG_ERR_UNKNOWN_SEXP);
430   s++;
431   n = snext (&s);
432   if (!n)
433     return gpg_error (GPG_ERR_INV_SEXP);
434   if (smatch (&s, n, "rsa"))
435     {
436       if (*s != '(')
437         return gpg_error (GPG_ERR_UNKNOWN_SEXP);
438       s++;
439       n = snext (&s);
440       if (!n)
441         return gpg_error (GPG_ERR_INV_SEXP);
442       if (!smatch (&s, n, "a"))
443         return gpg_error (GPG_ERR_UNKNOWN_SEXP);
444       n = snext (&s);
445     }
446   else if (smatch (&s, n, "ecdh"))
447     {
448       if (*s != '(')
449         return gpg_error (GPG_ERR_UNKNOWN_SEXP);
450       s++;
451       n = snext (&s);
452       if (!n)
453         return gpg_error (GPG_ERR_INV_SEXP);
454       if (smatch (&s, n, "s"))
455         {
456           n = snext (&s);
457           s += n;
458           if (*s++ != ')')
459             return gpg_error (GPG_ERR_INV_SEXP);
460           if (*s++ != '(')
461             return gpg_error (GPG_ERR_UNKNOWN_SEXP);
462           n = snext (&s);
463           if (!n)
464             return gpg_error (GPG_ERR_INV_SEXP);
465         }
466       if (!smatch (&s, n, "e"))
467         return gpg_error (GPG_ERR_UNKNOWN_SEXP);
468       n = snext (&s);
469     }
470   else
471     return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
472
473   if (!n)
474     return gpg_error (GPG_ERR_UNKNOWN_SEXP);
475   ciphertext = s;
476   ciphertextlen = n;
477
478   rc = ask_for_card (ctrl, shadow_info, &kid);
479   if (rc)
480     return rc;
481
482   rc = agent_card_pkdecrypt (ctrl, kid, getpin_cb, ctrl, desc_text,
483                              ciphertext, ciphertextlen,
484                              &plaintext, &plaintextlen, r_padding);
485   if (!rc)
486     {
487       *r_buf = plaintext;
488       *r_len = plaintextlen;
489     }
490   xfree (kid);
491   return rc;
492 }
493
494 int
495 divert_writekey (ctrl_t ctrl, int force, const char *serialno,
496                  const char *id, const char *keydata, size_t keydatalen)
497 {
498   return agent_card_writekey (ctrl, force, serialno, id, keydata, keydatalen,
499                               getpin_cb, ctrl);
500 }
501
502 int
503 divert_generic_cmd (ctrl_t ctrl, const char *cmdline, void *assuan_context)
504 {
505   return agent_card_scd (ctrl, cmdline, getpin_cb, ctrl, assuan_context);
506 }