vita-toolchain

git clone https://git.neptards.moe/neptards/vita-toolchain.git
Log | Files | Refs | README | LICENSE

sha256.c (8506B)


      1 #include "sha256.h"
      2 #include <stdint.h>
      3 #include <stdio.h>
      4 #include <stdlib.h>
      5 
      6 #define READ_BUFFER	(1*1024*1024)
      7 
      8 uint32_t k[64] = {
      9    0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
     10    0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
     11    0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
     12    0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
     13    0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
     14    0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
     15    0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
     16    0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
     17 };
     18 
     19 
     20 
     21 void sha256_transform(SHA256_CTX *ctx, uint8_t data[])
     22 {  
     23    uint32_t a,b,c,d,e,f,g,h,i,j,t1,t2,m[64];
     24       
     25    for (i=0,j=0; i < 16; ++i, j += 4)
     26       m[i] = (data[j] << 24) | (data[j+1] << 16) | (data[j+2] << 8) | (data[j+3]);
     27    for ( ; i < 64; ++i)
     28       m[i] = SIG1(m[i-2]) + m[i-7] + SIG0(m[i-15]) + m[i-16];
     29 
     30    a = ctx->state[0];
     31    b = ctx->state[1];
     32    c = ctx->state[2];
     33    d = ctx->state[3];
     34    e = ctx->state[4];
     35    f = ctx->state[5];
     36    g = ctx->state[6];
     37    h = ctx->state[7];
     38    
     39    for (i = 0; i < 64; ++i) {
     40       t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i];
     41       t2 = EP0(a) + MAJ(a,b,c);
     42       h = g;
     43       g = f;
     44       f = e;
     45       e = d + t1;
     46       d = c;
     47       c = b;
     48       b = a;
     49       a = t1 + t2;
     50    }
     51    
     52    ctx->state[0] += a;
     53    ctx->state[1] += b;
     54    ctx->state[2] += c;
     55    ctx->state[3] += d;
     56    ctx->state[4] += e;
     57    ctx->state[5] += f;
     58    ctx->state[6] += g;
     59    ctx->state[7] += h;
     60 }  
     61 
     62 void sha256_init(SHA256_CTX *ctx)
     63 {  
     64    ctx->datalen = 0; 
     65    ctx->bitlen[0] = 0; 
     66    ctx->bitlen[1] = 0; 
     67    ctx->state[0] = 0x6a09e667;
     68    ctx->state[1] = 0xbb67ae85;
     69    ctx->state[2] = 0x3c6ef372;
     70    ctx->state[3] = 0xa54ff53a;
     71    ctx->state[4] = 0x510e527f;
     72    ctx->state[5] = 0x9b05688c;
     73    ctx->state[6] = 0x1f83d9ab;
     74    ctx->state[7] = 0x5be0cd19;
     75 }
     76 
     77 void sha256_update(SHA256_CTX *ctx, uint8_t data[], uint32_t len)
     78 {  
     79    uint32_t i;
     80    
     81    for (i=0; i < len; ++i) { 
     82       ctx->data[ctx->datalen] = data[i]; 
     83       ctx->datalen++; 
     84       if (ctx->datalen == 64) { 
     85          sha256_transform(ctx,ctx->data);
     86          DBL_INT_ADD(ctx->bitlen[0],ctx->bitlen[1],512); 
     87          ctx->datalen = 0; 
     88       }  
     89    }  
     90 }  
     91 
     92 void sha256_final(SHA256_CTX *ctx, uint8_t hash[])
     93 {  
     94    uint32_t i; 
     95    
     96    i = ctx->datalen; 
     97    
     98    // Pad whatever data is left in the buffer. 
     99    if (ctx->datalen < 56) { 
    100       ctx->data[i++] = 0x80; 
    101       while (i < 56) 
    102          ctx->data[i++] = 0x00; 
    103    }  
    104    else { 
    105       ctx->data[i++] = 0x80; 
    106       while (i < 64) 
    107          ctx->data[i++] = 0x00; 
    108       sha256_transform(ctx,ctx->data);
    109       memset(ctx->data,0,56); 
    110    }  
    111    
    112    // Append to the padding the total message's length in bits and transform. 
    113    DBL_INT_ADD(ctx->bitlen[0],ctx->bitlen[1],ctx->datalen * 8);
    114    ctx->data[63] = ctx->bitlen[0]; 
    115    ctx->data[62] = ctx->bitlen[0] >> 8; 
    116    ctx->data[61] = ctx->bitlen[0] >> 16; 
    117    ctx->data[60] = ctx->bitlen[0] >> 24; 
    118    ctx->data[59] = ctx->bitlen[1]; 
    119    ctx->data[58] = ctx->bitlen[1] >> 8; 
    120    ctx->data[57] = ctx->bitlen[1] >> 16;  
    121    ctx->data[56] = ctx->bitlen[1] >> 24; 
    122    sha256_transform(ctx,ctx->data);
    123    
    124    // Since this implementation uses little endian byte ordering and SHA uses big endian,
    125    // reverse all the bytes when copying the final state to the output hash. 
    126    for (i=0; i < 4; ++i) { 
    127       hash[i]    = (ctx->state[0] >> (24-i*8)) & 0x000000ff; 
    128       hash[i+4]  = (ctx->state[1] >> (24-i*8)) & 0x000000ff; 
    129       hash[i+8]  = (ctx->state[2] >> (24-i*8)) & 0x000000ff;
    130       hash[i+12] = (ctx->state[3] >> (24-i*8)) & 0x000000ff;
    131       hash[i+16] = (ctx->state[4] >> (24-i*8)) & 0x000000ff;
    132       hash[i+20] = (ctx->state[5] >> (24-i*8)) & 0x000000ff;
    133       hash[i+24] = (ctx->state[6] >> (24-i*8)) & 0x000000ff;
    134       hash[i+28] = (ctx->state[7] >> (24-i*8)) & 0x000000ff;
    135    }  
    136 }  
    137 
    138 
    139 /**
    140  * hmac_sha256_vector - HMAC-SHA256 over data vector (RFC 2104)
    141  * @key: Key for HMAC operations
    142  * @key_len: Length of the key in bytes
    143  * @num_elem: Number of elements in the data vector
    144  * @addr: Pointers to the data areas
    145  * @len: Lengths of the data blocks
    146  * @mac: Buffer for the hash (32 bytes)
    147  */
    148 void hmac_sha256_vector( uint8_t *key, size_t key_len, size_t num_elem,
    149              uint8_t *addr[],  size_t *len, uint8_t *mac)
    150 {
    151     unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */
    152     unsigned char tk[32];
    153      uint8_t *_addr[6];
    154     size_t _len[6], i;
    155 
    156     if (num_elem > 5) {
    157         /*
    158          * Fixed limit on the number of fragments to avoid having to
    159          * allocate memory (which could fail).
    160          */
    161         return;
    162     }
    163 
    164         /* if key is longer than 64 bytes reset it to key = SHA256(key) */
    165         if (key_len > 64) {
    166         sha256_vector(1, &key, &key_len, tk);
    167         key = tk;
    168         key_len = 32;
    169         }
    170 
    171     /* the HMAC_SHA256 transform looks like:
    172      *
    173      * SHA256(K XOR opad, SHA256(K XOR ipad, text))
    174      *
    175      * where K is an n byte key
    176      * ipad is the byte 0x36 repeated 64 times
    177      * opad is the byte 0x5c repeated 64 times
    178      * and text is the data being protected */
    179 
    180     /* start out by storing key in ipad */
    181     memset(k_pad, 0, sizeof(k_pad));
    182     memcpy(k_pad, key, key_len);
    183     /* XOR key with ipad values */
    184     for (i = 0; i < 64; i++)
    185         k_pad[i] ^= 0x36;
    186 
    187     /* perform inner SHA256 */
    188     _addr[0] = k_pad;
    189     _len[0] = 64;
    190     for (i = 0; i < num_elem; i++) {
    191         _addr[i + 1] = addr[i];
    192         _len[i + 1] = len[i];
    193     }
    194     sha256_vector(1 + num_elem, _addr, _len, mac);
    195 
    196 		// NOTE: SCE HACK - they removed the clearing of the pad in their version.
    197     //memset(k_pad, 0, sizeof(k_pad));
    198     //memcpy(k_pad, key, key_len);
    199     /* XOR key with opad values */
    200     for (i = 0; i < 64; i++)
    201     		// NOTE: SCE HACK - they changed the normal 0x5C value to 0x6A
    202         k_pad[i] ^= 0x6A;
    203 
    204     /* perform outer SHA256 */
    205     _addr[0] = k_pad;
    206     _len[0] = 64;
    207     _addr[1] = mac;
    208     _len[1] = SHA256_MAC_LEN;
    209     sha256_vector(2, _addr, _len, mac);
    210 }
    211 
    212 
    213 /**
    214  * hmac_sha256 - HMAC-SHA256 over data buffer (RFC 2104)
    215  * @key: Key for HMAC operations
    216  * @key_len: Length of the key in bytes
    217  * @data: Pointers to the data area
    218  * @data_len: Length of the data area
    219  * @mac: Buffer for the hash (20 bytes)
    220  */
    221 void hmac_sha256( uint8_t *key, size_t key_len,  uint8_t *data,
    222          size_t data_len, uint8_t *mac)
    223 {
    224     hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac);
    225 }
    226 
    227 
    228 /**
    229  * sha256_vector - SHA256 hash for data vector
    230  * @num_elem: Number of elements in the data vector
    231  * @addr: Pointers to the data areas
    232  * @len: Lengths of the data blocks
    233  * @mac: Buffer for the hash
    234  */
    235 void sha256_vector(size_t num_elem,  uint8_t *addr[],  size_t *len,
    236          uint8_t *mac)
    237 {
    238     SHA256_CTX ctx;
    239     size_t i;
    240 
    241     sha256_init(&ctx);
    242     for (i = 0; i < num_elem; i++)
    243         sha256_update(&ctx, addr[i], len[i]);
    244     sha256_final(&ctx, mac);
    245 }
    246 
    247 uint32_t sha256_32_vector(size_t num_elem, uint8_t *addr[],  size_t *len)
    248 {
    249 	uint8_t hash[32];
    250 	
    251 	sha256_vector(num_elem, addr, len, hash);
    252 	
    253 	// swap to little endian
    254 	return (hash[0] << 24) | (hash[1] << 16) | (hash[2] << 8) | hash[3];
    255 }
    256 
    257 int sha256_file(const char *file, uint8_t *mac)
    258 {
    259 	size_t read = 0;
    260 	SHA256_CTX ctx;
    261 	FILE *fp = fopen(file, "rb");
    262 	
    263 	if (!fp)
    264 		return -1;
    265 	
    266 	uint8_t *data = malloc(READ_BUFFER);
    267 	
    268 	sha256_init(&ctx);
    269 	
    270 	while ((read = fread(data, 1, READ_BUFFER, fp)) > 0) {
    271 		sha256_update(&ctx, data, read);
    272 	}
    273 	
    274     sha256_final(&ctx, mac);
    275 	free(data);
    276 	fclose(fp);
    277 	return 0;
    278 }
    279 
    280 int sha256_32_file(const char *file, uint32_t *nid)
    281 {
    282   uint8_t hash[32];
    283   uint8_t *hash_ptr = hash;
    284   
    285   if (sha256_file(file, hash) < 0)
    286   {
    287     fprintf(stderr, "error: could not calculate SHA256 of '%s'\n", file);
    288     // TODO: handle better, cleanup tree
    289     return -1;
    290   }
    291   
    292   size_t len = 32;
    293   *nid = sha256_32_vector(1, &hash_ptr, &len);
    294   return 0;
    295 }