What is the correct way to clear sensitive data from memory in iOS?
Asked Answered
B

2

12

I want to clear sensitive data from memory in my iOS app. In Windows I used to use SecureZeroMemory. Now, in iOS, I use plain old memset, but I'm a little worried the compiler might optimize it: https://buildsecurityin.us-cert.gov/bsi/articles/knowledge/coding/771-BSI.html

code snippet:

 NSData *someSensitiveData;
 memset((void *)someSensitiveData.bytes, 0, someSensitiveData.length);
Bondon answered 2/4, 2012 at 8:41 Comment(0)
F
5

Paraphrasing 771-BSI (link see OP):

A way to avoid having the memset call optimized out by the compiler is to access the buffer again after the memset call in a way that would force the compiler not to optimize the location. This can be achieved by

*(volatile char*)buffer = *(volatile char*)buffer;

after the memset() call.

In fact, you could write a secure_memset() function

void* secure_memset(void *v, int c, size_t n) {
    volatile char *p = v;
    while (n--) *p++ = c;
    return v;
}

(Code taken from 771-BSI. Thanks to Daniel Trebbien for pointing out for a possible defect of the previous code proposal.)

Why does volatile prevent optimization? See https://mcmap.net/q/15187/-what-kinds-of-optimizations-does-39-volatile-39-prevent-in-c

UPDATE Please also read Sensitive Data In Memory because if you have an adversary on your iOS system, your are already more or less screwed even before he tries to read that memory. In a summary SecureZeroMemory() or secure_memset() do not really help.

Frail answered 2/4, 2012 at 14:30 Comment(10)
I thought maybe there's an equivalent to SecureZeroMemory() in iOS. Your solution looks good, but what about "Solution should be effective on most platforms, but consult platform documentation to verify that it suffices to reference one character in this fashion."Bondon
I think this is just cautiously waddling to and fro. It is dictated by the standard that accesses to volatile variables are NOT to be optimized away. In fact it could be that the one character is a hardware port and a read access triggers something on the hardware level. With volatile you declare to the compiler that you know better than it and that it never even think about trying to optimize that access away. And because that access depends on the memset() in front it, the memset() will not be optimized away.Frail
Your secure_memset function might not be sufficient. According to open-std.org/jtc1/sc22/wg14/www/docs/n1381.pdf there are optimizing compilers that will only zero the first byte.Guyguyana
It's not mine. It's from 771-BSI.Frail
Maybe the page changed? If you look again, they have a loop volatile char *p = v; while (n--) *p++ = c;Guyguyana
@DanielTrebbien Thanks, your concern seems to be a valid one. I updated my answer.Frail
Make sure to be careful when using this to secure erase the c pointer of an NSString - there are cases when an NSString can contain the same string that iOS uses, such as "password", which trying to memset on a device will crash.Garget
@NSDestroyer Thanks, but as I wrote in the update I don't think that secure_memset() is a good idea anyway. If you need it because of security, you are screwed anyway.Frail
@nalply: secure_memset is good "defence in depth". It certainly shouldn't be your only line of defence, but it makes an attacker's life that bit more difficult.Lookthrough
@MartinBonner, perhaps, but I don't think so. secure_memset() doesn't really help because a hacker could set a break point just before the call of the function and read the memory. The call even could even help the hacker in discovering the key section of your security. At least you'll lose simplicity for a diminutive gain in security if at all.Frail
S
0

The problem is NSData is immutable and you do not have control over what happens. If the buffer is controlled by you, you could use dataWithBytesNoCopy:length: and NSData will act as a wrapper. When finished you could memset your buffer.

Sinusoid answered 2/4, 2012 at 14:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.