Example #1
0
/* This function gets the signature parameters and encodes
 * them into a way for _gnutls_pk_verify to use.
 */
static cdk_error_t
sig_to_datum (gnutls_datum_t * r_sig, cdk_pkt_signature_t sig)
{
    int err;
    cdk_error_t rc;

    if (!r_sig || !sig)
        return CDK_Inv_Value;

    rc = 0;
    if (is_RSA (sig->pubkey_algo))
    {
        err = _gnutls_mpi_dprint (sig->mpi[0], r_sig);
        if (err < 0)
            rc = map_gnutls_error (err);
    }
    else if (is_DSA (sig->pubkey_algo))
    {
        err = _gnutls_encode_ber_rs (r_sig, sig->mpi[0], sig->mpi[1]);
        if (err < 0)
            rc = map_gnutls_error (err);
    }
    else
        rc = CDK_Inv_Algo;
    return rc;
}
Example #2
0
/* Hash all multi precision integers of the key PK with the given
   message digest context MD. */
static int
hash_mpibuf (cdk_pubkey_t pk, digest_hd_st * md, int usefpr)
{
  byte buf[MAX_MPI_BYTES];	/* FIXME: do not use hardcoded length. */
  size_t nbytes;
  size_t i, npkey;
  int err;

  /* We have to differ between two modes for v3 keys. To form the
     fingerprint, we hash the MPI values without the length prefix.
     But if we calculate the hash for verifying/signing we use all data. */
  npkey = cdk_pk_get_npkey (pk->pubkey_algo);
  for (i = 0; i < npkey; i++)
    {
      nbytes = MAX_MPI_BYTES;
      err = _gnutls_mpi_print_pgp (pk->mpi[i], buf, &nbytes);
      if (err < 0)
	return map_gnutls_error (err);
      if (!usefpr || pk->version == 4)
	_gnutls_hash (md, buf, nbytes);
      else			/* without the prefix. */
	_gnutls_hash (md, buf + 2, nbytes - 2);
    }
  return 0;
}
Example #3
0
/**
 * cdk_pk_get_fingerprint:
 * @pk: the public key
 * @fpr: the buffer to hold the fingerprint
 *
 * Return the fingerprint of the given public key.
 * The buffer must be at least 20 octets.
 * This function should be considered deprecated and
 * the new cdk_pk_to_fingerprint() should be used whenever
 * possible to avoid overflows.
 **/
cdk_error_t
cdk_pk_get_fingerprint (cdk_pubkey_t pk, byte * fpr)
{
    digest_hd_st hd;
    int md_algo;
    int dlen = 0;
    int err;

    if (!pk || !fpr)
        return CDK_Inv_Value;

    if (pk->version < 4 && is_RSA (pk->pubkey_algo))
        md_algo = GNUTLS_DIG_MD5;   /* special */
    else
        md_algo = GNUTLS_DIG_SHA1;
    dlen = _gnutls_hash_get_algo_len (md_algo);
    err = _gnutls_hash_init (&hd, md_algo);
    if (err < 0)
    {
        gnutls_assert ();
        return map_gnutls_error (err);
    }
    _cdk_hash_pubkey (pk, &hd, 1);
    _gnutls_hash_deinit (&hd, fpr);
    if (dlen == 16)
        memset (fpr + 16, 0, 4);
    return 0;
}
Example #4
0
/* You can use a NULL buf to get the output size only
 */
static cdk_error_t
mpi_to_buffer (bigint_t a, byte * buf, size_t buflen,
               size_t * r_nwritten, size_t * r_nbits)
{
    size_t nbits;
    int err;

    if (!a || !r_nwritten)
    {
        gnutls_assert ();
        return CDK_Inv_Value;
    }

    nbits = _gnutls_mpi_get_nbits (a);
    if (r_nbits)
        *r_nbits = nbits;

    if (r_nwritten)
        *r_nwritten = (nbits + 7) / 8 + 2;

    if ((nbits + 7) / 8 + 2 > buflen)
        return CDK_Too_Short;

    *r_nwritten = buflen;
    err = _gnutls_mpi_print (a, buf, r_nwritten);
    if (err < 0)
    {
        gnutls_assert ();
        return map_gnutls_error (err);
    }

    return 0;
}
Example #5
0
static int
write_mpi (cdk_stream_t out, bigint_t m)
{
  byte buf[MAX_MPI_BYTES + 2];
  size_t nbits, nread;
  int err;

  if (!out || !m)
    return CDK_Inv_Value;
  nbits = _gnutls_mpi_get_nbits (m);
  if (nbits > MAX_MPI_BITS || nbits < 1)
    return CDK_MPI_Error;

  nread = MAX_MPI_BYTES + 2;
  err = _gnutls_mpi_print_pgp (m, buf, &nread);
  if (err < 0)
    return map_gnutls_error (err);
  return stream_write (out, buf, nread);
}
Example #6
0
static cdk_error_t
read_mpi (cdk_stream_t inp, bigint_t * ret_m, int secure)
{
  bigint_t m;
  int err;
  byte buf[MAX_MPI_BYTES + 2];
  size_t nread, nbits;
  cdk_error_t rc;

  if (!inp || !ret_m)
    return CDK_Inv_Value;

  *ret_m = NULL;
  nbits = read_16 (inp);
  nread = (nbits + 7) / 8;

  if (nbits > MAX_MPI_BITS || nbits == 0)
    {
      _cdk_log_debug ("read_mpi: too large %d bits\n", nbits);
      return CDK_MPI_Error;	/* Sanity check */
    }

  rc = stream_read (inp, buf + 2, nread, &nread);
  if (!rc && nread != ((nbits + 7) / 8))
    {
      _cdk_log_debug ("read_mpi: too short %d < %d\n", nread,
		      (nbits + 7) / 8);
      return CDK_MPI_Error;
    }

  buf[0] = nbits >> 8;
  buf[1] = nbits >> 0;
  nread += 2;
  err = _gnutls_mpi_scan_pgp (&m, buf, nread);
  if (err < 0)
    return map_gnutls_error (err);

  *ret_m = m;
  return rc;
}
Example #7
0
File: hash.c Project: ares89/vlc
static cdk_error_t
hash_encode (void *data, FILE * in, FILE * out)
{
  md_filter_t *mfx = data;
  byte buf[BUFSIZE];
  int err;
  int nread;

  if (!mfx)
    {
      gnutls_assert ();
      return CDK_Inv_Value;
    }

  _cdk_log_debug ("hash filter: encode algo=%d\n", mfx->digest_algo);

  if (!mfx->md_initialized)
    {
      err = _gnutls_hash_init (&mfx->md, mfx->digest_algo);
      if (err < 0)
        {
          gnutls_assert ();
          return map_gnutls_error (err);
        }

      mfx->md_initialized = 1;
    }

  while (!feof (in))
    {
      nread = fread (buf, 1, BUFSIZE, in);
      if (!nread)
        break;
      _gnutls_hash (&mfx->md, buf, nread);
    }

  wipemem (buf, sizeof (buf));
  return 0;
}
Example #8
0
/**
 * cdk_pk_verify:
 * @pk: the public key
 * @sig: signature
 * @md: the message digest
 *
 * Verify the signature in @sig and compare it with the message digest in @md.
 **/
cdk_error_t
cdk_pk_verify (cdk_pubkey_t pk, cdk_pkt_signature_t sig, const byte * md)
{
    gnutls_datum_t s_sig;
    byte *encmd = NULL;
    size_t enclen;
    cdk_error_t rc;
    int ret, algo;
    unsigned int i;
    gnutls_datum_t data;
    gnutls_pk_params_st params;

    if (!pk || !sig || !md)
    {
        gnutls_assert ();
        return CDK_Inv_Value;
    }

    if (is_DSA (pk->pubkey_algo))
        algo = GNUTLS_PK_DSA;
    else if (is_RSA (pk->pubkey_algo))
        algo = GNUTLS_PK_RSA;
    else
    {
        gnutls_assert ();
        return CDK_Inv_Value;
    }

    rc = sig_to_datum (&s_sig, sig);
    if (rc)
    {
        gnutls_assert ();
        goto leave;
    }

    rc = _cdk_digest_encode_pkcs1 (&encmd, &enclen, pk->pubkey_algo, md,
                                   sig->digest_algo, cdk_pk_get_nbits (pk));
    if (rc)
    {
        gnutls_assert ();
        goto leave;
    }

    data.data = encmd;
    data.size = enclen;

    params.params_nr = cdk_pk_get_npkey (pk->pubkey_algo);
    for (i = 0; i < params.params_nr; i++)
        params.params[i] = pk->mpi[i];
    params.flags = 0;
    ret = _gnutls_pk_verify (algo, &data, &s_sig, &params);

    if (ret < 0)
    {
        gnutls_assert ();
        rc = map_gnutls_error (ret);
        goto leave;
    }

    rc = 0;

leave:
    _gnutls_free_datum (&s_sig);
    cdk_free (encmd);
    return rc;
}
Example #9
0
static cdk_error_t
file_verify_clearsign (cdk_ctx_t hd, const char *file, const char *output)
{
  cdk_stream_t inp = NULL, out = NULL, tmp = NULL;
  digest_hd_st md;
  char buf[512], chk[512];
  const char *s;
  int i, is_signed = 0, nbytes;
  int digest_algo = 0;
  int err;
  cdk_error_t rc;

  memset(&md, 0, sizeof(md));

  if (output)
    {
      rc = cdk_stream_create (output, &out);
      if (rc)
	return rc;
    }

  rc = cdk_stream_open (file, &inp);
  if (rc)
    {
      if (output)
	cdk_stream_close (out);
      return rc;
    }

  s = "-----BEGIN PGP SIGNED MESSAGE-----";
  while (!cdk_stream_eof (inp))
    {
      nbytes = _cdk_stream_gets (inp, buf, DIM (buf) - 1);
      if (!nbytes || nbytes == -1)
	break;
      if (!strncmp (buf, s, strlen (s)))
	{
	  is_signed = 1;
	  break;
	}
    }

  if (cdk_stream_eof (inp) && !is_signed)
    {
      rc = CDK_Armor_Error;
      goto leave;
    }

  while (!cdk_stream_eof (inp))
    {
      nbytes = _cdk_stream_gets (inp, buf, DIM (buf) - 1);
      if (!nbytes || nbytes == -1)
	break;
      if (nbytes == 1)		/* Empty line */
	break;
      else if (!strncmp (buf, "Hash: ", 6))
	{
	  for (i = 0; digest_table[i].name; i++)
	    {
	      if (!strcmp (buf + 6, digest_table[i].name))
		{
		  digest_algo = digest_table[i].algo;
		  break;
		}
	    }
	}
    }

  if (digest_algo && _gnutls_hash_get_algo_len (digest_algo) <= 0)
    {
      rc = CDK_Inv_Algo;
      goto leave;
    }

  if (!digest_algo)
    digest_algo = GNUTLS_DIG_MD5;

  err = _gnutls_hash_init (&md, digest_algo);
  if (err < 0)
    {
      rc = map_gnutls_error (err);
      goto leave;
    }

  s = "-----BEGIN PGP SIGNATURE-----";
  while (!cdk_stream_eof (inp))
    {
      nbytes = _cdk_stream_gets (inp, buf, DIM (buf) - 1);
      if (!nbytes || nbytes == -1)
	break;
      if (!strncmp (buf, s, strlen (s)))
	break;
      else
	{
	  cdk_stream_peek (inp, (byte *) chk, DIM (chk) - 1);
	  i = strncmp (chk, s, strlen (s));
	  if (strlen (buf) == 0 && i == 0)
	    continue;		/* skip last '\n' */
	  _cdk_trim_string (buf, i == 0 ? 0 : 1);
	  _gnutls_hash (&md, buf, strlen (buf));
	}
      if (!strncmp (buf, "- ", 2))	/* FIXME: handle it recursive. */
	memmove (buf, buf + 2, nbytes - 2);
      if (out)
	{
	  if (strstr (buf, "\r\n"))
	    buf[strlen (buf) - 2] = '\0';
	  cdk_stream_write (out, buf, strlen (buf));
	  _cdk_stream_puts (out, _cdk_armor_get_lineend ());
	}
    }

  /* We create a temporary stream object to store the
     signature data in there. */
  rc = cdk_stream_tmp_new (&tmp);
  if (rc)
    goto leave;

  s = "-----BEGIN PGP SIGNATURE-----\n";
  _cdk_stream_puts (tmp, s);
  while (!cdk_stream_eof (inp))
    {
      nbytes = _cdk_stream_gets (inp, buf, DIM (buf) - 1);
      if (!nbytes || nbytes == -1)
	break;
      if (nbytes < (int) (DIM (buf) - 3))
	{
	  buf[nbytes - 1] = '\n';
	  buf[nbytes] = '\0';
	}
      cdk_stream_write (tmp, buf, nbytes);
    }

  /* FIXME: This code is not very elegant. */
  cdk_stream_tmp_set_mode (tmp, STREAMCTL_READ);
  cdk_stream_seek (tmp, 0);
  cdk_stream_set_armor_flag (tmp, 0);
  cdk_stream_read (tmp, NULL, 0);

  /* the digest handle will be closed there. */
  rc = _cdk_proc_packets (hd, tmp, NULL, NULL, NULL, &md);

leave:
  _gnutls_hash_deinit (&md, NULL);
  cdk_stream_close (out);
  cdk_stream_close (tmp);
  cdk_stream_close (inp);
  return rc;
}
Example #10
0
/**
 * cdk_pk_verify:
 * @pk: the public key
 * @sig: signature
 * @md: the message digest
 *
 * Verify the signature in @sig and compare it with the message digest in @md.
 **/
cdk_error_t
cdk_pk_verify(cdk_pubkey_t pk, cdk_pkt_signature_t sig, const byte * md)
{
	gnutls_datum_t s_sig = { NULL, 0 }, di = {
	NULL, 0};
	byte *encmd = NULL;
	cdk_error_t rc;
	int ret, algo;
	unsigned int i;
	gnutls_pk_params_st params;
	const mac_entry_st *me;

	if (!pk || !sig || !md) {
		gnutls_assert();
		return CDK_Inv_Value;
	}

	if (is_DSA(pk->pubkey_algo))
		algo = GNUTLS_PK_DSA;
	else if (is_RSA(pk->pubkey_algo))
		algo = GNUTLS_PK_RSA;
	else {
		gnutls_assert();
		return CDK_Inv_Value;
	}

	rc = sig_to_datum(&s_sig, sig);
	if (rc) {
		gnutls_assert();
		goto leave;
	}

	me = mac_to_entry(sig->digest_algo);
	rc = _gnutls_set_datum(&di, md, _gnutls_hash_get_algo_len(me));
	if (rc < 0) {
		rc = gnutls_assert_val(CDK_Out_Of_Core);
		goto leave;
	}

	rc = pk_prepare_hash(algo, me, &di);
	if (rc < 0) {
		rc = gnutls_assert_val(CDK_General_Error);
		goto leave;
	}

	params.params_nr = cdk_pk_get_npkey(pk->pubkey_algo);
	for (i = 0; i < params.params_nr; i++)
		params.params[i] = pk->mpi[i];
	params.flags = 0;
	ret = _gnutls_pk_verify(algo, &di, &s_sig, &params);

	if (ret < 0) {
		gnutls_assert();
		rc = map_gnutls_error(ret);
		goto leave;
	}

	rc = 0;

      leave:
	_gnutls_free_datum(&s_sig);
	_gnutls_free_datum(&di);
	cdk_free(encmd);
	return rc;
}