summaryrefslogtreecommitdiff
path: root/third_party/srtp/srtp/ekt.c
blob: 335a21fff2c5ad48b3e9a08acff21571c39a2629 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
/*
 * ekt.c
 *
 * Encrypted Key Transport for SRTP
 * 
 * David McGrew
 * Cisco Systems, Inc.
 */
/*
 *	
 * Copyright (c) 2001-2006 Cisco Systems, Inc.
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 *   Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * 
 *   Redistributions in binary form must reproduce the above
 *   copyright notice, this list of conditions and the following
 *   disclaimer in the documentation and/or other materials provided
 *   with the distribution.
 * 
 *   Neither the name of the Cisco Systems, Inc. nor the names of its
 *   contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */


#include "srtp_priv.h"
#include "err.h"
#include "ekt.h"

extern debug_module_t mod_srtp;

/*
 *  The EKT Authentication Tag format.
 *
 *    0                   1                   2                   3
 *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *   :                   Base Authentication Tag                     :
 *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *   :                     Encrypted Master Key                      :
 *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *   |                       Rollover Counter                        |
 *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *   |    Initial Sequence Number    |   Security Parameter Index    |
 *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *
 */			 

#define EKT_OCTETS_AFTER_BASE_TAG 24
#define EKT_OCTETS_AFTER_EMK       8
#define EKT_OCTETS_AFTER_ROC       4
#define EKT_SPI_LEN                2

unsigned
ekt_octets_after_base_tag(ekt_stream_t ekt) {
  /*
   * if the pointer ekt is NULL, then EKT is not in effect, so we
   * indicate this by returning zero
   */
  if (!ekt)
    return 0;

  switch(ekt->data->ekt_cipher_type) {
  case EKT_CIPHER_AES_128_ECB:
    return 16 + EKT_OCTETS_AFTER_EMK;
    break;
  default:
    break;
  }
  return 0;
}

static inline ekt_spi_t
srtcp_packet_get_ekt_spi(const uint8_t *packet_start, unsigned pkt_octet_len) {
  const uint8_t *spi_location;
  
  spi_location = packet_start + (pkt_octet_len - EKT_SPI_LEN);
  
  return *((const ekt_spi_t *)spi_location);
}

static inline uint32_t
srtcp_packet_get_ekt_roc(const uint8_t *packet_start, unsigned pkt_octet_len) {
  const uint8_t *roc_location;
  
  roc_location = packet_start + (pkt_octet_len - EKT_OCTETS_AFTER_ROC);
  
  return *((const uint32_t *)roc_location);
}

static inline const uint8_t *
srtcp_packet_get_emk_location(const uint8_t *packet_start, 
			      unsigned pkt_octet_len) {
  const uint8_t *location;
  
  location = packet_start + (pkt_octet_len - EKT_OCTETS_AFTER_BASE_TAG);

  return location;
}


err_status_t 
ekt_alloc(ekt_stream_t *stream_data, ekt_policy_t policy) {

  /*
   * if the policy pointer is NULL, then EKT is not in use
   * so we just set the EKT stream data pointer to NULL
   */
  if (!policy) {
    *stream_data = NULL;
    return err_status_ok;
  }

  /* TODO */
  *stream_data = NULL;

  return err_status_ok;
}

err_status_t
ekt_stream_init_from_policy(ekt_stream_t stream_data, ekt_policy_t policy) {
  if (!stream_data)
    return err_status_ok;

  return err_status_ok;
}


void
aes_decrypt_with_raw_key(void *ciphertext, const void *key, int key_len) {
#ifndef OPENSSL
//FIXME: need to get this working through the crypto module interface
  aes_expanded_key_t expanded_key;

  aes_expand_decryption_key(key, key_len, &expanded_key);
  aes_decrypt(ciphertext, &expanded_key);
#endif
}

/*
 * The function srtp_stream_init_from_ekt() initializes a stream using
 * the EKT data from an SRTCP trailer.  
 */

err_status_t
srtp_stream_init_from_ekt(srtp_stream_t stream,			  
			  const void *srtcp_hdr,
			  unsigned pkt_octet_len) {
  err_status_t err;
  const uint8_t *master_key;
  srtp_policy_t srtp_policy;
  uint32_t roc;

  /*
   * NOTE: at present, we only support a single ekt_policy at a time.  
   */
  if (stream->ekt->data->spi != 
      srtcp_packet_get_ekt_spi(srtcp_hdr, pkt_octet_len))
    return err_status_no_ctx;

  if (stream->ekt->data->ekt_cipher_type != EKT_CIPHER_AES_128_ECB)
    return err_status_bad_param;

  /* decrypt the Encrypted Master Key field */
  master_key = srtcp_packet_get_emk_location(srtcp_hdr, pkt_octet_len);
  /* FIX!? This decrypts the master key in-place, and never uses it */
  /* FIX!? It's also passing to ekt_dec_key (which is an aes_expanded_key_t)
   * to a function which expects a raw (unexpanded) key */
  aes_decrypt_with_raw_key((void*)master_key, &stream->ekt->data->ekt_dec_key, 16);

  /* set the SRTP ROC */
  roc = srtcp_packet_get_ekt_roc(srtcp_hdr, pkt_octet_len);
  err = rdbx_set_roc(&stream->rtp_rdbx, roc);
  if (err) return err;

  err = srtp_stream_init(stream, &srtp_policy);
  if (err) return err;

  return err_status_ok;
}

void
ekt_write_data(ekt_stream_t ekt,
	       uint8_t *base_tag, 
	       unsigned base_tag_len, 
	       int *packet_len,
	       xtd_seq_num_t pkt_index) {
  uint32_t roc;
  uint16_t isn;
  unsigned emk_len;
  uint8_t *packet;

  /* if the pointer ekt is NULL, then EKT is not in effect */
  if (!ekt) {
    debug_print(mod_srtp, "EKT not in use", NULL);
    return;
  }

  /* write zeros into the location of the base tag */
  octet_string_set_to_zero(base_tag, base_tag_len);
  packet = base_tag + base_tag_len;

  /* copy encrypted master key into packet */
  emk_len = ekt_octets_after_base_tag(ekt);
  memcpy(packet, ekt->encrypted_master_key, emk_len);
  debug_print(mod_srtp, "writing EKT EMK: %s,", 
	      octet_string_hex_string(packet, emk_len));
  packet += emk_len;

  /* copy ROC into packet */
  roc = (uint32_t)(pkt_index >> 16);
  *((uint32_t *)packet) = be32_to_cpu(roc);
  debug_print(mod_srtp, "writing EKT ROC: %s,", 
	      octet_string_hex_string(packet, sizeof(roc)));
  packet += sizeof(roc);

  /* copy ISN into packet */
  isn = (uint16_t)pkt_index;
  *((uint16_t *)packet) = htons(isn);
  debug_print(mod_srtp, "writing EKT ISN: %s,", 
	      octet_string_hex_string(packet, sizeof(isn)));
  packet += sizeof(isn);

  /* copy SPI into packet */
  *((uint16_t *)packet) = htons(ekt->data->spi);
  debug_print(mod_srtp, "writing EKT SPI: %s,", 
	      octet_string_hex_string(packet, sizeof(ekt->data->spi)));

  /* increase packet length appropriately */
  *packet_len += EKT_OCTETS_AFTER_EMK + emk_len;
}


/*
 * The function call srtcp_ekt_trailer(ekt, auth_len, auth_tag   )
 * 
 * If the pointer ekt is NULL, then the other inputs are unaffected.
 *
 * auth_tag is a pointer to the pointer to the location of the
 * authentication tag in the packet.  If EKT is in effect, then the
 * auth_tag pointer is set to the location 
 */

void
srtcp_ekt_trailer(ekt_stream_t ekt,
		  unsigned *auth_len,
		  void **auth_tag,
		  void *tag_copy) {
  
  /* 
   * if there is no EKT policy, then the other inputs are unaffected
   */
  if (!ekt) 
    return;
      
  /* copy auth_tag into temporary location */
  
}