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 key, NULL); 122 else 123 ok = EVP_DecryptInit_ex(&ioq->ctx, EVP_aes_256_gcm(), NULL, 124 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, ioq->iv); 207 if (!ok) 208 goto fail; 209 210 u_len = 0; /* safety */ 211 ok = EVP_EncryptUpdate(&ioq->ctx, ct, &u_len, pt, in_size); 212 if (!ok) 213 goto fail; 214 215 f_len = 0; /* safety */ 216 ok = EVP_EncryptFinal_ex(&ioq->ctx, ct + u_len, &f_len); 217 if (!ok) 218 goto fail; 219 220 /* Retrieve auth tag */ 221 ok = EVP_CIPHER_CTX_ctrl(&ioq->ctx, EVP_CTRL_GCM_GET_TAG, 222 DMSG_CRYPTO_GCM_TAG_SIZE, 223 ct + u_len + f_len); 224 if (!ok) 225 goto fail; 226 227 ok = _gcm_iv_increment(ioq->iv); 228 if (!ok) { 229 ioq->error = DMSG_IOQ_ERROR_IVWRAP; 230 goto fail_out; 231 } 232 233 *out_size = u_len + f_len + DMSG_CRYPTO_GCM_TAG_SIZE; 234 EVP_CIPHER_CTX_reset(&ioq->ctx); 235 236 return 0; 237 238 fail: 239 ioq->error = DMSG_IOQ_ERROR_ALGO; 240 fail_out: 241 EVP_CIPHER_CTX_reset(&ioq->ctx); 242 dm_printf(1, "%s\n", "error during encrypt_chunk"); 243 return -1; 244 } 245 246 static 247 int 248 dmsg_crypto_gcm_decrypt_chunk(dmsg_ioq_t *ioq, char *ct, char *pt, 249 int out_size, int *consume_size) 250 { 251 int ok; 252 int u_len, f_len; 253 254 *consume_size = 0; 255 256 /* Re-initialize with new IV (but without redoing the key schedule) */ 257 ok = EVP_DecryptInit_ex(&ioq->ctx, NULL, NULL, NULL, ioq->iv); 258 if (!ok) { 259 ioq->error = DMSG_IOQ_ERROR_ALGO; 260 goto fail_out; 261 } 262 263 ok = EVP_CIPHER_CTX_ctrl(&ioq->ctx, EVP_CTRL_GCM_SET_TAG, 264 DMSG_CRYPTO_GCM_TAG_SIZE, 265 ct + out_size); 266 if (!ok) { 267 ioq->error = DMSG_IOQ_ERROR_ALGO; 268 goto fail_out; 269 } 270 271 ok = EVP_DecryptUpdate(&ioq->ctx, pt, &u_len, ct, out_size); 272 if (!ok) 273 goto fail; 274 275 ok = EVP_DecryptFinal_ex(&ioq->ctx, pt + u_len, &f_len); 276 if (!ok) 277 goto fail; 278 279 ok = _gcm_iv_increment(ioq->iv); 280 if (!ok) { 281 ioq->error = DMSG_IOQ_ERROR_IVWRAP; 282 goto fail_out; 283 } 284 285 *consume_size = u_len + f_len + DMSG_CRYPTO_GCM_TAG_SIZE; 286 EVP_CIPHER_CTX_reset(&ioq->ctx); 287 288 return 0; 289 290 fail: 291 ioq->error = DMSG_IOQ_ERROR_MACFAIL; 292 fail_out: 293 EVP_CIPHER_CTX_reset(&ioq->ctx); 294 dm_printf(1, "%s\n", 295 "error during decrypt_chunk " 296 "(likely authentication error)"); 297 return -1; 298 } 299 300 /* 301 * Synchronously negotiate crypto for a new session. This must occur 302 * within 10 seconds or the connection is error'd out. 303 * 304 * We work off the IP address and/or reverse DNS. The IP address is 305 * checked first, followed by the IP address at various levels of granularity, 306 * followed by the full domain name and domain names at various levels of 307 * granularity. 308 * 309 * /etc/hammer2/remote/<name>.pub - Contains a public key 310 * /etc/hammer2/remote/<name>.none - Indicates no encryption (empty file) 311 * (e.g. localhost.none). 312 * 313 * We first attempt to locate a public key file based on the peer address or 314 * peer FQDN. 315 * 316 * <name>.none - No further negotiation is needed. We simply return. 317 * All communication proceeds without encryption. 318 * No public key handshake occurs in this situation. 319 * (both ends must match). 320 * 321 * <name>.pub - We have located the public key for the peer. Both 322 * sides transmit a block encrypted with their private 323 * keys and the peer's public key. 324 * 325 * Both sides receive a block and decrypt it. 326 * 327 * Both sides formulate a reply using the decrypted 328 * block and transmit it. 329 * 330 * communication proceeds with the negotiated session 331 * key (typically AES-256-CBC). 332 * 333 * If we fail to locate the appropriate file and no floating.db exists the 334 * connection is terminated without further action. 335 * 336 * If floating.db exists the connection proceeds with a floating negotiation. 337 */ 338 typedef union { 339 struct sockaddr sa; 340 struct sockaddr_in sa_in; 341 struct sockaddr_in6 sa_in6; 342 } sockaddr_any_t; 343 344 void 345 dmsg_crypto_negotiate(dmsg_iocom_t *iocom) 346 { 347 sockaddr_any_t sa; 348 socklen_t salen = sizeof(sa); 349 char peername[128]; 350 char realname[128]; 351 dmsg_handshake_t handtx; 352 dmsg_handshake_t handrx; 353 char buf1[sizeof(handtx)]; 354 char buf2[sizeof(handtx)]; 355 char *ptr; 356 char *path; 357 struct stat st; 358 FILE *fp; 359 RSA *keys[3] = { NULL, NULL, NULL }; 360 size_t i; 361 size_t blksize; 362 size_t blkmask; 363 ssize_t n; 364 int fd; 365 int error; 366 367 /* 368 * Get the peer IP address for the connection as a string. 369 */ 370 if (getpeername(iocom->sock_fd, &sa.sa, &salen) < 0) { 371 iocom->ioq_rx.error = DMSG_IOQ_ERROR_NOPEER; 372 atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF); 373 dm_printf(1, "%s\n", "accept: getpeername() failed"); 374 goto done; 375 } 376 if (getnameinfo(&sa.sa, salen, peername, sizeof(peername), 377 NULL, 0, NI_NUMERICHOST) < 0) { 378 iocom->ioq_rx.error = DMSG_IOQ_ERROR_NOPEER; 379 atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF); 380 dm_printf(1, "%s\n", "accept: cannot decode sockaddr"); 381 goto done; 382 } 383 if (DMsgDebugOpt) { 384 if (realhostname_sa(realname, sizeof(realname), 385 &sa.sa, salen) == HOSTNAME_FOUND) { 386 dm_printf(1, "accept from %s (%s)\n", 387 peername, realname); 388 } else { 389 dm_printf(1, "accept from %s\n", peername); 390 } 391 } 392 393 /* 394 * Find the remote host's public key 395 * 396 * If the link is not to be encrypted (<ip>.none located) we shortcut 397 * the handshake entirely. No buffers are exchanged. 398 */ 399 asprintf(&path, "%s/%s.pub", DMSG_PATH_REMOTE, peername); 400 if ((fp = fopen(path, "r")) == NULL) { 401 free(path); 402 asprintf(&path, "%s/%s.none", 403 DMSG_PATH_REMOTE, peername); 404 if (stat(path, &st) < 0) { 405 iocom->ioq_rx.error = DMSG_IOQ_ERROR_NORKEY; 406 atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF); 407 dm_printf(1, "%s\n", "auth failure: unknown host"); 408 goto done; 409 } 410 dm_printf(1, "%s\n", "auth succeeded, unencrypted link"); 411 goto done; 412 } 413 if (fp) { 414 keys[0] = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL); 415 fclose(fp); 416 if (keys[0] == NULL) { 417 iocom->ioq_rx.error = DMSG_IOQ_ERROR_KEYFMT; 418 atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF); 419 dm_printf(1, "%s\n", "auth failure: bad key format"); 420 goto done; 421 } 422 } 423 424 /* 425 * Get our public and private keys 426 */ 427 free(path); 428 asprintf(&path, DMSG_DEFAULT_DIR "/rsa.pub"); 429 if ((fp = fopen(path, "r")) == NULL) { 430 iocom->ioq_rx.error = DMSG_IOQ_ERROR_NOLKEY; 431 atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF); 432 goto done; 433 } 434 keys[1] = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL); 435 fclose(fp); 436 if (keys[1] == NULL) { 437 iocom->ioq_rx.error = DMSG_IOQ_ERROR_KEYFMT; 438 atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF); 439 dm_printf(1, "%s\n", "auth failure: bad host key format"); 440 goto done; 441 } 442 443 free(path); 444 asprintf(&path, DMSG_DEFAULT_DIR "/rsa.prv"); 445 if ((fp = fopen(path, "r")) == NULL) { 446 iocom->ioq_rx.error = DMSG_IOQ_ERROR_NOLKEY; 447 atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF); 448 dm_printf(1, "%s\n", "auth failure: bad host key format"); 449 goto done; 450 } 451 keys[2] = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); 452 fclose(fp); 453 if (keys[2] == NULL) { 454 iocom->ioq_rx.error = DMSG_IOQ_ERROR_KEYFMT; 455 atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF); 456 dm_printf(1, "%s\n", "auth failure: bad host key format"); 457 goto done; 458 } 459 free(path); 460 path = NULL; 461 462 /* 463 * public key encrypt/decrypt block size. 464 */ 465 if (keys[0]) { 466 blksize = (size_t)RSA_size(keys[0]); 467 if (blksize != (size_t)RSA_size(keys[1]) || 468 blksize != (size_t)RSA_size(keys[2]) || 469 sizeof(handtx) % blksize != 0) { 470 iocom->ioq_rx.error = DMSG_IOQ_ERROR_KEYFMT; 471 atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF); 472 dm_printf(1, "%s\n", 473 "auth failure: key size mismatch"); 474 goto done; 475 } 476 } else { 477 blksize = sizeof(handtx); 478 } 479 blkmask = blksize - 1; 480 481 bzero(&handrx, sizeof(handrx)); 482 bzero(&handtx, sizeof(handtx)); 483 484 /* 485 * Fill all unused fields (particular all junk fields) with random 486 * data, and also set the session key. 487 */ 488 fd = open("/dev/urandom", O_RDONLY); 489 if (fd < 0 || 490 fstat(fd, &st) < 0 || /* something wrong */ 491 S_ISREG(st.st_mode) || /* supposed to be a RNG dev! */ 492 read(fd, &handtx, sizeof(handtx)) != sizeof(handtx)) { 493 urandfail: 494 if (fd >= 0) 495 close(fd); 496 iocom->ioq_rx.error = DMSG_IOQ_ERROR_BADURANDOM; 497 atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF); 498 dm_printf(1, "%s\n", "auth failure: bad rng"); 499 goto done; 500 } 501 if (bcmp(&handrx, &handtx, sizeof(handtx)) == 0) 502 goto urandfail; /* read all zeros */ 503 close(fd); 504 /* ERR_load_crypto_strings(); openssl debugging */ 505 506 /* 507 * Handshake with the remote. 508 * 509 * Encrypt with my private and remote's public 510 * Decrypt with my private and remote's public 511 * 512 * When encrypting we have to make sure our buffer fits within the 513 * modulus, which typically requires bit 7 o the first byte to be 514 * zero. To be safe make sure that bit 7 and bit 6 is zero. 515 */ 516 snprintf(handtx.quickmsg, sizeof(handtx.quickmsg), "Testing 1 2 3"); 517 handtx.magic = DMSG_HDR_MAGIC; 518 handtx.version = 1; 519 handtx.flags = 0; 520 assert(sizeof(handtx.verf) * 4 == sizeof(handtx.sess)); 521 bzero(handtx.verf, sizeof(handtx.verf)); 522 523 handtx.pad1[0] &= 0x3f; /* message must fit within modulus */ 524 handtx.pad2[0] &= 0x3f; /* message must fit within modulus */ 525 526 for (i = 0; i < sizeof(handtx.sess); ++i) 527 handtx.verf[i / 4] ^= handtx.sess[i]; 528 529 /* 530 * Write handshake buffer to remote 531 */ 532 for (i = 0; i < sizeof(handtx); i += blksize) { 533 ptr = (char *)&handtx + i; 534 if (keys[0]) { 535 /* 536 * Since we are double-encrypting we have to make 537 * sure that the result of the first stage does 538 * not blow out the modulus for the second stage. 539 * 540 * The pointer is pointing to the pad*[] area so 541 * we can mess with that until the first stage 542 * is legal. 543 */ 544 do { 545 ++*(int *)(ptr + 4); 546 if (RSA_private_encrypt(blksize, ptr, buf1, 547 keys[2], RSA_NO_PADDING) < 0) { 548 iocom->ioq_rx.error = 549 DMSG_IOQ_ERROR_KEYXCHGFAIL; 550 } 551 } while (buf1[0] & 0xC0); 552 553 if (RSA_public_encrypt(blksize, buf1, buf2, 554 keys[0], RSA_NO_PADDING) < 0) { 555 iocom->ioq_rx.error = 556 DMSG_IOQ_ERROR_KEYXCHGFAIL; 557 } 558 } 559 if (write(iocom->sock_fd, buf2, blksize) != (ssize_t)blksize) { 560 dmio_printf(iocom, 1, "%s\n", "WRITE ERROR"); 561 } 562 } 563 if (iocom->ioq_rx.error) { 564 atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF); 565 dmio_printf(iocom, 1, "%s\n", 566 "auth failure: key exchange failure " 567 "during encryption"); 568 goto done; 569 } 570 571 /* 572 * Read handshake buffer from remote 573 */ 574 i = 0; 575 while (i < sizeof(handrx)) { 576 ptr = (char *)&handrx + i; 577 n = read(iocom->sock_fd, ptr, blksize - (i & blkmask)); 578 if (n <= 0) 579 break; 580 ptr -= (i & blkmask); 581 i += n; 582 if (keys[0] && (i & blkmask) == 0) { 583 if (RSA_private_decrypt(blksize, ptr, buf1, 584 keys[2], RSA_NO_PADDING) < 0) 585 iocom->ioq_rx.error = 586 DMSG_IOQ_ERROR_KEYXCHGFAIL; 587 if (RSA_public_decrypt(blksize, buf1, ptr, 588 keys[0], RSA_NO_PADDING) < 0) 589 iocom->ioq_rx.error = 590 DMSG_IOQ_ERROR_KEYXCHGFAIL; 591 } 592 } 593 if (iocom->ioq_rx.error) { 594 atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF); 595 dmio_printf(iocom, 1, "%s\n", 596 "auth failure: key exchange failure " 597 "during decryption"); 598 goto done; 599 } 600 601 /* 602 * Validate the received data. Try to make this a constant-time 603 * algorithm. 604 */ 605 if (i != sizeof(handrx)) { 606 keyxchgfail: 607 iocom->ioq_rx.error = DMSG_IOQ_ERROR_KEYXCHGFAIL; 608 atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF); 609 dmio_printf(iocom, 1, "%s\n", 610 "auth failure: key exchange failure"); 611 goto done; 612 } 613 614 if (handrx.magic == DMSG_HDR_MAGIC_REV) { 615 handrx.version = bswap16(handrx.version); 616 handrx.flags = bswap32(handrx.flags); 617 } 618 for (i = 0; i < sizeof(handrx.sess); ++i) 619 handrx.verf[i / 4] ^= handrx.sess[i]; 620 n = 0; 621 for (i = 0; i < sizeof(handrx.verf); ++i) 622 n += handrx.verf[i]; 623 if (handrx.version != 1) 624 ++n; 625 if (n != 0) 626 goto keyxchgfail; 627 628 /* 629 * Use separate session keys and session fixed IVs for receive and 630 * transmit. 631 */ 632 error = crypto_algos[DMSG_CRYPTO_ALGO].init(&iocom->ioq_rx, 633 (char*)handrx.sess, 634 crypto_algos[DMSG_CRYPTO_ALGO].keylen, 635 (char*)handrx.sess + crypto_algos[DMSG_CRYPTO_ALGO].keylen, 636 sizeof(handrx.sess) - crypto_algos[DMSG_CRYPTO_ALGO].keylen, 637 0 /* decryption */); 638 if (error) 639 goto keyxchgfail; 640 641 error = crypto_algos[DMSG_CRYPTO_ALGO].init(&iocom->ioq_tx, 642 (char*)handtx.sess, 643 crypto_algos[DMSG_CRYPTO_ALGO].keylen, 644 (char*)handtx.sess + crypto_algos[DMSG_CRYPTO_ALGO].keylen, 645 sizeof(handtx.sess) - crypto_algos[DMSG_CRYPTO_ALGO].keylen, 646 1 /* encryption */); 647 if (error) 648 goto keyxchgfail; 649 650 atomic_set_int(&iocom->flags, DMSG_IOCOMF_CRYPTED); 651 652 dmio_printf(iocom, 1, "auth success: %s\n", handrx.quickmsg); 653 done: 654 if (path) 655 free(path); 656 if (keys[0]) 657 RSA_free(keys[0]); 658 if (keys[1]) 659 RSA_free(keys[1]); 660 if (keys[1]) 661 RSA_free(keys[2]); 662 } 663 664 /* 665 * Decrypt pending data in the ioq's fifo. The data is decrypted in-place. 666 */ 667 void 668 dmsg_crypto_decrypt(dmsg_iocom_t *iocom __unused, dmsg_ioq_t *ioq) 669 { 670 int p_len; 671 int used; 672 __unused int error; /* XXX */ 673 char buf[512]; 674 675 /* 676 * fifo_beg to fifo_cdx is data already decrypted. 677 * fifo_cdn to fifo_end is data not yet decrypted. 678 */ 679 p_len = ioq->fifo_end - ioq->fifo_cdn; /* data not yet decrypted */ 680 681 if (p_len == 0) 682 return; 683 684 while (p_len >= crypto_algos[DMSG_CRYPTO_ALGO].taglen + 685 DMSG_CRYPTO_CHUNK_SIZE) { 686 bcopy(ioq->buf + ioq->fifo_cdn, buf, 687 crypto_algos[DMSG_CRYPTO_ALGO].taglen + 688 DMSG_CRYPTO_CHUNK_SIZE); 689 error = crypto_algos[DMSG_CRYPTO_ALGO].dec_chunk( 690 ioq, buf, 691 ioq->buf + ioq->fifo_cdx, 692 DMSG_CRYPTO_CHUNK_SIZE, 693 &used); 694 #ifdef CRYPTO_DEBUG 695 dmio_printf(iocom, 5, 696 "dec: p_len: %d, used: %d, " 697 "fifo_cdn: %ju, fifo_cdx: %ju\n", 698 p_len, used, 699 ioq->fifo_cdn, ioq->fifo_cdx); 700 #endif 701 p_len -= used; 702 ioq->fifo_cdn += used; 703 ioq->fifo_cdx += DMSG_CRYPTO_CHUNK_SIZE; 704 #ifdef CRYPTO_DEBUG 705 dmio_printf(iocom, 5, 706 "dec: p_len: %d, used: %d, " 707 "fifo_cdn: %ju, fifo_cdx: %ju\n", 708 p_len, used, ioq->fifo_cdn, ioq->fifo_cdx); 709 #endif 710 } 711 } 712 713 /* 714 * *nactp is set to the number of ORIGINAL bytes consumed by the encrypter. 715 * The FIFO may contain more data. 716 */ 717 int 718 dmsg_crypto_encrypt(dmsg_iocom_t *iocom __unused, dmsg_ioq_t *ioq, 719 struct iovec *iov, int n, size_t *nactp) 720 { 721 int p_len, used, ct_used; 722 int i; 723 __unused int error; /* XXX */ 724 size_t nmax; 725 726 nmax = sizeof(ioq->buf) - ioq->fifo_end; /* max new bytes */ 727 728 *nactp = 0; 729 for (i = 0; i < n && nmax; ++i) { 730 used = 0; 731 p_len = iov[i].iov_len; 732 assert((p_len & DMSG_ALIGNMASK) == 0); 733 734 while (p_len >= DMSG_CRYPTO_CHUNK_SIZE && 735 nmax >= DMSG_CRYPTO_CHUNK_SIZE + 736 (size_t)crypto_algos[DMSG_CRYPTO_ALGO].taglen) { 737 error = crypto_algos[DMSG_CRYPTO_ALGO].enc_chunk( 738 ioq, 739 ioq->buf + ioq->fifo_cdx, 740 (char *)iov[i].iov_base + used, 741 DMSG_CRYPTO_CHUNK_SIZE, &ct_used); 742 #ifdef CRYPTO_DEBUG 743 dmio_printf(iocom, 5, 744 "nactp: %ju, p_len: %d, " 745 "ct_used: %d, used: %d, nmax: %ju\n", 746 *nactp, p_len, ct_used, used, nmax); 747 #endif 748 749 *nactp += (size_t)DMSG_CRYPTO_CHUNK_SIZE; /* plaintext count */ 750 used += DMSG_CRYPTO_CHUNK_SIZE; 751 p_len -= DMSG_CRYPTO_CHUNK_SIZE; 752 753 /* 754 * NOTE: crypted count will eventually differ from 755 * nmax, but for now we have not yet introduced 756 * random armor. 757 */ 758 ioq->fifo_cdx += (size_t)ct_used; 759 ioq->fifo_cdn += (size_t)ct_used; 760 ioq->fifo_end += (size_t)ct_used; 761 nmax -= (size_t)ct_used; 762 #ifdef CRYPTO_DEBUG 763 dmio_printf(iocom, 5, 764 "nactp: %ju, p_len: %d, " 765 "ct_used: %d, used: %d, nmax: %ju\n", 766 *nactp, p_len, ct_used, used, nmax); 767 #endif 768 } 769 } 770 iov[0].iov_base = ioq->buf + ioq->fifo_beg; 771 iov[0].iov_len = ioq->fifo_cdx - ioq->fifo_beg; 772 773 return (1); 774 } 775