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 if (DMsgDebugOpt) 104 fprintf(stderr, "Not enough key or iv material\n"); 105 return -1; 106 } 107 108 printf("%s key: ", enc ? "Encryption" : "Decryption"); 109 for (i = 0; i < DMSG_CRYPTO_GCM_KEY_SIZE; ++i) 110 printf("%02x", (unsigned char)key[i]); 111 printf("\n"); 112 113 printf("%s iv: ", enc ? "Encryption" : "Decryption"); 114 for (i = 0; i < DMSG_CRYPTO_GCM_IV_FIXED_SIZE; ++i) 115 printf("%02x", (unsigned char)iv_fixed[i]); 116 printf(" (fixed part only)\n"); 117 118 EVP_CIPHER_CTX_init(&ioq->ctx); 119 120 if (enc) 121 ok = EVP_EncryptInit_ex(&ioq->ctx, EVP_aes_256_gcm(), NULL, 122 key, NULL); 123 else 124 ok = EVP_DecryptInit_ex(&ioq->ctx, EVP_aes_256_gcm(), NULL, 125 key, NULL); 126 if (!ok) 127 goto fail; 128 129 /* 130 * According to the original Galois/Counter Mode of Operation (GCM) 131 * proposal, only IVs that are exactly 96 bits get used without any 132 * further processing. Other IV sizes cause the GHASH() operation 133 * to be applied to the IV, which is more costly. 134 * 135 * The NIST SP 800-38D also recommends using a 96 bit IV for the same 136 * reasons. We actually follow the deterministic construction 137 * recommended in NIST SP 800-38D with a 64 bit invocation field as an 138 * integer counter and a random, session-specific fixed field. 139 * 140 * This means that we can essentially use the same session key and 141 * IV fixed field for up to 2^64 invocations of the authenticated 142 * encryption or decryption. 143 * 144 * With a chunk size of 64 bytes, this adds up to 1 zettabyte of 145 * traffic. 146 */ 147 ok = EVP_CIPHER_CTX_ctrl(&ioq->ctx, EVP_CTRL_GCM_SET_IVLEN, 148 DMSG_CRYPTO_GCM_IV_SIZE, NULL); 149 if (!ok) 150 goto fail; 151 152 memset(ioq->iv, 0, DMSG_CRYPTO_GCM_IV_SIZE); 153 memcpy(ioq->iv, iv_fixed, DMSG_CRYPTO_GCM_IV_FIXED_SIZE); 154 155 /* 156 * Strictly speaking, padding is irrelevant with a counter mode 157 * encryption. 158 * 159 * However, setting padding to 0, even if using a counter mode such 160 * as GCM, will cause an error in _finish if the pt/ct size is not 161 * a multiple of the cipher block size. 162 */ 163 EVP_CIPHER_CTX_set_padding(&ioq->ctx, 0); 164 165 return 0; 166 167 fail: 168 if (DMsgDebugOpt) 169 fprintf(stderr, "Error during _gcm_init\n"); 170 return -1; 171 } 172 173 static 174 int 175 _gcm_iv_increment(char *iv) 176 { 177 /* 178 * Deterministic construction according to NIST SP 800-38D, with 179 * 64 bit invocation field as integer counter. 180 * 181 * In other words, our 96 bit IV consists of a 32 bit fixed field 182 * unique to the session and a 64 bit integer counter. 183 */ 184 185 uint64_t *c = (uint64_t *)(&iv[DMSG_CRYPTO_GCM_IV_FIXED_SIZE]); 186 187 /* Increment invocation field integer counter */ 188 *c = htobe64(be64toh(*c)+1); 189 190 /* 191 * Detect wrap-around, which means it is time to renegotiate 192 * the session to get a new key and/or fixed field. 193 */ 194 return (*c == 0) ? 0 : 1; 195 } 196 197 static 198 int 199 dmsg_crypto_gcm_encrypt_chunk(dmsg_ioq_t *ioq, char *ct, char *pt, 200 int in_size, int *out_size) 201 { 202 int ok; 203 int u_len, f_len; 204 205 *out_size = 0; 206 207 /* Re-initialize with new IV (but without redoing the key schedule) */ 208 ok = EVP_EncryptInit_ex(&ioq->ctx, NULL, NULL, NULL, ioq->iv); 209 if (!ok) 210 goto fail; 211 212 ok = EVP_EncryptUpdate(&ioq->ctx, ct, &u_len, pt, in_size); 213 if (!ok) 214 goto fail; 215 216 ok = EVP_EncryptFinal(&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 235 return 0; 236 237 fail: 238 ioq->error = DMSG_IOQ_ERROR_ALGO; 239 fail_out: 240 if (DMsgDebugOpt) 241 fprintf(stderr, "error during encrypt_chunk\n"); 242 return -1; 243 } 244 245 static 246 int 247 dmsg_crypto_gcm_decrypt_chunk(dmsg_ioq_t *ioq, char *ct, char *pt, 248 int out_size, int *consume_size) 249 { 250 int ok; 251 int u_len, f_len; 252 253 *consume_size = 0; 254 255 /* Re-initialize with new IV (but without redoing the key schedule) */ 256 ok = EVP_DecryptInit_ex(&ioq->ctx, NULL, NULL, NULL, ioq->iv); 257 if (!ok) { 258 ioq->error = DMSG_IOQ_ERROR_ALGO; 259 goto fail_out; 260 } 261 262 ok = EVP_CIPHER_CTX_ctrl(&ioq->ctx, EVP_CTRL_GCM_SET_TAG, 263 DMSG_CRYPTO_GCM_TAG_SIZE, 264 ct + out_size); 265 if (!ok) { 266 ioq->error = DMSG_IOQ_ERROR_ALGO; 267 goto fail_out; 268 } 269 270 ok = EVP_DecryptUpdate(&ioq->ctx, pt, &u_len, ct, out_size); 271 if (!ok) 272 goto fail; 273 274 ok = EVP_DecryptFinal(&ioq->ctx, pt + u_len, &f_len); 275 if (!ok) 276 goto fail; 277 278 ok = _gcm_iv_increment(ioq->iv); 279 if (!ok) { 280 ioq->error = DMSG_IOQ_ERROR_IVWRAP; 281 goto fail_out; 282 } 283 284 *consume_size = u_len + f_len + DMSG_CRYPTO_GCM_TAG_SIZE; 285 286 return 0; 287 288 fail: 289 ioq->error = DMSG_IOQ_ERROR_MACFAIL; 290 fail_out: 291 if (DMsgDebugOpt) 292 fprintf(stderr, "error during decrypt_chunk (likely authentication error)\n"); 293 return -1; 294 } 295 296 /* 297 * Synchronously negotiate crypto for a new session. This must occur 298 * within 10 seconds or the connection is error'd out. 299 * 300 * We work off the IP address and/or reverse DNS. The IP address is 301 * checked first, followed by the IP address at various levels of granularity, 302 * followed by the full domain name and domain names at various levels of 303 * granularity. 304 * 305 * /etc/hammer2/remote/<name>.pub - Contains a public key 306 * /etc/hammer2/remote/<name>.none - Indicates no encryption (empty file) 307 * (e.g. localhost.none). 308 * 309 * We first attempt to locate a public key file based on the peer address or 310 * peer FQDN. 311 * 312 * <name>.none - No further negotiation is needed. We simply return. 313 * All communication proceeds without encryption. 314 * No public key handshake occurs in this situation. 315 * (both ends must match). 316 * 317 * <name>.pub - We have located the public key for the peer. Both 318 * sides transmit a block encrypted with their private 319 * keys and the peer's public key. 320 * 321 * Both sides receive a block and decrypt it. 322 * 323 * Both sides formulate a reply using the decrypted 324 * block and transmit it. 325 * 326 * communication proceeds with the negotiated session 327 * key (typically AES-256-CBC). 328 * 329 * If we fail to locate the appropriate file and no floating.db exists the 330 * connection is terminated without further action. 331 * 332 * If floating.db exists the connection proceeds with a floating negotiation. 333 */ 334 typedef union { 335 struct sockaddr sa; 336 struct sockaddr_in sa_in; 337 struct sockaddr_in6 sa_in6; 338 } sockaddr_any_t; 339 340 void 341 dmsg_crypto_negotiate(dmsg_iocom_t *iocom) 342 { 343 sockaddr_any_t sa; 344 socklen_t salen = sizeof(sa); 345 char peername[128]; 346 char realname[128]; 347 dmsg_handshake_t handtx; 348 dmsg_handshake_t handrx; 349 char buf1[sizeof(handtx)]; 350 char buf2[sizeof(handtx)]; 351 char *ptr; 352 char *path; 353 struct stat st; 354 FILE *fp; 355 RSA *keys[3] = { NULL, NULL, NULL }; 356 size_t i; 357 size_t blksize; 358 size_t blkmask; 359 ssize_t n; 360 int fd; 361 int error; 362 363 /* 364 * Get the peer IP address for the connection as a string. 365 */ 366 if (getpeername(iocom->sock_fd, &sa.sa, &salen) < 0) { 367 iocom->ioq_rx.error = DMSG_IOQ_ERROR_NOPEER; 368 atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF); 369 if (DMsgDebugOpt) 370 fprintf(stderr, "accept: getpeername() failed\n"); 371 goto done; 372 } 373 if (getnameinfo(&sa.sa, salen, peername, sizeof(peername), 374 NULL, 0, NI_NUMERICHOST) < 0) { 375 iocom->ioq_rx.error = DMSG_IOQ_ERROR_NOPEER; 376 atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF); 377 if (DMsgDebugOpt) 378 fprintf(stderr, "accept: cannot decode sockaddr\n"); 379 goto done; 380 } 381 if (DMsgDebugOpt) { 382 if (realhostname_sa(realname, sizeof(realname), 383 &sa.sa, salen) == HOSTNAME_FOUND) { 384 fprintf(stderr, "accept from %s (%s)\n", 385 peername, realname); 386 } else { 387 fprintf(stderr, "accept from %s\n", peername); 388 } 389 } 390 391 /* 392 * Find the remote host's public key 393 * 394 * If the link is not to be encrypted (<ip>.none located) we shortcut 395 * the handshake entirely. No buffers are exchanged. 396 */ 397 asprintf(&path, "%s/%s.pub", DMSG_PATH_REMOTE, peername); 398 if ((fp = fopen(path, "r")) == NULL) { 399 free(path); 400 asprintf(&path, "%s/%s.none", 401 DMSG_PATH_REMOTE, peername); 402 if (stat(path, &st) < 0) { 403 iocom->ioq_rx.error = DMSG_IOQ_ERROR_NORKEY; 404 atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF); 405 if (DMsgDebugOpt) 406 fprintf(stderr, "auth failure: unknown host\n"); 407 goto done; 408 } 409 if (DMsgDebugOpt) 410 fprintf(stderr, "auth succeeded, unencrypted link\n"); 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 if (DMsgDebugOpt) 420 fprintf(stderr, 421 "auth failure: bad key format\n"); 422 goto done; 423 } 424 } 425 426 /* 427 * Get our public and private keys 428 */ 429 free(path); 430 asprintf(&path, DMSG_DEFAULT_DIR "/rsa.pub"); 431 if ((fp = fopen(path, "r")) == NULL) { 432 iocom->ioq_rx.error = DMSG_IOQ_ERROR_NOLKEY; 433 atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF); 434 goto done; 435 } 436 keys[1] = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL); 437 fclose(fp); 438 if (keys[1] == NULL) { 439 iocom->ioq_rx.error = DMSG_IOQ_ERROR_KEYFMT; 440 atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF); 441 if (DMsgDebugOpt) 442 fprintf(stderr, "auth failure: bad host key format\n"); 443 goto done; 444 } 445 446 free(path); 447 asprintf(&path, DMSG_DEFAULT_DIR "/rsa.prv"); 448 if ((fp = fopen(path, "r")) == NULL) { 449 iocom->ioq_rx.error = DMSG_IOQ_ERROR_NOLKEY; 450 atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF); 451 if (DMsgDebugOpt) 452 fprintf(stderr, "auth failure: bad host key format\n"); 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 if (DMsgDebugOpt) 461 fprintf(stderr, "auth failure: bad host key format\n"); 462 goto done; 463 } 464 free(path); 465 path = NULL; 466 467 /* 468 * public key encrypt/decrypt block size. 469 */ 470 if (keys[0]) { 471 blksize = (size_t)RSA_size(keys[0]); 472 if (blksize != (size_t)RSA_size(keys[1]) || 473 blksize != (size_t)RSA_size(keys[2]) || 474 sizeof(handtx) % blksize != 0) { 475 iocom->ioq_rx.error = DMSG_IOQ_ERROR_KEYFMT; 476 atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF); 477 if (DMsgDebugOpt) 478 fprintf(stderr, "auth failure: " 479 "key size mismatch\n"); 480 goto done; 481 } 482 } else { 483 blksize = sizeof(handtx); 484 } 485 blkmask = blksize - 1; 486 487 bzero(&handrx, sizeof(handrx)); 488 bzero(&handtx, sizeof(handtx)); 489 490 /* 491 * Fill all unused fields (particular all junk fields) with random 492 * data, and also set the session key. 493 */ 494 fd = open("/dev/urandom", O_RDONLY); 495 if (fd < 0 || 496 fstat(fd, &st) < 0 || /* something wrong */ 497 S_ISREG(st.st_mode) || /* supposed to be a RNG dev! */ 498 read(fd, &handtx, sizeof(handtx)) != sizeof(handtx)) { 499 urandfail: 500 if (fd >= 0) 501 close(fd); 502 iocom->ioq_rx.error = DMSG_IOQ_ERROR_BADURANDOM; 503 atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF); 504 if (DMsgDebugOpt) 505 fprintf(stderr, "auth failure: bad rng\n"); 506 goto done; 507 } 508 if (bcmp(&handrx, &handtx, sizeof(handtx)) == 0) 509 goto urandfail; /* read all zeros */ 510 close(fd); 511 /* ERR_load_crypto_strings(); openssl debugging */ 512 513 /* 514 * Handshake with the remote. 515 * 516 * Encrypt with my private and remote's public 517 * Decrypt with my private and remote's public 518 * 519 * When encrypting we have to make sure our buffer fits within the 520 * modulus, which typically requires bit 7 o the first byte to be 521 * zero. To be safe make sure that bit 7 and bit 6 is zero. 522 */ 523 snprintf(handtx.quickmsg, sizeof(handtx.quickmsg), "Testing 1 2 3"); 524 handtx.magic = DMSG_HDR_MAGIC; 525 handtx.version = 1; 526 handtx.flags = 0; 527 assert(sizeof(handtx.verf) * 4 == sizeof(handtx.sess)); 528 bzero(handtx.verf, sizeof(handtx.verf)); 529 530 handtx.pad1[0] &= 0x3f; /* message must fit within modulus */ 531 handtx.pad2[0] &= 0x3f; /* message must fit within modulus */ 532 533 for (i = 0; i < sizeof(handtx.sess); ++i) 534 handtx.verf[i / 4] ^= handtx.sess[i]; 535 536 /* 537 * Write handshake buffer to remote 538 */ 539 for (i = 0; i < sizeof(handtx); i += blksize) { 540 ptr = (char *)&handtx + i; 541 if (keys[0]) { 542 /* 543 * Since we are double-encrypting we have to make 544 * sure that the result of the first stage does 545 * not blow out the modulus for the second stage. 546 * 547 * The pointer is pointing to the pad*[] area so 548 * we can mess with that until the first stage 549 * is legal. 550 */ 551 do { 552 ++*(int *)(ptr + 4); 553 if (RSA_private_encrypt(blksize, ptr, buf1, 554 keys[2], RSA_NO_PADDING) < 0) { 555 iocom->ioq_rx.error = 556 DMSG_IOQ_ERROR_KEYXCHGFAIL; 557 } 558 } while (buf1[0] & 0xC0); 559 560 if (RSA_public_encrypt(blksize, buf1, buf2, 561 keys[0], RSA_NO_PADDING) < 0) { 562 iocom->ioq_rx.error = 563 DMSG_IOQ_ERROR_KEYXCHGFAIL; 564 } 565 } 566 if (write(iocom->sock_fd, buf2, blksize) != (ssize_t)blksize) { 567 fprintf(stderr, "WRITE ERROR\n"); 568 } 569 } 570 if (iocom->ioq_rx.error) { 571 atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF); 572 if (DMsgDebugOpt) 573 fprintf(stderr, "auth failure: key exchange failure " 574 "during encryption\n"); 575 goto done; 576 } 577 578 /* 579 * Read handshake buffer from remote 580 */ 581 i = 0; 582 while (i < sizeof(handrx)) { 583 ptr = (char *)&handrx + i; 584 n = read(iocom->sock_fd, ptr, blksize - (i & blkmask)); 585 if (n <= 0) 586 break; 587 ptr -= (i & blkmask); 588 i += n; 589 if (keys[0] && (i & blkmask) == 0) { 590 if (RSA_private_decrypt(blksize, ptr, buf1, 591 keys[2], RSA_NO_PADDING) < 0) 592 iocom->ioq_rx.error = 593 DMSG_IOQ_ERROR_KEYXCHGFAIL; 594 if (RSA_public_decrypt(blksize, buf1, ptr, 595 keys[0], RSA_NO_PADDING) < 0) 596 iocom->ioq_rx.error = 597 DMSG_IOQ_ERROR_KEYXCHGFAIL; 598 } 599 } 600 if (iocom->ioq_rx.error) { 601 atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF); 602 if (DMsgDebugOpt) 603 fprintf(stderr, "auth failure: key exchange failure " 604 "during decryption\n"); 605 goto done; 606 } 607 608 /* 609 * Validate the received data. Try to make this a constant-time 610 * algorithm. 611 */ 612 if (i != sizeof(handrx)) { 613 keyxchgfail: 614 iocom->ioq_rx.error = DMSG_IOQ_ERROR_KEYXCHGFAIL; 615 atomic_set_int(&iocom->flags, DMSG_IOCOMF_EOF); 616 if (DMsgDebugOpt) 617 fprintf(stderr, "auth failure: key exchange failure\n"); 618 goto done; 619 } 620 621 if (handrx.magic == DMSG_HDR_MAGIC_REV) { 622 handrx.version = bswap16(handrx.version); 623 handrx.flags = bswap32(handrx.flags); 624 } 625 for (i = 0; i < sizeof(handrx.sess); ++i) 626 handrx.verf[i / 4] ^= handrx.sess[i]; 627 n = 0; 628 for (i = 0; i < sizeof(handrx.verf); ++i) 629 n += handrx.verf[i]; 630 if (handrx.version != 1) 631 ++n; 632 if (n != 0) 633 goto keyxchgfail; 634 635 /* 636 * Use separate session keys and session fixed IVs for receive and 637 * transmit. 638 */ 639 error = crypto_algos[DMSG_CRYPTO_ALGO].init(&iocom->ioq_rx, handrx.sess, 640 crypto_algos[DMSG_CRYPTO_ALGO].keylen, 641 handrx.sess + crypto_algos[DMSG_CRYPTO_ALGO].keylen, 642 sizeof(handrx.sess) - crypto_algos[DMSG_CRYPTO_ALGO].keylen, 643 0 /* decryption */); 644 if (error) 645 goto keyxchgfail; 646 647 error = crypto_algos[DMSG_CRYPTO_ALGO].init(&iocom->ioq_tx, handtx.sess, 648 crypto_algos[DMSG_CRYPTO_ALGO].keylen, 649 handtx.sess + crypto_algos[DMSG_CRYPTO_ALGO].keylen, 650 sizeof(handtx.sess) - crypto_algos[DMSG_CRYPTO_ALGO].keylen, 651 1 /* encryption */); 652 if (error) 653 goto keyxchgfail; 654 655 atomic_set_int(&iocom->flags, DMSG_IOCOMF_CRYPTED); 656 657 if (DMsgDebugOpt) 658 fprintf(stderr, "auth success: %s\n", handrx.quickmsg); 659 done: 660 if (path) 661 free(path); 662 if (keys[0]) 663 RSA_free(keys[0]); 664 if (keys[1]) 665 RSA_free(keys[1]); 666 if (keys[1]) 667 RSA_free(keys[2]); 668 } 669 670 /* 671 * Decrypt pending data in the ioq's fifo. The data is decrypted in-place. 672 */ 673 void 674 dmsg_crypto_decrypt(dmsg_iocom_t *iocom __unused, dmsg_ioq_t *ioq) 675 { 676 int p_len; 677 int used; 678 __unused int error; /* XXX */ 679 char buf[512]; 680 681 /* 682 * fifo_beg to fifo_cdx is data already decrypted. 683 * fifo_cdn to fifo_end is data not yet decrypted. 684 */ 685 p_len = ioq->fifo_end - ioq->fifo_cdn; /* data not yet decrypted */ 686 687 if (p_len == 0) 688 return; 689 690 while (p_len >= crypto_algos[DMSG_CRYPTO_ALGO].taglen + 691 DMSG_CRYPTO_CHUNK_SIZE) { 692 bcopy(ioq->buf + ioq->fifo_cdn, buf, 693 crypto_algos[DMSG_CRYPTO_ALGO].taglen + 694 DMSG_CRYPTO_CHUNK_SIZE); 695 error = crypto_algos[DMSG_CRYPTO_ALGO].dec_chunk( 696 ioq, buf, 697 ioq->buf + ioq->fifo_cdx, 698 DMSG_CRYPTO_CHUNK_SIZE, 699 &used); 700 #ifdef CRYPTO_DEBUG 701 printf("dec: p_len: %d, used: %d, fifo_cdn: %ju, fifo_cdx: %ju\n", 702 p_len, used, ioq->fifo_cdn, ioq->fifo_cdx); 703 #endif 704 p_len -= used; 705 ioq->fifo_cdn += used; 706 ioq->fifo_cdx += DMSG_CRYPTO_CHUNK_SIZE; 707 #ifdef CRYPTO_DEBUG 708 printf("dec: p_len: %d, used: %d, fifo_cdn: %ju, fifo_cdx: %ju\n", 709 p_len, used, ioq->fifo_cdn, ioq->fifo_cdx); 710 #endif 711 } 712 } 713 714 /* 715 * *nactp is set to the number of ORIGINAL bytes consumed by the encrypter. 716 * The FIFO may contain more data. 717 */ 718 int 719 dmsg_crypto_encrypt(dmsg_iocom_t *iocom __unused, dmsg_ioq_t *ioq, 720 struct iovec *iov, int n, size_t *nactp) 721 { 722 int p_len, used, ct_used; 723 int i; 724 __unused int error; /* XXX */ 725 size_t nmax; 726 727 nmax = sizeof(ioq->buf) - ioq->fifo_end; /* max new bytes */ 728 729 *nactp = 0; 730 for (i = 0; i < n && nmax; ++i) { 731 used = 0; 732 p_len = iov[i].iov_len; 733 assert((p_len & DMSG_ALIGNMASK) == 0); 734 735 while (p_len >= DMSG_CRYPTO_CHUNK_SIZE && 736 nmax >= DMSG_CRYPTO_CHUNK_SIZE + 737 (size_t)crypto_algos[DMSG_CRYPTO_ALGO].taglen) { 738 error = crypto_algos[DMSG_CRYPTO_ALGO].enc_chunk( 739 ioq, 740 ioq->buf + ioq->fifo_cdx, 741 (char *)iov[i].iov_base + used, 742 DMSG_CRYPTO_CHUNK_SIZE, &ct_used); 743 #ifdef CRYPTO_DEBUG 744 printf("nactp: %ju, p_len: %d, ct_used: %d, used: %d, nmax: %ju\n", 745 *nactp, p_len, ct_used, used, nmax); 746 #endif 747 748 *nactp += (size_t)DMSG_CRYPTO_CHUNK_SIZE; /* plaintext count */ 749 used += DMSG_CRYPTO_CHUNK_SIZE; 750 p_len -= DMSG_CRYPTO_CHUNK_SIZE; 751 752 ioq->fifo_cdx += (size_t)ct_used; /* crypted count */ 753 ioq->fifo_cdn += (size_t)ct_used; /* crypted count */ 754 ioq->fifo_end += (size_t)ct_used; 755 nmax -= (size_t)ct_used; 756 #ifdef CRYPTO_DEBUG 757 printf("nactp: %ju, p_len: %d, ct_used: %d, used: %d, nmax: %ju\n", 758 *nactp, p_len, ct_used, used, nmax); 759 #endif 760 } 761 } 762 iov[0].iov_base = ioq->buf + ioq->fifo_beg; 763 iov[0].iov_len = ioq->fifo_cdx - ioq->fifo_beg; 764 765 return (1); 766 } 767