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