xref: /dpdk/lib/ipsec/crypto.h (revision 99f9d799ce21ab22e922ffec8aad51d56e24d04d)
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   * AES-GCM devices have some specific requirements for IV and AAD formats.
26   * Ideally that to be done by the driver itself.
27   */
28 
29 struct aead_gcm_iv {
30 	uint32_t salt;
31 	uint64_t iv;
32 	uint32_t cnt;
33 } __rte_packed;
34 
35 struct aead_gcm_aad {
36 	uint32_t spi;
37 	/*
38 	 * RFC 4106, section 5:
39 	 * Two formats of the AAD are defined:
40 	 * one for 32-bit sequence numbers, and one for 64-bit ESN.
41 	 */
42 	union {
43 		uint32_t u32[2];
44 		uint64_t u64;
45 	} sqn;
46 	uint32_t align0; /* align to 16B boundary */
47 } __rte_packed;
48 
49 struct gcm_esph_iv {
50 	struct rte_esp_hdr esph;
51 	uint64_t iv;
52 } __rte_packed;
53 
54 static inline void
55 aes_ctr_cnt_blk_fill(struct aesctr_cnt_blk *ctr, uint64_t iv, uint32_t nonce)
56 {
57 	ctr->nonce = nonce;
58 	ctr->iv = iv;
59 	ctr->cnt = rte_cpu_to_be_32(1);
60 }
61 
62 static inline void
63 aead_gcm_iv_fill(struct aead_gcm_iv *gcm, uint64_t iv, uint32_t salt)
64 {
65 	gcm->salt = salt;
66 	gcm->iv = iv;
67 	gcm->cnt = rte_cpu_to_be_32(1);
68 }
69 
70 /*
71  * RFC 4106, 5 AAD Construction
72  * spi and sqn should already be converted into network byte order.
73  * Make sure that not used bytes are zeroed.
74  */
75 static inline void
76 aead_gcm_aad_fill(struct aead_gcm_aad *aad, rte_be32_t spi, rte_be64_t sqn,
77 	int esn)
78 {
79 	aad->spi = spi;
80 	if (esn)
81 		aad->sqn.u64 = sqn;
82 	else {
83 		aad->sqn.u32[0] = sqn_low32(sqn);
84 		aad->sqn.u32[1] = 0;
85 	}
86 	aad->align0 = 0;
87 }
88 
89 static inline void
90 gen_iv(uint64_t iv[IPSEC_MAX_IV_QWORD], rte_be64_t sqn)
91 {
92 	iv[0] = sqn;
93 	iv[1] = 0;
94 }
95 
96 /*
97  * Helper routine to copy IV
98  * Right now we support only algorithms with IV length equals 0/8/16 bytes.
99  */
100 static inline void
101 copy_iv(uint64_t dst[IPSEC_MAX_IV_QWORD],
102 	const uint64_t src[IPSEC_MAX_IV_QWORD], uint32_t len)
103 {
104 	RTE_BUILD_BUG_ON(IPSEC_MAX_IV_SIZE != 2 * sizeof(uint64_t));
105 
106 	switch (len) {
107 	case IPSEC_MAX_IV_SIZE:
108 		dst[1] = src[1];
109 		/* fallthrough */
110 	case sizeof(uint64_t):
111 		dst[0] = src[0];
112 		/* fallthrough */
113 	case 0:
114 		break;
115 	default:
116 		/* should never happen */
117 		RTE_ASSERT(NULL);
118 	}
119 }
120 
121 /*
122  * from RFC 4303 3.3.2.1.4:
123  * If the ESN option is enabled for the SA, the high-order 32
124  * bits of the sequence number are appended after the Next Header field
125  * for purposes of this computation, but are not transmitted.
126  */
127 
128 /*
129  * Helper function that moves ICV by 4B below, and inserts SQN.hibits.
130  * icv parameter points to the new start of ICV.
131  */
132 static inline void
133 insert_sqh(uint32_t sqh, void *picv, uint32_t icv_len)
134 {
135 	uint32_t *icv;
136 	int32_t i;
137 
138 	RTE_ASSERT(icv_len % sizeof(uint32_t) == 0);
139 
140 	icv = picv;
141 	icv_len = icv_len / sizeof(uint32_t);
142 	for (i = icv_len; i-- != 0; icv[i] = icv[i - 1])
143 		;
144 
145 	icv[i] = sqh;
146 }
147 
148 /*
149  * Helper function that moves ICV by 4B up, and removes SQN.hibits.
150  * icv parameter points to the new start of ICV.
151  */
152 static inline void
153 remove_sqh(void *picv, uint32_t icv_len)
154 {
155 	uint32_t i, *icv;
156 
157 	RTE_ASSERT(icv_len % sizeof(uint32_t) == 0);
158 
159 	icv = picv;
160 	icv_len = icv_len / sizeof(uint32_t);
161 	for (i = 0; i != icv_len; i++)
162 		icv[i] = icv[i + 1];
163 }
164 
165 /*
166  * setup crypto ops for LOOKASIDE_NONE (pure crypto) type of devices.
167  */
168 static inline void
169 lksd_none_cop_prepare(struct rte_crypto_op *cop,
170 	struct rte_cryptodev_sym_session *cs, struct rte_mbuf *mb)
171 {
172 	struct rte_crypto_sym_op *sop;
173 
174 	sop = cop->sym;
175 	cop->type = RTE_CRYPTO_OP_TYPE_SYMMETRIC;
176 	cop->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;
177 	cop->sess_type = RTE_CRYPTO_OP_WITH_SESSION;
178 	sop->m_src = mb;
179 	__rte_crypto_sym_op_attach_sym_session(sop, cs);
180 }
181 
182 #endif /* _CRYPTO_H_ */
183