ProtoCore v1.0.16
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
ikev2.h
Go to the documentation of this file.
1// ProtoCore v1.0.16 - Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file ikev2.h
6 * @brief IKEv2 (RFC 7296): the message and payload codec, the key schedule, and the handshake driver.
7 *
8 * RFC 7296 sec 3.1: a message begins with the 28-octet IKE header - IKE SA Initiator's SPI, IKE SA
9 * Responder's SPI, Next Payload, MjVer/MnVer, Exchange Type, Flags, Message ID, Length - and every
10 * multi-octet field is big endian. RFC 7296 sec 3.2: every payload begins with the generic payload
11 * header - Next Payload, the Critical bit, RESERVED, Payload Length - so the chain is walked forward
12 * from the header's Next Payload until a Next Payload of zero.
13 *
14 * The codec frames the Security Association payload (sec 3.3) with its Proposal (sec 3.3.1) and
15 * Transform (sec 3.3.2) substructures and the Key Length attribute (sec 3.3.5), Key Exchange
16 * (sec 3.4), Identification (sec 3.5), Certificate and Certificate Request (sec 3.6, 3.7),
17 * Authentication (sec 3.8), Nonce (sec 3.9), Notify (sec 3.10), Delete (sec 3.11), Traffic Selector
18 * (sec 3.13), Encrypted (sec 3.14), Configuration (sec 3.15), and the Encrypted Fragment payload of
19 * RFC 7383 sec 2.5.
20 *
21 * On the codec sits the crypto: prf+ (sec 2.13), the SKEYSEED / SK_* schedule (sec 2.14), the IKE SA
22 * rekey schedule (sec 2.18), Child SA KEYMAT (sec 2.17), the authenticated encryption that protects
23 * the Encrypted payload (RFC 5282 sec 3, 4 and 5.1: AES-GCM with a 16-octet ICV, ENCR transform id 20
24 * per RFC 5282 sec 7.2), the Curve25519 key exchange (Diffie-Hellman Group Num 31, RFC 8031 sec 3),
25 * pre-shared key and digital-signature authentication (sec 2.15, RFC 7427 sec 3), and the stateless
26 * COOKIE (sec 2.6).
27 *
28 * On the crypto sits the handshake driver: both roles run IKE_SA_INIT then IKE_AUTH (sec 1.2) to
29 * IKE_ST_ESTABLISHED with mutual pre-shared key authentication, then INFORMATIONAL (sec 1.4) and
30 * CREATE_CHILD_SA (sec 1.3) exchanges over the established SA.
31 *
32 * The PRF is HMAC-SHA2-256, PRF transform id 5 (RFC 4868 sec 4), whose preferred key length fixes
33 * SK_d, SK_pi and SK_pr (sec 2.13); the integrity transform, when one is negotiated, is
34 * AUTH_HMAC_SHA2_256_128, id 12 (RFC 4868 sec 4), keyed with the 32-octet hash output
35 * (RFC 4868 sec 2.1.1). An AEAD cipher carries its own integrity, so SK_ai and SK_ar are then zero
36 * octets (RFC 5282 sec 7.1).
37 *
38 * The module exports one symbol, @ref Ike. Everything in ikev2.c has internal linkage. A caller sets
39 * the members a call takes, invokes it through ::Ike, and reads the outcome off the same handle.
40 *
41 * @author Douglas Quigg (dstroy0)
42 * @date 2026
43 */
44
45#ifndef PROTOCORE_IKEV2_H
46#define PROTOCORE_IKEV2_H
47
48#include "protocore_config.h" // the entry point: protocore_types.h for the widths
49
50#if PROTOCORE_ENABLE_IKEV2
51
53
54// ---------------------------------------------------------------------------
55// Literals
56// ---------------------------------------------------------------------------
57
58/** @brief UDP port IKE runs on (RFC 7296 sec 2.23). */
59#define PROTOCORE_IKEV2_PORT 500
60/** @brief UDP port reserved for UDP-encapsulated ESP and IKE (RFC 7296 sec 2.23, RFC 3948 sec 2.2). */
61#define PROTOCORE_IKEV2_NAT_PORT 4500
62/** @brief IKE header size (RFC 7296 sec 3.1). */
63#define PROTOCORE_IKE_HDR_LEN 28
64/** @brief IKE SA Initiator's / Responder's SPI size (RFC 7296 sec 3.1). */
65#define PROTOCORE_IKE_SPI_LEN 8
66/** @brief Generic payload header size: Next Payload, C bit + RESERVED, Payload Length (RFC 7296 sec 3.2). */
67#define PROTOCORE_IKE_PAYLOAD_HDR_LEN 4
68/** @brief MjVer 2, MnVer 0 in the version octet (RFC 7296 sec 3.1). */
69#define PROTOCORE_IKE_VERSION 0x20
70/** @brief The Critical bit in a payload's second header octet (RFC 7296 sec 3.2). */
71#define PROTOCORE_IKE_CRITICAL 0x80
72
73/** @brief IKE header Flags octet, bit layout X|X|R|V|I|X|X|X (RFC 7296 sec 3.1). */
74#define PROTOCORE_IKE_FLAG_INITIATOR 0x08 ///< I: sent by the original initiator of the IKE SA
75#define PROTOCORE_IKE_FLAG_VERSION 0x10 ///< V: a higher major version is supported
76#define PROTOCORE_IKE_FLAG_RESPONSE 0x20 ///< R: a response to the message with the same Message ID
77
78/** @brief Transform attribute type Key Length, in bits, TV form (RFC 7296 sec 3.3.5). */
79#define IKE_ATTR_KEY_LENGTH 14
80
81/** @brief Transform IDs this build names; any 16-bit id is accepted on the wire. */
82#define IKE_ENCR_AES_CBC 12 ///< ENCR_AES_CBC
83#define IKE_ENCR_AES_GCM_16 20 ///< AES-GCM with a 16-octet ICV (RFC 5282 sec 7.2)
84#define IKE_ENCR_CHACHA20_POLY1305 28 ///< ENCR_CHACHA20_POLY1305
85#define IKE_PRF_HMAC_SHA2_256 5 ///< PRF_HMAC_SHA2_256 (RFC 4868 sec 4)
86#define IKE_INTEG_HMAC_SHA2_256_128 12 ///< AUTH_HMAC_SHA2_256_128 (RFC 4868 sec 4)
87#define IKE_DH_MODP2048 14 ///< 2048-bit MODP group (RFC 7296 app. B)
88#define IKE_DH_ECP256 19 ///< 256-bit random ECP group
89#define IKE_DH_CURVE25519 31 ///< Curve25519 (RFC 8031 sec 3)
90
91// Configuration Attribute types (RFC 7296 sec 3.15.1).
92#define PROTOCORE_IKE_CFG_INTERNAL_IP4_ADDRESS 1
93#define PROTOCORE_IKE_CFG_INTERNAL_IP4_NETMASK 2
94#define PROTOCORE_IKE_CFG_INTERNAL_IP4_DNS 3
95#define PROTOCORE_IKE_CFG_INTERNAL_IP4_NBNS 4
96#define PROTOCORE_IKE_CFG_INTERNAL_IP4_DHCP 6
97#define PROTOCORE_IKE_CFG_APPLICATION_VERSION 7
98#define PROTOCORE_IKE_CFG_INTERNAL_IP6_ADDRESS 8
99#define PROTOCORE_IKE_CFG_INTERNAL_IP6_DNS 10
100#define PROTOCORE_IKE_CFG_INTERNAL_IP6_DHCP 12
101#define PROTOCORE_IKE_CFG_INTERNAL_IP4_SUBNET 13
102#define PROTOCORE_IKE_CFG_INTERNAL_IP6_SUBNET 15
103
104/** @brief IKEV2_FRAGMENTATION_SUPPORTED Notify Message Type, no data (RFC 7383 sec 2.3, sec 6). */
105#define PROTOCORE_IKE_N_FRAGMENTATION_SUPPORTED 16430
106/** @brief Largest Total Fragments this reassembler tracks (RFC 7383 sec 2.5). */
107#define PROTOCORE_IKE_FRAG_MAX 32
108
109/** @brief COOKIE Notify Message Type (RFC 7296 sec 3.10.1). */
110#define PROTOCORE_IKE_N_COOKIE 16390
111/** @brief Cookie length here: the VersionIDofSecret octet plus a SHA-256 hash (RFC 7296 sec 2.6). */
112#define PROTOCORE_IKE_COOKIE_LEN 33
113
114/** @brief PRF_HMAC_SHA2_256 output and preferred key length, in octets (RFC 4868 sec 2.1.2). */
115#define PROTOCORE_IKE_PRF_LEN 32
116/** @brief Largest single SK_* key stored: a 32-octet cipher key plus a 4-octet salt, with margin. */
117#define PROTOCORE_IKE_SK_MAX 40
118/** @brief Largest nonce stored; a nonce is at least 128 bits (RFC 7296 sec 2.10). */
119#define PROTOCORE_IKE_NONCE_MAX 256
120
121/** @brief AES-256 cipher key length inside SK_ei / SK_er, salt excluded (RFC 5282 sec 7.1). */
122#define PROTOCORE_IKE_AEAD_KEY_LEN 32
123/** @brief Salt: the 4-octet tail of SK_ei / SK_er, not sent on the wire (RFC 5282 sec 4, sec 7.1). */
124#define PROTOCORE_IKE_GCM_SALT_LEN 4
125/** @brief Initialization Vector carried in the Encrypted payload (RFC 5282 sec 3.1). */
126#define PROTOCORE_IKE_GCM_IV_LEN 8
127/** @brief Integrity Check Value length: the full AES-GCM Authentication Tag (RFC 5282 sec 3.2). */
128#define PROTOCORE_IKE_AEAD_ICV_LEN 16
129
130/** @brief Octets the SK envelope adds around the inner payloads: generic header, IV, Pad Length, ICV. */
131#define PROTOCORE_IKE_SK_OVERHEAD \
132 (PROTOCORE_IKE_PAYLOAD_HDR_LEN + PROTOCORE_IKE_GCM_IV_LEN + 1 + PROTOCORE_IKE_AEAD_ICV_LEN)
133
134/** @brief AUTH payload Authentication Data length for a PRF_HMAC_SHA2_256 MAC (RFC 7296 sec 2.15). */
135#define PROTOCORE_IKE_AUTH_LEN 32
136/** @brief The pre-shared key pad string: 17 ASCII characters, no null termination (RFC 7296 sec 2.15). */
137#define PROTOCORE_IKE_PSK_PAD "Key Pad for IKEv2"
138
139/** @brief Curve25519 private, public and shared-secret length (RFC 8031 sec 2, sec 3.1). */
140#define PROTOCORE_IKE_X25519_LEN 32
141
142/** @brief P-256 public point length, uncompressed (0x04 | X | Y). */
143#define PROTOCORE_IKE_ECDSA_P256_PUB_LEN 65
144/** @brief P-256 private scalar length. */
145#define PROTOCORE_IKE_ECDSA_P256_PRIV_LEN 32
146/** @brief ECDSA-P256 signature length, r | s. */
147#define PROTOCORE_IKE_ECDSA_P256_SIG_LEN 64
148
149/** @brief Largest message the handshake stores as RealMessage1 / RealMessage2 (RFC 7296 sec 2.15). */
150#define PROTOCORE_IKE_MSG_MAX 640
151
152// ---------------------------------------------------------------------------
153// Typedefs
154// ---------------------------------------------------------------------------
155
156/** @brief Exchange Type (RFC 7296 sec 3.1). */
157typedef enum PROTO_ENUM_PACKED
158{
159 IKE_SA_INIT = 34,
160 IKE_AUTH = 35,
161 IKE_CREATE_CHILD_SA = 36,
162 IKE_INFORMATIONAL = 37,
163} IkeExchange;
164
165/** @brief Next Payload / payload types; zero ends the chain (RFC 7296 sec 3.2). */
166typedef enum PROTO_ENUM_PACKED
167{
168 IKE_PL_NONE = 0,
169 IKE_PL_SA = 33, ///< Security Association, SA
170 IKE_PL_KE = 34, ///< Key Exchange, KE
171 IKE_PL_IDI = 35, ///< Identification - Initiator, IDi
172 IKE_PL_IDR = 36, ///< Identification - Responder, IDr
173 IKE_PL_CERT = 37, ///< Certificate, CERT
174 IKE_PL_CERTREQ = 38, ///< Certificate Request, CERTREQ
175 IKE_PL_AUTH = 39, ///< Authentication, AUTH
176 IKE_PL_NONCE = 40, ///< Nonce, Ni or Nr
177 IKE_PL_NOTIFY = 41, ///< Notify, N
178 IKE_PL_DELETE = 42, ///< Delete, D
179 IKE_PL_VENDOR = 43, ///< Vendor ID, V
180 IKE_PL_TSI = 44, ///< Traffic Selector - Initiator, TSi
181 IKE_PL_TSR = 45, ///< Traffic Selector - Responder, TSr
182 IKE_PL_SK = 46, ///< Encrypted and Authenticated, SK
183 IKE_PL_CP = 47, ///< Configuration, CP
184 IKE_PL_EAP = 48, ///< Extensible Authentication, EAP
185 IKE_PL_SKF = 53, ///< Encrypted and Authenticated Fragment, SKF (RFC 7383 sec 2.5)
186} IkePayloadType;
187
188/** @brief Transform Type (RFC 7296 sec 3.3.2). */
189typedef enum PROTO_ENUM_PACKED
190{
191 IKE_TRANSFORM_ENCR = 1, ///< Encryption Algorithm
192 IKE_TRANSFORM_PRF = 2, ///< Pseudorandom Function
193 IKE_TRANSFORM_INTEG = 3, ///< Integrity Algorithm
194 IKE_TRANSFORM_DH = 4, ///< Diffie-Hellman Group
195 IKE_TRANSFORM_ESN = 5, ///< Extended Sequence Numbers
196} IkeTransformType;
197
198/** @brief Protocol ID (RFC 7296 sec 3.3.1, sec 3.10, sec 3.11). */
199typedef enum PROTO_ENUM_PACKED
200{
201 IKE_PROTO_NONE = 0, ///< the notification concerns no existing SA and the SPI field is empty
202 IKE_PROTO_IKE = 1,
203 IKE_PROTO_AH = 2,
204 IKE_PROTO_ESP = 3,
205} IkeProtocol;
206
207/** @brief ID Type (RFC 7296 sec 3.5). */
208typedef enum PROTO_ENUM_PACKED
209{
210 IKE_ID_RESERVED = 0, ///< reserved; the value an out member holds before a parse succeeds
211 IKE_ID_IPV4_ADDR = 1,
212 IKE_ID_FQDN = 2,
213 IKE_ID_RFC822_ADDR = 3,
214 IKE_ID_IPV6_ADDR = 5,
215 IKE_ID_KEY_ID = 11,
216} IkeIdType;
217
218/** @brief Auth Method (RFC 7296 sec 3.8). */
219typedef enum PROTO_ENUM_PACKED
220{
221 IKE_AUTH_RESERVED = 0, ///< reserved; the value an out member holds before a parse succeeds
222 IKE_AUTH_RSA_SIG = 1, ///< RSA Digital Signature
223 IKE_AUTH_PSK = 2, ///< Shared Key Message Integrity Code
224 IKE_AUTH_DSS_SIG = 3, ///< DSS Digital Signature
225 IKE_AUTH_DIGITAL_SIG = 14 ///< Digital Signature (RFC 7427 sec 3)
226} IkeAuthMethod;
227
228/** @brief TS Type (RFC 7296 sec 3.13.1). */
229typedef enum PROTO_ENUM_PACKED
230{
231 IKE_TS_IPV4_ADDR_RANGE = 7,
232 IKE_TS_IPV6_ADDR_RANGE = 8,
233} IkeTsType;
234
235/** @brief CFG Type (RFC 7296 sec 3.15.1). */
236typedef enum PROTO_ENUM_PACKED
237{
238 IKE_CFG_REQUEST = 1, ///< CFG_REQUEST
239 IKE_CFG_REPLY = 2, ///< CFG_REPLY
240 IKE_CFG_SET = 3, ///< CFG_SET
241 IKE_CFG_ACK = 4, ///< CFG_ACK
242} IkeCfgType;
243
244/** @brief Handshake progress across IKE_SA_INIT and IKE_AUTH (RFC 7296 sec 1.2). */
245typedef enum PROTO_ENUM_PACKED
246{
247 IKE_ST_INIT = 0, ///< nothing sent yet
248 IKE_ST_SA_INIT_SENT, ///< IKE_SA_INIT emitted, awaiting the response
249 IKE_ST_SA_INIT_DONE, ///< the peer's IKE_SA_INIT consumed and the SK_* keys derived
250 IKE_ST_AUTH_SENT, ///< IKE_AUTH request emitted, awaiting the response
251 IKE_ST_ESTABLISHED, ///< the peer's AUTH verified; the IKE SA is up
252 IKE_ST_FAILED, ///< a received message was rejected
253} IkeState;
254
255/** @brief The IKE header, decoded or to be encoded (RFC 7296 sec 3.1). */
256typedef struct
257{
258 uint8_t init_spi[PROTOCORE_IKE_SPI_LEN]; ///< IKE SA Initiator's SPI
259 uint8_t resp_spi[PROTOCORE_IKE_SPI_LEN]; ///< IKE SA Responder's SPI
260 IkePayloadType next_payload; ///< type of the first payload in the message
261 uint8_t version; ///< MjVer | MnVer, 0x20 for IKEv2
262 IkeExchange exchange; ///< Exchange Type
263 uint8_t flags; ///< OR of PROTOCORE_IKE_FLAG_*
264 uint32_t message_id; ///< Message ID
265 uint32_t length; ///< Length of the whole message
266} IkeHeader;
267
268/** @brief One payload off the chain: its type, the following type, and its body (RFC 7296 sec 3.2). */
269typedef struct
270{
271 IkePayloadType type; ///< this payload's type, taken from the chain
272 IkePayloadType next_payload; ///< Next Payload; IKE_PL_NONE ends the chain
273 proto_bool critical; ///< the Critical bit
274 const uint8_t *body; ///< the octets after the generic payload header
275 size_t body_len;
276} IkePayload;
277
278/** @brief Forward walk of a message's payload chain (RFC 7296 sec 3.2). */
279typedef struct
280{
281 const uint8_t *area; ///< the payload area: the message plus PROTOCORE_IKE_HDR_LEN
282 size_t len; ///< octets in that area
283 size_t off; ///< current offset into @c area
284 IkePayloadType next_type; ///< type of the payload at @c off; IKE_PL_NONE is done
285} IkePayloadIter;
286
287/** @brief One Transform Substructure to encode (RFC 7296 sec 3.3.2). */
288typedef struct
289{
290 IkeTransformType type; ///< Transform Type
291 uint16_t id; ///< Transform ID
292 int32_t key_length; ///< Key Length attribute in bits (sec 3.3.5), or below zero for none
293} IkeTransform;
294
295/** @brief One decoded Transform Substructure (RFC 7296 sec 3.3.2). */
296typedef struct
297{
298 IkeTransformType type; ///< Transform Type
299 uint16_t id; ///< Transform ID
300 int32_t key_length; ///< decoded Key Length attribute, or below zero when absent
301 proto_bool last; ///< Last Substruc was 0: no transform follows
302} IkeTransformRef;
303
304/** @brief One decoded Proposal Substructure (RFC 7296 sec 3.3.1). */
305typedef struct
306{
307 uint8_t proposal_num; ///< Proposal Num
308 IkeProtocol protocol_id; ///< Protocol ID
309 uint8_t spi_size; ///< SPI Size
310 uint8_t num_transforms; ///< Num Transforms
311 const uint8_t *spi; ///< SPI, @c spi_size octets, or nullptr when SPI Size is zero
312 const uint8_t *transforms;
313 size_t transforms_len;
314 proto_bool last; ///< Last Substruc was 0: no proposal follows
315} IkeProposalRef;
316
317/** @brief Walk of the Transform Substructures inside one proposal (RFC 7296 sec 3.3.2). */
318typedef struct
319{
320 const uint8_t *area;
321 size_t len;
322 size_t off;
323} IkeTransformIter;
324
325/** @brief One Traffic Selector (RFC 7296 sec 3.13.1). */
326typedef struct
327{
328 IkeTsType ts_type; ///< TS Type
329 uint8_t ip_protocol; ///< IP Protocol ID; zero means any
330 uint16_t start_port; ///< Start Port
331 uint16_t end_port; ///< End Port
332 const uint8_t *start_addr; ///< Starting Address, 4 or 16 octets
333 const uint8_t *end_addr; ///< Ending Address, the same length
334 size_t addr_len; ///< 4 or 16
335} IkeTrafficSelector;
336
337/** @brief One Configuration Attribute: a 15-bit type and its value (RFC 7296 sec 3.15.1). */
338typedef struct
339{
340 uint16_t type; ///< Attribute Type, the reserved high bit masked off
341 const uint8_t *value; ///< Value, or nullptr when @c value_len is zero
342 uint16_t value_len; ///< Length
343} IkeCfgAttr;
344
345/** @brief Walk of a Configuration payload's attribute area (RFC 7296 sec 3.15.1). */
346typedef struct
347{
348 const uint8_t *area;
349 size_t len;
350 size_t off;
351} IkeCfgAttrIter;
352
353/**
354 * @brief Reassembly of one fragmented message (RFC 7383 sec 2.6).
355 *
356 * Decrypted Encrypted Fragment contents are staged into a caller-owned pool in arrival order and
357 * merged 1..Total once every fragment is present.
358 */
359typedef struct
360{
361 uint16_t total; ///< Total Fragments; zero until the first fragment sets it
362 uint16_t count; ///< distinct fragments stored
363 proto_bool present[PROTOCORE_IKE_FRAG_MAX]; ///< present[i] holds fragment (i+1)
364 size_t off[PROTOCORE_IKE_FRAG_MAX]; ///< pool offset of fragment (i+1)
365 size_t len[PROTOCORE_IKE_FRAG_MAX]; ///< length of fragment (i+1)
366 uint8_t *pool; ///< caller-owned staging buffer
367 size_t pool_cap;
368 size_t pool_used;
369} IkeFragReasm;
370
371/** @brief Per-key lengths of the SK_* chain, in octets (RFC 7296 sec 2.13, sec 2.14). */
372typedef struct
373{
374 size_t sk_d; ///< SK_d: the PRF's preferred key length
375 size_t sk_a; ///< SK_ai / SK_ar: the integrity key length, zero for an AEAD cipher
376 size_t sk_e; ///< SK_ei / SK_er: the cipher key plus any AEAD salt
377 size_t sk_p; ///< SK_pi / SK_pr: the PRF's preferred key length
378} IkeKeyLengths;
379
380/** @brief The seven keys taken in order from prf+ (RFC 7296 sec 2.14). */
381typedef struct
382{
383 uint8_t sk_d[PROTOCORE_IKE_SK_MAX];
384 uint8_t sk_ai[PROTOCORE_IKE_SK_MAX];
385 uint8_t sk_ar[PROTOCORE_IKE_SK_MAX];
386 uint8_t sk_ei[PROTOCORE_IKE_SK_MAX];
387 uint8_t sk_er[PROTOCORE_IKE_SK_MAX];
388 uint8_t sk_pi[PROTOCORE_IKE_SK_MAX];
389 uint8_t sk_pr[PROTOCORE_IKE_SK_MAX];
390 size_t sk_d_len; ///< valid octets in sk_d
391 size_t sk_a_len; ///< valid octets in sk_ai / sk_ar
392 size_t sk_e_len; ///< valid octets in sk_ei / sk_er
393 size_t sk_p_len; ///< valid octets in sk_pi / sk_pr
394} IkeKeyMaterial;
395
396/** @brief The four transforms negotiated for an IKE SA (RFC 7296 sec 2.13). */
397typedef struct
398{
399 uint16_t encr; ///< Encryption Algorithm transform id
400 int32_t encr_keylen; ///< Key Length attribute in bits, or below zero for a fixed-length key
401 uint16_t prf; ///< Pseudorandom Function transform id
402 uint16_t integ; ///< Integrity Algorithm transform id, zero for an AEAD cipher
403 uint16_t dh; ///< Diffie-Hellman Group Num
404} IkeSuite;
405
406/** @brief One IKE SA after IKE_SA_INIT: the SPIs, the negotiated suite, and the SK_* keys. */
407typedef struct
408{
409 uint8_t init_spi[PROTOCORE_IKE_SPI_LEN]; ///< IKE SA Initiator's SPI
410 uint8_t resp_spi[PROTOCORE_IKE_SPI_LEN]; ///< IKE SA Responder's SPI
411 proto_bool is_initiator; ///< this side is the original initiator
412 IkeSuite suite; ///< the negotiated transforms
413 IkeKeyMaterial keys; ///< SK_d, SK_ai, SK_ar, SK_ei, SK_er, SK_pi, SK_pr
414 // The cookie hash, the prf+ chain, the AUTH MAC and the signature run in sequence, so one region
415 // sized for the largest serves them all.
416 uint8_t work[PROTOCORE_IKE_BORROW];
417} IkeSa;
418
419/** @brief The salient contents of a parsed IKE_SA_INIT; slices point into the message (sec 1.2). */
420typedef struct
421{
422 uint8_t init_spi[PROTOCORE_IKE_SPI_LEN];
423 uint8_t resp_spi[PROTOCORE_IKE_SPI_LEN];
424 proto_bool is_response; ///< the R flag was set
425 IkeProposalRef proposal; ///< the first proposal of SAi1 or SAr1
426 uint16_t dh_group; ///< Diffie-Hellman Group Num from the KE payload
427 const uint8_t *ke_data; ///< Key Exchange Data
428 size_t ke_len;
429 const uint8_t *nonce; ///< Ni or Nr data
430 size_t nonce_len;
431} IkeSaInitMsg;
432
433/** @brief Handshake context: the SA under construction and what the next step signs over. */
434typedef struct
435{
436 IkeSa sa; ///< the SA being established
437 IkeState state; ///< @ref IkeState
438 uint8_t our_dh_priv[PROTOCORE_IKE_X25519_LEN]; ///< our ephemeral private, to compute g^ir
439 uint8_t our_nonce[PROTOCORE_IKE_NONCE_MAX]; ///< the nonce this side sent
440 uint16_t our_nonce_len;
441 uint8_t peer_nonce[PROTOCORE_IKE_NONCE_MAX]; ///< the nonce the peer sent
442 uint16_t peer_nonce_len;
443 uint8_t init_msg[PROTOCORE_IKE_MSG_MAX]; ///< RealMessage1: the IKE_SA_INIT request (sec 2.15)
444 uint16_t init_msg_len;
445 uint8_t resp_msg[PROTOCORE_IKE_MSG_MAX]; ///< RealMessage2: the IKE_SA_INIT response (sec 2.15)
446 uint16_t resp_msg_len;
447} IkeHandshake;
448
449/** @brief A decoded Key Exchange payload (RFC 7296 sec 3.4). */
450typedef struct
451{
452 uint16_t dh_group; ///< Diffie-Hellman Group Num
453 const uint8_t *ke_data; ///< Key Exchange Data
454 size_t ke_len;
455} IkeKeRef;
456
457/** @brief A decoded Identification payload (RFC 7296 sec 3.5). */
458typedef struct
459{
460 IkeIdType id_type; ///< ID Type
461 const uint8_t *id_data; ///< Identification Data
462 size_t id_len;
463} IkeIdRef;
464
465/** @brief A decoded Authentication payload (RFC 7296 sec 3.8). */
466typedef struct
467{
468 IkeAuthMethod auth_method; ///< Auth Method
469 const uint8_t *auth_data; ///< Authentication Data
470 size_t auth_len;
471} IkeAuthRef;
472
473/** @brief A decoded Notify payload (RFC 7296 sec 3.10). */
474typedef struct
475{
476 IkeProtocol protocol_id; ///< Protocol ID
477 uint8_t spi_size; ///< SPI Size
478 uint16_t notify_type; ///< Notify Message Type
479 const uint8_t *spi; ///< SPI, or nullptr when SPI Size is zero
480 const uint8_t *data; ///< Notification Data
481 size_t data_len;
482} IkeNotifyRef;
483
484/** @brief A decoded Delete payload (RFC 7296 sec 3.11). */
485typedef struct
486{
487 IkeProtocol protocol_id; ///< Protocol ID
488 uint8_t spi_size; ///< SPI Size
489 uint16_t num_spis; ///< Num of SPIs
490 const uint8_t *spis; ///< the SPI list, or nullptr when it is empty
491} IkeDeleteRef;
492
493/** @brief A sliced Encrypted or Encrypted Fragment payload body (RFC 7296 sec 3.14, RFC 7383 sec 2.5). */
494typedef struct
495{
496 uint16_t frag_num; ///< Fragment Number, zero for an unfragmented Encrypted payload
497 uint16_t total; ///< Total Fragments, zero for an unfragmented Encrypted payload
498 const uint8_t *iv; ///< Initialization Vector
499 const uint8_t *ct; ///< Ciphertext
500 size_t ct_len;
501 const uint8_t *icv; ///< Integrity Checksum Data
502} IkeSkRef;
503
504/** @brief A decoded Configuration payload (RFC 7296 sec 3.15). */
505typedef struct
506{
507 IkeCfgType cfg_type; ///< CFG Type
508 const uint8_t *attrs; ///< the Configuration Attribute area
509 size_t attrs_len;
510} IkeCpRef;
511
512/** @brief The inner payload chain an Encrypted payload was carrying (RFC 7296 sec 3.14). */
513typedef struct
514{
515 IkePayloadType first_inner_type; ///< the Encrypted payload's Next Payload
516 const uint8_t *inner; ///< the decrypted chain, inside the caller's message buffer
517 size_t inner_len;
518} IkeInnerRef;
519
520/** @brief Where a build, a hash or a signature writes. */
521typedef struct
522{
523 uint8_t *buf; ///< the octets a call writes
524 size_t cap; ///< room there; prf+ and child_keymat fill it exactly
525} IkeOutArgs;
526
527/** @brief The octets a parse reads: a whole message, or one payload body (RFC 7296 sec 3.2). */
528typedef struct
529{
530 const uint8_t *msg; ///< a message, a payload body, or an attribute area
531 size_t len;
532} IkeWireArgs;
533
534/** @brief The generic payload header a build writes, and the payload's own variable field (sec 3.2). */
535typedef struct
536{
537 IkePayloadType next_payload; ///< Next Payload: the type of the payload that follows this one
538 proto_bool critical; ///< the Critical bit
539 const uint8_t *data; ///< this payload's variable field, named per payload by each call
540 size_t data_len;
541} IkePayloadArgs;
542
543/** @brief The Proposal Substructure a build encodes, and the SPIs a Notify or Delete names (sec 3.3.1). */
544typedef struct
545{
546 uint8_t proposal_num; ///< Proposal Num
547 IkeProtocol protocol_id; ///< Protocol ID
548 const uint8_t *spi; ///< SPI
549 uint8_t spi_size; ///< SPI Size
550 uint16_t num_spis; ///< Num of SPIs in a Delete payload (sec 3.11)
551 const IkeTransform *transforms; ///< the Transform Substructures to encode (sec 3.3.2)
552 uint8_t num_transforms; ///< Num Transforms
553} IkeProposalArgs;
554
555/** @brief The key exchange: the group and the values (RFC 7296 sec 3.4, RFC 8031 sec 3). */
556typedef struct
557{
558 uint16_t dh_group; ///< Diffie-Hellman Group Num
559 const uint8_t *our_priv; ///< our ephemeral private value
560 size_t our_priv_len; ///< its length; 32 for group 31
561 const uint8_t *our_pub; ///< our Key Exchange Data
562 size_t our_pub_len; ///< its length; 32 for group 31
563 const uint8_t *peer_pub; ///< the peer's Key Exchange Data
564 size_t peer_pub_len; ///< its length
565} IkeKeArgs;
566
567/** @brief The identity: the ID payload's fields and its signed remainder (sec 3.5, 3.6, 2.15). */
568typedef struct
569{
570 IkeIdType id_type; ///< ID Type
571 const uint8_t *id_body; ///< RestOfInitIDPayload / RestOfRespIDPayload: the ID payload body
572 size_t id_body_len;
573 uint8_t cert_encoding; ///< Cert Encoding for a CERT or CERTREQ payload (sec 3.6)
574} IkeIdArgs;
575
576/** @brief Authentication: the method and every input the AUTH value is computed from (sec 2.15). */
577typedef struct
578{
579 IkeAuthMethod auth_method; ///< Auth Method (sec 3.8)
580 const uint8_t *psk; ///< the Shared Secret
581 size_t psk_len;
582 const uint8_t *real_msg; ///< RealMessage1 when the initiator signs, RealMessage2 when the responder does
583 size_t real_len;
584 const uint8_t *peer_nonce; ///< NonceRData when the initiator signs, NonceIData when the responder does
585 size_t peer_nonce_len;
586 const uint8_t *sk_p; ///< SK_pi when the initiator signs, SK_pr when the responder does
587 size_t sk_p_len;
588 uint8_t *scratch; ///< where the signed octets are assembled
589 size_t scratch_cap; ///< room there: real_len + peer_nonce_len + PROTOCORE_IKE_AUTH_LEN
590 const uint8_t *sig; ///< the signature a verify judges
591 size_t sig_len;
592 const uint8_t *priv; ///< the P-256 private scalar a sign uses
593 const uint8_t *pub; ///< the peer's P-256 public point
594 const uint8_t *rsa_n; ///< the peer's RSA modulus, 256 octets big endian
595 const uint8_t *rsa_e; ///< the peer's RSA exponent, 4 octets big endian
596} IkeAuthArgs;
597
598/** @brief The Notify payload's own fields and the COOKIE it carries (sec 3.10, sec 2.6). */
599typedef struct
600{
601 uint16_t notify_type; ///< Notify Message Type
602 uint8_t version; ///< VersionIDofSecret tagging which secret a cookie was made with
603 const uint8_t *secret; ///< the responder's current secret
604 size_t secret_len;
605 const uint8_t *ni; ///< Ni: the initiator's nonce data
606 size_t ni_len;
607 const uint8_t *ipi; ///< IPi: the initiator's source address octets
608 size_t ipi_len;
609 const uint8_t *spii; ///< SPIi: the initiator's SPI
610 const uint8_t *cookie; ///< the cookie a verify judges or a build carries
611 size_t cookie_len;
612} IkeNotifyArgs;
613
614/** @brief The Traffic Selectors a build encodes and the one a get names (RFC 7296 sec 3.13). */
615typedef struct
616{
617 const IkeTrafficSelector *sels; ///< the selectors to encode
618 uint8_t num; ///< Number of TSs
619 uint8_t index; ///< which selector a get decodes, zero based
620} IkeTsArgs;
621
622/** @brief The Configuration payload a build encodes (RFC 7296 sec 3.15). */
623typedef struct
624{
625 IkeCfgType cfg_type; ///< CFG Type
626 const IkeCfgAttr *attrs; ///< the Configuration Attributes to encode
627 uint8_t num_attrs; ///< how many
628} IkeCpArgs;
629
630/** @brief The Encrypted payload and its AEAD inputs (RFC 7296 sec 3.14, RFC 5282 sec 3, 4, 5.1). */
631typedef struct
632{
633 uint8_t *msg; ///< an SK-framed message an open verifies and decrypts in place
634 size_t msg_len; ///< octets received in it
635 const uint8_t *key; ///< the cipher key: SK_ei or SK_er, salt excluded (RFC 5282 sec 7.1)
636 const uint8_t *salt; ///< the implicit nonce half (RFC 5282 sec 4)
637 const uint8_t *iv; ///< Initialization Vector, the explicit nonce half
638 size_t iv_len; ///< its length as the negotiated transform defines it
639 const uint8_t *ct; ///< Ciphertext
640 size_t ct_len;
641 const uint8_t *icv; ///< Integrity Checksum Data
642 size_t icv_len; ///< its length as the negotiated transform defines it
643 const uint8_t *aad; ///< associated data: the header through the Encrypted payload's own header
644 size_t aad_len;
645 const uint8_t *pt; ///< the plaintext a seal encrypts
646 size_t pt_len;
647} IkeSkArgs;
648
649/** @brief The Encrypted Fragment counters and the chunk a reassembler stages (RFC 7383 sec 2.5, 2.6). */
650typedef struct
651{
652 uint16_t frag_num; ///< Fragment Number, from 1
653 uint16_t total; ///< Total Fragments
654 IkeFragReasm *reasm; ///< the reassembly a call acts on
655 const uint8_t *chunk; ///< one fragment's decrypted content
656 size_t chunk_len;
657} IkeFragArgs;
658
659/** @brief The key schedule's inputs and outputs (RFC 7296 sec 2.13, 2.14, 2.17, 2.18). */
660typedef struct
661{
662 const IkeSuite *suite; ///< the negotiated transforms a length mapping reads
663 IkeKeyLengths *lens; ///< in: the per-key lengths a derive uses; out: what suite_keylengths computed
664 IkeKeyMaterial *keys; ///< where a derive writes the seven SK_* keys
665 const uint8_t *prf_key; ///< K for a bare prf+ call
666 size_t prf_key_len;
667 const uint8_t *seed; ///< S for a bare prf+ call
668 size_t seed_len;
669 const uint8_t *dh_secret; ///< g^ir; nullptr in a Child SA derivation without a new exchange
670 size_t dh_len;
671 const uint8_t *ni; ///< Ni, stripped of its payload header
672 size_t ni_len;
673 const uint8_t *nr; ///< Nr, stripped of its payload header
674 size_t nr_len;
675 const uint8_t *spi_i; ///< SPIi of the SA being keyed
676 const uint8_t *spi_r; ///< SPIr of the SA being keyed
677 const uint8_t *sk_d; ///< SK_d: the old SA's for a rekey, this SA's for a Child SA
678 size_t sk_d_len;
679} IkeKeyArgs;
680
681/** @brief What a whole-message build stamps into the header and wraps (sec 3.1, sec 3.14). */
682typedef struct
683{
684 const uint8_t *init_spi; ///< IKE SA Initiator's SPI
685 const uint8_t *resp_spi; ///< IKE SA Responder's SPI
686 uint32_t message_id; ///< Message ID
687 proto_bool is_response; ///< set the R flag rather than the I flag
688 uint32_t length; ///< the Length a patch writes into an already-built header
689 IkePayloadType first_inner_type; ///< the Encrypted payload's Next Payload
690 const uint8_t *inner; ///< the chained inner payloads to encrypt
691 size_t inner_len;
692} IkeMsgArgs;
693
694/** @brief The walks a caller owns, so nested walks do not share one cursor (RFC 7296 sec 3.2). */
695typedef struct
696{
697 IkePayloadIter *chain; ///< the payload chain walk
698 IkeTransformIter *transforms; ///< the transform walk
699 IkeCfgAttrIter *attrs; ///< the Configuration Attribute walk
700 const IkeProposalRef *proposal; ///< the proposal a transform walk starts on
701 IkePayloadType first_type; ///< the header's Next Payload, where a chain walk starts
702} IkeWalkArgs;
703
704/** @brief The session an SA-level or handshake call acts on (RFC 7296 sec 1.2). */
705typedef struct
706{
707 IkeSa *sa; ///< the SA a post-auth exchange is protected by
708 IkeHandshake *hs; ///< the handshake a driver step advances
709 const uint8_t *our_spi; ///< the SPI this side chose
710 const uint8_t *our_nonce; ///< the nonce this side sends
711 size_t our_nonce_len;
712} IkeSessionArgs;
713
714/**
715 * @brief The IKEv2 handle (RFC 7296).
716 *
717 * A caller sets the members a call takes, invokes it through ::Ike, and reads the outcome off the
718 * same handle. Slices returned by a parse point into the caller's own buffer.
719 *
720 * No storage member: every octet, SA, handshake and reassembly a call touches belongs to the caller,
721 * so nothing survives a call.
722 *
723 * @var IkeNs::work the caller's scratch region the hash, PRF and signature calls borrow
724 * @var IkeNs::hdr in: the header a build encodes; out: the header a parse decoded (sec 3.1)
725 * @var IkeNs::out where a build, a hash or a signature writes
726 * @var IkeNs::wire the octets a parse reads
727 * @var IkeNs::pl the generic payload header a build writes, and the payload's variable field
728 * @var IkeNs::prop the Proposal Substructure a build encodes, and the SPIs a Notify or Delete names
729 * @var IkeNs::ke the key exchange: the group and the public and private values
730 * @var IkeNs::id the identity: the ID payload's fields and its signed remainder
731 * @var IkeNs::auth the Auth Method and every input the AUTH value is computed from
732 * @var IkeNs::notify the Notify payload's own fields and the COOKIE it carries
733 * @var IkeNs::ts the Traffic Selectors a build encodes and the one a get names
734 * @var IkeNs::cp the Configuration payload a build encodes
735 * @var IkeNs::sk the Encrypted payload and its AEAD inputs
736 * @var IkeNs::frag the Encrypted Fragment counters and the chunk a reassembler stages
737 * @var IkeNs::keymat the key schedule's inputs and outputs
738 * @var IkeNs::msg what a whole-message build stamps into the header and wraps
739 * @var IkeNs::walk the caller-owned chain, transform and attribute walks
740 * @var IkeNs::sess the SA or handshake a call acts on
741 *
742 * @var IkeNs::ok a call's true/false outcome
743 * @var IkeNs::n octets a build wrote or a call produced, zero on failure
744 * @var IkeNs::u8 Number of TSs a count reports (sec 3.13)
745 * @var IkeNs::payload the payload a chain walk produced
746 * @var IkeNs::proposal the first Proposal Substructure of an SA payload
747 * @var IkeNs::transform the Transform Substructure a transform walk produced
748 * @var IkeNs::sel the Traffic Selector a get decoded
749 * @var IkeNs::attr the Configuration Attribute an attribute walk produced
750 * @var IkeNs::ke_ref the decoded Key Exchange payload
751 * @var IkeNs::id_ref the decoded Identification payload
752 * @var IkeNs::auth_ref the decoded Authentication payload
753 * @var IkeNs::notify_ref the decoded Notify payload
754 * @var IkeNs::delete_ref the decoded Delete payload
755 * @var IkeNs::sk_ref the sliced Encrypted or Encrypted Fragment body
756 * @var IkeNs::cp_ref the decoded Configuration payload
757 * @var IkeNs::opened the inner payload chain an open exposed
758 * @var IkeNs::sa_init the parsed IKE_SA_INIT message
759 *
760 * @var IkeNs::hdr_build write the 28-octet IKE header from @c hdr, Length verbatim (sec 3.1)
761 * @var IkeNs::hdr_parse read the 28-octet IKE header into @c hdr (sec 3.1)
762 * @var IkeNs::set_length patch octets 24..27 of a built header to @c msg.length (sec 3.1)
763 * @var IkeNs::payload_iter_init start @c walk.chain at @c walk.first_type over @c wire (sec 3.2)
764 * @var IkeNs::payload_next read the next payload into @c payload and advance (sec 3.2)
765 * @var IkeNs::payload_build write a generic payload header and @c pl.data behind it (sec 3.2)
766 * @var IkeNs::sa_build write an SA payload carrying one proposal (sec 3.3, 3.3.1, 3.3.2)
767 * @var IkeNs::ke_build write a KE payload: @c ke.dh_group then @c pl.data (sec 3.4)
768 * @var IkeNs::nonce_build write a Nonce payload: @c pl.data is the Nonce Data (sec 3.9)
769 * @var IkeNs::id_build write an ID payload: @c id.id_type then @c pl.data (sec 3.5)
770 * @var IkeNs::auth_build write an AUTH payload: @c auth.auth_method then @c pl.data (sec 3.8)
771 * @var IkeNs::cert_build write a CERT or CERTREQ body: @c id.cert_encoding then @c pl.data (sec 3.6)
772 * @var IkeNs::notify_build write a Notify payload: @c prop SPI fields, type, @c pl.data (sec 3.10)
773 * @var IkeNs::delete_build write a Delete payload: @c prop fields then @c pl.data SPIs (sec 3.11)
774 * @var IkeNs::ts_build write a TSi or TSr payload from @c ts.sels (sec 3.13)
775 * @var IkeNs::cp_build write a CP payload: @c cp.cfg_type then its attributes (sec 3.15)
776 * @var IkeNs::sk_build lay out an SK payload: IV, Ciphertext, ICV (sec 3.14)
777 * @var IkeNs::skf_build lay out an SKF payload: the counters then IV, Ciphertext, ICV (RFC 7383 sec 2.5)
778 * @var IkeNs::skf_parse slice an SKF body into @c sk_ref (RFC 7383 sec 2.5)
779 * @var IkeNs::frag_reasm_init bind @c frag.reasm to the pool at @c out (RFC 7383 sec 2.6)
780 * @var IkeNs::frag_reasm_add stage one fragment's content (RFC 7383 sec 2.6)
781 * @var IkeNs::frag_reasm_complete every one of Total Fragments is staged (RFC 7383 sec 2.6)
782 * @var IkeNs::frag_reasm_assemble merge the staged fragments 1..Total into @c out (RFC 7383 sec 2.6)
783 * @var IkeNs::cookie_compute VersionIDofSecret | SHA-256(Ni | IPi | SPIi | secret) (sec 2.6)
784 * @var IkeNs::cookie_verify recompute that cookie and compare it in constant time (sec 2.6)
785 * @var IkeNs::cookie_notify_build write a COOKIE Notify carrying @c notify.cookie (sec 2.6)
786 * @var IkeNs::ke_parse decode a KE body into @c ke_ref (sec 3.4)
787 * @var IkeNs::id_parse decode an ID body into @c id_ref (sec 3.5)
788 * @var IkeNs::auth_parse decode an AUTH body into @c auth_ref (sec 3.8)
789 * @var IkeNs::notify_parse decode a Notify body into @c notify_ref (sec 3.10)
790 * @var IkeNs::delete_parse decode a Delete body into @c delete_ref (sec 3.11)
791 * @var IkeNs::sk_parse slice an SK body into @c sk_ref by @c sk.iv_len and @c sk.icv_len (sec 3.14)
792 * @var IkeNs::sa_first_proposal decode the first Proposal Substructure into @c proposal (sec 3.3.1)
793 * @var IkeNs::transform_iter_init start @c walk.transforms over @c walk.proposal (sec 3.3.2)
794 * @var IkeNs::transform_next read the next Transform Substructure into @c transform (sec 3.3.2)
795 * @var IkeNs::ts_count Number of TSs in a TS body, into @c u8 (sec 3.13)
796 * @var IkeNs::ts_get decode selector @c ts.index into @c sel (sec 3.13.1)
797 * @var IkeNs::cp_parse decode a CP body into @c cp_ref (sec 3.15)
798 * @var IkeNs::cp_attr_iter_init start @c walk.attrs over @c wire (sec 3.15.1)
799 * @var IkeNs::cp_attr_next read the next Configuration Attribute into @c attr (sec 3.15.1)
800 * @var IkeNs::prf_plus expand prf+(@c keymat.prf_key, @c keymat.seed) into @c out (sec 2.13)
801 * @var IkeNs::derive_keys SKEYSEED then the seven SK_* keys for a new IKE SA (sec 2.14)
802 * @var IkeNs::rekey_derive_keys the same split with SKEYSEED keyed by the old SK_d (sec 2.18)
803 * @var IkeNs::child_keymat KEYMAT = prf+(SK_d, [g^ir |] Ni | Nr) into @c out (sec 2.17)
804 * @var IkeNs::suite_keylengths map @c keymat.suite to the SK_* lengths in @c keymat.lens (sec 2.13)
805 * @var IkeNs::sa_keys_from_init compute g^ir then run the sec 2.14 schedule for @c sess.sa
806 * @var IkeNs::sk_aead_seal encrypt @c sk.pt under @c sk.key, writing Ciphertext then ICV (RFC 5282 sec 3.2)
807 * @var IkeNs::sk_aead_open verify the ICV, then decrypt into @c out (RFC 5282 sec 3.2, 5.1)
808 * @var IkeNs::dh_public our Key Exchange Data for @c ke.dh_group (RFC 8031 sec 3.1)
809 * @var IkeNs::dh_compute g^ir from @c ke.our_priv and @c ke.peer_pub (RFC 8031 sec 2)
810 * @var IkeNs::auth_psk AUTH = prf(prf(Shared Secret, pad), SignedOctets) (sec 2.15)
811 * @var IkeNs::signed_octets assemble RealMessage | Nonce | MACedID into @c auth.scratch (sec 2.15)
812 * @var IkeNs::auth_sign_ecdsa_p256 sign those octets with P-256, writing r | s to @c out (RFC 7427 sec 3)
813 * @var IkeNs::auth_verify_ecdsa_p256 verify a peer's P-256 signature over them (RFC 7427 sec 3)
814 * @var IkeNs::auth_verify_rsa_sha256 verify a peer's RSA PKCS#1 v1.5 SHA-256 signature (sec 3.8)
815 * @var IkeNs::sa_init_build build HDR, SA, KE, Nonce as one IKE_SA_INIT message (sec 1.2)
816 * @var IkeNs::sa_init_parse parse an IKE_SA_INIT message into @c sa_init (sec 1.2)
817 * @var IkeNs::auth_msg_build build HDR, SK{ @c msg.inner } for an IKE_AUTH exchange (sec 3.14)
818 * @var IkeNs::auth_msg_open verify and decrypt an SK message in place into @c opened (sec 3.14)
819 * @var IkeNs::initiator_start emit the initiator's IKE_SA_INIT request (sec 1.2)
820 * @var IkeNs::initiator_on_sa_init consume the IKE_SA_INIT response and derive the keys (sec 1.2)
821 * @var IkeNs::initiator_build_auth_psk emit SK{ IDi, AUTH } with a pre-shared key (sec 1.2, 2.15)
822 * @var IkeNs::initiator_on_auth_psk verify the responder's SK{ IDr, AUTH } (sec 1.2, 2.15)
823 * @var IkeNs::responder_on_sa_init consume an IKE_SA_INIT request and emit the response (sec 1.2)
824 * @var IkeNs::responder_on_auth_psk verify SK{ IDi, AUTH } and emit SK{ IDr, AUTH } (sec 1.2, 2.15)
825 * @var IkeNs::informational_build build an SK-protected INFORMATIONAL message (sec 1.4)
826 * @var IkeNs::informational_open verify and decrypt a received SK-protected message (sec 1.4)
827 * @var IkeNs::create_child_sa_build build an SK-protected CREATE_CHILD_SA message (sec 1.3)
828 */
829typedef struct
830{
831 uint8_t *work; ///< the caller's scratch region the hash, PRF and signature calls borrow
832 IkeHeader hdr; ///< the IKE header a build encodes and a parse decodes (sec 3.1)
833 IkeOutArgs out; ///< where a build writes
834 IkeWireArgs wire; ///< the octets a parse reads
835 IkePayloadArgs pl; ///< the generic payload header and the payload's variable field (sec 3.2)
836 IkeProposalArgs prop; ///< the proposal a build encodes and the SPIs a payload names (sec 3.3.1)
837 IkeKeArgs ke; ///< the key exchange values (sec 3.4)
838 IkeIdArgs id; ///< the identity (sec 3.5, 3.6)
839 IkeAuthArgs auth; ///< authentication inputs (sec 2.15, 3.8)
840 IkeNotifyArgs notify; ///< the Notify payload and the COOKIE (sec 3.10, 2.6)
841 IkeTsArgs ts; ///< the Traffic Selectors (sec 3.13)
842 IkeCpArgs cp; ///< the Configuration payload (sec 3.15)
843 IkeSkArgs sk; ///< the Encrypted payload and its AEAD inputs (sec 3.14)
844 IkeFragArgs frag; ///< the Encrypted Fragment counters and reassembly (RFC 7383)
845 IkeKeyArgs keymat; ///< the key schedule (sec 2.13, 2.14, 2.17, 2.18)
846 IkeMsgArgs msg; ///< whole-message assembly (sec 3.1, 3.14)
847 IkeWalkArgs walk; ///< the caller-owned walks (sec 3.2)
848 IkeSessionArgs sess; ///< the SA or handshake a call acts on (sec 1.2)
849 proto_bool ok;
850 size_t n;
851 uint8_t u8;
852 IkePayload payload;
853 IkeProposalRef proposal;
854 IkeTransformRef transform;
855 IkeTrafficSelector sel;
856 IkeCfgAttr attr;
857 IkeKeRef ke_ref;
858 IkeIdRef id_ref;
859 IkeAuthRef auth_ref;
860 IkeNotifyRef notify_ref;
861 IkeDeleteRef delete_ref;
862 IkeSkRef sk_ref;
863 IkeCpRef cp_ref;
864 IkeInnerRef opened;
865 IkeSaInitMsg sa_init;
866} IkeVars;
867
868/** @brief The operands and the outcome. */
869extern IkeVars IkeV;
870
871/** @brief The entries. */
872typedef struct
873{
874 void (*const hdr_build)(uint8_t *work);
875 void (*const hdr_parse)(uint8_t *work);
876 void (*const set_length)(uint8_t *work);
877 void (*const payload_iter_init)(uint8_t *work);
878 void (*const payload_next)(uint8_t *work);
879 void (*const payload_build)(uint8_t *work);
880 void (*const sa_build)(uint8_t *work);
881 void (*const ke_build)(uint8_t *work);
882 void (*const nonce_build)(uint8_t *work);
883 void (*const id_build)(uint8_t *work);
884 void (*const auth_build)(uint8_t *work);
885 void (*const cert_build)(uint8_t *work);
886 void (*const notify_build)(uint8_t *work);
887 void (*const delete_build)(uint8_t *work);
888 void (*const ts_build)(uint8_t *work);
889 void (*const cp_build)(uint8_t *work);
890 void (*const sk_build)(uint8_t *work);
891 void (*const skf_build)(uint8_t *work);
892 void (*const skf_parse)(uint8_t *work);
893 void (*const frag_reasm_init)(uint8_t *work);
894 void (*const frag_reasm_add)(uint8_t *work);
895 void (*const frag_reasm_complete)(uint8_t *work);
896 void (*const frag_reasm_assemble)(uint8_t *work);
897 void (*const cookie_compute)(uint8_t *work);
898 void (*const cookie_verify)(uint8_t *work);
899 void (*const cookie_notify_build)(uint8_t *work);
900 void (*const ke_parse)(uint8_t *work);
901 void (*const id_parse)(uint8_t *work);
902 void (*const auth_parse)(uint8_t *work);
903 void (*const notify_parse)(uint8_t *work);
904 void (*const delete_parse)(uint8_t *work);
905 void (*const sk_parse)(uint8_t *work);
906 void (*const sa_first_proposal)(uint8_t *work);
907 void (*const transform_iter_init)(uint8_t *work);
908 void (*const transform_next)(uint8_t *work);
909 void (*const ts_count)(uint8_t *work);
910 void (*const ts_get)(uint8_t *work);
911 void (*const cp_parse)(uint8_t *work);
912 void (*const cp_attr_iter_init)(uint8_t *work);
913 void (*const cp_attr_next)(uint8_t *work);
914 void (*const prf_plus)(uint8_t *work);
915 void (*const derive_keys)(uint8_t *work);
916 void (*const rekey_derive_keys)(uint8_t *work);
917 void (*const child_keymat)(uint8_t *work);
918 void (*const suite_keylengths)(uint8_t *work);
919 void (*const sa_keys_from_init)(uint8_t *work);
920 void (*const sk_aead_seal)(uint8_t *work);
921 void (*const sk_aead_open)(uint8_t *work);
922 void (*const dh_public)(uint8_t *work);
923 void (*const dh_compute)(uint8_t *work);
924 void (*const auth_psk)(uint8_t *work);
925 void (*const signed_octets)(uint8_t *work);
926 void (*const auth_sign_ecdsa_p256)(uint8_t *work);
927 void (*const auth_verify_ecdsa_p256)(uint8_t *work);
928 void (*const auth_verify_rsa_sha256)(uint8_t *work);
929 void (*const sa_init_build)(uint8_t *work);
930 void (*const sa_init_parse)(uint8_t *work);
931 void (*const auth_msg_build)(uint8_t *work);
932 void (*const auth_msg_open)(uint8_t *work);
933 void (*const initiator_start)(uint8_t *work);
934 void (*const initiator_on_sa_init)(uint8_t *work);
935 void (*const initiator_build_auth_psk)(uint8_t *work);
936 void (*const initiator_on_auth_psk)(uint8_t *work);
937 void (*const responder_on_sa_init)(uint8_t *work);
938 void (*const responder_on_auth_psk)(uint8_t *work);
939 void (*const informational_build)(uint8_t *work);
940 void (*const informational_open)(uint8_t *work);
941 void (*const create_child_sa_build)(uint8_t *work);
942} IkeNs;
943
944// What the table binds, defined once in the .c and taking one parameter each: everything
945// else an entry needs is an operand in IkeV or a region of the borrow at a fixed offset.
946void protocore_ike_hdr_build(uint8_t *work);
947void protocore_ike_hdr_parse(uint8_t *work);
948void protocore_ike_set_length(uint8_t *work);
949void protocore_ike_payload_iter_init(uint8_t *work);
950void protocore_ike_payload_next(uint8_t *work);
951void protocore_ike_payload_build(uint8_t *work);
952void protocore_ike_sa_build(uint8_t *work);
953void protocore_ike_ke_build(uint8_t *work);
954void protocore_ike_nonce_build(uint8_t *work);
955void protocore_ike_id_build(uint8_t *work);
956void protocore_ike_auth_build(uint8_t *work);
957void protocore_ike_cert_build(uint8_t *work);
958void protocore_ike_notify_build(uint8_t *work);
959void protocore_ike_delete_build(uint8_t *work);
960void protocore_ike_ts_build(uint8_t *work);
961void protocore_ike_cp_build(uint8_t *work);
962void protocore_ike_sk_build(uint8_t *work);
963void protocore_ike_skf_build(uint8_t *work);
964void protocore_ike_skf_parse(uint8_t *work);
965void protocore_ike_frag_reasm_init(uint8_t *work);
966void protocore_ike_frag_reasm_add(uint8_t *work);
967void protocore_ike_frag_reasm_complete(uint8_t *work);
968void protocore_ike_frag_reasm_assemble(uint8_t *work);
969void protocore_ike_cookie_compute(uint8_t *work);
970void protocore_ike_cookie_verify(uint8_t *work);
971void protocore_ike_cookie_notify_build(uint8_t *work);
972void protocore_ike_ke_parse(uint8_t *work);
973void protocore_ike_id_parse(uint8_t *work);
974void protocore_ike_auth_parse(uint8_t *work);
975void protocore_ike_notify_parse(uint8_t *work);
976void protocore_ike_delete_parse(uint8_t *work);
977void protocore_ike_sk_parse(uint8_t *work);
978void protocore_ike_sa_first_proposal(uint8_t *work);
979void protocore_ike_transform_iter_init(uint8_t *work);
980void protocore_ike_transform_next(uint8_t *work);
981void protocore_ike_ts_count(uint8_t *work);
982void protocore_ike_ts_get(uint8_t *work);
983void protocore_ike_cp_parse(uint8_t *work);
984void protocore_ike_cp_attr_iter_init(uint8_t *work);
985void protocore_ike_cp_attr_next(uint8_t *work);
986void protocore_ike_prf_plus(uint8_t *work);
987void protocore_ike_derive_keys(uint8_t *work);
988void protocore_ike_rekey_derive_keys(uint8_t *work);
989void protocore_ike_child_keymat(uint8_t *work);
990void protocore_ike_suite_keylengths(uint8_t *work);
991void protocore_ike_sa_keys_from_init(uint8_t *work);
992void protocore_ike_sk_aead_seal(uint8_t *work);
993void protocore_ike_sk_aead_open(uint8_t *work);
994void protocore_ike_dh_public(uint8_t *work);
995void protocore_ike_dh_compute(uint8_t *work);
996void protocore_ike_auth_psk(uint8_t *work);
997void protocore_ike_signed_octets(uint8_t *work);
998void protocore_ike_auth_sign_ecdsa_p256(uint8_t *work);
999void protocore_ike_auth_verify_ecdsa_p256(uint8_t *work);
1000void protocore_ike_auth_verify_rsa_sha256(uint8_t *work);
1001void protocore_ike_sa_init_build(uint8_t *work);
1002void protocore_ike_sa_init_parse(uint8_t *work);
1003void protocore_ike_auth_msg_build(uint8_t *work);
1004void protocore_ike_auth_msg_open(uint8_t *work);
1005void protocore_ike_initiator_start(uint8_t *work);
1006void protocore_ike_initiator_on_sa_init(uint8_t *work);
1007void protocore_ike_initiator_build_auth_psk(uint8_t *work);
1008void protocore_ike_initiator_on_auth_psk(uint8_t *work);
1009void protocore_ike_responder_on_sa_init(uint8_t *work);
1010void protocore_ike_responder_on_auth_psk(uint8_t *work);
1011void protocore_ike_informational_build(uint8_t *work);
1012void protocore_ike_informational_open(uint8_t *work);
1013void protocore_ike_create_child_sa_build(uint8_t *work);
1014
1015// `static const`, initialised HERE rather than `extern` against a definition in the .c: a
1016// const object whose initializer every translation unit can see is a COMPILE-TIME FACT, so
1017// `Ike.hdr_build(work)` resolves to a named function and becomes a DIRECT call. An extern table
1018// leaves the call indirect and the symbol live at every level, -O2 -flto included.
1019static const IkeNs Ike __attribute__((unused)) = {
1020 .hdr_build = protocore_ike_hdr_build,
1021 .hdr_parse = protocore_ike_hdr_parse,
1022 .set_length = protocore_ike_set_length,
1023 .payload_iter_init = protocore_ike_payload_iter_init,
1024 .payload_next = protocore_ike_payload_next,
1025 .payload_build = protocore_ike_payload_build,
1026 .sa_build = protocore_ike_sa_build,
1027 .ke_build = protocore_ike_ke_build,
1028 .nonce_build = protocore_ike_nonce_build,
1029 .id_build = protocore_ike_id_build,
1030 .auth_build = protocore_ike_auth_build,
1031 .cert_build = protocore_ike_cert_build,
1032 .notify_build = protocore_ike_notify_build,
1033 .delete_build = protocore_ike_delete_build,
1034 .ts_build = protocore_ike_ts_build,
1035 .cp_build = protocore_ike_cp_build,
1036 .sk_build = protocore_ike_sk_build,
1037 .skf_build = protocore_ike_skf_build,
1038 .skf_parse = protocore_ike_skf_parse,
1039 .frag_reasm_init = protocore_ike_frag_reasm_init,
1040 .frag_reasm_add = protocore_ike_frag_reasm_add,
1041 .frag_reasm_complete = protocore_ike_frag_reasm_complete,
1042 .frag_reasm_assemble = protocore_ike_frag_reasm_assemble,
1043 .cookie_compute = protocore_ike_cookie_compute,
1044 .cookie_verify = protocore_ike_cookie_verify,
1045 .cookie_notify_build = protocore_ike_cookie_notify_build,
1046 .ke_parse = protocore_ike_ke_parse,
1047 .id_parse = protocore_ike_id_parse,
1048 .auth_parse = protocore_ike_auth_parse,
1049 .notify_parse = protocore_ike_notify_parse,
1050 .delete_parse = protocore_ike_delete_parse,
1051 .sk_parse = protocore_ike_sk_parse,
1052 .sa_first_proposal = protocore_ike_sa_first_proposal,
1053 .transform_iter_init = protocore_ike_transform_iter_init,
1054 .transform_next = protocore_ike_transform_next,
1055 .ts_count = protocore_ike_ts_count,
1056 .ts_get = protocore_ike_ts_get,
1057 .cp_parse = protocore_ike_cp_parse,
1058 .cp_attr_iter_init = protocore_ike_cp_attr_iter_init,
1059 .cp_attr_next = protocore_ike_cp_attr_next,
1060 .prf_plus = protocore_ike_prf_plus,
1061 .derive_keys = protocore_ike_derive_keys,
1062 .rekey_derive_keys = protocore_ike_rekey_derive_keys,
1063 .child_keymat = protocore_ike_child_keymat,
1064 .suite_keylengths = protocore_ike_suite_keylengths,
1065 .sa_keys_from_init = protocore_ike_sa_keys_from_init,
1066 .sk_aead_seal = protocore_ike_sk_aead_seal,
1067 .sk_aead_open = protocore_ike_sk_aead_open,
1068 .dh_public = protocore_ike_dh_public,
1069 .dh_compute = protocore_ike_dh_compute,
1070 .auth_psk = protocore_ike_auth_psk,
1071 .signed_octets = protocore_ike_signed_octets,
1072 .auth_sign_ecdsa_p256 = protocore_ike_auth_sign_ecdsa_p256,
1073 .auth_verify_ecdsa_p256 = protocore_ike_auth_verify_ecdsa_p256,
1074 .auth_verify_rsa_sha256 = protocore_ike_auth_verify_rsa_sha256,
1075 .sa_init_build = protocore_ike_sa_init_build,
1076 .sa_init_parse = protocore_ike_sa_init_parse,
1077 .auth_msg_build = protocore_ike_auth_msg_build,
1078 .auth_msg_open = protocore_ike_auth_msg_open,
1079 .initiator_start = protocore_ike_initiator_start,
1080 .initiator_on_sa_init = protocore_ike_initiator_on_sa_init,
1081 .initiator_build_auth_psk = protocore_ike_initiator_build_auth_psk,
1082 .initiator_on_auth_psk = protocore_ike_initiator_on_auth_psk,
1083 .responder_on_sa_init = protocore_ike_responder_on_sa_init,
1084 .responder_on_auth_psk = protocore_ike_responder_on_auth_psk,
1085 .informational_build = protocore_ike_informational_build,
1086 .informational_open = protocore_ike_informational_open,
1087 .create_child_sa_build = protocore_ike_create_child_sa_build,
1088};
1089
1091
1092#endif // PROTOCORE_ENABLE_IKEV2
1093
1094#endif // PROTOCORE_IKEV2_H
#define PROTOCORE_IKE_BORROW
PROTO_ENUM_PACKED
Application protocol spoken on a listener port or connection slot.
#define PROTOCORE_BEGIN_DECLS
Give a header's declarations C linkage, so their symbol names carry no parameter types.
Definition types.h:96
_Bool proto_bool
The truth value.
Definition types.h:64
#define PROTOCORE_END_DECLS
Definition types.h:97