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-2016 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 <wolfssl/wolfcrypt/settings.h> 00041 00042 #ifdef HAVE_BLAKE2 00043 00044 #include <wolfssl/wolfcrypt/blake2.h> 00045 #include <wolfssl/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 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 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 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 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 P->digest_length = outlen; 00130 P->key_length = 0; 00131 P->fanout = 1; 00132 P->depth = 1; 00133 store32( &P->leaf_length, 0 ); 00134 store64( &P->node_offset, 0 ); 00135 P->node_depth = 0; 00136 P->inner_length = 0; 00137 XMEMSET( P->reserved, 0, sizeof( P->reserved ) ); 00138 XMEMSET( P->salt, 0, sizeof( P->salt ) ); 00139 XMEMSET( P->personal, 0, sizeof( P->personal ) ); 00140 return blake2b_init_param( S, P ); 00141 } 00142 00143 00144 int blake2b_init_key( blake2b_state *S, const byte outlen, const void *key, 00145 const byte keylen ) 00146 { 00147 blake2b_param P[1]; 00148 00149 if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1; 00150 00151 if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1; 00152 00153 P->digest_length = outlen; 00154 P->key_length = keylen; 00155 P->fanout = 1; 00156 P->depth = 1; 00157 store32( &P->leaf_length, 0 ); 00158 store64( &P->node_offset, 0 ); 00159 P->node_depth = 0; 00160 P->inner_length = 0; 00161 XMEMSET( P->reserved, 0, sizeof( P->reserved ) ); 00162 XMEMSET( P->salt, 0, sizeof( P->salt ) ); 00163 XMEMSET( P->personal, 0, sizeof( P->personal ) ); 00164 00165 if( blake2b_init_param( S, P ) < 0 ) return -1; 00166 00167 { 00168 #ifdef WOLFSSL_SMALL_STACK 00169 byte* block; 00170 00171 block = (byte*)XMALLOC(BLAKE2B_BLOCKBYTES, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00172 00173 if ( block == NULL ) return -1; 00174 #else 00175 byte block[BLAKE2B_BLOCKBYTES]; 00176 #endif 00177 00178 XMEMSET( block, 0, BLAKE2B_BLOCKBYTES ); 00179 XMEMCPY( block, key, keylen ); 00180 blake2b_update( S, block, BLAKE2B_BLOCKBYTES ); 00181 secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from */ 00182 /* memory */ 00183 00184 #ifdef WOLFSSL_SMALL_STACK 00185 XFREE(block, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00186 #endif 00187 } 00188 return 0; 00189 } 00190 00191 static int blake2b_compress( blake2b_state *S, 00192 const byte block[BLAKE2B_BLOCKBYTES] ) 00193 { 00194 int i; 00195 00196 #ifdef WOLFSSL_SMALL_STACK 00197 word64* m; 00198 word64* v; 00199 00200 m = (word64*)XMALLOC(sizeof(word64) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00201 00202 if ( m == NULL ) return -1; 00203 00204 v = (word64*)XMALLOC(sizeof(word64) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00205 00206 if ( v == NULL ) 00207 { 00208 XFREE(m, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00209 return -1; 00210 } 00211 #else 00212 word64 m[16]; 00213 word64 v[16]; 00214 #endif 00215 00216 for( i = 0; i < 16; ++i ) 00217 m[i] = load64( block + i * sizeof( m[i] ) ); 00218 00219 for( i = 0; i < 8; ++i ) 00220 v[i] = S->h[i]; 00221 00222 v[ 8] = blake2b_IV[0]; 00223 v[ 9] = blake2b_IV[1]; 00224 v[10] = blake2b_IV[2]; 00225 v[11] = blake2b_IV[3]; 00226 v[12] = S->t[0] ^ blake2b_IV[4]; 00227 v[13] = S->t[1] ^ blake2b_IV[5]; 00228 v[14] = S->f[0] ^ blake2b_IV[6]; 00229 v[15] = S->f[1] ^ blake2b_IV[7]; 00230 #define G(r,i,a,b,c,d) \ 00231 do { \ 00232 a = a + b + m[blake2b_sigma[r][2*i+0]]; \ 00233 d = rotr64(d ^ a, 32); \ 00234 c = c + d; \ 00235 b = rotr64(b ^ c, 24); \ 00236 a = a + b + m[blake2b_sigma[r][2*i+1]]; \ 00237 d = rotr64(d ^ a, 16); \ 00238 c = c + d; \ 00239 b = rotr64(b ^ c, 63); \ 00240 } while(0) 00241 #define ROUND(r) \ 00242 do { \ 00243 G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \ 00244 G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \ 00245 G(r,2,v[ 2],v[ 6],v[10],v[14]); \ 00246 G(r,3,v[ 3],v[ 7],v[11],v[15]); \ 00247 G(r,4,v[ 0],v[ 5],v[10],v[15]); \ 00248 G(r,5,v[ 1],v[ 6],v[11],v[12]); \ 00249 G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \ 00250 G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \ 00251 } while(0) 00252 ROUND( 0 ); 00253 ROUND( 1 ); 00254 ROUND( 2 ); 00255 ROUND( 3 ); 00256 ROUND( 4 ); 00257 ROUND( 5 ); 00258 ROUND( 6 ); 00259 ROUND( 7 ); 00260 ROUND( 8 ); 00261 ROUND( 9 ); 00262 ROUND( 10 ); 00263 ROUND( 11 ); 00264 00265 for( i = 0; i < 8; ++i ) 00266 S->h[i] = S->h[i] ^ v[i] ^ v[i + 8]; 00267 00268 #undef G 00269 #undef ROUND 00270 00271 #ifdef WOLFSSL_SMALL_STACK 00272 XFREE(m, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00273 XFREE(v, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00274 #endif 00275 00276 return 0; 00277 } 00278 00279 /* inlen now in bytes */ 00280 int blake2b_update( blake2b_state *S, const byte *in, word64 inlen ) 00281 { 00282 while( inlen > 0 ) 00283 { 00284 word64 left = S->buflen; 00285 word64 fill = 2 * BLAKE2B_BLOCKBYTES - left; 00286 00287 if( inlen > fill ) 00288 { 00289 XMEMCPY( S->buf + left, in, (wolfssl_word)fill ); /* Fill buffer */ 00290 S->buflen += fill; 00291 blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES ); 00292 00293 if ( blake2b_compress( S, S->buf ) < 0 ) return -1; /* Compress */ 00294 00295 XMEMCPY( S->buf, S->buf + BLAKE2B_BLOCKBYTES, BLAKE2B_BLOCKBYTES ); 00296 /* Shift buffer left */ 00297 S->buflen -= BLAKE2B_BLOCKBYTES; 00298 in += fill; 00299 inlen -= fill; 00300 } 00301 else /* inlen <= fill */ 00302 { 00303 XMEMCPY( S->buf + left, in, (wolfssl_word)inlen ); 00304 S->buflen += inlen; /* Be lazy, do not compress */ 00305 in += inlen; 00306 inlen -= inlen; 00307 } 00308 } 00309 00310 return 0; 00311 } 00312 00313 /* Is this correct? */ 00314 int blake2b_final( blake2b_state *S, byte *out, byte outlen ) 00315 { 00316 byte buffer[BLAKE2B_OUTBYTES]; 00317 int i; 00318 00319 if( S->buflen > BLAKE2B_BLOCKBYTES ) 00320 { 00321 blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES ); 00322 00323 if ( blake2b_compress( S, S->buf ) < 0 ) return -1; 00324 00325 S->buflen -= BLAKE2B_BLOCKBYTES; 00326 XMEMCPY( S->buf, S->buf + BLAKE2B_BLOCKBYTES, (wolfssl_word)S->buflen ); 00327 } 00328 00329 blake2b_increment_counter( S, S->buflen ); 00330 blake2b_set_lastblock( S ); 00331 XMEMSET( S->buf + S->buflen, 0, (wolfssl_word)(2 * BLAKE2B_BLOCKBYTES - S->buflen) ); 00332 /* Padding */ 00333 if ( blake2b_compress( S, S->buf ) < 0 ) return -1; 00334 00335 for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */ 00336 store64( buffer + sizeof( S->h[i] ) * i, S->h[i] ); 00337 00338 XMEMCPY( out, buffer, outlen ); 00339 return 0; 00340 } 00341 00342 /* inlen, at least, should be word64. Others can be size_t. */ 00343 int blake2b( byte *out, const void *in, const void *key, const byte outlen, 00344 const word64 inlen, byte keylen ) 00345 { 00346 blake2b_state S[1]; 00347 00348 /* Verify parameters */ 00349 if ( NULL == in ) return -1; 00350 00351 if ( NULL == out ) return -1; 00352 00353 if( NULL == key ) keylen = 0; 00354 00355 if( keylen > 0 ) 00356 { 00357 if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1; 00358 } 00359 else 00360 { 00361 if( blake2b_init( S, outlen ) < 0 ) return -1; 00362 } 00363 00364 if ( blake2b_update( S, ( byte * )in, inlen ) < 0) return -1; 00365 00366 return blake2b_final( S, out, outlen ); 00367 } 00368 00369 #if defined(BLAKE2B_SELFTEST) 00370 #include <string.h> 00371 #include "blake2-kat.h" 00372 int main( int argc, char **argv ) 00373 { 00374 byte key[BLAKE2B_KEYBYTES]; 00375 byte buf[KAT_LENGTH]; 00376 00377 for( word32 i = 0; i < BLAKE2B_KEYBYTES; ++i ) 00378 key[i] = ( byte )i; 00379 00380 for( word32 i = 0; i < KAT_LENGTH; ++i ) 00381 buf[i] = ( byte )i; 00382 00383 for( word32 i = 0; i < KAT_LENGTH; ++i ) 00384 { 00385 byte hash[BLAKE2B_OUTBYTES]; 00386 if ( blake2b( hash, buf, key, BLAKE2B_OUTBYTES, i, BLAKE2B_KEYBYTES ) < 0 ) 00387 { 00388 puts( "error" ); 00389 return -1; 00390 } 00391 00392 if( 0 != memcmp( hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) ) 00393 { 00394 puts( "error" ); 00395 return -1; 00396 } 00397 } 00398 00399 puts( "ok" ); 00400 return 0; 00401 } 00402 #endif 00403 00404 00405 /* wolfCrypt API */ 00406 00407 /* Init Blake2b digest, track size in case final doesn't want to "remember" */ 00408 int wc_InitBlake2b(Blake2b* b2b, word32 digestSz) 00409 { 00410 b2b->digestSz = digestSz; 00411 00412 return blake2b_init(b2b->S, (byte)digestSz); 00413 } 00414 00415 00416 /* Blake2b Update */ 00417 int wc_Blake2bUpdate(Blake2b* b2b, const byte* data, word32 sz) 00418 { 00419 return blake2b_update(b2b->S, data, sz); 00420 } 00421 00422 00423 /* Blake2b Final, if pass in zero size we use init digestSz */ 00424 int wc_Blake2bFinal(Blake2b* b2b, byte* final, word32 requestSz) 00425 { 00426 word32 sz = requestSz ? requestSz : b2b->digestSz; 00427 00428 return blake2b_final(b2b->S, final, (byte)sz); 00429 } 00430 00431 00432 /* end CTaoCrypt API */ 00433 00434 #endif /* HAVE_BLAKE2 */ 00435 00436
Generated on Tue Jul 12 2022 15:55:17 by
1.7.2