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 RTC_BASE_CRYPTSTRING_H_
12 #define RTC_BASE_CRYPTSTRING_H_
13 
14 #include <string.h>
15 
16 #include <memory>
17 #include <string>
18 #include <vector>
19 
20 namespace rtc {
21 
22 class CryptStringImpl {
23 public:
~CryptStringImpl()24   virtual ~CryptStringImpl() {}
25   virtual size_t GetLength() const = 0;
26   virtual void CopyTo(char * dest, bool nullterminate) const = 0;
27   virtual std::string UrlEncode() const = 0;
28   virtual CryptStringImpl * Copy() const = 0;
29   virtual void CopyRawTo(std::vector<unsigned char> * dest) const = 0;
30 };
31 
32 class EmptyCryptStringImpl : public CryptStringImpl {
33 public:
~EmptyCryptStringImpl()34   ~EmptyCryptStringImpl() override {}
35   size_t GetLength() const override;
36   void CopyTo(char* dest, bool nullterminate) const override;
37   std::string UrlEncode() const override;
38   CryptStringImpl* Copy() const override;
39   void CopyRawTo(std::vector<unsigned char>* dest) const override;
40 };
41 
42 class CryptString {
43  public:
44   CryptString();
GetLength()45   size_t GetLength() const { return impl_->GetLength(); }
CopyTo(char * dest,bool nullterminate)46   void CopyTo(char * dest, bool nullterminate) const { impl_->CopyTo(dest, nullterminate); }
47   CryptString(const CryptString& other);
48   explicit CryptString(const CryptStringImpl& impl);
49   ~CryptString();
50   CryptString & operator=(const CryptString & other) {
51     if (this != &other) {
52       impl_.reset(other.impl_->Copy());
53     }
54     return *this;
55   }
Clear()56   void Clear() { impl_.reset(new EmptyCryptStringImpl()); }
UrlEncode()57   std::string UrlEncode() const { return impl_->UrlEncode(); }
CopyRawTo(std::vector<unsigned char> * dest)58   void CopyRawTo(std::vector<unsigned char> * dest) const {
59     return impl_->CopyRawTo(dest);
60   }
61 
62  private:
63   std::unique_ptr<const CryptStringImpl> impl_;
64 };
65 
66 
67 // Used for constructing strings where a password is involved and we
68 // need to ensure that we zero memory afterwards
69 class FormatCryptString {
70 public:
FormatCryptString()71   FormatCryptString() {
72     storage_ = new char[32];
73     capacity_ = 32;
74     length_ = 0;
75     storage_[0] = 0;
76   }
77 
Append(const std::string & text)78   void Append(const std::string & text) {
79     Append(text.data(), text.length());
80   }
81 
Append(const char * data,size_t length)82   void Append(const char * data, size_t length) {
83     EnsureStorage(length_ + length + 1);
84     memcpy(storage_ + length_, data, length);
85     length_ += length;
86     storage_[length_] = '\0';
87   }
88 
Append(const CryptString * password)89   void Append(const CryptString * password) {
90     size_t len = password->GetLength();
91     EnsureStorage(length_ + len + 1);
92     password->CopyTo(storage_ + length_, true);
93     length_ += len;
94   }
95 
GetLength()96   size_t GetLength() {
97     return length_;
98   }
99 
GetData()100   const char * GetData() {
101     return storage_;
102   }
103 
104 
105   // Ensures storage of at least n bytes
EnsureStorage(size_t n)106   void EnsureStorage(size_t n) {
107     if (capacity_ >= n) {
108       return;
109     }
110 
111     size_t old_capacity = capacity_;
112     char * old_storage = storage_;
113 
114     for (;;) {
115       capacity_ *= 2;
116       if (capacity_ >= n)
117         break;
118     }
119 
120     storage_ = new char[capacity_];
121 
122     if (old_capacity) {
123       memcpy(storage_, old_storage, length_);
124 
125       // zero memory in a way that an optimizer won't optimize it out
126       old_storage[0] = 0;
127       for (size_t i = 1; i < old_capacity; i++) {
128         old_storage[i] = old_storage[i - 1];
129       }
130       delete[] old_storage;
131     }
132   }
133 
~FormatCryptString()134   ~FormatCryptString() {
135     if (capacity_) {
136       storage_[0] = 0;
137       for (size_t i = 1; i < capacity_; i++) {
138         storage_[i] = storage_[i - 1];
139       }
140     }
141     delete[] storage_;
142   }
143 private:
144   char * storage_;
145   size_t capacity_;
146   size_t length_;
147 };
148 
149 class InsecureCryptStringImpl : public CryptStringImpl {
150  public:
password()151   std::string& password() { return password_; }
password()152   const std::string& password() const { return password_; }
153 
154   ~InsecureCryptStringImpl() override = default;
155   size_t GetLength() const override;
156   void CopyTo(char* dest, bool nullterminate) const override;
157   std::string UrlEncode() const override;
158   CryptStringImpl* Copy() const override;
159   void CopyRawTo(std::vector<unsigned char>* dest) const override;
160 
161  private:
162   std::string password_;
163 };
164 
165 }
166 
167 #endif  // RTC_BASE_CRYPTSTRING_H_
168