1 /* 2 * QEMU crypto TLS session support 3 * 4 * Copyright (c) 2015 Red Hat, Inc. 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18 * 19 */ 20 21 #include "qemu/osdep.h" 22 #include "qemu/error-report.h" 23 #include "qemu/thread.h" 24 #include "crypto/tlssession.h" 25 #include "crypto/tlscredsanon.h" 26 #include "crypto/tlscredspsk.h" 27 #include "crypto/tlscredsx509.h" 28 #include "qapi/error.h" 29 #include "authz/base.h" 30 #include "tlscredspriv.h" 31 #include "trace.h" 32 33 #ifdef CONFIG_GNUTLS 34 35 36 #include <gnutls/x509.h> 37 38 39 struct QCryptoTLSSession { 40 QCryptoTLSCreds *creds; 41 gnutls_session_t handle; 42 char *hostname; 43 char *authzid; 44 bool handshakeComplete; 45 QCryptoTLSSessionWriteFunc writeFunc; 46 QCryptoTLSSessionReadFunc readFunc; 47 void *opaque; 48 char *peername; 49 50 /* 51 * Allow concurrent reads and writes, so track 52 * errors separately 53 */ 54 Error *rerr; 55 Error *werr; 56 57 /* 58 * Used to protect against broken GNUTLS thread safety 59 * https://gitlab.com/gnutls/gnutls/-/issues/1717 60 */ 61 bool requireThreadSafety; 62 bool lockEnabled; 63 QemuMutex lock; 64 }; 65 66 67 void 68 qcrypto_tls_session_free(QCryptoTLSSession *session) 69 { 70 if (!session) { 71 return; 72 } 73 74 error_free(session->rerr); 75 error_free(session->werr); 76 77 gnutls_deinit(session->handle); 78 g_free(session->hostname); 79 g_free(session->peername); 80 g_free(session->authzid); 81 object_unref(OBJECT(session->creds)); 82 qemu_mutex_destroy(&session->lock); 83 g_free(session); 84 } 85 86 87 static ssize_t 88 qcrypto_tls_session_push(void *opaque, const void *buf, size_t len) 89 { 90 QCryptoTLSSession *session = opaque; 91 ssize_t ret; 92 93 if (!session->writeFunc) { 94 errno = EIO; 95 return -1; 96 }; 97 98 if (session->lockEnabled) { 99 qemu_mutex_unlock(&session->lock); 100 } 101 102 error_free(session->werr); 103 session->werr = NULL; 104 105 ret = session->writeFunc(buf, len, session->opaque, &session->werr); 106 107 if (session->lockEnabled) { 108 qemu_mutex_lock(&session->lock); 109 } 110 111 if (ret == QCRYPTO_TLS_SESSION_ERR_BLOCK) { 112 errno = EAGAIN; 113 return -1; 114 } else if (ret < 0) { 115 errno = EIO; 116 return -1; 117 } else { 118 return ret; 119 } 120 } 121 122 123 static ssize_t 124 qcrypto_tls_session_pull(void *opaque, void *buf, size_t len) 125 { 126 QCryptoTLSSession *session = opaque; 127 ssize_t ret; 128 129 if (!session->readFunc) { 130 errno = EIO; 131 return -1; 132 }; 133 134 error_free(session->rerr); 135 session->rerr = NULL; 136 137 if (session->lockEnabled) { 138 qemu_mutex_unlock(&session->lock); 139 } 140 141 ret = session->readFunc(buf, len, session->opaque, &session->rerr); 142 143 if (session->lockEnabled) { 144 qemu_mutex_lock(&session->lock); 145 } 146 147 if (ret == QCRYPTO_TLS_SESSION_ERR_BLOCK) { 148 errno = EAGAIN; 149 return -1; 150 } else if (ret < 0) { 151 errno = EIO; 152 return -1; 153 } else { 154 return ret; 155 } 156 } 157 158 #define TLS_PRIORITY_ADDITIONAL_ANON "+ANON-DH" 159 #define TLS_PRIORITY_ADDITIONAL_PSK "+ECDHE-PSK:+DHE-PSK:+PSK" 160 161 QCryptoTLSSession * 162 qcrypto_tls_session_new(QCryptoTLSCreds *creds, 163 const char *hostname, 164 const char *authzid, 165 QCryptoTLSCredsEndpoint endpoint, 166 Error **errp) 167 { 168 QCryptoTLSSession *session; 169 int ret; 170 171 session = g_new0(QCryptoTLSSession, 1); 172 trace_qcrypto_tls_session_new( 173 session, creds, hostname ? hostname : "<none>", 174 authzid ? authzid : "<none>", endpoint); 175 176 if (hostname) { 177 session->hostname = g_strdup(hostname); 178 } 179 if (authzid) { 180 session->authzid = g_strdup(authzid); 181 } 182 session->creds = creds; 183 object_ref(OBJECT(creds)); 184 185 qemu_mutex_init(&session->lock); 186 187 if (creds->endpoint != endpoint) { 188 error_setg(errp, "Credentials endpoint doesn't match session"); 189 goto error; 190 } 191 192 if (endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) { 193 ret = gnutls_init(&session->handle, GNUTLS_SERVER); 194 } else { 195 ret = gnutls_init(&session->handle, GNUTLS_CLIENT); 196 } 197 if (ret < 0) { 198 error_setg(errp, "Cannot initialize TLS session: %s", 199 gnutls_strerror(ret)); 200 goto error; 201 } 202 203 if (object_dynamic_cast(OBJECT(creds), 204 TYPE_QCRYPTO_TLS_CREDS_ANON)) { 205 QCryptoTLSCredsAnon *acreds = QCRYPTO_TLS_CREDS_ANON(creds); 206 char *prio; 207 208 if (creds->priority != NULL) { 209 prio = g_strdup_printf("%s:%s", 210 creds->priority, 211 TLS_PRIORITY_ADDITIONAL_ANON); 212 } else { 213 prio = g_strdup(CONFIG_TLS_PRIORITY ":" 214 TLS_PRIORITY_ADDITIONAL_ANON); 215 } 216 217 ret = gnutls_priority_set_direct(session->handle, prio, NULL); 218 if (ret < 0) { 219 error_setg(errp, "Unable to set TLS session priority %s: %s", 220 prio, gnutls_strerror(ret)); 221 g_free(prio); 222 goto error; 223 } 224 g_free(prio); 225 if (creds->endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) { 226 ret = gnutls_credentials_set(session->handle, 227 GNUTLS_CRD_ANON, 228 acreds->data.server); 229 } else { 230 ret = gnutls_credentials_set(session->handle, 231 GNUTLS_CRD_ANON, 232 acreds->data.client); 233 } 234 if (ret < 0) { 235 error_setg(errp, "Cannot set session credentials: %s", 236 gnutls_strerror(ret)); 237 goto error; 238 } 239 } else if (object_dynamic_cast(OBJECT(creds), 240 TYPE_QCRYPTO_TLS_CREDS_PSK)) { 241 QCryptoTLSCredsPSK *pcreds = QCRYPTO_TLS_CREDS_PSK(creds); 242 char *prio; 243 244 if (creds->priority != NULL) { 245 prio = g_strdup_printf("%s:%s", 246 creds->priority, 247 TLS_PRIORITY_ADDITIONAL_PSK); 248 } else { 249 prio = g_strdup(CONFIG_TLS_PRIORITY ":" 250 TLS_PRIORITY_ADDITIONAL_PSK); 251 } 252 253 ret = gnutls_priority_set_direct(session->handle, prio, NULL); 254 if (ret < 0) { 255 error_setg(errp, "Unable to set TLS session priority %s: %s", 256 prio, gnutls_strerror(ret)); 257 g_free(prio); 258 goto error; 259 } 260 g_free(prio); 261 if (creds->endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) { 262 ret = gnutls_credentials_set(session->handle, 263 GNUTLS_CRD_PSK, 264 pcreds->data.server); 265 } else { 266 ret = gnutls_credentials_set(session->handle, 267 GNUTLS_CRD_PSK, 268 pcreds->data.client); 269 } 270 if (ret < 0) { 271 error_setg(errp, "Cannot set session credentials: %s", 272 gnutls_strerror(ret)); 273 goto error; 274 } 275 } else if (object_dynamic_cast(OBJECT(creds), 276 TYPE_QCRYPTO_TLS_CREDS_X509)) { 277 QCryptoTLSCredsX509 *tcreds = QCRYPTO_TLS_CREDS_X509(creds); 278 const char *prio = creds->priority; 279 if (!prio) { 280 prio = CONFIG_TLS_PRIORITY; 281 } 282 283 ret = gnutls_priority_set_direct(session->handle, prio, NULL); 284 if (ret < 0) { 285 error_setg(errp, "Cannot set default TLS session priority %s: %s", 286 prio, gnutls_strerror(ret)); 287 goto error; 288 } 289 ret = gnutls_credentials_set(session->handle, 290 GNUTLS_CRD_CERTIFICATE, 291 tcreds->data); 292 if (ret < 0) { 293 error_setg(errp, "Cannot set session credentials: %s", 294 gnutls_strerror(ret)); 295 goto error; 296 } 297 298 if (creds->endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) { 299 /* This requests, but does not enforce a client cert. 300 * The cert checking code later does enforcement */ 301 gnutls_certificate_server_set_request(session->handle, 302 GNUTLS_CERT_REQUEST); 303 } 304 } else { 305 error_setg(errp, "Unsupported TLS credentials type %s", 306 object_get_typename(OBJECT(creds))); 307 goto error; 308 } 309 310 gnutls_transport_set_ptr(session->handle, session); 311 gnutls_transport_set_push_function(session->handle, 312 qcrypto_tls_session_push); 313 gnutls_transport_set_pull_function(session->handle, 314 qcrypto_tls_session_pull); 315 316 return session; 317 318 error: 319 qcrypto_tls_session_free(session); 320 return NULL; 321 } 322 323 void qcrypto_tls_session_require_thread_safety(QCryptoTLSSession *sess) 324 { 325 sess->requireThreadSafety = true; 326 } 327 328 static int 329 qcrypto_tls_session_check_certificate(QCryptoTLSSession *session, 330 Error **errp) 331 { 332 int ret; 333 unsigned int status; 334 const gnutls_datum_t *certs; 335 unsigned int nCerts, i; 336 time_t now; 337 gnutls_x509_crt_t cert = NULL; 338 Error *err = NULL; 339 340 now = time(NULL); 341 if (now == ((time_t)-1)) { 342 error_setg_errno(errp, errno, "Cannot get current time"); 343 return -1; 344 } 345 346 ret = gnutls_certificate_verify_peers2(session->handle, &status); 347 if (ret < 0) { 348 error_setg(errp, "Verify failed: %s", gnutls_strerror(ret)); 349 return -1; 350 } 351 352 if (status != 0) { 353 const char *reason = "Invalid certificate"; 354 355 if (status & GNUTLS_CERT_INVALID) { 356 reason = "The certificate is not trusted"; 357 } 358 359 if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) { 360 reason = "The certificate hasn't got a known issuer"; 361 } 362 363 if (status & GNUTLS_CERT_REVOKED) { 364 reason = "The certificate has been revoked"; 365 } 366 367 if (status & GNUTLS_CERT_INSECURE_ALGORITHM) { 368 reason = "The certificate uses an insecure algorithm"; 369 } 370 371 error_setg(errp, "%s", reason); 372 return -1; 373 } 374 375 certs = gnutls_certificate_get_peers(session->handle, &nCerts); 376 if (!certs) { 377 error_setg(errp, "No certificate peers"); 378 return -1; 379 } 380 381 for (i = 0; i < nCerts; i++) { 382 ret = gnutls_x509_crt_init(&cert); 383 if (ret < 0) { 384 error_setg(errp, "Cannot initialize certificate: %s", 385 gnutls_strerror(ret)); 386 return -1; 387 } 388 389 ret = gnutls_x509_crt_import(cert, &certs[i], GNUTLS_X509_FMT_DER); 390 if (ret < 0) { 391 error_setg(errp, "Cannot import certificate: %s", 392 gnutls_strerror(ret)); 393 goto error; 394 } 395 396 if (gnutls_x509_crt_get_expiration_time(cert) < now) { 397 error_setg(errp, "The certificate has expired"); 398 goto error; 399 } 400 401 if (gnutls_x509_crt_get_activation_time(cert) > now) { 402 error_setg(errp, "The certificate is not yet activated"); 403 goto error; 404 } 405 406 if (gnutls_x509_crt_get_activation_time(cert) > now) { 407 error_setg(errp, "The certificate is not yet activated"); 408 goto error; 409 } 410 411 if (i == 0) { 412 size_t dnameSize = 1024; 413 session->peername = g_malloc(dnameSize); 414 requery: 415 ret = gnutls_x509_crt_get_dn(cert, session->peername, &dnameSize); 416 if (ret < 0) { 417 if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) { 418 session->peername = g_realloc(session->peername, 419 dnameSize); 420 goto requery; 421 } 422 error_setg(errp, "Cannot get client distinguished name: %s", 423 gnutls_strerror(ret)); 424 goto error; 425 } 426 if (session->authzid) { 427 bool allow; 428 429 allow = qauthz_is_allowed_by_id(session->authzid, 430 session->peername, &err); 431 if (err) { 432 error_propagate(errp, err); 433 goto error; 434 } 435 if (!allow) { 436 error_setg(errp, "TLS x509 authz check for %s is denied", 437 session->peername); 438 goto error; 439 } 440 } 441 if (session->hostname) { 442 if (!gnutls_x509_crt_check_hostname(cert, session->hostname)) { 443 error_setg(errp, 444 "Certificate does not match the hostname %s", 445 session->hostname); 446 goto error; 447 } 448 } else { 449 if (session->creds->endpoint == 450 QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT) { 451 error_setg(errp, "No hostname for certificate validation"); 452 goto error; 453 } 454 } 455 } 456 457 gnutls_x509_crt_deinit(cert); 458 } 459 460 return 0; 461 462 error: 463 gnutls_x509_crt_deinit(cert); 464 return -1; 465 } 466 467 468 int 469 qcrypto_tls_session_check_credentials(QCryptoTLSSession *session, 470 Error **errp) 471 { 472 if (object_dynamic_cast(OBJECT(session->creds), 473 TYPE_QCRYPTO_TLS_CREDS_ANON)) { 474 trace_qcrypto_tls_session_check_creds(session, "nop"); 475 return 0; 476 } else if (object_dynamic_cast(OBJECT(session->creds), 477 TYPE_QCRYPTO_TLS_CREDS_PSK)) { 478 trace_qcrypto_tls_session_check_creds(session, "nop"); 479 return 0; 480 } else if (object_dynamic_cast(OBJECT(session->creds), 481 TYPE_QCRYPTO_TLS_CREDS_X509)) { 482 if (session->creds->verifyPeer) { 483 int ret = qcrypto_tls_session_check_certificate(session, 484 errp); 485 trace_qcrypto_tls_session_check_creds(session, 486 ret == 0 ? "pass" : "fail"); 487 return ret; 488 } else { 489 trace_qcrypto_tls_session_check_creds(session, "skip"); 490 return 0; 491 } 492 } else { 493 trace_qcrypto_tls_session_check_creds(session, "error"); 494 error_setg(errp, "Unexpected credential type %s", 495 object_get_typename(OBJECT(session->creds))); 496 return -1; 497 } 498 } 499 500 501 void 502 qcrypto_tls_session_set_callbacks(QCryptoTLSSession *session, 503 QCryptoTLSSessionWriteFunc writeFunc, 504 QCryptoTLSSessionReadFunc readFunc, 505 void *opaque) 506 { 507 session->writeFunc = writeFunc; 508 session->readFunc = readFunc; 509 session->opaque = opaque; 510 } 511 512 513 ssize_t 514 qcrypto_tls_session_write(QCryptoTLSSession *session, 515 const char *buf, 516 size_t len, 517 Error **errp) 518 { 519 ssize_t ret; 520 521 if (session->lockEnabled) { 522 qemu_mutex_lock(&session->lock); 523 } 524 525 ret = gnutls_record_send(session->handle, buf, len); 526 527 if (session->lockEnabled) { 528 qemu_mutex_unlock(&session->lock); 529 } 530 531 if (ret < 0) { 532 if (ret == GNUTLS_E_AGAIN) { 533 return QCRYPTO_TLS_SESSION_ERR_BLOCK; 534 } else { 535 if (session->werr) { 536 error_propagate(errp, session->werr); 537 session->werr = NULL; 538 } else { 539 error_setg(errp, 540 "Cannot write to TLS channel: %s", 541 gnutls_strerror(ret)); 542 } 543 return -1; 544 } 545 } 546 547 return ret; 548 } 549 550 551 ssize_t 552 qcrypto_tls_session_read(QCryptoTLSSession *session, 553 char *buf, 554 size_t len, 555 bool gracefulTermination, 556 Error **errp) 557 { 558 ssize_t ret; 559 560 if (session->lockEnabled) { 561 qemu_mutex_lock(&session->lock); 562 } 563 564 ret = gnutls_record_recv(session->handle, buf, len); 565 566 if (session->lockEnabled) { 567 qemu_mutex_unlock(&session->lock); 568 } 569 570 if (ret < 0) { 571 if (ret == GNUTLS_E_AGAIN) { 572 return QCRYPTO_TLS_SESSION_ERR_BLOCK; 573 } else if ((ret == GNUTLS_E_PREMATURE_TERMINATION) && 574 gracefulTermination){ 575 return 0; 576 } else { 577 if (session->rerr) { 578 error_propagate(errp, session->rerr); 579 session->rerr = NULL; 580 } else { 581 error_setg(errp, 582 "Cannot read from TLS channel: %s", 583 gnutls_strerror(ret)); 584 } 585 return -1; 586 } 587 } 588 589 return ret; 590 } 591 592 593 size_t 594 qcrypto_tls_session_check_pending(QCryptoTLSSession *session) 595 { 596 return gnutls_record_check_pending(session->handle); 597 } 598 599 600 int 601 qcrypto_tls_session_handshake(QCryptoTLSSession *session, 602 Error **errp) 603 { 604 int ret; 605 ret = gnutls_handshake(session->handle); 606 607 if (!ret) { 608 #ifdef CONFIG_GNUTLS_BUG1717_WORKAROUND 609 gnutls_cipher_algorithm_t cipher = 610 gnutls_cipher_get(session->handle); 611 612 /* 613 * Any use of rekeying in TLS 1.3 is unsafe for 614 * a gnutls with bug 1717, however, we know that 615 * QEMU won't initiate manual rekeying. Thus we 616 * only have to protect against automatic rekeying 617 * which doesn't trigger with CHACHA20 618 */ 619 trace_qcrypto_tls_session_parameters( 620 session, 621 session->requireThreadSafety, 622 gnutls_protocol_get_version(session->handle), 623 cipher); 624 625 if (session->requireThreadSafety && 626 gnutls_protocol_get_version(session->handle) == 627 GNUTLS_TLS1_3 && 628 cipher != GNUTLS_CIPHER_CHACHA20_POLY1305) { 629 warn_report("WARNING: activating thread safety countermeasures " 630 "for potentially broken GNUTLS with TLS1.3 cipher=%d", 631 cipher); 632 trace_qcrypto_tls_session_bug1717_workaround(session); 633 session->lockEnabled = true; 634 } 635 #endif 636 637 session->handshakeComplete = true; 638 return QCRYPTO_TLS_HANDSHAKE_COMPLETE; 639 } 640 641 if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) { 642 int direction = gnutls_record_get_direction(session->handle); 643 return direction ? QCRYPTO_TLS_HANDSHAKE_SENDING : 644 QCRYPTO_TLS_HANDSHAKE_RECVING; 645 } 646 647 if (session->rerr || session->werr) { 648 error_setg(errp, "TLS handshake failed: %s: %s", 649 gnutls_strerror(ret), 650 error_get_pretty(session->rerr ? 651 session->rerr : session->werr)); 652 } else { 653 error_setg(errp, "TLS handshake failed: %s", 654 gnutls_strerror(ret)); 655 } 656 657 error_free(session->rerr); 658 error_free(session->werr); 659 session->rerr = session->werr = NULL; 660 661 return -1; 662 } 663 664 665 int 666 qcrypto_tls_session_bye(QCryptoTLSSession *session, Error **errp) 667 { 668 int ret; 669 670 if (!session->handshakeComplete) { 671 return 0; 672 } 673 674 if (session->lockEnabled) { 675 qemu_mutex_lock(&session->lock); 676 } 677 ret = gnutls_bye(session->handle, GNUTLS_SHUT_WR); 678 679 if (session->lockEnabled) { 680 qemu_mutex_unlock(&session->lock); 681 } 682 683 if (!ret) { 684 return QCRYPTO_TLS_BYE_COMPLETE; 685 } 686 687 if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) { 688 int direction = gnutls_record_get_direction(session->handle); 689 return direction ? QCRYPTO_TLS_BYE_SENDING : QCRYPTO_TLS_BYE_RECVING; 690 } 691 692 if (session->rerr || session->werr) { 693 error_setg(errp, "TLS termination failed: %s: %s", gnutls_strerror(ret), 694 error_get_pretty(session->rerr ? 695 session->rerr : session->werr)); 696 } else { 697 error_setg(errp, "TLS termination failed: %s", gnutls_strerror(ret)); 698 } 699 700 error_free(session->rerr); 701 error_free(session->werr); 702 session->rerr = session->werr = NULL; 703 704 return -1; 705 } 706 707 int 708 qcrypto_tls_session_get_key_size(QCryptoTLSSession *session, 709 Error **errp) 710 { 711 gnutls_cipher_algorithm_t cipher; 712 int ssf; 713 714 cipher = gnutls_cipher_get(session->handle); 715 ssf = gnutls_cipher_get_key_size(cipher); 716 if (!ssf) { 717 error_setg(errp, "Cannot get TLS cipher key size"); 718 return -1; 719 } 720 return ssf; 721 } 722 723 724 char * 725 qcrypto_tls_session_get_peer_name(QCryptoTLSSession *session) 726 { 727 if (session->peername) { 728 return g_strdup(session->peername); 729 } 730 return NULL; 731 } 732 733 734 #else /* ! CONFIG_GNUTLS */ 735 736 737 QCryptoTLSSession * 738 qcrypto_tls_session_new(QCryptoTLSCreds *creds G_GNUC_UNUSED, 739 const char *hostname G_GNUC_UNUSED, 740 const char *authzid G_GNUC_UNUSED, 741 QCryptoTLSCredsEndpoint endpoint G_GNUC_UNUSED, 742 Error **errp) 743 { 744 error_setg(errp, "TLS requires GNUTLS support"); 745 return NULL; 746 } 747 748 void qcrypto_tls_session_require_thread_safety(QCryptoTLSSession *sess) 749 { 750 } 751 752 void 753 qcrypto_tls_session_free(QCryptoTLSSession *sess G_GNUC_UNUSED) 754 { 755 } 756 757 758 int 759 qcrypto_tls_session_check_credentials(QCryptoTLSSession *sess G_GNUC_UNUSED, 760 Error **errp) 761 { 762 error_setg(errp, "TLS requires GNUTLS support"); 763 return -1; 764 } 765 766 767 void 768 qcrypto_tls_session_set_callbacks( 769 QCryptoTLSSession *sess G_GNUC_UNUSED, 770 QCryptoTLSSessionWriteFunc writeFunc G_GNUC_UNUSED, 771 QCryptoTLSSessionReadFunc readFunc G_GNUC_UNUSED, 772 void *opaque G_GNUC_UNUSED) 773 { 774 } 775 776 777 ssize_t 778 qcrypto_tls_session_write(QCryptoTLSSession *sess, 779 const char *buf, 780 size_t len, 781 Error **errp) 782 { 783 error_setg(errp, "TLS requires GNUTLS support"); 784 return -1; 785 } 786 787 788 ssize_t 789 qcrypto_tls_session_read(QCryptoTLSSession *sess, 790 char *buf, 791 size_t len, 792 bool gracefulTermination, 793 Error **errp) 794 { 795 error_setg(errp, "TLS requires GNUTLS support"); 796 return -1; 797 } 798 799 800 size_t 801 qcrypto_tls_session_check_pending(QCryptoTLSSession *session) 802 { 803 return 0; 804 } 805 806 807 int 808 qcrypto_tls_session_handshake(QCryptoTLSSession *sess, 809 Error **errp) 810 { 811 error_setg(errp, "TLS requires GNUTLS support"); 812 return -1; 813 } 814 815 816 int 817 qcrypto_tls_session_bye(QCryptoTLSSession *session, Error **errp) 818 { 819 return QCRYPTO_TLS_BYE_COMPLETE; 820 } 821 822 823 int 824 qcrypto_tls_session_get_key_size(QCryptoTLSSession *sess, 825 Error **errp) 826 { 827 error_setg(errp, "TLS requires GNUTLS support"); 828 return -1; 829 } 830 831 832 char * 833 qcrypto_tls_session_get_peer_name(QCryptoTLSSession *sess) 834 { 835 return NULL; 836 } 837 838 #endif 839