Exemple #1
0
static int test_mdc2(void)
{
    int testresult = 0;
    unsigned char md[MDC2_DIGEST_LENGTH];
    EVP_MD_CTX *c;
    static char text[] = "Now is the time for all ";
    size_t tlen = strlen(text);

# ifdef CHARSET_EBCDIC
    ebcdic2ascii(text, text, tlen);
# endif

    c = EVP_MD_CTX_new();
    if (!TEST_ptr(c)
        || !TEST_true(EVP_DigestInit_ex(c, EVP_mdc2(), NULL))
        || !TEST_true(EVP_DigestUpdate(c, (unsigned char *)text, tlen))
        || !TEST_true(EVP_DigestFinal_ex(c, &(md[0]), NULL))
        || !TEST_mem_eq(md, MDC2_DIGEST_LENGTH, pad1, MDC2_DIGEST_LENGTH)
        || !TEST_true(EVP_DigestInit_ex(c, EVP_mdc2(), NULL)))
        goto end;

    /* FIXME: use a ctl function? */
    ((MDC2_CTX *)EVP_MD_CTX_md_data(c))->pad_type = 2;
    if (!TEST_true(EVP_DigestUpdate(c, (unsigned char *)text, tlen))
        || !TEST_true(EVP_DigestFinal_ex(c, &(md[0]), NULL))
        || !TEST_mem_eq(md, MDC2_DIGEST_LENGTH, pad2, MDC2_DIGEST_LENGTH))
        goto end;

    testresult = 1;
 end:
    EVP_MD_CTX_free(c);
    return testresult;
}
Exemple #2
0
int main(int argc, char *argv[])
	{
	int ret=0;
	unsigned char md[MDC2_DIGEST_LENGTH];
	int i;
	EVP_MD_CTX c;
	static char *text="Now is the time for all ";

#ifdef CHARSET_EBCDIC
	ebcdic2ascii(text,text,strlen(text));
#endif

	EVP_MD_CTX_init(&c);
	EVP_DigestInit_ex(&c,EVP_mdc2(), NULL);
	EVP_DigestUpdate(&c,(unsigned char *)text,strlen(text));
	EVP_DigestFinal_ex(&c,&(md[0]),NULL);

	if (memcmp(md,pad1,MDC2_DIGEST_LENGTH) != 0)
		{
		for (i=0; i<MDC2_DIGEST_LENGTH; i++)
			printf("%02X",md[i]);
		printf(" <- generated\n");
		for (i=0; i<MDC2_DIGEST_LENGTH; i++)
			printf("%02X",pad1[i]);
		printf(" <- correct\n");
		ret=1;
		}
	else
		printf("pad1 - ok\n");

	EVP_DigestInit_ex(&c,EVP_mdc2(), NULL);
	/* FIXME: use a ctl function? */
	((MDC2_CTX *)c.md_data)->pad_type=2;
	EVP_DigestUpdate(&c,(unsigned char *)text,strlen(text));
	EVP_DigestFinal_ex(&c,&(md[0]),NULL);

	if (memcmp(md,pad2,MDC2_DIGEST_LENGTH) != 0)
		{
		for (i=0; i<MDC2_DIGEST_LENGTH; i++)
			printf("%02X",md[i]);
		printf(" <- generated\n");
		for (i=0; i<MDC2_DIGEST_LENGTH; i++)
			printf("%02X",pad2[i]);
		printf(" <- correct\n");
		ret=1;
		}
	else
		printf("pad2 - ok\n");

	EVP_MD_CTX_cleanup(&c);
#ifdef OPENSSL_SYS_NETWARE
    if (ret) printf("ERROR: %d\n", ret);
#endif
	EXIT(ret);
	return(ret);
	}
Exemple #3
0
void openssl_add_all_digests_internal(void)
{
#ifndef OPENSSL_NO_MD4
    EVP_add_digest(EVP_md4());
#endif
#ifndef OPENSSL_NO_MD5
    EVP_add_digest(EVP_md5());
    EVP_add_digest_alias(SN_md5, "ssl3-md5");
    EVP_add_digest(EVP_md5_sha1());
#endif
    EVP_add_digest(EVP_sha1());
    EVP_add_digest_alias(SN_sha1, "ssl3-sha1");
    EVP_add_digest_alias(SN_sha1WithRSAEncryption, SN_sha1WithRSA);
#if !defined(OPENSSL_NO_MDC2) && !defined(OPENSSL_NO_DES)
    EVP_add_digest(EVP_mdc2());
#endif
#ifndef OPENSSL_NO_RMD160
    EVP_add_digest(EVP_ripemd160());
    EVP_add_digest_alias(SN_ripemd160, "ripemd");
    EVP_add_digest_alias(SN_ripemd160, "rmd160");
#endif
    EVP_add_digest(EVP_sha224());
    EVP_add_digest(EVP_sha256());
    EVP_add_digest(EVP_sha384());
    EVP_add_digest(EVP_sha512());
#ifndef OPENSSL_NO_WHIRLPOOL
    EVP_add_digest(EVP_whirlpool());
#endif
}
Exemple #4
0
void
OpenSSL_add_all_digests(void)
{
#ifndef OPENSSL_NO_MD4
	EVP_add_digest(EVP_md4());
#endif

#ifndef OPENSSL_NO_MD5
	EVP_add_digest(EVP_md5());
	EVP_add_digest_alias(SN_md5, "ssl2-md5");
	EVP_add_digest_alias(SN_md5, "ssl3-md5");
#endif

#if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA0)
	EVP_add_digest(EVP_sha());
#ifndef OPENSSL_NO_DSA
	EVP_add_digest(EVP_dss());
#endif
#endif
#if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA1)
	EVP_add_digest(EVP_sha1());
	EVP_add_digest_alias(SN_sha1, "ssl3-sha1");
	EVP_add_digest_alias(SN_sha1WithRSAEncryption, SN_sha1WithRSA);
#ifndef OPENSSL_NO_DSA
	EVP_add_digest(EVP_dss1());
	EVP_add_digest_alias(SN_dsaWithSHA1, SN_dsaWithSHA1_2);
	EVP_add_digest_alias(SN_dsaWithSHA1, "DSS1");
	EVP_add_digest_alias(SN_dsaWithSHA1, "dss1");
#endif
#ifndef OPENSSL_NO_ECDSA
	EVP_add_digest(EVP_ecdsa());
#endif
#endif

#ifndef OPENSSL_NO_GOST
	EVP_add_digest(EVP_gostr341194());
	EVP_add_digest(EVP_gost2814789imit());
	EVP_add_digest(EVP_streebog256());
	EVP_add_digest(EVP_streebog512());
#endif
#if !defined(OPENSSL_NO_MDC2) && !defined(OPENSSL_NO_DES)
	EVP_add_digest(EVP_mdc2());
#endif
#ifndef OPENSSL_NO_RIPEMD
	EVP_add_digest(EVP_ripemd160());
	EVP_add_digest_alias(SN_ripemd160, "ripemd");
	EVP_add_digest_alias(SN_ripemd160, "rmd160");
#endif
#ifndef OPENSSL_NO_SHA256
	EVP_add_digest(EVP_sha224());
	EVP_add_digest(EVP_sha256());
#endif
#ifndef OPENSSL_NO_SHA512
	EVP_add_digest(EVP_sha384());
	EVP_add_digest(EVP_sha512());
#endif
#ifndef OPENSSL_NO_WHIRLPOOL
	EVP_add_digest(EVP_whirlpool());
#endif
}
ikptr
ikrt_openssl_evp_mdc2 (ikpcb * pcb)
{
#ifdef HAVE_EVP_MDC2
  const EVP_MD *	rv;
  rv = EVP_mdc2();
  return ika_pointer_alloc(pcb, (long)rv);
#else
  feature_failure(__func__);
#endif
}
Exemple #6
0
void OpenSSL_add_all_digests(void)
	{
#ifndef OPENSSL_NO_MD2
	EVP_add_digest(EVP_md2());
#endif
#ifndef OPENSSL_NO_MD4
	EVP_add_digest(EVP_md4());
#endif
#ifndef OPENSSL_NO_MD5
	EVP_add_digest(EVP_md5());
	EVP_add_digest_alias(SN_md5,"ssl2-md5");
	EVP_add_digest_alias(SN_md5,"ssl3-md5");
#endif
#if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA0)
	EVP_add_digest(EVP_sha());
#ifndef OPENSSL_NO_DSA
	EVP_add_digest(EVP_dss());
#endif
#endif
#ifndef OPENSSL_NO_SHA
	EVP_add_digest(EVP_sha1());
	EVP_add_digest_alias(SN_sha1,"ssl3-sha1");
	EVP_add_digest_alias(SN_sha1WithRSAEncryption,SN_sha1WithRSA);
#ifndef OPENSSL_NO_DSA
	EVP_add_digest(EVP_dss1());
	EVP_add_digest_alias(SN_dsaWithSHA1,SN_dsaWithSHA1_2);
	EVP_add_digest_alias(SN_dsaWithSHA1,"DSS1");
	EVP_add_digest_alias(SN_dsaWithSHA1,"dss1");
#endif
#ifndef OPENSSL_NO_ECDSA
	EVP_add_digest(EVP_ecdsa());
#endif
#endif
#if !defined(OPENSSL_NO_MDC2) && !defined(OPENSSL_NO_DES)
	EVP_add_digest(EVP_mdc2());
#endif
#ifndef OPENSSL_NO_RIPEMD
	EVP_add_digest(EVP_ripemd160());
	EVP_add_digest_alias(SN_ripemd160,"ripemd");
	EVP_add_digest_alias(SN_ripemd160,"rmd160");
#endif
#ifndef OPENSSL_NO_SHA256
/*	EVP_add_digest(EVP_sha224()); To be added later */
	EVP_add_digest(EVP_sha256());
#endif
#ifndef OPENSSL_NO_SHA512
	EVP_add_digest(EVP_sha384());
	EVP_add_digest(EVP_sha512());
#endif
	}
Exemple #7
0
const EVP_MD * hb_EVP_MD_par( int iParam )
{
   const EVP_MD * p;

   if( HB_ISCHAR( iParam ) )
      return EVP_get_digestbyname( hb_parc( iParam ) );

   switch( hb_parni( iParam ) )
   {
      case HB_EVP_MD_MD_NULL:    p = EVP_md_null();   break;
#if ! defined( OPENSSL_NO_MD2 ) && OPENSSL_VERSION_NUMBER < 0x10000000L
      case HB_EVP_MD_MD2:        p = EVP_md2();       break;
#endif
#ifndef OPENSSL_NO_MD4
      case HB_EVP_MD_MD4:        p = EVP_md4();       break;
#endif
#ifndef OPENSSL_NO_MD5
      case HB_EVP_MD_MD5:        p = EVP_md5();       break;
#endif
#ifndef OPENSSL_NO_SHA
      case HB_EVP_MD_SHA:        p = EVP_sha();       break;
      case HB_EVP_MD_SHA1:       p = EVP_sha1();      break;
      case HB_EVP_MD_DSS:        p = EVP_dss();       break;
      case HB_EVP_MD_DSS1:       p = EVP_dss1();      break;
#if ! defined( HB_OPENSSL_OLD_OSX_ )
      case HB_EVP_MD_ECDSA:      p = EVP_ecdsa();     break;
#endif
#endif
#ifndef OPENSSL_NO_SHA256
      case HB_EVP_MD_SHA224:     p = EVP_sha224();    break;
      case HB_EVP_MD_SHA256:     p = EVP_sha256();    break;
#endif
#ifndef OPENSSL_NO_SHA512
      case HB_EVP_MD_SHA384:     p = EVP_sha384();    break;
      case HB_EVP_MD_SHA512:     p = EVP_sha512();    break;
#endif
#ifndef OPENSSL_NO_MDC2
      case HB_EVP_MD_MDC2:       p = EVP_mdc2();      break;
#endif
#ifndef OPENSSL_NO_RIPEMD
      case HB_EVP_MD_RIPEMD160:  p = EVP_ripemd160(); break;
#endif
      default:                   p = NULL;
   }

   return p;
}
Exemple #8
0
static int hb_EVP_MD_ptr_to_id( const EVP_MD * p )
{
   int n;

   if(      p == EVP_md_null()   ) n = HB_EVP_MD_MD_NULL;
#ifndef OPENSSL_NO_MD2
   else if( p == EVP_md2()       ) n = HB_EVP_MD_MD2;
#endif
#ifndef OPENSSL_NO_MD4
   else if( p == EVP_md4()       ) n = HB_EVP_MD_MD4;
#endif
#ifndef OPENSSL_NO_MD5
   else if( p == EVP_md5()       ) n = HB_EVP_MD_MD5;
#endif
#ifndef OPENSSL_NO_SHA
   else if( p == EVP_sha()       ) n = HB_EVP_MD_SHA;
   else if( p == EVP_sha1()      ) n = HB_EVP_MD_SHA1;
   else if( p == EVP_dss()       ) n = HB_EVP_MD_DSS;
   else if( p == EVP_dss1()      ) n = HB_EVP_MD_DSS1;
#if ! defined( HB_OPENSSL_OLD_OSX_ )
   else if( p == EVP_ecdsa()     ) n = HB_EVP_MD_ECDSA;
#endif
#endif
#ifndef OPENSSL_NO_SHA256
   else if( p == EVP_sha224()    ) n = HB_EVP_MD_SHA224;
   else if( p == EVP_sha256()    ) n = HB_EVP_MD_SHA256;
#endif
#ifndef OPENSSL_NO_SHA512
   else if( p == EVP_sha384()    ) n = HB_EVP_MD_SHA384;
   else if( p == EVP_sha512()    ) n = HB_EVP_MD_SHA512;
#endif
#ifndef OPENSSL_NO_MDC2
   else if( p == EVP_mdc2()      ) n = HB_EVP_MD_MDC2;
#endif
#ifndef OPENSSL_NO_RIPEMD
   else if( p == EVP_ripemd160() ) n = HB_EVP_MD_RIPEMD160;
#endif
   else                            n = HB_EVP_MD_UNSUPPORTED;

   return n;
}
Exemple #9
0
static const EVP_MD *gtkhash_hash_lib_crypto_get_md(const enum hash_func_e id)
{
	switch (id) {
		case HASH_FUNC_MD4:
			return EVP_md4();
		case HASH_FUNC_MD5:
			return EVP_md5();
		case HASH_FUNC_SHA0:
			return EVP_sha();
		case HASH_FUNC_SHA1:
			return EVP_sha1();
		case HASH_FUNC_RIPEMD160:
			return EVP_ripemd160();
		case HASH_FUNC_MDC2:
			return EVP_mdc2();
		default:
			return NULL;
	}

	g_assert_not_reached();
}
Exemple #10
0
int
main(int argc, char **argv, char **envp)
{
#if 0
	const char *algorithm	= NULL;
#else
	const char *algorithm	= "md5";
#endif
	const char *key		= NULL;
	const char *msg		= NULL;
	const char *signature	= NULL;
#if 0
	const char *type	= NULL;
#else
	const char *type	= "rsa";
#endif

	xxxflag	= false;

	if(!(prog = basename(argv[0]))) {
		fprintf(stderr, "err: basename: %s -- %s\n",
			strerror(errno), argv[0]);

		return(-1);
		/* NOTREACHED */
	}

	{
		int ch = 0;
#if 0
		while((ch = getopt(argc, argv, "a:k:m:s:t:@")) != -1) {
#else
		while((ch = getopt(argc, argv, "k:m:s:@")) != -1) {
#endif
			switch (ch) {
#if 0
				case 'a':
					algorithm	= optarg;
					break;
#endif
				case 'k':
					key		= optarg;
					break;
				case 'm':
					msg		= optarg;
					break;
				case 's':
					signature	= optarg;
					break;
#if 0
				case 't':
					type		= optarg;
					break;
#endif
				case '@':
					xxxflag		= true;
					break;
				default:
					usage();
					/* NOTREACHED */

					break;
			}
		}

		argc -= optind;
		argv += optind;
	}

	if(argc || !algorithm || !key || !msg || !type) {
		usage();
		/* NOTREACHED */
	}

	return(sigcomp_main(algorithm, key, msg, signature, type)? 0: -1);
	/* NOTREACHED */
}



static bool
sigcomp_main(const char *const algorithm, const char *const key,
	const char *const msg, const char *const signature,
	const char *const type)
{
	const EVP_MD *evp_md	= NULL;
	BIGNUM *bn_key		= NULL;
	BIGNUM *bn_msg		= NULL;
	BIGNUM *bn_signature	= NULL;

	ERR_load_crypto_strings();

	if(!(evp_md = evp_md_with_algorithm(type, algorithm))) {
		fprintf(stderr, "err: algorithm: %s -- "
			"unknown algorithm for %s\n", algorithm, type);

		return(sigcomp_return(false, bn_key, bn_msg, bn_signature));
	}

	/* key -> bn_key */
	if(!(bn_key = BN_new())) {
		openssl_strerror("BN_new");
		return(sigcomp_return(false, bn_key, bn_msg, bn_signature));
	}

	if(!BN_hex2bn(&bn_key, (const char *)key)) {
		openssl_strerror("BN_hex2bn");
		return(sigcomp_return(false, bn_key, bn_msg, bn_signature));
	}

	/* msg -> bn_msg */
	if(!(bn_msg = BN_new())) {
		openssl_strerror("BN_new");
		return(sigcomp_return(false, bn_key, bn_msg, bn_signature));
	}

	if(!BN_hex2bn(&bn_msg, (const char *)msg)) {
		openssl_strerror("BN_hex2bn");
		return(sigcomp_return(false, bn_key, bn_msg, bn_signature));
	}

	if(signature) {
		/* signature -> bn_signature */
		if(!(bn_signature = BN_new())) {
			openssl_strerror("BN_new");
			return(sigcomp_return(false,
				bn_key, bn_msg, bn_signature));
		}

		if(!BN_hex2bn(&bn_signature, (const char *)signature)) {
			openssl_strerror("BN_hex2bn");
			return(sigcomp_return(false,
				bn_key, bn_msg, bn_signature));
		}

		if(!sigcomp_vrfy(evp_md, bn_key, bn_msg, bn_signature, type)) {
			return(sigcomp_return(false,
				bn_key, bn_msg, bn_signature));
		}
	} else {
		if(!sigcomp_sign(evp_md, bn_key, bn_msg, type)) {
			return(sigcomp_return(false,
				bn_key, bn_msg, bn_signature));
		}
	}

	return(sigcomp_return(true, bn_key, bn_msg, bn_signature));
}



static bool
sigcomp_return(const bool code,
	BIGNUM *bn_key, BIGNUM *bn_msg, BIGNUM *bn_signature)
{
	if(bn_signature) {
		BN_free(bn_signature); bn_signature = NULL;
	}

	if(bn_msg) {
		BN_free(bn_msg); bn_msg = NULL;
	}

	if(bn_key) {
		BN_free(bn_key); bn_key = NULL;
	}

	return(code);
}



static bool
sigcomp_sign(const EVP_MD *const evp_md, const BIGNUM *const bn_key,
	const BIGNUM *const bn_msg, const char *const type)
{
	EVP_PKEY *pkey			= NULL;
	unsigned char *key		= NULL;
	unsigned char *msg		= NULL;
	unsigned char *signature	= NULL;
	unsigned char *ptr = NULL;

	int keylen		= 0;
	int msglen		= 0;
	int signaturelen	= 0;
	int padding		= 0;

	/* bn_key -> key */
	if(!(keylen = BN_num_bytes(bn_key))) {
		openssl_strerror("BN_num_bytes");
		return(sigcomp_sign_return(false, key, msg, signature, pkey));
	}

	if(!(key = (unsigned char *)malloc(keylen))) {
		fprintf(stderr, "err: malloc: %s\n", strerror(errno));
		return(sigcomp_sign_return(false, key, msg, signature, pkey));
	}

	if(BN_bn2bin(bn_key, key) != keylen) {
		openssl_strerror("BN_bn2bin");
		return(sigcomp_sign_return(false, key, msg, signature, pkey));
	}
#ifdef DEBUG
	dmp(stderr, "key", key, keylen);
#endif	// DEBUG
	/* bn_msg -> msg */
	if(!(msglen = BN_num_bytes(bn_msg))) {
		openssl_strerror("BN_num_bytes");
		return(sigcomp_sign_return(false, key, msg, signature, pkey));
	}

	if(!(msg = (unsigned char *)malloc(msglen))) {
		fprintf(stderr, "err: malloc: %s\n", strerror(errno));
		return(sigcomp_sign_return(false, key, msg, signature, pkey));
	}

	if(BN_bn2bin(bn_msg, msg) != msglen) {
		openssl_strerror("BN_bn2bin");
		return(sigcomp_sign_return(false, key, msg, signature, pkey));
	}
#ifdef DEBUG
	dmp(stderr, "msg", msg, msglen);
#endif	// DEBUG
	ptr = key;

	for( ; ; ) {
		if(!strcmp(type, "rsa")) {
#if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x0090800fL)
			if(!(pkey = d2i_PrivateKey(EVP_PKEY_RSA,
				NULL, (const unsigned char **)&ptr, keylen))) {
#else
			if(!(pkey = d2i_PrivateKey(EVP_PKEY_RSA,
				NULL, &ptr, keylen))) {
#endif
				openssl_strerror("d2i_PrivateKey");
				return(sigcomp_sign_return(false,
					key, msg, signature, pkey));
			}

			signaturelen	= RSA_size(pkey->pkey.rsa);
			padding		= RSA_PKCS1_PADDING;

			break;
		}

		if(!strcmp(type, "dsa")) {
#if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x0090800fL)
			if(!(pkey = d2i_PrivateKey(EVP_PKEY_DSA,
				NULL, (const unsigned char **)&ptr, keylen))) {
#else
			if(!(pkey = d2i_PrivateKey(EVP_PKEY_DSA,
				NULL, &ptr, keylen))) {
#endif

				openssl_strerror("d2i_PrivateKey");
				return(sigcomp_sign_return(false,
					key, msg, signature, pkey));
			}

			fprintf(stderr, "err: type: %s -- not implemented\n",
				type);

			return(sigcomp_sign_return(false,
				key, msg, signature, pkey));

			break;
		}

		fprintf(stderr, "err: type: %s -- unknown type\n",
			type);

		return(sigcomp_sign_return(false, key, msg, signature, pkey));
		/* NOTREACHED */
	}

	if(!(signature = (unsigned char *)malloc(signaturelen))) {
		fprintf(stderr, "err: malloc: %s\n", strerror(errno));
		return(sigcomp_sign_return(false, key, msg, signature, pkey));
	}

	RSA_private_encrypt(msglen, msg, signature, pkey->pkey.rsa, padding);
#ifdef DEBUG
	dmp(stderr, "signature", signature, signaturelen);
#endif	// DEBUG
	sigcomp_sign_dump(key, keylen, msg, msglen, signature, signaturelen);

	return(sigcomp_sign_return(true, key, msg, signature, pkey));
}



static void
sigcomp_sign_dump(const unsigned char *const key, int keylen,
	const unsigned char *const msg, int msglen,
	const unsigned char *const signature, int signaturelen)
{
	int d = 0;

	if(xxxflag) {
#if 0	/* needless */
		for(d = 0; d < msglen; d ++) {
			printf("%02x", msg[d]);
		}
#endif
		for(d = 0; d < signaturelen; d ++) {
			printf("%02x", signature[d]);
		}

		printf("\n");

		return;
	}

	printf("log:SigCompSign_Results             (length:%d)\n",
		keylen + msglen + signaturelen);

	printf("log:| PrivateKey                      (length:%d)\n", keylen);
	printf("log:| | data                             = ");

	for(d = 0; d < keylen; d ++) {
		printf("%02x", key[d]);
	}

	printf("\n");

	printf("log:| Message                         (length:%d)\n", msglen);
	printf("log:| | data                             = ");

	for(d = 0; d < msglen; d ++) {
		printf("%02x", msg[d]);
	}

	printf("\n");

	printf("log:| Signature                       (length:%d)\n",
		signaturelen);

	printf("log:| | data                             = ");

	for(d = 0; d < signaturelen; d ++) {
		printf("%02x", signature[d]);
	}

	printf("\n");

	return;
}



static bool
sigcomp_sign_return(const bool code,
	unsigned char *key, unsigned char *msg, unsigned char *signature,
	EVP_PKEY *pkey)
{
	if(pkey) {
		EVP_PKEY_free(pkey); pkey = NULL;
	}

	if(signature) {
		free(signature); signature = NULL;
	}

	if(msg) {
		free(msg); msg = NULL;
	}

	if(key) {
		free(key); key = NULL;
	}

	return(code);
}



static bool
sigcomp_vrfy(const EVP_MD *const evp_md, const BIGNUM *const bn_key,
	const BIGNUM *const bn_msg,
	const BIGNUM *const bn_signature, const char *const type)
{
	EVP_PKEY *pkey  = NULL;

	unsigned char *key		= NULL;
	unsigned char *msg		= NULL;
	unsigned char *signature	= NULL;
	unsigned char *to		= NULL;
	unsigned char *ptr		= NULL;

	int keylen		= 0;
	int msglen		= 0;
	int signaturelen	= 0;
	int tolen		= 0;
	int padding		= 0;

	bool compare		= true;

	/* bn_key -> key */
	if(!(keylen = BN_num_bytes(bn_key))) {
		openssl_strerror("BN_num_bytes");
		return(sigcomp_vrfy_return(false,
			key, msg, signature, to, pkey));
	}

	if(!(key = (unsigned char *)malloc(keylen))) {
		fprintf(stderr, "err: malloc: %s\n", strerror(errno));
		return(sigcomp_vrfy_return(false,
			key, msg, signature, to, pkey));
	}

	if(BN_bn2bin(bn_key, key) != keylen) {
		openssl_strerror("BN_bn2bin");
		return(sigcomp_vrfy_return(false,
			key, msg, signature, to, pkey));
	}
#ifdef DEBUG
	dmp(stderr, "key", key, keylen);
#endif  // DEBUG
	/* bn_msg -> msg */
        if(!(msglen = BN_num_bytes(bn_msg))) {
		openssl_strerror("BN_num_bytes");
		return(sigcomp_vrfy_return(false,
			key, msg, signature, to, pkey));
        }

	if(!(msg = (unsigned char *)malloc(msglen))) {
		fprintf(stderr, "err: malloc: %s\n", strerror(errno));
		return(sigcomp_vrfy_return(false,
			key, msg, signature, to, pkey));
	}

	if(BN_bn2bin(bn_msg, msg) != msglen) {
		openssl_strerror("BN_bn2bin");
		return(sigcomp_vrfy_return(false,
			key, msg, signature, to, pkey));
	}
#ifdef DEBUG
	dmp(stderr, "msg", msg, msglen);
#endif  // DEBUG
	/* bn_signature -> signature */
        if(!(signaturelen = BN_num_bytes(bn_signature))) {
		openssl_strerror("BN_num_bytes");
		return(sigcomp_vrfy_return(false,
			key, msg, signature, to, pkey));
        }

	if(!(signature = (unsigned char *)malloc(signaturelen))) {
		fprintf(stderr, "err: malloc: %s\n", strerror(errno));
		return(sigcomp_vrfy_return(false,
			key, msg, signature, to, pkey));
	}

	if(BN_bn2bin(bn_signature, signature) != signaturelen) {
		openssl_strerror("BN_bn2bin");
		return(sigcomp_vrfy_return(false,
			key, msg, signature, to, pkey));
	}
#ifdef DEBUG
	dmp(stderr, "signature", signature, signaturelen);
#endif  // DEBUG
        ptr = key;

	for( ; ; ) {
		if(!strcmp(type, "rsa")) {
#if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x0090800fL)
			if(!(pkey = d2i_PublicKey(EVP_PKEY_RSA,
				NULL, (const unsigned char **)&ptr, keylen))) {
#else
			if(!(pkey = d2i_PublicKey(EVP_PKEY_RSA,
				NULL, &ptr, keylen))) {
#endif

				openssl_strerror("d2i_PublicKey");
				return(sigcomp_vrfy_return(false,
					key, msg, signature, to, pkey));
			}

			tolen		= RSA_size(pkey->pkey.rsa);
			padding		= RSA_PKCS1_PADDING;

			break;
		}

		if(!strcmp(type, "dsa")) {
#if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x0090800fL)
			if(!(pkey = d2i_PublicKey(EVP_PKEY_DSA,
				NULL, (const unsigned char **)&ptr, keylen))) {
#else
			if(!(pkey = d2i_PublicKey(EVP_PKEY_DSA,
				NULL, &ptr, keylen))) {
#endif

				openssl_strerror("d2i_PublicKey");
				return(sigcomp_vrfy_return(false,
					key, msg, signature, to, pkey));
			}

			fprintf(stderr, "err: type: %s -- not implemented\n",
				type);

			return(sigcomp_vrfy_return(false,
				key, msg, signature, to, pkey));
			/* NOTREACHED */

			break;
		}

		fprintf(stderr, "err: type: %s -- unknown type\n",
			type);

		return(sigcomp_vrfy_return(false,
			key, msg, signature, to, pkey));
		/* NOTREACHED */
	}

	if(!(to = (unsigned char *)malloc(tolen))) {
		fprintf(stderr, "err: malloc: %s\n", strerror(errno));
		return(sigcomp_vrfy_return(false,
			key, msg, signature, to, pkey));
	}

	if(RSA_public_decrypt(signaturelen,
		signature, to, pkey->pkey.rsa, padding) < 0) {

		openssl_strerror("RSA_public_decrypt");
		return(sigcomp_vrfy_return(true,
			key, msg, signature, to, pkey));
	}

	if(memcmp(msg, to, msglen)) {
		compare	= false;
	}

	sigcomp_vrfy_dump(compare, key, keylen,
		msg, msglen, signature, signaturelen, to, tolen);

	return(sigcomp_vrfy_return(true, key, msg, signature, to, pkey));
}



static void
sigcomp_vrfy_dump(const bool code, const unsigned char *const key, int keylen,
	const unsigned char *const msg, int msglen,
	const unsigned char *const signature, int signaturelen,
	const unsigned char *const to, int tolen)
{
	int d = 0;

	printf("log:SigCompVrfy_Results             (length:%d)\n",
		keylen + msglen + signaturelen + tolen);

	printf("log:| PublicKey                       (length:%d)\n", keylen);
	printf("log:| | data                             = ");

	for(d = 0; d < keylen; d ++) {
		printf("%02x", key[d]);
	}

	printf("\n");

	printf("log:| Message                         (length:%d)\n", msglen);
	printf("log:| | data                             = ");

	for(d = 0; d < msglen; d ++) {
		printf("%02x", msg[d]);
	}

	printf("\n");

	printf("log:| Signature                       (length:%d)\n",
		signaturelen + tolen);

	printf("log:| | status                           = %s\n",
		code? "true": "false");

	printf("log:| | Encrypted                       (length:%d)\n",
		signaturelen);

	printf("log:| | | data                             = ");

	for(d = 0; d < signaturelen; d ++) {
		printf("%02x", signature[d]);
	}

	printf("\n");

	printf("log:| | Decrypted                       (length:%d)\n", tolen);
	printf("log:| | | data                             = ");

	for(d = 0; d < tolen; d ++) {
		printf("%02x", to[d]);
	}

	printf("\n");

	return;
}



static bool
sigcomp_vrfy_return(const bool code,
	unsigned char *key, unsigned char *msg, unsigned char *signature,
	unsigned char *to, EVP_PKEY *pkey)
{
	if(pkey) {
		EVP_PKEY_free(pkey); pkey = NULL;
	}

	if(to) {
		free(to); to = NULL;
	}

	if(signature) {
		free(signature); signature = NULL;
	}

	if(msg) {
		free(msg); msg = NULL;
	}

	if(key) {
		free(key); key = NULL;
	}

	return(code);
}



static const EVP_MD *
evp_md_with_algorithm(const char *const type, const char *const algorithm)
{
	const EVP_MD *evp_md	= NULL;
	bool dsa	= false;
	bool rsa	= false;

	for( ; ; ) {
		if(!strcmp(type, "dsa")) {
			dsa = true;
			break;
		}

		if(!strcmp(type, "rsa")) {
			rsa = true;
			break;
		}

		break;
	}

	for( ; ; ) {
		if(dsa && !strcmp(algorithm, "dss1")) {
			evp_md = EVP_dss1();
			break;
		}

		if(rsa && !strcmp(algorithm, "md2")) {
			evp_md = EVP_md2();
			break;
		}

		if(rsa && !strcmp(algorithm, "md4")) {
			evp_md = EVP_md4();
			break;
		}

		if(rsa && !strcmp(algorithm, "md5")) {
			evp_md = EVP_md5();
			break;
		}

#if ! defined(__linux__)
		if(rsa && !strcmp(algorithm, "mdc2")) {
			evp_md = EVP_mdc2();
			break;
		}
#endif

		if(rsa && !strcmp(algorithm, "ripemd160")) {
			evp_md = EVP_ripemd160();
			break;
		}

		if(rsa && !strcmp(algorithm, "sha1")) {
			evp_md = EVP_sha1();
			break;
		}

		break;
	}

	return(evp_md);
}



static void
openssl_strerror(const char *const label)
{
	unsigned long code = 0;

	while((code = ERR_get_error())) {
		fprintf(stderr, "err: %s: %s\n",
			label, ERR_error_string(code, NULL));
	}

	return;
}