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 2 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 2 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] 20 lines
[+20] [+] ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
30
#include "asterisk/module.h"
30
#include "asterisk/module.h"
31
#include "asterisk/pbx.h"
31
#include "asterisk/pbx.h"
32
#include "asterisk/app.h"
32
#include "asterisk/app.h"
33
#include "asterisk/aes.h"
33
#include "asterisk/aes.h"
34

    
   
34

   

    
   
35
#define AES_BLOCK_SIZE 16
35

    
   
36

   
36
static int aes_encrypt_read(struct ast_channel *chan, const char *cmd, char *data,
37
/*** DOCUMENTATION

    
   
38
	<function name="AES_ENCRYPT" language="en_US">

    
   
39
		<synopsis>

    
   
40
			Encrypt a string with AES given a 16 character key.

    
   
41
		</synopsis>

    
   
42
		<syntax>

    
   
43
			<parameter name="string" required="true">

    
   
44
				<para>Input string</para>

    
   
45
			</parameter>

    
   
46
			<parameter name="key" required="true">

    
   
47
				<para>AES Key</para>

    
   
48
			</parameter>

    
   
49
		</syntax>

    
   
50
		<description>

    
   
51
			<para>Returns an AES encrypted string encoded in base64.</para>

    
   
52
		</description>

    
   
53
	</function>

    
   
54
	<function name="AES_DECRYPT" language="en_US">

    
   
55
		<synopsis>

    
   
56
			Decrypt a string encoded in base64 with AES given a 16 character key.

    
   
57
		</synopsis>

    
   
58
		<syntax>

    
   
59
			<parameter name="string" required="true">

    
   
60
				<para>Input string.</para>

    
   
61
			</parameter>

    
   
62
			<parameter name="key" required="true">

    
   
63
				<para>AES Key</para>

    
   
64
			</parameter>

    
   
65

   

    
   
66
		</syntax>

    
   
67
		<description>

    
   
68
			<para>Returns the plain text string.</para>

    
   
69
		</description>

    
   
70
	</function>

    
   
71
 ***/

    
   
72

   

    
   
73

   

    
   
74
static int aes_helper(struct ast_channel *chan, const char *cmd, char *data,
37
	       char *buf, size_t len)
75
	       char *buf, size_t len)
38
{
76
{
39
	unsigned char curblock[16] = { 0, };
77
	unsigned char curblock[AES_BLOCK_SIZE] = { 0, };
40
	char *src;
78
	char *tmp;
41
	char *dst;
79
	char *tmpP;
42
	int data_len;
80
	int data_len, encrypt;
43
	ast_aes_encrypt_key ecx;                       /*  AES 128 Encryption context */
81
	ast_aes_encrypt_key ecx;                        /*  AES 128 Encryption context */

    
   
82
	ast_aes_decrypt_key dcx;
44

    
   
83

   
45
	AST_DECLARE_APP_ARGS(args,
84
	AST_DECLARE_APP_ARGS(args,
46
		AST_APP_ARG(key);
85
		AST_APP_ARG(key);
47
		AST_APP_ARG(data);
86
		AST_APP_ARG(data);
48
	);
87
	);
49

    
   
88

   
50
	AST_STANDARD_APP_ARGS(args, data);
89
	AST_STANDARD_APP_ARGS(args, data);
51

    
   
90

   
52
	if (ast_strlen_zero(args.data) || ast_strlen_zero(args.key)) {
91
	if (ast_strlen_zero(args.data) || ast_strlen_zero(args.key)) {
53
		ast_log(LOG_WARNING, "Syntax: AES_ENCRYPT(<key>,<data>) - missing argument!\n");
92
		ast_log(LOG_WARNING, "Syntax: %s(<key>,<data>) - missing argument!\n", cmd);
54
		return -1;
93
		return -1;
55
	}
94
	}
56

    
   
95

   
57
	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 */
58
		ast_log(LOG_WARNING, "Syntax: AES_ENCRYPT(<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);
59
		return -1;
98
		return -1;
60
	}
99
	}
61

    
   
100

   
62
	ast_aes_encrypt_key(args.key, &ecx);
101
	ast_aes_encrypt_key(args.key, &ecx);   /* encryption:  plaintext -> encyptedtext -> base64 */
63

    
   
102
	ast_aes_decrypt_key(args.key, &dcx);   /* decryption:  base64 -> encyptedtext -> plaintext */
64
	dst = buf;
103
	tmp = ast_calloc(1, len);                     /* requires a tmp buffer for the base64 decode */
65
	src = args.data;
104
	tmpP = tmp;
66
	data_len = strlen(args.data);
105
	encrypt = strcmp("AES_DECRYPT", cmd);           /* -1 if encrypting, 0 if decrypting */

    
   
106

   

    
   
107
	if (encrypt) {                                  /* if decrypting first decode src to base64 */

    
   
108
		memcpy(tmp, args.data, strlen(args.data));  /* use same tmp buffer for encrypt as well to keep things simple */

    
   
109
		data_len = strlen(tmp);

    
   
110
	} else {

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

    
   
112
		data_len = strlen(tmp);

    
   
113
	}
67

    
   
114

   
68
	if (data_len >= len) {                           /* make sure to not go over buffer len */
115
	if (data_len >= len) {                        /* make sure to not go over buffer len */
69
		ast_log(LOG_WARNING, "Syntax: AES_ENCRYPT(<keys>,<data>) - <data> exceeds buffer length.  Result may be truncated!\n");
116
		ast_log(LOG_WARNING, "Syntax: %s(<keys>,<data>) - <data> exceeds buffer length.  Result may be truncated!\n", cmd);
70
		data_len = len - 1;
117
		data_len = len - 1;
71
	}
118
	}
72

    
   
119

   
73
	while (data_len > 0) {
120
	while (data_len > 0) {
74
		memset(curblock,0,sizeof(curblock));
121
		memset(curblock, 0, AES_BLOCK_SIZE);
75
		if (data_len < 16) {
122
		memcpy(curblock, tmpP, (data_len < AES_BLOCK_SIZE) ? data_len : AES_BLOCK_SIZE);
76
			memcpy(curblock,src,data_len);
123
		if (encrypt == 0) {

    
   
124
			ast_aes_encrypt(curblock, tmpP, &ecx);
77
		} else {
125
		} else {
78
			memcpy(curblock,src,16);
126
			ast_aes_decrypt(curblock, tmpP, &dcx);
79
		}

   
80
		ast_aes_encrypt(curblock, dst, &ecx);

   
81
		dst += 16;

   
82
		src += 16;

   
83
		data_len -= 16;

   
84
	}
127
		}
85

    
   
128
		tmpP += AES_BLOCK_SIZE;
86
	return 0;
129
		data_len -= AES_BLOCK_SIZE;
87
}
130
	}
88
static int aes_decrypt_read(struct ast_channel *chan, const char *cmd, char *data,

   
89
	char *buf, size_t len)

   
90
{

   
91
	unsigned char curblock[16] = { 0, };

   
92
	char *src;

   
93
	char *dst;

   
94
	int data_len;

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

   
96

    
   

   
97
	AST_DECLARE_APP_ARGS(args,

   
98
			AST_APP_ARG(key);

   
99
			AST_APP_ARG(data);

   
100
	);

   
101

    
   
131

   
102
	AST_STANDARD_APP_ARGS(args, data);
132
	if (encrypt) {                            /* if encrypting encode result to base64 */
103

    
   
133
		ast_base64encode(buf, (unsigned char *) tmp, len, len);
104
	if (ast_strlen_zero(args.data) || ast_strlen_zero(args.key)) {

   
105
		ast_log(LOG_WARNING, "Syntax: AES_DECRYPT(<key>,<data>) - missing argument!\n");

   
106
		return -1;

   
107
	}

   
108

    
   

   
109
	if (strlen(args.key) != 16 ) {         /* key must be of 16 characters in length, 128 bits */

   
110
		ast_log(LOG_WARNING, "Syntax: AES_DECRYPT(<key>,<data>) - <key> parameter must be exactly 16 characters!\n");

   
111
		return -1;

   
112
	}

   
113

    
   

   
114
	ast_aes_decrypt_key(args.key, &dcx);

   
115

    
   

   
116
	dst = buf;

   
117
	src = args.data;

   
118
	data_len = strlen(args.data);

   
119

    
   

   
120
	if (data_len >= len) {                       /* make sure to not go over buffer len */

   
121
		ast_log(LOG_WARNING, "Syntax: AES_DECRYPT(<keys>,<data>) - <data> exceeds buffer length.  Result may be truncated!\n");

   
122
		data_len = len - 1;

   
123
	}

   
124

    
   

   
125
	while (data_len > 0) {

   
126
		memset(curblock,0,sizeof(curblock));

   
127
		if (data_len < 16) {

   
128
			memcpy(curblock,src,data_len);

   
129
		} else {
134
	} else {
130
			memcpy(curblock,src,16);
135
		memcpy(buf, tmp, len);
131
		}

   
132
		ast_aes_decrypt(curblock, dst, &dcx);

   
133
		dst += 16;

   
134
		src += 16;

   
135
		data_len -= 16;

   
136
	}
136
	}

    
   
137
	free(tmp);
137

    
   
138

   
138
	return 0;
139
	return 0;
139
}
140
}
140

    
   
141

   
141
static struct ast_custom_function aes_encrypt_function = {
142
static struct ast_custom_function aes_encrypt_function = {
142
	.name = "AES_ENCRYPT",
143
	.name = "AES_ENCRYPT",
143
	.read = aes_encrypt_read,
144
	.read = aes_helper,
144
};
145
};
145

    
   
146

   
146
static struct ast_custom_function aes_decrypt_function = {
147
static struct ast_custom_function aes_decrypt_function = {
147
	.name = "AES_DECRYPT",
148
	.name = "AES_DECRYPT",
148
	.read = aes_decrypt_read,
149
	.read = aes_helper,
149
};
150
};
150

    
   
151

   
151

    
   
152

   
152
static int unload_module(void)
153
static int unload_module(void)
153
{
154
{
[+20] [20] 12 lines
  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.