michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim: set ts=2 et sw=2 tw=80: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: // Original author: ekr@rtfm.com michael@0: michael@0: #ifndef transportlayerdtls_h__ michael@0: #define transportlayerdtls_h__ michael@0: michael@0: #include michael@0: michael@0: #include "sigslot.h" michael@0: michael@0: #include "mozilla/RefPtr.h" michael@0: #include "mozilla/Scoped.h" michael@0: #include "nsCOMPtr.h" michael@0: #include "nsIEventTarget.h" michael@0: #include "nsITimer.h" michael@0: #include "ScopedNSSTypes.h" michael@0: #include "m_cpp_utils.h" michael@0: #include "dtlsidentity.h" michael@0: #include "transportflow.h" michael@0: #include "transportlayer.h" michael@0: michael@0: namespace mozilla { michael@0: michael@0: struct Packet; michael@0: michael@0: class TransportLayerNSPRAdapter { michael@0: public: michael@0: TransportLayerNSPRAdapter(TransportLayer *output) : michael@0: output_(output), michael@0: input_() {} michael@0: michael@0: void PacketReceived(const void *data, int32_t len); michael@0: int32_t Read(void *data, int32_t len); michael@0: int32_t Write(const void *buf, int32_t length); michael@0: michael@0: private: michael@0: DISALLOW_COPY_ASSIGN(TransportLayerNSPRAdapter); michael@0: michael@0: TransportLayer *output_; michael@0: std::queue input_; michael@0: }; michael@0: michael@0: class TransportLayerDtls : public TransportLayer { michael@0: public: michael@0: TransportLayerDtls() : michael@0: TransportLayer(DGRAM), michael@0: role_(CLIENT), michael@0: verification_mode_(VERIFY_UNSET), michael@0: ssl_fd_(nullptr), michael@0: auth_hook_called_(false), michael@0: cert_ok_(false) {} michael@0: michael@0: virtual ~TransportLayerDtls(); michael@0: michael@0: enum Role { CLIENT, SERVER}; michael@0: enum Verification { VERIFY_UNSET, VERIFY_ALLOW_ALL, VERIFY_DIGEST}; michael@0: const static size_t kMaxDigestLength = HASH_LENGTH_MAX; michael@0: michael@0: // DTLS-specific operations michael@0: void SetRole(Role role) { role_ = role;} michael@0: Role role() { return role_; } michael@0: michael@0: void SetIdentity(const RefPtr& identity) { michael@0: identity_ = identity; michael@0: } michael@0: nsresult SetVerificationAllowAll(); michael@0: nsresult SetVerificationDigest(const std::string digest_algorithm, michael@0: const unsigned char *digest_value, michael@0: size_t digest_len); michael@0: michael@0: nsresult SetSrtpCiphers(std::vector ciphers); michael@0: nsresult GetSrtpCipher(uint16_t *cipher); michael@0: michael@0: nsresult ExportKeyingMaterial(const std::string& label, michael@0: bool use_context, michael@0: const std::string& context, michael@0: unsigned char *out, michael@0: unsigned int outlen); michael@0: michael@0: const CERTCertificate *GetPeerCert() const { michael@0: return peer_cert_; michael@0: } michael@0: michael@0: // Transport layer overrides. michael@0: virtual nsresult InitInternal(); michael@0: virtual void WasInserted(); michael@0: virtual TransportResult SendPacket(const unsigned char *data, size_t len); michael@0: michael@0: // Signals michael@0: void StateChange(TransportLayer *layer, State state); michael@0: void PacketReceived(TransportLayer* layer, const unsigned char *data, michael@0: size_t len); michael@0: michael@0: TRANSPORT_LAYER_ID("dtls") michael@0: michael@0: private: michael@0: DISALLOW_COPY_ASSIGN(TransportLayerDtls); michael@0: michael@0: // A single digest to check michael@0: class VerificationDigest { michael@0: public: michael@0: VerificationDigest(std::string algorithm, michael@0: const unsigned char *value, size_t len) { michael@0: MOZ_ASSERT(len <= sizeof(value_)); michael@0: michael@0: algorithm_ = algorithm; michael@0: memcpy(value_, value, len); michael@0: len_ = len; michael@0: } michael@0: michael@0: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VerificationDigest) michael@0: michael@0: std::string algorithm_; michael@0: size_t len_; michael@0: unsigned char value_[kMaxDigestLength]; michael@0: michael@0: private: michael@0: DISALLOW_COPY_ASSIGN(VerificationDigest); michael@0: }; michael@0: michael@0: michael@0: bool Setup(); michael@0: void Handshake(); michael@0: michael@0: static SECStatus GetClientAuthDataHook(void *arg, PRFileDesc *fd, michael@0: CERTDistNames *caNames, michael@0: CERTCertificate **pRetCert, michael@0: SECKEYPrivateKey **pRetKey); michael@0: static SECStatus AuthCertificateHook(void *arg, michael@0: PRFileDesc *fd, michael@0: PRBool checksig, michael@0: PRBool isServer); michael@0: SECStatus AuthCertificateHook(PRFileDesc *fd, michael@0: PRBool checksig, michael@0: PRBool isServer); michael@0: michael@0: static void TimerCallback(nsITimer *timer, void *arg); michael@0: michael@0: SECStatus CheckDigest(const RefPtr& digest, michael@0: CERTCertificate *cert); michael@0: michael@0: RefPtr identity_; michael@0: std::vector srtp_ciphers_; michael@0: michael@0: Role role_; michael@0: Verification verification_mode_; michael@0: std::vector > digests_; michael@0: michael@0: // Must delete nspr_io_adapter after ssl_fd_ b/c ssl_fd_ causes an alert michael@0: // (ssl_fd_ contains an un-owning pointer to nspr_io_adapter_) michael@0: ScopedDeletePtr nspr_io_adapter_; michael@0: ScopedPRFileDesc ssl_fd_; michael@0: michael@0: ScopedCERTCertificate peer_cert_; michael@0: nsCOMPtr timer_; michael@0: bool auth_hook_called_; michael@0: bool cert_ok_; michael@0: }; michael@0: michael@0: michael@0: } // close namespace michael@0: #endif