358 lines
13 KiB
C
358 lines
13 KiB
C
/*
|
|
* libZRTP SDK library, implements the ZRTP secure VoIP protocol.
|
|
* Copyright (c) 2006-2009 Philip R. Zimmermann. All rights reserved.
|
|
* Contact: http://philzimmermann.com
|
|
* For licensing and other legal details, see the file zrtp_legal.c.
|
|
*
|
|
* Viktor Krykun <v.krikun at zfoneproject.com>
|
|
*/
|
|
|
|
#include "zrtp.h"
|
|
|
|
#define _ZTU_ "zrtp dh"
|
|
|
|
/*============================================================================*/
|
|
/* Global DH Functions */
|
|
/*============================================================================*/
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
static zrtp_status_t zrtp_dh_init(void *s)
|
|
{
|
|
struct BigNum* p = NULL;
|
|
struct BigNum* p_1 = NULL;
|
|
uint8_t* p_data = NULL;
|
|
unsigned int p_data_length = 0;
|
|
zrtp_pk_scheme_t *self = (zrtp_pk_scheme_t *) s;
|
|
|
|
switch (self->base.id) {
|
|
case ZRTP_PKTYPE_DH2048:
|
|
p = &self->base.zrtp->P_2048;
|
|
p_1 = &self->base.zrtp->P_2048_1;
|
|
p_data = self->base.zrtp->P_2048_data;
|
|
p_data_length = sizeof(self->base.zrtp->P_2048_data);
|
|
break;
|
|
case ZRTP_PKTYPE_DH3072:
|
|
p = &self->base.zrtp->P_3072;
|
|
p_1 = &self->base.zrtp->P_3072_1;
|
|
p_data = self->base.zrtp->P_3072_data;
|
|
p_data_length = sizeof(self->base.zrtp->P_3072_data);
|
|
break;
|
|
default:
|
|
return zrtp_status_bad_param;
|
|
}
|
|
|
|
bnBegin(p);
|
|
bnInsertBigBytes(p, (const unsigned char *)p_data, 0, p_data_length);
|
|
|
|
bnBegin(p_1);
|
|
bnCopy(p_1, p);
|
|
bnSub(p_1, &self->base.zrtp->one);
|
|
|
|
return zrtp_status_ok;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
static zrtp_status_t zrtp_dh_free(void *s)
|
|
{
|
|
zrtp_pk_scheme_t *self = (zrtp_pk_scheme_t *) s;
|
|
switch (self->base.id) {
|
|
case ZRTP_PKTYPE_DH2048:
|
|
bnEnd(&self->base.zrtp->P_2048);
|
|
bnEnd(&self->base.zrtp->P_2048_1);
|
|
break;
|
|
case ZRTP_PKTYPE_DH3072:
|
|
bnEnd(&self->base.zrtp->P_3072);
|
|
bnEnd(&self->base.zrtp->P_3072_1);
|
|
break;
|
|
default:
|
|
return zrtp_status_bad_param;
|
|
}
|
|
|
|
return zrtp_status_ok;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
static struct BigNum* _zrtp_get_p(zrtp_pk_scheme_t *self)
|
|
{
|
|
struct BigNum* p = NULL;
|
|
switch (self->base.id) {
|
|
case ZRTP_PKTYPE_DH2048:
|
|
p = &self->base.zrtp->P_2048;
|
|
break;
|
|
case ZRTP_PKTYPE_DH3072:
|
|
p = &self->base.zrtp->P_3072;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return p;
|
|
}
|
|
|
|
static zrtp_status_t zrtp_dh_initialize( zrtp_pk_scheme_t *self,
|
|
zrtp_dh_crypto_context_t *dh_cc)
|
|
{
|
|
unsigned char* buffer = zrtp_sys_alloc(sizeof(zrtp_uchar128_t));
|
|
struct BigNum* p = _zrtp_get_p(self);
|
|
zrtp_time_t start_ts = zrtp_time_now();
|
|
|
|
ZRTP_LOG(1,(_ZTU_,"\tDH TEST: %.4s zrtp_dh_initialize() START. now=%llums.\n", self->base.type, start_ts));
|
|
|
|
if (!buffer) {
|
|
return zrtp_status_alloc_fail;
|
|
}
|
|
if (!p) {
|
|
zrtp_sys_free(buffer);
|
|
return zrtp_status_bad_param;
|
|
}
|
|
|
|
if (64 != zrtp_randstr(self->base.zrtp, buffer, 64)) {
|
|
zrtp_sys_free(buffer);
|
|
return zrtp_status_rng_fail;
|
|
}
|
|
|
|
bnBegin(&dh_cc->sv);
|
|
bnInsertBigBytes(&dh_cc->sv, (const unsigned char *)buffer, 0, self->sv_length);
|
|
bnBegin(&dh_cc->pv);
|
|
bnExpMod(&dh_cc->pv, &self->base.zrtp->G, &dh_cc->sv, p);
|
|
|
|
zrtp_sys_free(buffer);
|
|
|
|
ZRTP_LOG(1,(_ZTU_,"\tDH TEST: zrtp_dh_initialize() for %.4s was executed ts=%llums d=%llums.\n", self->base.type, zrtp_time_now(), zrtp_time_now()-start_ts));
|
|
return zrtp_status_ok;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
static zrtp_status_t zrtp_dh_compute( zrtp_pk_scheme_t *self,
|
|
zrtp_dh_crypto_context_t *dh_cc,
|
|
struct BigNum *dhresult,
|
|
struct BigNum *pv)
|
|
{
|
|
struct BigNum* p = _zrtp_get_p(self);
|
|
zrtp_time_t start_ts = zrtp_time_now();
|
|
if (!p) {
|
|
return zrtp_status_bad_param;
|
|
}
|
|
|
|
ZRTP_LOG(1,(_ZTU_,"\tDH TEST: %.4s zrtp_dh_compute() START. now=%llums.\n", self->base.type, start_ts));
|
|
|
|
bnExpMod(dhresult, pv, &dh_cc->sv, p);
|
|
ZRTP_LOG(1,(_ZTU_,"\tDH TEST: zrtp_dh_compute() for %.4s was executed ts=%llums d=%llums.\n", self->base.type, zrtp_time_now(), zrtp_time_now()-start_ts));
|
|
return zrtp_status_ok;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
static zrtp_status_t zrtp_dh_validate(zrtp_pk_scheme_t *self, struct BigNum *pv)
|
|
{
|
|
struct BigNum* p = _zrtp_get_p(self);
|
|
if (!p) {
|
|
return zrtp_status_bad_param;
|
|
}
|
|
|
|
if (!pv || 0 == bnCmp(pv, &self->base.zrtp->one) || 0 == bnCmp(pv, p)) {
|
|
return zrtp_status_fail;
|
|
} else {
|
|
return zrtp_status_ok;
|
|
}
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
static zrtp_status_t zrtp_dh_self_test(zrtp_pk_scheme_t *self)
|
|
{
|
|
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;
|
|
zrtp_time_t start_ts = zrtp_time_now();
|
|
|
|
ZRTP_LOG(3, (_ZTU_, "PKS %.4s testing... ", self->base.type));
|
|
|
|
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;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
#if (defined(ZRTP_ENABLE_EC) && (ZRTP_ENABLE_EC == 1))
|
|
extern zrtp_status_t zrtp_defaults_ec_pkt(zrtp_global_t* zrtp);
|
|
#endif
|
|
|
|
zrtp_status_t zrtp_defaults_pkt(zrtp_global_t* zrtp)
|
|
{
|
|
zrtp_pk_scheme_t* presh = zrtp_sys_alloc(sizeof(zrtp_pk_scheme_t));
|
|
zrtp_pk_scheme_t* dh2048 = zrtp_sys_alloc(sizeof(zrtp_pk_scheme_t));
|
|
zrtp_pk_scheme_t* dh3072 = zrtp_sys_alloc(sizeof(zrtp_pk_scheme_t));
|
|
zrtp_pk_scheme_t* multi = zrtp_sys_alloc(sizeof(zrtp_pk_scheme_t));
|
|
|
|
uint8_t P_2048_data[] =
|
|
{
|
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
|
|
0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
|
|
0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
|
|
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
|
|
0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
|
|
0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
|
|
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
|
|
0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
|
|
0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
|
|
0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
|
|
0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
|
|
0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
|
|
0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
|
|
0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
|
|
0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
|
|
0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
|
};
|
|
|
|
uint8_t P_3072_data[] =
|
|
{
|
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
|
|
0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
|
|
0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
|
|
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
|
|
0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
|
|
0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
|
|
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
|
|
0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
|
|
0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
|
|
0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
|
|
0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
|
|
0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
|
|
0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
|
|
0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
|
|
0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
|
|
0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33,
|
|
0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A,
|
|
0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
|
|
0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D,
|
|
0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64,
|
|
0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
|
|
0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2,
|
|
0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E,
|
|
0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
|
};
|
|
|
|
if (!dh2048 || !dh3072 || !presh || !multi) {
|
|
if (presh) {
|
|
zrtp_sys_free(presh);
|
|
}
|
|
if (dh2048) {
|
|
zrtp_sys_free(dh2048);
|
|
}
|
|
if (dh3072) {
|
|
zrtp_sys_free(dh3072);
|
|
}
|
|
if (multi) {
|
|
zrtp_sys_free(multi);
|
|
}
|
|
return zrtp_status_alloc_fail;
|
|
}
|
|
|
|
zrtp_memset(dh3072, 0, sizeof(zrtp_pk_scheme_t));
|
|
zrtp_memcpy(dh3072->base.type, ZRTP_DH3K, ZRTP_COMP_TYPE_SIZE);
|
|
dh3072->base.id = ZRTP_PKTYPE_DH3072;
|
|
dh3072->base.zrtp = zrtp;
|
|
dh3072->sv_length = 256/8;
|
|
dh3072->pv_length = 384;
|
|
dh3072->base.init = zrtp_dh_init;
|
|
dh3072->base.free = zrtp_dh_free;
|
|
dh3072->initialize = zrtp_dh_initialize;
|
|
dh3072->compute = zrtp_dh_compute;
|
|
dh3072->validate = zrtp_dh_validate;
|
|
dh3072->self_test = zrtp_dh_self_test;
|
|
zrtp_memcpy(zrtp->P_3072_data, P_3072_data, sizeof(P_3072_data));
|
|
zrtp_comp_register(ZRTP_CC_PKT, dh3072, zrtp);
|
|
|
|
zrtp_memset(dh2048, 0, sizeof(zrtp_pk_scheme_t));
|
|
zrtp_memcpy(dh2048->base.type, ZRTP_DH2K, ZRTP_COMP_TYPE_SIZE);
|
|
dh2048->base.id = ZRTP_PKTYPE_DH2048;
|
|
dh2048->base.zrtp = zrtp;
|
|
dh2048->sv_length = 256/8;
|
|
dh2048->pv_length = 256;
|
|
dh2048->base.init = zrtp_dh_init;
|
|
dh2048->base.free = zrtp_dh_free;
|
|
dh2048->initialize = zrtp_dh_initialize;
|
|
dh2048->compute = zrtp_dh_compute;
|
|
dh2048->validate = zrtp_dh_validate;
|
|
dh2048->self_test = zrtp_dh_self_test;
|
|
zrtp_memcpy(zrtp->P_2048_data, P_2048_data, sizeof(P_2048_data));
|
|
zrtp_comp_register(ZRTP_CC_PKT, dh2048, zrtp);
|
|
|
|
zrtp_memset(multi, 0, sizeof(zrtp_pk_scheme_t));
|
|
zrtp_memcpy(multi->base.type, ZRTP_MULT, ZRTP_COMP_TYPE_SIZE);
|
|
multi->base.id = ZRTP_PKTYPE_MULT;
|
|
zrtp_comp_register(ZRTP_CC_PKT, multi, zrtp);
|
|
|
|
zrtp_memset(presh, 0, sizeof(zrtp_pk_scheme_t));
|
|
zrtp_memcpy(presh->base.type, ZRTP_PRESHARED, ZRTP_COMP_TYPE_SIZE);
|
|
presh->base.id = ZRTP_PKTYPE_PRESH;
|
|
zrtp_comp_register(ZRTP_CC_PKT, presh, zrtp);
|
|
|
|
#if (defined(ZRTP_ENABLE_EC) && (ZRTP_ENABLE_EC == 1))
|
|
return zrtp_defaults_ec_pkt(zrtp);
|
|
#else
|
|
return zrtp_status_ok;
|
|
#endif
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
zrtp_status_t zrtp_prepare_pkt(zrtp_global_t* zrtp)
|
|
{
|
|
bnInit();
|
|
bnBegin(&zrtp->one);
|
|
bnSetQ(&zrtp->one, 1);
|
|
bnBegin(&zrtp->G);
|
|
bnSetQ(&zrtp->G, 2);
|
|
|
|
return zrtp_status_ok;
|
|
}
|
|
|
|
zrtp_status_t zrtp_done_pkt(zrtp_global_t* zrtp)
|
|
{
|
|
bnEnd(&zrtp->one);
|
|
bnEnd(&zrtp->G);
|
|
|
|
return zrtp_status_ok;
|
|
}
|