예제 #1
0
파일: validate.c 프로젝트: 0ndorio/gnupg
/* Return the public key algorithm id from the S-expression PKEY.
   FIXME: libgcrypt should provide such a function.  Note that this
   implementation uses the names as used by libksba.  */
static int
pk_algo_from_sexp (gcry_sexp_t pkey)
{
  gcry_sexp_t l1, l2;
  const char *name;
  size_t n;
  int algo;

  l1 = gcry_sexp_find_token (pkey, "public-key", 0);
  if (!l1)
    return 0; /* Not found.  */
  l2 = gcry_sexp_cadr (l1);
  gcry_sexp_release (l1);

  name = gcry_sexp_nth_data (l2, 0, &n);
  if (!name)
    algo = 0; /* Not found. */
  else if (n==3 && !memcmp (name, "rsa", 3))
    algo = GCRY_PK_RSA;
  else if (n==3 && !memcmp (name, "dsa", 3))
    algo = GCRY_PK_DSA;
  else if (n==13 && !memcmp (name, "ambiguous-rsa", 13))
    algo = GCRY_PK_RSA;
  else
    algo = 0;
  gcry_sexp_release (l2);
  return algo;
}
예제 #2
0
파일: certcheck.c 프로젝트: 0ndorio/gnupg
/* Return the number of bits of the Q parameter from the DSA key
   KEY.  */
static unsigned int
get_dsa_qbits (gcry_sexp_t key)
{
  gcry_sexp_t l1, l2;
  gcry_mpi_t q;
  unsigned int nbits;

  l1 = gcry_sexp_find_token (key, "public-key", 0);
  if (!l1)
    return 0; /* Does not contain a key object.  */
  l2 = gcry_sexp_cadr (l1);
  gcry_sexp_release  (l1);
  l1 = gcry_sexp_find_token (l2, "q", 1);
  gcry_sexp_release (l2);
  if (!l1)
    return 0; /* Invalid object.  */
  q = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
  gcry_sexp_release (l1);
  if (!q)
    return 0; /* Missing value.  */
  nbits = gcry_mpi_get_nbits (q);
  gcry_mpi_release (q);

  return nbits;
}
예제 #3
0
파일: certcheck.c 프로젝트: 0ndorio/gnupg
/* Return the public key algorithm id from the S-expression PKEY.
   FIXME: libgcrypt should provide such a function.  Note that this
   implementation uses the names as used by libksba.  */
static int
pk_algo_from_sexp (gcry_sexp_t pkey)
{
  gcry_sexp_t l1, l2;
  const char *name;
  size_t n;
  int algo;

  l1 = gcry_sexp_find_token (pkey, "public-key", 0);
  if (!l1)
    return 0; /* Not found.  */
  l2 = gcry_sexp_cadr (l1);
  gcry_sexp_release (l1);

  name = gcry_sexp_nth_data (l2, 0, &n);
  if (!name)
    algo = 0; /* Not found. */
  else if (n==3 && !memcmp (name, "rsa", 3))
    algo = GCRY_PK_RSA;
  else if (n==3 && !memcmp (name, "dsa", 3))
    algo = GCRY_PK_DSA;
  /* Because this function is called only for verification we can
     assume that ECC actually means ECDSA.  */
  else if (n==3 && !memcmp (name, "ecc", 3))
    algo = GCRY_PK_ECDSA;
  else if (n==13 && !memcmp (name, "ambiguous-rsa", 13))
    algo = GCRY_PK_RSA;
  else
    algo = 0;
  gcry_sexp_release (l2);
  return algo;
}
예제 #4
0
/*
  Create a public key pair and return it in r_key.
  How the key is created depends on s_parms:
  (genkey
   (algo
     (parameter_name_1 ....)
      ....
     (parameter_name_n ....)
  ))
  The key is returned in a format depending on the
  algorithm. Both, private and secret keys are returned
  and optionally some additional informatin.
  For elgamal we return this structure:
  (key-data
   (public-key
     (elg
 	(p <mpi>)
 	(g <mpi>)
 	(y <mpi>)
     )
   )
   (private-key
     (elg
 	(p <mpi>)
 	(g <mpi>)
 	(y <mpi>)
 	(x <mpi>)
     )
   )
   (misc-key-info
      (pm1-factors n1 n2 ... nn)
   ))
 */
gcry_error_t
gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
{
  gcry_pk_spec_t *spec = NULL;
  gcry_sexp_t list = NULL;
  gcry_sexp_t l2 = NULL;
  char *name = NULL;
  gcry_err_code_t rc;

  *r_key = NULL;

  list = gcry_sexp_find_token (s_parms, "genkey", 0);
  if (!list)
    {
      rc = GPG_ERR_INV_OBJ; /* Does not contain genkey data. */
      goto leave;
    }

  l2 = gcry_sexp_cadr (list);
  gcry_sexp_release (list);
  list = l2;
  l2 = NULL;
  if (! list)
    {
      rc = GPG_ERR_NO_OBJ; /* No cdr for the genkey. */
      goto leave;
    }

  name = _gcry_sexp_nth_string (list, 0);
  if (!name)
    {
      rc = GPG_ERR_INV_OBJ; /* Algo string missing.  */
      goto leave;
    }

  spec = spec_from_name (name);
  gcry_free (name);
  name = NULL;
  if (!spec)
    {
      rc = GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm.  */
      goto leave;
    }

  if (spec->generate)
    rc = spec->generate (list, r_key);
  else
    rc = GPG_ERR_NOT_IMPLEMENTED;

 leave:
  gcry_sexp_release (list);
  gcry_free (name);
  gcry_sexp_release (l2);

  return gcry_error (rc);
}
예제 #5
0
/* Return the PK algorithm used by CERT as well as the length in bits
   of the public key at NBITS. */
int
gpgsm_get_key_algo_info (ksba_cert_t cert, unsigned int *nbits)
{
  gcry_sexp_t s_pkey;
  int rc;
  ksba_sexp_t p;
  size_t n;
  gcry_sexp_t l1, l2;
  const char *name;
  char namebuf[128];

  if (nbits)
    *nbits = 0;

  p = ksba_cert_get_public_key (cert);
  if (!p)
    return 0;
  n = gcry_sexp_canon_len (p, 0, NULL, NULL);
  if (!n)
    {
      xfree (p);
      return 0;
    }
  rc = gcry_sexp_sscan (&s_pkey, NULL, (char *)p, n);
  xfree (p);
  if (rc)
    return 0;

  if (nbits)
    *nbits = gcry_pk_get_nbits (s_pkey);

  /* Breaking the algorithm out of the S-exp is a bit of a challenge ... */
  l1 = gcry_sexp_find_token (s_pkey, "public-key", 0);
  if (!l1)
    {
      gcry_sexp_release (s_pkey);
      return 0;
    }
  l2 = gcry_sexp_cadr (l1);
  gcry_sexp_release (l1);
  l1 = l2;
  name = gcry_sexp_nth_data (l1, 0, &n);
  if (name)
    {
      if (n > sizeof namebuf -1)
        n = sizeof namebuf -1;
      memcpy (namebuf, name, n);
      namebuf[n] = 0;
    }
  else
    *namebuf = 0;
  gcry_sexp_release (l1);
  gcry_sexp_release (s_pkey);
  return gcry_pk_map_name (namebuf);
}
예제 #6
0
파일: crypto_rsa.c 프로젝트: tg-x/gnunet
/**
 * Extract values from an S-expression.
 *
 * @param array where to store the result(s)
 * @param sexp S-expression to parse
 * @param topname top-level name in the S-expression that is of interest
 * @param elems names of the elements to extract
 * @return 0 on success
 */
static int
key_from_sexp (gcry_mpi_t *array,
               gcry_sexp_t sexp,
               const char *topname,
               const char *elems)
{
  gcry_sexp_t list;
  gcry_sexp_t l2;
  const char *s;
  unsigned int i;
  unsigned int idx;

  if (! (list = gcry_sexp_find_token (sexp, topname, 0)))
    return 1;
  l2 = gcry_sexp_cadr (list);
  gcry_sexp_release (list);
  list = l2;
  if (! list)
    return 2;
  idx = 0;
  for (s = elems; *s; s++, idx++)
  {
    if (! (l2 = gcry_sexp_find_token (list, s, 1)))
    {
      for (i = 0; i < idx; i++)
      {
        gcry_free (array[i]);
        array[i] = NULL;
      }
      gcry_sexp_release (list);
      return 3;                 /* required parameter not found */
    }
    array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
    gcry_sexp_release (l2);
    if (! array[idx])
    {
      for (i = 0; i < idx; i++)
      {
        gcry_free (array[i]);
        array[i] = NULL;
      }
      gcry_sexp_release (list);
      return 4;                 /* required parameter is invalid */
    }
  }
  gcry_sexp_release (list);
  return 0;
}
예제 #7
0
/* Given the s-expression SEXP with the first element be either
 * "private-key" or "public-key" return the spec structure for it.  We
 * look through the list to find a list beginning with "private-key"
 * or "public-key" - the first one found is used.  If WANT_PRIVATE is
 * set the function will only succeed if a private key has been given.
 * On success the spec is stored at R_SPEC.  On error NULL is stored
 * at R_SPEC and an error code returned.  If R_PARMS is not NULL and
 * the fucntion returns success, the parameter list below
 * "private-key" or "public-key" is stored there and the caller must
 * call gcry_sexp_release on it.
 */
static gcry_err_code_t
spec_from_sexp (gcry_sexp_t sexp, int want_private,
                gcry_pk_spec_t **r_spec, gcry_sexp_t *r_parms)
{
  gcry_sexp_t list, l2;
  char *name;
  gcry_pk_spec_t *spec;

  *r_spec = NULL;
  if (r_parms)
    *r_parms = NULL;

  /* Check that the first element is valid.  If we are looking for a
     public key but a private key was supplied, we allow the use of
     the private key anyway.  The rationale for this is that the
     private key is a superset of the public key.  */
  list = gcry_sexp_find_token (sexp,
                               want_private? "private-key":"public-key", 0);
  if (!list && !want_private)
    list = gcry_sexp_find_token (sexp, "private-key", 0);
  if (!list)
    return GPG_ERR_INV_OBJ; /* Does not contain a key object.  */

  l2 = gcry_sexp_cadr (list);
  gcry_sexp_release (list);
  list = l2;
  name = _gcry_sexp_nth_string (list, 0);
  if (!name)
    {
      gcry_sexp_release ( list );
      return GPG_ERR_INV_OBJ;      /* Invalid structure of object. */
    }
  spec = spec_from_name (name);
  gcry_free (name);
  if (!spec)
    {
      gcry_sexp_release (list);
      return GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */
    }
  *r_spec = spec;
  if (r_parms)
    *r_parms = list;
  else
    gcry_sexp_release (list);
  return 0;
}
예제 #8
0
/* Return the public key for the keygrip GRIP.  The result is stored
   at RESULT.  This function extracts the public key from the private
   key database.  On failure an error code is returned and NULL stored
   at RESULT. */
gpg_error_t
agent_public_key_from_file (ctrl_t ctrl,
                            const unsigned char *grip,
                            gcry_sexp_t *result)
{
  int i, idx, rc;
  gcry_sexp_t s_skey;
  const char *algoname;
  gcry_sexp_t uri_sexp, comment_sexp;
  const char *uri, *comment;
  size_t uri_length, comment_length;
  char *format, *p;
  void *args[4+2+2+1]; /* Size is max. # of elements + 2 for uri + 2
                           for comment + end-of-list.  */
  int argidx;
  gcry_sexp_t list, l2;
  const char *name;
  const char *s;
  size_t n;
  const char *elems;
  gcry_mpi_t *array;

  (void)ctrl;

  *result = NULL;

  rc = read_key_file (grip, &s_skey);
  if (rc)
    return rc;

  list = gcry_sexp_find_token (s_skey, "shadowed-private-key", 0 );
  if (!list)
    list = gcry_sexp_find_token (s_skey, "protected-private-key", 0 );
  if (!list)
    list = gcry_sexp_find_token (s_skey, "private-key", 0 );
  if (!list)
    {
      log_error ("invalid private key format\n");
      gcry_sexp_release (s_skey);
      return gpg_error (GPG_ERR_BAD_SECKEY);
    }

  l2 = gcry_sexp_cadr (list);
  gcry_sexp_release (list);
  list = l2;
  name = gcry_sexp_nth_data (list, 0, &n);
  if (n==3 && !memcmp (name, "rsa", 3))
    {
      algoname = "rsa";
      elems = "ne";
    }
  else if (n==3 && !memcmp (name, "dsa", 3))
    {
      algoname = "dsa";
      elems = "pqgy";
    }
  else if (n==3 && !memcmp (name, "elg", 3))
    {
      algoname = "elg";
      elems = "pgy";
    }
  else
    {
      log_error ("unknown private key algorithm\n");
      gcry_sexp_release (list);
      gcry_sexp_release (s_skey);
      return gpg_error (GPG_ERR_BAD_SECKEY);
    }

  /* Allocate an array for the parameters and copy them out of the
     secret key.   FIXME: We should have a generic copy function. */
  array = xtrycalloc (strlen(elems) + 1, sizeof *array);
  if (!array)
    {
      rc = gpg_error_from_syserror ();
      gcry_sexp_release (list);
      gcry_sexp_release (s_skey);
      return rc;
    }

  for (idx=0, s=elems; *s; s++, idx++ )
    {
      l2 = gcry_sexp_find_token (list, s, 1);
      if (!l2)
        {
          /* Required parameter not found.  */
          for (i=0; i<idx; i++)
            gcry_mpi_release (array[i]);
          xfree (array);
          gcry_sexp_release (list);
          gcry_sexp_release (s_skey);
          return gpg_error (GPG_ERR_BAD_SECKEY);
	}
      array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
      gcry_sexp_release (l2);
      if (!array[idx])
        {
          /* Required parameter is invalid. */
          for (i=0; i<idx; i++)
            gcry_mpi_release (array[i]);
          xfree (array);
          gcry_sexp_release (list);
          gcry_sexp_release (s_skey);
          return gpg_error (GPG_ERR_BAD_SECKEY);
	}
    }
  gcry_sexp_release (list);
  list = NULL;

  uri = NULL;
  uri_length = 0;
  uri_sexp = gcry_sexp_find_token (s_skey, "uri", 0);
  if (uri_sexp)
    uri = gcry_sexp_nth_data (uri_sexp, 1, &uri_length);

  comment = NULL;
  comment_length = 0;
  comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
  if (comment_sexp)
    comment = gcry_sexp_nth_data (comment_sexp, 1, &comment_length);

  gcry_sexp_release (s_skey);
  s_skey = NULL;


  /* FIXME: The following thing is pretty ugly code; we should
     investigate how to make it cleaner. Probably code to handle
     canonical S-expressions in a memory buffer is better suioted for
     such a task.  After all that is what we do in protect.c.  Neeed
     to find common patterns and write a straightformward API to use
     them.  */
  assert (sizeof (size_t) <= sizeof (void*));

  format = xtrymalloc (15+7*strlen (elems)+10+15+1+1);
  if (!format)
    {
      rc = gpg_error_from_syserror ();
      for (i=0; array[i]; i++)
        gcry_mpi_release (array[i]);
      xfree (array);
      gcry_sexp_release (uri_sexp);
      gcry_sexp_release (comment_sexp);
      return rc;
    }

  argidx = 0;
  p = stpcpy (stpcpy (format, "(public-key("), algoname);
  for (idx=0, s=elems; *s; s++, idx++ )
    {
      *p++ = '(';
      *p++ = *s;
      p = stpcpy (p, " %m)");
      assert (argidx < DIM (args));
      args[argidx++] = &array[idx];
    }
  *p++ = ')';
  if (uri)
    {
      p = stpcpy (p, "(uri %b)");
      assert (argidx+1 < DIM (args));
      args[argidx++] = (void *)&uri_length;
      args[argidx++] = (void *)&uri;
    }
  if (comment)
    {
      p = stpcpy (p, "(comment %b)");
      assert (argidx+1 < DIM (args));
      args[argidx++] = (void *)&comment_length;
      args[argidx++] = (void*)&comment;
    }
  *p++ = ')';
  *p = 0;
  assert (argidx < DIM (args));
  args[argidx] = NULL;

  rc = gcry_sexp_build_array (&list, NULL, format, args);
  xfree (format);
  for (i=0; array[i]; i++)
    gcry_mpi_release (array[i]);
  xfree (array);
  gcry_sexp_release (uri_sexp);
  gcry_sexp_release (comment_sexp);

  if (!rc)
    *result = list;
  return rc;
}
예제 #9
0
파일: findkey.c 프로젝트: Juul/gnupg
/* Return the string name from the S-expression S_KEY as well as a
   string describing the names of the parameters.  ALGONAMESIZE and
   ELEMSSIZE give the allocated size of the provided buffers.  The
   buffers may be NULL if not required.  If R_LIST is not NULL the top
   level list will be stored tehre; the caller needs to release it in
   this case.  */
static gpg_error_t
key_parms_from_sexp (gcry_sexp_t s_key, gcry_sexp_t *r_list,
                     char *r_algoname, size_t algonamesize,
                     char *r_elems, size_t elemssize)
{
  gcry_sexp_t list, l2;
  const char *name, *algoname, *elems;
  size_t n;

  if (r_list)
    *r_list = NULL;

  list = gcry_sexp_find_token (s_key, "shadowed-private-key", 0 );
  if (!list)
    list = gcry_sexp_find_token (s_key, "protected-private-key", 0 );
  if (!list)
    list = gcry_sexp_find_token (s_key, "private-key", 0 );
  if (!list)
    {
      log_error ("invalid private key format\n");
      return gpg_error (GPG_ERR_BAD_SECKEY);
    }

  l2 = gcry_sexp_cadr (list);
  gcry_sexp_release (list);
  list = l2;
  name = gcry_sexp_nth_data (list, 0, &n);
  if (n==3 && !memcmp (name, "rsa", 3))
    {
      algoname = "rsa";
      elems = "ne";
    }
  else if (n==3 && !memcmp (name, "dsa", 3))
    {
      algoname = "dsa";
      elems = "pqgy";
    }
  else if (n==5 && !memcmp (name, "ecdsa", 5))
    {
      algoname = "ecdsa";
      elems = "pabgnq";
    }
  else if (n==4 && !memcmp (name, "ecdh", 4))
    {
      algoname = "ecdh";
      elems = "pabgnq";
    }
  else if (n==3 && !memcmp (name, "elg", 3))
    {
      algoname = "elg";
      elems = "pgy";
    }
  else
    {
      log_error ("unknown private key algorithm\n");
      gcry_sexp_release (list);
      return gpg_error (GPG_ERR_BAD_SECKEY);
    }

  if (r_algoname)
    {
      if (strlen (algoname) >= algonamesize)
        return gpg_error (GPG_ERR_BUFFER_TOO_SHORT);
      strcpy (r_algoname, algoname);
    }
  if (r_elems)
    {
      if (strlen (elems) >= elemssize)
        return gpg_error (GPG_ERR_BUFFER_TOO_SHORT);
      strcpy (r_elems, elems);
    }

  if (r_list)
    *r_list = list;
  else
    gcry_sexp_release (list);

  return 0;
}
예제 #10
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;
}
예제 #11
0
/* Return the Secure Shell type fingerprint for KEY using digest ALGO.
   The length of the fingerprint is returned at R_LEN and the
   fingerprint itself at R_FPR.  In case of a error code is returned
   and NULL stored at R_FPR.  */
static gpg_error_t
get_fingerprint (gcry_sexp_t key, int algo,
                 void **r_fpr, size_t *r_len, int as_string)
{
  gpg_error_t err;
  gcry_sexp_t list = NULL;
  gcry_sexp_t l2 = NULL;
  const char *s;
  char *name = NULL;
  int idx;
  const char *elems;
  gcry_md_hd_t md = NULL;
  int blobmode = 0;

  *r_fpr = NULL;
  *r_len = 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)
    {
      err = gpg_err_make (default_errsource, GPG_ERR_UNKNOWN_SEXP);
      goto leave;
    }

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

  name = gcry_sexp_nth_string (list, 0);
  if (!name)
    {
      err = gpg_err_make (default_errsource, GPG_ERR_INV_SEXP);
      goto leave;
    }

  err = gcry_md_open (&md, algo, 0);
  if (err)
    goto leave;

  switch (gcry_pk_map_name (name))
    {
    case GCRY_PK_RSA:
      elems = "en";
      gcry_md_write (md, "\0\0\0\x07ssh-rsa", 11);
      break;

    case GCRY_PK_DSA:
      elems = "pqgy";
      gcry_md_write (md, "\0\0\0\x07ssh-dss", 11);
      break;

    case GCRY_PK_ECC:
      if (is_eddsa (list))
        {
          elems = "q";
          blobmode = 1;
          /* For now there is just one curve, thus no need to switch
             on it.  */
          gcry_md_write (md, "\0\0\0\x0b" "ssh-ed25519", 15);
        }
      else
        {
          /* We only support the 3 standard curves for now.  It is
             just a quick hack.  */
          elems = "q";
          gcry_md_write (md, "\0\0\0\x13" "ecdsa-sha2-nistp", 20);
          l2 = gcry_sexp_find_token (list, "curve", 0);
          if (!l2)
            elems = "";
          else
            {
              gcry_free (name);
              name = gcry_sexp_nth_string (l2, 1);
              gcry_sexp_release (l2);
              l2 = NULL;
              if (!name)
                elems = "";
              else if (!strcmp (name, "NIST P-256")||!strcmp (name, "nistp256"))
                gcry_md_write (md, "256\0\0\0\x08nistp256", 15);
              else if (!strcmp (name, "NIST P-384")||!strcmp (name, "nistp384"))
                gcry_md_write (md, "384\0\0\0\x08nistp384", 15);
              else if (!strcmp (name, "NIST P-521")||!strcmp (name, "nistp521"))
                gcry_md_write (md, "521\0\0\0\x08nistp521", 15);
              else
                elems = "";
            }
          if (!*elems)
            err = gpg_err_make (default_errsource, GPG_ERR_UNKNOWN_CURVE);
        }
      break;

    default:
      elems = "";
      err = gpg_err_make (default_errsource, GPG_ERR_PUBKEY_ALGO);
      break;
    }
  if (err)
    goto leave;


  for (idx = 0, s = elems; *s; s++, idx++)
    {
      l2 = gcry_sexp_find_token (list, s, 1);
      if (!l2)
        {
          err = gpg_err_make (default_errsource, GPG_ERR_INV_SEXP);
          goto leave;
        }
      if (blobmode)
        {
          const char *blob;
          size_t bloblen;
          unsigned char lenbuf[4];

          blob = gcry_sexp_nth_data (l2, 1, &bloblen);
          if (!blob)
            {
              err = gpg_err_make (default_errsource, GPG_ERR_INV_SEXP);
              goto leave;
            }
          blob++;
          bloblen--;
          lenbuf[0] = bloblen >> 24;
          lenbuf[1] = bloblen >> 16;
          lenbuf[2] = bloblen >>  8;
          lenbuf[3] = bloblen;
          gcry_md_write (md, lenbuf, 4);
          gcry_md_write (md, blob, bloblen);
        }
      else
        {
          gcry_mpi_t a;
          unsigned char *buf;
          size_t buflen;

          a = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
          gcry_sexp_release (l2);
          l2 = NULL;
          if (!a)
            {
              err = gpg_err_make (default_errsource, GPG_ERR_INV_SEXP);
              goto leave;
            }

          err = gcry_mpi_aprint (GCRYMPI_FMT_SSH, &buf, &buflen, a);
          gcry_mpi_release (a);
          if (err)
            goto leave;
          gcry_md_write (md, buf, buflen);
          gcry_free (buf);
        }
    }
예제 #12
0
static gcry_mpi_t *
sexp_to_kparms (gcry_sexp_t sexp, unsigned long *created)
{
  gcry_sexp_t list, l2;
  const char *name;
  const char *s;
  size_t n;
  int i, idx;
  const char *elems;
  gcry_mpi_t *array;

  *created = 0;
  list = gcry_sexp_find_token (sexp, "private-key", 0 );
  if(!list)
    return NULL;

  /* quick hack to get the creation time. */
  l2 = gcry_sexp_find_token (list, "created", 0);
  if (l2 && (name = gcry_sexp_nth_data (l2, 1, &n)))
    {
      char *tmp = xmalloc (n+1);
      memcpy (tmp, name, n);
      tmp[n] = 0;
      *created = strtoul (tmp, NULL, 10);
      xfree (tmp);
    }
  gcry_sexp_release (l2);
  l2 = gcry_sexp_cadr (list);
  gcry_sexp_release (list);
  list = l2;
  name = gcry_sexp_nth_data (list, 0, &n);
  if(!name || n != 3 || memcmp (name, "rsa", 3))
    {
      gcry_sexp_release (list);
      return NULL;
    }

  /* Parameter names used with RSA. */
  elems = "nedpqu";
  array = xcalloc (strlen(elems) + 1, sizeof *array);
  for (idx=0, s=elems; *s; s++, idx++ )
    {
      l2 = gcry_sexp_find_token (list, s, 1);
      if (!l2)
        {
          for (i=0; i<idx; i++)
            gcry_mpi_release (array[i]);
          xfree (array);
          gcry_sexp_release (list);
          return NULL; /* required parameter not found */
	}
      array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
      gcry_sexp_release (l2);
      if (!array[idx])
        {
          for (i=0; i<idx; i++)
            gcry_mpi_release (array[i]);
          xfree (array);
          gcry_sexp_release (list);
          return NULL; /* required parameter is invalid */
	}
    }

  gcry_sexp_release (list);
  return array;
}
예제 #13
0
파일: export.c 프로젝트: FMayzek/gnupg
/* Parse a private key S-expression and retutn a malloced array with
   the RSA paramaters in pkcs#12 order.  The caller needs to
   deep-release this array.  */
static gcry_mpi_t *
sexp_to_kparms (gcry_sexp_t sexp)
{
  gcry_sexp_t list, l2;
  const char *name;
  const char *s;
  size_t n;
  int idx;
  const char *elems;
  gcry_mpi_t *array;

  list = gcry_sexp_find_token (sexp, "private-key", 0 );
  if(!list)
    return NULL;
  l2 = gcry_sexp_cadr (list);
  gcry_sexp_release (list);
  list = l2;
  name = gcry_sexp_nth_data (list, 0, &n);
  if(!name || n != 3 || memcmp (name, "rsa", 3))
    {
      gcry_sexp_release (list);
      return NULL;
    }

  /* Parameter names used with RSA in the pkcs#12 order. */
  elems = "nedqp--u";
  array = xtrycalloc (strlen(elems) + 1, sizeof *array);
  if (!array)
    {
      gcry_sexp_release (list);
      return NULL;
    }
  for (idx=0, s=elems; *s; s++, idx++ )
    {
      if (*s == '-')
        continue; /* Computed below  */
      l2 = gcry_sexp_find_token (list, s, 1);
      if (l2)
        {
          array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
          gcry_sexp_release (l2);
        }
      if (!array[idx]) /* Required parameter not found or invalid.  */
        {
          for (idx=0; array[idx]; idx++)
            gcry_mpi_release (array[idx]);
          xfree (array);
          gcry_sexp_release (list);
          return NULL;
        }
    }
  gcry_sexp_release (list);

  array[5] = gcry_mpi_snew (0);  /* compute d mod (q-1) */
  gcry_mpi_sub_ui (array[5], array[3], 1);
  gcry_mpi_mod (array[5], array[2], array[5]);

  array[6] = gcry_mpi_snew (0);  /* compute d mod (p-1) */
  gcry_mpi_sub_ui (array[6], array[4], 1);
  gcry_mpi_mod (array[6], array[3], array[6]);

  return array;
}