git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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


  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).