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