1 /* 2 * Copyright (C) 2021 - 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 __GOSTR34_11_94_H__ 12 #define __GOSTR34_11_94_H__ 13 14 /* Include libec for useful types and macros */ 15 #include <libecc/libec.h> 16 17 /****************************************************/ 18 /* 19 * 32-bit integer manipulation macros 20 */ 21 #ifndef GET_UINT32_BE 22 #define GET_UINT32_BE(n, b, i) \ 23 do { \ 24 (n) = ( ((u32) (b)[(i) ]) << 24 ) \ 25 | ( ((u32) (b)[(i) + 1]) << 16 ) \ 26 | ( ((u32) (b)[(i) + 2]) << 8 ) \ 27 | ( ((u32) (b)[(i) + 3]) ); \ 28 } while( 0 ) 29 #endif 30 #ifndef GET_UINT32_LE 31 #define GET_UINT32_LE(n, b, i) \ 32 do { \ 33 (n) = ( ((u32) (b)[(i) + 3]) << 24 ) \ 34 | ( ((u32) (b)[(i) + 2]) << 16 ) \ 35 | ( ((u32) (b)[(i) + 1]) << 8 ) \ 36 | ( ((u32) (b)[(i) ]) ); \ 37 } while( 0 ) 38 #endif 39 40 41 #ifndef PUT_UINT32_BE 42 #define PUT_UINT32_BE(n, b, i) \ 43 do { \ 44 (b)[(i) ] = (u8) ( (n) >> 24 ); \ 45 (b)[(i) + 1] = (u8) ( (n) >> 16 ); \ 46 (b)[(i) + 2] = (u8) ( (n) >> 8 ); \ 47 (b)[(i) + 3] = (u8) ( (n) ); \ 48 } while( 0 ) 49 #endif 50 51 #ifndef PUT_UINT32_LE 52 #define PUT_UINT32_LE(n, b, i) \ 53 do { \ 54 (b)[(i) + 3] = (u8) ( (n) >> 24 ); \ 55 (b)[(i) + 2] = (u8) ( (n) >> 16 ); \ 56 (b)[(i) + 1] = (u8) ( (n) >> 8 ); \ 57 (b)[(i) ] = (u8) ( (n) ); \ 58 } while( 0 ) 59 #endif 60 61 /* 62 * 64-bit integer manipulation macros 63 */ 64 #ifndef GET_UINT64_BE 65 #define GET_UINT64_BE(n,b,i) \ 66 do { \ 67 (n) = ( ((u64) (b)[(i) ]) << 56 ) \ 68 | ( ((u64) (b)[(i) + 1]) << 48 ) \ 69 | ( ((u64) (b)[(i) + 2]) << 40 ) \ 70 | ( ((u64) (b)[(i) + 3]) << 32 ) \ 71 | ( ((u64) (b)[(i) + 4]) << 24 ) \ 72 | ( ((u64) (b)[(i) + 5]) << 16 ) \ 73 | ( ((u64) (b)[(i) + 6]) << 8 ) \ 74 | ( ((u64) (b)[(i) + 7]) ); \ 75 } while( 0 ) 76 #endif /* GET_UINT64_BE */ 77 78 #ifndef GET_UINT64_LE 79 #define GET_UINT64_LE(n,b,i) \ 80 do { \ 81 (n) = ( ((u64) (b)[(i) + 7]) << 56 ) \ 82 | ( ((u64) (b)[(i) + 6]) << 48 ) \ 83 | ( ((u64) (b)[(i) + 5]) << 40 ) \ 84 | ( ((u64) (b)[(i) + 4]) << 32 ) \ 85 | ( ((u64) (b)[(i) + 3]) << 24 ) \ 86 | ( ((u64) (b)[(i) + 2]) << 16 ) \ 87 | ( ((u64) (b)[(i) + 1]) << 8 ) \ 88 | ( ((u64) (b)[(i) ]) ); \ 89 } while( 0 ) 90 #endif /* GET_UINT64_LE */ 91 92 #ifndef PUT_UINT64_BE 93 #define PUT_UINT64_BE(n,b,i) \ 94 do { \ 95 (b)[(i) ] = (u8) ( (n) >> 56 ); \ 96 (b)[(i) + 1] = (u8) ( (n) >> 48 ); \ 97 (b)[(i) + 2] = (u8) ( (n) >> 40 ); \ 98 (b)[(i) + 3] = (u8) ( (n) >> 32 ); \ 99 (b)[(i) + 4] = (u8) ( (n) >> 24 ); \ 100 (b)[(i) + 5] = (u8) ( (n) >> 16 ); \ 101 (b)[(i) + 6] = (u8) ( (n) >> 8 ); \ 102 (b)[(i) + 7] = (u8) ( (n) ); \ 103 } while( 0 ) 104 #endif /* PUT_UINT64_BE */ 105 106 #ifndef PUT_UINT64_LE 107 #define PUT_UINT64_LE(n,b,i) \ 108 do { \ 109 (b)[(i) + 7] = (u8) ( (n) >> 56 ); \ 110 (b)[(i) + 6] = (u8) ( (n) >> 48 ); \ 111 (b)[(i) + 5] = (u8) ( (n) >> 40 ); \ 112 (b)[(i) + 4] = (u8) ( (n) >> 32 ); \ 113 (b)[(i) + 3] = (u8) ( (n) >> 24 ); \ 114 (b)[(i) + 2] = (u8) ( (n) >> 16 ); \ 115 (b)[(i) + 1] = (u8) ( (n) >> 8 ); \ 116 (b)[(i) ] = (u8) ( (n) ); \ 117 } while( 0 ) 118 #endif /* PUT_UINT64_LE */ 119 120 #define GOSTR34_11_94_STATE_SIZE 4 121 #define GOSTR34_11_94_BLOCK_SIZE 32 122 #define GOSTR34_11_94_DIGEST_SIZE 32 123 #define GOSTR34_11_94_DIGEST_SIZE_BITS 256 124 125 #define GOSTR34_11_94_HASH_MAGIC ((word_t)(0x1262734139734143ULL)) 126 #define GOSTR34_11_94_HASH_CHECK_INITIALIZED(A, ret, err) \ 127 MUST_HAVE((((void *)(A)) != NULL) && ((A)->magic == GOSTR34_11_94_HASH_MAGIC), ret, err) 128 129 #define ROTL_GOSTR34_11_94(x, n) ((((u32)(x)) << (n)) | (((u32)(x)) >> (32-(n)))) 130 131 /* All the inner operations */ 132 133 typedef enum { 134 GOST34_11_94_NORM = 0, 135 GOST34_11_94_RFC4357 = 1, 136 } gostr34_11_94_type; 137 138 typedef struct { 139 /* "Type" of GOST, changing the SBOX to use */ 140 gostr34_11_94_type gostr34_11_94_t; 141 /* Number of bytes processed */ 142 u64 gostr34_11_94_total; 143 /* Internal state: 4 64-bit values */ 144 u64 gostr34_11_94_state[GOSTR34_11_94_STATE_SIZE]; 145 /* Internal buffer to handle updates in a block */ 146 u8 gostr34_11_94_buffer[GOSTR34_11_94_BLOCK_SIZE]; 147 /* The sum */ 148 u64 gostr34_11_94_sum[GOSTR34_11_94_STATE_SIZE]; 149 /* Initialization magic value */ 150 word_t magic; 151 } gostr34_11_94_context; 152 153 154 /* Init hash function. Returns 0 on success, -1 on error. */ 155 ATTRIBUTE_WARN_UNUSED_RET int gostr34_11_94_init(gostr34_11_94_context *ctx); 156 157 /* Function to modify the initial IV as it is not imposed by the RFCs */ 158 ATTRIBUTE_WARN_UNUSED_RET int gostr34_11_94_set_iv(gostr34_11_94_context *ctx, const u64 iv[GOSTR34_11_94_STATE_SIZE]); 159 160 /* Function to modify the GOST type (that will dictate the underlying SBOX to use for block encryption) */ 161 ATTRIBUTE_WARN_UNUSED_RET int gostr34_11_94_set_type(gostr34_11_94_context *ctx, gostr34_11_94_type type); 162 163 ATTRIBUTE_WARN_UNUSED_RET int gostr34_11_94_update(gostr34_11_94_context *ctx, const u8 *input, u32 ilen); 164 165 /* Finalize. Returns 0 on success, -1 on error.*/ 166 ATTRIBUTE_WARN_UNUSED_RET int gostr34_11_94_final(gostr34_11_94_context *ctx, u8 output[GOSTR34_11_94_DIGEST_SIZE]); 167 168 /* 169 * Scattered version performing init/update/finalize on a vector of buffers 170 * 'inputs' with the length of each buffer passed via 'ilens'. The function 171 * loops on pointers in 'inputs' until it finds a NULL pointer. The function 172 * returns 0 on success, -1 on error. 173 */ 174 ATTRIBUTE_WARN_UNUSED_RET int gostr34_11_94_scattered(const u8 **inputs, const u32 *ilens, 175 u8 output[GOSTR34_11_94_DIGEST_SIZE], gostr34_11_94_type type); 176 177 ATTRIBUTE_WARN_UNUSED_RET int gostr34_11_94_scattered_norm(const u8 **inputs, const u32 *ilens, 178 u8 output[GOSTR34_11_94_DIGEST_SIZE]); 179 180 ATTRIBUTE_WARN_UNUSED_RET int gostr34_11_94_scattered_rfc4357(const u8 **inputs, const u32 *ilens, 181 u8 output[GOSTR34_11_94_DIGEST_SIZE]); 182 183 /* 184 * Single call version performing init/update/final on given input. 185 * Returns 0 on success, -1 on error. 186 */ 187 ATTRIBUTE_WARN_UNUSED_RET int gostr34_11_94(const u8 *input, u32 ilen, u8 output[GOSTR34_11_94_DIGEST_SIZE], gostr34_11_94_type type); 188 189 ATTRIBUTE_WARN_UNUSED_RET int gostr34_11_94_norm(const u8 *input, u32 ilen, u8 output[GOSTR34_11_94_DIGEST_SIZE]); 190 191 ATTRIBUTE_WARN_UNUSED_RET int gostr34_11_94_rfc4357(const u8 *input, u32 ilen, u8 output[GOSTR34_11_94_DIGEST_SIZE]); 192 193 #endif /* __GOSTR34_11_94_H__ */ 194