File: | programs/pluto/ikev2_message.c |
Warning: | line 1089, column 38 Passed-by-value struct argument contains uninitialized data (e.g., field: 'ptr') |
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 | * Copyright (C) 2020 Yulia Kuzovkova <ukuzovkova@gmail.com> | |||
19 | * | |||
20 | * This program is free software; you can redistribute it and/or modify it | |||
21 | * under the terms of the GNU General Public License as published by the | |||
22 | * Free Software Foundation; either version 2 of the License, or (at your | |||
23 | * option) any later version. See <https://www.gnu.org/licenses/gpl2.txt>. | |||
24 | * | |||
25 | * This program is distributed in the hope that it will be useful, but | |||
26 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |||
27 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |||
28 | * for more details. | |||
29 | */ | |||
30 | ||||
31 | ||||
32 | #include "defs.h" | |||
33 | ||||
34 | #include "log.h" | |||
35 | #include "ikev2_message.h" | |||
36 | #include "server.h" | |||
37 | #include "state.h" | |||
38 | #include "connections.h" | |||
39 | #include "ike_alg.h" | |||
40 | #include "ike_alg_encrypt_ops.h" /* XXX: oops */ | |||
41 | #include "pluto_stats.h" | |||
42 | #include "demux.h" /* for struct msg_digest */ | |||
43 | #include "rnd.h" | |||
44 | #include "crypt_prf.h" | |||
45 | #include "send.h" /* record_outbound_ike_message() */ | |||
46 | #include "ip_info.h" | |||
47 | #include "iface.h" | |||
48 | #include "ip_protocol.h" | |||
49 | #include "ikev2_send.h" | |||
50 | ||||
51 | /* | |||
52 | * Determine the IKE version we will use for the IKE packet | |||
53 | * Normally, this is "2.0", but in the future we might need to | |||
54 | * change that. Version used is the minimum 2.x version both | |||
55 | * sides support. So if we support 2.1, and they support 2.0, | |||
56 | * we should sent 2.0 (not implemented until we hit 2.1 ourselves) | |||
57 | * We also have some impair functions that modify the major/minor | |||
58 | * version on purpose - for testing | |||
59 | * | |||
60 | * rcv_version: the received IKE version, 0 if we don't know | |||
61 | * | |||
62 | * top 4 bits are major version, lower 4 bits are minor version | |||
63 | */ | |||
64 | static uint8_t build_ikev2_version(void) | |||
65 | { | |||
66 | /* TODO: if bumping, we should also set the Version flag in the ISAKMP header */ | |||
67 | return ((IKEv2_MAJOR_VERSION0x2 + (impair.major_version_bump ? 1 : 0)) | |||
68 | << ISA_MAJ_SHIFT4) | | |||
69 | (IKEv2_MINOR_VERSION0x0 + (impair.minor_version_bump ? 1 : 0)); | |||
70 | } | |||
71 | ||||
72 | uint8_t build_ikev2_critical(bool_Bool impaired, struct logger *logger) | |||
73 | { | |||
74 | uint8_t octet = 0; | |||
75 | if (impaired) { | |||
76 | /* flip the expected bit */ | |||
77 | llog(RC_LOG, logger, "IMPAIR: setting (should be off) critical payload bit"); | |||
78 | octet = ISAKMP_PAYLOAD_CRITICAL(1<<ISAKMP_PAYLOAD_FLAG_CRITICAL_IX); | |||
79 | } else { | |||
80 | octet = ISAKMP_PAYLOAD_NONCRITICAL0x00; | |||
81 | } | |||
82 | if (impair.send_bogus_payload_flag) { | |||
83 | llog(RC_LOG, logger, "IMPAIR: adding bogus bit to critical octet"); | |||
84 | octet |= ISAKMP_PAYLOAD_FLAG_LIBRESWAN_BOGUS(1<<ISAKMP_PAYLOAD_FLAG_LIBRESWAN_BOGUS_IX); | |||
85 | } | |||
86 | return octet; | |||
87 | } | |||
88 | ||||
89 | /* | |||
90 | * Open an IKEv2 message, return the message body. | |||
91 | * | |||
92 | * Request: IKE, which must be non-NULL, is used to determine the IKE | |||
93 | * SA Initiator / Responder role; MD must be NULL (after all a request | |||
94 | * has no response). | |||
95 | * | |||
96 | * Response: If IKE is non-NULL then it is used to determine the IKE | |||
97 | * SA Initiator / Responder role (NULL implies IKE SA Initiator); MD | |||
98 | * must be non-NULL (the message being responded to). | |||
99 | */ | |||
100 | ||||
101 | struct pbs_outpacket_byte_stream open_v2_message(struct pbs_outpacket_byte_stream *message, | |||
102 | struct ike_sa *ike, struct msg_digest *md, | |||
103 | enum isakmp_xchg_type exchange_type) | |||
104 | { | |||
105 | /* at least one, possibly both */ | |||
106 | passert(ike != NULL || md != NULL)({ _Bool assertion__ = ike != ((void*)0) || md != ((void*)0); if (!assertion__) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2_message.c" , .line = 106, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_passert(logger_, here, "%s", "ike != ((void*)0) || md != ((void*)0)" ); } (void) 1; }); | |||
107 | ||||
108 | struct isakmp_hdr hdr = { | |||
109 | .isa_flags = impair.send_bogus_isakmp_flag ? ISAKMP_FLAGS_RESERVED_BIT6(1<<ISAKMP_FLAGS_RESERVED_BIT6_IX) : LEMPTY((lset_t)0), | |||
110 | .isa_version = build_ikev2_version(), | |||
111 | .isa_xchg = exchange_type, | |||
112 | .isa_length = 0, /* filled in when PBS is closed */ | |||
113 | }; | |||
114 | ||||
115 | /* | |||
116 | * I (Initiator) flag | |||
117 | * | |||
118 | * If there is an IKE SA, the sa_role can be used. | |||
119 | * | |||
120 | * If there is no IKE SA, then, presumably, this is a response | |||
121 | * to an initial exchange and the flag should be clear. | |||
122 | * | |||
123 | * The other possibility is that this is a response to an | |||
124 | * IKEv++ message, just assume this is the initial exchange | |||
125 | * and the I flag should be clear (see 1.5. Informational | |||
126 | * Messages outside of an IKE SA). The other option would be | |||
127 | * to flip MD's I bit, but since this is IKEv++, there may not | |||
128 | * even be an I bit. | |||
129 | */ | |||
130 | enum sa_role sa_role = (ike != NULL((void*)0) ? ike->sa.st_sa_role : SA_RESPONDER); | |||
131 | if (sa_role == SA_INITIATOR) { | |||
132 | hdr.isa_flags |= ISAKMP_FLAGS_v2_IKE_I(1<<ISAKMP_FLAGS_v2_IKE_I_IX); | |||
133 | } | |||
134 | ||||
135 | /* | |||
136 | * R (Response) flag | |||
137 | * | |||
138 | * If there's no MD, then this must be a new exchange request | |||
139 | * - R(Responder) flag clear. | |||
140 | * | |||
141 | * If there is an MD, then this must be a response - | |||
142 | * R(Responder) flag set. | |||
143 | * | |||
144 | * Note that when MD!= NULL, v2_msg_role() can't be called (as | |||
145 | * a cross check) as this code used to force a response to a | |||
146 | * message that is close to bogus requests (1.5. | |||
147 | * Informational Messages outside of an IKE SA - where the | |||
148 | * response is forced. | |||
149 | */ | |||
150 | enum message_role message_role = (md != NULL((void*)0) ? MESSAGE_RESPONSE : MESSAGE_REQUEST); | |||
151 | if (message_role == MESSAGE_RESPONSE) { | |||
152 | hdr.isa_flags |= ISAKMP_FLAGS_v2_MSG_R(1<<ISAKMP_FLAGS_v2_MSG_R_IX); | |||
153 | } | |||
154 | ||||
155 | /* | |||
156 | * SPI (aka cookies). | |||
157 | */ | |||
158 | if (ike != NULL((void*)0)) { | |||
159 | /* | |||
160 | * Note that when the original initiator sends the | |||
161 | * IKE_SA_INIT request, the still zero SPIr will be | |||
162 | * copied. | |||
163 | */ | |||
164 | hdr.isa_ike_initiator_spiisa_ike_spis.initiator = ike->sa.st_ike_spis.initiator; | |||
165 | hdr.isa_ike_responder_spiisa_ike_spis.responder = ike->sa.st_ike_spis.responder; | |||
166 | } else { | |||
167 | /* | |||
168 | * Either error response notification to IKE_SA_INIT | |||
169 | * or "Informational Messages outside of an IKE SA". | |||
170 | * Use the IKE SPIs from the request. | |||
171 | */ | |||
172 | passert(md != NULL)({ _Bool assertion__ = md != ((void*)0); if (!assertion__) { where_t here = ({ static const struct where here = { .func = __func__ , .file = "programs/pluto/ikev2_message.c", .line = 172, }; & here; }); const struct logger *logger_ = &failsafe_logger ; llog_passert(logger_, here, "%s", "md != ((void*)0)"); } (void ) 1; }); | |||
173 | hdr.isa_ike_initiator_spiisa_ike_spis.initiator = md->hdr.isa_ike_initiator_spiisa_ike_spis.initiator; | |||
174 | hdr.isa_ike_responder_spiisa_ike_spis.responder = md->hdr.isa_ike_responder_spiisa_ike_spis.responder; | |||
175 | } | |||
176 | ||||
177 | /* | |||
178 | * Message ID | |||
179 | */ | |||
180 | if (md != NULL((void*)0)) { | |||
181 | /* | |||
182 | * Since there is a message digest (MD) it is assumed | |||
183 | * to contain a message request. Presumably this open | |||
184 | * is for the message response - use the Message ID | |||
185 | * from the request. A better choice would be | |||
186 | * .st_v2_msgid_windows.responder.recv+1, but it isn't | |||
187 | * clear if/when that value is updated and the IKE SA | |||
188 | * isn't always available. | |||
189 | */ | |||
190 | hdr.isa_msgid = md->hdr.isa_msgid; | |||
191 | } else { | |||
192 | /* | |||
193 | * If it isn't a response then use the IKE SA's | |||
194 | * .st_v2_msgid_windows.initiator.sent+1. The field | |||
195 | * will be updated as part of finishing the state | |||
196 | * transition and sending the message. | |||
197 | */ | |||
198 | passert(ike != NULL)({ _Bool assertion__ = ike != ((void*)0); if (!assertion__) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2_message.c", .line = 198 , }; &here; }); const struct logger *logger_ = &failsafe_logger ; llog_passert(logger_, here, "%s", "ike != ((void*)0)"); } ( void) 1; }); | |||
199 | hdr.isa_msgid = ike->sa.st_v2_msgid_windows.initiator.sent + 1; | |||
200 | } | |||
201 | ||||
202 | if (impair.bad_ike_auth_xchg) { | |||
203 | log_state(RC_LOG, &ike->sa, "IMPAIR: Instead of replying with IKE_AUTH, forging an INFORMATIONAL reply"); | |||
204 | if ((hdr.isa_flags & ISAKMP_FLAGS_v2_MSG_R(1<<ISAKMP_FLAGS_v2_MSG_R_IX)) && exchange_type == ISAKMP_v2_IKE_AUTH) { | |||
205 | hdr.isa_xchg = ISAKMP_v2_INFORMATIONAL; | |||
206 | } | |||
207 | } | |||
208 | ||||
209 | struct pbs_outpacket_byte_stream body; | |||
210 | diag_t d = pbs_out_struct(message, &isakmp_hdr_desc, &hdr, sizeof(hdr), &body); | |||
211 | if (d != NULL((void*)0)) { | |||
212 | llog_diag(RC_LOG_SERIOUS, ike->sa.st_logger, &d, "%s", ""); | |||
213 | return empty_pbs; | |||
214 | } | |||
215 | if (impair.add_unknown_v2_payload_to == exchange_type && | |||
216 | !emit_v2UNKNOWN("request", exchange_type, &body)) { | |||
217 | return empty_pbs; | |||
218 | } | |||
219 | ||||
220 | return body; | |||
221 | } | |||
222 | ||||
223 | /* | |||
224 | * This code assumes that the encrypted part of an IKE message starts | |||
225 | * with an Initialization Vector (IV) of enc_blocksize of random | |||
226 | * octets. The IV will subsequently be discarded after decryption. | |||
227 | * This is true of Cipher Block Chaining mode (CBC). | |||
228 | */ | |||
229 | static bool_Bool emit_v2SK_iv(struct v2SK_payload *sk) | |||
230 | { | |||
231 | /* compute location/size */ | |||
232 | sk->iv = chunk2(sk->pbs.cur, sk->ike->sa.st_oakley.ta_encrypt->wire_iv_size); | |||
233 | /* make space */ | |||
234 | diag_t d = pbs_out_zero(&sk->pbs, sk->iv.len, "IV"); | |||
235 | if (d != NULL((void*)0)) { | |||
236 | llog_diag(RC_LOG_SERIOUS, sk->logger, &d, "%s", ""); | |||
237 | return false0; | |||
238 | } | |||
239 | /* scribble on it */ | |||
240 | fill_rnd_chunk(sk->iv); | |||
241 | return true1; | |||
242 | } | |||
243 | ||||
244 | struct v2SK_payload open_v2SK_payload(struct logger *logger, | |||
245 | struct pbs_outpacket_byte_stream *container, | |||
246 | struct ike_sa *ike) | |||
247 | { | |||
248 | static const struct v2SK_payload empty_sk; | |||
249 | struct v2SK_payload sk = { | |||
250 | .logger = logger, | |||
251 | .ike = ike, | |||
252 | .payload = { | |||
253 | .ptr = container->cur, | |||
254 | .len = 0, /* computed at end; set here to silence GCC 6.10 */ | |||
255 | } | |||
256 | }; | |||
257 | ||||
258 | /* emit Encryption Payload header */ | |||
259 | ||||
260 | struct ikev2_generic e = { | |||
261 | .isag_length = 0, /* filled in later */ | |||
262 | .isag_critical = build_ikev2_critical(false0, ike->sa.st_logger), | |||
263 | }; | |||
264 | if (!out_struct(&e, &ikev2_sk_desc, container, &sk.pbs)) { | |||
265 | llog(RC_LOG, logger, | |||
266 | "error initializing SK header for encrypted %s message", | |||
267 | container->name); | |||
268 | return empty_sk; | |||
269 | } | |||
270 | ||||
271 | /* emit IV and save location */ | |||
272 | ||||
273 | if (!emit_v2SK_iv(&sk)) { | |||
274 | llog(RC_LOG, logger, | |||
275 | "error initializing IV for encrypted %s message", | |||
276 | container->name); | |||
277 | return empty_sk; | |||
278 | } | |||
279 | ||||
280 | /* save cleartext start */ | |||
281 | ||||
282 | sk.cleartext.ptr = sk.pbs.cur; | |||
283 | passert(sk.iv.ptr <= sk.cleartext.ptr)({ _Bool assertion__ = sk.iv.ptr <= sk.cleartext.ptr; if ( !assertion__) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2_message.c" , .line = 283, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_passert(logger_, here, "%s", "sk.iv.ptr <= sk.cleartext.ptr" ); } (void) 1; }); | |||
284 | /* XXX: coverity thinks .container (set to E by out_struct() above) can be NULL. */ | |||
285 | passert(sk.pbs.container != NULL && sk.pbs.container->name == container->name)({ _Bool assertion__ = sk.pbs.container != ((void*)0) && sk.pbs.container->name == container->name; if (!assertion__ ) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2_message.c", .line = 285, }; &here; }); const struct logger *logger_ = &failsafe_logger ; llog_passert(logger_, here, "%s", "sk.pbs.container != ((void*)0) && sk.pbs.container->name == container->name" ); } (void) 1; }); | |||
286 | ||||
287 | return sk; | |||
288 | } | |||
289 | ||||
290 | bool_Bool close_v2SK_payload(struct v2SK_payload *sk) | |||
291 | { | |||
292 | /* save cleartext end */ | |||
293 | ||||
294 | sk->cleartext.len = sk->pbs.cur - sk->cleartext.ptr; | |||
295 | ||||
296 | /* emit padding + pad-length */ | |||
297 | ||||
298 | size_t padding; | |||
299 | if (sk->ike->sa.st_oakley.ta_encrypt->pad_to_blocksize) { | |||
300 | const size_t blocksize = sk->ike->sa.st_oakley.ta_encrypt->enc_blocksize; | |||
301 | padding = pad_up(sk->pbs.cur - sk->cleartext.ptr, blocksize)(((blocksize) - 1) - (((sk->pbs.cur - sk->cleartext.ptr ) + (blocksize) - 1) % (blocksize))); | |||
302 | if (padding == 0) { | |||
303 | padding = blocksize; | |||
304 | } | |||
305 | } else { | |||
306 | padding = 1; | |||
307 | } | |||
308 | 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); } } | |||
309 | padding){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("adding %zd bytes of padding (including 1 byte padding-length)" , padding); } }; | |||
310 | for (unsigned i = 0; i < padding; i++) { | |||
311 | diag_t d = pbs_out_repeated_byte(&sk->pbs, i, 1, "padding and length"); | |||
312 | if (d != NULL((void*)0)) { | |||
313 | llog_diag(RC_LOG_SERIOUS, sk->logger, &d, | |||
314 | "error initializing padding for encrypted %s payload: ", | |||
315 | sk->pbs.container->name); | |||
316 | return false0; | |||
317 | } | |||
318 | } | |||
319 | ||||
320 | /* emit space for integrity checksum data; save location */ | |||
321 | ||||
322 | size_t integ_size = (encrypt_desc_is_aead(sk->ike->sa.st_oakley.ta_encrypt) | |||
323 | ? sk->ike->sa.st_oakley.ta_encrypt->aead_tag_size | |||
324 | : sk->ike->sa.st_oakley.ta_integ->integ_output_size); | |||
325 | if (integ_size == 0) { | |||
326 | pexpect_failllog_pexpect(sk->logger, HERE({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2_message.c", .line = 326, }; &here ; }), | |||
327 | "error initializing integrity checksum for encrypted %s payload", | |||
328 | sk->pbs.container->name); | |||
329 | return false0; | |||
330 | } | |||
331 | sk->integrity = chunk2(sk->pbs.cur, integ_size); | |||
332 | diag_t d = pbs_out_zero(&sk->pbs, integ_size, "length of truncated HMAC/KEY"); | |||
333 | if (d != NULL((void*)0)) { | |||
334 | llog_diag(RC_LOG_SERIOUS, sk->logger, &d, "%s", ""); | |||
335 | return false0; | |||
336 | } | |||
337 | ||||
338 | /* close the SK payload */ | |||
339 | ||||
340 | sk->payload.len = sk->pbs.cur - sk->payload.ptr; | |||
341 | close_output_pbs(&sk->pbs); | |||
342 | ||||
343 | return true1; | |||
344 | } | |||
345 | ||||
346 | /* | |||
347 | * Form the encryption IV (a.k.a. starting variable) from the salt | |||
348 | * (a.k.a. nonce) wire-iv and a counter set to 1. | |||
349 | * | |||
350 | * note: no iv is longer than MAX_CBC_BLOCK_SIZE | |||
351 | */ | |||
352 | static void construct_enc_iv(const char *name, | |||
353 | uint8_t enc_iv[], | |||
354 | uint8_t *wire_iv, chunk_t salt, | |||
355 | const struct encrypt_desc *encrypter) | |||
356 | { | |||
357 | DBGF(DBG_CRYPT, "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); } } | |||
358 | 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); } } | |||
359 | 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); } }; | |||
360 | passert(salt.len == encrypter->salt_size)({ _Bool assertion__ = salt.len == encrypter->salt_size; if (!assertion__) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2_message.c" , .line = 360, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_passert(logger_, here, "%s", "salt.len == encrypter->salt_size" ); } (void) 1; }); | |||
361 | passert(encrypter->enc_blocksize <= MAX_CBC_BLOCK_SIZE)({ _Bool assertion__ = encrypter->enc_blocksize <= (((128 ) + 8 - 1) / 8); if (!assertion__) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2_message.c" , .line = 361, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_passert(logger_, here, "%s", "encrypter->enc_blocksize <= (((128) + 8 - 1) / 8)" ); } (void) 1; }); | |||
362 | 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__ ) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2_message.c", .line = 362, }; &here; }); const struct logger *logger_ = &failsafe_logger ; llog_passert(logger_, here, "%s", "encrypter->enc_blocksize >= encrypter->salt_size + encrypter->wire_iv_size" ); } (void) 1; }); | |||
363 | size_t counter_size = encrypter->enc_blocksize - encrypter->salt_size - encrypter->wire_iv_size; | |||
364 | DBGF(DBG_CRYPT, "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); } } | |||
365 | 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); } }; | |||
366 | ||||
367 | memcpy(enc_iv, salt.ptr, salt.len); | |||
368 | memcpy(enc_iv + salt.len, wire_iv, encrypter->wire_iv_size); | |||
369 | if (counter_size > 0) { | |||
370 | memset(enc_iv + encrypter->enc_blocksize - counter_size, 0, | |||
371 | counter_size - 1); | |||
372 | enc_iv[encrypter->enc_blocksize - 1] = 1; | |||
373 | } | |||
374 | if (DBGP(DBG_CRYPT)(cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX))))) { | |||
375 | DBG_dump(name, enc_iv, encrypter->enc_blocksize); | |||
376 | } | |||
377 | } | |||
378 | ||||
379 | /* | |||
380 | * Without this the code makes little sense. | |||
381 | * https://datatracker.ietf.org/doc/draft-ietf-ipsecme-ikev2-intermediate/?include_text=1 | |||
382 | * | |||
383 | * 1 2 3 | |||
384 | * 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 | |||
385 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ^ ^ | |||
386 | * | IKE SA Initiator's SPI | | | | |||
387 | * | | | | | |||
388 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ I | | |||
389 | * | IKE SA Responder's SPI | K | | |||
390 | * | | E | | |||
391 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | |||
392 | * | Next Payload | MjVer | MnVer | Exchange Type | Flags | H | | |||
393 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ d | | |||
394 | * | Message ID | r A | |||
395 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | |||
396 | * | Adjusted Length | | | | |||
397 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ v | | |||
398 | * | | | | |||
399 | * ~ Unencrypted payloads (if any) ~ | | |||
400 | * | | | | |||
401 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ^ | | |||
402 | * | Next Payload |C| RESERVED | Adjusted Payload Length | | | | |||
403 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ E v | |||
404 | * | Initialization Vector | n | |||
405 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ c ^ | |||
406 | * | | r | | |||
407 | * ~ Inner payloads (not yet encrypted) ~ P | |||
408 | * | | P | | |||
409 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ l v | |||
410 | * | Padding (0-255 octets) | Pad Length | d | |||
411 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | |||
412 | * ~ Integrity Checksum Data ~ | | |||
413 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ v | |||
414 | * | |||
415 | * Figure 1: Data to Authenticate in the IKE_INTERMEDIATE Exchange | |||
416 | * Messages | |||
417 | * | |||
418 | * Figure 1 illustrates the layout of the IntAuth_*_[I/R]_P (denoted as | |||
419 | * P) and the IntAuth_*_[I/R]_A (denoted as A) chunks in case the | |||
420 | * Encrypted payload is not empty. | |||
421 | */ | |||
422 | ||||
423 | static void compute_intermediate_mac(struct ike_sa *ike, | |||
424 | PK11SymKey *intermediate_key, | |||
425 | const uint8_t *auth_start, chunk_t plain, | |||
426 | chunk_t *out) | |||
427 | { | |||
428 | /* | |||
429 | * Define variables that match the naming scheme used by the | |||
430 | * RFC's ASCII diagram above. | |||
431 | */ | |||
432 | const uint8_t *header_start = auth_start; | |||
433 | size_t header_size = NSIZEOF_isakmp_hdr28; | |||
434 | const uint8_t *unencrypted_payload_start = header_start + header_size; | |||
435 | size_t unencrypted_payload_size = (plain.ptr | |||
436 | - ike->sa.st_oakley.ta_encrypt->wire_iv_size | |||
437 | - SK_HEADER_SIZE4 | |||
438 | - unencrypted_payload_start); | |||
439 | const uint8_t *sk_header_start = (unencrypted_payload_start + unencrypted_payload_size); | |||
440 | size_t sk_header_size = SK_HEADER_SIZE4; | |||
441 | /* skip the IV */ | |||
442 | const uint8_t *inner_payloads_start = plain.ptr; | |||
443 | size_t inner_payloads_size = plain.len; | |||
444 | /* compute the PRF over "A" + "P" */ | |||
445 | struct crypt_prf *prf = crypt_prf_init_symkey("prf(IntAuth_*_A [| IntAuth_*_P])", | |||
446 | ike->sa.st_oakley.ta_prf, | |||
447 | "SK_p", intermediate_key, | |||
448 | ike->sa.st_logger); | |||
449 | /* | |||
450 | * Hash IntAuth_*_[I/R]_A. | |||
451 | */ | |||
452 | ||||
453 | /* Header, stooping before Adjusted Length field. */ | |||
454 | crypt_prf_update_bytes(prf, "IKE Header short of Adjusted Length", | |||
455 | header_start, header_size - ADJ_LENGTH_SIZE4); | |||
456 | /* Adjusted length; in network byte order */ | |||
457 | size_t adjusted_length = (header_size | |||
458 | + unencrypted_payload_size | |||
459 | + sk_header_size | |||
460 | + inner_payloads_size); | |||
461 | DBG(DBG_CRYPT, DBG_log("adjusted length: %zu", adjusted_length)){ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { DBG_log("adjusted length: %zu", adjusted_length); } }; | |||
462 | uint8_t adjusted_length_bytes[ADJ_LENGTH_SIZE4]; | |||
463 | hton_bytes(adjusted_length, adjusted_length_bytes, | |||
464 | sizeof(adjusted_length_bytes)); | |||
465 | crypt_prf_update_thing(prf, "Adjusted Length",crypt_prf_update_bytes(prf, "Adjusted Length", &(adjusted_length_bytes ), sizeof(adjusted_length_bytes)) | |||
466 | adjusted_length_bytes)crypt_prf_update_bytes(prf, "Adjusted Length", &(adjusted_length_bytes ), sizeof(adjusted_length_bytes)); | |||
467 | /* Unencrypted payload */ | |||
468 | crypt_prf_update_bytes(prf, "Unencrypted payloads (if any)", | |||
469 | unencrypted_payload_start, unencrypted_payload_size); | |||
470 | /* sk header, stooping before adjusted payload length */ | |||
471 | crypt_prf_update_bytes(prf, "SK Header short of Adjusted Payload Length", | |||
472 | sk_header_start, sk_header_size - ADJ_PAYLOAD_LENGTH_SIZE2); | |||
473 | /* adjusted payload length, in network byte order */ | |||
474 | size_t adjusted_payload_length = inner_payloads_size + SK_HEADER_SIZE4; | |||
475 | DBG(DBG_CRYPT, DBG_log("adjusted payload length: %zu", adjusted_payload_length)){ if ((cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX ))))) { DBG_log("adjusted payload length: %zu", adjusted_payload_length ); } }; | |||
476 | uint8_t adjusted_payload_length_bytes[ADJ_PAYLOAD_LENGTH_SIZE2]; | |||
477 | hton_bytes(adjusted_payload_length, adjusted_payload_length_bytes, | |||
478 | sizeof(adjusted_payload_length_bytes)); | |||
479 | crypt_prf_update_thing(prf, "Adjusted Payload Length",crypt_prf_update_bytes(prf, "Adjusted Payload Length", &( adjusted_payload_length_bytes), sizeof(adjusted_payload_length_bytes )) | |||
480 | adjusted_payload_length_bytes)crypt_prf_update_bytes(prf, "Adjusted Payload Length", &( adjusted_payload_length_bytes), sizeof(adjusted_payload_length_bytes )); | |||
481 | ||||
482 | /* | |||
483 | * IntAuth_*_[I/R]_P aka inner payload. | |||
484 | */ | |||
485 | crypt_prf_update_bytes(prf, "Inner payloads (decrypted)", | |||
486 | inner_payloads_start, inner_payloads_size); | |||
487 | ||||
488 | /* extract the mac */ | |||
489 | struct crypt_mac mac = crypt_prf_final_mac(&prf, NULL((void*)0)/*no-truncation*/); | |||
490 | *out = clone_hunk(mac, "IntAuth")({ typeof(mac) hunk_ = mac; clone_bytes_as_chunk(hunk_.ptr, hunk_ .len, "IntAuth"); }); | |||
491 | } | |||
492 | ||||
493 | stf_status encrypt_v2SK_payload(struct v2SK_payload *sk) | |||
494 | { | |||
495 | struct ike_sa *ike = sk->ike; | |||
496 | uint8_t *auth_start = sk->pbs.container->start; | |||
497 | uint8_t *wire_iv_start = sk->iv.ptr; | |||
498 | uint8_t *enc_start = sk->cleartext.ptr; | |||
499 | uint8_t *integ_start = sk->integrity.ptr; | |||
500 | size_t integ_size = sk->integrity.len; | |||
501 | uint8_t exchange_type = *(auth_start + EXCH_TYPE_OFFSET18); | |||
502 | ||||
503 | passert(auth_start <= wire_iv_start)({ _Bool assertion__ = auth_start <= wire_iv_start; if (!assertion__ ) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2_message.c", .line = 503, }; &here; }); const struct logger *logger_ = &failsafe_logger ; llog_passert(logger_, here, "%s", "auth_start <= wire_iv_start" ); } (void) 1; }); | |||
504 | passert(wire_iv_start <= enc_start)({ _Bool assertion__ = wire_iv_start <= enc_start; if (!assertion__ ) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2_message.c", .line = 504, }; &here; }); const struct logger *logger_ = &failsafe_logger ; llog_passert(logger_, here, "%s", "wire_iv_start <= enc_start" ); } (void) 1; }); | |||
505 | passert(enc_start <= integ_start)({ _Bool assertion__ = enc_start <= integ_start; if (!assertion__ ) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2_message.c", .line = 505, }; &here; }); const struct logger *logger_ = &failsafe_logger ; llog_passert(logger_, here, "%s", "enc_start <= integ_start" ); } (void) 1; }); | |||
506 | ||||
507 | chunk_t salt; | |||
508 | PK11SymKey *cipherkey; | |||
509 | PK11SymKey *authkey; | |||
510 | PK11SymKey *intermediate_key; | |||
511 | /* encrypt with our end's key */ | |||
512 | switch (ike->sa.st_sa_role) { | |||
513 | case SA_INITIATOR: | |||
514 | cipherkey = ike->sa.st_skey_ei_nss; | |||
515 | authkey = ike->sa.st_skey_ai_nss; | |||
516 | salt = ike->sa.st_skey_initiator_salt; | |||
517 | intermediate_key = ike->sa.st_skey_pi_nss; | |||
518 | break; | |||
519 | case SA_RESPONDER: | |||
520 | cipherkey = ike->sa.st_skey_er_nss; | |||
521 | authkey = ike->sa.st_skey_ar_nss; | |||
522 | salt = ike->sa.st_skey_responder_salt; | |||
523 | intermediate_key = ike->sa.st_skey_pr_nss; | |||
524 | break; | |||
525 | default: | |||
526 | bad_case(ike->sa.st_sa_role)libreswan_bad_case("ike->sa.st_sa_role", (ike->sa.st_sa_role ), ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2_message.c", .line = 526, }; &here ; })); | |||
527 | } | |||
528 | ||||
529 | /* size of plain or cipher text. */ | |||
530 | size_t enc_size = integ_start - enc_start; | |||
531 | ||||
532 | /* | |||
533 | * For Intermediate Exchange, apply PRF to the peer's messages | |||
534 | * and store in state for further authentication. | |||
535 | */ | |||
536 | if (exchange_type == ISAKMP_v2_IKE_INTERMEDIATE) { | |||
537 | compute_intermediate_mac(ike, intermediate_key, | |||
538 | auth_start, | |||
539 | sk->cleartext /* inner payloads */, | |||
540 | &ike->sa.st_intermediate_packet_me); | |||
541 | } | |||
542 | ||||
543 | /* encrypt and authenticate the block */ | |||
544 | if (encrypt_desc_is_aead(ike->sa.st_oakley.ta_encrypt)) { | |||
545 | /* | |||
546 | * Additional Authenticated Data - AAD - size. | |||
547 | * RFC5282 says: The Initialization Vector and Ciphertext | |||
548 | * fields [...] MUST NOT be included in the associated | |||
549 | * data. | |||
550 | */ | |||
551 | size_t wire_iv_size = ike->sa.st_oakley.ta_encrypt->wire_iv_size; | |||
552 | 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__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2_message.c" , .line = 552, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect(logger_, here_, "%s", "integ_size == ike->sa.st_oakley.ta_encrypt->aead_tag_size" ); } assertion__; }); | |||
553 | unsigned char *aad_start = auth_start; | |||
554 | size_t aad_size = enc_start - aad_start - wire_iv_size; | |||
555 | ||||
556 | /* now, encrypt */ | |||
557 | if (DBGP(DBG_CRYPT)(cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX))))) { | |||
558 | DBG_dump_hunk("Salt before authenticated encryption:", salt){ typeof(salt) hunk_ = salt; DBG_dump("Salt before authenticated encryption:" , hunk_.ptr, hunk_.len); }; | |||
559 | DBG_dump("IV before authenticated encryption:", | |||
560 | wire_iv_start, wire_iv_size); | |||
561 | DBG_dump("AAD before authenticated encryption:", | |||
562 | aad_start, aad_size); | |||
563 | DBG_dump("data before authenticated encryption:", | |||
564 | enc_start, enc_size); | |||
565 | DBG_dump("integ before authenticated encryption:", | |||
566 | integ_start, integ_size); | |||
567 | } | |||
568 | ||||
569 | if (!ike->sa.st_oakley.ta_encrypt->encrypt_ops | |||
570 | ->do_aead(ike->sa.st_oakley.ta_encrypt, | |||
571 | salt.ptr, salt.len, | |||
572 | wire_iv_start, wire_iv_size, | |||
573 | aad_start, aad_size, | |||
574 | enc_start, enc_size, integ_size, | |||
575 | cipherkey, true1, sk->logger)) { | |||
576 | return STF_FAIL; | |||
577 | } | |||
578 | ||||
579 | if (DBGP(DBG_CRYPT)(cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX))))) { | |||
580 | DBG_dump("data after authenticated encryption:", | |||
581 | enc_start, enc_size); | |||
582 | DBG_dump("integ after authenticated encryption:", | |||
583 | integ_start, integ_size); | |||
584 | } | |||
585 | ||||
586 | } else { | |||
587 | /* note: no iv is longer than MAX_CBC_BLOCK_SIZE */ | |||
588 | unsigned char enc_iv[MAX_CBC_BLOCK_SIZE(((128) + 8 - 1) / 8)]; | |||
589 | construct_enc_iv("encryption IV/starting-variable", enc_iv, | |||
590 | wire_iv_start, salt, | |||
591 | ike->sa.st_oakley.ta_encrypt); | |||
592 | ||||
593 | /* now, encrypt */ | |||
594 | if (DBGP(DBG_CRYPT)(cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX))))) { | |||
595 | DBG_dump("data before encryption:", enc_start, enc_size); | |||
596 | } | |||
597 | ||||
598 | ike->sa.st_oakley.ta_encrypt->encrypt_ops | |||
599 | ->do_crypt(ike->sa.st_oakley.ta_encrypt, | |||
600 | enc_start, enc_size, | |||
601 | cipherkey, | |||
602 | enc_iv, true1, | |||
603 | sk->logger); | |||
604 | ||||
605 | if (DBGP(DBG_CRYPT)(cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX))))) { | |||
606 | DBG_dump("data after encryption:", enc_start, enc_size); | |||
607 | } | |||
608 | ||||
609 | /* note: saved_iv's updated value is discarded */ | |||
610 | ||||
611 | /* okay, authenticate from beginning of IV */ | |||
612 | struct crypt_prf *ctx = crypt_prf_init_symkey("integ", ike->sa.st_oakley.ta_integ->prf, | |||
613 | "authkey", authkey, sk->logger); | |||
614 | crypt_prf_update_bytes(ctx, "message", auth_start, integ_start - auth_start); | |||
615 | 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__) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2_message.c", .line = 615, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_passert (logger_, here, "%s", "integ_size == ike->sa.st_oakley.ta_integ->integ_output_size" ); } (void) 1; }); | |||
616 | struct crypt_mac mac = crypt_prf_final_mac(&ctx, ike->sa.st_oakley.ta_integ); | |||
617 | memcpy_hunk(integ_start, mac, integ_size)({ const typeof(mac) hunk_ = mac; ({ _Bool assertion__ = hunk_ .len == integ_size; if (!assertion__) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2_message.c" , .line = 617, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_passert(logger_, here, "%s", "hunk_.len == integ_size" ); } (void) 1; }); memcpy(integ_start, hunk_.ptr, integ_size) ; }); | |||
618 | ||||
619 | if (DBGP(DBG_CRYPT)(cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX))))) { | |||
620 | DBG_dump("data being hmac:", auth_start, | |||
621 | integ_start - auth_start); | |||
622 | DBG_dump("out calculated auth:", integ_start, integ_size); | |||
623 | } | |||
624 | } | |||
625 | ||||
626 | return STF_OK; | |||
627 | } | |||
628 | ||||
629 | /* | |||
630 | * ikev2_decrypt_msg: decode the payload. | |||
631 | * The result is stored in-place. | |||
632 | * Calls ikev2_process_payloads to decode the payloads within. | |||
633 | * | |||
634 | * This code assumes that the encrypted part of an IKE message starts | |||
635 | * with an Initialization Vector (IV) of WIRE_IV_SIZE random octets. | |||
636 | * We will discard the IV after decryption. | |||
637 | * | |||
638 | * The (optional) salt, wire-iv, and (optional) 1 are combined to form | |||
639 | * the actual starting-variable (a.k.a. IV). | |||
640 | */ | |||
641 | ||||
642 | static bool_Bool ikev2_verify_and_decrypt_sk_payload(struct ike_sa *ike, | |||
643 | struct msg_digest *md, | |||
644 | chunk_t text, | |||
645 | chunk_t *plain, | |||
646 | size_t iv_offset) | |||
647 | { | |||
648 | if (!ike->sa.hidden_variables.st_skeyid_calculated) { | |||
649 | endpoint_buf b; | |||
650 | pexpect_failllog_pexpect(ike->sa.st_logger, HERE({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2_message.c", .line = 650, }; &here ; }), | |||
651 | "received encrypted packet from %s but no exponents for state #%lu to decrypt it", | |||
652 | str_endpoint(&md->sender, &b), | |||
653 | ike->sa.st_serialno); | |||
654 | return false0; | |||
655 | } | |||
656 | ||||
657 | uint8_t *wire_iv_start = text.ptr + iv_offset; | |||
658 | size_t wire_iv_size = ike->sa.st_oakley.ta_encrypt->wire_iv_size; | |||
659 | size_t integ_size = (encrypt_desc_is_aead(ike->sa.st_oakley.ta_encrypt) | |||
660 | ? ike->sa.st_oakley.ta_encrypt->aead_tag_size | |||
661 | : ike->sa.st_oakley.ta_integ->integ_output_size); | |||
662 | ||||
663 | /* | |||
664 | * check to see if length is plausible: | |||
665 | * - wire-IV | |||
666 | * - encoded data (possibly empty) | |||
667 | * - at least one padding-length byte | |||
668 | * - truncated integrity digest / tag | |||
669 | */ | |||
670 | uint8_t *payload_end = text.ptr + text.len; | |||
671 | if (payload_end < (wire_iv_start + wire_iv_size + 1 + integ_size)) { | |||
672 | log_state(RC_LOG, &ike->sa, | |||
673 | "encrypted payload impossibly short (%tu)", | |||
674 | payload_end - wire_iv_start); | |||
675 | return false0; | |||
676 | } | |||
677 | ||||
678 | uint8_t *auth_start = text.ptr; | |||
679 | uint8_t *enc_start = wire_iv_start + wire_iv_size; | |||
680 | uint8_t *integ_start = payload_end - integ_size; | |||
681 | size_t enc_size = integ_start - enc_start; | |||
682 | uint8_t exchange_type = *(auth_start + EXCH_TYPE_OFFSET18); | |||
683 | ||||
684 | /* | |||
685 | * Check that the payload is block-size aligned. | |||
686 | * | |||
687 | * Per rfc7296 "the recipient MUST accept any length that | |||
688 | * results in proper alignment". | |||
689 | * | |||
690 | * Do this before the payload's integrity has been verified as | |||
691 | * block-alignment requirements aren't exactly secret | |||
692 | * (originally this was being done between integrity and | |||
693 | * decrypt). | |||
694 | */ | |||
695 | size_t enc_blocksize = ike->sa.st_oakley.ta_encrypt->enc_blocksize; | |||
696 | bool_Bool pad_to_blocksize = ike->sa.st_oakley.ta_encrypt->pad_to_blocksize; | |||
697 | if (pad_to_blocksize) { | |||
698 | if (enc_size % enc_blocksize != 0) { | |||
699 | log_state(RC_LOG, &ike->sa, | |||
700 | "discarding invalid packet: %zu octet payload length is not a multiple of encryption block-size (%zu)", | |||
701 | enc_size, enc_blocksize); | |||
702 | return false0; | |||
703 | } | |||
704 | } | |||
705 | ||||
706 | chunk_t salt; | |||
707 | PK11SymKey *cipherkey; | |||
708 | PK11SymKey *authkey; | |||
709 | PK11SymKey *intermediate_key; | |||
710 | switch (ike->sa.st_sa_role) { | |||
711 | case SA_INITIATOR: | |||
712 | /* need responders key */ | |||
713 | cipherkey = ike->sa.st_skey_er_nss; | |||
714 | authkey = ike->sa.st_skey_ar_nss; | |||
715 | salt = ike->sa.st_skey_responder_salt; | |||
716 | intermediate_key = ike->sa.st_skey_pr_nss; | |||
717 | break; | |||
718 | case SA_RESPONDER: | |||
719 | /* need initiators key */ | |||
720 | cipherkey = ike->sa.st_skey_ei_nss; | |||
721 | authkey = ike->sa.st_skey_ai_nss; | |||
722 | salt = ike->sa.st_skey_initiator_salt; | |||
723 | intermediate_key = ike->sa.st_skey_pi_nss; | |||
724 | break; | |||
725 | default: | |||
726 | bad_case(ike->sa.st_sa_role)libreswan_bad_case("ike->sa.st_sa_role", (ike->sa.st_sa_role ), ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2_message.c", .line = 726, }; &here ; })); | |||
727 | } | |||
728 | ||||
729 | /* authenticate and decrypt the block. */ | |||
730 | if (encrypt_desc_is_aead(ike->sa.st_oakley.ta_encrypt)) { | |||
731 | /* | |||
732 | * Additional Authenticated Data - AAD - size. | |||
733 | * RFC5282 says: The Initialization Vector and Ciphertext | |||
734 | * fields [...] MUST NOT be included in the associated | |||
735 | * data. | |||
736 | */ | |||
737 | unsigned char *aad_start = auth_start; | |||
738 | size_t aad_size = enc_start - auth_start - wire_iv_size; | |||
739 | ||||
740 | /* decrypt */ | |||
741 | if (DBGP(DBG_CRYPT)(cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX))))) { | |||
742 | DBG_dump_hunk("Salt before authenticated decryption:", salt){ typeof(salt) hunk_ = salt; DBG_dump("Salt before authenticated decryption:" , hunk_.ptr, hunk_.len); }; | |||
743 | DBG_dump("IV before authenticated decryption:", | |||
744 | wire_iv_start, wire_iv_size); | |||
745 | DBG_dump("AAD before authenticated decryption:", | |||
746 | aad_start, aad_size); | |||
747 | DBG_dump("data before authenticated decryption:", | |||
748 | enc_start, enc_size); | |||
749 | DBG_dump("integ before authenticated decryption:", | |||
750 | integ_start, integ_size); | |||
751 | } | |||
752 | ||||
753 | if (!ike->sa.st_oakley.ta_encrypt->encrypt_ops | |||
754 | ->do_aead(ike->sa.st_oakley.ta_encrypt, | |||
755 | salt.ptr, salt.len, | |||
756 | wire_iv_start, wire_iv_size, | |||
757 | aad_start, aad_size, | |||
758 | enc_start, enc_size, integ_size, | |||
759 | cipherkey, false0, ike->sa.st_logger)) { | |||
760 | return false0; | |||
761 | } | |||
762 | ||||
763 | if (DBGP(DBG_CRYPT)(cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX))))) { | |||
764 | DBG_dump("data after authenticated decryption:", | |||
765 | enc_start, enc_size + integ_size); | |||
766 | } | |||
767 | ||||
768 | } else { | |||
769 | /* | |||
770 | * check authenticator. The last INTEG_SIZE bytes are | |||
771 | * the truncated digest. | |||
772 | */ | |||
773 | struct crypt_prf *ctx = crypt_prf_init_symkey("auth", ike->sa.st_oakley.ta_integ->prf, | |||
774 | "authkey", authkey, ike->sa.st_logger); | |||
775 | crypt_prf_update_bytes(ctx, "message", auth_start, integ_start - auth_start); | |||
776 | struct crypt_mac td = crypt_prf_final_mac(&ctx, ike->sa.st_oakley.ta_integ); | |||
777 | ||||
778 | 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_); })) { | |||
779 | log_state(RC_LOG, &ike->sa, "failed to match authenticator"); | |||
780 | return false0; | |||
781 | } | |||
782 | ||||
783 | dbg("authenticator matched"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("authenticator matched"); } }; | |||
784 | ||||
785 | /* note: no iv is longer than MAX_CBC_BLOCK_SIZE */ | |||
786 | unsigned char enc_iv[MAX_CBC_BLOCK_SIZE(((128) + 8 - 1) / 8)]; | |||
787 | construct_enc_iv("decryption IV/starting-variable", enc_iv, | |||
788 | wire_iv_start, salt, | |||
789 | ike->sa.st_oakley.ta_encrypt); | |||
790 | ||||
791 | /* decrypt */ | |||
792 | if (DBGP(DBG_CRYPT)(cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX))))) { | |||
793 | DBG_dump("payload before decryption:", enc_start, enc_size); | |||
794 | } | |||
795 | ||||
796 | ike->sa.st_oakley.ta_encrypt->encrypt_ops | |||
797 | ->do_crypt(ike->sa.st_oakley.ta_encrypt, | |||
798 | enc_start, enc_size, | |||
799 | cipherkey, | |||
800 | enc_iv, false0, | |||
801 | ike->sa.st_logger); | |||
802 | ||||
803 | if (DBGP(DBG_CRYPT)(cur_debugging & (((lset_t)1 << (DBG_CRYPT_IX))))) { | |||
804 | DBG_dump("payload after decryption:", enc_start, enc_size); | |||
805 | } | |||
806 | } | |||
807 | ||||
808 | /* | |||
809 | * Check the padding. | |||
810 | * | |||
811 | * Per rfc7296 "The sender SHOULD set the Pad Length to the | |||
812 | * minimum value that makes the combination of the payloads, | |||
813 | * the Padding, and the Pad Length a multiple of the block | |||
814 | * size, but the recipient MUST accept any length that results | |||
815 | * in proper alignment." | |||
816 | * | |||
817 | * Notice the "should". RACOON, for instance, sends extra | |||
818 | * blocks of padding that contain random bytes. | |||
819 | */ | |||
820 | uint8_t padlen = enc_start[enc_size - 1] + 1; | |||
821 | if (padlen > enc_size) { | |||
822 | log_state(RC_LOG, &ike->sa, | |||
823 | "discarding invalid packet: padding-length %u (octet 0x%02x) is larger than %zu octet payload length", | |||
824 | padlen, padlen - 1, enc_size); | |||
825 | return false0; | |||
826 | } | |||
827 | if (pad_to_blocksize) { | |||
828 | if (padlen > enc_blocksize) { | |||
829 | /* probably racoon */ | |||
830 | dbg("payload contains %zu blocks of extra padding (padding-length: %d (octet 0x%2x), encryption block-size: %zu)",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_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 ); } } | |||
831 | (padlen - 1) / enc_blocksize,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_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 ); } } | |||
832 | padlen, padlen - 1, enc_blocksize){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_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 ); } }; | |||
833 | } | |||
834 | } else { | |||
835 | if (padlen > 1) { | |||
836 | dbg("payload contains %u octets of extra padding (padding-length: %u (octet 0x%2x))",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("payload contains %u octets of extra padding (padding-length: %u (octet 0x%2x))" , padlen - 1, padlen, padlen - 1); } } | |||
837 | padlen - 1, padlen, padlen - 1){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("payload contains %u octets of extra padding (padding-length: %u (octet 0x%2x))" , padlen - 1, padlen, padlen - 1); } }; | |||
838 | } | |||
839 | } | |||
840 | ||||
841 | /* | |||
842 | * Don't check the contents of the pad octets; racoon, for | |||
843 | * instance, sets them to random values. | |||
844 | */ | |||
845 | dbg("stripping %u octets as pad", padlen){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("stripping %u octets as pad", padlen); } }; | |||
846 | *plain = chunk2(enc_start, enc_size - padlen); | |||
847 | ||||
848 | /* | |||
849 | * Now that the payload has been decrypted, perform the | |||
850 | * intermediate exchange calculation. | |||
851 | * | |||
852 | * For Intermediate Exchange, apply PRF to the peer's messages | |||
853 | * and store in state for further authentication. | |||
854 | */ | |||
855 | if (exchange_type == ISAKMP_v2_IKE_INTERMEDIATE) { | |||
856 | compute_intermediate_mac(ike, intermediate_key, | |||
857 | auth_start, *plain, | |||
858 | &ike->sa.st_intermediate_packet_peer); | |||
859 | } | |||
860 | return true1; | |||
861 | } | |||
862 | ||||
863 | /* | |||
864 | * The IKE SA is responsible for fragments; which means this code can | |||
865 | * only handle a message window size of one. | |||
866 | * | |||
867 | * (the message may contain a delete, but that delete could contain | |||
868 | * multiple CHILD SAs so the assumption that the child could hold the | |||
869 | * fragments was flawed). | |||
870 | */ | |||
871 | ||||
872 | static bool_Bool ikev2_check_fragment(struct msg_digest *md, struct ike_sa *ike) | |||
873 | { | |||
874 | struct v2_incoming_fragments **frags = &ike->sa.st_v2_incoming[v2_msg_role(md)]; | |||
875 | struct ikev2_skf *skf = &md->chain[ISAKMP_NEXT_v2SKF]->payload.v2skf; | |||
876 | ||||
877 | /* ??? CLANG 3.5 thinks st might be NULL */ | |||
878 | if (!(ike->sa.st_connection->policy & POLICY_IKE_FRAG_ALLOW((lset_t)1 << (POLICY_IKE_FRAG_ALLOW_IX)))) { | |||
879 | dbg("discarding IKE encrypted fragment - fragmentation not allowed by local policy (ike_frag=no)"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("discarding IKE encrypted fragment - fragmentation not allowed by local policy (ike_frag=no)" ); } }; | |||
880 | return false0; | |||
881 | } | |||
882 | ||||
883 | if (!(ike->sa.st_seen_fragmentation_supported)) { | |||
884 | dbg("discarding IKE encrypted fragment - remote never proposed fragmentation"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("discarding IKE encrypted fragment - remote never proposed fragmentation" ); } }; | |||
885 | return false0; | |||
886 | } | |||
887 | ||||
888 | dbg("received IKE encrypted fragment number '%u', total number '%u', next payload '%u'",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("received IKE encrypted fragment number '%u', total number '%u', next payload '%u'" , skf->isaskf_number, skf->isaskf_total, skf->isaskf_np ); } } | |||
889 | skf->isaskf_number, skf->isaskf_total, skf->isaskf_np){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("received IKE encrypted fragment number '%u', total number '%u', next payload '%u'" , skf->isaskf_number, skf->isaskf_total, skf->isaskf_np ); } }; | |||
890 | ||||
891 | /* | |||
892 | * Sanity check: | |||
893 | * fragment number must be 1 or greater (not 0) | |||
894 | * fragment number must be no greater than the total number of fragments | |||
895 | * total number of fragments must be no more than MAX_IKE_FRAGMENTS | |||
896 | * first fragment's next payload must not be ISAKMP_NEXT_v2NONE. | |||
897 | * later fragments' next payload must be ISAKMP_NEXT_v2NONE. | |||
898 | */ | |||
899 | if (!(skf->isaskf_number != 0 && | |||
900 | skf->isaskf_number <= skf->isaskf_total && | |||
901 | skf->isaskf_total <= MAX_IKE_FRAGMENTS32 && | |||
902 | (skf->isaskf_number == 1) != (skf->isaskf_np == ISAKMP_NEXT_v2NONE))) { | |||
903 | dbg("ignoring invalid IKE encrypted fragment"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("ignoring invalid IKE encrypted fragment"); } }; | |||
904 | return false0; | |||
905 | } | |||
906 | ||||
907 | if (*frags == NULL((void*)0)) { | |||
908 | /* first fragment, so must be good */ | |||
909 | return true1; | |||
910 | } | |||
911 | ||||
912 | if (skf->isaskf_total != (*frags)->total) { | |||
913 | /* | |||
914 | * total number of fragments changed. | |||
915 | * Either this fragment is wrong or all the | |||
916 | * stored fragments are wrong or superseded. | |||
917 | * The only reason the other end would have | |||
918 | * started over with a different number of fragments | |||
919 | * is because it decided to ratchet down the packet size | |||
920 | * (and thus increase total). | |||
921 | * OK: skf->isaskf_total > i->total | |||
922 | * Bad: skf->isaskf_total < i->total | |||
923 | */ | |||
924 | if (skf->isaskf_total > (*frags)->total) { | |||
925 | dbg("discarding saved fragments because this fragment has larger total"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("discarding saved fragments because this fragment has larger total" ); } }; | |||
926 | free_v2_incoming_fragments(frags); | |||
927 | return true1; | |||
928 | } else { | |||
929 | dbg("ignoring odd IKE encrypted fragment (total shrank)"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("ignoring odd IKE encrypted fragment (total shrank)" ); } }; | |||
930 | return false0; | |||
931 | } | |||
932 | } else if ((*frags)->frags[skf->isaskf_number].text.ptr != NULL((void*)0)) { | |||
933 | /* retain earlier fragment with same index */ | |||
934 | dbg("ignoring repeated IKE encrypted fragment"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("ignoring repeated IKE encrypted fragment"); } }; | |||
935 | return false0; | |||
936 | } else { | |||
937 | return true1; | |||
938 | } | |||
939 | } | |||
940 | ||||
941 | bool_Bool ikev2_collect_fragment(struct msg_digest *md, struct ike_sa *ike) | |||
942 | { | |||
943 | struct v2_incoming_fragments **frags = &ike->sa.st_v2_incoming[v2_msg_role(md)]; | |||
944 | struct ikev2_skf *skf = &md->chain[ISAKMP_NEXT_v2SKF]->payload.v2skf; | |||
945 | struct pbs_inpacket_byte_stream *e_pbs = &md->chain[ISAKMP_NEXT_v2SKF]->pbs; | |||
946 | ||||
947 | if (!ike->sa.st_seen_fragmentation_supported) { | |||
948 | dbg(" fragments claiming to be from peer while peer did not signal fragmentation support - dropped"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log(" fragments claiming to be from peer while peer did not signal fragmentation support - dropped" ); } }; | |||
949 | return false0; | |||
950 | } | |||
951 | ||||
952 | if (!ikev2_check_fragment(md, ike)) { | |||
953 | return false0; | |||
954 | } | |||
955 | ||||
956 | /* | |||
957 | * Since the fragment check above can result in all fragments | |||
958 | * so-far being discarded; always check/fix frags. | |||
959 | */ | |||
960 | if ((*frags) == NULL((void*)0)) { | |||
961 | *frags = alloc_thing(struct v2_incoming_fragments, "incoming v2_ike_rfrags")((struct v2_incoming_fragments*) alloc_bytes(sizeof(struct v2_incoming_fragments ), ("incoming v2_ike_rfrags"))); | |||
962 | (*frags)->total = skf->isaskf_total; | |||
963 | } | |||
964 | ||||
965 | passert(skf->isaskf_number < elemsof((*frags)->frags))({ _Bool assertion__ = skf->isaskf_number < (sizeof((*frags )->frags) / sizeof(*((*frags)->frags))); if (!assertion__ ) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2_message.c", .line = 965, }; &here; }); const struct logger *logger_ = &failsafe_logger ; llog_passert(logger_, here, "%s", "skf->isaskf_number < (sizeof((*frags)->frags) / sizeof(*((*frags)->frags)))" ); } (void) 1; }); | |||
966 | struct v2_incoming_fragment *frag = &(*frags)->frags[skf->isaskf_number]; | |||
967 | passert(frag->text.ptr == NULL)({ _Bool assertion__ = frag->text.ptr == ((void*)0); if (! assertion__) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2_message.c" , .line = 967, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_passert(logger_, here, "%s", "frag->text.ptr == ((void*)0)" ); } (void) 1; }); | |||
968 | frag->iv_offset = e_pbs->cur - md->packet_pbs.start; | |||
969 | frag->text = clone_bytes_as_chunk(md->packet_pbs.start, | |||
970 | e_pbs->roof - md->packet_pbs.start, | |||
971 | "incoming IKEv2 encrypted fragment"); | |||
972 | ||||
973 | if (skf->isaskf_number == 1) { | |||
974 | (*frags)->first_np = skf->isaskf_np; | |||
975 | } | |||
976 | ||||
977 | passert((*frags)->count < (*frags)->total)({ _Bool assertion__ = (*frags)->count < (*frags)->total ; if (!assertion__) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2_message.c" , .line = 977, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_passert(logger_, here, "%s", "(*frags)->count < (*frags)->total" ); } (void) 1; }); | |||
978 | (*frags)->count++; | |||
979 | return (*frags)->count == (*frags)->total; | |||
980 | } | |||
981 | ||||
982 | static bool_Bool ikev2_reassemble_fragments(struct ike_sa *ike, | |||
983 | struct msg_digest *md) | |||
984 | { | |||
985 | if (md->chain[ISAKMP_NEXT_v2SK] != NULL((void*)0)) { | |||
986 | pexpect_failllog_pexpect(ike->sa.st_logger, HERE({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2_message.c", .line = 986, }; &here ; }), | |||
987 | "state #%lu has both SK ans SKF payloads", | |||
988 | ike->sa.st_serialno); | |||
989 | return false0; | |||
990 | } | |||
991 | ||||
992 | if (md->digest_roof >= elemsof(md->digest)(sizeof(md->digest) / sizeof(*(md->digest)))) { | |||
993 | log_state(RC_LOG, &ike->sa, | |||
994 | "packet contains too many payloads; discarded"); | |||
995 | return false0; | |||
996 | } | |||
997 | ||||
998 | struct v2_incoming_fragments **frags = &ike->sa.st_v2_incoming[v2_msg_role(md)]; | |||
999 | passert(*frags != NULL)({ _Bool assertion__ = *frags != ((void*)0); if (!assertion__ ) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2_message.c", .line = 999, }; &here; }); const struct logger *logger_ = &failsafe_logger ; llog_passert(logger_, here, "%s", "*frags != ((void*)0)"); } (void) 1; }); | |||
1000 | ||||
1001 | unsigned int size = 0; | |||
1002 | for (unsigned i = 1; i <= (*frags)->total; i++) { | |||
1003 | struct v2_incoming_fragment *frag = &(*frags)->frags[i]; | |||
1004 | /* | |||
1005 | * Point PLAIN at the encrypted fragment and then | |||
1006 | * decrypt in-place. After the decryption, PLAIN will | |||
1007 | * have been adjusted to just point at the data. | |||
1008 | */ | |||
1009 | if (!ikev2_verify_and_decrypt_sk_payload(ike, md, frag->text, | |||
1010 | &frag->plain, frag->iv_offset)) { | |||
1011 | log_state(RC_LOG_SERIOUS, &ike->sa, | |||
1012 | "fragment %u of %u invalid", i, (*frags)->total); | |||
1013 | free_v2_incoming_fragments(frags); | |||
1014 | return false0; | |||
1015 | } | |||
1016 | size += frag->plain.len; | |||
1017 | } | |||
1018 | ||||
1019 | /* | |||
1020 | * All the fragments have been disassembled, re-assemble them | |||
1021 | * into the .raw_packet buffer. | |||
1022 | */ | |||
1023 | pexpect(md->raw_packet.ptr == NULL)({ _Bool assertion__ = md->raw_packet.ptr == ((void*)0); if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2_message.c" , .line = 1023, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect(logger_, here_, "%s", "md->raw_packet.ptr == ((void*)0)" ); } assertion__; }); /* empty */ | |||
1024 | md->raw_packet = alloc_chunk(size, "IKEv2 fragments buffer"); | |||
1025 | unsigned int offset = 0; | |||
1026 | for (unsigned i = 1; i <= (*frags)->total; i++) { | |||
1027 | struct v2_incoming_fragment *frag = &(*frags)->frags[i]; | |||
1028 | passert(offset + frag->plain.len <= size)({ _Bool assertion__ = offset + frag->plain.len <= size ; if (!assertion__) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2_message.c" , .line = 1028, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_passert(logger_, here, "%s", "offset + frag->plain.len <= size" ); } (void) 1; }); | |||
1029 | memcpy(md->raw_packet.ptr + offset, | |||
1030 | frag->plain.ptr, frag->plain.len); | |||
1031 | offset += frag->plain.len; | |||
1032 | } | |||
1033 | ||||
1034 | /* | |||
1035 | * Fake up enough of an SK payload_digest to fool the caller | |||
1036 | * and then use that to scribble all over the SKF | |||
1037 | * payload_digest (remembering to also update the SK and SKF | |||
1038 | * chains). | |||
1039 | */ | |||
1040 | struct payload_digest sk = { | |||
1041 | .pbs = same_chunk_as_pbs_in(md->raw_packet, "decrypted SFK payloads"), | |||
1042 | .payload_type = ISAKMP_NEXT_v2SK, | |||
1043 | .payload.generic.isag_np = (*frags)->first_np, | |||
1044 | }; | |||
1045 | struct payload_digest *skf = md->chain[ISAKMP_NEXT_v2SKF]; | |||
1046 | md->chain[ISAKMP_NEXT_v2SKF] = NULL((void*)0); | |||
1047 | md->chain[ISAKMP_NEXT_v2SK] = skf; | |||
1048 | *skf = sk; /* scribble */ | |||
1049 | ||||
1050 | free_v2_incoming_fragments(frags); | |||
1051 | ||||
1052 | return true1; | |||
1053 | } | |||
1054 | ||||
1055 | /* | |||
1056 | * Decrypt the, possibly fragmented message intended for ST. | |||
1057 | * | |||
1058 | * Since the message fragments are stored in the recipient's ST | |||
1059 | * (either IKE or CHILD SA), it, and not the IKE SA is needed. | |||
1060 | */ | |||
1061 | bool_Bool ikev2_decrypt_msg(struct ike_sa *ike, struct msg_digest *md) | |||
1062 | { | |||
1063 | bool_Bool ok; | |||
1064 | if (md->chain[ISAKMP_NEXT_v2SKF] != NULL((void*)0)) { | |||
| ||||
1065 | ok = ikev2_reassemble_fragments(ike, md); | |||
1066 | } else { | |||
1067 | struct pbs_inpacket_byte_stream *e_pbs = &md->chain[ISAKMP_NEXT_v2SK]->pbs; | |||
1068 | /* | |||
1069 | * If so impaired, clone the encrypted message before | |||
1070 | * it gets decrypted in-place (but only once). | |||
1071 | */ | |||
1072 | if (impair.replay_encrypted && !md->fake_clone) { | |||
1073 | log_state(RC_LOG, &ike->sa, | |||
1074 | "IMPAIR: cloning incoming encrypted message and scheduling its replay"); | |||
1075 | schedule_md_event("replay encrypted message", | |||
1076 | clone_raw_md(md, HERE({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2_message.c", .line = 1076, }; &here ; }))); | |||
1077 | } | |||
1078 | if (impair.corrupt_encrypted && !md->fake_clone) { | |||
1079 | log_state(RC_LOG, &ike->sa, | |||
1080 | "IMPAIR: corrupting incoming encrypted message's SK payload's first byte"); | |||
1081 | *e_pbs->cur = ~(*e_pbs->cur); | |||
1082 | } | |||
1083 | ||||
1084 | chunk_t c = chunk2(md->packet_pbs.start, | |||
1085 | e_pbs->roof - md->packet_pbs.start); | |||
1086 | chunk_t plain; | |||
1087 | ok = ikev2_verify_and_decrypt_sk_payload(ike, md, c, &plain, | |||
1088 | e_pbs->cur - md->packet_pbs.start); | |||
1089 | md->chain[ISAKMP_NEXT_v2SK]->pbs = same_chunk_as_pbs_in(plain, "decrypted SK payload"); | |||
| ||||
1090 | } | |||
1091 | ||||
1092 | dbg("#%lu ikev2 %s decrypt %s",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("#%lu ikev2 %s decrypt %s", ike->sa.st_serialno , enum_name(&ikev2_exchange_names, md->hdr.isa_xchg), ok ? "success" : "failed"); } } | |||
1093 | ike->sa.st_serialno,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("#%lu ikev2 %s decrypt %s", ike->sa.st_serialno , enum_name(&ikev2_exchange_names, md->hdr.isa_xchg), ok ? "success" : "failed"); } } | |||
1094 | 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", ike->sa.st_serialno , enum_name(&ikev2_exchange_names, md->hdr.isa_xchg), ok ? "success" : "failed"); } } | |||
1095 | ok ? "success" : "failed"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("#%lu ikev2 %s decrypt %s", ike->sa.st_serialno , enum_name(&ikev2_exchange_names, md->hdr.isa_xchg), ok ? "success" : "failed"); } }; | |||
1096 | ||||
1097 | return ok; | |||
1098 | } | |||
1099 | ||||
1100 | /* | |||
1101 | * IKEv2 fragments: | |||
1102 | * | |||
1103 | * 1 2 3 | |||
1104 | * 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 | |||
1105 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
1106 | * | Next Payload |C| RESERVED | Payload Length | | |||
1107 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
1108 | * | Fragment Number | Total Fragments | | |||
1109 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
1110 | * | Initialization Vector | | |||
1111 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
1112 | * ~ Encrypted content ~ | |||
1113 | * + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
1114 | * | | Padding (0-255 octets) | | |||
1115 | * +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ | |||
1116 | * | | Pad Length | | |||
1117 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
1118 | * ~ Integrity Checksum Data ~ | |||
1119 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
1120 | * | |||
1121 | ||||
1122 | * | |||
1123 | */ | |||
1124 | ||||
1125 | static bool_Bool record_outbound_fragment(struct logger *logger, | |||
1126 | struct ike_sa *ike, | |||
1127 | const struct isakmp_hdr *hdr, | |||
1128 | enum next_payload_types_ikev2 skf_np, | |||
1129 | struct v2_outgoing_fragment **fragp, | |||
1130 | chunk_t *fragment, /* read-only */ | |||
1131 | unsigned int number, unsigned int total, | |||
1132 | const char *desc) | |||
1133 | { | |||
1134 | /* make sure HDR is at start of a clean buffer */ | |||
1135 | unsigned char frag_buffer[PMAX(MIN_MAX_UDP_DATA_v4, MIN_MAX_UDP_DATA_v6)(((576 - 20)) >= ((1280 - 48)) ? ((576 - 20)) : ((1280 - 48 )))]; | |||
1136 | struct pbs_outpacket_byte_stream frag_stream = open_pbs_out("reply frag packet", | |||
1137 | frag_buffer, sizeof(frag_buffer), | |||
1138 | logger); | |||
1139 | ||||
1140 | /* HDR out */ | |||
1141 | ||||
1142 | struct pbs_outpacket_byte_stream body; | |||
1143 | if (!out_struct(hdr, &isakmp_hdr_desc, &frag_stream, | |||
1144 | &body)) | |||
1145 | return false0; | |||
1146 | ||||
1147 | /* | |||
1148 | * Fake up an SK payload description sufficient to fool the | |||
1149 | * encryption code. | |||
1150 | * | |||
1151 | * While things are close, they are not identical - an SKF | |||
1152 | * payload header has extra fields and, for the first | |||
1153 | * fragment, forces the Next Payload. | |||
1154 | */ | |||
1155 | ||||
1156 | struct v2SK_payload skf = { | |||
1157 | .ike = ike, | |||
1158 | .logger = logger, | |||
1159 | .payload = { | |||
1160 | .ptr = body.cur, | |||
1161 | .len = 0 /* computed at end; set here to silence GCC 4.8.5 */ | |||
1162 | } | |||
1163 | }; | |||
1164 | ||||
1165 | /* | |||
1166 | * emit SKF header, save location. | |||
1167 | * | |||
1168 | * In the first fragment, .NP is set to the SK payload's next | |||
1169 | * payload type. | |||
1170 | */ | |||
1171 | ||||
1172 | const struct ikev2_skf e = { | |||
1173 | .isaskf_np = skf_np, /* needed */ | |||
1174 | .isaskf_critical = build_ikev2_critical(false0, ike->sa.st_logger), | |||
1175 | .isaskf_number = number, | |||
1176 | .isaskf_total = total, | |||
1177 | }; | |||
1178 | if (!out_struct(&e, &ikev2_skf_desc, &body, &skf.pbs)) | |||
1179 | return false0; | |||
1180 | ||||
1181 | /* emit IV and save location */ | |||
1182 | ||||
1183 | if (!emit_v2SK_iv(&skf)) { | |||
1184 | llog(RC_LOG, logger, | |||
1185 | "error initializing IV for encrypted %s message", | |||
1186 | desc); | |||
1187 | return false0; | |||
1188 | } | |||
1189 | ||||
1190 | /* save cleartext start */ | |||
1191 | ||||
1192 | skf.cleartext.ptr = skf.pbs.cur; | |||
1193 | ||||
1194 | /* output the fragment */ | |||
1195 | ||||
1196 | if (!out_hunk(*fragment, &skf.pbs, "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) ) { llog_diag(RC_LOG_SERIOUS, outs_->outs_logger, &d_, "%s", ""); } d_ == ((void*)0); })) | |||
1197 | return false0; | |||
1198 | ||||
1199 | if (!close_v2SK_payload(&skf)) { | |||
1200 | return false0; | |||
1201 | } | |||
1202 | ||||
1203 | close_output_pbs(&body); | |||
1204 | close_output_pbs(&frag_stream); | |||
1205 | ||||
1206 | stf_status ret = encrypt_v2SK_payload(&skf); | |||
1207 | if (ret != STF_OK) { | |||
1208 | llog(RC_LOG, logger, "error encrypting fragment %u", number); | |||
1209 | return false0; | |||
1210 | } | |||
1211 | ||||
1212 | dbg("recording fragment %u", number){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("recording fragment %u", number); } }; | |||
1213 | record_v2_outgoing_fragment(&frag_stream, desc, fragp); | |||
1214 | return true1; | |||
1215 | } | |||
1216 | ||||
1217 | static bool_Bool record_outbound_fragments(const struct pbs_outpacket_byte_stream *body, | |||
1218 | struct v2SK_payload *sk, | |||
1219 | const char *desc, | |||
1220 | struct v2_outgoing_fragment **frags) | |||
1221 | { | |||
1222 | free_v2_outgoing_fragments(frags); | |||
1223 | ||||
1224 | /* | |||
1225 | * fragment contents: | |||
1226 | * - sometimes: NON_ESP_MARKER (RFC3948) (NON_ESP_MARKER_SIZE) (4) | |||
1227 | * - always: isakmp header (NSIZEOF_isakmp_hdr) (28) | |||
1228 | * - always: ikev2_skf header (NSIZEOF_ikev2_skf) (8) | |||
1229 | * - variable: IV (no IV is longer than SHA2_512_DIGEST_SIZE) (64 or less) | |||
1230 | * - variable: fragment's data | |||
1231 | * - variable: padding (no padding is longer than MAX_CBC_BLOCK_SIZE) (16 or less) | |||
1232 | */ | |||
1233 | ||||
1234 | /* | |||
1235 | * XXX: this math seems very contrived, can the fragment() | |||
1236 | * function above be left to do the computation on-the-fly? | |||
1237 | */ | |||
1238 | ||||
1239 | unsigned int len = endpoint_type(&sk->ike->sa.st_remote_endpoint)->ikev2_max_fragment_size; | |||
1240 | ||||
1241 | /* | |||
1242 | * If we are doing NAT, so that the other end doesn't mistake | |||
1243 | * this message for ESP, each message needs a non-ESP_Marker | |||
1244 | * prefix. | |||
1245 | */ | |||
1246 | if (sk->ike->sa.st_interface != NULL((void*)0) && sk->ike->sa.st_interface->esp_encapsulation_enabled) | |||
1247 | len -= NON_ESP_MARKER_SIZE4; | |||
1248 | ||||
1249 | len -= NSIZEOF_isakmp_hdr28 + NSIZEOF_ikev2_skf8; | |||
1250 | ||||
1251 | len -= (encrypt_desc_is_aead(sk->ike->sa.st_oakley.ta_encrypt) | |||
1252 | ? sk->ike->sa.st_oakley.ta_encrypt->aead_tag_size | |||
1253 | : sk->ike->sa.st_oakley.ta_integ->integ_output_size); | |||
1254 | ||||
1255 | if (sk->ike->sa.st_oakley.ta_encrypt->pad_to_blocksize) | |||
1256 | len &= ~(sk->ike->sa.st_oakley.ta_encrypt->enc_blocksize - 1); | |||
1257 | ||||
1258 | len -= 2; /* ??? what's this? */ | |||
1259 | ||||
1260 | passert(sk->cleartext.len != 0)({ _Bool assertion__ = sk->cleartext.len != 0; if (!assertion__ ) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2_message.c", .line = 1260, }; &here; }); const struct logger *logger_ = & failsafe_logger; llog_passert(logger_, here, "%s", "sk->cleartext.len != 0" ); } (void) 1; }); | |||
1261 | ||||
1262 | unsigned int nfrags = (sk->cleartext.len + len - 1) / len; | |||
1263 | ||||
1264 | if (nfrags > MAX_IKE_FRAGMENTS32) { | |||
1265 | llog(RC_LOG_SERIOUS, sk->logger, | |||
1266 | "fragmenting this %zu byte message into %u byte chunks leads to too many frags", | |||
1267 | sk->cleartext.len, len); | |||
1268 | return false0; | |||
1269 | } | |||
1270 | ||||
1271 | /* | |||
1272 | * Extract the hdr from the original unfragmented message. | |||
1273 | * Set it up for auto-update of its next payload field chain. | |||
1274 | */ | |||
1275 | struct isakmp_hdr hdr; | |||
1276 | { | |||
1277 | struct pbs_inpacket_byte_stream pbs; | |||
1278 | init_pbs(&pbs, body->start, pbs_offset(body)((size_t)((body)->cur - (body)->start)), "sk hdr"); | |||
1279 | struct pbs_inpacket_byte_stream ignored; | |||
1280 | diag_t d = pbs_in_struct(&pbs, &isakmp_hdr_desc, &hdr, sizeof(hdr), &ignored); | |||
1281 | if (d != NULL((void*)0)) { | |||
1282 | llog_diag(RC_LOG, sk->logger, &d, "%s", ""); | |||
1283 | return false0; | |||
1284 | } | |||
1285 | } | |||
1286 | hdr.isa_np = ISAKMP_NEXT_v2NONE; /* clear NP */ | |||
1287 | ||||
1288 | /* | |||
1289 | * Extract the SK's next payload field from the original | |||
1290 | * unfragmented message. This is used as the first SKF's NP | |||
1291 | * field, the rest have NP=NONE(0). | |||
1292 | */ | |||
1293 | enum next_payload_types_ikev2 skf_np; | |||
1294 | { | |||
1295 | struct pbs_inpacket_byte_stream pbs = same_chunk_as_pbs_in(sk->payload, "sk"); | |||
1296 | struct ikev2_generic e; | |||
1297 | struct pbs_inpacket_byte_stream ignored; | |||
1298 | diag_t d = pbs_in_struct(&pbs, &ikev2_sk_desc, &e, sizeof(e), &ignored); | |||
1299 | if (d != NULL((void*)0)) { | |||
1300 | llog_diag(RC_LOG, sk->logger, &d, "%s", ""); | |||
1301 | return false0; | |||
1302 | } | |||
1303 | skf_np = e.isag_np; | |||
1304 | } | |||
1305 | ||||
1306 | unsigned int number = 1; | |||
1307 | unsigned int offset = 0; | |||
1308 | ||||
1309 | struct v2_outgoing_fragment **frag = frags; | |||
1310 | while (true1) { | |||
1311 | passert(*frag == NULL)({ _Bool assertion__ = *frag == ((void*)0); if (!assertion__) { where_t here = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2_message.c", .line = 1311, }; &here; }); const struct logger *logger_ = & failsafe_logger; llog_passert(logger_, here, "%s", "*frag == ((void*)0)" ); } (void) 1; }); | |||
1312 | chunk_t fragment = chunk2(sk->cleartext.ptr + offset, | |||
1313 | PMIN(sk->cleartext.len - offset, len)((sk->cleartext.len - offset) <= (len) ? (sk->cleartext .len - offset) : (len))); | |||
1314 | if (!record_outbound_fragment(sk->logger, sk->ike, &hdr, skf_np, frag, | |||
1315 | &fragment, number, nfrags, desc)) { | |||
1316 | return false0; | |||
1317 | } | |||
1318 | frag = &(*frag)->next; | |||
1319 | ||||
1320 | offset += fragment.len; | |||
1321 | number++; | |||
1322 | skf_np = ISAKMP_NEXT_v2NONE; | |||
1323 | ||||
1324 | if (offset >= sk->cleartext.len) { | |||
1325 | break; | |||
1326 | } | |||
1327 | } | |||
1328 | ||||
1329 | return true1; | |||
1330 | } | |||
1331 | ||||
1332 | /* | |||
1333 | * Record the message ready for sending. If needed, first fragment | |||
1334 | * it. | |||
1335 | */ | |||
1336 | ||||
1337 | stf_status record_v2SK_message(struct pbs_outpacket_byte_stream *msg, | |||
1338 | struct v2SK_payload *sk, | |||
1339 | const char *what, | |||
1340 | enum message_role message) | |||
1341 | { | |||
1342 | size_t len = pbs_offset(msg)((size_t)((msg)->cur - (msg)->start)); | |||
1343 | ||||
1344 | /* | |||
1345 | * If we are doing NAT, so that the other end doesn't mistake | |||
1346 | * this message for ESP, each message needs a non-ESP_Marker | |||
1347 | * prefix. | |||
1348 | */ | |||
1349 | if (!pexpect(sk->ike->sa.st_interface != NULL)({ _Bool assertion__ = sk->ike->sa.st_interface != ((void *)0); if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2_message.c" , .line = 1349, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect(logger_, here_, "%s", "sk->ike->sa.st_interface != ((void*)0)" ); } assertion__; }) && | |||
1350 | sk->ike->sa.st_interface->esp_encapsulation_enabled) | |||
1351 | len += NON_ESP_MARKER_SIZE4; | |||
1352 | ||||
1353 | /* IPv4 and IPv6 have different fragment sizes */ | |||
1354 | if (sk->ike->sa.st_interface->protocol == &ip_protocol_udpip_protocols[IPPROTO_UDP] && | |||
1355 | 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)))) && | |||
1356 | sk->ike->sa.st_seen_fragmentation_supported && | |||
1357 | len >= endpoint_type(&sk->ike->sa.st_remote_endpoint)->ikev2_max_fragment_size) { | |||
1358 | struct v2_outgoing_fragment **frags = &sk->ike->sa.st_v2_outgoing[message]; | |||
1359 | if (!record_outbound_fragments(msg, sk, what, frags)) { | |||
1360 | dbg("record outbound fragments failed"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("record outbound fragments failed"); } }; | |||
1361 | return STF_INTERNAL_ERROR; | |||
1362 | } | |||
1363 | } else { | |||
1364 | if (encrypt_v2SK_payload(sk) != STF_OK) { | |||
1365 | llog(RC_LOG, sk->logger, | |||
1366 | "error encrypting %s message", what); | |||
1367 | return STF_INTERNAL_ERROR; | |||
1368 | } | |||
1369 | dbg("recording outgoing fragment failed"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX) )))) { DBG_log("recording outgoing fragment failed"); } }; | |||
1370 | record_v2_message(sk->ike, msg, what, message); | |||
1371 | } | |||
1372 | return STF_OK; | |||
1373 | } | |||
1374 | ||||
1375 | struct ikev2_id build_v2_id_payload(const struct end *end, shunk_t *body, | |||
1376 | const char *what, struct logger *logger) | |||
1377 | { | |||
1378 | struct ikev2_id id_header = { | |||
1379 | .isai_type = id_to_payload(&end->id, &end->host_addr, body), | |||
1380 | .isai_critical = build_ikev2_critical(false0, logger), | |||
1381 | }; | |||
1382 | if (impair.send_nonzero_reserved_id) { | |||
1383 | llog(RC_LOG, logger, "IMPAIR: setting reserved byte 3 of %s to 0x%02x", | |||
1384 | what, ISAKMP_PAYLOAD_FLAG_LIBRESWAN_BOGUS(1<<ISAKMP_PAYLOAD_FLAG_LIBRESWAN_BOGUS_IX)); | |||
1385 | id_header.isai_res3 = ISAKMP_PAYLOAD_FLAG_LIBRESWAN_BOGUS(1<<ISAKMP_PAYLOAD_FLAG_LIBRESWAN_BOGUS_IX); | |||
1386 | } | |||
1387 | return id_header; | |||
1388 | } | |||
1389 | ||||
1390 | bool_Bool open_v2_payload(const char *story, | |||
1391 | struct ike_sa *ike, struct logger *logger, | |||
1392 | struct msg_digest *request_md, enum isakmp_xchg_type exchange_type, | |||
1393 | uint8_t *buf, size_t sizeof_buf, struct v2_payload *payload, | |||
1394 | enum payload_security security) | |||
1395 | { | |||
1396 | *payload = (struct v2_payload) { | |||
1397 | .story = story, | |||
1398 | .ike = ike, | |||
1399 | .logger = logger, | |||
1400 | .security = security, | |||
1401 | .role = (request_md != NULL((void*)0) ? MESSAGE_RESPONSE : MESSAGE_REQUEST), | |||
1402 | }; | |||
1403 | ||||
1404 | payload->message = open_pbs_out(story, buf, sizeof_buf, logger); | |||
1405 | ||||
1406 | payload->body = open_v2_message(&payload->message, ike, request_md, exchange_type); | |||
1407 | if (!pbs_ok(&payload->body)((&payload->body)->start != ((void*)0))) { | |||
1408 | llog(RC_LOG, payload->logger, | |||
1409 | "error initializing hdr for encrypted notification"); | |||
1410 | return false0; | |||
1411 | } | |||
1412 | ||||
1413 | switch (security) { | |||
1414 | case ENCRYPTED_PAYLOAD: | |||
1415 | /* never encrypt an IKE_SA_INIT exchange */ | |||
1416 | if (exchange_type == ISAKMP_v2_IKE_SA_INIT) { | |||
1417 | pexpect_failllog_pexpect(payload->logger, HERE({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2_message.c", .line = 1417, }; &here ; }), | |||
1418 | "exchange type IKE_SA_INIT is invalid for encrypted notification"); | |||
1419 | return false0; | |||
1420 | } | |||
1421 | /* check things are at least protected */ | |||
1422 | if (!pexpect(ike->sa.hidden_variables.st_skeyid_calculated)({ _Bool assertion__ = ike->sa.hidden_variables.st_skeyid_calculated ; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2_message.c" , .line = 1422, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect(logger_, here_, "%s", "ike->sa.hidden_variables.st_skeyid_calculated" ); } assertion__; })) { | |||
1423 | return false0; | |||
1424 | } | |||
1425 | payload->sk = open_v2SK_payload(logger, &payload->body, ike); | |||
1426 | if (!pbs_ok(&payload->sk.pbs)((&payload->sk.pbs)->start != ((void*)0))) { | |||
1427 | return false0; | |||
1428 | } | |||
1429 | payload->pbs = &payload->sk.pbs; | |||
1430 | break; | |||
1431 | case UNENCRYPTED_PAYLOAD: | |||
1432 | /* unsecured payload when secured allowed? */ | |||
1433 | pexpect(!ike->sa.hidden_variables.st_skeyid_calculated)({ _Bool assertion__ = !ike->sa.hidden_variables.st_skeyid_calculated ; if (!assertion__) { where_t here_ = ({ static const struct where here = { .func = __func__, .file = "programs/pluto/ikev2_message.c" , .line = 1433, }; &here; }); const struct logger *logger_ = &failsafe_logger; llog_pexpect(logger_, here_, "%s", "!ike->sa.hidden_variables.st_skeyid_calculated" ); } assertion__; }); | |||
1434 | payload->pbs = &payload->body; | |||
1435 | break; | |||
1436 | } | |||
1437 | ||||
1438 | return true1; | |||
1439 | } | |||
1440 | ||||
1441 | bool_Bool close_and_record_v2_payload(struct v2_payload *payload) | |||
1442 | { | |||
1443 | switch (payload->security) { | |||
1444 | case ENCRYPTED_PAYLOAD: | |||
1445 | if (!close_v2SK_payload(&payload->sk)) { | |||
1446 | return false0; | |||
1447 | } | |||
1448 | close_output_pbs(&payload->body); | |||
1449 | close_output_pbs(&payload->message); | |||
1450 | stf_status ret = encrypt_v2SK_payload(&payload->sk); | |||
1451 | if (ret != STF_OK) { | |||
1452 | llog(RC_LOG, payload->logger, | |||
1453 | "error encrypting response"); | |||
1454 | return false0; | |||
1455 | } | |||
1456 | break; | |||
1457 | case UNENCRYPTED_PAYLOAD: | |||
1458 | close_output_pbs(&payload->body); | |||
1459 | close_output_pbs(&payload->message); | |||
1460 | break; | |||
1461 | } | |||
1462 | ||||
1463 | record_v2_message(payload->ike, &payload->message, | |||
1464 | payload->story, payload->role); | |||
1465 | ||||
1466 | return true1; | |||
1467 | } |