func_aes.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  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="module">res_crypto</use>
  25. <use type="external">crypto</use>
  26. <support_level>core</support_level>
  27. ***/
  28. #include "asterisk.h"
  29. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  30. #include "asterisk/module.h"
  31. #include "asterisk/pbx.h"
  32. #include "asterisk/app.h"
  33. #include "asterisk/crypto.h"
  34. #define AES_BLOCK_SIZE 16
  35. /*** DOCUMENTATION
  36. <function name="AES_ENCRYPT" language="en_US">
  37. <synopsis>
  38. Encrypt a string with AES given a 16 character key.
  39. </synopsis>
  40. <syntax>
  41. <parameter name="key" required="true">
  42. <para>AES Key</para>
  43. </parameter>
  44. <parameter name="string" required="true">
  45. <para>Input string</para>
  46. </parameter>
  47. </syntax>
  48. <description>
  49. <para>Returns an AES encrypted string encoded in base64.</para>
  50. </description>
  51. <see-also>
  52. <ref type="function">AES_DECRYPT</ref>
  53. <ref type="function">BASE64_ENCODE</ref>
  54. <ref type="function">BASE64_DECODE</ref>
  55. </see-also>
  56. </function>
  57. <function name="AES_DECRYPT" language="en_US">
  58. <synopsis>
  59. Decrypt a string encoded in base64 with AES given a 16 character key.
  60. </synopsis>
  61. <syntax>
  62. <parameter name="key" required="true">
  63. <para>AES Key</para>
  64. </parameter>
  65. <parameter name="string" required="true">
  66. <para>Input string.</para>
  67. </parameter>
  68. </syntax>
  69. <description>
  70. <para>Returns the plain text string.</para>
  71. </description>
  72. <see-also>
  73. <ref type="function">AES_ENCRYPT</ref>
  74. <ref type="function">BASE64_ENCODE</ref>
  75. <ref type="function">BASE64_DECODE</ref>
  76. </see-also>
  77. </function>
  78. ***/
  79. static int aes_helper(struct ast_channel *chan, const char *cmd, char *data,
  80. char *buf, size_t len)
  81. {
  82. unsigned char curblock[AES_BLOCK_SIZE] = { 0, };
  83. char *tmp;
  84. char *tmpP;
  85. int data_len, encrypt;
  86. ast_aes_encrypt_key ecx; /* AES 128 Encryption context */
  87. ast_aes_decrypt_key dcx;
  88. AST_DECLARE_APP_ARGS(args,
  89. AST_APP_ARG(key);
  90. AST_APP_ARG(data);
  91. );
  92. AST_STANDARD_APP_ARGS(args, data);
  93. if (ast_strlen_zero(args.data) || ast_strlen_zero(args.key)) {
  94. ast_log(LOG_WARNING, "Syntax: %s(<key>,<data>) - missing argument!\n", cmd);
  95. return -1;
  96. }
  97. if (strlen(args.key) != AES_BLOCK_SIZE) { /* key must be of 16 characters in length, 128 bits */
  98. ast_log(LOG_WARNING, "Syntax: %s(<key>,<data>) - <key> parameter must be exactly 16 characters!\n", cmd);
  99. return -1;
  100. }
  101. ast_aes_set_encrypt_key((unsigned char *) args.key, &ecx); /* encryption: plaintext -> encryptedtext -> base64 */
  102. ast_aes_set_decrypt_key((unsigned char *) args.key, &dcx); /* decryption: base64 -> encryptedtext -> plaintext */
  103. tmp = ast_calloc(1, len); /* requires a tmp buffer for the base64 decode */
  104. if (!tmp) {
  105. ast_log(LOG_ERROR, "Unable to allocate memory for data\n");
  106. return -1;
  107. }
  108. tmpP = tmp;
  109. encrypt = strcmp("AES_DECRYPT", cmd); /* -1 if encrypting, 0 if decrypting */
  110. if (encrypt) { /* if decrypting first decode src to base64 */
  111. ast_copy_string(tmp, args.data, len);
  112. data_len = strlen(tmp);
  113. } else {
  114. data_len = ast_base64decode((unsigned char *) tmp, args.data, len);
  115. }
  116. if (data_len >= len) { /* make sure to not go over buffer len */
  117. ast_log(LOG_WARNING, "Syntax: %s(<keys>,<data>) - <data> exceeds buffer length. Result may be truncated!\n", cmd);
  118. data_len = len - 1;
  119. }
  120. while (data_len > 0) {
  121. memset(curblock, 0, AES_BLOCK_SIZE);
  122. memcpy(curblock, tmpP, (data_len < AES_BLOCK_SIZE) ? data_len : AES_BLOCK_SIZE);
  123. if (encrypt) {
  124. ast_aes_encrypt(curblock, (unsigned char *) tmpP, &ecx);
  125. } else {
  126. ast_aes_decrypt(curblock, (unsigned char *) tmpP, &dcx);
  127. }
  128. tmpP += AES_BLOCK_SIZE;
  129. data_len -= AES_BLOCK_SIZE;
  130. }
  131. if (encrypt) { /* if encrypting encode result to base64 */
  132. ast_base64encode(buf, (unsigned char *) tmp, tmpP - tmp, len);
  133. } else {
  134. memcpy(buf, tmp, len);
  135. }
  136. ast_free(tmp);
  137. return 0;
  138. }
  139. static struct ast_custom_function aes_encrypt_function = {
  140. .name = "AES_ENCRYPT",
  141. .read = aes_helper,
  142. };
  143. static struct ast_custom_function aes_decrypt_function = {
  144. .name = "AES_DECRYPT",
  145. .read = aes_helper,
  146. };
  147. static int unload_module(void)
  148. {
  149. int res = ast_custom_function_unregister(&aes_decrypt_function);
  150. return res | ast_custom_function_unregister(&aes_encrypt_function);
  151. }
  152. static int load_module(void)
  153. {
  154. int res = ast_custom_function_register(&aes_decrypt_function);
  155. res |= ast_custom_function_register(&aes_encrypt_function);
  156. return res ? AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS;
  157. }
  158. AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "AES dialplan functions",
  159. .support_level = AST_MODULE_SUPPORT_CORE,
  160. .load = load_module,
  161. .unload = unload_module,
  162. );