/* dh.c * * Copyright (C) 2006-2011 Sawtooth Consulting Ltd. * * This file is part of CyaSSL. * * CyaSSL is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * CyaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifndef NO_DH #include "ctc_dh.h" #include "error.h" #ifndef USER_MATH_LIB #include #define XPOW(x,y) pow((x),(y)) #define XLOG(x) log((x)) #else /* user's own math lib */ #endif #ifndef min static INLINE word32 min(word32 a, word32 b) { return a > b ? b : a; } #endif /* min */ void InitDhKey(DhKey* key) { /* TomsFastMath doesn't use memory allocation */ #ifndef USE_FAST_MATH key->p.dp = 0; key->g.dp = 0; #endif } void FreeDhKey(DhKey* key) { /* TomsFastMath doesn't use memory allocation */ #ifndef USE_FAST_MATH mp_clear(&key->p); mp_clear(&key->g); #endif } static word32 DiscreteLogWorkFactor(word32 n) { /* assuming discrete log takes about the same time as factoring */ if (n<5) return 0; else return (word32)(2.4 * XPOW((double)n, 1.0/3.0) * XPOW(XLOG((double)n), 2.0/3.0) - 5); } static void GeneratePrivate(DhKey* key, RNG* rng, byte* priv, word32* privSz) { word32 sz = mp_unsigned_bin_size(&key->p); sz = min(sz, 2 * DiscreteLogWorkFactor(sz * BIT_SIZE) / BIT_SIZE + 1); RNG_GenerateBlock(rng, priv, sz); priv[0] |= 0x0C; *privSz = sz; } static int GeneratePublic(DhKey* key, const byte* priv, word32 privSz, byte* pub, word32* pubSz) { int ret = 0; mp_int x; mp_int y; if (mp_init_multi(&x, &y, 0, 0, 0, 0) != MP_OKAY) return MP_INIT_E; if (mp_read_unsigned_bin(&x, priv, privSz) != MP_OKAY) ret = MP_READ_E; if (ret == 0 && mp_exptmod(&key->g, &x, &key->p, &y) != MP_OKAY) ret = MP_EXPTMOD_E; if (ret == 0 && mp_to_unsigned_bin(&y, pub) != MP_OKAY) ret = MP_TO_E; if (ret == 0) *pubSz = mp_unsigned_bin_size(&y); mp_clear(&y); mp_clear(&x); return ret; } int DhGenerateKeyPair(DhKey* key, RNG* rng, byte* priv, word32* privSz, byte* pub, word32* pubSz) { GeneratePrivate(key, rng, priv, privSz); return GeneratePublic(key, priv, *privSz, pub, pubSz); } int DhAgree(DhKey* key, byte* agree, word32* agreeSz, const byte* priv, word32 privSz, const byte* otherPub, word32 pubSz) { int ret = 0; mp_int x; mp_int y; mp_int z; if (mp_init_multi(&x, &y, &z, 0, 0, 0) != MP_OKAY) return MP_INIT_E; if (mp_read_unsigned_bin(&x, priv, privSz) != MP_OKAY) ret = MP_READ_E; if (ret == 0 && mp_read_unsigned_bin(&y, otherPub, pubSz) != MP_OKAY) ret = MP_READ_E; if (ret == 0 && mp_exptmod(&y, &x, &key->p, &z) != MP_OKAY) ret = MP_EXPTMOD_E; if (ret == 0 && mp_to_unsigned_bin(&z, agree) != MP_OKAY) ret = MP_TO_E; if (ret == 0) *agreeSz = mp_unsigned_bin_size(&z); mp_clear(&z); mp_clear(&y); mp_clear(&x); return ret; } #endif /* NO_DH */