blob: a7104bf20eff67efbc32d653d922e68d7c593802 [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
5#include <mbedtls/ssl.h>
6#include <test/ssl_helpers.h>
7
8/* END_HEADER */
9
10/* BEGIN_DEPENDENCIES
11 * depends_on:MBEDTLS_SSL_TLS_C
12 * END_DEPENDENCIES
13 */
14
15/* BEGIN_CASE depends_on:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_AES_C:MBEDTLS_SSL_PROTO_TLS1_2 */
16void ssl_decrypt_non_etm_cbc(int cipher_type, int hash_id, int trunc_hmac,
17 int length_selector)
18{
19 /*
20 * Test record decryption for CBC without EtM, focused on the verification
21 * of padding and MAC.
22 *
23 * Actually depends on TLS >= 1.0 (SSL 3.0 computes the MAC differently),
24 * and either AES, ARIA, Camellia or DES, but since the test framework
25 * doesn't support alternation in dependency statements, just depend on
26 * TLS 1.2 and AES.
27 *
28 * The length_selector argument is interpreted as follows:
29 * - if it's -1, the plaintext length is 0 and minimal padding is applied
30 * - if it's -2, the plaintext length is 0 and maximal padding is applied
31 * - otherwise it must be in [0, 255] and is padding_length from RFC 5246:
32 * it's the length of the rest of the padding, that is, excluding the
33 * byte that encodes the length. The minimal non-zero plaintext length
34 * that gives this padding_length is automatically selected.
35 */
36 mbedtls_ssl_context ssl; /* ONLY for debugging */
37 mbedtls_ssl_transform t0, t1;
38 mbedtls_record rec, rec_save;
39 unsigned char *buf = NULL, *buf_save = NULL;
40 size_t buflen, olen = 0;
41 size_t plaintext_len, block_size, i;
42 unsigned char padlen; /* excluding the padding_length byte */
Gilles Peskine9013b812023-09-18 12:42:37 +020043 int exp_ret;
44 const unsigned char pad_max_len = 255; /* Per the standard */
45
46 mbedtls_ssl_init(&ssl);
47 mbedtls_ssl_transform_init(&t0);
48 mbedtls_ssl_transform_init(&t1);
49 USE_PSA_INIT();
50
51 /* Set up transforms with dummy keys */
52 TEST_ASSERT(mbedtls_test_ssl_build_transforms(&t0, &t1, cipher_type, hash_id,
53 0, trunc_hmac,
54 MBEDTLS_SSL_MINOR_VERSION_3,
55 0, 0) == 0);
56
57 /* Determine padding/plaintext length */
58 TEST_ASSERT(length_selector >= -2 && length_selector <= 255);
59 block_size = t0.ivlen;
60 if (length_selector < 0) {
61 plaintext_len = 0;
62
63 /* Minimal padding
64 * The +1 is for the padding_length byte, not counted in padlen. */
65 padlen = block_size - (t0.maclen + 1) % block_size;
66
67 /* Maximal padding? */
68 if (length_selector == -2) {
69 padlen += block_size * ((pad_max_len - padlen) / block_size);
70 }
71 } else {
72 padlen = length_selector;
73
74 /* Minimal non-zero plaintext_length giving desired padding.
75 * The +1 is for the padding_length byte, not counted in padlen. */
76 plaintext_len = block_size - (padlen + t0.maclen + 1) % block_size;
77 }
78
79 /* Prepare a buffer for record data */
80 buflen = block_size
81 + plaintext_len
82 + t0.maclen
83 + padlen + 1;
84 TEST_CALLOC(buf, buflen);
85 TEST_CALLOC(buf_save, buflen);
86
87 /* Prepare a dummy record header */
88 memset(rec.ctr, 0, sizeof(rec.ctr));
89 rec.type = MBEDTLS_SSL_MSG_APPLICATION_DATA;
90 rec.ver[0] = MBEDTLS_SSL_MAJOR_VERSION_3;
91 rec.ver[1] = MBEDTLS_SSL_MINOR_VERSION_3;
92#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
93 rec.cid_len = 0;
94#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
95
96 /* Prepare dummy record content */
97 rec.buf = buf;
98 rec.buf_len = buflen;
99 rec.data_offset = block_size;
100 rec.data_len = plaintext_len;
101 memset(rec.buf + rec.data_offset, 42, rec.data_len);
102
Gilles Peskine9013b812023-09-18 12:42:37 +0200103 /* Set dummy IV */
104 memset(t0.iv_enc, 0x55, t0.ivlen);
105 memcpy(rec.buf, t0.iv_enc, t0.ivlen);
106
107 /*
108 * Prepare a pre-encryption record (with MAC and padding), and save it.
109 */
Gilles Peskine2198cc52023-09-18 13:11:50 +0200110 TEST_EQUAL(0, mbedtls_test_ssl_prepare_record_mac(&rec, &t0));
Gilles Peskine9013b812023-09-18 12:42:37 +0200111
112 /* Pad */
113 memset(rec.buf + rec.data_offset + rec.data_len, padlen, padlen + 1);
114 rec.data_len += padlen + 1;
115
116 /* Save correct pre-encryption record */
117 rec_save = rec;
118 rec_save.buf = buf_save;
119 memcpy(buf_save, buf, buflen);
120
121 /*
122 * Encrypt and decrypt the correct record, expecting success
123 */
124 TEST_EQUAL(0, mbedtls_cipher_crypt(&t0.cipher_ctx_enc,
125 t0.iv_enc, t0.ivlen,
126 rec.buf + rec.data_offset, rec.data_len,
127 rec.buf + rec.data_offset, &olen));
128 rec.data_offset -= t0.ivlen;
129 rec.data_len += t0.ivlen;
130
131 TEST_EQUAL(0, mbedtls_ssl_decrypt_buf(&ssl, &t1, &rec));
132
133 /*
134 * Modify each byte of the pre-encryption record before encrypting and
135 * decrypting it, expecting failure every time.
136 */
137 for (i = block_size; i < buflen; i++) {
138 mbedtls_test_set_step(i);
139
140 /* Restore correct pre-encryption record */
141 rec = rec_save;
142 rec.buf = buf;
143 memcpy(buf, buf_save, buflen);
144
145 /* Corrupt one byte of the data (could be plaintext, MAC or padding) */
146 rec.buf[i] ^= 0x01;
147
148 /* Encrypt */
149 TEST_EQUAL(0, mbedtls_cipher_crypt(&t0.cipher_ctx_enc,
150 t0.iv_enc, t0.ivlen,
151 rec.buf + rec.data_offset, rec.data_len,
152 rec.buf + rec.data_offset, &olen));
153 rec.data_offset -= t0.ivlen;
154 rec.data_len += t0.ivlen;
155
156 /* Decrypt and expect failure */
157 TEST_EQUAL(MBEDTLS_ERR_SSL_INVALID_MAC,
158 mbedtls_ssl_decrypt_buf(&ssl, &t1, &rec));
159 }
160
161 /*
162 * Use larger values of the padding bytes - with small buffers, this tests
163 * the case where the announced padlen would be larger than the buffer
164 * (and before that, than the buffer minus the size of the MAC), to make
165 * sure our padding checking code does not perform any out-of-bounds reads
166 * in this case. (With larger buffers, ie when the plaintext is long or
167 * maximal length padding is used, this is less relevant but still doesn't
168 * hurt to test.)
169 *
170 * (Start the loop with correct padding, just to double-check that record
171 * saving did work, and that we're overwriting the correct bytes.)
172 */
173 for (i = padlen; i <= pad_max_len; i++) {
174 mbedtls_test_set_step(i);
175
176 /* Restore correct pre-encryption record */
177 rec = rec_save;
178 rec.buf = buf;
179 memcpy(buf, buf_save, buflen);
180
181 /* Set padding bytes to new value */
182 memset(buf + buflen - padlen - 1, i, padlen + 1);
183
184 /* Encrypt */
185 TEST_EQUAL(0, mbedtls_cipher_crypt(&t0.cipher_ctx_enc,
186 t0.iv_enc, t0.ivlen,
187 rec.buf + rec.data_offset, rec.data_len,
188 rec.buf + rec.data_offset, &olen));
189 rec.data_offset -= t0.ivlen;
190 rec.data_len += t0.ivlen;
191
192 /* Decrypt and expect failure except the first time */
193 exp_ret = (i == padlen) ? 0 : MBEDTLS_ERR_SSL_INVALID_MAC;
194 TEST_EQUAL(exp_ret, mbedtls_ssl_decrypt_buf(&ssl, &t1, &rec));
195 }
196
197exit:
198 mbedtls_ssl_free(&ssl);
199 mbedtls_ssl_transform_free(&t0);
200 mbedtls_ssl_transform_free(&t1);
201 mbedtls_free(buf);
202 mbedtls_free(buf_save);
203 USE_PSA_DONE();
204}
205/* END_CASE */