diff --git a/webrtc/base/BUILD.gn b/webrtc/base/BUILD.gn index 04df46b47e..d81720652c 100644 --- a/webrtc/base/BUILD.gn +++ b/webrtc/base/BUILD.gn @@ -393,6 +393,8 @@ rtc_static_library("rtc_base") { "asyncudpsocket.h", "crc32.cc", "crc32.h", + "cryptstring.cc", + "cryptstring.h", "filerotatingstream.cc", "filerotatingstream.h", "fileutils.cc", diff --git a/webrtc/base/cryptstring.cc b/webrtc/base/cryptstring.cc new file mode 100644 index 0000000000..4b2a83fca9 --- /dev/null +++ b/webrtc/base/cryptstring.cc @@ -0,0 +1,75 @@ +/* + * Copyright 2015 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "webrtc/base/cryptstring.h" + +namespace rtc { + +size_t EmptyCryptStringImpl::GetLength() const { + return 0; +} + +void EmptyCryptStringImpl::CopyTo(char* dest, bool nullterminate) const { + if (nullterminate) { + *dest = '\0'; + } +} + +std::string EmptyCryptStringImpl::UrlEncode() const { + return ""; +} + +CryptStringImpl* EmptyCryptStringImpl::Copy() const { + return new EmptyCryptStringImpl(); +} + +void EmptyCryptStringImpl::CopyRawTo(std::vector* dest) const { + dest->clear(); +} + +CryptString::CryptString() : impl_(new EmptyCryptStringImpl()) { +} + +CryptString::CryptString(const CryptString& other) + : impl_(other.impl_->Copy()) { +} + +CryptString::CryptString(const CryptStringImpl& impl) : impl_(impl.Copy()) { +} + +CryptString::~CryptString() = default; + +size_t InsecureCryptStringImpl::GetLength() const { + return password_.size(); +} + +void InsecureCryptStringImpl::CopyTo(char* dest, bool nullterminate) const { + memcpy(dest, password_.data(), password_.size()); + if (nullterminate) + dest[password_.size()] = 0; +} + +std::string InsecureCryptStringImpl::UrlEncode() const { + return password_; +} + +CryptStringImpl* InsecureCryptStringImpl::Copy() const { + InsecureCryptStringImpl* copy = new InsecureCryptStringImpl; + copy->password() = password_; + return copy; +} + +void InsecureCryptStringImpl::CopyRawTo( + std::vector* dest) const { + dest->resize(password_.size()); + memcpy(&dest->front(), password_.data(), password_.size()); +} + +}; // namespace rtc diff --git a/webrtc/base/cryptstring.h b/webrtc/base/cryptstring.h new file mode 100644 index 0000000000..e1ee309f65 --- /dev/null +++ b/webrtc/base/cryptstring.h @@ -0,0 +1,167 @@ +/* + * Copyright 2004 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef _WEBRTC_BASE_CRYPTSTRING_H_ +#define _WEBRTC_BASE_CRYPTSTRING_H_ + +#include + +#include +#include +#include + +namespace rtc { + +class CryptStringImpl { +public: + virtual ~CryptStringImpl() {} + virtual size_t GetLength() const = 0; + virtual void CopyTo(char * dest, bool nullterminate) const = 0; + virtual std::string UrlEncode() const = 0; + virtual CryptStringImpl * Copy() const = 0; + virtual void CopyRawTo(std::vector * dest) const = 0; +}; + +class EmptyCryptStringImpl : public CryptStringImpl { +public: + ~EmptyCryptStringImpl() override {} + size_t GetLength() const override; + void CopyTo(char* dest, bool nullterminate) const override; + std::string UrlEncode() const override; + CryptStringImpl* Copy() const override; + void CopyRawTo(std::vector* dest) const override; +}; + +class CryptString { + public: + CryptString(); + size_t GetLength() const { return impl_->GetLength(); } + void CopyTo(char * dest, bool nullterminate) const { impl_->CopyTo(dest, nullterminate); } + CryptString(const CryptString& other); + explicit CryptString(const CryptStringImpl& impl); + ~CryptString(); + CryptString & operator=(const CryptString & other) { + if (this != &other) { + impl_.reset(other.impl_->Copy()); + } + return *this; + } + void Clear() { impl_.reset(new EmptyCryptStringImpl()); } + std::string UrlEncode() const { return impl_->UrlEncode(); } + void CopyRawTo(std::vector * dest) const { + return impl_->CopyRawTo(dest); + } + + private: + std::unique_ptr impl_; +}; + + +// Used for constructing strings where a password is involved and we +// need to ensure that we zero memory afterwards +class FormatCryptString { +public: + FormatCryptString() { + storage_ = new char[32]; + capacity_ = 32; + length_ = 0; + storage_[0] = 0; + } + + void Append(const std::string & text) { + Append(text.data(), text.length()); + } + + void Append(const char * data, size_t length) { + EnsureStorage(length_ + length + 1); + memcpy(storage_ + length_, data, length); + length_ += length; + storage_[length_] = '\0'; + } + + void Append(const CryptString * password) { + size_t len = password->GetLength(); + EnsureStorage(length_ + len + 1); + password->CopyTo(storage_ + length_, true); + length_ += len; + } + + size_t GetLength() { + return length_; + } + + const char * GetData() { + return storage_; + } + + + // Ensures storage of at least n bytes + void EnsureStorage(size_t n) { + if (capacity_ >= n) { + return; + } + + size_t old_capacity = capacity_; + char * old_storage = storage_; + + for (;;) { + capacity_ *= 2; + if (capacity_ >= n) + break; + } + + storage_ = new char[capacity_]; + + if (old_capacity) { + memcpy(storage_, old_storage, length_); + + // zero memory in a way that an optimizer won't optimize it out + old_storage[0] = 0; + for (size_t i = 1; i < old_capacity; i++) { + old_storage[i] = old_storage[i - 1]; + } + delete[] old_storage; + } + } + + ~FormatCryptString() { + if (capacity_) { + storage_[0] = 0; + for (size_t i = 1; i < capacity_; i++) { + storage_[i] = storage_[i - 1]; + } + } + delete[] storage_; + } +private: + char * storage_; + size_t capacity_; + size_t length_; +}; + +class InsecureCryptStringImpl : public CryptStringImpl { + public: + std::string& password() { return password_; } + const std::string& password() const { return password_; } + + ~InsecureCryptStringImpl() override = default; + size_t GetLength() const override; + void CopyTo(char* dest, bool nullterminate) const override; + std::string UrlEncode() const override; + CryptStringImpl* Copy() const override; + void CopyRawTo(std::vector* dest) const override; + + private: + std::string password_; +}; + +} + +#endif // _WEBRTC_BASE_CRYPTSTRING_H_ diff --git a/webrtc/base/socketadapters.h b/webrtc/base/socketadapters.h index dcf56abd79..57e1f9eeb1 100644 --- a/webrtc/base/socketadapters.h +++ b/webrtc/base/socketadapters.h @@ -16,6 +16,7 @@ #include "webrtc/base/asyncsocket.h" #include "webrtc/base/constructormagic.h" +#include "webrtc/base/cryptstring.h" #include "webrtc/base/logging.h" namespace rtc {