mirror of
				https://github.com/ossrs/srs.git
				synced 2025-03-09 15:49:59 +00:00 
			
		
		
		
	fix https://github.com/ossrs/srs/issues/3155 Build srt-1-fit fails with `standard attributes in middle of decl-specifiers` on GCC 12,Arch Linux. See https://github.com/Haivision/srt/releases/tag/v1.5.3
		
			
				
	
	
		
			775 lines
		
	
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			775 lines
		
	
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * 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.
 | 
						|
 | 
						|
   2019-06-28 (jdube)
 | 
						|
		CRYSPR/4SRT Initial implementation.
 | 
						|
*****************************************************************************/
 | 
						|
 | 
						|
#include "hcrypt.h"
 | 
						|
#include "cryspr.h"
 | 
						|
 | 
						|
#include <stdlib.h>
 | 
						|
#include <string.h>
 | 
						|
 | 
						|
int crysprStub_Prng(unsigned char *rn, int len)
 | 
						|
{
 | 
						|
	(void)rn;
 | 
						|
	(void)len;
 | 
						|
	return(0);
 | 
						|
}
 | 
						|
 | 
						|
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;
 | 
						|
	(void)aes_key;
 | 
						|
 | 
						|
	return(0);
 | 
						|
}
 | 
						|
 | 
						|
int crysprStub_AES_EcbCipher(
 | 
						|
	bool bEncrypt,              /* true:encrypt, false:decrypt */
 | 
						|
	CRYSPR_AESCTX *aes_key,     /* AES context */
 | 
						|
	const unsigned char *indata,/* src (clear text)*/
 | 
						|
	size_t inlen,               /* length */
 | 
						|
	unsigned char *out_txt,     /* dst (cipher text) */
 | 
						|
	size_t *outlen)             /* dst len */
 | 
						|
{
 | 
						|
	(void)bEncrypt;
 | 
						|
	(void)aes_key;
 | 
						|
	(void)indata;
 | 
						|
	(void)inlen;
 | 
						|
	(void)out_txt;
 | 
						|
	(void)outlen;
 | 
						|
 | 
						|
	return -1;
 | 
						|
}
 | 
						|
 | 
						|
int crysprStub_AES_CtrCipher(
 | 
						|
	bool bEncrypt,              /* true:encrypt, false:decrypt */
 | 
						|
	CRYSPR_AESCTX *aes_key,     /* AES context */
 | 
						|
	unsigned char *iv,          /* iv */
 | 
						|
	const unsigned char *indata,/* src */
 | 
						|
	size_t inlen,               /* length */
 | 
						|
	unsigned char *out_txt)     /* dest */
 | 
						|
{
 | 
						|
	(void)bEncrypt;
 | 
						|
	(void)aes_key;
 | 
						|
	(void)iv;
 | 
						|
	(void)indata;
 | 
						|
	(void)inlen;
 | 
						|
	(void)out_txt;
 | 
						|
 | 
						|
	return(-1);
 | 
						|
}
 | 
						|
 | 
						|
int crysprStub_AES_GCMCipher(
 | 
						|
	bool bEncrypt,              /* true:encrypt, false:decrypt */
 | 
						|
	CRYSPR_AESCTX *aes_key,     /* AES context */
 | 
						|
	unsigned char *iv,          /* iv */
 | 
						|
	const unsigned char *aad,   /* associated data */
 | 
						|
	size_t aadlen,
 | 
						|
	const unsigned char * indata,
 | 
						|
	size_t inlen,
 | 
						|
	unsigned char *out_txt,
 | 
						|
	unsigned char* out_tag)
 | 
						|
{
 | 
						|
	(void)bEncrypt;
 | 
						|
	(void)aes_key;
 | 
						|
	(void)iv;
 | 
						|
	(void)aad;
 | 
						|
	(void)aadlen;
 | 
						|
	(void)indata;
 | 
						|
	(void)inlen;
 | 
						|
	(void)out_txt;
 | 
						|
	(void)out_tag;
 | 
						|
 | 
						|
	return(-1);
 | 
						|
}
 | 
						|
 | 
						|
unsigned char *crysprStub_SHA1_MsgDigest(
 | 
						|
	const unsigned char *m, /* in: message */
 | 
						|
	size_t m_len,           /* message length */
 | 
						|
	unsigned char *md)      /* out: message digest buffer *160 bytes */
 | 
						|
{
 | 
						|
	(void)m;
 | 
						|
	(void)m_len;
 | 
						|
	(void)md;
 | 
						|
 | 
						|
	return(NULL);//return md;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
* Password-based Key Derivation Function
 | 
						|
*/
 | 
						|
int crysprStub_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;
 | 
						|
	(void)passwd;
 | 
						|
	(void)passwd_len;
 | 
						|
	(void)salt;
 | 
						|
	(void)salt_len;
 | 
						|
	(void)itr;
 | 
						|
	(void)key_len;
 | 
						|
	(void)out;
 | 
						|
 | 
						|
	/* >>Todo:
 | 
						|
	 * develop PBKDF2 using SHA1 primitive cryspr_cb->cryspr->sha1_msg_digest() for cryptolibs not providing it
 | 
						|
	 */
 | 
						|
	return(-1);
 | 
						|
}
 | 
						|
 | 
						|
static int crysprFallback_KmSetKey(CRYSPR_cb *cryspr_cb, bool bWrap, const unsigned char *kek, size_t kek_len)
 | 
						|
{
 | 
						|
	CRYSPR_AESCTX *aes_kek = CRYSPR_GETKEK(cryspr_cb);
 | 
						|
 | 
						|
	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);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
* AES_wrap_key()/AES_unwrap_key() introduced in openssl 0.9.8h
 | 
						|
* Here is an implementation using AES native API for cryspr not providing it.
 | 
						|
*/
 | 
						|
 | 
						|
static const unsigned char default_iv[] = {
 | 
						|
  0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6,
 | 
						|
};
 | 
						|
int crysprFallback_AES_WrapKey(CRYSPR_cb *cryspr_cb,
 | 
						|
		unsigned char *out,
 | 
						|
		const unsigned char *in,
 | 
						|
		unsigned int inlen)
 | 
						|
{
 | 
						|
	unsigned char *A, B[16], *R;
 | 
						|
	const unsigned char *iv = default_iv;
 | 
						|
	unsigned int i, j, t;
 | 
						|
	if ((inlen & 0x7) || (inlen < 8))
 | 
						|
		return -1;
 | 
						|
	A = B;
 | 
						|
	t = 1;
 | 
						|
	memcpy(out + 8, in, inlen);
 | 
						|
 | 
						|
	memcpy(A, iv, 8);
 | 
						|
 | 
						|
	for (j = 0; j < 6; j++)
 | 
						|
	{
 | 
						|
		R = out + 8;
 | 
						|
		for (i = 0; i < inlen; i += 8, t++, R += 8)
 | 
						|
		{
 | 
						|
			memcpy(B + 8, R, 8);
 | 
						|
			{
 | 
						|
				size_t outlen = 16;
 | 
						|
				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)	
 | 
						|
			{
 | 
						|
				A[6] ^= (unsigned char)((t >> 8) & 0xff);
 | 
						|
				A[5] ^= (unsigned char)((t >> 16) & 0xff);
 | 
						|
				A[4] ^= (unsigned char)((t >> 24) & 0xff);
 | 
						|
			}
 | 
						|
			memcpy(R, B + 8, 8);
 | 
						|
		}
 | 
						|
	}
 | 
						|
	memcpy(out, A, 8);
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
int crysprFallback_AES_UnwrapKey(CRYSPR_cb *cryspr_cb,
 | 
						|
		unsigned char *out,
 | 
						|
		const unsigned char *in,
 | 
						|
		unsigned int inlen)
 | 
						|
{
 | 
						|
	unsigned char *A, B[16], *R;
 | 
						|
	const unsigned char *iv = default_iv;
 | 
						|
	unsigned int i, j, t;
 | 
						|
	inlen -= 8;
 | 
						|
	if (inlen & 0x7)
 | 
						|
		return -1;
 | 
						|
	if (inlen < 8)
 | 
						|
		return -1;
 | 
						|
	A = B;
 | 
						|
	t =  6 * (inlen >> 3);
 | 
						|
	memcpy(A, in, 8);
 | 
						|
	memcpy(out, in + 8, inlen);
 | 
						|
	for (j = 0; j < 6; j++)
 | 
						|
	{
 | 
						|
		R = out + inlen - 8;
 | 
						|
		for (i = 0; i < inlen; i += 8, t--, R -= 8)
 | 
						|
		{
 | 
						|
			A[7] ^= (unsigned char)(t & 0xff);
 | 
						|
			if (t > 0xff)	
 | 
						|
			{
 | 
						|
				A[6] ^= (unsigned char)((t >> 8) & 0xff);
 | 
						|
				A[5] ^= (unsigned char)((t >> 16) & 0xff);
 | 
						|
				A[4] ^= (unsigned char)((t >> 24) & 0xff);
 | 
						|
			}
 | 
						|
			memcpy(B + 8, R, 8);
 | 
						|
			{
 | 
						|
				size_t outlen = 16;
 | 
						|
				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);
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if (memcmp(A, iv, 8))
 | 
						|
	{
 | 
						|
		memset(out, 0, inlen);
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
static unsigned char *_crysprFallback_GetOutbuf(CRYSPR_cb *cryspr_cb, size_t pfx_len, size_t out_len)
 | 
						|
{
 | 
						|
	unsigned char *out_buf;
 | 
						|
 | 
						|
	if ((pfx_len + out_len) > (cryspr_cb->outbuf_siz - cryspr_cb->outbuf_ofs)) {
 | 
						|
		/* Not enough room left, circle buffers */
 | 
						|
		cryspr_cb->outbuf_ofs = 0;
 | 
						|
	}
 | 
						|
	out_buf = &cryspr_cb->outbuf[cryspr_cb->outbuf_ofs];
 | 
						|
	cryspr_cb->outbuf_ofs += (pfx_len + out_len);
 | 
						|
	return(out_buf);
 | 
						|
}
 | 
						|
 | 
						|
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);
 | 
						|
 | 
						|
	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 = calloc(1, memsiz);
 | 
						|
	if (NULL == cryspr_cb) {
 | 
						|
		HCRYPT_LOG(LOG_ERR, "malloc(%zd) failed\n", memsiz);
 | 
						|
		return(NULL);
 | 
						|
	}
 | 
						|
	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;
 | 
						|
	cryspr_cb->ctr_stream_siz = HCRYPT_CTR_STREAM_SZ;
 | 
						|
	cryspr_cb->ctr_stream_len = 0;
 | 
						|
#endif /* !CRYSPR_HAS_AESCTR */
 | 
						|
 | 
						|
	cryspr_cb->outbuf = membuf;
 | 
						|
	cryspr_cb->outbuf_siz = CRYSPR_OUTMSGMAX * padded_len;
 | 
						|
	cryspr_cb->outbuf_ofs = 0;
 | 
						|
//	membuf += cryspr_cb->outbuf_siz;
 | 
						|
 | 
						|
	cryspr_cb->cryspr=(CRYSPR_methods *)cryspr;
 | 
						|
 | 
						|
	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)
 | 
						|
{
 | 
						|
	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_GETSEK(cryspr_cb, hcryptCtx_GetKeyIndex(ctx)); /* Ctx tells if it's for odd or even key */
 | 
						|
 | 
						|
	if (ctx->mode == HCRYPT_CTX_MODE_AESGCM) {   /* AES GCM mode */
 | 
						|
		if (cryspr_cb->cryspr->aes_set_key(HCRYPT_CTX_MODE_AESGCM, (ctx->flags & HCRYPT_CTX_F_ENCRYPT) != 0, key, key_len, aes_sek)) {
 | 
						|
			HCRYPT_LOG(LOG_ERR, "%s", "CRYSPR->set_encrypt_key(sek) failed\n");
 | 
						|
			return(-1);
 | 
						|
		}
 | 
						|
	} else 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(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(HCRYPT_CTX_MODE_AESCTR, false, key, key_len, aes_sek)) {
 | 
						|
			HCRYPT_LOG(LOG_ERR, "%s", "CRYSPR->set_decrypt_key(sek) failed\n");
 | 
						|
			return(-1);
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return(0);
 | 
						|
}
 | 
						|
 | 
						|
#if !CRYSPR_HAS_AESCTR
 | 
						|
static int _crysprFallback_AES_SetCtrStream(CRYSPR_cb *cryspr_cb, hcrypt_Ctx *ctx, size_t len, unsigned char *iv)
 | 
						|
{
 | 
						|
	/* Counter stream:
 | 
						|
	 *   0   1   2   3   4   5     nblk
 | 
						|
	 * +---+---+---+---+---+---+---+---+
 | 
						|
	 * |blk|blk|blk|blk|blk|blk|...|blk|
 | 
						|
	 * +---+---+---+---+---+---+---+---+
 | 
						|
	 */
 | 
						|
 | 
						|
	/* 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)
 | 
						|
	 */
 | 
						|
	unsigned char ctr[HCRYPT_CTR_BLK_SZ];
 | 
						|
	unsigned nblk;
 | 
						|
 | 
						|
	ASSERT(NULL != cryspr_cb);
 | 
						|
	ASSERT(NULL != ctx);
 | 
						|
 | 
						|
	memcpy(ctr, iv, HCRYPT_CTR_BLK_SZ);
 | 
						|
 | 
						|
	nblk = (len + (HCRYPT_CTR_BLK_SZ-1))/HCRYPT_CTR_BLK_SZ;
 | 
						|
	if ((nblk * HCRYPT_CTR_BLK_SZ) <= cryspr_cb->ctr_stream_siz) {
 | 
						|
		unsigned blk;
 | 
						|
		unsigned char *csp = &cryspr_cb->ctr_stream[0];
 | 
						|
 | 
						|
		for(blk = 0; blk < nblk; blk++) {
 | 
						|
			memcpy(csp, ctr, HCRYPT_CTR_BLK_SZ);
 | 
						|
			csp += HCRYPT_CTR_BLK_SZ;
 | 
						|
			if (0 == ++(ctr[HCRYPT_CTR_BLK_SZ-1])) ++(ctr[HCRYPT_CTR_BLK_SZ-2]);
 | 
						|
		}
 | 
						|
		cryspr_cb->ctr_stream_len = nblk * HCRYPT_CTR_BLK_SZ;
 | 
						|
	} else {
 | 
						|
		HCRYPT_LOG(LOG_ERR, "packet too long(%zd)\n", len);
 | 
						|
		return(-1);
 | 
						|
	}
 | 
						|
	return(0);
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
static int crysprFallback_MsEncrypt(
 | 
						|
	CRYSPR_cb *cryspr_cb,
 | 
						|
	hcrypt_Ctx *ctx,
 | 
						|
	hcrypt_DataDesc *in_data, int nbin ATR_UNUSED,
 | 
						|
	void *out_p[], size_t out_len_p[], int *nbout_p)
 | 
						|
{
 | 
						|
	unsigned char *out_msg;
 | 
						|
	size_t out_len = 0;	//payload size
 | 
						|
	int pfx_len;
 | 
						|
 | 
						|
	ASSERT(NULL != ctx);
 | 
						|
	ASSERT(NULL != cryspr_cb);
 | 
						|
	ASSERT((NULL != in_data) || (1 == nbin)); //Only one in_data[] supported
 | 
						|
 | 
						|
	/* 
 | 
						|
	 * Get message prefix length
 | 
						|
	 * to reserve room for unencrypted message header in output buffer
 | 
						|
	 */
 | 
						|
	pfx_len = ctx->msg_info->pfx_len;
 | 
						|
	/* Extra 16 bytes are needed for an authentication tag in GCM. */
 | 
						|
	const int aux_len = (ctx->mode == HCRYPT_CTX_MODE_AESGCM) ? HAICRYPT_AUTHTAG_MAX : 0;
 | 
						|
 | 
						|
	/* Auth tag produced by AES GCM. */
 | 
						|
	unsigned char tag[HAICRYPT_AUTHTAG_MAX];
 | 
						|
 | 
						|
	/*
 | 
						|
	 * Get buffer room from the internal circular output buffer.
 | 
						|
	 * Reserve additional 16 bytes for auth tag in AES GCM mode when needed.
 | 
						|
	 */
 | 
						|
	out_msg = _crysprFallback_GetOutbuf(cryspr_cb, pfx_len, in_data[0].len + aux_len);
 | 
						|
	if (NULL == out_msg) {
 | 
						|
		/* input data too big */
 | 
						|
		return(-1);
 | 
						|
	}
 | 
						|
 | 
						|
	switch(ctx->mode) {
 | 
						|
		case HCRYPT_CTX_MODE_AESCTR: /* Counter mode */
 | 
						|
		case HCRYPT_CTX_MODE_AESGCM:
 | 
						|
		{
 | 
						|
			/* 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);
 | 
						|
 | 
						|
			/*
 | 
						|
			 * 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 (ctx->mode == HCRYPT_CTX_MODE_AESGCM)
 | 
						|
			{
 | 
						|
				const int iret = cryspr_cb->cryspr->aes_gcm_cipher(true, aes_key, iv, in_data[0].pfx, pfx_len, in_data[0].payload, in_data[0].len,
 | 
						|
						&out_msg[pfx_len], tag);
 | 
						|
				if (iret) {
 | 
						|
					return(iret);
 | 
						|
				}
 | 
						|
			}
 | 
						|
			else {
 | 
						|
#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);
 | 
						|
				}
 | 
						|
				/* 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;
 | 
						|
			if (ctx->mode == HCRYPT_CTX_MODE_AESGCM)
 | 
						|
			{
 | 
						|
				memcpy(out_msg + pfx_len + out_len, tag, sizeof(tag));
 | 
						|
				out_len += sizeof(tag);
 | 
						|
			}
 | 
						|
			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);
 | 
						|
	}
 | 
						|
 | 
						|
	if (out_len <= 0) {
 | 
						|
		/*
 | 
						|
		 * Nothing out
 | 
						|
		 * This is not an error for implementations using deferred/async processing
 | 
						|
		 * with co-processor, DSP, crypto hardware, etc.
 | 
						|
		 * Submitted input data could be returned encrypted in a next call.
 | 
						|
		 */
 | 
						|
		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);
 | 
						|
			if (ctx->mode == HCRYPT_CTX_MODE_AESGCM) {
 | 
						|
				// Encoding produced more payload (auth tag).
 | 
						|
				return (int)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);
 | 
						|
}
 | 
						|
 | 
						|
static int crysprFallback_MsDecrypt(CRYSPR_cb *cryspr_cb, hcrypt_Ctx *ctx,
 | 
						|
	hcrypt_DataDesc *in_data, int nbin ATR_UNUSED, void *out_p[], size_t out_len_p[], int *nbout_p)
 | 
						|
{
 | 
						|
	unsigned char *out_txt;
 | 
						|
	size_t out_len;
 | 
						|
	int iret = 0;
 | 
						|
 | 
						|
	ASSERT(NULL != cryspr_cb);
 | 
						|
	ASSERT(NULL != ctx);
 | 
						|
	ASSERT((NULL != in_data) || (1 == nbin)); //Only one in_data[] supported
 | 
						|
 | 
						|
	/* Reserve output buffer (w/no header) */
 | 
						|
	out_txt = _crysprFallback_GetOutbuf(cryspr_cb, 0, in_data[0].len);
 | 
						|
 | 
						|
	if (NULL != out_txt) {
 | 
						|
		switch(ctx->mode) {
 | 
						|
			case HCRYPT_CTX_MODE_AESCTR:
 | 
						|
			case HCRYPT_CTX_MODE_AESGCM:
 | 
						|
			{
 | 
						|
				/* Get current key (odd|even) from context */
 | 
						|
				CRYSPR_AESCTX *aes_key = CRYSPR_GETSEK(cryspr_cb, 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);
 | 
						|
 | 
						|
				if (ctx->mode == HCRYPT_CTX_MODE_AESGCM)
 | 
						|
				{
 | 
						|
					unsigned char* tag = in_data[0].payload + in_data[0].len - HAICRYPT_AUTHTAG_MAX;
 | 
						|
					int liret = cryspr_cb->cryspr->aes_gcm_cipher(false, aes_key, iv, in_data[0].pfx, ctx->msg_info->pfx_len, in_data[0].payload, in_data[0].len - HAICRYPT_AUTHTAG_MAX,
 | 
						|
						out_txt, tag);
 | 
						|
					if (liret) {
 | 
						|
						return(liret);
 | 
						|
					}
 | 
						|
					out_len = in_data[0].len - HAICRYPT_AUTHTAG_MAX;
 | 
						|
				}
 | 
						|
				else {
 | 
						|
#if CRYSPR_HAS_AESCTR
 | 
						|
					cryspr_cb->cryspr->aes_ctr_cipher(false, aes_key, iv, in_data[0].payload, in_data[0].len,
 | 
						|
						out_txt);
 | 
						|
					out_len = in_data[0].len;
 | 
						|
#else  /*CRYSPR_HAS_AESCTR*/
 | 
						|
 | 
						|
					/* 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 cipher block size boundary) */
 | 
						|
					int liret = _crysprFallback_AES_SetCtrStream(cryspr_cb, ctx, in_data[0].len, iv);
 | 
						|
					if (liret) {
 | 
						|
						return(liret);
 | 
						|
					}
 | 
						|
					/* Reserve output buffer for cryspr */
 | 
						|
					out_txt = _crysprFallback_GetOutbuf(cryspr_cb, 0, cryspr_cb->ctr_stream_len);
 | 
						|
 | 
						|
					/* Create KeyStream (encrypt CtrStream) */
 | 
						|
					liret = cryspr_cb->cryspr->aes_ecb_cipher(true, aes_key,
 | 
						|
						cryspr_cb->ctr_stream, cryspr_cb->ctr_stream_len,
 | 
						|
						out_txt, &out_len);
 | 
						|
					if (liret) {
 | 
						|
						HCRYPT_LOG(LOG_ERR, "%s", "crysprNatural_AES_ecb_cipher(encrypt failed\n");
 | 
						|
						return(liret);
 | 
						|
					}
 | 
						|
 | 
						|
#endif /*CRYSPR_HAS_AESCTR*/
 | 
						|
				}
 | 
						|
				break;
 | 
						|
			}
 | 
						|
			case HCRYPT_CTX_MODE_CLRTXT:
 | 
						|
				memcpy(out_txt, in_data[0].payload, in_data[0].len);
 | 
						|
				out_len = in_data[0].len;
 | 
						|
				break;
 | 
						|
			default:
 | 
						|
				return(-1);
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		return(-1);
 | 
						|
	}
 | 
						|
 | 
						|
	if (out_len > 0) {
 | 
						|
		if (NULL == out_p) {
 | 
						|
			/*
 | 
						|
			 * Application did not provided output buffer,
 | 
						|
			 * so copy encrypted message back in input buffer
 | 
						|
			 */
 | 
						|
#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_txt, out_len);
 | 
						|
			}else{
 | 
						|
				/* Copy output data back in input buffer */
 | 
						|
				memcpy(in_data[0].payload, out_txt, out_len);
 | 
						|
			}
 | 
						|
#else /* CRYSPR_HAS_AESCTR */
 | 
						|
			/* Copy output data back in input buffer */
 | 
						|
			memcpy(in_data[0].payload, out_txt, out_len);
 | 
						|
			in_data->len = out_len;
 | 
						|
#endif /* CRYSPR_HAS_AESCTR */
 | 
						|
		} else {
 | 
						|
			/* Copy header in output buffer if needed */
 | 
						|
#if !CRYSPR_HAS_AESCTR
 | 
						|
			if (ctx->mode == HCRYPT_CTX_MODE_AESCTR) {
 | 
						|
				hcrypt_XorStream(out_txt, in_data[0].payload, out_len);
 | 
						|
			}
 | 
						|
#endif /* CRYSPR_HAS_AESCTR */
 | 
						|
			out_p[0] = out_txt;
 | 
						|
			out_len_p[0] = out_len;
 | 
						|
			*nbout_p = 1;
 | 
						|
		}
 | 
						|
		iret = 0;
 | 
						|
	} else {
 | 
						|
		if (NULL != nbout_p) *nbout_p = 0;
 | 
						|
		iret = -1;
 | 
						|
	}
 | 
						|
 | 
						|
#if 0
 | 
						|
	{	/* Debug decryption errors */
 | 
						|
		static int nberr = 0;
 | 
						|
 | 
						|
		if (out_txt[0] != 0x47){
 | 
						|
			if ((++nberr == 1)
 | 
						|
					||  ((nberr > 500) && (0 == ((((unsigned char *)&MSmsg->pki)[2] & 0x0F)|((unsigned char *)&MSmsg->pki)[3])))) {
 | 
						|
				HCRYPT_LOG(LOG_DEBUG, "keyindex=%d\n", hcryptCtx_GetKeyIndex(ctx));
 | 
						|
				HCRYPT_PRINTKEY(ctx->sek, ctx->sek_len, "sek"); 
 | 
						|
				HCRYPT_PRINTKEY(ctx->salt, ctx->salt_len, "salt"); 
 | 
						|
			}
 | 
						|
		} else {
 | 
						|
			nberr = 0;
 | 
						|
		}
 | 
						|
	}
 | 
						|
#endif
 | 
						|
	return(iret);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
CRYSPR_methods *crysprInit(CRYSPR_methods *cryspr)
 | 
						|
{
 | 
						|
	/* CryptoLib Primitive API */
 | 
						|
	cryspr->prng            = crysprStub_Prng;
 | 
						|
	cryspr->aes_set_key     = crysprStub_AES_SetKey;
 | 
						|
	cryspr->aes_ecb_cipher  = crysprStub_AES_EcbCipher;
 | 
						|
	cryspr->aes_ctr_cipher  = crysprStub_AES_CtrCipher;
 | 
						|
	cryspr->aes_gcm_cipher  = crysprStub_AES_GCMCipher;
 | 
						|
	cryspr->sha1_msg_digest = crysprStub_SHA1_MsgDigest;
 | 
						|
 | 
						|
	/* Crypto Session API */
 | 
						|
	cryspr->open       = crysprFallback_Open;
 | 
						|
	cryspr->close      = crysprFallback_Close;
 | 
						|
	//Keying material (km) encryption
 | 
						|
	cryspr->km_pbkdf2  = crysprStub_KmPbkdf2;
 | 
						|
	cryspr->km_setkey  = crysprFallback_KmSetKey;
 | 
						|
	cryspr->km_wrap    = crysprFallback_AES_WrapKey;
 | 
						|
	cryspr->km_unwrap  = crysprFallback_AES_UnwrapKey;
 | 
						|
	//Media stream (ms) encryption
 | 
						|
	cryspr->ms_setkey  = crysprFallback_MsSetKey;
 | 
						|
	cryspr->ms_encrypt = crysprFallback_MsEncrypt;
 | 
						|
	cryspr->ms_decrypt = crysprFallback_MsDecrypt;
 | 
						|
 | 
						|
	return(cryspr);
 | 
						|
}
 | 
						|
 | 
						|
HaiCrypt_Cryspr HaiCryptCryspr_Get_Instance(void)
 | 
						|
{
 | 
						|
	return((HaiCrypt_Cryspr)cryspr4SRT());
 | 
						|
}
 |