]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/commitdiff
openssl: fix aes accleration via cryptodev.
authorArne Fitzenreiter <arne_f@ipfire.org>
Sat, 31 Mar 2012 09:20:27 +0000 (11:20 +0200)
committerArne Fitzenreiter <arne_f@ipfire.org>
Sat, 7 Apr 2012 09:36:20 +0000 (11:36 +0200)
lfs/openssl
src/patches/openssl-0.9.8u-cryptodev.patch [new file with mode: 0644]

index 3336cfb4bb401232f496ee01645ea86fa1259b5f..9d559e1549f112984a4f723dddc00bfee85ed1d3 100644 (file)
@@ -70,15 +70,12 @@ $(subst %,%_MD5,$(objects)) :
 $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
        @$(PREBUILD)
        @rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar zxf $(DIR_DL)/$(DL_FILE)
-       cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/openssl-0.9.8n-cryptodev.diff
-ifeq "$(PADLOCK)" "1"
-       cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/openssl-0.9.8g-engine-padlock.patch
-endif
+       cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/openssl-0.9.8u-cryptodev.patch
        @rm -rf /etc/ssl
        cd $(DIR_APP) && sed -i -e 's/mcpu/march/' config
        cd $(DIR_APP) && sed -i -e 's/-O3/-O2/' -e 's/-march=i486/-march=i586/' Configure
        cd $(DIR_APP) && ./Configure --openssldir=/etc/ssl --prefix=/usr shared linux-elf \
-               zlib-dynamic no-asm 386
+               zlib-dynamic no-asm 386 -DHAVE_CRYPTODEV -DUSE_CRYPTODEV_DIGEST
        cd $(DIR_APP) && make MANDIR=/usr/share/man
        cd $(DIR_APP) && make MANDIR=/usr/share/man install
        rm -rf /etc/ssl/lib
diff --git a/src/patches/openssl-0.9.8u-cryptodev.patch b/src/patches/openssl-0.9.8u-cryptodev.patch
new file mode 100644 (file)
index 0000000..920648d
--- /dev/null
@@ -0,0 +1,882 @@
+diff -Naur openssl-0.9.8u.org/crypto/engine/eng_all.c openssl-0.9.8u/crypto/engine/eng_all.c
+--- openssl-0.9.8u.org/crypto/engine/eng_all.c 2010-03-01 01:30:11.000000000 +0100
++++ openssl-0.9.8u/crypto/engine/eng_all.c     2012-03-27 14:07:11.000000000 +0200
+@@ -113,7 +113,6 @@
+ #endif
+       }
+-#if defined(__OpenBSD__) || defined(__FreeBSD__)
+ void ENGINE_setup_bsd_cryptodev(void) {
+       static int bsd_cryptodev_default_loaded = 0;
+       if (!bsd_cryptodev_default_loaded) {
+@@ -122,4 +121,3 @@
+       }
+       bsd_cryptodev_default_loaded=1;
+ }
+-#endif
+diff -Naur openssl-0.9.8u.org/crypto/engine/eng_cryptodev.c openssl-0.9.8u/crypto/engine/eng_cryptodev.c
+--- openssl-0.9.8u.org/crypto/engine/eng_cryptodev.c   2012-03-06 14:22:32.000000000 +0100
++++ openssl-0.9.8u/crypto/engine/eng_cryptodev.c       2012-03-27 14:02:59.000000000 +0200
+@@ -2,6 +2,7 @@
+  * 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
+@@ -30,10 +31,6 @@
+ #include <openssl/engine.h>
+ #include <openssl/evp.h>
+ #include <openssl/bn.h>
+-#include <openssl/dsa.h>
+-#include <openssl/rsa.h>
+-#include <openssl/dh.h>
+-#include <openssl/err.h>
+ #if (defined(__unix__) || defined(unix)) && !defined(USG) && \
+       (defined(OpenBSD) || defined(__FreeBSD__))
+@@ -59,6 +56,10 @@
+  
+ #include <sys/types.h>
+ #include <crypto/cryptodev.h>
++#include <crypto/dh/dh.h>
++#include <crypto/dsa/dsa.h>
++#include <crypto/err/err.h>
++#include <crypto/rsa/rsa.h>
+ #include <sys/ioctl.h>
+ #include <errno.h>
+ #include <stdio.h>
+@@ -72,6 +73,12 @@
+ struct dev_crypto_state {
+       struct session_op d_sess;
+       int d_fd;
++
++#ifdef USE_CRYPTODEV_DIGESTS
++      unsigned char digest_res[HASH_MAX_LEN];
++      char *mac_data;
++      int mac_len;
++#endif
+ };
+ static u_int32_t cryptodev_asymfeat = 0;
+@@ -79,15 +86,14 @@
+ static int get_asym_dev_crypto(void);
+ static int open_dev_crypto(void);
+ static int get_dev_crypto(void);
+-static int cryptodev_max_iv(int cipher);
+-static int cryptodev_key_length_valid(int cipher, int len);
+-static int cipher_nid_to_cryptodev(int nid);
+ static int get_cryptodev_ciphers(const int **cnids);
+-/*static int get_cryptodev_digests(const int **cnids);*/
++#ifdef USE_CRYPTODEV_DIGESTS
++static int get_cryptodev_digests(const int **cnids);
++#endif
+ static int cryptodev_usable_ciphers(const int **nids);
+ static int cryptodev_usable_digests(const int **nids);
+ static int cryptodev_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+-    const unsigned char *in, unsigned int inl);
++    const unsigned char *in, size_t inl);
+ static int cryptodev_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+     const unsigned char *iv, int enc);
+ static int cryptodev_cleanup(EVP_CIPHER_CTX *ctx);
+@@ -121,7 +127,7 @@
+ static int cryptodev_dh_compute_key(unsigned char *key,
+     const BIGNUM *pub_key, DH *dh);
+ static int cryptodev_ctrl(ENGINE *e, int cmd, long i, void *p,
+-    void (*f)());
++    void (*f)(void));
+ void ENGINE_load_cryptodev(void);
+ static const ENGINE_CMD_DEFN cryptodev_defns[] = {
+@@ -134,27 +140,38 @@
+       int     ivmax;
+       int     keylen;
+ } ciphers[] = {
++      { CRYPTO_ARC4,                  NID_rc4,                0,      16, },
+       { CRYPTO_DES_CBC,               NID_des_cbc,            8,       8, },
+       { CRYPTO_3DES_CBC,              NID_des_ede3_cbc,       8,      24, },
+       { CRYPTO_AES_CBC,               NID_aes_128_cbc,        16,     16, },
++      { CRYPTO_AES_CBC,               NID_aes_192_cbc,        16,     24, },
++      { CRYPTO_AES_CBC,               NID_aes_256_cbc,        16,     32, },
+       { CRYPTO_BLF_CBC,               NID_bf_cbc,             8,      16, },
+       { CRYPTO_CAST_CBC,              NID_cast5_cbc,          8,      16, },
+       { CRYPTO_SKIPJACK_CBC,          NID_undef,              0,       0, },
+       { 0,                            NID_undef,              0,       0, },
+ };
+-#if 0
++#ifdef USE_CRYPTODEV_DIGESTS
+ static struct {
+       int     id;
+       int     nid;
++      int     digestlen;
+ } digests[] = {
+-      { CRYPTO_SHA1_HMAC,             NID_hmacWithSHA1,       },
+-      { CRYPTO_RIPEMD160_HMAC,        NID_ripemd160,          },
+-      { CRYPTO_MD5_KPDK,              NID_undef,              },
+-      { CRYPTO_SHA1_KPDK,             NID_undef,              },
+-      { CRYPTO_MD5,                   NID_md5,                },
+-      { CRYPTO_SHA1,                  NID_undef,              },
+-      { 0,                            NID_undef,              },
++#if 0
++        /* HMAC is not supported */
++      { CRYPTO_MD5_HMAC,              NID_hmacWithMD5,        16},
++      { CRYPTO_SHA1_HMAC,             NID_hmacWithSHA1,       20},
++      { CRYPTO_SHA2_256_HMAC,         NID_hmacWithSHA256,     32},
++      { CRYPTO_SHA2_384_HMAC,         NID_hmacWithSHA384,     48},
++      { 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},
+ };
+ #endif
+@@ -186,6 +203,7 @@
+       if ((fd = open_dev_crypto()) == -1)
+               return (-1);
++#ifndef CRIOGET_NOT_NEEDED
+       if (ioctl(fd, CRIOGET, &retfd) == -1)
+               return (-1);
+@@ -194,9 +212,19 @@
+               close(retfd);
+               return (-1);
+       }
++#else
++        retfd = fd;
++#endif
+       return (retfd);
+ }
++static void put_dev_crypto(int fd)
++{
++#ifndef CRIOGET_NOT_NEEDED
++      close(fd);
++#endif
++}
++
+ /* Caching version for asym operations */
+ static int
+ get_asym_dev_crypto(void)
+@@ -209,50 +237,6 @@
+ }
+ /*
+- * XXXX this needs to be set for each alg - and determined from
+- * a running card.
+- */
+-static int
+-cryptodev_max_iv(int cipher)
+-{
+-      int i;
+-
+-      for (i = 0; ciphers[i].id; i++)
+-              if (ciphers[i].id == cipher)
+-                      return (ciphers[i].ivmax);
+-      return (0);
+-}
+-
+-/*
+- * XXXX this needs to be set for each alg - and determined from
+- * a running card. For now, fake it out - but most of these
+- * for real devices should return 1 for the supported key
+- * sizes the device can handle.
+- */
+-static int
+-cryptodev_key_length_valid(int cipher, int len)
+-{
+-      int i;
+-
+-      for (i = 0; ciphers[i].id; i++)
+-              if (ciphers[i].id == cipher)
+-                      return (ciphers[i].keylen == len);
+-      return (0);
+-}
+-
+-/* convert libcrypto nids to cryptodev */
+-static int
+-cipher_nid_to_cryptodev(int nid)
+-{
+-      int i;
+-
+-      for (i = 0; ciphers[i].id; i++)
+-              if (ciphers[i].nid == nid)
+-                      return (ciphers[i].id);
+-      return (0);
+-}
+-
+-/*
+  * Find out what ciphers /dev/crypto will let us have a session for.
+  * XXX note, that some of these openssl doesn't deal with yet!
+  * returning them here is harmless, as long as we return NULL
+@@ -264,13 +248,14 @@
+       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)"123456781234567812345678";
++      sess.key = (void*)fake_key;
+       for (i = 0; ciphers[i].id && count < CRYPTO_ALGORITHM_MAX; i++) {
+               if (ciphers[i].nid == NID_undef)
+@@ -282,7 +267,7 @@
+                   ioctl(fd, CIOCFSESSION, &sess.ses) != -1)
+                       nids[count++] = ciphers[i].nid;
+       }
+-      close(fd);
++      put_dev_crypto(fd);
+       if (count > 0)
+               *cnids = nids;
+@@ -291,7 +276,7 @@
+       return (count);
+ }
+-#if 0  /* unused */
++#ifdef USE_CRYPTODEV_DIGESTS
+ /*
+  * Find out what digests /dev/crypto will let us have a session for.
+  * XXX note, that some of these openssl doesn't deal with yet!
+@@ -302,6 +287,7 @@
+ 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;
+@@ -310,16 +296,18 @@
+               return (0);
+       }
+       memset(&sess, 0, sizeof(sess));
++      sess.mackey = 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 = 8;
+               sess.cipher = 0;
+               if (ioctl(fd, CIOCGSESSION, &sess) != -1 &&
+                   ioctl(fd, CIOCFSESSION, &sess.ses) != -1)
+                       nids[count++] = digests[i].nid;
+       }
+-      close(fd);
++      put_dev_crypto(fd);
+       if (count > 0)
+               *cnids = nids;
+@@ -327,8 +315,7 @@
+               *cnids = NULL;
+       return (count);
+ }
+-
+-#endif
++#endif  /* 0 */
+ /*
+  * Find the useable ciphers|digests from dev/crypto - this is the first
+@@ -360,6 +347,9 @@
+ static int
+ cryptodev_usable_digests(const int **nids)
+ {
++#ifdef USE_CRYPTODEV_DIGESTS
++      return (get_cryptodev_digests(nids));
++#else
+       /*
+        * XXXX just disable all digests for now, because it sucks.
+        * we need a better way to decide this - i.e. I may not
+@@ -374,11 +364,12 @@
+        */
+       *nids = NULL;
+       return (0);
++#endif
+ }
+ static int
+ cryptodev_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+-    const unsigned char *in, unsigned int inl)
++    const unsigned char *in, size_t inl)
+ {
+       struct crypt_op cryp;
+       struct dev_crypto_state *state = ctx->cipher_data;
+@@ -398,14 +389,14 @@
+       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 = ctx->encrypt ? COP_ENCRYPT : COP_DECRYPT;
+       if (ctx->cipher->iv_len) {
+-              cryp.iv = (caddr_t) ctx->iv;
++              cryp.iv = (void*) ctx->iv;
+               if (!ctx->encrypt) {
+                       iiv = in + inl - ctx->cipher->iv_len;
+                       memcpy(save_iv, iiv, ctx->cipher->iv_len);
+@@ -436,28 +427,32 @@
+ {
+       struct dev_crypto_state *state = ctx->cipher_data;
+       struct session_op *sess = &state->d_sess;
+-      int cipher;
++      int cipher = -1, i;
+-      if ((cipher = cipher_nid_to_cryptodev(ctx->cipher->nid)) == NID_undef)
+-              return (0);
+-
+-      if (ctx->cipher->iv_len > cryptodev_max_iv(cipher))
+-              return (0);
++      for (i = 0; ciphers[i].id; i++)
++              if (ctx->cipher->nid == ciphers[i].nid &&
++                  ctx->cipher->iv_len <= ciphers[i].ivmax &&
++                  ctx->key_len == ciphers[i].keylen) {
++                      cipher = ciphers[i].id;
++                      break;
++              }
+-      if (!cryptodev_key_length_valid(cipher, ctx->key_len))
++      if (!ciphers[i].id) {
++              state->d_fd = -1;
+               return (0);
++      }
+       memset(sess, 0, sizeof(struct session_op));
+       if ((state->d_fd = get_dev_crypto()) < 0)
+               return (0);
+-      sess->key = (char *)key;
++      sess->key = (void*)key;
+       sess->keylen = ctx->key_len;
+       sess->cipher = cipher;
+       if (ioctl(state->d_fd, CIOCGSESSION, sess) == -1) {
+-              close(state->d_fd);
++              put_dev_crypto(state->d_fd);
+               state->d_fd = -1;
+               return (0);
+       }
+@@ -494,7 +489,7 @@
+       } else {
+               ret = 1;
+       }
+-      close(state->d_fd);
++      put_dev_crypto(state->d_fd);
+       state->d_fd = -1;
+       return (ret);
+@@ -505,6 +500,20 @@
+  * gets called when libcrypto requests a cipher NID.
+  */
++/* RC4 */
++const EVP_CIPHER cryptodev_rc4 = {
++      NID_rc4,
++      1, 16, 0,
++      EVP_CIPH_VARIABLE_LENGTH,
++      cryptodev_init_key,
++      cryptodev_cipher,
++      cryptodev_cleanup,
++      sizeof(struct dev_crypto_state),
++      NULL,
++      NULL,
++      NULL
++};
++
+ /* DES CBC EVP */
+ const EVP_CIPHER cryptodev_des_cbc = {
+       NID_des_cbc,
+@@ -572,6 +581,32 @@
+       NULL
+ };
++const EVP_CIPHER cryptodev_aes_192_cbc = {
++      NID_aes_192_cbc,
++      16, 24, 16,
++      EVP_CIPH_CBC_MODE,
++      cryptodev_init_key,
++      cryptodev_cipher,
++      cryptodev_cleanup,
++      sizeof(struct dev_crypto_state),
++      EVP_CIPHER_set_asn1_iv,
++      EVP_CIPHER_get_asn1_iv,
++      NULL
++};
++
++const EVP_CIPHER cryptodev_aes_256_cbc = {
++      NID_aes_256_cbc,
++      16, 32, 16,
++      EVP_CIPH_CBC_MODE,
++      cryptodev_init_key,
++      cryptodev_cipher,
++      cryptodev_cleanup,
++      sizeof(struct dev_crypto_state),
++      EVP_CIPHER_set_asn1_iv,
++      EVP_CIPHER_get_asn1_iv,
++      NULL
++};
++
+ /*
+  * Registered by the ENGINE when used to find out how to deal with
+  * a particular NID in the ENGINE. this says what we'll do at the
+@@ -585,6 +620,9 @@
+               return (cryptodev_usable_ciphers(nids));
+       switch (nid) {
++      case NID_rc4:
++              *cipher = &cryptodev_rc4;
++              break;
+       case NID_des_ede3_cbc:
+               *cipher = &cryptodev_3des_cbc;
+               break;
+@@ -600,6 +638,12 @@
+       case NID_aes_128_cbc:
+               *cipher = &cryptodev_aes_cbc;
+               break;
++      case NID_aes_192_cbc:
++              *cipher = &cryptodev_aes_192_cbc;
++              break;
++      case NID_aes_256_cbc:
++              *cipher = &cryptodev_aes_256_cbc;
++              break;
+       default:
+               *cipher = NULL;
+               break;
+@@ -607,6 +651,286 @@
+       return (*cipher != NULL);
+ }
++
++#ifdef USE_CRYPTODEV_DIGESTS
++
++/* convert digest type to cryptodev */
++static int
++digest_nid_to_cryptodev(int nid)
++{
++      int i;
++
++      for (i = 0; digests[i].id; i++)
++              if (digests[i].nid == nid)
++                      return (digests[i].id);
++      return (0);
++}
++
++
++static int cryptodev_digest_init(EVP_MD_CTX *ctx)
++{
++      struct dev_crypto_state *state = ctx->md_data;
++      struct session_op *sess = &state->d_sess;
++      int digest;
++
++      if ((digest = digest_nid_to_cryptodev(ctx->digest->type)) == NID_undef){
++              printf("cryptodev_digest_init: Can't get digest \n");
++              return (0);
++      }
++      memset(state, 0, sizeof(struct dev_crypto_state));
++
++      if ((state->d_fd = get_dev_crypto()) < 0) {
++              printf("cryptodev_digest_init: Can't get Dev \n");
++              return (0);
++      }
++
++      sess->mackey = NULL;
++      sess->mackeylen = 0;
++      sess->mac = digest;
++
++      if (ioctl(state->d_fd, CIOCGSESSION, sess) < 0) {
++              put_dev_crypto(state->d_fd);
++              state->d_fd = -1;
++              printf("cryptodev_digest_init: Open session failed\n");
++              return (0);
++      }
++
++      return (1);
++}
++
++static int cryptodev_digest_update(EVP_MD_CTX *ctx, const void *data,
++              size_t count)
++{
++      struct dev_crypto_state *state = ctx->md_data;
++      struct crypt_op cryp;
++      struct session_op *sess = &state->d_sess;
++
++      if (!data || state->d_fd < 0) {
++              printf("cryptodev_digest_update: illegal inputs \n");
++              return (0);
++      }
++
++      if (!count) {
++              return (1);
++      }
++
++      if (!(ctx->flags & EVP_MD_CTX_FLAG_ONESHOT)) {
++              /* if application doesn't support one buffer */
++              state->mac_data = OPENSSL_realloc(state->mac_data, state->mac_len + count);
++
++              if (!state->mac_data) {
++                      printf("cryptodev_digest_update: realloc failed\n");
++                      return (0);
++              }
++
++              memcpy(state->mac_data + state->mac_len, data, count);
++              state->mac_len += count;
++      
++              return (1);
++      }
++
++      memset(&cryp, 0, sizeof(cryp));
++
++      cryp.ses = sess->ses;
++      cryp.flags = 0;
++      cryp.len = count;
++      cryp.src = (void*) data;
++      cryp.dst = NULL;
++      cryp.mac = (void*) state->digest_res;
++      if (ioctl(state->d_fd, CIOCCRYPT, &cryp) < 0) {
++              printf("cryptodev_digest_update: digest failed\n");
++              return (0);
++      }
++      return (1);
++}
++
++
++static int cryptodev_digest_final(EVP_MD_CTX *ctx, unsigned char *md)
++{
++      struct crypt_op cryp;
++      struct dev_crypto_state *state = ctx->md_data;
++      struct session_op *sess = &state->d_sess;
++
++      if (!md || state->d_fd < 0) {
++              printf("cryptodev_digest_final: illegal input\n");
++              return(0);
++      }
++
++      if (! (ctx->flags & EVP_MD_CTX_FLAG_ONESHOT) ) {
++              /* if application doesn't support one buffer */
++              memset(&cryp, 0, sizeof(cryp));
++              cryp.ses = sess->ses;
++              cryp.flags = 0;
++              cryp.len = state->mac_len;
++              cryp.src = state->mac_data;
++              cryp.dst = NULL;
++              cryp.mac = (void*)md;
++              if (ioctl(state->d_fd, CIOCCRYPT, &cryp) < 0) {
++                      printf("cryptodev_digest_final: digest failed\n");
++                      return (0);
++              }
++
++              return 1;
++      }
++
++      memcpy(md, state->digest_res, ctx->digest->md_size);
++
++      return 1;
++}
++
++
++static int cryptodev_digest_cleanup(EVP_MD_CTX *ctx)
++{
++      int ret = 1;
++      struct dev_crypto_state *state = ctx->md_data;
++      struct session_op *sess = &state->d_sess;
++
++      if (state == NULL)
++        return 0;
++
++      if (state->d_fd < 0) {
++              printf("cryptodev_digest_cleanup: illegal input\n");
++              return (0);
++      }
++
++      if (state->mac_data) {
++              OPENSSL_free(state->mac_data);
++              state->mac_data = NULL;
++              state->mac_len = 0;
++      }
++
++      if (ioctl(state->d_fd, CIOCFSESSION, &sess->ses) < 0) {
++              printf("cryptodev_digest_cleanup: failed to close session\n");
++              ret = 0;
++      } else {
++              ret = 1;
++      }
++      put_dev_crypto(state->d_fd);    
++      state->d_fd = -1;
++
++      return (ret);
++}
++
++static int cryptodev_digest_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from)
++{
++      struct dev_crypto_state *fstate = from->md_data;
++      struct dev_crypto_state *dstate = to->md_data;
++      struct session_op *sess;
++      int digest;
++
++      if (dstate == NULL || fstate == NULL)
++        return 1;
++
++              memcpy(dstate, fstate, sizeof(struct dev_crypto_state));
++
++      sess = &dstate->d_sess;
++
++      digest = digest_nid_to_cryptodev(to->digest->type);
++
++      sess->mackey = NULL;
++      sess->mackeylen = 0;
++      sess->mac = digest;
++
++      dstate->d_fd = get_dev_crypto();
++
++      if (ioctl(dstate->d_fd, CIOCGSESSION, sess) < 0) {
++              put_dev_crypto(dstate->d_fd);
++              dstate->d_fd = -1;
++              printf("cryptodev_digest_init: Open session failed\n");
++              return (0);
++      }
++
++      if (fstate->mac_len != 0) {
++              if (fstate->mac_data != NULL)
++                      {
++                      dstate->mac_data = OPENSSL_malloc(fstate->mac_len);
++                      memcpy(dstate->mac_data, fstate->mac_data, fstate->mac_len);
++                      dstate->mac_len = fstate->mac_len;
++                      }
++      }
++
++      return 1;
++}
++
++
++static const EVP_MD cryptodev_sha1 = {
++      NID_sha1,
++      NID_sha1WithRSAEncryption,
++      SHA_DIGEST_LENGTH, 
++      EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT|EVP_MD_FLAG_ONESHOT,
++      cryptodev_digest_init,
++      cryptodev_digest_update,
++      cryptodev_digest_final,
++      cryptodev_digest_copy,
++      cryptodev_digest_cleanup,
++      EVP_PKEY_RSA_method,
++      SHA_CBLOCK,
++      sizeof(EVP_MD *)+sizeof(struct dev_crypto_state),
++};
++
++static const EVP_MD cryptodev_sha256 = {
++      NID_sha256,
++      NID_sha256WithRSAEncryption,
++      SHA256_DIGEST_LENGTH, 
++      EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT|EVP_MD_FLAG_ONESHOT,
++      cryptodev_digest_init,
++      cryptodev_digest_update,
++      cryptodev_digest_final,
++      cryptodev_digest_copy,
++      cryptodev_digest_cleanup,
++      EVP_PKEY_RSA_method,
++      SHA256_CBLOCK,
++      sizeof(EVP_MD *)+sizeof(struct dev_crypto_state),
++};
++
++static const EVP_MD cryptodev_sha384 = {
++      NID_sha384,
++      NID_sha384WithRSAEncryption, 
++      SHA384_DIGEST_LENGTH, 
++      EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT|EVP_MD_FLAG_ONESHOT,
++      cryptodev_digest_init,
++      cryptodev_digest_update,
++      cryptodev_digest_final,
++      cryptodev_digest_copy,
++      cryptodev_digest_cleanup,
++      EVP_PKEY_RSA_method,
++      SHA512_CBLOCK,
++      sizeof(EVP_MD *)+sizeof(struct dev_crypto_state),
++};
++
++static const EVP_MD cryptodev_sha512 = {
++      NID_sha512,
++      NID_sha512WithRSAEncryption, 
++      SHA512_DIGEST_LENGTH, 
++      EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT|EVP_MD_FLAG_ONESHOT,
++      cryptodev_digest_init,
++      cryptodev_digest_update,
++      cryptodev_digest_final,
++      cryptodev_digest_copy,
++      cryptodev_digest_cleanup,
++      EVP_PKEY_RSA_method,
++      SHA512_CBLOCK,
++      sizeof(EVP_MD *)+sizeof(struct dev_crypto_state),
++};
++
++static const EVP_MD cryptodev_md5 = {
++      NID_md5,
++      NID_md5WithRSAEncryption, 
++      16 /* MD5_DIGEST_LENGTH */, 
++      EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT|EVP_MD_FLAG_ONESHOT,
++      cryptodev_digest_init,
++      cryptodev_digest_update,
++      cryptodev_digest_final,
++      cryptodev_digest_copy,
++      cryptodev_digest_cleanup,
++      EVP_PKEY_RSA_method,
++      64 /* MD5_CBLOCK */,
++      sizeof(EVP_MD *)+sizeof(struct dev_crypto_state),
++};
++
++#endif /* USE_CRYPTODEV_DIGESTS */
++
++
+ static int
+ cryptodev_engine_digests(ENGINE *e, const EVP_MD **digest,
+     const int **nids, int nid)
+@@ -615,10 +939,24 @@
+               return (cryptodev_usable_digests(nids));
+       switch (nid) {
++#ifdef USE_CRYPTODEV_DIGESTS
+       case NID_md5:
+-              *digest = NULL; /* need to make a clean md5 critter */
++              *digest = &cryptodev_md5; 
+               break;
++      case NID_sha1:
++              *digest = &cryptodev_sha1;
++              break;
++      case NID_sha256:
++              *digest = &cryptodev_sha256;
++              break;
++      case NID_sha384:
++              *digest = &cryptodev_sha384;
++              break;
++      case NID_sha512:
++              *digest = &cryptodev_sha512;
++              break;
+       default:
++#endif /* USE_CRYPTODEV_DIGESTS */
+               *digest = NULL;
+               break;
+       }
+@@ -646,8 +984,9 @@
+       b = malloc(bytes);
+       if (b == NULL)
+               return (1);
++      memset(b, 0, bytes);
+-      crp->crp_p = (char *)b;
++      crp->crp_p = (void*) b;
+       crp->crp_nbits = bits;
+       for (i = 0, j = 0; i < a->top; i++) {
+@@ -690,7 +1029,7 @@
+ {
+       int i;
+-      for (i = 0; i <= kop->crk_iparams + kop->crk_oparams; 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);
+               kop->crk_param[i].crp_p = NULL;
+@@ -776,8 +1115,9 @@
+ cryptodev_rsa_nocrt_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
+ {
+       int r;
+-
++      ctx = BN_CTX_new();
+       r = cryptodev_bn_mod_exp(r0, I, rsa->d, rsa->n, ctx, NULL);
++      BN_CTX_free(ctx);
+       return (r);
+ }
+@@ -899,7 +1239,7 @@
+       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]))
+               goto err;
+@@ -939,7 +1279,7 @@
+       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]))
+               goto err;
+@@ -1017,7 +1357,7 @@
+               goto err;
+       kop.crk_iparams = 3;
+-      kop.crk_param[3].crp_p = (char *)key;
++      kop.crk_param[3].crp_p = (void*) key;
+       kop.crk_param[3].crp_nbits = keylen * 8;
+       kop.crk_oparams = 1;
+@@ -1048,7 +1388,7 @@
+  * but I expect we'll want some options soon.
+  */
+ static int
+-cryptodev_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
++cryptodev_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
+ {
+ #ifdef HAVE_SYSLOG_R
+       struct syslog_data sd = SYSLOG_DATA_INIT;
+@@ -1084,14 +1424,14 @@
+        * find out what asymmetric crypto algorithms we support
+        */
+       if (ioctl(fd, CIOCASYMFEAT, &cryptodev_asymfeat) == -1) {
+-              close(fd);
++              put_dev_crypto(fd);
+               ENGINE_free(engine);
+               return;
+       }
+-      close(fd);
++      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_ciphers(engine, cryptodev_engine_ciphers) ||
+           !ENGINE_set_digests(engine, cryptodev_engine_digests) ||
+           !ENGINE_set_ctrl_function(engine, cryptodev_ctrl) ||
+diff -Naur openssl-0.9.8u.org/crypto/engine/engine.h openssl-0.9.8u/crypto/engine/engine.h
+--- openssl-0.9.8u.org/crypto/engine/engine.h  2010-02-09 15:18:15.000000000 +0100
++++ openssl-0.9.8u/crypto/engine/engine.h      2012-03-27 14:05:15.000000000 +0200
+@@ -705,9 +705,7 @@
+  * values. */
+ void *ENGINE_get_static_state(void);
+-#if defined(__OpenBSD__) || defined(__FreeBSD__)
+ void ENGINE_setup_bsd_cryptodev(void);
+-#endif
+ /* BEGIN ERROR CODES */
+ /* The following lines are auto generated by the script mkerr.pl. Any changes
+diff -Naur openssl-0.9.8u.org/crypto/evp/c_all.c openssl-0.9.8u/crypto/evp/c_all.c
+--- openssl-0.9.8u.org/crypto/evp/c_all.c      2004-08-29 18:36:04.000000000 +0200
++++ openssl-0.9.8u/crypto/evp/c_all.c  2012-03-27 14:05:15.000000000 +0200
+@@ -83,8 +83,6 @@
+       OpenSSL_add_all_ciphers();
+       OpenSSL_add_all_digests();
+ #ifndef OPENSSL_NO_ENGINE
+-# if defined(__OpenBSD__) || defined(__FreeBSD__)
+       ENGINE_setup_bsd_cryptodev();
+-# endif
+ #endif
+       }