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) 
  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;
 
  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);
 
 
  859        sum += sprintf(sum, 
"%02hhx", *(
md5++));
 
 
  872#define FORMAT "%-18s %-8s %-16s %-33s\n" 
  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" 
 
void ast_cli_unregister_multiple(void)
General Definitions for Asterisk top level program Included by asterisk.h to handle platform-specific...
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.
#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
int crypto_load(void)
Initialize the crypto utils.
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)
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
#define MD5_DIGEST_LENGTH
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 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]
struct ast_key::@470 list
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.