X-Git-Url: https://git.hcoop.net/hcoop/debian/exim4.git/blobdiff_plain/ed7df6aed3350267779da0674e270711e5914e79:/src/auths/sha1.c..d1d56ac364669b9a323ad9494f96398ba502dac0:/src/hash.c diff --git a/src/auths/sha1.c b/src/hash.c similarity index 88% rename from src/auths/sha1.c rename to src/hash.c index 67a1191..7590d55 100644 --- a/src/auths/sha1.c +++ b/src/hash.c @@ -1,28 +1,188 @@ -/************************************************* -* Exim - an Internet mail transport agent * -*************************************************/ - -/* Copyright (c) University of Cambridge 1995 - 2009 */ -/* See the file NOTICE for conditions of use and distribution. */ +/* + * Exim - an Internet mail transport agent + * + * Copyright (C) 2016 Exim maintainers + * Copyright (c) University of Cambridge 1995 - 2016 + * + * Hash interface functions + */ #ifndef STAND_ALONE -#include "../exim.h" +# include "exim.h" + +#else /* For stand-alone testing, we need to have the structure defined, and to be able to do I/O */ -#else -#include -#include +# include +# include typedef unsigned char uschar; typedef struct sha1 { unsigned int H[5]; unsigned int length; } sha1; +#endif /*STAND_ALONE*/ + +#include + +/******************************************************************************/ +#ifdef SHA_OPENSSL + +BOOL +exim_sha_init(hctx * h, hashmethod m) +{ +switch (h->method = m) + { + case HASH_SHA1: h->hashlen = 20; SHA1_Init (&h->u.sha1); break; + case HASH_SHA256: h->hashlen = 32; SHA256_Init(&h->u.sha2); break; + default: h->hashlen = 0; return FALSE; + } +return TRUE; +} + + +void +exim_sha_update(hctx * h, const uschar * data, int len) +{ +switch (h->method) + { + case HASH_SHA1: SHA1_Update (&h->u.sha1, data, len); break; + case HASH_SHA256: SHA256_Update(&h->u.sha2, data, len); break; + /* should be blocked by init not handling these, but be explicit to + * guard against accidents later (and hush up clang -Wswitch) */ + default: assert(0); + } +} + + +void +exim_sha_finish(hctx * h, blob * b) +{ +b->data = store_get(b->len = h->hashlen); +switch (h->method) + { + case HASH_SHA1: SHA1_Final (b->data, &h->u.sha1); break; + case HASH_SHA256: SHA256_Final(b->data, &h->u.sha2); break; + default: assert(0); + } +} + + + +#elif defined(SHA_GNUTLS) +/******************************************************************************/ + +BOOL +exim_sha_init(hctx * h, hashmethod m) +{ +switch (h->method = m) + { + case HASH_SHA1: h->hashlen = 20; gnutls_hash_init(&h->sha, GNUTLS_DIG_SHA1); break; + case HASH_SHA256: h->hashlen = 32; gnutls_hash_init(&h->sha, GNUTLS_DIG_SHA256); break; +#ifdef EXIM_HAVE_SHA3 + case HASH_SHA3_256: h->hashlen = 32; gnutls_hash_init(&h->sha, GNUTLS_DIG_SHA3_256); break; #endif + default: h->hashlen = 0; return FALSE; + } +return TRUE; +} +void +exim_sha_update(hctx * h, const uschar * data, int len) +{ +gnutls_hash(h->sha, data, len); +} + + +void +exim_sha_finish(hctx * h, blob * b) +{ +b->data = store_get(b->len = h->hashlen); +gnutls_hash_output(h->sha, b->data); +} + + + +#elif defined(SHA_GCRYPT) +/******************************************************************************/ + +BOOL +exim_sha_init(hctx * h, hashmethod m) +{ +switch (h->method = m) + { + case HASH_SHA1: h->hashlen = 20; gcry_md_open(&h->sha, GCRY_MD_SHA1, 0); break; + case HASH_SHA256: h->hashlen = 32; gcry_md_open(&h->sha, GCRY_MD_SHA256, 0); break; + default: h->hashlen = 0; return FALSE; + } +return TRUE; +} + + +void +exim_sha_update(hctx * h, const uschar * data, int len) +{ +gcry_md_write(h->sha, data, len); +} + + +void +exim_sha_finish(hctx * h, blob * b) +{ +b->data = store_get(b->len = h->hashlen); +memcpy(b->data, gcry_md_read(h->sha, 0), h->hashlen); +} + + + + +#elif defined(SHA_POLARSSL) +/******************************************************************************/ + +BOOL +exim_sha_init(hctx * h, hashmethod m) +{ +switch (h->method = m) + { + case HASH_SHA1: h->hashlen = 20; sha1_starts(&h->u.sha1); break; + case HASH_SHA256: h->hashlen = 32; sha2_starts(&h->u.sha2, 0); break; + default: h->hashlen = 0; return FALSE; + } +return TRUE; +} + + +void +exim_sha_update(hctx * h, const uschar * data, int len) +{ +switch (h->method) + { + case HASH_SHA1: sha1_update(h->u.sha1, US data, len); break; + case HASH_SHA256: sha2_update(h->u.sha2, US data, len); break; + } +} + + +void +exim_sha_finish(hctx * h, blob * b) +{ +b->data = store_get(b->len = h->hashlen); +switch (h->method) + { + case HASH_SHA1: sha1_finish(h->u.sha1, b->data); break; + case HASH_SHA256: sha2_finish(h->u.sha2, b->data); break; + } +} + + + + +#elif defined(SHA_NATIVE) +/******************************************************************************/ +/* Only sha-1 supported */ /************************************************* * Start off a new SHA-1 computation. * @@ -33,8 +193,8 @@ Argument: pointer to sha1 storage structure Returns: nothing */ -void -sha1_start(sha1 *base) +static void +native_sha1_start(sha1 *base) { base->H[0] = 0x67452301; base->H[1] = 0xefcdab89; @@ -59,18 +219,18 @@ Arguments: Returns: nothing */ -void -sha1_mid(sha1 *base, const uschar *text) +static void +native_sha1_mid(sha1 *base, const uschar *text) { -register int i; -unsigned int A, B, C, D, E; -unsigned int W[80]; +int i; +uint A, B, C, D, E; +uint W[80]; base->length += 64; for (i = 0; i < 16; i++) { - W[i] = (text[0] << 24) | (text[1] << 16) | (text[2] << 8) | text[3]; + W[i] = ((uint)text[0] << 24) | (text[1] << 16) | (text[2] << 8) | text[3]; text += 4; } @@ -158,8 +318,8 @@ Arguments: Returns: nothing */ -void -sha1_end(sha1 *base, const uschar *text, int length, uschar *digest) +static void +native_sha1_end(sha1 *base, const uschar *text, int length, uschar *digest) { int i; uschar work[64]; @@ -168,7 +328,7 @@ uschar work[64]; while (length >= 64) { - sha1_mid(base, text); + native_sha1_mid(base, text); text += 64; length -= 64; } @@ -184,7 +344,7 @@ work[length] = 0x80; if (length > 55) { memset(work+length+1, 0, 63-length); - sha1_mid(base, work); + native_sha1_mid(base, work); base->length -= 64; memset(work, 0, 56); } @@ -210,7 +370,7 @@ memset(work+56, 0, 4); /* Process the final 64-byte chunk */ -sha1_mid(base, work); +native_sha1_mid(base, work); /* Pass back the result, high-order byte first in each word. */ @@ -226,13 +386,113 @@ for (i = 0; i < 5; i++) + + + +# ifdef notdef +BOOL +exim_sha_init(hctx * h, hashmethod m) +{ +h->hashlen = 20; +native_sha1_start(&h->sha1); +return TRUE; +} + + +void +exim_sha_update(hctx * h, const uschar * data, int len) +{ +native_sha1_mid(&h->sha1, US data); /* implicit size always 64 */ +} + + +void +exim_sha_finish(hctx * h, blob * b) +{ +b->data = store_get(b->len = h->hashlen); + +native_sha1_end(&h->sha1, NULL, 0, b->data); +} +# endif + + +#endif +/******************************************************************************/ + +/* Common to all library versions */ +int +exim_sha_hashlen(hctx * h) +{ +return h->method == HASH_SHA1 ? 20 + : h->method == HASH_SHA256 ? 32 + : 0; +} + + +/******************************************************************************/ +/******************************************************************************/ +/******************************************************************************/ +/******************************************************************************/ +/* Original sha-1 interface used by crypteq{shal1}, +${sha1:} ${hmac:} and ${prvs:} */ + +#ifdef SHA_NATIVE + +void +sha1_start(hctx * h) +{ +native_sha1_start(&h->sha1); +} + +void +sha1_mid(hctx * h, const uschar * data) +{ +native_sha1_mid(&h->sha1, data); +} + +void +sha1_end(hctx * h, const uschar * data, int len, uschar *digest) +{ +native_sha1_end(&h->sha1, data, len, digest); +} + +#else + +void +sha1_start(hctx * h) +{ +(void) exim_sha_init(h, HASH_SHA1); +} + +void +sha1_mid(hctx * h, const uschar * data) +{ +exim_sha_update(h, data, 64); +} + +void +sha1_end(hctx * h, const uschar * data, int len, uschar *digest) +{ +blob b; +exim_sha_update(h, data, len); +exim_sha_finish(h, &b); +memcpy(digest, b.data, 20); +} + +#endif + + + + + + /************************************************* ************************************************** * Stand-alone test program * ************************************************** *************************************************/ -#ifdef STAND_ALONE +# ifdef STAND_ALONE /* Test values. The first 128 may contain binary zeros and have increasing length. */ @@ -525,8 +785,8 @@ printf("Checking sha1: %s-endian\n\n", (ctest[0] == 0x04)? "little" : "big"); for (i = 0; i < sizeof(tests)/sizeof(uschar *); i ++) { printf("%d.\nShould be: %s\n", i, hashes[i]); - sha1_start(&base); - sha1_end(&base, tests[i], (i <= 128)? i : strlen(tests[i]), digest); + native_sha1_start(&base); + native_sha1_end(&base, tests[i], (i <= 128)? i : strlen(tests[i]), digest); for (j = 0; j < 20; j++) sprintf(s+2*j, "%02X", digest[j]); printf("Computed: %s\n", s); if (strcmp(s, hashes[i]) != 0) printf("*** No match ***\n"); @@ -540,13 +800,13 @@ memset(ctest, 'a', 1000000); printf("1 000 000 repetitions of 'a'\n"); printf("Should be: %s\n", atest); -sha1_start(&base); -sha1_end(&base, ctest, 1000000, digest); +native_sha1_start(&base); +native_sha1_end(&base, ctest, 1000000, digest); for (j = 0; j < 20; j++) sprintf(s+2*j, "%02X", digest[j]); printf("Computed: %s\n", s); if (strcmp(s, atest) != 0) printf("*** No match ***\n"); } -#endif +# endif /*STAND_ALONE*/ -/* End of sha1.c */ +/* End of File */