1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

SRT: Upgrade libsrt from 1.4.1 to 1.5.1. v6.0.12 (#3362)

Co-authored-by: winlin <winlin@vip.126.com>
This commit is contained in:
john 2023-01-04 19:56:33 +08:00 committed by GitHub
parent 7a56208f2f
commit fe086dfc31
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
143 changed files with 38185 additions and 15108 deletions

View file

@ -1,5 +1,5 @@
#ifndef INC__CRYSPR_CONFIG_H
#define INC__CRYSPR_CONFIG_H
#ifndef INC_SRT_CRYSPR_CONFIG_H
#define INC_SRT_CRYSPR_CONFIG_H
// Size of the single block for encryption.
// This might need tweaking for particular implementation library.
@ -8,14 +8,22 @@
#if defined(USE_OPENSSL)
#include "cryspr-openssl.h"
#define cryspr4SRT() crysprOpenSSL()
#define CRYSPR_IMPL_DESC "OpenSSL-AES"
#elif defined(USE_OPENSSL_EVP)
#include "cryspr-openssl-evp.h"
#define cryspr4SRT() crysprOpenSSL_EVP()
#define CRYSPR_IMPL_DESC "OpenSSL-EVP"
#elif defined(USE_GNUTLS)
#include "cryspr-gnutls.h"
#define cryspr4SRT() crysprGnuTLS()
#define CRYSPR_IMPL_DESC "GnuTLS"
#elif defined(USE_MBEDTLS)
#include "cryspr-mbedtls.h"
#define cryspr4SRT() crysprMbedtls()
#define CRYSPR_IMPL_DESC "MbedTLS"
#else
#error Cryspr implementation not selected. Please define USE_* + OPENSSL/GNUTLS/MBEDTLS.
#define CRYSPR_IMPL_DESC "No Cipher"
#endif

View file

@ -13,6 +13,8 @@
written by
Haivision Systems Inc.
2022-05-19 (jdube)
CRYSPR2 adaptation
2019-06-27 (jdube)
GnuTLS/Nettle CRYSPR/4SRT (CRYypto Service PRovider for SRT)
*****************************************************************************/
@ -24,6 +26,10 @@ written by
typedef struct tag_crysprGnuTLS_AES_cb {
CRYSPR_cb ccb; /* CRYSPR control block */
/* Add other cryptolib specific data here */
#ifdef CRYSPR2
CRYSPR_AESCTX aes_kek_buf; /* Key Encrypting Key (KEK) */
CRYSPR_AESCTX aes_sek_buf[2]; /* even/odd Stream Encrypting Key (SEK) */
#endif
} crysprGnuTLS_cb;
@ -33,11 +39,14 @@ int crysprGnuTLS_Prng(unsigned char *rn, int len)
}
int crysprGnuTLS_AES_SetKey(
int cipher_type, /* One of HCRYPT_CTX_MODE_[CLRTXT|AESECB|AESCTR] */
bool bEncrypt, /* true:encrypt key, false:decrypt key*/
const unsigned char *kstr, /* key string */
size_t kstr_len, /* kstr length in bytes (16, 24, or 32 bytes (for AES128,AES192, or AES256) */
CRYSPR_AESCTX *aes_key) /* Cryptolib Specific AES key context */
{
(void)cipher_type;
if (bEncrypt) { /* Encrypt key */
if (!(kstr_len == 16 || kstr_len == 24 || kstr_len == 32)) {
HCRYPT_LOG(LOG_ERR, "%s", "AES_set_encrypt_key(kek) bad length\n");
@ -114,6 +123,31 @@ int crysprGnuTLS_AES_CtrCipher( /* AES-CTR128 Encryption */
return 0;
}
#ifdef CRYSPR2
static CRYSPR_cb *crysprGnuTLS_Open(CRYSPR_methods *cryspr, size_t max_len)
{
crysprGnuTLS_cb *aes_data;
CRYSPR_cb *cryspr_cb;
aes_data = (crysprGnuTLS_cb *)crysprHelper_Open(cryspr, sizeof(crysprGnuTLS_cb), max_len);
if (NULL == aes_data) {
HCRYPT_LOG(LOG_ERR, "crysprHelper_Open(%p, %zd, %zd) failed\n", cryspr, sizeof(crysprGnuTLS_cb), max_len);
return(NULL);
}
aes_data->ccb.aes_kek = &aes_data->aes_kek_buf; //key encrypting key
aes_data->ccb.aes_sek[0] = &aes_data->aes_sek_buf[0]; //stream encrypting key
aes_data->ccb.aes_sek[1] = &aes_data->aes_sek_buf[1]; //stream encrypting key
return(&aes_data->ccb);
}
static int crysprGnuTLS_Close(CRYSPR_cb *cryspr_cb)
{
return(crysprHelper_Close(cryspr_cb));
}
#endif /* CRYSPR2 */
#ifdef CRYSPR_HAS_PBKDF2
/*
* Password-based Key Derivation Function
@ -157,8 +191,13 @@ CRYSPR_methods *crysprGnuTLS(void)
#endif
//--Crypto Session (Top API)
#ifdef CRYSPR2
crysprGnuTLS_methods.open = crysprGnuTLS_Open;
crysprGnuTLS_methods.close = crysprGnuTLS_Close;
#else /* CRYSPR2 */
// crysprGnuTLS_methods.open =
// crysprGnuTLS_methods.close =
#endif /* CRYSPR2 */
//--Keying material (km) encryption
#if CRYSPR_HAS_PBKDF2
crysprGnuTLS_methods.km_pbkdf2 = crysprGnuTLS_KmPbkdf2;

View file

@ -13,6 +13,8 @@
written by
Haivision Systems Inc.
2022-05-19 (jdube)
CRYSPR2 adaptation
2019-06-27 (jdube)
GnuTLS/Nettle CRYSPR/4SRT (CRYypto Service PRovider for SRT)
*****************************************************************************/
@ -29,11 +31,14 @@ written by
// Static members of cryspr::mbedtls class.
static mbedtls_ctr_drbg_context crysprMbedtls_ctr_drbg;
static mbedtls_entropy_context crysprMbedtls_entropy;
static mbedtls_md_context_t crysprMbedtls_mdctx;
typedef struct tag_crysprGnuTLS_AES_cb {
CRYSPR_cb ccb; /* CRYSPR control block */
/* Add other cryptolib specific data here */
#ifdef CRYSPR2
CRYSPR_AESCTX aes_kek_buf; /* Key Encrypting Key (KEK) */
CRYSPR_AESCTX aes_sek_buf[2]; /* even/odd Stream Encrypting Key (SEK) */
#endif
} crysprMbedtls_cb;
@ -49,18 +54,23 @@ int crysprMbedtls_Prng(unsigned char *rn, int len)
}
int crysprMbedtls_AES_SetKey(
int cipher_type, /* One of HCRYPT_CTX_MODE_[CLRTXT|AESECB|AESCTR] */
bool bEncrypt, /* true:encrypt key, false:decrypt key*/
const unsigned char *kstr, /* key string */
size_t kstr_len, /* kstr length in bytes (16, 24, or 32 bytes, for AES128,AES192, or AES256) */
CRYSPR_AESCTX *aes_key) /* Cryptolib Specific AES key context */
{
(void)cipher_type;
if (!(kstr_len == 16 || kstr_len == 24 || kstr_len == 32)) {
HCRYPT_LOG(LOG_ERR, "%s", "AES_set_encrypt_key(kek) bad length\n");
return -1;
}
int ret;
#ifdef CRYSPR2
(void)cipher_type;
#endif
// mbedtls uses the "bits" convention (128, 192, 254), just like openssl.
// kstr_len is in "bytes" convention (16, 24, 32).
@ -146,6 +156,31 @@ int crysprMbedtls_AES_CtrCipher( /* AES-CTR128 Encryption */
return 0;
}
#ifdef CRYSPR2
static CRYSPR_cb *crysprMbedtls_Open(CRYSPR_methods *cryspr, size_t max_len)
{
crysprMbedtls_cb *aes_data;
CRYSPR_cb *cryspr_cb;
aes_data = (crysprMbedtls_cb *)crysprHelper_Open(cryspr, sizeof(crysprMbedtls_cb), max_len);
if (NULL == aes_data) {
HCRYPT_LOG(LOG_ERR, "crysprHelper_Open(%p, %zd, %zd) failed\n", cryspr, sizeof(crysprMbedtls_cb), max_len);
return(NULL);
}
aes_data->ccb.aes_kek = &aes_data->aes_kek_buf; //key encrypting key
aes_data->ccb.aes_sek[0] = &aes_data->aes_sek_buf[0]; //stream encrypting key
aes_data->ccb.aes_sek[1] = &aes_data->aes_sek_buf[1]; //stream encrypting key
return(&aes_data->ccb);
}
static int crysprMbedtls_Close(CRYSPR_cb *cryspr_cb)
{
return(crysprHelper_Close(cryspr_cb));
}
#endif /* CRYSPR2 */
/*
* Password-based Key Derivation Function
*/
@ -161,10 +196,30 @@ int crysprMbedtls_KmPbkdf2(
{
(void)cryspr_cb;
int ret = mbedtls_pkcs5_pbkdf2_hmac(&crysprMbedtls_mdctx,
const mbedtls_md_info_t* ifo = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
if ( ifo == NULL ) {
// XXX report error, log?
return -1;
}
mbedtls_md_context_t mdctx;
mbedtls_md_init(&mdctx);
const int yes_use_hmac = 1;
int ret;
if ( (ret = mbedtls_md_setup(&mdctx, ifo, yes_use_hmac)) != 0 ) {
mbedtls_md_free(&mdctx);
// XXX report error, log?
return ret;
}
ret = mbedtls_pkcs5_pbkdf2_hmac(&mdctx,
(unsigned char*)passwd, passwd_len, salt, salt_len,
itr, key_len, out);
mbedtls_md_free(&mdctx);
if (ret == 0)
return 0;
@ -196,8 +251,13 @@ CRYSPR_methods *crysprMbedtls(void)
#endif
//--Crypto Session (Top API)
#ifdef CRYSPR2
crysprMbedtls_methods.open = crysprMbedtls_Open;
crysprMbedtls_methods.close = crysprMbedtls_Close;
#else
// crysprMbedtls_methods.open =
// crysprMbedtls_methods.close =
#endif
//--Keying material (km) encryption
crysprMbedtls_methods.km_pbkdf2 = crysprMbedtls_KmPbkdf2;
// crysprMbedtls_methods.km_setkey =
@ -220,14 +280,6 @@ CRYSPR_methods *crysprMbedtls(void)
return NULL;
}
// Ok, mbedtls with all flexibility you couldn't make it more complicated.
mbedtls_md_init(&crysprMbedtls_mdctx);
const mbedtls_md_info_t* ifo = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
const int yes_use_hmac = 1;
mbedtls_md_setup(&crysprMbedtls_mdctx, ifo, yes_use_hmac);
return(&crysprMbedtls_methods);
}

View file

@ -52,10 +52,10 @@ written by
/*
#define CRYSPR_AESCTX to the CRYSPR specifix AES key context object.
This type reserves room in the CRYPSPR control block for Haicrypt KEK and SEK
It is set from hte keystring through CRYSPR_methods.aes_set_key and passed
It is set from the keystring through CRYSPR_methods.aes_set_key and passed
to CRYSPR_methods.aes_XXX.
*/
typedef struct mbedtls_aes_context CRYSPR_AESCTX; /* CRYpto Service PRovider AES key context */
typedef mbedtls_aes_context CRYSPR_AESCTX; /* CRYpto Service PRovider AES key context */
struct tag_CRYSPR_methods *crysprMbedtls(void);

View file

@ -0,0 +1,335 @@
/*
* SRT - Secure, Reliable, Transport
* Copyright (c) 2019 Haivision Systems Inc.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*/
/*****************************************************************************
written by
Haivision Systems Inc.
2022-05-19 (jdube)
OpenSSL EVP CRYSPR/4SRT (CRYypto Service PRovider for SRT).
*****************************************************************************/
#include "hcrypt.h"
#include <string.h>
typedef struct tag_crysprOpenSSL_EVP_cb
{
CRYSPR_cb ccb;
/* Add cryptolib specific data here */
} crysprOpenSSL_EVP_cb;
int crysprOpenSSL_EVP_Prng(unsigned char* rn, int len)
{
return (RAND_bytes(rn, len) <= 0 ? -1 : 0);
}
const EVP_CIPHER* (*Xcipher_fnptr)(void) = EVP_aes_128_ecb;
const EVP_CIPHER* (*_crysprOpenSSL_EVP_cipher_fnptr[][3])(void) = {
{NULL, NULL, NULL},
{EVP_aes_128_ecb, EVP_aes_192_ecb, EVP_aes_256_ecb},
{EVP_aes_128_ctr, EVP_aes_192_ctr, EVP_aes_256_ctr},
};
int crysprOpenSSL_EVP_AES_SetKey(
int cipher_type, /* One of HCRYPT_CTX_MODE_[CLRTXT|AESECB|AESCTR] */
bool bEncrypt, /* true Enxcrypt key, false: decrypt */
const unsigned char* kstr, /* key sttring*/
size_t kstr_len, /* kstr len in bytes (16, 24, or 32 bytes (for AES128, AES192, or AES256) */
CRYSPR_AESCTX* aes_key) /* CRYpto Service PRovider AES Key context */
{
const EVP_CIPHER* cipher = NULL;
int idxKlen = (kstr_len / 8) - 2; /* key_len index in cipher_fnptr array in [0,1,2] range */
switch (cipher_type)
{
case HCRYPT_CTX_MODE_CLRTXT:
return 0;
case HCRYPT_CTX_MODE_AESECB:
break;
case HCRYPT_CTX_MODE_AESCTR:
#if !CRYSPR_HAS_AESCTR
/* internal implementation of AES-CTR using crypto lib's AES-ECB */
cipher_type = HCRYPT_CTX_MODE_AESECB;
#endif
break;
default:
HCRYPT_LOG(LOG_ERR,
"invalid cipher type (%d). Expected: [%d..%d]\n",
cipher_type,
HCRYPT_CTX_MODE_AESECB,
HCRYPT_CTX_MODE_AESCTR);
return (-1);
}
switch (kstr_len)
{
case 128 / 8:
case 192 / 8:
case 256 / 8:
break;
default:
HCRYPT_LOG(LOG_ERR, "invalid key length (%d). Expected: 16, 24, 32\n", (int)kstr_len);
return -1;
}
cipher = _crysprOpenSSL_EVP_cipher_fnptr[cipher_type][idxKlen]();
if (bEncrypt)
{ /* Encrypt key */
if (!EVP_EncryptInit_ex(aes_key, cipher, NULL, kstr, NULL))
{
HCRYPT_LOG(LOG_ERR, "%s", "EVP_CipherInit_ex(kek) failed\n");
return (-1);
}
}
else
{ /* Decrypt key */
if (!EVP_DecryptInit_ex(aes_key, cipher, NULL, kstr, NULL))
{
HCRYPT_LOG(LOG_ERR, "%s", "EVP_CipherInit_ex(kek) failed\n");
return (-1);
}
}
return (0);
}
static CRYSPR_cb* crysprOpenSSL_EVP_Open(CRYSPR_methods* cryspr, size_t max_len)
{
CRYSPR_cb* cryspr_cb = crysprHelper_Open(cryspr, sizeof(*cryspr_cb), max_len);
if (NULL == cryspr_cb)
{
HCRYPT_LOG(LOG_ERR, "crysprFallback_Open(%p, %zd) failed\n", cryspr, max_len);
return (NULL);
}
cryspr_cb->aes_kek = EVP_CIPHER_CTX_new();
cryspr_cb->aes_sek[0] = EVP_CIPHER_CTX_new();
cryspr_cb->aes_sek[1] = EVP_CIPHER_CTX_new();
return (cryspr_cb);
}
static int crysprOpenSSL_EVP_Close(CRYSPR_cb* cryspr_cb)
{
if (NULL != cryspr_cb)
{
EVP_CIPHER_CTX_free(cryspr_cb->aes_sek[0]);
EVP_CIPHER_CTX_free(cryspr_cb->aes_sek[1]);
EVP_CIPHER_CTX_free(cryspr_cb->aes_kek);
}
return (crysprHelper_Close(cryspr_cb));
}
#if !(CRYSPR_HAS_AESCTR && CRYSPR_HAS_AESKWRAP)
int crysprOpenSSL_EVP_AES_EcbCipher(bool bEncrypt, /* true:encrypt, false:decrypt */
CRYSPR_AESCTX* aes_key, /* CRYpto Service PRovider AES Key context */
const unsigned char* indata, /* src (clear text if encrypt, cipher text otherwise)*/
size_t inlen, /* indata length */
unsigned char* out_txt, /* dst (cipher text if encrypt, clear text otherwise) */
size_t* outlen_p) /* in/out dst len */
{
int nmore = inlen % CRYSPR_AESBLKSZ; /* bytes in last incomplete block */
int nblk = inlen / CRYSPR_AESBLKSZ + (nmore ? 1 : 0); /* blocks including incomplete */
size_t outsiz = (outlen_p ? *outlen_p : 0);
int c_len = 0, f_len = 0;
(void)bEncrypt; // not needed, alreadydefined in context
if (outsiz % CRYSPR_AESBLKSZ)
{
HCRYPT_LOG(LOG_ERR, "%s\n", "EcbCipher() no room for PKCS7 padding");
return (-1); /* output buf size must be a multiple of AES block size (16) */
}
if ((outsiz > 16) && ((int)outsiz < (nblk * CRYSPR_AESBLKSZ)))
{
HCRYPT_LOG(LOG_ERR, "%s\n", "EcbCipher() no room for PKCS7 padding");
return (-1); /* output buf size must have room for PKCS7 padding */
}
/* allows reusing of 'e' for multiple encryption cycles */
if (!EVP_CipherInit_ex(aes_key, NULL, NULL, NULL, NULL, -1))
{
HCRYPT_LOG(LOG_ERR, "EVP_CipherInit_ex(%p,NULL,...,-1) failed\n", aes_key);
return -1;
}
if (!EVP_CIPHER_CTX_set_padding(aes_key, 0))
{
HCRYPT_LOG(LOG_ERR, "%s\n", "EVP_CIPHER_CTX_set_padding(%p) failed", aes_key);
return -1;
}
/* update ciphertext, c_len is filled with the length of ciphertext generated,
* cryptoPtr->cipher_in_len is the size of plain/cipher text in bytes
*/
if (!EVP_CipherUpdate(aes_key, out_txt, &c_len, indata, inlen))
{
HCRYPT_LOG(LOG_ERR, "EVP_CipherUpdate(%p, out, %d, in, %d) failed\n", aes_key, c_len, inlen);
return -1;
}
/* update ciphertext with the final remaining bytes */
/* Useless with pre-padding */
f_len = 0;
if (0 == EVP_CipherFinal_ex(aes_key, &out_txt[c_len], &f_len))
{
#if ENABLE_HAICRYPT_LOGGING
char szErrBuf[256];
HCRYPT_LOG(LOG_ERR,
"EVP_CipherFinal_ex(ctx,&out[%d],%d)) failed: %s\n",
c_len,
f_len,
ERR_error_string(ERR_get_error(), szErrBuf));
#endif /*ENABLE_HAICRYPT_LOGGING*/
return -1;
}
if (outlen_p != NULL) *outlen_p = nblk * CRYSPR_AESBLKSZ;
return 0;
}
#endif /* !(CRYSPR_HAS_AESCTR && CRYSPR_HAS_AESKWRAP) */
int crysprOpenSSL_EVP_AES_CtrCipher(bool bEncrypt, /* true:encrypt, false:decrypt */
CRYSPR_AESCTX* aes_key, /* CRYpto Service PRovider AES Key context */
unsigned char* iv, /* iv */
const unsigned char* indata, /* src */
size_t inlen, /* length */
unsigned char* out_txt) /* dest */
{
int c_len, f_len;
(void)bEncrypt;
/* allows reusing of 'e' for multiple encryption cycles */
if (!EVP_CipherInit_ex(aes_key, NULL, NULL, NULL, iv, -1))
{
HCRYPT_LOG(LOG_ERR, "%s\n", "EVP_CipherInit_ex() failed");
return -1;
}
if (!EVP_CIPHER_CTX_set_padding(aes_key, 0))
{
HCRYPT_LOG(LOG_ERR, "%s\n", "EVP_CIPHER_CTX_set_padding() failed");
return -1;
}
/* update ciphertext, c_len is filled with the length of ciphertext generated,
* cryptoPtr->cipher_in_len is the size of plain/cipher text in bytes
*/
if (!EVP_CipherUpdate(aes_key, out_txt, &c_len, indata, inlen))
{
HCRYPT_LOG(LOG_ERR, "%s\n", "EVP_CipherUpdate() failed");
return -1;
}
/* update ciphertext with the final remaining bytes */
/* Useless with pre-padding */
f_len = 0;
if (0 == EVP_CipherFinal_ex(aes_key, &out_txt[c_len], &f_len))
{
#if ENABLE_HAICRYPT_LOGGING
char szErrBuf[256];
HCRYPT_LOG(LOG_ERR,
"EVP_CipherFinal_ex(ctx,&out[%d],%d)) failed: %s\n",
c_len,
f_len,
ERR_error_string(ERR_get_error(), szErrBuf));
#endif /*ENABLE_HAICRYPT_LOGGING*/
return -1;
}
return 0;
}
/*
* Password-based Key Derivation Function
*/
int crysprOpenSSL_EVP_KmPbkdf2(CRYSPR_cb* cryspr_cb,
char* passwd, /* passphrase */
size_t passwd_len, /* passphrase len */
unsigned char* salt, /* salt */
size_t salt_len, /* salt_len */
int itr, /* iterations */
size_t key_len, /* key_len */
unsigned char* out) /* derived key */
{
(void)cryspr_cb;
int rc = PKCS5_PBKDF2_HMAC_SHA1(passwd, passwd_len, salt, salt_len, itr, key_len, out);
return (rc == 1 ? 0 : -1);
}
#if CRYSPR_HAS_AESKWRAP
int crysprOpenSSL_EVP_KmWrap(CRYSPR_cb* cryspr_cb, unsigned char* wrap, const unsigned char* sek, unsigned int seklen)
{
crysprOpenSSL_EVP_cb* aes_data = (crysprOpenSSL_EVP_cb*)cryspr_cb;
EVP_CIPHER_CTX* kek = CRYSPR_GETKEK(cryspr_cb); // key encrypting key
return (((seklen + HAICRYPT_WRAPKEY_SIGN_SZ) == (unsigned int)AES_wrap_key(kek, NULL, wrap, sek, seklen)) ? 0 : -1);
}
int crysprOpenSSL_EVP_KmUnwrap(CRYSPR_cb* cryspr_cb,
unsigned char* sek, // Stream encrypting key
const unsigned char* wrap,
unsigned int wraplen)
{
crysprOpenSSL_EVP_cb* aes_data = (crysprOpenSSL_EVP_cb*)cryspr_cb;
EVP_CIPHER_CTX* kek = CRYSPR_GETKEK(cryspr_cb); // key encrypting key
return (((wraplen - HAICRYPT_WRAPKEY_SIGN_SZ) == (unsigned int)AES_unwrap_key(kek, NULL, sek, wrap, wraplen)) ? 0
: -1);
}
#endif /*CRYSPR_HAS_AESKWRAP*/
static CRYSPR_methods crysprOpenSSL_EVP_methods;
CRYSPR_methods* crysprOpenSSL_EVP(void)
{
if (NULL == crysprOpenSSL_EVP_methods.open)
{
crysprInit(&crysprOpenSSL_EVP_methods); // Default/fallback methods
crysprOpenSSL_EVP_methods.prng = crysprOpenSSL_EVP_Prng;
//--CryptoLib Primitive API-----------------------------------------------
crysprOpenSSL_EVP_methods.aes_set_key = crysprOpenSSL_EVP_AES_SetKey;
#if CRYSPR_HAS_AESCTR
crysprOpenSSL_EVP_methods.aes_ctr_cipher = crysprOpenSSL_EVP_AES_CtrCipher;
#endif
#if !(CRYSPR_HAS_AESCTR && CRYSPR_HAS_AESKWRAP)
/* AES-ECB only required if cryspr has no AES-CTR and no AES KeyWrap */
/* OpenSSL has both AESCTR and AESKWRP and the AESECB wrapper is only used
to test the falback methods */
crysprOpenSSL_EVP_methods.aes_ecb_cipher = crysprOpenSSL_EVP_AES_EcbCipher;
#endif
#if !CRYSPR_HAS_PBKDF2
crysprOpenSSL_EVP_methods.sha1_msg_digest = NULL; // Required to use eventual default/fallback KmPbkdf2
#endif
//--Crypto Session API-----------------------------------------
crysprOpenSSL_EVP_methods.open = crysprOpenSSL_EVP_Open;
crysprOpenSSL_EVP_methods.close = crysprOpenSSL_EVP_Close;
//--Keying material (km) encryption
#if CRYSPR_HAS_PBKDF2
crysprOpenSSL_EVP_methods.km_pbkdf2 = crysprOpenSSL_EVP_KmPbkdf2;
#else
#error There is no default/fallback method for PBKDF2
#endif
// crysprOpenSSL_EVP_methods.km_setkey =
#if CRYSPR_HAS_AESKWRAP
crysprOpenSSL_EVP_methods.km_wrap = crysprOpenSSL_EVP_KmWrap;
crysprOpenSSL_EVP_methods.km_unwrap = crysprOpenSSL_EVP_KmUnwrap;
#endif
//--Media stream (ms) encryption
// crysprOpenSSL_EVP_methods.ms_setkey =
// crysprOpenSSL_EVP_methods.ms_encrypt =
// crysprOpenSSL_EVP_methods.ms_decrypt =
}
return (&crysprOpenSSL_EVP_methods);
}

View file

@ -0,0 +1,63 @@
/*
* SRT - Secure, Reliable, Transport
* Copyright (c) 2019 Haivision Systems Inc.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*/
/*****************************************************************************
written by
Haivision Systems Inc.
2022-05-19 (jdube)
OpenSSL EVP AES CRYSPR/4SRT (CRYypto Service PRovider for SRT).
*****************************************************************************/
#ifndef CRYSPR_OPENSSL_H
#define CRYSPR_OPENSSL_H
#include <openssl/evp.h> /* PKCS5_xxx() */
#include <openssl/aes.h> /* AES_xxx() */
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(OPENSSL_IS_BORINGSSL))
#include <openssl/modes.h> /* CRYPTO_xxx() */
#endif
#include <openssl/rand.h>
#include <openssl/err.h>
#include <openssl/opensslv.h> /* OPENSSL_VERSION_NUMBER */
/* Define CRYSPR_HAS_AESCTR to 1 if this CRYSPR has AESCTR cipher mode
if not set it 0 to use enable CTR cipher mode implementation using ECB cipher mode
and provide the aes_ecb_cipher method.
*/
#define CRYSPR_HAS_AESCTR 1
/* Define CRYSPR_HAS_AESKWRAP to 1 if this CRYSPR has AES Key Wrap
if not set to 0 to enable default/fallback crysprFallback_AES_WrapKey/crysprFallback_AES_UnwrapKey methods
and provide the aes_ecb_cipher method .
*/
#if 1 // Force internal AES-WRAP (using AES-ECB) until implemented with EVP (OPENSSL_VERSION_NUMBER < 0x00xxxxxxL)
#define CRYSPR_HAS_AESKWRAP 0
#else
#define CRYSPR_HAS_AESKWRAP 1
#endif
/* Define CRYSPR_HAS_PBKDF2 to 1 if this CRYSPR has SHA1-HMAC Password-based Key Derivaion Function 2
if not set to 0 to enable not-yet-implemented/fallback crysprFallback.km_pbkdf2 method
and provide the sha1_msg_digest method.
*/
#define CRYSPR_HAS_PBKDF2 1 /* Define to 1 if CRYSPR has Password-based Key Derivaion Function 2 */
/*
#define CRYSPR_AESCTX to the CRYSPR specifix AES key context object.
This type reserves room in the CRYPSPR control block for Haicrypt KEK and SEK
It is set from hte keystring through CRYSPR_methods.aes_set_key and passed
to CRYSPR_methods.aes_*.
*/
typedef EVP_CIPHER_CTX CRYSPR_AESCTX; /* CRYpto Service PRovider AES key context */
struct tag_CRYSPR_methods* crysprOpenSSL_EVP(void);
#endif /* CRYSPR_OPENSSL_H */

View file

@ -13,18 +13,23 @@
written by
Haivision Systems Inc.
2022-05-19 (jdube)
CRYSPR2 adaptation
2019-06-26 (jdube)
OpenSSL CRYSPR/4SRT (CRYypto Service PRovider for SRT).
OpenSSL Direct AES CRYSPR/4SRT (CRYypto Service PRovider for SRT).
*****************************************************************************/
#include "hcrypt.h"
#include <string.h>
typedef struct tag_crysprOpenSSL_AES_cb {
CRYSPR_cb ccb;
/* Add cryptolib specific data here */
CRYSPR_cb ccb;
/* Add cryptolib specific data here */
#ifdef CRYSPR2
CRYSPR_AESCTX aes_kek_buf; /* Key Encrypting Key (KEK) */
CRYSPR_AESCTX aes_sek_buf[2]; /* even/odd Stream Encrypting Key (SEK) */
#endif
} crysprOpenSSL_cb;
@ -34,11 +39,14 @@ int crysprOpenSSL_Prng(unsigned char *rn, int len)
}
int crysprOpenSSL_AES_SetKey(
int cipher_type, /* One of HCRYPT_CTX_MODE_[CLRTXT|AESECB|AESCTR] */
bool bEncrypt, /* true Enxcrypt key, false: decrypt */
const unsigned char *kstr, /* key sttring*/
size_t kstr_len, /* kstr len in bytes (16, 24, or 32 bytes (for AES128,AES192, or AES256) */
CRYSPR_AESCTX *aes_key) /* CRYpto Service PRovider AES Key context */
{
(void)cipher_type;
if (bEncrypt) { /* Encrypt key */
if (AES_set_encrypt_key(kstr, kstr_len * 8, aes_key)) {
HCRYPT_LOG(LOG_ERR, "%s", "AES_set_encrypt_key(kek) failed\n");
@ -123,7 +131,24 @@ int crysprOpenSSL_AES_CtrCipher(
#endif
return 0;
}
#ifdef CRYSPR2
static CRYSPR_cb *crysprOpenSSL_Open(CRYSPR_methods *cryspr, size_t max_len)
{
crysprOpenSSL_cb *aes_data;
aes_data = (crysprOpenSSL_cb *)crysprHelper_Open(cryspr, sizeof(crysprOpenSSL_cb), max_len);
if (NULL == aes_data) {
HCRYPT_LOG(LOG_ERR, "crysprHelper_Open(%p, %zd, %zd) failed\n", cryspr, sizeof(crysprOpenSSL_cb), max_len);
return(NULL);
}
aes_data->ccb.aes_kek = &aes_data->aes_kek_buf; //key encrypting key
aes_data->ccb.aes_sek[0] = &aes_data->aes_sek_buf[0]; //stream encrypting key
aes_data->ccb.aes_sek[1] = &aes_data->aes_sek_buf[1]; //stream encrypting key
return(&aes_data->ccb);
}
#endif /* CRYSPR2 */
/*
* Password-based Key Derivation Function
*/
@ -148,8 +173,7 @@ int crysprOpenSSL_KmWrap(CRYSPR_cb *cryspr_cb,
const unsigned char *sek,
unsigned int seklen)
{
crysprOpenSSL_cb *aes_data = (crysprOpenSSL_cb *)cryspr_cb;
AES_KEY *kek = &aes_data->ccb.aes_kek; //key encrypting key
AES_KEY *kek = CRYSPR_GETKEK(cryspr_cb); //key encrypting key
return(((seklen + HAICRYPT_WRAPKEY_SIGN_SZ) == (unsigned int)AES_wrap_key(kek, NULL, wrap, sek, seklen)) ? 0 : -1);
}
@ -160,8 +184,7 @@ int crysprOpenSSL_KmUnwrap(
const unsigned char *wrap,
unsigned int wraplen)
{
crysprOpenSSL_cb *aes_data = (crysprOpenSSL_cb *)cryspr_cb;
AES_KEY *kek = &aes_data->ccb.aes_kek; //key encrypting key
AES_KEY *kek = CRYSPR_GETKEK(cryspr_cb); //key encrypting key
return(((wraplen - HAICRYPT_WRAPKEY_SIGN_SZ) == (unsigned int)AES_unwrap_key(kek, NULL, sek, wrap, wraplen)) ? 0 : -1);
}
@ -192,7 +215,11 @@ CRYSPR_methods *crysprOpenSSL(void)
#endif
//--Crypto Session API-----------------------------------------
#ifdef CRYSPR2
crysprOpenSSL_methods.open = crysprOpenSSL_Open;
#else
// crysprOpenSSL_methods.open =
#endif
// crysprOpenSSL_methods.close =
//--Keying material (km) encryption

View file

@ -31,11 +31,13 @@ int crysprStub_Prng(unsigned char *rn, int len)
}
int crysprStub_AES_SetKey(
int cipher_type, /* One of HCRYPT_CTX_MODE_[CLRTXT|AESECB|AESCTR|AESGDM] */
bool bEncrypt, /* true Enxcrypt key, false: decrypt */
const unsigned char *kstr, /* key sttring*/
size_t kstr_len, /* kstr len in bytes (16, 24, or 32 bytes (for AES128,AES192, or AES256) */
CRYSPR_AESCTX *aes_key) /* Cryptolib Specific AES key context */
{
(void)cipher_type;
(void)bEncrypt;
(void)kstr;
(void)kstr_len;
@ -122,10 +124,10 @@ int crysprStub_KmPbkdf2(
static int crysprFallback_KmSetKey(CRYSPR_cb *cryspr_cb, bool bWrap, const unsigned char *kek, size_t kek_len)
{
CRYSPR_AESCTX *aes_kek = &cryspr_cb->aes_kek;
CRYSPR_AESCTX *aes_kek = CRYSPR_GETKEK(cryspr_cb);
if (cryspr_cb->cryspr->aes_set_key(bWrap, kek, kek_len, aes_kek)) {
HCRYPT_LOG(LOG_ERR, "AES_set_%s_key(kek) failed\n", bWrap? "encrypt": "decrypt");
if (cryspr_cb->cryspr->aes_set_key(HCRYPT_CTX_MODE_AESECB, bWrap, kek, kek_len, aes_kek)) {
HCRYPT_LOG(LOG_ERR, "aes_set_%s_key(kek) failed\n", bWrap? "encrypt": "decrypt");
return(-1);
}
return(0);
@ -163,7 +165,9 @@ int crysprFallback_AES_WrapKey(CRYSPR_cb *cryspr_cb,
memcpy(B + 8, R, 8);
{
size_t outlen = 16;
cryspr_cb->cryspr->aes_ecb_cipher(true, &cryspr_cb->aes_kek, B, 16, B, &outlen);
CRYSPR_AESCTX *aes_kek = CRYSPR_GETKEK(cryspr_cb);
cryspr_cb->cryspr->aes_ecb_cipher(true, aes_kek, B, 16, B, &outlen);
}
A[7] ^= (unsigned char)(t & 0xff);
if (t > 0xff)
@ -211,7 +215,9 @@ int crysprFallback_AES_UnwrapKey(CRYSPR_cb *cryspr_cb,
memcpy(B + 8, R, 8);
{
size_t outlen = 16;
cryspr_cb->cryspr->aes_ecb_cipher(false, &cryspr_cb->aes_kek, B, 16, B, &outlen);
CRYSPR_AESCTX *aes_kek = CRYSPR_GETKEK(cryspr_cb);
cryspr_cb->cryspr->aes_ecb_cipher(false, aes_kek, B, 16, B, &outlen);
}
memcpy(R, B + 8, 8);
}
@ -237,20 +243,23 @@ static unsigned char *_crysprFallback_GetOutbuf(CRYSPR_cb *cryspr_cb, size_t pfx
return(out_buf);
}
static CRYSPR_cb *crysprFallback_Open(CRYSPR_methods *cryspr, size_t max_len)
CRYSPR_cb *crysprHelper_Open(CRYSPR_methods *cryspr, size_t cb_len, size_t max_len)
{
CRYSPR_cb *cryspr_cb;
unsigned char *membuf;
size_t memsiz, padded_len = hcryptMsg_PaddedLen(max_len, 128/8);
HCRYPT_LOG(LOG_DEBUG, "%s", "Using OpenSSL AES\n");
memsiz = sizeof(*cryspr_cb) + (CRYSPR_OUTMSGMAX * padded_len);
if(cb_len < sizeof(*cryspr_cb)) {
HCRYPT_LOG(LOG_ERR, "crysprHelper_Open() cb_len too small (%zd < %zd)n",
cb_len, sizeof(*cryspr_cb));
return(NULL);
}
memsiz = cb_len + (CRYSPR_OUTMSGMAX * padded_len);
#if !CRYSPR_HAS_AESCTR
memsiz += HCRYPT_CTR_STREAM_SZ;
#endif /* !CRYSPR_HAS_AESCTR */
cryspr_cb = malloc(memsiz);
cryspr_cb = calloc(1, memsiz);
if (NULL == cryspr_cb) {
HCRYPT_LOG(LOG_ERR, "malloc(%zd) failed\n", memsiz);
return(NULL);
@ -258,6 +267,9 @@ static CRYSPR_cb *crysprFallback_Open(CRYSPR_methods *cryspr, size_t max_len)
membuf = (unsigned char *)cryspr_cb;
membuf += sizeof(*cryspr_cb);
/*reserve cryspr's private data that caller will initialize */
membuf += (cb_len-sizeof(CRYSPR_cb));
#if !CRYSPR_HAS_AESCTR
cryspr_cb->ctr_stream = membuf;
membuf += HCRYPT_CTR_STREAM_SZ;
@ -275,26 +287,37 @@ static CRYSPR_cb *crysprFallback_Open(CRYSPR_methods *cryspr, size_t max_len)
return(cryspr_cb);
}
int crysprHelper_Close(CRYSPR_cb *cryspr_cb)
{
free(cryspr_cb);
return(0);
}
static CRYSPR_cb *crysprFallback_Open(CRYSPR_methods *cryspr, size_t max_len)
{
CRYSPR_cb *cryspr_cb;
cryspr_cb = crysprHelper_Open(cryspr, sizeof(CRYSPR_cb), max_len);
return(cryspr_cb);
}
static int crysprFallback_Close(CRYSPR_cb *cryspr_cb)
{
if (NULL != cryspr_cb) {
free(cryspr_cb);
}
return(0);
return(crysprHelper_Close(cryspr_cb));
}
static int crysprFallback_MsSetKey(CRYSPR_cb *cryspr_cb, hcrypt_Ctx *ctx, const unsigned char *key, size_t key_len)
{
CRYSPR_AESCTX *aes_sek = &cryspr_cb->aes_sek[hcryptCtx_GetKeyIndex(ctx)]; /* Ctx tells if it's for odd or even key */
CRYSPR_AESCTX *aes_sek = CRYSPR_GETSEK(cryspr_cb, hcryptCtx_GetKeyIndex(ctx)); /* Ctx tells if it's for odd or even key */
if ((ctx->flags & HCRYPT_CTX_F_ENCRYPT) /* Encrypt key */
|| (ctx->mode == HCRYPT_CTX_MODE_AESCTR)) { /* CTR mode decrypts using encryption methods */
if (cryspr_cb->cryspr->aes_set_key(true, key, key_len, aes_sek)) {
if (cryspr_cb->cryspr->aes_set_key(HCRYPT_CTX_MODE_AESCTR, true, key, key_len, aes_sek)) {
HCRYPT_LOG(LOG_ERR, "%s", "CRYSPR->set_encrypt_key(sek) failed\n");
return(-1);
}
} else { /* Decrypt key */
if (cryspr_cb->cryspr->aes_set_key(false, key, key_len, aes_sek)) {
if (cryspr_cb->cryspr->aes_set_key(HCRYPT_CTX_MODE_AESCTR, false, key, key_len, aes_sek)) {
HCRYPT_LOG(LOG_ERR, "%s", "CRYSPR->set_decrypt_key(sek) failed\n");
return(-1);
}
@ -376,135 +399,78 @@ static int crysprFallback_MsEncrypt(
/* Get buffer room from the internal circular output buffer */
out_msg = _crysprFallback_GetOutbuf(cryspr_cb, pfx_len, in_data[0].len);
if (NULL != out_msg) {
switch(ctx->mode) {
case HCRYPT_CTX_MODE_AESCTR: /* Counter mode */
{
#if CRYSPR_HAS_AESCTR
/* Get current key (odd|even) from context */
CRYSPR_AESCTX *aes_key = &cryspr_cb->aes_sek[hcryptCtx_GetKeyIndex(ctx)];
unsigned char iv[CRYSPR_AESBLKSZ];
/* Get input packet index (in network order) */
hcrypt_Pki pki = hcryptMsg_GetPki(ctx->msg_info, in_data[0].pfx, 1);
/*
* Compute the Initial Vector
* IV (128-bit):
* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
* | 0s | pki | ctr |
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
* XOR
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
* | nonce +
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
*
* pki (32-bit): packet index
* ctr (16-bit): block counter
* nonce (112-bit): number used once (salt)
*/
hcrypt_SetCtrIV((unsigned char *)&pki, ctx->salt, iv);
cryspr_cb->cryspr->aes_ctr_cipher(true, aes_key, iv, in_data[0].payload, in_data[0].len,
&out_msg[pfx_len]);
#else /*CRYSPR_HAS_AESCTR*/
/* Get current key (odd|even) from context */
CRYSPR_AESCTX *aes_key = &cryspr_cb->aes_sek[hcryptCtx_GetKeyIndex(ctx)];
unsigned char iv[CRYSPR_AESBLKSZ];
int iret = 0;
/* Get input packet index (in network order) */
hcrypt_Pki pki = hcryptMsg_GetPki(ctx->msg_info, in_data[0].pfx, 1);
/*
* Compute the Initial Vector
* IV (128-bit):
* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
* | 0s | pki | ctr |
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
* XOR
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
* | nonce +
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
*
* pki (32-bit): packet index
* ctr (16-bit): block counter
* nonce (112-bit): number used once (salt)
*/
hcrypt_SetCtrIV((unsigned char *)&pki, ctx->salt, iv);
/* Create CtrStream. May be longer than in_len (next cryspr block size boundary) */
iret = _crysprFallback_AES_SetCtrStream(cryspr_cb, ctx, in_data[0].len, iv);
if (iret) {
return(iret);
}
/* Reserve output buffer for cryspr */
out_msg = _crysprFallback_GetOutbuf(cryspr_cb, pfx_len, cryspr_cb->ctr_stream_len);
/* Create KeyStream (encrypt CtrStream) */
iret = cryspr_cb->cryspr->aes_ecb_cipher(true, aes_key,
cryspr_cb->ctr_stream, cryspr_cb->ctr_stream_len,
&out_msg[pfx_len], &out_len);
if (iret) {
HCRYPT_LOG(LOG_ERR, "%s", "hcOpenSSL_AES_ecb_cipher(encrypt, failed\n");
return(iret);
}
#endif/*CRYSPR_HAS_AESCTR*/
/* Prepend packet prefix (clear text) in output buffer */
memcpy(out_msg, in_data[0].pfx, pfx_len);
/* CTR mode output length is same as input, no padding */
out_len = in_data[0].len;
break;
}
case HCRYPT_CTX_MODE_CLRTXT: /* Clear text mode (transparent mode for tests) */
memcpy(&out_msg[pfx_len], in_data[0].payload, in_data[0].len);
memcpy(out_msg, in_data[0].pfx, pfx_len);
out_len = in_data[0].len;
break;
default:
/* Unsupported cipher mode */
return(-1);
}
} else {
if (NULL == out_msg) {
/* input data too big */
return(-1);
}
if (out_len > 0) {
/* Encrypted messages have been produced */
if (NULL == out_p) {
switch(ctx->mode) {
case HCRYPT_CTX_MODE_AESCTR: /* Counter mode */
{
/* Get current key (odd|even) from context */
CRYSPR_AESCTX *aes_key = CRYSPR_GETSEK(cryspr_cb, hcryptCtx_GetKeyIndex(ctx)); /* Ctx tells if it's for odd or even key */
unsigned char iv[CRYSPR_AESBLKSZ];
/* Get input packet index (in network order) */
hcrypt_Pki pki = hcryptMsg_GetPki(ctx->msg_info, in_data[0].pfx, 1);
/*
* Application did not provided output buffer,
* so copy encrypted message back in input buffer
*/
memcpy(in_data[0].pfx, out_msg, pfx_len);
#if !CRYSPR_HAS_AESCTR
if (ctx->mode == HCRYPT_CTX_MODE_AESCTR) {
/* XOR KeyStream with input text directly in input buffer */
hcrypt_XorStream(in_data[0].payload, &out_msg[pfx_len], out_len);
}else{
/* Copy output data back in input buffer */
memcpy(in_data[0].payload, &out_msg[pfx_len], out_len);
* Compute the Initial Vector
* IV (128-bit):
* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
* | 0s | pki | ctr |
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
* XOR
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
* | nonce +
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
*
* pki (32-bit): packet index
* ctr (16-bit): block counter
* nonce (112-bit): number used once (salt)
*/
hcrypt_SetCtrIV((unsigned char *)&pki, ctx->salt, iv);
#if CRYSPR_HAS_AESCTR
cryspr_cb->cryspr->aes_ctr_cipher(true, aes_key, iv, in_data[0].payload, in_data[0].len,
&out_msg[pfx_len]);
#else /*CRYSPR_HAS_AESCTR*/
/* Create CtrStream. May be longer than in_len (next cryspr block size boundary) */
int iret = _crysprFallback_AES_SetCtrStream(cryspr_cb, ctx, in_data[0].len, iv);
if (iret) {
return(iret);
}
#else /* CRYSPR_HAS_AESCTR */
/* Copy output data back in input buffer */
memcpy(in_data[0].payload, &out_msg[pfx_len], out_len);
#endif /* CRYSPR_HAS_AESCTR */
} else {
/* Copy header in output buffer if needed */
if (pfx_len > 0) memcpy(out_msg, in_data[0].pfx, pfx_len);
#if !CRYSPR_HAS_AESCTR
if (ctx->mode == HCRYPT_CTX_MODE_AESCTR) {
hcrypt_XorStream(&out_msg[pfx_len], in_data[0].payload, out_len);
/* Reserve output buffer for cryspr */
out_msg = _crysprFallback_GetOutbuf(cryspr_cb, pfx_len, cryspr_cb->ctr_stream_len);
/* Create KeyStream (encrypt CtrStream) */
iret = cryspr_cb->cryspr->aes_ecb_cipher(true, aes_key,
cryspr_cb->ctr_stream, cryspr_cb->ctr_stream_len,
&out_msg[pfx_len], &out_len);
if (iret) {
HCRYPT_LOG(LOG_ERR, "%s", "hcOpenSSL_AES_ecb_cipher(encrypt, failed\n");
return(iret);
}
#endif /* CRYSPR_HAS_AESCTR */
out_p[0] = out_msg;
out_len_p[0] = pfx_len + out_len;
*nbout_p = 1;
#endif/*CRYSPR_HAS_AESCTR*/
/* Prepend packet prefix (clear text) in output buffer */
memcpy(out_msg, in_data[0].pfx, pfx_len);
/* CTR mode output length is same as input, no padding */
out_len = in_data[0].len;
break;
}
} else {
case HCRYPT_CTX_MODE_CLRTXT: /* Clear text mode (transparent mode for tests) */
memcpy(&out_msg[pfx_len], in_data[0].payload, in_data[0].len);
memcpy(out_msg, in_data[0].pfx, pfx_len);
out_len = in_data[0].len;
break;
default:
/* Unsupported cipher mode */
return(-1);
}
if (out_len <= 0) {
/*
* Nothing out
* This is not an error for implementations using deferred/async processing
@ -514,6 +480,39 @@ static int crysprFallback_MsEncrypt(
if (nbout_p != NULL) *nbout_p = 0;
return(-1);
}
/* Encrypted messages have been produced */
if (NULL == out_p) {
/*
* Application did not provided output buffer,
* so copy encrypted message back in input buffer
*/
memcpy(in_data[0].pfx, out_msg, pfx_len);
#if !CRYSPR_HAS_AESCTR
if (ctx->mode == HCRYPT_CTX_MODE_AESCTR) {
/* XOR KeyStream with input text directly in input buffer */
hcrypt_XorStream(in_data[0].payload, &out_msg[pfx_len], out_len);
}else{
/* Copy output data back in input buffer */
memcpy(in_data[0].payload, &out_msg[pfx_len], out_len);
}
#else /* CRYSPR_HAS_AESCTR */
/* Copy output data back in input buffer */
memcpy(in_data[0].payload, &out_msg[pfx_len], out_len);
#endif /* CRYSPR_HAS_AESCTR */
} else {
/* Copy header in output buffer if needed */
if (pfx_len > 0) memcpy(out_msg, in_data[0].pfx, pfx_len);
#if !CRYSPR_HAS_AESCTR
if (ctx->mode == HCRYPT_CTX_MODE_AESCTR) {
hcrypt_XorStream(&out_msg[pfx_len], in_data[0].payload, out_len);
}
#endif /* CRYSPR_HAS_AESCTR */
out_p[0] = out_msg;
out_len_p[0] = pfx_len + out_len;
*nbout_p = 1;
}
return(0);
}
@ -537,7 +536,7 @@ static int crysprFallback_MsDecrypt(CRYSPR_cb *cryspr_cb, hcrypt_Ctx *ctx,
{
#if CRYSPR_HAS_AESCTR
/* Get current key (odd|even) from context */
CRYSPR_AESCTX *aes_key = &cryspr_cb->aes_sek[hcryptCtx_GetKeyIndex(ctx)];
CRYSPR_AESCTX *aes_key = CRYSPR_GETSEK(cryspr_cb, hcryptCtx_GetKeyIndex(ctx));
unsigned char iv[CRYSPR_AESBLKSZ];
/* Get input packet index (in network order) */
@ -566,7 +565,7 @@ static int crysprFallback_MsDecrypt(CRYSPR_cb *cryspr_cb, hcrypt_Ctx *ctx,
out_len = in_data[0].len;
#else /*CRYSPR_HAS_AESCTR*/
/* Get current key (odd|even) from context */
CRYSPR_AESCTX *aes_key = &cryspr_cb->aes_sek[hcryptCtx_GetKeyIndex(ctx)];
CRYSPR_AESCTX *aes_key = CRYSPR_GETSEK(cryspr_cb, hcryptCtx_GetKeyIndex(ctx));
unsigned char iv[CRYSPR_AESBLKSZ];
int iret = 0;

View file

@ -39,8 +39,17 @@ extern "C" {
#include "cryspr-config.h"
typedef struct tag_CRYSPR_cb {
#ifdef CRYSPR2
CRYSPR_AESCTX *aes_kek; /* Key Encrypting Key (KEK) */
CRYSPR_AESCTX *aes_sek[2]; /* even/odd Stream Encrypting Key (SEK) */
#define CRYSPR_GETKEK(cb) ((cb)->aes_kek)
#define CRYSPR_GETSEK(cb,kk) ((cb)->aes_sek[kk])
#else /*CRYSPR2*/
CRYSPR_AESCTX aes_kek; /* Key Encrypting Key (KEK) */
CRYSPR_AESCTX aes_sek[2]; /* even/odd Stream Encrypting Key (SEK) */
#define CRYSPR_GETKEK(cb) (&((cb)->aes_kek))
#define CRYSPR_GETSEK(cb,kk) (&((cb)->aes_sek[kk]))
#endif /*CRYSPR2*/
struct tag_CRYSPR_methods *cryspr;
@ -69,6 +78,7 @@ typedef struct tag_CRYSPR_methods {
int rn_len);
int (*aes_set_key)(
int cipher_type, /* One of HCRYPT_CTX_MODE_[CLRTXT|AESECB|AESCTR|AESGDM] */
bool bEncrypt, /* true Enxcrypt key, false: decrypt */
const unsigned char *kstr,/* key string*/
size_t kstr_len, /* kstr len in bytes (16, 24, or 32 bytes (for AES128,AES192, or AES256) */
@ -194,6 +204,9 @@ typedef struct tag_CRYSPR_methods {
} CRYSPR_methods;
CRYSPR_cb *crysprHelper_Open(CRYSPR_methods *cryspr, size_t cb_len, size_t max_len);
int crysprHelper_Close(CRYSPR_cb *cryspr_cb);
CRYSPR_methods *crysprInit(CRYSPR_methods *cryspr);
#ifdef __cplusplus

View file

@ -23,5 +23,4 @@ hcrypt_rx.c
hcrypt_sa.c
hcrypt_tx.c
hcrypt_xpt_srt.c
hcrypt_xpt_sta.c
haicrypt_log.cpp

View file

@ -21,5 +21,4 @@ hcrypt_rx.c
hcrypt_sa.c
hcrypt_tx.c
hcrypt_xpt_srt.c
hcrypt_xpt_sta.c
haicrypt_log.cpp

View file

@ -0,0 +1,24 @@
# HaiCrypt library contents
PUBLIC HEADERS
haicrypt.h
hcrypt_ctx.h
hcrypt_msg.h
PRIVATE HEADERS
hcrypt.h
cryspr.h
cryspr-openssl-evp.h
haicrypt_log.h
SOURCES
cryspr.c
cryspr-openssl-evp.c
hcrypt.c
hcrypt_ctx_rx.c
hcrypt_ctx_tx.c
hcrypt_rx.c
hcrypt_sa.c
hcrypt_tx.c
hcrypt_xpt_srt.c
haicrypt_log.cpp

View file

@ -21,5 +21,4 @@ hcrypt_rx.c
hcrypt_sa.c
hcrypt_tx.c
hcrypt_xpt_srt.c
hcrypt_xpt_sta.c
haicrypt_log.cpp

View file

@ -27,25 +27,9 @@ written by
#ifdef __cplusplus
extern "C" {
#endif
// setup exports
#if defined _WIN32 && !defined __MINGW__
#ifdef HAICRYPT_DYNAMIC
#ifdef HAICRYPT_EXPORTS
#define HAICRYPT_API __declspec(dllexport)
#else
#define HAICRYPT_API __declspec(dllimport)
#endif
#else
#define HAICRYPT_API
#endif
#else
#define HAICRYPT_API
#endif
typedef void *HaiCrypt_Cryspr;
HAICRYPT_API HaiCrypt_Cryspr HaiCryptCryspr_Get_Instance (void); /* Return a default cryspr instance */
HaiCrypt_Cryspr HaiCryptCryspr_Get_Instance (void); /* Return a default cryspr instance */
#define HAICRYPT_CIPHER_BLK_SZ 16 /* AES Block Size */
@ -108,21 +92,21 @@ typedef struct hcrypt_Session_str* HaiCrypt_Handle;
HAICRYPT_API int HaiCrypt_SetLogLevel(int level, int logfa);
int HaiCrypt_SetLogLevel(int level, int logfa);
HAICRYPT_API int HaiCrypt_Create(const HaiCrypt_Cfg *cfg, HaiCrypt_Handle *phhc);
HAICRYPT_API int HaiCrypt_Clone(HaiCrypt_Handle hhcSrc, HaiCrypt_CryptoDir tx, HaiCrypt_Handle *phhc);
HAICRYPT_API int HaiCrypt_Close(HaiCrypt_Handle hhc);
HAICRYPT_API int HaiCrypt_Tx_GetBuf(HaiCrypt_Handle hhc, size_t data_len, unsigned char **in_p);
HAICRYPT_API int HaiCrypt_Tx_Process(HaiCrypt_Handle hhc, unsigned char *in, size_t in_len,
void *out_p[], size_t out_len_p[], int maxout);
HAICRYPT_API int HaiCrypt_Rx_Process(HaiCrypt_Handle hhc, unsigned char *in, size_t in_len,
void *out_p[], size_t out_len_p[], int maxout);
int HaiCrypt_Create(const HaiCrypt_Cfg *cfg, HaiCrypt_Handle *phhc);
int HaiCrypt_Clone(HaiCrypt_Handle hhcSrc, HaiCrypt_CryptoDir tx, HaiCrypt_Handle *phhc);
int HaiCrypt_Close(HaiCrypt_Handle hhc);
int HaiCrypt_Tx_GetBuf(HaiCrypt_Handle hhc, size_t data_len, unsigned char **in_p);
int HaiCrypt_Tx_Process(HaiCrypt_Handle hhc, unsigned char *in, size_t in_len,
void *out_p[], size_t out_len_p[], int maxout);
int HaiCrypt_Rx_Process(HaiCrypt_Handle hhc, unsigned char *in, size_t in_len,
void *out_p[], size_t out_len_p[], int maxout);
HAICRYPT_API int HaiCrypt_Tx_GetKeyFlags(HaiCrypt_Handle hhc);
HAICRYPT_API int HaiCrypt_Tx_ManageKeys(HaiCrypt_Handle hhc, void *out_p[], size_t out_len_p[], int maxout);
HAICRYPT_API int HaiCrypt_Tx_Data(HaiCrypt_Handle hhc, unsigned char *pfx, unsigned char *data, size_t data_len);
HAICRYPT_API int HaiCrypt_Rx_Data(HaiCrypt_Handle hhc, unsigned char *pfx, unsigned char *data, size_t data_len);
int HaiCrypt_Tx_GetKeyFlags(HaiCrypt_Handle hhc);
int HaiCrypt_Tx_ManageKeys(HaiCrypt_Handle hhc, void *out_p[], size_t out_len_p[], int maxout);
int HaiCrypt_Tx_Data(HaiCrypt_Handle hhc, unsigned char *pfx, unsigned char *data, size_t data_len);
int HaiCrypt_Rx_Data(HaiCrypt_Handle hhc, unsigned char *pfx, unsigned char *data, size_t data_len);
/* Status values */

View file

@ -10,6 +10,8 @@
#if ENABLE_HAICRYPT_LOGGING
#include "haicrypt_log.h"
#include "hcrypt.h"
#include "haicrypt.h"
#include "../srtcore/srt.h"
@ -18,7 +20,7 @@
extern srt_logging::LogConfig srt_logger_config;
// LOGFA symbol defined in srt.h
srt_logging::Logger hclog(SRT_LOGFA_HAICRYPT, srt_logger_config, "SRT.k");
srt_logging::Logger hclog(SRT_LOGFA_HAICRYPT, srt_logger_config, "SRT.hc");
extern "C" {
@ -97,12 +99,7 @@ void HaiCrypt_DumpConfig(const HaiCrypt_Cfg* cfg)
LOGC(hclog.Debug, log << "CFG DUMP: flags=" << cfg_flags.str()
<< " xport=" << (cfg->xport == HAICRYPT_XPT_SRT ? "SRT" : "INVALID")
<< " cipher="
<< (cfg->cipher == HaiCryptCipher_OpenSSL_EVP_CTR() ? "OSSL-EVP-CTR":
cfg->cipher == HaiCryptCipher_OpenSSL_AES() ? "OSSL-AES":
// This below is used as the only one when Nettle is used. When OpenSSL
// is used, one of the above will trigger, and the one below will then never trigger.
cfg->cipher == HaiCryptCipher_Get_Instance() ? "Nettle-AES":
"UNKNOWN")
<< CRYSPR_IMPL_DESC
<< " key_len=" << cfg->key_len << " data_max_len=" << cfg->data_max_len);

View file

@ -1,5 +1,5 @@
#ifndef IMC__HAICRYPT_LOG_H
#define IMC__HAICRYPT_LOG_H
#ifndef INC_SRT_HAICRYPT_LOG_H
#define INC_SRT_HAICRYPT_LOG_H
#ifdef __cplusplus
extern "C" {

View file

@ -74,10 +74,6 @@ static hcrypt_Session* sHaiCrypt_PrepareHandle(const HaiCrypt_Cfg* cfg, HaiCrypt
/* Setup transport packet info */
switch (cfg->xport) {
case HAICRYPT_XPT_STANDALONE:
crypto->se = HCRYPT_SE_TSUDP;
crypto->msg_info = hcryptMsg_STA_MsgInfo();
break;
case HAICRYPT_XPT_SRT:
crypto->se = HCRYPT_SE_TSSRT;
crypto->msg_info = hcryptMsg_SRT_MsgInfo();

View file

@ -24,8 +24,8 @@ written by
MINGW-W64 Build.
*****************************************************************************/
#ifndef HCRYPT_H
#define HCRYPT_H
#ifndef INC_SRT_HCRYPT_H
#define INC_SRT_HCRYPT_H
#include <sys/types.h>

View file

@ -74,9 +74,10 @@ int hcryptCtx_Tx_Rekey(hcrypt_Session *crypto, hcrypt_Ctx *ctx)
HCRYPT_PRINTKEY(ctx->sek, ctx->sek_len, "sek");
/* Regenerate KEK if Password-based (uses newly generated salt and sek_len) */
if ((0 < ctx->cfg.pwd_len)
&& (0 > (iret = hcryptCtx_GenSecret(crypto, ctx)))) {
return(iret);
if (0 < ctx->cfg.pwd_len) {
iret = hcryptCtx_GenSecret(crypto, ctx);
if (iret < 0)
return(iret);
}
/* Assemble the new Keying Material message */
@ -106,22 +107,22 @@ int hcryptCtx_Tx_CloneKey(hcrypt_Session *crypto, hcrypt_Ctx *ctx, const hcrypt_
ASSERT(HCRYPT_CTX_S_SARDY <= ctx->status);
const hcrypt_Ctx* ctxSrc = cryptoSrc->ctx;
if (!ctxSrc)
{
/* Probbly the context is not yet completely initialized, so
* use blindly the first context from the pair
*/
ctxSrc = &cryptoSrc->ctx_pair[0];
}
const hcrypt_Ctx* ctxSrc = cryptoSrc->ctx;
if (!ctxSrc)
{
/* Probbly the context is not yet completely initialized, so
* use blindly the first context from the pair
*/
ctxSrc = &cryptoSrc->ctx_pair[0];
}
/* Copy SALT (instead of generating) */
ctx->salt_len = ctxSrc->salt_len;
memcpy(ctx->salt, ctxSrc->salt, ctx->salt_len);
/* Copy SALT (instead of generating) */
ctx->salt_len = ctxSrc->salt_len;
memcpy(ctx->salt, ctxSrc->salt, ctx->salt_len);
/* Copy SEK */
ctx->sek_len = ctxSrc->sek_len;
memcpy(ctx->sek, ctxSrc->sek, ctx->sek_len);
/* Copy SEK */
ctx->sek_len = ctxSrc->sek_len;
memcpy(ctx->sek, ctxSrc->sek, ctx->sek_len);
/* Set SEK in cryspr */
if (crypto->cryspr->ms_setkey(crypto->cryspr_cb, ctx, ctx->sek, ctx->sek_len)) {
@ -133,11 +134,12 @@ int hcryptCtx_Tx_CloneKey(hcrypt_Session *crypto, hcrypt_Ctx *ctx, const hcrypt_
HCRYPT_PRINTKEY(ctx->sek, ctx->sek_len, "sek");
/* Regenerate KEK if Password-based (uses newly generated salt and sek_len) */
/* (note for CloneKey imp: it's expected that the same passphrase-salt pair
shall generate the same KEK. GenSecret also prints the KEK */
if ((0 < ctx->cfg.pwd_len)
&& (0 > (iret = hcryptCtx_GenSecret(crypto, ctx)))) {
return(iret);
/* (note for CloneKey imp: it's expected that the same passphrase-salt pair
shall generate the same KEK. GenSecret also prints the KEK */
if (0 < ctx->cfg.pwd_len) {
iret = hcryptCtx_GenSecret(crypto, ctx);
if (iret < 0)
return(iret);
}
/* Assemble the new Keying Material message */
@ -336,8 +338,8 @@ int hcryptCtx_Tx_ManageKM(hcrypt_Session *crypto)
ASSERT(NULL != ctx);
HCRYPT_LOG(LOG_DEBUG, "KM[%d] KEY STATUS: pkt_cnt=%u against ref.rate=%u and pre.announce=%u\n",
(ctx->alt->flags & HCRYPT_CTX_F_xSEK)/2,
ctx->pkt_cnt, crypto->km.refresh_rate, crypto->km.pre_announce);
(ctx->alt->flags & HCRYPT_CTX_F_xSEK)/2,
ctx->pkt_cnt, crypto->km.refresh_rate, crypto->km.pre_announce);
if ((ctx->pkt_cnt > crypto->km.refresh_rate)
|| (ctx->pkt_cnt == 0)) { //rolled over

View file

@ -37,7 +37,7 @@ int hcryptCtx_SetSecret(hcrypt_Session *crypto, hcrypt_Ctx *ctx, const HaiCrypt_
ctx->cfg.pwd_len = 0;
/* KEK: Key Encrypting Key */
if (0 > (iret = crypto->cryspr->km_setkey(crypto->cryspr_cb,
(HCRYPT_CTX_F_ENCRYPT & ctx->flags ? true : false),
((HCRYPT_CTX_F_ENCRYPT & ctx->flags) ? true : false),
secret->str, secret->len))) {
HCRYPT_LOG(LOG_ERR, "km_setkey(pdkek[%zd]) failed (rc=%d)\n", secret->len, iret);
return(-1);
@ -87,7 +87,7 @@ int hcryptCtx_GenSecret(hcrypt_Session *crypto, hcrypt_Ctx *ctx)
HCRYPT_PRINTKEY(kek, kek_len, "kek");
/* KEK: Key Encrypting Key */
if (0 > (iret = crypto->cryspr->km_setkey(crypto->cryspr_cb, (HCRYPT_CTX_F_ENCRYPT & ctx->flags ? true : false), kek, kek_len))) {
if (0 > (iret = crypto->cryspr->km_setkey(crypto->cryspr_cb, ((HCRYPT_CTX_F_ENCRYPT & ctx->flags) ? true : false), kek, kek_len))) {
HCRYPT_LOG(LOG_ERR, "km_setkey(pdkek[%zd]) failed (rc=%d)\n", kek_len, iret);
return(-1);
}

View file

@ -55,11 +55,11 @@ int HaiCrypt_Tx_GetBuf(HaiCrypt_Handle hhc, size_t data_len, unsigned char **in_
int HaiCrypt_Tx_ManageKeys(HaiCrypt_Handle hhc, void *out_p[], size_t out_len_p[], int maxout)
{
hcrypt_Session *crypto = (hcrypt_Session *)hhc;
hcrypt_Ctx *ctx = NULL;
hcrypt_Ctx *ctx = crypto->ctx;
int nbout = 0;
if ((NULL == crypto)
|| (NULL == (ctx = crypto->ctx))
|| (NULL == ctx)
|| (NULL == out_p)
|| (NULL == out_len_p)) {
HCRYPT_LOG(LOG_ERR, "ManageKeys: invalid params: crypto=%p crypto->ctx=%p\n", crypto, ctx);
@ -69,7 +69,8 @@ int HaiCrypt_Tx_ManageKeys(HaiCrypt_Handle hhc, void *out_p[], size_t out_len_p[
/* Manage Key Material (refresh, announce, decommission) */
hcryptCtx_Tx_ManageKM(crypto);
if (NULL == (ctx = crypto->ctx)) {
ctx = crypto->ctx;
if (NULL == ctx) {
HCRYPT_LOG(LOG_ERR, "%s", "crypto context not defined\n");
return(-1);
}
@ -82,10 +83,10 @@ int HaiCrypt_Tx_ManageKeys(HaiCrypt_Handle hhc, void *out_p[], size_t out_len_p[
int HaiCrypt_Tx_GetKeyFlags(HaiCrypt_Handle hhc)
{
hcrypt_Session *crypto = (hcrypt_Session *)hhc;
hcrypt_Ctx *ctx = NULL;
hcrypt_Ctx *ctx = crypto->ctx;
if ((NULL == crypto)
|| (NULL == (ctx = crypto->ctx))){
|| (NULL == ctx)){
HCRYPT_LOG(LOG_ERR, "GetKeyFlags: invalid params: crypto=%p crypto->ctx=%p\n", crypto, ctx);
return(-1);
}
@ -96,11 +97,11 @@ int HaiCrypt_Tx_Data(HaiCrypt_Handle hhc,
unsigned char *in_pfx, unsigned char *in_data, size_t in_len)
{
hcrypt_Session *crypto = (hcrypt_Session *)hhc;
hcrypt_Ctx *ctx = NULL;
hcrypt_Ctx *ctx = crypto->ctx;
int nbout = 0;
if ((NULL == crypto)
|| (NULL == (ctx = crypto->ctx))){
|| (NULL == ctx)){
HCRYPT_LOG(LOG_ERR, "Tx_Data: invalid params: crypto=%p crypto->ctx=%p\n", crypto, ctx);
return(-1);
}
@ -129,11 +130,11 @@ int HaiCrypt_Tx_Process(HaiCrypt_Handle hhc,
void *out_p[], size_t out_len_p[], int maxout)
{
hcrypt_Session *crypto = (hcrypt_Session *)hhc;
hcrypt_Ctx *ctx = NULL;
hcrypt_Ctx *ctx = crypto->ctx;
int nb, nbout = 0;
if ((NULL == crypto)
|| (NULL == (ctx = crypto->ctx))
|| (NULL == ctx)
|| (NULL == out_p)
|| (NULL == out_len_p)) {
HCRYPT_LOG(LOG_ERR, "Tx_Process: invalid params: crypto=%p crypto->ctx=%p\n", crypto, ctx);
@ -143,7 +144,8 @@ int HaiCrypt_Tx_Process(HaiCrypt_Handle hhc,
/* Manage Key Material (refresh, announce, decommission) */
hcryptCtx_Tx_ManageKM(crypto);
if (NULL == (ctx = crypto->ctx)) {
ctx = crypto->ctx;
if (NULL == ctx) {
HCRYPT_LOG(LOG_ERR, "%s", "crypto context not defined\n");
return(-1);
}

View file

@ -1,180 +0,0 @@
/*
* SRT - Secure, Reliable, Transport
* Copyright (c) 2018 Haivision Systems Inc.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*/
/*****************************************************************************
written by
Haivision Systems Inc.
2011-06-23 (jdube)
HaiCrypt initial implementation.
2014-03-11 (jdube)
Adaptation for SRT.
*****************************************************************************/
#include <string.h> /* memset, memcpy */
#include <time.h> /* time() */
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <arpa/inet.h> /* htonl, ntohl */
#endif
#include "hcrypt.h"
/*
* HaiCrypt Standalone Transport Media Stream (MS) Data Msg Prefix:
* Cache maintained in network order
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
* 0x00 |0|Vers | PT | Sign | resv |KF |
* +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
* 0x04 | pki |
* +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
* | payload... |
*/
/*
* HaiCrypt Standalone Transport Keying Material (KM) Msg (no prefix, use KM Msg directly):
* Cache maintained in network order
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
* 0x00 |0|Vers | PT | Sign | resv |
* +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
* ... .
*/
#define HCRYPT_MSG_STA_HDR_SZ 4
#define HCRYPT_MSG_STA_PKI_SZ 4
#define HCRYPT_MSG_STA_PFX_SZ (HCRYPT_MSG_STA_HDR_SZ + HCRYPT_MSG_STA_PKI_SZ)
#define HCRYPT_MSG_STA_OFS_VERSION HCRYPT_MSG_KM_OFS_VERSION
#define HCRYPT_MSG_STA_OFS_PT HCRYPT_MSG_KM_OFS_PT
#define HCRYPT_MSG_STA_OFS_SIGN HCRYPT_MSG_KM_OFS_SIGN
#define HCRYPT_MSG_STA_OFS_KFLGS HCRYPT_MSG_KM_OFS_KFLGS
#define HCRYPT_MSG_STA_OFS_PKI HCRYPT_MSG_STA_HDR_SZ
#define hcryptMsg_STA_GetVersion(msg) (((msg)[HCRYPT_MSG_STA_OFS_VERSION]>>4)& 0xF)
#define hcryptMsg_STA_GetPktType(msg) (((msg)[HCRYPT_MSG_STA_OFS_PT]) & 0xF)
#define hcryptMsg_STA_GetSign(msg) (((msg)[HCRYPT_MSG_STA_OFS_SIGN]<<8) | (msg)[HCRYPT_MSG_STA_OFS_SIGN+1])
static hcrypt_MsgInfo _hcMsg_STA_MsgInfo;
static unsigned hcryptMsg_STA_GetKeyFlags(unsigned char *msg)
{
return((unsigned)(msg[HCRYPT_MSG_STA_OFS_KFLGS] & HCRYPT_MSG_F_xSEK));
}
static hcrypt_Pki hcryptMsg_STA_GetPki(unsigned char *msg, int nwkorder)
{
hcrypt_Pki pki;
memcpy(&pki, &msg[HCRYPT_MSG_STA_OFS_PKI], sizeof(pki)); //header is in host order
return (nwkorder ? pki : ntohl(pki));
}
static void hcryptMsg_STA_SetPki(unsigned char *msg, hcrypt_Pki pki)
{
hcrypt_Pki nwk_pki = htonl(pki);
memcpy(&msg[HCRYPT_MSG_STA_OFS_PKI], &nwk_pki, sizeof(nwk_pki)); //header is in host order
}
static void hcryptMsg_STA_ResetCache(unsigned char *pfx_cache, unsigned pkt_type, unsigned kflgs)
{
pfx_cache[HCRYPT_MSG_STA_OFS_VERSION] = (unsigned char)((HCRYPT_MSG_VERSION << 4) | pkt_type); // version || PT
pfx_cache[HCRYPT_MSG_STA_OFS_SIGN] = (unsigned char)((HCRYPT_MSG_SIGN >> 8) & 0xFF); // Haivision PnP Mfr ID
pfx_cache[HCRYPT_MSG_STA_OFS_SIGN+1] = (unsigned char)(HCRYPT_MSG_SIGN & 0xFF);
switch(pkt_type) {
case HCRYPT_MSG_PT_MS:
pfx_cache[HCRYPT_MSG_STA_OFS_KFLGS] = (unsigned char)kflgs; //HCRYPT_MSG_F_xxx
hcryptMsg_STA_SetPki(pfx_cache, 0);
break;
case HCRYPT_MSG_PT_KM:
pfx_cache[HCRYPT_MSG_KM_OFS_KFLGS] = (unsigned char)kflgs; //HCRYPT_MSG_F_xxx
break;
default:
break;
}
}
static void hcryptMsg_STA_IndexMsg(unsigned char *msg, unsigned char *pfx_cache)
{
hcrypt_Pki pki = hcryptMsg_STA_GetPki(pfx_cache, 0); //Get in host order
memcpy(msg, pfx_cache, HCRYPT_MSG_STA_PFX_SZ);
hcryptMsg_SetPki(&_hcMsg_STA_MsgInfo, pfx_cache, ++pki);
}
static time_t _tLastLogTime = 0;
static int hcryptMsg_STA_ParseMsg(unsigned char *msg)
{
int rc;
if ((HCRYPT_MSG_VERSION != hcryptMsg_STA_GetVersion(msg)) /* Version 1 */
|| (HCRYPT_MSG_SIGN != hcryptMsg_STA_GetSign(msg))) { /* 'HAI' PnP Mfr ID */
time_t tCurrentTime = time(NULL);
// invalid data
if ((tCurrentTime - _tLastLogTime) >= 2 || (0 == _tLastLogTime))
{
_tLastLogTime = tCurrentTime;
HCRYPT_LOG(LOG_ERR, "invalid msg hdr: 0x%02x %02x%02x %02x\n",
msg[0], msg[1], msg[2], msg[3]);
}
return(-1); /* Invalid packet */
}
rc = hcryptMsg_STA_GetPktType(msg);
switch(rc) {
case HCRYPT_MSG_PT_MS:
if (hcryptMsg_HasNoSek(&_hcMsg_STA_MsgInfo, msg)
|| hcryptMsg_HasBothSek(&_hcMsg_STA_MsgInfo, msg)) {
HCRYPT_LOG(LOG_ERR, "invalid MS msg flgs: %02x\n",
hcryptMsg_GetKeyIndex(&_hcMsg_STA_MsgInfo, msg));
return(-1);
}
break;
case HCRYPT_MSG_PT_KM:
if (HCRYPT_SE_TSUDP != hcryptMsg_KM_GetSE(msg)) {
HCRYPT_LOG(LOG_ERR, "invalid KM msg SE: %d\n",
hcryptMsg_KM_GetSE(msg));
} else if (hcryptMsg_KM_HasNoSek(msg)) {
HCRYPT_LOG(LOG_ERR, "invalid KM msg flgs: %02x\n",
hcryptMsg_KM_GetKeyIndex(msg));
return(-1);
}
break;
default:
HCRYPT_LOG(LOG_ERR, "invalid pkt type: %d\n", rc);
rc = 0; /* unknown packet type */
break;
}
return(rc); /* -1: error, 0: unknown: >0: PT */
}
static hcrypt_MsgInfo _hcMsg_STA_MsgInfo;
hcrypt_MsgInfo *hcryptMsg_STA_MsgInfo(void)
{
_hcMsg_STA_MsgInfo.hdr_len = HCRYPT_MSG_STA_HDR_SZ;
_hcMsg_STA_MsgInfo.pfx_len = HCRYPT_MSG_STA_PFX_SZ;
_hcMsg_STA_MsgInfo.getKeyFlags = hcryptMsg_STA_GetKeyFlags;
_hcMsg_STA_MsgInfo.getPki = hcryptMsg_STA_GetPki;
_hcMsg_STA_MsgInfo.setPki = hcryptMsg_STA_SetPki;
_hcMsg_STA_MsgInfo.resetCache = hcryptMsg_STA_ResetCache;
_hcMsg_STA_MsgInfo.indexMsg = hcryptMsg_STA_IndexMsg;
_hcMsg_STA_MsgInfo.parseMsg = hcryptMsg_STA_ParseMsg;
return(&_hcMsg_STA_MsgInfo);
}