#include <libecc/fp/fp.h>
#include <libecc/fp/fp_add.h>
#include <libecc/nn/nn_add.h>
#include <libecc/nn/nn_logical.h>
#include <libecc/nn/nn_mul_redc1.h>
#include "../nn/nn_div.h"
#define FP_CTX_MAGIC ((word_t)(0x114366fc34955125ULL))
int fp_ctx_check_initialized(fp_ctx_src_t ctx)
{
int ret = 0;
MUST_HAVE(((ctx != NULL) && (ctx->magic == FP_CTX_MAGIC)), ret, err);
err:
return ret;
}
int fp_ctx_init(fp_ctx_t ctx, nn_src_t p, bitcnt_t p_bitlen,
nn_src_t r, nn_src_t r_square,
word_t mpinv,
bitcnt_t p_shift, nn_src_t p_normalized, word_t p_reciprocal)
{
int ret;
MUST_HAVE((ctx != NULL), ret, err);
ret = nn_check_initialized(p); EG(ret, err);
ret = nn_check_initialized(r); EG(ret, err);
ret = nn_check_initialized(r_square); EG(ret, err);
ret = nn_check_initialized(p_normalized); EG(ret, err);
ret = nn_copy(&(ctx->p), p); EG(ret, err);
ctx->p_bitlen = p_bitlen;
ctx->mpinv = mpinv;
ctx->p_shift = p_shift;
ctx->p_reciprocal = p_reciprocal;
ret = nn_copy(&(ctx->p_normalized), p_normalized); EG(ret, err);
ret = nn_copy(&(ctx->r), r); EG(ret, err);
ret = nn_copy(&(ctx->r_square), r_square); EG(ret, err);
ctx->magic = FP_CTX_MAGIC;
err:
return ret;
}
int fp_ctx_init_from_p(fp_ctx_t ctx, nn_src_t p_in)
{
nn p, r, r_square, p_normalized;
word_t mpinv, p_shift, p_reciprocal;
bitcnt_t p_bitlen;
int ret;
p.magic = r.magic = r_square.magic = p_normalized.magic = WORD(0);
MUST_HAVE((ctx != NULL), ret, err);
ret = nn_check_initialized(p_in); EG(ret, err);
ret = nn_init(&p, 0); EG(ret, err);
ret = nn_copy(&p, p_in); EG(ret, err);
ret = nn_init(&r, 0); EG(ret, err);
ret = nn_init(&r_square, 0); EG(ret, err);
ret = nn_init(&p_normalized, 0); EG(ret, err);
if (p.wlen < 2) {
ret = nn_set_wlen(&p, 2); EG(ret, err);
}
ret = nn_compute_redc1_coefs(&r, &r_square, &p, &mpinv); EG(ret, err);
ret = nn_compute_div_coefs(&p_normalized, &p_shift, &p_reciprocal, &p); EG(ret, err);
ret = nn_bitlen(p_in, &p_bitlen); EG(ret, err);
ret = fp_ctx_init(ctx, &p, p_bitlen, &r, &r_square,
mpinv, (bitcnt_t)p_shift, &p_normalized, p_reciprocal);
err:
nn_uninit(&p);
nn_uninit(&r);
nn_uninit(&r_square);
nn_uninit(&p_normalized);
return ret;
}
#define FP_MAGIC ((word_t)(0x14e96c8ab28221efULL))
int fp_check_initialized(fp_src_t in)
{
int ret = 0;
MUST_HAVE(((in != NULL) && (in->magic == FP_MAGIC) && (in->ctx != NULL) && (in->ctx->magic == FP_CTX_MAGIC)), ret, err);
err:
return ret;
}
int fp_init(fp_t in, fp_ctx_src_t fpctx)
{
int ret;
MUST_HAVE((in != NULL), ret, err);
ret = fp_ctx_check_initialized(fpctx); EG(ret, err);
ret = nn_init(&(in->fp_val), (u16)((fpctx->p.wlen) * WORD_BYTES)); EG(ret, err);
in->ctx = fpctx;
in->magic = FP_MAGIC;
err:
return ret;
}
int fp_init_from_buf(fp_t in, fp_ctx_src_t fpctx, const u8 *buf, u16 buflen)
{
int ret;
ret = fp_ctx_check_initialized(fpctx); EG(ret, err);
ret = fp_init(in, fpctx); EG(ret, err);
ret = fp_import_from_buf(in, buf, buflen);
err:
return ret;
}
void fp_uninit(fp_t in)
{
if((in != NULL) && (in->magic == FP_MAGIC) && (in->ctx != NULL)){
nn_uninit(&in->fp_val);
in->ctx = NULL;
in->magic = WORD(0);
}
return;
}
int fp_set_nn(fp_t out, nn_src_t in)
{
int ret, cmp;
ret = fp_check_initialized(out); EG(ret, err);
ret = nn_check_initialized(in); EG(ret, err);
ret = nn_copy(&(out->fp_val), in); EG(ret, err);
ret = nn_cmp(&(out->fp_val), &(out->ctx->p), &cmp); EG(ret, err);
MUST_HAVE((cmp < 0), ret, err);
ret = nn_set_wlen(&(out->fp_val), out->ctx->p.wlen);
err:
return ret;
}
int fp_zero(fp_t out)
{
int ret;
ret = fp_check_initialized(out); EG(ret, err);
ret = nn_set_word_value(&(out->fp_val), 0); EG(ret, err);
ret = nn_set_wlen(&(out->fp_val), out->ctx->p.wlen);
err:
return ret;
}
int fp_one(fp_t out)
{
int ret, isone;
word_t val;
ret = fp_check_initialized(out); EG(ret, err);
ret = nn_isone(&(out->ctx->p), &isone); EG(ret, err);
val = isone ? WORD(0) : WORD(1);
ret = nn_set_word_value(&(out->fp_val), val); EG(ret, err);
ret = nn_set_wlen(&(out->fp_val), out->ctx->p.wlen);
err:
return ret;
}
int fp_set_word_value(fp_t out, word_t val)
{
int ret, cmp;
ret = fp_check_initialized(out); EG(ret, err);
ret = nn_cmp_word(&(out->ctx->p), val, &cmp); EG(ret, err);
MUST_HAVE((cmp > 0), ret, err);
ret = nn_set_word_value(&(out->fp_val), val); EG(ret, err);
ret = nn_set_wlen(&(out->fp_val), out->ctx->p.wlen);
err:
return ret;
}
int fp_cmp(fp_src_t in1, fp_src_t in2, int *cmp)
{
int ret;
ret = fp_check_initialized(in1); EG(ret, err);
ret = fp_check_initialized(in2); EG(ret, err);
MUST_HAVE((in1->ctx == in2->ctx), ret, err);
ret = nn_cmp(&(in1->fp_val), &(in2->fp_val), cmp);
err:
return ret;
}
int fp_iszero(fp_src_t in, int *iszero)
{
int ret;
ret = fp_check_initialized(in); EG(ret, err);
ret = nn_iszero(&(in->fp_val), iszero);
err:
return ret;
}
int fp_copy(fp_t out, fp_src_t in)
{
int ret;
ret = fp_check_initialized(in); EG(ret, err);
MUST_HAVE((out != NULL), ret, err);
if ((out->magic == FP_MAGIC) && (out->ctx != NULL)) {
MUST_HAVE((out->ctx == in->ctx), ret, err);
} else {
ret = fp_init(out, in->ctx); EG(ret, err);
}
ret = nn_copy(&(out->fp_val), &(in->fp_val));
err:
return ret;
}
int fp_tabselect(fp_t out, u8 idx, fp_src_t *tab, u8 tabsize)
{
u8 i, k, p_wlen;
word_t mask;
nn_src_t p;
int ret;
MUST_HAVE(((tab != NULL) && (idx < tabsize)), ret, err);
ret = fp_check_initialized(out); EG(ret, err);
p = &(out->ctx->p);
MUST_HAVE((p != NULL), ret, err);
p_wlen = p->wlen;
ret = nn_zero(&(out->fp_val)); EG(ret, err);
out->fp_val.wlen = p_wlen;
for (k = 0; k < tabsize; k++) {
ret = fp_check_initialized(tab[k]); EG(ret, err);
MUST_HAVE(((&(tab[k]->ctx->p)) == p), ret, err);
mask = WORD_MASK_IFNOTZERO(idx == k);
for (i = 0; i < p_wlen; i++) {
out->fp_val.val[i] |= (tab[k]->fp_val.val[i] & mask);
}
}
err:
return ret;
}
int fp_eq_or_opp(fp_src_t in1, fp_src_t in2, int *eq_or_opp)
{
int ret, cmp_eq, cmp_opp;
fp opp;
opp.magic = WORD(0);
MUST_HAVE((eq_or_opp != NULL), ret, err);
ret = fp_check_initialized(in1); EG(ret, err);
ret = fp_check_initialized(in2); EG(ret, err);
MUST_HAVE((in1->ctx == in2->ctx), ret, err);
ret = fp_init(&opp, in1->ctx); EG(ret, err);
ret = fp_neg(&opp, in2); EG(ret, err);
ret = nn_cmp(&(in1->fp_val), &(in2->fp_val), &cmp_eq); EG(ret, err);
ret = nn_cmp(&(in1->fp_val), &(opp.fp_val), &cmp_opp); EG(ret, err);
(*eq_or_opp) = ((cmp_eq == 0) | (cmp_opp == 0));
err:
fp_uninit(&opp);
return ret;
}
int fp_import_from_buf(fp_t out_fp, const u8 *buf, u16 buflen)
{
int ret, cmp;
ret = fp_check_initialized(out_fp); EG(ret, err);
ret = nn_init_from_buf(&(out_fp->fp_val), buf, buflen); EG(ret, err);
ret = nn_cmp(&(out_fp->fp_val), &(out_fp->ctx->p), &cmp); EG(ret, err);
MUST_HAVE((cmp < 0), ret, err);
err:
return ret;
}
int fp_export_to_buf(u8 *buf, u16 buflen, fp_src_t in_fp)
{
int ret;
ret = fp_check_initialized(in_fp); EG(ret, err);
ret = nn_export_to_buf(buf, buflen, &(in_fp->fp_val));
err:
return ret;
}