/ external / libecc / src / hash / sha3.c
sha3.c
  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  
 18  #if defined(WITH_HASH_SHA3_224) || defined(WITH_HASH_SHA3_256) || defined(WITH_HASH_SHA3_384) || defined(WITH_HASH_SHA3_512)
 19  #include <libecc/utils/utils.h>
 20  #include <libecc/hash/sha3.h>
 21  
 22  /* Init function depending on the digest size. Return 0 on success, -1 on error. */
 23  int _sha3_init(sha3_context *ctx, u8 digest_size)
 24  {
 25  	int ret;
 26  
 27  	/*
 28  	 * Check given inpur digest size: we only consider KECCAK versions
 29  	 * mapped on SHA-3 instances (224, 256, 384, 512).
 30  	 */
 31  	MUST_HAVE(((digest_size == (224/8)) || (digest_size == (256/8)) ||
 32  		   (digest_size == (384/8)) || (digest_size == (512/8))), ret, err);
 33  	MUST_HAVE((ctx != NULL), ret, err);
 34  
 35  	/* Zeroize the internal state */
 36  	ret = local_memset(ctx->sha3_state, 0, sizeof(ctx->sha3_state)); EG(ret, err);
 37  
 38  	ctx->sha3_idx = 0;
 39  	ctx->sha3_digest_size = digest_size;
 40  	ctx->sha3_block_size = (u8)((KECCAK_SLICES * KECCAK_SLICES * sizeof(u64)) - (u8)(2 * digest_size));
 41  
 42  	/* Detect endianness */
 43  	ctx->sha3_endian = arch_is_big_endian() ? SHA3_BIG : SHA3_LITTLE;
 44  
 45  err:
 46  	return ret;
 47  }
 48  
 49  /* Update hash function. Returns 0 on sucess, -1 on error. */
 50  int _sha3_update(sha3_context *ctx, const u8 *input, u32 ilen)
 51  {
 52  	u32 i;
 53  	u8 *state;
 54  	int ret;
 55  
 56  	MUST_HAVE(((ctx != NULL) && ((input != NULL) || (ilen == 0))), ret, err);
 57  
 58  	state = (u8*)(ctx->sha3_state);
 59  
 60  	for (i = 0; i < ilen; i++) {
 61  		u64 idx = (ctx->sha3_endian == SHA3_LITTLE) ? ctx->sha3_idx : SWAP64_Idx(ctx->sha3_idx);
 62  		ctx->sha3_idx++;
 63  		/* Update the state, and adapt endianness order */
 64  		state[idx] ^= input[i];
 65  		if(ctx->sha3_idx == ctx->sha3_block_size){
 66  			KECCAKF(ctx->sha3_state);
 67  			ctx->sha3_idx = 0;
 68  		}
 69  	}
 70  
 71  	ret = 0;
 72  
 73  err:
 74  	return ret;
 75  }
 76  
 77  /* Finalize hash function. Returns 0 on success, -1 on error. */
 78  int _sha3_finalize(sha3_context *ctx, u8 *output)
 79  {
 80  	unsigned int i;
 81  	u8 *state;
 82  	int ret;
 83  
 84  	MUST_HAVE((output != NULL) && (ctx != NULL), ret, err);
 85  	MUST_HAVE((ctx->sha3_digest_size <= sizeof(ctx->sha3_state)), ret, err);
 86  
 87  	state = (u8*)(ctx->sha3_state);
 88  
 89  	/* Proceed with the padding of the last block */
 90  	/* Compute the index depending on the endianness */
 91  	if (ctx->sha3_endian == SHA3_LITTLE) {
 92  		/* Little endian case */
 93  		state[ctx->sha3_idx] ^= 0x06;
 94  		state[ctx->sha3_block_size - 1] ^= 0x80;
 95  	} else {
 96  		/* Big endian case */
 97  		state[SWAP64_Idx(ctx->sha3_idx)] ^= 0x06;
 98  		state[SWAP64_Idx(ctx->sha3_block_size - 1)] ^= 0x80;
 99  	}
100  	KECCAKF(ctx->sha3_state);
101  	for(i = 0; i < ctx->sha3_digest_size; i++){
102  		output[i] = (ctx->sha3_endian == SHA3_LITTLE) ? state[i] : state[SWAP64_Idx(i)];
103  	}
104  
105  	ret = 0;
106  
107  err:
108  	return ret;
109  }
110  
111  #else
112  /*
113   * Dummy definition to avoid the empty translation unit ISO C warning
114   */
115  typedef int dummy;
116  #endif