Exemple #1
0
int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d,
           BN_CTX *ctx)
{
    int i, nm, nd;
    int ret = 0;
    BIGNUM *D;

    bn_check_top(m);
    bn_check_top(d);
    if (BN_is_zero(d)) {
        BNerr(BN_F_BN_DIV, BN_R_DIV_BY_ZERO);
        return (0);
    }

    if (BN_ucmp(m, d) < 0) {
        if (rem != NULL) {
            if (BN_copy(rem, m) == NULL)
                return (0);
        }
        if (dv != NULL)
            BN_zero(dv);
        return (1);
    }

    BN_CTX_start(ctx);
    D = BN_CTX_get(ctx);
    if (dv == NULL)
        dv = BN_CTX_get(ctx);
    if (rem == NULL)
        rem = BN_CTX_get(ctx);
    if (D == NULL || dv == NULL || rem == NULL)
        goto end;

    nd = BN_num_bits(d);
    nm = BN_num_bits(m);
    if (BN_copy(D, d) == NULL)
        goto end;
    if (BN_copy(rem, m) == NULL)
        goto end;

    /*
     * The next 2 are needed so we can do a dv->d[0]|=1 later since
     * BN_lshift1 will only work once there is a value :-)
     */
    BN_zero(dv);
    if (bn_wexpand(dv, 1) == NULL)
        goto end;
    dv->top = 1;

    if (!BN_lshift(D, D, nm - nd))
        goto end;
    for (i = nm - nd; i >= 0; i--) {
        if (!BN_lshift1(dv, dv))
            goto end;
        if (BN_ucmp(rem, D) >= 0) {
            dv->d[0] |= 1;
            if (!BN_usub(rem, rem, D))
                goto end;
        }
/* CAN IMPROVE (and have now :=) */
        if (!BN_rshift1(D, D))
            goto end;
    }
    rem->neg = BN_is_zero(rem) ? 0 : m->neg;
    dv->neg = m->neg ^ d->neg;
    ret = 1;
 end:
    BN_CTX_end(ctx);
    return (ret);
}
Exemple #2
0
BIGNUM *BN_mod_inverse(BIGNUM *in,
	const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx)
	{
	BIGNUM *A,*B,*X,*Y,*M,*D,*T,*R=NULL;
	BIGNUM *ret=NULL;
	int sign;

	if ((BN_get_flags(a, BN_FLG_CONSTTIME) != 0) || (BN_get_flags(n, BN_FLG_CONSTTIME) != 0))
		{
		return BN_mod_inverse_no_branch(in, a, n, ctx);
		}

	bn_check_top(a);
	bn_check_top(n);

	BN_CTX_start(ctx);
	A = BN_CTX_get(ctx);
	B = BN_CTX_get(ctx);
	X = BN_CTX_get(ctx);
	D = BN_CTX_get(ctx);
	M = BN_CTX_get(ctx);
	Y = BN_CTX_get(ctx);
	T = BN_CTX_get(ctx);
	if (T == NULL) goto err;

	if (in == NULL)
		R=BN_new();
	else
		R=in;
	if (R == NULL) goto err;

	BN_one(X);
	BN_zero(Y);
	if (BN_copy(B,a) == NULL) goto err;
	if (BN_copy(A,n) == NULL) goto err;
	A->neg = 0;
	if (B->neg || (BN_ucmp(B, A) >= 0))
		{
		if (!BN_nnmod(B, B, A, ctx)) goto err;
		}
	sign = -1;
	/* From  B = a mod |n|,  A = |n|  it follows that
	 *
	 *      0 <= B < A,
	 *     -sign*X*a  ==  B   (mod |n|),
	 *      sign*Y*a  ==  A   (mod |n|).
	 */

#if 0
	if (BN_is_odd(n) && (BN_num_bits(n) <= (BN_BITS <= 32 ? 450 : 2048)))
		{
		/* Binary inversion algorithm; requires odd modulus.
		 * This is faster than the general algorithm if the modulus
		 * is sufficiently small (about 400 .. 500 bits on 32-bit
		 * sytems, but much more on 64-bit systems) */
		int shift;
		
		while (!BN_is_zero(B))
			{
			/*
			 *      0 < B < |n|,
			 *      0 < A <= |n|,
			 * (1) -sign*X*a  ==  B   (mod |n|),
			 * (2)  sign*Y*a  ==  A   (mod |n|)
			 */

			/* Now divide  B  by the maximum possible power of two in the integers,
			 * and divide  X  by the same value mod |n|.
			 * When we're done, (1) still holds. */
			shift = 0;
			while (!BN_is_bit_set(B, shift)) /* note that 0 < B */
				{
				shift++;
				
				if (BN_is_odd(X))
					{
					if (!BN_uadd(X, X, n)) goto err;
					}
				/* now X is even, so we can easily divide it by two */
				if (!BN_rshift1(X, X)) goto err;
				}
			if (shift > 0)
				{
				if (!BN_rshift(B, B, shift)) goto err;
				}


			/* Same for  A  and  Y.  Afterwards, (2) still holds. */
			shift = 0;
			while (!BN_is_bit_set(A, shift)) /* note that 0 < A */
				{
				shift++;
				
				if (BN_is_odd(Y))
					{
					if (!BN_uadd(Y, Y, n)) goto err;
					}
				/* now Y is even */
				if (!BN_rshift1(Y, Y)) goto err;
				}
			if (shift > 0)
				{
				if (!BN_rshift(A, A, shift)) goto err;
				}

			
			/* We still have (1) and (2).
			 * Both  A  and  B  are odd.
			 * The following computations ensure that
			 *
			 *     0 <= B < |n|,
			 *      0 < A < |n|,
			 * (1) -sign*X*a  ==  B   (mod |n|),
			 * (2)  sign*Y*a  ==  A   (mod |n|),
			 *
			 * and that either  A  or  B  is even in the next iteration.
			 */
			if (BN_ucmp(B, A) >= 0)
				{
				/* -sign*(X + Y)*a == B - A  (mod |n|) */
				if (!BN_uadd(X, X, Y)) goto err;
				/* NB: we could use BN_mod_add_quick(X, X, Y, n), but that
				 * actually makes the algorithm slower */
				if (!BN_usub(B, B, A)) goto err;
				}
			else
				{
				/*  sign*(X + Y)*a == A - B  (mod |n|) */
				if (!BN_uadd(Y, Y, X)) goto err;
				/* as above, BN_mod_add_quick(Y, Y, X, n) would slow things down */
				if (!BN_usub(A, A, B)) goto err;
				}
			}
		}
	else
#endif
		{
		/* general inversion algorithm */

		while (!BN_is_zero(B))
			{
			BIGNUM *tmp;
			
			/*
			 *      0 < B < A,
			 * (*) -sign*X*a  ==  B   (mod |n|),
			 *      sign*Y*a  ==  A   (mod |n|)
			 */
			
			/* (D, M) := (A/B, A%B) ... */
			if (BN_num_bits(A) == BN_num_bits(B))
				{
				if (!BN_one(D)) goto err;
				if (!BN_sub(M,A,B)) goto err;
				}
			else if (BN_num_bits(A) == BN_num_bits(B) + 1)
				{
				/* A/B is 1, 2, or 3 */
				if (!BN_lshift1(T,B)) goto err;
				if (BN_ucmp(A,T) < 0)
					{
					/* A < 2*B, so D=1 */
					if (!BN_one(D)) goto err;
					if (!BN_sub(M,A,B)) goto err;
					}
				else
					{
					/* A >= 2*B, so D=2 or D=3 */
					if (!BN_sub(M,A,T)) goto err;
					if (!BN_add(D,T,B)) goto err; /* use D (:= 3*B) as temp */
					if (BN_ucmp(A,D) < 0)
						{
						/* A < 3*B, so D=2 */
						if (!BN_set_word(D,2)) goto err;
						/* M (= A - 2*B) already has the correct value */
						}
					else
						{
						/* only D=3 remains */
						if (!BN_set_word(D,3)) goto err;
						/* currently  M = A - 2*B,  but we need  M = A - 3*B */
						if (!BN_sub(M,M,B)) goto err;
						}
					}
				}
			else
				{
				if (!BN_div(D,M,A,B,ctx)) goto err;
				}
			
			/* Now
			 *      A = D*B + M;
			 * thus we have
			 * (**)  sign*Y*a  ==  D*B + M   (mod |n|).
			 */
			
			tmp=A; /* keep the BIGNUM object, the value does not matter */
			
			/* (A, B) := (B, A mod B) ... */
			A=B;
			B=M;
			/* ... so we have  0 <= B < A  again */
			
			/* Since the former  M  is now  B  and the former  B  is now  A,
			 * (**) translates into
			 *       sign*Y*a  ==  D*A + B    (mod |n|),
			 * i.e.
			 *       sign*Y*a - D*A  ==  B    (mod |n|).
			 * Similarly, (*) translates into
			 *      -sign*X*a  ==  A          (mod |n|).
			 *
			 * Thus,
			 *   sign*Y*a + D*sign*X*a  ==  B  (mod |n|),
			 * i.e.
			 *        sign*(Y + D*X)*a  ==  B  (mod |n|).
			 *
			 * So if we set  (X, Y, sign) := (Y + D*X, X, -sign),  we arrive back at
			 *      -sign*X*a  ==  B   (mod |n|),
			 *       sign*Y*a  ==  A   (mod |n|).
			 * Note that  X  and  Y  stay non-negative all the time.
			 */
			
			/* most of the time D is very small, so we can optimize tmp := D*X+Y */
			if (BN_is_one(D))
				{
				if (!BN_add(tmp,X,Y)) goto err;
				}
			else
				{
				if (BN_is_word(D,2))
					{
					if (!BN_lshift1(tmp,X)) goto err;
					}
				else if (BN_is_word(D,4))
					{
					if (!BN_lshift(tmp,X,2)) goto err;
					}
				else if (D->top == 1)
					{
					if (!BN_copy(tmp,X)) goto err;
					if (!BN_mul_word(tmp,D->d[0])) goto err;
					}
				else
					{
					if (!BN_mul(tmp,D,X,ctx)) goto err;
					}
				if (!BN_add(tmp,tmp,Y)) goto err;
				}
			
			M=Y; /* keep the BIGNUM object, the value does not matter */
			Y=X;
			X=tmp;
			sign = -sign;
			}
		}
		
	/*
	 * The while loop (Euclid's algorithm) ends when
	 *      A == gcd(a,n);
	 * we have
	 *       sign*Y*a  ==  A  (mod |n|),
	 * where  Y  is non-negative.
	 */

	if (sign < 0)
		{
		if (!BN_sub(Y,n,Y)) goto err;
		}
	/* Now  Y*a  ==  A  (mod |n|).  */
	

	if (BN_is_one(A))
		{
		/* Y*a == 1  (mod |n|) */
		if (!Y->neg && BN_ucmp(Y,n) < 0)
			{
			if (!BN_copy(R,Y)) goto err;
			}
		else
			{
			if (!BN_nnmod(R,Y,n,ctx)) goto err;
			}
		}
	else
		{
		BNerr(BN_F_BN_MOD_INVERSE,BN_R_NO_INVERSE);
		goto err;
		}
	ret=R;
err:
	if ((ret == NULL) && (in == NULL)) BN_free(R);
	BN_CTX_end(ctx);
	bn_check_top(ret);
	return(ret);
	}
Exemple #3
0
int BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m,
                BN_RECP_CTX *recp, BN_CTX *ctx)
{
    int i, j, ret = 0;
    BIGNUM *a, *b, *d, *r;

    BN_CTX_start(ctx);
    a = BN_CTX_get(ctx);
    b = BN_CTX_get(ctx);
    if (dv != NULL)
        d = dv;
    else
        d = BN_CTX_get(ctx);
    if (rem != NULL)
        r = rem;
    else
        r = BN_CTX_get(ctx);
    if (a == NULL || b == NULL || d == NULL || r == NULL)
        goto err;

    if (BN_ucmp(m, &(recp->N)) < 0) {
        BN_zero(d);
        if (!BN_copy(r, m)) {
            BN_CTX_end(ctx);
            return 0;
        }
        BN_CTX_end(ctx);
        return (1);
    }

    /*
     * We want the remainder Given input of ABCDEF / ab we need multiply
     * ABCDEF by 3 digests of the reciprocal of ab
     */

    /* i := max(BN_num_bits(m), 2*BN_num_bits(N)) */
    i = BN_num_bits(m);
    j = recp->num_bits << 1;
    if (j > i)
        i = j;

    /* Nr := round(2^i / N) */
    if (i != recp->shift)
        recp->shift = BN_reciprocal(&(recp->Nr), &(recp->N), i, ctx);
    /* BN_reciprocal could have returned -1 for an error */
    if (recp->shift == -1)
        goto err;

    /*-
     * d := |round(round(m / 2^BN_num_bits(N)) * recp->Nr / 2^(i - BN_num_bits(N)))|
     *    = |round(round(m / 2^BN_num_bits(N)) * round(2^i / N) / 2^(i - BN_num_bits(N)))|
     *   <= |(m / 2^BN_num_bits(N)) * (2^i / N) * (2^BN_num_bits(N) / 2^i)|
     *    = |m/N|
     */
    if (!BN_rshift(a, m, recp->num_bits))
        goto err;
    if (!BN_mul(b, a, &(recp->Nr), ctx))
        goto err;
    if (!BN_rshift(d, b, i - recp->num_bits))
        goto err;
    d->neg = 0;

    if (!BN_mul(b, &(recp->N), d, ctx))
        goto err;
    if (!BN_usub(r, m, b))
        goto err;
    r->neg = 0;

#if 1
    j = 0;
    while (BN_ucmp(r, &(recp->N)) >= 0) {
        if (j++ > 2) {
            BNerr(BN_F_BN_DIV_RECP, BN_R_BAD_RECIPROCAL);
            goto err;
        }
        if (!BN_usub(r, r, &(recp->N)))
            goto err;
        if (!BN_add_word(d, 1))
            goto err;
    }
#endif

    r->neg = BN_is_zero(r) ? 0 : m->neg;
    d->neg = m->neg ^ recp->N.neg;
    ret = 1;
 err:
    BN_CTX_end(ctx);
    bn_check_top(dv);
    bn_check_top(rem);
    return (ret);
}
Exemple #4
0
int verifyRingSignature(data_chunk &keyImage, uint256 &txnHash, int nRingSize, const uint8_t *pPubkeys, const uint8_t *pSigc, const uint8_t *pSigr)
{
    if (fDebugRingSig)
    {
        // LogPrintf("%s size %d\n", __func__, nRingSize); // happens often
    };

    int rv = 0;

    BN_CTX_start(bnCtx);

    BIGNUM   *bnT   = BN_CTX_get(bnCtx);
    BIGNUM   *bnH   = BN_CTX_get(bnCtx);
    BIGNUM   *bnC   = BN_CTX_get(bnCtx);
    BIGNUM   *bnR   = BN_CTX_get(bnCtx);
    BIGNUM   *bnSum = BN_CTX_get(bnCtx);
    EC_POINT *ptT1  = NULL;
    EC_POINT *ptT2  = NULL;
    EC_POINT *ptT3  = NULL;
    EC_POINT *ptPk  = NULL;
    EC_POINT *ptKi  = NULL;
    EC_POINT *ptL   = NULL;
    EC_POINT *ptR   = NULL;
    EC_POINT *ptSi  = NULL;

    uint8_t tempData[66]; // hold raw point data to hash
    uint256 commitHash;
    CHashWriter ssCommitHash(SER_GETHASH, PROTOCOL_VERSION);

    ssCommitHash << txnHash;

    // zero sum
    if (!bnSum || !(BN_zero(bnSum)))
    {
        LogPrintf("%s: BN_zero failed.\n", __func__);
        rv = 1; goto End;
    };

    if (   !(ptT1 = EC_POINT_new(ecGrp))
        || !(ptT2 = EC_POINT_new(ecGrp))
        || !(ptT3 = EC_POINT_new(ecGrp))
        || !(ptPk = EC_POINT_new(ecGrp))
        || !(ptKi = EC_POINT_new(ecGrp))
        || !(ptL  = EC_POINT_new(ecGrp))
        || !(ptSi = EC_POINT_new(ecGrp))
        || !(ptR  = EC_POINT_new(ecGrp)))
    {
        LogPrintf("%s: EC_POINT_new failed.\n", __func__);
        rv = 1; goto End;
    };

    // get keyimage as point
    if (!(bnT = BN_bin2bn(&keyImage[0], EC_COMPRESSED_SIZE, bnT))
        || !(ptKi) || !(ptKi = EC_POINT_bn2point(ecGrp, bnT, ptKi, bnCtx)))
    {
        LogPrintf("%s: extract ptKi failed.\n", __func__);
        rv = 1; goto End;
    };

    for (int i = 0; i < nRingSize; ++i)
    {
        // Li = ci * Pi + ri * G
        // Ri = ci * I + ri * Hp(Pi)

        if (   !bnC || !(bnC = BN_bin2bn(&pSigc[i * EC_SECRET_SIZE], EC_SECRET_SIZE, bnC))
            || !bnR || !(bnR = BN_bin2bn(&pSigr[i * EC_SECRET_SIZE], EC_SECRET_SIZE, bnR)))
        {
            LogPrintf("%s: extract bnC and bnR failed.\n", __func__);
            rv = 1; goto End;
        };

        // get Pk i as point
        if (!(bnT = BN_bin2bn(&pPubkeys[i * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnT))
            || !(ptPk) || !(ptPk = EC_POINT_bn2point(ecGrp, bnT, ptPk, bnCtx)))
        {
            LogPrintf("%s: extract ptPk failed.\n", __func__);
            rv = 1; goto End;
        };

        // ptT1 = ci * Pi
        if (!EC_POINT_mul(ecGrp, ptT1, NULL, ptPk, bnC, bnCtx))
        {
            LogPrintf("%s: EC_POINT_mul failed.\n", __func__);
            rv = 1; goto End;
        };

        // ptT2 = ri * G
        if (!EC_POINT_mul(ecGrp, ptT2, bnR, NULL, NULL, bnCtx))
        {
            LogPrintf("%s: EC_POINT_mul failed.\n", __func__);
            rv = 1; goto End;
        };

        // ptL = ptT1 + ptT2
        if (!EC_POINT_add(ecGrp, ptL, ptT1, ptT2, bnCtx))
        {
            LogPrintf("%s: EC_POINT_add failed.\n", __func__);
            rv = 1; goto End;
        };

        // ptT3 = Hp(Pi)
        if (hashToEC(&pPubkeys[i * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnT, ptT3) != 0)
        {
            LogPrintf("%s: hashToEC failed.\n", __func__);
            rv = 1; goto End;
        };

        // DEBUGGING: ------- check if we can find the signer...
        // ptSi = Pi * bnT
        if ((!EC_POINT_mul(ecGrp, ptSi, NULL, ptPk, bnT, bnCtx)
           || false)
        && (rv = errorN(1, "%s: EC_POINT_mul failed.1", __func__)))
            goto End;

        if (0 == EC_POINT_cmp(ecGrp, ptSi, ptKi, bnCtx) )
            LogPrintf("signer is index %d\n", i);
        // DEBUGGING: - End - check if we can find the signer...

        // ptT1 = k1 * I
        if (!EC_POINT_mul(ecGrp, ptT1, NULL, ptKi, bnC, bnCtx))
        {
            LogPrintf("%s: EC_POINT_mul failed.\n", __func__);
            rv = 1; goto End;
        };

        // ptT2 = k2 * ptT3
        if (!EC_POINT_mul(ecGrp, ptT2, NULL, ptT3, bnR, bnCtx))
        {
            LogPrintf("%s: EC_POINT_mul failed.\n", __func__);
            rv = 1; goto End;
        };

        // ptR = ptT1 + ptT2
        if (!EC_POINT_add(ecGrp, ptR, ptT1, ptT2, bnCtx))
        {
            LogPrintf("%s: EC_POINT_add failed.\n", __func__);
            rv = 1; goto End;
        };

        // sum = (sum + ci) % N
        if (!BN_mod_add(bnSum, bnSum, bnC, bnOrder, bnCtx))
        {
            LogPrintf("%s: BN_mod_add failed.\n", __func__);
            rv = 1; goto End;
        };

        // -- add ptL and ptR to hash
        if (   !(EC_POINT_point2oct(ecGrp, ptL, POINT_CONVERSION_COMPRESSED, &tempData[0],  33, bnCtx) == (int) EC_COMPRESSED_SIZE)
            || !(EC_POINT_point2oct(ecGrp, ptR, POINT_CONVERSION_COMPRESSED, &tempData[33], 33, bnCtx) == (int) EC_COMPRESSED_SIZE))
        {
            LogPrintf("%s: extract ptL and ptR failed.\n", __func__);
            rv = 1; goto End;
        };

        ssCommitHash.write((const char*)&tempData[0], 66);
    };

    commitHash = ssCommitHash.GetHash();

    if (!(bnH) || !(bnH = BN_bin2bn(commitHash.begin(), EC_SECRET_SIZE, bnH)))
    {
        LogPrintf("%s: commitHash -> bnH failed.\n", __func__);
        rv = 1; goto End;
    };

    if (!BN_mod(bnH, bnH, bnOrder, bnCtx))
    {
        LogPrintf("%s: BN_mod failed.\n", __func__);
        rv = 1; goto End;
    };

    // bnT = (bnH - bnSum) % N
    if (!BN_mod_sub(bnT, bnH, bnSum, bnOrder, bnCtx))
    {
        LogPrintf("%s: BN_mod_sub failed.\n", __func__);
        rv = 1; goto End;
    };

    // test bnT == 0  (bnSum == bnH)
    if (!BN_is_zero(bnT))
    {
        LogPrintf("%s: signature does not verify.\n", __func__);
        rv = 2;
    };

    End:

    EC_POINT_free(ptT1);
    EC_POINT_free(ptT2);
    EC_POINT_free(ptT3);
    EC_POINT_free(ptPk);
    EC_POINT_free(ptKi);
    EC_POINT_free(ptL);
    EC_POINT_free(ptR);
    EC_POINT_free(ptSi);

    BN_CTX_end(bnCtx);

    return rv;
};
Exemple #5
0
int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx)
{
    int i, ret = 0;
    BIGNUM *Ri, *R;

    if (BN_is_zero(mod))
        return 0;

    BN_CTX_start(ctx);
    if ((Ri = BN_CTX_get(ctx)) == NULL)
        goto err;
    R = &(mont->RR);            /* grab RR as a temp */
    if (!BN_copy(&(mont->N), mod))
        goto err;               /* Set N */
    if (BN_get_flags(mod, BN_FLG_CONSTTIME) != 0)
        BN_set_flags(&(mont->N), BN_FLG_CONSTTIME);
    mont->N.neg = 0;

#ifdef MONT_WORD
    {
        BIGNUM tmod;
        BN_ULONG buf[2];

        bn_init(&tmod);
        tmod.d = buf;
        tmod.dmax = 2;
        tmod.neg = 0;

        if (BN_get_flags(mod, BN_FLG_CONSTTIME) != 0)
            BN_set_flags(&tmod, BN_FLG_CONSTTIME);

        mont->ri = (BN_num_bits(mod) + (BN_BITS2 - 1)) / BN_BITS2 * BN_BITS2;

# if defined(OPENSSL_BN_ASM_MONT) && (BN_BITS2<=32)
        /*
         * Only certain BN_BITS2<=32 platforms actually make use of n0[1],
         * and we could use the #else case (with a shorter R value) for the
         * others.  However, currently only the assembler files do know which
         * is which.
         */

        BN_zero(R);
        if (!(BN_set_bit(R, 2 * BN_BITS2)))
            goto err;

        tmod.top = 0;
        if ((buf[0] = mod->d[0]))
            tmod.top = 1;
        if ((buf[1] = mod->top > 1 ? mod->d[1] : 0))
            tmod.top = 2;

        if (BN_is_one(&tmod))
            BN_zero(Ri);
        else if ((BN_mod_inverse(Ri, R, &tmod, ctx)) == NULL)
            goto err;
        if (!BN_lshift(Ri, Ri, 2 * BN_BITS2))
            goto err;           /* R*Ri */
        if (!BN_is_zero(Ri)) {
            if (!BN_sub_word(Ri, 1))
                goto err;
        } else {                /* if N mod word size == 1 */

            if (bn_expand(Ri, (int)sizeof(BN_ULONG) * 2) == NULL)
                goto err;
            /* Ri-- (mod double word size) */
            Ri->neg = 0;
            Ri->d[0] = BN_MASK2;
            Ri->d[1] = BN_MASK2;
            Ri->top = 2;
        }
        if (!BN_div(Ri, NULL, Ri, &tmod, ctx))
            goto err;
        /*
         * Ni = (R*Ri-1)/N, keep only couple of least significant words:
         */
        mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0;
        mont->n0[1] = (Ri->top > 1) ? Ri->d[1] : 0;
# else
        BN_zero(R);
        if (!(BN_set_bit(R, BN_BITS2)))
            goto err;           /* R */

        buf[0] = mod->d[0];     /* tmod = N mod word size */
        buf[1] = 0;
        tmod.top = buf[0] != 0 ? 1 : 0;
        /* Ri = R^-1 mod N */
        if (BN_is_one(&tmod))
            BN_zero(Ri);
        else if ((BN_mod_inverse(Ri, R, &tmod, ctx)) == NULL)
            goto err;
        if (!BN_lshift(Ri, Ri, BN_BITS2))
            goto err;           /* R*Ri */
        if (!BN_is_zero(Ri)) {
            if (!BN_sub_word(Ri, 1))
                goto err;
        } else {                /* if N mod word size == 1 */

            if (!BN_set_word(Ri, BN_MASK2))
                goto err;       /* Ri-- (mod word size) */
        }
        if (!BN_div(Ri, NULL, Ri, &tmod, ctx))
            goto err;
        /*
         * Ni = (R*Ri-1)/N, keep only least significant word:
         */
        mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0;
        mont->n0[1] = 0;
# endif
    }
#else                           /* !MONT_WORD */
    {                           /* bignum version */
        mont->ri = BN_num_bits(&mont->N);
        BN_zero(R);
        if (!BN_set_bit(R, mont->ri))
            goto err;           /* R = 2^ri */
        /* Ri = R^-1 mod N */
        if ((BN_mod_inverse(Ri, R, &mont->N, ctx)) == NULL)
            goto err;
        if (!BN_lshift(Ri, Ri, mont->ri))
            goto err;           /* R*Ri */
        if (!BN_sub_word(Ri, 1))
            goto err;
        /*
         * Ni = (R*Ri-1) / N
         */
        if (!BN_div(&(mont->Ni), NULL, Ri, &mont->N, ctx))
            goto err;
    }
#endif

    /* setup RR for conversions */
    BN_zero(&(mont->RR));
    if (!BN_set_bit(&(mont->RR), mont->ri * 2))
        goto err;
    if (!BN_mod(&(mont->RR), &(mont->RR), &(mont->N), ctx))
        goto err;

    for (i = mont->RR.top, ret = mont->N.top; i < ret; i++)
        mont->RR.d[i] = 0;
    mont->RR.top = ret;
    mont->RR.flags |= BN_FLG_FIXED_TOP;

    ret = 1;
 err:
    BN_CTX_end(ctx);
    return ret;
}
Exemple #6
0
/* random number r:  0 <= r < range */
static int bn_rand_range(int pseudo, BIGNUM *r, const BIGNUM *range)
	{
	int (*bn_rand)(BIGNUM *, int, int, int) = pseudo ? BN_pseudo_rand : BN_rand;
	int n;
	int count = 100;

	if (range->neg || BN_is_zero(range))
		{
		BNerr(BN_F_BN_RAND_RANGE, BN_R_INVALID_RANGE);
		return 0;
		}

	n = BN_num_bits(range); /* n > 0 */

	/* BN_is_bit_set(range, n - 1) always holds */

	if (n == 1)
		BN_zero(r);
#ifdef OPENSSL_FIPS
	/* FIPS 186-3 is picky about how random numbers for keys etc are
	 * generated. So we just use the second case which is equivalent to
	 * "Generation by Testing Candidates" mentioned in B.1.2 et al.
	 */
	else if (!FIPS_mode() && !BN_is_bit_set(range, n - 2) && !BN_is_bit_set(range, n - 3))
#else
	else if (!BN_is_bit_set(range, n - 2) && !BN_is_bit_set(range, n - 3))
#endif
		{
		/* range = 100..._2,
		 * so  3*range (= 11..._2)  is exactly one bit longer than  range */
		do
			{
			if (!bn_rand(r, n + 1, -1, 0)) return 0;
			/* If  r < 3*range,  use  r := r MOD range
			 * (which is either  r, r - range,  or  r - 2*range).
			 * Otherwise, iterate once more.
			 * Since  3*range = 11..._2, each iteration succeeds with
			 * probability >= .75. */
			if (BN_cmp(r ,range) >= 0)
				{
				if (!BN_sub(r, r, range)) return 0;
				if (BN_cmp(r, range) >= 0)
					if (!BN_sub(r, r, range)) return 0;
				}

			if (!--count)
				{
				BNerr(BN_F_BN_RAND_RANGE, BN_R_TOO_MANY_ITERATIONS);
				return 0;
				}
			
			}
		while (BN_cmp(r, range) >= 0);
		}
	else
		{
		do
			{
			/* range = 11..._2  or  range = 101..._2 */
			if (!bn_rand(r, n, -1, 0)) return 0;

			if (!--count)
				{
				BNerr(BN_F_BN_RAND_RANGE, BN_R_TOO_MANY_ITERATIONS);
				return 0;
				}
			}
		while (BN_cmp(r, range) >= 0);
		}

	bn_check_top(r);
	return 1;
	}
Exemple #7
0
int
MKEMParams_init(MKEMParams *params)
{
  const mk_curve_params *p = &mk_curves[MK_CURVE_163_0];
  BIGNUM *maxu = 0;
  size_t bitsize, bytesize, bitcap, k;

  memset(params, 0, sizeof(MKEMParams));

  FAILZ(params->ctx = BN_CTX_new());

  FAILZ(params->m  = BN_bin2bn(p->m,  p->L_m,  0));
  FAILZ(params->b  = BN_bin2bn(p->b,  p->L_b,  0));
  FAILZ(params->a0 = BN_new()); FAILZ(BN_zero((BIGNUM *)params->a0));
  FAILZ(params->a1 = BN_value_one());
  FAILZ(params->p0 = BN_bin2bn(p->p0, p->L_p0, 0));
  FAILZ(params->p1 = BN_bin2bn(p->p1, p->L_p1, 0));
  FAILZ(params->n0 = BN_bin2bn(p->n0, p->L_n0, 0));
  FAILZ(params->n1 = BN_bin2bn(p->n1, p->L_n1, 0));

  FAILZ(params->c0 = EC_GROUP_new_curve_GF2m(params->m, params->a0, params->b,
                                             params->ctx));
  FAILZ(params->c1 = EC_GROUP_new_curve_GF2m(params->m, params->a1, params->b,
                                             params->ctx));

  FAILZ(params->g0 = EC_POINT_new(params->c0));
  FAILZ(EC_POINT_oct2point(params->c0, (EC_POINT *)params->g0, p->g0, p->L_g0,
                           params->ctx));
  FAILZ(params->g1 = EC_POINT_new(params->c1));
  FAILZ(EC_POINT_oct2point(params->c1, (EC_POINT *)params->g1, p->g1, p->L_g1,
                           params->ctx));

  /* Calculate the upper limit for the random integer U input to
     MKEM_generate_message_u.

     The paper calls for us to choose between curve 0 and curve 1 with
     probability proportional to the number of points on that curve, and
     then choose a random integer in the range 0 < u < n{curve}.  The
     easiest way to do this accurately is to choose a random integer in the
     range [1, n0 + n1 - 2].  If it is less than n0, MKEM_generate_message_u
     will use it unmodified with curve 0.  If it is greater than or equal
     to n0, MKEM_generate_message_u will subtract n0-1, leaving a number in
     the range [1, n1-1], and use that with curve 1. */

  FAILZ(maxu = BN_dup(params->n0));
  FAILZ(BN_add(maxu, maxu, params->n1));
  FAILZ(BN_sub(maxu, maxu, BN_value_one()));
  FAILZ(BN_sub(maxu, maxu, BN_value_one()));
  params->maxu = maxu; maxu = 0;

  /* Calculate the maximum size of a message and the padding mask applied
     to the high byte of each message.  See MKEM_generate_message_u for
     further exposition. */
  bitsize = EC_GROUP_get_degree(params->c0);
  if ((size_t)EC_GROUP_get_degree(params->c1) != bitsize)
    goto fail;

  bytesize = (bitsize + 7) / 8;
  bitcap = bytesize * 8;
  k = bitcap - bitsize;
  if (k == 0)
    goto fail;

  params->msgsize   = bytesize;
  params->pad_bits  = k - 1;
  params->pad_mask  = ~((1 << (8 - params->pad_bits)) - 1);
  params->curve_bit = 1 << (8 - k);

  return 0;

 fail:
  if (maxu) BN_free(maxu);
  MKEMParams_teardown(params);
  return -1;
}
static int FIPS_dsa_builtin_paramgen(DSA *ret, int bits,
		unsigned char *seed_in, int seed_len,
		int *counter_ret, unsigned long *h_ret, BN_GENCB *cb)
	{
	int ok=0;
	unsigned char seed[SHA_DIGEST_LENGTH];
	unsigned char md[SHA_DIGEST_LENGTH];
	unsigned char buf[SHA_DIGEST_LENGTH],buf2[SHA_DIGEST_LENGTH];
	BIGNUM *r0,*W,*X,*c,*test;
	BIGNUM *g=NULL,*q=NULL,*p=NULL;
	BN_MONT_CTX *mont=NULL;
	int k,n=0,i,b,m=0;
	int counter=0;
	int r=0;
	BN_CTX *ctx=NULL;
	unsigned int h=2;

	if(FIPS_selftest_failed())
	    {
	    FIPSerr(FIPS_F_DSA_BUILTIN_PARAMGEN,
		    FIPS_R_FIPS_SELFTEST_FAILED);
	    goto err;
	    }

	if (FIPS_mode() && (bits < OPENSSL_DSA_FIPS_MIN_MODULUS_BITS))
		{
		DSAerr(DSA_F_DSA_BUILTIN_PARAMGEN, DSA_R_KEY_SIZE_TOO_SMALL);
		goto err;
		}

	if (bits < 512) bits=512;
	bits=(bits+63)/64*64;

	/* NB: seed_len == 0 is special case: copy generated seed to
 	 * seed_in if it is not NULL.
 	 */
	if (seed_len && (seed_len < 20))
		seed_in = NULL; /* seed buffer too small -- ignore */
	if (seed_len > 20) 
		seed_len = 20; /* App. 2.2 of FIPS PUB 186 allows larger SEED,
		                * but our internal buffers are restricted to 160 bits*/
	if ((seed_in != NULL) && (seed_len == 20))
		{
		memcpy(seed,seed_in,seed_len);
		/* set seed_in to NULL to avoid it being copied back */
		seed_in = NULL;
		}

	if ((ctx=BN_CTX_new()) == NULL) goto err;

	if ((mont=BN_MONT_CTX_new()) == NULL) goto err;

	BN_CTX_start(ctx);
	r0 = BN_CTX_get(ctx);
	g = BN_CTX_get(ctx);
	W = BN_CTX_get(ctx);
	q = BN_CTX_get(ctx);
	X = BN_CTX_get(ctx);
	c = BN_CTX_get(ctx);
	p = BN_CTX_get(ctx);
	test = BN_CTX_get(ctx);

	if (!BN_lshift(test,BN_value_one(),bits-1))
		goto err;

	for (;;)
		{
		for (;;) /* find q */
			{
			int seed_is_random;

			/* step 1 */
			if(!BN_GENCB_call(cb, 0, m++))
				goto err;

			if (!seed_len)
				{
				RAND_pseudo_bytes(seed,SHA_DIGEST_LENGTH);
				seed_is_random = 1;
				}
			else
				{
				seed_is_random = 0;
				seed_len=0; /* use random seed if 'seed_in' turns out to be bad*/
				}
			memcpy(buf,seed,SHA_DIGEST_LENGTH);
			memcpy(buf2,seed,SHA_DIGEST_LENGTH);
			/* precompute "SEED + 1" for step 7: */
			for (i=SHA_DIGEST_LENGTH-1; i >= 0; i--)
				{
				buf[i]++;
				if (buf[i] != 0) break;
				}

			/* step 2 */
			EVP_Digest(seed,SHA_DIGEST_LENGTH,md,NULL,HASH, NULL);
			EVP_Digest(buf,SHA_DIGEST_LENGTH,buf2,NULL,HASH, NULL);
			for (i=0; i<SHA_DIGEST_LENGTH; i++)
				md[i]^=buf2[i];

			/* step 3 */
			md[0]|=0x80;
			md[SHA_DIGEST_LENGTH-1]|=0x01;
			if (!BN_bin2bn(md,SHA_DIGEST_LENGTH,q)) goto err;

			/* step 4 */
			r = BN_is_prime_fasttest_ex(q, DSS_prime_checks, ctx,
					seed_is_random, cb);
			if (r > 0)
				break;
			if (r != 0)
				goto err;

			/* do a callback call */
			/* step 5 */
			}

		if(!BN_GENCB_call(cb, 2, 0)) goto err;
		if(!BN_GENCB_call(cb, 3, 0)) goto err;

		/* step 6 */
		counter=0;
		/* "offset = 2" */

		n=(bits-1)/160;
		b=(bits-1)-n*160;

		for (;;)
			{
			if ((counter != 0) && !BN_GENCB_call(cb, 0, counter))
				goto err;

			/* step 7 */
			BN_zero(W);
			/* now 'buf' contains "SEED + offset - 1" */
			for (k=0; k<=n; k++)
				{
				/* obtain "SEED + offset + k" by incrementing: */
				for (i=SHA_DIGEST_LENGTH-1; i >= 0; i--)
					{
					buf[i]++;
					if (buf[i] != 0) break;
					}

				EVP_Digest(buf,SHA_DIGEST_LENGTH,md,NULL,HASH, NULL);

				/* step 8 */
				if (!BN_bin2bn(md,SHA_DIGEST_LENGTH,r0))
					goto err;
				if (!BN_lshift(r0,r0,160*k)) goto err;
				if (!BN_add(W,W,r0)) goto err;
				}

			/* more of step 8 */
			if (!BN_mask_bits(W,bits-1)) goto err;
			if (!BN_copy(X,W)) goto err;
			if (!BN_add(X,X,test)) goto err;

			/* step 9 */
			if (!BN_lshift1(r0,q)) goto err;
			if (!BN_mod(c,X,r0,ctx)) goto err;
			if (!BN_sub(r0,c,BN_value_one())) goto err;
			if (!BN_sub(p,X,r0)) goto err;

			/* step 10 */
			if (BN_cmp(p,test) >= 0)
				{
				/* step 11 */
				r = BN_is_prime_fasttest_ex(p, DSS_prime_checks,
						ctx, 1, cb);
				if (r > 0)
						goto end; /* found it */
				if (r != 0)
					goto err;
				}

			/* step 13 */
			counter++;
			/* "offset = offset + n + 1" */

			/* step 14 */
			if (counter >= 4096) break;
			}
		}
end:
	if(!BN_GENCB_call(cb, 2, 1))
		goto err;

	/* We now need to generate g */
	/* Set r0=(p-1)/q */
	if (!BN_sub(test,p,BN_value_one())) goto err;
	if (!BN_div(r0,NULL,test,q,ctx)) goto err;

	if (!BN_set_word(test,h)) goto err;
	if (!BN_MONT_CTX_set(mont,p,ctx)) goto err;

	for (;;)
		{
		/* g=test^r0%p */
		if (!BN_mod_exp_mont(g,test,r0,p,ctx,mont)) goto err;
		if (!BN_is_one(g)) break;
		if (!BN_add(test,test,BN_value_one())) goto err;
		h++;
		}

	if(!BN_GENCB_call(cb, 3, 1))
		goto err;

	ok=1;
err:
	if (ok)
		{
		if(ret->p) BN_free(ret->p);
		if(ret->q) BN_free(ret->q);
		if(ret->g) BN_free(ret->g);
		ret->p=BN_dup(p);
		ret->q=BN_dup(q);
		ret->g=BN_dup(g);
		if (ret->p == NULL || ret->q == NULL || ret->g == NULL)
			{
			ok=0;
			goto err;
			}
		if (seed_in != NULL) memcpy(seed_in,seed,20);
		if (counter_ret != NULL) *counter_ret=counter;
		if (h_ret != NULL) *h_ret=h;
		}
	if(ctx)
		{
		BN_CTX_end(ctx);
		BN_CTX_free(ctx);
		}
	if (mont != NULL) BN_MONT_CTX_free(mont);
	return ok;
	}
Exemple #9
0
int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx)
	{
	int ret = 0;
	BIGNUM *Ri,*R;

	BN_CTX_start(ctx);
	if((Ri = BN_CTX_get(ctx)) == NULL) goto err;
	R= &(mont->RR);					/* grab RR as a temp */
	if (!BN_copy(&(mont->N),mod)) goto err;		/* Set N */
	mont->N.neg = 0;

#ifdef MONT_WORD
		{
		BIGNUM tmod;
		BN_ULONG buf[2];

		mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2;
		BN_zero(R);
		if (!(BN_set_bit(R,BN_BITS2))) goto err;	/* R */

		buf[0]=mod->d[0]; /* tmod = N mod word size */
		buf[1]=0;
		tmod.d=buf;
		tmod.top = buf[0] != 0 ? 1 : 0;
		tmod.dmax=2;
		tmod.neg=0;
							/* Ri = R^-1 mod N*/
		if ((BN_mod_inverse(Ri,R,&tmod,ctx)) == NULL)
			goto err;
		if (!BN_lshift(Ri,Ri,BN_BITS2)) goto err; /* R*Ri */
		if (!BN_is_zero(Ri))
			{
			if (!BN_sub_word(Ri,1)) goto err;
			}
		else /* if N mod word size == 1 */
			{
			if (!BN_set_word(Ri,BN_MASK2)) goto err;  /* Ri-- (mod word size) */
			}
		if (!BN_div(Ri,NULL,Ri,&tmod,ctx)) goto err;
		/* Ni = (R*Ri-1)/N,
		 * keep only least significant word: */
		mont->n0 = (Ri->top > 0) ? Ri->d[0] : 0;
		}
#else /* !MONT_WORD */
		{ /* bignum version */
		mont->ri=BN_num_bits(&mont->N);
		BN_zero(R);
		if (!BN_set_bit(R,mont->ri)) goto err;  /* R = 2^ri */
		                                        /* Ri = R^-1 mod N*/
		if ((BN_mod_inverse(Ri,R,&mont->N,ctx)) == NULL)
			goto err;
		if (!BN_lshift(Ri,Ri,mont->ri)) goto err; /* R*Ri */
		if (!BN_sub_word(Ri,1)) goto err;
							/* Ni = (R*Ri-1) / N */
		if (!BN_div(&(mont->Ni),NULL,Ri,&mont->N,ctx)) goto err;
		}
#endif

	/* setup RR for conversions */
	BN_zero(&(mont->RR));
	if (!BN_set_bit(&(mont->RR),mont->ri*2)) goto err;
	if (!BN_mod(&(mont->RR),&(mont->RR),&(mont->N),ctx)) goto err;

	ret = 1;
err:
	BN_CTX_end(ctx);
	return ret;
	}
Exemple #10
0
/*
 * test_exp_mod_zero tests that x**0 mod 1 == 0. It returns zero on success.
 */
static int test_exp_mod_zero()
{
    BIGNUM a, p, m;
    BIGNUM r;
    BN_ULONG one_word = 1;
    BN_CTX *ctx = BN_CTX_new();
    int ret = 1, failed = 0;

    BN_init(&m);
    BN_one(&m);

    BN_init(&a);
    BN_one(&a);

    BN_init(&p);
    BN_zero(&p);

    BN_init(&r);

    if (!BN_rand(&a, 1024, 0, 0))
        goto err;

    if (!BN_mod_exp(&r, &a, &p, &m, ctx))
        goto err;

    if (!a_is_zero_mod_one("BN_mod_exp", &r, &a))
        failed = 1;

    if (!BN_mod_exp_recp(&r, &a, &p, &m, ctx))
        goto err;

    if (!a_is_zero_mod_one("BN_mod_exp_recp", &r, &a))
        failed = 1;

    if (!BN_mod_exp_simple(&r, &a, &p, &m, ctx))
        goto err;

    if (!a_is_zero_mod_one("BN_mod_exp_simple", &r, &a))
        failed = 1;

    if (!BN_mod_exp_mont(&r, &a, &p, &m, ctx, NULL))
        goto err;

    if (!a_is_zero_mod_one("BN_mod_exp_mont", &r, &a))
        failed = 1;

    if (!BN_mod_exp_mont_consttime(&r, &a, &p, &m, ctx, NULL)) {
        goto err;
    }

    if (!a_is_zero_mod_one("BN_mod_exp_mont_consttime", &r, &a))
        failed = 1;

    /*
     * A different codepath exists for single word multiplication
     * in non-constant-time only.
     */
    if (!BN_mod_exp_mont_word(&r, one_word, &p, &m, ctx, NULL))
        goto err;

    if (!BN_is_zero(&r)) {
        fprintf(stderr, "BN_mod_exp_mont_word failed:\n");
        fprintf(stderr, "1 ** 0 mod 1 = r (should be 0)\n");
        fprintf(stderr, "r = ");
        BN_print_fp(stderr, &r);
        fprintf(stderr, "\n");
        return 0;
    }

    ret = failed;

 err:
    BN_free(&r);
    BN_free(&a);
    BN_free(&p);
    BN_free(&m);
    BN_CTX_free(ctx);

    return ret;
}
Exemple #11
0
BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) 
/* Returns 'ret' such that
 *      ret^2 == a (mod p),
 * using the Tonelli/Shanks algorithm (cf. Henri Cohen, "A Course
 * in Algebraic Computational Number Theory", algorithm 1.5.1).
 * 'p' must be prime!
 */
	{
	BIGNUM *ret = in;
	int err = 1;
	int r;
	BIGNUM *A, *b, *q, *t, *x, *y;
	int e, i, j;
	
	if (!BN_is_odd(p) || BN_abs_is_word(p, 1))
		{
		if (BN_abs_is_word(p, 2))
			{
			if (ret == NULL)
				ret = BN_new();
			if (ret == NULL)
				goto end;
			if (!BN_set_word(ret, BN_is_bit_set(a, 0)))
				{
				if (ret != in)
					BN_free(ret);
				return NULL;
				}
			bn_check_top(ret);
			return ret;
			}

		BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME);
		return(NULL);
		}

	if (BN_is_zero(a) || BN_is_one(a))
		{
		if (ret == NULL)
			ret = BN_new();
		if (ret == NULL)
			goto end;
		if (!BN_set_word(ret, BN_is_one(a)))
			{
			if (ret != in)
				BN_free(ret);
			return NULL;
			}
		bn_check_top(ret);
		return ret;
		}

	BN_CTX_start(ctx);
	A = BN_CTX_get(ctx);
	b = BN_CTX_get(ctx);
	q = BN_CTX_get(ctx);
	t = BN_CTX_get(ctx);
	x = BN_CTX_get(ctx);
	y = BN_CTX_get(ctx);
	if (y == NULL) goto end;
	
	if (ret == NULL)
		ret = BN_new();
	if (ret == NULL) goto end;

	/* A = a mod p */
	if (!BN_nnmod(A, a, p, ctx)) goto end;

	/* now write  |p| - 1  as  2^e*q  where  q  is odd */
	e = 1;
	while (!BN_is_bit_set(p, e))
		e++;
	/* we'll set  q  later (if needed) */

	if (e == 1)
		{
		/* The easy case:  (|p|-1)/2  is odd, so 2 has an inverse
		 * modulo  (|p|-1)/2,  and square roots can be computed
		 * directly by modular exponentiation.
		 * We have
		 *     2 * (|p|+1)/4 == 1   (mod (|p|-1)/2),
		 * so we can use exponent  (|p|+1)/4,  i.e.  (|p|-3)/4 + 1.
		 */
		if (!BN_rshift(q, p, 2)) goto end;
		q->neg = 0;
		if (!BN_add_word(q, 1)) goto end;
		if (!BN_mod_exp(ret, A, q, p, ctx)) goto end;
		err = 0;
		goto vrfy;
		}
	
	if (e == 2)
		{
		/* |p| == 5  (mod 8)
		 *
		 * In this case  2  is always a non-square since
		 * Legendre(2,p) = (-1)^((p^2-1)/8)  for any odd prime.
		 * So if  a  really is a square, then  2*a  is a non-square.
		 * Thus for
		 *      b := (2*a)^((|p|-5)/8),
		 *      i := (2*a)*b^2
		 * we have
		 *     i^2 = (2*a)^((1 + (|p|-5)/4)*2)
		 *         = (2*a)^((p-1)/2)
		 *         = -1;
		 * so if we set
		 *      x := a*b*(i-1),
		 * then
		 *     x^2 = a^2 * b^2 * (i^2 - 2*i + 1)
		 *         = a^2 * b^2 * (-2*i)
		 *         = a*(-i)*(2*a*b^2)
		 *         = a*(-i)*i
		 *         = a.
		 *
		 * (This is due to A.O.L. Atkin, 
		 * <URL: http://listserv.nodak.edu/scripts/wa.exe?A2=ind9211&L=nmbrthry&O=T&P=562>,
		 * November 1992.)
		 */

		/* t := 2*a */
		if (!BN_mod_lshift1_quick(t, A, p)) goto end;

		/* b := (2*a)^((|p|-5)/8) */
		if (!BN_rshift(q, p, 3)) goto end;
		q->neg = 0;
		if (!BN_mod_exp(b, t, q, p, ctx)) goto end;

		/* y := b^2 */
		if (!BN_mod_sqr(y, b, p, ctx)) goto end;

		/* t := (2*a)*b^2 - 1*/
		if (!BN_mod_mul(t, t, y, p, ctx)) goto end;
		if (!BN_sub_word(t, 1)) goto end;

		/* x = a*b*t */
		if (!BN_mod_mul(x, A, b, p, ctx)) goto end;
		if (!BN_mod_mul(x, x, t, p, ctx)) goto end;

		if (!BN_copy(ret, x)) goto end;
		err = 0;
		goto vrfy;
		}
	
	/* e > 2, so we really have to use the Tonelli/Shanks algorithm.
	 * First, find some  y  that is not a square. */
	if (!BN_copy(q, p)) goto end; /* use 'q' as temp */
	q->neg = 0;
	i = 2;
	do
		{
		/* For efficiency, try small numbers first;
		 * if this fails, try random numbers.
		 */
		if (i < 22)
			{
			if (!BN_set_word(y, i)) goto end;
			}
		else
			{
			if (!BN_pseudo_rand(y, BN_num_bits(p), 0, 0)) goto end;
			if (BN_ucmp(y, p) >= 0)
				{
				if (!(p->neg ? BN_add : BN_sub)(y, y, p)) goto end;
				}
			/* now 0 <= y < |p| */
			if (BN_is_zero(y))
				if (!BN_set_word(y, i)) goto end;
			}
		
		r = BN_kronecker(y, q, ctx); /* here 'q' is |p| */
		if (r < -1) goto end;
		if (r == 0)
			{
			/* m divides p */
			BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME);
			goto end;
			}
		}
	while (r == 1 && ++i < 82);
	
	if (r != -1)
		{
		/* Many rounds and still no non-square -- this is more likely
		 * a bug than just bad luck.
		 * Even if  p  is not prime, we should have found some  y
		 * such that r == -1.
		 */
		BNerr(BN_F_BN_MOD_SQRT, BN_R_TOO_MANY_ITERATIONS);
		goto end;
		}

	/* Here's our actual 'q': */
	if (!BN_rshift(q, q, e)) goto end;

	/* Now that we have some non-square, we can find an element
	 * of order  2^e  by computing its q'th power. */
	if (!BN_mod_exp(y, y, q, p, ctx)) goto end;
	if (BN_is_one(y))
		{
		BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME);
		goto end;
		}

	/* Now we know that (if  p  is indeed prime) there is an integer
	 * k,  0 <= k < 2^e,  such that
	 *
	 *      a^q * y^k == 1   (mod p).
	 *
	 * As  a^q  is a square and  y  is not,  k  must be even.
	 * q+1  is even, too, so there is an element
	 *
	 *     X := a^((q+1)/2) * y^(k/2),
	 *
	 * and it satisfies
	 *
	 *     X^2 = a^q * a     * y^k
	 *         = a,
	 *
	 * so it is the square root that we are looking for.
	 */
	
	/* t := (q-1)/2  (note that  q  is odd) */
	if (!BN_rshift1(t, q)) goto end;
	
	/* x := a^((q-1)/2) */
	if (BN_is_zero(t)) /* special case: p = 2^e + 1 */
		{
		if (!BN_nnmod(t, A, p, ctx)) goto end;
		if (BN_is_zero(t))
			{
			/* special case: a == 0  (mod p) */
			BN_zero(ret);
			err = 0;
			goto end;
			}
		else
			if (!BN_one(x)) goto end;
		}
	else
		{
		if (!BN_mod_exp(x, A, t, p, ctx)) goto end;
		if (BN_is_zero(x))
			{
			/* special case: a == 0  (mod p) */
			BN_zero(ret);
			err = 0;
			goto end;
			}
		}

	/* b := a*x^2  (= a^q) */
	if (!BN_mod_sqr(b, x, p, ctx)) goto end;
	if (!BN_mod_mul(b, b, A, p, ctx)) goto end;
	
	/* x := a*x    (= a^((q+1)/2)) */
	if (!BN_mod_mul(x, x, A, p, ctx)) goto end;

	while (1)
		{
		/* Now  b  is  a^q * y^k  for some even  k  (0 <= k < 2^E
		 * where  E  refers to the original value of  e,  which we
		 * don't keep in a variable),  and  x  is  a^((q+1)/2) * y^(k/2).
		 *
		 * We have  a*b = x^2,
		 *    y^2^(e-1) = -1,
		 *    b^2^(e-1) = 1.
		 */

		if (BN_is_one(b))
			{
			if (!BN_copy(ret, x)) goto end;
			err = 0;
			goto vrfy;
			}


		/* find smallest  i  such that  b^(2^i) = 1 */
		i = 1;
		if (!BN_mod_sqr(t, b, p, ctx)) goto end;
		while (!BN_is_one(t))
			{
			i++;
			if (i == e)
				{
				BNerr(BN_F_BN_MOD_SQRT, BN_R_NOT_A_SQUARE);
				goto end;
				}
			if (!BN_mod_mul(t, t, t, p, ctx)) goto end;
			}
		

		/* t := y^2^(e - i - 1) */
		if (!BN_copy(t, y)) goto end;
		for (j = e - i - 1; j > 0; j--)
			{
			if (!BN_mod_sqr(t, t, p, ctx)) goto end;
			}
		if (!BN_mod_mul(y, t, t, p, ctx)) goto end;
		if (!BN_mod_mul(x, x, t, p, ctx)) goto end;
		if (!BN_mod_mul(b, b, y, p, ctx)) goto end;
		e = i;
		}

 vrfy:
	if (!err)
		{
		/* verify the result -- the input might have been not a square
		 * (test added in 0.9.8) */
		
		if (!BN_mod_sqr(x, ret, p, ctx))
			err = 1;
		
		if (!err && 0 != BN_cmp(x, A))
			{
			BNerr(BN_F_BN_MOD_SQRT, BN_R_NOT_A_SQUARE);
			err = 1;
			}
		}

 end:
	if (err)
		{
		if (ret != NULL && ret != in)
			{
			BN_clear_free(ret);
			}
		ret = NULL;
		}
	BN_CTX_end(ctx);
	bn_check_top(ret);
	return ret;
	}
Exemple #12
0
int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
{
    int ret = 0;
    int top, al, bl;
    BIGNUM *rr;
#if defined(BN_MUL_COMBA) || defined(BN_RECURSION)
    int i;
#endif
#ifdef BN_RECURSION
    BIGNUM *t = NULL;
    int j = 0, k;
#endif

    bn_check_top(a);
    bn_check_top(b);
    bn_check_top(r);

    al = a->top;
    bl = b->top;

    if ((al == 0) || (bl == 0)) {
        BN_zero(r);
        return (1);
    }
    top = al + bl;

    BN_CTX_start(ctx);
    if ((r == a) || (r == b)) {
        if ((rr = BN_CTX_get(ctx)) == NULL)
            goto err;
    } else
        rr = r;
    rr->neg = a->neg ^ b->neg;

#if defined(BN_MUL_COMBA) || defined(BN_RECURSION)
    i = al - bl;
#endif
#ifdef BN_MUL_COMBA
    if (i == 0) {
# if 0
        if (al == 4) {
            if (bn_wexpand(rr, 8) == NULL)
                goto err;
            rr->top = 8;
            bn_mul_comba4(rr->d, a->d, b->d);
            goto end;
        }
# endif
        if (al == 8) {
            if (bn_wexpand(rr, 16) == NULL)
                goto err;
            rr->top = 16;
            bn_mul_comba8(rr->d, a->d, b->d);
            goto end;
        }
    }
#endif                          /* BN_MUL_COMBA */
#ifdef BN_RECURSION
    if ((al >= BN_MULL_SIZE_NORMAL) && (bl >= BN_MULL_SIZE_NORMAL)) {
        if (i >= -1 && i <= 1) {
            /*
             * Find out the power of two lower or equal to the longest of the
             * two numbers
             */
            if (i >= 0) {
                j = BN_num_bits_word((BN_ULONG)al);
            }
            if (i == -1) {
                j = BN_num_bits_word((BN_ULONG)bl);
            }
            j = 1 << (j - 1);
            assert(j <= al || j <= bl);
            k = j + j;
            t = BN_CTX_get(ctx);
            if (t == NULL)
                goto err;
            if (al > j || bl > j) {
                if (bn_wexpand(t, k * 4) == NULL)
                    goto err;
                if (bn_wexpand(rr, k * 4) == NULL)
                    goto err;
                bn_mul_part_recursive(rr->d, a->d, b->d,
                                      j, al - j, bl - j, t->d);
            } else {            /* al <= j || bl <= j */

                if (bn_wexpand(t, k * 2) == NULL)
                    goto err;
                if (bn_wexpand(rr, k * 2) == NULL)
                    goto err;
                bn_mul_recursive(rr->d, a->d, b->d, j, al - j, bl - j, t->d);
            }
            rr->top = top;
            goto end;
        }
# if 0
        if (i == 1 && !BN_get_flags(b, BN_FLG_STATIC_DATA)) {
            BIGNUM *tmp_bn = (BIGNUM *)b;
            if (bn_wexpand(tmp_bn, al) == NULL)
                goto err;
            tmp_bn->d[bl] = 0;
            bl++;
            i--;
        } else if (i == -1 && !BN_get_flags(a, BN_FLG_STATIC_DATA)) {
            BIGNUM *tmp_bn = (BIGNUM *)a;
            if (bn_wexpand(tmp_bn, bl) == NULL)
                goto err;
            tmp_bn->d[al] = 0;
            al++;
            i++;
        }
        if (i == 0) {
            /* symmetric and > 4 */
            /* 16 or larger */
            j = BN_num_bits_word((BN_ULONG)al);
            j = 1 << (j - 1);
            k = j + j;
            t = BN_CTX_get(ctx);
            if (al == j) {      /* exact multiple */
                if (bn_wexpand(t, k * 2) == NULL)
                    goto err;
                if (bn_wexpand(rr, k * 2) == NULL)
                    goto err;
                bn_mul_recursive(rr->d, a->d, b->d, al, t->d);
            } else {
                if (bn_wexpand(t, k * 4) == NULL)
                    goto err;
                if (bn_wexpand(rr, k * 4) == NULL)
                    goto err;
                bn_mul_part_recursive(rr->d, a->d, b->d, al - j, j, t->d);
            }
            rr->top = top;
            goto end;
        }
# endif
    }
#endif                          /* BN_RECURSION */
    if (bn_wexpand(rr, top) == NULL)
        goto err;
    rr->top = top;
    bn_mul_normal(rr->d, a->d, al, b->d, bl);

#if defined(BN_MUL_COMBA) || defined(BN_RECURSION)
 end:
#endif
    bn_correct_top(rr);
    if (r != rr)
        BN_copy(r, rr);
    ret = 1;
 err:
    bn_check_top(r);
    BN_CTX_end(ctx);
    return (ret);
}
Exemple #13
0
int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) {
  int ret = 0;
  BIGNUM *Ri, *R;
  BIGNUM tmod;
  BN_ULONG buf[2];

  if (BN_is_zero(mod)) {
    OPENSSL_PUT_ERROR(BN, BN_R_DIV_BY_ZERO);
    return 0;
  }

  BN_CTX_start(ctx);
  Ri = BN_CTX_get(ctx);
  if (Ri == NULL) {
    goto err;
  }
  R = &mont->RR; /* grab RR as a temp */
  if (!BN_copy(&mont->N, mod)) {
    goto err; /* Set N */
  }
  mont->N.neg = 0;

  BN_init(&tmod);
  tmod.d = buf;
  tmod.dmax = 2;
  tmod.neg = 0;

  mont->ri = (BN_num_bits(mod) + (BN_BITS2 - 1)) / BN_BITS2 * BN_BITS2;

#if defined(OPENSSL_BN_ASM_MONT) && (BN_BITS2 <= 32)
  /* Only certain BN_BITS2<=32 platforms actually make use of
   * n0[1], and we could use the #else case (with a shorter R
   * value) for the others.  However, currently only the assembler
   * files do know which is which. */

  BN_zero(R);
  if (!BN_set_bit(R, 2 * BN_BITS2)) {
    goto err;
  }

  tmod.top = 0;
  if ((buf[0] = mod->d[0])) {
    tmod.top = 1;
  }
  if ((buf[1] = mod->top > 1 ? mod->d[1] : 0)) {
    tmod.top = 2;
  }

  if (BN_mod_inverse(Ri, R, &tmod, ctx) == NULL) {
    goto err;
  }
  if (!BN_lshift(Ri, Ri, 2 * BN_BITS2)) {
    goto err; /* R*Ri */
  }
  if (!BN_is_zero(Ri)) {
    if (!BN_sub_word(Ri, 1)) {
      goto err;
    }
  } else {
    /* if N mod word size == 1 */
    if (bn_expand(Ri, (int)sizeof(BN_ULONG) * 2) == NULL) {
      goto err;
    }
    /* Ri-- (mod double word size) */
    Ri->neg = 0;
    Ri->d[0] = BN_MASK2;
    Ri->d[1] = BN_MASK2;
    Ri->top = 2;
  }

  if (!BN_div(Ri, NULL, Ri, &tmod, ctx)) {
    goto err;
  }
  /* Ni = (R*Ri-1)/N,
   * keep only couple of least significant words: */
  mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0;
  mont->n0[1] = (Ri->top > 1) ? Ri->d[1] : 0;
#else
  BN_zero(R);
  if (!BN_set_bit(R, BN_BITS2)) {
    goto err; /* R */
  }

  buf[0] = mod->d[0]; /* tmod = N mod word size */
  buf[1] = 0;
  tmod.top = buf[0] != 0 ? 1 : 0;
  /* Ri = R^-1 mod N*/
  if (BN_mod_inverse(Ri, R, &tmod, ctx) == NULL) {
    goto err;
  }
  if (!BN_lshift(Ri, Ri, BN_BITS2)) {
    goto err; /* R*Ri */
  }
  if (!BN_is_zero(Ri)) {
    if (!BN_sub_word(Ri, 1)) {
      goto err;
    }
  } else {
    /* if N mod word size == 1 */
    if (!BN_set_word(Ri, BN_MASK2)) {
      goto err; /* Ri-- (mod word size) */
    }
  }
  if (!BN_div(Ri, NULL, Ri, &tmod, ctx)) {
    goto err;
  }
  /* Ni = (R*Ri-1)/N,
   * keep only least significant word: */
  mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0;
  mont->n0[1] = 0;
#endif

  /* setup RR for conversions */
  BN_zero(&(mont->RR));
  if (!BN_set_bit(&(mont->RR), mont->ri * 2)) {
    goto err;
  }
  if (!BN_mod(&(mont->RR), &(mont->RR), &(mont->N), ctx)) {
    goto err;
  }

  ret = 1;

err:
  BN_CTX_end(ctx);
  return ret;
}
Exemple #14
0
// bn_mul_impl implements |BN_mul| and |bn_mul_consttime|. Note this function
// breaks |BIGNUM| invariants and may return a negative zero. This is handled by
// the callers.
static int bn_mul_impl(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
                       BN_CTX *ctx) {
  int al = a->width;
  int bl = b->width;
  if (al == 0 || bl == 0) {
    BN_zero(r);
    return 1;
  }

  int ret = 0;
  BIGNUM *rr;
  BN_CTX_start(ctx);
  if (r == a || r == b) {
    rr = BN_CTX_get(ctx);
    if (rr == NULL) {
      goto err;
    }
  } else {
    rr = r;
  }
  rr->neg = a->neg ^ b->neg;

  int i = al - bl;
  if (i == 0) {
    if (al == 8) {
      if (!bn_wexpand(rr, 16)) {
        goto err;
      }
      rr->width = 16;
      bn_mul_comba8(rr->d, a->d, b->d);
      goto end;
    }
  }

  int top = al + bl;
  static const int kMulNormalSize = 16;
  if (al >= kMulNormalSize && bl >= kMulNormalSize) {
    if (-1 <= i && i <= 1) {
      // Find the larger power of two less than or equal to the larger length.
      int j;
      if (i >= 0) {
        j = BN_num_bits_word((BN_ULONG)al);
      } else {
        j = BN_num_bits_word((BN_ULONG)bl);
      }
      j = 1 << (j - 1);
      assert(j <= al || j <= bl);
      BIGNUM *t = BN_CTX_get(ctx);
      if (t == NULL) {
        goto err;
      }
      if (al > j || bl > j) {
        // We know |al| and |bl| are at most one from each other, so if al > j,
        // bl >= j, and vice versa. Thus we can use |bn_mul_part_recursive|.
        assert(al >= j && bl >= j);
        if (!bn_wexpand(t, j * 8) ||
            !bn_wexpand(rr, j * 4)) {
          goto err;
        }
        bn_mul_part_recursive(rr->d, a->d, b->d, j, al - j, bl - j, t->d);
      } else {
        // al <= j && bl <= j. Additionally, we know j <= al or j <= bl, so one
        // of al - j or bl - j is zero. The other, by the bound on |i| above, is
        // zero or -1. Thus, we can use |bn_mul_recursive|.
        if (!bn_wexpand(t, j * 4) ||
            !bn_wexpand(rr, j * 2)) {
          goto err;
        }
        bn_mul_recursive(rr->d, a->d, b->d, j, al - j, bl - j, t->d);
      }
      rr->width = top;
      goto end;
    }
  }

  if (!bn_wexpand(rr, top)) {
    goto err;
  }
  rr->width = top;
  bn_mul_normal(rr->d, a->d, al, b->d, bl);

end:
  if (r != rr && !BN_copy(r, rr)) {
    goto err;
  }
  ret = 1;

err:
  BN_CTX_end(ctx);
  return ret;
}
Exemple #15
0
/**
 * Reconstruct secret using the provided shares
 *
 * @param shares Shares used to reconstruct secret (should contain t entries)
 * @param t Threshold used to reconstruct the secret
 * @param prime Prime for finite field arithmetic
 * @param s Pointer for storage of calculated secred
 */
static int reconstructSecret(secret_share_t *shares, unsigned char t, const BIGNUM prime, BIGNUM *s)
{
	unsigned char i;
	unsigned char j;

	// Array representing the polynomial a(x) = s + a_1 * x + ... + a_n-1 * x^n-1 mod p
	BIGNUM **bValue = malloc(t * sizeof(BIGNUM *));
	BIGNUM **pbValue;
	BIGNUM numerator;
	BIGNUM denominator;
	BIGNUM temp;
	secret_share_t *sp_i;
	secret_share_t *sp_j;
	BN_CTX *ctx;

	// Initialize
	pbValue = bValue;
	for (i = 0; i < t; i++) {
		*pbValue = BN_new();
		BN_init(*pbValue);
		pbValue++;
	}

	BN_init(&numerator);
	BN_init(&denominator);
	BN_init(&temp);

	// Create context for temporary variables of engine
	ctx = BN_CTX_new();
	BN_CTX_init(ctx);

	pbValue = bValue;
	sp_i = shares;
	for (i = 0; i < t; i++) {

		BN_one(&numerator);
		BN_one(&denominator);

		sp_j = shares;

		for (j = 0; j < t; j++) {

			if (i == j) {
				sp_j++;
				continue;
			}

			BN_mul(&numerator, &numerator, &(sp_j->x), ctx);
			BN_sub(&temp, &(sp_j->x), &(sp_i->x));
			BN_mul(&denominator, &denominator, &temp, ctx);

			sp_j++;
		}

		/*
		 * Use the modular inverse value of the denominator for the
		 * multiplication
		 */
		if (BN_mod_inverse(&denominator, &denominator, &prime, ctx) == NULL ) {
			free(bValue);
			return -1;
		}

		BN_mod_mul(*pbValue, &numerator, &denominator, &prime, ctx);

		pbValue++;
		sp_i++;
	}

	/*
	 * Calculate the secret by multiplying all y-values with their
	 * corresponding intermediate values
	 */
	pbValue = bValue;
	sp_i = shares;
	BN_zero(s);
	for (i = 0; i < t; i++) {

		BN_mul(&temp, &(sp_i->y), *pbValue, ctx);
		BN_add(s, s, &temp);
		pbValue++;
		sp_i++;
	}

	// Perform modulo operation and copy result
	BN_nnmod(&temp, s, &prime, ctx);
	BN_copy(s, &temp);

	BN_clear_free(&numerator);
	BN_clear_free(&denominator);
	BN_clear_free(&temp);

	BN_CTX_free(ctx);

	// Deallocate the resource of the polynomial
	pbValue = bValue;
	for (i = 0; i < t; i++) {
		BN_clear_free(*pbValue);
		pbValue++;
	}

	free(bValue);

	return 0;
}
int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
	{
	int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
	int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
	const BIGNUM *p;
	BN_CTX *new_ctx = NULL;
	BIGNUM *n0, *n1, *n2, *n3, *n4, *n5, *n6;
	int ret = 0;
	
	if (a == b)
		return EC_POINT_dbl(group, r, a, ctx);
	if (EC_POINT_is_at_infinity(group, a))
		return EC_POINT_copy(r, b);
	if (EC_POINT_is_at_infinity(group, b))
		return EC_POINT_copy(r, a);
	
	field_mul = group->meth->field_mul;
	field_sqr = group->meth->field_sqr;
	p = &group->field;

	if (ctx == NULL)
		{
		ctx = new_ctx = BN_CTX_new();
		if (ctx == NULL)
			return 0;
		}

	BN_CTX_start(ctx);
	n0 = BN_CTX_get(ctx);
	n1 = BN_CTX_get(ctx);
	n2 = BN_CTX_get(ctx);
	n3 = BN_CTX_get(ctx);
	n4 = BN_CTX_get(ctx);
	n5 = BN_CTX_get(ctx);
	n6 = BN_CTX_get(ctx);
	if (n6 == NULL) goto end;

	/* Note that in this function we must not read components of 'a' or 'b'
	 * once we have written the corresponding components of 'r'.
	 * ('r' might be one of 'a' or 'b'.)
	 */

	/* n1, n2 */
	if (b->Z_is_one)
		{
		if (!BN_copy(n1, &a->X)) goto end;
		if (!BN_copy(n2, &a->Y)) goto end;
		/* n1 = X_a */
		/* n2 = Y_a */
		}
	else
		{
		if (!field_sqr(group, n0, &b->Z, ctx)) goto end;
		if (!field_mul(group, n1, &a->X, n0, ctx)) goto end;
		/* n1 = X_a * Z_b^2 */

		if (!field_mul(group, n0, n0, &b->Z, ctx)) goto end;
		if (!field_mul(group, n2, &a->Y, n0, ctx)) goto end;
		/* n2 = Y_a * Z_b^3 */
		}

	/* n3, n4 */
	if (a->Z_is_one)
		{
		if (!BN_copy(n3, &b->X)) goto end;
		if (!BN_copy(n4, &b->Y)) goto end;
		/* n3 = X_b */
		/* n4 = Y_b */
		}
	else
		{
		if (!field_sqr(group, n0, &a->Z, ctx)) goto end;
		if (!field_mul(group, n3, &b->X, n0, ctx)) goto end;
		/* n3 = X_b * Z_a^2 */

		if (!field_mul(group, n0, n0, &a->Z, ctx)) goto end;
		if (!field_mul(group, n4, &b->Y, n0, ctx)) goto end;
		/* n4 = Y_b * Z_a^3 */
		}

	/* n5, n6 */
	if (!BN_mod_sub_quick(n5, n1, n3, p)) goto end;
	if (!BN_mod_sub_quick(n6, n2, n4, p)) goto end;
	/* n5 = n1 - n3 */
	/* n6 = n2 - n4 */

	if (BN_is_zero(n5))
		{
		if (BN_is_zero(n6))
			{
			/* a is the same point as b */
			BN_CTX_end(ctx);
			ret = EC_POINT_dbl(group, r, a, ctx);
			ctx = NULL;
			goto end;
			}
		else
			{
			/* a is the inverse of b */
			BN_zero(&r->Z);
			r->Z_is_one = 0;
			ret = 1;
			goto end;
			}
		}

	/* 'n7', 'n8' */
	if (!BN_mod_add_quick(n1, n1, n3, p)) goto end;
	if (!BN_mod_add_quick(n2, n2, n4, p)) goto end;
	/* 'n7' = n1 + n3 */
	/* 'n8' = n2 + n4 */

	/* Z_r */
	if (a->Z_is_one && b->Z_is_one)
		{
		if (!BN_copy(&r->Z, n5)) goto end;
		}
	else
		{
		if (a->Z_is_one)
			{ if (!BN_copy(n0, &b->Z)) goto end; }
		else if (b->Z_is_one)
			{ if (!BN_copy(n0, &a->Z)) goto end; }
		else
			{ if (!field_mul(group, n0, &a->Z, &b->Z, ctx)) goto end; }
		if (!field_mul(group, &r->Z, n0, n5, ctx)) goto end;
		}
	r->Z_is_one = 0;
	/* Z_r = Z_a * Z_b * n5 */

	/* X_r */
	if (!field_sqr(group, n0, n6, ctx)) goto end;
	if (!field_sqr(group, n4, n5, ctx)) goto end;
	if (!field_mul(group, n3, n1, n4, ctx)) goto end;
	if (!BN_mod_sub_quick(&r->X, n0, n3, p)) goto end;
	/* X_r = n6^2 - n5^2 * 'n7' */
	
	/* 'n9' */
	if (!BN_mod_lshift1_quick(n0, &r->X, p)) goto end;
	if (!BN_mod_sub_quick(n0, n3, n0, p)) goto end;
	/* n9 = n5^2 * 'n7' - 2 * X_r */

	/* Y_r */
	if (!field_mul(group, n0, n0, n6, ctx)) goto end;
	if (!field_mul(group, n5, n4, n5, ctx)) goto end; /* now n5 is n5^3 */
	if (!field_mul(group, n1, n2, n5, ctx)) goto end;
	if (!BN_mod_sub_quick(n0, n0, n1, p)) goto end;
	if (BN_is_odd(n0))
		if (!BN_add(n0, n0, p)) goto end;
	/* now  0 <= n0 < 2*p,  and n0 is even */
	if (!BN_rshift1(&r->Y, n0)) goto end;
	/* Y_r = (n6 * 'n9' - 'n8' * 'n5^3') / 2 */

	ret = 1;

 end:
	if (ctx) /* otherwise we already called BN_CTX_end */
		BN_CTX_end(ctx);
	if (new_ctx != NULL)
		BN_CTX_free(new_ctx);
	return ret;
	}
Exemple #17
0
static int bnrand(int pseudorand, BIGNUM *rnd, int bits, int top, int bottom)
	{
	unsigned char *buf=NULL;
	int ret=0,bit,bytes,mask;
	time_t tim;

	if (bits == 0)
		{
		BN_zero(rnd);
		return 1;
		}

	bytes=(bits+7)/8;
	bit=(bits-1)%8;
	mask=0xff<<(bit+1);

	buf=(unsigned char *)OPENSSL_malloc(bytes);
	if (buf == NULL)
		{
		BNerr(BN_F_BNRAND,ERR_R_MALLOC_FAILURE);
		goto err;
		}

	/* make a random number and set the top and bottom bits */
	time(&tim);
	RAND_add(&tim,sizeof(tim),0.0);

	if (pseudorand)
		{
		if (RAND_pseudo_bytes(buf, bytes) == -1)
			goto err;
		}
	else
		{
		if (RAND_bytes(buf, bytes) <= 0)
			goto err;
		}

#if 1
	if (pseudorand == 2)
		{
		/* generate patterns that are more likely to trigger BN
		   library bugs */
		int i;
		unsigned char c;

		for (i = 0; i < bytes; i++)
			{
			RAND_pseudo_bytes(&c, 1);
			if (c >= 128 && i > 0)
				buf[i] = buf[i-1];
			else if (c < 42)
				buf[i] = 0;
			else if (c < 84)
				buf[i] = 255;
			}
		}
#endif

	if (top != -1)
		{
		if (top)
			{
			if (bit == 0)
				{
				buf[0]=1;
				buf[1]|=0x80;
				}
			else
				{
				buf[0]|=(3<<(bit-1));
				}
			}
		else
			{
			buf[0]|=(1<<bit);
			}
		}
	buf[0] &= ~mask;
	if (bottom) /* set bottom bit if requested */
		buf[bytes-1]|=1;
	if (!BN_bin2bn(buf,bytes,rnd)) goto err;
	ret=1;
err:
	if (buf != NULL)
		{
		OPENSSL_cleanse(buf,bytes);
		OPENSSL_free(buf);
		}
	bn_check_top(rnd);
	return(ret);
	}
int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
	{
	int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
	int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
	const BIGNUM *p;
	BN_CTX *new_ctx = NULL;
	BIGNUM *n0, *n1, *n2, *n3;
	int ret = 0;
	
	if (EC_POINT_is_at_infinity(group, a))
		{
		BN_zero(&r->Z);
		r->Z_is_one = 0;
		return 1;
		}

	field_mul = group->meth->field_mul;
	field_sqr = group->meth->field_sqr;
	p = &group->field;

	if (ctx == NULL)
		{
		ctx = new_ctx = BN_CTX_new();
		if (ctx == NULL)
			return 0;
		}

	BN_CTX_start(ctx);
	n0 = BN_CTX_get(ctx);
	n1 = BN_CTX_get(ctx);
	n2 = BN_CTX_get(ctx);
	n3 = BN_CTX_get(ctx);
	if (n3 == NULL) goto err;

	/* Note that in this function we must not read components of 'a'
	 * once we have written the corresponding components of 'r'.
	 * ('r' might the same as 'a'.)
	 */

	/* n1 */
	if (a->Z_is_one)
		{
		if (!field_sqr(group, n0, &a->X, ctx)) goto err;
		if (!BN_mod_lshift1_quick(n1, n0, p)) goto err;
		if (!BN_mod_add_quick(n0, n0, n1, p)) goto err;
		if (!BN_mod_add_quick(n1, n0, &group->a, p)) goto err;
		/* n1 = 3 * X_a^2 + a_curve */
		}
	else if (group->a_is_minus3)
		{
		if (!field_sqr(group, n1, &a->Z, ctx)) goto err;
		if (!BN_mod_add_quick(n0, &a->X, n1, p)) goto err;
		if (!BN_mod_sub_quick(n2, &a->X, n1, p)) goto err;
		if (!field_mul(group, n1, n0, n2, ctx)) goto err;
		if (!BN_mod_lshift1_quick(n0, n1, p)) goto err;
		if (!BN_mod_add_quick(n1, n0, n1, p)) goto err;
		/* n1 = 3 * (X_a + Z_a^2) * (X_a - Z_a^2)
		 *    = 3 * X_a^2 - 3 * Z_a^4 */
		}
	else
		{
		if (!field_sqr(group, n0, &a->X, ctx)) goto err;
		if (!BN_mod_lshift1_quick(n1, n0, p)) goto err;
		if (!BN_mod_add_quick(n0, n0, n1, p)) goto err;
		if (!field_sqr(group, n1, &a->Z, ctx)) goto err;
		if (!field_sqr(group, n1, n1, ctx)) goto err;
		if (!field_mul(group, n1, n1, &group->a, ctx)) goto err;
		if (!BN_mod_add_quick(n1, n1, n0, p)) goto err;
		/* n1 = 3 * X_a^2 + a_curve * Z_a^4 */
		}

	/* Z_r */
	if (a->Z_is_one)
		{
		if (!BN_copy(n0, &a->Y)) goto err;
		}
	else
		{
		if (!field_mul(group, n0, &a->Y, &a->Z, ctx)) goto err;
		}
	if (!BN_mod_lshift1_quick(&r->Z, n0, p)) goto err;
	r->Z_is_one = 0;
	/* Z_r = 2 * Y_a * Z_a */

	/* n2 */
	if (!field_sqr(group, n3, &a->Y, ctx)) goto err;
	if (!field_mul(group, n2, &a->X, n3, ctx)) goto err;
	if (!BN_mod_lshift_quick(n2, n2, 2, p)) goto err;
	/* n2 = 4 * X_a * Y_a^2 */

	/* X_r */
	if (!BN_mod_lshift1_quick(n0, n2, p)) goto err;
	if (!field_sqr(group, &r->X, n1, ctx)) goto err;
	if (!BN_mod_sub_quick(&r->X, &r->X, n0, p)) goto err;
	/* X_r = n1^2 - 2 * n2 */
	
	/* n3 */
	if (!field_sqr(group, n0, n3, ctx)) goto err;
	if (!BN_mod_lshift_quick(n3, n0, 3, p)) goto err;
	/* n3 = 8 * Y_a^4 */
	
	/* Y_r */
	if (!BN_mod_sub_quick(n0, n2, &r->X, p)) goto err;
	if (!field_mul(group, n0, n1, n0, ctx)) goto err;
	if (!BN_mod_sub_quick(&r->Y, n0, n3, p)) goto err;
	/* Y_r = n1 * (n2 - X_r) - n3 */

	ret = 1;

 err:
	BN_CTX_end(ctx);
	if (new_ctx != NULL)
		BN_CTX_free(new_ctx);
	return ret;
	}
Exemple #19
0
/*-
 * Compute the x, y affine coordinates from the point (x1, z1) (x2, z2)
 * using Montgomery point multiplication algorithm Mxy() in appendix of
 *     Lopez, J. and Dahab, R.  "Fast multiplication on elliptic curves over
 *     GF(2^m) without precomputation" (CHES '99, LNCS 1717).
 * Returns:
 *     0 on error
 *     1 if return value should be the point at infinity
 *     2 otherwise
 */
static int gf2m_Mxy(const EC_GROUP *group, const BIGNUM *x, const BIGNUM *y,
                    BIGNUM *x1, BIGNUM *z1, BIGNUM *x2, BIGNUM *z2,
                    BN_CTX *ctx)
{
    BIGNUM *t3, *t4, *t5;
    int ret = 0;

    if (BN_is_zero(z1)) {
        BN_zero(x2);
        BN_zero(z2);
        return 1;
    }

    if (BN_is_zero(z2)) {
        if (!BN_copy(x2, x))
            return 0;
        if (!BN_GF2m_add(z2, x, y))
            return 0;
        return 2;
    }

    /* Since Mxy is static we can guarantee that ctx != NULL. */
    BN_CTX_start(ctx);
    t3 = BN_CTX_get(ctx);
    t4 = BN_CTX_get(ctx);
    t5 = BN_CTX_get(ctx);
    if (t5 == NULL)
        goto err;

    if (!BN_one(t5))
        goto err;

    if (!group->meth->field_mul(group, t3, z1, z2, ctx))
        goto err;

    if (!group->meth->field_mul(group, z1, z1, x, ctx))
        goto err;
    if (!BN_GF2m_add(z1, z1, x1))
        goto err;
    if (!group->meth->field_mul(group, z2, z2, x, ctx))
        goto err;
    if (!group->meth->field_mul(group, x1, z2, x1, ctx))
        goto err;
    if (!BN_GF2m_add(z2, z2, x2))
        goto err;

    if (!group->meth->field_mul(group, z2, z2, z1, ctx))
        goto err;
    if (!group->meth->field_sqr(group, t4, x, ctx))
        goto err;
    if (!BN_GF2m_add(t4, t4, y))
        goto err;
    if (!group->meth->field_mul(group, t4, t4, t3, ctx))
        goto err;
    if (!BN_GF2m_add(t4, t4, z2))
        goto err;

    if (!group->meth->field_mul(group, t3, t3, x, ctx))
        goto err;
    if (!group->meth->field_div(group, t3, t5, t3, ctx))
        goto err;
    if (!group->meth->field_mul(group, t4, t3, t4, ctx))
        goto err;
    if (!group->meth->field_mul(group, x2, x1, t3, ctx))
        goto err;
    if (!BN_GF2m_add(z2, x2, x))
        goto err;

    if (!group->meth->field_mul(group, z2, z2, t4, ctx))
        goto err;
    if (!BN_GF2m_add(z2, z2, y))
        goto err;

    ret = 2;

 err:
    BN_CTX_end(ctx);
    return ret;
}
int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
	{
	point->Z_is_one = 0;
	BN_zero(&point->Z);
	return 1;
	}
Exemple #21
0
int generateRingSignature(data_chunk &keyImage, uint256 &txnHash, int nRingSize, int nSecretOffset, ec_secret secret, const uint8_t *pPubkeys, uint8_t *pSigc, uint8_t *pSigr)
{
    if (fDebugRingSig)
        LogPrintf("%s: Ring size %d.\n", __func__, nRingSize);

    int rv = 0;
    int nBytes;

    BN_CTX_start(bnCtx);

    BIGNUM   *bnKS  = BN_CTX_get(bnCtx);
    BIGNUM   *bnK1  = BN_CTX_get(bnCtx);
    BIGNUM   *bnK2  = BN_CTX_get(bnCtx);
    BIGNUM   *bnT   = BN_CTX_get(bnCtx);
    BIGNUM   *bnH   = BN_CTX_get(bnCtx);
    BIGNUM   *bnSum = BN_CTX_get(bnCtx);
    EC_POINT *ptT1  = NULL;
    EC_POINT *ptT2  = NULL;
    EC_POINT *ptT3  = NULL;
    EC_POINT *ptPk  = NULL;
    EC_POINT *ptKi  = NULL;
    EC_POINT *ptL   = NULL;
    EC_POINT *ptR   = NULL;

    uint8_t tempData[66]; // hold raw point data to hash
    uint256 commitHash;
    ec_secret scData1, scData2;

    CHashWriter ssCommitHash(SER_GETHASH, PROTOCOL_VERSION);

    ssCommitHash << txnHash;

    // zero signature
    memset(pSigc, 0, EC_SECRET_SIZE * nRingSize);
    memset(pSigr, 0, EC_SECRET_SIZE * nRingSize);


    // ks = random 256 bit int mod P
    if (GenerateRandomSecret(scData1)
    && (rv = errorN(1, "%s: GenerateRandomSecret failed.", __func__)))
        goto End;

    if (!bnKS || !(BN_bin2bn(&scData1.e[0], EC_SECRET_SIZE, bnKS)))
    {
        LogPrintf("%s: BN_bin2bn failed.\n", __func__);
        rv = 1; goto End;
    };

    // zero sum
    if (!bnSum || !(BN_zero(bnSum)))
    {
        LogPrintf("%s: BN_zero failed.\n", __func__);
        rv = 1; goto End;
    };

    if (   !(ptT1 = EC_POINT_new(ecGrp))
        || !(ptT2 = EC_POINT_new(ecGrp))
        || !(ptT3 = EC_POINT_new(ecGrp))
        || !(ptPk = EC_POINT_new(ecGrp))
        || !(ptKi = EC_POINT_new(ecGrp))
        || !(ptL  = EC_POINT_new(ecGrp))
        || !(ptR  = EC_POINT_new(ecGrp)))
    {
        LogPrintf("%s: EC_POINT_new failed.\n", __func__);
        rv = 1; goto End;
    };

    // get keyimage as point
    if (!(bnT = BN_bin2bn(&keyImage[0], EC_COMPRESSED_SIZE, bnT))
        || !(ptKi) || !(ptKi = EC_POINT_bn2point(ecGrp, bnT, ptKi, bnCtx)))
    {
        LogPrintf("%s: extract ptKi failed.\n", __func__);
        rv = 1; goto End;
    };

    for (int i = 0; i < nRingSize; ++i)
    {
        if (i == nSecretOffset)
        {
            // k = random 256 bit int mod P
            // L = k * G
            // R = k * HashToEC(PKi)

            if (!EC_POINT_mul(ecGrp, ptL, bnKS, NULL, NULL, bnCtx))
            {
                LogPrintf("%s: EC_POINT_mul failed.\n", __func__);
                rv = 1; goto End;
            };

            if (hashToEC(&pPubkeys[i * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnT, ptT1) != 0)
            {
                LogPrintf("%s: hashToEC failed.\n", __func__);
                rv = 1; goto End;
            };

            if (!EC_POINT_mul(ecGrp, ptR, NULL, ptT1, bnKS, bnCtx))
            {
                LogPrintf("%s: EC_POINT_mul failed.\n", __func__);
                rv = 1; goto End;
            };

        } else
        {
            // k1 = random 256 bit int mod P
            // k2 = random 256 bit int mod P
            // Li = k1 * Pi + k2 * G
            // Ri = k1 * I + k2 * Hp(Pi)
            // ci = k1
            // ri = k2

            if (GenerateRandomSecret(scData1) != 0
                || !bnK1 || !(BN_bin2bn(&scData1.e[0], EC_SECRET_SIZE, bnK1))
                || GenerateRandomSecret(scData2) != 0
                || !bnK2 || !(BN_bin2bn(&scData2.e[0], EC_SECRET_SIZE, bnK2)))
            {
                LogPrintf("%s: k1 and k2 failed.\n", __func__);
                rv = 1; goto End;
            };

            // get Pk i as point
            if (!(bnT = BN_bin2bn(&pPubkeys[i * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnT))
                || !(ptPk) || !(ptPk = EC_POINT_bn2point(ecGrp, bnT, ptPk, bnCtx)))
            {
                LogPrintf("%s: extract ptPk failed.\n", __func__);
                rv = 1; goto End;
            };

            // ptT1 = k1 * Pi
            if (!EC_POINT_mul(ecGrp, ptT1, NULL, ptPk, bnK1, bnCtx))
            {
                LogPrintf("%s: EC_POINT_mul failed.\n", __func__);
                rv = 1; goto End;
            };

            // ptT2 = k2 * G
            if (!EC_POINT_mul(ecGrp, ptT2, bnK2, NULL, NULL, bnCtx))
            {
                LogPrintf("%s: EC_POINT_mul failed.\n", __func__);
                rv = 1; goto End;
            };

            // ptL = ptT1 + ptT2
            if (!EC_POINT_add(ecGrp, ptL, ptT1, ptT2, bnCtx))
            {
                LogPrintf("%s: EC_POINT_add failed.\n", __func__);
                rv = 1; goto End;
            };

            // ptT3 = Hp(Pi)
            if (hashToEC(&pPubkeys[i * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnT, ptT3) != 0)
            {
                LogPrintf("%s: hashToEC failed.\n", __func__);
                rv = 1; goto End;
            };

            // ptT1 = k1 * I
            if (!EC_POINT_mul(ecGrp, ptT1, NULL, ptKi, bnK1, bnCtx))
            {
                LogPrintf("%s: EC_POINT_mul failed.\n", __func__);
                rv = 1; goto End;
            };

            // ptT2 = k2 * ptT3
            if (!EC_POINT_mul(ecGrp, ptT2, NULL, ptT3, bnK2, bnCtx))
            {
                LogPrintf("%s: EC_POINT_mul failed.\n", __func__);
                rv = 1; goto End;
            };

            // ptR = ptT1 + ptT2
            if (!EC_POINT_add(ecGrp, ptR, ptT1, ptT2, bnCtx))
            {
                LogPrintf("%s: EC_POINT_add failed.\n", __func__);
                rv = 1; goto End;
            };

            memcpy(&pSigc[i * EC_SECRET_SIZE], &scData1.e[0], EC_SECRET_SIZE);
            memcpy(&pSigr[i * EC_SECRET_SIZE], &scData2.e[0], EC_SECRET_SIZE);

            // sum = (sum + sigc) % N , sigc == bnK1
            if (!BN_mod_add(bnSum, bnSum, bnK1, bnOrder, bnCtx))
            {
                LogPrintf("%s: BN_mod_add failed.\n", __func__);
                rv = 1; goto End;
            };
        };

        // -- add ptL and ptR to hash
        if (   !(EC_POINT_point2oct(ecGrp, ptL, POINT_CONVERSION_COMPRESSED, &tempData[0],  33, bnCtx) == (int) EC_COMPRESSED_SIZE)
            || !(EC_POINT_point2oct(ecGrp, ptR, POINT_CONVERSION_COMPRESSED, &tempData[33], 33, bnCtx) == (int) EC_COMPRESSED_SIZE))
        {
            LogPrintf("%s: extract ptL and ptR failed.\n", __func__);
            rv = 1; goto End;
        };

        ssCommitHash.write((const char*)&tempData[0], 66);
    };

    commitHash = ssCommitHash.GetHash();

    if (!(bnH) || !(bnH = BN_bin2bn(commitHash.begin(), EC_SECRET_SIZE, bnH)))
    {
        LogPrintf("%s: commitHash -> bnH failed.\n", __func__);
        rv = 1; goto End;
    };


    if (!BN_mod(bnH, bnH, bnOrder, bnCtx)) // this is necessary
    {
        LogPrintf("%s: BN_mod failed.\n", __func__);
        rv = 1; goto End;
    };

    // sigc[nSecretOffset] = (bnH - bnSum) % N
    if (!BN_mod_sub(bnT, bnH, bnSum, bnOrder, bnCtx))
    {
        LogPrintf("%s: BN_mod_sub failed.\n", __func__);
        rv = 1; goto End;
    };

    if ((nBytes = BN_num_bytes(bnT)) > (int)EC_SECRET_SIZE
        || BN_bn2bin(bnT, &pSigc[nSecretOffset * EC_SECRET_SIZE + (EC_SECRET_SIZE-nBytes)]) != nBytes)
    {
        LogPrintf("%s: bnT -> pSigc failed.\n", __func__);
        rv = 1; goto End;
    };

    // sigr[nSecretOffset] = (bnKS - sigc[nSecretOffset] * bnSecret) % N
    // reuse bnH for bnSecret
    if (!bnH || !(BN_bin2bn(&secret.e[0], EC_SECRET_SIZE, bnH)))
    {
        LogPrintf("%s: BN_bin2bn failed.\n", __func__);
        rv = 1; goto End;
    };

    // bnT = sigc[nSecretOffset] * bnSecret , TODO: mod N ?
    if (!BN_mul(bnT, bnT, bnH, bnCtx))
    {
        LogPrintf("%s: BN_mul failed.\n", __func__);
        rv = 1; goto End;
    };

    if (!BN_mod_sub(bnT, bnKS, bnT, bnOrder, bnCtx))
    {
        LogPrintf("%s: BN_mod_sub failed.\n", __func__);
        rv = 1; goto End;
    };

    if ((nBytes = BN_num_bytes(bnT)) > (int) EC_SECRET_SIZE
        || BN_bn2bin(bnT, &pSigr[nSecretOffset * EC_SECRET_SIZE + (EC_SECRET_SIZE-nBytes)]) != nBytes)
    {
        LogPrintf("%s: bnT -> pSigr failed.\n", __func__);
        rv = 1; goto End;
    };

    End:
    EC_POINT_free(ptT1);
    EC_POINT_free(ptT2);
    EC_POINT_free(ptT3);
    EC_POINT_free(ptPk);
    EC_POINT_free(ptKi);
    EC_POINT_free(ptL);
    EC_POINT_free(ptR);

    BN_CTX_end(bnCtx);

    return rv;
};
Exemple #22
0
int BN_div_recp(BIGNUM *dv, BIGNUM *rem, BIGNUM *m, BN_RECP_CTX *recp,
	     BN_CTX *ctx)
	{
	int i,j,ret=0;
	BIGNUM *a,*b,*d,*r;

	BN_CTX_start(ctx);
	a=BN_CTX_get(ctx);
	b=BN_CTX_get(ctx);
	if (dv != NULL)
		d=dv;
	else
		d=BN_CTX_get(ctx);
	if (rem != NULL)
		r=rem;
	else
		r=BN_CTX_get(ctx);
	if (a == NULL || b == NULL || d == NULL || r == NULL) goto err;

	if (BN_ucmp(m,&(recp->N)) < 0)
		{
		BN_zero(d);
		BN_copy(r,m);
		BN_CTX_end(ctx);
		return(1);
		}

	/* We want the remainder
	 * Given input of ABCDEF / ab
	 * we need multiply ABCDEF by 3 digests of the reciprocal of ab
	 *
	 */
	i=BN_num_bits(m);

	j=recp->num_bits<<1;
	if (j>i) i=j;
	j>>=1;

	if (i != recp->shift)
		recp->shift=BN_reciprocal(&(recp->Nr),&(recp->N),
			i,ctx);

	if (!BN_rshift(a,m,j)) goto err;
	if (!BN_mul(b,a,&(recp->Nr),ctx)) goto err;
	if (!BN_rshift(d,b,i-j)) goto err;
	d->neg=0;
	if (!BN_mul(b,&(recp->N),d,ctx)) goto err;
	if (!BN_usub(r,m,b)) goto err;
	r->neg=0;

#if 1
	j=0;
	while (BN_ucmp(r,&(recp->N)) >= 0)
		{
		if (j++ > 2)
			{
			BNerr(BN_F_BN_MOD_MUL_RECIPROCAL,BN_R_BAD_RECIPROCAL);
			goto err;
			}
		if (!BN_usub(r,r,&(recp->N))) goto err;
		if (!BN_add_word(d,1)) goto err;
		}
#endif

	r->neg=BN_is_zero(r)?0:m->neg;
	d->neg=m->neg^recp->N.neg;
	ret=1;
err:
	BN_CTX_end(ctx);
	return(ret);
	} 
Exemple #23
0
// Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields
// recid selects which key is recovered
// if check is nonzero, additional checks are performed
int ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned char *msg, int msglen, int recid, int check)
{
    if (!eckey) return 0;

    int ret = 0;
    BN_CTX *ctx = NULL;

    BIGNUM *x = NULL;
    BIGNUM *e = NULL;
    BIGNUM *order = NULL;
    BIGNUM *sor = NULL;
    BIGNUM *eor = NULL;
    BIGNUM *field = NULL;
    EC_POINT *R = NULL;
    EC_POINT *O = NULL;
    EC_POINT *Q = NULL;
    BIGNUM *rr = NULL;
    BIGNUM *zero = NULL;
    int n = 0;
    int i = recid / 2;

    const EC_GROUP *group = EC_KEY_get0_group(eckey);
    if ((ctx = BN_CTX_new()) == NULL) { ret = -1; goto err; }
    BN_CTX_start(ctx);
    order = BN_CTX_get(ctx);
    if (!EC_GROUP_get_order(group, order, ctx)) { ret = -2; goto err; }
    x = BN_CTX_get(ctx);
    if (!BN_copy(x, order)) { ret=-1; goto err; }
    if (!BN_mul_word(x, i)) { ret=-1; goto err; }
    if (!BN_add(x, x, ecsig->r)) { ret=-1; goto err; }
    field = BN_CTX_get(ctx);
    if (!EC_GROUP_get_curve_GFp(group, field, NULL, NULL, ctx)) { ret=-2; goto err; }
    if (BN_cmp(x, field) >= 0) { ret=0; goto err; }
    if ((R = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
    if (!EC_POINT_set_compressed_coordinates_GFp(group, R, x, recid % 2, ctx)) { ret=0; goto err; }
    if (check)
    {
        if ((O = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
        if (!EC_POINT_mul(group, O, NULL, R, order, ctx)) { ret=-2; goto err; }
        if (!EC_POINT_is_at_infinity(group, O)) { ret = 0; goto err; }
    }
    if ((Q = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
    n = EC_GROUP_get_degree(group);
    e = BN_CTX_get(ctx);
    if (!BN_bin2bn(msg, msglen, e)) { ret=-1; goto err; }
    if (8*msglen > n) BN_rshift(e, e, 8-(n & 7));
    zero = BN_CTX_get(ctx);
    if (!BN_zero(zero)) { ret=-1; goto err; }
    if (!BN_mod_sub(e, zero, e, order, ctx)) { ret=-1; goto err; }
    rr = BN_CTX_get(ctx);
    if (!BN_mod_inverse(rr, ecsig->r, order, ctx)) { ret=-1; goto err; }
    sor = BN_CTX_get(ctx);
    if (!BN_mod_mul(sor, ecsig->s, rr, order, ctx)) { ret=-1; goto err; }
    eor = BN_CTX_get(ctx);
    if (!BN_mod_mul(eor, e, rr, order, ctx)) { ret=-1; goto err; }
    if (!EC_POINT_mul(group, Q, eor, R, sor, ctx)) { ret=-2; goto err; }
    if (!EC_KEY_set_public_key(eckey, Q)) { ret=-2; goto err; }

    ret = 1;

err:
    if (ctx) {
        BN_CTX_end(ctx);
        BN_CTX_free(ctx);
    }
    if (R != NULL) EC_POINT_free(R);
    if (O != NULL) EC_POINT_free(O);
    if (Q != NULL) EC_POINT_free(Q);
    return ret;
}
Exemple #24
0
/* random number r:  0 <= r < range */
static int
bn_rand_range(int pseudo, BIGNUM *r, const BIGNUM *range)
{
	int (*bn_rand)(BIGNUM *, int, int, int) = pseudo ? BN_pseudo_rand : BN_rand;
	int n;
	int count = 100;

	if (range->neg || BN_is_zero(range)) {
		BNerr(BN_F_BN_RAND_RANGE, BN_R_INVALID_RANGE);
		return 0;
	}

	n = BN_num_bits(range); /* n > 0 */

	/* BN_is_bit_set(range, n - 1) always holds */

	if (n == 1)
		BN_zero(r);
	else if (!BN_is_bit_set(range, n - 2) && !BN_is_bit_set(range, n - 3)) {
		/* range = 100..._2,
		 * so  3*range (= 11..._2)  is exactly one bit longer than  range */
		do {
			if (!bn_rand(r, n + 1, -1, 0))
				return 0;
			/* If  r < 3*range,  use  r := r MOD range
			 * (which is either  r, r - range,  or  r - 2*range).
			 * Otherwise, iterate once more.
			 * Since  3*range = 11..._2, each iteration succeeds with
			 * probability >= .75. */
			if (BN_cmp(r, range) >= 0) {
				if (!BN_sub(r, r, range))
					return 0;
				if (BN_cmp(r, range) >= 0)
					if (!BN_sub(r, r, range))
						return 0;
			}

			if (!--count) {
				BNerr(BN_F_BN_RAND_RANGE,
				    BN_R_TOO_MANY_ITERATIONS);
				return 0;
			}

		} while (BN_cmp(r, range) >= 0);
	} else {
		do {
			/* range = 11..._2  or  range = 101..._2 */
			if (!bn_rand(r, n, -1, 0))
				return 0;

			if (!--count) {
				BNerr(BN_F_BN_RAND_RANGE,
				    BN_R_TOO_MANY_ITERATIONS);
				return 0;
			}
		} while (BN_cmp(r, range) >= 0);
	}

	bn_check_top(r);
	return 1;
}
int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits,
                         const EVP_MD *evpmd, const unsigned char *seed_in,
                         size_t seed_len, int *counter_ret,
                         unsigned long *h_ret, BN_GENCB *cb)
{
    int ok = 0;
    unsigned char seed[SHA256_DIGEST_LENGTH];
    unsigned char md[SHA256_DIGEST_LENGTH];
    unsigned char buf[SHA256_DIGEST_LENGTH], buf2[SHA256_DIGEST_LENGTH];
    BIGNUM *r0, *W, *X, *c, *test;
    BIGNUM *g = NULL, *q = NULL, *p = NULL;
    BN_MONT_CTX *mont = NULL;
    int i, k, n = 0, m = 0, qsize = qbits >> 3;
    int counter = 0;
    int r = 0;
    BN_CTX *ctx = NULL;
    unsigned int h = 2;

    if (qsize != SHA_DIGEST_LENGTH && qsize != SHA224_DIGEST_LENGTH &&
        qsize != SHA256_DIGEST_LENGTH)
        /* invalid q size */
        return 0;

    if (evpmd == NULL)
        /* use SHA1 as default */
        evpmd = EVP_sha1();

    if (bits < 512)
        bits = 512;

    bits = (bits + 63) / 64 * 64;

    /*
     * NB: seed_len == 0 is special case: copy generated seed to seed_in if
     * it is not NULL.
     */
    if (seed_len && (seed_len < (size_t)qsize))
        seed_in = NULL;         /* seed buffer too small -- ignore */
    if (seed_len > (size_t)qsize)
        seed_len = qsize;       /* App. 2.2 of FIPS PUB 186 allows larger
                                 * SEED, but our internal buffers are
                                 * restricted to 160 bits */
    if (seed_in != NULL)
        memcpy(seed, seed_in, seed_len);

    if ((ctx = BN_CTX_new()) == NULL)
        goto err;

    if ((mont = BN_MONT_CTX_new()) == NULL)
        goto err;

    BN_CTX_start(ctx);
    r0 = BN_CTX_get(ctx);
    g = BN_CTX_get(ctx);
    W = BN_CTX_get(ctx);
    q = BN_CTX_get(ctx);
    X = BN_CTX_get(ctx);
    c = BN_CTX_get(ctx);
    p = BN_CTX_get(ctx);
    test = BN_CTX_get(ctx);

    if (!BN_lshift(test, BN_value_one(), bits - 1))
        goto err;

    for (;;) {
        for (;;) {              /* find q */
            int seed_is_random;

            /* step 1 */
            if (!BN_GENCB_call(cb, 0, m++))
                goto err;

            if (!seed_len) {
                RAND_pseudo_bytes(seed, qsize);
                seed_is_random = 1;
            } else {
                seed_is_random = 0;
                seed_len = 0;   /* use random seed if 'seed_in' turns out to
                                 * be bad */
            }
            memcpy(buf, seed, qsize);
            memcpy(buf2, seed, qsize);
            /* precompute "SEED + 1" for step 7: */
            for (i = qsize - 1; i >= 0; i--) {
                buf[i]++;
                if (buf[i] != 0)
                    break;
            }

            /* step 2 */
            EVP_Digest(seed, qsize, md, NULL, evpmd, NULL);
            EVP_Digest(buf, qsize, buf2, NULL, evpmd, NULL);
            for (i = 0; i < qsize; i++)
                md[i] ^= buf2[i];

            /* step 3 */
            md[0] |= 0x80;
            md[qsize - 1] |= 0x01;
            if (!BN_bin2bn(md, qsize, q))
                goto err;

            /* step 4 */
            r = BN_is_prime_fasttest_ex(q, DSS_prime_checks, ctx,
                                        seed_is_random, cb);
            if (r > 0)
                break;
            if (r != 0)
                goto err;

            /* do a callback call */
            /* step 5 */
        }

        if (!BN_GENCB_call(cb, 2, 0))
            goto err;
        if (!BN_GENCB_call(cb, 3, 0))
            goto err;

        /* step 6 */
        counter = 0;
        /* "offset = 2" */

        n = (bits - 1) / 160;

        for (;;) {
            if ((counter != 0) && !BN_GENCB_call(cb, 0, counter))
                goto err;

            /* step 7 */
            BN_zero(W);
            /* now 'buf' contains "SEED + offset - 1" */
            for (k = 0; k <= n; k++) {
                /*
                 * obtain "SEED + offset + k" by incrementing:
                 */
                for (i = qsize - 1; i >= 0; i--) {
                    buf[i]++;
                    if (buf[i] != 0)
                        break;
                }

                EVP_Digest(buf, qsize, md, NULL, evpmd, NULL);

                /* step 8 */
                if (!BN_bin2bn(md, qsize, r0))
                    goto err;
                if (!BN_lshift(r0, r0, (qsize << 3) * k))
                    goto err;
                if (!BN_add(W, W, r0))
                    goto err;
            }

            /* more of step 8 */
            if (!BN_mask_bits(W, bits - 1))
                goto err;
            if (!BN_copy(X, W))
                goto err;
            if (!BN_add(X, X, test))
                goto err;

            /* step 9 */
            if (!BN_lshift1(r0, q))
                goto err;
            if (!BN_mod(c, X, r0, ctx))
                goto err;
            if (!BN_sub(r0, c, BN_value_one()))
                goto err;
            if (!BN_sub(p, X, r0))
                goto err;

            /* step 10 */
            if (BN_cmp(p, test) >= 0) {
                /* step 11 */
                r = BN_is_prime_fasttest_ex(p, DSS_prime_checks, ctx, 1, cb);
                if (r > 0)
                    goto end;   /* found it */
                if (r != 0)
                    goto err;
            }

            /* step 13 */
            counter++;
            /* "offset = offset + n + 1" */

            /* step 14 */
            if (counter >= 4096)
                break;
        }
    }
 end:
    if (!BN_GENCB_call(cb, 2, 1))
        goto err;

    /* We now need to generate g */
    /* Set r0=(p-1)/q */
    if (!BN_sub(test, p, BN_value_one()))
        goto err;
    if (!BN_div(r0, NULL, test, q, ctx))
        goto err;

    if (!BN_set_word(test, h))
        goto err;
    if (!BN_MONT_CTX_set(mont, p, ctx))
        goto err;

    for (;;) {
        /* g=test^r0%p */
        if (!BN_mod_exp_mont(g, test, r0, p, ctx, mont))
            goto err;
        if (!BN_is_one(g))
            break;
        if (!BN_add(test, test, BN_value_one()))
            goto err;
        h++;
    }

    if (!BN_GENCB_call(cb, 3, 1))
        goto err;

    ok = 1;
 err:
    if (ok) {
        if (ret->p)
            BN_free(ret->p);
        if (ret->q)
            BN_free(ret->q);
        if (ret->g)
            BN_free(ret->g);
        ret->p = BN_dup(p);
        ret->q = BN_dup(q);
        ret->g = BN_dup(g);
        if (ret->p == NULL || ret->q == NULL || ret->g == NULL) {
            ok = 0;
            goto err;
        }
        if (counter_ret != NULL)
            *counter_ret = counter;
        if (h_ret != NULL)
            *h_ret = h;
    }
    if (ctx) {
        BN_CTX_end(ctx);
        BN_CTX_free(ctx);
    }
    if (mont != NULL)
        BN_MONT_CTX_free(mont);
    return ok;
}
Exemple #26
0
/*-
 * BN_div computes  dv := num / divisor,  rounding towards
 * zero, and sets up rm  such that  dv*divisor + rm = num  holds.
 * Thus:
 *     dv->neg == num->neg ^ divisor->neg  (unless the result is zero)
 *     rm->neg == num->neg                 (unless the remainder is zero)
 * If 'dv' or 'rm' is NULL, the respective value is not returned.
 */
int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
           BN_CTX *ctx)
{
    int norm_shift, i, loop;
    BIGNUM *tmp, wnum, *snum, *sdiv, *res;
    BN_ULONG *resp, *wnump;
    BN_ULONG d0, d1;
    int num_n, div_n;
    int no_branch = 0;

    /*
     * Invalid zero-padding would have particularly bad consequences so don't
     * just rely on bn_check_top() here (bn_check_top() works only for
     * BN_DEBUG builds)
     */
    if ((num->top > 0 && num->d[num->top - 1] == 0) ||
        (divisor->top > 0 && divisor->d[divisor->top - 1] == 0)) {
        BNerr(BN_F_BN_DIV, BN_R_NOT_INITIALIZED);
        return 0;
    }

    bn_check_top(num);
    bn_check_top(divisor);

    if ((BN_get_flags(num, BN_FLG_CONSTTIME) != 0)
        || (BN_get_flags(divisor, BN_FLG_CONSTTIME) != 0)) {
        no_branch = 1;
    }

    bn_check_top(dv);
    bn_check_top(rm);
    /*- bn_check_top(num); *//*
     * 'num' has been checked already
     */
    /*- bn_check_top(divisor); *//*
     * 'divisor' has been checked already
     */

    if (BN_is_zero(divisor)) {
        BNerr(BN_F_BN_DIV, BN_R_DIV_BY_ZERO);
        return (0);
    }

    if (!no_branch && BN_ucmp(num, divisor) < 0) {
        if (rm != NULL) {
            if (BN_copy(rm, num) == NULL)
                return (0);
        }
        if (dv != NULL)
            BN_zero(dv);
        return (1);
    }

    BN_CTX_start(ctx);
    tmp = BN_CTX_get(ctx);
    snum = BN_CTX_get(ctx);
    sdiv = BN_CTX_get(ctx);
    if (dv == NULL)
        res = BN_CTX_get(ctx);
    else
        res = dv;
    if (sdiv == NULL || res == NULL || tmp == NULL || snum == NULL)
        goto err;

    /* First we normalise the numbers */
    norm_shift = BN_BITS2 - ((BN_num_bits(divisor)) % BN_BITS2);
    if (!(BN_lshift(sdiv, divisor, norm_shift)))
        goto err;
    sdiv->neg = 0;
    norm_shift += BN_BITS2;
    if (!(BN_lshift(snum, num, norm_shift)))
        goto err;
    snum->neg = 0;

    if (no_branch) {
        /*
         * Since we don't know whether snum is larger than sdiv, we pad snum
         * with enough zeroes without changing its value.
         */
        if (snum->top <= sdiv->top + 1) {
            if (bn_wexpand(snum, sdiv->top + 2) == NULL)
                goto err;
            for (i = snum->top; i < sdiv->top + 2; i++)
                snum->d[i] = 0;
            snum->top = sdiv->top + 2;
        } else {
            if (bn_wexpand(snum, snum->top + 1) == NULL)
                goto err;
            snum->d[snum->top] = 0;
            snum->top++;
        }
    }

    div_n = sdiv->top;
    num_n = snum->top;
    loop = num_n - div_n;
    /*
     * Lets setup a 'window' into snum This is the part that corresponds to
     * the current 'area' being divided
     */
    wnum.neg = 0;
    wnum.d = &(snum->d[loop]);
    wnum.top = div_n;
    /*
     * only needed when BN_ucmp messes up the values between top and max
     */
    wnum.dmax = snum->dmax - loop; /* so we don't step out of bounds */

    /* Get the top 2 words of sdiv */
    /* div_n=sdiv->top; */
    d0 = sdiv->d[div_n - 1];
    d1 = (div_n == 1) ? 0 : sdiv->d[div_n - 2];

    /* pointer to the 'top' of snum */
    wnump = &(snum->d[num_n - 1]);

    /* Setup to 'res' */
    res->neg = (num->neg ^ divisor->neg);
    if (!bn_wexpand(res, (loop + 1)))
        goto err;
    res->top = loop - no_branch;
    resp = &(res->d[loop - 1]);

    /* space for temp */
    if (!bn_wexpand(tmp, (div_n + 1)))
        goto err;

    if (!no_branch) {
        if (BN_ucmp(&wnum, sdiv) >= 0) {
            /*
             * If BN_DEBUG_RAND is defined BN_ucmp changes (via bn_pollute)
             * the const bignum arguments => clean the values between top and
             * max again
             */
            bn_clear_top2max(&wnum);
            bn_sub_words(wnum.d, wnum.d, sdiv->d, div_n);
            *resp = 1;
        } else
            res->top--;
    }

    /*
     * if res->top == 0 then clear the neg value otherwise decrease the resp
     * pointer
     */
    if (res->top == 0)
        res->neg = 0;
    else
        resp--;

    for (i = 0; i < loop - 1; i++, wnump--, resp--) {
        BN_ULONG q, l0;
        /*
         * the first part of the loop uses the top two words of snum and sdiv
         * to calculate a BN_ULONG q such that | wnum - sdiv * q | < sdiv
         */
# if defined(BN_DIV3W) && !defined(OPENSSL_NO_ASM)
        BN_ULONG bn_div_3_words(BN_ULONG *, BN_ULONG, BN_ULONG);
        q = bn_div_3_words(wnump, d1, d0);
# else
        BN_ULONG n0, n1, rem = 0;

        n0 = wnump[0];
        n1 = wnump[-1];
        if (n0 == d0)
            q = BN_MASK2;
        else {                  /* n0 < d0 */

#  ifdef BN_LLONG
            BN_ULLONG t2;

#   if defined(BN_LLONG) && defined(BN_DIV2W) && !defined(bn_div_words)
            q = (BN_ULONG)(((((BN_ULLONG) n0) << BN_BITS2) | n1) / d0);
#   else
            q = bn_div_words(n0, n1, d0);
#   endif

#   ifndef REMAINDER_IS_ALREADY_CALCULATED
            /*
             * rem doesn't have to be BN_ULLONG. The least we
             * know it's less that d0, isn't it?
             */
            rem = (n1 - q * d0) & BN_MASK2;
#   endif
            t2 = (BN_ULLONG) d1 *q;

            for (;;) {
                if (t2 <= ((((BN_ULLONG) rem) << BN_BITS2) | wnump[-2]))
                    break;
                q--;
                rem += d0;
                if (rem < d0)
                    break;      /* don't let rem overflow */
                t2 -= d1;
            }
#  else                         /* !BN_LLONG */
            BN_ULONG t2l, t2h;

            q = bn_div_words(n0, n1, d0);
#   ifndef REMAINDER_IS_ALREADY_CALCULATED
            rem = (n1 - q * d0) & BN_MASK2;
#   endif

#   if defined(BN_UMULT_LOHI)
            BN_UMULT_LOHI(t2l, t2h, d1, q);
#   elif defined(BN_UMULT_HIGH)
            t2l = d1 * q;
            t2h = BN_UMULT_HIGH(d1, q);
#   else
            {
                BN_ULONG ql, qh;
                t2l = LBITS(d1);
                t2h = HBITS(d1);
                ql = LBITS(q);
                qh = HBITS(q);
                mul64(t2l, t2h, ql, qh); /* t2=(BN_ULLONG)d1*q; */
            }
#   endif

            for (;;) {
                if ((t2h < rem) || ((t2h == rem) && (t2l <= wnump[-2])))
                    break;
                q--;
                rem += d0;
                if (rem < d0)
                    break;      /* don't let rem overflow */
                if (t2l < d1)
                    t2h--;
                t2l -= d1;
            }
#  endif                        /* !BN_LLONG */
        }
# endif                         /* !BN_DIV3W */

        l0 = bn_mul_words(tmp->d, sdiv->d, div_n, q);
        tmp->d[div_n] = l0;
        wnum.d--;
        /*
         * ingore top values of the bignums just sub the two BN_ULONG arrays
         * with bn_sub_words
         */
        if (bn_sub_words(wnum.d, wnum.d, tmp->d, div_n + 1)) {
            /*
             * Note: As we have considered only the leading two BN_ULONGs in
             * the calculation of q, sdiv * q might be greater than wnum (but
             * then (q-1) * sdiv is less or equal than wnum)
             */
            q--;
            if (bn_add_words(wnum.d, wnum.d, sdiv->d, div_n))
                /*
                 * we can't have an overflow here (assuming that q != 0, but
                 * if q == 0 then tmp is zero anyway)
                 */
                (*wnump)++;
        }
        /* store part of the result */
        *resp = q;
    }
    bn_correct_top(snum);
    if (rm != NULL) {
        /*
         * Keep a copy of the neg flag in num because if rm==num BN_rshift()
         * will overwrite it.
         */
        int neg = num->neg;
        BN_rshift(rm, snum, norm_shift);
        if (!BN_is_zero(rm))
            rm->neg = neg;
        bn_check_top(rm);
    }
    if (no_branch)
        bn_correct_top(res);
    BN_CTX_end(ctx);
    return (1);
 err:
    bn_check_top(rm);
    BN_CTX_end(ctx);
    return (0);
}
Exemple #27
0
/* BN_mod_inverse_no_branch is a special version of BN_mod_inverse. 
 * It does not contain branches that may leak sensitive information.
 */
static BIGNUM *BN_mod_inverse_no_branch(BIGNUM *in,
	const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx)
	{
	BIGNUM *A,*B,*X,*Y,*M,*D,*T,*R=NULL;
	BIGNUM local_A, local_B;
	BIGNUM *pA, *pB;
	BIGNUM *ret=NULL;
	int sign;

	bn_check_top(a);
	bn_check_top(n);

	BN_CTX_start(ctx);
	A = BN_CTX_get(ctx);
	B = BN_CTX_get(ctx);
	X = BN_CTX_get(ctx);
	D = BN_CTX_get(ctx);
	M = BN_CTX_get(ctx);
	Y = BN_CTX_get(ctx);
	T = BN_CTX_get(ctx);
	if (T == NULL) goto err;

	if (in == NULL)
		R=BN_new();
	else
		R=in;
	if (R == NULL) goto err;

	BN_one(X);
	BN_zero(Y);
	if (BN_copy(B,a) == NULL) goto err;
	if (BN_copy(A,n) == NULL) goto err;
	A->neg = 0;

	if (B->neg || (BN_ucmp(B, A) >= 0))
		{
		/* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,
	 	 * BN_div_no_branch will be called eventually.
	 	 */
		pB = &local_B;
		BN_with_flags(pB, B, BN_FLG_CONSTTIME);	
		if (!BN_nnmod(B, pB, A, ctx)) goto err;
		}
	sign = -1;
	/* From  B = a mod |n|,  A = |n|  it follows that
	 *
	 *      0 <= B < A,
	 *     -sign*X*a  ==  B   (mod |n|),
	 *      sign*Y*a  ==  A   (mod |n|).
	 */

	while (!BN_is_zero(B))
		{
		BIGNUM *tmp;
		
		/*
		 *      0 < B < A,
		 * (*) -sign*X*a  ==  B   (mod |n|),
		 *      sign*Y*a  ==  A   (mod |n|)
		 */

		/* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,
	 	 * BN_div_no_branch will be called eventually.
	 	 */
		pA = &local_A;
		BN_with_flags(pA, A, BN_FLG_CONSTTIME);	
		
		/* (D, M) := (A/B, A%B) ... */		
		if (!BN_div(D,M,pA,B,ctx)) goto err;
		
		/* Now
		 *      A = D*B + M;
		 * thus we have
		 * (**)  sign*Y*a  ==  D*B + M   (mod |n|).
		 */
		
		tmp=A; /* keep the BIGNUM object, the value does not matter */
		
		/* (A, B) := (B, A mod B) ... */
		A=B;
		B=M;
		/* ... so we have  0 <= B < A  again */
		
		/* Since the former  M  is now  B  and the former  B  is now  A,
		 * (**) translates into
		 *       sign*Y*a  ==  D*A + B    (mod |n|),
		 * i.e.
		 *       sign*Y*a - D*A  ==  B    (mod |n|).
		 * Similarly, (*) translates into
		 *      -sign*X*a  ==  A          (mod |n|).
		 *
		 * Thus,
		 *   sign*Y*a + D*sign*X*a  ==  B  (mod |n|),
		 * i.e.
		 *        sign*(Y + D*X)*a  ==  B  (mod |n|).
		 *
		 * So if we set  (X, Y, sign) := (Y + D*X, X, -sign),  we arrive back at
		 *      -sign*X*a  ==  B   (mod |n|),
		 *       sign*Y*a  ==  A   (mod |n|).
		 * Note that  X  and  Y  stay non-negative all the time.
		 */
			
		if (!BN_mul(tmp,D,X,ctx)) goto err;
		if (!BN_add(tmp,tmp,Y)) goto err;

		M=Y; /* keep the BIGNUM object, the value does not matter */
		Y=X;
		X=tmp;
		sign = -sign;
		}
		
	/*
	 * The while loop (Euclid's algorithm) ends when
	 *      A == gcd(a,n);
	 * we have
	 *       sign*Y*a  ==  A  (mod |n|),
	 * where  Y  is non-negative.
	 */

	if (sign < 0)
		{
		if (!BN_sub(Y,n,Y)) goto err;
		}
	/* Now  Y*a  ==  A  (mod |n|).  */

	if (BN_is_one(A))
		{
		/* Y*a == 1  (mod |n|) */
		if (!Y->neg && BN_ucmp(Y,n) < 0)
			{
			if (!BN_copy(R,Y)) goto err;
			}
		else
			{
			if (!BN_nnmod(R,Y,n,ctx)) goto err;
			}
		}
	else
		{
		BNerr(BN_F_BN_MOD_INVERSE_NO_BRANCH,BN_R_NO_INVERSE);
		goto err;
		}
	ret=R;
err:
	if ((ret == NULL) && (in == NULL)) BN_free(R);
	BN_CTX_end(ctx);
	bn_check_top(ret);
	return(ret);
	}
Exemple #28
0
int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) {
  int ret = 0;
  int top, al, bl;
  BIGNUM *rr;
  int i;
  BIGNUM *t = NULL;
  int j = 0, k;

  al = a->top;
  bl = b->top;

  if ((al == 0) || (bl == 0)) {
    BN_zero(r);
    return 1;
  }
  top = al + bl;

  BN_CTX_start(ctx);
  if ((r == a) || (r == b)) {
    if ((rr = BN_CTX_get(ctx)) == NULL) {
      goto err;
    }
  } else {
    rr = r;
  }
  rr->neg = a->neg ^ b->neg;

  i = al - bl;
  if (i == 0) {
    if (al == 8) {
      if (!bn_wexpand(rr, 16)) {
        goto err;
      }
      rr->top = 16;
      bn_mul_comba8(rr->d, a->d, b->d);
      goto end;
    }
  }

  static const int kMulNormalSize = 16;
  if (al >= kMulNormalSize && bl >= kMulNormalSize) {
    if (i >= -1 && i <= 1) {
      /* Find out the power of two lower or equal
         to the longest of the two numbers */
      if (i >= 0) {
        j = BN_num_bits_word((BN_ULONG)al);
      }
      if (i == -1) {
        j = BN_num_bits_word((BN_ULONG)bl);
      }
      j = 1 << (j - 1);
      assert(j <= al || j <= bl);
      k = j + j;
      t = BN_CTX_get(ctx);
      if (t == NULL) {
        goto err;
      }
      if (al > j || bl > j) {
        if (!bn_wexpand(t, k * 4)) {
          goto err;
        }
        if (!bn_wexpand(rr, k * 4)) {
          goto err;
        }
        bn_mul_part_recursive(rr->d, a->d, b->d, j, al - j, bl - j, t->d);
      } else {
        /* al <= j || bl <= j */
        if (!bn_wexpand(t, k * 2)) {
          goto err;
        }
        if (!bn_wexpand(rr, k * 2)) {
          goto err;
        }
        bn_mul_recursive(rr->d, a->d, b->d, j, al - j, bl - j, t->d);
      }
      rr->top = top;
      goto end;
    }
  }

  if (!bn_wexpand(rr, top)) {
    goto err;
  }
  rr->top = top;
  bn_mul_normal(rr->d, a->d, al, b->d, bl);

end:
  bn_correct_top(rr);
  if (r != rr && !BN_copy(r, rr)) {
    goto err;
  }
  ret = 1;

err:
  BN_CTX_end(ctx);
  return ret;
}