1 /** @file sha1.c
2 *
3 * @brief This file defines the sha1 functions
4 *
5 * Copyright (C) 2014-2017, Marvell International Ltd.
6 *
7 * This software file (the "File") is distributed by Marvell International
8 * Ltd. under the terms of the GNU General Public License Version 2, June 1991
9 * (the "License"). You may use, redistribute and/or modify this File in
10 * accordance with the terms and conditions of the License, a copy of which
11 * is available by writing to the Free Software Foundation, Inc.,
12 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
13 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
14 *
15 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
17 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
18 * this warranty disclaimer.
19 */
20
21 /******************************************************
22 Change log:
23 03/07/2014: Initial version
24 ******************************************************/
25 #include "wltypes.h"
26 #include "sha1.h"
27 #include "hostsa_ext_def.h"
28 #include "authenticator.h"
29
30 /*
31 * Define the SHA1 circular left shift macro
32 */
33
34 #define Mrvl_SHA1CircularShift(bits,word) \
35 (((word) << (bits)) | ((word) >> (32-(bits))))
36
37 /* Local Function Prototyptes */
38 static void Mrvl_SHA1PadMessage(Mrvl_SHA1_CTX *);
39 static void Mrvl_SHA1ProcessMessageBlock(Mrvl_SHA1_CTX *);
40 /*
41 * SHA1Init
42 *
43 * Description:
44 * This function will initialize the SHA1_CTX in preparation
45 * for computing a new SHA1 message digest.
46 *
47 * Parameters:
48 * context: [in/out]
49 * The context to reset.
50 *
51 * Returns:
52 * sha Error Code.
53 *
54 */
55 /*int SHA1Init(SHA1_CTX *context) */
56 int
Mrvl_SHA1Init(Mrvl_SHA1_CTX * context)57 Mrvl_SHA1Init(Mrvl_SHA1_CTX *context)
58 {
59 if (!context) {
60 return shaNull;
61 }
62
63 context->Length_Low = 0;
64 context->Length_High = 0;
65 context->Message_Block_Index = 0;
66
67 context->Intermediate_Hash[0] = 0x67452301;
68 context->Intermediate_Hash[1] = 0xEFCDAB89;
69 context->Intermediate_Hash[2] = 0x98BADCFE;
70 context->Intermediate_Hash[3] = 0x10325476;
71 context->Intermediate_Hash[4] = 0xC3D2E1F0;
72
73 context->Computed = 0;
74 context->Corrupted = 0;
75
76 return shaSuccess;
77 }
78
79 /*
80 * SHA1Final
81 *
82 * Description:
83 * This function will return the 160-bit message digest into the
84 * Message_Digest array provided by the caller.
85 * NOTE: The first octet of hash is stored in the 0th element,
86 * the last octet of hash in the 19th element.
87 *
88 * Parameters:
89 * context: [in/out]
90 * The context to use to calculate the SHA-1 hash.
91 * Message_Digest: [out]
92 * Where the digest is returned.
93 *
94 * Returns:
95 * sha Error Code.
96 *
97 */
98 int
Mrvl_SHA1Final(void * priv,Mrvl_SHA1_CTX * context,UINT8 Message_Digest[A_SHA_DIGEST_LEN])99 Mrvl_SHA1Final(void *priv, Mrvl_SHA1_CTX *context,
100 UINT8 Message_Digest[A_SHA_DIGEST_LEN])
101 {
102 phostsa_private psapriv = (phostsa_private)priv;
103 hostsa_util_fns *util_fns = &psapriv->util_fns;
104 int i;
105
106 if (!context || !Message_Digest) {
107 return shaNull;
108 }
109
110 if (context->Corrupted) {
111 return context->Corrupted;
112 }
113
114 if (!context->Computed) {
115 Mrvl_SHA1PadMessage(context);
116 for (i = 0; i < 64; ++i) {
117 /* message may be sensitive, clear it out */
118 context->Message_Block[i] = 0;
119 }
120 context->Length_Low = 0; /* and clear length */
121 context->Length_High = 0;
122 context->Computed = 1;
123
124 }
125
126 for (i = 0; i < A_SHA_DIGEST_LEN; ++i) {
127 Message_Digest[i] = context->Intermediate_Hash[i >> 2]
128 >> 8 * (3 - (i & 0x03));
129 }
130
131 memset(util_fns, context, 0x00, sizeof(Mrvl_SHA1_CTX));
132
133 return shaSuccess;
134 }
135
136 /*
137 * SHA1Update
138 *
139 * Description:
140 * This function accepts an array of octets as the next portion
141 * of the message.
142 *
143 * Parameters:
144 * context: [in/out]
145 * The SHA context to update
146 * message_array: [in]
147 * An array of characters representing the next portion of
148 * the message.
149 * length: [in]
150 * The length of the message in message_array
151 *
152 * Returns:
153 * sha Error Code.
154 *
155 */
156 int
Mrvl_SHA1Update(Mrvl_SHA1_CTX * context,const UINT8 * message_array,unsigned length)157 Mrvl_SHA1Update(Mrvl_SHA1_CTX *context,
158 const UINT8 *message_array, unsigned length)
159 {
160 if (!length) {
161 return shaSuccess;
162 }
163
164 if (!context || !message_array) {
165 return shaNull;
166 }
167
168 if (context->Computed) {
169 context->Corrupted = shaStateError;
170
171 return shaStateError;
172 }
173
174 if (context->Corrupted) {
175 return context->Corrupted;
176 }
177 while (length-- && !context->Corrupted) {
178 context->Message_Block[context->Message_Block_Index++] =
179 (*message_array & 0xFF);
180
181 context->Length_Low += 8;
182 if (context->Length_Low == 0) {
183 context->Length_High++;
184 if (context->Length_High == 0) {
185 /* Message is too long */
186 context->Corrupted = 1;
187 }
188 }
189
190 if (context->Message_Block_Index == 64) {
191 Mrvl_SHA1ProcessMessageBlock(context);
192 }
193
194 message_array++;
195 }
196
197 return shaSuccess;
198 }
199
200 /*
201 * SHA1ProcessMessageBlock
202 *
203 * Description:
204 * This function will process the next 512 bits of the message
205 * stored in the Message_Block array.
206 *
207 * Parameters:
208 * None.
209 *
210 * Returns:
211 * Nothing.
212 *
213 * Comments:
214
215
216
217 Eastlake & Jones Informational [Page 14]
218
219 RFC 3174 US Secure Hash Algorithm 1 (SHA1) September 2001
220
221
222 * Many of the variable names in this code, especially the
223 * single character names, were used because those were the
224 * names used in the publication.
225 *
226 *
227 */
228
229 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
230
231 /* blk0() and blk() perform the initial expand. */
232 /* I got the idea of expanding during the round function from SSLeay */
233 #define blk(i) (W[i&15] = rol(W[(i+13)&15]^W[(i+8)&15]^W[(i+2)&15]^W[i&15],1))
234 #define blk0(i) ((i & 0x30)? blk(i) : W[i])
235
236 /*
237 NOte- Some of the variables are made static in this file because
238 this function runs in the idle task. The idle task dosent have
239 enough stack space to accomodate these variables. In the future
240 if this function is run in a different task with large stack space
241 or if the stack space of the idle task is increased then we can
242 remove the static defination from these variables.
243 */
244 void
Mrvl_SHA1ProcessMessageBlock(Mrvl_SHA1_CTX * context)245 Mrvl_SHA1ProcessMessageBlock(Mrvl_SHA1_CTX *context)
246 {
247 static const UINT32 K[] = { /* Constants defined in SHA-1 */
248 0x5A827999,
249 0x6ED9EBA1,
250 0x8F1BBCDC,
251 0xCA62C1D6
252 };
253 int t; /* Loop counter */
254 UINT32 temp; /* Temporary word value */
255 UINT32 *W;
256 UINT32 A, B, C, D, E; /* Word buffers */
257
258 /* WLAN buffers are aligned, so the context starts at a UINT32 boundary */
259 W = context->Scratch;
260
261 for (t = 0; t < 16; t++) {
262 W[t] = context->Message_Block[t * 4] << 24;
263 W[t] |= context->Message_Block[t * 4 + 1] << 16;
264 W[t] |= context->Message_Block[t * 4 + 2] << 8;
265 W[t] |= context->Message_Block[t * 4 + 3];
266 }
267
268 A = context->Intermediate_Hash[0];
269 B = context->Intermediate_Hash[1];
270 C = context->Intermediate_Hash[2];
271 D = context->Intermediate_Hash[3];
272 E = context->Intermediate_Hash[4];
273
274 for (t = 0; t < 20; t++) {
275 temp = Mrvl_SHA1CircularShift(5, A) +
276 ((B & C) | ((~B) & D)) + E + blk0(t) + K[0];
277 E = D;
278 D = C;
279 C = Mrvl_SHA1CircularShift(30, B);
280
281 B = A;
282 A = temp;
283 }
284
285 for (t = 20; t < 40; t++) {
286 temp = Mrvl_SHA1CircularShift(5,
287 A) + (B ^ C ^ D) + E + blk(t) +
288 K[1];
289 E = D;
290 D = C;
291 C = Mrvl_SHA1CircularShift(30, B);
292 B = A;
293 A = temp;
294 }
295
296 for (t = 40; t < 60; t++) {
297 temp = Mrvl_SHA1CircularShift(5, A) +
298 ((B & C) | (B & D) | (C & D)) + E + blk(t) + K[2];
299 E = D;
300 D = C;
301 C = Mrvl_SHA1CircularShift(30, B);
302 B = A;
303 A = temp;
304 }
305
306 for (t = 60; t < 80; t++) {
307 temp = Mrvl_SHA1CircularShift(5,
308 A) + (B ^ C ^ D) + E + blk(t) +
309 K[3];
310 E = D;
311 D = C;
312 C = Mrvl_SHA1CircularShift(30, B);
313 B = A;
314 A = temp;
315 }
316
317 context->Intermediate_Hash[0] += A;
318 context->Intermediate_Hash[1] += B;
319 context->Intermediate_Hash[2] += C;
320 context->Intermediate_Hash[3] += D;
321 context->Intermediate_Hash[4] += E;
322
323 context->Message_Block_Index = 0;
324 }
325
326 /*
327 * SHA1PadMessage
328 *
329
330
331
332 Eastlake & Jones Informational [Page 16]
333
334 RFC 3174 US Secure Hash Algorithm 1 (SHA1) September 2001
335
336
337 * Description:
338 * According to the standard, the message must be padded to an even
339 * 512 bits. The first padding bit must be a '1'. The last 64
340 * bits represent the length of the original message. All bits in
341 * between should be 0. This function will pad the message
342 * according to those rules by filling the Message_Block array
343 * accordingly. It will also call the ProcessMessageBlock function
344 * provided appropriately. When it returns, it can be assumed that
345 * the message digest has been computed.
346 *
347 * Parameters:
348 * context: [in/out]
349 * The context to pad
350 * ProcessMessageBlock: [in]
351 * The appropriate SHA*ProcessMessageBlock function
352 * Returns:
353 * Nothing.
354 *
355 */
356
357 void
Mrvl_SHA1PadMessage(Mrvl_SHA1_CTX * context)358 Mrvl_SHA1PadMessage(Mrvl_SHA1_CTX *context)
359 {
360 /*
361 * Check to see if the current message block is too small to hold
362 * the initial padding bits and length. If so, we will pad the
363 * block, process it, and then continue padding into a second
364 * block.
365 */
366 if (context->Message_Block_Index > 55) {
367 context->Message_Block[context->Message_Block_Index++] = 0x80;
368 while (context->Message_Block_Index < 64) {
369 context->Message_Block[context->Message_Block_Index++] =
370 0;
371 }
372
373 Mrvl_SHA1ProcessMessageBlock(context);
374
375 while (context->Message_Block_Index < 56) {
376 context->Message_Block[context->Message_Block_Index++] =
377 0;
378 }
379 } else {
380 context->Message_Block[context->Message_Block_Index++] = 0x80;
381 while (context->Message_Block_Index < 56) {
382
383 context->Message_Block[context->Message_Block_Index++] =
384 0;
385 }
386 }
387
388 /*
389 * Store the message length as the last 8 octets
390 */
391 context->Message_Block[56] = context->Length_High >> 24;
392 context->Message_Block[57] = context->Length_High >> 16;
393 context->Message_Block[58] = context->Length_High >> 8;
394 context->Message_Block[59] = context->Length_High;
395 context->Message_Block[60] = context->Length_Low >> 24;
396 context->Message_Block[61] = context->Length_Low >> 16;
397 context->Message_Block[62] = context->Length_Low >> 8;
398 context->Message_Block[63] = context->Length_Low;
399
400 Mrvl_SHA1ProcessMessageBlock(context);
401 }
402