bio_enc_test.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. /*
  2. * Copyright 2016-2025 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. #include "testutil.h"
  15. #define ENCRYPT 1
  16. #define DECRYPT 0
  17. #define DATA_SIZE 1024
  18. #define MAX_IV 32
  19. #define BUF_SIZE (DATA_SIZE + MAX_IV)
  20. static const unsigned char KEY[] = {
  21. 0x51, 0x50, 0xd1, 0x77, 0x2f, 0x50, 0x83, 0x4a,
  22. 0x50, 0x3e, 0x06, 0x9a, 0x97, 0x3f, 0xbd, 0x7c,
  23. 0xe6, 0x1c, 0x43, 0x2b, 0x72, 0x0b, 0x19, 0xd1,
  24. 0x8e, 0xc8, 0xd8, 0x4b, 0xdc, 0x63, 0x15, 0x1b
  25. };
  26. static const unsigned char IV[] = {
  27. 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
  28. 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
  29. 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
  30. 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
  31. };
  32. static int do_bio_cipher(const EVP_CIPHER* cipher, const unsigned char* key,
  33. const unsigned char* iv)
  34. {
  35. BIO *b, *mem;
  36. static unsigned char inp[BUF_SIZE] = { 0 };
  37. unsigned char out[BUF_SIZE], ref[BUF_SIZE];
  38. int i, lref, len;
  39. /* Fill buffer with non-zero data so that over steps can be detected */
  40. if (!TEST_int_gt(RAND_bytes(inp, DATA_SIZE), 0))
  41. return 0;
  42. /* Encrypt tests */
  43. /* reference output for single-chunk operation */
  44. b = BIO_new(BIO_f_cipher());
  45. if (!TEST_ptr(b))
  46. return 0;
  47. if (!TEST_true(BIO_set_cipher(b, cipher, key, iv, ENCRYPT)))
  48. goto err;
  49. mem = BIO_new_mem_buf(inp, DATA_SIZE);
  50. if (!TEST_ptr(mem))
  51. goto err;
  52. BIO_push(b, mem);
  53. lref = BIO_read(b, ref, sizeof(ref));
  54. BIO_free_all(b);
  55. /* perform split operations and compare to reference */
  56. for (i = 1; i < lref; i++) {
  57. b = BIO_new(BIO_f_cipher());
  58. if (!TEST_ptr(b))
  59. return 0;
  60. if (!TEST_true(BIO_set_cipher(b, cipher, key, iv, ENCRYPT))) {
  61. TEST_info("Split encrypt failed @ operation %d", i);
  62. goto err;
  63. }
  64. mem = BIO_new_mem_buf(inp, DATA_SIZE);
  65. if (!TEST_ptr(mem))
  66. goto err;
  67. BIO_push(b, mem);
  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. goto err;
  75. }
  76. len += BIO_read(b, out + len, sizeof(out) - len);
  77. BIO_free_all(b);
  78. if (!TEST_mem_eq(out, len, ref, lref)) {
  79. TEST_info("Encrypt compare failed @ operation %d", i);
  80. return 0;
  81. }
  82. }
  83. /* perform small-chunk operations and compare to reference */
  84. for (i = 1; i < lref / 2; i++) {
  85. int delta;
  86. b = BIO_new(BIO_f_cipher());
  87. if (!TEST_ptr(b))
  88. return 0;
  89. if (!TEST_true(BIO_set_cipher(b, cipher, key, iv, ENCRYPT))) {
  90. TEST_info("Small chunk encrypt failed @ operation %d", i);
  91. goto err;
  92. }
  93. mem = BIO_new_mem_buf(inp, DATA_SIZE);
  94. if (!TEST_ptr(mem))
  95. goto err;
  96. BIO_push(b, mem);
  97. memset(out, 0, sizeof(out));
  98. for (len = 0; (delta = BIO_read(b, out + len, i)); ) {
  99. len += delta;
  100. }
  101. BIO_free_all(b);
  102. if (!TEST_mem_eq(out, len, ref, lref)) {
  103. TEST_info("Small chunk encrypt compare failed @ operation %d", i);
  104. return 0;
  105. }
  106. }
  107. /* Decrypt tests */
  108. /* reference output for single-chunk operation */
  109. b = BIO_new(BIO_f_cipher());
  110. if (!TEST_ptr(b))
  111. return 0;
  112. if (!TEST_true(BIO_set_cipher(b, cipher, key, iv, DECRYPT)))
  113. goto err;
  114. /* Use original reference output as input */
  115. mem = BIO_new_mem_buf(ref, lref);
  116. if (!TEST_ptr(mem))
  117. goto err;
  118. BIO_push(b, mem);
  119. #if 0
  120. /*
  121. * This is wrong to do, it always fails, and incorrectly ends up
  122. * calling `EVP_CipherFinal()` and setting ctx->finished = 1, ...
  123. * all of which are unwanted. But just deleting this is less
  124. * instructive to future readers of the code. Don't call BIO_flush
  125. * until you're done either reading or writing and want to finalise
  126. * the state.
  127. */
  128. (void)BIO_flush(b);
  129. #endif
  130. memset(out, 0, sizeof(out));
  131. len = BIO_read(b, out, sizeof(out));
  132. BIO_free_all(b);
  133. if (!TEST_mem_eq(inp, DATA_SIZE, out, len))
  134. return 0;
  135. /* perform split operations and compare to reference */
  136. for (i = 1; i < lref; i++) {
  137. b = BIO_new(BIO_f_cipher());
  138. if (!TEST_ptr(b))
  139. return 0;
  140. if (!TEST_true(BIO_set_cipher(b, cipher, key, iv, DECRYPT))) {
  141. TEST_info("Split decrypt failed @ operation %d", i);
  142. goto err;
  143. }
  144. mem = BIO_new_mem_buf(ref, lref);
  145. if (!TEST_ptr(mem))
  146. goto err;
  147. BIO_push(b, mem);
  148. memset(out, 0, sizeof(out));
  149. out[i] = ~ref[i];
  150. len = BIO_read(b, out, i);
  151. /* check for overstep */
  152. if (!TEST_uchar_eq(out[i], (unsigned char)~ref[i])) {
  153. TEST_info("Decrypt overstep check failed @ operation %d", i);
  154. goto err;
  155. }
  156. len += BIO_read(b, out + len, sizeof(out) - len);
  157. BIO_free_all(b);
  158. if (!TEST_mem_eq(inp, DATA_SIZE, out, len)) {
  159. TEST_info("Decrypt compare failed @ operation %d", i);
  160. return 0;
  161. }
  162. }
  163. /* perform small-chunk operations and compare to reference */
  164. for (i = 1; i < lref / 2; i++) {
  165. int delta;
  166. b = BIO_new(BIO_f_cipher());
  167. if (!TEST_ptr(b))
  168. return 0;
  169. if (!TEST_true(BIO_set_cipher(b, cipher, key, iv, DECRYPT))) {
  170. TEST_info("Small chunk decrypt failed @ operation %d", i);
  171. goto err;
  172. }
  173. mem = BIO_new_mem_buf(ref, lref);
  174. if (!TEST_ptr(mem))
  175. goto err;
  176. BIO_push(b, mem);
  177. memset(out, 0, sizeof(out));
  178. for (len = 0; (delta = BIO_read(b, out + len, i)); ) {
  179. len += delta;
  180. }
  181. BIO_free_all(b);
  182. if (!TEST_mem_eq(inp, DATA_SIZE, out, len)) {
  183. TEST_info("Small chunk decrypt compare failed @ operation %d", i);
  184. return 0;
  185. }
  186. }
  187. return 1;
  188. err:
  189. BIO_free_all(b);
  190. return 0;
  191. }
  192. static int do_test_bio_cipher(const EVP_CIPHER* cipher, int idx)
  193. {
  194. switch (idx)
  195. {
  196. case 0:
  197. return do_bio_cipher(cipher, KEY, NULL);
  198. case 1:
  199. return do_bio_cipher(cipher, KEY, IV);
  200. }
  201. return 0;
  202. }
  203. static int test_bio_enc_aes_128_cbc(int idx)
  204. {
  205. return do_test_bio_cipher(EVP_aes_128_cbc(), idx);
  206. }
  207. static int test_bio_enc_aes_128_ctr(int idx)
  208. {
  209. return do_test_bio_cipher(EVP_aes_128_ctr(), idx);
  210. }
  211. static int test_bio_enc_aes_256_cfb(int idx)
  212. {
  213. return do_test_bio_cipher(EVP_aes_256_cfb(), idx);
  214. }
  215. static int test_bio_enc_aes_256_ofb(int idx)
  216. {
  217. return do_test_bio_cipher(EVP_aes_256_ofb(), idx);
  218. }
  219. # ifndef OPENSSL_NO_CHACHA
  220. static int test_bio_enc_chacha20(int idx)
  221. {
  222. return do_test_bio_cipher(EVP_chacha20(), idx);
  223. }
  224. # ifndef OPENSSL_NO_POLY1305
  225. static int test_bio_enc_chacha20_poly1305(int idx)
  226. {
  227. return do_test_bio_cipher(EVP_chacha20_poly1305(), idx);
  228. }
  229. # endif
  230. # endif
  231. static int test_bio_enc_eof_read_flush(void)
  232. {
  233. /* Length chosen to ensure base64 encoding employs padding */
  234. const unsigned char pbuf[] = "Attack at dawn";
  235. unsigned char cbuf[16]; /* At least as long as pbuf */
  236. const EVP_CIPHER *cipher = EVP_aes_256_gcm();
  237. EVP_CIPHER_CTX *ctx = NULL;
  238. BIO *mem = NULL, *b64 = NULL, *cbio = NULL;
  239. unsigned char tag[16];
  240. size_t key_size, iv_size;
  241. int n, ret = 0;
  242. memset(tag, 0, sizeof(tag));
  243. if (!TEST_ptr(cipher)
  244. || !TEST_int_gt((key_size = EVP_CIPHER_key_length(cipher)), 0)
  245. || !TEST_int_gt((iv_size = EVP_CIPHER_iv_length(cipher)), 0)
  246. || !TEST_ptr(mem = BIO_new(BIO_s_mem()))
  247. || !TEST_ptr(b64 = BIO_new(BIO_f_base64()))
  248. || !TEST_ptr(cbio = BIO_new(BIO_f_cipher()))
  249. || !TEST_ptr(BIO_push(b64, mem))
  250. || !TEST_ptr(BIO_push(cbio, b64))
  251. || !TEST_int_gt(BIO_get_cipher_ctx(cbio, &ctx), 0)
  252. || !TEST_true(EVP_CipherInit_ex(ctx, cipher, NULL, KEY, IV, ENCRYPT))
  253. || !TEST_int_gt(BIO_write(cbio, pbuf, sizeof(pbuf) - 1), 0)
  254. || !TEST_int_gt(BIO_flush(cbio), 0)
  255. || !TEST_int_gt(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG,
  256. sizeof(tag), tag), 0))
  257. goto end;
  258. BIO_free(cbio);
  259. BIO_free(b64);
  260. b64 = cbio = NULL;
  261. BIO_set_mem_eof_return(mem, 0);
  262. BIO_set_flags(mem, BIO_FLAGS_NONCLEAR_RST);
  263. if (!TEST_int_gt(BIO_reset(mem), 0)
  264. || !TEST_ptr(b64 = BIO_new(BIO_f_base64()))
  265. || !TEST_ptr(cbio = BIO_new(BIO_f_cipher()))
  266. || !TEST_ptr(BIO_push(b64, mem))
  267. || !TEST_ptr(BIO_push(cbio, b64))
  268. || !TEST_int_gt(BIO_get_cipher_ctx(cbio, &ctx), 0)
  269. || !TEST_true(EVP_CipherInit_ex(ctx, cipher, NULL, KEY, IV, DECRYPT))
  270. || !TEST_int_gt(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG,
  271. sizeof(tag), tag), 0)
  272. || !TEST_int_gt((n = BIO_read(cbio, cbuf, sizeof(cbuf))), 0)
  273. || !TEST_true(BIO_get_cipher_status(cbio))
  274. /* Evaluate both and report whether either or both failed */
  275. || (!TEST_int_gt(BIO_flush(cbio), 0) +
  276. !TEST_true(BIO_get_cipher_status(cbio)))
  277. || !TEST_mem_eq(cbuf, n, pbuf, sizeof(pbuf) - 1))
  278. goto end;
  279. ret = 1;
  280. end:
  281. BIO_free(cbio);
  282. BIO_free(b64);
  283. BIO_free(mem);
  284. return ret;
  285. }
  286. int setup_tests(void)
  287. {
  288. ADD_ALL_TESTS(test_bio_enc_aes_128_cbc, 2);
  289. ADD_ALL_TESTS(test_bio_enc_aes_128_ctr, 2);
  290. ADD_ALL_TESTS(test_bio_enc_aes_256_cfb, 2);
  291. ADD_ALL_TESTS(test_bio_enc_aes_256_ofb, 2);
  292. # ifndef OPENSSL_NO_CHACHA
  293. ADD_ALL_TESTS(test_bio_enc_chacha20, 2);
  294. # ifndef OPENSSL_NO_POLY1305
  295. ADD_ALL_TESTS(test_bio_enc_chacha20_poly1305, 2);
  296. # endif
  297. # endif
  298. ADD_TEST(test_bio_enc_eof_read_flush);
  299. return 1;
  300. }