Мне надо сделать HMAC_SHA1 подпись для SRTP пакета, чтоб через mbedtls либу.
Я взял и подсмотрел в либу re в которой есть реализация SRTP и там для SRTP есть HMAC подпись, вот тут:
// 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;
}