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 58 namespace talk_base { 59 60 PRDescIdentity 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 73 struct 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 79 static 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 88 static PRStatus StreamClose(PRFileDesc *socket) { 89 // Noop 90 return PR_SUCCESS; 91 } 92 93 static 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 115 static 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 137 static PRInt32 StreamAvailable(PRFileDesc *socket) { 138 UNIMPLEMENTED; 139 return -1; 140 } 141 142 PRInt64 StreamAvailable64(PRFileDesc *socket) { 143 UNIMPLEMENTED; 144 return -1; 145 } 146 147 static PRStatus StreamSync(PRFileDesc *socket) { 148 UNIMPLEMENTED; 149 return PR_FAILURE; 150 } 151 152 static PROffset32 StreamSeek(PRFileDesc *socket, PROffset32 offset, 153 PRSeekWhence how) { 154 UNIMPLEMENTED; 155 return -1; 156 } 157 158 static PROffset64 StreamSeek64(PRFileDesc *socket, PROffset64 offset, 159 PRSeekWhence how) { 160 UNIMPLEMENTED; 161 return -1; 162 } 163 164 static PRStatus StreamFileInfo(PRFileDesc *socket, PRFileInfo *info) { 165 UNIMPLEMENTED; 166 return PR_FAILURE; 167 } 168 169 static PRStatus StreamFileInfo64(PRFileDesc *socket, PRFileInfo64 *info) { 170 UNIMPLEMENTED; 171 return PR_FAILURE; 172 } 173 174 static PRInt32 StreamWritev(PRFileDesc *socket, const PRIOVec *iov, 175 PRInt32 iov_size, PRIntervalTime timeout) { 176 UNIMPLEMENTED; 177 return -1; 178 } 179 180 static PRStatus StreamConnect(PRFileDesc *socket, const PRNetAddr *addr, 181 PRIntervalTime timeout) { 182 UNIMPLEMENTED; 183 return PR_FAILURE; 184 } 185 186 static PRFileDesc *StreamAccept(PRFileDesc *sd, PRNetAddr *addr, 187 PRIntervalTime timeout) { 188 UNIMPLEMENTED; 189 return NULL; 190 } 191 192 static PRStatus StreamBind(PRFileDesc *socket, const PRNetAddr *addr) { 193 UNIMPLEMENTED; 194 return PR_FAILURE; 195 } 196 197 static PRStatus StreamListen(PRFileDesc *socket, PRIntn depth) { 198 UNIMPLEMENTED; 199 return PR_FAILURE; 200 } 201 202 static 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 (at) rtfm.com): In future verify that the socket is 209 // actually in non-blocking mode. 210 // This function does not support peek. 211 static 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. 225 static 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 233 static PRInt32 StreamRecvfrom(PRFileDesc *socket, void *buf, 234 PRInt32 amount, PRIntn flags, 235 PRNetAddr *addr, PRIntervalTime to) { 236 UNIMPLEMENTED; 237 return -1; 238 } 239 240 static 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 247 static PRInt16 StreamPoll(PRFileDesc *socket, PRInt16 in_flags, 248 PRInt16 *out_flags) { 249 UNIMPLEMENTED; 250 return -1; 251 } 252 253 static PRInt32 StreamAcceptRead(PRFileDesc *sd, PRFileDesc **nd, 254 PRNetAddr **raddr, 255 void *buf, PRInt32 amount, PRIntervalTime t) { 256 UNIMPLEMENTED; 257 return -1; 258 } 259 260 static PRInt32 StreamTransmitFile(PRFileDesc *sd, PRFileDesc *socket, 261 const void *headers, PRInt32 hlen, 262 PRTransmitFileFlags flags, PRIntervalTime t) { 263 UNIMPLEMENTED; 264 return -1; 265 } 266 267 static PRStatus StreamGetPeerName(PRFileDesc *socket, PRNetAddr *addr) { 268 // TODO(ekr (at) 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 279 static PRStatus StreamGetSockName(PRFileDesc *socket, PRNetAddr *addr) { 280 UNIMPLEMENTED; 281 return PR_FAILURE; 282 } 283 284 static 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. 298 static 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 313 static PRInt32 StreamSendfile(PRFileDesc *out, PRSendFileData *in, 314 PRTransmitFileFlags flags, PRIntervalTime to) { 315 UNIMPLEMENTED; 316 return -1; 317 } 318 319 static PRStatus StreamConnectContinue(PRFileDesc *socket, PRInt16 flags) { 320 UNIMPLEMENTED; 321 return PR_FAILURE; 322 } 323 324 static PRIntn StreamReserved(PRFileDesc *socket) { 325 UNIMPLEMENTED; 326 return -1; 327 } 328 329 static 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 368 NSSStreamAdapter::NSSStreamAdapter(StreamInterface *stream) 369 : SSLStreamAdapterHelper(stream), 370 ssl_fd_(NULL), 371 cert_ok_(false) { 372 } 373 374 bool 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 (at) 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 446 NSSStreamAdapter::~NSSStreamAdapter() { 447 if (ssl_fd_) 448 PR_Close(ssl_fd_); 449 }; 450 451 452 int 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 553 int 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 609 void 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 625 StreamResult 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 673 StreamResult 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 715 void 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 767 void 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 778 SECStatus 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 (at) 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 (at) rtfm.com): Implement real certificate validation 819 UNIMPLEMENTED; 820 } 821 822 if (ok) { 823 stream->cert_ok_ = true; 824 return SECSuccess; 825 } 826 827 if (!ok && stream->ignore_bad_cert()) { 828 LOG(LS_WARNING) << "Ignoring cert error while verifying cert chain"; 829 stream->cert_ok_ = true; 830 return SECSuccess; 831 } 832 833 PORT_SetError(SEC_ERROR_UNTRUSTED_CERT); 834 return SECFailure; 835 } 836 837 838 SECStatus NSSStreamAdapter::GetClientAuthDataHook(void *arg, PRFileDesc *fd, 839 CERTDistNames *caNames, 840 CERTCertificate **pRetCert, 841 SECKEYPrivateKey **pRetKey) { 842 LOG(LS_INFO) << "Client cert requested"; 843 NSSStreamAdapter *stream = reinterpret_cast<NSSStreamAdapter *>(arg); 844 845 if (!stream->identity_.get()) { 846 LOG(LS_ERROR) << "No identity available"; 847 return SECFailure; 848 } 849 850 NSSIdentity *identity = static_cast<NSSIdentity *>(stream->identity_.get()); 851 // Destroyed internally by NSS 852 *pRetCert = CERT_DupCertificate(identity->certificate().certificate()); 853 *pRetKey = SECKEY_CopyPrivateKey(identity->keypair()->privkey()); 854 855 return SECSuccess; 856 } 857 858 // RFC 5705 Key Exporter 859 bool NSSStreamAdapter::ExportKeyingMaterial(const std::string& label, 860 const uint8* context, 861 size_t context_len, 862 bool use_context, 863 uint8* result, 864 size_t result_len) { 865 SECStatus rv = SSL_ExportKeyingMaterial(ssl_fd_, 866 label.c_str(), label.size(), 867 use_context, 868 context, context_len, 869 result, result_len); 870 871 return rv == SECSuccess; 872 } 873 874 bool NSSStreamAdapter::SetDtlsSrtpCiphers( 875 const std::vector<std::string>& ciphers) { 876 #ifdef HAVE_DTLS_SRTP 877 std::vector<PRUint16> internal_ciphers; 878 if (state_ != SSL_NONE) 879 return false; 880 881 for (std::vector<std::string>::const_iterator cipher = ciphers.begin(); 882 cipher != ciphers.end(); ++cipher) { 883 bool found = false; 884 for (const SrtpCipherMapEntry *entry = kSrtpCipherMap; entry->cipher_id; 885 ++entry) { 886 if (*cipher == entry->external_name) { 887 found = true; 888 internal_ciphers.push_back(entry->cipher_id); 889 break; 890 } 891 } 892 893 if (!found) { 894 LOG(LS_ERROR) << "Could not find cipher: " << *cipher; 895 return false; 896 } 897 } 898 899 if (internal_ciphers.empty()) 900 return false; 901 902 srtp_ciphers_ = internal_ciphers; 903 904 return true; 905 #else 906 return false; 907 #endif 908 } 909 910 bool NSSStreamAdapter::GetDtlsSrtpCipher(std::string* cipher) { 911 #ifdef HAVE_DTLS_SRTP 912 ASSERT(state_ == SSL_CONNECTED); 913 if (state_ != SSL_CONNECTED) 914 return false; 915 916 PRUint16 selected_cipher; 917 918 SECStatus rv = SSL_GetSRTPCipher(ssl_fd_, &selected_cipher); 919 if (rv == SECFailure) 920 return false; 921 922 for (const SrtpCipherMapEntry *entry = kSrtpCipherMap; 923 entry->cipher_id; ++entry) { 924 if (selected_cipher == entry->cipher_id) { 925 *cipher = entry->external_name; 926 return true; 927 } 928 } 929 930 ASSERT(false); // This should never happen 931 #endif 932 return false; 933 } 934 935 936 bool NSSContext::initialized; 937 NSSContext *NSSContext::global_nss_context; 938 939 // Static initialization and shutdown 940 NSSContext *NSSContext::Instance() { 941 if (!global_nss_context) { 942 NSSContext *new_ctx = new NSSContext(); 943 944 if (!(new_ctx->slot_ = PK11_GetInternalSlot())) { 945 delete new_ctx; 946 goto fail; 947 } 948 949 global_nss_context = new_ctx; 950 } 951 952 fail: 953 return global_nss_context; 954 } 955 956 957 958 bool NSSContext::InitializeSSL(VerificationCallback callback) { 959 ASSERT(!callback); 960 961 if (!initialized) { 962 SECStatus rv; 963 964 rv = NSS_NoDB_Init(NULL); 965 if (rv != SECSuccess) { 966 LOG(LS_ERROR) << "Couldn't initialize NSS error=" << 967 PORT_GetError(); 968 return false; 969 } 970 971 NSS_SetDomesticPolicy(); 972 973 initialized = true; 974 } 975 976 return true; 977 } 978 979 bool NSSContext::InitializeSSLThread() { 980 // Not needed 981 return true; 982 } 983 984 bool NSSContext::CleanupSSL() { 985 // Not needed 986 return true; 987 } 988 989 bool NSSStreamAdapter::HaveDtls() { 990 return true; 991 } 992 993 bool NSSStreamAdapter::HaveDtlsSrtp() { 994 #ifdef HAVE_DTLS_SRTP 995 return true; 996 #else 997 return false; 998 #endif 999 } 1000 1001 bool NSSStreamAdapter::HaveExporter() { 1002 return true; 1003 } 1004 1005 } // namespace talk_base 1006 1007 #endif // HAVE_NSS_SSL_H 1008