<p>Friendly Automation <strong>submitted</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/19148">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span></span><br></pre><div style="white-space:pre-wrap">Approvals:
George Joseph: Looks good to me, approved
Friendly Automation: Approved for Submit
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">test: Add coverage for res_crypto<br><br>We're validating the following functionality:<br><br>encrypting a block of data with RSA<br>decrypting a block of data with RSA<br>signing a block of data with RSA<br>verifying a signature with RSA<br>encrypting a block of data with AES-ECB<br>encrypting a block of data with AES-ECB<br><br>as well as accessing test keys from the keystore.<br><br>ASTERISK-30045 #close<br><br>Change-Id: I0d10e7b41009c5290a4356c6480e636712d5c96d<br>---<br>M include/asterisk/crypto.h<br>M res/res_crypto.c<br>M tests/Makefile<br>A tests/keys/rsa_key1.key<br>A tests/keys/rsa_key1.pub<br>A tests/test_crypto.c<br>6 files changed, 690 insertions(+), 2 deletions(-)<br><br></pre>
<pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/asterisk/crypto.h b/include/asterisk/crypto.h</span><br><span>index 7b889e1..da6add9 100644</span><br><span>--- a/include/asterisk/crypto.h</span><br><span>+++ b/include/asterisk/crypto.h</span><br><span>@@ -39,6 +39,12 @@</span><br><span> typedef char ast_aes_decrypt_key;</span><br><span> #endif /* HAVE_CRYPTO */</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* We previously used the key length explicitly; replace with constant.</span><br><span style="color: hsl(120, 100%, 40%);">+ * For now, Asterisk is limited to 1024 bit (128 byte) RSA keys.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#define AST_CRYPTO_RSA_KEY_BITS 1024</span><br><span style="color: hsl(120, 100%, 40%);">+#define AST_CRYPTO_AES_BLOCKSIZE 128</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #define AST_KEY_PUBLIC (1 << 0)</span><br><span> #define AST_KEY_PRIVATE (1 << 1)</span><br><span> </span><br><span>diff --git a/res/res_crypto.c b/res/res_crypto.c</span><br><span>index 19b011d..2a6a0e9 100644</span><br><span>--- a/res/res_crypto.c</span><br><span>+++ b/res/res_crypto.c</span><br><span>@@ -320,7 +320,7 @@</span><br><span> SHA1((unsigned char *)msg, msglen, digest);</span><br><span> </span><br><span> /* Verify signature */</span><br><span style="color: hsl(0, 100%, 40%);">- if (!(res = RSA_sign(NID_sha1, digest, sizeof(digest), dsig, &siglen, key->rsa))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if ((res = RSA_sign(NID_sha1, digest, sizeof(digest), dsig, &siglen, key->rsa)) != 1) {</span><br><span> ast_log(LOG_WARNING, "RSA Signature (key %s) failed\n", key->name);</span><br><span> return -1;</span><br><span> }</span><br><span>@@ -433,7 +433,7 @@</span><br><span> SHA1((unsigned char *)msg, msglen, digest);</span><br><span> </span><br><span> /* Verify signature */</span><br><span style="color: hsl(0, 100%, 40%);">- if (!(res = RSA_verify(NID_sha1, digest, sizeof(digest), (unsigned char *)dsig, 128, key->rsa))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if ((res = RSA_verify(NID_sha1, digest, sizeof(digest), (unsigned char *)dsig, 128, key->rsa)) != 1) {</span><br><span> ast_debug(1, "Key failed verification: %s\n", key->name);</span><br><span> return -1;</span><br><span> }</span><br><span>diff --git a/tests/Makefile b/tests/Makefile</span><br><span>index a3fc9dc..13f8855 100644</span><br><span>--- a/tests/Makefile</span><br><span>+++ b/tests/Makefile</span><br><span>@@ -22,5 +22,6 @@</span><br><span> test_astobj2.o: _ASTCFLAGS+=$(call get_menuselect_cflags,AO2_DEBUG)</span><br><span> # can't use '%y' in strftime() without warnings since it's not y2k compliant</span><br><span> test_capture.o: _ASTCFLAGS+=$(AST_NO_FORMAT_Y2K)</span><br><span style="color: hsl(120, 100%, 40%);">+test_crypto.o: _ASTCFLAGS+=$(AST_NO_FORMAT_TRUNCATION)</span><br><span> test_strings.o: _ASTCFLAGS+=$(AST_NO_FORMAT_TRUNCATION) $(AST_NO_STRINGOP_TRUNCATION)</span><br><span> test_voicemail_api.o: _ASTCFLAGS+=$(AST_NO_FORMAT_TRUNCATION)</span><br><span>diff --git a/tests/keys/rsa_key1.key b/tests/keys/rsa_key1.key</span><br><span>new file mode 100644</span><br><span>index 0000000..117a4e9</span><br><span>--- /dev/null</span><br><span>+++ b/tests/keys/rsa_key1.key</span><br><span>@@ -0,0 +1,15 @@</span><br><span style="color: hsl(120, 100%, 40%);">+-----BEGIN RSA PRIVATE KEY-----</span><br><span style="color: hsl(120, 100%, 40%);">+MIICXAIBAAKBgQC206PN7hvmoc0p1urAeKozmUha/h3KIAIO4DG5Muz6x3Zribdx</span><br><span style="color: hsl(120, 100%, 40%);">+cKfgmw28FwamAGT1n0y1+qGkL1vyHY4YMDjHVVSLB8h5Je89UxgXxl/PUpSx4kFN</span><br><span style="color: hsl(120, 100%, 40%);">+gZofk28Mx1lG2aLEBHXFNhrjZbdfZzeljZHYfrsLf9nxQvYeA0W2YJ3g1wIDAQAB</span><br><span style="color: hsl(120, 100%, 40%);">+AoGBAJ2V9OYmrAPySS4cIoI+P650G+raiIDVcBC0bAeO/rb2QHtW3Di6euldnMwY</span><br><span style="color: hsl(120, 100%, 40%);">+KNHjGyKf6XYeDz++1ojtsrHktrqcaXfh9J1qpxXXGxMZww00so+VOrhCbs0uf6Yh</span><br><span style="color: hsl(120, 100%, 40%);">+FdZ1Dc3UsBLhrA/fBaaw3xRwFvsgnxmJPX6R/gmC+A6uc/QxAkEA5z9TBbdW6bsA</span><br><span style="color: hsl(120, 100%, 40%);">+SPCmUOmSalX9WyGrbaZwkvCBtuKCfHzKUcxdbXw8e68GralzGITwU3XcYn/mVqk0</span><br><span style="color: hsl(120, 100%, 40%);">+ztfBWNt+fwJBAMplfFU7uPDZwfjC3eXXljxaSzoA7EzLcByslYLuAJMYKITQOiv0</span><br><span style="color: hsl(120, 100%, 40%);">+KBb+zJxvTntArF5TOkCeVYUMZKcL8HEXIakCQFaOwnHKTZMRdyrWQTraIv8AjuQU</span><br><span style="color: hsl(120, 100%, 40%);">+t0lE2rB1q+gb4wHb6BM0Luhzb2RQgGxyl+1enWJwJH0OKNbZYTXnVqz/A9sCQFME</span><br><span style="color: hsl(120, 100%, 40%);">+4cUMZEXW7GufcumOTr+ewfCe5E5zvB7m48T63x128VfZGaNh2PfluAQK3AROeOWP</span><br><span style="color: hsl(120, 100%, 40%);">++fr7d1TFypuCmDOrK1ECQH1CeBWxVRx695uYmsAYwX8FNIn0agFasdk7wGUyP7ow</span><br><span style="color: hsl(120, 100%, 40%);">+idIaA92AHJ1gQXbEyh4iDrZZdh5fopg8sxRXdFfouFo=</span><br><span style="color: hsl(120, 100%, 40%);">+-----END RSA PRIVATE KEY-----</span><br><span>diff --git a/tests/keys/rsa_key1.pub b/tests/keys/rsa_key1.pub</span><br><span>new file mode 100644</span><br><span>index 0000000..d25a2e4</span><br><span>--- /dev/null</span><br><span>+++ b/tests/keys/rsa_key1.pub</span><br><span>@@ -0,0 +1,6 @@</span><br><span style="color: hsl(120, 100%, 40%);">+-----BEGIN PUBLIC KEY-----</span><br><span style="color: hsl(120, 100%, 40%);">+MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC206PN7hvmoc0p1urAeKozmUha</span><br><span style="color: hsl(120, 100%, 40%);">+/h3KIAIO4DG5Muz6x3ZribdxcKfgmw28FwamAGT1n0y1+qGkL1vyHY4YMDjHVVSL</span><br><span style="color: hsl(120, 100%, 40%);">+B8h5Je89UxgXxl/PUpSx4kFNgZofk28Mx1lG2aLEBHXFNhrjZbdfZzeljZHYfrsL</span><br><span style="color: hsl(120, 100%, 40%);">+f9nxQvYeA0W2YJ3g1wIDAQAB</span><br><span style="color: hsl(120, 100%, 40%);">+-----END PUBLIC KEY-----</span><br><span>diff --git a/tests/test_crypto.c b/tests/test_crypto.c</span><br><span>new file mode 100644</span><br><span>index 0000000..55497d6</span><br><span>--- /dev/null</span><br><span>+++ b/tests/test_crypto.c</span><br><span>@@ -0,0 +1,638 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Asterisk -- An open source telephony toolkit.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (C) 2022, Philip Prindeville</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Philip Prindeville <philipp@redfish-solutions.com></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * See http://www.asterisk.org for more information about</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Asterisk project. Please do not directly contact</span><br><span style="color: hsl(120, 100%, 40%);">+ * any of the maintainers of this project for assistance;</span><br><span style="color: hsl(120, 100%, 40%);">+ * the project provides a web site, mailing lists and IRC</span><br><span style="color: hsl(120, 100%, 40%);">+ * channels for your use.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software, distributed under the terms of</span><br><span style="color: hsl(120, 100%, 40%);">+ * the GNU General Public License Version 2. See the LICENSE file</span><br><span style="color: hsl(120, 100%, 40%);">+ * at the top of the source tree.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \file</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Unit Tests for crypto API</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \author Philip Prindeville <philipp@redfish-solutions.com></span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*** MODULEINFO</span><br><span style="color: hsl(120, 100%, 40%);">+ <depend>TEST_FRAMEWORK</depend></span><br><span style="color: hsl(120, 100%, 40%);">+ <depend>res_crypto</depend></span><br><span style="color: hsl(120, 100%, 40%);">+ <depend>crypto</depend></span><br><span style="color: hsl(120, 100%, 40%);">+ <support_level>core</support_level></span><br><span style="color: hsl(120, 100%, 40%);">+ ***/</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/utils.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/test.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/crypto.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/paths.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/module.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/file.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <assert.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <linux/limits.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <openssl/evp.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static const char *keypair1 = "rsa_key1";</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static const char *old_key_dir = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static char *hexstring(const unsigned char *data, unsigned datalen)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ char *buf = alloca(datalen * 2 + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned n;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ for (n = 0; n < datalen; ++n) {</span><br><span style="color: hsl(120, 100%, 40%);">+ snprintf(&buf[n * 2], 3, "%02x", data[n]);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ buf[datalen * 2] = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return buf;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void push_key_dir(const char *dir)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ assert(old_key_dir == NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ old_key_dir = ast_config_AST_KEY_DIR;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_config_AST_KEY_DIR = ast_strdup(dir);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void pop_key_dir(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ assert(old_key_dir != NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_free((char *)ast_config_AST_KEY_DIR);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_config_AST_KEY_DIR = old_key_dir;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ old_key_dir = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AST_TEST_DEFINE(crypto_rsa_encrypt)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int res = AST_TEST_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_key *key = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ const unsigned char plaintext[23] = "Mary had a little lamb.";</span><br><span style="color: hsl(120, 100%, 40%);">+ char wd[PATH_MAX], key_dir[PATH_MAX], priv[PATH_MAX];</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned char buf[AST_CRYPTO_RSA_KEY_BITS / 8];</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *command = "openssl";</span><br><span style="color: hsl(120, 100%, 40%);">+ char *args[] = { "openssl", "pkeyutl", "-decrypt", "-inkey", "PRIVATE", "-pkeyopt", "rsa_padding_mode:oaep", NULL };</span><br><span style="color: hsl(120, 100%, 40%);">+ enum { PRIVATE = 4 };</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_test_capture cap;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case TEST_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+ info->name = "crypto_rsa_encrypt";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->category = "/res/res_crypto/";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->summary = "Encrypt w/ RSA public key";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->description = "Encrypt string with RSA public key";</span><br><span style="color: hsl(120, 100%, 40%);">+ return AST_TEST_NOT_RUN;</span><br><span style="color: hsl(120, 100%, 40%);">+ case TEST_EXECUTE:</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Executing RSA encryption test\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ast_check_command_in_path(command)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "couldn't find %s\n", command);</span><br><span style="color: hsl(120, 100%, 40%);">+ return res;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ getcwd(wd, sizeof(wd));</span><br><span style="color: hsl(120, 100%, 40%);">+ snprintf(key_dir, sizeof(key_dir), "%s/%s", wd, "tests/keys");</span><br><span style="color: hsl(120, 100%, 40%);">+ push_key_dir((const char *)key_dir);</span><br><span style="color: hsl(120, 100%, 40%);">+ snprintf(priv, sizeof(priv), "%s/%s.key", key_dir, keypair1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_crypto_reload() != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Couldn't force crypto reload\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ key = ast_key_get(keypair1, AST_KEY_PUBLIC);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!key) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Couldn't read key: %s\n", keypair1);</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ memset(buf, 0, sizeof(buf));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_encrypt_bin(buf, plaintext, sizeof(plaintext), key);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ args[PRIVATE] = priv;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_test_capture_command(&cap, command, args, (const char *)buf, sizeof(buf)) != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "ast_test_capture_command() failed\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cap.outlen != sizeof(plaintext) || memcmp(cap.outbuf, plaintext, cap.outlen)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Unexpected value/length for stdout: '%.*s' (%zu)\n", (int) cap.outlen, cap.outbuf, cap.outlen);</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cap.errlen != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Unexpected length for stderr: '%.*s' (%zu)\n", (int) cap.errlen, cap.errbuf, cap.errlen);</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cap.pid == -1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Invalid process id\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cap.exitcode != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Child exited %d\n", cap.exitcode);</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ res = AST_TEST_PASS;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+cleanup:</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_capture_free(&cap);</span><br><span style="color: hsl(120, 100%, 40%);">+ pop_key_dir();</span><br><span style="color: hsl(120, 100%, 40%);">+ return res;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AST_TEST_DEFINE(crypto_rsa_decrypt)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int res = AST_TEST_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_key *key = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ const unsigned char plaintext[23] = "Mary had a little lamb.";</span><br><span style="color: hsl(120, 100%, 40%);">+ char wd[PATH_MAX], key_dir[PATH_MAX], pub[PATH_MAX];</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned char buf[AST_CRYPTO_RSA_KEY_BITS / 8];</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *command = "openssl";</span><br><span style="color: hsl(120, 100%, 40%);">+ char *args[] = { "openssl", "pkeyutl", "-encrypt", "-pubin", "-inkey", "PUBLIC", "-pkeyopt", "rsa_padding_mode:oaep", NULL };</span><br><span style="color: hsl(120, 100%, 40%);">+ enum { PUBLIC = 5 };</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_test_capture cap;</span><br><span style="color: hsl(120, 100%, 40%);">+ int len;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case TEST_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+ info->name = "crypto_decrypt_pub_key";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->category = "/res/res_crypto/";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->summary = "Decrypt w/ RSA public key";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->description = "Decrypt string with RSA private key";</span><br><span style="color: hsl(120, 100%, 40%);">+ return AST_TEST_NOT_RUN;</span><br><span style="color: hsl(120, 100%, 40%);">+ case TEST_EXECUTE:</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Executing RSA decryption test\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ast_check_command_in_path(command)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "couldn't find %s\n", command);</span><br><span style="color: hsl(120, 100%, 40%);">+ return res;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ getcwd(wd, sizeof(wd));</span><br><span style="color: hsl(120, 100%, 40%);">+ snprintf(key_dir, sizeof(key_dir), "%s/%s", wd, "tests/keys");</span><br><span style="color: hsl(120, 100%, 40%);">+ push_key_dir((const char *)key_dir);</span><br><span style="color: hsl(120, 100%, 40%);">+ snprintf(pub, sizeof(pub), "%s/%s.pub", key_dir, keypair1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_crypto_reload() != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Couldn't force crypto reload\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ key = ast_key_get(keypair1, AST_KEY_PRIVATE);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!key) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Couldn't read key: %s\n", keypair1);</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ args[PUBLIC] = pub;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_test_capture_command(&cap, command, args, (const char *)plaintext, sizeof(plaintext)) != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "ast_test_capture_command() failed\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cap.outlen != sizeof(buf)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Unexpected length for stdout: %zu\n", cap.outlen);</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cap.errlen != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Unexpected value/length for stderr: '%.*s' (%zu)\n", (int) cap.errlen, cap.errbuf, cap.errlen);</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cap.pid == -1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Invalid process id\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cap.exitcode != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Child exited %d\n", cap.exitcode);</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ memset(buf, 0, sizeof(buf));</span><br><span style="color: hsl(120, 100%, 40%);">+ len = ast_decrypt_bin(buf, (unsigned char *)cap.outbuf, cap.outlen, key);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (len != sizeof(plaintext) || memcmp(buf, plaintext, len)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Unexpected value for decrypted text\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ res = AST_TEST_PASS;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+cleanup:</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_capture_free(&cap);</span><br><span style="color: hsl(120, 100%, 40%);">+ pop_key_dir();</span><br><span style="color: hsl(120, 100%, 40%);">+ return res;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AST_TEST_DEFINE(crypto_sign)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int res = AST_TEST_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_key *key = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ const char plaintext[23] = "Mary had a little lamb.";</span><br><span style="color: hsl(120, 100%, 40%);">+ char wd[PATH_MAX], key_dir[PATH_MAX], pub[PATH_MAX];</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned char buf[AST_CRYPTO_RSA_KEY_BITS / 8];</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *command = "openssl";</span><br><span style="color: hsl(120, 100%, 40%);">+ char *args[] = { "openssl", "pkeyutl", "-verify", "-inkey", "PUBLIC", "-pubin", "-sigfile", "SIGNATURE", "-pkeyopt", "digest:sha1", NULL };</span><br><span style="color: hsl(120, 100%, 40%);">+ enum { PUBLIC = 4, SIGNATURE = 7 };</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_test_capture cap;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned char digest[20];</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned digestlen;</span><br><span style="color: hsl(120, 100%, 40%);">+ EVP_MD_CTX *ctx;</span><br><span style="color: hsl(120, 100%, 40%);">+ FILE *fsig = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ char signpath[64] = "/tmp/signingXXXXXX";</span><br><span style="color: hsl(120, 100%, 40%);">+ const char success[] = "Signature Verified Successfully\n";</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case TEST_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+ info->name = "crypto_sign";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->category = "/res/res_crypto/";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->summary = "Sign w/ RSA private key";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->description = "Sign string with RSA private key";</span><br><span style="color: hsl(120, 100%, 40%);">+ return AST_TEST_NOT_RUN;</span><br><span style="color: hsl(120, 100%, 40%);">+ case TEST_EXECUTE:</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Executing RSA signing test\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ast_check_command_in_path(command)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "couldn't find %s\n", command);</span><br><span style="color: hsl(120, 100%, 40%);">+ return res;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ getcwd(wd, sizeof(wd));</span><br><span style="color: hsl(120, 100%, 40%);">+ snprintf(key_dir, sizeof(key_dir), "%s/%s", wd, "tests/keys");</span><br><span style="color: hsl(120, 100%, 40%);">+ push_key_dir((const char *)key_dir);</span><br><span style="color: hsl(120, 100%, 40%);">+ snprintf(pub, sizeof(pub), "%s/%s.pub", key_dir, keypair1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ctx = EVP_MD_CTX_create();</span><br><span style="color: hsl(120, 100%, 40%);">+ EVP_DigestInit(ctx, EVP_sha1());</span><br><span style="color: hsl(120, 100%, 40%);">+ EVP_DigestUpdate(ctx, plaintext, sizeof(plaintext));</span><br><span style="color: hsl(120, 100%, 40%);">+ EVP_DigestFinal(ctx, digest, &digestlen);</span><br><span style="color: hsl(120, 100%, 40%);">+ EVP_MD_CTX_destroy(ctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ ctx = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_crypto_reload() != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Couldn't force crypto reload\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ key = ast_key_get(keypair1, AST_KEY_PRIVATE);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!key) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Couldn't read key: %s\n", keypair1);</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ memset(buf, 0, sizeof(buf));</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_sign_bin(key, plaintext, sizeof(plaintext), buf) != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "ast_sign_bin() failed\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ fsig = ast_file_mkftemp(signpath, 0600);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (fsig == NULL) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Couldn't open temp signing file\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ fwrite(buf, sizeof(char), sizeof(buf), fsig);</span><br><span style="color: hsl(120, 100%, 40%);">+ fclose(fsig);</span><br><span style="color: hsl(120, 100%, 40%);">+ fsig = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ args[PUBLIC] = pub;</span><br><span style="color: hsl(120, 100%, 40%);">+ args[SIGNATURE] = signpath;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_test_capture_command(&cap, command, args, (const char *)digest, digestlen) != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "ast_test_capture_command() failed\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cap.outlen != sizeof(success) - 1 || memcmp(cap.outbuf, success, cap.outlen)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Unexpected value/length for stdout: '%.*s' (%zu)\n", (int) cap.outlen, cap.outbuf, cap.outlen);</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cap.errlen != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Unexpected value for stderr: '%.*s' (%zu)\n", (int) cap.errlen, cap.errbuf, cap.errlen);</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cap.pid == -1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Invalid process id\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#if OPENSSL_VERSION_NUMBER >= 0x10100000L</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cap.exitcode != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+#else</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cap.exitcode != 0 && cap.exitcode != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Child exited %d\n", cap.exitcode);</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ res = AST_TEST_PASS;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+cleanup:</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_capture_free(&cap);</span><br><span style="color: hsl(120, 100%, 40%);">+ unlink(signpath);</span><br><span style="color: hsl(120, 100%, 40%);">+ pop_key_dir();</span><br><span style="color: hsl(120, 100%, 40%);">+ return res;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AST_TEST_DEFINE(crypto_verify)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int res = AST_TEST_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_key *key = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ const char plaintext[23] = "Mary had a little lamb.";</span><br><span style="color: hsl(120, 100%, 40%);">+ char wd[PATH_MAX], key_dir[PATH_MAX], priv[PATH_MAX];</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *command = "openssl";</span><br><span style="color: hsl(120, 100%, 40%);">+ char *args[] = { "openssl", "pkeyutl", "-sign", "-inkey", "PRIVATE", "-pkeyopt", "digest:sha1", NULL };</span><br><span style="color: hsl(120, 100%, 40%);">+ enum { PRIVATE = 4 };</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_test_capture cap;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned char digest[20];</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned digestlen;</span><br><span style="color: hsl(120, 100%, 40%);">+ EVP_MD_CTX *ctx;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case TEST_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+ info->name = "crypto_verify";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->category = "/res/res_crypto/";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->summary = "Verify w/ RSA public key";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->description = "Verify signature with RSA public key";</span><br><span style="color: hsl(120, 100%, 40%);">+ return AST_TEST_NOT_RUN;</span><br><span style="color: hsl(120, 100%, 40%);">+ case TEST_EXECUTE:</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Executing RSA signature verification test\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ast_check_command_in_path(command)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "couldn't find %s\n", command);</span><br><span style="color: hsl(120, 100%, 40%);">+ return res;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ getcwd(wd, sizeof(wd));</span><br><span style="color: hsl(120, 100%, 40%);">+ snprintf(key_dir, sizeof(key_dir), "%s/%s", wd, "tests/keys");</span><br><span style="color: hsl(120, 100%, 40%);">+ push_key_dir((const char *)key_dir);</span><br><span style="color: hsl(120, 100%, 40%);">+ snprintf(priv, sizeof(priv), "%s/%s.key", key_dir, keypair1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_crypto_reload() != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Couldn't force crypto reload\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ key = ast_key_get(keypair1, AST_KEY_PUBLIC);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!key) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Couldn't read key: %s\n", keypair1);</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ctx = EVP_MD_CTX_create();</span><br><span style="color: hsl(120, 100%, 40%);">+ EVP_DigestInit(ctx, EVP_sha1());</span><br><span style="color: hsl(120, 100%, 40%);">+ EVP_DigestUpdate(ctx, plaintext, sizeof(plaintext));</span><br><span style="color: hsl(120, 100%, 40%);">+ EVP_DigestFinal(ctx, digest, &digestlen);</span><br><span style="color: hsl(120, 100%, 40%);">+ EVP_MD_CTX_destroy(ctx);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ args[PRIVATE] = priv;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_test_capture_command(&cap, command, args, (const char *)digest, sizeof(digest)) != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "ast_test_capture_command() failed\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cap.outlen != (AST_CRYPTO_RSA_KEY_BITS / 8)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Unexpected length for stdout: %zu\n", cap.outlen);</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cap.errlen != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Unexpected value/length for stderr: '%.*s'\n", (int) cap.errlen, cap.errbuf);</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cap.pid == -1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Invalid process id\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cap.exitcode != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Child exited %d\n", cap.exitcode);</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_check_signature_bin(key, plaintext, sizeof(plaintext), (const unsigned char *)cap.outbuf) != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "ast_check_signature_bin() failed\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ res = AST_TEST_PASS;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+cleanup:</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_capture_free(&cap);</span><br><span style="color: hsl(120, 100%, 40%);">+ pop_key_dir();</span><br><span style="color: hsl(120, 100%, 40%);">+ return res;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AST_TEST_DEFINE(crypto_aes_encrypt)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int res = AST_TEST_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+ const unsigned char key[16] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ 0x01, 0x23, 0x45, 0x67, 0x89, 0x01, 0x23, 0x45,</span><br><span style="color: hsl(120, 100%, 40%);">+ 0x67, 0x89, 0x01, 0x23, 0x45, 0x67, 0x89, 0x01</span><br><span style="color: hsl(120, 100%, 40%);">+ };</span><br><span style="color: hsl(120, 100%, 40%);">+ const unsigned char plaintext[16] = "Mary had a littl";</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *command = "openssl";</span><br><span style="color: hsl(120, 100%, 40%);">+ char *args[] = { "openssl", "enc", "-aes-128-ecb", "-d", "-K", "KEY", "-nopad", NULL };</span><br><span style="color: hsl(120, 100%, 40%);">+ enum { KEY = 5 };</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_test_capture cap;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned char buf[16];</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_aes_encrypt_key aes_key;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case TEST_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+ info->name = "crypto_aes_encrypt";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->category = "/res/res_crypto/";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->summary = "Encrypt test AES-128-ECB";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->description = "Encrypt a test string using AES-128 and ECB";</span><br><span style="color: hsl(120, 100%, 40%);">+ return AST_TEST_NOT_RUN;</span><br><span style="color: hsl(120, 100%, 40%);">+ case TEST_EXECUTE:</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Executing AES-ECB encryption test\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ast_check_command_in_path(command)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "couldn't find %s\n", command);</span><br><span style="color: hsl(120, 100%, 40%);">+ return res;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ memset(buf, 0, sizeof(buf));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_aes_set_encrypt_key(key, &aes_key);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_aes_encrypt(plaintext, buf, &aes_key);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ args[KEY] = hexstring(key, sizeof(key));</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_test_capture_command(&cap, command, args, (const char *)buf, sizeof(buf)) != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "ast_test_capture_command() failed\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cap.outlen != sizeof(plaintext) || memcmp(cap.outbuf, plaintext, cap.outlen)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Unexpected value/length for stdout: '%.*s' (%zu)\n", (int) cap.outlen, cap.outbuf, cap.outlen);</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cap.errlen != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Unexpected value/length for stderr: '%.*s'\n", (int) cap.errlen, cap.errbuf);</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cap.pid == -1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Invalid process id\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cap.exitcode != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Child exited %d\n", cap.exitcode);</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ res = AST_TEST_PASS;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+cleanup:</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_capture_free(&cap);</span><br><span style="color: hsl(120, 100%, 40%);">+ return res;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AST_TEST_DEFINE(crypto_aes_decrypt)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int res = AST_TEST_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+ const unsigned char key[16] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ 0x01, 0x23, 0x45, 0x67, 0x89, 0x01, 0x23, 0x45,</span><br><span style="color: hsl(120, 100%, 40%);">+ 0x67, 0x89, 0x01, 0x23, 0x45, 0x67, 0x89, 0x01</span><br><span style="color: hsl(120, 100%, 40%);">+ };</span><br><span style="color: hsl(120, 100%, 40%);">+ const unsigned char plaintext[16] = "Mary had a littl";</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned char buf[16];</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *command = "openssl";</span><br><span style="color: hsl(120, 100%, 40%);">+ char *args[] = { "openssl", "enc", "-aes-128-ecb", "-e", "-K", "KEY", "-nopad", NULL };</span><br><span style="color: hsl(120, 100%, 40%);">+ enum { KEY = 5 };</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_test_capture cap;</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_aes_encrypt_key aes_key;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case TEST_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+ info->name = "crypto_aes_decrypt";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->category = "/res/res_crypto/";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->summary = "Decrypt test AES-128-ECB";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->description = "Decrypt a test string using AES-128 and ECB";</span><br><span style="color: hsl(120, 100%, 40%);">+ return AST_TEST_NOT_RUN;</span><br><span style="color: hsl(120, 100%, 40%);">+ case TEST_EXECUTE:</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Executing AES-ECB decryption test\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ast_check_command_in_path(command)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "couldn't find %s\n", command);</span><br><span style="color: hsl(120, 100%, 40%);">+ return res;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ args[KEY] = hexstring(key, sizeof(key));</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_test_capture_command(&cap, command, args, (const char *)plaintext, sizeof(plaintext)) != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "ast_test_capture_command() failed\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cap.outlen != sizeof(buf)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Unexpected length for stdout: %zu\n", cap.outlen);</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cap.errlen != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Unexpected value/length for stderr: '%.*s'\n", (int) cap.errlen, cap.errbuf);</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cap.pid == -1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Invalid process id\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cap.exitcode != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Child exited %d\n", cap.exitcode);</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ memset(buf, 0, sizeof(buf));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_aes_set_decrypt_key(key, &aes_key);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_aes_decrypt((const unsigned char *)cap.outbuf, buf, &aes_key);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (memcmp(plaintext, buf, sizeof(plaintext))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "AES decryption mismatch\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ goto cleanup;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ res = AST_TEST_PASS;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+cleanup:</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_capture_free(&cap);</span><br><span style="color: hsl(120, 100%, 40%);">+ return res;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int unload_module(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_TEST_UNREGISTER(crypto_rsa_encrypt);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_TEST_UNREGISTER(crypto_rsa_decrypt);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_TEST_UNREGISTER(crypto_sign);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_TEST_UNREGISTER(crypto_verify);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_TEST_UNREGISTER(crypto_aes_encrypt);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_TEST_UNREGISTER(crypto_aes_decrypt);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int load_module(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_TEST_REGISTER(crypto_rsa_encrypt);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_TEST_REGISTER(crypto_rsa_decrypt);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_TEST_REGISTER(crypto_sign);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_TEST_REGISTER(crypto_verify);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_TEST_REGISTER(crypto_aes_encrypt);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_TEST_REGISTER(crypto_aes_decrypt);</span><br><span style="color: hsl(120, 100%, 40%);">+ return AST_MODULE_LOAD_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Crypto test module",</span><br><span style="color: hsl(120, 100%, 40%);">+ .support_level = AST_MODULE_SUPPORT_CORE,</span><br><span style="color: hsl(120, 100%, 40%);">+ .load = load_module,</span><br><span style="color: hsl(120, 100%, 40%);">+ .unload = unload_module,</span><br><span style="color: hsl(120, 100%, 40%);">+ .requires = "res_crypto",</span><br><span style="color: hsl(120, 100%, 40%);">+);</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/19148">change 19148</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/c/asterisk/+/19148"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 20 </div>
<div style="display:none"> Gerrit-Change-Id: I0d10e7b41009c5290a4356c6480e636712d5c96d </div>
<div style="display:none"> Gerrit-Change-Number: 19148 </div>
<div style="display:none"> Gerrit-PatchSet: 2 </div>
<div style="display:none"> Gerrit-Owner: Philip Prindeville <philipp@redfish-solutions.com> </div>
<div style="display:none"> Gerrit-Reviewer: Friendly Automation </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>