1 /* $OpenBSD: print-wg.c,v 1.7 2021/09/16 12:35:20 visa 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
wg_match(const u_char * bp,u_int length)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
wg_print(const u_char * bp,u_int length)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 /* data->nonce may be unaligned. */
146 printf("to 0x%08x nonce %llu",
147 letoh32(data->receiver), EXTRACT_LE_64BITS(&data->nonce));
148 break;
149 }
150 return;
151
152 trunc:
153 printf("[|wg]");
154 }
155