wireguard: add dos mitigation support
[vpp.git] / src / plugins / wireguard / wireguard_cookie.c
old mode 100755 (executable)
new mode 100644 (file)
index aa476f7..595b877
@@ -20,6 +20,7 @@
 #include <vlib/vlib.h>
 
 #include <wireguard/wireguard_cookie.h>
+#include <wireguard/wireguard_chachapoly.h>
 #include <wireguard/wireguard.h>
 
 static void cookie_precompute_key (uint8_t *,
@@ -29,9 +30,9 @@ static void cookie_macs_mac1 (message_macs_t *, const void *, size_t,
                              const uint8_t[COOKIE_KEY_SIZE]);
 static void cookie_macs_mac2 (message_macs_t *, const void *, size_t,
                              const uint8_t[COOKIE_COOKIE_SIZE]);
-static void cookie_checker_make_cookie (vlib_main_t * vm, cookie_checker_t *,
+static void cookie_checker_make_cookie (vlib_main_t *vm, cookie_checker_t *,
                                        uint8_t[COOKIE_COOKIE_SIZE],
-                                       ip4_address_t ip4, u16 udp_port);
+                                       ip46_address_t *ip, u16 udp_port);
 
 /* Public Functions */
 void
@@ -57,6 +58,51 @@ cookie_checker_update (cookie_checker_t * cc, uint8_t key[COOKIE_INPUT_SIZE])
     }
 }
 
+void
+cookie_checker_create_payload (vlib_main_t *vm, cookie_checker_t *cc,
+                              message_macs_t *cm,
+                              uint8_t nonce[COOKIE_NONCE_SIZE],
+                              uint8_t ecookie[COOKIE_ENCRYPTED_SIZE],
+                              ip46_address_t *ip, u16 udp_port)
+{
+  uint8_t cookie[COOKIE_COOKIE_SIZE];
+
+  cookie_checker_make_cookie (vm, cc, cookie, ip, udp_port);
+  RAND_bytes (nonce, COOKIE_NONCE_SIZE);
+
+  wg_xchacha20poly1305_encrypt (vm, cookie, COOKIE_COOKIE_SIZE, ecookie,
+                               cm->mac1, COOKIE_MAC_SIZE, nonce,
+                               cc->cc_cookie_key);
+
+  wg_secure_zero_memory (cookie, sizeof (cookie));
+}
+
+bool
+cookie_maker_consume_payload (vlib_main_t *vm, cookie_maker_t *cp,
+                             uint8_t nonce[COOKIE_NONCE_SIZE],
+                             uint8_t ecookie[COOKIE_ENCRYPTED_SIZE])
+{
+  uint8_t cookie[COOKIE_COOKIE_SIZE];
+
+  if (cp->cp_mac1_valid == 0)
+    {
+      return false;
+    }
+
+  if (!wg_xchacha20poly1305_decrypt (vm, ecookie, COOKIE_ENCRYPTED_SIZE,
+                                    cookie, cp->cp_mac1_last, COOKIE_MAC_SIZE,
+                                    nonce, cp->cp_cookie_key))
+    {
+      return false;
+    }
+
+  clib_memcpy (cp->cp_cookie, cookie, COOKIE_COOKIE_SIZE);
+  cp->cp_birthdate = vlib_time_now (vm);
+  cp->cp_mac1_valid = 0;
+
+  return true;
+}
+
 void
 cookie_maker_mac (cookie_maker_t * cp, message_macs_t * cm, void *buf,
                  size_t len)
@@ -76,9 +122,9 @@ cookie_maker_mac (cookie_maker_t * cp, message_macs_t * cm, void *buf,
 }
 
 enum cookie_mac_state
-cookie_checker_validate_macs (vlib_main_t * vm, cookie_checker_t * cc,
-                             message_macs_t * cm, void *buf, size_t len,
-                             bool busy, ip4_address_t ip4, u16 udp_port)
+cookie_checker_validate_macs (vlib_main_t *vm, cookie_checker_t *cc,
+                             message_macs_t *cm, void *buf, size_t len,
+                             bool busy, ip46_address_t *ip, u16 udp_port)
 {
   message_macs_t our_cm;
   uint8_t cookie[COOKIE_COOKIE_SIZE];
@@ -86,14 +132,14 @@ cookie_checker_validate_macs (vlib_main_t * vm, cookie_checker_t * cc,
   len = len - sizeof (message_macs_t);
   cookie_macs_mac1 (&our_cm, buf, len, cc->cc_mac1_key);
 
-  /* If mac1 is invald, we want to drop the packet */
+  /* If mac1 is invalid, we want to drop the packet */
   if (clib_memcmp (our_cm.mac1, cm->mac1, COOKIE_MAC_SIZE) != 0)
     return INVALID_MAC;
 
   if (!busy)
     return VALID_MAC_BUT_NO_COOKIE;
 
-  cookie_checker_make_cookie (vm, cc, cookie, ip4, udp_port);
+  cookie_checker_make_cookie (vm, cc, cookie, ip, udp_port);
   cookie_macs_mac2 (&our_cm, buf, len, cookie);
 
   /* If the mac2 is invalid, we want to send a cookie response */
@@ -139,9 +185,9 @@ cookie_macs_mac2 (message_macs_t * cm, const void *buf, size_t len,
 }
 
 static void
-cookie_checker_make_cookie (vlib_main_t * vm, cookie_checker_t * cc,
+cookie_checker_make_cookie (vlib_main_t *vm, cookie_checker_t *cc,
                            uint8_t cookie[COOKIE_COOKIE_SIZE],
-                           ip4_address_t ip4, u16 udp_port)
+                           ip46_address_t *ip, u16 udp_port)
 {
   blake2s_state_t state;
 
@@ -155,7 +201,14 @@ cookie_checker_make_cookie (vlib_main_t * vm, cookie_checker_t * cc,
   blake2s_init_key (&state, COOKIE_COOKIE_SIZE, cc->cc_secret,
                    COOKIE_SECRET_SIZE);
 
-  blake2s_update (&state, ip4.as_u8, sizeof (ip4_address_t));  //TODO: IP6
+  if (ip46_address_is_ip4 (ip))
+    {
+      blake2s_update (&state, ip->ip4.as_u8, sizeof (ip4_address_t));
+    }
+  else
+    {
+      blake2s_update (&state, ip->ip6.as_u8, sizeof (ip6_address_t));
+    }
   blake2s_update (&state, (u8 *) & udp_port, sizeof (u16));
   blake2s_final (&state, cookie, COOKIE_COOKIE_SIZE);
 }