Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template to perform automatic memory overwrite on destruction

It is a common pattern to use templates to enforce the compiler to initialize primitive / POD types values (https://stackoverflow.com/a/11493744/16673 or http://www.codeproject.com/Articles/825/Using-templates-for-initialization).

Does a similar pattern exist that could be used to erase the value once it goes out of scope for security reasons, to make sure the value is not left on the stack once the variable is destructed? I am afraid a naive analogous implementation might not work, as the compiler is free to ignore any assignments to a value which is going out of scope, as the value can be trivially proven not to be used any more. Is there some consistent and reasonably portable solution e.g. using volatile?

like image 666
Suma Avatar asked Sep 04 '12 07:09

Suma


2 Answers

There's a function in the Windows API called SecureZeroMemory. You could look at it's implementation.

However, generally speaking, the compiler is forced to honour volatile writes. If you made the variable volatile, it should not be able to remove writes.

like image 133
Puppy Avatar answered Nov 02 '22 22:11

Puppy


You could use some c++11 features to make this more portable, but this may suffice as a starting point:

Class

template<typename T>
class t_secure_destruct {
  static const size_t Size = sizeof(T);
  static const size_t Align = alignof(T);
public:
  t_secure_destruct() : d_memory() {
    new(this->d_memory)T;
  }

  ~t_secure_destruct() {
    reinterpret_cast<T*>(this->d_memory)->~T();
    this->scribble();
  }

  // @todo implement or delete op-assign and remaining constructors

public:
  T& get() {
    return *reinterpret_cast<T*>(this->d_memory);
  }

  const T& get() const {
    return *reinterpret_cast<const T*>(this->d_memory);
  }

private:
  void scribble() {
    for (size_t idx(0); idx < Size; ++idx) {
      this->d_memory[idx] = random();
    }
  }

private:
  __attribute__((aligned(Align))) char d_memory[Size];
};

Demo

#include <iostream>

class t_test {
public:
  t_test() : a(-1) {
    std::cout << "construct\n";
  }

  ~t_test() {
    std::cout << "destruct\n";
  }

public:
  void print() const {
    std::cout << "a = " << a << "\n";
  }

public:
  int a;
};

int main(int argc, const char* argv[]) {
  t_secure_destruct<t_test>test;
  test.get().print();
  test.get().a = 100;
  test.get().print();
  return 0;
}

Of course, you could also back that allocation with a heap allocation, if you favor. If you need to outsmart an optimizer, you may need to put the scribbler out of its reach.

like image 22
justin Avatar answered Nov 02 '22 22:11

justin