drm/linux: Add list_for_each_entry_safe_reverse()
[dragonfly.git] / lib / libdmsg / crypto.c
1 /*
2  * Copyright (c) 2011-2012 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Matthew Dillon <dillon@dragonflybsd.org>
6  * by Venkatesh Srinivas <vsrinivas@dragonflybsd.org>
7  * by Alex Hornung <alexh@dragonflybsd.org>
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  * 3. Neither the name of The DragonFly Project nor the names of its
20  *    contributors may be used to endorse or promote products derived
21  *    from this software without specific, prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
27  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
31  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  */
36
37 #include "dmsg_local.h"
38
39 /*
40  * Setup crypto for pthreads
41  */
42 static pthread_mutex_t *crypto_locks;
43 int crypto_count;
44
45 static int dmsg_crypto_gcm_init(dmsg_ioq_t *, char *, int, char *, int, int);
46 static int dmsg_crypto_gcm_encrypt_chunk(dmsg_ioq_t *, char *, char *, int, int *);
47 static int dmsg_crypto_gcm_decrypt_chunk(dmsg_ioq_t *, char *, char *, int, int *);
48
49 /*
50  * NOTE: the order of this table needs to match the DMSG_CRYPTO_ALGO_*_IDX
51  *       defines in network.h.
52  */
53 static struct crypto_algo crypto_algos[] = {
54         {
55                 .name      = "aes-256-gcm",
56                 .keylen    = DMSG_CRYPTO_GCM_KEY_SIZE,
57                 .taglen    = DMSG_CRYPTO_GCM_TAG_SIZE,
58                 .init      = dmsg_crypto_gcm_init,
59                 .enc_chunk = dmsg_crypto_gcm_encrypt_chunk,
60                 .dec_chunk = dmsg_crypto_gcm_decrypt_chunk
61         },
62         { NULL, 0, 0, NULL, NULL, NULL }
63 };
64
65 static
66 unsigned long
67 dmsg_crypto_id_callback(void)
68 {
69         return ((unsigned long)(uintptr_t)pthread_self());
70 }
71
72 static
73 void
74 dmsg_crypto_locking_callback(int mode, int type,
75                                 const char *file __unused, int line __unused)
76 {
77         assert(type >= 0 && type < crypto_count);
78         if (mode & CRYPTO_LOCK) {
79                 pthread_mutex_lock(&crypto_locks[type]);
80         } else {
81                 pthread_mutex_unlock(&crypto_locks[type]);
82         }
83 }
84
85 void
86 dmsg_crypto_setup(void)
87 {
88         crypto_count = CRYPTO_num_locks();
89         crypto_locks = calloc(crypto_count, sizeof(crypto_locks[0]));
90         CRYPTO_set_id_callback(dmsg_crypto_id_callback);
91         CRYPTO_set_locking_callback(dmsg_crypto_locking_callback);
92 }
93
94 static
95 int
96 dmsg_crypto_gcm_init(dmsg_ioq_t *ioq, char *key, int klen,
97                         char *iv_fixed, int ivlen, int enc)
98 {
99         int i, ok;
100
101         if (klen < DMSG_CRYPTO_GCM_KEY_SIZE ||
102             ivlen < DMSG_CRYPTO_GCM_IV_FIXED_SIZE) {
103                 dm_printf(1, "%s\n", "Not enough key or iv material");
104                 return -1;
105         }
106
107         dm_printf(6, "%s key: ", enc ? "Encryption" : "Decryption");
108         for (i = 0; i < DMSG_CRYPTO_GCM_KEY_SIZE; ++i)
109                 dmx_printf(6, "%02x", (unsigned char)key[i]);
110         dmx_printf(6, "%s\n", "");
111
112         dm_printf(6, "%s iv:  ", enc ? "Encryption" : "Decryption");
113         for (i = 0; i < DMSG_CRYPTO_GCM_IV_FIXED_SIZE; ++i)
114                 dmx_printf(6, "%02x", (unsigned char)iv_fixed[i]);
115         dmx_printf(6, "%s\n", " (fixed part only)");
116
117         EVP_CIPHER_CTX_init(&ioq->ctx);
118
119         if (enc)
120                 ok = EVP_EncryptInit_ex(&ioq->ctx, EVP_aes_256_gcm(), NULL,
121                                         (unsigned char*)key, NULL);
122         else
123                 ok = EVP_DecryptInit_ex(&ioq->ctx, EVP_aes_256_gcm(), NULL,
124                                         (unsigned char*)key, NULL);
125         if (!ok)
126                 goto fail;
127
128         /*
129          * According to the original Galois/Counter Mode of Operation (GCM)
130          * proposal, only IVs that are exactly 96 bits get used without any
131          * further processing. Other IV sizes cause the GHASH() operation
132          * to be applied to the IV, which is more costly.
133          *
134          * The NIST SP 800-38D also recommends using a 96 bit IV for the same
135          * reasons. We actually follow the deterministic construction
136          * recommended in NIST SP 800-38D with a 64 bit invocation field as an
137          * integer counter and a random, session-specific fixed field.
138          *
139          * This means that we can essentially use the same session key and
140          * IV fixed field for up to 2^64 invocations of the authenticated
141          * encryption or decryption.
142          *
143          * With a chunk size of 64 bytes, this adds up to 1 zettabyte of
144          * traffic.
145          */
146         ok = EVP_CIPHER_CTX_ctrl(&ioq->ctx, EVP_CTRL_GCM_SET_IVLEN,
147                                  DMSG_CRYPTO_GCM_IV_SIZE, NULL);
148         if (!ok)
149                 goto fail;
150
151         memset(ioq->iv, 0, DMSG_CRYPTO_GCM_IV_SIZE);
152         memcpy(ioq->iv, iv_fixed, DMSG_CRYPTO_GCM_IV_FIXED_SIZE);
153
154         /*
155          * Strictly speaking, padding is irrelevant with a counter mode
156          * encryption.
157          *
158          * However, setting padding to 0, even if using a counter mode such
159          * as GCM, will cause an error in _finish if the pt/ct size is not
160          * a multiple of the cipher block size.
161          */
162         EVP_CIPHER_CTX_set_padding(&ioq->ctx, 0);
163
164         return 0;
165
166 fail:
167         dm_printf(1, "%s\n", "Error during _gcm_init");
168         return -1;
169 }
170
171 static
172 int
173 _gcm_iv_increment(char *iv)
174 {
175         /*
176          * Deterministic construction according to NIST SP 800-38D, with
177          * 64 bit invocation field as integer counter.
178          *
179          * In other words, our 96 bit IV consists of a 32 bit fixed field
180          * unique to the session and a 64 bit integer counter.
181          */
182
183         uint64_t *c = (uint64_t *)(&iv[DMSG_CRYPTO_GCM_IV_FIXED_SIZE]);
184
185         /* Increment invocation field integer counter */
186         *c = htobe64(be64toh(*c)+1);
187
188         /*
189          * Detect wrap-around, which means it is time to renegotiate
190          * the session to get a new key and/or fixed field.
191          */
192         return (*c == 0) ? 0 : 1;
193 }
194
195 static
196 int
197 dmsg_crypto_gcm_encrypt_chunk(dmsg_ioq_t *ioq, char *ct, char *pt,
198                                  int in_size, int *out_size)
199 {
200         int ok;
201         int u_len, f_len;
202
203         *out_size = 0;
204
205         /* Re-initialize with new IV (but without redoing the key schedule) */
206         ok = EVP_EncryptInit_ex(&ioq->ctx, NULL, NULL, NULL,
207                 (unsigned char*)ioq->iv);
208         if (!ok)
209                 goto fail;
210
211         u_len = 0;      /* safety */
212         ok = EVP_EncryptUpdate(&ioq->ctx, (unsigned char*)ct, &u_len,
213                 (unsigned char*)pt, in_size);
214         if (!ok)
215                 goto fail;
216
217         f_len = 0;      /* safety */
218         ok = EVP_EncryptFinal_ex(&ioq->ctx, (unsigned char*)ct + u_len, &f_len);
219         if (!ok)
220                 goto fail;
221
222         /* Retrieve auth tag */
223         ok = EVP_CIPHER_CTX_ctrl(&ioq->ctx, EVP_CTRL_GCM_GET_TAG,
224                                  DMSG_CRYPTO_GCM_TAG_SIZE,
225                                  ct + u_len + f_len);
226         if (!ok)
227                 goto fail;
228
229         ok = _gcm_iv_increment(ioq->iv);
230         if (!ok) {
231                 ioq->error = DMSG_IOQ_ERROR_IVWRAP;
232                 goto fail_out;
233         }
234
235         *out_size = u_len + f_len + DMSG_CRYPTO_GCM_TAG_SIZE;
236         EVP_CIPHER_CTX_reset(&ioq->ctx);
237
238         return 0;
239
240 fail:
241         ioq->error = DMSG_IOQ_ERROR_ALGO;
242 fail_out:
243         EVP_CIPHER_CTX_reset(&ioq->ctx);
244         dm_printf(1, "%s\n", "error during encrypt_chunk");
245         return -1;
246 }
247
248 static
249 int
250 dmsg_crypto_gcm_decrypt_chunk(dmsg_ioq_t *ioq, char *ct, char *pt,
251                                  int out_size, int *consume_size)
252 {
253         int ok;
254         int u_len, f_len;
255
256         *consume_size = 0;
257
258         /* Re-initialize with new IV (but without redoing the key schedule) */
259         ok = EVP_DecryptInit_ex(&ioq->ctx, NULL, NULL, NULL,
260                 (unsigned char*)ioq->iv);
261         if (!ok) {
262                 ioq->error = DMSG_IOQ_ERROR_ALGO;
263                 goto fail_out;
264         }
265
266         ok = EVP_CIPHER_CTX_ctrl(&ioq->ctx, EVP_CTRL_GCM_SET_TAG,
267                                  DMSG_CRYPTO_GCM_TAG_SIZE,
268                                  ct + out_size);
269         if (!ok) {
270                 ioq->error = DMSG_IOQ_ERROR_ALGO;
271                 goto fail_out;
272         }
273
274         ok = EVP_DecryptUpdate(&ioq->ctx, (unsigned char*)pt, &u_len,
275                 (unsigned char*)ct, out_size);
276         if (!ok)
277                 goto fail;
278
279         ok = EVP_DecryptFinal_ex(&ioq->ctx, (unsigned char*)pt + u_len, &f_len);
280         if (!ok)
281                 goto fail;
282
283         ok = _gcm_iv_increment(ioq->iv);
284         if (!ok) {
285                 ioq->error = DMSG_IOQ_ERROR_IVWRAP;
286                 goto fail_out;
287         }
288
289         *consume_size = u_len + f_len + DMSG_CRYPTO_GCM_TAG_SIZE;
290         EVP_CIPHER_CTX_reset(&ioq->ctx);
291
292         return 0;
293
294 fail:
295         ioq->error = DMSG_IOQ_ERROR_MACFAIL;
296 fail_out:
297         EVP_CIPHER_CTX_reset(&ioq->ctx);
298         dm_printf(1, "%s\n",
299                   "error during decrypt_chunk "
300                   "(likely authentication error)");
301         return -1;
302 }
303
304 /*
305  * Synchronously negotiate crypto for a new session.  This must occur
306  * within 10 seconds or the connection is error'd out.
307  *
308  * We work off the IP address and/or reverse DNS.  The IP address is
309  * checked first, followed by the IP address at various levels of granularity,
310  * followed by the full domain name and domain names at various levels of
311  * granularity.
312  *
313  *      /etc/hammer2/remote/<name>.pub  - Contains a public key
314  *      /etc/hammer2/remote/<name>.none - Indicates no encryption (empty file)
315  *                                        (e.g. localhost.none).
316  *
317  * We first attempt to locate a public key file based on the peer address or
318  * peer FQDN.
319  *
320  *      <name>.none     - No further negotiation is needed.  We simply return.
321  *                        All communication proceeds without encryption.
322  *                        No public key handshake occurs in this situation.
323  *                        (both ends must match).
324  *
325  *      <name>.pub      - We have located the public key for the peer.  Both
326  *                        sides transmit a block encrypted with their private
327  *                        keys and the peer's public key.
328  *
329  *                        Both sides receive a block and decrypt it.
330  *
331  *                        Both sides formulate a reply using the decrypted
332  *                        block and transmit it.
333  *
334  *                        communication proceeds with the negotiated session
335  *                        key (typically AES-256-CBC).
336  *
337  * If we fail to locate the appropriate file and no floating.db exists the
338  * connection is terminated without further action.
339  *
340  * If floating.db exists the connection proceeds with a floating negotiation.
341  */
342 typedef union {
343         struct sockaddr sa;
344         struct sockaddr_in sa_in;
345         struct sockaddr_in6 sa_in6;
346 } sockaddr_any_t;
347
348 void
349 dmsg_crypto_negotiate(dmsg_iocom_t *iocom)
350 {
351         sockaddr_any_t sa;
352         socklen_t salen = sizeof(sa);
353         char peername[128];
354         char realname[128];
355         dmsg_handshake_t handtx;
356         dmsg_handshake_t handrx;
357         char buf1[sizeof(handtx)];
358         char buf2[sizeof(handtx)];
359         char *ptr;
360         char *path;
361         struct stat st;
362         FILE *fp;
363         RSA *keys[3] = { NULL, NULL, NULL };
364         size_t i;
365         size_t blksize;
366         size_t blkmask;
367         ssize_t n;
368         int fd;
369         int error;
370
371         /*
372          * Get the peer IP address for the connection as a string.
373          */
374         if (getpeername(iocom->sock_fd, &sa.sa, &salen) < 0) {
375                 iocom->ioq_rx.error = DMSG_IOQ_ERROR_NOPEER;
376                 atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF);
377                 dm_printf(1, "%s\n", "accept: getpeername() failed");
378                 goto done;
379         }
380         if (getnameinfo(&sa.sa, salen, peername, sizeof(peername),
381                         NULL, 0, NI_NUMERICHOST) < 0) {
382                 iocom->ioq_rx.error = DMSG_IOQ_ERROR_NOPEER;
383                 atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF);
384                 dm_printf(1, "%s\n", "accept: cannot decode sockaddr");
385                 goto done;
386         }
387         if (DMsgDebugOpt) {
388                 if (realhostname_sa(realname, sizeof(realname),
389                                     &sa.sa, salen) == HOSTNAME_FOUND) {
390                         dm_printf(1, "accept from %s (%s)\n",
391                                   peername, realname);
392                 } else {
393                         dm_printf(1, "accept from %s\n", peername);
394                 }
395         }
396
397         /*
398          * Find the remote host's public key
399          *
400          * If the link is not to be encrypted (<ip>.none located) we shortcut
401          * the handshake entirely.  No buffers are exchanged.
402          */
403         asprintf(&path, "%s/%s.pub", DMSG_PATH_REMOTE, peername);
404         if ((fp = fopen(path, "r")) == NULL) {
405                 free(path);
406                 asprintf(&path, "%s/%s.none",
407                          DMSG_PATH_REMOTE, peername);
408                 if (stat(path, &st) < 0) {
409                         iocom->ioq_rx.error = DMSG_IOQ_ERROR_NORKEY;
410                         atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF);
411                         dm_printf(1, "%s\n", "auth failure: unknown host");
412                         goto done;
413                 }
414                 dm_printf(1, "%s\n", "auth succeeded, unencrypted link");
415                 goto done;
416         }
417         if (fp) {
418                 keys[0] = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL);
419                 fclose(fp);
420                 if (keys[0] == NULL) {
421                         iocom->ioq_rx.error = DMSG_IOQ_ERROR_KEYFMT;
422                         atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF);
423                         dm_printf(1, "%s\n", "auth failure: bad key format");
424                         goto done;
425                 }
426         }
427
428         /*
429          * Get our public and private keys
430          */
431         free(path);
432         asprintf(&path, DMSG_DEFAULT_DIR "/rsa.pub");
433         if ((fp = fopen(path, "r")) == NULL) {
434                 iocom->ioq_rx.error = DMSG_IOQ_ERROR_NOLKEY;
435                 atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF);
436                 goto done;
437         }
438         keys[1] = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL);
439         fclose(fp);
440         if (keys[1] == NULL) {
441                 iocom->ioq_rx.error = DMSG_IOQ_ERROR_KEYFMT;
442                 atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF);
443                 dm_printf(1, "%s\n", "auth failure: bad host key format");
444                 goto done;
445         }
446
447         free(path);
448         asprintf(&path, DMSG_DEFAULT_DIR "/rsa.prv");
449         if ((fp = fopen(path, "r")) == NULL) {
450                 iocom->ioq_rx.error = DMSG_IOQ_ERROR_NOLKEY;
451                 atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF);
452                 dm_printf(1, "%s\n", "auth failure: bad host key format");
453                 goto done;
454         }
455         keys[2] = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
456         fclose(fp);
457         if (keys[2] == NULL) {
458                 iocom->ioq_rx.error = DMSG_IOQ_ERROR_KEYFMT;
459                 atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF);
460                 dm_printf(1, "%s\n", "auth failure: bad host key format");
461                 goto done;
462         }
463         free(path);
464         path = NULL;
465
466         /*
467          * public key encrypt/decrypt block size.
468          */
469         if (keys[0]) {
470                 blksize = (size_t)RSA_size(keys[0]);
471                 if (blksize != (size_t)RSA_size(keys[1]) ||
472                     blksize != (size_t)RSA_size(keys[2]) ||
473                     sizeof(handtx) % blksize != 0) {
474                         iocom->ioq_rx.error = DMSG_IOQ_ERROR_KEYFMT;
475                         atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF);
476                         dm_printf(1, "%s\n",
477                                   "auth failure: key size mismatch");
478                         goto done;
479                 }
480         } else {
481                 blksize = sizeof(handtx);
482         }
483         blkmask = blksize - 1;
484
485         bzero(&handrx, sizeof(handrx));
486         bzero(&handtx, sizeof(handtx));
487
488         /*
489          * Fill all unused fields (particular all junk fields) with random
490          * data, and also set the session key.
491          */
492         fd = open("/dev/urandom", O_RDONLY);
493         if (fd < 0 ||
494             fstat(fd, &st) < 0 ||       /* something wrong */
495             S_ISREG(st.st_mode) ||      /* supposed to be a RNG dev! */
496             read(fd, &handtx, sizeof(handtx)) != sizeof(handtx)) {
497 urandfail:
498                 if (fd >= 0)
499                         close(fd);
500                 iocom->ioq_rx.error = DMSG_IOQ_ERROR_BADURANDOM;
501                 atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF);
502                 dm_printf(1, "%s\n", "auth failure: bad rng");
503                 goto done;
504         }
505         if (bcmp(&handrx, &handtx, sizeof(handtx)) == 0)
506                 goto urandfail;                 /* read all zeros */
507         close(fd);
508         /* ERR_load_crypto_strings(); openssl debugging */
509
510         /*
511          * Handshake with the remote.
512          *
513          *      Encrypt with my private and remote's public
514          *      Decrypt with my private and remote's public
515          *
516          * When encrypting we have to make sure our buffer fits within the
517          * modulus, which typically requires bit 7 o the first byte to be
518          * zero.  To be safe make sure that bit 7 and bit 6 is zero.
519          */
520         snprintf(handtx.quickmsg, sizeof(handtx.quickmsg), "Testing 1 2 3");
521         handtx.magic = DMSG_HDR_MAGIC;
522         handtx.version = 1;
523         handtx.flags = 0;
524         assert(sizeof(handtx.verf) * 4 == sizeof(handtx.sess));
525         bzero(handtx.verf, sizeof(handtx.verf));
526
527         handtx.pad1[0] &= 0x3f; /* message must fit within modulus */
528         handtx.pad2[0] &= 0x3f; /* message must fit within modulus */
529
530         for (i = 0; i < sizeof(handtx.sess); ++i)
531                 handtx.verf[i / 4] ^= handtx.sess[i];
532
533         /*
534          * Write handshake buffer to remote
535          */
536         for (i = 0; i < sizeof(handtx); i += blksize) {
537                 ptr = (char *)&handtx + i;
538                 if (keys[0]) {
539                         /*
540                          * Since we are double-encrypting we have to make
541                          * sure that the result of the first stage does
542                          * not blow out the modulus for the second stage.
543                          *
544                          * The pointer is pointing to the pad*[] area so
545                          * we can mess with that until the first stage
546                          * is legal.
547                          */
548                         do {
549                                 ++*(int *)(ptr + 4);
550                                 if (RSA_private_encrypt(blksize,
551                                             (unsigned char*)ptr,
552                                             (unsigned char*)buf1,
553                                             keys[2], RSA_NO_PADDING) < 0) {
554                                         iocom->ioq_rx.error =
555                                                 DMSG_IOQ_ERROR_KEYXCHGFAIL;
556                                 }
557                         } while (buf1[0] & 0xC0);
558
559                         if (RSA_public_encrypt(blksize,
560                                             (unsigned char*)buf1,
561                                             (unsigned char*)buf2,
562                                             keys[0], RSA_NO_PADDING) < 0) {
563                                 iocom->ioq_rx.error =
564                                         DMSG_IOQ_ERROR_KEYXCHGFAIL;
565                         }
566                 }
567                 if (write(iocom->sock_fd, buf2, blksize) != (ssize_t)blksize) {
568                         dmio_printf(iocom, 1, "%s\n", "WRITE ERROR");
569                 }
570         }
571         if (iocom->ioq_rx.error) {
572                 atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF);
573                 dmio_printf(iocom, 1, "%s\n",
574                             "auth failure: key exchange failure "
575                             "during encryption");
576                 goto done;
577         }
578
579         /*
580          * Read handshake buffer from remote
581          */
582         i = 0;
583         while (i < sizeof(handrx)) {
584                 ptr = (char *)&handrx + i;
585                 n = read(iocom->sock_fd, ptr, blksize - (i & blkmask));
586                 if (n <= 0)
587                         break;
588                 ptr -= (i & blkmask);
589                 i += n;
590                 if (keys[0] && (i & blkmask) == 0) {
591                         if (RSA_private_decrypt(blksize,
592                                            (unsigned char*)ptr,
593                                            (unsigned char*)buf1,
594                                            keys[2], RSA_NO_PADDING) < 0)
595                                 iocom->ioq_rx.error =
596                                                 DMSG_IOQ_ERROR_KEYXCHGFAIL;
597                         if (RSA_public_decrypt(blksize,
598                                            (unsigned char*)buf1,
599                                            (unsigned char*)ptr,
600                                            keys[0], RSA_NO_PADDING) < 0)
601                                 iocom->ioq_rx.error =
602                                                 DMSG_IOQ_ERROR_KEYXCHGFAIL;
603                 }
604         }
605         if (iocom->ioq_rx.error) {
606                 atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF);
607                 dmio_printf(iocom, 1, "%s\n",
608                             "auth failure: key exchange failure "
609                             "during decryption");
610                 goto done;
611         }
612
613         /*
614          * Validate the received data.  Try to make this a constant-time
615          * algorithm.
616          */
617         if (i != sizeof(handrx)) {
618 keyxchgfail:
619                 iocom->ioq_rx.error = DMSG_IOQ_ERROR_KEYXCHGFAIL;
620                 atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF);
621                 dmio_printf(iocom, 1, "%s\n",
622                             "auth failure: key exchange failure");
623                 goto done;
624         }
625
626         if (handrx.magic == DMSG_HDR_MAGIC_REV) {
627                 handrx.version = bswap16(handrx.version);
628                 handrx.flags = bswap32(handrx.flags);
629         }
630         for (i = 0; i < sizeof(handrx.sess); ++i)
631                 handrx.verf[i / 4] ^= handrx.sess[i];
632         n = 0;
633         for (i = 0; i < sizeof(handrx.verf); ++i)
634                 n += handrx.verf[i];
635         if (handrx.version != 1)
636                 ++n;
637         if (n != 0)
638                 goto keyxchgfail;
639
640         /*
641          * Use separate session keys and session fixed IVs for receive and
642          * transmit.
643          */
644         error = crypto_algos[DMSG_CRYPTO_ALGO].init(&iocom->ioq_rx,
645             (char*)handrx.sess,
646             crypto_algos[DMSG_CRYPTO_ALGO].keylen,
647             (char*)handrx.sess + crypto_algos[DMSG_CRYPTO_ALGO].keylen,
648             sizeof(handrx.sess) - crypto_algos[DMSG_CRYPTO_ALGO].keylen,
649             0 /* decryption */);
650         if (error)
651                 goto keyxchgfail;
652
653         error = crypto_algos[DMSG_CRYPTO_ALGO].init(&iocom->ioq_tx,
654             (char*)handtx.sess,
655             crypto_algos[DMSG_CRYPTO_ALGO].keylen,
656             (char*)handtx.sess + crypto_algos[DMSG_CRYPTO_ALGO].keylen,
657             sizeof(handtx.sess) - crypto_algos[DMSG_CRYPTO_ALGO].keylen,
658             1 /* encryption */);
659         if (error)
660                 goto keyxchgfail;
661
662         atomic_set_int(&iocom->flags, DMSG_IOCOMF_CRYPTED);
663
664         dmio_printf(iocom, 1, "auth success: %s\n", handrx.quickmsg);
665 done:
666         if (path)
667                 free(path);
668         if (keys[0])
669                 RSA_free(keys[0]);
670         if (keys[1])
671                 RSA_free(keys[1]);
672         if (keys[1])
673                 RSA_free(keys[2]);
674 }
675
676 /*
677  * Decrypt pending data in the ioq's fifo.  The data is decrypted in-place.
678  */
679 void
680 dmsg_crypto_decrypt(dmsg_iocom_t *iocom __unused, dmsg_ioq_t *ioq)
681 {
682         int p_len;
683         int used;
684         __unused int error;     /* XXX */
685         char buf[512];
686
687         /*
688          * fifo_beg to fifo_cdx is data already decrypted.
689          * fifo_cdn to fifo_end is data not yet decrypted.
690          */
691         p_len = ioq->fifo_end - ioq->fifo_cdn; /* data not yet decrypted */
692
693         if (p_len == 0)
694                 return;
695
696         while (p_len >= crypto_algos[DMSG_CRYPTO_ALGO].taglen +
697             DMSG_CRYPTO_CHUNK_SIZE) {
698                 bcopy(ioq->buf + ioq->fifo_cdn, buf,
699                       crypto_algos[DMSG_CRYPTO_ALGO].taglen +
700                       DMSG_CRYPTO_CHUNK_SIZE);
701                 error = crypto_algos[DMSG_CRYPTO_ALGO].dec_chunk(
702                     ioq, buf,
703                     ioq->buf + ioq->fifo_cdx,
704                     DMSG_CRYPTO_CHUNK_SIZE,
705                     &used);
706 #ifdef CRYPTO_DEBUG
707                 dmio_printf(iocom, 5,
708                             "dec: p_len: %d, used: %d, "
709                             "fifo_cdn: %ju, fifo_cdx: %ju\n",
710                              p_len, used,
711                              ioq->fifo_cdn, ioq->fifo_cdx);
712 #endif
713                 p_len -= used;
714                 ioq->fifo_cdn += used;
715                 ioq->fifo_cdx += DMSG_CRYPTO_CHUNK_SIZE;
716 #ifdef CRYPTO_DEBUG
717                 dmio_printf(iocom, 5,
718                             "dec: p_len: %d, used: %d, "
719                             "fifo_cdn: %ju, fifo_cdx: %ju\n",
720                             p_len, used, ioq->fifo_cdn, ioq->fifo_cdx);
721 #endif
722         }
723 }
724
725 /*
726  * *nactp is set to the number of ORIGINAL bytes consumed by the encrypter.
727  * The FIFO may contain more data.
728  */
729 int
730 dmsg_crypto_encrypt(dmsg_iocom_t *iocom __unused, dmsg_ioq_t *ioq,
731                     struct iovec *iov, int n, size_t *nactp)
732 {
733         int p_len, used, ct_used;
734         int i;
735         __unused int error;     /* XXX */
736         size_t nmax;
737
738         nmax = sizeof(ioq->buf) - ioq->fifo_end;        /* max new bytes */
739
740         *nactp = 0;
741         for (i = 0; i < n && nmax; ++i) {
742                 used = 0;
743                 p_len = iov[i].iov_len;
744                 assert((p_len & DMSG_ALIGNMASK) == 0);
745
746                 while (p_len >= DMSG_CRYPTO_CHUNK_SIZE &&
747                     nmax >= DMSG_CRYPTO_CHUNK_SIZE +
748                     (size_t)crypto_algos[DMSG_CRYPTO_ALGO].taglen) {
749                         error = crypto_algos[DMSG_CRYPTO_ALGO].enc_chunk(
750                             ioq,
751                             ioq->buf + ioq->fifo_cdx,
752                             (char *)iov[i].iov_base + used,
753                             DMSG_CRYPTO_CHUNK_SIZE, &ct_used);
754 #ifdef CRYPTO_DEBUG
755                         dmio_printf(iocom, 5,
756                                     "nactp: %ju, p_len: %d, "
757                                     "ct_used: %d, used: %d, nmax: %ju\n",
758                                     *nactp, p_len, ct_used, used, nmax);
759 #endif
760
761                         *nactp += (size_t)DMSG_CRYPTO_CHUNK_SIZE;       /* plaintext count */
762                         used += DMSG_CRYPTO_CHUNK_SIZE;
763                         p_len -= DMSG_CRYPTO_CHUNK_SIZE;
764
765                         /*
766                          * NOTE: crypted count will eventually differ from
767                          *       nmax, but for now we have not yet introduced
768                          *       random armor.
769                          */
770                         ioq->fifo_cdx += (size_t)ct_used;
771                         ioq->fifo_cdn += (size_t)ct_used;
772                         ioq->fifo_end += (size_t)ct_used;
773                         nmax -= (size_t)ct_used;
774 #ifdef CRYPTO_DEBUG
775                         dmio_printf(iocom, 5,
776                                     "nactp: %ju, p_len: %d, "
777                                     "ct_used: %d, used: %d, nmax: %ju\n",
778                                     *nactp, p_len, ct_used, used, nmax);
779 #endif
780                 }
781         }
782         iov[0].iov_base = ioq->buf + ioq->fifo_beg;
783         iov[0].iov_len = ioq->fifo_cdx - ioq->fifo_beg;
784
785         return (1);
786 }