X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fcrypto%2Fopenssl%2Frte_openssl_pmd.c;h=6504959e6981e0bf0d071cfd0e8f7563ce3e3ed7;hb=5897ac139355e2d6602c89b0a1d28e609d6f6ebc;hp=6fa3e5a9b40e725b3027a9f659baceaadb01f889;hpb=3e9d6bd447fbf567df50c456caa2a6f7b1c78e74;p=dpdk.git diff --git a/drivers/crypto/openssl/rte_openssl_pmd.c b/drivers/crypto/openssl/rte_openssl_pmd.c index 6fa3e5a9b4..6504959e69 100644 --- a/drivers/crypto/openssl/rte_openssl_pmd.c +++ b/drivers/crypto/openssl/rte_openssl_pmd.c @@ -768,7 +768,8 @@ get_session(struct openssl_qp *qp, struct rte_crypto_op *op) if (rte_mempool_get(qp->sess_mp, (void **)&_sess)) return NULL; - if (rte_mempool_get(qp->sess_mp, (void **)&_sess_private_data)) + if (rte_mempool_get(qp->sess_mp_priv, + (void **)&_sess_private_data)) return NULL; sess = (struct openssl_session *)_sess_private_data; @@ -776,7 +777,7 @@ get_session(struct openssl_qp *qp, struct rte_crypto_op *op) if (unlikely(openssl_set_session_parameters(sess, op->sym->xform) != 0)) { rte_mempool_put(qp->sess_mp, _sess); - rte_mempool_put(qp->sess_mp, _sess_private_data); + rte_mempool_put(qp->sess_mp_priv, _sess_private_data); sess = NULL; } op->sym->session = (struct rte_cryptodev_sym_session *)_sess; @@ -1509,15 +1510,7 @@ process_openssl_auth_op(struct openssl_qp *qp, struct rte_crypto_op *op, srclen = op->sym->auth.data.length; - if (sess->auth.operation == RTE_CRYPTO_AUTH_OP_VERIFY) - dst = qp->temp_digest; - else { - dst = op->sym->auth.digest.data; - if (dst == NULL) - dst = rte_pktmbuf_mtod_offset(mbuf_dst, uint8_t *, - op->sym->auth.data.offset + - op->sym->auth.data.length); - } + dst = qp->temp_digest; switch (sess->auth.mode) { case OPENSSL_AUTH_AS_AUTH: @@ -1540,12 +1533,242 @@ process_openssl_auth_op(struct openssl_qp *qp, struct rte_crypto_op *op, sess->auth.digest_length) != 0) { op->status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED; } + } else { + uint8_t *auth_dst; + + auth_dst = op->sym->auth.digest.data; + if (auth_dst == NULL) + auth_dst = rte_pktmbuf_mtod_offset(mbuf_dst, uint8_t *, + op->sym->auth.data.offset + + op->sym->auth.data.length); + memcpy(auth_dst, dst, sess->auth.digest_length); } if (status != 0) op->status = RTE_CRYPTO_OP_STATUS_ERROR; } +/* process dsa sign operation */ +static int +process_openssl_dsa_sign_op(struct rte_crypto_op *cop, + struct openssl_asym_session *sess) +{ + struct rte_crypto_dsa_op_param *op = &cop->asym->dsa; + DSA *dsa = sess->u.s.dsa; + DSA_SIG *sign = NULL; + + sign = DSA_do_sign(op->message.data, + op->message.length, + dsa); + + if (sign == NULL) { + OPENSSL_LOG(ERR, "%s:%d\n", __func__, __LINE__); + cop->status = RTE_CRYPTO_OP_STATUS_ERROR; + } else { + const BIGNUM *r = NULL, *s = NULL; + get_dsa_sign(sign, &r, &s); + + op->r.length = BN_bn2bin(r, op->r.data); + op->s.length = BN_bn2bin(s, op->s.data); + cop->status = RTE_CRYPTO_OP_STATUS_SUCCESS; + } + + DSA_SIG_free(sign); + + return 0; +} + +/* process dsa verify operation */ +static int +process_openssl_dsa_verify_op(struct rte_crypto_op *cop, + struct openssl_asym_session *sess) +{ + struct rte_crypto_dsa_op_param *op = &cop->asym->dsa; + DSA *dsa = sess->u.s.dsa; + int ret; + DSA_SIG *sign = DSA_SIG_new(); + BIGNUM *r = NULL, *s = NULL; + BIGNUM *pub_key = NULL; + + if (sign == NULL) { + OPENSSL_LOG(ERR, " %s:%d\n", __func__, __LINE__); + cop->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED; + return -1; + } + + r = BN_bin2bn(op->r.data, + op->r.length, + r); + s = BN_bin2bn(op->s.data, + op->s.length, + s); + pub_key = BN_bin2bn(op->y.data, + op->y.length, + pub_key); + if (!r || !s || !pub_key) { + BN_free(r); + BN_free(s); + BN_free(pub_key); + + cop->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED; + return -1; + } + set_dsa_sign(sign, r, s); + set_dsa_pub_key(dsa, pub_key); + + ret = DSA_do_verify(op->message.data, + op->message.length, + sign, + dsa); + + if (ret != 1) + cop->status = RTE_CRYPTO_OP_STATUS_ERROR; + else + cop->status = RTE_CRYPTO_OP_STATUS_SUCCESS; + + DSA_SIG_free(sign); + + return 0; +} + +/* process dh operation */ +static int +process_openssl_dh_op(struct rte_crypto_op *cop, + struct openssl_asym_session *sess) +{ + struct rte_crypto_dh_op_param *op = &cop->asym->dh; + DH *dh_key = sess->u.dh.dh_key; + BIGNUM *priv_key = NULL; + int ret = 0; + + if (sess->u.dh.key_op & + (1 << RTE_CRYPTO_ASYM_OP_SHARED_SECRET_COMPUTE)) { + /* compute shared secret using peer public key + * and current private key + * shared secret = peer_key ^ priv_key mod p + */ + BIGNUM *peer_key = NULL; + + /* copy private key and peer key and compute shared secret */ + peer_key = BN_bin2bn(op->pub_key.data, + op->pub_key.length, + peer_key); + if (peer_key == NULL) { + cop->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED; + return -1; + } + priv_key = BN_bin2bn(op->priv_key.data, + op->priv_key.length, + priv_key); + if (priv_key == NULL) { + BN_free(peer_key); + cop->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED; + return -1; + } + ret = set_dh_priv_key(dh_key, priv_key); + if (ret) { + OPENSSL_LOG(ERR, "Failed to set private key\n"); + cop->status = RTE_CRYPTO_OP_STATUS_ERROR; + BN_free(peer_key); + BN_free(priv_key); + return 0; + } + + ret = DH_compute_key( + op->shared_secret.data, + peer_key, dh_key); + if (ret < 0) { + cop->status = RTE_CRYPTO_OP_STATUS_ERROR; + BN_free(peer_key); + /* priv key is already loaded into dh, + * let's not free that directly here. + * DH_free() will auto free it later. + */ + return 0; + } + cop->status = RTE_CRYPTO_OP_STATUS_SUCCESS; + op->shared_secret.length = ret; + BN_free(peer_key); + return 0; + } + + /* + * other options are public and private key generations. + * + * if user provides private key, + * then first set DH with user provided private key + */ + if ((sess->u.dh.key_op & + (1 << RTE_CRYPTO_ASYM_OP_PUBLIC_KEY_GENERATE)) && + !(sess->u.dh.key_op & + (1 << RTE_CRYPTO_ASYM_OP_PRIVATE_KEY_GENERATE))) { + /* generate public key using user-provided private key + * pub_key = g ^ priv_key mod p + */ + + /* load private key into DH */ + priv_key = BN_bin2bn(op->priv_key.data, + op->priv_key.length, + priv_key); + if (priv_key == NULL) { + cop->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED; + return -1; + } + ret = set_dh_priv_key(dh_key, priv_key); + if (ret) { + OPENSSL_LOG(ERR, "Failed to set private key\n"); + cop->status = RTE_CRYPTO_OP_STATUS_ERROR; + BN_free(priv_key); + return 0; + } + } + + /* generate public and private key pair. + * + * if private key already set, generates only public key. + * + * if private key is not already set, then set it to random value + * and update internal private key. + */ + if (!DH_generate_key(dh_key)) { + cop->status = RTE_CRYPTO_OP_STATUS_ERROR; + return 0; + } + + if (sess->u.dh.key_op & (1 << RTE_CRYPTO_ASYM_OP_PUBLIC_KEY_GENERATE)) { + const BIGNUM *pub_key = NULL; + + OPENSSL_LOG(DEBUG, "%s:%d update public key\n", + __func__, __LINE__); + + /* get the generated keys */ + get_dh_pub_key(dh_key, &pub_key); + + /* output public key */ + op->pub_key.length = BN_bn2bin(pub_key, + op->pub_key.data); + } + + if (sess->u.dh.key_op & + (1 << RTE_CRYPTO_ASYM_OP_PRIVATE_KEY_GENERATE)) { + const BIGNUM *priv_key = NULL; + + OPENSSL_LOG(DEBUG, "%s:%d updated priv key\n", + __func__, __LINE__); + + /* get the generated keys */ + get_dh_priv_key(dh_key, &priv_key); + + /* provide generated private key back to user */ + op->priv_key.length = BN_bn2bin(priv_key, + op->priv_key.data); + } + + cop->status = RTE_CRYPTO_OP_STATUS_SUCCESS; + + return 0; +} + /* process modinv operation */ static int process_openssl_modinv_op(struct rte_crypto_op *cop, @@ -1556,10 +1779,8 @@ process_openssl_modinv_op(struct rte_crypto_op *cop, BIGNUM *res = BN_CTX_get(sess->u.m.ctx); if (unlikely(base == NULL || res == NULL)) { - if (base) - BN_free(base); - if (res) - BN_free(res); + BN_free(base); + BN_free(res); cop->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED; return -1; } @@ -1569,11 +1790,14 @@ process_openssl_modinv_op(struct rte_crypto_op *cop, if (BN_mod_inverse(res, base, sess->u.m.modulus, sess->u.m.ctx)) { cop->status = RTE_CRYPTO_OP_STATUS_SUCCESS; - op->modinv.base.length = BN_bn2bin(res, op->modinv.base.data); + op->modinv.result.length = BN_bn2bin(res, op->modinv.result.data); } else { cop->status = RTE_CRYPTO_OP_STATUS_ERROR; } + BN_clear(res); + BN_clear(base); + return 0; } @@ -1587,25 +1811,26 @@ process_openssl_modexp_op(struct rte_crypto_op *cop, BIGNUM *res = BN_CTX_get(sess->u.e.ctx); if (unlikely(base == NULL || res == NULL)) { - if (base) - BN_free(base); - if (res) - BN_free(res); + BN_free(base); + BN_free(res); cop->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED; return -1; } - base = BN_bin2bn((const unsigned char *)op->modinv.base.data, - op->modinv.base.length, base); + base = BN_bin2bn((const unsigned char *)op->modex.base.data, + op->modex.base.length, base); if (BN_mod_exp(res, base, sess->u.e.exp, sess->u.e.mod, sess->u.e.ctx)) { - op->modinv.base.length = BN_bn2bin(res, op->modinv.base.data); + op->modex.result.length = BN_bn2bin(res, op->modex.result.data); cop->status = RTE_CRYPTO_OP_STATUS_SUCCESS; } else { cop->status = RTE_CRYPTO_OP_STATUS_ERROR; } + BN_clear(res); + BN_clear(base); + return 0; } @@ -1618,6 +1843,9 @@ process_openssl_rsa_op(struct rte_crypto_op *cop, struct rte_crypto_asym_op *op = cop->asym; RSA *rsa = sess->u.r.rsa; uint32_t pad = (op->rsa.pad); + uint8_t *tmp; + + cop->status = RTE_CRYPTO_OP_STATUS_SUCCESS; switch (pad) { case RTE_CRYPTO_RSA_PKCS1_V1_5_BT0: @@ -1670,9 +1898,15 @@ process_openssl_rsa_op(struct rte_crypto_op *cop, break; case RTE_CRYPTO_ASYM_OP_VERIFY: + tmp = rte_malloc(NULL, op->rsa.sign.length, 0); + if (tmp == NULL) { + OPENSSL_LOG(ERR, "Memory allocation failed"); + cop->status = RTE_CRYPTO_OP_STATUS_ERROR; + break; + } ret = RSA_public_decrypt(op->rsa.sign.length, op->rsa.sign.data, - op->rsa.sign.data, + tmp, rsa, pad); @@ -1680,13 +1914,12 @@ process_openssl_rsa_op(struct rte_crypto_op *cop, "Length of public_decrypt %d " "length of message %zd\n", ret, op->rsa.message.length); - - if (memcmp(op->rsa.sign.data, op->rsa.message.data, - op->rsa.message.length)) { - OPENSSL_LOG(ERR, - "RSA sign Verification failed"); - return -1; + if ((ret <= 0) || (memcmp(tmp, op->rsa.message.data, + op->rsa.message.length))) { + OPENSSL_LOG(ERR, "RSA sign Verification failed"); + cop->status = RTE_CRYPTO_OP_STATUS_ERROR; } + rte_free(tmp); break; default: @@ -1721,6 +1954,19 @@ process_asym_op(struct openssl_qp *qp, struct rte_crypto_op *op, case RTE_CRYPTO_ASYM_XFORM_MODINV: retval = process_openssl_modinv_op(op, sess); break; + case RTE_CRYPTO_ASYM_XFORM_DH: + retval = process_openssl_dh_op(op, sess); + break; + case RTE_CRYPTO_ASYM_XFORM_DSA: + if (op->asym->dsa.op_type == RTE_CRYPTO_ASYM_OP_SIGN) + retval = process_openssl_dsa_sign_op(op, sess); + else if (op->asym->dsa.op_type == + RTE_CRYPTO_ASYM_OP_VERIFY) + retval = + process_openssl_dsa_verify_op(op, sess); + else + op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS; + break; default: op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS; break; @@ -1780,8 +2026,9 @@ process_op(struct openssl_qp *qp, struct rte_crypto_op *op, openssl_reset_session(sess); memset(sess, 0, sizeof(struct openssl_session)); memset(op->sym->session, 0, - rte_cryptodev_sym_get_header_session_size()); - rte_mempool_put(qp->sess_mp, sess); + rte_cryptodev_sym_get_existing_header_session_size( + op->sym->session)); + rte_mempool_put(qp->sess_mp_priv, sess); rte_mempool_put(qp->sess_mp, op->sym->session); op->sym->session = NULL; } @@ -1878,7 +2125,9 @@ cryptodev_openssl_create(const char *name, RTE_CRYPTODEV_FF_CPU_AESNI | RTE_CRYPTODEV_FF_OOP_SGL_IN_LB_OUT | RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT | - RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO; + RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO | + RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_EXP | + RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_QT; /* Set vector instructions mode supported */ internals = dev->data->dev_private;