Preparing 1.4.0.
[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 undefined behaviour.  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   long int pgsize_val;
344   memblock_t *mb;
345
346   pool_size = n;
347
348   if (disable_secmem)
349     log_bug ("secure memory is disabled");
350
351 #if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE)
352   pgsize_val = sysconf (_SC_PAGESIZE);
353 #elif defined(HAVE_GETPAGESIZE)
354   pgsize_val = getpagesize ();
355 #else
356   pgsize_val = -1;
357 #endif
358   pgsize = (pgsize_val != -1 && pgsize_val > 0)? pgsize_val:DEFAULT_PAGE_SIZE;
359
360
361 #if HAVE_MMAP
362   pool_size = (pool_size + pgsize - 1) & ~(pgsize - 1);
363 #ifdef MAP_ANONYMOUS
364   pool = mmap (0, pool_size, PROT_READ | PROT_WRITE,
365                MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
366 #else /* map /dev/zero instead */
367   {
368     int fd;
369
370     fd = open ("/dev/zero", O_RDWR);
371     if (fd == -1)
372       {
373         log_error ("can't open /dev/zero: %s\n", strerror (errno));
374         pool = (void *) -1;
375       }
376     else
377       {
378         pool = mmap (0, pool_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
379         close (fd);
380       }
381   }
382 #endif
383   if (pool == (void *) -1)
384     log_info ("can't mmap pool of %u bytes: %s - using malloc\n",
385               (unsigned) pool_size, strerror (errno));
386   else
387     {
388       pool_is_mmapped = 1;
389       pool_okay = 1;
390     }
391
392 #endif
393   if (!pool_okay)
394     {
395       pool = malloc (pool_size);
396       if (!pool)
397         log_fatal ("can't allocate memory pool of %u bytes\n",
398                    (unsigned) pool_size);
399       else
400         pool_okay = 1;
401     }
402
403   /* Initialize first memory block.  */
404   mb = (memblock_t *) pool;
405   mb->size = pool_size;
406   mb->flags = 0;
407 }
408
409 void
410 _gcry_secmem_set_flags (unsigned flags)
411 {
412   int was_susp;
413
414   SECMEM_LOCK;
415
416   was_susp = suspend_warning;
417   no_warning = flags & GCRY_SECMEM_FLAG_NO_WARNING;
418   suspend_warning = flags & GCRY_SECMEM_FLAG_SUSPEND_WARNING;
419
420   /* and now issue the warning if it is not longer suspended */
421   if (was_susp && !suspend_warning && show_warning)
422     {
423       show_warning = 0;
424       print_warn ();
425     }
426
427   SECMEM_UNLOCK;
428 }
429
430 unsigned int
431 _gcry_secmem_get_flags (void)
432 {
433   unsigned flags;
434
435   SECMEM_LOCK;
436
437   flags = no_warning ? GCRY_SECMEM_FLAG_NO_WARNING : 0;
438   flags |= suspend_warning ? GCRY_SECMEM_FLAG_SUSPEND_WARNING : 0;
439   flags |= not_locked ? GCRY_SECMEM_FLAG_NOT_LOCKED : 0;
440
441   SECMEM_UNLOCK;
442
443   return flags;
444 }
445
446 /* Initialize the secure memory system.  If running with the necessary
447    privileges, the secure memory pool will be locked into the core in
448    order to prevent page-outs of the data.  Furthermore allocated
449    secure memory will be wiped out when released.  */
450 void
451 _gcry_secmem_init (size_t n)
452 {
453   SECMEM_LOCK;
454
455   if (!n)
456     {
457 #ifdef USE_CAPABILITIES
458       /* drop all capabilities */
459       cap_set_proc (cap_from_text ("all-eip"));
460
461 #elif !defined(HAVE_DOSISH_SYSTEM)
462       uid_t uid;
463
464       disable_secmem = 1;
465       uid = getuid ();
466       if (uid != geteuid ())
467         {
468           if (setuid (uid) || getuid () != geteuid () || !setuid (0))
469             log_fatal ("failed to drop setuid\n");
470         }
471 #endif
472     }
473   else
474     {
475       if (n < DEFAULT_POOL_SIZE)
476         n = DEFAULT_POOL_SIZE;
477       if (! pool_okay)
478         {
479           init_pool (n);
480           lock_pool (pool, n);
481         }
482       else
483         log_error ("Oops, secure memory pool already initialized\n");
484     }
485
486   SECMEM_UNLOCK;
487 }
488
489
490 static void *
491 _gcry_secmem_malloc_internal (size_t size)
492 {
493   memblock_t *mb;
494
495   if (!pool_okay)
496     {
497       log_bug (_
498         ("operation is not possible without initialized secure memory\n"));
499     }
500   if (show_warning && !suspend_warning)
501     {
502       show_warning = 0;
503       print_warn ();
504     }
505
506   /* Blocks are always a multiple of 32. */
507   size = ((size + 31) / 32) * 32;
508
509   mb = mb_get_new ((memblock_t *) pool, size);
510   if (mb)
511     stats_update (size, 0);
512
513   return mb ? &mb->aligned.c : NULL;
514 }
515
516 void *
517 _gcry_secmem_malloc (size_t size)
518 {
519   void *p;
520
521   SECMEM_LOCK;
522   p = _gcry_secmem_malloc_internal (size);
523   SECMEM_UNLOCK;
524   
525   return p;
526 }
527
528 static void
529 _gcry_secmem_free_internal (void *a)
530 {
531   memblock_t *mb;
532   int size;
533
534   if (!a)
535     return;
536
537   mb = ADDR_TO_BLOCK (a);
538   size = mb->size;
539
540   /* This does not make much sense: probably this memory is held in the
541    * cache. We do it anyway: */
542 #define MB_WIPE_OUT(byte) \
543   wipememory2 ((memblock_t *) ((char *) mb + BLOCK_HEAD_SIZE), (byte), size);
544
545   MB_WIPE_OUT (0xff);
546   MB_WIPE_OUT (0xaa);
547   MB_WIPE_OUT (0x55);
548   MB_WIPE_OUT (0x00);
549
550   stats_update (0, size);
551
552   mb->flags &= ~MB_FLAG_ACTIVE;
553
554   /* Update stats.  */
555
556   mb_merge (mb);
557 }
558
559 /* Wipe out and release memory.  */
560 void
561 _gcry_secmem_free (void *a)
562 {
563   SECMEM_LOCK;
564   _gcry_secmem_free_internal (a);
565   SECMEM_UNLOCK;
566 }
567
568 /* Realloc memory.  */
569 void *
570 _gcry_secmem_realloc (void *p, size_t newsize)
571 {
572   memblock_t *mb;
573   size_t size;
574   void *a;
575
576   SECMEM_LOCK;
577
578   mb = (memblock_t *) ((char *) p - ((size_t) &((memblock_t *) 0)->aligned.c));
579   size = mb->size;
580   if (newsize < size)
581     {
582       /* It is easier to not shrink the memory.  */
583       a = p;
584     }
585   else
586     {
587       a = _gcry_secmem_malloc_internal (newsize);
588       if (a)
589         {
590           memcpy (a, p, size);
591           memset ((char *) a + size, 0, newsize - size);
592           _gcry_secmem_free_internal (p);
593         }
594     }
595
596   SECMEM_UNLOCK;
597
598   return a;
599 }
600
601
602 /* Return true if P points into the secure memory area.  */
603 int
604 _gcry_private_is_secure (const void *p)
605 {
606   return pool_okay && ptr_into_pool_p (p);
607 }
608
609
610 /****************
611  * Warning:  This code might be called by an interrupt handler
612  *           and frankly, there should really be such a handler,
613  *           to make sure that the memory is wiped out.
614  *           We hope that the OS wipes out mlocked memory after
615  *           receiving a SIGKILL - it really should do so, otherwise
616  *           there is no chance to get the secure memory cleaned.
617  */
618 void
619 _gcry_secmem_term ()
620 {
621   if (!pool_okay)
622     return;
623
624   wipememory2 (pool, 0xff, pool_size);
625   wipememory2 (pool, 0xaa, pool_size);
626   wipememory2 (pool, 0x55, pool_size);
627   wipememory2 (pool, 0x00, pool_size);
628 #if HAVE_MMAP
629   if (pool_is_mmapped)
630     munmap (pool, pool_size);
631 #endif
632   pool = NULL;
633   pool_okay = 0;
634   pool_size = 0;
635   not_locked = 0;
636 }
637
638
639 void
640 _gcry_secmem_dump_stats ()
641 {
642 #if 1 
643   SECMEM_LOCK;
644
645  if (pool_okay)
646     log_info ("secmem usage: %u/%lu bytes in %u blocks\n",
647               cur_alloced, (unsigned long)pool_size, cur_blocks);
648   SECMEM_UNLOCK;
649 #else
650   memblock_t *mb;
651   int i;
652
653   SECMEM_LOCK;
654
655   for (i = 0, mb = (memblock_t *) pool;
656        ptr_into_pool_p (mb);
657        mb = mb_get_next (mb), i++)
658     log_info ("SECMEM: [%s] block: %i; size: %i\n",
659               (mb->flags & MB_FLAG_ACTIVE) ? "used" : "free",
660               i,
661               mb->size);
662   SECMEM_UNLOCK;
663 #endif
664 }