static int internal_verify(X509_STORE_CTX *ctx)
	{
	int i,ok=0,n;
	X509 *xs,*xi;
	EVP_PKEY *pkey=NULL;
	time_t *ptime;
	int (*cb)();

	cb=ctx->verify_cb;
	if (cb == NULL) cb=null_callback;

	n=sk_X509_num(ctx->chain);
	ctx->error_depth=n-1;
	n--;
	xi=sk_X509_value(ctx->chain,n);
	if(ctx->flags & X509_V_FLAG_USE_CHECK_TIME) ptime = &ctx->check_time;
	else ptime = NULL;
	if (ctx->check_issued(ctx, xi, xi))
		xs=xi;
	else
		{
		if (n <= 0)
			{
			ctx->error=X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE;
			ctx->current_cert=xi;
			ok=cb(0,ctx);
			goto end;
			}
		else
			{
			n--;
			ctx->error_depth=n;
			xs=sk_X509_value(ctx->chain,n);
			}
		}

/*	ctx->error=0;  not needed */
	while (n >= 0)
		{
		ctx->error_depth=n;
		if (!xs->valid)
			{
			if ((pkey=X509_get_pubkey(xi)) == NULL)
				{
				ctx->error=X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
				ctx->current_cert=xi;
				ok=(*cb)(0,ctx);
				if (!ok) goto end;
				}
			if (X509_verify(xs,pkey) <= 0)
				{
				ctx->error=X509_V_ERR_CERT_SIGNATURE_FAILURE;
				ctx->current_cert=xs;
				ok=(*cb)(0,ctx);
				if (!ok)
					{
					EVP_PKEY_free(pkey);
					goto end;
					}
				}
			EVP_PKEY_free(pkey);
			pkey=NULL;

			i=X509_cmp_time(X509_get_notBefore(xs), ptime);
			if (i == 0)
				{
				ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD;
				ctx->current_cert=xs;
				ok=(*cb)(0,ctx);
				if (!ok) goto end;
				}
			if (i > 0)
				{
				ctx->error=X509_V_ERR_CERT_NOT_YET_VALID;
				ctx->current_cert=xs;
				ok=(*cb)(0,ctx);
				if (!ok) goto end;
				}
			xs->valid=1;
			}

		i=X509_cmp_time(X509_get_notAfter(xs), ptime);
		if (i == 0)
			{
			ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD;
			ctx->current_cert=xs;
			ok=(*cb)(0,ctx);
			if (!ok) goto end;
			}

		if (i < 0)
			{
			ctx->error=X509_V_ERR_CERT_HAS_EXPIRED;
			ctx->current_cert=xs;
			ok=(*cb)(0,ctx);
			if (!ok) goto end;
			}

		/* CRL CHECK */

		/* The last error (if any) is still in the error value */
		ctx->current_cert=xs;
		ok=(*cb)(1,ctx);
		if (!ok) goto end;

		n--;
		if (n >= 0)
			{
			xi=xs;
			xs=sk_X509_value(ctx->chain,n);
			}
		}
	ok=1;
end:
	return(ok);
	}