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 _WEBRTC_BASE_CRYPTSTRING_H_ 12 #define _WEBRTC_BASE_CRYPTSTRING_H_ 13 14 #include <string.h> 15 16 #include <string> 17 #include <vector> 18 19 #include "webrtc/base/linked_ptr.h" 20 #include "webrtc/base/scoped_ptr.h" 21 22 namespace rtc { 23 24 class CryptStringImpl { 25 public: ~CryptStringImpl()26 virtual ~CryptStringImpl() {} 27 virtual size_t GetLength() const = 0; 28 virtual void CopyTo(char * dest, bool nullterminate) const = 0; 29 virtual std::string UrlEncode() const = 0; 30 virtual CryptStringImpl * Copy() const = 0; 31 virtual void CopyRawTo(std::vector<unsigned char> * dest) const = 0; 32 }; 33 34 class EmptyCryptStringImpl : public CryptStringImpl { 35 public: ~EmptyCryptStringImpl()36 virtual ~EmptyCryptStringImpl() {} GetLength()37 virtual size_t GetLength() const { return 0; } CopyTo(char * dest,bool nullterminate)38 virtual void CopyTo(char * dest, bool nullterminate) const { 39 if (nullterminate) { 40 *dest = '\0'; 41 } 42 } UrlEncode()43 virtual std::string UrlEncode() const { return ""; } Copy()44 virtual CryptStringImpl * Copy() const { return new EmptyCryptStringImpl(); } CopyRawTo(std::vector<unsigned char> * dest)45 virtual void CopyRawTo(std::vector<unsigned char> * dest) const { 46 dest->clear(); 47 } 48 }; 49 50 class CryptString { 51 public: CryptString()52 CryptString() : impl_(new EmptyCryptStringImpl()) {} GetLength()53 size_t GetLength() const { return impl_->GetLength(); } CopyTo(char * dest,bool nullterminate)54 void CopyTo(char * dest, bool nullterminate) const { impl_->CopyTo(dest, nullterminate); } CryptString(const CryptString & other)55 CryptString(const CryptString & other) : impl_(other.impl_->Copy()) {} CryptString(const CryptStringImpl & impl)56 explicit CryptString(const CryptStringImpl & impl) : impl_(impl.Copy()) {} 57 CryptString & operator=(const CryptString & other) { 58 if (this != &other) { 59 impl_.reset(other.impl_->Copy()); 60 } 61 return *this; 62 } Clear()63 void Clear() { impl_.reset(new EmptyCryptStringImpl()); } UrlEncode()64 std::string UrlEncode() const { return impl_->UrlEncode(); } CopyRawTo(std::vector<unsigned char> * dest)65 void CopyRawTo(std::vector<unsigned char> * dest) const { 66 return impl_->CopyRawTo(dest); 67 } 68 69 private: 70 scoped_ptr<const CryptStringImpl> impl_; 71 }; 72 73 74 // Used for constructing strings where a password is involved and we 75 // need to ensure that we zero memory afterwards 76 class FormatCryptString { 77 public: FormatCryptString()78 FormatCryptString() { 79 storage_ = new char[32]; 80 capacity_ = 32; 81 length_ = 0; 82 storage_[0] = 0; 83 } 84 Append(const std::string & text)85 void Append(const std::string & text) { 86 Append(text.data(), text.length()); 87 } 88 Append(const char * data,size_t length)89 void Append(const char * data, size_t length) { 90 EnsureStorage(length_ + length + 1); 91 memcpy(storage_ + length_, data, length); 92 length_ += length; 93 storage_[length_] = '\0'; 94 } 95 Append(const CryptString * password)96 void Append(const CryptString * password) { 97 size_t len = password->GetLength(); 98 EnsureStorage(length_ + len + 1); 99 password->CopyTo(storage_ + length_, true); 100 length_ += len; 101 } 102 GetLength()103 size_t GetLength() { 104 return length_; 105 } 106 GetData()107 const char * GetData() { 108 return storage_; 109 } 110 111 112 // Ensures storage of at least n bytes EnsureStorage(size_t n)113 void EnsureStorage(size_t n) { 114 if (capacity_ >= n) { 115 return; 116 } 117 118 size_t old_capacity = capacity_; 119 char * old_storage = storage_; 120 121 for (;;) { 122 capacity_ *= 2; 123 if (capacity_ >= n) 124 break; 125 } 126 127 storage_ = new char[capacity_]; 128 129 if (old_capacity) { 130 memcpy(storage_, old_storage, length_); 131 132 // zero memory in a way that an optimizer won't optimize it out 133 old_storage[0] = 0; 134 for (size_t i = 1; i < old_capacity; i++) { 135 old_storage[i] = old_storage[i - 1]; 136 } 137 delete[] old_storage; 138 } 139 } 140 ~FormatCryptString()141 ~FormatCryptString() { 142 if (capacity_) { 143 storage_[0] = 0; 144 for (size_t i = 1; i < capacity_; i++) { 145 storage_[i] = storage_[i - 1]; 146 } 147 } 148 delete[] storage_; 149 } 150 private: 151 char * storage_; 152 size_t capacity_; 153 size_t length_; 154 }; 155 156 class InsecureCryptStringImpl : public CryptStringImpl { 157 public: password()158 std::string& password() { return password_; } password()159 const std::string& password() const { return password_; } 160 ~InsecureCryptStringImpl()161 virtual ~InsecureCryptStringImpl() {} GetLength()162 virtual size_t GetLength() const { return password_.size(); } CopyTo(char * dest,bool nullterminate)163 virtual void CopyTo(char * dest, bool nullterminate) const { 164 memcpy(dest, password_.data(), password_.size()); 165 if (nullterminate) dest[password_.size()] = 0; 166 } UrlEncode()167 virtual std::string UrlEncode() const { return password_; } Copy()168 virtual CryptStringImpl * Copy() const { 169 InsecureCryptStringImpl * copy = new InsecureCryptStringImpl; 170 copy->password() = password_; 171 return copy; 172 } CopyRawTo(std::vector<unsigned char> * dest)173 virtual void CopyRawTo(std::vector<unsigned char> * dest) const { 174 dest->resize(password_.size()); 175 memcpy(&dest->front(), password_.data(), password_.size()); 176 } 177 private: 178 std::string password_; 179 }; 180 181 } 182 183 #endif // _WEBRTC_BASE_CRYPTSTRING_H_ 184