1/* 2 BLAKE2 reference source code package - reference C implementations 3 4 Written in 2012 by Samuel Neves <sneves@dei.uc.pt> 5 6 To the extent possible under law, the author(s) have dedicated all copyright 7 and related and neighboring rights to this software to the public domain 8 worldwide. This software is distributed without any warranty. 9 10 You should have received a copy of the CC0 Public Domain Dedication along with 11 this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>. 12*/ 13 14#include <stdint.h> 15#include <string.h> 16#include <stdio.h> 17 18#include "blake2.h" 19#include "blake2-impl.h" 20 21static const uint32_t blake2s_IV[8] = 22{ 23 0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL, 24 0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL 25}; 26 27static const uint8_t blake2s_sigma[10][16] = 28{ 29 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , 30 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , 31 { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , 32 { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , 33 { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , 34 { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , 35 { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , 36 { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , 37 { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , 38 { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } , 39}; 40 41static inline int blake2s_set_lastnode( blake2s_state *S ) 42{ 43 S->f[1] = ~0U; 44 return 0; 45} 46 47static inline int blake2s_clear_lastnode( blake2s_state *S ) 48{ 49 S->f[1] = 0U; 50 return 0; 51} 52 53/* Some helper functions, not necessarily useful */ 54static inline int blake2s_set_lastblock( blake2s_state *S ) 55{ 56 if( S->last_node ) blake2s_set_lastnode( S ); 57 58 S->f[0] = ~0U; 59 return 0; 60} 61 62static inline int blake2s_clear_lastblock( blake2s_state *S ) 63{ 64 if( S->last_node ) blake2s_clear_lastnode( S ); 65 66 S->f[0] = 0U; 67 return 0; 68} 69 70static inline int blake2s_increment_counter( blake2s_state *S, const uint32_t inc ) 71{ 72 S->t[0] += inc; 73 S->t[1] += ( S->t[0] < inc ); 74 return 0; 75} 76 77// Parameter-related functions 78static inline int blake2s_param_set_digest_length( blake2s_param *P, const uint8_t digest_length ) 79{ 80 P->digest_length = digest_length; 81 return 0; 82} 83 84static inline int blake2s_param_set_fanout( blake2s_param *P, const uint8_t fanout ) 85{ 86 P->fanout = fanout; 87 return 0; 88} 89 90static inline int blake2s_param_set_max_depth( blake2s_param *P, const uint8_t depth ) 91{ 92 P->depth = depth; 93 return 0; 94} 95 96static inline int blake2s_param_set_leaf_length( blake2s_param *P, const uint32_t leaf_length ) 97{ 98 store32( &P->leaf_length, leaf_length ); 99 return 0; 100} 101 102static inline int blake2s_param_set_node_offset( blake2s_param *P, const uint64_t node_offset ) 103{ 104 store48( P->node_offset, node_offset ); 105 return 0; 106} 107 108static inline int blake2s_param_set_node_depth( blake2s_param *P, const uint8_t node_depth ) 109{ 110 P->node_depth = node_depth; 111 return 0; 112} 113 114static inline int blake2s_param_set_inner_length( blake2s_param *P, const uint8_t inner_length ) 115{ 116 P->inner_length = inner_length; 117 return 0; 118} 119 120static inline int blake2s_param_set_salt( blake2s_param *P, const uint8_t salt[BLAKE2S_SALTBYTES] ) 121{ 122 memcpy( P->salt, salt, BLAKE2S_SALTBYTES ); 123 return 0; 124} 125 126static inline int blake2s_param_set_personal( blake2s_param *P, const uint8_t personal[BLAKE2S_PERSONALBYTES] ) 127{ 128 memcpy( P->personal, personal, BLAKE2S_PERSONALBYTES ); 129 return 0; 130} 131 132static inline int blake2s_init0( blake2s_state *S ) 133{ 134 memset( S, 0, sizeof( blake2s_state ) ); 135 136 for( int i = 0; i < 8; ++i ) S->h[i] = blake2s_IV[i]; 137 138 return 0; 139} 140 141#if defined(__cplusplus) 142extern "C" { 143#endif 144 int blake2s_init( blake2s_state *S, size_t outlen ); 145 int blake2s_init_param( blake2s_state *S, const blake2s_param *P ); 146 int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen ); 147 int blake2s_update( blake2s_state *S, const uint8_t *in, size_t inlen ); 148 int blake2s_final( blake2s_state *S, uint8_t *out, size_t outlen ); 149 int blake2s( uint8_t *out, const void *in, const void *key, size_t outlen, size_t inlen, size_t keylen ); 150#if defined(__cplusplus) 151} 152#endif 153 154/* init2 xors IV with input parameter block */ 155int blake2s_init_param( blake2s_state *S, const blake2s_param *P ) 156{ 157 blake2s_init0( S ); 158 uint32_t *p = ( uint32_t * )( P ); 159 160 /* IV XOR ParamBlock */ 161 for( size_t i = 0; i < 8; ++i ) 162 S->h[i] ^= load32( &p[i] ); 163 164 S->outlen = P->digest_length; 165 return 0; 166} 167 168 169// Sequential blake2s initialization 170int blake2s_init( blake2s_state *S, size_t outlen ) 171{ 172 blake2s_param P[1]; 173 174 /* Move interval verification here? */ 175 if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1; 176 177 P->digest_length = ( uint8_t) outlen; 178 P->key_length = 0; 179 P->fanout = 1; 180 P->depth = 1; 181 store32( &P->leaf_length, 0 ); 182 store48( &P->node_offset, 0 ); 183 P->node_depth = 0; 184 P->inner_length = 0; 185 // memset(P->reserved, 0, sizeof(P->reserved) ); 186 memset( P->salt, 0, sizeof( P->salt ) ); 187 memset( P->personal, 0, sizeof( P->personal ) ); 188 return blake2s_init_param( S, P ); 189} 190 191int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen ) 192{ 193 blake2s_param P[1]; 194 195 if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1; 196 197 if ( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return -1; 198 199 P->digest_length = ( uint8_t ) outlen; 200 P->key_length = ( uint8_t ) keylen; 201 P->fanout = 1; 202 P->depth = 1; 203 store32( &P->leaf_length, 0 ); 204 store48( &P->node_offset, 0 ); 205 P->node_depth = 0; 206 P->inner_length = 0; 207 // memset(P->reserved, 0, sizeof(P->reserved) ); 208 memset( P->salt, 0, sizeof( P->salt ) ); 209 memset( P->personal, 0, sizeof( P->personal ) ); 210 211 if( blake2s_init_param( S, P ) < 0 ) return -1; 212 213 { 214 uint8_t block[BLAKE2S_BLOCKBYTES]; 215 memset( block, 0, BLAKE2S_BLOCKBYTES ); 216 memcpy( block, key, keylen ); 217 blake2s_update( S, block, BLAKE2S_BLOCKBYTES ); 218 secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */ 219 } 220 return 0; 221} 222 223static int blake2s_compress( blake2s_state *S, const uint8_t block[BLAKE2S_BLOCKBYTES] ) 224{ 225 uint32_t m[16]; 226 uint32_t v[16]; 227 228 for( size_t i = 0; i < 16; ++i ) 229 m[i] = load32( block + i * sizeof( m[i] ) ); 230 231 for( size_t i = 0; i < 8; ++i ) 232 v[i] = S->h[i]; 233 234 v[ 8] = blake2s_IV[0]; 235 v[ 9] = blake2s_IV[1]; 236 v[10] = blake2s_IV[2]; 237 v[11] = blake2s_IV[3]; 238 v[12] = S->t[0] ^ blake2s_IV[4]; 239 v[13] = S->t[1] ^ blake2s_IV[5]; 240 v[14] = S->f[0] ^ blake2s_IV[6]; 241 v[15] = S->f[1] ^ blake2s_IV[7]; 242#define G(r,i,a,b,c,d) \ 243 do { \ 244 a = a + b + m[blake2s_sigma[r][2*i+0]]; \ 245 d = rotr32(d ^ a, 16); \ 246 c = c + d; \ 247 b = rotr32(b ^ c, 12); \ 248 a = a + b + m[blake2s_sigma[r][2*i+1]]; \ 249 d = rotr32(d ^ a, 8); \ 250 c = c + d; \ 251 b = rotr32(b ^ c, 7); \ 252 } while(0) 253#define ROUND(r) \ 254 do { \ 255 G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \ 256 G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \ 257 G(r,2,v[ 2],v[ 6],v[10],v[14]); \ 258 G(r,3,v[ 3],v[ 7],v[11],v[15]); \ 259 G(r,4,v[ 0],v[ 5],v[10],v[15]); \ 260 G(r,5,v[ 1],v[ 6],v[11],v[12]); \ 261 G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \ 262 G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \ 263 } while(0) 264 ROUND( 0 ); 265 ROUND( 1 ); 266 ROUND( 2 ); 267 ROUND( 3 ); 268 ROUND( 4 ); 269 ROUND( 5 ); 270 ROUND( 6 ); 271 ROUND( 7 ); 272 ROUND( 8 ); 273 ROUND( 9 ); 274 275 for( size_t i = 0; i < 8; ++i ) 276 S->h[i] = S->h[i] ^ v[i] ^ v[i + 8]; 277 278#undef G 279#undef ROUND 280 return 0; 281} 282 283 284int blake2s_update( blake2s_state *S, const uint8_t *in, size_t inlen ) 285{ 286 while( inlen > 0 ) 287 { 288 uint32_t left = S->buflen; 289 uint32_t fill = 2 * BLAKE2S_BLOCKBYTES - left; 290 291 if( inlen > fill ) 292 { 293 memcpy( S->buf + left, in, fill ); // Fill buffer 294 S->buflen += fill; 295 blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES ); 296 blake2s_compress( S, S->buf ); // Compress 297 memcpy( S->buf, S->buf + BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES ); // Shift buffer left 298 S->buflen -= BLAKE2S_BLOCKBYTES; 299 in += fill; 300 inlen -= fill; 301 } 302 else // inlen <= fill 303 { 304 memcpy( S->buf + left, in, inlen ); 305 S->buflen += ( uint32_t ) inlen; // Be lazy, do not compress 306 in += inlen; 307 inlen -= inlen; 308 } 309 } 310 311 return 0; 312} 313 314int blake2s_final( blake2s_state *S, uint8_t *out, size_t outlen ) 315{ 316 uint8_t buffer[BLAKE2S_OUTBYTES]; 317 size_t i; 318 319 if(S->outlen != outlen) return -1; 320 321 if( S->buflen > BLAKE2S_BLOCKBYTES ) 322 { 323 blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES ); 324 blake2s_compress( S, S->buf ); 325 S->buflen -= BLAKE2S_BLOCKBYTES; 326 memmove( S->buf, S->buf + BLAKE2S_BLOCKBYTES, S->buflen ); 327 } 328 329 blake2s_increment_counter( S, ( uint32_t )S->buflen ); 330 blake2s_set_lastblock( S ); 331 memset( S->buf + S->buflen, 0, 2 * BLAKE2S_BLOCKBYTES - S->buflen ); /* Padding */ 332 blake2s_compress( S, S->buf ); 333 334 for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */ 335 store32( buffer + sizeof( S->h[i] ) * i, S->h[i] ); 336 337 memcpy( out, buffer, outlen ); 338 return 0; 339} 340 341int blake2s( uint8_t *out, const void *in, const void *key, size_t outlen, size_t inlen, size_t keylen ) 342{ 343 blake2s_state S[1]; 344 345 /* Verify parameters */ 346 if ( NULL == in && inlen > 0 ) return -1; 347 348 if ( NULL == out ) return -1; 349 350 if ( NULL == key && keylen > 0 ) return -1; 351 352 if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1; 353 354 if( keylen > BLAKE2S_KEYBYTES ) return -1; 355 356 if( keylen > 0 ) 357 { 358 if( blake2s_init_key( S, outlen, key, keylen ) < 0 ) return -1; 359 } 360 else 361 { 362 if( blake2s_init( S, outlen ) < 0 ) return -1; 363 } 364 365 if( blake2s_update( S, ( uint8_t * )in, inlen ) < 0) return -1; 366 return blake2s_final( S, out, outlen ); 367} 368 369