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