aboutsummaryrefslogtreecommitdiffstats
path: root/recipes-connectivity/openssl/openssl-qoriq/qoriq/0007-Asynchronous-interface-added-for-PKC-cryptodev-inter.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes-connectivity/openssl/openssl-qoriq/qoriq/0007-Asynchronous-interface-added-for-PKC-cryptodev-inter.patch')
-rw-r--r--recipes-connectivity/openssl/openssl-qoriq/qoriq/0007-Asynchronous-interface-added-for-PKC-cryptodev-inter.patch2050
1 files changed, 2050 insertions, 0 deletions
diff --git a/recipes-connectivity/openssl/openssl-qoriq/qoriq/0007-Asynchronous-interface-added-for-PKC-cryptodev-inter.patch b/recipes-connectivity/openssl/openssl-qoriq/qoriq/0007-Asynchronous-interface-added-for-PKC-cryptodev-inter.patch
new file mode 100644
index 0000000..192cd18
--- /dev/null
+++ b/recipes-connectivity/openssl/openssl-qoriq/qoriq/0007-Asynchronous-interface-added-for-PKC-cryptodev-inter.patch
@@ -0,0 +1,2050 @@
+From 45cfc01ade9eeb43fdb5950d3db152cae1b41059 Mon Sep 17 00:00:00 2001
+From: Yashpal Dutta <yashpal.dutta@freescale.com>
+Date: Tue, 11 Mar 2014 07:14:30 +0545
+Subject: [PATCH 07/48] Asynchronous interface added for PKC cryptodev
+ interface
+
+Upstream-status: Pending
+
+Change-Id: Ia8974f793dc18a959ed6798dcdd7d3fad81cb7da
+Signed-off-by: Yashpal Dutta <yashpal.dutta@freescale.com>
+---
+ crypto/crypto.h | 16 +
+ crypto/dh/dh.h | 3 +
+ crypto/dsa/dsa.h | 5 +
+ crypto/ecdh/ech_locl.h | 3 +
+ crypto/ecdsa/ecs_locl.h | 5 +
+ crypto/engine/eng_cryptodev.c | 1598 +++++++++++++++++++++++++++++++++++++----
+ crypto/engine/eng_int.h | 23 +
+ crypto/engine/eng_lib.c | 46 ++
+ crypto/engine/engine.h | 24 +
+ crypto/rsa/rsa.h | 23 +
+ 10 files changed, 1605 insertions(+), 141 deletions(-)
+
+diff --git a/crypto/crypto.h b/crypto/crypto.h
+index 6c644ce..2b4ec59 100644
+--- a/crypto/crypto.h
++++ b/crypto/crypto.h
+@@ -655,6 +655,22 @@ void ERR_load_CRYPTO_strings(void);
+ # define CRYPTO_R_FIPS_MODE_NOT_SUPPORTED 101
+ # define CRYPTO_R_NO_DYNLOCK_CREATE_CALLBACK 100
+
++/* Additions for Asynchronous PKC Infrastructure */
++struct pkc_cookie_s {
++ void *cookie; /* To be filled by openssl library primitive method function caller */
++ void *eng_cookie; /* To be filled by Engine */
++ /*
++ * Callback handler to be provided by caller. Ensure to pass a
++ * handler which takes the crypto operation to completion.
++ * cookie: Container cookie from library
++ * status: Status of the crypto Job completion.
++ * 0: Job handled without any issue
++ * -EINVAL: Parameters Invalid
++ */
++ void (*pkc_callback)(struct pkc_cookie_s *cookie, int status);
++ void *eng_handle;
++};
++
+ #ifdef __cplusplus
+ }
+ #endif
+diff --git a/crypto/dh/dh.h b/crypto/dh/dh.h
+index a5bd901..31dd762 100644
+--- a/crypto/dh/dh.h
++++ b/crypto/dh/dh.h
+@@ -123,6 +123,9 @@ struct dh_method {
+ int (*bn_mod_exp) (const DH *dh, BIGNUM *r, const BIGNUM *a,
+ const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
+ BN_MONT_CTX *m_ctx);
++ int (*compute_key_async)(unsigned char *key,const BIGNUM *pub_key,DH *dh,
++ struct pkc_cookie_s *cookie);
++ int (*generate_key_async)(DH *dh, struct pkc_cookie_s *cookie);
+ int (*init) (DH *dh);
+ int (*finish) (DH *dh);
+ int flags;
+diff --git a/crypto/dsa/dsa.h b/crypto/dsa/dsa.h
+index 545358f..8584731 100644
+--- a/crypto/dsa/dsa.h
++++ b/crypto/dsa/dsa.h
+@@ -139,6 +139,10 @@ struct dsa_method {
+ /* Can be null */
+ int (*bn_mod_exp) (DSA *dsa, BIGNUM *r, BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
++ int (*dsa_do_sign_async)(const unsigned char *dgst, int dlen, DSA *dsa,
++ DSA_SIG *sig, struct pkc_cookie_s *cookie);
++ int (*dsa_do_verify_async)(const unsigned char *dgst, int dgst_len,
++ DSA_SIG *sig, DSA *dsa, struct pkc_cookie_s *cookie);
+ int (*init) (DSA *dsa);
+ int (*finish) (DSA *dsa);
+ int flags;
+@@ -150,6 +154,7 @@ struct dsa_method {
+ BN_GENCB *cb);
+ /* If this is non-NULL, it is used to generate DSA keys */
+ int (*dsa_keygen) (DSA *dsa);
++ int (*dsa_keygen_async)(DSA *dsa, struct pkc_cookie_s *cookie);
+ };
+
+ struct dsa_st {
+diff --git a/crypto/ecdh/ech_locl.h b/crypto/ecdh/ech_locl.h
+index 4e66024..502507b 100644
+--- a/crypto/ecdh/ech_locl.h
++++ b/crypto/ecdh/ech_locl.h
+@@ -68,6 +68,9 @@ struct ecdh_method {
+ EC_KEY *ecdh, void *(*KDF) (const void *in,
+ size_t inlen, void *out,
+ size_t *outlen));
++ int (*compute_key_async)(void *key, size_t outlen, const EC_POINT *pub_key, EC_KEY *ecdh,
++ void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen),
++ struct pkc_cookie_s *cookie);
+ # if 0
+ int (*init) (EC_KEY *eckey);
+ int (*finish) (EC_KEY *eckey);
+diff --git a/crypto/ecdsa/ecs_locl.h b/crypto/ecdsa/ecs_locl.h
+index d3a5efc..9b28c04 100644
+--- a/crypto/ecdsa/ecs_locl.h
++++ b/crypto/ecdsa/ecs_locl.h
+@@ -74,6 +74,11 @@ struct ecdsa_method {
+ BIGNUM **r);
+ int (*ecdsa_do_verify) (const unsigned char *dgst, int dgst_len,
+ const ECDSA_SIG *sig, EC_KEY *eckey);
++ int (*ecdsa_do_sign_async)(const unsigned char *dgst, int dgst_len,
++ const BIGNUM *inv, const BIGNUM *rp, EC_KEY *eckey,
++ ECDSA_SIG *sig, struct pkc_cookie_s *cookie);
++ int (*ecdsa_do_verify_async)(const unsigned char *dgst, int dgst_len,
++ const ECDSA_SIG *sig, EC_KEY *eckey, struct pkc_cookie_s *cookie);
+ # if 0
+ int (*init) (EC_KEY *eckey);
+ int (*finish) (EC_KEY *eckey);
+diff --git a/crypto/engine/eng_cryptodev.c b/crypto/engine/eng_cryptodev.c
+index 0b41bb2..8303630 100644
+--- a/crypto/engine/eng_cryptodev.c
++++ b/crypto/engine/eng_cryptodev.c
+@@ -1367,6 +1367,60 @@ static void zapparams(struct crypt_kop *kop)
+ }
+ }
+
++/*
++ * Any PKC request has at max 2 output parameters and they are stored here to
++ * be used while copying in the check availability
++ */
++struct cryptodev_cookie_s {
++ BIGNUM *r;
++ struct crparam r_param;
++ BIGNUM *s;
++ struct crparam s_param;
++ struct crypt_kop *kop;
++};
++
++static int
++cryptodev_asym_async(struct crypt_kop *kop, int rlen, BIGNUM *r, int slen,
++ BIGNUM *s)
++{
++ int fd;
++ struct pkc_cookie_s *cookie = kop->cookie;
++ struct cryptodev_cookie_s *eng_cookie;
++
++ fd = *(int *)cookie->eng_handle;
++
++ eng_cookie = malloc(sizeof(struct cryptodev_cookie_s));
++
++ if (eng_cookie) {
++ memset(eng_cookie, 0, sizeof(struct cryptodev_cookie_s));
++ if (r) {
++ kop->crk_param[kop->crk_iparams].crp_p =
++ calloc(rlen, sizeof(char));
++ if (!kop->crk_param[kop->crk_iparams].crp_p)
++ return -ENOMEM;
++ kop->crk_param[kop->crk_iparams].crp_nbits = rlen * 8;
++ kop->crk_oparams++;
++ eng_cookie->r = r;
++ eng_cookie->r_param = kop->crk_param[kop->crk_iparams];
++ }
++ if (s) {
++ kop->crk_param[kop->crk_iparams + 1].crp_p =
++ calloc(slen, sizeof(char));
++ if (!kop->crk_param[kop->crk_iparams + 1].crp_p)
++ return -ENOMEM;
++ kop->crk_param[kop->crk_iparams + 1].crp_nbits = slen * 8;
++ kop->crk_oparams++;
++ eng_cookie->s = s;
++ eng_cookie->s_param = kop->crk_param[kop->crk_iparams + 1];
++ }
++ } else
++ return -ENOMEM;
++
++ eng_cookie->kop = kop;
++ cookie->eng_cookie = eng_cookie;
++ return ioctl(fd, CIOCASYMASYNCRYPT, kop);
++}
++
+ static int
+ cryptodev_asym(struct crypt_kop *kop, int rlen, BIGNUM *r, int slen,
+ BIGNUM *s)
+@@ -1425,6 +1479,44 @@ void *cryptodev_init_instance(void)
+ return fd;
+ }
+
++# include <poll.h>
++
++/* Return 0 on success and 1 on failure */
++int cryptodev_check_availability(void *eng_handle)
++{
++ int fd = *(int *)eng_handle;
++ struct pkc_cookie_list_s cookie_list;
++ struct pkc_cookie_s *cookie;
++ int i;
++
++ /* FETCH COOKIE returns number of cookies extracted */
++ if (ioctl(fd, CIOCASYMFETCHCOOKIE, &cookie_list) <= 0)
++ return 1;
++
++ for (i = 0; i < cookie_list.cookie_available; i++) {
++ cookie = cookie_list.cookie[i];
++ if (cookie) {
++ struct cryptodev_cookie_s *eng_cookie = cookie->eng_cookie;
++ if (eng_cookie) {
++ struct crypt_kop *kop = eng_cookie->kop;
++
++ if (eng_cookie->r)
++ crparam2bn(&eng_cookie->r_param, eng_cookie->r);
++ if (eng_cookie->s)
++ crparam2bn(&eng_cookie->s_param, eng_cookie->s);
++ if (kop->crk_op == CRK_DH_COMPUTE_KEY)
++ kop->crk_oparams = 0;
++
++ zapparams(eng_cookie->kop);
++ free(eng_cookie->kop);
++ free(eng_cookie);
++ }
++ cookie->pkc_callback(cookie, cookie_list.status[i]);
++ }
++ }
++ return 0;
++}
++
+ static int
+ cryptodev_bn_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont)
+@@ -1472,6 +1564,66 @@ cryptodev_bn_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ }
+
+ static int
++cryptodev_bn_mod_exp_async(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
++ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont,
++ struct pkc_cookie_s *cookie)
++{
++ struct crypt_kop *kop = malloc(sizeof(struct crypt_kop));
++ int ret = 1;
++
++ /*
++ * Currently, we know we can do mod exp iff we can do any asymmetric
++ * operations at all.
++ */
++ if (cryptodev_asymfeat == 0 || !kop) {
++ ret = BN_mod_exp(r, a, p, m, ctx);
++ return (ret);
++ }
++
++ kop->crk_oparams = 0;
++ kop->crk_status = 0;
++ kop->crk_op = CRK_MOD_EXP;
++ kop->cookie = cookie;
++ /* inputs: a^p % m */
++ if (bn2crparam(a, &kop->crk_param[0]))
++ goto err;
++ if (bn2crparam(p, &kop->crk_param[1]))
++ goto err;
++ if (bn2crparam(m, &kop->crk_param[2]))
++ goto err;
++
++ kop->crk_iparams = 3;
++ if (cryptodev_asym_async(kop, BN_num_bytes(m), r, 0, NULL))
++ goto err;
++
++ return ret;
++ err:
++ {
++ const RSA_METHOD *meth = RSA_PKCS1_SSLeay();
++
++ if (kop)
++ free(kop);
++ ret = meth->bn_mod_exp(r, a, p, m, ctx, in_mont);
++ if (ret)
++ /* Call the completion handler immediately */
++ cookie->pkc_callback(cookie, 0);
++ }
++ return ret;
++}
++
++static int
++cryptodev_rsa_nocrt_mod_exp_async(BIGNUM *r0, const BIGNUM *I,
++ RSA *rsa, BN_CTX *ctx,
++ struct pkc_cookie_s *cookie)
++{
++ int r;
++ ctx = BN_CTX_new();
++ r = cryptodev_bn_mod_exp_async(r0, I, rsa->d, rsa->n, ctx, NULL, cookie);
++ BN_CTX_free(ctx);
++ return r;
++}
++
++static int
+ cryptodev_rsa_nocrt_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa,
+ BN_CTX *ctx)
+ {
+@@ -1538,6 +1690,63 @@ cryptodev_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
+ return (ret);
+ }
+
++static int
++cryptodev_rsa_mod_exp_async(BIGNUM *r0, const BIGNUM *I, RSA *rsa,
++ BN_CTX *ctx, struct pkc_cookie_s *cookie)
++{
++ struct crypt_kop *kop = malloc(sizeof(struct crypt_kop));
++ int ret = 1, f_len, p_len, q_len;
++ unsigned char *f = NULL, *p = NULL, *q = NULL, *dp = NULL, *dq =
++ NULL, *c = NULL;
++
++ if (!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp || !kop) {
++ return (0);
++ }
++
++ kop->crk_oparams = 0;
++ kop->crk_status = 0;
++ kop->crk_op = CRK_MOD_EXP_CRT;
++ f_len = BN_num_bytes(rsa->n);
++ spcf_bn2bin_ex(I, &f, &f_len);
++ spcf_bn2bin(rsa->p, &p, &p_len);
++ spcf_bn2bin(rsa->q, &q, &q_len);
++ spcf_bn2bin_ex(rsa->dmp1, &dp, &p_len);
++ spcf_bn2bin_ex(rsa->iqmp, &c, &p_len);
++ spcf_bn2bin_ex(rsa->dmq1, &dq, &q_len);
++ /* inputs: rsa->p rsa->q I rsa->dmp1 rsa->dmq1 rsa->iqmp */
++ kop->crk_param[0].crp_p = p;
++ kop->crk_param[0].crp_nbits = p_len * 8;
++ kop->crk_param[1].crp_p = q;
++ kop->crk_param[1].crp_nbits = q_len * 8;
++ kop->crk_param[2].crp_p = f;
++ kop->crk_param[2].crp_nbits = f_len * 8;
++ kop->crk_param[3].crp_p = dp;
++ kop->crk_param[3].crp_nbits = p_len * 8;
++ /* dq must of length q, rest all of length p */
++ kop->crk_param[4].crp_p = dq;
++ kop->crk_param[4].crp_nbits = q_len * 8;
++ kop->crk_param[5].crp_p = c;
++ kop->crk_param[5].crp_nbits = p_len * 8;
++ kop->crk_iparams = 6;
++ kop->cookie = cookie;
++ if (cryptodev_asym_async(kop, BN_num_bytes(rsa->n), r0, 0, NULL))
++ goto err;
++
++ return ret;
++ err:
++ {
++ const RSA_METHOD *meth = RSA_PKCS1_SSLeay();
++
++ if (kop)
++ free(kop);
++ ret = (*meth->rsa_mod_exp) (r0, I, rsa, ctx);
++ if (ret)
++ /* Call user completion handler immediately */
++ cookie->pkc_callback(cookie, 0);
++ }
++ return (ret);
++}
++
+ static RSA_METHOD cryptodev_rsa = {
+ "cryptodev RSA method",
+ NULL, /* rsa_pub_enc */
+@@ -1546,6 +1755,12 @@ static RSA_METHOD cryptodev_rsa = {
+ NULL, /* rsa_priv_dec */
+ NULL,
+ NULL,
++ NULL, /* rsa_pub_enc */
++ NULL, /* rsa_pub_dec */
++ NULL, /* rsa_priv_enc */
++ NULL, /* rsa_priv_dec */
++ NULL,
++ NULL,
+ NULL, /* init */
+ NULL, /* finish */
+ 0, /* flags */
+@@ -1846,128 +2061,428 @@ static int cryptodev_dsa_keygen(DSA *dsa)
+ return ret;
+ }
+
+-static DSA_METHOD cryptodev_dsa = {
+- "cryptodev DSA method",
+- NULL,
+- NULL, /* dsa_sign_setup */
+- NULL,
+- NULL, /* dsa_mod_exp */
+- NULL,
+- NULL, /* init */
+- NULL, /* finish */
+- 0, /* flags */
+- NULL /* app_data */
+-};
++/* Cryptodev DSA Key Gen routine */
++static int cryptodev_dsa_keygen_async(DSA *dsa, struct pkc_cookie_s *cookie)
++{
++ struct crypt_kop *kop = malloc(sizeof(struct crypt_kop));
++ int ret = 1, g_len;
++ unsigned char *g = NULL;
+
+-static ECDSA_METHOD cryptodev_ecdsa = {
+- "cryptodev ECDSA method",
+- NULL,
+- NULL, /* ecdsa_sign_setup */
+- NULL,
+- NULL,
+- 0, /* flags */
+- NULL /* app_data */
+-};
++ if (!kop)
++ goto sw_try;
+
+-typedef enum ec_curve_s {
+- EC_PRIME,
+- EC_BINARY
+-} ec_curve_t;
++ if (dsa->priv_key == NULL) {
++ if ((dsa->priv_key = BN_new()) == NULL)
++ goto sw_try;
++ }
+
+-/* ENGINE handler for ECDSA Sign */
+-static ECDSA_SIG *cryptodev_ecdsa_do_sign(const unsigned char *dgst,
+- int dgst_len, const BIGNUM *in_kinv,
+- const BIGNUM *in_r, EC_KEY *eckey)
+-{
+- BIGNUM *m = NULL, *p = NULL, *a = NULL;
+- BIGNUM *b = NULL, *x = NULL, *y = NULL;
+- BN_CTX *ctx = NULL;
+- ECDSA_SIG *ret = NULL;
+- ECDSA_DATA *ecdsa = NULL;
+- unsigned char *q = NULL, *r = NULL, *ab = NULL, *g_xy = NULL;
+- unsigned char *s = NULL, *c = NULL, *d = NULL, *f = NULL, *tmp_dgst =
+- NULL;
+- int i = 0, q_len = 0, priv_key_len = 0, r_len = 0;
+- int g_len = 0, d_len = 0, ab_len = 0;
+- const BIGNUM *order = NULL, *priv_key = NULL;
+- const EC_GROUP *group = NULL;
+- struct crypt_kop kop;
+- ec_curve_t ec_crv = EC_PRIME;
++ if (dsa->pub_key == NULL) {
++ if ((dsa->pub_key = BN_new()) == NULL)
++ goto sw_try;
++ }
+
+- memset(&kop, 0, sizeof(kop));
+- ecdsa = ecdsa_check(eckey);
+- if (!ecdsa) {
+- ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_PASSED_NULL_PARAMETER);
+- return NULL;
++ g_len = BN_num_bytes(dsa->p);
++ /**
++ * Get generator into a plain buffer. If length is less than
++ * q_len then add leading padding bytes.
++ */
++ if (spcf_bn2bin_ex(dsa->g, &g, &g_len)) {
++ DSAerr(DSA_F_DSA_GENERATE_KEY, ERR_R_MALLOC_FAILURE);
++ goto sw_try;
+ }
+
+- group = EC_KEY_get0_group(eckey);
+- priv_key = EC_KEY_get0_private_key(eckey);
++ memset(kop, 0, sizeof(struct crypt_kop));
++ kop->crk_op = CRK_DSA_GENERATE_KEY;
++ if (bn2crparam(dsa->p, &kop->crk_param[0]))
++ goto sw_try;
++ if (bn2crparam(dsa->q, &kop->crk_param[1]))
++ goto sw_try;
++ kop->crk_param[2].crp_p = g;
++ kop->crk_param[2].crp_nbits = g_len * 8;
++ kop->crk_iparams = 3;
++ kop->cookie = cookie;
+
+- if (!group || !priv_key) {
+- ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_PASSED_NULL_PARAMETER);
+- return NULL;
++ /* pub_key is or prime length while priv key is of length of order */
++ if (cryptodev_asym_async(kop, BN_num_bytes(dsa->p), dsa->pub_key,
++ BN_num_bytes(dsa->q), dsa->priv_key))
++ goto sw_try;
++
++ return ret;
++ sw_try:
++ {
++ const DSA_METHOD *meth = DSA_OpenSSL();
++
++ if (kop)
++ free(kop);
++ ret = (meth->dsa_keygen) (dsa);
++ cookie->pkc_callback(cookie, 0);
+ }
++ return ret;
++}
+
+- if ((ctx = BN_CTX_new()) == NULL || (m = BN_new()) == NULL ||
+- (a = BN_new()) == NULL || (b = BN_new()) == NULL ||
+- (p = BN_new()) == NULL || (x = BN_new()) == NULL ||
+- (y = BN_new()) == NULL) {
+- ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
++static int
++cryptodev_dsa_do_sign_async(const unsigned char *dgst, int dlen, DSA *dsa,
++ DSA_SIG *sig, struct pkc_cookie_s *cookie)
++{
++ struct crypt_kop *kop = malloc(sizeof(struct crypt_kop));
++ DSA_SIG *dsaret = NULL;
++ int q_len = 0, r_len = 0, g_len = 0;
++ int priv_key_len = 0, ret = 1;
++ unsigned char *q = NULL, *r = NULL, *g = NULL, *priv_key = NULL, *f =
++ NULL;
++ if (((sig->r = BN_new()) == NULL) || !kop) {
++ DSAerr(DSA_F_DSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+- order = &group->order;
+- if (!order || BN_is_zero(order)) {
+- ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ECDSA_R_MISSING_PARAMETERS);
++ if ((sig->s = BN_new()) == NULL) {
++ BN_free(sig->r);
++ DSAerr(DSA_F_DSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+- i = BN_num_bits(order);
+- /*
+- * Need to truncate digest if it is too long: first truncate whole bytes
+- */
+- if (8 * dgst_len > i)
+- dgst_len = (i + 7) / 8;
+-
+- if (!BN_bin2bn(dgst, dgst_len, m)) {
+- ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
++ if (spcf_bn2bin(dsa->p, &q, &q_len)) {
++ DSAerr(DSA_F_DSA_DO_SIGN, DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
+ goto err;
+ }
+
+- /* If still too long truncate remaining bits with a shift */
+- if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) {
+- ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
++ /* Get order of the field of private keys into plain buffer */
++ if (spcf_bn2bin(dsa->q, &r, &r_len)) {
++ DSAerr(DSA_F_DSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+- /* copy the truncated bits into plain buffer */
+- if (spcf_bn2bin(m, &tmp_dgst, &dgst_len)) {
+- fprintf(stderr, "%s:%d: OPENSSL_malloc failec\n", __FUNCTION__,
+- __LINE__);
++ /* sanity test */
++ if (dlen > r_len) {
++ DSAerr(DSA_F_DSA_DO_SIGN, DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
+ goto err;
+ }
+
+- ret = ECDSA_SIG_new();
+- if (!ret) {
+- ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
++ g_len = q_len;
++ /**
++ * Get generator into a plain buffer. If length is less than
++ * q_len then add leading padding bytes.
++ */
++ if (spcf_bn2bin_ex(dsa->g, &g, &g_len)) {
++ DSAerr(DSA_F_DSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+- /* check if this is prime or binary EC request */
+- if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) ==
+- NID_X9_62_prime_field) {
+- ec_crv = EC_PRIME;
+- /* get the generator point pair */
+- if (!EC_POINT_get_affine_coordinates_GFp
+- (group, EC_GROUP_get0_generator(group), x, y, ctx)) {
+- ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_EC_LIB);
+- goto err;
+- }
++ priv_key_len = r_len;
++ /**
++ * Get private key into a plain buffer. If length is less than
++ * r_len then add leading padding bytes.
++ */
++ if (spcf_bn2bin_ex(dsa->priv_key, &priv_key, &priv_key_len)) {
++ DSAerr(DSA_F_DSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
+
+- /* get the ECC curve parameters */
+- if (!EC_GROUP_get_curve_GFp(group, p, a, b, ctx)) {
+- ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_EC_LIB);
++ /* Allocate memory to store hash. */
++ f = OPENSSL_malloc(r_len);
++ if (!f) {
++ DSAerr(DSA_F_DSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /* Add padding, since SEC expects hash to of size r_len */
++ if (dlen < r_len)
++ memset(f, 0, r_len - dlen);
++
++ /* Skip leading bytes if dgst_len < r_len */
++ memcpy(f + r_len - dlen, dgst, dlen);
++
++ dlen = r_len;
++
++ memset(kop, 0, sizeof(struct crypt_kop));
++ kop->crk_op = CRK_DSA_SIGN;
++
++ /* inputs: dgst dsa->p dsa->q dsa->g dsa->priv_key */
++ kop->crk_param[0].crp_p = (void *)f;
++ kop->crk_param[0].crp_nbits = dlen * 8;
++ kop->crk_param[1].crp_p = (void *)q;
++ kop->crk_param[1].crp_nbits = q_len * 8;
++ kop->crk_param[2].crp_p = (void *)r;
++ kop->crk_param[2].crp_nbits = r_len * 8;
++ kop->crk_param[3].crp_p = (void *)g;
++ kop->crk_param[3].crp_nbits = g_len * 8;
++ kop->crk_param[4].crp_p = (void *)priv_key;
++ kop->crk_param[4].crp_nbits = priv_key_len * 8;
++ kop->crk_iparams = 5;
++ kop->cookie = cookie;
++
++ if (cryptodev_asym_async(kop, r_len, sig->r, r_len, sig->s))
++ goto err;
++
++ return ret;
++ err:
++ {
++ const DSA_METHOD *meth = DSA_OpenSSL();
++
++ if (kop)
++ free(kop);
++ BN_free(sig->r);
++ BN_free(sig->s);
++ dsaret = (meth->dsa_do_sign) (dgst, dlen, dsa);
++ sig->r = dsaret->r;
++ sig->s = dsaret->s;
++ /* Call user callback immediately */
++ cookie->pkc_callback(cookie, 0);
++ ret = dsaret;
++ }
++ return ret;
++}
++
++static int
++cryptodev_dsa_verify_async(const unsigned char *dgst, int dlen,
++ DSA_SIG *sig, DSA *dsa,
++ struct pkc_cookie_s *cookie)
++{
++ struct crypt_kop *kop = malloc(sizeof(struct crypt_kop));
++ int q_len = 0, r_len = 0, g_len = 0;
++ int w_len = 0, c_len = 0, d_len = 0, ret = 1;
++ unsigned char *q = NULL, *r = NULL, *w = NULL, *g = NULL;
++ unsigned char *c = NULL, *d = NULL, *f = NULL;
++
++ if (!kop)
++ goto err;
++
++ if (spcf_bn2bin(dsa->p, &q, &q_len)) {
++ DSAerr(DSA_F_DSA_DO_VERIFY, ERR_R_MALLOC_FAILURE);
++ return ret;
++ }
++
++ /* Get Order of field of private keys */
++ if (spcf_bn2bin(dsa->q, &r, &r_len)) {
++ DSAerr(DSA_F_DSA_DO_VERIFY, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ g_len = q_len;
++ /**
++ * Get generator into a plain buffer. If length is less than
++ * q_len then add leading padding bytes.
++ */
++ if (spcf_bn2bin_ex(dsa->g, &g, &g_len)) {
++ DSAerr(DSA_F_DSA_DO_VERIFY, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
++ w_len = q_len;
++ /**
++ * Get public key into a plain buffer. If length is less than
++ * q_len then add leading padding bytes.
++ */
++ if (spcf_bn2bin_ex(dsa->pub_key, &w, &w_len)) {
++ DSAerr(DSA_F_DSA_DO_VERIFY, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
++ /**
++ * Get the 1st part of signature into a flat buffer with
++ * appropriate padding
++ */
++ c_len = r_len;
++
++ if (spcf_bn2bin_ex(sig->r, &c, &c_len)) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /**
++ * Get the 2nd part of signature into a flat buffer with
++ * appropriate padding
++ */
++ d_len = r_len;
++
++ if (spcf_bn2bin_ex(sig->s, &d, &d_len)) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /* Sanity test */
++ if (dlen > r_len) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /* Allocate memory to store hash. */
++ f = OPENSSL_malloc(r_len);
++ if (!f) {
++ DSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /* Add padding, since SEC expects hash to of size r_len */
++ if (dlen < r_len)
++ memset(f, 0, r_len - dlen);
++
++ /* Skip leading bytes if dgst_len < r_len */
++ memcpy(f + r_len - dlen, dgst, dlen);
++
++ dlen = r_len;
++ memset(kop, 0, sizeof(struct crypt_kop));
++
++ /* inputs: dgst dsa->p dsa->q dsa->g dsa->pub_key sig->r sig->s */
++ kop->crk_param[0].crp_p = (void *)f;
++ kop->crk_param[0].crp_nbits = dlen * 8;
++ kop->crk_param[1].crp_p = q;
++ kop->crk_param[1].crp_nbits = q_len * 8;
++ kop->crk_param[2].crp_p = r;
++ kop->crk_param[2].crp_nbits = r_len * 8;
++ kop->crk_param[3].crp_p = g;
++ kop->crk_param[3].crp_nbits = g_len * 8;
++ kop->crk_param[4].crp_p = w;
++ kop->crk_param[4].crp_nbits = w_len * 8;
++ kop->crk_param[5].crp_p = c;
++ kop->crk_param[5].crp_nbits = c_len * 8;
++ kop->crk_param[6].crp_p = d;
++ kop->crk_param[6].crp_nbits = d_len * 8;
++ kop->crk_iparams = 7;
++ kop->crk_op = CRK_DSA_VERIFY;
++ kop->cookie = cookie;
++ if (cryptodev_asym_async(kop, 0, NULL, 0, NULL))
++ goto err;
++
++ return ret;
++ err:
++ {
++ const DSA_METHOD *meth = DSA_OpenSSL();
++
++ if (kop)
++ free(kop);
++
++ ret = (meth->dsa_do_verify) (dgst, dlen, sig, dsa);
++ cookie->pkc_callback(cookie, 0);
++ }
++ return ret;
++}
++
++static DSA_METHOD cryptodev_dsa = {
++ "cryptodev DSA method",
++ NULL,
++ NULL, /* dsa_sign_setup */
++ NULL,
++ NULL, /* dsa_mod_exp */
++ NULL,
++ NULL,
++ NULL,
++ NULL,
++ NULL, /* init */
++ NULL, /* finish */
++ 0, /* flags */
++ NULL /* app_data */
++};
++
++static ECDSA_METHOD cryptodev_ecdsa = {
++ "cryptodev ECDSA method",
++ NULL,
++ NULL, /* ecdsa_sign_setup */
++ NULL,
++ NULL,
++ NULL,
++ NULL,
++ 0, /* flags */
++ NULL /* app_data */
++};
++
++typedef enum ec_curve_s {
++ EC_PRIME,
++ EC_BINARY
++} ec_curve_t;
++
++/* ENGINE handler for ECDSA Sign */
++static ECDSA_SIG *cryptodev_ecdsa_do_sign(const unsigned char *dgst,
++ int dgst_len, const BIGNUM *in_kinv,
++ const BIGNUM *in_r, EC_KEY *eckey)
++{
++ BIGNUM *m = NULL, *p = NULL, *a = NULL;
++ BIGNUM *b = NULL, *x = NULL, *y = NULL;
++ BN_CTX *ctx = NULL;
++ ECDSA_SIG *ret = NULL;
++ ECDSA_DATA *ecdsa = NULL;
++ unsigned char *q = NULL, *r = NULL, *ab = NULL, *g_xy = NULL;
++ unsigned char *s = NULL, *c = NULL, *d = NULL, *f = NULL, *tmp_dgst =
++ NULL;
++ int i = 0, q_len = 0, priv_key_len = 0, r_len = 0;
++ int g_len = 0, d_len = 0, ab_len = 0;
++ const BIGNUM *order = NULL, *priv_key = NULL;
++ const EC_GROUP *group = NULL;
++ struct crypt_kop kop;
++ ec_curve_t ec_crv = EC_PRIME;
++
++ memset(&kop, 0, sizeof(kop));
++ ecdsa = ecdsa_check(eckey);
++ if (!ecdsa) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_PASSED_NULL_PARAMETER);
++ return NULL;
++ }
++
++ group = EC_KEY_get0_group(eckey);
++ priv_key = EC_KEY_get0_private_key(eckey);
++
++ if (!group || !priv_key) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_PASSED_NULL_PARAMETER);
++ return NULL;
++ }
++
++ if ((ctx = BN_CTX_new()) == NULL || (m = BN_new()) == NULL ||
++ (a = BN_new()) == NULL || (b = BN_new()) == NULL ||
++ (p = BN_new()) == NULL || (x = BN_new()) == NULL ||
++ (y = BN_new()) == NULL) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ order = &group->order;
++ if (!order || BN_is_zero(order)) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ECDSA_R_MISSING_PARAMETERS);
++ goto err;
++ }
++
++ i = BN_num_bits(order);
++ /*
++ * Need to truncate digest if it is too long: first truncate whole bytes
++ */
++ if (8 * dgst_len > i)
++ dgst_len = (i + 7) / 8;
++
++ if (!BN_bin2bn(dgst, dgst_len, m)) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
++ goto err;
++ }
++
++ /* If still too long truncate remaining bits with a shift */
++ if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
++ goto err;
++ }
++
++ /* copy the truncated bits into plain buffer */
++ if (spcf_bn2bin(m, &tmp_dgst, &dgst_len)) {
++ fprintf(stderr, "%s:%d: OPENSSL_malloc failec\n", __FUNCTION__,
++ __LINE__);
++ goto err;
++ }
++
++ ret = ECDSA_SIG_new();
++ if (!ret) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
++ goto err;
++ }
++
++ /* check if this is prime or binary EC request */
++ if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) ==
++ NID_X9_62_prime_field) {
++ ec_crv = EC_PRIME;
++ /* get the generator point pair */
++ if (!EC_POINT_get_affine_coordinates_GFp
++ (group, EC_GROUP_get0_generator(group), x, y, ctx)) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_EC_LIB);
++ goto err;
++ }
++
++ /* get the ECC curve parameters */
++ if (!EC_GROUP_get_curve_GFp(group, p, a, b, ctx)) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_EC_LIB);
+ goto err;
+ }
+ } else if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) ==
+@@ -2312,54 +2827,588 @@ static int cryptodev_ecdsa_verify(const unsigned char *dgst, int dgst_len,
+ goto err;
+ }
+
+- /* memory for message representative */
+- f = malloc(r_len);
+- if (!f) {
+- ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE);
+- goto err;
++ /* memory for message representative */
++ f = malloc(r_len);
++ if (!f) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /* Add padding, since SEC expects hash to of size r_len */
++ memset(f, 0, r_len - dgst_len);
++
++ /* Skip leading bytes if dgst_len < r_len */
++ memcpy(f + r_len - dgst_len, tmp_dgst, dgst_len);
++ dgst_len += r_len - dgst_len;
++ kop.crk_op = CRK_DSA_VERIFY;
++ /* inputs: dgst dsa->p dsa->q dsa->g dsa->priv_key */
++ kop.crk_param[0].crp_p = f;
++ kop.crk_param[0].crp_nbits = dgst_len * 8;
++ kop.crk_param[1].crp_p = q;
++ kop.crk_param[1].crp_nbits = q_len * 8;
++ kop.crk_param[2].crp_p = r;
++ kop.crk_param[2].crp_nbits = r_len * 8;
++ kop.crk_param[3].crp_p = g_xy;
++ kop.crk_param[3].crp_nbits = g_len * 8;
++ kop.crk_param[4].crp_p = w_xy;
++ kop.crk_param[4].crp_nbits = pub_key_len * 8;
++ kop.crk_param[5].crp_p = ab;
++ kop.crk_param[5].crp_nbits = ab_len * 8;
++ kop.crk_param[6].crp_p = c;
++ kop.crk_param[6].crp_nbits = d_len * 8;
++ kop.crk_param[7].crp_p = d;
++ kop.crk_param[7].crp_nbits = d_len * 8;
++ kop.crk_iparams = 8;
++
++ if (cryptodev_asym(&kop, 0, NULL, 0, NULL) == 0) {
++ /*
++ * OCF success value is 0, if not zero, change ret to fail
++ */
++ if (0 == kop.crk_status)
++ ret = 1;
++ } else {
++ const ECDSA_METHOD *meth = ECDSA_OpenSSL();
++
++ ret = (meth->ecdsa_do_verify) (dgst, dgst_len, sig, eckey);
++ }
++ kop.crk_param[0].crp_p = NULL;
++ zapparams(&kop);
++
++ err:
++ return ret;
++}
++
++static int cryptodev_ecdsa_do_sign_async(const unsigned char *dgst,
++ int dgst_len, const BIGNUM *in_kinv,
++ const BIGNUM *in_r, EC_KEY *eckey,
++ ECDSA_SIG *sig,
++ struct pkc_cookie_s *cookie)
++{
++ BIGNUM *m = NULL, *p = NULL, *a = NULL;
++ BIGNUM *b = NULL, *x = NULL, *y = NULL;
++ BN_CTX *ctx = NULL;
++ ECDSA_SIG *sig_ret = NULL;
++ ECDSA_DATA *ecdsa = NULL;
++ unsigned char *q = NULL, *r = NULL, *ab = NULL, *g_xy = NULL;
++ unsigned char *s = NULL, *f = NULL, *tmp_dgst = NULL;
++ int i = 0, q_len = 0, priv_key_len = 0, r_len = 0;
++ int g_len = 0, ab_len = 0, ret = 1;
++ const BIGNUM *order = NULL, *priv_key = NULL;
++ const EC_GROUP *group = NULL;
++ struct crypt_kop *kop = malloc(sizeof(struct crypt_kop));
++ ec_curve_t ec_crv = EC_PRIME;
++
++ if (!(sig->r = BN_new()) || !kop)
++ goto err;
++ if ((sig->s = BN_new()) == NULL) {
++ BN_free(r);
++ goto err;
++ }
++
++ memset(kop, 0, sizeof(struct crypt_kop));
++ ecdsa = ecdsa_check(eckey);
++ if (!ecdsa) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_PASSED_NULL_PARAMETER);
++ goto err;
++ }
++
++ group = EC_KEY_get0_group(eckey);
++ priv_key = EC_KEY_get0_private_key(eckey);
++
++ if (!group || !priv_key) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_PASSED_NULL_PARAMETER);
++ goto err;
++ }
++
++ if ((ctx = BN_CTX_new()) == NULL || (m = BN_new()) == NULL ||
++ (a = BN_new()) == NULL || (b = BN_new()) == NULL ||
++ (p = BN_new()) == NULL || (x = BN_new()) == NULL ||
++ (y = BN_new()) == NULL) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ order = &group->order;
++ if (!order || BN_is_zero(order)) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ECDSA_R_MISSING_PARAMETERS);
++ goto err;
++ }
++
++ i = BN_num_bits(order);
++ /*
++ * Need to truncate digest if it is too long: first truncate whole bytes
++ */
++ if (8 * dgst_len > i)
++ dgst_len = (i + 7) / 8;
++
++ if (!BN_bin2bn(dgst, dgst_len, m)) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
++ goto err;
++ }
++
++ /* If still too long truncate remaining bits with a shift */
++ if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
++ goto err;
++ }
++
++ /* copy the truncated bits into plain buffer */
++ if (spcf_bn2bin(m, &tmp_dgst, &dgst_len)) {
++ fprintf(stderr, "%s:%d: OPENSSL_malloc failec\n", __FUNCTION__,
++ __LINE__);
++ goto err;
++ }
++
++ /* check if this is prime or binary EC request */
++ if (EC_METHOD_get_field_type(EC_GROUP_method_of(group))
++ == NID_X9_62_prime_field) {
++ ec_crv = EC_PRIME;
++ /* get the generator point pair */
++ if (!EC_POINT_get_affine_coordinates_GFp(group,
++ EC_GROUP_get0_generator
++ (group), x, y, ctx)) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_EC_LIB);
++ goto err;
++ }
++
++ /* get the ECC curve parameters */
++ if (!EC_GROUP_get_curve_GFp(group, p, a, b, ctx)) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_EC_LIB);
++ goto err;
++ }
++ } else if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) ==
++ NID_X9_62_characteristic_two_field) {
++ ec_crv = EC_BINARY;
++ /* get the ECC curve parameters */
++ if (!EC_GROUP_get_curve_GF2m(group, p, a, b, ctx)) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_EC_LIB);
++ goto err;
++ }
++
++ /* get the generator point pair */
++ if (!EC_POINT_get_affine_coordinates_GF2m(group,
++ EC_GROUP_get0_generator
++ (group), x, y, ctx)) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_EC_LIB);
++ goto err;
++ }
++ } else {
++ printf("Unsupported Curve\n");
++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_EC_LIB);
++ goto err;
++ }
++
++ if (spcf_bn2bin(order, &r, &r_len)) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ if (spcf_bn2bin(p, &q, &q_len)) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ priv_key_len = r_len;
++
++ /**
++ * If BN_num_bytes of priv_key returns less then r_len then
++ * add padding bytes before the key
++ */
++ if (spcf_bn2bin_ex(priv_key, &s, &priv_key_len)) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /* Generation of ECC curve parameters */
++ ab_len = 2 * q_len;
++ ab = eng_copy_curve_points(a, b, ab_len, q_len);
++ if (!ab) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ if (ec_crv == EC_BINARY) {
++ if (eng_ec_get_cparam
++ (EC_GROUP_get_curve_name(group), ab + q_len, q_len)) {
++ unsigned char *c_temp = NULL;
++ int c_temp_len = q_len;
++ if (eng_ec_compute_cparam(b, p, &c_temp, &c_temp_len))
++ memcpy(ab + q_len, c_temp, q_len);
++ else
++ goto err;
++ }
++ kop->curve_type = ECC_BINARY;
++ }
++
++ /* Calculation of Generator point */
++ g_len = 2 * q_len;
++ g_xy = eng_copy_curve_points(x, y, g_len, q_len);
++ if (!g_xy) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /* memory for message representative */
++ f = malloc(r_len);
++ if (!f) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /* Add padding, since SEC expects hash to of size r_len */
++ memset(f, 0, r_len - dgst_len);
++
++ /* Skip leading bytes if dgst_len < r_len */
++ memcpy(f + r_len - dgst_len, tmp_dgst, dgst_len);
++
++ dgst_len += r_len - dgst_len;
++
++ kop->crk_op = CRK_DSA_SIGN;
++ /* inputs: dgst dsa->p dsa->q dsa->g dsa->priv_key */
++ kop->crk_param[0].crp_p = f;
++ kop->crk_param[0].crp_nbits = dgst_len * 8;
++ kop->crk_param[1].crp_p = q;
++ kop->crk_param[1].crp_nbits = q_len * 8;
++ kop->crk_param[2].crp_p = r;
++ kop->crk_param[2].crp_nbits = r_len * 8;
++ kop->crk_param[3].crp_p = g_xy;
++ kop->crk_param[3].crp_nbits = g_len * 8;
++ kop->crk_param[4].crp_p = s;
++ kop->crk_param[4].crp_nbits = priv_key_len * 8;
++ kop->crk_param[5].crp_p = ab;
++ kop->crk_param[5].crp_nbits = ab_len * 8;
++ kop->crk_iparams = 6;
++ kop->cookie = cookie;
++
++ if (cryptodev_asym_async(kop, r_len, sig->r, r_len, sig->s))
++ goto err;
++
++ return ret;
++ err:
++ {
++ const ECDSA_METHOD *meth = ECDSA_OpenSSL();
++ BN_free(sig->r);
++ BN_free(sig->s);
++ if (kop)
++ free(kop);
++ sig_ret =
++ (meth->ecdsa_do_sign) (dgst, dgst_len, in_kinv, in_r, eckey);
++ sig->r = sig_ret->r;
++ sig->s = sig_ret->s;
++ cookie->pkc_callback(cookie, 0);
++ }
++ return ret;
++}
++
++static int cryptodev_ecdsa_verify_async(const unsigned char *dgst,
++ int dgst_len, const ECDSA_SIG *sig,
++ EC_KEY *eckey,
++ struct pkc_cookie_s *cookie)
++{
++ BIGNUM *m = NULL, *p = NULL, *a = NULL, *b = NULL;
++ BIGNUM *x = NULL, *y = NULL, *w_x = NULL, *w_y = NULL;
++ BN_CTX *ctx = NULL;
++ ECDSA_DATA *ecdsa = NULL;
++ unsigned char *q = NULL, *r = NULL, *ab = NULL, *g_xy = NULL, *w_xy =
++ NULL;
++ unsigned char *c = NULL, *d = NULL, *f = NULL, *tmp_dgst = NULL;
++ int i = 0, q_len = 0, pub_key_len = 0, r_len = 0, c_len = 0, g_len = 0;
++ int d_len = 0, ab_len = 0, ret = 1;
++ const EC_POINT *pub_key = NULL;
++ const BIGNUM *order = NULL;
++ const EC_GROUP *group = NULL;
++ ec_curve_t ec_crv = EC_PRIME;
++ struct crypt_kop *kop = malloc(sizeof(struct crypt_kop));
++
++ if (!kop)
++ goto err;
++
++ memset(kop, 0, sizeof(struct crypt_kop));
++ ecdsa = ecdsa_check(eckey);
++ if (!ecdsa) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_PASSED_NULL_PARAMETER);
++ goto err;
++ }
++
++ group = EC_KEY_get0_group(eckey);
++ pub_key = EC_KEY_get0_public_key(eckey);
++
++ if (!group || !pub_key) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_PASSED_NULL_PARAMETER);
++ goto err;
++ }
++
++ if ((ctx = BN_CTX_new()) == NULL || (m = BN_new()) == NULL ||
++ (a = BN_new()) == NULL || (b = BN_new()) == NULL ||
++ (p = BN_new()) == NULL || (x = BN_new()) == NULL ||
++ (y = BN_new()) == NULL || (w_x = BN_new()) == NULL ||
++ (w_y = BN_new()) == NULL) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ order = &group->order;
++ if (!order || BN_is_zero(order)) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_MISSING_PARAMETERS);
++ goto err;
++ }
++
++ i = BN_num_bits(order);
++ /*
++ * Need to truncate digest if it is too long: first truncate whole *
++ * bytes
++ */
++ if (8 * dgst_len > i)
++ dgst_len = (i + 7) / 8;
++
++ if (!BN_bin2bn(dgst, dgst_len, m)) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
++ goto err;
++ }
++
++ /* If still too long truncate remaining bits with a shift */
++ if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
++ goto err;
++ }
++ /* copy the truncated bits into plain buffer */
++ if (spcf_bn2bin(m, &tmp_dgst, &dgst_len)) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /* check if this is prime or binary EC request */
++ if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) ==
++ NID_X9_62_prime_field) {
++ ec_crv = EC_PRIME;
++
++ /* get the generator point pair */
++ if (!EC_POINT_get_affine_coordinates_GFp(group,
++ EC_GROUP_get0_generator
++ (group), x, y, ctx)) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
++ goto err;
++ }
++
++ /* get the public key pair for prime curve */
++ if (!EC_POINT_get_affine_coordinates_GFp(group,
++ pub_key, w_x, w_y, ctx)) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
++ goto err;
++ }
++
++ /* get the ECC curve parameters */
++ if (!EC_GROUP_get_curve_GFp(group, p, a, b, ctx)) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
++ goto err;
++ }
++ } else if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) ==
++ NID_X9_62_characteristic_two_field) {
++ ec_crv = EC_BINARY;
++ /* get the ECC curve parameters */
++ if (!EC_GROUP_get_curve_GF2m(group, p, a, b, ctx)) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
++ goto err;
++ }
++
++ /* get the generator point pair */
++ if (!EC_POINT_get_affine_coordinates_GF2m(group,
++ EC_GROUP_get0_generator
++ (group), x, y, ctx)) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
++ goto err;
++ }
++
++ /* get the public key pair for binary curve */
++ if (!EC_POINT_get_affine_coordinates_GF2m(group,
++ pub_key, w_x, w_y, ctx)) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
++ goto err;
++ }
++ } else {
++ printf("Unsupported Curve\n");
++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
++ goto err;
++ }
++
++ /* Get the order of the subgroup of private keys */
++ if (spcf_bn2bin((BIGNUM *)order, &r, &r_len)) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /* Get the irreducible polynomial that creates the field */
++ if (spcf_bn2bin(p, &q, &q_len)) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /* Get the public key into a flat buffer with appropriate padding */
++ pub_key_len = 2 * q_len;
++
++ w_xy = eng_copy_curve_points(w_x, w_y, pub_key_len, q_len);
++ if (!w_xy) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /* Generation of ECC curve parameters */
++ ab_len = 2 * q_len;
++
++ ab = eng_copy_curve_points(a, b, ab_len, q_len);
++ if (!ab) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ if (ec_crv == EC_BINARY) {
++ /* copy b' i.e c(b), instead of only b */
++ eng_ec_get_cparam(EC_GROUP_get_curve_name(group), ab + q_len, q_len);
++ kop->curve_type = ECC_BINARY;
++ }
++
++ /* Calculation of Generator point */
++ g_len = 2 * q_len;
++
++ g_xy = eng_copy_curve_points(x, y, g_len, q_len);
++ if (!g_xy) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /**
++ * Get the 1st part of signature into a flat buffer with
++ * appropriate padding
++ */
++ if (BN_num_bytes(sig->r) < r_len)
++ c_len = r_len;
++
++ if (spcf_bn2bin_ex(sig->r, &c, &c_len)) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /**
++ * Get the 2nd part of signature into a flat buffer with
++ * appropriate padding
++ */
++ if (BN_num_bytes(sig->s) < r_len)
++ d_len = r_len;
++
++ if (spcf_bn2bin_ex(sig->s, &d, &d_len)) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /* memory for message representative */
++ f = malloc(r_len);
++ if (!f) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /* Add padding, since SEC expects hash to of size r_len */
++ memset(f, 0, r_len - dgst_len);
++
++ /* Skip leading bytes if dgst_len < r_len */
++ memcpy(f + r_len - dgst_len, tmp_dgst, dgst_len);
++
++ dgst_len += r_len - dgst_len;
++
++ kop->crk_op = CRK_DSA_VERIFY;
++ /* inputs: dgst dsa->p dsa->q dsa->g dsa->priv_key */
++ kop->crk_param[0].crp_p = f;
++ kop->crk_param[0].crp_nbits = dgst_len * 8;
++ kop->crk_param[1].crp_p = q;
++ kop->crk_param[1].crp_nbits = q_len * 8;
++ kop->crk_param[2].crp_p = r;
++ kop->crk_param[2].crp_nbits = r_len * 8;
++ kop->crk_param[3].crp_p = g_xy;
++ kop->crk_param[3].crp_nbits = g_len * 8;
++ kop->crk_param[4].crp_p = w_xy;
++ kop->crk_param[4].crp_nbits = pub_key_len * 8;
++ kop->crk_param[5].crp_p = ab;
++ kop->crk_param[5].crp_nbits = ab_len * 8;
++ kop->crk_param[6].crp_p = c;
++ kop->crk_param[6].crp_nbits = d_len * 8;
++ kop->crk_param[7].crp_p = d;
++ kop->crk_param[7].crp_nbits = d_len * 8;
++ kop->crk_iparams = 8;
++ kop->cookie = cookie;
++
++ if (cryptodev_asym_async(kop, 0, NULL, 0, NULL))
++ goto err;
++
++ return ret;
++ err:
++ {
++ const ECDSA_METHOD *meth = ECDSA_OpenSSL();
++
++ if (kop)
++ free(kop);
++ ret = (meth->ecdsa_do_verify) (dgst, dgst_len, sig, eckey);
++ cookie->pkc_callback(cookie, 0);
++ }
++
++ return ret;
++}
++
++/* Cryptodev DH Key Gen routine */
++static int cryptodev_dh_keygen_async(DH *dh, struct pkc_cookie_s *cookie)
++{
++ struct crypt_kop *kop = malloc(sizeof(struct crypt_kop));
++ int ret = 1, g_len;
++ unsigned char *g = NULL;
++
++ if (!kop)
++ goto sw_try;
++
++ if (dh->priv_key == NULL) {
++ if ((dh->priv_key = BN_new()) == NULL)
++ goto sw_try;
++ }
++
++ if (dh->pub_key == NULL) {
++ if ((dh->pub_key = BN_new()) == NULL)
++ goto sw_try;
++ }
++
++ g_len = BN_num_bytes(dh->p);
++ /**
++ * Get generator into a plain buffer. If length is less than
++ * q_len then add leading padding bytes.
++ */
++ if (spcf_bn2bin_ex(dh->g, &g, &g_len)) {
++ DSAerr(DH_F_DH_GENERATE_KEY, ERR_R_MALLOC_FAILURE);
++ goto sw_try;
+ }
+
+- /* Add padding, since SEC expects hash to of size r_len */
+- memset(f, 0, r_len - dgst_len);
++ memset(kop, 0, sizeof(struct crypt_kop));
++ kop->crk_op = CRK_DH_GENERATE_KEY;
++ if (bn2crparam(dh->p, &kop->crk_param[0]))
++ goto sw_try;
++ if (bn2crparam(dh->q, &kop->crk_param[1]))
++ goto sw_try;
++ kop->crk_param[2].crp_p = g;
++ kop->crk_param[2].crp_nbits = g_len * 8;
++ kop->crk_iparams = 3;
++ kop->cookie = cookie;
+
+- /* Skip leading bytes if dgst_len < r_len */
+- memcpy(f + r_len - dgst_len, tmp_dgst, dgst_len);
+- dgst_len += r_len - dgst_len;
+- kop.crk_op = CRK_DSA_VERIFY;
+- /* inputs: dgst dsa->p dsa->q dsa->g dsa->priv_key */
+- kop.crk_param[0].crp_p = f;
+- kop.crk_param[0].crp_nbits = dgst_len * 8;
+- kop.crk_param[1].crp_p = q;
+- kop.crk_param[1].crp_nbits = q_len * 8;
+- kop.crk_param[2].crp_p = r;
+- kop.crk_param[2].crp_nbits = r_len * 8;
+- kop.crk_param[3].crp_p = g_xy;
+- kop.crk_param[3].crp_nbits = g_len * 8;
+- kop.crk_param[4].crp_p = w_xy;
+- kop.crk_param[4].crp_nbits = pub_key_len * 8;
+- kop.crk_param[5].crp_p = ab;
+- kop.crk_param[5].crp_nbits = ab_len * 8;
+- kop.crk_param[6].crp_p = c;
+- kop.crk_param[6].crp_nbits = d_len * 8;
+- kop.crk_param[7].crp_p = d;
+- kop.crk_param[7].crp_nbits = d_len * 8;
+- kop.crk_iparams = 8;
++ /* pub_key is or prime length while priv key is of length of order */
++ if (cryptodev_asym_async(kop, BN_num_bytes(dh->p), dh->pub_key,
++ BN_num_bytes(dh->q), dh->priv_key))
++ goto sw_try;
+
+- if (cryptodev_asym(&kop, 0, NULL, 0, NULL) == 0) {
+- /*
+- * OCF success value is 0, if not zero, change ret to fail
+- */
+- if (0 == kop.crk_status)
+- ret = 1;
+- } else {
+- const ECDSA_METHOD *meth = ECDSA_OpenSSL();
++ return ret;
++ sw_try:
++ {
++ const DH_METHOD *meth = DH_OpenSSL();
+
+- ret = (meth->ecdsa_do_verify) (dgst, dgst_len, sig, eckey);
++ if (kop)
++ free(kop);
++ ret = (meth->generate_key) (dh);
++ cookie->pkc_callback(cookie, 0);
+ }
+- kop.crk_param[0].crp_p = NULL;
+- zapparams(&kop);
+-
+- err:
+ return ret;
+ }
+
+@@ -2468,6 +3517,54 @@ cryptodev_dh_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
+ return (dhret);
+ }
+
++/* Return Length if successful and 0 on failure */
++static int
++cryptodev_dh_compute_key_async(unsigned char *key, const BIGNUM *pub_key,
++ DH *dh, struct pkc_cookie_s *cookie)
++{
++ struct crypt_kop *kop = malloc(sizeof(struct crypt_kop));
++ int ret = 1;
++ int fd, p_len;
++ unsigned char *padded_pub_key = NULL, *p = NULL;
++
++ fd = *(int *)cookie->eng_handle;
++
++ memset(kop, 0, sizeof(struct crypt_kop));
++ kop->crk_op = CRK_DH_COMPUTE_KEY;
++ /* inputs: dh->priv_key pub_key dh->p key */
++ spcf_bn2bin(dh->p, &p, &p_len);
++ spcf_bn2bin_ex(pub_key, &padded_pub_key, &p_len);
++
++ if (bn2crparam(dh->priv_key, &kop->crk_param[0]))
++ goto err;
++ kop->crk_param[1].crp_p = padded_pub_key;
++ kop->crk_param[1].crp_nbits = p_len * 8;
++ kop->crk_param[2].crp_p = p;
++ kop->crk_param[2].crp_nbits = p_len * 8;
++ kop->crk_iparams = 3;
++
++ kop->cookie = cookie;
++ kop->crk_param[3].crp_p = (void *)key;
++ kop->crk_param[3].crp_nbits = p_len * 8;
++ kop->crk_oparams = 1;
++
++ if (cryptodev_asym_async(kop, 0, NULL, 0, NULL))
++ goto err;
++
++ return p_len;
++ err:
++ {
++ const DH_METHOD *meth = DH_OpenSSL();
++
++ if (kop)
++ free(kop);
++ ret = (meth->compute_key) (key, pub_key, dh);
++ /* Call user cookie handler */
++ cookie->pkc_callback(cookie, 0);
++ }
++ return (ret);
++}
++
+ int cryptodev_ecdh_compute_key(void *out, size_t outlen,
+ const EC_POINT *pub_key, EC_KEY *ecdh,
+ void *(*KDF) (const void *in, size_t inlen,
+@@ -2650,6 +3747,197 @@ int cryptodev_ecdh_compute_key(void *out, size_t outlen,
+ return ret;
+ }
+
++int cryptodev_ecdh_compute_key_async(void *out, size_t outlen,
++ const EC_POINT *pub_key, EC_KEY *ecdh,
++ void *(*KDF) (const void *in,
++ size_t inlen, void *out,
++ size_t *outlen),
++ struct pkc_cookie_s *cookie)
++{
++ ec_curve_t ec_crv = EC_PRIME;
++ unsigned char *q = NULL, *w_xy = NULL, *ab = NULL, *s = NULL, *r = NULL;
++ BIGNUM *w_x = NULL, *w_y = NULL;
++ int q_len = 0, ab_len = 0, pub_key_len = 0, r_len = 0, priv_key_len = 0;
++ BIGNUM *p = NULL, *a = NULL, *b = NULL;
++ BN_CTX *ctx;
++ EC_POINT *tmp = NULL;
++ BIGNUM *x = NULL, *y = NULL;
++ const BIGNUM *priv_key;
++ const EC_GROUP *group = NULL;
++ int ret = 1;
++ size_t buflen, len;
++ struct crypt_kop *kop = malloc(sizeof(struct crypt_kop));
++
++ if (!(ctx = BN_CTX_new()) || !kop)
++ goto err;
++
++ memset(kop, 0, sizeof(struct crypt_kop));
++
++ BN_CTX_start(ctx);
++ x = BN_CTX_get(ctx);
++ y = BN_CTX_get(ctx);
++ p = BN_CTX_get(ctx);
++ a = BN_CTX_get(ctx);
++ b = BN_CTX_get(ctx);
++ w_x = BN_CTX_get(ctx);
++ w_y = BN_CTX_get(ctx);
++
++ if (!x || !y || !p || !a || !b || !w_x || !w_y) {
++ ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ priv_key = EC_KEY_get0_private_key(ecdh);
++ if (priv_key == NULL) {
++ ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ECDH_R_NO_PRIVATE_VALUE);
++ goto err;
++ }
++
++ group = EC_KEY_get0_group(ecdh);
++ if ((tmp = EC_POINT_new(group)) == NULL) {
++ ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) ==
++ NID_X9_62_prime_field) {
++ ec_crv = EC_PRIME;
++
++ if (!EC_POINT_get_affine_coordinates_GFp(group,
++ EC_GROUP_get0_generator
++ (group), x, y, ctx)) {
++ ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ECDH_R_POINT_ARITHMETIC_FAILURE);
++ goto err;
++ }
++
++ /* get the ECC curve parameters */
++ if (!EC_GROUP_get_curve_GFp(group, p, a, b, ctx)) {
++ ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ERR_R_BN_LIB);
++ goto err;
++ }
++
++ /* get the public key pair for prime curve */
++ if (!EC_POINT_get_affine_coordinates_GFp
++ (group, pub_key, w_x, w_y, ctx)) {
++ ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ERR_R_BN_LIB);
++ goto err;
++ }
++ } else {
++ ec_crv = EC_BINARY;
++
++ if (!EC_POINT_get_affine_coordinates_GF2m(group,
++ EC_GROUP_get0_generator
++ (group), x, y, ctx)) {
++ ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ECDH_R_POINT_ARITHMETIC_FAILURE);
++ goto err;
++ }
++
++ /* get the ECC curve parameters */
++ if (!EC_GROUP_get_curve_GF2m(group, p, a, b, ctx)) {
++ ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ERR_R_BN_LIB);
++ goto err;
++ }
++
++ /* get the public key pair for binary curve */
++ if (!EC_POINT_get_affine_coordinates_GF2m(group,
++ pub_key, w_x, w_y, ctx)) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_EC_LIB);
++ goto err;
++ }
++ }
++
++ /* irreducible polynomial that creates the field */
++ if (spcf_bn2bin((BIGNUM *)&group->order, &r, &r_len)) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /* Get the irreducible polynomial that creates the field */
++ if (spcf_bn2bin(p, &q, &q_len)) {
++ ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ERR_R_BN_LIB);
++ goto err;
++ }
++
++ /* Get the public key into a flat buffer with appropriate padding */
++ pub_key_len = 2 * q_len;
++ w_xy = eng_copy_curve_points(w_x, w_y, pub_key_len, q_len);
++ if (!w_xy) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /* Generation of ECC curve parameters */
++ ab_len = 2 * q_len;
++ ab = eng_copy_curve_points(a, b, ab_len, q_len);
++ if (!ab) {
++ ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ERR_R_BN_LIB);
++ goto err;
++ }
++
++ if (ec_crv == EC_BINARY) {
++ /* copy b' i.e c(b), instead of only b */
++ if (eng_ec_get_cparam
++ (EC_GROUP_get_curve_name(group), ab + q_len, q_len)) {
++ unsigned char *c_temp = NULL;
++ int c_temp_len = q_len;
++ if (eng_ec_compute_cparam(b, p, &c_temp, &c_temp_len))
++ memcpy(ab + q_len, c_temp, q_len);
++ else
++ goto err;
++ }
++ kop->curve_type = ECC_BINARY;
++ } else
++ kop->curve_type = ECC_PRIME;
++
++ priv_key_len = r_len;
++
++ /*
++ * If BN_num_bytes of priv_key returns less then r_len then
++ * add padding bytes before the key
++ */
++ if (spcf_bn2bin_ex((BIGNUM *)priv_key, &s, &priv_key_len)) {
++ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ buflen = (EC_GROUP_get_degree(group) + 7) / 8;
++ len = BN_num_bytes(x);
++ if (len > buflen || q_len < buflen) {
++ ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ERR_R_INTERNAL_ERROR);
++ goto err;
++ }
++
++ kop->crk_op = CRK_DH_COMPUTE_KEY;
++ kop->crk_param[0].crp_p = (void *)s;
++ kop->crk_param[0].crp_nbits = priv_key_len * 8;
++ kop->crk_param[1].crp_p = (void *)w_xy;
++ kop->crk_param[1].crp_nbits = pub_key_len * 8;
++ kop->crk_param[2].crp_p = (void *)q;
++ kop->crk_param[2].crp_nbits = q_len * 8;
++ kop->crk_param[3].crp_p = (void *)ab;
++ kop->crk_param[3].crp_nbits = ab_len * 8;
++ kop->crk_iparams = 4;
++ kop->crk_param[4].crp_p = (void *)out;
++ kop->crk_param[4].crp_nbits = q_len * 8;
++ kop->crk_oparams = 1;
++ kop->cookie = cookie;
++ if (cryptodev_asym_async(kop, 0, NULL, 0, NULL))
++ goto err;
++
++ return q_len;
++ err:
++ {
++ const ECDH_METHOD *meth = ECDH_OpenSSL();
++
++ if (kop)
++ free(kop);
++ ret = (meth->compute_key) (out, outlen, pub_key, ecdh, KDF);
++ /* Call user cookie handler */
++ cookie->pkc_callback(cookie, 0);
++ }
++ return ret;
++}
++
+ static DH_METHOD cryptodev_dh = {
+ "cryptodev DH method",
+ NULL, /* cryptodev_dh_generate_key */
+@@ -2657,6 +3945,8 @@ static DH_METHOD cryptodev_dh = {
+ NULL,
+ NULL,
+ NULL,
++ NULL,
++ NULL,
+ 0, /* flags */
+ NULL /* app_data */
+ };
+@@ -2665,6 +3955,7 @@ static ECDH_METHOD cryptodev_ecdh = {
+ "cryptodev ECDH method",
+ NULL, /* cryptodev_ecdh_compute_key */
+ NULL,
++ NULL,
+ 0, /* flags */
+ NULL /* app_data */
+ };
+@@ -2735,10 +4026,15 @@ void ENGINE_load_cryptodev(void)
+ cryptodev_rsa.rsa_priv_dec = rsa_meth->rsa_priv_dec;
+ if (cryptodev_asymfeat & CRF_MOD_EXP) {
+ cryptodev_rsa.bn_mod_exp = cryptodev_bn_mod_exp;
+- if (cryptodev_asymfeat & CRF_MOD_EXP_CRT)
++ cryptodev_rsa.bn_mod_exp_async = cryptodev_bn_mod_exp_async;
++ if (cryptodev_asymfeat & CRF_MOD_EXP_CRT) {
+ cryptodev_rsa.rsa_mod_exp = cryptodev_rsa_mod_exp;
+- else
++ cryptodev_rsa.rsa_mod_exp_async = cryptodev_rsa_mod_exp_async;
++ } else {
+ cryptodev_rsa.rsa_mod_exp = cryptodev_rsa_nocrt_mod_exp;
++ cryptodev_rsa.rsa_mod_exp_async =
++ cryptodev_rsa_nocrt_mod_exp_async;
++ }
+ }
+ }
+
+@@ -2746,12 +4042,18 @@ void ENGINE_load_cryptodev(void)
+ const DSA_METHOD *meth = DSA_OpenSSL();
+
+ memcpy(&cryptodev_dsa, meth, sizeof(DSA_METHOD));
+- if (cryptodev_asymfeat & CRF_DSA_SIGN)
++ if (cryptodev_asymfeat & CRF_DSA_SIGN) {
+ cryptodev_dsa.dsa_do_sign = cryptodev_dsa_do_sign;
+- if (cryptodev_asymfeat & CRF_DSA_VERIFY)
++ cryptodev_dsa.dsa_do_sign_async = cryptodev_dsa_do_sign_async;
++ }
++ if (cryptodev_asymfeat & CRF_DSA_VERIFY) {
+ cryptodev_dsa.dsa_do_verify = cryptodev_dsa_verify;
+- if (cryptodev_asymfeat & CRF_DSA_GENERATE_KEY)
++ cryptodev_dsa.dsa_do_verify_async = cryptodev_dsa_verify_async;
++ }
++ if (cryptodev_asymfeat & CRF_DSA_GENERATE_KEY) {
+ cryptodev_dsa.dsa_keygen = cryptodev_dsa_keygen;
++ cryptodev_dsa.dsa_keygen_async = cryptodev_dsa_keygen_async;
++ }
+ }
+
+ if (ENGINE_set_DH(engine, &cryptodev_dh)) {
+@@ -2759,9 +4061,12 @@ void ENGINE_load_cryptodev(void)
+ memcpy(&cryptodev_dh, dh_meth, sizeof(DH_METHOD));
+ if (cryptodev_asymfeat & CRF_DH_COMPUTE_KEY) {
+ cryptodev_dh.compute_key = cryptodev_dh_compute_key;
++ cryptodev_dh.compute_key_async = cryptodev_dh_compute_key_async;
+ }
+ if (cryptodev_asymfeat & CRF_DH_GENERATE_KEY) {
+ cryptodev_dh.generate_key = cryptodev_dh_keygen;
++ cryptodev_dh.generate_key_async = cryptodev_dh_keygen_async;
++
+ }
+ }
+
+@@ -2770,9 +4075,13 @@ void ENGINE_load_cryptodev(void)
+ memcpy(&cryptodev_ecdsa, meth, sizeof(ECDSA_METHOD));
+ if (cryptodev_asymfeat & CRF_DSA_SIGN) {
+ cryptodev_ecdsa.ecdsa_do_sign = cryptodev_ecdsa_do_sign;
++ cryptodev_ecdsa.ecdsa_do_sign_async =
++ cryptodev_ecdsa_do_sign_async;
+ }
+ if (cryptodev_asymfeat & CRF_DSA_VERIFY) {
+ cryptodev_ecdsa.ecdsa_do_verify = cryptodev_ecdsa_verify;
++ cryptodev_ecdsa.ecdsa_do_verify_async =
++ cryptodev_ecdsa_verify_async;
+ }
+ }
+
+@@ -2781,9 +4090,16 @@ void ENGINE_load_cryptodev(void)
+ memcpy(&cryptodev_ecdh, ecdh_meth, sizeof(ECDH_METHOD));
+ if (cryptodev_asymfeat & CRF_DH_COMPUTE_KEY) {
+ cryptodev_ecdh.compute_key = cryptodev_ecdh_compute_key;
++ cryptodev_ecdh.compute_key_async =
++ cryptodev_ecdh_compute_key_async;
+ }
+ }
+
++ ENGINE_set_check_pkc_availability(engine, cryptodev_check_availability);
++ ENGINE_set_close_instance(engine, cryptodev_close_instance);
++ ENGINE_set_init_instance(engine, cryptodev_init_instance);
++ ENGINE_set_async_map(engine, ENGINE_ALLPKC_ASYNC);
++
+ ENGINE_add(engine);
+ ENGINE_free(engine);
+ ERR_clear_error();
+diff --git a/crypto/engine/eng_int.h b/crypto/engine/eng_int.h
+index 46f163b..b698a0c 100644
+--- a/crypto/engine/eng_int.h
++++ b/crypto/engine/eng_int.h
+@@ -198,6 +198,29 @@ struct engine_st {
+ ENGINE_LOAD_KEY_PTR load_privkey;
+ ENGINE_LOAD_KEY_PTR load_pubkey;
+ ENGINE_SSL_CLIENT_CERT_PTR load_ssl_client_cert;
++ /*
++ * Instantiate Engine handle to be passed in check_pkc_availability
++ * Ensure that Engine is instantiated before any pkc asynchronous call.
++ */
++ void *(*engine_init_instance)(void);
++ /*
++ * Instantiated Engine handle will be closed with this call.
++ * Ensure that no pkc asynchronous call is made after this call
++ */
++ void (*engine_close_instance)(void *handle);
++ /*
++ * Check availability will extract the data from kernel.
++ * eng_handle: This is the Engine handle corresponds to which
++ * the cookies needs to be polled.
++ * return 0 if cookie available else 1
++ */
++ int (*check_pkc_availability)(void *eng_handle);
++ /*
++ * The following map is used to check if the engine supports asynchronous implementation
++ * ENGINE_ASYNC_FLAG* for available bitmap. Any application checking for asynchronous
++ * implementation need to check this features using "int ENGINE_get_async_map(engine *)";
++ */
++ int async_map;
+ const ENGINE_CMD_DEFN *cmd_defns;
+ int flags;
+ /* reference count on the structure itself */
+diff --git a/crypto/engine/eng_lib.c b/crypto/engine/eng_lib.c
+index dc2abd2..0c57e12 100644
+--- a/crypto/engine/eng_lib.c
++++ b/crypto/engine/eng_lib.c
+@@ -100,7 +100,11 @@ void engine_set_all_null(ENGINE *e)
+ e->ctrl = NULL;
+ e->load_privkey = NULL;
+ e->load_pubkey = NULL;
++ e->check_pkc_availability = NULL;
++ e->engine_init_instance = NULL;
++ e->engine_close_instance = NULL;
+ e->cmd_defns = NULL;
++ e->async_map = 0;
+ e->flags = 0;
+ }
+
+@@ -246,6 +250,48 @@ int ENGINE_set_id(ENGINE *e, const char *id)
+ }
+ e->id = id;
+ return 1;
++ }
++
++void ENGINE_set_init_instance(ENGINE *e, void *(*engine_init_instance)(void))
++ {
++ e->engine_init_instance = engine_init_instance;
++ }
++
++void ENGINE_set_close_instance(ENGINE *e,
++ void (*engine_close_instance)(void *))
++ {
++ e->engine_close_instance = engine_close_instance;
++ }
++
++void ENGINE_set_async_map(ENGINE *e, int async_map)
++ {
++ e->async_map = async_map;
++ }
++
++void *ENGINE_init_instance(ENGINE *e)
++ {
++ return e->engine_init_instance();
++ }
++
++void ENGINE_close_instance(ENGINE *e, void *eng_handle)
++ {
++ e->engine_close_instance(eng_handle);
++ }
++
++int ENGINE_get_async_map(ENGINE *e)
++ {
++ return e->async_map;
++ }
++
++void ENGINE_set_check_pkc_availability(ENGINE *e,
++ int (*check_pkc_availability)(void *eng_handle))
++ {
++ e->check_pkc_availability = check_pkc_availability;
++ }
++
++int ENGINE_check_pkc_availability(ENGINE *e, void *eng_handle)
++ {
++ return e->check_pkc_availability(eng_handle);
+ }
+
+ int ENGINE_set_name(ENGINE *e, const char *name)
+diff --git a/crypto/engine/engine.h b/crypto/engine/engine.h
+index 020d912..4527aa1 100644
+--- a/crypto/engine/engine.h
++++ b/crypto/engine/engine.h
+@@ -551,6 +551,30 @@ ENGINE *ENGINE_new(void);
+ int ENGINE_free(ENGINE *e);
+ int ENGINE_up_ref(ENGINE *e);
+ int ENGINE_set_id(ENGINE *e, const char *id);
++void ENGINE_set_init_instance(ENGINE *e, void *(*engine_init_instance)(void));
++void ENGINE_set_close_instance(ENGINE *e,
++ void (*engine_free_instance)(void *));
++/*
++ * Following FLAGS are bitmap store in async_map to set asynchronous interface capability
++ *of the engine
++ */
++#define ENGINE_RSA_ASYNC 0x0001
++#define ENGINE_DSA_ASYNC 0x0002
++#define ENGINE_DH_ASYNC 0x0004
++#define ENGINE_ECDSA_ASYNC 0x0008
++#define ENGINE_ECDH_ASYNC 0x0010
++#define ENGINE_ALLPKC_ASYNC 0x001F
++/* Engine implementation will set the bitmap based on above flags using following API */
++void ENGINE_set_async_map(ENGINE *e, int async_map);
++ /* Application need to check the bitmap based on above flags using following API
++ * to confirm asynchronous methods supported
++ */
++int ENGINE_get_async_map(ENGINE *e);
++void *ENGINE_init_instance(ENGINE *e);
++void ENGINE_close_instance(ENGINE *e, void *eng_handle);
++void ENGINE_set_check_pkc_availability(ENGINE *e,
++ int (*check_pkc_availability)(void *eng_handle));
++int ENGINE_check_pkc_availability(ENGINE *e, void *eng_handle);
+ int ENGINE_set_name(ENGINE *e, const char *name);
+ int ENGINE_set_RSA(ENGINE *e, const RSA_METHOD *rsa_meth);
+ int ENGINE_set_DSA(ENGINE *e, const DSA_METHOD *dsa_meth);
+diff --git a/crypto/rsa/rsa.h b/crypto/rsa/rsa.h
+index d2ee374..7c539fc 100644
+--- a/crypto/rsa/rsa.h
++++ b/crypto/rsa/rsa.h
+@@ -97,6 +97,29 @@ struct rsa_meth_st {
+ /* Can be null */
+ int (*bn_mod_exp) (BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
++ /*
++ * Cookie in the following _async variant must be allocated before
++ * submission and can be freed once its corresponding callback
++ * handler is called
++ */
++ int (*rsa_pub_enc_asyn)(int flen,const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding,
++ struct pkc_cookie_s *cookie);
++ int (*rsa_pub_dec_async)(int flen,const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding,
++ struct pkc_cookie_s *cookie);
++ int (*rsa_priv_enc_async)(int flen,const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding,
++ struct pkc_cookie_s *cookie);
++ int (*rsa_priv_dec_async)(int flen,const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding,
++ struct pkc_cookie_s *cookie);
++ int (*rsa_mod_exp_async)(BIGNUM *r0, const BIGNUM *I, RSA *rsa,
++ BN_CTX *ctx, struct pkc_cookie_s *cookie);
++ int (*bn_mod_exp_async)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
++ const BIGNUM *m, BN_CTX *ctx,
++ BN_MONT_CTX *m_ctx, struct pkc_cookie_s *cookie);
++
+ /* called at new */
+ int (*init) (RSA *rsa);
+ /* called at free */
+--
+2.7.0
+