blob: ed30bb541033fb5809124d0b077935e37cab7ce1 [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 */
43 unsigned char add_data[13];
44 unsigned char mac[MBEDTLS_MD_MAX_SIZE];
45 int exp_ret;
46 const unsigned char pad_max_len = 255; /* Per the standard */
47
48 mbedtls_ssl_init(&ssl);
49 mbedtls_ssl_transform_init(&t0);
50 mbedtls_ssl_transform_init(&t1);
51 USE_PSA_INIT();
52
53 /* Set up transforms with dummy keys */
54 TEST_ASSERT(mbedtls_test_ssl_build_transforms(&t0, &t1, cipher_type, hash_id,
55 0, trunc_hmac,
56 MBEDTLS_SSL_MINOR_VERSION_3,
57 0, 0) == 0);
58
59 /* Determine padding/plaintext length */
60 TEST_ASSERT(length_selector >= -2 && length_selector <= 255);
61 block_size = t0.ivlen;
62 if (length_selector < 0) {
63 plaintext_len = 0;
64
65 /* Minimal padding
66 * The +1 is for the padding_length byte, not counted in padlen. */
67 padlen = block_size - (t0.maclen + 1) % block_size;
68
69 /* Maximal padding? */
70 if (length_selector == -2) {
71 padlen += block_size * ((pad_max_len - padlen) / block_size);
72 }
73 } else {
74 padlen = length_selector;
75
76 /* Minimal non-zero plaintext_length giving desired padding.
77 * The +1 is for the padding_length byte, not counted in padlen. */
78 plaintext_len = block_size - (padlen + t0.maclen + 1) % block_size;
79 }
80
81 /* Prepare a buffer for record data */
82 buflen = block_size
83 + plaintext_len
84 + t0.maclen
85 + padlen + 1;
86 TEST_CALLOC(buf, buflen);
87 TEST_CALLOC(buf_save, buflen);
88
89 /* Prepare a dummy record header */
90 memset(rec.ctr, 0, sizeof(rec.ctr));
91 rec.type = MBEDTLS_SSL_MSG_APPLICATION_DATA;
92 rec.ver[0] = MBEDTLS_SSL_MAJOR_VERSION_3;
93 rec.ver[1] = MBEDTLS_SSL_MINOR_VERSION_3;
94#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
95 rec.cid_len = 0;
96#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
97
98 /* Prepare dummy record content */
99 rec.buf = buf;
100 rec.buf_len = buflen;
101 rec.data_offset = block_size;
102 rec.data_len = plaintext_len;
103 memset(rec.buf + rec.data_offset, 42, rec.data_len);
104
105 /* Serialized version of record header for MAC purposes */
106 memcpy(add_data, rec.ctr, 8);
107 add_data[8] = rec.type;
108 add_data[9] = rec.ver[0];
109 add_data[10] = rec.ver[1];
110 add_data[11] = (rec.data_len >> 8) & 0xff;
111 add_data[12] = (rec.data_len >> 0) & 0xff;
112
113 /* Set dummy IV */
114 memset(t0.iv_enc, 0x55, t0.ivlen);
115 memcpy(rec.buf, t0.iv_enc, t0.ivlen);
116
117 /*
118 * Prepare a pre-encryption record (with MAC and padding), and save it.
119 */
120
121 /* MAC with additional data */
122 TEST_EQUAL(0, mbedtls_md_hmac_update(&t0.md_ctx_enc, add_data, 13));
123 TEST_EQUAL(0, mbedtls_md_hmac_update(&t0.md_ctx_enc,
124 rec.buf + rec.data_offset,
125 rec.data_len));
126 TEST_EQUAL(0, mbedtls_md_hmac_finish(&t0.md_ctx_enc, mac));
127
128 memcpy(rec.buf + rec.data_offset + rec.data_len, mac, t0.maclen);
129 rec.data_len += t0.maclen;
130
131 /* Pad */
132 memset(rec.buf + rec.data_offset + rec.data_len, padlen, padlen + 1);
133 rec.data_len += padlen + 1;
134
135 /* Save correct pre-encryption record */
136 rec_save = rec;
137 rec_save.buf = buf_save;
138 memcpy(buf_save, buf, buflen);
139
140 /*
141 * Encrypt and decrypt the correct record, expecting success
142 */
143 TEST_EQUAL(0, mbedtls_cipher_crypt(&t0.cipher_ctx_enc,
144 t0.iv_enc, t0.ivlen,
145 rec.buf + rec.data_offset, rec.data_len,
146 rec.buf + rec.data_offset, &olen));
147 rec.data_offset -= t0.ivlen;
148 rec.data_len += t0.ivlen;
149
150 TEST_EQUAL(0, mbedtls_ssl_decrypt_buf(&ssl, &t1, &rec));
151
152 /*
153 * Modify each byte of the pre-encryption record before encrypting and
154 * decrypting it, expecting failure every time.
155 */
156 for (i = block_size; i < buflen; i++) {
157 mbedtls_test_set_step(i);
158
159 /* Restore correct pre-encryption record */
160 rec = rec_save;
161 rec.buf = buf;
162 memcpy(buf, buf_save, buflen);
163
164 /* Corrupt one byte of the data (could be plaintext, MAC or padding) */
165 rec.buf[i] ^= 0x01;
166
167 /* Encrypt */
168 TEST_EQUAL(0, mbedtls_cipher_crypt(&t0.cipher_ctx_enc,
169 t0.iv_enc, t0.ivlen,
170 rec.buf + rec.data_offset, rec.data_len,
171 rec.buf + rec.data_offset, &olen));
172 rec.data_offset -= t0.ivlen;
173 rec.data_len += t0.ivlen;
174
175 /* Decrypt and expect failure */
176 TEST_EQUAL(MBEDTLS_ERR_SSL_INVALID_MAC,
177 mbedtls_ssl_decrypt_buf(&ssl, &t1, &rec));
178 }
179
180 /*
181 * Use larger values of the padding bytes - with small buffers, this tests
182 * the case where the announced padlen would be larger than the buffer
183 * (and before that, than the buffer minus the size of the MAC), to make
184 * sure our padding checking code does not perform any out-of-bounds reads
185 * in this case. (With larger buffers, ie when the plaintext is long or
186 * maximal length padding is used, this is less relevant but still doesn't
187 * hurt to test.)
188 *
189 * (Start the loop with correct padding, just to double-check that record
190 * saving did work, and that we're overwriting the correct bytes.)
191 */
192 for (i = padlen; i <= pad_max_len; i++) {
193 mbedtls_test_set_step(i);
194
195 /* Restore correct pre-encryption record */
196 rec = rec_save;
197 rec.buf = buf;
198 memcpy(buf, buf_save, buflen);
199
200 /* Set padding bytes to new value */
201 memset(buf + buflen - padlen - 1, i, padlen + 1);
202
203 /* Encrypt */
204 TEST_EQUAL(0, mbedtls_cipher_crypt(&t0.cipher_ctx_enc,
205 t0.iv_enc, t0.ivlen,
206 rec.buf + rec.data_offset, rec.data_len,
207 rec.buf + rec.data_offset, &olen));
208 rec.data_offset -= t0.ivlen;
209 rec.data_len += t0.ivlen;
210
211 /* Decrypt and expect failure except the first time */
212 exp_ret = (i == padlen) ? 0 : MBEDTLS_ERR_SSL_INVALID_MAC;
213 TEST_EQUAL(exp_ret, mbedtls_ssl_decrypt_buf(&ssl, &t1, &rec));
214 }
215
216exit:
217 mbedtls_ssl_free(&ssl);
218 mbedtls_ssl_transform_free(&t0);
219 mbedtls_ssl_transform_free(&t1);
220 mbedtls_free(buf);
221 mbedtls_free(buf_save);
222 USE_PSA_DONE();
223}
224/* END_CASE */