1c7da899bSchristos /*
2*b0d17251Schristos * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
3c7da899bSchristos *
4*b0d17251Schristos * Licensed under the Apache License 2.0 (the "License"). You may not use
5c7da899bSchristos * this file except in compliance with the License. You can obtain a copy
6c7da899bSchristos * in the file LICENSE in the source distribution or at
7c7da899bSchristos * https://www.openssl.org/source/license.html
8c7da899bSchristos */
9c7da899bSchristos #include <stdio.h>
10c7da899bSchristos #include <string.h>
11c7da899bSchristos #include <openssl/evp.h>
12c7da899bSchristos #include <openssl/bio.h>
13c7da899bSchristos #include <openssl/rand.h>
14c7da899bSchristos
1513d40330Schristos #include "testutil.h"
1613d40330Schristos
1713d40330Schristos #define ENCRYPT 1
1813d40330Schristos #define DECRYPT 0
1913d40330Schristos
2013d40330Schristos #define DATA_SIZE 1024
2113d40330Schristos #define MAX_IV 32
2213d40330Schristos #define BUF_SIZE (DATA_SIZE + MAX_IV)
2313d40330Schristos
2413d40330Schristos static const unsigned char KEY[] = {
2513d40330Schristos 0x51, 0x50, 0xd1, 0x77, 0x2f, 0x50, 0x83, 0x4a,
2613d40330Schristos 0x50, 0x3e, 0x06, 0x9a, 0x97, 0x3f, 0xbd, 0x7c,
2713d40330Schristos 0xe6, 0x1c, 0x43, 0x2b, 0x72, 0x0b, 0x19, 0xd1,
2813d40330Schristos 0x8e, 0xc8, 0xd8, 0x4b, 0xdc, 0x63, 0x15, 0x1b
2913d40330Schristos };
3013d40330Schristos
3113d40330Schristos static const unsigned char IV[] = {
3213d40330Schristos 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
3313d40330Schristos 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
3413d40330Schristos 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
3513d40330Schristos 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
3613d40330Schristos };
3713d40330Schristos
do_bio_cipher(const EVP_CIPHER * cipher,const unsigned char * key,const unsigned char * iv)3813d40330Schristos static int do_bio_cipher(const EVP_CIPHER* cipher, const unsigned char* key,
3913d40330Schristos const unsigned char* iv)
40c7da899bSchristos {
41*b0d17251Schristos BIO *b, *mem;
4213d40330Schristos static unsigned char inp[BUF_SIZE] = { 0 };
4313d40330Schristos unsigned char out[BUF_SIZE], ref[BUF_SIZE];
44c7da899bSchristos int i, lref, len;
45c7da899bSchristos
46c7da899bSchristos /* Fill buffer with non-zero data so that over steps can be detected */
4713d40330Schristos if (!TEST_int_gt(RAND_bytes(inp, DATA_SIZE), 0))
4813d40330Schristos return 0;
49c7da899bSchristos
5013d40330Schristos /* Encrypt tests */
51c7da899bSchristos
52c7da899bSchristos /* reference output for single-chunk operation */
53c7da899bSchristos b = BIO_new(BIO_f_cipher());
54*b0d17251Schristos if (!TEST_ptr(b))
5513d40330Schristos return 0;
56*b0d17251Schristos if (!TEST_true(BIO_set_cipher(b, cipher, key, iv, ENCRYPT)))
57*b0d17251Schristos goto err;
58*b0d17251Schristos mem = BIO_new_mem_buf(inp, DATA_SIZE);
59*b0d17251Schristos if (!TEST_ptr(mem))
60*b0d17251Schristos goto err;
61*b0d17251Schristos BIO_push(b, mem);
62c7da899bSchristos lref = BIO_read(b, ref, sizeof(ref));
63c7da899bSchristos BIO_free_all(b);
64c7da899bSchristos
65c7da899bSchristos /* perform split operations and compare to reference */
66c7da899bSchristos for (i = 1; i < lref; i++) {
67c7da899bSchristos b = BIO_new(BIO_f_cipher());
68*b0d17251Schristos if (!TEST_ptr(b))
69*b0d17251Schristos return 0;
7013d40330Schristos if (!TEST_true(BIO_set_cipher(b, cipher, key, iv, ENCRYPT))) {
7113d40330Schristos TEST_info("Split encrypt failed @ operation %d", i);
72*b0d17251Schristos goto err;
7313d40330Schristos }
74*b0d17251Schristos mem = BIO_new_mem_buf(inp, DATA_SIZE);
75*b0d17251Schristos if (!TEST_ptr(mem))
76*b0d17251Schristos goto err;
77*b0d17251Schristos BIO_push(b, mem);
78c7da899bSchristos memset(out, 0, sizeof(out));
79c7da899bSchristos out[i] = ~ref[i];
80c7da899bSchristos len = BIO_read(b, out, i);
81c7da899bSchristos /* check for overstep */
8213d40330Schristos if (!TEST_uchar_eq(out[i], (unsigned char)~ref[i])) {
8313d40330Schristos TEST_info("Encrypt overstep check failed @ operation %d", i);
84*b0d17251Schristos goto err;
8513d40330Schristos }
8613d40330Schristos len += BIO_read(b, out + len, sizeof(out) - len);
8713d40330Schristos BIO_free_all(b);
8813d40330Schristos
8913d40330Schristos if (!TEST_mem_eq(out, len, ref, lref)) {
9013d40330Schristos TEST_info("Encrypt compare failed @ operation %d", i);
9113d40330Schristos return 0;
9213d40330Schristos }
9313d40330Schristos }
9413d40330Schristos
9513d40330Schristos /* perform small-chunk operations and compare to reference */
9613d40330Schristos for (i = 1; i < lref / 2; i++) {
9713d40330Schristos int delta;
9813d40330Schristos
9913d40330Schristos b = BIO_new(BIO_f_cipher());
100*b0d17251Schristos if (!TEST_ptr(b))
101*b0d17251Schristos return 0;
10213d40330Schristos if (!TEST_true(BIO_set_cipher(b, cipher, key, iv, ENCRYPT))) {
10313d40330Schristos TEST_info("Small chunk encrypt failed @ operation %d", i);
104*b0d17251Schristos goto err;
10513d40330Schristos }
106*b0d17251Schristos mem = BIO_new_mem_buf(inp, DATA_SIZE);
107*b0d17251Schristos if (!TEST_ptr(mem))
108*b0d17251Schristos goto err;
109*b0d17251Schristos BIO_push(b, mem);
11013d40330Schristos memset(out, 0, sizeof(out));
11113d40330Schristos for (len = 0; (delta = BIO_read(b, out + len, i)); ) {
11213d40330Schristos len += delta;
11313d40330Schristos }
11413d40330Schristos BIO_free_all(b);
11513d40330Schristos
11613d40330Schristos if (!TEST_mem_eq(out, len, ref, lref)) {
11713d40330Schristos TEST_info("Small chunk encrypt compare failed @ operation %d", i);
11813d40330Schristos return 0;
11913d40330Schristos }
12013d40330Schristos }
12113d40330Schristos
12213d40330Schristos /* Decrypt tests */
12313d40330Schristos
12413d40330Schristos /* reference output for single-chunk operation */
12513d40330Schristos b = BIO_new(BIO_f_cipher());
126*b0d17251Schristos if (!TEST_ptr(b))
12713d40330Schristos return 0;
128*b0d17251Schristos if (!TEST_true(BIO_set_cipher(b, cipher, key, iv, DECRYPT)))
129*b0d17251Schristos goto err;
13013d40330Schristos /* Use original reference output as input */
131*b0d17251Schristos mem = BIO_new_mem_buf(ref, lref);
132*b0d17251Schristos if (!TEST_ptr(mem))
133*b0d17251Schristos goto err;
134*b0d17251Schristos BIO_push(b, mem);
13513d40330Schristos (void)BIO_flush(b);
13613d40330Schristos memset(out, 0, sizeof(out));
13713d40330Schristos len = BIO_read(b, out, sizeof(out));
13813d40330Schristos BIO_free_all(b);
13913d40330Schristos
14013d40330Schristos if (!TEST_mem_eq(inp, DATA_SIZE, out, len))
14113d40330Schristos return 0;
14213d40330Schristos
14313d40330Schristos /* perform split operations and compare to reference */
14413d40330Schristos for (i = 1; i < lref; i++) {
14513d40330Schristos b = BIO_new(BIO_f_cipher());
146*b0d17251Schristos if (!TEST_ptr(b))
147*b0d17251Schristos return 0;
14813d40330Schristos if (!TEST_true(BIO_set_cipher(b, cipher, key, iv, DECRYPT))) {
14913d40330Schristos TEST_info("Split decrypt failed @ operation %d", i);
150*b0d17251Schristos goto err;
15113d40330Schristos }
152*b0d17251Schristos mem = BIO_new_mem_buf(ref, lref);
153*b0d17251Schristos if (!TEST_ptr(mem))
154*b0d17251Schristos goto err;
155*b0d17251Schristos BIO_push(b, mem);
15613d40330Schristos memset(out, 0, sizeof(out));
15713d40330Schristos out[i] = ~ref[i];
15813d40330Schristos len = BIO_read(b, out, i);
15913d40330Schristos /* check for overstep */
16013d40330Schristos if (!TEST_uchar_eq(out[i], (unsigned char)~ref[i])) {
16113d40330Schristos TEST_info("Decrypt overstep check failed @ operation %d", i);
162*b0d17251Schristos goto err;
16313d40330Schristos }
16413d40330Schristos len += BIO_read(b, out + len, sizeof(out) - len);
16513d40330Schristos BIO_free_all(b);
16613d40330Schristos
16713d40330Schristos if (!TEST_mem_eq(inp, DATA_SIZE, out, len)) {
16813d40330Schristos TEST_info("Decrypt compare failed @ operation %d", i);
16913d40330Schristos return 0;
17013d40330Schristos }
17113d40330Schristos }
17213d40330Schristos
17313d40330Schristos /* perform small-chunk operations and compare to reference */
17413d40330Schristos for (i = 1; i < lref / 2; i++) {
17513d40330Schristos int delta;
17613d40330Schristos
17713d40330Schristos b = BIO_new(BIO_f_cipher());
178*b0d17251Schristos if (!TEST_ptr(b))
179*b0d17251Schristos return 0;
18013d40330Schristos if (!TEST_true(BIO_set_cipher(b, cipher, key, iv, DECRYPT))) {
18113d40330Schristos TEST_info("Small chunk decrypt failed @ operation %d", i);
182*b0d17251Schristos goto err;
18313d40330Schristos }
184*b0d17251Schristos mem = BIO_new_mem_buf(ref, lref);
185*b0d17251Schristos if (!TEST_ptr(mem))
186*b0d17251Schristos goto err;
187*b0d17251Schristos BIO_push(b, mem);
18813d40330Schristos memset(out, 0, sizeof(out));
18913d40330Schristos for (len = 0; (delta = BIO_read(b, out + len, i)); ) {
19013d40330Schristos len += delta;
19113d40330Schristos }
19213d40330Schristos BIO_free_all(b);
19313d40330Schristos
19413d40330Schristos if (!TEST_mem_eq(inp, DATA_SIZE, out, len)) {
19513d40330Schristos TEST_info("Small chunk decrypt compare failed @ operation %d", i);
19613d40330Schristos return 0;
19713d40330Schristos }
19813d40330Schristos }
19913d40330Schristos
200c7da899bSchristos return 1;
201*b0d17251Schristos
202*b0d17251Schristos err:
203*b0d17251Schristos BIO_free_all(b);
204*b0d17251Schristos return 0;
205c7da899bSchristos }
206c7da899bSchristos
do_test_bio_cipher(const EVP_CIPHER * cipher,int idx)20713d40330Schristos static int do_test_bio_cipher(const EVP_CIPHER* cipher, int idx)
20813d40330Schristos {
20913d40330Schristos switch(idx)
21013d40330Schristos {
21113d40330Schristos case 0:
21213d40330Schristos return do_bio_cipher(cipher, KEY, NULL);
21313d40330Schristos case 1:
21413d40330Schristos return do_bio_cipher(cipher, KEY, IV);
215c7da899bSchristos }
216c7da899bSchristos return 0;
217c7da899bSchristos }
21813d40330Schristos
test_bio_enc_aes_128_cbc(int idx)21913d40330Schristos static int test_bio_enc_aes_128_cbc(int idx)
22013d40330Schristos {
22113d40330Schristos return do_test_bio_cipher(EVP_aes_128_cbc(), idx);
22213d40330Schristos }
22313d40330Schristos
test_bio_enc_aes_128_ctr(int idx)22413d40330Schristos static int test_bio_enc_aes_128_ctr(int idx)
22513d40330Schristos {
22613d40330Schristos return do_test_bio_cipher(EVP_aes_128_ctr(), idx);
22713d40330Schristos }
22813d40330Schristos
test_bio_enc_aes_256_cfb(int idx)22913d40330Schristos static int test_bio_enc_aes_256_cfb(int idx)
23013d40330Schristos {
23113d40330Schristos return do_test_bio_cipher(EVP_aes_256_cfb(), idx);
23213d40330Schristos }
23313d40330Schristos
test_bio_enc_aes_256_ofb(int idx)23413d40330Schristos static int test_bio_enc_aes_256_ofb(int idx)
23513d40330Schristos {
23613d40330Schristos return do_test_bio_cipher(EVP_aes_256_ofb(), idx);
23713d40330Schristos }
23813d40330Schristos
23913d40330Schristos # ifndef OPENSSL_NO_CHACHA
test_bio_enc_chacha20(int idx)24013d40330Schristos static int test_bio_enc_chacha20(int idx)
24113d40330Schristos {
24213d40330Schristos return do_test_bio_cipher(EVP_chacha20(), idx);
24313d40330Schristos }
24413d40330Schristos
24513d40330Schristos # ifndef OPENSSL_NO_POLY1305
test_bio_enc_chacha20_poly1305(int idx)24613d40330Schristos static int test_bio_enc_chacha20_poly1305(int idx)
24713d40330Schristos {
24813d40330Schristos return do_test_bio_cipher(EVP_chacha20_poly1305(), idx);
24913d40330Schristos }
25013d40330Schristos # endif
25113d40330Schristos # endif
25213d40330Schristos
setup_tests(void)25313d40330Schristos int setup_tests(void)
25413d40330Schristos {
25513d40330Schristos ADD_ALL_TESTS(test_bio_enc_aes_128_cbc, 2);
25613d40330Schristos ADD_ALL_TESTS(test_bio_enc_aes_128_ctr, 2);
25713d40330Schristos ADD_ALL_TESTS(test_bio_enc_aes_256_cfb, 2);
25813d40330Schristos ADD_ALL_TESTS(test_bio_enc_aes_256_ofb, 2);
25913d40330Schristos # ifndef OPENSSL_NO_CHACHA
26013d40330Schristos ADD_ALL_TESTS(test_bio_enc_chacha20, 2);
26113d40330Schristos # ifndef OPENSSL_NO_POLY1305
26213d40330Schristos ADD_ALL_TESTS(test_bio_enc_chacha20_poly1305, 2);
26313d40330Schristos # endif
26413d40330Schristos # endif
26513d40330Schristos return 1;
26613d40330Schristos }
267