dtlstest.c revision 1.1.1.3 1 1.1 christos /*
2 1.1.1.2 christos * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
3 1.1 christos *
4 1.1 christos * Licensed under the OpenSSL license (the "License"). You may not use
5 1.1 christos * this file except in compliance with the License. You can obtain a copy
6 1.1 christos * in the file LICENSE in the source distribution or at
7 1.1 christos * https://www.openssl.org/source/license.html
8 1.1 christos */
9 1.1 christos
10 1.1 christos #include <openssl/bio.h>
11 1.1 christos #include <openssl/crypto.h>
12 1.1 christos #include <openssl/ssl.h>
13 1.1 christos #include <openssl/err.h>
14 1.1 christos
15 1.1 christos #include "ssltestlib.h"
16 1.1 christos #include "testutil.h"
17 1.1 christos
18 1.1 christos static char *cert = NULL;
19 1.1 christos static char *privkey = NULL;
20 1.1.1.3 christos static unsigned int timer_cb_count;
21 1.1 christos
22 1.1 christos #define NUM_TESTS 2
23 1.1 christos
24 1.1 christos
25 1.1 christos #define DUMMY_CERT_STATUS_LEN 12
26 1.1 christos
27 1.1 christos static unsigned char certstatus[] = {
28 1.1 christos SSL3_RT_HANDSHAKE, /* Content type */
29 1.1 christos 0xfe, 0xfd, /* Record version */
30 1.1 christos 0, 1, /* Epoch */
31 1.1 christos 0, 0, 0, 0, 0, 0x0f, /* Record sequence number */
32 1.1 christos 0, DTLS1_HM_HEADER_LENGTH + DUMMY_CERT_STATUS_LEN - 2,
33 1.1 christos SSL3_MT_CERTIFICATE_STATUS, /* Cert Status handshake message type */
34 1.1 christos 0, 0, DUMMY_CERT_STATUS_LEN, /* Message len */
35 1.1 christos 0, 5, /* Message sequence */
36 1.1 christos 0, 0, 0, /* Fragment offset */
37 1.1 christos 0, 0, DUMMY_CERT_STATUS_LEN - 2, /* Fragment len */
38 1.1 christos 0x80, 0x80, 0x80, 0x80, 0x80,
39 1.1 christos 0x80, 0x80, 0x80, 0x80, 0x80 /* Dummy data */
40 1.1 christos };
41 1.1 christos
42 1.1 christos #define RECORD_SEQUENCE 10
43 1.1 christos
44 1.1.1.3 christos static unsigned int timer_cb(SSL *s, unsigned int timer_us)
45 1.1.1.3 christos {
46 1.1.1.3 christos ++timer_cb_count;
47 1.1.1.3 christos
48 1.1.1.3 christos if (timer_us == 0)
49 1.1.1.3 christos return 50000;
50 1.1.1.3 christos else
51 1.1.1.3 christos return 2 * timer_us;
52 1.1.1.3 christos }
53 1.1.1.3 christos
54 1.1 christos static int test_dtls_unprocessed(int testidx)
55 1.1 christos {
56 1.1 christos SSL_CTX *sctx = NULL, *cctx = NULL;
57 1.1 christos SSL *serverssl1 = NULL, *clientssl1 = NULL;
58 1.1 christos BIO *c_to_s_fbio, *c_to_s_mempacket;
59 1.1 christos int testresult = 0;
60 1.1 christos
61 1.1.1.3 christos timer_cb_count = 0;
62 1.1 christos
63 1.1.1.3 christos if (!TEST_true(create_ssl_ctx_pair(DTLS_server_method(),
64 1.1.1.3 christos DTLS_client_method(),
65 1.1.1.3 christos DTLS1_VERSION, DTLS_MAX_VERSION,
66 1.1.1.3 christos &sctx, &cctx, cert, privkey)))
67 1.1 christos return 0;
68 1.1 christos
69 1.1.1.3 christos if (!TEST_true(SSL_CTX_set_cipher_list(cctx, "AES128-SHA")))
70 1.1.1.3 christos goto end;
71 1.1 christos
72 1.1 christos c_to_s_fbio = BIO_new(bio_f_tls_dump_filter());
73 1.1.1.3 christos if (!TEST_ptr(c_to_s_fbio))
74 1.1 christos goto end;
75 1.1 christos
76 1.1 christos /* BIO is freed by create_ssl_connection on error */
77 1.1.1.3 christos if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl1, &clientssl1,
78 1.1.1.3 christos NULL, c_to_s_fbio)))
79 1.1 christos goto end;
80 1.1.1.3 christos
81 1.1.1.3 christos DTLS_set_timer_cb(clientssl1, timer_cb);
82 1.1 christos
83 1.1 christos if (testidx == 1)
84 1.1 christos certstatus[RECORD_SEQUENCE] = 0xff;
85 1.1 christos
86 1.1 christos /*
87 1.1 christos * Inject a dummy record from the next epoch. In test 0, this should never
88 1.1 christos * get used because the message sequence number is too big. In test 1 we set
89 1.1 christos * the record sequence number to be way off in the future. This should not
90 1.1 christos * have an impact on the record replay protection because the record should
91 1.1 christos * be dropped before it is marked as arrived
92 1.1 christos */
93 1.1 christos c_to_s_mempacket = SSL_get_wbio(clientssl1);
94 1.1 christos c_to_s_mempacket = BIO_next(c_to_s_mempacket);
95 1.1 christos mempacket_test_inject(c_to_s_mempacket, (char *)certstatus,
96 1.1 christos sizeof(certstatus), 1, INJECT_PACKET_IGNORE_REC_SEQ);
97 1.1 christos
98 1.1.1.3 christos if (!TEST_true(create_ssl_connection(serverssl1, clientssl1,
99 1.1.1.3 christos SSL_ERROR_NONE)))
100 1.1.1.3 christos goto end;
101 1.1.1.3 christos
102 1.1.1.3 christos if (timer_cb_count == 0) {
103 1.1.1.3 christos printf("timer_callback was not called.\n");
104 1.1 christos goto end;
105 1.1 christos }
106 1.1 christos
107 1.1 christos testresult = 1;
108 1.1 christos end:
109 1.1 christos SSL_free(serverssl1);
110 1.1 christos SSL_free(clientssl1);
111 1.1 christos SSL_CTX_free(sctx);
112 1.1 christos SSL_CTX_free(cctx);
113 1.1 christos
114 1.1 christos return testresult;
115 1.1 christos }
116 1.1 christos
117 1.1.1.3 christos #define CLI_TO_SRV_EPOCH_0_RECS 3
118 1.1.1.3 christos #define CLI_TO_SRV_EPOCH_1_RECS 1
119 1.1.1.3 christos #if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
120 1.1.1.3 christos # define SRV_TO_CLI_EPOCH_0_RECS 12
121 1.1.1.3 christos #else
122 1.1.1.3 christos /*
123 1.1.1.3 christos * In this case we have no ServerKeyExchange message, because we don't have
124 1.1.1.3 christos * ECDHE or DHE. When it is present it gets fragmented into 3 records in this
125 1.1.1.3 christos * test.
126 1.1.1.3 christos */
127 1.1.1.3 christos # define SRV_TO_CLI_EPOCH_0_RECS 9
128 1.1.1.3 christos #endif
129 1.1.1.3 christos #define SRV_TO_CLI_EPOCH_1_RECS 1
130 1.1.1.3 christos #define TOTAL_FULL_HAND_RECORDS \
131 1.1.1.3 christos (CLI_TO_SRV_EPOCH_0_RECS + CLI_TO_SRV_EPOCH_1_RECS + \
132 1.1.1.3 christos SRV_TO_CLI_EPOCH_0_RECS + SRV_TO_CLI_EPOCH_1_RECS)
133 1.1.1.3 christos
134 1.1.1.3 christos #define CLI_TO_SRV_RESUME_EPOCH_0_RECS 3
135 1.1.1.3 christos #define CLI_TO_SRV_RESUME_EPOCH_1_RECS 1
136 1.1.1.3 christos #define SRV_TO_CLI_RESUME_EPOCH_0_RECS 2
137 1.1.1.3 christos #define SRV_TO_CLI_RESUME_EPOCH_1_RECS 1
138 1.1.1.3 christos #define TOTAL_RESUME_HAND_RECORDS \
139 1.1.1.3 christos (CLI_TO_SRV_RESUME_EPOCH_0_RECS + CLI_TO_SRV_RESUME_EPOCH_1_RECS + \
140 1.1.1.3 christos SRV_TO_CLI_RESUME_EPOCH_0_RECS + SRV_TO_CLI_RESUME_EPOCH_1_RECS)
141 1.1.1.3 christos
142 1.1.1.3 christos #define TOTAL_RECORDS (TOTAL_FULL_HAND_RECORDS + TOTAL_RESUME_HAND_RECORDS)
143 1.1.1.3 christos
144 1.1.1.3 christos static int test_dtls_drop_records(int idx)
145 1.1 christos {
146 1.1.1.3 christos SSL_CTX *sctx = NULL, *cctx = NULL;
147 1.1.1.3 christos SSL *serverssl = NULL, *clientssl = NULL;
148 1.1.1.3 christos BIO *c_to_s_fbio, *mempackbio;
149 1.1.1.3 christos int testresult = 0;
150 1.1.1.3 christos int epoch = 0;
151 1.1.1.3 christos SSL_SESSION *sess = NULL;
152 1.1.1.3 christos int cli_to_srv_epoch0, cli_to_srv_epoch1, srv_to_cli_epoch0;
153 1.1.1.3 christos
154 1.1.1.3 christos if (!TEST_true(create_ssl_ctx_pair(DTLS_server_method(),
155 1.1.1.3 christos DTLS_client_method(),
156 1.1.1.3 christos DTLS1_VERSION, DTLS_MAX_VERSION,
157 1.1.1.3 christos &sctx, &cctx, cert, privkey)))
158 1.1.1.3 christos return 0;
159 1.1 christos
160 1.1.1.3 christos if (idx >= TOTAL_FULL_HAND_RECORDS) {
161 1.1.1.3 christos /* We're going to do a resumption handshake. Get a session first. */
162 1.1.1.3 christos if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
163 1.1.1.3 christos NULL, NULL))
164 1.1.1.3 christos || !TEST_true(create_ssl_connection(serverssl, clientssl,
165 1.1.1.3 christos SSL_ERROR_NONE))
166 1.1.1.3 christos || !TEST_ptr(sess = SSL_get1_session(clientssl)))
167 1.1.1.3 christos goto end;
168 1.1.1.3 christos
169 1.1.1.3 christos SSL_shutdown(clientssl);
170 1.1.1.3 christos SSL_shutdown(serverssl);
171 1.1.1.3 christos SSL_free(serverssl);
172 1.1.1.3 christos SSL_free(clientssl);
173 1.1.1.3 christos serverssl = clientssl = NULL;
174 1.1.1.3 christos
175 1.1.1.3 christos cli_to_srv_epoch0 = CLI_TO_SRV_RESUME_EPOCH_0_RECS;
176 1.1.1.3 christos cli_to_srv_epoch1 = CLI_TO_SRV_RESUME_EPOCH_1_RECS;
177 1.1.1.3 christos srv_to_cli_epoch0 = SRV_TO_CLI_RESUME_EPOCH_0_RECS;
178 1.1.1.3 christos idx -= TOTAL_FULL_HAND_RECORDS;
179 1.1.1.3 christos } else {
180 1.1.1.3 christos cli_to_srv_epoch0 = CLI_TO_SRV_EPOCH_0_RECS;
181 1.1.1.3 christos cli_to_srv_epoch1 = CLI_TO_SRV_EPOCH_1_RECS;
182 1.1.1.3 christos srv_to_cli_epoch0 = SRV_TO_CLI_EPOCH_0_RECS;
183 1.1 christos }
184 1.1 christos
185 1.1.1.3 christos c_to_s_fbio = BIO_new(bio_f_tls_dump_filter());
186 1.1.1.3 christos if (!TEST_ptr(c_to_s_fbio))
187 1.1.1.3 christos goto end;
188 1.1 christos
189 1.1.1.3 christos /* BIO is freed by create_ssl_connection on error */
190 1.1.1.3 christos if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
191 1.1.1.3 christos NULL, c_to_s_fbio)))
192 1.1.1.3 christos goto end;
193 1.1 christos
194 1.1.1.3 christos if (sess != NULL) {
195 1.1.1.3 christos if (!TEST_true(SSL_set_session(clientssl, sess)))
196 1.1.1.3 christos goto end;
197 1.1.1.3 christos }
198 1.1.1.3 christos
199 1.1.1.3 christos DTLS_set_timer_cb(clientssl, timer_cb);
200 1.1.1.3 christos DTLS_set_timer_cb(serverssl, timer_cb);
201 1.1.1.3 christos
202 1.1.1.3 christos /* Work out which record to drop based on the test number */
203 1.1.1.3 christos if (idx >= cli_to_srv_epoch0 + cli_to_srv_epoch1) {
204 1.1.1.3 christos mempackbio = SSL_get_wbio(serverssl);
205 1.1.1.3 christos idx -= cli_to_srv_epoch0 + cli_to_srv_epoch1;
206 1.1.1.3 christos if (idx >= srv_to_cli_epoch0) {
207 1.1.1.3 christos epoch = 1;
208 1.1.1.3 christos idx -= srv_to_cli_epoch0;
209 1.1.1.3 christos }
210 1.1.1.3 christos } else {
211 1.1.1.3 christos mempackbio = SSL_get_wbio(clientssl);
212 1.1.1.3 christos if (idx >= cli_to_srv_epoch0) {
213 1.1.1.3 christos epoch = 1;
214 1.1.1.3 christos idx -= cli_to_srv_epoch0;
215 1.1.1.3 christos }
216 1.1.1.3 christos mempackbio = BIO_next(mempackbio);
217 1.1.1.3 christos }
218 1.1.1.3 christos BIO_ctrl(mempackbio, MEMPACKET_CTRL_SET_DROP_EPOCH, epoch, NULL);
219 1.1.1.3 christos BIO_ctrl(mempackbio, MEMPACKET_CTRL_SET_DROP_REC, idx, NULL);
220 1.1 christos
221 1.1.1.3 christos if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
222 1.1.1.3 christos goto end;
223 1.1 christos
224 1.1.1.3 christos if (sess != NULL && !TEST_true(SSL_session_reused(clientssl)))
225 1.1.1.3 christos goto end;
226 1.1 christos
227 1.1.1.3 christos /* If the test did what we planned then it should have dropped a record */
228 1.1.1.3 christos if (!TEST_int_eq((int)BIO_ctrl(mempackbio, MEMPACKET_CTRL_GET_DROP_REC, 0,
229 1.1.1.3 christos NULL), -1))
230 1.1.1.3 christos goto end;
231 1.1 christos
232 1.1.1.3 christos testresult = 1;
233 1.1.1.3 christos end:
234 1.1.1.3 christos SSL_SESSION_free(sess);
235 1.1.1.3 christos SSL_free(serverssl);
236 1.1.1.3 christos SSL_free(clientssl);
237 1.1.1.3 christos SSL_CTX_free(sctx);
238 1.1.1.3 christos SSL_CTX_free(cctx);
239 1.1 christos
240 1.1 christos return testresult;
241 1.1 christos }
242 1.1.1.3 christos
243 1.1.1.3 christos int setup_tests(void)
244 1.1.1.3 christos {
245 1.1.1.3 christos if (!TEST_ptr(cert = test_get_argument(0))
246 1.1.1.3 christos || !TEST_ptr(privkey = test_get_argument(1)))
247 1.1.1.3 christos return 0;
248 1.1.1.3 christos
249 1.1.1.3 christos ADD_ALL_TESTS(test_dtls_unprocessed, NUM_TESTS);
250 1.1.1.3 christos ADD_ALL_TESTS(test_dtls_drop_records, TOTAL_RECORDS);
251 1.1.1.3 christos
252 1.1.1.3 christos return 1;
253 1.1.1.3 christos }
254 1.1.1.3 christos
255 1.1.1.3 christos void cleanup_tests(void)
256 1.1.1.3 christos {
257 1.1.1.3 christos bio_f_tls_dump_filter_free();
258 1.1.1.3 christos bio_s_mempacket_test_free();
259 1.1.1.3 christos }
260