• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (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;
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_true(BIO_set_cipher(b, cipher, key, iv, ENCRYPT)))
55         return 0;
56     BIO_push(b, BIO_new_mem_buf(inp, DATA_SIZE));
57     lref = BIO_read(b, ref, sizeof(ref));
58     BIO_free_all(b);
59 
60     /* perform split operations and compare to reference */
61     for (i = 1; i < lref; i++) {
62         b = BIO_new(BIO_f_cipher());
63         if (!TEST_true(BIO_set_cipher(b, cipher, key, iv, ENCRYPT))) {
64             TEST_info("Split encrypt failed @ operation %d", i);
65             return 0;
66         }
67         BIO_push(b, BIO_new_mem_buf(inp, DATA_SIZE));
68         memset(out, 0, sizeof(out));
69         out[i] = ~ref[i];
70         len = BIO_read(b, out, i);
71         /* check for overstep */
72         if (!TEST_uchar_eq(out[i], (unsigned char)~ref[i])) {
73             TEST_info("Encrypt overstep check failed @ operation %d", i);
74             return 0;
75         }
76         len += BIO_read(b, out + len, sizeof(out) - len);
77         BIO_free_all(b);
78 
79         if (!TEST_mem_eq(out, len, ref, lref)) {
80             TEST_info("Encrypt compare failed @ operation %d", i);
81             return 0;
82         }
83     }
84 
85     /* perform small-chunk operations and compare to reference */
86     for (i = 1; i < lref / 2; i++) {
87         int delta;
88 
89         b = BIO_new(BIO_f_cipher());
90         if (!TEST_true(BIO_set_cipher(b, cipher, key, iv, ENCRYPT))) {
91             TEST_info("Small chunk encrypt failed @ operation %d", i);
92             return 0;
93         }
94         BIO_push(b, BIO_new_mem_buf(inp, DATA_SIZE));
95         memset(out, 0, sizeof(out));
96         for (len = 0; (delta = BIO_read(b, out + len, i)); ) {
97             len += delta;
98         }
99         BIO_free_all(b);
100 
101         if (!TEST_mem_eq(out, len, ref, lref)) {
102             TEST_info("Small chunk encrypt compare failed @ operation %d", i);
103             return 0;
104         }
105     }
106 
107     /* Decrypt tests */
108 
109     /* reference output for single-chunk operation */
110     b = BIO_new(BIO_f_cipher());
111     if (!TEST_true(BIO_set_cipher(b, cipher, key, iv, DECRYPT)))
112         return 0;
113     /* Use original reference output as input */
114     BIO_push(b, BIO_new_mem_buf(ref, lref));
115     (void)BIO_flush(b);
116     memset(out, 0, sizeof(out));
117     len = BIO_read(b, out, sizeof(out));
118     BIO_free_all(b);
119 
120     if (!TEST_mem_eq(inp, DATA_SIZE, out, len))
121         return 0;
122 
123     /* perform split operations and compare to reference */
124     for (i = 1; i < lref; i++) {
125         b = BIO_new(BIO_f_cipher());
126         if (!TEST_true(BIO_set_cipher(b, cipher, key, iv, DECRYPT))) {
127             TEST_info("Split decrypt failed @ operation %d", i);
128             return 0;
129         }
130         BIO_push(b, BIO_new_mem_buf(ref, lref));
131         memset(out, 0, sizeof(out));
132         out[i] = ~ref[i];
133         len = BIO_read(b, out, i);
134         /* check for overstep */
135         if (!TEST_uchar_eq(out[i], (unsigned char)~ref[i])) {
136             TEST_info("Decrypt overstep check failed @ operation %d", i);
137             return 0;
138         }
139         len += BIO_read(b, out + len, sizeof(out) - len);
140         BIO_free_all(b);
141 
142         if (!TEST_mem_eq(inp, DATA_SIZE, out, len)) {
143             TEST_info("Decrypt compare failed @ operation %d", i);
144             return 0;
145         }
146     }
147 
148     /* perform small-chunk operations and compare to reference */
149     for (i = 1; i < lref / 2; i++) {
150         int delta;
151 
152         b = BIO_new(BIO_f_cipher());
153         if (!TEST_true(BIO_set_cipher(b, cipher, key, iv, DECRYPT))) {
154             TEST_info("Small chunk decrypt failed @ operation %d", i);
155             return 0;
156         }
157         BIO_push(b, BIO_new_mem_buf(ref, lref));
158         memset(out, 0, sizeof(out));
159         for (len = 0; (delta = BIO_read(b, out + len, i)); ) {
160             len += delta;
161         }
162         BIO_free_all(b);
163 
164         if (!TEST_mem_eq(inp, DATA_SIZE, out, len)) {
165             TEST_info("Small chunk decrypt compare failed @ operation %d", i);
166             return 0;
167         }
168     }
169 
170     return 1;
171 }
172 
do_test_bio_cipher(const EVP_CIPHER * cipher,int idx)173 static int do_test_bio_cipher(const EVP_CIPHER* cipher, int idx)
174 {
175     switch(idx)
176     {
177         case 0:
178             return do_bio_cipher(cipher, KEY, NULL);
179         case 1:
180             return do_bio_cipher(cipher, KEY, IV);
181     }
182     return 0;
183 }
184 
test_bio_enc_aes_128_cbc(int idx)185 static int test_bio_enc_aes_128_cbc(int idx)
186 {
187     return do_test_bio_cipher(EVP_aes_128_cbc(), idx);
188 }
189 
test_bio_enc_aes_128_ctr(int idx)190 static int test_bio_enc_aes_128_ctr(int idx)
191 {
192     return do_test_bio_cipher(EVP_aes_128_ctr(), idx);
193 }
194 
test_bio_enc_aes_256_cfb(int idx)195 static int test_bio_enc_aes_256_cfb(int idx)
196 {
197     return do_test_bio_cipher(EVP_aes_256_cfb(), idx);
198 }
199 
test_bio_enc_aes_256_ofb(int idx)200 static int test_bio_enc_aes_256_ofb(int idx)
201 {
202     return do_test_bio_cipher(EVP_aes_256_ofb(), idx);
203 }
204 
205 # ifndef OPENSSL_NO_CHACHA
test_bio_enc_chacha20(int idx)206 static int test_bio_enc_chacha20(int idx)
207 {
208     return do_test_bio_cipher(EVP_chacha20(), idx);
209 }
210 
211 #  ifndef OPENSSL_NO_POLY1305
test_bio_enc_chacha20_poly1305(int idx)212 static int test_bio_enc_chacha20_poly1305(int idx)
213 {
214     return do_test_bio_cipher(EVP_chacha20_poly1305(), idx);
215 }
216 #  endif
217 # endif
218 
setup_tests(void)219 int setup_tests(void)
220 {
221     ADD_ALL_TESTS(test_bio_enc_aes_128_cbc, 2);
222     ADD_ALL_TESTS(test_bio_enc_aes_128_ctr, 2);
223     ADD_ALL_TESTS(test_bio_enc_aes_256_cfb, 2);
224     ADD_ALL_TESTS(test_bio_enc_aes_256_ofb, 2);
225 # ifndef OPENSSL_NO_CHACHA
226     ADD_ALL_TESTS(test_bio_enc_chacha20, 2);
227 #  ifndef OPENSSL_NO_POLY1305
228     ADD_ALL_TESTS(test_bio_enc_chacha20_poly1305, 2);
229 #  endif
230 # endif
231     return 1;
232 }
233