wolf SSL / CyaSSL-2.9.4

Dependents:  

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 /* 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