[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