1 /* gpg-pair-tool.c - The tool to run the pairing protocol.
2  * Copyright (C) 2018 g10 Code GmbH
3  *
4  * This file is part of GnuPG.
5  *
6  * This file is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * This file 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 Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, see <https://www.gnu.org/licenses/>.
18  * SPDX-License-Identifier: LGPL-2.1-or-later
19  */
20 
21 /* Protocol:
22  *
23  *    Initiator             Responder
24  *       |                     |
25  *       |    COMMIT           |
26  *       |-------------------->|
27  *       |                     |
28  *       |    DHPART1          |
29  *       |<--------------------|
30  *       |                     |
31  *       |    DHPART2          |
32  *       |-------------------->|
33  *       |                     |
34  *       |    CONFIRM          |
35  *       |<--------------------|
36  *       |                     |
37  *
38  * The initiator creates a keypar (PKi,SKi) and sends this COMMIT
39  * message to the responder:
40  *
41  *   7 byte Magic, value: "GPG-pa1"
42  *   1 byte MessageType, value 1 (COMMIT)
43  *   8 byte SessionId, value: 8 random bytes
44  *   1 byte Realm, value 1
45  *   2 byte reserved, value 0
46  *   5 byte ExpireTime, value: seconds since Epoch as an unsigned int.
47  *  32 byte Hash(PKi)
48  *
49  * The initiator also needs to locally store the sessionid, the realm,
50  * the expiration time, the keypair and a hash of the entire message
51  * sent.
52  *
53  * The responder checks that the received message has not expired and
54  * stores sessionid, realm, expiretime and the Hash(PKi).  The
55  * Responder then creates and locally stores its own keypair (PKr,SKr)
56  * and sends the DHPART1 message back:
57  *
58  *   7 byte Magic, value: "GPG-pa1"
59  *   1 byte MessageType, value 2 (DHPART1)
60  *   8 byte SessionId from COMMIT message
61  *  32 byte PKr
62  *  32 byte Hash(Hash(COMMIT) || DHPART1[0..47])
63  *
64  * Note that Hash(COMMIT) is the hash over the entire received COMMIT
65  * message.  DHPART1[0..47] are the first 48 bytes of the created
66  * DHPART1 message.
67  *
68  * The Initiator receives the DHPART1 message and checks that the hash
69  * matches.  Although this hash is easily malleable it is later in the
70  * protocol used to assert the integrity of all messages.  The
71  * Initiator then computes the shared master secret from its SKi and
72  * the received PKr.  Using this master secret several keys are
73  * derived:
74  *
75  *  - HMACi-key using the label "GPG-pa1-HMACi-key".
76  *  - SYMx-key using the label "GPG-pa1-SYMx-key"
77  *
78  * For details on the KDF see the implementation of the function kdf.
79  * The master secret is stored securily in the local state.  The
80  * DHPART2 message is then created and send to the Responder:
81  *
82  *   7 byte Magic, value: "GPG-pa1"
83  *   1 byte MessageType, value 3 (DHPART2)
84  *   8 byte SessionId from COMMIT message
85  *  32 byte PKi
86  *  32 byte MAC(HMACi-key, Hash(DHPART1) || DHPART2[0..47] || SYMx-key)
87  *
88  * The Responder receives the DHPART2 message and checks that the hash
89  * of the received PKi matches the Hash(PKi) value as received earlier
90  * with the COMMIT message.  The Responder now also computes the
91  * shared master secret from its SKr and the received PKi and derives
92  * the keys:
93  *
94  *  - HMACi-key using the label "GPG-pa1-HMACi-key".
95  *  - HMACr-key using the label "GPG-pa1-HMACr-key".
96  *  - SYMx-key using the label "GPG-pa1-SYMx-key"
97  *  - SAS using the label "GPG-pa1-SAS"
98  *
99  * With these keys the MAC from the received DHPART2 message is
100  * checked.  On success a SAS is displayed to the user and a CONFIRM
101  * message send back:
102  *
103  *   7 byte Magic, value: "GPG-pa1"
104  *   1 byte MessageType, value 4 (CONFIRM)
105  *   8 byte SessionId from COMMIT message
106  *  32 byte MAC(HMACr-key, Hash(DHPART2) || CONFIRM[0..15] || SYMx-key)
107  *
108  * The Initiator receives this CONFIRM message, gets the master shared
109  * secrey from its local state and derives the keys.  It checks the
110  * the MAC in the received CONFIRM message and ask the user to enter
111  * the SAS as displayed by the responder.  Iff the SAS matches the
112  * master key is flagged as confirmed and the Initiator may now use a
113  * derived key to send encrypted data to the Responder.
114  *
115  * In case the Responder also needs to send encrypted data we need to
116  * introduce another final message to tell the responder that the
117  * Initiator validated the SAS.
118  *
119  * TODO:  Encrypt the state files using a key stored in gpg-agent's cache.
120  *
121  */
122 
123 #include <config.h>
124 
125 #include <stdio.h>
126 #include <stdlib.h>
127 #include <string.h>
128 #include <sys/types.h>
129 #include <sys/stat.h>
130 #include <unistd.h>
131 #include <dirent.h>
132 #include <stdarg.h>
133 
134 #include "../common/util.h"
135 #include "../common/status.h"
136 #include "../common/i18n.h"
137 #include "../common/sysutils.h"
138 #include "../common/init.h"
139 #include "../common/name-value.h"
140 
141 /* Constants to identify the commands and options. */
142 enum cmd_and_opt_values
143   {
144     aNull       = 0,
145 
146     oQuiet      = 'q',
147     oVerbose	= 'v',
148     oOutput     = 'o',
149     oArmor      = 'a',
150 
151     aInitiate   = 400,
152     aRespond    = 401,
153     aGet        = 402,
154     aCleanup    = 403,
155 
156     oDebug      = 500,
157     oStatusFD,
158     oHomedir,
159     oSAS,
160 
161     oDummy
162   };
163 
164 
165 /* The list of commands and options. */
166 static gpgrt_opt_t opts[] = {
167   ARGPARSE_group (300, ("@Commands:\n ")),
168 
169   ARGPARSE_c (aInitiate, "initiate", N_("initiate a pairing request")),
170   ARGPARSE_c (aRespond,  "respond", N_("respond to a pairing request")),
171   ARGPARSE_c (aGet,      "get",     N_("return the keys")),
172   ARGPARSE_c (aCleanup,  "cleanup", N_("remove expired states etc.")),
173 
174   ARGPARSE_group (301, ("@\nOptions:\n ")),
175 
176   ARGPARSE_s_n (oVerbose, "verbose", N_("verbose")),
177   ARGPARSE_s_n (oQuiet,	"quiet", N_("be somewhat more quiet")),
178   ARGPARSE_s_n (oArmor, "armor", N_("create ascii armored output")),
179   ARGPARSE_s_s (oSAS, "sas", N_("|SAS|the SAS as shown by the peer")),
180   ARGPARSE_s_s (oDebug, "debug", "@"),
181   ARGPARSE_s_s (oOutput, "output", N_("|FILE|write the request to FILE")),
182   ARGPARSE_s_i (oStatusFD, "status-fd", N_("|FD|write status info to this FD")),
183 
184   ARGPARSE_s_s (oHomedir, "homedir", "@"),
185 
186   ARGPARSE_end ()
187 };
188 
189 
190 /* We keep all global options in the structure OPT.  */
191 static struct
192 {
193   int verbose;
194   unsigned int debug;
195   int quiet;
196   int armor;
197   const char *output;
198   estream_t statusfp;
199   unsigned int ttl;
200   const char *sas;
201 } opt;
202 
203 
204 /* Debug values and macros.  */
205 #define DBG_MESSAGE_VALUE     2 /* Debug the messages.  */
206 #define DBG_CRYPTO_VALUE      4	/* Debug low level crypto.  */
207 #define DBG_MEMORY_VALUE     32	/* Debug memory allocation stuff.  */
208 
209 #define DBG_MESSAGE  (opt.debug & DBG_MESSAGE_VALUE)
210 #define DBG_CRYPTO   (opt.debug & DBG_CRYPTO_VALUE)
211 
212 
213 /* The list of supported debug flags.  */
214 static struct debug_flags_s debug_flags [] =
215   {
216     { DBG_MESSAGE_VALUE, "message"  },
217     { DBG_CRYPTO_VALUE , "crypto"  },
218     { DBG_MEMORY_VALUE , "memory"  },
219     { 0, NULL }
220   };
221 
222 
223 /* The directory name below the cache dir to store paring states.  */
224 #define PAIRING_STATE_DIR  "state"
225 
226 /* Message types.  */
227 #define MSG_TYPE_COMMIT  1
228 #define MSG_TYPE_DHPART1 2
229 #define MSG_TYPE_DHPART2 3
230 #define MSG_TYPE_CONFIRM 4
231 
232 
233 /* Realm values.  */
234 #define REALM_STANDARD  1
235 
236 
237 
238 
239 /* Local prototypes.  */
240 static void wrong_args (const char *text) GPGRT_ATTR_NORETURN;
241 static void xnvc_set_printf (nvc_t nvc, const char *name, const char *format,
242                              ...) GPGRT_ATTR_PRINTF(3,4);
243 static void *hash_data (void *result, size_t resultsize,
244                         ...) GPGRT_ATTR_SENTINEL(0);
245 static void *hmac_data (void *result, size_t resultsize,
246                         const unsigned char *key, size_t keylen,
247                         ...) GPGRT_ATTR_SENTINEL(0);
248 
249 
250 static gpg_error_t command_initiate (void);
251 static gpg_error_t command_respond (void);
252 static gpg_error_t command_cleanup (void);
253 static gpg_error_t command_get (const char *sessionidstr);
254 
255 
256 
257 
258 /* Print usage information and provide strings for help. */
259 static const char *
my_strusage(int level)260 my_strusage( int level )
261 {
262   const char *p;
263 
264   switch (level)
265     {
266     case 9:  p = "LGPL-2.1-or-later"; break;
267     case 11: p = "gpg-pair-tool"; break;
268     case 12: p = "@GNUPG@"; break;
269     case 13: p = VERSION; break;
270     case 14: p = GNUPG_DEF_COPYRIGHT_LINE; break;
271     case 17: p = PRINTABLE_OS_NAME; break;
272     case 19: p = _("Please report bugs to <@EMAIL@>.\n"); break;
273 
274     case 1:
275     case 40:
276       p = ("Usage: gpg-pair-tool [command] [options] [args] (-h for help)");
277       break;
278     case 41:
279       p = ("Syntax: gpg-pair-tool [command] [options] [args]\n"
280            "Client to run the pairing protocol\n");
281       break;
282 
283     default: p = NULL; break;
284     }
285   return p;
286 }
287 
288 
289 static void
wrong_args(const char * text)290 wrong_args (const char *text)
291 {
292   es_fprintf (es_stderr, _("usage: %s [options] %s\n"),
293               gpgrt_strusage (11), text);
294   exit (2);
295 }
296 
297 
298 /* Set the status FD.  */
299 static void
set_status_fd(int fd)300 set_status_fd (int fd)
301 {
302   static int last_fd = -1;
303 
304   if (fd != -1 && last_fd == fd)
305     return;
306 
307   if (opt.statusfp && opt.statusfp != es_stdout && opt.statusfp != es_stderr)
308     es_fclose (opt.statusfp);
309   opt.statusfp = NULL;
310   if (fd == -1)
311     return;
312 
313   if (fd == 1)
314     opt.statusfp = es_stdout;
315   else if (fd == 2)
316     opt.statusfp = es_stderr;
317   else
318     opt.statusfp = es_fdopen (fd, "w");
319   if (!opt.statusfp)
320     {
321       log_fatal ("can't open fd %d for status output: %s\n",
322                  fd, gpg_strerror (gpg_error_from_syserror ()));
323     }
324   last_fd = fd;
325 }
326 
327 
328 /* Write a status line with code NO followed by the output of the
329  * printf style FORMAT.  The caller needs to make sure that LFs and
330  * CRs are not printed.  */
331 static void
write_status(int no,const char * format,...)332 write_status (int no, const char *format, ...)
333 {
334   va_list arg_ptr;
335 
336   if (!opt.statusfp)
337     return;  /* Not enabled.  */
338 
339   es_fputs ("[GNUPG:] ", opt.statusfp);
340   es_fputs (get_status_string (no), opt.statusfp);
341   if (format)
342     {
343       es_putc (' ', opt.statusfp);
344       va_start (arg_ptr, format);
345       es_vfprintf (opt.statusfp, format, arg_ptr);
346       va_end (arg_ptr);
347     }
348   es_putc ('\n', opt.statusfp);
349 }
350 
351 
352 
353 /* gpg-pair-tool main. */
354 int
main(int argc,char ** argv)355 main (int argc, char **argv)
356 {
357   gpg_error_t err;
358   gpgrt_argparse_t pargs = { &argc, &argv };
359   enum cmd_and_opt_values cmd = 0;
360 
361   opt.ttl = 8*3600; /* Default to 8 hours.  */
362 
363   gnupg_reopen_std ("gpg-pair-tool");
364   gpgrt_set_strusage (my_strusage);
365   log_set_prefix ("gpg-pair-tool", GPGRT_LOG_WITH_PREFIX);
366 
367   /* Make sure that our subsystems are ready.  */
368   i18n_init();
369   init_common_subsystems (&argc, &argv);
370 
371   /* Parse the command line. */
372   while (gpgrt_argparse (NULL, &pargs, opts))
373     {
374       switch (pargs.r_opt)
375         {
376 	case oQuiet:     opt.quiet = 1; break;
377         case oVerbose:   opt.verbose++; break;
378         case oArmor:     opt.armor = 1; break;
379 
380         case oDebug:
381           if (parse_debug_flag (pargs.r.ret_str, &opt.debug, debug_flags))
382             {
383               pargs.r_opt = ARGPARSE_INVALID_ARG;
384               pargs.err   = ARGPARSE_PRINT_ERROR;
385             }
386           break;
387 
388         case oOutput:
389           opt.output = pargs.r.ret_str;
390           break;
391 
392         case oStatusFD:
393           set_status_fd (translate_sys2libc_fd_int (pargs.r.ret_int, 1));
394           break;
395 
396         case oHomedir:
397           gnupg_set_homedir (pargs.r.ret_str);
398           break;
399 
400         case oSAS:
401           opt.sas = pargs.r.ret_str;
402           break;
403 
404 	case aInitiate:
405 	case aRespond:
406 	case aGet:
407 	case aCleanup:
408           if (cmd && cmd != pargs.r_opt)
409             log_error (_("conflicting commands\n"));
410           else
411             cmd = pargs.r_opt;
412           break;
413 
414         default: pargs.err = ARGPARSE_PRINT_WARNING; break;
415 	}
416     }
417   gpgrt_argparse (NULL, &pargs, NULL);  /* Release internal state.  */
418 
419   /* Print a warning if an argument looks like an option.  */
420   if (!opt.quiet && !(pargs.flags & ARGPARSE_FLAG_STOP_SEEN))
421     {
422       int i;
423 
424       for (i=0; i < argc; i++)
425         if (argv[i][0] == '-' && argv[i][1] == '-')
426           log_info (("NOTE: '%s' is not considered an option\n"), argv[i]);
427     }
428   gpgrt_argparse (NULL, &pargs, NULL);  /* Free internal memory.  */
429 
430   if (opt.sas)
431     {
432       if (strlen (opt.sas) != 11
433           || !digitp (opt.sas+0) || !digitp (opt.sas+1) || !digitp (opt.sas+2)
434           || opt.sas[3] != '-'
435           || !digitp (opt.sas+4) || !digitp (opt.sas+5) || !digitp (opt.sas+6)
436           || opt.sas[7] != '-'
437           || !digitp (opt.sas+8) || !digitp (opt.sas+9) || !digitp (opt.sas+10))
438         log_error ("invalid formatted SAS\n");
439     }
440 
441   /* Stop if any error, inclduing ARGPARSE_PRINT_WARNING, occurred.  */
442   if (log_get_errorcount (0))
443     exit (2);
444 
445   if (DBG_CRYPTO)
446     gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1|2);
447 
448 
449   /* Now run the requested command.  */
450   switch (cmd)
451     {
452     case aInitiate:
453       if (argc)
454         wrong_args ("--initiate");
455       err = command_initiate ();
456       break;
457 
458     case aRespond:
459       if (argc)
460         wrong_args ("--respond");
461       err = command_respond ();
462       break;
463 
464     case aGet:
465       if (argc > 1)
466         wrong_args ("--respond [sessionid]");
467       err = command_get (argc? *argv:NULL);
468       break;
469 
470     case aCleanup:
471       if (argc)
472         wrong_args ("--cleanup");
473       err = command_cleanup ();
474       break;
475 
476     default:
477       gpgrt_usage (1);
478       err = 0;
479       break;
480     }
481 
482   if (err)
483     write_status (STATUS_FAILURE, "- %u", err);
484   else if (log_get_errorcount (0))
485     write_status (STATUS_FAILURE, "- %u", GPG_ERR_GENERAL);
486   else
487     write_status (STATUS_SUCCESS, NULL);
488   return log_get_errorcount (0)? 1:0;
489 }
490 
491 
492 
493 /* Wrapper around nvc_new which terminates in the error case.  */
494 static nvc_t
xnvc_new(void)495 xnvc_new (void)
496 {
497   nvc_t c = nvc_new ();
498   if (!c)
499     log_fatal ("error creating NVC object: %s\n",
500                gpg_strerror (gpg_error_from_syserror ()));
501   return c;
502 }
503 
504 /* Wrapper around nvc_set which terminates in the error case.  */
505 static void
xnvc_set(nvc_t nvc,const char * name,const char * value)506 xnvc_set (nvc_t nvc, const char *name, const char *value)
507 {
508   gpg_error_t err = nvc_set (nvc, name, value);
509   if (err)
510     log_fatal ("error updating NVC object: %s\n", gpg_strerror (err));
511 }
512 
513 /* Call vnc_set with (BUFFER, BUFLEN) converted to a hex string as
514  * value.  Terminates in the error case.  */
515 static void
xnvc_set_hex(nvc_t nvc,const char * name,const void * buffer,size_t buflen)516 xnvc_set_hex (nvc_t nvc, const char *name, const void *buffer, size_t buflen)
517 {
518   char *hex;
519 
520   hex = bin2hex (buffer, buflen, NULL);
521   if (!hex)
522     xoutofcore ();
523   strlwr (hex);
524   xnvc_set (nvc, name, hex);
525   xfree (hex);
526 }
527 
528 /* Call nvc_set with a value created from the string generated using
529  * the printf style FORMAT.  Terminates in the error case.  */
530 static void
xnvc_set_printf(nvc_t nvc,const char * name,const char * format,...)531 xnvc_set_printf (nvc_t nvc, const char *name, const char *format, ...)
532 {
533   va_list arg_ptr;
534   char *buffer;
535 
536   va_start (arg_ptr, format);
537   if (gpgrt_vasprintf (&buffer, format, arg_ptr) < 0)
538     log_fatal ("estream_asprintf failed: %s\n",
539                gpg_strerror (gpg_error_from_syserror ()));
540   va_end (arg_ptr);
541   xnvc_set (nvc, name, buffer);
542   xfree (buffer);
543 }
544 
545 
546 /* Return the string for the first entry in NVC with NAME.  If NAME is
547  * missing, an empty string is returned.  The returned string is a
548  * pointer into NVC.  */
549 static const char *
xnvc_get_string(nvc_t nvc,const char * name)550 xnvc_get_string (nvc_t nvc, const char *name)
551 {
552   nve_t item;
553 
554   if (!nvc)
555     return "";
556   item = nvc_lookup (nvc, name);
557   if (!item)
558     return "";
559   return nve_value (item);
560 }
561 
562 
563 
564 /* Return a string for MSGTYPE.  */
565 const char *
msgtypestr(int msgtype)566 msgtypestr (int msgtype)
567 {
568   switch (msgtype)
569     {
570     case MSG_TYPE_COMMIT:  return "Commit";
571     case MSG_TYPE_DHPART1: return "DHPart1";
572     case MSG_TYPE_DHPART2: return "DHPart2";
573     case MSG_TYPE_CONFIRM: return "Confirm";
574     }
575   return "?";
576 }
577 
578 
579 /* Private to {get,set}_session_id().  */
580 static struct {
581   int initialized;
582   unsigned char sessid[8];
583 } session_id;
584 
585 
586 /* Return the 8 octet session.  */
587 static unsigned char *
get_session_id(void)588 get_session_id (void)
589 {
590   if (!session_id.initialized)
591     {
592       session_id.initialized = 1;
593       gcry_create_nonce (session_id.sessid, sizeof session_id.sessid);
594     }
595 
596   return session_id.sessid;
597 }
598 
599 static void
set_session_id(const void * sessid,size_t len)600 set_session_id (const void *sessid, size_t len)
601 {
602   log_assert (!session_id.initialized);
603   if (len > sizeof session_id.sessid)
604     len = sizeof session_id.sessid;
605   memcpy (session_id.sessid, sessid, len);
606   if (len < sizeof session_id.sessid)
607     memset (session_id.sessid+len, 0, sizeof session_id.sessid - len);
608   session_id.initialized = 1;
609 }
610 
611 /* Return a string with the hexified session id.  */
612 static const char *
get_session_id_hex(void)613 get_session_id_hex (void)
614 {
615   static char hexstr[16+1];
616 
617   bin2hex (get_session_id (), 8, hexstr);
618   strlwr (hexstr);
619   return hexstr;
620 }
621 
622 
623 /* Return a fixed string with the directory used to store the state of
624  * pairings.  On error a diagnostic is printed but the file name is
625  * returned anyway.  It is expected that the expected failure of the
626  * following open is responsible for error handling.  */
627 static const char *
get_pairing_statedir(void)628 get_pairing_statedir (void)
629 {
630   static char *fname;
631   gpg_error_t err = 0;
632   char *tmpstr;
633   struct stat statbuf;
634 
635   if (fname)
636     return fname;
637 
638   fname = make_filename (gnupg_homedir (), GNUPG_CACHE_DIR, NULL);
639   if (gnupg_stat (fname, &statbuf) && errno == ENOENT)
640     {
641       if (gnupg_mkdir (fname, "-rwx"))
642         {
643           err = gpg_error_from_syserror ();
644           log_error (_("can't create directory '%s': %s\n"),
645                      fname, gpg_strerror (err) );
646         }
647       else if (!opt.quiet)
648         log_info (_("directory '%s' created\n"), fname);
649     }
650 
651   tmpstr = make_filename (fname, PAIRING_STATE_DIR, NULL);
652   xfree (fname);
653   fname = tmpstr;
654   if (gnupg_stat (fname, &statbuf) && errno == ENOENT)
655     {
656       if (gnupg_mkdir (fname, "-rwx"))
657         {
658           if (!err)
659             {
660               err = gpg_error_from_syserror ();
661               log_error (_("can't create directory '%s': %s\n"),
662                          fname, gpg_strerror (err) );
663             }
664         }
665       else if (!opt.quiet)
666         log_info (_("directory '%s' created\n"), fname);
667     }
668 
669   return fname;
670 }
671 
672 
673 /* Open the pairing state file.  SESSIONID is a 8 byte buffer with the
674  * session-id.  If CREATE_FLAG is set the file is created and will
675  * always return a valid stream.  If CREATE_FLAG is not set the file
676  * is opened for reading and writing.  If the file does not exist NULL
677  * is return; in all other error cases the process is terminated.  If
678  * R_FNAME is not NULL the name of the file is stored there and the
679  * caller needs to free it.  */
680 static estream_t
open_pairing_state(const unsigned char * sessionid,int create_flag,char ** r_fname)681 open_pairing_state (const unsigned char *sessionid, int create_flag,
682                     char **r_fname)
683 {
684   gpg_error_t err;
685   char *fname, *tmpstr;
686   estream_t fp;
687 
688   /* The filename is the session id with a "pa1" suffix.  Note that
689    * the state dir may eventually be used for other purposes as well
690    * and thus the suffix identifies that the file belongs to this
691    * tool.  We use lowercase file names for no real reason.  */
692   tmpstr = bin2hex (sessionid, 8, NULL);
693   if (!tmpstr)
694     xoutofcore ();
695   strlwr (tmpstr);
696   fname = xstrconcat (tmpstr, ".pa1", NULL);
697   xfree (tmpstr);
698   tmpstr = make_filename (get_pairing_statedir (), fname, NULL);
699   xfree (fname);
700   fname = tmpstr;
701 
702   fp = es_fopen (fname, create_flag? "wbx,mode=-rw": "rb+,mode=-rw");
703   if (!fp)
704     {
705       err = gpg_error_from_syserror ();
706       if (create_flag)
707         {
708           /* We should always be able to create a file.  Also we use a
709            * 64 bit session id, it is theoretically possible that such
710            * a session already exists.  However, that is rare enough
711            * and thus the fatal error message should still be  okay.  */
712           log_fatal ("can't create '%s': %s\n", fname, gpg_strerror (err));
713         }
714       else if (gpg_err_code (err) == GPG_ERR_ENOENT)
715         {
716           /* That is an expected error; return NULL.  */
717         }
718       else
719         {
720           log_fatal ("can't open '%s': %s\n", fname, gpg_strerror (err));
721         }
722     }
723 
724   if (r_fname)
725     *r_fname = fname;
726   else
727     xfree (fname);
728 
729   return fp;
730 }
731 
732 
733 /* Write the state to a possible new state file.  */
734 static void
write_state(nvc_t state,int create_flag)735 write_state (nvc_t state, int create_flag)
736 {
737   gpg_error_t err;
738   char *fname = NULL;
739   estream_t fp;
740 
741   fp = open_pairing_state (get_session_id (), create_flag, &fname);
742   log_assert (fp);
743 
744   err = nvc_write (state, fp);
745   if (err)
746     {
747       es_fclose  (fp);
748       gnupg_remove (fname);
749       log_fatal ("error writing '%s': %s\n", fname, gpg_strerror (err));
750     }
751 
752   /* If we did not create the file, we need to truncate the file.  */
753   if (!create_flag && ftruncate (es_fileno (fp), es_ftello (fp)))
754     {
755       err = gpg_error_from_syserror ();
756       log_fatal ("error truncating '%s': %s\n", fname, gpg_strerror (err));
757     }
758   if (es_ferror (fp) || es_fclose (fp))
759     {
760       err = gpg_error_from_syserror ();
761       es_fclose  (fp);
762       gnupg_remove (fname);
763       log_fatal ("error writing '%s': %s\n", fname, gpg_strerror (err));
764     }
765 }
766 
767 
768 /* Read the state into a newly allocated state object and store that
769  * at R_STATE. If no state is available GPG_ERR_NOT_FOUND is returned
770  * and as with all errors NULL is tored at R_STATE.  SESSIONID is an
771  * input with the 8 session id.  */
772 static gpg_error_t
read_state(nvc_t * r_state)773 read_state (nvc_t *r_state)
774 {
775   gpg_error_t err;
776   char *fname = NULL;
777   estream_t fp;
778   nvc_t state = NULL;
779   nve_t item;
780   const char *value;
781   unsigned long expire;
782 
783   *r_state = NULL;
784 
785   fp = open_pairing_state (get_session_id (), 0, &fname);
786   if (!fp)
787     return gpg_error (GPG_ERR_NOT_FOUND);
788 
789   err = nvc_parse (&state, NULL, fp);
790   if (err)
791     {
792       log_info ("failed to parse state file '%s': %s\n",
793                 fname, gpg_strerror (err));
794       goto leave;
795     }
796 
797   /* Check whether the state already expired.  */
798   item = nvc_lookup (state, "Expires:");
799   if (!item)
800     {
801       log_info ("invalid state file '%s': %s\n",
802                 fname, "field 'expire' not found");
803       goto leave;
804     }
805   value = nve_value (item);
806   if (!value || !(expire = strtoul (value, NULL, 10)))
807     {
808       log_info ("invalid state file '%s': %s\n",
809                 fname, "field 'expire' has an invalid value");
810       goto leave;
811     }
812   if (expire <= gnupg_get_time ())
813     {
814       es_fclose (fp);
815       fp = NULL;
816       if (gnupg_remove (fname))
817         {
818           err = gpg_error_from_syserror ();
819           log_info ("failed to delete state file '%s': %s\n",
820                     fname, gpg_strerror (err));
821         }
822       else if (opt.verbose)
823         log_info ("state file '%s' deleted\n", fname);
824       err = gpg_error (GPG_ERR_NOT_FOUND);
825       goto leave;
826     }
827 
828   *r_state = state;
829   state = NULL;
830 
831  leave:
832   nvc_release (state);
833   es_fclose (fp);
834   return err;
835 }
836 
837 
838 /* Send (MSG,MSGLEN) to the output device.  */
839 static void
send_message(const unsigned char * msg,size_t msglen)840 send_message (const unsigned char *msg, size_t msglen)
841 {
842   gpg_error_t err;
843 
844   if (opt.verbose)
845     log_info ("session %s: sending %s message\n",
846               get_session_id_hex (), msgtypestr (msg[7]));
847 
848   if (DBG_MESSAGE)
849     log_printhex (msg, msglen, "send msg(%s):", msgtypestr (msg[7]));
850 
851   /* FIXME: For now only stdout.  */
852   if (opt.armor)
853     {
854       gpgrt_b64state_t state;
855 
856       state = gpgrt_b64enc_start (es_stdout, "");
857       if (!state)
858         log_fatal ("error setting up base64 encoder: %s\n",
859                    gpg_strerror (gpg_error_from_syserror ()));
860       err = gpgrt_b64enc_write (state, msg, msglen);
861       if (!err)
862         err = gpgrt_b64enc_finish (state);
863       if (err)
864         log_fatal ("error writing base64 to stdout: %s\n", gpg_strerror (err));
865     }
866   else
867     {
868       if (es_fwrite (msg, msglen, 1, es_stdout) != 1)
869         log_fatal ("error writing to stdout: %s\n",
870                    gpg_strerror (gpg_error_from_syserror ()));
871     }
872   es_fputc ('\n', es_stdout);
873 }
874 
875 
876 /* Read a message from stdin and store it at the address (R_MSG,
877  * R_MSGLEN).  This function detects armoring and removes it.  On
878  * error NULL is stored at R_MSG, a diagnostic printed and an error
879  * code returned.  The returned message has a proper message type and
880  * an appropriate length.  The message type is stored at R_MSGTYPE and
881  * if a state is available it is stored at R_STATE.  */
882 static gpg_error_t
read_message(unsigned char ** r_msg,size_t * r_msglen,int * r_msgtype,nvc_t * r_state)883 read_message (unsigned char **r_msg, size_t *r_msglen, int *r_msgtype,
884               nvc_t *r_state)
885 {
886   gpg_error_t err;
887   unsigned char msg[128];  /* max msg size is 80 but 107 with base64.  */
888   size_t msglen;
889   size_t reqlen;
890 
891   *r_msg = NULL;
892   *r_state = NULL;
893 
894   es_setvbuf (es_stdin, NULL, _IONBF, 0);
895   es_set_binary (es_stdin);
896 
897   if (es_read (es_stdin, msg, sizeof msg, &msglen))
898     {
899       err = gpg_error_from_syserror ();
900       log_error ("error reading from message: %s\n", gpg_strerror (err));
901       return err;
902     }
903 
904   if (msglen > 4 && !memcmp (msg, "R1BH", 4))
905     {
906       /* This is base64 of the first 3 bytes.  */
907       gpgrt_b64state_t state = gpgrt_b64dec_start (NULL);
908       if (!state)
909         log_fatal ("error setting up base64 decoder: %s\n",
910                    gpg_strerror (gpg_error_from_syserror ()));
911       err = gpgrt_b64dec_proc (state, msg, msglen, &msglen);
912       gpgrt_b64dec_finish (state);
913       if (err)
914         {
915           log_error ("error decoding message: %s\n", gpg_strerror (err));
916           return err;
917         }
918     }
919 
920   if (msglen < 16 || memcmp (msg, "GPG-pa1", 7))
921     {
922       log_error ("error parsing message: %s\n",
923                  msglen? "invalid header":"empty message");
924       return gpg_error (GPG_ERR_INV_RESPONSE);
925     }
926   switch (msg[7])
927     {
928     case MSG_TYPE_COMMIT:  reqlen = 56; break;
929     case MSG_TYPE_DHPART1: reqlen = 80; break;
930     case MSG_TYPE_DHPART2: reqlen = 80; break;
931     case MSG_TYPE_CONFIRM: reqlen = 48; break;
932 
933     default:
934       log_error ("error parsing message: %s\n", "invalid message type");
935       return gpg_error (GPG_ERR_INV_RESPONSE);
936     }
937   if (msglen < reqlen)
938     {
939       log_error ("error parsing message: %s\n", "message too short");
940       return gpg_error (GPG_ERR_INV_RESPONSE);
941     }
942 
943   if (DBG_MESSAGE)
944     log_printhex (msg, msglen, "recv msg(%s):", msgtypestr (msg[7]));
945 
946   /* Note that we ignore any garbage at the end of a message.  */
947   msglen = reqlen;
948 
949   set_session_id (msg+8, 8);
950 
951   if (opt.verbose)
952     log_info ("session %s: received %s message\n",
953               get_session_id_hex (), msgtypestr (msg[7]));
954 
955   /* Read the state.  */
956   err = read_state (r_state);
957   if (err && gpg_err_code (err) != GPG_ERR_NOT_FOUND)
958     return err;
959 
960   *r_msg = xmalloc (msglen);
961   memcpy (*r_msg, msg, msglen);
962   *r_msglen = msglen;
963   *r_msgtype = msg[7];
964   return err;
965 }
966 
967 
968 /* Display the Short Authentication String (SAS). If WAIT is true the
969  * function waits until the user has entered the SAS as seen at the
970  * peer.
971  *
972  * To construct the SAS we take the 4 most significant octets of HASH,
973  * interpret them as a 32 bit big endian unsigned integer, divide that
974  * integer by 10^9 and take the remainder.  The remainder is displayed
975  * as 3 groups of 3 decimal digits delimited by a hyphens.  This gives
976  * a search space of close to 2^30 and is still easy to compare.
977  */
978 static gpg_error_t
display_sas(const unsigned char * hash,size_t hashlen,int wait)979 display_sas (const unsigned char *hash, size_t hashlen, int wait)
980 {
981   gpg_error_t err = 0;
982   unsigned long sas = 0;
983   char sasbuf[12];
984 
985   log_assert (hashlen >= 4);
986 
987   sas |= (unsigned long)hash[20] << 24;
988   sas |= (unsigned long)hash[21] << 16;
989   sas |= (unsigned long)hash[22] <<  8;
990   sas |= (unsigned long)hash[23];
991   sas %= 1000000000ul;
992   snprintf (sasbuf, sizeof sasbuf, "%09lu", sas);
993   memmove (sasbuf+8, sasbuf+6, 3);
994   memmove (sasbuf+4, sasbuf+3, 3);
995   sasbuf[3] = sasbuf[7] = '-';
996   sasbuf[11] = 0;
997 
998   if (wait)
999     log_info ("Please check the SAS:\n");
1000   else
1001     log_info ("Please note the SAS:\n");
1002   log_info ("\n");
1003   log_info ("   %s\n", sasbuf);
1004   log_info ("\n");
1005 
1006   if (wait)
1007     {
1008       if (!opt.sas || strcmp (sasbuf, opt.sas))
1009         err = gpg_error (GPG_ERR_NOT_CONFIRMED);
1010       else
1011         log_info ("SAS confirmed\n");
1012     }
1013 
1014   if (err)
1015     log_info ("checking SAS failed: %s\n", gpg_strerror (err));
1016   return err;
1017 }
1018 
1019 
1020 
1021 static gpg_error_t
create_dh_keypair(unsigned char * dh_secret,size_t dh_secret_len,unsigned char * dh_public,size_t dh_public_len)1022 create_dh_keypair (unsigned char *dh_secret, size_t dh_secret_len,
1023                    unsigned char *dh_public, size_t dh_public_len)
1024 {
1025   gpg_error_t err;
1026   unsigned char *p;
1027 
1028   /* We need a temporary buffer for the public key.  Check the length
1029    * for the later memcpy.  */
1030   if (dh_public_len < 32 || dh_secret_len < 32)
1031     return gpg_error (GPG_ERR_BUFFER_TOO_SHORT);
1032 
1033   if (gcry_ecc_get_algo_keylen (GCRY_ECC_CURVE25519) > dh_public_len)
1034     return gpg_error (GPG_ERR_BUFFER_TOO_SHORT);
1035 
1036   p = gcry_random_bytes (32, GCRY_VERY_STRONG_RANDOM);
1037   if (!p)
1038     return gpg_error_from_syserror ();
1039 
1040   memcpy (dh_secret, p, 32);
1041   xfree (p);
1042 
1043   err = gcry_ecc_mul_point (GCRY_ECC_CURVE25519, dh_public, dh_secret, NULL);
1044   if (err)
1045     return err;
1046 
1047   if (DBG_CRYPTO)
1048     {
1049       log_printhex (dh_secret, 32, "DH secret:");
1050       log_printhex (dh_public, 32, "DH public:");
1051     }
1052 
1053   return 0;
1054 }
1055 
1056 
1057 /* SHA256 the data given as varargs tuples of (const void*, size_t)
1058  * and store the result in RESULT.  The end of the list is indicated
1059  * by a NULL element in a tuple.  RESULTLEN gives the length of the
1060  * RESULT buffer which must be at least 32.  Note that the second item
1061  * of the tuple is the length and it is a size_t.  */
1062 static void *
hash_data(void * result,size_t resultsize,...)1063 hash_data (void *result, size_t resultsize, ...)
1064 {
1065   va_list arg_ptr;
1066   gpg_error_t err;
1067   gcry_md_hd_t hd;
1068   const void *data;
1069   size_t datalen;
1070 
1071   log_assert (resultsize >= 32);
1072 
1073   err = gcry_md_open (&hd, GCRY_MD_SHA256, 0);
1074   if (err)
1075     log_fatal ("error creating a Hash handle: %s\n", gpg_strerror (err));
1076   /* log_printhex ("", 0, "Hash-256:"); */
1077 
1078   va_start (arg_ptr, resultsize);
1079   while ((data = va_arg (arg_ptr, const void *)))
1080     {
1081       datalen = va_arg (arg_ptr, size_t);
1082       /* log_printhex (data, datalen, "    data:"); */
1083       gcry_md_write (hd, data, datalen);
1084     }
1085   va_end (arg_ptr);
1086 
1087   memcpy (result, gcry_md_read (hd, 0), 32);
1088   /* log_printhex (result, 32, "  result:"); */
1089 
1090   gcry_md_close (hd);
1091 
1092   return result;
1093 }
1094 
1095 
1096 /* HMAC-SHA256 the data given as varargs tuples of (const void*,
1097  * size_t) using (KEYLEN,KEY) and store the result in RESULT.  The end
1098  * of the list is indicated by a NULL element in a tuple.  RESULTLEN
1099  * gives the length of the RESULT buffer which must be at least 32.
1100  * Note that the second item of the tuple is the length and it is a
1101  * size_t.  */
1102 static void *
hmac_data(void * result,size_t resultsize,const unsigned char * key,size_t keylen,...)1103 hmac_data (void *result, size_t resultsize,
1104            const unsigned char *key, size_t keylen, ...)
1105 {
1106   va_list arg_ptr;
1107   gpg_error_t err;
1108   gcry_mac_hd_t hd;
1109   const void *data;
1110   size_t datalen;
1111 
1112   log_assert (resultsize >= 32);
1113 
1114   err = gcry_mac_open (&hd, GCRY_MAC_HMAC_SHA256, 0, NULL);
1115   if (err)
1116     log_fatal ("error creating a MAC handle: %s\n", gpg_strerror (err));
1117   err = gcry_mac_setkey (hd, key, keylen);
1118   if (err)
1119     log_fatal ("error setting the MAC key: %s\n", gpg_strerror (err));
1120   /* log_printhex (key, keylen, "HMAC-key:"); */
1121 
1122   va_start (arg_ptr, keylen);
1123   while ((data = va_arg (arg_ptr, const void *)))
1124     {
1125       datalen = va_arg (arg_ptr, size_t);
1126       /* log_printhex (data, datalen, "    data:"); */
1127       err = gcry_mac_write (hd, data, datalen);
1128       if (err)
1129         log_fatal ("error writing to the MAC handle: %s\n", gpg_strerror (err));
1130     }
1131   va_end (arg_ptr);
1132 
1133   err = gcry_mac_read (hd, result, &resultsize);
1134   if (err || resultsize != 32)
1135     log_fatal ("error reading MAC value: %s\n", gpg_strerror (err));
1136   /* log_printhex (result, resultsize, "  result:"); */
1137 
1138   gcry_mac_close (hd);
1139 
1140   return result;
1141 }
1142 
1143 
1144 /* Key derivation function:
1145  *
1146  * FIXME(doc)
1147  */
1148 static void
kdf(unsigned char * result,size_t resultlen,const unsigned char * master,size_t masterlen,const unsigned char * sessionid,size_t sessionidlen,const unsigned char * expire,size_t expirelen,const char * label)1149 kdf (unsigned char *result, size_t resultlen,
1150      const unsigned char *master, size_t masterlen,
1151      const unsigned char *sessionid, size_t sessionidlen,
1152      const unsigned char *expire, size_t expirelen,
1153      const char *label)
1154 {
1155   log_assert (masterlen == 32 && sessionidlen == 8 && expirelen == 5);
1156   log_assert (*label);
1157   log_assert (resultlen == 32);
1158 
1159   hmac_data (result, resultlen, master, masterlen,
1160              "\x00\x00\x00\x01", (size_t)4,      /* Counter=1*/
1161              label, strlen (label) + 1,          /* Label, 0x00 */
1162              sessionid, sessionidlen,            /* Context */
1163              expire, expirelen,                  /* Context */
1164              "\x00\x00\x01\x00", (size_t)4,      /* L=256 */
1165              NULL);
1166 }
1167 
1168 
1169 static gpg_error_t
compute_master_secret(unsigned char * master,size_t masterlen,const unsigned char * sk_a,size_t sk_a_len,const unsigned char * pk_b,size_t pk_b_len)1170 compute_master_secret (unsigned char *master, size_t masterlen,
1171                        const unsigned char *sk_a, size_t sk_a_len,
1172                        const unsigned char *pk_b, size_t pk_b_len)
1173 {
1174   gpg_error_t err;
1175 
1176   log_assert (masterlen == 32);
1177   log_assert (sk_a_len == 32);
1178   log_assert (pk_b_len == 32);
1179 
1180   err = gcry_ecc_mul_point (GCRY_ECC_CURVE25519, master, sk_a, pk_b);
1181   if (err)
1182     log_error ("error computing DH: %s\n", gpg_strerror (err));
1183 
1184   return err;
1185 }
1186 
1187 
1188 /* We are the Initiator: Create the commit message.  This function
1189  * sends the COMMIT message and writes STATE. */
1190 static gpg_error_t
make_msg_commit(nvc_t state)1191 make_msg_commit (nvc_t state)
1192 {
1193   gpg_error_t err;
1194   uint64_t now, expire;
1195   unsigned char secret[32];
1196   unsigned char public[32];
1197   unsigned char *newmsg;
1198   size_t newmsglen;
1199   unsigned char tmphash[32];
1200 
1201   err = create_dh_keypair (secret, sizeof secret, public, sizeof public );
1202   if (err)
1203     log_error ("creating DH keypair failed: %s\n", gpg_strerror (err));
1204 
1205   now = gnupg_get_time ();
1206   expire = now + opt.ttl;
1207 
1208   newmsglen = 7+1+8+1+2+5+32;
1209   newmsg = xmalloc (newmsglen);
1210   memcpy (newmsg+0, "GPG-pa1", 7);
1211   newmsg[7] = MSG_TYPE_COMMIT;
1212   memcpy (newmsg+8, get_session_id (), 8);
1213   newmsg[16] = REALM_STANDARD;
1214   newmsg[17] = 0;
1215   newmsg[18] = 0;
1216   newmsg[19] = expire >> 32;
1217   newmsg[20] = expire >> 24;
1218   newmsg[21] = expire >> 16;
1219   newmsg[22] = expire >> 8;
1220   newmsg[23] = expire;
1221   gcry_md_hash_buffer (GCRY_MD_SHA256, newmsg+24, public, 32);
1222 
1223   /* Create the state file.  */
1224   xnvc_set (state, "State:", "Commit-sent");
1225   xnvc_set_printf (state, "Created:", "%llu", (unsigned long long)now);
1226   xnvc_set_printf (state, "Expires:", "%llu", (unsigned long long)expire);
1227   xnvc_set_hex (state, "DH-PKi:", public, 32);
1228   xnvc_set_hex (state, "DH-SKi:", secret, 32);
1229   gcry_md_hash_buffer (GCRY_MD_SHA256, tmphash, newmsg, newmsglen);
1230   xnvc_set_hex (state, "Hash-Commit:", tmphash, 32);
1231 
1232   /* Write the state.  Note that we need to create it.  The state
1233    * updating should in theory be done atomically with send_message.
1234    * However, we can't assure that the message will actually be
1235    * delivered and thus it doesn't matter whether we have an already
1236    * update state when we later fail in send_message.  */
1237   write_state (state, 1);
1238 
1239   /* Write the message.  */
1240   send_message (newmsg, newmsglen);
1241 
1242    xfree (newmsg);
1243   return err;
1244 }
1245 
1246 
1247 /* We are the Responder: Process a commit message in (MSG,MSGLEN)
1248  * which has already been validated to have a correct header and
1249  * message type.  Sends the DHPart1 message and writes STATE.  */
1250 static gpg_error_t
proc_msg_commit(nvc_t state,const unsigned char * msg,size_t msglen)1251 proc_msg_commit (nvc_t state, const unsigned char *msg, size_t msglen)
1252 {
1253   gpg_error_t err;
1254   uint64_t now, expire;
1255   unsigned char tmphash[32];
1256   unsigned char secret[32];
1257   unsigned char public[32];
1258   unsigned char *newmsg = NULL;
1259   size_t newmsglen;
1260 
1261   log_assert (msglen >= 56);
1262   now = gnupg_get_time ();
1263 
1264   /* Check that the message has not expired.  */
1265   expire  = (uint64_t)msg[19] << 32;
1266   expire |= (uint64_t)msg[20] << 24;
1267   expire |= (uint64_t)msg[21] << 16;
1268   expire |= (uint64_t)msg[22] <<  8;
1269   expire |= (uint64_t)msg[23];
1270   if (expire < now)
1271     {
1272       log_error ("received %s message is too old\n",
1273                  msgtypestr (MSG_TYPE_COMMIT));
1274       err = gpg_error (GPG_ERR_TOO_OLD);
1275       goto leave;
1276     }
1277 
1278   /* Create the response.  */
1279   err = create_dh_keypair (secret, sizeof secret, public, sizeof public );
1280   if (err)
1281     {
1282       log_error ("creating DH keypair failed: %s\n", gpg_strerror (err));
1283       goto leave;
1284     }
1285 
1286   newmsglen = 7+1+8+32+32;
1287   newmsg = xmalloc (newmsglen);
1288   memcpy (newmsg+0, "GPG-pa1", 7);
1289   newmsg[7] = MSG_TYPE_DHPART1;
1290   memcpy (newmsg+8, msg + 8, 8);   /* SessionID.  */
1291   memcpy (newmsg+16, public, 32);  /* PKr */
1292   /* Hash(Hash(Commit) || DHPart1[0..47]) */
1293   gcry_md_hash_buffer (GCRY_MD_SHA256, tmphash, msg, msglen);
1294   hash_data (newmsg+48, 32,
1295              tmphash, sizeof tmphash,
1296              newmsg, (size_t)48,
1297              NULL);
1298 
1299   /* Update the state.  */
1300   xnvc_set (state, "State:", "DHPart1-sent");
1301   xnvc_set_printf (state, "Created:", "%llu", (unsigned long long)now);
1302   xnvc_set_printf (state, "Expires:", "%llu", (unsigned long long)expire);
1303   xnvc_set_hex (state, "Hash-PKi:", msg+24, 32);
1304   xnvc_set_hex (state, "DH-PKr:", public, 32);
1305   xnvc_set_hex (state, "DH-SKr:", secret, 32);
1306   gcry_md_hash_buffer (GCRY_MD_SHA256, tmphash, newmsg, newmsglen);
1307   xnvc_set_hex (state, "Hash-DHPart1:", tmphash, 32);
1308 
1309   /* Write the state.  Note that we need to create it. */
1310   write_state (state, 1);
1311 
1312   /* Write the message.  */
1313   send_message (newmsg, newmsglen);
1314 
1315  leave:
1316   xfree (newmsg);
1317   return err;
1318 }
1319 
1320 
1321 /* We are the Initiator: Process a DHPART1 message in (MSG,MSGLEN)
1322  * which has already been validated to have a correct header and
1323  * message type.  Sends the DHPart2 message and writes STATE.  */
1324 static gpg_error_t
proc_msg_dhpart1(nvc_t state,const unsigned char * msg,size_t msglen)1325 proc_msg_dhpart1 (nvc_t state, const unsigned char *msg, size_t msglen)
1326 {
1327   gpg_error_t err;
1328   unsigned char hash[32];
1329   unsigned char tmphash[32];
1330   unsigned char pki[32];
1331   unsigned char pkr[32];
1332   unsigned char ski[32];
1333   unsigned char master[32];
1334   uint64_t expire;
1335   unsigned char expirebuf[5];
1336   unsigned char hmacikey[32];
1337   unsigned char symxkey[32];
1338   unsigned char *newmsg = NULL;
1339   size_t newmsglen;
1340 
1341   log_assert (msglen >= 80);
1342 
1343   /* Check that the message includes the Hash(Commit). */
1344   if (hex2bin (xnvc_get_string (state, "Hash-Commit:"), hash, sizeof hash) < 0)
1345     {
1346       err = gpg_error (GPG_ERR_INV_VALUE);
1347       log_error ("no or garbled 'Hash-Commit' in our state file\n");
1348       goto leave;
1349     }
1350   hash_data (tmphash, 32,
1351              hash, sizeof hash,
1352              msg, (size_t)48,
1353              NULL);
1354   if (memcmp (msg+48, tmphash, 32))
1355     {
1356       err = gpg_error (GPG_ERR_BAD_DATA);
1357       log_error ("manipulation of received %s message detected: %s\n",
1358                  msgtypestr (MSG_TYPE_DHPART1), "Bad Hash");
1359       goto leave;
1360     }
1361   /* Check that the received PKr is different from our PKi and copy
1362    * PKr into PKR.  */
1363   if (hex2bin (xnvc_get_string (state, "DH-PKi:"), pki, sizeof pki) < 0)
1364     {
1365       err = gpg_error (GPG_ERR_INV_VALUE);
1366       log_error ("no or garbled 'DH-PKi' in our state file\n");
1367       goto leave;
1368     }
1369   if (!memcmp (msg+16, pki, 32))
1370     {
1371       /* This can only happen if the state file leaked to the
1372        * responder.  */
1373       err = gpg_error (GPG_ERR_BAD_DATA);
1374       log_error ("received our own public key PKi instead of PKr\n");
1375       goto leave;
1376     }
1377   memcpy (pkr, msg+16, 32);
1378 
1379   /* Put the expire value into a buffer.  */
1380   expire = string_to_u64 (xnvc_get_string (state, "Expires:"));
1381   if (!expire)
1382     {
1383       err = gpg_error (GPG_ERR_INV_VALUE);
1384       log_error ("no 'Expire' in our state file\n");
1385       goto leave;
1386     }
1387   expirebuf[0] = expire >> 32;
1388   expirebuf[1] = expire >> 24;
1389   expirebuf[2] = expire >> 16;
1390   expirebuf[3] = expire >> 8;
1391   expirebuf[4] = expire;
1392 
1393   /* Get our secret from the state.  */
1394   if (hex2bin (xnvc_get_string (state, "DH-SKi:"), ski, sizeof ski) < 0)
1395     {
1396       err = gpg_error (GPG_ERR_INV_VALUE);
1397       log_error ("no or garbled 'DH-SKi' in our state file\n");
1398       goto leave;
1399     }
1400 
1401   /* Compute the shared secrets.  */
1402   err = compute_master_secret (master, sizeof master,
1403                                ski, sizeof ski, pkr, sizeof pkr);
1404   if (err)
1405     {
1406       log_error ("creating DH keypair failed: %s\n", gpg_strerror (err));
1407       goto leave;
1408     }
1409 
1410   kdf (hmacikey, sizeof hmacikey,
1411        master, sizeof master, msg+8, 8, expirebuf, sizeof expirebuf,
1412        "GPG-pa1-HMACi-key");
1413   kdf (symxkey, sizeof symxkey,
1414        master, sizeof master, msg+8, 8, expirebuf, sizeof expirebuf,
1415        "GPG-pa1-SYMx-key");
1416 
1417 
1418   /* Create the response.  */
1419   newmsglen = 7+1+8+32+32;
1420   newmsg = xmalloc (newmsglen);
1421   memcpy (newmsg+0, "GPG-pa1", 7);
1422   newmsg[7] = MSG_TYPE_DHPART2;
1423   memcpy (newmsg+8, msg + 8, 8); /* SessionID.  */
1424   memcpy (newmsg+16, pki, 32);   /* PKi */
1425   /* MAC(HMACi-key, Hash(DHPART1) || DHPART2[0..47] || SYMx-key) */
1426   gcry_md_hash_buffer (GCRY_MD_SHA256, tmphash, msg, msglen);
1427   hmac_data (newmsg+48, 32, hmacikey, sizeof hmacikey,
1428              tmphash, sizeof tmphash,
1429              newmsg, (size_t)48,
1430              symxkey, sizeof symxkey,
1431              NULL);
1432 
1433   /* Update the state.  */
1434   xnvc_set (state, "State:", "DHPart2-sent");
1435   xnvc_set_hex (state, "DH-Master:", master, sizeof master);
1436   gcry_md_hash_buffer (GCRY_MD_SHA256, tmphash, newmsg, newmsglen);
1437   xnvc_set_hex (state, "Hash-DHPart2:", tmphash, 32);
1438 
1439   /* Write the state.  */
1440   write_state (state, 0);
1441 
1442   /* Write the message.  */
1443   send_message (newmsg, newmsglen);
1444 
1445  leave:
1446   xfree (newmsg);
1447   return err;
1448 }
1449 
1450 
1451 /* We are the Responder: Process a DHPART2 message in (MSG,MSGLEN)
1452  * which has already been validated to have a correct header and
1453  * message type.  Sends the CONFIRM message and writes STATE.  */
1454 static gpg_error_t
proc_msg_dhpart2(nvc_t state,const unsigned char * msg,size_t msglen)1455 proc_msg_dhpart2 (nvc_t state, const unsigned char *msg, size_t msglen)
1456 {
1457   gpg_error_t err;
1458   unsigned char hash[32];
1459   unsigned char tmphash[32];
1460   uint64_t expire;
1461   unsigned char expirebuf[5];
1462   unsigned char pki[32];
1463   unsigned char pkr[32];
1464   unsigned char skr[32];
1465   unsigned char master[32];
1466   unsigned char hmacikey[32];
1467   unsigned char hmacrkey[32];
1468   unsigned char symxkey[32];
1469   unsigned char sas[32];
1470   unsigned char *newmsg = NULL;
1471   size_t newmsglen;
1472 
1473   log_assert (msglen >= 80);
1474 
1475   /* Check that the PKi in the message matches the Hash(Pki) received
1476    * with the Commit message. */
1477   memcpy (pki, msg + 16, 32);
1478   gcry_md_hash_buffer (GCRY_MD_SHA256, hash, pki, 32);
1479   if (hex2bin (xnvc_get_string (state, "Hash-PKi:"),
1480                tmphash, sizeof tmphash) < 0)
1481     {
1482       err = gpg_error (GPG_ERR_INV_VALUE);
1483       log_error ("no or garbled 'Hash-PKi' in our state file\n");
1484       goto leave;
1485     }
1486   if (memcmp (hash, tmphash, 32))
1487     {
1488       err = gpg_error (GPG_ERR_BAD_DATA);
1489       log_error ("Initiator sent a different key in %s than announced in %s\n",
1490                  msgtypestr (MSG_TYPE_DHPART2),
1491                  msgtypestr (MSG_TYPE_COMMIT));
1492       goto leave;
1493     }
1494   /* Check that the received PKi is different from our PKr.  */
1495   if (hex2bin (xnvc_get_string (state, "DH-PKr:"), pkr, sizeof pkr) < 0)
1496     {
1497       err = gpg_error (GPG_ERR_INV_VALUE);
1498       log_error ("no or garbled 'DH-PKr' in our state file\n");
1499       goto leave;
1500     }
1501   if (!memcmp (pkr, pki, 32))
1502     {
1503       err = gpg_error (GPG_ERR_BAD_DATA);
1504       log_error ("Initiator sent our own PKr back\n");
1505       goto leave;
1506     }
1507 
1508   /* Put the expire value into a buffer.  */
1509   expire = string_to_u64 (xnvc_get_string (state, "Expires:"));
1510   if (!expire)
1511     {
1512       err = gpg_error (GPG_ERR_INV_VALUE);
1513       log_error ("no 'Expire' in our state file\n");
1514       goto leave;
1515     }
1516   expirebuf[0] = expire >> 32;
1517   expirebuf[1] = expire >> 24;
1518   expirebuf[2] = expire >> 16;
1519   expirebuf[3] = expire >> 8;
1520   expirebuf[4] = expire;
1521 
1522   /* Get our secret from the state.  */
1523   if (hex2bin (xnvc_get_string (state, "DH-SKr:"), skr, sizeof skr) < 0)
1524     {
1525       err = gpg_error (GPG_ERR_INV_VALUE);
1526       log_error ("no or garbled 'DH-SKr' in our state file\n");
1527       goto leave;
1528     }
1529 
1530   /* Compute the shared secrets.  */
1531   err = compute_master_secret (master, sizeof master,
1532                                skr, sizeof skr, pki, sizeof pki);
1533   if (err)
1534     {
1535       log_error ("creating DH keypair failed: %s\n", gpg_strerror (err));
1536       goto leave;
1537     }
1538 
1539   kdf (hmacikey, sizeof hmacikey,
1540        master, sizeof master, msg+8, 8, expirebuf, sizeof expirebuf,
1541        "GPG-pa1-HMACi-key");
1542   kdf (hmacrkey, sizeof hmacrkey,
1543        master, sizeof master, msg+8, 8, expirebuf, sizeof expirebuf,
1544        "GPG-pa1-HMACr-key");
1545   kdf (symxkey, sizeof symxkey,
1546        master, sizeof master, msg+8, 8, expirebuf, sizeof expirebuf,
1547        "GPG-pa1-SYMx-key");
1548   kdf (sas, sizeof sas,
1549        master, sizeof master, msg+8, 8, expirebuf, sizeof expirebuf,
1550        "GPG-pa1-SAS");
1551 
1552   /* Check the MAC from the message which is
1553    *   MAC(HMACi-key, Hash(DHPART1) || DHPART2[0..47] || SYMx-key).
1554    * For that we need to fetch the stored hash from the state.  */
1555   if (hex2bin (xnvc_get_string (state, "Hash-DHPart1:"),
1556                tmphash, sizeof tmphash) < 0)
1557     {
1558       err = gpg_error (GPG_ERR_INV_VALUE);
1559       log_error ("no or garbled 'Hash-DHPart1' in our state file\n");
1560       goto leave;
1561     }
1562   hmac_data (hash, 32, hmacikey, sizeof hmacikey,
1563              tmphash, sizeof tmphash,
1564              msg, 48,
1565              symxkey, sizeof symxkey,
1566              NULL);
1567   if (memcmp (msg+48, hash, 32))
1568     {
1569       err = gpg_error (GPG_ERR_BAD_DATA);
1570       log_error ("manipulation of received %s message detected: %s\n",
1571                  msgtypestr (MSG_TYPE_DHPART2), "Bad MAC");
1572       goto leave;
1573     }
1574 
1575   /* Create the response.  */
1576   newmsglen = 7+1+8+32;
1577   newmsg = xmalloc (newmsglen);
1578   memcpy (newmsg+0, "GPG-pa1", 7);
1579   newmsg[7] = MSG_TYPE_CONFIRM;
1580   memcpy (newmsg+8, msg + 8, 8); /* SessionID.  */
1581   /* MAC(HMACr-key, Hash(DHPART2) || CONFIRM[0..15] || SYMx-key) */
1582   gcry_md_hash_buffer (GCRY_MD_SHA256, tmphash, msg, msglen);
1583   hmac_data (newmsg+16, 32, hmacrkey, sizeof hmacrkey,
1584              tmphash, sizeof tmphash,
1585              newmsg, (size_t)16,
1586              symxkey, sizeof symxkey,
1587              NULL);
1588 
1589   /* Update the state.  */
1590   xnvc_set (state, "State:", "Confirm-sent");
1591   xnvc_set_hex (state, "DH-Master:", master, sizeof master);
1592 
1593   /* Write the state.  */
1594   write_state (state, 0);
1595 
1596   /* Write the message.  */
1597   send_message (newmsg, newmsglen);
1598 
1599   display_sas (sas, sizeof sas, 0);
1600 
1601 
1602  leave:
1603   xfree (newmsg);
1604   return err;
1605 }
1606 
1607 
1608 /* We are the Initiator: Process a CONFIRM message in (MSG,MSGLEN)
1609  * which has already been validated to have a correct header and
1610  * message type.  Does not send anything back.  */
1611 static gpg_error_t
proc_msg_confirm(nvc_t state,const unsigned char * msg,size_t msglen)1612 proc_msg_confirm (nvc_t state, const unsigned char *msg, size_t msglen)
1613 {
1614   gpg_error_t err;
1615   unsigned char hash[32];
1616   unsigned char tmphash[32];
1617   unsigned char master[32];
1618   uint64_t expire;
1619   unsigned char expirebuf[5];
1620   unsigned char hmacrkey[32];
1621   unsigned char symxkey[32];
1622   unsigned char sas[32];
1623 
1624   log_assert (msglen >= 48);
1625 
1626   /* Put the expire value into a buffer.  */
1627   expire = string_to_u64 (xnvc_get_string (state, "Expires:"));
1628   if (!expire)
1629     {
1630       err = gpg_error (GPG_ERR_INV_VALUE);
1631       log_error ("no 'Expire' in our state file\n");
1632       goto leave;
1633     }
1634   expirebuf[0] = expire >> 32;
1635   expirebuf[1] = expire >> 24;
1636   expirebuf[2] = expire >> 16;
1637   expirebuf[3] = expire >> 8;
1638   expirebuf[4] = expire;
1639 
1640   /* Get the master secret.  */
1641   if (hex2bin (xnvc_get_string (state, "DH-Master:"),master,sizeof master) < 0)
1642     {
1643       err = gpg_error (GPG_ERR_INV_VALUE);
1644       log_error ("no or garbled 'DH-Master' in our state file\n");
1645       goto leave;
1646     }
1647 
1648   kdf (hmacrkey, sizeof hmacrkey,
1649        master, sizeof master, msg+8, 8, expirebuf, sizeof expirebuf,
1650        "GPG-pa1-HMACr-key");
1651   kdf (symxkey, sizeof symxkey,
1652        master, sizeof master, msg+8, 8, expirebuf, sizeof expirebuf,
1653        "GPG-pa1-SYMx-key");
1654   kdf (sas, sizeof sas,
1655        master, sizeof master, msg+8, 8, expirebuf, sizeof expirebuf,
1656        "GPG-pa1-SAS");
1657 
1658   /* Check the MAC from the message which is */
1659   /*   MAC(HMACr-key, Hash(DHPART2) || CONFIRM[0..15] || SYMx-key). */
1660   if (hex2bin (xnvc_get_string (state, "Hash-DHPart2:"),
1661                tmphash, sizeof tmphash) < 0)
1662     {
1663       err = gpg_error (GPG_ERR_INV_VALUE);
1664       log_error ("no or garbled 'Hash-DHPart2' in our state file\n");
1665       goto leave;
1666     }
1667   hmac_data (hash, 32, hmacrkey, sizeof hmacrkey,
1668              tmphash, sizeof tmphash,
1669              msg, (size_t)16,
1670              symxkey, sizeof symxkey,
1671              NULL);
1672   if (!memcmp (msg+48, hash, 32))
1673     {
1674       err = gpg_error (GPG_ERR_BAD_DATA);
1675       log_error ("manipulation of received %s message detected: %s\n",
1676                  msgtypestr (MSG_TYPE_CONFIRM), "Bad MAC");
1677       goto leave;
1678     }
1679 
1680 
1681   err = display_sas (sas, sizeof sas, 1);
1682   if (err)
1683     goto leave;
1684 
1685   /* Update the state.  */
1686   xnvc_set (state, "State:", "Confirmed");
1687 
1688   /* Write the state.  */
1689   write_state (state, 0);
1690 
1691  leave:
1692   return err;
1693 }
1694 
1695 
1696 
1697 /* Expire old state files.  This loops over all state files and remove
1698  * those which are expired.  */
1699 static void
expire_old_states(void)1700 expire_old_states (void)
1701 {
1702   gpg_error_t err = 0;
1703   const char *dirname;
1704   gnupg_dir_t dir = NULL;
1705   gnupg_dirent_t dir_entry;
1706   char *fname = NULL;
1707   estream_t fp = NULL;
1708   nvc_t nvc = NULL;
1709   nve_t item;
1710   const char *value;
1711   unsigned long expire;
1712   unsigned long now = gnupg_get_time ();
1713 
1714   dirname = get_pairing_statedir ();
1715   dir = gnupg_opendir (dirname);
1716   if (!dir)
1717     {
1718       err = gpg_error_from_syserror ();
1719       goto leave;
1720     }
1721 
1722   while ((dir_entry = gnupg_readdir (dir)))
1723     {
1724       if (strlen (dir_entry->d_name) != 16+4
1725           || strcmp (dir_entry->d_name + 16, ".pa1"))
1726         continue;
1727 
1728       xfree (fname);
1729       fname = make_filename (dirname, dir_entry->d_name, NULL);
1730       es_fclose (fp);
1731       fp = es_fopen (fname, "rb");
1732       if (!fp)
1733         {
1734           err = gpg_error_from_syserror ();
1735           if (gpg_err_code (err) != GPG_ERR_ENOENT)
1736             log_info ("failed to open state file '%s': %s\n",
1737                       fname, gpg_strerror (err));
1738           continue;
1739         }
1740       nvc_release (nvc);
1741 
1742       /* NB.: The following is similar to code in read_state.  */
1743       err = nvc_parse (&nvc, NULL, fp);
1744       if (err)
1745         {
1746           log_info ("failed to parse state file '%s': %s\n",
1747                     fname, gpg_strerror (err));
1748           continue; /* Skip */
1749         }
1750       item = nvc_lookup (nvc, "Expires:");
1751       if (!item)
1752         {
1753           log_info ("invalid state file '%s': %s\n",
1754                     fname, "field 'expire' not found");
1755           continue; /* Skip */
1756         }
1757       value = nve_value (item);
1758       if (!value || !(expire = strtoul (value, NULL, 10)))
1759         {
1760           log_info ("invalid state file '%s': %s\n",
1761                     fname, "field 'expire' has an invalid value");
1762           continue; /* Skip */
1763         }
1764 
1765       if (expire <= now)
1766         {
1767           es_fclose (fp);
1768           fp = NULL;
1769           if (gnupg_remove (fname))
1770             {
1771               err = gpg_error_from_syserror ();
1772               log_info ("failed to delete state file '%s': %s\n",
1773                         fname, gpg_strerror (err));
1774             }
1775           else if (opt.verbose)
1776             log_info ("state file '%s' deleted\n", fname);
1777         }
1778     }
1779 
1780  leave:
1781   if (err)
1782     log_error ("expiring old states in '%s' failed: %s\n",
1783                dirname, gpg_strerror (err));
1784   gnupg_closedir (dir);
1785   es_fclose (fp);
1786   xfree (fname);
1787 }
1788 
1789 
1790 
1791 /* Initiate a pairing.  The output needs to be conveyed to the
1792  * peer  */
1793 static gpg_error_t
command_initiate(void)1794 command_initiate (void)
1795 {
1796   gpg_error_t err;
1797   nvc_t state;
1798 
1799   state = xnvc_new ();
1800   xnvc_set (state, "Version:", "GPG-pa1");
1801   xnvc_set_hex (state, "Session:", get_session_id (), 8);
1802   xnvc_set (state, "Role:", "Initiator");
1803 
1804   err = make_msg_commit (state);
1805 
1806   nvc_release (state);
1807   return err;
1808 }
1809 
1810 
1811 
1812 /* Helper for command_respond().  */
1813 static gpg_error_t
expect_state(int msgtype,const char * statestr,const char * expected)1814 expect_state (int msgtype, const char *statestr, const char *expected)
1815 {
1816   if (strcmp (statestr, expected))
1817     {
1818       log_error ("received %s message in %s state (should be %s)\n",
1819                  msgtypestr (msgtype), statestr, expected);
1820       return gpg_error (GPG_ERR_INV_RESPONSE);
1821     }
1822   return 0;
1823 }
1824 
1825 /* Respond to a pairing intiation.  This is used by the peer and later
1826  * by the original responder.  Depending on the state the output needs
1827  * to be conveyed to the peer.  */
1828 static gpg_error_t
command_respond(void)1829 command_respond (void)
1830 {
1831   gpg_error_t err;
1832   unsigned char *msg;
1833   size_t msglen = 0; /* In case that read_message returns an error.  */
1834   int msgtype = 0;   /* ditto.  */
1835   nvc_t state;
1836   const char *rolestr;
1837   const char *statestr;
1838 
1839   err = read_message (&msg, &msglen, &msgtype, &state);
1840   if (err && gpg_err_code (err) != GPG_ERR_NOT_FOUND)
1841     goto leave;
1842   rolestr = xnvc_get_string (state, "Role:");
1843   statestr = xnvc_get_string (state, "State:");
1844   if (DBG_MESSAGE)
1845     {
1846       if (!state)
1847         log_debug ("no state available\n");
1848       else
1849         log_debug ("we are %s, our current state is %s\n", rolestr, statestr);
1850       log_debug ("got message of type %s (%d)\n",
1851                  msgtypestr (msgtype), msgtype);
1852     }
1853 
1854   if (!state)
1855     {
1856       if (msgtype == MSG_TYPE_COMMIT)
1857         {
1858           state = xnvc_new ();
1859           xnvc_set (state, "Version:", "GPG-pa1");
1860           xnvc_set_hex (state, "Session:", get_session_id (), 8);
1861           xnvc_set (state, "Role:", "Responder");
1862           err = proc_msg_commit (state, msg, msglen);
1863         }
1864       else
1865         {
1866           log_error ("%s message expected but got %s\n",
1867                      msgtypestr (MSG_TYPE_COMMIT), msgtypestr (msgtype));
1868           if (msgtype == MSG_TYPE_DHPART1)
1869             log_info ("the pairing probably took too long and timed out\n");
1870           err = gpg_error (GPG_ERR_INV_RESPONSE);
1871           goto leave;
1872         }
1873     }
1874   else if (!strcmp (rolestr, "Initiator"))
1875     {
1876       if (msgtype == MSG_TYPE_DHPART1)
1877         {
1878           if (!(err = expect_state (msgtype, statestr, "Commit-sent")))
1879             err = proc_msg_dhpart1 (state, msg, msglen);
1880         }
1881       else if (msgtype == MSG_TYPE_CONFIRM)
1882         {
1883           if (!(err = expect_state (msgtype, statestr, "DHPart2-sent")))
1884             err = proc_msg_confirm (state, msg, msglen);
1885         }
1886       else
1887         {
1888           log_error ("%s message not expected by Initiator\n",
1889                      msgtypestr (msgtype));
1890           err = gpg_error (GPG_ERR_INV_RESPONSE);
1891           goto leave;
1892         }
1893     }
1894   else if (!strcmp (rolestr, "Responder"))
1895     {
1896       if (msgtype == MSG_TYPE_DHPART2)
1897         {
1898           if (!(err = expect_state (msgtype, statestr, "DHPart1-sent")))
1899             err = proc_msg_dhpart2 (state, msg, msglen);
1900         }
1901       else
1902         {
1903           log_error ("%s message not expected by Responder\n",
1904                      msgtypestr (msgtype));
1905           err = gpg_error (GPG_ERR_INV_RESPONSE);
1906           goto leave;
1907         }
1908     }
1909   else
1910     log_fatal ("invalid role '%s' in state file\n", rolestr);
1911 
1912 
1913  leave:
1914   xfree (msg);
1915   nvc_release (state);
1916   return err;
1917 }
1918 
1919 
1920 
1921 /* Return the keys for SESSIONIDSTR or the last one if it is NULL.
1922  * Two keys are returned: The first is the one for sending encrypted
1923  * data and the second one for decrypting received data.  The keys are
1924  * always returned hex encoded and both are terminated by a LF. */
1925 static gpg_error_t
command_get(const char * sessionidstr)1926 command_get (const char *sessionidstr)
1927 {
1928   gpg_error_t err;
1929   unsigned char sessid[8];
1930   nvc_t state;
1931 
1932   if (!sessionidstr)
1933     {
1934       log_error ("calling without session-id is not yet implemented\n");
1935       err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1936       goto leave;
1937     }
1938   if (hex2bin (sessionidstr, sessid, sizeof sessid) < 0)
1939     {
1940       err = gpg_error (GPG_ERR_INV_VALUE);
1941       log_error ("invalid session id given\n");
1942       goto leave;
1943     }
1944   set_session_id (sessid, sizeof sessid);
1945   err = read_state (&state);
1946   if (err)
1947     {
1948       log_error ("reading state of session %s failed: %s\n",
1949                  sessionidstr, gpg_strerror (err));
1950       goto leave;
1951     }
1952 
1953  leave:
1954   return err;
1955 }
1956 
1957 
1958 
1959 /* Cleanup command.  */
1960 static gpg_error_t
command_cleanup(void)1961 command_cleanup (void)
1962 {
1963   expire_old_states ();
1964   return 0;
1965 }
1966