Example #1
0
static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
	{
	BIGNUM *n;
	BN_ULONG *ap,*np,*rp,n0,v,*nrp;
	int al,nl,max,i,x,ri;

	n= &(mont->N);
	/* mont->ri is the size of mont->N in bits (rounded up
	   to the word size) */
	al=ri=mont->ri/BN_BITS2;

	nl=n->top;
	if ((al == 0) || (nl == 0)) { ret->top=0; return(1); }

	max=(nl+al+1); /* allow for overflow (no?) XXX */
	if (bn_wexpand(r,max) == NULL) return(0);

	r->neg^=n->neg;
	np=n->d;
	rp=r->d;
	nrp= &(r->d[nl]);

	/* clear the top words of T */
#if 1
	for (i=r->top; i<max; i++) /* memset? XXX */
		r->d[i]=0;
#else
	memset(&(r->d[r->top]),0,(max-r->top)*sizeof(BN_ULONG)); 
#endif

	r->top=max;
	n0=mont->n0[0];

#ifdef BN_COUNT
	fprintf(stderr,"word BN_from_montgomery_word %d * %d\n",nl,nl);
#endif
	for (i=0; i<nl; i++)
		{
#ifdef __TANDEM
                {
                   long long t1;
                   long long t2;
                   long long t3;
                   t1 = rp[0] * (n0 & 0177777);
                   t2 = 037777600000l;
                   t2 = n0 & t2;
                   t3 = rp[0] & 0177777;
                   t2 = (t3 * t2) & BN_MASK2;
                   t1 = t1 + t2;
                   v=bn_mul_add_words(rp,np,nl,(BN_ULONG) t1);
                }
#else
		v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2);
#endif
		nrp++;
		rp++;
		if (((nrp[-1]+=v)&BN_MASK2) >= v)
			continue;
		else
			{
			if (((++nrp[0])&BN_MASK2) != 0) continue;
			if (((++nrp[1])&BN_MASK2) != 0) continue;
			for (x=2; (((++nrp[x])&BN_MASK2) == 0); x++) ;
			}
		}
	bn_correct_top(r);

	/* mont->ri will be a multiple of the word size and below code
	 * is kind of BN_rshift(ret,r,mont->ri) equivalent */
	if (r->top <= ri)
		{
		ret->top=0;
		return(1);
		}
	al=r->top-ri;

#define BRANCH_FREE 1
#if BRANCH_FREE
	if (bn_wexpand(ret,ri) == NULL) return(0);
	x=0-(((al-ri)>>(sizeof(al)*8-1))&1);
	ret->top=x=(ri&~x)|(al&x);	/* min(ri,al) */
	ret->neg=r->neg;

	rp=ret->d;
	ap=&(r->d[ri]);

	{
	size_t m1,m2;

	v=bn_sub_words(rp,ap,np,ri);
	/* this ----------------^^ works even in al<ri case
	 * thanks to zealous zeroing of top of the vector in the
	 * beginning. */

	/* if (al==ri && !v) || al>ri) nrp=rp; else nrp=ap; */
	/* in other words if subtraction result is real, then
	 * trick unconditional memcpy below to perform in-place
	 * "refresh" instead of actual copy. */
	m1=0-(size_t)(((al-ri)>>(sizeof(al)*8-1))&1);	/* al<ri */
	m2=0-(size_t)(((ri-al)>>(sizeof(al)*8-1))&1);	/* al>ri */
	m1|=m2;			/* (al!=ri) */
	m1|=(0-(size_t)v);	/* (al!=ri || v) */
	m1&=~m2;		/* (al!=ri || v) && !al>ri */
	nrp=(BN_ULONG *)(((PTR_SIZE_INT)rp&~m1)|((PTR_SIZE_INT)ap&m1));
	}

	/* 'i<ri' is chosen to eliminate dependency on input data, even
	 * though it results in redundant copy in al<ri case. */
	for (i=0,ri-=4; i<ri; i+=4)
		{
		BN_ULONG t1,t2,t3,t4;
		
		t1=nrp[i+0];
		t2=nrp[i+1];
		t3=nrp[i+2];	ap[i+0]=0;
		t4=nrp[i+3];	ap[i+1]=0;
		rp[i+0]=t1;	ap[i+2]=0;
		rp[i+1]=t2;	ap[i+3]=0;
		rp[i+2]=t3;
		rp[i+3]=t4;
		}
	for (ri+=4; i<ri; i++)
		rp[i]=nrp[i], ap[i]=0;
	bn_correct_top(r);
	bn_correct_top(ret);
#else
	if (bn_wexpand(ret,al) == NULL) return(0);
	ret->top=al;
	ret->neg=r->neg;

	rp=ret->d;
	ap=&(r->d[ri]);
	al-=4;
	for (i=0; i<al; i+=4)
		{
		BN_ULONG t1,t2,t3,t4;
		
		t1=ap[i+0];
		t2=ap[i+1];
		t3=ap[i+2];
		t4=ap[i+3];
		rp[i+0]=t1;
		rp[i+1]=t2;
		rp[i+2]=t3;
		rp[i+3]=t4;
		}
	al+=4;
	for (; i<al; i++)
		rp[i]=ap[i];

	if (BN_ucmp(ret, &(mont->N)) >= 0)
		{
		if (!BN_usub(ret,ret,&(mont->N))) return(0);
		}
#endif
	bn_check_top(ret);

	return(1);
	}
Example #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 (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 {
        /* 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);
}
Example #3
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;
        local_B.flags = 0;
        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;
        local_A.flags = 0;
        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);
}
static int ecdsa_do_verify(const unsigned char *dgst, int dgst_len,
		const ECDSA_SIG *sig, EC_KEY *eckey)
{
	int ret = -1, i;
	BN_CTX   *ctx;
	BIGNUM   *order, *u1, *u2, *m, *X;
	EC_POINT *point = NULL;
	const EC_GROUP *group;
	const EC_POINT *pub_key;

	/* check input values */
	if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL ||
	    (pub_key = EC_KEY_get0_public_key(eckey)) == NULL || sig == NULL)
	{
		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_MISSING_PARAMETERS);
		return -1;
	}

	ctx = BN_CTX_new();
	if (!ctx)
	{
		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE);
		return -1;
	}
	BN_CTX_start(ctx);
	order = BN_CTX_get(ctx);	
	u1    = BN_CTX_get(ctx);
	u2    = BN_CTX_get(ctx);
	m     = BN_CTX_get(ctx);
	X     = BN_CTX_get(ctx);
	if (!X)
	{
		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
		goto err;
	}
	
	if (!EC_GROUP_get_order(group, order, ctx))
	{
		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
		goto err;
	}

	if (BN_is_zero(sig->r)          || BN_is_negative(sig->r) || 
	    BN_ucmp(sig->r, order) >= 0 || BN_is_zero(sig->s)  ||
	    BN_is_negative(sig->s)      || BN_ucmp(sig->s, order) >= 0)
	{
		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_BAD_SIGNATURE);
		ret = 0;	/* signature is invalid */
		goto err;
	}
	/* calculate tmp1 = inv(S) mod order */
	if (!BN_mod_inverse(u2, sig->s, order, ctx))
	{
		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
		goto err;
	}
	/* digest -> m */
	i = BN_num_bits(order);
	/* Need to truncate digest if it is too long: first truncate whole
	 * bytes.
	 */
	if (8 * dgst_len > i)
		dgst_len = (i + 7)/8;
	if (!BN_bin2bn(dgst, dgst_len, m))
	{
		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
		goto err;
	}
	/* If still too long truncate remaining bits with a shift */
	if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7)))
	{
		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
		goto err;
	}
	/* u1 = m * tmp mod order */
	if (!BN_mod_mul(u1, m, u2, order, ctx))
	{
		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
		goto err;
	}
	/* u2 = r * w mod q */
	if (!BN_mod_mul(u2, sig->r, u2, order, ctx))
	{
		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
		goto err;
	}

	if ((point = EC_POINT_new(group)) == NULL)
	{
		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE);
		goto err;
	}
	if (!EC_POINT_mul(group, point, u1, pub_key, u2, ctx))
	{
		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
		goto err;
	}
	if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field)
	{
		if (!EC_POINT_get_affine_coordinates_GFp(group,
			point, X, NULL, ctx))
		{
			ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
			goto err;
		}
	}
#ifndef OPENSSL_NO_EC2M
	else /* NID_X9_62_characteristic_two_field */
	{
		if (!EC_POINT_get_affine_coordinates_GF2m(group,
			point, X, NULL, ctx))
		{
			ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
			goto err;
		}
	}
#endif	
	if (!BN_nnmod(u1, X, order, ctx))
	{
		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
		goto err;
	}
	/*  if the signature is correct u1 is equal to sig->r */
	ret = (BN_ucmp(u1, sig->r) == 0);
err:
	BN_CTX_end(ctx);
	BN_CTX_free(ctx);
	if (point)
		EC_POINT_free(point);
	return ret;
}
Example #5
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;
	}
Example #6
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);
    res = (dv == NULL) ? BN_CTX_get(ctx) : dv;
    tmp = BN_CTX_get(ctx);
    snum = BN_CTX_get(ctx);
    sdiv = BN_CTX_get(ctx);
    if (sdiv == 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;
    wnum.flags = BN_FLG_STATIC_DATA;
    /*
     * 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' */
    if (!bn_wexpand(res, (loop + 1)))
        goto err;
    res->neg = (num->neg ^ divisor->neg);
    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--;
    }

    /* Increase the resp pointer so that we never create an invalid pointer. */
    resp++;

    /*
     * 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--) {
        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--;
        *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;
}
Example #7
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;
}
int compute_password_element (pwd_session_t *sess, uint16_t grp_num,
			      char const *password, int password_len,
			      char const *id_server, int id_server_len,
			      char const *id_peer, int id_peer_len,
			      uint32_t *token)
{
	BIGNUM *x_candidate = NULL, *rnd = NULL, *cofactor = NULL;
	HMAC_CTX ctx;
	uint8_t pwe_digest[SHA256_DIGEST_LENGTH], *prfbuf = NULL, ctr;
	int nid, is_odd, primebitlen, primebytelen, ret = 0;

	switch (grp_num) { /* from IANA registry for IKE D-H groups */
	case 19:
		nid = NID_X9_62_prime256v1;
		break;

	case 20:
		nid = NID_secp384r1;
		break;

	case 21:
		nid = NID_secp521r1;
		break;

	case 25:
		nid = NID_X9_62_prime192v1;
		break;

	case 26:
		nid = NID_secp224r1;
		break;

	default:
		DEBUG("unknown group %d", grp_num);
		goto fail;
	}

	sess->pwe = NULL;
	sess->order = NULL;
	sess->prime = NULL;

	if ((sess->group = EC_GROUP_new_by_curve_name(nid)) == NULL) {
		DEBUG("unable to create EC_GROUP");
		goto fail;
	}

	if (((rnd = BN_new()) == NULL) ||
	    ((cofactor = BN_new()) == NULL) ||
	    ((sess->pwe = EC_POINT_new(sess->group)) == NULL) ||
	    ((sess->order = BN_new()) == NULL) ||
	    ((sess->prime = BN_new()) == NULL) ||
	    ((x_candidate = BN_new()) == NULL)) {
		DEBUG("unable to create bignums");
		goto fail;
	}

	if (!EC_GROUP_get_curve_GFp(sess->group, sess->prime, NULL, NULL, NULL)) {
		DEBUG("unable to get prime for GFp curve");
		goto fail;
	}

	if (!EC_GROUP_get_order(sess->group, sess->order, NULL)) {
		DEBUG("unable to get order for curve");
		goto fail;
	}

	if (!EC_GROUP_get_cofactor(sess->group, cofactor, NULL)) {
		DEBUG("unable to get cofactor for curve");
		goto fail;
	}

	primebitlen = BN_num_bits(sess->prime);
	primebytelen = BN_num_bytes(sess->prime);
	if ((prfbuf = talloc_zero_array(sess, uint8_t, primebytelen)) == NULL) {
		DEBUG("unable to alloc space for prf buffer");
		goto fail;
	}
	ctr = 0;
	while (1) {
		if (ctr > 10) {
			DEBUG("unable to find random point on curve for group %d, something's fishy", grp_num);
			goto fail;
		}
		ctr++;

		/*
		 * compute counter-mode password value and stretch to prime
		 *    pwd-seed = H(token | peer-id | server-id | password |
		 *		   counter)
		 */
		H_Init(&ctx);
		H_Update(&ctx, (uint8_t *)token, sizeof(*token));
		H_Update(&ctx, (uint8_t const *)id_peer, id_peer_len);
		H_Update(&ctx, (uint8_t const *)id_server, id_server_len);
		H_Update(&ctx, (uint8_t const *)password, password_len);
		H_Update(&ctx, (uint8_t *)&ctr, sizeof(ctr));
		H_Final(&ctx, pwe_digest);

		BN_bin2bn(pwe_digest, SHA256_DIGEST_LENGTH, rnd);
		eap_pwd_kdf(pwe_digest, SHA256_DIGEST_LENGTH, "EAP-pwd Hunting And Pecking",
			    strlen("EAP-pwd Hunting And Pecking"), prfbuf, primebitlen);

		BN_bin2bn(prfbuf, primebytelen, x_candidate);
		/*
		 * eap_pwd_kdf() returns a string of bits 0..primebitlen but
		 * BN_bin2bn will treat that string of bits as a big endian
		 * number. If the primebitlen is not an even multiple of 8
		 * then excessive bits-- those _after_ primebitlen-- so now
		 * we have to shift right the amount we masked off.
		 */
		if (primebitlen % 8) BN_rshift(x_candidate, x_candidate, (8 - (primebitlen % 8)));
		if (BN_ucmp(x_candidate, sess->prime) >= 0) continue;

		/*
		 * need to unambiguously identify the solution, if there is
		 * one...
		 */
		is_odd = BN_is_odd(rnd) ? 1 : 0;

		/*
		 * solve the quadratic equation, if it's not solvable then we
		 * don't have a point
		 */
		if (!EC_POINT_set_compressed_coordinates_GFp(sess->group, sess->pwe, x_candidate, is_odd, NULL)) {
			continue;
		}

		/*
		 * If there's a solution to the equation then the point must be
		 * on the curve so why check again explicitly? OpenSSL code
		 * says this is required by X9.62. We're not X9.62 but it can't
		 * hurt just to be sure.
		 */
		if (!EC_POINT_is_on_curve(sess->group, sess->pwe, NULL)) {
			DEBUG("EAP-pwd: point is not on curve");
			continue;
		}

		if (BN_cmp(cofactor, BN_value_one())) {
			/* make sure the point is not in a small sub-group */
			if (!EC_POINT_mul(sess->group, sess->pwe, NULL, sess->pwe,
				cofactor, NULL)) {
				DEBUG("EAP-pwd: cannot multiply generator by order");
				continue;
			}

			if (EC_POINT_is_at_infinity(sess->group, sess->pwe)) {
				DEBUG("EAP-pwd: point is at infinity");
				continue;
			}
		}
		/* if we got here then we have a new generator. */
		break;
	}

	sess->group_num = grp_num;
	if (0) {
		fail:		/* DON'T free sess, it's in handler->opaque */
		ret = -1;
	}

	/* cleanliness and order.... */
	BN_free(cofactor);
	BN_free(x_candidate);
	BN_free(rnd);
	talloc_free(prfbuf);

	return ret;
}
Example #9
0
int 
ec_GFp_simple_oct2point(const EC_GROUP * group, EC_POINT * point,
    const unsigned char *buf, size_t len, BN_CTX * ctx)
{
	point_conversion_form_t form;
	int y_bit;
	BN_CTX *new_ctx = NULL;
	BIGNUM *x, *y;
	size_t field_len, enc_len;
	int ret = 0;

	if (len == 0) {
		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
		return 0;
	}
	form = buf[0];
	y_bit = form & 1;
	form = form & ~1U;
	if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED)
	    && (form != POINT_CONVERSION_UNCOMPRESSED)
	    && (form != POINT_CONVERSION_HYBRID)) {
		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
		return 0;
	}
	if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit) {
		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
		return 0;
	}
	if (form == 0) {
		if (len != 1) {
			ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
			return 0;
		}
		return EC_POINT_set_to_infinity(group, point);
	}
	field_len = BN_num_bytes(&group->field);
	enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len;

	if (len != enc_len) {
		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
		return 0;
	}
	if (ctx == NULL) {
		ctx = new_ctx = BN_CTX_new();
		if (ctx == NULL)
			return 0;
	}
	BN_CTX_start(ctx);
	x = BN_CTX_get(ctx);
	y = BN_CTX_get(ctx);
	if (y == NULL)
		goto err;

	if (!BN_bin2bn(buf + 1, field_len, x))
		goto err;
	if (BN_ucmp(x, &group->field) >= 0) {
		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
		goto err;
	}
	if (form == POINT_CONVERSION_COMPRESSED) {
		if (!EC_POINT_set_compressed_coordinates_GFp(group, point, x, y_bit, ctx))
			goto err;
	} else {
		if (!BN_bin2bn(buf + 1 + field_len, field_len, y))
			goto err;
		if (BN_ucmp(y, &group->field) >= 0) {
			ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
			goto err;
		}
		if (form == POINT_CONVERSION_HYBRID) {
			if (y_bit != BN_is_odd(y)) {
				ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
				goto err;
			}
		}
		if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx))
			goto err;
	}

	if (!EC_POINT_is_on_curve(group, point, ctx)) {	/* test required by
							 * X9.62 */
		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE);
		goto err;
	}
	ret = 1;

err:
	BN_CTX_end(ctx);
	if (new_ctx != NULL)
		BN_CTX_free(new_ctx);
	return ret;
}
Example #10
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);
}
Example #11
0
static int dsa_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig,
		  DSA *dsa)
	{
	BN_CTX *ctx;
	BIGNUM u1,u2,t1;
	BN_MONT_CTX *mont=NULL;
	int ret = -1;

	if ((ctx=BN_CTX_new()) == NULL) goto err;
	BN_init(&u1);
	BN_init(&u2);
	BN_init(&t1);

	/* Calculate W = inv(S) mod Q
	 * save W in u2 */
	if ((BN_mod_inverse(&u2,sig->s,dsa->q,ctx)) == NULL) goto err;

	/* save M in u1 */
	if (BN_bin2bn(dgst,dgst_len,&u1) == NULL) goto err;

	/* u1 = M * w mod q */
	if (!BN_mod_mul(&u1,&u1,&u2,dsa->q,ctx)) goto err;

	/* u2 = r * w mod q */
	if (!BN_mod_mul(&u2,sig->r,&u2,dsa->q,ctx)) goto err;

	if ((dsa->method_mont_p == NULL) && (dsa->flags & DSA_FLAG_CACHE_MONT_P))
		{
		if ((dsa->method_mont_p=(char *)BN_MONT_CTX_new()) != NULL)
			if (!BN_MONT_CTX_set((BN_MONT_CTX *)dsa->method_mont_p,
				dsa->p,ctx)) goto err;
		}
	mont=(BN_MONT_CTX *)dsa->method_mont_p;

#if 0
	{
	BIGNUM t2;

	BN_init(&t2);
	/* v = ( g^u1 * y^u2 mod p ) mod q */
	/* let t1 = g ^ u1 mod p */
	if (!BN_mod_exp_mont(&t1,dsa->g,&u1,dsa->p,ctx,mont)) goto err;
	/* let t2 = y ^ u2 mod p */
	if (!BN_mod_exp_mont(&t2,dsa->pub_key,&u2,dsa->p,ctx,mont)) goto err;
	/* let u1 = t1 * t2 mod p */
	if (!BN_mod_mul(&u1,&t1,&t2,dsa->p,ctx)) goto err_bn;
	BN_free(&t2);
	}
	/* let u1 = u1 mod q */
	if (!BN_mod(&u1,&u1,dsa->q,ctx)) goto err;
#else
	{
	if (!dsa->meth->dsa_mod_exp(dsa, &t1,dsa->g,&u1,dsa->pub_key,&u2,
						dsa->p,ctx,mont)) goto err;
	/* BN_copy(&u1,&t1); */
	/* let u1 = u1 mod q */
	if (!BN_mod(&u1,&t1,dsa->q,ctx)) goto err;
	}
#endif
	/* V is now in u1.  If the signature is correct, it will be
	 * equal to R. */
	ret=(BN_ucmp(&u1, sig->r) == 0);

	err:
	if (ret != 1) DSAerr(DSA_F_DSA_DO_VERIFY,ERR_R_BN_LIB);
	if (ctx != NULL) BN_CTX_free(ctx);
	BN_free(&u1);
	BN_free(&u2);
	BN_free(&t1);
	return(ret);
	}
Example #12
0
// unsigned char *rgbHashData, 哈希数值
// unsigned char *rgbKeyPb, SM2公钥数据,Px Py 不含标志位 point_conversion_form_t
// unsigned char *rs 待验证的签名数据
unsigned char eccVerifySignature(unsigned char *rgbHashData, unsigned char *rgbKeyPb, unsigned char *rs)
{
	int ret = SM2_VERIFY_INNER_ERROR;
	EC_POINT *point = NULL;
	BN_CTX *ctx = NULL;
	BIGNUM *order = NULL;
	BIGNUM *e = NULL;
	BIGNUM *t = NULL;
	int i;

	EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_sm2p256v1);

	BIGNUM *x = BN_new();;
	BIGNUM *y = BN_new();;
	if (!BN_bin2bn(rgbKeyPb, 32, x)) {
		goto err;
	}
	if (!BN_bin2bn(rgbKeyPb + 32, 32, y)) {
		goto err;
	}
	if (!EC_KEY_set_public_key_affine_coordinates(ec_key, x, y)) {
		goto err;
	}
	const EC_POINT *pub_key = EC_KEY_get0_public_key(ec_key);

	BIGNUM *r= BN_new(), *s = BN_new();
	BN_bin2bn(rs, 32, r);
	BN_bin2bn(rs + 32, 32, s);

	//// 相当于
	//EC_KEY *ret = EC_KEY_new();
	EC_GROUP *ec_group = EC_GROUP_new_by_curve_name(NID_sm2p256v1);

	ctx = BN_CTX_new();
	order = BN_new();
	e = BN_new();
	t = BN_new();

	if (!ctx || !order || !e || !t) {
		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE);
		goto err;
	}
	if (!EC_GROUP_get_order(ec_group, order, ctx)) {
		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
		goto err;
	}

	/* check r, s in [1, n-1] and r + s != 0 (mod n) */ 
	if (BN_is_zero(r) ||
		BN_is_negative(r) ||
		BN_ucmp(r, order) >= 0 || 
		BN_is_zero(s) ||
		BN_is_negative(s) || 
		BN_ucmp(s, order) >= 0) {

			ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_BAD_SIGNATURE);
			ret = 0;
			goto err;
	}

	/* check t = r + s != 0 */
	if (!BN_mod_add(t, r, s, order, ctx)) {
		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
		goto err;
	}
	if (BN_is_zero(t)) {
		ret = 0;
		goto err;
	}

	/* convert digest to e */
	i = BN_num_bits(order);
#if 0
	if (8 * dgstlen > i) {
		dgstlen = (i + 7)/8;
	}
#endif
	if (!BN_bin2bn(rgbHashData, 32, e)) {
		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
		goto err;
	}
#if 0
	if ((8 * dgstlen > i) && !BN_rshift(e, e, 8 - (i & 0x7))) {
		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
		goto err;
	}
#endif

	/* compute (x, y) = sG + tP, P is pub_key */
	if (!(point = EC_POINT_new(ec_group))) {
		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE);
		goto err;
	}
	if (!EC_POINT_mul(ec_group, point, s, pub_key, t, ctx)) {
		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
		goto err;
	}
	if (EC_METHOD_get_field_type(EC_GROUP_method_of(ec_group)) == NID_X9_62_prime_field) {
		if (!EC_POINT_get_affine_coordinates_GFp(ec_group, point, t, NULL, ctx)) {
			ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
			goto err;
		}
	} else /* NID_X9_62_characteristic_two_field */ { 
		if (!EC_POINT_get_affine_coordinates_GF2m(ec_group, point, t, NULL, ctx)) {
			ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
			goto err;
		}
	}
	if (!BN_nnmod(t, t, order, ctx)) {
		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
		goto err;
	}

	/* check (sG + tP).x + e  == sig.r */
	if (!BN_mod_add(t, t, e, order, ctx)) {
		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
		goto err;
	}
	if (BN_ucmp(t, r) == 0) {
		ret = SM2_VERIFY_SUCCESS;
	} else {
		ret = SM2_VERIFY_FAILED;
	}

err:
	if (point) EC_POINT_free(point);
	if (order) BN_free(order);
	if (e) BN_free(e);
	if (t) BN_free(t);
	if (ctx) BN_CTX_free(ctx);
	return 0;
}