1 /* $OpenBSD: print-wg.c,v 1.6 2021/04/14 19:34:56 bluhm Exp $ */ 2 3 /* 4 * Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. 5 * Copyright (C) 2019-2020 Matt Dunwoodie <ncon@noconroy.net> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/types.h> 21 22 #include <stdio.h> 23 #include <stddef.h> 24 25 #include "interface.h" 26 #include "extract.h" 27 28 #define INITIATION 1 29 #define RESPONSE 2 30 #define COOKIE 3 31 #define DATA 4 32 33 struct wg_initiation { 34 uint32_t type; 35 uint32_t sender; 36 uint8_t fill[140]; /* Includes ephemeral + MAC */ 37 }; 38 39 struct wg_response { 40 uint32_t type; 41 uint32_t sender; 42 uint32_t receiver; 43 uint8_t fill[80]; /* Includes ephemeral + MAC */ 44 }; 45 46 struct wg_cookie { 47 uint32_t type; 48 uint32_t receiver; 49 uint8_t fill[56]; /* Includes nonce + encrypted cookie */ 50 }; 51 52 struct wg_data { 53 uint32_t type; 54 uint32_t receiver; 55 uint64_t nonce; 56 /* uint8_t data[variable]; - Variable length data */ 57 uint8_t mac[16]; 58 }; 59 60 /* 61 * Check if packet is a WireGuard packet, as WireGuard may run on any port. 62 */ 63 uint32_t 64 wg_match(const u_char *bp, u_int length) 65 { 66 uint32_t type; 67 68 if (length < sizeof(type)) 69 return 0; 70 71 if (snapend - bp < sizeof(type)) { 72 /* 73 * we don't have enough bytes to tell if it is wg, 74 * so don't claim it, and don't claim it's truncated 75 * wireguard either. 76 */ 77 return (0); 78 } 79 80 type = EXTRACT_LE_32BITS(bp); 81 82 if (type == INITIATION && length == sizeof(struct wg_initiation)) 83 return INITIATION; 84 if (type == RESPONSE && length == sizeof(struct wg_response)) 85 return RESPONSE; 86 if (type == COOKIE && length == sizeof(struct wg_cookie)) 87 return COOKIE; 88 if (type == DATA && length >= sizeof(struct wg_data)) 89 return DATA; 90 return 0; 91 } 92 93 /* 94 * Print WireGuard packet 95 */ 96 void 97 wg_print(const u_char *bp, u_int length) 98 { 99 uint32_t type; 100 uint64_t datalength; 101 struct wg_initiation *initiation = (void *)bp; 102 struct wg_response *response = (void *)bp; 103 struct wg_cookie *cookie = (void *)bp; 104 struct wg_data *data = (void *)bp; 105 u_int caplen; 106 107 caplen = snapend - bp; 108 if (caplen < sizeof(type)) 109 goto trunc; 110 111 if ((type = wg_match(bp, length)) == 0) { 112 /* doesn't match */ 113 printf("[wg] unknown"); 114 return; 115 } 116 117 switch (type) { 118 case INITIATION: 119 printf("[wg] initiation "); 120 if (caplen < offsetof(struct wg_initiation, fill)) 121 goto trunc; 122 printf("from 0x%08x", letoh32(initiation->sender)); 123 break; 124 case RESPONSE: 125 printf("[wg] response "); 126 if (caplen < offsetof(struct wg_response, fill)) 127 goto trunc; 128 printf("from 0x%08x to 0x%08x", 129 letoh32(response->sender), letoh32(response->receiver)); 130 break; 131 case COOKIE: 132 printf("[wg] cookie "); 133 if (caplen < offsetof(struct wg_cookie, fill)) 134 goto trunc; 135 printf(" to 0x%08x", letoh32(cookie->receiver)); 136 break; 137 case DATA: 138 datalength = length - sizeof(struct wg_data); 139 if (datalength != 0) 140 printf("[wg] data length %llu ", datalength); 141 else 142 printf("[wg] keepalive "); 143 if (caplen < offsetof(struct wg_data, mac)) 144 goto trunc; 145 printf("to 0x%08x nonce %llu", 146 letoh32(data->receiver), letoh64(data->nonce)); 147 break; 148 } 149 return; 150 151 trunc: 152 printf("[|wg]"); 153 } 154