Renesas / SecureDweet
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers dh.c Source File

dh.c

00001 /* dh.c
00002  *
00003  * Copyright (C) 2006-2016 wolfSSL Inc.
00004  *
00005  * This file is part of wolfSSL.
00006  *
00007  * wolfSSL is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * wolfSSL is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
00020  */
00021 
00022 
00023 #ifdef HAVE_CONFIG_H
00024     #include <config.h>
00025 #endif
00026 
00027 #include <wolfssl/wolfcrypt/settings.h>
00028 
00029 #ifndef NO_DH
00030 
00031 #include <wolfssl/wolfcrypt/dh.h>
00032 #include <wolfssl/wolfcrypt/error-crypt.h>
00033 
00034 #if !defined(USER_MATH_LIB) && !defined(WOLFSSL_DH_CONST)
00035     #include <math.h>
00036     #define XPOW(x,y) pow((x),(y))
00037     #define XLOG(x)   log((x))
00038 #else
00039     /* user's own math lib */
00040 #endif
00041 
00042 
00043 #if !defined(WOLFSSL_HAVE_MIN) && !defined(WOLFSSL_DH_CONST)
00044 #define WOLFSSL_HAVE_MIN
00045 
00046     static INLINE word32 min(word32 a, word32 b)
00047     {
00048         return a > b ? b : a;
00049     }
00050 
00051 #endif /* WOLFSSL_HAVE_MIN */
00052 
00053 
00054 void wc_InitDhKey(DhKey* key)
00055 {
00056     (void)key;
00057 /* TomsFastMath doesn't use memory allocation */
00058 #ifndef USE_FAST_MATH
00059     key->p.dp = 0;
00060     key->g.dp = 0;
00061 #endif
00062 }
00063 
00064 
00065 void wc_FreeDhKey(DhKey* key)
00066 {
00067     (void)key;
00068 /* TomsFastMath doesn't use memory allocation */
00069 #ifndef USE_FAST_MATH
00070     mp_clear(&key->p);
00071     mp_clear(&key->g);
00072 #endif
00073 }
00074 
00075 
00076 /* if defined to not use floating point values do not compile in */
00077 #ifndef WOLFSSL_DH_CONST
00078 static word32 DiscreteLogWorkFactor(word32 n)
00079 {
00080     /* assuming discrete log takes about the same time as factoring */
00081     if (n<5)
00082         return 0;
00083     else
00084         return (word32)(2.4 * XPOW((double)n, 1.0/3.0) *
00085                 XPOW(XLOG((double)n), 2.0/3.0) - 5);
00086 }
00087 #endif /* WOLFSSL_DH_CONST*/
00088 
00089 
00090 /* if not using fixed points use DiscreteLogWorkFactor function for unsual size
00091    otherwise round up on size needed */
00092 #ifndef WOLFSSL_DH_CONST
00093     #define WOLFSSL_DH_ROUND(x)
00094 #else
00095     #define WOLFSSL_DH_ROUND(x) \
00096         do {                    \
00097             if (x % 128) {      \
00098                 x &= 0xffffff80;\
00099                 x += 128;       \
00100             }                   \
00101         }                       \
00102         while (0)
00103 #endif
00104 
00105 
00106 static int GeneratePrivate(DhKey* key, WC_RNG* rng, byte* priv, word32* privSz)
00107 {
00108     int ret;
00109     word32 sz = mp_unsigned_bin_size(&key->p);
00110 
00111     /* Table of predetermined values from the operation
00112        2 * DiscreteLogWorkFactor(sz * WOLFSSL_BIT_SIZE) / WOLFSSL_BIT_SIZE + 1
00113        Sizes in table checked against RFC 3526
00114      */
00115     WOLFSSL_DH_ROUND(sz); /* if using fixed points only, then round up */
00116     switch (sz) {
00117         case 128:  sz = 21; break;
00118         case 256:  sz = 29; break;
00119         case 384:  sz = 34; break;
00120         case 512:  sz = 39; break;
00121         case 640:  sz = 42; break;
00122         case 768:  sz = 46; break;
00123         case 896:  sz = 49; break;
00124         case 1024: sz = 52; break;
00125         default:
00126             #ifndef WOLFSSL_DH_CONST
00127                 /* if using floating points and size of p is not in table */
00128                 sz = min(sz, 2 * DiscreteLogWorkFactor(sz * WOLFSSL_BIT_SIZE) /
00129                                            WOLFSSL_BIT_SIZE + 1);
00130                 break;
00131             #else
00132                 return BAD_FUNC_ARG;
00133             #endif
00134     }
00135 
00136     ret = wc_RNG_GenerateBlock(rng, priv, sz);
00137     if (ret != 0)
00138         return ret;
00139 
00140     priv[0] |= 0x0C;
00141 
00142     *privSz = sz;
00143 
00144     return 0;
00145 }
00146 
00147 
00148 static int GeneratePublic(DhKey* key, const byte* priv, word32 privSz,
00149                           byte* pub, word32* pubSz)
00150 {
00151     int ret = 0;
00152 
00153     mp_int x;
00154     mp_int y;
00155 
00156     if (mp_init_multi(&x, &y, 0, 0, 0, 0) != MP_OKAY)
00157         return MP_INIT_E;
00158 
00159     if (mp_read_unsigned_bin(&x, priv, privSz) != MP_OKAY)
00160         ret = MP_READ_E;
00161 
00162     if (ret == 0 && mp_exptmod(&key->g, &x, &key->p, &y) != MP_OKAY)
00163         ret = MP_EXPTMOD_E;
00164 
00165     if (ret == 0 && mp_to_unsigned_bin(&y, pub) != MP_OKAY)
00166         ret = MP_TO_E;
00167 
00168     if (ret == 0)
00169         *pubSz = mp_unsigned_bin_size(&y);
00170 
00171     mp_clear(&y);
00172     mp_clear(&x);
00173 
00174     return ret;
00175 }
00176 
00177 
00178 int wc_DhGenerateKeyPair(DhKey* key, WC_RNG* rng, byte* priv, word32* privSz,
00179                       byte* pub, word32* pubSz)
00180 {
00181     int ret = GeneratePrivate(key, rng, priv, privSz);
00182 
00183     return (ret != 0) ? ret : GeneratePublic(key, priv, *privSz, pub, pubSz);
00184 }
00185 
00186 int wc_DhAgree(DhKey* key, byte* agree, word32* agreeSz, const byte* priv,
00187             word32 privSz, const byte* otherPub, word32 pubSz)
00188 {
00189     int ret = 0;
00190 
00191     mp_int x; 
00192     mp_int y;
00193     mp_int z;
00194 
00195     if (mp_init_multi(&x, &y, &z, 0, 0, 0) != MP_OKAY)
00196         return MP_INIT_E;
00197 
00198     if (mp_read_unsigned_bin(&x, priv, privSz) != MP_OKAY)
00199         ret = MP_READ_E;
00200 
00201     if (ret == 0 && mp_read_unsigned_bin(&y, otherPub, pubSz) != MP_OKAY)
00202         ret = MP_READ_E;
00203 
00204     if (ret == 0 && mp_exptmod(&y, &x, &key->p, &z) != MP_OKAY)
00205         ret = MP_EXPTMOD_E;
00206 
00207     if (ret == 0 && mp_to_unsigned_bin(&z, agree) != MP_OKAY)
00208         ret = MP_TO_E;
00209 
00210     if (ret == 0)
00211         *agreeSz = mp_unsigned_bin_size(&z);
00212 
00213     mp_clear(&z);
00214     mp_clear(&y);
00215     mp_clear(&x);
00216 
00217     return ret;
00218 }
00219 
00220 
00221 /* not in asn anymore since no actual asn types used */
00222 int wc_DhSetKey(DhKey* key, const byte* p, word32 pSz, const byte* g,
00223                 word32 gSz)
00224 {
00225     if (key == NULL || p == NULL || g == NULL || pSz == 0 || gSz == 0)
00226         return BAD_FUNC_ARG;
00227 
00228     /* may have leading 0 */
00229     if (p[0] == 0) {
00230         pSz--; p++;
00231     }
00232 
00233     if (g[0] == 0) {
00234         gSz--; g++;
00235     }
00236 
00237     if (mp_init(&key->p) != MP_OKAY)
00238         return MP_INIT_E;
00239     if (mp_read_unsigned_bin(&key->p, p, pSz) != 0) {
00240         mp_clear(&key->p);
00241         return ASN_DH_KEY_E;
00242     }
00243 
00244     if (mp_init(&key->g) != MP_OKAY) {
00245         mp_clear(&key->p);
00246         return MP_INIT_E;
00247     }
00248     if (mp_read_unsigned_bin(&key->g, g, gSz) != 0) {
00249         mp_clear(&key->g);
00250         mp_clear(&key->p);
00251         return ASN_DH_KEY_E;
00252     }
00253 
00254     return 0;
00255 }
00256 
00257 
00258 #endif /* NO_DH */
00259 
00260