1 /***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
9 *
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at https://curl.haxx.se/docs/copyright.html.
13 *
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ***************************************************************************/
22
23 /*
24 * Source file for all GnuTLS-specific code for the TLS/SSL layer. No code
25 * but vtls.c should ever call or use these functions.
26 *
27 * Note: don't use the GnuTLS' *_t variable type names in this source code,
28 * since they were not present in 1.0.X.
29 */
30
31 #include "curl_setup.h"
32
33 #ifdef USE_GNUTLS
34
35 #include <gnutls/abstract.h>
36 #include <gnutls/gnutls.h>
37 #include <gnutls/x509.h>
38
39 #ifdef USE_GNUTLS_NETTLE
40 #include <gnutls/crypto.h>
41 #include <nettle/md5.h>
42 #include <nettle/sha2.h>
43 #else
44 #include <gcrypt.h>
45 #endif
46
47 #include "urldata.h"
48 #include "sendf.h"
49 #include "inet_pton.h"
50 #include "gtls.h"
51 #include "vtls.h"
52 #include "parsedate.h"
53 #include "connect.h" /* for the connect timeout */
54 #include "select.h"
55 #include "strcase.h"
56 #include "warnless.h"
57 #include "x509asn1.h"
58 #include "curl_printf.h"
59 #include "curl_memory.h"
60 /* The last #include file should be: */
61 #include "memdebug.h"
62
63 /* Enable GnuTLS debugging by defining GTLSDEBUG */
64 /*#define GTLSDEBUG */
65
66 #ifdef GTLSDEBUG
tls_log_func(int level,const char * str)67 static void tls_log_func(int level, const char *str)
68 {
69 fprintf(stderr, "|<%d>| %s", level, str);
70 }
71 #endif
72 static bool gtls_inited = FALSE;
73
74 #if defined(GNUTLS_VERSION_NUMBER)
75 # if (GNUTLS_VERSION_NUMBER >= 0x020c00)
76 # undef gnutls_transport_set_lowat
77 # define gnutls_transport_set_lowat(A,B) Curl_nop_stmt
78 # define USE_GNUTLS_PRIORITY_SET_DIRECT 1
79 # endif
80 # if (GNUTLS_VERSION_NUMBER >= 0x020c03)
81 # define GNUTLS_MAPS_WINSOCK_ERRORS 1
82 # endif
83
84 # if HAVE_GNUTLS_ALPN_SET_PROTOCOLS
85 # define HAS_ALPN
86 # endif
87
88 # if HAVE_GNUTLS_OCSP_REQ_INIT
89 # define HAS_OCSP
90 # endif
91
92 # if (GNUTLS_VERSION_NUMBER >= 0x030306)
93 # define HAS_CAPATH
94 # endif
95 #endif
96
97 #if (GNUTLS_VERSION_NUMBER >= 0x030603)
98 #define HAS_TLS13
99 #endif
100
101 #ifdef HAS_OCSP
102 # include <gnutls/ocsp.h>
103 #endif
104
105 struct ssl_backend_data {
106 gnutls_session_t session;
107 gnutls_certificate_credentials_t cred;
108 #ifdef USE_TLS_SRP
109 gnutls_srp_client_credentials_t srp_client_cred;
110 #endif
111 };
112
113 #define BACKEND connssl->backend
114
115 /*
116 * Custom push and pull callback functions used by GNU TLS to read and write
117 * to the socket. These functions are simple wrappers to send() and recv()
118 * (although here using the sread/swrite macros as defined by
119 * curl_setup_once.h).
120 * We use custom functions rather than the GNU TLS defaults because it allows
121 * us to get specific about the fourth "flags" argument, and to use arbitrary
122 * private data with gnutls_transport_set_ptr if we wish.
123 *
124 * When these custom push and pull callbacks fail, GNU TLS checks its own
125 * session-specific error variable, and when not set also its own global
126 * errno variable, in order to take appropriate action. GNU TLS does not
127 * require that the transport is actually a socket. This implies that for
128 * Windows builds these callbacks should ideally set the session-specific
129 * error variable using function gnutls_transport_set_errno or as a last
130 * resort global errno variable using gnutls_transport_set_global_errno,
131 * with a transport agnostic error value. This implies that some winsock
132 * error translation must take place in these callbacks.
133 *
134 * Paragraph above applies to GNU TLS versions older than 2.12.3, since
135 * this version GNU TLS does its own internal winsock error translation
136 * using system_errno() function.
137 */
138
139 #if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
140 # define gtls_EINTR 4
141 # define gtls_EIO 5
142 # define gtls_EAGAIN 11
gtls_mapped_sockerrno(void)143 static int gtls_mapped_sockerrno(void)
144 {
145 switch(SOCKERRNO) {
146 case WSAEWOULDBLOCK:
147 return gtls_EAGAIN;
148 case WSAEINTR:
149 return gtls_EINTR;
150 default:
151 break;
152 }
153 return gtls_EIO;
154 }
155 #endif
156
Curl_gtls_push(void * s,const void * buf,size_t len)157 static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len)
158 {
159 curl_socket_t sock = *(curl_socket_t *)s;
160 ssize_t ret = swrite(sock, buf, len);
161 #if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
162 if(ret < 0)
163 gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
164 #endif
165 return ret;
166 }
167
Curl_gtls_pull(void * s,void * buf,size_t len)168 static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len)
169 {
170 curl_socket_t sock = *(curl_socket_t *)s;
171 ssize_t ret = sread(sock, buf, len);
172 #if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
173 if(ret < 0)
174 gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
175 #endif
176 return ret;
177 }
178
Curl_gtls_push_ssl(void * s,const void * buf,size_t len)179 static ssize_t Curl_gtls_push_ssl(void *s, const void *buf, size_t len)
180 {
181 return gnutls_record_send((gnutls_session_t) s, buf, len);
182 }
183
Curl_gtls_pull_ssl(void * s,void * buf,size_t len)184 static ssize_t Curl_gtls_pull_ssl(void *s, void *buf, size_t len)
185 {
186 return gnutls_record_recv((gnutls_session_t) s, buf, len);
187 }
188
189 /* Curl_gtls_init()
190 *
191 * Global GnuTLS init, called from Curl_ssl_init(). This calls functions that
192 * are not thread-safe and thus this function itself is not thread-safe and
193 * must only be called from within curl_global_init() to keep the thread
194 * situation under control!
195 */
Curl_gtls_init(void)196 static int Curl_gtls_init(void)
197 {
198 int ret = 1;
199 if(!gtls_inited) {
200 ret = gnutls_global_init()?0:1;
201 #ifdef GTLSDEBUG
202 gnutls_global_set_log_function(tls_log_func);
203 gnutls_global_set_log_level(2);
204 #endif
205 gtls_inited = TRUE;
206 }
207 return ret;
208 }
209
Curl_gtls_cleanup(void)210 static void Curl_gtls_cleanup(void)
211 {
212 if(gtls_inited) {
213 gnutls_global_deinit();
214 gtls_inited = FALSE;
215 }
216 }
217
218 #ifndef CURL_DISABLE_VERBOSE_STRINGS
showtime(struct Curl_easy * data,const char * text,time_t stamp)219 static void showtime(struct Curl_easy *data,
220 const char *text,
221 time_t stamp)
222 {
223 struct tm buffer;
224 const struct tm *tm = &buffer;
225 char str[96];
226 CURLcode result = Curl_gmtime(stamp, &buffer);
227 if(result)
228 return;
229
230 msnprintf(str,
231 sizeof(str),
232 "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT",
233 text,
234 Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
235 tm->tm_mday,
236 Curl_month[tm->tm_mon],
237 tm->tm_year + 1900,
238 tm->tm_hour,
239 tm->tm_min,
240 tm->tm_sec);
241 infof(data, "%s\n", str);
242 }
243 #endif
244
load_file(const char * file)245 static gnutls_datum_t load_file(const char *file)
246 {
247 FILE *f;
248 gnutls_datum_t loaded_file = { NULL, 0 };
249 long filelen;
250 void *ptr;
251
252 f = fopen(file, "rb");
253 if(!f)
254 return loaded_file;
255 if(fseek(f, 0, SEEK_END) != 0
256 || (filelen = ftell(f)) < 0
257 || fseek(f, 0, SEEK_SET) != 0
258 || !(ptr = malloc((size_t)filelen)))
259 goto out;
260 if(fread(ptr, 1, (size_t)filelen, f) < (size_t)filelen) {
261 free(ptr);
262 goto out;
263 }
264
265 loaded_file.data = ptr;
266 loaded_file.size = (unsigned int)filelen;
267 out:
268 fclose(f);
269 return loaded_file;
270 }
271
unload_file(gnutls_datum_t data)272 static void unload_file(gnutls_datum_t data)
273 {
274 free(data.data);
275 }
276
277
278 /* this function does a SSL/TLS (re-)handshake */
handshake(struct connectdata * conn,int sockindex,bool duringconnect,bool nonblocking)279 static CURLcode handshake(struct connectdata *conn,
280 int sockindex,
281 bool duringconnect,
282 bool nonblocking)
283 {
284 struct Curl_easy *data = conn->data;
285 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
286 gnutls_session_t session = BACKEND->session;
287 curl_socket_t sockfd = conn->sock[sockindex];
288 time_t timeout_ms;
289 int rc;
290 int what;
291
292 for(;;) {
293 /* check allowed time left */
294 timeout_ms = Curl_timeleft(data, NULL, duringconnect);
295
296 if(timeout_ms < 0) {
297 /* no need to continue if time already is up */
298 failf(data, "SSL connection timeout");
299 return CURLE_OPERATION_TIMEDOUT;
300 }
301
302 /* if ssl is expecting something, check if it's available. */
303 if(connssl->connecting_state == ssl_connect_2_reading
304 || connssl->connecting_state == ssl_connect_2_writing) {
305
306 curl_socket_t writefd = ssl_connect_2_writing ==
307 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
308 curl_socket_t readfd = ssl_connect_2_reading ==
309 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
310
311 what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
312 nonblocking?0:
313 timeout_ms?timeout_ms:1000);
314 if(what < 0) {
315 /* fatal error */
316 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
317 return CURLE_SSL_CONNECT_ERROR;
318 }
319 else if(0 == what) {
320 if(nonblocking)
321 return CURLE_OK;
322 else if(timeout_ms) {
323 /* timeout */
324 failf(data, "SSL connection timeout at %ld", (long)timeout_ms);
325 return CURLE_OPERATION_TIMEDOUT;
326 }
327 }
328 /* socket is readable or writable */
329 }
330
331 rc = gnutls_handshake(session);
332
333 if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) {
334 connssl->connecting_state =
335 gnutls_record_get_direction(session)?
336 ssl_connect_2_writing:ssl_connect_2_reading;
337 continue;
338 }
339 else if((rc < 0) && !gnutls_error_is_fatal(rc)) {
340 const char *strerr = NULL;
341
342 if(rc == GNUTLS_E_WARNING_ALERT_RECEIVED) {
343 int alert = gnutls_alert_get(session);
344 strerr = gnutls_alert_get_name(alert);
345 }
346
347 if(strerr == NULL)
348 strerr = gnutls_strerror(rc);
349
350 infof(data, "gnutls_handshake() warning: %s\n", strerr);
351 continue;
352 }
353 else if(rc < 0) {
354 const char *strerr = NULL;
355
356 if(rc == GNUTLS_E_FATAL_ALERT_RECEIVED) {
357 int alert = gnutls_alert_get(session);
358 strerr = gnutls_alert_get_name(alert);
359 }
360
361 if(strerr == NULL)
362 strerr = gnutls_strerror(rc);
363
364 failf(data, "gnutls_handshake() failed: %s", strerr);
365 return CURLE_SSL_CONNECT_ERROR;
366 }
367
368 /* Reset our connect state machine */
369 connssl->connecting_state = ssl_connect_1;
370 return CURLE_OK;
371 }
372 }
373
do_file_type(const char * type)374 static gnutls_x509_crt_fmt_t do_file_type(const char *type)
375 {
376 if(!type || !type[0])
377 return GNUTLS_X509_FMT_PEM;
378 if(strcasecompare(type, "PEM"))
379 return GNUTLS_X509_FMT_PEM;
380 if(strcasecompare(type, "DER"))
381 return GNUTLS_X509_FMT_DER;
382 return -1;
383 }
384
385 #ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
386 static CURLcode
set_ssl_version_min_max(int * list,size_t list_size,struct connectdata * conn)387 set_ssl_version_min_max(int *list, size_t list_size, struct connectdata *conn)
388 {
389 struct Curl_easy *data = conn->data;
390 long ssl_version = SSL_CONN_CONFIG(version);
391 long ssl_version_max = SSL_CONN_CONFIG(version_max);
392 long i = ssl_version;
393 long protocol_priority_idx = 0;
394
395 switch(ssl_version_max) {
396 case CURL_SSLVERSION_MAX_NONE:
397 case CURL_SSLVERSION_MAX_DEFAULT:
398 #ifdef HAS_TLS13
399 ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_3;
400 #endif
401 ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
402 break;
403 }
404
405 for(; i <= (ssl_version_max >> 16) &&
406 protocol_priority_idx < list_size; ++i) {
407 switch(i) {
408 case CURL_SSLVERSION_TLSv1_0:
409 protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_0;
410 break;
411 case CURL_SSLVERSION_TLSv1_1:
412 protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_1;
413 break;
414 case CURL_SSLVERSION_TLSv1_2:
415 protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_2;
416 break;
417 case CURL_SSLVERSION_TLSv1_3:
418 #ifdef HAS_TLS13
419 protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_3;
420 break;
421 #else
422 failf(data, "GnuTLS: TLS 1.3 is not yet supported");
423 return CURLE_SSL_CONNECT_ERROR;
424 #endif
425 }
426 }
427 return CURLE_OK;
428 }
429 #else
430 #define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509"
431 /* If GnuTLS was compiled without support for SRP it will error out if SRP is
432 requested in the priority string, so treat it specially
433 */
434 #define GNUTLS_SRP "+SRP"
435
436 static CURLcode
set_ssl_version_min_max(const char ** prioritylist,struct connectdata * conn)437 set_ssl_version_min_max(const char **prioritylist, struct connectdata *conn)
438 {
439 struct Curl_easy *data = conn->data;
440 long ssl_version = SSL_CONN_CONFIG(version);
441 long ssl_version_max = SSL_CONN_CONFIG(version_max);
442
443 if(ssl_version_max == CURL_SSLVERSION_MAX_NONE) {
444 ssl_version_max = CURL_SSLVERSION_MAX_DEFAULT;
445 }
446 switch(ssl_version | ssl_version_max) {
447 case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_0:
448 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
449 "+VERS-TLS1.0:" GNUTLS_SRP;
450 return CURLE_OK;
451 case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_1:
452 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
453 "+VERS-TLS1.0:+VERS-TLS1.1:" GNUTLS_SRP;
454 return CURLE_OK;
455 case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_2:
456 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
457 "+VERS-TLS1.0:+VERS-TLS1.1:+VERS-TLS1.2:" GNUTLS_SRP;
458 return CURLE_OK;
459 case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_1:
460 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
461 "+VERS-TLS1.1:" GNUTLS_SRP;
462 return CURLE_OK;
463 case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_2:
464 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
465 "+VERS-TLS1.1:+VERS-TLS1.2:" GNUTLS_SRP;
466 return CURLE_OK;
467 case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_2:
468 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
469 "+VERS-TLS1.2:" GNUTLS_SRP;
470 return CURLE_OK;
471 case CURL_SSLVERSION_TLSv1_3 | CURL_SSLVERSION_MAX_TLSv1_3:
472 #ifdef HAS_TLS13
473 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
474 "+VERS-TLS1.3:" GNUTLS_SRP;
475 return CURLE_OK;
476 #else
477 failf(data, "GnuTLS: TLS 1.3 is not yet supported");
478 return CURLE_SSL_CONNECT_ERROR;
479 #endif
480 case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_DEFAULT:
481 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
482 "+VERS-TLS1.0:+VERS-TLS1.1:+VERS-TLS1.2:"
483 #ifdef HAS_TLS13
484 "+VERS-TLS1.3:"
485 #endif
486 GNUTLS_SRP;
487 return CURLE_OK;
488 case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_DEFAULT:
489 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
490 "+VERS-TLS1.1:+VERS-TLS1.2:"
491 #ifdef HAS_TLS13
492 "+VERS-TLS1.3:"
493 #endif
494 GNUTLS_SRP;
495 return CURLE_OK;
496 case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_DEFAULT:
497 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
498 "+VERS-TLS1.2:"
499 #ifdef HAS_TLS13
500 "+VERS-TLS1.3:"
501 #endif
502 GNUTLS_SRP;
503 return CURLE_OK;
504 case CURL_SSLVERSION_TLSv1_3 | CURL_SSLVERSION_MAX_DEFAULT:
505 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
506 "+VERS-TLS1.2:"
507 #ifdef HAS_TLS13
508 "+VERS-TLS1.3:"
509 #endif
510 GNUTLS_SRP;
511 return CURLE_OK;
512 }
513
514 failf(data, "GnuTLS: cannot set ssl protocol");
515 return CURLE_SSL_CONNECT_ERROR;
516 }
517 #endif
518
519 static CURLcode
gtls_connect_step1(struct connectdata * conn,int sockindex)520 gtls_connect_step1(struct connectdata *conn,
521 int sockindex)
522 {
523 struct Curl_easy *data = conn->data;
524 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
525 unsigned int init_flags;
526 gnutls_session_t session;
527 int rc;
528 bool sni = TRUE; /* default is SNI enabled */
529 void *transport_ptr = NULL;
530 gnutls_push_func gnutls_transport_push = NULL;
531 gnutls_pull_func gnutls_transport_pull = NULL;
532 #ifdef ENABLE_IPV6
533 struct in6_addr addr;
534 #else
535 struct in_addr addr;
536 #endif
537 #ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
538 static const int cipher_priority[] = {
539 /* These two ciphers were added to GnuTLS as late as ver. 3.0.1,
540 but this code path is only ever used for ver. < 2.12.0.
541 GNUTLS_CIPHER_AES_128_GCM,
542 GNUTLS_CIPHER_AES_256_GCM,
543 */
544 GNUTLS_CIPHER_AES_128_CBC,
545 GNUTLS_CIPHER_AES_256_CBC,
546 GNUTLS_CIPHER_CAMELLIA_128_CBC,
547 GNUTLS_CIPHER_CAMELLIA_256_CBC,
548 GNUTLS_CIPHER_3DES_CBC,
549 };
550 static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
551 int protocol_priority[] = { 0, 0, 0, 0 };
552 #else
553 const char *prioritylist;
554 const char *err = NULL;
555 #endif
556
557 const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
558 conn->host.name;
559
560 if(connssl->state == ssl_connection_complete)
561 /* to make us tolerant against being called more than once for the
562 same connection */
563 return CURLE_OK;
564
565 if(!gtls_inited)
566 Curl_gtls_init();
567
568 if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
569 failf(data, "GnuTLS does not support SSLv2");
570 return CURLE_SSL_CONNECT_ERROR;
571 }
572 else if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv3)
573 sni = FALSE; /* SSLv3 has no SNI */
574
575 /* allocate a cred struct */
576 rc = gnutls_certificate_allocate_credentials(&BACKEND->cred);
577 if(rc != GNUTLS_E_SUCCESS) {
578 failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc));
579 return CURLE_SSL_CONNECT_ERROR;
580 }
581
582 #ifdef USE_TLS_SRP
583 if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
584 infof(data, "Using TLS-SRP username: %s\n", SSL_SET_OPTION(username));
585
586 rc = gnutls_srp_allocate_client_credentials(
587 &BACKEND->srp_client_cred);
588 if(rc != GNUTLS_E_SUCCESS) {
589 failf(data, "gnutls_srp_allocate_client_cred() failed: %s",
590 gnutls_strerror(rc));
591 return CURLE_OUT_OF_MEMORY;
592 }
593
594 rc = gnutls_srp_set_client_credentials(BACKEND->srp_client_cred,
595 SSL_SET_OPTION(username),
596 SSL_SET_OPTION(password));
597 if(rc != GNUTLS_E_SUCCESS) {
598 failf(data, "gnutls_srp_set_client_cred() failed: %s",
599 gnutls_strerror(rc));
600 return CURLE_BAD_FUNCTION_ARGUMENT;
601 }
602 }
603 #endif
604
605 if(SSL_CONN_CONFIG(CAfile)) {
606 /* set the trusted CA cert bundle file */
607 gnutls_certificate_set_verify_flags(BACKEND->cred,
608 GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
609
610 rc = gnutls_certificate_set_x509_trust_file(BACKEND->cred,
611 SSL_CONN_CONFIG(CAfile),
612 GNUTLS_X509_FMT_PEM);
613 if(rc < 0) {
614 infof(data, "error reading ca cert file %s (%s)\n",
615 SSL_CONN_CONFIG(CAfile), gnutls_strerror(rc));
616 if(SSL_CONN_CONFIG(verifypeer))
617 return CURLE_SSL_CACERT_BADFILE;
618 }
619 else
620 infof(data, "found %d certificates in %s\n", rc,
621 SSL_CONN_CONFIG(CAfile));
622 }
623
624 #ifdef HAS_CAPATH
625 if(SSL_CONN_CONFIG(CApath)) {
626 /* set the trusted CA cert directory */
627 rc = gnutls_certificate_set_x509_trust_dir(BACKEND->cred,
628 SSL_CONN_CONFIG(CApath),
629 GNUTLS_X509_FMT_PEM);
630 if(rc < 0) {
631 infof(data, "error reading ca cert file %s (%s)\n",
632 SSL_CONN_CONFIG(CApath), gnutls_strerror(rc));
633 if(SSL_CONN_CONFIG(verifypeer))
634 return CURLE_SSL_CACERT_BADFILE;
635 }
636 else
637 infof(data, "found %d certificates in %s\n",
638 rc, SSL_CONN_CONFIG(CApath));
639 }
640 #endif
641
642 #ifdef CURL_CA_FALLBACK
643 /* use system ca certificate store as fallback */
644 if(SSL_CONN_CONFIG(verifypeer) &&
645 !(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(CApath))) {
646 gnutls_certificate_set_x509_system_trust(BACKEND->cred);
647 }
648 #endif
649
650 if(SSL_SET_OPTION(CRLfile)) {
651 /* set the CRL list file */
652 rc = gnutls_certificate_set_x509_crl_file(BACKEND->cred,
653 SSL_SET_OPTION(CRLfile),
654 GNUTLS_X509_FMT_PEM);
655 if(rc < 0) {
656 failf(data, "error reading crl file %s (%s)",
657 SSL_SET_OPTION(CRLfile), gnutls_strerror(rc));
658 return CURLE_SSL_CRL_BADFILE;
659 }
660 else
661 infof(data, "found %d CRL in %s\n",
662 rc, SSL_SET_OPTION(CRLfile));
663 }
664
665 /* Initialize TLS session as a client */
666 init_flags = GNUTLS_CLIENT;
667
668 #if defined(GNUTLS_NO_TICKETS)
669 /* Disable TLS session tickets */
670 init_flags |= GNUTLS_NO_TICKETS;
671 #endif
672
673 rc = gnutls_init(&BACKEND->session, init_flags);
674 if(rc != GNUTLS_E_SUCCESS) {
675 failf(data, "gnutls_init() failed: %d", rc);
676 return CURLE_SSL_CONNECT_ERROR;
677 }
678
679 /* convenient assign */
680 session = BACKEND->session;
681
682 if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
683 #ifdef ENABLE_IPV6
684 (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
685 #endif
686 sni &&
687 (gnutls_server_name_set(session, GNUTLS_NAME_DNS, hostname,
688 strlen(hostname)) < 0))
689 infof(data, "WARNING: failed to configure server name indication (SNI) "
690 "TLS extension\n");
691
692 /* Use default priorities */
693 rc = gnutls_set_default_priority(session);
694 if(rc != GNUTLS_E_SUCCESS)
695 return CURLE_SSL_CONNECT_ERROR;
696
697 #ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
698 rc = gnutls_cipher_set_priority(session, cipher_priority);
699 if(rc != GNUTLS_E_SUCCESS)
700 return CURLE_SSL_CONNECT_ERROR;
701
702 /* Sets the priority on the certificate types supported by gnutls. Priority
703 is higher for types specified before others. After specifying the types
704 you want, you must append a 0. */
705 rc = gnutls_certificate_type_set_priority(session, cert_type_priority);
706 if(rc != GNUTLS_E_SUCCESS)
707 return CURLE_SSL_CONNECT_ERROR;
708
709 if(SSL_CONN_CONFIG(cipher_list) != NULL) {
710 failf(data, "can't pass a custom cipher list to older GnuTLS"
711 " versions");
712 return CURLE_SSL_CONNECT_ERROR;
713 }
714
715 switch(SSL_CONN_CONFIG(version)) {
716 case CURL_SSLVERSION_SSLv3:
717 protocol_priority[0] = GNUTLS_SSL3;
718 break;
719 case CURL_SSLVERSION_DEFAULT:
720 case CURL_SSLVERSION_TLSv1:
721 protocol_priority[0] = GNUTLS_TLS1_0;
722 protocol_priority[1] = GNUTLS_TLS1_1;
723 protocol_priority[2] = GNUTLS_TLS1_2;
724 #ifdef HAS_TLS13
725 protocol_priority[3] = GNUTLS_TLS1_3;
726 #endif
727 break;
728 case CURL_SSLVERSION_TLSv1_0:
729 case CURL_SSLVERSION_TLSv1_1:
730 case CURL_SSLVERSION_TLSv1_2:
731 case CURL_SSLVERSION_TLSv1_3:
732 {
733 CURLcode result = set_ssl_version_min_max(protocol_priority,
734 sizeof(protocol_priority)/sizeof(protocol_priority[0]), conn);
735 if(result != CURLE_OK)
736 return result;
737 break;
738 }
739 case CURL_SSLVERSION_SSLv2:
740 failf(data, "GnuTLS does not support SSLv2");
741 return CURLE_SSL_CONNECT_ERROR;
742 default:
743 failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
744 return CURLE_SSL_CONNECT_ERROR;
745 }
746 rc = gnutls_protocol_set_priority(session, protocol_priority);
747 if(rc != GNUTLS_E_SUCCESS) {
748 failf(data, "Did you pass a valid GnuTLS cipher list?");
749 return CURLE_SSL_CONNECT_ERROR;
750 }
751
752 #else
753 /* Ensure +SRP comes at the *end* of all relevant strings so that it can be
754 * removed if a run-time error indicates that SRP is not supported by this
755 * GnuTLS version */
756 switch(SSL_CONN_CONFIG(version)) {
757 case CURL_SSLVERSION_SSLv3:
758 prioritylist = GNUTLS_CIPHERS ":-VERS-TLS-ALL:+VERS-SSL3.0";
759 break;
760 case CURL_SSLVERSION_DEFAULT:
761 case CURL_SSLVERSION_TLSv1:
762 prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:"
763 #ifdef HAS_TLS13
764 "+VERS-TLS1.3:"
765 #endif
766 GNUTLS_SRP;
767 break;
768 case CURL_SSLVERSION_TLSv1_0:
769 case CURL_SSLVERSION_TLSv1_1:
770 case CURL_SSLVERSION_TLSv1_2:
771 case CURL_SSLVERSION_TLSv1_3:
772 {
773 CURLcode result = set_ssl_version_min_max(&prioritylist, conn);
774 if(result != CURLE_OK)
775 return result;
776 break;
777 }
778 case CURL_SSLVERSION_SSLv2:
779 failf(data, "GnuTLS does not support SSLv2");
780 return CURLE_SSL_CONNECT_ERROR;
781 default:
782 failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
783 return CURLE_SSL_CONNECT_ERROR;
784 }
785 rc = gnutls_priority_set_direct(session, prioritylist, &err);
786 if((rc == GNUTLS_E_INVALID_REQUEST) && err) {
787 if(!strcmp(err, GNUTLS_SRP)) {
788 /* This GnuTLS was probably compiled without support for SRP.
789 * Note that fact and try again without it. */
790 int validprioritylen = curlx_uztosi(err - prioritylist);
791 char *prioritycopy = strdup(prioritylist);
792 if(!prioritycopy)
793 return CURLE_OUT_OF_MEMORY;
794
795 infof(data, "This GnuTLS does not support SRP\n");
796 if(validprioritylen)
797 /* Remove the :+SRP */
798 prioritycopy[validprioritylen - 1] = 0;
799 rc = gnutls_priority_set_direct(session, prioritycopy, &err);
800 free(prioritycopy);
801 }
802 }
803 if(rc != GNUTLS_E_SUCCESS) {
804 failf(data, "Error %d setting GnuTLS cipher list starting with %s",
805 rc, err);
806 return CURLE_SSL_CONNECT_ERROR;
807 }
808 #endif
809
810 #ifdef HAS_ALPN
811 if(conn->bits.tls_enable_alpn) {
812 int cur = 0;
813 gnutls_datum_t protocols[2];
814
815 #ifdef USE_NGHTTP2
816 if(data->set.httpversion >= CURL_HTTP_VERSION_2 &&
817 (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) {
818 protocols[cur].data = (unsigned char *)NGHTTP2_PROTO_VERSION_ID;
819 protocols[cur].size = NGHTTP2_PROTO_VERSION_ID_LEN;
820 cur++;
821 infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
822 }
823 #endif
824
825 protocols[cur].data = (unsigned char *)ALPN_HTTP_1_1;
826 protocols[cur].size = ALPN_HTTP_1_1_LENGTH;
827 cur++;
828 infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
829
830 gnutls_alpn_set_protocols(session, protocols, cur, 0);
831 }
832 #endif
833
834 if(SSL_SET_OPTION(cert)) {
835 if(SSL_SET_OPTION(key_passwd)) {
836 #if HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2
837 const unsigned int supported_key_encryption_algorithms =
838 GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR |
839 GNUTLS_PKCS_USE_PKCS12_RC2_40 | GNUTLS_PKCS_USE_PBES2_3DES |
840 GNUTLS_PKCS_USE_PBES2_AES_128 | GNUTLS_PKCS_USE_PBES2_AES_192 |
841 GNUTLS_PKCS_USE_PBES2_AES_256;
842 rc = gnutls_certificate_set_x509_key_file2(
843 BACKEND->cred,
844 SSL_SET_OPTION(cert),
845 SSL_SET_OPTION(key) ?
846 SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
847 do_file_type(SSL_SET_OPTION(cert_type)),
848 SSL_SET_OPTION(key_passwd),
849 supported_key_encryption_algorithms);
850 if(rc != GNUTLS_E_SUCCESS) {
851 failf(data,
852 "error reading X.509 potentially-encrypted key file: %s",
853 gnutls_strerror(rc));
854 return CURLE_SSL_CONNECT_ERROR;
855 }
856 #else
857 failf(data, "gnutls lacks support for encrypted key files");
858 return CURLE_SSL_CONNECT_ERROR;
859 #endif
860 }
861 else {
862 if(gnutls_certificate_set_x509_key_file(
863 BACKEND->cred,
864 SSL_SET_OPTION(cert),
865 SSL_SET_OPTION(key) ?
866 SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
867 do_file_type(SSL_SET_OPTION(cert_type)) ) !=
868 GNUTLS_E_SUCCESS) {
869 failf(data, "error reading X.509 key or certificate file");
870 return CURLE_SSL_CONNECT_ERROR;
871 }
872 }
873 }
874
875 #ifdef USE_TLS_SRP
876 /* put the credentials to the current session */
877 if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
878 rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP,
879 BACKEND->srp_client_cred);
880 if(rc != GNUTLS_E_SUCCESS) {
881 failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
882 return CURLE_SSL_CONNECT_ERROR;
883 }
884 }
885 else
886 #endif
887 {
888 rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
889 BACKEND->cred);
890 if(rc != GNUTLS_E_SUCCESS) {
891 failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
892 return CURLE_SSL_CONNECT_ERROR;
893 }
894 }
895
896 if(conn->proxy_ssl[sockindex].use) {
897 transport_ptr = conn->proxy_ssl[sockindex].backend->session;
898 gnutls_transport_push = Curl_gtls_push_ssl;
899 gnutls_transport_pull = Curl_gtls_pull_ssl;
900 }
901 else {
902 /* file descriptor for the socket */
903 transport_ptr = &conn->sock[sockindex];
904 gnutls_transport_push = Curl_gtls_push;
905 gnutls_transport_pull = Curl_gtls_pull;
906 }
907
908 /* set the connection handle */
909 gnutls_transport_set_ptr(session, transport_ptr);
910
911 /* register callback functions to send and receive data. */
912 gnutls_transport_set_push_function(session, gnutls_transport_push);
913 gnutls_transport_set_pull_function(session, gnutls_transport_pull);
914
915 /* lowat must be set to zero when using custom push and pull functions. */
916 gnutls_transport_set_lowat(session, 0);
917
918 #ifdef HAS_OCSP
919 if(SSL_CONN_CONFIG(verifystatus)) {
920 rc = gnutls_ocsp_status_request_enable_client(session, NULL, 0, NULL);
921 if(rc != GNUTLS_E_SUCCESS) {
922 failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc);
923 return CURLE_SSL_CONNECT_ERROR;
924 }
925 }
926 #endif
927
928 /* This might be a reconnect, so we check for a session ID in the cache
929 to speed up things */
930 if(SSL_SET_OPTION(primary.sessionid)) {
931 void *ssl_sessionid;
932 size_t ssl_idsize;
933
934 Curl_ssl_sessionid_lock(conn);
935 if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize, sockindex)) {
936 /* we got a session id, use it! */
937 gnutls_session_set_data(session, ssl_sessionid, ssl_idsize);
938
939 /* Informational message */
940 infof(data, "SSL re-using session ID\n");
941 }
942 Curl_ssl_sessionid_unlock(conn);
943 }
944
945 return CURLE_OK;
946 }
947
pkp_pin_peer_pubkey(struct Curl_easy * data,gnutls_x509_crt_t cert,const char * pinnedpubkey)948 static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
949 gnutls_x509_crt_t cert,
950 const char *pinnedpubkey)
951 {
952 /* Scratch */
953 size_t len1 = 0, len2 = 0;
954 unsigned char *buff1 = NULL;
955
956 gnutls_pubkey_t key = NULL;
957
958 /* Result is returned to caller */
959 int ret = 0;
960 CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
961
962 /* if a path wasn't specified, don't pin */
963 if(NULL == pinnedpubkey)
964 return CURLE_OK;
965
966 if(NULL == cert)
967 return result;
968
969 do {
970 /* Begin Gyrations to get the public key */
971 gnutls_pubkey_init(&key);
972
973 ret = gnutls_pubkey_import_x509(key, cert, 0);
974 if(ret < 0)
975 break; /* failed */
976
977 ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, NULL, &len1);
978 if(ret != GNUTLS_E_SHORT_MEMORY_BUFFER || len1 == 0)
979 break; /* failed */
980
981 buff1 = malloc(len1);
982 if(NULL == buff1)
983 break; /* failed */
984
985 len2 = len1;
986
987 ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, buff1, &len2);
988 if(ret < 0 || len1 != len2)
989 break; /* failed */
990
991 /* End Gyrations */
992
993 /* The one good exit point */
994 result = Curl_pin_peer_pubkey(data, pinnedpubkey, buff1, len1);
995 } while(0);
996
997 if(NULL != key)
998 gnutls_pubkey_deinit(key);
999
1000 Curl_safefree(buff1);
1001
1002 return result;
1003 }
1004
1005 static Curl_recv gtls_recv;
1006 static Curl_send gtls_send;
1007
1008 static CURLcode
gtls_connect_step3(struct connectdata * conn,int sockindex)1009 gtls_connect_step3(struct connectdata *conn,
1010 int sockindex)
1011 {
1012 unsigned int cert_list_size;
1013 const gnutls_datum_t *chainp;
1014 unsigned int verify_status = 0;
1015 gnutls_x509_crt_t x509_cert, x509_issuer;
1016 gnutls_datum_t issuerp;
1017 char certbuf[256] = ""; /* big enough? */
1018 size_t size;
1019 time_t certclock;
1020 const char *ptr;
1021 struct Curl_easy *data = conn->data;
1022 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1023 gnutls_session_t session = BACKEND->session;
1024 int rc;
1025 #ifdef HAS_ALPN
1026 gnutls_datum_t proto;
1027 #endif
1028 CURLcode result = CURLE_OK;
1029 #ifndef CURL_DISABLE_VERBOSE_STRINGS
1030 unsigned int algo;
1031 unsigned int bits;
1032 gnutls_protocol_t version = gnutls_protocol_get_version(session);
1033 #endif
1034 const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
1035 conn->host.name;
1036
1037 /* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
1038 ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session),
1039 gnutls_cipher_get(session),
1040 gnutls_mac_get(session));
1041
1042 infof(data, "SSL connection using %s / %s\n",
1043 gnutls_protocol_get_name(version), ptr);
1044
1045 /* This function will return the peer's raw certificate (chain) as sent by
1046 the peer. These certificates are in raw format (DER encoded for
1047 X.509). In case of a X.509 then a certificate list may be present. The
1048 first certificate in the list is the peer's certificate, following the
1049 issuer's certificate, then the issuer's issuer etc. */
1050
1051 chainp = gnutls_certificate_get_peers(session, &cert_list_size);
1052 if(!chainp) {
1053 if(SSL_CONN_CONFIG(verifypeer) ||
1054 SSL_CONN_CONFIG(verifyhost) ||
1055 SSL_SET_OPTION(issuercert)) {
1056 #ifdef USE_TLS_SRP
1057 if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
1058 && SSL_SET_OPTION(username) != NULL
1059 && !SSL_CONN_CONFIG(verifypeer)
1060 && gnutls_cipher_get(session)) {
1061 /* no peer cert, but auth is ok if we have SRP user and cipher and no
1062 peer verify */
1063 }
1064 else {
1065 #endif
1066 failf(data, "failed to get server cert");
1067 return CURLE_PEER_FAILED_VERIFICATION;
1068 #ifdef USE_TLS_SRP
1069 }
1070 #endif
1071 }
1072 infof(data, "\t common name: WARNING couldn't obtain\n");
1073 }
1074
1075 if(data->set.ssl.certinfo && chainp) {
1076 unsigned int i;
1077
1078 result = Curl_ssl_init_certinfo(data, cert_list_size);
1079 if(result)
1080 return result;
1081
1082 for(i = 0; i < cert_list_size; i++) {
1083 const char *beg = (const char *) chainp[i].data;
1084 const char *end = beg + chainp[i].size;
1085
1086 result = Curl_extract_certinfo(conn, i, beg, end);
1087 if(result)
1088 return result;
1089 }
1090 }
1091
1092 if(SSL_CONN_CONFIG(verifypeer)) {
1093 /* This function will try to verify the peer's certificate and return its
1094 status (trusted, invalid etc.). The value of status should be one or
1095 more of the gnutls_certificate_status_t enumerated elements bitwise
1096 or'd. To avoid denial of service attacks some default upper limits
1097 regarding the certificate key size and chain size are set. To override
1098 them use gnutls_certificate_set_verify_limits(). */
1099
1100 rc = gnutls_certificate_verify_peers2(session, &verify_status);
1101 if(rc < 0) {
1102 failf(data, "server cert verify failed: %d", rc);
1103 return CURLE_SSL_CONNECT_ERROR;
1104 }
1105
1106 /* verify_status is a bitmask of gnutls_certificate_status bits */
1107 if(verify_status & GNUTLS_CERT_INVALID) {
1108 if(SSL_CONN_CONFIG(verifypeer)) {
1109 failf(data, "server certificate verification failed. CAfile: %s "
1110 "CRLfile: %s", SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile):
1111 "none",
1112 SSL_SET_OPTION(CRLfile)?SSL_SET_OPTION(CRLfile):"none");
1113 return CURLE_PEER_FAILED_VERIFICATION;
1114 }
1115 else
1116 infof(data, "\t server certificate verification FAILED\n");
1117 }
1118 else
1119 infof(data, "\t server certificate verification OK\n");
1120 }
1121 else
1122 infof(data, "\t server certificate verification SKIPPED\n");
1123
1124 #ifdef HAS_OCSP
1125 if(SSL_CONN_CONFIG(verifystatus)) {
1126 if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) {
1127 gnutls_datum_t status_request;
1128 gnutls_ocsp_resp_t ocsp_resp;
1129
1130 gnutls_ocsp_cert_status_t status;
1131 gnutls_x509_crl_reason_t reason;
1132
1133 rc = gnutls_ocsp_status_request_get(session, &status_request);
1134
1135 infof(data, "\t server certificate status verification FAILED\n");
1136
1137 if(rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
1138 failf(data, "No OCSP response received");
1139 return CURLE_SSL_INVALIDCERTSTATUS;
1140 }
1141
1142 if(rc < 0) {
1143 failf(data, "Invalid OCSP response received");
1144 return CURLE_SSL_INVALIDCERTSTATUS;
1145 }
1146
1147 gnutls_ocsp_resp_init(&ocsp_resp);
1148
1149 rc = gnutls_ocsp_resp_import(ocsp_resp, &status_request);
1150 if(rc < 0) {
1151 failf(data, "Invalid OCSP response received");
1152 return CURLE_SSL_INVALIDCERTSTATUS;
1153 }
1154
1155 (void)gnutls_ocsp_resp_get_single(ocsp_resp, 0, NULL, NULL, NULL, NULL,
1156 &status, NULL, NULL, NULL, &reason);
1157
1158 switch(status) {
1159 case GNUTLS_OCSP_CERT_GOOD:
1160 break;
1161
1162 case GNUTLS_OCSP_CERT_REVOKED: {
1163 const char *crl_reason;
1164
1165 switch(reason) {
1166 default:
1167 case GNUTLS_X509_CRLREASON_UNSPECIFIED:
1168 crl_reason = "unspecified reason";
1169 break;
1170
1171 case GNUTLS_X509_CRLREASON_KEYCOMPROMISE:
1172 crl_reason = "private key compromised";
1173 break;
1174
1175 case GNUTLS_X509_CRLREASON_CACOMPROMISE:
1176 crl_reason = "CA compromised";
1177 break;
1178
1179 case GNUTLS_X509_CRLREASON_AFFILIATIONCHANGED:
1180 crl_reason = "affiliation has changed";
1181 break;
1182
1183 case GNUTLS_X509_CRLREASON_SUPERSEDED:
1184 crl_reason = "certificate superseded";
1185 break;
1186
1187 case GNUTLS_X509_CRLREASON_CESSATIONOFOPERATION:
1188 crl_reason = "operation has ceased";
1189 break;
1190
1191 case GNUTLS_X509_CRLREASON_CERTIFICATEHOLD:
1192 crl_reason = "certificate is on hold";
1193 break;
1194
1195 case GNUTLS_X509_CRLREASON_REMOVEFROMCRL:
1196 crl_reason = "will be removed from delta CRL";
1197 break;
1198
1199 case GNUTLS_X509_CRLREASON_PRIVILEGEWITHDRAWN:
1200 crl_reason = "privilege withdrawn";
1201 break;
1202
1203 case GNUTLS_X509_CRLREASON_AACOMPROMISE:
1204 crl_reason = "AA compromised";
1205 break;
1206 }
1207
1208 failf(data, "Server certificate was revoked: %s", crl_reason);
1209 break;
1210 }
1211
1212 default:
1213 case GNUTLS_OCSP_CERT_UNKNOWN:
1214 failf(data, "Server certificate status is unknown");
1215 break;
1216 }
1217
1218 gnutls_ocsp_resp_deinit(ocsp_resp);
1219
1220 return CURLE_SSL_INVALIDCERTSTATUS;
1221 }
1222 else
1223 infof(data, "\t server certificate status verification OK\n");
1224 }
1225 else
1226 infof(data, "\t server certificate status verification SKIPPED\n");
1227 #endif
1228
1229 /* initialize an X.509 certificate structure. */
1230 gnutls_x509_crt_init(&x509_cert);
1231
1232 if(chainp)
1233 /* convert the given DER or PEM encoded Certificate to the native
1234 gnutls_x509_crt_t format */
1235 gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
1236
1237 if(SSL_SET_OPTION(issuercert)) {
1238 gnutls_x509_crt_init(&x509_issuer);
1239 issuerp = load_file(SSL_SET_OPTION(issuercert));
1240 gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
1241 rc = gnutls_x509_crt_check_issuer(x509_cert, x509_issuer);
1242 gnutls_x509_crt_deinit(x509_issuer);
1243 unload_file(issuerp);
1244 if(rc <= 0) {
1245 failf(data, "server certificate issuer check failed (IssuerCert: %s)",
1246 SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none");
1247 gnutls_x509_crt_deinit(x509_cert);
1248 return CURLE_SSL_ISSUER_ERROR;
1249 }
1250 infof(data, "\t server certificate issuer check OK (Issuer Cert: %s)\n",
1251 SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none");
1252 }
1253
1254 size = sizeof(certbuf);
1255 rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
1256 0, /* the first and only one */
1257 FALSE,
1258 certbuf,
1259 &size);
1260 if(rc) {
1261 infof(data, "error fetching CN from cert:%s\n",
1262 gnutls_strerror(rc));
1263 }
1264
1265 /* This function will check if the given certificate's subject matches the
1266 given hostname. This is a basic implementation of the matching described
1267 in RFC2818 (HTTPS), which takes into account wildcards, and the subject
1268 alternative name PKIX extension. Returns non zero on success, and zero on
1269 failure. */
1270 rc = gnutls_x509_crt_check_hostname(x509_cert, hostname);
1271 #if GNUTLS_VERSION_NUMBER < 0x030306
1272 /* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP
1273 addresses. */
1274 if(!rc) {
1275 #ifdef ENABLE_IPV6
1276 #define use_addr in6_addr
1277 #else
1278 #define use_addr in_addr
1279 #endif
1280 unsigned char addrbuf[sizeof(struct use_addr)];
1281 unsigned char certaddr[sizeof(struct use_addr)];
1282 size_t addrlen = 0, certaddrlen;
1283 int i;
1284 int ret = 0;
1285
1286 if(Curl_inet_pton(AF_INET, hostname, addrbuf) > 0)
1287 addrlen = 4;
1288 #ifdef ENABLE_IPV6
1289 else if(Curl_inet_pton(AF_INET6, hostname, addrbuf) > 0)
1290 addrlen = 16;
1291 #endif
1292
1293 if(addrlen) {
1294 for(i = 0; ; i++) {
1295 certaddrlen = sizeof(certaddr);
1296 ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr,
1297 &certaddrlen, NULL);
1298 /* If this happens, it wasn't an IP address. */
1299 if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
1300 continue;
1301 if(ret < 0)
1302 break;
1303 if(ret != GNUTLS_SAN_IPADDRESS)
1304 continue;
1305 if(certaddrlen == addrlen && !memcmp(addrbuf, certaddr, addrlen)) {
1306 rc = 1;
1307 break;
1308 }
1309 }
1310 }
1311 }
1312 #endif
1313 if(!rc) {
1314 const char * const dispname = SSL_IS_PROXY() ?
1315 conn->http_proxy.host.dispname : conn->host.dispname;
1316
1317 if(SSL_CONN_CONFIG(verifyhost)) {
1318 failf(data, "SSL: certificate subject name (%s) does not match "
1319 "target host name '%s'", certbuf, dispname);
1320 gnutls_x509_crt_deinit(x509_cert);
1321 return CURLE_PEER_FAILED_VERIFICATION;
1322 }
1323 else
1324 infof(data, "\t common name: %s (does not match '%s')\n",
1325 certbuf, dispname);
1326 }
1327 else
1328 infof(data, "\t common name: %s (matched)\n", certbuf);
1329
1330 /* Check for time-based validity */
1331 certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
1332
1333 if(certclock == (time_t)-1) {
1334 if(SSL_CONN_CONFIG(verifypeer)) {
1335 failf(data, "server cert expiration date verify failed");
1336 gnutls_x509_crt_deinit(x509_cert);
1337 return CURLE_SSL_CONNECT_ERROR;
1338 }
1339 else
1340 infof(data, "\t server certificate expiration date verify FAILED\n");
1341 }
1342 else {
1343 if(certclock < time(NULL)) {
1344 if(SSL_CONN_CONFIG(verifypeer)) {
1345 failf(data, "server certificate expiration date has passed.");
1346 gnutls_x509_crt_deinit(x509_cert);
1347 return CURLE_PEER_FAILED_VERIFICATION;
1348 }
1349 else
1350 infof(data, "\t server certificate expiration date FAILED\n");
1351 }
1352 else
1353 infof(data, "\t server certificate expiration date OK\n");
1354 }
1355
1356 certclock = gnutls_x509_crt_get_activation_time(x509_cert);
1357
1358 if(certclock == (time_t)-1) {
1359 if(SSL_CONN_CONFIG(verifypeer)) {
1360 failf(data, "server cert activation date verify failed");
1361 gnutls_x509_crt_deinit(x509_cert);
1362 return CURLE_SSL_CONNECT_ERROR;
1363 }
1364 else
1365 infof(data, "\t server certificate activation date verify FAILED\n");
1366 }
1367 else {
1368 if(certclock > time(NULL)) {
1369 if(SSL_CONN_CONFIG(verifypeer)) {
1370 failf(data, "server certificate not activated yet.");
1371 gnutls_x509_crt_deinit(x509_cert);
1372 return CURLE_PEER_FAILED_VERIFICATION;
1373 }
1374 else
1375 infof(data, "\t server certificate activation date FAILED\n");
1376 }
1377 else
1378 infof(data, "\t server certificate activation date OK\n");
1379 }
1380
1381 ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
1382 data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
1383 if(ptr) {
1384 result = pkp_pin_peer_pubkey(data, x509_cert, ptr);
1385 if(result != CURLE_OK) {
1386 failf(data, "SSL: public key does not match pinned public key!");
1387 gnutls_x509_crt_deinit(x509_cert);
1388 return result;
1389 }
1390 }
1391
1392 /* Show:
1393
1394 - subject
1395 - start date
1396 - expire date
1397 - common name
1398 - issuer
1399
1400 */
1401
1402 #ifndef CURL_DISABLE_VERBOSE_STRINGS
1403 /* public key algorithm's parameters */
1404 algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
1405 infof(data, "\t certificate public key: %s\n",
1406 gnutls_pk_algorithm_get_name(algo));
1407
1408 /* version of the X.509 certificate. */
1409 infof(data, "\t certificate version: #%d\n",
1410 gnutls_x509_crt_get_version(x509_cert));
1411
1412
1413 size = sizeof(certbuf);
1414 gnutls_x509_crt_get_dn(x509_cert, certbuf, &size);
1415 infof(data, "\t subject: %s\n", certbuf);
1416
1417 certclock = gnutls_x509_crt_get_activation_time(x509_cert);
1418 showtime(data, "start date", certclock);
1419
1420 certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
1421 showtime(data, "expire date", certclock);
1422
1423 size = sizeof(certbuf);
1424 gnutls_x509_crt_get_issuer_dn(x509_cert, certbuf, &size);
1425 infof(data, "\t issuer: %s\n", certbuf);
1426 #endif
1427
1428 gnutls_x509_crt_deinit(x509_cert);
1429
1430 #ifdef HAS_ALPN
1431 if(conn->bits.tls_enable_alpn) {
1432 rc = gnutls_alpn_get_selected_protocol(session, &proto);
1433 if(rc == 0) {
1434 infof(data, "ALPN, server accepted to use %.*s\n", proto.size,
1435 proto.data);
1436
1437 #ifdef USE_NGHTTP2
1438 if(proto.size == NGHTTP2_PROTO_VERSION_ID_LEN &&
1439 !memcmp(NGHTTP2_PROTO_VERSION_ID, proto.data,
1440 NGHTTP2_PROTO_VERSION_ID_LEN)) {
1441 conn->negnpn = CURL_HTTP_VERSION_2;
1442 }
1443 else
1444 #endif
1445 if(proto.size == ALPN_HTTP_1_1_LENGTH &&
1446 !memcmp(ALPN_HTTP_1_1, proto.data, ALPN_HTTP_1_1_LENGTH)) {
1447 conn->negnpn = CURL_HTTP_VERSION_1_1;
1448 }
1449 }
1450 else
1451 infof(data, "ALPN, server did not agree to a protocol\n");
1452 }
1453 #endif
1454
1455 conn->ssl[sockindex].state = ssl_connection_complete;
1456 conn->recv[sockindex] = gtls_recv;
1457 conn->send[sockindex] = gtls_send;
1458
1459 if(SSL_SET_OPTION(primary.sessionid)) {
1460 /* we always unconditionally get the session id here, as even if we
1461 already got it from the cache and asked to use it in the connection, it
1462 might've been rejected and then a new one is in use now and we need to
1463 detect that. */
1464 bool incache;
1465 void *ssl_sessionid;
1466 void *connect_sessionid;
1467 size_t connect_idsize = 0;
1468
1469 /* get the session ID data size */
1470 gnutls_session_get_data(session, NULL, &connect_idsize);
1471 connect_sessionid = malloc(connect_idsize); /* get a buffer for it */
1472
1473 if(connect_sessionid) {
1474 /* extract session ID to the allocated buffer */
1475 gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
1476
1477 Curl_ssl_sessionid_lock(conn);
1478 incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL,
1479 sockindex));
1480 if(incache) {
1481 /* there was one before in the cache, so instead of risking that the
1482 previous one was rejected, we just kill that and store the new */
1483 Curl_ssl_delsessionid(conn, ssl_sessionid);
1484 }
1485
1486 /* store this session id */
1487 result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize,
1488 sockindex);
1489 Curl_ssl_sessionid_unlock(conn);
1490 if(result) {
1491 free(connect_sessionid);
1492 result = CURLE_OUT_OF_MEMORY;
1493 }
1494 }
1495 else
1496 result = CURLE_OUT_OF_MEMORY;
1497 }
1498
1499 return result;
1500 }
1501
1502
1503 /*
1504 * This function is called after the TCP connect has completed. Setup the TLS
1505 * layer and do all necessary magic.
1506 */
1507 /* We use connssl->connecting_state to keep track of the connection status;
1508 there are three states: 'ssl_connect_1' (not started yet or complete),
1509 'ssl_connect_2_reading' (waiting for data from server), and
1510 'ssl_connect_2_writing' (waiting to be able to write).
1511 */
1512 static CURLcode
gtls_connect_common(struct connectdata * conn,int sockindex,bool nonblocking,bool * done)1513 gtls_connect_common(struct connectdata *conn,
1514 int sockindex,
1515 bool nonblocking,
1516 bool *done)
1517 {
1518 int rc;
1519 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1520
1521 /* Initiate the connection, if not already done */
1522 if(ssl_connect_1 == connssl->connecting_state) {
1523 rc = gtls_connect_step1(conn, sockindex);
1524 if(rc)
1525 return rc;
1526 }
1527
1528 rc = handshake(conn, sockindex, TRUE, nonblocking);
1529 if(rc)
1530 /* handshake() sets its own error message with failf() */
1531 return rc;
1532
1533 /* Finish connecting once the handshake is done */
1534 if(ssl_connect_1 == connssl->connecting_state) {
1535 rc = gtls_connect_step3(conn, sockindex);
1536 if(rc)
1537 return rc;
1538 }
1539
1540 *done = ssl_connect_1 == connssl->connecting_state;
1541
1542 return CURLE_OK;
1543 }
1544
Curl_gtls_connect_nonblocking(struct connectdata * conn,int sockindex,bool * done)1545 static CURLcode Curl_gtls_connect_nonblocking(struct connectdata *conn,
1546 int sockindex, bool *done)
1547 {
1548 return gtls_connect_common(conn, sockindex, TRUE, done);
1549 }
1550
Curl_gtls_connect(struct connectdata * conn,int sockindex)1551 static CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex)
1552 {
1553 CURLcode result;
1554 bool done = FALSE;
1555
1556 result = gtls_connect_common(conn, sockindex, FALSE, &done);
1557 if(result)
1558 return result;
1559
1560 DEBUGASSERT(done);
1561
1562 return CURLE_OK;
1563 }
1564
Curl_gtls_data_pending(const struct connectdata * conn,int connindex)1565 static bool Curl_gtls_data_pending(const struct connectdata *conn,
1566 int connindex)
1567 {
1568 const struct ssl_connect_data *connssl = &conn->ssl[connindex];
1569 bool res = FALSE;
1570 if(BACKEND->session &&
1571 0 != gnutls_record_check_pending(BACKEND->session))
1572 res = TRUE;
1573
1574 connssl = &conn->proxy_ssl[connindex];
1575 if(BACKEND->session &&
1576 0 != gnutls_record_check_pending(BACKEND->session))
1577 res = TRUE;
1578
1579 return res;
1580 }
1581
gtls_send(struct connectdata * conn,int sockindex,const void * mem,size_t len,CURLcode * curlcode)1582 static ssize_t gtls_send(struct connectdata *conn,
1583 int sockindex,
1584 const void *mem,
1585 size_t len,
1586 CURLcode *curlcode)
1587 {
1588 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1589 ssize_t rc = gnutls_record_send(BACKEND->session, mem, len);
1590
1591 if(rc < 0) {
1592 *curlcode = (rc == GNUTLS_E_AGAIN)
1593 ? CURLE_AGAIN
1594 : CURLE_SEND_ERROR;
1595
1596 rc = -1;
1597 }
1598
1599 return rc;
1600 }
1601
close_one(struct ssl_connect_data * connssl)1602 static void close_one(struct ssl_connect_data *connssl)
1603 {
1604 if(BACKEND->session) {
1605 gnutls_bye(BACKEND->session, GNUTLS_SHUT_RDWR);
1606 gnutls_deinit(BACKEND->session);
1607 BACKEND->session = NULL;
1608 }
1609 if(BACKEND->cred) {
1610 gnutls_certificate_free_credentials(BACKEND->cred);
1611 BACKEND->cred = NULL;
1612 }
1613 #ifdef USE_TLS_SRP
1614 if(BACKEND->srp_client_cred) {
1615 gnutls_srp_free_client_credentials(BACKEND->srp_client_cred);
1616 BACKEND->srp_client_cred = NULL;
1617 }
1618 #endif
1619 }
1620
Curl_gtls_close(struct connectdata * conn,int sockindex)1621 static void Curl_gtls_close(struct connectdata *conn, int sockindex)
1622 {
1623 close_one(&conn->ssl[sockindex]);
1624 close_one(&conn->proxy_ssl[sockindex]);
1625 }
1626
1627 /*
1628 * This function is called to shut down the SSL layer but keep the
1629 * socket open (CCC - Clear Command Channel)
1630 */
Curl_gtls_shutdown(struct connectdata * conn,int sockindex)1631 static int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
1632 {
1633 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1634 ssize_t result;
1635 int retval = 0;
1636 struct Curl_easy *data = conn->data;
1637 bool done = FALSE;
1638 char buf[120];
1639
1640 /* This has only been tested on the proftpd server, and the mod_tls code
1641 sends a close notify alert without waiting for a close notify alert in
1642 response. Thus we wait for a close notify alert from the server, but
1643 we do not send one. Let's hope other servers do the same... */
1644
1645 if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
1646 gnutls_bye(BACKEND->session, GNUTLS_SHUT_WR);
1647
1648 if(BACKEND->session) {
1649 while(!done) {
1650 int what = SOCKET_READABLE(conn->sock[sockindex],
1651 SSL_SHUTDOWN_TIMEOUT);
1652 if(what > 0) {
1653 /* Something to read, let's do it and hope that it is the close
1654 notify alert from the server */
1655 result = gnutls_record_recv(BACKEND->session,
1656 buf, sizeof(buf));
1657 switch(result) {
1658 case 0:
1659 /* This is the expected response. There was no data but only
1660 the close notify alert */
1661 done = TRUE;
1662 break;
1663 case GNUTLS_E_AGAIN:
1664 case GNUTLS_E_INTERRUPTED:
1665 infof(data, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED\n");
1666 break;
1667 default:
1668 retval = -1;
1669 done = TRUE;
1670 break;
1671 }
1672 }
1673 else if(0 == what) {
1674 /* timeout */
1675 failf(data, "SSL shutdown timeout");
1676 done = TRUE;
1677 }
1678 else {
1679 /* anything that gets here is fatally bad */
1680 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
1681 retval = -1;
1682 done = TRUE;
1683 }
1684 }
1685 gnutls_deinit(BACKEND->session);
1686 }
1687 gnutls_certificate_free_credentials(BACKEND->cred);
1688
1689 #ifdef USE_TLS_SRP
1690 if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
1691 && SSL_SET_OPTION(username) != NULL)
1692 gnutls_srp_free_client_credentials(BACKEND->srp_client_cred);
1693 #endif
1694
1695 BACKEND->cred = NULL;
1696 BACKEND->session = NULL;
1697
1698 return retval;
1699 }
1700
gtls_recv(struct connectdata * conn,int num,char * buf,size_t buffersize,CURLcode * curlcode)1701 static ssize_t gtls_recv(struct connectdata *conn, /* connection data */
1702 int num, /* socketindex */
1703 char *buf, /* store read data here */
1704 size_t buffersize, /* max amount to read */
1705 CURLcode *curlcode)
1706 {
1707 struct ssl_connect_data *connssl = &conn->ssl[num];
1708 ssize_t ret;
1709
1710 ret = gnutls_record_recv(BACKEND->session, buf, buffersize);
1711 if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
1712 *curlcode = CURLE_AGAIN;
1713 return -1;
1714 }
1715
1716 if(ret == GNUTLS_E_REHANDSHAKE) {
1717 /* BLOCKING call, this is bad but a work-around for now. Fixing this "the
1718 proper way" takes a whole lot of work. */
1719 CURLcode result = handshake(conn, num, FALSE, FALSE);
1720 if(result)
1721 /* handshake() writes error message on its own */
1722 *curlcode = result;
1723 else
1724 *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */
1725 return -1;
1726 }
1727
1728 if(ret < 0) {
1729 failf(conn->data, "GnuTLS recv error (%d): %s",
1730
1731 (int)ret, gnutls_strerror((int)ret));
1732 *curlcode = CURLE_RECV_ERROR;
1733 return -1;
1734 }
1735
1736 return ret;
1737 }
1738
Curl_gtls_session_free(void * ptr)1739 static void Curl_gtls_session_free(void *ptr)
1740 {
1741 free(ptr);
1742 }
1743
Curl_gtls_version(char * buffer,size_t size)1744 static size_t Curl_gtls_version(char *buffer, size_t size)
1745 {
1746 return msnprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
1747 }
1748
1749 #ifndef USE_GNUTLS_NETTLE
Curl_gtls_seed(struct Curl_easy * data)1750 static int Curl_gtls_seed(struct Curl_easy *data)
1751 {
1752 /* we have the "SSL is seeded" boolean static to prevent multiple
1753 time-consuming seedings in vain */
1754 static bool ssl_seeded = FALSE;
1755
1756 /* Quickly add a bit of entropy */
1757 gcry_fast_random_poll();
1758
1759 if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] ||
1760 data->set.str[STRING_SSL_EGDSOCKET]) {
1761
1762 /* TODO: to a good job seeding the RNG
1763 This may involve the gcry_control function and these options:
1764 GCRYCTL_SET_RANDOM_SEED_FILE
1765 GCRYCTL_SET_RNDEGD_SOCKET
1766 */
1767 ssl_seeded = TRUE;
1768 }
1769 return 0;
1770 }
1771 #endif
1772
1773 /* data might be NULL! */
Curl_gtls_random(struct Curl_easy * data,unsigned char * entropy,size_t length)1774 static CURLcode Curl_gtls_random(struct Curl_easy *data,
1775 unsigned char *entropy, size_t length)
1776 {
1777 #if defined(USE_GNUTLS_NETTLE)
1778 int rc;
1779 (void)data;
1780 rc = gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
1781 return rc?CURLE_FAILED_INIT:CURLE_OK;
1782 #elif defined(USE_GNUTLS)
1783 if(data)
1784 Curl_gtls_seed(data); /* Initiate the seed if not already done */
1785 gcry_randomize(entropy, length, GCRY_STRONG_RANDOM);
1786 #endif
1787 return CURLE_OK;
1788 }
1789
Curl_gtls_md5sum(unsigned char * tmp,size_t tmplen,unsigned char * md5sum,size_t md5len)1790 static CURLcode Curl_gtls_md5sum(unsigned char *tmp, /* input */
1791 size_t tmplen,
1792 unsigned char *md5sum, /* output */
1793 size_t md5len)
1794 {
1795 #if defined(USE_GNUTLS_NETTLE)
1796 struct md5_ctx MD5pw;
1797 md5_init(&MD5pw);
1798 md5_update(&MD5pw, (unsigned int)tmplen, tmp);
1799 md5_digest(&MD5pw, (unsigned int)md5len, md5sum);
1800 #elif defined(USE_GNUTLS)
1801 gcry_md_hd_t MD5pw;
1802 gcry_md_open(&MD5pw, GCRY_MD_MD5, 0);
1803 gcry_md_write(MD5pw, tmp, tmplen);
1804 memcpy(md5sum, gcry_md_read(MD5pw, 0), md5len);
1805 gcry_md_close(MD5pw);
1806 #endif
1807 return CURLE_OK;
1808 }
1809
Curl_gtls_sha256sum(const unsigned char * tmp,size_t tmplen,unsigned char * sha256sum,size_t sha256len)1810 static CURLcode Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
1811 size_t tmplen,
1812 unsigned char *sha256sum, /* output */
1813 size_t sha256len)
1814 {
1815 #if defined(USE_GNUTLS_NETTLE)
1816 struct sha256_ctx SHA256pw;
1817 sha256_init(&SHA256pw);
1818 sha256_update(&SHA256pw, (unsigned int)tmplen, tmp);
1819 sha256_digest(&SHA256pw, (unsigned int)sha256len, sha256sum);
1820 #elif defined(USE_GNUTLS)
1821 gcry_md_hd_t SHA256pw;
1822 gcry_md_open(&SHA256pw, GCRY_MD_SHA256, 0);
1823 gcry_md_write(SHA256pw, tmp, tmplen);
1824 memcpy(sha256sum, gcry_md_read(SHA256pw, 0), sha256len);
1825 gcry_md_close(SHA256pw);
1826 #endif
1827 return CURLE_OK;
1828 }
1829
Curl_gtls_cert_status_request(void)1830 static bool Curl_gtls_cert_status_request(void)
1831 {
1832 #ifdef HAS_OCSP
1833 return TRUE;
1834 #else
1835 return FALSE;
1836 #endif
1837 }
1838
Curl_gtls_get_internals(struct ssl_connect_data * connssl,CURLINFO info UNUSED_PARAM)1839 static void *Curl_gtls_get_internals(struct ssl_connect_data *connssl,
1840 CURLINFO info UNUSED_PARAM)
1841 {
1842 (void)info;
1843 return BACKEND->session;
1844 }
1845
1846 const struct Curl_ssl Curl_ssl_gnutls = {
1847 { CURLSSLBACKEND_GNUTLS, "gnutls" }, /* info */
1848
1849 SSLSUPP_CA_PATH |
1850 SSLSUPP_CERTINFO |
1851 SSLSUPP_PINNEDPUBKEY |
1852 SSLSUPP_HTTPS_PROXY,
1853
1854 sizeof(struct ssl_backend_data),
1855
1856 Curl_gtls_init, /* init */
1857 Curl_gtls_cleanup, /* cleanup */
1858 Curl_gtls_version, /* version */
1859 Curl_none_check_cxn, /* check_cxn */
1860 Curl_gtls_shutdown, /* shutdown */
1861 Curl_gtls_data_pending, /* data_pending */
1862 Curl_gtls_random, /* random */
1863 Curl_gtls_cert_status_request, /* cert_status_request */
1864 Curl_gtls_connect, /* connect */
1865 Curl_gtls_connect_nonblocking, /* connect_nonblocking */
1866 Curl_gtls_get_internals, /* get_internals */
1867 Curl_gtls_close, /* close_one */
1868 Curl_none_close_all, /* close_all */
1869 Curl_gtls_session_free, /* session_free */
1870 Curl_none_set_engine, /* set_engine */
1871 Curl_none_set_engine_default, /* set_engine_default */
1872 Curl_none_engines_list, /* engines_list */
1873 Curl_none_false_start, /* false_start */
1874 Curl_gtls_md5sum, /* md5sum */
1875 Curl_gtls_sha256sum /* sha256sum */
1876 };
1877
1878 #endif /* USE_GNUTLS */
1879