| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- #include <string.h>
- #include "audio_crypto.h"
- #include "mbedtls/aes.h"
- #include "sodium.h"
- int audio_crypto_decrypt_rtp(const audio_encrypt_t *encrypt,
- const uint8_t *input, size_t input_len,
- uint8_t *output, size_t output_capacity,
- const uint8_t *full_packet,
- size_t full_packet_len) {
- if (!encrypt || !input || !output) {
- return -1;
- }
- if (encrypt->type == AUDIO_ENCRYPT_NONE) {
- if (input_len > output_capacity) {
- return -1;
- }
- memcpy(output, input, input_len);
- return (int)input_len;
- }
- if (encrypt->type == AUDIO_ENCRYPT_AES_CBC) {
- if (input_len > output_capacity) {
- return -1;
- }
- uint8_t iv[16];
- memcpy(iv, encrypt->iv, sizeof(iv));
- size_t num_blocks = input_len / 16;
- size_t remainder = input_len % 16;
- size_t encrypted_len = num_blocks * 16;
- if (encrypted_len > 0) {
- mbedtls_aes_context aes;
- mbedtls_aes_init(&aes);
- int ret = mbedtls_aes_setkey_dec(&aes, encrypt->key, 128);
- if (ret != 0) {
- mbedtls_aes_free(&aes);
- return -1;
- }
- ret = mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, encrypted_len, iv,
- input, output);
- mbedtls_aes_free(&aes);
- if (ret != 0) {
- return -1;
- }
- }
- if (remainder > 0) {
- memcpy(output + encrypted_len, input + encrypted_len, remainder);
- }
- return (int)input_len;
- }
- if (encrypt->type == AUDIO_ENCRYPT_CHACHA20_POLY1305) {
- // AirPlay 2 RTP: nonce = 4 zero bytes + last 8 bytes of packet,
- // AAD = RTP timestamp + SSRC (bytes 4-11 of the full packet).
- if (!full_packet || full_packet_len < 12) {
- return -1;
- }
- if (input_len < crypto_aead_chacha20poly1305_ietf_ABYTES + 8) {
- return -1;
- }
- uint8_t nonce[12] = {0};
- memcpy(nonce + 4, full_packet + full_packet_len - 8, 8);
- const uint8_t *aad = full_packet + 4;
- size_t aad_len = 8;
- size_t ciphertext_len = input_len - 8;
- unsigned long long decrypted_len = 0;
- int ret = crypto_aead_chacha20poly1305_ietf_decrypt(
- output, &decrypted_len, NULL, input, ciphertext_len, aad, aad_len,
- nonce, encrypt->key);
- if (ret != 0) {
- return -1;
- }
- return (int)decrypted_len;
- }
- return -1;
- }
- int audio_crypto_decrypt_buffered(const audio_encrypt_t *encrypt,
- const uint8_t *packet, size_t packet_len,
- uint8_t *output, size_t output_capacity) {
- if (!packet || !output) {
- return -1;
- }
- if (!encrypt || encrypt->type != AUDIO_ENCRYPT_CHACHA20_POLY1305) {
- if (packet_len <= 12) {
- return -1;
- }
- size_t payload_len = packet_len - 12;
- if (payload_len > output_capacity) {
- return -1;
- }
- memcpy(output, packet + 12, payload_len);
- return (int)payload_len;
- }
- if (packet_len < 36) {
- return -1;
- }
- // Buffered audio: AAD is bytes 4-11 (timestamp + SSRC), nonce in last 8
- // bytes.
- uint8_t nonce[12] = {0};
- memcpy(nonce + 4, packet + packet_len - 8, 8);
- const uint8_t *aad = packet + 4;
- size_t aad_len = 8;
- const uint8_t *ciphertext = packet + 12;
- size_t ciphertext_len = packet_len - 12 - 8;
- if (ciphertext_len >
- output_capacity + crypto_aead_chacha20poly1305_ietf_ABYTES) {
- return -1;
- }
- unsigned long long decrypted_len = 0;
- int ret = crypto_aead_chacha20poly1305_ietf_decrypt(
- output, &decrypted_len, NULL, ciphertext, ciphertext_len, aad, aad_len,
- nonce, encrypt->key);
- if (ret != 0) {
- return -1;
- }
- return (int)decrypted_len;
- }
|