ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/connection.C
(Generate patch)

Comparing gvpe/src/connection.C (file contents):
Revision 1.100 by root, Wed Jul 17 05:34:17 2013 UTC vs.
Revision 1.105 by root, Fri Jul 19 18:22:54 2013 UTC

48#include "hkdf.h" 48#include "hkdf.h"
49 49
50#include "netcompat.h" 50#include "netcompat.h"
51 51
52#define MAGIC "gvpe\xbd\xc6\xdb\x82" // 8 bytes of magic 52#define MAGIC "gvpe\xbd\xc6\xdb\x82" // 8 bytes of magic
53#define MAGIC "HUHN\xbd\xc6\xdb\x82" // 8 bytes of magic//D
53 54
54#define ULTRA_FAST 1 55#define ULTRA_FAST 1
55#define HLOG 15 56#define HLOG 15
56#include "lzf/lzf.h" 57#include "lzf/lzf.h"
57#include "lzf/lzf_c.c" 58#include "lzf/lzf_c.c"
119 { 120 {
120 u8 mac_key[MAC_KEYSIZE]; 121 u8 mac_key[MAC_KEYSIZE];
121 static const unsigned char mac_info[] = "gvpe mac key"; 122 static const unsigned char mac_info[] = "gvpe mac key";
122 123
123 hkdf kdf (auth2.rsa.hkdf_salt, sizeof (auth2.rsa.hkdf_salt), HKDF_XTR_HASH ()); 124 hkdf kdf (auth2.rsa.hkdf_salt, sizeof (auth2.rsa.hkdf_salt), HKDF_XTR_HASH ());
124 kdf.extract (auth2.rsa.ikm, sizeof (auth2.rsa.ikm));
125 kdf.extract (auth1.rsa.mac_key, sizeof (auth1.rsa.mac_key)); 125 kdf.extract (auth1.rsa.mac_key, sizeof (auth1.rsa.mac_key));
126 kdf.extract (s, sizeof (s)); 126 kdf.extract (s, sizeof (s));
127 kdf.extract_done (HKDF_PRF_HASH ()); 127 kdf.extract_done (HKDF_PRF_HASH ());
128 kdf.expand (mac_key, sizeof (mac_key), mac_info, sizeof (mac_info)); 128 kdf.expand (mac_key, sizeof (mac_key), mac_info, sizeof (mac_info));
129 129
134 { 134 {
135 u8 cipher_key[CIPHER_KEYSIZE]; 135 u8 cipher_key[CIPHER_KEYSIZE];
136 static const unsigned char cipher_info[] = "gvpe cipher key"; 136 static const unsigned char cipher_info[] = "gvpe cipher key";
137 137
138 hkdf kdf (auth2.rsa.hkdf_salt, sizeof (auth2.rsa.hkdf_salt), HKDF_XTR_HASH ()); 138 hkdf kdf (auth2.rsa.hkdf_salt, sizeof (auth2.rsa.hkdf_salt), HKDF_XTR_HASH ());
139 kdf.extract (auth2.rsa.ikm, sizeof (auth2.rsa.ikm));
140 kdf.extract (auth1.rsa.cipher_key, sizeof (auth1.rsa.cipher_key)); 139 kdf.extract (auth1.rsa.cipher_key, sizeof (auth1.rsa.cipher_key));
141 kdf.extract (s, sizeof (s)); 140 kdf.extract (s, sizeof (s));
142 kdf.extract_done (HKDF_PRF_HASH ()); 141 kdf.extract_done (HKDF_PRF_HASH ());
143 kdf.expand (cipher_key, sizeof (cipher_key), cipher_info, sizeof (cipher_info)); 142 kdf.expand (cipher_key, sizeof (cipher_key), cipher_info, sizeof (cipher_info));
144 143
179 178
180 return 1; 179 return 1;
181} 180}
182 181
183static void 182static void
184auth_hash (const auth_data &auth, auth_mac &mac) 183auth_hash (const auth_data &auth, const ecdh_key &b, auth_mac &mac)
185{ 184{
186 HMAC_CTX ctx; 185 hkdf kdf (&auth.ecdh, sizeof (auth.ecdh), AUTH_DIGEST ()); // use remote ecdh b as salt
187 186 kdf.extract (&auth.rsa, sizeof (auth.rsa));
188 HMAC_CTX_init (&ctx); 187 kdf.extract_done ();
189 require (HMAC_Init_ex (&ctx, auth.rsa.auth_key, sizeof (auth.rsa.auth_key), AUTH_DIGEST (), 0)); 188 kdf.expand (mac, sizeof mac, b, sizeof b); // use response ecdh b as info
190 require (HMAC_Update (&ctx, (const unsigned char *)&auth, sizeof auth));
191 require (HMAC_Final (&ctx, (unsigned char *)&mac, 0));
192 HMAC_CTX_cleanup (&ctx);
193} 189}
194 190
195void 191void
196connection::generate_auth_data () 192connection::generate_auth_data ()
197{ 193{
198 if (auth_expire < ev_now ()) 194 if (auth_expire < ev_now ())
199 { 195 {
200 // request data 196 // request data
201 RAND_bytes ((unsigned char *)&snd_auth.rsa, sizeof snd_auth.rsa); 197 rand_fill (snd_auth.rsa);
202 curve25519_generate (snd_ecdh_a, snd_auth.ecdh); 198 curve25519_generate (snd_ecdh_a, snd_auth.ecdh);
203 auth_hash (snd_auth, snd_auth_mac);
204 199
205 // eventual response data 200 // eventual response data
206 curve25519_generate (rcv_ecdh_a, rcv_ecdh_b); 201 curve25519_generate (rcv_ecdh_a, rcv_ecdh_b);
207 } 202 }
208 203
364 } 359 }
365} 360}
366 361
367///////////////////////////////////////////////////////////////////////////// 362/////////////////////////////////////////////////////////////////////////////
368 363
369unsigned char hmac_packet::hmac_digest[EVP_MAX_MD_SIZE];
370
371void 364void
372hmac_packet::hmac_gen (crypto_ctx *ctx) 365hmac_packet::hmac_gen (crypto_ctx *ctx, u8 *hmac_digest)
373{ 366{
374 unsigned int xlen;
375
376 HMAC_CTX *hctx = &ctx->hctx; 367 HMAC_CTX *hctx = &ctx->hctx;
377 368
378 require (HMAC_Init_ex (hctx, 0, 0, 0, 0)); 369 require (HMAC_Init_ex (hctx, 0, 0, 0, 0));
379 require (HMAC_Update (hctx, ((unsigned char *) this) + sizeof (hmac_packet), 370 require (HMAC_Update (hctx, ((unsigned char *) this) + sizeof (hmac_packet), len - sizeof (hmac_packet)));
380 len - sizeof (hmac_packet)));
381 require (HMAC_Final (hctx, (unsigned char *) &hmac_digest, &xlen)); 371 require (HMAC_Final (hctx, hmac_digest, 0));
382} 372}
383 373
384void 374void
385hmac_packet::hmac_set (crypto_ctx *ctx) 375hmac_packet::hmac_set (crypto_ctx *ctx)
386{ 376{
387 hmac_gen (ctx); 377 unsigned char hmac_digest[EVP_MAX_MD_SIZE];
388 378 hmac_gen (ctx, hmac_digest);
389 memcpy (hmac, hmac_digest, HMACLENGTH); 379 memcpy (hmac, hmac_digest, HMACLENGTH);
390} 380}
391 381
392bool 382bool
393hmac_packet::hmac_chk (crypto_ctx *ctx) 383hmac_packet::hmac_chk (crypto_ctx *ctx)
394{ 384{
395 hmac_gen (ctx); 385 unsigned char hmac_digest[EVP_MAX_MD_SIZE];
396 386 hmac_gen (ctx, hmac_digest);
397 return !memcmp (hmac, hmac_digest, HMACLENGTH); 387 return !memcmp (hmac, hmac_digest, HMACLENGTH);
398} 388}
399 389
400void 390void
401vpn_packet::set_hdr (ptype type_, unsigned int dst) 391vpn_packet::set_hdr (ptype type_, unsigned int dst)
461 u32 seqno; 451 u32 seqno;
462 } datahdr; 452 } datahdr;
463 453
464 datahdr.seqno = ntohl (seqno); 454 datahdr.seqno = ntohl (seqno);
465#if RAND_SIZE 455#if RAND_SIZE
466 RAND_bytes ((unsigned char *) datahdr.rnd, RAND_SIZE); 456 // NB: a constant (per session) random prefix
457 // is likely enough, but we don't take any chances.
458 conn->oiv.get (datahdr.rnd, RAND_SIZE);
467#endif 459#endif
468 460
469 require (EVP_EncryptUpdate (cctx, 461 require (EVP_EncryptUpdate (cctx,
470 (unsigned char *) data + outl, &outl2, 462 (unsigned char *) data + outl, &outl2,
471 (unsigned char *) &datahdr, DATAHDR)); 463 (unsigned char *) &datahdr, DATAHDR));
502 494
503 if (type == PT_DATA_COMPRESSED) 495 if (type == PT_DATA_COMPRESSED)
504 d = cdata; 496 d = cdata;
505 else 497 else
506#endif 498#endif
507 d = &(*p)[6 + 6 - DATAHDR]; 499 d = &(*p)[6 + 6] - DATAHDR;
508 500
509 /* this overwrites part of the src mac, but we fix that later */ 501 // we play do evil games with the struct layout atm.
502 // pending better solutions, we at least do some verification.
503 // this is fine, as we left ISO territory long ago.
504 require (DATAHDR <= 16);
505 require ((u8 *)(&p->len + 1) == &(*p)[0]);
506
507 // this can overwrite the len/dst/src fields
510 require (EVP_DecryptUpdate (cctx, 508 require (EVP_DecryptUpdate (cctx,
511 d, &outl2, 509 d, &outl2,
512 (unsigned char *)&data, len - data_hdr_size ())); 510 (unsigned char *)&data, len - data_hdr_size ()));
513 outl += outl2; 511 outl += outl2;
514 512
545 } 543 }
546}; 544};
547 545
548struct config_packet : vpn_packet 546struct config_packet : vpn_packet
549{ 547{
548 u8 serial[SERIAL_SIZE];
550 u8 prot_major, prot_minor, randsize; 549 u8 prot_major, prot_minor, randsize;
551 u8 flags, features, pad6, pad7, pad8; 550 u8 flags, features, pad6, pad7, pad8;
552 u32 cipher_nid, mac_nid, auth_nid; 551 u32 cipher_nid, mac_nid, auth_nid;
553 552
554 void setup (ptype type, int dst); 553 void setup (ptype type, int dst);
555 bool chk_config () const; 554 bool chk_config (const conf_node *conf, const sockinfo &rsi) const;
556 555
557 static u8 get_features () 556 static u8 get_features ()
558 { 557 {
559 u8 f = 0; 558 u8 f = 0;
560#if ENABLE_COMPRESSION 559#if ENABLE_COMPRESSION
577 prot_minor = PROTOCOL_MINOR; 576 prot_minor = PROTOCOL_MINOR;
578 randsize = RAND_SIZE; 577 randsize = RAND_SIZE;
579 flags = 0; 578 flags = 0;
580 features = get_features (); 579 features = get_features ();
581 580
581 strncpy ((char *)serial, conf.serial, sizeof (serial));
582
582 cipher_nid = htonl (EVP_CIPHER_nid (CIPHER ())); 583 cipher_nid = htonl (EVP_CIPHER_nid (CIPHER ()));
583 mac_nid = htonl (EVP_MD_type (MAC_DIGEST ())); 584 mac_nid = htonl (EVP_MD_type (MAC_DIGEST ()));
584 auth_nid = htonl (EVP_MD_type (AUTH_DIGEST ())); 585 auth_nid = htonl (EVP_MD_type (AUTH_DIGEST ()));
585 586
586 len = sizeof (*this) - sizeof (net_packet); 587 len = sizeof (*this) - sizeof (net_packet);
587 set_hdr (type, dst); 588 set_hdr (type, dst);
588} 589}
589 590
590bool 591bool
591config_packet::chk_config () const 592config_packet::chk_config (const conf_node *conf, const sockinfo &rsi) const
592{ 593{
593 if (prot_major != PROTOCOL_MAJOR) 594 if (prot_major != PROTOCOL_MAJOR)
594 slog (L_WARN, _("major version mismatch (remote %d <=> local %d)"), prot_major, PROTOCOL_MAJOR); 595 slog (L_WARN, _("%s(%s): major version mismatch (remote %d <=> local %d)"),
596 conf->nodename, (const char *)rsi, prot_major, PROTOCOL_MAJOR);
595 else if (randsize != RAND_SIZE) 597 else if (randsize != RAND_SIZE)
596 slog (L_WARN, _("rand size mismatch (remote %d <=> local %d)"), randsize, RAND_SIZE); 598 slog (L_WARN, _("%s(%s): rand size mismatch (remote %d <=> local %d)"),
599 conf->nodename, (const char *)rsi, randsize, RAND_SIZE);
597 else if (cipher_nid != htonl (EVP_CIPHER_nid (CIPHER ()))) 600 else if (cipher_nid != htonl (EVP_CIPHER_nid (CIPHER ())))
598 slog (L_WARN, _("cipher algo mismatch (remote %x <=> local %x)"), ntohl (cipher_nid), EVP_CIPHER_nid (CIPHER ())); 601 slog (L_WARN, _("%s(%s): cipher algo mismatch (remote %x <=> local %x)"),
602 conf->nodename, (const char *)rsi, ntohl (cipher_nid), EVP_CIPHER_nid (CIPHER ()));
599 else if (mac_nid != htonl (EVP_MD_type (MAC_DIGEST ()))) 603 else if (mac_nid != htonl (EVP_MD_type (MAC_DIGEST ())))
600 slog (L_WARN, _("mac algo mismatch (remote %x <=> local %x)"), ntohl (mac_nid), EVP_MD_type (MAC_DIGEST ())); 604 slog (L_WARN, _("%s(%s): mac algo mismatch (remote %x <=> local %x)"),
605 conf->nodename, (const char *)rsi, ntohl (mac_nid), EVP_MD_type (MAC_DIGEST ()));
601 else if (auth_nid != htonl (EVP_MD_type (AUTH_DIGEST ()))) 606 else if (auth_nid != htonl (EVP_MD_type (AUTH_DIGEST ())))
602 slog (L_WARN, _("auth algo mismatch (remote %x <=> local %x)"), ntohl (auth_nid), EVP_MD_type (AUTH_DIGEST ())); 607 slog (L_WARN, _("%s(%s): auth algo mismatch (remote %x <=> local %x)"),
608 conf->nodename, (const char *)rsi, ntohl (auth_nid), EVP_MD_type (AUTH_DIGEST ()));
603 else 609 else
610 {
611 int cmp = memcmp (serial, ::conf.serial, sizeof (serial));
612
613 if (cmp > 0)
614 slog (L_WARN, _("%s(%s): remote serial newer than local serial - outdated config?"),
615 conf->nodename, (const char *)rsi);
616 else if (cmp == 0)
604 return true; 617 return true;
618 }
605 619
606 return false; 620 return false;
607} 621}
608 622
609struct auth_req_packet : config_packet // UNPROTECTED 623struct auth_req_packet : config_packet // UNPROTECTED
623 637
624 len = sizeof (*this) - sizeof (net_packet); 638 len = sizeof (*this) - sizeof (net_packet);
625 } 639 }
626}; 640};
627 641
628struct auth_res_packet : config_packet // UNPROTECTED 642struct auth_res_packet : vpn_packet // UNPROTECTED
629{ 643{
630 auth_response response; 644 auth_response response;
631 645
632 auth_res_packet (int dst) 646 auth_res_packet (int dst)
633 { 647 {
634 config_packet::setup (PT_AUTH_RES, dst); 648 set_hdr (PT_AUTH_RES, dst);
635 649
636 len = sizeof (*this) - sizeof (net_packet); 650 len = sizeof (*this) - sizeof (net_packet);
637 } 651 }
638}; 652};
639 653
695 iseqno.reset (ntohl (rcv_auth.rsa.seqno) & 0x7fffffff); 709 iseqno.reset (ntohl (rcv_auth.rsa.seqno) & 0x7fffffff);
696 710
697 delete octx; octx = new crypto_ctx (snd_auth, rcv_auth, snd_ecdh_a, snd_ecdh_b , 1); 711 delete octx; octx = new crypto_ctx (snd_auth, rcv_auth, snd_ecdh_a, snd_ecdh_b , 1);
698 oseqno = ntohl (snd_auth.rsa.seqno) & 0x7fffffff; 712 oseqno = ntohl (snd_auth.rsa.seqno) & 0x7fffffff;
699 713
714 oiv.reset ();
715
716 // make sure rekeying timeouts are slightly asymmetric
717 ev::tstamp rekey_interval = ::conf.rekey + (conf->id > THISNODE->id ? 10 : 0);
718 rekey.start (rekey_interval, rekey_interval);
719
720 keepalive.start (::conf.keepalive);
721
722 // send queued packets
700 if (ictx && octx) 723 if (ictx && octx)
701 { 724 {
702 // make sure rekeying timeouts are slightly asymmetric 725 while (tap_packet *p = (tap_packet *)data_queue.get ())
703 ev::tstamp rekey_interval = ::conf.rekey + (conf->id > THISNODE->id ? 10 : 0);
704 rekey.start (rekey_interval, rekey_interval);
705
706 keepalive.start (::conf.keepalive);
707
708 // send queued packets
709 if (ictx && octx)
710 { 726 {
711 while (tap_packet *p = (tap_packet *)data_queue.get ())
712 {
713 if (p->len) send_data_packet (p); 727 if (p->len) send_data_packet (p);
714 delete p; 728 delete p;
715 }
716
717 while (vpn_packet *p = (vpn_packet *)vpn_queue.get ())
718 {
719 if (p->len) send_vpn_packet (p, si, IPTOS_RELIABILITY);
720 delete p;
721 }
722 } 729 }
723 730
731 while (vpn_packet *p = (vpn_packet *)vpn_queue.get ())
732 {
733 if (p->len) send_vpn_packet (p, si, IPTOS_RELIABILITY);
734 delete p;
735 }
736 }
737
724 vpn->connection_established (this); 738 vpn->connection_established (this);
725 }
726#if 0
727 else
728 {
729 retry_cnt = 0;
730 establish_connection.start (5);
731 keepalive.stop ();
732 rekey.stop ();
733 }
734#endif
735} 739}
736 740
737void 741void
738connection::reset_si () 742connection::reset_si ()
739{ 743{
823void 827void
824connection::send_auth_response (const sockinfo &si) 828connection::send_auth_response (const sockinfo &si)
825{ 829{
826 auth_res_packet *pkt = new auth_res_packet (conf->id); 830 auth_res_packet *pkt = new auth_res_packet (conf->id);
827 831
828 auth_hash (rcv_auth, pkt->response.mac);
829 memcpy (pkt->response.ecdh, rcv_ecdh_b, sizeof (rcv_ecdh_b)); 832 memcpy (pkt->response.ecdh, rcv_ecdh_b, sizeof rcv_ecdh_b);
833 auth_hash (rcv_auth, rcv_ecdh_b, pkt->response.mac);
830 834
831 slog (L_TRACE, "%s << PT_AUTH_RES [%s]", conf->nodename, (const char *)si); 835 slog (L_TRACE, "%s << PT_AUTH_RES [%s]", conf->nodename, (const char *)si);
832 send_vpn_packet (pkt, si, IPTOS_RELIABILITY); // rsa is very very costly 836 send_vpn_packet (pkt, si, IPTOS_RELIABILITY); // rsa is very very costly
833 837
834 delete pkt; 838 delete pkt;
1059 { 1063 {
1060 reset_connection (); 1064 reset_connection ();
1061 1065
1062 config_packet *p = (config_packet *) pkt; 1066 config_packet *p = (config_packet *) pkt;
1063 1067
1064 if (!p->chk_config ()) 1068 if (p->chk_config (conf, rsi) && connectmode == conf_node::C_ALWAYS)
1065 {
1066 slog (L_WARN, _("%s(%s): protocol mismatch, disabling node."),
1067 conf->nodename, (const char *)rsi);
1068 connectmode = conf_node::C_DISABLED;
1069 }
1070 else if (connectmode == conf_node::C_ALWAYS)
1071 establish_connection (); 1069 establish_connection ();
1072 } 1070 }
1073 break; 1071 break;
1074 1072
1075 case vpn_packet::PT_AUTH_REQ: 1073 case vpn_packet::PT_AUTH_REQ:
1079 1077
1080 slog (L_TRACE, "%s >> PT_AUTH_REQ(%s,p%02x,f%02x)", 1078 slog (L_TRACE, "%s >> PT_AUTH_REQ(%s,p%02x,f%02x)",
1081 conf->nodename, p->initiate ? "initiate" : "reply", 1079 conf->nodename, p->initiate ? "initiate" : "reply",
1082 p->protocols, p->features); 1080 p->protocols, p->features);
1083 1081
1084 if (p->chk_config () && !memcmp (p->magic, MAGIC, 8)) 1082 if (memcmp (p->magic, MAGIC, 8))
1083 {
1084 slog (L_WARN, _("%s(%s): protocol magic mismatch - stray packet?"),
1085 conf->nodename, (const char *)rsi);
1086 }
1087 else if (p->chk_config (conf, rsi))
1085 { 1088 {
1086 if (p->prot_minor != PROTOCOL_MINOR) 1089 if (p->prot_minor != PROTOCOL_MINOR)
1087 slog (L_INFO, _("%s(%s): protocol minor version mismatch: ours is %d, %s's is %d."), 1090 slog (L_INFO, _("%s(%s): protocol minor version mismatch: ours is %d, %s's is %d."),
1088 conf->nodename, (const char *)rsi, 1091 conf->nodename, (const char *)rsi,
1089 PROTOCOL_MINOR, conf->nodename, p->prot_minor); 1092 PROTOCOL_MINOR, conf->nodename, p->prot_minor);
1116 } 1119 }
1117 } 1120 }
1118 1121
1119 break; 1122 break;
1120 } 1123 }
1121 else
1122 slog (L_WARN, _("%s(%s): protocol mismatch."),
1123 conf->nodename, (const char *)rsi);
1124 1124
1125 send_reset (rsi); 1125 send_reset (rsi);
1126 } 1126 }
1127 1127
1128 break; 1128 break;
1131 { 1131 {
1132 auth_res_packet *p = (auth_res_packet *)pkt; 1132 auth_res_packet *p = (auth_res_packet *)pkt;
1133 1133
1134 slog (L_TRACE, "%s >> PT_AUTH_RES", conf->nodename); 1134 slog (L_TRACE, "%s >> PT_AUTH_RES", conf->nodename);
1135 1135
1136 if (p->chk_config ()) 1136 auth_mac local_mac;
1137 auth_hash (snd_auth, p->response.ecdh, local_mac);
1138
1139 if (memcmp (&p->response.mac, local_mac, sizeof local_mac))
1137 { 1140 {
1138 if (memcmp (&p->response.mac, snd_auth_mac, sizeof (snd_auth_mac)))
1139 {
1140 slog (L_ERR, _("%s(%s): unrequested or outdated auth response, ignoring."), 1141 slog (L_ERR, _("%s(%s): unrequested or outdated auth response, ignoring."),
1141 conf->nodename, (const char *)rsi); 1142 conf->nodename, (const char *)rsi);
1142 } 1143 }
1143 else if (!have_snd_auth) 1144 else if (!have_snd_auth)
1144 { 1145 {
1145 if (p->prot_minor != PROTOCOL_MINOR)
1146 slog (L_INFO, _("%s(%s): protocol minor version mismatch: ours is %d, %s's is %d."),
1147 conf->nodename, (const char *)rsi,
1148 PROTOCOL_MINOR, conf->nodename, p->prot_minor);
1149
1150 prot_minor = p->prot_minor;
1151 memcpy (snd_ecdh_b, p->response.ecdh, sizeof (snd_ecdh_b)); 1146 memcpy (snd_ecdh_b, p->response.ecdh, sizeof snd_ecdh_b);
1152 1147
1153 have_snd_auth = true; 1148 have_snd_auth = true;
1154 connection_established (rsi); 1149 connection_established (rsi);
1155 }
1156
1157 break;
1158 } 1150 }
1159 } 1151 }
1160
1161 send_reset (rsi);
1162 break; 1152 break;
1163 1153
1164 case vpn_packet::PT_DATA_COMPRESSED: 1154 case vpn_packet::PT_DATA_COMPRESSED:
1165#if !ENABLE_COMPRESSION 1155#if !ENABLE_COMPRESSION
1166 send_reset (rsi); 1156 send_reset (rsi);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines