1/* 2 * libjingle 3 * Copyright 2004--2008, Google Inc. 4 * Copyright 2004--2011, RTFM, Inc. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 20 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include <vector> 30 31#if HAVE_CONFIG_H 32#include "config.h" 33#endif // HAVE_CONFIG_H 34 35#if HAVE_NSS_SSL_H 36 37#include "talk/base/nssstreamadapter.h" 38 39#include "keyhi.h" 40#include "nspr.h" 41#include "nss.h" 42#include "pk11pub.h" 43#include "secerr.h" 44 45#ifdef NSS_SSL_RELATIVE_PATH 46#include "ssl.h" 47#include "sslerr.h" 48#include "sslproto.h" 49#else 50#include "net/third_party/nss/ssl/ssl.h" 51#include "net/third_party/nss/ssl/sslerr.h" 52#include "net/third_party/nss/ssl/sslproto.h" 53#endif 54 55#include "talk/base/nssidentity.h" 56#include "talk/base/thread.h" 57 58namespace talk_base { 59 60PRDescIdentity NSSStreamAdapter::nspr_layer_identity = PR_INVALID_IO_LAYER; 61 62#define UNIMPLEMENTED \ 63 PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); \ 64 LOG(LS_ERROR) \ 65 << "Call to unimplemented function "<< __FUNCTION__; ASSERT(false) 66 67#ifdef SRTP_AES128_CM_HMAC_SHA1_80 68#define HAVE_DTLS_SRTP 69#endif 70 71#ifdef HAVE_DTLS_SRTP 72// SRTP cipher suite table 73struct SrtpCipherMapEntry { 74 const char* external_name; 75 PRUint16 cipher_id; 76}; 77 78// This isn't elegant, but it's better than an external reference 79static const SrtpCipherMapEntry kSrtpCipherMap[] = { 80 {"AES_CM_128_HMAC_SHA1_80", SRTP_AES128_CM_HMAC_SHA1_80 }, 81 {"AES_CM_128_HMAC_SHA1_32", SRTP_AES128_CM_HMAC_SHA1_32 }, 82 {NULL, 0} 83}; 84#endif 85 86 87// Implementation of NSPR methods 88static PRStatus StreamClose(PRFileDesc *socket) { 89 // Noop 90 return PR_SUCCESS; 91} 92 93static PRInt32 StreamRead(PRFileDesc *socket, void *buf, PRInt32 length) { 94 StreamInterface *stream = reinterpret_cast<StreamInterface *>(socket->secret); 95 size_t read; 96 int error; 97 StreamResult result = stream->Read(buf, length, &read, &error); 98 if (result == SR_SUCCESS) { 99 return read; 100 } 101 102 if (result == SR_EOS) { 103 return 0; 104 } 105 106 if (result == SR_BLOCK) { 107 PR_SetError(PR_WOULD_BLOCK_ERROR, 0); 108 return -1; 109 } 110 111 PR_SetError(PR_UNKNOWN_ERROR, error); 112 return -1; 113} 114 115static PRInt32 StreamWrite(PRFileDesc *socket, const void *buf, 116 PRInt32 length) { 117 StreamInterface *stream = reinterpret_cast<StreamInterface *>(socket->secret); 118 size_t written; 119 int error; 120 StreamResult result = stream->Write(buf, length, &written, &error); 121 if (result == SR_SUCCESS) { 122 return written; 123 } 124 125 if (result == SR_BLOCK) { 126 LOG(LS_INFO) << 127 "NSSStreamAdapter: write to underlying transport would block"; 128 PR_SetError(PR_WOULD_BLOCK_ERROR, 0); 129 return -1; 130 } 131 132 LOG(LS_ERROR) << "Write error"; 133 PR_SetError(PR_UNKNOWN_ERROR, error); 134 return -1; 135} 136 137static PRInt32 StreamAvailable(PRFileDesc *socket) { 138 UNIMPLEMENTED; 139 return -1; 140} 141 142PRInt64 StreamAvailable64(PRFileDesc *socket) { 143 UNIMPLEMENTED; 144 return -1; 145} 146 147static PRStatus StreamSync(PRFileDesc *socket) { 148 UNIMPLEMENTED; 149 return PR_FAILURE; 150} 151 152static PROffset32 StreamSeek(PRFileDesc *socket, PROffset32 offset, 153 PRSeekWhence how) { 154 UNIMPLEMENTED; 155 return -1; 156} 157 158static PROffset64 StreamSeek64(PRFileDesc *socket, PROffset64 offset, 159 PRSeekWhence how) { 160 UNIMPLEMENTED; 161 return -1; 162} 163 164static PRStatus StreamFileInfo(PRFileDesc *socket, PRFileInfo *info) { 165 UNIMPLEMENTED; 166 return PR_FAILURE; 167} 168 169static PRStatus StreamFileInfo64(PRFileDesc *socket, PRFileInfo64 *info) { 170 UNIMPLEMENTED; 171 return PR_FAILURE; 172} 173 174static PRInt32 StreamWritev(PRFileDesc *socket, const PRIOVec *iov, 175 PRInt32 iov_size, PRIntervalTime timeout) { 176 UNIMPLEMENTED; 177 return -1; 178} 179 180static PRStatus StreamConnect(PRFileDesc *socket, const PRNetAddr *addr, 181 PRIntervalTime timeout) { 182 UNIMPLEMENTED; 183 return PR_FAILURE; 184} 185 186static PRFileDesc *StreamAccept(PRFileDesc *sd, PRNetAddr *addr, 187 PRIntervalTime timeout) { 188 UNIMPLEMENTED; 189 return NULL; 190} 191 192static PRStatus StreamBind(PRFileDesc *socket, const PRNetAddr *addr) { 193 UNIMPLEMENTED; 194 return PR_FAILURE; 195} 196 197static PRStatus StreamListen(PRFileDesc *socket, PRIntn depth) { 198 UNIMPLEMENTED; 199 return PR_FAILURE; 200} 201 202static PRStatus StreamShutdown(PRFileDesc *socket, PRIntn how) { 203 UNIMPLEMENTED; 204 return PR_FAILURE; 205} 206 207// Note: this is always nonblocking and ignores the timeout. 208// TODO(ekr@rtfm.com): In future verify that the socket is 209// actually in non-blocking mode. 210// This function does not support peek. 211static PRInt32 StreamRecv(PRFileDesc *socket, void *buf, PRInt32 amount, 212 PRIntn flags, PRIntervalTime to) { 213 ASSERT(flags == 0); 214 215 if (flags != 0) { 216 PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); 217 return -1; 218 } 219 220 return StreamRead(socket, buf, amount); 221} 222 223// Note: this is always nonblocking and assumes a zero timeout. 224// This function does not support peek. 225static PRInt32 StreamSend(PRFileDesc *socket, const void *buf, 226 PRInt32 amount, PRIntn flags, 227 PRIntervalTime to) { 228 ASSERT(flags == 0); 229 230 return StreamWrite(socket, buf, amount); 231} 232 233static PRInt32 StreamRecvfrom(PRFileDesc *socket, void *buf, 234 PRInt32 amount, PRIntn flags, 235 PRNetAddr *addr, PRIntervalTime to) { 236 UNIMPLEMENTED; 237 return -1; 238} 239 240static PRInt32 StreamSendto(PRFileDesc *socket, const void *buf, 241 PRInt32 amount, PRIntn flags, 242 const PRNetAddr *addr, PRIntervalTime to) { 243 UNIMPLEMENTED; 244 return -1; 245} 246 247static PRInt16 StreamPoll(PRFileDesc *socket, PRInt16 in_flags, 248 PRInt16 *out_flags) { 249 UNIMPLEMENTED; 250 return -1; 251} 252 253static PRInt32 StreamAcceptRead(PRFileDesc *sd, PRFileDesc **nd, 254 PRNetAddr **raddr, 255 void *buf, PRInt32 amount, PRIntervalTime t) { 256 UNIMPLEMENTED; 257 return -1; 258} 259 260static PRInt32 StreamTransmitFile(PRFileDesc *sd, PRFileDesc *socket, 261 const void *headers, PRInt32 hlen, 262 PRTransmitFileFlags flags, PRIntervalTime t) { 263 UNIMPLEMENTED; 264 return -1; 265} 266 267static PRStatus StreamGetPeerName(PRFileDesc *socket, PRNetAddr *addr) { 268 // TODO(ekr@rtfm.com): Modify to return unique names for each channel 269 // somehow, as opposed to always the same static address. The current 270 // implementation messes up the session cache, which is why it's off 271 // elsewhere 272 addr->inet.family = PR_AF_INET; 273 addr->inet.port = 0; 274 addr->inet.ip = 0; 275 276 return PR_SUCCESS; 277} 278 279static PRStatus StreamGetSockName(PRFileDesc *socket, PRNetAddr *addr) { 280 UNIMPLEMENTED; 281 return PR_FAILURE; 282} 283 284static PRStatus StreamGetSockOption(PRFileDesc *socket, PRSocketOptionData *opt) { 285 switch (opt->option) { 286 case PR_SockOpt_Nonblocking: 287 opt->value.non_blocking = PR_TRUE; 288 return PR_SUCCESS; 289 default: 290 UNIMPLEMENTED; 291 break; 292 } 293 294 return PR_FAILURE; 295} 296 297// Imitate setting socket options. These are mostly noops. 298static PRStatus StreamSetSockOption(PRFileDesc *socket, 299 const PRSocketOptionData *opt) { 300 switch (opt->option) { 301 case PR_SockOpt_Nonblocking: 302 return PR_SUCCESS; 303 case PR_SockOpt_NoDelay: 304 return PR_SUCCESS; 305 default: 306 UNIMPLEMENTED; 307 break; 308 } 309 310 return PR_FAILURE; 311} 312 313static PRInt32 StreamSendfile(PRFileDesc *out, PRSendFileData *in, 314 PRTransmitFileFlags flags, PRIntervalTime to) { 315 UNIMPLEMENTED; 316 return -1; 317} 318 319static PRStatus StreamConnectContinue(PRFileDesc *socket, PRInt16 flags) { 320 UNIMPLEMENTED; 321 return PR_FAILURE; 322} 323 324static PRIntn StreamReserved(PRFileDesc *socket) { 325 UNIMPLEMENTED; 326 return -1; 327} 328 329static const struct PRIOMethods nss_methods = { 330 PR_DESC_LAYERED, 331 StreamClose, 332 StreamRead, 333 StreamWrite, 334 StreamAvailable, 335 StreamAvailable64, 336 StreamSync, 337 StreamSeek, 338 StreamSeek64, 339 StreamFileInfo, 340 StreamFileInfo64, 341 StreamWritev, 342 StreamConnect, 343 StreamAccept, 344 StreamBind, 345 StreamListen, 346 StreamShutdown, 347 StreamRecv, 348 StreamSend, 349 StreamRecvfrom, 350 StreamSendto, 351 StreamPoll, 352 StreamAcceptRead, 353 StreamTransmitFile, 354 StreamGetSockName, 355 StreamGetPeerName, 356 StreamReserved, 357 StreamReserved, 358 StreamGetSockOption, 359 StreamSetSockOption, 360 StreamSendfile, 361 StreamConnectContinue, 362 StreamReserved, 363 StreamReserved, 364 StreamReserved, 365 StreamReserved 366}; 367 368NSSStreamAdapter::NSSStreamAdapter(StreamInterface *stream) 369 : SSLStreamAdapterHelper(stream), 370 ssl_fd_(NULL), 371 cert_ok_(false) { 372} 373 374bool NSSStreamAdapter::Init() { 375 if (nspr_layer_identity == PR_INVALID_IO_LAYER) { 376 nspr_layer_identity = PR_GetUniqueIdentity("nssstreamadapter"); 377 } 378 PRFileDesc *pr_fd = PR_CreateIOLayerStub(nspr_layer_identity, &nss_methods); 379 if (!pr_fd) 380 return false; 381 pr_fd->secret = reinterpret_cast<PRFilePrivate *>(stream()); 382 383 PRFileDesc *ssl_fd; 384 if (ssl_mode_ == SSL_MODE_DTLS) { 385 ssl_fd = DTLS_ImportFD(NULL, pr_fd); 386 } else { 387 ssl_fd = SSL_ImportFD(NULL, pr_fd); 388 } 389 ASSERT(ssl_fd != NULL); // This should never happen 390 if (!ssl_fd) { 391 PR_Close(pr_fd); 392 return false; 393 } 394 395 SECStatus rv; 396 // Turn on security. 397 rv = SSL_OptionSet(ssl_fd, SSL_SECURITY, PR_TRUE); 398 if (rv != SECSuccess) { 399 LOG(LS_ERROR) << "Error enabling security on SSL Socket"; 400 return false; 401 } 402 403 // Disable SSLv2. 404 rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_SSL2, PR_FALSE); 405 if (rv != SECSuccess) { 406 LOG(LS_ERROR) << "Error disabling SSL2"; 407 return false; 408 } 409 410 // Disable caching. 411 // TODO(ekr@rtfm.com): restore this when I have the caching 412 // identity set. 413 rv = SSL_OptionSet(ssl_fd, SSL_NO_CACHE, PR_TRUE); 414 if (rv != SECSuccess) { 415 LOG(LS_ERROR) << "Error disabling cache"; 416 return false; 417 } 418 419 // Disable session tickets. 420 rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_SESSION_TICKETS, PR_FALSE); 421 if (rv != SECSuccess) { 422 LOG(LS_ERROR) << "Error enabling tickets"; 423 return false; 424 } 425 426 // Disable renegotiation. 427 rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_RENEGOTIATION, 428 SSL_RENEGOTIATE_NEVER); 429 if (rv != SECSuccess) { 430 LOG(LS_ERROR) << "Error disabling renegotiation"; 431 return false; 432 } 433 434 // Disable false start. 435 rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_FALSE_START, PR_FALSE); 436 if (rv != SECSuccess) { 437 LOG(LS_ERROR) << "Error disabling false start"; 438 return false; 439 } 440 441 ssl_fd_ = ssl_fd; 442 443 return true; 444} 445 446NSSStreamAdapter::~NSSStreamAdapter() { 447 if (ssl_fd_) 448 PR_Close(ssl_fd_); 449}; 450 451 452int NSSStreamAdapter::BeginSSL() { 453 SECStatus rv; 454 455 if (!Init()) { 456 Error("Init", -1, false); 457 return -1; 458 } 459 460 ASSERT(state_ == SSL_CONNECTING); 461 // The underlying stream has been opened. If we are in peer-to-peer mode 462 // then a peer certificate must have been specified by now. 463 ASSERT(!ssl_server_name_.empty() || 464 peer_certificate_.get() != NULL || 465 !peer_certificate_digest_algorithm_.empty()); 466 LOG(LS_INFO) << "BeginSSL: " 467 << (!ssl_server_name_.empty() ? ssl_server_name_ : 468 "with peer"); 469 470 if (role_ == SSL_CLIENT) { 471 LOG(LS_INFO) << "BeginSSL: as client"; 472 473 rv = SSL_GetClientAuthDataHook(ssl_fd_, GetClientAuthDataHook, 474 this); 475 if (rv != SECSuccess) { 476 Error("BeginSSL", -1, false); 477 return -1; 478 } 479 } else { 480 LOG(LS_INFO) << "BeginSSL: as server"; 481 NSSIdentity *identity; 482 483 if (identity_.get()) { 484 identity = static_cast<NSSIdentity *>(identity_.get()); 485 } else { 486 LOG(LS_ERROR) << "Can't be an SSL server without an identity"; 487 Error("BeginSSL", -1, false); 488 return -1; 489 } 490 rv = SSL_ConfigSecureServer(ssl_fd_, identity->certificate().certificate(), 491 identity->keypair()->privkey(), 492 kt_rsa); 493 if (rv != SECSuccess) { 494 Error("BeginSSL", -1, false); 495 return -1; 496 } 497 498 // Insist on a certificate from the client 499 rv = SSL_OptionSet(ssl_fd_, SSL_REQUEST_CERTIFICATE, PR_TRUE); 500 if (rv != SECSuccess) { 501 Error("BeginSSL", -1, false); 502 return -1; 503 } 504 505 rv = SSL_OptionSet(ssl_fd_, SSL_REQUIRE_CERTIFICATE, PR_TRUE); 506 if (rv != SECSuccess) { 507 Error("BeginSSL", -1, false); 508 return -1; 509 } 510 } 511 512 // Set the version range. 513 SSLVersionRange vrange; 514 vrange.min = (ssl_mode_ == SSL_MODE_DTLS) ? 515 SSL_LIBRARY_VERSION_TLS_1_1 : 516 SSL_LIBRARY_VERSION_TLS_1_0; 517 vrange.max = SSL_LIBRARY_VERSION_TLS_1_1; 518 519 rv = SSL_VersionRangeSet(ssl_fd_, &vrange); 520 if (rv != SECSuccess) { 521 Error("BeginSSL", -1, false); 522 return -1; 523 } 524 525 // SRTP 526#ifdef HAVE_DTLS_SRTP 527 if (!srtp_ciphers_.empty()) { 528 rv = SSL_SetSRTPCiphers(ssl_fd_, &srtp_ciphers_[0], srtp_ciphers_.size()); 529 if (rv != SECSuccess) { 530 Error("BeginSSL", -1, false); 531 return -1; 532 } 533 } 534#endif 535 536 // Certificate validation 537 rv = SSL_AuthCertificateHook(ssl_fd_, AuthCertificateHook, this); 538 if (rv != SECSuccess) { 539 Error("BeginSSL", -1, false); 540 return -1; 541 } 542 543 // Now start the handshake 544 rv = SSL_ResetHandshake(ssl_fd_, role_ == SSL_SERVER ? PR_TRUE : PR_FALSE); 545 if (rv != SECSuccess) { 546 Error("BeginSSL", -1, false); 547 return -1; 548 } 549 550 return ContinueSSL(); 551} 552 553int NSSStreamAdapter::ContinueSSL() { 554 LOG(LS_INFO) << "ContinueSSL"; 555 ASSERT(state_ == SSL_CONNECTING); 556 557 // Clear the DTLS timer 558 Thread::Current()->Clear(this, MSG_DTLS_TIMEOUT); 559 560 SECStatus rv = SSL_ForceHandshake(ssl_fd_); 561 562 if (rv == SECSuccess) { 563 LOG(LS_INFO) << "Handshake complete"; 564 565 ASSERT(cert_ok_); 566 if (!cert_ok_) { 567 Error("ContinueSSL", -1, true); 568 return -1; 569 } 570 571 state_ = SSL_CONNECTED; 572 StreamAdapterInterface::OnEvent(stream(), SE_OPEN|SE_READ|SE_WRITE, 0); 573 return 0; 574 } 575 576 PRInt32 err = PR_GetError(); 577 switch (err) { 578 case SSL_ERROR_RX_MALFORMED_HANDSHAKE: 579 if (ssl_mode_ != SSL_MODE_DTLS) { 580 Error("ContinueSSL", -1, true); 581 return -1; 582 } else { 583 LOG(LS_INFO) << "Malformed DTLS message. Ignoring."; 584 // Fall through 585 } 586 case PR_WOULD_BLOCK_ERROR: 587 LOG(LS_INFO) << "Would have blocked"; 588 if (ssl_mode_ == SSL_MODE_DTLS) { 589 PRIntervalTime timeout; 590 591 SECStatus rv = DTLS_GetHandshakeTimeout(ssl_fd_, &timeout); 592 if (rv == SECSuccess) { 593 LOG(LS_INFO) << "Timeout is " << timeout << " ms"; 594 Thread::Current()->PostDelayed(PR_IntervalToMilliseconds(timeout), 595 this, MSG_DTLS_TIMEOUT, 0); 596 } 597 } 598 599 return 0; 600 default: 601 LOG(LS_INFO) << "Error " << err; 602 break; 603 } 604 605 Error("ContinueSSL", -1, true); 606 return -1; 607} 608 609void NSSStreamAdapter::Cleanup() { 610 if (state_ != SSL_ERROR) { 611 state_ = SSL_CLOSED; 612 } 613 614 if (ssl_fd_) { 615 PR_Close(ssl_fd_); 616 ssl_fd_ = NULL; 617 } 618 619 identity_.reset(); 620 peer_certificate_.reset(); 621 622 Thread::Current()->Clear(this, MSG_DTLS_TIMEOUT); 623} 624 625StreamResult NSSStreamAdapter::Read(void* data, size_t data_len, 626 size_t* read, int* error) { 627 // SSL_CONNECTED sanity check. 628 switch (state_) { 629 case SSL_NONE: 630 case SSL_WAIT: 631 case SSL_CONNECTING: 632 return SR_BLOCK; 633 634 case SSL_CONNECTED: 635 break; 636 637 case SSL_CLOSED: 638 return SR_EOS; 639 640 case SSL_ERROR: 641 default: 642 if (error) 643 *error = ssl_error_code_; 644 return SR_ERROR; 645 } 646 647 PRInt32 rv = PR_Read(ssl_fd_, data, data_len); 648 649 if (rv == 0) { 650 return SR_EOS; 651 } 652 653 // Error 654 if (rv < 0) { 655 PRInt32 err = PR_GetError(); 656 657 switch (err) { 658 case PR_WOULD_BLOCK_ERROR: 659 return SR_BLOCK; 660 default: 661 Error("Read", -1, false); 662 *error = err; // libjingle semantics are that this is impl-specific 663 return SR_ERROR; 664 } 665 } 666 667 // Success 668 *read = rv; 669 670 return SR_SUCCESS; 671} 672 673StreamResult NSSStreamAdapter::Write(const void* data, size_t data_len, 674 size_t* written, int* error) { 675 // SSL_CONNECTED sanity check. 676 switch (state_) { 677 case SSL_NONE: 678 case SSL_WAIT: 679 case SSL_CONNECTING: 680 return SR_BLOCK; 681 682 case SSL_CONNECTED: 683 break; 684 685 case SSL_ERROR: 686 case SSL_CLOSED: 687 default: 688 if (error) 689 *error = ssl_error_code_; 690 return SR_ERROR; 691 } 692 693 PRInt32 rv = PR_Write(ssl_fd_, data, data_len); 694 695 // Error 696 if (rv < 0) { 697 PRInt32 err = PR_GetError(); 698 699 switch (err) { 700 case PR_WOULD_BLOCK_ERROR: 701 return SR_BLOCK; 702 default: 703 Error("Write", -1, false); 704 *error = err; // libjingle semantics are that this is impl-specific 705 return SR_ERROR; 706 } 707 } 708 709 // Success 710 *written = rv; 711 712 return SR_SUCCESS; 713} 714 715void NSSStreamAdapter::OnEvent(StreamInterface* stream, int events, 716 int err) { 717 int events_to_signal = 0; 718 int signal_error = 0; 719 ASSERT(stream == this->stream()); 720 if ((events & SE_OPEN)) { 721 LOG(LS_INFO) << "NSSStreamAdapter::OnEvent SE_OPEN"; 722 if (state_ != SSL_WAIT) { 723 ASSERT(state_ == SSL_NONE); 724 events_to_signal |= SE_OPEN; 725 } else { 726 state_ = SSL_CONNECTING; 727 if (int err = BeginSSL()) { 728 Error("BeginSSL", err, true); 729 return; 730 } 731 } 732 } 733 if ((events & (SE_READ|SE_WRITE))) { 734 LOG(LS_INFO) << "NSSStreamAdapter::OnEvent" 735 << ((events & SE_READ) ? " SE_READ" : "") 736 << ((events & SE_WRITE) ? " SE_WRITE" : ""); 737 if (state_ == SSL_NONE) { 738 events_to_signal |= events & (SE_READ|SE_WRITE); 739 } else if (state_ == SSL_CONNECTING) { 740 if (int err = ContinueSSL()) { 741 Error("ContinueSSL", err, true); 742 return; 743 } 744 } else if (state_ == SSL_CONNECTED) { 745 if (events & SE_WRITE) { 746 LOG(LS_INFO) << " -- onStreamWriteable"; 747 events_to_signal |= SE_WRITE; 748 } 749 if (events & SE_READ) { 750 LOG(LS_INFO) << " -- onStreamReadable"; 751 events_to_signal |= SE_READ; 752 } 753 } 754 } 755 if ((events & SE_CLOSE)) { 756 LOG(LS_INFO) << "NSSStreamAdapter::OnEvent(SE_CLOSE, " << err << ")"; 757 Cleanup(); 758 events_to_signal |= SE_CLOSE; 759 // SE_CLOSE is the only event that uses the final parameter to OnEvent(). 760 ASSERT(signal_error == 0); 761 signal_error = err; 762 } 763 if (events_to_signal) 764 StreamAdapterInterface::OnEvent(stream, events_to_signal, signal_error); 765} 766 767void NSSStreamAdapter::OnMessage(Message* msg) { 768 // Process our own messages and then pass others to the superclass 769 if (MSG_DTLS_TIMEOUT == msg->message_id) { 770 LOG(LS_INFO) << "DTLS timeout expired"; 771 ContinueSSL(); 772 } else { 773 StreamInterface::OnMessage(msg); 774 } 775} 776 777// Certificate verification callback. Called to check any certificate 778SECStatus NSSStreamAdapter::AuthCertificateHook(void *arg, 779 PRFileDesc *fd, 780 PRBool checksig, 781 PRBool isServer) { 782 LOG(LS_INFO) << "NSSStreamAdapter::AuthCertificateHook"; 783 NSSCertificate peer_cert(SSL_PeerCertificate(fd)); 784 bool ok = false; 785 786 // TODO(ekr@rtfm.com): Should we be enforcing self-signed like 787 // the OpenSSL version? 788 NSSStreamAdapter *stream = reinterpret_cast<NSSStreamAdapter *>(arg); 789 790 if (stream->peer_certificate_.get()) { 791 LOG(LS_INFO) << "Checking against specified certificate"; 792 793 // The peer certificate was specified 794 if (reinterpret_cast<NSSCertificate *>(stream->peer_certificate_.get())-> 795 Equals(&peer_cert)) { 796 LOG(LS_INFO) << "Accepted peer certificate"; 797 ok = true; 798 } 799 } else if (!stream->peer_certificate_digest_algorithm_.empty()) { 800 LOG(LS_INFO) << "Checking against specified digest"; 801 // The peer certificate digest was specified 802 unsigned char digest[64]; // Maximum size 803 std::size_t digest_length; 804 805 if (!peer_cert.ComputeDigest( 806 stream->peer_certificate_digest_algorithm_, 807 digest, sizeof(digest), &digest_length)) { 808 LOG(LS_ERROR) << "Digest computation failed"; 809 } else { 810 Buffer computed_digest(digest, digest_length); 811 if (computed_digest == stream->peer_certificate_digest_value_) { 812 LOG(LS_INFO) << "Accepted peer certificate"; 813 ok = true; 814 } 815 } 816 } else { 817 // Other modes, but we haven't implemented yet 818 // TODO(ekr@rtfm.com): Implement real certificate validation 819 UNIMPLEMENTED; 820 } 821 822 if (ok) { 823 stream->cert_ok_ = true; 824 825 // Record the peer's certificate chain. 826 CERTCertList* cert_list = SSL_PeerCertificateChain(fd); 827 ASSERT(cert_list != NULL); 828 829 stream->peer_certificate_.reset(new NSSCertificate(cert_list)); 830 CERT_DestroyCertList(cert_list); 831 return SECSuccess; 832 } 833 834 if (!ok && stream->ignore_bad_cert()) { 835 LOG(LS_WARNING) << "Ignoring cert error while verifying cert chain"; 836 stream->cert_ok_ = true; 837 return SECSuccess; 838 } 839 840 PORT_SetError(SEC_ERROR_UNTRUSTED_CERT); 841 return SECFailure; 842} 843 844 845SECStatus NSSStreamAdapter::GetClientAuthDataHook(void *arg, PRFileDesc *fd, 846 CERTDistNames *caNames, 847 CERTCertificate **pRetCert, 848 SECKEYPrivateKey **pRetKey) { 849 LOG(LS_INFO) << "Client cert requested"; 850 NSSStreamAdapter *stream = reinterpret_cast<NSSStreamAdapter *>(arg); 851 852 if (!stream->identity_.get()) { 853 LOG(LS_ERROR) << "No identity available"; 854 return SECFailure; 855 } 856 857 NSSIdentity *identity = static_cast<NSSIdentity *>(stream->identity_.get()); 858 // Destroyed internally by NSS 859 *pRetCert = CERT_DupCertificate(identity->certificate().certificate()); 860 *pRetKey = SECKEY_CopyPrivateKey(identity->keypair()->privkey()); 861 862 return SECSuccess; 863} 864 865// RFC 5705 Key Exporter 866bool NSSStreamAdapter::ExportKeyingMaterial(const std::string& label, 867 const uint8* context, 868 size_t context_len, 869 bool use_context, 870 uint8* result, 871 size_t result_len) { 872 SECStatus rv = SSL_ExportKeyingMaterial(ssl_fd_, 873 label.c_str(), label.size(), 874 use_context, 875 context, context_len, 876 result, result_len); 877 878 return rv == SECSuccess; 879} 880 881bool NSSStreamAdapter::SetDtlsSrtpCiphers( 882 const std::vector<std::string>& ciphers) { 883#ifdef HAVE_DTLS_SRTP 884 std::vector<PRUint16> internal_ciphers; 885 if (state_ != SSL_NONE) 886 return false; 887 888 for (std::vector<std::string>::const_iterator cipher = ciphers.begin(); 889 cipher != ciphers.end(); ++cipher) { 890 bool found = false; 891 for (const SrtpCipherMapEntry *entry = kSrtpCipherMap; entry->cipher_id; 892 ++entry) { 893 if (*cipher == entry->external_name) { 894 found = true; 895 internal_ciphers.push_back(entry->cipher_id); 896 break; 897 } 898 } 899 900 if (!found) { 901 LOG(LS_ERROR) << "Could not find cipher: " << *cipher; 902 return false; 903 } 904 } 905 906 if (internal_ciphers.empty()) 907 return false; 908 909 srtp_ciphers_ = internal_ciphers; 910 911 return true; 912#else 913 return false; 914#endif 915} 916 917bool NSSStreamAdapter::GetDtlsSrtpCipher(std::string* cipher) { 918#ifdef HAVE_DTLS_SRTP 919 ASSERT(state_ == SSL_CONNECTED); 920 if (state_ != SSL_CONNECTED) 921 return false; 922 923 PRUint16 selected_cipher; 924 925 SECStatus rv = SSL_GetSRTPCipher(ssl_fd_, &selected_cipher); 926 if (rv == SECFailure) 927 return false; 928 929 for (const SrtpCipherMapEntry *entry = kSrtpCipherMap; 930 entry->cipher_id; ++entry) { 931 if (selected_cipher == entry->cipher_id) { 932 *cipher = entry->external_name; 933 return true; 934 } 935 } 936 937 ASSERT(false); // This should never happen 938#endif 939 return false; 940} 941 942 943bool NSSContext::initialized; 944NSSContext *NSSContext::global_nss_context; 945 946// Static initialization and shutdown 947NSSContext *NSSContext::Instance() { 948 if (!global_nss_context) { 949 NSSContext *new_ctx = new NSSContext(); 950 951 if (!(new_ctx->slot_ = PK11_GetInternalSlot())) { 952 delete new_ctx; 953 goto fail; 954 } 955 956 global_nss_context = new_ctx; 957 } 958 959 fail: 960 return global_nss_context; 961} 962 963 964 965bool NSSContext::InitializeSSL(VerificationCallback callback) { 966 ASSERT(!callback); 967 968 if (!initialized) { 969 SECStatus rv; 970 971 rv = NSS_NoDB_Init(NULL); 972 if (rv != SECSuccess) { 973 LOG(LS_ERROR) << "Couldn't initialize NSS error=" << 974 PORT_GetError(); 975 return false; 976 } 977 978 NSS_SetDomesticPolicy(); 979 980 initialized = true; 981 } 982 983 return true; 984} 985 986bool NSSContext::InitializeSSLThread() { 987 // Not needed 988 return true; 989} 990 991bool NSSContext::CleanupSSL() { 992 // Not needed 993 return true; 994} 995 996bool NSSStreamAdapter::HaveDtls() { 997 return true; 998} 999 1000bool NSSStreamAdapter::HaveDtlsSrtp() { 1001#ifdef HAVE_DTLS_SRTP 1002 return true; 1003#else 1004 return false; 1005#endif 1006} 1007 1008bool NSSStreamAdapter::HaveExporter() { 1009 return true; 1010} 1011 1012} // namespace talk_base 1013 1014#endif // HAVE_NSS_SSL_H 1015