File: | src/sbin/iked/ikev2_msg.c |
Warning: | line 1196, column 3 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: ikev2_msg.c,v 1.84 2021/12/01 16:42:13 deraadt Exp $ */ | |||
2 | ||||
3 | /* | |||
4 | * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de> | |||
5 | * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org> | |||
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 | #include <sys/queue.h> | |||
22 | #include <sys/socket.h> | |||
23 | #include <sys/uio.h> | |||
24 | ||||
25 | #include <netinet/in.h> | |||
26 | #include <arpa/inet.h> | |||
27 | ||||
28 | #include <stdlib.h> | |||
29 | #include <stdio.h> | |||
30 | #include <syslog.h> | |||
31 | #include <unistd.h> | |||
32 | #include <string.h> | |||
33 | #include <signal.h> | |||
34 | #include <errno(*__errno()).h> | |||
35 | #include <err.h> | |||
36 | #include <event.h> | |||
37 | ||||
38 | #include <openssl/sha.h> | |||
39 | #include <openssl/evp.h> | |||
40 | ||||
41 | #include "iked.h" | |||
42 | #include "ikev2.h" | |||
43 | #include "eap.h" | |||
44 | #include "dh.h" | |||
45 | ||||
46 | void ikev1_recv(struct iked *, struct iked_message *); | |||
47 | void ikev2_msg_response_timeout(struct iked *, void *); | |||
48 | void ikev2_msg_retransmit_timeout(struct iked *, void *); | |||
49 | int ikev2_check_frag_oversize(struct iked_sa *, struct ibuf *); | |||
50 | int ikev2_send_encrypted_fragments(struct iked *, struct iked_sa *, | |||
51 | struct ibuf *, uint8_t, uint8_t, int); | |||
52 | int ikev2_msg_encrypt_prepare(struct iked_sa *, struct ikev2_payload *, | |||
53 | struct ibuf*, struct ibuf *, struct ike_header *, uint8_t, int); | |||
54 | ||||
55 | void | |||
56 | ikev2_msg_cb(int fd, short event, void *arg) | |||
57 | { | |||
58 | struct iked_socket *sock = arg; | |||
59 | struct iked *env = sock->sock_env; | |||
60 | struct iked_message msg; | |||
61 | struct ike_header hdr; | |||
62 | uint32_t natt = 0x00000000; | |||
63 | uint8_t buf[IKED_MSGBUF_MAX8192]; | |||
64 | ssize_t len; | |||
65 | off_t off; | |||
66 | ||||
67 | bzero(&msg, sizeof(msg)); | |||
68 | bzero(buf, sizeof(buf)); | |||
69 | ||||
70 | msg.msg_peerlen = sizeof(msg.msg_peer); | |||
71 | msg.msg_locallen = sizeof(msg.msg_local); | |||
72 | msg.msg_parent = &msg; | |||
73 | memcpy(&msg.msg_local, &sock->sock_addr, sizeof(sock->sock_addr)); | |||
74 | ||||
75 | if ((len = recvfromto(fd, buf, sizeof(buf), 0, | |||
76 | (struct sockaddr *)&msg.msg_peer, &msg.msg_peerlen, | |||
77 | (struct sockaddr *)&msg.msg_local, &msg.msg_locallen)) < | |||
78 | (ssize_t)sizeof(natt)) | |||
79 | return; | |||
80 | ||||
81 | if (socket_getport((struct sockaddr *)&msg.msg_local) == | |||
82 | env->sc_nattportsc_static.st_nattport) { | |||
83 | if (memcmp(&natt, buf, sizeof(natt)) != 0) | |||
84 | return; | |||
85 | msg.msg_natt = 1; | |||
86 | off = sizeof(natt); | |||
87 | } else | |||
88 | off = 0; | |||
89 | ||||
90 | if ((size_t)(len - off) <= sizeof(hdr)) | |||
91 | return; | |||
92 | memcpy(&hdr, buf + off, sizeof(hdr)); | |||
93 | ||||
94 | if ((msg.msg_data = ibuf_new(buf + off, len - off)) == NULL((void*)0)) | |||
95 | return; | |||
96 | ||||
97 | TAILQ_INIT(&msg.msg_proposals)do { (&msg.msg_proposals)->tqh_first = ((void*)0); (& msg.msg_proposals)->tqh_last = &(&msg.msg_proposals )->tqh_first; } while (0); | |||
98 | SIMPLEQ_INIT(&msg.msg_certreqs)do { (&msg.msg_certreqs)->sqh_first = ((void*)0); (& msg.msg_certreqs)->sqh_last = &(&msg.msg_certreqs) ->sqh_first; } while (0); | |||
99 | msg.msg_fd = fd; | |||
100 | ||||
101 | if (hdr.ike_version == IKEV1_VERSION0x10) | |||
102 | ikev1_recv(env, &msg); | |||
103 | else | |||
104 | ikev2_recv(env, &msg); | |||
105 | ||||
106 | ikev2_msg_cleanup(env, &msg); | |||
107 | } | |||
108 | ||||
109 | void | |||
110 | ikev1_recv(struct iked *env, struct iked_message *msg) | |||
111 | { | |||
112 | struct ike_header *hdr; | |||
113 | ||||
114 | if (ibuf_size(msg->msg_data) <= sizeof(*hdr)) { | |||
115 | log_debug("%s: short message", __func__); | |||
116 | return; | |||
117 | } | |||
118 | ||||
119 | hdr = (struct ike_header *)ibuf_data(msg->msg_data); | |||
120 | ||||
121 | log_debug("%s: header ispi %s rspi %s" | |||
122 | " nextpayload %u version 0x%02x exchange %u flags 0x%02x" | |||
123 | " msgid %u length %u", __func__, | |||
124 | print_spi(betoh64(hdr->ike_ispi)(__uint64_t)(__builtin_constant_p(hdr->ike_ispi) ? (__uint64_t )((((__uint64_t)(hdr->ike_ispi) & 0xff) << 56) | ((__uint64_t)(hdr->ike_ispi) & 0xff00ULL) << 40 | ((__uint64_t)(hdr->ike_ispi) & 0xff0000ULL) << 24 | ((__uint64_t)(hdr->ike_ispi) & 0xff000000ULL) << 8 | ((__uint64_t)(hdr->ike_ispi) & 0xff00000000ULL) >> 8 | ((__uint64_t)(hdr->ike_ispi) & 0xff0000000000ULL) >> 24 | ((__uint64_t)(hdr->ike_ispi) & 0xff000000000000ULL ) >> 40 | ((__uint64_t)(hdr->ike_ispi) & 0xff00000000000000ULL ) >> 56) : __swap64md(hdr->ike_ispi)), 8), | |||
125 | print_spi(betoh64(hdr->ike_rspi)(__uint64_t)(__builtin_constant_p(hdr->ike_rspi) ? (__uint64_t )((((__uint64_t)(hdr->ike_rspi) & 0xff) << 56) | ((__uint64_t)(hdr->ike_rspi) & 0xff00ULL) << 40 | ((__uint64_t)(hdr->ike_rspi) & 0xff0000ULL) << 24 | ((__uint64_t)(hdr->ike_rspi) & 0xff000000ULL) << 8 | ((__uint64_t)(hdr->ike_rspi) & 0xff00000000ULL) >> 8 | ((__uint64_t)(hdr->ike_rspi) & 0xff0000000000ULL) >> 24 | ((__uint64_t)(hdr->ike_rspi) & 0xff000000000000ULL ) >> 40 | ((__uint64_t)(hdr->ike_rspi) & 0xff00000000000000ULL ) >> 56) : __swap64md(hdr->ike_rspi)), 8), | |||
126 | hdr->ike_nextpayload, | |||
127 | hdr->ike_version, | |||
128 | hdr->ike_exchange, | |||
129 | hdr->ike_flags, | |||
130 | betoh32(hdr->ike_msgid)(__uint32_t)(__builtin_constant_p(hdr->ike_msgid) ? (__uint32_t )(((__uint32_t)(hdr->ike_msgid) & 0xff) << 24 | ( (__uint32_t)(hdr->ike_msgid) & 0xff00) << 8 | (( __uint32_t)(hdr->ike_msgid) & 0xff0000) >> 8 | ( (__uint32_t)(hdr->ike_msgid) & 0xff000000) >> 24 ) : __swap32md(hdr->ike_msgid)), | |||
131 | betoh32(hdr->ike_length)(__uint32_t)(__builtin_constant_p(hdr->ike_length) ? (__uint32_t )(((__uint32_t)(hdr->ike_length) & 0xff) << 24 | ((__uint32_t)(hdr->ike_length) & 0xff00) << 8 | ((__uint32_t)(hdr->ike_length) & 0xff0000) >> 8 | ((__uint32_t)(hdr->ike_length) & 0xff000000) >> 24) : __swap32md(hdr->ike_length))); | |||
132 | ||||
133 | log_debug("%s: IKEv1 not supported", __func__); | |||
134 | } | |||
135 | ||||
136 | struct ibuf * | |||
137 | ikev2_msg_init(struct iked *env, struct iked_message *msg, | |||
138 | struct sockaddr_storage *peer, socklen_t peerlen, | |||
139 | struct sockaddr_storage *local, socklen_t locallen, int response) | |||
140 | { | |||
141 | bzero(msg, sizeof(*msg)); | |||
142 | memcpy(&msg->msg_peer, peer, peerlen); | |||
143 | msg->msg_peerlen = peerlen; | |||
144 | memcpy(&msg->msg_local, local, locallen); | |||
145 | msg->msg_locallen = locallen; | |||
146 | msg->msg_response = response ? 1 : 0; | |||
147 | msg->msg_fd = -1; | |||
148 | msg->msg_data = ibuf_static(); | |||
149 | msg->msg_e = 0; | |||
150 | msg->msg_parent = msg; /* has to be set */ | |||
151 | TAILQ_INIT(&msg->msg_proposals)do { (&msg->msg_proposals)->tqh_first = ((void*)0); (&msg->msg_proposals)->tqh_last = &(&msg-> msg_proposals)->tqh_first; } while (0); | |||
152 | ||||
153 | return (msg->msg_data); | |||
154 | } | |||
155 | ||||
156 | struct iked_message * | |||
157 | ikev2_msg_copy(struct iked *env, struct iked_message *msg) | |||
158 | { | |||
159 | struct iked_message *m = NULL((void*)0); | |||
160 | struct ibuf *buf; | |||
161 | size_t len; | |||
162 | void *ptr; | |||
163 | ||||
164 | if (ibuf_size(msg->msg_data) < msg->msg_offset) | |||
165 | return (NULL((void*)0)); | |||
166 | len = ibuf_size(msg->msg_data) - msg->msg_offset; | |||
167 | ||||
168 | if ((m = malloc(sizeof(*m))) == NULL((void*)0)) | |||
169 | return (NULL((void*)0)); | |||
170 | ||||
171 | if ((ptr = ibuf_seek(msg->msg_data, msg->msg_offset, len)) == NULL((void*)0) || | |||
172 | (buf = ikev2_msg_init(env, m, &msg->msg_peer, msg->msg_peerlen, | |||
173 | &msg->msg_local, msg->msg_locallen, msg->msg_response)) == NULL((void*)0) || | |||
174 | ibuf_add(buf, ptr, len)) { | |||
175 | free(m); | |||
176 | return (NULL((void*)0)); | |||
177 | } | |||
178 | ||||
179 | m->msg_fd = msg->msg_fd; | |||
180 | m->msg_msgid = msg->msg_msgid; | |||
181 | m->msg_offset = msg->msg_offset; | |||
182 | m->msg_sa = msg->msg_sa; | |||
183 | ||||
184 | return (m); | |||
185 | } | |||
186 | ||||
187 | void | |||
188 | ikev2_msg_cleanup(struct iked *env, struct iked_message *msg) | |||
189 | { | |||
190 | struct iked_certreq *cr; | |||
191 | ||||
192 | if (msg == msg->msg_parent) { | |||
193 | ibuf_release(msg->msg_nonce); | |||
194 | ibuf_release(msg->msg_ke); | |||
195 | ibuf_release(msg->msg_auth.id_buf); | |||
196 | ibuf_release(msg->msg_peerid.id_buf); | |||
197 | ibuf_release(msg->msg_localid.id_buf); | |||
198 | ibuf_release(msg->msg_cert.id_buf); | |||
199 | ibuf_release(msg->msg_cookie); | |||
200 | ibuf_release(msg->msg_cookie2); | |||
201 | ibuf_release(msg->msg_del_buf); | |||
202 | free(msg->msg_eap.eam_user); | |||
203 | free(msg->msg_cp_addr); | |||
204 | free(msg->msg_cp_addr6); | |||
205 | free(msg->msg_cp_dns); | |||
206 | ||||
207 | msg->msg_nonce = NULL((void*)0); | |||
208 | msg->msg_ke = NULL((void*)0); | |||
209 | msg->msg_auth.id_buf = NULL((void*)0); | |||
210 | msg->msg_peerid.id_buf = NULL((void*)0); | |||
211 | msg->msg_localid.id_buf = NULL((void*)0); | |||
212 | msg->msg_cert.id_buf = NULL((void*)0); | |||
213 | msg->msg_cookie = NULL((void*)0); | |||
214 | msg->msg_cookie2 = NULL((void*)0); | |||
215 | msg->msg_del_buf = NULL((void*)0); | |||
216 | msg->msg_eap.eam_user = NULL((void*)0); | |||
217 | msg->msg_cp_addr = NULL((void*)0); | |||
218 | msg->msg_cp_addr6 = NULL((void*)0); | |||
219 | msg->msg_cp_dns = NULL((void*)0); | |||
220 | ||||
221 | config_free_proposals(&msg->msg_proposals, 0); | |||
222 | while ((cr = SIMPLEQ_FIRST(&msg->msg_certreqs)((&msg->msg_certreqs)->sqh_first))) { | |||
223 | ibuf_release(cr->cr_data); | |||
224 | SIMPLEQ_REMOVE_HEAD(&msg->msg_certreqs, cr_entry)do { if (((&msg->msg_certreqs)->sqh_first = (&msg ->msg_certreqs)->sqh_first->cr_entry.sqe_next) == (( void*)0)) (&msg->msg_certreqs)->sqh_last = &(& msg->msg_certreqs)->sqh_first; } while (0); | |||
225 | free(cr); | |||
226 | } | |||
227 | } | |||
228 | ||||
229 | if (msg->msg_data != NULL((void*)0)) { | |||
230 | ibuf_release(msg->msg_data); | |||
231 | msg->msg_data = NULL((void*)0); | |||
232 | } | |||
233 | } | |||
234 | ||||
235 | int | |||
236 | ikev2_msg_valid_ike_sa(struct iked *env, struct ike_header *oldhdr, | |||
237 | struct iked_message *msg) | |||
238 | { | |||
239 | if (msg->msg_sa != NULL((void*)0) && msg->msg_policy != NULL((void*)0)) { | |||
240 | if (msg->msg_sa->sa_state == IKEV2_STATE_CLOSED11) | |||
241 | return (-1); | |||
242 | /* | |||
243 | * Only permit informational requests from initiator | |||
244 | * on closing SAs (for DELETE). | |||
245 | */ | |||
246 | if (msg->msg_sa->sa_state == IKEV2_STATE_CLOSING10) { | |||
247 | if (((oldhdr->ike_flags & | |||
248 | (IKEV2_FLAG_INITIATOR0x08|IKEV2_FLAG_RESPONSE0x20)) == | |||
249 | IKEV2_FLAG_INITIATOR0x08) && | |||
250 | (oldhdr->ike_exchange == | |||
251 | IKEV2_EXCHANGE_INFORMATIONAL37)) | |||
252 | return (0); | |||
253 | return (-1); | |||
254 | } | |||
255 | return (0); | |||
256 | } | |||
257 | ||||
258 | /* Always fail */ | |||
259 | return (-1); | |||
260 | } | |||
261 | ||||
262 | int | |||
263 | ikev2_msg_send(struct iked *env, struct iked_message *msg) | |||
264 | { | |||
265 | struct iked_sa *sa = msg->msg_sa; | |||
266 | struct ibuf *buf = msg->msg_data; | |||
267 | uint32_t natt = 0x00000000; | |||
268 | int isnatt = 0; | |||
269 | uint8_t exchange, flags; | |||
270 | struct ike_header *hdr; | |||
271 | struct iked_message *m; | |||
272 | ||||
273 | if (buf == NULL((void*)0) || (hdr = ibuf_seek(msg->msg_data, | |||
274 | msg->msg_offset, sizeof(*hdr))) == NULL((void*)0)) | |||
275 | return (-1); | |||
276 | ||||
277 | isnatt = (msg->msg_natt || (sa && sa->sa_natt)); | |||
278 | ||||
279 | exchange = hdr->ike_exchange; | |||
280 | flags = hdr->ike_flags; | |||
281 | logit(exchange == IKEV2_EXCHANGE_INFORMATIONAL37 ? LOG_DEBUG7 : LOG_INFO6, | |||
282 | "%ssend %s %s %u peer %s local %s, %ld bytes%s", | |||
283 | SPI_IH(hdr)ikev2_ikesa_info((__uint64_t)(__builtin_constant_p((hdr)-> ike_ispi) ? (__uint64_t)((((__uint64_t)((hdr)->ike_ispi) & 0xff) << 56) | ((__uint64_t)((hdr)->ike_ispi) & 0xff00ULL) << 40 | ((__uint64_t)((hdr)->ike_ispi) & 0xff0000ULL) << 24 | ((__uint64_t)((hdr)->ike_ispi) & 0xff000000ULL) << 8 | ((__uint64_t)((hdr)->ike_ispi ) & 0xff00000000ULL) >> 8 | ((__uint64_t)((hdr)-> ike_ispi) & 0xff0000000000ULL) >> 24 | ((__uint64_t )((hdr)->ike_ispi) & 0xff000000000000ULL) >> 40 | ((__uint64_t)((hdr)->ike_ispi) & 0xff00000000000000ULL ) >> 56) : __swap64md((hdr)->ike_ispi)), ((void*)0)), | |||
284 | print_map(exchange, ikev2_exchange_map), | |||
285 | (flags & IKEV2_FLAG_RESPONSE0x20) ? "res" : "req", | |||
286 | betoh32(hdr->ike_msgid)(__uint32_t)(__builtin_constant_p(hdr->ike_msgid) ? (__uint32_t )(((__uint32_t)(hdr->ike_msgid) & 0xff) << 24 | ( (__uint32_t)(hdr->ike_msgid) & 0xff00) << 8 | (( __uint32_t)(hdr->ike_msgid) & 0xff0000) >> 8 | ( (__uint32_t)(hdr->ike_msgid) & 0xff000000) >> 24 ) : __swap32md(hdr->ike_msgid)), | |||
287 | print_host((struct sockaddr *)&msg->msg_peer, NULL((void*)0), 0), | |||
288 | print_host((struct sockaddr *)&msg->msg_local, NULL((void*)0), 0), | |||
289 | ibuf_length(buf), isnatt ? ", NAT-T" : ""); | |||
290 | ||||
291 | if (isnatt) { | |||
292 | if (ibuf_prepend(buf, &natt, sizeof(natt)) == -1) { | |||
293 | log_debug("%s: failed to set NAT-T", __func__); | |||
294 | return (-1); | |||
295 | } | |||
296 | } | |||
297 | ||||
298 | if (sendtofrom(msg->msg_fd, ibuf_data(buf), ibuf_size(buf), 0, | |||
299 | (struct sockaddr *)&msg->msg_peer, msg->msg_peerlen, | |||
300 | (struct sockaddr *)&msg->msg_local, msg->msg_locallen) == -1) { | |||
301 | log_warn("%s: sendtofrom", __func__); | |||
302 | if (sa != NULL((void*)0) && errno(*__errno()) == EADDRNOTAVAIL49) { | |||
303 | sa_state(env, sa, IKEV2_STATE_CLOSING10); | |||
304 | timer_del(env, &sa->sa_timer); | |||
305 | timer_set(env, &sa->sa_timer, | |||
306 | ikev2_ike_sa_timeout, sa); | |||
307 | timer_add(env, &sa->sa_timer, | |||
308 | IKED_IKE_SA_DELETE_TIMEOUT120); | |||
309 | } | |||
310 | } | |||
311 | ||||
312 | if (sa == NULL((void*)0)) | |||
313 | return (0); | |||
314 | ||||
315 | if ((m = ikev2_msg_copy(env, msg)) == NULL((void*)0)) { | |||
316 | log_debug("%s: failed to copy a message", __func__); | |||
317 | return (-1); | |||
318 | } | |||
319 | m->msg_exchange = exchange; | |||
320 | ||||
321 | if (flags & IKEV2_FLAG_RESPONSE0x20) { | |||
322 | TAILQ_INSERT_TAIL(&sa->sa_responses, m, msg_entry)do { (m)->msg_entry.tqe_next = ((void*)0); (m)->msg_entry .tqe_prev = (&sa->sa_responses)->tqh_last; *(&sa ->sa_responses)->tqh_last = (m); (&sa->sa_responses )->tqh_last = &(m)->msg_entry.tqe_next; } while (0); | |||
323 | timer_set(env, &m->msg_timer, ikev2_msg_response_timeout, m); | |||
324 | timer_add(env, &m->msg_timer, IKED_RESPONSE_TIMEOUT120); | |||
325 | } else { | |||
326 | TAILQ_INSERT_TAIL(&sa->sa_requests, m, msg_entry)do { (m)->msg_entry.tqe_next = ((void*)0); (m)->msg_entry .tqe_prev = (&sa->sa_requests)->tqh_last; *(&sa ->sa_requests)->tqh_last = (m); (&sa->sa_requests )->tqh_last = &(m)->msg_entry.tqe_next; } while (0); | |||
327 | timer_set(env, &m->msg_timer, ikev2_msg_retransmit_timeout, m); | |||
328 | timer_add(env, &m->msg_timer, IKED_RETRANSMIT_TIMEOUT2); | |||
329 | } | |||
330 | ||||
331 | return (0); | |||
332 | } | |||
333 | ||||
334 | uint32_t | |||
335 | ikev2_msg_id(struct iked *env, struct iked_sa *sa) | |||
336 | { | |||
337 | uint32_t id = sa->sa_reqid; | |||
338 | ||||
339 | if (++sa->sa_reqid == UINT32_MAX0xffffffffU) { | |||
340 | /* XXX we should close and renegotiate the connection now */ | |||
341 | log_debug("%s: IKEv2 message sequence overflow", __func__); | |||
342 | } | |||
343 | return (id); | |||
344 | } | |||
345 | ||||
346 | /* | |||
347 | * Calculate the final sizes of the IKEv2 header and the encrypted payload | |||
348 | * header. This must be done before encryption to make sure the correct | |||
349 | * headers are authenticated. | |||
350 | */ | |||
351 | int | |||
352 | ikev2_msg_encrypt_prepare(struct iked_sa *sa, struct ikev2_payload *pld, | |||
353 | struct ibuf *buf, struct ibuf *e, struct ike_header *hdr, | |||
354 | uint8_t firstpayload, int fragmentation) | |||
355 | { | |||
356 | size_t len, ivlen, encrlen, integrlen, blocklen, pldlen, outlen; | |||
357 | ||||
358 | if (sa == NULL((void*)0) || | |||
359 | sa->sa_encr == NULL((void*)0) || | |||
360 | sa->sa_integr == NULL((void*)0)) { | |||
361 | log_debug("%s: invalid SA", __func__); | |||
362 | return (-1); | |||
363 | } | |||
364 | ||||
365 | len = ibuf_size(e); | |||
366 | blocklen = cipher_length(sa->sa_encr); | |||
367 | integrlen = hash_length(sa->sa_integr); | |||
368 | ivlen = cipher_ivlength(sa->sa_encr); | |||
369 | encrlen = roundup(len + 1, blocklen)((((len + 1)+((blocklen)-1))/(blocklen))*(blocklen)); | |||
370 | outlen = cipher_outlength(sa->sa_encr, encrlen); | |||
371 | pldlen = ivlen + outlen + integrlen; | |||
372 | ||||
373 | if (ikev2_next_payload(pld, | |||
374 | pldlen + (fragmentation ? sizeof(struct ikev2_frag_payload) : 0), | |||
375 | firstpayload) == -1) | |||
376 | return (-1); | |||
377 | if (ikev2_set_header(hdr, ibuf_size(buf) + pldlen - sizeof(*hdr)) == -1) | |||
378 | return (-1); | |||
379 | ||||
380 | return (0); | |||
381 | } | |||
382 | ||||
383 | struct ibuf * | |||
384 | ikev2_msg_encrypt(struct iked *env, struct iked_sa *sa, struct ibuf *src, | |||
385 | struct ibuf *aad) | |||
386 | { | |||
387 | size_t len, encrlen, integrlen, blocklen, | |||
388 | outlen; | |||
389 | uint8_t *buf, pad = 0, *ptr; | |||
390 | struct ibuf *encr, *dst = NULL((void*)0), *out = NULL((void*)0); | |||
391 | ||||
392 | buf = ibuf_data(src); | |||
393 | len = ibuf_size(src); | |||
394 | ||||
395 | log_debug("%s: decrypted length %zu", __func__, len); | |||
396 | print_hex(buf, 0, len); | |||
397 | ||||
398 | if (sa == NULL((void*)0) || | |||
399 | sa->sa_encr == NULL((void*)0) || | |||
400 | sa->sa_integr == NULL((void*)0)) { | |||
401 | log_debug("%s: invalid SA", __func__); | |||
402 | goto done; | |||
403 | } | |||
404 | ||||
405 | if (sa->sa_hdr.sh_initiator) | |||
406 | encr = sa->sa_key_iencr; | |||
407 | else | |||
408 | encr = sa->sa_key_rencr; | |||
409 | ||||
410 | blocklen = cipher_length(sa->sa_encr); | |||
411 | integrlen = hash_length(sa->sa_integr); | |||
412 | encrlen = roundup(len + sizeof(pad), blocklen)((((len + sizeof(pad))+((blocklen)-1))/(blocklen))*(blocklen) ); | |||
413 | pad = encrlen - (len + sizeof(pad)); | |||
414 | ||||
415 | /* | |||
416 | * Pad the payload and encrypt it | |||
417 | */ | |||
418 | if (pad) { | |||
419 | if ((ptr = ibuf_advance(src, pad)) == NULL((void*)0)) | |||
420 | goto done; | |||
421 | arc4random_buf(ptr, pad); | |||
422 | } | |||
423 | if (ibuf_add(src, &pad, sizeof(pad)) != 0) | |||
424 | goto done; | |||
425 | ||||
426 | log_debug("%s: padded length %zu", __func__, ibuf_size(src)); | |||
427 | print_hex(ibuf_data(src), 0, ibuf_size(src)); | |||
428 | ||||
429 | cipher_setkey(sa->sa_encr, encr->buf, ibuf_length(encr)); | |||
430 | cipher_setiv(sa->sa_encr, NULL((void*)0), 0); /* XXX ivlen */ | |||
431 | if (cipher_init_encrypt(sa->sa_encr) == -1) { | |||
432 | log_info("%s: error initiating cipher.", __func__); | |||
433 | goto done; | |||
434 | } | |||
435 | ||||
436 | if ((dst = ibuf_dup(sa->sa_encr->encr_iv)) == NULL((void*)0)) | |||
437 | goto done; | |||
438 | ||||
439 | if ((out = ibuf_new(NULL((void*)0), | |||
440 | cipher_outlength(sa->sa_encr, encrlen))) == NULL((void*)0)) | |||
441 | goto done; | |||
442 | ||||
443 | outlen = ibuf_size(out); | |||
444 | ||||
445 | /* Add AAD for AEAD ciphers */ | |||
446 | if (sa->sa_integr->hash_isaead) | |||
447 | cipher_aad(sa->sa_encr, ibuf_data(aad), | |||
448 | ibuf_length(aad), &outlen); | |||
449 | ||||
450 | if (cipher_update(sa->sa_encr, ibuf_data(src), encrlen, | |||
451 | ibuf_data(out), &outlen) == -1) { | |||
452 | log_info("%s: error updating cipher.", __func__); | |||
453 | goto done; | |||
454 | } | |||
455 | ||||
456 | if (cipher_final(sa->sa_encr) == -1) { | |||
457 | log_info("%s: encryption failed.", __func__); | |||
458 | goto done; | |||
459 | } | |||
460 | ||||
461 | if (outlen && ibuf_add(dst, ibuf_data(out), outlen) != 0) | |||
462 | goto done; | |||
463 | ||||
464 | if ((ptr = ibuf_advance(dst, integrlen)) == NULL((void*)0)) | |||
465 | goto done; | |||
466 | explicit_bzero(ptr, integrlen); | |||
467 | ||||
468 | log_debug("%s: length %zu, padding %d, output length %zu", | |||
469 | __func__, len + sizeof(pad), pad, ibuf_size(dst)); | |||
470 | print_hex(ibuf_data(dst), 0, ibuf_size(dst)); | |||
471 | ||||
472 | ibuf_release(src); | |||
473 | ibuf_release(out); | |||
474 | return (dst); | |||
475 | done: | |||
476 | ibuf_release(src); | |||
477 | ibuf_release(out); | |||
478 | ibuf_release(dst); | |||
479 | return (NULL((void*)0)); | |||
480 | } | |||
481 | ||||
482 | int | |||
483 | ikev2_msg_integr(struct iked *env, struct iked_sa *sa, struct ibuf *src) | |||
484 | { | |||
485 | int ret = -1; | |||
486 | size_t integrlen, tmplen; | |||
487 | struct ibuf *integr, *tmp = NULL((void*)0); | |||
488 | uint8_t *ptr; | |||
489 | ||||
490 | log_debug("%s: message length %zu", __func__, ibuf_size(src)); | |||
491 | print_hex(ibuf_data(src), 0, ibuf_size(src)); | |||
492 | ||||
493 | if (sa == NULL((void*)0) || | |||
494 | sa->sa_encr == NULL((void*)0) || | |||
495 | sa->sa_integr == NULL((void*)0)) { | |||
496 | log_debug("%s: invalid SA", __func__); | |||
497 | return (-1); | |||
498 | } | |||
499 | ||||
500 | integrlen = hash_length(sa->sa_integr); | |||
501 | log_debug("%s: integrity checksum length %zu", __func__, | |||
502 | integrlen); | |||
503 | ||||
504 | /* | |||
505 | * Validate packet checksum | |||
506 | */ | |||
507 | if ((tmp = ibuf_new(NULL((void*)0), hash_keylength(sa->sa_integr))) == NULL((void*)0)) | |||
508 | goto done; | |||
509 | ||||
510 | if (!sa->sa_integr->hash_isaead) { | |||
511 | if (sa->sa_hdr.sh_initiator) | |||
512 | integr = sa->sa_key_iauth; | |||
513 | else | |||
514 | integr = sa->sa_key_rauth; | |||
515 | ||||
516 | hash_setkey(sa->sa_integr, ibuf_data(integr), | |||
517 | ibuf_size(integr)); | |||
518 | hash_init(sa->sa_integr); | |||
519 | hash_update(sa->sa_integr, ibuf_data(src), | |||
520 | ibuf_size(src) - integrlen); | |||
521 | hash_final(sa->sa_integr, ibuf_data(tmp), &tmplen); | |||
522 | ||||
523 | if (tmplen != integrlen) { | |||
524 | log_debug("%s: hash failure", __func__); | |||
525 | goto done; | |||
526 | } | |||
527 | } else { | |||
528 | /* Append AEAD tag */ | |||
529 | if (cipher_gettag(sa->sa_encr, ibuf_data(tmp), ibuf_size(tmp))) | |||
530 | goto done; | |||
531 | } | |||
532 | ||||
533 | if ((ptr = ibuf_seek(src, | |||
534 | ibuf_size(src) - integrlen, integrlen)) == NULL((void*)0)) | |||
535 | goto done; | |||
536 | memcpy(ptr, ibuf_data(tmp), integrlen); | |||
537 | ||||
538 | print_hex(ibuf_data(tmp), 0, ibuf_size(tmp)); | |||
539 | ||||
540 | ret = 0; | |||
541 | done: | |||
542 | ibuf_release(tmp); | |||
543 | ||||
544 | return (ret); | |||
545 | } | |||
546 | ||||
547 | struct ibuf * | |||
548 | ikev2_msg_decrypt(struct iked *env, struct iked_sa *sa, | |||
549 | struct ibuf *msg, struct ibuf *src) | |||
550 | { | |||
551 | ssize_t ivlen, encrlen, integrlen, blocklen, | |||
552 | outlen, tmplen; | |||
553 | uint8_t pad = 0, *ptr, *integrdata; | |||
554 | struct ibuf *integr, *encr, *tmp = NULL((void*)0), *out = NULL((void*)0); | |||
555 | off_t ivoff, encroff, integroff; | |||
556 | ||||
557 | if (sa == NULL((void*)0) || | |||
558 | sa->sa_encr == NULL((void*)0) || | |||
559 | sa->sa_integr == NULL((void*)0)) { | |||
560 | log_debug("%s: invalid SA", __func__); | |||
561 | print_hex(ibuf_data(src), 0, ibuf_size(src)); | |||
562 | goto done; | |||
563 | } | |||
564 | ||||
565 | if (!sa->sa_hdr.sh_initiator) { | |||
566 | encr = sa->sa_key_iencr; | |||
567 | integr = sa->sa_key_iauth; | |||
568 | } else { | |||
569 | encr = sa->sa_key_rencr; | |||
570 | integr = sa->sa_key_rauth; | |||
571 | } | |||
572 | ||||
573 | blocklen = cipher_length(sa->sa_encr); | |||
574 | ivlen = cipher_ivlength(sa->sa_encr); | |||
575 | ivoff = 0; | |||
576 | integrlen = hash_length(sa->sa_integr); | |||
577 | integroff = ibuf_size(src) - integrlen; | |||
578 | encroff = ivlen; | |||
579 | encrlen = ibuf_size(src) - integrlen - ivlen; | |||
580 | ||||
581 | if (encrlen < 0 || integroff < 0) { | |||
582 | log_debug("%s: invalid integrity value", __func__); | |||
583 | goto done; | |||
584 | } | |||
585 | ||||
586 | log_debug("%s: IV length %zd", __func__, ivlen); | |||
587 | print_hex(ibuf_data(src), 0, ivlen); | |||
588 | log_debug("%s: encrypted payload length %zd", __func__, encrlen); | |||
589 | print_hex(ibuf_data(src), encroff, encrlen); | |||
590 | log_debug("%s: integrity checksum length %zd", __func__, integrlen); | |||
591 | print_hex(ibuf_data(src), integroff, integrlen); | |||
592 | ||||
593 | /* | |||
594 | * Validate packet checksum | |||
595 | */ | |||
596 | if (!sa->sa_integr->hash_isaead) { | |||
597 | if ((tmp = ibuf_new(NULL((void*)0), hash_keylength(sa->sa_integr))) == NULL((void*)0)) | |||
598 | goto done; | |||
599 | ||||
600 | hash_setkey(sa->sa_integr, integr->buf, ibuf_length(integr)); | |||
601 | hash_init(sa->sa_integr); | |||
602 | hash_update(sa->sa_integr, ibuf_data(msg), | |||
603 | ibuf_size(msg) - integrlen); | |||
604 | hash_final(sa->sa_integr, tmp->buf, &tmplen); | |||
605 | ||||
606 | integrdata = ibuf_seek(src, integroff, integrlen); | |||
607 | if (integrdata == NULL((void*)0)) | |||
608 | goto done; | |||
609 | if (memcmp(tmp->buf, integrdata, integrlen) != 0) { | |||
610 | log_debug("%s: integrity check failed", __func__); | |||
611 | goto done; | |||
612 | } | |||
613 | ||||
614 | log_debug("%s: integrity check succeeded", __func__); | |||
615 | print_hex(tmp->buf, 0, tmplen); | |||
616 | ||||
617 | ibuf_release(tmp); | |||
618 | tmp = NULL((void*)0); | |||
619 | } | |||
620 | ||||
621 | /* | |||
622 | * Decrypt the payload and strip any padding | |||
623 | */ | |||
624 | if ((encrlen % blocklen) != 0) { | |||
625 | log_debug("%s: unaligned encrypted payload", __func__); | |||
626 | goto done; | |||
627 | } | |||
628 | ||||
629 | cipher_setkey(sa->sa_encr, encr->buf, ibuf_length(encr)); | |||
630 | cipher_setiv(sa->sa_encr, ibuf_data(src) + ivoff, ivlen); | |||
631 | if (cipher_init_decrypt(sa->sa_encr) == -1) { | |||
632 | log_info("%s: error initiating cipher.", __func__); | |||
633 | goto done; | |||
634 | } | |||
635 | ||||
636 | /* Set AEAD tag */ | |||
637 | if (sa->sa_integr->hash_isaead) { | |||
638 | integrdata = ibuf_seek(src, integroff, integrlen); | |||
639 | if (integrdata == NULL((void*)0)) | |||
640 | goto done; | |||
641 | if (cipher_settag(sa->sa_encr, integrdata, integrlen)) { | |||
642 | log_info("%s: failed to set tag.", __func__); | |||
643 | goto done; | |||
644 | } | |||
645 | } | |||
646 | ||||
647 | if ((out = ibuf_new(NULL((void*)0), cipher_outlength(sa->sa_encr, | |||
648 | encrlen))) == NULL((void*)0)) | |||
649 | goto done; | |||
650 | ||||
651 | /* | |||
652 | * Add additional authenticated data for AEAD ciphers | |||
653 | */ | |||
654 | if (sa->sa_integr->hash_isaead) { | |||
655 | log_debug("%s: AAD length %zu", __func__, ibuf_length(msg) - ibuf_length(src)); | |||
656 | print_hex(ibuf_data(msg), 0, ibuf_length(msg) - ibuf_length(src)); | |||
657 | cipher_aad(sa->sa_encr, ibuf_data(msg), | |||
658 | ibuf_length(msg) - ibuf_length(src), &outlen); | |||
659 | } | |||
660 | ||||
661 | if ((outlen = ibuf_length(out)) != 0) { | |||
662 | if (cipher_update(sa->sa_encr, ibuf_data(src) + encroff, | |||
663 | encrlen, ibuf_data(out), &outlen) == -1) { | |||
664 | log_info("%s: error updating cipher.", __func__); | |||
665 | goto done; | |||
666 | } | |||
667 | ||||
668 | ptr = ibuf_seek(out, outlen - 1, 1); | |||
669 | pad = *ptr; | |||
670 | } | |||
671 | ||||
672 | if (cipher_final(sa->sa_encr) == -1) { | |||
673 | log_info("%s: decryption failed.", __func__); | |||
674 | goto done; | |||
675 | } | |||
676 | ||||
677 | log_debug("%s: decrypted payload length %zd/%zd padding %d", | |||
678 | __func__, outlen, encrlen, pad); | |||
679 | print_hex(ibuf_data(out), 0, ibuf_size(out)); | |||
680 | ||||
681 | /* Strip padding and padding length */ | |||
682 | if (ibuf_setsize(out, outlen - pad - 1) != 0) | |||
683 | goto done; | |||
684 | ||||
685 | ibuf_release(src); | |||
686 | return (out); | |||
687 | done: | |||
688 | ibuf_release(tmp); | |||
689 | ibuf_release(out); | |||
690 | ibuf_release(src); | |||
691 | return (NULL((void*)0)); | |||
692 | } | |||
693 | ||||
694 | int | |||
695 | ikev2_check_frag_oversize(struct iked_sa *sa, struct ibuf *buf) { | |||
696 | size_t len = ibuf_length(buf); | |||
697 | sa_family_t sa_fam; | |||
698 | size_t max; | |||
699 | size_t ivlen, integrlen, blocklen; | |||
700 | ||||
701 | if (sa == NULL((void*)0) || | |||
702 | sa->sa_encr == NULL((void*)0) || | |||
703 | sa->sa_integr == NULL((void*)0)) { | |||
704 | log_debug("%s: invalid SA", __func__); | |||
705 | return (-1); | |||
706 | } | |||
707 | ||||
708 | sa_fam = ((struct sockaddr *)&sa->sa_local.addr)->sa_family; | |||
709 | ||||
710 | max = sa_fam == AF_INET2 ? IKEV2_MAXLEN_IPV4_FRAG(576 - (20 + 8 + 28)) | |||
711 | : IKEV2_MAXLEN_IPV6_FRAG(1280 - (40 + 8 + 28)); | |||
712 | ||||
713 | blocklen = cipher_length(sa->sa_encr); | |||
714 | ivlen = cipher_ivlength(sa->sa_encr); | |||
715 | integrlen = hash_length(sa->sa_integr); | |||
716 | ||||
717 | /* Estimated maximum packet size (with 0 < padding < blocklen) */ | |||
718 | return ((len + ivlen + blocklen + integrlen) >= max) && sa->sa_frag; | |||
719 | } | |||
720 | ||||
721 | int | |||
722 | ikev2_msg_send_encrypt(struct iked *env, struct iked_sa *sa, struct ibuf **ep, | |||
723 | uint8_t exchange, uint8_t firstpayload, int response) | |||
724 | { | |||
725 | struct iked_message resp; | |||
726 | struct ike_header *hdr; | |||
727 | struct ikev2_payload *pld; | |||
728 | struct ibuf *buf, *e = *ep; | |||
729 | int ret = -1; | |||
730 | ||||
731 | /* Check if msg needs to be fragmented */ | |||
732 | if (ikev2_check_frag_oversize(sa, e)) { | |||
733 | return ikev2_send_encrypted_fragments(env, sa, e, exchange, | |||
734 | firstpayload, response); | |||
735 | } | |||
736 | ||||
737 | if ((buf = ikev2_msg_init(env, &resp, &sa->sa_peer.addr, | |||
738 | sa->sa_peer.addr.ss_len, &sa->sa_local.addr, | |||
739 | sa->sa_local.addr.ss_len, response)) == NULL((void*)0)) | |||
740 | goto done; | |||
741 | ||||
742 | resp.msg_msgid = response ? sa->sa_msgid_current : ikev2_msg_id(env, sa); | |||
743 | ||||
744 | /* IKE header */ | |||
745 | if ((hdr = ikev2_add_header(buf, sa, resp.msg_msgid, IKEV2_PAYLOAD_SK46, | |||
746 | exchange, response ? IKEV2_FLAG_RESPONSE0x20 : 0)) == NULL((void*)0)) | |||
747 | goto done; | |||
748 | ||||
749 | if ((pld = ikev2_add_payload(buf)) == NULL((void*)0)) | |||
750 | goto done; | |||
751 | ||||
752 | if (ikev2_msg_encrypt_prepare(sa, pld, buf, e, hdr, firstpayload, 0) == -1) | |||
753 | goto done; | |||
754 | ||||
755 | /* Encrypt message and add as an E payload */ | |||
756 | if ((e = ikev2_msg_encrypt(env, sa, e, buf)) == NULL((void*)0)) { | |||
757 | log_debug("%s: encryption failed", __func__); | |||
758 | goto done; | |||
759 | } | |||
760 | if (ibuf_cat(buf, e) != 0) | |||
761 | goto done; | |||
762 | ||||
763 | /* Add integrity checksum (HMAC) */ | |||
764 | if (ikev2_msg_integr(env, sa, buf) != 0) { | |||
765 | log_debug("%s: integrity checksum failed", __func__); | |||
766 | goto done; | |||
767 | } | |||
768 | ||||
769 | resp.msg_data = buf; | |||
770 | resp.msg_sa = sa; | |||
771 | resp.msg_fd = sa->sa_fd; | |||
772 | TAILQ_INIT(&resp.msg_proposals)do { (&resp.msg_proposals)->tqh_first = ((void*)0); (& resp.msg_proposals)->tqh_last = &(&resp.msg_proposals )->tqh_first; } while (0); | |||
773 | ||||
774 | (void)ikev2_pld_parse(env, hdr, &resp, 0); | |||
775 | ||||
776 | ret = ikev2_msg_send(env, &resp); | |||
777 | ||||
778 | done: | |||
779 | /* e is cleaned up by the calling function */ | |||
780 | *ep = e; | |||
781 | ikev2_msg_cleanup(env, &resp); | |||
782 | ||||
783 | return (ret); | |||
784 | } | |||
785 | ||||
786 | int | |||
787 | ikev2_send_encrypted_fragments(struct iked *env, struct iked_sa *sa, | |||
788 | struct ibuf *in, uint8_t exchange, uint8_t firstpayload, int response) { | |||
789 | struct iked_message resp; | |||
790 | struct ibuf *buf, *e = NULL((void*)0); | |||
791 | struct ike_header *hdr; | |||
792 | struct ikev2_payload *pld; | |||
793 | struct ikev2_frag_payload *frag; | |||
794 | sa_family_t sa_fam; | |||
795 | size_t ivlen, integrlen, blocklen; | |||
796 | size_t max_len, left, offset=0; | |||
797 | size_t frag_num = 1, frag_total; | |||
798 | uint8_t *data; | |||
799 | uint32_t msgid; | |||
800 | int ret = -1; | |||
801 | ||||
802 | if (sa == NULL((void*)0) || | |||
803 | sa->sa_encr == NULL((void*)0) || | |||
804 | sa->sa_integr == NULL((void*)0)) { | |||
805 | log_debug("%s: invalid SA", __func__); | |||
806 | goto done; | |||
807 | } | |||
808 | ||||
809 | sa_fam = ((struct sockaddr *)&sa->sa_local.addr)->sa_family; | |||
810 | ||||
811 | left = ibuf_length(in); | |||
812 | ||||
813 | /* Calculate max allowed size of a fragments payload */ | |||
814 | blocklen = cipher_length(sa->sa_encr); | |||
815 | ivlen = cipher_ivlength(sa->sa_encr); | |||
816 | integrlen = hash_length(sa->sa_integr); | |||
817 | max_len = (sa_fam == AF_INET2 ? IKEV2_MAXLEN_IPV4_FRAG(576 - (20 + 8 + 28)) | |||
818 | : IKEV2_MAXLEN_IPV6_FRAG(1280 - (40 + 8 + 28))) | |||
819 | - ivlen - blocklen - integrlen; | |||
820 | ||||
821 | /* Total number of fragments to send */ | |||
822 | frag_total = (left / max_len) + 1; | |||
823 | ||||
824 | msgid = response ? sa->sa_msgid_current : ikev2_msg_id(env, sa); | |||
825 | ||||
826 | while (frag_num <= frag_total) { | |||
827 | if ((buf = ikev2_msg_init(env, &resp, &sa->sa_peer.addr, | |||
828 | sa->sa_peer.addr.ss_len, &sa->sa_local.addr, | |||
829 | sa->sa_local.addr.ss_len, response)) == NULL((void*)0)) | |||
830 | goto done; | |||
831 | ||||
832 | resp.msg_msgid = msgid; | |||
833 | ||||
834 | /* IKE header */ | |||
835 | if ((hdr = ikev2_add_header(buf, sa, resp.msg_msgid, | |||
836 | IKEV2_PAYLOAD_SKF53, exchange, response ? IKEV2_FLAG_RESPONSE0x20 | |||
837 | : 0)) == NULL((void*)0)) | |||
838 | goto done; | |||
839 | ||||
840 | /* Payload header */ | |||
841 | if ((pld = ikev2_add_payload(buf)) == NULL((void*)0)) | |||
842 | goto done; | |||
843 | ||||
844 | /* Fragment header */ | |||
845 | if ((frag = ibuf_advance(buf, sizeof(*frag))) == NULL((void*)0)) { | |||
846 | log_debug("%s: failed to add SKF fragment header", | |||
847 | __func__); | |||
848 | goto done; | |||
849 | } | |||
850 | frag->frag_num = htobe16(frag_num)(__uint16_t)(__builtin_constant_p(frag_num) ? (__uint16_t)((( __uint16_t)(frag_num) & 0xffU) << 8 | ((__uint16_t) (frag_num) & 0xff00U) >> 8) : __swap16md(frag_num)); | |||
851 | frag->frag_total = htobe16(frag_total)(__uint16_t)(__builtin_constant_p(frag_total) ? (__uint16_t)( ((__uint16_t)(frag_total) & 0xffU) << 8 | ((__uint16_t )(frag_total) & 0xff00U) >> 8) : __swap16md(frag_total )); | |||
852 | ||||
853 | /* Encrypt message and add as an E payload */ | |||
854 | data = ibuf_seek(in, offset, 0); | |||
855 | if ((e = ibuf_new(data, MINIMUM(left, max_len)(((left)<(max_len))?(left):(max_len)))) == NULL((void*)0)) { | |||
856 | goto done; | |||
857 | } | |||
858 | ||||
859 | if (ikev2_msg_encrypt_prepare(sa, pld, buf, e, hdr, | |||
860 | firstpayload, 1) == -1) | |||
861 | goto done; | |||
862 | ||||
863 | if ((e = ikev2_msg_encrypt(env, sa, e, buf)) == NULL((void*)0)) { | |||
864 | log_debug("%s: encryption failed", __func__); | |||
865 | goto done; | |||
866 | } | |||
867 | if (ibuf_cat(buf, e) != 0) | |||
868 | goto done; | |||
869 | ||||
870 | /* Add integrity checksum (HMAC) */ | |||
871 | if (ikev2_msg_integr(env, sa, buf) != 0) { | |||
872 | log_debug("%s: integrity checksum failed", __func__); | |||
873 | goto done; | |||
874 | } | |||
875 | ||||
876 | log_debug("%s: Fragment %zu of %zu has size of %zu bytes.", | |||
877 | __func__, frag_num, frag_total, | |||
878 | ibuf_size(buf) - sizeof(*hdr)); | |||
879 | print_hex(ibuf_data(buf), 0, ibuf_size(buf)); | |||
880 | ||||
881 | resp.msg_data = buf; | |||
882 | resp.msg_sa = sa; | |||
883 | resp.msg_fd = sa->sa_fd; | |||
884 | TAILQ_INIT(&resp.msg_proposals)do { (&resp.msg_proposals)->tqh_first = ((void*)0); (& resp.msg_proposals)->tqh_last = &(&resp.msg_proposals )->tqh_first; } while (0); | |||
885 | ||||
886 | if (ikev2_msg_send(env, &resp) == -1) | |||
887 | goto done; | |||
888 | ||||
889 | offset += MINIMUM(left, max_len)(((left)<(max_len))?(left):(max_len)); | |||
890 | left -= MINIMUM(left, max_len)(((left)<(max_len))?(left):(max_len)); | |||
891 | frag_num++; | |||
892 | ||||
893 | /* MUST be zero after first fragment */ | |||
894 | firstpayload = 0; | |||
895 | ||||
896 | ikev2_msg_cleanup(env, &resp); | |||
897 | ibuf_release(e); | |||
898 | e = NULL((void*)0); | |||
899 | } | |||
900 | ||||
901 | return 0; | |||
902 | done: | |||
903 | ikev2_msg_cleanup(env, &resp); | |||
904 | ibuf_release(e); | |||
905 | return ret; | |||
906 | } | |||
907 | ||||
908 | struct ibuf * | |||
909 | ikev2_msg_auth(struct iked *env, struct iked_sa *sa, int response) | |||
910 | { | |||
911 | struct ibuf *authmsg = NULL((void*)0), *nonce, *prfkey, *buf; | |||
912 | uint8_t *ptr; | |||
913 | struct iked_id *id; | |||
914 | size_t tmplen; | |||
915 | ||||
916 | /* | |||
917 | * Create the payload to be signed/MAC'ed for AUTH | |||
918 | */ | |||
919 | ||||
920 | if (!response) { | |||
921 | if ((nonce = sa->sa_rnoncesa_kex.kex_rnonce) == NULL((void*)0) || | |||
922 | (sa->sa_iid.id_type == 0) || | |||
923 | (prfkey = sa->sa_key_iprf) == NULL((void*)0) || | |||
924 | (buf = sa->sa_1stmsg) == NULL((void*)0)) | |||
925 | return (NULL((void*)0)); | |||
926 | id = &sa->sa_iid; | |||
927 | } else { | |||
928 | if ((nonce = sa->sa_inoncesa_kex.kex_inonce) == NULL((void*)0) || | |||
929 | (sa->sa_rid.id_type == 0) || | |||
930 | (prfkey = sa->sa_key_rprf) == NULL((void*)0) || | |||
931 | (buf = sa->sa_2ndmsg) == NULL((void*)0)) | |||
932 | return (NULL((void*)0)); | |||
933 | id = &sa->sa_rid; | |||
934 | } | |||
935 | ||||
936 | if ((authmsg = ibuf_dup(buf)) == NULL((void*)0)) | |||
937 | return (NULL((void*)0)); | |||
938 | if (ibuf_cat(authmsg, nonce) != 0) | |||
939 | goto fail; | |||
940 | ||||
941 | if ((hash_setkey(sa->sa_prf, ibuf_data(prfkey), | |||
942 | ibuf_size(prfkey))) == NULL((void*)0)) | |||
943 | goto fail; | |||
944 | ||||
945 | /* require non-truncating hash */ | |||
946 | if (hash_keylength(sa->sa_prf) != hash_length(sa->sa_prf)) | |||
947 | goto fail; | |||
948 | ||||
949 | if ((ptr = ibuf_advance(authmsg, hash_keylength(sa->sa_prf))) == NULL((void*)0)) | |||
950 | goto fail; | |||
951 | ||||
952 | hash_init(sa->sa_prf); | |||
953 | hash_update(sa->sa_prf, ibuf_data(id->id_buf), ibuf_size(id->id_buf)); | |||
954 | hash_final(sa->sa_prf, ptr, &tmplen); | |||
955 | ||||
956 | if (tmplen != hash_length(sa->sa_prf)) | |||
957 | goto fail; | |||
958 | ||||
959 | log_debug("%s: %s auth data length %zu", | |||
960 | __func__, response ? "responder" : "initiator", | |||
961 | ibuf_size(authmsg)); | |||
962 | print_hex(ibuf_data(authmsg), 0, ibuf_size(authmsg)); | |||
963 | ||||
964 | return (authmsg); | |||
965 | ||||
966 | fail: | |||
967 | ibuf_release(authmsg); | |||
968 | return (NULL((void*)0)); | |||
969 | } | |||
970 | ||||
971 | int | |||
972 | ikev2_msg_authverify(struct iked *env, struct iked_sa *sa, | |||
973 | struct iked_auth *auth, uint8_t *buf, size_t len, struct ibuf *authmsg) | |||
974 | { | |||
975 | uint8_t *key, *psk = NULL((void*)0); | |||
976 | ssize_t keylen; | |||
977 | struct iked_id *id; | |||
978 | struct iked_dsa *dsa = NULL((void*)0); | |||
979 | int ret = -1; | |||
980 | uint8_t keytype; | |||
981 | ||||
982 | if (sa->sa_hdr.sh_initiator) | |||
983 | id = &sa->sa_rcert; | |||
984 | else | |||
985 | id = &sa->sa_icert; | |||
986 | ||||
987 | if ((dsa = dsa_verify_new(auth->auth_method, sa->sa_prf)) == NULL((void*)0)) { | |||
988 | log_debug("%s: invalid auth method", __func__); | |||
989 | return (-1); | |||
990 | } | |||
991 | ||||
992 | switch (auth->auth_method) { | |||
993 | case IKEV2_AUTH_SHARED_KEY_MIC2: | |||
994 | if (!auth->auth_length) { | |||
995 | log_debug("%s: no pre-shared key found", __func__); | |||
996 | goto done; | |||
997 | } | |||
998 | if ((keylen = ikev2_psk(sa, auth->auth_data, | |||
999 | auth->auth_length, &psk)) == -1) { | |||
1000 | log_debug("%s: failed to get PSK", __func__); | |||
1001 | goto done; | |||
1002 | } | |||
1003 | key = psk; | |||
1004 | keytype = 0; | |||
1005 | break; | |||
1006 | default: | |||
1007 | if (!id->id_type || !ibuf_length(id->id_buf)) { | |||
1008 | log_debug("%s: no cert found", __func__); | |||
1009 | goto done; | |||
1010 | } | |||
1011 | key = ibuf_data(id->id_buf); | |||
1012 | keylen = ibuf_size(id->id_buf); | |||
1013 | keytype = id->id_type; | |||
1014 | break; | |||
1015 | } | |||
1016 | ||||
1017 | log_debug("%s: method %s keylen %zd type %s", __func__, | |||
1018 | print_map(auth->auth_method, ikev2_auth_map), keylen, | |||
1019 | print_map(id->id_type, ikev2_cert_map)); | |||
1020 | ||||
1021 | if (dsa_setkey(dsa, key, keylen, keytype) == NULL((void*)0) || | |||
1022 | dsa_init(dsa, buf, len) != 0 || | |||
1023 | dsa_update(dsa, ibuf_data(authmsg), ibuf_size(authmsg))) { | |||
1024 | log_debug("%s: failed to compute digital signature", __func__); | |||
1025 | goto done; | |||
1026 | } | |||
1027 | ||||
1028 | if ((ret = dsa_verify_final(dsa, buf, len)) == 0) { | |||
1029 | log_debug("%s: authentication successful", __func__); | |||
1030 | sa_state(env, sa, IKEV2_STATE_AUTH_SUCCESS6); | |||
1031 | sa_stateflags(sa, IKED_REQ_AUTHVALID0x0010); | |||
1032 | } else { | |||
1033 | log_debug("%s: authentication failed", __func__); | |||
1034 | sa_state(env, sa, IKEV2_STATE_AUTH_REQUEST5); | |||
1035 | } | |||
1036 | ||||
1037 | done: | |||
1038 | free(psk); | |||
1039 | dsa_free(dsa); | |||
1040 | ||||
1041 | return (ret); | |||
1042 | } | |||
1043 | ||||
1044 | int | |||
1045 | ikev2_msg_authsign(struct iked *env, struct iked_sa *sa, | |||
1046 | struct iked_auth *auth, struct ibuf *authmsg) | |||
1047 | { | |||
1048 | uint8_t *key, *psk = NULL((void*)0); | |||
1049 | ssize_t keylen, siglen; | |||
1050 | struct iked_hash *prf = sa->sa_prf; | |||
1051 | struct iked_id *id; | |||
1052 | struct iked_dsa *dsa = NULL((void*)0); | |||
1053 | struct ibuf *buf; | |||
1054 | int ret = -1; | |||
1055 | uint8_t keytype; | |||
1056 | ||||
1057 | if (sa->sa_hdr.sh_initiator) | |||
1058 | id = &sa->sa_icert; | |||
1059 | else | |||
1060 | id = &sa->sa_rcert; | |||
1061 | ||||
1062 | if ((dsa = dsa_sign_new(auth->auth_method, prf)) == NULL((void*)0)) { | |||
1063 | log_debug("%s: invalid auth method", __func__); | |||
1064 | return (-1); | |||
1065 | } | |||
1066 | ||||
1067 | switch (auth->auth_method) { | |||
1068 | case IKEV2_AUTH_SHARED_KEY_MIC2: | |||
1069 | if (!auth->auth_length) { | |||
1070 | log_debug("%s: no pre-shared key found", __func__); | |||
1071 | goto done; | |||
1072 | } | |||
1073 | if ((keylen = ikev2_psk(sa, auth->auth_data, | |||
1074 | auth->auth_length, &psk)) == -1) { | |||
1075 | log_debug("%s: failed to get PSK", __func__); | |||
1076 | goto done; | |||
1077 | } | |||
1078 | key = psk; | |||
1079 | keytype = 0; | |||
1080 | break; | |||
1081 | default: | |||
1082 | if (id == NULL((void*)0)) { | |||
1083 | log_debug("%s: no cert found", __func__); | |||
1084 | goto done; | |||
1085 | } | |||
1086 | key = ibuf_data(id->id_buf); | |||
1087 | keylen = ibuf_size(id->id_buf); | |||
1088 | keytype = id->id_type; | |||
1089 | break; | |||
1090 | } | |||
1091 | ||||
1092 | if (dsa_setkey(dsa, key, keylen, keytype) == NULL((void*)0) || | |||
1093 | dsa_init(dsa, NULL((void*)0), 0) != 0 || | |||
1094 | dsa_update(dsa, ibuf_data(authmsg), ibuf_size(authmsg))) { | |||
1095 | log_debug("%s: failed to compute digital signature", __func__); | |||
1096 | goto done; | |||
1097 | } | |||
1098 | ||||
1099 | ibuf_release(sa->sa_localauth.id_buf); | |||
1100 | sa->sa_localauth.id_buf = NULL((void*)0); | |||
1101 | ||||
1102 | if ((buf = ibuf_new(NULL((void*)0), dsa_length(dsa))) == NULL((void*)0)) { | |||
1103 | log_debug("%s: failed to get auth buffer", __func__); | |||
1104 | goto done; | |||
1105 | } | |||
1106 | ||||
1107 | if ((siglen = dsa_sign_final(dsa, | |||
1108 | ibuf_data(buf), ibuf_size(buf))) < 0) { | |||
1109 | log_debug("%s: failed to create auth signature", __func__); | |||
1110 | ibuf_release(buf); | |||
1111 | goto done; | |||
1112 | } | |||
1113 | ||||
1114 | if (ibuf_setsize(buf, siglen) < 0) { | |||
1115 | log_debug("%s: failed to set auth signature size to %zd", | |||
1116 | __func__, siglen); | |||
1117 | ibuf_release(buf); | |||
1118 | goto done; | |||
1119 | } | |||
1120 | ||||
1121 | sa->sa_localauth.id_type = auth->auth_method; | |||
1122 | sa->sa_localauth.id_buf = buf; | |||
1123 | ||||
1124 | ret = 0; | |||
1125 | done: | |||
1126 | free(psk); | |||
1127 | dsa_free(dsa); | |||
1128 | ||||
1129 | return (ret); | |||
1130 | } | |||
1131 | ||||
1132 | int | |||
1133 | ikev2_msg_frompeer(struct iked_message *msg) | |||
1134 | { | |||
1135 | struct iked_sa *sa = msg->msg_sa; | |||
1136 | struct ike_header *hdr; | |||
1137 | ||||
1138 | msg = msg->msg_parent; | |||
1139 | ||||
1140 | if (sa == NULL((void*)0) || | |||
1141 | (hdr = ibuf_seek(msg->msg_data, 0, sizeof(*hdr))) == NULL((void*)0)) | |||
1142 | return (0); | |||
1143 | ||||
1144 | if (!sa->sa_hdr.sh_initiator && | |||
1145 | (hdr->ike_flags & IKEV2_FLAG_INITIATOR0x08)) | |||
1146 | return (1); | |||
1147 | else if (sa->sa_hdr.sh_initiator && | |||
1148 | (hdr->ike_flags & IKEV2_FLAG_INITIATOR0x08) == 0) | |||
1149 | return (1); | |||
1150 | ||||
1151 | return (0); | |||
1152 | } | |||
1153 | ||||
1154 | struct iked_socket * | |||
1155 | ikev2_msg_getsocket(struct iked *env, int af, int natt) | |||
1156 | { | |||
1157 | switch (af) { | |||
1158 | case AF_INET2: | |||
1159 | return (env->sc_sock4[natt ? 1 : 0]); | |||
1160 | case AF_INET624: | |||
1161 | return (env->sc_sock6[natt ? 1 : 0]); | |||
1162 | } | |||
1163 | ||||
1164 | log_debug("%s: af socket %d not available", __func__, af); | |||
1165 | return (NULL((void*)0)); | |||
1166 | } | |||
1167 | ||||
1168 | void | |||
1169 | ikev2_msg_prevail(struct iked *env, struct iked_msgqueue *queue, | |||
1170 | struct iked_message *msg) | |||
1171 | { | |||
1172 | struct iked_message *m, *mtmp; | |||
1173 | ||||
1174 | TAILQ_FOREACH_SAFE(m, queue, msg_entry, mtmp)for ((m) = ((queue)->tqh_first); (m) != ((void*)0) && ((mtmp) = ((m)->msg_entry.tqe_next), 1); (m) = (mtmp)) { | |||
1175 | if (m->msg_msgid < msg->msg_msgid) | |||
1176 | ikev2_msg_dispose(env, queue, m); | |||
1177 | } | |||
1178 | } | |||
1179 | ||||
1180 | void | |||
1181 | ikev2_msg_dispose(struct iked *env, struct iked_msgqueue *queue, | |||
1182 | struct iked_message *msg) | |||
1183 | { | |||
1184 | TAILQ_REMOVE(queue, msg, msg_entry)do { if (((msg)->msg_entry.tqe_next) != ((void*)0)) (msg)-> msg_entry.tqe_next->msg_entry.tqe_prev = (msg)->msg_entry .tqe_prev; else (queue)->tqh_last = (msg)->msg_entry.tqe_prev ; *(msg)->msg_entry.tqe_prev = (msg)->msg_entry.tqe_next ; ; ; } while (0); | |||
1185 | timer_del(env, &msg->msg_timer); | |||
1186 | ikev2_msg_cleanup(env, msg); | |||
1187 | free(msg); | |||
1188 | } | |||
1189 | ||||
1190 | void | |||
1191 | ikev2_msg_flushqueue(struct iked *env, struct iked_msgqueue *queue) | |||
1192 | { | |||
1193 | struct iked_message *m = NULL((void*)0); | |||
1194 | ||||
1195 | while ((m = TAILQ_FIRST(queue)((queue)->tqh_first)) != NULL((void*)0)) | |||
| ||||
1196 | ikev2_msg_dispose(env, queue, m); | |||
| ||||
1197 | } | |||
1198 | ||||
1199 | struct iked_message * | |||
1200 | ikev2_msg_lookup(struct iked *env, struct iked_msgqueue *queue, | |||
1201 | struct iked_message *msg, struct ike_header *hdr) | |||
1202 | { | |||
1203 | struct iked_message *m = NULL((void*)0); | |||
1204 | ||||
1205 | TAILQ_FOREACH(m, queue, msg_entry)for((m) = ((queue)->tqh_first); (m) != ((void*)0); (m) = ( (m)->msg_entry.tqe_next)) { | |||
1206 | if (m->msg_msgid == msg->msg_msgid && | |||
1207 | m->msg_exchange == hdr->ike_exchange) | |||
1208 | break; | |||
1209 | } | |||
1210 | ||||
1211 | return (m); | |||
1212 | } | |||
1213 | ||||
1214 | void | |||
1215 | ikev2_msg_lookup_dispose_all(struct iked *env, struct iked_msgqueue *queue, | |||
1216 | struct iked_message *msg, struct ike_header *hdr) | |||
1217 | { | |||
1218 | struct iked_message *m = NULL((void*)0), *tmp = NULL((void*)0); | |||
1219 | ||||
1220 | TAILQ_FOREACH_SAFE(m, queue, msg_entry, tmp)for ((m) = ((queue)->tqh_first); (m) != ((void*)0) && ((tmp) = ((m)->msg_entry.tqe_next), 1); (m) = (tmp)) { | |||
1221 | if (m->msg_msgid == msg->msg_msgid && | |||
1222 | m->msg_exchange == hdr->ike_exchange) { | |||
1223 | TAILQ_REMOVE(queue, m, msg_entry)do { if (((m)->msg_entry.tqe_next) != ((void*)0)) (m)-> msg_entry.tqe_next->msg_entry.tqe_prev = (m)->msg_entry .tqe_prev; else (queue)->tqh_last = (m)->msg_entry.tqe_prev ; *(m)->msg_entry.tqe_prev = (m)->msg_entry.tqe_next; ; ; } while (0); | |||
1224 | timer_del(env, &m->msg_timer); | |||
1225 | ikev2_msg_cleanup(env, m); | |||
1226 | free(m); | |||
1227 | } | |||
1228 | } | |||
1229 | } | |||
1230 | ||||
1231 | int | |||
1232 | ikev2_msg_lookup_retransmit_all(struct iked *env, struct iked_msgqueue *queue, | |||
1233 | struct iked_message *msg, struct ike_header *hdr, struct iked_sa *sa) | |||
1234 | { | |||
1235 | struct iked_message *m = NULL((void*)0), *tmp = NULL((void*)0); | |||
1236 | int count = 0; | |||
1237 | ||||
1238 | TAILQ_FOREACH_SAFE(m, queue, msg_entry, tmp)for ((m) = ((queue)->tqh_first); (m) != ((void*)0) && ((tmp) = ((m)->msg_entry.tqe_next), 1); (m) = (tmp)) { | |||
1239 | if (m->msg_msgid == msg->msg_msgid && | |||
1240 | m->msg_exchange == hdr->ike_exchange) { | |||
1241 | if (ikev2_msg_retransmit_response(env, sa, m)) | |||
1242 | return -1; | |||
1243 | count++; | |||
1244 | } | |||
1245 | } | |||
1246 | return count; | |||
1247 | } | |||
1248 | ||||
1249 | int | |||
1250 | ikev2_msg_retransmit_response(struct iked *env, struct iked_sa *sa, | |||
1251 | struct iked_message *msg) | |||
1252 | { | |||
1253 | if (sendtofrom(msg->msg_fd, ibuf_data(msg->msg_data), | |||
1254 | ibuf_size(msg->msg_data), 0, | |||
1255 | (struct sockaddr *)&msg->msg_peer, msg->msg_peerlen, | |||
1256 | (struct sockaddr *)&msg->msg_local, msg->msg_locallen) == -1) { | |||
1257 | log_warn("%s: sendtofrom", __func__); | |||
1258 | return (-1); | |||
1259 | } | |||
1260 | log_info("%sretransmit %s res %u local %s peer %s", | |||
1261 | SPI_SA(sa, NULL)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((((void *)0)))), | |||
1262 | print_map(msg->msg_exchange, ikev2_exchange_map), | |||
1263 | msg->msg_msgid, | |||
1264 | print_host((struct sockaddr *)&msg->msg_local, NULL((void*)0), 0), | |||
1265 | print_host((struct sockaddr *)&msg->msg_peer, NULL((void*)0), 0)); | |||
1266 | ||||
1267 | timer_add(env, &msg->msg_timer, IKED_RESPONSE_TIMEOUT120); | |||
1268 | return (0); | |||
1269 | } | |||
1270 | ||||
1271 | void | |||
1272 | ikev2_msg_response_timeout(struct iked *env, void *arg) | |||
1273 | { | |||
1274 | struct iked_message *msg = arg; | |||
1275 | struct iked_sa *sa = msg->msg_sa; | |||
1276 | ||||
1277 | ikev2_msg_dispose(env, &sa->sa_responses, msg); | |||
1278 | } | |||
1279 | ||||
1280 | void | |||
1281 | ikev2_msg_retransmit_timeout(struct iked *env, void *arg) | |||
1282 | { | |||
1283 | struct iked_message *msg = arg; | |||
1284 | struct iked_sa *sa = msg->msg_sa; | |||
1285 | ||||
1286 | if (msg->msg_tries < IKED_RETRANSMIT_TRIES5) { | |||
1287 | if (sendtofrom(msg->msg_fd, ibuf_data(msg->msg_data), | |||
1288 | ibuf_size(msg->msg_data), 0, | |||
1289 | (struct sockaddr *)&msg->msg_peer, msg->msg_peerlen, | |||
1290 | (struct sockaddr *)&msg->msg_local, | |||
1291 | msg->msg_locallen) == -1) { | |||
1292 | log_warn("%s: sendtofrom", __func__); | |||
1293 | ikev2_ike_sa_setreason(sa, "retransmit failed"); | |||
1294 | sa_free(env, sa); | |||
1295 | return; | |||
1296 | } | |||
1297 | /* Exponential timeout */ | |||
1298 | timer_add(env, &msg->msg_timer, | |||
1299 | IKED_RETRANSMIT_TIMEOUT2 * (2 << (msg->msg_tries++))); | |||
1300 | log_info("%sretransmit %d %s req %u peer %s local %s", | |||
1301 | SPI_SA(sa, NULL)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((((void *)0)))), | |||
1302 | msg->msg_tries, | |||
1303 | print_map(msg->msg_exchange, ikev2_exchange_map), | |||
1304 | msg->msg_msgid, | |||
1305 | print_host((struct sockaddr *)&msg->msg_peer, NULL((void*)0), 0), | |||
1306 | print_host((struct sockaddr *)&msg->msg_local, NULL((void*)0), 0)); | |||
1307 | } else { | |||
1308 | log_debug("%s: retransmit limit reached for req %u", | |||
1309 | __func__, msg->msg_msgid); | |||
1310 | ikev2_ike_sa_setreason(sa, "retransmit limit reached"); | |||
1311 | sa_free(env, sa); | |||
1312 | } | |||
1313 | } |