Asterisk - The Open Source Telephony Project  GIT-master-b7027de
Data Structures | Macros | Functions | Variables
res_crypto.c File Reference

Provide Cryptographic Signature capability. More...

#include "asterisk.h"
#include <dirent.h>
#include <openssl/aes.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>
#include "asterisk/cli.h"
#include "asterisk/compat.h"
#include "asterisk/io.h"
#include "asterisk/linkedlists.h"
#include "asterisk/logger.h"
#include "asterisk/md5.h"
#include "asterisk/module.h"
#include "asterisk/options.h"
#include "asterisk/paths.h"
#include "asterisk/utils.h"
#include "asterisk/crypto.h"

Go to the source code of this file.

Data Structures

struct  ast_key
 
struct  keys
 

Macros

#define AST_API_MODULE
 
#define FORMAT   "%-18s %-8s %-16s %-33s\n"
 
#define KEY_NEEDS_PASSCODE   (1 << 16)
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
void AST_OPTIONAL_API_NAME() ast_aes_decrypt (const unsigned char *in, unsigned char *out, const ast_aes_decrypt_key *ctx)
 AES decrypt data. More...
 
void AST_OPTIONAL_API_NAME() ast_aes_encrypt (const unsigned char *in, unsigned char *out, const ast_aes_encrypt_key *ctx)
 AES encrypt data. More...
 
int AST_OPTIONAL_API_NAME() ast_aes_set_decrypt_key (const unsigned char *key, ast_aes_decrypt_key *ctx)
 Set a decryption key. More...
 
int AST_OPTIONAL_API_NAME() ast_aes_set_encrypt_key (const unsigned char *key, ast_aes_encrypt_key *ctx)
 Set an encryption key. More...
 
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 More...
 
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 More...
 
int AST_OPTIONAL_API_NAME() ast_crypto_loaded (void)
 
int AST_OPTIONAL_API_NAME() ast_decrypt_bin (unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key)
 decrypt a message More...
 
int AST_OPTIONAL_API_NAME() ast_encrypt_bin (unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key)
 encrypt a message More...
 
struct ast_key *AST_OPTIONAL_API_NAME() ast_key_get (const char *kname, int ktype)
 return the ast_key structure for name More...
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
int AST_OPTIONAL_API_NAME() ast_sign (struct ast_key *key, char *msg, char *sig)
 wrapper for __ast_sign_bin then base64 encode it More...
 
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 More...
 
static int crypto_init (void)
 initialise the res_crypto module More...
 
static void crypto_load (int ifd, int ofd)
 refresh RSA keys from file More...
 
static char * handle_cli_keys_init (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 initialize all RSA keys More...
 
static char * handle_cli_keys_show (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 show the list of RSA keys More...
 
static int load_module (void)
 
static void md52sum (char *sum, unsigned char *md5)
 
static int pw_cb (char *buf, int size, int rwflag, void *userdata)
 setting of priv key More...
 
static int reload (void)
 
static struct ast_keytry_load_key (const char *dir, const char *fname, int ifd, int ofd, int *not2)
 load RSA key from file More...
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Cryptographic Digital Signatures" , .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, }
 
static struct ast_cli_entry cli_crypto []
 
static struct keys keys = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 

Detailed Description

Provide Cryptographic Signature capability.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m

Uses the OpenSSL library, available at http://www.openssl.org/

Definition in file res_crypto.c.

Macro Definition Documentation

◆ AST_API_MODULE

#define AST_API_MODULE

Definition at line 56 of file res_crypto.c.

◆ FORMAT

#define FORMAT   "%-18s %-8s %-16s %-33s\n"

Referenced by handle_cli_keys_show().

◆ KEY_NEEDS_PASSCODE

#define KEY_NEEDS_PASSCODE   (1 << 16)

Definition at line 72 of file res_crypto.c.

Referenced by handle_cli_keys_init(), handle_cli_keys_show(), and try_load_key().

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 677 of file res_crypto.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 677 of file res_crypto.c.

◆ ast_aes_decrypt()

void AST_OPTIONAL_API_NAME() ast_aes_decrypt ( const unsigned char *  in,
unsigned char *  out,
const ast_aes_decrypt_key ctx 
)

AES decrypt data.

Parameters
inencrypted data
outpointer to a buffer to hold the decrypted output
ctxaddress of an aes encryption context filled in with ast_aes_set_decrypt_key

Definition at line 481 of file res_crypto.c.

References in, and out.

Referenced by aes_helper(), decrypt_memcpy(), and memcpy_decrypt().

482 {
483  return AES_decrypt(in, out, ctx);
484 }
FILE * in
Definition: utils/frame.c:33
FILE * out
Definition: utils/frame.c:33

◆ ast_aes_encrypt()

void AST_OPTIONAL_API_NAME() ast_aes_encrypt ( const unsigned char *  in,
unsigned char *  out,
const ast_aes_encrypt_key ctx 
)

AES encrypt data.

Parameters
indata to be encrypted
outpointer to a buffer to hold the encrypted output
ctxaddress of an aes encryption context filled in with ast_aes_set_encrypt_key

Definition at line 476 of file res_crypto.c.

References in, and out.

Referenced by aes_helper(), encrypt_memcpy(), and memcpy_encrypt().

477 {
478  return AES_encrypt(in, out, ctx);
479 }
FILE * in
Definition: utils/frame.c:33
FILE * out
Definition: utils/frame.c:33

◆ ast_aes_set_decrypt_key()

int AST_OPTIONAL_API_NAME() ast_aes_set_decrypt_key ( const unsigned char *  key,
ast_aes_decrypt_key ctx 
)

Set a decryption key.

Parameters
keya 16 char key
ctxaddress of an aes encryption context
Return values
0success
nonzerofailure

Definition at line 471 of file res_crypto.c.

Referenced by aes_helper(), build_ecx_key(), build_encryption_keys(), check_key(), socket_process_helper(), and update_key().

472 {
473  return AES_set_decrypt_key(key, 128, ctx);
474 }

◆ ast_aes_set_encrypt_key()

int AST_OPTIONAL_API_NAME() ast_aes_set_encrypt_key ( const unsigned char *  key,
ast_aes_encrypt_key ctx 
)

Set an encryption key.

Parameters
keya 16 char key
ctxaddress of an aes encryption context
Return values
0success
nonzerofailure

Definition at line 466 of file res_crypto.c.

Referenced by aes_helper(), build_ecx_key(), check_key(), and update_key().

467 {
468  return AES_set_encrypt_key(key, 128, ctx);
469 }

◆ ast_check_signature()

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

Check the authenticity of a message signature using a given public key.

See also
ast_check_signature

Definition at line 445 of file res_crypto.c.

References ast_base64decode(), ast_check_signature_bin(), ast_log, and LOG_WARNING.

Referenced by authenticate_verify(), and register_verify().

446 {
447  unsigned char dsig[128];
448  int res;
449 
450  /* Decode signature */
451  if ((res = ast_base64decode(dsig, sig, sizeof(dsig))) != sizeof(dsig)) {
452  ast_log(LOG_WARNING, "Signature improper length (expect %d, got %d)\n", (int)sizeof(dsig), (int)res);
453  return -1;
454  }
455 
456  res = ast_check_signature_bin(key, msg, strlen(msg), dsig);
457 
458  return res;
459 }
#define LOG_WARNING
Definition: logger.h:274
int ast_base64decode(unsigned char *dst, const char *src, int max)
Decode data from base64.
Definition: main/utils.c:294
#define ast_log
Definition: astobj2.c:42
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
Definition: res_crypto.c:416

◆ ast_check_signature_bin()

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

Check the authenticity of a message signature using a given public key.

See also
ast_check_signature_bin

Definition at line 416 of file res_crypto.c.

References ast_debug, AST_KEY_PUBLIC, ast_log, ast_key::digest, ast_key::ktype, LOG_WARNING, ast_key::name, ast_key::rsa, and SHA1.

Referenced by ast_check_signature(), and check_key().

417 {
418  unsigned char digest[20];
419  int res;
420 
421  if (key->ktype != AST_KEY_PUBLIC) {
422  /* Okay, so of course you really *can* but for our purposes
423  we're going to say you can't */
424  ast_log(LOG_WARNING, "Cannot check message signature with a private key\n");
425  return -1;
426  }
427 
428  /* Calculate digest of message */
429  SHA1((unsigned char *)msg, msglen, digest);
430 
431  /* Verify signature */
432  if (!(res = RSA_verify(NID_sha1, digest, sizeof(digest), (unsigned char *)dsig, 128, key->rsa))) {
433  ast_debug(1, "Key failed verification: %s\n", key->name);
434  return -1;
435  }
436 
437  /* Pass */
438  return 0;
439 }
RSA * rsa
Definition: res_crypto.c:82
int ktype
Definition: res_crypto.c:80
#define LOG_WARNING
Definition: logger.h:274
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_log
Definition: astobj2.c:42
char name[80]
Definition: res_crypto.c:76
Definition: sha1.h:122
#define AST_KEY_PUBLIC
Definition: crypto.h:42

◆ ast_crypto_loaded()

int AST_OPTIONAL_API_NAME() ast_crypto_loaded ( void  )

Definition at line 461 of file res_crypto.c.

Referenced by AST_TEST_DEFINE().

462 {
463  return 1;
464 }

◆ ast_decrypt_bin()

int AST_OPTIONAL_API_NAME() ast_decrypt_bin ( unsigned char *  dst,
const unsigned char *  src,
int  srclen,
struct ast_key key 
)

decrypt a message

Decrypt a message using a given private key.

See also
ast_decrypt_bin

Definition at line 336 of file res_crypto.c.

References AST_KEY_PRIVATE, ast_log, ast_key::ktype, LOG_NOTICE, LOG_WARNING, and ast_key::rsa.

Referenced by check_key().

337 {
338  int res, pos = 0;
339 
340  if (key->ktype != AST_KEY_PRIVATE) {
341  ast_log(LOG_WARNING, "Cannot decrypt with a public key\n");
342  return -1;
343  }
344 
345  if (srclen % 128) {
346  ast_log(LOG_NOTICE, "Tried to decrypt something not a multiple of 128 bytes\n");
347  return -1;
348  }
349 
350  while (srclen) {
351  /* Process chunks 128 bytes at a time */
352  if ((res = RSA_private_decrypt(128, src, dst, key->rsa, RSA_PKCS1_OAEP_PADDING)) < 0) {
353  return -1;
354  }
355  pos += res;
356  src += 128;
357  srclen -= 128;
358  dst += res;
359  }
360 
361  return pos;
362 }
RSA * rsa
Definition: res_crypto.c:82
int ktype
Definition: res_crypto.c:80
#define LOG_WARNING
Definition: logger.h:274
#define ast_log
Definition: astobj2.c:42
#define AST_KEY_PRIVATE
Definition: crypto.h:43
#define LOG_NOTICE
Definition: logger.h:263

◆ ast_encrypt_bin()

int AST_OPTIONAL_API_NAME() ast_encrypt_bin ( unsigned char *  dst,
const unsigned char *  src,
int  srclen,
struct ast_key key 
)

encrypt a message

Encrypt a message using a given private key.

See also
ast_encrypt_bin

Definition at line 368 of file res_crypto.c.

References AST_KEY_PUBLIC, ast_log, ast_key::ktype, LOG_NOTICE, LOG_WARNING, and ast_key::rsa.

Referenced by update_key().

369 {
370  int res, bytes, pos = 0;
371 
372  if (key->ktype != AST_KEY_PUBLIC) {
373  ast_log(LOG_WARNING, "Cannot encrypt with a private key\n");
374  return -1;
375  }
376 
377  while (srclen) {
378  bytes = srclen;
379  if (bytes > 128 - 41) {
380  bytes = 128 - 41;
381  }
382  /* Process chunks 128-41 bytes at a time */
383  if ((res = RSA_public_encrypt(bytes, src, dst, key->rsa, RSA_PKCS1_OAEP_PADDING)) != 128) {
384  ast_log(LOG_NOTICE, "How odd, encrypted size is %d\n", res);
385  return -1;
386  }
387  src += bytes;
388  srclen -= bytes;
389  pos += res;
390  dst += res;
391  }
392  return pos;
393 }
RSA * rsa
Definition: res_crypto.c:82
int ktype
Definition: res_crypto.c:80
#define LOG_WARNING
Definition: logger.h:274
#define ast_log
Definition: astobj2.c:42
#define LOG_NOTICE
Definition: logger.h:263
#define AST_KEY_PUBLIC
Definition: crypto.h:42

◆ ast_key_get()

struct ast_key* AST_OPTIONAL_API_NAME() ast_key_get ( const char *  kname,
int  ktype 
)

return the ast_key structure for name

Retrieve a key.

See also
ast_key_get

Definition at line 141 of file res_crypto.c.

References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_key::ktype, and ast_key::name.

Referenced by authenticate(), authenticate_verify(), check_key(), register_verify(), and update_key().

142 {
143  struct ast_key *key;
144 
146  AST_RWLIST_TRAVERSE(&keys, key, list) {
147  if (!strcmp(kname, key->name) &&
148  (ktype == key->ktype)) {
149  break;
150  }
151  }
153 
154  return key;
155 }
int ktype
Definition: res_crypto.c:80
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
char name[80]
Definition: res_crypto.c:76

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 677 of file res_crypto.c.

◆ ast_sign()

int AST_OPTIONAL_API_NAME() ast_sign ( struct ast_key key,
char *  msg,
char *  sig 
)

wrapper for __ast_sign_bin then base64 encode it

Sign a message signature using a given private key.

See also
ast_sign

Definition at line 399 of file res_crypto.c.

References ast_base64encode(), and ast_sign_bin().

Referenced by authenticate().

400 {
401  unsigned char dsig[128];
402  int siglen = sizeof(dsig), res;
403 
404  if (!(res = ast_sign_bin(key, msg, strlen(msg), dsig))) {
405  /* Success -- encode (256 bytes max as documented) */
406  ast_base64encode(sig, dsig, siglen, 256);
407  }
408 
409  return res;
410 }
int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max)
Encode data in base64.
Definition: main/utils.c:404
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
Definition: res_crypto.c:304

◆ ast_sign_bin()

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

Sign a message signature using a given private key.

See also
ast_sign_bin

Definition at line 304 of file res_crypto.c.

References AST_KEY_PRIVATE, ast_log, ast_key::digest, ast_key::ktype, LOG_WARNING, ast_key::name, ast_key::rsa, and SHA1.

Referenced by ast_sign(), and update_key().

305 {
306  unsigned char digest[20];
307  unsigned int siglen = 128;
308  int res;
309 
310  if (key->ktype != AST_KEY_PRIVATE) {
311  ast_log(LOG_WARNING, "Cannot sign with a public key\n");
312  return -1;
313  }
314 
315  /* Calculate digest of message */
316  SHA1((unsigned char *)msg, msglen, digest);
317 
318  /* Verify signature */
319  if (!(res = RSA_sign(NID_sha1, digest, sizeof(digest), dsig, &siglen, key->rsa))) {
320  ast_log(LOG_WARNING, "RSA Signature (key %s) failed\n", key->name);
321  return -1;
322  }
323 
324  if (siglen != 128) {
325  ast_log(LOG_WARNING, "Unexpected signature length %d, expecting %d\n", (int)siglen, (int)128);
326  return -1;
327  }
328 
329  return 0;
330 }
RSA * rsa
Definition: res_crypto.c:82
int ktype
Definition: res_crypto.c:80
#define LOG_WARNING
Definition: logger.h:274
#define ast_log
Definition: astobj2.c:42
#define AST_KEY_PRIVATE
Definition: crypto.h:43
char name[80]
Definition: res_crypto.c:76
Definition: sha1.h:122
unsigned char digest[16]
Definition: res_crypto.c:90

◆ crypto_init()

static int crypto_init ( void  )
static

initialise the res_crypto module

Definition at line 640 of file res_crypto.c.

References ARRAY_LEN, and ast_cli_register_multiple.

Referenced by load_module().

641 {
643  return 0;
644 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static struct ast_cli_entry cli_crypto[]
Definition: res_crypto.c:634

◆ crypto_load()

static void crypto_load ( int  ifd,
int  ofd 
)
static

refresh RSA keys from file

Parameters
ifdfile descriptor
ofdfile descriptor
Returns
void

Definition at line 492 of file res_crypto.c.

References ast_config_AST_KEY_DIR, ast_debug, ast_free, ast_log, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_key::delme, ast_key::ktype, LOG_NOTICE, LOG_WARNING, ast_key::name, NULL, ast_key::rsa, and try_load_key().

Referenced by load_module(), and reload().

493 {
494  struct ast_key *key;
495  DIR *dir = NULL;
496  struct dirent *ent;
497  int note = 0;
498 
500 
501  /* Mark all keys for deletion */
502  AST_RWLIST_TRAVERSE(&keys, key, list) {
503  key->delme = 1;
504  }
505 
506  /* Load new keys */
507  if ((dir = opendir(ast_config_AST_KEY_DIR))) {
508  while ((ent = readdir(dir))) {
509  try_load_key(ast_config_AST_KEY_DIR, ent->d_name, ifd, ofd, &note);
510  }
511  closedir(dir);
512  } else {
513  ast_log(LOG_WARNING, "Unable to open key directory '%s'\n", ast_config_AST_KEY_DIR);
514  }
515 
516  if (note) {
517  ast_log(LOG_NOTICE, "Please run the command 'keys init' to enter the passcodes for the keys\n");
518  }
519 
520  /* Delete any keys that are no longer present */
521  AST_RWLIST_TRAVERSE_SAFE_BEGIN(&keys, key, list) {
522  if (key->delme) {
523  ast_debug(1, "Deleting key %s type %d\n", key->name, key->ktype);
525  if (key->rsa) {
526  RSA_free(key->rsa);
527  }
528  ast_free(key);
529  }
530  }
532 
534 }
const char * ast_config_AST_KEY_DIR
Definition: options.c:161
RSA * rsa
Definition: res_crypto.c:82
int ktype
Definition: res_crypto.c:80
static struct ast_key * try_load_key(const char *dir, const char *fname, int ifd, int ofd, int *not2)
load RSA key from file
Definition: res_crypto.c:167
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define LOG_WARNING
Definition: logger.h:274
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define NULL
Definition: resample.c:96
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_log
Definition: astobj2.c:42
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:569
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:544
char name[80]
Definition: res_crypto.c:76
#define LOG_NOTICE
Definition: logger.h:263
#define ast_free(a)
Definition: astmm.h:182
int delme
Definition: res_crypto.c:84
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:616

◆ handle_cli_keys_init()

static char* handle_cli_keys_init ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

initialize all RSA keys

Parameters
eCLI command
cmd
alist of CLI arguments
Returns
CLI_SUCCESS

Definition at line 597 of file res_crypto.c.

References ast_cli_args::argc, ast_config_AST_KEY_DIR, ast_copy_string(), AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_key::fn, KEY_NEEDS_PASSCODE, ast_key::ktype, NULL, tmp(), try_load_key(), and ast_cli_entry::usage.

598 {
599  struct ast_key *key;
600  int ign;
601  char *kn, tmp[256] = "";
602 
603  switch (cmd) {
604  case CLI_INIT:
605  e->command = "keys init";
606  e->usage =
607  "Usage: keys init\n"
608  " Initializes private keys (by reading in pass code from\n"
609  " the user)\n";
610  return NULL;
611  case CLI_GENERATE:
612  return NULL;
613  }
614 
615  if (a->argc != 2) {
616  return CLI_SHOWUSAGE;
617  }
618 
620  AST_RWLIST_TRAVERSE_SAFE_BEGIN(&keys, key, list) {
621  /* Reload keys that need pass codes now */
622  if (key->ktype & KEY_NEEDS_PASSCODE) {
623  kn = key->fn + strlen(ast_config_AST_KEY_DIR) + 1;
624  ast_copy_string(tmp, kn, sizeof(tmp));
625  try_load_key(ast_config_AST_KEY_DIR, tmp, a->fd, a->fd, &ign);
626  }
627  }
630 
631  return CLI_SUCCESS;
632 }
const char * ast_config_AST_KEY_DIR
Definition: options.c:161
int ktype
Definition: res_crypto.c:80
static struct ast_key * try_load_key(const char *dir, const char *fname, int ifd, int ofd, int *not2)
load RSA key from file
Definition: res_crypto.c:167
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
const int argc
Definition: cli.h:160
static int tmp()
Definition: bt_open.c:389
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
Definition: cli.h:152
#define NULL
Definition: resample.c:96
const int fd
Definition: cli.h:159
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:544
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define KEY_NEEDS_PASSCODE
Definition: res_crypto.c:72
char fn[256]
Definition: res_crypto.c:78
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:616

◆ handle_cli_keys_show()

static char* handle_cli_keys_show ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

show the list of RSA keys

Parameters
eCLI command
cmd
alist of CLI arguments
Returns
CLI_SUCCESS

Definition at line 551 of file res_crypto.c.

References ast_cli(), AST_KEY_PUBLIC, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_key::digest, ast_cli_args::fd, FORMAT, KEY_NEEDS_PASSCODE, ast_key::ktype, md52sum(), ast_key::name, NULL, and ast_cli_entry::usage.

552 {
553 #define FORMAT "%-18s %-8s %-16s %-33s\n"
554 
555  struct ast_key *key;
556  char sum[16 * 2 + 1];
557  int count_keys = 0;
558 
559  switch (cmd) {
560  case CLI_INIT:
561  e->command = "keys show";
562  e->usage =
563  "Usage: keys show\n"
564  " Displays information about RSA keys known by Asterisk\n";
565  return NULL;
566  case CLI_GENERATE:
567  return NULL;
568  }
569 
570  ast_cli(a->fd, FORMAT, "Key Name", "Type", "Status", "Sum");
571  ast_cli(a->fd, FORMAT, "------------------", "--------", "----------------", "--------------------------------");
572 
574  AST_RWLIST_TRAVERSE(&keys, key, list) {
575  md52sum(sum, key->digest);
576  ast_cli(a->fd, FORMAT, key->name,
577  (key->ktype & 0xf) == AST_KEY_PUBLIC ? "PUBLIC" : "PRIVATE",
578  key->ktype & KEY_NEEDS_PASSCODE ? "[Needs Passcode]" : "[Loaded]", sum);
579  count_keys++;
580  }
582 
583  ast_cli(a->fd, "\n%d known RSA keys.\n", count_keys);
584 
585  return CLI_SUCCESS;
586 
587 #undef FORMAT
588 }
int ktype
Definition: res_crypto.c:80
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
Definition: cli.h:152
#define FORMAT
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
const int fd
Definition: cli.h:159
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
char name[80]
Definition: res_crypto.c:76
unsigned char digest[16]
Definition: res_crypto.c:90
#define KEY_NEEDS_PASSCODE
Definition: res_crypto.c:72
static void md52sum(char *sum, unsigned char *md5)
Definition: res_crypto.c:536
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
#define AST_KEY_PUBLIC
Definition: crypto.h:42

◆ load_module()

static int load_module ( void  )
static

Definition at line 652 of file res_crypto.c.

References AST_MODULE_LOAD_SUCCESS, ast_opt_init_keys, crypto_init(), and crypto_load().

Referenced by unload_module().

653 {
654  crypto_init();
655  if (ast_opt_init_keys) {
656  crypto_load(STDIN_FILENO, STDOUT_FILENO);
657  } else {
658  crypto_load(-1, -1);
659  }
660 
662 }
#define ast_opt_init_keys
Definition: options.h:111
static void crypto_load(int ifd, int ofd)
refresh RSA keys from file
Definition: res_crypto.c:492
static int crypto_init(void)
initialise the res_crypto module
Definition: res_crypto.c:640

◆ md52sum()

static void md52sum ( char *  sum,
unsigned char *  md5 
)
static

Definition at line 536 of file res_crypto.c.

Referenced by handle_cli_keys_show().

537 {
538  int x;
539  for (x = 0; x < 16; x++) {
540  sum += sprintf(sum, "%02hhx", *(md5++));
541  }
542 }
static int md5(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_md5.c:52

◆ pw_cb()

static int pw_cb ( char *  buf,
int  size,
int  rwflag,
void *  userdata 
)
static

setting of priv key

Parameters
buf
size
rwflag
userdata
Returns
length of string,-1 on failure

Definition at line 104 of file res_crypto.c.

References ast_hide_password(), AST_KEY_PRIVATE, ast_log, ast_restore_tty(), errno, ast_key::infd, ast_key::ktype, LOG_WARNING, ast_key::name, ast_key::outfd, prompt, and tmp().

Referenced by try_load_key().

105 {
106  struct ast_key *key = (struct ast_key *)userdata;
107  char prompt[256];
108  int tmp;
109  int res;
110 
111  if (key->infd < 0) {
112  /* Note that we were at least called */
113  key->infd = -2;
114  return -1;
115  }
116 
117  snprintf(prompt, sizeof(prompt), ">>>> passcode for %s key '%s': ",
118  key->ktype == AST_KEY_PRIVATE ? "PRIVATE" : "PUBLIC", key->name);
119  if (write(key->outfd, prompt, strlen(prompt)) < 0) {
120  ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
121  key->infd = -2;
122  return -1;
123  }
124  tmp = ast_hide_password(key->infd);
125  memset(buf, 0, size);
126  res = read(key->infd, buf, size);
127  if (res == -1) {
128  ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
129  }
130  ast_restore_tty(key->infd, tmp);
131  if (buf[strlen(buf) -1] == '\n') {
132  buf[strlen(buf) - 1] = '\0';
133  }
134  return strlen(buf);
135 }
int ktype
Definition: res_crypto.c:80
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define LOG_WARNING
Definition: logger.h:274
int ast_hide_password(int fd)
Definition: io.c:337
static int tmp()
Definition: bt_open.c:389
int ast_restore_tty(int fd, int oldstatus)
Restores TTY mode. Call with result from previous ast_hide_password.
Definition: io.c:356
int outfd
Definition: res_crypto.c:88
#define ast_log
Definition: astobj2.c:42
#define AST_KEY_PRIVATE
Definition: crypto.h:43
char name[80]
Definition: res_crypto.c:76
int errno
int infd
Definition: res_crypto.c:86
static struct ast_str * prompt
Definition: asterisk.c:2725

◆ reload()

static int reload ( void  )
static

Definition at line 646 of file res_crypto.c.

References crypto_load().

Referenced by unload_module().

647 {
648  crypto_load(-1, -1);
649  return 0;
650 }
static void crypto_load(int ifd, int ofd)
refresh RSA keys from file
Definition: res_crypto.c:492

◆ try_load_key()

static struct ast_key* try_load_key ( const char *  dir,
const char *  fname,
int  ifd,
int  ofd,
int *  not2 
)
static

load RSA key from file

Parameters
dirdirectory string
fnamename of file
ifdincoming file descriptor
ofdoutgoing file descriptor
not2
Return values
keyon success.
NULLon failure.

Definition at line 167 of file res_crypto.c.

References ast_calloc, ast_copy_string(), ast_debug, AST_KEY_PRIVATE, AST_KEY_PUBLIC, ast_log, ast_opt_init_keys, AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, ast_verb, buf, c, ast_key::delme, ast_key::digest, errno, ast_key::fn, ast_key::infd, KEY_NEEDS_PASSCODE, ast_key::ktype, LOG_NOTICE, LOG_WARNING, MD5Final(), MD5Init(), MD5Update(), ast_key::name, NULL, ast_key::outfd, pw_cb(), and ast_key::rsa.

Referenced by crypto_load(), and handle_cli_keys_init().

168 {
169  int ktype = 0, found = 0;
170  char *c = NULL, ffname[256];
171  unsigned char digest[16];
172  FILE *f;
173  struct MD5Context md5;
174  struct ast_key *key;
175  static int notice = 0;
176 
177  /* Make sure its name is a public or private key */
178  if ((c = strstr(fname, ".pub")) && !strcmp(c, ".pub")) {
179  ktype = AST_KEY_PUBLIC;
180  } else if ((c = strstr(fname, ".key")) && !strcmp(c, ".key")) {
181  ktype = AST_KEY_PRIVATE;
182  } else {
183  return NULL;
184  }
185 
186  /* Get actual filename */
187  snprintf(ffname, sizeof(ffname), "%s/%s", dir, fname);
188 
189  /* Open file */
190  if (!(f = fopen(ffname, "r"))) {
191  ast_log(LOG_WARNING, "Unable to open key file %s: %s\n", ffname, strerror(errno));
192  return NULL;
193  }
194 
195  MD5Init(&md5);
196  while (!feof(f)) {
197  /* Calculate a "whatever" quality md5sum of the key */
198  char buf[256] = "";
199  if (!fgets(buf, sizeof(buf), f)) {
200  continue;
201  }
202  if (!feof(f)) {
203  MD5Update(&md5, (unsigned char *) buf, strlen(buf));
204  }
205  }
206  MD5Final(digest, &md5);
207 
208  /* Look for an existing key */
209  AST_RWLIST_TRAVERSE(&keys, key, list) {
210  if (!strcasecmp(key->fn, ffname)) {
211  break;
212  }
213  }
214 
215  if (key) {
216  /* If the MD5 sum is the same, and it isn't awaiting a passcode
217  then this is far enough */
218  if (!memcmp(digest, key->digest, 16) &&
219  !(key->ktype & KEY_NEEDS_PASSCODE)) {
220  fclose(f);
221  key->delme = 0;
222  return NULL;
223  } else {
224  /* Preserve keytype */
225  ktype = key->ktype;
226  /* Recycle the same structure */
227  found++;
228  }
229  }
230 
231  /* Make fname just be the normal name now */
232  *c = '\0';
233  if (!key) {
234  if (!(key = ast_calloc(1, sizeof(*key)))) {
235  fclose(f);
236  return NULL;
237  }
238  }
239  /* First the filename */
240  ast_copy_string(key->fn, ffname, sizeof(key->fn));
241  /* Then the name */
242  ast_copy_string(key->name, fname, sizeof(key->name));
243  key->ktype = ktype;
244  /* Yes, assume we're going to be deleted */
245  key->delme = 1;
246  /* Keep the key type */
247  memcpy(key->digest, digest, 16);
248  /* Can I/O takes the FD we're given */
249  key->infd = ifd;
250  key->outfd = ofd;
251  /* Reset the file back to the beginning */
252  rewind(f);
253  /* Now load the key with the right method */
254  if (ktype == AST_KEY_PUBLIC) {
255  key->rsa = PEM_read_RSA_PUBKEY(f, NULL, pw_cb, key);
256  } else {
257  key->rsa = PEM_read_RSAPrivateKey(f, NULL, pw_cb, key);
258  }
259  fclose(f);
260  if (key->rsa) {
261  if (RSA_size(key->rsa) == 128) {
262  /* Key loaded okay */
263  key->ktype &= ~KEY_NEEDS_PASSCODE;
264  ast_verb(3, "Loaded %s key '%s'\n", key->ktype == AST_KEY_PUBLIC ? "PUBLIC" : "PRIVATE", key->name);
265  ast_debug(1, "Key '%s' loaded OK\n", key->name);
266  key->delme = 0;
267  } else {
268  ast_log(LOG_NOTICE, "Key '%s' is not expected size.\n", key->name);
269  }
270  } else if (key->infd != -2) {
271  ast_log(LOG_WARNING, "Key load %s '%s' failed\n",key->ktype == AST_KEY_PUBLIC ? "PUBLIC" : "PRIVATE", key->name);
272  if (ofd > -1) {
273  ERR_print_errors_fp(stderr);
274  } else {
275  ERR_print_errors_fp(stderr);
276  }
277  } else {
278  ast_log(LOG_NOTICE, "Key '%s' needs passcode.\n", key->name);
279  key->ktype |= KEY_NEEDS_PASSCODE;
280  if (!notice) {
281  if (!ast_opt_init_keys) {
282  ast_log(LOG_NOTICE, "Add the '-i' flag to the asterisk command line if you want to automatically initialize passcodes at launch.\n");
283  }
284  notice++;
285  }
286  /* Keep it anyway */
287  key->delme = 0;
288  /* Print final notice about "keys init" when done */
289  *not2 = 1;
290  }
291 
292  /* If this is a new key add it to the list */
293  if (!found) {
294  AST_RWLIST_INSERT_TAIL(&keys, key, list);
295  }
296 
297  return key;
298 }
RSA * rsa
Definition: res_crypto.c:82
int ktype
Definition: res_crypto.c:80
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define LOG_WARNING
Definition: logger.h:274
void MD5Final(unsigned char digest[16], struct MD5Context *context)
Definition: md5.c:120
static struct test_val c
#define NULL
Definition: resample.c:96
#define ast_opt_init_keys
Definition: options.h:111
#define ast_verb(level,...)
Definition: logger.h:455
void MD5Init(struct MD5Context *context)
Definition: md5.c:57
int outfd
Definition: res_crypto.c:88
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_log
Definition: astobj2.c:42
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
#define AST_KEY_PRIVATE
Definition: crypto.h:43
void MD5Update(struct MD5Context *context, unsigned char const *buf, unsigned len)
Definition: md5.c:72
char name[80]
Definition: res_crypto.c:76
static int md5(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_md5.c:52
unsigned char digest[16]
Definition: res_crypto.c:90
int errno
#define KEY_NEEDS_PASSCODE
Definition: res_crypto.c:72
#define LOG_NOTICE
Definition: logger.h:263
int infd
Definition: res_crypto.c:86
char fn[256]
Definition: res_crypto.c:78
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
int delme
Definition: res_crypto.c:84
Definition: md5.h:26
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:740
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static int pw_cb(char *buf, int size, int rwflag, void *userdata)
setting of priv key
Definition: res_crypto.c:104
#define AST_KEY_PUBLIC
Definition: crypto.h:42

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 664 of file res_crypto.c.

References ARRAY_LEN, ast_cli_unregister_multiple(), AST_MODFLAG_GLOBAL_SYMBOLS, AST_MODFLAG_LOAD_ORDER, AST_MODPRI_CHANNEL_DEPEND, AST_MODULE_INFO(), AST_MODULE_SUPPORT_CORE, ASTERISK_GPL_KEY, load_module(), and reload().

665 {
667 
668  return 0;
669 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
static struct ast_cli_entry cli_crypto[]
Definition: res_crypto.c:634

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Cryptographic Digital Signatures" , .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, }
static

Definition at line 677 of file res_crypto.c.

◆ cli_crypto

struct ast_cli_entry cli_crypto[]
static
Initial value:
= {
{ .handler = handle_cli_keys_show , .summary = "Displays RSA key information" ,},
{ .handler = handle_cli_keys_init , .summary = "Initialize RSA key passcodes" ,}
}
static char * handle_cli_keys_init(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
initialize all RSA keys
Definition: res_crypto.c:597
static char * handle_cli_keys_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
show the list of RSA keys
Definition: res_crypto.c:551

Definition at line 634 of file res_crypto.c.

◆ keys

struct keys keys = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
static

Referenced by misdn_set_opt_exec(), and store_odbc().