… | |
… | |
178 | |
178 | |
179 | return 1; |
179 | return 1; |
180 | } |
180 | } |
181 | |
181 | |
182 | static void |
182 | static void |
183 | auth_hash (const auth_data &auth, auth_mac &mac) |
183 | auth_hash (const auth_data &auth, const ecdh_key &b, auth_mac &mac) |
184 | { |
184 | { |
185 | HMAC_CTX ctx; |
185 | hkdf kdf (&auth.ecdh, sizeof (auth.ecdh), AUTH_DIGEST ()); // use remote ecdh b as salt |
186 | |
186 | kdf.extract (&auth.rsa, sizeof (auth.rsa)); |
187 | HMAC_CTX_init (&ctx); |
187 | kdf.extract_done (); |
188 | 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 |
189 | require (HMAC_Update (&ctx, (const unsigned char *)&auth, sizeof auth)); |
|
|
190 | require (HMAC_Final (&ctx, (unsigned char *)&mac, 0)); |
|
|
191 | HMAC_CTX_cleanup (&ctx); |
|
|
192 | } |
189 | } |
193 | |
190 | |
194 | void |
191 | void |
195 | connection::generate_auth_data () |
192 | connection::generate_auth_data () |
196 | { |
193 | { |
197 | if (auth_expire < ev_now ()) |
194 | if (auth_expire < ev_now ()) |
198 | { |
195 | { |
199 | // request data |
196 | // request data |
200 | rand_fill (snd_auth.rsa); |
197 | rand_fill (snd_auth.rsa); |
201 | curve25519_generate (snd_ecdh_a, snd_auth.ecdh); |
198 | curve25519_generate (snd_ecdh_a, snd_auth.ecdh); |
202 | auth_hash (snd_auth, snd_auth_mac); |
|
|
203 | |
199 | |
204 | // eventual response data |
200 | // eventual response data |
205 | curve25519_generate (rcv_ecdh_a, rcv_ecdh_b); |
201 | curve25519_generate (rcv_ecdh_a, rcv_ecdh_b); |
206 | } |
202 | } |
207 | |
203 | |
… | |
… | |
363 | } |
359 | } |
364 | } |
360 | } |
365 | |
361 | |
366 | ///////////////////////////////////////////////////////////////////////////// |
362 | ///////////////////////////////////////////////////////////////////////////// |
367 | |
363 | |
368 | unsigned char hmac_packet::hmac_digest[EVP_MAX_MD_SIZE]; |
|
|
369 | |
|
|
370 | void |
364 | void |
371 | hmac_packet::hmac_gen (crypto_ctx *ctx) |
365 | hmac_packet::hmac_gen (crypto_ctx *ctx, u8 *hmac_digest) |
372 | { |
366 | { |
373 | unsigned int xlen; |
|
|
374 | |
|
|
375 | HMAC_CTX *hctx = &ctx->hctx; |
367 | HMAC_CTX *hctx = &ctx->hctx; |
376 | |
368 | |
377 | require (HMAC_Init_ex (hctx, 0, 0, 0, 0)); |
369 | require (HMAC_Init_ex (hctx, 0, 0, 0, 0)); |
378 | 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))); |
379 | len - sizeof (hmac_packet))); |
|
|
380 | require (HMAC_Final (hctx, (unsigned char *) &hmac_digest, &xlen)); |
371 | require (HMAC_Final (hctx, hmac_digest, 0)); |
381 | } |
372 | } |
382 | |
373 | |
383 | void |
374 | void |
384 | hmac_packet::hmac_set (crypto_ctx *ctx) |
375 | hmac_packet::hmac_set (crypto_ctx *ctx) |
385 | { |
376 | { |
386 | hmac_gen (ctx); |
377 | unsigned char hmac_digest[EVP_MAX_MD_SIZE]; |
387 | |
378 | hmac_gen (ctx, hmac_digest); |
388 | memcpy (hmac, hmac_digest, HMACLENGTH); |
379 | memcpy (hmac, hmac_digest, HMACLENGTH); |
389 | } |
380 | } |
390 | |
381 | |
391 | bool |
382 | bool |
392 | hmac_packet::hmac_chk (crypto_ctx *ctx) |
383 | hmac_packet::hmac_chk (crypto_ctx *ctx) |
393 | { |
384 | { |
394 | hmac_gen (ctx); |
385 | unsigned char hmac_digest[EVP_MAX_MD_SIZE]; |
395 | |
386 | hmac_gen (ctx, hmac_digest); |
396 | return !memcmp (hmac, hmac_digest, HMACLENGTH); |
387 | return !memcmp (hmac, hmac_digest, HMACLENGTH); |
397 | } |
388 | } |
398 | |
389 | |
399 | void |
390 | void |
400 | vpn_packet::set_hdr (ptype type_, unsigned int dst) |
391 | vpn_packet::set_hdr (ptype type_, unsigned int dst) |
… | |
… | |
836 | void |
827 | void |
837 | connection::send_auth_response (const sockinfo &si) |
828 | connection::send_auth_response (const sockinfo &si) |
838 | { |
829 | { |
839 | auth_res_packet *pkt = new auth_res_packet (conf->id); |
830 | auth_res_packet *pkt = new auth_res_packet (conf->id); |
840 | |
831 | |
841 | auth_hash (rcv_auth, pkt->response.mac); |
|
|
842 | 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); |
843 | |
834 | |
844 | 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); |
845 | 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 |
846 | |
837 | |
847 | delete pkt; |
838 | delete pkt; |
… | |
… | |
1140 | { |
1131 | { |
1141 | auth_res_packet *p = (auth_res_packet *)pkt; |
1132 | auth_res_packet *p = (auth_res_packet *)pkt; |
1142 | |
1133 | |
1143 | slog (L_TRACE, "%s >> PT_AUTH_RES", conf->nodename); |
1134 | slog (L_TRACE, "%s >> PT_AUTH_RES", conf->nodename); |
1144 | |
1135 | |
|
|
1136 | auth_mac local_mac; |
|
|
1137 | auth_hash (snd_auth, p->response.ecdh, local_mac); |
|
|
1138 | |
1145 | if (memcmp (&p->response.mac, snd_auth_mac, sizeof (snd_auth_mac))) |
1139 | if (memcmp (&p->response.mac, local_mac, sizeof local_mac)) |
1146 | { |
1140 | { |
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 | memcpy (snd_ecdh_b, p->response.ecdh, sizeof (snd_ecdh_b)); |
1146 | memcpy (snd_ecdh_b, p->response.ecdh, sizeof snd_ecdh_b); |
1153 | |
1147 | |
1154 | have_snd_auth = true; |
1148 | have_snd_auth = true; |
1155 | connection_established (rsi); |
1149 | connection_established (rsi); |
1156 | } |
1150 | } |
1157 | |
1151 | |