• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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