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 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 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 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 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 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 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 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 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 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