From 1987a2f97592c592e2881fabd0331f96cf39d70e Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Sat, 22 Aug 2015 17:29:46 +0200 Subject: [PATCH] add adler32 checksum algorithm --- src/headers/tomcrypt_custom.h | 2 + src/headers/tomcrypt_misc.h | 11 +++ src/misc/adler32.c | 135 ++++++++++++++++++++++++++++++++++ src/misc/crypt/crypt.c | 3 + src/misc/crypt/crypt_sizes.c | 4 + testprof/misc_test.c | 3 + 6 files changed, 158 insertions(+) create mode 100644 src/misc/adler32.c diff --git a/src/headers/tomcrypt_custom.h b/src/headers/tomcrypt_custom.h index 91143cc..68b8f12 100644 --- a/src/headers/tomcrypt_custom.h +++ b/src/headers/tomcrypt_custom.h @@ -430,6 +430,8 @@ #define LTC_HKDF #endif /* LTC_NO_HKDF */ +#define LTC_ADLER32 + #endif /* LTC_NO_MISC */ /* cleanup */ diff --git a/src/headers/tomcrypt_misc.h b/src/headers/tomcrypt_misc.h index c5e4ab3..407dd65 100644 --- a/src/headers/tomcrypt_misc.h +++ b/src/headers/tomcrypt_misc.h @@ -69,6 +69,17 @@ void init_GMP(void); #endif */ +#ifdef LTC_ADLER32 +typedef struct adler32_state_s +{ + unsigned short s[2]; +} adler32_state; + +void adler32_init(adler32_state *ctx); +void adler32_update(adler32_state *ctx, const unsigned char *input, unsigned long length); +void adler32_finish(adler32_state *ctx, void *hash, unsigned long size); +int adler32_test(void); +#endif /* $Source$ */ /* $Revision$ */ diff --git a/src/misc/adler32.c b/src/misc/adler32.c new file mode 100644 index 0000000..3e6f4e5 --- /dev/null +++ b/src/misc/adler32.c @@ -0,0 +1,135 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file adler32.c + Adler-32 checksum algorithm + Written and placed in the public domain by Wei Dai + Adapted for libtomcrypt by Steffen Jaeckel +*/ +#ifdef LTC_ADLER32 + +static const unsigned long _adler32_base = 65521; + +void adler32_init(adler32_state *ctx) +{ + LTC_ARGCHKVD(ctx != NULL); + ctx->s[0] = 1; + ctx->s[1] = 0; +} + +void adler32_update(adler32_state *ctx, const unsigned char *input, unsigned long length) +{ + LTC_ARGCHKVD(ctx != NULL); + LTC_ARGCHKVD(input != NULL); + unsigned long s1 = ctx->s[0]; + unsigned long s2 = ctx->s[1]; + + if (length % 8 != 0) { + do { + s1 += *input++; + s2 += s1; + length--; + } while (length % 8 != 0); + + if (s1 >= _adler32_base) + s1 -= _adler32_base; + s2 %= _adler32_base; + } + + while (length > 0) { + s1 += input[0]; + s2 += s1; + s1 += input[1]; + s2 += s1; + s1 += input[2]; + s2 += s1; + s1 += input[3]; + s2 += s1; + s1 += input[4]; + s2 += s1; + s1 += input[5]; + s2 += s1; + s1 += input[6]; + s2 += s1; + s1 += input[7]; + s2 += s1; + + length -= 8; + input += 8; + + if (s1 >= _adler32_base) + s1 -= _adler32_base; + s2 %= _adler32_base; + } + + LTC_ARGCHKVD(s1 < _adler32_base); + LTC_ARGCHKVD(s2 < _adler32_base); + + ctx->s[0] = (unsigned short)s1; + ctx->s[1] = (unsigned short)s2; +} + +void adler32_finish(adler32_state *ctx, void *hash, unsigned long size) +{ + LTC_ARGCHKVD(ctx != NULL); + LTC_ARGCHKVD(hash != NULL); + + unsigned char* h = hash; + + switch (size) { + default: + h[3] = ctx->s[0] & 0x0ff; + /* no break */ + case 3: + h[2] = (ctx->s[0] >> 8) & 0x0ff; + /* no break */ + case 2: + h[1] = ctx->s[1] & 0x0ff; + /* no break */ + case 1: + h[0] = (ctx->s[1] >> 8) & 0x0ff; + /* no break */ + case 0: + ; + } +} + +int adler32_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + const void* in = "libtomcrypt"; + const unsigned char adler32[] = { 0x1b, 0xe8, 0x04, 0xba }; + unsigned char out[4]; + adler32_state ctx; + adler32_init(&ctx); + adler32_update(&ctx, in, strlen(in)); + adler32_finish(&ctx, &out, 4); + if (XMEMCMP(adler32, out, 4)) { +#ifdef LTC_TEST_DBG + ulong32 _out, _adler32; + LOAD32H(_out, out); + LOAD32H(_adler32, adler32); + printf("adler32 fail! Is: 0x%x Should: 0x%x\n", _out, _adler32); +#endif + return CRYPT_FAIL_TESTVECTOR; + } + return CRYPT_OK; +#endif +} +#endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/misc/crypt/crypt.c b/src/misc/crypt/crypt.c index 9d90dfe..0c7dc11 100644 --- a/src/misc/crypt/crypt.c +++ b/src/misc/crypt/crypt.c @@ -322,6 +322,9 @@ const char *crypt_build_settings = #endif "\nVarious others: " +#if defined(LTC_ADLER32) + " ADLER32 " +#endif #if defined(LTC_BASE64) " BASE64 " #endif diff --git a/src/misc/crypt/crypt_sizes.c b/src/misc/crypt/crypt_sizes.c index 1870130..eecb80e 100755 --- a/src/misc/crypt/crypt_sizes.c +++ b/src/misc/crypt/crypt_sizes.c @@ -231,6 +231,10 @@ static const crypt_size _crypt_sizes[] = { #endif // sprng has no state as it uses other potentially available sources // like /dev/random. See Developers Guide for more info. + +#ifdef LTC_ADLER32 + _SZ_STRINGIFY_T(adler32_state), +#endif }; /* crypt_get_size() diff --git a/testprof/misc_test.c b/testprof/misc_test.c index 242bb01..2407ddb 100644 --- a/testprof/misc_test.c +++ b/testprof/misc_test.c @@ -10,6 +10,9 @@ int misc_test(void) #endif #ifdef LTC_BASE64 DO(base64_test()); +#endif +#ifdef LTC_ADLER32 + DO(adler32_test()); #endif return 0; }