1 /* 2 * Copyright (C) 2017 - This file is part of libecc project 3 * 4 * Authors: 5 * Ryad BENADJILA <ryadbenadjila@gmail.com> 6 * Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr> 7 * Jean-Pierre FLORI <jean-pierre.flori@ssi.gouv.fr> 8 * 9 * Contributors: 10 * Nicolas VIVET <nicolas.vivet@ssi.gouv.fr> 11 * Karim KHALFALLAH <karim.khalfallah@ssi.gouv.fr> 12 * 13 * This software is licensed under a dual BSD and GPL v2 license. 14 * See LICENSE file at the root folder of the project. 15 */ 16 #include <libecc/lib_ecc_config.h> 17 #ifdef WITH_HASH_SHA384 18 19 #include <libecc/hash/sha384.h> 20 21 /* SHA-2 core processing. Returns 0 on success, -1 on error. */ 22 ATTRIBUTE_WARN_UNUSED_RET static int sha384_process(sha384_context *ctx, 23 const u8 data[SHA384_BLOCK_SIZE]) 24 { 25 u64 a, b, c, d, e, f, g, h; 26 u64 W[80]; 27 unsigned int i; 28 int ret; 29 30 MUST_HAVE((data != NULL), ret, err); 31 SHA384_HASH_CHECK_INITIALIZED(ctx, ret, err); 32 33 /* Init our inner variables */ 34 a = ctx->sha384_state[0]; 35 b = ctx->sha384_state[1]; 36 c = ctx->sha384_state[2]; 37 d = ctx->sha384_state[3]; 38 e = ctx->sha384_state[4]; 39 f = ctx->sha384_state[5]; 40 g = ctx->sha384_state[6]; 41 h = ctx->sha384_state[7]; 42 43 for (i = 0; i < 16; i++) { 44 GET_UINT64_BE(W[i], data, 8 * i); 45 SHA2CORE_SHA512(a, b, c, d, e, f, g, h, W[i], K_SHA512[i]); 46 } 47 48 for (i = 16; i < 80; i++) { 49 SHA2CORE_SHA512(a, b, c, d, e, f, g, h, UPDATEW_SHA512(W, i), 50 K_SHA512[i]); 51 } 52 53 /* Update state */ 54 ctx->sha384_state[0] += a; 55 ctx->sha384_state[1] += b; 56 ctx->sha384_state[2] += c; 57 ctx->sha384_state[3] += d; 58 ctx->sha384_state[4] += e; 59 ctx->sha384_state[5] += f; 60 ctx->sha384_state[6] += g; 61 ctx->sha384_state[7] += h; 62 63 ret = 0; 64 65 err: 66 return ret; 67 } 68 69 /* Init hash function. Returns 0 on success, -1 on error. */ 70 int sha384_init(sha384_context *ctx) 71 { 72 int ret; 73 74 MUST_HAVE((ctx != NULL), ret, err); 75 76 ctx->sha384_total[0] = ctx->sha384_total[1] = 0; 77 ctx->sha384_state[0] = (u64)(0xCBBB9D5DC1059ED8); 78 ctx->sha384_state[1] = (u64)(0x629A292A367CD507); 79 ctx->sha384_state[2] = (u64)(0x9159015A3070DD17); 80 ctx->sha384_state[3] = (u64)(0x152FECD8F70E5939); 81 ctx->sha384_state[4] = (u64)(0x67332667FFC00B31); 82 ctx->sha384_state[5] = (u64)(0x8EB44A8768581511); 83 ctx->sha384_state[6] = (u64)(0xDB0C2E0D64F98FA7); 84 ctx->sha384_state[7] = (u64)(0x47B5481DBEFA4FA4); 85 86 /* Tell that we are initialized */ 87 ctx->magic = SHA384_HASH_MAGIC; 88 ret = 0; 89 90 err: 91 return ret; 92 } 93 94 /* Update hash function. Returns 0 on success, -1 on error. */ 95 int sha384_update(sha384_context *ctx, const u8 *input, u32 ilen) 96 { 97 u32 left; 98 u32 fill; 99 const u8 *data_ptr = input; 100 u32 remain_ilen = ilen; 101 int ret; 102 103 MUST_HAVE((input != NULL), ret, err); 104 SHA384_HASH_CHECK_INITIALIZED(ctx, ret, err); 105 106 /* Nothing to process, return */ 107 if (ilen == 0) { 108 ret = 0; 109 goto err; 110 } 111 112 /* Get what's left in our local buffer */ 113 left = (ctx->sha384_total[0] & 0x7F); 114 fill = (SHA384_BLOCK_SIZE - left); 115 116 ADD_UINT128_UINT64(ctx->sha384_total[0], ctx->sha384_total[1], ilen); 117 118 if ((left > 0) && (remain_ilen >= fill)) { 119 /* Copy data at the end of the buffer */ 120 ret = local_memcpy(ctx->sha384_buffer + left, data_ptr, fill); EG(ret, err); 121 ret = sha384_process(ctx, ctx->sha384_buffer); EG(ret, err); 122 data_ptr += fill; 123 remain_ilen -= fill; 124 left = 0; 125 } 126 127 while (remain_ilen >= SHA384_BLOCK_SIZE) { 128 ret = sha384_process(ctx, data_ptr); EG(ret, err); 129 data_ptr += SHA384_BLOCK_SIZE; 130 remain_ilen -= SHA384_BLOCK_SIZE; 131 } 132 133 if (remain_ilen > 0) { 134 ret = local_memcpy(ctx->sha384_buffer + left, data_ptr, remain_ilen); EG(ret, err); 135 } 136 137 ret = 0; 138 139 err: 140 return ret; 141 } 142 143 /* 144 * Finalize hash function. Returns 0 on success, -1 on error. In all 145 * cases (success or error), hash context is no more usable after the 146 * call. 147 */ 148 int sha384_final(sha384_context *ctx, u8 output[SHA384_DIGEST_SIZE]) 149 { 150 unsigned int block_present = 0; 151 u8 last_padded_block[2 * SHA384_BLOCK_SIZE]; 152 int ret; 153 154 MUST_HAVE((output != NULL), ret, err); 155 SHA384_HASH_CHECK_INITIALIZED(ctx, ret, err); 156 157 /* Fill in our last block with zeroes */ 158 ret = local_memset(last_padded_block, 0, sizeof(last_padded_block)); EG(ret, err); 159 160 /* This is our final step, so we proceed with the padding */ 161 block_present = (ctx->sha384_total[0] % SHA384_BLOCK_SIZE); 162 if (block_present != 0) { 163 /* Copy what's left in our temporary context buffer */ 164 ret = local_memcpy(last_padded_block, ctx->sha384_buffer, 165 block_present); EG(ret, err); 166 } 167 168 /* Put the 0x80 byte, beginning of padding */ 169 last_padded_block[block_present] = 0x80; 170 171 /* Handle possible additional block */ 172 if (block_present > (SHA384_BLOCK_SIZE - 1 - (2 * sizeof(u64)))) { 173 /* We need an additional block */ 174 PUT_MUL8_UINT128_BE(ctx->sha384_total[0], ctx->sha384_total[1], 175 last_padded_block, 176 2 * (SHA384_BLOCK_SIZE - sizeof(u64))); 177 ret = sha384_process(ctx, last_padded_block); EG(ret, err); 178 ret = sha384_process(ctx, last_padded_block + SHA384_BLOCK_SIZE); EG(ret, err); 179 } else { 180 /* We do not need an additional block */ 181 PUT_MUL8_UINT128_BE(ctx->sha384_total[0], ctx->sha384_total[1], 182 last_padded_block, 183 SHA384_BLOCK_SIZE - (2 * sizeof(u64))); 184 ret = sha384_process(ctx, last_padded_block); EG(ret, err); 185 } 186 187 /* Output the hash result */ 188 PUT_UINT64_BE(ctx->sha384_state[0], output, 0); 189 PUT_UINT64_BE(ctx->sha384_state[1], output, 8); 190 PUT_UINT64_BE(ctx->sha384_state[2], output, 16); 191 PUT_UINT64_BE(ctx->sha384_state[3], output, 24); 192 PUT_UINT64_BE(ctx->sha384_state[4], output, 32); 193 PUT_UINT64_BE(ctx->sha384_state[5], output, 40); 194 195 /* Tell that we are uninitialized */ 196 ctx->magic = WORD(0); 197 198 ret = 0; 199 200 err: 201 return ret; 202 } 203 204 /* 205 * Scattered version performing init/update/finalize on a vector of buffers 206 * 'inputs' with the length of each buffer passed via 'ilens'. The function 207 * loops on pointers in 'inputs' until it finds a NULL pointer. The function 208 * returns 0 on success, -1 on error. 209 */ 210 int sha384_scattered(const u8 **inputs, const u32 *ilens, 211 u8 output[SHA384_DIGEST_SIZE]) 212 { 213 sha384_context ctx; 214 int pos = 0; 215 int ret; 216 217 MUST_HAVE((inputs != NULL) && (ilens != NULL) && (output != NULL), ret, err); 218 219 ret = sha384_init(&ctx); EG(ret, err); 220 221 while (inputs[pos] != NULL) { 222 const u8 *buf = inputs[pos]; 223 u32 buflen = ilens[pos]; 224 225 ret = sha384_update(&ctx, buf, buflen); EG(ret, err); 226 pos += 1; 227 } 228 229 ret = sha384_final(&ctx, output); 230 231 err: 232 return ret; 233 } 234 235 /* init/update/finalize on a single buffer 'input' of length 'ilen'. */ 236 int sha384(const u8 *input, u32 ilen, u8 output[SHA384_DIGEST_SIZE]) 237 { 238 sha384_context ctx; 239 int ret; 240 241 ret = sha384_init(&ctx); EG(ret, err); 242 ret = sha384_update(&ctx, input, ilen); EG(ret, err); 243 ret = sha384_final(&ctx, output); 244 245 err: 246 return ret; 247 } 248 249 #else /* WITH_HASH_SHA384 */ 250 251 /* 252 * Dummy definition to avoid the empty translation unit ISO C warning 253 */ 254 typedef int dummy; 255 #endif /* WITH_HASH_SHA384 */ 256