1169ca3dbSZbigniew Bodek /* 2169ca3dbSZbigniew Bodek * BSD LICENSE 3169ca3dbSZbigniew Bodek * 4169ca3dbSZbigniew Bodek * Copyright (C) Cavium networks Ltd. 2017. 5169ca3dbSZbigniew Bodek * 6169ca3dbSZbigniew Bodek * Redistribution and use in source and binary forms, with or without 7169ca3dbSZbigniew Bodek * modification, are permitted provided that the following conditions 8169ca3dbSZbigniew Bodek * are met: 9169ca3dbSZbigniew Bodek * 10169ca3dbSZbigniew Bodek * * Redistributions of source code must retain the above copyright 11169ca3dbSZbigniew Bodek * notice, this list of conditions and the following disclaimer. 12169ca3dbSZbigniew Bodek * * Redistributions in binary form must reproduce the above copyright 13169ca3dbSZbigniew Bodek * notice, this list of conditions and the following disclaimer in 14169ca3dbSZbigniew Bodek * the documentation and/or other materials provided with the 15169ca3dbSZbigniew Bodek * distribution. 16169ca3dbSZbigniew Bodek * * Neither the name of Cavium networks nor the names of its 17169ca3dbSZbigniew Bodek * contributors may be used to endorse or promote products derived 18169ca3dbSZbigniew Bodek * from this software without specific prior written permission. 19169ca3dbSZbigniew Bodek * 20169ca3dbSZbigniew Bodek * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21169ca3dbSZbigniew Bodek * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22169ca3dbSZbigniew Bodek * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23169ca3dbSZbigniew Bodek * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24169ca3dbSZbigniew Bodek * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25169ca3dbSZbigniew Bodek * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26169ca3dbSZbigniew Bodek * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27169ca3dbSZbigniew Bodek * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28169ca3dbSZbigniew Bodek * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29169ca3dbSZbigniew Bodek * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30169ca3dbSZbigniew Bodek * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31169ca3dbSZbigniew Bodek */ 32169ca3dbSZbigniew Bodek 33169ca3dbSZbigniew Bodek #include <stdbool.h> 34169ca3dbSZbigniew Bodek 35169ca3dbSZbigniew Bodek #include <rte_common.h> 36169ca3dbSZbigniew Bodek #include <rte_hexdump.h> 37169ca3dbSZbigniew Bodek #include <rte_cryptodev.h> 38169ca3dbSZbigniew Bodek #include <rte_cryptodev_pmd.h> 3963348b9dSPablo de Lara #include <rte_cryptodev_vdev.h> 40169ca3dbSZbigniew Bodek #include <rte_vdev.h> 41169ca3dbSZbigniew Bodek #include <rte_malloc.h> 42169ca3dbSZbigniew Bodek #include <rte_cpuflags.h> 43169ca3dbSZbigniew Bodek 44169ca3dbSZbigniew Bodek #include "armv8_crypto_defs.h" 45169ca3dbSZbigniew Bodek 46169ca3dbSZbigniew Bodek #include "rte_armv8_pmd_private.h" 47169ca3dbSZbigniew Bodek 485d2aa461SJan Blunck static int cryptodev_armv8_crypto_uninit(struct rte_vdev_device *vdev); 49169ca3dbSZbigniew Bodek 50169ca3dbSZbigniew Bodek /** 51169ca3dbSZbigniew Bodek * Pointers to the supported combined mode crypto functions are stored 52169ca3dbSZbigniew Bodek * in the static tables. Each combined (chained) cryptographic operation 53169ca3dbSZbigniew Bodek * can be described by a set of numbers: 54169ca3dbSZbigniew Bodek * - order: order of operations (cipher, auth) or (auth, cipher) 55169ca3dbSZbigniew Bodek * - direction: encryption or decryption 56169ca3dbSZbigniew Bodek * - calg: cipher algorithm such as AES_CBC, AES_CTR, etc. 57169ca3dbSZbigniew Bodek * - aalg: authentication algorithm such as SHA1, SHA256, etc. 58169ca3dbSZbigniew Bodek * - keyl: cipher key length, for example 128, 192, 256 bits 59169ca3dbSZbigniew Bodek * 60169ca3dbSZbigniew Bodek * In order to quickly acquire each function pointer based on those numbers, 61169ca3dbSZbigniew Bodek * a hierarchy of arrays is maintained. The final level, 3D array is indexed 62169ca3dbSZbigniew Bodek * by the combined mode function parameters only (cipher algorithm, 63169ca3dbSZbigniew Bodek * authentication algorithm and key length). 64169ca3dbSZbigniew Bodek * 65169ca3dbSZbigniew Bodek * This gives 3 memory accesses to obtain a function pointer instead of 66169ca3dbSZbigniew Bodek * traversing the array manually and comparing function parameters on each loop. 67169ca3dbSZbigniew Bodek * 68169ca3dbSZbigniew Bodek * +--+CRYPTO_FUNC 69169ca3dbSZbigniew Bodek * +--+ENC| 70169ca3dbSZbigniew Bodek * +--+CA| 71169ca3dbSZbigniew Bodek * | +--+DEC 72169ca3dbSZbigniew Bodek * ORDER| 73169ca3dbSZbigniew Bodek * | +--+ENC 74169ca3dbSZbigniew Bodek * +--+AC| 75169ca3dbSZbigniew Bodek * +--+DEC 76169ca3dbSZbigniew Bodek * 77169ca3dbSZbigniew Bodek */ 78169ca3dbSZbigniew Bodek 79169ca3dbSZbigniew Bodek /** 80169ca3dbSZbigniew Bodek * 3D array type for ARM Combined Mode crypto functions pointers. 81169ca3dbSZbigniew Bodek * CRYPTO_CIPHER_MAX: max cipher ID number 82169ca3dbSZbigniew Bodek * CRYPTO_AUTH_MAX: max auth ID number 83169ca3dbSZbigniew Bodek * CRYPTO_CIPHER_KEYLEN_MAX: max key length ID number 84169ca3dbSZbigniew Bodek */ 85169ca3dbSZbigniew Bodek typedef const crypto_func_t 86169ca3dbSZbigniew Bodek crypto_func_tbl_t[CRYPTO_CIPHER_MAX][CRYPTO_AUTH_MAX][CRYPTO_CIPHER_KEYLEN_MAX]; 87169ca3dbSZbigniew Bodek 88169ca3dbSZbigniew Bodek /* Evaluate to key length definition */ 89169ca3dbSZbigniew Bodek #define KEYL(keyl) (ARMV8_CRYPTO_CIPHER_KEYLEN_ ## keyl) 90169ca3dbSZbigniew Bodek 91169ca3dbSZbigniew Bodek /* Local aliases for supported ciphers */ 92169ca3dbSZbigniew Bodek #define CIPH_AES_CBC RTE_CRYPTO_CIPHER_AES_CBC 93169ca3dbSZbigniew Bodek /* Local aliases for supported hashes */ 94169ca3dbSZbigniew Bodek #define AUTH_SHA1_HMAC RTE_CRYPTO_AUTH_SHA1_HMAC 95169ca3dbSZbigniew Bodek #define AUTH_SHA256_HMAC RTE_CRYPTO_AUTH_SHA256_HMAC 96169ca3dbSZbigniew Bodek 97169ca3dbSZbigniew Bodek /** 98169ca3dbSZbigniew Bodek * Arrays containing pointers to particular cryptographic, 99169ca3dbSZbigniew Bodek * combined mode functions. 100169ca3dbSZbigniew Bodek * crypto_op_ca_encrypt: cipher (encrypt), authenticate 101169ca3dbSZbigniew Bodek * crypto_op_ca_decrypt: cipher (decrypt), authenticate 102169ca3dbSZbigniew Bodek * crypto_op_ac_encrypt: authenticate, cipher (encrypt) 103169ca3dbSZbigniew Bodek * crypto_op_ac_decrypt: authenticate, cipher (decrypt) 104169ca3dbSZbigniew Bodek */ 105169ca3dbSZbigniew Bodek static const crypto_func_tbl_t 106169ca3dbSZbigniew Bodek crypto_op_ca_encrypt = { 107169ca3dbSZbigniew Bodek /* [cipher alg][auth alg][key length] = crypto_function, */ 108169ca3dbSZbigniew Bodek [CIPH_AES_CBC][AUTH_SHA1_HMAC][KEYL(128)] = aes128cbc_sha1_hmac, 109169ca3dbSZbigniew Bodek [CIPH_AES_CBC][AUTH_SHA256_HMAC][KEYL(128)] = aes128cbc_sha256_hmac, 110169ca3dbSZbigniew Bodek }; 111169ca3dbSZbigniew Bodek 112169ca3dbSZbigniew Bodek static const crypto_func_tbl_t 113169ca3dbSZbigniew Bodek crypto_op_ca_decrypt = { 114169ca3dbSZbigniew Bodek NULL 115169ca3dbSZbigniew Bodek }; 116169ca3dbSZbigniew Bodek 117169ca3dbSZbigniew Bodek static const crypto_func_tbl_t 118169ca3dbSZbigniew Bodek crypto_op_ac_encrypt = { 119169ca3dbSZbigniew Bodek NULL 120169ca3dbSZbigniew Bodek }; 121169ca3dbSZbigniew Bodek 122169ca3dbSZbigniew Bodek static const crypto_func_tbl_t 123169ca3dbSZbigniew Bodek crypto_op_ac_decrypt = { 124169ca3dbSZbigniew Bodek /* [cipher alg][auth alg][key length] = crypto_function, */ 125169ca3dbSZbigniew Bodek [CIPH_AES_CBC][AUTH_SHA1_HMAC][KEYL(128)] = sha1_hmac_aes128cbc_dec, 126169ca3dbSZbigniew Bodek [CIPH_AES_CBC][AUTH_SHA256_HMAC][KEYL(128)] = sha256_hmac_aes128cbc_dec, 127169ca3dbSZbigniew Bodek }; 128169ca3dbSZbigniew Bodek 129169ca3dbSZbigniew Bodek /** 130169ca3dbSZbigniew Bodek * Arrays containing pointers to particular cryptographic function sets, 131169ca3dbSZbigniew Bodek * covering given cipher operation directions (encrypt, decrypt) 132169ca3dbSZbigniew Bodek * for each order of cipher and authentication pairs. 133169ca3dbSZbigniew Bodek */ 134169ca3dbSZbigniew Bodek static const crypto_func_tbl_t * 135169ca3dbSZbigniew Bodek crypto_cipher_auth[] = { 136169ca3dbSZbigniew Bodek &crypto_op_ca_encrypt, 137169ca3dbSZbigniew Bodek &crypto_op_ca_decrypt, 138169ca3dbSZbigniew Bodek NULL 139169ca3dbSZbigniew Bodek }; 140169ca3dbSZbigniew Bodek 141169ca3dbSZbigniew Bodek static const crypto_func_tbl_t * 142169ca3dbSZbigniew Bodek crypto_auth_cipher[] = { 143169ca3dbSZbigniew Bodek &crypto_op_ac_encrypt, 144169ca3dbSZbigniew Bodek &crypto_op_ac_decrypt, 145169ca3dbSZbigniew Bodek NULL 146169ca3dbSZbigniew Bodek }; 147169ca3dbSZbigniew Bodek 148169ca3dbSZbigniew Bodek /** 149169ca3dbSZbigniew Bodek * Top level array containing pointers to particular cryptographic 150169ca3dbSZbigniew Bodek * function sets, covering given order of chained operations. 151169ca3dbSZbigniew Bodek * crypto_cipher_auth: cipher first, authenticate after 152169ca3dbSZbigniew Bodek * crypto_auth_cipher: authenticate first, cipher after 153169ca3dbSZbigniew Bodek */ 154169ca3dbSZbigniew Bodek static const crypto_func_tbl_t ** 155169ca3dbSZbigniew Bodek crypto_chain_order[] = { 156169ca3dbSZbigniew Bodek crypto_cipher_auth, 157169ca3dbSZbigniew Bodek crypto_auth_cipher, 158169ca3dbSZbigniew Bodek NULL 159169ca3dbSZbigniew Bodek }; 160169ca3dbSZbigniew Bodek 161169ca3dbSZbigniew Bodek /** 162169ca3dbSZbigniew Bodek * Extract particular combined mode crypto function from the 3D array. 163169ca3dbSZbigniew Bodek */ 164169ca3dbSZbigniew Bodek #define CRYPTO_GET_ALGO(order, cop, calg, aalg, keyl) \ 165169ca3dbSZbigniew Bodek ({ \ 166169ca3dbSZbigniew Bodek crypto_func_tbl_t *func_tbl = \ 167169ca3dbSZbigniew Bodek (crypto_chain_order[(order)])[(cop)]; \ 168169ca3dbSZbigniew Bodek \ 169169ca3dbSZbigniew Bodek ((*func_tbl)[(calg)][(aalg)][KEYL(keyl)]); \ 170169ca3dbSZbigniew Bodek }) 171169ca3dbSZbigniew Bodek 172169ca3dbSZbigniew Bodek /*----------------------------------------------------------------------------*/ 173169ca3dbSZbigniew Bodek 174169ca3dbSZbigniew Bodek /** 175169ca3dbSZbigniew Bodek * 2D array type for ARM key schedule functions pointers. 176169ca3dbSZbigniew Bodek * CRYPTO_CIPHER_MAX: max cipher ID number 177169ca3dbSZbigniew Bodek * CRYPTO_CIPHER_KEYLEN_MAX: max key length ID number 178169ca3dbSZbigniew Bodek */ 179169ca3dbSZbigniew Bodek typedef const crypto_key_sched_t 180169ca3dbSZbigniew Bodek crypto_key_sched_tbl_t[CRYPTO_CIPHER_MAX][CRYPTO_CIPHER_KEYLEN_MAX]; 181169ca3dbSZbigniew Bodek 182169ca3dbSZbigniew Bodek static const crypto_key_sched_tbl_t 183169ca3dbSZbigniew Bodek crypto_key_sched_encrypt = { 184169ca3dbSZbigniew Bodek /* [cipher alg][key length] = key_expand_func, */ 185169ca3dbSZbigniew Bodek [CIPH_AES_CBC][KEYL(128)] = aes128_key_sched_enc, 186169ca3dbSZbigniew Bodek }; 187169ca3dbSZbigniew Bodek 188169ca3dbSZbigniew Bodek static const crypto_key_sched_tbl_t 189169ca3dbSZbigniew Bodek crypto_key_sched_decrypt = { 190169ca3dbSZbigniew Bodek /* [cipher alg][key length] = key_expand_func, */ 191169ca3dbSZbigniew Bodek [CIPH_AES_CBC][KEYL(128)] = aes128_key_sched_dec, 192169ca3dbSZbigniew Bodek }; 193169ca3dbSZbigniew Bodek 194169ca3dbSZbigniew Bodek /** 195169ca3dbSZbigniew Bodek * Top level array containing pointers to particular key generation 196169ca3dbSZbigniew Bodek * function sets, covering given operation direction. 197169ca3dbSZbigniew Bodek * crypto_key_sched_encrypt: keys for encryption 198169ca3dbSZbigniew Bodek * crypto_key_sched_decrypt: keys for decryption 199169ca3dbSZbigniew Bodek */ 200169ca3dbSZbigniew Bodek static const crypto_key_sched_tbl_t * 201169ca3dbSZbigniew Bodek crypto_key_sched_dir[] = { 202169ca3dbSZbigniew Bodek &crypto_key_sched_encrypt, 203169ca3dbSZbigniew Bodek &crypto_key_sched_decrypt, 204169ca3dbSZbigniew Bodek NULL 205169ca3dbSZbigniew Bodek }; 206169ca3dbSZbigniew Bodek 207169ca3dbSZbigniew Bodek /** 208169ca3dbSZbigniew Bodek * Extract particular combined mode crypto function from the 3D array. 209169ca3dbSZbigniew Bodek */ 210169ca3dbSZbigniew Bodek #define CRYPTO_GET_KEY_SCHED(cop, calg, keyl) \ 211169ca3dbSZbigniew Bodek ({ \ 212169ca3dbSZbigniew Bodek crypto_key_sched_tbl_t *ks_tbl = crypto_key_sched_dir[(cop)]; \ 213169ca3dbSZbigniew Bodek \ 214169ca3dbSZbigniew Bodek ((*ks_tbl)[(calg)][KEYL(keyl)]); \ 215169ca3dbSZbigniew Bodek }) 216169ca3dbSZbigniew Bodek 217169ca3dbSZbigniew Bodek /*----------------------------------------------------------------------------*/ 218169ca3dbSZbigniew Bodek 219169ca3dbSZbigniew Bodek /* 220169ca3dbSZbigniew Bodek *------------------------------------------------------------------------------ 221169ca3dbSZbigniew Bodek * Session Prepare 222169ca3dbSZbigniew Bodek *------------------------------------------------------------------------------ 223169ca3dbSZbigniew Bodek */ 224169ca3dbSZbigniew Bodek 225169ca3dbSZbigniew Bodek /** Get xform chain order */ 226169ca3dbSZbigniew Bodek static enum armv8_crypto_chain_order 227169ca3dbSZbigniew Bodek armv8_crypto_get_chain_order(const struct rte_crypto_sym_xform *xform) 228169ca3dbSZbigniew Bodek { 229169ca3dbSZbigniew Bodek 230169ca3dbSZbigniew Bodek /* 231169ca3dbSZbigniew Bodek * This driver currently covers only chained operations. 232169ca3dbSZbigniew Bodek * Ignore only cipher or only authentication operations 233169ca3dbSZbigniew Bodek * or chains longer than 2 xform structures. 234169ca3dbSZbigniew Bodek */ 235169ca3dbSZbigniew Bodek if (xform->next == NULL || xform->next->next != NULL) 236169ca3dbSZbigniew Bodek return ARMV8_CRYPTO_CHAIN_NOT_SUPPORTED; 237169ca3dbSZbigniew Bodek 238169ca3dbSZbigniew Bodek if (xform->type == RTE_CRYPTO_SYM_XFORM_AUTH) { 239169ca3dbSZbigniew Bodek if (xform->next->type == RTE_CRYPTO_SYM_XFORM_CIPHER) 240169ca3dbSZbigniew Bodek return ARMV8_CRYPTO_CHAIN_AUTH_CIPHER; 241169ca3dbSZbigniew Bodek } 242169ca3dbSZbigniew Bodek 243169ca3dbSZbigniew Bodek if (xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER) { 244169ca3dbSZbigniew Bodek if (xform->next->type == RTE_CRYPTO_SYM_XFORM_AUTH) 245169ca3dbSZbigniew Bodek return ARMV8_CRYPTO_CHAIN_CIPHER_AUTH; 246169ca3dbSZbigniew Bodek } 247169ca3dbSZbigniew Bodek 248169ca3dbSZbigniew Bodek return ARMV8_CRYPTO_CHAIN_NOT_SUPPORTED; 249169ca3dbSZbigniew Bodek } 250169ca3dbSZbigniew Bodek 251169ca3dbSZbigniew Bodek static inline void 252169ca3dbSZbigniew Bodek auth_hmac_pad_prepare(struct armv8_crypto_session *sess, 253169ca3dbSZbigniew Bodek const struct rte_crypto_sym_xform *xform) 254169ca3dbSZbigniew Bodek { 255169ca3dbSZbigniew Bodek size_t i; 256169ca3dbSZbigniew Bodek 257169ca3dbSZbigniew Bodek /* Generate i_key_pad and o_key_pad */ 258169ca3dbSZbigniew Bodek memset(sess->auth.hmac.i_key_pad, 0, sizeof(sess->auth.hmac.i_key_pad)); 259169ca3dbSZbigniew Bodek rte_memcpy(sess->auth.hmac.i_key_pad, sess->auth.hmac.key, 260169ca3dbSZbigniew Bodek xform->auth.key.length); 261169ca3dbSZbigniew Bodek memset(sess->auth.hmac.o_key_pad, 0, sizeof(sess->auth.hmac.o_key_pad)); 262169ca3dbSZbigniew Bodek rte_memcpy(sess->auth.hmac.o_key_pad, sess->auth.hmac.key, 263169ca3dbSZbigniew Bodek xform->auth.key.length); 264169ca3dbSZbigniew Bodek /* 265169ca3dbSZbigniew Bodek * XOR key with IPAD/OPAD values to obtain i_key_pad 266169ca3dbSZbigniew Bodek * and o_key_pad. 267169ca3dbSZbigniew Bodek * Byte-by-byte operation may seem to be the less efficient 268169ca3dbSZbigniew Bodek * here but in fact it's the opposite. 269169ca3dbSZbigniew Bodek * The result ASM code is likely operate on NEON registers 270169ca3dbSZbigniew Bodek * (load auth key to Qx, load IPAD/OPAD to multiple 271169ca3dbSZbigniew Bodek * elements of Qy, eor 128 bits at once). 272169ca3dbSZbigniew Bodek */ 273169ca3dbSZbigniew Bodek for (i = 0; i < SHA_BLOCK_MAX; i++) { 274169ca3dbSZbigniew Bodek sess->auth.hmac.i_key_pad[i] ^= HMAC_IPAD_VALUE; 275169ca3dbSZbigniew Bodek sess->auth.hmac.o_key_pad[i] ^= HMAC_OPAD_VALUE; 276169ca3dbSZbigniew Bodek } 277169ca3dbSZbigniew Bodek } 278169ca3dbSZbigniew Bodek 279169ca3dbSZbigniew Bodek static inline int 280169ca3dbSZbigniew Bodek auth_set_prerequisites(struct armv8_crypto_session *sess, 281169ca3dbSZbigniew Bodek const struct rte_crypto_sym_xform *xform) 282169ca3dbSZbigniew Bodek { 283169ca3dbSZbigniew Bodek uint8_t partial[64] = { 0 }; 284169ca3dbSZbigniew Bodek int error; 285169ca3dbSZbigniew Bodek 286169ca3dbSZbigniew Bodek switch (xform->auth.algo) { 287169ca3dbSZbigniew Bodek case RTE_CRYPTO_AUTH_SHA1_HMAC: 288169ca3dbSZbigniew Bodek /* 289169ca3dbSZbigniew Bodek * Generate authentication key, i_key_pad and o_key_pad. 290169ca3dbSZbigniew Bodek */ 291169ca3dbSZbigniew Bodek /* Zero memory under key */ 292169ca3dbSZbigniew Bodek memset(sess->auth.hmac.key, 0, SHA1_AUTH_KEY_LENGTH); 293169ca3dbSZbigniew Bodek 294169ca3dbSZbigniew Bodek if (xform->auth.key.length > SHA1_AUTH_KEY_LENGTH) { 295169ca3dbSZbigniew Bodek /* 296169ca3dbSZbigniew Bodek * In case the key is longer than 160 bits 297169ca3dbSZbigniew Bodek * the algorithm will use SHA1(key) instead. 298169ca3dbSZbigniew Bodek */ 299169ca3dbSZbigniew Bodek error = sha1_block(NULL, xform->auth.key.data, 300169ca3dbSZbigniew Bodek sess->auth.hmac.key, xform->auth.key.length); 301169ca3dbSZbigniew Bodek if (error != 0) 302169ca3dbSZbigniew Bodek return -1; 303169ca3dbSZbigniew Bodek } else { 304169ca3dbSZbigniew Bodek /* 305169ca3dbSZbigniew Bodek * Now copy the given authentication key to the session 306169ca3dbSZbigniew Bodek * key assuming that the session key is zeroed there is 307169ca3dbSZbigniew Bodek * no need for additional zero padding if the key is 308169ca3dbSZbigniew Bodek * shorter than SHA1_AUTH_KEY_LENGTH. 309169ca3dbSZbigniew Bodek */ 310169ca3dbSZbigniew Bodek rte_memcpy(sess->auth.hmac.key, xform->auth.key.data, 311169ca3dbSZbigniew Bodek xform->auth.key.length); 312169ca3dbSZbigniew Bodek } 313169ca3dbSZbigniew Bodek 314169ca3dbSZbigniew Bodek /* Prepare HMAC padding: key|pattern */ 315169ca3dbSZbigniew Bodek auth_hmac_pad_prepare(sess, xform); 316169ca3dbSZbigniew Bodek /* 317169ca3dbSZbigniew Bodek * Calculate partial hash values for i_key_pad and o_key_pad. 318169ca3dbSZbigniew Bodek * Will be used as initialization state for final HMAC. 319169ca3dbSZbigniew Bodek */ 320169ca3dbSZbigniew Bodek error = sha1_block_partial(NULL, sess->auth.hmac.i_key_pad, 321169ca3dbSZbigniew Bodek partial, SHA1_BLOCK_SIZE); 322169ca3dbSZbigniew Bodek if (error != 0) 323169ca3dbSZbigniew Bodek return -1; 324169ca3dbSZbigniew Bodek memcpy(sess->auth.hmac.i_key_pad, partial, SHA1_BLOCK_SIZE); 325169ca3dbSZbigniew Bodek 326169ca3dbSZbigniew Bodek error = sha1_block_partial(NULL, sess->auth.hmac.o_key_pad, 327169ca3dbSZbigniew Bodek partial, SHA1_BLOCK_SIZE); 328169ca3dbSZbigniew Bodek if (error != 0) 329169ca3dbSZbigniew Bodek return -1; 330169ca3dbSZbigniew Bodek memcpy(sess->auth.hmac.o_key_pad, partial, SHA1_BLOCK_SIZE); 331169ca3dbSZbigniew Bodek 332169ca3dbSZbigniew Bodek break; 333169ca3dbSZbigniew Bodek case RTE_CRYPTO_AUTH_SHA256_HMAC: 334169ca3dbSZbigniew Bodek /* 335169ca3dbSZbigniew Bodek * Generate authentication key, i_key_pad and o_key_pad. 336169ca3dbSZbigniew Bodek */ 337169ca3dbSZbigniew Bodek /* Zero memory under key */ 338169ca3dbSZbigniew Bodek memset(sess->auth.hmac.key, 0, SHA256_AUTH_KEY_LENGTH); 339169ca3dbSZbigniew Bodek 340169ca3dbSZbigniew Bodek if (xform->auth.key.length > SHA256_AUTH_KEY_LENGTH) { 341169ca3dbSZbigniew Bodek /* 342169ca3dbSZbigniew Bodek * In case the key is longer than 256 bits 343169ca3dbSZbigniew Bodek * the algorithm will use SHA256(key) instead. 344169ca3dbSZbigniew Bodek */ 345169ca3dbSZbigniew Bodek error = sha256_block(NULL, xform->auth.key.data, 346169ca3dbSZbigniew Bodek sess->auth.hmac.key, xform->auth.key.length); 347169ca3dbSZbigniew Bodek if (error != 0) 348169ca3dbSZbigniew Bodek return -1; 349169ca3dbSZbigniew Bodek } else { 350169ca3dbSZbigniew Bodek /* 351169ca3dbSZbigniew Bodek * Now copy the given authentication key to the session 352169ca3dbSZbigniew Bodek * key assuming that the session key is zeroed there is 353169ca3dbSZbigniew Bodek * no need for additional zero padding if the key is 354169ca3dbSZbigniew Bodek * shorter than SHA256_AUTH_KEY_LENGTH. 355169ca3dbSZbigniew Bodek */ 356169ca3dbSZbigniew Bodek rte_memcpy(sess->auth.hmac.key, xform->auth.key.data, 357169ca3dbSZbigniew Bodek xform->auth.key.length); 358169ca3dbSZbigniew Bodek } 359169ca3dbSZbigniew Bodek 360169ca3dbSZbigniew Bodek /* Prepare HMAC padding: key|pattern */ 361169ca3dbSZbigniew Bodek auth_hmac_pad_prepare(sess, xform); 362169ca3dbSZbigniew Bodek /* 363169ca3dbSZbigniew Bodek * Calculate partial hash values for i_key_pad and o_key_pad. 364169ca3dbSZbigniew Bodek * Will be used as initialization state for final HMAC. 365169ca3dbSZbigniew Bodek */ 366169ca3dbSZbigniew Bodek error = sha256_block_partial(NULL, sess->auth.hmac.i_key_pad, 367169ca3dbSZbigniew Bodek partial, SHA256_BLOCK_SIZE); 368169ca3dbSZbigniew Bodek if (error != 0) 369169ca3dbSZbigniew Bodek return -1; 370169ca3dbSZbigniew Bodek memcpy(sess->auth.hmac.i_key_pad, partial, SHA256_BLOCK_SIZE); 371169ca3dbSZbigniew Bodek 372169ca3dbSZbigniew Bodek error = sha256_block_partial(NULL, sess->auth.hmac.o_key_pad, 373169ca3dbSZbigniew Bodek partial, SHA256_BLOCK_SIZE); 374169ca3dbSZbigniew Bodek if (error != 0) 375169ca3dbSZbigniew Bodek return -1; 376169ca3dbSZbigniew Bodek memcpy(sess->auth.hmac.o_key_pad, partial, SHA256_BLOCK_SIZE); 377169ca3dbSZbigniew Bodek 378169ca3dbSZbigniew Bodek break; 379169ca3dbSZbigniew Bodek default: 380169ca3dbSZbigniew Bodek break; 381169ca3dbSZbigniew Bodek } 382169ca3dbSZbigniew Bodek 383169ca3dbSZbigniew Bodek return 0; 384169ca3dbSZbigniew Bodek } 385169ca3dbSZbigniew Bodek 386169ca3dbSZbigniew Bodek static inline int 387169ca3dbSZbigniew Bodek cipher_set_prerequisites(struct armv8_crypto_session *sess, 388169ca3dbSZbigniew Bodek const struct rte_crypto_sym_xform *xform) 389169ca3dbSZbigniew Bodek { 390169ca3dbSZbigniew Bodek crypto_key_sched_t cipher_key_sched; 391169ca3dbSZbigniew Bodek 392169ca3dbSZbigniew Bodek cipher_key_sched = sess->cipher.key_sched; 393169ca3dbSZbigniew Bodek if (likely(cipher_key_sched != NULL)) { 394169ca3dbSZbigniew Bodek /* Set up cipher session key */ 395169ca3dbSZbigniew Bodek cipher_key_sched(sess->cipher.key.data, xform->cipher.key.data); 396169ca3dbSZbigniew Bodek } 397169ca3dbSZbigniew Bodek 398169ca3dbSZbigniew Bodek return 0; 399169ca3dbSZbigniew Bodek } 400169ca3dbSZbigniew Bodek 401169ca3dbSZbigniew Bodek static int 402169ca3dbSZbigniew Bodek armv8_crypto_set_session_chained_parameters(struct armv8_crypto_session *sess, 403169ca3dbSZbigniew Bodek const struct rte_crypto_sym_xform *cipher_xform, 404169ca3dbSZbigniew Bodek const struct rte_crypto_sym_xform *auth_xform) 405169ca3dbSZbigniew Bodek { 406169ca3dbSZbigniew Bodek enum armv8_crypto_chain_order order; 407169ca3dbSZbigniew Bodek enum armv8_crypto_cipher_operation cop; 408169ca3dbSZbigniew Bodek enum rte_crypto_cipher_algorithm calg; 409169ca3dbSZbigniew Bodek enum rte_crypto_auth_algorithm aalg; 410169ca3dbSZbigniew Bodek 411169ca3dbSZbigniew Bodek /* Validate and prepare scratch order of combined operations */ 412169ca3dbSZbigniew Bodek switch (sess->chain_order) { 413169ca3dbSZbigniew Bodek case ARMV8_CRYPTO_CHAIN_CIPHER_AUTH: 414169ca3dbSZbigniew Bodek case ARMV8_CRYPTO_CHAIN_AUTH_CIPHER: 415169ca3dbSZbigniew Bodek order = sess->chain_order; 416169ca3dbSZbigniew Bodek break; 417169ca3dbSZbigniew Bodek default: 418169ca3dbSZbigniew Bodek return -EINVAL; 419169ca3dbSZbigniew Bodek } 420169ca3dbSZbigniew Bodek /* Select cipher direction */ 421169ca3dbSZbigniew Bodek sess->cipher.direction = cipher_xform->cipher.op; 422169ca3dbSZbigniew Bodek /* Select cipher key */ 423169ca3dbSZbigniew Bodek sess->cipher.key.length = cipher_xform->cipher.key.length; 424169ca3dbSZbigniew Bodek /* Set cipher direction */ 425169ca3dbSZbigniew Bodek cop = sess->cipher.direction; 426169ca3dbSZbigniew Bodek /* Set cipher algorithm */ 427169ca3dbSZbigniew Bodek calg = cipher_xform->cipher.algo; 428169ca3dbSZbigniew Bodek 429169ca3dbSZbigniew Bodek /* Select cipher algo */ 430169ca3dbSZbigniew Bodek switch (calg) { 431169ca3dbSZbigniew Bodek /* Cover supported cipher algorithms */ 432169ca3dbSZbigniew Bodek case RTE_CRYPTO_CIPHER_AES_CBC: 433169ca3dbSZbigniew Bodek sess->cipher.algo = calg; 434169ca3dbSZbigniew Bodek /* IV len is always 16 bytes (block size) for AES CBC */ 435*0fbd75a9SPablo de Lara sess->cipher.iv.length = 16; 436169ca3dbSZbigniew Bodek break; 437169ca3dbSZbigniew Bodek default: 438169ca3dbSZbigniew Bodek return -EINVAL; 439169ca3dbSZbigniew Bodek } 440169ca3dbSZbigniew Bodek /* Select auth generate/verify */ 441169ca3dbSZbigniew Bodek sess->auth.operation = auth_xform->auth.op; 442169ca3dbSZbigniew Bodek 443169ca3dbSZbigniew Bodek /* Select auth algo */ 444169ca3dbSZbigniew Bodek switch (auth_xform->auth.algo) { 445169ca3dbSZbigniew Bodek /* Cover supported hash algorithms */ 446169ca3dbSZbigniew Bodek case RTE_CRYPTO_AUTH_SHA1_HMAC: 447169ca3dbSZbigniew Bodek case RTE_CRYPTO_AUTH_SHA256_HMAC: /* Fall through */ 448169ca3dbSZbigniew Bodek aalg = auth_xform->auth.algo; 449169ca3dbSZbigniew Bodek sess->auth.mode = ARMV8_CRYPTO_AUTH_AS_HMAC; 450169ca3dbSZbigniew Bodek break; 451169ca3dbSZbigniew Bodek default: 452169ca3dbSZbigniew Bodek return -EINVAL; 453169ca3dbSZbigniew Bodek } 454169ca3dbSZbigniew Bodek 455169ca3dbSZbigniew Bodek /* Verify supported key lengths and extract proper algorithm */ 456169ca3dbSZbigniew Bodek switch (cipher_xform->cipher.key.length << 3) { 457169ca3dbSZbigniew Bodek case 128: 458169ca3dbSZbigniew Bodek sess->crypto_func = 459169ca3dbSZbigniew Bodek CRYPTO_GET_ALGO(order, cop, calg, aalg, 128); 460169ca3dbSZbigniew Bodek sess->cipher.key_sched = 461169ca3dbSZbigniew Bodek CRYPTO_GET_KEY_SCHED(cop, calg, 128); 462169ca3dbSZbigniew Bodek break; 463169ca3dbSZbigniew Bodek case 192: 464169ca3dbSZbigniew Bodek case 256: 465169ca3dbSZbigniew Bodek /* These key lengths are not supported yet */ 466169ca3dbSZbigniew Bodek default: /* Fall through */ 467169ca3dbSZbigniew Bodek sess->crypto_func = NULL; 468169ca3dbSZbigniew Bodek sess->cipher.key_sched = NULL; 469169ca3dbSZbigniew Bodek return -EINVAL; 470169ca3dbSZbigniew Bodek } 471169ca3dbSZbigniew Bodek 472169ca3dbSZbigniew Bodek if (unlikely(sess->crypto_func == NULL)) { 473169ca3dbSZbigniew Bodek /* 474169ca3dbSZbigniew Bodek * If we got here that means that there must be a bug 475169ca3dbSZbigniew Bodek * in the algorithms selection above. Nevertheless keep 476169ca3dbSZbigniew Bodek * it here to catch bug immediately and avoid NULL pointer 477169ca3dbSZbigniew Bodek * dereference in OPs processing. 478169ca3dbSZbigniew Bodek */ 479169ca3dbSZbigniew Bodek ARMV8_CRYPTO_LOG_ERR( 480169ca3dbSZbigniew Bodek "No appropriate crypto function for given parameters"); 481169ca3dbSZbigniew Bodek return -EINVAL; 482169ca3dbSZbigniew Bodek } 483169ca3dbSZbigniew Bodek 484169ca3dbSZbigniew Bodek /* Set up cipher session prerequisites */ 485169ca3dbSZbigniew Bodek if (cipher_set_prerequisites(sess, cipher_xform) != 0) 486169ca3dbSZbigniew Bodek return -EINVAL; 487169ca3dbSZbigniew Bodek 488169ca3dbSZbigniew Bodek /* Set up authentication session prerequisites */ 489169ca3dbSZbigniew Bodek if (auth_set_prerequisites(sess, auth_xform) != 0) 490169ca3dbSZbigniew Bodek return -EINVAL; 491169ca3dbSZbigniew Bodek 492169ca3dbSZbigniew Bodek return 0; 493169ca3dbSZbigniew Bodek } 494169ca3dbSZbigniew Bodek 495169ca3dbSZbigniew Bodek /** Parse crypto xform chain and set private session parameters */ 496169ca3dbSZbigniew Bodek int 497169ca3dbSZbigniew Bodek armv8_crypto_set_session_parameters(struct armv8_crypto_session *sess, 498169ca3dbSZbigniew Bodek const struct rte_crypto_sym_xform *xform) 499169ca3dbSZbigniew Bodek { 500169ca3dbSZbigniew Bodek const struct rte_crypto_sym_xform *cipher_xform = NULL; 501169ca3dbSZbigniew Bodek const struct rte_crypto_sym_xform *auth_xform = NULL; 502169ca3dbSZbigniew Bodek bool is_chained_op; 503169ca3dbSZbigniew Bodek int ret; 504169ca3dbSZbigniew Bodek 505169ca3dbSZbigniew Bodek /* Filter out spurious/broken requests */ 506169ca3dbSZbigniew Bodek if (xform == NULL) 507169ca3dbSZbigniew Bodek return -EINVAL; 508169ca3dbSZbigniew Bodek 509169ca3dbSZbigniew Bodek sess->chain_order = armv8_crypto_get_chain_order(xform); 510169ca3dbSZbigniew Bodek switch (sess->chain_order) { 511169ca3dbSZbigniew Bodek case ARMV8_CRYPTO_CHAIN_CIPHER_AUTH: 512169ca3dbSZbigniew Bodek cipher_xform = xform; 513169ca3dbSZbigniew Bodek auth_xform = xform->next; 514169ca3dbSZbigniew Bodek is_chained_op = true; 515169ca3dbSZbigniew Bodek break; 516169ca3dbSZbigniew Bodek case ARMV8_CRYPTO_CHAIN_AUTH_CIPHER: 517169ca3dbSZbigniew Bodek auth_xform = xform; 518169ca3dbSZbigniew Bodek cipher_xform = xform->next; 519169ca3dbSZbigniew Bodek is_chained_op = true; 520169ca3dbSZbigniew Bodek break; 521169ca3dbSZbigniew Bodek default: 522169ca3dbSZbigniew Bodek is_chained_op = false; 523169ca3dbSZbigniew Bodek return -EINVAL; 524169ca3dbSZbigniew Bodek } 525169ca3dbSZbigniew Bodek 526*0fbd75a9SPablo de Lara /* Set IV offset */ 527*0fbd75a9SPablo de Lara sess->cipher.iv.offset = cipher_xform->cipher.iv.offset; 528*0fbd75a9SPablo de Lara 529169ca3dbSZbigniew Bodek if (is_chained_op) { 530169ca3dbSZbigniew Bodek ret = armv8_crypto_set_session_chained_parameters(sess, 531169ca3dbSZbigniew Bodek cipher_xform, auth_xform); 532169ca3dbSZbigniew Bodek if (unlikely(ret != 0)) { 533169ca3dbSZbigniew Bodek ARMV8_CRYPTO_LOG_ERR( 534169ca3dbSZbigniew Bodek "Invalid/unsupported chained (cipher/auth) parameters"); 535169ca3dbSZbigniew Bodek return -EINVAL; 536169ca3dbSZbigniew Bodek } 537169ca3dbSZbigniew Bodek } else { 538169ca3dbSZbigniew Bodek ARMV8_CRYPTO_LOG_ERR("Invalid/unsupported operation"); 539169ca3dbSZbigniew Bodek return -EINVAL; 540169ca3dbSZbigniew Bodek } 541169ca3dbSZbigniew Bodek 542169ca3dbSZbigniew Bodek return 0; 543169ca3dbSZbigniew Bodek } 544169ca3dbSZbigniew Bodek 545169ca3dbSZbigniew Bodek /** Provide session for operation */ 546169ca3dbSZbigniew Bodek static inline struct armv8_crypto_session * 547169ca3dbSZbigniew Bodek get_session(struct armv8_crypto_qp *qp, struct rte_crypto_op *op) 548169ca3dbSZbigniew Bodek { 549169ca3dbSZbigniew Bodek struct armv8_crypto_session *sess = NULL; 550169ca3dbSZbigniew Bodek 5515209df0dSPablo de Lara if (op->sess_type == RTE_CRYPTO_OP_WITH_SESSION) { 552169ca3dbSZbigniew Bodek /* get existing session */ 553169ca3dbSZbigniew Bodek if (likely(op->sym->session != NULL && 554169ca3dbSZbigniew Bodek op->sym->session->dev_type == 555169ca3dbSZbigniew Bodek RTE_CRYPTODEV_ARMV8_PMD)) { 556169ca3dbSZbigniew Bodek sess = (struct armv8_crypto_session *) 557169ca3dbSZbigniew Bodek op->sym->session->_private; 558169ca3dbSZbigniew Bodek } 559169ca3dbSZbigniew Bodek } else { 560169ca3dbSZbigniew Bodek /* provide internal session */ 561169ca3dbSZbigniew Bodek void *_sess = NULL; 562169ca3dbSZbigniew Bodek 563169ca3dbSZbigniew Bodek if (!rte_mempool_get(qp->sess_mp, (void **)&_sess)) { 564169ca3dbSZbigniew Bodek sess = (struct armv8_crypto_session *) 565169ca3dbSZbigniew Bodek ((struct rte_cryptodev_sym_session *)_sess) 566169ca3dbSZbigniew Bodek ->_private; 567169ca3dbSZbigniew Bodek 568169ca3dbSZbigniew Bodek if (unlikely(armv8_crypto_set_session_parameters( 569169ca3dbSZbigniew Bodek sess, op->sym->xform) != 0)) { 570169ca3dbSZbigniew Bodek rte_mempool_put(qp->sess_mp, _sess); 571169ca3dbSZbigniew Bodek sess = NULL; 572169ca3dbSZbigniew Bodek } else 573169ca3dbSZbigniew Bodek op->sym->session = _sess; 574169ca3dbSZbigniew Bodek } 575169ca3dbSZbigniew Bodek } 576169ca3dbSZbigniew Bodek 577169ca3dbSZbigniew Bodek if (unlikely(sess == NULL)) 578169ca3dbSZbigniew Bodek op->status = RTE_CRYPTO_OP_STATUS_INVALID_SESSION; 579169ca3dbSZbigniew Bodek 580169ca3dbSZbigniew Bodek return sess; 581169ca3dbSZbigniew Bodek } 582169ca3dbSZbigniew Bodek 583169ca3dbSZbigniew Bodek /* 584169ca3dbSZbigniew Bodek *------------------------------------------------------------------------------ 585169ca3dbSZbigniew Bodek * Process Operations 586169ca3dbSZbigniew Bodek *------------------------------------------------------------------------------ 587169ca3dbSZbigniew Bodek */ 588169ca3dbSZbigniew Bodek 589169ca3dbSZbigniew Bodek /*----------------------------------------------------------------------------*/ 590169ca3dbSZbigniew Bodek 591169ca3dbSZbigniew Bodek /** Process cipher operation */ 592169ca3dbSZbigniew Bodek static inline void 593169ca3dbSZbigniew Bodek process_armv8_chained_op 594169ca3dbSZbigniew Bodek (struct rte_crypto_op *op, struct armv8_crypto_session *sess, 595169ca3dbSZbigniew Bodek struct rte_mbuf *mbuf_src, struct rte_mbuf *mbuf_dst) 596169ca3dbSZbigniew Bodek { 597169ca3dbSZbigniew Bodek crypto_func_t crypto_func; 598169ca3dbSZbigniew Bodek crypto_arg_t arg; 599169ca3dbSZbigniew Bodek struct rte_mbuf *m_asrc, *m_adst; 600169ca3dbSZbigniew Bodek uint8_t *csrc, *cdst; 601169ca3dbSZbigniew Bodek uint8_t *adst, *asrc; 602169ca3dbSZbigniew Bodek uint64_t clen, alen; 603169ca3dbSZbigniew Bodek int error; 604169ca3dbSZbigniew Bodek 605169ca3dbSZbigniew Bodek clen = op->sym->cipher.data.length; 606169ca3dbSZbigniew Bodek alen = op->sym->auth.data.length; 607169ca3dbSZbigniew Bodek 608169ca3dbSZbigniew Bodek csrc = rte_pktmbuf_mtod_offset(mbuf_src, uint8_t *, 609169ca3dbSZbigniew Bodek op->sym->cipher.data.offset); 610169ca3dbSZbigniew Bodek cdst = rte_pktmbuf_mtod_offset(mbuf_dst, uint8_t *, 611169ca3dbSZbigniew Bodek op->sym->cipher.data.offset); 612169ca3dbSZbigniew Bodek 613169ca3dbSZbigniew Bodek switch (sess->chain_order) { 614169ca3dbSZbigniew Bodek case ARMV8_CRYPTO_CHAIN_CIPHER_AUTH: 615169ca3dbSZbigniew Bodek m_asrc = m_adst = mbuf_dst; 616169ca3dbSZbigniew Bodek break; 617169ca3dbSZbigniew Bodek case ARMV8_CRYPTO_CHAIN_AUTH_CIPHER: 618169ca3dbSZbigniew Bodek m_asrc = mbuf_src; 619169ca3dbSZbigniew Bodek m_adst = mbuf_dst; 620169ca3dbSZbigniew Bodek break; 621169ca3dbSZbigniew Bodek default: 622169ca3dbSZbigniew Bodek op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS; 623169ca3dbSZbigniew Bodek return; 624169ca3dbSZbigniew Bodek } 625169ca3dbSZbigniew Bodek asrc = rte_pktmbuf_mtod_offset(m_asrc, uint8_t *, 626169ca3dbSZbigniew Bodek op->sym->auth.data.offset); 627169ca3dbSZbigniew Bodek 628169ca3dbSZbigniew Bodek switch (sess->auth.mode) { 629169ca3dbSZbigniew Bodek case ARMV8_CRYPTO_AUTH_AS_AUTH: 630169ca3dbSZbigniew Bodek /* Nothing to do here, just verify correct option */ 631169ca3dbSZbigniew Bodek break; 632169ca3dbSZbigniew Bodek case ARMV8_CRYPTO_AUTH_AS_HMAC: 633169ca3dbSZbigniew Bodek arg.digest.hmac.key = sess->auth.hmac.key; 634169ca3dbSZbigniew Bodek arg.digest.hmac.i_key_pad = sess->auth.hmac.i_key_pad; 635169ca3dbSZbigniew Bodek arg.digest.hmac.o_key_pad = sess->auth.hmac.o_key_pad; 636169ca3dbSZbigniew Bodek break; 637169ca3dbSZbigniew Bodek default: 638169ca3dbSZbigniew Bodek op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS; 639169ca3dbSZbigniew Bodek return; 640169ca3dbSZbigniew Bodek } 641169ca3dbSZbigniew Bodek 642169ca3dbSZbigniew Bodek if (sess->auth.operation == RTE_CRYPTO_AUTH_OP_GENERATE) { 643169ca3dbSZbigniew Bodek adst = op->sym->auth.digest.data; 644169ca3dbSZbigniew Bodek if (adst == NULL) { 645169ca3dbSZbigniew Bodek adst = rte_pktmbuf_mtod_offset(m_adst, 646169ca3dbSZbigniew Bodek uint8_t *, 647169ca3dbSZbigniew Bodek op->sym->auth.data.offset + 648169ca3dbSZbigniew Bodek op->sym->auth.data.length); 649169ca3dbSZbigniew Bodek } 650169ca3dbSZbigniew Bodek } else { 651169ca3dbSZbigniew Bodek adst = (uint8_t *)rte_pktmbuf_append(m_asrc, 652169ca3dbSZbigniew Bodek op->sym->auth.digest.length); 653169ca3dbSZbigniew Bodek } 654169ca3dbSZbigniew Bodek 6555082f991SPablo de Lara arg.cipher.iv = rte_crypto_op_ctod_offset(op, uint8_t *, 656*0fbd75a9SPablo de Lara sess->cipher.iv.offset); 657169ca3dbSZbigniew Bodek arg.cipher.key = sess->cipher.key.data; 658169ca3dbSZbigniew Bodek /* Acquire combined mode function */ 659169ca3dbSZbigniew Bodek crypto_func = sess->crypto_func; 660169ca3dbSZbigniew Bodek ARMV8_CRYPTO_ASSERT(crypto_func != NULL); 661169ca3dbSZbigniew Bodek error = crypto_func(csrc, cdst, clen, asrc, adst, alen, &arg); 662169ca3dbSZbigniew Bodek if (error != 0) { 663169ca3dbSZbigniew Bodek op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS; 664169ca3dbSZbigniew Bodek return; 665169ca3dbSZbigniew Bodek } 666169ca3dbSZbigniew Bodek 667169ca3dbSZbigniew Bodek op->status = RTE_CRYPTO_OP_STATUS_SUCCESS; 668169ca3dbSZbigniew Bodek if (sess->auth.operation == RTE_CRYPTO_AUTH_OP_VERIFY) { 669169ca3dbSZbigniew Bodek if (memcmp(adst, op->sym->auth.digest.data, 670169ca3dbSZbigniew Bodek op->sym->auth.digest.length) != 0) { 671169ca3dbSZbigniew Bodek op->status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED; 672169ca3dbSZbigniew Bodek } 673169ca3dbSZbigniew Bodek /* Trim area used for digest from mbuf. */ 674169ca3dbSZbigniew Bodek rte_pktmbuf_trim(m_asrc, 675169ca3dbSZbigniew Bodek op->sym->auth.digest.length); 676169ca3dbSZbigniew Bodek } 677169ca3dbSZbigniew Bodek } 678169ca3dbSZbigniew Bodek 679169ca3dbSZbigniew Bodek /** Process crypto operation for mbuf */ 680169ca3dbSZbigniew Bodek static inline int 681169ca3dbSZbigniew Bodek process_op(const struct armv8_crypto_qp *qp, struct rte_crypto_op *op, 682169ca3dbSZbigniew Bodek struct armv8_crypto_session *sess) 683169ca3dbSZbigniew Bodek { 684169ca3dbSZbigniew Bodek struct rte_mbuf *msrc, *mdst; 685169ca3dbSZbigniew Bodek 686169ca3dbSZbigniew Bodek msrc = op->sym->m_src; 687169ca3dbSZbigniew Bodek mdst = op->sym->m_dst ? op->sym->m_dst : op->sym->m_src; 688169ca3dbSZbigniew Bodek 689169ca3dbSZbigniew Bodek op->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED; 690169ca3dbSZbigniew Bodek 691169ca3dbSZbigniew Bodek switch (sess->chain_order) { 692169ca3dbSZbigniew Bodek case ARMV8_CRYPTO_CHAIN_CIPHER_AUTH: 693169ca3dbSZbigniew Bodek case ARMV8_CRYPTO_CHAIN_AUTH_CIPHER: /* Fall through */ 694169ca3dbSZbigniew Bodek process_armv8_chained_op(op, sess, msrc, mdst); 695169ca3dbSZbigniew Bodek break; 696169ca3dbSZbigniew Bodek default: 697169ca3dbSZbigniew Bodek op->status = RTE_CRYPTO_OP_STATUS_ERROR; 698169ca3dbSZbigniew Bodek break; 699169ca3dbSZbigniew Bodek } 700169ca3dbSZbigniew Bodek 701169ca3dbSZbigniew Bodek /* Free session if a session-less crypto op */ 7025209df0dSPablo de Lara if (op->sess_type == RTE_CRYPTO_OP_SESSIONLESS) { 703169ca3dbSZbigniew Bodek memset(sess, 0, sizeof(struct armv8_crypto_session)); 704169ca3dbSZbigniew Bodek rte_mempool_put(qp->sess_mp, op->sym->session); 705169ca3dbSZbigniew Bodek op->sym->session = NULL; 706169ca3dbSZbigniew Bodek } 707169ca3dbSZbigniew Bodek 708169ca3dbSZbigniew Bodek if (op->status == RTE_CRYPTO_OP_STATUS_NOT_PROCESSED) 709169ca3dbSZbigniew Bodek op->status = RTE_CRYPTO_OP_STATUS_SUCCESS; 710169ca3dbSZbigniew Bodek 711169ca3dbSZbigniew Bodek if (unlikely(op->status == RTE_CRYPTO_OP_STATUS_ERROR)) 712169ca3dbSZbigniew Bodek return -1; 713169ca3dbSZbigniew Bodek 714169ca3dbSZbigniew Bodek return 0; 715169ca3dbSZbigniew Bodek } 716169ca3dbSZbigniew Bodek 717169ca3dbSZbigniew Bodek /* 718169ca3dbSZbigniew Bodek *------------------------------------------------------------------------------ 719169ca3dbSZbigniew Bodek * PMD Framework 720169ca3dbSZbigniew Bodek *------------------------------------------------------------------------------ 721169ca3dbSZbigniew Bodek */ 722169ca3dbSZbigniew Bodek 723169ca3dbSZbigniew Bodek /** Enqueue burst */ 724169ca3dbSZbigniew Bodek static uint16_t 725169ca3dbSZbigniew Bodek armv8_crypto_pmd_enqueue_burst(void *queue_pair, struct rte_crypto_op **ops, 726169ca3dbSZbigniew Bodek uint16_t nb_ops) 727169ca3dbSZbigniew Bodek { 728169ca3dbSZbigniew Bodek struct armv8_crypto_session *sess; 729169ca3dbSZbigniew Bodek struct armv8_crypto_qp *qp = queue_pair; 730169ca3dbSZbigniew Bodek int i, retval; 731169ca3dbSZbigniew Bodek 732169ca3dbSZbigniew Bodek for (i = 0; i < nb_ops; i++) { 733169ca3dbSZbigniew Bodek sess = get_session(qp, ops[i]); 734169ca3dbSZbigniew Bodek if (unlikely(sess == NULL)) 735169ca3dbSZbigniew Bodek goto enqueue_err; 736169ca3dbSZbigniew Bodek 737169ca3dbSZbigniew Bodek retval = process_op(qp, ops[i], sess); 738169ca3dbSZbigniew Bodek if (unlikely(retval < 0)) 739169ca3dbSZbigniew Bodek goto enqueue_err; 740169ca3dbSZbigniew Bodek } 741169ca3dbSZbigniew Bodek 74214fbffb0SBruce Richardson retval = rte_ring_enqueue_burst(qp->processed_ops, (void *)ops, i, 74314fbffb0SBruce Richardson NULL); 744169ca3dbSZbigniew Bodek qp->stats.enqueued_count += retval; 745169ca3dbSZbigniew Bodek 746169ca3dbSZbigniew Bodek return retval; 747169ca3dbSZbigniew Bodek 748169ca3dbSZbigniew Bodek enqueue_err: 74914fbffb0SBruce Richardson retval = rte_ring_enqueue_burst(qp->processed_ops, (void *)ops, i, 75014fbffb0SBruce Richardson NULL); 751169ca3dbSZbigniew Bodek if (ops[i] != NULL) 752169ca3dbSZbigniew Bodek ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS; 753169ca3dbSZbigniew Bodek 754169ca3dbSZbigniew Bodek qp->stats.enqueue_err_count++; 755169ca3dbSZbigniew Bodek return retval; 756169ca3dbSZbigniew Bodek } 757169ca3dbSZbigniew Bodek 758169ca3dbSZbigniew Bodek /** Dequeue burst */ 759169ca3dbSZbigniew Bodek static uint16_t 760169ca3dbSZbigniew Bodek armv8_crypto_pmd_dequeue_burst(void *queue_pair, struct rte_crypto_op **ops, 761169ca3dbSZbigniew Bodek uint16_t nb_ops) 762169ca3dbSZbigniew Bodek { 763169ca3dbSZbigniew Bodek struct armv8_crypto_qp *qp = queue_pair; 764169ca3dbSZbigniew Bodek 765169ca3dbSZbigniew Bodek unsigned int nb_dequeued = 0; 766169ca3dbSZbigniew Bodek 767169ca3dbSZbigniew Bodek nb_dequeued = rte_ring_dequeue_burst(qp->processed_ops, 768ecaed092SBruce Richardson (void **)ops, nb_ops, NULL); 769169ca3dbSZbigniew Bodek qp->stats.dequeued_count += nb_dequeued; 770169ca3dbSZbigniew Bodek 771169ca3dbSZbigniew Bodek return nb_dequeued; 772169ca3dbSZbigniew Bodek } 773169ca3dbSZbigniew Bodek 774169ca3dbSZbigniew Bodek /** Create ARMv8 crypto device */ 775169ca3dbSZbigniew Bodek static int 776168b9e76SPablo de Lara cryptodev_armv8_crypto_create(const char *name, 777168b9e76SPablo de Lara struct rte_vdev_device *vdev, 7785d2aa461SJan Blunck struct rte_crypto_vdev_init_params *init_params) 779169ca3dbSZbigniew Bodek { 780169ca3dbSZbigniew Bodek struct rte_cryptodev *dev; 781169ca3dbSZbigniew Bodek struct armv8_crypto_private *internals; 782169ca3dbSZbigniew Bodek 783169ca3dbSZbigniew Bodek /* Check CPU for support for AES instruction set */ 784169ca3dbSZbigniew Bodek if (!rte_cpu_get_flag_enabled(RTE_CPUFLAG_AES)) { 785169ca3dbSZbigniew Bodek ARMV8_CRYPTO_LOG_ERR( 786169ca3dbSZbigniew Bodek "AES instructions not supported by CPU"); 787169ca3dbSZbigniew Bodek return -EFAULT; 788169ca3dbSZbigniew Bodek } 789169ca3dbSZbigniew Bodek 790169ca3dbSZbigniew Bodek /* Check CPU for support for SHA instruction set */ 791169ca3dbSZbigniew Bodek if (!rte_cpu_get_flag_enabled(RTE_CPUFLAG_SHA1) || 792169ca3dbSZbigniew Bodek !rte_cpu_get_flag_enabled(RTE_CPUFLAG_SHA2)) { 793169ca3dbSZbigniew Bodek ARMV8_CRYPTO_LOG_ERR( 794169ca3dbSZbigniew Bodek "SHA1/SHA2 instructions not supported by CPU"); 795169ca3dbSZbigniew Bodek return -EFAULT; 796169ca3dbSZbigniew Bodek } 797169ca3dbSZbigniew Bodek 798169ca3dbSZbigniew Bodek /* Check CPU for support for Advance SIMD instruction set */ 799169ca3dbSZbigniew Bodek if (!rte_cpu_get_flag_enabled(RTE_CPUFLAG_NEON)) { 800169ca3dbSZbigniew Bodek ARMV8_CRYPTO_LOG_ERR( 801169ca3dbSZbigniew Bodek "Advanced SIMD instructions not supported by CPU"); 802169ca3dbSZbigniew Bodek return -EFAULT; 803169ca3dbSZbigniew Bodek } 804169ca3dbSZbigniew Bodek 805168b9e76SPablo de Lara if (init_params->name[0] == '\0') 806168b9e76SPablo de Lara snprintf(init_params->name, sizeof(init_params->name), 807168b9e76SPablo de Lara "%s", name); 808169ca3dbSZbigniew Bodek 80963348b9dSPablo de Lara dev = rte_cryptodev_vdev_pmd_init(init_params->name, 810169ca3dbSZbigniew Bodek sizeof(struct armv8_crypto_private), 811917ac9c4SPablo de Lara init_params->socket_id, 812917ac9c4SPablo de Lara vdev); 813169ca3dbSZbigniew Bodek if (dev == NULL) { 814169ca3dbSZbigniew Bodek ARMV8_CRYPTO_LOG_ERR("failed to create cryptodev vdev"); 815169ca3dbSZbigniew Bodek goto init_error; 816169ca3dbSZbigniew Bodek } 817169ca3dbSZbigniew Bodek 818169ca3dbSZbigniew Bodek dev->dev_type = RTE_CRYPTODEV_ARMV8_PMD; 819169ca3dbSZbigniew Bodek dev->dev_ops = rte_armv8_crypto_pmd_ops; 820169ca3dbSZbigniew Bodek 821169ca3dbSZbigniew Bodek /* register rx/tx burst functions for data path */ 822169ca3dbSZbigniew Bodek dev->dequeue_burst = armv8_crypto_pmd_dequeue_burst; 823169ca3dbSZbigniew Bodek dev->enqueue_burst = armv8_crypto_pmd_enqueue_burst; 824169ca3dbSZbigniew Bodek 825169ca3dbSZbigniew Bodek dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO | 826c2fec022SZbigniew Bodek RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING | 827c2fec022SZbigniew Bodek RTE_CRYPTODEV_FF_CPU_NEON | 828c2fec022SZbigniew Bodek RTE_CRYPTODEV_FF_CPU_ARM_CE; 829169ca3dbSZbigniew Bodek 830169ca3dbSZbigniew Bodek /* Set vector instructions mode supported */ 831169ca3dbSZbigniew Bodek internals = dev->data->dev_private; 832169ca3dbSZbigniew Bodek 833169ca3dbSZbigniew Bodek internals->max_nb_qpairs = init_params->max_nb_queue_pairs; 834169ca3dbSZbigniew Bodek internals->max_nb_sessions = init_params->max_nb_sessions; 835169ca3dbSZbigniew Bodek 836169ca3dbSZbigniew Bodek return 0; 837169ca3dbSZbigniew Bodek 838169ca3dbSZbigniew Bodek init_error: 839169ca3dbSZbigniew Bodek ARMV8_CRYPTO_LOG_ERR( 840169ca3dbSZbigniew Bodek "driver %s: cryptodev_armv8_crypto_create failed", 841169ca3dbSZbigniew Bodek init_params->name); 842169ca3dbSZbigniew Bodek 8435d2aa461SJan Blunck cryptodev_armv8_crypto_uninit(vdev); 844169ca3dbSZbigniew Bodek return -EFAULT; 845169ca3dbSZbigniew Bodek } 846169ca3dbSZbigniew Bodek 847169ca3dbSZbigniew Bodek /** Initialise ARMv8 crypto device */ 848169ca3dbSZbigniew Bodek static int 8495d2aa461SJan Blunck cryptodev_armv8_crypto_init(struct rte_vdev_device *vdev) 850169ca3dbSZbigniew Bodek { 851169ca3dbSZbigniew Bodek struct rte_crypto_vdev_init_params init_params = { 852169ca3dbSZbigniew Bodek RTE_CRYPTODEV_VDEV_DEFAULT_MAX_NB_QUEUE_PAIRS, 853169ca3dbSZbigniew Bodek RTE_CRYPTODEV_VDEV_DEFAULT_MAX_NB_SESSIONS, 854169ca3dbSZbigniew Bodek rte_socket_id(), 855169ca3dbSZbigniew Bodek {0} 856169ca3dbSZbigniew Bodek }; 8575d2aa461SJan Blunck const char *name; 8585d2aa461SJan Blunck const char *input_args; 859169ca3dbSZbigniew Bodek 8605d2aa461SJan Blunck name = rte_vdev_device_name(vdev); 8617e214771SPablo de Lara if (name == NULL) 8627e214771SPablo de Lara return -EINVAL; 8635d2aa461SJan Blunck input_args = rte_vdev_device_args(vdev); 86463348b9dSPablo de Lara rte_cryptodev_vdev_parse_init_params(&init_params, input_args); 865169ca3dbSZbigniew Bodek 866169ca3dbSZbigniew Bodek RTE_LOG(INFO, PMD, "Initialising %s on NUMA node %d\n", name, 867169ca3dbSZbigniew Bodek init_params.socket_id); 868169ca3dbSZbigniew Bodek if (init_params.name[0] != '\0') { 869169ca3dbSZbigniew Bodek RTE_LOG(INFO, PMD, " User defined name = %s\n", 870169ca3dbSZbigniew Bodek init_params.name); 871169ca3dbSZbigniew Bodek } 872169ca3dbSZbigniew Bodek RTE_LOG(INFO, PMD, " Max number of queue pairs = %d\n", 873169ca3dbSZbigniew Bodek init_params.max_nb_queue_pairs); 874169ca3dbSZbigniew Bodek RTE_LOG(INFO, PMD, " Max number of sessions = %d\n", 875169ca3dbSZbigniew Bodek init_params.max_nb_sessions); 876169ca3dbSZbigniew Bodek 877168b9e76SPablo de Lara return cryptodev_armv8_crypto_create(name, vdev, &init_params); 878169ca3dbSZbigniew Bodek } 879169ca3dbSZbigniew Bodek 880169ca3dbSZbigniew Bodek /** Uninitialise ARMv8 crypto device */ 881169ca3dbSZbigniew Bodek static int 8825d2aa461SJan Blunck cryptodev_armv8_crypto_uninit(struct rte_vdev_device *vdev) 883169ca3dbSZbigniew Bodek { 8845d2aa461SJan Blunck const char *name; 8855d2aa461SJan Blunck 8865d2aa461SJan Blunck name = rte_vdev_device_name(vdev); 887169ca3dbSZbigniew Bodek if (name == NULL) 888169ca3dbSZbigniew Bodek return -EINVAL; 889169ca3dbSZbigniew Bodek 890169ca3dbSZbigniew Bodek RTE_LOG(INFO, PMD, 891169ca3dbSZbigniew Bodek "Closing ARMv8 crypto device %s on numa socket %u\n", 892169ca3dbSZbigniew Bodek name, rte_socket_id()); 893169ca3dbSZbigniew Bodek 894169ca3dbSZbigniew Bodek return 0; 895169ca3dbSZbigniew Bodek } 896169ca3dbSZbigniew Bodek 897169ca3dbSZbigniew Bodek static struct rte_vdev_driver armv8_crypto_drv = { 898169ca3dbSZbigniew Bodek .probe = cryptodev_armv8_crypto_init, 899169ca3dbSZbigniew Bodek .remove = cryptodev_armv8_crypto_uninit 900169ca3dbSZbigniew Bodek }; 901169ca3dbSZbigniew Bodek 902169ca3dbSZbigniew Bodek RTE_PMD_REGISTER_VDEV(CRYPTODEV_NAME_ARMV8_PMD, armv8_crypto_drv); 903169ca3dbSZbigniew Bodek RTE_PMD_REGISTER_ALIAS(CRYPTODEV_NAME_ARMV8_PMD, cryptodev_armv8_pmd); 904169ca3dbSZbigniew Bodek RTE_PMD_REGISTER_PARAM_STRING(CRYPTODEV_NAME_ARMV8_PMD, 905169ca3dbSZbigniew Bodek "max_nb_queue_pairs=<int> " 906169ca3dbSZbigniew Bodek "max_nb_sessions=<int> " 907169ca3dbSZbigniew Bodek "socket_id=<int>"); 908