178acc472SPeter Tyser /* 278acc472SPeter Tyser * FIPS-180-2 compliant SHA-256 implementation 378acc472SPeter Tyser * 478acc472SPeter Tyser * Copyright (C) 2001-2003 Christophe Devine 578acc472SPeter Tyser * 6*1a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 778acc472SPeter Tyser */ 878acc472SPeter Tyser 978acc472SPeter Tyser #ifndef USE_HOSTCC 1078acc472SPeter Tyser #include <common.h> 1178acc472SPeter Tyser #endif /* USE_HOSTCC */ 1278acc472SPeter Tyser #include <watchdog.h> 1378acc472SPeter Tyser #include <linux/string.h> 1478acc472SPeter Tyser #include <sha256.h> 1578acc472SPeter Tyser 1678acc472SPeter Tyser /* 1778acc472SPeter Tyser * 32-bit integer manipulation macros (big endian) 1878acc472SPeter Tyser */ 1978acc472SPeter Tyser #ifndef GET_UINT32_BE 2078acc472SPeter Tyser #define GET_UINT32_BE(n,b,i) { \ 2178acc472SPeter Tyser (n) = ( (unsigned long) (b)[(i) ] << 24 ) \ 2278acc472SPeter Tyser | ( (unsigned long) (b)[(i) + 1] << 16 ) \ 2378acc472SPeter Tyser | ( (unsigned long) (b)[(i) + 2] << 8 ) \ 2478acc472SPeter Tyser | ( (unsigned long) (b)[(i) + 3] ); \ 2578acc472SPeter Tyser } 2678acc472SPeter Tyser #endif 2778acc472SPeter Tyser #ifndef PUT_UINT32_BE 2878acc472SPeter Tyser #define PUT_UINT32_BE(n,b,i) { \ 2978acc472SPeter Tyser (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ 3078acc472SPeter Tyser (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ 3178acc472SPeter Tyser (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ 3278acc472SPeter Tyser (b)[(i) + 3] = (unsigned char) ( (n) ); \ 3378acc472SPeter Tyser } 3478acc472SPeter Tyser #endif 3578acc472SPeter Tyser 3678acc472SPeter Tyser void sha256_starts(sha256_context * ctx) 3778acc472SPeter Tyser { 3878acc472SPeter Tyser ctx->total[0] = 0; 3978acc472SPeter Tyser ctx->total[1] = 0; 4078acc472SPeter Tyser 4178acc472SPeter Tyser ctx->state[0] = 0x6A09E667; 4278acc472SPeter Tyser ctx->state[1] = 0xBB67AE85; 4378acc472SPeter Tyser ctx->state[2] = 0x3C6EF372; 4478acc472SPeter Tyser ctx->state[3] = 0xA54FF53A; 4578acc472SPeter Tyser ctx->state[4] = 0x510E527F; 4678acc472SPeter Tyser ctx->state[5] = 0x9B05688C; 4778acc472SPeter Tyser ctx->state[6] = 0x1F83D9AB; 4878acc472SPeter Tyser ctx->state[7] = 0x5BE0CD19; 4978acc472SPeter Tyser } 5078acc472SPeter Tyser 51ec7381fbSSimon Glass static void sha256_process(sha256_context *ctx, const uint8_t data[64]) 5278acc472SPeter Tyser { 5378acc472SPeter Tyser uint32_t temp1, temp2; 5478acc472SPeter Tyser uint32_t W[64]; 5578acc472SPeter Tyser uint32_t A, B, C, D, E, F, G, H; 5678acc472SPeter Tyser 5778acc472SPeter Tyser GET_UINT32_BE(W[0], data, 0); 5878acc472SPeter Tyser GET_UINT32_BE(W[1], data, 4); 5978acc472SPeter Tyser GET_UINT32_BE(W[2], data, 8); 6078acc472SPeter Tyser GET_UINT32_BE(W[3], data, 12); 6178acc472SPeter Tyser GET_UINT32_BE(W[4], data, 16); 6278acc472SPeter Tyser GET_UINT32_BE(W[5], data, 20); 6378acc472SPeter Tyser GET_UINT32_BE(W[6], data, 24); 6478acc472SPeter Tyser GET_UINT32_BE(W[7], data, 28); 6578acc472SPeter Tyser GET_UINT32_BE(W[8], data, 32); 6678acc472SPeter Tyser GET_UINT32_BE(W[9], data, 36); 6778acc472SPeter Tyser GET_UINT32_BE(W[10], data, 40); 6878acc472SPeter Tyser GET_UINT32_BE(W[11], data, 44); 6978acc472SPeter Tyser GET_UINT32_BE(W[12], data, 48); 7078acc472SPeter Tyser GET_UINT32_BE(W[13], data, 52); 7178acc472SPeter Tyser GET_UINT32_BE(W[14], data, 56); 7278acc472SPeter Tyser GET_UINT32_BE(W[15], data, 60); 7378acc472SPeter Tyser 7478acc472SPeter Tyser #define SHR(x,n) ((x & 0xFFFFFFFF) >> n) 7578acc472SPeter Tyser #define ROTR(x,n) (SHR(x,n) | (x << (32 - n))) 7678acc472SPeter Tyser 7778acc472SPeter Tyser #define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3)) 7878acc472SPeter Tyser #define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10)) 7978acc472SPeter Tyser 8078acc472SPeter Tyser #define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22)) 8178acc472SPeter Tyser #define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25)) 8278acc472SPeter Tyser 8378acc472SPeter Tyser #define F0(x,y,z) ((x & y) | (z & (x | y))) 8478acc472SPeter Tyser #define F1(x,y,z) (z ^ (x & (y ^ z))) 8578acc472SPeter Tyser 8678acc472SPeter Tyser #define R(t) \ 8778acc472SPeter Tyser ( \ 8878acc472SPeter Tyser W[t] = S1(W[t - 2]) + W[t - 7] + \ 8978acc472SPeter Tyser S0(W[t - 15]) + W[t - 16] \ 9078acc472SPeter Tyser ) 9178acc472SPeter Tyser 9278acc472SPeter Tyser #define P(a,b,c,d,e,f,g,h,x,K) { \ 9378acc472SPeter Tyser temp1 = h + S3(e) + F1(e,f,g) + K + x; \ 9478acc472SPeter Tyser temp2 = S2(a) + F0(a,b,c); \ 9578acc472SPeter Tyser d += temp1; h = temp1 + temp2; \ 9678acc472SPeter Tyser } 9778acc472SPeter Tyser 9878acc472SPeter Tyser A = ctx->state[0]; 9978acc472SPeter Tyser B = ctx->state[1]; 10078acc472SPeter Tyser C = ctx->state[2]; 10178acc472SPeter Tyser D = ctx->state[3]; 10278acc472SPeter Tyser E = ctx->state[4]; 10378acc472SPeter Tyser F = ctx->state[5]; 10478acc472SPeter Tyser G = ctx->state[6]; 10578acc472SPeter Tyser H = ctx->state[7]; 10678acc472SPeter Tyser 10778acc472SPeter Tyser P(A, B, C, D, E, F, G, H, W[0], 0x428A2F98); 10878acc472SPeter Tyser P(H, A, B, C, D, E, F, G, W[1], 0x71374491); 10978acc472SPeter Tyser P(G, H, A, B, C, D, E, F, W[2], 0xB5C0FBCF); 11078acc472SPeter Tyser P(F, G, H, A, B, C, D, E, W[3], 0xE9B5DBA5); 11178acc472SPeter Tyser P(E, F, G, H, A, B, C, D, W[4], 0x3956C25B); 11278acc472SPeter Tyser P(D, E, F, G, H, A, B, C, W[5], 0x59F111F1); 11378acc472SPeter Tyser P(C, D, E, F, G, H, A, B, W[6], 0x923F82A4); 11478acc472SPeter Tyser P(B, C, D, E, F, G, H, A, W[7], 0xAB1C5ED5); 11578acc472SPeter Tyser P(A, B, C, D, E, F, G, H, W[8], 0xD807AA98); 11678acc472SPeter Tyser P(H, A, B, C, D, E, F, G, W[9], 0x12835B01); 11778acc472SPeter Tyser P(G, H, A, B, C, D, E, F, W[10], 0x243185BE); 11878acc472SPeter Tyser P(F, G, H, A, B, C, D, E, W[11], 0x550C7DC3); 11978acc472SPeter Tyser P(E, F, G, H, A, B, C, D, W[12], 0x72BE5D74); 12078acc472SPeter Tyser P(D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE); 12178acc472SPeter Tyser P(C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7); 12278acc472SPeter Tyser P(B, C, D, E, F, G, H, A, W[15], 0xC19BF174); 12378acc472SPeter Tyser P(A, B, C, D, E, F, G, H, R(16), 0xE49B69C1); 12478acc472SPeter Tyser P(H, A, B, C, D, E, F, G, R(17), 0xEFBE4786); 12578acc472SPeter Tyser P(G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6); 12678acc472SPeter Tyser P(F, G, H, A, B, C, D, E, R(19), 0x240CA1CC); 12778acc472SPeter Tyser P(E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F); 12878acc472SPeter Tyser P(D, E, F, G, H, A, B, C, R(21), 0x4A7484AA); 12978acc472SPeter Tyser P(C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC); 13078acc472SPeter Tyser P(B, C, D, E, F, G, H, A, R(23), 0x76F988DA); 13178acc472SPeter Tyser P(A, B, C, D, E, F, G, H, R(24), 0x983E5152); 13278acc472SPeter Tyser P(H, A, B, C, D, E, F, G, R(25), 0xA831C66D); 13378acc472SPeter Tyser P(G, H, A, B, C, D, E, F, R(26), 0xB00327C8); 13478acc472SPeter Tyser P(F, G, H, A, B, C, D, E, R(27), 0xBF597FC7); 13578acc472SPeter Tyser P(E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3); 13678acc472SPeter Tyser P(D, E, F, G, H, A, B, C, R(29), 0xD5A79147); 13778acc472SPeter Tyser P(C, D, E, F, G, H, A, B, R(30), 0x06CA6351); 13878acc472SPeter Tyser P(B, C, D, E, F, G, H, A, R(31), 0x14292967); 13978acc472SPeter Tyser P(A, B, C, D, E, F, G, H, R(32), 0x27B70A85); 14078acc472SPeter Tyser P(H, A, B, C, D, E, F, G, R(33), 0x2E1B2138); 14178acc472SPeter Tyser P(G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC); 14278acc472SPeter Tyser P(F, G, H, A, B, C, D, E, R(35), 0x53380D13); 14378acc472SPeter Tyser P(E, F, G, H, A, B, C, D, R(36), 0x650A7354); 14478acc472SPeter Tyser P(D, E, F, G, H, A, B, C, R(37), 0x766A0ABB); 14578acc472SPeter Tyser P(C, D, E, F, G, H, A, B, R(38), 0x81C2C92E); 14678acc472SPeter Tyser P(B, C, D, E, F, G, H, A, R(39), 0x92722C85); 14778acc472SPeter Tyser P(A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1); 14878acc472SPeter Tyser P(H, A, B, C, D, E, F, G, R(41), 0xA81A664B); 14978acc472SPeter Tyser P(G, H, A, B, C, D, E, F, R(42), 0xC24B8B70); 15078acc472SPeter Tyser P(F, G, H, A, B, C, D, E, R(43), 0xC76C51A3); 15178acc472SPeter Tyser P(E, F, G, H, A, B, C, D, R(44), 0xD192E819); 15278acc472SPeter Tyser P(D, E, F, G, H, A, B, C, R(45), 0xD6990624); 15378acc472SPeter Tyser P(C, D, E, F, G, H, A, B, R(46), 0xF40E3585); 15478acc472SPeter Tyser P(B, C, D, E, F, G, H, A, R(47), 0x106AA070); 15578acc472SPeter Tyser P(A, B, C, D, E, F, G, H, R(48), 0x19A4C116); 15678acc472SPeter Tyser P(H, A, B, C, D, E, F, G, R(49), 0x1E376C08); 15778acc472SPeter Tyser P(G, H, A, B, C, D, E, F, R(50), 0x2748774C); 15878acc472SPeter Tyser P(F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5); 15978acc472SPeter Tyser P(E, F, G, H, A, B, C, D, R(52), 0x391C0CB3); 16078acc472SPeter Tyser P(D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A); 16178acc472SPeter Tyser P(C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F); 16278acc472SPeter Tyser P(B, C, D, E, F, G, H, A, R(55), 0x682E6FF3); 16378acc472SPeter Tyser P(A, B, C, D, E, F, G, H, R(56), 0x748F82EE); 16478acc472SPeter Tyser P(H, A, B, C, D, E, F, G, R(57), 0x78A5636F); 16578acc472SPeter Tyser P(G, H, A, B, C, D, E, F, R(58), 0x84C87814); 16678acc472SPeter Tyser P(F, G, H, A, B, C, D, E, R(59), 0x8CC70208); 16778acc472SPeter Tyser P(E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA); 16878acc472SPeter Tyser P(D, E, F, G, H, A, B, C, R(61), 0xA4506CEB); 16978acc472SPeter Tyser P(C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7); 17078acc472SPeter Tyser P(B, C, D, E, F, G, H, A, R(63), 0xC67178F2); 17178acc472SPeter Tyser 17278acc472SPeter Tyser ctx->state[0] += A; 17378acc472SPeter Tyser ctx->state[1] += B; 17478acc472SPeter Tyser ctx->state[2] += C; 17578acc472SPeter Tyser ctx->state[3] += D; 17678acc472SPeter Tyser ctx->state[4] += E; 17778acc472SPeter Tyser ctx->state[5] += F; 17878acc472SPeter Tyser ctx->state[6] += G; 17978acc472SPeter Tyser ctx->state[7] += H; 18078acc472SPeter Tyser } 18178acc472SPeter Tyser 182ec7381fbSSimon Glass void sha256_update(sha256_context *ctx, const uint8_t *input, uint32_t length) 18378acc472SPeter Tyser { 18478acc472SPeter Tyser uint32_t left, fill; 18578acc472SPeter Tyser 18678acc472SPeter Tyser if (!length) 18778acc472SPeter Tyser return; 18878acc472SPeter Tyser 18978acc472SPeter Tyser left = ctx->total[0] & 0x3F; 19078acc472SPeter Tyser fill = 64 - left; 19178acc472SPeter Tyser 19278acc472SPeter Tyser ctx->total[0] += length; 19378acc472SPeter Tyser ctx->total[0] &= 0xFFFFFFFF; 19478acc472SPeter Tyser 19578acc472SPeter Tyser if (ctx->total[0] < length) 19678acc472SPeter Tyser ctx->total[1]++; 19778acc472SPeter Tyser 19878acc472SPeter Tyser if (left && length >= fill) { 19978acc472SPeter Tyser memcpy((void *) (ctx->buffer + left), (void *) input, fill); 20078acc472SPeter Tyser sha256_process(ctx, ctx->buffer); 20178acc472SPeter Tyser length -= fill; 20278acc472SPeter Tyser input += fill; 20378acc472SPeter Tyser left = 0; 20478acc472SPeter Tyser } 20578acc472SPeter Tyser 20678acc472SPeter Tyser while (length >= 64) { 20778acc472SPeter Tyser sha256_process(ctx, input); 20878acc472SPeter Tyser length -= 64; 20978acc472SPeter Tyser input += 64; 21078acc472SPeter Tyser } 21178acc472SPeter Tyser 21278acc472SPeter Tyser if (length) 21378acc472SPeter Tyser memcpy((void *) (ctx->buffer + left), (void *) input, length); 21478acc472SPeter Tyser } 21578acc472SPeter Tyser 21678acc472SPeter Tyser static uint8_t sha256_padding[64] = { 21778acc472SPeter Tyser 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21878acc472SPeter Tyser 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21978acc472SPeter Tyser 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22078acc472SPeter Tyser 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 22178acc472SPeter Tyser }; 22278acc472SPeter Tyser 22378acc472SPeter Tyser void sha256_finish(sha256_context * ctx, uint8_t digest[32]) 22478acc472SPeter Tyser { 22578acc472SPeter Tyser uint32_t last, padn; 22678acc472SPeter Tyser uint32_t high, low; 22778acc472SPeter Tyser uint8_t msglen[8]; 22878acc472SPeter Tyser 22978acc472SPeter Tyser high = ((ctx->total[0] >> 29) 23078acc472SPeter Tyser | (ctx->total[1] << 3)); 23178acc472SPeter Tyser low = (ctx->total[0] << 3); 23278acc472SPeter Tyser 23378acc472SPeter Tyser PUT_UINT32_BE(high, msglen, 0); 23478acc472SPeter Tyser PUT_UINT32_BE(low, msglen, 4); 23578acc472SPeter Tyser 23678acc472SPeter Tyser last = ctx->total[0] & 0x3F; 23778acc472SPeter Tyser padn = (last < 56) ? (56 - last) : (120 - last); 23878acc472SPeter Tyser 23978acc472SPeter Tyser sha256_update(ctx, sha256_padding, padn); 24078acc472SPeter Tyser sha256_update(ctx, msglen, 8); 24178acc472SPeter Tyser 24278acc472SPeter Tyser PUT_UINT32_BE(ctx->state[0], digest, 0); 24378acc472SPeter Tyser PUT_UINT32_BE(ctx->state[1], digest, 4); 24478acc472SPeter Tyser PUT_UINT32_BE(ctx->state[2], digest, 8); 24578acc472SPeter Tyser PUT_UINT32_BE(ctx->state[3], digest, 12); 24678acc472SPeter Tyser PUT_UINT32_BE(ctx->state[4], digest, 16); 24778acc472SPeter Tyser PUT_UINT32_BE(ctx->state[5], digest, 20); 24878acc472SPeter Tyser PUT_UINT32_BE(ctx->state[6], digest, 24); 24978acc472SPeter Tyser PUT_UINT32_BE(ctx->state[7], digest, 28); 25078acc472SPeter Tyser } 251ec7381fbSSimon Glass 252ec7381fbSSimon Glass /* 253ec7381fbSSimon Glass * Output = SHA-256( input buffer ). Trigger the watchdog every 'chunk_sz' 254ec7381fbSSimon Glass * bytes of input processed. 255ec7381fbSSimon Glass */ 256ec7381fbSSimon Glass void sha256_csum_wd(const unsigned char *input, unsigned int ilen, 257ec7381fbSSimon Glass unsigned char *output, unsigned int chunk_sz) 258ec7381fbSSimon Glass { 259ec7381fbSSimon Glass sha256_context ctx; 260ec7381fbSSimon Glass #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) 261ec7381fbSSimon Glass unsigned char *end, *curr; 262ec7381fbSSimon Glass int chunk; 263ec7381fbSSimon Glass #endif 264ec7381fbSSimon Glass 265ec7381fbSSimon Glass sha256_starts(&ctx); 266ec7381fbSSimon Glass 267ec7381fbSSimon Glass #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) 268ec7381fbSSimon Glass curr = input; 269ec7381fbSSimon Glass end = input + ilen; 270ec7381fbSSimon Glass while (curr < end) { 271ec7381fbSSimon Glass chunk = end - curr; 272ec7381fbSSimon Glass if (chunk > chunk_sz) 273ec7381fbSSimon Glass chunk = chunk_sz; 274ec7381fbSSimon Glass sha256_update(&ctx, curr, chunk); 275ec7381fbSSimon Glass curr += chunk; 276ec7381fbSSimon Glass WATCHDOG_RESET(); 277ec7381fbSSimon Glass } 278ec7381fbSSimon Glass #else 279ec7381fbSSimon Glass sha256_update(&ctx, input, ilen); 280ec7381fbSSimon Glass #endif 281ec7381fbSSimon Glass 282ec7381fbSSimon Glass sha256_finish(&ctx, output); 283ec7381fbSSimon Glass } 284