147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/*
247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *
447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  Use of this source code is governed by a BSD-style license
547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  that can be found in the LICENSE file in the root of the source
647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  tree. An additional intellectual property rights grant can be found
747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  in the file PATENTS.  All contributing project authors may
847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org */
1047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#ifndef _WEBRTC_BASE_CRYPTSTRING_H_
1247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#define _WEBRTC_BASE_CRYPTSTRING_H_
1347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <string.h>
1547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <string>
1747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <vector>
1847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/linked_ptr.h"
2047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/scoped_ptr.h"
2147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
2247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgnamespace rtc {
2347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
2447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgclass CryptStringImpl {
2547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgpublic:
2647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual ~CryptStringImpl() {}
2747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual size_t GetLength() const = 0;
2847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual void CopyTo(char * dest, bool nullterminate) const = 0;
2947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual std::string UrlEncode() const = 0;
3047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual CryptStringImpl * Copy() const = 0;
3147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual void CopyRawTo(std::vector<unsigned char> * dest) const = 0;
3247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org};
3347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
3447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgclass EmptyCryptStringImpl : public CryptStringImpl {
3547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgpublic:
3647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual ~EmptyCryptStringImpl() {}
3747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual size_t GetLength() const { return 0; }
3847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual void CopyTo(char * dest, bool nullterminate) const {
3947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (nullterminate) {
4047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      *dest = '\0';
4147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
4247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
4347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual std::string UrlEncode() const { return ""; }
4447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual CryptStringImpl * Copy() const { return new EmptyCryptStringImpl(); }
4547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual void CopyRawTo(std::vector<unsigned char> * dest) const {
4647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    dest->clear();
4747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
4847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org};
4947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
5047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgclass CryptString {
5147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgpublic:
5247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  CryptString() : impl_(new EmptyCryptStringImpl()) {}
5347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t GetLength() const { return impl_->GetLength(); }
5447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  void CopyTo(char * dest, bool nullterminate) const { impl_->CopyTo(dest, nullterminate); }
5547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  CryptString(const CryptString & other) : impl_(other.impl_->Copy()) {}
5647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  explicit CryptString(const CryptStringImpl & impl) : impl_(impl.Copy()) {}
5747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  CryptString & operator=(const CryptString & other) {
5847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (this != &other) {
5947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      impl_.reset(other.impl_->Copy());
6047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
6147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return *this;
6247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
6347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  void Clear() { impl_.reset(new EmptyCryptStringImpl()); }
6447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  std::string UrlEncode() const { return impl_->UrlEncode(); }
6547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  void CopyRawTo(std::vector<unsigned char> * dest) const {
6647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return impl_->CopyRawTo(dest);
6747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
6847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
6947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgprivate:
7047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  scoped_ptr<const CryptStringImpl> impl_;
7147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org};
7247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
7347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
7447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Used for constructing strings where a password is involved and we
7547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// need to ensure that we zero memory afterwards
7647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgclass FormatCryptString {
7747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgpublic:
7847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  FormatCryptString() {
7947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    storage_ = new char[32];
8047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    capacity_ = 32;
8147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    length_ = 0;
8247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    storage_[0] = 0;
8347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
8447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
8547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  void Append(const std::string & text) {
8647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    Append(text.data(), text.length());
8747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
8847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
8947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  void Append(const char * data, size_t length) {
9047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    EnsureStorage(length_ + length + 1);
9147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    memcpy(storage_ + length_, data, length);
9247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    length_ += length;
9347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    storage_[length_] = '\0';
9447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
9547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
9647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  void Append(const CryptString * password) {
9747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    size_t len = password->GetLength();
9847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    EnsureStorage(length_ + len + 1);
9947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    password->CopyTo(storage_ + length_, true);
10047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    length_ += len;
10147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
10247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
10347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t GetLength() {
10447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return length_;
10547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
10647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
10747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  const char * GetData() {
10847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return storage_;
10947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
11047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
11147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
11247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Ensures storage of at least n bytes
11347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  void EnsureStorage(size_t n) {
11447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (capacity_ >= n) {
11547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return;
11647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
11747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
11847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    size_t old_capacity = capacity_;
11947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    char * old_storage = storage_;
12047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
12147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    for (;;) {
12247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      capacity_ *= 2;
12347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (capacity_ >= n)
12447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        break;
12547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
12647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
12747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    storage_ = new char[capacity_];
12847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
12947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (old_capacity) {
13047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      memcpy(storage_, old_storage, length_);
13147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
13247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // zero memory in a way that an optimizer won't optimize it out
13347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      old_storage[0] = 0;
13447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      for (size_t i = 1; i < old_capacity; i++) {
13547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        old_storage[i] = old_storage[i - 1];
13647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
13747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      delete[] old_storage;
13847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
13947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
14047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
14147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ~FormatCryptString() {
14247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (capacity_) {
14347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      storage_[0] = 0;
14447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      for (size_t i = 1; i < capacity_; i++) {
14547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        storage_[i] = storage_[i - 1];
14647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
14747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
14847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    delete[] storage_;
14947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
15047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgprivate:
15147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  char * storage_;
15247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t capacity_;
15347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t length_;
15447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org};
15547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
15647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgclass InsecureCryptStringImpl : public CryptStringImpl {
15747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org public:
15847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  std::string& password() { return password_; }
15947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  const std::string& password() const { return password_; }
16047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
16147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual ~InsecureCryptStringImpl() {}
16247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual size_t GetLength() const { return password_.size(); }
16347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual void CopyTo(char * dest, bool nullterminate) const {
16447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    memcpy(dest, password_.data(), password_.size());
16547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (nullterminate) dest[password_.size()] = 0;
16647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
16747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual std::string UrlEncode() const { return password_; }
16847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual CryptStringImpl * Copy() const {
16947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    InsecureCryptStringImpl * copy = new InsecureCryptStringImpl;
17047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    copy->password() = password_;
17147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return copy;
17247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
17347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  virtual void CopyRawTo(std::vector<unsigned char> * dest) const {
17447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    dest->resize(password_.size());
17547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    memcpy(&dest->front(), password_.data(), password_.size());
17647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
17747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org private:
17847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  std::string password_;
17947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org};
18047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
18147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
18247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
18347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif  // _WEBRTC_BASE_CRYPTSTRING_H_
184