Exemplo n.º 1
0
void
hash_bench (char **argv, int argc)
{
  int i, algo;

  bench_print_section ("hash", "Hash");
  bench_print_header (14, "");

  if (argv && argc)
    {
      for (i = 0; i < argc; i++)
	{
	  algo = gcry_md_map_name (argv[i]);
	  if (algo)
	    _hash_bench (algo);
	}
    }
  else
    {
      for (i = 1; i < 400; i++)
	if (!gcry_md_test_algo (i))
	  _hash_bench (i);
    }

  bench_print_footer (14);
}
Exemplo n.º 2
0
int crypt_hash_init(struct crypt_hash **ctx, const char *name)
{
	struct crypt_hash *h;
	unsigned int flags = 0;

	assert(crypto_backend_initialised);

	h = malloc(sizeof(*h));
	if (!h)
		return -ENOMEM;

	h->hash_id = gcry_md_map_name(crypt_hash_compat_name(name, &flags));
	if (!h->hash_id) {
		free(h);
		return -EINVAL;
	}

	if (gcry_md_open(&h->hd, h->hash_id, flags)) {
		free(h);
		return -EINVAL;
	}

	h->hash_len = gcry_md_get_algo_dlen(h->hash_id);
	*ctx = h;
	return 0;
}
Exemplo n.º 3
0
int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
		    const void *buffer, size_t length)
{
	struct crypt_hmac *h;
	unsigned int flags = GCRY_MD_FLAG_HMAC;

	assert(crypto_backend_initialised);

	h = malloc(sizeof(*h));
	if (!h)
		return -ENOMEM;

	h->hash_id = gcry_md_map_name(crypt_hash_compat_name(name, &flags));
	if (!h->hash_id) {
		free(h);
		return -EINVAL;
	}

	if (gcry_md_open(&h->hd, h->hash_id, flags)) {
		free(h);
		return -EINVAL;
	}

	if (gcry_md_setkey(h->hd, buffer, length)) {
		gcry_md_close(h->hd);
		free(h);
		return -EINVAL;
	}

	h->hash_len = gcry_md_get_algo_dlen(h->hash_id);
	*ctx = h;
	return 0;
}
Exemplo n.º 4
0
/* PBKDF */
int crypt_pbkdf(const char *kdf, const char *hash,
		const char *password, size_t password_length,
		const char *salt, size_t salt_length,
		char *key, size_t key_length,
		unsigned int iterations)
{
	const char *hash_name = crypt_hash_compat_name(hash, NULL);

#if USE_INTERNAL_PBKDF2
	if (!kdf || strncmp(kdf, "pbkdf2", 6))
		return -EINVAL;

	return pkcs5_pbkdf2(hash_name, password, password_length, salt, salt_length,
			    iterations, key_length, key, 0);

#else /* USE_INTERNAL_PBKDF2 */
	int hash_id = gcry_md_map_name(hash_name);
	int kdf_id;

	if (!hash_id)
		return -EINVAL;

	if (kdf && !strncmp(kdf, "pbkdf2", 6))
		kdf_id = GCRY_KDF_PBKDF2;
	else
		return -EINVAL;

	if (gcry_kdf_derive(password, password_length, kdf_id, hash_id,
	    salt, salt_length, iterations, key_length, key))
		return -EINVAL;

	return 0;
#endif /* USE_INTERNAL_PBKDF2 */
}
Exemplo n.º 5
0
int crypt_hash_size(const char *name)
{
	const int hash_id = gcry_md_map_name(name);
	if (!hash_id)
		return -EINVAL;

	return gcry_md_get_algo_dlen(hash_id);
}
Exemplo n.º 6
0
static crypto_t _hash_new(crypto_t c, const gchar *algoname)
{
  c->algo = gcry_md_map_name(algoname);
  if (c->algo ==0)
    {
      return (_fail(c, g_strdup_printf("algorithm `%s' was not available",
                                       algoname)));
    }
  return (c);
}
Exemplo n.º 7
0
/* HASH */
int crypt_hash_size(const char *name)
{
	int hash_id;

	assert(crypto_backend_initialised);

	hash_id = gcry_md_map_name(crypt_hash_compat_name(name, NULL));
	if (!hash_id)
		return -EINVAL;

	return gcry_md_get_algo_dlen(hash_id);
}
Exemplo n.º 8
0
int my_hash(const char alg[], const unsigned char input[], const unsigned int input_len, unsigned char output[]) {
	int md = gcry_md_map_name(alg);
	unsigned int mdlen = gcry_md_get_algo_dlen(md);
	gchar *keybuf = g_new0(gchar, mdlen);
	memset(keybuf, 0, mdlen);
	gcry_md_hash_buffer(md, keybuf, input, input_len);
	
	//copy
	size_t i = 0;
	for(i = 0; i<mdlen; ++i) {
		output[i] = keybuf[ i%mdlen ];
	}
	return 0;
}
Exemplo n.º 9
0
int
P_hash(const char *digest, unsigned char *dest, int dlen, unsigned char *secret, int sslen,
       unsigned char *seed, int slen)
{
    unsigned char hmac[48];
    uint32_t hlen;
    gcry_md_hd_t md;
    uint32_t tmpslen;
    unsigned char tmpseed[slen];
    unsigned char *out = dest;
    int pending = dlen;
    int algo = gcry_md_map_name(digest);
    int algolen = gcry_md_get_algo_dlen(algo);

    // Copy initial seed
    memcpy(tmpseed, seed, slen);
    tmpslen = slen;

    // Calculate enough data to fill destination
    while (pending > 0) {
        gcry_md_open(&md, algo, GCRY_MD_FLAG_HMAC);
        gcry_md_setkey(md, secret, sslen);
        gcry_md_write(md, tmpseed, tmpslen);
        memcpy(tmpseed, gcry_md_read(md, algo), algolen);
        tmpslen = algolen;
        gcry_md_close(md);

        gcry_md_open(&md, algo, GCRY_MD_FLAG_HMAC);
        gcry_md_setkey(md, secret, sslen);
        gcry_md_write(md, tmpseed, tmpslen);
        gcry_md_write(md, seed, slen);
        memcpy(hmac, gcry_md_read(md, algo), algolen);
        hlen = algolen;

        hlen = (hlen > pending) ? pending : hlen;
        memcpy(out, hmac, hlen);
        out += hlen;
        pending -= hlen;
    }

    return hlen;
}
Exemplo n.º 10
0
/* Return the hash algorithm from a KSBA sig-val. SIGVAL is a
   canonical encoded S-expression.  Return 0 if the hash algorithm is
   not encoded in SIG-VAL or it is not supported by libgcrypt.  */
int
hash_algo_from_sigval (const unsigned char *sigval)
{
    const unsigned char *s = sigval;
    size_t n;
    int depth;
    char buffer[50];

    if (!s || *s != '(')
        return 0; /* Invalid S-expression.  */
    s++;
    n = snext (&s);
    if (!n)
        return 0; /* Invalid S-expression.  */
    if (!smatch (&s, n, "sig-val"))
        return 0; /* Not a sig-val.  */
    if (*s != '(')
        return 0; /* Invalid S-expression.  */
    s++;
    /* Skip over the algo+parameter list.  */
    depth = 1;
    if (sskip (&s, &depth) || depth)
        return 0; /* Invalid S-expression.  */
    if (*s != '(')
        return 0; /* No futher list.  */
    /* Check whether this is (hash ALGO).  */
    s++;
    n = snext (&s);
    if (!n)
        return 0; /* Invalid S-expression.  */
    if (!smatch (&s, n, "hash"))
        return 0; /* Not a "hash" keyword.  */
    n = snext (&s);
    if (!n || n+1 >= sizeof (buffer))
        return 0; /* Algorithm string is missing or too long.  */
    memcpy (buffer, s, n);
    buffer[n] = 0;

    return gcry_md_map_name (buffer);
}
Exemplo n.º 11
0
int crypt_hmac_init(crypt_hmac **ctx, const char *name, bool isHmac)
{
	unsigned int flags = isHmac ? GCRY_MD_FLAG_HMAC : 0;
	crypt_hmac *h = reinterpret_cast<crypt_hmac*>(malloc(sizeof(*h)));
	if (!h)
		return -ENOMEM;

	h->hash_id = gcry_md_map_name(name);
	if (!h->hash_id) {
		free(h);
		return -EINVAL;
	}

	if (gcry_md_open(&h->hd, h->hash_id, flags)) {
		free(h);
		return -EINVAL;
	}

	h->hash_len = gcry_md_get_algo_dlen(h->hash_id);
	*ctx = h;
	return 0;
}
Exemplo n.º 12
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;
}
Exemplo n.º 13
0
static int pkcs5_pbkdf2(const char *hash,
			const char *P, size_t Plen,
			const char *S, size_t Slen,
			unsigned int c, unsigned int dkLen,
			char *DK, int perfcheck)
{
	gcry_md_hd_t prf;
	char U[MAX_PRF_BLOCK_LEN];
	char T[MAX_PRF_BLOCK_LEN];
	int PRF, i, k, rc = -EINVAL;
	unsigned int u, hLen, l, r;
	unsigned char *p;
	size_t tmplen = Slen + 4;
	char *tmp;

	tmp = alloca(tmplen);
	if (tmp == NULL)
		return -ENOMEM;

	if (init_crypto())
		return -ENOSYS;

	PRF = gcry_md_map_name(hash);
	if (PRF == 0)
		return -EINVAL;

	hLen = gcry_md_get_algo_dlen(PRF);
	if (hLen == 0 || hLen > MAX_PRF_BLOCK_LEN)
		return -EINVAL;

	if (c == 0)
		return -EINVAL;

	if (dkLen == 0)
		return -EINVAL;

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

	if (dkLen > 4294967295U)
		return -EINVAL;

	/*
	 *     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.
	 *
	 */

	if(gcry_md_open(&prf, PRF, GCRY_MD_FLAG_HMAC))
		return -EINVAL;

	if (gcry_md_setkey(prf, P, Plen))
		goto out;

	for (i = 1; (uint) i <= l; i++) {
		memset(T, 0, hLen);

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

			if (u == 1) {
				memcpy(tmp, S, Slen);
				tmp[Slen + 0] = (i & 0xff000000) >> 24;
				tmp[Slen + 1] = (i & 0x00ff0000) >> 16;
				tmp[Slen + 2] = (i & 0x0000ff00) >> 8;
				tmp[Slen + 3] = (i & 0x000000ff) >> 0;

				gcry_md_write(prf, tmp, tmplen);
			} else {
				gcry_md_write(prf, U, hLen);
			}

			p = gcry_md_read(prf, PRF);
			if (p == NULL)
				goto out;

			memcpy(U, p, hLen);

			for (k = 0; (uint) k < hLen; k++)
				T[k] ^= U[k];

			if (perfcheck && __PBKDF2_performance) {
				rc = 0;
				goto out;
			}

			if (perfcheck)
				__PBKDF2_global_j++;
		}
Exemplo n.º 14
0
int main(int argc, char *argv[])
{
	static struct option long_options[] = {
		{ "block-size", required_argument, 0, 'b' },
		{ "hash-algo", required_argument, 0, 'h' },
		{ "hash-algorithm", required_argument, 0, 'h' },
		{ "max-iter", required_argument, 0, 'i' },
		{ "freeze", required_argument, 0, 'f' },
		{ "loop", no_argument, 0, 'l' },
		{ 0, 0, 0, 0 },
	};
	int i;
	int freeze_count = 0;

	gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);

	if (!gcry_check_version(GCRYPT_VERSION)) {
		fprintf(stderr, "libgcrypt version mismatch\n");
		return 1;
	}

	while (1) {
		int c;

		c = getopt_long(argc, argv, "b:h:i:f:l", long_options, NULL);
		if (c == -1)
			break;

		switch (c) {
		case 'b':
			if (sscanf(optarg, "%i", &block_size) != 1) {
				fprintf(stderr, "cannot parse block size: "
						"%s\n", optarg);
				return 1;
			}

			if ((block_size & 7) != 0) {
				fprintf(stderr, "error: block size must be "
						"a multiple of 8\n");
				return 1;
			}

			break;

		case 'h':
			hash_algo = gcry_md_map_name(optarg);
			if (hash_algo == 0) {
				fprintf(stderr, "unknown hash algorithm "
						"name: %s\n", optarg);
				return 1;
			}

			break;

		case 'i':
			if (sscanf(optarg, "%i", &max_iterations) != 1) {
				fprintf(stderr, "cannot parse iteration "
						"count: %s\n", optarg);
				return 1;
			}

			break;

		case 'f':
			if (freeze_count == MAX_FREEZE) {
				fprintf(stderr, "too many --freeze options\n");
				return 1;
			}

			freeze_fs[freeze_count++] = optarg;

			break;

		case 'l':
			loop = 1;
			break;

		case '?':
			return 1;

		default:
			abort();
		}
	}

	if (optind + 4 != argc) {
		fprintf(stderr, "%s: [opts] <src> <srchashmap> <dst> "
				"<dsthashmap>\n", argv[0]);
		fprintf(stderr, " -b, --block-size=SIZE    hash block size\n");
		fprintf(stderr, " -f, --freeze=MOUNTPOINT  freeze "
				"filesystem\n");
		fprintf(stderr, " -h, --hash-algo=ALGO     hash algorithm\n");
		fprintf(stderr, " -i, --max-iter=ITER      maximum number of "
				"iterations\n");
		fprintf(stderr, " -l, --loop               create consistent "
				"image copy\n");
		return 1;
	}

	hash_size = gcry_md_get_algo_dlen(hash_algo);

	fd_src = open(argv[optind], O_RDONLY);
	if (fd_src < 0) {
		perror("opening src");
		return 1;
	}

	sizeblocks = lseek(fd_src, 0, SEEK_END);
	if (sizeblocks < 0) {
		perror("lseek");
		return 1;
	}
	sizeblocks = (sizeblocks + block_size - 1) / block_size;

	if (strcmp(argv[optind + 1], "-")) {
		int fd_srchashmap;

		if (loop) {
			fprintf(stderr, "consistent image copy requested, "
					"but source hashmap specified\n");
			return 1;
		}

		fd_srchashmap = open(argv[optind + 1], O_RDONLY);
		if (fd_srchashmap < 0) {
			perror("opening srchashmap");
			return 1;
		}

		srchashmap = malloc(sizeblocks * hash_size);
		if (srchashmap == NULL) {
			fprintf(stderr, "out of memory allocating hash map\n");
			return 1;
		}

		if (read(fd_srchashmap, srchashmap, sizeblocks * hash_size)
		    != sizeblocks * hash_size) {
			fprintf(stderr, "error reading hash map\n");
			return 1;
		}

		close(fd_srchashmap);
	} else {
		srchashmap = NULL;
	}

	fd_dst = open(argv[optind + 2], O_CREAT | O_RDWR, 0666);
	if (fd_dst < 0) {
		perror("opening dst");
		return 1;
	}

	fd_dsthashmap = open(argv[optind + 3], O_CREAT | O_RDWR, 0666);
	if (fd_dsthashmap < 0) {
		perror("opening dsthashmap");
		return 1;
	}

	dsthashmap = malloc(sizeblocks * hash_size);
	if (dsthashmap == NULL) {
		fprintf(stderr, "out of memory allocating hash map\n");
		return 1;
	}

	if (read(fd_dsthashmap, dsthashmap, sizeblocks * hash_size)
	    != sizeblocks * hash_size) {
		fprintf(stderr, "error reading hash map\n");
		return 1;
	}

	setup_sig_handlers();

	if (freeze_count) {
		for (i = 0; i < MAX_FREEZE; i++)
			freeze_fd[i] = -1;

		atexit(thaw_fs);

		fprintf(stderr, "freezing filesystems\n");

		for (i = 0; i < freeze_count; i++) {
			int fd;

			fd = open(freeze_fs[i], O_RDONLY);
			if (fd < 0) {
				fprintf(stderr, "error opening freeze mount "
						"point %s (%s)\n", freeze_fs[i],
						strerror(errno));
				return 1;
			}

			if (ioctl(fd, FIFREEZE, 0) < 0) {
				fprintf(stderr, "error freezing fs %s (%s)\n",
						freeze_fs[i], strerror(errno));
				return 1;
			}

			freeze_fd[i] = fd;
		}
	}

	if (loop) {
		for (i = 0; i < max_iterations; i++) {
			fd_off = 0;
			again = 0;

			fprintf(stderr, "scanning for differences... ");
			run_threads(copy_thread_no_hashmap);
			if (!signal_quit_flag) {
				fprintf(stderr, "done                      "
						"                          \n");
			}

			if (!again)
				break;

			if (i == max_iterations - 1) {
				fprintf(stderr, "maximum iteration count "
						"reached, bailing out\n");
			} else {
				fprintf(stderr, "repeating scanning due to "
						"differences\n");
			}
		}
	} else {
		fd_off = 0;

		if (srchashmap == NULL) {
			fprintf(stderr, "scanning for differences... ");
			run_threads(copy_thread_no_hashmap);
		} else {
			off_t off;

			mismatch_idx = 0;

			mismatch_cnt = 0;
			for (off = 0; off < sizeblocks; off++) {
				if (memcmp(srchashmap + off * hash_size,
					   dsthashmap + off * hash_size,
					   hash_size)) {
					mismatch_cnt++;
				}
			}

			fprintf(stderr, "copying differences... ");
			run_threads(copy_thread_hashmap);
		}
		if (!signal_quit_flag) {
			fprintf(stderr, "done                      "
					"                          \n");
		}
	}

	fprintf(stderr, "flushing buffers... ");
	close(fd_src);
	close(fd_dst);
	close(fd_dsthashmap);
	fprintf(stderr, "done\n");

	return signal_quit_flag ? EXIT_FAILURE : EXIT_SUCCESS;
}
Exemplo n.º 15
0
int
main (int argc, char **argv)
{
  int last_argc = -1;
  int gigs = 0;
  int algo = 0;
  int idx;

  if (argc)
    { argc--; argv++; }

  while (argc && last_argc != argc )
    {
      last_argc = argc;
      if (!strcmp (*argv, "--"))
        {
          argc--; argv++;
          break;
        }
      else if (!strcmp (*argv, "--help"))
        {
          fputs ("usage: " PGM " [options] [algos]\n"
                 "Options:\n"
                 "  --verbose       print timings etc.\n"
                 "  --debug         flyswatter\n"
                 "  --gigs N        Run a test on N GiB\n",
                 stdout);
          exit (0);
        }
      else if (!strcmp (*argv, "--verbose"))
        {
          verbose++;
          argc--; argv++;
        }
      else if (!strcmp (*argv, "--debug"))
        {
          verbose += 2;
          debug++;
          argc--; argv++;
        }
      else if (!strcmp (*argv, "--gigs"))
        {
          argc--; argv++;
          if (argc)
            {
              gigs = atoi (*argv);
              argc--; argv++;
            }
        }
      else if (!strncmp (*argv, "--", 2))
        die ("unknown option '%s'", *argv);
    }

  if (gigs < 0 || gigs > 1024*1024)
    die ("value for --gigs must be in the range 0 to %d", 1024*1024);

  gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
  if (!gcry_check_version (GCRYPT_VERSION))
    die ("version mismatch\n");
  if (debug)
    gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0);
  gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
  gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);

  /* A quick check that all given algorithms are valid.  */
  for (idx=0; idx < argc; idx++)
    {
      algo = gcry_md_map_name (argv[idx]);
      if (!algo)
        fail ("invalid algorithm '%s'", argv[idx]);
    }
  if (error_count)
    exit (1);

  /* Start checking.  */
  start_timer ();
  if (!argc)
    {
      for (algo=1; algo < 400; algo++)
        if (!gcry_md_test_algo (algo))
          {
            if (!gigs)
              run_selftest (algo);
            else
              run_longtest (algo, gigs);
          }
     }
  else
    {
      for (idx=0; idx < argc; idx++)
        {
          algo = gcry_md_map_name (argv[idx]);
          if (!algo)
            die ("invalid algorithm '%s'", argv[idx]);

          if (!gigs)
            run_selftest (algo);
          else
            run_longtest (algo, gigs);
        }
    }
  stop_timer ();

  if (missing_test_vectors)
    fail ("Some test vectors are missing");

  if (verbose)
    show ("All tests completed in %s.  Errors: %d\n",
          elapsed_time (), error_count);
  return !!error_count;
}
Exemplo n.º 16
0
int check_hash(int fd_no, const char *f_md5, const char *f_sha256){
	int md5algo, sha256algo, i;
	char hashed_md5[33], hashed_sha256[65];
	struct stat fileStat;
	char *buffer;
	const char *md5name = gcry_md_algo_name(GCRY_MD_MD5);
	const char *sha256name = gcry_md_algo_name(GCRY_MD_SHA256);
	md5algo = gcry_md_map_name(md5name);
	sha256algo = gcry_md_map_name(sha256name);
	off_t fsize = 0, donesize = 0, diff = 0;
  	if(fstat(fd_no, &fileStat) < 0){
  		perror("Fstat error");
    	return -1;
  	}
  	fsize = fileStat.st_size;
  	FILE *fp = fdopen(fd_no, "r");
  	if(fp == NULL){
  		printf("Cannot open file for read\n");
  		return -1;
  	}
	gcry_md_hd_t hd_md5;
	gcry_md_hd_t hd_sha256;
	gcry_md_open(&hd_md5, md5algo, 0);
	gcry_md_open(&hd_sha256, sha256algo, 0);
	if(fsize < 10024){
		buffer = malloc(fsize);
  		if(buffer == NULL){
  			printf("malloc error\n");
  			return -1;
  		}
		fread(buffer, 1, fsize, fp);
		gcry_md_write(hd_md5, buffer, fsize);
		gcry_md_write(hd_sha256, buffer, fsize);
		goto nowhile;
	}
	buffer = malloc(10024);
  	if(buffer == NULL){
  		printf("malloc error\n");
  		return -1;
  	}
	while(fsize > donesize){
		fread(buffer, 1, 10024, fp);
		gcry_md_write(hd_md5, buffer, 10024);
		gcry_md_write(hd_sha256, buffer, 10024);
		donesize+=10024;
		diff=fsize-donesize;
		if(diff < 10024){
			fread(buffer, 1, diff, fp);
			gcry_md_write(hd_md5, buffer, diff);
			gcry_md_write(hd_sha256, buffer, diff);
			break;
		}
	}
	nowhile:
	gcry_md_final(hd_md5);
	gcry_md_final(hd_sha256);
	unsigned const char *md5 = gcry_md_read(hd_md5, md5algo);
	unsigned const char *sha256 = gcry_md_read(hd_sha256, sha256algo);
 	for(i=0; i<16; i++){
 		sprintf(hashed_md5+(i*2), "%02x", md5[i]);
 	}
 	for(i=0; i<32; i++){
 		sprintf(hashed_sha256+(i*2), "%02x", sha256[i]);
 	}
 	hashed_md5[32] = '\0';
 	hashed_sha256[64] = '\0';
 	free(buffer);
 	fclose(fp);
 	close(fd_no);
 	if((strcmp(f_md5, hashed_md5) != 0) || (strcmp(f_sha256, hashed_sha256) != 0)){
 		printf("Error: checksum mismatch\n");
 	}
 	else printf("Checksum ok\n");
	gcry_md_close(hd_md5);
	gcry_md_close(hd_sha256);
	return 0;
}
Exemplo n.º 17
0
static void
md_bench ( const char *algoname )
{
  int algo;
  gcry_md_hd_t hd;
  int i, j, repcount;
  char buf_base[1000+15];
  size_t bufsize = 1000;
  char *buf;
  char *largebuf_base;
  char *largebuf;
  char digest[512/8];
  gcry_error_t err = GPG_ERR_NO_ERROR;

  if (!algoname)
    {
      for (i=1; i < 400; i++)
        if (in_fips_mode && i == GCRY_MD_MD5)
          ; /* Don't use MD5 in fips mode.  */
        else if ( !gcry_md_test_algo (i) )
          md_bench (gcry_md_algo_name (i));
      return;
    }

  buf = buf_base + ((16 - ((size_t)buf_base & 0x0f)) % buffer_alignment);

  algo = gcry_md_map_name (algoname);
  if (!algo)
    {
      fprintf (stderr, PGM ": invalid hash algorithm `%s'\n", algoname);
      exit (1);
    }

  err = gcry_md_open (&hd, algo, 0);
  if (err)
    {
      fprintf (stderr, PGM ": error opening hash algorithm `%s'\n", algoname);
      exit (1);
    }

  for (i=0; i < bufsize; i++)
    buf[i] = i;

  printf ("%-12s", gcry_md_algo_name (algo));

  start_timer ();
  for (repcount=0; repcount < hash_repetitions; repcount++)
    for (i=0; i < 1000; i++)
      gcry_md_write (hd, buf, bufsize);
  gcry_md_final (hd);
  stop_timer ();
  printf (" %s", elapsed_time ());
  fflush (stdout);

  gcry_md_reset (hd);
  start_timer ();
  for (repcount=0; repcount < hash_repetitions; repcount++)
    for (i=0; i < 10000; i++)
      gcry_md_write (hd, buf, bufsize/10);
  gcry_md_final (hd);
  stop_timer ();
  printf (" %s", elapsed_time ());
  fflush (stdout);

  gcry_md_reset (hd);
  start_timer ();
  for (repcount=0; repcount < hash_repetitions; repcount++)
    for (i=0; i < 1000000; i++)
      gcry_md_write (hd, buf, 1);
  gcry_md_final (hd);
  stop_timer ();
  printf (" %s", elapsed_time ());
  fflush (stdout);

  start_timer ();
  for (repcount=0; repcount < hash_repetitions; repcount++)
    for (i=0; i < 1000; i++)
      for (j=0; j < bufsize; j++)
        gcry_md_putc (hd, buf[j]);
  gcry_md_final (hd);
  stop_timer ();
  printf (" %s", elapsed_time ());
  fflush (stdout);

  gcry_md_close (hd);

  /* Now 100 hash operations on 10000 bytes using the fast function.
     We initialize the buffer so that all memory pages are committed
     and we have repeatable values.  */
  if (gcry_md_get_algo_dlen (algo) > sizeof digest)
    die ("digest buffer too short\n");

  largebuf_base = malloc (10000+15);
  if (!largebuf_base)
    die ("out of core\n");
  largebuf = (largebuf_base
              + ((16 - ((size_t)largebuf_base & 0x0f)) % buffer_alignment));

  for (i=0; i < 10000; i++)
    largebuf[i] = i;
  start_timer ();
  for (repcount=0; repcount < hash_repetitions; repcount++)
    for (i=0; i < 100; i++)
      gcry_md_hash_buffer (algo, digest, largebuf, 10000);
  stop_timer ();
  printf (" %s", elapsed_time ());
  free (largebuf_base);

  putchar ('\n');
  fflush (stdout);
}
Exemplo n.º 18
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;
}
Exemplo n.º 19
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;
}
Exemplo n.º 20
0
static void
md_bench ( const char *algoname )
{
  int algo;
  gcry_md_hd_t hd;
  int i;
  char buf[1000];
  gcry_error_t err = GPG_ERR_NO_ERROR;

  if (!algoname)
    {
      for (i=1; i < 400; i++)
        if ( !gcry_md_test_algo (i) )
          md_bench (gcry_md_algo_name (i));
      return;
    }

  algo = gcry_md_map_name (algoname);
  if (!algo)
    {
      fprintf (stderr, PGM ": invalid hash algorithm `%s'\n", algoname);
      exit (1);
    }

  err = gcry_md_open (&hd, algo, 0);
  if (err)
    {
      fprintf (stderr, PGM ": error opening hash algorithm `%s'\n", algoname);
      exit (1);
    }

  for (i=0; i < sizeof buf; i++)
    buf[i] = i;

  printf ("%-12s", gcry_md_algo_name (algo));

  start_timer ();
  for (i=0; i < 1000; i++)
    gcry_md_write (hd, buf, sizeof buf);
  gcry_md_final (hd);
  stop_timer ();
  printf (" %s", elapsed_time ());

  gcry_md_reset (hd);
  start_timer ();
  for (i=0; i < 10000; i++)
    gcry_md_write (hd, buf, sizeof buf/10);
  gcry_md_final (hd);
  stop_timer ();
  printf (" %s", elapsed_time ());

  gcry_md_reset (hd);
  start_timer ();
  for (i=0; i < 1000000; i++)
    gcry_md_write (hd, "", 1);
  gcry_md_final (hd);
  stop_timer ();
  printf (" %s", elapsed_time ());

  gcry_md_close (hd);
  putchar ('\n');
}
Exemplo n.º 21
0
/* Perform a verify operation.  To verify detached signatures, data_fd
   must be different than -1.  With OUT_FP given and a non-detached
   signature, the signed material is written to that stream. */
int
gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, FILE *out_fp)
{
  int i, rc;
  Base64Context b64reader = NULL;
  Base64Context b64writer = NULL;
  ksba_reader_t reader;
  ksba_writer_t writer = NULL;
  ksba_cms_t cms = NULL;
  ksba_stop_reason_t stopreason;
  ksba_cert_t cert;
  KEYDB_HANDLE kh;
  gcry_md_hd_t data_md = NULL;
  int signer;
  const char *algoid;
  int algo;
  int is_detached;
  FILE *fp = NULL;
  char *p;

  audit_set_type (ctrl->audit, AUDIT_TYPE_VERIFY);

  kh = keydb_new (0);
  if (!kh)
    {
      log_error (_("failed to allocated keyDB handle\n"));
      rc = gpg_error (GPG_ERR_GENERAL);
      goto leave;
    }


  fp = fdopen ( dup (in_fd), "rb");
  if (!fp)
    {
      rc = gpg_error (gpg_err_code_from_errno (errno));
      log_error ("fdopen() failed: %s\n", strerror (errno));
      goto leave;
    }

  rc = gpgsm_create_reader (&b64reader, ctrl, fp, 0, &reader);
  if (rc)
    {
      log_error ("can't create reader: %s\n", gpg_strerror (rc));
      goto leave;
    }

  if (out_fp)
    {
      rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, NULL, &writer);
      if (rc)
        {
          log_error ("can't create writer: %s\n", gpg_strerror (rc));
          goto leave;
        }
    }

  rc = ksba_cms_new (&cms);
  if (rc)
    goto leave;

  rc = ksba_cms_set_reader_writer (cms, reader, writer);
  if (rc)
    {
      log_error ("ksba_cms_set_reader_writer failed: %s\n",
                 gpg_strerror (rc));
      goto leave;
    }

  rc = gcry_md_open (&data_md, 0, 0);
  if (rc)
    {
      log_error ("md_open failed: %s\n", gpg_strerror (rc));
      goto leave;
    }
  if (DBG_HASHING)
    gcry_md_start_debug (data_md, "vrfy.data");

  audit_log (ctrl->audit, AUDIT_SETUP_READY);

  is_detached = 0;
  do 
    {
      rc = ksba_cms_parse (cms, &stopreason);
      if (rc)
        {
          log_error ("ksba_cms_parse failed: %s\n", gpg_strerror (rc));
          goto leave;
        }

      if (stopreason == KSBA_SR_NEED_HASH)
        {
          is_detached = 1;
          audit_log (ctrl->audit, AUDIT_DETACHED_SIGNATURE);
          if (opt.verbose)
            log_info ("detached signature\n");
        }

      if (stopreason == KSBA_SR_NEED_HASH
          || stopreason == KSBA_SR_BEGIN_DATA)
        { 
          audit_log (ctrl->audit, AUDIT_GOT_DATA);

          /* We are now able to enable the hash algorithms */
          for (i=0; (algoid=ksba_cms_get_digest_algo_list (cms, i)); i++)
            {
              algo = gcry_md_map_name (algoid);
              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"));
                  audit_log_s (ctrl->audit, AUDIT_BAD_DATA_HASH_ALGO, algoid);
                }
              else
                {
                  if (DBG_X509)
                    log_debug ("enabling hash algorithm %d (%s)\n",
                               algo, algoid? algoid:"");
                  gcry_md_enable (data_md, algo);
                  audit_log_i (ctrl->audit, AUDIT_DATA_HASH_ALGO, algo);
                }
            }
          if (opt.extra_digest_algo)
            {
              if (DBG_X509)
                log_debug ("enabling extra hash algorithm %d\n", 
                           opt.extra_digest_algo);
              gcry_md_enable (data_md, opt.extra_digest_algo);
              audit_log_i (ctrl->audit, AUDIT_DATA_HASH_ALGO,
                           opt.extra_digest_algo);
            }
          if (is_detached)
            {
              if (data_fd == -1)
                {
                  log_info ("detached signature w/o data "
                            "- assuming certs-only\n");
                  audit_log (ctrl->audit, AUDIT_CERT_ONLY_SIG);
                }
              else
                audit_log_ok (ctrl->audit, AUDIT_DATA_HASHING,
                              hash_data (data_fd, data_md));
            }
          else
            {
              ksba_cms_set_hash_function (cms, HASH_FNC, data_md);
            }
        }
      else if (stopreason == KSBA_SR_END_DATA)
        { /* The data bas been hashed */
          audit_log_ok (ctrl->audit, AUDIT_DATA_HASHING, 0);
        }
    }
  while (stopreason != KSBA_SR_READY);   

  if (b64writer)
    {
      rc = gpgsm_finish_writer (b64writer);
      if (rc) 
        {
          log_error ("write failed: %s\n", gpg_strerror (rc));
          audit_log_ok (ctrl->audit, AUDIT_WRITE_ERROR, rc);
          goto leave;
        }
    }

  if (data_fd != -1 && !is_detached)
    {
      log_error ("data given for a non-detached signature\n");
      rc = gpg_error (GPG_ERR_CONFLICT);
      audit_log (ctrl->audit, AUDIT_USAGE_ERROR);
      goto leave;
    }

  for (i=0; (cert=ksba_cms_get_cert (cms, i)); i++)
    {
      /* Fixme: it might be better to check the validity of the
         certificate first before entering it into the DB.  This way
         we would avoid cluttering the DB with invalid
         certificates. */
      audit_log_cert (ctrl->audit, AUDIT_SAVE_CERT, cert, 
                      keydb_store_cert (cert, 0, NULL));
      ksba_cert_release (cert);
    }

  cert = NULL;
  for (signer=0; ; signer++)
    {
      char *issuer = NULL;
      ksba_sexp_t sigval = NULL;
      ksba_isotime_t sigtime, keyexptime;
      ksba_sexp_t serial;
      char *msgdigest = NULL;
      size_t msgdigestlen;
      char *ctattr;
      int sigval_hash_algo;
      int info_pkalgo;
      unsigned int verifyflags;

      rc = ksba_cms_get_issuer_serial (cms, signer, &issuer, &serial);
      if (!signer && gpg_err_code (rc) == GPG_ERR_NO_DATA
          && data_fd == -1 && is_detached)
        {
          log_info ("certs-only message accepted\n");
          rc = 0;
          break;
        }
      if (rc)
        {
          if (signer && rc == -1)
            rc = 0;
          break;
        }

      gpgsm_status (ctrl, STATUS_NEWSIG, NULL);
      audit_log_i (ctrl->audit, AUDIT_NEW_SIG, signer);

      if (DBG_X509)
        {
          log_debug ("signer %d - issuer: `%s'\n",
                     signer, issuer? issuer:"[NONE]");
          log_debug ("signer %d - serial: ", signer);
          gpgsm_dump_serial (serial);
          log_printf ("\n");
        }
      if (ctrl->audit)
        {
          char *tmpstr = gpgsm_format_sn_issuer (serial, issuer);
          audit_log_s (ctrl->audit, AUDIT_SIG_NAME, tmpstr);
          xfree (tmpstr);
        }

      rc = ksba_cms_get_signing_time (cms, signer, sigtime);
      if (gpg_err_code (rc) == GPG_ERR_NO_DATA)
        *sigtime = 0;
      else if (rc)
        {
          log_error ("error getting signing time: %s\n", gpg_strerror (rc));
          *sigtime = 0; /* (we can't encode an error in the time string.) */
        }

      rc = ksba_cms_get_message_digest (cms, signer,
                                        &msgdigest, &msgdigestlen);
      if (!rc)
        {
          size_t is_enabled;

          algoid = ksba_cms_get_digest_algo (cms, signer);
          algo = gcry_md_map_name (algoid);
          if (DBG_X509)
            log_debug ("signer %d - digest algo: %d\n", signer, algo);
          is_enabled = sizeof algo;
          if ( gcry_md_info (data_md, GCRYCTL_IS_ALGO_ENABLED,
                             &algo, &is_enabled)
               || !is_enabled)
            {
              log_error ("digest algo %d (%s) has not been enabled\n", 
                         algo, algoid?algoid:"");
              audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "unsupported");
              goto next_signer;
            }
        }
      else if (gpg_err_code (rc) == GPG_ERR_NO_DATA)
        {
          assert (!msgdigest);
          rc = 0;
          algoid = NULL;
          algo = 0; 
        }
      else /* real error */
        {
          audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "error");
          break;
        }

      rc = ksba_cms_get_sigattr_oids (cms, signer,
                                      "1.2.840.113549.1.9.3", &ctattr);
      if (!rc) 
        {
          const char *s;

          if (DBG_X509)
            log_debug ("signer %d - content-type attribute: %s",
                       signer, ctattr);

          s = ksba_cms_get_content_oid (cms, 1);
          if (!s || strcmp (ctattr, s))
            {
              log_error ("content-type attribute does not match "
                         "actual content-type\n");
              ksba_free (ctattr);
              ctattr = NULL;
              audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "bad");
              goto next_signer;
            }
          ksba_free (ctattr);
          ctattr = NULL;
        }
      else if (rc != -1)
        {
          log_error ("error getting content-type attribute: %s\n",
                     gpg_strerror (rc));
          audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "bad");
          goto next_signer;
        }
      rc = 0;


      sigval = ksba_cms_get_sig_val (cms, signer);
      if (!sigval)
        {
          log_error ("no signature value available\n");
          audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "bad");
          goto next_signer;
        }
      sigval_hash_algo = hash_algo_from_sigval (sigval);
      if (DBG_X509)
        {
          log_debug ("signer %d - signature available (sigval hash=%d)",
                     signer, sigval_hash_algo);
/*           log_printhex ("sigval    ", sigval, */
/*                         gcry_sexp_canon_len (sigval, 0, NULL, NULL)); */
        }
      if (!sigval_hash_algo)
        sigval_hash_algo = algo; /* Fallback used e.g. with old libksba. */

      /* Find the certificate of the signer */
      keydb_search_reset (kh);
      rc = keydb_search_issuer_sn (kh, issuer, serial);
      if (rc)
        {
          if (rc == -1)
            {
              log_error ("certificate not found\n");
              rc = gpg_error (GPG_ERR_NO_PUBKEY);
            }
          else
            log_error ("failed to find the certificate: %s\n",
                       gpg_strerror(rc));
          {
            char numbuf[50];
            sprintf (numbuf, "%d", rc);

            gpgsm_status2 (ctrl, STATUS_ERROR, "verify.findkey",
                           numbuf, NULL);
          }
          audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "no-cert");
          goto next_signer;
        }

      rc = keydb_get_cert (kh, &cert);
      if (rc)
        {
          log_error ("failed to get cert: %s\n", gpg_strerror (rc));
          audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "error");
          goto next_signer;
        }

      log_info (_("Signature made "));
      if (*sigtime)
        dump_isotime (sigtime);
      else
        log_printf (_("[date not given]"));
      log_printf (_(" using certificate ID 0x%08lX\n"),
                  gpgsm_get_short_fingerprint (cert, NULL));

      audit_log_i (ctrl->audit, AUDIT_DATA_HASH_ALGO, algo);

      if (msgdigest)
        { /* Signed attributes are available. */
          gcry_md_hd_t md;
          unsigned char *s;

          /* Check that the message digest in the signed attributes
             matches the one we calculated on the data.  */
          s = gcry_md_read (data_md, algo);
          if ( !s || !msgdigestlen
               || gcry_md_get_algo_dlen (algo) != msgdigestlen
               || !s || memcmp (s, msgdigest, msgdigestlen) )
            {
              char *fpr;

              log_error (_("invalid signature: message digest attribute "
                           "does not match computed one\n"));
              if (DBG_X509)
                {
                  if (msgdigest)
                    log_printhex ("message:  ", msgdigest, msgdigestlen);
                  if (s)
                    log_printhex ("computed: ",
                                  s, gcry_md_get_algo_dlen (algo));
                }
              fpr = gpgsm_fpr_and_name_for_status (cert);
              gpgsm_status (ctrl, STATUS_BADSIG, fpr);
              xfree (fpr);
              audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "bad");
              goto next_signer; 
            }
            
          audit_log_i (ctrl->audit, AUDIT_ATTR_HASH_ALGO, sigval_hash_algo);
          rc = gcry_md_open (&md, sigval_hash_algo, 0);
          if (rc)
            {
              log_error ("md_open failed: %s\n", gpg_strerror (rc));
              audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "error");
              goto next_signer;
            }
          if (DBG_HASHING)
            gcry_md_start_debug (md, "vrfy.attr");

          ksba_cms_set_hash_function (cms, HASH_FNC, md);
          rc = ksba_cms_hash_signed_attrs (cms, signer);
          if (rc)
            {
              log_error ("hashing signed attrs failed: %s\n",
                         gpg_strerror (rc));
              gcry_md_close (md);
              audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "error");
              goto next_signer;
            }
          rc = gpgsm_check_cms_signature (cert, sigval, md, 
                                          sigval_hash_algo, &info_pkalgo);
          gcry_md_close (md);
        }
      else
        {
          rc = gpgsm_check_cms_signature (cert, sigval, data_md, 
                                          algo, &info_pkalgo);
        }

      if (rc)
        {
          char *fpr;

          log_error ("invalid signature: %s\n", gpg_strerror (rc));
          fpr = gpgsm_fpr_and_name_for_status (cert);
          gpgsm_status (ctrl, STATUS_BADSIG, fpr);
          xfree (fpr);
          audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "bad");
          goto next_signer;
        }
      rc = gpgsm_cert_use_verify_p (cert); /*(this displays an info message)*/
      if (rc)
        {
          gpgsm_status_with_err_code (ctrl, STATUS_ERROR, "verify.keyusage",
                                      gpg_err_code (rc));
          rc = 0;
        }

      if (DBG_X509)
        log_debug ("signature okay - checking certs\n");
      audit_log (ctrl->audit, AUDIT_VALIDATE_CHAIN);
      rc = gpgsm_validate_chain (ctrl, cert,
                                 *sigtime? sigtime : "19700101T000000",
                                 keyexptime, 0, 
                                 NULL, 0, &verifyflags);
      {
        char *fpr, *buf, *tstr;

        fpr = gpgsm_fpr_and_name_for_status (cert);
        if (gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED)
          {
            gpgsm_status (ctrl, STATUS_EXPKEYSIG, fpr);
            rc = 0;
          }
        else
          gpgsm_status (ctrl, STATUS_GOODSIG, fpr);
        
        xfree (fpr);

        fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
        tstr = strtimestamp_r (sigtime);
        buf = xasprintf ("%s %s %s %s 0 0 %d %d 00", fpr, tstr,
                         *sigtime? sigtime : "0",
                         *keyexptime? keyexptime : "0",
                         info_pkalgo, algo);
        xfree (tstr);
        xfree (fpr);
        gpgsm_status (ctrl, STATUS_VALIDSIG, buf);
        xfree (buf);
      }

      audit_log_ok (ctrl->audit, AUDIT_CHAIN_STATUS, rc);
      if (rc) /* of validate_chain */
        {
          log_error ("invalid certification chain: %s\n", gpg_strerror (rc));
          if (gpg_err_code (rc) == GPG_ERR_BAD_CERT_CHAIN
              || gpg_err_code (rc) == GPG_ERR_BAD_CERT
              || gpg_err_code (rc) == GPG_ERR_BAD_CA_CERT
              || gpg_err_code (rc) == GPG_ERR_CERT_REVOKED)
            gpgsm_status_with_err_code (ctrl, STATUS_TRUST_NEVER, NULL,
                                        gpg_err_code (rc));
          else
            gpgsm_status_with_err_code (ctrl, STATUS_TRUST_UNDEFINED, NULL, 
                                        gpg_err_code (rc));
          audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "bad");
          goto next_signer;
        }

      audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "good");

      for (i=0; (p = ksba_cert_get_subject (cert, i)); i++)
        {
          log_info (!i? _("Good signature from")
                      : _("                aka"));
          log_printf (" \"");
          gpgsm_print_name (log_get_stream (), p);
          log_printf ("\"\n");
          ksba_free (p);
        }

      /* Print a note if this is a qualified signature.  */
      {
        size_t qualbuflen;
        char qualbuffer[1];
        
        rc = ksba_cert_get_user_data (cert, "is_qualified", &qualbuffer,
                                      sizeof (qualbuffer), &qualbuflen);
        if (!rc && qualbuflen)
          {
            if (*qualbuffer)
              {
                log_info (_("This is a qualified signature\n"));
                if (!opt.qualsig_approval)
                  log_info 
                    (_("Note, that this software is not officially approved "
                       "to create or verify such signatures.\n"));
              }
          }    
        else if (gpg_err_code (rc) != GPG_ERR_NOT_FOUND)
          log_error ("get_user_data(is_qualified) failed: %s\n",
                     gpg_strerror (rc)); 
      }

      gpgsm_status (ctrl, STATUS_TRUST_FULLY, 
                    (verifyflags & VALIDATE_FLAG_CHAIN_MODEL)?
                    "0 chain": "0 shell");
          

    next_signer:
      rc = 0;
      xfree (issuer);
      xfree (serial);
      xfree (sigval);
      xfree (msgdigest);
      ksba_cert_release (cert);
      cert = NULL;
    }
  rc = 0;

 leave:
  ksba_cms_release (cms);
  gpgsm_destroy_reader (b64reader);
  gpgsm_destroy_writer (b64writer);
  keydb_release (kh); 
  gcry_md_close (data_md);
  if (fp)
    fclose (fp);

  if (rc)
    {
      char numbuf[50];
      sprintf (numbuf, "%d", rc );
      gpgsm_status2 (ctrl, STATUS_ERROR, "verify.leave",
                     numbuf, NULL);
    }

  return rc;
}