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