Review Board 1.7.16


added AES_ENCRYPT and AES_DECRYPT dialplan functions

Review Request #128 - Created Jan. 22, 2009 and submitted

David Vossel
trunk
0014301
Reviewers
asterisk-dev
mmichelson, russell
Asterisk
Allows data to be encrypted and decrypted using AES in the dialplan.  

 

Changes between revision 1 and 4

1 2 3 4 5
1 2 3 4 5

  1. /trunk/funcs/func_aes.c: Loading...
/trunk/funcs/func_aes.c
Diff Revision 1 Diff Revision 4
1
/*
1
/*
2
 * Asterisk -- An open source telephony toolkit.
2
 * Asterisk -- An open source telephony toolkit.
3
 *
3
 *
4
 * Copyright (C) 1999-2009, Digium, Inc.
4
 * Copyright (C) 2009, Digium, Inc.
5
 *
5
 *
6
 * See http://www.asterisk.org for more information about
6
 * See http://www.asterisk.org for more information about
7
 * the Asterisk project. Please do not directly contact
7
 * the Asterisk project. Please do not directly contact
8
 * any of the maintainers of this project for assistance;
8
 * any of the maintainers of this project for assistance;
9
 * the project provides a web site, mailing lists and IRC
9
 * the project provides a web site, mailing lists and IRC
[+20] [20] 5 lines
[+20]
15
 */
15
 */
16

    
   
16

   
17
/*! \file
17
/*! \file
18
 *
18
 *
19
 * \brief AES encryption/decryption dialplan functions
19
 * \brief AES encryption/decryption dialplan functions
20
 * 
20
 *

    
   
21
 * \author David Vossel <dvossel@digium.com>
21
 * \ingroup functions
22
 * \ingroup functions
22
 */
23
 */
23

    
   
24

   
24

    
   
25

   
25
#include "asterisk.h"
26
#include "asterisk.h"
26

    
   
27

   
27
ASTERISK_FILE_VERSION(__FILE__, "$Revision: 170151 $")
28
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
28

    
   
29

   
29
#include "asterisk/module.h"
30
#include "asterisk/module.h"
30
#include "asterisk/pbx.h"
31
#include "asterisk/pbx.h"
31
#include "asterisk/app.h"
32
#include "asterisk/app.h"
32
#include "asterisk/aes.h"
33
#include "asterisk/aes.h"
33

    
   
34

   

    
   
35
#define AES_BLOCK_SIZE 16
34

    
   
36

   
35
static int aes_encrypt_read(struct ast_channel *chan, const char *cmd, char *data,
37
/*** DOCUMENTATION
36
	       char *buf, size_t len)
38
	<function name="AES_ENCRYPT" language="en_US">
37
{
39
		<synopsis>
38
	
40
			Encrypt a string with AES given a 16 character key.
39
	unsigned char curblock[16];
41
		</synopsis>
40
	char *src;
42
		<syntax>
41
	char *dst;
43
			<parameter name="string" required="true">
42
	int x, data_len; 
44
				<para>Input string</para>
43
	ast_aes_encrypt_key ecx;                       /*  AES 128 Encryption context */
45
			</parameter>
44
	
46
			<parameter name="key" required="true">
45
	AST_DECLARE_APP_ARGS(args,  
47
				<para>AES Key</para>
46
		AST_APP_ARG(key);
48
			</parameter>
47
		AST_APP_ARG(data);
49
		</syntax>
48
	);
50
		<description>
49
	
51
			<para>Returns an AES encrypted string encoded in base64.</para>
50
	AST_STANDARD_APP_ARGS(args, data);
52
		</description>
51
	
53
	</function>
52
	if (ast_strlen_zero(args.data) || ast_strlen_zero(args.key)) {
54
	<function name="AES_DECRYPT" language="en_US">
53
		ast_log(LOG_WARNING, "Syntax: AES_ENCRYPT(<key>, <data>) - missing argument!\n");
55
		<synopsis>
54
		return -1;
56
			Decrypt a string encoded in base64 with AES given a 16 character key.
55
	}
57
		</synopsis>
56
	
58
		<syntax>
57
	if (strlen(args.key) != 16 ) {         /* key must be of 16 characters in length, 128 bits */
59
			<parameter name="string" required="true">
58
		ast_log(LOG_WARNING, "Syntax: AES_ENCRYPT(<key>, <data>) - <key> parameter must be exactly 16 characters!\n");
60
				<para>Input string.</para>
59
		return -1;
61
			</parameter>
60
	}
62
			<parameter name="key" required="true">
61
	
63
				<para>AES Key</para>
62
	ast_aes_encrypt_key(args.key, &ecx);
64
			</parameter>
63
	
65

   
64
	dst = buf;
66
		</syntax>
65
	src = args.data; 
67
		<description>
66
	data_len = strlen(args.data);
68
			<para>Returns the plain text string.</para>
67
	memset(curblock, '\0', sizeof(curblock));
69
		</description>
68
	
70
	</function>
69
	if (data_len >= len) {                           /* make sure to not go over buffer len */
71
 ***/
70
		data_len = (len-1);
72

   
71
	}
73

   
72
	
74
static int aes_helper(struct ast_channel *chan, const char *cmd, char *data,
73
	while (data_len > 0) {

   
74
		for (x = 0; x < 16; x++)

   
75
			curblock[x] = src[x];

   
76
		ast_aes_encrypt(curblock, dst, &ecx);

   
77
		memcpy(curblock, dst, sizeof(curblock));

   
78
		dst += 16;

   
79
		src += 16;

   
80
		data_len -= 16;

   
81
	}

   
82
	

   
83
	return 0;

   
84
}

   
85
static int aes_decrypt_read(struct ast_channel *chan, const char *cmd, char *data,

   
86
	char *buf, size_t len)
75
	       char *buf, size_t len)
87
{
76
{

    
   
77
	unsigned char curblock[AES_BLOCK_SIZE] = { 0, };

    
   
78
	char *tmp;

    
   
79
	char *tmpP;

    
   
80
	int data_len, encrypt;

    
   
81
	ast_aes_encrypt_key ecx;                        /*  AES 128 Encryption context */

    
   
82
	ast_aes_decrypt_key dcx;
88

    
   
83

   
89
	unsigned char curblock[16];
84
	AST_DECLARE_APP_ARGS(args,
90
	char *src;

   
91
	char *dst;

   
92
	int x, data_len; 	

   
93
	ast_aes_decrypt_key dcx;                       /*!< AES 128 Encryption context */

   
94
	

   
95
	AST_DECLARE_APP_ARGS(args,  

   
96
			AST_APP_ARG(key);
85
		AST_APP_ARG(key);
97
			AST_APP_ARG(data);
86
		AST_APP_ARG(data);
98
	);
87
	);
99
	
88

   
100
	AST_STANDARD_APP_ARGS(args, data);
89
	AST_STANDARD_APP_ARGS(args, data);
101
	
90

   
102
	if (ast_strlen_zero(args.data) || ast_strlen_zero(args.key)) {
91
	if (ast_strlen_zero(args.data) || ast_strlen_zero(args.key)) {
103
		ast_log(LOG_WARNING, "Syntax: AES_DECRYPT(<key>, <data>) - missing argument!\n");
92
		ast_log(LOG_WARNING, "Syntax: %s(<key>,<data>) - missing argument!\n", cmd);
104
		return -1;
93
		return -1;
105
	}
94
	}
106

    
   
95

   
107
	if (strlen(args.key) != 16 ) {         /* key must be of 16 characters in length, 128 bits */
96
	if (strlen(args.key) != AES_BLOCK_SIZE) {        /* key must be of 16 characters in length, 128 bits */
108
		ast_log(LOG_WARNING, "Syntax: AES_DECRYPT(<key>, <data>) - <key> parameter must be exactly 16 characters!\n");
97
		ast_log(LOG_WARNING, "Syntax: %s(<key>,<data>) - <key> parameter must be exactly 16 characters!\n", cmd);
109
		return -1;
98
		return -1;
110
	}
99
	}
111
	
100

   
112
	ast_aes_decrypt_key(args.key, &dcx);
101
	ast_aes_encrypt_key(args.key, &ecx);   /* encryption:  plaintext -> encyptedtext -> base64 */
113
	
102
	ast_aes_decrypt_key(args.key, &dcx);   /* decryption:  base64 -> encyptedtext -> plaintext */
114
	dst = buf;
103
	tmp = ast_calloc(1, len);                     /* requires a tmp buffer for the base64 decode */
115
	src = args.data; 
104
	tmpP = tmp;
116
	data_len = strlen(args.data);
105
	encrypt = strcmp("AES_DECRYPT", cmd);           /* -1 if encrypting, 0 if decrypting */
117
	memset(curblock, '\0', sizeof(curblock));
106

   
118
	
107
	if (encrypt) {                                  /* if decrypting first decode src to base64 */
119
	if (data_len >= len) {                       /* make sure to not go over buffer len */
108
		memcpy(tmp, args.data, strlen(args.data));  /* use same tmp buffer for encrypt as well to keep things simple */
120
		data_len = (len-1);
109
		data_len = strlen(tmp);

    
   
110
	} else {

    
   
111
		ast_base64decode((unsigned char *) tmp, args.data, len);

    
   
112
		data_len = strlen(tmp);

    
   
113
	}

    
   
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;
121
	}
118
	}
122
	
119

   
123
	while (data_len > 0) {
120
	while (data_len > 0) {
124
		for (x = 0; x < 16; x++)
121
		memset(curblock, 0, AES_BLOCK_SIZE);
125
			curblock[x] = src[x];
122
		memcpy(curblock, tmpP, (data_len < AES_BLOCK_SIZE) ? data_len : AES_BLOCK_SIZE);
126
		ast_aes_decrypt(curblock, dst, &dcx);
123
		if (encrypt == 0) {
127
		memcpy(curblock, dst, sizeof(curblock));
124
			ast_aes_encrypt(curblock, tmpP, &ecx);
128
		dst += 16;
125
		} else {
129
		src += 16;
126
			ast_aes_decrypt(curblock, tmpP, &dcx);
130
		data_len -= 16;
127
		}

    
   
128
		tmpP += AES_BLOCK_SIZE;

    
   
129
		data_len -= AES_BLOCK_SIZE;

    
   
130
	}

    
   
131

   

    
   
132
	if (encrypt) {                            /* if encrypting encode result to base64 */

    
   
133
		ast_base64encode(buf, (unsigned char *) tmp, len, len);

    
   
134
	} else {

    
   
135
		memcpy(buf, tmp, len);
131
	}
136
	}
132
	
137
	free(tmp);

    
   
138

   
133
	return 0;
139
	return 0;
134
}
140
}
135

    
   
141

   
136
static struct ast_custom_function aes_encrypt_function = {
142
static struct ast_custom_function aes_encrypt_function = {
137
	.name = "AES_ENCRYPT",
143
	.name = "AES_ENCRYPT",
138
	.read = aes_encrypt_read,
144
	.read = aes_helper,
139
};
145
};
140

    
   
146

   
141
static struct ast_custom_function aes_decrypt_function = {
147
static struct ast_custom_function aes_decrypt_function = {
142
	.name = "AES_DECRYPT",
148
	.name = "AES_DECRYPT",
143
	.read = aes_decrypt_read,
149
	.read = aes_helper,
144
};
150
};
145

    
   
151

   
146

    
   
152

   
147
static int unload_module(void)
153
static int unload_module(void)
148
{
154
{
149
	int res = ast_custom_function_unregister(&aes_decrypt_function);
155
	int res = ast_custom_function_unregister(&aes_decrypt_function);
150
	return res |= ast_custom_function_unregister(&aes_encrypt_function);
156
	return res | ast_custom_function_unregister(&aes_encrypt_function);
151
}
157
}
152

    
   
158

   
153
static int load_module(void)
159
static int load_module(void)
154
{
160
{
155
	int res = ast_custom_function_register(&aes_decrypt_function);
161
	int res = ast_custom_function_register(&aes_decrypt_function);
156
	return res |= ast_custom_function_register(&aes_encrypt_function);
162
	res |= ast_custom_function_register(&aes_encrypt_function);

    
   
163
	return res ? AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS;
157
}
164
}
158

    
   
165

   
159
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "AES dialplan functions");
166
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "AES dialplan functions");
  1. /trunk/funcs/func_aes.c: Loading...

https://reviewboard.asterisk.org/ runs on a server provided by Digium, Inc. and uses bandwidth donated to the open source Asterisk community by API Digital Communications in Huntsville, AL USA.
Please report problems with this site to asteriskteam@digium.com.