31644049554ce5d345cce31034e14791dd74bbbb
[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 /* Return true if STRING ends in "%0A". */
161 static int
162 has_percent0A_suffix (const char *string)
163 {
164   size_t n;
165
166   return (string
167           && (n = strlen (string)) >= 3
168           && !strcmp (string + n - 3, "%0A"));
169 }
170
171
172 /* Callback used to ask for the PIN which should be set into BUF.  The
173    buf has been allocated by the caller and is of size MAXBUF which
174    includes the terminating null.  The function should return an UTF-8
175    string with the passphrase, the buffer may optionally be padded
176    with arbitrary characters.
177
178    If DESC_TEXT is not NULL it can be used as further informtion shown
179    atop of the INFO message.
180
181    INFO gets displayed as part of a generic string.  However if the
182    first character of INFO is a vertical bar all up to the next
183    verical bar are considered flags and only everything after the
184    second vertical bar gets displayed as the full prompt.
185
186    Flags:
187
188       'N' = New PIN, this requests a second prompt to repeat the
189             PIN.  If the PIN is not correctly repeated it starts from
190             all over.
191       'A' = The PIN is an Admin PIN, SO-PIN or alike.
192       'P' = The PIN is a PUK (Personal Unblocking Key).
193       'R' = The PIN is a Reset Code.
194
195    Example:
196
197      "|AN|Please enter the new security officer's PIN"
198
199    The text "Please ..." will get displayed and the flags 'A' and 'N'
200    are considered.
201  */
202 static int
203 getpin_cb (void *opaque, const char *desc_text, const char *info,
204            char *buf, size_t maxbuf)
205 {
206   struct pin_entry_info_s *pi;
207   int rc;
208   ctrl_t ctrl = opaque;
209   const char *ends, *s;
210   int any_flags = 0;
211   int newpin = 0;
212   int resetcode = 0;
213   int is_puk = 0;
214   const char *again_text = NULL;
215   const char *prompt = "PIN";
216
217   if (buf && maxbuf < 2)
218     return gpg_error (GPG_ERR_INV_VALUE);
219
220   /* Parse the flags. */
221   if (info && *info =='|' && (ends=strchr (info+1, '|')))
222     {
223       for (s=info+1; s < ends; s++)
224         {
225           if (*s == 'A')
226             prompt = L_("Admin PIN");
227           else if (*s == 'P')
228             {
229               /* TRANSLATORS: A PUK is the Personal Unblocking Code
230                  used to unblock a PIN. */
231               prompt = L_("PUK");
232               is_puk = 1;
233             }
234           else if (*s == 'N')
235             newpin = 1;
236           else if (*s == 'R')
237             {
238               prompt = L_("Reset Code");
239               resetcode = 1;
240             }
241         }
242       info = ends+1;
243       any_flags = 1;
244     }
245   else if (info && *info == '|')
246     log_debug ("pin_cb called without proper PIN info hack\n");
247
248   /* If BUF has been passed as NULL, we are in pinpad mode: The
249      callback opens the popup and immediately returns. */
250   if (!buf)
251     {
252       if (maxbuf == 0) /* Close the pinentry. */
253         {
254           agent_popup_message_stop (ctrl);
255           rc = 0;
256         }
257       else if (maxbuf == 1)  /* Open the pinentry. */
258         {
259           if (info)
260             {
261               char *desc, *desc2;
262
263               if ( asprintf (&desc,
264                              L_("%s%%0A%%0AUse the reader's pinpad for input."),
265                              info) < 0 )
266                 rc = gpg_error_from_syserror ();
267               else
268                 {
269                   /* Prepend DESC_TEXT to INFO.  */
270                   if (desc_text)
271                     desc2 = strconcat (desc_text,
272                                        has_percent0A_suffix (desc_text)
273                                        ? "%0A" : "%0A%0A",
274                                        desc, NULL);
275                   else
276                     desc2 = NULL;
277                   rc = agent_popup_message_start (ctrl,
278                                                   desc2? desc2:desc, NULL);
279                   xfree (desc2);
280                   xfree (desc);
281                 }
282             }
283           else
284             rc = agent_popup_message_start (ctrl, desc_text, NULL);
285         }
286       else
287         rc = gpg_error (GPG_ERR_INV_VALUE);
288       return rc;
289     }
290
291   /* FIXME: keep PI and TRIES in OPAQUE.  Frankly this is a whole
292      mess because we should call the card's verify function from the
293      pinentry check pin CB. */
294  again:
295   pi = gcry_calloc_secure (1, sizeof (*pi) + maxbuf + 10);
296   if (!pi)
297     return gpg_error_from_syserror ();
298   pi->max_length = maxbuf-1;
299   pi->min_digits = 0;  /* we want a real passphrase */
300   pi->max_digits = 16;
301   pi->max_tries = 3;
302
303   if (any_flags)
304     {
305       {
306         char *desc2;
307
308         if (desc_text)
309           desc2 = strconcat (desc_text,
310                              has_percent0A_suffix (desc_text)
311                              ? "%0A" : "%0A%0A",
312                              info, NULL);
313         else
314           desc2 = NULL;
315         rc = agent_askpin (ctrl, desc2, prompt, again_text, pi, NULL, 0);
316         xfree (desc2);
317       }
318       again_text = NULL;
319       if (!rc && newpin)
320         {
321           struct pin_entry_info_s *pi2;
322           pi2 = gcry_calloc_secure (1, sizeof (*pi) + maxbuf + 10);
323           if (!pi2)
324             {
325               rc = gpg_error_from_syserror ();
326               xfree (pi);
327               return rc;
328             }
329           pi2->max_length = maxbuf-1;
330           pi2->min_digits = 0;
331           pi2->max_digits = 16;
332           pi2->max_tries = 1;
333           rc = agent_askpin (ctrl,
334                              (resetcode?
335                               L_("Repeat this Reset Code"):
336                               is_puk?
337                               L_("Repeat this PUK"):
338                               L_("Repeat this PIN")),
339                              prompt, NULL, pi2, NULL, 0);
340           if (!rc && strcmp (pi->pin, pi2->pin))
341             {
342               again_text = (resetcode?
343                             L_("Reset Code not correctly repeated; try again"):
344                             is_puk?
345                             L_("PUK not correctly repeated; try again"):
346                             L_("PIN not correctly repeated; try again"));
347               xfree (pi2);
348               xfree (pi);
349               goto again;
350             }
351           xfree (pi2);
352         }
353     }
354   else
355     {
356       char *desc, *desc2;
357
358       if ( asprintf (&desc,
359                      L_("Please enter the PIN%s%s%s to unlock the card"),
360                      info? " (":"",
361                      info? info:"",
362                      info? ")":"") < 0)
363         desc = NULL;
364       if (desc_text)
365         desc2 = strconcat (desc_text,
366                            has_percent0A_suffix (desc_text)
367                            ? "%0A" : "%0A%0A",
368                            desc, NULL);
369       else
370         desc2 = NULL;
371       rc = agent_askpin (ctrl, desc2? desc2 : desc? desc : info,
372                          prompt, NULL, pi, NULL, 0);
373       xfree (desc2);
374       xfree (desc);
375     }
376
377   if (!rc)
378     {
379       strncpy (buf, pi->pin, maxbuf-1);
380       buf[maxbuf-1] = 0;
381     }
382   xfree (pi);
383   return rc;
384 }
385
386
387
388 /* This function is used when a sign operation has been diverted to a
389  * smartcard.  DESC_TEXT is the original text for a prompt has send by
390  * gpg to gpg-agent.
391  *
392  * FIXME: Explain the other args.  */
393 int
394 divert_pksign (ctrl_t ctrl, const char *desc_text,
395                const unsigned char *digest, size_t digestlen, int algo,
396                const unsigned char *shadow_info, unsigned char **r_sig,
397                size_t *r_siglen)
398 {
399   int rc;
400   char *kid;
401   size_t siglen;
402   unsigned char *sigval = NULL;
403
404   rc = ask_for_card (ctrl, shadow_info, &kid);
405   if (rc)
406     return rc;
407
408   if (algo == MD_USER_TLS_MD5SHA1)
409     {
410       int save = ctrl->use_auth_call;
411       ctrl->use_auth_call = 1;
412       rc = agent_card_pksign (ctrl, kid, getpin_cb, ctrl, desc_text,
413                               algo, digest, digestlen, &sigval, &siglen);
414       ctrl->use_auth_call = save;
415     }
416   else
417     {
418       unsigned char *data;
419       size_t ndata;
420
421       rc = encode_md_for_card (digest, digestlen, algo, &data, &ndata);
422       if (!rc)
423         {
424           rc = agent_card_pksign (ctrl, kid, getpin_cb, ctrl, desc_text,
425                                   algo, data, ndata, &sigval, &siglen);
426           xfree (data);
427         }
428     }
429
430   if (!rc)
431     {
432       *r_sig = sigval;
433       *r_siglen = siglen;
434     }
435
436   xfree (kid);
437
438   return rc;
439 }
440
441
442 /* Decrypt the value given asn an S-expression in CIPHER using the
443    key identified by SHADOW_INFO and return the plaintext in an
444    allocated buffer in R_BUF.  The padding information is stored at
445    R_PADDING with -1 for not known.  */
446 int
447 divert_pkdecrypt (ctrl_t ctrl, const char *desc_text,
448                   const unsigned char *cipher,
449                   const unsigned char *shadow_info,
450                   char **r_buf, size_t *r_len, int *r_padding)
451 {
452   int rc;
453   char *kid;
454   const unsigned char *s;
455   size_t n;
456   const unsigned char *ciphertext;
457   size_t ciphertextlen;
458   char *plaintext;
459   size_t plaintextlen;
460
461   *r_padding = -1;
462
463   s = cipher;
464   if (*s != '(')
465     return gpg_error (GPG_ERR_INV_SEXP);
466   s++;
467   n = snext (&s);
468   if (!n)
469     return gpg_error (GPG_ERR_INV_SEXP);
470   if (!smatch (&s, n, "enc-val"))
471     return gpg_error (GPG_ERR_UNKNOWN_SEXP);
472   if (*s != '(')
473     return gpg_error (GPG_ERR_UNKNOWN_SEXP);
474   s++;
475   n = snext (&s);
476   if (!n)
477     return gpg_error (GPG_ERR_INV_SEXP);
478   if (smatch (&s, n, "rsa"))
479     {
480       if (*s != '(')
481         return gpg_error (GPG_ERR_UNKNOWN_SEXP);
482       s++;
483       n = snext (&s);
484       if (!n)
485         return gpg_error (GPG_ERR_INV_SEXP);
486       if (!smatch (&s, n, "a"))
487         return gpg_error (GPG_ERR_UNKNOWN_SEXP);
488       n = snext (&s);
489     }
490   else if (smatch (&s, n, "ecdh"))
491     {
492       if (*s != '(')
493         return gpg_error (GPG_ERR_UNKNOWN_SEXP);
494       s++;
495       n = snext (&s);
496       if (!n)
497         return gpg_error (GPG_ERR_INV_SEXP);
498       if (smatch (&s, n, "s"))
499         {
500           n = snext (&s);
501           s += n;
502           if (*s++ != ')')
503             return gpg_error (GPG_ERR_INV_SEXP);
504           if (*s++ != '(')
505             return gpg_error (GPG_ERR_UNKNOWN_SEXP);
506           n = snext (&s);
507           if (!n)
508             return gpg_error (GPG_ERR_INV_SEXP);
509         }
510       if (!smatch (&s, n, "e"))
511         return gpg_error (GPG_ERR_UNKNOWN_SEXP);
512       n = snext (&s);
513     }
514   else
515     return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
516
517   if (!n)
518     return gpg_error (GPG_ERR_UNKNOWN_SEXP);
519   ciphertext = s;
520   ciphertextlen = n;
521
522   rc = ask_for_card (ctrl, shadow_info, &kid);
523   if (rc)
524     return rc;
525
526   rc = agent_card_pkdecrypt (ctrl, kid, getpin_cb, ctrl, desc_text,
527                              ciphertext, ciphertextlen,
528                              &plaintext, &plaintextlen, r_padding);
529   if (!rc)
530     {
531       *r_buf = plaintext;
532       *r_len = plaintextlen;
533     }
534   xfree (kid);
535   return rc;
536 }
537
538 int
539 divert_writekey (ctrl_t ctrl, int force, const char *serialno,
540                  const char *id, const char *keydata, size_t keydatalen)
541 {
542   return agent_card_writekey (ctrl, force, serialno, id, keydata, keydatalen,
543                               getpin_cb, ctrl);
544 }
545
546 int
547 divert_generic_cmd (ctrl_t ctrl, const char *cmdline, void *assuan_context)
548 {
549   return agent_card_scd (ctrl, cmdline, getpin_cb, ctrl, assuan_context);
550 }