-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsha1.c
More file actions
161 lines (135 loc) · 4.73 KB
/
Copy pathsha1.c
File metadata and controls
161 lines (135 loc) · 4.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#include "sha1.h"
#include <string.h>
/* Straightforward textbook SHA-1 (FIPS 180-4), structured the same
* way as sha256.c: init/update/final plus a one-shot wrapper. */
static uint32_t rotl32(uint32_t x, int n) {
return (x << n) | (x >> (32 - n));
}
static void sha1_process_block(khm_sha1_ctx *ctx, const uint8_t block[64]) {
uint32_t w[80];
for (int i = 0; i < 16; i++) {
w[i] = ((uint32_t)block[i * 4] << 24) |
((uint32_t)block[i * 4 + 1] << 16) |
((uint32_t)block[i * 4 + 2] << 8) |
((uint32_t)block[i * 4 + 3]);
}
for (int i = 16; i < 80; i++) {
w[i] = rotl32(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1);
}
uint32_t a = ctx->state[0];
uint32_t b = ctx->state[1];
uint32_t c = ctx->state[2];
uint32_t d = ctx->state[3];
uint32_t e = ctx->state[4];
for (int i = 0; i < 80; i++) {
uint32_t f, k;
if (i < 20) { f = (b & c) | ((~b) & d); k = 0x5A827999; }
else if (i < 40) { f = b ^ c ^ d; k = 0x6ED9EBA1; }
else if (i < 60) { f = (b & c) | (b & d) | (c & d); k = 0x8F1BBCDC; }
else { f = b ^ c ^ d; k = 0xCA62C1D6; }
uint32_t temp = rotl32(a, 5) + f + e + k + w[i];
e = d;
d = c;
c = rotl32(b, 30);
b = a;
a = temp;
}
ctx->state[0] += a;
ctx->state[1] += b;
ctx->state[2] += c;
ctx->state[3] += d;
ctx->state[4] += e;
}
void khm_sha1_init(khm_sha1_ctx *ctx) {
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476;
ctx->state[4] = 0xC3D2E1F0;
ctx->count = 0;
}
void khm_sha1_update(khm_sha1_ctx *ctx, const uint8_t *data, size_t len) {
size_t buf_used = (size_t)(ctx->count % 64);
ctx->count += len;
if (buf_used > 0) {
size_t take = 64 - buf_used;
if (take > len) take = len;
memcpy(ctx->buf + buf_used, data, take);
buf_used += take;
data += take;
len -= take;
if (buf_used == 64) {
sha1_process_block(ctx, ctx->buf);
buf_used = 0;
}
}
while (len >= 64) {
sha1_process_block(ctx, data);
data += 64;
len -= 64;
}
if (len > 0) memcpy(ctx->buf, data, len);
}
void khm_sha1_final(khm_sha1_ctx *ctx, uint8_t digest[20]) {
uint64_t bit_len = ctx->count * 8;
size_t buf_used = (size_t)(ctx->count % 64);
uint8_t pad = 0x80;
khm_sha1_update(ctx, &pad, 1);
/* update() above bumped count; recompute buf_used off the pre-pad count */
buf_used = (buf_used + 1) % 64;
uint8_t zero = 0x00;
while (buf_used != 56) {
khm_sha1_update(ctx, &zero, 1);
buf_used = (buf_used + 1) % 64;
}
uint8_t len_bytes[8];
for (int i = 0; i < 8; i++) {
len_bytes[i] = (uint8_t)(bit_len >> (56 - i * 8));
}
/* Append length directly via the block processor path, bypassing
* update()'s count tracking since we're finishing up. */
size_t used = (size_t)(ctx->count % 64);
memcpy(ctx->buf + used, len_bytes, 8);
sha1_process_block(ctx, ctx->buf);
for (int i = 0; i < 5; i++) {
digest[i * 4] = (uint8_t)(ctx->state[i] >> 24);
digest[i * 4 + 1] = (uint8_t)(ctx->state[i] >> 16);
digest[i * 4 + 2] = (uint8_t)(ctx->state[i] >> 8);
digest[i * 4 + 3] = (uint8_t)(ctx->state[i]);
}
}
void khm_sha1(const uint8_t *data, size_t len, uint8_t digest[20]) {
khm_sha1_ctx ctx;
khm_sha1_init(&ctx);
khm_sha1_update(&ctx, data, len);
khm_sha1_final(&ctx, digest);
}
/* ------------------------------------------------------------------ */
/* HMAC-SHA1 (RFC 2104) */
/* ------------------------------------------------------------------ */
void khm_hmac_sha1(const uint8_t *key, size_t key_len,
const uint8_t *msg, size_t msg_len,
uint8_t digest[20]) {
uint8_t key_block[64];
memset(key_block, 0, sizeof(key_block));
if (key_len > 64) {
khm_sha1(key, key_len, key_block); /* digest is 20 bytes, rest stays 0 */
} else {
memcpy(key_block, key, key_len);
}
uint8_t ipad[64], opad[64];
for (int i = 0; i < 64; i++) {
ipad[i] = key_block[i] ^ 0x36;
opad[i] = key_block[i] ^ 0x5c;
}
khm_sha1_ctx ctx;
uint8_t inner_digest[20];
khm_sha1_init(&ctx);
khm_sha1_update(&ctx, ipad, sizeof(ipad));
khm_sha1_update(&ctx, msg, msg_len);
khm_sha1_final(&ctx, inner_digest);
khm_sha1_init(&ctx);
khm_sha1_update(&ctx, opad, sizeof(opad));
khm_sha1_update(&ctx, inner_digest, sizeof(inner_digest));
khm_sha1_final(&ctx, digest);
}