Line data Source code
1 : /*
2 : SHA-1 in C
3 : By Steve Reid <steve@edmweb.com>
4 : 100% Public Domain
5 :
6 : Test Vectors (from FIPS PUB 180-1)
7 : "abc"
8 : A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
9 : "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
10 : 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
11 : A million repetitions of "a"
12 : 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
13 : */
14 :
15 : #include "sha1.h"
16 : #include <stdint.h>
17 : #include <stdio.h>
18 : #include <string.h>
19 : #include <endian.h>
20 :
21 : #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
22 :
23 : /* blk0() and blk() perform the initial expand. */
24 : /* I got the idea of expanding during the round function from SSLeay */
25 : #define blk0(i) (block[i] = htobe32(block[i]))
26 : #define blk(i) \
27 : (block[i & 15] = rol(block[(i + 13) & 15] ^ block[(i + 8) & 15] ^ \
28 : block[(i + 2) & 15] ^ block[i & 15], \
29 : 1))
30 :
31 : /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
32 : #define R0(v, w, x, y, z, i) \
33 : z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \
34 : w = rol(w, 30);
35 : #define R1(v, w, x, y, z, i) \
36 : z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
37 : w = rol(w, 30);
38 : #define R2(v, w, x, y, z, i) \
39 : z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \
40 : w = rol(w, 30);
41 : #define R3(v, w, x, y, z, i) \
42 : z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
43 : w = rol(w, 30);
44 : #define R4(v, w, x, y, z, i) \
45 : z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
46 : w = rol(w, 30);
47 :
48 : /* Hash a single 512-bit block. This is the core of the algorithm. */
49 :
50 : #define STATE(i) state[(index + (i)) % 5]
51 :
52 0 : static void sha1_transform(uint32_t orig_state[5], const unsigned char buffer[64])
53 : {
54 : uint32_t state[5];
55 : uint32_t block[16];
56 0 : int round = 0;
57 0 : int index = 0;
58 :
59 0 : memcpy(block, buffer, sizeof(block));
60 :
61 : /* Copy context->state[] to working vars */
62 0 : memcpy(state, orig_state, sizeof(state));
63 :
64 : /* 4 rounds of 20 operations each. */
65 0 : for (; round < 16; round++, index += 4) {
66 0 : R0(STATE(0), STATE(1), STATE(2), STATE(3), STATE(4), round);
67 : }
68 0 : for (; round < 20; round++, index += 4) {
69 0 : R1(STATE(0), STATE(1), STATE(2), STATE(3), STATE(4), round);
70 : }
71 :
72 0 : for (; round < 40; round++, index += 4) {
73 0 : R2(STATE(0), STATE(1), STATE(2), STATE(3), STATE(4), round);
74 : }
75 :
76 0 : for (; round < 60; round++, index += 4) {
77 0 : R3(STATE(0), STATE(1), STATE(2), STATE(3), STATE(4), round);
78 : }
79 :
80 0 : for (; round < 80; round++, index += 4) {
81 0 : R4(STATE(0), STATE(1), STATE(2), STATE(3), STATE(4), round);
82 : }
83 :
84 : /* Add the working vars back into context.state[] */
85 0 : for (int i = 0; i < 5; i++)
86 0 : orig_state[i] += state[i];
87 :
88 : /* Wipe transient state */
89 0 : memset(state, 0, sizeof(state));
90 0 : memset(block, 0, sizeof(block));
91 0 : __asm__ volatile("" : : "g"(block), "g"(state) : "memory");
92 0 : }
93 :
94 : /* sha1_init - Initialize new context */
95 :
96 0 : void sha1_init(sha1_context *context)
97 : {
98 : /* SHA1 initialization constants */
99 0 : context->state[0] = 0x67452301;
100 0 : context->state[1] = 0xEFCDAB89;
101 0 : context->state[2] = 0x98BADCFE;
102 0 : context->state[3] = 0x10325476;
103 0 : context->state[4] = 0xC3D2E1F0;
104 0 : context->count[0] = context->count[1] = 0;
105 0 : }
106 :
107 : /* Run your data through this. */
108 :
109 0 : void sha1_update(sha1_context *context, const unsigned char *data, size_t len)
110 : {
111 : size_t i;
112 : size_t j;
113 :
114 0 : j = context->count[0];
115 0 : if ((context->count[0] += len << 3) < j)
116 0 : context->count[1]++;
117 0 : context->count[1] += (len >> 29);
118 :
119 0 : j = (j >> 3) & 63;
120 :
121 0 : if ((j + len) > 63) {
122 0 : i = 64 - j;
123 0 : memcpy(&context->buffer[j], data, i);
124 0 : sha1_transform(context->state, context->buffer);
125 :
126 0 : for (; i + 63 < len; i += 64)
127 0 : sha1_transform(context->state, &data[i]);
128 :
129 0 : j = 0;
130 : } else {
131 0 : i = 0;
132 : }
133 :
134 0 : memcpy(&context->buffer[j], &data[i], len - i);
135 0 : }
136 :
137 : /* Add padding and return the message digest. */
138 :
139 0 : void sha1_finalize(sha1_context *context, unsigned char digest[20])
140 : {
141 : unsigned i;
142 : unsigned char finalcount[8];
143 : unsigned char c;
144 :
145 0 : for (i = 0; i < 8; i++) {
146 0 : finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] >>
147 0 : ((3 - (i & 3)) * 8)) &
148 : 255); /* Endian independent */
149 : }
150 :
151 0 : c = 0200;
152 0 : sha1_update(context, &c, 1);
153 0 : while ((context->count[0] & 504) != 448) {
154 0 : c = 0000;
155 0 : sha1_update(context, &c, 1);
156 : }
157 0 : sha1_update(context, finalcount, 8); /* Should cause a sha1_transform() */
158 0 : for (i = 0; i < 20; i++) {
159 0 : digest[i] =
160 0 : (unsigned char)((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) &
161 : 255);
162 : }
163 :
164 : /* Wipe variables */
165 0 : memset(context, '\0', sizeof(*context));
166 0 : __asm__ volatile("" : : "g"(context) : "memory");
167 :
168 0 : memset(&finalcount, '\0', sizeof(finalcount));
169 0 : __asm__ volatile("" : : "g"(finalcount) : "memory");
170 0 : }
171 :
172 :
173 : #ifdef SHA1_TEST
174 : #include <unistd.h>
175 :
176 : int main(int argc, char *argv)
177 : {
178 : sha1_context ctx;
179 : unsigned char buffer[512];
180 : unsigned char digest[20];
181 :
182 : sha1_init(&ctx);
183 :
184 : for (;;) {
185 : ssize_t r = read(fileno(stdin), buffer, sizeof(buffer));
186 :
187 : if (r < 0) {
188 : perror("read");
189 : return 1;
190 : }
191 :
192 : sha1_update(&ctx, buffer, (size_t)r);
193 :
194 : if (r < (ssize_t)sizeof(buffer))
195 : break;
196 : }
197 :
198 : sha1_finalize(&ctx, digest);
199 :
200 : printf("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%"
201 : "02x%02x%02x%02x\n",
202 : digest[0], digest[1], digest[2], digest[3], digest[4], digest[5],
203 : digest[6], digest[7], digest[8], digest[9], digest[10], digest[11],
204 : digest[12], digest[13], digest[14], digest[15], digest[16],
205 : digest[17], digest[18], digest[19]);
206 : }
207 : #endif
|