1  /* dh.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_DH


29 


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


31  #include <wolfssl/wolfcrypt/errorcrypt.h>


32 


33  #ifndef USER_MATH_LIB


34  #include <math.h>


35  #define XPOW(x,y) pow((x),(y))


36  #define XLOG(x) log((x))


37  #else


38  /* user's own math lib */


39  #endif


40 


41 


42  #ifdef min


43  #define WOLFSSL_HAVE_MIN


44  #endif


45  #ifndef WOLFSSL_HAVE_MIN


46  #define WOLFSSL_HAVE_MIN


47 


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


49  {


50  return a > b ? b : a;


51  }


52 


53  #endif /* WOLFSSL_HAVE_MIN */


54 


55 


56  void wc_InitDhKey(DhKey* key)


57  {


58  (void)key;


59  /* TomsFastMath doesn't use memory allocation */


60  #ifndef USE_FAST_MATH


61  key>p.dp = 0;


62  key>g.dp = 0;


63  #endif


64  }


65 


66 


67  void wc_FreeDhKey(DhKey* key)


68  {


69  (void)key;


70  /* TomsFastMath doesn't use memory allocation */


71  #ifndef USE_FAST_MATH


72  mp_clear(&key>p);


73  mp_clear(&key>g);


74  #endif


75  }


76 


77 


78  static word32 DiscreteLogWorkFactor(word32 n)


79  {


80  /* assuming discrete log takes about the same time as factoring */


81  if (n<5)


82  return 0;


83  else


84  return (word32)(2.4 * XPOW((double)n, 1.0/3.0) *


85  XPOW(XLOG((double)n), 2.0/3.0)  5);


86  }


87 


88 


89  static int GeneratePrivate(DhKey* key, WC_RNG* rng, byte* priv, word32* privSz)


90  {


91  int ret;


92  word32 sz = mp_unsigned_bin_size(&key>p);


93  sz = min(sz, 2 * DiscreteLogWorkFactor(sz * WOLFSSL_BIT_SIZE) /


94  WOLFSSL_BIT_SIZE + 1);


95 


96  ret = wc_RNG_GenerateBlock(rng, priv, sz);


97  if (ret != 0)


98  return ret;


99 


100  priv[0] = 0x0C;


101 


102  *privSz = sz;


103 


104  return 0;


105  }


106 


107 


108  static int GeneratePublic(DhKey* key, const byte* priv, word32 privSz,


109  byte* pub, word32* pubSz)


110  {


111  int ret = 0;


112 


113  mp_int x;


114  mp_int y;


115 


116  if (mp_init_multi(&x, &y, 0, 0, 0, 0) != MP_OKAY)


117  return MP_INIT_E;


118 


119  if (mp_read_unsigned_bin(&x, priv, privSz) != MP_OKAY)


120  ret = MP_READ_E;


121 


122  if (ret == 0 && mp_exptmod(&key>g, &x, &key>p, &y) != MP_OKAY)


123  ret = MP_EXPTMOD_E;


124 


125  if (ret == 0 && mp_to_unsigned_bin(&y, pub) != MP_OKAY)


126  ret = MP_TO_E;


127 


128  if (ret == 0)


129  *pubSz = mp_unsigned_bin_size(&y);


130 


131  mp_clear(&y);


132  mp_clear(&x);


133 


134  return ret;


135  }


136 


137 


138  int wc_DhGenerateKeyPair(DhKey* key, WC_RNG* rng, byte* priv, word32* privSz,


139  byte* pub, word32* pubSz)


140  {


141  int ret = GeneratePrivate(key, rng, priv, privSz);


142 


143  return (ret != 0) ? ret : GeneratePublic(key, priv, *privSz, pub, pubSz);


144  }


145 


146  int wc_DhAgree(DhKey* key, byte* agree, word32* agreeSz, const byte* priv,


147  word32 privSz, const byte* otherPub, word32 pubSz)


148  {


149  int ret = 0;


150 


151  mp_int x;


152  mp_int y;


153  mp_int z;


154 


155  if (mp_init_multi(&x, &y, &z, 0, 0, 0) != MP_OKAY)


156  return MP_INIT_E;


157 


158  if (mp_read_unsigned_bin(&x, priv, privSz) != MP_OKAY)


159  ret = MP_READ_E;


160 


161  if (ret == 0 && mp_read_unsigned_bin(&y, otherPub, pubSz) != MP_OKAY)


162  ret = MP_READ_E;


163 


164  if (ret == 0 && mp_exptmod(&y, &x, &key>p, &z) != MP_OKAY)


165  ret = MP_EXPTMOD_E;


166 


167  if (ret == 0 && mp_to_unsigned_bin(&z, agree) != MP_OKAY)


168  ret = MP_TO_E;


169 


170  if (ret == 0)


171  *agreeSz = mp_unsigned_bin_size(&z);


172 


173  mp_clear(&z);


174  mp_clear(&y);


175  mp_clear(&x);


176 


177  return ret;


178  }


179 


180 


181  /* not in asn anymore since no actual asn types used */


182  int wc_DhSetKey(DhKey* key, const byte* p, word32 pSz, const byte* g,


183  word32 gSz)


184  {


185  if (key == NULL  p == NULL  g == NULL  pSz == 0  gSz == 0)


186  return BAD_FUNC_ARG;


187 


188  /* may have leading 0 */


189  if (p[0] == 0) {


190  pSz; p++;


191  }


192 


193  if (g[0] == 0) {


194  gSz; g++;


195  }


196 


197  if (mp_init(&key>p) != MP_OKAY)


198  return MP_INIT_E;


199  if (mp_read_unsigned_bin(&key>p, p, pSz) != 0) {


200  mp_clear(&key>p);


201  return ASN_DH_KEY_E;


202  }


203 


204  if (mp_init(&key>g) != MP_OKAY) {


205  mp_clear(&key>p);


206  return MP_INIT_E;


207  }


208  if (mp_read_unsigned_bin(&key>g, g, gSz) != 0) {


209  mp_clear(&key>g);


210  mp_clear(&key>p);


211  return ASN_DH_KEY_E;


212  }


213 


214  return 0;


215  }


216 


217 


218  #endif /* NO_DH */


219 

