Xuyi Wang / wolfcrypt

Dependents:   OS

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers blake2b.c Source File

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