1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2014, 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 http://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/gnutls.h> 36#include <gnutls/x509.h> 37 38#ifdef USE_GNUTLS_NETTLE 39#include <gnutls/crypto.h> 40#include <nettle/md5.h> 41#else 42#include <gcrypt.h> 43#endif 44 45#include "urldata.h" 46#include "sendf.h" 47#include "inet_pton.h" 48#include "gtls.h" 49#include "vtls.h" 50#include "parsedate.h" 51#include "connect.h" /* for the connect timeout */ 52#include "select.h" 53#include "rawstr.h" 54#include "warnless.h" 55 56#define _MPRINTF_REPLACE /* use our functions only */ 57#include <curl/mprintf.h> 58#include "curl_memory.h" 59/* The last #include file should be: */ 60#include "memdebug.h" 61 62/* 63 Some hackish cast macros based on: 64 http://library.gnome.org/devel/glib/unstable/glib-Type-Conversion-Macros.html 65*/ 66#ifndef GNUTLS_POINTER_TO_INT_CAST 67#define GNUTLS_POINTER_TO_INT_CAST(p) ((int) (long) (p)) 68#endif 69#ifndef GNUTLS_INT_TO_POINTER_CAST 70#define GNUTLS_INT_TO_POINTER_CAST(i) ((void*) (long) (i)) 71#endif 72 73/* Enable GnuTLS debugging by defining GTLSDEBUG */ 74/*#define GTLSDEBUG */ 75 76#ifdef GTLSDEBUG 77static void tls_log_func(int level, const char *str) 78{ 79 fprintf(stderr, "|<%d>| %s", level, str); 80} 81#endif 82static bool gtls_inited = FALSE; 83 84#if defined(GNUTLS_VERSION_NUMBER) 85# if (GNUTLS_VERSION_NUMBER >= 0x020c00) 86# undef gnutls_transport_set_lowat 87# define gnutls_transport_set_lowat(A,B) Curl_nop_stmt 88# define USE_GNUTLS_PRIORITY_SET_DIRECT 1 89# endif 90# if (GNUTLS_VERSION_NUMBER >= 0x020c03) 91# define GNUTLS_MAPS_WINSOCK_ERRORS 1 92# endif 93 94# ifdef USE_NGHTTP2 95# undef HAS_ALPN 96# if (GNUTLS_VERSION_NUMBER >= 0x030200) 97# define HAS_ALPN 98# endif 99# endif 100#endif 101 102/* 103 * Custom push and pull callback functions used by GNU TLS to read and write 104 * to the socket. These functions are simple wrappers to send() and recv() 105 * (although here using the sread/swrite macros as defined by 106 * curl_setup_once.h). 107 * We use custom functions rather than the GNU TLS defaults because it allows 108 * us to get specific about the fourth "flags" argument, and to use arbitrary 109 * private data with gnutls_transport_set_ptr if we wish. 110 * 111 * When these custom push and pull callbacks fail, GNU TLS checks its own 112 * session-specific error variable, and when not set also its own global 113 * errno variable, in order to take appropriate action. GNU TLS does not 114 * require that the transport is actually a socket. This implies that for 115 * Windows builds these callbacks should ideally set the session-specific 116 * error variable using function gnutls_transport_set_errno or as a last 117 * resort global errno variable using gnutls_transport_set_global_errno, 118 * with a transport agnostic error value. This implies that some winsock 119 * error translation must take place in these callbacks. 120 * 121 * Paragraph above applies to GNU TLS versions older than 2.12.3, since 122 * this version GNU TLS does its own internal winsock error translation 123 * using system_errno() function. 124 */ 125 126#if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS) 127# define gtls_EINTR 4 128# define gtls_EIO 5 129# define gtls_EAGAIN 11 130static int gtls_mapped_sockerrno(void) 131{ 132 switch(SOCKERRNO) { 133 case WSAEWOULDBLOCK: 134 return gtls_EAGAIN; 135 case WSAEINTR: 136 return gtls_EINTR; 137 default: 138 break; 139 } 140 return gtls_EIO; 141} 142#endif 143 144static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len) 145{ 146 ssize_t ret = swrite(GNUTLS_POINTER_TO_INT_CAST(s), buf, len); 147#if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS) 148 if(ret < 0) 149 gnutls_transport_set_global_errno(gtls_mapped_sockerrno()); 150#endif 151 return ret; 152} 153 154static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len) 155{ 156 ssize_t ret = sread(GNUTLS_POINTER_TO_INT_CAST(s), buf, len); 157#if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS) 158 if(ret < 0) 159 gnutls_transport_set_global_errno(gtls_mapped_sockerrno()); 160#endif 161 return ret; 162} 163 164/* Curl_gtls_init() 165 * 166 * Global GnuTLS init, called from Curl_ssl_init(). This calls functions that 167 * are not thread-safe and thus this function itself is not thread-safe and 168 * must only be called from within curl_global_init() to keep the thread 169 * situation under control! 170 */ 171int Curl_gtls_init(void) 172{ 173 int ret = 1; 174 if(!gtls_inited) { 175 ret = gnutls_global_init()?0:1; 176#ifdef GTLSDEBUG 177 gnutls_global_set_log_function(tls_log_func); 178 gnutls_global_set_log_level(2); 179#endif 180 gtls_inited = TRUE; 181 } 182 return ret; 183} 184 185int Curl_gtls_cleanup(void) 186{ 187 if(gtls_inited) { 188 gnutls_global_deinit(); 189 gtls_inited = FALSE; 190 } 191 return 1; 192} 193 194static void showtime(struct SessionHandle *data, 195 const char *text, 196 time_t stamp) 197{ 198 struct tm buffer; 199 const struct tm *tm = &buffer; 200 CURLcode result = Curl_gmtime(stamp, &buffer); 201 if(result) 202 return; 203 204 snprintf(data->state.buffer, 205 BUFSIZE, 206 "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT\n", 207 text, 208 Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], 209 tm->tm_mday, 210 Curl_month[tm->tm_mon], 211 tm->tm_year + 1900, 212 tm->tm_hour, 213 tm->tm_min, 214 tm->tm_sec); 215 infof(data, "%s\n", data->state.buffer); 216} 217 218static gnutls_datum_t load_file (const char *file) 219{ 220 FILE *f; 221 gnutls_datum_t loaded_file = { NULL, 0 }; 222 long filelen; 223 void *ptr; 224 225 if(!(f = fopen(file, "r"))) 226 return loaded_file; 227 if(fseek(f, 0, SEEK_END) != 0 228 || (filelen = ftell(f)) < 0 229 || fseek(f, 0, SEEK_SET) != 0 230 || !(ptr = malloc((size_t)filelen))) 231 goto out; 232 if(fread(ptr, 1, (size_t)filelen, f) < (size_t)filelen) { 233 free(ptr); 234 goto out; 235 } 236 237 loaded_file.data = ptr; 238 loaded_file.size = (unsigned int)filelen; 239out: 240 fclose(f); 241 return loaded_file; 242} 243 244static void unload_file(gnutls_datum_t data) { 245 free(data.data); 246} 247 248 249/* this function does a SSL/TLS (re-)handshake */ 250static CURLcode handshake(struct connectdata *conn, 251 int sockindex, 252 bool duringconnect, 253 bool nonblocking) 254{ 255 struct SessionHandle *data = conn->data; 256 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 257 gnutls_session_t session = conn->ssl[sockindex].session; 258 curl_socket_t sockfd = conn->sock[sockindex]; 259 long timeout_ms; 260 int rc; 261 int what; 262 263 for(;;) { 264 /* check allowed time left */ 265 timeout_ms = Curl_timeleft(data, NULL, duringconnect); 266 267 if(timeout_ms < 0) { 268 /* no need to continue if time already is up */ 269 failf(data, "SSL connection timeout"); 270 return CURLE_OPERATION_TIMEDOUT; 271 } 272 273 /* if ssl is expecting something, check if it's available. */ 274 if(connssl->connecting_state == ssl_connect_2_reading 275 || connssl->connecting_state == ssl_connect_2_writing) { 276 277 curl_socket_t writefd = ssl_connect_2_writing== 278 connssl->connecting_state?sockfd:CURL_SOCKET_BAD; 279 curl_socket_t readfd = ssl_connect_2_reading== 280 connssl->connecting_state?sockfd:CURL_SOCKET_BAD; 281 282 what = Curl_socket_ready(readfd, writefd, 283 nonblocking?0: 284 timeout_ms?timeout_ms:1000); 285 if(what < 0) { 286 /* fatal error */ 287 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); 288 return CURLE_SSL_CONNECT_ERROR; 289 } 290 else if(0 == what) { 291 if(nonblocking) 292 return CURLE_OK; 293 else if(timeout_ms) { 294 /* timeout */ 295 failf(data, "SSL connection timeout at %ld", timeout_ms); 296 return CURLE_OPERATION_TIMEDOUT; 297 } 298 } 299 /* socket is readable or writable */ 300 } 301 302 rc = gnutls_handshake(session); 303 304 if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) { 305 connssl->connecting_state = 306 gnutls_record_get_direction(session)? 307 ssl_connect_2_writing:ssl_connect_2_reading; 308 continue; 309 if(nonblocking) 310 return CURLE_OK; 311 } 312 else if((rc < 0) && !gnutls_error_is_fatal(rc)) { 313 const char *strerr = NULL; 314 315 if(rc == GNUTLS_E_WARNING_ALERT_RECEIVED) { 316 int alert = gnutls_alert_get(session); 317 strerr = gnutls_alert_get_name(alert); 318 } 319 320 if(strerr == NULL) 321 strerr = gnutls_strerror(rc); 322 323 failf(data, "gnutls_handshake() warning: %s", strerr); 324 } 325 else if(rc < 0) { 326 const char *strerr = NULL; 327 328 if(rc == GNUTLS_E_FATAL_ALERT_RECEIVED) { 329 int alert = gnutls_alert_get(session); 330 strerr = gnutls_alert_get_name(alert); 331 } 332 333 if(strerr == NULL) 334 strerr = gnutls_strerror(rc); 335 336 failf(data, "gnutls_handshake() failed: %s", strerr); 337 return CURLE_SSL_CONNECT_ERROR; 338 } 339 340 /* Reset our connect state machine */ 341 connssl->connecting_state = ssl_connect_1; 342 return CURLE_OK; 343 } 344} 345 346static gnutls_x509_crt_fmt_t do_file_type(const char *type) 347{ 348 if(!type || !type[0]) 349 return GNUTLS_X509_FMT_PEM; 350 if(Curl_raw_equal(type, "PEM")) 351 return GNUTLS_X509_FMT_PEM; 352 if(Curl_raw_equal(type, "DER")) 353 return GNUTLS_X509_FMT_DER; 354 return -1; 355} 356 357static CURLcode 358gtls_connect_step1(struct connectdata *conn, 359 int sockindex) 360{ 361 struct SessionHandle *data = conn->data; 362 gnutls_session_t session; 363 int rc; 364 void *ssl_sessionid; 365 size_t ssl_idsize; 366 bool sni = TRUE; /* default is SNI enabled */ 367#ifdef ENABLE_IPV6 368 struct in6_addr addr; 369#else 370 struct in_addr addr; 371#endif 372#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT 373 static const int cipher_priority[] = { 374 /* These two ciphers were added to GnuTLS as late as ver. 3.0.1, 375 but this code path is only ever used for ver. < 2.12.0. 376 GNUTLS_CIPHER_AES_128_GCM, 377 GNUTLS_CIPHER_AES_256_GCM, 378 */ 379 GNUTLS_CIPHER_AES_128_CBC, 380 GNUTLS_CIPHER_AES_256_CBC, 381 GNUTLS_CIPHER_CAMELLIA_128_CBC, 382 GNUTLS_CIPHER_CAMELLIA_256_CBC, 383 GNUTLS_CIPHER_3DES_CBC, 384 }; 385 static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 }; 386 static int protocol_priority[] = { 0, 0, 0, 0 }; 387#else 388#define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509" 389/* If GnuTLS was compiled without support for SRP it will error out if SRP is 390 requested in the priority string, so treat it specially 391 */ 392#define GNUTLS_SRP "+SRP" 393 const char* prioritylist; 394 const char *err = NULL; 395#endif 396#ifdef HAS_ALPN 397 int protocols_size = 2; 398 gnutls_datum_t protocols[2]; 399#endif 400 401 if(conn->ssl[sockindex].state == ssl_connection_complete) 402 /* to make us tolerant against being called more than once for the 403 same connection */ 404 return CURLE_OK; 405 406 if(!gtls_inited) 407 Curl_gtls_init(); 408 409 /* GnuTLS only supports SSLv3 and TLSv1 */ 410 if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) { 411 failf(data, "GnuTLS does not support SSLv2"); 412 return CURLE_SSL_CONNECT_ERROR; 413 } 414 else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3) 415 sni = FALSE; /* SSLv3 has no SNI */ 416 417 /* allocate a cred struct */ 418 rc = gnutls_certificate_allocate_credentials(&conn->ssl[sockindex].cred); 419 if(rc != GNUTLS_E_SUCCESS) { 420 failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc)); 421 return CURLE_SSL_CONNECT_ERROR; 422 } 423 424#ifdef USE_TLS_SRP 425 if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) { 426 infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username); 427 428 rc = gnutls_srp_allocate_client_credentials( 429 &conn->ssl[sockindex].srp_client_cred); 430 if(rc != GNUTLS_E_SUCCESS) { 431 failf(data, "gnutls_srp_allocate_client_cred() failed: %s", 432 gnutls_strerror(rc)); 433 return CURLE_OUT_OF_MEMORY; 434 } 435 436 rc = gnutls_srp_set_client_credentials(conn->ssl[sockindex]. 437 srp_client_cred, 438 data->set.ssl.username, 439 data->set.ssl.password); 440 if(rc != GNUTLS_E_SUCCESS) { 441 failf(data, "gnutls_srp_set_client_cred() failed: %s", 442 gnutls_strerror(rc)); 443 return CURLE_BAD_FUNCTION_ARGUMENT; 444 } 445 } 446#endif 447 448 if(data->set.ssl.CAfile) { 449 /* set the trusted CA cert bundle file */ 450 gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred, 451 GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT); 452 453 rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred, 454 data->set.ssl.CAfile, 455 GNUTLS_X509_FMT_PEM); 456 if(rc < 0) { 457 infof(data, "error reading ca cert file %s (%s)\n", 458 data->set.ssl.CAfile, gnutls_strerror(rc)); 459 if(data->set.ssl.verifypeer) 460 return CURLE_SSL_CACERT_BADFILE; 461 } 462 else 463 infof(data, "found %d certificates in %s\n", 464 rc, data->set.ssl.CAfile); 465 } 466 467 if(data->set.ssl.CRLfile) { 468 /* set the CRL list file */ 469 rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred, 470 data->set.ssl.CRLfile, 471 GNUTLS_X509_FMT_PEM); 472 if(rc < 0) { 473 failf(data, "error reading crl file %s (%s)", 474 data->set.ssl.CRLfile, gnutls_strerror(rc)); 475 return CURLE_SSL_CRL_BADFILE; 476 } 477 else 478 infof(data, "found %d CRL in %s\n", 479 rc, data->set.ssl.CRLfile); 480 } 481 482 /* Initialize TLS session as a client */ 483 rc = gnutls_init(&conn->ssl[sockindex].session, GNUTLS_CLIENT); 484 if(rc != GNUTLS_E_SUCCESS) { 485 failf(data, "gnutls_init() failed: %d", rc); 486 return CURLE_SSL_CONNECT_ERROR; 487 } 488 489 /* convenient assign */ 490 session = conn->ssl[sockindex].session; 491 492 if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) && 493#ifdef ENABLE_IPV6 494 (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) && 495#endif 496 sni && 497 (gnutls_server_name_set(session, GNUTLS_NAME_DNS, conn->host.name, 498 strlen(conn->host.name)) < 0)) 499 infof(data, "WARNING: failed to configure server name indication (SNI) " 500 "TLS extension\n"); 501 502 /* Use default priorities */ 503 rc = gnutls_set_default_priority(session); 504 if(rc != GNUTLS_E_SUCCESS) 505 return CURLE_SSL_CONNECT_ERROR; 506 507#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT 508 rc = gnutls_cipher_set_priority(session, cipher_priority); 509 if(rc != GNUTLS_E_SUCCESS) 510 return CURLE_SSL_CONNECT_ERROR; 511 512 /* Sets the priority on the certificate types supported by gnutls. Priority 513 is higher for types specified before others. After specifying the types 514 you want, you must append a 0. */ 515 rc = gnutls_certificate_type_set_priority(session, cert_type_priority); 516 if(rc != GNUTLS_E_SUCCESS) 517 return CURLE_SSL_CONNECT_ERROR; 518 519 if(data->set.ssl.cipher_list != NULL) { 520 failf(data, "can't pass a custom cipher list to older GnuTLS" 521 " versions"); 522 return CURLE_SSL_CONNECT_ERROR; 523 } 524 525 switch (data->set.ssl.version) { 526 case CURL_SSLVERSION_SSLv3: 527 protocol_priority[0] = GNUTLS_SSL3; 528 break; 529 case CURL_SSLVERSION_DEFAULT: 530 case CURL_SSLVERSION_TLSv1: 531 protocol_priority[0] = GNUTLS_TLS1_0; 532 protocol_priority[1] = GNUTLS_TLS1_1; 533 protocol_priority[2] = GNUTLS_TLS1_2; 534 break; 535 case CURL_SSLVERSION_TLSv1_0: 536 protocol_priority[0] = GNUTLS_TLS1_0; 537 break; 538 case CURL_SSLVERSION_TLSv1_1: 539 protocol_priority[0] = GNUTLS_TLS1_1; 540 break; 541 case CURL_SSLVERSION_TLSv1_2: 542 protocol_priority[0] = GNUTLS_TLS1_2; 543 break; 544 case CURL_SSLVERSION_SSLv2: 545 default: 546 failf(data, "GnuTLS does not support SSLv2"); 547 return CURLE_SSL_CONNECT_ERROR; 548 break; 549 } 550 rc = gnutls_protocol_set_priority(session, protocol_priority); 551 if(rc != GNUTLS_E_SUCCESS) { 552 failf(data, "Did you pass a valid GnuTLS cipher list?"); 553 return CURLE_SSL_CONNECT_ERROR; 554 } 555 556#else 557 /* Ensure +SRP comes at the *end* of all relevant strings so that it can be 558 * removed if a run-time error indicates that SRP is not supported by this 559 * GnuTLS version */ 560 switch (data->set.ssl.version) { 561 case CURL_SSLVERSION_SSLv3: 562 prioritylist = GNUTLS_CIPHERS ":-VERS-TLS-ALL:+VERS-SSL3.0"; 563 sni = false; 564 break; 565 case CURL_SSLVERSION_DEFAULT: 566 case CURL_SSLVERSION_TLSv1: 567 prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:" GNUTLS_SRP; 568 break; 569 case CURL_SSLVERSION_TLSv1_0: 570 prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" 571 "+VERS-TLS1.0:" GNUTLS_SRP; 572 break; 573 case CURL_SSLVERSION_TLSv1_1: 574 prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" 575 "+VERS-TLS1.1:" GNUTLS_SRP; 576 break; 577 case CURL_SSLVERSION_TLSv1_2: 578 prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" 579 "+VERS-TLS1.2:" GNUTLS_SRP; 580 break; 581 case CURL_SSLVERSION_SSLv2: 582 default: 583 failf(data, "GnuTLS does not support SSLv2"); 584 return CURLE_SSL_CONNECT_ERROR; 585 break; 586 } 587 rc = gnutls_priority_set_direct(session, prioritylist, &err); 588 if((rc == GNUTLS_E_INVALID_REQUEST) && err) { 589 if(!strcmp(err, GNUTLS_SRP)) { 590 /* This GnuTLS was probably compiled without support for SRP. 591 * Note that fact and try again without it. */ 592 int validprioritylen = curlx_uztosi(err - prioritylist); 593 char *prioritycopy = strdup(prioritylist); 594 if(!prioritycopy) 595 return CURLE_OUT_OF_MEMORY; 596 597 infof(data, "This GnuTLS does not support SRP\n"); 598 if(validprioritylen) 599 /* Remove the :+SRP */ 600 prioritycopy[validprioritylen - 1] = 0; 601 rc = gnutls_priority_set_direct(session, prioritycopy, &err); 602 free(prioritycopy); 603 } 604 } 605 if(rc != GNUTLS_E_SUCCESS) { 606 failf(data, "Error %d setting GnuTLS cipher list starting with %s", 607 rc, err); 608 return CURLE_SSL_CONNECT_ERROR; 609 } 610#endif 611 612#ifdef HAS_ALPN 613 if(data->set.httpversion == CURL_HTTP_VERSION_2_0) { 614 if(data->set.ssl_enable_alpn) { 615 protocols[0].data = NGHTTP2_PROTO_VERSION_ID; 616 protocols[0].size = NGHTTP2_PROTO_VERSION_ID_LEN; 617 protocols[1].data = ALPN_HTTP_1_1; 618 protocols[1].size = ALPN_HTTP_1_1_LENGTH; 619 gnutls_alpn_set_protocols(session, protocols, protocols_size, 0); 620 infof(data, "ALPN, offering %s, %s\n", NGHTTP2_PROTO_VERSION_ID, 621 ALPN_HTTP_1_1); 622 } 623 else { 624 infof(data, "SSL, can't negotiate HTTP/2.0 without ALPN\n"); 625 } 626 } 627#endif 628 629 if(data->set.str[STRING_CERT]) { 630 if(gnutls_certificate_set_x509_key_file( 631 conn->ssl[sockindex].cred, 632 data->set.str[STRING_CERT], 633 data->set.str[STRING_KEY] ? 634 data->set.str[STRING_KEY] : data->set.str[STRING_CERT], 635 do_file_type(data->set.str[STRING_CERT_TYPE]) ) != 636 GNUTLS_E_SUCCESS) { 637 failf(data, "error reading X.509 key or certificate file"); 638 return CURLE_SSL_CONNECT_ERROR; 639 } 640 } 641 642#ifdef USE_TLS_SRP 643 /* put the credentials to the current session */ 644 if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) { 645 rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP, 646 conn->ssl[sockindex].srp_client_cred); 647 if(rc != GNUTLS_E_SUCCESS) 648 failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc)); 649 } 650 else 651#endif 652 rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, 653 conn->ssl[sockindex].cred); 654 655 /* set the connection handle (file descriptor for the socket) */ 656 gnutls_transport_set_ptr(session, 657 GNUTLS_INT_TO_POINTER_CAST(conn->sock[sockindex])); 658 659 /* register callback functions to send and receive data. */ 660 gnutls_transport_set_push_function(session, Curl_gtls_push); 661 gnutls_transport_set_pull_function(session, Curl_gtls_pull); 662 663 /* lowat must be set to zero when using custom push and pull functions. */ 664 gnutls_transport_set_lowat(session, 0); 665 666 /* This might be a reconnect, so we check for a session ID in the cache 667 to speed up things */ 668 669 if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize)) { 670 /* we got a session id, use it! */ 671 gnutls_session_set_data(session, ssl_sessionid, ssl_idsize); 672 673 /* Informational message */ 674 infof (data, "SSL re-using session ID\n"); 675 } 676 677 return CURLE_OK; 678} 679 680static Curl_recv gtls_recv; 681static Curl_send gtls_send; 682 683static CURLcode 684gtls_connect_step3(struct connectdata *conn, 685 int sockindex) 686{ 687 unsigned int cert_list_size; 688 const gnutls_datum_t *chainp; 689 unsigned int verify_status; 690 gnutls_x509_crt_t x509_cert,x509_issuer; 691 gnutls_datum_t issuerp; 692 char certbuf[256] = ""; /* big enough? */ 693 size_t size; 694 unsigned int algo; 695 unsigned int bits; 696 time_t certclock; 697 const char *ptr; 698 struct SessionHandle *data = conn->data; 699 gnutls_session_t session = conn->ssl[sockindex].session; 700 int rc; 701 int incache; 702 void *ssl_sessionid; 703#ifdef HAS_ALPN 704 gnutls_datum_t proto; 705#endif 706 CURLcode result = CURLE_OK; 707 708 /* This function will return the peer's raw certificate (chain) as sent by 709 the peer. These certificates are in raw format (DER encoded for 710 X.509). In case of a X.509 then a certificate list may be present. The 711 first certificate in the list is the peer's certificate, following the 712 issuer's certificate, then the issuer's issuer etc. */ 713 714 chainp = gnutls_certificate_get_peers(session, &cert_list_size); 715 if(!chainp) { 716 if(data->set.ssl.verifypeer || 717 data->set.ssl.verifyhost || 718 data->set.ssl.issuercert) { 719#ifdef USE_TLS_SRP 720 if(data->set.ssl.authtype == CURL_TLSAUTH_SRP 721 && data->set.ssl.username != NULL 722 && !data->set.ssl.verifypeer 723 && gnutls_cipher_get(session)) { 724 /* no peer cert, but auth is ok if we have SRP user and cipher and no 725 peer verify */ 726 } 727 else { 728#endif 729 failf(data, "failed to get server cert"); 730 return CURLE_PEER_FAILED_VERIFICATION; 731#ifdef USE_TLS_SRP 732 } 733#endif 734 } 735 infof(data, "\t common name: WARNING couldn't obtain\n"); 736 } 737 738 if(data->set.ssl.verifypeer) { 739 /* This function will try to verify the peer's certificate and return its 740 status (trusted, invalid etc.). The value of status should be one or 741 more of the gnutls_certificate_status_t enumerated elements bitwise 742 or'd. To avoid denial of service attacks some default upper limits 743 regarding the certificate key size and chain size are set. To override 744 them use gnutls_certificate_set_verify_limits(). */ 745 746 rc = gnutls_certificate_verify_peers2(session, &verify_status); 747 if(rc < 0) { 748 failf(data, "server cert verify failed: %d", rc); 749 return CURLE_SSL_CONNECT_ERROR; 750 } 751 752 /* verify_status is a bitmask of gnutls_certificate_status bits */ 753 if(verify_status & GNUTLS_CERT_INVALID) { 754 if(data->set.ssl.verifypeer) { 755 failf(data, "server certificate verification failed. CAfile: %s " 756 "CRLfile: %s", data->set.ssl.CAfile?data->set.ssl.CAfile:"none", 757 data->set.ssl.CRLfile?data->set.ssl.CRLfile:"none"); 758 return CURLE_SSL_CACERT; 759 } 760 else 761 infof(data, "\t server certificate verification FAILED\n"); 762 } 763 else 764 infof(data, "\t server certificate verification OK\n"); 765 } 766 else 767 infof(data, "\t server certificate verification SKIPPED\n"); 768 769 /* initialize an X.509 certificate structure. */ 770 gnutls_x509_crt_init(&x509_cert); 771 772 if(chainp) 773 /* convert the given DER or PEM encoded Certificate to the native 774 gnutls_x509_crt_t format */ 775 gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER); 776 777 if(data->set.ssl.issuercert) { 778 gnutls_x509_crt_init(&x509_issuer); 779 issuerp = load_file(data->set.ssl.issuercert); 780 gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM); 781 rc = gnutls_x509_crt_check_issuer(x509_cert,x509_issuer); 782 unload_file(issuerp); 783 if(rc <= 0) { 784 failf(data, "server certificate issuer check failed (IssuerCert: %s)", 785 data->set.ssl.issuercert?data->set.ssl.issuercert:"none"); 786 return CURLE_SSL_ISSUER_ERROR; 787 } 788 infof(data,"\t server certificate issuer check OK (Issuer Cert: %s)\n", 789 data->set.ssl.issuercert?data->set.ssl.issuercert:"none"); 790 } 791 792 size=sizeof(certbuf); 793 rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME, 794 0, /* the first and only one */ 795 FALSE, 796 certbuf, 797 &size); 798 if(rc) { 799 infof(data, "error fetching CN from cert:%s\n", 800 gnutls_strerror(rc)); 801 } 802 803 /* This function will check if the given certificate's subject matches the 804 given hostname. This is a basic implementation of the matching described 805 in RFC2818 (HTTPS), which takes into account wildcards, and the subject 806 alternative name PKIX extension. Returns non zero on success, and zero on 807 failure. */ 808 rc = gnutls_x509_crt_check_hostname(x509_cert, conn->host.name); 809#if GNUTLS_VERSION_NUMBER < 0x030306 810 /* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP 811 addresses. */ 812 if(!rc) { 813#ifdef ENABLE_IPV6 814 #define use_addr in6_addr 815#else 816 #define use_addr in_addr 817#endif 818 unsigned char addrbuf[sizeof(struct use_addr)]; 819 unsigned char certaddr[sizeof(struct use_addr)]; 820 size_t addrlen = 0, certaddrlen; 821 int i; 822 int ret = 0; 823 824 if(Curl_inet_pton(AF_INET, conn->host.name, addrbuf) > 0) 825 addrlen = 4; 826#ifdef ENABLE_IPV6 827 else if(Curl_inet_pton(AF_INET6, conn->host.name, addrbuf) > 0) 828 addrlen = 16; 829#endif 830 831 if(addrlen) { 832 for(i=0; ; i++) { 833 certaddrlen = sizeof(certaddr); 834 ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr, 835 &certaddrlen, NULL); 836 /* If this happens, it wasn't an IP address. */ 837 if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER) 838 continue; 839 if(ret < 0) 840 break; 841 if(ret != GNUTLS_SAN_IPADDRESS) 842 continue; 843 if(certaddrlen == addrlen && !memcmp(addrbuf, certaddr, addrlen)) { 844 rc = 1; 845 break; 846 } 847 } 848 } 849 } 850#endif 851 if(!rc) { 852 if(data->set.ssl.verifyhost) { 853 failf(data, "SSL: certificate subject name (%s) does not match " 854 "target host name '%s'", certbuf, conn->host.dispname); 855 gnutls_x509_crt_deinit(x509_cert); 856 return CURLE_PEER_FAILED_VERIFICATION; 857 } 858 else 859 infof(data, "\t common name: %s (does not match '%s')\n", 860 certbuf, conn->host.dispname); 861 } 862 else 863 infof(data, "\t common name: %s (matched)\n", certbuf); 864 865 /* Check for time-based validity */ 866 certclock = gnutls_x509_crt_get_expiration_time(x509_cert); 867 868 if(certclock == (time_t)-1) { 869 if(data->set.ssl.verifypeer) { 870 failf(data, "server cert expiration date verify failed"); 871 return CURLE_SSL_CONNECT_ERROR; 872 } 873 else 874 infof(data, "\t server certificate expiration date verify FAILED\n"); 875 } 876 else { 877 if(certclock < time(NULL)) { 878 if(data->set.ssl.verifypeer) { 879 failf(data, "server certificate expiration date has passed."); 880 return CURLE_PEER_FAILED_VERIFICATION; 881 } 882 else 883 infof(data, "\t server certificate expiration date FAILED\n"); 884 } 885 else 886 infof(data, "\t server certificate expiration date OK\n"); 887 } 888 889 certclock = gnutls_x509_crt_get_activation_time(x509_cert); 890 891 if(certclock == (time_t)-1) { 892 if(data->set.ssl.verifypeer) { 893 failf(data, "server cert activation date verify failed"); 894 return CURLE_SSL_CONNECT_ERROR; 895 } 896 else 897 infof(data, "\t server certificate activation date verify FAILED\n"); 898 } 899 else { 900 if(certclock > time(NULL)) { 901 if(data->set.ssl.verifypeer) { 902 failf(data, "server certificate not activated yet."); 903 return CURLE_PEER_FAILED_VERIFICATION; 904 } 905 else 906 infof(data, "\t server certificate activation date FAILED\n"); 907 } 908 else 909 infof(data, "\t server certificate activation date OK\n"); 910 } 911 912 /* Show: 913 914 - ciphers used 915 - subject 916 - start date 917 - expire date 918 - common name 919 - issuer 920 921 */ 922 923 /* public key algorithm's parameters */ 924 algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits); 925 infof(data, "\t certificate public key: %s\n", 926 gnutls_pk_algorithm_get_name(algo)); 927 928 /* version of the X.509 certificate. */ 929 infof(data, "\t certificate version: #%d\n", 930 gnutls_x509_crt_get_version(x509_cert)); 931 932 933 size = sizeof(certbuf); 934 gnutls_x509_crt_get_dn(x509_cert, certbuf, &size); 935 infof(data, "\t subject: %s\n", certbuf); 936 937 certclock = gnutls_x509_crt_get_activation_time(x509_cert); 938 showtime(data, "start date", certclock); 939 940 certclock = gnutls_x509_crt_get_expiration_time(x509_cert); 941 showtime(data, "expire date", certclock); 942 943 size = sizeof(certbuf); 944 gnutls_x509_crt_get_issuer_dn(x509_cert, certbuf, &size); 945 infof(data, "\t issuer: %s\n", certbuf); 946 947 gnutls_x509_crt_deinit(x509_cert); 948 949 /* compression algorithm (if any) */ 950 ptr = gnutls_compression_get_name(gnutls_compression_get(session)); 951 /* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */ 952 infof(data, "\t compression: %s\n", ptr); 953 954 /* the name of the cipher used. ie 3DES. */ 955 ptr = gnutls_cipher_get_name(gnutls_cipher_get(session)); 956 infof(data, "\t cipher: %s\n", ptr); 957 958 /* the MAC algorithms name. ie SHA1 */ 959 ptr = gnutls_mac_get_name(gnutls_mac_get(session)); 960 infof(data, "\t MAC: %s\n", ptr); 961 962#ifdef HAS_ALPN 963 if(data->set.ssl_enable_alpn) { 964 rc = gnutls_alpn_get_selected_protocol(session, &proto); 965 if(rc == 0) { 966 infof(data, "ALPN, server accepted to use %.*s\n", proto.size, 967 proto.data); 968 969 if(proto.size == NGHTTP2_PROTO_VERSION_ID_LEN && 970 memcmp(NGHTTP2_PROTO_VERSION_ID, proto.data, 971 NGHTTP2_PROTO_VERSION_ID_LEN) == 0) { 972 conn->negnpn = NPN_HTTP2; 973 } 974 else if(proto.size == ALPN_HTTP_1_1_LENGTH && memcmp(ALPN_HTTP_1_1, 975 proto.data, ALPN_HTTP_1_1_LENGTH) == 0) { 976 conn->negnpn = NPN_HTTP1_1; 977 } 978 } 979 else { 980 infof(data, "ALPN, server did not agree to a protocol\n"); 981 } 982 } 983#endif 984 985 conn->ssl[sockindex].state = ssl_connection_complete; 986 conn->recv[sockindex] = gtls_recv; 987 conn->send[sockindex] = gtls_send; 988 989 { 990 /* we always unconditionally get the session id here, as even if we 991 already got it from the cache and asked to use it in the connection, it 992 might've been rejected and then a new one is in use now and we need to 993 detect that. */ 994 void *connect_sessionid; 995 size_t connect_idsize = 0; 996 997 /* get the session ID data size */ 998 gnutls_session_get_data(session, NULL, &connect_idsize); 999 connect_sessionid = malloc(connect_idsize); /* get a buffer for it */ 1000 1001 if(connect_sessionid) { 1002 /* extract session ID to the allocated buffer */ 1003 gnutls_session_get_data(session, connect_sessionid, &connect_idsize); 1004 1005 incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)); 1006 if(incache) { 1007 /* there was one before in the cache, so instead of risking that the 1008 previous one was rejected, we just kill that and store the new */ 1009 Curl_ssl_delsessionid(conn, ssl_sessionid); 1010 } 1011 1012 /* store this session id */ 1013 result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize); 1014 if(result) { 1015 free(connect_sessionid); 1016 result = CURLE_OUT_OF_MEMORY; 1017 } 1018 } 1019 else 1020 result = CURLE_OUT_OF_MEMORY; 1021 } 1022 1023 return result; 1024} 1025 1026 1027/* 1028 * This function is called after the TCP connect has completed. Setup the TLS 1029 * layer and do all necessary magic. 1030 */ 1031/* We use connssl->connecting_state to keep track of the connection status; 1032 there are three states: 'ssl_connect_1' (not started yet or complete), 1033 'ssl_connect_2_reading' (waiting for data from server), and 1034 'ssl_connect_2_writing' (waiting to be able to write). 1035 */ 1036static CURLcode 1037gtls_connect_common(struct connectdata *conn, 1038 int sockindex, 1039 bool nonblocking, 1040 bool *done) 1041{ 1042 int rc; 1043 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 1044 1045 /* Initiate the connection, if not already done */ 1046 if(ssl_connect_1==connssl->connecting_state) { 1047 rc = gtls_connect_step1 (conn, sockindex); 1048 if(rc) 1049 return rc; 1050 } 1051 1052 rc = handshake(conn, sockindex, TRUE, nonblocking); 1053 if(rc) 1054 /* handshake() sets its own error message with failf() */ 1055 return rc; 1056 1057 /* Finish connecting once the handshake is done */ 1058 if(ssl_connect_1==connssl->connecting_state) { 1059 rc = gtls_connect_step3(conn, sockindex); 1060 if(rc) 1061 return rc; 1062 } 1063 1064 *done = ssl_connect_1==connssl->connecting_state; 1065 1066 return CURLE_OK; 1067} 1068 1069CURLcode 1070Curl_gtls_connect_nonblocking(struct connectdata *conn, 1071 int sockindex, 1072 bool *done) 1073{ 1074 return gtls_connect_common(conn, sockindex, TRUE, done); 1075} 1076 1077CURLcode 1078Curl_gtls_connect(struct connectdata *conn, 1079 int sockindex) 1080 1081{ 1082 CURLcode retcode; 1083 bool done = FALSE; 1084 1085 retcode = gtls_connect_common(conn, sockindex, FALSE, &done); 1086 if(retcode) 1087 return retcode; 1088 1089 DEBUGASSERT(done); 1090 1091 return CURLE_OK; 1092} 1093 1094static ssize_t gtls_send(struct connectdata *conn, 1095 int sockindex, 1096 const void *mem, 1097 size_t len, 1098 CURLcode *curlcode) 1099{ 1100 ssize_t rc = gnutls_record_send(conn->ssl[sockindex].session, mem, len); 1101 1102 if(rc < 0 ) { 1103 *curlcode = (rc == GNUTLS_E_AGAIN) 1104 ? CURLE_AGAIN 1105 : CURLE_SEND_ERROR; 1106 1107 rc = -1; 1108 } 1109 1110 return rc; 1111} 1112 1113void Curl_gtls_close_all(struct SessionHandle *data) 1114{ 1115 /* FIX: make the OpenSSL code more generic and use parts of it here */ 1116 (void)data; 1117} 1118 1119static void close_one(struct connectdata *conn, 1120 int idx) 1121{ 1122 if(conn->ssl[idx].session) { 1123 gnutls_bye(conn->ssl[idx].session, GNUTLS_SHUT_RDWR); 1124 gnutls_deinit(conn->ssl[idx].session); 1125 conn->ssl[idx].session = NULL; 1126 } 1127 if(conn->ssl[idx].cred) { 1128 gnutls_certificate_free_credentials(conn->ssl[idx].cred); 1129 conn->ssl[idx].cred = NULL; 1130 } 1131#ifdef USE_TLS_SRP 1132 if(conn->ssl[idx].srp_client_cred) { 1133 gnutls_srp_free_client_credentials(conn->ssl[idx].srp_client_cred); 1134 conn->ssl[idx].srp_client_cred = NULL; 1135 } 1136#endif 1137} 1138 1139void Curl_gtls_close(struct connectdata *conn, int sockindex) 1140{ 1141 close_one(conn, sockindex); 1142} 1143 1144/* 1145 * This function is called to shut down the SSL layer but keep the 1146 * socket open (CCC - Clear Command Channel) 1147 */ 1148int Curl_gtls_shutdown(struct connectdata *conn, int sockindex) 1149{ 1150 ssize_t result; 1151 int retval = 0; 1152 struct SessionHandle *data = conn->data; 1153 int done = 0; 1154 char buf[120]; 1155 1156 /* This has only been tested on the proftpd server, and the mod_tls code 1157 sends a close notify alert without waiting for a close notify alert in 1158 response. Thus we wait for a close notify alert from the server, but 1159 we do not send one. Let's hope other servers do the same... */ 1160 1161 if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE) 1162 gnutls_bye(conn->ssl[sockindex].session, GNUTLS_SHUT_WR); 1163 1164 if(conn->ssl[sockindex].session) { 1165 while(!done) { 1166 int what = Curl_socket_ready(conn->sock[sockindex], 1167 CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT); 1168 if(what > 0) { 1169 /* Something to read, let's do it and hope that it is the close 1170 notify alert from the server */ 1171 result = gnutls_record_recv(conn->ssl[sockindex].session, 1172 buf, sizeof(buf)); 1173 switch(result) { 1174 case 0: 1175 /* This is the expected response. There was no data but only 1176 the close notify alert */ 1177 done = 1; 1178 break; 1179 case GNUTLS_E_AGAIN: 1180 case GNUTLS_E_INTERRUPTED: 1181 infof(data, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED\n"); 1182 break; 1183 default: 1184 retval = -1; 1185 done = 1; 1186 break; 1187 } 1188 } 1189 else if(0 == what) { 1190 /* timeout */ 1191 failf(data, "SSL shutdown timeout"); 1192 done = 1; 1193 break; 1194 } 1195 else { 1196 /* anything that gets here is fatally bad */ 1197 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); 1198 retval = -1; 1199 done = 1; 1200 } 1201 } 1202 gnutls_deinit(conn->ssl[sockindex].session); 1203 } 1204 gnutls_certificate_free_credentials(conn->ssl[sockindex].cred); 1205 1206#ifdef USE_TLS_SRP 1207 if(data->set.ssl.authtype == CURL_TLSAUTH_SRP 1208 && data->set.ssl.username != NULL) 1209 gnutls_srp_free_client_credentials(conn->ssl[sockindex].srp_client_cred); 1210#endif 1211 1212 conn->ssl[sockindex].cred = NULL; 1213 conn->ssl[sockindex].session = NULL; 1214 1215 return retval; 1216} 1217 1218static ssize_t gtls_recv(struct connectdata *conn, /* connection data */ 1219 int num, /* socketindex */ 1220 char *buf, /* store read data here */ 1221 size_t buffersize, /* max amount to read */ 1222 CURLcode *curlcode) 1223{ 1224 ssize_t ret; 1225 1226 ret = gnutls_record_recv(conn->ssl[num].session, buf, buffersize); 1227 if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) { 1228 *curlcode = CURLE_AGAIN; 1229 return -1; 1230 } 1231 1232 if(ret == GNUTLS_E_REHANDSHAKE) { 1233 /* BLOCKING call, this is bad but a work-around for now. Fixing this "the 1234 proper way" takes a whole lot of work. */ 1235 CURLcode rc = handshake(conn, num, FALSE, FALSE); 1236 if(rc) 1237 /* handshake() writes error message on its own */ 1238 *curlcode = rc; 1239 else 1240 *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */ 1241 return -1; 1242 } 1243 1244 if(ret < 0) { 1245 failf(conn->data, "GnuTLS recv error (%d): %s", 1246 (int)ret, gnutls_strerror((int)ret)); 1247 *curlcode = CURLE_RECV_ERROR; 1248 return -1; 1249 } 1250 1251 return ret; 1252} 1253 1254void Curl_gtls_session_free(void *ptr) 1255{ 1256 free(ptr); 1257} 1258 1259size_t Curl_gtls_version(char *buffer, size_t size) 1260{ 1261 return snprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL)); 1262} 1263 1264int Curl_gtls_seed(struct SessionHandle *data) 1265{ 1266 /* we have the "SSL is seeded" boolean static to prevent multiple 1267 time-consuming seedings in vain */ 1268 static bool ssl_seeded = FALSE; 1269 1270 /* Quickly add a bit of entropy */ 1271#ifndef USE_GNUTLS_NETTLE 1272 gcry_fast_random_poll(); 1273#endif 1274 1275 if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] || 1276 data->set.str[STRING_SSL_EGDSOCKET]) { 1277 1278 /* TODO: to a good job seeding the RNG 1279 This may involve the gcry_control function and these options: 1280 GCRYCTL_SET_RANDOM_SEED_FILE 1281 GCRYCTL_SET_RNDEGD_SOCKET 1282 */ 1283 ssl_seeded = TRUE; 1284 } 1285 return 0; 1286} 1287 1288void Curl_gtls_random(struct SessionHandle *data, 1289 unsigned char *entropy, 1290 size_t length) 1291{ 1292#if defined(USE_GNUTLS_NETTLE) 1293 (void)data; 1294 gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length); 1295#elif defined(USE_GNUTLS) 1296 Curl_gtls_seed(data); /* Initiate the seed if not already done */ 1297 gcry_randomize(entropy, length, GCRY_STRONG_RANDOM); 1298#endif 1299} 1300 1301void Curl_gtls_md5sum(unsigned char *tmp, /* input */ 1302 size_t tmplen, 1303 unsigned char *md5sum, /* output */ 1304 size_t md5len) 1305{ 1306#if defined(USE_GNUTLS_NETTLE) 1307 struct md5_ctx MD5pw; 1308 md5_init(&MD5pw); 1309 md5_update(&MD5pw, (unsigned int)tmplen, tmp); 1310 md5_digest(&MD5pw, (unsigned int)md5len, md5sum); 1311#elif defined(USE_GNUTLS) 1312 gcry_md_hd_t MD5pw; 1313 gcry_md_open(&MD5pw, GCRY_MD_MD5, 0); 1314 gcry_md_write(MD5pw, tmp, tmplen); 1315 memcpy(md5sum, gcry_md_read (MD5pw, 0), md5len); 1316 gcry_md_close(MD5pw); 1317#endif 1318} 1319 1320#endif /* USE_GNUTLS */ 1321