xref: /openbsd/sbin/iked/ikev2_msg.c (revision 3189733a)
1*3189733aSmikeb /*	$OpenBSD: ikev2_msg.c,v 1.8 2010/09/30 10:34:56 mikeb Exp $	*/
2fde46d6eSreyk /*	$vantronix: ikev2.c,v 1.101 2010/06/03 07:57:33 reyk Exp $	*/
3fde46d6eSreyk 
4fde46d6eSreyk /*
5fde46d6eSreyk  * Copyright (c) 2010 Reyk Floeter <reyk@vantronix.net>
6fde46d6eSreyk  *
7fde46d6eSreyk  * Permission to use, copy, modify, and distribute this software for any
8fde46d6eSreyk  * purpose with or without fee is hereby granted, provided that the above
9fde46d6eSreyk  * copyright notice and this permission notice appear in all copies.
10fde46d6eSreyk  *
11fde46d6eSreyk  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12fde46d6eSreyk  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13fde46d6eSreyk  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14fde46d6eSreyk  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15fde46d6eSreyk  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16fde46d6eSreyk  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17fde46d6eSreyk  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18fde46d6eSreyk  */
19fde46d6eSreyk 
20fde46d6eSreyk #include <sys/param.h>
21fde46d6eSreyk #include <sys/types.h>
22fde46d6eSreyk #include <sys/queue.h>
23fde46d6eSreyk #include <sys/socket.h>
24fde46d6eSreyk #include <sys/wait.h>
25fde46d6eSreyk #include <sys/uio.h>
26fde46d6eSreyk 
27fde46d6eSreyk #include <netinet/in.h>
28fde46d6eSreyk #include <netinet/ip_ipsp.h>
29fde46d6eSreyk #include <arpa/inet.h>
30fde46d6eSreyk 
31fde46d6eSreyk #include <stdlib.h>
32fde46d6eSreyk #include <stdio.h>
33fde46d6eSreyk #include <unistd.h>
34fde46d6eSreyk #include <string.h>
35fde46d6eSreyk #include <getopt.h>
36fde46d6eSreyk #include <signal.h>
37fde46d6eSreyk #include <errno.h>
38fde46d6eSreyk #include <err.h>
39fde46d6eSreyk #include <pwd.h>
40fde46d6eSreyk #include <event.h>
41fde46d6eSreyk 
42fde46d6eSreyk #include <openssl/sha.h>
43fde46d6eSreyk #include <openssl/evp.h>
44fde46d6eSreyk 
45fde46d6eSreyk #include "iked.h"
46fde46d6eSreyk #include "ikev2.h"
47fde46d6eSreyk #include "eap.h"
48fde46d6eSreyk #include "dh.h"
49fde46d6eSreyk 
50fde46d6eSreyk void
51fde46d6eSreyk ikev2_msg_cb(int fd, short event, void *arg)
52fde46d6eSreyk {
53fde46d6eSreyk 	struct iked_socket	*sock = arg;
54fde46d6eSreyk 	struct iked		*env = sock->sock_env;
55fde46d6eSreyk 	struct iked_message	 msg;
56fde46d6eSreyk 	struct ike_header	 hdr;
57fde46d6eSreyk 	u_int32_t		 natt = 0x00000000;
58fde46d6eSreyk 	u_int8_t		 buf[IKED_MSGBUF_MAX];
59fde46d6eSreyk 	ssize_t			 len;
60fde46d6eSreyk 	off_t			 off;
61fde46d6eSreyk 	struct iovec		 iov[2];
62fde46d6eSreyk 
63fde46d6eSreyk 	bzero(&msg, sizeof(msg));
64fde46d6eSreyk 	bzero(buf, sizeof(buf));
65fde46d6eSreyk 
66fde46d6eSreyk 	msg.msg_peerlen = sizeof(msg.msg_peer);
67fde46d6eSreyk 	msg.msg_locallen = sizeof(msg.msg_local);
6826d7dba1Sreyk 	msg.msg_parent = &msg;
69fde46d6eSreyk 	memcpy(&msg.msg_local, &sock->sock_addr, sizeof(sock->sock_addr));
70fde46d6eSreyk 
71fde46d6eSreyk 	if ((len = recvfromto(fd, buf, sizeof(buf), 0,
72fde46d6eSreyk 	    (struct sockaddr*)&msg.msg_peer, &msg.msg_peerlen,
73fde46d6eSreyk 	    (struct sockaddr*)&msg.msg_local, &msg.msg_locallen)) <
74fde46d6eSreyk 	    (ssize_t)sizeof(natt))
75fde46d6eSreyk 		return;
76fde46d6eSreyk 
77fde46d6eSreyk 	if (socket_getport(&msg.msg_local) == IKED_NATT_PORT) {
78fde46d6eSreyk 		if (bcmp(&natt, buf, sizeof(natt)) != 0)
79fde46d6eSreyk 			return;
80fde46d6eSreyk 		msg.msg_natt = 1;
81fde46d6eSreyk 		off = sizeof(natt);
82fde46d6eSreyk 	} else
83fde46d6eSreyk 		off = 0;
84fde46d6eSreyk 
85fde46d6eSreyk 	if ((size_t)(len - off) <= sizeof(hdr))
86fde46d6eSreyk 		return;
87fde46d6eSreyk 	memcpy(&hdr, buf + off, sizeof(hdr));
88fde46d6eSreyk 
89fde46d6eSreyk 	if ((msg.msg_data = ibuf_new(buf + off, len - off)) == NULL)
90fde46d6eSreyk 		return;
91fde46d6eSreyk 
92fde46d6eSreyk 	if (hdr.ike_version == IKEV1_VERSION) {
93fde46d6eSreyk 		iov[0].iov_base = &msg;
94fde46d6eSreyk 		iov[0].iov_len = sizeof(msg);
95fde46d6eSreyk 		iov[1].iov_base = buf;
96fde46d6eSreyk 		iov[1].iov_len = len;
97fde46d6eSreyk 
98fde46d6eSreyk 		imsg_composev_proc(env, PROC_IKEV1, IMSG_IKE_MESSAGE, -1,
99fde46d6eSreyk 		    iov, 2);
100fde46d6eSreyk 		goto done;
101fde46d6eSreyk 	}
102fde46d6eSreyk 	TAILQ_INIT(&msg.msg_proposals);
103fde46d6eSreyk 
104fde46d6eSreyk 	msg.msg_fd = fd;
105fde46d6eSreyk 	ikev2_recv(env, &msg);
106fde46d6eSreyk 
107fde46d6eSreyk  done:
108763023d6Sreyk 	ikev2_msg_cleanup(env, &msg);
109fde46d6eSreyk }
110fde46d6eSreyk 
111fde46d6eSreyk struct ibuf *
112fde46d6eSreyk ikev2_msg_init(struct iked *env, struct iked_message *msg,
113fde46d6eSreyk     struct sockaddr_storage *peer, socklen_t peerlen,
114fde46d6eSreyk     struct sockaddr_storage *local, socklen_t locallen, int response)
115fde46d6eSreyk {
116fde46d6eSreyk 	bzero(msg, sizeof(*msg));
117fde46d6eSreyk 	memcpy(&msg->msg_peer, peer, peerlen);
118fde46d6eSreyk 	msg->msg_peerlen = peerlen;
119fde46d6eSreyk 	memcpy(&msg->msg_local, local, locallen);
120fde46d6eSreyk 	msg->msg_locallen = locallen;
121fde46d6eSreyk 	msg->msg_response = response ? 1 : 0;
122fde46d6eSreyk 	msg->msg_fd = -1;
123fde46d6eSreyk 	msg->msg_data = ibuf_static();
12426d7dba1Sreyk 	msg->msg_e = 0;
12526d7dba1Sreyk 	msg->msg_parent = msg;	/* has to be set */
126763023d6Sreyk 	TAILQ_INIT(&msg->msg_proposals);
127fde46d6eSreyk 
128fde46d6eSreyk 	return (msg->msg_data);
129fde46d6eSreyk }
130fde46d6eSreyk 
131763023d6Sreyk void
132763023d6Sreyk ikev2_msg_cleanup(struct iked *env, struct iked_message *msg)
133763023d6Sreyk {
13426d7dba1Sreyk 	if (msg == msg->msg_parent) {
13526d7dba1Sreyk 		ibuf_release(msg->msg_nonce);
13626d7dba1Sreyk 		ibuf_release(msg->msg_ke);
13726d7dba1Sreyk 		ibuf_release(msg->msg_auth.id_buf);
13826d7dba1Sreyk 		ibuf_release(msg->msg_id.id_buf);
13926d7dba1Sreyk 		ibuf_release(msg->msg_cert.id_buf);
14026d7dba1Sreyk 
14126d7dba1Sreyk 		config_free_proposals(&msg->msg_proposals, 0);
14226d7dba1Sreyk 	}
14326d7dba1Sreyk 
144763023d6Sreyk 	if (msg->msg_data != NULL) {
145763023d6Sreyk 		ibuf_release(msg->msg_data);
146763023d6Sreyk 		msg->msg_data = NULL;
147763023d6Sreyk 	}
148763023d6Sreyk }
149763023d6Sreyk 
150fde46d6eSreyk int
151fde46d6eSreyk ikev2_msg_valid_ike_sa(struct iked *env, struct ike_header *oldhdr,
152fde46d6eSreyk     struct iked_message *msg)
153fde46d6eSreyk {
154fde46d6eSreyk #if 0
155fde46d6eSreyk 	/* XXX Disabled, see comment below */
156fde46d6eSreyk 	struct iked_message		 resp;
157fde46d6eSreyk 	struct ike_header		*hdr;
158fde46d6eSreyk 	struct ikev2_payload		*pld;
159fde46d6eSreyk 	struct ikev2_notify		*n;
160fde46d6eSreyk 	struct ibuf			*buf;
161fde46d6eSreyk 	struct iked_sa			 sa;
162fde46d6eSreyk #endif
163fde46d6eSreyk 
164fde46d6eSreyk 	if (msg->msg_sa != NULL && msg->msg_policy != NULL)
165fde46d6eSreyk 		return (0);
166fde46d6eSreyk 
167fde46d6eSreyk #if 0
168fde46d6eSreyk 	/*
169fde46d6eSreyk 	 * XXX Sending INVALID_IKE_SPIs notifications is disabled
170fde46d6eSreyk 	 * XXX because it is not mandatory and ignored by most
171fde46d6eSreyk 	 * XXX implementations.  We might want to enable it in
172fde46d6eSreyk 	 * XXX combination with a rate-limitation to avoid DoS situations.
173fde46d6eSreyk 	 */
174fde46d6eSreyk 
175fde46d6eSreyk 	/* Fail without error message */
176fde46d6eSreyk 	if (msg->msg_response || msg->msg_policy == NULL)
177fde46d6eSreyk 		return (-1);
178fde46d6eSreyk 
179fde46d6eSreyk 	/* Invalid IKE SA, return notification */
180fde46d6eSreyk 	if ((buf = ikev2_msg_init(env, &resp,
181fde46d6eSreyk 	    &msg->msg_peer, msg->msg_peerlen,
182fde46d6eSreyk 	    &msg->msg_local, msg->msg_locallen, 1)) == NULL)
183fde46d6eSreyk 		goto done;
184fde46d6eSreyk 
185fde46d6eSreyk 	bzero(&sa, sizeof(sa));
186fde46d6eSreyk 	if ((oldhdr->ike_flags & IKEV2_FLAG_INITIATOR) == 0)
187fde46d6eSreyk 		sa.sa_hdr.sh_initiator = 1;
188fde46d6eSreyk 	sa.sa_hdr.sh_ispi = betoh64(oldhdr->ike_ispi);
189fde46d6eSreyk 	sa.sa_hdr.sh_rspi = betoh64(oldhdr->ike_rspi);
190fde46d6eSreyk 
191fde46d6eSreyk 	/* IKE header */
192fde46d6eSreyk 	if ((hdr = ikev2_add_header(buf, &sa, betoh32(oldhdr->ike_msgid),
193fde46d6eSreyk 	    IKEV2_PAYLOAD_NOTIFY, IKEV2_EXCHANGE_INFORMATIONAL,
194fde46d6eSreyk 	    IKEV2_FLAG_RESPONSE)) == NULL)
195fde46d6eSreyk 		goto done;
196fde46d6eSreyk 
197fde46d6eSreyk 	/* SA payload */
198fde46d6eSreyk 	if ((pld = ikev2_add_payload(buf)) == NULL)
199fde46d6eSreyk 		goto done;
200fde46d6eSreyk 	if ((n = ibuf_advance(buf, sizeof(*n))) == NULL)
201fde46d6eSreyk 		goto done;
202fde46d6eSreyk 	n->n_protoid = IKEV2_SAPROTO_IKE;
203fde46d6eSreyk 	n->n_spisize = 0;
204fde46d6eSreyk 	n->n_type = htobe16(IKEV2_N_INVALID_IKE_SPI);
205fde46d6eSreyk 
206fde46d6eSreyk 	if (ikev2_next_payload(pld, sizeof(*n), IKEV2_PAYLOAD_NONE) == -1)
207fde46d6eSreyk 		goto done;
208fde46d6eSreyk 
209fde46d6eSreyk 	if (ikev2_set_header(hdr, ibuf_size(buf) - sizeof(*hdr)) == -1)
210fde46d6eSreyk 		goto done;
211fde46d6eSreyk 
212fde46d6eSreyk 	(void)ikev2_pld_parse(env, hdr, &resp, 0);
213fde46d6eSreyk 	(void)ikev2_msg_send(env, msg->msg_fd, &resp);
214fde46d6eSreyk 
215fde46d6eSreyk  done:
216763023d6Sreyk 	ikev2_msg_cleanup(env, &resp);
217fde46d6eSreyk #endif
218fde46d6eSreyk 
219fde46d6eSreyk 	/* Always fail */
220fde46d6eSreyk 	return (-1);
221fde46d6eSreyk }
222fde46d6eSreyk 
223fde46d6eSreyk int
224fde46d6eSreyk ikev2_msg_send(struct iked *env, int fd, struct iked_message *msg)
225fde46d6eSreyk {
226fde46d6eSreyk 	struct ibuf		*buf = msg->msg_data;
227fde46d6eSreyk 	u_int32_t		 natt = 0x00000000;
228fde46d6eSreyk 	struct ike_header	*hdr;
229fde46d6eSreyk 
230fde46d6eSreyk 	if (buf == NULL || (hdr = ibuf_seek(msg->msg_data,
231fde46d6eSreyk 	    msg->msg_offset, sizeof(*hdr))) == NULL)
232fde46d6eSreyk 		return (-1);
233fde46d6eSreyk 
234d4614e98Sreyk 	log_info("%s: %s from %s to %s, %ld bytes", __func__,
235fde46d6eSreyk 	    print_map(hdr->ike_exchange, ikev2_exchange_map),
236d4614e98Sreyk 	    print_host(&msg->msg_local, NULL, 0),
237fde46d6eSreyk 	    print_host(&msg->msg_peer, NULL, 0),
238d4614e98Sreyk 	    ibuf_length(buf));
239fde46d6eSreyk 
240fde46d6eSreyk 	if (msg->msg_natt || (msg->msg_sa && msg->msg_sa->sa_natt)) {
241fde46d6eSreyk 		if (ibuf_prepend(buf, &natt, sizeof(natt)) == -1) {
242fde46d6eSreyk 			log_debug("%s: failed to set NAT-T", __func__);
243fde46d6eSreyk 			return (-1);
244fde46d6eSreyk 		}
245fde46d6eSreyk 	}
246fde46d6eSreyk 	if ((sendto(fd, ibuf_data(buf), ibuf_size(buf), 0,
247fde46d6eSreyk 	    (struct sockaddr *)&msg->msg_peer, msg->msg_peerlen)) == -1) {
248fde46d6eSreyk 		log_warn("%s: sendto", __func__);
249fde46d6eSreyk 		return (-1);
250fde46d6eSreyk 	}
251fde46d6eSreyk 
252fde46d6eSreyk 	return (0);
253fde46d6eSreyk }
254fde46d6eSreyk 
255fde46d6eSreyk u_int32_t
256fde46d6eSreyk ikev2_msg_id(struct iked *env, struct iked_sa *sa, int response)
257fde46d6eSreyk {
258fde46d6eSreyk 	if (response)
259fde46d6eSreyk 		return (sa->sa_msgid);
260fde46d6eSreyk 
261fde46d6eSreyk 	if (++sa->sa_msgid == UINT32_MAX) {
262fde46d6eSreyk 		/* XXX we should close and renegotiate the connection now */
263fde46d6eSreyk 		log_debug("%s: IKEv2 message sequence overflow", __func__);
264fde46d6eSreyk 	}
265fde46d6eSreyk 
266fde46d6eSreyk 	return (sa->sa_msgid);
267fde46d6eSreyk }
268fde46d6eSreyk 
269fde46d6eSreyk struct ibuf *
270fde46d6eSreyk ikev2_msg_encrypt(struct iked *env, struct iked_sa *sa, struct ibuf *src)
271fde46d6eSreyk {
272fde46d6eSreyk 	size_t			 len, ivlen, encrlen, integrlen, blocklen,
273fde46d6eSreyk 				    outlen;
274fde46d6eSreyk 	u_int8_t		*buf, pad = 0, *ptr;
275fde46d6eSreyk 	struct ibuf		*integr, *encr, *dst = NULL, *out = NULL;
276fde46d6eSreyk 
277fde46d6eSreyk 	buf = ibuf_data(src);
278fde46d6eSreyk 	len = ibuf_size(src);
279fde46d6eSreyk 
280fde46d6eSreyk 	log_debug("%s: decrypted length %d", __func__, len);
281fde46d6eSreyk 	print_hex(buf, 0, len);
282fde46d6eSreyk 
283fde46d6eSreyk 	if (sa == NULL ||
284fde46d6eSreyk 	    sa->sa_encr == NULL ||
285fde46d6eSreyk 	    sa->sa_integr == NULL) {
286fde46d6eSreyk 		log_debug("%s: invalid SA", __func__);
287fde46d6eSreyk 		goto done;
288fde46d6eSreyk 	}
289fde46d6eSreyk 
290fde46d6eSreyk 	if (sa->sa_hdr.sh_initiator) {
291fde46d6eSreyk 		encr = sa->sa_key_iencr;
292fde46d6eSreyk 		integr = sa->sa_key_iauth;
293fde46d6eSreyk 	} else {
294fde46d6eSreyk 		encr = sa->sa_key_rencr;
295fde46d6eSreyk 		integr = sa->sa_key_rauth;
296fde46d6eSreyk 	}
297fde46d6eSreyk 
298fde46d6eSreyk 	blocklen = cipher_length(sa->sa_encr);
299fde46d6eSreyk 	ivlen = cipher_ivlength(sa->sa_encr);
300fde46d6eSreyk 	integrlen = hash_length(sa->sa_integr);
301fde46d6eSreyk 	encrlen = roundup(len + sizeof(pad), blocklen);
302fde46d6eSreyk 	pad = encrlen - (len + sizeof(pad));
303fde46d6eSreyk 
304fde46d6eSreyk 	/*
305fde46d6eSreyk 	 * Pad the payload and encrypt it
306fde46d6eSreyk 	 */
307fde46d6eSreyk 	if (pad) {
308fde46d6eSreyk 		if ((ptr = ibuf_advance(src, pad)) == NULL)
309fde46d6eSreyk 			goto done;
310fde46d6eSreyk 		arc4random_buf(ptr, pad);
311fde46d6eSreyk 	}
312fde46d6eSreyk 	if (ibuf_add(src, &pad, sizeof(pad)) != 0)
313fde46d6eSreyk 		goto done;
314fde46d6eSreyk 
315fde46d6eSreyk 	log_debug("%s: padded length %d", __func__, ibuf_size(src));
316fde46d6eSreyk 	print_hex(ibuf_data(src), 0, ibuf_size(src));
317fde46d6eSreyk 
318fde46d6eSreyk 	cipher_setkey(sa->sa_encr, encr->buf, ibuf_length(encr));
319fde46d6eSreyk 	cipher_setiv(sa->sa_encr, NULL, 0);	/* new IV */
320fde46d6eSreyk 	cipher_init_encrypt(sa->sa_encr);
321fde46d6eSreyk 
322fde46d6eSreyk 	if ((dst = ibuf_dup(sa->sa_encr->encr_iv)) == NULL)
323fde46d6eSreyk 		goto done;
324fde46d6eSreyk 
325fde46d6eSreyk 	if ((out = ibuf_new(NULL,
326fde46d6eSreyk 	    cipher_outlength(sa->sa_encr, encrlen))) == NULL)
327fde46d6eSreyk 		goto done;
328fde46d6eSreyk 
329fde46d6eSreyk 	outlen = ibuf_size(out);
330fde46d6eSreyk 	cipher_update(sa->sa_encr,
331fde46d6eSreyk 	    ibuf_data(src), encrlen, ibuf_data(out), &outlen);
332fde46d6eSreyk 
333fde46d6eSreyk 	if (outlen && ibuf_add(dst, ibuf_data(out), outlen) != 0)
334fde46d6eSreyk 		goto done;
335fde46d6eSreyk 
336fde46d6eSreyk 	if ((ptr = ibuf_advance(dst, integrlen)) == NULL)
337fde46d6eSreyk 		goto done;
338fde46d6eSreyk 	bzero(ptr, integrlen);
339fde46d6eSreyk 
340fde46d6eSreyk 	log_debug("%s: length %d, padding %d, output length %d",
341fde46d6eSreyk 	    __func__, len + sizeof(pad), pad, ibuf_size(dst));
342fde46d6eSreyk 	print_hex(ibuf_data(dst), 0, ibuf_size(dst));
343fde46d6eSreyk 
344fde46d6eSreyk 	ibuf_release(src);
345fde46d6eSreyk 	ibuf_release(out);
346fde46d6eSreyk 	return (dst);
347fde46d6eSreyk  done:
348fde46d6eSreyk 	ibuf_release(src);
349fde46d6eSreyk 	ibuf_release(out);
350fde46d6eSreyk 	ibuf_release(dst);
351fde46d6eSreyk 	return (NULL);
352fde46d6eSreyk }
353fde46d6eSreyk 
354fde46d6eSreyk int
355fde46d6eSreyk ikev2_msg_integr(struct iked *env, struct iked_sa *sa, struct ibuf *src)
356fde46d6eSreyk {
357fde46d6eSreyk 	int			 ret = -1;
358fde46d6eSreyk 	size_t			 integrlen, tmplen;
359fde46d6eSreyk 	struct ibuf		*integr, *prf, *tmp = NULL;
360fde46d6eSreyk 	u_int8_t		*ptr;
361fde46d6eSreyk 
362fde46d6eSreyk 	log_debug("%s: message length %d", __func__, ibuf_size(src));
363fde46d6eSreyk 	print_hex(ibuf_data(src), 0, ibuf_size(src));
364fde46d6eSreyk 
365fde46d6eSreyk 	if (sa == NULL ||
366fde46d6eSreyk 	    sa->sa_integr == NULL) {
367fde46d6eSreyk 		log_debug("%s: invalid SA", __func__);
368fde46d6eSreyk 		return (-1);
369fde46d6eSreyk 	}
370fde46d6eSreyk 
371fde46d6eSreyk 	if (sa->sa_hdr.sh_initiator) {
372fde46d6eSreyk 		integr = sa->sa_key_iauth;
373fde46d6eSreyk 		prf = sa->sa_key_iprf;
374fde46d6eSreyk 	} else {
375fde46d6eSreyk 		integr = sa->sa_key_rauth;
376fde46d6eSreyk 		prf = sa->sa_key_rprf;
377fde46d6eSreyk 	}
378fde46d6eSreyk 
379fde46d6eSreyk 	integrlen = hash_length(sa->sa_integr);
380fde46d6eSreyk 
381fde46d6eSreyk 	log_debug("%s: integrity checksum length %d", __func__,
382fde46d6eSreyk 	    integrlen);
383fde46d6eSreyk 
384fde46d6eSreyk 	/*
385fde46d6eSreyk 	 * Validate packet checksum
386fde46d6eSreyk 	 */
387fde46d6eSreyk 	if ((tmp = ibuf_new(NULL, hash_keylength(sa->sa_integr))) == NULL)
388fde46d6eSreyk 		goto done;
389fde46d6eSreyk 
390fde46d6eSreyk 	hash_setkey(sa->sa_integr, ibuf_data(integr), ibuf_size(integr));
391fde46d6eSreyk 	hash_init(sa->sa_integr);
392fde46d6eSreyk 	hash_update(sa->sa_integr, ibuf_data(src),
393fde46d6eSreyk 	    ibuf_size(src) - integrlen);
394fde46d6eSreyk 	hash_final(sa->sa_integr, ibuf_data(tmp), &tmplen);
395fde46d6eSreyk 
396fde46d6eSreyk 	if (tmplen != integrlen) {
397fde46d6eSreyk 		log_debug("%s: hash failure", __func__);
398fde46d6eSreyk 		goto done;
399fde46d6eSreyk 	}
400fde46d6eSreyk 
401fde46d6eSreyk 	if ((ptr = ibuf_seek(src,
402fde46d6eSreyk 	    ibuf_size(src) - integrlen, integrlen)) == NULL)
403fde46d6eSreyk 		goto done;
404fde46d6eSreyk 	memcpy(ptr, ibuf_data(tmp), tmplen);
405fde46d6eSreyk 
406fde46d6eSreyk 	print_hex(ibuf_data(tmp), 0, ibuf_size(tmp));
407fde46d6eSreyk 
408fde46d6eSreyk 	ret = 0;
409fde46d6eSreyk  done:
410fde46d6eSreyk 	ibuf_release(tmp);
411fde46d6eSreyk 
412fde46d6eSreyk 	return (ret);
413fde46d6eSreyk }
414fde46d6eSreyk 
415fde46d6eSreyk struct ibuf *
416fde46d6eSreyk ikev2_msg_decrypt(struct iked *env, struct iked_sa *sa,
417fde46d6eSreyk     struct ibuf *msg, struct ibuf *src)
418fde46d6eSreyk {
419fde46d6eSreyk 	size_t			 ivlen, encrlen, integrlen, blocklen,
420fde46d6eSreyk 				    outlen, tmplen;
421fde46d6eSreyk 	u_int8_t		 pad, *ptr;
422fde46d6eSreyk 	struct ibuf		*integr, *encr, *tmp = NULL, *out = NULL;
423fde46d6eSreyk 	off_t			 ivoff, encroff, integroff;
424fde46d6eSreyk 
425fde46d6eSreyk 	if (sa == NULL ||
426fde46d6eSreyk 	    sa->sa_encr == NULL ||
427fde46d6eSreyk 	    sa->sa_integr == NULL) {
428fde46d6eSreyk 		log_debug("%s: invalid SA", __func__);
429fde46d6eSreyk 		print_hex(ibuf_data(src), 0, ibuf_size(src));
430fde46d6eSreyk 		goto done;
431fde46d6eSreyk 	}
432fde46d6eSreyk 
433fde46d6eSreyk 	if (!sa->sa_hdr.sh_initiator) {
434fde46d6eSreyk 		encr = sa->sa_key_iencr;
435fde46d6eSreyk 		integr = sa->sa_key_iauth;
436fde46d6eSreyk 	} else {
437fde46d6eSreyk 		encr = sa->sa_key_rencr;
438fde46d6eSreyk 		integr = sa->sa_key_rauth;
439fde46d6eSreyk 	}
440fde46d6eSreyk 
441fde46d6eSreyk 	blocklen = cipher_length(sa->sa_encr);
442fde46d6eSreyk 	ivlen = cipher_ivlength(sa->sa_encr);
443fde46d6eSreyk 	ivoff = 0;
444fde46d6eSreyk 	integrlen = hash_length(sa->sa_integr);
445fde46d6eSreyk 	integroff = ibuf_size(src) - integrlen;
446fde46d6eSreyk 	encroff = ivlen;
447fde46d6eSreyk 	encrlen = ibuf_size(src) - integrlen - ivlen;
448fde46d6eSreyk 
449fde46d6eSreyk 	log_debug("%s: IV length %d", __func__, ivlen);
450fde46d6eSreyk 	print_hex(ibuf_data(src), 0, ivlen);
451fde46d6eSreyk 	log_debug("%s: encrypted payload length %d", __func__, encrlen);
452fde46d6eSreyk 	print_hex(ibuf_data(src), encroff, encrlen);
453fde46d6eSreyk 	log_debug("%s: integrity checksum length %d", __func__, integrlen);
454fde46d6eSreyk 	print_hex(ibuf_data(src), integroff, integrlen);
455fde46d6eSreyk 
456fde46d6eSreyk 	/*
457fde46d6eSreyk 	 * Validate packet checksum
458fde46d6eSreyk 	 */
459fde46d6eSreyk 	if ((tmp = ibuf_new(NULL, ibuf_length(integr))) == NULL)
460fde46d6eSreyk 		goto done;
461fde46d6eSreyk 
462fde46d6eSreyk 	hash_setkey(sa->sa_integr, integr->buf, ibuf_length(integr));
463fde46d6eSreyk 	hash_init(sa->sa_integr);
464fde46d6eSreyk 	hash_update(sa->sa_integr, ibuf_data(msg),
465fde46d6eSreyk 	    ibuf_size(msg) - integrlen);
466fde46d6eSreyk 	hash_final(sa->sa_integr, tmp->buf, &tmplen);
467fde46d6eSreyk 
468fde46d6eSreyk 	if (memcmp(tmp->buf, ibuf_data(src) + integroff, integrlen) != 0) {
469fde46d6eSreyk 		log_debug("%s: integrity check failed", __func__);
470fde46d6eSreyk 		goto done;
471fde46d6eSreyk 	}
472fde46d6eSreyk 
473fde46d6eSreyk 	log_debug("%s: integrity check succeeded", __func__, tmplen);
474fde46d6eSreyk 	print_hex(tmp->buf, 0, tmplen);
475fde46d6eSreyk 
476fde46d6eSreyk 	ibuf_release(tmp);
477fde46d6eSreyk 	tmp = NULL;
478fde46d6eSreyk 
479fde46d6eSreyk 	/*
480fde46d6eSreyk 	 * Decrypt the payload and strip any padding
481fde46d6eSreyk 	 */
482fde46d6eSreyk 	if ((encrlen % blocklen) != 0) {
483fde46d6eSreyk 		log_debug("%s: unaligned encrypted payload", __func__);
484fde46d6eSreyk 		goto done;
485fde46d6eSreyk 	}
486fde46d6eSreyk 
487fde46d6eSreyk 	cipher_setkey(sa->sa_encr, encr->buf, ibuf_length(encr));
488fde46d6eSreyk 	cipher_setiv(sa->sa_encr, ibuf_data(src) + ivoff, ivlen);
489fde46d6eSreyk 	cipher_init_decrypt(sa->sa_encr);
490fde46d6eSreyk 
491fde46d6eSreyk 	if ((out = ibuf_new(NULL, cipher_outlength(sa->sa_encr,
492fde46d6eSreyk 	    encrlen))) == NULL)
493fde46d6eSreyk 		goto done;
494fde46d6eSreyk 
495fde46d6eSreyk 	outlen = ibuf_length(out);
496fde46d6eSreyk 
497*3189733aSmikeb 	cipher_update(sa->sa_encr, ibuf_data(src) + encroff, encrlen,
498*3189733aSmikeb 	    ibuf_data(out), &outlen);
499*3189733aSmikeb 
500fde46d6eSreyk 	ptr = ibuf_seek(out, outlen - 1, 1);
501fde46d6eSreyk 	pad = *ptr;
502fde46d6eSreyk 
503fde46d6eSreyk 	log_debug("%s: decrypted payload length %d/%d padding %d",
504fde46d6eSreyk 	    __func__, outlen, encrlen, pad);
505fde46d6eSreyk 	print_hex(ibuf_data(out), 0, ibuf_size(out));
506fde46d6eSreyk 
507fde46d6eSreyk 	if (ibuf_setsize(out, outlen) != 0)
508fde46d6eSreyk 		goto done;
509fde46d6eSreyk 
510fde46d6eSreyk 	ibuf_release(src);
511fde46d6eSreyk 	return (out);
512fde46d6eSreyk  done:
513fde46d6eSreyk 	ibuf_release(tmp);
514fde46d6eSreyk 	ibuf_release(out);
515fde46d6eSreyk 	ibuf_release(src);
516fde46d6eSreyk 	return (NULL);
517fde46d6eSreyk }
518fde46d6eSreyk 
519fde46d6eSreyk int
520fde46d6eSreyk ikev2_msg_send_encrypt(struct iked *env, struct iked_sa *sa,
521fde46d6eSreyk     struct ibuf **ep, u_int8_t exchange, u_int8_t firstpayload, int response)
522fde46d6eSreyk {
523fde46d6eSreyk 	struct iked_message		 resp;
524fde46d6eSreyk 	struct ike_header		*hdr;
525fde46d6eSreyk 	struct ikev2_payload		*pld;
526fde46d6eSreyk 	struct ibuf			*buf, *e = *ep;
527fde46d6eSreyk 	int				 ret = -1;
528fde46d6eSreyk 
529fde46d6eSreyk 	if ((buf = ikev2_msg_init(env, &resp,
530fde46d6eSreyk 	    &sa->sa_peer.addr, sa->sa_peer.addr.ss_len,
531fde46d6eSreyk 	    &sa->sa_local.addr, sa->sa_local.addr.ss_len, 1)) == NULL)
532fde46d6eSreyk 		goto done;
533fde46d6eSreyk 
534fde46d6eSreyk 	/* IKE header */
535fde46d6eSreyk 	if ((hdr = ikev2_add_header(buf, sa,
536fde46d6eSreyk 	    ikev2_msg_id(env, sa, response),
537fde46d6eSreyk 	    IKEV2_PAYLOAD_E, exchange,
538fde46d6eSreyk 	    response ? IKEV2_FLAG_RESPONSE : 0)) == NULL)
539fde46d6eSreyk 		goto done;
540fde46d6eSreyk 
541fde46d6eSreyk 	if ((pld = ikev2_add_payload(buf)) == NULL)
542fde46d6eSreyk 		goto done;
543fde46d6eSreyk 
544fde46d6eSreyk 	/* Encrypt message and add as an E payload */
545fde46d6eSreyk 	if ((e = ikev2_msg_encrypt(env, sa, e)) == NULL) {
546fde46d6eSreyk 		log_debug("%s: encryption failed", __func__);
547fde46d6eSreyk 		goto done;
548fde46d6eSreyk 	}
549fde46d6eSreyk 	if (ibuf_cat(buf, e) != 0)
550fde46d6eSreyk 		goto done;
551fde46d6eSreyk 	if (ikev2_next_payload(pld, ibuf_size(e), firstpayload) == -1)
552fde46d6eSreyk 		goto done;
553fde46d6eSreyk 
554fde46d6eSreyk 	if (ikev2_set_header(hdr, ibuf_size(buf) - sizeof(*hdr)) == -1)
555fde46d6eSreyk 		goto done;
556fde46d6eSreyk 
557fde46d6eSreyk 	/* Add integrity checksum (HMAC) */
558fde46d6eSreyk 	if (ikev2_msg_integr(env, sa, buf) != 0) {
559fde46d6eSreyk 		log_debug("%s: integrity checksum failed", __func__);
560fde46d6eSreyk 		goto done;
561fde46d6eSreyk 	}
562fde46d6eSreyk 
563fde46d6eSreyk 	resp.msg_data = buf;
564fde46d6eSreyk 	resp.msg_sa = sa;
565fde46d6eSreyk 	TAILQ_INIT(&resp.msg_proposals);
566fde46d6eSreyk 
567fde46d6eSreyk 	(void)ikev2_pld_parse(env, hdr, &resp, 0);
568fde46d6eSreyk 
569fde46d6eSreyk 	ret = ikev2_msg_send(env, sa->sa_fd, &resp);
570fde46d6eSreyk 
571fde46d6eSreyk  done:
572fde46d6eSreyk 	/* e is cleaned up by the calling function */
573fde46d6eSreyk 	*ep = e;
574763023d6Sreyk 	ikev2_msg_cleanup(env, &resp);
575fde46d6eSreyk 
576fde46d6eSreyk 	return (ret);
577fde46d6eSreyk }
578fde46d6eSreyk 
579fde46d6eSreyk struct ibuf *
580fde46d6eSreyk ikev2_msg_auth(struct iked *env, struct iked_sa *sa, int response)
581fde46d6eSreyk {
582fde46d6eSreyk 	struct ibuf		*authmsg = NULL, *nonce, *prfkey, *buf;
583fde46d6eSreyk 	u_int8_t		*ptr;
584fde46d6eSreyk 	struct iked_id		*id;
585fde46d6eSreyk 	size_t			 tmplen;
586fde46d6eSreyk 
587fde46d6eSreyk 	/*
588fde46d6eSreyk 	 * Create the payload to be signed/MAC'ed for AUTH
589fde46d6eSreyk 	 */
590fde46d6eSreyk 
591fde46d6eSreyk 	if (!response) {
592fde46d6eSreyk 		if ((nonce = sa->sa_rnonce) == NULL ||
593fde46d6eSreyk 		    (sa->sa_iid.id_type == 0) ||
594fde46d6eSreyk 		    (prfkey = sa->sa_key_iprf) == NULL ||
595fde46d6eSreyk 		    (buf = sa->sa_1stmsg) == NULL)
596fde46d6eSreyk 			return (NULL);
597fde46d6eSreyk 		id = &sa->sa_iid;
598fde46d6eSreyk 	} else {
599fde46d6eSreyk 		if ((nonce = sa->sa_inonce) == NULL ||
600fde46d6eSreyk 		    (sa->sa_rid.id_type == 0) ||
601fde46d6eSreyk 		    (prfkey = sa->sa_key_rprf) == NULL ||
602fde46d6eSreyk 		    (buf = sa->sa_2ndmsg) == NULL)
603fde46d6eSreyk 			return (NULL);
604fde46d6eSreyk 		id = &sa->sa_rid;
605fde46d6eSreyk 	}
606fde46d6eSreyk 
607fde46d6eSreyk 	if ((authmsg = ibuf_dup(buf)) == NULL)
608fde46d6eSreyk 		return (NULL);
609fde46d6eSreyk 	if (ibuf_cat(authmsg, nonce) != 0)
610fde46d6eSreyk 		goto fail;
611fde46d6eSreyk 
612fde46d6eSreyk 	if ((hash_setkey(sa->sa_prf, ibuf_data(prfkey),
613fde46d6eSreyk 	    ibuf_size(prfkey))) == NULL)
614fde46d6eSreyk 		goto fail;
615fde46d6eSreyk 
616fde46d6eSreyk 	if ((ptr = ibuf_advance(authmsg,
617fde46d6eSreyk 	    hash_length(sa->sa_prf))) == NULL)
618fde46d6eSreyk 		goto fail;
619fde46d6eSreyk 
620fde46d6eSreyk 	hash_init(sa->sa_prf);
621fde46d6eSreyk 	hash_update(sa->sa_prf, ibuf_data(id->id_buf), ibuf_size(id->id_buf));
622fde46d6eSreyk 	hash_final(sa->sa_prf, ptr, &tmplen);
623fde46d6eSreyk 
624fde46d6eSreyk 	if (tmplen != hash_length(sa->sa_prf))
625fde46d6eSreyk 		goto fail;
626fde46d6eSreyk 
627fde46d6eSreyk 	log_debug("%s: %s auth data length %d",
628fde46d6eSreyk 	    __func__, response ? "responder" : "initiator",
629fde46d6eSreyk 	    ibuf_size(authmsg));
630fde46d6eSreyk 	print_hex(ibuf_data(authmsg), 0, ibuf_size(authmsg));
631fde46d6eSreyk 
632fde46d6eSreyk 	return (authmsg);
633fde46d6eSreyk 
634fde46d6eSreyk  fail:
635fde46d6eSreyk 	ibuf_release(authmsg);
636fde46d6eSreyk 	return (NULL);
637fde46d6eSreyk }
638fde46d6eSreyk 
639fde46d6eSreyk int
640fde46d6eSreyk ikev2_msg_authverify(struct iked *env, struct iked_sa *sa,
641fde46d6eSreyk     struct iked_auth *auth, u_int8_t *buf, size_t len, struct ibuf *authmsg)
642fde46d6eSreyk {
643fde46d6eSreyk 	u_int8_t			*key, *psk = NULL;
644fde46d6eSreyk 	ssize_t				 keylen;
645fde46d6eSreyk 	struct iked_id			*id;
646fde46d6eSreyk 	struct iked_dsa			*dsa = NULL;
647fde46d6eSreyk 	int				 ret = -1;
648fde46d6eSreyk 	u_int8_t			 keytype;
649fde46d6eSreyk 
650fde46d6eSreyk 	if (sa->sa_hdr.sh_initiator)
651fde46d6eSreyk 		id = &sa->sa_rcert;
652fde46d6eSreyk 	else
653fde46d6eSreyk 		id = &sa->sa_icert;
654fde46d6eSreyk 
655fde46d6eSreyk 	if ((dsa = dsa_verify_new(auth->auth_method, sa->sa_prf)) == NULL) {
656fde46d6eSreyk 		log_debug("%s: invalid auth method", __func__);
657fde46d6eSreyk 		return (-1);
658fde46d6eSreyk 	}
659fde46d6eSreyk 
660fde46d6eSreyk 	switch (auth->auth_method) {
661fde46d6eSreyk 	case IKEV2_AUTH_SHARED_KEY_MIC:
662fde46d6eSreyk 		if (!auth->auth_length) {
663fde46d6eSreyk 			log_debug("%s: no pre-shared key found", __func__);
664fde46d6eSreyk 			goto done;
665fde46d6eSreyk 		}
666fde46d6eSreyk 		if ((keylen = ikev2_psk(sa, auth->auth_data,
667fde46d6eSreyk 		    auth->auth_length, &psk)) == -1) {
668fde46d6eSreyk 			log_debug("%s: failed to get PSK", __func__);
669fde46d6eSreyk 			goto done;
670fde46d6eSreyk 		}
671fde46d6eSreyk 		key = psk;
672fde46d6eSreyk 		keytype = 0;
673fde46d6eSreyk 		break;
674fde46d6eSreyk 	default:
675202133c5Sreyk 		if (!id->id_type || !ibuf_length(id->id_buf)) {
676fde46d6eSreyk 			log_debug("%s: no cert found", __func__);
677fde46d6eSreyk 			goto done;
678fde46d6eSreyk 		}
679fde46d6eSreyk 		key = ibuf_data(id->id_buf);
680fde46d6eSreyk 		keylen = ibuf_size(id->id_buf);
681fde46d6eSreyk 		keytype = id->id_type;
682fde46d6eSreyk 		break;
683fde46d6eSreyk 	}
684fde46d6eSreyk 
685fde46d6eSreyk 	log_debug("%s: method %s keylen %d type %s", __func__,
686fde46d6eSreyk 	    print_map(auth->auth_method, ikev2_auth_map), keylen,
687fde46d6eSreyk 	    print_map(id->id_type, ikev2_cert_map));
688fde46d6eSreyk 
689fde46d6eSreyk 	if (dsa_setkey(dsa, key, keylen, keytype) == NULL ||
690fde46d6eSreyk 	    dsa_init(dsa) != 0 ||
691fde46d6eSreyk 	    dsa_update(dsa, ibuf_data(authmsg), ibuf_size(authmsg))) {
692fde46d6eSreyk 		log_debug("%s: failed to compute digital signature", __func__);
693fde46d6eSreyk 		goto done;
694fde46d6eSreyk 	}
695fde46d6eSreyk 
696fde46d6eSreyk 	if ((ret = dsa_verify_final(dsa, buf, len)) == 0) {
697fde46d6eSreyk 		log_debug("%s: authentication successful", __func__);
698fde46d6eSreyk 		sa_state(env, sa, IKEV2_STATE_AUTH_SUCCESS);
699fde46d6eSreyk 
700fde46d6eSreyk 		if (!sa->sa_policy->pol_auth.auth_eap &&
701fde46d6eSreyk 		    auth->auth_method == IKEV2_AUTH_SHARED_KEY_MIC)
702fde46d6eSreyk 			sa_state(env, sa, IKEV2_STATE_VALID);
703fde46d6eSreyk 	} else {
704fde46d6eSreyk 		log_debug("%s: authentication failed", __func__);
705fde46d6eSreyk 		sa_state(env, sa, IKEV2_STATE_AUTH_REQUEST);
706fde46d6eSreyk 	}
707fde46d6eSreyk 
708fde46d6eSreyk  done:
709fde46d6eSreyk 	if (psk != NULL)
710fde46d6eSreyk 		free(psk);
711fde46d6eSreyk 	dsa_free(dsa);
712fde46d6eSreyk 
713fde46d6eSreyk 	return (ret);
714fde46d6eSreyk }
715fde46d6eSreyk 
716fde46d6eSreyk int
717fde46d6eSreyk ikev2_msg_authsign(struct iked *env, struct iked_sa *sa,
718fde46d6eSreyk     struct iked_auth *auth, struct ibuf *authmsg)
719fde46d6eSreyk {
720fde46d6eSreyk 	u_int8_t			*key, *psk = NULL;
721fde46d6eSreyk 	ssize_t				 keylen;
722fde46d6eSreyk 	struct iked_hash		*prf = sa->sa_prf;
723fde46d6eSreyk 	struct iked_id			*id;
724fde46d6eSreyk 	struct iked_dsa			*dsa = NULL;
725fde46d6eSreyk 	struct ibuf			*buf;
726fde46d6eSreyk 	int				 ret = -1;
727fde46d6eSreyk 	u_int8_t			 keytype;
728fde46d6eSreyk 
729fde46d6eSreyk 	if (sa->sa_hdr.sh_initiator)
730fde46d6eSreyk 		id = &sa->sa_icert;
731fde46d6eSreyk 	else
732fde46d6eSreyk 		id = &sa->sa_rcert;
733fde46d6eSreyk 
734fde46d6eSreyk 	if ((dsa = dsa_sign_new(auth->auth_method, prf)) == NULL) {
735fde46d6eSreyk 		log_debug("%s: invalid auth method", __func__);
736fde46d6eSreyk 		return (-1);
737fde46d6eSreyk 	}
738fde46d6eSreyk 
739fde46d6eSreyk 	switch (auth->auth_method) {
740fde46d6eSreyk 	case IKEV2_AUTH_SHARED_KEY_MIC:
741fde46d6eSreyk 		if (!auth->auth_length) {
742fde46d6eSreyk 			log_debug("%s: no pre-shared key found", __func__);
743fde46d6eSreyk 			goto done;
744fde46d6eSreyk 		}
745fde46d6eSreyk 		if ((keylen = ikev2_psk(sa, auth->auth_data,
746fde46d6eSreyk 		    auth->auth_length, &psk)) == -1) {
747fde46d6eSreyk 			log_debug("%s: failed to get PSK", __func__);
748fde46d6eSreyk 			goto done;
749fde46d6eSreyk 		}
750fde46d6eSreyk 		key = psk;
751fde46d6eSreyk 		keytype = 0;
752fde46d6eSreyk 		break;
753fde46d6eSreyk 	default:
754fde46d6eSreyk 		if (id == NULL) {
755fde46d6eSreyk 			log_debug("%s: no cert found", __func__);
756fde46d6eSreyk 			goto done;
757fde46d6eSreyk 		}
758fde46d6eSreyk 		key = ibuf_data(id->id_buf);
759fde46d6eSreyk 		keylen = ibuf_size(id->id_buf);
760fde46d6eSreyk 		keytype = id->id_type;
761fde46d6eSreyk 		break;
762fde46d6eSreyk 	}
763fde46d6eSreyk 
764fde46d6eSreyk 	if (dsa_setkey(dsa, key, keylen, keytype) == NULL ||
765fde46d6eSreyk 	    dsa_init(dsa) != 0 ||
766fde46d6eSreyk 	    dsa_update(dsa, ibuf_data(authmsg), ibuf_size(authmsg))) {
767fde46d6eSreyk 		log_debug("%s: failed to compute digital signature", __func__);
768fde46d6eSreyk 		goto done;
769fde46d6eSreyk 	}
770fde46d6eSreyk 
771fde46d6eSreyk 	ibuf_release(sa->sa_localauth.id_buf);
772fde46d6eSreyk 	sa->sa_localauth.id_buf = NULL;
773fde46d6eSreyk 
774fde46d6eSreyk 	if ((buf = ibuf_new(NULL, dsa_length(dsa))) == NULL) {
775fde46d6eSreyk 		log_debug("%s: failed to get auth buffer", __func__);
776fde46d6eSreyk 		goto done;
777fde46d6eSreyk 	}
778fde46d6eSreyk 
779fde46d6eSreyk 	if ((ret = dsa_sign_final(dsa,
780fde46d6eSreyk 	    ibuf_data(buf), ibuf_size(buf))) == -1) {
781fde46d6eSreyk 		log_debug("%s: failed to create auth signature", __func__);
782fde46d6eSreyk 		ibuf_release(buf);
783fde46d6eSreyk 		goto done;
784fde46d6eSreyk 	}
785fde46d6eSreyk 
786fde46d6eSreyk 	sa->sa_localauth.id_type = auth->auth_method;
787fde46d6eSreyk 	sa->sa_localauth.id_buf = buf;
788fde46d6eSreyk 
789fde46d6eSreyk 	ret = 0;
790fde46d6eSreyk  done:
791fde46d6eSreyk 	if (psk != NULL)
792fde46d6eSreyk 		free(psk);
793fde46d6eSreyk 	dsa_free(dsa);
794fde46d6eSreyk 
795fde46d6eSreyk 	return (ret);
796fde46d6eSreyk }
797ae494144Sreyk 
798ae494144Sreyk int
799ae494144Sreyk ikev2_msg_frompeer(struct iked_message *msg)
800ae494144Sreyk {
801ae494144Sreyk 	struct iked_sa		*sa = msg->msg_sa;
802ae494144Sreyk 	struct ike_header	*hdr;
803ae494144Sreyk 
80426d7dba1Sreyk 	msg = msg->msg_parent;
8051b0d4946Sreyk 
806ae494144Sreyk 	if (sa == NULL ||
807ae494144Sreyk 	    (hdr = ibuf_seek(msg->msg_data, 0, sizeof(*hdr))) == NULL)
808ae494144Sreyk 		return (0);
809ae494144Sreyk 
810ae494144Sreyk 	if (!sa->sa_hdr.sh_initiator &&
811ae494144Sreyk 	    (hdr->ike_flags & IKEV2_FLAG_INITIATOR))
812ae494144Sreyk 		return (1);
813ae494144Sreyk 	else if (sa->sa_hdr.sh_initiator &&
814ae494144Sreyk 	    (hdr->ike_flags & IKEV2_FLAG_INITIATOR) == 0)
815ae494144Sreyk 		return (1);
816ae494144Sreyk 
817ae494144Sreyk 	return (0);
818ae494144Sreyk }
819ae494144Sreyk 
820ae494144Sreyk struct iked_socket *
821ae494144Sreyk ikev2_msg_getsocket(struct iked *env, int af)
822ae494144Sreyk {
823ae494144Sreyk 	switch (af) {
824ae494144Sreyk 	case AF_INET:
825ae494144Sreyk 		return (env->sc_sock4);
826ae494144Sreyk 	case AF_INET6:
827ae494144Sreyk 		return (env->sc_sock6);
828ae494144Sreyk 	}
829ae494144Sreyk 
830ae494144Sreyk 	log_debug("%s: af socket %d not available", __func__, af);
831ae494144Sreyk 	return (NULL);
832ae494144Sreyk }
833