Line data Source code
1 : /* t-secmem.c - Test the secmem memory allocator
2 : * Copyright (C) 2016 g10 Code GmbH
3 : *
4 : * This file is part of Libgcrypt.
5 : *
6 : * Libgcrypt is free software; you can redistribute it and/or modify
7 : * it under the terms of the GNU Lesser General Public License as
8 : * published by the Free Software Foundation; either version 2.1 of
9 : * the License, or (at your option) any later version.
10 : *
11 : * Libgcrypt is distributed in the hope that it will be useful,
12 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : * GNU Lesser General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU Lesser General Public
17 : * License along with this program; if not, see <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : #ifdef HAVE_CONFIG_H
21 : # include <config.h>
22 : #endif
23 : #include <stdarg.h>
24 : #include <stdio.h>
25 : #include <stdlib.h>
26 : #include <string.h>
27 : #include <errno.h>
28 :
29 : #define PGM "t-secmem"
30 :
31 : #include "t-common.h"
32 : #include "../src/gcrypt-testapi.h"
33 :
34 :
35 : static void
36 0 : test_secmem (void)
37 : {
38 : void *a[28];
39 : void *b;
40 : int i;
41 :
42 0 : memset (a, 0, sizeof a);
43 :
44 : /* Allocating 28*512=14k should work in the default 16k pool even
45 : * with extrem alignment requirements. */
46 0 : for (i=0; i < DIM(a); i++)
47 0 : a[i] = gcry_xmalloc_secure (512);
48 :
49 : /* Allocating another 2k should fail for the default 16k pool. */
50 0 : b = gcry_malloc_secure (2048);
51 0 : if (b)
52 0 : fail ("allocation did not fail as expected\n");
53 :
54 0 : for (i=0; i < DIM(a); i++)
55 0 : xfree (a[i]);
56 0 : xfree (b);
57 0 : }
58 :
59 :
60 : static void
61 0 : test_secmem_overflow (void)
62 : {
63 : void *a[150];
64 : int i;
65 :
66 0 : memset (a, 0, sizeof a);
67 :
68 : /* Allocating 150*512=75k should require more than one overflow buffer. */
69 0 : for (i=0; i < DIM(a); i++)
70 : {
71 0 : a[i] = gcry_xmalloc_secure (512);
72 0 : if (verbose && !(i %40))
73 0 : xgcry_control (GCRYCTL_DUMP_SECMEM_STATS, 0 , 0);
74 : }
75 :
76 0 : if (debug)
77 0 : xgcry_control (PRIV_CTL_DUMP_SECMEM_STATS, 0 , 0);
78 0 : if (verbose)
79 0 : xgcry_control (GCRYCTL_DUMP_SECMEM_STATS, 0 , 0);
80 0 : for (i=0; i < DIM(a); i++)
81 0 : xfree (a[i]);
82 0 : }
83 :
84 :
85 : /* This function is called when we ran out of core and there is no way
86 : * to return that error to the caller (xmalloc or mpi allocation). */
87 : static int
88 0 : outofcore_handler (void *opaque, size_t req_n, unsigned int flags)
89 : {
90 : static int been_here; /* Used to protect against recursive calls. */
91 :
92 : (void)opaque;
93 :
94 : /* Protect against a second call. */
95 0 : if (been_here)
96 0 : return 0; /* Let libgcrypt call its own fatal error handler. */
97 0 : been_here = 1;
98 :
99 0 : info ("outofcore handler invoked");
100 0 : xgcry_control (PRIV_CTL_DUMP_SECMEM_STATS, 0 , 0);
101 0 : fail ("out of core%s while allocating %lu bytes",
102 0 : (flags & 1)?" in secure memory":"", (unsigned long)req_n);
103 :
104 0 : die ("stopped");
105 : /*NOTREACHED*/
106 : return 0;
107 : }
108 :
109 :
110 : int
111 1 : main (int argc, char **argv)
112 : {
113 1 : int last_argc = -1;
114 :
115 1 : if (argc)
116 1 : { argc--; argv++; }
117 :
118 2 : while (argc && last_argc != argc )
119 : {
120 0 : last_argc = argc;
121 0 : if (!strcmp (*argv, "--"))
122 : {
123 0 : argc--; argv++;
124 0 : break;
125 : }
126 0 : else if (!strcmp (*argv, "--help"))
127 : {
128 0 : fputs ("usage: " PGM " [options]\n"
129 : "Options:\n"
130 : " --verbose print timings etc.\n"
131 : " --debug flyswatter\n"
132 : , stdout);
133 0 : exit (0);
134 : }
135 0 : else if (!strcmp (*argv, "--verbose"))
136 : {
137 0 : verbose++;
138 0 : argc--; argv++;
139 : }
140 0 : else if (!strcmp (*argv, "--debug"))
141 : {
142 0 : verbose += 2;
143 0 : debug++;
144 0 : argc--; argv++;
145 : }
146 0 : else if (!strncmp (*argv, "--", 2))
147 0 : die ("unknown option '%s'", *argv);
148 : }
149 :
150 1 : if (!gcry_check_version (GCRYPT_VERSION))
151 0 : die ("version mismatch; pgm=%s, library=%s\n",
152 : GCRYPT_VERSION, gcry_check_version (NULL));
153 1 : if (debug)
154 0 : xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0);
155 1 : xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
156 1 : xgcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
157 0 : gcry_set_outofcore_handler (outofcore_handler, NULL);
158 0 : xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
159 :
160 : /* Libgcrypt prints a warning when the first overflow is allocated;
161 : * we do not want to see that. */
162 0 : if (!verbose)
163 0 : xgcry_control (GCRYCTL_DISABLE_SECMEM_WARN, 0);
164 :
165 :
166 0 : test_secmem ();
167 0 : test_secmem_overflow ();
168 : /* FIXME: We need to improve the tests, for example by registering
169 : * our own log handler and comparing the output of
170 : * PRIV_CTL_DUMP_SECMEM_STATS to expected pattern. */
171 :
172 0 : if (verbose)
173 : {
174 0 : xgcry_control (PRIV_CTL_DUMP_SECMEM_STATS, 0 , 0);
175 0 : xgcry_control (GCRYCTL_DUMP_SECMEM_STATS, 0 , 0);
176 : }
177 :
178 0 : info ("All tests completed. Errors: %d\n", error_count);
179 0 : xgcry_control (GCRYCTL_TERM_SECMEM, 0 , 0);
180 0 : return !!error_count;
181 : }
|