File: | programs/pluto/ikev2_message.c |
Warning: | line 746, column 3 The right operand of '+' is a garbage value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* IKEv2 message routines, for Libreswan | |||
2 | * | |||
3 | * Copyright (C) 2007-2008 Michael Richardson <mcr@xelerance.com> | |||
4 | * Copyright (C) 2008-2011 Paul Wouters <paul@xelerance.com> | |||
5 | * Copyright (C) 2008 Antony Antony <antony@xelerance.com> | |||
6 | * Copyright (C) 2008-2009 David McCullough <david_mccullough@securecomputing.com> | |||
7 | * Copyright (C) 2010,2012 Avesh Agarwal <avagarwa@redhat.com> | |||
8 | * Copyright (C) 2010 Tuomo Soini <tis@foobar.fi | |||
9 | * Copyright (C) 2012-2019 Paul Wouters <pwouters@redhat.com> | |||
10 | * Copyright (C) 2012-2017 Antony Antony <antony@phenome.org> | |||
11 | * Copyright (C) 2013-2019 D. Hugh Redelmeier <hugh@mimosa.com> | |||
12 | * Copyright (C) 2013 David McCullough <ucdevel@gmail.com> | |||
13 | * Copyright (C) 2013 Matt Rogers <mrogers@redhat.com> | |||
14 | * Copyright (C) 2015-2019 Andrew Cagney <cagney@gnu.org> | |||
15 | * Copyright (C) 2017 Sahana Prasad <sahana.prasad07@gmail.com> | |||
16 | * Copyright (C) 2017 Vukasin Karadzic <vukasin.karadzic@gmail.com> | |||
17 | * Copyright (C) 2017 Mayank Totale <mtotale@gmail.com> | |||
18 | * | |||
19 | * This program is free software; you can redistribute it and/or modify it | |||
20 | * under the terms of the GNU General Public License as published by the | |||
21 | * Free Software Foundation; either version 2 of the License, or (at your | |||
22 | * option) any later version. See <https://www.gnu.org/licenses/gpl2.txt>. | |||
23 | * | |||
24 | * This program is distributed in the hope that it will be useful, but | |||
25 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |||
26 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |||
27 | * for more details. | |||
28 | */ | |||
29 | ||||
30 | ||||
31 | #include "defs.h" | |||
32 | ||||
33 | #include "log.h" | |||
34 | #include "ikev2_message.h" | |||
35 | #include "server.h" | |||
36 | #include "state.h" | |||
37 | #include "connections.h" | |||
38 | #include "ike_alg.h" | |||
39 | #include "ike_alg_encrypt_ops.h" /* XXX: oops */ | |||
40 | #include "pluto_stats.h" | |||
41 | #include "demux.h" /* for struct msg_digest */ | |||
42 | #include "rnd.h" | |||
43 | #include "crypt_prf.h" | |||
44 | #include "send.h" /* record_outbound_ike_message() */ | |||
45 | #include "ip_info.h" | |||
46 | #include "iface.h" | |||
47 | #include "ip_protocol.h" | |||
48 | #include "ikev2_send.h" | |||
49 | ||||
50 | /* | |||
51 | * Determine the IKE version we will use for the IKE packet | |||
52 | * Normally, this is "2.0", but in the future we might need to | |||
53 | * change that. Version used is the minimum 2.x version both | |||
54 | * sides support. So if we support 2.1, and they support 2.0, | |||
55 | * we should sent 2.0 (not implemented until we hit 2.1 ourselves) | |||
56 | * We also have some impair functions that modify the major/minor | |||
57 | * version on purpose - for testing | |||
58 | * | |||
59 | * rcv_version: the received IKE version, 0 if we don't know | |||
60 | * | |||
61 | * top 4 bits are major version, lower 4 bits are minor version | |||
62 | */ | |||
63 | static uint8_t build_ikev2_version(void) | |||
64 | { | |||
65 | /* TODO: if bumping, we should also set the Version flag in the ISAKMP header */ | |||
66 | return ((IKEv2_MAJOR_VERSION0x2 + (impair.major_version_bump ? 1 : 0)) | |||
67 | << ISA_MAJ_SHIFT4) | | |||
68 | (IKEv2_MINOR_VERSION0x0 + (impair.minor_version_bump ? 1 : 0)); | |||
69 | } | |||
70 | ||||
71 | uint8_t build_ikev2_critical(bool_Bool impaired) | |||
72 | { | |||
73 | uint8_t octet = 0; | |||
74 | if (impaired) { | |||
75 | /* flip the expected bit */ | |||
76 | libreswan_log("IMPAIR: setting (should be off) critical payload bit")loglog(RC_LOG, "IMPAIR: setting (should be off) critical payload bit" ); | |||
77 | octet = ISAKMP_PAYLOAD_CRITICAL0x80; | |||
78 | } else { | |||
79 | octet = ISAKMP_PAYLOAD_NONCRITICAL0x00; | |||
80 | } | |||
81 | if (impair.send_bogus_payload_flag) { | |||
82 | libreswan_log("IMPAIR: adding bogus bit to critical octet")loglog(RC_LOG, "IMPAIR: adding bogus bit to critical octet"); | |||
83 | octet |= ISAKMP_PAYLOAD_LIBRESWAN_BOGUS0x01; | |||
84 | } | |||
85 | return octet; | |||
86 | } | |||
87 | ||||
88 | /* | |||
89 | * Open an IKEv2 message. | |||
90 | * | |||
91 | * Request: IKE, which must be non-NULL, is used to determine the IKE | |||
92 | * SA Initiator / Responder role; MD must be NULL (after all a request | |||
93 | * has no response). | |||
94 | * | |||
95 | * Response: If IKE is non-NULL then it is used to determine the IKE | |||
96 | * SA Initiator / Responder role (NULL implies IKE SA Initiator); MD | |||
97 | * must be non-NULL (the message being responded to). | |||
98 | */ | |||
99 | ||||
100 | pb_stream open_v2_message(pb_stream *reply, | |||
101 | struct ike_sa *ike, struct msg_digest *md, | |||
102 | enum isakmp_xchg_types exchange_type) | |||
103 | { | |||
104 | /* at least one, possibly both */ | |||
105 | passert(ike != NULL || md != NULL){ _Bool assertion__ = ike != ((void*)0) || md != ((void*)0); if (!assertion__) { lsw_passert_fail((where_t) { .func = __func__ , .basename = "ikev2_message.c" , .line = 105}, "%s", "ike != NULL || md != NULL" ); } }; | |||
106 | ||||
107 | struct isakmp_hdr hdr = { | |||
108 | .isa_flags = impair.send_bogus_isakmp_flag ? ISAKMP_FLAGS_RESERVED_BIT6(1 << 6) : LEMPTY((lset_t)0), | |||
109 | .isa_version = build_ikev2_version(), | |||
110 | .isa_xchg = exchange_type, | |||
111 | .isa_length = 0, /* filled in when PBS is closed */ | |||
112 | }; | |||
113 | ||||
114 | /* | |||
115 | * I (Initiator) flag | |||
116 | * | |||
117 | * If there is an IKE SA, the sa_role can be used. | |||
118 | * | |||
119 | * If there is no IKE SA, then, presumably, this is a response | |||
120 | * to an initial exchange and the flag should be clear. | |||
121 | * | |||
122 | * The other possability is that this is a response to an | |||
123 | * IKEv++ message, just assume this is the initial exchange | |||
124 | * and the I flag should be clear (see 1.5. Informational | |||
125 | * Messages outside of an IKE SA). The other option would be | |||
126 | * to flip MD's I bit, but since this is IKEv++, there may not | |||
127 | * even be an I bit. | |||
128 | */ | |||
129 | enum sa_role sa_role = (ike != NULL((void*)0) ? ike->sa.st_sa_role : SA_RESPONDER); | |||
130 | if (sa_role == SA_INITIATOR) { | |||
131 | hdr.isa_flags |= ISAKMP_FLAGS_v2_IKE_I(1 << 3); | |||
132 | } | |||
133 | ||||
134 | /* | |||
135 | * R (Response) flag | |||
136 | * | |||
137 | * If there's no MD, then this must be a new exchange request | |||
138 | * - R(Responder) flag clear. | |||
139 | * | |||
140 | * If there is an MD, then this must be a response - | |||
141 | * R(Responder) flag set. | |||
142 | * | |||
143 | * Note that when MD!= NULL, v2_msg_role() can't be called (as | |||
144 | * a cross check) as this code used to force a response to a | |||
145 | * message that is close to bogus requests (1.5. | |||
146 | * Informational Messages outside of an IKE SA - where the | |||
147 | * response is forced. | |||
148 | */ | |||
149 | enum message_role message_role = (md != NULL((void*)0) ? MESSAGE_RESPONSE : MESSAGE_REQUEST); | |||
150 | if (message_role == MESSAGE_RESPONSE) { | |||
151 | hdr.isa_flags |= ISAKMP_FLAGS_v2_MSG_R(1 << 5); | |||
152 | } | |||
153 | ||||
154 | /* | |||
155 | * SPI (aka cookies). | |||
156 | */ | |||
157 | if (ike != NULL((void*)0)) { | |||
158 | /* | |||
159 | * Note that when the original initiator sends the | |||
160 | * IKE_SA_INIT request, the still zero SPIr will be | |||
161 | * copied. | |||
162 | */ | |||
163 | hdr.isa_ike_initiator_spiisa_ike_spis.initiator = ike->sa.st_ike_spis.initiator; | |||
164 | hdr.isa_ike_responder_spiisa_ike_spis.responder = ike->sa.st_ike_spis.responder; | |||
165 | } else { | |||
166 | /* | |||
167 | * Either error response notification to IKE_SA_INIT | |||
168 | * or "Informational Messages outside of an IKE SA". | |||
169 | * Use the IKE SPIs from the request. | |||
170 | */ | |||
171 | passert(md != NULL){ _Bool assertion__ = md != ((void*)0); if (!assertion__) { lsw_passert_fail ((where_t) { .func = __func__, .basename = "ikev2_message.c" , .line = 171}, "%s", "md != NULL"); } }; | |||
172 | hdr.isa_ike_initiator_spiisa_ike_spis.initiator = md->hdr.isa_ike_initiator_spiisa_ike_spis.initiator; | |||
173 | hdr.isa_ike_responder_spiisa_ike_spis.responder = md->hdr.isa_ike_responder_spiisa_ike_spis.responder; | |||
174 | } | |||
175 | ||||
176 | /* | |||
177 | * Message ID | |||
178 | */ | |||
179 | if (md != NULL((void*)0)) { | |||
180 | /* | |||
181 | * Since there is a message digest (MD) it is assumed | |||
182 | * to contain a message request. Presumably this open | |||
183 | * is for the message response - use the Message ID | |||
184 | * from the request. A better choice would be | |||
185 | * .st_v2_msgid_windows.responder.recv+1, but it isn't | |||
186 | * clear if/when that value is updated and the IKE SA | |||
187 | * isn't always available. | |||
188 | */ | |||
189 | hdr.isa_msgid = md->hdr.isa_msgid; | |||
190 | } else { | |||
191 | /* | |||
192 | * If it isn't a response then use the IKE SA's | |||
193 | * .st_v2_msgid_windows.initiator.sent+1. The field | |||
194 | * will be updated as part of finishing the state | |||
195 | * transition and sending the message. | |||
196 | */ | |||
197 | passert(ike != NULL){ _Bool assertion__ = ike != ((void*)0); if (!assertion__) { lsw_passert_fail ((where_t) { .func = __func__, .basename = "ikev2_message.c" , .line = 197}, "%s", "ike != NULL"); } }; | |||
198 | hdr.isa_msgid = ike->sa.st_v2_msgid_windows.initiator.sent + 1; | |||
199 | } | |||
200 | ||||
201 | if (impair.bad_ike_auth_xchg) { | |||
202 | libreswan_log("IMPAIR: Instead of replying with IKE_AUTH, forging an INFORMATIONAL reply")loglog(RC_LOG, "IMPAIR: Instead of replying with IKE_AUTH, forging an INFORMATIONAL reply" ); | |||
203 | if ((hdr.isa_flags & ISAKMP_FLAGS_v2_MSG_R(1 << 5)) && exchange_type == ISAKMP_v2_IKE_AUTH) { | |||
204 | hdr.isa_xchg = ISAKMP_v2_INFORMATIONAL; | |||
205 | } | |||
206 | } | |||
207 | ||||
208 | struct pbs_outpacket_byte_stream rbody; | |||
209 | diag_t d = pbs_out_struct(reply, &isakmp_hdr_desc, &hdr, sizeof(hdr), &rbody); | |||
210 | if (d != NULL((void*)0)) { | |||
211 | log_diag(RC_LOG_SERIOUS, ike->sa.st_logger, &d, "%s", ""); | |||
212 | return empty_pbs; | |||
213 | } | |||
214 | if (impair.add_unknown_v2_payload_to == exchange_type && | |||
215 | !emit_v2UNKNOWN("request", exchange_type, &rbody)) { | |||
216 | return empty_pbs; | |||
217 | } | |||
218 | ||||
219 | return rbody; | |||
220 | } | |||
221 | ||||
222 | /* | |||
223 | * This code assumes that the encrypted part of an IKE message starts | |||
224 | * with an Initialization Vector (IV) of enc_blocksize of random | |||
225 | * octets. The IV will subsequently be discarded after decryption. | |||
226 | * This is true of Cipher Block Chaining mode (CBC). | |||
227 | */ | |||
228 | static bool_Bool emit_v2SK_iv(v2SK_payload_t *sk) | |||
229 | { | |||
230 | /* compute location/size */ | |||
231 | sk->iv = chunk2(sk->pbs.cur, sk->ike->sa.st_oakley.ta_encrypt->wire_iv_size); | |||
232 | /* make space */ | |||
233 | diag_t d = pbs_out_zero(&sk->pbs, sk->iv.len, "IV"); | |||
234 | if (d != NULL((void*)0)) { | |||
235 | log_diag(RC_LOG_SERIOUS, sk->logger, &d, "%s", ""); | |||
236 | return false0; | |||
237 | } | |||
238 | /* scribble on it */ | |||
239 | fill_rnd_chunk(sk->iv); | |||
240 | return true1; | |||
241 | } | |||
242 | ||||
243 | v2SK_payload_t open_v2SK_payload(struct logger *logger, | |||
244 | pb_stream *container, | |||
245 | struct ike_sa *ike) | |||
246 | { | |||
247 | static const v2SK_payload_t empty_sk; | |||
248 | v2SK_payload_t sk = { | |||
249 | .logger = logger, | |||
250 | .ike = ike, | |||
251 | .payload = { | |||
252 | .ptr = container->cur, | |||
253 | .len = 0, /* computed at end; set here to silence GCC 6.10 */ | |||
254 | } | |||
255 | }; | |||
256 | ||||
257 | /* emit Encryption Payload header */ | |||
258 | ||||
259 | struct ikev2_generic e = { | |||
260 | .isag_length = 0, /* filled in later */ | |||
261 | .isag_critical = build_ikev2_critical(false0), | |||
262 | }; | |||
263 | if (!out_struct(&e, &ikev2_sk_desc, container, &sk.pbs)) { | |||
264 | log_message(RC_LOG, logger, | |||
265 | "error initializing SK header for encrypted %s message", | |||
266 | container->name); | |||
267 | return empty_sk; | |||
268 | } | |||
269 | ||||
270 | /* emit IV and save location */ | |||
271 | ||||
272 | if (!emit_v2SK_iv(&sk)) { | |||
273 | log_message(RC_LOG, logger, | |||
274 | "error initializing IV for encrypted %s message", | |||
275 | container->name); | |||
276 | return empty_sk; | |||
277 | } | |||
278 | ||||
279 | /* save cleartext start */ | |||
280 | ||||
281 | sk.cleartext.ptr = sk.pbs.cur; | |||
282 | passert(sk.iv.ptr <= sk.cleartext.ptr){ _Bool assertion__ = sk.iv.ptr <= sk.cleartext.ptr; if (! assertion__) { lsw_passert_fail((where_t) { .func = __func__, .basename = "ikev2_message.c" , .line = 282}, "%s", "sk.iv.ptr <= sk.cleartext.ptr" ); } }; | |||
283 | passert(sk.pbs.container->name == container->name){ _Bool assertion__ = sk.pbs.container->name == container-> name; if (!assertion__) { lsw_passert_fail((where_t) { .func = __func__, .basename = "ikev2_message.c" , .line = 283}, "%s" , "sk.pbs.container->name == container->name"); } }; | |||
284 | ||||
285 | return sk; | |||
286 | } | |||
287 | ||||
288 | bool_Bool close_v2SK_payload(v2SK_payload_t *sk) | |||
289 | { | |||
290 | /* save cleartext end */ | |||
291 | ||||
292 | sk->cleartext.len = sk->pbs.cur - sk->cleartext.ptr; | |||
293 | ||||
294 | /* emit padding + pad-length */ | |||
295 | ||||
296 | size_t padding; | |||
297 | if (sk->ike->sa.st_oakley.ta_encrypt->pad_to_blocksize) { | |||
298 | const size_t blocksize = sk->ike->sa.st_oakley.ta_encrypt->enc_blocksize; | |||
299 | padding = pad_up(sk->pbs.cur - sk->cleartext.ptr, blocksize)(((blocksize) - 1) - (((sk->pbs.cur - sk->cleartext.ptr ) + (blocksize) - 1) % (blocksize))); | |||
300 | if (padding == 0) { | |||
301 | padding = blocksize; | |||
302 | } | |||
303 | } else { | |||
304 | padding = 1; | |||
305 | } | |||
306 | dbg("adding %zd bytes of padding (including 1 byte padding-length)",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("adding %zd bytes of padding (including 1 byte padding-length)" , padding); } } | |||
307 | padding){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("adding %zd bytes of padding (including 1 byte padding-length)" , padding); } }; | |||
308 | for (unsigned i = 0; i < padding; i++) { | |||
309 | diag_t d = pbs_out_repeated_byte(&sk->pbs, i, 1, "padding and length"); | |||
310 | if (d != NULL((void*)0)) { | |||
311 | log_diag(RC_LOG_SERIOUS, sk->logger, &d, | |||
312 | "error initializing padding for encrypted %s payload: ", | |||
313 | sk->pbs.container->name); | |||
314 | return false0; | |||
315 | } | |||
316 | } | |||
317 | ||||
318 | /* emit space for integrity checksum data; save location */ | |||
319 | ||||
320 | size_t integ_size = (encrypt_desc_is_aead(sk->ike->sa.st_oakley.ta_encrypt) | |||
321 | ? sk->ike->sa.st_oakley.ta_encrypt->aead_tag_size | |||
322 | : sk->ike->sa.st_oakley.ta_integ->integ_output_size); | |||
323 | if (integ_size == 0) { | |||
324 | pexpect_fail(sk->logger, HERE(where_t) { .func = __func__, .basename = "ikev2_message.c" , .line = 324}, | |||
325 | "error initializing integrity checksum for encrypted %s payload", | |||
326 | sk->pbs.container->name); | |||
327 | return false0; | |||
328 | } | |||
329 | sk->integrity = chunk2(sk->pbs.cur, integ_size); | |||
330 | diag_t d = pbs_out_zero(&sk->pbs, integ_size, "length of truncated HMAC/KEY"); | |||
331 | if (d != NULL((void*)0)) { | |||
332 | log_diag(RC_LOG_SERIOUS, sk->logger, &d, "%s", ""); | |||
333 | return false0; | |||
334 | } | |||
335 | ||||
336 | /* close the SK payload */ | |||
337 | ||||
338 | sk->payload.len = sk->pbs.cur - sk->payload.ptr; | |||
339 | close_output_pbs(&sk->pbs); | |||
340 | ||||
341 | return true1; | |||
342 | } | |||
343 | ||||
344 | /* | |||
345 | * Form the encryption IV (a.k.a. starting variable) from the salt | |||
346 | * (a.k.a. nonce) wire-iv and a counter set to 1. | |||
347 | * | |||
348 | * note: no iv is longer than MAX_CBC_BLOCK_SIZE | |||
349 | */ | |||
350 | static void construct_enc_iv(const char *name, | |||
351 | u_char enc_iv[], | |||
352 | u_char *wire_iv, chunk_t salt, | |||
353 | const struct encrypt_desc *encrypter) | |||
354 | { | |||
355 | DBG(DBG_CRYPT, DBG_log("construct_enc_iv: %s: salt-size=%zd wire-IV-size=%zd block-size %zd",{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { DBG_log("construct_enc_iv: %s: salt-size=%zd wire-IV-size=%zd block-size %zd" , name, encrypter->salt_size, encrypter->wire_iv_size, encrypter ->enc_blocksize); } } | |||
356 | name, encrypter->salt_size, encrypter->wire_iv_size,{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { DBG_log("construct_enc_iv: %s: salt-size=%zd wire-IV-size=%zd block-size %zd" , name, encrypter->salt_size, encrypter->wire_iv_size, encrypter ->enc_blocksize); } } | |||
357 | encrypter->enc_blocksize)){ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { DBG_log("construct_enc_iv: %s: salt-size=%zd wire-IV-size=%zd block-size %zd" , name, encrypter->salt_size, encrypter->wire_iv_size, encrypter ->enc_blocksize); } }; | |||
358 | passert(salt.len == encrypter->salt_size){ _Bool assertion__ = salt.len == encrypter->salt_size; if (!assertion__) { lsw_passert_fail((where_t) { .func = __func__ , .basename = "ikev2_message.c" , .line = 358}, "%s", "salt.len == encrypter->salt_size" ); } }; | |||
359 | passert(encrypter->enc_blocksize <= MAX_CBC_BLOCK_SIZE){ _Bool assertion__ = encrypter->enc_blocksize <= (((128 ) + 8 - 1) / 8); if (!assertion__) { lsw_passert_fail((where_t ) { .func = __func__, .basename = "ikev2_message.c" , .line = 359}, "%s", "encrypter->enc_blocksize <= MAX_CBC_BLOCK_SIZE" ); } }; | |||
360 | passert(encrypter->enc_blocksize >= encrypter->salt_size + encrypter->wire_iv_size){ _Bool assertion__ = encrypter->enc_blocksize >= encrypter ->salt_size + encrypter->wire_iv_size; if (!assertion__ ) { lsw_passert_fail((where_t) { .func = __func__, .basename = "ikev2_message.c" , .line = 360}, "%s", "encrypter->enc_blocksize >= encrypter->salt_size + encrypter->wire_iv_size" ); } }; | |||
361 | size_t counter_size = encrypter->enc_blocksize - encrypter->salt_size - encrypter->wire_iv_size; | |||
362 | DBG(DBG_CRYPT, DBG_log("construct_enc_iv: %s: computed counter-size=%zd",{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { DBG_log("construct_enc_iv: %s: computed counter-size=%zd" , name, counter_size); } } | |||
363 | name, counter_size)){ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { DBG_log("construct_enc_iv: %s: computed counter-size=%zd" , name, counter_size); } }; | |||
364 | ||||
365 | memcpy(enc_iv, salt.ptr, salt.len); | |||
366 | memcpy(enc_iv + salt.len, wire_iv, encrypter->wire_iv_size); | |||
367 | if (counter_size > 0) { | |||
368 | memset(enc_iv + encrypter->enc_blocksize - counter_size, 0, | |||
369 | counter_size - 1); | |||
370 | enc_iv[encrypter->enc_blocksize - 1] = 1; | |||
371 | } | |||
372 | DBG(DBG_CRYPT, DBG_dump(name, enc_iv, encrypter->enc_blocksize)){ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { DBG_dump(name, enc_iv, encrypter->enc_blocksize); } }; | |||
373 | } | |||
374 | ||||
375 | ||||
376 | stf_status encrypt_v2SK_payload(v2SK_payload_t *sk) | |||
377 | { | |||
378 | struct ike_sa *ike = sk->ike; | |||
379 | uint8_t *auth_start = sk->pbs.container->start; | |||
380 | uint8_t *wire_iv_start = sk->iv.ptr; | |||
381 | uint8_t *enc_start = sk->cleartext.ptr; | |||
382 | uint8_t *integ_start = sk->integrity.ptr; | |||
383 | size_t integ_size = sk->integrity.len; | |||
384 | ||||
385 | passert(auth_start <= wire_iv_start){ _Bool assertion__ = auth_start <= wire_iv_start; if (!assertion__ ) { lsw_passert_fail((where_t) { .func = __func__, .basename = "ikev2_message.c" , .line = 385}, "%s", "auth_start <= wire_iv_start" ); } }; | |||
386 | passert(wire_iv_start <= enc_start){ _Bool assertion__ = wire_iv_start <= enc_start; if (!assertion__ ) { lsw_passert_fail((where_t) { .func = __func__, .basename = "ikev2_message.c" , .line = 386}, "%s", "wire_iv_start <= enc_start" ); } }; | |||
387 | passert(enc_start <= integ_start){ _Bool assertion__ = enc_start <= integ_start; if (!assertion__ ) { lsw_passert_fail((where_t) { .func = __func__, .basename = "ikev2_message.c" , .line = 387}, "%s", "enc_start <= integ_start" ); } }; | |||
388 | ||||
389 | chunk_t salt; | |||
390 | PK11SymKey *cipherkey; | |||
391 | PK11SymKey *authkey; | |||
392 | /* encrypt with our end's key */ | |||
393 | switch (ike->sa.st_sa_role) { | |||
394 | case SA_INITIATOR: | |||
395 | cipherkey = ike->sa.st_skey_ei_nss; | |||
396 | authkey = ike->sa.st_skey_ai_nss; | |||
397 | salt = ike->sa.st_skey_initiator_salt; | |||
398 | break; | |||
399 | case SA_RESPONDER: | |||
400 | cipherkey = ike->sa.st_skey_er_nss; | |||
401 | authkey = ike->sa.st_skey_ar_nss; | |||
402 | salt = ike->sa.st_skey_responder_salt; | |||
403 | break; | |||
404 | default: | |||
405 | bad_case(ike->sa.st_sa_role)libreswan_bad_case("ike->sa.st_sa_role", (ike->sa.st_sa_role ), (where_t) { .func = __func__, .basename = "ikev2_message.c" , .line = 405}); | |||
406 | } | |||
407 | ||||
408 | /* size of plain or cipher text. */ | |||
409 | size_t enc_size = integ_start - enc_start; | |||
410 | ||||
411 | /* encrypt and authenticate the block */ | |||
412 | if (encrypt_desc_is_aead(ike->sa.st_oakley.ta_encrypt)) { | |||
413 | /* | |||
414 | * Additional Authenticated Data - AAD - size. | |||
415 | * RFC5282 says: The Initialization Vector and Ciphertext | |||
416 | * fields [...] MUST NOT be included in the associated | |||
417 | * data. | |||
418 | */ | |||
419 | size_t wire_iv_size = ike->sa.st_oakley.ta_encrypt->wire_iv_size; | |||
420 | pexpect(integ_size == ike->sa.st_oakley.ta_encrypt->aead_tag_size)({ _Bool assertion__ = integ_size == ike->sa.st_oakley.ta_encrypt ->aead_tag_size; if (!assertion__) { log_pexpect((where_t) { .func = __func__, .basename = "ikev2_message.c" , .line = 420 }, "%s", "integ_size == ike->sa.st_oakley.ta_encrypt->aead_tag_size" ); } assertion__; }); | |||
421 | unsigned char *aad_start = auth_start; | |||
422 | size_t aad_size = enc_start - aad_start - wire_iv_size; | |||
423 | ||||
424 | DBG(DBG_CRYPT,{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { { typeof(salt) hunk_ = salt; DBG_dump("Salt before authenticated encryption:" , hunk_.ptr, hunk_.len); }; DBG_dump("IV before authenticated encryption:" , wire_iv_start, wire_iv_size); DBG_dump("AAD before authenticated encryption:" , aad_start, aad_size); DBG_dump("data before authenticated encryption:" , enc_start, enc_size); DBG_dump("integ before authenticated encryption:" , integ_start, integ_size); } } | |||
425 | DBG_dump_hunk("Salt before authenticated encryption:", salt);{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { { typeof(salt) hunk_ = salt; DBG_dump("Salt before authenticated encryption:" , hunk_.ptr, hunk_.len); }; DBG_dump("IV before authenticated encryption:" , wire_iv_start, wire_iv_size); DBG_dump("AAD before authenticated encryption:" , aad_start, aad_size); DBG_dump("data before authenticated encryption:" , enc_start, enc_size); DBG_dump("integ before authenticated encryption:" , integ_start, integ_size); } } | |||
426 | DBG_dump("IV before authenticated encryption:",{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { { typeof(salt) hunk_ = salt; DBG_dump("Salt before authenticated encryption:" , hunk_.ptr, hunk_.len); }; DBG_dump("IV before authenticated encryption:" , wire_iv_start, wire_iv_size); DBG_dump("AAD before authenticated encryption:" , aad_start, aad_size); DBG_dump("data before authenticated encryption:" , enc_start, enc_size); DBG_dump("integ before authenticated encryption:" , integ_start, integ_size); } } | |||
427 | wire_iv_start, wire_iv_size);{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { { typeof(salt) hunk_ = salt; DBG_dump("Salt before authenticated encryption:" , hunk_.ptr, hunk_.len); }; DBG_dump("IV before authenticated encryption:" , wire_iv_start, wire_iv_size); DBG_dump("AAD before authenticated encryption:" , aad_start, aad_size); DBG_dump("data before authenticated encryption:" , enc_start, enc_size); DBG_dump("integ before authenticated encryption:" , integ_start, integ_size); } } | |||
428 | DBG_dump("AAD before authenticated encryption:",{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { { typeof(salt) hunk_ = salt; DBG_dump("Salt before authenticated encryption:" , hunk_.ptr, hunk_.len); }; DBG_dump("IV before authenticated encryption:" , wire_iv_start, wire_iv_size); DBG_dump("AAD before authenticated encryption:" , aad_start, aad_size); DBG_dump("data before authenticated encryption:" , enc_start, enc_size); DBG_dump("integ before authenticated encryption:" , integ_start, integ_size); } } | |||
429 | aad_start, aad_size);{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { { typeof(salt) hunk_ = salt; DBG_dump("Salt before authenticated encryption:" , hunk_.ptr, hunk_.len); }; DBG_dump("IV before authenticated encryption:" , wire_iv_start, wire_iv_size); DBG_dump("AAD before authenticated encryption:" , aad_start, aad_size); DBG_dump("data before authenticated encryption:" , enc_start, enc_size); DBG_dump("integ before authenticated encryption:" , integ_start, integ_size); } } | |||
430 | DBG_dump("data before authenticated encryption:",{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { { typeof(salt) hunk_ = salt; DBG_dump("Salt before authenticated encryption:" , hunk_.ptr, hunk_.len); }; DBG_dump("IV before authenticated encryption:" , wire_iv_start, wire_iv_size); DBG_dump("AAD before authenticated encryption:" , aad_start, aad_size); DBG_dump("data before authenticated encryption:" , enc_start, enc_size); DBG_dump("integ before authenticated encryption:" , integ_start, integ_size); } } | |||
431 | enc_start, enc_size);{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { { typeof(salt) hunk_ = salt; DBG_dump("Salt before authenticated encryption:" , hunk_.ptr, hunk_.len); }; DBG_dump("IV before authenticated encryption:" , wire_iv_start, wire_iv_size); DBG_dump("AAD before authenticated encryption:" , aad_start, aad_size); DBG_dump("data before authenticated encryption:" , enc_start, enc_size); DBG_dump("integ before authenticated encryption:" , integ_start, integ_size); } } | |||
432 | DBG_dump("integ before authenticated encryption:",{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { { typeof(salt) hunk_ = salt; DBG_dump("Salt before authenticated encryption:" , hunk_.ptr, hunk_.len); }; DBG_dump("IV before authenticated encryption:" , wire_iv_start, wire_iv_size); DBG_dump("AAD before authenticated encryption:" , aad_start, aad_size); DBG_dump("data before authenticated encryption:" , enc_start, enc_size); DBG_dump("integ before authenticated encryption:" , integ_start, integ_size); } } | |||
433 | integ_start, integ_size)){ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { { typeof(salt) hunk_ = salt; DBG_dump("Salt before authenticated encryption:" , hunk_.ptr, hunk_.len); }; DBG_dump("IV before authenticated encryption:" , wire_iv_start, wire_iv_size); DBG_dump("AAD before authenticated encryption:" , aad_start, aad_size); DBG_dump("data before authenticated encryption:" , enc_start, enc_size); DBG_dump("integ before authenticated encryption:" , integ_start, integ_size); } }; | |||
434 | if (!ike->sa.st_oakley.ta_encrypt->encrypt_ops | |||
435 | ->do_aead(ike->sa.st_oakley.ta_encrypt, | |||
436 | salt.ptr, salt.len, | |||
437 | wire_iv_start, wire_iv_size, | |||
438 | aad_start, aad_size, | |||
439 | enc_start, enc_size, integ_size, | |||
440 | cipherkey, true1, sk->logger)) { | |||
441 | return STF_FAIL; | |||
442 | } | |||
443 | DBG(DBG_CRYPT,{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { DBG_dump("data after authenticated encryption:", enc_start , enc_size); DBG_dump("integ after authenticated encryption:" , integ_start, integ_size); } } | |||
444 | DBG_dump("data after authenticated encryption:",{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { DBG_dump("data after authenticated encryption:", enc_start , enc_size); DBG_dump("integ after authenticated encryption:" , integ_start, integ_size); } } | |||
445 | enc_start, enc_size);{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { DBG_dump("data after authenticated encryption:", enc_start , enc_size); DBG_dump("integ after authenticated encryption:" , integ_start, integ_size); } } | |||
446 | DBG_dump("integ after authenticated encryption:",{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { DBG_dump("data after authenticated encryption:", enc_start , enc_size); DBG_dump("integ after authenticated encryption:" , integ_start, integ_size); } } | |||
447 | integ_start, integ_size)){ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { DBG_dump("data after authenticated encryption:", enc_start , enc_size); DBG_dump("integ after authenticated encryption:" , integ_start, integ_size); } }; | |||
448 | } else { | |||
449 | /* note: no iv is longer than MAX_CBC_BLOCK_SIZE */ | |||
450 | unsigned char enc_iv[MAX_CBC_BLOCK_SIZE(((128) + 8 - 1) / 8)]; | |||
451 | construct_enc_iv("encryption IV/starting-variable", enc_iv, | |||
452 | wire_iv_start, salt, | |||
453 | ike->sa.st_oakley.ta_encrypt); | |||
454 | ||||
455 | DBG(DBG_CRYPT,{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { DBG_dump("data before encryption:", enc_start, enc_size ); } } | |||
456 | DBG_dump("data before encryption:", enc_start, enc_size)){ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { DBG_dump("data before encryption:", enc_start, enc_size ); } }; | |||
457 | ||||
458 | /* now, encrypt */ | |||
459 | ike->sa.st_oakley.ta_encrypt->encrypt_ops | |||
460 | ->do_crypt(ike->sa.st_oakley.ta_encrypt, | |||
461 | enc_start, enc_size, | |||
462 | cipherkey, | |||
463 | enc_iv, TRUE1, | |||
464 | sk->logger); | |||
465 | ||||
466 | DBG(DBG_CRYPT,{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { DBG_dump("data after encryption:", enc_start, enc_size ); } } | |||
467 | DBG_dump("data after encryption:", enc_start, enc_size)){ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { DBG_dump("data after encryption:", enc_start, enc_size ); } }; | |||
468 | /* note: saved_iv's updated value is discarded */ | |||
469 | ||||
470 | /* okay, authenticate from beginning of IV */ | |||
471 | struct crypt_prf *ctx = crypt_prf_init_symkey("integ", ike->sa.st_oakley.ta_integ->prf, | |||
472 | "authkey", authkey, sk->logger); | |||
473 | crypt_prf_update_bytes(ctx, "message", auth_start, integ_start - auth_start); | |||
474 | passert(integ_size == ike->sa.st_oakley.ta_integ->integ_output_size){ _Bool assertion__ = integ_size == ike->sa.st_oakley.ta_integ ->integ_output_size; if (!assertion__) { lsw_passert_fail( (where_t) { .func = __func__, .basename = "ikev2_message.c" , .line = 474}, "%s", "integ_size == ike->sa.st_oakley.ta_integ->integ_output_size" ); } }; | |||
475 | struct crypt_mac mac = crypt_prf_final_mac(&ctx, ike->sa.st_oakley.ta_integ); | |||
476 | memcpy_hunk(integ_start, mac, integ_size)({ const typeof(mac) hunk_ = mac; { _Bool assertion__ = hunk_ .len == integ_size; if (!assertion__) { lsw_passert_fail((where_t ) { .func = __func__, .basename = "ikev2_message.c" , .line = 476}, "%s", "hunk_.len == integ_size"); } }; memcpy(integ_start , hunk_.ptr, integ_size); }); | |||
477 | ||||
478 | DBG(DBG_CRYPT, {{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { { DBG_dump("data being hmac:", auth_start, integ_start - auth_start); DBG_dump("out calculated auth:", integ_start, integ_size); }; } } | |||
479 | DBG_dump("data being hmac:", auth_start,{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { { DBG_dump("data being hmac:", auth_start, integ_start - auth_start); DBG_dump("out calculated auth:", integ_start, integ_size); }; } } | |||
480 | integ_start - auth_start);{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { { DBG_dump("data being hmac:", auth_start, integ_start - auth_start); DBG_dump("out calculated auth:", integ_start, integ_size); }; } } | |||
481 | DBG_dump("out calculated auth:", integ_start, integ_size);{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { { DBG_dump("data being hmac:", auth_start, integ_start - auth_start); DBG_dump("out calculated auth:", integ_start, integ_size); }; } } | |||
482 | }){ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { { DBG_dump("data being hmac:", auth_start, integ_start - auth_start); DBG_dump("out calculated auth:", integ_start, integ_size); }; } }; | |||
483 | } | |||
484 | ||||
485 | return STF_OK; | |||
486 | } | |||
487 | ||||
488 | /* | |||
489 | * ikev2_decrypt_msg: decode the payload. | |||
490 | * The result is stored in-place. | |||
491 | * Calls ikev2_process_payloads to decode the payloads within. | |||
492 | * | |||
493 | * This code assumes that the encrypted part of an IKE message starts | |||
494 | * with an Initialization Vector (IV) of WIRE_IV_SIZE random octets. | |||
495 | * We will discard the IV after decryption. | |||
496 | * | |||
497 | * The (optional) salt, wire-iv, and (optional) 1 are combined to form | |||
498 | * the actual starting-variable (a.k.a. IV). | |||
499 | */ | |||
500 | ||||
501 | static bool_Bool ikev2_verify_and_decrypt_sk_payload(struct ike_sa *ike, | |||
502 | struct msg_digest *md, | |||
503 | chunk_t *chunk, | |||
504 | unsigned int iv) | |||
505 | { | |||
506 | if (!ike->sa.hidden_variables.st_skeyid_calculated) { | |||
507 | endpoint_buf b; | |||
508 | pexpect_fail(ike->sa.st_logger, HERE(where_t) { .func = __func__, .basename = "ikev2_message.c" , .line = 508}, | |||
509 | "received encrypted packet from %s but no exponents for state #%lu to decrypt it", | |||
510 | str_endpoint(&md->sender, &b), | |||
511 | ike->sa.st_serialno); | |||
512 | return false0; | |||
513 | } | |||
514 | ||||
515 | u_char *wire_iv_start = chunk->ptr + iv; | |||
516 | size_t wire_iv_size = ike->sa.st_oakley.ta_encrypt->wire_iv_size; | |||
517 | size_t integ_size = (encrypt_desc_is_aead(ike->sa.st_oakley.ta_encrypt) | |||
518 | ? ike->sa.st_oakley.ta_encrypt->aead_tag_size | |||
519 | : ike->sa.st_oakley.ta_integ->integ_output_size); | |||
520 | ||||
521 | /* | |||
522 | * check to see if length is plausible: | |||
523 | * - wire-IV | |||
524 | * - encoded data (possibly empty) | |||
525 | * - at least one padding-length byte | |||
526 | * - truncated integrity digest / tag | |||
527 | */ | |||
528 | u_char *payload_end = chunk->ptr + chunk->len; | |||
529 | if (payload_end < (wire_iv_start + wire_iv_size + 1 + integ_size)) { | |||
530 | libreswan_log("encrypted payload impossibly short (%tu)",loglog(RC_LOG, "encrypted payload impossibly short (%tu)", payload_end - wire_iv_start) | |||
531 | payload_end - wire_iv_start)loglog(RC_LOG, "encrypted payload impossibly short (%tu)", payload_end - wire_iv_start); | |||
532 | return false0; | |||
533 | } | |||
534 | ||||
535 | u_char *auth_start = chunk->ptr; | |||
536 | u_char *enc_start = wire_iv_start + wire_iv_size; | |||
537 | u_char *integ_start = payload_end - integ_size; | |||
538 | size_t enc_size = integ_start - enc_start; | |||
539 | ||||
540 | /* | |||
541 | * Check that the payload is block-size aligned. | |||
542 | * | |||
543 | * Per rfc7296 "the recipient MUST accept any length that | |||
544 | * results in proper alignment". | |||
545 | * | |||
546 | * Do this before the payload's integrity has been verified as | |||
547 | * block-alignment requirements aren't exactly secret | |||
548 | * (originally this was being done between integrity and | |||
549 | * decrypt). | |||
550 | */ | |||
551 | size_t enc_blocksize = ike->sa.st_oakley.ta_encrypt->enc_blocksize; | |||
552 | bool_Bool pad_to_blocksize = ike->sa.st_oakley.ta_encrypt->pad_to_blocksize; | |||
553 | if (pad_to_blocksize) { | |||
554 | if (enc_size % enc_blocksize != 0) { | |||
555 | libreswan_log("discarding invalid packet: %zu octet payload length is not a multiple of encryption block-size (%zu)",loglog(RC_LOG, "discarding invalid packet: %zu octet payload length is not a multiple of encryption block-size (%zu)" , enc_size, enc_blocksize) | |||
556 | enc_size, enc_blocksize)loglog(RC_LOG, "discarding invalid packet: %zu octet payload length is not a multiple of encryption block-size (%zu)" , enc_size, enc_blocksize); | |||
557 | return false0; | |||
558 | } | |||
559 | } | |||
560 | ||||
561 | chunk_t salt; | |||
562 | PK11SymKey *cipherkey; | |||
563 | PK11SymKey *authkey; | |||
564 | switch (ike->sa.st_sa_role) { | |||
565 | case SA_INITIATOR: | |||
566 | /* need responders key */ | |||
567 | cipherkey = ike->sa.st_skey_er_nss; | |||
568 | authkey = ike->sa.st_skey_ar_nss; | |||
569 | salt = ike->sa.st_skey_responder_salt; | |||
570 | break; | |||
571 | case SA_RESPONDER: | |||
572 | /* need initiators key */ | |||
573 | cipherkey = ike->sa.st_skey_ei_nss; | |||
574 | authkey = ike->sa.st_skey_ai_nss; | |||
575 | salt = ike->sa.st_skey_initiator_salt; | |||
576 | break; | |||
577 | default: | |||
578 | bad_case(ike->sa.st_sa_role)libreswan_bad_case("ike->sa.st_sa_role", (ike->sa.st_sa_role ), (where_t) { .func = __func__, .basename = "ikev2_message.c" , .line = 578}); | |||
579 | } | |||
580 | ||||
581 | /* authenticate and decrypt the block. */ | |||
582 | if (encrypt_desc_is_aead(ike->sa.st_oakley.ta_encrypt)) { | |||
583 | /* | |||
584 | * Additional Authenticated Data - AAD - size. | |||
585 | * RFC5282 says: The Initialization Vector and Ciphertext | |||
586 | * fields [...] MUST NOT be included in the associated | |||
587 | * data. | |||
588 | */ | |||
589 | unsigned char *aad_start = auth_start; | |||
590 | size_t aad_size = enc_start - auth_start - wire_iv_size; | |||
591 | ||||
592 | DBG(DBG_CRYPT,{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { { typeof(salt) hunk_ = salt; DBG_dump("Salt before authenticated decryption:" , hunk_.ptr, hunk_.len); }; DBG_dump("IV before authenticated decryption:" , wire_iv_start, wire_iv_size); DBG_dump("AAD before authenticated decryption:" , aad_start, aad_size); DBG_dump("data before authenticated decryption:" , enc_start, enc_size); DBG_dump("integ before authenticated decryption:" , integ_start, integ_size); } } | |||
593 | DBG_dump_hunk("Salt before authenticated decryption:", salt);{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { { typeof(salt) hunk_ = salt; DBG_dump("Salt before authenticated decryption:" , hunk_.ptr, hunk_.len); }; DBG_dump("IV before authenticated decryption:" , wire_iv_start, wire_iv_size); DBG_dump("AAD before authenticated decryption:" , aad_start, aad_size); DBG_dump("data before authenticated decryption:" , enc_start, enc_size); DBG_dump("integ before authenticated decryption:" , integ_start, integ_size); } } | |||
594 | DBG_dump("IV before authenticated decryption:",{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { { typeof(salt) hunk_ = salt; DBG_dump("Salt before authenticated decryption:" , hunk_.ptr, hunk_.len); }; DBG_dump("IV before authenticated decryption:" , wire_iv_start, wire_iv_size); DBG_dump("AAD before authenticated decryption:" , aad_start, aad_size); DBG_dump("data before authenticated decryption:" , enc_start, enc_size); DBG_dump("integ before authenticated decryption:" , integ_start, integ_size); } } | |||
595 | wire_iv_start, wire_iv_size);{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { { typeof(salt) hunk_ = salt; DBG_dump("Salt before authenticated decryption:" , hunk_.ptr, hunk_.len); }; DBG_dump("IV before authenticated decryption:" , wire_iv_start, wire_iv_size); DBG_dump("AAD before authenticated decryption:" , aad_start, aad_size); DBG_dump("data before authenticated decryption:" , enc_start, enc_size); DBG_dump("integ before authenticated decryption:" , integ_start, integ_size); } } | |||
596 | DBG_dump("AAD before authenticated decryption:",{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { { typeof(salt) hunk_ = salt; DBG_dump("Salt before authenticated decryption:" , hunk_.ptr, hunk_.len); }; DBG_dump("IV before authenticated decryption:" , wire_iv_start, wire_iv_size); DBG_dump("AAD before authenticated decryption:" , aad_start, aad_size); DBG_dump("data before authenticated decryption:" , enc_start, enc_size); DBG_dump("integ before authenticated decryption:" , integ_start, integ_size); } } | |||
597 | aad_start, aad_size);{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { { typeof(salt) hunk_ = salt; DBG_dump("Salt before authenticated decryption:" , hunk_.ptr, hunk_.len); }; DBG_dump("IV before authenticated decryption:" , wire_iv_start, wire_iv_size); DBG_dump("AAD before authenticated decryption:" , aad_start, aad_size); DBG_dump("data before authenticated decryption:" , enc_start, enc_size); DBG_dump("integ before authenticated decryption:" , integ_start, integ_size); } } | |||
598 | DBG_dump("data before authenticated decryption:",{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { { typeof(salt) hunk_ = salt; DBG_dump("Salt before authenticated decryption:" , hunk_.ptr, hunk_.len); }; DBG_dump("IV before authenticated decryption:" , wire_iv_start, wire_iv_size); DBG_dump("AAD before authenticated decryption:" , aad_start, aad_size); DBG_dump("data before authenticated decryption:" , enc_start, enc_size); DBG_dump("integ before authenticated decryption:" , integ_start, integ_size); } } | |||
599 | enc_start, enc_size);{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { { typeof(salt) hunk_ = salt; DBG_dump("Salt before authenticated decryption:" , hunk_.ptr, hunk_.len); }; DBG_dump("IV before authenticated decryption:" , wire_iv_start, wire_iv_size); DBG_dump("AAD before authenticated decryption:" , aad_start, aad_size); DBG_dump("data before authenticated decryption:" , enc_start, enc_size); DBG_dump("integ before authenticated decryption:" , integ_start, integ_size); } } | |||
600 | DBG_dump("integ before authenticated decryption:",{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { { typeof(salt) hunk_ = salt; DBG_dump("Salt before authenticated decryption:" , hunk_.ptr, hunk_.len); }; DBG_dump("IV before authenticated decryption:" , wire_iv_start, wire_iv_size); DBG_dump("AAD before authenticated decryption:" , aad_start, aad_size); DBG_dump("data before authenticated decryption:" , enc_start, enc_size); DBG_dump("integ before authenticated decryption:" , integ_start, integ_size); } } | |||
601 | integ_start, integ_size)){ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { { typeof(salt) hunk_ = salt; DBG_dump("Salt before authenticated decryption:" , hunk_.ptr, hunk_.len); }; DBG_dump("IV before authenticated decryption:" , wire_iv_start, wire_iv_size); DBG_dump("AAD before authenticated decryption:" , aad_start, aad_size); DBG_dump("data before authenticated decryption:" , enc_start, enc_size); DBG_dump("integ before authenticated decryption:" , integ_start, integ_size); } }; | |||
602 | if (!ike->sa.st_oakley.ta_encrypt->encrypt_ops | |||
603 | ->do_aead(ike->sa.st_oakley.ta_encrypt, | |||
604 | salt.ptr, salt.len, | |||
605 | wire_iv_start, wire_iv_size, | |||
606 | aad_start, aad_size, | |||
607 | enc_start, enc_size, integ_size, | |||
608 | cipherkey, false0, ike->sa.st_logger)) { | |||
609 | return false0; | |||
610 | } | |||
611 | DBG(DBG_CRYPT,{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { DBG_dump("data after authenticated decryption:", enc_start , enc_size + integ_size); } } | |||
612 | DBG_dump("data after authenticated decryption:",{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { DBG_dump("data after authenticated decryption:", enc_start , enc_size + integ_size); } } | |||
613 | enc_start, enc_size + integ_size)){ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { DBG_dump("data after authenticated decryption:", enc_start , enc_size + integ_size); } }; | |||
614 | } else { | |||
615 | /* | |||
616 | * check authenticator. The last INTEG_SIZE bytes are | |||
617 | * the truncated digest. | |||
618 | */ | |||
619 | struct crypt_prf *ctx = crypt_prf_init_symkey("auth", ike->sa.st_oakley.ta_integ->prf, | |||
620 | "authkey", authkey, ike->sa.st_logger); | |||
621 | crypt_prf_update_bytes(ctx, "message", auth_start, integ_start - auth_start); | |||
622 | struct crypt_mac td = crypt_prf_final_mac(&ctx, ike->sa.st_oakley.ta_integ); | |||
623 | ||||
624 | if (!hunk_memeq(td, integ_start, integ_size)({ const typeof(td) hunk_ = td; const void *mem_ = integ_start ; size_t size_ = integ_size; bytes_eq(hunk_.ptr, hunk_.len, mem_ , size_); })) { | |||
625 | libreswan_log("failed to match authenticator")loglog(RC_LOG, "failed to match authenticator"); | |||
626 | return false0; | |||
627 | } | |||
628 | ||||
629 | dbg("authenticator matched"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("authenticator matched"); } }; | |||
630 | ||||
631 | /* decrypt */ | |||
632 | ||||
633 | /* note: no iv is longer than MAX_CBC_BLOCK_SIZE */ | |||
634 | unsigned char enc_iv[MAX_CBC_BLOCK_SIZE(((128) + 8 - 1) / 8)]; | |||
635 | construct_enc_iv("decryption IV/starting-variable", enc_iv, | |||
636 | wire_iv_start, salt, | |||
637 | ike->sa.st_oakley.ta_encrypt); | |||
638 | ||||
639 | DBG(DBG_CRYPT,{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { DBG_dump("payload before decryption:", enc_start, enc_size ); } } | |||
640 | DBG_dump("payload before decryption:", enc_start, enc_size)){ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { DBG_dump("payload before decryption:", enc_start, enc_size ); } }; | |||
641 | ike->sa.st_oakley.ta_encrypt->encrypt_ops | |||
642 | ->do_crypt(ike->sa.st_oakley.ta_encrypt, | |||
643 | enc_start, enc_size, | |||
644 | cipherkey, | |||
645 | enc_iv, FALSE0, | |||
646 | ike->sa.st_logger); | |||
647 | DBG(DBG_CRYPT,{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { DBG_dump("payload after decryption:", enc_start, enc_size ); } } | |||
648 | DBG_dump("payload after decryption:", enc_start, enc_size)){ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { DBG_dump("payload after decryption:", enc_start, enc_size ); } }; | |||
649 | } | |||
650 | ||||
651 | /* | |||
652 | * Check the padding. | |||
653 | * | |||
654 | * Per rfc7296 "The sender SHOULD set the Pad Length to the | |||
655 | * minimum value that makes the combination of the payloads, | |||
656 | * the Padding, and the Pad Length a multiple of the block | |||
657 | * size, but the recipient MUST accept any length that results | |||
658 | * in proper alignment." | |||
659 | * | |||
660 | * Notice the "should". RACOON, for instance, sends extra | |||
661 | * blocks of padding that contain random bytes. | |||
662 | */ | |||
663 | uint8_t padlen = enc_start[enc_size - 1] + 1; | |||
664 | if (padlen > enc_size) { | |||
665 | libreswan_log("discarding invalid packet: padding-length %u (octet 0x%02x) is larger than %zu octet payload length",loglog(RC_LOG, "discarding invalid packet: padding-length %u (octet 0x%02x) is larger than %zu octet payload length" , padlen, padlen - 1, enc_size) | |||
666 | padlen, padlen - 1, enc_size)loglog(RC_LOG, "discarding invalid packet: padding-length %u (octet 0x%02x) is larger than %zu octet payload length" , padlen, padlen - 1, enc_size); | |||
667 | return false0; | |||
668 | } | |||
669 | if (pad_to_blocksize) { | |||
670 | if (padlen > enc_blocksize) { | |||
671 | /* probably racoon */ | |||
672 | DBG(DBG_CRYPT,{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { DBG_log("payload contains %zu blocks of extra padding (padding-length: %d (octet 0x%2x), encryption block-size: %zu)" , (padlen - 1) / enc_blocksize, padlen, padlen - 1, enc_blocksize ); } } | |||
673 | DBG_log("payload contains %zu blocks of extra padding (padding-length: %d (octet 0x%2x), encryption block-size: %zu)",{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { DBG_log("payload contains %zu blocks of extra padding (padding-length: %d (octet 0x%2x), encryption block-size: %zu)" , (padlen - 1) / enc_blocksize, padlen, padlen - 1, enc_blocksize ); } } | |||
674 | (padlen - 1) / enc_blocksize,{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { DBG_log("payload contains %zu blocks of extra padding (padding-length: %d (octet 0x%2x), encryption block-size: %zu)" , (padlen - 1) / enc_blocksize, padlen, padlen - 1, enc_blocksize ); } } | |||
675 | padlen, padlen - 1, enc_blocksize)){ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { DBG_log("payload contains %zu blocks of extra padding (padding-length: %d (octet 0x%2x), encryption block-size: %zu)" , (padlen - 1) / enc_blocksize, padlen, padlen - 1, enc_blocksize ); } }; | |||
676 | } | |||
677 | } else { | |||
678 | if (padlen > 1) { | |||
679 | DBG(DBG_CRYPT,{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { DBG_log("payload contains %u octets of extra padding (padding-length: %u (octet 0x%2x))" , padlen - 1, padlen, padlen - 1); } } | |||
680 | DBG_log("payload contains %u octets of extra padding (padding-length: %u (octet 0x%2x))",{ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { DBG_log("payload contains %u octets of extra padding (padding-length: %u (octet 0x%2x))" , padlen - 1, padlen, padlen - 1); } } | |||
681 | padlen - 1, padlen, padlen - 1)){ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { DBG_log("payload contains %u octets of extra padding (padding-length: %u (octet 0x%2x))" , padlen - 1, padlen, padlen - 1); } }; | |||
682 | } | |||
683 | } | |||
684 | ||||
685 | /* | |||
686 | * Don't check the contents of the pad octets; racoon, for | |||
687 | * instance, sets them to random values. | |||
688 | */ | |||
689 | DBG(DBG_CRYPT, DBG_log("stripping %u octets as pad", padlen)){ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { DBG_log("stripping %u octets as pad", padlen); } }; | |||
690 | *chunk = chunk2(enc_start, enc_size - padlen); | |||
691 | ||||
692 | return true1; | |||
693 | } | |||
694 | ||||
695 | /* | |||
696 | * Since the fragmented packet is intended for ST (either an IKE or | |||
697 | * CHILD SA), ST contains the fragments. | |||
698 | */ | |||
699 | static bool_Bool ikev2_reassemble_fragments(struct state *st, | |||
700 | struct msg_digest *md) | |||
701 | { | |||
702 | if (md->chain[ISAKMP_NEXT_v2SK] != NULL((void*)0)) { | |||
703 | pexpect_fail(st->st_logger, HERE(where_t) { .func = __func__, .basename = "ikev2_message.c" , .line = 703}, | |||
704 | "state #%lu has both SK ans SKF payloads", | |||
705 | st->st_serialno); | |||
706 | return false0; | |||
707 | } | |||
708 | ||||
709 | if (md->digest_roof >= elemsof(md->digest)(sizeof(md->digest) / sizeof(*(md->digest)))) { | |||
710 | libreswan_log("packet contains too many payloads; discarded")loglog(RC_LOG, "packet contains too many payloads; discarded" ); | |||
711 | return false0; | |||
712 | } | |||
713 | ||||
714 | struct v2_incomming_fragments **frags = &st->st_v2_incomming[v2_msg_role(md)]; | |||
715 | passert(*frags != NULL){ _Bool assertion__ = *frags != ((void*)0); if (!assertion__) { lsw_passert_fail((where_t) { .func = __func__, .basename = "ikev2_message.c" , .line = 715}, "%s", "*frags != NULL"); } }; | |||
716 | ||||
717 | chunk_t plain[MAX_IKE_FRAGMENTS32 + 1]; | |||
718 | passert(elemsof(plain) == elemsof((*frags)->frags)){ _Bool assertion__ = (sizeof(plain) / sizeof(*(plain))) == ( sizeof((*frags)->frags) / sizeof(*((*frags)->frags))); if (!assertion__) { lsw_passert_fail((where_t) { .func = __func__ , .basename = "ikev2_message.c" , .line = 718}, "%s", "elemsof(plain) == elemsof((*frags)->frags)" ); } }; | |||
719 | unsigned int size = 0; | |||
720 | for (unsigned i = 1; i <= (*frags)->total; i++) { | |||
721 | struct v2_incomming_fragment *frag = &(*frags)->frags[i]; | |||
722 | /* | |||
723 | * Point PLAIN at the encrypted fragment and then | |||
724 | * decrypt in-place. After the decryption, PLAIN will | |||
725 | * have been adjusted to just point at the data. | |||
726 | */ | |||
727 | plain[i] = frag->cipher; | |||
728 | if (!ikev2_verify_and_decrypt_sk_payload(ike_sa(st, HERE(where_t) { .func = __func__, .basename = "ikev2_message.c" , .line = 728}), md, | |||
729 | &plain[i], frag->iv)) { | |||
730 | loglog(RC_LOG_SERIOUS, "fragment %u of %u invalid", | |||
731 | i, (*frags)->total); | |||
732 | free_v2_incomming_fragments(frags); | |||
733 | return false0; | |||
734 | } | |||
735 | size += plain[i].len; | |||
736 | } | |||
737 | ||||
738 | /* | |||
739 | * All the fragments have been disassembled, re-assemble them | |||
740 | * into the .raw_packet buffer. | |||
741 | */ | |||
742 | pexpect(md->raw_packet.ptr == NULL)({ _Bool assertion__ = md->raw_packet.ptr == ((void*)0); if (!assertion__) { log_pexpect((where_t) { .func = __func__, . basename = "ikev2_message.c" , .line = 742}, "%s", "md->raw_packet.ptr == NULL" ); } assertion__; }); /* empty */ | |||
743 | md->raw_packet = alloc_chunk(size, "IKEv2 fragments buffer"); | |||
744 | unsigned int offset = 0; | |||
745 | for (unsigned i = 1; i <= (*frags)->total; i++) { | |||
746 | passert(offset + plain[i].len <= size){ _Bool assertion__ = offset + plain[i].len <= size; if (! assertion__) { lsw_passert_fail((where_t) { .func = __func__, .basename = "ikev2_message.c" , .line = 746}, "%s", "offset + plain[i].len <= size" ); } }; | |||
| ||||
747 | memcpy(md->raw_packet.ptr + offset, plain[i].ptr, | |||
748 | plain[i].len); | |||
749 | offset += plain[i].len; | |||
750 | } | |||
751 | ||||
752 | /* | |||
753 | * Fake up enough of an SK payload_digest to fool the caller | |||
754 | * and then use that to scribble all over the SKF | |||
755 | * payload_digest (remembering to also update the SK and SKF | |||
756 | * chains). | |||
757 | */ | |||
758 | struct payload_digest sk = { | |||
759 | .pbs = same_chunk_as_in_pbs(md->raw_packet, "decrypted SFK payloads"), | |||
760 | .payload_type = ISAKMP_NEXT_v2SK, | |||
761 | .payload.generic.isag_np = (*frags)->first_np, | |||
762 | }; | |||
763 | struct payload_digest *skf = md->chain[ISAKMP_NEXT_v2SKF]; | |||
764 | md->chain[ISAKMP_NEXT_v2SKF] = NULL((void*)0); | |||
765 | md->chain[ISAKMP_NEXT_v2SK] = skf; | |||
766 | *skf = sk; /* scribble */ | |||
767 | ||||
768 | free_v2_incomming_fragments(frags); | |||
769 | ||||
770 | return true1; | |||
771 | } | |||
772 | ||||
773 | /* | |||
774 | * Decrypt the, possibly fragmented message intended for ST. | |||
775 | * | |||
776 | * Since the message fragments are stored in the recipient's ST | |||
777 | * (either IKE or CHILD SA), it, and not the IKE SA is needed. | |||
778 | */ | |||
779 | bool_Bool ikev2_decrypt_msg(struct state *st, struct msg_digest *md) | |||
780 | { | |||
781 | bool_Bool ok; | |||
782 | if (md->chain[ISAKMP_NEXT_v2SKF] != NULL((void*)0)) { | |||
| ||||
783 | /* | |||
784 | * ST points at the state (parent or child) that has | |||
785 | * all the fragments. | |||
786 | */ | |||
787 | ok = ikev2_reassemble_fragments(st, md); | |||
788 | } else { | |||
789 | pb_stream *e_pbs = &md->chain[ISAKMP_NEXT_v2SK]->pbs; | |||
790 | /* | |||
791 | * If so impaired, clone the encrypted message before | |||
792 | * it gets decrypted in-place (but only once). | |||
793 | */ | |||
794 | if (impair.replay_encrypted && !md->fake_clone) { | |||
795 | libreswan_log("IMPAIR: cloning incoming encrypted message and scheduling its replay")loglog(RC_LOG, "IMPAIR: cloning incoming encrypted message and scheduling its replay" ); | |||
796 | schedule_md_event("replay encrypted message", | |||
797 | clone_raw_md(md, "copy of encrypted message")); | |||
798 | } | |||
799 | if (impair.corrupt_encrypted && !md->fake_clone) { | |||
800 | libreswan_log("IMPAIR: corrupting incoming encrypted message's SK payload's first byte")loglog(RC_LOG, "IMPAIR: corrupting incoming encrypted message's SK payload's first byte" ); | |||
801 | *e_pbs->cur = ~(*e_pbs->cur); | |||
802 | } | |||
803 | ||||
804 | chunk_t c = chunk2(md->packet_pbs.start, | |||
805 | e_pbs->roof - md->packet_pbs.start); | |||
806 | ok = ikev2_verify_and_decrypt_sk_payload(ike_sa(st, HERE(where_t) { .func = __func__, .basename = "ikev2_message.c" , .line = 806}), md, &c, | |||
807 | e_pbs->cur - md->packet_pbs.start); | |||
808 | md->chain[ISAKMP_NEXT_v2SK]->pbs = same_chunk_as_in_pbs(c, "decrypted SK payload"); | |||
809 | } | |||
810 | ||||
811 | dbg("#%lu ikev2 %s decrypt %s",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("#%lu ikev2 %s decrypt %s", st->st_serialno , enum_name(&ikev2_exchange_names, md->hdr.isa_xchg), ok ? "success" : "failed"); } } | |||
812 | st->st_serialno,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("#%lu ikev2 %s decrypt %s", st->st_serialno , enum_name(&ikev2_exchange_names, md->hdr.isa_xchg), ok ? "success" : "failed"); } } | |||
813 | enum_name(&ikev2_exchange_names, md->hdr.isa_xchg),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("#%lu ikev2 %s decrypt %s", st->st_serialno , enum_name(&ikev2_exchange_names, md->hdr.isa_xchg), ok ? "success" : "failed"); } } | |||
814 | ok ? "success" : "failed"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("#%lu ikev2 %s decrypt %s", st->st_serialno , enum_name(&ikev2_exchange_names, md->hdr.isa_xchg), ok ? "success" : "failed"); } }; | |||
815 | ||||
816 | return ok; | |||
817 | } | |||
818 | ||||
819 | /* | |||
820 | * IKEv2 fragments: | |||
821 | * | |||
822 | * 1 2 3 | |||
823 | * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | |||
824 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
825 | * | Next Payload |C| RESERVED | Payload Length | | |||
826 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
827 | * | Fragment Number | Total Fragments | | |||
828 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
829 | * | Initialization Vector | | |||
830 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
831 | * ~ Encrypted content ~ | |||
832 | * + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
833 | * | | Padding (0-255 octets) | | |||
834 | * +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ | |||
835 | * | | Pad Length | | |||
836 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
837 | * ~ Integrity Checksum Data ~ | |||
838 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
839 | * | |||
840 | ||||
841 | * | |||
842 | */ | |||
843 | ||||
844 | static bool_Bool record_outbound_fragment(struct logger *logger, | |||
845 | struct ike_sa *ike, | |||
846 | const struct isakmp_hdr *hdr, | |||
847 | enum next_payload_types_ikev2 skf_np, | |||
848 | struct v2_outgoing_fragment **fragp, | |||
849 | chunk_t *fragment, /* read-only */ | |||
850 | unsigned int number, unsigned int total, | |||
851 | const char *desc) | |||
852 | { | |||
853 | /* make sure HDR is at start of a clean buffer */ | |||
854 | unsigned char frag_buffer[PMAX(MIN_MAX_UDP_DATA_v4, MIN_MAX_UDP_DATA_v6)(((576 - 20)) >= ((1280 - 48)) ? ((576 - 20)) : ((1280 - 48 )))]; | |||
855 | struct pbs_outpacket_byte_stream frag_stream = open_pbs_out("reply frag packet", | |||
856 | frag_buffer, sizeof(frag_buffer), | |||
857 | logger); | |||
858 | ||||
859 | /* HDR out */ | |||
860 | ||||
861 | pb_stream rbody; | |||
862 | if (!out_struct(hdr, &isakmp_hdr_desc, &frag_stream, | |||
863 | &rbody)) | |||
864 | return false0; | |||
865 | ||||
866 | /* | |||
867 | * Fake up an SK payload description sufficient to fool the | |||
868 | * encryption code. | |||
869 | * | |||
870 | * While things are close, they are not identical - an SKF | |||
871 | * payload header has extra fields and, for the first | |||
872 | * fragment, forces the Next Payload. | |||
873 | */ | |||
874 | ||||
875 | v2SK_payload_t skf = { | |||
876 | .ike = ike, | |||
877 | .payload = { | |||
878 | .ptr = rbody.cur, | |||
879 | .len = 0 /* computed at end; set here to silence GCC 4.8.5 */ | |||
880 | } | |||
881 | }; | |||
882 | ||||
883 | /* | |||
884 | * emit SKF header, save location. | |||
885 | * | |||
886 | * In the first fragment, .NP is set to the SK payload's next | |||
887 | * payload type. | |||
888 | */ | |||
889 | ||||
890 | const struct ikev2_skf e = { | |||
891 | .isaskf_np = skf_np, /* needed */ | |||
892 | .isaskf_critical = build_ikev2_critical(false0), | |||
893 | .isaskf_number = number, | |||
894 | .isaskf_total = total, | |||
895 | }; | |||
896 | if (!out_struct(&e, &ikev2_skf_desc, &rbody, &skf.pbs)) | |||
897 | return false0; | |||
898 | ||||
899 | /* emit IV and save location */ | |||
900 | ||||
901 | if (!emit_v2SK_iv(&skf)) { | |||
902 | log_message(RC_LOG, logger, | |||
903 | "error initializing IV for encrypted %s message", | |||
904 | desc); | |||
905 | return false0; | |||
906 | } | |||
907 | ||||
908 | /* save cleartext start */ | |||
909 | ||||
910 | skf.cleartext.ptr = skf.pbs.cur; | |||
911 | ||||
912 | /* output the fragment */ | |||
913 | ||||
914 | if (!pbs_out_hunk(*fragment, &skf.pbs,({ typeof(*fragment) hunk_ = *fragment; struct packet_byte_stream *outs_ = &skf.pbs; diag_t d_ = pbs_out_raw(outs_, hunk_. ptr, hunk_.len, ("cleartext fragment")); if (d_ != ((void*)0) ) { log_diag(RC_LOG_SERIOUS, outs_->out_logger, &d_, "%s" , ""); } d_ == ((void*)0); }) | |||
915 | "cleartext fragment")({ typeof(*fragment) hunk_ = *fragment; struct packet_byte_stream *outs_ = &skf.pbs; diag_t d_ = pbs_out_raw(outs_, hunk_. ptr, hunk_.len, ("cleartext fragment")); if (d_ != ((void*)0) ) { log_diag(RC_LOG_SERIOUS, outs_->out_logger, &d_, "%s" , ""); } d_ == ((void*)0); })) | |||
916 | return false0; | |||
917 | ||||
918 | if (!close_v2SK_payload(&skf)) { | |||
919 | return false0; | |||
920 | } | |||
921 | ||||
922 | close_output_pbs(&rbody); | |||
923 | close_output_pbs(&frag_stream); | |||
924 | ||||
925 | stf_status ret = encrypt_v2SK_payload(&skf); | |||
926 | if (ret != STF_OK) { | |||
927 | log_message(RC_LOG, logger, "error encrypting fragment %u", number); | |||
928 | return false0; | |||
929 | } | |||
930 | ||||
931 | dbg("recording fragment %u", number){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("recording fragment %u", number); } }; | |||
932 | record_v2_outgoing_fragment(&frag_stream, desc, fragp); | |||
933 | return true1; | |||
934 | } | |||
935 | ||||
936 | static bool_Bool record_outbound_fragments(const pb_stream *rbody, | |||
937 | v2SK_payload_t *sk, | |||
938 | const char *desc, | |||
939 | struct v2_outgoing_fragment **frags) | |||
940 | { | |||
941 | free_v2_outgoing_fragments(frags); | |||
942 | ||||
943 | /* | |||
944 | * fragment contents: | |||
945 | * - sometimes: NON_ESP_MARKER (RFC3948) (NON_ESP_MARKER_SIZE) (4) | |||
946 | * - always: isakmp header (NSIZEOF_isakmp_hdr) (28) | |||
947 | * - always: ikev2_skf header (NSIZEOF_ikev2_skf) (8) | |||
948 | * - variable: IV (no IV is longer than SHA2_512_DIGEST_SIZE) (64 or less) | |||
949 | * - variable: fragment's data | |||
950 | * - variable: padding (no padding is longer than MAX_CBC_BLOCK_SIZE) (16 or less) | |||
951 | */ | |||
952 | ||||
953 | /* | |||
954 | * XXX: this math seems very contrived, can the fragment() | |||
955 | * function above be left to do the computation on-the-fly? | |||
956 | */ | |||
957 | ||||
958 | unsigned int len = endpoint_type(&sk->ike->sa.st_remote_endpoint)->ikev2_max_fragment_size; | |||
959 | ||||
960 | /* | |||
961 | * If we are doing NAT, so that the other end doesn't mistake | |||
962 | * this message for ESP, each message needs a non-ESP_Marker | |||
963 | * prefix. | |||
964 | */ | |||
965 | if (sk->ike->sa.st_interface != NULL((void*)0) && sk->ike->sa.st_interface->esp_encapsulation_enabled) | |||
966 | len -= NON_ESP_MARKER_SIZE4; | |||
967 | ||||
968 | len -= NSIZEOF_isakmp_hdr28 + NSIZEOF_ikev2_skf8; | |||
969 | ||||
970 | len -= (encrypt_desc_is_aead(sk->ike->sa.st_oakley.ta_encrypt) | |||
971 | ? sk->ike->sa.st_oakley.ta_encrypt->aead_tag_size | |||
972 | : sk->ike->sa.st_oakley.ta_integ->integ_output_size); | |||
973 | ||||
974 | if (sk->ike->sa.st_oakley.ta_encrypt->pad_to_blocksize) | |||
975 | len &= ~(sk->ike->sa.st_oakley.ta_encrypt->enc_blocksize - 1); | |||
976 | ||||
977 | len -= 2; /* ??? what's this? */ | |||
978 | ||||
979 | passert(sk->cleartext.len != 0){ _Bool assertion__ = sk->cleartext.len != 0; if (!assertion__ ) { lsw_passert_fail((where_t) { .func = __func__, .basename = "ikev2_message.c" , .line = 979}, "%s", "sk->cleartext.len != 0" ); } }; | |||
980 | ||||
981 | unsigned int nfrags = (sk->cleartext.len + len - 1) / len; | |||
982 | ||||
983 | if (nfrags > MAX_IKE_FRAGMENTS32) { | |||
984 | log_message(RC_LOG_SERIOUS, sk->logger, | |||
985 | "fragmenting this %zu byte message into %u byte chunks leads to too many frags", | |||
986 | sk->cleartext.len, len); | |||
987 | return false0; | |||
988 | } | |||
989 | ||||
990 | /* | |||
991 | * Extract the hdr from the original unfragmented message. | |||
992 | * Set it up for auto-update of it's next payload field chain. | |||
993 | */ | |||
994 | struct isakmp_hdr hdr; | |||
995 | { | |||
996 | pb_stream pbs; | |||
997 | init_pbs(&pbs, rbody->start, pbs_offset(rbody)((size_t)((rbody)->cur - (rbody)->start)), "sk hdr"); | |||
998 | if (!in_struct(&hdr, &isakmp_hdr_desc, &pbs, NULL((void*)0))) { | |||
999 | return false0; | |||
1000 | } | |||
1001 | } | |||
1002 | hdr.isa_np = ISAKMP_NEXT_v2NONE; /* clear NP */ | |||
1003 | ||||
1004 | /* | |||
1005 | * Extract the SK's next payload field from the original | |||
1006 | * unfragmented message. This is used as the first SKF's NP | |||
1007 | * field, the rest have NP=NONE(0). | |||
1008 | */ | |||
1009 | enum next_payload_types_ikev2 skf_np; | |||
1010 | { | |||
1011 | pb_stream pbs = same_chunk_as_in_pbs(sk->payload, "sk"); | |||
1012 | struct ikev2_generic e; | |||
1013 | if (!in_struct(&e, &ikev2_sk_desc, &pbs, NULL((void*)0))) { | |||
1014 | return false0; | |||
1015 | } | |||
1016 | skf_np = e.isag_np; | |||
1017 | } | |||
1018 | ||||
1019 | unsigned int number = 1; | |||
1020 | unsigned int offset = 0; | |||
1021 | ||||
1022 | struct v2_outgoing_fragment **frag = frags; | |||
1023 | while (true1) { | |||
1024 | passert(*frag == NULL){ _Bool assertion__ = *frag == ((void*)0); if (!assertion__) { lsw_passert_fail((where_t) { .func = __func__, .basename = "ikev2_message.c" , .line = 1024}, "%s", "*frag == NULL"); } }; | |||
1025 | chunk_t fragment = chunk2(sk->cleartext.ptr + offset, | |||
1026 | PMIN(sk->cleartext.len - offset, len)((sk->cleartext.len - offset) <= (len) ? (sk->cleartext .len - offset) : (len))); | |||
1027 | if (!record_outbound_fragment(sk->logger, sk->ike, &hdr, skf_np, frag, | |||
1028 | &fragment, number, nfrags, desc)) { | |||
1029 | return false0; | |||
1030 | } | |||
1031 | frag = &(*frag)->next; | |||
1032 | ||||
1033 | offset += fragment.len; | |||
1034 | number++; | |||
1035 | skf_np = ISAKMP_NEXT_v2NONE; | |||
1036 | ||||
1037 | if (offset >= sk->cleartext.len) { | |||
1038 | break; | |||
1039 | } | |||
1040 | } | |||
1041 | ||||
1042 | return true1; | |||
1043 | } | |||
1044 | ||||
1045 | /* | |||
1046 | * Record the message ready for sending. If needed, first fragment | |||
1047 | * it. | |||
1048 | * | |||
1049 | * ST is where to save the outgoing message. XXX: Currently it is | |||
1050 | * always the parent. But that breaks when trying to juggle multiple | |||
1051 | * children trying to exchange messages. | |||
1052 | */ | |||
1053 | ||||
1054 | stf_status record_v2SK_message(pb_stream *msg, | |||
1055 | v2SK_payload_t *sk, | |||
1056 | const char *what, | |||
1057 | enum message_role message) | |||
1058 | { | |||
1059 | size_t len = pbs_offset(msg)((size_t)((msg)->cur - (msg)->start)); | |||
1060 | ||||
1061 | /* | |||
1062 | * If we are doing NAT, so that the other end doesn't mistake | |||
1063 | * this message for ESP, each message needs a non-ESP_Marker | |||
1064 | * prefix. | |||
1065 | */ | |||
1066 | if (!pexpect(sk->ike->sa.st_interface != NULL)({ _Bool assertion__ = sk->ike->sa.st_interface != ((void *)0); if (!assertion__) { log_pexpect((where_t) { .func = __func__ , .basename = "ikev2_message.c" , .line = 1066}, "%s", "sk->ike->sa.st_interface != NULL" ); } assertion__; }) && | |||
1067 | sk->ike->sa.st_interface->esp_encapsulation_enabled) | |||
1068 | len += NON_ESP_MARKER_SIZE4; | |||
1069 | ||||
1070 | /* IPv4 and IPv6 have different fragment sizes */ | |||
1071 | if (sk->ike->sa.st_interface->protocol == &ip_protocol_udp && | |||
1072 | LIN(POLICY_IKE_FRAG_ALLOW, sk->ike->sa.st_connection->policy)(((((lset_t)1 << (POLICY_IKE_FRAG_ALLOW_IX))) & (sk ->ike->sa.st_connection->policy)) == (((lset_t)1 << (POLICY_IKE_FRAG_ALLOW_IX)))) && | |||
1073 | sk->ike->sa.st_seen_fragmentation_supported && | |||
1074 | len >= endpoint_type(&sk->ike->sa.st_remote_endpoint)->ikev2_max_fragment_size) { | |||
1075 | struct v2_outgoing_fragment **frags = &sk->ike->sa.st_v2_outgoing[message]; | |||
1076 | if (!record_outbound_fragments(msg, sk, what, frags)) { | |||
1077 | dbg("record outbound fragments failed"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("record outbound fragments failed"); } }; | |||
1078 | return STF_INTERNAL_ERROR; | |||
1079 | } | |||
1080 | } else { | |||
1081 | if (encrypt_v2SK_payload(sk) != STF_OK) { | |||
1082 | log_message(RC_LOG, sk->logger, | |||
1083 | "error encrypting %s message", what); | |||
1084 | return STF_INTERNAL_ERROR; | |||
1085 | } | |||
1086 | dbg("recording outgoing fragment failed"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("recording outgoing fragment failed"); } }; | |||
1087 | record_v2_message(sk->ike, msg, what, message); | |||
1088 | } | |||
1089 | return STF_OK; | |||
1090 | } | |||
1091 | ||||
1092 | struct ikev2_id build_v2_id_payload(const struct end *end, shunk_t *body, | |||
1093 | const char *what, struct logger *logger) | |||
1094 | { | |||
1095 | struct ikev2_id id_header = { | |||
1096 | .isai_type = id_to_payload(&end->id, &end->host_addr, body), | |||
1097 | .isai_critical = build_ikev2_critical(false0), | |||
1098 | }; | |||
1099 | if (impair.send_nonzero_reserved_id) { | |||
1100 | log_message(RC_LOG, logger, "IMPAIR: setting reserved byte 3 of %s to 0x%02x", | |||
1101 | what, ISAKMP_PAYLOAD_LIBRESWAN_BOGUS0x01); | |||
1102 | id_header.isai_res3 = ISAKMP_PAYLOAD_LIBRESWAN_BOGUS0x01; | |||
1103 | } | |||
1104 | return id_header; | |||
1105 | } |