Include correctly.
[openssl.git] / crypto / engine / eng_cryptodev.c
index d30a58d332d4e8514449517758d6a14abd607f1a..71e6fa5de86349b1e97ff48620b332818f9781ab 100644 (file)
@@ -32,7 +32,7 @@
 #include <openssl/bn.h>
 
 #if (defined(__unix__) || defined(unix)) && !defined(USG) && \
-       (defined(OpenBSD) || defined(__FreeBSD_version))
+       (defined(OpenBSD) || defined(__FreeBSD__))
 #include <sys/param.h>
 # if (OpenBSD >= 200112) || ((__FreeBSD_version >= 470101 && __FreeBSD_version < 500000) || __FreeBSD_version >= 500041)
 #  define HAVE_CRYPTODEV
@@ -55,6 +55,10 @@ ENGINE_load_cryptodev(void)
  
 #include <sys/types.h>
 #include <crypto/cryptodev.h>
+#include <openssl/dh.h>
+#include <openssl/dsa.h>
+#include <openssl/err.h>
+#include <openssl/rsa.h>
 #include <sys/ioctl.h>
 #include <errno.h>
 #include <stdio.h>
@@ -70,13 +74,11 @@ struct dev_crypto_state {
        int d_fd;
 
 #ifdef USE_CRYPTODEV_DIGESTS
-       char dummy_mac_key[20];
+       char dummy_mac_key[HASH_MAX_LEN];
 
-       unsigned char digest_res[20];
+       unsigned char digest_res[HASH_MAX_LEN];
        char *mac_data;
        int mac_len;
-
-       int copy;
 #endif
 };
 
@@ -86,11 +88,13 @@ static int get_asym_dev_crypto(void);
 static int open_dev_crypto(void);
 static int get_dev_crypto(void);
 static int get_cryptodev_ciphers(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);
@@ -124,7 +128,7 @@ static int cryptodev_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a,
 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[] = {
@@ -149,6 +153,7 @@ static struct {
        { 0,                            NID_undef,              0,       0, },
 };
 
+#ifdef USE_CRYPTODEV_DIGESTS
 static struct {
        int     id;
        int     nid;
@@ -163,6 +168,7 @@ static struct {
        { CRYPTO_SHA1,                  NID_sha1,               20},
        { 0,                            NID_undef,              0},
 };
+#endif
 
 /*
  * Return a fd if /dev/crypto seems usable, 0 otherwise.
@@ -192,6 +198,7 @@ get_dev_crypto(void)
 
        if ((fd = open_dev_crypto()) == -1)
                return (-1);
+#ifndef CRIOGET_NOT_NEEDED
        if (ioctl(fd, CRIOGET, &retfd) == -1)
                return (-1);
 
@@ -200,9 +207,19 @@ get_dev_crypto(void)
                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)
@@ -244,7 +261,7 @@ get_cryptodev_ciphers(const int **cnids)
                    ioctl(fd, CIOCFSESSION, &sess.ses) != -1)
                        nids[count++] = ciphers[i].nid;
        }
-       close(fd);
+       put_dev_crypto(fd);
 
        if (count > 0)
                *cnids = nids;
@@ -253,6 +270,7 @@ get_cryptodev_ciphers(const int **cnids)
        return (count);
 }
 
+#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!
@@ -282,7 +300,7 @@ get_cryptodev_digests(const int **cnids)
                    ioctl(fd, CIOCFSESSION, &sess.ses) != -1)
                        nids[count++] = digests[i].nid;
        }
-       close(fd);
+       put_dev_crypto(fd);
 
        if (count > 0)
                *cnids = nids;
@@ -290,6 +308,7 @@ get_cryptodev_digests(const int **cnids)
                *cnids = NULL;
        return (count);
 }
+#endif  /* 0 */
 
 /*
  * Find the useable ciphers|digests from dev/crypto - this is the first
@@ -343,12 +362,12 @@ 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)
 {
        struct crypt_op cryp;
        struct dev_crypto_state *state = ctx->cipher_data;
        struct session_op *sess = &state->d_sess;
-       void *iiv;
+       const void *iiv;
        unsigned char save_iv[EVP_MAX_IV_LENGTH];
 
        if (state->d_fd < 0)
@@ -372,7 +391,7 @@ cryptodev_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
        if (ctx->cipher->iv_len) {
                cryp.iv = (caddr_t) ctx->iv;
                if (!ctx->encrypt) {
-                       iiv = (void *) in + inl - ctx->cipher->iv_len;
+                       iiv = in + inl - ctx->cipher->iv_len;
                        memcpy(save_iv, iiv, ctx->cipher->iv_len);
                }
        } else
@@ -387,7 +406,7 @@ cryptodev_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
 
        if (ctx->cipher->iv_len) {
                if (ctx->encrypt)
-                       iiv = (void *) out + inl - ctx->cipher->iv_len;
+                       iiv = out + inl - ctx->cipher->iv_len;
                else
                        iiv = save_iv;
                memcpy(ctx->iv, iiv, ctx->cipher->iv_len);
@@ -401,7 +420,7 @@ cryptodev_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
 {
        struct dev_crypto_state *state = ctx->cipher_data;
        struct session_op *sess = &state->d_sess;
-       int cipher, i;
+       int cipher = -1, i;
 
        for (i = 0; ciphers[i].id; i++)
                if (ctx->cipher->nid == ciphers[i].nid &&
@@ -421,12 +440,12 @@ cryptodev_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
        if ((state->d_fd = get_dev_crypto()) < 0)
                return (0);
 
-       sess->key = (unsigned char *)key;
+       sess->key = (caddr_t)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);
        }
@@ -463,7 +482,7 @@ cryptodev_cleanup(EVP_CIPHER_CTX *ctx)
        } else {
                ret = 1;
        }
-       close(state->d_fd);
+       put_dev_crypto(state->d_fd);
        state->d_fd = -1;
 
        return (ret);
@@ -676,7 +695,7 @@ static int cryptodev_digest_init(EVP_MD_CTX *ctx)
        sess->mac = digest;
 
        if (ioctl(state->d_fd, CIOCGSESSION, sess) < 0) {
-               close(state->d_fd);
+               put_dev_crypto(state->d_fd);
                state->d_fd = -1;
                printf("cryptodev_digest_init: Open session failed\n");
                return (0);
@@ -723,7 +742,7 @@ static int cryptodev_digest_update(EVP_MD_CTX *ctx, const void *data,
        cryp.len = count;
        cryp.src = (caddr_t) data;
        cryp.dst = NULL;
-       cryp.mac = state->digest_res;
+       cryp.mac = (caddr_t) state->digest_res;
        if (ioctl(state->d_fd, CIOCCRYPT, &cryp) < 0) {
                printf("cryptodev_digest_update: digest failed\n");
                return (0);
@@ -748,14 +767,12 @@ static int cryptodev_digest_final(EVP_MD_CTX *ctx, unsigned char *md)
        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 = md;
-
+               cryp.mac = (caddr_t)md;
                if (ioctl(state->d_fd, CIOCCRYPT, &cryp) < 0) {
                        printf("cryptodev_digest_final: digest failed\n");
                        return (0);
@@ -776,6 +793,9 @@ static int cryptodev_digest_cleanup(EVP_MD_CTX *ctx)
        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);
@@ -787,16 +807,13 @@ static int cryptodev_digest_cleanup(EVP_MD_CTX *ctx)
                state->mac_len = 0;
        }
 
-       if (state->copy)
-               return 1;
-
        if (ioctl(state->d_fd, CIOCFSESSION, &sess->ses) < 0) {
                printf("cryptodev_digest_cleanup: failed to close session\n");
                ret = 0;
        } else {
                ret = 1;
        }
-       close(state->d_fd);     
+       put_dev_crypto(state->d_fd);    
        state->d_fd = -1;
 
        return (ret);
@@ -806,15 +823,39 @@ 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;
 
-       memcpy(dstate, fstate, sizeof(struct dev_crypto_state));
+       if (dstate == NULL || fstate == NULL)
+         return 1;
 
-       if (fstate->mac_len != 0) {
-               dstate->mac_data = OPENSSL_malloc(fstate->mac_len);
-               memcpy(dstate->mac_data, fstate->mac_data, fstate->mac_len);
+               memcpy(dstate, fstate, sizeof(struct dev_crypto_state));
+
+       sess = &dstate->d_sess;
+
+       digest = digest_nid_to_cryptodev(to->digest->type);
+
+       sess->mackey = dstate->dummy_mac_key;
+       sess->mackeylen = digest_key_length(to->digest->type);
+       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);
        }
 
-       dstate->copy = 1;
+       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;
 }
@@ -899,7 +940,7 @@ bn2crparam(const BIGNUM *a, struct crparam *crp)
                return (1);
        memset(b, 0, bytes);
 
-       crp->crp_p = b;
+       crp->crp_p = (caddr_t) b;
        crp->crp_nbits = bits;
 
        for (i = 0, j = 0; i < a->top; i++) {
@@ -1007,10 +1048,18 @@ cryptodev_bn_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
                goto err;
        kop.crk_iparams = 3;
 
-       if (cryptodev_asym(&kop, BN_num_bytes(m), r, 0, NULL) == -1) {
+       if (cryptodev_asym(&kop, BN_num_bytes(m), r, 0, NULL)) {
                const RSA_METHOD *meth = RSA_PKCS1_SSLeay();
+               printf("OCF asym process failed, Running in software\n");
+               ret = meth->bn_mod_exp(r, a, p, m, ctx, in_mont);
+
+       } else if (ECANCELED == kop.crk_status) {
+               const RSA_METHOD *meth = RSA_PKCS1_SSLeay();
+               printf("OCF hardware operation cancelled. Running in Software\n");
                ret = meth->bn_mod_exp(r, a, p, m, ctx, in_mont);
        }
+       /* else cryptodev operation worked ok ==> ret = 1*/
+
 err:
        zapparams(&kop);
        return (ret);
@@ -1054,10 +1103,18 @@ cryptodev_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
                goto err;
        kop.crk_iparams = 6;
 
-       if (cryptodev_asym(&kop, BN_num_bytes(rsa->n), r0, 0, NULL) == -1) {
+       if (cryptodev_asym(&kop, BN_num_bytes(rsa->n), r0, 0, NULL)) {
                const RSA_METHOD *meth = RSA_PKCS1_SSLeay();
+               printf("OCF asym process failed, running in Software\n");
+               ret = (*meth->rsa_mod_exp)(r0, I, rsa, ctx);
+
+       } else if (ECANCELED == kop.crk_status) {
+               const RSA_METHOD *meth = RSA_PKCS1_SSLeay();
+               printf("OCF hardware operation cancelled. Running in Software\n");
                ret = (*meth->rsa_mod_exp)(r0, I, rsa, ctx);
        }
+       /* else cryptodev operation worked ok ==> ret = 1*/
+
 err:
        zapparams(&kop);
        return (ret);
@@ -1193,7 +1250,8 @@ cryptodev_dsa_verify(const unsigned char *dgst, int dlen,
        kop.crk_iparams = 7;
 
        if (cryptodev_asym(&kop, 0, NULL, 0, NULL) == 0) {
-               dsaret = kop.crk_status;
+/*OCF success value is 0, if not zero, change dsaret to fail*/
+               if(0 != kop.crk_status) dsaret  = 0;
        } else {
                const DSA_METHOD *meth = DSA_OpenSSL();
 
@@ -1253,7 +1311,7 @@ cryptodev_dh_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
                goto err;
        kop.crk_iparams = 3;
 
-       kop.crk_param[3].crp_p = key;
+       kop.crk_param[3].crp_p = (caddr_t) key;
        kop.crk_param[3].crp_nbits = keylen * 8;
        kop.crk_oparams = 1;
 
@@ -1284,7 +1342,7 @@ static DH_METHOD cryptodev_dh = {
  * 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;
@@ -1320,11 +1378,11 @@ ENGINE_load_cryptodev(void)
         * 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") ||