39#include <openssl/err.h>
40#include <openssl/ssl.h>
41#include <openssl/evp.h>
42#include <openssl/md5.h>
43#include <openssl/sha.h>
73#define KEY_NEEDS_PASSCODE (1 << 16)
78#define RSA_PKCS1_OAEP_PADDING_SIZE (1 + 2 * SHA_DIGEST_LENGTH)
96 unsigned char digest[MD5_DIGEST_LENGTH];
112static int pw_cb(
char *
buf,
int size,
int rwflag,
void *userdata)
125 snprintf(
prompt,
sizeof(
prompt),
">>>> passcode for %s key '%s': ",
133 memset(
buf, 0, size);
134 res = read(key->
infd,
buf, size);
139 if (
buf[strlen(
buf) -1] ==
'\n') {
140 buf[strlen(
buf) - 1] =
'\0';
155 if (!strcmp(kname, key->
name) &&
177 int n,
ktype = 0, found = 0;
178 const char *
c =
NULL;
180 unsigned char digest[MD5_DIGEST_LENGTH];
183 EVP_MD_CTX *ctx =
NULL;
185 static int notice = 0;
187 size_t fnamelen = strlen(fname);
190 if (fnamelen > 4 && !strcmp((
c = &fname[fnamelen - 4]),
".pub")) {
192 }
else if (fnamelen > 4 && !strcmp((
c = &fname[fnamelen - 4]),
".key")) {
199 n = snprintf(ffname,
sizeof(ffname),
"%s/%s", dir, fname);
200 if (n >=
sizeof(ffname)) {
202 "Key filenames can be up to %zu bytes long, but the filename for the"
203 " key we are currently trying to load (%s/%s) is %d bytes long.",
204 sizeof(ffname) - 1, dir, fname, n);
209 if (!(f = fopen(ffname,
"r"))) {
214 n = fstat(fileno(f), &st);
221 if (!S_ISREG(st.st_mode)) {
230#define FILE_MODE_BITS (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)
240 ctx = EVP_MD_CTX_create();
246 EVP_DigestInit(ctx, EVP_md5());
251 if (!fgets(
buf,
sizeof(
buf), f)) {
255 EVP_DigestUpdate(ctx, (
unsigned char *)
buf, strlen(
buf));
258 EVP_DigestFinal(ctx, digest, &digestlen);
259 EVP_MD_CTX_destroy(ctx);
263 if (!strcasecmp(key->
fn, ffname)) {
271 if (!memcmp(digest, key->
digest,
sizeof(digest)) &&
293 snprintf(key->
name,
sizeof(key->
name),
"%.*s", (
int)(
c - fname), fname);
306 PEM_read_PUBKEY(f, &key->
pkey,
pw_cb, key);
308 PEM_read_PrivateKey(f, &key->
pkey,
pw_cb, key);
314 key->
ktype &= ~KEY_NEEDS_PASSCODE;
321 }
else if (key->
infd != -2) {
324 ERR_print_errors_fp(stderr);
326 ERR_print_errors_fp(stderr);
333 ast_log(
LOG_NOTICE,
"Add the '-i' flag to the asterisk command line if you want to automatically initialize passcodes at launch.\n");
351static int evp_pkey_sign(EVP_PKEY *pkey,
const unsigned char *
in,
unsigned inlen,
unsigned char *sig,
unsigned *siglen,
unsigned padding)
353 EVP_PKEY_CTX *ctx =
NULL;
357 if (*siglen < EVP_PKEY_size(pkey)) {
361 if ((ctx = EVP_PKEY_CTX_new(pkey,
NULL)) ==
NULL) {
366 if ((res = EVP_PKEY_sign_init(ctx)) <= 0) {
369 if ((res = EVP_PKEY_CTX_set_rsa_padding(ctx, padding)) <= 0) {
372 if ((res = EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha1())) <= 0) {
376 if ((res = EVP_PKEY_sign(ctx, sig, &_siglen,
in, inlen)) <= 0) {
382 EVP_PKEY_CTX_free(ctx);
392 unsigned char digest[SHA_DIGEST_LENGTH];
393 unsigned digestlen, siglen = 128;
395 EVP_MD_CTX *ctx =
NULL;
402 if (siglen < EVP_PKEY_size(key->
pkey)) {
408 ctx = EVP_MD_CTX_create();
413 EVP_DigestInit(ctx, EVP_sha1());
414 EVP_DigestUpdate(ctx, msg, msglen);
415 EVP_DigestFinal(ctx,
digest, &digestlen);
416 EVP_MD_CTX_destroy(ctx);
424 if (siglen != EVP_PKEY_size(key->
pkey)) {
432static int evp_pkey_decrypt(EVP_PKEY *
pkey,
const unsigned char *
in,
unsigned inlen,
unsigned char *
out,
unsigned *outlen,
unsigned padding)
434 EVP_PKEY_CTX *ctx =
NULL;
438 if (*outlen < EVP_PKEY_size(
pkey)) {
442 if (inlen != EVP_PKEY_size(
pkey)) {
451 if ((res = EVP_PKEY_decrypt_init(ctx)) <= 0) {
454 if ((res = EVP_PKEY_CTX_set_rsa_padding(ctx, padding)) <= 0) {
458 if ((res = EVP_PKEY_decrypt(ctx,
out, &_outlen,
in, inlen)) <= 0) {
461 res = *outlen = _outlen;
464 EVP_PKEY_CTX_free(ctx);
475 unsigned pos = 0, dstlen, blocksize;
482 blocksize = EVP_PKEY_size(key->
pkey);
484 if (srclen % blocksize) {
485 ast_log(
LOG_NOTICE,
"Tried to decrypt something not a multiple of %u bytes\n", blocksize);
492 if ((res =
evp_pkey_decrypt(key->
pkey, src, blocksize, dst, &dstlen, RSA_PKCS1_OAEP_PADDING)) <= 0) {
504static int evp_pkey_encrypt(EVP_PKEY *
pkey,
const unsigned char *
in,
unsigned inlen,
unsigned char *
out,
unsigned *outlen,
unsigned padding)
506 EVP_PKEY_CTX *ctx =
NULL;
510 if (padding != RSA_PKCS1_OAEP_PADDING) {
519 if (*outlen < EVP_PKEY_size(
pkey)) {
528 if ((res = EVP_PKEY_encrypt_init(ctx)) <= 0) {
531 if ((res = EVP_PKEY_CTX_set_rsa_padding(ctx, padding)) <= 0) {
535 if ((res = EVP_PKEY_encrypt(ctx,
out, &_outlen,
in, inlen)) <= 0) {
538 res = *outlen = _outlen;
541 EVP_PKEY_CTX_free(ctx);
551 unsigned bytes, pos = 0, dstlen, blocksize;
559 blocksize = EVP_PKEY_size(key->
pkey);
568 if ((res =
evp_pkey_encrypt(key->
pkey, src, bytes, dst, &dstlen, RSA_PKCS1_OAEP_PADDING)) != blocksize) {
587 unsigned char dsig[128];
588 int siglen =
sizeof(dsig), res;
590 if (!(res =
ast_sign_bin(key, msg, strlen(msg), dsig))) {
598static int evp_pkey_verify(EVP_PKEY *
pkey,
const unsigned char *
in,
unsigned inlen,
const unsigned char *sig,
unsigned siglen,
unsigned padding)
600 EVP_PKEY_CTX *ctx =
NULL;
603 if (siglen < EVP_PKEY_size(
pkey)) {
612 if ((res = EVP_PKEY_verify_init(ctx)) <= 0) {
615 if ((res = EVP_PKEY_CTX_set_rsa_padding(ctx, padding)) <= 0) {
618 if ((res = EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha1())) <= 0) {
621 if ((res = EVP_PKEY_verify(ctx, sig, siglen,
in, inlen)) <= 0) {
626 EVP_PKEY_CTX_free(ctx);
636 unsigned char digest[SHA_DIGEST_LENGTH];
639 EVP_MD_CTX *ctx =
NULL;
649 ctx = EVP_MD_CTX_create();
654 EVP_DigestInit(ctx, EVP_sha1());
655 EVP_DigestUpdate(ctx, msg, msglen);
656 EVP_DigestFinal(ctx,
digest, &digestlen);
657 EVP_MD_CTX_destroy(ctx);
675 unsigned char dsig[128];
680 ast_log(
LOG_WARNING,
"Signature improper length (expect %d, got %d)\n", (
int)
sizeof(dsig), (
int)res);
720 EVP_CIPHER_CTX *ctx =
NULL;
721 int res, outlen, finallen;
724 if ((ctx = EVP_CIPHER_CTX_new()) ==
NULL) {
729 if ((res = EVP_CipherInit(ctx, EVP_aes_128_ecb(), key->
raw,
NULL, 1)) <= 0) {
732 EVP_CIPHER_CTX_set_padding(ctx, 0);
733 if ((res = EVP_CipherUpdate(ctx,
out, &outlen,
in, inlen)) <= 0) {
737 if ((res = EVP_CipherFinal(ctx,
final, &finallen)) <= 0) {
744 EVP_CIPHER_CTX_free(ctx);
761 EVP_CIPHER_CTX *ctx =
NULL;
762 int res, outlen, finallen;
765 if ((ctx = EVP_CIPHER_CTX_new()) ==
NULL) {
770 if ((res = EVP_CipherInit(ctx, EVP_aes_128_ecb(), key->
raw,
NULL, 0)) <= 0) {
773 EVP_CIPHER_CTX_set_padding(ctx, 0);
774 if ((res = EVP_CipherUpdate(ctx,
out, &outlen,
in, inlen)) <= 0) {
778 if ((res = EVP_CipherFinal(ctx,
final, &finallen)) <= 0) {
785 EVP_CIPHER_CTX_free(ctx);
836 ast_log(
LOG_NOTICE,
"Please run the command 'keys init' to enter the passcodes for the keys\n");
845 EVP_PKEY_free(key->
pkey);
858 for (x = 0; x < MD5_DIGEST_LENGTH; x++) {
859 sum += sprintf(sum,
"%02hhx", *(
md5++));
872#define FORMAT "%-18s %-8s %-16s %-33s\n"
875 char sum[MD5_DIGEST_LENGTH * 2 + 1];
883 " Displays information about RSA keys known by Asterisk\n";
890 ast_cli(
a->fd,
FORMAT,
"------------------",
"--------",
"----------------",
"--------------------------------");
902 ast_cli(
a->fd,
"\n%d known RSA keys.\n", count_keys);
920 char *kn,
tmp[256] =
"";
927 " Initializes private keys (by reading in pass code from\n"
static struct ast_str * prompt
Asterisk main include file. File version handling, generic pbx functions.
#define ast_calloc(num, len)
A wrapper for calloc()
Standard Command Line Interface.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
#define AST_CLI_DEFINE(fn, txt,...)
void ast_cli(int fd, const char *fmt,...)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Provide cryptographic signature routines.
#define AST_CRYPTO_RSA_KEY_BITS
#define AST_CRYPTO_AES_BLOCKSIZE
Generic File Format Support. Should be included by clients of the file handling routines....
int ast_file_read_dirs(const char *dir_name, ast_file_on_file on_file, void *obj, int max_depth)
Recursively iterate through files and directories up to max_depth.
static int md5(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
General Definitions for Asterisk top level program Included by asterisk.h to handle platform-specific...
Support for logging to various files, console and syslog Configuration in file logger....
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_verb(level,...)
I/O Management (derived from Cheops-NG)
int ast_hide_password(int fd)
Hide password.
int ast_restore_tty(int fd, int oldstatus)
Restores TTY mode.
A set of macros to manage forward-linked lists.
#define AST_RWLIST_REMOVE_CURRENT
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized.
#define AST_RWLIST_TRAVERSE_SAFE_END
#define AST_RWLIST_TRAVERSE
#define AST_RWLIST_INSERT_TAIL
Asterisk module definitions.
@ AST_MODFLAG_GLOBAL_SYMBOLS
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
@ AST_MODPRI_CHANNEL_DEPEND
@ AST_MODULE_SUPPORT_CORE
#define ASTERISK_GPL_KEY
The text the key() function should return.
@ AST_MODULE_LOAD_SUCCESS
#define AST_OPTIONAL_API_NAME(name)
Expands to the name of the implementation function.
Options provided by main asterisk program.
#define ast_opt_init_keys
Asterisk file paths, configured in asterisk.conf.
const char * ast_config_AST_KEY_DIR
#define KEY_NEEDS_PASSCODE
int AST_OPTIONAL_API_NAME() ast_check_signature(struct ast_key *key, const char *msg, const char *sig)
base64 decode then sent to __ast_check_signature_bin
static int evp_cipher_aes_decrypt(const unsigned char *in, unsigned char *out, unsigned inlen, const ast_aes_decrypt_key *key)
int AST_OPTIONAL_API_NAME() ast_crypto_reload(void)
int AST_OPTIONAL_API_NAME() ast_aes_set_encrypt_key(const unsigned char *key, ast_aes_encrypt_key *ctx)
Set an encryption key.
int AST_OPTIONAL_API_NAME() ast_sign(struct ast_key *key, char *msg, char *sig)
wrapper for __ast_sign_bin then base64 encode it
int AST_OPTIONAL_API_NAME() ast_aes_decrypt(const unsigned char *in, unsigned char *out, const ast_aes_decrypt_key *key)
AES decrypt data.
#define RSA_PKCS1_OAEP_PADDING_SIZE
int AST_OPTIONAL_API_NAME() ast_decrypt_bin(unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key)
decrypt a message
int AST_OPTIONAL_API_NAME() ast_sign_bin(struct ast_key *key, const char *msg, int msglen, unsigned char *dsig)
signs outgoing message with public key
static char * handle_cli_keys_init(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
initialize all RSA keys
int AST_OPTIONAL_API_NAME() ast_crypto_loaded(void)
static void md52sum(char *sum, unsigned char *md5)
static int evp_pkey_encrypt(EVP_PKEY *pkey, const unsigned char *in, unsigned inlen, unsigned char *out, unsigned *outlen, unsigned padding)
static char * handle_cli_keys_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
show the list of RSA keys
static int evp_cipher_aes_encrypt(const unsigned char *in, unsigned char *out, unsigned inlen, const ast_aes_encrypt_key *key)
struct ast_key *AST_OPTIONAL_API_NAME() ast_key_get(const char *kname, int ktype)
return the ast_key structure for name
int AST_OPTIONAL_API_NAME() ast_aes_set_decrypt_key(const unsigned char *key, ast_aes_decrypt_key *ctx)
Set a decryption key.
static int evp_pkey_sign(EVP_PKEY *pkey, const unsigned char *in, unsigned inlen, unsigned char *sig, unsigned *siglen, unsigned padding)
static void crypto_load(int ifd, int ofd)
refresh RSA keys from file
static int evp_pkey_decrypt(EVP_PKEY *pkey, const unsigned char *in, unsigned inlen, unsigned char *out, unsigned *outlen, unsigned padding)
int AST_OPTIONAL_API_NAME() ast_check_signature_bin(struct ast_key *key, const char *msg, int msglen, const unsigned char *dsig)
check signature of a message
static int evp_pkey_verify(EVP_PKEY *pkey, const unsigned char *in, unsigned inlen, const unsigned char *sig, unsigned siglen, unsigned padding)
int AST_OPTIONAL_API_NAME() ast_aes_encrypt(const unsigned char *in, unsigned char *out, const ast_aes_encrypt_key *key)
AES encrypt data.
static int load_module(void)
static int unload_module(void)
static int crypto_load_cb(const char *directory, const char *file, void *obj)
static int pw_cb(char *buf, int size, int rwflag, void *userdata)
setting of priv key
static struct ast_key * try_load_key(const char *dir, const char *fname, int ifd, int ofd, int *not2)
load RSA key from file
static struct ast_cli_entry cli_crypto[]
int AST_OPTIONAL_API_NAME() ast_encrypt_bin(unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key)
encrypt a message
static int crypto_init(void)
initialise the res_crypto module
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
unsigned char raw[AST_CRYPTO_AES_BLOCKSIZE/8]
descriptor for a cli entry.
unsigned char digest[MD5_DIGEST_LENGTH]
int ast_base64decode(unsigned char *dst, const char *src, int max)
Decode data from base64.
int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max)
Encode data in base64.