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 */
_fp_pow(fp_t out,fp_src_t base,nn_src_t exp)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 */
_fp_pow_aliased(fp_t out,nn_src_t exp)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 */
fp_pow(fp_t out,fp_src_t base,nn_src_t exp)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