Esempio n. 1
0
static void
get_keys_sample (gcry_sexp_t *pkey, gcry_sexp_t *skey, int secret_variant)
{
  gcry_sexp_t pub_key, sec_key;
  int rc;
  static const char *secret;


  switch (secret_variant)
    {
    case 0: secret = sample_private_key_1; break;
    case 1: secret = sample_private_key_1_1; break;
    case 2: secret = sample_private_key_1_2; break;
    default: die ("BUG\n");
    }

  rc = gcry_sexp_sscan (&pub_key, NULL, sample_public_key_1,
			strlen (sample_public_key_1));
  if (!rc)
    rc = gcry_sexp_sscan (&sec_key, NULL, secret, strlen (secret));
  if (rc)
    die ("converting sample keys failed: %s\n", gcry_strerror (rc));

  *pkey = pub_key;
  *skey = sec_key;
}
Esempio n. 2
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);
}
Esempio n. 3
0
/* Encrypt the DEK under the key contained in CERT and return it as a
   canonical S-Exp in encval. */
static int
encrypt_dek (const DEK dek, ksba_cert_t cert, unsigned char **encval)
{
  gcry_sexp_t s_ciph, s_data, s_pkey;
  int rc;
  ksba_sexp_t buf;
  size_t len;

  *encval = NULL;

  /* get the key from the cert */
  buf = ksba_cert_get_public_key (cert);
  if (!buf)
    {
      log_error ("no public key for recipient\n");
      return gpg_error (GPG_ERR_NO_PUBKEY);
    }
  len = gcry_sexp_canon_len (buf, 0, NULL, NULL);
  if (!len)
    {
      log_error ("libksba did not return a proper S-Exp\n");
      return gpg_error (GPG_ERR_BUG);
    }
  rc = gcry_sexp_sscan (&s_pkey, NULL, (char*)buf, len);
  xfree (buf); buf = NULL;
  if (rc)
    {
      log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
      return rc;
    }

  /* Put the encoded cleartext into a simple list. */
  s_data = NULL; /* (avoid compiler warning) */
  rc = encode_session_key (dek, &s_data);
  if (rc)
    {
      log_error ("encode_session_key failed: %s\n", gpg_strerror (rc));
      return rc;
    }

  /* pass it to libgcrypt */
  rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey);
  gcry_sexp_release (s_data);
  gcry_sexp_release (s_pkey);
  
  /* Reformat it. */
  if (!rc)
    {
      rc = make_canon_sexp (s_ciph, encval, NULL);
      gcry_sexp_release (s_ciph);
    }
  return rc;
}
Esempio n. 4
0
/* Send a GENKEY command to the SCdaemon.  SERIALNO is not used in
   this implementation.  If CREATEDATE has been given, it will be
   passed to SCDAEMON so that the key can be created with this
   timestamp; note the user needs to use the returned timestamp as old
   versions of scddaemon don't support this option.  */
int
agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
                  const char *serialno, u32 createtime, gcry_sexp_t *r_pubkey)
{
    int rc;
    char line[ASSUAN_LINELENGTH];
    gnupg_isotime_t tbuf;
    membuf_t data;
    unsigned char *buf;
    size_t len;

    (void)serialno;

    rc = start_agent (1);
    if (rc)
        return rc;

    if (createtime)
        epoch2isotime (tbuf, createtime);
    else
        *tbuf = 0;

    memset (info, 0, sizeof *info);
    snprintf (line, DIM(line)-1, "SCD GENKEY %s%s %s %d",
              *tbuf? "--timestamp=":"", tbuf,
              force? "--force":"",
              keyno);
    line[DIM(line)-1] = 0;

    memset (info, 0, sizeof *info);
    init_membuf_secure (&data, 1024);
    rc = assuan_transact (agent_ctx, line,
                          membuf_data_cb, &data, default_inq_cb, NULL,
                          scd_genkey_cb, info);

    status_sc_op_failure (rc);

    if (rc)
    {
        xfree (get_membuf (&data, &len));
    }
    else
    {
        buf = get_membuf (&data, &len);
        if (!buf)
            return gpg_error_from_syserror ();
        rc = gcry_sexp_sscan (r_pubkey, NULL, buf, len);
        xfree (buf);
    }

    return rc;
}
Esempio n. 5
0
/* Return the so called "keygrip" which is the SHA-1 hash of the
   public key parameters expressed in a way depended on the algorithm.

   KEY is expected to be an canonical encoded S-expression with a
   public or private key. KEYLEN is the length of that buffer.

   GRIP must be at least 20 bytes long.  On success 0 is returned, on
   error an error code. */
gpg_error_t
keygrip_from_canon_sexp (const unsigned char *key, size_t keylen,
                         unsigned char *grip)
{
    gpg_error_t err;
    gcry_sexp_t sexp;

    if (!grip)
        return gpg_error (GPG_ERR_INV_VALUE);
    err = gcry_sexp_sscan (&sexp, NULL, (const char *)key, keylen);
    if (err)
        return err;
    if (!gcry_pk_get_keygrip (sexp, grip))
        err = gpg_error (GPG_ERR_INTERNAL);
    gcry_sexp_release (sexp);
    return err;
}
Esempio n. 6
0
static int
encode_session_key (DEK dek, gcry_sexp_t * r_data)
{
  gcry_sexp_t data;
  char *p;
  int rc;

  p = xtrymalloc (64 + 2 * dek->keylen);
  if (!p)
    return gpg_error_from_syserror ();
  strcpy (p, "(data\n (flags pkcs1)\n (value #");
  bin2hex (dek->key, dek->keylen, p + strlen (p));
  strcat (p, "#))\n");
  rc = gcry_sexp_sscan (&data, NULL, p, strlen (p));
  xfree (p);
  *r_data = data;
  return rc;    
}
Esempio n. 7
0
static void
check_one_pubkey (int n, test_spec_pubkey_t spec)
{
  gcry_error_t err = GPG_ERR_NO_ERROR;
  gcry_sexp_t skey, pkey;

  err = gcry_sexp_sscan (&skey, NULL, spec.key.secret,
			 strlen (spec.key.secret));
  if (!err)
    err = gcry_sexp_sscan (&pkey, NULL, spec.key.public,
			   strlen (spec.key.public));
  if (err)
    die ("converting sample key failed: %s\n", gpg_strerror (err));

  do_check_one_pubkey (n, skey, pkey, spec.key.grip, spec.flags);
 
  gcry_sexp_release (skey);
  gcry_sexp_release (pkey);
}
Esempio n. 8
0
static void
check_sscan (void)
{
  static struct {
    const char *text;
    gcry_error_t expected_err;
  } values[] = {
    /* Bug reported by Olivier L'Heureux 2003-10-07 */
    { "(7:sig-val(3:dsa"
      "(1:r20:\x7e\xff\xd5\xba\xc9\xc9\xa4\x9b\xd4\x26\x8b\x64"
      "\x06\x7a\xcf\x42\x7b\x6c\x51\xfb)"
      "(1:s21:\x01\x8c\x6c\x6f\x37\x1a\x8d\xfd\x5a\xb3\x2a\x3d"
      "\xc5\xae\x23\xed\x32\x62\x30\x62\x3e)))",
      GPG_ERR_NO_ERROR },
    { "(7:sig-val(3:dsa"
      "(1:r20:\x7e\xff\xd5\xba\xc9\xc9\xa4\x9b\xd4\x26\x8b\x64"
      "\x06\x7a\xcf\x42\x7b\x6c\x51\xfb)"
      "(1:s21:\x01\x8c\x6c\x6f\x37\x1a\x8d\xfd\x5a\xb3\x2a\x3d"
      "\xc5\xae\x23\xed\x32\x62\x30\x62\x3e))",
      GPG_ERR_SEXP_UNMATCHED_PAREN },
    { "(7:sig-val(3:dsa"
      "(1:r20:\x7e\xff\xd5\xba\xc9\xc9\xa4\x9b\xd4\x26\x8b\x64"
      "\x06\x7a\xcf\x42\x7b\x6c\x51\xfb)"
      "(1:s21:\x01\x8c\x6c\x6f\x37\x1a\x8d\xfd\x5a\xb3\x2a\x3d"
      "\xc5\xae\x23\xed\x32\x62\x30\x62\x3e))))",
      GPG_ERR_SEXP_UNMATCHED_PAREN },
    { NULL, 0 }
  };
  int idx;
  gcry_error_t err;
  gcry_sexp_t s;

  info ("checking gcry_sexp_sscan\n");
  for (idx=0; values[idx].text; idx++)
    {
      err = gcry_sexp_sscan (&s, NULL,
                             values[idx].text,
                             strlen (values[idx].text));
      if (gpg_err_code (err) != values[idx].expected_err)
        fail ("gcry_sexp_sscan test %d failed: %s\n", idx, gpg_strerror (err));
      gcry_sexp_release (s);
    }
}
Esempio n. 9
0
/* Print the S-Expression in BUF to extended STREAM, which has a valid
   length of BUFLEN, as a human readable string in one line to FP. */
static void
pretty_es_print_sexp (estream_t fp, const unsigned char *buf, size_t buflen)
{
  size_t len;
  gcry_sexp_t sexp;
  char *result, *p;

  if ( gcry_sexp_sscan (&sexp, NULL, (const char*)buf, buflen) )
    {
      es_fputs (_("[Error - invalid encoding]"), fp);
      return;
    }
  len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0);
  assert (len);
  result = xtrymalloc (len);
  if (!result)
    {
      es_fputs (_("[Error - out of core]"), fp);
      gcry_sexp_release (sexp);
      return;
    }
  len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, result, len);
  assert (len);
  for (p = result; len; len--, p++)
    {
      if (*p == '\n')
        {
          if (len > 1) /* Avoid printing the trailing LF. */
            es_fputs ("\\n", fp);
        }
      else if (*p == '\r')
        es_fputs ("\\r", fp);
      else if (*p == '\v')
        es_fputs ("\\v", fp);
      else if (*p == '\t')
        es_fputs ("\\t", fp);
      else
        es_putc (*p, fp);
    }
  xfree (result);
  gcry_sexp_release (sexp);
}
Esempio n. 10
0
File: misc.c Progetto: FMayzek/gnupg
/* Convert a canonical encoded S-expression in CANON into the GCRY
   type. */
gpg_error_t
canon_sexp_to_gcry (const unsigned char *canon, gcry_sexp_t *r_sexp)
{
  gpg_error_t err;
  size_t n;
  gcry_sexp_t sexp;

  *r_sexp = NULL;
  n = gcry_sexp_canon_len (canon, 0, NULL, NULL);
  if (!n)
    {
      log_error (_("invalid canonical S-expression found\n"));
      err = gpg_error (GPG_ERR_INV_SEXP);
    }
  else if ((err = gcry_sexp_sscan (&sexp, NULL, canon, n)))
    log_error (_("converting S-expression failed: %s\n"), gcry_strerror (err));
  else
    *r_sexp = sexp;
  return err;
}
Esempio n. 11
0
/* Return the so called KEYGRIP which is the SHA-1 hash of the public
   key parameters expressed as an canoncial encoded S-Exp.  ARRAY must
   be 20 bytes long.  Returns ARRAY or a newly allocated buffer if ARRAY was
   given as NULL.  May return NULL on error.  */
unsigned char *
gpgsm_get_keygrip (ksba_cert_t cert, unsigned char *array)
{
  gcry_sexp_t s_pkey;
  int rc;
  ksba_sexp_t p;
  size_t n;

  p = ksba_cert_get_public_key (cert);
  if (!p)
    return NULL; /* oops */

  if (DBG_X509)
    log_debug ("get_keygrip for public key\n");
  n = gcry_sexp_canon_len (p, 0, NULL, NULL);
  if (!n)
    {
      log_error ("libksba did not return a proper S-Exp\n");
      return NULL;
    }
  rc = gcry_sexp_sscan ( &s_pkey, NULL, (char*)p, n);
  xfree (p);
  if (rc)
    {
      log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
      return NULL;
    }
  array = gcry_pk_get_keygrip (s_pkey, array);
  gcry_sexp_release (s_pkey);
  if (!array)
    {
      rc = gpg_error (GPG_ERR_GENERAL);
      log_error ("can't calculate keygrip\n");
      return NULL;
    }
  if (DBG_X509)
    log_printhex ("keygrip=", array, 20);

  return array;
}
Esempio n. 12
0
/* Get the keygrip from CERT, return 0 on success */
int
card_help_get_keygrip (ksba_cert_t cert, unsigned char *array)
{
  gcry_sexp_t s_pkey;
  int rc;
  ksba_sexp_t p;
  size_t n;

  p = ksba_cert_get_public_key (cert);
  if (!p)
    return -1; /* oops */
  n = gcry_sexp_canon_len (p, 0, NULL, NULL);
  if (!n)
    return -1; /* libksba did not return a proper S-expression */
  rc = gcry_sexp_sscan ( &s_pkey, NULL, p, n);
  xfree (p);
  if (rc)
    return -1; /* can't parse that S-expression */
  array = gcry_pk_get_keygrip (s_pkey, array);
  gcry_sexp_release (s_pkey);
  if (!array)
    return -1; /* failed to calculate the keygrip */
  return 0;
}
Esempio n. 13
0
/* Check the signature on CERT using the ISSUER_CERT.  This function
   does only test the cryptographic signature and nothing else.  It is
   assumed that the ISSUER_CERT is valid. */
static gpg_error_t
check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert)
{
  gpg_error_t err;
  const char *algoid;
  gcry_md_hd_t md;
  int i, algo;
  ksba_sexp_t p;
  size_t n;
  gcry_sexp_t s_sig, s_hash, s_pkey;
  const char *s;
  char algo_name[16+1]; /* hash algorithm name converted to lower case. */
  int digestlen;
  unsigned char *digest;

  /* Hash the target certificate using the algorithm from that certificate.  */
  algoid = ksba_cert_get_digest_algo (cert);
  algo = gcry_md_map_name (algoid);
  if (!algo)
    {
      log_error (_("unknown hash algorithm '%s'\n"), algoid? algoid:"?");
      return gpg_error (GPG_ERR_GENERAL);
    }
  s = gcry_md_algo_name (algo);
  for (i=0; *s && i < sizeof algo_name - 1; s++, i++)
    algo_name[i] = tolower (*s);
  algo_name[i] = 0;

  err = gcry_md_open (&md, algo, 0);
  if (err)
    {
      log_error ("md_open failed: %s\n", gpg_strerror (err));
      return err;
    }
  if (DBG_HASHING)
    gcry_md_debug (md, "hash.cert");

  err = ksba_cert_hash (cert, 1, HASH_FNC, md);
  if (err)
    {
      log_error ("ksba_cert_hash failed: %s\n", gpg_strerror (err));
      gcry_md_close (md);
      return err;
    }
  gcry_md_final (md);

  /* Get the signature value out of the target certificate.  */
  p = ksba_cert_get_sig_val (cert);
  n = gcry_sexp_canon_len (p, 0, NULL, NULL);
  if (!n)
    {
      log_error ("libksba did not return a proper S-Exp\n");
      gcry_md_close (md);
      ksba_free (p);
      return gpg_error (GPG_ERR_BUG);
    }
  if (DBG_CRYPTO)
    {
      int j;
      log_debug ("signature value:");
      for (j=0; j < n; j++)
        log_printf (" %02X", p[j]);
      log_printf ("\n");
    }

  err = gcry_sexp_sscan ( &s_sig, NULL, p, n);
  ksba_free (p);
  if (err)
    {
      log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (err));
      gcry_md_close (md);
      return err;
    }

  /* Get the public key from the issuer certificate.  */
  p = ksba_cert_get_public_key (issuer_cert);
  n = gcry_sexp_canon_len (p, 0, NULL, NULL);
  if (!n)
    {
      log_error ("libksba did not return a proper S-Exp\n");
      gcry_md_close (md);
      ksba_free (p);
      gcry_sexp_release (s_sig);
      return gpg_error (GPG_ERR_BUG);
    }
  err = gcry_sexp_sscan ( &s_pkey, NULL, p, n);
  ksba_free (p);
  if (err)
    {
      log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (err));
      gcry_md_close (md);
      gcry_sexp_release (s_sig);
      return err;
    }


  /* Prepare the values for signature verification. At this point we
     have these values:

     S_PKEY    - S-expression with the issuer's public key.
     S_SIG     - Signature value as given in the certrificate.
     MD        - Finalized hash context with hash of the certificate.
     ALGO_NAME - Lowercase hash algorithm name
   */
  digestlen = gcry_md_get_algo_dlen (algo);
  digest = gcry_md_read (md, algo);
  if (pk_algo_from_sexp (s_pkey) == GCRY_PK_DSA)
    {
      if (digestlen != 20)
        {
          log_error (_("DSA requires the use of a 160 bit hash algorithm\n"));
          gcry_md_close (md);
          gcry_sexp_release (s_sig);
          gcry_sexp_release (s_pkey);
          return gpg_error (GPG_ERR_INTERNAL);
        }
      if ( gcry_sexp_build (&s_hash, NULL, "(data(flags raw)(value %b))",
                            (int)digestlen, digest) )
        BUG ();
    }
  else /* Not DSA.  */
    {
      if ( gcry_sexp_build (&s_hash, NULL, "(data(flags pkcs1)(hash %s %b))",
                            algo_name, (int)digestlen, digest) )
        BUG ();

    }

  err = gcry_pk_verify (s_sig, s_hash, s_pkey);
  if (DBG_X509)
    log_debug ("gcry_pk_verify: %s\n", gpg_strerror (err));
  gcry_md_close (md);
  gcry_sexp_release (s_sig);
  gcry_sexp_release (s_hash);
  gcry_sexp_release (s_pkey);
  return err;
}
Esempio n. 14
0
/* Unprotect the canconical encoded S-expression key in KEYBUF.  GRIP
   should be the hex encoded keygrip of that key to be used with the
   caching mechanism. DESC_TEXT may be set to override the default
   description used for the pinentry.  If LOOKUP_TTL is given this
   function is used to lookup the default ttl.  If R_PASSPHRASE is not
   NULL, the function succeeded and the key was protected the used
   passphrase (entered or from the cache) is stored there; if not NULL
   will be stored.  The caller needs to free the returned
   passphrase. */
static int
unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
           unsigned char **keybuf, const unsigned char *grip,
           cache_mode_t cache_mode, lookup_ttl_t lookup_ttl,
           char **r_passphrase)
{
  struct pin_entry_info_s *pi;
  struct try_unprotect_arg_s arg;
  int rc;
  unsigned char *result;
  size_t resultlen;
  char hexgrip[40+1];

  if (r_passphrase)
    *r_passphrase = NULL;

  bin2hex (grip, 20, hexgrip);

  /* Initially try to get it using a cache nonce.  */
  if (cache_nonce)
    {
      char *pw;

      pw = agent_get_cache (cache_nonce, CACHE_MODE_NONCE);
      if (pw)
        {
          rc = agent_unprotect (ctrl, *keybuf, pw, NULL, &result, &resultlen);
          if (!rc)
            {
              if (r_passphrase)
                *r_passphrase = pw;
              else
                xfree (pw);
              xfree (*keybuf);
              *keybuf = result;
              return 0;
            }
          xfree (pw);
        }
    }

  /* First try to get it from the cache - if there is none or we can't
     unprotect it, we fall back to ask the user */
  if (cache_mode != CACHE_MODE_IGNORE)
    {
      char *pw;

    retry:
      pw = agent_get_cache (hexgrip, cache_mode);
      if (pw)
        {
          rc = agent_unprotect (ctrl, *keybuf, pw, NULL, &result, &resultlen);
          if (!rc)
            {
              if (cache_mode == CACHE_MODE_NORMAL)
                agent_store_cache_hit (hexgrip);
              if (r_passphrase)
                *r_passphrase = pw;
              else
                xfree (pw);
              xfree (*keybuf);
              *keybuf = result;
              return 0;
            }
          xfree (pw);
          rc  = 0;
        }
      else if (cache_mode == CACHE_MODE_NORMAL)
        {
          /* The standard use of GPG keys is to have a signing and an
             encryption subkey.  Commonly both use the same
             passphrase.  We try to help the user to enter the
             passphrase only once by silently trying the last
             correctly entered passphrase.  Checking one additional
             passphrase should be acceptable; despite the S2K
             introduced delays. The assumed workflow is:

               1. Read encrypted message in a MUA and thus enter a
                  passphrase for the encryption subkey.

               2. Reply to that mail with an encrypted and signed
                  mail, thus entering the passphrase for the signing
                  subkey.

             We can often avoid the passphrase entry in the second
             step.  We do this only in normal mode, so not to
             interfere with unrelated cache entries.  */
          pw = agent_get_cache (NULL, cache_mode);
          if (pw)
            {
              rc = agent_unprotect (ctrl, *keybuf, pw, NULL,
                                    &result, &resultlen);
              if (!rc)
                {
                  if (r_passphrase)
                    *r_passphrase = pw;
                  else
                    xfree (pw);
                  xfree (*keybuf);
                  *keybuf = result;
                  return 0;
                }
              xfree (pw);
              rc  = 0;
            }
        }

      /* If the pinentry is currently in use, we wait up to 60 seconds
         for it to close and check the cache again.  This solves a common
         situation where several requests for unprotecting a key have
         been made but the user is still entering the passphrase for
         the first request.  Because all requests to agent_askpin are
         serialized they would then pop up one after the other to
         request the passphrase - despite that the user has already
         entered it and is then available in the cache.  This
         implementation is not race free but in the worst case the
         user has to enter the passphrase only once more. */
      if (pinentry_active_p (ctrl, 0))
        {
          /* Active - wait */
          if (!pinentry_active_p (ctrl, 60))
            {
              /* We need to give the other thread a chance to actually put
                 it into the cache. */
              npth_sleep (1);
              goto retry;
            }
          /* Timeout - better call pinentry now the plain way. */
        }
    }

  pi = gcry_calloc_secure (1, sizeof (*pi) + MAX_PASSPHRASE_LEN + 1);
  if (!pi)
    return gpg_error_from_syserror ();
  pi->max_length = MAX_PASSPHRASE_LEN + 1;
  pi->min_digits = 0;  /* we want a real passphrase */
  pi->max_digits = 16;
  pi->max_tries = 3;
  pi->check_cb = try_unprotect_cb;
  arg.ctrl = ctrl;
  arg.protected_key = *keybuf;
  arg.unprotected_key = NULL;
  arg.change_required = 0;
  pi->check_cb_arg = &arg;

  rc = agent_askpin (ctrl, desc_text, NULL, NULL, pi, hexgrip, cache_mode);
  if (!rc)
    {
      assert (arg.unprotected_key);
      if (arg.change_required)
        {
          /* The callback told as that the user should change their
             passphrase.  Present the dialog to do.  */
          size_t canlen, erroff;
          gcry_sexp_t s_skey;

          assert (arg.unprotected_key);
          canlen = gcry_sexp_canon_len (arg.unprotected_key, 0, NULL, NULL);
          rc = gcry_sexp_sscan (&s_skey, &erroff,
                                (char*)arg.unprotected_key, canlen);
          if (rc)
            {
              log_error ("failed to build S-Exp (off=%u): %s\n",
                         (unsigned int)erroff, gpg_strerror (rc));
              wipememory (arg.unprotected_key, canlen);
              xfree (arg.unprotected_key);
              xfree (pi);
              return rc;
            }
          rc = agent_protect_and_store (ctrl, s_skey, NULL);
          gcry_sexp_release (s_skey);
          if (rc)
            {
              log_error ("changing the passphrase failed: %s\n",
                         gpg_strerror (rc));
              wipememory (arg.unprotected_key, canlen);
              xfree (arg.unprotected_key);
              xfree (pi);
              return rc;
            }
        }
      else
        {
          /* Passphrase is fine.  */
          agent_put_cache (hexgrip, cache_mode, pi->pin,
                           lookup_ttl? lookup_ttl (hexgrip) : 0);
          agent_store_cache_hit (hexgrip);
          if (r_passphrase && *pi->pin)
            *r_passphrase = xtrystrdup (pi->pin);
        }
      xfree (*keybuf);
      *keybuf = arg.unprotected_key;
    }
  xfree (pi);
  return rc;
}
Esempio n. 15
0
int
gpgsm_check_cms_signature (ksba_cert_t cert, ksba_const_sexp_t sigval,
                           gcry_md_hd_t md, int mdalgo, int *r_pkalgo)
{
  int rc;
  ksba_sexp_t p;
  gcry_mpi_t frame;
  gcry_sexp_t s_sig, s_hash, s_pkey;
  size_t n;
  int pkalgo;

  if (r_pkalgo)
    *r_pkalgo = 0;

  n = gcry_sexp_canon_len (sigval, 0, NULL, NULL);
  if (!n)
    {
      log_error ("libksba did not return a proper S-Exp\n");
      return gpg_error (GPG_ERR_BUG);
    }
  rc = gcry_sexp_sscan (&s_sig, NULL, (char*)sigval, n);
  if (rc)
    {
      log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
      return rc;
    }

  p = ksba_cert_get_public_key (cert);
  n = gcry_sexp_canon_len (p, 0, NULL, NULL);
  if (!n)
    {
      log_error ("libksba did not return a proper S-Exp\n");
      ksba_free (p);
      gcry_sexp_release (s_sig);
      return gpg_error (GPG_ERR_BUG);
    }
  if (DBG_CRYPTO)
    log_printhex ("public key: ", p, n);

  rc = gcry_sexp_sscan ( &s_pkey, NULL, (char*)p, n);
  ksba_free (p);
  if (rc)
    {
      log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
      gcry_sexp_release (s_sig);
      return rc;
    }

  pkalgo = pk_algo_from_sexp (s_pkey);
  if (r_pkalgo)
    *r_pkalgo = pkalgo;
  rc = do_encode_md (md, mdalgo, pkalgo,
                     gcry_pk_get_nbits (s_pkey), s_pkey, &frame);
  if (rc)
    {
      gcry_sexp_release (s_sig);
      gcry_sexp_release (s_pkey);
      return rc;
    }
  /* put hash into the S-Exp s_hash */
  if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) )
    BUG ();
  gcry_mpi_release (frame);

  rc = gcry_pk_verify (s_sig, s_hash, s_pkey);
  if (DBG_X509)
      log_debug ("gcry_pk_verify: %s\n", gpg_strerror (rc));
  gcry_sexp_release (s_sig);
  gcry_sexp_release (s_hash);
  gcry_sexp_release (s_pkey);
  return rc;
}
Esempio n. 16
0
/* Read the key identified by GRIP from the private key directory and
   return it as an gcrypt S-expression object in RESULT.  On failure
   returns an error code and stores NULL at RESULT. */
static gpg_error_t
read_key_file (const unsigned char *grip, gcry_sexp_t *result)
{
  int rc;
  char *fname;
  estream_t fp;
  struct stat st;
  unsigned char *buf;
  size_t buflen, erroff;
  gcry_sexp_t s_skey;
  char hexgrip[40+4+1];
  char first;

  *result = NULL;

  bin2hex (grip, 20, hexgrip);
  strcpy (hexgrip+40, ".key");

  fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
  fp = es_fopen (fname, "rb");
  if (!fp)
    {
      rc = gpg_error_from_syserror ();
      if (gpg_err_code (rc) != GPG_ERR_ENOENT)
        log_error ("can't open '%s': %s\n", fname, strerror (errno));
      xfree (fname);
      return rc;
    }

  if (es_fread (&first, 1, 1, fp) != 1)
    {
      rc = gpg_error_from_syserror ();
      log_error ("error reading first byte from '%s': %s\n",
                 fname, strerror (errno));
      xfree (fname);
      es_fclose (fp);
      return rc;
    }

  rc = es_fseek (fp, 0, SEEK_SET);
  if (rc)
    {
      log_error ("error seeking in '%s': %s\n", fname, strerror (errno));
      xfree (fname);
      es_fclose (fp);
      return rc;
    }

  if (first != '(')
    {
      /* Key is in extended format.  */
      pkc_t pk;
      int line;

      rc = pkc_parse (&pk, &line, fp);
      es_fclose (fp);

      if (rc)
        log_error ("error parsing '%s' line %d: %s\n",
                   fname, line, gpg_strerror (rc));
      else
        {
          rc = pkc_get_private_key (pk, result);
          pkc_release (pk);
          if (rc)
            log_error ("error getting private key from '%s': %s\n",
                       fname, gpg_strerror (rc));
        }

      xfree (fname);
      return rc;
    }

  if (fstat (es_fileno (fp), &st))
    {
      rc = gpg_error_from_syserror ();
      log_error ("can't stat '%s': %s\n", fname, strerror (errno));
      xfree (fname);
      es_fclose (fp);
      return rc;
    }

  buflen = st.st_size;
  buf = xtrymalloc (buflen+1);
  if (!buf)
    {
      rc = gpg_error_from_syserror ();
      log_error ("error allocating %zu bytes for '%s': %s\n",
                 buflen, fname, strerror (errno));
      xfree (fname);
      es_fclose (fp);
      xfree (buf);
      return rc;

    }

  if (es_fread (buf, buflen, 1, fp) != 1)
    {
      rc = gpg_error_from_syserror ();
      log_error ("error reading %zu bytes from '%s': %s\n",
                 buflen, fname, strerror (errno));
      xfree (fname);
      es_fclose (fp);
      xfree (buf);
      return rc;
    }

  /* Convert the file into a gcrypt S-expression object.  */
  rc = gcry_sexp_sscan (&s_skey, &erroff, (char*)buf, buflen);
  xfree (fname);
  es_fclose (fp);
  xfree (buf);
  if (rc)
    {
      log_error ("failed to build S-Exp (off=%u): %s\n",
                 (unsigned int)erroff, gpg_strerror (rc));
      return rc;
    }
  *result = s_skey;
  return 0;
}
Esempio n. 17
0
static gpg_error_t
write_extended_private_key (char *fname, estream_t fp,
                            const void *buf, size_t len)
{
  gpg_error_t err;
  pkc_t pk = NULL;
  gcry_sexp_t key = NULL;
  int remove = 0;
  int line;

  err = pkc_parse (&pk, &line, fp);
  if (err)
    {
      log_error ("error parsing '%s' line %d: %s\n",
                 fname, line, gpg_strerror (err));
      goto leave;
    }

  err = gcry_sexp_sscan (&key, NULL, buf, len);
  if (err)
    goto leave;

  err = pkc_set_private_key (pk, key);
  if (err)
    goto leave;

  err = es_fseek (fp, 0, SEEK_SET);
  if (err)
    goto leave;

  err = pkc_write (pk, fp);
  if (err)
    {
      log_error ("error writing '%s': %s\n", fname, gpg_strerror (err));
      remove = 1;
      goto leave;
    }

  if (ftruncate (es_fileno (fp), es_ftello (fp)))
    {
      err = gpg_error_from_syserror ();
      log_error ("error truncating '%s': %s\n", fname, gpg_strerror (err));
      remove = 1;
      goto leave;
    }

  if (es_fclose (fp))
    {
      err = gpg_error_from_syserror ();
      log_error ("error closing '%s': %s\n", fname, gpg_strerror (err));
      remove = 1;
      goto leave;
    }
  else
    fp = NULL;

  bump_key_eventcounter ();

 leave:
  if (fp)
    es_fclose (fp);
  if (remove)
    gnupg_remove (fname);
  xfree (fname);
  gcry_sexp_release (key);
  pkc_release (pk);
  return err;
}
Esempio n. 18
0
/* Read the key identified by GRIP from the private key directory and
   return it as an gcrypt S-expression object in RESULT.  On failure
   returns an error code and stores NULL at RESULT. */
static gpg_error_t
read_key_file (const unsigned char *grip, gcry_sexp_t *result)
{
  int rc;
  char *fname;
  FILE *fp;
  struct stat st;
  unsigned char *buf;
  size_t buflen, erroff;
  gcry_sexp_t s_skey;
  char hexgrip[40+4+1];

  *result = NULL;

  bin2hex (grip, 20, hexgrip);
  strcpy (hexgrip+40, ".key");

  fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
  fp = fopen (fname, "rb");
  if (!fp)
    {
      rc = gpg_error_from_syserror ();
      if (gpg_err_code (rc) != GPG_ERR_ENOENT)
        log_error ("can't open `%s': %s\n", fname, strerror (errno));
      xfree (fname);
      return rc;
    }

  if (fstat (fileno(fp), &st))
    {
      rc = gpg_error_from_syserror ();
      log_error ("can't stat `%s': %s\n", fname, strerror (errno));
      xfree (fname);
      fclose (fp);
      return rc;
    }

  buflen = st.st_size;
  buf = xtrymalloc (buflen+1);
  if (!buf || fread (buf, buflen, 1, fp) != 1)
    {
      rc = gpg_error_from_syserror ();
      log_error ("error reading `%s': %s\n", fname, strerror (errno));
      xfree (fname);
      fclose (fp);
      xfree (buf);
      return rc;
    }

  /* Convert the file into a gcrypt S-expression object.  */
  rc = gcry_sexp_sscan (&s_skey, &erroff, (char*)buf, buflen);
  xfree (fname);
  fclose (fp);
  xfree (buf);
  if (rc)
    {
      log_error ("failed to build S-Exp (off=%u): %s\n",
                 (unsigned int)erroff, gpg_strerror (rc));
      return rc;
    }
  *result = s_skey;
  return 0;
}
Esempio n. 19
0
/* Return the secret key as an S-Exp in RESULT after locating it using
   the GRIP.  Stores NULL at RESULT if the operation shall be diverted
   to a token; in this case an allocated S-expression with the
   shadow_info part from the file is stored at SHADOW_INFO.
   CACHE_MODE defines now the cache shall be used.  DESC_TEXT may be
   set to present a custom description for the pinentry.  LOOKUP_TTL
   is an optional function to convey a TTL to the cache manager; we do
   not simply pass the TTL value because the value is only needed if an
   unprotect action was needed and looking up the TTL may have some
   overhead (e.g. scanning the sshcontrol file). */
gpg_error_t
agent_key_from_file (ctrl_t ctrl, const char *desc_text,
                     const unsigned char *grip, unsigned char **shadow_info,
                     cache_mode_t cache_mode, lookup_ttl_t lookup_ttl,
                     gcry_sexp_t *result)
{
  int rc;
  unsigned char *buf;
  size_t len, buflen, erroff;
  gcry_sexp_t s_skey;
  int got_shadow_info = 0;

  *result = NULL;
  if (shadow_info)
    *shadow_info = NULL;

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

  /* For use with the protection functions we also need the key as an
     canonical encoded S-expression in a buffer.  Create this buffer
     now.  */
  rc = make_canon_sexp (s_skey, &buf, &len);
  if (rc)
    return rc;

  switch (agent_private_key_type (buf))
    {
    case PRIVATE_KEY_CLEAR:
      break; /* no unprotection needed */
    case PRIVATE_KEY_PROTECTED:
      {
	char *desc_text_final;
	char *comment = NULL;

        /* Note, that we will take the comment as a C string for
           display purposes; i.e. all stuff beyond a Nul character is
           ignored.  */
        {
          gcry_sexp_t comment_sexp;

          comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
          if (comment_sexp)
            comment = gcry_sexp_nth_string (comment_sexp, 1);
          gcry_sexp_release (comment_sexp);
        }

        desc_text_final = NULL;
	if (desc_text)
          rc = modify_description (desc_text, comment? comment:"", s_skey,
                                   &desc_text_final);
        gcry_free (comment);

	if (!rc)
	  {
	    rc = unprotect (ctrl, desc_text_final, &buf, grip,
                            cache_mode, lookup_ttl);
	    if (rc)
	      log_error ("failed to unprotect the secret key: %s\n",
			 gpg_strerror (rc));
	  }

	xfree (desc_text_final);
      }
      break;
    case PRIVATE_KEY_SHADOWED:
      if (shadow_info)
        {
          const unsigned char *s;
          size_t n;

          rc = agent_get_shadow_info (buf, &s);
          if (!rc)
            {
              n = gcry_sexp_canon_len (s, 0, NULL,NULL);
              assert (n);
              *shadow_info = xtrymalloc (n);
              if (!*shadow_info)
                rc = out_of_core ();
              else
                {
                  memcpy (*shadow_info, s, n);
                  rc = 0;
                  got_shadow_info = 1;
                }
            }
          if (rc)
            log_error ("get_shadow_info failed: %s\n", gpg_strerror (rc));
        }
      else
        rc = gpg_error (GPG_ERR_UNUSABLE_SECKEY);
      break;
    default:
      log_error ("invalid private key format\n");
      rc = gpg_error (GPG_ERR_BAD_SECKEY);
      break;
    }
  gcry_sexp_release (s_skey);
  s_skey = NULL;
  if (rc || got_shadow_info)
    {
      xfree (buf);
      return rc;
    }

  buflen = gcry_sexp_canon_len (buf, 0, NULL, NULL);
  rc = gcry_sexp_sscan (&s_skey, &erroff, (char*)buf, buflen);
  wipememory (buf, buflen);
  xfree (buf);
  if (rc)
    {
      log_error ("failed to build S-Exp (off=%u): %s\n",
                 (unsigned int)erroff, gpg_strerror (rc));
      return rc;
    }

  *result = s_skey;
  return 0;
}
Esempio n. 20
0
/* Unprotect the canconical encoded S-expression key in KEYBUF.  GRIP
   should be the hex encoded keygrip of that key to be used with the
   caching mechanism. DESC_TEXT may be set to override the default
   description used for the pinentry.  If LOOKUP_TTL is given this
   function is used to lookup the default ttl. */
static int
unprotect (ctrl_t ctrl, const char *desc_text,
           unsigned char **keybuf, const unsigned char *grip,
           cache_mode_t cache_mode, lookup_ttl_t lookup_ttl)
{
  struct pin_entry_info_s *pi;
  struct try_unprotect_arg_s arg;
  int rc;
  unsigned char *result;
  size_t resultlen;
  char hexgrip[40+1];

  bin2hex (grip, 20, hexgrip);

  /* First try to get it from the cache - if there is none or we can't
     unprotect it, we fall back to ask the user */
  if (cache_mode != CACHE_MODE_IGNORE)
    {
      void *cache_marker;
      const char *pw;

    retry:
      pw = agent_get_cache (hexgrip, cache_mode, &cache_marker);
      if (pw)
        {
          rc = agent_unprotect (*keybuf, pw, NULL, &result, &resultlen);
          agent_unlock_cache_entry (&cache_marker);
          if (!rc)
            {
              xfree (*keybuf);
              *keybuf = result;
              return 0;
            }
          rc  = 0;
        }

      /* If the pinentry is currently in use, we wait up to 60 seconds
         for it to close and check the cache again.  This solves a common
         situation where several requests for unprotecting a key have
         been made but the user is still entering the passphrase for
         the first request.  Because all requests to agent_askpin are
         serialized they would then pop up one after the other to
         request the passphrase - despite that the user has already
         entered it and is then available in the cache.  This
         implementation is not race free but in the worst case the
         user has to enter the passphrase only once more. */
      if (pinentry_active_p (ctrl, 0))
        {
          /* Active - wait */
          if (!pinentry_active_p (ctrl, 60))
            {
              /* We need to give the other thread a chance to actually put
                 it into the cache. */
              pth_sleep (1);
              goto retry;
            }
          /* Timeout - better call pinentry now the plain way. */
        }
    }

  pi = gcry_calloc_secure (1, sizeof (*pi) + 100);
  if (!pi)
    return gpg_error_from_syserror ();
  pi->max_length = 100;
  pi->min_digits = 0;  /* we want a real passphrase */
  pi->max_digits = 16;
  pi->max_tries = 3;
  pi->check_cb = try_unprotect_cb;
  arg.ctrl = ctrl;
  arg.protected_key = *keybuf;
  arg.unprotected_key = NULL;
  arg.change_required = 0;
  pi->check_cb_arg = &arg;

  rc = agent_askpin (ctrl, desc_text, NULL, NULL, pi);
  if (!rc)
    {
      assert (arg.unprotected_key);
      if (arg.change_required)
        {
          size_t canlen, erroff;
          gcry_sexp_t s_skey;

          assert (arg.unprotected_key);
          canlen = gcry_sexp_canon_len (arg.unprotected_key, 0, NULL, NULL);
          rc = gcry_sexp_sscan (&s_skey, &erroff,
                                (char*)arg.unprotected_key, canlen);
          if (rc)
            {
              log_error ("failed to build S-Exp (off=%u): %s\n",
                         (unsigned int)erroff, gpg_strerror (rc));
              wipememory (arg.unprotected_key, canlen);
              xfree (arg.unprotected_key);
              xfree (pi);
              return rc;
            }
          rc = agent_protect_and_store (ctrl, s_skey);
          gcry_sexp_release (s_skey);
          if (rc)
            {
              log_error ("changing the passphrase failed: %s\n",
                         gpg_strerror (rc));
              wipememory (arg.unprotected_key, canlen);
              xfree (arg.unprotected_key);
              xfree (pi);
              return rc;
            }
        }
      else
        agent_put_cache (hexgrip, cache_mode, pi->pin,
                         lookup_ttl? lookup_ttl (hexgrip) : 0);
      xfree (*keybuf);
      *keybuf = arg.unprotected_key;
    }
  xfree (pi);
  return rc;
}
Esempio n. 21
0
/* Return true if the key in BLOB matches the 20 bytes keygrip GRIP.
   We don't have the keygrips as meta data, thus we need to parse the
   certificate. Fixme: We might want to return proper error codes
   instead of failing a search for invalid certificates etc.  */
static int
blob_x509_has_grip (KEYBOXBLOB blob, const unsigned char *grip)
{
  int rc;
  const unsigned char *buffer;
  size_t length;
  size_t cert_off, cert_len;
  ksba_reader_t reader = NULL;
  ksba_cert_t cert = NULL;
  ksba_sexp_t p = NULL;
  gcry_sexp_t s_pkey;
  unsigned char array[20];
  unsigned char *rcp;
  size_t n;

  buffer = _keybox_get_blob_image (blob, &length);
  if (length < 40)
    return 0; /* Too short. */
  cert_off = get32 (buffer+8);
  cert_len = get32 (buffer+12);
  if (cert_off+cert_len > length)
    return 0; /* Too short.  */

  rc = ksba_reader_new (&reader);
  if (rc)
    return 0; /* Problem with ksba. */
  rc = ksba_reader_set_mem (reader, buffer+cert_off, cert_len);
  if (rc)
    goto failed;
  rc = ksba_cert_new (&cert);
  if (rc)
    goto failed;
  rc = ksba_cert_read_der (cert, reader);
  if (rc)
    goto failed;
  p = ksba_cert_get_public_key (cert);
  if (!p)
    goto failed;
  n = gcry_sexp_canon_len (p, 0, NULL, NULL);
  if (!n)
    goto failed;
  rc = gcry_sexp_sscan (&s_pkey, NULL, (char*)p, n);
  if (rc)
    {
      gcry_sexp_release (s_pkey);
      goto failed;
    }
  rcp = gcry_pk_get_keygrip (s_pkey, array);
  gcry_sexp_release (s_pkey);
  if (!rcp)
    goto failed; /* Can't calculate keygrip. */

  xfree (p);
  ksba_cert_release (cert);
  ksba_reader_release (reader);
  return !memcmp (array, grip, 20);
 failed:
  xfree (p);
  ksba_cert_release (cert);
  ksba_reader_release (reader);
  return 0;
}
Esempio n. 22
0
/* Test the public key sign function using the private ket SKEY. PKEY
   is used for verification. */
static void
check_pubkey_sign (int n, gcry_sexp_t skey, gcry_sexp_t pkey)
{
  gcry_error_t rc;
  gcry_sexp_t sig, badhash, hash;
  int dataidx;
  static const char baddata[] =
    "(data\n (flags pkcs1)\n"
    " (hash sha1 #11223344556677889900AABBCCDDEEFF10203041#))\n";
  static struct
  {
    const char *data;
    int expected_rc;
  } datas[] =
    {
      { "(data\n (flags pkcs1)\n"
	" (hash sha1 #11223344556677889900AABBCCDDEEFF10203040#))\n",
	0 },
      {	"(data\n (flags )\n"
	" (hash sha1 #11223344556677889900AABBCCDDEEFF10203040#))\n",
	GPG_ERR_CONFLICT },
      {	"(data\n (flags pkcs1)\n"
	" (hash foo #11223344556677889900AABBCCDDEEFF10203040#))\n",
	GPG_ERR_DIGEST_ALGO },
      {	"(data\n (flags )\n" " (value #11223344556677889900AA#))\n",
	0 },
      { "(data\n (flags raw)\n" " (value #11223344556677889900AA#))\n",
	0 },
      {	"(data\n (flags pkcs1)\n"
	" (value #11223344556677889900AA#))\n",
	GPG_ERR_CONFLICT },
      { "(data\n (flags raw foo)\n"
	" (value #11223344556677889900AA#))\n",
	GPG_ERR_INV_FLAG },
      { NULL }
    };

  rc = gcry_sexp_sscan (&badhash, NULL, baddata, strlen (baddata));
  if (rc)
    die ("converting data failed: %s\n", gpg_strerror (rc));

  for (dataidx = 0; datas[dataidx].data; dataidx++)
    {
      if (verbose)
	fprintf (stderr, "signature test %d\n", dataidx);

      rc = gcry_sexp_sscan (&hash, NULL, datas[dataidx].data,
			    strlen (datas[dataidx].data));
      if (rc)
	die ("converting data failed: %s\n", gpg_strerror (rc));

      rc = gcry_pk_sign (&sig, hash, skey);
      if (gcry_err_code (rc) != datas[dataidx].expected_rc)
	fail ("gcry_pk_sign failed: %s\n", gpg_strerror (rc));

      if (!rc)
	verify_one_signature (pkey, hash, badhash, sig);

      gcry_sexp_release (sig);
      sig = NULL;
      gcry_sexp_release (hash);
      hash = NULL;
    }

  gcry_sexp_release (badhash);
}
Esempio n. 23
0
static void
dsa_bench (int iterations, int print_header)
{
  gpg_error_t err;
  gcry_sexp_t pub_key[3], sec_key[3];
  int p_sizes[3] = { 1024, 2048, 3072 };
  int q_sizes[3] = { 160, 224, 256 };
  gcry_sexp_t data;
  gcry_sexp_t sig = NULL;
  int i, j;

  err = gcry_sexp_sscan (pub_key+0, NULL, sample_public_dsa_key_1024,
                         strlen (sample_public_dsa_key_1024));
  if (!err)
    err = gcry_sexp_sscan (sec_key+0, NULL, sample_private_dsa_key_1024,
                           strlen (sample_private_dsa_key_1024));
  if (!err)
    err = gcry_sexp_sscan (pub_key+1, NULL, sample_public_dsa_key_2048,
                           strlen (sample_public_dsa_key_2048));
  if (!err)
    err = gcry_sexp_sscan (sec_key+1, NULL, sample_private_dsa_key_2048,
                           strlen (sample_private_dsa_key_2048));
  if (!err)
    err = gcry_sexp_sscan (pub_key+2, NULL, sample_public_dsa_key_3072,
                           strlen (sample_public_dsa_key_3072));
  if (!err)
    err = gcry_sexp_sscan (sec_key+2, NULL, sample_private_dsa_key_3072,
                           strlen (sample_private_dsa_key_3072));
  if (err)
    {
      fprintf (stderr, PGM ": converting sample keys failed: %s\n",
               gcry_strerror (err));
      exit (1);
    }

  if (print_header)
    printf ("Algorithm         generate %4d*sign %4d*verify\n"
            "------------------------------------------------\n",
            iterations, iterations );
  for (i=0; i < DIM (q_sizes); i++)
    {
      gcry_mpi_t x;

      x = gcry_mpi_new (q_sizes[i]);
      gcry_mpi_randomize (x, q_sizes[i], GCRY_WEAK_RANDOM);
      err = gcry_sexp_build (&data, NULL, "(data (flags raw) (value %m))", x);
      gcry_mpi_release (x);
      if (err)
        {
          fprintf (stderr, PGM ": converting data failed: %s\n",
                   gcry_strerror (err));
          exit (1);
        }

      printf ("DSA %d/%d             -", p_sizes[i], q_sizes[i]);
      fflush (stdout);

      start_timer ();
      for (j=0; j < iterations; j++)
        {
          gcry_sexp_release (sig);
          err = gcry_pk_sign (&sig, data, sec_key[i]);
          if (err)
            {
              putchar ('\n');
              fprintf (stderr, PGM ": signing failed: %s\n",
                       gpg_strerror (err));
              exit (1);
            }
        }
      stop_timer ();
      printf ("   %s", elapsed_time ());
      fflush (stdout);

      start_timer ();
      for (j=0; j < iterations; j++)
        {
          err = gcry_pk_verify (sig, data, pub_key[i]);
          if (err)
            {
              putchar ('\n');
              fprintf (stderr, PGM ": verify failed: %s\n",
                       gpg_strerror (err));
              exit (1);
            }
        }
      stop_timer ();
      printf ("     %s\n", elapsed_time ());
      fflush (stdout);

      gcry_sexp_release (sig);
      gcry_sexp_release (data);
      sig = NULL;
    }


  for (i=0; i < DIM (q_sizes); i++)
    {
      gcry_sexp_release (sec_key[i]);
      gcry_sexp_release (pub_key[i]);
    }
}
Esempio n. 24
0
/* Check the signature on CERT using the ISSUER-CERT.  This function
   does only test the cryptographic signature and nothing else.  It is
   assumed that the ISSUER_CERT is valid. */
int
gpgsm_check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert)
{
  const char *algoid;
  gcry_md_hd_t md;
  int rc, algo;
  gcry_mpi_t frame;
  ksba_sexp_t p;
  size_t n;
  gcry_sexp_t s_sig, s_hash, s_pkey;

  algo = gcry_md_map_name ( (algoid=ksba_cert_get_digest_algo (cert)));
  if (!algo)
    {
      log_error ("unknown hash algorithm '%s'\n", algoid? algoid:"?");
      if (algoid
          && (  !strcmp (algoid, "1.2.840.113549.1.1.2")
                ||!strcmp (algoid, "1.2.840.113549.2.2")))
        log_info (_("(this is the MD2 algorithm)\n"));
      return gpg_error (GPG_ERR_GENERAL);
    }
  rc = gcry_md_open (&md, algo, 0);
  if (rc)
    {
      log_error ("md_open failed: %s\n", gpg_strerror (rc));
      return rc;
    }
  if (DBG_HASHING)
    gcry_md_debug (md, "hash.cert");

  rc = ksba_cert_hash (cert, 1, HASH_FNC, md);
  if (rc)
    {
      log_error ("ksba_cert_hash failed: %s\n", gpg_strerror (rc));
      gcry_md_close (md);
      return rc;
    }
  gcry_md_final (md);

  p = ksba_cert_get_sig_val (cert);
  n = gcry_sexp_canon_len (p, 0, NULL, NULL);
  if (!n)
    {
      log_error ("libksba did not return a proper S-Exp\n");
      gcry_md_close (md);
      ksba_free (p);
      return gpg_error (GPG_ERR_BUG);
    }
  if (DBG_CRYPTO)
    {
      int j;
      log_debug ("signature value:");
      for (j=0; j < n; j++)
        log_printf (" %02X", p[j]);
      log_printf ("\n");
    }

  rc = gcry_sexp_sscan ( &s_sig, NULL, (char*)p, n);
  ksba_free (p);
  if (rc)
    {
      log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
      gcry_md_close (md);
      return rc;
    }

  p = ksba_cert_get_public_key (issuer_cert);
  n = gcry_sexp_canon_len (p, 0, NULL, NULL);
  if (!n)
    {
      log_error ("libksba did not return a proper S-Exp\n");
      gcry_md_close (md);
      ksba_free (p);
      gcry_sexp_release (s_sig);
      return gpg_error (GPG_ERR_BUG);
    }
  rc = gcry_sexp_sscan ( &s_pkey, NULL, (char*)p, n);
  ksba_free (p);
  if (rc)
    {
      log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
      gcry_md_close (md);
      gcry_sexp_release (s_sig);
      return rc;
    }

  rc = do_encode_md (md, algo, pk_algo_from_sexp (s_pkey),
                     gcry_pk_get_nbits (s_pkey), s_pkey, &frame);
  if (rc)
    {
      gcry_md_close (md);
      gcry_sexp_release (s_sig);
      gcry_sexp_release (s_pkey);
      return rc;
    }

  /* put hash into the S-Exp s_hash */
  if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) )
    BUG ();
  gcry_mpi_release (frame);


  rc = gcry_pk_verify (s_sig, s_hash, s_pkey);
  if (DBG_X509)
      log_debug ("gcry_pk_verify: %s\n", gpg_strerror (rc));
  gcry_md_close (md);
  gcry_sexp_release (s_sig);
  gcry_sexp_release (s_hash);
  gcry_sexp_release (s_pkey);
  return rc;
}