libaaruformat 1.0
Aaru Data Preservation Suite - Format Library
Loading...
Searching...
No Matches
sha1.c
Go to the documentation of this file.
1/*
2 * Public domain / MIT SHA-1 implementation for libaaruformat.
3 *
4 * This implementation is derived from the FIPS PUB 180-1 specification and
5 * other public domain reference implementations; released as public domain.
6 * If public domain dedication is not recognized, you may use it under the
7 * MIT license terms (see header in sha1.h).
8 */
9#include <stdbool.h>
10#include <stdint.h>
11#include <stdio.h>
12#include <string.h>
13
14#include "decls.h"
15#include "sha1.h"
16
17#ifndef AARU_LOCAL
18#define AARU_LOCAL static
19#endif
20
21/* Rotate-left 32-bit */
22#if defined(_MSC_VER)
23#define ROTL32(v, n) _rotl(v, n)
24#else
25#define ROTL32(v, n) (((v) << (n)) | ((v) >> (32 - (n))))
26#endif
27
28/* SHA-1 logical functions */
29#define F0(b, c, d) (((b) & (c)) | (~(b) & (d)))
30#define F1(b, c, d) ((b) ^ (c) ^ (d))
31#define F2(b, c, d) (((b) & (c)) | ((b) & (d)) | ((c) & (d)))
32#define F3(b, c, d) ((b) ^ (c) ^ (d))
33
35{
36 ctx->state[0] = 0x67452301UL;
37 ctx->state[1] = 0xEFCDAB89UL;
38 ctx->state[2] = 0x98BADCFEUL;
39 ctx->state[3] = 0x10325476UL;
40 ctx->state[4] = 0xC3D2E1F0UL;
41 ctx->count = 0ULL;
42 memset(ctx->buffer, 0, sizeof(ctx->buffer));
43}
44
45AARU_LOCAL void sha1_transform(uint32_t state[5], const uint8_t block[64])
46{
47 uint32_t W[80];
48
49 /* Prepare message schedule */
50 for(int t = 0; t < 16; t++)
51 {
52 W[t] = ((uint32_t)block[t * 4] << 24) | ((uint32_t)block[t * 4 + 1] << 16) | ((uint32_t)block[t * 4 + 2] << 8) |
53 ((uint32_t)block[t * 4 + 3]);
54 }
55 for(int t = 16; t < 80; t++) { W[t] = ROTL32(W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16], 1); }
56
57 uint32_t a = state[0];
58 uint32_t b = state[1];
59 uint32_t c = state[2];
60 uint32_t d = state[3];
61 uint32_t e = state[4];
62
63 for(int t = 0; t < 80; t++)
64 {
65 uint32_t temp;
66 if(t < 20)
67 temp = ROTL32(a, 5) + F0(b, c, d) + e + W[t] + 0x5A827999UL;
68 else if(t < 40)
69 temp = ROTL32(a, 5) + F1(b, c, d) + e + W[t] + 0x6ED9EBA1UL;
70 else if(t < 60)
71 temp = ROTL32(a, 5) + F2(b, c, d) + e + W[t] + 0x8F1BBCDCUL;
72 else
73 temp = ROTL32(a, 5) + F3(b, c, d) + e + W[t] + 0xCA62C1D6UL;
74
75 e = d;
76 d = c;
77 c = ROTL32(b, 30);
78 b = a;
79 a = temp;
80 }
81
82 state[0] += a;
83 state[1] += b;
84 state[2] += c;
85 state[3] += d;
86 state[4] += e;
87}
88
89AARU_EXPORT void AARU_CALL aaruf_sha1_update(sha1_ctx *ctx, const void *data_ptr, unsigned long len)
90{
91 const uint8_t *data = (const uint8_t *)data_ptr;
92 if(len == 0) return;
93
94 /* Number of bytes mod 64 currently in buffer */
95 uint32_t buffer_bytes = (uint32_t)((ctx->count >> 3) & 0x3F);
96
97 /* Update bit count */
98 ctx->count += (uint64_t)len << 3;
99
100 uint32_t free_bytes = 64 - buffer_bytes;
101
102 if(len >= free_bytes)
103 {
104 /* Fill buffer and compress */
105 memcpy(ctx->buffer + buffer_bytes, data, free_bytes);
106 sha1_transform(ctx->state, ctx->buffer);
107 data += free_bytes;
108 len -= free_bytes;
109
110 /* Process direct blocks */
111 while(len >= 64)
112 {
113 sha1_transform(ctx->state, data);
114 data += 64;
115 len -= 64;
116 }
117 buffer_bytes = 0;
118 }
119
120 /* Buffer the remaining */
121 if(len > 0) memcpy(ctx->buffer + buffer_bytes, data, len);
122}
123
124AARU_EXPORT void AARU_CALL aaruf_sha1_final(sha1_ctx *ctx, unsigned char *digest)
125{
126 uint8_t pad[64];
127 memset(pad, 0, sizeof(pad));
128 pad[0] = 0x80;
129
130 uint8_t length_be[8];
131 uint64_t bits = ctx->count;
132 for(int i = 0; i < 8; i++) { length_be[7 - i] = (uint8_t)(bits >> (i * 8)); }
133
134 /* Current bytes mod 64 */
135 uint32_t buffer_bytes = (uint32_t)((ctx->count >> 3) & 0x3F);
136
137 uint32_t pad_len = (buffer_bytes < 56) ? (56 - buffer_bytes) : (120 - buffer_bytes);
138
139 aaruf_sha1_update(ctx, pad, pad_len);
140 aaruf_sha1_update(ctx, length_be, 8);
141
142 /* Output digest big-endian */
143 for(int i = 0; i < 5; i++)
144 {
145 digest[i * 4] = (uint8_t)(ctx->state[i] >> 24);
146 digest[i * 4 + 1] = (uint8_t)(ctx->state[i] >> 16);
147 digest[i * 4 + 2] = (uint8_t)(ctx->state[i] >> 8);
148 digest[i * 4 + 3] = (uint8_t)(ctx->state[i]);
149 }
150
151 /* Wipe context (except state in case reused) */
152 memset(ctx->buffer, 0, sizeof(ctx->buffer));
153}
154
155AARU_EXPORT void AARU_CALL aaruf_sha1_buffer(const void *data, unsigned long size, unsigned char *result)
156{
157 sha1_ctx ctx;
158 aaruf_sha1_init(&ctx);
159 aaruf_sha1_update(&ctx, data, size);
160 aaruf_sha1_final(&ctx, result);
161}
#define AARU_CALL
Definition decls.h:45
#define AARU_LOCAL
Definition decls.h:55
#define AARU_EXPORT
Definition decls.h:54
void aaruf_sha1_buffer(const void *data, unsigned long size, unsigned char *result)
Definition sha1.c:155
#define F2(b, c, d)
Definition sha1.c:31
#define ROTL32(v, n)
Definition sha1.c:25
#define F1(b, c, d)
Definition sha1.c:30
void aaruf_sha1_update(sha1_ctx *ctx, const void *data_ptr, unsigned long len)
Definition sha1.c:89
#define F3(b, c, d)
Definition sha1.c:32
#define F0(b, c, d)
Definition sha1.c:29
void aaruf_sha1_final(sha1_ctx *ctx, unsigned char *digest)
Definition sha1.c:124
void aaruf_sha1_init(sha1_ctx *ctx)
Definition sha1.c:34
static void sha1_transform(uint32_t state[5], const uint8_t block[64])
Definition sha1.c:45
uint64_t count
Definition sha1.h:45
uint8_t buffer[64]
Definition sha1.h:46
uint32_t state[5]
Definition sha1.h:44