Asterisk - The Open Source Telephony Project GIT-master-f36a736
Functions | Variables
test_crypto.c File Reference

Unit Tests for crypto API. More...

#include "asterisk.h"
#include "asterisk/utils.h"
#include "asterisk/test.h"
#include "asterisk/crypto.h"
#include "asterisk/paths.h"
#include "asterisk/module.h"
#include "asterisk/file.h"
#include <assert.h>
#include <sys/stat.h>
#include <limits.h>
#include <openssl/evp.h>
Include dependency graph for test_crypto.c:

Go to the source code of this file.

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
 AST_TEST_DEFINE (crypto_aes_decrypt)
 
 AST_TEST_DEFINE (crypto_aes_encrypt)
 
 AST_TEST_DEFINE (crypto_rsa_decrypt)
 
 AST_TEST_DEFINE (crypto_rsa_encrypt)
 
 AST_TEST_DEFINE (crypto_sign)
 
 AST_TEST_DEFINE (crypto_verify)
 
static char * hexstring (const unsigned char *data, unsigned datalen)
 
static int load_module (void)
 
static void pop_key_dir (void)
 
static void push_key_dir (const char *dir)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Crypto test module" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .requires = "res_crypto", }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static const char * keypair1 = "rsa_key1"
 
static const char * old_key_dir = NULL
 

Detailed Description

Unit Tests for crypto API.

Author
Philip Prindeville phili.nosp@m.pp@r.nosp@m.edfis.nosp@m.h-so.nosp@m.lutio.nosp@m.ns.c.nosp@m.om

Definition in file test_crypto.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 689 of file test_crypto.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 689 of file test_crypto.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 689 of file test_crypto.c.

◆ AST_TEST_DEFINE() [1/6]

AST_TEST_DEFINE ( crypto_aes_decrypt  )

Definition at line 581 of file test_crypto.c.

582{
583 int res = AST_TEST_FAIL;
584 const unsigned char key[16] = {
585 0x01, 0x23, 0x45, 0x67, 0x89, 0x01, 0x23, 0x45,
586 0x67, 0x89, 0x01, 0x23, 0x45, 0x67, 0x89, 0x01
587 };
588 const unsigned char plaintext[16] = "Mary had a littl";
589 unsigned char buf[16];
590 const char *command = "openssl";
591 char *args[] = { "openssl", "enc", "-aes-128-ecb", "-e", "-K", "KEY", "-nopad", NULL };
592 enum { KEY = 5 };
593 struct ast_test_capture cap;
595
596 switch (cmd) {
597 case TEST_INIT:
598 info->name = "crypto_aes_decrypt";
599 info->category = "/res/res_crypto/";
600 info->summary = "Decrypt test AES-128-ECB";
601 info->description = "Decrypt a test string using AES-128 and ECB";
602 return AST_TEST_NOT_RUN;
603 case TEST_EXECUTE:
604 break;
605 }
606
607 ast_test_status_update(test, "Executing AES-ECB decryption test\n");
608
609 ast_test_capture_init(&cap);
610
611 if (!ast_check_command_in_path(command)) {
612 ast_test_status_update(test, "couldn't find %s\n", command);
613 return res;
614 }
615
616 args[KEY] = hexstring(key, sizeof(key));
617 if (ast_test_capture_command(&cap, command, args, (const char *)plaintext, sizeof(plaintext)) != 1) {
618 ast_test_status_update(test, "ast_test_capture_command() failed\n");
619 goto cleanup;
620 }
621
622 if (cap.outlen != sizeof(buf)) {
623 ast_test_status_update(test, "Unexpected length for stdout: %zu\n", cap.outlen);
624 goto cleanup;
625 }
626
627 if (cap.errlen != 0) {
628 ast_test_status_update(test, "Unexpected value/length for stderr: '%.*s'\n", (int) cap.errlen, cap.errbuf);
629 goto cleanup;
630 }
631
632 if (cap.pid == -1) {
633 ast_test_status_update(test, "Invalid process id\n");
634 goto cleanup;
635 }
636
637 if (cap.exitcode != 0) {
638 ast_test_status_update(test, "Child exited %d\n", cap.exitcode);
639 goto cleanup;
640 }
641
642 memset(buf, 0, sizeof(buf));
644 if (ast_aes_decrypt((const unsigned char *)cap.outbuf, buf, &aes_key) <= 0) {
645 ast_test_status_update(test, "ast_aes_decrypt() failed\n");
646 goto cleanup;
647 }
648
649 if (memcmp(plaintext, buf, sizeof(plaintext))) {
650 ast_test_status_update(test, "AES decryption mismatch\n");
651 goto cleanup;
652 }
653
654 res = AST_TEST_PASS;
655
656cleanup:
657 ast_free(args[KEY]);
658 ast_test_capture_free(&cap);
659 return res;
660}
#define ast_free(a)
Definition: astmm.h:180
int ast_aes_set_decrypt_key(const unsigned char *key, ast_aes_decrypt_key *ctx)
Set a decryption key.
Definition: res_crypto.c:709
int ast_aes_decrypt(const unsigned char *in, unsigned char *out, const ast_aes_decrypt_key *key)
AES decrypt data.
Definition: res_crypto.c:790
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
def info(msg)
static void * cleanup(void *unused)
Definition: pbx_realtime.c:124
#define NULL
Definition: resample.c:96
Definition: crypto.h:39
A capture of running an external process.
Definition: test.h:217
@ TEST_INIT
Definition: test.h:200
@ TEST_EXECUTE
Definition: test.h:201
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
@ AST_TEST_PASS
Definition: test.h:195
@ AST_TEST_FAIL
Definition: test.h:196
@ AST_TEST_NOT_RUN
Definition: test.h:194
static char * hexstring(const unsigned char *data, unsigned datalen)
Definition: test_crypto.c:51
@ KEY
Definition: test_db.c:41
const char * args
int ast_check_command_in_path(const char *cmd)
Test for the presence of an executable command in $PATH.
Definition: utils.c:3263

References args, ast_aes_decrypt(), ast_aes_set_decrypt_key(), ast_check_command_in_path(), ast_free, AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, buf, cleanup(), ast_test_capture::errbuf, ast_test_capture::errlen, ast_test_capture::exitcode, hexstring(), sip_to_pjsip::info(), KEY, NULL, ast_test_capture::outbuf, ast_test_capture::outlen, ast_test_capture::pid, TEST_EXECUTE, and TEST_INIT.

◆ AST_TEST_DEFINE() [2/6]

AST_TEST_DEFINE ( crypto_aes_encrypt  )

Definition at line 505 of file test_crypto.c.

506{
507 int res = AST_TEST_FAIL;
508 const unsigned char key[16] = {
509 0x01, 0x23, 0x45, 0x67, 0x89, 0x01, 0x23, 0x45,
510 0x67, 0x89, 0x01, 0x23, 0x45, 0x67, 0x89, 0x01
511 };
512 const unsigned char plaintext[16] = "Mary had a littl";
513 const char *command = "openssl";
514 char *args[] = { "openssl", "enc", "-aes-128-ecb", "-d", "-K", "KEY", "-nopad", NULL };
515 enum { KEY = 5 };
516 struct ast_test_capture cap;
517 unsigned char buf[16];
519
520 switch (cmd) {
521 case TEST_INIT:
522 info->name = "crypto_aes_encrypt";
523 info->category = "/res/res_crypto/";
524 info->summary = "Encrypt test AES-128-ECB";
525 info->description = "Encrypt a test string using AES-128 and ECB";
526 return AST_TEST_NOT_RUN;
527 case TEST_EXECUTE:
528 break;
529 }
530
531 ast_test_status_update(test, "Executing AES-ECB encryption test\n");
532
533 ast_test_capture_init(&cap);
534
535 if (!ast_check_command_in_path(command)) {
536 ast_test_status_update(test, "couldn't find %s\n", command);
537 return res;
538 }
539
540 memset(buf, 0, sizeof(buf));
542 if (ast_aes_encrypt(plaintext, buf, &aes_key) <= 0) {
543 ast_test_status_update(test, "ast_aes_encrypt() failed\n");
544 goto cleanup;
545 }
546
547 args[KEY] = hexstring(key, sizeof(key));
548 if (ast_test_capture_command(&cap, command, args, (const char *)buf, sizeof(buf)) != 1) {
549 ast_test_status_update(test, "ast_test_capture_command() failed\n");
550 goto cleanup;
551 }
552
553 if (cap.outlen != sizeof(plaintext) || memcmp(cap.outbuf, plaintext, cap.outlen)) {
554 ast_test_status_update(test, "Unexpected value/length for stdout: '%.*s' (%zu)\n", (int) cap.outlen, cap.outbuf, cap.outlen);
555 goto cleanup;
556 }
557
558 if (cap.errlen != 0) {
559 ast_test_status_update(test, "Unexpected value/length for stderr: '%.*s'\n", (int) cap.errlen, cap.errbuf);
560 goto cleanup;
561 }
562
563 if (cap.pid == -1) {
564 ast_test_status_update(test, "Invalid process id\n");
565 goto cleanup;
566 }
567
568 if (cap.exitcode != 0) {
569 ast_test_status_update(test, "Child exited %d\n", cap.exitcode);
570 goto cleanup;
571 }
572
573 res = AST_TEST_PASS;
574
575cleanup:
576 ast_free(args[KEY]);
577 ast_test_capture_free(&cap);
578 return res;
579}
int ast_aes_set_encrypt_key(const unsigned char *key, ast_aes_encrypt_key *ctx)
Set an encryption key.
Definition: res_crypto.c:700
int ast_aes_encrypt(const unsigned char *in, unsigned char *out, const ast_aes_encrypt_key *key)
AES encrypt data.
Definition: res_crypto.c:749

References args, ast_aes_encrypt(), ast_aes_set_encrypt_key(), ast_check_command_in_path(), ast_free, AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, buf, cleanup(), ast_test_capture::errbuf, ast_test_capture::errlen, ast_test_capture::exitcode, hexstring(), sip_to_pjsip::info(), KEY, NULL, ast_test_capture::outbuf, ast_test_capture::outlen, ast_test_capture::pid, TEST_EXECUTE, and TEST_INIT.

◆ AST_TEST_DEFINE() [3/6]

AST_TEST_DEFINE ( crypto_rsa_decrypt  )

Definition at line 179 of file test_crypto.c.

180{
181 int res = AST_TEST_FAIL;
182 struct ast_key *key = NULL;
183 const unsigned char plaintext[23] = "Mary had a little lamb.";
184 char wd[PATH_MAX], key_dir[PATH_MAX], pub[PATH_MAX];
185 unsigned char buf[AST_CRYPTO_RSA_KEY_BITS / 8];
186 const char *command = "openssl";
187 char *args[] = { "openssl", "pkeyutl", "-encrypt", "-pubin", "-inkey", "PUBLIC", "-pkeyopt", "rsa_padding_mode:oaep", NULL };
188 enum { PUBLIC = 5 };
189 struct ast_test_capture cap;
190 int len;
191
192 switch (cmd) {
193 case TEST_INIT:
194 info->name = "crypto_decrypt_pub_key";
195 info->category = "/res/res_crypto/";
196 info->summary = "Decrypt w/ RSA public key";
197 info->description = "Decrypt string with RSA private key";
198 return AST_TEST_NOT_RUN;
199 case TEST_EXECUTE:
200 break;
201 }
202
203 ast_test_status_update(test, "Executing RSA decryption test\n");
204
205 ast_test_capture_init(&cap);
206
207 if (!ast_check_command_in_path(command)) {
208 ast_test_status_update(test, "couldn't find %s\n", command);
209 ast_test_capture_free(&cap);
210 return res;
211 }
212
213 if (getcwd(wd, sizeof(wd)) == NULL) {
214 ast_test_status_update(test, "Could not determine current working directory\n");
215 ast_test_capture_free(&cap);
216 return res;
217 }
218
219 snprintf(key_dir, sizeof(key_dir), "%s/%s", wd, "tests/keys");
220 push_key_dir((const char *)key_dir);
221 snprintf(pub, sizeof(pub), "%s/%s.pub", key_dir, keypair1);
222
223 if (ast_crypto_reload() != 1) {
224 ast_test_status_update(test, "Couldn't force crypto reload\n");
225 goto cleanup;
226 }
227
229
230 if (!key) {
231 ast_test_status_update(test, "Couldn't read key: %s\n", keypair1);
232 goto cleanup;
233 }
234
235 args[PUBLIC] = pub;
236 if (ast_test_capture_command(&cap, command, args, (const char *)plaintext, sizeof(plaintext)) != 1) {
237 ast_test_status_update(test, "ast_test_capture_command() failed\n");
238 goto cleanup;
239 }
240
241 if (cap.outlen != sizeof(buf)) {
242 ast_test_status_update(test, "Unexpected length for stdout: %zu\n", cap.outlen);
243 goto cleanup;
244 }
245
246 if (cap.errlen != 0) {
247 ast_test_status_update(test, "Unexpected value/length for stderr: '%.*s' (%zu)\n", (int) cap.errlen, cap.errbuf, cap.errlen);
248 goto cleanup;
249 }
250
251 if (cap.pid == -1) {
252 ast_test_status_update(test, "Invalid process id\n");
253 goto cleanup;
254 }
255
256 if (cap.exitcode != 0) {
257 ast_test_status_update(test, "Child exited %d\n", cap.exitcode);
258 goto cleanup;
259 }
260
261 memset(buf, 0, sizeof(buf));
262 len = ast_decrypt_bin(buf, (unsigned char *)cap.outbuf, cap.outlen, key);
263
264 if (len != sizeof(plaintext) || memcmp(buf, plaintext, len)) {
265 ast_test_status_update(test, "Unexpected value for decrypted text\n");
266 goto cleanup;
267 }
268
269 res = AST_TEST_PASS;
270
271cleanup:
272 ast_test_capture_free(&cap);
273 pop_key_dir();
274 return res;
275}
#define PATH_MAX
Definition: asterisk.h:40
struct ast_key * ast_key_get(const char *kname, int ktype)
Retrieve a key.
Definition: res_crypto.c:149
#define AST_KEY_PRIVATE
Definition: crypto.h:47
#define AST_CRYPTO_RSA_KEY_BITS
Definition: crypto.h:36
int ast_decrypt_bin(unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key)
Decrypt a message using a given private key.
Definition: res_crypto.c:472
int ast_crypto_reload(void)
Definition: res_crypto.c:694
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static const char * keypair1
Definition: test_crypto.c:47
static void push_key_dir(const char *dir)
Definition: test_crypto.c:64
static void pop_key_dir(void)
Definition: test_crypto.c:73

References args, ast_check_command_in_path(), ast_crypto_reload(), AST_CRYPTO_RSA_KEY_BITS, ast_decrypt_bin(), ast_key_get(), AST_KEY_PRIVATE, AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, buf, cleanup(), ast_test_capture::errbuf, ast_test_capture::errlen, ast_test_capture::exitcode, sip_to_pjsip::info(), keypair1, len(), NULL, ast_test_capture::outbuf, ast_test_capture::outlen, PATH_MAX, ast_test_capture::pid, pop_key_dir(), push_key_dir(), TEST_EXECUTE, and TEST_INIT.

◆ AST_TEST_DEFINE() [4/6]

AST_TEST_DEFINE ( crypto_rsa_encrypt  )

Definition at line 84 of file test_crypto.c.

85{
86 int res = AST_TEST_FAIL;
87 struct ast_key *key = NULL;
88 const unsigned char plaintext[23] = "Mary had a little lamb.";
89 char wd[PATH_MAX], key_dir[PATH_MAX], priv[PATH_MAX];
90 unsigned char buf[AST_CRYPTO_RSA_KEY_BITS / 8];
91 const char *command = "openssl";
92 char *args[] = { "openssl", "pkeyutl", "-decrypt", "-inkey", "PRIVATE", "-pkeyopt", "rsa_padding_mode:oaep", NULL };
93 enum { PRIVATE = 4 };
94 struct ast_test_capture cap;
95
96 switch (cmd) {
97 case TEST_INIT:
98 info->name = "crypto_rsa_encrypt";
99 info->category = "/res/res_crypto/";
100 info->summary = "Encrypt w/ RSA public key";
101 info->description = "Encrypt string with RSA public key";
102 return AST_TEST_NOT_RUN;
103 case TEST_EXECUTE:
104 break;
105 }
106
107 ast_test_status_update(test, "Executing RSA encryption test\n");
108
109 ast_test_capture_init(&cap);
110
111 if (!ast_check_command_in_path(command)) {
112 ast_test_status_update(test, "couldn't find %s\n", command);
113 ast_test_capture_free(&cap);
114 return res;
115 }
116
117 if (getcwd(wd, sizeof(wd)) == NULL) {
118 ast_test_status_update(test, "Could not determine current working directory\n");
119 ast_test_capture_free(&cap);
120 return res;
121 }
122
123 snprintf(key_dir, sizeof(key_dir), "%s/%s", wd, "tests/keys");
124 push_key_dir((const char *)key_dir);
125 snprintf(priv, sizeof(priv), "%s/%s.key", key_dir, keypair1);
126
127 /* because git doesn't preserve permissions */
128 (void)chmod(priv, 0400);
129
130 if (ast_crypto_reload() != 1) {
131 ast_test_status_update(test, "Couldn't force crypto reload\n");
132 goto cleanup;
133 }
134
136
137 if (!key) {
138 ast_test_status_update(test, "Couldn't read key: %s\n", keypair1);
139 goto cleanup;
140 }
141
142 memset(buf, 0, sizeof(buf));
143 ast_encrypt_bin(buf, plaintext, sizeof(plaintext), key);
144
145 args[PRIVATE] = priv;
146 if (ast_test_capture_command(&cap, command, args, (const char *)buf, sizeof(buf)) != 1) {
147 ast_test_status_update(test, "ast_test_capture_command() failed\n");
148 goto cleanup;
149 }
150
151 if (cap.outlen != sizeof(plaintext) || memcmp(cap.outbuf, plaintext, cap.outlen)) {
152 ast_test_status_update(test, "Unexpected value/length for stdout: '%.*s' (%zu)\n", (int) cap.outlen, cap.outbuf, cap.outlen);
153 goto cleanup;
154 }
155
156 if (cap.errlen != 0) {
157 ast_test_status_update(test, "Unexpected length for stderr: '%.*s' (%zu)\n", (int) cap.errlen, cap.errbuf, cap.errlen);
158 goto cleanup;
159 }
160
161 if (cap.pid == -1) {
162 ast_test_status_update(test, "Invalid process id\n");
163 goto cleanup;
164 }
165
166 if (cap.exitcode != 0) {
167 ast_test_status_update(test, "Child exited %d\n", cap.exitcode);
168 goto cleanup;
169 }
170
171 res = AST_TEST_PASS;
172
173cleanup:
174 ast_test_capture_free(&cap);
175 pop_key_dir();
176 return res;
177}
#define AST_KEY_PUBLIC
Definition: crypto.h:46
int ast_encrypt_bin(unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key)
Encrypt a message using a given private key.
Definition: res_crypto.c:549

References args, ast_check_command_in_path(), ast_crypto_reload(), AST_CRYPTO_RSA_KEY_BITS, ast_encrypt_bin(), ast_key_get(), AST_KEY_PUBLIC, AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, buf, cleanup(), ast_test_capture::errbuf, ast_test_capture::errlen, ast_test_capture::exitcode, sip_to_pjsip::info(), keypair1, NULL, ast_test_capture::outbuf, ast_test_capture::outlen, PATH_MAX, ast_test_capture::pid, pop_key_dir(), push_key_dir(), TEST_EXECUTE, and TEST_INIT.

◆ AST_TEST_DEFINE() [5/6]

AST_TEST_DEFINE ( crypto_sign  )

Definition at line 277 of file test_crypto.c.

278{
279 int res = AST_TEST_FAIL;
280 struct ast_key *key = NULL;
281 const char plaintext[23] = "Mary had a little lamb.";
282 char wd[PATH_MAX], key_dir[PATH_MAX], pub[PATH_MAX];
283 unsigned char buf[AST_CRYPTO_RSA_KEY_BITS / 8];
284 const char *command = "openssl";
285 char *args[] = { "openssl", "pkeyutl", "-verify", "-inkey", "PUBLIC", "-pubin", "-sigfile", "SIGNATURE", "-pkeyopt", "digest:sha1", NULL };
286 enum { PUBLIC = 4, SIGNATURE = 7 };
287 struct ast_test_capture cap;
288 unsigned char digest[20];
289 unsigned digestlen;
290 EVP_MD_CTX *ctx;
291 FILE *fsig = NULL;
292 char signpath[64] = "/tmp/signingXXXXXX";
293 const char success[] = "Signature Verified Successfully\n";
294
295 switch (cmd) {
296 case TEST_INIT:
297 info->name = "crypto_sign";
298 info->category = "/res/res_crypto/";
299 info->summary = "Sign w/ RSA private key";
300 info->description = "Sign string with RSA private key";
301 return AST_TEST_NOT_RUN;
302 case TEST_EXECUTE:
303 break;
304 }
305
306 ast_test_status_update(test, "Executing RSA signing test\n");
307
308 ast_test_capture_init(&cap);
309
310 if (!ast_check_command_in_path(command)) {
311 ast_test_status_update(test, "couldn't find %s\n", command);
312 ast_test_capture_free(&cap);
313 return res;
314 }
315
316 if (getcwd(wd, sizeof(wd)) == NULL) {
317 ast_test_status_update(test, "Could not determine current working directory\n");
318 ast_test_capture_free(&cap);
319 return res;
320 }
321
322 snprintf(key_dir, sizeof(key_dir), "%s/%s", wd, "tests/keys");
323 push_key_dir((const char *)key_dir);
324 snprintf(pub, sizeof(pub), "%s/%s.pub", key_dir, keypair1);
325
326 ctx = EVP_MD_CTX_create();
327 EVP_DigestInit(ctx, EVP_sha1());
328 EVP_DigestUpdate(ctx, plaintext, sizeof(plaintext));
329 EVP_DigestFinal(ctx, digest, &digestlen);
330 EVP_MD_CTX_destroy(ctx);
331 ctx = NULL;
332
333 if (ast_crypto_reload() != 1) {
334 ast_test_status_update(test, "Couldn't force crypto reload\n");
335 goto cleanup;
336 }
337
339
340 if (!key) {
341 ast_test_status_update(test, "Couldn't read key: %s\n", keypair1);
342 goto cleanup;
343 }
344
345 memset(buf, 0, sizeof(buf));
346 if (ast_sign_bin(key, plaintext, sizeof(plaintext), buf) != 0) {
347 ast_test_status_update(test, "ast_sign_bin() failed\n");
348 goto cleanup;
349 }
350
351 fsig = ast_file_mkftemp(signpath, 0600);
352 if (fsig == NULL) {
353 ast_test_status_update(test, "Couldn't open temp signing file\n");
354 goto cleanup;
355 }
356 fwrite(buf, sizeof(char), sizeof(buf), fsig);
357 fclose(fsig);
358 fsig = NULL;
359
360 args[PUBLIC] = pub;
361 args[SIGNATURE] = signpath;
362 if (ast_test_capture_command(&cap, command, args, (const char *)digest, digestlen) != 1) {
363 ast_test_status_update(test, "ast_test_capture_command() failed\n");
364 goto cleanup;
365 }
366
367 if (cap.outlen != sizeof(success) - 1 || memcmp(cap.outbuf, success, cap.outlen)) {
368 ast_test_status_update(test, "Unexpected value/length for stdout: '%.*s' (%zu)\n", (int) cap.outlen, cap.outbuf, cap.outlen);
369 goto cleanup;
370 }
371
372 if (cap.errlen != 0) {
373 ast_test_status_update(test, "Unexpected value for stderr: '%.*s' (%zu)\n", (int) cap.errlen, cap.errbuf, cap.errlen);
374 goto cleanup;
375 }
376
377 if (cap.pid == -1) {
378 ast_test_status_update(test, "Invalid process id\n");
379 goto cleanup;
380 }
381
382#if OPENSSL_VERSION_NUMBER >= 0x10100000L
383 if (cap.exitcode != 0) {
384#else
385 if (cap.exitcode != 0 && cap.exitcode != 1) {
386#endif
387 ast_test_status_update(test, "Child exited %d\n", cap.exitcode);
388 goto cleanup;
389 }
390
391 res = AST_TEST_PASS;
392
393cleanup:
394 ast_test_capture_free(&cap);
395 unlink(signpath);
396 pop_key_dir();
397 return res;
398}
int ast_sign_bin(struct ast_key *key, const char *msg, int msglen, unsigned char *dsig)
Sign a message signature using a given private key.
Definition: res_crypto.c:390
FILE * ast_file_mkftemp(char *template_name, mode_t mode)
same as mkstemp, but return a FILE
Definition: file.c:187

References args, ast_check_command_in_path(), ast_crypto_reload(), AST_CRYPTO_RSA_KEY_BITS, ast_file_mkftemp(), ast_key_get(), AST_KEY_PRIVATE, ast_sign_bin(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, buf, cleanup(), ast_test_capture::errbuf, ast_test_capture::errlen, ast_test_capture::exitcode, sip_to_pjsip::info(), keypair1, NULL, ast_test_capture::outbuf, ast_test_capture::outlen, PATH_MAX, ast_test_capture::pid, pop_key_dir(), push_key_dir(), TEST_EXECUTE, and TEST_INIT.

◆ AST_TEST_DEFINE() [6/6]

AST_TEST_DEFINE ( crypto_verify  )

Definition at line 400 of file test_crypto.c.

401{
402 int res = AST_TEST_FAIL;
403 struct ast_key *key = NULL;
404 const char plaintext[23] = "Mary had a little lamb.";
405 char wd[PATH_MAX], key_dir[PATH_MAX], priv[PATH_MAX];
406 const char *command = "openssl";
407 char *args[] = { "openssl", "pkeyutl", "-sign", "-inkey", "PRIVATE", "-pkeyopt", "digest:sha1", NULL };
408 enum { PRIVATE = 4 };
409 struct ast_test_capture cap;
410 unsigned char digest[20];
411 unsigned digestlen;
412 EVP_MD_CTX *ctx;
413
414 switch (cmd) {
415 case TEST_INIT:
416 info->name = "crypto_verify";
417 info->category = "/res/res_crypto/";
418 info->summary = "Verify w/ RSA public key";
419 info->description = "Verify signature with RSA public key";
420 return AST_TEST_NOT_RUN;
421 case TEST_EXECUTE:
422 break;
423 }
424
425 ast_test_status_update(test, "Executing RSA signature verification test\n");
426
427 ast_test_capture_init(&cap);
428
429 if (!ast_check_command_in_path(command)) {
430 ast_test_status_update(test, "couldn't find %s\n", command);
431 ast_test_capture_free(&cap);
432 return res;
433 }
434
435 if (getcwd(wd, sizeof(wd)) == NULL) {
436 ast_test_status_update(test, "Could not determine current working directory\n");
437 ast_test_capture_free(&cap);
438 return res;
439 }
440
441 snprintf(key_dir, sizeof(key_dir), "%s/%s", wd, "tests/keys");
442 push_key_dir((const char *)key_dir);
443 snprintf(priv, sizeof(priv), "%s/%s.key", key_dir, keypair1);
444
445 /* because git doesn't preserve permissions */
446 (void)chmod(priv, 0400);
447
448 if (ast_crypto_reload() != 1) {
449 ast_test_status_update(test, "Couldn't force crypto reload\n");
450 goto cleanup;
451 }
452
454
455 if (!key) {
456 ast_test_status_update(test, "Couldn't read key: %s\n", keypair1);
457 goto cleanup;
458 }
459
460 ctx = EVP_MD_CTX_create();
461 EVP_DigestInit(ctx, EVP_sha1());
462 EVP_DigestUpdate(ctx, plaintext, sizeof(plaintext));
463 EVP_DigestFinal(ctx, digest, &digestlen);
464 EVP_MD_CTX_destroy(ctx);
465
466 args[PRIVATE] = priv;
467 if (ast_test_capture_command(&cap, command, args, (const char *)digest, sizeof(digest)) != 1) {
468 ast_test_status_update(test, "ast_test_capture_command() failed\n");
469 goto cleanup;
470 }
471
472 if (cap.outlen != (AST_CRYPTO_RSA_KEY_BITS / 8)) {
473 ast_test_status_update(test, "Unexpected length for stdout: %zu\n", cap.outlen);
474 goto cleanup;
475 }
476
477 if (cap.errlen != 0) {
478 ast_test_status_update(test, "Unexpected value/length for stderr: '%.*s'\n", (int) cap.errlen, cap.errbuf);
479 goto cleanup;
480 }
481
482 if (cap.pid == -1) {
483 ast_test_status_update(test, "Invalid process id\n");
484 goto cleanup;
485 }
486
487 if (cap.exitcode != 0) {
488 ast_test_status_update(test, "Child exited %d\n", cap.exitcode);
489 goto cleanup;
490 }
491
492 if (ast_check_signature_bin(key, plaintext, sizeof(plaintext), (const unsigned char *)cap.outbuf) != 0) {
493 ast_test_status_update(test, "ast_check_signature_bin() failed\n");
494 goto cleanup;
495 }
496
497 res = AST_TEST_PASS;
498
499cleanup:
500 ast_test_capture_free(&cap);
501 pop_key_dir();
502 return res;
503}
int ast_check_signature_bin(struct ast_key *key, const char *msg, int msglen, const unsigned char *dsig)
Check the authenticity of a message signature using a given public key.
Definition: res_crypto.c:634

References args, ast_check_command_in_path(), ast_check_signature_bin(), ast_crypto_reload(), AST_CRYPTO_RSA_KEY_BITS, ast_key_get(), AST_KEY_PUBLIC, AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, cleanup(), ast_test_capture::errbuf, ast_test_capture::errlen, ast_test_capture::exitcode, sip_to_pjsip::info(), keypair1, NULL, ast_test_capture::outbuf, ast_test_capture::outlen, PATH_MAX, ast_test_capture::pid, pop_key_dir(), push_key_dir(), TEST_EXECUTE, and TEST_INIT.

◆ hexstring()

static char * hexstring ( const unsigned char *  data,
unsigned  datalen 
)
static

Definition at line 51 of file test_crypto.c.

52{
53 char *buf = ast_malloc(datalen * 2 + 1);
54 unsigned n;
55
56 for (n = 0; n < datalen; ++n) {
57 snprintf(&buf[n * 2], 3, "%02x", data[n]);
58 }
59 buf[datalen * 2] = '\0';
60
61 return buf;
62}
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191

References ast_malloc, and buf.

Referenced by AST_TEST_DEFINE().

◆ load_module()

static int load_module ( void  )
static

Definition at line 673 of file test_crypto.c.

674{
675 AST_TEST_REGISTER(crypto_rsa_encrypt);
676 AST_TEST_REGISTER(crypto_rsa_decrypt);
677 AST_TEST_REGISTER(crypto_sign);
678 AST_TEST_REGISTER(crypto_verify);
679 AST_TEST_REGISTER(crypto_aes_encrypt);
680 AST_TEST_REGISTER(crypto_aes_decrypt);
682}
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
#define AST_TEST_REGISTER(cb)
Definition: test.h:127

References AST_MODULE_LOAD_SUCCESS, and AST_TEST_REGISTER.

◆ pop_key_dir()

static void pop_key_dir ( void  )
static

Definition at line 73 of file test_crypto.c.

74{
75 assert(old_key_dir != NULL);
76
78
80
82}
const char * ast_config_AST_KEY_DIR
Definition: options.c:161
static const char * old_key_dir
Definition: test_crypto.c:49

References ast_config_AST_KEY_DIR, ast_free, NULL, and old_key_dir.

Referenced by AST_TEST_DEFINE().

◆ push_key_dir()

static void push_key_dir ( const char *  dir)
static

Definition at line 64 of file test_crypto.c.

65{
66 assert(old_key_dir == NULL);
67
69
71}
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241

References ast_config_AST_KEY_DIR, ast_strdup, NULL, and old_key_dir.

Referenced by AST_TEST_DEFINE().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 662 of file test_crypto.c.

663{
664 AST_TEST_UNREGISTER(crypto_rsa_encrypt);
665 AST_TEST_UNREGISTER(crypto_rsa_decrypt);
666 AST_TEST_UNREGISTER(crypto_sign);
667 AST_TEST_UNREGISTER(crypto_verify);
668 AST_TEST_UNREGISTER(crypto_aes_encrypt);
669 AST_TEST_UNREGISTER(crypto_aes_decrypt);
670 return 0;
671}
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128

References AST_TEST_UNREGISTER.

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Crypto test module" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .requires = "res_crypto", }
static

Definition at line 689 of file test_crypto.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 689 of file test_crypto.c.

◆ keypair1

const char* keypair1 = "rsa_key1"
static

Definition at line 47 of file test_crypto.c.

Referenced by AST_TEST_DEFINE().

◆ old_key_dir

const char* old_key_dir = NULL
static

Definition at line 49 of file test_crypto.c.

Referenced by pop_key_dir(), and push_key_dir().