freeswitch/libs/libzrtp/src/zrtp_crypto_pk.c
Travis Cross d2edcad66e Merge Phil Zimmermann's libzrtp as a FreeSWITCH library
Thanks to Phil Zimmermann for the code and for the license exception
we needed to include it.

There remains some build system integration work to be done before
this code will build properly in the FreeSWITCH tree.
2012-03-31 23:42:27 +00:00

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;
}