From: Michael Clark <michaeljclark@mac.com>
To: git@vger.kernel.org
Cc: Michael Clark <michaeljclark@mac.com>
Subject: [PATCH 5/6] Add OpenSSL EVP interface for SHA-3 and SHA-512 algorithms
Date: Sun, 22 Dec 2019 19:48:08 +1300 [thread overview]
Message-ID: <20191222064809.35667-6-michaeljclark@mac.com> (raw)
In-Reply-To: <20191222064809.35667-1-michaeljclark@mac.com>
- Add OpenSSL EVP context wrapper and interface.
- Add configuration machinery to select SHA-3 and SHA-512 impls
from OpenSSL using the EVP interface.
- Use `make OPENSSL_EVP=1` to build using the OpenSSL EVP impls
for all SHA-3 and SHA-512 algos.
---
Makefile | 9 +++-
hash.h | 6 +++
sha/sha_evp/sha_evp.c | 99 +++++++++++++++++++++++++++++++++++++++++++
sha/sha_evp/sha_evp.h | 51 ++++++++++++++++++++++
4 files changed, 164 insertions(+), 1 deletion(-)
create mode 100644 sha/sha_evp/sha_evp.c
create mode 100644 sha/sha_evp/sha_evp.h
diff --git a/Makefile b/Makefile
index 6bf9900291cb..e065630e24fa 100644
--- a/Makefile
+++ b/Makefile
@@ -189,6 +189,8 @@ all::
#
# Define OPENSSL_SHA256 to use the SHA-256 routines in OpenSSL.
#
+# Define OPENSSL_EVP to use the SHA-3 and SHA-512 routines in OpenSSL.
+#
# Define NEEDS_CRYPTO_WITH_SSL if you need -lcrypto when using -lssl (Darwin).
#
# Define NEEDS_SSL_WITH_CRYPTO if you need -lssl when using -lcrypto (Darwin).
@@ -1716,6 +1718,11 @@ else
endif
endif
+ifdef OPENSSL_EVP
+ EXTLIBS += $(LIB_4_CRYPTO)
+ BASIC_CFLAGS += -DSHA_EVP_OPENSSL
+ LIB_OBJS += sha/sha_evp/sha_evp.o
+else
ifdef GCRYPT_SHA512
BASIC_CFLAGS += -DSHA512_GCRYPT
EXTLIBS += -lgcrypt
@@ -1723,7 +1730,6 @@ else
LIB_OBJS += sha/sha512/sha512.o
BASIC_CFLAGS += -DSHA512_BLK
endif
-
ifdef GCRYPT_SHA3
BASIC_CFLAGS += -DSHA3_GCRYPT
EXTLIBS += -lgcrypt
@@ -1731,6 +1737,7 @@ else
LIB_OBJS += sha/sha3/sha3.o
BASIC_CFLAGS += -DSHA3_BLK
endif
+endif
ifdef SHA1_MAX_BLOCK_SIZE
LIB_OBJS += compat/sha1-chunked.o
diff --git a/hash.h b/hash.h
index 16924203d035..38e691fe8961 100644
--- a/hash.h
+++ b/hash.h
@@ -25,12 +25,18 @@
#if defined(SHA512_GCRYPT)
#include "sha/sha512/gcrypt.h"
+#elif defined(SHA_EVP_OPENSSL)
+#include <openssl/evp.h>
+#include "sha/sha_evp/sha_evp.h"
#else
#include "sha/sha512/sha512.h"
#endif
#if defined(SHA3_GCRYPT)
#include "sha/sha3/gcrypt.h"
+#elif defined(SHA_EVP_OPENSSL)
+#include <openssl/evp.h>
+#include "sha/sha_evp/sha_evp.h"
#else
#include "sha/sha3/sha3.h"
#endif
diff --git a/sha/sha_evp/sha_evp.c b/sha/sha_evp/sha_evp.c
new file mode 100644
index 000000000000..6871f9744a71
--- /dev/null
+++ b/sha/sha_evp/sha_evp.c
@@ -0,0 +1,99 @@
+#include "git-compat-util.h"
+#include "sha_evp.h"
+
+void evp_SHA2_224_Init(SHA_EVP_CTX *ctx)
+{
+ ctx->digest_ctx = NULL;
+ ctx->digest_md = EVP_sha224();
+}
+
+void evp_SHA2_256_Init(SHA_EVP_CTX *ctx)
+{
+ ctx->digest_ctx = NULL;
+ ctx->digest_md = EVP_sha256();
+}
+
+void evp_SHA2_512_Init(SHA_EVP_CTX *ctx)
+{
+ ctx->digest_ctx = NULL;
+ ctx->digest_md = EVP_sha512();
+}
+
+void evp_SHA2_512_224_Init(SHA_EVP_CTX *ctx)
+{
+ ctx->digest_ctx = NULL;
+ ctx->digest_md = EVP_sha512_224();
+}
+
+void evp_SHA2_512_256_Init(SHA_EVP_CTX *ctx)
+{
+ ctx->digest_ctx = NULL;
+ ctx->digest_md = EVP_sha512_256();
+}
+
+void evp_SHA3_224_Init(SHA_EVP_CTX *ctx)
+{
+ ctx->digest_ctx = NULL;
+ ctx->digest_md = EVP_sha3_224();
+}
+
+void evp_SHA3_256_Init(SHA_EVP_CTX *ctx)
+{
+ ctx->digest_ctx = NULL;
+ ctx->digest_md = EVP_sha3_256();
+}
+
+void evp_SHA3_384_Init(SHA_EVP_CTX *ctx)
+{
+ ctx->digest_ctx = NULL;
+ ctx->digest_md = EVP_sha3_384();
+}
+
+void evp_SHA3_512_Init(SHA_EVP_CTX *ctx)
+{
+ ctx->digest_ctx = NULL;
+ ctx->digest_md = EVP_sha3_512();
+}
+
+static void evp_SHA_Lazy_Init(SHA_EVP_CTX *ctx)
+{
+ /*
+ * The OpenSSL EVP digest API requires a dynamically sized context to be
+ * allocated and destroyed, however, the digest API we are emulating uses
+ * static structures and thus has no allocation or deallocation API.
+ *
+ * Due to this, we must call EVP_MD_CTX_destroy in Final to free up
+ * dynamically allocated memory. Context creation is thus done lazily in
+ * either Update or Final to handle cases where the context is reused
+ * after Final has been called.
+ */
+ if (ctx->digest_ctx) return;
+ if ((ctx->digest_ctx = EVP_MD_CTX_create()) == NULL)
+ abort();
+ if (EVP_DigestInit_ex(ctx->digest_ctx, ctx->digest_md, NULL) != 1)
+ abort();
+}
+
+void evp_SHA_Update(SHA_EVP_CTX *ctx, const void *data, size_t len)
+{
+ /* handle late Init as well as being called again after Final */
+ evp_SHA_Lazy_Init(ctx);
+
+ if (EVP_DigestUpdate(ctx->digest_ctx, data, len) != 1)
+ abort();
+}
+
+void evp_SHA_Final(unsigned char *result, SHA_EVP_CTX *ctx)
+{
+ unsigned int len;
+
+ /* handle case where Final is called without Update (empty hash) */
+ evp_SHA_Lazy_Init(ctx);
+
+ if (EVP_DigestFinal_ex(ctx->digest_ctx, result, &len) != 1)
+ abort();
+ assert(EVP_MD_size(ctx->digest_md) == len);
+
+ EVP_MD_CTX_destroy(ctx->digest_ctx);
+ ctx->digest_ctx = NULL;
+}
diff --git a/sha/sha_evp/sha_evp.h b/sha/sha_evp/sha_evp.h
new file mode 100644
index 000000000000..8757f77f4c13
--- /dev/null
+++ b/sha/sha_evp/sha_evp.h
@@ -0,0 +1,51 @@
+#ifndef SHAEVP_BLOCK_H
+#define SHAEVP_BLOCK_H
+
+#include <openssl/evp.h>
+
+#define evp_SHA2_256_hash_size 32
+#define evp_SHA2_512_224_hash_size 28
+#define evp_SHA2_512_256_hash_size 32
+#define evp_SHA2_512_hash_size 64
+#define evp_SHA3_224_hash_size 28
+#define evp_SHA3_256_hash_size 32
+#define evp_SHA3_384_hash_size 48
+#define evp_SHA3_512_hash_size 64
+
+struct SHA_EVP_CTX {
+ EVP_MD_CTX *digest_ctx;
+ const EVP_MD* digest_md;
+};
+
+typedef struct SHA_EVP_CTX SHA_EVP_CTX;
+
+void evp_SHA2_224_Init(SHA_EVP_CTX *ctx);
+void evp_SHA2_256_Init(SHA_EVP_CTX *ctx);
+void evp_SHA2_512_Init(SHA_EVP_CTX *ctx);
+void evp_SHA2_512_224_Init(SHA_EVP_CTX *ctx);
+void evp_SHA2_512_256_Init(SHA_EVP_CTX *ctx);
+void evp_SHA3_224_Init(SHA_EVP_CTX *ctx);
+void evp_SHA3_256_Init(SHA_EVP_CTX *ctx);
+void evp_SHA3_384_Init(SHA_EVP_CTX *ctx);
+void evp_SHA3_512_Init(SHA_EVP_CTX *ctx);
+
+void evp_SHA_Update(SHA_EVP_CTX *ctx, const void *data, size_t len);
+void evp_SHA_Final(unsigned char *result, SHA_EVP_CTX *ctx);
+
+#define platform_SHA512_CTX SHA_EVP_CTX
+#define platform_SHA512_Init evp_SHA2_512_Init
+#define platform_SHA512_224_Init evp_SHA2_512_224_Init
+#define platform_SHA512_256_Init evp_SHA2_512_256_Init
+#define platform_SHA512_Update evp_SHA_Update
+#define platform_SHA512_Final evp_SHA_Final
+
+#define platform_SHA3_CTX SHA_EVP_CTX
+#define platform_SHA3_Init evp_SHA3_256_Init
+#define platform_SHA3_224_Init evp_SHA3_224_Init
+#define platform_SHA3_256_Init evp_SHA3_256_Init
+#define platform_SHA3_384_Init evp_SHA3_384_Init
+#define platform_SHA3_512_Init evp_SHA3_512_Init
+#define platform_SHA3_Update evp_SHA_Update
+#define platform_SHA3_Final evp_SHA_Final
+
+#endif
\ No newline at end of file
--
2.20.1
next prev parent reply other threads:[~2019-12-22 6:48 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-12-22 6:48 [PATCH 0/6] Additional SHA implementations Michael Clark
2019-12-22 6:48 ` [PATCH 1/6] Move all SHA algorithm variants into sha/ directory Michael Clark
2019-12-22 6:48 ` [PATCH 2/6] Add an implementation of the SHA-512 hash algorithm Michael Clark
2019-12-22 6:48 ` [PATCH 3/6] Add an implementation of the SHA-3 " Michael Clark
2019-12-22 6:48 ` [PATCH 4/6] Add an implementation of the SHA224 truncated " Michael Clark
2019-12-22 6:48 ` Michael Clark [this message]
2019-12-22 6:48 ` [PATCH 6/6] Add sha/README.md with table of SHA algorithm details Michael Clark
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20191222064809.35667-6-michaeljclark@mac.com \
--to=michaeljclark@mac.com \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).