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