From 0c4110779d679ff1ecf1d0f91a16d624a9c91422 Mon Sep 17 00:00:00 2001 From: SPChan Date: Wed, 20 Jan 2021 10:08:16 -0500 Subject: [PATCH] TT#108551 add support for AEAD-AES-GCM close PR #1133 Squashed commit of: commit b5009eff0be233e4357546994393819712d63b23 Author: SPChan Date: Fri Dec 11 11:40:17 2020 +0800 crypto.c: handle 12 bytes master salt length of AEAD AEAD RFC7714 specifies 12 bytes master salt length (section 12) but the KDF expects 14 bytes. The erratum to RFC7714 specifies to pad on the right by 16 bits to be compliant with the KDF. https://www.rfc-editor.org/errata_search.php?rfc=7714 commit 30ba71f10cefa93da44291cf28e936da0c015d51 Author: SPChan Date: Fri Dec 11 09:31:00 2020 +0800 crypto.c: AEAD make clear which operations are for AAD commit 3e4d87681dc49b01f969f5b2d5d341aba79e65d1 Author: SPChan Date: Thu Dec 10 19:38:51 2020 +0800 Implement RFC7714 ciphers: AEAD AES Initial userspace only implementation Change-Id: I8624b255e4fd83a5ca418655ef117c48e56e2379 --- daemon/crypto.c | 206 ++++++++++++++++++++++++++++++++++++++++- t/Makefile | 6 +- t/aead-aes-crypt.c | 223 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 432 insertions(+), 3 deletions(-) create mode 100644 t/aead-aes-crypt.c diff --git a/daemon/crypto.c b/daemon/crypto.c index 85c9bf577..d31d55d5a 100644 --- a/daemon/crypto.c +++ b/daemon/crypto.c @@ -25,11 +25,16 @@ GString __thread *crypto_debug_string; static int aes_cm_encrypt_rtp(struct crypto_context *, struct rtp_header *, str *, u_int64_t); static int aes_cm_encrypt_rtcp(struct crypto_context *, struct rtcp_packet *, str *, u_int64_t); +static int aes_gcm_encrypt_rtp(struct crypto_context *, struct rtp_header *, str *, u_int64_t); +static int aes_gcm_decrypt_rtp(struct crypto_context *, struct rtp_header *, str *, u_int64_t); +static int aes_gcm_encrypt_rtcp(struct crypto_context *, struct rtcp_packet *, str *, u_int64_t); +static int aes_gcm_decrypt_rtcp(struct crypto_context *, struct rtcp_packet *, str *, u_int64_t); static int hmac_sha1_rtp(struct crypto_context *, char *out, str *in, u_int64_t); static int hmac_sha1_rtcp(struct crypto_context *, char *out, str *in); static int aes_f8_encrypt_rtp(struct crypto_context *c, struct rtp_header *r, str *s, u_int64_t idx); static int aes_f8_encrypt_rtcp(struct crypto_context *c, struct rtcp_packet *r, str *s, u_int64_t idx); static int aes_cm_session_key_init(struct crypto_context *c); +static int aes_gcm_session_key_init(struct crypto_context *c); static int aes_f8_session_key_init(struct crypto_context *c); static int evp_session_key_cleanup(struct crypto_context *c); static int null_crypt_rtp(struct crypto_context *c, struct rtp_header *r, str *s, u_int64_t idx); @@ -181,6 +186,54 @@ struct crypto_suite __crypto_suites[] = { .session_key_init = aes_cm_session_key_init, .session_key_cleanup = evp_session_key_cleanup, }, + { + .name = "AEAD_AES_128_GCM", + .dtls_name = "SRTP_AEAD_AES_128_GCM", + .master_key_len = 16, + .master_salt_len = 12, + .session_key_len = 16, + .session_salt_len = 12, + .srtp_lifetime = 1ULL << 48, + .srtcp_lifetime = 1ULL << 31, + //.kernel_cipher = REC_AES_CM_128, + //.kernel_hmac = REH_HMAC_SHA1, + .srtp_auth_tag = 0, + .srtcp_auth_tag = 0, + .srtp_auth_key_len = 0, + .srtcp_auth_key_len = 0, + .encrypt_rtp = aes_gcm_encrypt_rtp, + .decrypt_rtp = aes_gcm_decrypt_rtp, + .encrypt_rtcp = aes_gcm_encrypt_rtcp, + .decrypt_rtcp = aes_gcm_decrypt_rtcp, + //.hash_rtp = hmac_sha1_rtp, + //.hash_rtcp = hmac_sha1_rtcp, + .session_key_init = aes_gcm_session_key_init, + .session_key_cleanup = evp_session_key_cleanup, + }, + { + .name = "AEAD_AES_256_GCM", + .dtls_name = "SRTP_AEAD_AES_256_GCM", + .master_key_len = 32, + .master_salt_len = 12, + .session_key_len = 32, + .session_salt_len = 12, + .srtp_lifetime = 1ULL << 48, + .srtcp_lifetime = 1ULL << 31, + //.kernel_cipher = REC_AES_CM_256, + //.kernel_hmac = REH_HMAC_SHA1, + .srtp_auth_tag = 0, + .srtcp_auth_tag = 0, + .srtp_auth_key_len = 0, + .srtcp_auth_key_len = 0, + .encrypt_rtp = aes_gcm_encrypt_rtp, + .decrypt_rtp = aes_gcm_decrypt_rtp, + .encrypt_rtcp = aes_gcm_encrypt_rtcp, + .decrypt_rtcp = aes_gcm_decrypt_rtcp, + //.hash_rtp = hmac_sha1_rtp, + //.hash_rtcp = hmac_sha1_rtcp, + .session_key_init = aes_gcm_session_key_init, + .session_key_cleanup = evp_session_key_cleanup, + }, { .name = "F8_128_HMAC_SHA1_80", // .dtls_name = "SRTP_AES128_F8_SHA1_80", @@ -418,7 +471,14 @@ int crypto_gen_session_key(struct crypto_context *c, str *out, unsigned char lab * key_derivation_rate == 0 --> r == 0 */ key_id[0] = label; - memcpy(x, c->params.master_salt, 14); + // AEAD uses 12 bytes master salt; pad on the right to get 14 + // Errata: https://www.rfc-editor.org/errata_search.php?rfc=7714 + if (c->params.crypto_suite->master_salt_len == 12) { + memcpy(x, c->params.master_salt, 12); + x[12] = x[13] = '\x00'; + } else { + memcpy(x, c->params.master_salt, 14); + } for (i = 13 - index_len; i < 14; i++) x[i] = key_id[i - (13 - index_len)] ^ x[i]; @@ -491,6 +551,138 @@ static int aes_cm_encrypt_rtcp(struct crypto_context *c, struct rtcp_packet *r, return aes_cm_encrypt(c, r->ssrc, s, idx); } +/* rfc 7714 section 8 */ + +static int aes_gcm_encrypt_rtp(struct crypto_context *c, struct rtp_header *r, str *s, u_int64_t idx) { + unsigned char iv[12]; + int len, ciphertext_len; + + memcpy(iv, c->session_salt, 12); + + *(u_int32_t*)(iv+2) ^= r->ssrc; + *(u_int32_t*)(iv+6) ^= htonl((idx & 0x00ffffffff0000ULL) >> 16); + *(u_int16_t*)(iv+10) ^= htons(idx & 0x00ffffULL); + + if (c->params.crypto_suite->session_key_len == 16) { + EVP_EncryptInit_ex(c->session_key_ctx[0], EVP_aes_128_gcm(), NULL, c->session_key, iv); + } else { + EVP_EncryptInit_ex(c->session_key_ctx[0], EVP_aes_256_gcm(), NULL, c->session_key, iv); + } + + // nominally 12 bytes of AAD + EVP_EncryptUpdate(c->session_key_ctx[0], NULL, &len, (void *)r, s->s - (char *)r); + + EVP_EncryptUpdate(c->session_key_ctx[0], s->s, &len, s->s, s->len); + ciphertext_len = len; + if (!EVP_EncryptFinal_ex(c->session_key_ctx[0], s->s+len, &len)) + return 1; + ciphertext_len += len; + // append the tag to the str buffer + EVP_CIPHER_CTX_ctrl(c->session_key_ctx[0], EVP_CTRL_GCM_GET_TAG, 16, s->s+ciphertext_len); + s->len = ciphertext_len + 16; + + return 0; +} + +static int aes_gcm_decrypt_rtp(struct crypto_context *c, struct rtp_header *r, str *s, u_int64_t idx) { + unsigned char iv[12]; + int len, plaintext_len; + + memcpy(iv, c->session_salt, 12); + + *(u_int32_t*)(iv+2) ^= r->ssrc; + *(u_int32_t*)(iv+6) ^= htonl((idx & 0x00ffffffff0000ULL) >> 16); + *(u_int16_t*)(iv+10) ^= htons(idx & 0x00ffffULL); + + if (c->params.crypto_suite->session_key_len == 16) { + EVP_DecryptInit_ex(c->session_key_ctx[0], EVP_aes_128_gcm(), NULL, c->session_key, iv); + } else { + EVP_DecryptInit_ex(c->session_key_ctx[0], EVP_aes_256_gcm(), NULL, c->session_key, iv); + } + + // nominally 12 bytes of AAD + EVP_DecryptUpdate(c->session_key_ctx[0], NULL, &len, (void *)r, s->s - (char *)r); + + // decrypt partial buffer - the last 16 bytes are the tag + EVP_DecryptUpdate(c->session_key_ctx[0], s->s, &len, s->s, s->len-16); + plaintext_len = len; + EVP_CIPHER_CTX_ctrl(c->session_key_ctx[0], EVP_CTRL_GCM_SET_TAG, 16, s->s + s->len-16); + if (!EVP_DecryptFinal_ex(c->session_key_ctx[0], s->s+len, &len)) + return 1; + plaintext_len += len; + s->len = plaintext_len; + + return 0; +} + +/* rfc 7714 section 9 */ + +static int aes_gcm_encrypt_rtcp(struct crypto_context *c, struct rtcp_packet *r, str *s, u_int64_t idx) { + unsigned char iv[12]; + unsigned char e_idx[4]; + int len, ciphertext_len; + + memcpy(iv, c->session_salt, 12); + + *(u_int32_t*)(iv+2) ^= r->ssrc; + *(u_int32_t*)(iv+8) ^= htonl(idx & 0x007fffffffULL); + *(u_int32_t*)e_idx = htonl( (idx&0x007fffffffULL) | 0x80000000); + + if (c->params.crypto_suite->session_key_len == 16) { + EVP_EncryptInit_ex(c->session_key_ctx[0], EVP_aes_128_gcm(), NULL, c->session_key, iv); + } else { + EVP_EncryptInit_ex(c->session_key_ctx[0], EVP_aes_256_gcm(), NULL, c->session_key, iv); + } + + // nominally 8 + 4 bytes of AAD + EVP_EncryptUpdate(c->session_key_ctx[0], NULL, &len, (void *)r, s->s - (char *)r); + EVP_EncryptUpdate(c->session_key_ctx[0], NULL, &len, (void *)e_idx, 4); + + EVP_EncryptUpdate(c->session_key_ctx[0], s->s, &len, s->s, s->len); + ciphertext_len = len; + if (!EVP_EncryptFinal_ex(c->session_key_ctx[0], s->s+len, &len)) + return 1; + ciphertext_len += len; + // append the tag to the str buffer + EVP_CIPHER_CTX_ctrl(c->session_key_ctx[0], EVP_CTRL_GCM_GET_TAG, 16, s->s+ciphertext_len); + s->len = ciphertext_len + 16; + + return 0; +} + +static int aes_gcm_decrypt_rtcp(struct crypto_context *c, struct rtcp_packet *r, str *s, u_int64_t idx) { + unsigned char iv[12]; + unsigned char e_idx[4]; + int len, plaintext_len; + + memcpy(iv, c->session_salt, 12); + + *(u_int32_t*)(iv+2) ^= r->ssrc; + *(u_int32_t*)(iv+8) ^= htonl(idx & 0x007fffffffULL); + *(u_int32_t*)e_idx = htonl( (idx&0x007fffffffULL) | 0x80000000); + + if (c->params.crypto_suite->session_key_len == 16) { + EVP_DecryptInit_ex(c->session_key_ctx[0], EVP_aes_128_gcm(), NULL, c->session_key, iv); + } else { + EVP_DecryptInit_ex(c->session_key_ctx[0], EVP_aes_256_gcm(), NULL, c->session_key, iv); + } + + // nominally 8 + 4 bytes of AAD + EVP_DecryptUpdate(c->session_key_ctx[0], NULL, &len, (void *)r, s->s - (char *)r); + EVP_DecryptUpdate(c->session_key_ctx[0], NULL, &len, (void *)e_idx, 4); + + // decrypt partial buffer - the last 16 bytes are the tag + EVP_DecryptUpdate(c->session_key_ctx[0], s->s, &len, s->s, s->len-16); + plaintext_len = len; + EVP_CIPHER_CTX_ctrl(c->session_key_ctx[0], EVP_CTRL_GCM_SET_TAG, 16, s->s + s->len-16); + if (!EVP_DecryptFinal_ex(c->session_key_ctx[0], s->s+len, &len)) + return 1; + plaintext_len += len; + s->len = plaintext_len; + + return 0; +} + /* rfc 3711 sections 4.1.2 and 4.1.2.1 * encrypts in place */ static void aes_128_f8_encrypt(struct crypto_context *c, unsigned char *iv, str *s) { @@ -639,6 +831,18 @@ static int aes_cm_session_key_init(struct crypto_context *c) { return 0; } +static int aes_gcm_session_key_init(struct crypto_context *c) { + evp_session_key_cleanup(c); + +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + c->session_key_ctx[0] = EVP_CIPHER_CTX_new(); +#else + c->session_key_ctx[0] = g_slice_alloc(sizeof(EVP_CIPHER_CTX)); + EVP_CIPHER_CTX_init(c->session_key_ctx[0]); +#endif + return 0; +} + static int aes_f8_session_key_init(struct crypto_context *c) { unsigned char m[16]; int i; diff --git a/t/Makefile b/t/Makefile index 20644a0b3..1a39e11be 100644 --- a/t/Makefile +++ b/t/Makefile @@ -56,7 +56,7 @@ LDLIBS+= -lhiredis LDLIBS+= $(shell mysql_config --libs) endif -SRCS= bitstr-test.c aes-crypt.c const_str_hash-test.strhash.c +SRCS= bitstr-test.c aes-crypt.c aead-aes-crypt.c const_str_hash-test.strhash.c LIBSRCS= loglib.c auxlib.c str.c rtplib.c DAEMONSRCS= crypto.c ssrc.c aux.c rtp.c HASHSRCS= @@ -86,7 +86,7 @@ include .depend .PHONY: all-tests unit-tests daemon-tests -TESTS= bitstr-test aes-crypt const_str_hash-test.strhash +TESTS= bitstr-test aes-crypt aead-aes-crypt const_str_hash-test.strhash ifeq ($(with_transcoding),yes) TESTS+= transcode-test test-dtmf-detect payload-tracker-test ifeq ($(with_amr_tests),yes) @@ -139,6 +139,8 @@ test-dtmf-detect: test-dtmf-detect.o aes-crypt: aes-crypt.o $(COMMONOBJS) crypto.o +aead-aes-crypt: aead-aes-crypt.o $(COMMONOBJS) crypto.o + transcode-test: transcode-test.o $(COMMONOBJS) codeclib.o resample.o codec.o ssrc.o call.o ice.o aux.o \ kernel.o media_socket.o stun.o bencode.o socket.o poller.o dtls.o recording.o statistics.o \ rtcp.o redis.o iptables.o graphite.o call_interfaces.strhash.o sdp.strhash.o rtp.o crypto.o \ diff --git a/t/aead-aes-crypt.c b/t/aead-aes-crypt.c new file mode 100644 index 000000000..8b095f521 --- /dev/null +++ b/t/aead-aes-crypt.c @@ -0,0 +1,223 @@ +#include +#include + +#include "crypto.h" +#include "rtplib.h" +#include "log.h" +#include "main.h" + +#include + +// rfc 7714 section 16 +// contains 16/32 bytes of key, 12 bytes of salt [32:44] +uint8_t test_key[44] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x51, 0x75, 0x69, 0x64, 0x20, 0x70, 0x72, 0x6f, + 0x20, 0x71, 0x75, 0x6f +}; + +// rfc 7714 section 16 +uint8_t srtp_pt[66] = { + 0x80, 0x40, 0xf1, 0x7b, 0x80, 0x41, 0xf8, 0xd3, + 0x55, 0x01, 0xa0, 0xb2, 0x47, 0x61, 0x6c, 0x6c, + 0x69, 0x61, 0x20, 0x65, 0x73, 0x74, 0x20, 0x6f, + 0x6d, 0x6e, 0x69, 0x73, 0x20, 0x64, 0x69, 0x76, + 0x69, 0x73, 0x61, 0x20, 0x69, 0x6e, 0x20, 0x70, + 0x61, 0x72, 0x74, 0x65, 0x73, 0x20, 0x74, 0x72, + 0x65, 0x73, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +uint8_t answer128[66] = { + 0x80, 0x40, 0xf1, 0x7b, 0x80, 0x41, 0xf8, 0xd3, + 0x55, 0x01, 0xa0, 0xb2, 0xf2, 0x4d, 0xe3, 0xa3, + 0xfb, 0x34, 0xde, 0x6c, 0xac, 0xba, 0x86, 0x1c, + 0x9d, 0x7e, 0x4b, 0xca, 0xbe, 0x63, 0x3b, 0xd5, + 0x0d, 0x29, 0x4e, 0x6f, 0x42, 0xa5, 0xf4, 0x7a, + 0x51, 0xc7, 0xd1, 0x9b, 0x36, 0xde, 0x3a, 0xdf, + 0x88, 0x33, 0x89, 0x9d, 0x7f, 0x27, 0xbe, 0xb1, + 0x6a, 0x91, 0x52, 0xcf, 0x76, 0x5e, 0xe4, 0x39, + 0x0c, 0xce +}; + +uint8_t answer256[66] = { + 0x80, 0x40, 0xf1, 0x7b, 0x80, 0x41, 0xf8, 0xd3, + 0x55, 0x01, 0xa0, 0xb2, 0x32, 0xb1, 0xde, 0x78, + 0xa8, 0x22, 0xfe, 0x12, 0xef, 0x9f, 0x78, 0xfa, + 0x33, 0x2e, 0x33, 0xaa, 0xb1, 0x80, 0x12, 0x38, + 0x9a, 0x58, 0xe2, 0xf3, 0xb5, 0x0b, 0x2a, 0x02, + 0x76, 0xff, 0xae, 0x0f, 0x1b, 0xa6, 0x37, 0x99, + 0xb8, 0x7b, 0x7a, 0xa3, 0xdb, 0x36, 0xdf, 0xff, + 0xd6, 0xb0, 0xf9, 0xbb, 0x78, 0x78, 0xd7, 0xa7, + 0x6c, 0x13 +}; +// rfc 7714 section 17.1 - this is NOT the same +// as the putative test vector in section 17 +// typo perhaps? +uint8_t srtcp_pt[68] = { + 0x81, 0xc8, 0x00, 0x0d, 0x4d, 0x61, 0x72, 0x73, + 0x4e, 0x54, 0x50, 0x31, 0x4e, 0x54, 0x50, 0x32, + 0x52, 0x54, 0x50, 0x20, 0x00, 0x00, 0x04, 0x2a, + 0x00, 0x00, 0xe9, 0x30, 0x4c, 0x75, 0x6e, 0x61, + 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, + 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, + 0xde, 0xad, 0xbe, 0xef, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +uint8_t answer128_srtcp[72] = { + 0x81, 0xc8, 0x00, 0x0d, 0x4d, 0x61, 0x72, 0x73, + 0x63, 0xe9, 0x48, 0x85, 0xdc, 0xda, 0xb6, 0x7c, + 0xa7, 0x27, 0xd7, 0x66, 0x2f, 0x6b, 0x7e, 0x99, + 0x7f, 0xf5, 0xc0, 0xf7, 0x6c, 0x06, 0xf3, 0x2d, + 0xc6, 0x76, 0xa5, 0xf1, 0x73, 0x0d, 0x6f, 0xda, + 0x4c, 0xe0, 0x9b, 0x46, 0x86, 0x30, 0x3d, 0xed, + 0x0b, 0xb9, 0x27, 0x5b, 0xc8, 0x4a, 0xa4, 0x58, + 0x96, 0xcf, 0x4d, 0x2f, 0xc5, 0xab, 0xf8, 0x72, + 0x45, 0xd9, 0xea, 0xde, 0x80, 0x00, 0x05, 0xd4 +}; + +uint8_t answer256_srtcp[72] = { + 0x81, 0xc8, 0x00, 0x0d, 0x4d, 0x61, 0x72, 0x73, + 0xd5, 0x0a, 0xe4, 0xd1, 0xf5, 0xce, 0x5d, 0x30, + 0x4b, 0xa2, 0x97, 0xe4, 0x7d, 0x47, 0x0c, 0x28, + 0x2c, 0x3e, 0xce, 0x5d, 0xbf, 0xfe, 0x0a, 0x50, + 0xa2, 0xea, 0xa5, 0xc1, 0x11, 0x05, 0x55, 0xbe, + 0x84, 0x15, 0xf6, 0x58, 0xc6, 0x1d, 0xe0, 0x47, + 0x6f, 0x1b, 0x6f, 0xad, 0x1d, 0x1e, 0xb3, 0x0c, + 0x44, 0x46, 0x83, 0x9f, 0x57, 0xff, 0x6f, 0x6c, + 0xb2, 0x6a, 0xc3, 0xbe, 0x80, 0x00, 0x05, 0xd4 +}; + +struct rtpengine_config rtpe_config = { +}; + +int main(int argc, char *argv) +{ + + str suite, payload; + const struct crypto_suite *c; + struct crypto_context ctx; + int rc; + + uint8_t working[100]; + + crypto_init_main(); + + str_init(&suite, "AEAD_AES_128_GCM"); + c = crypto_find_suite(&suite); + assert(c); + + memset(&ctx, 0, sizeof(ctx)); + ctx.params.crypto_suite = c; + ctx.session_key_ctx[0] = EVP_CIPHER_CTX_new(); + + memcpy(ctx.session_key, test_key, 16); + memcpy(ctx.session_salt, (uint8_t *)test_key + 32, 12); + + memcpy(working, srtp_pt, 50); + payload.len = 38; + payload.s = working + 12; + + rc = crypto_encrypt_rtp(&ctx, (struct rtp_header *)working, + &payload, + 0x00000000f17bULL); + assert(rc == 0 && payload.len == 54); + assert(memcmp(working, answer128, 66) == 0); + printf("RTP/AEAD-AES-128-GCM Encrypt - PASS\n"); + + payload.len = 54; + payload.s = working + 12; + + rc = crypto_decrypt_rtp(&ctx, (struct rtp_header *)working, + &payload, + 0x00000000f17bULL); + + assert(rc == 0 && payload.len == 38); + assert(memcmp(working, srtp_pt, 50) == 0); + printf("RTP/AEAD-AES-128-GCM Decrypt - PASS\n"); + + // RTCP + memcpy(working, srtcp_pt, 52); + payload.len = 44; + payload.s = working + 8; + + rc = crypto_encrypt_rtcp(&ctx, (struct rtcp_packet *)working, + &payload, + 0x0000000005d4ULL); + assert(rc == 0 && payload.len == 60); + assert(memcmp(working, answer128_srtcp, 68) == 0); + printf("RTCP/AEAD-AES-128-GCM Encrypt - PASS\n"); + + payload.len = 60; + payload.s = working + 8; + + rc = crypto_decrypt_rtcp(&ctx, (struct rtcp_packet *)working, + &payload, + 0x000000005d4ULL); + + assert(rc == 0 && payload.len == 44); + assert(memcmp(working, srtcp_pt, 52) == 0); + printf("RTCP/AEAD-AES-128-GCM Decrypt - PASS\n"); + + // AES 256 + str_init(&suite, "AEAD_AES_256_GCM"); + c = crypto_find_suite(&suite); + assert(c); + + memset(&ctx, 0, sizeof(ctx)); + ctx.params.crypto_suite = c; + ctx.session_key_ctx[0] = EVP_CIPHER_CTX_new(); + + memcpy(ctx.session_key, test_key, 32); + memcpy(ctx.session_salt, (uint8_t *)test_key + 32, 12); + + memcpy(working, srtp_pt, 50); + payload.len = 38; + payload.s = working + 12; + + rc = crypto_encrypt_rtp(&ctx, (struct rtp_header *)working, + &payload, + 0x00000000f17bULL); + assert(rc == 0 && payload.len == 54); + assert(memcmp(working, answer256, 66) == 0); + printf("RTP/AEAD-AES-256-GCM Encrypt - PASS\n"); + + payload.len = 54; + payload.s = working + 12; + + rc = crypto_decrypt_rtp(&ctx, (struct rtp_header *)working, + &payload, + 0x00000000f17bULL); + assert(rc == 0 && payload.len == 38); + assert(memcmp(working, srtp_pt, 50) == 0); + printf("RTP/AEAD-AES-256-GCM Decrypt - PASS\n"); + + // RTCP + memcpy(working, srtcp_pt, 52); + payload.len = 44; + payload.s = working + 8; + + rc = crypto_encrypt_rtcp(&ctx, (struct rtcp_packet *)working, + &payload, + 0x0000000005d4ULL); + assert(rc == 0 && payload.len == 60); + assert(memcmp(working, answer256_srtcp, 68) == 0); + printf("RTCP/AEAD-AES-256-GCM Encrypt - PASS\n"); + + payload.len = 60; + payload.s = working + 8; + + rc = crypto_decrypt_rtcp(&ctx, (struct rtcp_packet *)working, + &payload, + 0x000000005d4ULL); + + assert(rc == 0 && payload.len == 44); + assert(memcmp(working, srtcp_pt, 52) == 0); + printf("RTCP/AEAD-AES-256-GCM Decrypt - PASS\n"); +}