1 /************************************************************************************
2 Copyright (C) 2014 MariaDB Corporation AB
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library 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 GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public
15 License along with this library; if not see <http://www.gnu.org/licenses>
16 or write to the Free Software Foundation, Inc.,
17 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
18
19 *************************************************************************************/
20 #ifdef HAVE_GNUTLS
21
22 #include <ma_global.h>
23 #include <gnutls/gnutls.h>
24 #include <gnutls/x509.h>
25 #include <gnutls/abstract.h>
26 #include <ma_sys.h>
27 #include <ma_common.h>
28 #include <ma_pvio.h>
29 #include <errmsg.h>
30 #include <ma_pthread.h>
31 #include <mysql/client_plugin.h>
32 #include <string.h>
33 #include <ma_tls.h>
34 #include <mariadb_async.h>
35 #include <ma_context.h>
36
37 pthread_mutex_t LOCK_gnutls_config;
38
39 extern my_bool ma_tls_initialized;
40 extern unsigned int mariadb_deinitialize_ssl;
41
42 enum ma_pem_type {
43 MA_TLS_PEM_CERT= 0,
44 MA_TLS_PEM_KEY,
45 MA_TLS_PEM_CA,
46 MA_TLS_PEM_CRL
47 };
48
49 static int my_verify_callback(gnutls_session_t ssl);
50
51 char tls_library_version[TLS_VERSION_LENGTH];
52
53 struct st_gnutls_data {
54 MYSQL *mysql;
55 gnutls_privkey_t key;
56 gnutls_pcert_st cert;
57 };
58
59 struct st_cipher_map {
60 unsigned char sid[2];
61 const char *iana_name;
62 const char *openssl_name;
63 const char *gnutls_name;
64 };
65
66 const struct st_cipher_map tls_ciphers[]=
67 {
68 { {0x00, 0x01},
69 "TLS_RSA_WITH_NULL_MD5",
70 NULL,
71 "TLS_RSA_NULL_MD5"},
72 { {0x00, 0x02},
73 "TLS_RSA_WITH_NULL_SHA",
74 NULL,
75 "TLS_RSA_NULL_SHA1"},
76 { {0x00, 0x3B},
77 "TLS_RSA_WITH_NULL_SHA256",
78 NULL,
79 "TLS_RSA_NULL_SHA256"},
80 { {0x00, 0x05},
81 "TLS_RSA_WITH_RC4_128_SHA",
82 NULL,
83 "TLS_RSA_ARCFOUR_128_SHA1"},
84 { {0x00, 0x04},
85 "TLS_RSA_WITH_RC4_128_MD5",
86 NULL,
87 "TLS_RSA_ARCFOUR_128_MD5"},
88 { {0x00, 0x0A},
89 "TLS_RSA_WITH_3DES_EDE_CBC_SHA",
90 "DES-CBC3-SHA",
91 "TLS_RSA_3DES_EDE_CBC_SHA1"},
92 { {0x00, 0x2F},
93 "TLS_RSA_WITH_AES_128_CBC_SHA",
94 "AES128-SHA",
95 "TLS_RSA_AES_128_CBC_SHA1"},
96 { {0x00, 0x35},
97 "TLS_RSA_WITH_AES_256_CBC_SHA",
98 "AES256-SHA",
99 "TLS_RSA_AES_256_CBC_SHA1"},
100 { {0x00, 0xBA},
101 "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256",
102 "CAMELLIA128-SHA256",
103 "TLS_RSA_CAMELLIA_128_CBC_SHA256"},
104 { {0x00, 0xC0},
105 "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256",
106 NULL,
107 "TLS_RSA_CAMELLIA_256_CBC_SHA256"},
108 { {0x00, 0x41},
109 "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA",
110 "CAMELLIA128-SHA",
111 "TLS_RSA_CAMELLIA_128_CBC_SHA1"},
112 { {0x00, 0x84},
113 "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA",
114 "CAMELLIA256-SHA",
115 "TLS_RSA_CAMELLIA_256_CBC_SHA1"},
116 { {0x00, 0x3C},
117 "TLS_RSA_WITH_AES_128_CBC_SHA256",
118 "AES128-SHA256",
119 "TLS_RSA_AES_128_CBC_SHA256"},
120 { {0x00, 0x3D},
121 "TLS_RSA_WITH_AES_256_CBC_SHA256",
122 "AES256-SHA256",
123 "TLS_RSA_AES_256_CBC_SHA256"},
124 { {0x00, 0x9C},
125 "TLS_RSA_WITH_AES_128_GCM_SHA256",
126 "AES128-GCM-SHA256",
127 "TLS_RSA_AES_128_GCM_SHA256"},
128 { {0x00, 0x9D},
129 "TLS_RSA_WITH_AES_256_GCM_SHA384",
130 "AES256-GCM-SHA384",
131 "TLS_RSA_AES_256_GCM_SHA384"},
132 { {0xC0, 0x7A},
133 "TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256",
134 NULL,
135 "TLS_RSA_CAMELLIA_128_GCM_SHA256"},
136 { {0xC0, 0x7B},
137 "TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384",
138 NULL,
139 "TLS_RSA_CAMELLIA_256_GCM_SHA384"},
140 { {0xC0, 0x9C},
141 "TLS_RSA_WITH_AES_128_CCM",
142 NULL,
143 "TLS_RSA_AES_128_CCM"},
144 { {0xC0, 0x9D},
145 "TLS_RSA_WITH_AES_256_CCM",
146 NULL,
147 "TLS_RSA_AES_256_CCM"},
148 { {0xC0, 0xA0},
149 "TLS_RSA_WITH_AES_128_CCM_8",
150 NULL,
151 "TLS_RSA_AES_128_CCM_8"},
152 { {0xC0, 0xA1},
153 "TLS_RSA_WITH_AES_256_CCM_8",
154 NULL,
155 "TLS_RSA_AES_256_CCM_8"},
156 { {0x00, 0x66},
157 "TLS_DHE_DSS_WITH_RC4_128_SHA",
158 NULL,
159 "TLS_DHE_DSS_ARCFOUR_128_SHA1"},
160 { {0x00, 0x13},
161 "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
162 NULL,
163 "TLS_DHE_DSS_3DES_EDE_CBC_SHA1"},
164 { {0x00, 0x32},
165 "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
166 NULL,
167 "TLS_DHE_DSS_AES_128_CBC_SHA1"},
168 { {0x00, 0x38},
169 "TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
170 NULL,
171 "TLS_DHE_DSS_AES_256_CBC_SHA1"},
172 { {0x00, 0xBD},
173 "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256",
174 NULL,
175 "TLS_DHE_DSS_CAMELLIA_128_CBC_SHA256"},
176 { {0x00, 0xC3},
177 "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256",
178 NULL,
179 "TLS_DHE_DSS_CAMELLIA_256_CBC_SHA256"},
180 { {0x00, 0x44},
181 "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA",
182 NULL,
183 "TLS_DHE_DSS_CAMELLIA_128_CBC_SHA1"},
184 { {0x00, 0x87},
185 "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA",
186 NULL,
187 "TLS_DHE_DSS_CAMELLIA_256_CBC_SHA1"},
188 { {0x00, 0x40},
189 "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256",
190 NULL,
191 "TLS_DHE_DSS_AES_128_CBC_SHA256"},
192 { {0x00, 0x6A},
193 "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",
194 NULL,
195 "TLS_DHE_DSS_AES_256_CBC_SHA256"},
196 { {0x00, 0xA2},
197 "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",
198 NULL,
199 "TLS_DHE_DSS_AES_128_GCM_SHA256"},
200 { {0x00, 0xA3},
201 "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",
202 NULL,
203 "TLS_DHE_DSS_AES_256_GCM_SHA384"},
204 { {0xC0, 0x80},
205 "TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256",
206 NULL,
207 "TLS_DHE_DSS_CAMELLIA_128_GCM_SHA256"},
208 { {0xC0, 0x81},
209 "TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384",
210 NULL,
211 "TLS_DHE_DSS_CAMELLIA_256_GCM_SHA384"},
212 { {0x00, 0x16},
213 "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
214 "EDH-RSA-DES-CBC3-SHA",
215 "TLS_DHE_RSA_3DES_EDE_CBC_SHA1"},
216 { {0x00, 0x33},
217 "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
218 "DHE-RSA-AES128-SHA",
219 "TLS_DHE_RSA_AES_128_CBC_SHA1"},
220 { {0x00, 0x39},
221 "TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
222 "DHE-RSA-AES256-SHA",
223 "TLS_DHE_RSA_AES_256_CBC_SHA1"},
224 { {0x00, 0xBE},
225 "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256",
226 NULL,
227 "TLS_DHE_RSA_CAMELLIA_128_CBC_SHA256"},
228 { {0x00, 0xC4},
229 "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256",
230 NULL,
231 "TLS_DHE_RSA_CAMELLIA_256_CBC_SHA256"},
232 { {0x00, 0x45},
233 "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA",
234 "DHE-RSA-CAMELLIA128-SHA",
235 "TLS_DHE_RSA_CAMELLIA_128_CBC_SHA1"},
236 { {0x00, 0x88},
237 "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA",
238 "DHE-RSA-CAMELLIA256-SHA",
239 "TLS_DHE_RSA_CAMELLIA_256_CBC_SHA1"},
240 { {0x00, 0x67},
241 "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
242 "DHE-RSA-AES128-SHA256",
243 "TLS_DHE_RSA_AES_128_CBC_SHA256"},
244 { {0x00, 0x6B},
245 "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
246 "DHE-RSA-AES256-SHA256",
247 "TLS_DHE_RSA_AES_256_CBC_SHA256"},
248 { {0x00, 0x9E},
249 "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
250 "DHE-RSA-AES128-GCM-SHA256",
251 "TLS_DHE_RSA_AES_128_GCM_SHA256"},
252 { {0x00, 0x9F},
253 "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
254 "DHE-RSA-AES256-GCM-SHA384",
255 "TLS_DHE_RSA_AES_256_GCM_SHA384"},
256 { {0xC0, 0x7C},
257 "TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256",
258 NULL,
259 "TLS_DHE_RSA_CAMELLIA_128_GCM_SHA256"},
260 { {0xC0, 0x7D},
261 "TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384",
262 NULL,
263 "TLS_DHE_RSA_CAMELLIA_256_GCM_SHA384"},
264 { {0xCC, 0xAA},
265 "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
266 "DHE-RSA-CHACHA20-POLY1305",
267 "TLS_DHE_RSA_CHACHA20_POLY1305"},
268 { {0xC0, 0x9E},
269 "TLS_DHE_RSA_WITH_AES_128_CCM",
270 NULL,
271 "TLS_DHE_RSA_AES_128_CCM"},
272 { {0xC0, 0x9F},
273 "TLS_DHE_RSA_WITH_AES_256_CCM",
274 NULL,
275 "TLS_DHE_RSA_AES_256_CCM"},
276 { {0xC0, 0xA2},
277 "TLS_DHE_RSA_WITH_AES_128_CCM_8",
278 NULL,
279 "TLS_DHE_RSA_AES_128_CCM_8"},
280 { {0xC0, 0xA3},
281 "TLS_DHE_RSA_WITH_AES_256_CCM_8",
282 NULL,
283 "TLS_DHE_RSA_AES_256_CCM_8"},
284 { {0xC0, 0x10},
285 "TLS_ECDHE_RSA_WITH_",
286 NULL,
287 "TLS_ECDHE_RSA_NULL_SHA1"},
288 { {0xC0, 0x12},
289 "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
290 "ECDHE-RSA-DES-CBC3-SHA",
291 "TLS_ECDHE_RSA_3DES_EDE_CBC_SHA1"},
292 { {0xC0, 0x13},
293 "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
294 "ECDHE-RSA-AES128-SHA",
295 "TLS_ECDHE_RSA_AES_128_CBC_SHA1"},
296 { {0xC0, 0x14},
297 "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
298 "ECDHE-RSA-AES256-SHA",
299 "TLS_ECDHE_RSA_AES_256_CBC_SHA1"},
300 { {0xC0, 0x28},
301 "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
302 "ECDHE-RSA-AES256-SHA384",
303 "TLS_ECDHE_RSA_AES_256_CBC_SHA384"},
304 { {0xC0, 0x11},
305 "TLS_ECDHE_RSA_WITH_RC4_128_SHA",
306 NULL,
307 "TLS_ECDHE_RSA_ARCFOUR_128_SHA1"},
308 { {0xC0, 0x76},
309 "TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256",
310 NULL,
311 "TLS_ECDHE_RSA_CAMELLIA_128_CBC_SHA256"},
312 { {0xC0, 0x77},
313 "TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384",
314 NULL,
315 "TLS_ECDHE_RSA_CAMELLIA_256_CBC_SHA384"},
316 { {0xC0, 0x06},
317 "TLS_ECDHE_ECDSA_WITH_",
318 NULL,
319 "TLS_ECDHE_ECDSA_NULL_SHA1"},
320 { {0xC0, 0x08},
321 "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
322 "ECDHE-ECDSA-DES-CBC3-SHA",
323 "TLS_ECDHE_ECDSA_3DES_EDE_CBC_SHA1"},
324 { {0xC0, 0x09},
325 "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
326 "ECDHE-ECDSA-AES128-SHA",
327 "TLS_ECDHE_ECDSA_AES_128_CBC_SHA1"},
328 { {0xC0, 0x0A},
329 "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
330 "ECDHE-ECDSA-AES256-SHA",
331 "TLS_ECDHE_ECDSA_AES_256_CBC_SHA1"},
332 { {0xC0, 0x07},
333 "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
334 NULL,
335 "TLS_ECDHE_ECDSA_ARCFOUR_128_SHA1"},
336 { {0xC0, 0x72},
337 "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256",
338 NULL,
339 "TLS_ECDHE_ECDSA_CAMELLIA_128_CBC_SHA256"},
340 { {0xC0, 0x73},
341 "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384",
342 NULL,
343 "TLS_ECDHE_ECDSA_CAMELLIA_256_CBC_SHA384"},
344 { {0xC0, 0x23},
345 "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
346 "ECDHE-ECDSA-AES128-SHA256",
347 "TLS_ECDHE_ECDSA_AES_128_CBC_SHA256"},
348 { {0xC0, 0x27},
349 "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
350 "ECDHE-RSA-AES128-SHA256",
351 "TLS_ECDHE_RSA_AES_128_CBC_SHA256"},
352 { {0xC0, 0x86},
353 "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256",
354 NULL,
355 "TLS_ECDHE_ECDSA_CAMELLIA_128_GCM_SHA256"},
356 { {0xC0, 0x87},
357 "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384",
358 NULL,
359 "TLS_ECDHE_ECDSA_CAMELLIA_256_GCM_SHA384"},
360 { {0xC0, 0x2B},
361 "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
362 "ECDHE-ECDSA-AES128-GCM-SHA256",
363 "TLS_ECDHE_ECDSA_AES_128_GCM_SHA256"},
364 { {0xC0, 0x2C},
365 "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
366 "ECDHE-ECDSA-AES256-GCM-SHA384",
367 "TLS_ECDHE_ECDSA_AES_256_GCM_SHA384"},
368 { {0xC0, 0x2F},
369 "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
370 "ECDHE-RSA-AES128-GCM-SHA256",
371 "TLS_ECDHE_RSA_AES_128_GCM_SHA256"},
372 { {0xC0, 0x30},
373 "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
374 "ECDHE-RSA-AES256-GCM-SHA384",
375 "TLS_ECDHE_RSA_AES_256_GCM_SHA384"},
376 { {0xC0, 0x24},
377 "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
378 "ECDHE-ECDSA-AES256-SHA384",
379 "TLS_ECDHE_ECDSA_AES_256_CBC_SHA384"},
380 { {0xC0, 0x8A},
381 "TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256",
382 NULL,
383 "TLS_ECDHE_RSA_CAMELLIA_128_GCM_SHA256"},
384 { {0xC0, 0x8B},
385 "TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384",
386 NULL,
387 "TLS_ECDHE_RSA_CAMELLIA_256_GCM_SHA384"},
388 { {0xCC, 0xA8},
389 "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
390 "ECDHE-RSA-CHACHA20-POLY1305",
391 "TLS_ECDHE_RSA_CHACHA20_POLY1305"},
392 { {0xCC, 0xA9},
393 "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
394 "ECDHE-ECDSA-CHACHA20-POLY1305",
395 "TLS_ECDHE_ECDSA_CHACHA20_POLY1305"},
396 { {0xC0, 0xAC},
397 "TLS_ECDHE_ECDSA_WITH_AES_128_CCM",
398 NULL,
399 "TLS_ECDHE_ECDSA_AES_128_CCM"},
400 { {0xC0, 0xAD},
401 "TLS_ECDHE_ECDSA_WITH_AES_256_CCM",
402 NULL,
403 "TLS_ECDHE_ECDSA_AES_256_CCM"},
404 { {0xC0, 0xAE},
405 "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8",
406 NULL,
407 "TLS_ECDHE_ECDSA_AES_128_CCM_8"},
408 { {0xC0, 0xAF},
409 "TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8",
410 NULL,
411 "TLS_ECDHE_ECDSA_AES_256_CCM_8"},
412 { {0xC0, 0x34},
413 "TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA",
414 "ECDHE-PSK-3DES-EDE-CBC-SHA",
415 "TLS_ECDHE_PSK_3DES_EDE_CBC_SHA1"},
416 { {0xC0, 0x35},
417 "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA",
418 "ECDHE-PSK-AES128-CBC-SHA",
419 "TLS_ECDHE_PSK_AES_128_CBC_SHA1"},
420 { {0xC0, 0x36},
421 "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA",
422 "ECDHE-PSK-AES256-CBC-SHA",
423 "TLS_ECDHE_PSK_AES_256_CBC_SHA1"},
424 { {0xC0, 0x37},
425 "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256",
426 "ECDHE-PSK-AES128-CBC-SHA256",
427 "TLS_ECDHE_PSK_AES_128_CBC_SHA256"},
428 { {0xC0, 0x38},
429 "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384",
430 "ECDHE-PSK-AES256-CBC-SHA384",
431 "TLS_ECDHE_PSK_AES_256_CBC_SHA384"},
432 { {0xC0, 0x33},
433 "TLS_ECDHE_PSK_WITH_RC4_128_SHA",
434 NULL,
435 "TLS_ECDHE_PSK_ARCFOUR_128_SHA1"},
436 { {0xC0, 0x39},
437 "TLS_ECDHE_PSK_WITH_NULL_SHA",
438 NULL,
439 "TLS_ECDHE_PSK_NULL_SHA1"},
440 { {0xC0, 0x3A},
441 "TLS_ECDHE_PSK_WITH_NULL_SHA256",
442 NULL,
443 "TLS_ECDHE_PSK_NULL_SHA256"},
444 { {0xC0, 0x3B},
445 "TLS_ECDHE_PSK_WITH_NULL_SHA384",
446 NULL,
447 "TLS_ECDHE_PSK_NULL_SHA384"},
448 { {0xC0, 0x9A},
449 "TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256",
450 NULL,
451 "TLS_ECDHE_PSK_CAMELLIA_128_CBC_SHA256"},
452 { {0xC0, 0x9B},
453 "TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384",
454 NULL,
455 "TLS_ECDHE_PSK_CAMELLIA_256_CBC_SHA384"},
456 { {0x00, 0x8A},
457 "TLS_PSK_WITH_RC4_128_SHA",
458 NULL,
459 "TLS_PSK_ARCFOUR_128_SHA1"},
460 { {0x00, 0x8B},
461 "TLS_PSK_WITH_3DES_EDE_CBC_SHA",
462 "PSK-3DES-EDE-CBC-SHA",
463 "TLS_PSK_3DES_EDE_CBC_SHA1"},
464 { {0x00, 0x8C},
465 "TLS_PSK_WITH_AES_128_CBC_SHA",
466 "PSK-AES128-CBC-SHA",
467 "TLS_PSK_AES_128_CBC_SHA1"},
468 { {0x00, 0x8D},
469 "TLS_PSK_WITH_AES_256_CBC_SHA",
470 "PSK-AES256-CBC-SHA",
471 "TLS_PSK_AES_256_CBC_SHA1"},
472 { {0x00, 0xAE},
473 "TLS_PSK_WITH_AES_128_CBC_SHA256",
474 "PSK-AES128-CBC-SHA256",
475 "TLS_PSK_AES_128_CBC_SHA256"},
476 { {0x00, 0xA9},
477 "TLS_PSK_WITH_AES_256_GCM_SHA384",
478 "PSK-AES256-GCM-SHA384",
479 "TLS_PSK_AES_256_GCM_SHA384"},
480 { {0xC0, 0x8E},
481 "TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256",
482 NULL,
483 "TLS_PSK_CAMELLIA_128_GCM_SHA256"},
484 { {0xC0, 0x8F},
485 "TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384",
486 NULL,
487 "TLS_PSK_CAMELLIA_256_GCM_SHA384"},
488 { {0x00, 0xA8},
489 "TLS_PSK_WITH_AES_128_GCM_SHA256",
490 "PSK-AES128-GCM-SHA256",
491 "TLS_PSK_AES_128_GCM_SHA256"},
492 { {0x00, 0x2C},
493 "TLS_PSK_WITH_",
494 NULL,
495 "TLS_PSK_NULL_SHA1"},
496 { {0x00, 0xB0},
497 "TLS_PSK_WITH_",
498 NULL,
499 "TLS_PSK_NULL_SHA256"},
500 { {0xC0, 0x94},
501 "TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256",
502 NULL,
503 "TLS_PSK_CAMELLIA_128_CBC_SHA256"},
504 { {0xC0, 0x95},
505 "TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384",
506 NULL,
507 "TLS_PSK_CAMELLIA_256_CBC_SHA384"},
508 { {0x00, 0xAF},
509 "TLS_PSK_WITH_AES_256_CBC_SHA384",
510 "PSK-AES256-CBC-SHA384",
511 "TLS_PSK_AES_256_CBC_SHA384"},
512 { {0x00, 0xB1},
513 "TLS_PSK_WITH_",
514 NULL,
515 "TLS_PSK_NULL_SHA384"},
516 { {0x00, 0x92},
517 "TLS_RSA_PSK_WITH_RC4_128_SHA",
518 NULL,
519 "TLS_RSA_PSK_ARCFOUR_128_SHA1"},
520 { {0x00, 0x93},
521 "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA",
522 "RSA-PSK-3DES-EDE-CBC-SHA",
523 "TLS_RSA_PSK_3DES_EDE_CBC_SHA1"},
524 { {0x00, 0x94},
525 "TLS_RSA_PSK_WITH_AES_128_CBC_SHA",
526 "RSA-PSK-AES128-CBC-SHA",
527 "TLS_RSA_PSK_AES_128_CBC_SHA1"},
528 { {0x00, 0x95},
529 "TLS_RSA_PSK_WITH_AES_256_CBC_SHA",
530 "RSA-PSK-AES256-CBC-SHA",
531 "TLS_RSA_PSK_AES_256_CBC_SHA1"},
532 { {0xC0, 0x92},
533 "TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256",
534 NULL,
535 "TLS_RSA_PSK_CAMELLIA_128_GCM_SHA256"},
536 { {0xC0, 0x93},
537 "TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384",
538 NULL,
539 "TLS_RSA_PSK_CAMELLIA_256_GCM_SHA384"},
540 { {0x00, 0xAC},
541 "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256",
542 "RSA-PSK-AES128-GCM-SHA256",
543 "TLS_RSA_PSK_AES_128_GCM_SHA256"},
544 { {0x00, 0xB6},
545 "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256",
546 "RSA-PSK-AES128-CBC-SHA256",
547 "TLS_RSA_PSK_AES_128_CBC_SHA256"},
548 { {0x00, 0x2E},
549 "TLS_RSA_PSK_WITH_NULL_SHA",
550 NULL,
551 "TLS_RSA_PSK_NULL_SHA1"},
552 { {0x00, 0xB8},
553 "TLS_RSA_PSK_WITH_",
554 NULL,
555 "TLS_RSA_PSK_NULL_SHA256"},
556 { {0x00, 0xAD},
557 "TLS_RSA_PSK_WITH_AES_256_GCM_SHA384",
558 "RSA-PSK-AES256-GCM-SHA384",
559 "TLS_RSA_PSK_AES_256_GCM_SHA384"},
560 { {0x00, 0xB7},
561 "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384",
562 "RSA-PSK-AES256-CBC-SHA384",
563 "TLS_RSA_PSK_AES_256_CBC_SHA384"},
564 { {0x00, 0xB9},
565 "TLS_RSA_PSK_WITH_",
566 NULL,
567 "TLS_RSA_PSK_NULL_SHA384"},
568 { {0xC0, 0x98},
569 "TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256",
570 NULL,
571 "TLS_RSA_PSK_CAMELLIA_128_CBC_SHA256"},
572 { {0xC0, 0x99},
573 "TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384",
574 NULL,
575 "TLS_RSA_PSK_CAMELLIA_256_CBC_SHA384"},
576 { {0x00, 0x8E},
577 "TLS_DHE_PSK_WITH_RC4_128_SHA",
578 NULL,
579 "TLS_DHE_PSK_ARCFOUR_128_SHA1"},
580 { {0x00, 0x8F},
581 "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA",
582 "DHE-PSK-3DES-EDE-CBC-SHA",
583 "TLS_DHE_PSK_3DES_EDE_CBC_SHA1"},
584 { {0x00, 0x90},
585 "TLS_DHE_PSK_WITH_AES_128_CBC_SHA",
586 "DHE-PSK-AES128-CBC-SHA",
587 "TLS_DHE_PSK_AES_128_CBC_SHA1"},
588 { {0x00, 0x91},
589 "TLS_DHE_PSK_WITH_AES_256_CBC_SHA",
590 "DHE-PSK-AES256-CBC-SHA",
591 "TLS_DHE_PSK_AES_256_CBC_SHA1"},
592 { {0x00, 0xB2},
593 "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256",
594 "DHE-PSK-AES128-CBC-SHA256",
595 "TLS_DHE_PSK_AES_128_CBC_SHA256"},
596 { {0x00, 0xAA},
597 "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256",
598 "DHE-PSK-AES128-GCM-SHA256",
599 "TLS_DHE_PSK_AES_128_GCM_SHA256"},
600 { {0x00, 0x2D},
601 "TLS_DHE_PSK_WITH_",
602 NULL,
603 "TLS_DHE_PSK_NULL_SHA1"},
604 { {0x00, 0xB4},
605 "TLS_DHE_PSK_WITH_",
606 NULL,
607 "TLS_DHE_PSK_NULL_SHA256"},
608 { {0x00, 0xB5},
609 "TLS_DHE_PSK_WITH_",
610 NULL,
611 "TLS_DHE_PSK_NULL_SHA384"},
612 { {0x00, 0xB3},
613 "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384",
614 "DHE-PSK-AES256-CBC-SHA384",
615 "TLS_DHE_PSK_AES_256_CBC_SHA384"},
616 { {0x00, 0xAB},
617 "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384",
618 "DHE-PSK-AES256-GCM-SHA384",
619 "TLS_DHE_PSK_AES_256_GCM_SHA384"},
620 { {0xC0, 0x96},
621 "TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256",
622 NULL,
623 "TLS_DHE_PSK_CAMELLIA_128_CBC_SHA256"},
624 { {0xC0, 0x97},
625 "TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384",
626 NULL,
627 "TLS_DHE_PSK_CAMELLIA_256_CBC_SHA384"},
628 { {0xC0, 0x90},
629 "TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256",
630 NULL,
631 "TLS_DHE_PSK_CAMELLIA_128_GCM_SHA256"},
632 { {0xC0, 0x91},
633 "TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384",
634 NULL,
635 "TLS_DHE_PSK_CAMELLIA_256_GCM_SHA384"},
636 { {0xC0, 0xA4},
637 "TLS_PSK_WITH_AES_128_CCM",
638 NULL,
639 "TLS_PSK_AES_128_CCM"},
640 { {0xC0, 0xA5},
641 "TLS_PSK_WITH_AES_256_CCM",
642 NULL,
643 "TLS_PSK_AES_256_CCM"},
644 { {0xC0, 0xA6},
645 "TLS_DHE_PSK_WITH_AES_128_CCM",
646 NULL,
647 "TLS_DHE_PSK_AES_128_CCM"},
648 { {0xC0, 0xA7},
649 "TLS_DHE_PSK_WITH_AES_256_CCM",
650 NULL,
651 "TLS_DHE_PSK_AES_256_CCM"},
652 { {0xC0, 0xA8},
653 "TLS_PSK_WITH_AES_128_CCM_8",
654 NULL,
655 "TLS_PSK_AES_128_CCM_8"},
656 { {0xC0, 0xA9},
657 "TLS_PSK_WITH_AES_256_CCM_8",
658 NULL,
659 "TLS_PSK_AES_256_CCM_8"},
660 { {0xC0, 0xAA},
661 "TLS_PSK_DHE_WITH_AES_128_CCM_8",
662 NULL,
663 "TLS_DHE_PSK_AES_128_CCM_8"},
664 { {0xC0, 0xAB},
665 "TLS_PSK_DHE_WITH_AES_256_CCM_8",
666 NULL,
667 "TLS_DHE_PSK_AES_256_CCM_8"},
668 { {0xCC, 0xAD},
669 "TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256",
670 "DHE-PSK-CHACHA20-POLY1305",
671 "TLS_DHE_PSK_CHACHA20_POLY1305"},
672 { {0xCC, 0xAC},
673 "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256",
674 "ECDHE-PSK-CHACHA20-POLY1305",
675 "TLS_ECDHE_PSK_CHACHA20_POLY1305"},
676 { {0xCC, 0xAE},
677 "TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256",
678 "RSA-PSK-CHACHA20-POLY1305",
679 "TLS_RSA_PSK_CHACHA20_POLY1305"},
680 { {0xCC, 0xAB},
681 "TLS_PSK_WITH_CHACHA20_POLY1305_SHA256",
682 "PSK-CHACHA20-POLY1305",
683 "TLS_PSK_CHACHA20_POLY1305"},
684 { {0x00, 0x18},
685 "TLS_DH_anon_WITH_RC4_128_MD5",
686 NULL,
687 "TLS_DH_ANON_ARCFOUR_128_MD5"},
688 { {0x00, 0x1B},
689 "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA",
690 NULL,
691 "TLS_DH_ANON_3DES_EDE_CBC_SHA1"},
692 { {0x00, 0x34},
693 "TLS_DH_anon_WITH_AES_128_CBC_SHA",
694 NULL,
695 "TLS_DH_ANON_AES_128_CBC_SHA1"},
696 { {0x00, 0x3A},
697 "TLS_DH_anon_WITH_AES_256_CBC_SHA",
698 NULL,
699 "TLS_DH_ANON_AES_256_CBC_SHA1"},
700 { {0x00, 0xBF},
701 "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256",
702 NULL,
703 "TLS_DH_ANON_CAMELLIA_128_CBC_SHA256"},
704 { {0x00, 0xC5},
705 "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256",
706 NULL,
707 "TLS_DH_ANON_CAMELLIA_256_CBC_SHA256"},
708 { {0x00, 0x46},
709 "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA",
710 NULL,
711 "TLS_DH_ANON_CAMELLIA_128_CBC_SHA1"},
712 { {0x00, 0x89},
713 "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA",
714 NULL,
715 "TLS_DH_ANON_CAMELLIA_256_CBC_SHA1"},
716 { {0x00, 0x6C},
717 "TLS_DH_anon_WITH_AES_128_CBC_SHA256",
718 NULL,
719 "TLS_DH_ANON_AES_128_CBC_SHA256"},
720 { {0x00, 0x6D},
721 "TLS_DH_anon_WITH_AES_256_CBC_SHA256",
722 NULL,
723 "TLS_DH_ANON_AES_256_CBC_SHA256"},
724 { {0x00, 0xA6},
725 "TLS_DH_anon_WITH_AES_128_GCM_SHA256",
726 NULL,
727 "TLS_DH_ANON_AES_128_GCM_SHA256"},
728 { {0x00, 0xA7},
729 "TLS_DH_anon_WITH_AES_256_GCM_SHA384",
730 NULL,
731 "TLS_DH_ANON_AES_256_GCM_SHA384"},
732 { {0xC0, 0x84},
733 "TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256",
734 NULL,
735 "TLS_DH_ANON_CAMELLIA_128_GCM_SHA256"},
736 { {0xC0, 0x85},
737 "TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384",
738 NULL,
739 "TLS_DH_ANON_CAMELLIA_256_GCM_SHA384"},
740 { {0xC0, 0x15},
741 "TLS_ECDH_anon_WITH_",
742 NULL,
743 "TLS_ECDH_ANON_NULL_SHA1"},
744 { {0xC0, 0x17},
745 "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA",
746 NULL,
747 "TLS_ECDH_ANON_3DES_EDE_CBC_SHA1"},
748 { {0xC0, 0x18},
749 "TLS_ECDH_anon_WITH_AES_128_CBC_SHA",
750 NULL,
751 "TLS_ECDH_ANON_AES_128_CBC_SHA1"},
752 { {0xC0, 0x19},
753 "TLS_ECDH_anon_WITH_AES_256_CBC_SHA",
754 NULL,
755 "TLS_ECDH_ANON_AES_256_CBC_SHA1"},
756 { {0xC0, 0x16},
757 "TLS_ECDH_anon_WITH_RC4_128_SHA",
758 NULL,
759 "TLS_ECDH_ANON_ARCFOUR_128_SHA1"},
760 { {0xC0, 0x1A},
761 "TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA",
762 "SRP-3DES-EDE-CBC-SHA",
763 "TLS_SRP_SHA_3DES_EDE_CBC_SHA1"},
764 { {0xC0, 0x1D},
765 "TLS_SRP_SHA_WITH_AES_128_CBC_SHA",
766 "SRP-AES-128-CBC-SHA",
767 "TLS_SRP_SHA_AES_128_CBC_SHA1"},
768 { {0xC0, 0x20},
769 "TLS_SRP_SHA_WITH_AES_256_CBC_SHA",
770 "SRP-AES-256-CBC-SHA",
771 "TLS_SRP_SHA_AES_256_CBC_SHA1"},
772 { {0xC0, 0x1C},
773 "TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA",
774 NULL,
775 "TLS_SRP_SHA_DSS_3DES_EDE_CBC_SHA1"},
776 { {0xC0, 0x1B},
777 "TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA",
778 "SRP-RSA-3DES-EDE-CBC-SHA",
779 "TLS_SRP_SHA_RSA_3DES_EDE_CBC_SHA1"},
780 { {0xC0, 0x1F},
781 "TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA",
782 NULL,
783 "TLS_SRP_SHA_DSS_AES_128_CBC_SHA1"},
784 { {0xC0, 0x1E},
785 "TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA",
786 "SRP-RSA-AES-128-CBC-SHA",
787 "TLS_SRP_SHA_RSA_AES_128_CBC_SHA1"},
788 { {0xC0, 0x22},
789 "TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA",
790 NULL,
791 "TLS_SRP_SHA_DSS_AES_256_CBC_SHA1"},
792 { {0xC0, 0x21},
793 "TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA",
794 "SRP-RSA-AES-256-CBC-SHA",
795 "TLS_SRP_SHA_RSA_AES_256_CBC_SHA1"},
796 { {0x00, 0x00},
797 NULL,
798 NULL,
799 NULL}
800 };
801
802 /* free data assigned to the connection */
free_gnutls_data(struct st_gnutls_data * data)803 static void free_gnutls_data(struct st_gnutls_data *data)
804 {
805 if (data)
806 {
807 if (data->key)
808 gnutls_privkey_deinit(data->key);
809 gnutls_pcert_deinit(&data->cert);
810 free(data);
811 }
812 }
813
814 /* map the gnutls cipher suite (defined by key exchange algorithm, cipher
815 and mac algorithm) to the corresponding OpenSSL cipher name */
openssl_cipher_name(gnutls_kx_algorithm_t kx,gnutls_cipher_algorithm_t cipher,gnutls_mac_algorithm_t mac)816 static const char *openssl_cipher_name(gnutls_kx_algorithm_t kx,
817 gnutls_cipher_algorithm_t cipher,
818 gnutls_mac_algorithm_t mac)
819 {
820 unsigned int i=0;
821 const char *name= 0;
822 unsigned char sid[2];
823 gnutls_kx_algorithm_t lkx;
824 gnutls_cipher_algorithm_t lcipher;
825 gnutls_mac_algorithm_t lmac;
826
827 while ((name= gnutls_cipher_suite_info(i++, (unsigned char *)&sid, &lkx, &lcipher, &lmac, NULL)))
828 {
829 if (lkx == kx &&
830 lcipher == cipher &&
831 lmac == mac)
832 {
833 i=0;
834 while (tls_ciphers[i].iana_name)
835 {
836 if (!memcmp(tls_ciphers[i].sid, &sid, 2))
837 {
838 if (tls_ciphers[i].openssl_name)
839 return tls_ciphers[i].openssl_name;
840 if (tls_ciphers[i].gnutls_name)
841 return tls_ciphers[i].gnutls_name;
842 return tls_ciphers[i].iana_name;
843 }
844 i++;
845 }
846 }
847 }
848 return NULL;
849 }
850
851 /* get priority string for a given openssl cipher name */
get_priority(const char * cipher_name,char * priority,size_t len)852 static char *get_priority(const char *cipher_name, char *priority, size_t len)
853 {
854 unsigned int i= 0;
855 while (tls_ciphers[i].iana_name)
856 {
857 if (strcmp(tls_ciphers[i].iana_name, cipher_name) == 0 ||
858 (tls_ciphers[i].openssl_name &&
859 strcmp(tls_ciphers[i].openssl_name, cipher_name) == 0) ||
860 (tls_ciphers[i].gnutls_name &&
861 strcmp(tls_ciphers[i].gnutls_name, cipher_name) == 0))
862 {
863 const char *name;
864 gnutls_kx_algorithm_t kx;
865 gnutls_cipher_algorithm_t cipher;
866 gnutls_mac_algorithm_t mac;
867 gnutls_protocol_t min_version;
868 unsigned j= 0;
869
870 if (!tls_ciphers[i].gnutls_name)
871 return NULL;
872
873 while ((name= gnutls_cipher_suite_info(j++, NULL, &kx, &cipher,
874 &mac, &min_version)))
875 {
876 if (!strcmp(name, tls_ciphers[i].gnutls_name))
877 {
878 snprintf(priority, len - 1, ":+%s:+%s:+%s",
879 gnutls_cipher_get_name(cipher),
880 gnutls_mac_get_name(mac),
881 gnutls_kx_get_name(kx));
882 return priority;
883 }
884 }
885 return NULL;
886 }
887 i++;
888 }
889 return NULL;
890 }
891
892 #define MAX_SSL_ERR_LEN 100
893
ma_tls_set_error(MYSQL * mysql,void * ssl,int ssl_errno)894 static void ma_tls_set_error(MYSQL *mysql, void *ssl, int ssl_errno)
895 {
896 char ssl_error[MAX_SSL_ERR_LEN];
897 const char *ssl_error_reason;
898 MARIADB_PVIO *pvio= mysql->net.pvio;
899
900 if (!ssl_errno)
901 {
902 pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Unknown SSL error");
903 return;
904 }
905
906 /* give a more descriptive error message for alerts */
907 if (ssl_errno == GNUTLS_E_FATAL_ALERT_RECEIVED)
908 {
909 gnutls_alert_description_t alert_desc;
910 const char *alert_name;
911 alert_desc= gnutls_alert_get((gnutls_session_t)ssl);
912 alert_name= gnutls_alert_get_name(alert_desc);
913 snprintf(ssl_error, MAX_SSL_ERR_LEN, "fatal alert received: %s",
914 alert_name);
915 pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, 0,
916 ssl_error);
917 return;
918 }
919
920 if ((ssl_error_reason= gnutls_strerror(ssl_errno)))
921 {
922 pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, 0,
923 ssl_error_reason);
924 return;
925 }
926 snprintf(ssl_error, MAX_SSL_ERR_LEN, "SSL errno=%d", ssl_errno);
927 pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
928 ssl_error);
929 }
930
931
ma_tls_get_error(char * errmsg,size_t length,int ssl_errno)932 static void ma_tls_get_error(char *errmsg, size_t length, int ssl_errno)
933 {
934 const char *ssl_error_reason;
935
936 if (!ssl_errno)
937 {
938 strncpy(errmsg, "Unknown SSL error", length);
939 return;
940 }
941 if ((ssl_error_reason= gnutls_strerror(ssl_errno)))
942 {
943 strncpy(errmsg, ssl_error_reason, length);
944 return;
945 }
946 snprintf(errmsg, length, "SSL errno=%d", ssl_errno);
947 }
948
949 /*
950 Initializes SSL and allocate global
951 context SSL_context
952
953 SYNOPSIS
954 my_gnutls_start
955 mysql connection handle
956
957 RETURN VALUES
958 0 success
959 1 error
960 */
ma_tls_start(char * errmsg,size_t errmsg_len)961 int ma_tls_start(char *errmsg, size_t errmsg_len)
962 {
963 int rc= 0;
964
965 if (ma_tls_initialized)
966 return 0;
967
968 pthread_mutex_init(&LOCK_gnutls_config,NULL);
969 pthread_mutex_lock(&LOCK_gnutls_config);
970
971 if ((rc= gnutls_global_init()) != GNUTLS_E_SUCCESS)
972 {
973 ma_tls_get_error(errmsg, errmsg_len, rc);
974 goto end;
975 }
976 snprintf(tls_library_version, TLS_VERSION_LENGTH - 1, "GnuTLS %s",
977 gnutls_check_version(NULL));
978
979 ma_tls_initialized= TRUE;
980 end:
981 pthread_mutex_unlock(&LOCK_gnutls_config);
982 return rc;
983 }
984
985 /*
986 Release SSL and free resources
987 Will be automatically executed by
988 mysql_server_end() function
989
990 SYNOPSIS
991 my_gnutls_end()
992 void
993
994 RETURN VALUES
995 void
996 */
ma_tls_end()997 void ma_tls_end()
998 {
999 if (ma_tls_initialized)
1000 {
1001 pthread_mutex_lock(&LOCK_gnutls_config);
1002 if (mariadb_deinitialize_ssl)
1003 gnutls_global_deinit();
1004 ma_tls_initialized= FALSE;
1005 pthread_mutex_unlock(&LOCK_gnutls_config);
1006 pthread_mutex_destroy(&LOCK_gnutls_config);
1007 }
1008 return;
1009 }
1010
ma_gnutls_get_protocol_version(const char * tls_version_option,char * priority_string,size_t prio_len)1011 static size_t ma_gnutls_get_protocol_version(const char *tls_version_option,
1012 char *priority_string,
1013 size_t prio_len)
1014 {
1015 char tls_versions[128];
1016
1017 tls_versions[0]= 0;
1018 if (!tls_version_option || !tls_version_option[0])
1019 goto end;
1020
1021
1022 if (strstr(tls_version_option, "TLSv1.0"))
1023 strcat(tls_versions, ":+VERS-TLS1.0");
1024 if (strstr(tls_version_option, "TLSv1.1"))
1025 strcat(tls_versions, ":+VERS-TLS1.1");
1026 if (strstr(tls_version_option, "TLSv1.2"))
1027 strcat(tls_versions, ":+VERS-TLS1.2");
1028 #if GNUTLS_VERSION_NUMBER > 0x030605
1029 if (strstr(tls_version_option, "TLSv1.3"))
1030 strcat(tls_versions, ":+VERS-TLS1.3");
1031 #endif
1032 end:
1033 if (tls_versions[0])
1034 snprintf(priority_string, prio_len - 1, "-VERS-TLS-ALL%s:NORMAL", tls_versions);
1035 else
1036 strncpy(priority_string, "NORMAL:+VERS-ALL", prio_len - 1);
1037 return strlen(priority_string);
1038 }
1039
ma_gnutls_set_ciphers(gnutls_session_t ssl,const char * cipher_str,const char * tls_version)1040 static int ma_gnutls_set_ciphers(gnutls_session_t ssl,
1041 const char *cipher_str,
1042 const char *tls_version)
1043 {
1044 const char *err;
1045 char *token;
1046 #define PRIO_SIZE 1024
1047 char prio[PRIO_SIZE];
1048
1049 ma_gnutls_get_protocol_version(tls_version, prio, PRIO_SIZE);
1050
1051 if (!cipher_str)
1052 return gnutls_priority_set_direct(ssl, prio, &err);
1053
1054 token= strtok((char *)cipher_str, ":");
1055
1056 strcpy(prio, "NONE:+VERS-TLS-ALL:+SIGN-ALL:+COMP-NULL:+CURVE-ALL");
1057
1058 while (token)
1059 {
1060 char priority[1024];
1061 char *p= get_priority(token, priority, 1024);
1062 if (p)
1063 strncat(prio, p, PRIO_SIZE - strlen(prio) - 1);
1064 token = strtok(NULL, ":");
1065 }
1066 return gnutls_priority_set_direct(ssl, prio , &err);
1067 }
1068
ma_tls_set_certs(MYSQL * mysql,gnutls_certificate_credentials_t ctx)1069 static int ma_tls_set_certs(MYSQL *mysql,
1070 gnutls_certificate_credentials_t ctx)
1071 {
1072 int ssl_error= 0;
1073
1074 if (mysql->options.ssl_ca)
1075 {
1076
1077 ssl_error= gnutls_certificate_set_x509_trust_file(ctx,
1078 mysql->options.ssl_ca,
1079 GNUTLS_X509_FMT_PEM);
1080 if (ssl_error < 0)
1081 goto error;
1082 }
1083
1084 if (mysql->options.ssl_capath)
1085 {
1086 ssl_error= gnutls_certificate_set_x509_trust_dir(ctx,
1087 mysql->options.ssl_capath,
1088 GNUTLS_X509_FMT_PEM);
1089 if (ssl_error < 0)
1090 goto error;
1091 }
1092
1093 if (!mysql->options.ssl_ca && !mysql->options.ssl_capath)
1094 {
1095 ssl_error= gnutls_certificate_set_x509_system_trust(ctx);
1096 if (ssl_error < 0)
1097 goto error;
1098 }
1099
1100 gnutls_certificate_set_verify_function(ctx,
1101 my_verify_callback);
1102
1103 if (mysql->options.ssl_key || mysql->options.ssl_cert)
1104 {
1105 char *keyfile= mysql->options.ssl_key;
1106 char *certfile= mysql->options.ssl_cert;
1107
1108 if (!certfile)
1109 certfile= keyfile;
1110 else if (!keyfile)
1111 keyfile= certfile;
1112
1113 /* load cert/key into context */
1114 if ((ssl_error= gnutls_certificate_set_x509_key_file2(ctx,
1115 certfile, keyfile, GNUTLS_X509_FMT_PEM,
1116 mysql->options.extension ? mysql->options.extension->tls_pw : NULL, 0)) < 0)
1117 goto error;
1118 }
1119
1120 error:
1121 return ssl_error;
1122 }
1123
ma_tls_init(MYSQL * mysql)1124 void *ma_tls_init(MYSQL *mysql)
1125 {
1126 gnutls_session_t ssl= NULL;
1127 gnutls_certificate_credentials_t ctx;
1128 int ssl_error= 0;
1129 struct st_gnutls_data *data= NULL;
1130
1131 pthread_mutex_lock(&LOCK_gnutls_config);
1132
1133 if (gnutls_certificate_allocate_credentials(&ctx) != GNUTLS_E_SUCCESS)
1134 goto error;
1135
1136 if ((ssl_error= ma_tls_set_certs(mysql, ctx)) < 0)
1137 goto error;
1138
1139 if ((ssl_error = gnutls_init(&ssl, GNUTLS_CLIENT & GNUTLS_NONBLOCK)) < 0)
1140 goto error;
1141
1142 if (!(data= (struct st_gnutls_data *)calloc(1, sizeof(struct st_gnutls_data))))
1143 goto error;
1144
1145 data->mysql= mysql;
1146 gnutls_session_set_ptr(ssl, (void *)data);
1147 /*
1148 gnutls_certificate_set_retrieve_function2(GNUTLS_xcred, client_cert_callback);
1149 */
1150 ssl_error= ma_gnutls_set_ciphers(ssl, mysql->options.ssl_cipher, mysql->options.extension ? mysql->options.extension->tls_version : NULL);
1151 if (ssl_error < 0)
1152 goto error;
1153
1154 /* we don't load private key and cert by default - if the server requests
1155 a client certificate we will send it via callback function */
1156 if ((ssl_error= gnutls_credentials_set(ssl, GNUTLS_CRD_CERTIFICATE, ctx)) < 0)
1157 goto error;
1158
1159 pthread_mutex_unlock(&LOCK_gnutls_config);
1160 return (void *)ssl;
1161 error:
1162 free_gnutls_data(data);
1163 ma_tls_set_error(mysql, ssl, ssl_error);
1164 gnutls_certificate_free_credentials(ctx);
1165 if (ssl)
1166 gnutls_deinit(ssl);
1167 pthread_mutex_unlock(&LOCK_gnutls_config);
1168 return NULL;
1169 }
1170
1171 #ifdef GNUTLS_EXTERNAL_TRANSPORT
ma_tls_push(gnutls_transport_ptr_t ptr,const void * data,size_t len)1172 ssize_t ma_tls_push(gnutls_transport_ptr_t ptr, const void* data, size_t len)
1173 {
1174 MARIADB_PVIO *pvio= (MARIADB_PVIO *)ptr;
1175 ssize_t rc= pvio->methods->write(pvio, data, len);
1176 return rc;
1177 }
1178
ma_tls_pull(gnutls_transport_ptr_t ptr,void * data,size_t len)1179 ssize_t ma_tls_pull(gnutls_transport_ptr_t ptr, void* data, size_t len)
1180 {
1181 MARIADB_PVIO *pvio= (MARIADB_PVIO *)ptr;
1182 ssize_t rc= pvio->methods->read(pvio, data, len);
1183 return rc;
1184 }
1185
ma_tls_pull_timeout(gnutls_transport_ptr_t ptr,unsigned int ms)1186 static int ma_tls_pull_timeout(gnutls_transport_ptr_t ptr, unsigned int ms)
1187 {
1188 MARIADB_PVIO *pvio= (MARIADB_PVIO *)ptr;
1189 return pvio->methods->wait_io_or_timeout(pvio, 0, ms);
1190 }
1191 #endif
1192
ma_tls_connect(MARIADB_TLS * ctls)1193 my_bool ma_tls_connect(MARIADB_TLS *ctls)
1194 {
1195 gnutls_session_t ssl = (gnutls_session_t)ctls->ssl;
1196 my_bool blocking;
1197 MYSQL *mysql;
1198 MARIADB_PVIO *pvio;
1199 int ret;
1200 struct st_gnutls_data *data;
1201 data= (struct st_gnutls_data *)gnutls_session_get_ptr(ssl);
1202 mysql= data->mysql;
1203
1204 if (!mysql)
1205 return 1;
1206
1207 pvio= mysql->net.pvio;
1208
1209 /* Set socket to blocking if not already set */
1210 if (!(blocking= pvio->methods->is_blocking(pvio)))
1211 pvio->methods->blocking(pvio, TRUE, 0);
1212
1213
1214 #ifdef GNUTLS_EXTERNAL_TRANSPORT
1215 /* we don't use GnuTLS read/write functions */
1216 gnutls_transport_set_ptr(ssl, pvio);
1217 gnutls_transport_set_push_function(ssl, ma_tls_push);
1218 gnutls_transport_set_pull_function(ssl, ma_tls_pull);
1219 gnutls_transport_set_pull_timeout_function(ssl, ma_tls_pull_timeout);
1220 gnutls_handshake_set_timeout(ssl, pvio->timeout[PVIO_CONNECT_TIMEOUT]);
1221 #else
1222 gnutls_transport_set_int(ssl, mysql_get_socket(mysql));
1223 #endif
1224
1225 do {
1226 ret = gnutls_handshake(ssl);
1227 } while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
1228
1229 if (ret < 0)
1230 {
1231 /* If error message was not set while calling certification callback function,
1232 use default error message (which is not very descriptive */
1233 if (!mysql_errno(mysql))
1234 ma_tls_set_error(mysql, ssl, ret);
1235
1236 ma_tls_close(ctls);
1237
1238 /* restore blocking mode */
1239 if (!blocking)
1240 pvio->methods->blocking(pvio, FALSE, 0);
1241 return 1;
1242 }
1243 ctls->ssl= (void *)ssl;
1244 return 0;
1245 }
1246
ma_tls_write_async(MARIADB_PVIO * pvio,const uchar * buffer,size_t length)1247 ssize_t ma_tls_write_async(MARIADB_PVIO *pvio, const uchar *buffer, size_t length)
1248 {
1249 ssize_t res;
1250 struct mysql_async_context *b= pvio->mysql->options.extension->async_context;
1251 MARIADB_TLS *ctls= pvio->ctls;
1252
1253 for (;;)
1254 {
1255 b->events_to_wait_for= 0;
1256 res= gnutls_record_send((gnutls_session_t)ctls->ssl, (void *)buffer, length);
1257 if (res > 0)
1258 return res;
1259 if (res == GNUTLS_E_AGAIN)
1260 b->events_to_wait_for|= MYSQL_WAIT_WRITE;
1261 else
1262 return res;
1263 if (b->suspend_resume_hook)
1264 (*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data);
1265 my_context_yield(&b->async_context);
1266 if (b->suspend_resume_hook)
1267 (*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data);
1268 }
1269 }
1270
1271
ma_tls_read_async(MARIADB_PVIO * pvio,const uchar * buffer,size_t length)1272 ssize_t ma_tls_read_async(MARIADB_PVIO *pvio, const uchar *buffer, size_t length)
1273 {
1274 ssize_t res;
1275 struct mysql_async_context *b= pvio->mysql->options.extension->async_context;
1276 MARIADB_TLS *ctls= pvio->ctls;
1277
1278 for (;;)
1279 {
1280 b->events_to_wait_for= 0;
1281 res= gnutls_record_recv((gnutls_session_t)ctls->ssl, (void *)buffer, length);
1282 if (res > 0)
1283 return res;
1284 if (res == GNUTLS_E_AGAIN)
1285 b->events_to_wait_for|= MYSQL_WAIT_READ;
1286 else
1287 return res;
1288 if (b->suspend_resume_hook)
1289 (*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data);
1290 my_context_yield(&b->async_context);
1291 if (b->suspend_resume_hook)
1292 (*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data);
1293 }
1294 }
1295
ma_tls_read(MARIADB_TLS * ctls,const uchar * buffer,size_t length)1296 ssize_t ma_tls_read(MARIADB_TLS *ctls, const uchar* buffer, size_t length)
1297 {
1298 ssize_t rc;
1299 MARIADB_PVIO *pvio= ctls->pvio;
1300
1301 while ((rc= gnutls_record_recv((gnutls_session_t)ctls->ssl, (void *)buffer, length)) <= 0)
1302 {
1303 if (rc != GNUTLS_E_AGAIN && rc != GNUTLS_E_INTERRUPTED)
1304 return rc;
1305 if (pvio->methods->wait_io_or_timeout(pvio, TRUE, pvio->mysql->options.read_timeout) < 1)
1306 return rc;
1307 }
1308 return rc;
1309 }
1310
ma_tls_write(MARIADB_TLS * ctls,const uchar * buffer,size_t length)1311 ssize_t ma_tls_write(MARIADB_TLS *ctls, const uchar* buffer, size_t length)
1312 {
1313 ssize_t rc;
1314 MARIADB_PVIO *pvio= ctls->pvio;
1315
1316 while ((rc= gnutls_record_send((gnutls_session_t)ctls->ssl, (void *)buffer, length)) <= 0)
1317 {
1318 if (rc != GNUTLS_E_AGAIN && rc != GNUTLS_E_INTERRUPTED)
1319 return rc;
1320 if (pvio->methods->wait_io_or_timeout(pvio, TRUE, pvio->mysql->options.write_timeout) < 1)
1321 return rc;
1322 }
1323 return rc;
1324 }
1325
ma_tls_close(MARIADB_TLS * ctls)1326 my_bool ma_tls_close(MARIADB_TLS *ctls)
1327 {
1328 if (ctls->ssl)
1329 {
1330 gnutls_certificate_credentials_t ctx;
1331 struct st_gnutls_data *data=
1332 (struct st_gnutls_data *)gnutls_session_get_ptr(ctls->ssl);
1333 /* this would be the correct way, however can't detect afterwards
1334 if the socket is closed or not, so we don't send encrypted
1335 finish alert.
1336 rc= gnutls_bye((gnutls_session_t )ctls->ssl, GNUTLS_SHUT_WR);
1337 */
1338 free_gnutls_data(data);
1339 gnutls_credentials_get(ctls->ssl, GNUTLS_CRD_CERTIFICATE, (void **)&ctx);
1340 gnutls_certificate_free_keys(ctx);
1341 gnutls_certificate_free_cas(ctx);
1342 gnutls_certificate_free_crls(ctx);
1343 gnutls_certificate_free_ca_names(ctx);
1344 gnutls_certificate_free_credentials(ctx);
1345 gnutls_deinit((gnutls_session_t )ctls->ssl);
1346 ctls->ssl= NULL;
1347 }
1348 return 0;
1349 }
1350
ma_tls_verify_server_cert(MARIADB_TLS * ctls)1351 int ma_tls_verify_server_cert(MARIADB_TLS *ctls __attribute__((unused)))
1352 {
1353 /* server verification is already handled before during handshake */
1354 return 0;
1355 }
1356
ma_tls_get_cipher(MARIADB_TLS * ctls)1357 const char *ma_tls_get_cipher(MARIADB_TLS *ctls)
1358 {
1359 gnutls_kx_algorithm_t kx;
1360 gnutls_cipher_algorithm_t cipher;
1361 gnutls_mac_algorithm_t mac;
1362
1363 if (!ctls || !ctls->ssl)
1364 return NULL;
1365
1366 mac= gnutls_mac_get((gnutls_session_t)ctls->ssl);
1367 cipher= gnutls_cipher_get((gnutls_session_t)ctls->ssl);
1368 kx= gnutls_kx_get((gnutls_session_t)ctls->ssl);
1369 return openssl_cipher_name(kx, cipher, mac);
1370 }
1371
my_verify_callback(gnutls_session_t ssl)1372 static int my_verify_callback(gnutls_session_t ssl)
1373 {
1374 unsigned int status= 0;
1375 struct st_gnutls_data *data= (struct st_gnutls_data *)gnutls_session_get_ptr(ssl);
1376 MYSQL *mysql;
1377
1378 mysql= data->mysql;
1379
1380 CLEAR_CLIENT_ERROR(mysql);
1381
1382 if ((mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT))
1383 {
1384 const char *hostname= mysql->host;
1385
1386 if (gnutls_certificate_verify_peers3 (ssl, hostname, &status) < 0)
1387 return GNUTLS_E_CERTIFICATE_ERROR;
1388 } else {
1389 if (gnutls_certificate_verify_peers2 (ssl, &status) < 0)
1390 return GNUTLS_E_CERTIFICATE_ERROR;
1391 }
1392 if (status & GNUTLS_CERT_INVALID)
1393 {
1394 gnutls_datum_t out;
1395 int type;
1396 /* accept self signed certificates if we don't have to verify server cert */
1397 if (!(mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) &&
1398 (status & GNUTLS_CERT_SIGNER_NOT_FOUND))
1399 return 0;
1400
1401 /* gnutls default error message "certificate validation failed" isn't very
1402 descriptive, so we provide more information about the error here */
1403 type= gnutls_certificate_type_get(ssl);
1404 gnutls_certificate_verification_status_print(status, type, &out, 0);
1405 my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
1406 ER(CR_SSL_CONNECTION_ERROR), out.data);
1407 gnutls_free(out.data);
1408
1409 return GNUTLS_E_CERTIFICATE_ERROR;
1410 }
1411
1412
1413 return 0;
1414 }
1415
ma_tls_get_finger_print(MARIADB_TLS * ctls,char * fp,unsigned int len)1416 unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, char *fp, unsigned int len)
1417 {
1418 MYSQL *mysql;
1419 size_t fp_len= len;
1420 const gnutls_datum_t *cert_list;
1421 unsigned int cert_list_size;
1422 struct st_gnutls_data *data;
1423
1424 if (!ctls || !ctls->ssl)
1425 return 0;
1426
1427 data= (struct st_gnutls_data *)gnutls_session_get_ptr(ctls->ssl);
1428 mysql= (MYSQL *)data->mysql;
1429
1430 cert_list = gnutls_certificate_get_peers (ctls->ssl, &cert_list_size);
1431 if (cert_list == NULL)
1432 {
1433 my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
1434 ER(CR_SSL_CONNECTION_ERROR),
1435 "Unable to get server certificate");
1436 return 0;
1437 }
1438
1439 if (gnutls_fingerprint(GNUTLS_DIG_SHA1, &cert_list[0], fp, &fp_len) == 0)
1440 return fp_len;
1441 else
1442 {
1443 my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
1444 ER(CR_SSL_CONNECTION_ERROR),
1445 "Finger print buffer too small");
1446 return 0;
1447 }
1448 }
1449
ma_tls_get_protocol_version(MARIADB_TLS * ctls)1450 int ma_tls_get_protocol_version(MARIADB_TLS *ctls)
1451 {
1452 if (!ctls || !ctls->ssl)
1453 return 1;
1454
1455 return gnutls_protocol_get_version(ctls->ssl) - 1;
1456 }
1457 #endif /* HAVE_GNUTLS */
1458