Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TLS_cyassl TLS_cyassl
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-2013 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 static INLINE int blake2b_clear_lastnode( blake2b_state *S ) 00079 { 00080 S->f[1] = 0ULL; 00081 return 0; 00082 } 00083 00084 /* Some helper functions, not necessarily useful */ 00085 static INLINE int blake2b_set_lastblock( blake2b_state *S ) 00086 { 00087 if( S->last_node ) blake2b_set_lastnode( S ); 00088 00089 S->f[0] = ~0ULL; 00090 return 0; 00091 } 00092 00093 static INLINE int blake2b_clear_lastblock( blake2b_state *S ) 00094 { 00095 if( S->last_node ) blake2b_clear_lastnode( S ); 00096 00097 S->f[0] = 0ULL; 00098 return 0; 00099 } 00100 00101 static INLINE int blake2b_increment_counter( blake2b_state *S, const word64 00102 inc ) 00103 { 00104 S->t[0] += inc; 00105 S->t[1] += ( S->t[0] < inc ); 00106 return 0; 00107 } 00108 00109 00110 00111 /* Parameter-related functions */ 00112 static INLINE int blake2b_param_set_digest_length( blake2b_param *P, 00113 const byte digest_length ) 00114 { 00115 P->digest_length = digest_length; 00116 return 0; 00117 } 00118 00119 static INLINE int blake2b_param_set_fanout( blake2b_param *P, const byte fanout) 00120 { 00121 P->fanout = fanout; 00122 return 0; 00123 } 00124 00125 static INLINE int blake2b_param_set_max_depth( blake2b_param *P, 00126 const byte depth ) 00127 { 00128 P->depth = depth; 00129 return 0; 00130 } 00131 00132 static INLINE int blake2b_param_set_leaf_length( blake2b_param *P, 00133 const word32 leaf_length ) 00134 { 00135 store32( &P->leaf_length, leaf_length ); 00136 return 0; 00137 } 00138 00139 static INLINE int blake2b_param_set_node_offset( blake2b_param *P, 00140 const word64 node_offset ) 00141 { 00142 store64( &P->node_offset, node_offset ); 00143 return 0; 00144 } 00145 00146 static INLINE int blake2b_param_set_node_depth( blake2b_param *P, 00147 const byte node_depth ) 00148 { 00149 P->node_depth = node_depth; 00150 return 0; 00151 } 00152 00153 static INLINE int blake2b_param_set_inner_length( blake2b_param *P, 00154 const byte inner_length ) 00155 { 00156 P->inner_length = inner_length; 00157 return 0; 00158 } 00159 00160 static INLINE int blake2b_param_set_salt( blake2b_param *P, 00161 const byte salt[BLAKE2B_SALTBYTES] ) 00162 { 00163 XMEMCPY( P->salt, salt, BLAKE2B_SALTBYTES ); 00164 return 0; 00165 } 00166 00167 static INLINE int blake2b_param_set_personal( blake2b_param *P, 00168 const byte personal[BLAKE2B_PERSONALBYTES] ) 00169 { 00170 XMEMCPY( P->personal, personal, BLAKE2B_PERSONALBYTES ); 00171 return 0; 00172 } 00173 00174 static INLINE int blake2b_init0( blake2b_state *S ) 00175 { 00176 int i; 00177 XMEMSET( S, 0, sizeof( blake2b_state ) ); 00178 00179 for( i = 0; i < 8; ++i ) S->h[i] = blake2b_IV[i]; 00180 00181 return 0; 00182 } 00183 00184 /* init xors IV with input parameter block */ 00185 int blake2b_init_param( blake2b_state *S, const blake2b_param *P ) 00186 { 00187 word32 i; 00188 blake2b_init0( S ); 00189 byte *p = ( byte * )( P ); 00190 00191 /* IV XOR ParamBlock */ 00192 for( i = 0; i < 8; ++i ) 00193 S->h[i] ^= load64( p + sizeof( S->h[i] ) * i ); 00194 00195 return 0; 00196 } 00197 00198 00199 00200 int blake2b_init( blake2b_state *S, const byte outlen ) 00201 { 00202 blake2b_param P[1]; 00203 00204 if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1; 00205 00206 P->digest_length = outlen; 00207 P->key_length = 0; 00208 P->fanout = 1; 00209 P->depth = 1; 00210 store32( &P->leaf_length, 0 ); 00211 store64( &P->node_offset, 0 ); 00212 P->node_depth = 0; 00213 P->inner_length = 0; 00214 XMEMSET( P->reserved, 0, sizeof( P->reserved ) ); 00215 XMEMSET( P->salt, 0, sizeof( P->salt ) ); 00216 XMEMSET( P->personal, 0, sizeof( P->personal ) ); 00217 return blake2b_init_param( S, P ); 00218 } 00219 00220 00221 int blake2b_init_key( blake2b_state *S, const byte outlen, const void *key, 00222 const byte keylen ) 00223 { 00224 blake2b_param P[1]; 00225 00226 if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1; 00227 00228 if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1; 00229 00230 P->digest_length = outlen; 00231 P->key_length = keylen; 00232 P->fanout = 1; 00233 P->depth = 1; 00234 store32( &P->leaf_length, 0 ); 00235 store64( &P->node_offset, 0 ); 00236 P->node_depth = 0; 00237 P->inner_length = 0; 00238 XMEMSET( P->reserved, 0, sizeof( P->reserved ) ); 00239 XMEMSET( P->salt, 0, sizeof( P->salt ) ); 00240 XMEMSET( P->personal, 0, sizeof( P->personal ) ); 00241 00242 if( blake2b_init_param( S, P ) < 0 ) return -1; 00243 00244 { 00245 byte block[BLAKE2B_BLOCKBYTES]; 00246 XMEMSET( block, 0, BLAKE2B_BLOCKBYTES ); 00247 XMEMCPY( block, key, keylen ); 00248 blake2b_update( S, block, BLAKE2B_BLOCKBYTES ); 00249 secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from */ 00250 /*stack */ 00251 } 00252 return 0; 00253 } 00254 00255 static int blake2b_compress( blake2b_state *S, 00256 const byte block[BLAKE2B_BLOCKBYTES] ) 00257 { 00258 word64 m[16]; 00259 word64 v[16]; 00260 int i; 00261 00262 for( i = 0; i < 16; ++i ) 00263 m[i] = load64( block + i * sizeof( m[i] ) ); 00264 00265 for( i = 0; i < 8; ++i ) 00266 v[i] = S->h[i]; 00267 00268 v[ 8] = blake2b_IV[0]; 00269 v[ 9] = blake2b_IV[1]; 00270 v[10] = blake2b_IV[2]; 00271 v[11] = blake2b_IV[3]; 00272 v[12] = S->t[0] ^ blake2b_IV[4]; 00273 v[13] = S->t[1] ^ blake2b_IV[5]; 00274 v[14] = S->f[0] ^ blake2b_IV[6]; 00275 v[15] = S->f[1] ^ blake2b_IV[7]; 00276 #define G(r,i,a,b,c,d) \ 00277 do { \ 00278 a = a + b + m[blake2b_sigma[r][2*i+0]]; \ 00279 d = rotr64(d ^ a, 32); \ 00280 c = c + d; \ 00281 b = rotr64(b ^ c, 24); \ 00282 a = a + b + m[blake2b_sigma[r][2*i+1]]; \ 00283 d = rotr64(d ^ a, 16); \ 00284 c = c + d; \ 00285 b = rotr64(b ^ c, 63); \ 00286 } while(0) 00287 #define ROUND(r) \ 00288 do { \ 00289 G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \ 00290 G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \ 00291 G(r,2,v[ 2],v[ 6],v[10],v[14]); \ 00292 G(r,3,v[ 3],v[ 7],v[11],v[15]); \ 00293 G(r,4,v[ 0],v[ 5],v[10],v[15]); \ 00294 G(r,5,v[ 1],v[ 6],v[11],v[12]); \ 00295 G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \ 00296 G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \ 00297 } while(0) 00298 ROUND( 0 ); 00299 ROUND( 1 ); 00300 ROUND( 2 ); 00301 ROUND( 3 ); 00302 ROUND( 4 ); 00303 ROUND( 5 ); 00304 ROUND( 6 ); 00305 ROUND( 7 ); 00306 ROUND( 8 ); 00307 ROUND( 9 ); 00308 ROUND( 10 ); 00309 ROUND( 11 ); 00310 00311 for( i = 0; i < 8; ++i ) 00312 S->h[i] = S->h[i] ^ v[i] ^ v[i + 8]; 00313 00314 #undef G 00315 #undef ROUND 00316 return 0; 00317 } 00318 00319 /* inlen now in bytes */ 00320 int blake2b_update( blake2b_state *S, const byte *in, word64 inlen ) 00321 { 00322 while( inlen > 0 ) 00323 { 00324 word64 left = S->buflen; 00325 word64 fill = 2 * BLAKE2B_BLOCKBYTES - left; 00326 00327 if( inlen > fill ) 00328 { 00329 XMEMCPY( S->buf + left, in, (word)fill ); /* Fill buffer */ 00330 S->buflen += fill; 00331 blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES ); 00332 blake2b_compress( S, S->buf ); /* Compress */ 00333 XMEMCPY( S->buf, S->buf + BLAKE2B_BLOCKBYTES, BLAKE2B_BLOCKBYTES ); 00334 /* Shift buffer left */ 00335 S->buflen -= BLAKE2B_BLOCKBYTES; 00336 in += fill; 00337 inlen -= fill; 00338 } 00339 else /* inlen <= fill */ 00340 { 00341 XMEMCPY( S->buf + left, in, (word)inlen ); 00342 S->buflen += inlen; /* Be lazy, do not compress */ 00343 in += inlen; 00344 inlen -= inlen; 00345 } 00346 } 00347 00348 return 0; 00349 } 00350 00351 /* Is this correct? */ 00352 int blake2b_final( blake2b_state *S, byte *out, byte outlen ) 00353 { 00354 byte buffer[BLAKE2B_OUTBYTES]; 00355 int i; 00356 00357 if( S->buflen > BLAKE2B_BLOCKBYTES ) 00358 { 00359 blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES ); 00360 blake2b_compress( S, S->buf ); 00361 S->buflen -= BLAKE2B_BLOCKBYTES; 00362 XMEMCPY( S->buf, S->buf + BLAKE2B_BLOCKBYTES, (word)S->buflen ); 00363 } 00364 00365 blake2b_increment_counter( S, S->buflen ); 00366 blake2b_set_lastblock( S ); 00367 XMEMSET( S->buf + S->buflen, 0, (word)(2 * BLAKE2B_BLOCKBYTES - S->buflen) ); 00368 /* Padding */ 00369 blake2b_compress( S, S->buf ); 00370 00371 for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */ 00372 store64( buffer + sizeof( S->h[i] ) * i, S->h[i] ); 00373 00374 XMEMCPY( out, buffer, outlen ); 00375 return 0; 00376 } 00377 00378 /* inlen, at least, should be word64. Others can be size_t. */ 00379 int blake2b( byte *out, const void *in, const void *key, const byte outlen, 00380 const word64 inlen, byte keylen ) 00381 { 00382 blake2b_state S[1]; 00383 00384 /* Verify parameters */ 00385 if ( NULL == in ) return -1; 00386 00387 if ( NULL == out ) return -1; 00388 00389 if( NULL == key ) keylen = 0; 00390 00391 if( keylen > 0 ) 00392 { 00393 if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1; 00394 } 00395 else 00396 { 00397 if( blake2b_init( S, outlen ) < 0 ) return -1; 00398 } 00399 00400 blake2b_update( S, ( byte * )in, inlen ); 00401 blake2b_final( S, out, outlen ); 00402 return 0; 00403 } 00404 00405 #if defined(BLAKE2B_SELFTEST) 00406 #include <string.h> 00407 #include "blake2-kat.h" 00408 int main( int argc, char **argv ) 00409 { 00410 byte key[BLAKE2B_KEYBYTES]; 00411 byte buf[KAT_LENGTH]; 00412 00413 for( word32 i = 0; i < BLAKE2B_KEYBYTES; ++i ) 00414 key[i] = ( byte )i; 00415 00416 for( word32 i = 0; i < KAT_LENGTH; ++i ) 00417 buf[i] = ( byte )i; 00418 00419 for( word32 i = 0; i < KAT_LENGTH; ++i ) 00420 { 00421 byte hash[BLAKE2B_OUTBYTES]; 00422 blake2b( hash, buf, key, BLAKE2B_OUTBYTES, i, BLAKE2B_KEYBYTES ); 00423 00424 if( 0 != memcmp( hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) ) 00425 { 00426 puts( "error" ); 00427 return -1; 00428 } 00429 } 00430 00431 puts( "ok" ); 00432 return 0; 00433 } 00434 #endif 00435 00436 00437 /* CTaoCrypt API */ 00438 00439 /* Init Blake2b digest, track size incase final doesn't want to "remember" */ 00440 int InitBlake2b(Blake2b* b2b, word32 digestSz) 00441 { 00442 b2b->digestSz = digestSz; 00443 00444 return blake2b_init(b2b->S, (byte)digestSz); 00445 } 00446 00447 00448 /* Blake2b Update */ 00449 int Blake2bUpdate(Blake2b* b2b, const byte* data, word32 sz) 00450 { 00451 return blake2b_update(b2b->S, data, sz); 00452 } 00453 00454 00455 /* Blake2b Final, if pass in zero size we use init digestSz */ 00456 int Blake2bFinal(Blake2b* b2b, byte* final, word32 requestSz) 00457 { 00458 word32 sz = requestSz ? requestSz : b2b->digestSz; 00459 00460 return blake2b_final(b2b->S, final, (byte)sz); 00461 } 00462 00463 00464 /* end CTaoCrypt API */ 00465 00466 #endif /* HAVE_BLAKE2 */ 00467
Generated on Thu Jul 14 2022 20:26:02 by
1.7.2