tests: Check the result of all gcry_control operations.
[libgcrypt.git] / tests / t-secmem.c
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 test_secmem (void)
37 {
38   void *a[28];
39   void *b;
40   int i;
41
42   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   for (i=0; i < DIM(a); i++)
47     a[i] = gcry_xmalloc_secure (512);
48
49   /* Allocating another 2k should fail for the default 16k pool.  */
50   b = gcry_malloc_secure (2048);
51   if (b)
52     fail ("allocation did not fail as expected\n");
53
54   for (i=0; i < DIM(a); i++)
55     xfree (a[i]);
56   xfree (b);
57 }
58
59
60 static void
61 test_secmem_overflow (void)
62 {
63   void *a[150];
64   int i;
65
66   memset (a, 0, sizeof a);
67
68   /* Allocating 150*512=75k should require more than one overflow buffer.  */
69   for (i=0; i < DIM(a); i++)
70     {
71       a[i] = gcry_xmalloc_secure (512);
72       if (verbose && !(i %40))
73         xgcry_control (GCRYCTL_DUMP_SECMEM_STATS, 0 , 0);
74     }
75
76   if (debug)
77     xgcry_control (PRIV_CTL_DUMP_SECMEM_STATS, 0 , 0);
78   if (verbose)
79     xgcry_control (GCRYCTL_DUMP_SECMEM_STATS, 0 , 0);
80   for (i=0; i < DIM(a); i++)
81     xfree (a[i]);
82 }
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 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   if (been_here)
96     return 0; /* Let libgcrypt call its own fatal error handler.  */
97   been_here = 1;
98
99   info ("outofcore handler invoked");
100   xgcry_control (PRIV_CTL_DUMP_SECMEM_STATS, 0 , 0);
101   fail ("out of core%s while allocating %lu bytes",
102        (flags & 1)?" in secure memory":"", (unsigned long)req_n);
103
104   die ("stopped");
105   /*NOTREACHED*/
106   return 0;
107 }
108
109
110 int
111 main (int argc, char **argv)
112 {
113   int last_argc = -1;
114
115   if (argc)
116     { argc--; argv++; }
117
118   while (argc && last_argc != argc )
119     {
120       last_argc = argc;
121       if (!strcmp (*argv, "--"))
122         {
123           argc--; argv++;
124           break;
125         }
126       else if (!strcmp (*argv, "--help"))
127         {
128           fputs ("usage: " PGM " [options]\n"
129                  "Options:\n"
130                  "  --verbose       print timings etc.\n"
131                  "  --debug         flyswatter\n"
132                  , stdout);
133           exit (0);
134         }
135       else if (!strcmp (*argv, "--verbose"))
136         {
137           verbose++;
138           argc--; argv++;
139         }
140       else if (!strcmp (*argv, "--debug"))
141         {
142           verbose += 2;
143           debug++;
144           argc--; argv++;
145         }
146       else if (!strncmp (*argv, "--", 2))
147         die ("unknown option '%s'", *argv);
148     }
149
150   if (!gcry_check_version (GCRYPT_VERSION))
151     die ("version mismatch; pgm=%s, library=%s\n",
152          GCRYPT_VERSION, gcry_check_version (NULL));
153   if (debug)
154     xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0);
155   xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
156   xgcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
157   gcry_set_outofcore_handler (outofcore_handler, NULL);
158   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   if (!verbose)
163     xgcry_control (GCRYCTL_DISABLE_SECMEM_WARN, 0);
164
165
166   test_secmem ();
167   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   if (verbose)
173     {
174       xgcry_control (PRIV_CTL_DUMP_SECMEM_STATS, 0 , 0);
175       xgcry_control (GCRYCTL_DUMP_SECMEM_STATS, 0 , 0);
176     }
177
178   info ("All tests completed.  Errors: %d\n", error_count);
179   xgcry_control (GCRYCTL_TERM_SECMEM, 0 , 0);
180   return !!error_count;
181 }