gpg: Fix using --decrypt along with --use-embedded-filename.
[gnupg.git] / tools / card-yubikey.c
1 /* card-yubikey.c - Yubikey specific functions.
2  * Copyright (C) 2019 g10 Code GmbH
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  * SPDX-License-Identifier: GPL-3.0-or-later
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <unistd.h>
27
28 #include "../common/util.h"
29 #include "../common/i18n.h"
30 #include "../common/tlv.h"
31 #include "../common/ttyio.h"
32 #include "gpg-card.h"
33
34
35 /* Object to describe requested interface options.  */
36 struct iface_s {
37   unsigned int usb:1;
38   unsigned int nfc:1;
39 };
40
41
42 /* Bit flags as used by the fields in struct ykapps_s. */
43 #define YKAPP_USB_SUPPORTED  0x01
44 #define YKAPP_USB_ENABLED    0x02
45 #define YKAPP_NFC_SUPPORTED  0x04
46 #define YKAPP_NFC_ENABLED    0x08
47 #define YKAPP_SELECTED       0x80  /* Selected by the command.  */
48
49 /* An object to describe the applications on a Yubikey.  Each field
50  * has 8 bits to hold the above flag values.  */
51 struct ykapps_s {
52   unsigned int otp:8;
53   unsigned int u2f:8;
54   unsigned int opgp:8;
55   unsigned int piv:8;
56   unsigned int oath:8;
57   unsigned int fido2:8;
58 };
59
60
61
62 /* Helper to parse an unsigned integer config value consisting of bit
63  * flags.  TAG select the config item and MASK is the mask ORed into
64  * the value for a set bit.  The function modifies YK.  */
65 static gpg_error_t
66 parse_ul_config_value (struct ykapps_s *yk,
67                        const unsigned char *config, size_t configlen,
68                        int tag, unsigned int mask)
69 {
70   const unsigned char *s;
71   size_t n;
72   unsigned long ul = 0;
73   int i;
74
75   s = find_tlv (config, configlen, tag, &n);
76   if (s && n)
77     {
78       if (n > sizeof ul)
79         {
80           log_error ("too large integer in Yubikey config tag %02x detected\n",
81                      tag);
82           if (opt.verbose)
83             log_printhex (config, configlen, "config:");
84           return gpg_error (GPG_ERR_CARD);
85         }
86       for (i=0; i < n; i++)
87         {
88           ul <<=8;
89           ul |= s[i];
90         }
91       if (ul & 0x01)
92         yk->otp |= mask;
93       if (ul & 0x02)
94         yk->u2f |= mask;
95       if (ul & 0x08)
96         yk->opgp |= mask;
97       if (ul & 0x10)
98         yk->piv |= mask;
99       if (ul & 0x20)
100         yk->oath |= mask;
101       if (ul & 0x200)
102         yk->fido2 |= mask;
103     }
104   return 0;
105 }
106
107
108 /* Create an unsigned integer config value for TAG from the data in YK
109  * and store it the provided 4 byte buffer RESULT. If ENABLE is true
110  * the respective APP_SELECTED bit in YK sets the corresponding bit
111  * flags, it is is false that bit flag is cleared.  IF APP_SELECTED is
112  * not set the bit flag is not changed.  */
113 static void
114 set_ul_config_value (struct ykapps_s *yk,
115                      unsigned int bitflag, int tag, unsigned int enable,
116                      unsigned char *result)
117 {
118   unsigned long ul = 0;
119
120   /* First set the current values.  */
121   if ((yk->otp & bitflag))
122     ul |= 0x01;
123   if ((yk->u2f & bitflag))
124     ul |= 0x02;
125   if ((yk->opgp & bitflag))
126     ul |= 0x08;
127   if ((yk->piv & bitflag))
128     ul |= 0x10;
129   if ((yk->oath & bitflag))
130     ul |= 0x20;
131   if ((yk->fido2 & bitflag))
132     ul |= 0x200;
133
134   /* Then enable or disable the bits according to the selection flag.  */
135   if (enable)
136     {
137       if ((yk->otp & YKAPP_SELECTED))
138         ul |= 0x01;
139       if ((yk->u2f & YKAPP_SELECTED))
140         ul |= 0x02;
141       if ((yk->opgp & YKAPP_SELECTED))
142         ul |= 0x08;
143       if ((yk->piv & YKAPP_SELECTED))
144         ul |= 0x10;
145       if ((yk->oath & YKAPP_SELECTED))
146         ul |= 0x20;
147       if ((yk->fido2 & YKAPP_SELECTED))
148         ul |= 0x200;
149     }
150   else
151     {
152       if ((yk->otp & YKAPP_SELECTED))
153         ul &= ~0x01;
154       if ((yk->u2f & YKAPP_SELECTED))
155         ul &= ~0x02;
156       if ((yk->opgp & YKAPP_SELECTED))
157         ul &= ~0x08;
158       if ((yk->piv & YKAPP_SELECTED))
159         ul &= ~0x10;
160       if ((yk->oath & YKAPP_SELECTED))
161         ul &= ~0x20;
162       if ((yk->fido2 & YKAPP_SELECTED))
163         ul &= ~0x200;
164     }
165
166   /* Make sure that we do not disable the CCID transport.  Without
167    * CCID we won't have any way to change the configuration again.  We
168    * would instead need one of the other Yubikey tools to enable an
169    * application and thus its transport again.  */
170   if (bitflag == YKAPP_USB_ENABLED && !(ul & (0x08|0x10|0x20)))
171     {
172       log_info ("Enabling PIV to have at least one CCID transport\n");
173       ul |= 0x10;
174     }
175
176   result[0] = tag;
177   result[1] = 2;
178   result[2] = ul >> 8;
179   result[3] = ul;
180 }
181
182
183 /* Print the info from YK.  */
184 static void
185 yk_list (estream_t fp, struct ykapps_s *yk)
186 {
187   if (opt.interactive)
188     tty_fprintf (fp, ("Application  USB    NFC\n"
189                       "-----------------------\n"));
190   tty_fprintf (fp, "OTP          %s    %s\n",
191                (yk->otp & YKAPP_USB_SUPPORTED)?
192                (yk->otp & YKAPP_USB_ENABLED?   "yes" : "no ") : "-  ",
193                (yk->otp & YKAPP_NFC_SUPPORTED)?
194                (yk->otp & YKAPP_NFC_ENABLED?   "yes" : "no ") : "-  ");
195   tty_fprintf (fp, "U2F          %s    %s\n",
196                (yk->otp & YKAPP_USB_SUPPORTED)?
197                (yk->otp & YKAPP_USB_ENABLED?   "yes" : "no ") : "-  ",
198                (yk->otp & YKAPP_NFC_SUPPORTED)?
199                (yk->otp & YKAPP_NFC_ENABLED?   "yes" : "no ") : "-  ");
200   tty_fprintf (fp, "OPGP         %s    %s\n",
201                (yk->opgp & YKAPP_USB_SUPPORTED)?
202                (yk->opgp & YKAPP_USB_ENABLED?  "yes" : "no ") : "-  ",
203                (yk->opgp & YKAPP_NFC_SUPPORTED)?
204                (yk->opgp & YKAPP_NFC_ENABLED?  "yes" : "no ") : "-  ");
205   tty_fprintf (fp, "PIV          %s    %s\n",
206                (yk->piv & YKAPP_USB_SUPPORTED)?
207                (yk->piv & YKAPP_USB_ENABLED?   "yes" : "no ") : "-  ",
208                (yk->piv & YKAPP_NFC_SUPPORTED)?
209                (yk->piv & YKAPP_NFC_ENABLED?   "yes" : "no ") : "-  ");
210   tty_fprintf (fp, "OATH         %s    %s\n",
211                (yk->oath & YKAPP_USB_SUPPORTED)?
212                (yk->oath & YKAPP_USB_ENABLED?  "yes" : "no ") : "-  ",
213                (yk->oath & YKAPP_NFC_SUPPORTED)?
214                (yk->oath & YKAPP_NFC_ENABLED?  "yes" : "no ") : "-  ");
215   tty_fprintf (fp, "FIDO2        %s    %s\n",
216                (yk->fido2 & YKAPP_USB_SUPPORTED)?
217                (yk->fido2 & YKAPP_USB_ENABLED? "yes" : "no ") : "-  ",
218                (yk->fido2 & YKAPP_NFC_SUPPORTED)?
219                (yk->fido2 & YKAPP_NFC_ENABLED? "yes" : "no ") : "-  ");
220 }
221
222
223 /* Enable disable the apps as marked in YK with flag YKAPP_SELECTED.  */
224 static gpg_error_t
225 yk_enable_disable (struct ykapps_s *yk, struct iface_s *iface,
226                    const unsigned char *config, size_t configlen, int enable)
227 {
228   gpg_error_t err = 0;
229   unsigned char apdu[100];
230   unsigned int apdulen;
231   /* const unsigned char *s; */
232   /* size_t n; */
233   char *hexapdu = NULL;
234
235   apdulen = 0;
236   apdu[apdulen++] = 0x00;
237   apdu[apdulen++] = 0x1c;  /* Write Config instruction.  */
238   apdu[apdulen++] = 0x00;
239   apdu[apdulen++] = 0x00;
240   apdu[apdulen++] = 0x00;  /* Lc will be fixed up later.  */
241   apdu[apdulen++] = 0x00;  /* Length of data will also be fixed up later.  */
242
243   /* The ykman tool has no way to set NFC and USB flags in one go.
244    * Reasoning about the Yubikey's firmware it seems plausible that
245    * combining should work.  Let's try it here if the user called for
246    * setting both interfaces.  */
247   if (iface->nfc)
248     {
249       set_ul_config_value (yk, YKAPP_NFC_ENABLED, 0x0e, enable, apdu+apdulen);
250       apdulen += 4;
251     }
252   if (iface->usb)
253     {
254       set_ul_config_value (yk, YKAPP_USB_ENABLED, 0x03, enable, apdu+apdulen);
255       apdulen += 4;
256       /* Yubikey's ykman copies parts of the config data when writing
257        * the config for USB.  Below is a commented example on how that
258        * can be done.  */
259       (void)config;
260       (void)configlen;
261       /* Copy the device flags.  */
262       /* s = find_tlv (config, configlen, 0x08, &n); */
263       /* if (s && n) */
264       /*   { */
265       /*     s -= 2; */
266       /*     n += 2; */
267       /*     if (apdulen + n > sizeof apdu) */
268       /*       { */
269       /*         err = gpg_error (GPG_ERR_BUFFER_TOO_SHORT); */
270       /*         goto leave; */
271       /*       } */
272       /*     memcpy (apdu+apdulen, s, n); */
273       /*     apdulen += n; */
274       /*   } */
275     }
276   if (iface->nfc || iface->usb)
277     {
278       if (apdulen + 2 > sizeof apdu)
279         {
280           err = gpg_error (GPG_ERR_BUFFER_TOO_SHORT);
281           goto leave;
282         }
283       /* Disable the next two lines to let the card reboot.  Not doing
284        * this is however more convenient for this tool because further
285        * commands don't end up with an error.  It seems to be better
286        * that a "reset" command from gpg-card-tool is run at the
287        * user's discretion.  */
288       /* apdu[apdulen++] = 0x0c;  /\* Reboot tag *\/ */
289       /* apdu[apdulen++] = 0;     /\* No data for reboot.  *\/ */
290       /* Fixup the lngth bytes.  */
291       apdu[4] = apdulen - 6 + 1;
292       apdu[5] = apdulen - 6;
293
294       hexapdu = bin2hex (apdu, apdulen, NULL);
295       if (!hexapdu)
296         err = gpg_error_from_syserror ();
297       else
298         err = send_apdu (hexapdu, "YK.write_config", 0, NULL, NULL);
299     }
300
301  leave:
302   xfree (hexapdu);
303   return err;
304 }
305
306
307 /* Implementation part of cmd_yubikey.  ARGV is an array of size ARGc
308  * with the argumets given to the yubikey command.  Note that ARGV has
309  * no terminating NULL so that ARGC must be considred.  FP is the
310  * stream to output information.  This function must only be called on
311  * Yubikeys. */
312 gpg_error_t
313 yubikey_commands (card_info_t info, estream_t fp, int argc, char *argv[])
314 {
315   gpg_error_t err;
316   enum {ykLIST, ykENABLE, ykDISABLE } cmd;
317   struct iface_s iface = {0,0};
318   struct ykapps_s ykapps = {0};
319   unsigned char *config = NULL;
320   size_t configlen;
321   int i;
322
323   if (!argc)
324     return gpg_error (GPG_ERR_SYNTAX);
325
326   /* Parse command.  */
327   if (!ascii_strcasecmp (argv[0], "list"))
328     cmd = ykLIST;
329   else if (!ascii_strcasecmp (argv[0], "enable"))
330     cmd = ykENABLE;
331   else if (!ascii_strcasecmp (argv[0], "disable"))
332     cmd = ykDISABLE;
333   else
334     {
335       err = gpg_error (GPG_ERR_UNKNOWN_COMMAND);
336       goto leave;
337     }
338
339   if (info->cardversion < 0x050000 && cmd != ykLIST)
340     {
341       log_info ("Sub-command '%s' is only support by Yubikey-5 and later\n",
342                 argv[0]);
343       err = gpg_error (GPG_ERR_NOT_SUPPORTED);
344       goto leave;
345     }
346
347   /* Parse interface if needed.  */
348   if (cmd == ykLIST)
349     iface.usb = iface.nfc = 1;
350   else if (argc < 2)
351     {
352       err = gpg_error (GPG_ERR_SYNTAX);
353       goto leave;
354     }
355   else if (!ascii_strcasecmp (argv[1], "usb"))
356     iface.usb = 1;
357   else if (!ascii_strcasecmp (argv[1], "nfc"))
358     iface.nfc = 1;
359   else if (!ascii_strcasecmp (argv[1], "all") || !strcmp (argv[1], "*"))
360     iface.usb = iface.nfc = 1;
361   else
362     {
363       err = gpg_error (GPG_ERR_SYNTAX);
364       goto leave;
365     }
366
367   /* Parse list of applications.  */
368   for (i=2; i < argc; i++)
369     {
370       if (!ascii_strcasecmp (argv[i], "otp"))
371         ykapps.otp = 0x80;
372       else if (!ascii_strcasecmp (argv[i], "u2f"))
373         ykapps.u2f = 0x80;
374       else if (!ascii_strcasecmp (argv[i], "opgp")
375                ||!ascii_strcasecmp (argv[i], "openpgp"))
376         ykapps.opgp = 0x80;
377       else if (!ascii_strcasecmp (argv[i], "piv"))
378         ykapps.piv = 0x80;
379       else if (!ascii_strcasecmp (argv[i], "oath")
380                || !ascii_strcasecmp (argv[i], "oauth"))
381         ykapps.oath = 0x80;
382       else if (!ascii_strcasecmp (argv[i], "fido2"))
383         ykapps.fido2 = 0x80;
384       else if (!ascii_strcasecmp (argv[i], "all")|| !strcmp (argv[i], "*"))
385         {
386           ykapps.otp = ykapps.u2f = ykapps.opgp = ykapps.piv = ykapps.oath
387             = ykapps.fido2 = 0x80;
388         }
389       else
390         {
391           err = gpg_error (GPG_ERR_SYNTAX);
392           goto leave;
393         }
394     }
395
396   /* Select the Yubikey Manager application.  */
397   err = send_apdu ("00A4040008a000000527471117", "Select.YK-Manager", 0,
398                    NULL, NULL);
399   if (err)
400     goto leave;
401   /* Send the read config command.  */
402   err = send_apdu ("001D000000", "YK.read_config", 0, &config, &configlen);
403   if (err)
404     goto leave;
405   if (!configlen || *config > configlen - 1)
406     {
407       /* The length byte is shorter than the actual length. */
408       log_error ("Yubikey returned improper config data\n");
409       log_printhex (config, configlen, "config:");
410       err = gpg_error (GPG_ERR_CARD);
411       goto leave;
412     }
413   if (configlen-1 > *config)
414     {
415       log_info ("Extra config data ignored\n");
416       log_printhex (config, configlen, "config:");
417     }
418   configlen = *config;
419
420   err = parse_ul_config_value (&ykapps, config+1, configlen,
421                                0x01, YKAPP_USB_SUPPORTED);
422   if (!err)
423     err = parse_ul_config_value (&ykapps, config+1, configlen,
424                                  0x03, YKAPP_USB_ENABLED);
425   if (!err)
426     err = parse_ul_config_value (&ykapps, config+1, configlen,
427                                  0x0d, YKAPP_NFC_SUPPORTED);
428   if (!err)
429     err = parse_ul_config_value (&ykapps, config+1, configlen,
430                                  0x0e, YKAPP_NFC_ENABLED);
431   if (err)
432     goto leave;
433
434   switch (cmd)
435     {
436     case ykLIST: yk_list (fp, &ykapps); break;
437     case ykENABLE: err = yk_enable_disable (&ykapps, &iface,
438                                             config+1, configlen, 1); break;
439     case ykDISABLE: err = yk_enable_disable (&ykapps, &iface,
440                                              config+1, configlen, 0); break;
441     }
442
443  leave:
444   xfree (config);
445   return err;
446 }