- 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