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>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
18 * 3. Neither the name of The DragonFly Project nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific, prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * Setup crypto for pthreads
41 static pthread_mutex_t *crypto_locks;
46 hammer2_crypto_id_callback(void)
48 return ((unsigned long)(uintptr_t)pthread_self());
53 hammer2_crypto_locking_callback(int mode, int type,
54 const char *file __unused, int line __unused)
56 assert(type >= 0 && type < crypto_count);
57 if (mode & CRYPTO_LOCK) {
58 pthread_mutex_lock(&crypto_locks[type]);
60 pthread_mutex_unlock(&crypto_locks[type]);
65 hammer2_crypto_setup(void)
67 crypto_count = CRYPTO_num_locks();
68 crypto_locks = calloc(crypto_count, sizeof(crypto_locks[0]));
69 CRYPTO_set_id_callback(hammer2_crypto_id_callback);
70 CRYPTO_set_locking_callback(hammer2_crypto_locking_callback);
74 * Synchronously negotiate crypto for a new session. This must occur
75 * within 10 seconds or the connection is error'd out.
77 * We work off the IP address and/or reverse DNS. The IP address is
78 * checked first, followed by the IP address at various levels of granularity,
79 * followed by the full domain name and domain names at various levels of
82 * /etc/hammer2/remote/<name>.pub - Contains a public key
83 * /etc/hammer2/remote/<name>.none - Indicates no encryption (empty file)
84 * (e.g. localhost.none).
86 * We first attempt to locate a public key file based on the peer address or
89 * <name>.none - No further negotiation is needed. We simply return.
90 * All communication proceeds without encryption.
91 * No public key handshake occurs in this situation.
92 * (both ends must match).
94 * <name>.pub - We have located the public key for the peer. Both
95 * sides transmit a block encrypted with their private
96 * keys and the peer's public key.
98 * Both sides receive a block and decrypt it.
100 * Both sides formulate a reply using the decrypted
101 * block and transmit it.
103 * communication proceeds with the negotiated session
104 * key (typically AES-256-CBC).
106 * If we fail to locate the appropriate file and no floating.db exists the
107 * connection is terminated without further action.
109 * If floating.db exists the connection proceeds with a floating negotiation.
113 struct sockaddr_in sa_in;
114 struct sockaddr_in6 sa_in6;
118 hammer2_crypto_negotiate(hammer2_iocom_t *iocom)
121 socklen_t salen = sizeof(sa);
124 hammer2_handshake_t handtx;
125 hammer2_handshake_t handrx;
126 char buf1[sizeof(handtx)];
127 char buf2[sizeof(handtx)];
132 RSA *keys[3] = { NULL, NULL, NULL };
140 * Get the peer IP address for the connection as a string.
142 if (getpeername(iocom->sock_fd, &sa.sa, &salen) < 0) {
143 iocom->ioq_rx.error = HAMMER2_IOQ_ERROR_NOPEER;
144 iocom->flags |= HAMMER2_IOCOMF_EOF;
146 fprintf(stderr, "accept: getpeername() failed\n");
149 if (getnameinfo(&sa.sa, salen, peername, sizeof(peername),
150 NULL, 0, NI_NUMERICHOST) < 0) {
151 iocom->ioq_rx.error = HAMMER2_IOQ_ERROR_NOPEER;
152 iocom->flags |= HAMMER2_IOCOMF_EOF;
154 fprintf(stderr, "accept: cannot decode sockaddr\n");
158 if (realhostname_sa(realname, sizeof(realname),
159 &sa.sa, salen) == HOSTNAME_FOUND) {
160 fprintf(stderr, "accept from %s (%s)\n",
163 fprintf(stderr, "accept from %s\n", peername);
168 * Find the remote host's public key
170 * If the link is not to be encrypted (<ip>.none located) we shortcut
171 * the handshake entirely. No buffers are exchanged.
173 asprintf(&path, "%s/%s.pub", HAMMER2_PATH_REMOTE, peername);
174 if ((fp = fopen(path, "r")) == NULL) {
176 asprintf(&path, "%s/%s.none",
177 HAMMER2_PATH_REMOTE, peername);
178 if (stat(path, &st) < 0) {
179 iocom->ioq_rx.error = HAMMER2_IOQ_ERROR_NORKEY;
180 iocom->flags |= HAMMER2_IOCOMF_EOF;
182 fprintf(stderr, "auth failure: unknown host\n");
186 fprintf(stderr, "auth succeeded, unencrypted link\n");
190 keys[0] = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL);
192 if (keys[0] == NULL) {
193 iocom->ioq_rx.error = HAMMER2_IOQ_ERROR_KEYFMT;
194 iocom->flags |= HAMMER2_IOCOMF_EOF;
197 "auth failure: bad key format\n");
203 * Get our public and private keys
206 asprintf(&path, HAMMER2_DEFAULT_DIR "/rsa.pub");
207 if ((fp = fopen(path, "r")) == NULL) {
208 iocom->ioq_rx.error = HAMMER2_IOQ_ERROR_NOLKEY;
209 iocom->flags |= HAMMER2_IOCOMF_EOF;
212 keys[1] = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL);
214 if (keys[1] == NULL) {
215 iocom->ioq_rx.error = HAMMER2_IOQ_ERROR_KEYFMT;
216 iocom->flags |= HAMMER2_IOCOMF_EOF;
218 fprintf(stderr, "auth failure: bad host key format\n");
223 asprintf(&path, HAMMER2_DEFAULT_DIR "/rsa.prv");
224 if ((fp = fopen(path, "r")) == NULL) {
225 iocom->ioq_rx.error = HAMMER2_IOQ_ERROR_NOLKEY;
226 iocom->flags |= HAMMER2_IOCOMF_EOF;
228 fprintf(stderr, "auth failure: bad host key format\n");
231 keys[2] = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
233 if (keys[2] == NULL) {
234 iocom->ioq_rx.error = HAMMER2_IOQ_ERROR_KEYFMT;
235 iocom->flags |= HAMMER2_IOCOMF_EOF;
237 fprintf(stderr, "auth failure: bad host key format\n");
244 * public key encrypt/decrypt block size.
247 blksize = (size_t)RSA_size(keys[0]);
248 if (blksize != (size_t)RSA_size(keys[1]) ||
249 blksize != (size_t)RSA_size(keys[2]) ||
250 sizeof(handtx) % blksize != 0) {
251 iocom->ioq_rx.error = HAMMER2_IOQ_ERROR_KEYFMT;
252 iocom->flags |= HAMMER2_IOCOMF_EOF;
254 fprintf(stderr, "auth failure: "
255 "key size mismatch\n");
259 blksize = sizeof(handtx);
261 blkmask = blksize - 1;
263 bzero(&handrx, sizeof(handrx));
264 bzero(&handtx, sizeof(handtx));
267 * Fill all unused fields (particular all junk fields) with random
268 * data, and also set the session key.
270 fd = open("/dev/urandom", O_RDONLY);
272 fstat(fd, &st) < 0 || /* something wrong */
273 S_ISREG(st.st_mode) || /* supposed to be a RNG dev! */
274 read(fd, &handtx, sizeof(handtx)) != sizeof(handtx)) {
278 iocom->ioq_rx.error = HAMMER2_IOQ_ERROR_BADURANDOM;
279 iocom->flags |= HAMMER2_IOCOMF_EOF;
281 fprintf(stderr, "auth failure: bad rng\n");
284 if (bcmp(&handrx, &handtx, sizeof(handtx)) == 0)
285 goto urandfail; /* read all zeros */
287 /* ERR_load_crypto_strings(); openssl debugging */
290 * Handshake with the remote.
292 * Encrypt with my private and remote's public
293 * Decrypt with my private and remote's public
295 * When encrypting we have to make sure our buffer fits within the
296 * modulus, which typically requires bit 7 o the first byte to be
297 * zero. To be safe make sure that bit 7 and bit 6 is zero.
299 snprintf(handtx.quickmsg, sizeof(handtx.quickmsg), "Testing 1 2 3");
300 handtx.magic = HAMMER2_MSGHDR_MAGIC;
303 assert(sizeof(handtx.verf) * 4 == sizeof(handtx.sess));
304 bzero(handtx.verf, sizeof(handtx.verf));
306 handtx.pad1[0] &= 0x3f; /* message must fit within modulus */
307 handtx.pad2[0] &= 0x3f; /* message must fit within modulus */
309 for (i = 0; i < sizeof(handtx.sess); ++i)
310 handtx.verf[i / 4] ^= handtx.sess[i];
313 * Write handshake buffer to remote
315 for (i = 0; i < sizeof(handtx); i += blksize) {
316 ptr = (char *)&handtx + i;
319 * Since we are double-encrypting we have to make
320 * sure that the result of the first stage does
321 * not blow out the modulus for the second stage.
323 * The pointer is pointing to the pad*[] area so
324 * we can mess with that until the first stage
329 if (RSA_private_encrypt(blksize, ptr, buf1,
330 keys[2], RSA_NO_PADDING) < 0) {
331 iocom->ioq_rx.error =
332 HAMMER2_IOQ_ERROR_KEYXCHGFAIL;
334 } while (buf1[0] & 0xC0);
336 if (RSA_public_encrypt(blksize, buf1, buf2,
337 keys[0], RSA_NO_PADDING) < 0) {
338 iocom->ioq_rx.error =
339 HAMMER2_IOQ_ERROR_KEYXCHGFAIL;
342 if (write(iocom->sock_fd, buf2, blksize) != (ssize_t)blksize) {
343 fprintf(stderr, "WRITE ERROR\n");
346 if (iocom->ioq_rx.error) {
347 iocom->flags |= HAMMER2_IOCOMF_EOF;
349 fprintf(stderr, "auth failure: key exchange failure "
350 "during encryption\n");
355 * Read handshake buffer from remote
358 while (i < sizeof(handrx)) {
359 ptr = (char *)&handrx + i;
360 n = read(iocom->sock_fd, ptr, blksize - (i & blkmask));
363 ptr -= (i & blkmask);
365 if (keys[0] && (i & blkmask) == 0) {
366 if (RSA_private_decrypt(blksize, ptr, buf1,
367 keys[2], RSA_NO_PADDING) < 0)
368 iocom->ioq_rx.error =
369 HAMMER2_IOQ_ERROR_KEYXCHGFAIL;
370 if (RSA_public_decrypt(blksize, buf1, ptr,
371 keys[0], RSA_NO_PADDING) < 0)
372 iocom->ioq_rx.error =
373 HAMMER2_IOQ_ERROR_KEYXCHGFAIL;
376 if (iocom->ioq_rx.error) {
377 iocom->flags |= HAMMER2_IOCOMF_EOF;
379 fprintf(stderr, "auth failure: key exchange failure "
380 "during decryption\n");
385 * Validate the received data. Try to make this a constant-time
388 if (i != sizeof(handrx)) {
390 iocom->ioq_rx.error = HAMMER2_IOQ_ERROR_KEYXCHGFAIL;
391 iocom->flags |= HAMMER2_IOCOMF_EOF;
393 fprintf(stderr, "auth failure: key exchange failure\n");
397 if (handrx.magic == HAMMER2_MSGHDR_MAGIC_REV) {
398 handrx.version = bswap16(handrx.version);
399 handrx.flags = bswap32(handrx.flags);
401 for (i = 0; i < sizeof(handrx.sess); ++i)
402 handrx.verf[i / 4] ^= handrx.sess[i];
404 for (i = 0; i < sizeof(handrx.verf); ++i)
406 if (handrx.version != 1)
412 * Calculate the session key and initialize the iv[].
414 assert(HAMMER2_AES_KEY_SIZE * 2 == sizeof(handrx.sess));
415 for (i = 0; i < HAMMER2_AES_KEY_SIZE; ++i) {
416 iocom->sess[i] = handrx.sess[i] ^ handtx.sess[i];
417 iocom->ioq_rx.iv[i] = handrx.sess[HAMMER2_AES_KEY_SIZE + i] ^
418 handtx.sess[HAMMER2_AES_KEY_SIZE + i];
419 iocom->ioq_tx.iv[i] = handrx.sess[HAMMER2_AES_KEY_SIZE + i] ^
420 handtx.sess[HAMMER2_AES_KEY_SIZE + i];
423 for (i = 0; i < HAMMER2_AES_KEY_SIZE; ++i)
424 printf("%02x", (unsigned char)iocom->sess[i]);
427 for (i = 0; i < HAMMER2_AES_KEY_SIZE; ++i)
428 printf("%02x", (unsigned char)iocom->ioq_rx.iv[i]);
431 EVP_CIPHER_CTX_init(&iocom->ioq_rx.ctx);
432 EVP_DecryptInit_ex(&iocom->ioq_rx.ctx, HAMMER2_AES_TYPE_EVP, NULL,
433 iocom->sess, iocom->ioq_rx.iv);
434 EVP_CIPHER_CTX_set_padding(&iocom->ioq_rx.ctx, 0);
436 EVP_CIPHER_CTX_init(&iocom->ioq_tx.ctx);
437 EVP_EncryptInit_ex(&iocom->ioq_tx.ctx, HAMMER2_AES_TYPE_EVP, NULL,
438 iocom->sess, iocom->ioq_tx.iv);
439 EVP_CIPHER_CTX_set_padding(&iocom->ioq_tx.ctx, 0);
441 iocom->flags |= HAMMER2_IOCOMF_CRYPTED;
444 fprintf(stderr, "auth success: %s\n", handrx.quickmsg);
457 * Decrypt pending data in the ioq's fifo. The data is decrypted in-place.
460 hammer2_crypto_decrypt(hammer2_iocom_t *iocom __unused, hammer2_ioq_t *ioq)
467 p_len = ioq->fifo_end - ioq->fifo_cdn;
468 p_len &= ~HAMMER2_AES_KEY_MASK;
472 for (i = 0; i < p_len; i += n) {
473 n = (p_len - i > (int)sizeof(buf)) ?
474 (int)sizeof(buf) : p_len - i;
475 bcopy(ioq->buf + ioq->fifo_cdx + i, buf, n);
476 EVP_DecryptUpdate(&ioq->ctx,
477 ioq->buf + ioq->fifo_cdx + i, &n,
480 ioq->fifo_cdx += p_len;
481 ioq->fifo_cdn += p_len;
485 * *nactp is set to the number of ORIGINAL bytes consumed by the encrypter.
486 * The FIFO may contain more data.
489 hammer2_crypto_encrypt(hammer2_iocom_t *iocom __unused, hammer2_ioq_t *ioq,
490 struct iovec *iov, int n, size_t *nactp)
496 nmax = sizeof(ioq->buf) - ioq->fifo_end; /* max new bytes */
499 for (i = 0; i < n && nmax; ++i) {
500 p_len = iov[i].iov_len;
501 assert((p_len & HAMMER2_AES_KEY_MASK) == 0);
502 if ((size_t)p_len > nmax)
504 *nactp += (size_t)p_len; /* plaintext count */
505 EVP_EncryptUpdate(&ioq->ctx,
506 ioq->buf + ioq->fifo_cdx, &p_len,
507 (char *)iov[i].iov_base, p_len);
508 assert((size_t)p_len == iov[i].iov_len);
509 ioq->fifo_cdx += (size_t)p_len; /* crypted count */
510 ioq->fifo_cdn += (size_t)p_len; /* crypted count */
511 ioq->fifo_end += (size_t)p_len;
512 nmax -= (size_t)p_len;
516 iov[0].iov_base = ioq->buf + ioq->fifo_beg;
517 iov[0].iov_len = ioq->fifo_cdx - ioq->fifo_beg;