1 /**
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  */
srtp_get_index(uint32_t roc,uint16_t s_l,uint16_t seq)22 uint64_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 
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)44 int 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 
srtp_iv_calc(union vect128 * iv,const union vect128 * k_s,uint32_t ssrc,uint64_t ix)76 void 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  */
srtp_iv_calc_gcm(union vect128 * iv,const union vect128 * k_s,uint32_t ssrc,uint64_t ix)93 void 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 
srtp_suite_name(enum srtp_suite suite)108 const 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 }
121