1 1.1 christos /* 2 1.1 christos * Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved. 3 1.1 christos * 4 1.1 christos * Licensed under the Apache License 2.0 (the "License"). You may not use 5 1.1 christos * this file except in compliance with the License. You can obtain a copy 6 1.1 christos * in the file LICENSE in the source distribution or at 7 1.1 christos * https://www.openssl.org/source/license.html 8 1.1 christos */ 9 1.1 christos 10 1.1 christos #include <openssl/crypto.h> 11 1.1 christos 12 1.1 christos #include "testutil.h" 13 1.1 christos #include "internal/e_os.h" 14 1.1 christos 15 1.1 christos static int test_sec_mem(void) 16 1.1 christos { 17 1.1 christos #ifndef OPENSSL_NO_SECURE_MEMORY 18 1.1 christos int testresult = 0; 19 1.1 christos char *p = NULL, *q = NULL, *r = NULL, *s = NULL; 20 1.1 christos 21 1.1 christos TEST_info("Secure memory is implemented."); 22 1.1 christos 23 1.1 christos s = OPENSSL_secure_malloc(20); 24 1.1 christos /* s = non-secure 20 */ 25 1.1 christos if (!TEST_ptr(s) 26 1.1 christos || !TEST_false(CRYPTO_secure_allocated(s))) 27 1.1 christos goto end; 28 1.1 christos r = OPENSSL_secure_malloc(20); 29 1.1 christos /* r = non-secure 20, s = non-secure 20 */ 30 1.1 christos if (!TEST_ptr(r) 31 1.1 christos || !TEST_true(CRYPTO_secure_malloc_init(4096, 32)) 32 1.1 christos || !TEST_false(CRYPTO_secure_allocated(r))) 33 1.1 christos goto end; 34 1.1 christos p = OPENSSL_secure_malloc(20); 35 1.1 christos if (!TEST_ptr(p) 36 1.1 christos /* r = non-secure 20, p = secure 20, s = non-secure 20 */ 37 1.1 christos || !TEST_true(CRYPTO_secure_allocated(p)) 38 1.1 christos /* 20 secure -> 32-byte minimum allocation unit */ 39 1.1 christos || !TEST_size_t_eq(CRYPTO_secure_used(), 32)) 40 1.1 christos goto end; 41 1.1 christos q = OPENSSL_malloc(20); 42 1.1 christos if (!TEST_ptr(q)) 43 1.1 christos goto end; 44 1.1 christos /* r = non-secure 20, p = secure 20, q = non-secure 20, s = non-secure 20 */ 45 1.1 christos if (!TEST_false(CRYPTO_secure_allocated(q))) 46 1.1 christos goto end; 47 1.1 christos OPENSSL_secure_clear_free(s, 20); 48 1.1 christos s = OPENSSL_secure_malloc(20); 49 1.1 christos if (!TEST_ptr(s) 50 1.1 christos /* r = non-secure 20, p = secure 20, q = non-secure 20, s = secure 20 */ 51 1.1 christos || !TEST_true(CRYPTO_secure_allocated(s)) 52 1.1 christos /* 2 * 20 secure -> 64 bytes allocated */ 53 1.1 christos || !TEST_size_t_eq(CRYPTO_secure_used(), 64)) 54 1.1 christos goto end; 55 1.1 christos OPENSSL_secure_clear_free(p, 20); 56 1.1 christos p = NULL; 57 1.1 christos /* 20 secure -> 32 bytes allocated */ 58 1.1 christos if (!TEST_size_t_eq(CRYPTO_secure_used(), 32)) 59 1.1 christos goto end; 60 1.1 christos OPENSSL_free(q); 61 1.1 christos q = NULL; 62 1.1 christos /* should not complete, as secure memory is still allocated */ 63 1.1 christos if (!TEST_false(CRYPTO_secure_malloc_done()) 64 1.1 christos || !TEST_true(CRYPTO_secure_malloc_initialized())) 65 1.1 christos goto end; 66 1.1 christos OPENSSL_secure_free(s); 67 1.1 christos s = NULL; 68 1.1 christos /* secure memory should now be 0, so done should complete */ 69 1.1 christos if (!TEST_size_t_eq(CRYPTO_secure_used(), 0) 70 1.1 christos || !TEST_true(CRYPTO_secure_malloc_done()) 71 1.1 christos || !TEST_false(CRYPTO_secure_malloc_initialized())) 72 1.1 christos goto end; 73 1.1 christos 74 1.1 christos TEST_info("Possible infinite loop: allocate more than available"); 75 1.1 christos if (!TEST_true(CRYPTO_secure_malloc_init(32768, 16))) 76 1.1 christos goto end; 77 1.1 christos TEST_ptr_null(OPENSSL_secure_malloc((size_t)-1)); 78 1.1 christos TEST_true(CRYPTO_secure_malloc_done()); 79 1.1 christos 80 1.1 christos /* 81 1.1 christos * If init fails, then initialized should be false, if not, this 82 1.1 christos * could cause an infinite loop secure_malloc, but we don't test it 83 1.1 christos */ 84 1.1.1.2 christos if (TEST_false(CRYPTO_secure_malloc_init(16, 16)) && !TEST_false(CRYPTO_secure_malloc_initialized())) { 85 1.1 christos TEST_true(CRYPTO_secure_malloc_done()); 86 1.1 christos goto end; 87 1.1 christos } 88 1.1 christos 89 1.1 christos /*- 90 1.1 christos * There was also a possible infinite loop when the number of 91 1.1 christos * elements was 1<<31, as |int i| was set to that, which is a 92 1.1 christos * negative number. However, it requires minimum input values: 93 1.1 christos * 94 1.1 christos * CRYPTO_secure_malloc_init((size_t)1<<34, 1<<4); 95 1.1 christos * 96 1.1 christos * Which really only works on 64-bit systems, since it took 16 GB 97 1.1 christos * secure memory arena to trigger the problem. It naturally takes 98 1.1 christos * corresponding amount of available virtual and physical memory 99 1.1 christos * for test to be feasible/representative. Since we can't assume 100 1.1 christos * that every system is equipped with that much memory, the test 101 1.1 christos * remains disabled. If the reader of this comment really wants 102 1.1 christos * to make sure that infinite loop is fixed, they can enable the 103 1.1 christos * code below. 104 1.1 christos */ 105 1.1.1.2 christos #if 0 106 1.1 christos /*- 107 1.1 christos * On Linux and BSD this test has a chance to complete in minimal 108 1.1 christos * time and with minimum side effects, because mlock is likely to 109 1.1 christos * fail because of RLIMIT_MEMLOCK, which is customarily [much] 110 1.1 christos * smaller than 16GB. In other words Linux and BSD users can be 111 1.1 christos * limited by virtual space alone... 112 1.1 christos */ 113 1.1 christos if (sizeof(size_t) > 4) { 114 1.1 christos TEST_info("Possible infinite loop: 1<<31 limit"); 115 1.1 christos if (TEST_true(CRYPTO_secure_malloc_init((size_t)1<<34, 1<<4) != 0)) 116 1.1 christos TEST_true(CRYPTO_secure_malloc_done()); 117 1.1 christos } 118 1.1.1.2 christos #endif 119 1.1 christos 120 1.1 christos /* this can complete - it was not really secure */ 121 1.1 christos testresult = 1; 122 1.1.1.2 christos end: 123 1.1 christos OPENSSL_secure_free(p); 124 1.1 christos OPENSSL_free(q); 125 1.1 christos OPENSSL_secure_free(r); 126 1.1 christos OPENSSL_secure_free(s); 127 1.1 christos return testresult; 128 1.1 christos #else 129 1.1 christos TEST_info("Secure memory is *not* implemented."); 130 1.1 christos /* Should fail. */ 131 1.1 christos return TEST_false(CRYPTO_secure_malloc_init(4096, 32)); 132 1.1 christos #endif 133 1.1 christos } 134 1.1 christos 135 1.1 christos static int test_sec_mem_clear(void) 136 1.1 christos { 137 1.1 christos #ifndef OPENSSL_NO_SECURE_MEMORY 138 1.1 christos const int size = 64; 139 1.1 christos unsigned char *p = NULL; 140 1.1 christos int i, res = 0; 141 1.1 christos 142 1.1 christos if (!TEST_true(CRYPTO_secure_malloc_init(4096, 32)) 143 1.1.1.2 christos || !TEST_ptr(p = OPENSSL_secure_malloc(size))) 144 1.1 christos goto err; 145 1.1 christos 146 1.1 christos for (i = 0; i < size; i++) 147 1.1 christos if (!TEST_uchar_eq(p[i], 0)) 148 1.1 christos goto err; 149 1.1 christos 150 1.1 christos for (i = 0; i < size; i++) 151 1.1 christos p[i] = (unsigned char)(i + ' ' + 1); 152 1.1 christos 153 1.1 christos OPENSSL_secure_free(p); 154 1.1 christos 155 1.1 christos /* 156 1.1 christos * A deliberate use after free here to verify that the memory has been 157 1.1 christos * cleared properly. Since secure free doesn't return the memory to 158 1.1 christos * libc's memory pool, it technically isn't freed. However, the header 159 1.1 christos * bytes have to be skipped and these consist of two pointers in the 160 1.1 christos * current implementation. 161 1.1 christos */ 162 1.1 christos for (i = sizeof(void *) * 2; i < size; i++) 163 1.1 christos if (!TEST_uchar_eq(p[i], 0)) 164 1.1 christos return 0; 165 1.1 christos 166 1.1 christos res = 1; 167 1.1 christos p = NULL; 168 1.1 christos err: 169 1.1 christos OPENSSL_secure_free(p); 170 1.1 christos CRYPTO_secure_malloc_done(); 171 1.1 christos return res; 172 1.1 christos #else 173 1.1 christos return 1; 174 1.1 christos #endif 175 1.1 christos } 176 1.1 christos 177 1.1 christos int setup_tests(void) 178 1.1 christos { 179 1.1 christos ADD_TEST(test_sec_mem); 180 1.1 christos ADD_TEST(test_sec_mem_clear); 181 1.1 christos return 1; 182 1.1 christos } 183