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