#include <string.h>
#include <openssl/ec.h>
#include "bn_local.h"
#include "bn_internal.h"
#include "ec_local.h"
#include "ec_internal.h"
int
ec_field_modulus_from_bn(EC_FIELD_MODULUS *fm, const BIGNUM *bn, BN_CTX *ctx)
{
BN_MONT_CTX *mctx = NULL;
size_t i;
int ret = 0;
if (BN_is_negative(bn))
goto err;
if (BN_num_bits(bn) > EC_FIELD_ELEMENT_MAX_BITS)
goto err;
memset(fm, 0, sizeof(*fm));
fm->n = (BN_num_bits(bn) + BN_BITS2 - 1) / BN_BITS2;
for (i = 0; i < bn->top; i++)
fm->m.w[i] = bn->d[i];
if ((mctx = BN_MONT_CTX_new()) == NULL)
goto err;
if (!BN_MONT_CTX_set(mctx, bn, ctx))
goto err;
for (i = 0; i < mctx->RR.top; i++)
fm->rr.w[i] = mctx->RR.d[i];
fm->minv0 = mctx->n0[0];
ret = 1;
err:
BN_MONT_CTX_free(mctx);
return ret;
}
int
ec_field_element_from_bn(const EC_FIELD_MODULUS *fm, const EC_GROUP *group,
EC_FIELD_ELEMENT *fe, const BIGNUM *bn, BN_CTX *ctx)
{
BN_ULONG t[EC_FIELD_ELEMENT_MAX_WORDS * 2 + 2];
BIGNUM *tmp;
size_t i;
int ret = 0;
BN_CTX_start(ctx);
if ((tmp = BN_CTX_get(ctx)) == NULL)
goto err;
if (BN_num_bits(bn) > EC_FIELD_ELEMENT_MAX_BITS)
goto err;
if (!BN_nnmod(tmp, bn, group->p, ctx))
goto err;
if (BN_num_bits(tmp) > EC_FIELD_ELEMENT_MAX_BITS)
abort();
memset(fe->w, 0, sizeof(fe->w));
for (i = 0; i < tmp->top; i++)
fe->w[i] = tmp->d[i];
bn_mod_mul_words(fe->w, fe->w, fm->rr.w, fm->m.w, t, fm->minv0, fm->n);
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
int
ec_field_element_to_bn(const EC_FIELD_MODULUS *fm, const EC_FIELD_ELEMENT *fe,
BIGNUM *bn, BN_CTX *ctx)
{
BN_ULONG t[EC_FIELD_ELEMENT_MAX_WORDS * 2 + 2];
size_t i;
if (!bn_wexpand(bn, fm->n))
return 0;
memset(t, 0, sizeof(t));
for (i = 0; i < fm->n; i++)
t[i] = fe->w[i];
bn_montgomery_reduce_words(bn->d, t, fm->m.w, fm->minv0, fm->n);
bn->top = fm->n;
bn_correct_top(bn);
return 1;
}
void
ec_field_element_copy(EC_FIELD_ELEMENT *dst, const EC_FIELD_ELEMENT *src)
{
memcpy(dst, src, sizeof(EC_FIELD_ELEMENT));
}
void
ec_field_element_select(const EC_FIELD_MODULUS *fm, EC_FIELD_ELEMENT *r,
const EC_FIELD_ELEMENT *a, const EC_FIELD_ELEMENT *b, int conditional)
{
BN_ULONG mask;
int i;
mask = bn_ct_eq_zero_mask(conditional);
for (i = 0; i < fm->n; i++)
r->w[i] = (a->w[i] & mask) | (b->w[i] & ~mask);
}
int
ec_field_element_equal(const EC_FIELD_MODULUS *fm, const EC_FIELD_ELEMENT *a,
const EC_FIELD_ELEMENT *b)
{
BN_ULONG v = 0;
int i;
for (i = 0; i < fm->n; i++)
v |= a->w[i] ^ b->w[i];
return bn_ct_eq_zero(v);
}
int
ec_field_element_is_zero(const EC_FIELD_MODULUS *fm, const EC_FIELD_ELEMENT *fe)
{
BN_ULONG v = 0;
int i;
for (i = 0; i < fm->n; i++)
v |= fe->w[i];
return bn_ct_eq_zero(v);
}
void
ec_field_element_add(const EC_FIELD_MODULUS *m, EC_FIELD_ELEMENT *r,
const EC_FIELD_ELEMENT *a, const EC_FIELD_ELEMENT *b)
{
bn_mod_add_words(r->w, a->w, b->w, m->m.w, m->n);
}
void
ec_field_element_sub(const EC_FIELD_MODULUS *m, EC_FIELD_ELEMENT *r,
const EC_FIELD_ELEMENT *a, const EC_FIELD_ELEMENT *b)
{
bn_mod_sub_words(r->w, a->w, b->w, m->m.w, m->n);
}
void
ec_field_element_mul(const EC_FIELD_MODULUS *m, EC_FIELD_ELEMENT *r,
const EC_FIELD_ELEMENT *a, const EC_FIELD_ELEMENT *b)
{
BN_ULONG t[EC_FIELD_ELEMENT_MAX_WORDS * 2 + 2];
bn_mod_mul_words(r->w, a->w, b->w, m->m.w, t, m->minv0, m->n);
}
void
ec_field_element_sqr(const EC_FIELD_MODULUS *m, EC_FIELD_ELEMENT *r,
const EC_FIELD_ELEMENT *a)
{
BN_ULONG t[EC_FIELD_ELEMENT_MAX_WORDS * 2 + 2];
bn_mod_sqr_words(r->w, a->w, m->m.w, t, m->minv0, m->n);
}