0c11f826355e0b4834487ea55978f8a3515000da
[libgcrypt.git] / src / secmem.c
1 /* secmem.c  -  memory allocation from a secure heap
2  * Copyright (C) 1998, 1999, 2000, 2001, 2002,
3  *               2003, 2007 Free Software Foundation, Inc.
4  *
5  * This file is part of Libgcrypt.
6  *
7  * Libgcrypt is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser general Public License as
9  * published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * Libgcrypt is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20  */
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <stdarg.h>
28 #include <unistd.h>
29 #include <stddef.h>
30
31 #if defined(HAVE_MLOCK) || defined(HAVE_MMAP)
32 #include <sys/mman.h>
33 #include <sys/types.h>
34 #include <fcntl.h>
35 #ifdef USE_CAPABILITIES
36 #include <sys/capability.h>
37 #endif
38 #endif
39
40 #include "ath.h"
41 #include "g10lib.h"
42 #include "secmem.h"
43
44 #if defined (MAP_ANON) && ! defined (MAP_ANONYMOUS)
45 #define MAP_ANONYMOUS MAP_ANON
46 #endif
47
48 #define DEFAULT_POOL_SIZE 16384
49 #define DEFAULT_PAGE_SIZE 4096
50
51 typedef struct memblock
52 {
53   unsigned size;                /* Size of the memory available to the
54                                    user.  */
55   int flags;                    /* See below.  */
56   PROPERLY_ALIGNED_TYPE aligned;
57 } memblock_t;
58
59 /* This flag specifies that the memory block is in use.  */
60 #define MB_FLAG_ACTIVE (1 << 0)
61
62 /* The pool of secure memory.  */
63 static void *pool;
64
65 /* Size of POOL in bytes.  */
66 static size_t pool_size;
67
68 /* True, if the memory pool is ready for use.  May be checked in an
69    atexit function.  */
70 static volatile int pool_okay;
71
72 /* True, if the memory pool is mmapped.  */
73 static volatile int pool_is_mmapped;
74
75 /* FIXME?  */
76 static int disable_secmem;
77 static int show_warning;
78 static int not_locked;
79 static int no_warning;
80 static int suspend_warning;
81
82 /* Stats.  */
83 static unsigned int cur_alloced, cur_blocks;
84
85 /* Lock protecting accesses to the memory pool.  */
86 static ath_mutex_t secmem_lock;
87
88 /* Convenient macros.  */
89 #define SECMEM_LOCK   ath_mutex_lock   (&secmem_lock)
90 #define SECMEM_UNLOCK ath_mutex_unlock (&secmem_lock)
91
92 /* The size of the memblock structure; this does not include the
93    memory that is available to the user.  */
94 #define BLOCK_HEAD_SIZE \
95   offsetof (memblock_t, aligned)
96
97 /* Convert an address into the according memory block structure.  */
98 #define ADDR_TO_BLOCK(addr) \
99   (memblock_t *) ((char *) addr - BLOCK_HEAD_SIZE)
100
101 /* Check whether P points into the pool.  */
102 static int
103 ptr_into_pool_p (const void *p)
104 {
105   /* We need to convert pointers to addresses.  This is required by
106      C-99 6.5.8 to avoid undefeined behavious.  Using size_t is at
107      least only implementation defined.  See also
108      http://lists.gnupg.org/pipermail/gcrypt-devel/2007-February/001102.html
109   */
110   size_t p_addr = (size_t)p;
111   size_t pool_addr = (size_t)pool;
112
113   return p_addr >= pool_addr && p_addr <  pool_addr+pool_size;
114 }
115
116 /* Update the stats.  */
117 static void
118 stats_update (size_t add, size_t sub)
119 {
120   if (add)
121     {
122       cur_alloced += add;
123       cur_blocks++;
124     }
125   if (sub)
126     {
127       cur_alloced -= sub;
128       cur_blocks--;
129     }
130 }
131
132 /* Return the block following MB or NULL, if MB is the last block.  */
133 static memblock_t *
134 mb_get_next (memblock_t *mb)
135 {
136   memblock_t *mb_next;
137
138   mb_next = (memblock_t *) ((char *) mb + BLOCK_HEAD_SIZE + mb->size);
139   
140   if (! ptr_into_pool_p (mb_next))
141     mb_next = NULL;
142
143   return mb_next;
144 }
145
146 /* Return the block preceeding MB or NULL, if MB is the first
147    block.  */
148 static memblock_t *
149 mb_get_prev (memblock_t *mb)
150 {
151   memblock_t *mb_prev, *mb_next;
152
153   if (mb == pool)
154     mb_prev = NULL;
155   else
156     {
157       mb_prev = (memblock_t *) pool;
158       while (1)
159         {
160           mb_next = mb_get_next (mb_prev);
161           if (mb_next == mb)
162             break;
163           else
164             mb_prev = mb_next;
165         }
166     }
167
168   return mb_prev;
169 }
170
171 /* If the preceeding block of MB and/or the following block of MB
172    exist and are not active, merge them to form a bigger block.  */
173 static void
174 mb_merge (memblock_t *mb)
175 {
176   memblock_t *mb_prev, *mb_next;
177
178   mb_prev = mb_get_prev (mb);
179   mb_next = mb_get_next (mb);
180
181   if (mb_prev && (! (mb_prev->flags & MB_FLAG_ACTIVE)))
182     {
183       mb_prev->size += BLOCK_HEAD_SIZE + mb->size;
184       mb = mb_prev;
185     }
186   if (mb_next && (! (mb_next->flags & MB_FLAG_ACTIVE)))
187     mb->size += BLOCK_HEAD_SIZE + mb_next->size;
188 }
189
190 /* Return a new block, which can hold SIZE bytes.  */
191 static memblock_t *
192 mb_get_new (memblock_t *block, size_t size)
193 {
194   memblock_t *mb, *mb_split;
195   
196   for (mb = block; ptr_into_pool_p (mb); mb = mb_get_next (mb))
197     if (! (mb->flags & MB_FLAG_ACTIVE) && mb->size >= size)
198       {
199         /* Found a free block.  */
200         mb->flags |= MB_FLAG_ACTIVE;
201
202         if (mb->size - size > BLOCK_HEAD_SIZE)
203           {
204             /* Split block.  */
205           
206             mb_split = (memblock_t *) (((char *) mb) + BLOCK_HEAD_SIZE + size);
207             mb_split->size = mb->size - size - BLOCK_HEAD_SIZE;
208             mb_split->flags = 0;
209
210             mb->size = size;
211
212             mb_merge (mb_split);
213
214           }
215
216         break;
217       }
218
219   if (! ptr_into_pool_p (mb))
220     mb = NULL;
221
222   return mb;
223 }
224
225 /* Print a warning message.  */
226 static void
227 print_warn (void)
228 {
229   if (!no_warning)
230     log_info (_("Warning: using insecure memory!\n"));
231 }
232
233 /* Lock the memory pages into core and drop privileges.  */
234 static void
235 lock_pool (void *p, size_t n)
236 {
237 #if defined(USE_CAPABILITIES) && defined(HAVE_MLOCK)
238   int err;
239
240   cap_set_proc (cap_from_text ("cap_ipc_lock+ep"));
241   err = mlock (p, n);
242   if (err && errno)
243     err = errno;
244   cap_set_proc (cap_from_text ("cap_ipc_lock+p"));
245
246   if (err)
247     {
248       if (errno != EPERM
249 #ifdef EAGAIN   /* OpenBSD returns this */
250           && errno != EAGAIN
251 #endif
252 #ifdef ENOSYS   /* Some SCOs return this (function not implemented) */
253           && errno != ENOSYS
254 #endif
255 #ifdef ENOMEM  /* Linux might return this. */
256             && errno != ENOMEM
257 #endif
258           )
259         log_error ("can't lock memory: %s\n", strerror (err));
260       show_warning = 1;
261       not_locked = 1;
262     }
263
264 #elif defined(HAVE_MLOCK)
265   uid_t uid;
266   int err;
267
268   uid = getuid ();
269
270 #ifdef HAVE_BROKEN_MLOCK
271   /* Under HP/UX mlock segfaults if called by non-root.  Note, we have
272      noch checked whether mlock does really work under AIX where we
273      also detected a broken nlock.  Note further, that using plock ()
274      is not a good idea under AIX. */ 
275   if (uid)
276     {
277       errno = EPERM;
278       err = errno;
279     }
280   else
281     {
282       err = mlock (p, n);
283       if (err && errno)
284         err = errno;
285     }
286 #else /* !HAVE_BROKEN_MLOCK */
287   err = mlock (p, n);
288   if (err && errno)
289     err = errno;
290 #endif /* !HAVE_BROKEN_MLOCK */
291
292   if (uid && ! geteuid ())
293     {
294       /* check that we really dropped the privs.
295        * Note: setuid(0) should always fail */
296       if (setuid (uid) || getuid () != geteuid () || !setuid (0))
297         log_fatal ("failed to reset uid: %s\n", strerror (errno));
298     }
299
300   if (err)
301     {
302       if (errno != EPERM
303 #ifdef EAGAIN   /* OpenBSD returns this. */
304           && errno != EAGAIN
305 #endif
306 #ifdef ENOSYS   /* Some SCOs return this (function not implemented). */
307           && errno != ENOSYS
308 #endif
309 #ifdef ENOMEM  /* Linux might return this. */
310             && errno != ENOMEM
311 #endif
312           )
313         log_error ("can't lock memory: %s\n", strerror (err));
314       show_warning = 1;
315       not_locked = 1;
316     }
317
318 #elif defined ( __QNX__ )
319   /* QNX does not page at all, so the whole secure memory stuff does
320    * not make much sense.  However it is still of use because it
321    * wipes out the memory on a free().
322    * Therefore it is sufficient to suppress the warning
323    */
324 #elif defined (HAVE_DOSISH_SYSTEM) || defined (__CYGWIN__)
325     /* It does not make sense to print such a warning, given the fact that 
326      * this whole Windows !@#$% and their user base are inherently insecure
327      */
328 #elif defined (__riscos__)
329     /* no virtual memory on RISC OS, so no pages are swapped to disc,
330      * besides we don't have mmap, so we don't use it! ;-)
331      * But don't complain, as explained above.
332      */
333 #else
334   log_info ("Please note that you don't have secure memory on this system\n");
335 #endif
336 }
337
338 /* Initialize POOL.  */
339 static void
340 init_pool (size_t n)
341 {
342   size_t pgsize;
343   memblock_t *mb;
344
345   pool_size = n;
346
347   if (disable_secmem)
348     log_bug ("secure memory is disabled");
349
350 #ifdef HAVE_GETPAGESIZE
351   pgsize = getpagesize ();
352 #else
353   pgsize = DEFAULT_PAGE_SIZE;
354 #endif
355
356 #if HAVE_MMAP
357   pool_size = (pool_size + pgsize - 1) & ~(pgsize - 1);
358 #ifdef MAP_ANONYMOUS
359   pool = mmap (0, pool_size, PROT_READ | PROT_WRITE,
360                MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
361 #else /* map /dev/zero instead */
362   {
363     int fd;
364
365     fd = open ("/dev/zero", O_RDWR);
366     if (fd == -1)
367       {
368         log_error ("can't open /dev/zero: %s\n", strerror (errno));
369         pool = (void *) -1;
370       }
371     else
372       {
373         pool = mmap (0, pool_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
374         close (fd);
375       }
376   }
377 #endif
378   if (pool == (void *) -1)
379     log_info ("can't mmap pool of %u bytes: %s - using malloc\n",
380               (unsigned) pool_size, strerror (errno));
381   else
382     {
383       pool_is_mmapped = 1;
384       pool_okay = 1;
385     }
386
387 #endif
388   if (!pool_okay)
389     {
390       pool = malloc (pool_size);
391       if (!pool)
392         log_fatal ("can't allocate memory pool of %u bytes\n",
393                    (unsigned) pool_size);
394       else
395         pool_okay = 1;
396     }
397
398   /* Initialize first memory block.  */
399   mb = (memblock_t *) pool;
400   mb->size = pool_size;
401   mb->flags = 0;
402 }
403
404 void
405 _gcry_secmem_set_flags (unsigned flags)
406 {
407   int was_susp;
408
409   SECMEM_LOCK;
410
411   was_susp = suspend_warning;
412   no_warning = flags & GCRY_SECMEM_FLAG_NO_WARNING;
413   suspend_warning = flags & GCRY_SECMEM_FLAG_SUSPEND_WARNING;
414
415   /* and now issue the warning if it is not longer suspended */
416   if (was_susp && !suspend_warning && show_warning)
417     {
418       show_warning = 0;
419       print_warn ();
420     }
421
422   SECMEM_UNLOCK;
423 }
424
425 unsigned int
426 _gcry_secmem_get_flags (void)
427 {
428   unsigned flags;
429
430   SECMEM_LOCK;
431
432   flags = no_warning ? GCRY_SECMEM_FLAG_NO_WARNING : 0;
433   flags |= suspend_warning ? GCRY_SECMEM_FLAG_SUSPEND_WARNING : 0;
434   flags |= not_locked ? GCRY_SECMEM_FLAG_NOT_LOCKED : 0;
435
436   SECMEM_UNLOCK;
437
438   return flags;
439 }
440
441 /* Initialize the secure memory system.  If running with the necessary
442    privileges, the secure memory pool will be locked into the core in
443    order to prevent page-outs of the data.  Furthermore allocated
444    secure memory will be wiped out when released.  */
445 void
446 _gcry_secmem_init (size_t n)
447 {
448   SECMEM_LOCK;
449
450   if (!n)
451     {
452 #ifdef USE_CAPABILITIES
453       /* drop all capabilities */
454       cap_set_proc (cap_from_text ("all-eip"));
455
456 #elif !defined(HAVE_DOSISH_SYSTEM)
457       uid_t uid;
458
459       disable_secmem = 1;
460       uid = getuid ();
461       if (uid != geteuid ())
462         {
463           if (setuid (uid) || getuid () != geteuid () || !setuid (0))
464             log_fatal ("failed to drop setuid\n");
465         }
466 #endif
467     }
468   else
469     {
470       if (n < DEFAULT_POOL_SIZE)
471         n = DEFAULT_POOL_SIZE;
472       if (! pool_okay)
473         {
474           init_pool (n);
475           lock_pool (pool, n);
476         }
477       else
478         log_error ("Oops, secure memory pool already initialized\n");
479     }
480
481   SECMEM_UNLOCK;
482 }
483
484
485 static void *
486 _gcry_secmem_malloc_internal (size_t size)
487 {
488   memblock_t *mb;
489
490   if (!pool_okay)
491     {
492       log_info (_
493         ("operation is not possible without initialized secure memory\n"));
494       exit (2);
495     }
496   if (show_warning && !suspend_warning)
497     {
498       show_warning = 0;
499       print_warn ();
500     }
501
502   /* Blocks are always a multiple of 32. */
503   size = ((size + 31) / 32) * 32;
504
505   mb = mb_get_new ((memblock_t *) pool, size);
506   if (mb)
507     stats_update (size, 0);
508
509   return mb ? &mb->aligned.c : NULL;
510 }
511
512 void *
513 _gcry_secmem_malloc (size_t size)
514 {
515   void *p;
516
517   SECMEM_LOCK;
518   p = _gcry_secmem_malloc_internal (size);
519   SECMEM_UNLOCK;
520   
521   return p;
522 }
523
524 static void
525 _gcry_secmem_free_internal (void *a)
526 {
527   memblock_t *mb;
528   int size;
529
530   if (!a)
531     return;
532
533   mb = ADDR_TO_BLOCK (a);
534   size = mb->size;
535
536   /* This does not make much sense: probably this memory is held in the
537    * cache. We do it anyway: */
538 #define MB_WIPE_OUT(byte) \
539   wipememory2 ((memblock_t *) ((char *) mb + BLOCK_HEAD_SIZE), (byte), size);
540
541   MB_WIPE_OUT (0xff);
542   MB_WIPE_OUT (0xaa);
543   MB_WIPE_OUT (0x55);
544   MB_WIPE_OUT (0x00);
545
546   stats_update (0, size);
547
548   mb->flags &= ~MB_FLAG_ACTIVE;
549
550   /* Update stats.  */
551
552   mb_merge (mb);
553 }
554
555 /* Wipe out and release memory.  */
556 void
557 _gcry_secmem_free (void *a)
558 {
559   SECMEM_LOCK;
560   _gcry_secmem_free_internal (a);
561   SECMEM_UNLOCK;
562 }
563
564 /* Realloc memory.  */
565 void *
566 _gcry_secmem_realloc (void *p, size_t newsize)
567 {
568   memblock_t *mb;
569   size_t size;
570   void *a;
571
572   SECMEM_LOCK;
573
574   mb = (memblock_t *) ((char *) p - ((size_t) &((memblock_t *) 0)->aligned.c));
575   size = mb->size;
576   if (newsize < size)
577     {
578       /* It is easier to not shrink the memory.  */
579       a = p;
580     }
581   else
582     {
583       a = _gcry_secmem_malloc_internal (newsize);
584       if (a)
585         {
586           memcpy (a, p, size);
587           memset ((char *) a + size, 0, newsize - size);
588           _gcry_secmem_free_internal (p);
589         }
590     }
591
592   SECMEM_UNLOCK;
593
594   return a;
595 }
596
597
598 /* Return true if P points into the secure memory area.  */
599 int
600 _gcry_private_is_secure (const void *p)
601 {
602   return pool_okay && ptr_into_pool_p (p);
603 }
604
605
606 /****************
607  * Warning:  This code might be called by an interrupt handler
608  *           and frankly, there should really be such a handler,
609  *           to make sure that the memory is wiped out.
610  *           We hope that the OS wipes out mlocked memory after
611  *           receiving a SIGKILL - it really should do so, otherwise
612  *           there is no chance to get the secure memory cleaned.
613  */
614 void
615 _gcry_secmem_term ()
616 {
617   if (!pool_okay)
618     return;
619
620   wipememory2 (pool, 0xff, pool_size);
621   wipememory2 (pool, 0xaa, pool_size);
622   wipememory2 (pool, 0x55, pool_size);
623   wipememory2 (pool, 0x00, pool_size);
624 #if HAVE_MMAP
625   if (pool_is_mmapped)
626     munmap (pool, pool_size);
627 #endif
628   pool = NULL;
629   pool_okay = 0;
630   pool_size = 0;
631   not_locked = 0;
632 }
633
634
635 void
636 _gcry_secmem_dump_stats ()
637 {
638 #if 1 
639   SECMEM_LOCK;
640
641  if (pool_okay)
642     log_info ("secmem usage: %u/%lu bytes in %u blocks\n",
643               cur_alloced, (unsigned long)pool_size, cur_blocks);
644   SECMEM_UNLOCK;
645 #else
646   memblock_t *mb;
647   int i;
648
649   SECMEM_LOCK;
650
651   for (i = 0, mb = (memblock_t *) pool;
652        ptr_into_pool_p (mb);
653        mb = mb_get_next (mb), i++)
654     log_info ("SECMEM: [%s] block: %i; size: %i\n",
655               (mb->flags & MB_FLAG_ACTIVE) ? "used" : "free",
656               i,
657               mb->size);
658   SECMEM_UNLOCK;
659 #endif
660 }