Blame src/misc.c

Packit 0680ba
/* misc.c
Packit 0680ba
 * Copyright (C) 1999, 2001, 2002, 2003, 2007,
Packit 0680ba
 *               2008 Free Software Foundation, Inc.
Packit 0680ba
 *
Packit 0680ba
 * This file is part of Libgcrypt.
Packit 0680ba
 *
Packit 0680ba
 * Libgcrypt is free software; you can redistribute it and/or modify
Packit 0680ba
 * it under the terms of the GNU Lesser General Public License as
Packit 0680ba
 * published by the Free Software Foundation; either version 2.1 of
Packit 0680ba
 * the License, or (at your option) any later version.
Packit 0680ba
 *
Packit 0680ba
 * Libgcrypt is distributed in the hope that it will be useful,
Packit 0680ba
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 0680ba
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 0680ba
 * GNU Lesser General Public License for more details.
Packit 0680ba
 *
Packit 0680ba
 * You should have received a copy of the GNU Lesser General Public
Packit 0680ba
 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
Packit 0680ba
 */
Packit 0680ba
Packit 0680ba
#include <config.h>
Packit 0680ba
#include <errno.h>
Packit 0680ba
#include <stdio.h>
Packit 0680ba
#include <stdlib.h>
Packit 0680ba
#include <string.h>
Packit 0680ba
#include <stdarg.h>
Packit 0680ba
#include <unistd.h>
Packit 0680ba
Packit 0680ba
#include "g10lib.h"
Packit 0680ba
#include "secmem.h"
Packit 0680ba
#include "mpi.h"
Packit 0680ba
Packit 0680ba
static int verbosity_level = 0;
Packit 0680ba
Packit 0680ba
static void (*fatal_error_handler)(void*,int, const char*) = NULL;
Packit 0680ba
static void *fatal_error_handler_value = 0;
Packit 0680ba
static void (*log_handler)(void*,int, const char*, va_list) = NULL;
Packit 0680ba
static void *log_handler_value = 0;
Packit 0680ba
Packit 0680ba
static const char *(*user_gettext_handler)( const char * ) = NULL;
Packit 0680ba
Packit 0680ba
void
Packit 0680ba
_gcry_set_gettext_handler (const char *(*f)(const char*))
Packit 0680ba
{
Packit 0680ba
    user_gettext_handler = f;
Packit 0680ba
}
Packit 0680ba
Packit 0680ba
Packit 0680ba
const char *
Packit 0680ba
_gcry_gettext( const char *key )
Packit 0680ba
{
Packit 0680ba
    if( user_gettext_handler )
Packit 0680ba
	return user_gettext_handler( key );
Packit 0680ba
    /* FIXME: switch the domain to gnupg and restore later */
Packit 0680ba
    return key;
Packit 0680ba
}
Packit 0680ba
Packit 0680ba
void
Packit 0680ba
_gcry_set_fatalerror_handler( void (*fnc)(void*,int, const char*), void *value)
Packit 0680ba
{
Packit 0680ba
    fatal_error_handler_value = value;
Packit 0680ba
    fatal_error_handler = fnc;
Packit 0680ba
}
Packit 0680ba
Packit 0680ba
static void
Packit 0680ba
write2stderr( const char *s )
Packit 0680ba
{
Packit 0680ba
  /* Dummy variable to silence gcc warning.  */
Packit 0680ba
  int res = write( 2, s, strlen(s) );
Packit 0680ba
  (void) res;
Packit 0680ba
}
Packit 0680ba
Packit 0680ba
/*
Packit 0680ba
 * This function is called for fatal errors.  A caller might want to
Packit 0680ba
 * set his own handler because this function simply calls abort().
Packit 0680ba
 */
Packit 0680ba
void
Packit 0680ba
_gcry_fatal_error (int rc, const char *text)
Packit 0680ba
{
Packit 0680ba
  if ( !text ) /* get a default text */
Packit 0680ba
    text = gpg_strerror (rc);
Packit 0680ba
Packit 0680ba
  if (fatal_error_handler && !fips_mode () )
Packit 0680ba
    fatal_error_handler (fatal_error_handler_value, rc, text);
Packit 0680ba
Packit 0680ba
  fips_signal_fatal_error (text);
Packit 0680ba
  write2stderr("\nFatal error: ");
Packit 0680ba
  write2stderr(text);
Packit 0680ba
  write2stderr("\n");
Packit 0680ba
  _gcry_secmem_term ();
Packit 0680ba
  abort ();
Packit 0680ba
}
Packit 0680ba
Packit 0680ba
void
Packit 0680ba
_gcry_set_log_handler (void (*f)(void*,int, const char*, va_list), void *opaque)
Packit 0680ba
{
Packit 0680ba
    log_handler = f;
Packit 0680ba
    log_handler_value = opaque;
Packit 0680ba
}
Packit 0680ba
Packit 0680ba
void
Packit 0680ba
_gcry_set_log_verbosity( int level )
Packit 0680ba
{
Packit 0680ba
    verbosity_level = level;
Packit 0680ba
}
Packit 0680ba
Packit 0680ba
int
Packit 0680ba
_gcry_log_verbosity( int level )
Packit 0680ba
{
Packit 0680ba
    return verbosity_level >= level;
Packit 0680ba
}
Packit 0680ba
Packit 0680ba
/****************
Packit 0680ba
 * This is our log function which prints all log messages to stderr or
Packit 0680ba
 * using the function defined with gcry_set_log_handler().
Packit 0680ba
 */
Packit 0680ba
void
Packit 0680ba
_gcry_logv( int level, const char *fmt, va_list arg_ptr )
Packit 0680ba
{
Packit 0680ba
  if (log_handler)
Packit 0680ba
    log_handler (log_handler_value, level, fmt, arg_ptr);
Packit 0680ba
  else
Packit 0680ba
    {
Packit 0680ba
      switch (level)
Packit 0680ba
        {
Packit 0680ba
        case GCRY_LOG_CONT:  break;
Packit 0680ba
        case GCRY_LOG_INFO:  break;
Packit 0680ba
        case GCRY_LOG_WARN:  break;
Packit 0680ba
        case GCRY_LOG_ERROR: break;
Packit 0680ba
        case GCRY_LOG_FATAL: fputs("Fatal: ",stderr ); break;
Packit 0680ba
        case GCRY_LOG_BUG:   fputs("Ohhhh jeeee: ", stderr); break;
Packit 0680ba
        case GCRY_LOG_DEBUG: fputs("DBG: ", stderr ); break;
Packit 0680ba
        default: fprintf(stderr,"[Unknown log level %d]: ", level ); break;
Packit 0680ba
	}
Packit 0680ba
      vfprintf(stderr,fmt,arg_ptr) ;
Packit 0680ba
    }
Packit 0680ba
Packit 0680ba
  if ( level == GCRY_LOG_FATAL || level == GCRY_LOG_BUG )
Packit 0680ba
    {
Packit 0680ba
      fips_signal_fatal_error ("internal error (fatal or bug)");
Packit 0680ba
      _gcry_secmem_term ();
Packit 0680ba
      abort ();
Packit 0680ba
    }
Packit 0680ba
}
Packit 0680ba
Packit 0680ba
Packit 0680ba
void
Packit 0680ba
_gcry_log( int level, const char *fmt, ... )
Packit 0680ba
{
Packit 0680ba
    va_list arg_ptr ;
Packit 0680ba
Packit 0680ba
    va_start( arg_ptr, fmt ) ;
Packit 0680ba
    _gcry_logv( level, fmt, arg_ptr );
Packit 0680ba
    va_end(arg_ptr);
Packit 0680ba
}
Packit 0680ba
Packit 0680ba
Packit 0680ba
#if defined(JNLIB_GCC_M_FUNCTION) || __STDC_VERSION__ >= 199901L
Packit 0680ba
void
Packit 0680ba
_gcry_bug( const char *file, int line, const char *func )
Packit 0680ba
{
Packit 0680ba
    _gcry_log( GCRY_LOG_BUG,
Packit 0680ba
	     ("... this is a bug (%s:%d:%s)\n"), file, line, func );
Packit 0680ba
    abort(); /* never called, but it makes the compiler happy */
Packit 0680ba
}
Packit 0680ba
void
Packit 0680ba
_gcry_assert_failed (const char *expr, const char *file, int line,
Packit 0680ba
                     const char *func)
Packit 0680ba
{
Packit 0680ba
  _gcry_log (GCRY_LOG_BUG,
Packit 0680ba
             ("Assertion `%s' failed (%s:%d:%s)\n"), expr, file, line, func );
Packit 0680ba
  abort(); /* Never called, but it makes the compiler happy. */
Packit 0680ba
}
Packit 0680ba
#else
Packit 0680ba
void
Packit 0680ba
_gcry_bug( const char *file, int line )
Packit 0680ba
{
Packit 0680ba
    _gcry_log( GCRY_LOG_BUG,
Packit 0680ba
	     _("you found a bug ... (%s:%d)\n"), file, line);
Packit 0680ba
    abort(); /* never called, but it makes the compiler happy */
Packit 0680ba
}
Packit 0680ba
void
Packit 0680ba
_gcry_assert_failed (const char *expr, const char *file, int line)
Packit 0680ba
{
Packit 0680ba
  _gcry_log (GCRY_LOG_BUG,
Packit 0680ba
             ("Assertion `%s' failed (%s:%d)\n"), expr, file, line);
Packit 0680ba
  abort(); /* Never called, but it makes the compiler happy. */
Packit 0680ba
}
Packit 0680ba
#endif
Packit 0680ba
Packit 0680ba
void
Packit 0680ba
_gcry_log_info( const char *fmt, ... )
Packit 0680ba
{
Packit 0680ba
    va_list arg_ptr ;
Packit 0680ba
Packit 0680ba
    va_start( arg_ptr, fmt ) ;
Packit 0680ba
    _gcry_logv( GCRY_LOG_INFO, fmt, arg_ptr );
Packit 0680ba
    va_end(arg_ptr);
Packit 0680ba
}
Packit 0680ba
Packit 0680ba
int
Packit 0680ba
_gcry_log_info_with_dummy_fp (FILE *fp, const char *fmt, ... )
Packit 0680ba
{
Packit 0680ba
    va_list arg_ptr;
Packit 0680ba
Packit 0680ba
    (void)fp;
Packit 0680ba
    va_start( arg_ptr, fmt ) ;
Packit 0680ba
    _gcry_logv( GCRY_LOG_INFO, fmt, arg_ptr );
Packit 0680ba
    va_end(arg_ptr);
Packit 0680ba
    return 0;
Packit 0680ba
}
Packit 0680ba
Packit 0680ba
void
Packit 0680ba
_gcry_log_error( const char *fmt, ... )
Packit 0680ba
{
Packit 0680ba
    va_list arg_ptr ;
Packit 0680ba
Packit 0680ba
    va_start( arg_ptr, fmt ) ;
Packit 0680ba
    _gcry_logv( GCRY_LOG_ERROR, fmt, arg_ptr );
Packit 0680ba
    va_end(arg_ptr);
Packit 0680ba
}
Packit 0680ba
Packit 0680ba
Packit 0680ba
void
Packit 0680ba
_gcry_log_fatal( const char *fmt, ... )
Packit 0680ba
{
Packit 0680ba
    va_list arg_ptr ;
Packit 0680ba
Packit 0680ba
    va_start( arg_ptr, fmt ) ;
Packit 0680ba
    _gcry_logv( GCRY_LOG_FATAL, fmt, arg_ptr );
Packit 0680ba
    va_end(arg_ptr);
Packit 0680ba
    abort(); /* never called, but it makes the compiler happy */
Packit 0680ba
}
Packit 0680ba
Packit 0680ba
void
Packit 0680ba
_gcry_log_bug( const char *fmt, ... )
Packit 0680ba
{
Packit 0680ba
    va_list arg_ptr ;
Packit 0680ba
Packit 0680ba
    va_start( arg_ptr, fmt ) ;
Packit 0680ba
    _gcry_logv( GCRY_LOG_BUG, fmt, arg_ptr );
Packit 0680ba
    va_end(arg_ptr);
Packit 0680ba
    abort(); /* never called, but it makes the compiler happy */
Packit 0680ba
}
Packit 0680ba
Packit 0680ba
void
Packit 0680ba
_gcry_log_debug( const char *fmt, ... )
Packit 0680ba
{
Packit 0680ba
    va_list arg_ptr ;
Packit 0680ba
Packit 0680ba
    va_start( arg_ptr, fmt ) ;
Packit 0680ba
    _gcry_logv( GCRY_LOG_DEBUG, fmt, arg_ptr );
Packit 0680ba
    va_end(arg_ptr);
Packit 0680ba
}
Packit 0680ba
Packit 0680ba
Packit 0680ba
void
Packit 0680ba
_gcry_log_printf (const char *fmt, ...)
Packit 0680ba
{
Packit 0680ba
  va_list arg_ptr;
Packit 0680ba
Packit 0680ba
  if (fmt)
Packit 0680ba
    {
Packit 0680ba
      va_start( arg_ptr, fmt ) ;
Packit 0680ba
      _gcry_logv (GCRY_LOG_CONT, fmt, arg_ptr);
Packit 0680ba
      va_end(arg_ptr);
Packit 0680ba
    }
Packit 0680ba
}
Packit 0680ba
Packit 0680ba
Packit 0680ba
/* Helper for _gcry_log_printhex and _gcry_log_printmpi.  */
Packit 0680ba
static void
Packit 0680ba
do_printhex (const char *text, const char *text2,
Packit 0680ba
             const void *buffer, size_t length)
Packit 0680ba
{
Packit 0680ba
  int wrap = 0;
Packit 0680ba
  int cnt = 0;
Packit 0680ba
Packit 0680ba
  if (text && *text)
Packit 0680ba
    {
Packit 0680ba
      wrap = 1;
Packit 0680ba
      log_debug ("%s:%s", text, text2);
Packit 0680ba
      if (text2[1] == '[' && length && buffer)
Packit 0680ba
        {
Packit 0680ba
          /* Start with a new line so that we get nice output for
Packit 0680ba
             opaque MPIS:
Packit 0680ba
               "value: [31 bit]"
Packit 0680ba
               "        01020300"  */
Packit 0680ba
          log_printf ("\n");
Packit 0680ba
          text2 = " ";
Packit 0680ba
          log_debug ("%*s  ", (int)strlen(text), "");
Packit 0680ba
        }
Packit 0680ba
    }
Packit 0680ba
  if (length)
Packit 0680ba
    {
Packit 0680ba
      const unsigned char *p = buffer;
Packit 0680ba
      for (; length--; p++)
Packit 0680ba
        {
Packit 0680ba
          log_printf ("%02x", *p);
Packit 0680ba
          if (wrap && ++cnt == 32 && length)
Packit 0680ba
            {
Packit 0680ba
              cnt = 0;
Packit 0680ba
              log_printf (" \\\n");
Packit 0680ba
              log_debug ("%*s %*s",
Packit 0680ba
                         (int)strlen(text), "", (int)strlen(text2), "");
Packit 0680ba
            }
Packit 0680ba
        }
Packit 0680ba
    }
Packit 0680ba
  if (text)
Packit 0680ba
    log_printf ("\n");
Packit 0680ba
}
Packit 0680ba
Packit 0680ba
Packit 0680ba
/* Print a hexdump of BUFFER.  With TEXT of NULL print just the raw
Packit 0680ba
   dump without any wrappping, with TEXT an empty string, print a
Packit 0680ba
   trailing linefeed, otherwise print an entire debug line. */
Packit 0680ba
void
Packit 0680ba
_gcry_log_printhex (const char *text, const void *buffer, size_t length)
Packit 0680ba
{
Packit 0680ba
  do_printhex (text, " ", buffer, length);
Packit 0680ba
}
Packit 0680ba
Packit 0680ba
Packit 0680ba
/* Print MPI in hex notation.  To make clear that the output is an MPI
Packit 0680ba
   a sign is always printed. With TEXT of NULL print just the raw dump
Packit 0680ba
   without any wrapping, with TEXT an empty string, print a trailing
Packit 0680ba
   linefeed, otherwise print an entire debug line. */
Packit 0680ba
void
Packit 0680ba
_gcry_log_printmpi (const char *text, gcry_mpi_t mpi)
Packit 0680ba
{
Packit 0680ba
  unsigned char *rawmpi;
Packit 0680ba
  unsigned int rawmpilen;
Packit 0680ba
  int sign;
Packit 0680ba
Packit 0680ba
  if (!mpi)
Packit 0680ba
    do_printhex (text? text:" ", " (null)", NULL, 0);
Packit 0680ba
  else if (mpi_is_opaque (mpi))
Packit 0680ba
    {
Packit 0680ba
      unsigned int nbits;
Packit 0680ba
      const unsigned char *p;
Packit 0680ba
      char prefix[30];
Packit 0680ba
Packit 0680ba
      p = mpi_get_opaque (mpi, &nbits);
Packit 0680ba
      snprintf (prefix, sizeof prefix, " [%u bit]", nbits);
Packit 0680ba
      do_printhex (text? text:" ", prefix, p, (nbits+7)/8);
Packit 0680ba
    }
Packit 0680ba
  else
Packit 0680ba
    {
Packit 0680ba
      rawmpi = _gcry_mpi_get_buffer (mpi, 0, &rawmpilen, &sign;;
Packit 0680ba
      if (!rawmpi)
Packit 0680ba
        do_printhex (text? text:" ", " [out of core]", NULL, 0);
Packit 0680ba
      else
Packit 0680ba
        {
Packit 0680ba
          if (!rawmpilen)
Packit 0680ba
            do_printhex (text, sign? "-":"+", "", 1);
Packit 0680ba
          else
Packit 0680ba
            do_printhex (text, sign? "-":"+", rawmpi, rawmpilen);
Packit 0680ba
          xfree (rawmpi);
Packit 0680ba
        }
Packit 0680ba
    }
Packit 0680ba
}
Packit 0680ba
Packit 0680ba
Packit 0680ba
static int
Packit 0680ba
count_closing_parens (const char *p)
Packit 0680ba
{
Packit 0680ba
  int count = 0;
Packit 0680ba
Packit 0680ba
  for (; *p; p++)
Packit 0680ba
    if (*p == ')')
Packit 0680ba
      count++;
Packit 0680ba
    else if (!strchr ("\n \t", *p))
Packit 0680ba
      return 0;
Packit 0680ba
Packit 0680ba
  return count;
Packit 0680ba
}
Packit 0680ba
Packit 0680ba
Packit 0680ba
/* Print SEXP in human readabale format.  With TEXT of NULL print just the raw
Packit 0680ba
   dump without any wrappping, with TEXT an empty string, print a
Packit 0680ba
   trailing linefeed, otherwise print the full debug output. */
Packit 0680ba
void
Packit 0680ba
_gcry_log_printsxp (const char *text, gcry_sexp_t sexp)
Packit 0680ba
{
Packit 0680ba
  int with_lf = 0;
Packit 0680ba
Packit 0680ba
  if (text && *text)
Packit 0680ba
    {
Packit 0680ba
      if ((with_lf = !!strchr (text, '\n')))
Packit 0680ba
        log_debug ("%s", text);
Packit 0680ba
      else
Packit 0680ba
        log_debug ("%s: ", text);
Packit 0680ba
    }
Packit 0680ba
  if (sexp)
Packit 0680ba
    {
Packit 0680ba
      int any = 0;
Packit 0680ba
      int n_closing;
Packit 0680ba
      char *buf, *pend;
Packit 0680ba
      const char *p;
Packit 0680ba
      size_t size;
Packit 0680ba
Packit 0680ba
      size = sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0);
Packit 0680ba
      p = buf = xmalloc (size);
Packit 0680ba
      sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, buf, size);
Packit 0680ba
Packit 0680ba
      do
Packit 0680ba
        {
Packit 0680ba
          if (any && !with_lf)
Packit 0680ba
            log_debug ("%*s  ", (int)strlen(text), "");
Packit 0680ba
          else
Packit 0680ba
            any = 1;
Packit 0680ba
          pend = strchr (p, '\n');
Packit 0680ba
          size = pend? (pend - p) : strlen (p);
Packit 0680ba
          if (with_lf)
Packit 0680ba
            log_debug ("%.*s", (int)size, p);
Packit 0680ba
          else
Packit 0680ba
            log_printf ("%.*s", (int)size, p);
Packit 0680ba
          if (pend)
Packit 0680ba
            p = pend + 1;
Packit 0680ba
          else
Packit 0680ba
            p += size;
Packit 0680ba
          n_closing = count_closing_parens (p);
Packit 0680ba
          if (n_closing)
Packit 0680ba
            {
Packit 0680ba
              while (n_closing--)
Packit 0680ba
                log_printf (")");
Packit 0680ba
              p = "";
Packit 0680ba
            }
Packit 0680ba
          log_printf ("\n");
Packit 0680ba
        }
Packit 0680ba
      while (*p);
Packit 0680ba
      xfree (buf);
Packit 0680ba
    }
Packit 0680ba
  else if (text)
Packit 0680ba
    log_printf ("\n");
Packit 0680ba
}
Packit 0680ba
Packit 0680ba
Packit 0680ba
void
Packit 0680ba
__gcry_burn_stack (unsigned int bytes)
Packit 0680ba
{
Packit 0680ba
#ifdef HAVE_VLA
Packit 0680ba
    /* (bytes == 0 ? 1 : bytes) == (!bytes + bytes) */
Packit 0680ba
    unsigned int buflen = ((!bytes + bytes) + 63) & ~63;
Packit 0680ba
    volatile char buf[buflen];
Packit 0680ba
Packit 0680ba
    wipememory (buf, sizeof buf);
Packit 0680ba
#else
Packit 0680ba
    volatile char buf[64];
Packit 0680ba
Packit 0680ba
    wipememory (buf, sizeof buf);
Packit 0680ba
Packit 0680ba
    if (bytes > sizeof buf)
Packit 0680ba
        _gcry_burn_stack (bytes - sizeof buf);
Packit 0680ba
#endif
Packit 0680ba
}
Packit 0680ba
Packit 0680ba
#ifndef HAVE_GCC_ASM_VOLATILE_MEMORY
Packit 0680ba
void
Packit 0680ba
__gcry_burn_stack_dummy (void)
Packit 0680ba
{
Packit 0680ba
}
Packit 0680ba
#endif
Packit 0680ba
Packit 0680ba
void
Packit 0680ba
_gcry_divide_by_zero (void)
Packit 0680ba
{
Packit 0680ba
    gpg_err_set_errno (EDOM);
Packit 0680ba
    _gcry_fatal_error (gpg_err_code_from_errno (errno), "divide by zero");
Packit 0680ba
}