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