139beb93cSSam Leffler /* 239beb93cSSam Leffler * SHA-256 hash implementation and interface functions 339beb93cSSam Leffler * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi> 439beb93cSSam Leffler * 539beb93cSSam Leffler * This program is free software; you can redistribute it and/or modify 639beb93cSSam Leffler * it under the terms of the GNU General Public License version 2 as 739beb93cSSam Leffler * published by the Free Software Foundation. 839beb93cSSam Leffler * 939beb93cSSam Leffler * Alternatively, this software may be distributed under the terms of BSD 1039beb93cSSam Leffler * license. 1139beb93cSSam Leffler * 1239beb93cSSam Leffler * See README and COPYING for more details. 1339beb93cSSam Leffler */ 1439beb93cSSam Leffler 1539beb93cSSam Leffler #include "includes.h" 1639beb93cSSam Leffler 1739beb93cSSam Leffler #include "common.h" 1839beb93cSSam Leffler #include "sha256.h" 1939beb93cSSam Leffler #include "crypto.h" 2039beb93cSSam Leffler 2139beb93cSSam Leffler 2239beb93cSSam Leffler /** 2339beb93cSSam Leffler * hmac_sha256_vector - HMAC-SHA256 over data vector (RFC 2104) 2439beb93cSSam Leffler * @key: Key for HMAC operations 2539beb93cSSam Leffler * @key_len: Length of the key in bytes 2639beb93cSSam Leffler * @num_elem: Number of elements in the data vector 2739beb93cSSam Leffler * @addr: Pointers to the data areas 2839beb93cSSam Leffler * @len: Lengths of the data blocks 2939beb93cSSam Leffler * @mac: Buffer for the hash (32 bytes) 3039beb93cSSam Leffler */ 3139beb93cSSam Leffler void hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem, 3239beb93cSSam Leffler const u8 *addr[], const size_t *len, u8 *mac) 3339beb93cSSam Leffler { 3439beb93cSSam Leffler unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */ 3539beb93cSSam Leffler unsigned char tk[32]; 3639beb93cSSam Leffler const u8 *_addr[6]; 3739beb93cSSam Leffler size_t _len[6], i; 3839beb93cSSam Leffler 3939beb93cSSam Leffler if (num_elem > 5) { 4039beb93cSSam Leffler /* 4139beb93cSSam Leffler * Fixed limit on the number of fragments to avoid having to 4239beb93cSSam Leffler * allocate memory (which could fail). 4339beb93cSSam Leffler */ 4439beb93cSSam Leffler return; 4539beb93cSSam Leffler } 4639beb93cSSam Leffler 4739beb93cSSam Leffler /* if key is longer than 64 bytes reset it to key = SHA256(key) */ 4839beb93cSSam Leffler if (key_len > 64) { 4939beb93cSSam Leffler sha256_vector(1, &key, &key_len, tk); 5039beb93cSSam Leffler key = tk; 5139beb93cSSam Leffler key_len = 32; 5239beb93cSSam Leffler } 5339beb93cSSam Leffler 5439beb93cSSam Leffler /* the HMAC_SHA256 transform looks like: 5539beb93cSSam Leffler * 5639beb93cSSam Leffler * SHA256(K XOR opad, SHA256(K XOR ipad, text)) 5739beb93cSSam Leffler * 5839beb93cSSam Leffler * where K is an n byte key 5939beb93cSSam Leffler * ipad is the byte 0x36 repeated 64 times 6039beb93cSSam Leffler * opad is the byte 0x5c repeated 64 times 6139beb93cSSam Leffler * and text is the data being protected */ 6239beb93cSSam Leffler 6339beb93cSSam Leffler /* start out by storing key in ipad */ 6439beb93cSSam Leffler os_memset(k_pad, 0, sizeof(k_pad)); 6539beb93cSSam Leffler os_memcpy(k_pad, key, key_len); 6639beb93cSSam Leffler /* XOR key with ipad values */ 6739beb93cSSam Leffler for (i = 0; i < 64; i++) 6839beb93cSSam Leffler k_pad[i] ^= 0x36; 6939beb93cSSam Leffler 7039beb93cSSam Leffler /* perform inner SHA256 */ 7139beb93cSSam Leffler _addr[0] = k_pad; 7239beb93cSSam Leffler _len[0] = 64; 7339beb93cSSam Leffler for (i = 0; i < num_elem; i++) { 7439beb93cSSam Leffler _addr[i + 1] = addr[i]; 7539beb93cSSam Leffler _len[i + 1] = len[i]; 7639beb93cSSam Leffler } 7739beb93cSSam Leffler sha256_vector(1 + num_elem, _addr, _len, mac); 7839beb93cSSam Leffler 7939beb93cSSam Leffler os_memset(k_pad, 0, sizeof(k_pad)); 8039beb93cSSam Leffler os_memcpy(k_pad, key, key_len); 8139beb93cSSam Leffler /* XOR key with opad values */ 8239beb93cSSam Leffler for (i = 0; i < 64; i++) 8339beb93cSSam Leffler k_pad[i] ^= 0x5c; 8439beb93cSSam Leffler 8539beb93cSSam Leffler /* perform outer SHA256 */ 8639beb93cSSam Leffler _addr[0] = k_pad; 8739beb93cSSam Leffler _len[0] = 64; 8839beb93cSSam Leffler _addr[1] = mac; 8939beb93cSSam Leffler _len[1] = SHA256_MAC_LEN; 9039beb93cSSam Leffler sha256_vector(2, _addr, _len, mac); 9139beb93cSSam Leffler } 9239beb93cSSam Leffler 9339beb93cSSam Leffler 9439beb93cSSam Leffler /** 9539beb93cSSam Leffler * hmac_sha256 - HMAC-SHA256 over data buffer (RFC 2104) 9639beb93cSSam Leffler * @key: Key for HMAC operations 9739beb93cSSam Leffler * @key_len: Length of the key in bytes 9839beb93cSSam Leffler * @data: Pointers to the data area 9939beb93cSSam Leffler * @data_len: Length of the data area 10039beb93cSSam Leffler * @mac: Buffer for the hash (20 bytes) 10139beb93cSSam Leffler */ 10239beb93cSSam Leffler void hmac_sha256(const u8 *key, size_t key_len, const u8 *data, 10339beb93cSSam Leffler size_t data_len, u8 *mac) 10439beb93cSSam Leffler { 10539beb93cSSam Leffler hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac); 10639beb93cSSam Leffler } 10739beb93cSSam Leffler 10839beb93cSSam Leffler 10939beb93cSSam Leffler /** 11039beb93cSSam Leffler * sha256_prf - SHA256-based Pseudo-Random Function (IEEE 802.11r, 8.5.1.5.2) 11139beb93cSSam Leffler * @key: Key for PRF 11239beb93cSSam Leffler * @key_len: Length of the key in bytes 11339beb93cSSam Leffler * @label: A unique label for each purpose of the PRF 11439beb93cSSam Leffler * @data: Extra data to bind into the key 11539beb93cSSam Leffler * @data_len: Length of the data 11639beb93cSSam Leffler * @buf: Buffer for the generated pseudo-random key 11739beb93cSSam Leffler * @buf_len: Number of bytes of key to generate 11839beb93cSSam Leffler * 11939beb93cSSam Leffler * This function is used to derive new, cryptographically separate keys from a 12039beb93cSSam Leffler * given key. 12139beb93cSSam Leffler */ 12239beb93cSSam Leffler void sha256_prf(const u8 *key, size_t key_len, const char *label, 12339beb93cSSam Leffler const u8 *data, size_t data_len, u8 *buf, size_t buf_len) 12439beb93cSSam Leffler { 12539beb93cSSam Leffler u16 counter = 0; 12639beb93cSSam Leffler size_t pos, plen; 12739beb93cSSam Leffler u8 hash[SHA256_MAC_LEN]; 12839beb93cSSam Leffler const u8 *addr[4]; 12939beb93cSSam Leffler size_t len[4]; 13039beb93cSSam Leffler u8 counter_le[2], length_le[2]; 13139beb93cSSam Leffler 13239beb93cSSam Leffler addr[0] = counter_le; 13339beb93cSSam Leffler len[0] = 2; 13439beb93cSSam Leffler addr[1] = (u8 *) label; 13539beb93cSSam Leffler len[1] = os_strlen(label); 13639beb93cSSam Leffler addr[2] = data; 13739beb93cSSam Leffler len[2] = data_len; 13839beb93cSSam Leffler addr[3] = length_le; 13939beb93cSSam Leffler len[3] = sizeof(length_le); 14039beb93cSSam Leffler 14139beb93cSSam Leffler WPA_PUT_LE16(length_le, buf_len * 8); 14239beb93cSSam Leffler pos = 0; 14339beb93cSSam Leffler while (pos < buf_len) { 14439beb93cSSam Leffler plen = buf_len - pos; 14539beb93cSSam Leffler WPA_PUT_LE16(counter_le, counter); 14639beb93cSSam Leffler if (plen >= SHA256_MAC_LEN) { 14739beb93cSSam Leffler hmac_sha256_vector(key, key_len, 4, addr, len, 14839beb93cSSam Leffler &buf[pos]); 14939beb93cSSam Leffler pos += SHA256_MAC_LEN; 15039beb93cSSam Leffler } else { 15139beb93cSSam Leffler hmac_sha256_vector(key, key_len, 4, addr, len, hash); 15239beb93cSSam Leffler os_memcpy(&buf[pos], hash, plen); 15339beb93cSSam Leffler break; 15439beb93cSSam Leffler } 15539beb93cSSam Leffler counter++; 15639beb93cSSam Leffler } 15739beb93cSSam Leffler } 15839beb93cSSam Leffler 15939beb93cSSam Leffler 16039beb93cSSam Leffler #ifdef INTERNAL_SHA256 16139beb93cSSam Leffler 16239beb93cSSam Leffler struct sha256_state { 16339beb93cSSam Leffler u64 length; 16439beb93cSSam Leffler u32 state[8], curlen; 16539beb93cSSam Leffler u8 buf[64]; 16639beb93cSSam Leffler }; 16739beb93cSSam Leffler 16839beb93cSSam Leffler static void sha256_init(struct sha256_state *md); 16939beb93cSSam Leffler static int sha256_process(struct sha256_state *md, const unsigned char *in, 17039beb93cSSam Leffler unsigned long inlen); 17139beb93cSSam Leffler static int sha256_done(struct sha256_state *md, unsigned char *out); 17239beb93cSSam Leffler 17339beb93cSSam Leffler 17439beb93cSSam Leffler /** 17539beb93cSSam Leffler * sha256_vector - SHA256 hash for data vector 17639beb93cSSam Leffler * @num_elem: Number of elements in the data vector 17739beb93cSSam Leffler * @addr: Pointers to the data areas 17839beb93cSSam Leffler * @len: Lengths of the data blocks 17939beb93cSSam Leffler * @mac: Buffer for the hash 18039beb93cSSam Leffler */ 18139beb93cSSam Leffler void sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, 18239beb93cSSam Leffler u8 *mac) 18339beb93cSSam Leffler { 18439beb93cSSam Leffler struct sha256_state ctx; 18539beb93cSSam Leffler size_t i; 18639beb93cSSam Leffler 18739beb93cSSam Leffler sha256_init(&ctx); 18839beb93cSSam Leffler for (i = 0; i < num_elem; i++) 18939beb93cSSam Leffler sha256_process(&ctx, addr[i], len[i]); 19039beb93cSSam Leffler sha256_done(&ctx, mac); 19139beb93cSSam Leffler } 19239beb93cSSam Leffler 19339beb93cSSam Leffler 19439beb93cSSam Leffler /* ===== start - public domain SHA256 implementation ===== */ 19539beb93cSSam Leffler 19639beb93cSSam Leffler /* This is based on SHA256 implementation in LibTomCrypt that was released into 19739beb93cSSam Leffler * public domain by Tom St Denis. */ 19839beb93cSSam Leffler 19939beb93cSSam Leffler /* the K array */ 20039beb93cSSam Leffler static const unsigned long K[64] = { 20139beb93cSSam Leffler 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, 20239beb93cSSam Leffler 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, 20339beb93cSSam Leffler 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 20439beb93cSSam Leffler 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, 20539beb93cSSam Leffler 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, 20639beb93cSSam Leffler 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, 20739beb93cSSam Leffler 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 20839beb93cSSam Leffler 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, 20939beb93cSSam Leffler 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, 21039beb93cSSam Leffler 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, 21139beb93cSSam Leffler 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 21239beb93cSSam Leffler 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, 21339beb93cSSam Leffler 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL 21439beb93cSSam Leffler }; 21539beb93cSSam Leffler 21639beb93cSSam Leffler 21739beb93cSSam Leffler /* Various logical functions */ 21839beb93cSSam Leffler #define RORc(x, y) \ 21939beb93cSSam Leffler ( ((((unsigned long) (x) & 0xFFFFFFFFUL) >> (unsigned long) ((y) & 31)) | \ 22039beb93cSSam Leffler ((unsigned long) (x) << (unsigned long) (32 - ((y) & 31)))) & 0xFFFFFFFFUL) 22139beb93cSSam Leffler #define Ch(x,y,z) (z ^ (x & (y ^ z))) 22239beb93cSSam Leffler #define Maj(x,y,z) (((x | y) & z) | (x & y)) 22339beb93cSSam Leffler #define S(x, n) RORc((x), (n)) 22439beb93cSSam Leffler #define R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) 22539beb93cSSam Leffler #define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) 22639beb93cSSam Leffler #define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) 22739beb93cSSam Leffler #define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) 22839beb93cSSam Leffler #define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) 22939beb93cSSam Leffler #ifndef MIN 23039beb93cSSam Leffler #define MIN(x, y) (((x) < (y)) ? (x) : (y)) 23139beb93cSSam Leffler #endif 23239beb93cSSam Leffler 23339beb93cSSam Leffler /* compress 512-bits */ 23439beb93cSSam Leffler static int sha256_compress(struct sha256_state *md, unsigned char *buf) 23539beb93cSSam Leffler { 23639beb93cSSam Leffler u32 S[8], W[64], t0, t1; 23739beb93cSSam Leffler u32 t; 23839beb93cSSam Leffler int i; 23939beb93cSSam Leffler 24039beb93cSSam Leffler /* copy state into S */ 24139beb93cSSam Leffler for (i = 0; i < 8; i++) { 24239beb93cSSam Leffler S[i] = md->state[i]; 24339beb93cSSam Leffler } 24439beb93cSSam Leffler 24539beb93cSSam Leffler /* copy the state into 512-bits into W[0..15] */ 24639beb93cSSam Leffler for (i = 0; i < 16; i++) 24739beb93cSSam Leffler W[i] = WPA_GET_BE32(buf + (4 * i)); 24839beb93cSSam Leffler 24939beb93cSSam Leffler /* fill W[16..63] */ 25039beb93cSSam Leffler for (i = 16; i < 64; i++) { 25139beb93cSSam Leffler W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + 25239beb93cSSam Leffler W[i - 16]; 25339beb93cSSam Leffler } 25439beb93cSSam Leffler 25539beb93cSSam Leffler /* Compress */ 25639beb93cSSam Leffler #define RND(a,b,c,d,e,f,g,h,i) \ 25739beb93cSSam Leffler t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ 25839beb93cSSam Leffler t1 = Sigma0(a) + Maj(a, b, c); \ 25939beb93cSSam Leffler d += t0; \ 26039beb93cSSam Leffler h = t0 + t1; 26139beb93cSSam Leffler 26239beb93cSSam Leffler for (i = 0; i < 64; ++i) { 26339beb93cSSam Leffler RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i); 26439beb93cSSam Leffler t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; 26539beb93cSSam Leffler S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t; 26639beb93cSSam Leffler } 26739beb93cSSam Leffler 26839beb93cSSam Leffler /* feedback */ 26939beb93cSSam Leffler for (i = 0; i < 8; i++) { 27039beb93cSSam Leffler md->state[i] = md->state[i] + S[i]; 27139beb93cSSam Leffler } 27239beb93cSSam Leffler return 0; 27339beb93cSSam Leffler } 27439beb93cSSam Leffler 27539beb93cSSam Leffler 27639beb93cSSam Leffler /* Initialize the hash state */ 27739beb93cSSam Leffler static void sha256_init(struct sha256_state *md) 27839beb93cSSam Leffler { 27939beb93cSSam Leffler md->curlen = 0; 28039beb93cSSam Leffler md->length = 0; 28139beb93cSSam Leffler md->state[0] = 0x6A09E667UL; 28239beb93cSSam Leffler md->state[1] = 0xBB67AE85UL; 28339beb93cSSam Leffler md->state[2] = 0x3C6EF372UL; 28439beb93cSSam Leffler md->state[3] = 0xA54FF53AUL; 28539beb93cSSam Leffler md->state[4] = 0x510E527FUL; 28639beb93cSSam Leffler md->state[5] = 0x9B05688CUL; 28739beb93cSSam Leffler md->state[6] = 0x1F83D9ABUL; 28839beb93cSSam Leffler md->state[7] = 0x5BE0CD19UL; 28939beb93cSSam Leffler } 29039beb93cSSam Leffler 29139beb93cSSam Leffler /** 29239beb93cSSam Leffler Process a block of memory though the hash 29339beb93cSSam Leffler @param md The hash state 29439beb93cSSam Leffler @param in The data to hash 29539beb93cSSam Leffler @param inlen The length of the data (octets) 29639beb93cSSam Leffler @return CRYPT_OK if successful 29739beb93cSSam Leffler */ 29839beb93cSSam Leffler static int sha256_process(struct sha256_state *md, const unsigned char *in, 29939beb93cSSam Leffler unsigned long inlen) 30039beb93cSSam Leffler { 30139beb93cSSam Leffler unsigned long n; 30239beb93cSSam Leffler #define block_size 64 30339beb93cSSam Leffler 30439beb93cSSam Leffler if (md->curlen > sizeof(md->buf)) 30539beb93cSSam Leffler return -1; 30639beb93cSSam Leffler 30739beb93cSSam Leffler while (inlen > 0) { 30839beb93cSSam Leffler if (md->curlen == 0 && inlen >= block_size) { 30939beb93cSSam Leffler if (sha256_compress(md, (unsigned char *) in) < 0) 31039beb93cSSam Leffler return -1; 31139beb93cSSam Leffler md->length += block_size * 8; 31239beb93cSSam Leffler in += block_size; 31339beb93cSSam Leffler inlen -= block_size; 31439beb93cSSam Leffler } else { 31539beb93cSSam Leffler n = MIN(inlen, (block_size - md->curlen)); 31639beb93cSSam Leffler os_memcpy(md->buf + md->curlen, in, n); 31739beb93cSSam Leffler md->curlen += n; 31839beb93cSSam Leffler in += n; 31939beb93cSSam Leffler inlen -= n; 32039beb93cSSam Leffler if (md->curlen == block_size) { 32139beb93cSSam Leffler if (sha256_compress(md, md->buf) < 0) 32239beb93cSSam Leffler return -1; 32339beb93cSSam Leffler md->length += 8 * block_size; 32439beb93cSSam Leffler md->curlen = 0; 32539beb93cSSam Leffler } 32639beb93cSSam Leffler } 32739beb93cSSam Leffler } 32839beb93cSSam Leffler 32939beb93cSSam Leffler return 0; 33039beb93cSSam Leffler } 33139beb93cSSam Leffler 33239beb93cSSam Leffler 33339beb93cSSam Leffler /** 33439beb93cSSam Leffler Terminate the hash to get the digest 33539beb93cSSam Leffler @param md The hash state 33639beb93cSSam Leffler @param out [out] The destination of the hash (32 bytes) 33739beb93cSSam Leffler @return CRYPT_OK if successful 33839beb93cSSam Leffler */ 33939beb93cSSam Leffler static int sha256_done(struct sha256_state *md, unsigned char *out) 34039beb93cSSam Leffler { 34139beb93cSSam Leffler int i; 34239beb93cSSam Leffler 34339beb93cSSam Leffler if (md->curlen >= sizeof(md->buf)) 34439beb93cSSam Leffler return -1; 34539beb93cSSam Leffler 34639beb93cSSam Leffler /* increase the length of the message */ 34739beb93cSSam Leffler md->length += md->curlen * 8; 34839beb93cSSam Leffler 34939beb93cSSam Leffler /* append the '1' bit */ 35039beb93cSSam Leffler md->buf[md->curlen++] = (unsigned char) 0x80; 35139beb93cSSam Leffler 35239beb93cSSam Leffler /* if the length is currently above 56 bytes we append zeros 35339beb93cSSam Leffler * then compress. Then we can fall back to padding zeros and length 35439beb93cSSam Leffler * encoding like normal. 35539beb93cSSam Leffler */ 35639beb93cSSam Leffler if (md->curlen > 56) { 35739beb93cSSam Leffler while (md->curlen < 64) { 35839beb93cSSam Leffler md->buf[md->curlen++] = (unsigned char) 0; 35939beb93cSSam Leffler } 36039beb93cSSam Leffler sha256_compress(md, md->buf); 36139beb93cSSam Leffler md->curlen = 0; 36239beb93cSSam Leffler } 36339beb93cSSam Leffler 36439beb93cSSam Leffler /* pad upto 56 bytes of zeroes */ 36539beb93cSSam Leffler while (md->curlen < 56) { 36639beb93cSSam Leffler md->buf[md->curlen++] = (unsigned char) 0; 36739beb93cSSam Leffler } 36839beb93cSSam Leffler 36939beb93cSSam Leffler /* store length */ 37039beb93cSSam Leffler WPA_PUT_BE64(md->buf + 56, md->length); 37139beb93cSSam Leffler sha256_compress(md, md->buf); 37239beb93cSSam Leffler 37339beb93cSSam Leffler /* copy output */ 37439beb93cSSam Leffler for (i = 0; i < 8; i++) 37539beb93cSSam Leffler WPA_PUT_BE32(out + (4 * i), md->state[i]); 37639beb93cSSam Leffler 37739beb93cSSam Leffler return 0; 37839beb93cSSam Leffler } 37939beb93cSSam Leffler 38039beb93cSSam Leffler /* ===== end - public domain SHA256 implementation ===== */ 38139beb93cSSam Leffler 38239beb93cSSam Leffler #endif /* INTERNAL_SHA256 */ 383