… | |
… | |
405 | srcdst = ((src >> 8) << 4) | (dst >> 8); |
405 | srcdst = ((src >> 8) << 4) | (dst >> 8); |
406 | dst1 = dst; |
406 | dst1 = dst; |
407 | } |
407 | } |
408 | |
408 | |
409 | #define MAXVPNDATA (MAX_MTU - 6 - 6) |
409 | #define MAXVPNDATA (MAX_MTU - 6 - 6) |
410 | #define DATAHDR (sizeof (u32) + RAND_SIZE) |
|
|
411 | |
410 | |
412 | struct vpndata_packet : vpn_packet |
411 | struct vpndata_packet : vpn_packet |
413 | { |
412 | { |
414 | u8 data[MAXVPNDATA + DATAHDR]; // seqno |
413 | u32 ctr; // seqno |
|
|
414 | u8 data[MAXVPNDATA]; |
415 | |
415 | |
416 | void setup (connection *conn, int dst, u8 *d, u32 len, u32 seqno); |
416 | void setup (connection *conn, int dst, u8 *d, u32 len, u32 seqno); |
417 | tap_packet *unpack (connection *conn, u32 &seqno); |
417 | tap_packet *unpack (connection *conn, u32 &seqno); |
418 | |
418 | |
419 | private: |
419 | private: |
420 | const u32 data_hdr_size () const |
420 | const u32 data_hdr_size () const |
421 | { |
421 | { |
422 | return sizeof (vpndata_packet) - sizeof (net_packet) - MAXVPNDATA - DATAHDR; |
422 | // the distance from beginning of packet to data member |
|
|
423 | return data - at (0); |
423 | } |
424 | } |
424 | }; |
425 | }; |
|
|
426 | |
|
|
427 | // expands packet counter (unlike seqno, in network byte order) to counter mode IV |
|
|
428 | static unsigned char * |
|
|
429 | expand_iv (u32 ctr) |
|
|
430 | { |
|
|
431 | static u32 iv[IV_SIZE (CIPHER) / 4]; |
|
|
432 | |
|
|
433 | require (sizeof (iv) == 4 * 4); |
|
|
434 | require (IV_SIZE (CIPHER) % 4 == 0); |
|
|
435 | |
|
|
436 | iv[0] = |
|
|
437 | iv[1] = |
|
|
438 | iv[2] = ctr; |
|
|
439 | |
|
|
440 | // I would reuse ctr here to to avoid potential endianness issues, |
|
|
441 | // but it seems openssl wraps around. While this would be still ok, |
|
|
442 | // and I don't even know if its true, let's play safe and initialise |
|
|
443 | // to 0. |
|
|
444 | iv[3] = 0; |
|
|
445 | |
|
|
446 | return (unsigned char *)iv; |
|
|
447 | } |
425 | |
448 | |
426 | void |
449 | void |
427 | vpndata_packet::setup (connection *conn, int dst, u8 *d, u32 l, u32 seqno) |
450 | vpndata_packet::setup (connection *conn, int dst, u8 *d, u32 l, u32 seqno) |
428 | { |
451 | { |
429 | EVP_CIPHER_CTX *cctx = &conn->octx->cctx; |
452 | EVP_CIPHER_CTX *cctx = &conn->octx->cctx; |
… | |
… | |
447 | d[1] = cl; |
470 | d[1] = cl; |
448 | } |
471 | } |
449 | } |
472 | } |
450 | #endif |
473 | #endif |
451 | |
474 | |
452 | require (EVP_CipherInit_ex (cctx, 0, 0, 0, 0, 1)); |
475 | ctr = htonl (seqno); |
453 | |
476 | |
454 | struct { |
477 | require (EVP_EncryptInit_ex (cctx, 0, 0, 0, expand_iv (ctr))); |
455 | #if RAND_SIZE |
|
|
456 | u8 rnd[RAND_SIZE]; |
|
|
457 | #endif |
|
|
458 | u32 seqno; |
|
|
459 | } datahdr; |
|
|
460 | |
|
|
461 | datahdr.seqno = ntohl (seqno); |
|
|
462 | #if RAND_SIZE |
|
|
463 | // NB: a constant (per session) random prefix |
|
|
464 | // is likely enough, but we don't take any chances. |
|
|
465 | conn->oiv.get (datahdr.rnd, RAND_SIZE); |
|
|
466 | #endif |
|
|
467 | |
478 | |
468 | require (EVP_EncryptUpdate (cctx, |
479 | require (EVP_EncryptUpdate (cctx, |
469 | (unsigned char *) data + outl, &outl2, |
480 | (unsigned char *)data + outl, &outl2, |
470 | (unsigned char *) &datahdr, DATAHDR)); |
481 | (unsigned char *)d, l)); |
471 | outl += outl2; |
482 | outl += outl2; |
472 | |
483 | |
473 | require (EVP_EncryptUpdate (cctx, |
484 | // it seems this is a nop for us, but we do it anyways |
474 | (unsigned char *) data + outl, &outl2, |
485 | require (EVP_EncryptFinal_ex (cctx, (unsigned char *)data + outl, &outl2)); |
475 | (unsigned char *) d, l)); |
|
|
476 | outl += outl2; |
486 | outl += outl2; |
477 | |
487 | |
478 | require (EVP_EncryptFinal_ex (cctx, (unsigned char *) data + outl, &outl2)); |
|
|
479 | outl += outl2; |
|
|
480 | |
|
|
481 | len = outl + data_hdr_size (); |
488 | len = data_hdr_size () + outl; |
482 | |
489 | |
483 | set_hdr (type, dst); |
490 | set_hdr (type, dst); |
484 | |
491 | |
485 | hmac_set (conn->octx); |
492 | hmac_set (conn->octx); |
486 | } |
493 | } |
… | |
… | |
490 | { |
497 | { |
491 | EVP_CIPHER_CTX *cctx = &conn->ictx->cctx; |
498 | EVP_CIPHER_CTX *cctx = &conn->ictx->cctx; |
492 | int outl = 0, outl2; |
499 | int outl = 0, outl2; |
493 | tap_packet *p = new tap_packet; |
500 | tap_packet *p = new tap_packet; |
494 | u8 *d; |
501 | u8 *d; |
495 | u32 l = len - data_hdr_size (); |
|
|
496 | |
502 | |
497 | require (EVP_CipherInit_ex (cctx, 0, 0, 0, 0, 0)); |
503 | seqno = ntohl (ctr); |
|
|
504 | |
|
|
505 | require (EVP_DecryptInit_ex (cctx, 0, 0, 0, expand_iv (ctr))); |
498 | |
506 | |
499 | #if ENABLE_COMPRESSION |
507 | #if ENABLE_COMPRESSION |
500 | u8 cdata[MAX_MTU]; |
508 | u8 cdata[MAX_MTU]; |
501 | |
509 | |
502 | if (type == PT_DATA_COMPRESSED) |
510 | if (type == PT_DATA_COMPRESSED) |
503 | d = cdata; |
511 | d = cdata; |
504 | else |
512 | else |
505 | #endif |
513 | #endif |
506 | d = &(*p)[6 + 6] - DATAHDR; |
514 | d = &(*p)[6 + 6]; |
507 | |
|
|
508 | // we play do evil games with the struct layout atm. |
|
|
509 | // pending better solutions, we at least do some verification. |
|
|
510 | // this is fine, as we left ISO territory long ago. |
|
|
511 | require (DATAHDR <= 16); |
|
|
512 | require ((u8 *)(&p->len + 1) == &(*p)[0]); |
|
|
513 | |
515 | |
514 | // this can overwrite the len/dst/src fields |
516 | // this can overwrite the len/dst/src fields |
515 | require (EVP_DecryptUpdate (cctx, |
517 | require (EVP_DecryptUpdate (cctx, |
516 | d, &outl2, |
518 | d, &outl2, |
517 | (unsigned char *)&data, len - data_hdr_size ())); |
519 | (unsigned char *)&data, len - data_hdr_size ())); |
518 | outl += outl2; |
520 | outl += outl2; |
519 | |
521 | |
|
|
522 | // it seems this is a nop for us, but we do it anyways |
520 | require (EVP_DecryptFinal_ex (cctx, (unsigned char *)d + outl, &outl2)); |
523 | require (EVP_DecryptFinal_ex (cctx, (unsigned char *)d + outl, &outl2)); |
521 | outl += outl2; |
524 | outl += outl2; |
522 | |
525 | |
523 | seqno = ntohl (*(u32 *)(d + RAND_SIZE)); |
|
|
524 | |
|
|
525 | id2mac (dst () ? dst() : THISNODE->id, p->dst); |
526 | id2mac (dst () ? dst() : THISNODE->id, p->dst); |
526 | id2mac (src (), p->src); |
527 | id2mac (src (), p->src); |
527 | |
528 | |
528 | #if ENABLE_COMPRESSION |
529 | #if ENABLE_COMPRESSION |
529 | if (type == PT_DATA_COMPRESSED) |
530 | if (type == PT_DATA_COMPRESSED) |
530 | { |
531 | { |
531 | u32 cl = (d[DATAHDR] << 8) | d[DATAHDR + 1]; |
532 | u32 cl = (d[0] << 8) | d[1]; |
532 | |
533 | |
533 | p->len = lzf_decompress (d + DATAHDR + 2, cl < MAX_MTU ? cl : 0, |
534 | p->len = lzf_decompress (d + 2, cl < MAX_MTU - 2 ? cl : 0, |
534 | &(*p)[6 + 6], MAX_MTU) |
535 | &(*p)[6 + 6], MAX_MTU) |
535 | + 6 + 6; |
536 | + 6 + 6; |
536 | } |
537 | } |
537 | else |
538 | else |
538 | p->len = outl + (6 + 6 - DATAHDR); |
539 | p->len = outl + (6 + 6); |
539 | #endif |
540 | #endif |
540 | |
541 | |
541 | return p; |
542 | return p; |
542 | } |
543 | } |
543 | |
544 | |
… | |
… | |
579 | void |
580 | void |
580 | config_packet::setup (ptype type, int dst) |
581 | config_packet::setup (ptype type, int dst) |
581 | { |
582 | { |
582 | prot_major = PROTOCOL_MAJOR; |
583 | prot_major = PROTOCOL_MAJOR; |
583 | prot_minor = PROTOCOL_MINOR; |
584 | prot_minor = PROTOCOL_MINOR; |
584 | randsize = RAND_SIZE; |
|
|
585 | flags = 0; |
585 | flags = 0; |
586 | features = get_features (); |
586 | features = get_features (); |
587 | |
587 | |
588 | strncpy ((char *)serial, conf.serial, sizeof (serial)); |
588 | strncpy ((char *)serial, conf.serial, sizeof (serial)); |
589 | |
589 | |
… | |
… | |
599 | config_packet::chk_config (const conf_node *conf, const sockinfo &rsi) const |
599 | config_packet::chk_config (const conf_node *conf, const sockinfo &rsi) const |
600 | { |
600 | { |
601 | if (prot_major != PROTOCOL_MAJOR) |
601 | if (prot_major != PROTOCOL_MAJOR) |
602 | slog (L_WARN, _("%s(%s): major version mismatch (remote %d <=> local %d)"), |
602 | slog (L_WARN, _("%s(%s): major version mismatch (remote %d <=> local %d)"), |
603 | conf->nodename, (const char *)rsi, prot_major, PROTOCOL_MAJOR); |
603 | conf->nodename, (const char *)rsi, prot_major, PROTOCOL_MAJOR); |
604 | else if (randsize != RAND_SIZE) |
|
|
605 | slog (L_WARN, _("%s(%s): rand size mismatch (remote %d <=> local %d)"), |
|
|
606 | conf->nodename, (const char *)rsi, randsize, RAND_SIZE); |
|
|
607 | else if (cipher_nid != htonl (EVP_CIPHER_nid (CIPHER ()))) |
604 | else if (cipher_nid != htonl (EVP_CIPHER_nid (CIPHER ()))) |
608 | slog (L_WARN, _("%s(%s): cipher algo mismatch (remote %x <=> local %x)"), |
605 | slog (L_WARN, _("%s(%s): cipher algo mismatch (remote %x <=> local %x)"), |
609 | conf->nodename, (const char *)rsi, ntohl (cipher_nid), EVP_CIPHER_nid (CIPHER ())); |
606 | conf->nodename, (const char *)rsi, ntohl (cipher_nid), EVP_CIPHER_nid (CIPHER ())); |
610 | else if (mac_nid != htonl (EVP_MD_type (MAC_DIGEST ()))) |
607 | else if (mac_nid != htonl (EVP_MD_type (MAC_DIGEST ()))) |
611 | slog (L_WARN, _("%s(%s): mac algo mismatch (remote %x <=> local %x)"), |
608 | slog (L_WARN, _("%s(%s): mac algo mismatch (remote %x <=> local %x)"), |
… | |
… | |
715 | delete ictx; ictx = new crypto_ctx (rcv_auth, snd_auth, rcv_ecdh_a, rcv_auth.ecdh, 0); |
712 | delete ictx; ictx = new crypto_ctx (rcv_auth, snd_auth, rcv_ecdh_a, rcv_auth.ecdh, 0); |
716 | iseqno.reset (ntohl (rcv_auth.rsa.seqno) & 0x7fffffff); |
713 | iseqno.reset (ntohl (rcv_auth.rsa.seqno) & 0x7fffffff); |
717 | |
714 | |
718 | delete octx; octx = new crypto_ctx (snd_auth, rcv_auth, snd_ecdh_a, snd_ecdh_b , 1); |
715 | delete octx; octx = new crypto_ctx (snd_auth, rcv_auth, snd_ecdh_a, snd_ecdh_b , 1); |
719 | oseqno = ntohl (snd_auth.rsa.seqno) & 0x7fffffff; |
716 | oseqno = ntohl (snd_auth.rsa.seqno) & 0x7fffffff; |
720 | |
|
|
721 | oiv.reset (); |
|
|
722 | |
717 | |
723 | // make sure rekeying timeouts are slightly asymmetric |
718 | // make sure rekeying timeouts are slightly asymmetric |
724 | ev::tstamp rekey_interval = ::conf.rekey + (conf->id > THISNODE->id ? 10 : 0); |
719 | ev::tstamp rekey_interval = ::conf.rekey + (conf->id > THISNODE->id ? 10 : 0); |
725 | rekey.start (rekey_interval, rekey_interval); |
720 | rekey.start (rekey_interval, rekey_interval); |
726 | |
721 | |