Adapt for BSD cryptodev.h differences
authorRichard Levitte <levitte@openssl.org>
Tue, 18 Apr 2017 06:51:51 +0000 (08:51 +0200)
committerRichard Levitte <levitte@openssl.org>
Wed, 28 Jun 2017 10:54:33 +0000 (12:54 +0200)
The BSD cryptodev.h doesn't have things like COP_FLAG_WRITE_IV and
COP_FLAG_UPDATE.  In that case, we need to implement that
functionality ourselves.

Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/3744)

crypto/engine/eng_devcrypto.c
crypto/engine/eng_err.c
crypto/err/openssl.txt
include/openssl/engineerr.h

index 9b1d8ab409259bbcc50cae0fb3ff67fb76a12a37..ed3335e8972298af7507fa16669f9f6822911c1d 100644 (file)
@@ -161,6 +161,9 @@ static int cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
     struct cipher_ctx *cipher_ctx =
         (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
     struct crypt_op cryp;
+#if !defined(COP_FLAG_WRITE_IV)
+    unsigned char saved_iv[EVP_MAX_IV_LENGTH];
+#endif
 
     memset(&cryp, 0, sizeof(cryp));
     cryp.ses = cipher_ctx->sess.ses;
@@ -169,12 +172,39 @@ static int cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
     cryp.dst = (void *)out;
     cryp.iv = (void *)EVP_CIPHER_CTX_iv_noconst(ctx);
     cryp.op = cipher_ctx->op;
+#if !defined(COP_FLAG_WRITE_IV)
+    cryp.flags = 0;
+
+    if (EVP_CIPHER_CTX_iv_length(ctx) > 0) {
+        assert(inl >= EVP_CIPHER_CTX_iv_length(ctx));
+        if (!EVP_CIPHER_CTX_encrypting(ctx)) {
+            unsigned char *ivptr = in + inl - EVP_CIPHER_CTX_iv_length(ctx);
+
+            memcpy(saved_iv, ivptr, EVP_CIPHER_CTX_iv_length(ctx));
+        }
+    }
+#else
     cryp.flags = COP_FLAG_WRITE_IV;
+#endif
+
     if (ioctl(cipher_ctx->cfd, CIOCCRYPT, &cryp) < 0) {
         SYSerr(SYS_F_IOCTL, errno);
         return 0;
     }
 
+#if !defined(COP_FLAG_WRITE_IV)
+    if (EVP_CIPHER_CTX_iv_length(ctx) > 0) {
+        unsigned char *ivptr = saved_iv;
+
+        assert(inl >= EVP_CIPHER_CTX_iv_length(ctx));
+        if (!EVP_CIPHER_CTX_encrypting(ctx))
+            ivptr = out + inl - EVP_CIPHER_CTX_iv_length(ctx);
+
+        memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), ivptr,
+               EVP_CIPHER_CTX_iv_length(ctx));
+    }
+#endif
+
     return 1;
 }
 
@@ -298,6 +328,14 @@ static int devcrypto_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
     return *cipher != NULL;
 }
 
+/*
+ * We only support digests if the cryptodev implementation supports multiple
+ * data updates.  Otherwise, we would be forced to maintain a cache, which is
+ * perilous if there's a lot of data coming in (if someone wants to checksum
+ * an OpenSSL tarball, for example).
+ */
+#if defined(COP_FLAG_UPDATE) && defined(COP_FLAG_FINAL)
+
 /******************************************************************************
  *
  * Digests
@@ -395,18 +433,30 @@ static int digest_init(EVP_MD_CTX *ctx)
     return 1;
 }
 
+static int digest_op(struct digest_ctx *ctx, const void *src, size_t srclen,
+                     void *res, unsigned int flags)
+{
+    struct crypt_op cryp;
+
+    memset(&cryp, 0, sizeof(cryp));
+    cryp.ses = ctx->sess.ses;
+    cryp.len = srclen;
+    cryp.src = (void *)src;
+    cryp.dst = NULL;
+    cryp.mac = res;
+    cryp.flags = flags;
+    return ioctl(ctx->cfd, CIOCCRYPT, &cryp);
+}
+
 static int digest_update(EVP_MD_CTX *ctx, const void *data, size_t count)
 {
     struct digest_ctx *digest_ctx =
         (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
-    struct crypt_op cryp;
 
-    memset(&cryp, 0, sizeof(cryp));
-    cryp.ses = digest_ctx->sess.ses;
-    cryp.len = count;
-    cryp.src = (void *)data;
-    cryp.flags = COP_FLAG_UPDATE;
-    if (ioctl(digest_ctx->cfd, CIOCCRYPT, &cryp) < 0) {
+    if (count == 0)
+        return 1;
+
+    if (digest_op(digest_ctx, data, count, NULL, COP_FLAG_UPDATE) < 0) {
         SYSerr(SYS_F_IOCTL, errno);
         return 0;
     }
@@ -418,15 +468,8 @@ static int digest_final(EVP_MD_CTX *ctx, unsigned char *md)
 {
     struct digest_ctx *digest_ctx =
         (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
-    struct crypt_op cryp;
 
-    memset(&cryp, 0, sizeof(cryp));
-    cryp.ses = digest_ctx->sess.ses;
-    cryp.len = 0;
-    cryp.src = NULL;
-    cryp.mac = (void *)md;
-    cryp.flags = COP_FLAG_FINAL;
-    if (ioctl(digest_ctx->cfd, CIOCCRYPT, &cryp) < 0) {
+    if (digest_op(digest_ctx, NULL, 0, md, COP_FLAG_FINAL) < 0) {
         SYSerr(SYS_F_IOCTL, errno);
         return 0;
     }
@@ -545,6 +588,8 @@ static int devcrypto_digests(ENGINE *e, const EVP_MD **digest,
     return *digest != NULL;
 }
 
+#endif
+
 /******************************************************************************
  *
  * LOAD / UNLOAD
@@ -554,7 +599,9 @@ static int devcrypto_digests(ENGINE *e, const EVP_MD **digest,
 static int devcrypto_unload(ENGINE *e)
 {
     destroy_all_cipher_methods();
+#if defined(COP_FLAG_UPDATE) && defined(COP_FLAG_FINAL)
     destroy_all_digest_methods();
+#endif
     return 1;
 }
 /*
@@ -572,7 +619,9 @@ void engine_load_devcrypto_int()
     }
 
     prepare_cipher_methods();
+#if defined(COP_FLAG_UPDATE) && defined(COP_FLAG_FINAL)
     prepare_digest_methods();
+#endif
 
     if ((e = ENGINE_new()) == NULL)
         return;
@@ -595,7 +644,10 @@ void engine_load_devcrypto_int()
 # endif
 #endif
         || !ENGINE_set_ciphers(e, devcrypto_ciphers)
-        || !ENGINE_set_digests(e, devcrypto_digests)) {
+#if defined(COP_FLAG_UPDATE) && defined(COP_FLAG_FINAL)
+        || !ENGINE_set_digests(e, devcrypto_digests)
+#endif
+        ) {
         ENGINE_free(e);
         return;
     }
index ec783bec3769504880e6fc79de19099a370033f9..5f24e998da354ecefc7360b92b089c00564fec96 100644 (file)
@@ -14,6 +14,7 @@
 #ifndef OPENSSL_NO_ERR
 
 static const ERR_STRING_DATA ENGINE_str_functs[] = {
+    {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_DIGEST_UPDATE, 0), "digest_update"},
     {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_DYNAMIC_CTRL, 0), "dynamic_ctrl"},
     {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_DYNAMIC_GET_DATA_CTX, 0),
      "dynamic_get_data_ctx"},
index 813ca74c009e170eb88712bab209f35d7af63c76..d9fa3d33091eefd789f477f4f292b18be516d6b7 100644 (file)
@@ -589,6 +589,7 @@ EC_F_PKEY_EC_DERIVE:217:pkey_ec_derive
 EC_F_PKEY_EC_KEYGEN:199:pkey_ec_keygen
 EC_F_PKEY_EC_PARAMGEN:219:pkey_ec_paramgen
 EC_F_PKEY_EC_SIGN:218:pkey_ec_sign
+ENGINE_F_DIGEST_UPDATE:198:digest_update
 ENGINE_F_DYNAMIC_CTRL:180:dynamic_ctrl
 ENGINE_F_DYNAMIC_GET_DATA_CTX:181:dynamic_get_data_ctx
 ENGINE_F_DYNAMIC_LOAD:182:dynamic_load
index 2f3588733c275626e7bca971f5853667f961ebf2..c3e3844d07746530e5a0a1a55a67452c17b6db7e 100644 (file)
@@ -22,6 +22,7 @@ int ERR_load_ENGINE_strings(void);
 /*
  * ENGINE function codes.
  */
+# define ENGINE_F_DIGEST_UPDATE                           198
 # define ENGINE_F_DYNAMIC_CTRL                            180
 # define ENGINE_F_DYNAMIC_GET_DATA_CTX                    181
 # define ENGINE_F_DYNAMIC_LOAD                            182