aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Dunwoodie <ncon@mail.noconroy.net>2019-10-02 01:17:00 +0100
committerMatt Dunwoodie <ncon@mail.noconroy.net>2019-10-02 01:17:00 +0100
commit4cc3172aedfbd877e98c70c0fa229778332ef454 (patch)
treeb892bcee013457b6377b6c2516bd4367402b5f8a
parentI don't have a good commit message for this (diff)
downloadwireguard-openbsd-4cc3172aedfbd877e98c70c0fa229778332ef454.tar.xz
wireguard-openbsd-4cc3172aedfbd877e98c70c0fa229778332ef454.zip
Bugfixes
Fix a number of bugs, including: * If a transport packet arrived before the response during a handshake, it would panic with invalid state in session_promote. * p_rx_bytes/p_tx_bytes was not updated * p_lock should be exit_read, not exit_write in wg_device_tx_initiation * "want rekey" error str was not removed along with WG_REKEY
-rw-r--r--src/if_wg.c3
-rw-r--r--src/wireguard.c27
-rw-r--r--src/wireguard.h1
3 files changed, 16 insertions, 15 deletions
diff --git a/src/if_wg.c b/src/if_wg.c
index 0d22adf..fe2eb0d 100644
--- a/src/if_wg.c
+++ b/src/if_wg.c
@@ -542,6 +542,7 @@ wg_encrypt(struct mbuf *m)
drop:
m_freem(em);
counters_inc(tag->t_sc->sc_if.if_counters, ifc_oerrors);
+ DPRINTF(tag->t_sc, "failed transport tx: %s\n", wg_error_str[err]);
tag->t_state = WG_PKT_STATE_DEAD;
}
@@ -661,7 +662,7 @@ keepalive:
return;
drop:
counters_inc(tag->t_sc->sc_if.if_counters, ifc_ierrors);
- DPRINTF(tag->t_sc, "failed transport: %s\n", wg_error_str[err]);
+ DPRINTF(tag->t_sc, "failed transport rx: %s\n", wg_error_str[err]);
tag->t_state = WG_PKT_STATE_DEAD;
}
diff --git a/src/wireguard.c b/src/wireguard.c
index 557d6de..6c049b6 100644
--- a/src/wireguard.c
+++ b/src/wireguard.c
@@ -125,9 +125,9 @@ wg_device_new_session(struct wg_device *dev)
getnanotime(&session->s_created);
- rw_enter_write(&peer->p_lock);
+ rw_enter_write(&session->s_lock);
session->s_local_id = fm_insert(&dev->d_sessions, session);
- rw_exit_write(&peer->p_lock);
+ rw_exit_write(&session->s_lock);
return session;
}
@@ -146,13 +146,13 @@ wg_device_ref_peerkey(struct wg_device *dev, struct wg_pubkey *key)
uint32_t id = 0;
struct wg_peer *peer;
struct map_item *item;
- rw_enter_read(&dev->d_peers.d_lock);
+ rw_enter_read(&dev->d_peers.lock);
FM_FOREACH_FILLED(item, &dev->d_peers) {
peer = item->value;
if (memcmp(key->k, peer->p_remote.k, sizeof(key->k)) == 0)
id = peer->p_id;
}
- rw_exit_read(&dev->d_peers.d_lock);
+ rw_exit_read(&dev->d_peers.lock);
/* Take reference and return peer */
return wg_device_ref_peerid(dev, id);
@@ -237,17 +237,15 @@ wg_session_promote(struct wg_session *session)
/* Setup session: derive keys, initialise the antireplay structure */
rw_enter_write(&peer->p_lock);
rw_enter_write(&session->s_lock);
- if (session->s_state == WG_STATE_INITIATOR ||
- session->s_state == WG_STATE_RESPONDER) {
- goto leave;
- } else if (session->s_state == WG_STATE_RECV_RESPONSE) {
+ if (session->s_state == WG_STATE_RECV_RESPONSE) {
session->s_state = WG_STATE_INITIATOR;
wg_kdf(ks->k_txkey.k, ks->k_rxkey.k, NULL, hs->h_ck, NULL, 0);
} else if (session->s_state == WG_STATE_MADE_RESPONSE) {
session->s_state = WG_STATE_RESPONDER;
wg_kdf(ks->k_rxkey.k, ks->k_txkey.k, NULL, hs->h_ck, NULL, 0);
- } else
- panic("invalid session state");
+ } else {
+ goto leave;
+ }
antireplay_init(&ks->k_ar);
@@ -549,6 +547,7 @@ wg_device_rx_transport(struct wg_device *dev, struct wg_msg_transport *msg,
ret_error(WG_REPLAY);
session->s_keyset.k_rxcounter = counter;
+ session->s_peer->p_rx_bytes += data_len - WG_MAC_SIZE;
if (session->s_state == WG_STATE_RESPONDER &&
wg_timespec_timedout(&session->s_created, WG_REKEY_AFTER_TIME_RECV))
@@ -639,7 +638,7 @@ wg_device_tx_initiation(struct wg_device *dev, struct wg_msg_initiation *init,
wg_peer_put(peer);
return WG_OK;
leave:
- rw_exit_write(&peer->p_lock);
+ rw_exit_read(&peer->p_lock);
wg_peer_put(peer);
return ret;
}
@@ -746,6 +745,8 @@ wg_device_tx_transport(struct wg_device *dev, struct wg_msg_transport *msg,
session->s_keyset.k_txcounter > WG_REKEY_AFTER_MESSAGES)
dev->d_outq(session->s_peer, WG_PKT_INITIATION, session->s_peer->p_id);
+ session->s_peer->p_tx_bytes += len;
+
*s = session;
leave:
rw_exit_read(&session->s_lock);
@@ -917,7 +918,7 @@ wg_msg_response_valid_mac2(struct wg_msg_response *m, struct wg_cookie *c)
offsetof(struct wg_msg_response, mac2), WG_COOKIE_SIZE);
return timingsafe_bcmp(mac, m->mac2, WG_MAC_SIZE) ? WG_MAC : WG_OK;
}
-
+
void
wg_cookie_from_token(struct wg_cookie *c, struct wg_cookie_maker *cm,
uint8_t *ip, uint8_t ip_len)
@@ -929,7 +930,7 @@ wg_cookie_from_token(struct wg_cookie *c, struct wg_cookie_maker *cm,
blake2s(c->cookie, ip, cm->seed, WG_MAC_SIZE, ip_len, WG_COOKIE_SIZE);
}
-
+
void
wg_device_make_cookie(struct wg_device *dev, struct wg_cookie *c,
uint32_t sender, uint8_t mac[WG_MAC_SIZE], struct wg_msg_cookie *m)
diff --git a/src/wireguard.h b/src/wireguard.h
index 332cb28..5b64457 100644
--- a/src/wireguard.h
+++ b/src/wireguard.h
@@ -233,7 +233,6 @@ static char *wg_error_str[] = {
"replay detected",
"packet rejected",
"packet invalid",
- "want rekey",
"invalid state",
"invalid mac",
"invalid ID",