1 /* $OpenBSD: ike_aggressive.c,v 1.10 2005/04/08 22:32:10 cloder Exp $	 */
2 /* $EOM: ike_aggressive.c,v 1.4 2000/01/31 22:33:45 niklas Exp $	 */
3 
4 /*
5  * Copyright (c) 1999 Niklas Hallqvist.  All rights reserved.
6  * Copyright (c) 1999 Angelos D. Keromytis.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /*
30  * This code was written under funding by Ericsson Radio Systems.
31  */
32 
33 #include <sys/types.h>
34 #include <netinet/in.h>
35 #include <stdlib.h>
36 #include <string.h>
37 
38 #include "attribute.h"
39 #include "conf.h"
40 #include "constants.h"
41 #include "crypto.h"
42 #include "dh.h"
43 #include "doi.h"
44 #include "exchange.h"
45 #include "hash.h"
46 #include "ike_auth.h"
47 #include "ike_aggressive.h"
48 #include "ike_phase_1.h"
49 #include "ipsec.h"
50 #include "ipsec_doi.h"
51 #include "isakmp.h"
52 #include "log.h"
53 #include "math_group.h"
54 #include "message.h"
55 #include "nat_traversal.h"
56 #include "prf.h"
57 #include "sa.h"
58 #include "transport.h"
59 #include "util.h"
60 
61 static int	initiator_recv_SA_KE_NONCE_ID_AUTH(struct message *);
62 static int	initiator_send_SA_KE_NONCE_ID(struct message *);
63 static int	initiator_send_AUTH(struct message *);
64 static int	responder_recv_SA_KE_NONCE_ID(struct message *);
65 static int	responder_send_SA_KE_NONCE_ID_AUTH(struct message *);
66 static int	responder_recv_AUTH(struct message *);
67 
68 int (*ike_aggressive_initiator[])(struct message *) = {
69 	initiator_send_SA_KE_NONCE_ID,
70 	initiator_recv_SA_KE_NONCE_ID_AUTH,
71 	initiator_send_AUTH
72 };
73 
74 int (*ike_aggressive_responder[])(struct message *) = {
75 	responder_recv_SA_KE_NONCE_ID,
76 	responder_send_SA_KE_NONCE_ID_AUTH,
77 	responder_recv_AUTH
78 };
79 
80 /* Offer a set of transforms to the responder in the MSG message.  */
81 static int
initiator_send_SA_KE_NONCE_ID(struct message * msg)82 initiator_send_SA_KE_NONCE_ID(struct message *msg)
83 {
84 	if (ike_phase_1_initiator_send_SA(msg))
85 		return -1;
86 
87 	if (ike_phase_1_initiator_send_KE_NONCE(msg))
88 		return -1;
89 
90 	return ike_phase_1_send_ID(msg);
91 }
92 
93 /* Figure out what transform the responder chose.  */
94 static int
initiator_recv_SA_KE_NONCE_ID_AUTH(struct message * msg)95 initiator_recv_SA_KE_NONCE_ID_AUTH(struct message *msg)
96 {
97 	if (ike_phase_1_initiator_recv_SA(msg))
98 		return -1;
99 
100 	if (ike_phase_1_initiator_recv_KE_NONCE(msg))
101 		return -1;
102 
103 	return ike_phase_1_recv_ID_AUTH(msg);
104 }
105 
106 static int
initiator_send_AUTH(struct message * msg)107 initiator_send_AUTH(struct message *msg)
108 {
109 	msg->exchange->flags |= EXCHANGE_FLAG_ENCRYPT;
110 
111 	if (ike_phase_1_send_AUTH(msg))
112 		return -1;
113 
114 	/*
115 	 * RFC 2407 4.6.3 says that, among others, INITIAL-CONTACT MUST NOT
116 	 * be sent in Aggressive Mode.  This leaves us with the choice of
117 	 * doing it in an informational exchange of its own with no delivery
118 	 * guarantee or in the first Quick Mode, or not at all.
119 	 * draft-jenkins-ipsec-rekeying-01.txt has some text that requires
120 	 * INITIAL-CONTACT in phase 1, thus contradicting what we learned
121 	 * above.  I will bring this up in the IPsec list.  For now we don't
122 	 * do INITIAL-CONTACT at all when using aggressive mode.
123          */
124 	return 0;
125 }
126 
127 /*
128  * Accept a set of transforms offered by the initiator and chose one we can
129  * handle.  Also accept initiator's public DH value, nonce and ID.
130  */
131 static int
responder_recv_SA_KE_NONCE_ID(struct message * msg)132 responder_recv_SA_KE_NONCE_ID(struct message *msg)
133 {
134 	if (ike_phase_1_responder_recv_SA(msg))
135 		return -1;
136 
137 	if (ike_phase_1_recv_ID(msg))
138 		return -1;
139 
140 	return ike_phase_1_recv_KE_NONCE(msg);
141 }
142 
143 /*
144  * Reply with the transform we chose.  Send our public DH value and a nonce
145  * to the initiator.
146  */
147 static int
responder_send_SA_KE_NONCE_ID_AUTH(struct message * msg)148 responder_send_SA_KE_NONCE_ID_AUTH(struct message *msg)
149 {
150 	/* Add the SA payload with the transform that was chosen.  */
151 	if (ike_phase_1_responder_send_SA(msg))
152 		return -1;
153 
154 	/* XXX Should we really just use the initiator's nonce size?  */
155 	if (ike_phase_1_send_KE_NONCE(msg, msg->exchange->nonce_i_len))
156 		return -1;
157 
158 	if (ike_phase_1_post_exchange_KE_NONCE(msg))
159 		return -1;
160 
161 	return ike_phase_1_responder_send_ID_AUTH(msg);
162 }
163 
164 /*
165  * Reply with the transform we chose.  Send our public DH value and a nonce
166  * to the initiator.
167  */
168 static int
responder_recv_AUTH(struct message * msg)169 responder_recv_AUTH(struct message *msg)
170 {
171 	if (ike_phase_1_recv_AUTH(msg))
172 		return -1;
173 
174 	/* Aggressive: Check for NAT-D payloads and contents.  */
175 	if (msg->exchange->flags & EXCHANGE_FLAG_NAT_T_CAP_PEER)
176 		(void)nat_t_exchange_check_nat_d(msg);
177 	return 0;
178 }
179