bio_pw_callback_test.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. /*
  2. * Copyright 2024 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 "testutil.h"
  10. #include <openssl/bio.h>
  11. #include <openssl/pem.h>
  12. /* dummy data that needs to be passed to the callback */
  13. typedef struct CallbackData {
  14. char magic;
  15. int result;
  16. } CALLBACK_DATA;
  17. /* constants */
  18. static const char weak_password[] = "weak_password";
  19. static const char a0a_password[] = "aaaaaaaa\0aaaaaaaa";
  20. static const char a0b_password[] = "aaaaaaaa\0bbbbbbbb";
  21. static const char cb_magic = 'p';
  22. /* shared working data for all tests */
  23. static char *key_file = NULL;
  24. static EVP_PKEY *original_pkey = NULL;
  25. /* the test performed by the callback */
  26. typedef enum CallbackTest {
  27. CB_TEST_NEGATIVE = 0,
  28. CB_TEST_ZERO_LENGTH,
  29. CB_TEST_WEAK,
  30. CB_TEST_16ZERO,
  31. CB_TEST_A0A,
  32. CB_TEST_A0B,
  33. CB_TEST_MATCH_SIZE,
  34. CB_TEST_EXCEED_SIZE
  35. } CALLBACK_TEST;
  36. static CALLBACK_TEST callback_test = CB_TEST_NEGATIVE;
  37. typedef enum KeyEncoding {
  38. KE_PEM = 0,
  39. KE_PKCS8
  40. } KEY_ENCODING;
  41. typedef enum ExpectedResult {
  42. ER_FAILURE = 0,
  43. ER_SUCCESS
  44. } EXPECTED_RESULT;
  45. typedef enum OPTION_choice {
  46. OPT_ERR = -1,
  47. OPT_EOF = 0,
  48. OPT_KEY_FILE,
  49. OPT_TEST_ENUM
  50. } OPTION_CHOICE;
  51. const OPTIONS *test_get_options(void)
  52. {
  53. static const OPTIONS test_options[] = {
  54. OPT_TEST_OPTIONS_DEFAULT_USAGE,
  55. { "keyfile", OPT_KEY_FILE, '<',
  56. "The PEM file with the encrypted key to load" },
  57. { NULL }
  58. };
  59. return test_options;
  60. }
  61. static int callback_copy_password(char *buf, int size)
  62. {
  63. int ret = -1;
  64. switch (callback_test) {
  65. case CB_TEST_NEGATIVE:
  66. break;
  67. case CB_TEST_ZERO_LENGTH:
  68. ret = 0;
  69. break;
  70. case CB_TEST_WEAK:
  71. ret = sizeof(weak_password) - 1;
  72. memcpy(buf, weak_password, ret);
  73. break;
  74. case CB_TEST_16ZERO:
  75. memset(buf, 0, 16);
  76. ret = 16;
  77. break;
  78. case CB_TEST_A0A:
  79. ret = sizeof(a0a_password) - 1;
  80. memcpy(buf, a0a_password, ret);
  81. break;
  82. case CB_TEST_A0B:
  83. ret = sizeof(a0b_password) - 1;
  84. memcpy(buf, a0b_password, ret);
  85. break;
  86. case CB_TEST_MATCH_SIZE:
  87. memset(buf, 'e', size);
  88. ret = size;
  89. break;
  90. case CB_TEST_EXCEED_SIZE:
  91. memset(buf, 'e', size);
  92. ret = 1000000;
  93. break;
  94. }
  95. return ret;
  96. }
  97. static int read_callback(char *buf, int size, int rwflag, void *u)
  98. {
  99. CALLBACK_DATA *cb_data = (CALLBACK_DATA *)u;
  100. int ret = -1;
  101. /* basic verification of the received data */
  102. if (!TEST_ptr(cb_data))
  103. goto err;
  104. if (!TEST_char_eq(cb_data->magic, cb_magic))
  105. goto err;
  106. if (!TEST_ptr(buf))
  107. goto err;
  108. if (!TEST_int_gt(size, 0))
  109. goto err;
  110. if (!TEST_int_eq(rwflag, 0))
  111. goto err;
  112. ret = callback_copy_password(buf, size);
  113. cb_data->result = 1;
  114. err:
  115. return ret;
  116. }
  117. static int write_callback(char *buf, int size, int rwflag, void *u)
  118. {
  119. CALLBACK_DATA *cb_data = (CALLBACK_DATA *)u;
  120. int ret = -1;
  121. /* basic verification of the received data */
  122. if (!TEST_ptr(cb_data))
  123. goto err;
  124. if (!TEST_char_eq(cb_data->magic, cb_magic))
  125. goto err;
  126. if (!TEST_ptr(buf))
  127. goto err;
  128. if (!TEST_int_gt(size, 0))
  129. goto err;
  130. if (!TEST_int_eq(rwflag, 1))
  131. goto err;
  132. ret = callback_copy_password(buf, size);
  133. cb_data->result = 1;
  134. err:
  135. return ret;
  136. }
  137. static int re_encrypt_key(char **enc_data, int *enc_data_size,
  138. KEY_ENCODING key_encoding)
  139. {
  140. CALLBACK_DATA cb_data;
  141. int w_ret = 0;
  142. BUF_MEM *bptr = NULL;
  143. BIO *bio = NULL;
  144. int ret = 0;
  145. if (!TEST_ptr(enc_data))
  146. goto err;
  147. if (!TEST_ptr(enc_data_size))
  148. goto err;
  149. if (!TEST_ptr(bio = BIO_new(BIO_s_mem())))
  150. goto err;
  151. cb_data.magic = cb_magic;
  152. cb_data.result = 0;
  153. switch (key_encoding) {
  154. case KE_PEM:
  155. w_ret = PEM_write_bio_PrivateKey(bio, original_pkey, EVP_aes_256_cbc(),
  156. NULL, 0, write_callback, &cb_data);
  157. break;
  158. case KE_PKCS8:
  159. w_ret = i2d_PKCS8PrivateKey_bio(bio, original_pkey, EVP_aes_256_cbc(),
  160. NULL, 0, write_callback, &cb_data);
  161. break;
  162. }
  163. if (!TEST_int_ne(w_ret, 0))
  164. goto err;
  165. if (!TEST_char_eq(cb_data.magic, cb_magic))
  166. goto err;
  167. if (!TEST_int_eq(cb_data.result, 1))
  168. goto err;
  169. *enc_data_size = BIO_get_mem_data(bio, enc_data);
  170. BIO_get_mem_ptr(bio, &bptr);
  171. if (!BIO_set_close(bio, BIO_NOCLOSE))
  172. goto err;
  173. bptr->data = NULL;
  174. ret = 1;
  175. err:
  176. BUF_MEM_free(bptr);
  177. BIO_free(bio);
  178. return ret;
  179. }
  180. static int decrypt_key(char *enc_data, int enc_data_size,
  181. KEY_ENCODING key_encoding,
  182. EXPECTED_RESULT expected_result)
  183. {
  184. CALLBACK_DATA cb_data;
  185. EVP_PKEY *r_ret = NULL;
  186. BIO *bio = NULL;
  187. EVP_PKEY *pkey = NULL;
  188. int ret = 0;
  189. if (!TEST_ptr(bio = BIO_new_mem_buf(enc_data, enc_data_size)))
  190. goto err;
  191. cb_data.magic = cb_magic;
  192. cb_data.result = 0;
  193. switch (key_encoding) {
  194. case KE_PEM:
  195. r_ret = PEM_read_bio_PrivateKey(bio, &pkey, read_callback, &cb_data);
  196. break;
  197. case KE_PKCS8:
  198. r_ret = d2i_PKCS8PrivateKey_bio(bio, &pkey, read_callback, &cb_data);
  199. break;
  200. }
  201. if (expected_result == ER_SUCCESS) {
  202. if (!TEST_ptr(r_ret))
  203. goto err;
  204. } else {
  205. if (!TEST_ptr_null(r_ret))
  206. goto err;
  207. }
  208. if (!TEST_char_eq(cb_data.magic, cb_magic))
  209. goto err;
  210. if (!TEST_int_eq(cb_data.result, 1))
  211. goto err;
  212. ret = 1;
  213. err:
  214. EVP_PKEY_free(pkey);
  215. BIO_free(bio);
  216. return ret;
  217. }
  218. static int full_cycle_test(KEY_ENCODING key_encoding, CALLBACK_TEST write_test,
  219. CALLBACK_TEST read_test,
  220. EXPECTED_RESULT expected_read_result)
  221. {
  222. char *enc_data = NULL;
  223. int enc_data_size = 0;
  224. int ret = 0;
  225. callback_test = write_test;
  226. if (!re_encrypt_key(&enc_data, &enc_data_size, key_encoding))
  227. goto err;
  228. callback_test = read_test;
  229. if (!decrypt_key(enc_data, enc_data_size, key_encoding,
  230. expected_read_result))
  231. goto err;
  232. ret = 1;
  233. err:
  234. OPENSSL_free(enc_data);
  235. return ret;
  236. }
  237. static int test_pem_negative(void)
  238. {
  239. return full_cycle_test(KE_PEM, CB_TEST_WEAK, CB_TEST_NEGATIVE, ER_FAILURE);
  240. }
  241. static int test_pem_zero_length(void)
  242. {
  243. return full_cycle_test(KE_PEM, CB_TEST_ZERO_LENGTH, CB_TEST_ZERO_LENGTH,
  244. ER_SUCCESS);
  245. }
  246. static int test_pem_weak(void)
  247. {
  248. return full_cycle_test(KE_PEM, CB_TEST_WEAK, CB_TEST_WEAK, ER_SUCCESS);
  249. }
  250. static int test_pem_16zero(void)
  251. {
  252. return full_cycle_test(KE_PEM, CB_TEST_16ZERO, CB_TEST_16ZERO, ER_SUCCESS);
  253. }
  254. static int test_pem_a0a(void)
  255. {
  256. return full_cycle_test(KE_PEM, CB_TEST_A0A, CB_TEST_A0A, ER_SUCCESS);
  257. }
  258. static int test_pem_a0a_a0b(void)
  259. {
  260. return full_cycle_test(KE_PEM, CB_TEST_A0A, CB_TEST_A0B, ER_FAILURE);
  261. }
  262. static int test_pem_match_size(void)
  263. {
  264. return full_cycle_test(KE_PEM, CB_TEST_MATCH_SIZE, CB_TEST_MATCH_SIZE,
  265. ER_SUCCESS);
  266. }
  267. static int test_pem_exceed_size(void)
  268. {
  269. return full_cycle_test(KE_PEM, CB_TEST_MATCH_SIZE, CB_TEST_EXCEED_SIZE,
  270. ER_FAILURE);
  271. }
  272. static int test_pkcs8_negative(void)
  273. {
  274. return full_cycle_test(KE_PKCS8, CB_TEST_WEAK, CB_TEST_NEGATIVE, ER_FAILURE);
  275. }
  276. static int test_pkcs8_zero_length(void)
  277. {
  278. return full_cycle_test(KE_PKCS8, CB_TEST_ZERO_LENGTH, CB_TEST_ZERO_LENGTH,
  279. ER_SUCCESS);
  280. }
  281. static int test_pkcs8_weak(void)
  282. {
  283. return full_cycle_test(KE_PKCS8, CB_TEST_WEAK, CB_TEST_WEAK, ER_SUCCESS);
  284. }
  285. static int test_pkcs8_16zero(void)
  286. {
  287. return full_cycle_test(KE_PKCS8, CB_TEST_16ZERO, CB_TEST_16ZERO,
  288. ER_SUCCESS);
  289. }
  290. static int test_pkcs8_a0a(void)
  291. {
  292. return full_cycle_test(KE_PKCS8, CB_TEST_A0A, CB_TEST_A0A, ER_SUCCESS);
  293. }
  294. static int test_pkcs8_a0a_a0b(void)
  295. {
  296. return full_cycle_test(KE_PKCS8, CB_TEST_A0A, CB_TEST_A0B, ER_FAILURE);
  297. }
  298. static int test_pkcs8_match_size(void)
  299. {
  300. return full_cycle_test(KE_PKCS8, CB_TEST_MATCH_SIZE, CB_TEST_MATCH_SIZE,
  301. ER_SUCCESS);
  302. }
  303. static int test_pkcs8_exceed_size(void)
  304. {
  305. return full_cycle_test(KE_PKCS8, CB_TEST_MATCH_SIZE, CB_TEST_EXCEED_SIZE,
  306. ER_FAILURE);
  307. }
  308. static int callback_original_pw(char *buf, int size, int rwflag, void *u)
  309. {
  310. memcpy(buf, weak_password, sizeof(weak_password) - 1);
  311. return sizeof(weak_password) - 1;
  312. }
  313. int setup_tests(void)
  314. {
  315. OPTION_CHOICE o;
  316. BIO *bio = NULL;
  317. while ((o = opt_next()) != OPT_EOF) {
  318. switch (o) {
  319. case OPT_KEY_FILE:
  320. key_file = opt_arg();
  321. break;
  322. case OPT_TEST_CASES:
  323. break;
  324. default:
  325. case OPT_ERR:
  326. return 0;
  327. }
  328. }
  329. /* read the original key */
  330. if (!TEST_ptr(bio = BIO_new_file(key_file, "r")))
  331. return 0;
  332. if (!TEST_ptr(PEM_read_bio_PrivateKey(bio, &original_pkey,
  333. callback_original_pw, NULL)))
  334. return 0;
  335. BIO_free(bio);
  336. /* add all tests */
  337. ADD_TEST(test_pem_negative);
  338. ADD_TEST(test_pem_zero_length);
  339. ADD_TEST(test_pem_weak);
  340. ADD_TEST(test_pem_16zero);
  341. ADD_TEST(test_pem_a0a);
  342. ADD_TEST(test_pem_a0a_a0b);
  343. ADD_TEST(test_pem_match_size);
  344. ADD_TEST(test_pem_exceed_size);
  345. ADD_TEST(test_pkcs8_negative);
  346. ADD_TEST(test_pkcs8_zero_length);
  347. ADD_TEST(test_pkcs8_weak);
  348. ADD_TEST(test_pkcs8_16zero);
  349. ADD_TEST(test_pkcs8_a0a);
  350. ADD_TEST(test_pkcs8_a0a_a0b);
  351. ADD_TEST(test_pkcs8_match_size);
  352. ADD_TEST(test_pkcs8_exceed_size);
  353. return 1;
  354. }
  355. void cleanup_tests(void)
  356. {
  357. EVP_PKEY_free(original_pkey);
  358. }