/ external / libecc / src / fp / fp_pow.c
fp_pow.c
 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  }