1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * SRTP encryption/decryption 3cabdff1aSopenharmony_ci * Copyright (c) 2012 Martin Storsjo 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * This file is part of FFmpeg. 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 11cabdff1aSopenharmony_ci * 12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15cabdff1aSopenharmony_ci * Lesser General Public License for more details. 16cabdff1aSopenharmony_ci * 17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20cabdff1aSopenharmony_ci */ 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci#include "libavutil/base64.h" 23cabdff1aSopenharmony_ci#include "libavutil/aes.h" 24cabdff1aSopenharmony_ci#include "libavutil/hmac.h" 25cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h" 26cabdff1aSopenharmony_ci#include "libavutil/log.h" 27cabdff1aSopenharmony_ci#include "rtp.h" 28cabdff1aSopenharmony_ci#include "rtpdec.h" 29cabdff1aSopenharmony_ci#include "srtp.h" 30cabdff1aSopenharmony_ci 31cabdff1aSopenharmony_civoid ff_srtp_free(struct SRTPContext *s) 32cabdff1aSopenharmony_ci{ 33cabdff1aSopenharmony_ci if (!s) 34cabdff1aSopenharmony_ci return; 35cabdff1aSopenharmony_ci av_freep(&s->aes); 36cabdff1aSopenharmony_ci if (s->hmac) 37cabdff1aSopenharmony_ci av_hmac_free(s->hmac); 38cabdff1aSopenharmony_ci s->hmac = NULL; 39cabdff1aSopenharmony_ci} 40cabdff1aSopenharmony_ci 41cabdff1aSopenharmony_cistatic void encrypt_counter(struct AVAES *aes, uint8_t *iv, uint8_t *outbuf, 42cabdff1aSopenharmony_ci int outlen) 43cabdff1aSopenharmony_ci{ 44cabdff1aSopenharmony_ci int i, j, outpos; 45cabdff1aSopenharmony_ci for (i = 0, outpos = 0; outpos < outlen; i++) { 46cabdff1aSopenharmony_ci uint8_t keystream[16]; 47cabdff1aSopenharmony_ci AV_WB16(&iv[14], i); 48cabdff1aSopenharmony_ci av_aes_crypt(aes, keystream, iv, 1, NULL, 0); 49cabdff1aSopenharmony_ci for (j = 0; j < 16 && outpos < outlen; j++, outpos++) 50cabdff1aSopenharmony_ci outbuf[outpos] ^= keystream[j]; 51cabdff1aSopenharmony_ci } 52cabdff1aSopenharmony_ci} 53cabdff1aSopenharmony_ci 54cabdff1aSopenharmony_cistatic void derive_key(struct AVAES *aes, const uint8_t *salt, int label, 55cabdff1aSopenharmony_ci uint8_t *out, int outlen) 56cabdff1aSopenharmony_ci{ 57cabdff1aSopenharmony_ci uint8_t input[16] = { 0 }; 58cabdff1aSopenharmony_ci memcpy(input, salt, 14); 59cabdff1aSopenharmony_ci // Key derivation rate assumed to be zero 60cabdff1aSopenharmony_ci input[14 - 7] ^= label; 61cabdff1aSopenharmony_ci memset(out, 0, outlen); 62cabdff1aSopenharmony_ci encrypt_counter(aes, input, out, outlen); 63cabdff1aSopenharmony_ci} 64cabdff1aSopenharmony_ci 65cabdff1aSopenharmony_ciint ff_srtp_set_crypto(struct SRTPContext *s, const char *suite, 66cabdff1aSopenharmony_ci const char *params) 67cabdff1aSopenharmony_ci{ 68cabdff1aSopenharmony_ci uint8_t buf[30]; 69cabdff1aSopenharmony_ci 70cabdff1aSopenharmony_ci ff_srtp_free(s); 71cabdff1aSopenharmony_ci 72cabdff1aSopenharmony_ci // RFC 4568 73cabdff1aSopenharmony_ci if (!strcmp(suite, "AES_CM_128_HMAC_SHA1_80") || 74cabdff1aSopenharmony_ci !strcmp(suite, "SRTP_AES128_CM_HMAC_SHA1_80")) { 75cabdff1aSopenharmony_ci s->rtp_hmac_size = s->rtcp_hmac_size = 10; 76cabdff1aSopenharmony_ci } else if (!strcmp(suite, "AES_CM_128_HMAC_SHA1_32")) { 77cabdff1aSopenharmony_ci s->rtp_hmac_size = s->rtcp_hmac_size = 4; 78cabdff1aSopenharmony_ci } else if (!strcmp(suite, "SRTP_AES128_CM_HMAC_SHA1_32")) { 79cabdff1aSopenharmony_ci // RFC 5764 section 4.1.2 80cabdff1aSopenharmony_ci s->rtp_hmac_size = 4; 81cabdff1aSopenharmony_ci s->rtcp_hmac_size = 10; 82cabdff1aSopenharmony_ci } else { 83cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_WARNING, "SRTP Crypto suite %s not supported\n", 84cabdff1aSopenharmony_ci suite); 85cabdff1aSopenharmony_ci return AVERROR(EINVAL); 86cabdff1aSopenharmony_ci } 87cabdff1aSopenharmony_ci if (av_base64_decode(buf, params, sizeof(buf)) != sizeof(buf)) { 88cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_WARNING, "Incorrect amount of SRTP params\n"); 89cabdff1aSopenharmony_ci return AVERROR(EINVAL); 90cabdff1aSopenharmony_ci } 91cabdff1aSopenharmony_ci // MKI and lifetime not handled yet 92cabdff1aSopenharmony_ci s->aes = av_aes_alloc(); 93cabdff1aSopenharmony_ci s->hmac = av_hmac_alloc(AV_HMAC_SHA1); 94cabdff1aSopenharmony_ci if (!s->aes || !s->hmac) 95cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 96cabdff1aSopenharmony_ci memcpy(s->master_key, buf, 16); 97cabdff1aSopenharmony_ci memcpy(s->master_salt, buf + 16, 14); 98cabdff1aSopenharmony_ci 99cabdff1aSopenharmony_ci // RFC 3711 100cabdff1aSopenharmony_ci av_aes_init(s->aes, s->master_key, 128, 0); 101cabdff1aSopenharmony_ci 102cabdff1aSopenharmony_ci derive_key(s->aes, s->master_salt, 0x00, s->rtp_key, sizeof(s->rtp_key)); 103cabdff1aSopenharmony_ci derive_key(s->aes, s->master_salt, 0x02, s->rtp_salt, sizeof(s->rtp_salt)); 104cabdff1aSopenharmony_ci derive_key(s->aes, s->master_salt, 0x01, s->rtp_auth, sizeof(s->rtp_auth)); 105cabdff1aSopenharmony_ci 106cabdff1aSopenharmony_ci derive_key(s->aes, s->master_salt, 0x03, s->rtcp_key, sizeof(s->rtcp_key)); 107cabdff1aSopenharmony_ci derive_key(s->aes, s->master_salt, 0x05, s->rtcp_salt, sizeof(s->rtcp_salt)); 108cabdff1aSopenharmony_ci derive_key(s->aes, s->master_salt, 0x04, s->rtcp_auth, sizeof(s->rtcp_auth)); 109cabdff1aSopenharmony_ci return 0; 110cabdff1aSopenharmony_ci} 111cabdff1aSopenharmony_ci 112cabdff1aSopenharmony_cistatic void create_iv(uint8_t *iv, const uint8_t *salt, uint64_t index, 113cabdff1aSopenharmony_ci uint32_t ssrc) 114cabdff1aSopenharmony_ci{ 115cabdff1aSopenharmony_ci uint8_t indexbuf[8]; 116cabdff1aSopenharmony_ci int i; 117cabdff1aSopenharmony_ci memset(iv, 0, 16); 118cabdff1aSopenharmony_ci AV_WB32(&iv[4], ssrc); 119cabdff1aSopenharmony_ci AV_WB64(indexbuf, index); 120cabdff1aSopenharmony_ci for (i = 0; i < 8; i++) // index << 16 121cabdff1aSopenharmony_ci iv[6 + i] ^= indexbuf[i]; 122cabdff1aSopenharmony_ci for (i = 0; i < 14; i++) 123cabdff1aSopenharmony_ci iv[i] ^= salt[i]; 124cabdff1aSopenharmony_ci} 125cabdff1aSopenharmony_ci 126cabdff1aSopenharmony_ciint ff_srtp_decrypt(struct SRTPContext *s, uint8_t *buf, int *lenptr) 127cabdff1aSopenharmony_ci{ 128cabdff1aSopenharmony_ci uint8_t iv[16] = { 0 }, hmac[20]; 129cabdff1aSopenharmony_ci int len = *lenptr; 130cabdff1aSopenharmony_ci int av_uninit(seq_largest); 131cabdff1aSopenharmony_ci uint32_t ssrc, av_uninit(roc); 132cabdff1aSopenharmony_ci uint64_t index; 133cabdff1aSopenharmony_ci int rtcp, hmac_size; 134cabdff1aSopenharmony_ci 135cabdff1aSopenharmony_ci // TODO: Missing replay protection 136cabdff1aSopenharmony_ci 137cabdff1aSopenharmony_ci if (len < 2) 138cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 139cabdff1aSopenharmony_ci 140cabdff1aSopenharmony_ci rtcp = RTP_PT_IS_RTCP(buf[1]); 141cabdff1aSopenharmony_ci hmac_size = rtcp ? s->rtcp_hmac_size : s->rtp_hmac_size; 142cabdff1aSopenharmony_ci 143cabdff1aSopenharmony_ci if (len < hmac_size) 144cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 145cabdff1aSopenharmony_ci 146cabdff1aSopenharmony_ci // Authentication HMAC 147cabdff1aSopenharmony_ci av_hmac_init(s->hmac, rtcp ? s->rtcp_auth : s->rtp_auth, sizeof(s->rtp_auth)); 148cabdff1aSopenharmony_ci // If MKI is used, this should exclude the MKI as well 149cabdff1aSopenharmony_ci av_hmac_update(s->hmac, buf, len - hmac_size); 150cabdff1aSopenharmony_ci 151cabdff1aSopenharmony_ci if (!rtcp) { 152cabdff1aSopenharmony_ci int seq = AV_RB16(buf + 2); 153cabdff1aSopenharmony_ci uint32_t v; 154cabdff1aSopenharmony_ci uint8_t rocbuf[4]; 155cabdff1aSopenharmony_ci 156cabdff1aSopenharmony_ci // RFC 3711 section 3.3.1, appendix A 157cabdff1aSopenharmony_ci seq_largest = s->seq_initialized ? s->seq_largest : seq; 158cabdff1aSopenharmony_ci v = roc = s->roc; 159cabdff1aSopenharmony_ci if (seq_largest < 32768) { 160cabdff1aSopenharmony_ci if (seq - seq_largest > 32768) 161cabdff1aSopenharmony_ci v = roc - 1; 162cabdff1aSopenharmony_ci } else { 163cabdff1aSopenharmony_ci if (seq_largest - 32768 > seq) 164cabdff1aSopenharmony_ci v = roc + 1; 165cabdff1aSopenharmony_ci } 166cabdff1aSopenharmony_ci if (v == roc) { 167cabdff1aSopenharmony_ci seq_largest = FFMAX(seq_largest, seq); 168cabdff1aSopenharmony_ci } else if (v == roc + 1) { 169cabdff1aSopenharmony_ci seq_largest = seq; 170cabdff1aSopenharmony_ci roc = v; 171cabdff1aSopenharmony_ci } 172cabdff1aSopenharmony_ci index = seq + (((uint64_t)v) << 16); 173cabdff1aSopenharmony_ci 174cabdff1aSopenharmony_ci AV_WB32(rocbuf, roc); 175cabdff1aSopenharmony_ci av_hmac_update(s->hmac, rocbuf, 4); 176cabdff1aSopenharmony_ci } 177cabdff1aSopenharmony_ci 178cabdff1aSopenharmony_ci av_hmac_final(s->hmac, hmac, sizeof(hmac)); 179cabdff1aSopenharmony_ci if (memcmp(hmac, buf + len - hmac_size, hmac_size)) { 180cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_WARNING, "HMAC mismatch\n"); 181cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 182cabdff1aSopenharmony_ci } 183cabdff1aSopenharmony_ci 184cabdff1aSopenharmony_ci len -= hmac_size; 185cabdff1aSopenharmony_ci *lenptr = len; 186cabdff1aSopenharmony_ci 187cabdff1aSopenharmony_ci if (len < 12) 188cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 189cabdff1aSopenharmony_ci 190cabdff1aSopenharmony_ci if (rtcp) { 191cabdff1aSopenharmony_ci uint32_t srtcp_index = AV_RB32(buf + len - 4); 192cabdff1aSopenharmony_ci len -= 4; 193cabdff1aSopenharmony_ci *lenptr = len; 194cabdff1aSopenharmony_ci 195cabdff1aSopenharmony_ci ssrc = AV_RB32(buf + 4); 196cabdff1aSopenharmony_ci index = srtcp_index & 0x7fffffff; 197cabdff1aSopenharmony_ci 198cabdff1aSopenharmony_ci buf += 8; 199cabdff1aSopenharmony_ci len -= 8; 200cabdff1aSopenharmony_ci if (!(srtcp_index & 0x80000000)) 201cabdff1aSopenharmony_ci return 0; 202cabdff1aSopenharmony_ci } else { 203cabdff1aSopenharmony_ci int ext, csrc; 204cabdff1aSopenharmony_ci s->seq_initialized = 1; 205cabdff1aSopenharmony_ci s->seq_largest = seq_largest; 206cabdff1aSopenharmony_ci s->roc = roc; 207cabdff1aSopenharmony_ci 208cabdff1aSopenharmony_ci csrc = buf[0] & 0x0f; 209cabdff1aSopenharmony_ci ext = buf[0] & 0x10; 210cabdff1aSopenharmony_ci ssrc = AV_RB32(buf + 8); 211cabdff1aSopenharmony_ci 212cabdff1aSopenharmony_ci buf += 12; 213cabdff1aSopenharmony_ci len -= 12; 214cabdff1aSopenharmony_ci 215cabdff1aSopenharmony_ci buf += 4 * csrc; 216cabdff1aSopenharmony_ci len -= 4 * csrc; 217cabdff1aSopenharmony_ci if (len < 0) 218cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 219cabdff1aSopenharmony_ci 220cabdff1aSopenharmony_ci if (ext) { 221cabdff1aSopenharmony_ci if (len < 4) 222cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 223cabdff1aSopenharmony_ci ext = (AV_RB16(buf + 2) + 1) * 4; 224cabdff1aSopenharmony_ci if (len < ext) 225cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 226cabdff1aSopenharmony_ci len -= ext; 227cabdff1aSopenharmony_ci buf += ext; 228cabdff1aSopenharmony_ci } 229cabdff1aSopenharmony_ci } 230cabdff1aSopenharmony_ci 231cabdff1aSopenharmony_ci create_iv(iv, rtcp ? s->rtcp_salt : s->rtp_salt, index, ssrc); 232cabdff1aSopenharmony_ci av_aes_init(s->aes, rtcp ? s->rtcp_key : s->rtp_key, 128, 0); 233cabdff1aSopenharmony_ci encrypt_counter(s->aes, iv, buf, len); 234cabdff1aSopenharmony_ci 235cabdff1aSopenharmony_ci return 0; 236cabdff1aSopenharmony_ci} 237cabdff1aSopenharmony_ci 238cabdff1aSopenharmony_ciint ff_srtp_encrypt(struct SRTPContext *s, const uint8_t *in, int len, 239cabdff1aSopenharmony_ci uint8_t *out, int outlen) 240cabdff1aSopenharmony_ci{ 241cabdff1aSopenharmony_ci uint8_t iv[16] = { 0 }, hmac[20]; 242cabdff1aSopenharmony_ci uint64_t index; 243cabdff1aSopenharmony_ci uint32_t ssrc; 244cabdff1aSopenharmony_ci int rtcp, hmac_size, padding; 245cabdff1aSopenharmony_ci uint8_t *buf; 246cabdff1aSopenharmony_ci 247cabdff1aSopenharmony_ci if (len < 8) 248cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 249cabdff1aSopenharmony_ci 250cabdff1aSopenharmony_ci rtcp = RTP_PT_IS_RTCP(in[1]); 251cabdff1aSopenharmony_ci hmac_size = rtcp ? s->rtcp_hmac_size : s->rtp_hmac_size; 252cabdff1aSopenharmony_ci padding = hmac_size; 253cabdff1aSopenharmony_ci if (rtcp) 254cabdff1aSopenharmony_ci padding += 4; // For the RTCP index 255cabdff1aSopenharmony_ci 256cabdff1aSopenharmony_ci if (len + padding > outlen) 257cabdff1aSopenharmony_ci return 0; 258cabdff1aSopenharmony_ci 259cabdff1aSopenharmony_ci memcpy(out, in, len); 260cabdff1aSopenharmony_ci buf = out; 261cabdff1aSopenharmony_ci 262cabdff1aSopenharmony_ci if (rtcp) { 263cabdff1aSopenharmony_ci ssrc = AV_RB32(buf + 4); 264cabdff1aSopenharmony_ci index = s->rtcp_index++; 265cabdff1aSopenharmony_ci 266cabdff1aSopenharmony_ci buf += 8; 267cabdff1aSopenharmony_ci len -= 8; 268cabdff1aSopenharmony_ci } else { 269cabdff1aSopenharmony_ci int ext, csrc; 270cabdff1aSopenharmony_ci int seq = AV_RB16(buf + 2); 271cabdff1aSopenharmony_ci 272cabdff1aSopenharmony_ci if (len < 12) 273cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 274cabdff1aSopenharmony_ci 275cabdff1aSopenharmony_ci ssrc = AV_RB32(buf + 8); 276cabdff1aSopenharmony_ci 277cabdff1aSopenharmony_ci if (seq < s->seq_largest) 278cabdff1aSopenharmony_ci s->roc++; 279cabdff1aSopenharmony_ci s->seq_largest = seq; 280cabdff1aSopenharmony_ci index = seq + (((uint64_t)s->roc) << 16); 281cabdff1aSopenharmony_ci 282cabdff1aSopenharmony_ci csrc = buf[0] & 0x0f; 283cabdff1aSopenharmony_ci ext = buf[0] & 0x10; 284cabdff1aSopenharmony_ci 285cabdff1aSopenharmony_ci buf += 12; 286cabdff1aSopenharmony_ci len -= 12; 287cabdff1aSopenharmony_ci 288cabdff1aSopenharmony_ci buf += 4 * csrc; 289cabdff1aSopenharmony_ci len -= 4 * csrc; 290cabdff1aSopenharmony_ci if (len < 0) 291cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 292cabdff1aSopenharmony_ci 293cabdff1aSopenharmony_ci if (ext) { 294cabdff1aSopenharmony_ci if (len < 4) 295cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 296cabdff1aSopenharmony_ci ext = (AV_RB16(buf + 2) + 1) * 4; 297cabdff1aSopenharmony_ci if (len < ext) 298cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 299cabdff1aSopenharmony_ci len -= ext; 300cabdff1aSopenharmony_ci buf += ext; 301cabdff1aSopenharmony_ci } 302cabdff1aSopenharmony_ci } 303cabdff1aSopenharmony_ci 304cabdff1aSopenharmony_ci create_iv(iv, rtcp ? s->rtcp_salt : s->rtp_salt, index, ssrc); 305cabdff1aSopenharmony_ci av_aes_init(s->aes, rtcp ? s->rtcp_key : s->rtp_key, 128, 0); 306cabdff1aSopenharmony_ci encrypt_counter(s->aes, iv, buf, len); 307cabdff1aSopenharmony_ci 308cabdff1aSopenharmony_ci if (rtcp) { 309cabdff1aSopenharmony_ci AV_WB32(buf + len, 0x80000000 | index); 310cabdff1aSopenharmony_ci len += 4; 311cabdff1aSopenharmony_ci } 312cabdff1aSopenharmony_ci 313cabdff1aSopenharmony_ci av_hmac_init(s->hmac, rtcp ? s->rtcp_auth : s->rtp_auth, sizeof(s->rtp_auth)); 314cabdff1aSopenharmony_ci av_hmac_update(s->hmac, out, buf + len - out); 315cabdff1aSopenharmony_ci if (!rtcp) { 316cabdff1aSopenharmony_ci uint8_t rocbuf[4]; 317cabdff1aSopenharmony_ci AV_WB32(rocbuf, s->roc); 318cabdff1aSopenharmony_ci av_hmac_update(s->hmac, rocbuf, 4); 319cabdff1aSopenharmony_ci } 320cabdff1aSopenharmony_ci av_hmac_final(s->hmac, hmac, sizeof(hmac)); 321cabdff1aSopenharmony_ci 322cabdff1aSopenharmony_ci memcpy(buf + len, hmac, hmac_size); 323cabdff1aSopenharmony_ci len += hmac_size; 324cabdff1aSopenharmony_ci return buf + len - out; 325cabdff1aSopenharmony_ci} 326