EC_KEY *EC_KEY_copy(EC_KEY *dest, EC_KEY *src) { if (dest == NULL || src == NULL) { ECerr(EC_F_EC_KEY_COPY, ERR_R_PASSED_NULL_PARAMETER); return NULL; } if (src->meth != dest->meth) { if (dest->meth->finish != NULL) dest->meth->finish(dest); #ifndef OPENSSL_NO_ENGINE if (dest->engine != NULL && ENGINE_finish(dest->engine) == 0) return 0; dest->engine = NULL; #endif } /* copy the parameters */ if (src->group != NULL) { const EC_METHOD *meth = EC_GROUP_method_of(src->group); /* clear the old group */ EC_GROUP_free(dest->group); dest->group = EC_GROUP_new(meth); if (dest->group == NULL) return NULL; if (!EC_GROUP_copy(dest->group, src->group)) return NULL; } /* copy the public key */ if (src->pub_key != NULL && src->group != NULL) { EC_POINT_free(dest->pub_key); dest->pub_key = EC_POINT_new(src->group); if (dest->pub_key == NULL) return NULL; if (!EC_POINT_copy(dest->pub_key, src->pub_key)) return NULL; } /* copy the private key */ if (src->priv_key != NULL) { if (dest->priv_key == NULL) { dest->priv_key = BN_new(); if (dest->priv_key == NULL) return NULL; } if (!BN_copy(dest->priv_key, src->priv_key)) return NULL; } /* copy the rest */ dest->enc_flag = src->enc_flag; dest->conv_form = src->conv_form; dest->version = src->version; dest->flags = src->flags; if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_EC_KEY, &dest->ex_data, &src->ex_data)) return NULL; if (src->meth != dest->meth) { #ifndef OPENSSL_NO_ENGINE if (src->engine != NULL && ENGINE_init(src->engine) == 0) return NULL; dest->engine = src->engine; #endif dest->meth = src->meth; } if (src->meth->copy != NULL && src->meth->copy(dest, src) == 0) return NULL; return dest; }
int test_kron(BIO *bp, BN_CTX *ctx) { BIGNUM *a,*b,*r,*t; int i; int legendre, kronecker; int ret = 0; a = BN_new(); b = BN_new(); r = BN_new(); t = BN_new(); if (a == NULL || b == NULL || r == NULL || t == NULL) goto err; /* We test BN_kronecker(a, b, ctx) just for b odd (Jacobi symbol). * In this case we know that if b is prime, then BN_kronecker(a, b, ctx) * is congruent to $a^{(b-1)/2}$, modulo $b$ (Legendre symbol). * So we generate a random prime b and compare these values * for a number of random a's. (That is, we run the Solovay-Strassen * primality test to confirm that b is prime, except that we * don't want to test whether b is prime but whether BN_kronecker * works.) */ if (!BN_generate_prime(b, 512, 0, NULL, NULL, genprime_cb, NULL)) goto err; b->neg = rand_neg(); putc('\n', stderr); for (i = 0; i < num0; i++) { if (!BN_bntest_rand(a, 512, 0, 0)) goto err; a->neg = rand_neg(); /* t := (|b|-1)/2 (note that b is odd) */ if (!BN_copy(t, b)) goto err; t->neg = 0; if (!BN_sub_word(t, 1)) goto err; if (!BN_rshift1(t, t)) goto err; /* r := a^t mod b */ b->neg=0; if (!BN_mod_exp_recp(r, a, t, b, ctx)) goto err; b->neg=1; if (BN_is_word(r, 1)) legendre = 1; else if (BN_is_zero(r)) legendre = 0; else { if (!BN_add_word(r, 1)) goto err; if (0 != BN_ucmp(r, b)) { fprintf(stderr, "Legendre symbol computation failed\n"); goto err; } legendre = -1; } kronecker = BN_kronecker(a, b, ctx); if (kronecker < -1) goto err; /* we actually need BN_kronecker(a, |b|) */ if (a->neg && b->neg) kronecker = -kronecker; if (legendre != kronecker) { fprintf(stderr, "legendre != kronecker; a = "); BN_print_fp(stderr, a); fprintf(stderr, ", b = "); BN_print_fp(stderr, b); fprintf(stderr, "\n"); goto err; } putc('.', stderr); fflush(stderr); } putc('\n', stderr); fflush(stderr); ret = 1; err: if (a != NULL) BN_free(a); if (b != NULL) BN_free(b); if (r != NULL) BN_free(r); if (t != NULL) BN_free(t); return ret; }
/* I've just gone over this and it is now %20 faster on x86 - eay - 27 Jun 96 */ int BN_sqr(BIGNUM *r, BIGNUM *a, BN_CTX *ctx) { int max,al; int ret = 0; BIGNUM *tmp,*rr; #ifdef BN_COUNT printf("BN_sqr %d * %d\n",a->top,a->top); #endif bn_check_top(a); al=a->top; if (al <= 0) { r->top=0; return(1); } BN_CTX_start(ctx); rr=(a != r) ? r : BN_CTX_get(ctx); tmp=BN_CTX_get(ctx); if (tmp == NULL) goto err; max=(al+al); if (bn_wexpand(rr,max+1) == NULL) goto err; r->neg=0; if (al == 4) { #ifndef BN_SQR_COMBA BN_ULONG t[8]; bn_sqr_normal(rr->d,a->d,4,t); #else bn_sqr_comba4(rr->d,a->d); #endif } else if (al == 8) { #ifndef BN_SQR_COMBA BN_ULONG t[16]; bn_sqr_normal(rr->d,a->d,8,t); #else bn_sqr_comba8(rr->d,a->d); #endif } else { #if defined(BN_RECURSION) if (al < BN_SQR_RECURSIVE_SIZE_NORMAL) { BN_ULONG t[BN_SQR_RECURSIVE_SIZE_NORMAL*2]; bn_sqr_normal(rr->d,a->d,al,t); } else { int j,k; j=BN_num_bits_word((BN_ULONG)al); j=1<<(j-1); k=j+j; if (al == j) { if (bn_wexpand(a,k*2) == NULL) goto err; if (bn_wexpand(tmp,k*2) == NULL) goto err; bn_sqr_recursive(rr->d,a->d,al,tmp->d); } else { if (bn_wexpand(tmp,max) == NULL) goto err; bn_sqr_normal(rr->d,a->d,al,tmp->d); } } #else if (bn_wexpand(tmp,max) == NULL) goto err; bn_sqr_normal(rr->d,a->d,al,tmp->d); #endif } rr->top=max; if ((max > 0) && (rr->d[max-1] == 0)) rr->top--; if (rr != r) BN_copy(r,rr); ret = 1; err: BN_CTX_end(ctx); return(ret); }
// Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields // recid selects which key is recovered // if check is non-zero, 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; }
BigNumber BigNumber::operator=(const BigNumber &bn) { BN_copy(m_bn, bn.m_bn); return *this; }
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)) 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 returns i, or -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); }
static bool blkdb_connect(struct blkdb *db, struct blkinfo *bi, struct blkdb_reorg *reorg_info) { memset(reorg_info, 0, sizeof(*reorg_info)); if (blkdb_lookup(db, &bi->hash)) return false; bool rc = false; BIGNUM cur_work; BN_init(&cur_work); u256_from_compact(&cur_work, bi->hdr.nBits); bool best_chain = false; /* verify genesis block matches first record */ if (bp_hashtab_size(db->blocks) == 0) { if (!bu256_equal(&bi->hdr.sha256, &db->block0)) goto out; /* bi->prev = NULL; */ bi->height = 0; BN_copy(&bi->work, &cur_work); best_chain = true; } /* lookup and verify previous block */ else { struct blkinfo *prev = blkdb_lookup(db, &bi->hdr.hashPrevBlock); if (!prev) goto out; bi->prev = prev; bi->height = prev->height + 1; if (!BN_add(&bi->work, &cur_work, &prev->work)) goto out; if (BN_cmp(&bi->work, &db->best_chain->work) > 0) best_chain = true; } /* add to block map */ bp_hashtab_put(db->blocks, &bi->hash, bi); /* if new best chain found, update pointers */ if (best_chain) { struct blkinfo *old_best = db->best_chain; struct blkinfo *new_best = bi; reorg_info->old_best = old_best; /* likely case: new best chain has greater height */ if (!old_best) { while (new_best) { new_best = new_best->prev; reorg_info->conn++; } } else { while (new_best && (new_best->height > old_best->height)) { new_best = new_best->prev; reorg_info->conn++; } } /* unlikely case: old best chain has greater height */ while (old_best && new_best && (old_best->height > new_best->height)) { old_best = old_best->prev; reorg_info->disconn++; } /* height matches, but we are still walking parallel chains */ while (old_best && new_best && (old_best != new_best)) { new_best = new_best->prev; reorg_info->conn++; old_best = old_best->prev; reorg_info->disconn++; } /* reorg analyzed. update database's best-chain pointer */ db->best_chain = bi; } rc = true; out: BN_clear_free(&cur_work); return rc; }
int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx) { BN_CTX *new_ctx = NULL; BIGNUM *tmp, *tmp_Z; BIGNUM **prod_Z = NULL; size_t i; int ret = 0; if (num == 0) { return 1; } if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) { return 0; } } BN_CTX_start(ctx); tmp = BN_CTX_get(ctx); tmp_Z = BN_CTX_get(ctx); if (tmp == NULL || tmp_Z == NULL) { goto err; } prod_Z = OPENSSL_malloc(num * sizeof(prod_Z[0])); if (prod_Z == NULL) { goto err; } memset(prod_Z, 0, num * sizeof(prod_Z[0])); for (i = 0; i < num; i++) { prod_Z[i] = BN_new(); if (prod_Z[i] == NULL) { goto err; } } /* Set each prod_Z[i] to the product of points[0]->Z .. points[i]->Z, * skipping any zero-valued inputs (pretend that they're 1). */ if (!BN_is_zero(&points[0]->Z)) { if (!BN_copy(prod_Z[0], &points[0]->Z)) { goto err; } } else { if (group->meth->field_set_to_one != 0) { if (!group->meth->field_set_to_one(group, prod_Z[0], ctx)) { goto err; } } else { if (!BN_one(prod_Z[0])) { goto err; } } } for (i = 1; i < num; i++) { if (!BN_is_zero(&points[i]->Z)) { if (!group->meth->field_mul(group, prod_Z[i], prod_Z[i - 1], &points[i]->Z, ctx)) { goto err; } } else { if (!BN_copy(prod_Z[i], prod_Z[i - 1])) { goto err; } } } /* Now use a single explicit inversion to replace every * non-zero points[i]->Z by its inverse. */ if (!BN_mod_inverse(tmp, prod_Z[num - 1], &group->field, ctx)) { OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); goto err; } if (group->meth->field_encode != NULL) { /* In the Montgomery case, we just turned R*H (representing H) * into 1/(R*H), but we need R*(1/H) (representing 1/H); * i.e. we need to multiply by the Montgomery factor twice. */ if (!group->meth->field_encode(group, tmp, tmp, ctx) || !group->meth->field_encode(group, tmp, tmp, ctx)) { goto err; } } for (i = num - 1; i > 0; --i) { /* Loop invariant: tmp is the product of the inverses of * points[0]->Z .. points[i]->Z (zero-valued inputs skipped). */ if (BN_is_zero(&points[i]->Z)) { continue; } /* Set tmp_Z to the inverse of points[i]->Z (as product * of Z inverses 0 .. i, Z values 0 .. i - 1). */ if (!group->meth->field_mul(group, tmp_Z, prod_Z[i - 1], tmp, ctx) || /* Update tmp to satisfy the loop invariant for i - 1. */ !group->meth->field_mul(group, tmp, tmp, &points[i]->Z, ctx) || /* Replace points[i]->Z by its inverse. */ !BN_copy(&points[i]->Z, tmp_Z)) { goto err; } } /* Replace points[0]->Z by its inverse. */ if (!BN_is_zero(&points[0]->Z) && !BN_copy(&points[0]->Z, tmp)) { goto err; } /* Finally, fix up the X and Y coordinates for all points. */ for (i = 0; i < num; i++) { EC_POINT *p = points[i]; if (!BN_is_zero(&p->Z)) { /* turn (X, Y, 1/Z) into (X/Z^2, Y/Z^3, 1). */ if (!group->meth->field_sqr(group, tmp, &p->Z, ctx) || !group->meth->field_mul(group, &p->X, &p->X, tmp, ctx) || !group->meth->field_mul(group, tmp, tmp, &p->Z, ctx) || !group->meth->field_mul(group, &p->Y, &p->Y, tmp, ctx)) { goto err; } if (group->meth->field_set_to_one != NULL) { if (!group->meth->field_set_to_one(group, &p->Z, ctx)) { goto err; } } else { if (!BN_one(&p->Z)) { goto err; } } p->Z_is_one = 1; } } ret = 1; err: BN_CTX_end(ctx); BN_CTX_free(new_ctx); if (prod_Z != NULL) { for (i = 0; i < num; i++) { if (prod_Z[i] == NULL) { break; } BN_clear_free(prod_Z[i]); } OPENSSL_free(prod_Z); } return ret; }
int ec_GFp_simple_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { int ret = 0; BN_CTX *new_ctx = NULL; BIGNUM *tmp_a; /* p must be a prime > 3 */ if (BN_num_bits(p) <= 2 || !BN_is_odd(p)) { OPENSSL_PUT_ERROR(EC, EC_R_INVALID_FIELD); return 0; } if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) { return 0; } } BN_CTX_start(ctx); tmp_a = BN_CTX_get(ctx); if (tmp_a == NULL) { goto err; } /* group->field */ if (!BN_copy(&group->field, p)) { goto err; } BN_set_negative(&group->field, 0); /* group->a */ if (!BN_nnmod(tmp_a, a, p, ctx)) { goto err; } if (group->meth->field_encode) { if (!group->meth->field_encode(group, &group->a, tmp_a, ctx)) { goto err; } } else if (!BN_copy(&group->a, tmp_a)) { goto err; } /* group->b */ if (!BN_nnmod(&group->b, b, p, ctx)) { goto err; } if (group->meth->field_encode && !group->meth->field_encode(group, &group->b, &group->b, ctx)) { goto err; } /* group->a_is_minus3 */ if (!BN_add_word(tmp_a, 3)) { goto err; } group->a_is_minus3 = (0 == BN_cmp(tmp_a, &group->field)); ret = 1; err: BN_CTX_end(ctx); BN_CTX_free(new_ctx); return ret; }
int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) { if (BN_copy(order, EC_GROUP_get0_order(group)) == NULL) { return 0; } return 1; }
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 BN_from_montgomery(BIGNUM *ret, BIGNUM *a, BN_MONT_CTX *mont, BN_CTX *ctx) { int retn=0; BIGNUM *n,*r; BN_ULONG *ap,*np,*rp,n0,v,*nrp; int al,nl,max,i,x,ri; BN_CTX_start(ctx); if ((r = BN_CTX_get(ctx)) == NULL) goto err; if (!BN_copy(r,a)) goto err; n= &(mont->N); ap=a->d; /* 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)) { r->top=0; return(1); } max=(nl+al+1); /* allow for overflow (no?) XXX */ if (bn_wexpand(r,max) == NULL) goto err; if (bn_wexpand(ret,max) == NULL) goto err; r->neg=a->neg^n->neg; np=n->d; rp=r->d; nrp= &(r->d[nl]); /* clear the top words of T */ for (i=r->top; i<max; i++) /* memset? XXX */ r->d[i]=0; r->top=max; n0=mont->n0; for (i=0; i<nl; i++) { v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2); 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_fix_top(r); /* mont->ri will be a multiple of the word size */ ret->neg = r->neg; x=ri; rp=ret->d; ap= &(r->d[x]); if (r->top < x) al=0; else al=r->top-x; ret->top=al; 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) { BN_usub(ret,ret,&(mont->N)); } retn=1; err: BN_CTX_end(ctx); return(retn); }
int BN_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b, BN_CTX *ctx) { int top,al,bl; BIGNUM *rr; int ret = 0; #if defined(BN_MUL_COMBA) || defined(BN_RECURSION) int i; #endif #ifdef BN_COUNT printf("BN_mul %d * %d\n",a->top,b->top); #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 */ 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_fix_top(rr); if (r != rr) BN_copy(r,rr); ret=1; err: BN_CTX_end(ctx); return(ret); }
bigint& bigint::operator = ( const bigint& a ) { if( &a == this ) return *this; BN_copy( n, a.n ); return *this; }
int rsa_default_multi_prime_keygen(RSA *rsa, int bits, int num_primes, BIGNUM *e_value, BN_GENCB *cb) { BIGNUM *r0 = NULL, *r1 = NULL, *r2 = NULL, *r3 = NULL, *tmp; BIGNUM local_r0, local_d, local_p; BIGNUM *pr0, *d, *p; int prime_bits, ok = -1, n = 0, i, j; BN_CTX *ctx = NULL; STACK_OF(RSA_additional_prime) *additional_primes = NULL; if (num_primes < 2) { ok = 0; /* we set our own err */ OPENSSL_PUT_ERROR(RSA, RSA_R_MUST_HAVE_AT_LEAST_TWO_PRIMES); goto err; } ctx = BN_CTX_new(); if (ctx == NULL) { goto err; } BN_CTX_start(ctx); r0 = BN_CTX_get(ctx); r1 = BN_CTX_get(ctx); r2 = BN_CTX_get(ctx); r3 = BN_CTX_get(ctx); if (r0 == NULL || r1 == NULL || r2 == NULL || r3 == NULL) { goto err; } if (num_primes > 2) { additional_primes = sk_RSA_additional_prime_new_null(); if (additional_primes == NULL) { goto err; } } for (i = 2; i < num_primes; i++) { RSA_additional_prime *ap = OPENSSL_malloc(sizeof(RSA_additional_prime)); if (ap == NULL) { goto err; } memset(ap, 0, sizeof(RSA_additional_prime)); ap->prime = BN_new(); ap->exp = BN_new(); ap->coeff = BN_new(); ap->r = BN_new(); if (ap->prime == NULL || ap->exp == NULL || ap->coeff == NULL || ap->r == NULL || !sk_RSA_additional_prime_push(additional_primes, ap)) { RSA_additional_prime_free(ap); goto err; } } /* We need the RSA components non-NULL */ if (!rsa->n && ((rsa->n = BN_new()) == NULL)) { goto err; } if (!rsa->d && ((rsa->d = BN_new()) == NULL)) { goto err; } if (!rsa->e && ((rsa->e = BN_new()) == NULL)) { goto err; } if (!rsa->p && ((rsa->p = BN_new()) == NULL)) { goto err; } if (!rsa->q && ((rsa->q = BN_new()) == NULL)) { goto err; } if (!rsa->dmp1 && ((rsa->dmp1 = BN_new()) == NULL)) { goto err; } if (!rsa->dmq1 && ((rsa->dmq1 = BN_new()) == NULL)) { goto err; } if (!rsa->iqmp && ((rsa->iqmp = BN_new()) == NULL)) { goto err; } if (!BN_copy(rsa->e, e_value)) { goto err; } /* generate p and q */ prime_bits = (bits + (num_primes - 1)) / num_primes; for (;;) { if (!BN_generate_prime_ex(rsa->p, prime_bits, 0, NULL, NULL, cb) || !BN_sub(r2, rsa->p, BN_value_one()) || !BN_gcd(r1, r2, rsa->e, ctx)) { goto err; } if (BN_is_one(r1)) { break; } if (!BN_GENCB_call(cb, 2, n++)) { goto err; } } if (!BN_GENCB_call(cb, 3, 0)) { goto err; } prime_bits = ((bits - prime_bits) + (num_primes - 2)) / (num_primes - 1); for (;;) { /* When generating ridiculously small keys, we can get stuck * continually regenerating the same prime values. Check for * this and bail if it happens 3 times. */ unsigned int degenerate = 0; do { if (!BN_generate_prime_ex(rsa->q, prime_bits, 0, NULL, NULL, cb)) { goto err; } } while ((BN_cmp(rsa->p, rsa->q) == 0) && (++degenerate < 3)); if (degenerate == 3) { ok = 0; /* we set our own err */ OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL); goto err; } if (!BN_sub(r2, rsa->q, BN_value_one()) || !BN_gcd(r1, r2, rsa->e, ctx)) { goto err; } if (BN_is_one(r1)) { break; } if (!BN_GENCB_call(cb, 2, n++)) { goto err; } } if (!BN_GENCB_call(cb, 3, 1) || !BN_mul(rsa->n, rsa->p, rsa->q, ctx)) { goto err; } for (i = 2; i < num_primes; i++) { RSA_additional_prime *ap = sk_RSA_additional_prime_value(additional_primes, i - 2); prime_bits = ((bits - BN_num_bits(rsa->n)) + (num_primes - (i + 1))) / (num_primes - i); for (;;) { if (!BN_generate_prime_ex(ap->prime, prime_bits, 0, NULL, NULL, cb)) { goto err; } if (BN_cmp(rsa->p, ap->prime) == 0 || BN_cmp(rsa->q, ap->prime) == 0) { continue; } for (j = 0; j < i - 2; j++) { if (BN_cmp(sk_RSA_additional_prime_value(additional_primes, j)->prime, ap->prime) == 0) { break; } } if (j != i - 2) { continue; } if (!BN_sub(r2, ap->prime, BN_value_one()) || !BN_gcd(r1, r2, rsa->e, ctx)) { goto err; } if (!BN_is_one(r1)) { continue; } if (i != num_primes - 1) { break; } /* For the last prime we'll check that it makes n large enough. In the * two prime case this isn't a problem because we generate primes with * the top two bits set and so the product is always of the expected * size. In the multi prime case, this doesn't follow. */ if (!BN_mul(r1, rsa->n, ap->prime, ctx)) { goto err; } if (BN_num_bits(r1) == (unsigned) bits) { break; } if (!BN_GENCB_call(cb, 2, n++)) { goto err; } } /* ap->r is is the product of all the primes prior to the current one * (including p and q). */ if (!BN_copy(ap->r, rsa->n)) { goto err; } if (i == num_primes - 1) { /* In the case of the last prime, we calculated n as |r1| in the loop * above. */ if (!BN_copy(rsa->n, r1)) { goto err; } } else if (!BN_mul(rsa->n, rsa->n, ap->prime, ctx)) { goto err; } if (!BN_GENCB_call(cb, 3, 1)) { goto err; } } if (BN_cmp(rsa->p, rsa->q) < 0) { tmp = rsa->p; rsa->p = rsa->q; rsa->q = tmp; } /* calculate d */ if (!BN_sub(r1, rsa->p, BN_value_one())) { goto err; /* p-1 */ } if (!BN_sub(r2, rsa->q, BN_value_one())) { goto err; /* q-1 */ } if (!BN_mul(r0, r1, r2, ctx)) { goto err; /* (p-1)(q-1) */ } for (i = 2; i < num_primes; i++) { RSA_additional_prime *ap = sk_RSA_additional_prime_value(additional_primes, i - 2); if (!BN_sub(r3, ap->prime, BN_value_one()) || !BN_mul(r0, r0, r3, ctx)) { goto err; } } pr0 = &local_r0; BN_with_flags(pr0, r0, BN_FLG_CONSTTIME); if (!BN_mod_inverse(rsa->d, rsa->e, pr0, ctx)) { goto err; /* d */ } /* set up d for correct BN_FLG_CONSTTIME flag */ d = &local_d; BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME); /* calculate d mod (p-1) */ if (!BN_mod(rsa->dmp1, d, r1, ctx)) { goto err; } /* calculate d mod (q-1) */ if (!BN_mod(rsa->dmq1, d, r2, ctx)) { goto err; } /* calculate inverse of q mod p */ p = &local_p; BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME); if (!BN_mod_inverse(rsa->iqmp, rsa->q, p, ctx)) { goto err; } for (i = 2; i < num_primes; i++) { RSA_additional_prime *ap = sk_RSA_additional_prime_value(additional_primes, i - 2); if (!BN_sub(ap->exp, ap->prime, BN_value_one()) || !BN_mod(ap->exp, rsa->d, ap->exp, ctx) || !BN_mod_inverse(ap->coeff, ap->r, ap->prime, ctx)) { goto err; } } ok = 1; rsa->additional_primes = additional_primes; additional_primes = NULL; err: if (ok == -1) { OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN); ok = 0; } if (ctx != NULL) { BN_CTX_end(ctx); BN_CTX_free(ctx); } sk_RSA_additional_prime_pop_free(additional_primes, RSA_additional_prime_free); return ok; }
int ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx) { int ret = 0; BIGNUM *a, *b, *order, *tmp_1, *tmp_2; const BIGNUM *p = &group->field; BN_CTX *new_ctx = NULL; if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) { OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); goto err; } } BN_CTX_start(ctx); a = BN_CTX_get(ctx); b = BN_CTX_get(ctx); tmp_1 = BN_CTX_get(ctx); tmp_2 = BN_CTX_get(ctx); order = BN_CTX_get(ctx); if (order == NULL) { goto err; } if (group->meth->field_decode) { if (!group->meth->field_decode(group, a, &group->a, ctx) || !group->meth->field_decode(group, b, &group->b, ctx)) { goto err; } } else { if (!BN_copy(a, &group->a) || !BN_copy(b, &group->b)) { goto err; } } /* check the discriminant: * y^2 = x^3 + a*x + b is an elliptic curve <=> 4*a^3 + 27*b^2 != 0 (mod p) * 0 =< a, b < p */ if (BN_is_zero(a)) { if (BN_is_zero(b)) { goto err; } } else if (!BN_is_zero(b)) { if (!BN_mod_sqr(tmp_1, a, p, ctx) || !BN_mod_mul(tmp_2, tmp_1, a, p, ctx) || !BN_lshift(tmp_1, tmp_2, 2)) { goto err; } /* tmp_1 = 4*a^3 */ if (!BN_mod_sqr(tmp_2, b, p, ctx) || !BN_mul_word(tmp_2, 27)) { goto err; } /* tmp_2 = 27*b^2 */ if (!BN_mod_add(a, tmp_1, tmp_2, p, ctx) || BN_is_zero(a)) { goto err; } } ret = 1; err: if (ctx != NULL) { BN_CTX_end(ctx); } BN_CTX_free(new_ctx); return ret; }
/* 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; bn_check_top(dv); bn_check_top(rm); bn_check_top(num); bn_check_top(divisor); if (BN_is_zero(divisor)) { BNerr(BN_F_BN_DIV,BN_R_DIV_BY_ZERO); return(0); } if (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) 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; 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; resp= &(res->d[loop-1]); /* space for temp */ if (!bn_wexpand(tmp,(div_n+1))) goto err; 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) 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); #ifdef BN_DEBUG_LEVITTE fprintf(stderr,"DEBUG: bn_div_words(0x%08X,0x%08X,0x%08\ X) -> 0x%08X\n", n0, n1, d0, q); #endif #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,ql,qh; q=bn_div_words(n0,n1,d0); #ifdef BN_DEBUG_LEVITTE fprintf(stderr,"DEBUG: bn_div_words(0x%08X,0x%08X,0x%08\ X) -> 0x%08X\n", n0, n1, d0, q); #endif #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 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); } BN_CTX_end(ctx); return(1); err: bn_check_top(rm); BN_CTX_end(ctx); return(0); }
int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx) { BN_CTX *new_ctx = NULL; BIGNUM *Z, *Z_1, *Z_2, *Z_3; const BIGNUM *Z_; int ret = 0; if (EC_POINT_is_at_infinity(group, point)) { OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY); return 0; } if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) { return 0; } } BN_CTX_start(ctx); Z = BN_CTX_get(ctx); Z_1 = BN_CTX_get(ctx); Z_2 = BN_CTX_get(ctx); Z_3 = BN_CTX_get(ctx); if (Z_3 == NULL) { goto err; } /* transform (X, Y, Z) into (x, y) := (X/Z^2, Y/Z^3) */ if (group->meth->field_decode) { if (!group->meth->field_decode(group, Z, &point->Z, ctx)) { goto err; } Z_ = Z; } else { Z_ = &point->Z; } if (BN_is_one(Z_)) { if (group->meth->field_decode) { if (x != NULL && !group->meth->field_decode(group, x, &point->X, ctx)) { goto err; } if (y != NULL && !group->meth->field_decode(group, y, &point->Y, ctx)) { goto err; } } else { if (x != NULL && !BN_copy(x, &point->X)) { goto err; } if (y != NULL && !BN_copy(y, &point->Y)) { goto err; } } } else { if (!BN_mod_inverse(Z_1, Z_, &group->field, ctx)) { OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); goto err; } if (group->meth->field_encode == 0) { /* field_sqr works on standard representation */ if (!group->meth->field_sqr(group, Z_2, Z_1, ctx)) { goto err; } } else if (!BN_mod_sqr(Z_2, Z_1, &group->field, ctx)) { goto err; } /* in the Montgomery case, field_mul will cancel out Montgomery factor in * X: */ if (x != NULL && !group->meth->field_mul(group, x, &point->X, Z_2, ctx)) { goto err; } if (y != NULL) { if (group->meth->field_encode == 0) { /* field_mul works on standard representation */ if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx)) { goto err; } } else if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx)) { goto err; } /* in the Montgomery case, field_mul will cancel out Montgomery factor in * Y: */ if (!group->meth->field_mul(group, y, &point->Y, Z_3, ctx)) { goto err; } } } ret = 1; err: BN_CTX_end(ctx); BN_CTX_free(new_ctx); return ret; }
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,b,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) TINYCLR_SSL_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*/ } TINYCLR_SSL_MEMCPY(buf , seed, qsize); TINYCLR_SSL_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; 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 = 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; }
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) || !BN_copy(n2, &a->Y)) { goto end; } /* n1 = X_a */ /* n2 = Y_a */ } else { if (!field_sqr(group, n0, &b->Z, ctx) || !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) || !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) || !BN_copy(n4, &b->Y)) { goto end; } /* n3 = X_b */ /* n4 = Y_b */ } else { if (!field_sqr(group, n0, &a->Z, ctx) || !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) || !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) || !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) || !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) || !field_sqr(group, n4, n5, ctx) || !field_mul(group, n3, n1, n4, ctx) || !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) || !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) || !field_mul(group, n5, n4, n5, ctx)) { goto end; /* now n5 is n5^3 */ } if (!field_mul(group, n1, n2, n5, ctx) || !BN_mod_sub_quick(n0, n0, n1, p)) { goto end; } if (BN_is_odd(n0) && !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); } BN_CTX_free(new_ctx); return ret; }
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; #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 rr->neg = a->neg ^ b->neg; bn_correct_top(rr); if (r != rr && BN_copy(r, rr) == NULL) goto err; ret = 1; err: bn_check_top(r); BN_CTX_end(ctx); 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) || !BN_mod_lshift1_quick(n1, n0, p) || !BN_mod_add_quick(n0, n0, n1, p) || !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) || !BN_mod_add_quick(n0, &a->X, n1, p) || !BN_mod_sub_quick(n2, &a->X, n1, p) || !field_mul(group, n1, n0, n2, ctx) || !BN_mod_lshift1_quick(n0, n1, p) || !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) || !BN_mod_lshift1_quick(n1, n0, p) || !BN_mod_add_quick(n0, n0, n1, p) || !field_sqr(group, n1, &a->Z, ctx) || !field_sqr(group, n1, n1, ctx) || !field_mul(group, n1, n1, &group->a, ctx) || !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) || !field_mul(group, n2, &a->X, n3, ctx) || !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) || !field_sqr(group, &r->X, n1, ctx) || !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) || !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) || !field_mul(group, n0, n1, n0, ctx) || !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); BN_CTX_free(new_ctx); return ret; }
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]; 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 } #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; }
static int vg_prefix_context_add_patterns(vg_context_t *vcp, const char ** const patterns, int npatterns) { vg_prefix_context_t *vcpp = (vg_prefix_context_t *) vcp; prefix_case_iter_t caseiter; vg_prefix_t *vp, *vp2; BN_CTX *bnctx; BIGNUM bntmp, bntmp2, bntmp3; BIGNUM *ranges[4]; int ret = 0; int i, impossible = 0; int case_impossible; unsigned long npfx; char *dbuf; bnctx = BN_CTX_new(); BN_init(&bntmp); BN_init(&bntmp2); BN_init(&bntmp3); npfx = 0; for (i = 0; i < npatterns; i++) { if (!vcpp->vcp_caseinsensitive) { vp = NULL; ret = get_prefix_ranges(vcpp->base.vc_addrtype, patterns[i], ranges, bnctx); if (!ret) { vp = vg_prefix_add_ranges(&vcpp->vcp_avlroot, patterns[i], ranges, NULL); } } else { /* Case-enumerate the prefix */ if (!prefix_case_iter_init(&caseiter, patterns[i])) { fprintf(stderr, "Prefix '%s' is too long\n", patterns[i]); continue; } if (caseiter.ci_nbits > 16) { fprintf(stderr, "WARNING: Prefix '%s' has " "2^%d case-varied derivatives\n", patterns[i], caseiter.ci_nbits); } case_impossible = 0; vp = NULL; do { ret = get_prefix_ranges(vcpp->base.vc_addrtype, caseiter.ci_prefix, ranges, bnctx); if (ret == -2) { case_impossible++; ret = 0; continue; } if (ret) break; vp2 = vg_prefix_add_ranges(&vcpp->vcp_avlroot, patterns[i], ranges, vp); if (!vp2) { ret = -1; break; } if (!vp) vp = vp2; } while (prefix_case_iter_next(&caseiter)); if (!vp && case_impossible) ret = -2; if (ret && vp) { vg_prefix_delete(&vcpp->vcp_avlroot, vp); vp = NULL; } } if (ret == -2) { fprintf(stderr, "Prefix '%s' not possible\n", patterns[i]); impossible++; } if (!vp) continue; npfx++; /* Determine the probability of finding a match */ vg_prefix_range_sum(vp, &bntmp, &bntmp2); BN_add(&bntmp2, &vcpp->vcp_difficulty, &bntmp); BN_copy(&vcpp->vcp_difficulty, &bntmp2); if (vcp->vc_verbose > 1) { BN_clear(&bntmp2); BN_set_bit(&bntmp2, 192); BN_div(&bntmp3, NULL, &bntmp2, &bntmp, bnctx); dbuf = BN_bn2dec(&bntmp3); fprintf(stderr, "Prefix difficulty: %20s %s\n", dbuf, patterns[i]); OPENSSL_free(dbuf); } } vcpp->base.vc_npatterns += npfx; vcpp->base.vc_npatterns_start += npfx; if (!npfx && impossible) { const char *ats = "bitcoin", *bw = "\"1\""; switch (vcpp->base.vc_addrtype) { case 5: ats = "bitcoin script"; bw = "\"3\""; break; case 111: ats = "testnet"; bw = "\"m\" or \"n\""; break; case 52: ats = "namecoin"; bw = "\"M\" or \"N\""; break; case 55: ats = "peercoin"; bw = "\"P\""; break; default: break; } fprintf(stderr, "Hint: valid %s addresses begin with %s\n", ats, bw); } if (npfx) vg_prefix_context_next_difficulty(vcpp, &bntmp, &bntmp2, bnctx); ret = (npfx != 0); BN_clear_free(&bntmp); BN_clear_free(&bntmp2); BN_clear_free(&bntmp3); BN_CTX_free(bnctx); return ret; }
int test_div_recp(BIO *bp, BN_CTX *ctx) { BIGNUM a,b,c,d,e; BN_RECP_CTX recp; int i; BN_RECP_CTX_init(&recp); BN_init(&a); BN_init(&b); BN_init(&c); BN_init(&d); BN_init(&e); for (i=0; i<num0+num1; i++) { if (i < num1) { BN_bntest_rand(&a,400,0,0); BN_copy(&b,&a); BN_lshift(&a,&a,i); BN_add_word(&a,i); } else BN_bntest_rand(&b,50+3*(i-num1),0,0); a.neg=rand_neg(); b.neg=rand_neg(); BN_RECP_CTX_set(&recp,&b,ctx); BN_div_recp(&d,&c,&a,&recp,ctx); if (bp != NULL) { if (!results) { BN_print(bp,&a); BIO_puts(bp," / "); BN_print(bp,&b); BIO_puts(bp," - "); } BN_print(bp,&d); BIO_puts(bp,"\n"); if (!results) { BN_print(bp,&a); BIO_puts(bp," % "); BN_print(bp,&b); BIO_puts(bp," - "); } BN_print(bp,&c); BIO_puts(bp,"\n"); } BN_mul(&e,&d,&b,ctx); BN_add(&d,&e,&c); BN_sub(&d,&d,&a); if(!BN_is_zero(&d)) { fprintf(stderr,"Reciprocal division test failed!\n"); fprintf(stderr,"a="); BN_print_fp(stderr,&a); fprintf(stderr,"\nb="); BN_print_fp(stderr,&b); fprintf(stderr,"\n"); return 0; } } BN_free(&a); BN_free(&b); BN_free(&c); BN_free(&d); BN_free(&e); BN_RECP_CTX_free(&recp); return(1); }
/* * Find the bignum ranges that produce a given prefix. */ static int get_prefix_ranges(int addrtype, const char *pfx, BIGNUM **result, BN_CTX *bnctx) { int i, p, c; int zero_prefix = 0; int check_upper = 0; int b58pow, b58ceil, b58top = 0; int ret = -1; BIGNUM bntarg, bnceil, bnfloor; BIGNUM bnbase; BIGNUM *bnap, *bnbp, *bntp; BIGNUM *bnhigh = NULL, *bnlow = NULL, *bnhigh2 = NULL, *bnlow2 = NULL; BIGNUM bntmp, bntmp2; BN_init(&bntarg); BN_init(&bnceil); BN_init(&bnfloor); BN_init(&bnbase); BN_init(&bntmp); BN_init(&bntmp2); BN_set_word(&bnbase, 58); p = strlen(pfx); for (i = 0; i < p; i++) { c = vg_b58_reverse_map[(int)pfx[i]]; if (c == -1) { fprintf(stderr, "Invalid character '%c' in prefix '%s'\n", pfx[i], pfx); goto out; } if (i == zero_prefix) { if (c == 0) { /* Add another zero prefix */ zero_prefix++; if (zero_prefix > 19) { fprintf(stderr, "Prefix '%s' is too long\n", pfx); goto out; } continue; } /* First non-zero character */ b58top = c; BN_set_word(&bntarg, c); } else { BN_set_word(&bntmp2, c); BN_mul(&bntmp, &bntarg, &bnbase, bnctx); BN_add(&bntarg, &bntmp, &bntmp2); } } /* Power-of-two ceiling and floor values based on leading 1s */ BN_clear(&bntmp); BN_set_bit(&bntmp, 200 - (zero_prefix * 8)); BN_sub(&bnceil, &bntmp, BN_value_one()); BN_set_bit(&bnfloor, 192 - (zero_prefix * 8)); bnlow = BN_new(); bnhigh = BN_new(); if (b58top) { /* * If a non-zero was given in the prefix, find the * numeric boundaries of the prefix. */ BN_copy(&bntmp, &bnceil); bnap = &bntmp; bnbp = &bntmp2; b58pow = 0; while (BN_cmp(bnap, &bnbase) > 0) { b58pow++; BN_div(bnbp, NULL, bnap, &bnbase, bnctx); bntp = bnap; bnap = bnbp; bnbp = bntp; } b58ceil = BN_get_word(bnap); if ((b58pow - (p - zero_prefix)) < 6) { /* * Do not allow the prefix to constrain the * check value, this is ridiculous. */ fprintf(stderr, "Prefix '%s' is too long\n", pfx); goto out; } BN_set_word(&bntmp2, b58pow - (p - zero_prefix)); BN_exp(&bntmp, &bnbase, &bntmp2, bnctx); BN_mul(bnlow, &bntmp, &bntarg, bnctx); BN_sub(&bntmp2, &bntmp, BN_value_one()); BN_add(bnhigh, bnlow, &bntmp2); if (b58top <= b58ceil) { /* Fill out the upper range too */ check_upper = 1; bnlow2 = BN_new(); bnhigh2 = BN_new(); BN_mul(bnlow2, bnlow, &bnbase, bnctx); BN_mul(&bntmp2, bnhigh, &bnbase, bnctx); BN_set_word(&bntmp, 57); BN_add(bnhigh2, &bntmp2, &bntmp); /* * Addresses above the ceiling will have one * fewer "1" prefix in front than we require. */ if (BN_cmp(&bnceil, bnlow2) < 0) { /* High prefix is above the ceiling */ check_upper = 0; BN_free(bnhigh2); bnhigh2 = NULL; BN_free(bnlow2); bnlow2 = NULL; } else if (BN_cmp(&bnceil, bnhigh2) < 0) /* High prefix is partly above the ceiling */ BN_copy(bnhigh2, &bnceil); /* * Addresses below the floor will have another * "1" prefix in front instead of our target. */ if (BN_cmp(&bnfloor, bnhigh) >= 0) { /* Low prefix is completely below the floor */ assert(check_upper); check_upper = 0; BN_free(bnhigh); bnhigh = bnhigh2; bnhigh2 = NULL; BN_free(bnlow); bnlow = bnlow2; bnlow2 = NULL; } else if (BN_cmp(&bnfloor, bnlow) > 0) { /* Low prefix is partly below the floor */ BN_copy(bnlow, &bnfloor); } } } else { BN_copy(bnhigh, &bnceil); BN_clear(bnlow); } /* Limit the prefix to the address type */ BN_clear(&bntmp); BN_set_word(&bntmp, addrtype); BN_lshift(&bntmp2, &bntmp, 192); if (check_upper) { if (BN_cmp(&bntmp2, bnhigh2) > 0) { check_upper = 0; BN_free(bnhigh2); bnhigh2 = NULL; BN_free(bnlow2); bnlow2 = NULL; } else if (BN_cmp(&bntmp2, bnlow2) > 0) BN_copy(bnlow2, &bntmp2); } if (BN_cmp(&bntmp2, bnhigh) > 0) { if (!check_upper) goto not_possible; check_upper = 0; BN_free(bnhigh); bnhigh = bnhigh2; bnhigh2 = NULL; BN_free(bnlow); bnlow = bnlow2; bnlow2 = NULL; } else if (BN_cmp(&bntmp2, bnlow) > 0) { BN_copy(bnlow, &bntmp2); } BN_set_word(&bntmp, addrtype + 1); BN_lshift(&bntmp2, &bntmp, 192); if (check_upper) { if (BN_cmp(&bntmp2, bnlow2) < 0) { check_upper = 0; BN_free(bnhigh2); bnhigh2 = NULL; BN_free(bnlow2); bnlow2 = NULL; } else if (BN_cmp(&bntmp2, bnhigh2) < 0) BN_copy(bnlow2, &bntmp2); } if (BN_cmp(&bntmp2, bnlow) < 0) { if (!check_upper) goto not_possible; check_upper = 0; BN_free(bnhigh); bnhigh = bnhigh2; bnhigh2 = NULL; BN_free(bnlow); bnlow = bnlow2; bnlow2 = NULL; } else if (BN_cmp(&bntmp2, bnhigh) < 0) { BN_copy(bnhigh, &bntmp2); } /* Address ranges are complete */ assert(check_upper || ((bnlow2 == NULL) && (bnhigh2 == NULL))); result[0] = bnlow; result[1] = bnhigh; result[2] = bnlow2; result[3] = bnhigh2; bnlow = NULL; bnhigh = NULL; bnlow2 = NULL; bnhigh2 = NULL; ret = 0; if (0) { not_possible: ret = -2; } out: BN_clear_free(&bntarg); BN_clear_free(&bnceil); BN_clear_free(&bnfloor); BN_clear_free(&bnbase); BN_clear_free(&bntmp); BN_clear_free(&bntmp2); if (bnhigh) BN_free(bnhigh); if (bnlow) BN_free(bnlow); if (bnhigh2) BN_free(bnhigh2); if (bnlow2) BN_free(bnlow2); return ret; }
int bn_sqr_fixed_top(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) { int max, al; int ret = 0; BIGNUM *tmp, *rr; bn_check_top(a); al = a->top; if (al <= 0) { r->top = 0; r->neg = 0; return 1; } BN_CTX_start(ctx); rr = (a != r) ? r : BN_CTX_get(ctx); tmp = BN_CTX_get(ctx); if (rr == NULL || tmp == NULL) goto err; max = 2 * al; /* Non-zero (from above) */ if (bn_wexpand(rr, max) == NULL) goto err; if (al == 4) { #ifndef BN_SQR_COMBA BN_ULONG t[8]; bn_sqr_normal(rr->d, a->d, 4, t); #else bn_sqr_comba4(rr->d, a->d); #endif } else if (al == 8) { #ifndef BN_SQR_COMBA BN_ULONG t[16]; bn_sqr_normal(rr->d, a->d, 8, t); #else bn_sqr_comba8(rr->d, a->d); #endif } else { #if defined(BN_RECURSION) if (al < BN_SQR_RECURSIVE_SIZE_NORMAL) { BN_ULONG t[BN_SQR_RECURSIVE_SIZE_NORMAL * 2]; bn_sqr_normal(rr->d, a->d, al, t); } else { int j, k; j = BN_num_bits_word((BN_ULONG)al); j = 1 << (j - 1); k = j + j; if (al == j) { if (bn_wexpand(tmp, k * 2) == NULL) goto err; bn_sqr_recursive(rr->d, a->d, al, tmp->d); } else { if (bn_wexpand(tmp, max) == NULL) goto err; bn_sqr_normal(rr->d, a->d, al, tmp->d); } } #else if (bn_wexpand(tmp, max) == NULL) goto err; bn_sqr_normal(rr->d, a->d, al, tmp->d); #endif } rr->neg = 0; rr->top = max; rr->flags |= BN_FLG_FIXED_TOP; if (r != rr && BN_copy(r, rr) == NULL) goto err; ret = 1; err: bn_check_top(rr); bn_check_top(tmp); BN_CTX_end(ctx); return ret; }
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; }
/* Returns -2 for errors because both -1 and 0 are valid results. */ int BN_kronecker(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { int i; int ret = -2; /* avoid 'uninitialized' warning */ int err = 0; BIGNUM *A, *B, *tmp; /* In 'tab', only odd-indexed entries are relevant: * For any odd BIGNUM n, * tab[BN_lsw(n) & 7] * is $(-1)^{(n^2-1)/8}$ (using TeX notation). * Note that the sign of n does not matter. */ static const int tab[8] = {0, 1, 0, -1, 0, -1, 0, 1}; bn_check_top(a); bn_check_top(b); BN_CTX_start(ctx); A = BN_CTX_get(ctx); B = BN_CTX_get(ctx); if (B == NULL) goto end; err = !BN_copy(A, a); if (err) goto end; err = !BN_copy(B, b); if (err) goto end; /* * Kronecker symbol, imlemented according to Henri Cohen, * "A Course in Computational Algebraic Number Theory" * (algorithm 1.4.10). */ /* Cohen's step 1: */ if (BN_is_zero(B)) { ret = BN_abs_is_word(A, 1); goto end; } /* Cohen's step 2: */ if (!BN_is_odd(A) && !BN_is_odd(B)) { ret = 0; goto end; } /* now B is non-zero */ i = 0; while (!BN_is_bit_set(B, i)) i++; err = !BN_rshift(B, B, i); if (err) goto end; if (i & 1) { /* i is odd */ /* (thus B was even, thus A must be odd!) */ /* set 'ret' to $(-1)^{(A^2-1)/8}$ */ ret = tab[BN_lsw(A) & 7]; } else { /* i is even */ ret = 1; } if (B->neg) { B->neg = 0; if (A->neg) ret = -ret; } /* now B is positive and odd, so what remains to be done is * to compute the Jacobi symbol (A/B) and multiply it by 'ret' */ while (1) { /* Cohen's step 3: */ /* B is positive and odd */ if (BN_is_zero(A)) { ret = BN_is_one(B) ? ret : 0; goto end; } /* now A is non-zero */ i = 0; while (!BN_is_bit_set(A, i)) i++; err = !BN_rshift(A, A, i); if (err) goto end; if (i & 1) { /* i is odd */ /* multiply 'ret' by $(-1)^{(B^2-1)/8}$ */ ret = ret * tab[BN_lsw(B) & 7]; } /* Cohen's step 4: */ /* multiply 'ret' by $(-1)^{(A-1)(B-1)/4}$ */ if ((A->neg ? ~BN_lsw(A) : BN_lsw(A)) & BN_lsw(B) & 2) ret = -ret; /* (A, B) := (B mod |A|, |A|) */ err = !BN_nnmod(B, B, A, ctx); if (err) goto end; tmp = A; A = B; B = tmp; tmp->neg = 0; } end: BN_CTX_end(ctx); if (err) return -2; else return ret; }
int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx) { BN_CTX *new_ctx = NULL; BIGNUM *tmp0, *tmp1; size_t pow2 = 0; BIGNUM **heap = NULL; size_t i; int ret = 0; if (num == 0) return 1; if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) return 0; } BN_CTX_start(ctx); tmp0 = BN_CTX_get(ctx); tmp1 = BN_CTX_get(ctx); if (tmp0 == NULL || tmp1 == NULL) goto err; /* Before converting the individual points, compute inverses of all Z values. * Modular inversion is rather slow, but luckily we can do with a single * explicit inversion, plus about 3 multiplications per input value. */ pow2 = 1; while (num > pow2) pow2 <<= 1; /* Now pow2 is the smallest power of 2 satifsying pow2 >= num. * We need twice that. */ pow2 <<= 1; heap = OPENSSL_malloc(pow2 * sizeof heap[0]); if (heap == NULL) goto err; /* The array is used as a binary tree, exactly as in heapsort: * * heap[1] * heap[2] heap[3] * heap[4] heap[5] heap[6] heap[7] * heap[8]heap[9] heap[10]heap[11] heap[12]heap[13] heap[14] heap[15] * * We put the Z's in the last line; * then we set each other node to the product of its two child-nodes (where * empty or 0 entries are treated as ones); * then we invert heap[1]; * then we invert each other node by replacing it by the product of its * parent (after inversion) and its sibling (before inversion). */ heap[0] = NULL; for (i = pow2/2 - 1; i > 0; i--) heap[i] = NULL; for (i = 0; i < num; i++) heap[pow2/2 + i] = &points[i]->Z; for (i = pow2/2 + num; i < pow2; i++) heap[i] = NULL; /* set each node to the product of its children */ for (i = pow2/2 - 1; i > 0; i--) { heap[i] = BN_new(); if (heap[i] == NULL) goto err; if (heap[2*i] != NULL) { if ((heap[2*i + 1] == NULL) || BN_is_zero(heap[2*i + 1])) { if (!BN_copy(heap[i], heap[2*i])) goto err; } else { if (BN_is_zero(heap[2*i])) { if (!BN_copy(heap[i], heap[2*i + 1])) goto err; } else { if (!group->meth->field_mul(group, heap[i], heap[2*i], heap[2*i + 1], ctx)) goto err; } } } } /* invert heap[1] */ if (!BN_is_zero(heap[1])) { if (!BN_mod_inverse(heap[1], heap[1], &group->field, ctx)) { ECerr(EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE, ERR_R_BN_LIB); goto err; } } if (group->meth->field_encode != 0) { /* in the Montgomery case, we just turned R*H (representing H) * into 1/(R*H), but we need R*(1/H) (representing 1/H); * i.e. we have need to multiply by the Montgomery factor twice */ if (!group->meth->field_encode(group, heap[1], heap[1], ctx)) goto err; if (!group->meth->field_encode(group, heap[1], heap[1], ctx)) goto err; } /* set other heap[i]'s to their inverses */ for (i = 2; i < pow2/2 + num; i += 2) { /* i is even */ if ((heap[i + 1] != NULL) && !BN_is_zero(heap[i + 1])) { if (!group->meth->field_mul(group, tmp0, heap[i/2], heap[i + 1], ctx)) goto err; if (!group->meth->field_mul(group, tmp1, heap[i/2], heap[i], ctx)) goto err; if (!BN_copy(heap[i], tmp0)) goto err; if (!BN_copy(heap[i + 1], tmp1)) goto err; } else { if (!BN_copy(heap[i], heap[i/2])) goto err; } } /* we have replaced all non-zero Z's by their inverses, now fix up all the points */ for (i = 0; i < num; i++) { EC_POINT *p = points[i]; if (!BN_is_zero(&p->Z)) { /* turn (X, Y, 1/Z) into (X/Z^2, Y/Z^3, 1) */ if (!group->meth->field_sqr(group, tmp1, &p->Z, ctx)) goto err; if (!group->meth->field_mul(group, &p->X, &p->X, tmp1, ctx)) goto err; if (!group->meth->field_mul(group, tmp1, tmp1, &p->Z, ctx)) goto err; if (!group->meth->field_mul(group, &p->Y, &p->Y, tmp1, ctx)) goto err; if (group->meth->field_set_to_one != 0) { if (!group->meth->field_set_to_one(group, &p->Z, ctx)) goto err; } else { if (!BN_one(&p->Z)) goto err; } p->Z_is_one = 1; } } ret = 1; err: BN_CTX_end(ctx); if (new_ctx != NULL) BN_CTX_free(new_ctx); if (heap != NULL) { /* heap[pow2/2] .. heap[pow2-1] have not been allocated locally! */ for (i = pow2/2 - 1; i > 0; i--) { if (heap[i] != NULL) BN_clear_free(heap[i]); } OPENSSL_free(heap); } return ret; }