# Memory during crypto computation

I'm implementing a cryptographic primitive and I have a question about the memory model. The function (simplified) looks something like this:

void encrypt(unsigned char *out,
const unsigned char *in,
const unsigned char *pub_key)
{
unsigned char buf[OUTPUT_SIZE];
size_t i, j;

memcpy(out, in, OUTPUT_SIZE);
for (i = OUTPUT_SIZE; i < INPUT_SIZE; i += OUTPUT_SIZE) {
compute(buf, in[i], pub_key);
for (j = 0; j < OUTPUT_SIZE; ++j) {
out[j] ^= buf[j];
}
}
}


To summarize: the input (plaintext) is chopped in blocks of size OUTPUT_SIZE and a computation is done on each block (except the first). Each iteration, the result of a computation on the input block and the public key gets stored in the buffer. The output (ciphertext) is the result of the binary sum (xor) of all processed blocks. The caller of the function has to provide an allocated memory block for the output. This memory may reside on the stack or the heap.

My question is: is this construction secure? I am afraid that because the memory is provided by the caller, there are scenario's in which an adversary can inspect intermediate values of this memory through sidechannels and learn about the secret plaintext. On the other hand I'm thinking: if the attacker has access to the out buffer, then why not also to the in buffer?

• You should implement the OS "unpaged" apis to make sure that the memory location will not be placed in the pagefile for any reason (VirtualLock in windows) until you are done with that memory location – Richie Frame Aug 9 '16 at 0:26

You should worry about accidental leaks, due to a buggy caller. It is standard good practice to wipe all memory that has been used for cryptographic computations after use. This way, even if the program later leaks memory, that's one secret that won't leak. For example, in this case, you should wipe the temporary variable on the stack. The basic idea is to call memset(buf, 0, sizeof(buf)) at the end of encrypt, but this actually doesn't work in practice, because the compiler is likely to optimize it away (what sense is there to write to an object that goes out of scope immediately afterwards?). CERT recommendation MSC06-C discusses this problem and some solutions (use memset_s if you have it, but it was only standardized in C11).