>-----Original Message----- >From: Jastrzebski, MichalX K >Sent: Wednesday, September 14, 2016 10:48 AM >To: Akhil Goyal <akhil.goyal at nxp.com>; Azarewicz, PiotrX T ><piotrx.t.azarewicz at intel.com>; Doherty, Declan ><declan.doherty at intel.com>; dev at dpdk.org >Cc: Kerlin, MarcinX <marcinx.kerlin at intel.com>; Mrozowicz, SlawomirX ><slawomirx.mrozowicz at intel.com>; Kobylinski, MichalX ><michalx.kobylinski at intel.com>; Kulasek, TomaszX ><tomaszx.kulasek at intel.com>; Mrzyglod, DanielX T ><danielx.t.mrzyglod at intel.com> >Subject: RE: [dpdk-dev] [PATCH 1/4] libcrypto_pmd: initial implementation of >SW crypto device > >> -----Original Message----- >> From: dev [mailto:dev-bounces at dpdk.org] On Behalf Of Akhil Goyal >> Sent: Monday, September 12, 2016 1:17 PM >> To: Azarewicz, PiotrX T <piotrx.t.azarewicz at intel.com>; Doherty, >> Declan <declan.doherty at intel.com>; dev at dpdk.org >> Cc: Kerlin, MarcinX <marcinx.kerlin at intel.com>; Mrozowicz, SlawomirX >> <slawomirx.mrozowicz at intel.com>; Kobylinski, MichalX >> <michalx.kobylinski at intel.com>; Kulasek, TomaszX >> <tomaszx.kulasek at intel.com>; Mrzyglod, DanielX T >> <danielx.t.mrzyglod at intel.com> >> Subject: Re: [dpdk-dev] [PATCH 1/4] libcrypto_pmd: initial >> implementation of SW crypto device >> >> On 8/26/2016 12:51 PM, Piotr Azarewicz wrote: >> >> > +/** Provide session for operation */ static struct >> > +libcrypto_session * get_session(struct libcrypto_qp *qp, struct >> > +rte_crypto_op *op) { >> > + struct libcrypto_session *sess = NULL; >> > + >> > + if (op->sym->sess_type == RTE_CRYPTO_SYM_OP_WITH_SESSION) { >> > + /* get existing session */ >> > + if (!unlikely(op->sym->session == NULL || >> > + op->sym->session->dev_type != >> > + RTE_CRYPTODEV_LIBCRYPTO_PMD)) >> > + sess = (struct libcrypto_session *) >> > + op->sym->session->_private; >> > + } else { >> > + /* provide internal session */ >> > + void *_sess = NULL; >> > + >> > + if (!rte_mempool_get(qp->sess_mp, (void **)&_sess)) { >> > + sess = (struct libcrypto_session *) >> > + ((struct rte_cryptodev_sym_session *)_sess) >> > + ->_private; >> > + >> > + if (unlikely(libcrypto_set_session_parameters( >> > + sess, op->sym->xform) != 0)) { >> > + rte_mempool_put(qp->sess_mp, _sess); >> > + sess = NULL; >> > + } else >> > + op->sym->session = _sess; >> > + } >> > + } >> > + >> > + if (sess == NULL) >> > + op->status = RTE_CRYPTO_OP_STATUS_INVALID_SESSION; >> > + >> > + return sess; >> > +} >> > + >> > +/* >> > + >> > +*------------------------------------------------------------------ >> > +------------ >> > + * Process Operations >> > + >> > +*------------------------------------------------------------------ >> > +------------ >> > + */ >> > + >> > +/** Process standard libcrypto cipher encryption */ static int >> > +process_libcrypto_cipher_encrypt(uint8_t *src, uint8_t *dst, >> > + uint8_t *iv, uint8_t *key, int srclen, >> > + EVP_CIPHER_CTX *ctx, const EVP_CIPHER *algo) { >> > + int dstlen, totlen; >> > + >> > + if (EVP_EncryptInit_ex(ctx, algo, NULL, key, iv) <= 0) >> > + goto process_cipher_encrypt_err; >> [Akhil] this EVP_EncryptInit_ex() can be done for each session instead >> of each packet. This will improve the performance. Also if there is >> some change in the parameters later then it can be called again here >> with the updated parameters only. >> Same comment is for all cases (hmac, auth, etc) > >Hi Akhil, >Thank You for this comment. We will check if this is possible. > >Michal >
[S?awomir] We have done some investigation: - At first glance it is valuable to call this kind of function only once per session. - We done test: just remove the functions like EVP_XXXInitXXX and we reduce packet processing time between 1% to 10% depending of processed algorithm. - We analyzed calling only once per session also functions like EVP_XXXFinalXXX but it is not possible because this kind of functions finalize cipher or authenticate process and return result. - The functions like EVP_XXXFinalXXX change context and It is not possible to proper continue processing without reinitialize the context. So after call functions EVP_XXXFinalXXX we need to call EVP_XXXInitXXX for next operation. In sum we can't do the proposed performance improvement. >> > + >> > + if (EVP_EncryptUpdate(ctx, dst, &dstlen, src, srclen) <= 0) >> > + goto process_cipher_encrypt_err; >> > + >> > + if (EVP_EncryptFinal_ex(ctx, dst + dstlen, &totlen) <= 0) >> > + goto process_cipher_encrypt_err; >> > + >> > + return 0; >> > + >> > +process_cipher_encrypt_err: >> > + LIBCRYPTO_LOG_ERR("Process libcrypto cipher encrypt failed"); >> > + return -EINVAL; >> > +} >> > + >> > +/** Process standard libcrypto cipher decryption */ static int >> > +process_libcrypto_cipher_decrypt(uint8_t *src, uint8_t *dst, >> > + uint8_t *iv, uint8_t *key, int srclen, >> > + EVP_CIPHER_CTX *ctx, const EVP_CIPHER *algo) { >> > + int dstlen, totlen; >> > + >> > + if (EVP_DecryptInit_ex(ctx, algo, NULL, key, iv) <= 0) >> > + goto process_cipher_decrypt_err; >> > + >> > + if (EVP_CIPHER_CTX_set_padding(ctx, 0) <= 0) >> > + goto process_cipher_decrypt_err; >> > + >> > + if (EVP_DecryptUpdate(ctx, dst, &dstlen, src, srclen) <= 0) >> > + goto process_cipher_decrypt_err; >> > + >> > + if (EVP_DecryptFinal_ex(ctx, dst + dstlen, &totlen) <= 0) >> > + goto process_cipher_decrypt_err; >> > + >> > + return 0; >> > + >> > +process_cipher_decrypt_err: >> > + LIBCRYPTO_LOG_ERR("Process libcrypto cipher decrypt failed"); >> > + return -EINVAL; >> > +} >> > + >> > +/** Process cipher des 3 ctr encryption, decryption algorithm */ >> > +static int process_libcrypto_cipher_des3ctr(uint8_t *src, uint8_t >> > +*dst, >> > + uint8_t *iv, uint8_t *key, int srclen, EVP_CIPHER_CTX *ctx) { >> > + uint8_t ebuf[8], ctr[8]; >> > + int unused, n; >> > + >> > + /* We use 3DES encryption also for decryption. >> > + * IV is not important for 3DES ecb >> > + */ >> > + if (EVP_EncryptInit_ex(ctx, EVP_des_ede3_ecb(), NULL, key, NULL) >> > +<= >> 0) >> > + goto process_cipher_des3ctr_err; >> > + >> > + memcpy(ctr, iv, 8); >> > + n = 0; >> > + >> > + while (n < srclen) { >> > + if (n % 8 == 0) { >> > + if (EVP_EncryptUpdate(ctx, (unsigned char *)&ebuf, >> &unused, >> > + (const unsigned char *)&ctr, 8) <= 0) >> > + goto process_cipher_des3ctr_err; >> > + ctr_inc(ctr); >> > + } >> > + dst[n] = src[n] ^ ebuf[n % 8]; >> > + n++; >> > + } >> > + >> > + return 0; >> > + >> > +process_cipher_des3ctr_err: >> > + LIBCRYPTO_LOG_ERR("Process libcrypto cipher des 3 ede ctr failed"); >> > + return -EINVAL; >> > +} >> > + >> > +/** Process auth gmac algorithm */ >> > +static int >> > +process_libcrypto_auth_gmac(uint8_t *src, uint8_t *dst, >> > + uint8_t *iv, uint8_t *key, int srclen, int ivlen, >> > + EVP_CIPHER_CTX *ctx, const EVP_CIPHER *algo) { >> > + int unused; >> > + >> > + if (EVP_EncryptInit_ex(ctx, algo, NULL, NULL, NULL) <= 0) >> > + goto process_auth_gmac_err; >> > + >> > + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, ivlen, >> NULL) <= 0) >> > + goto process_auth_gmac_err; >> > + >> > + if (EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv) <= 0) >> > + goto process_auth_gmac_err; >> > + >> > + if (EVP_EncryptUpdate(ctx, NULL, &unused, src, srclen) <= 0) >> > + goto process_auth_gmac_err; >> > + >> > + if (EVP_EncryptFinal_ex(ctx, NULL, &unused) <= 0) >> > + goto process_auth_gmac_err; >> > + >> > + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, dst) <= >> 0) >> > + goto process_auth_gmac_err; >> > + >> > + return 0; >> > + >> > +process_auth_gmac_err: >> > + LIBCRYPTO_LOG_ERR("Process libcrypto auth gmac failed"); >> > + return -EINVAL; >> > +} >> > + >> > +/** Process standard libcrypto auth algorithms */ static int >> > +process_libcrypto_auth(uint8_t *src, uint8_t *dst, >> > + __rte_unused uint8_t *iv, __rte_unused EVP_PKEY * pkey, >> > + int srclen, EVP_MD_CTX *ctx, const EVP_MD *algo) { >> > + size_t dstlen; >> > + >> > + if (EVP_DigestInit_ex(ctx, algo, NULL) <= 0) >> > + goto process_auth_err; >> > + >> > + if (EVP_DigestUpdate(ctx, (char *)src, srclen) <= 0) >> > + goto process_auth_err; >> > + >> > + if (EVP_DigestFinal_ex(ctx, dst, (unsigned int *)&dstlen) <= 0) >> > + goto process_auth_err; >> > + >> > + return 0; >> > + >> > +process_auth_err: >> > + LIBCRYPTO_LOG_ERR("Process libcrypto auth failed"); >> > + return -EINVAL; >> > +} >> > + >> > +/** Process standard libcrypto auth algorithms with hmac */ static >> > +int process_libcrypto_auth_hmac(uint8_t *src, uint8_t *dst, >> > + __rte_unused uint8_t *iv, EVP_PKEY *pkey, >> > + int srclen, EVP_MD_CTX *ctx, const EVP_MD *algo) >> > +{ >> > + size_t dstlen; >> > + >> > + if (EVP_DigestSignInit(ctx, NULL, algo, NULL, pkey) <= 0) >> > + goto process_auth_err; >> > + >> > + if (EVP_DigestSignUpdate(ctx, (char *)src, srclen) <= 0) >> > + goto process_auth_err; >> > + >> > + if (EVP_DigestSignFinal(ctx, dst, &dstlen) <= 0) >> > + goto process_auth_err; >> > + >> > + return 0; >> > + >> > +process_auth_err: >> > + LIBCRYPTO_LOG_ERR("Process libcrypto auth failed"); >> > + return -EINVAL; >> > +} >> > + >> > +/*----------------------------------------------------------------- >> > +-----------*/ >> > + >> >>