wipememory: use memset for non-constant length or large buffer wipes
[libgcrypt.git] / src / misc.c
1 /* misc.c
2  * Copyright (C) 1999, 2001, 2002, 2003, 2007,
3  *               2008 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, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22 #include <errno.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdarg.h>
27 #include <unistd.h>
28
29 #include "g10lib.h"
30 #include "secmem.h"
31 #include "mpi.h"
32
33 static int verbosity_level = 0;
34
35 static void *(*volatile memset_ptr)(void *, int, size_t) = (void *)memset;
36
37 static void (*fatal_error_handler)(void*,int, const char*) = NULL;
38 static void *fatal_error_handler_value = 0;
39 static void (*log_handler)(void*,int, const char*, va_list) = NULL;
40 static void *log_handler_value = 0;
41
42 static const char *(*user_gettext_handler)( const char * ) = NULL;
43
44 void
45 _gcry_set_gettext_handler (const char *(*f)(const char*))
46 {
47     user_gettext_handler = f;
48 }
49
50
51 const char *
52 _gcry_gettext( const char *key )
53 {
54     if( user_gettext_handler )
55         return user_gettext_handler( key );
56     /* FIXME: switch the domain to gnupg and restore later */
57     return key;
58 }
59
60 void
61 _gcry_set_fatalerror_handler( void (*fnc)(void*,int, const char*), void *value)
62 {
63     fatal_error_handler_value = value;
64     fatal_error_handler = fnc;
65 }
66
67 static void
68 write2stderr( const char *s )
69 {
70   /* Dummy variable to silence gcc warning.  */
71   int res = write( 2, s, strlen(s) );
72   (void) res;
73 }
74
75 /*
76  * This function is called for fatal errors.  A caller might want to
77  * set his own handler because this function simply calls abort().
78  */
79 void
80 _gcry_fatal_error (int rc, const char *text)
81 {
82   if ( !text ) /* get a default text */
83     text = gpg_strerror (rc);
84
85   if (fatal_error_handler && !fips_mode () )
86     fatal_error_handler (fatal_error_handler_value, rc, text);
87
88   fips_signal_fatal_error (text);
89   write2stderr("\nFatal error: ");
90   write2stderr(text);
91   write2stderr("\n");
92   _gcry_secmem_term ();
93   abort ();
94 }
95
96 void
97 _gcry_set_log_handler (void (*f)(void*,int, const char*, va_list), void *opaque)
98 {
99     log_handler = f;
100     log_handler_value = opaque;
101 }
102
103 void
104 _gcry_set_log_verbosity( int level )
105 {
106     verbosity_level = level;
107 }
108
109 int
110 _gcry_log_verbosity( int level )
111 {
112     return verbosity_level >= level;
113 }
114
115 /****************
116  * This is our log function which prints all log messages to stderr or
117  * using the function defined with gcry_set_log_handler().
118  */
119 void
120 _gcry_logv( int level, const char *fmt, va_list arg_ptr )
121 {
122   if (log_handler)
123     log_handler (log_handler_value, level, fmt, arg_ptr);
124   else
125     {
126       switch (level)
127         {
128         case GCRY_LOG_CONT:  break;
129         case GCRY_LOG_INFO:  break;
130         case GCRY_LOG_WARN:  break;
131         case GCRY_LOG_ERROR: break;
132         case GCRY_LOG_FATAL: fputs("Fatal: ",stderr ); break;
133         case GCRY_LOG_BUG:   fputs("Ohhhh jeeee: ", stderr); break;
134         case GCRY_LOG_DEBUG: fputs("DBG: ", stderr ); break;
135         default: fprintf(stderr,"[Unknown log level %d]: ", level ); break;
136         }
137       vfprintf(stderr,fmt,arg_ptr) ;
138     }
139
140   if ( level == GCRY_LOG_FATAL || level == GCRY_LOG_BUG )
141     {
142       fips_signal_fatal_error ("internal error (fatal or bug)");
143       _gcry_secmem_term ();
144       abort ();
145     }
146 }
147
148
149 void
150 _gcry_log( int level, const char *fmt, ... )
151 {
152     va_list arg_ptr ;
153
154     va_start( arg_ptr, fmt ) ;
155     _gcry_logv( level, fmt, arg_ptr );
156     va_end(arg_ptr);
157 }
158
159
160 #if defined(JNLIB_GCC_M_FUNCTION) || __STDC_VERSION__ >= 199901L
161 void
162 _gcry_bug( const char *file, int line, const char *func )
163 {
164     _gcry_log( GCRY_LOG_BUG,
165              ("... this is a bug (%s:%d:%s)\n"), file, line, func );
166     abort(); /* never called, but it makes the compiler happy */
167 }
168 void
169 _gcry_assert_failed (const char *expr, const char *file, int line,
170                      const char *func)
171 {
172   _gcry_log (GCRY_LOG_BUG,
173              ("Assertion `%s' failed (%s:%d:%s)\n"), expr, file, line, func );
174   abort(); /* Never called, but it makes the compiler happy. */
175 }
176 #else
177 void
178 _gcry_bug( const char *file, int line )
179 {
180     _gcry_log( GCRY_LOG_BUG,
181              _("you found a bug ... (%s:%d)\n"), file, line);
182     abort(); /* never called, but it makes the compiler happy */
183 }
184 void
185 _gcry_assert_failed (const char *expr, const char *file, int line)
186 {
187   _gcry_log (GCRY_LOG_BUG,
188              ("Assertion `%s' failed (%s:%d)\n"), expr, file, line);
189   abort(); /* Never called, but it makes the compiler happy. */
190 }
191 #endif
192
193 void
194 _gcry_log_info( const char *fmt, ... )
195 {
196     va_list arg_ptr ;
197
198     va_start( arg_ptr, fmt ) ;
199     _gcry_logv( GCRY_LOG_INFO, fmt, arg_ptr );
200     va_end(arg_ptr);
201 }
202
203 void
204 _gcry_log_error( const char *fmt, ... )
205 {
206     va_list arg_ptr ;
207
208     va_start( arg_ptr, fmt ) ;
209     _gcry_logv( GCRY_LOG_ERROR, fmt, arg_ptr );
210     va_end(arg_ptr);
211 }
212
213
214 void
215 _gcry_log_fatal( const char *fmt, ... )
216 {
217     va_list arg_ptr ;
218
219     va_start( arg_ptr, fmt ) ;
220     _gcry_logv( GCRY_LOG_FATAL, fmt, arg_ptr );
221     va_end(arg_ptr);
222     abort(); /* never called, but it makes the compiler happy */
223 }
224
225 void
226 _gcry_log_bug( const char *fmt, ... )
227 {
228     va_list arg_ptr ;
229
230     va_start( arg_ptr, fmt ) ;
231     _gcry_logv( GCRY_LOG_BUG, fmt, arg_ptr );
232     va_end(arg_ptr);
233     abort(); /* never called, but it makes the compiler happy */
234 }
235
236 void
237 _gcry_log_debug( const char *fmt, ... )
238 {
239     va_list arg_ptr ;
240
241     va_start( arg_ptr, fmt ) ;
242     _gcry_logv( GCRY_LOG_DEBUG, fmt, arg_ptr );
243     va_end(arg_ptr);
244 }
245
246
247 void
248 _gcry_log_printf (const char *fmt, ...)
249 {
250   va_list arg_ptr;
251
252   if (fmt)
253     {
254       va_start( arg_ptr, fmt ) ;
255       _gcry_logv (GCRY_LOG_CONT, fmt, arg_ptr);
256       va_end(arg_ptr);
257     }
258 }
259
260
261 /* Helper for _gcry_log_printhex and _gcry_log_printmpi.  */
262 static void
263 do_printhex (const char *text, const char *text2,
264              const void *buffer, size_t length)
265 {
266   int wrap = 0;
267   int cnt = 0;
268
269   if (text && *text)
270     {
271       wrap = 1;
272       log_debug ("%s:%s", text, text2);
273       if (text2[1] == '[' && length && buffer)
274         {
275           /* Start with a new line so that we get nice output for
276              opaque MPIS:
277                "value: [31 bit]"
278                "        01020300"  */
279           log_printf ("\n");
280           text2 = " ";
281           log_debug ("%*s  ", (int)strlen(text), "");
282         }
283     }
284   if (length && buffer)
285     {
286       const unsigned char *p = buffer;
287       for (; length--; p++)
288         {
289           log_printf ("%02x", *p);
290           if (wrap && ++cnt == 32 && length)
291             {
292               cnt = 0;
293               log_printf (" \\\n");
294               log_debug ("%*s %*s",
295                          (int)strlen(text), "", (int)strlen(text2), "");
296             }
297         }
298     }
299   if (text)
300     log_printf ("\n");
301 }
302
303
304 /* Print a hexdump of BUFFER.  With TEXT of NULL print just the raw
305    dump without any wrappping, with TEXT an empty string, print a
306    trailing linefeed, otherwise print an entire debug line. */
307 void
308 _gcry_log_printhex (const char *text, const void *buffer, size_t length)
309 {
310   do_printhex (text, " ", buffer, length);
311 }
312
313
314 /* Print MPI in hex notation.  To make clear that the output is an MPI
315    a sign is always printed. With TEXT of NULL print just the raw dump
316    without any wrapping, with TEXT an empty string, print a trailing
317    linefeed, otherwise print an entire debug line. */
318 void
319 _gcry_log_printmpi (const char *text, gcry_mpi_t mpi)
320 {
321   unsigned char *rawmpi;
322   unsigned int rawmpilen;
323   int sign;
324
325   if (!mpi)
326     do_printhex (text? text:" ", " (null)", NULL, 0);
327   else if (mpi_is_opaque (mpi))
328     {
329       unsigned int nbits;
330       const unsigned char *p;
331       char prefix[30];
332
333       p = mpi_get_opaque (mpi, &nbits);
334       snprintf (prefix, sizeof prefix, " [%u bit]", nbits);
335       do_printhex (text? text:" ", prefix, p, (nbits+7)/8);
336     }
337   else
338     {
339       rawmpi = _gcry_mpi_get_buffer (mpi, 0, &rawmpilen, &sign);
340       if (!rawmpi)
341         do_printhex (text? text:" ", " [out of core]", NULL, 0);
342       else
343         {
344           if (!rawmpilen)
345             do_printhex (text, sign? "-":"+", "", 1);
346           else
347             do_printhex (text, sign? "-":"+", rawmpi, rawmpilen);
348           xfree (rawmpi);
349         }
350     }
351 }
352
353
354 static int
355 count_closing_parens (const char *p)
356 {
357   int count = 0;
358
359   for (; *p; p++)
360     if (*p == ')')
361       count++;
362     else if (!strchr ("\n \t", *p))
363       return 0;
364
365   return count;
366 }
367
368
369 /* Print SEXP in human readabale format.  With TEXT of NULL print just the raw
370    dump without any wrappping, with TEXT an empty string, print a
371    trailing linefeed, otherwise print the full debug output. */
372 void
373 _gcry_log_printsxp (const char *text, gcry_sexp_t sexp)
374 {
375   int with_lf = 0;
376
377   if (text && *text)
378     {
379       if ((with_lf = !!strchr (text, '\n')))
380         log_debug ("%s", text);
381       else
382         log_debug ("%s: ", text);
383     }
384   if (sexp)
385     {
386       int any = 0;
387       int n_closing;
388       char *buf, *pend;
389       const char *p;
390       size_t size;
391
392       size = sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0);
393       p = buf = xmalloc (size);
394       sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, buf, size);
395
396       do
397         {
398           if (any && !with_lf)
399             log_debug ("%*s  ", text?(int)strlen(text):0, "");
400           else
401             any = 1;
402           pend = strchr (p, '\n');
403           size = pend? (pend - p) : strlen (p);
404           if (with_lf)
405             log_debug ("%.*s", (int)size, p);
406           else
407             log_printf ("%.*s", (int)size, p);
408           if (pend)
409             p = pend + 1;
410           else
411             p += size;
412           n_closing = count_closing_parens (p);
413           if (n_closing)
414             {
415               while (n_closing--)
416                 log_printf (")");
417               p = "";
418             }
419           log_printf ("\n");
420         }
421       while (*p);
422       xfree (buf);
423     }
424   else if (text)
425     log_printf ("\n");
426 }
427
428
429 /*
430  * Tokenize STRING using the set of delimiters in DELIM.  Leading
431  * white spaces are removed from all tokens.  The caller must xfree
432  * the result.
433  *
434  * Returns: A malloced and NULL delimited array with the tokens.  On
435  *          memory error NULL is returned and ERRNO is set.
436  */
437 char **
438 _gcry_strtokenize (const char *string, const char *delim)
439 {
440   const char *s;
441   size_t fields;
442   size_t bytes, n;
443   char *buffer;
444   char *p, *px, *pend;
445   char **result;
446   char const ws[] = " \t\v\f\r\n";
447
448   if (!delim)
449     delim = ws;
450
451   /* Count the number of fields.  */
452   for (fields = 1, s = strpbrk (string, delim); s; s = strpbrk (s + 1, delim))
453     fields++;
454   fields++; /* Add one for the terminating NULL.  */
455
456   /* Allocate an array for all fields, a terminating NULL, and space
457      for a copy of the string.  */
458   bytes = fields * sizeof *result;
459   if (bytes / sizeof *result != fields)
460     {
461       gpg_err_set_errno (ENOMEM);
462       return NULL;
463     }
464   n = strlen (string) + 1;
465   bytes += n;
466   if (bytes < n)
467     {
468       gpg_err_set_errno (ENOMEM);
469       return NULL;
470     }
471   result = xtrymalloc (bytes);
472   if (!result)
473     return NULL;
474   buffer = (char*)(result + fields);
475
476   /* Copy and parse the string.  */
477   strcpy (buffer, string);
478   for (n = 0, p = buffer; (pend = strpbrk (p, delim)); p = pend + 1)
479     {
480       *pend = 0;
481       while (strchr (ws, *(byte*)p))
482         p++;
483       for (px = pend - 1; px >= p && strchr (ws, *(byte*)px); px--)
484         *px = 0;
485       result[n++] = p;
486     }
487   while (*p && strchr (ws, *(byte*)p))
488     p++;
489   for (px = p + strlen (p) - 1; px >= p && strchr (ws, *(byte*)px); px--)
490     *px = 0;
491   /* Traling spaces may result in an empty field.  We do not want to
492      store that.  */
493   result[n++] = *p? p : NULL;
494   result[n] = NULL;
495
496   gcry_assert ((char*)(result + n + 1) == buffer);
497
498   return result;
499 }
500
501
502 void
503 _gcry_wipememory2 (void *ptr, int set, size_t len)
504 {
505   memset_ptr (ptr, set, len);
506 }
507
508
509 void
510 __gcry_burn_stack (unsigned int bytes)
511 {
512 #ifdef HAVE_VLA
513   /* (bytes == 0 ? 1 : bytes) == (!bytes + bytes) */
514   unsigned int buflen = ((!bytes + bytes) + 63) & ~63;
515   char buf[buflen];
516
517   memset_ptr (buf, 0, buflen);
518 #else
519   volatile char buf[64];
520
521   wipememory (buf, sizeof buf);
522
523   if (bytes > sizeof buf)
524       _gcry_burn_stack (bytes - sizeof buf);
525 #endif
526 }
527
528 #ifndef HAVE_GCC_ASM_VOLATILE_MEMORY
529 void
530 __gcry_burn_stack_dummy (void)
531 {
532 }
533 #endif
534
535 void
536 _gcry_divide_by_zero (void)
537 {
538     gpg_err_set_errno (EDOM);
539     _gcry_fatal_error (gpg_err_code_from_errno (errno), "divide by zero");
540 }