1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci#include <stdio.h>
10e1051a39Sopenharmony_ci#include <string.h>
11e1051a39Sopenharmony_ci#include <openssl/evp.h>
12e1051a39Sopenharmony_ci#include <openssl/bio.h>
13e1051a39Sopenharmony_ci#include <openssl/rand.h>
14e1051a39Sopenharmony_ci
15e1051a39Sopenharmony_ci#include "testutil.h"
16e1051a39Sopenharmony_ci
17e1051a39Sopenharmony_ci#define ENCRYPT  1
18e1051a39Sopenharmony_ci#define DECRYPT  0
19e1051a39Sopenharmony_ci
20e1051a39Sopenharmony_ci#define DATA_SIZE    1024
21e1051a39Sopenharmony_ci#define MAX_IV       32
22e1051a39Sopenharmony_ci#define BUF_SIZE     (DATA_SIZE + MAX_IV)
23e1051a39Sopenharmony_ci
24e1051a39Sopenharmony_cistatic const unsigned char KEY[] = {
25e1051a39Sopenharmony_ci    0x51, 0x50, 0xd1, 0x77, 0x2f, 0x50, 0x83, 0x4a,
26e1051a39Sopenharmony_ci    0x50, 0x3e, 0x06, 0x9a, 0x97, 0x3f, 0xbd, 0x7c,
27e1051a39Sopenharmony_ci    0xe6, 0x1c, 0x43, 0x2b, 0x72, 0x0b, 0x19, 0xd1,
28e1051a39Sopenharmony_ci    0x8e, 0xc8, 0xd8, 0x4b, 0xdc, 0x63, 0x15, 0x1b
29e1051a39Sopenharmony_ci};
30e1051a39Sopenharmony_ci
31e1051a39Sopenharmony_cistatic const unsigned char IV[] = {
32e1051a39Sopenharmony_ci    0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
33e1051a39Sopenharmony_ci    0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
34e1051a39Sopenharmony_ci    0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
35e1051a39Sopenharmony_ci    0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
36e1051a39Sopenharmony_ci};
37e1051a39Sopenharmony_ci
38e1051a39Sopenharmony_cistatic int do_bio_cipher(const EVP_CIPHER* cipher, const unsigned char* key,
39e1051a39Sopenharmony_ci    const unsigned char* iv)
40e1051a39Sopenharmony_ci{
41e1051a39Sopenharmony_ci    BIO *b, *mem;
42e1051a39Sopenharmony_ci    static unsigned char inp[BUF_SIZE] = { 0 };
43e1051a39Sopenharmony_ci    unsigned char out[BUF_SIZE], ref[BUF_SIZE];
44e1051a39Sopenharmony_ci    int i, lref, len;
45e1051a39Sopenharmony_ci
46e1051a39Sopenharmony_ci    /* Fill buffer with non-zero data so that over steps can be detected */
47e1051a39Sopenharmony_ci    if (!TEST_int_gt(RAND_bytes(inp, DATA_SIZE), 0))
48e1051a39Sopenharmony_ci        return 0;
49e1051a39Sopenharmony_ci
50e1051a39Sopenharmony_ci    /* Encrypt tests */
51e1051a39Sopenharmony_ci
52e1051a39Sopenharmony_ci    /* reference output for single-chunk operation */
53e1051a39Sopenharmony_ci    b = BIO_new(BIO_f_cipher());
54e1051a39Sopenharmony_ci    if (!TEST_ptr(b))
55e1051a39Sopenharmony_ci        return 0;
56e1051a39Sopenharmony_ci    if (!TEST_true(BIO_set_cipher(b, cipher, key, iv, ENCRYPT)))
57e1051a39Sopenharmony_ci        goto err;
58e1051a39Sopenharmony_ci    mem = BIO_new_mem_buf(inp, DATA_SIZE);
59e1051a39Sopenharmony_ci    if (!TEST_ptr(mem))
60e1051a39Sopenharmony_ci        goto err;
61e1051a39Sopenharmony_ci    BIO_push(b, mem);
62e1051a39Sopenharmony_ci    lref = BIO_read(b, ref, sizeof(ref));
63e1051a39Sopenharmony_ci    BIO_free_all(b);
64e1051a39Sopenharmony_ci
65e1051a39Sopenharmony_ci    /* perform split operations and compare to reference */
66e1051a39Sopenharmony_ci    for (i = 1; i < lref; i++) {
67e1051a39Sopenharmony_ci        b = BIO_new(BIO_f_cipher());
68e1051a39Sopenharmony_ci        if (!TEST_ptr(b))
69e1051a39Sopenharmony_ci            return 0;
70e1051a39Sopenharmony_ci        if (!TEST_true(BIO_set_cipher(b, cipher, key, iv, ENCRYPT))) {
71e1051a39Sopenharmony_ci            TEST_info("Split encrypt failed @ operation %d", i);
72e1051a39Sopenharmony_ci            goto err;
73e1051a39Sopenharmony_ci        }
74e1051a39Sopenharmony_ci        mem = BIO_new_mem_buf(inp, DATA_SIZE);
75e1051a39Sopenharmony_ci        if (!TEST_ptr(mem))
76e1051a39Sopenharmony_ci            goto err;
77e1051a39Sopenharmony_ci        BIO_push(b, mem);
78e1051a39Sopenharmony_ci        memset(out, 0, sizeof(out));
79e1051a39Sopenharmony_ci        out[i] = ~ref[i];
80e1051a39Sopenharmony_ci        len = BIO_read(b, out, i);
81e1051a39Sopenharmony_ci        /* check for overstep */
82e1051a39Sopenharmony_ci        if (!TEST_uchar_eq(out[i], (unsigned char)~ref[i])) {
83e1051a39Sopenharmony_ci            TEST_info("Encrypt overstep check failed @ operation %d", i);
84e1051a39Sopenharmony_ci            goto err;
85e1051a39Sopenharmony_ci        }
86e1051a39Sopenharmony_ci        len += BIO_read(b, out + len, sizeof(out) - len);
87e1051a39Sopenharmony_ci        BIO_free_all(b);
88e1051a39Sopenharmony_ci
89e1051a39Sopenharmony_ci        if (!TEST_mem_eq(out, len, ref, lref)) {
90e1051a39Sopenharmony_ci            TEST_info("Encrypt compare failed @ operation %d", i);
91e1051a39Sopenharmony_ci            return 0;
92e1051a39Sopenharmony_ci        }
93e1051a39Sopenharmony_ci    }
94e1051a39Sopenharmony_ci
95e1051a39Sopenharmony_ci    /* perform small-chunk operations and compare to reference */
96e1051a39Sopenharmony_ci    for (i = 1; i < lref / 2; i++) {
97e1051a39Sopenharmony_ci        int delta;
98e1051a39Sopenharmony_ci
99e1051a39Sopenharmony_ci        b = BIO_new(BIO_f_cipher());
100e1051a39Sopenharmony_ci        if (!TEST_ptr(b))
101e1051a39Sopenharmony_ci            return 0;
102e1051a39Sopenharmony_ci        if (!TEST_true(BIO_set_cipher(b, cipher, key, iv, ENCRYPT))) {
103e1051a39Sopenharmony_ci            TEST_info("Small chunk encrypt failed @ operation %d", i);
104e1051a39Sopenharmony_ci            goto err;
105e1051a39Sopenharmony_ci        }
106e1051a39Sopenharmony_ci        mem = BIO_new_mem_buf(inp, DATA_SIZE);
107e1051a39Sopenharmony_ci        if (!TEST_ptr(mem))
108e1051a39Sopenharmony_ci            goto err;
109e1051a39Sopenharmony_ci        BIO_push(b, mem);
110e1051a39Sopenharmony_ci        memset(out, 0, sizeof(out));
111e1051a39Sopenharmony_ci        for (len = 0; (delta = BIO_read(b, out + len, i)); ) {
112e1051a39Sopenharmony_ci            len += delta;
113e1051a39Sopenharmony_ci        }
114e1051a39Sopenharmony_ci        BIO_free_all(b);
115e1051a39Sopenharmony_ci
116e1051a39Sopenharmony_ci        if (!TEST_mem_eq(out, len, ref, lref)) {
117e1051a39Sopenharmony_ci            TEST_info("Small chunk encrypt compare failed @ operation %d", i);
118e1051a39Sopenharmony_ci            return 0;
119e1051a39Sopenharmony_ci        }
120e1051a39Sopenharmony_ci    }
121e1051a39Sopenharmony_ci
122e1051a39Sopenharmony_ci    /* Decrypt tests */
123e1051a39Sopenharmony_ci
124e1051a39Sopenharmony_ci    /* reference output for single-chunk operation */
125e1051a39Sopenharmony_ci    b = BIO_new(BIO_f_cipher());
126e1051a39Sopenharmony_ci    if (!TEST_ptr(b))
127e1051a39Sopenharmony_ci        return 0;
128e1051a39Sopenharmony_ci    if (!TEST_true(BIO_set_cipher(b, cipher, key, iv, DECRYPT)))
129e1051a39Sopenharmony_ci        goto err;
130e1051a39Sopenharmony_ci    /* Use original reference output as input */
131e1051a39Sopenharmony_ci    mem = BIO_new_mem_buf(ref, lref);
132e1051a39Sopenharmony_ci    if (!TEST_ptr(mem))
133e1051a39Sopenharmony_ci        goto err;
134e1051a39Sopenharmony_ci    BIO_push(b, mem);
135e1051a39Sopenharmony_ci    (void)BIO_flush(b);
136e1051a39Sopenharmony_ci    memset(out, 0, sizeof(out));
137e1051a39Sopenharmony_ci    len = BIO_read(b, out, sizeof(out));
138e1051a39Sopenharmony_ci    BIO_free_all(b);
139e1051a39Sopenharmony_ci
140e1051a39Sopenharmony_ci    if (!TEST_mem_eq(inp, DATA_SIZE, out, len))
141e1051a39Sopenharmony_ci        return 0;
142e1051a39Sopenharmony_ci
143e1051a39Sopenharmony_ci    /* perform split operations and compare to reference */
144e1051a39Sopenharmony_ci    for (i = 1; i < lref; i++) {
145e1051a39Sopenharmony_ci        b = BIO_new(BIO_f_cipher());
146e1051a39Sopenharmony_ci        if (!TEST_ptr(b))
147e1051a39Sopenharmony_ci            return 0;
148e1051a39Sopenharmony_ci        if (!TEST_true(BIO_set_cipher(b, cipher, key, iv, DECRYPT))) {
149e1051a39Sopenharmony_ci            TEST_info("Split decrypt failed @ operation %d", i);
150e1051a39Sopenharmony_ci            goto err;
151e1051a39Sopenharmony_ci        }
152e1051a39Sopenharmony_ci        mem = BIO_new_mem_buf(ref, lref);
153e1051a39Sopenharmony_ci        if (!TEST_ptr(mem))
154e1051a39Sopenharmony_ci            goto err;
155e1051a39Sopenharmony_ci        BIO_push(b, mem);
156e1051a39Sopenharmony_ci        memset(out, 0, sizeof(out));
157e1051a39Sopenharmony_ci        out[i] = ~ref[i];
158e1051a39Sopenharmony_ci        len = BIO_read(b, out, i);
159e1051a39Sopenharmony_ci        /* check for overstep */
160e1051a39Sopenharmony_ci        if (!TEST_uchar_eq(out[i], (unsigned char)~ref[i])) {
161e1051a39Sopenharmony_ci            TEST_info("Decrypt overstep check failed @ operation %d", i);
162e1051a39Sopenharmony_ci            goto err;
163e1051a39Sopenharmony_ci        }
164e1051a39Sopenharmony_ci        len += BIO_read(b, out + len, sizeof(out) - len);
165e1051a39Sopenharmony_ci        BIO_free_all(b);
166e1051a39Sopenharmony_ci
167e1051a39Sopenharmony_ci        if (!TEST_mem_eq(inp, DATA_SIZE, out, len)) {
168e1051a39Sopenharmony_ci            TEST_info("Decrypt compare failed @ operation %d", i);
169e1051a39Sopenharmony_ci            return 0;
170e1051a39Sopenharmony_ci        }
171e1051a39Sopenharmony_ci    }
172e1051a39Sopenharmony_ci
173e1051a39Sopenharmony_ci    /* perform small-chunk operations and compare to reference */
174e1051a39Sopenharmony_ci    for (i = 1; i < lref / 2; i++) {
175e1051a39Sopenharmony_ci        int delta;
176e1051a39Sopenharmony_ci
177e1051a39Sopenharmony_ci        b = BIO_new(BIO_f_cipher());
178e1051a39Sopenharmony_ci        if (!TEST_ptr(b))
179e1051a39Sopenharmony_ci            return 0;
180e1051a39Sopenharmony_ci        if (!TEST_true(BIO_set_cipher(b, cipher, key, iv, DECRYPT))) {
181e1051a39Sopenharmony_ci            TEST_info("Small chunk decrypt failed @ operation %d", i);
182e1051a39Sopenharmony_ci            goto err;
183e1051a39Sopenharmony_ci        }
184e1051a39Sopenharmony_ci        mem = BIO_new_mem_buf(ref, lref);
185e1051a39Sopenharmony_ci        if (!TEST_ptr(mem))
186e1051a39Sopenharmony_ci            goto err;
187e1051a39Sopenharmony_ci        BIO_push(b, mem);
188e1051a39Sopenharmony_ci        memset(out, 0, sizeof(out));
189e1051a39Sopenharmony_ci        for (len = 0; (delta = BIO_read(b, out + len, i)); ) {
190e1051a39Sopenharmony_ci            len += delta;
191e1051a39Sopenharmony_ci        }
192e1051a39Sopenharmony_ci        BIO_free_all(b);
193e1051a39Sopenharmony_ci
194e1051a39Sopenharmony_ci        if (!TEST_mem_eq(inp, DATA_SIZE, out, len)) {
195e1051a39Sopenharmony_ci            TEST_info("Small chunk decrypt compare failed @ operation %d", i);
196e1051a39Sopenharmony_ci            return 0;
197e1051a39Sopenharmony_ci        }
198e1051a39Sopenharmony_ci    }
199e1051a39Sopenharmony_ci
200e1051a39Sopenharmony_ci    return 1;
201e1051a39Sopenharmony_ci
202e1051a39Sopenharmony_cierr:
203e1051a39Sopenharmony_ci    BIO_free_all(b);
204e1051a39Sopenharmony_ci    return 0;
205e1051a39Sopenharmony_ci}
206e1051a39Sopenharmony_ci
207e1051a39Sopenharmony_cistatic int do_test_bio_cipher(const EVP_CIPHER* cipher, int idx)
208e1051a39Sopenharmony_ci{
209e1051a39Sopenharmony_ci    switch(idx)
210e1051a39Sopenharmony_ci    {
211e1051a39Sopenharmony_ci        case 0:
212e1051a39Sopenharmony_ci            return do_bio_cipher(cipher, KEY, NULL);
213e1051a39Sopenharmony_ci        case 1:
214e1051a39Sopenharmony_ci            return do_bio_cipher(cipher, KEY, IV);
215e1051a39Sopenharmony_ci    }
216e1051a39Sopenharmony_ci    return 0;
217e1051a39Sopenharmony_ci}
218e1051a39Sopenharmony_ci
219e1051a39Sopenharmony_cistatic int test_bio_enc_aes_128_cbc(int idx)
220e1051a39Sopenharmony_ci{
221e1051a39Sopenharmony_ci    return do_test_bio_cipher(EVP_aes_128_cbc(), idx);
222e1051a39Sopenharmony_ci}
223e1051a39Sopenharmony_ci
224e1051a39Sopenharmony_cistatic int test_bio_enc_aes_128_ctr(int idx)
225e1051a39Sopenharmony_ci{
226e1051a39Sopenharmony_ci    return do_test_bio_cipher(EVP_aes_128_ctr(), idx);
227e1051a39Sopenharmony_ci}
228e1051a39Sopenharmony_ci
229e1051a39Sopenharmony_cistatic int test_bio_enc_aes_256_cfb(int idx)
230e1051a39Sopenharmony_ci{
231e1051a39Sopenharmony_ci    return do_test_bio_cipher(EVP_aes_256_cfb(), idx);
232e1051a39Sopenharmony_ci}
233e1051a39Sopenharmony_ci
234e1051a39Sopenharmony_cistatic int test_bio_enc_aes_256_ofb(int idx)
235e1051a39Sopenharmony_ci{
236e1051a39Sopenharmony_ci    return do_test_bio_cipher(EVP_aes_256_ofb(), idx);
237e1051a39Sopenharmony_ci}
238e1051a39Sopenharmony_ci
239e1051a39Sopenharmony_ci# ifndef OPENSSL_NO_CHACHA
240e1051a39Sopenharmony_cistatic int test_bio_enc_chacha20(int idx)
241e1051a39Sopenharmony_ci{
242e1051a39Sopenharmony_ci    return do_test_bio_cipher(EVP_chacha20(), idx);
243e1051a39Sopenharmony_ci}
244e1051a39Sopenharmony_ci
245e1051a39Sopenharmony_ci#  ifndef OPENSSL_NO_POLY1305
246e1051a39Sopenharmony_cistatic int test_bio_enc_chacha20_poly1305(int idx)
247e1051a39Sopenharmony_ci{
248e1051a39Sopenharmony_ci    return do_test_bio_cipher(EVP_chacha20_poly1305(), idx);
249e1051a39Sopenharmony_ci}
250e1051a39Sopenharmony_ci#  endif
251e1051a39Sopenharmony_ci# endif
252e1051a39Sopenharmony_ci
253e1051a39Sopenharmony_ciint setup_tests(void)
254e1051a39Sopenharmony_ci{
255e1051a39Sopenharmony_ci    ADD_ALL_TESTS(test_bio_enc_aes_128_cbc, 2);
256e1051a39Sopenharmony_ci    ADD_ALL_TESTS(test_bio_enc_aes_128_ctr, 2);
257e1051a39Sopenharmony_ci    ADD_ALL_TESTS(test_bio_enc_aes_256_cfb, 2);
258e1051a39Sopenharmony_ci    ADD_ALL_TESTS(test_bio_enc_aes_256_ofb, 2);
259e1051a39Sopenharmony_ci# ifndef OPENSSL_NO_CHACHA
260e1051a39Sopenharmony_ci    ADD_ALL_TESTS(test_bio_enc_chacha20, 2);
261e1051a39Sopenharmony_ci#  ifndef OPENSSL_NO_POLY1305
262e1051a39Sopenharmony_ci    ADD_ALL_TESTS(test_bio_enc_chacha20_poly1305, 2);
263e1051a39Sopenharmony_ci#  endif
264e1051a39Sopenharmony_ci# endif
265e1051a39Sopenharmony_ci    return 1;
266e1051a39Sopenharmony_ci}
267