Dependents: HTTPClient-SSL HTTPClient-SSL HTTPClient-SSL HTTPClient-SSL
blake2b.c
00001 /* 00002 BLAKE2 reference source code package - reference C implementations 00003 00004 Written in 2012 by Samuel Neves <sneves@dei.uc.pt> 00005 00006 To the extent possible under law, the author(s) have dedicated all copyright 00007 and related and neighboring rights to this software to the public domain 00008 worldwide. This software is distributed without any warranty. 00009 00010 You should have received a copy of the CC0 Public Domain Dedication along with 00011 this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>. 00012 */ 00013 /* blake2b.c 00014 * 00015 * Copyright (C) 2006-2014 wolfSSL Inc. 00016 * 00017 * This file is part of CyaSSL. 00018 * 00019 * CyaSSL is free software; you can redistribute it and/or modify 00020 * it under the terms of the GNU General Public License as published by 00021 * the Free Software Foundation; either version 2 of the License, or 00022 * (at your option) any later version. 00023 * 00024 * CyaSSL is distributed in the hope that it will be useful, 00025 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00026 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00027 * GNU General Public License for more details. 00028 * 00029 * You should have received a copy of the GNU General Public License 00030 * along with this program; if not, write to the Free Software 00031 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 00032 */ 00033 00034 00035 #ifdef HAVE_CONFIG_H 00036 #include <config.h> 00037 #endif 00038 00039 #include <cyassl/ctaocrypt/settings.h> 00040 00041 #ifdef HAVE_BLAKE2 00042 00043 #include <cyassl/ctaocrypt/blake2.h> 00044 #include <cyassl/ctaocrypt/blake2-impl.h> 00045 00046 00047 static const word64 blake2b_IV[8] = 00048 { 00049 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 00050 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL, 00051 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL, 00052 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL 00053 }; 00054 00055 static const byte blake2b_sigma[12][16] = 00056 { 00057 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , 00058 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , 00059 { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , 00060 { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , 00061 { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , 00062 { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , 00063 { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , 00064 { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , 00065 { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , 00066 { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } , 00067 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , 00068 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } 00069 }; 00070 00071 00072 static INLINE int blake2b_set_lastnode( blake2b_state *S ) 00073 { 00074 S->f[1] = ~0ULL; 00075 return 0; 00076 } 00077 00078 /* Some helper functions, not necessarily useful */ 00079 static INLINE int blake2b_set_lastblock( blake2b_state *S ) 00080 { 00081 if( S->last_node ) blake2b_set_lastnode( S ); 00082 00083 S->f[0] = ~0ULL; 00084 return 0; 00085 } 00086 00087 static INLINE int blake2b_increment_counter( blake2b_state *S, const word64 00088 inc ) 00089 { 00090 S->t[0] += inc; 00091 S->t[1] += ( S->t[0] < inc ); 00092 return 0; 00093 } 00094 00095 static INLINE int blake2b_init0( blake2b_state *S ) 00096 { 00097 int i; 00098 XMEMSET( S, 0, sizeof( blake2b_state ) ); 00099 00100 for( i = 0; i < 8; ++i ) S->h[i] = blake2b_IV[i]; 00101 00102 return 0; 00103 } 00104 00105 /* init xors IV with input parameter block */ 00106 int blake2b_init_param( blake2b_state *S, const blake2b_param *P ) 00107 { 00108 word32 i; 00109 blake2b_init0( S ); 00110 byte *p = ( byte * )( P ); 00111 00112 /* IV XOR ParamBlock */ 00113 for( i = 0; i < 8; ++i ) 00114 S->h[i] ^= load64( p + sizeof( S->h[i] ) * i ); 00115 00116 return 0; 00117 } 00118 00119 00120 00121 int blake2b_init( blake2b_state *S, const byte outlen ) 00122 { 00123 blake2b_param P[1]; 00124 00125 if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1; 00126 00127 P->digest_length = outlen; 00128 P->key_length = 0; 00129 P->fanout = 1; 00130 P->depth = 1; 00131 store32( &P->leaf_length, 0 ); 00132 store64( &P->node_offset, 0 ); 00133 P->node_depth = 0; 00134 P->inner_length = 0; 00135 XMEMSET( P->reserved, 0, sizeof( P->reserved ) ); 00136 XMEMSET( P->salt, 0, sizeof( P->salt ) ); 00137 XMEMSET( P->personal, 0, sizeof( P->personal ) ); 00138 return blake2b_init_param( S, P ); 00139 } 00140 00141 00142 int blake2b_init_key( blake2b_state *S, const byte outlen, const void *key, 00143 const byte keylen ) 00144 { 00145 blake2b_param P[1]; 00146 00147 if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1; 00148 00149 if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1; 00150 00151 P->digest_length = outlen; 00152 P->key_length = keylen; 00153 P->fanout = 1; 00154 P->depth = 1; 00155 store32( &P->leaf_length, 0 ); 00156 store64( &P->node_offset, 0 ); 00157 P->node_depth = 0; 00158 P->inner_length = 0; 00159 XMEMSET( P->reserved, 0, sizeof( P->reserved ) ); 00160 XMEMSET( P->salt, 0, sizeof( P->salt ) ); 00161 XMEMSET( P->personal, 0, sizeof( P->personal ) ); 00162 00163 if( blake2b_init_param( S, P ) < 0 ) return -1; 00164 00165 { 00166 #ifdef CYASSL_SMALL_STACK 00167 byte* block; 00168 00169 block = (byte*)XMALLOC(BLAKE2B_BLOCKBYTES, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00170 00171 if ( block == NULL ) return -1; 00172 #else 00173 byte block[BLAKE2B_BLOCKBYTES]; 00174 #endif 00175 00176 XMEMSET( block, 0, BLAKE2B_BLOCKBYTES ); 00177 XMEMCPY( block, key, keylen ); 00178 blake2b_update( S, block, BLAKE2B_BLOCKBYTES ); 00179 secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from */ 00180 /* memory */ 00181 00182 #ifdef CYASSL_SMALL_STACK 00183 XFREE(block, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00184 #endif 00185 } 00186 return 0; 00187 } 00188 00189 static int blake2b_compress( blake2b_state *S, 00190 const byte block[BLAKE2B_BLOCKBYTES] ) 00191 { 00192 int i; 00193 00194 #ifdef CYASSL_SMALL_STACK 00195 word64* m; 00196 word64* v; 00197 00198 m = (word64*)XMALLOC(sizeof(word64) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00199 00200 if ( m == NULL ) return -1; 00201 00202 v = (word64*)XMALLOC(sizeof(word64) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00203 00204 if ( v == NULL ) 00205 { 00206 XFREE(m, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00207 return -1; 00208 } 00209 #else 00210 word64 m[16]; 00211 word64 v[16]; 00212 #endif 00213 00214 for( i = 0; i < 16; ++i ) 00215 m[i] = load64( block + i * sizeof( m[i] ) ); 00216 00217 for( i = 0; i < 8; ++i ) 00218 v[i] = S->h[i]; 00219 00220 v[ 8] = blake2b_IV[0]; 00221 v[ 9] = blake2b_IV[1]; 00222 v[10] = blake2b_IV[2]; 00223 v[11] = blake2b_IV[3]; 00224 v[12] = S->t[0] ^ blake2b_IV[4]; 00225 v[13] = S->t[1] ^ blake2b_IV[5]; 00226 v[14] = S->f[0] ^ blake2b_IV[6]; 00227 v[15] = S->f[1] ^ blake2b_IV[7]; 00228 #define G(r,i,a,b,c,d) \ 00229 do { \ 00230 a = a + b + m[blake2b_sigma[r][2*i+0]]; \ 00231 d = rotr64(d ^ a, 32); \ 00232 c = c + d; \ 00233 b = rotr64(b ^ c, 24); \ 00234 a = a + b + m[blake2b_sigma[r][2*i+1]]; \ 00235 d = rotr64(d ^ a, 16); \ 00236 c = c + d; \ 00237 b = rotr64(b ^ c, 63); \ 00238 } while(0) 00239 #define ROUND(r) \ 00240 do { \ 00241 G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \ 00242 G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \ 00243 G(r,2,v[ 2],v[ 6],v[10],v[14]); \ 00244 G(r,3,v[ 3],v[ 7],v[11],v[15]); \ 00245 G(r,4,v[ 0],v[ 5],v[10],v[15]); \ 00246 G(r,5,v[ 1],v[ 6],v[11],v[12]); \ 00247 G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \ 00248 G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \ 00249 } while(0) 00250 ROUND( 0 ); 00251 ROUND( 1 ); 00252 ROUND( 2 ); 00253 ROUND( 3 ); 00254 ROUND( 4 ); 00255 ROUND( 5 ); 00256 ROUND( 6 ); 00257 ROUND( 7 ); 00258 ROUND( 8 ); 00259 ROUND( 9 ); 00260 ROUND( 10 ); 00261 ROUND( 11 ); 00262 00263 for( i = 0; i < 8; ++i ) 00264 S->h[i] = S->h[i] ^ v[i] ^ v[i + 8]; 00265 00266 #undef G 00267 #undef ROUND 00268 00269 #ifdef CYASSL_SMALL_STACK 00270 XFREE(m, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00271 XFREE(v, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00272 #endif 00273 00274 return 0; 00275 } 00276 00277 /* inlen now in bytes */ 00278 int blake2b_update( blake2b_state *S, const byte *in, word64 inlen ) 00279 { 00280 while( inlen > 0 ) 00281 { 00282 word64 left = S->buflen; 00283 word64 fill = 2 * BLAKE2B_BLOCKBYTES - left; 00284 00285 if( inlen > fill ) 00286 { 00287 XMEMCPY( S->buf + left, in, (cyassl_word)fill ); /* Fill buffer */ 00288 S->buflen += fill; 00289 blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES ); 00290 00291 if ( blake2b_compress( S, S->buf ) < 0 ) return -1; /* Compress */ 00292 00293 XMEMCPY( S->buf, S->buf + BLAKE2B_BLOCKBYTES, BLAKE2B_BLOCKBYTES ); 00294 /* Shift buffer left */ 00295 S->buflen -= BLAKE2B_BLOCKBYTES; 00296 in += fill; 00297 inlen -= fill; 00298 } 00299 else /* inlen <= fill */ 00300 { 00301 XMEMCPY( S->buf + left, in, (cyassl_word)inlen ); 00302 S->buflen += inlen; /* Be lazy, do not compress */ 00303 in += inlen; 00304 inlen -= inlen; 00305 } 00306 } 00307 00308 return 0; 00309 } 00310 00311 /* Is this correct? */ 00312 int blake2b_final( blake2b_state *S, byte *out, byte outlen ) 00313 { 00314 byte buffer[BLAKE2B_OUTBYTES]; 00315 int i; 00316 00317 if( S->buflen > BLAKE2B_BLOCKBYTES ) 00318 { 00319 blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES ); 00320 00321 if ( blake2b_compress( S, S->buf ) < 0 ) return -1; 00322 00323 S->buflen -= BLAKE2B_BLOCKBYTES; 00324 XMEMCPY( S->buf, S->buf + BLAKE2B_BLOCKBYTES, (cyassl_word)S->buflen ); 00325 } 00326 00327 blake2b_increment_counter( S, S->buflen ); 00328 blake2b_set_lastblock( S ); 00329 XMEMSET( S->buf + S->buflen, 0, (cyassl_word)(2 * BLAKE2B_BLOCKBYTES - S->buflen) ); 00330 /* Padding */ 00331 if ( blake2b_compress( S, S->buf ) < 0 ) return -1; 00332 00333 for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */ 00334 store64( buffer + sizeof( S->h[i] ) * i, S->h[i] ); 00335 00336 XMEMCPY( out, buffer, outlen ); 00337 return 0; 00338 } 00339 00340 /* inlen, at least, should be word64. Others can be size_t. */ 00341 int blake2b( byte *out, const void *in, const void *key, const byte outlen, 00342 const word64 inlen, byte keylen ) 00343 { 00344 blake2b_state S[1]; 00345 00346 /* Verify parameters */ 00347 if ( NULL == in ) return -1; 00348 00349 if ( NULL == out ) return -1; 00350 00351 if( NULL == key ) keylen = 0; 00352 00353 if( keylen > 0 ) 00354 { 00355 if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1; 00356 } 00357 else 00358 { 00359 if( blake2b_init( S, outlen ) < 0 ) return -1; 00360 } 00361 00362 if ( blake2b_update( S, ( byte * )in, inlen ) < 0) return -1; 00363 00364 return blake2b_final( S, out, outlen ); 00365 } 00366 00367 #if defined(BLAKE2B_SELFTEST) 00368 #include <string.h> 00369 #include "blake2-kat.h" 00370 int main( int argc, char **argv ) 00371 { 00372 byte key[BLAKE2B_KEYBYTES]; 00373 byte buf[KAT_LENGTH]; 00374 00375 for( word32 i = 0; i < BLAKE2B_KEYBYTES; ++i ) 00376 key[i] = ( byte )i; 00377 00378 for( word32 i = 0; i < KAT_LENGTH; ++i ) 00379 buf[i] = ( byte )i; 00380 00381 for( word32 i = 0; i < KAT_LENGTH; ++i ) 00382 { 00383 byte hash[BLAKE2B_OUTBYTES]; 00384 if ( blake2b( hash, buf, key, BLAKE2B_OUTBYTES, i, BLAKE2B_KEYBYTES ) < 0 ) 00385 { 00386 puts( "error" ); 00387 return -1; 00388 } 00389 00390 if( 0 != memcmp( hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) ) 00391 { 00392 puts( "error" ); 00393 return -1; 00394 } 00395 } 00396 00397 puts( "ok" ); 00398 return 0; 00399 } 00400 #endif 00401 00402 00403 /* CTaoCrypt API */ 00404 00405 /* Init Blake2b digest, track size incase final doesn't want to "remember" */ 00406 int InitBlake2b(Blake2b* b2b, word32 digestSz) 00407 { 00408 b2b->digestSz = digestSz; 00409 00410 return blake2b_init(b2b->S, (byte)digestSz); 00411 } 00412 00413 00414 /* Blake2b Update */ 00415 int Blake2bUpdate(Blake2b* b2b, const byte* data, word32 sz) 00416 { 00417 return blake2b_update(b2b->S, data, sz); 00418 } 00419 00420 00421 /* Blake2b Final, if pass in zero size we use init digestSz */ 00422 int Blake2bFinal(Blake2b* b2b, byte* final, word32 requestSz) 00423 { 00424 word32 sz = requestSz ? requestSz : b2b->digestSz; 00425 00426 return blake2b_final(b2b->S, final, (byte)sz); 00427 } 00428 00429 00430 /* end CTaoCrypt API */ 00431 00432 #endif /* HAVE_BLAKE2 */ 00433
Generated on Wed Jul 13 2022 02:33:55 by
