147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/* 247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * Copyright 2004 The WebRTC Project Authors. All rights reserved. 347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * 447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * Use of this source code is governed by a BSD-style license 547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * that can be found in the LICENSE file in the root of the source 647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * tree. An additional intellectual property rights grant can be found 747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * in the file PATENTS. All contributing project authors may 847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * be found in the AUTHORS file in the root of the source tree. 947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org */ 1047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <vector> 1247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if HAVE_CONFIG_H 1447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "config.h" 1547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif // HAVE_CONFIG_H 1647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if HAVE_NSS_SSL_H 1847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/nssstreamadapter.h" 2047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 2147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "keyhi.h" 2247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "nspr.h" 2347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "nss.h" 2447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "pk11pub.h" 2547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "secerr.h" 2647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 2747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#ifdef NSS_SSL_RELATIVE_PATH 2847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "ssl.h" 2947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "sslerr.h" 3047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "sslproto.h" 3147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#else 3247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "net/third_party/nss/ssl/ssl.h" 3347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "net/third_party/nss/ssl/sslerr.h" 3447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "net/third_party/nss/ssl/sslproto.h" 3547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif 3647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 3747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/nssidentity.h" 3847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/safe_conversions.h" 3947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/thread.h" 4047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 4147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgnamespace rtc { 4247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 4347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgPRDescIdentity NSSStreamAdapter::nspr_layer_identity = PR_INVALID_IO_LAYER; 4447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 4547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#define UNIMPLEMENTED \ 4647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); \ 4747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) \ 4847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org << "Call to unimplemented function "<< __FUNCTION__; ASSERT(false) 4947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 5047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#ifdef SRTP_AES128_CM_HMAC_SHA1_80 5147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#define HAVE_DTLS_SRTP 5247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif 5347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 5447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#ifdef HAVE_DTLS_SRTP 5547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// SRTP cipher suite table 5647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstruct SrtpCipherMapEntry { 5747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const char* external_name; 5847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PRUint16 cipher_id; 5947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}; 6047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 6147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// This isn't elegant, but it's better than an external reference 6247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic const SrtpCipherMapEntry kSrtpCipherMap[] = { 6347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org {"AES_CM_128_HMAC_SHA1_80", SRTP_AES128_CM_HMAC_SHA1_80 }, 6447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org {"AES_CM_128_HMAC_SHA1_32", SRTP_AES128_CM_HMAC_SHA1_32 }, 6547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org {NULL, 0} 6647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}; 6747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif 6847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 6947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 7047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Implementation of NSPR methods 7147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic PRStatus StreamClose(PRFileDesc *socket) { 7247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(!socket->lower); 7347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org socket->dtor(socket); 7447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return PR_SUCCESS; 7547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 7647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 7747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic PRInt32 StreamRead(PRFileDesc *socket, void *buf, PRInt32 length) { 7847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamInterface *stream = reinterpret_cast<StreamInterface *>(socket->secret); 7947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org size_t read; 8047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int error; 8147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamResult result = stream->Read(buf, length, &read, &error); 8247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (result == SR_SUCCESS) { 8347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return checked_cast<PRInt32>(read); 8447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 8547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 8647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (result == SR_EOS) { 8747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return 0; 8847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 8947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 9047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (result == SR_BLOCK) { 9147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PR_SetError(PR_WOULD_BLOCK_ERROR, 0); 9247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 9347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 9447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 9547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PR_SetError(PR_UNKNOWN_ERROR, error); 9647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 9747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 9847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 9947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic PRInt32 StreamWrite(PRFileDesc *socket, const void *buf, 10047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PRInt32 length) { 10147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamInterface *stream = reinterpret_cast<StreamInterface *>(socket->secret); 10247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org size_t written; 10347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int error; 10447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamResult result = stream->Write(buf, length, &written, &error); 10547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (result == SR_SUCCESS) { 10647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return checked_cast<PRInt32>(written); 10747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 10847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 10947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (result == SR_BLOCK) { 11047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_INFO) << 11147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org "NSSStreamAdapter: write to underlying transport would block"; 11247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PR_SetError(PR_WOULD_BLOCK_ERROR, 0); 11347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 11447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 11547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 11647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << "Write error"; 11747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PR_SetError(PR_UNKNOWN_ERROR, error); 11847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 11947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 12047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 12147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic PRInt32 StreamAvailable(PRFileDesc *socket) { 12247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UNIMPLEMENTED; 12347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 12447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 12547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 12647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgPRInt64 StreamAvailable64(PRFileDesc *socket) { 12747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UNIMPLEMENTED; 12847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 12947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 13047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 13147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic PRStatus StreamSync(PRFileDesc *socket) { 13247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UNIMPLEMENTED; 13347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return PR_FAILURE; 13447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 13547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 13647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic PROffset32 StreamSeek(PRFileDesc *socket, PROffset32 offset, 13747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PRSeekWhence how) { 13847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UNIMPLEMENTED; 13947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 14047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 14147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 14247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic PROffset64 StreamSeek64(PRFileDesc *socket, PROffset64 offset, 14347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PRSeekWhence how) { 14447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UNIMPLEMENTED; 14547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 14647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 14747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 14847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic PRStatus StreamFileInfo(PRFileDesc *socket, PRFileInfo *info) { 14947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UNIMPLEMENTED; 15047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return PR_FAILURE; 15147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 15247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 15347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic PRStatus StreamFileInfo64(PRFileDesc *socket, PRFileInfo64 *info) { 15447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UNIMPLEMENTED; 15547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return PR_FAILURE; 15647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 15747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 15847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic PRInt32 StreamWritev(PRFileDesc *socket, const PRIOVec *iov, 15947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PRInt32 iov_size, PRIntervalTime timeout) { 16047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UNIMPLEMENTED; 16147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 16247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 16347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 16447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic PRStatus StreamConnect(PRFileDesc *socket, const PRNetAddr *addr, 16547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PRIntervalTime timeout) { 16647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UNIMPLEMENTED; 16747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return PR_FAILURE; 16847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 16947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 17047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic PRFileDesc *StreamAccept(PRFileDesc *sd, PRNetAddr *addr, 17147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PRIntervalTime timeout) { 17247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UNIMPLEMENTED; 17347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return NULL; 17447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 17547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 17647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic PRStatus StreamBind(PRFileDesc *socket, const PRNetAddr *addr) { 17747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UNIMPLEMENTED; 17847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return PR_FAILURE; 17947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 18047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 18147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic PRStatus StreamListen(PRFileDesc *socket, PRIntn depth) { 18247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UNIMPLEMENTED; 18347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return PR_FAILURE; 18447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 18547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 18647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic PRStatus StreamShutdown(PRFileDesc *socket, PRIntn how) { 18747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UNIMPLEMENTED; 18847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return PR_FAILURE; 18947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 19047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 19147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Note: this is always nonblocking and ignores the timeout. 19247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// TODO(ekr@rtfm.com): In future verify that the socket is 19347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// actually in non-blocking mode. 19447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// This function does not support peek. 19547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic PRInt32 StreamRecv(PRFileDesc *socket, void *buf, PRInt32 amount, 19647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PRIntn flags, PRIntervalTime to) { 19747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(flags == 0); 19847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 19947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (flags != 0) { 20047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); 20147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 20247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 20347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 20447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return StreamRead(socket, buf, amount); 20547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 20647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 20747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Note: this is always nonblocking and assumes a zero timeout. 20847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// This function does not support peek. 20947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic PRInt32 StreamSend(PRFileDesc *socket, const void *buf, 21047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PRInt32 amount, PRIntn flags, 21147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PRIntervalTime to) { 21247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(flags == 0); 21347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 21447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return StreamWrite(socket, buf, amount); 21547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 21647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 21747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic PRInt32 StreamRecvfrom(PRFileDesc *socket, void *buf, 21847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PRInt32 amount, PRIntn flags, 21947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PRNetAddr *addr, PRIntervalTime to) { 22047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UNIMPLEMENTED; 22147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 22247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 22347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 22447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic PRInt32 StreamSendto(PRFileDesc *socket, const void *buf, 22547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PRInt32 amount, PRIntn flags, 22647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const PRNetAddr *addr, PRIntervalTime to) { 22747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UNIMPLEMENTED; 22847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 22947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 23047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 23147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic PRInt16 StreamPoll(PRFileDesc *socket, PRInt16 in_flags, 23247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PRInt16 *out_flags) { 23347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UNIMPLEMENTED; 23447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 23547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 23647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 23747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic PRInt32 StreamAcceptRead(PRFileDesc *sd, PRFileDesc **nd, 23847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PRNetAddr **raddr, 23947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org void *buf, PRInt32 amount, PRIntervalTime t) { 24047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UNIMPLEMENTED; 24147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 24247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 24347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 24447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic PRInt32 StreamTransmitFile(PRFileDesc *sd, PRFileDesc *socket, 24547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const void *headers, PRInt32 hlen, 24647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PRTransmitFileFlags flags, PRIntervalTime t) { 24747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UNIMPLEMENTED; 24847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 24947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 25047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 25147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic PRStatus StreamGetPeerName(PRFileDesc *socket, PRNetAddr *addr) { 25247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // TODO(ekr@rtfm.com): Modify to return unique names for each channel 25347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // somehow, as opposed to always the same static address. The current 25447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // implementation messes up the session cache, which is why it's off 25547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // elsewhere 25647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org addr->inet.family = PR_AF_INET; 25747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org addr->inet.port = 0; 25847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org addr->inet.ip = 0; 25947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 26047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return PR_SUCCESS; 26147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 26247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 26347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic PRStatus StreamGetSockName(PRFileDesc *socket, PRNetAddr *addr) { 26447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UNIMPLEMENTED; 26547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return PR_FAILURE; 26647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 26747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 26847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic PRStatus StreamGetSockOption(PRFileDesc *socket, PRSocketOptionData *opt) { 26947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org switch (opt->option) { 27047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case PR_SockOpt_Nonblocking: 27147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org opt->value.non_blocking = PR_TRUE; 27247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return PR_SUCCESS; 27347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org default: 27447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UNIMPLEMENTED; 27547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 27647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 27747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 27847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return PR_FAILURE; 27947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 28047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 28147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Imitate setting socket options. These are mostly noops. 28247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic PRStatus StreamSetSockOption(PRFileDesc *socket, 28347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const PRSocketOptionData *opt) { 28447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org switch (opt->option) { 28547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case PR_SockOpt_Nonblocking: 28647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return PR_SUCCESS; 28747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case PR_SockOpt_NoDelay: 28847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return PR_SUCCESS; 28947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org default: 29047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UNIMPLEMENTED; 29147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 29247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 29347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 29447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return PR_FAILURE; 29547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 29647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 29747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic PRInt32 StreamSendfile(PRFileDesc *out, PRSendFileData *in, 29847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PRTransmitFileFlags flags, PRIntervalTime to) { 29947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UNIMPLEMENTED; 30047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 30147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 30247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 30347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic PRStatus StreamConnectContinue(PRFileDesc *socket, PRInt16 flags) { 30447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UNIMPLEMENTED; 30547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return PR_FAILURE; 30647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 30747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 30847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic PRIntn StreamReserved(PRFileDesc *socket) { 30947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UNIMPLEMENTED; 31047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 31147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 31247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 31347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic const struct PRIOMethods nss_methods = { 31447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PR_DESC_LAYERED, 31547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamClose, 31647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamRead, 31747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamWrite, 31847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamAvailable, 31947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamAvailable64, 32047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamSync, 32147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamSeek, 32247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamSeek64, 32347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamFileInfo, 32447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamFileInfo64, 32547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamWritev, 32647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamConnect, 32747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamAccept, 32847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamBind, 32947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamListen, 33047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamShutdown, 33147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamRecv, 33247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamSend, 33347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamRecvfrom, 33447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamSendto, 33547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamPoll, 33647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamAcceptRead, 33747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamTransmitFile, 33847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamGetSockName, 33947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamGetPeerName, 34047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamReserved, 34147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamReserved, 34247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamGetSockOption, 34347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamSetSockOption, 34447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamSendfile, 34547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamConnectContinue, 34647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamReserved, 34747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamReserved, 34847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamReserved, 34947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamReserved 35047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}; 35147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 35247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgNSSStreamAdapter::NSSStreamAdapter(StreamInterface *stream) 35347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org : SSLStreamAdapterHelper(stream), 35447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ssl_fd_(NULL), 35547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org cert_ok_(false) { 35647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 35747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 35847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool NSSStreamAdapter::Init() { 35947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (nspr_layer_identity == PR_INVALID_IO_LAYER) { 36047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org nspr_layer_identity = PR_GetUniqueIdentity("nssstreamadapter"); 36147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 36247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PRFileDesc *pr_fd = PR_CreateIOLayerStub(nspr_layer_identity, &nss_methods); 36347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!pr_fd) 36447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 36547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org pr_fd->secret = reinterpret_cast<PRFilePrivate *>(stream()); 36647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 36747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PRFileDesc *ssl_fd; 36847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (ssl_mode_ == SSL_MODE_DTLS) { 36947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ssl_fd = DTLS_ImportFD(NULL, pr_fd); 37047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 37147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ssl_fd = SSL_ImportFD(NULL, pr_fd); 37247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 37347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(ssl_fd != NULL); // This should never happen 37447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!ssl_fd) { 37547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PR_Close(pr_fd); 37647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 37747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 37847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 37947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SECStatus rv; 38047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Turn on security. 38147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org rv = SSL_OptionSet(ssl_fd, SSL_SECURITY, PR_TRUE); 38247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (rv != SECSuccess) { 38347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << "Error enabling security on SSL Socket"; 38447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 38547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 38647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 38747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Disable SSLv2. 38847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_SSL2, PR_FALSE); 38947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (rv != SECSuccess) { 39047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << "Error disabling SSL2"; 39147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 39247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 39347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 39447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Disable caching. 39547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // TODO(ekr@rtfm.com): restore this when I have the caching 39647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // identity set. 39747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org rv = SSL_OptionSet(ssl_fd, SSL_NO_CACHE, PR_TRUE); 39847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (rv != SECSuccess) { 39947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << "Error disabling cache"; 40047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 40147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 40247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 40347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Disable session tickets. 40447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_SESSION_TICKETS, PR_FALSE); 40547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (rv != SECSuccess) { 40647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << "Error enabling tickets"; 40747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 40847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 40947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 41047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Disable renegotiation. 41147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_RENEGOTIATION, 41247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SSL_RENEGOTIATE_NEVER); 41347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (rv != SECSuccess) { 41447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << "Error disabling renegotiation"; 41547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 41647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 41747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 41847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Disable false start. 41947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_FALSE_START, PR_FALSE); 42047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (rv != SECSuccess) { 42147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << "Error disabling false start"; 42247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 42347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 42447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 42547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ssl_fd_ = ssl_fd; 42647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 42747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return true; 42847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 42947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 43047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgNSSStreamAdapter::~NSSStreamAdapter() { 43147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (ssl_fd_) 43247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PR_Close(ssl_fd_); 43347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}; 43447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 43547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 43647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint NSSStreamAdapter::BeginSSL() { 43747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SECStatus rv; 43847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 43947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!Init()) { 44047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Error("Init", -1, false); 44147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 44247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 44347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 44447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(state_ == SSL_CONNECTING); 44547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // The underlying stream has been opened. If we are in peer-to-peer mode 44647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // then a peer certificate must have been specified by now. 44747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(!ssl_server_name_.empty() || 44847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org peer_certificate_.get() != NULL || 44947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org !peer_certificate_digest_algorithm_.empty()); 45047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_INFO) << "BeginSSL: " 45147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org << (!ssl_server_name_.empty() ? ssl_server_name_ : 45247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org "with peer"); 45347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 45447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (role_ == SSL_CLIENT) { 45547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_INFO) << "BeginSSL: as client"; 45647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 45747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org rv = SSL_GetClientAuthDataHook(ssl_fd_, GetClientAuthDataHook, 45847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org this); 45947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (rv != SECSuccess) { 46047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Error("BeginSSL", -1, false); 46147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 46247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 46347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 46447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_INFO) << "BeginSSL: as server"; 46547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org NSSIdentity *identity; 46647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 46747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (identity_.get()) { 46847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org identity = static_cast<NSSIdentity *>(identity_.get()); 46947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 47047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << "Can't be an SSL server without an identity"; 47147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Error("BeginSSL", -1, false); 47247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 47347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 47447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org rv = SSL_ConfigSecureServer(ssl_fd_, identity->certificate().certificate(), 47547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org identity->keypair()->privkey(), 47647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org kt_rsa); 47747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (rv != SECSuccess) { 47847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Error("BeginSSL", -1, false); 47947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 48047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 48147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 48247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Insist on a certificate from the client 48347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org rv = SSL_OptionSet(ssl_fd_, SSL_REQUEST_CERTIFICATE, PR_TRUE); 48447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (rv != SECSuccess) { 48547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Error("BeginSSL", -1, false); 48647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 48747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 48847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 4894f81cfbdcc099ef101e726a7b1fa8bfc30a23d49tkchin@webrtc.org // TODO(juberti): Check for client_auth_enabled() 4904f81cfbdcc099ef101e726a7b1fa8bfc30a23d49tkchin@webrtc.org 49147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org rv = SSL_OptionSet(ssl_fd_, SSL_REQUIRE_CERTIFICATE, PR_TRUE); 49247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (rv != SECSuccess) { 49347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Error("BeginSSL", -1, false); 49447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 49547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 49647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 49747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 49847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Set the version range. 49947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SSLVersionRange vrange; 50047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org vrange.min = (ssl_mode_ == SSL_MODE_DTLS) ? 50147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SSL_LIBRARY_VERSION_TLS_1_1 : 50247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SSL_LIBRARY_VERSION_TLS_1_0; 50347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org vrange.max = SSL_LIBRARY_VERSION_TLS_1_1; 50447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 50547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org rv = SSL_VersionRangeSet(ssl_fd_, &vrange); 50647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (rv != SECSuccess) { 50747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Error("BeginSSL", -1, false); 50847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 50947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 51047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 51147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // SRTP 51247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#ifdef HAVE_DTLS_SRTP 51347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!srtp_ciphers_.empty()) { 51447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org rv = SSL_SetSRTPCiphers( 51547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ssl_fd_, &srtp_ciphers_[0], 51647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org checked_cast<unsigned int>(srtp_ciphers_.size())); 51747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (rv != SECSuccess) { 51847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Error("BeginSSL", -1, false); 51947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 52047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 52147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 52247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif 52347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 52447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Certificate validation 52547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org rv = SSL_AuthCertificateHook(ssl_fd_, AuthCertificateHook, this); 52647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (rv != SECSuccess) { 52747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Error("BeginSSL", -1, false); 52847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 52947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 53047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 53147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Now start the handshake 53247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org rv = SSL_ResetHandshake(ssl_fd_, role_ == SSL_SERVER ? PR_TRUE : PR_FALSE); 53347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (rv != SECSuccess) { 53447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Error("BeginSSL", -1, false); 53547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 53647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 53747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 53847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return ContinueSSL(); 53947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 54047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 54147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint NSSStreamAdapter::ContinueSSL() { 54247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_INFO) << "ContinueSSL"; 54347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(state_ == SSL_CONNECTING); 54447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 54547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Clear the DTLS timer 54647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Thread::Current()->Clear(this, MSG_DTLS_TIMEOUT); 54747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 54847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SECStatus rv = SSL_ForceHandshake(ssl_fd_); 54947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 55047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (rv == SECSuccess) { 55147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_INFO) << "Handshake complete"; 55247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 55347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(cert_ok_); 55447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!cert_ok_) { 55547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Error("ContinueSSL", -1, true); 55647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 55747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 55847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 55947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org state_ = SSL_CONNECTED; 56047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamAdapterInterface::OnEvent(stream(), SE_OPEN|SE_READ|SE_WRITE, 0); 56147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return 0; 56247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 56347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 56447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PRInt32 err = PR_GetError(); 56547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org switch (err) { 56647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case SSL_ERROR_RX_MALFORMED_HANDSHAKE: 56747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (ssl_mode_ != SSL_MODE_DTLS) { 56847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Error("ContinueSSL", -1, true); 56947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 57047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 57147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_INFO) << "Malformed DTLS message. Ignoring."; 57247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Fall through 57347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 57447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case PR_WOULD_BLOCK_ERROR: 57547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_INFO) << "Would have blocked"; 57647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (ssl_mode_ == SSL_MODE_DTLS) { 57747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PRIntervalTime timeout; 57847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 57947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SECStatus rv = DTLS_GetHandshakeTimeout(ssl_fd_, &timeout); 58047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (rv == SECSuccess) { 58147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_INFO) << "Timeout is " << timeout << " ms"; 58247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Thread::Current()->PostDelayed(PR_IntervalToMilliseconds(timeout), 58347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org this, MSG_DTLS_TIMEOUT, 0); 58447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 58547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 58647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 58747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return 0; 58847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org default: 58947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_INFO) << "Error " << err; 59047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 59147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 59247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 59347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Error("ContinueSSL", -1, true); 59447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 59547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 59647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 59747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid NSSStreamAdapter::Cleanup() { 59847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (state_ != SSL_ERROR) { 59947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org state_ = SSL_CLOSED; 60047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 60147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 60247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (ssl_fd_) { 60347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PR_Close(ssl_fd_); 60447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ssl_fd_ = NULL; 60547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 60647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 60747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org identity_.reset(); 60847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org peer_certificate_.reset(); 60947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 61047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Thread::Current()->Clear(this, MSG_DTLS_TIMEOUT); 61147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 61247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 61347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgStreamResult NSSStreamAdapter::Read(void* data, size_t data_len, 61447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org size_t* read, int* error) { 61547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // SSL_CONNECTED sanity check. 61647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org switch (state_) { 61747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case SSL_NONE: 61847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case SSL_WAIT: 61947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case SSL_CONNECTING: 62047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SR_BLOCK; 62147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 62247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case SSL_CONNECTED: 62347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 62447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 62547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case SSL_CLOSED: 62647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SR_EOS; 62747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 62847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case SSL_ERROR: 62947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org default: 63047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (error) 63147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *error = ssl_error_code_; 63247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SR_ERROR; 63347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 63447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 63547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PRInt32 rv = PR_Read(ssl_fd_, data, checked_cast<PRInt32>(data_len)); 63647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 63747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (rv == 0) { 63847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SR_EOS; 63947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 64047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 64147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Error 64247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (rv < 0) { 64347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PRInt32 err = PR_GetError(); 64447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 64547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org switch (err) { 64647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case PR_WOULD_BLOCK_ERROR: 64747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SR_BLOCK; 64847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org default: 64947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Error("Read", -1, false); 65047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *error = err; // libjingle semantics are that this is impl-specific 65147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SR_ERROR; 65247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 65347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 65447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 65547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Success 65647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *read = rv; 65747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 65847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SR_SUCCESS; 65947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 66047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 66147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgStreamResult NSSStreamAdapter::Write(const void* data, size_t data_len, 66247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org size_t* written, int* error) { 66347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // SSL_CONNECTED sanity check. 66447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org switch (state_) { 66547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case SSL_NONE: 66647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case SSL_WAIT: 66747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case SSL_CONNECTING: 66847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SR_BLOCK; 66947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 67047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case SSL_CONNECTED: 67147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 67247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 67347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case SSL_ERROR: 67447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case SSL_CLOSED: 67547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org default: 67647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (error) 67747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *error = ssl_error_code_; 67847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SR_ERROR; 67947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 68047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 68147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PRInt32 rv = PR_Write(ssl_fd_, data, checked_cast<PRInt32>(data_len)); 68247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 68347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Error 68447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (rv < 0) { 68547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PRInt32 err = PR_GetError(); 68647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 68747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org switch (err) { 68847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case PR_WOULD_BLOCK_ERROR: 68947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SR_BLOCK; 69047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org default: 69147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Error("Write", -1, false); 69247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *error = err; // libjingle semantics are that this is impl-specific 69347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SR_ERROR; 69447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 69547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 69647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 69747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Success 69847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *written = rv; 69947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 70047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SR_SUCCESS; 70147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 70247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 70347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid NSSStreamAdapter::OnEvent(StreamInterface* stream, int events, 70447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int err) { 70547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int events_to_signal = 0; 70647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int signal_error = 0; 70747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(stream == this->stream()); 70847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if ((events & SE_OPEN)) { 70947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_INFO) << "NSSStreamAdapter::OnEvent SE_OPEN"; 71047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (state_ != SSL_WAIT) { 71147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(state_ == SSL_NONE); 71247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org events_to_signal |= SE_OPEN; 71347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 71447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org state_ = SSL_CONNECTING; 71547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (int err = BeginSSL()) { 71647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Error("BeginSSL", err, true); 71747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return; 71847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 71947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 72047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 72147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if ((events & (SE_READ|SE_WRITE))) { 72247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_INFO) << "NSSStreamAdapter::OnEvent" 72347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org << ((events & SE_READ) ? " SE_READ" : "") 72447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org << ((events & SE_WRITE) ? " SE_WRITE" : ""); 72547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (state_ == SSL_NONE) { 72647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org events_to_signal |= events & (SE_READ|SE_WRITE); 72747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else if (state_ == SSL_CONNECTING) { 72847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (int err = ContinueSSL()) { 72947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Error("ContinueSSL", err, true); 73047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return; 73147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 73247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else if (state_ == SSL_CONNECTED) { 73347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (events & SE_WRITE) { 73447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_INFO) << " -- onStreamWriteable"; 73547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org events_to_signal |= SE_WRITE; 73647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 73747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (events & SE_READ) { 73847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_INFO) << " -- onStreamReadable"; 73947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org events_to_signal |= SE_READ; 74047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 74147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 74247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 74347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if ((events & SE_CLOSE)) { 74447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_INFO) << "NSSStreamAdapter::OnEvent(SE_CLOSE, " << err << ")"; 74547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Cleanup(); 74647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org events_to_signal |= SE_CLOSE; 74747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // SE_CLOSE is the only event that uses the final parameter to OnEvent(). 74847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(signal_error == 0); 74947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org signal_error = err; 75047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 75147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (events_to_signal) 75247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamAdapterInterface::OnEvent(stream, events_to_signal, signal_error); 75347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 75447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 75547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid NSSStreamAdapter::OnMessage(Message* msg) { 75647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Process our own messages and then pass others to the superclass 75747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (MSG_DTLS_TIMEOUT == msg->message_id) { 75847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_INFO) << "DTLS timeout expired"; 75947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ContinueSSL(); 76047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 76147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StreamInterface::OnMessage(msg); 76247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 76347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 76447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 76547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Certificate verification callback. Called to check any certificate 76647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSECStatus NSSStreamAdapter::AuthCertificateHook(void *arg, 76747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PRFileDesc *fd, 76847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PRBool checksig, 76947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PRBool isServer) { 77047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_INFO) << "NSSStreamAdapter::AuthCertificateHook"; 77147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // SSL_PeerCertificate returns a pointer that is owned by the caller, and 77247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // the NSSCertificate constructor copies its argument, so |raw_peer_cert| 77347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // must be destroyed in this function. 77447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CERTCertificate* raw_peer_cert = SSL_PeerCertificate(fd); 77547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org NSSCertificate peer_cert(raw_peer_cert); 77647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CERT_DestroyCertificate(raw_peer_cert); 77747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 77847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org NSSStreamAdapter *stream = reinterpret_cast<NSSStreamAdapter *>(arg); 77947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org stream->cert_ok_ = false; 78047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 78147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Read the peer's certificate chain. 78247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CERTCertList* cert_list = SSL_PeerCertificateChain(fd); 78347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(cert_list != NULL); 78447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 78547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // If the peer provided multiple certificates, check that they form a valid 78647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // chain as defined by RFC 5246 Section 7.4.2: "Each following certificate 78747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // MUST directly certify the one preceding it.". This check does NOT 78847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // verify other requirements, such as whether the chain reaches a trusted 78947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // root, self-signed certificates have valid signatures, certificates are not 79047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // expired, etc. 79147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Even if the chain is valid, the leaf certificate must still match a 79247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // provided certificate or digest. 79347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!NSSCertificate::IsValidChain(cert_list)) { 79447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CERT_DestroyCertList(cert_list); 79547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PORT_SetError(SEC_ERROR_BAD_SIGNATURE); 79647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SECFailure; 79747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 79847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 79947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (stream->peer_certificate_.get()) { 80047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_INFO) << "Checking against specified certificate"; 80147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 80247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // The peer certificate was specified 80347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (reinterpret_cast<NSSCertificate *>(stream->peer_certificate_.get())-> 80447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Equals(&peer_cert)) { 80547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_INFO) << "Accepted peer certificate"; 80647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org stream->cert_ok_ = true; 80747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 80847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else if (!stream->peer_certificate_digest_algorithm_.empty()) { 80947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_INFO) << "Checking against specified digest"; 81047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // The peer certificate digest was specified 81147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org unsigned char digest[64]; // Maximum size 81247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org size_t digest_length; 81347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 81447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!peer_cert.ComputeDigest( 81547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org stream->peer_certificate_digest_algorithm_, 81647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org digest, sizeof(digest), &digest_length)) { 81747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << "Digest computation failed"; 81847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 81947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Buffer computed_digest(digest, digest_length); 82047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (computed_digest == stream->peer_certificate_digest_value_) { 82147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_INFO) << "Accepted peer certificate"; 82247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org stream->cert_ok_ = true; 82347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 82447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 82547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 82647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Other modes, but we haven't implemented yet 82747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // TODO(ekr@rtfm.com): Implement real certificate validation 82847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UNIMPLEMENTED; 82947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 83047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 83147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!stream->cert_ok_ && stream->ignore_bad_cert()) { 83247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_WARNING) << "Ignoring cert error while verifying cert chain"; 83347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org stream->cert_ok_ = true; 83447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 83547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 83647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (stream->cert_ok_) 83747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org stream->peer_certificate_.reset(new NSSCertificate(cert_list)); 83847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 83947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CERT_DestroyCertList(cert_list); 84047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 84147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (stream->cert_ok_) 84247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SECSuccess; 84347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 84447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PORT_SetError(SEC_ERROR_UNTRUSTED_CERT); 84547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SECFailure; 84647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 84747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 84847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 84947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSECStatus NSSStreamAdapter::GetClientAuthDataHook(void *arg, PRFileDesc *fd, 85047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CERTDistNames *caNames, 85147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CERTCertificate **pRetCert, 85247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SECKEYPrivateKey **pRetKey) { 85347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_INFO) << "Client cert requested"; 85447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org NSSStreamAdapter *stream = reinterpret_cast<NSSStreamAdapter *>(arg); 85547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 85647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!stream->identity_.get()) { 85747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << "No identity available"; 85847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SECFailure; 85947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 86047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 86147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org NSSIdentity *identity = static_cast<NSSIdentity *>(stream->identity_.get()); 86247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Destroyed internally by NSS 86347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *pRetCert = CERT_DupCertificate(identity->certificate().certificate()); 86447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *pRetKey = SECKEY_CopyPrivateKey(identity->keypair()->privkey()); 86547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 86647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SECSuccess; 86747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 86847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 86947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// RFC 5705 Key Exporter 87047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool NSSStreamAdapter::ExportKeyingMaterial(const std::string& label, 87147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const uint8* context, 87247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org size_t context_len, 87347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org bool use_context, 87447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org uint8* result, 87547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org size_t result_len) { 87647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SECStatus rv = SSL_ExportKeyingMaterial( 87747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ssl_fd_, 87847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org label.c_str(), 87947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org checked_cast<unsigned int>(label.size()), 88047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org use_context, 88147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org context, 88247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org checked_cast<unsigned int>(context_len), 88347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org result, 88447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org checked_cast<unsigned int>(result_len)); 88547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 88647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return rv == SECSuccess; 88747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 88847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 88947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool NSSStreamAdapter::SetDtlsSrtpCiphers( 89047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const std::vector<std::string>& ciphers) { 89147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#ifdef HAVE_DTLS_SRTP 89247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org std::vector<PRUint16> internal_ciphers; 89347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (state_ != SSL_NONE) 89447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 89547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 89647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org for (std::vector<std::string>::const_iterator cipher = ciphers.begin(); 89747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org cipher != ciphers.end(); ++cipher) { 89847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org bool found = false; 89947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org for (const SrtpCipherMapEntry *entry = kSrtpCipherMap; entry->cipher_id; 90047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ++entry) { 90147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (*cipher == entry->external_name) { 90247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org found = true; 90347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org internal_ciphers.push_back(entry->cipher_id); 90447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 90547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 90647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 90747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 90847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!found) { 90947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << "Could not find cipher: " << *cipher; 91047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 91147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 91247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 91347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 91447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (internal_ciphers.empty()) 91547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 91647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 91747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org srtp_ciphers_ = internal_ciphers; 91847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 91947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return true; 92047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#else 92147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 92247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif 92347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 92447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 92547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool NSSStreamAdapter::GetDtlsSrtpCipher(std::string* cipher) { 92647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#ifdef HAVE_DTLS_SRTP 92747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(state_ == SSL_CONNECTED); 92847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (state_ != SSL_CONNECTED) 92947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 93047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 93147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PRUint16 selected_cipher; 93247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 93347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SECStatus rv = SSL_GetSRTPCipher(ssl_fd_, &selected_cipher); 93447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (rv == SECFailure) 93547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 93647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 93747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org for (const SrtpCipherMapEntry *entry = kSrtpCipherMap; 93847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org entry->cipher_id; ++entry) { 93947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (selected_cipher == entry->cipher_id) { 94047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *cipher = entry->external_name; 94147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return true; 94247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 94347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 94447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 94547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(false); // This should never happen 94647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif 94747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 94847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 94947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 95047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 95147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool NSSContext::initialized; 95247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgNSSContext *NSSContext::global_nss_context; 95347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 95447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Static initialization and shutdown 95547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgNSSContext *NSSContext::Instance() { 95647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!global_nss_context) { 9579fbd3ec906560447cebb21681c7e79e37c2eed83tommi@webrtc.org scoped_ptr<NSSContext> new_ctx(new NSSContext()); 9589fbd3ec906560447cebb21681c7e79e37c2eed83tommi@webrtc.org new_ctx->slot_ = PK11_GetInternalSlot(); 9599fbd3ec906560447cebb21681c7e79e37c2eed83tommi@webrtc.org if (new_ctx->slot_) 9609fbd3ec906560447cebb21681c7e79e37c2eed83tommi@webrtc.org global_nss_context = new_ctx.release(); 96147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 96247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return global_nss_context; 96347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 96447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 96547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 96647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 96747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool NSSContext::InitializeSSL(VerificationCallback callback) { 96847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(!callback); 96947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 97047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!initialized) { 97147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SECStatus rv; 97247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 97347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org rv = NSS_NoDB_Init(NULL); 97447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (rv != SECSuccess) { 97547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << "Couldn't initialize NSS error=" << 97647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PORT_GetError(); 97747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 97847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 97947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 98047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org NSS_SetDomesticPolicy(); 98147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 98247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org initialized = true; 98347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 98447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 98547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return true; 98647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 98747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 98847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool NSSContext::InitializeSSLThread() { 98947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Not needed 99047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return true; 99147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 99247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 99347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool NSSContext::CleanupSSL() { 99447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Not needed 99547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return true; 99647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 99747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 99847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool NSSStreamAdapter::HaveDtls() { 99947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return true; 100047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 100147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 100247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool NSSStreamAdapter::HaveDtlsSrtp() { 100347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#ifdef HAVE_DTLS_SRTP 100447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return true; 100547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#else 100647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 100747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif 100847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 100947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 101047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool NSSStreamAdapter::HaveExporter() { 101147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return true; 101247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 101347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 101447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} // namespace rtc 101547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 101647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif // HAVE_NSS_SSL_H 1017