1 /* 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef RTC_BASE_CRYPTSTRING_H_ 12 #define RTC_BASE_CRYPTSTRING_H_ 13 14 #include <string.h> 15 16 #include <memory> 17 #include <string> 18 #include <vector> 19 20 namespace rtc { 21 22 class CryptStringImpl { 23 public: ~CryptStringImpl()24 virtual ~CryptStringImpl() {} 25 virtual size_t GetLength() const = 0; 26 virtual void CopyTo(char * dest, bool nullterminate) const = 0; 27 virtual std::string UrlEncode() const = 0; 28 virtual CryptStringImpl * Copy() const = 0; 29 virtual void CopyRawTo(std::vector<unsigned char> * dest) const = 0; 30 }; 31 32 class EmptyCryptStringImpl : public CryptStringImpl { 33 public: ~EmptyCryptStringImpl()34 ~EmptyCryptStringImpl() override {} 35 size_t GetLength() const override; 36 void CopyTo(char* dest, bool nullterminate) const override; 37 std::string UrlEncode() const override; 38 CryptStringImpl* Copy() const override; 39 void CopyRawTo(std::vector<unsigned char>* dest) const override; 40 }; 41 42 class CryptString { 43 public: 44 CryptString(); GetLength()45 size_t GetLength() const { return impl_->GetLength(); } CopyTo(char * dest,bool nullterminate)46 void CopyTo(char * dest, bool nullterminate) const { impl_->CopyTo(dest, nullterminate); } 47 CryptString(const CryptString& other); 48 explicit CryptString(const CryptStringImpl& impl); 49 ~CryptString(); 50 CryptString & operator=(const CryptString & other) { 51 if (this != &other) { 52 impl_.reset(other.impl_->Copy()); 53 } 54 return *this; 55 } Clear()56 void Clear() { impl_.reset(new EmptyCryptStringImpl()); } UrlEncode()57 std::string UrlEncode() const { return impl_->UrlEncode(); } CopyRawTo(std::vector<unsigned char> * dest)58 void CopyRawTo(std::vector<unsigned char> * dest) const { 59 return impl_->CopyRawTo(dest); 60 } 61 62 private: 63 std::unique_ptr<const CryptStringImpl> impl_; 64 }; 65 66 67 // Used for constructing strings where a password is involved and we 68 // need to ensure that we zero memory afterwards 69 class FormatCryptString { 70 public: FormatCryptString()71 FormatCryptString() { 72 storage_ = new char[32]; 73 capacity_ = 32; 74 length_ = 0; 75 storage_[0] = 0; 76 } 77 Append(const std::string & text)78 void Append(const std::string & text) { 79 Append(text.data(), text.length()); 80 } 81 Append(const char * data,size_t length)82 void Append(const char * data, size_t length) { 83 EnsureStorage(length_ + length + 1); 84 memcpy(storage_ + length_, data, length); 85 length_ += length; 86 storage_[length_] = '\0'; 87 } 88 Append(const CryptString * password)89 void Append(const CryptString * password) { 90 size_t len = password->GetLength(); 91 EnsureStorage(length_ + len + 1); 92 password->CopyTo(storage_ + length_, true); 93 length_ += len; 94 } 95 GetLength()96 size_t GetLength() { 97 return length_; 98 } 99 GetData()100 const char * GetData() { 101 return storage_; 102 } 103 104 105 // Ensures storage of at least n bytes EnsureStorage(size_t n)106 void EnsureStorage(size_t n) { 107 if (capacity_ >= n) { 108 return; 109 } 110 111 size_t old_capacity = capacity_; 112 char * old_storage = storage_; 113 114 for (;;) { 115 capacity_ *= 2; 116 if (capacity_ >= n) 117 break; 118 } 119 120 storage_ = new char[capacity_]; 121 122 if (old_capacity) { 123 memcpy(storage_, old_storage, length_); 124 125 // zero memory in a way that an optimizer won't optimize it out 126 old_storage[0] = 0; 127 for (size_t i = 1; i < old_capacity; i++) { 128 old_storage[i] = old_storage[i - 1]; 129 } 130 delete[] old_storage; 131 } 132 } 133 ~FormatCryptString()134 ~FormatCryptString() { 135 if (capacity_) { 136 storage_[0] = 0; 137 for (size_t i = 1; i < capacity_; i++) { 138 storage_[i] = storage_[i - 1]; 139 } 140 } 141 delete[] storage_; 142 } 143 private: 144 char * storage_; 145 size_t capacity_; 146 size_t length_; 147 }; 148 149 class InsecureCryptStringImpl : public CryptStringImpl { 150 public: password()151 std::string& password() { return password_; } password()152 const std::string& password() const { return password_; } 153 154 ~InsecureCryptStringImpl() override = default; 155 size_t GetLength() const override; 156 void CopyTo(char* dest, bool nullterminate) const override; 157 std::string UrlEncode() const override; 158 CryptStringImpl* Copy() const override; 159 void CopyRawTo(std::vector<unsigned char>* dest) const override; 160 161 private: 162 std::string password_; 163 }; 164 165 } 166 167 #endif // RTC_BASE_CRYPTSTRING_H_ 168