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