1.. SPDX-License-Identifier: BSD-3-Clause 2 Copyright(c) 2018 Intel Corporation. 3 4IPsec Packet Processing Library 5=============================== 6 7DPDK provides a library for IPsec data-path processing. 8The library utilizes the existing DPDK crypto-dev and 9security API to provide the application with a transparent and 10high performant IPsec packet processing API. 11The library is concentrated on data-path protocols processing 12(ESP and AH), IKE protocol(s) implementation is out of scope 13for this library. 14 15SA level API 16------------ 17 18This API operates on the IPsec Security Association (SA) level. 19It provides functionality that allows user for given SA to process 20inbound and outbound IPsec packets. 21 22To be more specific: 23 24* for inbound ESP/AH packets perform decryption, authentication, integrity checking, remove ESP/AH related headers 25* for outbound packets perform payload encryption, attach ICV, update/add IP headers, add ESP/AH headers/trailers, 26* setup related mbuf fields (ol_flags, tx_offloads, etc.). 27* initialize/un-initialize given SA based on user provided parameters. 28 29The SA level API is based on top of crypto-dev/security API and relies on 30them to perform actual cipher and integrity checking. 31 32Due to the nature of the crypto-dev API (enqueue/dequeue model) the library 33introduces an asynchronous API for IPsec packets destined to be processed by 34the crypto-device. 35 36The expected API call sequence for data-path processing would be: 37 38.. code-block:: c 39 40 /* enqueue for processing by crypto-device */ 41 rte_ipsec_pkt_crypto_prepare(...); 42 rte_cryptodev_enqueue_burst(...); 43 /* dequeue from crypto-device and do final processing (if any) */ 44 rte_cryptodev_dequeue_burst(...); 45 rte_ipsec_pkt_crypto_group(...); /* optional */ 46 rte_ipsec_pkt_process(...); 47 48For packets destined for inline processing no extra overhead 49is required and the synchronous API call: rte_ipsec_pkt_process() 50is sufficient for that case. 51 52.. note:: 53 54 For more details about the IPsec API, please refer to the *DPDK API Reference*. 55 56The current implementation supports all four currently defined 57rte_security types: 58 59RTE_SECURITY_ACTION_TYPE_NONE 60~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 61 62In that mode the library functions perform 63 64* for inbound packets: 65 66 - check SQN 67 - prepare *rte_crypto_op* structure for each input packet 68 - verify that integrity check and decryption performed by crypto device 69 completed successfully 70 - check padding data 71 - remove outer IP header (tunnel mode) / update IP header (transport mode) 72 - remove ESP header and trailer, padding, IV and ICV data 73 - update SA replay window 74 75* for outbound packets: 76 77 - generate SQN and IV 78 - add outer IP header (tunnel mode) / update IP header (transport mode) 79 - add ESP header and trailer, padding and IV data 80 - prepare *rte_crypto_op* structure for each input packet 81 - verify that crypto device operations (encryption, ICV generation) 82 were completed successfully 83 84RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO 85~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 86 87In that mode the library functions perform 88 89* for inbound packets: 90 91 - verify that integrity check and decryption performed by *rte_security* 92 device completed successfully 93 - check SQN 94 - check padding data 95 - remove outer IP header (tunnel mode) / update IP header (transport mode) 96 - remove ESP header and trailer, padding, IV and ICV data 97 - update SA replay window 98 99* for outbound packets: 100 101 - generate SQN and IV 102 - add outer IP header (tunnel mode) / update IP header (transport mode) 103 - add ESP header and trailer, padding and IV data 104 - update *ol_flags* inside *struct rte_mbuf* to indicate that 105 inline-crypto processing has to be performed by HW on this packet 106 - invoke *rte_security* device specific *set_pkt_metadata()* to associate 107 security device specific data with the packet 108 109RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL 110~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 111 112In that mode the library functions perform 113 114* for inbound packets: 115 116 - verify that integrity check and decryption performed by *rte_security* 117 device completed successfully 118 119* for outbound packets: 120 121 - update *ol_flags* inside *struct rte_mbuf* to indicate that 122 inline-crypto processing has to be performed by HW on this packet 123 - invoke *rte_security* device specific *set_pkt_metadata()* to associate 124 security device specific data with the packet 125 126RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL 127~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 128 129In that mode the library functions perform 130 131* for inbound packets: 132 133 - prepare *rte_crypto_op* structure for each input packet 134 - verify that integrity check and decryption performed by crypto device 135 completed successfully 136 137* for outbound packets: 138 139 - prepare *rte_crypto_op* structure for each input packet 140 - verify that crypto device operations (encryption, ICV generation) 141 were completed successfully 142 143To accommodate future custom implementations function pointers 144model is used for both *crypto_prepare* and *process* implementations. 145 146SA database API 147---------------- 148 149SA database(SAD) is a table with <key, value> pairs. 150 151Value is an opaque user provided pointer to the user defined SA data structure. 152 153According to RFC4301 each SA can be uniquely identified by a key 154which is either: 155 156 - security parameter index(SPI) 157 - or SPI and destination IP(DIP) 158 - or SPI, DIP and source IP(SIP) 159 160In case of multiple matches, longest matching key will be returned. 161 162Create/destroy 163~~~~~~~~~~~~~~ 164 165librte_ipsec SAD implementation provides ability to create/destroy SAD tables. 166 167To create SAD table user has to specify how many entries of each key type is 168required and IP protocol type (IPv4/IPv6). 169As an example: 170 171 172.. code-block:: c 173 174 struct rte_ipsec_sad *sad; 175 struct rte_ipsec_sad_conf conf; 176 177 conf.socket_id = -1; 178 conf.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = some_nb_rules_spi_only; 179 conf.max_sa[RTE_IPSEC_SAD_SPI_DIP] = some_nb_rules_spi_dip; 180 conf.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = some_nb_rules_spi_dip_sip; 181 conf.flags = RTE_IPSEC_SAD_FLAG_RW_CONCURRENCY; 182 183 sad = rte_ipsec_sad_create("test", &conf); 184 185.. note:: 186 187 for more information please refer to ipsec library API reference 188 189Add/delete rules 190~~~~~~~~~~~~~~~~ 191 192Library also provides methods to add or delete key/value pairs from the SAD. 193To add user has to specify key, key type and a value which is an opaque pointer to SA. 194The key type reflects a set of tuple fields that will be used for lookup of the SA. 195As mentioned above there are 3 types of a key and the representation of a key type is: 196 197.. code-block:: c 198 199 RTE_IPSEC_SAD_SPI_ONLY, 200 RTE_IPSEC_SAD_SPI_DIP, 201 RTE_IPSEC_SAD_SPI_DIP_SIP, 202 203As an example, to add new entry into the SAD for IPv4 addresses: 204 205.. code-block:: c 206 207 struct rte_ipsec_sa *sa; 208 union rte_ipsec_sad_key key; 209 210 key.v4.spi = rte_cpu_to_be_32(spi_val); 211 if (key_type >= RTE_IPSEC_SAD_SPI_DIP) /* DIP is optional*/ 212 key.v4.dip = rte_cpu_to_be_32(dip_val); 213 if (key_type == RTE_IPSEC_SAD_SPI_DIP_SIP) /* SIP is optional*/ 214 key.v4.sip = rte_cpu_to_be_32(sip_val); 215 216 rte_ipsec_sad_add(sad, &key, key_type, sa); 217 218.. note:: 219 220 By performance reason it is better to keep spi/dip/sip in net byte order 221 to eliminate byteswap on lookup 222 223To delete user has to specify key and key type. 224 225Delete code would look like: 226 227.. code-block:: c 228 229 union rte_ipsec_sad_key key; 230 231 key.v4.spi = rte_cpu_to_be_32(necessary_spi); 232 if (key_type >= RTE_IPSEC_SAD_SPI_DIP) /* DIP is optional*/ 233 key.v4.dip = rte_cpu_to_be_32(necessary_dip); 234 if (key_type == RTE_IPSEC_SAD_SPI_DIP_SIP) /* SIP is optional*/ 235 key.v4.sip = rte_cpu_to_be_32(necessary_sip); 236 237 rte_ipsec_sad_del(sad, &key, key_type); 238 239 240Lookup 241~~~~~~ 242Library provides lookup by the given {SPI,DIP,SIP} tuple of 243inbound ipsec packet as a key. 244 245The search key is represented by: 246 247.. code-block:: c 248 249 union rte_ipsec_sad_key { 250 struct rte_ipsec_sadv4_key v4; 251 struct rte_ipsec_sadv6_key v6; 252 }; 253 254where v4 is a tuple for IPv4: 255 256.. code-block:: c 257 258 struct rte_ipsec_sadv4_key { 259 uint32_t spi; 260 uint32_t dip; 261 uint32_t sip; 262 }; 263 264and v6 is a tuple for IPv6: 265 266.. code-block:: c 267 268 struct rte_ipsec_sadv6_key { 269 uint32_t spi; 270 uint8_t dip[16]; 271 uint8_t sip[16]; 272 }; 273 274As an example, lookup related code could look like that: 275 276.. code-block:: c 277 278 int i; 279 union rte_ipsec_sad_key keys[BURST_SZ]; 280 const union rte_ipsec_sad_key *keys_p[BURST_SZ]; 281 void *vals[BURST_SZ]; 282 283 for (i = 0; i < BURST_SZ_MAX; i++) { 284 keys[i].v4.spi = esp_hdr[i]->spi; 285 keys[i].v4.dip = ipv4_hdr[i]->dst_addr; 286 keys[i].v4.sip = ipv4_hdr[i]->src_addr; 287 keys_p[i] = &keys[i]; 288 } 289 rte_ipsec_sad_lookup(sad, keys_p, vals, BURST_SZ); 290 291 for (i = 0; i < BURST_SZ_MAX; i++) { 292 if (vals[i] == NULL) 293 printf("SA not found for key index %d\n", i); 294 else 295 printf("SA pointer is %p\n", vals[i]); 296 } 297 298 299Supported features 300------------------ 301 302* ESP protocol tunnel mode both IPv4/IPv6. 303 304* ESP protocol transport mode both IPv4/IPv6. 305 306* ESN and replay window. 307 308* algorithms: 3DES-CBC, AES-CBC, AES-CTR, AES-GCM, HMAC-SHA1, NULL. 309 310 311Limitations 312----------- 313 314The following features are not properly supported in the current version: 315 316* Hard/soft limit for SA lifetime (time interval/byte count). 317