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
|
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
|
-
+
-
-
+
-
-
-
-
+
-
-
-
+
+
-
-
-
-
+
+
+
+
+
-
-
-
+
-
-
-
+
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
+
+
-
+
-
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
|
#include <string.h>
#import "OFSHA1Hash.h"
#import "OFHashAlreadyCalculatedException.h"
/* blk0() and blk() perform the initial expand. */
#define F(a, b, c, d) ((d) ^ ((b) & ((c) ^ (d))))
#ifndef OF_BIG_ENDIAN
#define blk0(i) \
#define G(a, b, c, d) ((b) ^ (c) ^ (d))
(block.l[i] = (OF_ROL(block.l[i], 24) & 0xFF00FF00) | \
(OF_ROL(block.l[i], 8) & 0x00FF00FF))
#else
#define blk0(i) block.l[i]
#define H(a, b, c, d) (((b) & (c)) | ((d) & ((b) | (c))))
#endif
#define blk(i) \
(block.l[i & 15] = OF_ROL(block.l[(i + 13) & 15] ^ \
#define I(a, b, c, d) ((b) ^ (c) ^ (d))
block.l[(i + 8) & 15] ^ block.l[(i + 2) & 15] ^ \
block.l[i & 15], 1))
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
static void
byteSwapVectorIfLE(uint32_t *vector, uint_fast8_t length)
{
uint_fast8_t i;
#define R0(v, w, x, y, z, i) \
z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + OF_ROL(v, 5); \
w = OF_ROL(w, 30);
for (i = 0; i < length; i++)
#define R1(v, w, x, y, z, i) \
z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + OF_ROL(v, 5); \
w = OF_ROL(w, 30);
vector[i] = OF_BSWAP32_IF_LE(vector[i]);
#define R2(v, w, x, y, z, i) \
z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + OF_ROL(v, 5); \
w = OF_ROL(w, 30);
#define R3(v, w, x, y, z, i) \
z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + OF_ROL(v, 5); \
}
w = OF_ROL(w, 30);
#define R4(v, w, x, y, z, i) \
z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + OF_ROL(v, 5); \
w = OF_ROL(w, 30);
typedef union {
char c[64];
uint32_t l[16];
} sha1_c64l16_t;
static inline void
sha1_transform(uint32_t state[5], const char buffer[64])
static void
processBlock(uint32_t *state, uint32_t *buffer)
{
uint32_t a, b, c, d, e;
uint32_t new[5];
sha1_c64l16_t block;
uint_fast8_t i;
memcpy(block.c, buffer, 64);
/* Copy state[] to working vars */
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
new[0] = state[0];
new[1] = state[1];
new[2] = state[2];
new[3] = state[3];
new[4] = state[4];
byteSwapVectorIfLE(buffer, 16);
/* 4 rounds of 20 operations each. Loop unrolled. */
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
for (i = 16; i < 80; i++) {
uint32_t tmp = buffer[i - 3] ^ buffer[i - 8] ^
buffer[i - 14] ^ buffer[i - 16];
buffer[i] = OF_ROL(tmp, 1);
}
#define LOOP_BODY(f, k) \
R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
{ \
uint32_t tmp = OF_ROL(new[0], 5) + \
f(new[0], new[1], new[2], new[3]) + \
new[4] + k + buffer[i]; \
new[4] = new[3]; \
new[3] = new[2]; \
new[2] = OF_ROL(new[1], 30); \
new[1] = new[0]; \
new[0] = tmp; \
}
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
for (i = 0; i < 20; i++)
LOOP_BODY(F, 0x5A827999)
for (; i < 40; i++)
LOOP_BODY(G, 0x6ED9EBA1)
for (; i < 60; i++)
LOOP_BODY(H, 0x8F1BBCDC)
for (; i < 80; i++)
LOOP_BODY(I, 0xCA62C1D6)
#undef LOOP_BODY
/* Add the working vars back into state[] */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
state[0] += new[0];
state[1] += new[1];
state[2] += new[2];
state[3] += new[3];
state[4] += new[4];
}
static inline void
sha1_update(uint32_t *state, uint64_t *count, char *buffer,
const char *buf, size_t length)
{
size_t i, j;
j = (size_t)((*count >> 3) & 63);
*count += (length << 3);
if ((j + length) > 63) {
memcpy(&buffer[j], buf, (i = 64 - j));
sha1_transform(state, buffer);
for (; i + 63 < length; i += 64)
sha1_transform(state, &buf[i]);
j = 0;
} else
i = 0;
memcpy(&buffer[j], &buf[i], length - i);
}
@implementation OFSHA1Hash
+ (size_t)digestSize
{
return 20;
}
|