From 8843819ce5179d9a03488e4d865b6b5c61858263 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sun, 10 Feb 2013 21:54:15 +0000 Subject: [PATCH] Add back the elliptic curve (ECC) files Signed-off-by: Travis Cross Signed-off-by: Philip Zimmermann --- libs/libzrtp/include/zrtp_config_user.h | 2 +- libs/libzrtp/include/zrtp_ec.h | 89 +++ libs/libzrtp/projects/win/libzrtp.vcproj | 20 +- .../projects/win_ce/libzrtp_wince.vcproj | 28 +- .../projects/win_kernel/MAKEFILE.WIN32 | 11 +- .../projects/win_kernel/MAKEFILE.WIN64 | 11 +- libs/libzrtp/src/zrtp_crypto_ec.c | 469 +++++++++++++ libs/libzrtp/src/zrtp_crypto_ecdh.c | 567 +++++++++++++++ libs/libzrtp/src/zrtp_crypto_ecdsa.c | 646 ++++++++++++++++++ 9 files changed, 1828 insertions(+), 15 deletions(-) create mode 100644 libs/libzrtp/include/zrtp_ec.h create mode 100644 libs/libzrtp/src/zrtp_crypto_ec.c create mode 100644 libs/libzrtp/src/zrtp_crypto_ecdh.c create mode 100644 libs/libzrtp/src/zrtp_crypto_ecdsa.c diff --git a/libs/libzrtp/include/zrtp_config_user.h b/libs/libzrtp/include/zrtp_config_user.h index 352770eaa4..c87a6c790e 100644 --- a/libs/libzrtp/include/zrtp_config_user.h +++ b/libs/libzrtp/include/zrtp_config_user.h @@ -123,7 +123,7 @@ #endif #ifndef ZRTP_ENABLE_EC -#define ZRTP_ENABLE_EC 0 +#define ZRTP_ENABLE_EC 1 #endif #ifndef ZRTP_DEBUG_WITH_PJSIP diff --git a/libs/libzrtp/include/zrtp_ec.h b/libs/libzrtp/include/zrtp_ec.h new file mode 100644 index 0000000000..c4d2f712c6 --- /dev/null +++ b/libs/libzrtp/include/zrtp_ec.h @@ -0,0 +1,89 @@ +/* + * zrtp_crypto_ec.c - Elliptic Curve Low Level Crypto functions for ZRTP. + * NSA Suite B Elliptic Curves from NIST SP 800-56A and FIPS 186-3. + * + * Copyright (c) 2006-2009 Philip R. Zimmermann. All rights reserved. + * This is NOT licensed under the GPL or any other open source license. + * For licensing terms or other information, + * contact: Philip Zimmermann . + * For more contact information, see http://philzimmermann.com + */ + +#ifndef __ZRTP_CRYPTO_EC_H__ +#define __ZRTP_CRYPTO_EC_H__ + +#include "bn.h" + +#include "zrtp_config.h" +#include "zrtp_types.h" +#include "zrtp_error.h" + +#if (defined(ZRTP_ENABLE_EC) && (ZRTP_ENABLE_EC == 1)) + +#define ZRTP_MAXECBITS 521 +#define ZRTP_MAXECWORDS ((ZRTP_MAXECBITS+7)/8) + +typedef struct zrtp_ec_params +{ + unsigned ec_bits; /* # EC bits: 256, 384, 521 */ + uint8_t P_data[ZRTP_MAXECWORDS]; /* curve field prime */ + uint8_t n_data[ZRTP_MAXECWORDS]; /* curve order (# points) */ + uint8_t b_data[ZRTP_MAXECWORDS]; /* curve param, y^3 = x^2 -3x + b */ + uint8_t Gx_data[ZRTP_MAXECWORDS]; /* curve point, x coordinate */ + uint8_t Gy_data[ZRTP_MAXECWORDS]; /* curve point, y coordinate */ +} zrtp_ec_params_t; + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/*============================================================================*/ +/* Elliptic Curve library */ +/*============================================================================*/ + +int zrtp_ecAdd ( struct BigNum *rsltx, + struct BigNum *rslty, + struct BigNum *p1x, + struct BigNum *p1y, + struct BigNum *p2x, + struct BigNum *p2y, + struct BigNum *mod); + +int zrtp_ecMul ( struct BigNum *rsltx, + struct BigNum *rslty, + struct BigNum *mult, + struct BigNum *basex, + struct BigNum *basey, + struct BigNum *mod); + +zrtp_status_t zrtp_ec_random_point( zrtp_global_t *zrtp, + struct BigNum *P, + struct BigNum *n, + struct BigNum *Gx, + struct BigNum *Gy, + struct BigNum *pkx, + struct BigNum *pky, + struct BigNum *sv, + uint8_t *test_sv_data, + size_t test_sv_data_len); + +extern zrtp_status_t zrtp_ec_init_params(struct zrtp_ec_params *params, uint32_t bits ); + + +/* Useful bignum utility functions not defined in bignum library */ +int bnAddMod_ (struct BigNum *rslt, struct BigNum *n1, struct BigNum *mod); +int bnAddQMod_ (struct BigNum *rslt, unsigned n1, struct BigNum *mod); +int bnSubMod_ (struct BigNum *rslt, struct BigNum *n1, struct BigNum *mod); +int bnSubQMod_ (struct BigNum *rslt, unsigned n1, struct BigNum *mod); +int bnMulMod_ (struct BigNum *rslt, struct BigNum *n1, struct BigNum *n2, struct BigNum *mod); +int bnMulQMod_ (struct BigNum *rslt, struct BigNum *n1, unsigned n2, struct BigNum *mod); +int bnSquareMod_ (struct BigNum *rslt, struct BigNum *n1, struct BigNum *mod); + +#if defined(__cplusplus) +} +#endif + +#endif /*ZRTP_ENABLE_EC*/ + +#endif /* __ZRTP_CRYPTO_EC_H__ */ diff --git a/libs/libzrtp/projects/win/libzrtp.vcproj b/libs/libzrtp/projects/win/libzrtp.vcproj index 38fd62fbb4..485bd2f02d 100644 --- a/libs/libzrtp/projects/win/libzrtp.vcproj +++ b/libs/libzrtp/projects/win/libzrtp.vcproj @@ -43,7 +43,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="../../include;../../third_party/bnlib;../../third_party/bgaes;../../test/include" - PreprocessorDefinitions="WIN32;_DEBUG;_LIB;HAVE_CONFIG_H=1;ZRTP_ENABLE_EC=0" + PreprocessorDefinitions="WIN32;_DEBUG;_LIB;HAVE_CONFIG_H=1;ZRTP_ENABLE_EC=1" MinimalRebuild="true" BasicRuntimeChecks="3" RuntimeLibrary="1" @@ -109,7 +109,7 @@ + + @@ -244,6 +248,10 @@ RelativePath="..\..\include\zrtp_utils.h" > + + + + + + diff --git a/libs/libzrtp/projects/win_ce/libzrtp_wince.vcproj b/libs/libzrtp/projects/win_ce/libzrtp_wince.vcproj index d16b5559d6..cbe4fb4389 100644 --- a/libs/libzrtp/projects/win_ce/libzrtp_wince.vcproj +++ b/libs/libzrtp/projects/win_ce/libzrtp_wince.vcproj @@ -52,7 +52,7 @@ ExecutionBucket="7" Optimization="0" AdditionalIncludeDirectories="../../third_party/bnlib;../../include;../../include/enterprise;../../third_party/bgaes;../../test/include" - PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;DEBUG;_LIB;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE;ZRTP_ENABLE_EC=0" + PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;DEBUG;_LIB;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE;ZRTP_ENABLE_EC=1" MinimalRebuild="true" RuntimeLibrary="1" StructMemberAlignment="0" @@ -136,7 +136,7 @@ ExecutionBucket="7" Optimization="0" AdditionalIncludeDirectories="../../third_party/bnlib;../../include;../../include/enterprise;../../third_party/bgaes;../../test/include" - PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;DEBUG;_LIB;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;ZRTP_ENABLE_EC=0" + PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;DEBUG;_LIB;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;ZRTP_ENABLE_EC=1" MinimalRebuild="true" RuntimeLibrary="1" BufferSecurityCheck="false" @@ -219,7 +219,7 @@ ExecutionBucket="7" Optimization="2" AdditionalIncludeDirectories="../../third_party/bnlib;../../include;../../include/enterprise;../../third_party/bgaes;../../test/include" - PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;_LIB;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;ZRTP_ENABLE_EC=0" + PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;_LIB;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;ZRTP_ENABLE_EC=1" RuntimeLibrary="0" BufferSecurityCheck="false" UsePrecompiledHeader="0" @@ -300,7 +300,7 @@ ExecutionBucket="7" Optimization="2" AdditionalIncludeDirectories="../../third_party/bnlib;../../include;../../include/enterprise;../../third_party/bgaes;../../test/include" - PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;_LIB;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE;ZRTP_ENABLE_EC=0" + PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;_LIB;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE;ZRTP_ENABLE_EC=1" RuntimeLibrary="0" BufferSecurityCheck="false" UsePrecompiledHeader="0" @@ -382,6 +382,10 @@ RelativePath="..\..\include\zrtp_crypto.h" > + + @@ -462,6 +466,18 @@ RelativePath="..\..\src\zrtp_crypto_atl.c" > + + + + + + @@ -482,6 +498,10 @@ RelativePath="..\..\src\zrtp_engine.c" > + + diff --git a/libs/libzrtp/projects/win_kernel/MAKEFILE.WIN32 b/libs/libzrtp/projects/win_kernel/MAKEFILE.WIN32 index e44b955933..2b15ded64a 100644 --- a/libs/libzrtp/projects/win_kernel/MAKEFILE.WIN32 +++ b/libs/libzrtp/projects/win_kernel/MAKEFILE.WIN32 @@ -43,6 +43,9 @@ protocol = \ ../../src/zrtp_crypto_sas.obj \ ../../src/zrtp_datatypes.obj \ ../../src/zrtp_engine.obj \ + ../../src/enterprise/zrtp_engine_driven.obj \ + ../../src/enterprise/zrtp_crypto_ec.obj \ + ../../src/enterprise/zrtp_crypto_ecdh.obj \ ../../src/zrtp_iface_sys.obj \ ../../src/zrtp_initiator.obj \ ../../src/zrtp_legal.obj \ @@ -71,13 +74,13 @@ OBJECTS = $(bnlib) $(protocol) $(bgaes) # Debug -OUT_DIR = debug.km +OUT_DIR = debug_ec.km DEFINES_D = -D_X86_=1 -Di386=1 -DSTD_CALL -DCONDITION_HANDLING=1 \ -DNT_UP=1 -DNT_INST=0 -DWIN32=100 -D_NT1X_=100 \ -DWINNT=1 -D_WIN32_WINNT=0x0500 -DWIN32_LEAN_AND_MEAN=1 -DDBG=1 -D_DEBUG -DDEBUG -DDEVL=1 \ -DFPO=0 -D_DLL=1 -D_IDWBUILD -DRDRDBG -DSRVDBG -DDBG_MESSAGES=1 \ --D_UNICODE -DLITTLE_ENDIAN -DZRTP_USE_ENTERPRISE=0 +-D_UNICODE -DLITTLE_ENDIAN -DZRTP_USE_ENTERPRISE=1 CFLAGS_D = $(DEFINES_D) -Zel -Zp8 -Gy -cbstring -Gz -QIfdiv- -QIf -Gi- -Gm- -GX- \ -GR- -GF -FI$(DDK)\inc\$(OS)\warning.h -Z7 -Od -Oi -Oy- -W3 @@ -86,13 +89,13 @@ CFLAGS_D = $(DEFINES_D) -Zel -Zp8 -Gy -cbstring -Gz -QIfdiv- -QIf -Gi- -Gm- -GX- # Release -OUT_DIR = release.km +OUT_DIR = release_ec.km DEFINES_D = -D_X86_=1 -Di386=1 -DSTD_CALL -DCONDITION_HANDLING=1 \ -DNT_UP=1 -DNO_DISK_ACCESS -DNT_INST=0 -DWIN32=100 -D_NT1X_=100 \ -DWINNT=1 -D_WIN32_WINNT=0x0500 -DWIN32_LEAN_AND_MEAN=1 -DDEVL=1 \ -DFPO=1 -DNDEBUG -D_DLL=1 -D_IDWBUILD -D_UNICODE \ --DLITTLE_ENDIAN -DZRTP_USE_ENTERPRISE=0 +-DLITTLE_ENDIAN -DZRTP_USE_ENTERPRISE=1 CFLAGS_D = $(DEFINES_D) -Zel -Zp8 -Gy -cbstring -Gz -QIfdiv- -QIf -Gi- -Gm- -GX- \ -GR- -GF -Oxs -Oy -FI$(DDK)\inc\$(OS)\warning.h -W3 -FAcs -Z7 diff --git a/libs/libzrtp/projects/win_kernel/MAKEFILE.WIN64 b/libs/libzrtp/projects/win_kernel/MAKEFILE.WIN64 index 52a1cb7e4d..ccc2a73a17 100644 --- a/libs/libzrtp/projects/win_kernel/MAKEFILE.WIN64 +++ b/libs/libzrtp/projects/win_kernel/MAKEFILE.WIN64 @@ -44,6 +44,9 @@ protocol = \ ../../src/zrtp_crypto_sas.obj \ ../../src/zrtp_datatypes.obj \ ../../src/zrtp_engine.obj \ + ../../src/enterprise/zrtp_engine_driven.obj \ + ../../src/enterprise/zrtp_crypto_ec.obj \ + ../../src/enterprise/zrtp_crypto_ecdh.obj \ ../../src/zrtp_iface_sys.obj \ ../../src/zrtp_initiator.obj \ ../../src/zrtp_legal.obj \ @@ -72,14 +75,14 @@ OBJECTS = $(bnlib) $(protocol) $(bgaes) # Debug -OUT_DIR = debug64.km +OUT_DIR = debug64_ec.km DEFINES_D = -DWIN64=1 -D_WIN64=1 -D_AMD64_=1 -D_M_AMD64 -D_WINDOWS \ -DSTD_CALL -DCONDITION_HANDLING=1 \ -DNT_UP=1 -DNT_INST=0 -D_NT1X_=100 \ -DWINNT=1 -D_WIN32_WINNT=0x0500 -DWIN32_LEAN_AND_MEAN=1 -DDBG=1 -D_DEBUG -DDEBUG -DDEVL=1 \ -DFPO=0 -D_DLL=1 -D_IDWBUILD -DRDRDBG -DSRVDBG -DDBG_MESSAGES=1 \ --D_UNICODE -DLITTLE_ENDIAN -DZRTP_USE_ENTERPRISE=0 +-D_UNICODE -DLITTLE_ENDIAN -DZRTP_USE_ENTERPRISE=1 CFLAGS_D = $(DEFINES_D) -Zp8 -Gy -cbstring -Gz -Gm- -EHs-c- \ -GR- -GF -FI$(DDK)\inc\$(OS)\warning.h -Z7 -Od -Oi -Oy- -W3 @@ -88,14 +91,14 @@ CFLAGS_D = $(DEFINES_D) -Zp8 -Gy -cbstring -Gz -Gm- -EHs-c- \ # Release -OUT_DIR = release64.km +OUT_DIR = release64_ec.km DEFINES_D = -DWIN64=1 -D_WIN64=1 -D_AMD64_=1 -D_M_AMD64 -D_WINDOWS \ -DSTD_CALL -DCONDITION_HANDLING=1 \ -DNT_UP=1 -DNO_DISK_ACCESS -DNT_INST=0 -DWIN32=100 -D_NT1X_=100 \ -DWINNT=1 -D_WIN32_WINNT=0x0500 -DWIN32_LEAN_AND_MEAN=1 -DDEVL=1 \ -DFPO=1 -DNDEBUG -D_DLL=1 -D_IDWBUILD -D_UNICODE \ --DLITTLE_ENDIAN -DZRTP_USE_ENTERPRISE=0 +-DLITTLE_ENDIAN -DZRTP_USE_ENTERPRISE=1 CFLAGS_D = $(DEFINES_D) -Zel -Zp8 -Gy -cbstring -Gz -QIfdiv- -QIf -Gi- -Gm- -GX- \ -GR- -GF -Oxs -Oy -FI$(DDK)\inc\$(OS)\warning.h -W3 -FAcs -Z7 diff --git a/libs/libzrtp/src/zrtp_crypto_ec.c b/libs/libzrtp/src/zrtp_crypto_ec.c new file mode 100644 index 0000000000..818081c74d --- /dev/null +++ b/libs/libzrtp/src/zrtp_crypto_ec.c @@ -0,0 +1,469 @@ +/* + * zrtp_crypto_ec.c - Elliptic Curve Low Level Crypto functions for ZRTP. + * NSA Suite B Elliptic Curves from NIST SP 800-56A and FIPS 186-3. + * + * Copyright (c) 2006-2009 Philip R. Zimmermann. All rights reserved. + * This is NOT licensed under the GPL or any other open source license. + * For licensing terms or other information, + * contact: Philip Zimmermann . + * For more contact information, see http://philzimmermann.com + */ + +#include "zrtp.h" + +#if (defined(ZRTP_ENABLE_EC) && (ZRTP_ENABLE_EC == 1)) + +/* Size of extra random data to approximate a uniform distribution mod n */ +#define UNIFORMBYTES 8 + + +/*============================================================================*/ +/* Bignum Shorthand Functions */ +/*============================================================================*/ + +int bnAddMod_ (struct BigNum *rslt, struct BigNum *n1, struct BigNum *mod) +{ + bnAdd (rslt, n1); + if (bnCmp (rslt, mod) >= 0) { + bnSub (rslt, mod); + } + return 0; +} + +int bnAddQMod_ (struct BigNum *rslt, unsigned n1, struct BigNum *mod) +{ + bnAddQ (rslt, n1); + if (bnCmp (rslt, mod) >= 0) { + bnSub (rslt, mod); + } + return 0; +} + +int bnSubMod_ (struct BigNum *rslt, struct BigNum *n1, struct BigNum *mod) +{ + if (bnCmp (rslt, n1) < 0) { + bnAdd (rslt, mod); + } + bnSub (rslt, n1); + return 0; +} + +int bnSubQMod_ (struct BigNum *rslt, unsigned n1, struct BigNum *mod) +{ + if (bnCmpQ (rslt, n1) < 0) { + bnAdd (rslt, mod); + } + bnSubQ (rslt, n1); + return 0; +} + +int bnMulMod_ (struct BigNum *rslt, struct BigNum *n1, struct BigNum *n2, struct BigNum *mod) +{ + bnMul (rslt, n1, n2); + bnMod (rslt, rslt, mod); + return 0; +} + +int bnMulQMod_ (struct BigNum *rslt, struct BigNum *n1, unsigned n2, struct BigNum *mod) +{ + bnMulQ (rslt, n1, n2); + bnMod (rslt, rslt, mod); + return 0; +} + +int bnSquareMod_ (struct BigNum *rslt, struct BigNum *n1, struct BigNum *mod) +{ + bnSquare (rslt, n1); + bnMod (rslt, rslt, mod); + return 0; +} + + +/*============================================================================*/ +/* Elliptic Curve arithmetic */ +/*============================================================================*/ + +/* Add two elliptic curve points. Any of them may be the same object. */ +int zrtp_ecAdd ( struct BigNum *rsltx, struct BigNum *rslty, + struct BigNum *p1x, struct BigNum *p1y, + struct BigNum *p2x, struct BigNum *p2y, struct BigNum *mod) +{ + struct BigNum trsltx, trslty; + struct BigNum t1, gam; + struct BigNum bnzero; + + bnBegin (&bnzero); + + /* Check for an operand being zero */ + if (bnCmp (p1x, &bnzero) == 0 && bnCmp (p1y, &bnzero) == 0) { + bnCopy (rsltx, p2x); bnCopy (rslty, p2y); + bnEnd (&bnzero); + return 0; + } + if (bnCmp (p2x, &bnzero) == 0 && bnCmp (p2y, &bnzero) == 0) { + bnCopy (rsltx, p1x); bnCopy (rslty, p1y); + bnEnd (&bnzero); + return 0; + } + + /* Check if p1 == -p2 and return 0 if so */ + if (bnCmp (p1x, p2x) == 0) { + struct BigNum tsum; + bnBegin (&tsum); + bnCopy (&tsum, p1x); + bnAddMod_ (&tsum, p2x, mod); + if (bnCmp (&tsum, &bnzero) == 0) { + bnSetQ (rsltx, 0); bnSetQ (rslty, 0); + bnEnd (&tsum); + bnEnd (&bnzero); + return 0; + } + bnEnd (&tsum); + } + + bnBegin (&t1); + bnBegin (&gam); + bnBegin (&trsltx); + bnBegin (&trslty); + + /* Check for doubling, different formula for gamma */ + if (bnCmp (p1x, p2x) == 0 && bnCmp (p1y, p2y) == 0) { + bnCopy (&t1, p1y); + bnAddMod_ (&t1, p1y, mod); + bnInv (&t1, &t1, mod); + bnSquareMod_ (&gam, p1x, mod); + bnMulQMod_ (&gam, &gam, 3, mod); + bnSubQMod_ (&gam, 3, mod); + bnMulMod_ (&gam, &gam, &t1, mod); + } else { + bnCopy (&t1, p2x); + bnSubMod_ (&t1, p1x, mod); + bnInv (&t1, &t1, mod); + bnCopy (&gam, p2y); + bnSubMod_ (&gam, p1y, mod); + bnMulMod_ (&gam, &gam, &t1, mod); + } + + bnSquareMod_ (&trsltx, &gam, mod); + bnSubMod_ (&trsltx, p1x, mod); + bnSubMod_ (&trsltx, p2x, mod); + + bnCopy (&trslty, p1x); + bnSubMod_ (&trslty, &trsltx, mod); + bnMulMod_ (&trslty, &trslty, &gam, mod); + bnSubMod_ (&trslty, p1y, mod); + + bnCopy (rsltx, &trsltx); + bnCopy (rslty, &trslty); + + bnEnd (&t1); + bnEnd (&gam); + bnEnd (&trsltx); + bnEnd (&trslty); + bnEnd (&bnzero); + + return 0; +} + +int zrtp_ecMul ( struct BigNum *rsltx, struct BigNum *rslty, struct BigNum *mult, + struct BigNum *basex, struct BigNum *basey, struct BigNum *mod) +{ + struct BigNum bnzero; + struct BigNum tbasex, tbasey; + struct BigNum trsltx, trslty; + struct BigNum tmult; + + bnBegin (&bnzero); + bnBegin (&tbasex); + bnBegin (&tbasey); + bnBegin (&trsltx); + bnBegin (&trslty); + bnBegin (&tmult); + + /* Initialize result to 0 before additions */ + bnSetQ (&trsltx, 0); + bnSetQ (&trslty, 0); + /* Make copies of base and multiplier */ + bnCopy (&tbasex, basex); + bnCopy (&tbasey, basey); + bnCopy (&tmult, mult); + while (bnCmp (&tmult, &bnzero) > 0) { + /* Test lsb of mult */ + unsigned lsw = bnLSWord (&tmult); + if (lsw & 1) { + /* Add base to result */ + zrtp_ecAdd (&trsltx, &trslty, &trsltx, &trslty, &tbasex, &tbasey, mod); + } + /* Double the base */ + zrtp_ecAdd (&tbasex, &tbasey, &tbasex, &tbasey, &tbasex, &tbasey, mod); + /* Shift multiplier right */ + bnRShift (&tmult, 1); + } + + bnCopy (rsltx, &trsltx); + bnCopy (rslty, &trslty); + + bnEnd (&bnzero); + bnEnd (&tbasex); + bnEnd (&tbasey); + bnEnd (&trsltx); + bnEnd (&trslty); + bnEnd (&tmult); + return 0; +} + + + +/*----------------------------------------------------------------------------*/ +/* Choose a random point on the elliptic curve. */ +/* Provision is made to use a given point from test vectors. */ +/* pkx and pky are the output point, sv is output discrete log */ +/* Input base is Gx, Gy; curve field modulus is P; curve order is n. */ +/*----------------------------------------------------------------------------*/ +zrtp_status_t zrtp_ec_random_point( zrtp_global_t *zrtp, + struct BigNum *P, + struct BigNum *n, + struct BigNum *Gx, + struct BigNum *Gy, + struct BigNum *pkx, + struct BigNum *pky, + struct BigNum *sv, + uint8_t *test_sv_data, + size_t test_sv_data_len) +{ + zrtp_status_t s = zrtp_status_fail; + unsigned char* buffer = zrtp_sys_alloc(sizeof(zrtp_uchar1024_t)); + + if (!buffer) { + return zrtp_status_alloc_fail; + } + zrtp_memset(buffer, 0, sizeof(zrtp_uchar1024_t)); + + do + { + if (test_sv_data_len != 0) { + /* Force certain secret value */ + if (bnBytes(P) != test_sv_data_len) { + break; + } + zrtp_memcpy(buffer+UNIFORMBYTES, test_sv_data, test_sv_data_len); + } else { + /* Choose random value, larger than needed so it will be uniform */ + if (bnBytes(P)+UNIFORMBYTES != (uint32_t)zrtp_randstr(zrtp, buffer, bnBytes(P)+UNIFORMBYTES)) { + break; /* if we can't generate random string - fail initialization */ + } + } + + bnInsertBigBytes(sv, (const unsigned char *)buffer, 0, bnBytes(P)+UNIFORMBYTES); + bnMod(sv, sv, n); + zrtp_ecMul(pkx, pky, sv, Gx, Gy, P); + + s = zrtp_status_ok; + } while (0); + + if (buffer) { + zrtp_sys_free(buffer); + } + + return s; +} + + +/*============================================================================*/ +/* Curve parameters */ +/*============================================================================*/ + +uint8_t P_256_data[] = +{ + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +uint8_t n_256_data[] = +{ + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84, + 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51 +}; + +uint8_t b_256_data[] = +{ + 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, + 0xb3, 0xeb, 0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc, + 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, 0xb0, 0xf6, + 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b +}; + +uint8_t Gx_256_data[] = +{ + 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, + 0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, + 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, + 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96 +}; + +uint8_t Gy_256_data[] = +{ + 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, + 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, + 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, + 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5 +}; + + + +uint8_t P_384_data[] = +{ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF +}; + +uint8_t n_384_data[] = +{ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF, + 0x58, 0x1A, 0x0D, 0xB2, 0x48, 0xB0, 0xA7, 0x7A, + 0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73 +}; + +uint8_t b_384_data[] = +{ + 0xb3, 0x31, 0x2f, 0xa7, 0xe2, 0x3e, 0xe7, 0xe4, + 0x98, 0x8e, 0x05, 0x6b, 0xe3, 0xf8, 0x2d, 0x19, + 0x18, 0x1d, 0x9c, 0x6e, 0xfe, 0x81, 0x41, 0x12, + 0x03, 0x14, 0x08, 0x8f, 0x50, 0x13, 0x87, 0x5a, + 0xc6, 0x56, 0x39, 0x8d, 0x8a, 0x2e, 0xd1, 0x9d, + 0x2a, 0x85, 0xc8, 0xed, 0xd3, 0xec, 0x2a, 0xef +}; + +uint8_t Gx_384_data[] = +{ + 0xaa, 0x87, 0xca, 0x22, 0xbe, 0x8b, 0x05, 0x37, + 0x8e, 0xb1, 0xc7, 0x1e, 0xf3, 0x20, 0xad, 0x74, + 0x6e, 0x1d, 0x3b, 0x62, 0x8b, 0xa7, 0x9b, 0x98, + 0x59, 0xf7, 0x41, 0xe0, 0x82, 0x54, 0x2a, 0x38, + 0x55, 0x02, 0xf2, 0x5d, 0xbf, 0x55, 0x29, 0x6c, + 0x3a, 0x54, 0x5e, 0x38, 0x72, 0x76, 0x0a, 0xb7 +}; + +uint8_t Gy_384_data[] = +{ + 0x36, 0x17, 0xde, 0x4a, 0x96, 0x26, 0x2c, 0x6f, + 0x5d, 0x9e, 0x98, 0xbf, 0x92, 0x92, 0xdc, 0x29, + 0xf8, 0xf4, 0x1d, 0xbd, 0x28, 0x9a, 0x14, 0x7c, + 0xe9, 0xda, 0x31, 0x13, 0xb5, 0xf0, 0xb8, 0xc0, + 0x0a, 0x60, 0xb1, 0xce, 0x1d, 0x7e, 0x81, 0x9d, + 0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0x0e, 0x5f +}; + + +uint8_t P_521_data[] = +{ + 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF +}; + +uint8_t n_521_data[] = +{ + 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFA, 0x51, 0x86, 0x87, 0x83, 0xBF, 0x2F, + 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09, + 0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, + 0x47, 0xAE, 0xBB, 0x6F, 0xB7, 0x1E, 0x91, 0x38, + 0x64, 0x09 +}; + +uint8_t b_521_data[] = +{ + 0x00, 0x51, 0x95, 0x3e, 0xb9, 0x61, 0x8e, 0x1c, + 0x9a, 0x1f, 0x92, 0x9a, 0x21, 0xa0, 0xb6, 0x85, + 0x40, 0xee, 0xa2, 0xda, 0x72, 0x5b, 0x99, 0xb3, + 0x15, 0xf3, 0xb8, 0xb4, 0x89, 0x91, 0x8e, 0xf1, + 0x09, 0xe1, 0x56, 0x19, 0x39, 0x51, 0xec, 0x7e, + 0x93, 0x7b, 0x16, 0x52, 0xc0, 0xbd, 0x3b, 0xb1, + 0xbf, 0x07, 0x35, 0x73, 0xdf, 0x88, 0x3d, 0x2c, + 0x34, 0xf1, 0xef, 0x45, 0x1f, 0xd4, 0x6b, 0x50, + 0x3f, 0x00 +}; + +uint8_t Gx_521_data[] = +{ + 0x00, 0xc6, 0x85, 0x8e, 0x06, 0xb7, 0x04, 0x04, + 0xe9, 0xcd, 0x9e, 0x3e, 0xcb, 0x66, 0x23, 0x95, + 0xb4, 0x42, 0x9c, 0x64, 0x81, 0x39, 0x05, 0x3f, + 0xb5, 0x21, 0xf8, 0x28, 0xaf, 0x60, 0x6b, 0x4d, + 0x3d, 0xba, 0xa1, 0x4b, 0x5e, 0x77, 0xef, 0xe7, + 0x59, 0x28, 0xfe, 0x1d, 0xc1, 0x27, 0xa2, 0xff, + 0xa8, 0xde, 0x33, 0x48, 0xb3, 0xc1, 0x85, 0x6a, + 0x42, 0x9b, 0xf9, 0x7e, 0x7e, 0x31, 0xc2, 0xe5, + 0xbd, 0x66 +}; + +uint8_t Gy_521_data[] = +{ + 0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, + 0xc0, 0x04, 0x5c, 0x8a, 0x5f, 0xb4, 0x2c, 0x7d, + 0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b, + 0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, + 0x66, 0x2c, 0x97, 0xee, 0x72, 0x99, 0x5e, 0xf4, + 0x26, 0x40, 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad, + 0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, + 0xc2, 0x40, 0x88, 0xbe, 0x94, 0x76, 0x9f, 0xd1, + 0x66, 0x50 +}; + +/*----------------------------------------------------------------------------*/ +/* Initialize the curve parameters struct */ +zrtp_status_t zrtp_ec_init_params( struct zrtp_ec_params *params, uint32_t bits ) +{ + unsigned ec_bytes = (bits+7) / 8; + params->ec_bits = bits; + switch (bits) { + case 256: + zrtp_memcpy (params->P_data, P_256_data, ec_bytes); + zrtp_memcpy (params->n_data, n_256_data, ec_bytes); + zrtp_memcpy (params->b_data, b_256_data, ec_bytes); + zrtp_memcpy (params->Gx_data, Gx_256_data, ec_bytes); + zrtp_memcpy (params->Gy_data, Gy_256_data, ec_bytes); + break; + case 384: + zrtp_memcpy (params->P_data, P_384_data, ec_bytes); + zrtp_memcpy (params->n_data, n_384_data, ec_bytes); + zrtp_memcpy (params->b_data, b_384_data, ec_bytes); + zrtp_memcpy (params->Gx_data, Gx_384_data, ec_bytes); + zrtp_memcpy (params->Gy_data, Gy_384_data, ec_bytes); + break; + case 521: + zrtp_memcpy (params->P_data, P_521_data, ec_bytes); + zrtp_memcpy (params->n_data, n_521_data, ec_bytes); + zrtp_memcpy (params->b_data, b_521_data, ec_bytes); + zrtp_memcpy (params->Gx_data, Gx_521_data, ec_bytes); + zrtp_memcpy (params->Gy_data, Gy_521_data, ec_bytes); + break; + default: + return zrtp_status_bad_param; + } + + return zrtp_status_ok; +} + +#endif /*ZRTP_ENABLE_EC*/ diff --git a/libs/libzrtp/src/zrtp_crypto_ecdh.c b/libs/libzrtp/src/zrtp_crypto_ecdh.c new file mode 100644 index 0000000000..b78ecb1439 --- /dev/null +++ b/libs/libzrtp/src/zrtp_crypto_ecdh.c @@ -0,0 +1,567 @@ +/* + * zrtp_crypto_ecdh.c - Elliptic Curve Diffie Hellman functions for ZRTP. + * NSA Suite B Elliptic Curves from NIST SP 800-56A and FIPS 186-3. + * + * Copyright (c) 2006-2009 Philip R. Zimmermann. All rights reserved. + * This is NOT licensed under the GPL or any other open source license. + * For licensing terms or other information, + * contact: Philip Zimmermann . + * For more contact information, see http://philzimmermann.com + */ + +#include "zrtp.h" + + +#if (defined(ZRTP_ENABLE_EC) && (ZRTP_ENABLE_EC == 1)) + +#define _ZTU_ "zrtp ecdh" + +static unsigned get_pbits(zrtp_pk_scheme_t *self) +{ + switch (self->base.id) { + case ZRTP_PKTYPE_EC256P: + return 256; + break; + case ZRTP_PKTYPE_EC384P: + return 384; + break; + case ZRTP_PKTYPE_EC521P: + return 521; + break; + default: + return 0; + } +} + +/*============================================================================*/ +/* Shared Elliptic Curve functions */ +/* */ +/* The Elliptic Curve DH algorithm and key generation is from */ +/* NIST SP 800-56A. The curves used are from NSA Suite B, which */ +/* uses the same curves as ECDSA defined by FIPS 186-3, and are */ +/* also defined in RFC 4753, sections 3.1 through 3.3. */ +/* The validation procedures are from NIST SP 800-56A section 5.6.2.6, */ +/* method 3, ECC Partial Validation. */ +/*============================================================================*/ + + +/*----------------------------------------------------------------------------*/ +static zrtp_status_t zrtp_ecdh_init(void *s) { + return zrtp_status_ok; +} + +static zrtp_status_t zrtp_ecdh_free(void *s) { + return zrtp_status_ok; +} + + +/*----------------------------------------------------------------------------*/ +/* Return dh_cc->pv holding public value and dh_cc->sv holding secret value */ +/* The public value is an elliptic curve point encoded as the x part shifted */ +/* left Pbits bits and or'd with the y part. */ +/*----------------------------------------------------------------------------*/ +static zrtp_status_t zrtp_ecdh_initialize( zrtp_pk_scheme_t *self, + zrtp_dh_crypto_context_t *dh_cc) +{ + zrtp_status_t s = zrtp_status_fail; + struct BigNum P, Gx, Gy, n; + struct BigNum pkx, pky; + unsigned ec_bytes = 0; + unsigned pbits = 0; + struct zrtp_ec_params ec_params; + zrtp_time_t start_ts = zrtp_time_now(); + + if (!self || !dh_cc) { + return zrtp_status_bad_param; + } + + pbits = get_pbits(self); + if (!pbits) { + return zrtp_status_bad_param; + } + + zrtp_ec_init_params(&ec_params, pbits); + + ec_bytes = (ec_params.ec_bits+7) / 8; + + bnBegin(&P); + bnInsertBigBytes(&P, ec_params.P_data, 0, ec_bytes ); + bnBegin(&Gx); + bnInsertBigBytes(&Gx, ec_params.Gx_data, 0, ec_bytes ); + bnBegin(&Gy); + bnInsertBigBytes(&Gy, ec_params.Gy_data, 0, ec_bytes ); + bnBegin(&n); + bnInsertBigBytes(&n, ec_params.n_data, 0, ec_bytes ); + + bnBegin(&pkx); + bnBegin(&pky); + bnBegin(&dh_cc->sv); + s = zrtp_ec_random_point( self->base.zrtp, &P, &n, &Gx, &Gy, + &pkx, &pky, &dh_cc->sv, + NULL, 0); + + if (zrtp_status_ok == s) + { + bnBegin(&dh_cc->pv); + bnCopy (&dh_cc->pv, &pkx); + bnLShift (&dh_cc->pv, pbits); + bnAdd (&dh_cc->pv, &pky); + } + + bnEnd (&pkx); + bnEnd (&pky); + bnEnd (&P); + bnEnd (&Gx); + bnEnd (&Gy); + bnEnd (&n); + + ZRTP_LOG(1,(_ZTU_,"\tDH TEST: zrtp_ecdh_initialize() for %.4s was executed by %llums.\n", self->base.type, zrtp_time_now()-start_ts)); + return s; +} + + +/*----------------------------------------------------------------------------*/ +/* Compute the shared dhresult as the X coordinate of the EC point. */ +/*----------------------------------------------------------------------------*/ +static zrtp_status_t zrtp_ecdh_compute( zrtp_pk_scheme_t *self, + zrtp_dh_crypto_context_t *dh_cc, + struct BigNum *dhresult, + struct BigNum *pv) +{ + struct BigNum P; + struct BigNum pkx, pky, rsltx, rslty; + unsigned ec_bytes = 0; + unsigned pbits = 0; + struct zrtp_ec_params ec_params; + zrtp_time_t start_ts = zrtp_time_now(); + + if (!self || !dh_cc || !dhresult || !pv) { + return zrtp_status_bad_param; + } + + pbits = get_pbits(self); + if (!pbits) { + return zrtp_status_bad_param; + } + + zrtp_ec_init_params(&ec_params, pbits); + + ec_bytes = (ec_params.ec_bits+7) / 8; + + bnBegin(&P); + bnInsertBigBytes( &P, ec_params.P_data, 0, ec_bytes ); + + bnBegin (&pkx); + bnBegin (&pky); + bnBegin (&rsltx); + bnBegin (&rslty); + + bnSetQ (&pkx, 1); + bnLShift (&pkx, pbits); + bnMod (&pky, pv, &pkx); + bnCopy (&pkx, pv); + bnRShift (&pkx, pbits); + + zrtp_ecMul (&rsltx, &rslty, &dh_cc->sv, &pkx, &pky, &P); + bnCopy (dhresult, &rsltx); + + bnEnd (&pkx); + bnEnd (&pky); + bnEnd (&rsltx); + bnEnd (&rslty); + bnEnd (&P); + + ZRTP_LOG(1,(_ZTU_,"\tDH TEST: zrtp_ecdh_compute() for %.4s was executed by %llums.\n", self->base.type, zrtp_time_now()-start_ts)); + return zrtp_status_ok; +} + +/*----------------------------------------------------------------------------*/ +/* ECC Partial Validation per NIST SP800-56A section 5.6.2.6 */ +/*----------------------------------------------------------------------------*/ +static zrtp_status_t zrtp_ecdh_validate( zrtp_pk_scheme_t *self, + struct BigNum *pv) +{ + zrtp_status_t s = zrtp_status_fail; + struct BigNum P, b; + struct BigNum t1, t2; + struct BigNum pkx, pky, bnzero; + unsigned ec_bytes = 0; + unsigned pbits = 0; + struct zrtp_ec_params ec_params; + zrtp_time_t start_ts = zrtp_time_now(); + + if (!self || !pv) { + return zrtp_status_bad_param; + } + + pbits = get_pbits(self); + if (!pbits) { + return zrtp_status_bad_param; + } + + zrtp_ec_init_params(&ec_params, pbits); + + ec_bytes = (ec_params.ec_bits+7) / 8; + + bnBegin(&P); + bnInsertBigBytes( &P, ec_params.P_data, 0, ec_bytes ); + bnBegin(&b); + bnInsertBigBytes( &b, ec_params.b_data, 0, ec_bytes ); + + bnBegin (&t1); + bnBegin (&t2); + bnBegin (&pkx); + bnBegin (&pky); + bnBegin (&bnzero); + + bnSetQ (&pkx, 1); + bnLShift (&pkx, pbits); + bnMod (&pky, pv, &pkx); + bnCopy (&pkx, pv); + bnRShift (&pkx, pbits); + + do{ + /* Represent point at infinity by (0, 0), make sure it's not that */ + if (bnCmp (&pkx, &bnzero) == 0 && bnCmp (&pky, &bnzero) == 0) { + break; + } + /* Check coordinates within range */ + if (bnCmp (&pkx, &bnzero) < 0 || bnCmp (&pkx, &P) >= 0) { + break; + } + if (bnCmp (&pky, &bnzero) < 0 || bnCmp (&pky, &P) >= 0) { + break; + } + + /* Check that point satisfies EC equation y^2 = x^3 - 3x + b, mod P */ + bnSquareMod_ (&t1, &pky, &P); + bnSquareMod_ (&t2, &pkx, &P); + bnSubQMod_ (&t2, 3, &P); + bnMulMod_ (&t2, &t2, &pkx, &P); + bnAddMod_ (&t2, &b, &P); + if (bnCmp (&t1, &t2) != 0) { + break; + } + + s = zrtp_status_ok; + } while (0); + + bnEnd (&t1); + bnEnd (&t2); + bnEnd (&pkx); + bnEnd (&pky); + bnEnd (&bnzero); + bnEnd (&P); + bnEnd (&b); + + ZRTP_LOG(1,(_ZTU_,"\tDH TEST: zrtp_ecdh_validate() for %.4s was executed by %llums.\n", self->base.type, zrtp_time_now()-start_ts)); + return s; +} + + +/*============================================================================*/ +/* P-256, 384, 521 (FIPS 186-3) support. See RFC 4753 3.1, 3.2, 3.3 */ +/*============================================================================*/ + +static uint8_t sv256_data[] = { + 0x81, 0x42, 0x64, 0x14, 0x5F, 0x2F, 0x56, 0xF2, + 0xE9, 0x6A, 0x8E, 0x33, 0x7A, 0x12, 0x84, 0x99, + 0x3F, 0xAF, 0x43, 0x2A, 0x5A, 0xBC, 0xE5, 0x9E, + 0x86, 0x7B, 0x72, 0x91, 0xD5, 0x07, 0xA3, 0xAF +}; +static uint8_t pvx256_data[] = { + 0x2A, 0xF5, 0x02, 0xF3, 0xBE, 0x89, 0x52, 0xF2, + 0xC9, 0xB5, 0xA8, 0xD4, 0x16, 0x0D, 0x09, 0xE9, + 0x71, 0x65, 0xBE, 0x50, 0xBC, 0x42, 0xAE, 0x4A, + 0x5E, 0x8D, 0x3B, 0x4B, 0xA8, 0x3A, 0xEB, 0x15 +}; +static uint8_t pvy256_data[] = { + 0xEB, 0x0F, 0xAF, 0x4C, 0xA9, 0x86, 0xC4, 0xD3, + 0x86, 0x81, 0xA0, 0xF9, 0x87, 0x2D, 0x79, 0xD5, + 0x67, 0x95, 0xBD, 0x4B, 0xFF, 0x6E, 0x6D, 0xE3, + 0xC0, 0xF5, 0x01, 0x5E, 0xCE, 0x5E, 0xFD, 0x85 +}; + +static uint8_t sv384_data[] = { + 0xD2, 0x73, 0x35, 0xEA, 0x71, 0x66, 0x4A, 0xF2, + 0x44, 0xDD, 0x14, 0xE9, 0xFD, 0x12, 0x60, 0x71, + 0x5D, 0xFD, 0x8A, 0x79, 0x65, 0x57, 0x1C, 0x48, + 0xD7, 0x09, 0xEE, 0x7A, 0x79, 0x62, 0xA1, 0x56, + 0xD7, 0x06, 0xA9, 0x0C, 0xBC, 0xB5, 0xDF, 0x29, + 0x86, 0xF0, 0x5F, 0xEA, 0xDB, 0x93, 0x76, 0xF1 +}; +static uint8_t pvx384_data[] = { + 0x79, 0x31, 0x48, 0xF1, 0x78, 0x76, 0x34, 0xD5, + 0xDA, 0x4C, 0x6D, 0x90, 0x74, 0x41, 0x7D, 0x05, + 0xE0, 0x57, 0xAB, 0x62, 0xF8, 0x20, 0x54, 0xD1, + 0x0E, 0xE6, 0xB0, 0x40, 0x3D, 0x62, 0x79, 0x54, + 0x7E, 0x6A, 0x8E, 0xA9, 0xD1, 0xFD, 0x77, 0x42, + 0x7D, 0x01, 0x6F, 0xE2, 0x7A, 0x8B, 0x8C, 0x66 +}; +static uint8_t pvy384_data[] = { + 0xC6, 0xC4, 0x12, 0x94, 0x33, 0x1D, 0x23, 0xE6, + 0xF4, 0x80, 0xF4, 0xFB, 0x4C, 0xD4, 0x05, 0x04, + 0xC9, 0x47, 0x39, 0x2E, 0x94, 0xF4, 0xC3, 0xF0, + 0x6B, 0x8F, 0x39, 0x8B, 0xB2, 0x9E, 0x42, 0x36, + 0x8F, 0x7A, 0x68, 0x59, 0x23, 0xDE, 0x3B, 0x67, + 0xBA, 0xCE, 0xD2, 0x14, 0xA1, 0xA1, 0xD1, 0x28 +}; + +static uint8_t sv521_data[] = { + 0x01, 0x13, 0xF8, 0x2D, 0xA8, 0x25, 0x73, 0x5E, + 0x3D, 0x97, 0x27, 0x66, 0x83, 0xB2, 0xB7, 0x42, + 0x77, 0xBA, 0xD2, 0x73, 0x35, 0xEA, 0x71, 0x66, + 0x4A, 0xF2, 0x43, 0x0C, 0xC4, 0xF3, 0x34, 0x59, + 0xB9, 0x66, 0x9E, 0xE7, 0x8B, 0x3F, 0xFB, 0x9B, + 0x86, 0x83, 0x01, 0x5D, 0x34, 0x4D, 0xCB, 0xFE, + 0xF6, 0xFB, 0x9A, 0xF4, 0xC6, 0xC4, 0x70, 0xBE, + 0x25, 0x45, 0x16, 0xCD, 0x3C, 0x1A, 0x1F, 0xB4, + 0x73, 0x62 +}; +static uint8_t pvx521_data[] = { + 0x01, 0xEB, 0xB3, 0x4D, 0xD7, 0x57, 0x21, 0xAB, + 0xF8, 0xAD, 0xC9, 0xDB, 0xED, 0x17, 0x88, 0x9C, + 0xBB, 0x97, 0x65, 0xD9, 0x0A, 0x7C, 0x60, 0xF2, + 0xCE, 0xF0, 0x07, 0xBB, 0x0F, 0x2B, 0x26, 0xE1, + 0x48, 0x81, 0xFD, 0x44, 0x42, 0xE6, 0x89, 0xD6, + 0x1C, 0xB2, 0xDD, 0x04, 0x6E, 0xE3, 0x0E, 0x3F, + 0xFD, 0x20, 0xF9, 0xA4, 0x5B, 0xBD, 0xF6, 0x41, + 0x3D, 0x58, 0x3A, 0x2D, 0xBF, 0x59, 0x92, 0x4F, + 0xD3, 0x5C +}; +static uint8_t pvy521_data[] = { + 0x00, 0xF6, 0xB6, 0x32, 0xD1, 0x94, 0xC0, 0x38, + 0x8E, 0x22, 0xD8, 0x43, 0x7E, 0x55, 0x8C, 0x55, + 0x2A, 0xE1, 0x95, 0xAD, 0xFD, 0x15, 0x3F, 0x92, + 0xD7, 0x49, 0x08, 0x35, 0x1B, 0x2F, 0x8C, 0x4E, + 0xDA, 0x94, 0xED, 0xB0, 0x91, 0x6D, 0x1B, 0x53, + 0xC0, 0x20, 0xB5, 0xEE, 0xCA, 0xED, 0x1A, 0x5F, + 0xC3, 0x8A, 0x23, 0x3E, 0x48, 0x30, 0x58, 0x7B, + 0xB2, 0xEE, 0x34, 0x89, 0xB3, 0xB4, 0x2A, 0x5A, + 0x86, 0xA4 +}; + +zrtp_status_t zrtp_ecdh_selftest(zrtp_pk_scheme_t *self) +{ + zrtp_status_t s = zrtp_status_fail; + struct BigNum P, Gx, Gy, n, sv; + struct BigNum pkx, pky; + unsigned ec_bytes = 0; + unsigned pbits = 0; + struct zrtp_ec_params ec_params; + + zrtp_time_t start_ts = 0; + + uint8_t *sv_data = NULL; + size_t sv_data_len = 0; + uint8_t *pvx_data = NULL; + size_t pvx_data_len = 0; + uint8_t *pvy_data = NULL; + size_t pvy_data_len = 0; + + if (!self) { + return zrtp_status_bad_param; + } + + ZRTP_LOG(3, (_ZTU_, "PKS %.4s testing... ", self->base.type)); + + switch (self->base.id) { + case ZRTP_PKTYPE_EC256P: + sv_data = sv256_data; + sv_data_len = sizeof(sv256_data); + pvx_data = pvx256_data; + pvx_data_len = sizeof(pvx256_data); + pvy_data = pvy256_data; + pvy_data_len = sizeof(pvy256_data); + break; + case ZRTP_PKTYPE_EC384P: + sv_data = sv384_data; + sv_data_len = sizeof(sv384_data); + pvx_data = pvx384_data; + pvx_data_len = sizeof(pvx384_data); + pvy_data = pvy384_data; + pvy_data_len = sizeof(pvy384_data); + break; + case ZRTP_PKTYPE_EC521P: + sv_data = sv521_data; + sv_data_len = sizeof(sv521_data); + pvx_data = pvx521_data; + pvx_data_len = sizeof(pvx521_data); + pvy_data = pvy521_data; + pvy_data_len = sizeof(pvy521_data); + break; + default: + return 0; + } + + pbits = get_pbits(self); + if (!pbits) { + return zrtp_status_bad_param; + } + + zrtp_ec_init_params(&ec_params, pbits); + + ec_bytes = (ec_params.ec_bits+7) / 8; + + bnBegin(&P); + bnInsertBigBytes(&P, ec_params.P_data, 0, ec_bytes ); + bnBegin(&Gx); + bnInsertBigBytes(&Gx, ec_params.Gx_data, 0, ec_bytes ); + bnBegin(&Gy); + bnInsertBigBytes(&Gy, ec_params.Gy_data, 0, ec_bytes ); + bnBegin(&n); + bnInsertBigBytes(&n, ec_params.n_data, 0, ec_bytes ); + + bnBegin(&pkx); + bnBegin(&pky); + bnBegin(&sv); + s = zrtp_ec_random_point( self->base.zrtp, &P, &n, &Gx, &Gy, + &pkx, &pky, &sv, + sv_data, sv_data_len); + if (zrtp_status_ok == s) + { + struct BigNum pkx1, pky1; + + bnBegin(&pkx1); bnBegin(&pky1); + bnInsertBigBytes(&pkx1, pvx_data, 0, pvx_data_len); + bnInsertBigBytes(&pky1, pvy_data, 0, pvy_data_len); + s = (bnCmp (&pkx1, &pkx) == 0 && bnCmp (&pky1, &pky) == 0) ? zrtp_status_ok : zrtp_status_fail; + bnEnd(&pkx1); + bnEnd(&pky1); + } + + bnEnd (&pkx); + bnEnd (&pky); + bnEnd (&P); + bnEnd (&Gx); + bnEnd (&Gy); + bnEnd (&n); + bnEnd (&sv); + + if (zrtp_status_ok == s) { + zrtp_status_t s = zrtp_status_ok; + zrtp_dh_crypto_context_t alice_cc; + zrtp_dh_crypto_context_t bob_cc; + struct BigNum alice_k; + struct BigNum bob_k; + + start_ts = zrtp_time_now(); + + bnBegin(&alice_k); + bnBegin(&bob_k); + + do { + /* Both sides initalise DH schemes and compute secret and public values. */ + s = self->initialize(self, &alice_cc); + if (zrtp_status_ok != s) { + break; + } + s = self->initialize(self, &bob_cc); + if (zrtp_status_ok != s) { + break; + } + + /* Both sides validate public values. (to provide exact performance estimation) */ + s = self->validate(self, &bob_cc.pv); + if (zrtp_status_ok != s) { + break; + } + s = self->validate(self, &alice_cc.pv); + if (zrtp_status_ok != s) { + break; + } + + /* Compute secret keys and compare them. */ + s = self->compute(self, &alice_cc, &alice_k, &bob_cc.pv); + if (zrtp_status_ok != s) { + break; + } + s= self->compute(self, &bob_cc, &bob_k, &alice_cc.pv); + if (zrtp_status_ok != s) { + break; + } + + s = (0 == bnCmp(&alice_k, &bob_k)) ? zrtp_status_ok : zrtp_status_algo_fail; + } while (0); + + bnEnd(&alice_k); + bnEnd(&bob_k); + } + ZRTP_LOGC(3, ("%s (%llu ms)\n", zrtp_log_status2str(s), (zrtp_time_now()-start_ts)/2)); + + return s; +} + + +/*============================================================================*/ +/* Public Key support */ +/*============================================================================*/ + +/*----------------------------------------------------------------------------*/ +zrtp_status_t zrtp_defaults_ec_pkt(zrtp_global_t* zrtp) +{ + zrtp_pk_scheme_t* ec256p = zrtp_sys_alloc(sizeof(zrtp_pk_scheme_t)); + zrtp_pk_scheme_t* ec384p = zrtp_sys_alloc(sizeof(zrtp_pk_scheme_t)); + zrtp_pk_scheme_t* ec521p = zrtp_sys_alloc(sizeof(zrtp_pk_scheme_t)); + + if (!ec256p || !ec384p || !ec521p) { + if(ec256p) { + zrtp_sys_free(ec256p); + } + if(ec384p) { + zrtp_sys_free(ec384p); + } + if(ec521p) { + zrtp_sys_free(ec521p); + } + return zrtp_status_alloc_fail; + } + + zrtp_memset(ec256p, 0, sizeof(zrtp_pk_scheme_t)); + zrtp_memcpy(ec256p->base.type, ZRTP_EC256P, ZRTP_COMP_TYPE_SIZE); + ec256p->base.id = ZRTP_PKTYPE_EC256P; + ec256p->base.zrtp = zrtp; + ec256p->sv_length = 256/8; + ec256p->pv_length = 2*256/8; + ec256p->base.init = zrtp_ecdh_init; + ec256p->base.free = zrtp_ecdh_free; + ec256p->initialize = zrtp_ecdh_initialize; + ec256p->compute = zrtp_ecdh_compute; + ec256p->validate = zrtp_ecdh_validate; + ec256p->self_test = zrtp_ecdh_selftest; + + zrtp_memset(ec384p, 0, sizeof(zrtp_pk_scheme_t)); + zrtp_memcpy(ec384p->base.type, ZRTP_EC384P, ZRTP_COMP_TYPE_SIZE); + ec384p->base.id = ZRTP_PKTYPE_EC384P; + ec384p->base.zrtp = zrtp; + ec384p->sv_length = 384/8; + ec384p->pv_length = 2*384/8; + ec384p->base.init = zrtp_ecdh_init; + ec384p->base.free = zrtp_ecdh_free; + ec384p->initialize = zrtp_ecdh_initialize; + ec384p->compute = zrtp_ecdh_compute; + ec384p->validate = zrtp_ecdh_validate; + ec384p->self_test = zrtp_ecdh_selftest; + + + zrtp_memset(ec521p, 0, sizeof(zrtp_pk_scheme_t)); + zrtp_memcpy(ec521p->base.type, ZRTP_EC521P, ZRTP_COMP_TYPE_SIZE); + ec521p->base.id = ZRTP_PKTYPE_EC521P; + ec521p->base.zrtp = zrtp; + ec521p->sv_length = 528/8; + ec521p->pv_length = 2*528/8; + ec521p->base.init = zrtp_ecdh_init; + ec521p->base.free = zrtp_ecdh_free; + ec521p->initialize = zrtp_ecdh_initialize; + ec521p->compute = zrtp_ecdh_compute; + ec521p->validate = zrtp_ecdh_validate; + ec521p->self_test = zrtp_ecdh_selftest; + + zrtp_comp_register(ZRTP_CC_PKT, ec256p, zrtp); + zrtp_comp_register(ZRTP_CC_PKT, ec384p, zrtp); + zrtp_comp_register(ZRTP_CC_PKT, ec521p, zrtp); + + return zrtp_status_ok; +} + +#endif /*ZRTP_ENABLE_EC*/ diff --git a/libs/libzrtp/src/zrtp_crypto_ecdsa.c b/libs/libzrtp/src/zrtp_crypto_ecdsa.c new file mode 100644 index 0000000000..679f1259c1 --- /dev/null +++ b/libs/libzrtp/src/zrtp_crypto_ecdsa.c @@ -0,0 +1,646 @@ +/* + * zrtp_crypto_ecdsa.c - Elliptic Curve Digital Signature functions for ZRTP. + * NSA Suite B Elliptic Curves from NIST SP 800-56A and FIPS 186-3. + * + * Copyright (c) 2006-2009 Philip R. Zimmermann. All rights reserved. + * This is NOT licensed under the GPL or any other open source license. + * For licensing terms or other information, + * contact: Philip Zimmermann . + * For more contact information, see http://philzimmermann.com + */ + +#include "zrtp.h" + +/* We don't have digital signatures ready yet. */ +#if 0 + +/* Size of extra random data to approximate a uniform distribution mod n */ +#define UNIFORMBYTES 8 + +/*============================================================================*/ +/* Shared Elliptic Curve functions */ +/* */ +/* The Elliptic Curve DSA algorithm, key generation, and curves are */ +/* from FIPS 186-3. The curves used are */ +/* also defined in RFC 4753, sections 3.1 through 3.3. */ +/*============================================================================*/ + +/*----------------------------------------------------------------------------*/ +/* Return dsa_cc->pv holding public value and dsa_cc->sv holding secret value */ +/* The public value is an elliptic curve point encoded as the x part shifted */ +/* left Pbits bits and or'd with the y part. */ +/*----------------------------------------------------------------------------*/ +static zrtp_status_t ECDSA_keygen( struct zrtp_sig_scheme *self, + zrtp_dsa_crypto_context_t *dsa_cc, + zrtp_ec_params_t *ec_params, +#ifdef ZRTP_TEST_VECTORS + uint8_t *sv_data, size_t sv_data_len, + uint8_t *pvx_data, size_t pvx_data_len, + uint8_t *pvy_data, size_t pvy_data_len, +#endif + unsigned Pbits ) +{ + zrtp_status_t s = zrtp_status_fail; + struct BigNum P, Gx, Gy, n; + struct BigNum pkx, pky; + unsigned ec_bytes; + + if (!ec_params) + return zrtp_status_bad_param; + + ec_bytes = (ec_params->ec_bits+7) / 8; + + do + { + if (!self || !dsa_cc) + { + s = zrtp_status_bad_param; + break; + } + + bnBegin(&P); + bnInsertBigBytes( &P, ec_params->P_data, 0, ec_bytes ); + bnBegin(&Gx); + bnInsertBigBytes( &Gx, ec_params->Gx_data, 0, ec_bytes ); + bnBegin(&Gy); + bnInsertBigBytes( &Gy, ec_params->Gy_data, 0, ec_bytes ); + bnBegin(&n); + bnInsertBigBytes( &n, ec_params->n_data, 0, ec_bytes ); + + bnBegin(&pkx); + bnBegin(&pky); + bnBegin(&dsa_cc->sv); + s = zrtp_ec_random_point( self->base.zrtp_global, &P, &n, &Gx, &Gy, +#ifdef ZRTP_TEST_VECTORS + sv_data, sv_data_len, + pvx_data, pvx_data_len, + pvy_data, pvy_data_len, +#endif + &pkx, &pky, &dsa_cc->sv ); + if ( s != zrtp_status_ok ) + break; + s = zrtp_status_fail; + + bnBegin(&dsa_cc->pv); + bnCopy (&dsa_cc->pv, &pkx); + bnLShift (&dsa_cc->pv, Pbits); + bnAdd (&dsa_cc->pv, &pky); + bnEnd (&pkx); + bnEnd (&pky); + bnEnd (&P); + bnEnd (&Gx); + bnEnd (&Gy); + bnEnd (&n); + + s = zrtp_status_ok; + } while (0); + + return s; +} + + +/*----------------------------------------------------------------------------*/ +/* Sign the specified hash value - must be size matching the curve */ +/*----------------------------------------------------------------------------*/ +static zrtp_status_t ECDSA_sign( struct zrtp_sig_scheme *self, + zrtp_dsa_crypto_context_t *dsa_cc, + zrtp_ec_params_t *ec_params, +#ifdef ZRTP_TEST_VECTORS + uint8_t *k_data, size_t k_data_len, + uint8_t *rx_data, size_t rx_data_len, + uint8_t *ry_data, size_t ry_data_len, + uint8_t *s_data, size_t s_data_len, +#endif + uint8_t *hash, uint32_t hash_len, + struct BigNum *dsasig ) +{ + zrtp_status_t s = zrtp_status_fail; + struct BigNum P, Gx, Gy, n; + struct BigNum h, s1, k, rx, ry, kinv, pkx, pky; + unsigned ec_bytes; + + if (!ec_params) + return zrtp_status_bad_param; + + ec_bytes = (ec_params->ec_bits+7) / 8; + + do + { + if (!self || !dsa_cc) + { + s = zrtp_status_bad_param; + break; + } + + bnBegin(&P); + bnInsertBigBytes( &P, ec_params->P_data, 0, ec_bytes ); + bnBegin(&Gx); + bnInsertBigBytes( &Gx, ec_params->Gx_data, 0, ec_bytes ); + bnBegin(&Gy); + bnInsertBigBytes( &Gy, ec_params->Gy_data, 0, ec_bytes ); + bnBegin(&n); + bnInsertBigBytes( &n, ec_params->n_data, 0, ec_bytes ); + + /* Hash to bignum */ + bnBegin(&h); + bnInsertBigBytes( &h, hash, 0, hash_len ); + bnMod (&h, &h, &P); + + /* Unpack signing key */ + bnBegin(&pkx); + bnBegin(&pky); + bnSetQ (&pkx, 1); + bnLShift (&pkx, ec_bytes*8); + bnMod (&pky, &dsa_cc->pv, &pkx); + bnCopy (&pkx, &dsa_cc->pv); + bnRShift (&pkx, ec_bytes*8); + + /* Choose signature secret k value */ + bnBegin(&rx); + bnBegin(&ry); + bnBegin(&k); + s = zrtp_ec_random_point( self->base.zrtp_global, &P, &n, &Gx, &Gy, +#ifdef ZRTP_TEST_VECTORS + k_data, k_data_len, + rx_data, rx_data_len, + ry_data, ry_data_len, +#endif + &rx, &ry, &k ); + if ( s != zrtp_status_ok ) + break; + s = zrtp_status_fail; + +#ifndef ZRTP_TEST_VECTORS + /* For further randomness we are going to add the secret key to k */ + bnAddMod_ (&k, &dsa_cc->sv, &n); + zrtp_ecAdd (&rx, &ry, &rx, &ry, &pkx, &pky, &P); +#endif + + /* Perform the signature */ + bnBegin (&s1); + bnMulMod_ (&s1, &rx, &dsa_cc->sv, &n); + bnAddMod_ (&s1, &h, &n); + bnBegin (&kinv); + bnInv (&kinv, &k, &n); + bnMulMod_ (&s1, &s1, &kinv, &n); + +#ifdef ZRTP_TEST_VECTORS + if (k_data_len != 0) + { + /* rx is checked in ec_random_point */ + struct BigNum s2; + int ok; + bnBegin(&s2); + bnInsertBigBytes(&s2, s_data, 0, s_data_len); + ok = (bnCmp (&s1, &s2) == 0); + bnEnd(&s2); + if (!ok) + break; + } +#endif + + /* Combine r, s into dsasig */ + bnBegin(dsasig); + bnCopy (dsasig, &rx); + bnLShift (dsasig, ec_bytes*8); + bnAdd (dsasig, &s1); + bnEnd (&rx); + bnEnd (&ry); + bnEnd (&k); + bnEnd (&kinv); + bnEnd (&s1); + bnEnd (&h); + bnEnd (&pkx); + bnEnd (&pky); + bnEnd (&P); + bnEnd (&Gx); + bnEnd (&Gy); + bnEnd (&n); + + s = zrtp_status_ok; + } while (0); + + return s; +} + + +/*----------------------------------------------------------------------------*/ +/* Verify a signature value - hash must be size matching the curve */ +/* Signing key should be in peer_pv entry of dsa_cc */ +/*----------------------------------------------------------------------------*/ +static zrtp_status_t ECDSA_verify( struct zrtp_sig_scheme *self, + zrtp_dsa_crypto_context_t *dsa_cc, + zrtp_ec_params_t *ec_params, + uint8_t *hash, uint32_t hash_len, + struct BigNum *dsasig ) +{ + zrtp_status_t s = zrtp_status_fail; + struct BigNum P, Gx, Gy, n; + struct BigNum rx, ry, pkx, pky, r, s1, sinv, u1, u2, u1x, u2x, u1y, u2y, h; + unsigned ec_bytes; + + if (!ec_params) + return zrtp_status_bad_param; + + ec_bytes = (ec_params->ec_bits+7) / 8; + + do + { + if (!self || !dsa_cc) + { + s = zrtp_status_bad_param; + break; + } + + bnBegin(&P); + bnInsertBigBytes( &P, ec_params->P_data, 0, ec_bytes ); + bnBegin(&Gx); + bnInsertBigBytes( &Gx, ec_params->Gx_data, 0, ec_bytes ); + bnBegin(&Gy); + bnInsertBigBytes( &Gy, ec_params->Gy_data, 0, ec_bytes ); + bnBegin(&n); + bnInsertBigBytes( &n, ec_params->n_data, 0, ec_bytes ); + + /* hash */ + bnBegin(&h); + bnInsertBigBytes( &h, hash, 0, hash_len ); + bnMod (&h, &h, &P); + + /* Unpack sig */ + bnBegin(&r); + bnBegin(&s1); + bnSetQ (&r, 1); + bnLShift (&r, ec_bytes*8); + bnMod (&s1, dsasig, &r); + bnCopy (&r, dsasig); + bnRShift (&r, ec_bytes*8); + + /* Unpack signing key */ + bnBegin(&pkx); + bnBegin(&pky); + bnSetQ (&pkx, 1); + bnLShift (&pkx, ec_bytes*8); + bnMod (&pky, &dsa_cc->peer_pv, &pkx); + bnCopy (&pkx, &dsa_cc->peer_pv); + bnRShift (&pkx, ec_bytes*8); + + /* Verify signature */ + bnBegin (&sinv); + bnInv (&sinv, &s1, &n); + bnBegin (&u1); + bnBegin (&u2); + bnMulMod_ (&u1, &sinv, &h, &n); + bnMulMod_ (&u2, &sinv, &r, &n); + + bnBegin (&u1x); + bnBegin (&u1y); + bnBegin (&u2x); + bnBegin (&u2y); + bnBegin (&rx); + bnBegin (&ry); + zrtp_ecMul (&u1x, &u1y, &u1, &Gx, &Gy, &P); + zrtp_ecMul (&u2x, &u2y, &u2, &pkx, &pky, &P); + zrtp_ecAdd (&rx, &ry, &u1x, &u1y, &u2x, &u2y, &P); + + if (bnCmp (&rx, &r) == 0) { + s = zrtp_status_ok; + } else { + s = zrtp_status_fail; + } + + /* Clean up */ + bnEnd (&rx); + bnEnd (&ry); + bnEnd (&r); + bnEnd (&s1); + bnEnd (&sinv); + bnEnd (&u1); + bnEnd (&u1x); + bnEnd (&u1y); + bnEnd (&u2); + bnEnd (&u2x); + bnEnd (&u2y); + bnEnd (&h); + bnEnd (&pkx); + bnEnd (&pky); + bnEnd (&P); + bnEnd (&Gx); + bnEnd (&Gy); + bnEnd (&n); + + } while (0); + + return s; +} + + + +/*----------------------------------------------------------------------------*/ +static zrtp_status_t EC_dummy(void *s) +{ + return zrtp_status_ok; +} + + +/*============================================================================*/ +/* P-256 (FIPS 186-3) support. See RFC 4753, section 3.1. */ +/*============================================================================*/ + +/* Test vectors from RFC4754 */ +#ifdef ZRTP_TEST_VECTORS +static uint8_t sv256_data[] = { + 0xDC, 0x51, 0xD3, 0x86, 0x6A, 0x15, 0xBA, 0xCD, + 0xE3, 0x3D, 0x96, 0xF9, 0x92, 0xFC, 0xA9, 0x9D, + 0xA7, 0xE6, 0xEF, 0x09, 0x34, 0xE7, 0x09, 0x75, + 0x59, 0xC2, 0x7F, 0x16, 0x14, 0xC8, 0x8A, 0x7F, +}; +static uint8_t pvx256_data[] = { + 0x24, 0x42, 0xA5, 0xCC, 0x0E, 0xCD, 0x01, 0x5F, + 0xA3, 0xCA, 0x31, 0xDC, 0x8E, 0x2B, 0xBC, 0x70, + 0xBF, 0x42, 0xD6, 0x0C, 0xBC, 0xA2, 0x00, 0x85, + 0xE0, 0x82, 0x2C, 0xB0, 0x42, 0x35, 0xE9, 0x70, +}; +static uint8_t pvy256_data[] = { + 0x6F, 0xC9, 0x8B, 0xD7, 0xE5, 0x02, 0x11, 0xA4, + 0xA2, 0x71, 0x02, 0xFA, 0x35, 0x49, 0xDF, 0x79, + 0xEB, 0xCB, 0x4B, 0xF2, 0x46, 0xB8, 0x09, 0x45, + 0xCD, 0xDF, 0xE7, 0xD5, 0x09, 0xBB, 0xFD, 0x7D, +}; + +static uint8_t k256_data[] = { + 0x9E, 0x56, 0xF5, 0x09, 0x19, 0x67, 0x84, 0xD9, + 0x63, 0xD1, 0xC0, 0xA4, 0x01, 0x51, 0x0E, 0xE7, + 0xAD, 0xA3, 0xDC, 0xC5, 0xDE, 0xE0, 0x4B, 0x15, + 0x4B, 0xF6, 0x1A, 0xF1, 0xD5, 0xA6, 0xDE, 0xCE, +}; +static uint8_t rx256_data[] = { + 0xCB, 0x28, 0xE0, 0x99, 0x9B, 0x9C, 0x77, 0x15, + 0xFD, 0x0A, 0x80, 0xD8, 0xE4, 0x7A, 0x77, 0x07, + 0x97, 0x16, 0xCB, 0xBF, 0x91, 0x7D, 0xD7, 0x2E, + 0x97, 0x56, 0x6E, 0xA1, 0xC0, 0x66, 0x95, 0x7C, +}; +static uint8_t ry256_data[] = { + 0x2B, 0x57, 0xC0, 0x23, 0x5F, 0xB7, 0x48, 0x97, + 0x68, 0xD0, 0x58, 0xFF, 0x49, 0x11, 0xC2, 0x0F, + 0xDB, 0xE7, 0x1E, 0x36, 0x99, 0xD9, 0x13, 0x39, + 0xAF, 0xBB, 0x90, 0x3E, 0xE1, 0x72, 0x55, 0xDC, +}; + +static uint8_t h256_data[] = { + 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA, + 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23, + 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C, + 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD, +}; +static uint8_t s256_data[] = { + 0x86, 0xFA, 0x3B, 0xB4, 0xE2, 0x6C, 0xAD, 0x5B, + 0xF9, 0x0B, 0x7F, 0x81, 0x89, 0x92, 0x56, 0xCE, + 0x75, 0x94, 0xBB, 0x1E, 0xA0, 0xC8, 0x92, 0x12, + 0x74, 0x8B, 0xFF, 0x3B, 0x3D, 0x5B, 0x03, 0x15, +}; + + +#endif + +/*----------------------------------------------------------------------------*/ +/* Return dsa_cc->pv holding public value and dsa_cc->sv holding secret value */ +/* The public value is an elliptic curve point encoded as the x part shifted */ +/* left 256 bits and or'd with the y part. */ +/*----------------------------------------------------------------------------*/ +static zrtp_status_t EC256P_keygen( struct zrtp_sig_scheme *self, + zrtp_dsa_crypto_context_t *dsa_cc ) +{ + struct zrtp_ec_params params; + zrtp_ec_init_params(¶ms, 256); + return ECDSA_keygen(self, dsa_cc, ¶ms, +#ifdef ZRTP_TEST_VECTORS + sv256_data, sizeof(sv256_data), + pvx256_data, sizeof(pvx256_data), + pvy256_data, sizeof(pvy256_data), +#endif + 256); +} + + +/*----------------------------------------------------------------------------*/ +/* Sign the specified hash value */ +/*----------------------------------------------------------------------------*/ +static zrtp_status_t EC256P_sign( struct zrtp_sig_scheme *self, + zrtp_dsa_crypto_context_t *dsa_cc, + uint8_t *hash, uint32_t hash_len, + struct BigNum *dsasig ) +{ + struct zrtp_ec_params params; + zrtp_ec_init_params(¶ms, 256); + return ECDSA_sign(self, dsa_cc, ¶ms, +#ifdef ZRTP_TEST_VECTORS + k256_data, sizeof(k256_data), + rx256_data, sizeof(rx256_data), + ry256_data, sizeof(ry256_data), + s256_data, sizeof(s256_data), + h256_data, sizeof(h256_data), +#else + hash, hash_len, +#endif + dsasig); +} + + +/*----------------------------------------------------------------------------*/ +/* Verify the signature on the hash value */ +/*----------------------------------------------------------------------------*/ +static zrtp_status_t EC256P_verify(struct zrtp_sig_scheme *self, + zrtp_dsa_crypto_context_t *dsa_cc, + uint8_t *hash, uint32_t hash_len, + struct BigNum *dsasig ) +{ + struct zrtp_ec_params params; + zrtp_ec_init_params(¶ms, 256); + return ECDSA_verify(self, dsa_cc, ¶ms, +#ifdef ZRTP_TEST_VECTORS + h256_data, sizeof(h256_data), +#else + hash, hash_len, +#endif + dsasig); +} + + + +/*============================================================================*/ +/* P-384 (FIPS 186-3) support. See RFC 4753, section 3.2. */ +/*============================================================================*/ + + + +/*----------------------------------------------------------------------------*/ +/* Return dsa_cc->pv holding public value and dsa_cc->sv holding secret value */ +/* The public value is an elliptic curve point encoded as the x part shifted */ +/* left 384 bits and or'd with the y part. */ +/*----------------------------------------------------------------------------*/ +static zrtp_status_t EC384P_keygen( struct zrtp_sig_scheme *self, + zrtp_dsa_crypto_context_t *dsa_cc ) +{ + struct zrtp_ec_params params; + zrtp_ec_init_params(¶ms, 384); + return ECDSA_keygen(self, dsa_cc, ¶ms, +#ifdef ZRTP_TEST_VECTORS + 0, 0, 0, 0, 0, 0, +#endif + 384); +} + + +/*----------------------------------------------------------------------------*/ +/* Sign the specified hash value */ +/*----------------------------------------------------------------------------*/ +static zrtp_status_t EC384P_sign( struct zrtp_sig_scheme *self, + zrtp_dsa_crypto_context_t *dsa_cc, + uint8_t *hash, uint32_t hash_len, + struct BigNum *dsasig ) +{ + struct zrtp_ec_params params; + zrtp_ec_init_params(¶ms, 384); + return ECDSA_sign(self, dsa_cc, ¶ms, +#ifdef ZRTP_TEST_VECTORS + 0, 0, 0, 0, 0, 0, 0, 0, +#endif + hash, hash_len, dsasig); +} + + +/*----------------------------------------------------------------------------*/ +/* Verify the signature on the hash value */ +/*----------------------------------------------------------------------------*/ +static zrtp_status_t EC384P_verify(struct zrtp_sig_scheme *self, + zrtp_dsa_crypto_context_t *dsa_cc, + uint8_t *hash, uint32_t hash_len, + struct BigNum *dsasig ) +{ + struct zrtp_ec_params params; + zrtp_ec_init_params(¶ms, 384); + return ECDSA_verify(self, dsa_cc, ¶ms, hash, hash_len, dsasig); +} + + + +/*============================================================================*/ +/* P-521 (FIPS 186-3) support. See RFC 4753, section 3.3. */ +/*============================================================================*/ + + +/*----------------------------------------------------------------------------*/ +/* Return dsa_cc->pv holding public value and dsa_cc->sv holding secret value */ +/* The public value is an elliptic curve point encoded as the x part shifted */ +/* left 528 bits (note, not 521) and or'd with the y part. */ +/*----------------------------------------------------------------------------*/ +static zrtp_status_t EC521P_keygen( struct zrtp_sig_scheme *self, + zrtp_dsa_crypto_context_t *dsa_cc ) +{ + struct zrtp_ec_params params; + zrtp_ec_init_params(¶ms, 521); + return ECDSA_keygen(self, dsa_cc, ¶ms, +#ifdef ZRTP_TEST_VECTORS + 0, 0, 0, 0, 0, 0, +#endif + 528); +} + + +/*----------------------------------------------------------------------------*/ +/* Sign the specified hash value */ +/*----------------------------------------------------------------------------*/ +static zrtp_status_t EC521P_sign( struct zrtp_sig_scheme *self, + zrtp_dsa_crypto_context_t *dsa_cc, + uint8_t *hash, uint32_t hash_len, + struct BigNum *dsasig ) +{ + struct zrtp_ec_params params; + zrtp_ec_init_params(¶ms, 521); + return ECDSA_sign(self, dsa_cc, ¶ms, +#ifdef ZRTP_TEST_VECTORS + 0, 0, 0, 0, 0, 0, 0, 0, +#endif + hash, hash_len, dsasig); +} + + +/*----------------------------------------------------------------------------*/ +/* Verify the signature on the hash value */ +/*----------------------------------------------------------------------------*/ +static zrtp_status_t EC521P_verify(struct zrtp_sig_scheme *self, + zrtp_dsa_crypto_context_t *dsa_cc, + uint8_t *hash, uint32_t hash_len, + struct BigNum *dsasig ) +{ + struct zrtp_ec_params params; + zrtp_ec_init_params(¶ms, 521); + return ECDSA_verify(self, dsa_cc, ¶ms, hash, hash_len, dsasig); +} + + + +/*============================================================================*/ +/* Public Key support */ +/*============================================================================*/ + + +/*----------------------------------------------------------------------------*/ +zrtp_status_t zrtp_defaults_sig(zrtp_global_ctx_t* zrtp_global) +{ + zrtp_sig_scheme_t* ec256p = zrtp_sys_alloc(sizeof(zrtp_sig_scheme_t)); + zrtp_sig_scheme_t* ec384p = zrtp_sys_alloc(sizeof(zrtp_sig_scheme_t)); + zrtp_sig_scheme_t* ec521p = zrtp_sys_alloc(sizeof(zrtp_sig_scheme_t)); + + if (!ec256p || !ec384p || !ec521p) + { + if(ec256p) zrtp_sys_free(ec256p); + if(ec384p) zrtp_sys_free(ec384p); + if(ec521p) zrtp_sys_free(ec521p); + return zrtp_status_alloc_fail; + } + + zrtp_memset(ec256p, 0, sizeof(zrtp_sig_scheme_t)); + zrtp_memcpy(ec256p->base.type, ZRTP_EC256P, ZRTP_COMP_TYPE_SIZE); + ec256p->base.id = ZRTP_SIGTYPE_EC256P; + ec256p->base.zrtp_global = zrtp_global; + ec256p->sv_length = 256/8; + ec256p->pv_length = 2*256/8; + ec256p->base.init = EC_dummy; + ec256p->base.free = EC_dummy; + ec256p->generate_key = EC256P_keygen; + ec256p->sign = EC256P_sign; + ec256p->verify = EC256P_verify; + + zrtp_memset(ec384p, 0, sizeof(zrtp_sig_scheme_t)); + zrtp_memcpy(ec384p->base.type, ZRTP_EC384P, ZRTP_COMP_TYPE_SIZE); + ec384p->base.id = ZRTP_SIGTYPE_EC384P; + ec384p->base.zrtp_global = zrtp_global; + ec384p->sv_length = 384/8; + ec384p->pv_length = 2*384/8; + ec384p->base.init = EC_dummy; + ec384p->base.free = EC_dummy; + ec384p->generate_key = EC384P_keygen; + ec384p->sign = EC384P_sign; + ec384p->verify = EC384P_verify; + + zrtp_memset(ec521p, 0, sizeof(zrtp_sig_scheme_t)); + zrtp_memcpy(ec521p->base.type, ZRTP_EC521P, ZRTP_COMP_TYPE_SIZE); + ec521p->base.id = ZRTP_SIGTYPE_EC521P; + ec521p->base.zrtp_global = zrtp_global; + ec521p->sv_length = 528/8; + ec521p->pv_length = 2*528/8; + ec521p->base.init = EC_dummy; + ec521p->base.free = EC_dummy; + ec521p->generate_key = EC521P_keygen; + ec521p->sign = EC521P_sign; + ec521p->verify = EC521P_verify; + + zrtp_register_comp(ZRTP_CC_SIG, ec256p, zrtp_global); + zrtp_register_comp(ZRTP_CC_SIG, ec384p, zrtp_global); + zrtp_register_comp(ZRTP_CC_SIG, ec521p, zrtp_global); + + return zrtp_status_ok; +} + +#endif /* don't have disgital signature ready for the moment*/