chiark / gitweb /
Import gnupg2_2.1.17.orig.tar.bz2
[gnupg2.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);
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                         ? L_("Please insert the card with serial number")
93                         : L_("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 = L_("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 = L_("PUK");
210               is_puk = 1;
211             }
212           else if (*s == 'N')
213             newpin = 1;
214           else if (*s == 'R')
215             {
216               prompt = L_("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 pinpad mode: The
227      callback opens the popup and immediately 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                              L_("%s%%0A%%0AUse the reader's pinpad 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, NULL, 0);
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                               L_("Repeat this Reset Code"):
292                               is_puk?
293                               L_("Repeat this PUK"):
294                               L_("Repeat this PIN")),
295                              prompt, NULL, pi2, NULL, 0);
296           if (!rc && strcmp (pi->pin, pi2->pin))
297             {
298               again_text = (resetcode?
299                             L_("Reset Code not correctly repeated; try again"):
300                             is_puk?
301                             L_("PUK not correctly repeated; try again"):
302                             L_("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                      L_("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, NULL, 0);
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                size_t *r_siglen)
340 {
341   int rc;
342   char *kid;
343   size_t siglen;
344   unsigned char *sigval = NULL;
345
346   rc = ask_for_card (ctrl, shadow_info, &kid);
347   if (rc)
348     return rc;
349
350   if (algo == MD_USER_TLS_MD5SHA1)
351     {
352       int save = ctrl->use_auth_call;
353       ctrl->use_auth_call = 1;
354       rc = agent_card_pksign (ctrl, kid, getpin_cb, ctrl,
355                               algo, digest, digestlen, &sigval, &siglen);
356       ctrl->use_auth_call = save;
357     }
358   else
359     {
360       unsigned char *data;
361       size_t ndata;
362
363       rc = encode_md_for_card (digest, digestlen, algo, &data, &ndata);
364       if (!rc)
365         {
366           rc = agent_card_pksign (ctrl, kid, getpin_cb, ctrl,
367                                   algo, data, ndata, &sigval, &siglen);
368           xfree (data);
369         }
370     }
371
372   if (!rc)
373     {
374       *r_sig = sigval;
375       *r_siglen = siglen;
376     }
377
378   xfree (kid);
379
380   return rc;
381 }
382
383
384 /* Decrypt the the value given asn an S-expression in CIPHER using the
385    key identified by SHADOW_INFO and return the plaintext in an
386    allocated buffer in R_BUF.  The padding information is stored at
387    R_PADDING with -1 for not known.  */
388 int
389 divert_pkdecrypt (ctrl_t ctrl,
390                   const unsigned char *cipher,
391                   const unsigned char *shadow_info,
392                   char **r_buf, size_t *r_len, int *r_padding)
393 {
394   int rc;
395   char *kid;
396   const unsigned char *s;
397   size_t n;
398   const unsigned char *ciphertext;
399   size_t ciphertextlen;
400   char *plaintext;
401   size_t plaintextlen;
402
403   *r_padding = -1;
404
405   s = cipher;
406   if (*s != '(')
407     return gpg_error (GPG_ERR_INV_SEXP);
408   s++;
409   n = snext (&s);
410   if (!n)
411     return gpg_error (GPG_ERR_INV_SEXP);
412   if (!smatch (&s, n, "enc-val"))
413     return gpg_error (GPG_ERR_UNKNOWN_SEXP);
414   if (*s != '(')
415     return gpg_error (GPG_ERR_UNKNOWN_SEXP);
416   s++;
417   n = snext (&s);
418   if (!n)
419     return gpg_error (GPG_ERR_INV_SEXP);
420   if (smatch (&s, n, "rsa"))
421     {
422       if (*s != '(')
423         return gpg_error (GPG_ERR_UNKNOWN_SEXP);
424       s++;
425       n = snext (&s);
426       if (!n)
427         return gpg_error (GPG_ERR_INV_SEXP);
428       if (!smatch (&s, n, "a"))
429         return gpg_error (GPG_ERR_UNKNOWN_SEXP);
430       n = snext (&s);
431     }
432   else if (smatch (&s, n, "ecdh"))
433     {
434       if (*s != '(')
435         return gpg_error (GPG_ERR_UNKNOWN_SEXP);
436       s++;
437       n = snext (&s);
438       if (!n)
439         return gpg_error (GPG_ERR_INV_SEXP);
440       if (smatch (&s, n, "s"))
441         {
442           n = snext (&s);
443           s += n;
444           if (*s++ != ')')
445             return gpg_error (GPG_ERR_INV_SEXP);
446           if (*s++ != '(')
447             return gpg_error (GPG_ERR_UNKNOWN_SEXP);
448           n = snext (&s);
449           if (!n)
450             return gpg_error (GPG_ERR_INV_SEXP);
451         }
452       if (!smatch (&s, n, "e"))
453         return gpg_error (GPG_ERR_UNKNOWN_SEXP);
454       n = snext (&s);
455     }
456   else
457     return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
458
459   if (!n)
460     return gpg_error (GPG_ERR_UNKNOWN_SEXP);
461   ciphertext = s;
462   ciphertextlen = n;
463
464   rc = ask_for_card (ctrl, shadow_info, &kid);
465   if (rc)
466     return rc;
467
468   rc = agent_card_pkdecrypt (ctrl, kid, getpin_cb, ctrl,
469                              ciphertext, ciphertextlen,
470                              &plaintext, &plaintextlen, r_padding);
471   if (!rc)
472     {
473       *r_buf = plaintext;
474       *r_len = plaintextlen;
475     }
476   xfree (kid);
477   return rc;
478 }
479
480 int
481 divert_writekey (ctrl_t ctrl, int force, const char *serialno,
482                  const char *id, const char *keydata, size_t keydatalen)
483 {
484   return agent_card_writekey (ctrl, force, serialno, id, keydata, keydatalen,
485                               getpin_cb, ctrl);
486 }
487
488 int
489 divert_generic_cmd (ctrl_t ctrl, const char *cmdline, void *assuan_context)
490 {
491   return agent_card_scd (ctrl, cmdline, getpin_cb, ctrl, assuan_context);
492 }