1251875Speter/* Licensed to the Apache Software Foundation (ASF) under one or more
2251875Speter * contributor license agreements.  See the NOTICE file distributed with
3251875Speter * this work for additional information regarding copyright ownership.
4251875Speter * The ASF licenses this file to You under the Apache License, Version 2.0
5251875Speter * (the "License"); you may not use this file except in compliance with
6251875Speter * the License.  You may obtain a copy of the License at
7251875Speter *
8251875Speter *     http://www.apache.org/licenses/LICENSE-2.0
9251875Speter *
10251875Speter * Unless required by applicable law or agreed to in writing, software
11251875Speter * distributed under the License is distributed on an "AS IS" BASIS,
12251875Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13251875Speter * See the License for the specific language governing permissions and
14251875Speter * limitations under the License.
15251875Speter */
16251875Speter/*
17251875Speter * FILE:        sha2.c
18251875Speter * AUTHOR:      Aaron D. Gifford <me@aarongifford.com>
19251875Speter *
20251875Speter * A licence was granted to the ASF by Aaron on 4 November 2003.
21251875Speter */
22251875Speter
23251875Speter#include <string.h>     /* memcpy()/memset() or bcopy()/bzero() */
24251875Speter#include <assert.h>     /* assert() */
25251875Speter#include "sha2.h"
26251875Speter
27251875Speter/*
28251875Speter * ASSERT NOTE:
29251875Speter * Some sanity checking code is included using assert().  On my FreeBSD
30251875Speter * system, this additional code can be removed by compiling with NDEBUG
31251875Speter * defined.  Check your own systems manpage on assert() to see how to
32251875Speter * compile WITHOUT the sanity checking code on your system.
33251875Speter *
34251875Speter * UNROLLED TRANSFORM LOOP NOTE:
35251875Speter * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform
36251875Speter * loop version for the hash transform rounds (defined using macros
37251875Speter * later in this file).  Either define on the command line, for example:
38251875Speter *
39251875Speter *   cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c
40251875Speter *
41251875Speter * or define below:
42251875Speter *
43251875Speter *   #define SHA2_UNROLL_TRANSFORM
44251875Speter *
45251875Speter */
46251875Speter
47251875Speter/*** SHA-256/384/512 Machine Architecture Definitions *****************/
48251875Spetertypedef apr_byte_t   sha2_byte;         /* Exactly 1 byte */
49251875Spetertypedef apr_uint32_t sha2_word32;       /* Exactly 4 bytes */
50251875Spetertypedef apr_uint64_t sha2_word64;       /* Exactly 8 bytes */
51251875Speter
52251875Speter/*** SHA-256/384/512 Various Length Definitions ***********************/
53251875Speter/* NOTE: Most of these are in sha2.h */
54251875Speter#define SHA256_SHORT_BLOCK_LENGTH       (SHA256_BLOCK_LENGTH - 8)
55251875Speter
56251875Speter
57251875Speter/*** ENDIAN REVERSAL MACROS *******************************************/
58251875Speter#if !APR_IS_BIGENDIAN
59251875Speter#define REVERSE32(w,x)  { \
60251875Speter        sha2_word32 tmp = (w); \
61251875Speter        tmp = (tmp >> 16) | (tmp << 16); \
62251875Speter        (x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \
63251875Speter}
64251875Speter#define REVERSE64(w,x)  { \
65251875Speter        sha2_word64 tmp = (w); \
66251875Speter        tmp = (tmp >> 32) | (tmp << 32); \
67251875Speter        tmp = ((tmp & APR_UINT64_C(0xff00ff00ff00ff00)) >> 8) | \
68251875Speter              ((tmp & APR_UINT64_C(0x00ff00ff00ff00ff)) << 8); \
69251875Speter        (x) = ((tmp & APR_UINT64_C(0xffff0000ffff0000)) >> 16) | \
70251875Speter              ((tmp & APR_UINT64_C(0x0000ffff0000ffff)) << 16); \
71251875Speter}
72251875Speter#endif /* !APR_IS_BIGENDIAN */
73251875Speter
74251875Speter/*
75251875Speter * Macro for incrementally adding the unsigned 64-bit integer n to the
76251875Speter * unsigned 128-bit integer (represented using a two-element array of
77251875Speter * 64-bit words):
78251875Speter */
79251875Speter#define ADDINC128(w,n)  { \
80251875Speter        (w)[0] += (sha2_word64)(n); \
81251875Speter        if ((w)[0] < (n)) { \
82251875Speter                (w)[1]++; \
83251875Speter        } \
84251875Speter}
85251875Speter
86251875Speter/*
87251875Speter * Macros for copying blocks of memory and for zeroing out ranges
88251875Speter * of memory.  Using these macros makes it easy to switch from
89251875Speter * using memset()/memcpy() and using bzero()/bcopy().
90251875Speter *
91251875Speter * Please define either SHA2_USE_MEMSET_MEMCPY or define
92251875Speter * SHA2_USE_BZERO_BCOPY depending on which function set you
93251875Speter * choose to use:
94251875Speter */
95251875Speter#if !defined(SHA2_USE_MEMSET_MEMCPY) && !defined(SHA2_USE_BZERO_BCOPY)
96251875Speter/* Default to memset()/memcpy() if no option is specified */
97251875Speter#define SHA2_USE_MEMSET_MEMCPY  1
98251875Speter#endif
99251875Speter#if defined(SHA2_USE_MEMSET_MEMCPY) && defined(SHA2_USE_BZERO_BCOPY)
100251875Speter/* Abort with an error if BOTH options are defined */
101251875Speter#error Define either SHA2_USE_MEMSET_MEMCPY or SHA2_USE_BZERO_BCOPY, not both!
102251875Speter#endif
103251875Speter
104251875Speter#ifdef SHA2_USE_MEMSET_MEMCPY
105251875Speter#define MEMSET_BZERO(p,l)       memset((p), 0, (l))
106251875Speter#define MEMCPY_BCOPY(d,s,l)     memcpy((d), (s), (l))
107251875Speter#endif
108251875Speter#ifdef SHA2_USE_BZERO_BCOPY
109251875Speter#define MEMSET_BZERO(p,l)       bzero((p), (l))
110251875Speter#define MEMCPY_BCOPY(d,s,l)     bcopy((s), (d), (l))
111251875Speter#endif
112251875Speter
113251875Speter
114251875Speter/*** THE SIX LOGICAL FUNCTIONS ****************************************/
115251875Speter/*
116251875Speter * Bit shifting and rotation (used by the six SHA-XYZ logical functions:
117251875Speter *
118251875Speter *   NOTE:  The naming of R and S appears backwards here (R is a SHIFT and
119251875Speter *   S is a ROTATION) because the SHA-256/384/512 description document
120251875Speter *   (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this
121251875Speter *   same "backwards" definition.
122251875Speter */
123251875Speter/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */
124251875Speter#define R(b,x)          ((x) >> (b))
125251875Speter/* 32-bit Rotate-right (used in SHA-256): */
126251875Speter#define S32(b,x)        (((x) >> (b)) | ((x) << (32 - (b))))
127251875Speter/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */
128251875Speter#define S64(b,x)        (((x) >> (b)) | ((x) << (64 - (b))))
129251875Speter
130251875Speter/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */
131251875Speter#define Ch(x,y,z)       (((x) & (y)) ^ ((~(x)) & (z)))
132251875Speter#define Maj(x,y,z)      (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
133251875Speter
134251875Speter/* Four of six logical functions used in SHA-256: */
135251875Speter#define Sigma0_256(x)   (S32(2,  (x)) ^ S32(13, (x)) ^ S32(22, (x)))
136251875Speter#define Sigma1_256(x)   (S32(6,  (x)) ^ S32(11, (x)) ^ S32(25, (x)))
137251875Speter#define sigma0_256(x)   (S32(7,  (x)) ^ S32(18, (x)) ^ R(3 ,   (x)))
138251875Speter#define sigma1_256(x)   (S32(17, (x)) ^ S32(19, (x)) ^ R(10,   (x)))
139251875Speter
140251875Speter/* Four of six logical functions used in SHA-384 and SHA-512: */
141251875Speter#define Sigma0_512(x)   (S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x)))
142251875Speter#define Sigma1_512(x)   (S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x)))
143251875Speter#define sigma0_512(x)   (S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7,   (x)))
144251875Speter#define sigma1_512(x)   (S64(19, (x)) ^ S64(61, (x)) ^ R( 6,   (x)))
145251875Speter
146251875Speter/*** INTERNAL FUNCTION PROTOTYPES *************************************/
147251875Speter/* NOTE: These should not be accessed directly from outside this
148251875Speter * library -- they are intended for private internal visibility/use
149251875Speter * only.
150251875Speter */
151251875Spetervoid apr__SHA256_Transform(SHA256_CTX*, const sha2_word32*);
152251875Speter
153251875Speter
154251875Speter/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/
155251875Speter/* Hash constant words K for SHA-256: */
156251875Speterstatic const sha2_word32 K256[64] = {
157251875Speter        0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
158251875Speter        0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
159251875Speter        0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
160251875Speter        0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
161251875Speter        0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
162251875Speter        0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
163251875Speter        0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
164251875Speter        0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
165251875Speter        0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
166251875Speter        0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
167251875Speter        0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
168251875Speter        0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
169251875Speter        0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
170251875Speter        0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
171251875Speter        0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
172251875Speter        0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
173251875Speter};
174251875Speter
175251875Speter/* Initial hash value H for SHA-256: */
176251875Speterstatic const sha2_word32 sha256_initial_hash_value[8] = {
177251875Speter        0x6a09e667UL,
178251875Speter        0xbb67ae85UL,
179251875Speter        0x3c6ef372UL,
180251875Speter        0xa54ff53aUL,
181251875Speter        0x510e527fUL,
182251875Speter        0x9b05688cUL,
183251875Speter        0x1f83d9abUL,
184251875Speter        0x5be0cd19UL
185251875Speter};
186251875Speter
187251875Speter/*
188251875Speter * Constant used by SHA256/384/512_End() functions for converting the
189251875Speter * digest to a readable hexadecimal character string:
190251875Speter */
191251875Speterstatic const char *sha2_hex_digits = "0123456789abcdef";
192251875Speter
193251875Speter
194251875Speter/*** SHA-256: *********************************************************/
195251875Spetervoid apr__SHA256_Init(SHA256_CTX* context) {
196251875Speter        if (context == (SHA256_CTX*)0) {
197251875Speter                return;
198251875Speter        }
199251875Speter        MEMCPY_BCOPY(context->state, sha256_initial_hash_value, SHA256_DIGEST_LENGTH);
200251875Speter        MEMSET_BZERO(context->buffer, SHA256_BLOCK_LENGTH);
201251875Speter        context->bitcount = 0;
202251875Speter}
203251875Speter
204251875Speter#ifdef SHA2_UNROLL_TRANSFORM
205251875Speter
206251875Speter/* Unrolled SHA-256 round macros: */
207251875Speter
208251875Speter#if !APR_IS_BIGENDIAN
209251875Speter
210251875Speter#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h)       \
211251875Speter        REVERSE32(*data++, W256[j]); \
212251875Speter        T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
213251875Speter             K256[j] + W256[j]; \
214251875Speter        (d) += T1; \
215251875Speter        (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
216251875Speter        j++
217251875Speter
218251875Speter
219251875Speter#else /* APR_IS_BIGENDIAN */
220251875Speter
221251875Speter#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h)       \
222251875Speter        T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
223251875Speter             K256[j] + (W256[j] = *data++); \
224251875Speter        (d) += T1; \
225251875Speter        (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
226251875Speter        j++
227251875Speter
228251875Speter#endif /* APR_IS_BIGENDIAN */
229251875Speter
230251875Speter#define ROUND256(a,b,c,d,e,f,g,h)       \
231251875Speter        s0 = W256[(j+1)&0x0f]; \
232251875Speter        s0 = sigma0_256(s0); \
233251875Speter        s1 = W256[(j+14)&0x0f]; \
234251875Speter        s1 = sigma1_256(s1); \
235251875Speter        T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \
236251875Speter             (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \
237251875Speter        (d) += T1; \
238251875Speter        (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
239251875Speter        j++
240251875Speter
241251875Spetervoid apr__SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) {
242251875Speter        sha2_word32     a, b, c, d, e, f, g, h, s0, s1;
243251875Speter        sha2_word32     T1, *W256;
244251875Speter        int             j;
245251875Speter
246251875Speter        W256 = (sha2_word32*)context->buffer;
247251875Speter
248251875Speter        /* Initialize registers with the prev. intermediate value */
249251875Speter        a = context->state[0];
250251875Speter        b = context->state[1];
251251875Speter        c = context->state[2];
252251875Speter        d = context->state[3];
253251875Speter        e = context->state[4];
254251875Speter        f = context->state[5];
255251875Speter        g = context->state[6];
256251875Speter        h = context->state[7];
257251875Speter
258251875Speter        j = 0;
259251875Speter        do {
260251875Speter                /* Rounds 0 to 15 (unrolled): */
261251875Speter                ROUND256_0_TO_15(a,b,c,d,e,f,g,h);
262251875Speter                ROUND256_0_TO_15(h,a,b,c,d,e,f,g);
263251875Speter                ROUND256_0_TO_15(g,h,a,b,c,d,e,f);
264251875Speter                ROUND256_0_TO_15(f,g,h,a,b,c,d,e);
265251875Speter                ROUND256_0_TO_15(e,f,g,h,a,b,c,d);
266251875Speter                ROUND256_0_TO_15(d,e,f,g,h,a,b,c);
267251875Speter                ROUND256_0_TO_15(c,d,e,f,g,h,a,b);
268251875Speter                ROUND256_0_TO_15(b,c,d,e,f,g,h,a);
269251875Speter        } while (j < 16);
270251875Speter
271251875Speter        /* Now for the remaining rounds to 64: */
272251875Speter        do {
273251875Speter                ROUND256(a,b,c,d,e,f,g,h);
274251875Speter                ROUND256(h,a,b,c,d,e,f,g);
275251875Speter                ROUND256(g,h,a,b,c,d,e,f);
276251875Speter                ROUND256(f,g,h,a,b,c,d,e);
277251875Speter                ROUND256(e,f,g,h,a,b,c,d);
278251875Speter                ROUND256(d,e,f,g,h,a,b,c);
279251875Speter                ROUND256(c,d,e,f,g,h,a,b);
280251875Speter                ROUND256(b,c,d,e,f,g,h,a);
281251875Speter        } while (j < 64);
282251875Speter
283251875Speter        /* Compute the current intermediate hash value */
284251875Speter        context->state[0] += a;
285251875Speter        context->state[1] += b;
286251875Speter        context->state[2] += c;
287251875Speter        context->state[3] += d;
288251875Speter        context->state[4] += e;
289251875Speter        context->state[5] += f;
290251875Speter        context->state[6] += g;
291251875Speter        context->state[7] += h;
292251875Speter
293251875Speter        /* Clean up */
294251875Speter        a = b = c = d = e = f = g = h = T1 = 0;
295251875Speter}
296251875Speter
297251875Speter#else /* SHA2_UNROLL_TRANSFORM */
298251875Speter
299251875Spetervoid apr__SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) {
300251875Speter        sha2_word32     a, b, c, d, e, f, g, h, s0, s1;
301251875Speter        sha2_word32     T1, T2, *W256;
302251875Speter        int             j;
303251875Speter
304251875Speter        W256 = (sha2_word32*)context->buffer;
305251875Speter
306251875Speter        /* Initialize registers with the prev. intermediate value */
307251875Speter        a = context->state[0];
308251875Speter        b = context->state[1];
309251875Speter        c = context->state[2];
310251875Speter        d = context->state[3];
311251875Speter        e = context->state[4];
312251875Speter        f = context->state[5];
313251875Speter        g = context->state[6];
314251875Speter        h = context->state[7];
315251875Speter
316251875Speter        j = 0;
317251875Speter        do {
318251875Speter#if !APR_IS_BIGENDIAN
319251875Speter                /* Copy data while converting to host byte order */
320251875Speter                REVERSE32(*data++,W256[j]);
321251875Speter                /* Apply the SHA-256 compression function to update a..h */
322251875Speter                T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j];
323251875Speter#else /* APR_IS_BIGENDIAN */
324251875Speter                /* Apply the SHA-256 compression function to update a..h with copy */
325251875Speter                T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++);
326251875Speter#endif /* APR_IS_BIGENDIAN */
327251875Speter                T2 = Sigma0_256(a) + Maj(a, b, c);
328251875Speter                h = g;
329251875Speter                g = f;
330251875Speter                f = e;
331251875Speter                e = d + T1;
332251875Speter                d = c;
333251875Speter                c = b;
334251875Speter                b = a;
335251875Speter                a = T1 + T2;
336251875Speter
337251875Speter                j++;
338251875Speter        } while (j < 16);
339251875Speter
340251875Speter        do {
341251875Speter                /* Part of the message block expansion: */
342251875Speter                s0 = W256[(j+1)&0x0f];
343251875Speter                s0 = sigma0_256(s0);
344251875Speter                s1 = W256[(j+14)&0x0f];
345251875Speter                s1 = sigma1_256(s1);
346251875Speter
347251875Speter                /* Apply the SHA-256 compression function to update a..h */
348251875Speter                T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] +
349251875Speter                     (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0);
350251875Speter                T2 = Sigma0_256(a) + Maj(a, b, c);
351251875Speter                h = g;
352251875Speter                g = f;
353251875Speter                f = e;
354251875Speter                e = d + T1;
355251875Speter                d = c;
356251875Speter                c = b;
357251875Speter                b = a;
358251875Speter                a = T1 + T2;
359251875Speter
360251875Speter                j++;
361251875Speter        } while (j < 64);
362251875Speter
363251875Speter        /* Compute the current intermediate hash value */
364251875Speter        context->state[0] += a;
365251875Speter        context->state[1] += b;
366251875Speter        context->state[2] += c;
367251875Speter        context->state[3] += d;
368251875Speter        context->state[4] += e;
369251875Speter        context->state[5] += f;
370251875Speter        context->state[6] += g;
371251875Speter        context->state[7] += h;
372251875Speter
373251875Speter        /* Clean up */
374251875Speter        a = b = c = d = e = f = g = h = T1 = T2 = 0;
375251875Speter}
376251875Speter
377251875Speter#endif /* SHA2_UNROLL_TRANSFORM */
378251875Speter
379251875Spetervoid apr__SHA256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) {
380251875Speter        unsigned int    freespace, usedspace;
381251875Speter
382251875Speter        if (len == 0) {
383251875Speter                /* Calling with no data is valid - we do nothing */
384251875Speter                return;
385251875Speter        }
386251875Speter
387251875Speter        /* Sanity check: */
388251875Speter        assert(context != (SHA256_CTX*)0 && data != (sha2_byte*)0);
389251875Speter
390251875Speter        usedspace = (unsigned int)((context->bitcount >> 3)
391251875Speter                                 % SHA256_BLOCK_LENGTH);
392251875Speter        if (usedspace > 0) {
393251875Speter                /* Calculate how much free space is available in the buffer */
394251875Speter                freespace = SHA256_BLOCK_LENGTH - usedspace;
395251875Speter
396251875Speter                if (len >= freespace) {
397251875Speter                        /* Fill the buffer completely and process it */
398251875Speter                        MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace);
399251875Speter                        context->bitcount += freespace << 3;
400251875Speter                        len -= freespace;
401251875Speter                        data += freespace;
402251875Speter                        apr__SHA256_Transform(context, (sha2_word32*)context->buffer);
403251875Speter                } else {
404251875Speter                        /* The buffer is not yet full */
405251875Speter                        MEMCPY_BCOPY(&context->buffer[usedspace], data, len);
406251875Speter                        context->bitcount += len << 3;
407251875Speter                        /* Clean up: */
408251875Speter                        usedspace = freespace = 0;
409251875Speter                        return;
410251875Speter                }
411251875Speter        }
412251875Speter        while (len >= SHA256_BLOCK_LENGTH) {
413251875Speter                /* Process as many complete blocks as we can */
414251875Speter                apr__SHA256_Transform(context, (sha2_word32*)data);
415251875Speter                context->bitcount += SHA256_BLOCK_LENGTH << 3;
416251875Speter                len -= SHA256_BLOCK_LENGTH;
417251875Speter                data += SHA256_BLOCK_LENGTH;
418251875Speter        }
419251875Speter        if (len > 0) {
420251875Speter                /* There's left-overs, so save 'em */
421251875Speter                MEMCPY_BCOPY(context->buffer, data, len);
422251875Speter                context->bitcount += len << 3;
423251875Speter        }
424251875Speter        /* Clean up: */
425251875Speter        usedspace = freespace = 0;
426251875Speter}
427251875Speter
428370556Semastevoid apr__SHA256_Final(sha2_byte digest[SHA256_DIGEST_LENGTH], SHA256_CTX* context) {
429251875Speter        sha2_word32     *d = (sha2_word32*)digest;
430251875Speter        unsigned int    usedspace;
431251875Speter
432251875Speter        /* Sanity check: */
433251875Speter        assert(context != (SHA256_CTX*)0);
434251875Speter
435251875Speter        /* If no digest buffer is passed, we don't bother doing this: */
436251875Speter        if (digest != (sha2_byte*)0) {
437251875Speter                usedspace = (unsigned int)((context->bitcount >> 3)
438251875Speter                                         % SHA256_BLOCK_LENGTH);
439251875Speter#if !APR_IS_BIGENDIAN
440251875Speter                /* Convert FROM host byte order */
441251875Speter                REVERSE64(context->bitcount,context->bitcount);
442251875Speter#endif
443251875Speter                if (usedspace > 0) {
444251875Speter                        /* Begin padding with a 1 bit: */
445251875Speter                        context->buffer[usedspace++] = 0x80;
446251875Speter
447251875Speter                        if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) {
448251875Speter                                /* Set-up for the last transform: */
449251875Speter                                MEMSET_BZERO(&context->buffer[usedspace], SHA256_SHORT_BLOCK_LENGTH - usedspace);
450251875Speter                        } else {
451251875Speter                                if (usedspace < SHA256_BLOCK_LENGTH) {
452251875Speter                                        MEMSET_BZERO(&context->buffer[usedspace], SHA256_BLOCK_LENGTH - usedspace);
453251875Speter                                }
454251875Speter                                /* Do second-to-last transform: */
455251875Speter                                apr__SHA256_Transform(context, (sha2_word32*)context->buffer);
456251875Speter
457251875Speter                                /* And set-up for the last transform: */
458251875Speter                                MEMSET_BZERO(context->buffer, SHA256_SHORT_BLOCK_LENGTH);
459251875Speter                        }
460251875Speter                } else {
461251875Speter                        /* Set-up for the last transform: */
462251875Speter                        MEMSET_BZERO(context->buffer, SHA256_SHORT_BLOCK_LENGTH);
463251875Speter
464251875Speter                        /* Begin padding with a 1 bit: */
465251875Speter                        *context->buffer = 0x80;
466251875Speter                }
467251875Speter                /* Set the bit count: */
468253734Speter                {
469253734Speter                        union dummy {
470253734Speter                                apr_uint64_t bitcount;
471253734Speter                                apr_byte_t bytes[8];
472253734Speter                        } bitcount;
473253734Speter                        bitcount.bitcount = context->bitcount;
474253734Speter                        MEMCPY_BCOPY(&context->buffer[SHA256_SHORT_BLOCK_LENGTH], bitcount.bytes, 8);
475253734Speter                }
476251875Speter
477251875Speter                /* Final transform: */
478251875Speter                apr__SHA256_Transform(context, (sha2_word32*)context->buffer);
479251875Speter
480251875Speter#if !APR_IS_BIGENDIAN
481251875Speter                {
482251875Speter                        /* Convert TO host byte order */
483251875Speter                        int     j;
484251875Speter                        for (j = 0; j < 8; j++) {
485251875Speter                                REVERSE32(context->state[j],context->state[j]);
486251875Speter                                *d++ = context->state[j];
487251875Speter                        }
488251875Speter                }
489251875Speter#else
490251875Speter                MEMCPY_BCOPY(d, context->state, SHA256_DIGEST_LENGTH);
491251875Speter#endif
492251875Speter        }
493251875Speter
494251875Speter        /* Clean up state data: */
495251875Speter        MEMSET_BZERO(context, sizeof(*context));
496251875Speter        usedspace = 0;
497251875Speter}
498251875Speter
499370556Semastechar *apr__SHA256_End(SHA256_CTX* context, char buffer[SHA256_DIGEST_STRING_LENGTH]) {
500251875Speter        sha2_byte       digest[SHA256_DIGEST_LENGTH], *d = digest;
501251875Speter        int             i;
502251875Speter
503251875Speter        /* Sanity check: */
504251875Speter        assert(context != (SHA256_CTX*)0);
505251875Speter
506251875Speter        if (buffer != (char*)0) {
507251875Speter                apr__SHA256_Final(digest, context);
508251875Speter
509251875Speter                for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
510251875Speter                        *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
511251875Speter                        *buffer++ = sha2_hex_digits[*d & 0x0f];
512251875Speter                        d++;
513251875Speter                }
514251875Speter                *buffer = (char)0;
515251875Speter        } else {
516251875Speter                MEMSET_BZERO(context, sizeof(*context));
517251875Speter        }
518251875Speter        MEMSET_BZERO(digest, SHA256_DIGEST_LENGTH);
519251875Speter        return buffer;
520251875Speter}
521251875Speter
522251875Speterchar* apr__SHA256_Data(const sha2_byte* data, size_t len, char digest[SHA256_DIGEST_STRING_LENGTH]) {
523251875Speter        SHA256_CTX      context;
524251875Speter
525251875Speter        apr__SHA256_Init(&context);
526251875Speter        apr__SHA256_Update(&context, data, len);
527251875Speter        return apr__SHA256_End(&context, digest);
528251875Speter}
529