/src/hostap/src/crypto/sha256-internal.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * SHA-256 hash implementation and interface functions |
3 | | * Copyright (c) 2003-2011, Jouni Malinen <j@w1.fi> |
4 | | * |
5 | | * This software may be distributed under the terms of the BSD license. |
6 | | * See README for more details. |
7 | | */ |
8 | | |
9 | | #include "includes.h" |
10 | | |
11 | | #include "common.h" |
12 | | #include "sha256.h" |
13 | | #include "sha256_i.h" |
14 | | #include "crypto.h" |
15 | | |
16 | | |
17 | | /** |
18 | | * sha256_vector - SHA256 hash for data vector |
19 | | * @num_elem: Number of elements in the data vector |
20 | | * @addr: Pointers to the data areas |
21 | | * @len: Lengths of the data blocks |
22 | | * @mac: Buffer for the hash |
23 | | * Returns: 0 on success, -1 of failure |
24 | | */ |
25 | | int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, |
26 | | u8 *mac) |
27 | 0 | { |
28 | 0 | struct sha256_state ctx; |
29 | 0 | size_t i; |
30 | |
|
31 | 0 | if (TEST_FAIL()) |
32 | 0 | return -1; |
33 | | |
34 | 0 | sha256_init(&ctx); |
35 | 0 | for (i = 0; i < num_elem; i++) |
36 | 0 | if (sha256_process(&ctx, addr[i], len[i])) |
37 | 0 | return -1; |
38 | 0 | if (sha256_done(&ctx, mac)) |
39 | 0 | return -1; |
40 | 0 | return 0; |
41 | 0 | } |
42 | | |
43 | | |
44 | | /* ===== start - public domain SHA256 implementation ===== */ |
45 | | |
46 | | /* This is based on SHA256 implementation in LibTomCrypt that was released into |
47 | | * public domain by Tom St Denis. */ |
48 | | |
49 | | /* the K array */ |
50 | | static const unsigned long K[64] = { |
51 | | 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, |
52 | | 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, |
53 | | 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, |
54 | | 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, |
55 | | 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, |
56 | | 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, |
57 | | 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, |
58 | | 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, |
59 | | 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, |
60 | | 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, |
61 | | 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, |
62 | | 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, |
63 | | 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL |
64 | | }; |
65 | | |
66 | | |
67 | | /* Various logical functions */ |
68 | 0 | #define RORc(x, y) \ |
69 | 0 | ( ((((unsigned long) (x) & 0xFFFFFFFFUL) >> (unsigned long) ((y) & 31)) | \ |
70 | 0 | ((unsigned long) (x) << (unsigned long) (32 - ((y) & 31)))) & 0xFFFFFFFFUL) |
71 | 0 | #define Ch(x,y,z) (z ^ (x & (y ^ z))) |
72 | 0 | #define Maj(x,y,z) (((x | y) & z) | (x & y)) |
73 | 0 | #define S(x, n) RORc((x), (n)) |
74 | 0 | #define R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) |
75 | 0 | #define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) |
76 | 0 | #define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) |
77 | 0 | #define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) |
78 | 0 | #define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) |
79 | | |
80 | | /* compress 512-bits */ |
81 | | static int sha256_compress(struct sha256_state *md, unsigned char *buf) |
82 | 0 | { |
83 | 0 | u32 S[8], W[64], t0, t1; |
84 | 0 | u32 t; |
85 | 0 | int i; |
86 | | |
87 | | /* copy state into S */ |
88 | 0 | for (i = 0; i < 8; i++) { |
89 | 0 | S[i] = md->state[i]; |
90 | 0 | } |
91 | | |
92 | | /* copy the state into 512-bits into W[0..15] */ |
93 | 0 | for (i = 0; i < 16; i++) |
94 | 0 | W[i] = WPA_GET_BE32(buf + (4 * i)); |
95 | | |
96 | | /* fill W[16..63] */ |
97 | 0 | for (i = 16; i < 64; i++) { |
98 | 0 | W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + |
99 | 0 | W[i - 16]; |
100 | 0 | } |
101 | | |
102 | | /* Compress */ |
103 | 0 | #define RND(a,b,c,d,e,f,g,h,i) \ |
104 | 0 | t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ |
105 | 0 | t1 = Sigma0(a) + Maj(a, b, c); \ |
106 | 0 | d += t0; \ |
107 | 0 | h = t0 + t1; |
108 | |
|
109 | 0 | for (i = 0; i < 64; ++i) { |
110 | 0 | RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i); |
111 | 0 | t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; |
112 | 0 | S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t; |
113 | 0 | } |
114 | | |
115 | | /* feedback */ |
116 | 0 | for (i = 0; i < 8; i++) { |
117 | 0 | md->state[i] = md->state[i] + S[i]; |
118 | 0 | } |
119 | 0 | return 0; |
120 | 0 | } |
121 | | |
122 | | |
123 | | /* Initialize the hash state */ |
124 | | void sha256_init(struct sha256_state *md) |
125 | 6 | { |
126 | 6 | md->curlen = 0; |
127 | 6 | md->length = 0; |
128 | 6 | md->state[0] = 0x6A09E667UL; |
129 | 6 | md->state[1] = 0xBB67AE85UL; |
130 | 6 | md->state[2] = 0x3C6EF372UL; |
131 | 6 | md->state[3] = 0xA54FF53AUL; |
132 | 6 | md->state[4] = 0x510E527FUL; |
133 | 6 | md->state[5] = 0x9B05688CUL; |
134 | 6 | md->state[6] = 0x1F83D9ABUL; |
135 | 6 | md->state[7] = 0x5BE0CD19UL; |
136 | 6 | } |
137 | | |
138 | | /** |
139 | | Process a block of memory though the hash |
140 | | @param md The hash state |
141 | | @param in The data to hash |
142 | | @param inlen The length of the data (octets) |
143 | | @return CRYPT_OK if successful |
144 | | */ |
145 | | int sha256_process(struct sha256_state *md, const unsigned char *in, |
146 | | unsigned long inlen) |
147 | 0 | { |
148 | 0 | unsigned long n; |
149 | |
|
150 | 0 | if (md->curlen >= sizeof(md->buf)) |
151 | 0 | return -1; |
152 | | |
153 | 0 | while (inlen > 0) { |
154 | 0 | if (md->curlen == 0 && inlen >= SHA256_BLOCK_SIZE) { |
155 | 0 | if (sha256_compress(md, (unsigned char *) in) < 0) |
156 | 0 | return -1; |
157 | 0 | md->length += SHA256_BLOCK_SIZE * 8; |
158 | 0 | in += SHA256_BLOCK_SIZE; |
159 | 0 | inlen -= SHA256_BLOCK_SIZE; |
160 | 0 | } else { |
161 | 0 | n = MIN(inlen, (SHA256_BLOCK_SIZE - md->curlen)); |
162 | 0 | os_memcpy(md->buf + md->curlen, in, n); |
163 | 0 | md->curlen += n; |
164 | 0 | in += n; |
165 | 0 | inlen -= n; |
166 | 0 | if (md->curlen == SHA256_BLOCK_SIZE) { |
167 | 0 | if (sha256_compress(md, md->buf) < 0) |
168 | 0 | return -1; |
169 | 0 | md->length += 8 * SHA256_BLOCK_SIZE; |
170 | 0 | md->curlen = 0; |
171 | 0 | } |
172 | 0 | } |
173 | 0 | } |
174 | | |
175 | 0 | return 0; |
176 | 0 | } |
177 | | |
178 | | |
179 | | /** |
180 | | Terminate the hash to get the digest |
181 | | @param md The hash state |
182 | | @param out [out] The destination of the hash (32 bytes) |
183 | | @return CRYPT_OK if successful |
184 | | */ |
185 | | int sha256_done(struct sha256_state *md, unsigned char *out) |
186 | 0 | { |
187 | 0 | int i; |
188 | |
|
189 | 0 | if (md->curlen >= sizeof(md->buf)) |
190 | 0 | return -1; |
191 | | |
192 | | /* increase the length of the message */ |
193 | 0 | md->length += md->curlen * 8; |
194 | | |
195 | | /* append the '1' bit */ |
196 | 0 | md->buf[md->curlen++] = (unsigned char) 0x80; |
197 | | |
198 | | /* if the length is currently above 56 bytes we append zeros |
199 | | * then compress. Then we can fall back to padding zeros and length |
200 | | * encoding like normal. |
201 | | */ |
202 | 0 | if (md->curlen > 56) { |
203 | 0 | while (md->curlen < SHA256_BLOCK_SIZE) { |
204 | 0 | md->buf[md->curlen++] = (unsigned char) 0; |
205 | 0 | } |
206 | 0 | sha256_compress(md, md->buf); |
207 | 0 | md->curlen = 0; |
208 | 0 | } |
209 | | |
210 | | /* pad up to 56 bytes of zeroes */ |
211 | 0 | while (md->curlen < 56) { |
212 | 0 | md->buf[md->curlen++] = (unsigned char) 0; |
213 | 0 | } |
214 | | |
215 | | /* store length */ |
216 | 0 | WPA_PUT_BE64(md->buf + 56, md->length); |
217 | 0 | sha256_compress(md, md->buf); |
218 | | |
219 | | /* copy output */ |
220 | 0 | for (i = 0; i < 8; i++) |
221 | 0 | WPA_PUT_BE32(out + (4 * i), md->state[i]); |
222 | |
|
223 | 0 | return 0; |
224 | 0 | } |
225 | | |
226 | | /* ===== end - public domain SHA256 implementation ===== */ |