1214501Srpaulo/* 2214501Srpaulo * SHA-256 hash implementation and interface functions 3252726Srpaulo * Copyright (c) 2003-2011, Jouni Malinen <j@w1.fi> 4214501Srpaulo * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7214501Srpaulo */ 8214501Srpaulo 9214501Srpaulo#include "includes.h" 10214501Srpaulo 11214501Srpaulo#include "common.h" 12214501Srpaulo#include "sha256.h" 13252726Srpaulo#include "sha256_i.h" 14214501Srpaulo#include "crypto.h" 15214501Srpaulo 16214501Srpaulo 17214501Srpaulo/** 18214501Srpaulo * sha256_vector - SHA256 hash for data vector 19214501Srpaulo * @num_elem: Number of elements in the data vector 20214501Srpaulo * @addr: Pointers to the data areas 21214501Srpaulo * @len: Lengths of the data blocks 22214501Srpaulo * @mac: Buffer for the hash 23214501Srpaulo * Returns: 0 on success, -1 of failure 24214501Srpaulo */ 25214501Srpauloint sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, 26214501Srpaulo u8 *mac) 27214501Srpaulo{ 28214501Srpaulo struct sha256_state ctx; 29214501Srpaulo size_t i; 30214501Srpaulo 31214501Srpaulo sha256_init(&ctx); 32214501Srpaulo for (i = 0; i < num_elem; i++) 33214501Srpaulo if (sha256_process(&ctx, addr[i], len[i])) 34214501Srpaulo return -1; 35214501Srpaulo if (sha256_done(&ctx, mac)) 36214501Srpaulo return -1; 37214501Srpaulo return 0; 38214501Srpaulo} 39214501Srpaulo 40214501Srpaulo 41214501Srpaulo/* ===== start - public domain SHA256 implementation ===== */ 42214501Srpaulo 43214501Srpaulo/* This is based on SHA256 implementation in LibTomCrypt that was released into 44214501Srpaulo * public domain by Tom St Denis. */ 45214501Srpaulo 46214501Srpaulo/* the K array */ 47214501Srpaulostatic const unsigned long K[64] = { 48214501Srpaulo 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, 49214501Srpaulo 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, 50214501Srpaulo 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 51214501Srpaulo 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, 52214501Srpaulo 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, 53214501Srpaulo 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, 54214501Srpaulo 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 55214501Srpaulo 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, 56214501Srpaulo 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, 57214501Srpaulo 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, 58214501Srpaulo 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 59214501Srpaulo 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, 60214501Srpaulo 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL 61214501Srpaulo}; 62214501Srpaulo 63214501Srpaulo 64214501Srpaulo/* Various logical functions */ 65214501Srpaulo#define RORc(x, y) \ 66214501Srpaulo( ((((unsigned long) (x) & 0xFFFFFFFFUL) >> (unsigned long) ((y) & 31)) | \ 67214501Srpaulo ((unsigned long) (x) << (unsigned long) (32 - ((y) & 31)))) & 0xFFFFFFFFUL) 68214501Srpaulo#define Ch(x,y,z) (z ^ (x & (y ^ z))) 69214501Srpaulo#define Maj(x,y,z) (((x | y) & z) | (x & y)) 70214501Srpaulo#define S(x, n) RORc((x), (n)) 71214501Srpaulo#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) 72214501Srpaulo#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) 73214501Srpaulo#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) 74214501Srpaulo#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) 75214501Srpaulo#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) 76214501Srpaulo#ifndef MIN 77214501Srpaulo#define MIN(x, y) (((x) < (y)) ? (x) : (y)) 78214501Srpaulo#endif 79214501Srpaulo 80214501Srpaulo/* compress 512-bits */ 81214501Srpaulostatic int sha256_compress(struct sha256_state *md, unsigned char *buf) 82214501Srpaulo{ 83214501Srpaulo u32 S[8], W[64], t0, t1; 84214501Srpaulo u32 t; 85214501Srpaulo int i; 86214501Srpaulo 87214501Srpaulo /* copy state into S */ 88214501Srpaulo for (i = 0; i < 8; i++) { 89214501Srpaulo S[i] = md->state[i]; 90214501Srpaulo } 91214501Srpaulo 92214501Srpaulo /* copy the state into 512-bits into W[0..15] */ 93214501Srpaulo for (i = 0; i < 16; i++) 94214501Srpaulo W[i] = WPA_GET_BE32(buf + (4 * i)); 95214501Srpaulo 96214501Srpaulo /* fill W[16..63] */ 97214501Srpaulo for (i = 16; i < 64; i++) { 98214501Srpaulo W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + 99214501Srpaulo W[i - 16]; 100214501Srpaulo } 101214501Srpaulo 102214501Srpaulo /* Compress */ 103214501Srpaulo#define RND(a,b,c,d,e,f,g,h,i) \ 104214501Srpaulo t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ 105214501Srpaulo t1 = Sigma0(a) + Maj(a, b, c); \ 106214501Srpaulo d += t0; \ 107214501Srpaulo h = t0 + t1; 108214501Srpaulo 109214501Srpaulo for (i = 0; i < 64; ++i) { 110214501Srpaulo RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i); 111214501Srpaulo t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; 112214501Srpaulo S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t; 113214501Srpaulo } 114214501Srpaulo 115214501Srpaulo /* feedback */ 116214501Srpaulo for (i = 0; i < 8; i++) { 117214501Srpaulo md->state[i] = md->state[i] + S[i]; 118214501Srpaulo } 119214501Srpaulo return 0; 120214501Srpaulo} 121214501Srpaulo 122214501Srpaulo 123214501Srpaulo/* Initialize the hash state */ 124252726Srpaulovoid sha256_init(struct sha256_state *md) 125214501Srpaulo{ 126214501Srpaulo md->curlen = 0; 127214501Srpaulo md->length = 0; 128214501Srpaulo md->state[0] = 0x6A09E667UL; 129214501Srpaulo md->state[1] = 0xBB67AE85UL; 130214501Srpaulo md->state[2] = 0x3C6EF372UL; 131214501Srpaulo md->state[3] = 0xA54FF53AUL; 132214501Srpaulo md->state[4] = 0x510E527FUL; 133214501Srpaulo md->state[5] = 0x9B05688CUL; 134214501Srpaulo md->state[6] = 0x1F83D9ABUL; 135214501Srpaulo md->state[7] = 0x5BE0CD19UL; 136214501Srpaulo} 137214501Srpaulo 138214501Srpaulo/** 139214501Srpaulo Process a block of memory though the hash 140214501Srpaulo @param md The hash state 141214501Srpaulo @param in The data to hash 142214501Srpaulo @param inlen The length of the data (octets) 143214501Srpaulo @return CRYPT_OK if successful 144214501Srpaulo*/ 145252726Srpauloint sha256_process(struct sha256_state *md, const unsigned char *in, 146252726Srpaulo unsigned long inlen) 147214501Srpaulo{ 148214501Srpaulo unsigned long n; 149214501Srpaulo 150252726Srpaulo if (md->curlen >= sizeof(md->buf)) 151214501Srpaulo return -1; 152214501Srpaulo 153214501Srpaulo while (inlen > 0) { 154252726Srpaulo if (md->curlen == 0 && inlen >= SHA256_BLOCK_SIZE) { 155214501Srpaulo if (sha256_compress(md, (unsigned char *) in) < 0) 156214501Srpaulo return -1; 157252726Srpaulo md->length += SHA256_BLOCK_SIZE * 8; 158252726Srpaulo in += SHA256_BLOCK_SIZE; 159252726Srpaulo inlen -= SHA256_BLOCK_SIZE; 160214501Srpaulo } else { 161252726Srpaulo n = MIN(inlen, (SHA256_BLOCK_SIZE - md->curlen)); 162214501Srpaulo os_memcpy(md->buf + md->curlen, in, n); 163214501Srpaulo md->curlen += n; 164214501Srpaulo in += n; 165214501Srpaulo inlen -= n; 166252726Srpaulo if (md->curlen == SHA256_BLOCK_SIZE) { 167214501Srpaulo if (sha256_compress(md, md->buf) < 0) 168214501Srpaulo return -1; 169252726Srpaulo md->length += 8 * SHA256_BLOCK_SIZE; 170214501Srpaulo md->curlen = 0; 171214501Srpaulo } 172214501Srpaulo } 173214501Srpaulo } 174214501Srpaulo 175214501Srpaulo return 0; 176214501Srpaulo} 177214501Srpaulo 178214501Srpaulo 179214501Srpaulo/** 180214501Srpaulo Terminate the hash to get the digest 181214501Srpaulo @param md The hash state 182214501Srpaulo @param out [out] The destination of the hash (32 bytes) 183214501Srpaulo @return CRYPT_OK if successful 184214501Srpaulo*/ 185252726Srpauloint sha256_done(struct sha256_state *md, unsigned char *out) 186214501Srpaulo{ 187214501Srpaulo int i; 188214501Srpaulo 189214501Srpaulo if (md->curlen >= sizeof(md->buf)) 190214501Srpaulo return -1; 191214501Srpaulo 192214501Srpaulo /* increase the length of the message */ 193214501Srpaulo md->length += md->curlen * 8; 194214501Srpaulo 195214501Srpaulo /* append the '1' bit */ 196214501Srpaulo md->buf[md->curlen++] = (unsigned char) 0x80; 197214501Srpaulo 198214501Srpaulo /* if the length is currently above 56 bytes we append zeros 199214501Srpaulo * then compress. Then we can fall back to padding zeros and length 200214501Srpaulo * encoding like normal. 201214501Srpaulo */ 202214501Srpaulo if (md->curlen > 56) { 203252726Srpaulo while (md->curlen < SHA256_BLOCK_SIZE) { 204214501Srpaulo md->buf[md->curlen++] = (unsigned char) 0; 205214501Srpaulo } 206214501Srpaulo sha256_compress(md, md->buf); 207214501Srpaulo md->curlen = 0; 208214501Srpaulo } 209214501Srpaulo 210252726Srpaulo /* pad up to 56 bytes of zeroes */ 211214501Srpaulo while (md->curlen < 56) { 212214501Srpaulo md->buf[md->curlen++] = (unsigned char) 0; 213214501Srpaulo } 214214501Srpaulo 215214501Srpaulo /* store length */ 216214501Srpaulo WPA_PUT_BE64(md->buf + 56, md->length); 217214501Srpaulo sha256_compress(md, md->buf); 218214501Srpaulo 219214501Srpaulo /* copy output */ 220214501Srpaulo for (i = 0; i < 8; i++) 221214501Srpaulo WPA_PUT_BE32(out + (4 * i), md->state[i]); 222214501Srpaulo 223214501Srpaulo return 0; 224214501Srpaulo} 225214501Srpaulo 226214501Srpaulo/* ===== end - public domain SHA256 implementation ===== */ 227