1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 #ifdef FREEBL_NO_DEPEND
6 #include "stubs.h"
7 #endif
8
9 #include <memory.h>
10 #include "blapi.h"
11 #include "sha_fast.h"
12 #include "prerror.h"
13 #include "secerr.h"
14
15 #ifdef TRACING_SSL
16 #include "ssl.h"
17 #include "ssltrace.h"
18 #endif
19
20 static void shaCompress(volatile SHA_HW_t *X, const PRUint32 *datain);
21
22 #define W u.w
23 #define B u.b
24
25 #define SHA_F1(X, Y, Z) ((((Y) ^ (Z)) & (X)) ^ (Z))
26 #define SHA_F2(X, Y, Z) ((X) ^ (Y) ^ (Z))
27 #define SHA_F3(X, Y, Z) (((X) & (Y)) | ((Z) & ((X) | (Y))))
28 #define SHA_F4(X, Y, Z) ((X) ^ (Y) ^ (Z))
29
30 #define SHA_MIX(n, a, b, c) XW(n) = SHA_ROTL(XW(a) ^ XW(b) ^ XW(c) ^ XW(n), 1)
31
32 void SHA1_Compress_Native(SHA1Context *ctx);
33 void SHA1_Update_Native(SHA1Context *ctx, const unsigned char *dataIn, unsigned int len);
34
35 static void SHA1_Compress_Generic(SHA1Context *ctx);
36 static void SHA1_Update_Generic(SHA1Context *ctx, const unsigned char *dataIn, unsigned int len);
37
38 #ifndef USE_HW_SHA1
39 void
SHA1_Compress_Native(SHA1Context * ctx)40 SHA1_Compress_Native(SHA1Context *ctx)
41 {
42 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
43 PORT_Assert(0);
44 }
45
46 void
SHA1_Update_Native(SHA1Context * ctx,const unsigned char * dataIn,unsigned int len)47 SHA1_Update_Native(SHA1Context *ctx, const unsigned char *dataIn, unsigned int len)
48 {
49 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
50 PORT_Assert(0);
51 }
52 #endif
53
54 /*
55 * SHA: initialize context
56 */
57 void
SHA1_Begin(SHA1Context * ctx)58 SHA1_Begin(SHA1Context *ctx)
59 {
60 ctx->size = 0;
61 /*
62 * Initialize H with constants from FIPS180-1.
63 */
64 ctx->H[0] = 0x67452301L;
65 ctx->H[1] = 0xefcdab89L;
66 ctx->H[2] = 0x98badcfeL;
67 ctx->H[3] = 0x10325476L;
68 ctx->H[4] = 0xc3d2e1f0L;
69
70 #if defined(USE_HW_SHA1) && defined(IS_LITTLE_ENDIAN)
71 /* arm's implementation is tested on little endian only */
72 if (arm_sha1_support()) {
73 ctx->compress = SHA1_Compress_Native;
74 ctx->update = SHA1_Update_Native;
75 } else
76 #endif
77 {
78 ctx->compress = SHA1_Compress_Generic;
79 ctx->update = SHA1_Update_Generic;
80 }
81 }
82
83 /* Explanation of H array and index values:
84 * The context's H array is actually the concatenation of two arrays
85 * defined by SHA1, the H array of state variables (5 elements),
86 * and the W array of intermediate values, of which there are 16 elements.
87 * The W array starts at H[5], that is W[0] is H[5].
88 * Although these values are defined as 32-bit values, we use 64-bit
89 * variables to hold them because the AMD64 stores 64 bit values in
90 * memory MUCH faster than it stores any smaller values.
91 *
92 * Rather than passing the context structure to shaCompress, we pass
93 * this combined array of H and W values. We do not pass the address
94 * of the first element of this array, but rather pass the address of an
95 * element in the middle of the array, element X. Presently X[0] is H[11].
96 * So we pass the address of H[11] as the address of array X to shaCompress.
97 * Then shaCompress accesses the members of the array using positive AND
98 * negative indexes.
99 *
100 * Pictorially: (each element is 8 bytes)
101 * H | H0 H1 H2 H3 H4 W0 W1 W2 W3 W4 W5 W6 W7 W8 W9 Wa Wb Wc Wd We Wf |
102 * X |-11-10 -9 -8 -7 -6 -5 -4 -3 -2 -1 X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 |
103 *
104 * The byte offset from X[0] to any member of H and W is always
105 * representable in a signed 8-bit value, which will be encoded
106 * as a single byte offset in the X86-64 instruction set.
107 * If we didn't pass the address of H[11], and instead passed the
108 * address of H[0], the offsets to elements H[16] and above would be
109 * greater than 127, not representable in a signed 8-bit value, and the
110 * x86-64 instruction set would encode every such offset as a 32-bit
111 * signed number in each instruction that accessed element H[16] or
112 * higher. This results in much bigger and slower code.
113 */
114 #if !defined(SHA_PUT_W_IN_STACK)
115 #define H2X 11 /* X[0] is H[11], and H[0] is X[-11] */
116 #define W2X 6 /* X[0] is W[6], and W[0] is X[-6] */
117 #else
118 #define H2X 0
119 #endif
120
121 /*
122 * SHA: Add data to context.
123 */
124 void
SHA1_Update(SHA1Context * ctx,const unsigned char * dataIn,unsigned int len)125 SHA1_Update(SHA1Context *ctx, const unsigned char *dataIn, unsigned int len)
126 {
127 ctx->update(ctx, dataIn, len);
128 }
129
130 static void
SHA1_Update_Generic(SHA1Context * ctx,const unsigned char * dataIn,unsigned int len)131 SHA1_Update_Generic(SHA1Context *ctx, const unsigned char *dataIn, unsigned int len)
132 {
133 register unsigned int lenB;
134 register unsigned int togo;
135
136 if (!len)
137 return;
138
139 /* accumulate the byte count. */
140 lenB = (unsigned int)(ctx->size) & 63U;
141
142 ctx->size += len;
143
144 /*
145 * Read the data into W and process blocks as they get full
146 */
147 if (lenB > 0) {
148 togo = 64U - lenB;
149 if (len < togo)
150 togo = len;
151 memcpy(ctx->B + lenB, dataIn, togo);
152 len -= togo;
153 dataIn += togo;
154 lenB = (lenB + togo) & 63U;
155 if (!lenB) {
156 shaCompress(&ctx->H[H2X], ctx->W);
157 }
158 }
159 #if !defined(HAVE_UNALIGNED_ACCESS)
160 if ((ptrdiff_t)dataIn % sizeof(PRUint32)) {
161 while (len >= 64U) {
162 memcpy(ctx->B, dataIn, 64);
163 len -= 64U;
164 shaCompress(&ctx->H[H2X], ctx->W);
165 dataIn += 64U;
166 }
167 } else
168 #endif
169 {
170 while (len >= 64U) {
171 len -= 64U;
172 shaCompress(&ctx->H[H2X], (PRUint32 *)dataIn);
173 dataIn += 64U;
174 }
175 }
176 if (len) {
177 memcpy(ctx->B, dataIn, len);
178 }
179 }
180
181 /*
182 * SHA: Generate hash value from context
183 */
184 void NO_SANITIZE_ALIGNMENT
SHA1_End(SHA1Context * ctx,unsigned char * hashout,unsigned int * pDigestLen,unsigned int maxDigestLen)185 SHA1_End(SHA1Context *ctx, unsigned char *hashout,
186 unsigned int *pDigestLen, unsigned int maxDigestLen)
187 {
188 register PRUint64 size;
189 register PRUint32 lenB;
190
191 static const unsigned char bulk_pad[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0,
192 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
193 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
194 #define tmp lenB
195
196 PORT_Assert(maxDigestLen >= SHA1_LENGTH);
197
198 /*
199 * Pad with a binary 1 (e.g. 0x80), then zeroes, then length in bits
200 */
201 size = ctx->size;
202
203 lenB = (PRUint32)size & 63;
204 SHA1_Update(ctx, bulk_pad, (((55 + 64) - lenB) & 63) + 1);
205 PORT_Assert(((PRUint32)ctx->size & 63) == 56);
206 /* Convert size from bytes to bits. */
207 size <<= 3;
208 ctx->W[14] = SHA_HTONL((PRUint32)(size >> 32));
209 ctx->W[15] = SHA_HTONL((PRUint32)size);
210 ctx->compress(ctx);
211
212 /*
213 * Output hash
214 */
215 SHA_STORE_RESULT;
216 if (pDigestLen) {
217 *pDigestLen = SHA1_LENGTH;
218 }
219 #undef tmp
220 }
221
222 void
SHA1_EndRaw(SHA1Context * ctx,unsigned char * hashout,unsigned int * pDigestLen,unsigned int maxDigestLen)223 SHA1_EndRaw(SHA1Context *ctx, unsigned char *hashout,
224 unsigned int *pDigestLen, unsigned int maxDigestLen)
225 {
226 #if defined(SHA_NEED_TMP_VARIABLE)
227 register PRUint32 tmp;
228 #endif
229 PORT_Assert(maxDigestLen >= SHA1_LENGTH);
230
231 SHA_STORE_RESULT;
232 if (pDigestLen)
233 *pDigestLen = SHA1_LENGTH;
234 }
235
236 #undef B
237 /*
238 * SHA: Compression function, unrolled.
239 *
240 * Some operations in shaCompress are done as 5 groups of 16 operations.
241 * Others are done as 4 groups of 20 operations.
242 * The code below shows that structure.
243 *
244 * The functions that compute the new values of the 5 state variables
245 * A-E are done in 4 groups of 20 operations (or you may also think
246 * of them as being done in 16 groups of 5 operations). They are
247 * done by the SHA_RNDx macros below, in the right column.
248 *
249 * The functions that set the 16 values of the W array are done in
250 * 5 groups of 16 operations. The first group is done by the
251 * LOAD macros below, the latter 4 groups are done by SHA_MIX below,
252 * in the left column.
253 *
254 * gcc's optimizer observes that each member of the W array is assigned
255 * a value 5 times in this code. It reduces the number of store
256 * operations done to the W array in the context (that is, in the X array)
257 * by creating a W array on the stack, and storing the W values there for
258 * the first 4 groups of operations on W, and storing the values in the
259 * context's W array only in the fifth group. This is undesirable.
260 * It is MUCH bigger code than simply using the context's W array, because
261 * all the offsets to the W array in the stack are 32-bit signed offsets,
262 * and it is no faster than storing the values in the context's W array.
263 *
264 * The original code for sha_fast.c prevented this creation of a separate
265 * W array in the stack by creating a W array of 80 members, each of
266 * whose elements is assigned only once. It also separated the computations
267 * of the W array values and the computations of the values for the 5
268 * state variables into two separate passes, W's, then A-E's so that the
269 * second pass could be done all in registers (except for accessing the W
270 * array) on machines with fewer registers. The method is suboptimal
271 * for machines with enough registers to do it all in one pass, and it
272 * necessitates using many instructions with 32-bit offsets.
273 *
274 * This code eliminates the separate W array on the stack by a completely
275 * different means: by declaring the X array volatile. This prevents
276 * the optimizer from trying to reduce the use of the X array by the
277 * creation of a MORE expensive W array on the stack. The result is
278 * that all instructions use signed 8-bit offsets and not 32-bit offsets.
279 *
280 * The combination of this code and the -O3 optimizer flag on GCC 3.4.3
281 * results in code that is 3 times faster than the previous NSS sha_fast
282 * code on AMD64.
283 */
284 static void NO_SANITIZE_ALIGNMENT
shaCompress(volatile SHA_HW_t * X,const PRUint32 * inbuf)285 shaCompress(volatile SHA_HW_t *X, const PRUint32 *inbuf)
286 {
287 register SHA_HW_t A, B, C, D, E;
288
289 #if defined(SHA_NEED_TMP_VARIABLE)
290 register PRUint32 tmp;
291 #endif
292
293 #if !defined(SHA_PUT_W_IN_STACK)
294 #define XH(n) X[n - H2X]
295 #define XW(n) X[n - W2X]
296 #else
297 SHA_HW_t w_0, w_1, w_2, w_3, w_4, w_5, w_6, w_7,
298 w_8, w_9, w_10, w_11, w_12, w_13, w_14, w_15;
299 #define XW(n) w_##n
300 #define XH(n) X[n]
301 #endif
302
303 #define K0 0x5a827999L
304 #define K1 0x6ed9eba1L
305 #define K2 0x8f1bbcdcL
306 #define K3 0xca62c1d6L
307
308 #define SHA_RND1(a, b, c, d, e, n) \
309 a = SHA_ROTL(b, 5) + SHA_F1(c, d, e) + a + XW(n) + K0; \
310 c = SHA_ROTL(c, 30)
311 #define SHA_RND2(a, b, c, d, e, n) \
312 a = SHA_ROTL(b, 5) + SHA_F2(c, d, e) + a + XW(n) + K1; \
313 c = SHA_ROTL(c, 30)
314 #define SHA_RND3(a, b, c, d, e, n) \
315 a = SHA_ROTL(b, 5) + SHA_F3(c, d, e) + a + XW(n) + K2; \
316 c = SHA_ROTL(c, 30)
317 #define SHA_RND4(a, b, c, d, e, n) \
318 a = SHA_ROTL(b, 5) + SHA_F4(c, d, e) + a + XW(n) + K3; \
319 c = SHA_ROTL(c, 30)
320
321 #define LOAD(n) XW(n) = SHA_HTONL(inbuf[n])
322
323 A = XH(0);
324 B = XH(1);
325 C = XH(2);
326 D = XH(3);
327 E = XH(4);
328
329 LOAD(0);
330 SHA_RND1(E, A, B, C, D, 0);
331 LOAD(1);
332 SHA_RND1(D, E, A, B, C, 1);
333 LOAD(2);
334 SHA_RND1(C, D, E, A, B, 2);
335 LOAD(3);
336 SHA_RND1(B, C, D, E, A, 3);
337 LOAD(4);
338 SHA_RND1(A, B, C, D, E, 4);
339 LOAD(5);
340 SHA_RND1(E, A, B, C, D, 5);
341 LOAD(6);
342 SHA_RND1(D, E, A, B, C, 6);
343 LOAD(7);
344 SHA_RND1(C, D, E, A, B, 7);
345 LOAD(8);
346 SHA_RND1(B, C, D, E, A, 8);
347 LOAD(9);
348 SHA_RND1(A, B, C, D, E, 9);
349 LOAD(10);
350 SHA_RND1(E, A, B, C, D, 10);
351 LOAD(11);
352 SHA_RND1(D, E, A, B, C, 11);
353 LOAD(12);
354 SHA_RND1(C, D, E, A, B, 12);
355 LOAD(13);
356 SHA_RND1(B, C, D, E, A, 13);
357 LOAD(14);
358 SHA_RND1(A, B, C, D, E, 14);
359 LOAD(15);
360 SHA_RND1(E, A, B, C, D, 15);
361
362 SHA_MIX(0, 13, 8, 2);
363 SHA_RND1(D, E, A, B, C, 0);
364 SHA_MIX(1, 14, 9, 3);
365 SHA_RND1(C, D, E, A, B, 1);
366 SHA_MIX(2, 15, 10, 4);
367 SHA_RND1(B, C, D, E, A, 2);
368 SHA_MIX(3, 0, 11, 5);
369 SHA_RND1(A, B, C, D, E, 3);
370
371 SHA_MIX(4, 1, 12, 6);
372 SHA_RND2(E, A, B, C, D, 4);
373 SHA_MIX(5, 2, 13, 7);
374 SHA_RND2(D, E, A, B, C, 5);
375 SHA_MIX(6, 3, 14, 8);
376 SHA_RND2(C, D, E, A, B, 6);
377 SHA_MIX(7, 4, 15, 9);
378 SHA_RND2(B, C, D, E, A, 7);
379 SHA_MIX(8, 5, 0, 10);
380 SHA_RND2(A, B, C, D, E, 8);
381 SHA_MIX(9, 6, 1, 11);
382 SHA_RND2(E, A, B, C, D, 9);
383 SHA_MIX(10, 7, 2, 12);
384 SHA_RND2(D, E, A, B, C, 10);
385 SHA_MIX(11, 8, 3, 13);
386 SHA_RND2(C, D, E, A, B, 11);
387 SHA_MIX(12, 9, 4, 14);
388 SHA_RND2(B, C, D, E, A, 12);
389 SHA_MIX(13, 10, 5, 15);
390 SHA_RND2(A, B, C, D, E, 13);
391 SHA_MIX(14, 11, 6, 0);
392 SHA_RND2(E, A, B, C, D, 14);
393 SHA_MIX(15, 12, 7, 1);
394 SHA_RND2(D, E, A, B, C, 15);
395
396 SHA_MIX(0, 13, 8, 2);
397 SHA_RND2(C, D, E, A, B, 0);
398 SHA_MIX(1, 14, 9, 3);
399 SHA_RND2(B, C, D, E, A, 1);
400 SHA_MIX(2, 15, 10, 4);
401 SHA_RND2(A, B, C, D, E, 2);
402 SHA_MIX(3, 0, 11, 5);
403 SHA_RND2(E, A, B, C, D, 3);
404 SHA_MIX(4, 1, 12, 6);
405 SHA_RND2(D, E, A, B, C, 4);
406 SHA_MIX(5, 2, 13, 7);
407 SHA_RND2(C, D, E, A, B, 5);
408 SHA_MIX(6, 3, 14, 8);
409 SHA_RND2(B, C, D, E, A, 6);
410 SHA_MIX(7, 4, 15, 9);
411 SHA_RND2(A, B, C, D, E, 7);
412
413 SHA_MIX(8, 5, 0, 10);
414 SHA_RND3(E, A, B, C, D, 8);
415 SHA_MIX(9, 6, 1, 11);
416 SHA_RND3(D, E, A, B, C, 9);
417 SHA_MIX(10, 7, 2, 12);
418 SHA_RND3(C, D, E, A, B, 10);
419 SHA_MIX(11, 8, 3, 13);
420 SHA_RND3(B, C, D, E, A, 11);
421 SHA_MIX(12, 9, 4, 14);
422 SHA_RND3(A, B, C, D, E, 12);
423 SHA_MIX(13, 10, 5, 15);
424 SHA_RND3(E, A, B, C, D, 13);
425 SHA_MIX(14, 11, 6, 0);
426 SHA_RND3(D, E, A, B, C, 14);
427 SHA_MIX(15, 12, 7, 1);
428 SHA_RND3(C, D, E, A, B, 15);
429
430 SHA_MIX(0, 13, 8, 2);
431 SHA_RND3(B, C, D, E, A, 0);
432 SHA_MIX(1, 14, 9, 3);
433 SHA_RND3(A, B, C, D, E, 1);
434 SHA_MIX(2, 15, 10, 4);
435 SHA_RND3(E, A, B, C, D, 2);
436 SHA_MIX(3, 0, 11, 5);
437 SHA_RND3(D, E, A, B, C, 3);
438 SHA_MIX(4, 1, 12, 6);
439 SHA_RND3(C, D, E, A, B, 4);
440 SHA_MIX(5, 2, 13, 7);
441 SHA_RND3(B, C, D, E, A, 5);
442 SHA_MIX(6, 3, 14, 8);
443 SHA_RND3(A, B, C, D, E, 6);
444 SHA_MIX(7, 4, 15, 9);
445 SHA_RND3(E, A, B, C, D, 7);
446 SHA_MIX(8, 5, 0, 10);
447 SHA_RND3(D, E, A, B, C, 8);
448 SHA_MIX(9, 6, 1, 11);
449 SHA_RND3(C, D, E, A, B, 9);
450 SHA_MIX(10, 7, 2, 12);
451 SHA_RND3(B, C, D, E, A, 10);
452 SHA_MIX(11, 8, 3, 13);
453 SHA_RND3(A, B, C, D, E, 11);
454
455 SHA_MIX(12, 9, 4, 14);
456 SHA_RND4(E, A, B, C, D, 12);
457 SHA_MIX(13, 10, 5, 15);
458 SHA_RND4(D, E, A, B, C, 13);
459 SHA_MIX(14, 11, 6, 0);
460 SHA_RND4(C, D, E, A, B, 14);
461 SHA_MIX(15, 12, 7, 1);
462 SHA_RND4(B, C, D, E, A, 15);
463
464 SHA_MIX(0, 13, 8, 2);
465 SHA_RND4(A, B, C, D, E, 0);
466 SHA_MIX(1, 14, 9, 3);
467 SHA_RND4(E, A, B, C, D, 1);
468 SHA_MIX(2, 15, 10, 4);
469 SHA_RND4(D, E, A, B, C, 2);
470 SHA_MIX(3, 0, 11, 5);
471 SHA_RND4(C, D, E, A, B, 3);
472 SHA_MIX(4, 1, 12, 6);
473 SHA_RND4(B, C, D, E, A, 4);
474 SHA_MIX(5, 2, 13, 7);
475 SHA_RND4(A, B, C, D, E, 5);
476 SHA_MIX(6, 3, 14, 8);
477 SHA_RND4(E, A, B, C, D, 6);
478 SHA_MIX(7, 4, 15, 9);
479 SHA_RND4(D, E, A, B, C, 7);
480 SHA_MIX(8, 5, 0, 10);
481 SHA_RND4(C, D, E, A, B, 8);
482 SHA_MIX(9, 6, 1, 11);
483 SHA_RND4(B, C, D, E, A, 9);
484 SHA_MIX(10, 7, 2, 12);
485 SHA_RND4(A, B, C, D, E, 10);
486 SHA_MIX(11, 8, 3, 13);
487 SHA_RND4(E, A, B, C, D, 11);
488 SHA_MIX(12, 9, 4, 14);
489 SHA_RND4(D, E, A, B, C, 12);
490 SHA_MIX(13, 10, 5, 15);
491 SHA_RND4(C, D, E, A, B, 13);
492 SHA_MIX(14, 11, 6, 0);
493 SHA_RND4(B, C, D, E, A, 14);
494 SHA_MIX(15, 12, 7, 1);
495 SHA_RND4(A, B, C, D, E, 15);
496
497 XH(0) += A;
498 XH(1) += B;
499 XH(2) += C;
500 XH(3) += D;
501 XH(4) += E;
502 }
503
504 static void
SHA1_Compress_Generic(SHA1Context * ctx)505 SHA1_Compress_Generic(SHA1Context *ctx)
506 {
507 shaCompress(&ctx->H[H2X], ctx->u.w);
508 }
509
510 /*************************************************************************
511 ** Code below this line added to make SHA code support BLAPI interface
512 */
513
514 SHA1Context *
SHA1_NewContext(void)515 SHA1_NewContext(void)
516 {
517 SHA1Context *cx;
518
519 /* no need to ZNew, SHA1_Begin will init the context */
520 cx = PORT_New(SHA1Context);
521 return cx;
522 }
523
524 /* Zero and free the context */
525 void
SHA1_DestroyContext(SHA1Context * cx,PRBool freeit)526 SHA1_DestroyContext(SHA1Context *cx, PRBool freeit)
527 {
528 memset(cx, 0, sizeof *cx);
529 if (freeit) {
530 PORT_Free(cx);
531 }
532 }
533
534 SECStatus
SHA1_HashBuf(unsigned char * dest,const unsigned char * src,PRUint32 src_length)535 SHA1_HashBuf(unsigned char *dest, const unsigned char *src, PRUint32 src_length)
536 {
537 SHA1Context ctx;
538 unsigned int outLen;
539
540 SHA1_Begin(&ctx);
541 ctx.update(&ctx, src, src_length);
542 SHA1_End(&ctx, dest, &outLen, SHA1_LENGTH);
543 memset(&ctx, 0, sizeof ctx);
544 return SECSuccess;
545 }
546
547 /* Hash a null-terminated character string. */
548 SECStatus
SHA1_Hash(unsigned char * dest,const char * src)549 SHA1_Hash(unsigned char *dest, const char *src)
550 {
551 return SHA1_HashBuf(dest, (const unsigned char *)src, PORT_Strlen(src));
552 }
553
554 /*
555 * need to support save/restore state in pkcs11. Stores all the info necessary
556 * for a structure into just a stream of bytes.
557 */
558 unsigned int
SHA1_FlattenSize(SHA1Context * cx)559 SHA1_FlattenSize(SHA1Context *cx)
560 {
561 return sizeof(SHA1Context);
562 }
563
564 SECStatus
SHA1_Flatten(SHA1Context * cx,unsigned char * space)565 SHA1_Flatten(SHA1Context *cx, unsigned char *space)
566 {
567 PORT_Memcpy(space, cx, sizeof(SHA1Context));
568 return SECSuccess;
569 }
570
571 SHA1Context *
SHA1_Resurrect(unsigned char * space,void * arg)572 SHA1_Resurrect(unsigned char *space, void *arg)
573 {
574 SHA1Context *cx = SHA1_NewContext();
575 if (cx == NULL)
576 return NULL;
577
578 PORT_Memcpy(cx, space, sizeof(SHA1Context));
579 return cx;
580 }
581
582 void
SHA1_Clone(SHA1Context * dest,SHA1Context * src)583 SHA1_Clone(SHA1Context *dest, SHA1Context *src)
584 {
585 memcpy(dest, src, sizeof *dest);
586 }
587
588 void
SHA1_TraceState(SHA1Context * ctx)589 SHA1_TraceState(SHA1Context *ctx)
590 {
591 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
592 }
593