crypto/aesni_mb: fix DOCSIS AES-256
[dpdk.git] / drivers / crypto / aesni_mb / rte_aesni_mb_pmd.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2015-2017 Intel Corporation
3  */
4
5 #include <intel-ipsec-mb.h>
6
7 #include <rte_common.h>
8 #include <rte_hexdump.h>
9 #include <rte_cryptodev.h>
10 #include <rte_cryptodev_pmd.h>
11 #include <rte_bus_vdev.h>
12 #include <rte_malloc.h>
13 #include <rte_cpuflags.h>
14 #include <rte_per_lcore.h>
15
16 #include "aesni_mb_pmd_private.h"
17
18 int aesni_mb_logtype_driver;
19
20 #define AES_CCM_DIGEST_MIN_LEN 4
21 #define AES_CCM_DIGEST_MAX_LEN 16
22 #define HMAC_MAX_BLOCK_SIZE 128
23 static uint8_t cryptodev_driver_id;
24
25 /*
26  * Needed to support CPU-CRYPTO API (rte_cryptodev_sym_cpu_crypto_process),
27  * as we still use JOB based API even for synchronous processing.
28  */
29 static RTE_DEFINE_PER_LCORE(MB_MGR *, sync_mb_mgr);
30
31 typedef void (*hash_one_block_t)(const void *data, void *digest);
32 typedef void (*aes_keyexp_t)(const void *key, void *enc_exp_keys, void *dec_exp_keys);
33
34 /**
35  * Calculate the authentication pre-computes
36  *
37  * @param one_block_hash        Function pointer to calculate digest on ipad/opad
38  * @param ipad                  Inner pad output byte array
39  * @param opad                  Outer pad output byte array
40  * @param hkey                  Authentication key
41  * @param hkey_len              Authentication key length
42  * @param blocksize             Block size of selected hash algo
43  */
44 static void
45 calculate_auth_precomputes(hash_one_block_t one_block_hash,
46                 uint8_t *ipad, uint8_t *opad,
47                 const uint8_t *hkey, uint16_t hkey_len,
48                 uint16_t blocksize)
49 {
50         unsigned i, length;
51
52         uint8_t ipad_buf[blocksize] __rte_aligned(16);
53         uint8_t opad_buf[blocksize] __rte_aligned(16);
54
55         /* Setup inner and outer pads */
56         memset(ipad_buf, HMAC_IPAD_VALUE, blocksize);
57         memset(opad_buf, HMAC_OPAD_VALUE, blocksize);
58
59         /* XOR hash key with inner and outer pads */
60         length = hkey_len > blocksize ? blocksize : hkey_len;
61
62         for (i = 0; i < length; i++) {
63                 ipad_buf[i] ^= hkey[i];
64                 opad_buf[i] ^= hkey[i];
65         }
66
67         /* Compute partial hashes */
68         (*one_block_hash)(ipad_buf, ipad);
69         (*one_block_hash)(opad_buf, opad);
70
71         /* Clean up stack */
72         memset(ipad_buf, 0, blocksize);
73         memset(opad_buf, 0, blocksize);
74 }
75
76 /** Get xform chain order */
77 static enum aesni_mb_operation
78 aesni_mb_get_chain_order(const struct rte_crypto_sym_xform *xform)
79 {
80         if (xform == NULL)
81                 return AESNI_MB_OP_NOT_SUPPORTED;
82
83         if (xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER) {
84                 if (xform->next == NULL)
85                         return AESNI_MB_OP_CIPHER_ONLY;
86                 if (xform->next->type == RTE_CRYPTO_SYM_XFORM_AUTH)
87                         return AESNI_MB_OP_CIPHER_HASH;
88         }
89
90         if (xform->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
91                 if (xform->next == NULL)
92                         return AESNI_MB_OP_HASH_ONLY;
93                 if (xform->next->type == RTE_CRYPTO_SYM_XFORM_CIPHER)
94                         return AESNI_MB_OP_HASH_CIPHER;
95         }
96 #if IMB_VERSION_NUM > IMB_VERSION(0, 52, 0)
97         if (xform->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
98                 if (xform->aead.op == RTE_CRYPTO_AEAD_OP_ENCRYPT) {
99                         /*
100                          * CCM requires to hash first and cipher later
101                          * when encrypting
102                          */
103                         if (xform->aead.algo == RTE_CRYPTO_AEAD_AES_CCM)
104                                 return AESNI_MB_OP_AEAD_HASH_CIPHER;
105                         else
106                                 return AESNI_MB_OP_AEAD_CIPHER_HASH;
107                 } else {
108                         if (xform->aead.algo == RTE_CRYPTO_AEAD_AES_CCM)
109                                 return AESNI_MB_OP_AEAD_CIPHER_HASH;
110                         else
111                                 return AESNI_MB_OP_AEAD_HASH_CIPHER;
112                 }
113         }
114 #else
115         if (xform->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
116                 if (xform->aead.algo == RTE_CRYPTO_AEAD_AES_CCM ||
117                                 xform->aead.algo == RTE_CRYPTO_AEAD_AES_GCM) {
118                         if (xform->aead.op == RTE_CRYPTO_AEAD_OP_ENCRYPT)
119                                 return AESNI_MB_OP_AEAD_CIPHER_HASH;
120                         else
121                                 return AESNI_MB_OP_AEAD_HASH_CIPHER;
122                 }
123         }
124 #endif
125
126         return AESNI_MB_OP_NOT_SUPPORTED;
127 }
128
129 /** Set session authentication parameters */
130 static int
131 aesni_mb_set_session_auth_parameters(const MB_MGR *mb_mgr,
132                 struct aesni_mb_session *sess,
133                 const struct rte_crypto_sym_xform *xform)
134 {
135         hash_one_block_t hash_oneblock_fn = NULL;
136         unsigned int key_larger_block_size = 0;
137         uint8_t hashed_key[HMAC_MAX_BLOCK_SIZE] = { 0 };
138         uint32_t auth_precompute = 1;
139
140         if (xform == NULL) {
141                 sess->auth.algo = NULL_HASH;
142                 return 0;
143         }
144
145         if (xform->type != RTE_CRYPTO_SYM_XFORM_AUTH) {
146                 AESNI_MB_LOG(ERR, "Crypto xform struct not of type auth");
147                 return -1;
148         }
149
150         /* Set the request digest size */
151         sess->auth.req_digest_len = xform->auth.digest_length;
152
153         /* Select auth generate/verify */
154         sess->auth.operation = xform->auth.op;
155
156         /* Set Authentication Parameters */
157         if (xform->auth.algo == RTE_CRYPTO_AUTH_AES_XCBC_MAC) {
158                 sess->auth.algo = AES_XCBC;
159
160                 uint16_t xcbc_mac_digest_len =
161                         get_truncated_digest_byte_length(AES_XCBC);
162                 if (sess->auth.req_digest_len != xcbc_mac_digest_len) {
163                         AESNI_MB_LOG(ERR, "Invalid digest size\n");
164                         return -EINVAL;
165                 }
166                 sess->auth.gen_digest_len = sess->auth.req_digest_len;
167
168                 IMB_AES_XCBC_KEYEXP(mb_mgr, xform->auth.key.data,
169                                 sess->auth.xcbc.k1_expanded,
170                                 sess->auth.xcbc.k2, sess->auth.xcbc.k3);
171                 return 0;
172         }
173
174         if (xform->auth.algo == RTE_CRYPTO_AUTH_AES_CMAC) {
175                 uint32_t dust[4*15];
176
177                 sess->auth.algo = AES_CMAC;
178
179                 uint16_t cmac_digest_len = get_digest_byte_length(AES_CMAC);
180
181                 if (sess->auth.req_digest_len > cmac_digest_len) {
182                         AESNI_MB_LOG(ERR, "Invalid digest size\n");
183                         return -EINVAL;
184                 }
185                 /*
186                  * Multi-buffer lib supports digest sizes from 4 to 16 bytes
187                  * in version 0.50 and sizes of 12 and 16 bytes,
188                  * in version 0.49.
189                  * If size requested is different, generate the full digest
190                  * (16 bytes) in a temporary location and then memcpy
191                  * the requested number of bytes.
192                  */
193                 if (sess->auth.req_digest_len < 4)
194                         sess->auth.gen_digest_len = cmac_digest_len;
195                 else
196                         sess->auth.gen_digest_len = sess->auth.req_digest_len;
197
198                 IMB_AES_KEYEXP_128(mb_mgr, xform->auth.key.data,
199                                 sess->auth.cmac.expkey, dust);
200                 IMB_AES_CMAC_SUBKEY_GEN_128(mb_mgr, sess->auth.cmac.expkey,
201                                 sess->auth.cmac.skey1, sess->auth.cmac.skey2);
202                 return 0;
203         }
204
205         if (xform->auth.algo == RTE_CRYPTO_AUTH_AES_GMAC) {
206                 if (xform->auth.op == RTE_CRYPTO_AUTH_OP_GENERATE) {
207                         sess->cipher.direction = ENCRYPT;
208                         sess->chain_order = CIPHER_HASH;
209                 } else
210                         sess->cipher.direction = DECRYPT;
211
212                 sess->auth.algo = AES_GMAC;
213                 /*
214                  * Multi-buffer lib supports 8, 12 and 16 bytes of digest.
215                  * If size requested is different, generate the full digest
216                  * (16 bytes) in a temporary location and then memcpy
217                  * the requested number of bytes.
218                  */
219                 if (sess->auth.req_digest_len != 16 &&
220                                 sess->auth.req_digest_len != 12 &&
221                                 sess->auth.req_digest_len != 8) {
222                         sess->auth.gen_digest_len = 16;
223                 } else {
224                         sess->auth.gen_digest_len = sess->auth.req_digest_len;
225                 }
226                 sess->iv.length = xform->auth.iv.length;
227                 sess->iv.offset = xform->auth.iv.offset;
228
229                 switch (xform->auth.key.length) {
230                 case AES_128_BYTES:
231                         IMB_AES128_GCM_PRE(mb_mgr, xform->auth.key.data,
232                                 &sess->cipher.gcm_key);
233                         sess->cipher.key_length_in_bytes = AES_128_BYTES;
234                         break;
235                 case AES_192_BYTES:
236                         IMB_AES192_GCM_PRE(mb_mgr, xform->auth.key.data,
237                                 &sess->cipher.gcm_key);
238                         sess->cipher.key_length_in_bytes = AES_192_BYTES;
239                         break;
240                 case AES_256_BYTES:
241                         IMB_AES256_GCM_PRE(mb_mgr, xform->auth.key.data,
242                                 &sess->cipher.gcm_key);
243                         sess->cipher.key_length_in_bytes = AES_256_BYTES;
244                         break;
245                 default:
246                         RTE_LOG(ERR, PMD, "failed to parse test type\n");
247                         return -EINVAL;
248                 }
249
250                 return 0;
251         }
252
253         switch (xform->auth.algo) {
254         case RTE_CRYPTO_AUTH_MD5_HMAC:
255                 sess->auth.algo = MD5;
256                 hash_oneblock_fn = mb_mgr->md5_one_block;
257                 break;
258         case RTE_CRYPTO_AUTH_SHA1_HMAC:
259                 sess->auth.algo = SHA1;
260                 hash_oneblock_fn = mb_mgr->sha1_one_block;
261                 if (xform->auth.key.length > get_auth_algo_blocksize(SHA1)) {
262                         IMB_SHA1(mb_mgr,
263                                 xform->auth.key.data,
264                                 xform->auth.key.length,
265                                 hashed_key);
266                         key_larger_block_size = 1;
267                 }
268                 break;
269         case RTE_CRYPTO_AUTH_SHA1:
270                 sess->auth.algo = PLAIN_SHA1;
271                 auth_precompute = 0;
272                 break;
273         case RTE_CRYPTO_AUTH_SHA224_HMAC:
274                 sess->auth.algo = SHA_224;
275                 hash_oneblock_fn = mb_mgr->sha224_one_block;
276                 if (xform->auth.key.length > get_auth_algo_blocksize(SHA_224)) {
277                         IMB_SHA224(mb_mgr,
278                                 xform->auth.key.data,
279                                 xform->auth.key.length,
280                                 hashed_key);
281                         key_larger_block_size = 1;
282                 }
283                 break;
284         case RTE_CRYPTO_AUTH_SHA224:
285                 sess->auth.algo = PLAIN_SHA_224;
286                 auth_precompute = 0;
287                 break;
288         case RTE_CRYPTO_AUTH_SHA256_HMAC:
289                 sess->auth.algo = SHA_256;
290                 hash_oneblock_fn = mb_mgr->sha256_one_block;
291                 if (xform->auth.key.length > get_auth_algo_blocksize(SHA_256)) {
292                         IMB_SHA256(mb_mgr,
293                                 xform->auth.key.data,
294                                 xform->auth.key.length,
295                                 hashed_key);
296                         key_larger_block_size = 1;
297                 }
298                 break;
299         case RTE_CRYPTO_AUTH_SHA256:
300                 sess->auth.algo = PLAIN_SHA_256;
301                 auth_precompute = 0;
302                 break;
303         case RTE_CRYPTO_AUTH_SHA384_HMAC:
304                 sess->auth.algo = SHA_384;
305                 hash_oneblock_fn = mb_mgr->sha384_one_block;
306                 if (xform->auth.key.length > get_auth_algo_blocksize(SHA_384)) {
307                         IMB_SHA384(mb_mgr,
308                                 xform->auth.key.data,
309                                 xform->auth.key.length,
310                                 hashed_key);
311                         key_larger_block_size = 1;
312                 }
313                 break;
314         case RTE_CRYPTO_AUTH_SHA384:
315                 sess->auth.algo = PLAIN_SHA_384;
316                 auth_precompute = 0;
317                 break;
318         case RTE_CRYPTO_AUTH_SHA512_HMAC:
319                 sess->auth.algo = SHA_512;
320                 hash_oneblock_fn = mb_mgr->sha512_one_block;
321                 if (xform->auth.key.length > get_auth_algo_blocksize(SHA_512)) {
322                         IMB_SHA512(mb_mgr,
323                                 xform->auth.key.data,
324                                 xform->auth.key.length,
325                                 hashed_key);
326                         key_larger_block_size = 1;
327                 }
328                 break;
329         case RTE_CRYPTO_AUTH_SHA512:
330                 sess->auth.algo = PLAIN_SHA_512;
331                 auth_precompute = 0;
332                 break;
333         default:
334                 AESNI_MB_LOG(ERR, "Unsupported authentication algorithm selection");
335                 return -ENOTSUP;
336         }
337         uint16_t trunc_digest_size =
338                         get_truncated_digest_byte_length(sess->auth.algo);
339         uint16_t full_digest_size =
340                         get_digest_byte_length(sess->auth.algo);
341
342         if (sess->auth.req_digest_len > full_digest_size ||
343                         sess->auth.req_digest_len == 0) {
344                 AESNI_MB_LOG(ERR, "Invalid digest size\n");
345                 return -EINVAL;
346         }
347
348         if (sess->auth.req_digest_len != trunc_digest_size &&
349                         sess->auth.req_digest_len != full_digest_size)
350                 sess->auth.gen_digest_len = full_digest_size;
351         else
352                 sess->auth.gen_digest_len = sess->auth.req_digest_len;
353
354         /* Plain SHA does not require precompute key */
355         if (auth_precompute == 0)
356                 return 0;
357
358         /* Calculate Authentication precomputes */
359         if (key_larger_block_size) {
360                 calculate_auth_precomputes(hash_oneblock_fn,
361                         sess->auth.pads.inner, sess->auth.pads.outer,
362                         hashed_key,
363                         xform->auth.key.length,
364                         get_auth_algo_blocksize(sess->auth.algo));
365         } else {
366                 calculate_auth_precomputes(hash_oneblock_fn,
367                         sess->auth.pads.inner, sess->auth.pads.outer,
368                         xform->auth.key.data,
369                         xform->auth.key.length,
370                         get_auth_algo_blocksize(sess->auth.algo));
371         }
372
373         return 0;
374 }
375
376 /** Set session cipher parameters */
377 static int
378 aesni_mb_set_session_cipher_parameters(const MB_MGR *mb_mgr,
379                 struct aesni_mb_session *sess,
380                 const struct rte_crypto_sym_xform *xform)
381 {
382         uint8_t is_aes = 0;
383         uint8_t is_3DES = 0;
384         uint8_t is_docsis = 0;
385
386         if (xform == NULL) {
387                 sess->cipher.mode = NULL_CIPHER;
388                 return 0;
389         }
390
391         if (xform->type != RTE_CRYPTO_SYM_XFORM_CIPHER) {
392                 AESNI_MB_LOG(ERR, "Crypto xform struct not of type cipher");
393                 return -EINVAL;
394         }
395
396         /* Select cipher direction */
397         switch (xform->cipher.op) {
398         case RTE_CRYPTO_CIPHER_OP_ENCRYPT:
399                 sess->cipher.direction = ENCRYPT;
400                 break;
401         case RTE_CRYPTO_CIPHER_OP_DECRYPT:
402                 sess->cipher.direction = DECRYPT;
403                 break;
404         default:
405                 AESNI_MB_LOG(ERR, "Invalid cipher operation parameter");
406                 return -EINVAL;
407         }
408
409         /* Select cipher mode */
410         switch (xform->cipher.algo) {
411         case RTE_CRYPTO_CIPHER_AES_CBC:
412                 sess->cipher.mode = CBC;
413                 is_aes = 1;
414                 break;
415         case RTE_CRYPTO_CIPHER_AES_CTR:
416                 sess->cipher.mode = CNTR;
417                 is_aes = 1;
418                 break;
419         case RTE_CRYPTO_CIPHER_AES_DOCSISBPI:
420                 sess->cipher.mode = DOCSIS_SEC_BPI;
421                 is_docsis = 1;
422                 break;
423         case RTE_CRYPTO_CIPHER_DES_CBC:
424                 sess->cipher.mode = DES;
425                 break;
426         case RTE_CRYPTO_CIPHER_DES_DOCSISBPI:
427                 sess->cipher.mode = DOCSIS_DES;
428                 break;
429         case RTE_CRYPTO_CIPHER_3DES_CBC:
430                 sess->cipher.mode = DES3;
431                 is_3DES = 1;
432                 break;
433         default:
434                 AESNI_MB_LOG(ERR, "Unsupported cipher mode parameter");
435                 return -ENOTSUP;
436         }
437
438         /* Set IV parameters */
439         sess->iv.offset = xform->cipher.iv.offset;
440         sess->iv.length = xform->cipher.iv.length;
441
442         /* Check key length and choose key expansion function for AES */
443         if (is_aes) {
444                 switch (xform->cipher.key.length) {
445                 case AES_128_BYTES:
446                         sess->cipher.key_length_in_bytes = AES_128_BYTES;
447                         IMB_AES_KEYEXP_128(mb_mgr, xform->cipher.key.data,
448                                         sess->cipher.expanded_aes_keys.encode,
449                                         sess->cipher.expanded_aes_keys.decode);
450                         break;
451                 case AES_192_BYTES:
452                         sess->cipher.key_length_in_bytes = AES_192_BYTES;
453                         IMB_AES_KEYEXP_192(mb_mgr, xform->cipher.key.data,
454                                         sess->cipher.expanded_aes_keys.encode,
455                                         sess->cipher.expanded_aes_keys.decode);
456                         break;
457                 case AES_256_BYTES:
458                         sess->cipher.key_length_in_bytes = AES_256_BYTES;
459                         IMB_AES_KEYEXP_256(mb_mgr, xform->cipher.key.data,
460                                         sess->cipher.expanded_aes_keys.encode,
461                                         sess->cipher.expanded_aes_keys.decode);
462                         break;
463                 default:
464                         AESNI_MB_LOG(ERR, "Invalid cipher key length");
465                         return -EINVAL;
466                 }
467         } else if (is_docsis) {
468                 switch (xform->cipher.key.length) {
469                 case AES_128_BYTES:
470                         sess->cipher.key_length_in_bytes = AES_128_BYTES;
471                         IMB_AES_KEYEXP_128(mb_mgr, xform->cipher.key.data,
472                                         sess->cipher.expanded_aes_keys.encode,
473                                         sess->cipher.expanded_aes_keys.decode);
474                         break;
475 #if IMB_VERSION_NUM >= IMB_VERSION(0, 53, 3)
476                 case AES_256_BYTES:
477                         sess->cipher.key_length_in_bytes = AES_256_BYTES;
478                         IMB_AES_KEYEXP_256(mb_mgr, xform->cipher.key.data,
479                                         sess->cipher.expanded_aes_keys.encode,
480                                         sess->cipher.expanded_aes_keys.decode);
481                         break;
482 #endif
483                 default:
484                         AESNI_MB_LOG(ERR, "Invalid cipher key length");
485                         return -EINVAL;
486                 }
487         } else if (is_3DES) {
488                 uint64_t *keys[3] = {sess->cipher.exp_3des_keys.key[0],
489                                 sess->cipher.exp_3des_keys.key[1],
490                                 sess->cipher.exp_3des_keys.key[2]};
491
492                 switch (xform->cipher.key.length) {
493                 case  24:
494                         IMB_DES_KEYSCHED(mb_mgr, keys[0],
495                                         xform->cipher.key.data);
496                         IMB_DES_KEYSCHED(mb_mgr, keys[1],
497                                         xform->cipher.key.data + 8);
498                         IMB_DES_KEYSCHED(mb_mgr, keys[2],
499                                         xform->cipher.key.data + 16);
500
501                         /* Initialize keys - 24 bytes: [K1-K2-K3] */
502                         sess->cipher.exp_3des_keys.ks_ptr[0] = keys[0];
503                         sess->cipher.exp_3des_keys.ks_ptr[1] = keys[1];
504                         sess->cipher.exp_3des_keys.ks_ptr[2] = keys[2];
505                         break;
506                 case 16:
507                         IMB_DES_KEYSCHED(mb_mgr, keys[0],
508                                         xform->cipher.key.data);
509                         IMB_DES_KEYSCHED(mb_mgr, keys[1],
510                                         xform->cipher.key.data + 8);
511                         /* Initialize keys - 16 bytes: [K1=K1,K2=K2,K3=K1] */
512                         sess->cipher.exp_3des_keys.ks_ptr[0] = keys[0];
513                         sess->cipher.exp_3des_keys.ks_ptr[1] = keys[1];
514                         sess->cipher.exp_3des_keys.ks_ptr[2] = keys[0];
515                         break;
516                 case 8:
517                         IMB_DES_KEYSCHED(mb_mgr, keys[0],
518                                         xform->cipher.key.data);
519
520                         /* Initialize keys - 8 bytes: [K1 = K2 = K3] */
521                         sess->cipher.exp_3des_keys.ks_ptr[0] = keys[0];
522                         sess->cipher.exp_3des_keys.ks_ptr[1] = keys[0];
523                         sess->cipher.exp_3des_keys.ks_ptr[2] = keys[0];
524                         break;
525                 default:
526                         AESNI_MB_LOG(ERR, "Invalid cipher key length");
527                         return -EINVAL;
528                 }
529
530                 sess->cipher.key_length_in_bytes = 24;
531         } else {
532                 if (xform->cipher.key.length != 8) {
533                         AESNI_MB_LOG(ERR, "Invalid cipher key length");
534                         return -EINVAL;
535                 }
536                 sess->cipher.key_length_in_bytes = 8;
537
538                 IMB_DES_KEYSCHED(mb_mgr,
539                         (uint64_t *)sess->cipher.expanded_aes_keys.encode,
540                                 xform->cipher.key.data);
541                 IMB_DES_KEYSCHED(mb_mgr,
542                         (uint64_t *)sess->cipher.expanded_aes_keys.decode,
543                                 xform->cipher.key.data);
544         }
545
546         return 0;
547 }
548
549 static int
550 aesni_mb_set_session_aead_parameters(const MB_MGR *mb_mgr,
551                 struct aesni_mb_session *sess,
552                 const struct rte_crypto_sym_xform *xform)
553 {
554         switch (xform->aead.op) {
555         case RTE_CRYPTO_AEAD_OP_ENCRYPT:
556                 sess->cipher.direction = ENCRYPT;
557                 sess->auth.operation = RTE_CRYPTO_AUTH_OP_GENERATE;
558                 break;
559         case RTE_CRYPTO_AEAD_OP_DECRYPT:
560                 sess->cipher.direction = DECRYPT;
561                 sess->auth.operation = RTE_CRYPTO_AUTH_OP_VERIFY;
562                 break;
563         default:
564                 AESNI_MB_LOG(ERR, "Invalid aead operation parameter");
565                 return -EINVAL;
566         }
567
568         switch (xform->aead.algo) {
569         case RTE_CRYPTO_AEAD_AES_CCM:
570                 sess->cipher.mode = CCM;
571                 sess->auth.algo = AES_CCM;
572
573                 /* Check key length and choose key expansion function for AES */
574                 switch (xform->aead.key.length) {
575                 case AES_128_BYTES:
576                         sess->cipher.key_length_in_bytes = AES_128_BYTES;
577                         IMB_AES_KEYEXP_128(mb_mgr, xform->aead.key.data,
578                                         sess->cipher.expanded_aes_keys.encode,
579                                         sess->cipher.expanded_aes_keys.decode);
580                         break;
581                 default:
582                         AESNI_MB_LOG(ERR, "Invalid cipher key length");
583                         return -EINVAL;
584                 }
585
586                 break;
587
588         case RTE_CRYPTO_AEAD_AES_GCM:
589                 sess->cipher.mode = GCM;
590                 sess->auth.algo = AES_GMAC;
591
592                 switch (xform->aead.key.length) {
593                 case AES_128_BYTES:
594                         sess->cipher.key_length_in_bytes = AES_128_BYTES;
595                         IMB_AES128_GCM_PRE(mb_mgr, xform->aead.key.data,
596                                 &sess->cipher.gcm_key);
597                         break;
598                 case AES_192_BYTES:
599                         sess->cipher.key_length_in_bytes = AES_192_BYTES;
600                         IMB_AES192_GCM_PRE(mb_mgr, xform->aead.key.data,
601                                 &sess->cipher.gcm_key);
602                         break;
603                 case AES_256_BYTES:
604                         sess->cipher.key_length_in_bytes = AES_256_BYTES;
605                         IMB_AES256_GCM_PRE(mb_mgr, xform->aead.key.data,
606                                 &sess->cipher.gcm_key);
607                         break;
608                 default:
609                         AESNI_MB_LOG(ERR, "Invalid cipher key length");
610                         return -EINVAL;
611                 }
612
613                 break;
614
615         default:
616                 AESNI_MB_LOG(ERR, "Unsupported aead mode parameter");
617                 return -ENOTSUP;
618         }
619
620         /* Set IV parameters */
621         sess->iv.offset = xform->aead.iv.offset;
622         sess->iv.length = xform->aead.iv.length;
623
624         sess->auth.req_digest_len = xform->aead.digest_length;
625         /* CCM digests must be between 4 and 16 and an even number */
626         if (sess->auth.req_digest_len < AES_CCM_DIGEST_MIN_LEN ||
627                         sess->auth.req_digest_len > AES_CCM_DIGEST_MAX_LEN ||
628                         (sess->auth.req_digest_len & 1) == 1) {
629                 AESNI_MB_LOG(ERR, "Invalid digest size\n");
630                 return -EINVAL;
631         }
632         sess->auth.gen_digest_len = sess->auth.req_digest_len;
633
634         return 0;
635 }
636
637 /** Parse crypto xform chain and set private session parameters */
638 int
639 aesni_mb_set_session_parameters(const MB_MGR *mb_mgr,
640                 struct aesni_mb_session *sess,
641                 const struct rte_crypto_sym_xform *xform)
642 {
643         const struct rte_crypto_sym_xform *auth_xform = NULL;
644         const struct rte_crypto_sym_xform *cipher_xform = NULL;
645         const struct rte_crypto_sym_xform *aead_xform = NULL;
646         int ret;
647
648         /* Select Crypto operation - hash then cipher / cipher then hash */
649         switch (aesni_mb_get_chain_order(xform)) {
650         case AESNI_MB_OP_HASH_CIPHER:
651                 sess->chain_order = HASH_CIPHER;
652                 auth_xform = xform;
653                 cipher_xform = xform->next;
654                 break;
655         case AESNI_MB_OP_CIPHER_HASH:
656                 sess->chain_order = CIPHER_HASH;
657                 auth_xform = xform->next;
658                 cipher_xform = xform;
659                 break;
660         case AESNI_MB_OP_HASH_ONLY:
661                 sess->chain_order = HASH_CIPHER;
662                 auth_xform = xform;
663                 cipher_xform = NULL;
664                 break;
665         case AESNI_MB_OP_CIPHER_ONLY:
666                 /*
667                  * Multi buffer library operates only at two modes,
668                  * CIPHER_HASH and HASH_CIPHER. When doing ciphering only,
669                  * chain order depends on cipher operation: encryption is always
670                  * the first operation and decryption the last one.
671                  */
672                 if (xform->cipher.op == RTE_CRYPTO_CIPHER_OP_ENCRYPT)
673                         sess->chain_order = CIPHER_HASH;
674                 else
675                         sess->chain_order = HASH_CIPHER;
676                 auth_xform = NULL;
677                 cipher_xform = xform;
678                 break;
679         case AESNI_MB_OP_AEAD_CIPHER_HASH:
680                 sess->chain_order = CIPHER_HASH;
681                 sess->aead.aad_len = xform->aead.aad_length;
682                 aead_xform = xform;
683                 break;
684         case AESNI_MB_OP_AEAD_HASH_CIPHER:
685                 sess->chain_order = HASH_CIPHER;
686                 sess->aead.aad_len = xform->aead.aad_length;
687                 aead_xform = xform;
688                 break;
689         case AESNI_MB_OP_NOT_SUPPORTED:
690         default:
691                 AESNI_MB_LOG(ERR, "Unsupported operation chain order parameter");
692                 return -ENOTSUP;
693         }
694
695         /* Default IV length = 0 */
696         sess->iv.length = 0;
697
698         ret = aesni_mb_set_session_auth_parameters(mb_mgr, sess, auth_xform);
699         if (ret != 0) {
700                 AESNI_MB_LOG(ERR, "Invalid/unsupported authentication parameters");
701                 return ret;
702         }
703
704         ret = aesni_mb_set_session_cipher_parameters(mb_mgr, sess,
705                         cipher_xform);
706         if (ret != 0) {
707                 AESNI_MB_LOG(ERR, "Invalid/unsupported cipher parameters");
708                 return ret;
709         }
710
711         if (aead_xform) {
712                 ret = aesni_mb_set_session_aead_parameters(mb_mgr, sess,
713                                 aead_xform);
714                 if (ret != 0) {
715                         AESNI_MB_LOG(ERR, "Invalid/unsupported aead parameters");
716                         return ret;
717                 }
718         }
719
720         return 0;
721 }
722
723 /**
724  * burst enqueue, place crypto operations on ingress queue for processing.
725  *
726  * @param __qp         Queue Pair to process
727  * @param ops          Crypto operations for processing
728  * @param nb_ops       Number of crypto operations for processing
729  *
730  * @return
731  * - Number of crypto operations enqueued
732  */
733 static uint16_t
734 aesni_mb_pmd_enqueue_burst(void *__qp, struct rte_crypto_op **ops,
735                 uint16_t nb_ops)
736 {
737         struct aesni_mb_qp *qp = __qp;
738
739         unsigned int nb_enqueued;
740
741         nb_enqueued = rte_ring_enqueue_burst(qp->ingress_queue,
742                         (void **)ops, nb_ops, NULL);
743
744         qp->stats.enqueued_count += nb_enqueued;
745
746         return nb_enqueued;
747 }
748
749 /** Get multi buffer session */
750 static inline struct aesni_mb_session *
751 get_session(struct aesni_mb_qp *qp, struct rte_crypto_op *op)
752 {
753         struct aesni_mb_session *sess = NULL;
754
755         if (op->sess_type == RTE_CRYPTO_OP_WITH_SESSION) {
756                 if (likely(op->sym->session != NULL))
757                         sess = (struct aesni_mb_session *)
758                                         get_sym_session_private_data(
759                                         op->sym->session,
760                                         cryptodev_driver_id);
761         } else {
762                 void *_sess = rte_cryptodev_sym_session_create(qp->sess_mp);
763                 void *_sess_private_data = NULL;
764
765                 if (_sess == NULL)
766                         return NULL;
767
768                 if (rte_mempool_get(qp->sess_mp_priv,
769                                 (void **)&_sess_private_data))
770                         return NULL;
771
772                 sess = (struct aesni_mb_session *)_sess_private_data;
773
774                 if (unlikely(aesni_mb_set_session_parameters(qp->mb_mgr,
775                                 sess, op->sym->xform) != 0)) {
776                         rte_mempool_put(qp->sess_mp, _sess);
777                         rte_mempool_put(qp->sess_mp_priv, _sess_private_data);
778                         sess = NULL;
779                 }
780                 op->sym->session = (struct rte_cryptodev_sym_session *)_sess;
781                 set_sym_session_private_data(op->sym->session,
782                                 cryptodev_driver_id, _sess_private_data);
783         }
784
785         if (unlikely(sess == NULL))
786                 op->status = RTE_CRYPTO_OP_STATUS_INVALID_SESSION;
787
788         return sess;
789 }
790
791 static inline uint64_t
792 auth_start_offset(struct rte_crypto_op *op, struct aesni_mb_session *session,
793                 uint32_t oop)
794 {
795         struct rte_mbuf *m_src, *m_dst;
796         uint8_t *p_src, *p_dst;
797         uintptr_t u_src, u_dst;
798         uint32_t cipher_end, auth_end;
799
800         /* Only cipher then hash needs special calculation. */
801         if (!oop || session->chain_order != CIPHER_HASH)
802                 return op->sym->auth.data.offset;
803
804         m_src = op->sym->m_src;
805         m_dst = op->sym->m_dst;
806
807         p_src = rte_pktmbuf_mtod(m_src, uint8_t *);
808         p_dst = rte_pktmbuf_mtod(m_dst, uint8_t *);
809         u_src = (uintptr_t)p_src;
810         u_dst = (uintptr_t)p_dst + op->sym->auth.data.offset;
811
812         /**
813          * Copy the content between cipher offset and auth offset for generating
814          * correct digest.
815          */
816         if (op->sym->cipher.data.offset > op->sym->auth.data.offset)
817                 memcpy(p_dst + op->sym->auth.data.offset,
818                                 p_src + op->sym->auth.data.offset,
819                                 op->sym->cipher.data.offset -
820                                 op->sym->auth.data.offset);
821
822         /**
823          * Copy the content between (cipher offset + length) and (auth offset +
824          * length) for generating correct digest
825          */
826         cipher_end = op->sym->cipher.data.offset + op->sym->cipher.data.length;
827         auth_end = op->sym->auth.data.offset + op->sym->auth.data.length;
828         if (cipher_end < auth_end)
829                 memcpy(p_dst + cipher_end, p_src + cipher_end,
830                                 auth_end - cipher_end);
831
832         /**
833          * Since intel-ipsec-mb only supports positive values,
834          * we need to deduct the correct offset between src and dst.
835          */
836
837         return u_src < u_dst ? (u_dst - u_src) :
838                         (UINT64_MAX - u_src + u_dst + 1);
839 }
840
841 static inline void
842 set_cpu_mb_job_params(JOB_AES_HMAC *job, struct aesni_mb_session *session,
843                 union rte_crypto_sym_ofs sofs, void *buf, uint32_t len,
844                 void *iv, void *aad, void *digest, void *udata)
845 {
846         /* Set crypto operation */
847         job->chain_order = session->chain_order;
848
849         /* Set cipher parameters */
850         job->cipher_direction = session->cipher.direction;
851         job->cipher_mode = session->cipher.mode;
852
853         job->aes_key_len_in_bytes = session->cipher.key_length_in_bytes;
854
855         /* Set authentication parameters */
856         job->hash_alg = session->auth.algo;
857         job->iv = iv;
858
859         switch (job->hash_alg) {
860         case AES_XCBC:
861                 job->u.XCBC._k1_expanded = session->auth.xcbc.k1_expanded;
862                 job->u.XCBC._k2 = session->auth.xcbc.k2;
863                 job->u.XCBC._k3 = session->auth.xcbc.k3;
864
865                 job->aes_enc_key_expanded =
866                                 session->cipher.expanded_aes_keys.encode;
867                 job->aes_dec_key_expanded =
868                                 session->cipher.expanded_aes_keys.decode;
869                 break;
870
871         case AES_CCM:
872                 job->u.CCM.aad = (uint8_t *)aad + 18;
873                 job->u.CCM.aad_len_in_bytes = session->aead.aad_len;
874                 job->aes_enc_key_expanded =
875                                 session->cipher.expanded_aes_keys.encode;
876                 job->aes_dec_key_expanded =
877                                 session->cipher.expanded_aes_keys.decode;
878                 job->iv++;
879                 break;
880
881         case AES_CMAC:
882                 job->u.CMAC._key_expanded = session->auth.cmac.expkey;
883                 job->u.CMAC._skey1 = session->auth.cmac.skey1;
884                 job->u.CMAC._skey2 = session->auth.cmac.skey2;
885                 job->aes_enc_key_expanded =
886                                 session->cipher.expanded_aes_keys.encode;
887                 job->aes_dec_key_expanded =
888                                 session->cipher.expanded_aes_keys.decode;
889                 break;
890
891         case AES_GMAC:
892                 if (session->cipher.mode == GCM) {
893                         job->u.GCM.aad = aad;
894                         job->u.GCM.aad_len_in_bytes = session->aead.aad_len;
895                 } else {
896                         /* For GMAC */
897                         job->u.GCM.aad = buf;
898                         job->u.GCM.aad_len_in_bytes = len;
899                         job->cipher_mode = GCM;
900                 }
901                 job->aes_enc_key_expanded = &session->cipher.gcm_key;
902                 job->aes_dec_key_expanded = &session->cipher.gcm_key;
903                 break;
904
905         default:
906                 job->u.HMAC._hashed_auth_key_xor_ipad =
907                                 session->auth.pads.inner;
908                 job->u.HMAC._hashed_auth_key_xor_opad =
909                                 session->auth.pads.outer;
910
911                 if (job->cipher_mode == DES3) {
912                         job->aes_enc_key_expanded =
913                                 session->cipher.exp_3des_keys.ks_ptr;
914                         job->aes_dec_key_expanded =
915                                 session->cipher.exp_3des_keys.ks_ptr;
916                 } else {
917                         job->aes_enc_key_expanded =
918                                 session->cipher.expanded_aes_keys.encode;
919                         job->aes_dec_key_expanded =
920                                 session->cipher.expanded_aes_keys.decode;
921                 }
922         }
923
924         /*
925          * Multi-buffer library current only support returning a truncated
926          * digest length as specified in the relevant IPsec RFCs
927          */
928
929         /* Set digest location and length */
930         job->auth_tag_output = digest;
931         job->auth_tag_output_len_in_bytes = session->auth.gen_digest_len;
932
933         /* Set IV parameters */
934         job->iv_len_in_bytes = session->iv.length;
935
936         /* Data Parameters */
937         job->src = buf;
938         job->dst = (uint8_t *)buf + sofs.ofs.cipher.head;
939         job->cipher_start_src_offset_in_bytes = sofs.ofs.cipher.head;
940         job->hash_start_src_offset_in_bytes = sofs.ofs.auth.head;
941         if (job->hash_alg == AES_GMAC && session->cipher.mode != GCM) {
942                 job->msg_len_to_hash_in_bytes = 0;
943                 job->msg_len_to_cipher_in_bytes = 0;
944         } else {
945                 job->msg_len_to_hash_in_bytes = len - sofs.ofs.auth.head -
946                         sofs.ofs.auth.tail;
947                 job->msg_len_to_cipher_in_bytes = len - sofs.ofs.cipher.head -
948                         sofs.ofs.cipher.tail;
949         }
950
951         job->user_data = udata;
952 }
953
954 /**
955  * Process a crypto operation and complete a JOB_AES_HMAC job structure for
956  * submission to the multi buffer library for processing.
957  *
958  * @param       qp      queue pair
959  * @param       job     JOB_AES_HMAC structure to fill
960  * @param       m       mbuf to process
961  *
962  * @return
963  * - Completed JOB_AES_HMAC structure pointer on success
964  * - NULL pointer if completion of JOB_AES_HMAC structure isn't possible
965  */
966 static inline int
967 set_mb_job_params(JOB_AES_HMAC *job, struct aesni_mb_qp *qp,
968                 struct rte_crypto_op *op, uint8_t *digest_idx)
969 {
970         struct rte_mbuf *m_src = op->sym->m_src, *m_dst;
971         struct aesni_mb_session *session;
972         uint32_t m_offset, oop;
973
974         session = get_session(qp, op);
975         if (session == NULL) {
976                 op->status = RTE_CRYPTO_OP_STATUS_INVALID_SESSION;
977                 return -1;
978         }
979
980         /* Set crypto operation */
981         job->chain_order = session->chain_order;
982
983         /* Set cipher parameters */
984         job->cipher_direction = session->cipher.direction;
985         job->cipher_mode = session->cipher.mode;
986
987         job->aes_key_len_in_bytes = session->cipher.key_length_in_bytes;
988
989         /* Set authentication parameters */
990         job->hash_alg = session->auth.algo;
991
992         switch (job->hash_alg) {
993         case AES_XCBC:
994                 job->u.XCBC._k1_expanded = session->auth.xcbc.k1_expanded;
995                 job->u.XCBC._k2 = session->auth.xcbc.k2;
996                 job->u.XCBC._k3 = session->auth.xcbc.k3;
997
998                 job->aes_enc_key_expanded =
999                                 session->cipher.expanded_aes_keys.encode;
1000                 job->aes_dec_key_expanded =
1001                                 session->cipher.expanded_aes_keys.decode;
1002                 break;
1003
1004         case AES_CCM:
1005                 job->u.CCM.aad = op->sym->aead.aad.data + 18;
1006                 job->u.CCM.aad_len_in_bytes = session->aead.aad_len;
1007                 job->aes_enc_key_expanded =
1008                                 session->cipher.expanded_aes_keys.encode;
1009                 job->aes_dec_key_expanded =
1010                                 session->cipher.expanded_aes_keys.decode;
1011                 break;
1012
1013         case AES_CMAC:
1014                 job->u.CMAC._key_expanded = session->auth.cmac.expkey;
1015                 job->u.CMAC._skey1 = session->auth.cmac.skey1;
1016                 job->u.CMAC._skey2 = session->auth.cmac.skey2;
1017                 job->aes_enc_key_expanded =
1018                                 session->cipher.expanded_aes_keys.encode;
1019                 job->aes_dec_key_expanded =
1020                                 session->cipher.expanded_aes_keys.decode;
1021                 break;
1022
1023         case AES_GMAC:
1024                 if (session->cipher.mode == GCM) {
1025                         job->u.GCM.aad = op->sym->aead.aad.data;
1026                         job->u.GCM.aad_len_in_bytes = session->aead.aad_len;
1027                 } else {
1028                         /* For GMAC */
1029                         job->u.GCM.aad = rte_pktmbuf_mtod_offset(m_src,
1030                                         uint8_t *, op->sym->auth.data.offset);
1031                         job->u.GCM.aad_len_in_bytes = op->sym->auth.data.length;
1032                         job->cipher_mode = GCM;
1033                 }
1034                 job->aes_enc_key_expanded = &session->cipher.gcm_key;
1035                 job->aes_dec_key_expanded = &session->cipher.gcm_key;
1036                 break;
1037
1038         default:
1039                 job->u.HMAC._hashed_auth_key_xor_ipad = session->auth.pads.inner;
1040                 job->u.HMAC._hashed_auth_key_xor_opad = session->auth.pads.outer;
1041
1042                 if (job->cipher_mode == DES3) {
1043                         job->aes_enc_key_expanded =
1044                                 session->cipher.exp_3des_keys.ks_ptr;
1045                         job->aes_dec_key_expanded =
1046                                 session->cipher.exp_3des_keys.ks_ptr;
1047                 } else {
1048                         job->aes_enc_key_expanded =
1049                                 session->cipher.expanded_aes_keys.encode;
1050                         job->aes_dec_key_expanded =
1051                                 session->cipher.expanded_aes_keys.decode;
1052                 }
1053         }
1054
1055         if (!op->sym->m_dst) {
1056                 /* in-place operation */
1057                 m_dst = m_src;
1058                 oop = 0;
1059         } else if (op->sym->m_dst == op->sym->m_src) {
1060                 /* in-place operation */
1061                 m_dst = m_src;
1062                 oop = 0;
1063         } else {
1064                 /* out-of-place operation */
1065                 m_dst = op->sym->m_dst;
1066                 oop = 1;
1067         }
1068
1069         if (job->hash_alg == AES_CCM || (job->hash_alg == AES_GMAC &&
1070                         session->cipher.mode == GCM))
1071                 m_offset = op->sym->aead.data.offset;
1072         else
1073                 m_offset = op->sym->cipher.data.offset;
1074
1075         /* Set digest output location */
1076         if (job->hash_alg != NULL_HASH &&
1077                         session->auth.operation == RTE_CRYPTO_AUTH_OP_VERIFY) {
1078                 job->auth_tag_output = qp->temp_digests[*digest_idx];
1079                 *digest_idx = (*digest_idx + 1) % MAX_JOBS;
1080         } else {
1081                 if (job->hash_alg == AES_CCM || (job->hash_alg == AES_GMAC &&
1082                                 session->cipher.mode == GCM))
1083                         job->auth_tag_output = op->sym->aead.digest.data;
1084                 else
1085                         job->auth_tag_output = op->sym->auth.digest.data;
1086
1087                 if (session->auth.req_digest_len != session->auth.gen_digest_len) {
1088                         job->auth_tag_output = qp->temp_digests[*digest_idx];
1089                         *digest_idx = (*digest_idx + 1) % MAX_JOBS;
1090                 }
1091         }
1092         /*
1093          * Multi-buffer library current only support returning a truncated
1094          * digest length as specified in the relevant IPsec RFCs
1095          */
1096
1097         /* Set digest length */
1098         job->auth_tag_output_len_in_bytes = session->auth.gen_digest_len;
1099
1100         /* Set IV parameters */
1101         job->iv_len_in_bytes = session->iv.length;
1102
1103         /* Data Parameters */
1104         job->src = rte_pktmbuf_mtod(m_src, uint8_t *);
1105         job->dst = rte_pktmbuf_mtod_offset(m_dst, uint8_t *, m_offset);
1106
1107         switch (job->hash_alg) {
1108         case AES_CCM:
1109                 job->cipher_start_src_offset_in_bytes =
1110                                 op->sym->aead.data.offset;
1111                 job->msg_len_to_cipher_in_bytes = op->sym->aead.data.length;
1112                 job->hash_start_src_offset_in_bytes = op->sym->aead.data.offset;
1113                 job->msg_len_to_hash_in_bytes = op->sym->aead.data.length;
1114
1115                 job->iv = rte_crypto_op_ctod_offset(op, uint8_t *,
1116                         session->iv.offset + 1);
1117                 break;
1118
1119         case AES_GMAC:
1120                 if (session->cipher.mode == GCM) {
1121                         job->cipher_start_src_offset_in_bytes =
1122                                         op->sym->aead.data.offset;
1123                         job->hash_start_src_offset_in_bytes =
1124                                         op->sym->aead.data.offset;
1125                         job->msg_len_to_cipher_in_bytes =
1126                                         op->sym->aead.data.length;
1127                         job->msg_len_to_hash_in_bytes =
1128                                         op->sym->aead.data.length;
1129                 } else {
1130                         job->cipher_start_src_offset_in_bytes =
1131                                         op->sym->auth.data.offset;
1132                         job->hash_start_src_offset_in_bytes =
1133                                         op->sym->auth.data.offset;
1134                         job->msg_len_to_cipher_in_bytes = 0;
1135                         job->msg_len_to_hash_in_bytes = 0;
1136                 }
1137
1138                 job->iv = rte_crypto_op_ctod_offset(op, uint8_t *,
1139                                 session->iv.offset);
1140                 break;
1141
1142         default:
1143                 job->cipher_start_src_offset_in_bytes =
1144                                 op->sym->cipher.data.offset;
1145                 job->msg_len_to_cipher_in_bytes = op->sym->cipher.data.length;
1146
1147                 job->hash_start_src_offset_in_bytes = auth_start_offset(op,
1148                                 session, oop);
1149                 job->msg_len_to_hash_in_bytes = op->sym->auth.data.length;
1150
1151                 job->iv = rte_crypto_op_ctod_offset(op, uint8_t *,
1152                         session->iv.offset);
1153         }
1154
1155         /* Set user data to be crypto operation data struct */
1156         job->user_data = op;
1157
1158         return 0;
1159 }
1160
1161 static inline void
1162 verify_digest(JOB_AES_HMAC *job, void *digest, uint16_t len, uint8_t *status)
1163 {
1164         /* Verify digest if required */
1165         if (memcmp(job->auth_tag_output, digest, len) != 0)
1166                 *status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED;
1167 }
1168
1169 static inline void
1170 generate_digest(JOB_AES_HMAC *job, struct rte_crypto_op *op,
1171                 struct aesni_mb_session *sess)
1172 {
1173         /* No extra copy needed */
1174         if (likely(sess->auth.req_digest_len == sess->auth.gen_digest_len))
1175                 return;
1176
1177         /*
1178          * This can only happen for HMAC, so only digest
1179          * for authentication algos is required
1180          */
1181         memcpy(op->sym->auth.digest.data, job->auth_tag_output,
1182                         sess->auth.req_digest_len);
1183 }
1184
1185 /**
1186  * Process a completed job and return rte_mbuf which job processed
1187  *
1188  * @param qp            Queue Pair to process
1189  * @param job   JOB_AES_HMAC job to process
1190  *
1191  * @return
1192  * - Returns processed crypto operation.
1193  * - Returns NULL on invalid job
1194  */
1195 static inline struct rte_crypto_op *
1196 post_process_mb_job(struct aesni_mb_qp *qp, JOB_AES_HMAC *job)
1197 {
1198         struct rte_crypto_op *op = (struct rte_crypto_op *)job->user_data;
1199         struct aesni_mb_session *sess = get_sym_session_private_data(
1200                                                         op->sym->session,
1201                                                         cryptodev_driver_id);
1202         if (unlikely(sess == NULL)) {
1203                 op->status = RTE_CRYPTO_OP_STATUS_INVALID_SESSION;
1204                 return op;
1205         }
1206
1207         if (likely(op->status == RTE_CRYPTO_OP_STATUS_NOT_PROCESSED)) {
1208                 switch (job->status) {
1209                 case STS_COMPLETED:
1210                         op->status = RTE_CRYPTO_OP_STATUS_SUCCESS;
1211
1212                         if (job->hash_alg == NULL_HASH)
1213                                 break;
1214
1215                         if (sess->auth.operation == RTE_CRYPTO_AUTH_OP_VERIFY) {
1216                                 if (job->hash_alg == AES_CCM ||
1217                                         (job->hash_alg == AES_GMAC &&
1218                                                 sess->cipher.mode == GCM))
1219                                         verify_digest(job,
1220                                                 op->sym->aead.digest.data,
1221                                                 sess->auth.req_digest_len,
1222                                                 &op->status);
1223                                 else
1224                                         verify_digest(job,
1225                                                 op->sym->auth.digest.data,
1226                                                 sess->auth.req_digest_len,
1227                                                 &op->status);
1228                         } else
1229                                 generate_digest(job, op, sess);
1230                         break;
1231                 default:
1232                         op->status = RTE_CRYPTO_OP_STATUS_ERROR;
1233                 }
1234         }
1235
1236         /* Free session if a session-less crypto op */
1237         if (op->sess_type == RTE_CRYPTO_OP_SESSIONLESS) {
1238                 memset(sess, 0, sizeof(struct aesni_mb_session));
1239                 memset(op->sym->session, 0,
1240                         rte_cryptodev_sym_get_existing_header_session_size(
1241                                 op->sym->session));
1242                 rte_mempool_put(qp->sess_mp_priv, sess);
1243                 rte_mempool_put(qp->sess_mp, op->sym->session);
1244                 op->sym->session = NULL;
1245         }
1246
1247         return op;
1248 }
1249
1250 static inline void
1251 post_process_mb_sync_job(JOB_AES_HMAC *job)
1252 {
1253         uint32_t *st;
1254
1255         st = job->user_data;
1256         st[0] = (job->status == STS_COMPLETED) ? 0 : EBADMSG;
1257 }
1258
1259 /**
1260  * Process a completed JOB_AES_HMAC job and keep processing jobs until
1261  * get_completed_job return NULL
1262  *
1263  * @param qp            Queue Pair to process
1264  * @param job           JOB_AES_HMAC job
1265  *
1266  * @return
1267  * - Number of processed jobs
1268  */
1269 static unsigned
1270 handle_completed_jobs(struct aesni_mb_qp *qp, JOB_AES_HMAC *job,
1271                 struct rte_crypto_op **ops, uint16_t nb_ops)
1272 {
1273         struct rte_crypto_op *op = NULL;
1274         unsigned processed_jobs = 0;
1275
1276         while (job != NULL) {
1277                 op = post_process_mb_job(qp, job);
1278
1279                 if (op) {
1280                         ops[processed_jobs++] = op;
1281                         qp->stats.dequeued_count++;
1282                 } else {
1283                         qp->stats.dequeue_err_count++;
1284                         break;
1285                 }
1286                 if (processed_jobs == nb_ops)
1287                         break;
1288
1289                 job = IMB_GET_COMPLETED_JOB(qp->mb_mgr);
1290         }
1291
1292         return processed_jobs;
1293 }
1294
1295 static inline uint32_t
1296 handle_completed_sync_jobs(JOB_AES_HMAC *job, MB_MGR *mb_mgr)
1297 {
1298         uint32_t i;
1299
1300         for (i = 0; job != NULL; i++, job = IMB_GET_COMPLETED_JOB(mb_mgr))
1301                 post_process_mb_sync_job(job);
1302
1303         return i;
1304 }
1305
1306 static inline uint32_t
1307 flush_mb_sync_mgr(MB_MGR *mb_mgr)
1308 {
1309         JOB_AES_HMAC *job;
1310
1311         job = IMB_FLUSH_JOB(mb_mgr);
1312         return handle_completed_sync_jobs(job, mb_mgr);
1313 }
1314
1315 static inline uint16_t
1316 flush_mb_mgr(struct aesni_mb_qp *qp, struct rte_crypto_op **ops,
1317                 uint16_t nb_ops)
1318 {
1319         int processed_ops = 0;
1320
1321         /* Flush the remaining jobs */
1322         JOB_AES_HMAC *job = IMB_FLUSH_JOB(qp->mb_mgr);
1323
1324         if (job)
1325                 processed_ops += handle_completed_jobs(qp, job,
1326                                 &ops[processed_ops], nb_ops - processed_ops);
1327
1328         return processed_ops;
1329 }
1330
1331 static inline JOB_AES_HMAC *
1332 set_job_null_op(JOB_AES_HMAC *job, struct rte_crypto_op *op)
1333 {
1334         job->chain_order = HASH_CIPHER;
1335         job->cipher_mode = NULL_CIPHER;
1336         job->hash_alg = NULL_HASH;
1337         job->cipher_direction = DECRYPT;
1338
1339         /* Set user data to be crypto operation data struct */
1340         job->user_data = op;
1341
1342         return job;
1343 }
1344
1345 static uint16_t
1346 aesni_mb_pmd_dequeue_burst(void *queue_pair, struct rte_crypto_op **ops,
1347                 uint16_t nb_ops)
1348 {
1349         struct aesni_mb_qp *qp = queue_pair;
1350
1351         struct rte_crypto_op *op;
1352         JOB_AES_HMAC *job;
1353
1354         int retval, processed_jobs = 0;
1355
1356         if (unlikely(nb_ops == 0))
1357                 return 0;
1358
1359         uint8_t digest_idx = qp->digest_idx;
1360         do {
1361                 /* Get next free mb job struct from mb manager */
1362                 job = IMB_GET_NEXT_JOB(qp->mb_mgr);
1363                 if (unlikely(job == NULL)) {
1364                         /* if no free mb job structs we need to flush mb_mgr */
1365                         processed_jobs += flush_mb_mgr(qp,
1366                                         &ops[processed_jobs],
1367                                         nb_ops - processed_jobs);
1368
1369                         if (nb_ops == processed_jobs)
1370                                 break;
1371
1372                         job = IMB_GET_NEXT_JOB(qp->mb_mgr);
1373                 }
1374
1375                 /*
1376                  * Get next operation to process from ingress queue.
1377                  * There is no need to return the job to the MB_MGR
1378                  * if there are no more operations to process, since the MB_MGR
1379                  * can use that pointer again in next get_next calls.
1380                  */
1381                 retval = rte_ring_dequeue(qp->ingress_queue, (void **)&op);
1382                 if (retval < 0)
1383                         break;
1384
1385                 retval = set_mb_job_params(job, qp, op, &digest_idx);
1386                 if (unlikely(retval != 0)) {
1387                         qp->stats.dequeue_err_count++;
1388                         set_job_null_op(job, op);
1389                 }
1390
1391                 /* Submit job to multi-buffer for processing */
1392 #ifdef RTE_LIBRTE_PMD_AESNI_MB_DEBUG
1393                 job = IMB_SUBMIT_JOB(qp->mb_mgr);
1394 #else
1395                 job = IMB_SUBMIT_JOB_NOCHECK(qp->mb_mgr);
1396 #endif
1397                 /*
1398                  * If submit returns a processed job then handle it,
1399                  * before submitting subsequent jobs
1400                  */
1401                 if (job)
1402                         processed_jobs += handle_completed_jobs(qp, job,
1403                                         &ops[processed_jobs],
1404                                         nb_ops - processed_jobs);
1405
1406         } while (processed_jobs < nb_ops);
1407
1408         qp->digest_idx = digest_idx;
1409
1410         if (processed_jobs < 1)
1411                 processed_jobs += flush_mb_mgr(qp,
1412                                 &ops[processed_jobs],
1413                                 nb_ops - processed_jobs);
1414
1415         return processed_jobs;
1416 }
1417
1418 static MB_MGR *
1419 alloc_init_mb_mgr(enum aesni_mb_vector_mode vector_mode)
1420 {
1421         MB_MGR *mb_mgr = alloc_mb_mgr(0);
1422         if (mb_mgr == NULL)
1423                 return NULL;
1424
1425         switch (vector_mode) {
1426         case RTE_AESNI_MB_SSE:
1427                 init_mb_mgr_sse(mb_mgr);
1428                 break;
1429         case RTE_AESNI_MB_AVX:
1430                 init_mb_mgr_avx(mb_mgr);
1431                 break;
1432         case RTE_AESNI_MB_AVX2:
1433                 init_mb_mgr_avx2(mb_mgr);
1434                 break;
1435         case RTE_AESNI_MB_AVX512:
1436                 init_mb_mgr_avx512(mb_mgr);
1437                 break;
1438         default:
1439                 AESNI_MB_LOG(ERR, "Unsupported vector mode %u\n", vector_mode);
1440                 free_mb_mgr(mb_mgr);
1441                 return NULL;
1442         }
1443
1444         return mb_mgr;
1445 }
1446
1447 static inline void
1448 aesni_mb_fill_error_code(struct rte_crypto_sym_vec *vec, int32_t err)
1449 {
1450         uint32_t i;
1451
1452         for (i = 0; i != vec->num; ++i)
1453                 vec->status[i] = err;
1454 }
1455
1456 static inline int
1457 check_crypto_sgl(union rte_crypto_sym_ofs so, const struct rte_crypto_sgl *sgl)
1458 {
1459         /* no multi-seg support with current AESNI-MB PMD */
1460         if (sgl->num != 1)
1461                 return ENOTSUP;
1462         else if (so.ofs.cipher.head + so.ofs.cipher.tail > sgl->vec[0].len)
1463                 return EINVAL;
1464         return 0;
1465 }
1466
1467 static inline JOB_AES_HMAC *
1468 submit_sync_job(MB_MGR *mb_mgr)
1469 {
1470 #ifdef RTE_LIBRTE_PMD_AESNI_MB_DEBUG
1471         return IMB_SUBMIT_JOB(mb_mgr);
1472 #else
1473         return IMB_SUBMIT_JOB_NOCHECK(mb_mgr);
1474 #endif
1475 }
1476
1477 static inline uint32_t
1478 generate_sync_dgst(struct rte_crypto_sym_vec *vec,
1479         const uint8_t dgst[][DIGEST_LENGTH_MAX], uint32_t len)
1480 {
1481         uint32_t i, k;
1482
1483         for (i = 0, k = 0; i != vec->num; i++) {
1484                 if (vec->status[i] == 0) {
1485                         memcpy(vec->digest[i], dgst[i], len);
1486                         k++;
1487                 }
1488         }
1489
1490         return k;
1491 }
1492
1493 static inline uint32_t
1494 verify_sync_dgst(struct rte_crypto_sym_vec *vec,
1495         const uint8_t dgst[][DIGEST_LENGTH_MAX], uint32_t len)
1496 {
1497         uint32_t i, k;
1498
1499         for (i = 0, k = 0; i != vec->num; i++) {
1500                 if (vec->status[i] == 0) {
1501                         if (memcmp(vec->digest[i], dgst[i], len) != 0)
1502                                 vec->status[i] = EBADMSG;
1503                         else
1504                                 k++;
1505                 }
1506         }
1507
1508         return k;
1509 }
1510
1511 uint32_t
1512 aesni_mb_cpu_crypto_process_bulk(struct rte_cryptodev *dev,
1513         struct rte_cryptodev_sym_session *sess, union rte_crypto_sym_ofs sofs,
1514         struct rte_crypto_sym_vec *vec)
1515 {
1516         int32_t ret;
1517         uint32_t i, j, k, len;
1518         void *buf;
1519         JOB_AES_HMAC *job;
1520         MB_MGR *mb_mgr;
1521         struct aesni_mb_private *priv;
1522         struct aesni_mb_session *s;
1523         uint8_t tmp_dgst[vec->num][DIGEST_LENGTH_MAX];
1524
1525         s = get_sym_session_private_data(sess, dev->driver_id);
1526         if (s == NULL) {
1527                 aesni_mb_fill_error_code(vec, EINVAL);
1528                 return 0;
1529         }
1530
1531         /* get per-thread MB MGR, create one if needed */
1532         mb_mgr = RTE_PER_LCORE(sync_mb_mgr);
1533         if (mb_mgr == NULL) {
1534
1535                 priv = dev->data->dev_private;
1536                 mb_mgr = alloc_init_mb_mgr(priv->vector_mode);
1537                 if (mb_mgr == NULL) {
1538                         aesni_mb_fill_error_code(vec, ENOMEM);
1539                         return 0;
1540                 }
1541                 RTE_PER_LCORE(sync_mb_mgr) = mb_mgr;
1542         }
1543
1544         for (i = 0, j = 0, k = 0; i != vec->num; i++) {
1545
1546
1547                 ret = check_crypto_sgl(sofs, vec->sgl + i);
1548                 if (ret != 0) {
1549                         vec->status[i] = ret;
1550                         continue;
1551                 }
1552
1553                 buf = vec->sgl[i].vec[0].base;
1554                 len = vec->sgl[i].vec[0].len;
1555
1556                 job = IMB_GET_NEXT_JOB(mb_mgr);
1557                 if (job == NULL) {
1558                         k += flush_mb_sync_mgr(mb_mgr);
1559                         job = IMB_GET_NEXT_JOB(mb_mgr);
1560                         RTE_ASSERT(job != NULL);
1561                 }
1562
1563                 /* Submit job for processing */
1564                 set_cpu_mb_job_params(job, s, sofs, buf, len,
1565                         vec->iv[i], vec->aad[i], tmp_dgst[i],
1566                         &vec->status[i]);
1567                 job = submit_sync_job(mb_mgr);
1568                 j++;
1569
1570                 /* handle completed jobs */
1571                 k += handle_completed_sync_jobs(job, mb_mgr);
1572         }
1573
1574         /* flush remaining jobs */
1575         while (k != j)
1576                 k += flush_mb_sync_mgr(mb_mgr);
1577
1578         /* finish processing for successful jobs: check/update digest */
1579         if (k != 0) {
1580                 if (s->auth.operation == RTE_CRYPTO_AUTH_OP_VERIFY)
1581                         k = verify_sync_dgst(vec,
1582                                 (const uint8_t (*)[DIGEST_LENGTH_MAX])tmp_dgst,
1583                                 s->auth.req_digest_len);
1584                 else
1585                         k = generate_sync_dgst(vec,
1586                                 (const uint8_t (*)[DIGEST_LENGTH_MAX])tmp_dgst,
1587                                 s->auth.req_digest_len);
1588         }
1589
1590         return k;
1591 }
1592
1593 static int cryptodev_aesni_mb_remove(struct rte_vdev_device *vdev);
1594
1595 static uint64_t
1596 vec_mode_to_flags(enum aesni_mb_vector_mode mode)
1597 {
1598         switch (mode) {
1599         case RTE_AESNI_MB_SSE:
1600                 return RTE_CRYPTODEV_FF_CPU_SSE;
1601         case RTE_AESNI_MB_AVX:
1602                 return RTE_CRYPTODEV_FF_CPU_AVX;
1603         case RTE_AESNI_MB_AVX2:
1604                 return RTE_CRYPTODEV_FF_CPU_AVX2;
1605         case RTE_AESNI_MB_AVX512:
1606                 return RTE_CRYPTODEV_FF_CPU_AVX512;
1607         default:
1608                 AESNI_MB_LOG(ERR, "Unsupported vector mode %u\n", mode);
1609                 return 0;
1610         }
1611 }
1612
1613 static int
1614 cryptodev_aesni_mb_create(const char *name,
1615                         struct rte_vdev_device *vdev,
1616                         struct rte_cryptodev_pmd_init_params *init_params)
1617 {
1618         struct rte_cryptodev *dev;
1619         struct aesni_mb_private *internals;
1620         enum aesni_mb_vector_mode vector_mode;
1621         MB_MGR *mb_mgr;
1622
1623         dev = rte_cryptodev_pmd_create(name, &vdev->device, init_params);
1624         if (dev == NULL) {
1625                 AESNI_MB_LOG(ERR, "failed to create cryptodev vdev");
1626                 return -ENODEV;
1627         }
1628
1629         /* Check CPU for supported vector instruction set */
1630         if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX512F))
1631                 vector_mode = RTE_AESNI_MB_AVX512;
1632         else if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX2))
1633                 vector_mode = RTE_AESNI_MB_AVX2;
1634         else if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX))
1635                 vector_mode = RTE_AESNI_MB_AVX;
1636         else
1637                 vector_mode = RTE_AESNI_MB_SSE;
1638
1639         dev->driver_id = cryptodev_driver_id;
1640         dev->dev_ops = rte_aesni_mb_pmd_ops;
1641
1642         /* register rx/tx burst functions for data path */
1643         dev->dequeue_burst = aesni_mb_pmd_dequeue_burst;
1644         dev->enqueue_burst = aesni_mb_pmd_enqueue_burst;
1645
1646         dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
1647                         RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
1648                         RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT |
1649                         RTE_CRYPTODEV_FF_SYM_CPU_CRYPTO |
1650                         RTE_CRYPTODEV_FF_SYM_SESSIONLESS;
1651
1652         /* Check CPU for support for AES instruction set */
1653         if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_AES))
1654                 dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_AESNI;
1655         else
1656                 AESNI_MB_LOG(WARNING, "AES instructions not supported by CPU");
1657
1658         dev->feature_flags |= vec_mode_to_flags(vector_mode);
1659
1660         mb_mgr = alloc_init_mb_mgr(vector_mode);
1661         if (mb_mgr == NULL) {
1662                 rte_cryptodev_pmd_destroy(dev);
1663                 return -ENOMEM;
1664         }
1665
1666         /* Set vector instructions mode supported */
1667         internals = dev->data->dev_private;
1668
1669         internals->vector_mode = vector_mode;
1670         internals->max_nb_queue_pairs = init_params->max_nb_queue_pairs;
1671         internals->mb_mgr = mb_mgr;
1672
1673         AESNI_MB_LOG(INFO, "IPSec Multi-buffer library version used: %s\n",
1674                         imb_get_version_str());
1675         return 0;
1676 }
1677
1678 static int
1679 cryptodev_aesni_mb_probe(struct rte_vdev_device *vdev)
1680 {
1681         struct rte_cryptodev_pmd_init_params init_params = {
1682                 "",
1683                 sizeof(struct aesni_mb_private),
1684                 rte_socket_id(),
1685                 RTE_CRYPTODEV_PMD_DEFAULT_MAX_NB_QUEUE_PAIRS
1686         };
1687         const char *name, *args;
1688         int retval;
1689
1690         name = rte_vdev_device_name(vdev);
1691         if (name == NULL)
1692                 return -EINVAL;
1693
1694         args = rte_vdev_device_args(vdev);
1695
1696         retval = rte_cryptodev_pmd_parse_input_args(&init_params, args);
1697         if (retval) {
1698                 AESNI_MB_LOG(ERR, "Failed to parse initialisation arguments[%s]",
1699                                 args);
1700                 return -EINVAL;
1701         }
1702
1703         return cryptodev_aesni_mb_create(name, vdev, &init_params);
1704 }
1705
1706 static int
1707 cryptodev_aesni_mb_remove(struct rte_vdev_device *vdev)
1708 {
1709         struct rte_cryptodev *cryptodev;
1710         struct aesni_mb_private *internals;
1711         const char *name;
1712
1713         name = rte_vdev_device_name(vdev);
1714         if (name == NULL)
1715                 return -EINVAL;
1716
1717         cryptodev = rte_cryptodev_pmd_get_named_dev(name);
1718         if (cryptodev == NULL)
1719                 return -ENODEV;
1720
1721         internals = cryptodev->data->dev_private;
1722
1723         free_mb_mgr(internals->mb_mgr);
1724         if (RTE_PER_LCORE(sync_mb_mgr)) {
1725                 free_mb_mgr(RTE_PER_LCORE(sync_mb_mgr));
1726                 RTE_PER_LCORE(sync_mb_mgr) = NULL;
1727         }
1728
1729         return rte_cryptodev_pmd_destroy(cryptodev);
1730 }
1731
1732 static struct rte_vdev_driver cryptodev_aesni_mb_pmd_drv = {
1733         .probe = cryptodev_aesni_mb_probe,
1734         .remove = cryptodev_aesni_mb_remove
1735 };
1736
1737 static struct cryptodev_driver aesni_mb_crypto_drv;
1738
1739 RTE_PMD_REGISTER_VDEV(CRYPTODEV_NAME_AESNI_MB_PMD, cryptodev_aesni_mb_pmd_drv);
1740 RTE_PMD_REGISTER_ALIAS(CRYPTODEV_NAME_AESNI_MB_PMD, cryptodev_aesni_mb_pmd);
1741 RTE_PMD_REGISTER_PARAM_STRING(CRYPTODEV_NAME_AESNI_MB_PMD,
1742         "max_nb_queue_pairs=<int> "
1743         "socket_id=<int>");
1744 RTE_PMD_REGISTER_CRYPTO_DRIVER(aesni_mb_crypto_drv,
1745                 cryptodev_aesni_mb_pmd_drv.driver,
1746                 cryptodev_driver_id);
1747
1748 RTE_INIT(aesni_mb_init_log)
1749 {
1750         aesni_mb_logtype_driver = rte_log_register("pmd.crypto.aesni_mb");
1751 }