1 /* 2 * libjingle 3 * Copyright 2004--2005, Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #ifndef _TALK_BASE_CRYPTSTRING_H_ 29 #define _TALK_BASE_CRYPTSTRING_H_ 30 31 #include <string.h> 32 33 #include <string> 34 #include <vector> 35 36 #include "talk/base/linked_ptr.h" 37 #include "talk/base/scoped_ptr.h" 38 39 namespace talk_base { 40 41 class CryptStringImpl { 42 public: ~CryptStringImpl()43 virtual ~CryptStringImpl() {} 44 virtual size_t GetLength() const = 0; 45 virtual void CopyTo(char * dest, bool nullterminate) const = 0; 46 virtual std::string UrlEncode() const = 0; 47 virtual CryptStringImpl * Copy() const = 0; 48 virtual void CopyRawTo(std::vector<unsigned char> * dest) const = 0; 49 }; 50 51 class EmptyCryptStringImpl : public CryptStringImpl { 52 public: ~EmptyCryptStringImpl()53 virtual ~EmptyCryptStringImpl() {} GetLength()54 virtual size_t GetLength() const { return 0; } CopyTo(char * dest,bool nullterminate)55 virtual void CopyTo(char * dest, bool nullterminate) const { 56 if (nullterminate) { 57 *dest = '\0'; 58 } 59 } UrlEncode()60 virtual std::string UrlEncode() const { return ""; } Copy()61 virtual CryptStringImpl * Copy() const { return new EmptyCryptStringImpl(); } CopyRawTo(std::vector<unsigned char> * dest)62 virtual void CopyRawTo(std::vector<unsigned char> * dest) const { 63 dest->clear(); 64 } 65 }; 66 67 class CryptString { 68 public: CryptString()69 CryptString() : impl_(new EmptyCryptStringImpl()) {} GetLength()70 size_t GetLength() const { return impl_->GetLength(); } CopyTo(char * dest,bool nullterminate)71 void CopyTo(char * dest, bool nullterminate) const { impl_->CopyTo(dest, nullterminate); } CryptString(const CryptString & other)72 CryptString(const CryptString & other) : impl_(other.impl_->Copy()) {} CryptString(const CryptStringImpl & impl)73 explicit CryptString(const CryptStringImpl & impl) : impl_(impl.Copy()) {} 74 CryptString & operator=(const CryptString & other) { 75 if (this != &other) { 76 impl_.reset(other.impl_->Copy()); 77 } 78 return *this; 79 } Clear()80 void Clear() { impl_.reset(new EmptyCryptStringImpl()); } UrlEncode()81 std::string UrlEncode() const { return impl_->UrlEncode(); } CopyRawTo(std::vector<unsigned char> * dest)82 void CopyRawTo(std::vector<unsigned char> * dest) const { 83 return impl_->CopyRawTo(dest); 84 } 85 86 private: 87 scoped_ptr<const CryptStringImpl> impl_; 88 }; 89 90 91 // Used for constructing strings where a password is involved and we 92 // need to ensure that we zero memory afterwards 93 class FormatCryptString { 94 public: FormatCryptString()95 FormatCryptString() { 96 storage_ = new char[32]; 97 capacity_ = 32; 98 length_ = 0; 99 storage_[0] = 0; 100 } 101 Append(const std::string & text)102 void Append(const std::string & text) { 103 Append(text.data(), text.length()); 104 } 105 Append(const char * data,size_t length)106 void Append(const char * data, size_t length) { 107 EnsureStorage(length_ + length + 1); 108 memcpy(storage_ + length_, data, length); 109 length_ += length; 110 storage_[length_] = '\0'; 111 } 112 Append(const CryptString * password)113 void Append(const CryptString * password) { 114 size_t len = password->GetLength(); 115 EnsureStorage(length_ + len + 1); 116 password->CopyTo(storage_ + length_, true); 117 length_ += len; 118 } 119 GetLength()120 size_t GetLength() { 121 return length_; 122 } 123 GetData()124 const char * GetData() { 125 return storage_; 126 } 127 128 129 // Ensures storage of at least n bytes EnsureStorage(size_t n)130 void EnsureStorage(size_t n) { 131 if (capacity_ >= n) { 132 return; 133 } 134 135 size_t old_capacity = capacity_; 136 char * old_storage = storage_; 137 138 for (;;) { 139 capacity_ *= 2; 140 if (capacity_ >= n) 141 break; 142 } 143 144 storage_ = new char[capacity_]; 145 146 if (old_capacity) { 147 memcpy(storage_, old_storage, length_); 148 149 // zero memory in a way that an optimizer won't optimize it out 150 old_storage[0] = 0; 151 for (size_t i = 1; i < old_capacity; i++) { 152 old_storage[i] = old_storage[i - 1]; 153 } 154 delete[] old_storage; 155 } 156 } 157 ~FormatCryptString()158 ~FormatCryptString() { 159 if (capacity_) { 160 storage_[0] = 0; 161 for (size_t i = 1; i < capacity_; i++) { 162 storage_[i] = storage_[i - 1]; 163 } 164 } 165 delete[] storage_; 166 } 167 private: 168 char * storage_; 169 size_t capacity_; 170 size_t length_; 171 }; 172 173 class InsecureCryptStringImpl : public CryptStringImpl { 174 public: password()175 std::string& password() { return password_; } password()176 const std::string& password() const { return password_; } 177 ~InsecureCryptStringImpl()178 virtual ~InsecureCryptStringImpl() {} GetLength()179 virtual size_t GetLength() const { return password_.size(); } CopyTo(char * dest,bool nullterminate)180 virtual void CopyTo(char * dest, bool nullterminate) const { 181 memcpy(dest, password_.data(), password_.size()); 182 if (nullterminate) dest[password_.size()] = 0; 183 } UrlEncode()184 virtual std::string UrlEncode() const { return password_; } Copy()185 virtual CryptStringImpl * Copy() const { 186 InsecureCryptStringImpl * copy = new InsecureCryptStringImpl; 187 copy->password() = password_; 188 return copy; 189 } CopyRawTo(std::vector<unsigned char> * dest)190 virtual void CopyRawTo(std::vector<unsigned char> * dest) const { 191 dest->resize(password_.size()); 192 memcpy(&dest->front(), password_.data(), password_.size()); 193 } 194 private: 195 std::string password_; 196 }; 197 198 } 199 200 #endif // _TALK_BASE_CRYPTSTRING_H_ 201