1 /*
2  * libZRTP SDK library, implements the ZRTP secure VoIP protocol.
3  * Copyright (c) 2006-2009 Philip R. Zimmermann.  All rights reserved.
4  * Contact: http://philzimmermann.com
5  * For licensing and other legal details, see the file zrtp_legal.c.
6  *
7  * Viktor Krykun <v.krikun at zfoneproject.com>
8  */
9 
10 #include <setjmp.h>
11 #include <stdio.h>
12 
13 #include "zrtp.h"
14 #include "cmockery/cmockery.h"
15 
16 #define _ZTU_ "srtp replay test"
17 
18 zrtp_global_t *zrtp;
19 
20 #define TEST_MAP_WIDTH 64
21 #if TEST_MAP_WIDTH%8
22 #	define TEST_MAP_WIDTH_BYTES TEST_MAP_WIDTH/8+1
23 #else
24 #	define TEST_MAP_WIDTH_BYTES TEST_MAP_WIDTH/8
25 #endif
26 
27 #define FIRST_TEST_MAP_INIT_WIDTH 24
28 
29 extern zrtp_rp_node_t *get_rp_node_non_lock(zrtp_rp_ctx_t *ctx, uint8_t direction, uint32_t ssrc);
30 extern zrtp_rp_node_t *add_rp_node(zrtp_srtp_ctx_t *srtp_ctx, zrtp_rp_ctx_t *ctx, uint8_t direction, uint32_t ssrc);
31 extern zrtp_status_t zrtp_srtp_rp_check(zrtp_srtp_rp_t *srtp_rp, zrtp_rtp_info_t *packet);
32 extern zrtp_status_t zrtp_srtp_rp_add(zrtp_srtp_rp_t *srtp_rp, zrtp_rtp_info_t *packet);
33 
34 
setup()35 void setup() {
36 	zrtp_status_t s;
37 	zrtp_config_t zrtp_config;
38 
39 	zrtp_config_defaults(&zrtp_config);
40 
41 	s = zrtp_init(&zrtp_config, &zrtp);
42 	assert_int_equal(s, zrtp_status_ok);
43 }
44 
teardown()45 void teardown() {
46 	zrtp_down(zrtp);
47 }
48 
print_map(uint8_t * map,int width_bytes)49 static void print_map(uint8_t *map, int width_bytes)
50 {
51 	int i;
52 	for(i=width_bytes-1; i >= 0; i--) {
53 		ZRTP_LOGC(3, ("%i%i%i%i%i%i%i%i",
54 					zrtp_bitmap_get_bit(map, 8*i+7),
55 					zrtp_bitmap_get_bit(map, 8*i+6),
56 					zrtp_bitmap_get_bit(map, 8*i+5),
57 					zrtp_bitmap_get_bit(map, 8*i+4),
58 					zrtp_bitmap_get_bit(map, 8*i+3),
59 					zrtp_bitmap_get_bit(map, 8*i+2),
60 					zrtp_bitmap_get_bit(map, 8*i+1),
61 					zrtp_bitmap_get_bit(map, 8*i+0)));
62 	}
63 	ZRTP_LOG(3, (_ZTU_, "\n"));
64 }
65 
init_random_map(uint8_t * map,int width,zrtp_global_t * zrtp)66 static void init_random_map(uint8_t *map, int width, zrtp_global_t *zrtp) {
67 	int i;
68 	for(i=0; i<width; i++) {
69 		uint32_t rnd = 0;
70 		zrtp_randstr(zrtp, (uint8_t*)&rnd, sizeof(rnd));
71 		if(rnd%10 < 5) {
72 			zrtp_bitmap_set_bit(map, i);
73 		} else {
74 			zrtp_bitmap_clear_bit(map, i);
75 		}
76 	}
77 }
78 
inject_from_map(zrtp_srtp_global_t * srtp_global,uint32_t ssrc,uint8_t * src_map,uint8_t * dst_map,int width)79 void inject_from_map( zrtp_srtp_global_t *srtp_global,
80 					  uint32_t ssrc,
81 					  uint8_t *src_map, uint8_t *dst_map, int width) {
82 	zrtp_rp_node_t *rp_node;
83 	int i;
84 	zrtp_rtp_info_t pkt;
85 
86 	rp_node = get_rp_node_non_lock(srtp_global->rp_ctx, RP_INCOMING_DIRECTION, ssrc);
87 	if (NULL == rp_node) {
88 		return;
89 	}
90 
91 	for (i=0; i< width; i++) {
92 		if (1 == zrtp_bitmap_get_bit(src_map, i)) {
93 			pkt.seq = i;
94 			if (zrtp_status_ok == zrtp_srtp_rp_check(&rp_node->rtp_rp, &pkt)) {
95 				zrtp_bitmap_set_bit(dst_map, i);
96 				zrtp_srtp_rp_add(&rp_node->rtp_rp, &pkt);
97 			}
98 		}
99 	}
100 }
101 
102 // TODO: split test into several, more atomic tests
srtp_replay_test()103 static void srtp_replay_test() {
104 	int res = 0;
105 	uint32_t ssrc = 1;
106 	int i = 0;
107 	uint8_t test_map[TEST_MAP_WIDTH_BYTES];
108 	uint8_t result_map[TEST_MAP_WIDTH_BYTES];
109 	uint8_t tmp_window[ZRTP_SRTP_WINDOW_WIDTH_BYTES];
110 	uint32_t tmp_seq;
111 	int delta, shift;
112 
113 	zrtp_rp_node_t *rp_node;
114 	zrtp_srtp_global_t *srtp = zrtp->srtp_global;
115 
116 	rp_node = add_rp_node(NULL, srtp->rp_ctx, RP_INCOMING_DIRECTION, ssrc);
117 	assert_non_null(rp_node);
118 
119 	for (i=0; i< TEST_MAP_WIDTH_BYTES; i++) {
120 		test_map[i] = 0;
121 		result_map[i] = 0;
122 	}
123 	/*
124 	 * 1st test
125 	 * ----------------------------------------------------------------------
126 	 */
127 	init_random_map(test_map, FIRST_TEST_MAP_INIT_WIDTH, zrtp);
128 	inject_from_map(srtp, ssrc, test_map, result_map, TEST_MAP_WIDTH);
129 
130 	ZRTP_LOG(3, (_ZTU_,"1st test. Wnd[%i]...\n", ZRTP_SRTP_WINDOW_WIDTH));
131 
132 	tmp_seq = rp_node->rtp_rp.seq;
133 	for (i=0; i<ZRTP_SRTP_WINDOW_WIDTH_BYTES; i++) {
134 		tmp_window[i] = rp_node->rtp_rp.window[i];
135 	}
136 
137 	delta = tmp_seq-ZRTP_SRTP_WINDOW_WIDTH + 1;
138 	if (delta > 0) {
139 		ZRTP_LOG(3, (_ZTU_,"after  wnd: (%i;0]\n", delta));
140 		ZRTP_LOG(3, (_ZTU_,"inside wnd: [%i;%i]\n", tmp_seq, delta));
141 	} else {
142 		ZRTP_LOG(3, (_ZTU_,"after  wnd: (0;0)\n"));
143 		ZRTP_LOG(3, (_ZTU_,"inside wnd: [%i;0]\n", tmp_seq));
144 	}
145 
146 	ZRTP_LOG(3, (_ZTU_,"before wnd: [%i;%i)\n", TEST_MAP_WIDTH-1, tmp_seq));
147 
148 	ZRTP_LOG(3, (_ZTU_,"Test map: "));
149 	print_map(test_map, TEST_MAP_WIDTH_BYTES);
150 
151 	ZRTP_LOG(3, (_ZTU_,"Res  map: "));
152 	print_map(result_map, TEST_MAP_WIDTH_BYTES);
153 
154 	shift = TEST_MAP_WIDTH;
155 	shift -= rp_node->rtp_rp.seq + 1;
156 
157 	ZRTP_LOG(3, (_ZTU_,"Window  : "));
158 	for(i=shift; i > 0; i--){
159 		ZRTP_LOGC(3, (" "));
160 	}
161 	print_map(rp_node->rtp_rp.window, ZRTP_SRTP_WINDOW_WIDTH_BYTES);
162 
163 	/*
164 	 * 2nd test
165 	 * ----------------------------------------------------------------------
166 	 */
167 	for(i=0; i< TEST_MAP_WIDTH_BYTES; i++){
168 		test_map[i] = 0;
169 		result_map[i] = 0;
170 	}
171 
172 	init_random_map(test_map, TEST_MAP_WIDTH, zrtp);
173 	inject_from_map(srtp, ssrc, test_map, result_map, TEST_MAP_WIDTH);
174 
175 	ZRTP_LOG(3, (_ZTU_,"2nd test. Wnd[%i]...\n", ZRTP_SRTP_WINDOW_WIDTH));
176 	ZRTP_LOG(3, (_ZTU_,"Test map: "));
177 	print_map(test_map, TEST_MAP_WIDTH_BYTES);
178 
179 	ZRTP_LOG(3, (_ZTU_,"Res  map: "));
180 	print_map(result_map, TEST_MAP_WIDTH_BYTES);
181 
182 	shift = TEST_MAP_WIDTH;
183 	shift -= rp_node->rtp_rp.seq + 1;
184 
185 	ZRTP_LOG(3, (_ZTU_,"Window  : "));
186 	for (i=shift; i > 0; i--) {
187 		//zrtp_print_log(ZRTP_LOG_DEBUG, " ");
188 	}
189 	print_map(rp_node->rtp_rp.window, ZRTP_SRTP_WINDOW_WIDTH_BYTES);
190 
191 
192 	/*
193 	  in result map:
194 	  - after window we should to have all zeroes
195 	  - into the window we should have ones only if window have zero at appropriate position
196 	  - before window we should have equal values of test map and result map bits
197 	*/
198 	for (i=0; i < TEST_MAP_WIDTH; i++) {
199 		if (delta > 0 && i < delta) {
200 			/* After window */
201 			if (0 != zrtp_bitmap_get_bit(result_map, i)) {
202 				ZRTP_LOG(3, (_ZTU_,"After window. %i bit should be 0\n", i));
203 				res = -1;
204 			}
205 		} else if (i <= (int)tmp_seq && i >= delta) {
206 			/* inside window */
207 
208 			/* check window filtering */
209 			if(1 == zrtp_bitmap_get_bit(result_map, i)) {
210 				if (1 == zrtp_bitmap_get_bit(tmp_window, i - (tmp_seq-ZRTP_SRTP_WINDOW_WIDTH) - 1)) {
211 					ZRTP_LOG(3, (_ZTU_,"Inside window. Window filtering fail. %i bit should be 0\n", i));
212 					res = -1;
213 				}
214 			}
215 			/* check test vs result maps */
216 			if ( zrtp_bitmap_get_bit(result_map, i) != zrtp_bitmap_get_bit(test_map, i) &&
217 				 !zrtp_bitmap_get_bit(tmp_window, i - (tmp_seq-ZRTP_SRTP_WINDOW_WIDTH) - 1)) {
218 				ZRTP_LOG(3, (_ZTU_, "Inside window. Test map isn't equal to result at bit %i\n", i));
219 				res = -1;
220 			}
221 
222 		} else {
223 			/* after window */
224 			if (zrtp_bitmap_get_bit(result_map, i) != zrtp_bitmap_get_bit(test_map, i)) {
225 				ZRTP_LOG(3, (_ZTU_,"Before window. Test map isn't equal to result at bit %i\n", i));
226 				res = -1;
227 			}
228 		}
229 	}
230 
231 	assert_int_equal(res, 0);
232 }
233 
main(void)234 int main(void) {
235 	const UnitTest tests[] = {
236 		unit_test_setup_teardown(srtp_replay_test, setup, teardown),
237   	};
238 
239 	return run_tests(tests);
240 }
241