From a933e6341fd8989bdd82f8a5446b6f04aa00eef9 Mon Sep 17 00:00:00 2001 From: Yashpal Dutta Date: Tue, 11 Mar 2014 07:14:30 +0545 Subject: [PATCH 10/26] Asynchronous interface added for PKC cryptodev interface Upstream-status: Pending Signed-off-by: Yashpal Dutta --- crypto/crypto.h | 16 + crypto/dh/dh.h | 4 +- crypto/dsa/dsa.h | 5 + crypto/ecdh/ech_locl.h | 3 + crypto/ecdsa/ecs_locl.h | 5 + crypto/engine/eng_cryptodev.c | 1578 +++++++++++++++++++++++++++++++++++++---- crypto/engine/eng_int.h | 24 +- crypto/engine/eng_lib.c | 46 ++ crypto/engine/engine.h | 24 + crypto/rsa/rsa.h | 23 + 10 files changed, 1582 insertions(+), 146 deletions(-) diff --git a/crypto/crypto.h b/crypto/crypto.h index f92fc51..ce12731 100644 --- a/crypto/crypto.h +++ b/crypto/crypto.h @@ -605,6 +605,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 ea59e61..20ffad2 100644 --- a/crypto/dh/dh.h +++ b/crypto/dh/dh.h @@ -118,7 +118,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); /* Can be null */ - + 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 a6f6d0b..b04a029 100644 --- a/crypto/dsa/dsa.h +++ b/crypto/dsa/dsa.h @@ -140,6 +140,10 @@ struct dsa_method int (*bn_mod_exp)(DSA *dsa, BIGNUM *r, BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); /* Can be null */ + 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; @@ -151,6 +155,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 f6cad6a..adce6b3 100644 --- a/crypto/ecdh/ech_locl.h +++ b/crypto/ecdh/ech_locl.h @@ -67,6 +67,9 @@ struct ecdh_method const char *name; int (*compute_key)(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)); + 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 cb3be13..eb0ebe0 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 7ee314b..9f2416e 100644 --- a/crypto/engine/eng_cryptodev.c +++ b/crypto/engine/eng_cryptodev.c @@ -1281,6 +1281,56 @@ 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) { @@ -1337,6 +1387,44 @@ void *cryptodev_init_instance(void) return fd; } +#include + +/* 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) @@ -1382,6 +1470,63 @@ err: } 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) { int r; @@ -1446,6 +1591,62 @@ err: 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 */ @@ -1454,6 +1655,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 */ @@ -1751,126 +1958,424 @@ sw_try: return ret; } +/* 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; + if (!kop) + goto sw_try; -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 */ -}; + if (dsa->priv_key == NULL) { + if ((dsa->priv_key=BN_new()) == NULL) + goto sw_try; + } -static ECDSA_METHOD cryptodev_ecdsa = { - "cryptodev ECDSA method", - NULL, - NULL, /* ecdsa_sign_setup */ - NULL, - NULL, - 0, /* flags */ - NULL /* app_data */ -}; + if (dsa->pub_key == NULL) { + if ((dsa->pub_key=BN_new()) == NULL) + goto sw_try; + } -typedef enum ec_curve_s -{ - EC_PRIME, - EC_BINARY -} ec_curve_t; + 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; + } -/* 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(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; - memset(&kop, 0, sizeof(kop)); - ecdsa = ecdsa_check(eckey); - if (!ecdsa) { - 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; +} - group = EC_KEY_get0_group(eckey); - priv_key = EC_KEY_get0_private_key(eckey); +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 (!group || !priv_key) { - ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_PASSED_NULL_PARAMETER); - return NULL; + if (((sig->r = BN_new()) == NULL) || !kop) { + DSAerr(DSA_F_DSA_DO_SIGN, ERR_R_MALLOC_FAILURE); + 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); + if ((sig->s = BN_new()) == NULL) { + BN_free(sig->r); + 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 (spcf_bn2bin(dsa->p, &q, &q_len)) { + DSAerr(DSA_F_DSA_DO_SIGN, DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); 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; + /* 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; + } - if (!BN_bin2bn(dgst, dgst_len, m)) { - ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); + /* sanity test */ + if (dlen > r_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); + 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; } - /* 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__); + 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; } - ret = ECDSA_SIG_new(); - if (!ret) { - ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_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; } - /* 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; - } + /* Add padding, since SEC expects hash to of size r_len */ + if (dlen < r_len) + memset(f, 0, r_len - dlen); - /* 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); + /* 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)) == NID_X9_62_characteristic_two_field) { @@ -2195,63 +2700,581 @@ static int cryptodev_ecdsa_verify(const unsigned char *dgst, int dgst_len, } /** - * Get the 2nd part of signature into a flat buffer with - * appropriate padding + * 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; + + 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 (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; + 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; } @@ -2360,6 +3383,54 @@ sw_try: 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, void *out, size_t *outlen)) @@ -2537,6 +3608,190 @@ err: 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", @@ -2545,6 +3800,8 @@ static DH_METHOD cryptodev_dh = { NULL, NULL, NULL, + NULL, + NULL, 0, /* flags */ NULL /* app_data */ }; @@ -2553,6 +3810,7 @@ static ECDH_METHOD cryptodev_ecdh = { "cryptodev ECDH method", NULL, /* cryptodev_ecdh_compute_key */ NULL, + NULL, 0, /* flags */ NULL /* app_data */ }; @@ -2625,12 +3883,19 @@ 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; + } } } @@ -2638,12 +3903,21 @@ 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)){ @@ -2652,10 +3926,15 @@ ENGINE_load_cryptodev(void) 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; + } } @@ -2664,10 +3943,14 @@ 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; } } @@ -2676,9 +3959,16 @@ 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 451ef8f..8fc3077 100644 --- a/crypto/engine/eng_int.h +++ b/crypto/engine/eng_int.h @@ -181,7 +181,29 @@ struct engine_st 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 18a6664..6fa621c 100644 --- a/crypto/engine/eng_lib.c +++ b/crypto/engine/eng_lib.c @@ -98,7 +98,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; } @@ -233,6 +237,48 @@ int ENGINE_set_id(ENGINE *e, const char *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) { if(name == NULL) diff --git a/crypto/engine/engine.h b/crypto/engine/engine.h index 237a6c9..ccff86a 100644 --- a/crypto/engine/engine.h +++ b/crypto/engine/engine.h @@ -473,6 +473,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 5f269e5..6ef1b15 100644 --- a/crypto/rsa/rsa.h +++ b/crypto/rsa/rsa.h @@ -101,6 +101,29 @@ struct rsa_meth_st int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); /* Can be null */ + /* + * 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); + int (*init)(RSA *rsa); /* called at new */ int (*finish)(RSA *rsa); /* called at free */ int flags; /* RSA_METHOD_FLAG_* things */ -- 2.3.5