Renesas / SecureDweet
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-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