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