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.
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-2017 wolfSSL Inc. 00016 * 00017 * This file is part of wolfSSL. 00018 * 00019 * wolfSSL 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 * wolfSSL 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-1335, USA 00032 */ 00033 00034 00035 00036 #ifdef HAVE_CONFIG_H 00037 #include <config.h> 00038 #endif 00039 00040 #include <wolfcrypt/settings.h> 00041 00042 #ifdef HAVE_BLAKE2 00043 00044 #include <wolfcrypt/blake2.h> 00045 #include <wolfcrypt/blake2-impl.h> 00046 00047 00048 static const word64 blake2b_IV[8] = 00049 { 00050 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 00051 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL, 00052 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL, 00053 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL 00054 }; 00055 00056 static const byte blake2b_sigma[12][16] = 00057 { 00058 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , 00059 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , 00060 { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , 00061 { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , 00062 { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , 00063 { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , 00064 { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , 00065 { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , 00066 { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , 00067 { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } , 00068 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , 00069 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } 00070 }; 00071 00072 00073 static WC_INLINE int blake2b_set_lastnode( blake2b_state *S ) 00074 { 00075 S->f[1] = ~0ULL; 00076 return 0; 00077 } 00078 00079 /* Some helper functions, not necessarily useful */ 00080 static WC_INLINE int blake2b_set_lastblock( blake2b_state *S ) 00081 { 00082 if( S->last_node ) blake2b_set_lastnode( S ); 00083 00084 S->f[0] = ~0ULL; 00085 return 0; 00086 } 00087 00088 static WC_INLINE int blake2b_increment_counter( blake2b_state *S, const word64 00089 inc ) 00090 { 00091 S->t[0] += inc; 00092 S->t[1] += ( S->t[0] < inc ); 00093 return 0; 00094 } 00095 00096 static WC_INLINE int blake2b_init0( blake2b_state *S ) 00097 { 00098 int i; 00099 XMEMSET( S, 0, sizeof( blake2b_state ) ); 00100 00101 for( i = 0; i < 8; ++i ) S->h[i] = blake2b_IV[i]; 00102 00103 return 0; 00104 } 00105 00106 /* init xors IV with input parameter block */ 00107 int blake2b_init_param( blake2b_state *S, const blake2b_param *P ) 00108 { 00109 word32 i; 00110 byte *p ; 00111 blake2b_init0( S ); 00112 p = ( byte * )( P ); 00113 00114 /* IV XOR ParamBlock */ 00115 for( i = 0; i < 8; ++i ) 00116 S->h[i] ^= load64( p + sizeof( S->h[i] ) * i ); 00117 00118 return 0; 00119 } 00120 00121 00122 00123 int blake2b_init( blake2b_state *S, const byte outlen ) 00124 { 00125 blake2b_param P[1]; 00126 00127 if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1; 00128 00129 #ifdef WOLFSSL_BLAKE2B_INIT_EACH_FIELD 00130 P->digest_length = outlen; 00131 P->key_length = 0; 00132 P->fanout = 1; 00133 P->depth = 1; 00134 store32( &P->leaf_length, 0 ); 00135 store64( &P->node_offset, 0 ); 00136 P->node_depth = 0; 00137 P->inner_length = 0; 00138 XMEMSET( P->reserved, 0, sizeof( P->reserved ) ); 00139 XMEMSET( P->salt, 0, sizeof( P->salt ) ); 00140 XMEMSET( P->personal, 0, sizeof( P->personal ) ); 00141 #else 00142 XMEMSET( P, 0, sizeof( *P ) ); 00143 P->digest_length = outlen; 00144 P->fanout = 1; 00145 P->depth = 1; 00146 #endif 00147 return blake2b_init_param( S, P ); 00148 } 00149 00150 00151 int blake2b_init_key( blake2b_state *S, const byte outlen, const void *key, 00152 const byte keylen ) 00153 { 00154 blake2b_param P[1]; 00155 00156 if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1; 00157 00158 if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1; 00159 00160 #ifdef WOLFSSL_BLAKE2B_INIT_EACH_FIELD 00161 P->digest_length = outlen; 00162 P->key_length = keylen; 00163 P->fanout = 1; 00164 P->depth = 1; 00165 store32( &P->leaf_length, 0 ); 00166 store64( &P->node_offset, 0 ); 00167 P->node_depth = 0; 00168 P->inner_length = 0; 00169 XMEMSET( P->reserved, 0, sizeof( P->reserved ) ); 00170 XMEMSET( P->salt, 0, sizeof( P->salt ) ); 00171 XMEMSET( P->personal, 0, sizeof( P->personal ) ); 00172 #else 00173 XMEMSET( P, 0, sizeof( *P ) ); 00174 P->digest_length = outlen; 00175 P->key_length = keylen; 00176 P->fanout = 1; 00177 P->depth = 1; 00178 #endif 00179 00180 if( blake2b_init_param( S, P ) < 0 ) return -1; 00181 00182 { 00183 #ifdef WOLFSSL_SMALL_STACK 00184 byte* block; 00185 00186 block = (byte*)XMALLOC(BLAKE2B_BLOCKBYTES, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00187 00188 if ( block == NULL ) return -1; 00189 #else 00190 byte block[BLAKE2B_BLOCKBYTES]; 00191 #endif 00192 00193 XMEMSET( block, 0, BLAKE2B_BLOCKBYTES ); 00194 XMEMCPY( block, key, keylen ); 00195 blake2b_update( S, block, BLAKE2B_BLOCKBYTES ); 00196 secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from */ 00197 /* memory */ 00198 00199 #ifdef WOLFSSL_SMALL_STACK 00200 XFREE(block, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00201 #endif 00202 } 00203 return 0; 00204 } 00205 00206 static int blake2b_compress( blake2b_state *S, 00207 const byte block[BLAKE2B_BLOCKBYTES] ) 00208 { 00209 int i; 00210 00211 #ifdef WOLFSSL_SMALL_STACK 00212 word64* m; 00213 word64* v; 00214 00215 m = (word64*)XMALLOC(sizeof(word64) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00216 00217 if ( m == NULL ) return -1; 00218 00219 v = (word64*)XMALLOC(sizeof(word64) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00220 00221 if ( v == NULL ) 00222 { 00223 XFREE(m, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00224 return -1; 00225 } 00226 #else 00227 word64 m[16]; 00228 word64 v[16]; 00229 #endif 00230 00231 for( i = 0; i < 16; ++i ) 00232 m[i] = load64( block + i * sizeof( m[i] ) ); 00233 00234 for( i = 0; i < 8; ++i ) 00235 v[i] = S->h[i]; 00236 00237 v[ 8] = blake2b_IV[0]; 00238 v[ 9] = blake2b_IV[1]; 00239 v[10] = blake2b_IV[2]; 00240 v[11] = blake2b_IV[3]; 00241 v[12] = S->t[0] ^ blake2b_IV[4]; 00242 v[13] = S->t[1] ^ blake2b_IV[5]; 00243 v[14] = S->f[0] ^ blake2b_IV[6]; 00244 v[15] = S->f[1] ^ blake2b_IV[7]; 00245 #define G(r,i,a,b,c,d) \ 00246 do { \ 00247 a = a + b + m[blake2b_sigma[r][2*i+0]]; \ 00248 d = rotr64(d ^ a, 32); \ 00249 c = c + d; \ 00250 b = rotr64(b ^ c, 24); \ 00251 a = a + b + m[blake2b_sigma[r][2*i+1]]; \ 00252 d = rotr64(d ^ a, 16); \ 00253 c = c + d; \ 00254 b = rotr64(b ^ c, 63); \ 00255 } while(0) 00256 #define ROUND(r) \ 00257 do { \ 00258 G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \ 00259 G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \ 00260 G(r,2,v[ 2],v[ 6],v[10],v[14]); \ 00261 G(r,3,v[ 3],v[ 7],v[11],v[15]); \ 00262 G(r,4,v[ 0],v[ 5],v[10],v[15]); \ 00263 G(r,5,v[ 1],v[ 6],v[11],v[12]); \ 00264 G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \ 00265 G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \ 00266 } while(0) 00267 ROUND( 0 ); 00268 ROUND( 1 ); 00269 ROUND( 2 ); 00270 ROUND( 3 ); 00271 ROUND( 4 ); 00272 ROUND( 5 ); 00273 ROUND( 6 ); 00274 ROUND( 7 ); 00275 ROUND( 8 ); 00276 ROUND( 9 ); 00277 ROUND( 10 ); 00278 ROUND( 11 ); 00279 00280 for( i = 0; i < 8; ++i ) 00281 S->h[i] = S->h[i] ^ v[i] ^ v[i + 8]; 00282 00283 #undef G 00284 #undef ROUND 00285 00286 #ifdef WOLFSSL_SMALL_STACK 00287 XFREE(m, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00288 XFREE(v, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00289 #endif 00290 00291 return 0; 00292 } 00293 00294 /* inlen now in bytes */ 00295 int blake2b_update( blake2b_state *S, const byte *in, word64 inlen ) 00296 { 00297 while( inlen > 0 ) 00298 { 00299 word64 left = S->buflen; 00300 word64 fill = 2 * BLAKE2B_BLOCKBYTES - left; 00301 00302 if( inlen > fill ) 00303 { 00304 XMEMCPY( S->buf + left, in, (wolfssl_word)fill ); /* Fill buffer */ 00305 S->buflen += fill; 00306 blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES ); 00307 00308 if ( blake2b_compress( S, S->buf ) < 0 ) return -1; /* Compress */ 00309 00310 XMEMCPY( S->buf, S->buf + BLAKE2B_BLOCKBYTES, BLAKE2B_BLOCKBYTES ); 00311 /* Shift buffer left */ 00312 S->buflen -= BLAKE2B_BLOCKBYTES; 00313 in += fill; 00314 inlen -= fill; 00315 } 00316 else /* inlen <= fill */ 00317 { 00318 XMEMCPY( S->buf + left, in, (wolfssl_word)inlen ); 00319 S->buflen += inlen; /* Be lazy, do not compress */ 00320 in += inlen; 00321 inlen -= inlen; 00322 } 00323 } 00324 00325 return 0; 00326 } 00327 00328 /* Is this correct? */ 00329 int blake2b_final( blake2b_state *S, byte *out, byte outlen ) 00330 { 00331 byte buffer[BLAKE2B_OUTBYTES]; 00332 int i; 00333 00334 if( S->buflen > BLAKE2B_BLOCKBYTES ) 00335 { 00336 blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES ); 00337 00338 if ( blake2b_compress( S, S->buf ) < 0 ) return -1; 00339 00340 S->buflen -= BLAKE2B_BLOCKBYTES; 00341 XMEMCPY( S->buf, S->buf + BLAKE2B_BLOCKBYTES, (wolfssl_word)S->buflen ); 00342 } 00343 00344 blake2b_increment_counter( S, S->buflen ); 00345 blake2b_set_lastblock( S ); 00346 XMEMSET( S->buf + S->buflen, 0, (wolfssl_word)(2 * BLAKE2B_BLOCKBYTES - S->buflen) ); 00347 /* Padding */ 00348 if ( blake2b_compress( S, S->buf ) < 0 ) return -1; 00349 00350 for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */ 00351 store64( buffer + sizeof( S->h[i] ) * i, S->h[i] ); 00352 00353 XMEMCPY( out, buffer, outlen ); 00354 return 0; 00355 } 00356 00357 /* inlen, at least, should be word64. Others can be size_t. */ 00358 int blake2b( byte *out, const void *in, const void *key, const byte outlen, 00359 const word64 inlen, byte keylen ) 00360 { 00361 blake2b_state S[1]; 00362 00363 /* Verify parameters */ 00364 if ( NULL == in ) return -1; 00365 00366 if ( NULL == out ) return -1; 00367 00368 if( NULL == key ) keylen = 0; 00369 00370 if( keylen > 0 ) 00371 { 00372 if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1; 00373 } 00374 else 00375 { 00376 if( blake2b_init( S, outlen ) < 0 ) return -1; 00377 } 00378 00379 if ( blake2b_update( S, ( byte * )in, inlen ) < 0) return -1; 00380 00381 return blake2b_final( S, out, outlen ); 00382 } 00383 00384 #if defined(BLAKE2B_SELFTEST) 00385 #include <string.h> 00386 #include "blake2-kat.h" 00387 int main( int argc, char **argv ) 00388 { 00389 byte key[BLAKE2B_KEYBYTES]; 00390 byte buf[KAT_LENGTH]; 00391 00392 for( word32 i = 0; i < BLAKE2B_KEYBYTES; ++i ) 00393 key[i] = ( byte )i; 00394 00395 for( word32 i = 0; i < KAT_LENGTH; ++i ) 00396 buf[i] = ( byte )i; 00397 00398 for( word32 i = 0; i < KAT_LENGTH; ++i ) 00399 { 00400 byte hash[BLAKE2B_OUTBYTES]; 00401 if ( blake2b( hash, buf, key, BLAKE2B_OUTBYTES, i, BLAKE2B_KEYBYTES ) < 0 ) 00402 { 00403 puts( "error" ); 00404 return -1; 00405 } 00406 00407 if( 0 != XMEMCMP( hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) ) 00408 { 00409 puts( "error" ); 00410 return -1; 00411 } 00412 } 00413 00414 puts( "ok" ); 00415 return 0; 00416 } 00417 #endif 00418 00419 00420 /* wolfCrypt API */ 00421 00422 /* Init Blake2b digest, track size in case final doesn't want to "remember" */ 00423 int wc_InitBlake2b(Blake2b* b2b, word32 digestSz) 00424 { 00425 if (b2b == NULL){ 00426 return -1; 00427 } 00428 b2b->digestSz = digestSz; 00429 00430 return blake2b_init(b2b->S, (byte)digestSz); 00431 } 00432 00433 00434 /* Blake2b Update */ 00435 int wc_Blake2bUpdate(Blake2b* b2b, const byte* data, word32 sz) 00436 { 00437 return blake2b_update(b2b->S, data, sz); 00438 } 00439 00440 00441 /* Blake2b Final, if pass in zero size we use init digestSz */ 00442 int wc_Blake2bFinal(Blake2b* b2b, byte* final, word32 requestSz) 00443 { 00444 word32 sz = requestSz ? requestSz : b2b->digestSz; 00445 00446 return blake2b_final(b2b->S, final, (byte)sz); 00447 } 00448 00449 00450 /* end CTaoCrypt API */ 00451 00452 #endif /* HAVE_BLAKE2 */ 00453 00454
Generated on Tue Jul 12 2022 16:58:05 by
1.7.2