LINUX.ORG.RU

Как правильно посчитать HMAC_SHA1 для SRTP пакета?

 , , , srtp,


0

1

Мне надо сделать HMAC_SHA1 подпись для SRTP пакета, чтоб через mbedtls либу. Я взял и подсмотрел в либу re в которой есть реализация SRTP и там для SRTP есть HMAC подпись, вот тут:

https://github.com/creytiv/re/blob/05a960b6d633b7f648b7b23b8afc02becbfab157/s...

https://github.com/creytiv/re/blob/38e17f90870c02bed4e50ee883372a1932a4cb67/s...

Попробовал это всё переделать, в общем вот такой код получился

// gcc main.c -lmbedtls -lmbedcrypto

#include <inttypes.h>
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
#include <arpa/inet.h>
#include <errno.h>
#include "mbedtls/aes.h"

#include "mbedtls/md.h"

#include <stdio.h>


//test_srtp_libsrtp
#define AES_BLOCK_SIZE 16
#define MAX_KEYLEN 32
#define SHA_DIGEST_LENGTH 20
#define RTP_VERSION 2

enum aes_mode {
	AES_MODE_CTR,  /**< AES Counter mode (CTR) */
	AES_MODE_GCM,  /**< AES Galois Counter Mode (GCM) */
};

union vect128 {
	uint64_t u64[ 2];
	uint32_t u32[ 4];
	uint16_t u16[ 8];
	uint8_t   u8[16];
};

struct rtp_header {
	uint8_t  ver;       /**< RTP version number     */
	bool     pad;       /**< Padding bit            */
	bool     ext;       /**< Extension bit          */
	uint8_t  cc;        /**< CSRC count             */
	bool     m;         /**< Marker bit             */
	uint8_t  pt;        /**< Payload type           */
	uint16_t seq;       /**< Sequence number        */
	uint32_t ts;        /**< Timestamp              */
	uint32_t ssrc;      /**< Synchronization source */
	uint32_t csrc[16];  /**< Contributing sources   */
	struct {
		uint16_t type;  /**< Defined by profile     */
		uint16_t len;   /**< Number of 32-bit words */
	} x;
};


struct hmac {
	uint8_t key[SHA_DIGEST_LENGTH];
	size_t key_len;
};


struct comp {
//	struct aes *aes;    /**< AES Context                       */
//	enum aes_mode mode; /**< AES encryption mode               */
	mbedtls_aes_context aes;
	
//	struct hmac *hmac;  /**< HMAC Context                      */
	struct hmac hmac;
	union vect128 iv;
	union vect128 k_s;  /**< Derived salting key (14 bytes)    */
	size_t tag_len;     /**< CTR Auth. tag length [bytes]      */
};



static int test_srtp_libsrtp(void);

static int comp_init(struct comp *c, unsigned offs,
		     const uint8_t *key, size_t key_b,
		     const uint8_t *s, size_t s_b,
		     size_t tag_len, bool encrypted, bool hash,
		     enum aes_mode mode);

int srtp_derive(uint8_t *out, size_t out_len, uint8_t label,
		const uint8_t *master_key, size_t key_bytes,
		const uint8_t *master_salt, size_t salt_bytes);


void srtp_iv_calc(union vect128 *iv, const union vect128 *k_s,
		  uint32_t ssrc, uint64_t ix);

int main(void)
{
  test_srtp_libsrtp();
  return 0;
}




/*
 * Reference SRTP-packet generated by libsrtp
 *
 * cipher:       AES-CM-128
 * auth:         HMAC-SHA1 80-bits tag
 * master key:   0x22222222222222222222222222222222
 * master salt:  0x4444444444444444444444444444
 * SSRC:         0x01020304
 * Seq:          0x0001
 * RTP payload:  0xa5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5
 */

/*
static const char *srtp_libsrtp =
	"800000010000000001020304"
	"f5b44b7e3ad4eb057bc6480c45df6547bb70bcc2"
	"7b136e1f3d3a62821b15";
*/

static const char *srtp_payload =
"f5b44b7e3ad4eb057bc6480c45df6547bb70bcc2";
static const char *srtp_hmac =
"7b136e1f3d3a62821b15";

static int test_srtp_libsrtp(void)
{
//	uint8_t pkt[12+20+10];
	uint8_t payload_encr[20];
	uint8_t payload_hash[8];
//	struct srtp *srtp_enc = NULL;
	static const uint8_t mast_key[16+14] =
		"\x22\x22\x22\x22\x22\x22\x22\x22"
		"\x22\x22\x22\x22\x22\x22\x22\x22"
		"\x44\x44\x44\x44\x44\x44\x44"
		"\x44\x44\x44\x44\x44\x44\x44";
	static const uint8_t rtp_payload[20] =
		"\xa5\xa5\xa5\xa5\xa5\xa5\xa5\xa5\xa5\xa5"
		"\xa5\xa5\xa5\xa5\xa5\xa5\xa5\xa5\xa5\xa5";
	
	struct mbuf *mb;
	struct rtp_header hdr;
	memset(&hdr, 0, sizeof(hdr));
	hdr.ver  = RTP_VERSION;
	hdr.ssrc = 0x01020304;
	hdr.seq  = 0x0001;



//// SRTP alloc

// SRTP_AES_CM_128_HMAC_SHA1_80
	size_t cipher_bytes, salt_bytes, auth_bytes;
//mode = AES_MODE_CTR;

	enum aes_mode mode;
	bool hash;
	const uint8_t *master_salt;

	mode = AES_MODE_CTR;
	cipher_bytes = 16;
	salt_bytes   = 14;
	auth_bytes   = 10;
	hash         = true;

	master_salt = &mast_key[cipher_bytes];

	/*comp_init(&srtp->rtp,  0, key, cipher_bytes,
			 master_salt, salt_bytes, auth_bytes,
			 true, hash, mode);
*/



	struct comp rtp;

	comp_init(&rtp,  0, mast_key, cipher_bytes,
			 master_salt, salt_bytes, auth_bytes,
			 true, hash, mode);
//// end SRTP alloc

	union vect128 iv;
	//uint8_t *p = payload_encr;


	struct srtp_stream *strm;
	uint64_t ix;
	
	//ix = 65536ULL * strm->roc + hdr.seq;
	ix = hdr.seq;

	srtp_iv_calc(&rtp.iv, &rtp.k_s, hdr.ssrc, ix);

	//aes_set_iv(comp->aes, iv.u8);
	//comp.iv = iv;

	size_t nc_off = 0;
	uint8_t stream_block[16] = {0};

	mbedtls_aes_crypt_ctr(&rtp.aes,
		sizeof(payload_encr), &nc_off, rtp.iv.u8,
		stream_block, rtp_payload, payload_encr);

	mbedtls_aes_free( &rtp.aes );

	for(size_t i = 0; i < sizeof(payload_encr); i++)
	{
		printf("%02" PRIx8 "", payload_encr[i]);
	}
	puts("");
	puts(srtp_payload);

	printf("\n-------------\n");


	const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type (MBEDTLS_MD_SHA1);

	unsigned char hmac_sign[20] = {0};

	/// ТУТ КАКАЯ_ТО ПРОБЛЕМА!!!!!!!!!!!!!!
	mbedtls_md_hmac (md_info, rtp.hmac.key, rtp.hmac.key_len,
		payload_encr, sizeof(payload_encr), hmac_sign);


	for(size_t i = 0; i < sizeof(hmac_sign); i++)
	{
		printf("%02" PRIx8 "", hmac_sign[i]);
	}
	puts("");
	puts(srtp_hmac);

	printf("\n-------------\n");

}


static int comp_init(struct comp *c, unsigned offs,
		     const uint8_t *key, size_t key_b,
		     const uint8_t *s, size_t s_b,
		     size_t tag_len, bool encrypted, bool hash,
		     enum aes_mode mode)
{
	uint8_t k_e[MAX_KEYLEN], k_a[SHA_DIGEST_LENGTH];
	int err = 0;

	if (key_b > sizeof(k_e))
		return EINVAL;

	if (tag_len > SHA_DIGEST_LENGTH)
		return EINVAL;

	c->tag_len = tag_len;
	//c->mode = mode;

	err |= srtp_derive(k_e, key_b,       0x00+offs, key, key_b, s, s_b);
	err |= srtp_derive(k_a, sizeof(k_a), 0x01+offs, key, key_b, s, s_b);
	err |= srtp_derive(c->k_s.u8, 14,    0x02+offs, key, key_b, s, s_b);
	if (err)
		return err;

	if (encrypted) {
		mbedtls_aes_init(&c->aes);
		mbedtls_aes_setkey_enc(&c->aes, k_e, key_b*8);
/*		err = aes_alloc(&c->aes, mode, k_e, key_b*8, NULL);
		if (err)
			return err;*/
	}

	if (hash) {
		memcpy(&c->hmac.key, k_a, sizeof(k_a));
		c->hmac.key_len = sizeof(k_a);
		/*err = hmac_create(&c->hmac, HMAC_HASH_SHA1, k_a, sizeof(k_a));
		if (err)
			return err;*/
	}

	return err;
}


int srtp_derive(uint8_t *out, size_t out_len, uint8_t label,
		const uint8_t *master_key, size_t key_bytes,
		const uint8_t *master_salt, size_t salt_bytes)
{
	uint8_t x[AES_BLOCK_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
	static const uint8_t null[AES_BLOCK_SIZE * 2];
	//struct aes *aes;
	int err = 0;

	if (!out || !master_key || !master_salt)
		return EINVAL;

	if (out_len > sizeof(null) || salt_bytes > sizeof(x))
		return EINVAL;

	memcpy(x, master_salt, salt_bytes);
	x[7] ^= label;

	/* NOTE: Counter Mode is used for both CTR and GCM */
//	err = aes_alloc(&aes, AES_MODE_CTR, master_key, key_bytes*8, x); TODO
//	if (err)
//		return err;

//	err = aes_encr(aes, out, null, out_len);
	size_t nc_off = 0;

	mbedtls_aes_context aes;
	mbedtls_aes_init(&aes);
	mbedtls_aes_setkey_enc(&aes, master_key, key_bytes*8);

	uint8_t stream_block[16] = {0};

	mbedtls_aes_crypt_ctr(&aes,
		out_len, &nc_off, x,
		stream_block, null, out);

	/*int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx,
                       out_len,
                       size_t *nc_off,
                       unsigned char nonce_counter[16],
                       unsigned char stream_block[16],
                       const unsigned char *input,
                       unsigned char *output )*/
	mbedtls_aes_free( &aes );

//	mem_deref(aes); TODO

	return err;

}

void srtp_iv_calc(union vect128 *iv, const union vect128 *k_s,
		  uint32_t ssrc, uint64_t ix)
{
	if (!iv || !k_s)
		return;

	iv->u32[0] = k_s->u32[0];
	iv->u32[1] = k_s->u32[1] ^ htonl(ssrc);
	iv->u32[2] = k_s->u32[2] ^ htonl((uint32_t)(ix>>16));
	iv->u16[6] = k_s->u16[6] ^ htons((uint16_t)ix);
	iv->u16[7] = 0;
}

Я использую функцию mbedtls_md_hmac() но оно выдает не то, что надо. Притом само шифрование сходится. В чем тут может быть проблема, где я напутал?

★★★★★

Последнее исправление: SZT (всего исправлений: 1)

Разобрался сам

SZT ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.