1 // SPDX-License-Identifier: Apache-2.0 2 /* 3 * FIPS-180-2 compliant SHA-384/512 implementation 4 * 5 * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); you may 8 * not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 * This file is part of mbed TLS (https://tls.mbed.org) 20 */ 21 /* 22 * The SHA-512 Secure Hash Standard was published by NIST in 2002. 23 * 24 * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf 25 */ 26 27 #ifndef USE_HOSTCC 28 #include <common.h> 29 #include <linux/string.h> 30 #else 31 #include <string.h> 32 #endif /* USE_HOSTCC */ 33 #include <u-boot/sha512.h> 34 35 #if defined(_MSC_VER) || defined(__WATCOMC__) 36 #define UL64(x) x##ui64 37 #else 38 #define UL64(x) x##ULL 39 #endif 40 41 /* 42 * 64-bit integer manipulation macros (big endian) 43 */ 44 #ifndef GET_UINT64_BE 45 #define GET_UINT64_BE(n,b,i) \ 46 { \ 47 (n) = ((uint64_t)(b)[(i) ] << 56) \ 48 | ((uint64_t)(b)[(i) + 1] << 48) \ 49 | ((uint64_t)(b)[(i) + 2] << 40) \ 50 | ((uint64_t)(b)[(i) + 3] << 32) \ 51 | ((uint64_t)(b)[(i) + 4] << 24) \ 52 | ((uint64_t)(b)[(i) + 5] << 16) \ 53 | ((uint64_t)(b)[(i) + 6] << 8) \ 54 | ((uint64_t)(b)[(i) + 7] ); \ 55 } 56 #endif /* GET_UINT64_BE */ 57 58 #ifndef PUT_UINT64_BE 59 #define PUT_UINT64_BE(n,b,i) \ 60 { \ 61 (b)[(i) ] = (unsigned char) ((n) >> 56); \ 62 (b)[(i) + 1] = (unsigned char) ((n) >> 48); \ 63 (b)[(i) + 2] = (unsigned char) ((n) >> 40); \ 64 (b)[(i) + 3] = (unsigned char) ((n) >> 32); \ 65 (b)[(i) + 4] = (unsigned char) ((n) >> 24); \ 66 (b)[(i) + 5] = (unsigned char) ((n) >> 16); \ 67 (b)[(i) + 6] = (unsigned char) ((n) >> 8); \ 68 (b)[(i) + 7] = (unsigned char) ((n) ); \ 69 } 70 #endif /* PUT_UINT64_BE */ 71 72 /* 73 * SHA-512 context setup 74 */ 75 static int __sha512_starts(sha512_context *ctx, int is384) 76 { 77 ctx->total[0] = 0; 78 ctx->total[1] = 0; 79 80 if (is384 == 0) { 81 /* SHA-512 */ 82 ctx->state[0] = UL64(0x6A09E667F3BCC908); 83 ctx->state[1] = UL64(0xBB67AE8584CAA73B); 84 ctx->state[2] = UL64(0x3C6EF372FE94F82B); 85 ctx->state[3] = UL64(0xA54FF53A5F1D36F1); 86 ctx->state[4] = UL64(0x510E527FADE682D1); 87 ctx->state[5] = UL64(0x9B05688C2B3E6C1F); 88 ctx->state[6] = UL64(0x1F83D9ABFB41BD6B); 89 ctx->state[7] = UL64(0x5BE0CD19137E2179); 90 } else { 91 /* SHA-384 */ 92 ctx->state[0] = UL64(0xCBBB9D5DC1059ED8); 93 ctx->state[1] = UL64(0x629A292A367CD507); 94 ctx->state[2] = UL64(0x9159015A3070DD17); 95 ctx->state[3] = UL64(0x152FECD8F70E5939); 96 ctx->state[4] = UL64(0x67332667FFC00B31); 97 ctx->state[5] = UL64(0x8EB44A8768581511); 98 ctx->state[6] = UL64(0xDB0C2E0D64F98FA7); 99 ctx->state[7] = UL64(0x47B5481DBEFA4FA4); 100 } 101 102 ctx->is384 = is384; 103 104 return(0); 105 } 106 107 int sha512_starts(sha512_context *ctx) 108 { 109 return __sha512_starts(ctx, 0); 110 } 111 112 /* 113 * Round constants 114 */ 115 static const uint64_t K[80] = { 116 UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD), 117 UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC), 118 UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019), 119 UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118), 120 UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE), 121 UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2), 122 UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1), 123 UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694), 124 UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3), 125 UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65), 126 UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483), 127 UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5), 128 UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210), 129 UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4), 130 UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725), 131 UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70), 132 UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926), 133 UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF), 134 UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8), 135 UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B), 136 UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001), 137 UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30), 138 UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910), 139 UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8), 140 UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53), 141 UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8), 142 UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB), 143 UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3), 144 UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60), 145 UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC), 146 UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9), 147 UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B), 148 UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207), 149 UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178), 150 UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6), 151 UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B), 152 UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493), 153 UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C), 154 UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A), 155 UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817) 156 }; 157 158 static int sha512_process(sha512_context *ctx, const unsigned char data[128]) 159 { 160 int i; 161 uint64_t temp1, temp2, W[80]; 162 uint64_t A, B, C, D, E, F, G, H; 163 164 #define SHR(x,n) (x >> n) 165 #define ROTR(x,n) (SHR(x,n) | (x << (64 - n))) 166 167 #define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7)) 168 #define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6)) 169 170 #define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39)) 171 #define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41)) 172 173 #define F0(x,y,z) ((x & y) | (z & (x | y))) 174 #define F1(x,y,z) (z ^ (x & (y ^ z))) 175 176 #define P(a,b,c,d,e,f,g,h,x,K) \ 177 { \ 178 temp1 = h + S3(e) + F1(e,f,g) + K + x; \ 179 temp2 = S2(a) + F0(a,b,c); \ 180 d += temp1; h = temp1 + temp2; \ 181 } 182 183 for (i = 0; i < 16; i++) { 184 GET_UINT64_BE(W[i], data, i << 3); 185 } 186 187 for (; i < 80; i++) { 188 W[i] = S1(W[i - 2]) + W[i - 7] + 189 S0(W[i - 15]) + W[i - 16]; 190 } 191 192 A = ctx->state[0]; 193 B = ctx->state[1]; 194 C = ctx->state[2]; 195 D = ctx->state[3]; 196 E = ctx->state[4]; 197 F = ctx->state[5]; 198 G = ctx->state[6]; 199 H = ctx->state[7]; 200 i = 0; 201 202 do { 203 P(A, B, C, D, E, F, G, H, W[i], K[i]); 204 i++; 205 P(H, A, B, C, D, E, F, G, W[i], K[i]); 206 i++; 207 P(G, H, A, B, C, D, E, F, W[i], K[i]); 208 i++; 209 P(F, G, H, A, B, C, D, E, W[i], K[i]); 210 i++; 211 P(E, F, G, H, A, B, C, D, W[i], K[i]); 212 i++; 213 P(D, E, F, G, H, A, B, C, W[i], K[i]); 214 i++; 215 P(C, D, E, F, G, H, A, B, W[i], K[i]); 216 i++; 217 P(B, C, D, E, F, G, H, A, W[i], K[i]); 218 i++; 219 } while (i < 80); 220 221 ctx->state[0] += A; 222 ctx->state[1] += B; 223 ctx->state[2] += C; 224 ctx->state[3] += D; 225 ctx->state[4] += E; 226 ctx->state[5] += F; 227 ctx->state[6] += G; 228 ctx->state[7] += H; 229 230 return(0); 231 } 232 233 /* 234 * SHA-512 process buffer 235 */ 236 int sha512_update(sha512_context *ctx, const unsigned char *input, size_t ilen) 237 { 238 int ret; 239 size_t fill; 240 unsigned int left; 241 242 if (ilen == 0) 243 return(0); 244 245 left = (unsigned int)(ctx->total[0] & 0x7F); 246 fill = 128 - left; 247 248 ctx->total[0] += (uint64_t)ilen; 249 250 if (ctx->total[0] < (uint64_t)ilen) 251 ctx->total[1]++; 252 253 if (left && ilen >= fill) { 254 memcpy((void *)(ctx->buffer + left), input, fill); 255 256 if ((ret = sha512_process(ctx, ctx->buffer)) != 0) 257 return(ret); 258 259 input += fill; 260 ilen -= fill; 261 left = 0; 262 } 263 264 while (ilen >= 128) { 265 if ((ret = sha512_process(ctx, input)) != 0) 266 return(ret); 267 268 input += 128; 269 ilen -= 128; 270 } 271 272 if (ilen > 0) 273 memcpy((void *)(ctx->buffer + left), input, ilen); 274 275 return(0); 276 } 277 278 /* 279 * SHA-512 final digest 280 */ 281 int sha512_finish(sha512_context *ctx, unsigned char output[64]) 282 { 283 int ret; 284 unsigned used; 285 uint64_t high, low; 286 287 /* 288 * Add padding: 0x80 then 0x00 until 16 bytes remain for the length 289 */ 290 used = ctx->total[0] & 0x7F; 291 292 ctx->buffer[used++] = 0x80; 293 294 if (used <= 112) { 295 /* Enough room for padding + length in current block */ 296 memset(ctx->buffer + used, 0, 112 - used); 297 } else { 298 /* We'll need an extra block */ 299 memset(ctx->buffer + used, 0, 128 - used); 300 301 if ((ret = sha512_process(ctx, ctx->buffer)) != 0) 302 return(ret); 303 304 memset(ctx->buffer, 0, 112); 305 } 306 307 /* 308 * Add message length 309 */ 310 high = (ctx->total[0] >> 61) 311 | (ctx->total[1] << 3); 312 low = (ctx->total[0] << 3); 313 314 PUT_UINT64_BE(high, ctx->buffer, 112); 315 PUT_UINT64_BE(low, ctx->buffer, 120); 316 317 if ((ret = sha512_process(ctx, ctx->buffer)) != 0) 318 return(ret); 319 320 /* 321 * Output final state 322 */ 323 PUT_UINT64_BE(ctx->state[0], output, 0); 324 PUT_UINT64_BE(ctx->state[1], output, 8); 325 PUT_UINT64_BE(ctx->state[2], output, 16); 326 PUT_UINT64_BE(ctx->state[3], output, 24); 327 PUT_UINT64_BE(ctx->state[4], output, 32); 328 PUT_UINT64_BE(ctx->state[5], output, 40); 329 330 if (ctx->is384 == 0) { 331 PUT_UINT64_BE(ctx->state[6], output, 48); 332 PUT_UINT64_BE(ctx->state[7], output, 56); 333 } 334 335 return(0); 336 } 337 338 void sha512_csum(const unsigned char *input, unsigned int ilen, 339 unsigned char output[64]) 340 { 341 sha512_context ctx; 342 343 sha512_starts(&ctx); 344 sha512_update(&ctx, input, ilen); 345 sha512_finish(&ctx, output); 346 } 347