summaryrefslogtreecommitdiffstats
path: root/src/if_wg.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/if_wg.c')
-rw-r--r--src/if_wg.c111
1 files changed, 53 insertions, 58 deletions
diff --git a/src/if_wg.c b/src/if_wg.c
index bb3322893ee..1674b519b00 100644
--- a/src/if_wg.c
+++ b/src/if_wg.c
@@ -315,6 +315,7 @@ wg_id_create(struct wg_softc *sc, struct wg_peer *p)
{
struct wg_id_item item = { arc4random() , p };
HASHMAP_SET(&sc->sc_id_hashmap, item);
+ DPRINTF("wg_id_create: %p - 0x%08x\n", p, item.id);
return item.id;
}
@@ -322,6 +323,7 @@ void
wg_id_destroy(struct wg_softc *sc, uint32_t id)
{
struct wg_id_item item = { id, NULL };
+ DPRINTF("wg_id_destroy: 0x%08x\n", id);
HASHMAP_UNSET(&sc->sc_id_hashmap, item);
}
@@ -590,6 +592,7 @@ void
wg_transmit_slow(struct wg_pkt *pkt)
{
uint32_t id;
+ enum wg_error e;
struct wg_msg_initiation *init;
struct wg_msg_response *resp;
struct wg_msg_cookie *cookie;
@@ -603,24 +606,29 @@ wg_transmit_slow(struct wg_pkt *pkt)
id = wg_handshake_clean(&pkt->p_p->p_hs);
wg_id_destroy(pkt->p_sc, id);
id = wg_id_create(pkt->p_sc, pkt->p_p);
- wg_handshake_make_initiation(&pkt->p_p->p_hs, id, init);
+ if ((e = wg_handshake_make_initiation(&pkt->p_p->p_hs, id, init)) != WG_OK) {
+ DPRINTF("wg_transmit_slow: unable to initiate %d\n", e);
+ goto dead;
+ }
break;
case WG_PKT_RESPONSE:
DPRINTF("wg_transmit_slow: response\n");
resp = mtod(pkt->p_m, struct wg_msg_response *);
pkt->p_m->m_len = sizeof(struct wg_msg_response);
- //id = wg_handshake_clean(&pkt->p_p->p_hs);
wg_id_destroy(pkt->p_sc, pkt->p_p->p_hs.hs_local_id);
id = wg_id_create(pkt->p_sc, pkt->p_p);
- if (wg_handshake_make_response(&pkt->p_p->p_hs, id, resp) != 0) {
- panic("temporary panic");
- DPRINTF("wg_transmit_slow: response bad state\n");
- pkt->p_state = WG_PKT_DEAD;
- return;
+
+ if ((e = wg_handshake_make_response(&pkt->p_p->p_hs, id, resp)) != WG_OK) {
+ DPRINTF("wg_transmit_slow: response bad state %d\n", e);
+ goto dead;
}
- /* TODO fix this - insecure */
- wg_session_from_handshake(&pkt->p_p->p_sess, &pkt->p_p->p_hs);
+
+ if ((e = wg_session_from_handshake(&pkt->p_p->p_sess, &pkt->p_p->p_hs)) != WG_OK) {
+ DPRINTF("wg_transmit_slow: unable to session %d\n", e);
+ goto dead;
+ };
+
wg_peer_new_session(pkt->p_sc, pkt->p_p);
break;
case WG_PKT_COOKIE:
@@ -636,6 +644,9 @@ wg_transmit_slow(struct wg_pkt *pkt)
m_calchdrlen(pkt->p_m);
pkt->p_state = WG_PKT_PASS;
+ return;
+dead:
+ pkt->p_state = WG_PKT_DEAD;
}
void
@@ -651,31 +662,21 @@ wg_receive_slow(struct wg_pkt *pkt)
switch (pkt->p_type) {
case WG_PKT_INITIATION:
init = mtod(pkt->p_m, struct wg_msg_initiation *);
- wg_handshake_init(&hs);
-
- hs.hs_skey = &pkt->p_sc->sc_kp;
-
- if ((e = wg_handshake_recv_initiation(&hs, init)) != 0) {
+ if ((e = wg_handshake_recv_initiation(&hs, &pkt->p_sc->sc_kp, init)) != WG_OK) {
DPRINTF("wg_receive_slow: bad initiation %d\n", e);
goto dead;
}
- p = wg_peer_lookup(pkt->p_sc, hs.hs_spub);
-
- if (p == NULL) {
+ if ((p = wg_peer_lookup(pkt->p_sc, hs.hs_spub)) == NULL) {
DPRINTF("wg_receive_slow: unable to find initiation peer\n");
goto dead;
}
- memcpy(hs.hs_spub, p->p_hs.hs_spub, sizeof(hs.hs_spub));
- memcpy(hs.hs_shared, p->p_hs.hs_shared, sizeof(hs.hs_shared));
-
- if (memcmp(hs.hs_timestamp, p->p_hs.hs_timestamp, WG_TIMESTAMP_SIZE) <= 0) {
- DPRINTF("wg_receive_slow: timestamp too old\n");
+ if ((e = wg_handshake_merge(&p->p_hs, &hs)) != WG_OK) {
+ DPRINTF("wg_receive_slow: unable to merge %d\n", e);
goto dead;
}
- wg_handshake_clone(&p->p_hs, &hs);
wg_send_pkt(p->p_sc, p, WG_PKT_RESPONSE);
break;
case WG_PKT_RESPONSE:
@@ -687,15 +688,16 @@ wg_receive_slow(struct wg_pkt *pkt)
goto dead;
}
- wg_handshake_init(&hs);
- wg_handshake_clone(&hs, &p->p_hs);
- if ((e = wg_handshake_recv_response(&hs, resp)) != 0) {
+ if ((e = wg_handshake_recv_response(&p->p_hs, resp)) != 0) {
DPRINTF("wg_receive_slow: bad response %d\n", e);
goto dead;
}
- wg_handshake_clone(&p->p_hs, &hs);
- wg_session_from_handshake(&p->p_sess, &p->p_hs);
+ if ((e = wg_session_from_handshake(&p->p_sess, &p->p_hs)) != WG_OK) {
+ DPRINTF("wg_receive_slow: unable to session %d\n", e);
+ goto dead;
+ };
+
wg_peer_new_session(pkt->p_sc, p);
break;
case WG_PKT_COOKIE:
@@ -743,8 +745,11 @@ wg_transport_encrypt(struct wg_pkt *pkt)
struct wg_session *s = &pkt->p_p->p_sess;
size_t encrypted_len, padding_len, plain_len;
- if (wg_session_rekey_tx(s))
- wg_want_init(pkt->p_p);
+ if (m_defrag(m, M_NOWAIT)) {
+ counters_inc(pkt->p_sc->sc_if.if_counters, ifc_oerrors);
+ pkt->p_state = WG_PKT_FREE;
+ return;
+ }
plain_len = m->m_pkthdr.len;
padding_len = WG_PADDING_SIZE(plain_len);
@@ -764,8 +769,18 @@ wg_transport_encrypt(struct wg_pkt *pkt)
memcpy(msg->data, mtod(m, void *), plain_len);
bzero(msg->data + plain_len, padding_len);
- if (wg_session_encrypt(s, msg, plain_len + padding_len) != 0) {
- m_free(m);
+ switch (wg_session_encrypt(s, msg, plain_len + padding_len)) {
+ case WG_REKEY:
+ wg_want_init(pkt->p_p);
+ case WG_OK:
+ break;
+ case WG_REJECT:
+ wg_want_init(pkt->p_p);
+ if (mq_push(&pkt->p_p->p_outgoing, m) != 0)
+ counters_inc(pkt->p_sc->sc_if.if_counters, ifc_oqdrops);
+ pkt->p_state = WG_PKT_DEAD;
+ return;
+ default:
pkt->p_state = WG_PKT_DEAD;
return;
}
@@ -806,19 +821,16 @@ wg_transport_decrypt(struct wg_pkt *pkt)
s = &pkt->p_p->p_sess;
- if (wg_session_reject_rx(s)) {
- pkt->p_state = WG_PKT_DEAD;
- return;
- }
-
- if (wg_session_decrypt(s, msg, m->m_pkthdr.len)) {
+ switch (wg_session_decrypt(s, msg, m->m_pkthdr.len)) {
+ case WG_REKEY:
+ wg_want_init(pkt->p_p);
+ case WG_OK:
+ break;
+ default:
pkt->p_state = WG_PKT_DEAD;
return;
}
- if (wg_session_rekey_rx(s))
- wg_want_init(pkt->p_p);
-
m_adj(m, sizeof(struct wg_msg_transport));
if (m->m_pkthdr.len == WG_ENCRYPTED_SIZE(0)) {
@@ -957,23 +969,6 @@ wg_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa, struct rtentry
goto exit;
}
- if (m_defrag(m, M_NOWAIT)) {
- counters_inc(sc->sc_if.if_counters, ifc_oerrors);
- error = ENOBUFS;
- goto exit;
- }
-
- if (wg_session_reject_tx(&p->p_sess)) {
- wg_want_init(p);
-
- if (mq_push(&p->p_outgoing, m) != 0) {
- error = ENOBUFS;
- counters_inc(sc->sc_if.if_counters, ifc_oqdrops);
- }
-
- goto exit;
- }
-
struct wg_pkt pkt = WG_PKT_INIT(p, m, sc, WG_PKT_TRANSPORT);
if (MPQ_ADD(wg_pkt_queue, &sc->sc_txq, &pkt) == 0) {