int gost_do_verify(const unsigned char *dgst, int dgst_len,
	DSA_SIG *sig, DSA *dsa)
	{
	BIGNUM *md, *tmp=NULL;
	BIGNUM *q2=NULL;
	BIGNUM *u=NULL,*v=NULL,*z1=NULL,*z2=NULL;
	BIGNUM *tmp2=NULL,*tmp3=NULL;
	int ok;
	BN_CTX *ctx = BN_CTX_new();

	BN_CTX_start(ctx);
	if (BN_cmp(sig->s,dsa->q)>=1||
		BN_cmp(sig->r,dsa->q)>=1)
		{
		GOSTerr(GOST_F_GOST_DO_VERIFY,GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q);
		return 0;
		}
	md=hashsum2bn(dgst);
	
	tmp=BN_CTX_get(ctx);
	v=BN_CTX_get(ctx);
	q2=BN_CTX_get(ctx);
	z1=BN_CTX_get(ctx);
	z2=BN_CTX_get(ctx);
	tmp2=BN_CTX_get(ctx);
	tmp3=BN_CTX_get(ctx);
	u = BN_CTX_get(ctx);
	
	BN_mod(tmp,md,dsa->q,ctx);
	if (BN_is_zero(tmp))
		{
		BN_one(md);
		}
	BN_copy(q2,dsa->q);
	BN_sub_word(q2,2);
	BN_mod_exp(v,md,q2,dsa->q,ctx);
	BN_mod_mul(z1,sig->s,v,dsa->q,ctx);
	BN_sub(tmp,dsa->q,sig->r);
	BN_mod_mul(z2,tmp,v,dsa->p,ctx);
	BN_mod_exp(tmp,dsa->g,z1,dsa->p,ctx);
	BN_mod_exp(tmp2,dsa->pub_key,z2,dsa->p,ctx);
	BN_mod_mul(tmp3,tmp,tmp2,dsa->p,ctx);
	BN_mod(u,tmp3,dsa->q,ctx);
	ok= BN_cmp(u,sig->r);
	
	BN_free(md);
	BN_CTX_end(ctx);
	BN_CTX_free(ctx);
	if (ok!=0)
		{
		GOSTerr(GOST_F_GOST_DO_VERIFY,GOST_R_SIGNATURE_MISMATCH);
		}	
	return (ok==0);
	}