Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Insecure compiler optimizations can occur leaving sensitive data (such as passwords or cryptographic keys) in memory. 

Non-Compliant Code Example

...

(memset())

Code Block
void getPassword() {
	char pwd[64];
	if( GetPassword(pwd, sizeof(pwd)) {
		/* checking of password, secure operations, etc */
	}
 	memset(pwd, 0, sizeof(pwd));
}

...

For all of the below listed compliant code examples, it is strongly recommended that the programmer inspect the generated assembly code to ensure that memory is actually zeroed and none of the function calls were optimized out.

Non-Compliant Code Example (Touching Memory)

This non-compliant code example accesses the buffer again after the call to memset(). This prevents some compilers from optimizing out the call to memset() but does not work for all implementaitons. Check compiler documentation to guarantee this behavior for a specific platform. 1

Code Block
void getPassword() {
	char pwd[64];
	if(GetPassword(pwd, sizeof(pwd)) {
		/*checking of password, secure operations, etc */
	}
	memset(pwd, 0, sizeof(pwd));
	*(volatile char*)buffer pwd= *(volatile char*)bufferpwd;
}

 This compliant solution accesses the buffer again after the call to memset and should cause most compilers not to optimize out the call to memset. Check compiler documentation to guarantee this behavior for a specific platform.

Compliant Code Example 2 (Windows)

Implementation Details

The MIPSpro compiler and versions 3 and later of GCC cleverly nullify only the first byte and leave the rest intact.

Non-Compliant Code Example (Windows)

This compliant solution uses a ZeroMemory() function provided by many versions of the Microsoft Visual Studio compiler.

Code Block
void getPassword() {
	  char pwd[64];
	  if (GetPassword(pwd, sizeof(pwd)) {
		    /* checking of password, secure operations, etc */
	  }
	SecureZeroMemory  ZeroMemory(pwd, sizeof(pwd));
}

A call to ZeroMemory() may be optimized out in similar manner as a call to memset().

Compliant Code Example (Windows)

This compliant solution uses a SecureZeroMemory() function provided by many version versions of the Microsoft Visual Studio compiler. The documentation for the SecureZeroMemory() function guarantees that the compiler will not optimize out this call when zeroing memory.Compliant Code Example 3 (Windows)

Code Block
void getPassword() {
	  char pwd[64];
	  if(GetPassword(pwd, sizeof(pwd)) {
		    /* checking of password, secure operations, etc */
	  }
	#pragma optimize("", off)
	memset SecureZeroMemory(pwd, 0, sizeof(pwd));
	 #pragma optimize("", on)
}

}

Compliant Solution (Windows)

The #pragma directives here instructs the compiler to avoid optimizing the enclosed code. This #pragma directive is support supported on some versions of Microsoft Visual Studio, and may be supported on other compilers. Check compiler documentation to ensure its availability and its optimization guarantees.

Code Block

void getPassword() {
  char pwd[64];
  if(GetPassword(pwd, sizeof(pwd)) {
    /* checking of password, secure operations, etc */
  }
#pragma optimize("", off)
  memset(pwd, 0, sizeof(pwd));
#pragma optimize("", on)
}

Risk Assessment

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

DRAFT

2 (Medium)

2 (Probable)

2 (Medium) 

P8

L2

References

https://buildsecurityin.us-cert.gov/daisy/bsi-rules/home/g1/771.html
http://msdn2.microsoft.com/en-us/library/aa366877.aspx
http://msdn2.microsoft.com/en-us/library/chh3fb0k(VS.80).aspx
David Wheeler
C99