1/*
2 Copyright (c) 2014 Google Inc.
3 Copyright (c) 2014, 2015 MariaDB Corporation
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; version 2 of the License.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
17
18/**
19 Example key management plugin. It demonstrates how to return
20 keys on request, how to change them. That the engine can have
21 different pages in the same tablespace encrypted with different keys
22 and what the background re-encryption thread does.
23
24 THIS IS AN EXAMPLE ONLY! ENCRYPTION KEYS ARE HARD-CODED AND *NOT* SECRET!
25 DO NOT USE THIS PLUGIN IN PRODUCTION! EVER!
26*/
27
28#include <my_global.h>
29#include <my_pthread.h>
30#include <mysql/plugin_encryption.h>
31#include <my_crypt.h>
32
33/* rotate key randomly between 45 and 90 seconds */
34#define KEY_ROTATION_MIN 45
35#define KEY_ROTATION_MAX 90
36
37static time_t key_version = 0;
38static time_t next_key_version = 0;
39static pthread_mutex_t mutex;
40
41
42/* Random double value in 0..1 range */
43static double double_rnd()
44{
45 return ((double)rand()) / RAND_MAX;
46}
47
48
49static unsigned int
50get_latest_key_version(unsigned int key_id)
51{
52 time_t now = time(0);
53 pthread_mutex_lock(&mutex);
54 if (now >= next_key_version)
55 {
56 key_version = now;
57 unsigned int interval = KEY_ROTATION_MAX - KEY_ROTATION_MIN;
58 next_key_version = (time_t) (now + KEY_ROTATION_MIN +
59 double_rnd() * interval);
60 }
61 pthread_mutex_unlock(&mutex);
62
63 return (unsigned int) key_version;
64}
65
66static unsigned int
67get_key(unsigned int key_id, unsigned int version,
68 unsigned char* dstbuf, unsigned *buflen)
69{
70 if (*buflen < MY_MD5_HASH_SIZE)
71 {
72 *buflen= MY_MD5_HASH_SIZE;
73 return ENCRYPTION_KEY_BUFFER_TOO_SMALL;
74 }
75 *buflen= MY_MD5_HASH_SIZE;
76 if (!dstbuf)
77 return 0;
78
79 my_md5_multi(dstbuf, (const char*)&key_id, sizeof(key_id),
80 (const char*)&version, sizeof(version), NULL);
81
82 return 0;
83}
84
85/*
86 for the sake of an example, let's use different encryption algorithms/modes
87 for different keys versions:
88*/
89static inline enum my_aes_mode mode(unsigned int key_version)
90{
91 return key_version & 1 ? MY_AES_ECB : MY_AES_CBC;
92}
93
94int ctx_init(void *ctx, const unsigned char* key, unsigned int klen, const
95 unsigned char* iv, unsigned int ivlen, int flags, unsigned int
96 key_id, unsigned int key_version)
97{
98 return my_aes_crypt_init(ctx, mode(key_version), flags, key, klen, iv, ivlen);
99}
100
101static unsigned int get_length(unsigned int slen, unsigned int key_id,
102 unsigned int key_version)
103{
104 return my_aes_get_size(mode(key_version), slen);
105}
106
107static int example_key_management_plugin_init(void *p)
108{
109 /* init */
110 pthread_mutex_init(&mutex, NULL);
111 get_latest_key_version(1);
112
113 return 0;
114}
115
116static int example_key_management_plugin_deinit(void *p)
117{
118 pthread_mutex_destroy(&mutex);
119 return 0;
120}
121
122
123static int ctx_update(void *ctx, const unsigned char *src, unsigned int slen,
124 unsigned char *dst, unsigned int *dlen)
125{
126 return my_aes_crypt_update(ctx, src, slen, dst, dlen);
127}
128
129
130int ctx_finish(void *ctx, unsigned char *dst, unsigned int *dlen)
131{
132 return my_aes_crypt_finish(ctx, dst, dlen);
133}
134
135static uint ctx_size(unsigned int , unsigned int key_version)
136{
137 return my_aes_ctx_size(mode(key_version));
138}
139
140struct st_mariadb_encryption example_key_management_plugin= {
141 MariaDB_ENCRYPTION_INTERFACE_VERSION,
142 get_latest_key_version,
143 get_key,
144 ctx_size,
145 ctx_init,
146 ctx_update,
147 ctx_finish,
148 get_length
149};
150
151/*
152 Plugin library descriptor
153*/
154maria_declare_plugin(example_key_management)
155{
156 MariaDB_ENCRYPTION_PLUGIN,
157 &example_key_management_plugin,
158 "example_key_management",
159 "Jonas Oreland",
160 "Example key management plugin",
161 PLUGIN_LICENSE_GPL,
162 example_key_management_plugin_init,
163 example_key_management_plugin_deinit,
164 0x0100 /* 1.0 */,
165 NULL, /* status variables */
166 NULL, /* system variables */
167 "1.0",
168 MariaDB_PLUGIN_MATURITY_EXPERIMENTAL
169}
170maria_declare_plugin_end;
171