Esempio n. 1
0
/* Turn VALUE into an octet string and store it in an allocated buffer
   at R_FRAME.  If the resulting octet string is shorter than NBYTES
   the result will be left padded with zeroes.  If VALUE does not fit
   into NBYTES an error code is returned.  */
static gpg_err_code_t
int2octets (unsigned char **r_frame, gcry_mpi_t value, size_t nbytes)
{
  gpg_err_code_t rc;
  size_t nframe, noff, n;
  unsigned char *frame;

  rc = gpg_err_code (gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0,
                                      &nframe, value));
  if (rc)
    return rc;
  if (nframe > nbytes)
    return GPG_ERR_TOO_LARGE; /* Value too long to fit into NBYTES.  */

  noff = (nframe < nbytes)? nbytes - nframe : 0;
  n = nframe + noff;
  frame = mpi_is_secure (value)? gcry_malloc_secure (n) : gcry_malloc (n);
  if (!frame)
    return gpg_err_code_from_syserror ();
  if (noff)
    memset (frame, 0, noff);
  nframe += noff;
  rc = gpg_err_code (gcry_mpi_print (GCRYMPI_FMT_USG, frame+noff, nframe-noff,
                                      NULL, value));
  if (rc)
    {
      gcry_free (frame);
      return rc;
    }

  *r_frame = frame;
  return 0;
}
Esempio n. 2
0
void *
gcry_xmalloc( size_t n )
{
    void *p;

    while ( !(p = gcry_malloc( n )) ) {
	if( !outofcore_handler
	    || !outofcore_handler( outofcore_handler_value, n, 0 ) ) {
	    _gcry_fatal_error(gpg_err_code_from_errno (errno), NULL );
	}
    }
    return p;
}
Esempio n. 3
0
char* sexp_string(gcry_sexp_t sexp) {
	size_t buf_len = gcry_sexp_sprint(sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0);
	char *buffer = (char*)gcry_malloc(buf_len);
	if (buffer == NULL) {
		printf("gcry_malloc(%ld) returned NULL in sexp_string()!\n", buf_len);
		exit(1);
	}
	if (0 == gcry_sexp_sprint(sexp, GCRYSEXP_FMT_ADVANCED, buffer, buf_len)) {
		printf("gcry_sexp_sprint() lies!\n");
		exit(1);
	}
	return buffer;

	// This should be freed with gcry_free(buffer);
}
Esempio n. 4
0
/* Return an allocated buffer with the MPI (msb first).  NBYTES
   receives the length of this buffer.  Caller must free the return
   string.  This function returns an allocated buffer with NBYTES set
   to zero if the value of A is zero.  If sign is not NULL, it will be
   set to the sign of the A.  On error NULL is returned and ERRNO set
   appropriately.  */
static unsigned char *
do_get_buffer (gcry_mpi_t a, unsigned int *nbytes, int *sign, int force_secure)
{
  unsigned char *p, *buffer;
  mpi_limb_t alimb;
  int i;
  size_t n;

  if (sign)
    *sign = a->sign;

  *nbytes = a->nlimbs * BYTES_PER_MPI_LIMB;
  n = *nbytes? *nbytes:1; /* Allocate at least one byte.  */
  p = buffer = (force_secure || mpi_is_secure(a))? gcry_malloc_secure (n)
						 : gcry_malloc (n);
  if (!buffer)
    return NULL;

  for (i=a->nlimbs-1; i >= 0; i--)
    {
      alimb = a->d[i];
#if BYTES_PER_MPI_LIMB == 4
      *p++ = alimb >> 24;
      *p++ = alimb >> 16;
      *p++ = alimb >>  8;
      *p++ = alimb	  ;
#elif BYTES_PER_MPI_LIMB == 8
      *p++ = alimb >> 56;
      *p++ = alimb >> 48;
      *p++ = alimb >> 40;
      *p++ = alimb >> 32;
      *p++ = alimb >> 24;
      *p++ = alimb >> 16;
      *p++ = alimb >>  8;
      *p++ = alimb	  ;
#else
#     error please implement for this limb size.
#endif
    }

  /* This is sub-optimal but we need to do the shift operation because
     the caller has to free the returned buffer.  */
  for (p=buffer; *nbytes && !*p; p++, --*nbytes)
    ;
  if (p != buffer)
    memmove (buffer,p, *nbytes);
  return buffer;
}
Esempio n. 5
0
/* Get a string from the car.  The returned value is a malloced string
   and needs to be freed by the caller.  */
char *
gcry_sexp_nth_string (const gcry_sexp_t list, int number)
{
  const char *s;
  size_t n;
  char *buf;

  s = sexp_nth_data (list, number, &n);
  if (!s || n < 1 || (n+1) < 1)
    return NULL;
  buf = gcry_malloc (n+1);
  if (!buf)
    return NULL;
  memcpy (buf, s, n);
  buf[n] = 0;
  return buf;
}
Esempio n. 6
0
/* Get the nth element of a list which needs to be a simple object.
   The returned value is a malloced buffer and needs to be freed by
   the caller.  This is basically the same as gcry_sexp_nth_data but
   with an allocated result. */
void *
gcry_sexp_nth_buffer (const gcry_sexp_t list, int number, size_t *rlength)
{
  const char *s;
  size_t n;
  char *buf;

  *rlength = 0;
  s = sexp_nth_data (list, number, &n);
  if (!s || !n)
    return NULL;
  buf = gcry_malloc (n);
  if (!buf)
    return NULL;
  memcpy (buf, s, n);
  *rlength = n;
  return buf;
}
Esempio n. 7
0
/* Create and return a copy of the null-terminated string STRING.  If
   it is contained in secure memory, the copy will be contained in
   secure memory as well.  In an out-of-memory condition, NULL is
   returned.  */
char *
gcry_strdup (const char *string)
{
  char *string_cp = NULL;
  size_t string_n = 0;

  string_n = strlen (string);

  if (gcry_is_secure (string))
    string_cp = gcry_malloc_secure (string_n + 1);
  else
    string_cp = gcry_malloc (string_n + 1);
  
  if (string_cp)
    strcpy (string_cp, string);

  return string_cp;
}
Esempio n. 8
0
void *
gcry_calloc (size_t n, size_t m)
{
  size_t bytes;
  void *p;

  bytes = n * m; /* size_t is unsigned so the behavior on overflow is
                    defined. */
  if (m && bytes / m != n) 
    {
      errno = ENOMEM;
      return NULL;
    }

  p = gcry_malloc (bytes);
  if (p)
    memset (p, 0, bytes);
  return p;
}
Esempio n. 9
0
/* Add a module specification to the list ENTRIES.  The new module has
   it's use-counter set to one.  */
gcry_err_code_t
_gcry_module_add (gcry_module_t *entries, unsigned int mod_id,
		  void *spec, void *extraspec, gcry_module_t *module)
{
  gcry_err_code_t err = 0;
  gcry_module_t entry;

  if (! mod_id)
    err = _gcry_module_id_new (*entries, &mod_id);

  if (! err)
    {
      entry = gcry_malloc (sizeof (struct gcry_module));
      if (! entry)
	err = gpg_err_code_from_errno (errno);
    }

  if (! err)
    {
      /* Fill new module entry.  */
      entry->flags = 0;
      entry->counter = 1;
      entry->spec = spec;
      entry->extraspec = extraspec;
      entry->mod_id = mod_id;

      /* Link it into the list.  */
      entry->next = *entries;
      entry->prevp = entries;
      if (*entries)
	(*entries)->prevp = &entry->next;
      *entries = entry;

      /* And give it to the caller.  */
      if (module)
	*module = entry;
    }
  return err;
}
Esempio n. 10
0
/****************
 * This function allocates an MPI which is optimized to hold
 * a value as large as the one given in the argument and allocates it
 * with the same flags as A.
 */
gcry_mpi_t
_gcry_mpi_alloc_like( gcry_mpi_t a )
{
    gcry_mpi_t b;

    if( a && (a->flags & 4) ) {
	int n = (a->sign+7)/8;
	void *p = gcry_is_secure(a->d)? gcry_malloc_secure( n )
				     : gcry_malloc( n );
	memcpy( p, a->d, n );
	b = gcry_mpi_set_opaque( NULL, p, a->sign );
    }
    else if( a ) {
	b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs )
			    : mpi_alloc( a->nlimbs );
	b->nlimbs = 0;
	b->sign = 0;
	b->flags = a->flags;
    }
    else
	b = NULL;
    return b;
}
Esempio n. 11
0
/* Return the so called KEYGRIP which is the SHA-1 hash of the public
   key parameters expressed in a way depending on the algorithm.

   ARRAY must either be 20 bytes long or NULL; in the latter case a
   newly allocated array of that size is returned, otherwise ARRAY or
   NULL is returned to indicate an error which is most likely an
   unknown algorithm.  The function accepts public or secret keys. */
unsigned char *
gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array)
{
  gcry_sexp_t list = NULL;
  gcry_sexp_t l2 = NULL;
  gcry_pk_spec_t *spec = NULL;
  const char *s;
  char *name = NULL;
  int idx;
  const char *elems;
  gcry_md_hd_t md = NULL;
  int okay = 0;

  /* Check that the first element is valid. */
  list = gcry_sexp_find_token (key, "public-key", 0);
  if (! list)
    list = gcry_sexp_find_token (key, "private-key", 0);
  if (! list)
    list = gcry_sexp_find_token (key, "protected-private-key", 0);
  if (! list)
    list = gcry_sexp_find_token (key, "shadowed-private-key", 0);
  if (! list)
    return NULL; /* No public- or private-key object. */

  l2 = gcry_sexp_cadr (list);
  gcry_sexp_release (list);
  list = l2;
  l2 = NULL;

  name = _gcry_sexp_nth_string (list, 0);
  if (!name)
    goto fail; /* Invalid structure of object. */

  spec = spec_from_name (name);
  if (!spec)
    goto fail; /* Unknown algorithm.  */

  elems = spec->elements_grip;
  if (!elems)
    goto fail; /* No grip parameter.  */

  if (gcry_md_open (&md, GCRY_MD_SHA1, 0))
    goto fail;

  if (spec->comp_keygrip)
    {
      /* Module specific method to compute a keygrip.  */
      if (spec->comp_keygrip (md, list))
        goto fail;
    }
  else
    {
      /* Generic method to compute a keygrip.  */
      for (idx = 0, s = elems; *s; s++, idx++)
        {
          const char *data;
          size_t datalen;
          char buf[30];

          l2 = gcry_sexp_find_token (list, s, 1);
          if (! l2)
            goto fail;
          data = gcry_sexp_nth_data (l2, 1, &datalen);
          if (! data)
            goto fail;

          snprintf (buf, sizeof buf, "(1:%c%u:", *s, (unsigned int)datalen);
          gcry_md_write (md, buf, strlen (buf));
          gcry_md_write (md, data, datalen);
          gcry_sexp_release (l2);
          l2 = NULL;
          gcry_md_write (md, ")", 1);
        }
    }

  if (!array)
    {
      array = gcry_malloc (20);
      if (! array)
        goto fail;
    }

  memcpy (array, gcry_md_read (md, GCRY_MD_SHA1), 20);
  okay = 1;

 fail:
  gcry_free (name);
  gcry_sexp_release (l2);
  gcry_md_close (md);
  gcry_sexp_release (list);
  return okay? array : NULL;
}
Esempio n. 12
0
/****************
 * Scan the provided buffer and return the S expression in our internal
 * format.  Returns a newly allocated expression.  If erroff is not NULL and
 * a parsing error has occurred, the offset into buffer will be returned.
 * If ARGFLAG is true, the function supports some printf like
 * expressions.
 *  These are:
 *	%m - MPI
 *	%s - string (no autoswitch to secure allocation)
 *	%d - integer stored as string (no autoswitch to secure allocation)
 *      %b - memory buffer; this takes _two_ arguments: an integer with the
 *           length of the buffer and a pointer to the buffer.
 *      %S - Copy an gcry_sexp_t here.  The S-expression needs to be a
 *           regular one, starting with a parenthesis.
 *           (no autoswitch to secure allocation)
 *  all other format elements are currently not defined and return an error.
 *  this includes the "%%" sequence becauce the percent sign is not an
 *  allowed character.
 * FIXME: We should find a way to store the secure-MPIs not in the string
 * but as reference to somewhere - this can help us to save huge amounts
 * of secure memory.  The problem is, that if only one element is secure, all
 * other elements are automagicaly copied to secure memory too, so the most
 * common operation gcry_sexp_cdr_mpi() will always return a secure MPI
 * regardless whether it is needed or not.
 */
static gcry_error_t
vsexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
	     const char *buffer, size_t length, int argflag,
	     void **arg_list, va_list arg_ptr)
{
  gcry_err_code_t err = 0;
  static const char tokenchars[] =
    "abcdefghijklmnopqrstuvwxyz"
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "0123456789-./_:*+=";
  const char *p;
  size_t n;
  const char *digptr = NULL;
  const char *quoted = NULL;
  const char *tokenp = NULL;
  const char *hexfmt = NULL;
  const char *base64 = NULL;
  const char *disphint = NULL;
  const char *percent = NULL;
  int hexcount = 0;
  int quoted_esc = 0;
  int datalen = 0;
  size_t dummy_erroff;
  struct make_space_ctx c;
  int arg_counter = 0;
  int level = 0;

  if (!erroff)
    erroff = &dummy_erroff;

  /* Depending on whether ARG_LIST is non-zero or not, this macro gives
     us the next argument, either from the variable argument list as
     specified by ARG_PTR or from the argument array ARG_LIST.  */
#define ARG_NEXT(storage, type)                          \
  do                                                     \
    {                                                    \
      if (!arg_list)                                     \
	storage = va_arg (arg_ptr, type);                \
      else                                               \
	storage = *((type *) (arg_list[arg_counter++])); \
    }                                                    \
  while (0)

  /* The MAKE_SPACE macro is used before each store operation to
     ensure that the buffer is large enough.  It requires a global
     context named C and jumps out to the label LEAVE on error! It
     also sets ERROFF using the variables BUFFER and P.  */
#define MAKE_SPACE(n)  do {                                                \
                            gpg_err_code_t _ms_err = make_space (&c, (n)); \
                            if (_ms_err)                                   \
                              {                                            \
                                err = _ms_err;                             \
                                *erroff = p - buffer;                      \
                                goto leave;                                \
                              }                                            \
                       } while (0)

  /* The STORE_LEN macro is used to store the length N at buffer P. */
#define STORE_LEN(p,n) do {						   \
			    DATALEN ashort = (n);			   \
			    memcpy ( (p), &ashort, sizeof(ashort) );	   \
			    (p) += sizeof (ashort);			   \
			} while (0)

  /* We assume that the internal representation takes less memory than
     the provided one.  However, we add space for one extra datalen so
     that the code which does the ST_CLOSE can use MAKE_SPACE */
  c.allocated = length + sizeof(DATALEN);
  if (buffer && length && gcry_is_secure (buffer))
    c.sexp = gcry_malloc_secure (sizeof *c.sexp + c.allocated - 1);
  else
    c.sexp = gcry_malloc (sizeof *c.sexp + c.allocated - 1);
  if (!c.sexp)
    {
      err = gpg_err_code_from_errno (errno);
      *erroff = 0;
      goto leave;
    }
  c.pos = c.sexp->d;

  for (p = buffer, n = length; n; p++, n--)
    {
      if (tokenp && !hexfmt)
	{
	  if (strchr (tokenchars, *p))
	    continue;
	  else
	    {
	      datalen = p - tokenp;
	      MAKE_SPACE (datalen);
	      *c.pos++ = ST_DATA;
	      STORE_LEN (c.pos, datalen);
	      memcpy (c.pos, tokenp, datalen);
	      c.pos += datalen;
	      tokenp = NULL;
	    }
	}

      if (quoted)
	{
	  if (quoted_esc)
	    {
	      switch (*p)
		{
		case 'b': case 't': case 'v': case 'n': case 'f':
		case 'r': case '"': case '\'': case '\\':
		  quoted_esc = 0;
		  break;

		case '0': case '1': case '2': case '3': case '4':
		case '5': case '6': case '7':
		  if (!((n > 2)
                        && (p[1] >= '0') && (p[1] <= '7')
                        && (p[2] >= '0') && (p[2] <= '7')))
		    {
		      *erroff = p - buffer;
		      /* Invalid octal value.  */
		      err = GPG_ERR_SEXP_BAD_QUOTATION;
                      goto leave;
		    }
		  p += 2;
		  n -= 2;
		  quoted_esc = 0;
		  break;

		case 'x':
		  if (!((n > 2) && hexdigitp (p+1) && hexdigitp (p+2)))
		    {
		      *erroff = p - buffer;
		      /* Invalid hex value.  */
		      err = GPG_ERR_SEXP_BAD_QUOTATION;
                      goto leave;
		    }
		  p += 2;
		  n -= 2;
		  quoted_esc = 0;
		  break;

		case '\r':
		  /* ignore CR[,LF] */
		  if (n && (p[1] == '\n'))
		    {
		      p++;
		      n--;
		    }
		  quoted_esc = 0;
		  break;

		case '\n':
		  /* ignore LF[,CR] */
		  if (n && (p[1] == '\r'))
		    {
		      p++;
		      n--;
		    }
		  quoted_esc = 0;
		  break;

		default:
		  *erroff = p - buffer;
		  /* Invalid quoted string escape.  */
		  err = GPG_ERR_SEXP_BAD_QUOTATION;
                  goto leave;
		}
	    }
	  else if (*p == '\\')
	    quoted_esc = 1;
	  else if (*p == '\"')
	    {
	      /* Keep it easy - we know that the unquoted string will
		 never be larger. */
	      unsigned char *save;
	      size_t len;

	      quoted++; /* Skip leading quote.  */
	      MAKE_SPACE (p - quoted);
	      *c.pos++ = ST_DATA;
	      save = c.pos;
	      STORE_LEN (c.pos, 0); /* Will be fixed up later.  */
	      len = unquote_string (quoted, p - quoted, c.pos);
	      c.pos += len;
	      STORE_LEN (save, len);
	      quoted = NULL;
	    }
	}
      else if (hexfmt)
	{
	  if (isxdigit (*p))
	    hexcount++;
	  else if (*p == '#')
	    {
	      if ((hexcount & 1))
		{
		  *erroff = p - buffer;
		  err = GPG_ERR_SEXP_ODD_HEX_NUMBERS;
                  goto leave;
		}

	      datalen = hexcount / 2;
	      MAKE_SPACE (datalen);
	      *c.pos++ = ST_DATA;
	      STORE_LEN (c.pos, datalen);
	      for (hexfmt++; hexfmt < p; hexfmt++)
		{
                  int tmpc;

		  if (whitespacep (hexfmt))
		    continue;
		  tmpc = hextonibble (*(const unsigned char*)hexfmt);
                  for (hexfmt++; hexfmt < p && whitespacep (hexfmt); hexfmt++)
		    ;
                  if (hexfmt < p)
                    {
                      tmpc *= 16;
                      tmpc += hextonibble (*(const unsigned char*)hexfmt);
                    }
                  *c.pos++ = tmpc;
		}
	      hexfmt = NULL;
	    }
	  else if (!whitespacep (p))
	    {
	      *erroff = p - buffer;
	      err = GPG_ERR_SEXP_BAD_HEX_CHAR;
              goto leave;
	    }
	}
      else if (base64)
	{
	  if (*p == '|')
	    base64 = NULL;
	}
      else if (digptr)
	{
	  if (digitp (p))
	    ;
	  else if (*p == ':')
	    {
	      datalen = atoi (digptr); /* FIXME: check for overflow.  */
	      digptr = NULL;
	      if (datalen > n - 1)
		{
		  *erroff = p - buffer;
		  /* Buffer too short.  */
		  err = GPG_ERR_SEXP_STRING_TOO_LONG;
                  goto leave;
		}
	      /* Make a new list entry.  */
	      MAKE_SPACE (datalen);
	      *c.pos++ = ST_DATA;
	      STORE_LEN (c.pos, datalen);
	      memcpy (c.pos, p + 1, datalen);
	      c.pos += datalen;
	      n -= datalen;
	      p += datalen;
	    }
	  else if (*p == '\"')
	    {
	      digptr = NULL; /* We ignore the optional length.  */
	      quoted = p;
	      quoted_esc = 0;
	    }
	  else if (*p == '#')
	    {
	      digptr = NULL; /* We ignore the optional length.  */
	      hexfmt = p;
	      hexcount = 0;
	    }
	  else if (*p == '|')
	    {
	      digptr = NULL; /* We ignore the optional length.  */
	      base64 = p;
	    }
	  else
	    {
	      *erroff = p - buffer;
	      err = GPG_ERR_SEXP_INV_LEN_SPEC;
              goto leave;
	    }
	}
      else if (percent)
	{
	  if (*p == 'm' || *p == 'M')
	    {
	      /* Insert an MPI.  */
	      gcry_mpi_t m;
	      size_t nm = 0;
              int mpifmt = *p == 'm'? GCRYMPI_FMT_STD: GCRYMPI_FMT_USG;

	      ARG_NEXT (m, gcry_mpi_t);

              if (gcry_mpi_get_flag (m, GCRYMPI_FLAG_OPAQUE))
                {
                  void *mp;
                  unsigned int nbits;

                  mp = gcry_mpi_get_opaque (m, &nbits);
                  nm = (nbits+7)/8;
                  if (mp && nm)
                    {
                      MAKE_SPACE (nm);
                      if (!gcry_is_secure (c.sexp->d)
                          && gcry_mpi_get_flag (m, GCRYMPI_FLAG_SECURE))
                        {
                          /* We have to switch to secure allocation.  */
                          gcry_sexp_t newsexp;
                          byte *newhead;

                          newsexp = gcry_malloc_secure (sizeof *newsexp
                                                        + c.allocated - 1);
                          if (!newsexp)
                            {
                              err = gpg_err_code_from_errno (errno);
                              goto leave;
                            }
                          newhead = newsexp->d;
                          memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d));
                          c.pos = newhead + (c.pos - c.sexp->d);
                          gcry_free (c.sexp);
                          c.sexp = newsexp;
                        }

                      *c.pos++ = ST_DATA;
                      STORE_LEN (c.pos, nm);
                      memcpy (c.pos, mp, nm);
                      c.pos += nm;
                    }
                }
              else
                {
                  if (gcry_mpi_print (mpifmt, NULL, 0, &nm, m))
                    BUG ();

                  MAKE_SPACE (nm);
                  if (!gcry_is_secure (c.sexp->d)
                      && gcry_mpi_get_flag ( m, GCRYMPI_FLAG_SECURE))
                    {
                      /* We have to switch to secure allocation.  */
                      gcry_sexp_t newsexp;
                      byte *newhead;

                      newsexp = gcry_malloc_secure (sizeof *newsexp
                                                    + c.allocated - 1);
                      if (!newsexp)
                        {
                          err = gpg_err_code_from_errno (errno);
                          goto leave;
                        }
                      newhead = newsexp->d;
                      memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d));
                      c.pos = newhead + (c.pos - c.sexp->d);
                      gcry_free (c.sexp);
                      c.sexp = newsexp;
                    }

                  *c.pos++ = ST_DATA;
                  STORE_LEN (c.pos, nm);
                  if (gcry_mpi_print (mpifmt, c.pos, nm, &nm, m))
                    BUG ();
                  c.pos += nm;
                }
	    }
	  else if (*p == 's')
	    {
	      /* Insert an string.  */
	      const char *astr;
	      size_t alen;

	      ARG_NEXT (astr, const char *);
	      alen = strlen (astr);

	      MAKE_SPACE (alen);
	      *c.pos++ = ST_DATA;
	      STORE_LEN (c.pos, alen);
	      memcpy (c.pos, astr, alen);
	      c.pos += alen;
	    }
	  else if (*p == 'b')
	    {
	      /* Insert a memory buffer.  */
	      const char *astr;
	      int alen;

	      ARG_NEXT (alen, int);
	      ARG_NEXT (astr, const char *);

	      MAKE_SPACE (alen);
	      if (alen
                  && !gcry_is_secure (c.sexp->d)
		  && gcry_is_secure (astr))
              {
		  /* We have to switch to secure allocation.  */
		  gcry_sexp_t newsexp;
		  byte *newhead;

		  newsexp = gcry_malloc_secure (sizeof *newsexp
                                                + c.allocated - 1);
                  if (!newsexp)
                    {
                      err = gpg_err_code_from_errno (errno);
                      goto leave;
                    }
		  newhead = newsexp->d;
		  memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d));
		  c.pos = newhead + (c.pos - c.sexp->d);
		  gcry_free (c.sexp);
		  c.sexp = newsexp;
		}

	      *c.pos++ = ST_DATA;
	      STORE_LEN (c.pos, alen);
	      memcpy (c.pos, astr, alen);
	      c.pos += alen;
	    }
	  else if (*p == 'd')
	    {
	      /* Insert an integer as string.  */
	      int aint;
	      size_t alen;
	      char buf[35];

	      ARG_NEXT (aint, int);
	      sprintf (buf, "%d", aint);
	      alen = strlen (buf);
	      MAKE_SPACE (alen);
	      *c.pos++ = ST_DATA;
	      STORE_LEN (c.pos, alen);
	      memcpy (c.pos, buf, alen);
	      c.pos += alen;
	    }
	  else if (*p == 'u')
	    {
	      /* Insert an unsigned integer as string.  */
	      unsigned int aint;
	      size_t alen;
	      char buf[35];

	      ARG_NEXT (aint, unsigned int);
	      sprintf (buf, "%u", aint);
	      alen = strlen (buf);
	      MAKE_SPACE (alen);
	      *c.pos++ = ST_DATA;
	      STORE_LEN (c.pos, alen);
	      memcpy (c.pos, buf, alen);
	      c.pos += alen;
	    }
	  else if (*p == 'S')
	    {
	      /* Insert a gcry_sexp_t.  */
	      gcry_sexp_t asexp;
	      size_t alen, aoff;

	      ARG_NEXT (asexp, gcry_sexp_t);
              alen = get_internal_buffer (asexp, &aoff);
              if (alen)
                {
                  MAKE_SPACE (alen);
                  memcpy (c.pos, asexp->d + aoff, alen);
                  c.pos += alen;
                }
	    }
	  else
	    {
	      *erroff = p - buffer;
	      /* Invalid format specifier.  */
	      err = GPG_ERR_SEXP_INV_LEN_SPEC;
              goto leave;
	    }
	  percent = NULL;
	}
      else if (*p == '(')
	{
	  if (disphint)
	    {
	      *erroff = p - buffer;
	      /* Open display hint.  */
	      err = GPG_ERR_SEXP_UNMATCHED_DH;
              goto leave;
	    }
	  MAKE_SPACE (0);
	  *c.pos++ = ST_OPEN;
	  level++;
	}
      else if (*p == ')')
	{
	  /* Walk up.  */
	  if (disphint)
	    {
	      *erroff = p - buffer;
	      /* Open display hint.  */
	      err = GPG_ERR_SEXP_UNMATCHED_DH;
              goto leave;
	    }
	  MAKE_SPACE (0);
	  *c.pos++ = ST_CLOSE;
	  level--;
	}
      else if (*p == '\"')
	{
	  quoted = p;
	  quoted_esc = 0;
	}
      else if (*p == '#')
	{
	  hexfmt = p;
	  hexcount = 0;
	}
      else if (*p == '|')
	base64 = p;
      else if (*p == '[')
	{
	  if (disphint)
	    {
	      *erroff = p - buffer;
	      /* Open display hint.  */
	      err = GPG_ERR_SEXP_NESTED_DH;
              goto leave;
	    }
	  disphint = p;
	}
      else if (*p == ']')
	{
	  if (!disphint)
	    {
	      *erroff = p - buffer;
	      /* Open display hint.  */
	      err = GPG_ERR_SEXP_UNMATCHED_DH;
              goto leave;
	    }
	  disphint = NULL;
	}
      else if (digitp (p))
	{
	  if (*p == '0')
	    {
	      /* A length may not begin with zero.  */
	      *erroff = p - buffer;
	      err = GPG_ERR_SEXP_ZERO_PREFIX;
              goto leave;
	    }
	  digptr = p;
	}
      else if (strchr (tokenchars, *p))
	tokenp = p;
      else if (whitespacep (p))
	;
      else if (*p == '{')
	{
	  /* fixme: handle rescanning: we can do this by saving our
	     current state and start over at p+1 -- Hmmm. At this
	     point here we are in a well defined state, so we don't
	     need to save it.  Great.  */
	  *erroff = p - buffer;
	  err = GPG_ERR_SEXP_UNEXPECTED_PUNC;
          goto leave;
	}
      else if (strchr ("&\\", *p))
	{
	  /* Reserved punctuation.  */
	  *erroff = p - buffer;
	  err = GPG_ERR_SEXP_UNEXPECTED_PUNC;
          goto leave;
	}
      else if (argflag && (*p == '%'))
	percent = p;
      else
	{
	  /* Bad or unavailable.  */
	  *erroff = p - buffer;
	  err = GPG_ERR_SEXP_BAD_CHARACTER;
          goto leave;
	}
    }
  MAKE_SPACE (0);
  *c.pos++ = ST_STOP;

  if (level && !err)
    err = GPG_ERR_SEXP_UNMATCHED_PAREN;

 leave:
  if (err)
    {
      /* Error -> deallocate.  */
      if (c.sexp)
        {
          /* Extra paranoid wipe on error. */
          if (gcry_is_secure (c.sexp))
            wipememory (c.sexp, sizeof (struct gcry_sexp) + c.allocated - 1);
          gcry_free (c.sexp);
        }
      /* This might be expected by existing code...  */
      *retsexp = NULL;
    }
  else
    *retsexp = normalize (c.sexp);

  return gcry_error (err);
#undef MAKE_SPACE
#undef STORE_LEN
}
Esempio n. 13
0
/* Extract the CAR of the given list.  May return NULL for bad lists
   or memory failure.  */
gcry_sexp_t
gcry_sexp_nth (const gcry_sexp_t list, int number)
{
  const byte *p;
  DATALEN n;
  gcry_sexp_t newlist;
  byte *d;
  int level = 0;

  if (!list || list->d[0] != ST_OPEN)
    return NULL;
  p = list->d;

  while (number > 0)
    {
      p++;
      if (*p == ST_DATA)
        {
          memcpy (&n, ++p, sizeof n);
          p += sizeof n + n;
          p--;
          if (!level)
            number--;
	}
      else if (*p == ST_OPEN)
        {
          level++;
	}
      else if (*p == ST_CLOSE)
        {
          level--;
          if ( !level )
            number--;
	}
      else if (*p == ST_STOP)
        {
          return NULL;
	}
    }
  p++;

  if (*p == ST_DATA)
    {
      memcpy (&n, p, sizeof n);
      p += sizeof n;
      newlist = gcry_malloc (sizeof *newlist + n + 1);
      if (!newlist)
        return NULL;
      d = newlist->d;
      memcpy (d, p, n);
      d += n;
      *d++ = ST_STOP;
    }
  else if (*p == ST_OPEN)
    {
      const byte *head = p;

      level = 1;
      do {
        p++;
        if (*p == ST_DATA)
          {
            memcpy (&n, ++p, sizeof n);
            p += sizeof n + n;
            p--;
          }
        else if (*p == ST_OPEN)
          {
            level++;
          }
        else if (*p == ST_CLOSE)
          {
            level--;
          }
        else if (*p == ST_STOP)
          {
            BUG ();
          }
      } while (level);
      n = p + 1 - head;

      newlist = gcry_malloc (sizeof *newlist + n);
      if (!newlist)
        return NULL;
      d = newlist->d;
      memcpy (d, head, n);
      d += n;
      *d++ = ST_STOP;
    }
  else
    newlist = NULL;

  return normalize (newlist);
}
Esempio n. 14
0
/****************
 * Locate token in a list. The token must be the car of a sublist.
 * Returns: A new list with this sublist or NULL if not found.
 */
gcry_sexp_t
gcry_sexp_find_token( const gcry_sexp_t list, const char *tok, size_t toklen )
{
  const byte *p;
  DATALEN n;

  if ( !list )
    return NULL;

  if ( !toklen )
    toklen = strlen(tok);

  p = list->d;
  while ( *p != ST_STOP )
    {
      if ( *p == ST_OPEN && p[1] == ST_DATA )
        {
          const byte *head = p;

          p += 2;
          memcpy ( &n, p, sizeof n );
          p += sizeof n;
          if ( n == toklen && !memcmp( p, tok, toklen ) )
            { /* found it */
              gcry_sexp_t newlist;
              byte *d;
              int level = 1;

              /* Look for the end of the list.  */
              for ( p += n; level; p++ )
                {
                  if ( *p == ST_DATA )
                    {
			memcpy ( &n, ++p, sizeof n );
			p += sizeof n + n;
			p--; /* Compensate for later increment. */
		    }
                  else if ( *p == ST_OPEN )
                    {
                      level++;
		    }
                  else if ( *p == ST_CLOSE )
                    {
                      level--;
		    }
                  else if ( *p == ST_STOP )
                    {
                      BUG ();
		    }
		}
              n = p - head;

              newlist = gcry_malloc ( sizeof *newlist + n );
              if (!newlist)
                {
                  /* No way to return an error code, so we can only
                     return Not Found. */
                  return NULL;
                }
              d = newlist->d;
              memcpy ( d, head, n ); d += n;
              *d++ = ST_STOP;
              return normalize ( newlist );
	    }
          p += n;
	}
      else if ( *p == ST_DATA )
        {
          memcpy ( &n, ++p, sizeof n ); p += sizeof n;
          p += n;
	}
      else
        p++;
    }
  return NULL;
}
Esempio n. 15
0
/****************
 * Get the CDR
 */
gcry_sexp_t
gcry_sexp_cdr(const gcry_sexp_t list)
{
  const byte *p;
  const byte *head;
  DATALEN n;
  gcry_sexp_t newlist;
  byte *d;
  int level = 0;
  int skip = 1;

  if (!list || list->d[0] != ST_OPEN)
    return NULL;
  p = list->d;

  while (skip > 0)
    {
      p++;
      if (*p == ST_DATA)
        {
          memcpy ( &n, ++p, sizeof n );
          p += sizeof n + n;
          p--;
          if ( !level )
            skip--;
	}
      else if (*p == ST_OPEN)
        {
          level++;
	}
      else if (*p == ST_CLOSE)
        {
          level--;
          if ( !level )
            skip--;
	}
      else if (*p == ST_STOP)
        {
          return NULL;
	}
    }
  p++;

  head = p;
  level = 0;
  do {
    if (*p == ST_DATA)
      {
        memcpy ( &n, ++p, sizeof n );
        p += sizeof n + n;
        p--;
      }
    else if (*p == ST_OPEN)
      {
        level++;
      }
    else if (*p == ST_CLOSE)
      {
        level--;
      }
    else if (*p == ST_STOP)
      {
        return NULL;
      }
    p++;
  } while (level);
  n = p - head;

  newlist = gcry_malloc (sizeof *newlist + n + 2);
  if (!newlist)
    return NULL;
  d = newlist->d;
  *d++ = ST_OPEN;
  memcpy (d, head, n);
  d += n;
  *d++ = ST_CLOSE;
  *d++ = ST_STOP;

  return normalize (newlist);
}
Esempio n. 16
0
/* Run an integrity check on the binary.  Returns 0 on success.  */
static int
check_binary_integrity (void)
{
#ifdef ENABLE_HMAC_BINARY_CHECK
  gpg_error_t err;
  Dl_info info;
  unsigned char digest[32];
  int dlen;
  char *fname = NULL;
  const char key[] = "What am I, a doctor or a moonshuttle conductor?";

  if (!dladdr ("gcry_check_version", &info))
    err = gpg_error_from_syserror ();
  else
    {
      dlen = _gcry_hmac256_file (digest, sizeof digest, info.dli_fname,
                                 key, strlen (key));
      if (dlen < 0)
        err = gpg_error_from_syserror ();
      else if (dlen != 32)
        err = gpg_error (GPG_ERR_INTERNAL);
      else
        {
          fname = gcry_malloc (strlen (info.dli_fname) + 1 + 5 + 1 );
          if (!fname)
            err = gpg_error_from_syserror ();
          else
            {
              FILE *fp;
              char *p;

              /* Prefix the basename with a dot.  */
              strcpy (fname, info.dli_fname);
              p = strrchr (fname, '/');
              if (p)
                p++;
              else
                p = fname;
              memmove (p+1, p, strlen (p)+1);
              *p = '.';
              strcat (fname, ".hmac");

              /* Open the file.  */
              fp = fopen (fname, "r");
              if (!fp)
                err = gpg_error_from_syserror ();
              else
                {
                  /* A buffer of 64 bytes plus one for a LF and one to
                     detect garbage.  */
                  unsigned char buffer[64+1+1];
                  const unsigned char *s;
                  int n;

                  /* The HMAC files consists of lowercase hex digits
                     only with an optional trailing linefeed.  Fail if
                     there is any garbage.  */
                  err = gpg_error (GPG_ERR_SELFTEST_FAILED);
                  n = fread (buffer, 1, sizeof buffer, fp);
                  if (n == 64 || (n == 65 && buffer[64] == '\n'))
                    {
                      buffer[64] = 0;
                      for (n=0, s= buffer;
                           n < 32 && loxdigit_p (s) && loxdigit_p (s+1);
                           n++, s += 2)
                        buffer[n] = loxtoi_2 (s);
                      if ( n == 32 && !memcmp (digest, buffer, 32) )
                        err = 0;
                    }
                  fclose (fp);
                }
            }
        }
    }
  reporter ("binary", 0, fname, err? gpg_strerror (err):NULL);
#ifdef HAVE_SYSLOG
  if (err)
    syslog (LOG_USER|LOG_ERR, "Libgcrypt error: "
            "integrity check using `%s' failed: %s",
            fname? fname:"[?]", gpg_strerror (err));
#endif /*HAVE_SYSLOG*/
  gcry_free (fname);
  return !!err;
#else
  return 0;
#endif
}
Esempio n. 17
0
gboolean
egg_hkdf_perform (const gchar *hash_algo, gconstpointer input, gsize n_input,
                  gconstpointer salt, gsize n_salt, gconstpointer info,
                  gsize n_info, gpointer output, gsize n_output)
{
	gpointer alloc = NULL;
	gpointer buffer = NULL;
	gcry_md_hd_t md1, md2;
	guint hash_len;
	gint i;
	gint flags, algo;
	gsize step, n_buffer;
	guchar *at;
	gcry_error_t gcry;

	algo = gcry_md_map_name (hash_algo);
	g_return_val_if_fail (algo != 0, FALSE);

	hash_len = gcry_md_get_algo_dlen (algo);
	g_return_val_if_fail (hash_len != 0, FALSE);
	g_return_val_if_fail (n_output <= 255 * hash_len, FALSE);

	/* Buffer we need to for intermediate stuff */
	if (gcry_is_secure (input)) {
		flags = GCRY_MD_FLAG_SECURE;
		buffer = gcry_malloc_secure (hash_len);
	} else {
		flags = 0;
		buffer = gcry_malloc (hash_len);
	}

	g_return_val_if_fail (buffer, FALSE);
	n_buffer = 0;

	/* Salt defaults to hash_len zeros */
	if (!salt) {
		salt = alloc = g_malloc0 (hash_len);
		n_salt = hash_len;
	}

	/* Step 1: Extract */
	gcry = gcry_md_open (&md1, algo, GCRY_MD_FLAG_HMAC | flags);
	g_return_val_if_fail (gcry == 0, FALSE);
	gcry = gcry_md_setkey (md1, salt, n_salt);
	g_return_val_if_fail (gcry == 0, FALSE);
	gcry_md_write (md1, input, n_input);

	/* Step 2: Expand */
	gcry = gcry_md_open (&md2, algo, GCRY_MD_FLAG_HMAC | flags);
	g_return_val_if_fail (gcry == 0, FALSE);
	gcry = gcry_md_setkey (md2, gcry_md_read (md1, algo), hash_len);
	g_return_val_if_fail (gcry == 0, FALSE);
	gcry_md_close (md1);

	at = output;
	for (i = 1; i < 256; ++i) {
		gcry_md_reset (md2);
		gcry_md_write (md2, buffer, n_buffer);
		gcry_md_write (md2, info, n_info);
		gcry_md_putc (md2, i);

		n_buffer = hash_len;
		memcpy (buffer, gcry_md_read (md2, algo), n_buffer);

		step = MIN (n_buffer, n_output);
		memcpy (at, buffer, step);
		n_output -= step;
		at += step;

		if (!n_output)
			break;
	}

	g_free (alloc);
	gcry_free (buffer);
	return TRUE;
}
Esempio n. 18
0
/*
 * Generate a deterministic secret exponent K less than DSA_Q.  H1 is
 * the to be signed digest with a length of HLEN bytes.  HALGO is the
 * algorithm used to create the hash.  On success the value for K is
 * stored at R_K.
 */
gpg_err_code_t
_gcry_dsa_gen_rfc6979_k (gcry_mpi_t *r_k,
                         gcry_mpi_t dsa_q, gcry_mpi_t dsa_x,
                         const unsigned char *h1, unsigned int hlen,
                         int halgo, unsigned int extraloops)
{
  gpg_err_code_t rc;
  unsigned char *V = NULL;
  unsigned char *K = NULL;
  unsigned char *x_buf = NULL;
  unsigned char *h1_buf = NULL;
  gcry_md_hd_t hd = NULL;
  unsigned char *t = NULL;
  gcry_mpi_t k = NULL;
  unsigned int tbits, qbits;
  int i;

  qbits = mpi_get_nbits (dsa_q);

  if (!qbits || !h1 || !hlen)
    return GPG_ERR_EINVAL;

  if (gcry_md_get_algo_dlen (halgo) != hlen)
    return GPG_ERR_DIGEST_ALGO;

  /* Step b:  V = 0x01 0x01 0x01 ... 0x01 */
  V = gcry_malloc (hlen);
  if (!V)
    {
      rc = gpg_err_code_from_syserror ();
      goto leave;
    }
  for (i=0; i < hlen; i++)
    V[i] = 1;

  /* Step c:  K = 0x00 0x00 0x00 ... 0x00 */
  K = gcry_calloc (1, hlen);
  if (!K)
    {
      rc = gpg_err_code_from_syserror ();
      goto leave;
    }

  rc = int2octets (&x_buf, dsa_x, (qbits+7)/8);
  if (rc)
    goto leave;

  rc = bits2octets (&h1_buf, h1, hlen*8, dsa_q, qbits);
  if (rc)
    goto leave;

  /* Create a handle to compute the HMACs.  */
  rc = gpg_err_code (gcry_md_open (&hd, halgo,
                                   (GCRY_MD_FLAG_SECURE | GCRY_MD_FLAG_HMAC)));
  if (rc)
    goto leave;

  /* Step d:  K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) */
  rc = gpg_err_code (gcry_md_setkey (hd, K, hlen));
  if (rc)
    goto leave;
  gcry_md_write (hd, V, hlen);
  gcry_md_write (hd, "", 1);
  gcry_md_write (hd, x_buf, (qbits+7)/8);
  gcry_md_write (hd, h1_buf, (qbits+7)/8);
  memcpy (K, gcry_md_read (hd, 0), hlen);

  /* Step e:  V = HMAC_K(V) */
  rc = gpg_err_code (gcry_md_setkey (hd, K, hlen));
  if (rc)
    goto leave;
  gcry_md_write (hd, V, hlen);
  memcpy (V, gcry_md_read (hd, 0), hlen);

  /* Step f:  K = HMAC_K(V || 0x01 || int2octets(x) || bits2octets(h1) */
  rc = gpg_err_code (gcry_md_setkey (hd, K, hlen));
  if (rc)
    goto leave;
  gcry_md_write (hd, V, hlen);
  gcry_md_write (hd, "\x01", 1);
  gcry_md_write (hd, x_buf, (qbits+7)/8);
  gcry_md_write (hd, h1_buf, (qbits+7)/8);
  memcpy (K, gcry_md_read (hd, 0), hlen);

  /* Step g:  V = HMAC_K(V) */
  rc = gpg_err_code (gcry_md_setkey (hd, K, hlen));
  if (rc)
    goto leave;
  gcry_md_write (hd, V, hlen);
  memcpy (V, gcry_md_read (hd, 0), hlen);

  /* Step h. */
  t = gcry_malloc ((qbits+7)/8+hlen);
  if (!t)
    {
      rc = gpg_err_code_from_syserror ();
      goto leave;
    }

 again:
  for (tbits = 0; tbits < qbits;)
    {
      /* V = HMAC_K(V) */
      rc = gpg_err_code (gcry_md_setkey (hd, K, hlen));
      if (rc)
        goto leave;
      gcry_md_write (hd, V, hlen);
      memcpy (V, gcry_md_read (hd, 0), hlen);

      /* T = T || V */
      memcpy (t+(tbits+7)/8, V, hlen);
      tbits += 8*hlen;
    }

  /* k = bits2int (T) */
  mpi_free (k);
  k = NULL;
  rc = gpg_err_code (gcry_mpi_scan (&k, GCRYMPI_FMT_USG, t, (tbits+7)/8, NULL));
  if (rc)
    goto leave;
  if (tbits > qbits)
    gcry_mpi_rshift (k, k, tbits - qbits);

  /* Check: k < q and k > 1 */
  if (!(mpi_cmp (k, dsa_q) < 0 && mpi_cmp_ui (k, 0) > 0))
    {
      /* K = HMAC_K(V || 0x00) */
      rc = gpg_err_code (gcry_md_setkey (hd, K, hlen));
      if (rc)
        goto leave;
      gcry_md_write (hd, V, hlen);
      gcry_md_write (hd, "", 1);
      memcpy (K, gcry_md_read (hd, 0), hlen);

      /* V = HMAC_K(V) */
      rc = gpg_err_code (gcry_md_setkey (hd, K, hlen));
      if (rc)
        goto leave;
      gcry_md_write (hd, V, hlen);
      memcpy (V, gcry_md_read (hd, 0), hlen);

      goto again;
    }

  /* The caller may have requested that we introduce some extra loops.
     This is for example useful if the caller wants another value for
     K because the last returned one yielded an R of 0.  Becuase this
     is very unlikely we implement it in a straightforward way.  */
  if (extraloops)
    {
      extraloops--;

      /* K = HMAC_K(V || 0x00) */
      rc = gpg_err_code (gcry_md_setkey (hd, K, hlen));
      if (rc)
        goto leave;
      gcry_md_write (hd, V, hlen);
      gcry_md_write (hd, "", 1);
      memcpy (K, gcry_md_read (hd, 0), hlen);

      /* V = HMAC_K(V) */
      rc = gpg_err_code (gcry_md_setkey (hd, K, hlen));
      if (rc)
        goto leave;
      gcry_md_write (hd, V, hlen);
      memcpy (V, gcry_md_read (hd, 0), hlen);

      goto again;
    }

  /* log_mpidump ("  k", k); */

 leave:
  gcry_free (t);
  gcry_md_close (hd);
  gcry_free (h1_buf);
  gcry_free (x_buf);
  gcry_free (K);
  gcry_free (V);

  if (rc)
    mpi_free (k);
  else
    *r_k = k;
  return rc;
}
Esempio n. 19
0
static void
back_and_forth_one (int testno, const char *buffer, size_t length)
{
  gcry_error_t rc;
  gcry_sexp_t se, se1;
  unsigned char *canon;
  size_t canonlen;  /* Including the hidden nul suffix.  */
  size_t n, n1;
  char *p1;

  rc = gcry_sexp_new (&se, buffer, length, 1);
  if (rc)
    {
      fail ("baf %d: gcry_sexp_new failed: %s\n", testno, gpg_strerror (rc));
      return;
    }
  n1 = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, NULL, 0);
  if (!n1)
    {
      fail ("baf %d: get required length for canon failed\n", testno);
      return;
    }
  p1 = gcry_xmalloc (n1);
  n = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, p1, n1);
  if (n1 != n+1) /* sprints adds an extra 0 but does not return it. */
    {
      fail ("baf %d: length mismatch for canon\n", testno);
      return;
    }
  canonlen = n1;
  canon = gcry_malloc (canonlen);
  memcpy (canon, p1, canonlen);
  rc = gcry_sexp_create (&se1, p1, n, 0, gcry_free);
  if (rc)
    {
      fail ("baf %d: gcry_sexp_create failed: %s\n",
            testno, gpg_strerror (rc));
      return;
    }
  gcry_sexp_release (se1);

  /* Again but with memory checking. */
  p1 = gcry_xmalloc (n1+2);
  *p1 = '\x55';
  p1[n1+1] = '\xaa';
  n = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, p1+1, n1);
  if (n1 != n+1) /* sprints adds an extra 0 but does not return it */
    {
      fail ("baf %d: length mismatch for canon\n", testno);
      return;
    }
  if (*p1 != '\x55' || p1[n1+1] != '\xaa')
    fail ("baf %d: memory corrupted (1)\n", testno);
  rc = gcry_sexp_create (&se1, p1+1, n, 0, NULL);
  if (rc)
    {
      fail ("baf %d: gcry_sexp_create failed: %s\n",
            testno, gpg_strerror (rc));
      return;
    }
  if (*p1 != '\x55' || p1[n1+1] != '\xaa')
    fail ("baf %d: memory corrupted (2)\n", testno);
  gcry_sexp_release (se1);
  if (*p1 != '\x55' || p1[n1+1] != '\xaa')
    fail ("baf %d: memory corrupted (3)\n", testno);
  gcry_free (p1);

  /* Check converting to advanced format.  */
  n1 = gcry_sexp_sprint (se, GCRYSEXP_FMT_ADVANCED, NULL, 0);
  if (!n1)
    {
      fail ("baf %d: get required length for advanced failed\n", testno);
      return;
    }
  p1 = gcry_xmalloc (n1);
  n = gcry_sexp_sprint (se, GCRYSEXP_FMT_ADVANCED, p1, n1);
  if (n1 != n+1) /* sprints adds an extra 0 but does not return it */
    {
      fail ("baf %d: length mismatch for advanced\n", testno);
      return;
    }
  rc = gcry_sexp_create (&se1, p1, n, 0, gcry_free);
  if (rc)
    {
      fail ("baf %d: gcry_sexp_create failed: %s\n",
            testno, gpg_strerror (rc));
      return;
    }
  if (compare_to_canon (se1, canon, canonlen))
    {
      fail ("baf %d: converting to advanced failed: %s\n",
            testno, gpg_strerror (rc));
      return;
    }
  gcry_sexp_release (se1);


  /* FIXME: we need a lot more tests */

  gcry_sexp_release (se);
  xfree (canon);
}
Esempio n. 20
0
gcry_error_t
gcry_pbkdf2 (int PRF, const char *P, size_t Plen, const char *S,
	     size_t Slen, unsigned int c, unsigned int dkLen, char *DK)
{
  gcry_md_hd_t prf;
  gcry_error_t rc;
  char *U;
  unsigned int u;
  unsigned int hLen;
  unsigned int l;
  unsigned int r;
  unsigned char *p;
  unsigned int i;
  unsigned int k;

  hLen = gcry_md_get_algo_dlen (PRF);
  if (hLen == 0)
    return GPG_ERR_UNSUPPORTED_ALGORITHM;

  if (c == 0)
    return GPG_ERR_INV_ARG;

  if (dkLen == 0)
    return GPG_ERR_TOO_SHORT;

  /*
   *
   *  Steps:
   *
   *     1. If dkLen > (2^32 - 1) * hLen, output "derived key too long" and
   *        stop.
   */

  if (dkLen > 4294967295U)
    return GPG_ERR_TOO_LARGE;

  /*
   *     2. Let l be the number of hLen-octet blocks in the derived key,
   *        rounding up, and let r be the number of octets in the last
   *        block:
   *
   *                  l = CEIL (dkLen / hLen) ,
   *                  r = dkLen - (l - 1) * hLen .
   *
   *        Here, CEIL (x) is the "ceiling" function, i.e. the smallest
   *        integer greater than, or equal to, x.
   */

  l = dkLen / hLen;
  if (dkLen % hLen)
    l++;
  r = dkLen - (l - 1) * hLen;

  /*
   *     3. For each block of the derived key apply the function F defined
   *        below to the password P, the salt S, the iteration count c, and
   *        the block index to compute the block:
   *
   *                  T_1 = F (P, S, c, 1) ,
   *                  T_2 = F (P, S, c, 2) ,
   *                  ...
   *                  T_l = F (P, S, c, l) ,
   *
   *        where the function F is defined as the exclusive-or sum of the
   *        first c iterates of the underlying pseudorandom function PRF
   *        applied to the password P and the concatenation of the salt S
   *        and the block index i:
   *
   *                  F (P, S, c, i) = U_1 \xor U_2 \xor ... \xor U_c
   *
   *        where
   *
   *                  U_1 = PRF (P, S || INT (i)) ,
   *                  U_2 = PRF (P, U_1) ,
   *                  ...
   *                  U_c = PRF (P, U_{c-1}) .
   *
   *        Here, INT (i) is a four-octet encoding of the integer i, most
   *        significant octet first.
   *
   *     4. Concatenate the blocks and extract the first dkLen octets to
   *        produce a derived key DK:
   *
   *                  DK = T_1 || T_2 ||  ...  || T_l<0..r-1>
   *
   *     5. Output the derived key DK.
   *
   *  Note. The construction of the function F follows a "belt-and-
   *  suspenders" approach. The iterates U_i are computed recursively to
   *  remove a degree of parallelism from an opponent; they are exclusive-
   *  ored together to reduce concerns about the recursion degenerating
   *  into a small set of values.
   *
   */
  rc = gcry_md_open (&prf, PRF, GCRY_MD_FLAG_HMAC | GCRY_MD_FLAG_SECURE);
  if (rc != GPG_ERR_NO_ERROR)
    return rc;

  U = (char*)gcry_malloc(hLen);
  if (!U)
    {
      rc = GPG_ERR_ENOMEM;
      goto done;
    }

  for (i = 1; i <= l; i++)
    {
      memset(DK + (i - 1) * hLen, 0, i == l ? r : hLen);

      for (u = 1; u <= c; u++)
       {
         gcry_md_reset (prf);

         rc = gcry_md_setkey (prf, P, Plen);
         if (rc != GPG_ERR_NO_ERROR) {
           goto done;
	 }
         if (u == 1)
           {
             char tmp[4];
             gcry_md_write (prf, S, Slen);
             tmp[0] = (i & 0xff000000) >> 24;
             tmp[1] = (i & 0x00ff0000) >> 16;
             tmp[2] = (i & 0x0000ff00) >> 8;
             tmp[3] = (i & 0x000000ff) >> 0;
             gcry_md_write (prf, tmp, 4);
           }
         else
           gcry_md_write (prf, U, hLen);

         p = gcry_md_read (prf, PRF);
         if (p == NULL)
           {
             rc = GPG_ERR_CONFIGURATION;
             goto done;
          }

         memcpy (U, p, hLen);
        for (k = 0; k < (i == l ? r : hLen); k++)
           DK[(i - 1) * hLen + k] ^= U[k];
       }
Esempio n. 21
0
gcry_err_code_t
_gcry_kdf_scrypt (const unsigned char *passwd, size_t passwdlen,
                  int algo, int subalgo,
                  const unsigned char *salt, size_t saltlen,
                  unsigned long iterations,
                  size_t dkLen, unsigned char *DK)
{
  u64 N = subalgo;    /* CPU/memory cost paramter.  */
  u32 r;              /* Block size.  */
  u32 p = iterations; /* Parallelization parameter.  */

  gpg_err_code_t ec;
  u32 i;
  unsigned char *B = NULL;
  unsigned char *tmp1 = NULL;
  unsigned char *tmp2 = NULL;
  size_t r128;
  size_t nbytes;

  if (subalgo < 1 || !iterations)
    return GPG_ERR_INV_VALUE;

  if (algo == GCRY_KDF_SCRYPT)
    r = 8;
  else if (algo == 41) /* Hack to allow the use of all test vectors.  */
    r = 1;
  else
    return GPG_ERR_UNKNOWN_ALGORITHM;

  r128 = r * 128;
  if (r128 / 128 != r)
    return GPG_ERR_ENOMEM;

  nbytes = p * r128;
  if (r128 && nbytes / r128 != p)
    return GPG_ERR_ENOMEM;

  nbytes = N * r128;
  if (r128 && nbytes / r128 != N)
    return GPG_ERR_ENOMEM;

  nbytes = 64 + r128;
  if (nbytes < r128)
    return GPG_ERR_ENOMEM;

  B = gcry_malloc (p * r128);
  if (!B)
    {
      ec = gpg_err_code_from_syserror ();
      goto leave;
    }

  tmp1 = gcry_malloc (N * r128);
  if (!tmp1)
    {
      ec = gpg_err_code_from_syserror ();
      goto leave;
    }

  tmp2 = gcry_malloc (64 + r128);
  if (!tmp2)
    {
      ec = gpg_err_code_from_syserror ();
      goto leave;
    }

  ec = _gcry_kdf_pkdf2 (passwd, passwdlen, GCRY_MD_SHA256, salt, saltlen,
                        1 /* iterations */, p * r128, B);

  for (i = 0; !ec && i < p; i++)
    _scryptROMix (r, &B[i * r128], N, tmp1, tmp2);

  for (i = 0; !ec && i < p; i++)
    ec = _gcry_kdf_pkdf2 (passwd, passwdlen, GCRY_MD_SHA256, B, p * r128,
                          1 /* iterations */, dkLen, DK);

 leave:
  gcry_free (tmp2);
  gcry_free (tmp1);
  gcry_free (B);

  return ec;
}