]>
Commit | Line | Data |
---|---|---|
71712b27 GM |
1 | /********************************************************************** |
2 | * Copyright (c) 2013, 2014 Pieter Wuille * | |
3 | * Distributed under the MIT software license, see the accompanying * | |
4 | * file COPYING or http://www.opensource.org/licenses/mit-license.php.* | |
5 | **********************************************************************/ | |
0a433ea2 | 6 | |
b394396b PW |
7 | #ifndef _SECP256K1_GROUP_ |
8 | #define _SECP256K1_GROUP_ | |
9 | ||
607884fc | 10 | #include "num.h" |
b394396b PW |
11 | #include "field.h" |
12 | ||
7fef6619 | 13 | /** A group element of the secp256k1 curve, in affine coordinates. */ |
254327e4 PW |
14 | typedef struct { |
15 | secp256k1_fe_t x; | |
16 | secp256k1_fe_t y; | |
71712b27 | 17 | int infinity; /* whether this represents the point at infinity */ |
254327e4 PW |
18 | } secp256k1_ge_t; |
19 | ||
443cd4b8 PW |
20 | #define SECP256K1_GE_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_CONST((i),(j),(k),(l),(m),(n),(o),(p)), 0} |
21 | #define SECP256K1_GE_CONST_INFINITY {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), 1} | |
22 | ||
7fef6619 | 23 | /** A group element of the secp256k1 curve, in jacobian coordinates. */ |
254327e4 | 24 | typedef struct { |
71712b27 GM |
25 | secp256k1_fe_t x; /* actual X: x/z^2 */ |
26 | secp256k1_fe_t y; /* actual Y: y/z^3 */ | |
254327e4 | 27 | secp256k1_fe_t z; |
71712b27 | 28 | int infinity; /* whether this represents the point at infinity */ |
254327e4 PW |
29 | } secp256k1_gej_t; |
30 | ||
443cd4b8 PW |
31 | #define SECP256K1_GEJ_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_CONST((i),(j),(k),(l),(m),(n),(o),(p)), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1), 0} |
32 | #define SECP256K1_GEJ_CONST_INFINITY {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), 1} | |
33 | ||
e68d7208 PW |
34 | typedef struct { |
35 | secp256k1_fe_storage_t x; | |
36 | secp256k1_fe_storage_t y; | |
37 | } secp256k1_ge_storage_t; | |
38 | ||
443cd4b8 PW |
39 | #define SECP256K1_GE_STORAGE_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_STORAGE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_STORAGE_CONST((i),(j),(k),(l),(m),(n),(o),(p))} |
40 | ||
fbecc38a TD |
41 | #define SECP256K1_GE_STORAGE_CONST_GET(t) SECP256K1_FE_STORAGE_CONST_GET(t.x), SECP256K1_FE_STORAGE_CONST_GET(t.y) |
42 | ||
7fef6619 | 43 | /** Set a group element equal to the point at infinity */ |
a4a43d75 | 44 | static void secp256k1_ge_set_infinity(secp256k1_ge_t *r); |
7fef6619 PW |
45 | |
46 | /** Set a group element equal to the point with given X and Y coordinates */ | |
a4a43d75 | 47 | static void secp256k1_ge_set_xy(secp256k1_ge_t *r, const secp256k1_fe_t *x, const secp256k1_fe_t *y); |
7fef6619 | 48 | |
09ca4f32 PD |
49 | /** Set a group element (affine) equal to the point with the given X coordinate, and given oddness |
50 | * for Y. Return value indicates whether the result is valid. */ | |
39bd94d8 | 51 | static int secp256k1_ge_set_xo_var(secp256k1_ge_t *r, const secp256k1_fe_t *x, int odd); |
764332d0 | 52 | |
7fef6619 | 53 | /** Check whether a group element is the point at infinity. */ |
a4a43d75 | 54 | static int secp256k1_ge_is_infinity(const secp256k1_ge_t *a); |
7fef6619 | 55 | |
764332d0 | 56 | /** Check whether a group element is valid (i.e., on the curve). */ |
39bd94d8 | 57 | static int secp256k1_ge_is_valid_var(const secp256k1_ge_t *a); |
764332d0 | 58 | |
a4a43d75 | 59 | static void secp256k1_ge_neg(secp256k1_ge_t *r, const secp256k1_ge_t *a); |
7fef6619 | 60 | |
7fef6619 | 61 | /** Set a group element equal to another which is given in jacobian coordinates */ |
a4a43d75 | 62 | static void secp256k1_ge_set_gej(secp256k1_ge_t *r, secp256k1_gej_t *a); |
254327e4 | 63 | |
f16be77f | 64 | /** Set a batch of group elements equal to the inputs given in jacobian coordinates */ |
995c5487 | 65 | static void secp256k1_ge_set_all_gej_var(size_t len, secp256k1_ge_t *r, const secp256k1_gej_t *a, const callback_t *cb); |
f16be77f | 66 | |
4f9791ab PD |
67 | /** Set a batch of group elements equal to the inputs given in jacobian |
68 | * coordinates (with known z-ratios). zr must contain the known z-ratios such | |
69 | * that mul(a[i].z, zr[i+1]) == a[i+1].z. zr[0] is ignored. */ | |
70 | static void secp256k1_ge_set_table_gej_var(size_t len, secp256k1_ge_t *r, const secp256k1_gej_t *a, const secp256k1_fe_t *zr); | |
71 | ||
72 | /** Bring a batch inputs given in jacobian coordinates (with known z-ratios) to | |
73 | * the same global z "denominator". zr must contain the known z-ratios such | |
74 | * that mul(a[i].z, zr[i+1]) == a[i+1].z. zr[0] is ignored. The x and y | |
75 | * coordinates of the result are stored in r, the common z coordinate is | |
76 | * stored in globalz. */ | |
77 | static void secp256k1_ge_globalz_set_table_gej(size_t len, secp256k1_ge_t *r, secp256k1_fe_t *globalz, const secp256k1_gej_t *a, const secp256k1_fe_t *zr); | |
7fef6619 PW |
78 | |
79 | /** Set a group element (jacobian) equal to the point at infinity. */ | |
a4a43d75 | 80 | static void secp256k1_gej_set_infinity(secp256k1_gej_t *r); |
7fef6619 PW |
81 | |
82 | /** Set a group element (jacobian) equal to the point with given X and Y coordinates. */ | |
a4a43d75 | 83 | static void secp256k1_gej_set_xy(secp256k1_gej_t *r, const secp256k1_fe_t *x, const secp256k1_fe_t *y); |
7fef6619 | 84 | |
7fef6619 | 85 | /** Set a group element (jacobian) equal to another which is given in affine coordinates. */ |
a4a43d75 | 86 | static void secp256k1_gej_set_ge(secp256k1_gej_t *r, const secp256k1_ge_t *a); |
7fef6619 | 87 | |
ce7eb6fb PW |
88 | /** Compare the X coordinate of a group element (jacobian). */ |
89 | static int secp256k1_gej_eq_x_var(const secp256k1_fe_t *x, const secp256k1_gej_t *a); | |
7fef6619 PW |
90 | |
91 | /** Set r equal to the inverse of a (i.e., mirrored around the X axis) */ | |
0295f0a3 | 92 | static void secp256k1_gej_neg(secp256k1_gej_t *r, const secp256k1_gej_t *a); |
7fef6619 PW |
93 | |
94 | /** Check whether a group element is the point at infinity. */ | |
a4a43d75 | 95 | static int secp256k1_gej_is_infinity(const secp256k1_gej_t *a); |
7fef6619 | 96 | |
44015000 AP |
97 | /** Set r equal to the double of a. If rzr is not-NULL, r->z = a->z * *rzr (where infinity means an implicit z = 0). |
98 | * a may not be zero. Constant time. */ | |
99 | static void secp256k1_gej_double_nonzero(secp256k1_gej_t *r, const secp256k1_gej_t *a, secp256k1_fe_t *rzr); | |
100 | ||
4f9791ab PD |
101 | /** Set r equal to the double of a. If rzr is not-NULL, r->z = a->z * *rzr (where infinity means an implicit z = 0). */ |
102 | static void secp256k1_gej_double_var(secp256k1_gej_t *r, const secp256k1_gej_t *a, secp256k1_fe_t *rzr); | |
7fef6619 | 103 | |
4f9791ab PD |
104 | /** Set r equal to the sum of a and b. If rzr is non-NULL, r->z = a->z * *rzr (a cannot be infinity in that case). */ |
105 | static void secp256k1_gej_add_var(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_gej_t *b, secp256k1_fe_t *rzr); | |
7fef6619 | 106 | |
9338dbf7 | 107 | /** Set r equal to the sum of a and b (with b given in affine coordinates, and not infinity). */ |
a4a43d75 | 108 | static void secp256k1_gej_add_ge(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_ge_t *b); |
9338dbf7 | 109 | |
09ca4f32 | 110 | /** Set r equal to the sum of a and b (with b given in affine coordinates). This is more efficient |
9338dbf7 | 111 | than secp256k1_gej_add_var. It is identical to secp256k1_gej_add_ge but without constant-time |
2d5a186c PD |
112 | guarantee, and b is allowed to be infinity. If rzr is non-NULL, r->z = a->z * *rzr (a cannot be infinity in that case). */ |
113 | static void secp256k1_gej_add_ge_var(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_ge_t *b, secp256k1_fe_t *rzr); | |
7fef6619 | 114 | |
4f9791ab PD |
115 | /** Set r equal to the sum of a and b (with the inverse of b's Z coordinate passed as bzinv). */ |
116 | static void secp256k1_gej_add_zinv_var(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_ge_t *b, const secp256k1_fe_t *bzinv); | |
117 | ||
399c03f2 | 118 | #ifdef USE_ENDOMORPHISM |
7fef6619 | 119 | /** Set r to be equal to lambda times a, where lambda is chosen in a way such that this is very fast. */ |
4f9791ab | 120 | static void secp256k1_ge_mul_lambda(secp256k1_ge_t *r, const secp256k1_ge_t *a); |
399c03f2 | 121 | #endif |
254327e4 | 122 | |
2f6c8019 | 123 | /** Clear a secp256k1_gej_t to prevent leaking sensitive information. */ |
a4a43d75 | 124 | static void secp256k1_gej_clear(secp256k1_gej_t *r); |
2f6c8019 GM |
125 | |
126 | /** Clear a secp256k1_ge_t to prevent leaking sensitive information. */ | |
a4a43d75 | 127 | static void secp256k1_ge_clear(secp256k1_ge_t *r); |
2f6c8019 | 128 | |
e68d7208 PW |
129 | /** Convert a group element to the storage type. */ |
130 | static void secp256k1_ge_to_storage(secp256k1_ge_storage_t *r, const secp256k1_ge_t*); | |
131 | ||
132 | /** Convert a group element back from the storage type. */ | |
133 | static void secp256k1_ge_from_storage(secp256k1_ge_t *r, const secp256k1_ge_storage_t*); | |
134 | ||
55422b6a PW |
135 | /** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */ |
136 | static void secp256k1_ge_storage_cmov(secp256k1_ge_storage_t *r, const secp256k1_ge_storage_t *a, int flag); | |
137 | ||
d2275795 GM |
138 | /** Rescale a jacobian point by b which must be non-zero. Constant-time. */ |
139 | static void secp256k1_gej_rescale(secp256k1_gej_t *r, const secp256k1_fe_t *b); | |
140 | ||
b394396b | 141 | #endif |