blob: 8b4d5c3d86a0e1510645f50b53d032ff8eacd42e [file] [log] [blame]
James Kuszmaul82f6c042021-01-17 11:30:16 -08001/**
2 * @file srtp/misc.c SRTP functions
3 *
4 * Copyright (C) 2010 Creytiv.com
5 */
6#include <string.h>
7#include <re_types.h>
8#include <re_mem.h>
9#include <re_mbuf.h>
10#include <re_list.h>
11#include <re_aes.h>
12#include <re_sa.h>
13#include <re_srtp.h>
14#include "srtp.h"
15
16
17/*
18 * Appendix A: Pseudocode for Index Determination
19 *
20 * In the following, signed arithmetic is assumed.
21 */
22uint64_t srtp_get_index(uint32_t roc, uint16_t s_l, uint16_t seq)
23{
24 int v;
25
26 if (s_l < 32768) {
27
28 if ((int)seq - (int)s_l > 32768)
29 v = (roc-1) & 0xffffffffu;
30 else
31 v = roc;
32 }
33 else {
34 if ((int)s_l - 32768 > seq)
35 v = (roc+1) & 0xffffffffu;
36 else
37 v = roc;
38 }
39
40 return seq + v*65536;
41}
42
43
44int srtp_derive(uint8_t *out, size_t out_len, uint8_t label,
45 const uint8_t *master_key, size_t key_bytes,
46 const uint8_t *master_salt, size_t salt_bytes)
47{
48 uint8_t x[AES_BLOCK_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
49 static const uint8_t null[AES_BLOCK_SIZE * 2];
50 struct aes *aes;
51 int err;
52
53 if (!out || !master_key || !master_salt)
54 return EINVAL;
55
56 if (out_len > sizeof(null) || salt_bytes > sizeof(x))
57 return EINVAL;
58
59 memcpy(x, master_salt, salt_bytes);
60 x[7] ^= label;
61
62 /* NOTE: Counter Mode is used for both CTR and GCM */
63 err = aes_alloc(&aes, AES_MODE_CTR, master_key, key_bytes*8, x);
64 if (err)
65 return err;
66
67 err = aes_encr(aes, out, null, out_len);
68
69 mem_deref(aes);
70
71 return err;
72
73}
74
75
76void srtp_iv_calc(union vect128 *iv, const union vect128 *k_s,
77 uint32_t ssrc, uint64_t ix)
78{
79 if (!iv || !k_s)
80 return;
81
82 iv->u32[0] = k_s->u32[0];
83 iv->u32[1] = k_s->u32[1] ^ htonl(ssrc);
84 iv->u32[2] = k_s->u32[2] ^ htonl((uint32_t)(ix>>16));
85 iv->u16[6] = k_s->u16[6] ^ htons((uint16_t)ix);
86 iv->u16[7] = 0;
87}
88
89
90/*
91 * NOTE: The IV for AES-GCM is 12 bytes
92 */
93void srtp_iv_calc_gcm(union vect128 *iv, const union vect128 *k_s,
94 uint32_t ssrc, uint64_t ix)
95{
96 if (!iv || !k_s)
97 return;
98
99 iv->u16[0] = k_s->u16[0];
100 iv->u16[1] = k_s->u16[1] ^ htons(ssrc >> 16);
101 iv->u16[2] = k_s->u16[2] ^ htons(ssrc & 0xffff);
102 iv->u16[3] = k_s->u16[3] ^ htons((ix >> 32) & 0xffff);
103 iv->u16[4] = k_s->u16[4] ^ htons((ix >> 16) & 0xffff);
104 iv->u16[5] = k_s->u16[5] ^ htons(ix & 0xffff);
105}
106
107
108const char *srtp_suite_name(enum srtp_suite suite)
109{
110 switch (suite) {
111
112 case SRTP_AES_CM_128_HMAC_SHA1_32: return "AES_CM_128_HMAC_SHA1_32";
113 case SRTP_AES_CM_128_HMAC_SHA1_80: return "AES_CM_128_HMAC_SHA1_80";
114 case SRTP_AES_256_CM_HMAC_SHA1_32: return "AES_256_CM_HMAC_SHA1_32";
115 case SRTP_AES_256_CM_HMAC_SHA1_80: return "AES_256_CM_HMAC_SHA1_80";
116 case SRTP_AES_128_GCM: return "AEAD_AES_128_GCM";
117 case SRTP_AES_256_GCM: return "AEAD_AES_256_GCM";
118 default: return "?";
119 }
120}