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