• 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 <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:
~CryptStringImpl()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:
~EmptyCryptStringImpl()51   virtual ~EmptyCryptStringImpl() {}
GetLength()52   virtual size_t GetLength() const { return 0; }
CopyTo(char * dest,bool nullterminate)53   virtual void CopyTo(char * dest, bool nullterminate) const {
54     if (nullterminate) {
55       *dest = '\0';
56     }
57   }
UrlEncode()58   virtual std::string UrlEncode() const { return ""; }
Copy()59   virtual CryptStringImpl * Copy() const { return new EmptyCryptStringImpl(); }
CopyRawTo(std::vector<unsigned char> * dest)60   virtual void CopyRawTo(std::vector<unsigned char> * dest) const {
61     dest->clear();
62   }
63 };
64 
65 class CryptString {
66 public:
CryptString()67   CryptString() : impl_(new EmptyCryptStringImpl()) {}
GetLength()68   size_t GetLength() const { return impl_->GetLength(); }
CopyTo(char * dest,bool nullterminate)69   void CopyTo(char * dest, bool nullterminate) const { impl_->CopyTo(dest, nullterminate); }
CryptString(const CryptString & other)70   CryptString(const CryptString & other) : impl_(other.impl_->Copy()) {}
CryptString(const CryptStringImpl & impl)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   }
Clear()78   void Clear() { impl_.reset(new EmptyCryptStringImpl()); }
UrlEncode()79   std::string UrlEncode() const { return impl_->UrlEncode(); }
CopyRawTo(std::vector<unsigned char> * dest)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:
FormatCryptString()93   FormatCryptString() {
94     storage_ = new char[32];
95     capacity_ = 32;
96     length_ = 0;
97     storage_[0] = 0;
98   }
99 
Append(const std::string & text)100   void Append(const std::string & text) {
101     Append(text.data(), text.length());
102   }
103 
Append(const char * data,size_t length)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 
Append(const CryptString * password)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 
GetLength()118   size_t GetLength() {
119     return length_;
120   }
121 
GetData()122   const char * GetData() {
123     return storage_;
124   }
125 
126 
127   // Ensures storage of at least n bytes
EnsureStorage(size_t n)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 
~FormatCryptString()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:
password()173   std::string& password() { return password_; }
password()174   const std::string& password() const { return password_; }
175 
~InsecureCryptStringImpl()176   virtual ~InsecureCryptStringImpl() {}
GetLength()177   virtual size_t GetLength() const { return password_.size(); }
CopyTo(char * dest,bool nullterminate)178   virtual void CopyTo(char * dest, bool nullterminate) const {
179     memcpy(dest, password_.data(), password_.size());
180     if (nullterminate) dest[password_.size()] = 0;
181   }
UrlEncode()182   virtual std::string UrlEncode() const { return password_; }
Copy()183   virtual CryptStringImpl * Copy() const {
184     InsecureCryptStringImpl * copy = new InsecureCryptStringImpl;
185     copy->password() = password_;
186     return copy;
187   }
CopyRawTo(std::vector<unsigned char> * dest)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