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 22namespace rtc { 23 24class CryptStringImpl { 25public: 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 34class EmptyCryptStringImpl : public CryptStringImpl { 35public: 36 virtual ~EmptyCryptStringImpl() {} 37 virtual size_t GetLength() const { return 0; } 38 virtual void CopyTo(char * dest, bool nullterminate) const { 39 if (nullterminate) { 40 *dest = '\0'; 41 } 42 } 43 virtual std::string UrlEncode() const { return ""; } 44 virtual CryptStringImpl * Copy() const { return new EmptyCryptStringImpl(); } 45 virtual void CopyRawTo(std::vector<unsigned char> * dest) const { 46 dest->clear(); 47 } 48}; 49 50class CryptString { 51public: 52 CryptString() : impl_(new EmptyCryptStringImpl()) {} 53 size_t GetLength() const { return impl_->GetLength(); } 54 void CopyTo(char * dest, bool nullterminate) const { impl_->CopyTo(dest, nullterminate); } 55 CryptString(const CryptString & other) : impl_(other.impl_->Copy()) {} 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 } 63 void Clear() { impl_.reset(new EmptyCryptStringImpl()); } 64 std::string UrlEncode() const { return impl_->UrlEncode(); } 65 void CopyRawTo(std::vector<unsigned char> * dest) const { 66 return impl_->CopyRawTo(dest); 67 } 68 69private: 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 76class FormatCryptString { 77public: 78 FormatCryptString() { 79 storage_ = new char[32]; 80 capacity_ = 32; 81 length_ = 0; 82 storage_[0] = 0; 83 } 84 85 void Append(const std::string & text) { 86 Append(text.data(), text.length()); 87 } 88 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 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 103 size_t GetLength() { 104 return length_; 105 } 106 107 const char * GetData() { 108 return storage_; 109 } 110 111 112 // Ensures storage of at least n bytes 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 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 } 150private: 151 char * storage_; 152 size_t capacity_; 153 size_t length_; 154}; 155 156class InsecureCryptStringImpl : public CryptStringImpl { 157 public: 158 std::string& password() { return password_; } 159 const std::string& password() const { return password_; } 160 161 virtual ~InsecureCryptStringImpl() {} 162 virtual size_t GetLength() const { return password_.size(); } 163 virtual void CopyTo(char * dest, bool nullterminate) const { 164 memcpy(dest, password_.data(), password_.size()); 165 if (nullterminate) dest[password_.size()] = 0; 166 } 167 virtual std::string UrlEncode() const { return password_; } 168 virtual CryptStringImpl * Copy() const { 169 InsecureCryptStringImpl * copy = new InsecureCryptStringImpl; 170 copy->password() = password_; 171 return copy; 172 } 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