blob: 39c92ce1e98d9f980c7adda69474bcd2d7bed847 [file] [log] [blame]
Gilles Peskine9013b812023-09-18 12:42:37 +02001/* BEGIN_HEADER */
2/* Testing of mbedtls_ssl_decrypt_buf() specifically, focusing on negative
3 * testing (using malformed inputs). */
4
Gilles Peskinedc48f6e2023-09-18 14:05:55 +02005#include <mbedtls/cipher.h>
Gilles Peskine9013b812023-09-18 12:42:37 +02006#include <mbedtls/ssl.h>
7#include <test/ssl_helpers.h>
8
9/* END_HEADER */
10
11/* BEGIN_DEPENDENCIES
12 * depends_on:MBEDTLS_SSL_TLS_C
13 * END_DEPENDENCIES
14 */
15
Gilles Peskinedc48f6e2023-09-18 14:05:55 +020016/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_SSL_SOME_MODES_USE_MAC */
17void ssl_decrypt_stream(int cipher_type, int hash_id, int trunc_hmac)
18{
19 mbedtls_ssl_transform transform_in, transform_out;
20 mbedtls_ssl_transform_init(&transform_in);
21 mbedtls_ssl_transform_init(&transform_out);
22 mbedtls_record rec_good = {
23 .ctr = { 0 },
24 .type = MBEDTLS_SSL_MSG_APPLICATION_DATA,
25 /* For simplicity, we only test one protocol version (TLS 1.2).
26 * For stream ciphers (unlike CBC), there are no changes in the
27 * data record format between SSL 3.0 and TLS 1.2 inclusive, so
28 * testing a single version should be good enough. */
29 .ver = { MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3 },
30 .buf = NULL,
31 .buf_len = 0,
32 .data_offset = 0,
33 .data_len = 0,
34#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
35 .cid_len = 0,
36 .cid = { 0 },
37#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
38 };
39 const char sample_plaintext[3] = "ABC";
40 mbedtls_cipher_context_t cipher;
41 mbedtls_cipher_init(&cipher);
42 mbedtls_ssl_context ssl;
43 mbedtls_ssl_init(&ssl);
44 uint8_t *buf = NULL;
45
46 USE_PSA_INIT();
47
48 TEST_EQUAL(mbedtls_test_ssl_build_transforms(&transform_in, &transform_out,
49 cipher_type, hash_id,
50 0, trunc_hmac,
51 rec_good.ver[1],
52 0, 0), 0);
53
54 const size_t plaintext_length = sizeof(sample_plaintext);
55 rec_good.buf_len = plaintext_length + transform_in.maclen;
56 rec_good.data_len = plaintext_length;
57 TEST_CALLOC(rec_good.buf, rec_good.buf_len);
58 memcpy(rec_good.buf, sample_plaintext, plaintext_length);
59 TEST_EQUAL(mbedtls_test_ssl_prepare_record_mac(&rec_good,
60 &transform_out), 0);
61
62 /* Encrypt in place */
63 size_t len;
64 TEST_EQUAL(mbedtls_cipher_crypt(&transform_out.cipher_ctx_enc,
65 transform_out.iv_enc, transform_out.ivlen,
66 rec_good.buf + rec_good.data_offset,
67 rec_good.data_len,
68 rec_good.buf + rec_good.data_offset,
69 &len), 0);
70 /* This function only supports stream ciphers, which should preserve
71 * the length. */
72 TEST_EQUAL(len, rec_good.data_len);
73
74 /* Good case */
75 mbedtls_record rec = rec_good;
76 TEST_EQUAL(mbedtls_ssl_decrypt_buf(&ssl, &transform_in, &rec), 0);
77
78 /* Change any one byte of the plaintext or MAC. The MAC will be wrong. */
79 TEST_CALLOC(buf, rec.buf_len);
80 for (size_t i = 0; i < rec.buf_len; i++) {
81 mbedtls_test_set_step(i);
82 rec = rec_good;
83 rec.buf = buf;
84 memcpy(buf, rec_good.buf, rec.buf_len);
85 buf[i] ^= 1;
86 TEST_EQUAL(mbedtls_ssl_decrypt_buf(&ssl, &transform_in, &rec),
87 MBEDTLS_ERR_SSL_INVALID_MAC);
88 }
89 mbedtls_free(buf);
90 buf = NULL;
91
92 /* Shorter input buffer. Either the MAC will be wrong, or there isn't
93 * enough room for a MAC. */
94 for (size_t n = 1; n < rec.buf_len; n++) {
95 mbedtls_test_set_step(n);
96 rec = rec_good;
97 TEST_CALLOC(buf, n);
98 rec.buf = buf;
99 rec.buf_len = n;
100 rec.data_len = n;
101 memcpy(buf, rec_good.buf, n);
102 TEST_EQUAL(mbedtls_ssl_decrypt_buf(&ssl, &transform_in, &rec),
103 MBEDTLS_ERR_SSL_INVALID_MAC);
104 mbedtls_free(buf);
105 buf = NULL;
106 }
107
108 /* For robustness, check a 0-length buffer (non-null, then null).
109 * This should not reach mbedtls_ssl_decrypt_buf() as used in the library,
110 * so the exact error doesn't matter, but we don't want a crash. */
111 {
112 const uint8_t buf1[1] = { 'a' };
113 rec = rec_good;
114 /* We won't write to buf1[0] since it's out of range, so we can cast
115 * the const away. */
116 rec.buf = (uint8_t *) buf1;
117 rec.buf_len = 0;
118 TEST_EQUAL(mbedtls_ssl_decrypt_buf(&ssl, &transform_in, &rec),
119 MBEDTLS_ERR_SSL_INTERNAL_ERROR);
120 }
121 rec = rec_good;
122 rec.buf = NULL;
123 rec.buf_len = 0;
124 TEST_EQUAL(mbedtls_ssl_decrypt_buf(&ssl, &transform_in, &rec),
125 MBEDTLS_ERR_SSL_INTERNAL_ERROR);
126
127exit:
128 USE_PSA_DONE();
129 mbedtls_ssl_transform_free(&transform_in);
130 mbedtls_ssl_transform_free(&transform_out);
131 mbedtls_free(rec_good.buf);
132 mbedtls_ssl_free(&ssl);
133 mbedtls_cipher_free(&cipher);
134 mbedtls_free(buf);
135}
136/* END_CASE */
137
Gilles Peskine9013b812023-09-18 12:42:37 +0200138/* BEGIN_CASE depends_on:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_AES_C:MBEDTLS_SSL_PROTO_TLS1_2 */
139void ssl_decrypt_non_etm_cbc(int cipher_type, int hash_id, int trunc_hmac,
140 int length_selector)
141{
142 /*
143 * Test record decryption for CBC without EtM, focused on the verification
144 * of padding and MAC.
145 *
146 * Actually depends on TLS >= 1.0 (SSL 3.0 computes the MAC differently),
147 * and either AES, ARIA, Camellia or DES, but since the test framework
148 * doesn't support alternation in dependency statements, just depend on
149 * TLS 1.2 and AES.
150 *
151 * The length_selector argument is interpreted as follows:
152 * - if it's -1, the plaintext length is 0 and minimal padding is applied
153 * - if it's -2, the plaintext length is 0 and maximal padding is applied
154 * - otherwise it must be in [0, 255] and is padding_length from RFC 5246:
155 * it's the length of the rest of the padding, that is, excluding the
156 * byte that encodes the length. The minimal non-zero plaintext length
157 * that gives this padding_length is automatically selected.
158 */
159 mbedtls_ssl_context ssl; /* ONLY for debugging */
160 mbedtls_ssl_transform t0, t1;
161 mbedtls_record rec, rec_save;
162 unsigned char *buf = NULL, *buf_save = NULL;
163 size_t buflen, olen = 0;
164 size_t plaintext_len, block_size, i;
165 unsigned char padlen; /* excluding the padding_length byte */
Gilles Peskine9013b812023-09-18 12:42:37 +0200166 int exp_ret;
167 const unsigned char pad_max_len = 255; /* Per the standard */
168
169 mbedtls_ssl_init(&ssl);
170 mbedtls_ssl_transform_init(&t0);
171 mbedtls_ssl_transform_init(&t1);
172 USE_PSA_INIT();
173
174 /* Set up transforms with dummy keys */
175 TEST_ASSERT(mbedtls_test_ssl_build_transforms(&t0, &t1, cipher_type, hash_id,
176 0, trunc_hmac,
177 MBEDTLS_SSL_MINOR_VERSION_3,
178 0, 0) == 0);
179
180 /* Determine padding/plaintext length */
181 TEST_ASSERT(length_selector >= -2 && length_selector <= 255);
182 block_size = t0.ivlen;
183 if (length_selector < 0) {
184 plaintext_len = 0;
185
186 /* Minimal padding
187 * The +1 is for the padding_length byte, not counted in padlen. */
188 padlen = block_size - (t0.maclen + 1) % block_size;
189
190 /* Maximal padding? */
191 if (length_selector == -2) {
192 padlen += block_size * ((pad_max_len - padlen) / block_size);
193 }
194 } else {
195 padlen = length_selector;
196
197 /* Minimal non-zero plaintext_length giving desired padding.
198 * The +1 is for the padding_length byte, not counted in padlen. */
199 plaintext_len = block_size - (padlen + t0.maclen + 1) % block_size;
200 }
201
202 /* Prepare a buffer for record data */
203 buflen = block_size
204 + plaintext_len
205 + t0.maclen
206 + padlen + 1;
207 TEST_CALLOC(buf, buflen);
208 TEST_CALLOC(buf_save, buflen);
209
210 /* Prepare a dummy record header */
211 memset(rec.ctr, 0, sizeof(rec.ctr));
212 rec.type = MBEDTLS_SSL_MSG_APPLICATION_DATA;
213 rec.ver[0] = MBEDTLS_SSL_MAJOR_VERSION_3;
214 rec.ver[1] = MBEDTLS_SSL_MINOR_VERSION_3;
215#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
216 rec.cid_len = 0;
217#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
218
219 /* Prepare dummy record content */
220 rec.buf = buf;
221 rec.buf_len = buflen;
222 rec.data_offset = block_size;
223 rec.data_len = plaintext_len;
224 memset(rec.buf + rec.data_offset, 42, rec.data_len);
225
Gilles Peskine9013b812023-09-18 12:42:37 +0200226 /* Set dummy IV */
227 memset(t0.iv_enc, 0x55, t0.ivlen);
228 memcpy(rec.buf, t0.iv_enc, t0.ivlen);
229
230 /*
231 * Prepare a pre-encryption record (with MAC and padding), and save it.
232 */
Gilles Peskine2198cc52023-09-18 13:11:50 +0200233 TEST_EQUAL(0, mbedtls_test_ssl_prepare_record_mac(&rec, &t0));
Gilles Peskine9013b812023-09-18 12:42:37 +0200234
235 /* Pad */
236 memset(rec.buf + rec.data_offset + rec.data_len, padlen, padlen + 1);
237 rec.data_len += padlen + 1;
238
239 /* Save correct pre-encryption record */
240 rec_save = rec;
241 rec_save.buf = buf_save;
242 memcpy(buf_save, buf, buflen);
243
244 /*
245 * Encrypt and decrypt the correct record, expecting success
246 */
247 TEST_EQUAL(0, mbedtls_cipher_crypt(&t0.cipher_ctx_enc,
248 t0.iv_enc, t0.ivlen,
249 rec.buf + rec.data_offset, rec.data_len,
250 rec.buf + rec.data_offset, &olen));
251 rec.data_offset -= t0.ivlen;
252 rec.data_len += t0.ivlen;
253
254 TEST_EQUAL(0, mbedtls_ssl_decrypt_buf(&ssl, &t1, &rec));
255
256 /*
257 * Modify each byte of the pre-encryption record before encrypting and
258 * decrypting it, expecting failure every time.
259 */
260 for (i = block_size; i < buflen; i++) {
261 mbedtls_test_set_step(i);
262
263 /* Restore correct pre-encryption record */
264 rec = rec_save;
265 rec.buf = buf;
266 memcpy(buf, buf_save, buflen);
267
268 /* Corrupt one byte of the data (could be plaintext, MAC or padding) */
269 rec.buf[i] ^= 0x01;
270
271 /* Encrypt */
272 TEST_EQUAL(0, mbedtls_cipher_crypt(&t0.cipher_ctx_enc,
273 t0.iv_enc, t0.ivlen,
274 rec.buf + rec.data_offset, rec.data_len,
275 rec.buf + rec.data_offset, &olen));
276 rec.data_offset -= t0.ivlen;
277 rec.data_len += t0.ivlen;
278
279 /* Decrypt and expect failure */
280 TEST_EQUAL(MBEDTLS_ERR_SSL_INVALID_MAC,
281 mbedtls_ssl_decrypt_buf(&ssl, &t1, &rec));
282 }
283
284 /*
285 * Use larger values of the padding bytes - with small buffers, this tests
286 * the case where the announced padlen would be larger than the buffer
287 * (and before that, than the buffer minus the size of the MAC), to make
288 * sure our padding checking code does not perform any out-of-bounds reads
289 * in this case. (With larger buffers, ie when the plaintext is long or
290 * maximal length padding is used, this is less relevant but still doesn't
291 * hurt to test.)
292 *
293 * (Start the loop with correct padding, just to double-check that record
294 * saving did work, and that we're overwriting the correct bytes.)
295 */
296 for (i = padlen; i <= pad_max_len; i++) {
297 mbedtls_test_set_step(i);
298
299 /* Restore correct pre-encryption record */
300 rec = rec_save;
301 rec.buf = buf;
302 memcpy(buf, buf_save, buflen);
303
304 /* Set padding bytes to new value */
305 memset(buf + buflen - padlen - 1, i, padlen + 1);
306
307 /* Encrypt */
308 TEST_EQUAL(0, mbedtls_cipher_crypt(&t0.cipher_ctx_enc,
309 t0.iv_enc, t0.ivlen,
310 rec.buf + rec.data_offset, rec.data_len,
311 rec.buf + rec.data_offset, &olen));
312 rec.data_offset -= t0.ivlen;
313 rec.data_len += t0.ivlen;
314
315 /* Decrypt and expect failure except the first time */
316 exp_ret = (i == padlen) ? 0 : MBEDTLS_ERR_SSL_INVALID_MAC;
317 TEST_EQUAL(exp_ret, mbedtls_ssl_decrypt_buf(&ssl, &t1, &rec));
318 }
319
320exit:
321 mbedtls_ssl_free(&ssl);
322 mbedtls_ssl_transform_free(&t0);
323 mbedtls_ssl_transform_free(&t1);
324 mbedtls_free(buf);
325 mbedtls_free(buf_save);
326 USE_PSA_DONE();
327}
328/* END_CASE */