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.101 by root, Wed Jul 17 16:40:57 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 "PORN\xbd\xc6\xdb\x82" // 8 bytes of magic//D 53#define MAGIC "HUHN\xbd\xc6\xdb\x82" // 8 bytes of magic//D
54 54
55#define ULTRA_FAST 1 55#define ULTRA_FAST 1
56#define HLOG 15 56#define HLOG 15
57#include "lzf/lzf.h" 57#include "lzf/lzf.h"
58#include "lzf/lzf_c.c" 58#include "lzf/lzf_c.c"
120 { 120 {
121 u8 mac_key[MAC_KEYSIZE]; 121 u8 mac_key[MAC_KEYSIZE];
122 static const unsigned char mac_info[] = "gvpe mac key"; 122 static const unsigned char mac_info[] = "gvpe mac key";
123 123
124 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 ());
125 kdf.extract (auth2.rsa.ikm, sizeof (auth2.rsa.ikm));
126 kdf.extract (auth1.rsa.mac_key, sizeof (auth1.rsa.mac_key)); 125 kdf.extract (auth1.rsa.mac_key, sizeof (auth1.rsa.mac_key));
127 kdf.extract (s, sizeof (s)); 126 kdf.extract (s, sizeof (s));
128 kdf.extract_done (HKDF_PRF_HASH ()); 127 kdf.extract_done (HKDF_PRF_HASH ());
129 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));
130 129
135 { 134 {
136 u8 cipher_key[CIPHER_KEYSIZE]; 135 u8 cipher_key[CIPHER_KEYSIZE];
137 static const unsigned char cipher_info[] = "gvpe cipher key"; 136 static const unsigned char cipher_info[] = "gvpe cipher key";
138 137
139 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 ());
140 kdf.extract (auth2.rsa.ikm, sizeof (auth2.rsa.ikm));
141 kdf.extract (auth1.rsa.cipher_key, sizeof (auth1.rsa.cipher_key)); 139 kdf.extract (auth1.rsa.cipher_key, sizeof (auth1.rsa.cipher_key));
142 kdf.extract (s, sizeof (s)); 140 kdf.extract (s, sizeof (s));
143 kdf.extract_done (HKDF_PRF_HASH ()); 141 kdf.extract_done (HKDF_PRF_HASH ());
144 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));
145 143
180 178
181 return 1; 179 return 1;
182} 180}
183 181
184static void 182static void
185auth_hash (const auth_data &auth, auth_mac &mac) 183auth_hash (const auth_data &auth, const ecdh_key &b, auth_mac &mac)
186{ 184{
187 HMAC_CTX ctx; 185 hkdf kdf (&auth.ecdh, sizeof (auth.ecdh), AUTH_DIGEST ()); // use remote ecdh b as salt
188 186 kdf.extract (&auth.rsa, sizeof (auth.rsa));
189 HMAC_CTX_init (&ctx); 187 kdf.extract_done ();
190 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
191 require (HMAC_Update (&ctx, (const unsigned char *)&auth, sizeof auth));
192 require (HMAC_Final (&ctx, (unsigned char *)&mac, 0));
193 HMAC_CTX_cleanup (&ctx);
194} 189}
195 190
196void 191void
197connection::generate_auth_data () 192connection::generate_auth_data ()
198{ 193{
199 if (auth_expire < ev_now ()) 194 if (auth_expire < ev_now ())
200 { 195 {
201 // request data 196 // request data
202 rand_fill (snd_auth.rsa); 197 rand_fill (snd_auth.rsa);
203 curve25519_generate (snd_ecdh_a, snd_auth.ecdh); 198 curve25519_generate (snd_ecdh_a, snd_auth.ecdh);
204 auth_hash (snd_auth, snd_auth_mac);
205 199
206 // eventual response data 200 // eventual response data
207 curve25519_generate (rcv_ecdh_a, rcv_ecdh_b); 201 curve25519_generate (rcv_ecdh_a, rcv_ecdh_b);
208 } 202 }
209 203
365 } 359 }
366} 360}
367 361
368///////////////////////////////////////////////////////////////////////////// 362/////////////////////////////////////////////////////////////////////////////
369 363
370unsigned char hmac_packet::hmac_digest[EVP_MAX_MD_SIZE];
371
372void 364void
373hmac_packet::hmac_gen (crypto_ctx *ctx) 365hmac_packet::hmac_gen (crypto_ctx *ctx, u8 *hmac_digest)
374{ 366{
375 unsigned int xlen;
376
377 HMAC_CTX *hctx = &ctx->hctx; 367 HMAC_CTX *hctx = &ctx->hctx;
378 368
379 require (HMAC_Init_ex (hctx, 0, 0, 0, 0)); 369 require (HMAC_Init_ex (hctx, 0, 0, 0, 0));
380 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)));
381 len - sizeof (hmac_packet)));
382 require (HMAC_Final (hctx, (unsigned char *) &hmac_digest, &xlen)); 371 require (HMAC_Final (hctx, hmac_digest, 0));
383} 372}
384 373
385void 374void
386hmac_packet::hmac_set (crypto_ctx *ctx) 375hmac_packet::hmac_set (crypto_ctx *ctx)
387{ 376{
388 hmac_gen (ctx); 377 unsigned char hmac_digest[EVP_MAX_MD_SIZE];
389 378 hmac_gen (ctx, hmac_digest);
390 memcpy (hmac, hmac_digest, HMACLENGTH); 379 memcpy (hmac, hmac_digest, HMACLENGTH);
391} 380}
392 381
393bool 382bool
394hmac_packet::hmac_chk (crypto_ctx *ctx) 383hmac_packet::hmac_chk (crypto_ctx *ctx)
395{ 384{
396 hmac_gen (ctx); 385 unsigned char hmac_digest[EVP_MAX_MD_SIZE];
397 386 hmac_gen (ctx, hmac_digest);
398 return !memcmp (hmac, hmac_digest, HMACLENGTH); 387 return !memcmp (hmac, hmac_digest, HMACLENGTH);
399} 388}
400 389
401void 390void
402vpn_packet::set_hdr (ptype type_, unsigned int dst) 391vpn_packet::set_hdr (ptype type_, unsigned int dst)
462 u32 seqno; 451 u32 seqno;
463 } datahdr; 452 } datahdr;
464 453
465 datahdr.seqno = ntohl (seqno); 454 datahdr.seqno = ntohl (seqno);
466#if RAND_SIZE 455#if RAND_SIZE
467 require (RAND_pseudo_bytes ((unsigned char *) datahdr.rnd, RAND_SIZE) >= 0); 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);
468#endif 459#endif
469 460
470 require (EVP_EncryptUpdate (cctx, 461 require (EVP_EncryptUpdate (cctx,
471 (unsigned char *) data + outl, &outl2, 462 (unsigned char *) data + outl, &outl2,
472 (unsigned char *) &datahdr, DATAHDR)); 463 (unsigned char *) &datahdr, DATAHDR));
552 } 543 }
553}; 544};
554 545
555struct config_packet : vpn_packet 546struct config_packet : vpn_packet
556{ 547{
548 u8 serial[SERIAL_SIZE];
557 u8 prot_major, prot_minor, randsize; 549 u8 prot_major, prot_minor, randsize;
558 u8 flags, features, pad6, pad7, pad8; 550 u8 flags, features, pad6, pad7, pad8;
559 u32 cipher_nid, mac_nid, auth_nid; 551 u32 cipher_nid, mac_nid, auth_nid;
560 552
561 void setup (ptype type, int dst); 553 void setup (ptype type, int dst);
562 bool chk_config () const; 554 bool chk_config (const conf_node *conf, const sockinfo &rsi) const;
563 555
564 static u8 get_features () 556 static u8 get_features ()
565 { 557 {
566 u8 f = 0; 558 u8 f = 0;
567#if ENABLE_COMPRESSION 559#if ENABLE_COMPRESSION
584 prot_minor = PROTOCOL_MINOR; 576 prot_minor = PROTOCOL_MINOR;
585 randsize = RAND_SIZE; 577 randsize = RAND_SIZE;
586 flags = 0; 578 flags = 0;
587 features = get_features (); 579 features = get_features ();
588 580
581 strncpy ((char *)serial, conf.serial, sizeof (serial));
582
589 cipher_nid = htonl (EVP_CIPHER_nid (CIPHER ())); 583 cipher_nid = htonl (EVP_CIPHER_nid (CIPHER ()));
590 mac_nid = htonl (EVP_MD_type (MAC_DIGEST ())); 584 mac_nid = htonl (EVP_MD_type (MAC_DIGEST ()));
591 auth_nid = htonl (EVP_MD_type (AUTH_DIGEST ())); 585 auth_nid = htonl (EVP_MD_type (AUTH_DIGEST ()));
592 586
593 len = sizeof (*this) - sizeof (net_packet); 587 len = sizeof (*this) - sizeof (net_packet);
594 set_hdr (type, dst); 588 set_hdr (type, dst);
595} 589}
596 590
597bool 591bool
598config_packet::chk_config () const 592config_packet::chk_config (const conf_node *conf, const sockinfo &rsi) const
599{ 593{
600 if (prot_major != PROTOCOL_MAJOR) 594 if (prot_major != PROTOCOL_MAJOR)
601 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);
602 else if (randsize != RAND_SIZE) 597 else if (randsize != RAND_SIZE)
603 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);
604 else if (cipher_nid != htonl (EVP_CIPHER_nid (CIPHER ()))) 600 else if (cipher_nid != htonl (EVP_CIPHER_nid (CIPHER ())))
605 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 ()));
606 else if (mac_nid != htonl (EVP_MD_type (MAC_DIGEST ()))) 603 else if (mac_nid != htonl (EVP_MD_type (MAC_DIGEST ())))
607 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 ()));
608 else if (auth_nid != htonl (EVP_MD_type (AUTH_DIGEST ()))) 606 else if (auth_nid != htonl (EVP_MD_type (AUTH_DIGEST ())))
609 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 ()));
610 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)
611 return true; 617 return true;
618 }
612 619
613 return false; 620 return false;
614} 621}
615 622
616struct auth_req_packet : config_packet // UNPROTECTED 623struct auth_req_packet : config_packet // UNPROTECTED
630 637
631 len = sizeof (*this) - sizeof (net_packet); 638 len = sizeof (*this) - sizeof (net_packet);
632 } 639 }
633}; 640};
634 641
635struct auth_res_packet : config_packet // UNPROTECTED 642struct auth_res_packet : vpn_packet // UNPROTECTED
636{ 643{
637 auth_response response; 644 auth_response response;
638 645
639 auth_res_packet (int dst) 646 auth_res_packet (int dst)
640 { 647 {
641 config_packet::setup (PT_AUTH_RES, dst); 648 set_hdr (PT_AUTH_RES, dst);
642 649
643 len = sizeof (*this) - sizeof (net_packet); 650 len = sizeof (*this) - sizeof (net_packet);
644 } 651 }
645}; 652};
646 653
702 iseqno.reset (ntohl (rcv_auth.rsa.seqno) & 0x7fffffff); 709 iseqno.reset (ntohl (rcv_auth.rsa.seqno) & 0x7fffffff);
703 710
704 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);
705 oseqno = ntohl (snd_auth.rsa.seqno) & 0x7fffffff; 712 oseqno = ntohl (snd_auth.rsa.seqno) & 0x7fffffff;
706 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
707 if (ictx && octx) 723 if (ictx && octx)
708 { 724 {
709 // make sure rekeying timeouts are slightly asymmetric 725 while (tap_packet *p = (tap_packet *)data_queue.get ())
710 ev::tstamp rekey_interval = ::conf.rekey + (conf->id > THISNODE->id ? 10 : 0);
711 rekey.start (rekey_interval, rekey_interval);
712
713 keepalive.start (::conf.keepalive);
714
715 // send queued packets
716 if (ictx && octx)
717 { 726 {
718 while (tap_packet *p = (tap_packet *)data_queue.get ())
719 {
720 if (p->len) send_data_packet (p); 727 if (p->len) send_data_packet (p);
721 delete p; 728 delete p;
722 }
723
724 while (vpn_packet *p = (vpn_packet *)vpn_queue.get ())
725 {
726 if (p->len) send_vpn_packet (p, si, IPTOS_RELIABILITY);
727 delete p;
728 }
729 } 729 }
730 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
731 vpn->connection_established (this); 738 vpn->connection_established (this);
732 }
733#if 0
734 else
735 {
736 retry_cnt = 0;
737 establish_connection.start (5);
738 keepalive.stop ();
739 rekey.stop ();
740 }
741#endif
742} 739}
743 740
744void 741void
745connection::reset_si () 742connection::reset_si ()
746{ 743{
830void 827void
831connection::send_auth_response (const sockinfo &si) 828connection::send_auth_response (const sockinfo &si)
832{ 829{
833 auth_res_packet *pkt = new auth_res_packet (conf->id); 830 auth_res_packet *pkt = new auth_res_packet (conf->id);
834 831
835 auth_hash (rcv_auth, pkt->response.mac);
836 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);
837 834
838 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);
839 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
840 837
841 delete pkt; 838 delete pkt;
1066 { 1063 {
1067 reset_connection (); 1064 reset_connection ();
1068 1065
1069 config_packet *p = (config_packet *) pkt; 1066 config_packet *p = (config_packet *) pkt;
1070 1067
1071 if (!p->chk_config ()) 1068 if (p->chk_config (conf, rsi) && connectmode == conf_node::C_ALWAYS)
1072 {
1073 slog (L_WARN, _("%s(%s): protocol mismatch, disabling node."),
1074 conf->nodename, (const char *)rsi);
1075 connectmode = conf_node::C_DISABLED;
1076 }
1077 else if (connectmode == conf_node::C_ALWAYS)
1078 establish_connection (); 1069 establish_connection ();
1079 } 1070 }
1080 break; 1071 break;
1081 1072
1082 case vpn_packet::PT_AUTH_REQ: 1073 case vpn_packet::PT_AUTH_REQ:
1086 1077
1087 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)",
1088 conf->nodename, p->initiate ? "initiate" : "reply", 1079 conf->nodename, p->initiate ? "initiate" : "reply",
1089 p->protocols, p->features); 1080 p->protocols, p->features);
1090 1081
1091 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))
1092 { 1088 {
1093 if (p->prot_minor != PROTOCOL_MINOR) 1089 if (p->prot_minor != PROTOCOL_MINOR)
1094 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."),
1095 conf->nodename, (const char *)rsi, 1091 conf->nodename, (const char *)rsi,
1096 PROTOCOL_MINOR, conf->nodename, p->prot_minor); 1092 PROTOCOL_MINOR, conf->nodename, p->prot_minor);
1123 } 1119 }
1124 } 1120 }
1125 1121
1126 break; 1122 break;
1127 } 1123 }
1128 else
1129 slog (L_WARN, _("%s(%s): protocol mismatch."),
1130 conf->nodename, (const char *)rsi);
1131 1124
1132 send_reset (rsi); 1125 send_reset (rsi);
1133 } 1126 }
1134 1127
1135 break; 1128 break;
1138 { 1131 {
1139 auth_res_packet *p = (auth_res_packet *)pkt; 1132 auth_res_packet *p = (auth_res_packet *)pkt;
1140 1133
1141 slog (L_TRACE, "%s >> PT_AUTH_RES", conf->nodename); 1134 slog (L_TRACE, "%s >> PT_AUTH_RES", conf->nodename);
1142 1135
1143 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))
1144 { 1140 {
1145 if (memcmp (&p->response.mac, snd_auth_mac, sizeof (snd_auth_mac)))
1146 {
1147 slog (L_ERR, _("%s(%s): unrequested or outdated auth response, ignoring."), 1141 slog (L_ERR, _("%s(%s): unrequested or outdated auth response, ignoring."),
1148 conf->nodename, (const char *)rsi); 1142 conf->nodename, (const char *)rsi);
1149 } 1143 }
1150 else if (!have_snd_auth) 1144 else if (!have_snd_auth)
1151 { 1145 {
1152 if (p->prot_minor != PROTOCOL_MINOR)
1153 slog (L_INFO, _("%s(%s): protocol minor version mismatch: ours is %d, %s's is %d."),
1154 conf->nodename, (const char *)rsi,
1155 PROTOCOL_MINOR, conf->nodename, p->prot_minor);
1156
1157 prot_minor = p->prot_minor;
1158 memcpy (snd_ecdh_b, p->response.ecdh, sizeof (snd_ecdh_b)); 1146 memcpy (snd_ecdh_b, p->response.ecdh, sizeof snd_ecdh_b);
1159 1147
1160 have_snd_auth = true; 1148 have_snd_auth = true;
1161 connection_established (rsi); 1149 connection_established (rsi);
1162 }
1163
1164 break;
1165 } 1150 }
1166 } 1151 }
1167
1168 send_reset (rsi);
1169 break; 1152 break;
1170 1153
1171 case vpn_packet::PT_DATA_COMPRESSED: 1154 case vpn_packet::PT_DATA_COMPRESSED:
1172#if !ENABLE_COMPRESSION 1155#if !ENABLE_COMPRESSION
1173 send_reset (rsi); 1156 send_reset (rsi);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines