#endif
#ifndef ZRTP_ENABLE_EC
-#define ZRTP_ENABLE_EC 0
+#define ZRTP_ENABLE_EC 1
#endif
#ifndef ZRTP_DEBUG_WITH_PJSIP
--- /dev/null
+/*
+ * 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 <prz@mit.edu>.
+ * 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__ */
Name="VCCLCompilerTool"\r
Optimization="0"\r
AdditionalIncludeDirectories="../../include;../../third_party/bnlib;../../third_party/bgaes;../../test/include"\r
- PreprocessorDefinitions="WIN32;_DEBUG;_LIB;HAVE_CONFIG_H=1;ZRTP_ENABLE_EC=0"\r
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;HAVE_CONFIG_H=1;ZRTP_ENABLE_EC=1"\r
MinimalRebuild="true"\r
BasicRuntimeChecks="3"\r
RuntimeLibrary="1"\r
<Tool\r
Name="VCCLCompilerTool"\r
AdditionalIncludeDirectories="../../include;../../third_party/bnlib;../../third_party/bgaes"\r
- PreprocessorDefinitions="WIN32;NDEBUG;_LIB;HAVE_CONFIG_H=1;ZRTP_ENABLE_EC=0"\r
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;HAVE_CONFIG_H=1;ZRTP_ENABLE_EC=1"\r
ExceptionHandling="0"\r
RuntimeLibrary="0"\r
StructMemberAlignment="0"\r
RelativePath="..\..\include\zrtp_crypto.h"\r
>\r
</File>\r
+ <File\r
+ RelativePath="..\..\include\zrtp_ec.h"\r
+ >\r
+ </File>\r
<File\r
RelativePath="..\..\include\zrtp_engine.h"\r
>\r
RelativePath="..\..\include\zrtp_utils.h"\r
>\r
</File>\r
+ <File\r
+ RelativePath="..\..\include\zrtp_version.h"\r
+ >\r
+ </File>\r
</Filter>\r
<Filter\r
Name="src"\r
RelativePath="..\..\src\zrtp_crypto_atl.c"\r
>\r
</File>\r
+ <File\r
+ RelativePath="..\..\src\zrtp_crypto_ec.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\src\zrtp_crypto_ecdh.c"\r
+ >\r
+ </File>\r
<File\r
RelativePath="..\..\src\zrtp_crypto_hash.c"\r
>\r
ExecutionBucket="7"\r
Optimization="0"\r
AdditionalIncludeDirectories="../../third_party/bnlib;../../include;../../include/enterprise;../../third_party/bgaes;../../test/include"\r
- PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;DEBUG;_LIB;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE;ZRTP_ENABLE_EC=0"\r
+ PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;DEBUG;_LIB;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE;ZRTP_ENABLE_EC=1"\r
MinimalRebuild="true"\r
RuntimeLibrary="1"\r
StructMemberAlignment="0"\r
ExecutionBucket="7"\r
Optimization="0"\r
AdditionalIncludeDirectories="../../third_party/bnlib;../../include;../../include/enterprise;../../third_party/bgaes;../../test/include"\r
- PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;DEBUG;_LIB;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;ZRTP_ENABLE_EC=0"\r
+ PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;DEBUG;_LIB;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;ZRTP_ENABLE_EC=1"\r
MinimalRebuild="true"\r
RuntimeLibrary="1"\r
BufferSecurityCheck="false"\r
ExecutionBucket="7"\r
Optimization="2"\r
AdditionalIncludeDirectories="../../third_party/bnlib;../../include;../../include/enterprise;../../third_party/bgaes;../../test/include"\r
- PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;_LIB;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;ZRTP_ENABLE_EC=0"\r
+ PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;_LIB;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;ZRTP_ENABLE_EC=1"\r
RuntimeLibrary="0"\r
BufferSecurityCheck="false"\r
UsePrecompiledHeader="0"\r
ExecutionBucket="7"\r
Optimization="2"\r
AdditionalIncludeDirectories="../../third_party/bnlib;../../include;../../include/enterprise;../../third_party/bgaes;../../test/include"\r
- PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;_LIB;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE;ZRTP_ENABLE_EC=0"\r
+ PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;_LIB;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE;ZRTP_ENABLE_EC=1"\r
RuntimeLibrary="0"\r
BufferSecurityCheck="false"\r
UsePrecompiledHeader="0"\r
RelativePath="..\..\include\zrtp_crypto.h"\r
>\r
</File>\r
+ <File\r
+ RelativePath="..\..\include\zrtp_ec.h"\r
+ >\r
+ </File>\r
<File\r
RelativePath="..\..\include\zrtp_engine.h"\r
>\r
RelativePath="..\..\src\zrtp_crypto_atl.c"\r
>\r
</File>\r
+ <File\r
+ RelativePath="..\..\src\zrtp_crypto_ec.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\src\zrtp_crypto_ecdh.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\src\zrtp_crypto_ecdsa.c"\r
+ >\r
+ </File>\r
<File\r
RelativePath="..\..\src\zrtp_crypto_hash.c"\r
>\r
RelativePath="..\..\src\zrtp_engine.c"\r
>\r
</File>\r
+ <File\r
+ RelativePath="..\..\src\zrtp_engine_driven.c"\r
+ >\r
+ </File>\r
<File\r
RelativePath="..\..\src\zrtp_iface_cache.c"\r
>\r
../../src/zrtp_crypto_sas.obj \\r
../../src/zrtp_datatypes.obj \\r
../../src/zrtp_engine.obj \\r
+ ../../src/enterprise/zrtp_engine_driven.obj \\r
+ ../../src/enterprise/zrtp_crypto_ec.obj \\r
+ ../../src/enterprise/zrtp_crypto_ecdh.obj \\r
../../src/zrtp_iface_sys.obj \\r
../../src/zrtp_initiator.obj \\r
../../src/zrtp_legal.obj \\r
\r
# Debug\r
\r
-OUT_DIR = debug.km\r
+OUT_DIR = debug_ec.km\r
\r
DEFINES_D = -D_X86_=1 -Di386=1 -DSTD_CALL -DCONDITION_HANDLING=1 \\r
-DNT_UP=1 -DNT_INST=0 -DWIN32=100 -D_NT1X_=100 \\r
-DWINNT=1 -D_WIN32_WINNT=0x0500 -DWIN32_LEAN_AND_MEAN=1 -DDBG=1 -D_DEBUG -DDEBUG -DDEVL=1 \\r
-DFPO=0 -D_DLL=1 -D_IDWBUILD -DRDRDBG -DSRVDBG -DDBG_MESSAGES=1 \\r
--D_UNICODE -DLITTLE_ENDIAN -DZRTP_USE_ENTERPRISE=0\r
+-D_UNICODE -DLITTLE_ENDIAN -DZRTP_USE_ENTERPRISE=1\r
\r
CFLAGS_D = $(DEFINES_D) -Zel -Zp8 -Gy -cbstring -Gz -QIfdiv- -QIf -Gi- -Gm- -GX- \\r
-GR- -GF -FI$(DDK)\inc\$(OS)\warning.h -Z7 -Od -Oi -Oy- -W3\r
\r
# Release\r
\r
-OUT_DIR = release.km\r
+OUT_DIR = release_ec.km\r
\r
DEFINES_D = -D_X86_=1 -Di386=1 -DSTD_CALL -DCONDITION_HANDLING=1 \\r
-DNT_UP=1 -DNO_DISK_ACCESS -DNT_INST=0 -DWIN32=100 -D_NT1X_=100 \\r
-DWINNT=1 -D_WIN32_WINNT=0x0500 -DWIN32_LEAN_AND_MEAN=1 -DDEVL=1 \\r
-DFPO=1 -DNDEBUG -D_DLL=1 -D_IDWBUILD -D_UNICODE \\r
--DLITTLE_ENDIAN -DZRTP_USE_ENTERPRISE=0\r
+-DLITTLE_ENDIAN -DZRTP_USE_ENTERPRISE=1\r
\r
CFLAGS_D = $(DEFINES_D) -Zel -Zp8 -Gy -cbstring -Gz -QIfdiv- -QIf -Gi- -Gm- -GX- \\r
-GR- -GF -Oxs -Oy -FI$(DDK)\inc\$(OS)\warning.h -W3 -FAcs -Z7\r
../../src/zrtp_crypto_sas.obj \\r
../../src/zrtp_datatypes.obj \\r
../../src/zrtp_engine.obj \\r
+ ../../src/enterprise/zrtp_engine_driven.obj \\r
+ ../../src/enterprise/zrtp_crypto_ec.obj \\r
+ ../../src/enterprise/zrtp_crypto_ecdh.obj \\r
../../src/zrtp_iface_sys.obj \\r
../../src/zrtp_initiator.obj \\r
../../src/zrtp_legal.obj \\r
\r
# Debug\r
\r
-OUT_DIR = debug64.km\r
+OUT_DIR = debug64_ec.km\r
\r
DEFINES_D = -DWIN64=1 -D_WIN64=1 -D_AMD64_=1 -D_M_AMD64 -D_WINDOWS \\r
-DSTD_CALL -DCONDITION_HANDLING=1 \\r
-DNT_UP=1 -DNT_INST=0 -D_NT1X_=100 \\r
-DWINNT=1 -D_WIN32_WINNT=0x0500 -DWIN32_LEAN_AND_MEAN=1 -DDBG=1 -D_DEBUG -DDEBUG -DDEVL=1 \\r
-DFPO=0 -D_DLL=1 -D_IDWBUILD -DRDRDBG -DSRVDBG -DDBG_MESSAGES=1 \\r
--D_UNICODE -DLITTLE_ENDIAN -DZRTP_USE_ENTERPRISE=0\r
+-D_UNICODE -DLITTLE_ENDIAN -DZRTP_USE_ENTERPRISE=1\r
\r
CFLAGS_D = $(DEFINES_D) -Zp8 -Gy -cbstring -Gz -Gm- -EHs-c- \\r
-GR- -GF -FI$(DDK)\inc\$(OS)\warning.h -Z7 -Od -Oi -Oy- -W3\r
\r
# Release\r
\r
-OUT_DIR = release64.km\r
+OUT_DIR = release64_ec.km\r
\r
DEFINES_D = -DWIN64=1 -D_WIN64=1 -D_AMD64_=1 -D_M_AMD64 -D_WINDOWS \\r
-DSTD_CALL -DCONDITION_HANDLING=1 \\r
-DNT_UP=1 -DNO_DISK_ACCESS -DNT_INST=0 -DWIN32=100 -D_NT1X_=100 \\r
-DWINNT=1 -D_WIN32_WINNT=0x0500 -DWIN32_LEAN_AND_MEAN=1 -DDEVL=1 \\r
-DFPO=1 -DNDEBUG -D_DLL=1 -D_IDWBUILD -D_UNICODE \\r
--DLITTLE_ENDIAN -DZRTP_USE_ENTERPRISE=0\r
+-DLITTLE_ENDIAN -DZRTP_USE_ENTERPRISE=1\r
\r
CFLAGS_D = $(DEFINES_D) -Zel -Zp8 -Gy -cbstring -Gz -QIfdiv- -QIf -Gi- -Gm- -GX- \\r
-GR- -GF -Oxs -Oy -FI$(DDK)\inc\$(OS)\warning.h -W3 -FAcs -Z7\r
--- /dev/null
+/*
+ * 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 <prz@mit.edu>.
+ * 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*/
--- /dev/null
+/*
+ * 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 <prz@mit.edu>.
+ * 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*/
--- /dev/null
+/*
+ * 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 <prz@mit.edu>.
+ * 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*/