tests: New test t-secmem.
[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 PGMNAME "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 /* This function is called when we ran out of core and there is no way
61  * to return that error to the caller (xmalloc or mpi allocation).  */
62 static int
63 outofcore_handler (void *opaque, size_t req_n, unsigned int flags)
64 {
65   static int been_here;  /* Used to protect against recursive calls. */
66
67   (void)opaque;
68
69   /* Protect against a second call.  */
70   if (been_here)
71     return 0; /* Let libgcrypt call its own fatal error handler.  */
72   been_here = 1;
73
74   info ("outofcore handler invoked");
75   gcry_control (PRIV_CTL_DUMP_SECMEM_STATS, 0 , 0);
76   fail ("out of core%s while allocating %lu bytes",
77        (flags & 1)?" in secure memory":"", (unsigned long)req_n);
78
79   die ("stopped");
80   /*NOTREACHED*/
81   return 0;
82 }
83
84
85 int
86 main (int argc, char **argv)
87 {
88   int last_argc = -1;
89
90   if (argc)
91     { argc--; argv++; }
92
93   while (argc && last_argc != argc )
94     {
95       last_argc = argc;
96       if (!strcmp (*argv, "--"))
97         {
98           argc--; argv++;
99           break;
100         }
101       else if (!strcmp (*argv, "--help"))
102         {
103           fputs ("usage: " PGMNAME " [options]\n"
104                  "Options:\n"
105                  "  --verbose       print timings etc.\n"
106                  "  --debug         flyswatter\n"
107                  , stdout);
108           exit (0);
109         }
110       else if (!strcmp (*argv, "--verbose"))
111         {
112           verbose++;
113           argc--; argv++;
114         }
115       else if (!strcmp (*argv, "--debug"))
116         {
117           verbose += 2;
118           debug++;
119           argc--; argv++;
120         }
121       else if (!strncmp (*argv, "--", 2))
122         die ("unknown option '%s'", *argv);
123     }
124
125   if (!gcry_check_version (GCRYPT_VERSION))
126     die ("version mismatch; pgm=%s, library=%s\n",
127          GCRYPT_VERSION, gcry_check_version (NULL));
128   if (debug)
129     gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0);
130   gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
131   gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
132   gcry_set_outofcore_handler (outofcore_handler, NULL);
133   gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
134
135   test_secmem ();
136
137   if (verbose)
138     gcry_control (PRIV_CTL_DUMP_SECMEM_STATS, 0 , 0);
139   info ("All tests completed.  Errors: %d\n", errorcount);
140   return !!errorcount;
141 }