/*1* Copyright (C) 2017 - This file is part of libecc project2*3* Authors:4* Ryad BENADJILA <[email protected]>5* Arnaud EBALARD <[email protected]>6* Jean-Pierre FLORI <[email protected]>7*8* Contributors:9* Nicolas VIVET <[email protected]>10* Karim KHALFALLAH <[email protected]>11*12* This software is licensed under a dual BSD and GPL v2 license.13* See LICENSE file at the root folder of the project.14*/15#include <libecc/nn/nn_logical.h>16#include <libecc/nn/nn_mod_pow.h>17#include <libecc/fp/fp_pow.h>18#include <libecc/fp/fp.h>1920/*21* NOT constant time with regard to the bitlength of exp.22* Aliasing not supported. Expects caller to check parameters23* have been initialized. This is an internal helper.24*25* Returns 0 on success, -1 on error.26*/27ATTRIBUTE_WARN_UNUSED_RET static int _fp_pow(fp_t out, fp_src_t base, nn_src_t exp)28{29/* Use the lower layer modular exponentiation */30return nn_mod_pow_redc(&(out->fp_val), &(base->fp_val), exp, &(out->ctx->p), &(out->ctx->r), &(out->ctx->r_square), out->ctx->mpinv);31}3233/*34* Same purpose as above but handles aliasing of 'base' and 'out', i.e.35* base is passed via 'out'. Expects caller to check parameters36* have been initialized. This is an internal helper.37*/38ATTRIBUTE_WARN_UNUSED_RET static int _fp_pow_aliased(fp_t out, nn_src_t exp)39{40fp base;41int ret;42base.magic = WORD(0);4344ret = fp_init(&base, out->ctx); EG(ret, err);45ret = fp_copy(&base, out); EG(ret, err);46ret = _fp_pow(out, &base, exp); EG(ret, err);4748err:49fp_uninit(&base);5051return ret;52}5354/*55* Compute out = base^exp (p). 'base', 'exp' and 'out' are supposed to be initialized.56* Aliased version of previous one.57*58* Aliasing is supported.59*/60int fp_pow(fp_t out, fp_src_t base, nn_src_t exp)61{62int ret;6364ret = fp_check_initialized(base); EG(ret, err);65ret = nn_check_initialized(exp); EG(ret, err);66ret = fp_check_initialized(out); EG(ret, err);67MUST_HAVE(((&(out->ctx->p)) == (&(base->ctx->p))), ret, err);6869/* Handle output aliasing */70if (out == base) {71ret = _fp_pow_aliased(out, exp);72} else {73ret = _fp_pow(out, base, exp);74}7576err:77return ret;78}798081