Zero memory in CRYPTO_secure_malloc.
This commit destroys the free list pointers which would otherwise be
present in the returned memory blocks. This in turn helps prevent
information leakage from the secure memory area.
Note: CRYPTO_secure_malloc is not guaranteed to return zeroed memory:
before the secure memory system is initialised or if it isn't implemented.
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com>
(Merged from https://github.com/openssl/openssl/pull/7011)
Pauli
5 years ago
136 | 136 |
|
137 | 137 |
void *CRYPTO_secure_zalloc(size_t num, const char *file, int line)
|
138 | 138 |
{
|
139 | |
void *ret = CRYPTO_secure_malloc(num, file, line);
|
140 | |
|
141 | |
if (ret != NULL)
|
142 | |
memset(ret, 0, num);
|
143 | |
return ret;
|
|
139 |
#ifdef IMPLEMENTED
|
|
140 |
if (secure_mem_initialized)
|
|
141 |
/* CRYPTO_secure_malloc() zeroes allocations when it is implemented */
|
|
142 |
return CRYPTO_secure_malloc(num, file, line);
|
|
143 |
#endif
|
|
144 |
return CRYPTO_zalloc(num, file, line);
|
144 | 145 |
}
|
145 | 146 |
|
146 | 147 |
void CRYPTO_secure_free(void *ptr, const char *file, int line)
|
|
587 | 588 |
|
588 | 589 |
OPENSSL_assert(WITHIN_ARENA(chunk));
|
589 | 590 |
|
|
591 |
/* zero the free list header as a precaution against information leakage */
|
|
592 |
memset(chunk, 0, sizeof(SH_LIST));
|
|
593 |
|
590 | 594 |
return chunk;
|
591 | 595 |
}
|
592 | 596 |
|
|
619 | 623 |
|
620 | 624 |
list--;
|
621 | 625 |
|
|
626 |
/* Zero the higher addressed block's free list pointers */
|
|
627 |
memset(ptr > buddy ? ptr : buddy, 0, sizeof(SH_LIST));
|
622 | 628 |
if (ptr > buddy)
|
623 | 629 |
ptr = buddy;
|
624 | 630 |
|
128 | 128 |
#endif
|
129 | 129 |
}
|
130 | 130 |
|
|
131 |
static int test_sec_mem_clear(void)
|
|
132 |
{
|
|
133 |
#if defined(OPENSSL_SYS_LINUX) || defined(OPENSSL_SYS_UNIX)
|
|
134 |
const int size = 64;
|
|
135 |
unsigned char *p = NULL;
|
|
136 |
int i, res = 0;
|
|
137 |
|
|
138 |
if (!TEST_true(CRYPTO_secure_malloc_init(4096, 32))
|
|
139 |
|| !TEST_ptr(p = OPENSSL_secure_malloc(size)))
|
|
140 |
goto err;
|
|
141 |
|
|
142 |
for (i = 0; i < size; i++)
|
|
143 |
if (!TEST_uchar_eq(p[i], 0))
|
|
144 |
goto err;
|
|
145 |
|
|
146 |
for (i = 0; i < size; i++)
|
|
147 |
p[i] = (unsigned char)(i + ' ' + 1);
|
|
148 |
|
|
149 |
OPENSSL_secure_free(p);
|
|
150 |
|
|
151 |
/*
|
|
152 |
* A deliberate use after free here to verify that the memory has been
|
|
153 |
* cleared properly. Since secure free doesn't return the memory to
|
|
154 |
* libc's memory pool, it technically isn't freed. However, the header
|
|
155 |
* bytes have to be skipped and these consist of two pointers in the
|
|
156 |
* current implementation.
|
|
157 |
*/
|
|
158 |
for (i = sizeof(void *) * 2; i < size; i++)
|
|
159 |
if (!TEST_uchar_eq(p[i], 0))
|
|
160 |
return 0;
|
|
161 |
|
|
162 |
res = 1;
|
|
163 |
p = NULL;
|
|
164 |
|
|
165 |
err:
|
|
166 |
OPENSSL_secure_free(p);
|
|
167 |
CRYPTO_secure_malloc_done();
|
|
168 |
return res;
|
|
169 |
#else
|
|
170 |
return 1;
|
|
171 |
#endif
|
|
172 |
}
|
|
173 |
|
131 | 174 |
int setup_tests(void)
|
132 | 175 |
{
|
133 | 176 |
ADD_TEST(test_sec_mem);
|
|
177 |
ADD_TEST(test_sec_mem_clear);
|
134 | 178 |
return 1;
|
135 | 179 |
}
|