2 * Copyright (c) 2011-2012 The DragonFly Project. All rights reserved.
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>
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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
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.
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
40 * Setup crypto for pthreads
42 static pthread_mutex_t *crypto_locks;
47 hammer2_crypto_id_callback(void)
49 return ((unsigned long)(uintptr_t)pthread_self());
54 hammer2_crypto_locking_callback(int mode, int type,
55 const char *file __unused, int line __unused)
57 assert(type >= 0 && type < crypto_count);
58 if (mode & CRYPTO_LOCK) {
59 pthread_mutex_lock(&crypto_locks[type]);
61 pthread_mutex_unlock(&crypto_locks[type]);
66 hammer2_crypto_setup(void)
68 crypto_count = CRYPTO_num_locks();
69 crypto_locks = calloc(crypto_count, sizeof(crypto_locks[0]));
70 CRYPTO_set_id_callback(hammer2_crypto_id_callback);
71 CRYPTO_set_locking_callback(hammer2_crypto_locking_callback);
76 _gcm_init(hammer2_ioq_t *ioq, char *key, int klen, char *iv_fixed, int ivlen,
81 if (klen < 32 /* 256 bits */ || ivlen < 4 /* 32 bits */) {
83 fprintf(stderr, "Not enough key or iv material\n");
87 printf("%s key: ", enc ? "Encryption" : "Decryption");
88 for (i = 0; i < HAMMER2_AES_KEY_SIZE; ++i)
89 printf("%02x", (unsigned char)key[i]);
92 printf("%s iv: ", enc ? "Encryption" : "Decryption");
93 for (i = 0; i < HAMMER2_CRYPTO_IV_FIXED_SIZE; ++i)
94 printf("%02x", (unsigned char)iv_fixed[i]);
95 printf(" (fixed part only)\n");
98 EVP_CIPHER_CTX_init(&ioq->ctx);
101 ok = EVP_EncryptInit_ex(&ioq->ctx, EVP_aes_256_gcm(), NULL,
104 ok = EVP_DecryptInit_ex(&ioq->ctx, EVP_aes_256_gcm(), NULL,
110 * According to the original Galois/Counter Mode of Operation (GCM)
111 * proposal, only IVs that are exactly 96 bits get used without any
112 * further processing. Other IV sizes cause the GHASH() operation
113 * to be applied to the IV, which is more costly.
115 * The NIST SP 800-38D also recommends using a 96 bit IV for the same
116 * reasons. We actually follow the deterministic construction
117 * recommended in NIST SP 800-38D with a 64 bit invocation field as an
118 * integer counter and a random, session-specific fixed field.
120 * This means that we can essentially use the same session key and
121 * IV fixed field for up to 2^64 invocations of the authenticated
122 * encryption or decryption.
124 * With a chunk size of 64 bytes, this adds up to 1 zettabyte of
127 ok = EVP_CIPHER_CTX_ctrl(&ioq->ctx, EVP_CTRL_GCM_SET_IVLEN,
128 HAMMER2_CRYPTO_IV_SIZE, NULL);
132 memset(ioq->iv, 0, HAMMER2_CRYPTO_IV_SIZE);
133 memcpy(ioq->iv, iv_fixed, HAMMER2_CRYPTO_IV_FIXED_SIZE);
136 * Strictly speaking, padding is irrelevant with a counter mode
139 * However, setting padding to 0, even if using a counter mode such
140 * as GCM, will cause an error in _finish if the pt/ct size is not
141 * a multiple of the cipher block size.
143 EVP_CIPHER_CTX_set_padding(&ioq->ctx, 0);
149 fprintf(stderr, "Error during _gcm_init\n");
155 _gcm_iv_increment(char *iv)
158 * Deterministic construction according to NIST SP 800-38D, with
159 * 64 bit invocation field as integer counter.
161 * In other words, our 96 bit IV consists of a 32 bit fixed field
162 * unique to the session and a 64 bit integer counter.
165 uint64_t *c = (uint64_t *)(&iv[HAMMER2_CRYPTO_IV_FIXED_SIZE]);
167 /* Increment invocation field integer counter */
169 * XXX: this should ideally be an atomic update, but we don't have
170 * an atomic_fetchadd_64 for i386 yet
175 * Detect wrap-around, which means it is time to renegotiate
176 * the session to get a new key and/or fixed field.
178 return (c == 0) ? -1 : 0;
183 hammer2_crypto_encrypt_chunk(hammer2_ioq_t *ioq, char *ct, char *pt,
184 int in_size, int *out_size)
194 /* Re-initialize with new IV (but without redoing the key schedule) */
195 ok = EVP_EncryptInit_ex(&ioq->ctx, NULL, NULL, NULL, ioq->iv);
199 ok = EVP_EncryptUpdate(&ioq->ctx, ct, &u_len, pt, in_size);
203 ok = EVP_EncryptFinal(&ioq->ctx, ct + u_len, &f_len);
207 /* Retrieve auth tag */
208 ok = EVP_CIPHER_CTX_ctrl(&ioq->ctx, EVP_CTRL_GCM_GET_TAG,
209 HAMMER2_CRYPTO_TAG_SIZE,
215 printf("enc_chunk iv: ");
216 for (i = 0; i < HAMMER2_CRYPTO_IV_SIZE; i++)
217 printf("%02x", (unsigned char)ioq->iv[i]);
220 printf("enc_chunk pt: ");
221 for (i = 0; i < in_size; i++)
222 printf("%02x", (unsigned char)pt[i]);
225 printf("enc_chunk ct: ");
226 for (i = 0; i < in_size; i++)
227 printf("%02x", (unsigned char)ct[i]);
230 printf("enc_chunk tag: ");
231 for (i = 0; i < HAMMER2_CRYPTO_TAG_SIZE; i++)
232 printf("%02x", (unsigned char)ct[i + u_len + f_len]);
236 _gcm_iv_increment(ioq->iv);
238 *out_size = u_len + f_len + HAMMER2_CRYPTO_TAG_SIZE;
244 fprintf(stderr, "error during encrypt_chunk\n");
250 hammer2_crypto_decrypt_chunk(hammer2_ioq_t *ioq, char *ct, char *pt,
251 int out_size, int *consume_size)
261 /* Re-initialize with new IV (but without redoing the key schedule) */
262 ok = EVP_DecryptInit_ex(&ioq->ctx, NULL, NULL, NULL, ioq->iv);
267 printf("dec_chunk iv: ");
268 for (i = 0; i < HAMMER2_CRYPTO_IV_SIZE; i++)
269 printf("%02x", (unsigned char)ioq->iv[i]);
272 printf("dec_chunk ct: ");
273 for (i = 0; i < out_size; i++)
274 printf("%02x", (unsigned char)ct[i]);
277 printf("dec_chunk tag: ");
278 for (i = 0; i < HAMMER2_CRYPTO_TAG_SIZE; i++)
279 printf("%02x", (unsigned char)ct[out_size + i]);
283 ok = EVP_CIPHER_CTX_ctrl(&ioq->ctx, EVP_CTRL_GCM_SET_TAG,
284 HAMMER2_CRYPTO_TAG_SIZE,
289 ok = EVP_DecryptUpdate(&ioq->ctx, pt, &u_len, ct, out_size);
293 ok = EVP_DecryptFinal(&ioq->ctx, pt + u_len, &f_len);
297 _gcm_iv_increment(ioq->iv);
299 *consume_size = u_len + f_len + HAMMER2_CRYPTO_TAG_SIZE;
302 printf("dec_chunk pt: ");
303 for (i = 0; i < out_size; i++)
304 printf("%02x", (unsigned char)pt[i]);
312 fprintf(stderr, "error during decrypt_chunk (likely authentication error)\n");
317 * Synchronously negotiate crypto for a new session. This must occur
318 * within 10 seconds or the connection is error'd out.
320 * We work off the IP address and/or reverse DNS. The IP address is
321 * checked first, followed by the IP address at various levels of granularity,
322 * followed by the full domain name and domain names at various levels of
325 * /etc/hammer2/remote/<name>.pub - Contains a public key
326 * /etc/hammer2/remote/<name>.none - Indicates no encryption (empty file)
327 * (e.g. localhost.none).
329 * We first attempt to locate a public key file based on the peer address or
332 * <name>.none - No further negotiation is needed. We simply return.
333 * All communication proceeds without encryption.
334 * No public key handshake occurs in this situation.
335 * (both ends must match).
337 * <name>.pub - We have located the public key for the peer. Both
338 * sides transmit a block encrypted with their private
339 * keys and the peer's public key.
341 * Both sides receive a block and decrypt it.
343 * Both sides formulate a reply using the decrypted
344 * block and transmit it.
346 * communication proceeds with the negotiated session
347 * key (typically AES-256-CBC).
349 * If we fail to locate the appropriate file and no floating.db exists the
350 * connection is terminated without further action.
352 * If floating.db exists the connection proceeds with a floating negotiation.
356 struct sockaddr_in sa_in;
357 struct sockaddr_in6 sa_in6;
361 hammer2_crypto_negotiate(hammer2_iocom_t *iocom)
364 socklen_t salen = sizeof(sa);
367 hammer2_handshake_t handtx;
368 hammer2_handshake_t handrx;
369 char buf1[sizeof(handtx)];
370 char buf2[sizeof(handtx)];
375 RSA *keys[3] = { NULL, NULL, NULL };
384 * Get the peer IP address for the connection as a string.
386 if (getpeername(iocom->sock_fd, &sa.sa, &salen) < 0) {
387 iocom->ioq_rx.error = HAMMER2_IOQ_ERROR_NOPEER;
388 iocom->flags |= HAMMER2_IOCOMF_EOF;
390 fprintf(stderr, "accept: getpeername() failed\n");
393 if (getnameinfo(&sa.sa, salen, peername, sizeof(peername),
394 NULL, 0, NI_NUMERICHOST) < 0) {
395 iocom->ioq_rx.error = HAMMER2_IOQ_ERROR_NOPEER;
396 iocom->flags |= HAMMER2_IOCOMF_EOF;
398 fprintf(stderr, "accept: cannot decode sockaddr\n");
402 if (realhostname_sa(realname, sizeof(realname),
403 &sa.sa, salen) == HOSTNAME_FOUND) {
404 fprintf(stderr, "accept from %s (%s)\n",
407 fprintf(stderr, "accept from %s\n", peername);
412 * Find the remote host's public key
414 * If the link is not to be encrypted (<ip>.none located) we shortcut
415 * the handshake entirely. No buffers are exchanged.
417 asprintf(&path, "%s/%s.pub", HAMMER2_PATH_REMOTE, peername);
418 if ((fp = fopen(path, "r")) == NULL) {
420 asprintf(&path, "%s/%s.none",
421 HAMMER2_PATH_REMOTE, peername);
422 if (stat(path, &st) < 0) {
423 iocom->ioq_rx.error = HAMMER2_IOQ_ERROR_NORKEY;
424 iocom->flags |= HAMMER2_IOCOMF_EOF;
426 fprintf(stderr, "auth failure: unknown host\n");
430 fprintf(stderr, "auth succeeded, unencrypted link\n");
434 keys[0] = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL);
436 if (keys[0] == NULL) {
437 iocom->ioq_rx.error = HAMMER2_IOQ_ERROR_KEYFMT;
438 iocom->flags |= HAMMER2_IOCOMF_EOF;
441 "auth failure: bad key format\n");
447 * Get our public and private keys
450 asprintf(&path, HAMMER2_DEFAULT_DIR "/rsa.pub");
451 if ((fp = fopen(path, "r")) == NULL) {
452 iocom->ioq_rx.error = HAMMER2_IOQ_ERROR_NOLKEY;
453 iocom->flags |= HAMMER2_IOCOMF_EOF;
456 keys[1] = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL);
458 if (keys[1] == NULL) {
459 iocom->ioq_rx.error = HAMMER2_IOQ_ERROR_KEYFMT;
460 iocom->flags |= HAMMER2_IOCOMF_EOF;
462 fprintf(stderr, "auth failure: bad host key format\n");
467 asprintf(&path, HAMMER2_DEFAULT_DIR "/rsa.prv");
468 if ((fp = fopen(path, "r")) == NULL) {
469 iocom->ioq_rx.error = HAMMER2_IOQ_ERROR_NOLKEY;
470 iocom->flags |= HAMMER2_IOCOMF_EOF;
472 fprintf(stderr, "auth failure: bad host key format\n");
475 keys[2] = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
477 if (keys[2] == NULL) {
478 iocom->ioq_rx.error = HAMMER2_IOQ_ERROR_KEYFMT;
479 iocom->flags |= HAMMER2_IOCOMF_EOF;
481 fprintf(stderr, "auth failure: bad host key format\n");
488 * public key encrypt/decrypt block size.
491 blksize = (size_t)RSA_size(keys[0]);
492 if (blksize != (size_t)RSA_size(keys[1]) ||
493 blksize != (size_t)RSA_size(keys[2]) ||
494 sizeof(handtx) % blksize != 0) {
495 iocom->ioq_rx.error = HAMMER2_IOQ_ERROR_KEYFMT;
496 iocom->flags |= HAMMER2_IOCOMF_EOF;
498 fprintf(stderr, "auth failure: "
499 "key size mismatch\n");
503 blksize = sizeof(handtx);
505 blkmask = blksize - 1;
507 bzero(&handrx, sizeof(handrx));
508 bzero(&handtx, sizeof(handtx));
511 * Fill all unused fields (particular all junk fields) with random
512 * data, and also set the session key.
514 fd = open("/dev/urandom", O_RDONLY);
516 fstat(fd, &st) < 0 || /* something wrong */
517 S_ISREG(st.st_mode) || /* supposed to be a RNG dev! */
518 read(fd, &handtx, sizeof(handtx)) != sizeof(handtx)) {
522 iocom->ioq_rx.error = HAMMER2_IOQ_ERROR_BADURANDOM;
523 iocom->flags |= HAMMER2_IOCOMF_EOF;
525 fprintf(stderr, "auth failure: bad rng\n");
528 if (bcmp(&handrx, &handtx, sizeof(handtx)) == 0)
529 goto urandfail; /* read all zeros */
531 /* ERR_load_crypto_strings(); openssl debugging */
534 * Handshake with the remote.
536 * Encrypt with my private and remote's public
537 * Decrypt with my private and remote's public
539 * When encrypting we have to make sure our buffer fits within the
540 * modulus, which typically requires bit 7 o the first byte to be
541 * zero. To be safe make sure that bit 7 and bit 6 is zero.
543 snprintf(handtx.quickmsg, sizeof(handtx.quickmsg), "Testing 1 2 3");
544 handtx.magic = HAMMER2_MSGHDR_MAGIC;
547 assert(sizeof(handtx.verf) * 4 == sizeof(handtx.sess));
548 bzero(handtx.verf, sizeof(handtx.verf));
550 handtx.pad1[0] &= 0x3f; /* message must fit within modulus */
551 handtx.pad2[0] &= 0x3f; /* message must fit within modulus */
553 for (i = 0; i < sizeof(handtx.sess); ++i)
554 handtx.verf[i / 4] ^= handtx.sess[i];
557 * Write handshake buffer to remote
559 for (i = 0; i < sizeof(handtx); i += blksize) {
560 ptr = (char *)&handtx + i;
563 * Since we are double-encrypting we have to make
564 * sure that the result of the first stage does
565 * not blow out the modulus for the second stage.
567 * The pointer is pointing to the pad*[] area so
568 * we can mess with that until the first stage
573 if (RSA_private_encrypt(blksize, ptr, buf1,
574 keys[2], RSA_NO_PADDING) < 0) {
575 iocom->ioq_rx.error =
576 HAMMER2_IOQ_ERROR_KEYXCHGFAIL;
578 } while (buf1[0] & 0xC0);
580 if (RSA_public_encrypt(blksize, buf1, buf2,
581 keys[0], RSA_NO_PADDING) < 0) {
582 iocom->ioq_rx.error =
583 HAMMER2_IOQ_ERROR_KEYXCHGFAIL;
586 if (write(iocom->sock_fd, buf2, blksize) != (ssize_t)blksize) {
587 fprintf(stderr, "WRITE ERROR\n");
590 if (iocom->ioq_rx.error) {
591 iocom->flags |= HAMMER2_IOCOMF_EOF;
593 fprintf(stderr, "auth failure: key exchange failure "
594 "during encryption\n");
599 * Read handshake buffer from remote
602 while (i < sizeof(handrx)) {
603 ptr = (char *)&handrx + i;
604 n = read(iocom->sock_fd, ptr, blksize - (i & blkmask));
607 ptr -= (i & blkmask);
609 if (keys[0] && (i & blkmask) == 0) {
610 if (RSA_private_decrypt(blksize, ptr, buf1,
611 keys[2], RSA_NO_PADDING) < 0)
612 iocom->ioq_rx.error =
613 HAMMER2_IOQ_ERROR_KEYXCHGFAIL;
614 if (RSA_public_decrypt(blksize, buf1, ptr,
615 keys[0], RSA_NO_PADDING) < 0)
616 iocom->ioq_rx.error =
617 HAMMER2_IOQ_ERROR_KEYXCHGFAIL;
620 if (iocom->ioq_rx.error) {
621 iocom->flags |= HAMMER2_IOCOMF_EOF;
623 fprintf(stderr, "auth failure: key exchange failure "
624 "during decryption\n");
629 * Validate the received data. Try to make this a constant-time
632 if (i != sizeof(handrx)) {
634 iocom->ioq_rx.error = HAMMER2_IOQ_ERROR_KEYXCHGFAIL;
635 iocom->flags |= HAMMER2_IOCOMF_EOF;
637 fprintf(stderr, "auth failure: key exchange failure\n");
641 if (handrx.magic == HAMMER2_MSGHDR_MAGIC_REV) {
642 handrx.version = bswap16(handrx.version);
643 handrx.flags = bswap32(handrx.flags);
645 for (i = 0; i < sizeof(handrx.sess); ++i)
646 handrx.verf[i / 4] ^= handrx.sess[i];
648 for (i = 0; i < sizeof(handrx.verf); ++i)
650 if (handrx.version != 1)
655 assert(HAMMER2_AES_KEY_SIZE * 2 == sizeof(handrx.sess));
657 * Use separate session keys and session fixed IVs for receive and
660 error = _gcm_init(&iocom->ioq_rx, handrx.sess, HAMMER2_AES_KEY_SIZE,
661 handrx.sess + HAMMER2_AES_KEY_SIZE,
662 sizeof(handrx.sess) - HAMMER2_AES_KEY_SIZE,
667 error = _gcm_init(&iocom->ioq_tx, handtx.sess, HAMMER2_AES_KEY_SIZE,
668 handtx.sess + HAMMER2_AES_KEY_SIZE,
669 sizeof(handtx.sess) - HAMMER2_AES_KEY_SIZE,
674 iocom->flags |= HAMMER2_IOCOMF_CRYPTED;
677 fprintf(stderr, "auth success: %s\n", handrx.quickmsg);
690 * Decrypt pending data in the ioq's fifo. The data is decrypted in-place.
693 hammer2_crypto_decrypt(hammer2_iocom_t *iocom __unused, hammer2_ioq_t *ioq)
701 * fifo_beg to fifo_cdx is data already decrypted.
702 * fifo_cdn to fifo_end is data not yet decrypted.
704 p_len = ioq->fifo_end - ioq->fifo_cdn; /* data not yet decrypted */
709 while (p_len >= HAMMER2_CRYPTO_TAG_SIZE + HAMMER2_CRYPTO_CHUNK_SIZE) {
710 bcopy(ioq->buf + ioq->fifo_cdn, buf,
711 HAMMER2_CRYPTO_TAG_SIZE + HAMMER2_CRYPTO_CHUNK_SIZE);
712 error = hammer2_crypto_decrypt_chunk(ioq, buf,
713 ioq->buf + ioq->fifo_cdx,
714 HAMMER2_CRYPTO_CHUNK_SIZE,
717 printf("dec: p_len: %d, used: %d, fifo_cdn: %ju, fifo_cdx: %ju\n",
718 p_len, used, ioq->fifo_cdn, ioq->fifo_cdx);
721 ioq->fifo_cdn += used;
722 ioq->fifo_cdx += HAMMER2_CRYPTO_CHUNK_SIZE;
724 printf("dec: p_len: %d, used: %d, fifo_cdn: %ju, fifo_cdx: %ju\n",
725 p_len, used, ioq->fifo_cdn, ioq->fifo_cdx);
731 * *nactp is set to the number of ORIGINAL bytes consumed by the encrypter.
732 * The FIFO may contain more data.
735 hammer2_crypto_encrypt(hammer2_iocom_t *iocom __unused, hammer2_ioq_t *ioq,
736 struct iovec *iov, int n, size_t *nactp)
738 int p_len, used, ct_used;
743 nmax = sizeof(ioq->buf) - ioq->fifo_end; /* max new bytes */
746 for (i = 0; i < n && nmax; ++i) {
748 p_len = iov[i].iov_len;
749 assert((p_len & HAMMER2_AES_KEY_MASK) == 0);
751 while (p_len >= HAMMER2_CRYPTO_CHUNK_SIZE &&
752 nmax >= HAMMER2_CRYPTO_CHUNK_SIZE + HAMMER2_CRYPTO_TAG_SIZE) {
753 error = hammer2_crypto_encrypt_chunk(ioq,
754 ioq->buf + ioq->fifo_cdx,
755 (char *)iov[i].iov_base + used,
756 HAMMER2_CRYPTO_CHUNK_SIZE, &ct_used);
758 printf("nactp: %ju, p_len: %d, ct_used: %d, used: %d, nmax: %ju\n",
759 *nactp, p_len, ct_used, used, nmax);
762 *nactp += (size_t)HAMMER2_CRYPTO_CHUNK_SIZE; /* plaintext count */
763 used += HAMMER2_CRYPTO_CHUNK_SIZE;
764 p_len -= HAMMER2_CRYPTO_CHUNK_SIZE;
766 ioq->fifo_cdx += (size_t)ct_used; /* crypted count */
767 ioq->fifo_cdn += (size_t)ct_used; /* crypted count */
768 ioq->fifo_end += (size_t)ct_used;
769 nmax -= (size_t)ct_used;
771 printf("nactp: %ju, p_len: %d, ct_used: %d, used: %d, nmax: %ju\n",
772 *nactp, p_len, ct_used, used, nmax);
776 iov[0].iov_base = ioq->buf + ioq->fifo_beg;
777 iov[0].iov_len = ioq->fifo_cdx - ioq->fifo_beg;