1/*
2 * Copyright (c) 2026 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28#ifndef _IPSEC_OFFLOAD_H_
29#define _IPSEC_OFFLOAD_H_
30
31#ifdef __cplusplus
32extern "C" {
33#endif
34
35#include <stdint.h>
36
37/* Increase if ABI-breaking changes are added */
38#define IPSEC_OFFLOAD_KPI_VERSION 2
39
40/* Protocol / mode */
41typedef enum ipsec_offload_proto {
42 IPSEC_OFFLOAD_PROTO_ESP = 50,
43 IPSEC_OFFLOAD_PROTO_AH = 51
44} ipsec_offload_proto_t;
45
46typedef enum ipsec_offload_mode {
47 IPSEC_OFFLOAD_MODE_TRANSPORT = 0,
48 IPSEC_OFFLOAD_MODE_TUNNEL = 1
49} ipsec_offload_mode_t;
50
51/* Direction type for SA and policy */
52typedef enum ipsec_offload_dir {
53 IPSEC_OFFLOAD_DIR_IN = 1, /* inbound/receive */
54 IPSEC_OFFLOAD_DIR_OUT = 2, /* outbound/transmit */
55 IPSEC_OFFLOAD_DIR_FWD = 3 /* forward (optional) */
56} ipsec_offload_dir_t;
57
58/*
59 * Policy action. The kernel asks the driver to install one rule per
60 * policy; this tells the driver whether to encrypt/decrypt (ALLOW) or
61 * to drop matching packets in hardware (DISCARD). The two map directly
62 * to PF_KEY's IPSEC_POLICY_IPSEC and IPSEC_POLICY_DISCARD respectively.
63 * BYPASS/NONE policies don't need driver-side state and are not
64 * offloaded.
65 */
66typedef enum ipsec_offload_action {
67 IPSEC_OFFLOAD_ACTION_ALLOW = 1, /* apply IPsec (encrypt/decrypt) */
68 IPSEC_OFFLOAD_ACTION_DISCARD = 2, /* drop matching packets in HW */
69} ipsec_offload_action_t;
70
71/* Algorithm definitions taken from <net/pfkeyv2.h> */
72/* RFC2367 numbers - meets RFC2407 */
73#define IPSEC_OFFLOAD_AALG_NONE 0
74#define IPSEC_OFFLOAD_AALG_MD5HMAC 1 /*2*/
75#define IPSEC_OFFLOAD_AALG_SHA1HMAC 2 /*3*/
76#define IPSEC_OFFLOAD_AALG_MAX 8
77/* private allocations - based on RFC2407/IANA assignment */
78#define IPSEC_OFFLOAD_X_AALG_SHA2_256 6 /*5*/
79#define IPSEC_OFFLOAD_X_AALG_SHA2_384 7 /*6*/
80#define IPSEC_OFFLOAD_X_AALG_SHA2_512 8 /*7*/
81/* private allocations should use 249-255 (RFC2407) */
82#define IPSEC_OFFLOAD_X_AALG_MD5 3 /*249*/ /* Keyed MD5, not implemented */
83#define IPSEC_OFFLOAD_X_AALG_SHA 4 /*250*/ /* Keyed SHA, not implemented */
84#define IPSEC_OFFLOAD_X_AALG_NULL 5 /*251*/ /* null authentication */
85
86/* RFC2367 numbers - meets RFC2407 */
87#define IPSEC_OFFLOAD_EALG_NONE 0
88#define IPSEC_OFFLOAD_EALG_DESCBC 1 /*2*/
89#define IPSEC_OFFLOAD_EALG_3DESCBC 2 /*3*/
90#define IPSEC_OFFLOAD_EALG_NULL 3 /*11*/
91#define IPSEC_OFFLOAD_EALG_MAX 12
92/* private allocations - based on RFC2407/IANA assignment */
93#define IPSEC_OFFLOAD_X_EALG_CAST128CBC 5 /*6*/
94#define IPSEC_OFFLOAD_X_EALG_BLOWFISHCBC 4 /*7*/
95#define IPSEC_OFFLOAD_X_EALG_RIJNDAELCBC 12
96#define IPSEC_OFFLOAD_X_EALG_AESCBC 12
97#define IPSEC_OFFLOAD_X_EALG_AES 12
98#define IPSEC_OFFLOAD_X_EALG_AES_GCM 13
99#define IPSEC_OFFLOAD_X_EALG_CHACHA20POLY1305 14
100#define IPSEC_OFFLOAD_X_EALG_AES_GMAC 15
101/* private allocations should use 249-255 (RFC2407) */
102
103/*
104 * Keying material
105 *
106 * Keys are stored inline in fixed-size arrays. key_enc_key_len and
107 * key_auth_key_len indicate the valid bytes; unused trailing bytes
108 * are zeroed. Maximum supported key length is IPSEC_OFFLOAD_MAX_KEY_LEN.
109 *
110 * AEAD (e.g. AES-GCM, ChaCha20-Poly1305, AES-GMAC):
111 * key_aead_alg != 0; key_enc_alg = key_auth_alg = 0.
112 * key_enc_key/key_enc_key_len = AEAD key (16 or 32 bytes, excludes salt).
113 * key_auth_key/key_auth_key_len = unused (0).
114 * key_salt = per-SA AEAD salt (4 bytes, extracted from raw key material).
115 * key_icv_len = authentication tag length in bytes (e.g. 16 for AES-GCM-16);
116 * derived from algorithm, not independently configurable.
117 *
118 * Non-AEAD:
119 * key_aead_alg = 0.
120 * key_enc_alg = IPSEC_OFFLOAD_EALG_* or IPSEC_OFFLOAD_X_EALG_* (0 if AH-only).
121 * key_auth_alg = IPSEC_OFFLOAD_AALG_* or IPSEC_OFFLOAD_X_AALG_* (0 if none).
122 * key_enc_key/key_auth_key populated as applicable; key_salt typically 0.
123 * key_icv_len = MAC/ICV truncation length in bytes (0 = algorithm default);
124 * derived from algorithm, not independently configurable.
125 */
126#define IPSEC_OFFLOAD_MAX_KEY_LEN 64
127
128typedef struct ipsec_offload_keymat {
129 uint16_t key_aead_alg;
130 uint16_t key_enc_alg;
131 uint16_t key_auth_alg;
132 uint8_t key_enc_key[IPSEC_OFFLOAD_MAX_KEY_LEN];
133 uint16_t key_enc_key_len;
134 uint8_t key_auth_key[IPSEC_OFFLOAD_MAX_KEY_LEN];
135 uint16_t key_auth_key_len;
136 uint8_t __reserved[2]; /* explicit padding so key_salt is
137 * 4-byte aligned in the wire layout */
138 uint32_t key_salt;
139 uint16_t key_icv_len;
140} ipsec_offload_keymat_t;
141
142/* IP version */
143typedef enum ipsec_offload_ip_version {
144 IPSEC_OFFLOAD_IPV4 = 4,
145 IPSEC_OFFLOAD_IPV6 = 6
146} ipsec_offload_ip_version_t;
147
148/*
149 * L4 protocol values for ipsec_offload_selector.sel_transport
150 * 0 means "wildcard / no L4 match".
151 */
152typedef enum ipsec_offload_transport {
153 IPSEC_OFFLOAD_L4_ANY = 0, /* no L4 match */
154 IPSEC_OFFLOAD_L4_TCP = 6, /* TCP */
155 IPSEC_OFFLOAD_L4_UDP = 17, /* UDP */
156} ipsec_offload_transport_t;
157
158/* Selector for packet offload classification (inner flow) */
159typedef struct ipsec_offload_selector {
160 ipsec_offload_ip_version_t sel_ip_version; /* IP version */
161 uint8_t sel_src[16]; /* source address, network order */
162 uint8_t sel_dst[16]; /* destination address, network order */
163 uint8_t sel_src_prefix; /* 32/128 for exact */
164 uint8_t sel_dst_prefix; /* 32/128 for exact */
165 ipsec_offload_transport_t sel_transport; /* transport proto */
166 uint16_t sel_src_port; /* source port, network order */
167 uint16_t sel_dst_port; /* destination port, network order */
168} ipsec_offload_selector_t;
169
170/* Optional outer tunnel endpoints (used if mode == TUNNEL) */
171typedef struct ipsec_offload_tunnel {
172 ipsec_offload_ip_version_t tun_ip_version; /* IP version */
173 uint8_t tun_src[16]; /* outer source IP, network order */
174 uint8_t tun_dst[16]; /* outer destination IP, network order */
175 uint8_t tun_hop_limit; /* 0 = stack default */
176} ipsec_offload_tunnel_t;
177
178/* SA flags (bitfield) */
179typedef enum ipsec_offload_sa_flags {
180 IPSEC_OFFLOAD_SA_F_ESN = 1u << 0 /* Extended Sequence Numbers */
181} ipsec_offload_sa_flags_t;
182
183/* SA programming (used by crypto + packet offload) */
184typedef struct ipsec_offload_sa {
185 uint32_t sa_flags; /* ipsec_offload_sa_flags_t */
186 uint32_t sa_spi; /* SPI (network order) */
187 ipsec_offload_proto_t sa_proto; /* ESP / AH */
188 ipsec_offload_mode_t sa_mode; /* Transport / Tunnel */
189 ipsec_offload_dir_t sa_dir; /* IN / OUT / FWD */
190 ipsec_offload_selector_t sa_selector; /* SA src/dst addresses, plus
191 * optional transport proto +
192 * src/dst ports. Prefix
193 * lengths are 32 (IPv4) or
194 * 128 (IPv6) — SAs match by
195 * exact host addresses.
196 * Transport / ports default
197 * to ANY / 0 if userspace did
198 * not specify them. */
199 ipsec_offload_keymat_t sa_keys; /* Keying material */
200 uint32_t sa_replay_win; /* anti-replay window size in bytes
201 * (e.g. 4/8/16/32 for 32/64/128/256-bit
202 * windows); 0 = disabled.
203 * Driver should reject unsupported sizes. */
204 uint32_t sa_reqid; /* Optional binding hint, 0 = unused */
205 ipsec_offload_tunnel_t sa_tunnel; /* valid if mode == TUNNEL */
206} ipsec_offload_sa_t;
207
208/* Policy classifier (packet offload) */
209typedef struct ipsec_offload_policy {
210 ipsec_offload_dir_t pol_dir; /* IN / OUT / FWD */
211 ipsec_offload_action_t pol_action; /* ALLOW = apply IPsec via the
212 * bound SA; DISCARD = HW drops
213 * matching packets. */
214 ipsec_offload_selector_t pol_sel; /* flow match */
215
216 /* Optional binding choices (driver may use either if provided): */
217 uint32_t pol_reqid; /* binding hint; 0 = unused */
218 uint64_t pol_sa_handle; /* direct SA cookie; 0 = resolve via reqid/SPI/etc. */
219} ipsec_offload_policy_t;
220
221
222#ifdef __cplusplus
223}
224#endif
225#endif /* _IPSEC_OFFLOAD_H_ */