func_aes.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2009, Digium, Inc.
  5. *
  6. * See http://www.asterisk.org for more information about
  7. * the Asterisk project. Please do not directly contact
  8. * any of the maintainers of this project for assistance;
  9. * the project provides a web site, mailing lists and IRC
  10. * channels for your use.
  11. *
  12. * This program is free software, distributed under the terms of
  13. * the GNU General Public License Version 2. See the LICENSE file
  14. * at the top of the source tree.
  15. */
  16. /*! \file
  17. *
  18. * \brief AES encryption/decryption dialplan functions
  19. *
  20. * \author David Vossel <dvossel@digium.com>
  21. * \ingroup functions
  22. */
  23. /*** MODULEINFO
  24. <use type="external">crypto</use>
  25. <support_level>core</support_level>
  26. ***/
  27. #include "asterisk.h"
  28. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  29. #include "asterisk/module.h"
  30. #include "asterisk/pbx.h"
  31. #include "asterisk/app.h"
  32. #include "asterisk/crypto.h"
  33. #define AES_BLOCK_SIZE 16
  34. /*** DOCUMENTATION
  35. <function name="AES_ENCRYPT" language="en_US">
  36. <synopsis>
  37. Encrypt a string with AES given a 16 character key.
  38. </synopsis>
  39. <syntax>
  40. <parameter name="key" required="true">
  41. <para>AES Key</para>
  42. </parameter>
  43. <parameter name="string" required="true">
  44. <para>Input string</para>
  45. </parameter>
  46. </syntax>
  47. <description>
  48. <para>Returns an AES encrypted string encoded in base64.</para>
  49. </description>
  50. <see-also>
  51. <ref type="function">AES_DECRYPT</ref>
  52. <ref type="function">BASE64_ENCODE</ref>
  53. <ref type="function">BASE64_DECODE</ref>
  54. </see-also>
  55. </function>
  56. <function name="AES_DECRYPT" language="en_US">
  57. <synopsis>
  58. Decrypt a string encoded in base64 with AES given a 16 character key.
  59. </synopsis>
  60. <syntax>
  61. <parameter name="key" required="true">
  62. <para>AES Key</para>
  63. </parameter>
  64. <parameter name="string" required="true">
  65. <para>Input string.</para>
  66. </parameter>
  67. </syntax>
  68. <description>
  69. <para>Returns the plain text string.</para>
  70. </description>
  71. <see-also>
  72. <ref type="function">AES_ENCRYPT</ref>
  73. <ref type="function">BASE64_ENCODE</ref>
  74. <ref type="function">BASE64_DECODE</ref>
  75. </see-also>
  76. </function>
  77. ***/
  78. static int aes_helper(struct ast_channel *chan, const char *cmd, char *data,
  79. char *buf, size_t len)
  80. {
  81. unsigned char curblock[AES_BLOCK_SIZE] = { 0, };
  82. char *tmp;
  83. char *tmpP;
  84. int data_len, encrypt;
  85. ast_aes_encrypt_key ecx; /* AES 128 Encryption context */
  86. ast_aes_decrypt_key dcx;
  87. AST_DECLARE_APP_ARGS(args,
  88. AST_APP_ARG(key);
  89. AST_APP_ARG(data);
  90. );
  91. AST_STANDARD_APP_ARGS(args, data);
  92. if (ast_strlen_zero(args.data) || ast_strlen_zero(args.key)) {
  93. ast_log(LOG_WARNING, "Syntax: %s(<key>,<data>) - missing argument!\n", cmd);
  94. return -1;
  95. }
  96. if (strlen(args.key) != AES_BLOCK_SIZE) { /* key must be of 16 characters in length, 128 bits */
  97. ast_log(LOG_WARNING, "Syntax: %s(<key>,<data>) - <key> parameter must be exactly 16 characters!\n", cmd);
  98. return -1;
  99. }
  100. ast_aes_set_encrypt_key((unsigned char *) args.key, &ecx); /* encryption: plaintext -> encryptedtext -> base64 */
  101. ast_aes_set_decrypt_key((unsigned char *) args.key, &dcx); /* decryption: base64 -> encryptedtext -> plaintext */
  102. tmp = ast_calloc(1, len); /* requires a tmp buffer for the base64 decode */
  103. if (!tmp) {
  104. ast_log(LOG_ERROR, "Unable to allocate memory for data\n");
  105. return -1;
  106. }
  107. tmpP = tmp;
  108. encrypt = strcmp("AES_DECRYPT", cmd); /* -1 if encrypting, 0 if decrypting */
  109. if (encrypt) { /* if decrypting first decode src to base64 */
  110. ast_copy_string(tmp, args.data, len);
  111. data_len = strlen(tmp);
  112. } else {
  113. data_len = ast_base64decode((unsigned char *) tmp, args.data, len);
  114. }
  115. if (data_len >= len) { /* make sure to not go over buffer len */
  116. ast_log(LOG_WARNING, "Syntax: %s(<keys>,<data>) - <data> exceeds buffer length. Result may be truncated!\n", cmd);
  117. data_len = len - 1;
  118. }
  119. while (data_len > 0) {
  120. memset(curblock, 0, AES_BLOCK_SIZE);
  121. memcpy(curblock, tmpP, (data_len < AES_BLOCK_SIZE) ? data_len : AES_BLOCK_SIZE);
  122. if (encrypt) {
  123. ast_aes_encrypt(curblock, (unsigned char *) tmpP, &ecx);
  124. } else {
  125. ast_aes_decrypt(curblock, (unsigned char *) tmpP, &dcx);
  126. }
  127. tmpP += AES_BLOCK_SIZE;
  128. data_len -= AES_BLOCK_SIZE;
  129. }
  130. if (encrypt) { /* if encrypting encode result to base64 */
  131. ast_base64encode(buf, (unsigned char *) tmp, strlen(tmp), len);
  132. } else {
  133. memcpy(buf, tmp, len);
  134. }
  135. ast_free(tmp);
  136. return 0;
  137. }
  138. static struct ast_custom_function aes_encrypt_function = {
  139. .name = "AES_ENCRYPT",
  140. .read = aes_helper,
  141. };
  142. static struct ast_custom_function aes_decrypt_function = {
  143. .name = "AES_DECRYPT",
  144. .read = aes_helper,
  145. };
  146. static int unload_module(void)
  147. {
  148. int res = ast_custom_function_unregister(&aes_decrypt_function);
  149. return res | ast_custom_function_unregister(&aes_encrypt_function);
  150. }
  151. static int load_module(void)
  152. {
  153. int res = ast_custom_function_register(&aes_decrypt_function);
  154. res |= ast_custom_function_register(&aes_encrypt_function);
  155. return res ? AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS;
  156. }
  157. AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "AES dialplan functions",
  158. .support_level = AST_MODULE_SUPPORT_CORE,
  159. .load = load_module,
  160. .unload = unload_module,
  161. .nonoptreq = "res_crypto",
  162. );