1  /* md4.c


2  *


3  * Copyright (C) 20062015 wolfSSL Inc.


4  *


5  * This file is part of wolfSSL. (formerly known as CyaSSL)


6  *


7  * wolfSSL is free software; you can redistribute it and/or modify


8  * it under the terms of the GNU General Public License as published by


9  * the Free Software Foundation; either version 2 of the License, or


10  * (at your option) any later version.


11  *


12  * wolfSSL is distributed in the hope that it will be useful,


13  * but WITHOUT ANY WARRANTY; without even the implied warranty of


14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the


15  * GNU General Public License for more details.


16  *


17  * You should have received a copy of the GNU General Public License


18  * along with this program; if not, write to the Free Software


19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 021101301, USA


20  */


21 


22  #ifdef HAVE_CONFIG_H


23  #include <config.h>


24  #endif


25 


26  #include <wolfssl/wolfcrypt/settings.h>


27 


28  #ifndef NO_MD4


29 


30  #include <wolfssl/wolfcrypt/md4.h>


31  #ifdef NO_INLINE


32  #include <wolfssl/wolfcrypt/misc.h>


33  #else


34  #include <wolfcrypt/src/misc.c>


35  #endif


36 


37 


38  #ifdef min


39  #define WOLFSSL_HAVE_MIN


40  #endif


41  #ifndef WOLFSSL_HAVE_MIN


42  #define WOLFSSL_HAVE_MIN


43 


44  static INLINE word32 min(word32 a, word32 b)


45  {


46  return a > b ? b : a;


47  }


48 


49  #endif /* WOLFSSL_HAVE_MIN */


50 


51 


52  void wc_InitMd4(Md4* md4)


53  {


54  md4>digest[0] = 0x67452301L;


55  md4>digest[1] = 0xefcdab89L;


56  md4>digest[2] = 0x98badcfeL;


57  md4>digest[3] = 0x10325476L;


58 


59  md4>buffLen = 0;


60  md4>loLen = 0;


61  md4>hiLen = 0;


62  }


63 


64 


65  static void Transform(Md4* md4)


66  {


67  #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))


68  #define G(x, y, z) (((x) & (y))  ((x) & (z))  ((y) & (z)))


69  #define H(x, y, z) ((x) ^ (y) ^ (z))


70 


71  /* Copy context>state[] to working vars */


72  word32 A = md4>digest[0];


73  word32 B = md4>digest[1];


74  word32 C = md4>digest[2];


75  word32 D = md4>digest[3];


76 


77  #define function(a,b,c,d,k,s) a=rotlFixed(a+F(b,c,d)+md4>buffer[k],s);


78  function(A,B,C,D, 0, 3);


79  function(D,A,B,C, 1, 7);


80  function(C,D,A,B, 2,11);


81  function(B,C,D,A, 3,19);


82  function(A,B,C,D, 4, 3);


83  function(D,A,B,C, 5, 7);


84  function(C,D,A,B, 6,11);


85  function(B,C,D,A, 7,19);


86  function(A,B,C,D, 8, 3);


87  function(D,A,B,C, 9, 7);


88  function(C,D,A,B,10,11);


89  function(B,C,D,A,11,19);


90  function(A,B,C,D,12, 3);


91  function(D,A,B,C,13, 7);


92  function(C,D,A,B,14,11);


93  function(B,C,D,A,15,19);


94 


95  #undef function


96  #define function(a,b,c,d,k,s) \


97  a=rotlFixed(a+G(b,c,d)+md4>buffer[k]+0x5a827999,s);


98 


99  function(A,B,C,D, 0, 3);


100  function(D,A,B,C, 4, 5);


101  function(C,D,A,B, 8, 9);


102  function(B,C,D,A,12,13);


103  function(A,B,C,D, 1, 3);


104  function(D,A,B,C, 5, 5);


105  function(C,D,A,B, 9, 9);


106  function(B,C,D,A,13,13);


107  function(A,B,C,D, 2, 3);


108  function(D,A,B,C, 6, 5);


109  function(C,D,A,B,10, 9);


110  function(B,C,D,A,14,13);


111  function(A,B,C,D, 3, 3);


112  function(D,A,B,C, 7, 5);


113  function(C,D,A,B,11, 9);


114  function(B,C,D,A,15,13);


115 


116  #undef function


117  #define function(a,b,c,d,k,s) \


118  a=rotlFixed(a+H(b,c,d)+md4>buffer[k]+0x6ed9eba1,s);


119 


120  function(A,B,C,D, 0, 3);


121  function(D,A,B,C, 8, 9);


122  function(C,D,A,B, 4,11);


123  function(B,C,D,A,12,15);


124  function(A,B,C,D, 2, 3);


125  function(D,A,B,C,10, 9);


126  function(C,D,A,B, 6,11);


127  function(B,C,D,A,14,15);


128  function(A,B,C,D, 1, 3);


129  function(D,A,B,C, 9, 9);


130  function(C,D,A,B, 5,11);


131  function(B,C,D,A,13,15);


132  function(A,B,C,D, 3, 3);


133  function(D,A,B,C,11, 9);


134  function(C,D,A,B, 7,11);


135  function(B,C,D,A,15,15);


136 


137  /* Add the working vars back into digest state[] */


138  md4>digest[0] += A;


139  md4>digest[1] += B;


140  md4>digest[2] += C;


141  md4>digest[3] += D;


142  }


143 


144 


145  static INLINE void AddLength(Md4* md4, word32 len)


146  {


147  word32 tmp = md4>loLen;


148  if ( (md4>loLen += len) < tmp)


149  md4>hiLen++; /* carry low to high */


150  }


151 


152 


153  void wc_Md4Update(Md4* md4, const byte* data, word32 len)


154  {


155  /* do block size increments */


156  byte* local = (byte*)md4>buffer;


157 


158  while (len) {


159  word32 add = min(len, MD4_BLOCK_SIZE  md4>buffLen);


160  XMEMCPY(&local[md4>buffLen], data, add);


161 


162  md4>buffLen += add;


163  data += add;


164  len = add;


165 


166  if (md4>buffLen == MD4_BLOCK_SIZE) {


167  #ifdef BIG_ENDIAN_ORDER


168  ByteReverseWords(md4>buffer, md4>buffer, MD4_BLOCK_SIZE);


169  #endif


170  Transform(md4);


171  AddLength(md4, MD4_BLOCK_SIZE);


172  md4>buffLen = 0;


173  }


174  }


175  }


176 


177 


178  void wc_Md4Final(Md4* md4, byte* hash)


179  {


180  byte* local = (byte*)md4>buffer;


181 


182  AddLength(md4, md4>buffLen); /* before adding pads */


183 


184  local[md4>buffLen++] = 0x80; /* add 1 */


185 


186  /* pad with zeros */


187  if (md4>buffLen > MD4_PAD_SIZE) {


188  XMEMSET(&local[md4>buffLen], 0, MD4_BLOCK_SIZE  md4>buffLen);


189  md4>buffLen += MD4_BLOCK_SIZE  md4>buffLen;


190 


191  #ifdef BIG_ENDIAN_ORDER


192  ByteReverseWords(md4>buffer, md4>buffer, MD4_BLOCK_SIZE);


193  #endif


194  Transform(md4);


195  md4>buffLen = 0;


196  }


197  XMEMSET(&local[md4>buffLen], 0, MD4_PAD_SIZE  md4>buffLen);


198 


199  /* put lengths in bits */


200  md4>hiLen = (md4>loLen >> (8*sizeof(md4>loLen)  3)) +


201  (md4>hiLen << 3);


202  md4>loLen = md4>loLen << 3;


203 


204  /* store lengths */


205  #ifdef BIG_ENDIAN_ORDER


206  ByteReverseWords(md4>buffer, md4>buffer, MD4_BLOCK_SIZE);


207  #endif


208  /* ! length ordering dependent on digest endian type ! */


209  XMEMCPY(&local[MD4_PAD_SIZE], &md4>loLen, sizeof(word32));


210  XMEMCPY(&local[MD4_PAD_SIZE + sizeof(word32)], &md4>hiLen, sizeof(word32));


211 


212  Transform(md4);


213  #ifdef BIG_ENDIAN_ORDER


214  ByteReverseWords(md4>digest, md4>digest, MD4_DIGEST_SIZE);


215  #endif


216  XMEMCPY(hash, md4>digest, MD4_DIGEST_SIZE);


217 


218  wc_InitMd4(md4); /* reset state */


219  }


220 


221 


222  #endif /* NO_MD4 */


223 

