tortls_nss.c (20996B)
1 /* Copyright (c) 2003, Roger Dingledine. 2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. 3 * Copyright (c) 2007-2021, The Tor Project, Inc. */ 4 /* See LICENSE for licensing information */ 5 6 /** 7 * \file tortls_nss.c 8 * \brief Wrapper functions to present a consistent interface to 9 * TLS and SSL X.509 functions from NSS. 10 **/ 11 12 #include "orconfig.h" 13 14 #define TORTLS_PRIVATE 15 #define TOR_X509_PRIVATE 16 17 #ifdef _WIN32 18 #include <winsock2.h> 19 #include <ws2tcpip.h> 20 #endif 21 22 #include "lib/crypt_ops/crypto_cipher.h" 23 #include "lib/crypt_ops/crypto_rand.h" 24 #include "lib/crypt_ops/crypto_dh.h" 25 #include "lib/crypt_ops/crypto_util.h" 26 #include "lib/crypt_ops/crypto_nss_mgt.h" 27 #include "lib/string/printf.h" 28 29 #include "lib/tls/x509.h" 30 #include "lib/tls/x509_internal.h" 31 #include "lib/tls/tortls.h" 32 #include "lib/tls/tortls_st.h" 33 #include "lib/tls/tortls_internal.h" 34 #include "lib/tls/nss_countbytes.h" 35 #include "lib/log/util_bug.h" 36 37 DISABLE_GCC_WARNING("-Wstrict-prototypes") 38 #include <prio.h> 39 // For access to rar sockets. 40 #include <private/pprio.h> 41 #include <ssl.h> 42 #include <sslt.h> 43 #include <sslproto.h> 44 #include <certt.h> 45 ENABLE_GCC_WARNING("-Wstrict-prototypes") 46 47 static SECStatus always_accept_cert_cb(void *, PRFileDesc *, PRBool, PRBool); 48 49 static bool 50 we_like_ssl_cipher(SSLCipherAlgorithm ca) 51 { 52 switch (ca) { 53 case ssl_calg_null: return false; 54 case ssl_calg_rc4: return false; 55 case ssl_calg_rc2: return false; 56 case ssl_calg_des: return false; 57 case ssl_calg_3des: return false; /* ???? */ 58 case ssl_calg_idea: return false; 59 case ssl_calg_fortezza: return false; 60 case ssl_calg_camellia: return false; 61 case ssl_calg_seed: return false; 62 63 case ssl_calg_aes: return true; 64 case ssl_calg_aes_gcm: return true; 65 case ssl_calg_chacha20: return true; 66 default: return true; 67 } 68 } 69 static bool 70 we_like_ssl_kea(SSLKEAType kt) 71 { 72 switch (kt) { 73 case ssl_kea_null: return false; 74 case ssl_kea_rsa: return false; /* ??? */ 75 case ssl_kea_fortezza: return false; 76 case ssl_kea_ecdh_psk: return false; 77 case ssl_kea_dh_psk: return false; 78 79 #ifdef NSS_HAS_ECDH_HYBRID 80 case ssl_kea_ecdh_hybrid_psk: return false; 81 case ssl_kea_ecdh_hybrid: return true; 82 #endif 83 84 case ssl_kea_dh: return true; 85 case ssl_kea_ecdh: return true; 86 case ssl_kea_tls13_any: return true; 87 88 case ssl_kea_size: return true; /* prevent a warning. */ 89 default: return true; 90 } 91 } 92 93 static bool 94 we_like_mac_algorithm(SSLMACAlgorithm ma) 95 { 96 switch (ma) { 97 case ssl_mac_null: return false; 98 case ssl_mac_md5: return false; 99 case ssl_hmac_md5: return false; 100 101 case ssl_mac_sha: return true; 102 case ssl_hmac_sha: return true; 103 case ssl_hmac_sha256: return true; 104 case ssl_mac_aead: return true; 105 case ssl_hmac_sha384: return true; 106 default: return true; 107 } 108 } 109 110 static bool 111 we_like_auth_type(SSLAuthType at) 112 { 113 switch (at) { 114 case ssl_auth_null: return false; 115 case ssl_auth_rsa_decrypt: return false; 116 case ssl_auth_dsa: return false; 117 case ssl_auth_kea: return false; 118 119 case ssl_auth_ecdsa: return true; 120 case ssl_auth_ecdh_rsa: return true; 121 case ssl_auth_ecdh_ecdsa: return true; 122 case ssl_auth_rsa_sign: return true; 123 case ssl_auth_rsa_pss: return true; 124 case ssl_auth_psk: return true; 125 case ssl_auth_tls13_any: return true; 126 127 case ssl_auth_size: return true; /* prevent a warning. */ 128 default: return true; 129 } 130 } 131 132 /** 133 * Return true iff this ciphersuite will be hit by a mozilla bug 1312976, 134 * which makes TLS key exporters not work with TLS 1.2 non-SHA256 135 * ciphersuites. 136 **/ 137 static bool 138 ciphersuite_has_nss_export_bug(const SSLCipherSuiteInfo *info) 139 { 140 /* For more information on the bug, see 141 https://bugzilla.mozilla.org/show_bug.cgi?id=1312976 */ 142 143 /* This bug only exists in TLS 1.2. */ 144 if (info->authType == ssl_auth_tls13_any) 145 return false; 146 147 /* Sadly, there's no way to get this information from the 148 * CipherSuiteInfo object itself other than by looking at the 149 * name. */ 150 if (strstr(info->cipherSuiteName, "_SHA384") || 151 strstr(info->cipherSuiteName, "_SHA512")) { 152 return true; 153 } 154 155 return false; 156 } 157 158 tor_tls_context_t * 159 tor_tls_context_new(crypto_pk_t *identity, 160 unsigned int key_lifetime, unsigned flags, int is_client) 161 { 162 SECStatus s; 163 tor_assert(identity); 164 165 tor_tls_init(); 166 167 tor_tls_context_t *ctx = tor_malloc_zero(sizeof(tor_tls_context_t)); 168 ctx->refcnt = 1; 169 170 if (! is_client) { 171 if (tor_tls_context_init_certificates(ctx, identity, 172 key_lifetime, flags) < 0) { 173 goto err; 174 } 175 } 176 177 { 178 /* Create the "model" PRFileDesc that we will use to base others on. */ 179 PRFileDesc *tcp = PR_NewTCPSocket(); 180 if (!tcp) 181 goto err; 182 183 ctx->ctx = SSL_ImportFD(NULL, tcp); 184 if (!ctx->ctx) { 185 PR_Close(tcp); 186 goto err; 187 } 188 } 189 190 // Configure the certificate. 191 if (!is_client) { 192 s = SSL_ConfigServerCert(ctx->ctx, 193 ctx->my_link_cert->cert, 194 (SECKEYPrivateKey *) 195 crypto_pk_get_nss_privkey(ctx->link_key), 196 NULL, /* ExtraServerCertData */ 197 0 /* DataLen */); 198 if (s != SECSuccess) 199 goto err; 200 } 201 202 // We need a certificate from the other side. 203 if (is_client) { 204 // XXXX does this do anything? 205 s = SSL_OptionSet(ctx->ctx, SSL_REQUIRE_CERTIFICATE, PR_TRUE); 206 if (s != SECSuccess) 207 goto err; 208 } 209 210 // Always accept other side's cert; we'll check it ourselves in goofy 211 // tor ways. 212 s = SSL_AuthCertificateHook(ctx->ctx, always_accept_cert_cb, NULL); 213 214 // We allow simultaneous read and write. 215 s = SSL_OptionSet(ctx->ctx, SSL_ENABLE_FDX, PR_TRUE); 216 if (s != SECSuccess) 217 goto err; 218 // XXXX SSL_ROLLBACK_DETECTION?? 219 // XXXX SSL_ENABLE_ALPN?? 220 221 // Force client-mode or server_mode. 222 s = SSL_OptionSet(ctx->ctx, 223 is_client ? SSL_HANDSHAKE_AS_CLIENT : SSL_HANDSHAKE_AS_SERVER, 224 PR_TRUE); 225 if (s != SECSuccess) 226 goto err; 227 228 // Disable everything before TLS 1.0; support everything else. 229 { 230 SSLVersionRange vrange; 231 memset(&vrange, 0, sizeof(vrange)); 232 s = SSL_VersionRangeGetSupported(ssl_variant_stream, &vrange); 233 if (s != SECSuccess) 234 goto err; 235 if (vrange.min < SSL_LIBRARY_VERSION_TLS_1_0) 236 vrange.min = SSL_LIBRARY_VERSION_TLS_1_0; 237 s = SSL_VersionRangeSet(ctx->ctx, &vrange); 238 if (s != SECSuccess) 239 goto err; 240 } 241 242 // Only support strong ciphers. 243 { 244 const PRUint16 *ciphers = SSL_GetImplementedCiphers(); 245 const PRUint16 n_ciphers = SSL_GetNumImplementedCiphers(); 246 PRUint16 i; 247 for (i = 0; i < n_ciphers; ++i) { 248 SSLCipherSuiteInfo info; 249 memset(&info, 0, sizeof(info)); 250 s = SSL_GetCipherSuiteInfo(ciphers[i], &info, sizeof(info)); 251 if (s != SECSuccess) 252 goto err; 253 if (BUG(info.cipherSuite != ciphers[i])) 254 goto err; 255 int disable = info.effectiveKeyBits < 128 || 256 info.macBits < 128 || 257 !we_like_ssl_cipher(info.symCipher) || 258 !we_like_ssl_kea(info.keaType) || 259 !we_like_mac_algorithm(info.macAlgorithm) || 260 !we_like_auth_type(info.authType)/* Requires NSS 3.24 */; 261 262 if (ciphersuite_has_nss_export_bug(&info)) { 263 /* SSL_ExportKeyingMaterial will fail; we can't use this cipher. 264 */ 265 disable = 1; 266 } 267 268 s = SSL_CipherPrefSet(ctx->ctx, ciphers[i], 269 disable ? PR_FALSE : PR_TRUE); 270 if (s != SECSuccess) 271 goto err; 272 } 273 } 274 275 // Only use DH and ECDH keys once. 276 s = SSL_OptionSet(ctx->ctx, SSL_REUSE_SERVER_ECDHE_KEY, PR_FALSE); 277 if (s != SECSuccess) 278 goto err; 279 280 // don't cache sessions. 281 s = SSL_OptionSet(ctx->ctx, SSL_NO_CACHE, PR_TRUE); 282 if (s != SECSuccess) 283 goto err; 284 285 // Enable DH. 286 s = SSL_OptionSet(ctx->ctx, SSL_ENABLE_SERVER_DHE, PR_TRUE); 287 if (s != SECSuccess) 288 goto err; 289 290 // Set DH and ECDH groups. 291 SSLNamedGroup groups[] = { 292 ssl_grp_ec_curve25519, 293 ssl_grp_ec_secp256r1, 294 ssl_grp_ec_secp224r1, 295 ssl_grp_ffdhe_2048, 296 }; 297 s = SSL_NamedGroupConfig(ctx->ctx, groups, ARRAY_LENGTH(groups)); 298 if (s != SECSuccess) 299 goto err; 300 301 // These features are off by default, so we don't need to disable them: 302 // Session tickets 303 // Renegotiation 304 // Compression 305 306 goto done; 307 err: 308 tor_tls_context_decref(ctx); 309 ctx = NULL; 310 done: 311 return ctx; 312 } 313 314 void 315 tor_tls_context_impl_free_(tor_tls_context_impl_t *ctx) 316 { 317 if (!ctx) 318 return; 319 PR_Close(ctx); 320 } 321 322 void 323 tor_tls_get_state_description(tor_tls_t *tls, char *buf, size_t sz) 324 { 325 (void)tls; 326 (void)buf; 327 (void)sz; 328 // AFAICT, NSS doesn't expose its internal state. 329 buf[0]=0; 330 } 331 332 void 333 tor_tls_init(void) 334 { 335 tor_nss_countbytes_init(); 336 } 337 338 void 339 tls_log_errors(tor_tls_t *tls, int severity, int domain, 340 const char *doing) 341 { 342 /* This implementation is a little different for NSS than it is for OpenSSL 343 -- it logs the last error whether anything actually failed or not. So we 344 have to only call it when something has gone wrong and we have a real 345 error to report. */ 346 347 (void)tls; 348 PRErrorCode code = PORT_GetError(); 349 if (tls) 350 tls->last_error = code; 351 352 const char *addr = tls ? tls->address : NULL; 353 const char *string = PORT_ErrorToString(code); 354 const char *name = PORT_ErrorToName(code); 355 char buf[16]; 356 if (!string) 357 string = "<unrecognized>"; 358 if (!name) { 359 tor_snprintf(buf, sizeof(buf), "%d", code); 360 name = buf; 361 } 362 363 const char *with = addr ? " with " : ""; 364 addr = addr ? addr : ""; 365 if (doing) { 366 log_fn(severity, domain, "TLS error %s while %s%s%s: %s", 367 name, doing, with, addr, string); 368 } else { 369 log_fn(severity, domain, "TLS error %s%s%s: %s", name, string, 370 with, addr); 371 } 372 } 373 const char * 374 tor_tls_get_last_error_msg(const tor_tls_t *tls) 375 { 376 IF_BUG_ONCE(!tls) { 377 return NULL; 378 } 379 if (tls->last_error == 0) { 380 return NULL; 381 } 382 return PORT_ErrorToString((PRErrorCode)tls->last_error); 383 } 384 385 tor_tls_t * 386 tor_tls_new(tor_socket_t sock, int is_server) 387 { 388 (void)sock; 389 tor_tls_context_t *ctx = tor_tls_context_get(is_server); 390 391 PRFileDesc *tcp = NULL; 392 if (SOCKET_OK(sock)) { 393 tcp = PR_ImportTCPSocket(sock); 394 } else { 395 tcp = PR_NewTCPSocket(); 396 } 397 398 if (!tcp) 399 return NULL; 400 401 PRFileDesc *count = tor_wrap_prfiledesc_with_byte_counter(tcp); 402 if (! count) 403 return NULL; 404 405 PRFileDesc *ssl = SSL_ImportFD(ctx->ctx, count); 406 if (!ssl) { 407 PR_Close(tcp); 408 return NULL; 409 } 410 411 /* even if though the socket is already nonblocking, we need to tell NSS 412 * about the fact, so that it knows what to do when it says EAGAIN. */ 413 PRSocketOptionData data; 414 data.option = PR_SockOpt_Nonblocking; 415 data.value.non_blocking = 1; 416 if (PR_SetSocketOption(ssl, &data) != PR_SUCCESS) { 417 PR_Close(ssl); 418 return NULL; 419 } 420 421 tor_tls_t *tls = tor_malloc_zero(sizeof(tor_tls_t)); 422 tls->magic = TOR_TLS_MAGIC; 423 tls->context = ctx; 424 tor_tls_context_incref(ctx); 425 tls->ssl = ssl; 426 tls->socket = sock; 427 tls->state = TOR_TLS_ST_HANDSHAKE; 428 tls->isServer = !!is_server; 429 430 if (!is_server) { 431 /* Set a random SNI */ 432 char *fake_hostname = crypto_random_hostname(4,25, "www.",".com"); 433 SSL_SetURL(tls->ssl, fake_hostname); 434 tor_free(fake_hostname); 435 } 436 SECStatus s = SSL_ResetHandshake(ssl, is_server ? PR_TRUE : PR_FALSE); 437 if (s != SECSuccess) { 438 tls_log_errors(tls, LOG_WARN, LD_CRYPTO, "resetting handshake state"); 439 } 440 441 return tls; 442 } 443 444 /** 445 * Tell the TLS library that the underlying socket for <b>tls</b> has been 446 * closed, and the library should not attempt to free that socket itself. 447 */ 448 void 449 tor_tls_release_socket(tor_tls_t *tls) 450 { 451 if (! tls) 452 return; 453 454 /* NSS doesn't have the equivalent of BIO_NO_CLOSE. If you replace the 455 * fd with something that's invalid, it causes a memory leak in PR_Close. 456 * 457 * If there were a way to put the PRFileDesc into the CLOSED state, that 458 * would prevent it from closing its fd -- but there doesn't seem to be a 459 * supported way to do that either. 460 * 461 * So instead: we make a new sacrificial socket, and replace the original 462 * socket with that one. This seems to be the best we can do, until we 463 * redesign the mainloop code enough to make this function unnecessary. 464 */ 465 tor_socket_t sock = 466 tor_open_socket_nonblocking(AF_INET, SOCK_STREAM, IPPROTO_TCP); 467 if (! SOCKET_OK(sock)) { 468 log_warn(LD_NET, "Out of sockets when trying to shut down an NSS " 469 "connection"); 470 return; 471 } 472 473 PRFileDesc *tcp = PR_GetIdentitiesLayer(tls->ssl, PR_NSPR_IO_LAYER); 474 if (BUG(! tcp)) { 475 tor_close_socket(sock); 476 return; 477 } 478 479 PR_ChangeFileDescNativeHandle(tcp, sock); 480 /* Tell our socket accounting layer that we don't own this socket any more: 481 * NSS is about to free it for us. */ 482 tor_release_socket_ownership(sock); 483 } 484 485 void 486 tor_tls_impl_free_(tor_tls_impl_t *tls) 487 { 488 // XXXX This will close the underlying fd, which our OpenSSL version does 489 // not do! 490 if (!tls) 491 return; 492 493 PR_Close(tls); 494 } 495 496 int 497 tor_tls_peer_has_cert(tor_tls_t *tls) 498 { 499 CERTCertificate *cert = SSL_PeerCertificate(tls->ssl); 500 int result = (cert != NULL); 501 CERT_DestroyCertificate(cert); 502 return result; 503 } 504 505 MOCK_IMPL(tor_x509_cert_t *, 506 tor_tls_get_peer_cert,(tor_tls_t *tls)) 507 { 508 CERTCertificate *cert = SSL_PeerCertificate(tls->ssl); 509 if (cert) 510 return tor_x509_cert_new(cert); 511 else 512 return NULL; 513 } 514 515 MOCK_IMPL(tor_x509_cert_t *, 516 tor_tls_get_own_cert,(tor_tls_t *tls)) 517 { 518 tor_assert(tls); 519 CERTCertificate *cert = SSL_LocalCertificate(tls->ssl); 520 if (cert) 521 return tor_x509_cert_new(cert); 522 else 523 return NULL; 524 } 525 526 MOCK_IMPL(int, 527 tor_tls_read, (tor_tls_t *tls, char *cp, size_t len)) 528 { 529 tor_assert(tls); 530 tor_assert(cp); 531 tor_assert(len < INT_MAX); 532 533 PRInt32 rv = PR_Read(tls->ssl, cp, (int)len); 534 // log_debug(LD_NET, "PR_Read(%zu) returned %d", n, (int)rv); 535 if (rv > 0) { 536 return rv; 537 } 538 if (rv == 0) 539 return TOR_TLS_CLOSE; 540 PRErrorCode err = PORT_GetError(); 541 if (err == PR_WOULD_BLOCK_ERROR) { 542 return TOR_TLS_WANTREAD; // XXXX ???? 543 } else { 544 tls_log_errors(tls, LOG_NOTICE, LD_CRYPTO, "reading"); // XXXX 545 return TOR_TLS_ERROR_MISC; // ???? 546 } 547 } 548 549 int 550 tor_tls_write(tor_tls_t *tls, const char *cp, size_t n) 551 { 552 tor_assert(tls); 553 tor_assert(cp || n == 0); 554 tor_assert(n < INT_MAX); 555 556 if (n == 0) { 557 return 0; 558 } 559 560 PRInt32 rv = PR_Write(tls->ssl, cp, (int)n); 561 // log_debug(LD_NET, "PR_Write(%zu) returned %d", n, (int)rv); 562 if (rv > 0) { 563 return rv; 564 } 565 if (rv == 0) 566 return TOR_TLS_ERROR_MISC; 567 PRErrorCode err = PORT_GetError(); 568 569 if (err == PR_WOULD_BLOCK_ERROR) { 570 return TOR_TLS_WANTWRITE; // XXXX ???? 571 } else { 572 tls_log_errors(tls, LOG_NOTICE, LD_CRYPTO, "writing"); // XXXX 573 return TOR_TLS_ERROR_MISC; // ???? 574 } 575 } 576 577 int 578 tor_tls_handshake(tor_tls_t *tls) 579 { 580 tor_assert(tls); 581 tor_assert(tls->state == TOR_TLS_ST_HANDSHAKE); 582 583 SECStatus s = SSL_ForceHandshake(tls->ssl); 584 if (s == SECSuccess) { 585 tls->state = TOR_TLS_ST_OPEN; 586 log_debug(LD_NET, "SSL handshake is supposedly complete."); 587 return TOR_TLS_DONE; 588 } 589 if (PORT_GetError() == PR_WOULD_BLOCK_ERROR) 590 return TOR_TLS_WANTREAD; /* XXXX What about wantwrite? */ 591 592 return TOR_TLS_ERROR_MISC; // XXXX 593 } 594 595 int 596 tor_tls_get_pending_bytes(tor_tls_t *tls) 597 { 598 tor_assert(tls); 599 int n = SSL_DataPending(tls->ssl); 600 if (n < 0) { 601 tls_log_errors(tls, LOG_WARN, LD_CRYPTO, "looking up pending bytes"); 602 return 0; 603 } 604 return (int)n; 605 } 606 607 size_t 608 tor_tls_get_forced_write_size(tor_tls_t *tls) 609 { 610 tor_assert(tls); 611 /* NSS doesn't have the same "forced write" restriction as openssl. */ 612 return 0; 613 } 614 615 void 616 tor_tls_get_n_raw_bytes(tor_tls_t *tls, 617 size_t *n_read, size_t *n_written) 618 { 619 tor_assert(tls); 620 tor_assert(n_read); 621 tor_assert(n_written); 622 uint64_t r, w; 623 if (tor_get_prfiledesc_byte_counts(tls->ssl, &r, &w) < 0) { 624 *n_read = *n_written = 0; 625 return; 626 } 627 628 *n_read = (size_t)(r - tls->last_read_count); 629 *n_written = (size_t)(w - tls->last_write_count); 630 631 tls->last_read_count = r; 632 tls->last_write_count = w; 633 } 634 635 int 636 tor_tls_get_buffer_sizes(tor_tls_t *tls, 637 size_t *rbuf_capacity, size_t *rbuf_bytes, 638 size_t *wbuf_capacity, size_t *wbuf_bytes) 639 { 640 tor_assert(tls); 641 tor_assert(rbuf_capacity); 642 tor_assert(rbuf_bytes); 643 tor_assert(wbuf_capacity); 644 tor_assert(wbuf_bytes); 645 646 /* This is an acceptable way to say "we can't measure this." */ 647 return -1; 648 } 649 650 MOCK_IMPL(double, 651 tls_get_write_overhead_ratio, (void)) 652 { 653 /* XXX We don't currently have a way to measure this in NSS; we could do that 654 * XXX with a PRIO layer, but it'll take a little coding. */ 655 return 0.95; 656 } 657 658 MOCK_IMPL(int, 659 tor_tls_cert_matches_key,(const tor_tls_t *tls, 660 const struct tor_x509_cert_t *cert)) 661 { 662 tor_assert(cert); 663 tor_assert(cert->cert); 664 665 int rv = 0; 666 667 tor_x509_cert_t *peercert = tor_tls_get_peer_cert((tor_tls_t *)tls); 668 669 if (!peercert || !peercert->cert) 670 goto done; 671 672 CERTSubjectPublicKeyInfo *peer_info = &peercert->cert->subjectPublicKeyInfo; 673 CERTSubjectPublicKeyInfo *cert_info = &cert->cert->subjectPublicKeyInfo; 674 675 /* NSS stores the `len` field in bits, instead of bytes, for the 676 * `subjectPublicKey` field in CERTSubjectPublicKeyInfo, but 677 * `SECITEM_ItemsAreEqual()` compares the two bitstrings using a length field 678 * defined in bytes. 679 * 680 * We convert the `len` field from bits to bytes, do our comparison with 681 * `SECITEM_ItemsAreEqual()`, and reset the length field from bytes to bits 682 * again. 683 * 684 * See also NSS's own implementation of `SECKEY_CopySubjectPublicKeyInfo()` 685 * in seckey.c in the NSS source tree. This function also does the conversion 686 * between bits and bytes. 687 */ 688 const unsigned int peer_info_orig_len = peer_info->subjectPublicKey.len; 689 const unsigned int cert_info_orig_len = cert_info->subjectPublicKey.len; 690 691 /* We convert the length from bits to bytes, but instead of using NSS's 692 * `DER_ConvertBitString()` macro on both of peer_info->subjectPublicKey and 693 * cert_info->subjectPublicKey, we have to do the conversion explicitly since 694 * both of the two subjectPublicKey fields are allowed to point to the same 695 * memory address. Otherwise, the bits to bytes conversion would potentially 696 * be applied twice, which would lead to us comparing too few of the bytes 697 * when we call SECITEM_ItemsAreEqual(), which would be catastrophic. 698 */ 699 peer_info->subjectPublicKey.len = ((peer_info_orig_len + 7) >> 3); 700 cert_info->subjectPublicKey.len = ((cert_info_orig_len + 7) >> 3); 701 702 rv = SECOID_CompareAlgorithmID(&peer_info->algorithm, 703 &cert_info->algorithm) == 0 && 704 SECITEM_ItemsAreEqual(&peer_info->subjectPublicKey, 705 &cert_info->subjectPublicKey); 706 707 /* Convert from bytes back to bits. */ 708 peer_info->subjectPublicKey.len = peer_info_orig_len; 709 cert_info->subjectPublicKey.len = cert_info_orig_len; 710 711 done: 712 tor_x509_cert_free(peercert); 713 714 return rv; 715 } 716 717 MOCK_IMPL(int, 718 tor_tls_export_key_material,(tor_tls_t *tls, uint8_t *secrets_out, 719 const uint8_t *context, 720 size_t context_len, 721 const char *label)) 722 { 723 tor_assert(tls); 724 tor_assert(secrets_out); 725 tor_assert(context); 726 tor_assert(label); 727 tor_assert(strlen(label) <= UINT_MAX); 728 tor_assert(context_len <= UINT_MAX); 729 730 SECStatus s; 731 /* Make sure that the error code is set here, so that we can be sure that 732 * any error code set after a failure was in fact caused by 733 * SSL_ExportKeyingMaterial. */ 734 PR_SetError(PR_UNKNOWN_ERROR, 0); 735 s = SSL_ExportKeyingMaterial(tls->ssl, 736 label, (unsigned)strlen(label), 737 PR_TRUE, context, (unsigned)context_len, 738 secrets_out, DIGEST256_LEN); 739 if (s != SECSuccess) { 740 tls_log_errors(tls, LOG_WARN, LD_CRYPTO, 741 "exporting key material for a TLS handshake"); 742 } 743 744 return (s == SECSuccess) ? 0 : -1; 745 } 746 747 /** The group we should use for ecdhe when none was selected. */ 748 #define SEC_OID_TOR_DEFAULT_ECDHE_GROUP SEC_OID_ANSIX962_EC_PRIME256V1 749 750 int 751 evaluate_ecgroup_for_tls(const char *ecgroup) 752 { 753 SECOidTag tag; 754 755 if (!ecgroup) 756 tag = SEC_OID_TOR_DEFAULT_ECDHE_GROUP; 757 else if (!strcasecmp(ecgroup, "P256")) 758 tag = SEC_OID_ANSIX962_EC_PRIME256V1; 759 else if (!strcasecmp(ecgroup, "P224")) 760 tag = SEC_OID_SECG_EC_SECP224R1; 761 else 762 return 0; 763 764 /* I don't think we need any additional tests here for NSS */ 765 (void) tag; 766 767 return 1; 768 } 769 770 static SECStatus 771 always_accept_cert_cb(void *arg, PRFileDesc *ssl, PRBool checkSig, 772 PRBool isServer) 773 { 774 (void)arg; 775 (void)ssl; 776 (void)checkSig; 777 (void)isServer; 778 return SECSuccess; 779 }