Clearing memory securely and reallocations

c++, cryptography, memory, passwords, security

Solution

Here is another program that reproduces the problem more directly:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

inline void SecureWipeBuffer(char* buf, size_t n){
  volatile char* p = buf;
  asm volatile("rep stosb" : "+c"(n), "+D"(p) : "a"(0) : "memory");
}

void mymemcpy(char* b, const char* a, size_t n){
  char* s1 = b;
  const char* s2= a;
  for(; 0<n; --n) *s1++ = *s2++;
}

int main(){
  const size_t size1 = 200;
  const size_t size2 = 400;

  char* b = new char[size1];
  for(int j=0;j<size1-10;j+=10){
    memcpy(b+j, "LOL", 3);
    memcpy(b+j+3, "WUT", 3);
    sprintf((char*) (b+j+6), "%d", j);
  }
  char* nb = new char[size2];
  memcpy(nb, b, size1);
  //mymemcpy(nb, b, size1);
  SecureWipeBuffer(b,size1);
  SecureWipeBuffer(nb,size2);

  *((int*)NULL) = 1;

  return 0;    
}

If you replace `memcpy` with `mymemcpy` or use smaller sizes the problem goes away, so my best guess is that the builtin memcpy does something that leaves part of the copied data in memory.

I guess this just shows that clearing sensitive data from memory is practically impossible unless it is designed into the entire system from scratch.

Problem

Following the discussion here, if you want to have a secure class for storing sensitive information (e.g passwords) on memory, you have to: - memset/clear the memory before freeing it - reallocations must also follow the same rule - instead of using realloc, use malloc to create a new memory region, copy the old to the new, and then memset/clear the old memory before freeing it finally So this sounds good, and I created a test class to see if this works. So I made a simple test case where I keep adding the words "LOL" and "WUT", followed by a number to this secure buffer class around a thousand times, destroying that object, before finally doing something that causes a core dump. Since the class is supposed to securely clear the memory before the destruction, I'm not supposed to be able to find a "LOLWUT" on the coredump. However, I managed to find them still, and wondered if my implementation is just buggy. However, I tried the same thing using CryptoPP library's SecByteBlock: ``` #include <cryptopp/osrng.h> #include <cryptopp/dh.h> #include <cryptopp/sha.h> #include <cryptopp/aes.h> #include <cryptopp/modes.h> #include <cryptopp/filters.h> #include <stdlib.h> #include <stdio.h> #include <string.h> using namespace std; int main(){ { CryptoPP::SecByteBlock moo; int i; for(i = 0; i < 234; i++){ moo += (CryptoPP::SecByteBlock((byte*)"LOL", 3)); moo += (CryptoPP::SecByteBlock((byte*)"WUT", 3)); char buffer[33]; sprintf(buffer, "%d", i); string thenumber (buffer); moo += (CryptoPP::SecByteBlock((byte*)thenumber.c_str(), thenumber.size())); } moo.CleanNew(0); } sleep(1); *((int*)NULL) = 1; return 0; } ``` And then compile using: ``` g++ clearer.cpp -lcryptopp -O0 ``` And then enable core dump ``` ulimit -c 99999999 ``` But then, enabling core dump and running it ``` ./a.out ; grep LOLWUT core ; echo hello ``` gives the following output ``` Segmentation fault (core dumped) Binary file core matches hello ``` What is causing this? Did the whole memory region for the application realloc itself, because of the reallocation caused by SecByteBlock's append? Also, This is SecByteBlock's Documentation edit: After checking the core dump using vim, I got this: https://i.stack.imgur.com/3iXb3.jpg edit2: updated code so it's more readily compilable, and compilation instructions final edit3: It looks like memcpy is the culprit. See Rasmus' `mymemcpy` implementation on his answer below.

Original source

Related problems