Francois Berder / cyassl-lib

Dependents:   TLS_cyassl TLS_cyassl

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