/ external / libecc / include / libecc / hash / bash.h
bash.h
  1  /*
  2   *  Copyright (C) 2022 - 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   *
  8   *  This software is licensed under a dual BSD and GPL v2 license.
  9   *  See LICENSE file at the root folder of the project.
 10   */
 11  #ifndef __BASH_H__
 12  #define __BASH_H__
 13  
 14  #include <libecc/words/words.h>
 15  
 16  /*
 17   * This is an implementation of the BASH hash functions family (for sizes 224, 256, 384 and 512)
 18   * following the standard STB 34.101.77-2020 (http://apmi.bsu.by/assets/files/std/bash-spec24.pdf).
 19   * An english version of the specifications exist here: https://eprint.iacr.org/2016/587.pdf
 20   */
 21  
 22  #define _BASH_ROTHI_(x, y) (((x) << (y)) | ((x) >> ((sizeof(u64) * 8) - (y))))
 23  
 24  /* We handle the case where one of the shifts is more than 64-bit: in this
 25   * case, behaviour is undefined as per ANSI C definition. In this case, we
 26   * return the untouched input.
 27   */
 28  #define BASH_ROTHI(x, y) ((((y) < (sizeof(u64) * 8)) && ((y) > 0)) ? (_BASH_ROTHI_(x, y)) : (x))
 29  
 30  /*
 31   * Round transformation of the state. Notations are the
 32   * same as the ones used in:
 33   * https://eprint.iacr.org/2016/587.pdf
 34   */
 35  #define BASH_SLICES_X   3
 36  #define BASH_SLICES_Y   8
 37  #define BASH_ROT_ROUNDS 8
 38  #define BASH_ROT_IDX    4
 39  #define BASH_ROUNDS     24
 40  
 41  #define BASH_L3_S3(W0, W1, W2, m1, n1, m2, n2) do {				\
 42  	u64 T0, T1, T2;								\
 43  	T0 = BASH_ROTHI(W0, m1);						\
 44  	W0 = (W0 ^ W1 ^ W2);							\
 45  	T1 = (W1 ^ BASH_ROTHI(W0, n1));						\
 46  	W1 = (T0 ^ T1);								\
 47  	W2 = (W2 ^ BASH_ROTHI(W2, m2) ^ BASH_ROTHI(T1, n2));			\
 48  	T0 = (~(W2));								\
 49  	T1 = (W0 | W2);								\
 50  	T2 = (W0 & W1);								\
 51  	T0 = (T0 | W1);								\
 52  	W1 = (W1 ^ T1);								\
 53  	W2 = (W2 ^ T2);								\
 54  	W0 = (W0 ^ T0);								\
 55  } while(0)
 56  
 57  #define BASH_PERMUTE(S) do {							\
 58  	u64 S_[BASH_SLICES_X * BASH_SLICES_Y];					\
 59  	IGNORE_RET_VAL(local_memcpy(S_, S, sizeof(S_)));			\
 60  	S[ 0] = S_[15]; S[ 1] = S_[10]; S[ 2] = S_[ 9]; S[ 3] = S_[12];		\
 61  	S[ 4] = S_[11]; S[ 5] = S_[14]; S[ 6] = S_[13]; S[ 7] = S_[ 8];		\
 62  	S[ 8] = S_[17]; S[ 9] = S_[16]; S[10] = S_[19]; S[11] = S_[18];		\
 63  	S[12] = S_[21]; S[13] = S_[20]; S[14] = S_[23]; S[15] = S_[22];		\
 64  	S[16] = S_[ 6]; S[17] = S_[ 3]; S[18] = S_[ 0]; S[19] = S_[ 5];		\
 65  	S[20] = S_[ 2]; S[21] = S_[ 7]; S[22] = S_[ 4]; S[23] = S_[ 1];		\
 66  } while(0)
 67  
 68  static const u64 bash_rc[BASH_ROUNDS] =
 69  {
 70  	0x3bf5080ac8ba94b1ULL,
 71  	0xc1d1659c1bbd92f6ULL,
 72  	0x60e8b2ce0ddec97bULL,
 73  	0xec5fb8fe790fbc13ULL,
 74  	0xaa043de6436706a7ULL,
 75  	0x8929ff6a5e535bfdULL,
 76  	0x98bf1e2c50c97550ULL,
 77  	0x4c5f8f162864baa8ULL,
 78  	0x262fc78b14325d54ULL,
 79  	0x1317e3c58a192eaaULL,
 80  	0x098bf1e2c50c9755ULL,
 81  	0xd8ee19681d669304ULL,
 82  	0x6c770cb40eb34982ULL,
 83  	0x363b865a0759a4c1ULL,
 84  	0xc73622b47c4c0aceULL,
 85  	0x639b115a3e260567ULL,
 86  	0xede6693460f3da1dULL,
 87  	0xaad8d5034f9935a0ULL,
 88  	0x556c6a81a7cc9ad0ULL,
 89  	0x2ab63540d3e64d68ULL,
 90  	0x155b1aa069f326b4ULL,
 91  	0x0aad8d5034f9935aULL,
 92  	0x0556c6a81a7cc9adULL,
 93  	0xde8082cd72debc78ULL,
 94  };
 95  
 96  static const u8 bash_rot[BASH_ROT_ROUNDS][BASH_ROT_IDX] =
 97  {
 98  	{  8, 53, 14,  1 },
 99  	{ 56, 51, 34,  7 },
100  	{  8, 37, 46, 49 },
101  	{ 56,  3,  2, 23 },
102  	{  8, 21, 14, 33 },
103  	{ 56, 19, 34, 39 },
104  	{  8,  5, 46, 17 },
105  	{ 56, 35,  2, 55 },
106  };
107  
108  /* Macro to handle endianness conversion */
109  #define SWAP64(A) do {								\
110  	A = ((A) << 56 | ((A) & 0xff00) << 40 | ((A) & 0xff0000) << 24 |	\
111  	    ((A) & 0xff000000) << 8 | ((A) >> 8 & 0xff000000) |			\
112  	    ((A) >> 24 & 0xff0000) | ((A) >> 40 & 0xff00) | (A) >> 56);		\
113  } while(0)
114  
115  /* The main Bash-f core as descibed in the specification. */
116  #define BASHF(S, end) do {									\
117  	unsigned int round, i;									\
118  	/* Swap endianness if necessary */							\
119  	if(end == BASH_BIG){									\
120  		for(i = 0; i < (BASH_SLICES_X * BASH_SLICES_Y); i++){				\
121  			SWAP64(S[i]);								\
122  		}										\
123  	}											\
124  	for(round = 0; round < BASH_ROUNDS; round++){						\
125  		unsigned int v;									\
126  		for(v = 0; v < 8; v++){								\
127  			BASH_L3_S3(S[v], S[v+8], S[v+16], bash_rot[v][0], bash_rot[v][1],	\
128  							bash_rot[v][2], bash_rot[v][3]);	\
129  		}										\
130  		BASH_PERMUTE(S);								\
131  		S[23] ^= bash_rc[round];							\
132  	}											\
133  	/* Swap back endianness if necessary */							\
134  	if(end == BASH_BIG){									\
135  		for(i = 0; i < (BASH_SLICES_X * BASH_SLICES_Y); i++){				\
136  			SWAP64(S[i]);								\
137  		}										\
138  	}											\
139  } while(0)
140  
141  typedef enum {
142  	BASH_LITTLE = 0,
143  	BASH_BIG = 1,
144  } bash_endianness;
145  
146  typedef struct bash_context_ {
147  	u8 bash_digest_size;
148  	u8 bash_block_size;
149  	bash_endianness bash_endian;
150  	/* Local counter */
151  	u64 bash_total;
152  	/* Bash state */
153  	u64 bash_state[BASH_SLICES_X * BASH_SLICES_Y];
154  	/* Initialization magic value */
155  	u64 magic;
156  } bash_context;
157  
158  ATTRIBUTE_WARN_UNUSED_RET int _bash_init(bash_context *ctx, uint8_t digest_size);
159  ATTRIBUTE_WARN_UNUSED_RET int _bash_update(bash_context *ctx, const uint8_t *buf, uint32_t buflen);
160  ATTRIBUTE_WARN_UNUSED_RET int _bash_finalize(bash_context *ctx, uint8_t *output);
161  
162  #endif /* __BASH_H__ */