1*f0865ec9SKyle Evans /*
2*f0865ec9SKyle Evans * Copyright (C) 2017 - This file is part of libecc project
3*f0865ec9SKyle Evans *
4*f0865ec9SKyle Evans * Authors:
5*f0865ec9SKyle Evans * Ryad BENADJILA <ryadbenadjila@gmail.com>
6*f0865ec9SKyle Evans * Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr>
7*f0865ec9SKyle Evans * Jean-Pierre FLORI <jean-pierre.flori@ssi.gouv.fr>
8*f0865ec9SKyle Evans *
9*f0865ec9SKyle Evans * Contributors:
10*f0865ec9SKyle Evans * Nicolas VIVET <nicolas.vivet@ssi.gouv.fr>
11*f0865ec9SKyle Evans * Karim KHALFALLAH <karim.khalfallah@ssi.gouv.fr>
12*f0865ec9SKyle Evans *
13*f0865ec9SKyle Evans * This software is licensed under a dual BSD and GPL v2 license.
14*f0865ec9SKyle Evans * See LICENSE file at the root folder of the project.
15*f0865ec9SKyle Evans */
16*f0865ec9SKyle Evans #include <libecc/lib_ecc_config.h>
17*f0865ec9SKyle Evans
18*f0865ec9SKyle Evans #if defined(WITH_HASH_SHA3_224) || defined(WITH_HASH_SHA3_256) || defined(WITH_HASH_SHA3_384) || defined(WITH_HASH_SHA3_512)
19*f0865ec9SKyle Evans #include <libecc/utils/utils.h>
20*f0865ec9SKyle Evans #include <libecc/hash/sha3.h>
21*f0865ec9SKyle Evans
22*f0865ec9SKyle Evans /* Init function depending on the digest size. Return 0 on success, -1 on error. */
_sha3_init(sha3_context * ctx,u8 digest_size)23*f0865ec9SKyle Evans int _sha3_init(sha3_context *ctx, u8 digest_size)
24*f0865ec9SKyle Evans {
25*f0865ec9SKyle Evans int ret;
26*f0865ec9SKyle Evans
27*f0865ec9SKyle Evans /*
28*f0865ec9SKyle Evans * Check given inpur digest size: we only consider KECCAK versions
29*f0865ec9SKyle Evans * mapped on SHA-3 instances (224, 256, 384, 512).
30*f0865ec9SKyle Evans */
31*f0865ec9SKyle Evans MUST_HAVE(((digest_size == (224/8)) || (digest_size == (256/8)) ||
32*f0865ec9SKyle Evans (digest_size == (384/8)) || (digest_size == (512/8))), ret, err);
33*f0865ec9SKyle Evans MUST_HAVE((ctx != NULL), ret, err);
34*f0865ec9SKyle Evans
35*f0865ec9SKyle Evans /* Zeroize the internal state */
36*f0865ec9SKyle Evans ret = local_memset(ctx->sha3_state, 0, sizeof(ctx->sha3_state)); EG(ret, err);
37*f0865ec9SKyle Evans
38*f0865ec9SKyle Evans ctx->sha3_idx = 0;
39*f0865ec9SKyle Evans ctx->sha3_digest_size = digest_size;
40*f0865ec9SKyle Evans ctx->sha3_block_size = (u8)((KECCAK_SLICES * KECCAK_SLICES * sizeof(u64)) - (u8)(2 * digest_size));
41*f0865ec9SKyle Evans
42*f0865ec9SKyle Evans /* Detect endianness */
43*f0865ec9SKyle Evans ctx->sha3_endian = arch_is_big_endian() ? SHA3_BIG : SHA3_LITTLE;
44*f0865ec9SKyle Evans
45*f0865ec9SKyle Evans err:
46*f0865ec9SKyle Evans return ret;
47*f0865ec9SKyle Evans }
48*f0865ec9SKyle Evans
49*f0865ec9SKyle Evans /* Update hash function. Returns 0 on sucess, -1 on error. */
_sha3_update(sha3_context * ctx,const u8 * input,u32 ilen)50*f0865ec9SKyle Evans int _sha3_update(sha3_context *ctx, const u8 *input, u32 ilen)
51*f0865ec9SKyle Evans {
52*f0865ec9SKyle Evans u32 i;
53*f0865ec9SKyle Evans u8 *state;
54*f0865ec9SKyle Evans int ret;
55*f0865ec9SKyle Evans
56*f0865ec9SKyle Evans MUST_HAVE(((ctx != NULL) && ((input != NULL) || (ilen == 0))), ret, err);
57*f0865ec9SKyle Evans
58*f0865ec9SKyle Evans state = (u8*)(ctx->sha3_state);
59*f0865ec9SKyle Evans
60*f0865ec9SKyle Evans for (i = 0; i < ilen; i++) {
61*f0865ec9SKyle Evans u64 idx = (ctx->sha3_endian == SHA3_LITTLE) ? ctx->sha3_idx : SWAP64_Idx(ctx->sha3_idx);
62*f0865ec9SKyle Evans ctx->sha3_idx++;
63*f0865ec9SKyle Evans /* Update the state, and adapt endianness order */
64*f0865ec9SKyle Evans state[idx] ^= input[i];
65*f0865ec9SKyle Evans if(ctx->sha3_idx == ctx->sha3_block_size){
66*f0865ec9SKyle Evans KECCAKF(ctx->sha3_state);
67*f0865ec9SKyle Evans ctx->sha3_idx = 0;
68*f0865ec9SKyle Evans }
69*f0865ec9SKyle Evans }
70*f0865ec9SKyle Evans
71*f0865ec9SKyle Evans ret = 0;
72*f0865ec9SKyle Evans
73*f0865ec9SKyle Evans err:
74*f0865ec9SKyle Evans return ret;
75*f0865ec9SKyle Evans }
76*f0865ec9SKyle Evans
77*f0865ec9SKyle Evans /* Finalize hash function. Returns 0 on success, -1 on error. */
_sha3_finalize(sha3_context * ctx,u8 * output)78*f0865ec9SKyle Evans int _sha3_finalize(sha3_context *ctx, u8 *output)
79*f0865ec9SKyle Evans {
80*f0865ec9SKyle Evans unsigned int i;
81*f0865ec9SKyle Evans u8 *state;
82*f0865ec9SKyle Evans int ret;
83*f0865ec9SKyle Evans
84*f0865ec9SKyle Evans MUST_HAVE((output != NULL) && (ctx != NULL), ret, err);
85*f0865ec9SKyle Evans MUST_HAVE((ctx->sha3_digest_size <= sizeof(ctx->sha3_state)), ret, err);
86*f0865ec9SKyle Evans
87*f0865ec9SKyle Evans state = (u8*)(ctx->sha3_state);
88*f0865ec9SKyle Evans
89*f0865ec9SKyle Evans /* Proceed with the padding of the last block */
90*f0865ec9SKyle Evans /* Compute the index depending on the endianness */
91*f0865ec9SKyle Evans if (ctx->sha3_endian == SHA3_LITTLE) {
92*f0865ec9SKyle Evans /* Little endian case */
93*f0865ec9SKyle Evans state[ctx->sha3_idx] ^= 0x06;
94*f0865ec9SKyle Evans state[ctx->sha3_block_size - 1] ^= 0x80;
95*f0865ec9SKyle Evans } else {
96*f0865ec9SKyle Evans /* Big endian case */
97*f0865ec9SKyle Evans state[SWAP64_Idx(ctx->sha3_idx)] ^= 0x06;
98*f0865ec9SKyle Evans state[SWAP64_Idx(ctx->sha3_block_size - 1)] ^= 0x80;
99*f0865ec9SKyle Evans }
100*f0865ec9SKyle Evans KECCAKF(ctx->sha3_state);
101*f0865ec9SKyle Evans for(i = 0; i < ctx->sha3_digest_size; i++){
102*f0865ec9SKyle Evans output[i] = (ctx->sha3_endian == SHA3_LITTLE) ? state[i] : state[SWAP64_Idx(i)];
103*f0865ec9SKyle Evans }
104*f0865ec9SKyle Evans
105*f0865ec9SKyle Evans ret = 0;
106*f0865ec9SKyle Evans
107*f0865ec9SKyle Evans err:
108*f0865ec9SKyle Evans return ret;
109*f0865ec9SKyle Evans }
110*f0865ec9SKyle Evans
111*f0865ec9SKyle Evans #else
112*f0865ec9SKyle Evans /*
113*f0865ec9SKyle Evans * Dummy definition to avoid the empty translation unit ISO C warning
114*f0865ec9SKyle Evans */
115*f0865ec9SKyle Evans typedef int dummy;
116*f0865ec9SKyle Evans #endif
117