1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */ 2 /* SPDX-License-Identifier: Unlicense */ 3 #include "tomcrypt_private.h" 4 5 /** 6 @file adler32.c 7 Adler-32 checksum algorithm 8 Written and placed in the public domain by Wei Dai 9 Adapted for libtomcrypt by Steffen Jaeckel 10 */ 11 #ifdef LTC_ADLER32 12 13 static const unsigned long s_adler32_base = 65521; 14 15 void adler32_init(adler32_state *ctx) 16 { 17 LTC_ARGCHKVD(ctx != NULL); 18 ctx->s[0] = 1; 19 ctx->s[1] = 0; 20 } 21 22 void adler32_update(adler32_state *ctx, const unsigned char *input, unsigned long length) 23 { 24 unsigned long s1, s2; 25 26 LTC_ARGCHKVD(ctx != NULL); 27 LTC_ARGCHKVD(input != NULL); 28 s1 = ctx->s[0]; 29 s2 = ctx->s[1]; 30 31 if (length % 8 != 0) { 32 do { 33 s1 += *input++; 34 s2 += s1; 35 length--; 36 } while (length % 8 != 0); 37 38 if (s1 >= s_adler32_base) { 39 s1 -= s_adler32_base; 40 } 41 s2 %= s_adler32_base; 42 } 43 44 while (length > 0) { 45 s1 += input[0]; 46 s2 += s1; 47 s1 += input[1]; 48 s2 += s1; 49 s1 += input[2]; 50 s2 += s1; 51 s1 += input[3]; 52 s2 += s1; 53 s1 += input[4]; 54 s2 += s1; 55 s1 += input[5]; 56 s2 += s1; 57 s1 += input[6]; 58 s2 += s1; 59 s1 += input[7]; 60 s2 += s1; 61 62 length -= 8; 63 input += 8; 64 65 if (s1 >= s_adler32_base) { 66 s1 -= s_adler32_base; 67 } 68 s2 %= s_adler32_base; 69 } 70 71 LTC_ARGCHKVD(s1 < s_adler32_base); 72 LTC_ARGCHKVD(s2 < s_adler32_base); 73 74 ctx->s[0] = (unsigned short)s1; 75 ctx->s[1] = (unsigned short)s2; 76 } 77 78 void adler32_finish(const adler32_state *ctx, void *hash, unsigned long size) 79 { 80 unsigned char* h; 81 82 LTC_ARGCHKVD(ctx != NULL); 83 LTC_ARGCHKVD(hash != NULL); 84 85 h = hash; 86 87 switch (size) { 88 default: 89 h[3] = ctx->s[0] & 0x0ff; 90 /* FALLTHROUGH */ 91 case 3: 92 h[2] = (ctx->s[0] >> 8) & 0x0ff; 93 /* FALLTHROUGH */ 94 case 2: 95 h[1] = ctx->s[1] & 0x0ff; 96 /* FALLTHROUGH */ 97 case 1: 98 h[0] = (ctx->s[1] >> 8) & 0x0ff; 99 /* FALLTHROUGH */ 100 case 0: 101 ; 102 } 103 } 104 105 int adler32_test(void) 106 { 107 #ifndef LTC_TEST 108 return CRYPT_NOP; 109 #else 110 const void* in = "libtomcrypt"; 111 const unsigned char adler32[] = { 0x1b, 0xe8, 0x04, 0xba }; 112 unsigned char out[4]; 113 adler32_state ctx; 114 adler32_init(&ctx); 115 adler32_update(&ctx, in, XSTRLEN(in)); 116 adler32_finish(&ctx, out, 4); 117 if (compare_testvector(adler32, 4, out, 4, "adler32", 0)) { 118 return CRYPT_FAIL_TESTVECTOR; 119 } 120 return CRYPT_OK; 121 #endif 122 } 123 #endif 124