1 | /* Copyright (c) 2002, 2012, eperi GmbH. |
2 | |
3 | This program is free software; you can redistribute it and/or modify |
4 | it under the terms of the GNU General Public License as published by |
5 | the Free Software Foundation; version 2 of the License. |
6 | |
7 | This program is distributed in the hope that it will be useful, |
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
10 | GNU General Public License for more details. |
11 | |
12 | You should have received a copy of the GNU General Public License |
13 | along with this program; if not, write to the Free Software |
14 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ |
15 | |
16 | #include <my_global.h> |
17 | #include <typelib.h> |
18 | #include "parser.h" |
19 | #include <mysql/plugin_encryption.h> |
20 | #include <string.h> |
21 | |
22 | static char* filename; |
23 | static char* filekey; |
24 | static unsigned long encryption_algorithm; |
25 | |
26 | static const char *encryption_algorithm_names[]= |
27 | { |
28 | "aes_cbc" , |
29 | #ifdef HAVE_EncryptAes128Ctr |
30 | "aes_ctr" , |
31 | #endif |
32 | 0 |
33 | }; |
34 | |
35 | static TYPELIB encryption_algorithm_typelib= |
36 | { |
37 | array_elements(encryption_algorithm_names)-1,"" , |
38 | encryption_algorithm_names, NULL |
39 | }; |
40 | |
41 | |
42 | static MYSQL_SYSVAR_STR(filename, filename, |
43 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, |
44 | "Path and name of the key file." , |
45 | NULL, NULL, "" ); |
46 | |
47 | static MYSQL_SYSVAR_STR(filekey, filekey, |
48 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, |
49 | "Key to encrypt / decrypt the keyfile." , |
50 | NULL, NULL, "" ); |
51 | |
52 | #ifdef HAVE_EncryptAes128Ctr |
53 | #define recommendation ", aes_ctr is the recommended one" |
54 | #else |
55 | #define recommendation "" |
56 | #endif |
57 | static MYSQL_SYSVAR_ENUM(encryption_algorithm, encryption_algorithm, |
58 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, |
59 | "Encryption algorithm to use" recommendation "." , |
60 | NULL, NULL, 0, &encryption_algorithm_typelib); |
61 | |
62 | static struct st_mysql_sys_var* settings[] = { |
63 | MYSQL_SYSVAR(filename), |
64 | MYSQL_SYSVAR(filekey), |
65 | MYSQL_SYSVAR(encryption_algorithm), |
66 | NULL |
67 | }; |
68 | |
69 | std::map<unsigned int,keyentry> keys; |
70 | |
71 | static keyentry *get_key(unsigned int key_id) |
72 | { |
73 | keyentry &key= keys[key_id]; |
74 | if (key.id == 0) |
75 | return 0; |
76 | return &key; |
77 | } |
78 | |
79 | /* the version is always the same, no automatic key rotation */ |
80 | static unsigned int get_latest_version(uint key_id) |
81 | { |
82 | return get_key(key_id) ? 1 : ENCRYPTION_KEY_VERSION_INVALID; |
83 | } |
84 | |
85 | static unsigned int get_key_from_key_file(unsigned int key_id, |
86 | unsigned int key_version, unsigned char* dstbuf, unsigned *buflen) |
87 | { |
88 | if (key_version != 1) |
89 | return ENCRYPTION_KEY_VERSION_INVALID; |
90 | |
91 | keyentry* entry = get_key(key_id); |
92 | |
93 | if (entry == NULL) |
94 | return ENCRYPTION_KEY_VERSION_INVALID; |
95 | |
96 | if (*buflen < entry->length) |
97 | { |
98 | *buflen= entry->length; |
99 | return ENCRYPTION_KEY_BUFFER_TOO_SMALL; |
100 | } |
101 | |
102 | *buflen= entry->length; |
103 | if (dstbuf) |
104 | memcpy(dstbuf, entry->key, entry->length); |
105 | |
106 | return 0; |
107 | } |
108 | |
109 | // let's simplify the condition below |
110 | #ifndef HAVE_EncryptAes128Gcm |
111 | #define MY_AES_GCM MY_AES_CTR |
112 | #ifndef HAVE_EncryptAes128Ctr |
113 | #define MY_AES_CTR MY_AES_CBC |
114 | #endif |
115 | #endif |
116 | |
117 | static inline enum my_aes_mode mode(int flags) |
118 | { |
119 | /* |
120 | If encryption_algorithm is AES_CTR then |
121 | if no-padding, use AES_CTR |
122 | else use AES_GCM (like CTR but appends a "checksum" block) |
123 | else |
124 | use AES_CBC |
125 | */ |
126 | if (encryption_algorithm) |
127 | if (flags & ENCRYPTION_FLAG_NOPAD) |
128 | return MY_AES_CTR; |
129 | else |
130 | return MY_AES_GCM; |
131 | else |
132 | return MY_AES_CBC; |
133 | } |
134 | |
135 | static int ctx_init(void *ctx, const unsigned char* key, unsigned int klen, |
136 | const unsigned char* iv, unsigned int ivlen, int flags, |
137 | unsigned int key_id, unsigned int key_version) |
138 | { |
139 | return my_aes_crypt_init(ctx, mode(flags), flags, key, klen, iv, ivlen); |
140 | } |
141 | |
142 | static int ctx_update(void *ctx, const unsigned char *src, unsigned int slen, |
143 | unsigned char *dst, unsigned int *dlen) |
144 | { |
145 | return my_aes_crypt_update(ctx, src, slen, dst, dlen); |
146 | } |
147 | |
148 | |
149 | static int ctx_finish(void *ctx, unsigned char *dst, unsigned int *dlen) |
150 | { |
151 | return my_aes_crypt_finish(ctx, dst, dlen); |
152 | } |
153 | |
154 | static unsigned int get_length(unsigned int slen, unsigned int key_id, |
155 | unsigned int key_version) |
156 | { |
157 | return my_aes_get_size(mode(0), slen); |
158 | } |
159 | |
160 | static uint ctx_size(uint, uint) |
161 | { |
162 | return my_aes_ctx_size(mode(0)); |
163 | } |
164 | |
165 | struct st_mariadb_encryption file_key_management_plugin= { |
166 | MariaDB_ENCRYPTION_INTERFACE_VERSION, |
167 | get_latest_version, |
168 | get_key_from_key_file, |
169 | ctx_size, |
170 | ctx_init, |
171 | ctx_update, |
172 | ctx_finish, |
173 | get_length |
174 | }; |
175 | |
176 | static int file_key_management_plugin_init(void *p) |
177 | { |
178 | Parser parser(filename, filekey); |
179 | return parser.parse(&keys); |
180 | } |
181 | |
182 | static int file_key_management_plugin_deinit(void *p) |
183 | { |
184 | keys.clear(); |
185 | return 0; |
186 | } |
187 | |
188 | /* |
189 | Plugin library descriptor |
190 | */ |
191 | maria_declare_plugin(file_key_management) |
192 | { |
193 | MariaDB_ENCRYPTION_PLUGIN, |
194 | &file_key_management_plugin, |
195 | "file_key_management" , |
196 | "Denis Endro eperi GmbH" , |
197 | "File-based key management plugin" , |
198 | PLUGIN_LICENSE_GPL, |
199 | file_key_management_plugin_init, |
200 | file_key_management_plugin_deinit, |
201 | 0x0100 /* 1.0 */, |
202 | NULL, /* status variables */ |
203 | settings, |
204 | "1.0" , |
205 | MariaDB_PLUGIN_MATURITY_STABLE |
206 | } |
207 | maria_declare_plugin_end; |
208 | |