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 * Synchronously negotiate crypto for a new session. This must occur
40 * within 10 seconds or the connection is error'd out.
42 * We work off the IP address and/or reverse DNS. The IP address is
43 * checked first, followed by the IP address at various levels of granularity,
44 * followed by the full domain name and domain names at various levels of
47 * /etc/hammer2/remote/<name>.pub - Contains a public key
48 * /etc/hammer2/remote/<name>.none - Indicates no encryption (empty file)
49 * (e.g. localhost.none).
51 * We first attempt to locate a public key file based on the peer address or
54 * <name>.none - No further negotiation is needed. We simply return.
55 * All communication proceeds without encryption.
56 * No public key handshake occurs in this situation.
57 * (both ends must match).
59 * <name>.pub - We have located the public key for the peer. Both
60 * sides transmit a block encrypted with their private
61 * keys and the peer's public key.
63 * Both sides receive a block and decrypt it.
65 * Both sides formulate a reply using the decrypted
66 * block and transmit it.
68 * communication proceeds with the negotiated session
69 * key (typically AES-256-CBC).
71 * If we fail to locate the appropriate file and no floating.db exists the
72 * connection is terminated without further action.
74 * If floating.db exists the connection proceeds with a floating negotiation.
78 struct sockaddr_in sa_in;
79 struct sockaddr_in6 sa_in6;
83 hammer2_crypto_negotiate(hammer2_iocom_t *iocom)
86 socklen_t salen = sizeof(sa);
89 hammer2_handshake_t handtx;
90 hammer2_handshake_t handrx;
91 char buf1[sizeof(handtx)];
92 char buf2[sizeof(handtx)];
97 RSA *keys[3] = { NULL, NULL, NULL };
105 * Get the peer IP address for the connection as a string.
107 if (getpeername(iocom->sock_fd, &sa.sa, &salen) < 0) {
108 iocom->ioq_rx.error = HAMMER2_IOQ_ERROR_NOPEER;
109 iocom->flags |= HAMMER2_IOCOMF_EOF;
111 fprintf(stderr, "accept: getpeername() failed\n");
114 if (getnameinfo(&sa.sa, salen, peername, sizeof(peername),
115 NULL, 0, NI_NUMERICHOST) < 0) {
116 iocom->ioq_rx.error = HAMMER2_IOQ_ERROR_NOPEER;
117 iocom->flags |= HAMMER2_IOCOMF_EOF;
119 fprintf(stderr, "accept: cannot decode sockaddr\n");
123 if (realhostname_sa(realname, sizeof(realname),
124 &sa.sa, salen) == HOSTNAME_FOUND) {
125 fprintf(stderr, "accept from %s (%s)\n",
128 fprintf(stderr, "accept from %s\n", peername);
133 * Find the remote host's public key
135 asprintf(&path, "%s/%s.pub", HAMMER2_PATH_REMOTE, peername);
136 if ((fp = fopen(path, "r")) == NULL) {
138 asprintf(&path, "%s/%s.none",
139 HAMMER2_PATH_REMOTE, peername);
140 if (stat(path, &st) < 0) {
141 iocom->ioq_rx.error = HAMMER2_IOQ_ERROR_NORKEY;
142 iocom->flags |= HAMMER2_IOCOMF_EOF;
144 fprintf(stderr, "auth failure: unknown host\n");
148 fprintf(stderr, "auth succeeded, unencrypted link\n");
151 keys[0] = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL);
153 if (keys[0] == NULL) {
154 iocom->ioq_rx.error = HAMMER2_IOQ_ERROR_KEYFMT;
155 iocom->flags |= HAMMER2_IOCOMF_EOF;
158 "auth failure: bad key format\n");
164 * Get our public and private keys
167 asprintf(&path, HAMMER2_DEFAULT_DIR "/rsa.pub");
168 if ((fp = fopen(path, "r")) == NULL) {
169 iocom->ioq_rx.error = HAMMER2_IOQ_ERROR_NOLKEY;
170 iocom->flags |= HAMMER2_IOCOMF_EOF;
173 keys[1] = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL);
175 if (keys[1] == NULL) {
176 iocom->ioq_rx.error = HAMMER2_IOQ_ERROR_KEYFMT;
177 iocom->flags |= HAMMER2_IOCOMF_EOF;
179 fprintf(stderr, "auth failure: bad host key format\n");
184 asprintf(&path, HAMMER2_DEFAULT_DIR "/rsa.prv");
185 if ((fp = fopen(path, "r")) == NULL) {
186 iocom->ioq_rx.error = HAMMER2_IOQ_ERROR_NOLKEY;
187 iocom->flags |= HAMMER2_IOCOMF_EOF;
189 fprintf(stderr, "auth failure: bad host key format\n");
192 keys[2] = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
194 if (keys[2] == NULL) {
195 iocom->ioq_rx.error = HAMMER2_IOQ_ERROR_KEYFMT;
196 iocom->flags |= HAMMER2_IOCOMF_EOF;
198 fprintf(stderr, "auth failure: bad host key format\n");
205 * public key encrypt/decrypt block size.
208 blksize = (size_t)RSA_size(keys[0]);
209 if (blksize != (size_t)RSA_size(keys[1]) ||
210 blksize != (size_t)RSA_size(keys[2]) ||
211 sizeof(handtx) % blksize != 0) {
212 iocom->ioq_rx.error = HAMMER2_IOQ_ERROR_KEYFMT;
213 iocom->flags |= HAMMER2_IOCOMF_EOF;
215 fprintf(stderr, "auth failure: "
216 "key size mismatch\n");
220 blksize = sizeof(handtx);
222 blkmask = blksize - 1;
224 bzero(&handrx, sizeof(handrx));
225 bzero(&handtx, sizeof(handtx));
228 * Fill all unused fields (particular all junk fields) with random
229 * data, and also set the session key.
231 fd = open("/dev/urandom", O_RDONLY);
233 fstat(fd, &st) < 0 || /* something wrong */
234 S_ISREG(st.st_mode) || /* supposed to be a RNG dev! */
235 read(fd, &handtx, sizeof(handtx)) != sizeof(handtx)) {
239 iocom->ioq_rx.error = HAMMER2_IOQ_ERROR_BADURANDOM;
240 iocom->flags |= HAMMER2_IOCOMF_EOF;
242 fprintf(stderr, "auth failure: bad rng\n");
245 if (bcmp(&handrx, &handtx, sizeof(handtx)) == 0)
246 goto urandfail; /* read all zeros */
248 /* ERR_load_crypto_strings(); openssl debugging */
251 * Handshake with the remote.
253 * Encrypt with my private and remote's public
254 * Decrypt with my private and remote's public
256 * When encrypting we have to make sure our buffer fits within the
257 * modulus, which typically requires bit 7 o the first byte to be
258 * zero. To be safe make sure that bit 7 and bit 6 is zero.
260 snprintf(handtx.quickmsg, sizeof(handtx.quickmsg), "Testing 1 2 3");
261 handtx.magic = HAMMER2_MSGHDR_MAGIC;
264 assert(sizeof(handtx.verf) * 4 == sizeof(handtx.sess));
265 bzero(handtx.verf, sizeof(handtx.verf));
267 handtx.pad1[0] &= 0x3f; /* message must fit within modulus */
268 handtx.pad2[0] &= 0x3f; /* message must fit within modulus */
270 for (i = 0; i < sizeof(handtx.sess); ++i)
271 handtx.verf[i / 4] ^= handtx.sess[i];
274 * Write handshake buffer to remote
276 for (i = 0; i < sizeof(handtx); i += blksize) {
277 ptr = (char *)&handtx + i;
280 * Since we are double-encrypting we have to make
281 * sure that the result of the first stage does
282 * not blow out the modulus for the second stage.
284 * The pointer is pointing to the pad*[] area so
285 * we can mess with that until the first stage
290 if (RSA_private_encrypt(blksize, ptr, buf1,
291 keys[2], RSA_NO_PADDING) < 0) {
292 iocom->ioq_rx.error =
293 HAMMER2_IOQ_ERROR_KEYXCHGFAIL;
295 } while (buf1[0] & 0xC0);
297 if (RSA_public_encrypt(blksize, buf1, buf2,
298 keys[0], RSA_NO_PADDING) < 0) {
299 iocom->ioq_rx.error =
300 HAMMER2_IOQ_ERROR_KEYXCHGFAIL;
303 if (write(iocom->sock_fd, buf2, blksize) != (ssize_t)blksize) {
304 fprintf(stderr, "WRITE ERROR\n");
307 if (iocom->ioq_rx.error) {
308 iocom->flags |= HAMMER2_IOCOMF_EOF;
310 fprintf(stderr, "auth failure: key exchange failure "
311 "during encryption\n");
316 * Read handshake buffer from remote
319 while (i < sizeof(handrx)) {
320 ptr = (char *)&handrx + i;
321 n = read(iocom->sock_fd, ptr, blksize - (i & blkmask));
324 ptr -= (i & blkmask);
326 if (keys[0] && (i & blkmask) == 0) {
327 if (RSA_private_decrypt(blksize, ptr, buf1,
328 keys[2], RSA_NO_PADDING) < 0)
329 iocom->ioq_rx.error =
330 HAMMER2_IOQ_ERROR_KEYXCHGFAIL;
331 if (RSA_public_decrypt(blksize, buf1, ptr,
332 keys[0], RSA_NO_PADDING) < 0)
333 iocom->ioq_rx.error =
334 HAMMER2_IOQ_ERROR_KEYXCHGFAIL;
337 if (iocom->ioq_rx.error) {
338 iocom->flags |= HAMMER2_IOCOMF_EOF;
340 fprintf(stderr, "auth failure: key exchange failure "
341 "during decryption\n");
346 * Validate the received data. Try to make this a constant-time
349 if (i != sizeof(handrx)) {
351 iocom->ioq_rx.error = HAMMER2_IOQ_ERROR_KEYXCHGFAIL;
352 iocom->flags |= HAMMER2_IOCOMF_EOF;
354 fprintf(stderr, "auth failure: key exchange failure\n");
358 if (handrx.magic == HAMMER2_MSGHDR_MAGIC_REV) {
359 handrx.version = bswap16(handrx.version);
360 handrx.flags = bswap32(handrx.flags);
362 for (i = 0; i < sizeof(handrx.sess); ++i)
363 handrx.verf[i / 4] ^= handrx.sess[i];
365 for (i = 0; i < sizeof(handrx.verf); ++i)
367 if (handrx.version != 1)
373 * Calculate the session key and initialize the iv[].
375 assert(HAMMER2_AES_KEY_SIZE * 2 == sizeof(handrx.sess));
376 for (i = 0; i < HAMMER2_AES_KEY_SIZE; ++i) {
377 iocom->sess[i] = handrx.sess[i] ^ handtx.sess[i];
378 iocom->ioq_rx.iv[i] = handrx.sess[HAMMER2_AES_KEY_SIZE + i] ^
379 handtx.sess[HAMMER2_AES_KEY_SIZE + i];
380 iocom->ioq_tx.iv[i] = handrx.sess[HAMMER2_AES_KEY_SIZE + i] ^
381 handtx.sess[HAMMER2_AES_KEY_SIZE + i];
384 for (i = 0; i < HAMMER2_AES_KEY_SIZE; ++i)
385 printf("%02x", (unsigned char)iocom->sess[i]);
388 for (i = 0; i < HAMMER2_AES_KEY_SIZE; ++i)
389 printf("%02x", (unsigned char)iocom->ioq_rx.iv[i]);
392 EVP_CIPHER_CTX_init(&iocom->ioq_rx.ctx);
393 EVP_DecryptInit_ex(&iocom->ioq_rx.ctx, HAMMER2_AES_TYPE_EVP, NULL,
394 iocom->sess, iocom->ioq_rx.iv);
395 EVP_CIPHER_CTX_set_padding(&iocom->ioq_rx.ctx, 0);
397 EVP_CIPHER_CTX_init(&iocom->ioq_tx.ctx);
398 EVP_EncryptInit_ex(&iocom->ioq_tx.ctx, HAMMER2_AES_TYPE_EVP, NULL,
399 iocom->sess, iocom->ioq_tx.iv);
400 EVP_CIPHER_CTX_set_padding(&iocom->ioq_tx.ctx, 0);
402 iocom->flags |= HAMMER2_IOCOMF_CRYPTED;
405 fprintf(stderr, "auth success: %s\n", handrx.quickmsg);
418 * Decrypt pending data in the ioq's fifo. The data is decrypted in-place.
421 hammer2_crypto_decrypt(hammer2_iocom_t *iocom, hammer2_ioq_t *ioq)
428 if ((iocom->flags & HAMMER2_IOCOMF_CRYPTED) == 0)
430 p_len = ioq->fifo_end - ioq->fifo_cdx;
431 p_len &= ~HAMMER2_AES_KEY_MASK;
434 for (i = 0; i < p_len; i += n) {
435 n = (p_len - i > (int)sizeof(buf)) ?
436 (int)sizeof(buf) : p_len - i;
437 bcopy(ioq->buf + ioq->fifo_cdx + i, buf, n);
438 EVP_DecryptUpdate(&ioq->ctx,
439 ioq->buf + ioq->fifo_cdx + i, &n,
442 ioq->fifo_cdx += p_len;
446 * Decrypt data in the message's auxilary buffer. The data is decrypted
450 hammer2_crypto_decrypt_aux(hammer2_iocom_t *iocom, hammer2_ioq_t *ioq,
451 hammer2_msg_t *msg, int already)
458 if ((iocom->flags & HAMMER2_IOCOMF_CRYPTED) == 0)
460 p_len = msg->aux_size;
461 assert((p_len & HAMMER2_AES_KEY_MASK) == 0);
466 n = (p_len - i > (int)sizeof(buf)) ?
467 (int)sizeof(buf) : p_len - i;
468 bcopy(msg->aux_data + i, buf, n);
469 EVP_DecryptUpdate(&ioq->ctx,
470 msg->aux_data + i, &n,
475 EVP_DecryptUpdate(&iocom->ioq_rx.ctx,
476 msg->aux_data, &p_len,
477 msg->aux_data, p_len);
482 hammer2_crypto_encrypt(hammer2_iocom_t *iocom, hammer2_ioq_t *ioq,
483 struct iovec *iov, int n)
490 if ((iocom->flags & HAMMER2_IOCOMF_CRYPTED) == 0)
492 nmax = sizeof(ioq->buf) - ioq->fifo_cdx; /* max new bytes */
493 already = ioq->fifo_cdx - ioq->fifo_beg; /* already encrypted */
495 for (i = 0; i < n; ++i) {
496 p_len = iov[i].iov_len;
497 if (p_len <= already) {
504 EVP_EncryptUpdate(&ioq->ctx,
505 ioq->buf + ioq->fifo_cdx, &p_len,
506 (char *)iov[i].iov_base + already, p_len);
507 ioq->fifo_cdx += p_len;
508 ioq->fifo_end += p_len;
514 iov[0].iov_base = ioq->buf + ioq->fifo_beg;
515 iov[0].iov_len = ioq->fifo_cdx - ioq->fifo_beg;
521 hammer2_crypto_encrypt_wrote(hammer2_iocom_t *iocom, hammer2_ioq_t *ioq,
524 if ((iocom->flags & HAMMER2_IOCOMF_CRYPTED) == 0)
528 ioq->fifo_beg += nact;
529 if (ioq->fifo_beg == ioq->fifo_end) {