1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2018 Intel Corporation
3 */
4
5 #ifndef _CRYPTO_H_
6 #define _CRYPTO_H_
7
8 /**
9 * @file crypto.h
10 * Contains crypto specific functions/structures/macros used internally
11 * by ipsec library.
12 */
13
14 /*
15 * AES-CTR counter block format.
16 */
17
18 struct aesctr_cnt_blk {
19 uint32_t nonce;
20 uint64_t iv;
21 uint32_t cnt;
22 } __rte_packed;
23
24 /*
25 * CHACHA20-POLY1305 devices have some specific requirements
26 * for IV and AAD formats.
27 * Ideally that to be done by the driver itself.
28 */
29
30 struct aead_chacha20_poly1305_iv {
31 uint32_t salt;
32 uint64_t iv;
33 uint32_t cnt;
34 } __rte_packed;
35
36 struct aead_chacha20_poly1305_aad {
37 uint32_t spi;
38 /*
39 * RFC 4106, section 5:
40 * Two formats of the AAD are defined:
41 * one for 32-bit sequence numbers, and one for 64-bit ESN.
42 */
43 union {
44 uint32_t u32[2];
45 uint64_t u64;
46 } sqn;
47 uint32_t align0; /* align to 16B boundary */
48 } __rte_packed;
49
50 struct chacha20_poly1305_esph_iv {
51 struct rte_esp_hdr esph;
52 uint64_t iv;
53 } __rte_packed;
54
55 /*
56 * AES-GCM devices have some specific requirements for IV and AAD formats.
57 * Ideally that to be done by the driver itself.
58 */
59
60 struct aead_gcm_iv {
61 uint32_t salt;
62 uint64_t iv;
63 uint32_t cnt;
64 } __rte_packed;
65
66 struct aead_gcm_aad {
67 uint32_t spi;
68 /*
69 * RFC 4106, section 5:
70 * Two formats of the AAD are defined:
71 * one for 32-bit sequence numbers, and one for 64-bit ESN.
72 */
73 union {
74 uint32_t u32[2];
75 uint64_t u64;
76 } sqn;
77 uint32_t align0; /* align to 16B boundary */
78 } __rte_packed;
79
80 struct gcm_esph_iv {
81 struct rte_esp_hdr esph;
82 uint64_t iv;
83 } __rte_packed;
84
85 /*
86 * AES-CCM devices have some specific requirements for IV and AAD formats.
87 * Ideally that to be done by the driver itself.
88 */
89 union aead_ccm_salt {
90 uint32_t salt;
91 struct inner {
92 uint8_t salt8[3];
93 uint8_t ccm_flags;
94 } inner;
95 } __rte_packed;
96
97
98 struct aead_ccm_iv {
99 uint8_t ccm_flags;
100 uint8_t salt[3];
101 uint64_t iv;
102 uint32_t cnt;
103 } __rte_packed;
104
105 struct aead_ccm_aad {
106 uint8_t padding[18];
107 uint32_t spi;
108 /*
109 * RFC 4309, section 5:
110 * Two formats of the AAD are defined:
111 * one for 32-bit sequence numbers, and one for 64-bit ESN.
112 */
113 union {
114 uint32_t u32[2];
115 uint64_t u64;
116 } sqn;
117 uint32_t align0; /* align to 16B boundary */
118 } __rte_packed;
119
120 struct ccm_esph_iv {
121 struct rte_esp_hdr esph;
122 uint64_t iv;
123 } __rte_packed;
124
125
126 static inline void
aes_ctr_cnt_blk_fill(struct aesctr_cnt_blk * ctr,uint64_t iv,uint32_t nonce)127 aes_ctr_cnt_blk_fill(struct aesctr_cnt_blk *ctr, uint64_t iv, uint32_t nonce)
128 {
129 ctr->nonce = nonce;
130 ctr->iv = iv;
131 ctr->cnt = rte_cpu_to_be_32(1);
132 }
133
134 static inline void
aead_chacha20_poly1305_iv_fill(struct aead_chacha20_poly1305_iv * chacha20_poly1305,uint64_t iv,uint32_t salt)135 aead_chacha20_poly1305_iv_fill(struct aead_chacha20_poly1305_iv
136 *chacha20_poly1305,
137 uint64_t iv, uint32_t salt)
138 {
139 chacha20_poly1305->salt = salt;
140 chacha20_poly1305->iv = iv;
141 chacha20_poly1305->cnt = rte_cpu_to_be_32(1);
142 }
143
144 static inline void
aead_gcm_iv_fill(struct aead_gcm_iv * gcm,uint64_t iv,uint32_t salt)145 aead_gcm_iv_fill(struct aead_gcm_iv *gcm, uint64_t iv, uint32_t salt)
146 {
147 gcm->salt = salt;
148 gcm->iv = iv;
149 gcm->cnt = rte_cpu_to_be_32(1);
150 }
151
152 static inline void
aead_ccm_iv_fill(struct aead_ccm_iv * ccm,uint64_t iv,uint32_t salt)153 aead_ccm_iv_fill(struct aead_ccm_iv *ccm, uint64_t iv, uint32_t salt)
154 {
155 union aead_ccm_salt tsalt;
156
157 tsalt.salt = salt;
158 ccm->ccm_flags = tsalt.inner.ccm_flags;
159 ccm->salt[0] = tsalt.inner.salt8[0];
160 ccm->salt[1] = tsalt.inner.salt8[1];
161 ccm->salt[2] = tsalt.inner.salt8[2];
162 ccm->iv = iv;
163 ccm->cnt = rte_cpu_to_be_32(1);
164 }
165
166
167 /*
168 * RFC 4106, 5 AAD Construction
169 * spi and sqn should already be converted into network byte order.
170 * Make sure that not used bytes are zeroed.
171 */
172 static inline void
aead_gcm_aad_fill(struct aead_gcm_aad * aad,rte_be32_t spi,rte_be64_t sqn,int esn)173 aead_gcm_aad_fill(struct aead_gcm_aad *aad, rte_be32_t spi, rte_be64_t sqn,
174 int esn)
175 {
176 aad->spi = spi;
177 if (esn)
178 aad->sqn.u64 = sqn;
179 else {
180 aad->sqn.u32[0] = sqn_low32(sqn);
181 aad->sqn.u32[1] = 0;
182 }
183 aad->align0 = 0;
184 }
185
186 /*
187 * RFC 4309, 5 AAD Construction
188 * spi and sqn should already be converted into network byte order.
189 * Make sure that not used bytes are zeroed.
190 */
191 static inline void
aead_ccm_aad_fill(struct aead_ccm_aad * aad,rte_be32_t spi,rte_be64_t sqn,int esn)192 aead_ccm_aad_fill(struct aead_ccm_aad *aad, rte_be32_t spi, rte_be64_t sqn,
193 int esn)
194 {
195 aad->spi = spi;
196 if (esn)
197 aad->sqn.u64 = sqn;
198 else {
199 aad->sqn.u32[0] = sqn_low32(sqn);
200 aad->sqn.u32[1] = 0;
201 }
202 aad->align0 = 0;
203 }
204
205 static inline void
gen_iv(uint64_t iv[IPSEC_MAX_IV_QWORD],rte_be64_t sqn)206 gen_iv(uint64_t iv[IPSEC_MAX_IV_QWORD], rte_be64_t sqn)
207 {
208 iv[0] = sqn;
209 iv[1] = 0;
210 }
211
212
213 /*
214 * RFC 7634, 2.1 AAD Construction
215 * spi and sqn should already be converted into network byte order.
216 * Make sure that not used bytes are zeroed.
217 */
218 static inline void
aead_chacha20_poly1305_aad_fill(struct aead_chacha20_poly1305_aad * aad,rte_be32_t spi,rte_be64_t sqn,int esn)219 aead_chacha20_poly1305_aad_fill(struct aead_chacha20_poly1305_aad *aad,
220 rte_be32_t spi, rte_be64_t sqn,
221 int esn)
222 {
223 aad->spi = spi;
224 if (esn)
225 aad->sqn.u64 = sqn;
226 else {
227 aad->sqn.u32[0] = sqn_low32(sqn);
228 aad->sqn.u32[1] = 0;
229 }
230 aad->align0 = 0;
231 }
232
233 /*
234 * Helper routine to copy IV
235 * Right now we support only algorithms with IV length equals 0/8/16 bytes.
236 */
237 static inline void
copy_iv(uint64_t dst[IPSEC_MAX_IV_QWORD],const uint64_t src[IPSEC_MAX_IV_QWORD],uint32_t len)238 copy_iv(uint64_t dst[IPSEC_MAX_IV_QWORD],
239 const uint64_t src[IPSEC_MAX_IV_QWORD], uint32_t len)
240 {
241 RTE_BUILD_BUG_ON(IPSEC_MAX_IV_SIZE != 2 * sizeof(uint64_t));
242
243 switch (len) {
244 case IPSEC_MAX_IV_SIZE:
245 dst[1] = src[1];
246 /* fallthrough */
247 case sizeof(uint64_t):
248 dst[0] = src[0];
249 /* fallthrough */
250 case 0:
251 break;
252 default:
253 /* should never happen */
254 RTE_ASSERT(NULL);
255 }
256 }
257
258 /*
259 * from RFC 4303 3.3.2.1.4:
260 * If the ESN option is enabled for the SA, the high-order 32
261 * bits of the sequence number are appended after the Next Header field
262 * for purposes of this computation, but are not transmitted.
263 */
264
265 /*
266 * Helper function that moves ICV by 4B below, and inserts SQN.hibits.
267 * icv parameter points to the new start of ICV.
268 */
269 static inline void
insert_sqh(uint32_t sqh,void * picv,uint32_t icv_len)270 insert_sqh(uint32_t sqh, void *picv, uint32_t icv_len)
271 {
272 uint32_t *icv;
273 int32_t i;
274
275 RTE_ASSERT(icv_len % sizeof(uint32_t) == 0);
276
277 icv = picv;
278 icv_len = icv_len / sizeof(uint32_t);
279 for (i = icv_len; i-- != 0; icv[i] = icv[i - 1])
280 ;
281
282 icv[i] = sqh;
283 }
284
285 /*
286 * Helper function that moves ICV by 4B up, and removes SQN.hibits.
287 * icv parameter points to the new start of ICV.
288 */
289 static inline void
remove_sqh(void * picv,uint32_t icv_len)290 remove_sqh(void *picv, uint32_t icv_len)
291 {
292 uint32_t i, *icv;
293
294 RTE_ASSERT(icv_len % sizeof(uint32_t) == 0);
295
296 icv = picv;
297 icv_len = icv_len / sizeof(uint32_t);
298 for (i = 0; i != icv_len; i++)
299 icv[i] = icv[i + 1];
300 }
301
302 /*
303 * setup crypto ops for LOOKASIDE_NONE (pure crypto) type of devices.
304 */
305 static inline void
lksd_none_cop_prepare(struct rte_crypto_op * cop,struct rte_cryptodev_sym_session * cs,struct rte_mbuf * mb)306 lksd_none_cop_prepare(struct rte_crypto_op *cop,
307 struct rte_cryptodev_sym_session *cs, struct rte_mbuf *mb)
308 {
309 struct rte_crypto_sym_op *sop;
310
311 sop = cop->sym;
312 cop->type = RTE_CRYPTO_OP_TYPE_SYMMETRIC;
313 cop->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;
314 cop->sess_type = RTE_CRYPTO_OP_WITH_SESSION;
315 sop->m_src = mb;
316 __rte_crypto_sym_op_attach_sym_session(sop, cs);
317 }
318
319 #endif /* _CRYPTO_H_ */
320