[PATCH 1/2] lib: use glib for sha1 digests instead of embedding libsha1
Tomi Ollila
tomi.ollila at iki.fi
Sat Jan 7 00:47:42 PST 2017
On Fri, Jan 06 2017, Jani Nikula <jani at nikula.org> wrote:
> We already depend on glib both directly and indirectly (via gmime). We
> might as well make use of its facilities. Drop the embedded libsha1
> and use glib for sha1 digests.
Nice! tests pass. probably doesn't collide with anything in review queue.
+1
Tomi
> ---
> lib/Makefile.local | 1 -
> lib/libsha1.c | 244 -----------------------------------------------------
> lib/libsha1.h | 71 ----------------
> lib/sha1.c | 69 ++++++---------
> 4 files changed, 24 insertions(+), 361 deletions(-)
> delete mode 100644 lib/libsha1.c
> delete mode 100644 lib/libsha1.h
>
> diff --git a/lib/Makefile.local b/lib/Makefile.local
> index 3d1030a56740..b77e57803288 100644
> --- a/lib/Makefile.local
> +++ b/lib/Makefile.local
> @@ -35,7 +35,6 @@ libnotmuch_c_srcs = \
> $(notmuch_compat_srcs) \
> $(dir)/filenames.c \
> $(dir)/string-list.c \
> - $(dir)/libsha1.c \
> $(dir)/message-file.c \
> $(dir)/messages.c \
> $(dir)/sha1.c \
> diff --git a/lib/libsha1.c b/lib/libsha1.c
> deleted file mode 100644
> index aaaa4eb2fc14..000000000000
> --- a/lib/libsha1.c
> +++ /dev/null
> @@ -1,244 +0,0 @@
> -/*
> - ---------------------------------------------------------------------------
> - Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved.
> -
> - LICENSE TERMS
> -
> - The free distribution and use of this software in both source and binary
> - form is allowed (with or without changes) provided that:
> -
> - 1. distributions of this source code include the above copyright
> - notice, this list of conditions and the following disclaimer;
> -
> - 2. distributions in binary form include the above copyright
> - notice, this list of conditions and the following disclaimer
> - in the documentation and/or other associated materials;
> -
> - 3. the copyright holder's name is not used to endorse products
> - built using this software without specific written permission.
> -
> - ALTERNATIVELY, provided that this notice is retained in full, this product
> - may be distributed under the terms of the GNU General Public License (GPL),
> - in which case the provisions of the GPL apply INSTEAD OF those given above.
> -
> - DISCLAIMER
> -
> - This software is provided 'as is' with no explicit or implied warranties
> - in respect of its properties, including, but not limited to, correctness
> - and/or fitness for purpose.
> - ---------------------------------------------------------------------------
> - Issue Date: 01/08/2005
> -
> - This is a byte oriented version of SHA1 that operates on arrays of bytes
> - stored in memory.
> -*/
> -
> -#include <string.h> /* for memcpy() etc. */
> -#include "endian-util.h"
> -#include "libsha1.h"
> -
> -#if defined(__cplusplus)
> -extern "C"
> -{
> -#endif
> -
> -#define SHA1_BLOCK_SIZE 64
> -
> -#define rotl32(x,n) (((x) << n) | ((x) >> (32 - n)))
> -#define rotr32(x,n) (((x) >> n) | ((x) << (32 - n)))
> -
> -#define bswap_32(x) ((rotr32((x), 24) & 0x00ff00ff) | (rotr32((x), 8) & 0xff00ff00))
> -
> -#if (UTIL_BYTE_ORDER == UTIL_ORDER_LITTLE_ENDIAN)
> -# define bsw_32(p,n) \
> - { int _i = (n); while(_i--) ((uint32_t*)p)[_i] = bswap_32(((uint32_t*)p)[_i]); }
> -#elif (UTIL_BYTE_ORDER == UTIL_ORDER_BIG_ENDIAN)
> -# define bsw_32(p,n)
> -#else
> -# error "Unsupported byte order"
> -#endif
> -
> -#define SHA1_MASK (SHA1_BLOCK_SIZE - 1)
> -
> -#if 0
> -
> -#define ch(x,y,z) (((x) & (y)) ^ (~(x) & (z)))
> -#define parity(x,y,z) ((x) ^ (y) ^ (z))
> -#define maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
> -
> -#else /* Discovered by Rich Schroeppel and Colin Plumb */
> -
> -#define ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
> -#define parity(x,y,z) ((x) ^ (y) ^ (z))
> -#define maj(x,y,z) (((x) & (y)) | ((z) & ((x) ^ (y))))
> -
> -#endif
> -
> -/* Compile 64 bytes of hash data into SHA1 context. Note */
> -/* that this routine assumes that the byte order in the */
> -/* ctx->wbuf[] at this point is in such an order that low */
> -/* address bytes in the ORIGINAL byte stream will go in */
> -/* this buffer to the high end of 32-bit words on BOTH big */
> -/* and little endian systems */
> -
> -#ifdef ARRAY
> -#define q(v,n) v[n]
> -#else
> -#define q(v,n) v##n
> -#endif
> -
> -#define one_cycle(v,a,b,c,d,e,f,k,h) \
> - q(v,e) += rotr32(q(v,a),27) + \
> - f(q(v,b),q(v,c),q(v,d)) + k + h; \
> - q(v,b) = rotr32(q(v,b), 2)
> -
> -#define five_cycle(v,f,k,i) \
> - one_cycle(v, 0,1,2,3,4, f,k,hf(i )); \
> - one_cycle(v, 4,0,1,2,3, f,k,hf(i+1)); \
> - one_cycle(v, 3,4,0,1,2, f,k,hf(i+2)); \
> - one_cycle(v, 2,3,4,0,1, f,k,hf(i+3)); \
> - one_cycle(v, 1,2,3,4,0, f,k,hf(i+4))
> -
> -static void sha1_compile(sha1_ctx ctx[1])
> -{ uint32_t *w = ctx->wbuf;
> -
> -#ifdef ARRAY
> - uint32_t v[5];
> - memcpy(v, ctx->hash, 5 * sizeof(uint32_t));
> -#else
> - uint32_t v0, v1, v2, v3, v4;
> - v0 = ctx->hash[0]; v1 = ctx->hash[1];
> - v2 = ctx->hash[2]; v3 = ctx->hash[3];
> - v4 = ctx->hash[4];
> -#endif
> -
> -#define hf(i) w[i]
> -
> - five_cycle(v, ch, 0x5a827999, 0);
> - five_cycle(v, ch, 0x5a827999, 5);
> - five_cycle(v, ch, 0x5a827999, 10);
> - one_cycle(v,0,1,2,3,4, ch, 0x5a827999, hf(15)); \
> -
> -#undef hf
> -#define hf(i) (w[(i) & 15] = rotl32( \
> - w[((i) + 13) & 15] ^ w[((i) + 8) & 15] \
> - ^ w[((i) + 2) & 15] ^ w[(i) & 15], 1))
> -
> - one_cycle(v,4,0,1,2,3, ch, 0x5a827999, hf(16));
> - one_cycle(v,3,4,0,1,2, ch, 0x5a827999, hf(17));
> - one_cycle(v,2,3,4,0,1, ch, 0x5a827999, hf(18));
> - one_cycle(v,1,2,3,4,0, ch, 0x5a827999, hf(19));
> -
> - five_cycle(v, parity, 0x6ed9eba1, 20);
> - five_cycle(v, parity, 0x6ed9eba1, 25);
> - five_cycle(v, parity, 0x6ed9eba1, 30);
> - five_cycle(v, parity, 0x6ed9eba1, 35);
> -
> - five_cycle(v, maj, 0x8f1bbcdc, 40);
> - five_cycle(v, maj, 0x8f1bbcdc, 45);
> - five_cycle(v, maj, 0x8f1bbcdc, 50);
> - five_cycle(v, maj, 0x8f1bbcdc, 55);
> -
> - five_cycle(v, parity, 0xca62c1d6, 60);
> - five_cycle(v, parity, 0xca62c1d6, 65);
> - five_cycle(v, parity, 0xca62c1d6, 70);
> - five_cycle(v, parity, 0xca62c1d6, 75);
> -
> -#ifdef ARRAY
> - ctx->hash[0] += v[0]; ctx->hash[1] += v[1];
> - ctx->hash[2] += v[2]; ctx->hash[3] += v[3];
> - ctx->hash[4] += v[4];
> -#else
> - ctx->hash[0] += v0; ctx->hash[1] += v1;
> - ctx->hash[2] += v2; ctx->hash[3] += v3;
> - ctx->hash[4] += v4;
> -#endif
> -}
> -
> -void sha1_begin(sha1_ctx ctx[1])
> -{
> - ctx->count[0] = ctx->count[1] = 0;
> - ctx->hash[0] = 0x67452301;
> - ctx->hash[1] = 0xefcdab89;
> - ctx->hash[2] = 0x98badcfe;
> - ctx->hash[3] = 0x10325476;
> - ctx->hash[4] = 0xc3d2e1f0;
> -}
> -
> -/* SHA1 hash data in an array of bytes into hash buffer and */
> -/* call the hash_compile function as required. */
> -
> -void sha1_hash(const unsigned char data[], unsigned long len, sha1_ctx ctx[1])
> -{ uint32_t pos = (uint32_t)(ctx->count[0] & SHA1_MASK),
> - space = SHA1_BLOCK_SIZE - pos;
> - const unsigned char *sp = data;
> -
> - if((ctx->count[0] += len) < len)
> - ++(ctx->count[1]);
> -
> - while(len >= space) /* transfer whole blocks if possible */
> - {
> - memcpy(((unsigned char*)ctx->wbuf) + pos, sp, space);
> - sp += space; len -= space; space = SHA1_BLOCK_SIZE; pos = 0;
> - bsw_32(ctx->wbuf, SHA1_BLOCK_SIZE >> 2);
> - sha1_compile(ctx);
> - }
> -
> - memcpy(((unsigned char*)ctx->wbuf) + pos, sp, len);
> -}
> -
> -/* SHA1 final padding and digest calculation */
> -
> -void sha1_end(unsigned char hval[], sha1_ctx ctx[1])
> -{ uint32_t i = (uint32_t)(ctx->count[0] & SHA1_MASK);
> -
> - /* put bytes in the buffer in an order in which references to */
> - /* 32-bit words will put bytes with lower addresses into the */
> - /* top of 32 bit words on BOTH big and little endian machines */
> - bsw_32(ctx->wbuf, (i + 3) >> 2);
> -
> - /* we now need to mask valid bytes and add the padding which is */
> - /* a single 1 bit and as many zero bits as necessary. Note that */
> - /* we can always add the first padding byte here because the */
> - /* buffer always has at least one empty slot */
> - ctx->wbuf[i >> 2] &= 0xffffff80 << 8 * (~i & 3);
> - ctx->wbuf[i >> 2] |= 0x00000080 << 8 * (~i & 3);
> -
> - /* we need 9 or more empty positions, one for the padding byte */
> - /* (above) and eight for the length count. If there is not */
> - /* enough space, pad and empty the buffer */
> - if(i > SHA1_BLOCK_SIZE - 9)
> - {
> - if(i < 60) ctx->wbuf[15] = 0;
> - sha1_compile(ctx);
> - i = 0;
> - }
> - else /* compute a word index for the empty buffer positions */
> - i = (i >> 2) + 1;
> -
> - while(i < 14) /* and zero pad all but last two positions */
> - ctx->wbuf[i++] = 0;
> -
> - /* the following 32-bit length fields are assembled in the */
> - /* wrong byte order on little endian machines but this is */
> - /* corrected later since they are only ever used as 32-bit */
> - /* word values. */
> - ctx->wbuf[14] = (ctx->count[1] << 3) | (ctx->count[0] >> 29);
> - ctx->wbuf[15] = ctx->count[0] << 3;
> - sha1_compile(ctx);
> -
> - /* extract the hash value as bytes in case the hash buffer is */
> - /* misaligned for 32-bit words */
> - for(i = 0; i < SHA1_DIGEST_SIZE; ++i)
> - hval[i] = (unsigned char)(ctx->hash[i >> 2] >> (8 * (~i & 3)));
> -}
> -
> -void sha1(unsigned char hval[], const unsigned char data[], unsigned long len)
> -{ sha1_ctx cx[1];
> -
> - sha1_begin(cx); sha1_hash(data, len, cx); sha1_end(hval, cx);
> -}
> -
> -#if defined(__cplusplus)
> -}
> -#endif
> diff --git a/lib/libsha1.h b/lib/libsha1.h
> deleted file mode 100644
> index 56f445a9ac42..000000000000
> --- a/lib/libsha1.h
> +++ /dev/null
> @@ -1,71 +0,0 @@
> -/*
> - ---------------------------------------------------------------------------
> - Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved.
> -
> - LICENSE TERMS
> -
> - The free distribution and use of this software in both source and binary
> - form is allowed (with or without changes) provided that:
> -
> - 1. distributions of this source code include the above copyright
> - notice, this list of conditions and the following disclaimer;
> -
> - 2. distributions in binary form include the above copyright
> - notice, this list of conditions and the following disclaimer
> - in the documentation and/or other associated materials;
> -
> - 3. the copyright holder's name is not used to endorse products
> - built using this software without specific written permission.
> -
> - ALTERNATIVELY, provided that this notice is retained in full, this product
> - may be distributed under the terms of the GNU General Public License (GPL),
> - in which case the provisions of the GPL apply INSTEAD OF those given above.
> -
> - DISCLAIMER
> -
> - This software is provided 'as is' with no explicit or implied warranties
> - in respect of its properties, including, but not limited to, correctness
> - and/or fitness for purpose.
> - ---------------------------------------------------------------------------
> - Issue Date: 01/08/2005
> -*/
> -
> -#ifndef _SHA1_H
> -#define _SHA1_H
> -
> -#if defined(__cplusplus)
> -extern "C"
> -{
> -#endif
> -#if 0
> -} /* Appeasing Emacs */
> -#endif
> -
> -#include <stdint.h>
> -
> -#pragma GCC visibility push(hidden)
> -
> -/* Size of SHA1 digest */
> -
> -#define SHA1_DIGEST_SIZE 20
> -
> -/* type to hold the SHA1 context */
> -
> -typedef struct
> -{ uint32_t count[2];
> - uint32_t hash[5];
> - uint32_t wbuf[16];
> -} sha1_ctx;
> -
> -void sha1_begin(sha1_ctx ctx[1]);
> -void sha1_hash(const unsigned char data[], unsigned long len, sha1_ctx ctx[1]);
> -void sha1_end(unsigned char hval[], sha1_ctx ctx[1]);
> -void sha1(unsigned char hval[], const unsigned char data[], unsigned long len);
> -
> -#pragma GCC visibility pop
> -
> -#if defined(__cplusplus)
> -}
> -#endif
> -
> -#endif
> diff --git a/lib/sha1.c b/lib/sha1.c
> index b7dea1c2a577..cb55b49a4f11 100644
> --- a/lib/sha1.c
> +++ b/lib/sha1.c
> @@ -20,28 +20,7 @@
>
> #include "notmuch-private.h"
>
> -#include "libsha1.h"
> -
> -/* Just some simple interfaces on top of libsha1 so that we can leave
> - * libsha1 as untouched as possible. */
> -
> -static char *
> -_hex_of_sha1_digest (const unsigned char digest[SHA1_DIGEST_SIZE])
> -{
> - char *result, *r;
> - int i;
> -
> - result = xcalloc (SHA1_DIGEST_SIZE * 2 + 1, 1);
> -
> - for (r = result, i = 0;
> - i < SHA1_DIGEST_SIZE;
> - r += 2, i++)
> - {
> - sprintf (r, "%02x", digest[i]);
> - }
> -
> - return result;
> -}
> +#include <glib.h>
>
> /* Create a hexadecimal string version of the SHA-1 digest of 'str'
> * (including its null terminating character).
> @@ -52,16 +31,15 @@ _hex_of_sha1_digest (const unsigned char digest[SHA1_DIGEST_SIZE])
> char *
> _notmuch_sha1_of_string (const char *str)
> {
> - sha1_ctx sha1;
> - unsigned char digest[SHA1_DIGEST_SIZE];
> -
> - sha1_begin (&sha1);
> + GChecksum *sha1;
> + char *digest;
>
> - sha1_hash ((unsigned char *) str, strlen (str) + 1, &sha1);
> + sha1 = g_checksum_new (G_CHECKSUM_SHA1);
> + g_checksum_update (sha1, (const guchar *) str, strlen (str) + 1);
> + digest = xstrdup (g_checksum_get_string (sha1));
> + g_checksum_free (sha1);
>
> - sha1_end (digest, &sha1);
> -
> - return _hex_of_sha1_digest (digest);
> + return digest;
> }
>
> /* Create a hexadecimal string version of the SHA-1 digest of the
> @@ -80,35 +58,36 @@ _notmuch_sha1_of_file (const char *filename)
> #define BLOCK_SIZE 4096
> unsigned char block[BLOCK_SIZE];
> size_t bytes_read;
> - sha1_ctx sha1;
> - unsigned char digest[SHA1_DIGEST_SIZE];
> - char *result;
> + GChecksum *sha1;
> + char *digest = NULL;
>
> file = fopen (filename, "r");
> if (file == NULL)
> return NULL;
>
> - sha1_begin (&sha1);
> + sha1 = g_checksum_new (G_CHECKSUM_SHA1);
> + if (sha1 == NULL)
> + goto DONE;
>
> while (1) {
> bytes_read = fread (block, 1, 4096, file);
> if (bytes_read == 0) {
> - if (feof (file)) {
> + if (feof (file))
> break;
> - } else if (ferror (file)) {
> - fclose (file);
> - return NULL;
> - }
> + else if (ferror (file))
> + goto DONE;
> } else {
> - sha1_hash (block, bytes_read, &sha1);
> + g_checksum_update (sha1, block, bytes_read);
> }
> }
>
> - sha1_end (digest, &sha1);
> -
> - result = _hex_of_sha1_digest (digest);
> + digest = xstrdup (g_checksum_get_string (sha1));
>
> - fclose (file);
> + DONE:
> + if (sha1)
> + g_checksum_free (sha1);
> + if (file)
> + fclose (file);
>
> - return result;
> + return digest;
> }
> --
> 2.11.0
>
> _______________________________________________
> notmuch mailing list
> notmuch at notmuchmail.org
> https://notmuchmail.org/mailman/listinfo/notmuch
More information about the notmuch
mailing list