test_crypto.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2022, Philip Prindeville
  5. *
  6. * Philip Prindeville <philipp@redfish-solutions.com>
  7. *
  8. * See http://www.asterisk.org for more information about
  9. * the Asterisk project. Please do not directly contact
  10. * any of the maintainers of this project for assistance;
  11. * the project provides a web site, mailing lists and IRC
  12. * channels for your use.
  13. *
  14. * This program is free software, distributed under the terms of
  15. * the GNU General Public License Version 2. See the LICENSE file
  16. * at the top of the source tree.
  17. */
  18. /*!
  19. * \file
  20. * \brief Unit Tests for crypto API
  21. *
  22. * \author Philip Prindeville <philipp@redfish-solutions.com>
  23. */
  24. /*** MODULEINFO
  25. <depend>TEST_FRAMEWORK</depend>
  26. <depend>res_crypto</depend>
  27. <depend>crypto</depend>
  28. <support_level>core</support_level>
  29. ***/
  30. #include "asterisk.h"
  31. #include "asterisk/utils.h"
  32. #include "asterisk/test.h"
  33. #include "asterisk/crypto.h"
  34. #include "asterisk/paths.h"
  35. #include "asterisk/module.h"
  36. #include "asterisk/file.h"
  37. #include <assert.h>
  38. #include <sys/stat.h>
  39. #include <linux/limits.h>
  40. #include <openssl/evp.h>
  41. static const char *keypair1 = "rsa_key1";
  42. static const char *old_key_dir = NULL;
  43. static char *hexstring(const unsigned char *data, unsigned datalen)
  44. {
  45. char *buf = ast_malloc(datalen * 2 + 1);
  46. unsigned n;
  47. for (n = 0; n < datalen; ++n) {
  48. snprintf(&buf[n * 2], 3, "%02x", data[n]);
  49. }
  50. buf[datalen * 2] = '\0';
  51. return buf;
  52. }
  53. static void push_key_dir(const char *dir)
  54. {
  55. assert(old_key_dir == NULL);
  56. old_key_dir = ast_config_AST_KEY_DIR;
  57. ast_config_AST_KEY_DIR = ast_strdup(dir);
  58. }
  59. static void pop_key_dir(void)
  60. {
  61. assert(old_key_dir != NULL);
  62. ast_free((char *)ast_config_AST_KEY_DIR);
  63. ast_config_AST_KEY_DIR = old_key_dir;
  64. old_key_dir = NULL;
  65. }
  66. AST_TEST_DEFINE(crypto_rsa_encrypt)
  67. {
  68. int res = AST_TEST_FAIL;
  69. struct ast_key *key = NULL;
  70. const unsigned char plaintext[23] = "Mary had a little lamb.";
  71. char wd[PATH_MAX], key_dir[PATH_MAX], priv[PATH_MAX];
  72. unsigned char buf[AST_CRYPTO_RSA_KEY_BITS / 8];
  73. const char *command = "openssl";
  74. char *args[] = { "openssl", "pkeyutl", "-decrypt", "-inkey", "PRIVATE", "-pkeyopt", "rsa_padding_mode:oaep", NULL };
  75. enum { PRIVATE = 4 };
  76. struct ast_test_capture cap;
  77. switch (cmd) {
  78. case TEST_INIT:
  79. info->name = "crypto_rsa_encrypt";
  80. info->category = "/res/res_crypto/";
  81. info->summary = "Encrypt w/ RSA public key";
  82. info->description = "Encrypt string with RSA public key";
  83. return AST_TEST_NOT_RUN;
  84. case TEST_EXECUTE:
  85. break;
  86. }
  87. ast_test_status_update(test, "Executing RSA encryption test\n");
  88. ast_test_capture_init(&cap);
  89. if (!ast_check_command_in_path(command)) {
  90. ast_test_status_update(test, "couldn't find %s\n", command);
  91. ast_test_capture_free(&cap);
  92. return res;
  93. }
  94. if (getcwd(wd, sizeof(wd)) == NULL) {
  95. ast_test_status_update(test, "Could not determine current working directory\n");
  96. ast_test_capture_free(&cap);
  97. return res;
  98. }
  99. snprintf(key_dir, sizeof(key_dir), "%s/%s", wd, "tests/keys");
  100. push_key_dir((const char *)key_dir);
  101. snprintf(priv, sizeof(priv), "%s/%s.key", key_dir, keypair1);
  102. /* because git doesn't preserve permissions */
  103. (void)chmod(priv, 0400);
  104. if (ast_crypto_reload() != 1) {
  105. ast_test_status_update(test, "Couldn't force crypto reload\n");
  106. goto cleanup;
  107. }
  108. key = ast_key_get(keypair1, AST_KEY_PUBLIC);
  109. if (!key) {
  110. ast_test_status_update(test, "Couldn't read key: %s\n", keypair1);
  111. goto cleanup;
  112. }
  113. memset(buf, 0, sizeof(buf));
  114. ast_encrypt_bin(buf, plaintext, sizeof(plaintext), key);
  115. args[PRIVATE] = priv;
  116. if (ast_test_capture_command(&cap, command, args, (const char *)buf, sizeof(buf)) != 1) {
  117. ast_test_status_update(test, "ast_test_capture_command() failed\n");
  118. goto cleanup;
  119. }
  120. if (cap.outlen != sizeof(plaintext) || memcmp(cap.outbuf, plaintext, cap.outlen)) {
  121. ast_test_status_update(test, "Unexpected value/length for stdout: '%.*s' (%zu)\n", (int) cap.outlen, cap.outbuf, cap.outlen);
  122. goto cleanup;
  123. }
  124. if (cap.errlen != 0) {
  125. ast_test_status_update(test, "Unexpected length for stderr: '%.*s' (%zu)\n", (int) cap.errlen, cap.errbuf, cap.errlen);
  126. goto cleanup;
  127. }
  128. if (cap.pid == -1) {
  129. ast_test_status_update(test, "Invalid process id\n");
  130. goto cleanup;
  131. }
  132. if (cap.exitcode != 0) {
  133. ast_test_status_update(test, "Child exited %d\n", cap.exitcode);
  134. goto cleanup;
  135. }
  136. res = AST_TEST_PASS;
  137. cleanup:
  138. ast_test_capture_free(&cap);
  139. pop_key_dir();
  140. return res;
  141. }
  142. AST_TEST_DEFINE(crypto_rsa_decrypt)
  143. {
  144. int res = AST_TEST_FAIL;
  145. struct ast_key *key = NULL;
  146. const unsigned char plaintext[23] = "Mary had a little lamb.";
  147. char wd[PATH_MAX], key_dir[PATH_MAX], pub[PATH_MAX];
  148. unsigned char buf[AST_CRYPTO_RSA_KEY_BITS / 8];
  149. const char *command = "openssl";
  150. char *args[] = { "openssl", "pkeyutl", "-encrypt", "-pubin", "-inkey", "PUBLIC", "-pkeyopt", "rsa_padding_mode:oaep", NULL };
  151. enum { PUBLIC = 5 };
  152. struct ast_test_capture cap;
  153. int len;
  154. switch (cmd) {
  155. case TEST_INIT:
  156. info->name = "crypto_decrypt_pub_key";
  157. info->category = "/res/res_crypto/";
  158. info->summary = "Decrypt w/ RSA public key";
  159. info->description = "Decrypt string with RSA private key";
  160. return AST_TEST_NOT_RUN;
  161. case TEST_EXECUTE:
  162. break;
  163. }
  164. ast_test_status_update(test, "Executing RSA decryption test\n");
  165. ast_test_capture_init(&cap);
  166. if (!ast_check_command_in_path(command)) {
  167. ast_test_status_update(test, "couldn't find %s\n", command);
  168. ast_test_capture_free(&cap);
  169. return res;
  170. }
  171. if (getcwd(wd, sizeof(wd)) == NULL) {
  172. ast_test_status_update(test, "Could not determine current working directory\n");
  173. ast_test_capture_free(&cap);
  174. return res;
  175. }
  176. snprintf(key_dir, sizeof(key_dir), "%s/%s", wd, "tests/keys");
  177. push_key_dir((const char *)key_dir);
  178. snprintf(pub, sizeof(pub), "%s/%s.pub", key_dir, keypair1);
  179. if (ast_crypto_reload() != 1) {
  180. ast_test_status_update(test, "Couldn't force crypto reload\n");
  181. goto cleanup;
  182. }
  183. key = ast_key_get(keypair1, AST_KEY_PRIVATE);
  184. if (!key) {
  185. ast_test_status_update(test, "Couldn't read key: %s\n", keypair1);
  186. goto cleanup;
  187. }
  188. args[PUBLIC] = pub;
  189. if (ast_test_capture_command(&cap, command, args, (const char *)plaintext, sizeof(plaintext)) != 1) {
  190. ast_test_status_update(test, "ast_test_capture_command() failed\n");
  191. goto cleanup;
  192. }
  193. if (cap.outlen != sizeof(buf)) {
  194. ast_test_status_update(test, "Unexpected length for stdout: %zu\n", cap.outlen);
  195. goto cleanup;
  196. }
  197. if (cap.errlen != 0) {
  198. ast_test_status_update(test, "Unexpected value/length for stderr: '%.*s' (%zu)\n", (int) cap.errlen, cap.errbuf, cap.errlen);
  199. goto cleanup;
  200. }
  201. if (cap.pid == -1) {
  202. ast_test_status_update(test, "Invalid process id\n");
  203. goto cleanup;
  204. }
  205. if (cap.exitcode != 0) {
  206. ast_test_status_update(test, "Child exited %d\n", cap.exitcode);
  207. goto cleanup;
  208. }
  209. memset(buf, 0, sizeof(buf));
  210. len = ast_decrypt_bin(buf, (unsigned char *)cap.outbuf, cap.outlen, key);
  211. if (len != sizeof(plaintext) || memcmp(buf, plaintext, len)) {
  212. ast_test_status_update(test, "Unexpected value for decrypted text\n");
  213. goto cleanup;
  214. }
  215. res = AST_TEST_PASS;
  216. cleanup:
  217. ast_test_capture_free(&cap);
  218. pop_key_dir();
  219. return res;
  220. }
  221. AST_TEST_DEFINE(crypto_sign)
  222. {
  223. int res = AST_TEST_FAIL;
  224. struct ast_key *key = NULL;
  225. const char plaintext[23] = "Mary had a little lamb.";
  226. char wd[PATH_MAX], key_dir[PATH_MAX], pub[PATH_MAX];
  227. unsigned char buf[AST_CRYPTO_RSA_KEY_BITS / 8];
  228. const char *command = "openssl";
  229. char *args[] = { "openssl", "pkeyutl", "-verify", "-inkey", "PUBLIC", "-pubin", "-sigfile", "SIGNATURE", "-pkeyopt", "digest:sha1", NULL };
  230. enum { PUBLIC = 4, SIGNATURE = 7 };
  231. struct ast_test_capture cap;
  232. unsigned char digest[20];
  233. unsigned digestlen;
  234. EVP_MD_CTX *ctx;
  235. FILE *fsig = NULL;
  236. char signpath[64] = "/tmp/signingXXXXXX";
  237. const char success[] = "Signature Verified Successfully\n";
  238. switch (cmd) {
  239. case TEST_INIT:
  240. info->name = "crypto_sign";
  241. info->category = "/res/res_crypto/";
  242. info->summary = "Sign w/ RSA private key";
  243. info->description = "Sign string with RSA private key";
  244. return AST_TEST_NOT_RUN;
  245. case TEST_EXECUTE:
  246. break;
  247. }
  248. ast_test_status_update(test, "Executing RSA signing test\n");
  249. ast_test_capture_init(&cap);
  250. if (!ast_check_command_in_path(command)) {
  251. ast_test_status_update(test, "couldn't find %s\n", command);
  252. ast_test_capture_free(&cap);
  253. return res;
  254. }
  255. if (getcwd(wd, sizeof(wd)) == NULL) {
  256. ast_test_status_update(test, "Could not determine current working directory\n");
  257. ast_test_capture_free(&cap);
  258. return res;
  259. }
  260. snprintf(key_dir, sizeof(key_dir), "%s/%s", wd, "tests/keys");
  261. push_key_dir((const char *)key_dir);
  262. snprintf(pub, sizeof(pub), "%s/%s.pub", key_dir, keypair1);
  263. ctx = EVP_MD_CTX_create();
  264. EVP_DigestInit(ctx, EVP_sha1());
  265. EVP_DigestUpdate(ctx, plaintext, sizeof(plaintext));
  266. EVP_DigestFinal(ctx, digest, &digestlen);
  267. EVP_MD_CTX_destroy(ctx);
  268. ctx = NULL;
  269. if (ast_crypto_reload() != 1) {
  270. ast_test_status_update(test, "Couldn't force crypto reload\n");
  271. goto cleanup;
  272. }
  273. key = ast_key_get(keypair1, AST_KEY_PRIVATE);
  274. if (!key) {
  275. ast_test_status_update(test, "Couldn't read key: %s\n", keypair1);
  276. goto cleanup;
  277. }
  278. memset(buf, 0, sizeof(buf));
  279. if (ast_sign_bin(key, plaintext, sizeof(plaintext), buf) != 0) {
  280. ast_test_status_update(test, "ast_sign_bin() failed\n");
  281. goto cleanup;
  282. }
  283. fsig = ast_file_mkftemp(signpath, 0600);
  284. if (fsig == NULL) {
  285. ast_test_status_update(test, "Couldn't open temp signing file\n");
  286. goto cleanup;
  287. }
  288. fwrite(buf, sizeof(char), sizeof(buf), fsig);
  289. fclose(fsig);
  290. fsig = NULL;
  291. args[PUBLIC] = pub;
  292. args[SIGNATURE] = signpath;
  293. if (ast_test_capture_command(&cap, command, args, (const char *)digest, digestlen) != 1) {
  294. ast_test_status_update(test, "ast_test_capture_command() failed\n");
  295. goto cleanup;
  296. }
  297. if (cap.outlen != sizeof(success) - 1 || memcmp(cap.outbuf, success, cap.outlen)) {
  298. ast_test_status_update(test, "Unexpected value/length for stdout: '%.*s' (%zu)\n", (int) cap.outlen, cap.outbuf, cap.outlen);
  299. goto cleanup;
  300. }
  301. if (cap.errlen != 0) {
  302. ast_test_status_update(test, "Unexpected value for stderr: '%.*s' (%zu)\n", (int) cap.errlen, cap.errbuf, cap.errlen);
  303. goto cleanup;
  304. }
  305. if (cap.pid == -1) {
  306. ast_test_status_update(test, "Invalid process id\n");
  307. goto cleanup;
  308. }
  309. #if OPENSSL_VERSION_NUMBER >= 0x10100000L
  310. if (cap.exitcode != 0) {
  311. #else
  312. if (cap.exitcode != 0 && cap.exitcode != 1) {
  313. #endif
  314. ast_test_status_update(test, "Child exited %d\n", cap.exitcode);
  315. goto cleanup;
  316. }
  317. res = AST_TEST_PASS;
  318. cleanup:
  319. ast_test_capture_free(&cap);
  320. unlink(signpath);
  321. pop_key_dir();
  322. return res;
  323. }
  324. AST_TEST_DEFINE(crypto_verify)
  325. {
  326. int res = AST_TEST_FAIL;
  327. struct ast_key *key = NULL;
  328. const char plaintext[23] = "Mary had a little lamb.";
  329. char wd[PATH_MAX], key_dir[PATH_MAX], priv[PATH_MAX];
  330. const char *command = "openssl";
  331. char *args[] = { "openssl", "pkeyutl", "-sign", "-inkey", "PRIVATE", "-pkeyopt", "digest:sha1", NULL };
  332. enum { PRIVATE = 4 };
  333. struct ast_test_capture cap;
  334. unsigned char digest[20];
  335. unsigned digestlen;
  336. EVP_MD_CTX *ctx;
  337. switch (cmd) {
  338. case TEST_INIT:
  339. info->name = "crypto_verify";
  340. info->category = "/res/res_crypto/";
  341. info->summary = "Verify w/ RSA public key";
  342. info->description = "Verify signature with RSA public key";
  343. return AST_TEST_NOT_RUN;
  344. case TEST_EXECUTE:
  345. break;
  346. }
  347. ast_test_status_update(test, "Executing RSA signature verification test\n");
  348. ast_test_capture_init(&cap);
  349. if (!ast_check_command_in_path(command)) {
  350. ast_test_status_update(test, "couldn't find %s\n", command);
  351. ast_test_capture_free(&cap);
  352. return res;
  353. }
  354. if (getcwd(wd, sizeof(wd)) == NULL) {
  355. ast_test_status_update(test, "Could not determine current working directory\n");
  356. ast_test_capture_free(&cap);
  357. return res;
  358. }
  359. snprintf(key_dir, sizeof(key_dir), "%s/%s", wd, "tests/keys");
  360. push_key_dir((const char *)key_dir);
  361. snprintf(priv, sizeof(priv), "%s/%s.key", key_dir, keypair1);
  362. /* because git doesn't preserve permissions */
  363. (void)chmod(priv, 0400);
  364. if (ast_crypto_reload() != 1) {
  365. ast_test_status_update(test, "Couldn't force crypto reload\n");
  366. goto cleanup;
  367. }
  368. key = ast_key_get(keypair1, AST_KEY_PUBLIC);
  369. if (!key) {
  370. ast_test_status_update(test, "Couldn't read key: %s\n", keypair1);
  371. goto cleanup;
  372. }
  373. ctx = EVP_MD_CTX_create();
  374. EVP_DigestInit(ctx, EVP_sha1());
  375. EVP_DigestUpdate(ctx, plaintext, sizeof(plaintext));
  376. EVP_DigestFinal(ctx, digest, &digestlen);
  377. EVP_MD_CTX_destroy(ctx);
  378. args[PRIVATE] = priv;
  379. if (ast_test_capture_command(&cap, command, args, (const char *)digest, sizeof(digest)) != 1) {
  380. ast_test_status_update(test, "ast_test_capture_command() failed\n");
  381. goto cleanup;
  382. }
  383. if (cap.outlen != (AST_CRYPTO_RSA_KEY_BITS / 8)) {
  384. ast_test_status_update(test, "Unexpected length for stdout: %zu\n", cap.outlen);
  385. goto cleanup;
  386. }
  387. if (cap.errlen != 0) {
  388. ast_test_status_update(test, "Unexpected value/length for stderr: '%.*s'\n", (int) cap.errlen, cap.errbuf);
  389. goto cleanup;
  390. }
  391. if (cap.pid == -1) {
  392. ast_test_status_update(test, "Invalid process id\n");
  393. goto cleanup;
  394. }
  395. if (cap.exitcode != 0) {
  396. ast_test_status_update(test, "Child exited %d\n", cap.exitcode);
  397. goto cleanup;
  398. }
  399. if (ast_check_signature_bin(key, plaintext, sizeof(plaintext), (const unsigned char *)cap.outbuf) != 0) {
  400. ast_test_status_update(test, "ast_check_signature_bin() failed\n");
  401. goto cleanup;
  402. }
  403. res = AST_TEST_PASS;
  404. cleanup:
  405. ast_test_capture_free(&cap);
  406. pop_key_dir();
  407. return res;
  408. }
  409. AST_TEST_DEFINE(crypto_aes_encrypt)
  410. {
  411. int res = AST_TEST_FAIL;
  412. const unsigned char key[16] = {
  413. 0x01, 0x23, 0x45, 0x67, 0x89, 0x01, 0x23, 0x45,
  414. 0x67, 0x89, 0x01, 0x23, 0x45, 0x67, 0x89, 0x01
  415. };
  416. const unsigned char plaintext[16] = "Mary had a littl";
  417. const char *command = "openssl";
  418. char *args[] = { "openssl", "enc", "-aes-128-ecb", "-d", "-K", "KEY", "-nopad", NULL };
  419. enum { KEY = 5 };
  420. struct ast_test_capture cap;
  421. unsigned char buf[16];
  422. ast_aes_encrypt_key aes_key;
  423. switch (cmd) {
  424. case TEST_INIT:
  425. info->name = "crypto_aes_encrypt";
  426. info->category = "/res/res_crypto/";
  427. info->summary = "Encrypt test AES-128-ECB";
  428. info->description = "Encrypt a test string using AES-128 and ECB";
  429. return AST_TEST_NOT_RUN;
  430. case TEST_EXECUTE:
  431. break;
  432. }
  433. ast_test_status_update(test, "Executing AES-ECB encryption test\n");
  434. ast_test_capture_init(&cap);
  435. if (!ast_check_command_in_path(command)) {
  436. ast_test_status_update(test, "couldn't find %s\n", command);
  437. return res;
  438. }
  439. memset(buf, 0, sizeof(buf));
  440. ast_aes_set_encrypt_key(key, &aes_key);
  441. if (ast_aes_encrypt(plaintext, buf, &aes_key) <= 0) {
  442. ast_test_status_update(test, "ast_aes_encrypt() failed\n");
  443. goto cleanup;
  444. }
  445. args[KEY] = hexstring(key, sizeof(key));
  446. if (ast_test_capture_command(&cap, command, args, (const char *)buf, sizeof(buf)) != 1) {
  447. ast_test_status_update(test, "ast_test_capture_command() failed\n");
  448. goto cleanup;
  449. }
  450. if (cap.outlen != sizeof(plaintext) || memcmp(cap.outbuf, plaintext, cap.outlen)) {
  451. ast_test_status_update(test, "Unexpected value/length for stdout: '%.*s' (%zu)\n", (int) cap.outlen, cap.outbuf, cap.outlen);
  452. goto cleanup;
  453. }
  454. if (cap.errlen != 0) {
  455. ast_test_status_update(test, "Unexpected value/length for stderr: '%.*s'\n", (int) cap.errlen, cap.errbuf);
  456. goto cleanup;
  457. }
  458. if (cap.pid == -1) {
  459. ast_test_status_update(test, "Invalid process id\n");
  460. goto cleanup;
  461. }
  462. if (cap.exitcode != 0) {
  463. ast_test_status_update(test, "Child exited %d\n", cap.exitcode);
  464. goto cleanup;
  465. }
  466. res = AST_TEST_PASS;
  467. cleanup:
  468. ast_free(args[KEY]);
  469. ast_test_capture_free(&cap);
  470. return res;
  471. }
  472. AST_TEST_DEFINE(crypto_aes_decrypt)
  473. {
  474. int res = AST_TEST_FAIL;
  475. const unsigned char key[16] = {
  476. 0x01, 0x23, 0x45, 0x67, 0x89, 0x01, 0x23, 0x45,
  477. 0x67, 0x89, 0x01, 0x23, 0x45, 0x67, 0x89, 0x01
  478. };
  479. const unsigned char plaintext[16] = "Mary had a littl";
  480. unsigned char buf[16];
  481. const char *command = "openssl";
  482. char *args[] = { "openssl", "enc", "-aes-128-ecb", "-e", "-K", "KEY", "-nopad", NULL };
  483. enum { KEY = 5 };
  484. struct ast_test_capture cap;
  485. ast_aes_encrypt_key aes_key;
  486. switch (cmd) {
  487. case TEST_INIT:
  488. info->name = "crypto_aes_decrypt";
  489. info->category = "/res/res_crypto/";
  490. info->summary = "Decrypt test AES-128-ECB";
  491. info->description = "Decrypt a test string using AES-128 and ECB";
  492. return AST_TEST_NOT_RUN;
  493. case TEST_EXECUTE:
  494. break;
  495. }
  496. ast_test_status_update(test, "Executing AES-ECB decryption test\n");
  497. ast_test_capture_init(&cap);
  498. if (!ast_check_command_in_path(command)) {
  499. ast_test_status_update(test, "couldn't find %s\n", command);
  500. return res;
  501. }
  502. args[KEY] = hexstring(key, sizeof(key));
  503. if (ast_test_capture_command(&cap, command, args, (const char *)plaintext, sizeof(plaintext)) != 1) {
  504. ast_test_status_update(test, "ast_test_capture_command() failed\n");
  505. goto cleanup;
  506. }
  507. if (cap.outlen != sizeof(buf)) {
  508. ast_test_status_update(test, "Unexpected length for stdout: %zu\n", cap.outlen);
  509. goto cleanup;
  510. }
  511. if (cap.errlen != 0) {
  512. ast_test_status_update(test, "Unexpected value/length for stderr: '%.*s'\n", (int) cap.errlen, cap.errbuf);
  513. goto cleanup;
  514. }
  515. if (cap.pid == -1) {
  516. ast_test_status_update(test, "Invalid process id\n");
  517. goto cleanup;
  518. }
  519. if (cap.exitcode != 0) {
  520. ast_test_status_update(test, "Child exited %d\n", cap.exitcode);
  521. goto cleanup;
  522. }
  523. memset(buf, 0, sizeof(buf));
  524. ast_aes_set_decrypt_key(key, &aes_key);
  525. if (ast_aes_decrypt((const unsigned char *)cap.outbuf, buf, &aes_key) <= 0) {
  526. ast_test_status_update(test, "ast_aes_decrypt() failed\n");
  527. goto cleanup;
  528. }
  529. if (memcmp(plaintext, buf, sizeof(plaintext))) {
  530. ast_test_status_update(test, "AES decryption mismatch\n");
  531. goto cleanup;
  532. }
  533. res = AST_TEST_PASS;
  534. cleanup:
  535. ast_free(args[KEY]);
  536. ast_test_capture_free(&cap);
  537. return res;
  538. }
  539. static int unload_module(void)
  540. {
  541. AST_TEST_UNREGISTER(crypto_rsa_encrypt);
  542. AST_TEST_UNREGISTER(crypto_rsa_decrypt);
  543. AST_TEST_UNREGISTER(crypto_sign);
  544. AST_TEST_UNREGISTER(crypto_verify);
  545. AST_TEST_UNREGISTER(crypto_aes_encrypt);
  546. AST_TEST_UNREGISTER(crypto_aes_decrypt);
  547. return 0;
  548. }
  549. static int load_module(void)
  550. {
  551. AST_TEST_REGISTER(crypto_rsa_encrypt);
  552. AST_TEST_REGISTER(crypto_rsa_decrypt);
  553. AST_TEST_REGISTER(crypto_sign);
  554. AST_TEST_REGISTER(crypto_verify);
  555. AST_TEST_REGISTER(crypto_aes_encrypt);
  556. AST_TEST_REGISTER(crypto_aes_decrypt);
  557. return AST_MODULE_LOAD_SUCCESS;
  558. }
  559. AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Crypto test module",
  560. .support_level = AST_MODULE_SUPPORT_CORE,
  561. .load = load_module,
  562. .unload = unload_module,
  563. .requires = "res_crypto",
  564. );