Skip to content

Commit

Permalink
Applied fixes for crypto in RX-to-TX cloning (#365)
Browse files Browse the repository at this point in the history
* Applied fixes for crypto in RX-to-TX cloning
  • Loading branch information
ethouris authored and rndi committed Jun 12, 2018
1 parent 1fa5736 commit febe51f
Show file tree
Hide file tree
Showing 6 changed files with 453 additions and 152 deletions.
251 changes: 160 additions & 91 deletions haicrypt/hcrypt.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,64 +38,23 @@ void HaiCrypt_DumpConfig(const HaiCrypt_Cfg* cfg);
#endif


int HaiCrypt_Create(const HaiCrypt_Cfg *cfg, HaiCrypt_Handle *phhc)
static hcrypt_Session* sHaiCrypt_PrepareHandle(const HaiCrypt_Cfg* cfg, HaiCrypt_CryptoDir tx)
{
hcrypt_Session *crypto;
hcrypt_Cipher *cipher;
cipher = (hcrypt_Cipher *)cfg->cipher;
unsigned char *mem_buf;
size_t mem_siz, inbuf_siz;
int tx;

*phhc = NULL;

ASSERT(NULL != cfg);

HCRYPT_LOG_INIT();
//Test log
HCRYPT_LOG(LOG_INFO, "creating crypto context(flags=0x%x)\n", cfg->flags);

if (!(HAICRYPT_CFG_F_CRYPTO & cfg->flags)) {
HCRYPT_LOG(LOG_INFO, "no supported flags set (0x%x)\n", cfg->flags);
return(-1);
} else if ((16 != cfg->key_len) /* SEK length */
&& (24 != cfg->key_len)
&& (32 != cfg->key_len)) {
HCRYPT_LOG(LOG_ERR, "invalid key length (%d). Expected: 16, 24, 32\n", (int)cfg->key_len);
return(-1);
} else if ((HAICRYPT_SECTYP_PASSPHRASE == cfg->secret.typ)
&& ((0 == cfg->secret.len) || (sizeof(cfg->secret.str) < cfg->secret.len))) { /* KEK length */
HCRYPT_LOG(LOG_ERR, "invalid secret passphrase length (%d)\n", (int)cfg->secret.len);
return(-1);
} else if ((HAICRYPT_SECTYP_PRESHARED == cfg->secret.typ)
&& (16 != cfg->key_len) /* SEK length */
&& (24 != cfg->key_len)
&& (32 != cfg->key_len)) {
HCRYPT_LOG(LOG_ERR, "invalid pre-shared secret length (%d)\n", (int)cfg->secret.len);
return(-1);
} else if ((HAICRYPT_SECTYP_PRESHARED == cfg->secret.typ)
&& (cfg->key_len > cfg->secret.len)) {
HCRYPT_LOG(LOG_ERR, "preshared secret length (%d) smaller than key length (%d)\n",
(int)cfg->secret.len, (int)cfg->key_len);
return(-1);
} else if (NULL == cfg->cipher) {
HCRYPT_LOG(LOG_ERR, "%s\n", "no cipher specified");
return(-1);
} else if (0 == cfg->data_max_len) {
HCRYPT_LOG(LOG_ERR, "%s\n", "no data_max_len specified");
return(-1);
}

HaiCrypt_DumpConfig(cfg);

cipher = (hcrypt_Cipher *)cfg->cipher;
tx = HAICRYPT_CFG_F_TX & cfg->flags;
HCRYPT_PRINTKEY(cfg->secret.str, cfg->secret.len, "cfgkey");

/*
* If cipher has no special input buffer alignment requirement,
* handle it in the crypto session.
*/
inbuf_siz = 0;
inbuf_siz = 0;
if (NULL == cipher->getinbuf) {
inbuf_siz = hcryptMsg_PaddedLen(cfg->data_max_len, 128/8);
}
Expand All @@ -105,9 +64,9 @@ int HaiCrypt_Create(const HaiCrypt_Cfg *cfg, HaiCrypt_Handle *phhc)
+ inbuf_siz;

crypto = malloc(mem_siz);
if (NULL == crypto){
if (NULL == crypto) {
HCRYPT_LOG(LOG_ERR, "%s\n", "malloc failed");
return(-1);
return NULL;
}
mem_buf = (unsigned char *)crypto;
mem_buf += sizeof(*crypto);
Expand All @@ -134,7 +93,7 @@ int HaiCrypt_Create(const HaiCrypt_Cfg *cfg, HaiCrypt_Handle *phhc)
default:
HCRYPT_LOG(LOG_ERR, "invalid xport: %d\n", cfg->xport);
free(crypto);
return(-1);
return NULL;
}

timerclear(&crypto->km.tx_last);
Expand All @@ -154,8 +113,55 @@ int HaiCrypt_Create(const HaiCrypt_Cfg *cfg, HaiCrypt_Handle *phhc)
crypto->cipher_data = crypto->cipher->open(cfg->data_max_len);
if (NULL == crypto->cipher_data) {
free(crypto);
return NULL;
}

return crypto;
}

int HaiCrypt_Create(const HaiCrypt_Cfg *cfg, HaiCrypt_Handle *phhc)
{
ASSERT(cfg != NULL);
ASSERT(phhc != NULL);

hcrypt_Session *crypto;
HaiCrypt_CryptoDir tx = (HaiCrypt_CryptoDir)(HAICRYPT_CFG_F_TX & cfg->flags);

*phhc = NULL;

HCRYPT_LOG_INIT();
//Test log
HCRYPT_LOG(LOG_INFO, "creating crypto context(flags=0x%x)\n", cfg->flags);

if (!(HAICRYPT_CFG_F_CRYPTO & cfg->flags)) {
HCRYPT_LOG(LOG_INFO, "no supported flags set (0x%x)\n", cfg->flags);
return(-1);
} else if ((16 != cfg->key_len) /* SEK length */
&& (24 != cfg->key_len)
&& (32 != cfg->key_len)) {
HCRYPT_LOG(LOG_ERR, "invalid key length (%d). Expected: 16, 24, 32\n", (int)cfg->key_len);
return(-1);
} else if ((HAICRYPT_SECTYP_PASSPHRASE == cfg->secret.typ)
&& ((0 == cfg->secret.len) || (sizeof(cfg->secret.str) < cfg->secret.len))) { /* KEK length */
HCRYPT_LOG(LOG_ERR, "invalid secret passphrase length (%d)\n", (int)cfg->secret.len);
return(-1);
} else if ((HAICRYPT_SECTYP_PRESHARED == cfg->secret.typ)
&& (cfg->key_len > cfg->secret.len)) {
HCRYPT_LOG(LOG_ERR, "preshared secret length (%d) smaller than key length (%d)\n",
(int)cfg->secret.len, (int)cfg->key_len);
return(-1);
} else if (NULL == cfg->cipher) {
HCRYPT_LOG(LOG_ERR, "%s\n", "no cipher specified");
return(-1);
} else if (0 == cfg->data_max_len) {
HCRYPT_LOG(LOG_ERR, "%s\n", "no data_max_len specified");
return(-1);
}

crypto = sHaiCrypt_PrepareHandle(cfg, tx);
if (!crypto)
return -1;

if (tx) { /* Encoder */
/* Configure initial context */
if (hcryptCtx_Tx_Init(crypto, &crypto->ctx_pair[0], cfg)
Expand Down Expand Up @@ -184,6 +190,50 @@ int HaiCrypt_Create(const HaiCrypt_Cfg *cfg, HaiCrypt_Handle *phhc)
return(0);
}

int HaiCrypt_ExtractConfig(HaiCrypt_Handle hhcSrc, HaiCrypt_Cfg* pcfg)
{
hcrypt_Session *crypto = (hcrypt_Session *)hhcSrc;
hcrypt_Ctx* ctx = crypto->ctx;
if (!ctx)
{
// Fall back to the first of the pair;
// Should this be not initialized, ignore it.
ctx = &crypto->ctx_pair[0];

// We assume that when ctx != NULL, it is active or keyed anyway.
if (ctx->status != HCRYPT_CTX_S_KEYED && ctx->status != HCRYPT_CTX_S_ACTIVE)
return -1;
}

pcfg->flags = HAICRYPT_CFG_F_CRYPTO;
if ((ctx->flags & HCRYPT_CTX_F_ENCRYPT) == HCRYPT_CTX_F_ENCRYPT)
pcfg->flags |= HAICRYPT_CFG_F_TX;

/* Set this explicitly - this use of this library is SRT only. */
pcfg->xport = HAICRYPT_XPT_SRT;
pcfg->cipher = crypto->cipher;
pcfg->key_len = ctx->cfg.key_len;
if (pcfg->key_len == 0) // not initialized - usual in RX
{
pcfg->key_len = ctx->sek_len;
}
pcfg->data_max_len = crypto->cfg.data_max_len;
pcfg->km_tx_period_ms = 0;//No HaiCrypt KM inject period, handled in SRT;

pcfg->km_refresh_rate_pkt = crypto->km.refresh_rate;
pcfg->km_pre_announce_pkt = crypto->km.pre_announce;

/* As SRT is using only the PASSPHRASE type, never PRESHARED,
* this is so assumed here, although there are completely no
* premises as to which is currently used by the hhcSrc.
*/
pcfg->secret.typ = HAICRYPT_SECTYP_PASSPHRASE;
pcfg->secret.len = ctx->cfg.pwd_len;
memcpy(pcfg->secret.str, ctx->cfg.pwd, pcfg->secret.len);

return 0;
}

int HaiCrypt_Clone(HaiCrypt_Handle hhcSrc, HaiCrypt_CryptoDir tx, HaiCrypt_Handle *phhc)
{
hcrypt_Session *cryptoSrc = (hcrypt_Session *)hhcSrc;
Expand All @@ -195,57 +245,76 @@ int HaiCrypt_Clone(HaiCrypt_Handle hhcSrc, HaiCrypt_CryptoDir tx, HaiCrypt_Handl

ASSERT(NULL != hhcSrc);

/*
* If cipher has no special input buffer alignment requirement,
* handle it in the crypto session.
*/
inbuf_siz = cryptoSrc->inbuf_siz ;
HCRYPT_LOG(LOG_INFO, "%s\n", "creating CLONED crypto context");

/* Allocate crypto session control struct */
mem_siz = sizeof(hcrypt_Session) // structure
+ inbuf_siz;
if (tx) {
HaiCrypt_Cfg crypto_config;
HaiCrypt_ExtractConfig(hhcSrc, &crypto_config);

cryptoClone = malloc(mem_siz);
if (NULL == cryptoClone){
HCRYPT_LOG(LOG_ERR, "%s\n", "malloc failed");
return(-1);
}
mem_buf = (unsigned char *)cryptoClone;
mem_buf += sizeof(*cryptoClone);
memset(cryptoClone, 0, sizeof(*cryptoClone));
memcpy(cryptoClone, cryptoSrc, sizeof(*cryptoClone));
/*
* Just invert the direction written in flags and use the
* standard way of creating the context, as you already have a config.
*/
crypto_config.flags |= HAICRYPT_CFG_F_TX;
cryptoClone = sHaiCrypt_PrepareHandle(&crypto_config, tx);
if (!cryptoClone)
return -1;

if (inbuf_siz) {
cryptoClone->inbuf = mem_buf;
mem_buf += inbuf_siz;
}
timerclear(&cryptoClone->km.tx_last);

/* Adjust pointers pointing into cryproSrc after copy
msg_info adn ciphers are extern statics so this is ok*/
cryptoClone->ctx_pair[0].alt = &cryptoClone->ctx_pair[1];
cryptoClone->ctx_pair[1].alt = &cryptoClone->ctx_pair[0];

/* create a new cipher (OpenSSL) context */
cryptoClone->cipher_data = cryptoClone->cipher->open(cryptoClone->cfg.data_max_len);
if (NULL == cryptoClone->cipher_data) {
//shred
free(cryptoClone);
return(-1);
}
if (tx) { /* Sender */
hcrypt_Ctx *ctx = cryptoClone->ctx = &cryptoClone->ctx_pair[0];
/* Configure initial context */
if (hcryptCtx_Tx_Init(cryptoClone, &cryptoClone->ctx_pair[0], &crypto_config)
|| hcryptCtx_Tx_Init(cryptoClone, &cryptoClone->ctx_pair[1], &crypto_config)) {
free(cryptoClone);
return(-1);
}
/* Clone keys for first (default) context from the source RX crypto */
if (hcryptCtx_Tx_CloneKey(cryptoClone, &cryptoClone->ctx_pair[0], cryptoSrc)) {
free(cryptoClone);
return(-1);
}
cryptoClone->ctx = &cryptoClone->ctx_pair[0];
cryptoClone->ctx->flags |= (HCRYPT_CTX_F_ANNOUNCE | HCRYPT_CTX_F_TTSEND);
cryptoClone->ctx->status = HCRYPT_CTX_S_ACTIVE;

} else { /* Receiver */

/*
* If cipher has no special input buffer alignment requirement,
* handle it in the crypto session.
*/
inbuf_siz = cryptoSrc->inbuf_siz ;

cryptoClone->ctx_pair[0].flags |= HCRYPT_CTX_F_ENCRYPT;
cryptoClone->ctx_pair[1].flags |= HCRYPT_CTX_F_ENCRYPT;
/* Allocate crypto session control struct */
mem_siz = sizeof(hcrypt_Session) // structure
+ inbuf_siz;

/* Set SEK in cipher */
if (cryptoClone->cipher->setkey(cryptoClone->cipher_data, ctx, ctx->sek, ctx->sek_len)) {
HCRYPT_LOG(LOG_ERR, "cipher setkey(sek[%zd]) failed\n", ctx->sek_len);
cryptoClone = malloc(mem_siz);
if (NULL == cryptoClone) {
HCRYPT_LOG(LOG_ERR, "%s\n", "malloc failed");
return(-1);
}
ctx->status = HCRYPT_CTX_S_ACTIVE;
} else { /* Receiver */
mem_buf = (unsigned char *)cryptoClone;
mem_buf += sizeof(*cryptoClone);
memcpy(cryptoClone, cryptoSrc, sizeof(*cryptoClone));

if (inbuf_siz) {
cryptoClone->inbuf = mem_buf;
mem_buf += inbuf_siz;
}
timerclear(&cryptoClone->km.tx_last);

/* Adjust pointers pointing into cryproSrc after copy
msg_info adn ciphers are extern statics so this is ok*/
cryptoClone->ctx_pair[0].alt = &cryptoClone->ctx_pair[1];
cryptoClone->ctx_pair[1].alt = &cryptoClone->ctx_pair[0];

/* create a new cipher (OpenSSL) context */
cryptoClone->cipher_data = cryptoClone->cipher->open(cryptoClone->cfg.data_max_len);
if (NULL == cryptoClone->cipher_data) {
//shred
free(cryptoClone);
return(-1);
}


/* Configure contexts */
if (hcryptCtx_Rx_Init(cryptoClone, &cryptoClone->ctx_pair[0], NULL)
Expand Down
1 change: 1 addition & 0 deletions haicrypt/hcrypt.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ int hcryptCtx_GenSecret(hcrypt_Session *crypto, hcrypt_Ctx *ctx);

int hcryptCtx_Tx_Init(hcrypt_Session *crypto, hcrypt_Ctx *ctx, const HaiCrypt_Cfg *cfg);
int hcryptCtx_Tx_Rekey(hcrypt_Session *crypto, hcrypt_Ctx *ctx);
int hcryptCtx_Tx_CloneKey(hcrypt_Session *crypto, hcrypt_Ctx *ctx, const hcrypt_Session* cryptoSrc);
int hcryptCtx_Tx_Refresh(hcrypt_Session *crypto);
int hcryptCtx_Tx_PreSwitch(hcrypt_Session *crypto);
int hcryptCtx_Tx_Switch(hcrypt_Session *crypto);
Expand Down
Loading

0 comments on commit febe51f

Please sign in to comment.