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-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 /* 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 byte block[BLAKE2B_BLOCKBYTES]; 00167 XMEMSET( block, 0, BLAKE2B_BLOCKBYTES ); 00168 XMEMCPY( block, key, keylen ); 00169 blake2b_update( S, block, BLAKE2B_BLOCKBYTES ); 00170 secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from */ 00171 /*stack */ 00172 } 00173 return 0; 00174 } 00175 00176 static int blake2b_compress( blake2b_state *S, 00177 const byte block[BLAKE2B_BLOCKBYTES] ) 00178 { 00179 word64 m[16]; 00180 word64 v[16]; 00181 int i; 00182 00183 for( i = 0; i < 16; ++i ) 00184 m[i] = load64( block + i * sizeof( m[i] ) ); 00185 00186 for( i = 0; i < 8; ++i ) 00187 v[i] = S->h[i]; 00188 00189 v[ 8] = blake2b_IV[0]; 00190 v[ 9] = blake2b_IV[1]; 00191 v[10] = blake2b_IV[2]; 00192 v[11] = blake2b_IV[3]; 00193 v[12] = S->t[0] ^ blake2b_IV[4]; 00194 v[13] = S->t[1] ^ blake2b_IV[5]; 00195 v[14] = S->f[0] ^ blake2b_IV[6]; 00196 v[15] = S->f[1] ^ blake2b_IV[7]; 00197 #define G(r,i,a,b,c,d) \ 00198 do { \ 00199 a = a + b + m[blake2b_sigma[r][2*i+0]]; \ 00200 d = rotr64(d ^ a, 32); \ 00201 c = c + d; \ 00202 b = rotr64(b ^ c, 24); \ 00203 a = a + b + m[blake2b_sigma[r][2*i+1]]; \ 00204 d = rotr64(d ^ a, 16); \ 00205 c = c + d; \ 00206 b = rotr64(b ^ c, 63); \ 00207 } while(0) 00208 #define ROUND(r) \ 00209 do { \ 00210 G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \ 00211 G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \ 00212 G(r,2,v[ 2],v[ 6],v[10],v[14]); \ 00213 G(r,3,v[ 3],v[ 7],v[11],v[15]); \ 00214 G(r,4,v[ 0],v[ 5],v[10],v[15]); \ 00215 G(r,5,v[ 1],v[ 6],v[11],v[12]); \ 00216 G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \ 00217 G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \ 00218 } while(0) 00219 ROUND( 0 ); 00220 ROUND( 1 ); 00221 ROUND( 2 ); 00222 ROUND( 3 ); 00223 ROUND( 4 ); 00224 ROUND( 5 ); 00225 ROUND( 6 ); 00226 ROUND( 7 ); 00227 ROUND( 8 ); 00228 ROUND( 9 ); 00229 ROUND( 10 ); 00230 ROUND( 11 ); 00231 00232 for( i = 0; i < 8; ++i ) 00233 S->h[i] = S->h[i] ^ v[i] ^ v[i + 8]; 00234 00235 #undef G 00236 #undef ROUND 00237 return 0; 00238 } 00239 00240 /* inlen now in bytes */ 00241 int blake2b_update( blake2b_state *S, const byte *in, word64 inlen ) 00242 { 00243 while( inlen > 0 ) 00244 { 00245 word64 left = S->buflen; 00246 word64 fill = 2 * BLAKE2B_BLOCKBYTES - left; 00247 00248 if( inlen > fill ) 00249 { 00250 XMEMCPY( S->buf + left, in, (word)fill ); /* Fill buffer */ 00251 S->buflen += fill; 00252 blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES ); 00253 blake2b_compress( S, S->buf ); /* Compress */ 00254 XMEMCPY( S->buf, S->buf + BLAKE2B_BLOCKBYTES, BLAKE2B_BLOCKBYTES ); 00255 /* Shift buffer left */ 00256 S->buflen -= BLAKE2B_BLOCKBYTES; 00257 in += fill; 00258 inlen -= fill; 00259 } 00260 else /* inlen <= fill */ 00261 { 00262 XMEMCPY( S->buf + left, in, (word)inlen ); 00263 S->buflen += inlen; /* Be lazy, do not compress */ 00264 in += inlen; 00265 inlen -= inlen; 00266 } 00267 } 00268 00269 return 0; 00270 } 00271 00272 /* Is this correct? */ 00273 int blake2b_final( blake2b_state *S, byte *out, byte outlen ) 00274 { 00275 byte buffer[BLAKE2B_OUTBYTES]; 00276 int i; 00277 00278 if( S->buflen > BLAKE2B_BLOCKBYTES ) 00279 { 00280 blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES ); 00281 blake2b_compress( S, S->buf ); 00282 S->buflen -= BLAKE2B_BLOCKBYTES; 00283 XMEMCPY( S->buf, S->buf + BLAKE2B_BLOCKBYTES, (word)S->buflen ); 00284 } 00285 00286 blake2b_increment_counter( S, S->buflen ); 00287 blake2b_set_lastblock( S ); 00288 XMEMSET( S->buf + S->buflen, 0, (word)(2 * BLAKE2B_BLOCKBYTES - S->buflen) ); 00289 /* Padding */ 00290 blake2b_compress( S, S->buf ); 00291 00292 for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */ 00293 store64( buffer + sizeof( S->h[i] ) * i, S->h[i] ); 00294 00295 XMEMCPY( out, buffer, outlen ); 00296 return 0; 00297 } 00298 00299 /* inlen, at least, should be word64. Others can be size_t. */ 00300 int blake2b( byte *out, const void *in, const void *key, const byte outlen, 00301 const word64 inlen, byte keylen ) 00302 { 00303 blake2b_state S[1]; 00304 00305 /* Verify parameters */ 00306 if ( NULL == in ) return -1; 00307 00308 if ( NULL == out ) return -1; 00309 00310 if( NULL == key ) keylen = 0; 00311 00312 if( keylen > 0 ) 00313 { 00314 if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1; 00315 } 00316 else 00317 { 00318 if( blake2b_init( S, outlen ) < 0 ) return -1; 00319 } 00320 00321 blake2b_update( S, ( byte * )in, inlen ); 00322 blake2b_final( S, out, outlen ); 00323 return 0; 00324 } 00325 00326 #if defined(BLAKE2B_SELFTEST) 00327 #include <string.h> 00328 #include "blake2-kat.h" 00329 int main( int argc, char **argv ) 00330 { 00331 byte key[BLAKE2B_KEYBYTES]; 00332 byte buf[KAT_LENGTH]; 00333 00334 for( word32 i = 0; i < BLAKE2B_KEYBYTES; ++i ) 00335 key[i] = ( byte )i; 00336 00337 for( word32 i = 0; i < KAT_LENGTH; ++i ) 00338 buf[i] = ( byte )i; 00339 00340 for( word32 i = 0; i < KAT_LENGTH; ++i ) 00341 { 00342 byte hash[BLAKE2B_OUTBYTES]; 00343 blake2b( hash, buf, key, BLAKE2B_OUTBYTES, i, BLAKE2B_KEYBYTES ); 00344 00345 if( 0 != memcmp( hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) ) 00346 { 00347 puts( "error" ); 00348 return -1; 00349 } 00350 } 00351 00352 puts( "ok" ); 00353 return 0; 00354 } 00355 #endif 00356 00357 00358 /* CTaoCrypt API */ 00359 00360 /* Init Blake2b digest, track size incase final doesn't want to "remember" */ 00361 int InitBlake2b(Blake2b* b2b, word32 digestSz) 00362 { 00363 b2b->digestSz = digestSz; 00364 00365 return blake2b_init(b2b->S, (byte)digestSz); 00366 } 00367 00368 00369 /* Blake2b Update */ 00370 int Blake2bUpdate(Blake2b* b2b, const byte* data, word32 sz) 00371 { 00372 return blake2b_update(b2b->S, data, sz); 00373 } 00374 00375 00376 /* Blake2b Final, if pass in zero size we use init digestSz */ 00377 int Blake2bFinal(Blake2b* b2b, byte* final, word32 requestSz) 00378 { 00379 word32 sz = requestSz ? requestSz : b2b->digestSz; 00380 00381 return blake2b_final(b2b->S, final, (byte)sz); 00382 } 00383 00384 00385 /* end CTaoCrypt API */ 00386 00387 #endif /* HAVE_BLAKE2 */ 00388
Generated on Tue Jul 12 2022 20:12:50 by
