1 /* 2 * Copyright (C) 2017 - This file is part of libecc project 3 * 4 * Authors: 5 * Ryad BENADJILA <ryadbenadjila@gmail.com> 6 * Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr> 7 * Jean-Pierre FLORI <jean-pierre.flori@ssi.gouv.fr> 8 * 9 * Contributors: 10 * Nicolas VIVET <nicolas.vivet@ssi.gouv.fr> 11 * Karim KHALFALLAH <karim.khalfallah@ssi.gouv.fr> 12 * 13 * This software is licensed under a dual BSD and GPL v2 license. 14 * See LICENSE file at the root folder of the project. 15 */ 16 #include <libecc/nn/nn_logical.h> 17 #include <libecc/nn/nn_mod_pow.h> 18 #include <libecc/fp/fp_pow.h> 19 #include <libecc/fp/fp.h> 20 21 /* 22 * NOT constant time with regard to the bitlength of exp. 23 * Aliasing not supported. Expects caller to check parameters 24 * have been initialized. This is an internal helper. 25 * 26 * Returns 0 on success, -1 on error. 27 */ 28 ATTRIBUTE_WARN_UNUSED_RET static int _fp_pow(fp_t out, fp_src_t base, nn_src_t exp) 29 { 30 /* Use the lower layer modular exponentiation */ 31 return nn_mod_pow_redc(&(out->fp_val), &(base->fp_val), exp, &(out->ctx->p), &(out->ctx->r), &(out->ctx->r_square), out->ctx->mpinv); 32 } 33 34 /* 35 * Same purpose as above but handles aliasing of 'base' and 'out', i.e. 36 * base is passed via 'out'. Expects caller to check parameters 37 * have been initialized. This is an internal helper. 38 */ 39 ATTRIBUTE_WARN_UNUSED_RET static int _fp_pow_aliased(fp_t out, nn_src_t exp) 40 { 41 fp base; 42 int ret; 43 base.magic = WORD(0); 44 45 ret = fp_init(&base, out->ctx); EG(ret, err); 46 ret = fp_copy(&base, out); EG(ret, err); 47 ret = _fp_pow(out, &base, exp); EG(ret, err); 48 49 err: 50 fp_uninit(&base); 51 52 return ret; 53 } 54 55 /* 56 * Compute out = base^exp (p). 'base', 'exp' and 'out' are supposed to be initialized. 57 * Aliased version of previous one. 58 * 59 * Aliasing is supported. 60 */ 61 int fp_pow(fp_t out, fp_src_t base, nn_src_t exp) 62 { 63 int ret; 64 65 ret = fp_check_initialized(base); EG(ret, err); 66 ret = nn_check_initialized(exp); EG(ret, err); 67 ret = fp_check_initialized(out); EG(ret, err); 68 MUST_HAVE(((&(out->ctx->p)) == (&(base->ctx->p))), ret, err); 69 70 /* Handle output aliasing */ 71 if (out == base) { 72 ret = _fp_pow_aliased(out, exp); 73 } else { 74 ret = _fp_pow(out, base, exp); 75 } 76 77 err: 78 return ret; 79 } 80