static int ubsec_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
		const BIGNUM *m, BN_CTX *ctx)
	{
	int 	y_len = 0;
	int 	fd;

	if(ubsec_dso == NULL)
	{
		UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_NOT_LOADED);
		return 0;
	}

	/* Check if hardware can't handle this argument. */
	y_len = BN_num_bits(m);
	if (y_len > max_key_len) {
		UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
                return BN_mod_exp(r, a, p, m, ctx);
	} 

	if(!bn_wexpand(r, m->top))
	{
		UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_BN_EXPAND_FAIL);
		return 0;
	}
	memset(r->d, 0, BN_num_bytes(m));

	if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) {
		fd = 0;
		UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_UNIT_FAILURE);
                return BN_mod_exp(r, a, p, m, ctx);
	}

	if (p_UBSEC_rsa_mod_exp_ioctl(fd, (unsigned char *)a->d, BN_num_bits(a),
		(unsigned char *)m->d, BN_num_bits(m), (unsigned char *)p->d, 
		BN_num_bits(p), (unsigned char *)r->d, &y_len) != 0)
	{
		UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_REQUEST_FAILED);
                p_UBSEC_ubsec_close(fd);

                return BN_mod_exp(r, a, p, m, ctx);
	}

	p_UBSEC_ubsec_close(fd);

	r->top = (BN_num_bits(m)+BN_BITS2-1)/BN_BITS2;
	return 1;
	}