X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;ds=sidebyside;f=drivers%2Fcrypto%2Fopenssl%2Frte_openssl_pmd_ops.c;h=de2284390b12a85eb755cc3f8ad8e760b9cfc768;hb=b63264c8342e6a1b6971c79550d2af2024b6a4de;hp=1cb87d59a6a61f31f28805ae671bf765edadd48d;hpb=ca33590b6af032bff57d9cc70455660466a654b2;p=deb_dpdk.git diff --git a/drivers/crypto/openssl/rte_openssl_pmd_ops.c b/drivers/crypto/openssl/rte_openssl_pmd_ops.c index 1cb87d59..de228439 100644 --- a/drivers/crypto/openssl/rte_openssl_pmd_ops.c +++ b/drivers/crypto/openssl/rte_openssl_pmd_ops.c @@ -9,6 +9,7 @@ #include #include "rte_openssl_pmd_private.h" +#include "compat.h" static const struct rte_cryptodev_capabilities openssl_pmd_capabilities[] = { @@ -397,7 +398,7 @@ static const struct rte_cryptodev_capabilities openssl_pmd_capabilities[] = { .algo = RTE_CRYPTO_CIPHER_3DES_CBC, .block_size = 8, .key_size = { - .min = 16, + .min = 8, .max = 24, .increment = 8 }, @@ -469,6 +470,105 @@ static const struct rte_cryptodev_capabilities openssl_pmd_capabilities[] = { }, } }, } }, + { /* RSA */ + .op = RTE_CRYPTO_OP_TYPE_ASYMMETRIC, + {.asym = { + .xform_capa = { + .xform_type = RTE_CRYPTO_ASYM_XFORM_RSA, + .op_types = ((1 << RTE_CRYPTO_ASYM_OP_SIGN) | + (1 << RTE_CRYPTO_ASYM_OP_VERIFY) | + (1 << RTE_CRYPTO_ASYM_OP_ENCRYPT) | + (1 << RTE_CRYPTO_ASYM_OP_DECRYPT)), + { + .modlen = { + /* min length is based on openssl rsa keygen */ + .min = 30, + /* value 0 symbolizes no limit on max length */ + .max = 0, + .increment = 1 + }, } + } + }, + } + }, + { /* modexp */ + .op = RTE_CRYPTO_OP_TYPE_ASYMMETRIC, + {.asym = { + .xform_capa = { + .xform_type = RTE_CRYPTO_ASYM_XFORM_MODEX, + .op_types = 0, + { + .modlen = { + /* value 0 symbolizes no limit on min length */ + .min = 0, + /* value 0 symbolizes no limit on max length */ + .max = 0, + .increment = 1 + }, } + } + }, + } + }, + { /* modinv */ + .op = RTE_CRYPTO_OP_TYPE_ASYMMETRIC, + {.asym = { + .xform_capa = { + .xform_type = RTE_CRYPTO_ASYM_XFORM_MODINV, + .op_types = 0, + { + .modlen = { + /* value 0 symbolizes no limit on min length */ + .min = 0, + /* value 0 symbolizes no limit on max length */ + .max = 0, + .increment = 1 + }, } + } + }, + } + }, + { /* dh */ + .op = RTE_CRYPTO_OP_TYPE_ASYMMETRIC, + {.asym = { + .xform_capa = { + .xform_type = RTE_CRYPTO_ASYM_XFORM_DH, + .op_types = + ((1<feature_flags = dev->feature_flags; dev_info->capabilities = openssl_pmd_capabilities; dev_info->max_nb_queue_pairs = internals->max_nb_qpairs; - dev_info->sym.max_nb_sessions = internals->max_nb_sessions; + /* No limit of number of sessions */ + dev_info->sym.max_nb_sessions = 0; } } @@ -588,14 +689,14 @@ openssl_pmd_qp_create_processed_ops_ring(struct openssl_qp *qp, r = rte_ring_lookup(qp->name); if (r) { if (rte_ring_get_size(r) >= ring_size) { - OPENSSL_LOG_INFO( - "Reusing existing ring %s for processed ops", + OPENSSL_LOG(INFO, + "Reusing existing ring %s for processed ops", qp->name); return r; } - OPENSSL_LOG_ERR( - "Unable to reuse existing ring %s for processed ops", + OPENSSL_LOG(ERR, + "Unable to reuse existing ring %s for processed ops", qp->name); return NULL; } @@ -647,22 +748,6 @@ qp_setup_cleanup: return -1; } -/** Start queue pair */ -static int -openssl_pmd_qp_start(__rte_unused struct rte_cryptodev *dev, - __rte_unused uint16_t queue_pair_id) -{ - return -ENOTSUP; -} - -/** Stop queue pair */ -static int -openssl_pmd_qp_stop(__rte_unused struct rte_cryptodev *dev, - __rte_unused uint16_t queue_pair_id) -{ - return -ENOTSUP; -} - /** Return the number of allocated queue pairs */ static uint32_t openssl_pmd_qp_count(struct rte_cryptodev *dev) @@ -670,16 +755,23 @@ openssl_pmd_qp_count(struct rte_cryptodev *dev) return dev->data->nb_queue_pairs; } -/** Returns the size of the session structure */ +/** Returns the size of the symmetric session structure */ static unsigned -openssl_pmd_session_get_size(struct rte_cryptodev *dev __rte_unused) +openssl_pmd_sym_session_get_size(struct rte_cryptodev *dev __rte_unused) { return sizeof(struct openssl_session); } +/** Returns the size of the asymmetric session structure */ +static unsigned +openssl_pmd_asym_session_get_size(struct rte_cryptodev *dev __rte_unused) +{ + return sizeof(struct openssl_asym_session); +} + /** Configure the session from a crypto xform chain */ static int -openssl_pmd_session_configure(struct rte_cryptodev *dev __rte_unused, +openssl_pmd_sym_session_configure(struct rte_cryptodev *dev __rte_unused, struct rte_crypto_sym_xform *xform, struct rte_cryptodev_sym_session *sess, struct rte_mempool *mempool) @@ -688,46 +780,460 @@ openssl_pmd_session_configure(struct rte_cryptodev *dev __rte_unused, int ret; if (unlikely(sess == NULL)) { - OPENSSL_LOG_ERR("invalid session struct"); + OPENSSL_LOG(ERR, "invalid session struct"); return -EINVAL; } if (rte_mempool_get(mempool, &sess_private_data)) { - CDEV_LOG_ERR( + OPENSSL_LOG(ERR, "Couldn't get object from session mempool"); return -ENOMEM; } ret = openssl_set_session_parameters(sess_private_data, xform); if (ret != 0) { - OPENSSL_LOG_ERR("failed configure session parameters"); + OPENSSL_LOG(ERR, "failed configure session parameters"); /* Return session to mempool */ rte_mempool_put(mempool, sess_private_data); return ret; } - set_session_private_data(sess, dev->driver_id, + set_sym_session_private_data(sess, dev->driver_id, sess_private_data); return 0; } +static int openssl_set_asym_session_parameters( + struct openssl_asym_session *asym_session, + struct rte_crypto_asym_xform *xform) +{ + int ret = 0; + + if ((xform->xform_type != RTE_CRYPTO_ASYM_XFORM_DH) && + (xform->next != NULL)) { + OPENSSL_LOG(ERR, "chained xfrms are not supported on %s", + rte_crypto_asym_xform_strings[xform->xform_type]); + return -1; + } + + switch (xform->xform_type) { + case RTE_CRYPTO_ASYM_XFORM_RSA: + { + BIGNUM *n = NULL; + BIGNUM *e = NULL; + BIGNUM *d = NULL; + BIGNUM *p = NULL, *q = NULL, *dmp1 = NULL; + BIGNUM *iqmp = NULL, *dmq1 = NULL; + + /* copy xfrm data into rsa struct */ + n = BN_bin2bn((const unsigned char *)xform->rsa.n.data, + xform->rsa.n.length, n); + e = BN_bin2bn((const unsigned char *)xform->rsa.e.data, + xform->rsa.e.length, e); + + if (!n || !e) + goto err_rsa; + + RSA *rsa = RSA_new(); + if (rsa == NULL) + goto err_rsa; + + if (xform->rsa.key_type == RTE_RSA_KEY_TYPE_EXP) { + d = BN_bin2bn( + (const unsigned char *)xform->rsa.d.data, + xform->rsa.d.length, + d); + if (!d) { + RSA_free(rsa); + goto err_rsa; + } + } else { + p = BN_bin2bn((const unsigned char *) + xform->rsa.qt.p.data, + xform->rsa.qt.p.length, + p); + q = BN_bin2bn((const unsigned char *) + xform->rsa.qt.q.data, + xform->rsa.qt.q.length, + q); + dmp1 = BN_bin2bn((const unsigned char *) + xform->rsa.qt.dP.data, + xform->rsa.qt.dP.length, + dmp1); + dmq1 = BN_bin2bn((const unsigned char *) + xform->rsa.qt.dQ.data, + xform->rsa.qt.dQ.length, + dmq1); + iqmp = BN_bin2bn((const unsigned char *) + xform->rsa.qt.qInv.data, + xform->rsa.qt.qInv.length, + iqmp); + + if (!p || !q || !dmp1 || !dmq1 || !iqmp) { + RSA_free(rsa); + goto err_rsa; + } + set_rsa_params(rsa, p, q, ret); + if (ret) { + OPENSSL_LOG(ERR, + "failed to set rsa params\n"); + RSA_free(rsa); + goto err_rsa; + } + set_rsa_crt_params(rsa, dmp1, dmq1, iqmp, ret); + if (ret) { + OPENSSL_LOG(ERR, + "failed to set crt params\n"); + RSA_free(rsa); + /* + * set already populated params to NULL + * as its freed by call to RSA_free + */ + p = q = NULL; + goto err_rsa; + } + } + + set_rsa_keys(rsa, n, e, d, ret); + if (ret) { + OPENSSL_LOG(ERR, "Failed to load rsa keys\n"); + RSA_free(rsa); + return -1; + } + asym_session->u.r.rsa = rsa; + asym_session->xfrm_type = RTE_CRYPTO_ASYM_XFORM_RSA; + break; +err_rsa: + if (n) + BN_free(n); + if (e) + BN_free(e); + if (d) + BN_free(d); + if (p) + BN_free(p); + if (q) + BN_free(q); + if (dmp1) + BN_free(dmp1); + if (dmq1) + BN_free(dmq1); + if (iqmp) + BN_free(iqmp); + + return -1; + } + case RTE_CRYPTO_ASYM_XFORM_MODEX: + { + struct rte_crypto_modex_xform *xfrm = &(xform->modex); + + BN_CTX *ctx = BN_CTX_new(); + if (ctx == NULL) { + OPENSSL_LOG(ERR, + " failed to allocate resources\n"); + return -1; + } + BN_CTX_start(ctx); + BIGNUM *mod = BN_CTX_get(ctx); + BIGNUM *exp = BN_CTX_get(ctx); + if (mod == NULL || exp == NULL) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return -1; + } + + mod = BN_bin2bn((const unsigned char *) + xfrm->modulus.data, + xfrm->modulus.length, mod); + exp = BN_bin2bn((const unsigned char *) + xfrm->exponent.data, + xfrm->exponent.length, exp); + asym_session->u.e.ctx = ctx; + asym_session->u.e.mod = mod; + asym_session->u.e.exp = exp; + asym_session->xfrm_type = RTE_CRYPTO_ASYM_XFORM_MODEX; + break; + } + case RTE_CRYPTO_ASYM_XFORM_MODINV: + { + struct rte_crypto_modinv_xform *xfrm = &(xform->modinv); + + BN_CTX *ctx = BN_CTX_new(); + if (ctx == NULL) { + OPENSSL_LOG(ERR, + " failed to allocate resources\n"); + return -1; + } + BN_CTX_start(ctx); + BIGNUM *mod = BN_CTX_get(ctx); + if (mod == NULL) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return -1; + } + + mod = BN_bin2bn((const unsigned char *) + xfrm->modulus.data, + xfrm->modulus.length, + mod); + asym_session->u.m.ctx = ctx; + asym_session->u.m.modulus = mod; + asym_session->xfrm_type = RTE_CRYPTO_ASYM_XFORM_MODINV; + break; + } + case RTE_CRYPTO_ASYM_XFORM_DH: + { + BIGNUM *p = NULL; + BIGNUM *g = NULL; + + p = BN_bin2bn((const unsigned char *) + xform->dh.p.data, + xform->dh.p.length, + p); + g = BN_bin2bn((const unsigned char *) + xform->dh.g.data, + xform->dh.g.length, + g); + if (!p || !g) + goto err_dh; + + DH *dh = DH_new(); + if (dh == NULL) { + OPENSSL_LOG(ERR, + "failed to allocate resources\n"); + goto err_dh; + } + set_dh_params(dh, p, g, ret); + if (ret) { + DH_free(dh); + goto err_dh; + } + + /* + * setup xfrom for + * public key generate, or + * DH Priv key generate, or both + * public and private key generate + */ + asym_session->u.dh.key_op = (1 << xform->dh.type); + + if (xform->dh.type == + RTE_CRYPTO_ASYM_OP_PRIVATE_KEY_GENERATE) { + /* check if next is pubkey */ + if ((xform->next != NULL) && + (xform->next->xform_type == + RTE_CRYPTO_ASYM_XFORM_DH) && + (xform->next->dh.type == + RTE_CRYPTO_ASYM_OP_PUBLIC_KEY_GENERATE) + ) { + /* + * setup op as pub/priv key + * pair generationi + */ + asym_session->u.dh.key_op |= + (1 << + RTE_CRYPTO_ASYM_OP_PUBLIC_KEY_GENERATE); + } + } + asym_session->u.dh.dh_key = dh; + asym_session->xfrm_type = RTE_CRYPTO_ASYM_XFORM_DH; + break; + +err_dh: + OPENSSL_LOG(ERR, " failed to set dh params\n"); + if (p) + BN_free(p); + if (g) + BN_free(g); + return -1; + } + case RTE_CRYPTO_ASYM_XFORM_DSA: + { + BIGNUM *p = NULL, *g = NULL; + BIGNUM *q = NULL, *priv_key = NULL; + BIGNUM *pub_key = BN_new(); + BN_zero(pub_key); + + p = BN_bin2bn((const unsigned char *) + xform->dsa.p.data, + xform->dsa.p.length, + p); + + g = BN_bin2bn((const unsigned char *) + xform->dsa.g.data, + xform->dsa.g.length, + g); + + q = BN_bin2bn((const unsigned char *) + xform->dsa.q.data, + xform->dsa.q.length, + q); + if (!p || !q || !g) + goto err_dsa; + + priv_key = BN_bin2bn((const unsigned char *) + xform->dsa.x.data, + xform->dsa.x.length, + priv_key); + if (priv_key == NULL) + goto err_dsa; + + DSA *dsa = DSA_new(); + if (dsa == NULL) { + OPENSSL_LOG(ERR, + " failed to allocate resources\n"); + goto err_dsa; + } + + set_dsa_params(dsa, p, q, g, ret); + if (ret) { + DSA_free(dsa); + OPENSSL_LOG(ERR, "Failed to dsa params\n"); + goto err_dsa; + } + + /* + * openssl 1.1.0 mandate that public key can't be + * NULL in very first call. so set a dummy pub key. + * to keep consistency, lets follow same approach for + * both versions + */ + /* just set dummy public for very 1st call */ + set_dsa_keys(dsa, pub_key, priv_key, ret); + if (ret) { + DSA_free(dsa); + OPENSSL_LOG(ERR, "Failed to set keys\n"); + return -1; + } + asym_session->u.s.dsa = dsa; + asym_session->xfrm_type = RTE_CRYPTO_ASYM_XFORM_DSA; + break; + +err_dsa: + if (p) + BN_free(p); + if (q) + BN_free(q); + if (g) + BN_free(g); + if (priv_key) + BN_free(priv_key); + if (pub_key) + BN_free(pub_key); + return -1; + } + default: + return -1; + } + + return 0; +} + +/** Configure the session from a crypto xform chain */ +static int +openssl_pmd_asym_session_configure(struct rte_cryptodev *dev __rte_unused, + struct rte_crypto_asym_xform *xform, + struct rte_cryptodev_asym_session *sess, + struct rte_mempool *mempool) +{ + void *asym_sess_private_data; + int ret; + + if (unlikely(sess == NULL)) { + OPENSSL_LOG(ERR, "invalid asymmetric session struct"); + return -EINVAL; + } + + if (rte_mempool_get(mempool, &asym_sess_private_data)) { + CDEV_LOG_ERR( + "Couldn't get object from session mempool"); + return -ENOMEM; + } + + ret = openssl_set_asym_session_parameters(asym_sess_private_data, + xform); + if (ret != 0) { + OPENSSL_LOG(ERR, "failed configure session parameters"); + + /* Return session to mempool */ + rte_mempool_put(mempool, asym_sess_private_data); + return ret; + } + + set_asym_session_private_data(sess, dev->driver_id, + asym_sess_private_data); + + return 0; +} /** Clear the memory of session so it doesn't leave key material behind */ static void -openssl_pmd_session_clear(struct rte_cryptodev *dev, +openssl_pmd_sym_session_clear(struct rte_cryptodev *dev, struct rte_cryptodev_sym_session *sess) { uint8_t index = dev->driver_id; - void *sess_priv = get_session_private_data(sess, index); + void *sess_priv = get_sym_session_private_data(sess, index); /* Zero out the whole structure */ if (sess_priv) { openssl_reset_session(sess_priv); memset(sess_priv, 0, sizeof(struct openssl_session)); struct rte_mempool *sess_mp = rte_mempool_from_obj(sess_priv); - set_session_private_data(sess, index, NULL); + set_sym_session_private_data(sess, index, NULL); + rte_mempool_put(sess_mp, sess_priv); + } +} + +static void openssl_reset_asym_session(struct openssl_asym_session *sess) +{ + switch (sess->xfrm_type) { + case RTE_CRYPTO_ASYM_XFORM_RSA: + if (sess->u.r.rsa) + RSA_free(sess->u.r.rsa); + break; + case RTE_CRYPTO_ASYM_XFORM_MODEX: + if (sess->u.e.ctx) { + BN_CTX_end(sess->u.e.ctx); + BN_CTX_free(sess->u.e.ctx); + } + break; + case RTE_CRYPTO_ASYM_XFORM_MODINV: + if (sess->u.m.ctx) { + BN_CTX_end(sess->u.m.ctx); + BN_CTX_free(sess->u.m.ctx); + } + break; + case RTE_CRYPTO_ASYM_XFORM_DH: + if (sess->u.dh.dh_key) + DH_free(sess->u.dh.dh_key); + break; + case RTE_CRYPTO_ASYM_XFORM_DSA: + if (sess->u.s.dsa) + DSA_free(sess->u.s.dsa); + break; + default: + break; + } +} + +/** Clear the memory of asymmetric session + * so it doesn't leave key material behind + */ +static void +openssl_pmd_asym_session_clear(struct rte_cryptodev *dev, + struct rte_cryptodev_asym_session *sess) +{ + uint8_t index = dev->driver_id; + void *sess_priv = get_asym_session_private_data(sess, index); + + /* Zero out the whole structure */ + if (sess_priv) { + openssl_reset_asym_session(sess_priv); + memset(sess_priv, 0, sizeof(struct openssl_asym_session)); + struct rte_mempool *sess_mp = rte_mempool_from_obj(sess_priv); + set_asym_session_private_data(sess, index, NULL); rte_mempool_put(sess_mp, sess_priv); } } @@ -745,13 +1251,14 @@ struct rte_cryptodev_ops openssl_pmd_ops = { .queue_pair_setup = openssl_pmd_qp_setup, .queue_pair_release = openssl_pmd_qp_release, - .queue_pair_start = openssl_pmd_qp_start, - .queue_pair_stop = openssl_pmd_qp_stop, .queue_pair_count = openssl_pmd_qp_count, - .session_get_size = openssl_pmd_session_get_size, - .session_configure = openssl_pmd_session_configure, - .session_clear = openssl_pmd_session_clear + .sym_session_get_size = openssl_pmd_sym_session_get_size, + .asym_session_get_size = openssl_pmd_asym_session_get_size, + .sym_session_configure = openssl_pmd_sym_session_configure, + .asym_session_configure = openssl_pmd_asym_session_configure, + .sym_session_clear = openssl_pmd_sym_session_clear, + .asym_session_clear = openssl_pmd_asym_session_clear }; struct rte_cryptodev_ops *rte_openssl_pmd_ops = &openssl_pmd_ops;