cryptodev: Fix issue with signature generation
[openssl.git] / crypto / engine / eng_cryptodev.c
index 34193f38ad2e7711236c9986fe01aa1e0fdc7a79..188e61c187c221d71296449365c3beedc74022b1 100644 (file)
@@ -1,7 +1,17 @@
+/*
+ * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
 /*
  * Copyright (c) 2002 Bob Beck <beck@openbsd.org>
  * Copyright (c) 2002 Theo de Raadt
  * Copyright (c) 2002 Markus Friedl
+ * Copyright (c) 2012 Nikos Mavrogiannopoulos
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -33,9 +43,9 @@
 #include <openssl/crypto.h>
 
 #if (defined(__unix__) || defined(unix)) && !defined(USG) && \
-        (defined(OpenBSD) || defined(__FreeBSD__))
+        (defined(OpenBSD) || defined(__FreeBSD__) || defined(__DragonFly__))
 # include <sys/param.h>
-# if (OpenBSD >= 200112) || ((__FreeBSD_version >= 470101 && __FreeBSD_version < 500000) || __FreeBSD_version >= 500041)
+# if (OpenBSD >= 200112) || ((__FreeBSD_version >= 470101 && __FreeBSD_version < 500000) || __FreeBSD_version >= 500041) || defined(__DragonFly__)
 #  define HAVE_CRYPTODEV
 # endif
 # if (OpenBSD >= 200110)
@@ -63,7 +73,7 @@
 
 #ifndef HAVE_CRYPTODEV
 
-void engine_load_cryptodev_internal(void)
+void engine_load_cryptodev_int(void)
 {
     /* This is a NOP on platforms without /dev/crypto */
     return;
@@ -75,7 +85,6 @@ struct dev_crypto_state {
     struct session_op d_sess;
     int d_fd;
 # ifdef USE_CRYPTODEV_DIGESTS
-    char dummy_mac_key[HASH_MAX_LEN];
     unsigned char digest_res[HASH_MAX_LEN];
     char *mac_data;
     int mac_len;
@@ -84,6 +93,14 @@ struct dev_crypto_state {
 
 static u_int32_t cryptodev_asymfeat = 0;
 
+static RSA_METHOD *cryptodev_rsa;
+# ifndef OPENSSL_NO_DSA
+static DSA_METHOD *cryptodev_dsa = NULL;
+# endif
+# ifndef OPENSSL_NO_DH
+static DH_METHOD *cryptodev_dh;
+# endif
+
 static int get_asym_dev_crypto(void);
 static int open_dev_crypto(void);
 static int get_dev_crypto(void);
@@ -115,27 +132,29 @@ static int cryptodev_rsa_nocrt_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa,
                                        BN_CTX *ctx);
 static int cryptodev_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa,
                                  BN_CTX *ctx);
-static int cryptodev_dsa_bn_mod_exp(DSA *dsa, BIGNUM *r, BIGNUM *a,
+# ifndef OPENSSL_NO_DSA
+static int cryptodev_dsa_bn_mod_exp(DSA *dsa, BIGNUM *r, const BIGNUM *a,
                                     const BIGNUM *p, const BIGNUM *m,
                                     BN_CTX *ctx, BN_MONT_CTX *m_ctx);
-static int cryptodev_dsa_dsa_mod_exp(DSA *dsa, BIGNUM *t1, BIGNUM *g,
-                                     BIGNUM *u1, BIGNUM *pub_key, BIGNUM *u2,
-                                     BIGNUM *p, BN_CTX *ctx,
-                                     BN_MONT_CTX *mont);
+static int cryptodev_dsa_dsa_mod_exp(DSA *dsa, BIGNUM *t1, const BIGNUM *g,
+                                     const BIGNUM *u1, const BIGNUM *pub_key,
+                                     const BIGNUM *u2, const BIGNUM *p,
+                                     BN_CTX *ctx, BN_MONT_CTX *mont);
 static DSA_SIG *cryptodev_dsa_do_sign(const unsigned char *dgst, int dlen,
                                       DSA *dsa);
 static int cryptodev_dsa_verify(const unsigned char *dgst, int dgst_len,
                                 DSA_SIG *sig, DSA *dsa);
-#ifndef OPENSSL_NO_DH
+# endif
+# ifndef OPENSSL_NO_DH
 static int cryptodev_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a,
                                 const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
                                 BN_MONT_CTX *m_ctx);
 static int cryptodev_dh_compute_key(unsigned char *key, const BIGNUM *pub_key,
                                     DH *dh);
-#endif
+# endif
 static int cryptodev_ctrl(ENGINE *e, int cmd, long i, void *p,
                           void (*f) (void));
-void engine_load_cryptodev_internal(void);
+void engine_load_cryptodev_int(void);
 
 static const ENGINE_CMD_DEFN cryptodev_defns[] = {
     {0, NULL, NULL, 0}
@@ -194,8 +213,10 @@ static struct {
 static struct {
     int id;
     int nid;
-    int keylen;
+    int  digestlen;
 } digests[] = {
+#  if 0
+    /* HMAC is not supported */
     {
         CRYPTO_MD5_HMAC, NID_hmacWithMD5, 16
     },
@@ -203,21 +224,30 @@ static struct {
         CRYPTO_SHA1_HMAC, NID_hmacWithSHA1, 20
     },
     {
-        CRYPTO_RIPEMD160_HMAC, NID_ripemd160, 16
-        /* ? */
+        CRYPTO_SHA2_256_HMAC, NID_hmacWithSHA256, 32
     },
     {
-        CRYPTO_MD5_KPDK, NID_undef, 0
+        CRYPTO_SHA2_384_HMAC, NID_hmacWithSHA384, 48
     },
     {
-        CRYPTO_SHA1_KPDK, NID_undef, 0
+        CRYPTO_SHA2_512_HMAC, NID_hmacWithSHA512, 64
     },
+#  endif
     {
         CRYPTO_MD5, NID_md5, 16
     },
     {
         CRYPTO_SHA1, NID_sha1, 20
     },
+    {
+        CRYPTO_SHA2_256, NID_sha256, 32
+    },
+    {
+        CRYPTO_SHA2_384, NID_sha384, 48
+    },
+    {
+        CRYPTO_SHA2_512, NID_sha512, 64
+    },
     {
         0, NID_undef, 0
     },
@@ -293,13 +323,14 @@ static int get_cryptodev_ciphers(const int **cnids)
     static int nids[CRYPTO_ALGORITHM_MAX];
     struct session_op sess;
     int fd, i, count = 0;
+    unsigned char fake_key[CRYPTO_CIPHER_MAX_KEY_LEN];
 
     if ((fd = get_dev_crypto()) < 0) {
         *cnids = NULL;
         return (0);
     }
     memset(&sess, 0, sizeof(sess));
-    sess.key = (caddr_t) "123456789abcdefghijklmno";
+    sess.key = (void *)fake_key;
 
     for (i = 0; ciphers[i].id && count < CRYPTO_ALGORITHM_MAX; i++) {
         if (ciphers[i].nid == NID_undef)
@@ -330,6 +361,7 @@ static int get_cryptodev_ciphers(const int **cnids)
 static int get_cryptodev_digests(const int **cnids)
 {
     static int nids[CRYPTO_ALGORITHM_MAX];
+    unsigned char fake_key[CRYPTO_CIPHER_MAX_KEY_LEN];
     struct session_op sess;
     int fd, i, count = 0;
 
@@ -338,12 +370,12 @@ static int get_cryptodev_digests(const int **cnids)
         return (0);
     }
     memset(&sess, 0, sizeof(sess));
-    sess.mackey = (caddr_t) "123456789abcdefghijklmno";
+    sess.mackey = (void *)fake_key;
     for (i = 0; digests[i].id && count < CRYPTO_ALGORITHM_MAX; i++) {
         if (digests[i].nid == NID_undef)
             continue;
         sess.mac = digests[i].id;
-        sess.mackeylen = digests[i].keylen;
+        sess.mackeylen = digests[i].digestlen;
         sess.cipher = 0;
         if (ioctl(fd, CIOCGSESSION, &sess) != -1 &&
             ioctl(fd, CIOCFSESSION, &sess.ses) != -1)
@@ -429,14 +461,14 @@ cryptodev_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
     cryp.ses = sess->ses;
     cryp.flags = 0;
     cryp.len = inl;
-    cryp.src = (caddr_t) in;
-    cryp.dst = (caddr_t) out;
+    cryp.src = (void *) in;
+    cryp.dst = (void *) out;
     cryp.mac = 0;
 
     cryp.op = EVP_CIPHER_CTX_encrypting(ctx) ? COP_ENCRYPT : COP_DECRYPT;
 
     if (EVP_CIPHER_CTX_iv_length(ctx) > 0) {
-        cryp.iv = *(caddr_t*) EVP_CIPHER_CTX_iv(ctx);
+        cryp.iv = (void *) EVP_CIPHER_CTX_iv(ctx);
         if (!EVP_CIPHER_CTX_encrypting(ctx)) {
             iiv = in + inl - EVP_CIPHER_CTX_iv_length(ctx);
             memcpy(save_iv, iiv, EVP_CIPHER_CTX_iv_length(ctx));
@@ -489,7 +521,7 @@ cryptodev_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
     if ((state->d_fd = get_dev_crypto()) < 0)
         return (0);
 
-    sess->key = (caddr_t) key;
+    sess->key = (void *) key;
     sess->keylen = EVP_CIPHER_CTX_key_length(ctx);
     sess->cipher = cipher;
 
@@ -837,10 +869,10 @@ cryptodev_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
         *cipher = cryptodev_aes_ctr();
         break;
     case NID_aes_192_ctr:
-        *cipher = cryptodev_aes_ctr_192();
+        *cipher = cryptodev_aes_192_ctr();
         break;
     case NID_aes_256_ctr:
-        *cipher = cryptodev_aes_ctr_256();
+        *cipher = cryptodev_aes_256_ctr();
         break;
 # endif
     default:
@@ -863,16 +895,6 @@ static int digest_nid_to_cryptodev(int nid)
     return (0);
 }
 
-static int digest_key_length(int nid)
-{
-    int i;
-
-    for (i = 0; digests[i].id; i++)
-        if (digests[i].nid == nid)
-            return digests[i].keylen;
-    return (0);
-}
-
 static int cryptodev_digest_init(EVP_MD_CTX *ctx)
 {
     struct dev_crypto_state *state = EVP_MD_CTX_md_data(ctx);
@@ -891,8 +913,8 @@ static int cryptodev_digest_init(EVP_MD_CTX *ctx)
         return (0);
     }
 
-    sess->mackey = state->dummy_mac_key;
-    sess->mackeylen = digest_key_length(EVP_MD_CTX_type(ctx));
+    sess->mackey = NULL;
+    sess->mackeylen = 0;
     sess->mac = digest;
 
     if (ioctl(state->d_fd, CIOCGSESSION, sess) < 0) {
@@ -944,9 +966,9 @@ static int cryptodev_digest_update(EVP_MD_CTX *ctx, const void *data,
     cryp.ses = sess->ses;
     cryp.flags = 0;
     cryp.len = count;
-    cryp.src = (caddr_t) data;
+    cryp.src = (void *) data;
     cryp.dst = NULL;
-    cryp.mac = (caddr_t) state->digest_res;
+    cryp.mac = (void *) state->digest_res;
     if (ioctl(state->d_fd, CIOCCRYPT, &cryp) < 0) {
         printf("cryptodev_digest_update: digest failed\n");
         return (0);
@@ -975,7 +997,7 @@ static int cryptodev_digest_final(EVP_MD_CTX *ctx, unsigned char *md)
         cryp.len = state->mac_len;
         cryp.src = state->mac_data;
         cryp.dst = NULL;
-        cryp.mac = (caddr_t) md;
+        cryp.mac = (void *) md;
         if (ioctl(state->d_fd, CIOCCRYPT, &cryp) < 0) {
             printf("cryptodev_digest_final: digest failed\n");
             return (0);
@@ -1035,8 +1057,8 @@ static int cryptodev_digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
 
     digest = digest_nid_to_cryptodev(EVP_MD_CTX_type(to));
 
-    sess->mackey = dstate->dummy_mac_key;
-    sess->mackeylen = digest_key_length(EVP_MD_CTX_type(to));
+    sess->mackey = NULL;
+    sess->mackeylen = 0;
     sess->mac = digest;
 
     dstate->d_fd = get_dev_crypto();
@@ -1088,6 +1110,106 @@ static const EVP_MD *cryptodev_sha1(void)
     return sha1_md;
 }
 
+static EVP_MD *sha256_md = NULL;
+static const EVP_MD *cryptodev_sha256(void)
+{
+    if (sha256_md == NULL) {
+        EVP_MD *md;
+
+        if ((md = EVP_MD_meth_new(NID_sha256, NID_undef)) == NULL
+            || !EVP_MD_meth_set_result_size(md, SHA_DIGEST_LENGTH)
+            || !EVP_MD_meth_set_flags(md, EVP_MD_FLAG_ONESHOT)
+            || !EVP_MD_meth_set_input_blocksize(md, SHA_CBLOCK)
+            || !EVP_MD_meth_set_app_datasize(md,
+                                             sizeof(struct dev_crypto_state))
+            || !EVP_MD_meth_set_init(md, cryptodev_digest_init)
+            || !EVP_MD_meth_set_update(md, cryptodev_digest_update)
+            || !EVP_MD_meth_set_final(md, cryptodev_digest_final)
+            || !EVP_MD_meth_set_copy(md, cryptodev_digest_copy)
+            || !EVP_MD_meth_set_cleanup(md, cryptodev_digest_cleanup)) {
+            EVP_MD_meth_free(md);
+            md = NULL;
+        }
+        sha256_md = md;
+    }
+    return sha256_md;
+}
+
+static EVP_MD *sha224_md = NULL;
+static const EVP_MD *cryptodev_sha224(void)
+{
+    if (sha224_md == NULL) {
+        EVP_MD *md;
+
+        if ((md = EVP_MD_meth_new(NID_sha224, NID_undef)) == NULL
+            || !EVP_MD_meth_set_result_size(md, SHA_DIGEST_LENGTH)
+            || !EVP_MD_meth_set_flags(md, EVP_MD_FLAG_ONESHOT)
+            || !EVP_MD_meth_set_input_blocksize(md, SHA_CBLOCK)
+            || !EVP_MD_meth_set_app_datasize(md,
+                                             sizeof(struct dev_crypto_state))
+            || !EVP_MD_meth_set_init(md, cryptodev_digest_init)
+            || !EVP_MD_meth_set_update(md, cryptodev_digest_update)
+            || !EVP_MD_meth_set_final(md, cryptodev_digest_final)
+            || !EVP_MD_meth_set_copy(md, cryptodev_digest_copy)
+            || !EVP_MD_meth_set_cleanup(md, cryptodev_digest_cleanup)) {
+            EVP_MD_meth_free(md);
+            md = NULL;
+        }
+        sha224_md = md;
+    }
+    return sha224_md;
+}
+
+static EVP_MD *sha384_md = NULL;
+static const EVP_MD *cryptodev_sha384(void)
+{
+    if (sha384_md == NULL) {
+        EVP_MD *md;
+
+        if ((md = EVP_MD_meth_new(NID_sha384, NID_undef)) == NULL
+            || !EVP_MD_meth_set_result_size(md, SHA_DIGEST_LENGTH)
+            || !EVP_MD_meth_set_flags(md, EVP_MD_FLAG_ONESHOT)
+            || !EVP_MD_meth_set_input_blocksize(md, SHA_CBLOCK)
+            || !EVP_MD_meth_set_app_datasize(md,
+                                             sizeof(struct dev_crypto_state))
+            || !EVP_MD_meth_set_init(md, cryptodev_digest_init)
+            || !EVP_MD_meth_set_update(md, cryptodev_digest_update)
+            || !EVP_MD_meth_set_final(md, cryptodev_digest_final)
+            || !EVP_MD_meth_set_copy(md, cryptodev_digest_copy)
+            || !EVP_MD_meth_set_cleanup(md, cryptodev_digest_cleanup)) {
+            EVP_MD_meth_free(md);
+            md = NULL;
+        }
+        sha384_md = md;
+    }
+    return sha384_md;
+}
+
+static EVP_MD *sha512_md = NULL;
+static const EVP_MD *cryptodev_sha512(void)
+{
+    if (sha512_md == NULL) {
+        EVP_MD *md;
+
+        if ((md = EVP_MD_meth_new(NID_sha512, NID_undef)) == NULL
+            || !EVP_MD_meth_set_result_size(md, SHA_DIGEST_LENGTH)
+            || !EVP_MD_meth_set_flags(md, EVP_MD_FLAG_ONESHOT)
+            || !EVP_MD_meth_set_input_blocksize(md, SHA_CBLOCK)
+            || !EVP_MD_meth_set_app_datasize(md,
+                                             sizeof(struct dev_crypto_state))
+            || !EVP_MD_meth_set_init(md, cryptodev_digest_init)
+            || !EVP_MD_meth_set_update(md, cryptodev_digest_update)
+            || !EVP_MD_meth_set_final(md, cryptodev_digest_final)
+            || !EVP_MD_meth_set_copy(md, cryptodev_digest_copy)
+            || !EVP_MD_meth_set_cleanup(md, cryptodev_digest_cleanup)) {
+            EVP_MD_meth_free(md);
+            md = NULL;
+        }
+        sha512_md = md;
+    }
+    return sha512_md;
+}
+
 static EVP_MD *md5_md = NULL;
 static const EVP_MD *cryptodev_md5(void)
 {
@@ -1130,6 +1252,18 @@ cryptodev_engine_digests(ENGINE *e, const EVP_MD **digest,
     case NID_sha1:
         *digest = cryptodev_sha1();
         break;
+    case NID_sha256:
+        *digest = cryptodev_sha256();
+        break;
+    case NID_sha224:
+        *digest = cryptodev_sha224();
+        break;
+    case NID_sha384:
+        *digest = cryptodev_sha384();
+        break;
+    case NID_sha512:
+        *digest = cryptodev_sha512();
+        break;
     default:
 # endif                         /* USE_CRYPTODEV_DIGESTS */
         *digest = NULL;
@@ -1167,8 +1301,26 @@ static int cryptodev_engine_destroy(ENGINE *e)
 # ifdef USE_CRYPTODEV_DIGESTS
     EVP_MD_meth_free(sha1_md);
     sha1_md = NULL;
+    EVP_MD_meth_free(sha256_md);
+    sha256_md = NULL;
+    EVP_MD_meth_free(sha224_md);
+    sha224_md = NULL;
+    EVP_MD_meth_free(sha384_md);
+    sha384_md = NULL;
+    EVP_MD_meth_free(sha512_md);
+    sha512_md = NULL;
     EVP_MD_meth_free(md5_md);
     md5_md = NULL;
+# endif
+    RSA_meth_free(cryptodev_rsa);
+    cryptodev_rsa = NULL;
+# ifndef OPENSSL_NO_DSA
+    DSA_meth_free(cryptodev_dsa);
+    cryptodev_dsa = NULL;
+# endif
+# ifndef OPENSSL_NO_DH
+    DH_meth_free(cryptodev_dh);
+    cryptodev_dh = NULL;
 # endif
     return 1;
 }
@@ -1193,7 +1345,7 @@ static int bn2crparam(const BIGNUM *a, struct crparam *crp)
     if (b == NULL)
         return (1);
 
-    crp->crp_p = (caddr_t) b;
+    crp->crp_p = (void *) b;
     crp->crp_nbits = bits;
 
     BN_bn2bin(a, b);
@@ -1228,8 +1380,7 @@ static void zapparams(struct crypt_kop *kop)
     int i;
 
     for (i = 0; i < kop->crk_iparams + kop->crk_oparams; i++) {
-        if (kop->crk_param[i].crp_p)
-            free(kop->crk_param[i].crp_p);
+        OPENSSL_free(kop->crk_param[i].crp_p);
         kop->crk_param[i].crp_p = NULL;
         kop->crk_param[i].crp_nbits = 0;
     }
@@ -1242,16 +1393,24 @@ cryptodev_asym(struct crypt_kop *kop, int rlen, BIGNUM *r, int slen,
     int fd, ret = -1;
 
     if ((fd = get_asym_dev_crypto()) < 0)
-        return (ret);
+        return ret;
 
     if (r) {
-        kop->crk_param[kop->crk_iparams].crp_p = calloc(rlen, sizeof(char));
+        kop->crk_param[kop->crk_iparams].crp_p = OPENSSL_zalloc(rlen);
+        if (kop->crk_param[kop->crk_iparams].crp_p == NULL)
+            return ret;
         kop->crk_param[kop->crk_iparams].crp_nbits = rlen * 8;
         kop->crk_oparams++;
     }
     if (s) {
         kop->crk_param[kop->crk_iparams + 1].crp_p =
-            calloc(slen, sizeof(char));
+            OPENSSL_zalloc(slen);
+        /* No need to free the kop->crk_iparams parameter if it was allocated,
+         * callers of this routine have to free allocated parameters through
+         * zapparams both in case of success and failure
+         */
+        if (kop->crk_param[kop->crk_iparams+1].crp_p == NULL)
+            return ret;
         kop->crk_param[kop->crk_iparams + 1].crp_nbits = slen * 8;
         kop->crk_oparams++;
     }
@@ -1264,7 +1423,7 @@ cryptodev_asym(struct crypt_kop *kop, int rlen, BIGNUM *r, int slen,
         ret = 0;
     }
 
-    return (ret);
+    return ret;
 }
 
 static int
@@ -1298,12 +1457,12 @@ cryptodev_bn_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
     if (cryptodev_asym(&kop, BN_num_bytes(m), r, 0, NULL)) {
         const RSA_METHOD *meth = RSA_PKCS1_OpenSSL();
         printf("OCF asym process failed, Running in software\n");
-        ret = meth->bn_mod_exp(r, a, p, m, ctx, in_mont);
+        ret = RSA_meth_get_bn_mod_exp(meth)(r, a, p, m, ctx, in_mont);
 
     } else if (ECANCELED == kop.crk_status) {
         const RSA_METHOD *meth = RSA_PKCS1_OpenSSL();
         printf("OCF hardware operation cancelled. Running in Software\n");
-        ret = meth->bn_mod_exp(r, a, p, m, ctx, in_mont);
+        ret = RSA_meth_get_bn_mod_exp(meth)(r, a, p, m, ctx, in_mont);
     }
     /* else cryptodev operation worked ok ==> ret = 1 */
 
@@ -1317,8 +1476,12 @@ cryptodev_rsa_nocrt_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa,
                             BN_CTX *ctx)
 {
     int r;
+    const BIGNUM *n = NULL;
+    const BIGNUM *d = NULL;
+
     ctx = BN_CTX_new();
-    r = cryptodev_bn_mod_exp(r0, I, rsa->d, rsa->n, ctx, NULL);
+    RSA_get0_key(rsa, &n, NULL, &d);
+    r = cryptodev_bn_mod_exp(r0, I, d, n, ctx, NULL);
     BN_CTX_free(ctx);
     return (r);
 }
@@ -1328,8 +1491,18 @@ cryptodev_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
 {
     struct crypt_kop kop;
     int ret = 1;
-
-    if (!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp) {
+    const BIGNUM *p = NULL;
+    const BIGNUM *q = NULL;
+    const BIGNUM *dmp1 = NULL;
+    const BIGNUM *dmq1 = NULL;
+    const BIGNUM *iqmp = NULL;
+    const BIGNUM *n = NULL;
+
+    RSA_get0_factors(rsa, &p, &q);
+    RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp);
+    RSA_get0_key(rsa, &n, NULL, NULL);
+
+    if (!p || !q || !dmp1 || !dmq1 || !iqmp) {
         /* XXX 0 means failure?? */
         return (0);
     }
@@ -1337,29 +1510,29 @@ cryptodev_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
     memset(&kop, 0, sizeof(kop));
     kop.crk_op = CRK_MOD_EXP_CRT;
     /* inputs: rsa->p rsa->q I rsa->dmp1 rsa->dmq1 rsa->iqmp */
-    if (bn2crparam(rsa->p, &kop.crk_param[0]))
+    if (bn2crparam(p, &kop.crk_param[0]))
         goto err;
-    if (bn2crparam(rsa->q, &kop.crk_param[1]))
+    if (bn2crparam(q, &kop.crk_param[1]))
         goto err;
     if (bn2crparam(I, &kop.crk_param[2]))
         goto err;
-    if (bn2crparam(rsa->dmp1, &kop.crk_param[3]))
+    if (bn2crparam(dmp1, &kop.crk_param[3]))
         goto err;
-    if (bn2crparam(rsa->dmq1, &kop.crk_param[4]))
+    if (bn2crparam(dmq1, &kop.crk_param[4]))
         goto err;
-    if (bn2crparam(rsa->iqmp, &kop.crk_param[5]))
+    if (bn2crparam(iqmp, &kop.crk_param[5]))
         goto err;
     kop.crk_iparams = 6;
 
-    if (cryptodev_asym(&kop, BN_num_bytes(rsa->n), r0, 0, NULL)) {
+    if (cryptodev_asym(&kop, BN_num_bytes(n), r0, 0, NULL)) {
         const RSA_METHOD *meth = RSA_PKCS1_OpenSSL();
         printf("OCF asym process failed, running in Software\n");
-        ret = (*meth->rsa_mod_exp) (r0, I, rsa, ctx);
+        ret = RSA_meth_get_mod_exp(meth)(r0, I, rsa, ctx);
 
     } else if (ECANCELED == kop.crk_status) {
         const RSA_METHOD *meth = RSA_PKCS1_OpenSSL();
         printf("OCF hardware operation cancelled. Running in Software\n");
-        ret = (*meth->rsa_mod_exp) (r0, I, rsa, ctx);
+        ret = RSA_meth_get_mod_exp(meth)(r0, I, rsa, ctx);
     }
     /* else cryptodev operation worked ok ==> ret = 1 */
 
@@ -1368,36 +1541,26 @@ cryptodev_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
     return (ret);
 }
 
-static RSA_METHOD cryptodev_rsa = {
-    "cryptodev RSA method",
-    NULL,                       /* rsa_pub_enc */
-    NULL,                       /* rsa_pub_dec */
-    NULL,                       /* rsa_priv_enc */
-    NULL,                       /* rsa_priv_dec */
-    NULL,
-    NULL,
-    NULL,                       /* init */
-    NULL,                       /* finish */
-    0,                          /* flags */
-    NULL,                       /* app_data */
-    NULL,                       /* rsa_sign */
-    NULL                        /* rsa_verify */
-};
-
+# ifndef OPENSSL_NO_DSA
 static int
-cryptodev_dsa_bn_mod_exp(DSA *dsa, BIGNUM *r, BIGNUM *a, const BIGNUM *p,
+cryptodev_dsa_bn_mod_exp(DSA *dsa, BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
                          const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
 {
-    return (cryptodev_bn_mod_exp(r, a, p, m, ctx, m_ctx));
+    return cryptodev_bn_mod_exp(r, a, p, m, ctx, m_ctx);
 }
 
 static int
-cryptodev_dsa_dsa_mod_exp(DSA *dsa, BIGNUM *t1, BIGNUM *g,
-                          BIGNUM *u1, BIGNUM *pub_key, BIGNUM *u2, BIGNUM *p,
-                          BN_CTX *ctx, BN_MONT_CTX *mont)
+cryptodev_dsa_dsa_mod_exp(DSA *dsa, BIGNUM *t1, const BIGNUM *g,
+                          const BIGNUM *u1, const BIGNUM *pub_key,
+                          const BIGNUM *u2, const BIGNUM *p, BN_CTX *ctx,
+                          BN_MONT_CTX *mont)
 {
+    const BIGNUM *dsag, *dsap, *dsapub_key;
     BIGNUM *t2;
     int ret = 0;
+    const DSA_METHOD *meth;
+    int (*bn_mod_exp)(DSA *, BIGNUM *, const BIGNUM *, const BIGNUM *, const BIGNUM *,
+                      BN_CTX *, BN_MONT_CTX *);
 
     t2 = BN_new();
     if (t2 == NULL)
@@ -1407,18 +1570,26 @@ cryptodev_dsa_dsa_mod_exp(DSA *dsa, BIGNUM *t1, BIGNUM *g,
     /* let t1 = g ^ u1 mod p */
     ret = 0;
 
-    if (!dsa->meth->bn_mod_exp(dsa, t1, dsa->g, u1, dsa->p, ctx, mont))
+    DSA_get0_pqg(dsa, &dsap, NULL, &dsag);
+    DSA_get0_key(dsa, &dsapub_key, NULL);
+
+    meth = DSA_get_method(dsa);
+    if (meth == NULL)
+        goto err;
+    bn_mod_exp = DSA_meth_get_bn_mod_exp(meth);
+    if (bn_mod_exp == NULL)
+        goto err;
+
+    if (!bn_mod_exp(dsa, t1, dsag, u1, dsap, ctx, mont))
         goto err;
 
     /* let t2 = y ^ u2 mod p */
-    if (!dsa->meth->bn_mod_exp(dsa, t2, dsa->pub_key, u2, dsa->p, ctx, mont))
+    if (!bn_mod_exp(dsa, t2, dsapub_key, u2, dsap, ctx, mont))
         goto err;
-    /* let u1 = t1 * t2 mod p */
-    if (!BN_mod_mul(u1, t1, t2, dsa->p, ctx))
+    /* let t1 = t1 * t2 mod p */
+    if (!BN_mod_mul(t1, t1, t2, dsap, ctx))
         goto err;
 
-    BN_copy(t1, u1);
-
     ret = 1;
  err:
     BN_free(t2);
@@ -1429,36 +1600,45 @@ static DSA_SIG *cryptodev_dsa_do_sign(const unsigned char *dgst, int dlen,
                                       DSA *dsa)
 {
     struct crypt_kop kop;
-    BIGNUM *r = NULL, *s = NULL;
+    BIGNUM *r, *s;
+    const BIGNUM *dsap = NULL, *dsaq = NULL, *dsag = NULL;
+    const BIGNUM *priv_key = NULL;
     DSA_SIG *dsasig, *dsaret = NULL;
 
     dsasig = DSA_SIG_new();
     if (dsasig == NULL)
         goto err;
-    DSA_SIG_get0(&r, &s, dsasig);
 
     memset(&kop, 0, sizeof(kop));
     kop.crk_op = CRK_DSA_SIGN;
 
     /* inputs: dgst dsa->p dsa->q dsa->g dsa->priv_key */
-    kop.crk_param[0].crp_p = (caddr_t) dgst;
+    kop.crk_param[0].crp_p = (void *) dgst;
     kop.crk_param[0].crp_nbits = dlen * 8;
-    if (bn2crparam(dsa->p, &kop.crk_param[1]))
+    DSA_get0_pqg(dsa, &dsap, &dsaq, &dsag);
+    DSA_get0_key(dsa, NULL, &priv_key);
+    if (bn2crparam(dsap, &kop.crk_param[1]))
         goto err;
-    if (bn2crparam(dsa->q, &kop.crk_param[2]))
+    if (bn2crparam(dsaq, &kop.crk_param[2]))
         goto err;
-    if (bn2crparam(dsa->g, &kop.crk_param[3]))
+    if (bn2crparam(dsag, &kop.crk_param[3]))
         goto err;
-    if (bn2crparam(dsa->priv_key, &kop.crk_param[4]))
+    if (bn2crparam(priv_key, &kop.crk_param[4]))
         goto err;
     kop.crk_iparams = 5;
 
-    if (cryptodev_asym(&kop, BN_num_bytes(dsa->q), r,
-                       BN_num_bytes(dsa->q), s) == 0) {
+    r = BN_new();
+    if (r == NULL)
+        goto err;
+    s = BN_new();
+    if (s == NULL)
+        goto err;
+    if (cryptodev_asym(&kop, BN_num_bytes(dsaq), r,
+                       BN_num_bytes(dsaq), s) == 0) {
+        DSA_SIG_set0(dsasig, r, s);
         dsaret = dsasig;
     } else {
-        const DSA_METHOD *meth = DSA_OpenSSL();
-        dsaret = (meth->dsa_do_sign) (dgst, dlen, dsa);
+        dsaret = DSA_meth_get_sign(DSA_OpenSSL())(dgst, dlen, dsa);
     }
  err:
     if (dsaret != dsasig)
@@ -1474,23 +1654,25 @@ cryptodev_dsa_verify(const unsigned char *dgst, int dlen,
 {
     struct crypt_kop kop;
     int dsaret = 1;
-    BIGNUM *pr, *ps;
+    const BIGNUM *pr, *ps, *p = NULL, *q = NULL, *g = NULL, *pub_key = NULL;
 
     memset(&kop, 0, sizeof(kop));
     kop.crk_op = CRK_DSA_VERIFY;
 
     /* inputs: dgst dsa->p dsa->q dsa->g dsa->pub_key sig->r sig->s */
-    kop.crk_param[0].crp_p = (caddr_t) dgst;
+    kop.crk_param[0].crp_p = (void *) dgst;
     kop.crk_param[0].crp_nbits = dlen * 8;
-    if (bn2crparam(dsa->p, &kop.crk_param[1]))
+    DSA_get0_pqg(dsa, &p, &q, &g);
+    if (bn2crparam(p, &kop.crk_param[1]))
         goto err;
-    if (bn2crparam(dsa->q, &kop.crk_param[2]))
+    if (bn2crparam(q, &kop.crk_param[2]))
         goto err;
-    if (bn2crparam(dsa->g, &kop.crk_param[3]))
+    if (bn2crparam(g, &kop.crk_param[3]))
         goto err;
-    if (bn2crparam(dsa->pub_key, &kop.crk_param[4]))
+    DSA_get0_key(dsa, &pub_key, NULL);
+    if (bn2crparam(pub_key, &kop.crk_param[4]))
         goto err;
-    DSA_SIG_get0(&pr, &ps, sig);
+    DSA_SIG_get0(sig, &pr, &ps);
     if (bn2crparam(pr, &kop.crk_param[5]))
         goto err;
     if (bn2crparam(ps, &kop.crk_param[6]))
@@ -1504,30 +1686,16 @@ cryptodev_dsa_verify(const unsigned char *dgst, int dlen,
         if (0 != kop.crk_status)
             dsaret = 0;
     } else {
-        const DSA_METHOD *meth = DSA_OpenSSL();
-
-        dsaret = (meth->dsa_do_verify) (dgst, dlen, sig, dsa);
+        dsaret = DSA_meth_get_verify(DSA_OpenSSL())(dgst, dlen, sig, dsa);
     }
  err:
     kop.crk_param[0].crp_p = NULL;
     zapparams(&kop);
     return (dsaret);
 }
+# endif
 
-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 */
-};
-
-#ifndef OPENSSL_NO_DH
+# ifndef OPENSSL_NO_DH
 static int
 cryptodev_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a,
                      const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
@@ -1542,35 +1710,40 @@ cryptodev_dh_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
     struct crypt_kop kop;
     int dhret = 1;
     int fd, keylen;
+    const BIGNUM *p = NULL;
+    const BIGNUM *priv_key = NULL;
 
     if ((fd = get_asym_dev_crypto()) < 0) {
         const DH_METHOD *meth = DH_OpenSSL();
 
-        return ((meth->compute_key) (key, pub_key, dh));
+        return DH_meth_get_compute_key(meth)(key, pub_key, dh);
     }
 
-    keylen = BN_num_bits(dh->p);
+    DH_get0_pqg(dh, &p, NULL, NULL);
+    DH_get0_key(dh, NULL, &priv_key);
+
+    keylen = BN_num_bits(p);
 
     memset(&kop, 0, sizeof(kop));
     kop.crk_op = CRK_DH_COMPUTE_KEY;
 
     /* inputs: dh->priv_key pub_key dh->p key */
-    if (bn2crparam(dh->priv_key, &kop.crk_param[0]))
+    if (bn2crparam(priv_key, &kop.crk_param[0]))
         goto err;
     if (bn2crparam(pub_key, &kop.crk_param[1]))
         goto err;
-    if (bn2crparam(dh->p, &kop.crk_param[2]))
+    if (bn2crparam(p, &kop.crk_param[2]))
         goto err;
     kop.crk_iparams = 3;
 
-    kop.crk_param[3].crp_p = (caddr_t) key;
+    kop.crk_param[3].crp_p = (void *) key;
     kop.crk_param[3].crp_nbits = keylen * 8;
     kop.crk_oparams = 1;
 
     if (ioctl(fd, CIOCKEY, &kop) == -1) {
         const DH_METHOD *meth = DH_OpenSSL();
 
-        dhret = (meth->compute_key) (key, pub_key, dh);
+        dhret = DH_meth_get_compute_key(meth)(key, pub_key, dh);
     }
  err:
     kop.crk_param[3].crp_p = NULL;
@@ -1578,18 +1751,7 @@ cryptodev_dh_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
     return (dhret);
 }
 
-static DH_METHOD cryptodev_dh = {
-    "cryptodev DH method",
-    NULL,                       /* cryptodev_dh_generate_key */
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    0,                          /* flags */
-    NULL                        /* app_data */
-};
-
-#endif /* ndef OPENSSL_NO_DH */
+# endif /* ndef OPENSSL_NO_DH */
 
 /*
  * ctrl right now is just a wrapper that doesn't do much
@@ -1614,7 +1776,7 @@ cryptodev_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
     return (1);
 }
 
-void engine_load_cryptodev_internal(void)
+void engine_load_cryptodev_int(void)
 {
     ENGINE *engine = ENGINE_new();
     int fd;
@@ -1637,7 +1799,7 @@ void engine_load_cryptodev_internal(void)
     put_dev_crypto(fd);
 
     if (!ENGINE_set_id(engine, "cryptodev") ||
-        !ENGINE_set_name(engine, "BSD cryptodev engine") ||
+        !ENGINE_set_name(engine, "cryptodev engine") ||
         !ENGINE_set_destroy_function(engine, cryptodev_engine_destroy) ||
         !ENGINE_set_ciphers(engine, cryptodev_engine_ciphers) ||
         !ENGINE_set_digests(engine, cryptodev_engine_digests) ||
@@ -1647,52 +1809,65 @@ void engine_load_cryptodev_internal(void)
         return;
     }
 
-    if (ENGINE_set_RSA(engine, &cryptodev_rsa)) {
-        const RSA_METHOD *rsa_meth = RSA_PKCS1_OpenSSL();
-
-        cryptodev_rsa.bn_mod_exp = rsa_meth->bn_mod_exp;
-        cryptodev_rsa.rsa_mod_exp = rsa_meth->rsa_mod_exp;
-        cryptodev_rsa.rsa_pub_enc = rsa_meth->rsa_pub_enc;
-        cryptodev_rsa.rsa_pub_dec = rsa_meth->rsa_pub_dec;
-        cryptodev_rsa.rsa_priv_enc = rsa_meth->rsa_priv_enc;
-        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.rsa_mod_exp = cryptodev_rsa_mod_exp;
-            else
-                cryptodev_rsa.rsa_mod_exp = cryptodev_rsa_nocrt_mod_exp;
+    cryptodev_rsa = RSA_meth_dup(RSA_PKCS1_OpenSSL());
+    if (cryptodev_rsa != NULL) {
+        RSA_meth_set1_name(cryptodev_rsa, "cryptodev RSA method");
+        RSA_meth_set_flags(cryptodev_rsa, 0);
+        if (ENGINE_set_RSA(engine, cryptodev_rsa)) {
+            if (cryptodev_asymfeat & CRF_MOD_EXP) {
+                RSA_meth_set_bn_mod_exp(cryptodev_rsa, cryptodev_bn_mod_exp);
+                if (cryptodev_asymfeat & CRF_MOD_EXP_CRT)
+                    RSA_meth_set_mod_exp(cryptodev_rsa, cryptodev_rsa_mod_exp);
+                else
+                    RSA_meth_set_mod_exp(cryptodev_rsa,
+                                         cryptodev_rsa_nocrt_mod_exp);
+            }
         }
+    } else {
+        ENGINE_free(engine);
+        return;
     }
 
-    if (ENGINE_set_DSA(engine, &cryptodev_dsa)) {
-        const DSA_METHOD *meth = DSA_OpenSSL();
-
-        memcpy(&cryptodev_dsa, meth, sizeof(DSA_METHOD));
-        if (cryptodev_asymfeat & CRF_DSA_SIGN)
-            cryptodev_dsa.dsa_do_sign = cryptodev_dsa_do_sign;
-        if (cryptodev_asymfeat & CRF_MOD_EXP) {
-            cryptodev_dsa.bn_mod_exp = cryptodev_dsa_bn_mod_exp;
-            cryptodev_dsa.dsa_mod_exp = cryptodev_dsa_dsa_mod_exp;
+# ifndef OPENSSL_NO_DSA
+    cryptodev_dsa = DSA_meth_dup(DSA_OpenSSL());
+    if (cryptodev_dsa != NULL) {
+        DSA_meth_set1_name(cryptodev_dsa, "cryptodev DSA method");
+        DSA_meth_set_flags(cryptodev_dsa, 0);
+        if (ENGINE_set_DSA(engine, cryptodev_dsa)) {
+            if (cryptodev_asymfeat & CRF_DSA_SIGN)
+                DSA_meth_set_sign(cryptodev_dsa, cryptodev_dsa_do_sign);
+            if (cryptodev_asymfeat & CRF_MOD_EXP) {
+                DSA_meth_set_bn_mod_exp(cryptodev_dsa,
+                                        cryptodev_dsa_bn_mod_exp);
+                DSA_meth_set_mod_exp(cryptodev_dsa, cryptodev_dsa_dsa_mod_exp);
+            }
+            if (cryptodev_asymfeat & CRF_DSA_VERIFY)
+                DSA_meth_set_verify(cryptodev_dsa, cryptodev_dsa_verify);
         }
-        if (cryptodev_asymfeat & CRF_DSA_VERIFY)
-            cryptodev_dsa.dsa_do_verify = cryptodev_dsa_verify;
+    } else {
+        ENGINE_free(engine);
+        return;
     }
+# endif
 
-#ifndef OPENSSL_NO_DH
-    if (ENGINE_set_DH(engine, &cryptodev_dh)) {
-        const DH_METHOD *dh_meth = DH_OpenSSL();
-
-        cryptodev_dh.generate_key = dh_meth->generate_key;
-        cryptodev_dh.compute_key = dh_meth->compute_key;
-        cryptodev_dh.bn_mod_exp = dh_meth->bn_mod_exp;
-        if (cryptodev_asymfeat & CRF_MOD_EXP) {
-            cryptodev_dh.bn_mod_exp = cryptodev_mod_exp_dh;
-            if (cryptodev_asymfeat & CRF_DH_COMPUTE_KEY)
-                cryptodev_dh.compute_key = cryptodev_dh_compute_key;
+# ifndef OPENSSL_NO_DH
+    cryptodev_dh = DH_meth_dup(DH_OpenSSL());
+    if (cryptodev_dh != NULL) {
+        DH_meth_set1_name(cryptodev_dh, "cryptodev DH method");
+        DH_meth_set_flags(cryptodev_dh, 0);
+        if (ENGINE_set_DH(engine, cryptodev_dh)) {
+            if (cryptodev_asymfeat & CRF_MOD_EXP) {
+                DH_meth_set_bn_mod_exp(cryptodev_dh, cryptodev_mod_exp_dh);
+                if (cryptodev_asymfeat & CRF_DH_COMPUTE_KEY)
+                    DH_meth_set_compute_key(cryptodev_dh,
+                                            cryptodev_dh_compute_key);
+            }
         }
+    } else {
+        ENGINE_free(engine);
+        return;
     }
-#endif
+# endif
 
     ENGINE_add(engine);
     ENGINE_free(engine);