mirror of
https://github.com/git/git.git
synced 2026-08-10 17:15:14 +00:00
Our git_hash_discard() is a bit hacky: it just calls git_hash_final()
into a dummy result buffer, using the side effect that each
implementation's Final() function will also free any resources.
This is probably not too terrible, since generating the final hash is
not that expensive and we'd mostly call discard on unusual or error code
paths. But we can do better by widening the platform API a bit to add an
explicit discard function.
This requires an annoying amount of boilerplate:
- Each algorithm needs a git_$ALGO_discard() wrapper that dereferences
the union'd git_hash_ctx into the type-safe field. So sha1 + sha256
+ sha1-unsafe, plus a BUG() for the unknown algo. And then these all
need to be referenced in the git_hash_algo structs.
- Platforms which don't do anything special to discard now need a
fallback function which does nothing. And we need this for each algo
(sha1, sha256, and sha1-unsafe).
- Platforms which do need to discard must define their discard
functions. This includes sha1/openssl, sha256/openssl, and
sha256/gcrypt (no sha1-unsafe here as it sits atop the sha1/openssl
functions).
- Algo selection needs to point platform_*_Discard to the appropriate
underlying macro, or indicate that the fallback should be used. We
have a similar situation for the Clone function (where a straight
memcpy() of the context struct is not enough for some platforms).
I've tied Discard to the same flag used by Clone here, since they
are basically the same problem: is the hash context a sequence of
bytes, or does it need smart copying/discarding?
It's easy to miss a case here since we don't even compile the
implementations we aren't using. I've tested with each of:
- no flags, which uses our internal sha1/sha256 implementations, both
of which exercise the noop fallback function
- OPENSSL_SHA1_UNSAFE=1, which checks that our unsafe macro
redirections work
- OPENSSL_SHA1=1, though you should not do that in real life!
- OPENSSL_SHA256=1, passes tests with GIT_TEST_DEFAULT_HASH=sha256
- GCRYPT_SHA256=1, which likewise passes
The other implementations do not set the CLONE_HELPER flag, so they
treat the context as bytes and should be fine with the fallback.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
47 lines
1.2 KiB
C
47 lines
1.2 KiB
C
#ifndef SHA256_GCRYPT_H
|
|
#define SHA256_GCRYPT_H
|
|
|
|
#include <gcrypt.h>
|
|
|
|
#define SHA256_DIGEST_SIZE 32
|
|
|
|
typedef gcry_md_hd_t gcrypt_SHA256_CTX;
|
|
|
|
static inline void gcrypt_SHA256_Init(gcrypt_SHA256_CTX *ctx)
|
|
{
|
|
gcry_error_t err = gcry_md_open(ctx, GCRY_MD_SHA256, 0);
|
|
if (err)
|
|
die("gcry_md_open: %s", gcry_strerror(err));
|
|
}
|
|
|
|
static inline void gcrypt_SHA256_Update(gcrypt_SHA256_CTX *ctx, const void *data, size_t len)
|
|
{
|
|
gcry_md_write(*ctx, data, len);
|
|
}
|
|
|
|
static inline void gcrypt_SHA256_Final(unsigned char *digest, gcrypt_SHA256_CTX *ctx)
|
|
{
|
|
memcpy(digest, gcry_md_read(*ctx, GCRY_MD_SHA256), SHA256_DIGEST_SIZE);
|
|
gcry_md_close(*ctx);
|
|
}
|
|
|
|
static inline void gcrypt_SHA256_Clone(gcrypt_SHA256_CTX *dst, const gcrypt_SHA256_CTX *src)
|
|
{
|
|
gcry_md_close(*dst);
|
|
gcry_md_copy(dst, *src);
|
|
}
|
|
|
|
static inline void gcrypt_SHA256_Discard(gcrypt_SHA256_CTX *ctx)
|
|
{
|
|
gcry_md_close(*ctx);
|
|
}
|
|
|
|
#define platform_SHA256_CTX gcrypt_SHA256_CTX
|
|
#define platform_SHA256_Init gcrypt_SHA256_Init
|
|
#define platform_SHA256_Clone gcrypt_SHA256_Clone
|
|
#define platform_SHA256_Update gcrypt_SHA256_Update
|
|
#define platform_SHA256_Final gcrypt_SHA256_Final
|
|
#define platform_SHA256_Discard gcrypt_SHA256_Discard
|
|
|
|
#endif
|