static int post_cb(int op, int id, int subid, void *ex)
	{
	const char *idstr, *exstr = "";
	char asctmp[20];
	int keytype = -1;
	int exp_fail = 0;
#ifdef FIPS_POST_TIME
	static struct timespec start, end, tstart, tend;
#endif
	switch(id)
		{
		case FIPS_TEST_INTEGRITY:
		idstr = "Integrity";
		break;

		case FIPS_TEST_DIGEST:
		idstr = "Digest";
		exstr = lookup_id(subid);
		break;

		case FIPS_TEST_CIPHER:
		exstr = lookup_id(subid);
		idstr = "Cipher";
		break;

		case FIPS_TEST_SIGNATURE:
		if (ex)
			{
			EVP_PKEY *pkey = ex;
			keytype = pkey->type;
			if (keytype == EVP_PKEY_EC)
				{
				const EC_GROUP *grp;
				int cnid;
				grp = EC_KEY_get0_group(pkey->pkey.ec);
				cnid = EC_GROUP_get_curve_name(grp);
				sprintf(asctmp, "ECDSA %s", lookup_id(cnid));
				exstr = asctmp;
				}
			else
				exstr = lookup_id(keytype);
			}
		idstr = "Signature";
		break;

		case FIPS_TEST_HMAC:
		exstr = lookup_id(subid);
		idstr = "HMAC";
		break;

		case FIPS_TEST_CMAC:
		idstr = "CMAC";
		exstr = lookup_id(subid);
		break;

		case FIPS_TEST_GCM:
		idstr = "GCM";
		break;

		case FIPS_TEST_XTS:
		idstr = "XTS";
		exstr = lookup_id(subid);
		break;

		case FIPS_TEST_CCM:
		idstr = "CCM";
		break;

		case FIPS_TEST_X931:
		idstr = "X9.31 PRNG";
		sprintf(asctmp, "keylen=%d", subid);
		exstr = asctmp;
		break;

		case FIPS_TEST_DRBG:
		idstr = "DRBG";
		if (*(int *)ex & DRBG_FLAG_CTR_USE_DF)
			{
			sprintf(asctmp, "%s DF", lookup_id(subid));
			exstr = asctmp;
			}
		else if (subid >> 16)
			{
			sprintf(asctmp, "%s %s",
					lookup_id(subid >> 16),
					lookup_id(subid & 0xFFFF));
			exstr = asctmp;
			}
		else
			exstr = lookup_id(subid);
		break;

		case FIPS_TEST_PAIRWISE:
		if (ex)
			{
			EVP_PKEY *pkey = ex;
			keytype = pkey->type;
			exstr = lookup_id(keytype);
			}
		idstr = "Pairwise Consistency";
		break;

		case FIPS_TEST_CONTINUOUS:
		idstr = "Continuous PRNG";
		break;

		case FIPS_TEST_ECDH:
		idstr = "ECDH";
		exstr = lookup_id(subid);
		break;

		default:
		idstr = "Unknown";
		break;

		}

	if (fail_id == id
		&& (fail_key == -1 || fail_key == keytype)
		&& (fail_sub == -1 || fail_sub == subid))
			exp_fail = 1;

	switch(op)
		{
		case FIPS_POST_BEGIN:
#ifdef FIPS_POST_TIME
		clock_getres(CLOCK_REALTIME, &tstart);
		printf("\tTimer resolution %ld s, %ld ns\n",
				(long)tstart.tv_sec, (long)tstart.tv_nsec);
		clock_gettime(CLOCK_REALTIME, &tstart);
#endif
		printf("\tPOST started\n");
		break;

		case FIPS_POST_END:
		printf("\tPOST %s\n", id ? "Success" : "Failed");
#ifdef FIPS_POST_TIME
		clock_gettime(CLOCK_REALTIME, &tend);
		printf("\t\tTook %f seconds\n",
			(double)((tend.tv_sec+tend.tv_nsec*1e-9)
                        - (tstart.tv_sec+tstart.tv_nsec*1e-9)));
#endif
		break;

		case FIPS_POST_STARTED:
		if (!post_quiet && !exp_fail)
			printf("\t\t%s %s test started\n", idstr, exstr);
#ifdef FIPS_POST_TIME
		clock_gettime(CLOCK_REALTIME, &start);
#endif
		break;

		case FIPS_POST_SUCCESS:
		if (exp_fail)
			{
			printf("\t\t%s %s test OK but should've failed\n",
								idstr, exstr);
			st_err++;
			}
		else if (!post_quiet)
			printf("\t\t%s %s test OK\n", idstr, exstr);
#ifdef FIPS_POST_TIME
		clock_gettime(CLOCK_REALTIME, &end);
		printf("\t\t\tTook %f seconds\n",
			(double)((end.tv_sec+end.tv_nsec*1e-9)
                        - (start.tv_sec+start.tv_nsec*1e-9)));
#endif
		break;

		case FIPS_POST_FAIL:
		if (exp_fail)
			{
			printf("\t\t%s %s test failed as expected\n",
							idstr, exstr);
			}
		else
			{
			printf("\t\t%s %s test Failed Incorrectly!!\n",
							idstr, exstr);
			st_err++;
			}
		break;

		case FIPS_POST_CORRUPT:
		if (exp_fail)
			{
			printf("\t\t%s %s test failure induced\n", idstr, exstr);
			return 0;
			}
		break;

		}
	return 1;
	}
static int post_cb(int op, int id, int subid, void *ex)
	{
	const char *idstr, *exstr = "";
	char asctmp[20];
	int keytype = -1;
	int exp_fail = 0;
#ifdef FIPS_POST_TIME
	static struct timespec start, end, tstart, tend;
#endif
	switch(id)
		{
		case FIPS_TEST_INTEGRITY:
		idstr = "Integrity";
		break;

		case FIPS_TEST_DIGEST:
		idstr = "Digest";
		exstr = lookup_id(subid);
		break;

		case FIPS_TEST_CIPHER:
		exstr = lookup_id(subid);
		idstr = "Cipher";
		break;

		case FIPS_TEST_SIGNATURE:
		if (ex)
			{
			EVP_PKEY *pkey = ex;
			keytype = pkey->type;
			if (keytype == EVP_PKEY_EC)
				{
				const EC_GROUP *grp;
				int cnid;
				grp = EC_KEY_get0_group(pkey->pkey.ec);
				cnid = EC_GROUP_get_curve_name(grp);
				sprintf(asctmp, "ECDSA %s", lookup_id(cnid));
				exstr = asctmp;
				}
			else
				exstr = lookup_id(keytype);
			}
		idstr = "Signature";
		break;

		case FIPS_TEST_HMAC:
		exstr = lookup_id(subid);
		idstr = "HMAC";
		break;

		case FIPS_TEST_CMAC:
		idstr = "CMAC";
		exstr = lookup_id(subid);
		break;

		case FIPS_TEST_GCM:
		idstr = "GCM";
		break;

		case FIPS_TEST_XTS:
		idstr = "XTS";
		exstr = lookup_id(subid);
		break;

		case FIPS_TEST_CCM:
		idstr = "CCM";
		break;

		case FIPS_TEST_X931:
		idstr = "X9.31 PRNG";
		sprintf(asctmp, "keylen=%d", subid);
		exstr = asctmp;
		break;

		case FIPS_TEST_DRBG:
		idstr = "DRBG";
		if (*(int *)ex & DRBG_FLAG_CTR_USE_DF)
			{
			sprintf(asctmp, "%s DF", lookup_id(subid));
			exstr = asctmp;
			}
		else if (subid >> 16)
			{
			sprintf(asctmp, "%s %s",
					lookup_id(subid >> 16),
					lookup_id(subid & 0xFFFF));
			exstr = asctmp;
			}
		else
			exstr = lookup_id(subid);
		break;

		case FIPS_TEST_PAIRWISE:
		if (ex)
			{
			EVP_PKEY *pkey = ex;
			keytype = pkey->type;
			exstr = lookup_id(keytype);
			}
		idstr = "Pairwise Consistency";
		break;

		case FIPS_TEST_CONTINUOUS:
		idstr = "Continuous PRNG";
		break;

		case FIPS_TEST_ECDH:
		idstr = "ECDH";
		exstr = lookup_id(subid);
		break;

		default:
		idstr = "Unknown";
		break;

		}

	if (fail_id == id
		&& (fail_key == -1 || fail_key == keytype)
		&& (fail_sub == -1 || fail_sub == subid))
			exp_fail = 1;

	switch(op)
		{
		case FIPS_POST_BEGIN:
#ifdef FIPS_POST_TIME
		clock_getres(CLOCK_REALTIME, &tstart);
		printf("\tTimer resolution %ld s, %ld ns\n",
				(long)tstart.tv_sec, (long)tstart.tv_nsec);
		clock_gettime(CLOCK_REALTIME, &tstart);
#endif
		printf("\tPOST started\n");
		break;

		case FIPS_POST_END:
		printf("\tPOST %s\n", id ? "Success" : "Failed");
#ifdef FIPS_POST_TIME
		clock_gettime(CLOCK_REALTIME, &tend);
		printf("\t\tTook %f seconds\n",
			(double)((tend.tv_sec+tend.tv_nsec*1e-9)
                        - (tstart.tv_sec+tstart.tv_nsec*1e-9)));
#endif
		break;

		case FIPS_POST_STARTED:
		if (!post_quiet && !exp_fail)
			printf("\t\t%s %s test started\n", idstr, exstr);
#ifdef FIPS_POST_TIME
		clock_gettime(CLOCK_REALTIME, &start);
#endif
		break;

		case FIPS_POST_SUCCESS:
		if (exp_fail)
			{
			printf("\t\t%s %s test OK but should've failed\n",
								idstr, exstr);
			st_err++;
			}
		else if (!post_quiet)
			printf("\t\t%s %s test OK\n", idstr, exstr);
#ifdef FIPS_POST_TIME
		clock_gettime(CLOCK_REALTIME, &end);
		printf("\t\t\tTook %f seconds\n",
			(double)((end.tv_sec+end.tv_nsec*1e-9)
                        - (start.tv_sec+start.tv_nsec*1e-9)));
#endif
		break;

		case FIPS_POST_FAIL:
		if (exp_fail)
			{
			printf("\t\t%s %s test failed as expected\n",
							idstr, exstr);
			}
		else
			{
			printf("\t\t%s %s test Failed Incorrectly!!\n",
							idstr, exstr);
			st_err++;
			}
		break;

		case FIPS_POST_CORRUPT:
		if (exp_fail)
			{
			printf("\t\t%s %s test failure induced\n", idstr, exstr);
			return 0;
			}
		break;

		}
	return 1;
	}