1/*
2 * cczp.h
3 * corecrypto
4 *
5 * Created on 11/16/2010
6 *
7 * Copyright (c) 2010,2011,2012,2013,2014,2015 Apple Inc. All rights reserved.
8 *
9 */
10
11#ifndef _CORECRYPTO_CCZP_H_
12#define _CORECRYPTO_CCZP_H_
13
14#include <corecrypto/ccn.h>
15#include <corecrypto/ccrng.h>
16
17/*
18 Don't use cczp_hd struct directly, except in static tables such as eliptic curve parameter
19 definitions.
20
21 Declare cczp objects using cczp_decl_n(). It allocates cc_unit arrays of the length returned by
22 either cczp_nof_n() or cczp_short_nof_n().
23*/
24
25struct cczp;
26
27typedef struct cczp *cczp_t;
28typedef const struct cczp *cczp_const_t;
29
30typedef void (*ccmod_func_t)(cc_ws_t ws, cczp_const_t zp, cc_unit *r, const cc_unit *s);
31
32// keep cczp_hd and cczp structures consistent
33// cczp_hd is typecasted to cczp to read EC curve params
34// options field is to specify Montgomery arithmetic, bit field, etc
35// make sure n is the first element see ccrsa_ctx_n macro
36#define __CCZP_HEADER_ELEMENTS_DEFINITIONS(pre) \
37 cc_size pre##n; \
38 cc_unit pre##options; \
39 ccmod_func_t pre##mod_prime;
40
41#define __CCZP_ELEMENTS_DEFINITIONS(pre) \
42 __CCZP_HEADER_ELEMENTS_DEFINITIONS(pre) \
43 cc_unit pre##ccn[];
44
45// cczp_hd must be defined separetly without variable length array ccn[], because it is used in
46// sructures such as ccdh_gp_decl_n
47struct cczp_hd {
48 __CCZP_HEADER_ELEMENTS_DEFINITIONS()
49} CC_ALIGNED(CCN_UNIT_SIZE);
50
51struct cczp {
52 __CCZP_ELEMENTS_DEFINITIONS()
53} CC_ALIGNED(CCN_UNIT_SIZE);
54
55/* Return the size of an cczp where each ccn is _size_ bytes. */
56#define cczp_size(_size_) (sizeof(struct cczp) + ccn_sizeof_n(1) + 2 * (_size_))
57
58/* Return number of units that a struct cczp needs to be in units for a prime
59 size of N units. This is large enough for all operations. */
60#define cczp_nof_n(_n_) (ccn_nof_size(sizeof(struct cczp)) + 1 + 2 * (_n_))
61
62/* Return number of units that a struct cczp needs to be in units for a prime
63 size of _n_ units. The _short variant does not have room for CCZP_RECIP,
64 so it can not be used with cczp_mod, cczp_mul, cczp_sqr. It can be used
65 with cczp_add, cczp_sub, cczp_div2, cczp_mod_inv. */
66#define cczp_short_nof_n(_n_) (ccn_nof_size(sizeof(struct cczp)) + (_n_))
67
68#define cczp_decl_n(_n_, _name_) cc_ctx_decl(struct cczp, ccn_sizeof_n(cczp_nof_n(_n_)), _name_)
69#define cczp_short_decl_n(_n_, _name_) \
70 cc_ctx_decl(struct cczp_short, ccn_sizeof_n(cczp_short_nof_n(_n_)), _name_)
71
72#define cczp_clear_n(_n_, _name_) cc_clear(ccn_sizeof_n(cczp_nof_n(_n_)), _name_)
73#define cczp_short_clear_n(_n_, _name_) cc_clear(ccn_sizeof_n(cczp_short_nof_n(_n_)), _name_)
74
75#define CCZP_N(ZP) ((ZP)->n)
76#define CCZP_MOD(ZP) ((ZP)->mod_prime)
77#define CCZP_MOD_PRIME(ZP) CCZP_MOD(ZP)
78#define CCZP_PRIME(ZP) ((ZP)->ccn)
79#define CCZP_RECIP(ZP) ((ZP)->ccn + CCZP_N(ZP))
80#define CCZP_OPS(ZP) ((ZP)->options)
81CC_CONST CC_NONNULL((1)) static inline cc_size cczp_n(cczp_const_t zp)
82{
83 return zp->n;
84}
85
86CC_CONST CC_NONNULL((1)) static inline cc_unit cczp_options(cczp_const_t zp)
87{
88 return zp->options;
89}
90
91CC_CONST CC_NONNULL((1)) static inline ccmod_func_t cczp_mod_prime(cczp_const_t zp)
92{
93 return zp->mod_prime;
94}
95
96CC_CONST CC_NONNULL((1)) static inline const cc_unit *cczp_prime(cczp_const_t zp)
97{
98 return zp->ccn;
99}
100
101/* Return a pointer to the Reciprocal or Montgomery constant of zp, which is
102 allocated cczp_n(zp) + 1 units long. */
103CC_CONST CC_NONNULL((1))
104
105 static inline const cc_unit *cczp_recip(cczp_const_t zp)
106{
107 return zp->ccn + zp->n;
108}
109
110CC_CONST CC_NONNULL((1)) CC_INLINE size_t cczp_bitlen(cczp_const_t zp)
111{
112 return ccn_bitlen(cczp_n(zp), cczp_prime(zp));
113}
114
115/* Ensure both cczp_mod_prime(zp) and cczp_recip(zp) are valid. cczp_n and
116 cczp_prime must have been previously initialized. */
117CC_NONNULL((1))
118int cczp_init(cczp_t zp);
119
120/* Compute r = s2n mod cczp_prime(zp). Will write cczp_n(zp)
121 units to r and reads 2 * cczp_n(zp) units units from s2n. If r and s2n are not
122 identical they must not overlap. Before calling this function either
123 cczp_init(zp) must have been called or both CCZP_MOD_PRIME((cc_unit *)zp)
124 and CCZP_RECIP((cc_unit *)zp) must be initialized some other way. */
125CC_NONNULL((1, 2, 3)) void cczp_mod(cc_ws_t ws, cczp_const_t zp, cc_unit *r, const cc_unit *s2n);
126
127/* Compute r = sn mod cczp_prime(zp), Will write cczp_n(zp)
128 units to r and reads sn units units from s. If r and s are not
129 identical they must not overlap. Before calling this function either
130 cczp_init(zp) must have been called or both CCZP_MOD_PRIME((cc_unit *)zp)
131 and CCZP_RECIP((cc_unit *)zp) must be initialized some other way. */
132CC_NONNULL((1, 2, 4)) int cczp_modn(cczp_const_t zp, cc_unit *r, cc_size ns, const cc_unit *s);
133
134/* Compute r = x * y mod cczp_prime(zp). Will write cczp_n(zp) units to r
135 and reads cczp_n(zp) units units from both x and y. If r and x are not
136 identical they must not overlap, The same holds for r and y. Before
137 calling this function either cczp_init(zp) must have been called or both
138 CCZP_MOD_PRIME((cc_unit *)zp) and CCZP_RECIP((cc_unit *)zp) must be
139 initialized some other way. */
140CC_NONNULL((1, 2, 3, 4))
141void cczp_mul(cczp_const_t zp, cc_unit *t, const cc_unit *x, const cc_unit *y);
142
143/* Compute r = m ^ e mod cczp_prime(zp), using Montgomery ladder.
144 - writes cczp_n(zp) units to r
145 - reads cczp_n(zp) units units from m and e
146 - if r and m are not identical they must not overlap.
147 - r and e must not overlap nor be identical.
148 - before calling this function either cczp_init(zp) must have been called
149 or both CCZP_MOD_PRIME((cc_unit *)zp) and CCZP_RECIP((cc_unit *)zp) must
150 be initialized some other way.
151 */
152CC_NONNULL((1, 2, 3, 4))
153int cczp_power(cczp_const_t zp, cc_unit *r, const cc_unit *m, const cc_unit *e);
154
155/* Compute r = m ^ e mod cczp_prime(zp), using Square Square Multiply Always.
156 - writes cczp_n(zp) units to r
157 - reads cczp_n(zp) units units from m and e
158 - if r and m are not identical they must not overlap.
159 - r and e must not overlap nor be identical.
160 - before calling this function either cczp_init(zp) must have been called
161 or both CCZP_MOD_PRIME((cc_unit *)zp) and CCZP_RECIP((cc_unit *)zp) must
162 be initialized some other way.
163
164 Important: This function is intented to be constant time but is more likely
165 to leak information due to memory cache. Only used with randomized input
166 */
167CC_NONNULL((1, 2, 3, 4))
168int cczp_power_ssma(cczp_const_t zp, cc_unit *r, const cc_unit *m, const cc_unit *e);
169
170/*!
171 @brief cczp_inv(zp, r, x) computes r = x^-1 (mod p) , where p=cczp_prime(zp).
172 @discussion It is a general function and works for any p. It validates the inputs. r and x can
173 overlap. It writes n =cczp_n(zp) units to r, and read n units units from x and p. The output r is
174 overwriten only if the inverse is correctly computed. This function is not constant time in
175 absolute sense, but it does not have data dependent 'if' statements in the code.
176 @param zp The input zp. cczp_n(zp) and cczp_prime(zp) need to be valid. cczp_init(zp) need not to
177 be called before invoking cczp_inv().
178 @param x input big integer
179 @param r output big integer
180 @return 0 if inverse exists and correctly computed.
181 */
182CC_NONNULL((1, 2, 3))
183int cczp_inv(cczp_const_t zp, cc_unit *r, const cc_unit *x);
184
185/*!
186 @brief cczp_inv_odd(zp, r, x) computes r = x^-1 (mod p) , where p=cczp_prime(zp) is an odd number.
187 @discussion r and x can overlap.
188 @param zp The input zp. cczp_n(zp) and cczp_prime(zp) need to be valid. cczp_init(zp) need not to
189 be called before invoking.
190 @param x input big integer
191 @param r output big integer
192 @return 0 if successful
193 */
194CC_NONNULL((1, 2, 3)) int cczp_inv_odd(cczp_const_t zp, cc_unit *r, const cc_unit *x);
195
196/*!
197 @brief cczp_inv_field(zp, r, x) computes r = x^-1 (mod p) , where p=cczp_prime(zp) is a prime
198 number number.
199 @discussion r and x must NOT overlap. The excution time of the function is independent to the value
200 of the input x. It works only if p is a field. That is, when p is a prime. It supports Montgomery
201 and non-Montgomery form of zp. It leaks the value of the prime and should only be used be used for
202 public (not secret) primes (ex. Elliptic Curves)
203
204 @param zp The input zp. cczp_n(zp) and cczp_prime(zp) need to be valid. cczp_init(zp) need not to
205 be called before invoking cczp_inv_field().
206 @param x input big unteger
207 @param r output big integer
208 @return 0 if inverse exists and correctly computed.
209 */
210CC_NONNULL((1, 2, 3))
211int cczp_inv_field(cczp_const_t zp, cc_unit *r, const cc_unit *x);
212
213#endif /* _CORECRYPTO_CCZP_H_ */
214