grpc 1.10.0.pre1 → 1.10.0.pre2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of grpc might be problematic. Click here for more details.

Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +3 -3
  3. data/src/core/ext/filters/max_age/max_age_filter.cc +3 -0
  4. data/src/core/lib/surface/version.cc +1 -1
  5. data/src/ruby/lib/grpc/version.rb +1 -1
  6. data/third_party/boringssl/crypto/fipsmodule/aes/aes.c +1100 -0
  7. data/third_party/boringssl/crypto/fipsmodule/aes/key_wrap.c +138 -0
  8. data/third_party/boringssl/crypto/fipsmodule/aes/mode_wrappers.c +112 -0
  9. data/third_party/boringssl/crypto/fipsmodule/bn/add.c +375 -0
  10. data/third_party/boringssl/crypto/fipsmodule/bn/asm/x86_64-gcc.c +537 -0
  11. data/third_party/boringssl/crypto/fipsmodule/bn/bn.c +370 -0
  12. data/third_party/boringssl/crypto/fipsmodule/bn/bytes.c +269 -0
  13. data/third_party/boringssl/crypto/fipsmodule/bn/cmp.c +239 -0
  14. data/third_party/boringssl/crypto/fipsmodule/bn/ctx.c +303 -0
  15. data/third_party/boringssl/crypto/fipsmodule/bn/div.c +726 -0
  16. data/third_party/boringssl/crypto/fipsmodule/bn/exponentiation.c +1233 -0
  17. data/third_party/boringssl/crypto/fipsmodule/bn/gcd.c +627 -0
  18. data/third_party/boringssl/crypto/fipsmodule/bn/generic.c +715 -0
  19. data/third_party/boringssl/crypto/fipsmodule/bn/jacobi.c +146 -0
  20. data/third_party/boringssl/crypto/fipsmodule/bn/montgomery.c +430 -0
  21. data/third_party/boringssl/crypto/fipsmodule/bn/montgomery_inv.c +207 -0
  22. data/third_party/boringssl/crypto/fipsmodule/bn/mul.c +869 -0
  23. data/third_party/boringssl/crypto/fipsmodule/bn/prime.c +894 -0
  24. data/third_party/boringssl/crypto/fipsmodule/bn/random.c +283 -0
  25. data/third_party/boringssl/crypto/fipsmodule/bn/rsaz_exp.c +254 -0
  26. data/third_party/boringssl/crypto/fipsmodule/bn/shift.c +307 -0
  27. data/third_party/boringssl/crypto/fipsmodule/bn/sqrt.c +502 -0
  28. data/third_party/boringssl/crypto/fipsmodule/cipher/aead.c +284 -0
  29. data/third_party/boringssl/crypto/fipsmodule/cipher/cipher.c +613 -0
  30. data/third_party/boringssl/crypto/fipsmodule/cipher/e_aes.c +1437 -0
  31. data/third_party/boringssl/crypto/fipsmodule/cipher/e_des.c +233 -0
  32. data/third_party/boringssl/crypto/fipsmodule/des/des.c +785 -0
  33. data/third_party/boringssl/crypto/fipsmodule/digest/digest.c +256 -0
  34. data/third_party/boringssl/crypto/fipsmodule/digest/digests.c +280 -0
  35. data/third_party/boringssl/crypto/fipsmodule/ec/ec.c +842 -0
  36. data/third_party/boringssl/crypto/fipsmodule/ec/ec_key.c +517 -0
  37. data/third_party/boringssl/crypto/fipsmodule/ec/ec_montgomery.c +304 -0
  38. data/third_party/boringssl/crypto/fipsmodule/ec/oct.c +404 -0
  39. data/third_party/boringssl/crypto/fipsmodule/ec/p224-64.c +1165 -0
  40. data/third_party/boringssl/crypto/fipsmodule/ec/p256-64.c +1708 -0
  41. data/third_party/boringssl/crypto/fipsmodule/ec/p256-x86_64.c +561 -0
  42. data/third_party/boringssl/crypto/fipsmodule/ec/simple.c +1113 -0
  43. data/third_party/boringssl/crypto/fipsmodule/ec/util-64.c +109 -0
  44. data/third_party/boringssl/crypto/fipsmodule/ec/wnaf.c +456 -0
  45. data/third_party/boringssl/crypto/fipsmodule/ecdsa/ecdsa.c +444 -0
  46. data/third_party/boringssl/crypto/fipsmodule/hmac/hmac.c +228 -0
  47. data/third_party/boringssl/crypto/fipsmodule/md4/md4.c +254 -0
  48. data/third_party/boringssl/crypto/fipsmodule/md5/md5.c +298 -0
  49. data/third_party/boringssl/crypto/fipsmodule/modes/cbc.c +212 -0
  50. data/third_party/boringssl/crypto/fipsmodule/modes/cfb.c +230 -0
  51. data/third_party/boringssl/crypto/fipsmodule/modes/ctr.c +219 -0
  52. data/third_party/boringssl/crypto/fipsmodule/modes/gcm.c +1074 -0
  53. data/third_party/boringssl/crypto/fipsmodule/modes/ofb.c +95 -0
  54. data/third_party/boringssl/crypto/fipsmodule/modes/polyval.c +91 -0
  55. data/third_party/boringssl/crypto/fipsmodule/rand/ctrdrbg.c +200 -0
  56. data/third_party/boringssl/crypto/fipsmodule/rand/rand.c +358 -0
  57. data/third_party/boringssl/crypto/fipsmodule/rand/urandom.c +302 -0
  58. data/third_party/boringssl/crypto/fipsmodule/rsa/blinding.c +263 -0
  59. data/third_party/boringssl/crypto/fipsmodule/rsa/padding.c +692 -0
  60. data/third_party/boringssl/crypto/fipsmodule/rsa/rsa.c +855 -0
  61. data/third_party/boringssl/crypto/fipsmodule/rsa/rsa_impl.c +1061 -0
  62. data/third_party/boringssl/crypto/fipsmodule/sha/sha1-altivec.c +361 -0
  63. data/third_party/boringssl/crypto/fipsmodule/sha/sha1.c +375 -0
  64. data/third_party/boringssl/crypto/fipsmodule/sha/sha256.c +337 -0
  65. data/third_party/boringssl/crypto/fipsmodule/sha/sha512.c +608 -0
  66. metadata +62 -2
@@ -0,0 +1,1165 @@
1
+ /* Copyright (c) 2015, Google Inc.
2
+ *
3
+ * Permission to use, copy, modify, and/or distribute this software for any
4
+ * purpose with or without fee is hereby granted, provided that the above
5
+ * copyright notice and this permission notice appear in all copies.
6
+ *
7
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14
+
15
+ // A 64-bit implementation of the NIST P-224 elliptic curve point multiplication
16
+ //
17
+ // Inspired by Daniel J. Bernstein's public domain nistp224 implementation
18
+ // and Adam Langley's public domain 64-bit C implementation of curve25519.
19
+
20
+ #include <openssl/base.h>
21
+
22
+ #if defined(OPENSSL_64_BIT) && !defined(OPENSSL_WINDOWS) && \
23
+ !defined(OPENSSL_SMALL)
24
+
25
+ #include <openssl/bn.h>
26
+ #include <openssl/ec.h>
27
+ #include <openssl/err.h>
28
+ #include <openssl/mem.h>
29
+
30
+ #include <string.h>
31
+
32
+ #include "internal.h"
33
+ #include "../delocate.h"
34
+ #include "../../internal.h"
35
+
36
+
37
+ // Field elements are represented as a_0 + 2^56*a_1 + 2^112*a_2 + 2^168*a_3
38
+ // using 64-bit coefficients called 'limbs', and sometimes (for multiplication
39
+ // results) as b_0 + 2^56*b_1 + 2^112*b_2 + 2^168*b_3 + 2^224*b_4 + 2^280*b_5 +
40
+ // 2^336*b_6 using 128-bit coefficients called 'widelimbs'. A 4-p224_limb
41
+ // representation is an 'p224_felem'; a 7-p224_widelimb representation is a
42
+ // 'p224_widefelem'. Even within felems, bits of adjacent limbs overlap, and we
43
+ // don't always reduce the representations: we ensure that inputs to each
44
+ // p224_felem multiplication satisfy a_i < 2^60, so outputs satisfy b_i <
45
+ // 4*2^60*2^60, and fit into a 128-bit word without overflow. The coefficients
46
+ // are then again partially reduced to obtain an p224_felem satisfying a_i <
47
+ // 2^57. We only reduce to the unique minimal representation at the end of the
48
+ // computation.
49
+
50
+ typedef uint64_t p224_limb;
51
+ typedef uint128_t p224_widelimb;
52
+
53
+ typedef p224_limb p224_felem[4];
54
+ typedef p224_widelimb p224_widefelem[7];
55
+
56
+ // Field element represented as a byte arrary. 28*8 = 224 bits is also the
57
+ // group order size for the elliptic curve, and we also use this type for
58
+ // scalars for point multiplication.
59
+ typedef uint8_t p224_felem_bytearray[28];
60
+
61
+ // Precomputed multiples of the standard generator
62
+ // Points are given in coordinates (X, Y, Z) where Z normally is 1
63
+ // (0 for the point at infinity).
64
+ // For each field element, slice a_0 is word 0, etc.
65
+ //
66
+ // The table has 2 * 16 elements, starting with the following:
67
+ // index | bits | point
68
+ // ------+---------+------------------------------
69
+ // 0 | 0 0 0 0 | 0G
70
+ // 1 | 0 0 0 1 | 1G
71
+ // 2 | 0 0 1 0 | 2^56G
72
+ // 3 | 0 0 1 1 | (2^56 + 1)G
73
+ // 4 | 0 1 0 0 | 2^112G
74
+ // 5 | 0 1 0 1 | (2^112 + 1)G
75
+ // 6 | 0 1 1 0 | (2^112 + 2^56)G
76
+ // 7 | 0 1 1 1 | (2^112 + 2^56 + 1)G
77
+ // 8 | 1 0 0 0 | 2^168G
78
+ // 9 | 1 0 0 1 | (2^168 + 1)G
79
+ // 10 | 1 0 1 0 | (2^168 + 2^56)G
80
+ // 11 | 1 0 1 1 | (2^168 + 2^56 + 1)G
81
+ // 12 | 1 1 0 0 | (2^168 + 2^112)G
82
+ // 13 | 1 1 0 1 | (2^168 + 2^112 + 1)G
83
+ // 14 | 1 1 1 0 | (2^168 + 2^112 + 2^56)G
84
+ // 15 | 1 1 1 1 | (2^168 + 2^112 + 2^56 + 1)G
85
+ // followed by a copy of this with each element multiplied by 2^28.
86
+ //
87
+ // The reason for this is so that we can clock bits into four different
88
+ // locations when doing simple scalar multiplies against the base point,
89
+ // and then another four locations using the second 16 elements.
90
+ static const p224_felem g_p224_pre_comp[2][16][3] = {
91
+ {{{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}},
92
+ {{0x3280d6115c1d21, 0xc1d356c2112234, 0x7f321390b94a03, 0xb70e0cbd6bb4bf},
93
+ {0xd5819985007e34, 0x75a05a07476444, 0xfb4c22dfe6cd43, 0xbd376388b5f723},
94
+ {1, 0, 0, 0}},
95
+ {{0xfd9675666ebbe9, 0xbca7664d40ce5e, 0x2242df8d8a2a43, 0x1f49bbb0f99bc5},
96
+ {0x29e0b892dc9c43, 0xece8608436e662, 0xdc858f185310d0, 0x9812dd4eb8d321},
97
+ {1, 0, 0, 0}},
98
+ {{0x6d3e678d5d8eb8, 0x559eed1cb362f1, 0x16e9a3bbce8a3f, 0xeedcccd8c2a748},
99
+ {0xf19f90ed50266d, 0xabf2b4bf65f9df, 0x313865468fafec, 0x5cb379ba910a17},
100
+ {1, 0, 0, 0}},
101
+ {{0x0641966cab26e3, 0x91fb2991fab0a0, 0xefec27a4e13a0b, 0x0499aa8a5f8ebe},
102
+ {0x7510407766af5d, 0x84d929610d5450, 0x81d77aae82f706, 0x6916f6d4338c5b},
103
+ {1, 0, 0, 0}},
104
+ {{0xea95ac3b1f15c6, 0x086000905e82d4, 0xdd323ae4d1c8b1, 0x932b56be7685a3},
105
+ {0x9ef93dea25dbbf, 0x41665960f390f0, 0xfdec76dbe2a8a7, 0x523e80f019062a},
106
+ {1, 0, 0, 0}},
107
+ {{0x822fdd26732c73, 0xa01c83531b5d0f, 0x363f37347c1ba4, 0xc391b45c84725c},
108
+ {0xbbd5e1b2d6ad24, 0xddfbcde19dfaec, 0xc393da7e222a7f, 0x1efb7890ede244},
109
+ {1, 0, 0, 0}},
110
+ {{0x4c9e90ca217da1, 0xd11beca79159bb, 0xff8d33c2c98b7c, 0x2610b39409f849},
111
+ {0x44d1352ac64da0, 0xcdbb7b2c46b4fb, 0x966c079b753c89, 0xfe67e4e820b112},
112
+ {1, 0, 0, 0}},
113
+ {{0xe28cae2df5312d, 0xc71b61d16f5c6e, 0x79b7619a3e7c4c, 0x05c73240899b47},
114
+ {0x9f7f6382c73e3a, 0x18615165c56bda, 0x641fab2116fd56, 0x72855882b08394},
115
+ {1, 0, 0, 0}},
116
+ {{0x0469182f161c09, 0x74a98ca8d00fb5, 0xb89da93489a3e0, 0x41c98768fb0c1d},
117
+ {0xe5ea05fb32da81, 0x3dce9ffbca6855, 0x1cfe2d3fbf59e6, 0x0e5e03408738a7},
118
+ {1, 0, 0, 0}},
119
+ {{0xdab22b2333e87f, 0x4430137a5dd2f6, 0xe03ab9f738beb8, 0xcb0c5d0dc34f24},
120
+ {0x764a7df0c8fda5, 0x185ba5c3fa2044, 0x9281d688bcbe50, 0xc40331df893881},
121
+ {1, 0, 0, 0}},
122
+ {{0xb89530796f0f60, 0xade92bd26909a3, 0x1a0c83fb4884da, 0x1765bf22a5a984},
123
+ {0x772a9ee75db09e, 0x23bc6c67cec16f, 0x4c1edba8b14e2f, 0xe2a215d9611369},
124
+ {1, 0, 0, 0}},
125
+ {{0x571e509fb5efb3, 0xade88696410552, 0xc8ae85fada74fe, 0x6c7e4be83bbde3},
126
+ {0xff9f51160f4652, 0xb47ce2495a6539, 0xa2946c53b582f4, 0x286d2db3ee9a60},
127
+ {1, 0, 0, 0}},
128
+ {{0x40bbd5081a44af, 0x0995183b13926c, 0xbcefba6f47f6d0, 0x215619e9cc0057},
129
+ {0x8bc94d3b0df45e, 0xf11c54a3694f6f, 0x8631b93cdfe8b5, 0xe7e3f4b0982db9},
130
+ {1, 0, 0, 0}},
131
+ {{0xb17048ab3e1c7b, 0xac38f36ff8a1d8, 0x1c29819435d2c6, 0xc813132f4c07e9},
132
+ {0x2891425503b11f, 0x08781030579fea, 0xf5426ba5cc9674, 0x1e28ebf18562bc},
133
+ {1, 0, 0, 0}},
134
+ {{0x9f31997cc864eb, 0x06cd91d28b5e4c, 0xff17036691a973, 0xf1aef351497c58},
135
+ {0xdd1f2d600564ff, 0xdead073b1402db, 0x74a684435bd693, 0xeea7471f962558},
136
+ {1, 0, 0, 0}}},
137
+ {{{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}},
138
+ {{0x9665266dddf554, 0x9613d78b60ef2d, 0xce27a34cdba417, 0xd35ab74d6afc31},
139
+ {0x85ccdd22deb15e, 0x2137e5783a6aab, 0xa141cffd8c93c6, 0x355a1830e90f2d},
140
+ {1, 0, 0, 0}},
141
+ {{0x1a494eadaade65, 0xd6da4da77fe53c, 0xe7992996abec86, 0x65c3553c6090e3},
142
+ {0xfa610b1fb09346, 0xf1c6540b8a4aaf, 0xc51a13ccd3cbab, 0x02995b1b18c28a},
143
+ {1, 0, 0, 0}},
144
+ {{0x7874568e7295ef, 0x86b419fbe38d04, 0xdc0690a7550d9a, 0xd3966a44beac33},
145
+ {0x2b7280ec29132f, 0xbeaa3b6a032df3, 0xdc7dd88ae41200, 0xd25e2513e3a100},
146
+ {1, 0, 0, 0}},
147
+ {{0x924857eb2efafd, 0xac2bce41223190, 0x8edaa1445553fc, 0x825800fd3562d5},
148
+ {0x8d79148ea96621, 0x23a01c3dd9ed8d, 0xaf8b219f9416b5, 0xd8db0cc277daea},
149
+ {1, 0, 0, 0}},
150
+ {{0x76a9c3b1a700f0, 0xe9acd29bc7e691, 0x69212d1a6b0327, 0x6322e97fe154be},
151
+ {0x469fc5465d62aa, 0x8d41ed18883b05, 0x1f8eae66c52b88, 0xe4fcbe9325be51},
152
+ {1, 0, 0, 0}},
153
+ {{0x825fdf583cac16, 0x020b857c7b023a, 0x683c17744b0165, 0x14ffd0a2daf2f1},
154
+ {0x323b36184218f9, 0x4944ec4e3b47d4, 0xc15b3080841acf, 0x0bced4b01a28bb},
155
+ {1, 0, 0, 0}},
156
+ {{0x92ac22230df5c4, 0x52f33b4063eda8, 0xcb3f19870c0c93, 0x40064f2ba65233},
157
+ {0xfe16f0924f8992, 0x012da25af5b517, 0x1a57bb24f723a6, 0x06f8bc76760def},
158
+ {1, 0, 0, 0}},
159
+ {{0x4a7084f7817cb9, 0xbcab0738ee9a78, 0x3ec11e11d9c326, 0xdc0fe90e0f1aae},
160
+ {0xcf639ea5f98390, 0x5c350aa22ffb74, 0x9afae98a4047b7, 0x956ec2d617fc45},
161
+ {1, 0, 0, 0}},
162
+ {{0x4306d648c1be6a, 0x9247cd8bc9a462, 0xf5595e377d2f2e, 0xbd1c3caff1a52e},
163
+ {0x045e14472409d0, 0x29f3e17078f773, 0x745a602b2d4f7d, 0x191837685cdfbb},
164
+ {1, 0, 0, 0}},
165
+ {{0x5b6ee254a8cb79, 0x4953433f5e7026, 0xe21faeb1d1def4, 0xc4c225785c09de},
166
+ {0x307ce7bba1e518, 0x31b125b1036db8, 0x47e91868839e8f, 0xc765866e33b9f3},
167
+ {1, 0, 0, 0}},
168
+ {{0x3bfece24f96906, 0x4794da641e5093, 0xde5df64f95db26, 0x297ecd89714b05},
169
+ {0x701bd3ebb2c3aa, 0x7073b4f53cb1d5, 0x13c5665658af16, 0x9895089d66fe58},
170
+ {1, 0, 0, 0}},
171
+ {{0x0fef05f78c4790, 0x2d773633b05d2e, 0x94229c3a951c94, 0xbbbd70df4911bb},
172
+ {0xb2c6963d2c1168, 0x105f47a72b0d73, 0x9fdf6111614080, 0x7b7e94b39e67b0},
173
+ {1, 0, 0, 0}},
174
+ {{0xad1a7d6efbe2b3, 0xf012482c0da69d, 0x6b3bdf12438345, 0x40d7558d7aa4d9},
175
+ {0x8a09fffb5c6d3d, 0x9a356e5d9ffd38, 0x5973f15f4f9b1c, 0xdcd5f59f63c3ea},
176
+ {1, 0, 0, 0}},
177
+ {{0xacf39f4c5ca7ab, 0x4c8071cc5fd737, 0xc64e3602cd1184, 0x0acd4644c9abba},
178
+ {0x6c011a36d8bf6e, 0xfecd87ba24e32a, 0x19f6f56574fad8, 0x050b204ced9405},
179
+ {1, 0, 0, 0}},
180
+ {{0xed4f1cae7d9a96, 0x5ceef7ad94c40a, 0x778e4a3bf3ef9b, 0x7405783dc3b55e},
181
+ {0x32477c61b6e8c6, 0xb46a97570f018b, 0x91176d0a7e95d1, 0x3df90fbc4c7d0e},
182
+ {1, 0, 0, 0}}}};
183
+
184
+ static uint64_t p224_load_u64(const uint8_t in[8]) {
185
+ uint64_t ret;
186
+ OPENSSL_memcpy(&ret, in, sizeof(ret));
187
+ return ret;
188
+ }
189
+
190
+ // Helper functions to convert field elements to/from internal representation
191
+ static void p224_bin28_to_felem(p224_felem out, const uint8_t in[28]) {
192
+ out[0] = p224_load_u64(in) & 0x00ffffffffffffff;
193
+ out[1] = p224_load_u64(in + 7) & 0x00ffffffffffffff;
194
+ out[2] = p224_load_u64(in + 14) & 0x00ffffffffffffff;
195
+ out[3] = p224_load_u64(in + 20) >> 8;
196
+ }
197
+
198
+ static void p224_felem_to_bin28(uint8_t out[28], const p224_felem in) {
199
+ for (size_t i = 0; i < 7; ++i) {
200
+ out[i] = in[0] >> (8 * i);
201
+ out[i + 7] = in[1] >> (8 * i);
202
+ out[i + 14] = in[2] >> (8 * i);
203
+ out[i + 21] = in[3] >> (8 * i);
204
+ }
205
+ }
206
+
207
+ // To preserve endianness when using BN_bn2bin and BN_bin2bn
208
+ static void p224_flip_endian(uint8_t *out, const uint8_t *in, size_t len) {
209
+ for (size_t i = 0; i < len; ++i) {
210
+ out[i] = in[len - 1 - i];
211
+ }
212
+ }
213
+
214
+ // From OpenSSL BIGNUM to internal representation
215
+ static int p224_BN_to_felem(p224_felem out, const BIGNUM *bn) {
216
+ // BN_bn2bin eats leading zeroes
217
+ p224_felem_bytearray b_out;
218
+ OPENSSL_memset(b_out, 0, sizeof(b_out));
219
+ size_t num_bytes = BN_num_bytes(bn);
220
+ if (num_bytes > sizeof(b_out) ||
221
+ BN_is_negative(bn)) {
222
+ OPENSSL_PUT_ERROR(EC, EC_R_BIGNUM_OUT_OF_RANGE);
223
+ return 0;
224
+ }
225
+
226
+ p224_felem_bytearray b_in;
227
+ num_bytes = BN_bn2bin(bn, b_in);
228
+ p224_flip_endian(b_out, b_in, num_bytes);
229
+ p224_bin28_to_felem(out, b_out);
230
+ return 1;
231
+ }
232
+
233
+ // From internal representation to OpenSSL BIGNUM
234
+ static BIGNUM *p224_felem_to_BN(BIGNUM *out, const p224_felem in) {
235
+ p224_felem_bytearray b_in, b_out;
236
+ p224_felem_to_bin28(b_in, in);
237
+ p224_flip_endian(b_out, b_in, sizeof(b_out));
238
+ return BN_bin2bn(b_out, sizeof(b_out), out);
239
+ }
240
+
241
+ // Field operations, using the internal representation of field elements.
242
+ // NB! These operations are specific to our point multiplication and cannot be
243
+ // expected to be correct in general - e.g., multiplication with a large scalar
244
+ // will cause an overflow.
245
+
246
+ static void p224_felem_assign(p224_felem out, const p224_felem in) {
247
+ out[0] = in[0];
248
+ out[1] = in[1];
249
+ out[2] = in[2];
250
+ out[3] = in[3];
251
+ }
252
+
253
+ // Sum two field elements: out += in
254
+ static void p224_felem_sum(p224_felem out, const p224_felem in) {
255
+ out[0] += in[0];
256
+ out[1] += in[1];
257
+ out[2] += in[2];
258
+ out[3] += in[3];
259
+ }
260
+
261
+ // Get negative value: out = -in
262
+ // Assumes in[i] < 2^57
263
+ static void p224_felem_neg(p224_felem out, const p224_felem in) {
264
+ static const p224_limb two58p2 =
265
+ (((p224_limb)1) << 58) + (((p224_limb)1) << 2);
266
+ static const p224_limb two58m2 =
267
+ (((p224_limb)1) << 58) - (((p224_limb)1) << 2);
268
+ static const p224_limb two58m42m2 =
269
+ (((p224_limb)1) << 58) - (((p224_limb)1) << 42) - (((p224_limb)1) << 2);
270
+
271
+ // Set to 0 mod 2^224-2^96+1 to ensure out > in
272
+ out[0] = two58p2 - in[0];
273
+ out[1] = two58m42m2 - in[1];
274
+ out[2] = two58m2 - in[2];
275
+ out[3] = two58m2 - in[3];
276
+ }
277
+
278
+ // Subtract field elements: out -= in
279
+ // Assumes in[i] < 2^57
280
+ static void p224_felem_diff(p224_felem out, const p224_felem in) {
281
+ static const p224_limb two58p2 =
282
+ (((p224_limb)1) << 58) + (((p224_limb)1) << 2);
283
+ static const p224_limb two58m2 =
284
+ (((p224_limb)1) << 58) - (((p224_limb)1) << 2);
285
+ static const p224_limb two58m42m2 =
286
+ (((p224_limb)1) << 58) - (((p224_limb)1) << 42) - (((p224_limb)1) << 2);
287
+
288
+ // Add 0 mod 2^224-2^96+1 to ensure out > in
289
+ out[0] += two58p2;
290
+ out[1] += two58m42m2;
291
+ out[2] += two58m2;
292
+ out[3] += two58m2;
293
+
294
+ out[0] -= in[0];
295
+ out[1] -= in[1];
296
+ out[2] -= in[2];
297
+ out[3] -= in[3];
298
+ }
299
+
300
+ // Subtract in unreduced 128-bit mode: out -= in
301
+ // Assumes in[i] < 2^119
302
+ static void p224_widefelem_diff(p224_widefelem out, const p224_widefelem in) {
303
+ static const p224_widelimb two120 = ((p224_widelimb)1) << 120;
304
+ static const p224_widelimb two120m64 =
305
+ (((p224_widelimb)1) << 120) - (((p224_widelimb)1) << 64);
306
+ static const p224_widelimb two120m104m64 = (((p224_widelimb)1) << 120) -
307
+ (((p224_widelimb)1) << 104) -
308
+ (((p224_widelimb)1) << 64);
309
+
310
+ // Add 0 mod 2^224-2^96+1 to ensure out > in
311
+ out[0] += two120;
312
+ out[1] += two120m64;
313
+ out[2] += two120m64;
314
+ out[3] += two120;
315
+ out[4] += two120m104m64;
316
+ out[5] += two120m64;
317
+ out[6] += two120m64;
318
+
319
+ out[0] -= in[0];
320
+ out[1] -= in[1];
321
+ out[2] -= in[2];
322
+ out[3] -= in[3];
323
+ out[4] -= in[4];
324
+ out[5] -= in[5];
325
+ out[6] -= in[6];
326
+ }
327
+
328
+ // Subtract in mixed mode: out128 -= in64
329
+ // in[i] < 2^63
330
+ static void p224_felem_diff_128_64(p224_widefelem out, const p224_felem in) {
331
+ static const p224_widelimb two64p8 =
332
+ (((p224_widelimb)1) << 64) + (((p224_widelimb)1) << 8);
333
+ static const p224_widelimb two64m8 =
334
+ (((p224_widelimb)1) << 64) - (((p224_widelimb)1) << 8);
335
+ static const p224_widelimb two64m48m8 = (((p224_widelimb)1) << 64) -
336
+ (((p224_widelimb)1) << 48) -
337
+ (((p224_widelimb)1) << 8);
338
+
339
+ // Add 0 mod 2^224-2^96+1 to ensure out > in
340
+ out[0] += two64p8;
341
+ out[1] += two64m48m8;
342
+ out[2] += two64m8;
343
+ out[3] += two64m8;
344
+
345
+ out[0] -= in[0];
346
+ out[1] -= in[1];
347
+ out[2] -= in[2];
348
+ out[3] -= in[3];
349
+ }
350
+
351
+ // Multiply a field element by a scalar: out = out * scalar
352
+ // The scalars we actually use are small, so results fit without overflow
353
+ static void p224_felem_scalar(p224_felem out, const p224_limb scalar) {
354
+ out[0] *= scalar;
355
+ out[1] *= scalar;
356
+ out[2] *= scalar;
357
+ out[3] *= scalar;
358
+ }
359
+
360
+ // Multiply an unreduced field element by a scalar: out = out * scalar
361
+ // The scalars we actually use are small, so results fit without overflow
362
+ static void p224_widefelem_scalar(p224_widefelem out,
363
+ const p224_widelimb scalar) {
364
+ out[0] *= scalar;
365
+ out[1] *= scalar;
366
+ out[2] *= scalar;
367
+ out[3] *= scalar;
368
+ out[4] *= scalar;
369
+ out[5] *= scalar;
370
+ out[6] *= scalar;
371
+ }
372
+
373
+ // Square a field element: out = in^2
374
+ static void p224_felem_square(p224_widefelem out, const p224_felem in) {
375
+ p224_limb tmp0, tmp1, tmp2;
376
+ tmp0 = 2 * in[0];
377
+ tmp1 = 2 * in[1];
378
+ tmp2 = 2 * in[2];
379
+ out[0] = ((p224_widelimb)in[0]) * in[0];
380
+ out[1] = ((p224_widelimb)in[0]) * tmp1;
381
+ out[2] = ((p224_widelimb)in[0]) * tmp2 + ((p224_widelimb)in[1]) * in[1];
382
+ out[3] = ((p224_widelimb)in[3]) * tmp0 + ((p224_widelimb)in[1]) * tmp2;
383
+ out[4] = ((p224_widelimb)in[3]) * tmp1 + ((p224_widelimb)in[2]) * in[2];
384
+ out[5] = ((p224_widelimb)in[3]) * tmp2;
385
+ out[6] = ((p224_widelimb)in[3]) * in[3];
386
+ }
387
+
388
+ // Multiply two field elements: out = in1 * in2
389
+ static void p224_felem_mul(p224_widefelem out, const p224_felem in1,
390
+ const p224_felem in2) {
391
+ out[0] = ((p224_widelimb)in1[0]) * in2[0];
392
+ out[1] = ((p224_widelimb)in1[0]) * in2[1] + ((p224_widelimb)in1[1]) * in2[0];
393
+ out[2] = ((p224_widelimb)in1[0]) * in2[2] + ((p224_widelimb)in1[1]) * in2[1] +
394
+ ((p224_widelimb)in1[2]) * in2[0];
395
+ out[3] = ((p224_widelimb)in1[0]) * in2[3] + ((p224_widelimb)in1[1]) * in2[2] +
396
+ ((p224_widelimb)in1[2]) * in2[1] + ((p224_widelimb)in1[3]) * in2[0];
397
+ out[4] = ((p224_widelimb)in1[1]) * in2[3] + ((p224_widelimb)in1[2]) * in2[2] +
398
+ ((p224_widelimb)in1[3]) * in2[1];
399
+ out[5] = ((p224_widelimb)in1[2]) * in2[3] + ((p224_widelimb)in1[3]) * in2[2];
400
+ out[6] = ((p224_widelimb)in1[3]) * in2[3];
401
+ }
402
+
403
+ // Reduce seven 128-bit coefficients to four 64-bit coefficients.
404
+ // Requires in[i] < 2^126,
405
+ // ensures out[0] < 2^56, out[1] < 2^56, out[2] < 2^56, out[3] <= 2^56 + 2^16
406
+ static void p224_felem_reduce(p224_felem out, const p224_widefelem in) {
407
+ static const p224_widelimb two127p15 =
408
+ (((p224_widelimb)1) << 127) + (((p224_widelimb)1) << 15);
409
+ static const p224_widelimb two127m71 =
410
+ (((p224_widelimb)1) << 127) - (((p224_widelimb)1) << 71);
411
+ static const p224_widelimb two127m71m55 = (((p224_widelimb)1) << 127) -
412
+ (((p224_widelimb)1) << 71) -
413
+ (((p224_widelimb)1) << 55);
414
+ p224_widelimb output[5];
415
+
416
+ // Add 0 mod 2^224-2^96+1 to ensure all differences are positive
417
+ output[0] = in[0] + two127p15;
418
+ output[1] = in[1] + two127m71m55;
419
+ output[2] = in[2] + two127m71;
420
+ output[3] = in[3];
421
+ output[4] = in[4];
422
+
423
+ // Eliminate in[4], in[5], in[6]
424
+ output[4] += in[6] >> 16;
425
+ output[3] += (in[6] & 0xffff) << 40;
426
+ output[2] -= in[6];
427
+
428
+ output[3] += in[5] >> 16;
429
+ output[2] += (in[5] & 0xffff) << 40;
430
+ output[1] -= in[5];
431
+
432
+ output[2] += output[4] >> 16;
433
+ output[1] += (output[4] & 0xffff) << 40;
434
+ output[0] -= output[4];
435
+
436
+ // Carry 2 -> 3 -> 4
437
+ output[3] += output[2] >> 56;
438
+ output[2] &= 0x00ffffffffffffff;
439
+
440
+ output[4] = output[3] >> 56;
441
+ output[3] &= 0x00ffffffffffffff;
442
+
443
+ // Now output[2] < 2^56, output[3] < 2^56, output[4] < 2^72
444
+
445
+ // Eliminate output[4]
446
+ output[2] += output[4] >> 16;
447
+ // output[2] < 2^56 + 2^56 = 2^57
448
+ output[1] += (output[4] & 0xffff) << 40;
449
+ output[0] -= output[4];
450
+
451
+ // Carry 0 -> 1 -> 2 -> 3
452
+ output[1] += output[0] >> 56;
453
+ out[0] = output[0] & 0x00ffffffffffffff;
454
+
455
+ output[2] += output[1] >> 56;
456
+ // output[2] < 2^57 + 2^72
457
+ out[1] = output[1] & 0x00ffffffffffffff;
458
+ output[3] += output[2] >> 56;
459
+ // output[3] <= 2^56 + 2^16
460
+ out[2] = output[2] & 0x00ffffffffffffff;
461
+
462
+ // out[0] < 2^56, out[1] < 2^56, out[2] < 2^56,
463
+ // out[3] <= 2^56 + 2^16 (due to final carry),
464
+ // so out < 2*p
465
+ out[3] = output[3];
466
+ }
467
+
468
+ // Reduce to unique minimal representation.
469
+ // Requires 0 <= in < 2*p (always call p224_felem_reduce first)
470
+ static void p224_felem_contract(p224_felem out, const p224_felem in) {
471
+ static const int64_t two56 = ((p224_limb)1) << 56;
472
+ // 0 <= in < 2*p, p = 2^224 - 2^96 + 1
473
+ // if in > p , reduce in = in - 2^224 + 2^96 - 1
474
+ int64_t tmp[4], a;
475
+ tmp[0] = in[0];
476
+ tmp[1] = in[1];
477
+ tmp[2] = in[2];
478
+ tmp[3] = in[3];
479
+ // Case 1: a = 1 iff in >= 2^224
480
+ a = (in[3] >> 56);
481
+ tmp[0] -= a;
482
+ tmp[1] += a << 40;
483
+ tmp[3] &= 0x00ffffffffffffff;
484
+ // Case 2: a = 0 iff p <= in < 2^224, i.e., the high 128 bits are all 1 and
485
+ // the lower part is non-zero
486
+ a = ((in[3] & in[2] & (in[1] | 0x000000ffffffffff)) + 1) |
487
+ (((int64_t)(in[0] + (in[1] & 0x000000ffffffffff)) - 1) >> 63);
488
+ a &= 0x00ffffffffffffff;
489
+ // turn a into an all-one mask (if a = 0) or an all-zero mask
490
+ a = (a - 1) >> 63;
491
+ // subtract 2^224 - 2^96 + 1 if a is all-one
492
+ tmp[3] &= a ^ 0xffffffffffffffff;
493
+ tmp[2] &= a ^ 0xffffffffffffffff;
494
+ tmp[1] &= (a ^ 0xffffffffffffffff) | 0x000000ffffffffff;
495
+ tmp[0] -= 1 & a;
496
+
497
+ // eliminate negative coefficients: if tmp[0] is negative, tmp[1] must
498
+ // be non-zero, so we only need one step
499
+ a = tmp[0] >> 63;
500
+ tmp[0] += two56 & a;
501
+ tmp[1] -= 1 & a;
502
+
503
+ // carry 1 -> 2 -> 3
504
+ tmp[2] += tmp[1] >> 56;
505
+ tmp[1] &= 0x00ffffffffffffff;
506
+
507
+ tmp[3] += tmp[2] >> 56;
508
+ tmp[2] &= 0x00ffffffffffffff;
509
+
510
+ // Now 0 <= out < p
511
+ out[0] = tmp[0];
512
+ out[1] = tmp[1];
513
+ out[2] = tmp[2];
514
+ out[3] = tmp[3];
515
+ }
516
+
517
+ // Zero-check: returns 1 if input is 0, and 0 otherwise. We know that field
518
+ // elements are reduced to in < 2^225, so we only need to check three cases: 0,
519
+ // 2^224 - 2^96 + 1, and 2^225 - 2^97 + 2
520
+ static p224_limb p224_felem_is_zero(const p224_felem in) {
521
+ p224_limb zero = in[0] | in[1] | in[2] | in[3];
522
+ zero = (((int64_t)(zero)-1) >> 63) & 1;
523
+
524
+ p224_limb two224m96p1 = (in[0] ^ 1) | (in[1] ^ 0x00ffff0000000000) |
525
+ (in[2] ^ 0x00ffffffffffffff) |
526
+ (in[3] ^ 0x00ffffffffffffff);
527
+ two224m96p1 = (((int64_t)(two224m96p1)-1) >> 63) & 1;
528
+ p224_limb two225m97p2 = (in[0] ^ 2) | (in[1] ^ 0x00fffe0000000000) |
529
+ (in[2] ^ 0x00ffffffffffffff) |
530
+ (in[3] ^ 0x01ffffffffffffff);
531
+ two225m97p2 = (((int64_t)(two225m97p2)-1) >> 63) & 1;
532
+ return (zero | two224m96p1 | two225m97p2);
533
+ }
534
+
535
+ // Invert a field element
536
+ // Computation chain copied from djb's code
537
+ static void p224_felem_inv(p224_felem out, const p224_felem in) {
538
+ p224_felem ftmp, ftmp2, ftmp3, ftmp4;
539
+ p224_widefelem tmp;
540
+
541
+ p224_felem_square(tmp, in);
542
+ p224_felem_reduce(ftmp, tmp); // 2
543
+ p224_felem_mul(tmp, in, ftmp);
544
+ p224_felem_reduce(ftmp, tmp); // 2^2 - 1
545
+ p224_felem_square(tmp, ftmp);
546
+ p224_felem_reduce(ftmp, tmp); // 2^3 - 2
547
+ p224_felem_mul(tmp, in, ftmp);
548
+ p224_felem_reduce(ftmp, tmp); // 2^3 - 1
549
+ p224_felem_square(tmp, ftmp);
550
+ p224_felem_reduce(ftmp2, tmp); // 2^4 - 2
551
+ p224_felem_square(tmp, ftmp2);
552
+ p224_felem_reduce(ftmp2, tmp); // 2^5 - 4
553
+ p224_felem_square(tmp, ftmp2);
554
+ p224_felem_reduce(ftmp2, tmp); // 2^6 - 8
555
+ p224_felem_mul(tmp, ftmp2, ftmp);
556
+ p224_felem_reduce(ftmp, tmp); // 2^6 - 1
557
+ p224_felem_square(tmp, ftmp);
558
+ p224_felem_reduce(ftmp2, tmp); // 2^7 - 2
559
+ for (size_t i = 0; i < 5; ++i) { // 2^12 - 2^6
560
+ p224_felem_square(tmp, ftmp2);
561
+ p224_felem_reduce(ftmp2, tmp);
562
+ }
563
+ p224_felem_mul(tmp, ftmp2, ftmp);
564
+ p224_felem_reduce(ftmp2, tmp); // 2^12 - 1
565
+ p224_felem_square(tmp, ftmp2);
566
+ p224_felem_reduce(ftmp3, tmp); // 2^13 - 2
567
+ for (size_t i = 0; i < 11; ++i) { // 2^24 - 2^12
568
+ p224_felem_square(tmp, ftmp3);
569
+ p224_felem_reduce(ftmp3, tmp);
570
+ }
571
+ p224_felem_mul(tmp, ftmp3, ftmp2);
572
+ p224_felem_reduce(ftmp2, tmp); // 2^24 - 1
573
+ p224_felem_square(tmp, ftmp2);
574
+ p224_felem_reduce(ftmp3, tmp); // 2^25 - 2
575
+ for (size_t i = 0; i < 23; ++i) { // 2^48 - 2^24
576
+ p224_felem_square(tmp, ftmp3);
577
+ p224_felem_reduce(ftmp3, tmp);
578
+ }
579
+ p224_felem_mul(tmp, ftmp3, ftmp2);
580
+ p224_felem_reduce(ftmp3, tmp); // 2^48 - 1
581
+ p224_felem_square(tmp, ftmp3);
582
+ p224_felem_reduce(ftmp4, tmp); // 2^49 - 2
583
+ for (size_t i = 0; i < 47; ++i) { // 2^96 - 2^48
584
+ p224_felem_square(tmp, ftmp4);
585
+ p224_felem_reduce(ftmp4, tmp);
586
+ }
587
+ p224_felem_mul(tmp, ftmp3, ftmp4);
588
+ p224_felem_reduce(ftmp3, tmp); // 2^96 - 1
589
+ p224_felem_square(tmp, ftmp3);
590
+ p224_felem_reduce(ftmp4, tmp); // 2^97 - 2
591
+ for (size_t i = 0; i < 23; ++i) { // 2^120 - 2^24
592
+ p224_felem_square(tmp, ftmp4);
593
+ p224_felem_reduce(ftmp4, tmp);
594
+ }
595
+ p224_felem_mul(tmp, ftmp2, ftmp4);
596
+ p224_felem_reduce(ftmp2, tmp); // 2^120 - 1
597
+ for (size_t i = 0; i < 6; ++i) { // 2^126 - 2^6
598
+ p224_felem_square(tmp, ftmp2);
599
+ p224_felem_reduce(ftmp2, tmp);
600
+ }
601
+ p224_felem_mul(tmp, ftmp2, ftmp);
602
+ p224_felem_reduce(ftmp, tmp); // 2^126 - 1
603
+ p224_felem_square(tmp, ftmp);
604
+ p224_felem_reduce(ftmp, tmp); // 2^127 - 2
605
+ p224_felem_mul(tmp, ftmp, in);
606
+ p224_felem_reduce(ftmp, tmp); // 2^127 - 1
607
+ for (size_t i = 0; i < 97; ++i) { // 2^224 - 2^97
608
+ p224_felem_square(tmp, ftmp);
609
+ p224_felem_reduce(ftmp, tmp);
610
+ }
611
+ p224_felem_mul(tmp, ftmp, ftmp3);
612
+ p224_felem_reduce(out, tmp); // 2^224 - 2^96 - 1
613
+ }
614
+
615
+ // Copy in constant time:
616
+ // if icopy == 1, copy in to out,
617
+ // if icopy == 0, copy out to itself.
618
+ static void p224_copy_conditional(p224_felem out, const p224_felem in,
619
+ p224_limb icopy) {
620
+ // icopy is a (64-bit) 0 or 1, so copy is either all-zero or all-one
621
+ const p224_limb copy = -icopy;
622
+ for (size_t i = 0; i < 4; ++i) {
623
+ const p224_limb tmp = copy & (in[i] ^ out[i]);
624
+ out[i] ^= tmp;
625
+ }
626
+ }
627
+
628
+ // ELLIPTIC CURVE POINT OPERATIONS
629
+ //
630
+ // Points are represented in Jacobian projective coordinates:
631
+ // (X, Y, Z) corresponds to the affine point (X/Z^2, Y/Z^3),
632
+ // or to the point at infinity if Z == 0.
633
+
634
+ // Double an elliptic curve point:
635
+ // (X', Y', Z') = 2 * (X, Y, Z), where
636
+ // X' = (3 * (X - Z^2) * (X + Z^2))^2 - 8 * X * Y^2
637
+ // Y' = 3 * (X - Z^2) * (X + Z^2) * (4 * X * Y^2 - X') - 8 * Y^2
638
+ // Z' = (Y + Z)^2 - Y^2 - Z^2 = 2 * Y * Z
639
+ // Outputs can equal corresponding inputs, i.e., x_out == x_in is allowed,
640
+ // while x_out == y_in is not (maybe this works, but it's not tested).
641
+ static void p224_point_double(p224_felem x_out, p224_felem y_out,
642
+ p224_felem z_out, const p224_felem x_in,
643
+ const p224_felem y_in, const p224_felem z_in) {
644
+ p224_widefelem tmp, tmp2;
645
+ p224_felem delta, gamma, beta, alpha, ftmp, ftmp2;
646
+
647
+ p224_felem_assign(ftmp, x_in);
648
+ p224_felem_assign(ftmp2, x_in);
649
+
650
+ // delta = z^2
651
+ p224_felem_square(tmp, z_in);
652
+ p224_felem_reduce(delta, tmp);
653
+
654
+ // gamma = y^2
655
+ p224_felem_square(tmp, y_in);
656
+ p224_felem_reduce(gamma, tmp);
657
+
658
+ // beta = x*gamma
659
+ p224_felem_mul(tmp, x_in, gamma);
660
+ p224_felem_reduce(beta, tmp);
661
+
662
+ // alpha = 3*(x-delta)*(x+delta)
663
+ p224_felem_diff(ftmp, delta);
664
+ // ftmp[i] < 2^57 + 2^58 + 2 < 2^59
665
+ p224_felem_sum(ftmp2, delta);
666
+ // ftmp2[i] < 2^57 + 2^57 = 2^58
667
+ p224_felem_scalar(ftmp2, 3);
668
+ // ftmp2[i] < 3 * 2^58 < 2^60
669
+ p224_felem_mul(tmp, ftmp, ftmp2);
670
+ // tmp[i] < 2^60 * 2^59 * 4 = 2^121
671
+ p224_felem_reduce(alpha, tmp);
672
+
673
+ // x' = alpha^2 - 8*beta
674
+ p224_felem_square(tmp, alpha);
675
+ // tmp[i] < 4 * 2^57 * 2^57 = 2^116
676
+ p224_felem_assign(ftmp, beta);
677
+ p224_felem_scalar(ftmp, 8);
678
+ // ftmp[i] < 8 * 2^57 = 2^60
679
+ p224_felem_diff_128_64(tmp, ftmp);
680
+ // tmp[i] < 2^116 + 2^64 + 8 < 2^117
681
+ p224_felem_reduce(x_out, tmp);
682
+
683
+ // z' = (y + z)^2 - gamma - delta
684
+ p224_felem_sum(delta, gamma);
685
+ // delta[i] < 2^57 + 2^57 = 2^58
686
+ p224_felem_assign(ftmp, y_in);
687
+ p224_felem_sum(ftmp, z_in);
688
+ // ftmp[i] < 2^57 + 2^57 = 2^58
689
+ p224_felem_square(tmp, ftmp);
690
+ // tmp[i] < 4 * 2^58 * 2^58 = 2^118
691
+ p224_felem_diff_128_64(tmp, delta);
692
+ // tmp[i] < 2^118 + 2^64 + 8 < 2^119
693
+ p224_felem_reduce(z_out, tmp);
694
+
695
+ // y' = alpha*(4*beta - x') - 8*gamma^2
696
+ p224_felem_scalar(beta, 4);
697
+ // beta[i] < 4 * 2^57 = 2^59
698
+ p224_felem_diff(beta, x_out);
699
+ // beta[i] < 2^59 + 2^58 + 2 < 2^60
700
+ p224_felem_mul(tmp, alpha, beta);
701
+ // tmp[i] < 4 * 2^57 * 2^60 = 2^119
702
+ p224_felem_square(tmp2, gamma);
703
+ // tmp2[i] < 4 * 2^57 * 2^57 = 2^116
704
+ p224_widefelem_scalar(tmp2, 8);
705
+ // tmp2[i] < 8 * 2^116 = 2^119
706
+ p224_widefelem_diff(tmp, tmp2);
707
+ // tmp[i] < 2^119 + 2^120 < 2^121
708
+ p224_felem_reduce(y_out, tmp);
709
+ }
710
+
711
+ // Add two elliptic curve points:
712
+ // (X_1, Y_1, Z_1) + (X_2, Y_2, Z_2) = (X_3, Y_3, Z_3), where
713
+ // X_3 = (Z_1^3 * Y_2 - Z_2^3 * Y_1)^2 - (Z_1^2 * X_2 - Z_2^2 * X_1)^3 -
714
+ // 2 * Z_2^2 * X_1 * (Z_1^2 * X_2 - Z_2^2 * X_1)^2
715
+ // Y_3 = (Z_1^3 * Y_2 - Z_2^3 * Y_1) * (Z_2^2 * X_1 * (Z_1^2 * X_2 - Z_2^2 *
716
+ // X_1)^2 - X_3) -
717
+ // Z_2^3 * Y_1 * (Z_1^2 * X_2 - Z_2^2 * X_1)^3
718
+ // Z_3 = (Z_1^2 * X_2 - Z_2^2 * X_1) * (Z_1 * Z_2)
719
+ //
720
+ // This runs faster if 'mixed' is set, which requires Z_2 = 1 or Z_2 = 0.
721
+
722
+ // This function is not entirely constant-time: it includes a branch for
723
+ // checking whether the two input points are equal, (while not equal to the
724
+ // point at infinity). This case never happens during single point
725
+ // multiplication, so there is no timing leak for ECDH or ECDSA signing.
726
+ static void p224_point_add(p224_felem x3, p224_felem y3, p224_felem z3,
727
+ const p224_felem x1, const p224_felem y1,
728
+ const p224_felem z1, const int mixed,
729
+ const p224_felem x2, const p224_felem y2,
730
+ const p224_felem z2) {
731
+ p224_felem ftmp, ftmp2, ftmp3, ftmp4, ftmp5, x_out, y_out, z_out;
732
+ p224_widefelem tmp, tmp2;
733
+ p224_limb z1_is_zero, z2_is_zero, x_equal, y_equal;
734
+
735
+ if (!mixed) {
736
+ // ftmp2 = z2^2
737
+ p224_felem_square(tmp, z2);
738
+ p224_felem_reduce(ftmp2, tmp);
739
+
740
+ // ftmp4 = z2^3
741
+ p224_felem_mul(tmp, ftmp2, z2);
742
+ p224_felem_reduce(ftmp4, tmp);
743
+
744
+ // ftmp4 = z2^3*y1
745
+ p224_felem_mul(tmp2, ftmp4, y1);
746
+ p224_felem_reduce(ftmp4, tmp2);
747
+
748
+ // ftmp2 = z2^2*x1
749
+ p224_felem_mul(tmp2, ftmp2, x1);
750
+ p224_felem_reduce(ftmp2, tmp2);
751
+ } else {
752
+ // We'll assume z2 = 1 (special case z2 = 0 is handled later)
753
+
754
+ // ftmp4 = z2^3*y1
755
+ p224_felem_assign(ftmp4, y1);
756
+
757
+ // ftmp2 = z2^2*x1
758
+ p224_felem_assign(ftmp2, x1);
759
+ }
760
+
761
+ // ftmp = z1^2
762
+ p224_felem_square(tmp, z1);
763
+ p224_felem_reduce(ftmp, tmp);
764
+
765
+ // ftmp3 = z1^3
766
+ p224_felem_mul(tmp, ftmp, z1);
767
+ p224_felem_reduce(ftmp3, tmp);
768
+
769
+ // tmp = z1^3*y2
770
+ p224_felem_mul(tmp, ftmp3, y2);
771
+ // tmp[i] < 4 * 2^57 * 2^57 = 2^116
772
+
773
+ // ftmp3 = z1^3*y2 - z2^3*y1
774
+ p224_felem_diff_128_64(tmp, ftmp4);
775
+ // tmp[i] < 2^116 + 2^64 + 8 < 2^117
776
+ p224_felem_reduce(ftmp3, tmp);
777
+
778
+ // tmp = z1^2*x2
779
+ p224_felem_mul(tmp, ftmp, x2);
780
+ // tmp[i] < 4 * 2^57 * 2^57 = 2^116
781
+
782
+ // ftmp = z1^2*x2 - z2^2*x1
783
+ p224_felem_diff_128_64(tmp, ftmp2);
784
+ // tmp[i] < 2^116 + 2^64 + 8 < 2^117
785
+ p224_felem_reduce(ftmp, tmp);
786
+
787
+ // the formulae are incorrect if the points are equal
788
+ // so we check for this and do doubling if this happens
789
+ x_equal = p224_felem_is_zero(ftmp);
790
+ y_equal = p224_felem_is_zero(ftmp3);
791
+ z1_is_zero = p224_felem_is_zero(z1);
792
+ z2_is_zero = p224_felem_is_zero(z2);
793
+ // In affine coordinates, (X_1, Y_1) == (X_2, Y_2)
794
+ if (x_equal && y_equal && !z1_is_zero && !z2_is_zero) {
795
+ p224_point_double(x3, y3, z3, x1, y1, z1);
796
+ return;
797
+ }
798
+
799
+ // ftmp5 = z1*z2
800
+ if (!mixed) {
801
+ p224_felem_mul(tmp, z1, z2);
802
+ p224_felem_reduce(ftmp5, tmp);
803
+ } else {
804
+ // special case z2 = 0 is handled later
805
+ p224_felem_assign(ftmp5, z1);
806
+ }
807
+
808
+ // z_out = (z1^2*x2 - z2^2*x1)*(z1*z2)
809
+ p224_felem_mul(tmp, ftmp, ftmp5);
810
+ p224_felem_reduce(z_out, tmp);
811
+
812
+ // ftmp = (z1^2*x2 - z2^2*x1)^2
813
+ p224_felem_assign(ftmp5, ftmp);
814
+ p224_felem_square(tmp, ftmp);
815
+ p224_felem_reduce(ftmp, tmp);
816
+
817
+ // ftmp5 = (z1^2*x2 - z2^2*x1)^3
818
+ p224_felem_mul(tmp, ftmp, ftmp5);
819
+ p224_felem_reduce(ftmp5, tmp);
820
+
821
+ // ftmp2 = z2^2*x1*(z1^2*x2 - z2^2*x1)^2
822
+ p224_felem_mul(tmp, ftmp2, ftmp);
823
+ p224_felem_reduce(ftmp2, tmp);
824
+
825
+ // tmp = z2^3*y1*(z1^2*x2 - z2^2*x1)^3
826
+ p224_felem_mul(tmp, ftmp4, ftmp5);
827
+ // tmp[i] < 4 * 2^57 * 2^57 = 2^116
828
+
829
+ // tmp2 = (z1^3*y2 - z2^3*y1)^2
830
+ p224_felem_square(tmp2, ftmp3);
831
+ // tmp2[i] < 4 * 2^57 * 2^57 < 2^116
832
+
833
+ // tmp2 = (z1^3*y2 - z2^3*y1)^2 - (z1^2*x2 - z2^2*x1)^3
834
+ p224_felem_diff_128_64(tmp2, ftmp5);
835
+ // tmp2[i] < 2^116 + 2^64 + 8 < 2^117
836
+
837
+ // ftmp5 = 2*z2^2*x1*(z1^2*x2 - z2^2*x1)^2
838
+ p224_felem_assign(ftmp5, ftmp2);
839
+ p224_felem_scalar(ftmp5, 2);
840
+ // ftmp5[i] < 2 * 2^57 = 2^58
841
+
842
+ /* x_out = (z1^3*y2 - z2^3*y1)^2 - (z1^2*x2 - z2^2*x1)^3 -
843
+ 2*z2^2*x1*(z1^2*x2 - z2^2*x1)^2 */
844
+ p224_felem_diff_128_64(tmp2, ftmp5);
845
+ // tmp2[i] < 2^117 + 2^64 + 8 < 2^118
846
+ p224_felem_reduce(x_out, tmp2);
847
+
848
+ // ftmp2 = z2^2*x1*(z1^2*x2 - z2^2*x1)^2 - x_out
849
+ p224_felem_diff(ftmp2, x_out);
850
+ // ftmp2[i] < 2^57 + 2^58 + 2 < 2^59
851
+
852
+ // tmp2 = (z1^3*y2 - z2^3*y1)*(z2^2*x1*(z1^2*x2 - z2^2*x1)^2 - x_out)
853
+ p224_felem_mul(tmp2, ftmp3, ftmp2);
854
+ // tmp2[i] < 4 * 2^57 * 2^59 = 2^118
855
+
856
+ /* y_out = (z1^3*y2 - z2^3*y1)*(z2^2*x1*(z1^2*x2 - z2^2*x1)^2 - x_out) -
857
+ z2^3*y1*(z1^2*x2 - z2^2*x1)^3 */
858
+ p224_widefelem_diff(tmp2, tmp);
859
+ // tmp2[i] < 2^118 + 2^120 < 2^121
860
+ p224_felem_reduce(y_out, tmp2);
861
+
862
+ // the result (x_out, y_out, z_out) is incorrect if one of the inputs is
863
+ // the point at infinity, so we need to check for this separately
864
+
865
+ // if point 1 is at infinity, copy point 2 to output, and vice versa
866
+ p224_copy_conditional(x_out, x2, z1_is_zero);
867
+ p224_copy_conditional(x_out, x1, z2_is_zero);
868
+ p224_copy_conditional(y_out, y2, z1_is_zero);
869
+ p224_copy_conditional(y_out, y1, z2_is_zero);
870
+ p224_copy_conditional(z_out, z2, z1_is_zero);
871
+ p224_copy_conditional(z_out, z1, z2_is_zero);
872
+ p224_felem_assign(x3, x_out);
873
+ p224_felem_assign(y3, y_out);
874
+ p224_felem_assign(z3, z_out);
875
+ }
876
+
877
+ // p224_select_point selects the |idx|th point from a precomputation table and
878
+ // copies it to out.
879
+ static void p224_select_point(const uint64_t idx, size_t size,
880
+ const p224_felem pre_comp[/*size*/][3],
881
+ p224_felem out[3]) {
882
+ p224_limb *outlimbs = &out[0][0];
883
+ OPENSSL_memset(outlimbs, 0, 3 * sizeof(p224_felem));
884
+
885
+ for (size_t i = 0; i < size; i++) {
886
+ const p224_limb *inlimbs = &pre_comp[i][0][0];
887
+ uint64_t mask = i ^ idx;
888
+ mask |= mask >> 4;
889
+ mask |= mask >> 2;
890
+ mask |= mask >> 1;
891
+ mask &= 1;
892
+ mask--;
893
+ for (size_t j = 0; j < 4 * 3; j++) {
894
+ outlimbs[j] |= inlimbs[j] & mask;
895
+ }
896
+ }
897
+ }
898
+
899
+ // p224_get_bit returns the |i|th bit in |in|
900
+ static char p224_get_bit(const p224_felem_bytearray in, size_t i) {
901
+ if (i >= 224) {
902
+ return 0;
903
+ }
904
+ return (in[i >> 3] >> (i & 7)) & 1;
905
+ }
906
+
907
+ // Interleaved point multiplication using precomputed point multiples:
908
+ // The small point multiples 0*P, 1*P, ..., 16*P are in p_pre_comp, the scalars
909
+ // in p_scalar, if non-NULL. If g_scalar is non-NULL, we also add this multiple
910
+ // of the generator, using certain (large) precomputed multiples in
911
+ // g_p224_pre_comp. Output point (X, Y, Z) is stored in x_out, y_out, z_out
912
+ static void p224_batch_mul(p224_felem x_out, p224_felem y_out, p224_felem z_out,
913
+ const uint8_t *p_scalar, const uint8_t *g_scalar,
914
+ const p224_felem p_pre_comp[17][3]) {
915
+ p224_felem nq[3], tmp[4];
916
+ uint64_t bits;
917
+ uint8_t sign, digit;
918
+
919
+ // set nq to the point at infinity
920
+ OPENSSL_memset(nq, 0, 3 * sizeof(p224_felem));
921
+
922
+ // Loop over both scalars msb-to-lsb, interleaving additions of multiples of
923
+ // the generator (two in each of the last 28 rounds) and additions of p (every
924
+ // 5th round).
925
+ int skip = 1; // save two point operations in the first round
926
+ size_t i = p_scalar != NULL ? 220 : 27;
927
+ for (;;) {
928
+ // double
929
+ if (!skip) {
930
+ p224_point_double(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2]);
931
+ }
932
+
933
+ // add multiples of the generator
934
+ if (g_scalar != NULL && i <= 27) {
935
+ // first, look 28 bits upwards
936
+ bits = p224_get_bit(g_scalar, i + 196) << 3;
937
+ bits |= p224_get_bit(g_scalar, i + 140) << 2;
938
+ bits |= p224_get_bit(g_scalar, i + 84) << 1;
939
+ bits |= p224_get_bit(g_scalar, i + 28);
940
+ // select the point to add, in constant time
941
+ p224_select_point(bits, 16, g_p224_pre_comp[1], tmp);
942
+
943
+ if (!skip) {
944
+ p224_point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1 /* mixed */,
945
+ tmp[0], tmp[1], tmp[2]);
946
+ } else {
947
+ OPENSSL_memcpy(nq, tmp, 3 * sizeof(p224_felem));
948
+ skip = 0;
949
+ }
950
+
951
+ // second, look at the current position
952
+ bits = p224_get_bit(g_scalar, i + 168) << 3;
953
+ bits |= p224_get_bit(g_scalar, i + 112) << 2;
954
+ bits |= p224_get_bit(g_scalar, i + 56) << 1;
955
+ bits |= p224_get_bit(g_scalar, i);
956
+ // select the point to add, in constant time
957
+ p224_select_point(bits, 16, g_p224_pre_comp[0], tmp);
958
+ p224_point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1 /* mixed */,
959
+ tmp[0], tmp[1], tmp[2]);
960
+ }
961
+
962
+ // do other additions every 5 doublings
963
+ if (p_scalar != NULL && i % 5 == 0) {
964
+ bits = p224_get_bit(p_scalar, i + 4) << 5;
965
+ bits |= p224_get_bit(p_scalar, i + 3) << 4;
966
+ bits |= p224_get_bit(p_scalar, i + 2) << 3;
967
+ bits |= p224_get_bit(p_scalar, i + 1) << 2;
968
+ bits |= p224_get_bit(p_scalar, i) << 1;
969
+ bits |= p224_get_bit(p_scalar, i - 1);
970
+ ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits);
971
+
972
+ // select the point to add or subtract
973
+ p224_select_point(digit, 17, p_pre_comp, tmp);
974
+ p224_felem_neg(tmp[3], tmp[1]); // (X, -Y, Z) is the negative point
975
+ p224_copy_conditional(tmp[1], tmp[3], sign);
976
+
977
+ if (!skip) {
978
+ p224_point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 0 /* mixed */,
979
+ tmp[0], tmp[1], tmp[2]);
980
+ } else {
981
+ OPENSSL_memcpy(nq, tmp, 3 * sizeof(p224_felem));
982
+ skip = 0;
983
+ }
984
+ }
985
+
986
+ if (i == 0) {
987
+ break;
988
+ }
989
+ --i;
990
+ }
991
+ p224_felem_assign(x_out, nq[0]);
992
+ p224_felem_assign(y_out, nq[1]);
993
+ p224_felem_assign(z_out, nq[2]);
994
+ }
995
+
996
+ // Takes the Jacobian coordinates (X, Y, Z) of a point and returns
997
+ // (X', Y') = (X/Z^2, Y/Z^3)
998
+ static int ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group,
999
+ const EC_POINT *point,
1000
+ BIGNUM *x, BIGNUM *y,
1001
+ BN_CTX *ctx) {
1002
+ p224_felem z1, z2, x_in, y_in, x_out, y_out;
1003
+ p224_widefelem tmp;
1004
+
1005
+ if (EC_POINT_is_at_infinity(group, point)) {
1006
+ OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY);
1007
+ return 0;
1008
+ }
1009
+
1010
+ if (!p224_BN_to_felem(x_in, &point->X) ||
1011
+ !p224_BN_to_felem(y_in, &point->Y) ||
1012
+ !p224_BN_to_felem(z1, &point->Z)) {
1013
+ return 0;
1014
+ }
1015
+
1016
+ p224_felem_inv(z2, z1);
1017
+ p224_felem_square(tmp, z2);
1018
+ p224_felem_reduce(z1, tmp);
1019
+ p224_felem_mul(tmp, x_in, z1);
1020
+ p224_felem_reduce(x_in, tmp);
1021
+ p224_felem_contract(x_out, x_in);
1022
+ if (x != NULL && !p224_felem_to_BN(x, x_out)) {
1023
+ OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
1024
+ return 0;
1025
+ }
1026
+
1027
+ p224_felem_mul(tmp, z1, z2);
1028
+ p224_felem_reduce(z1, tmp);
1029
+ p224_felem_mul(tmp, y_in, z1);
1030
+ p224_felem_reduce(y_in, tmp);
1031
+ p224_felem_contract(y_out, y_in);
1032
+ if (y != NULL && !p224_felem_to_BN(y, y_out)) {
1033
+ OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
1034
+ return 0;
1035
+ }
1036
+
1037
+ return 1;
1038
+ }
1039
+
1040
+ static int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
1041
+ const BIGNUM *g_scalar, const EC_POINT *p,
1042
+ const BIGNUM *p_scalar, BN_CTX *ctx) {
1043
+ int ret = 0;
1044
+ BN_CTX *new_ctx = NULL;
1045
+ BIGNUM *x, *y, *z, *tmp_scalar;
1046
+ p224_felem_bytearray g_secret, p_secret;
1047
+ p224_felem p_pre_comp[17][3];
1048
+ p224_felem_bytearray tmp;
1049
+ p224_felem x_in, y_in, z_in, x_out, y_out, z_out;
1050
+
1051
+ if (ctx == NULL) {
1052
+ ctx = BN_CTX_new();
1053
+ new_ctx = ctx;
1054
+ if (ctx == NULL) {
1055
+ return 0;
1056
+ }
1057
+ }
1058
+
1059
+ BN_CTX_start(ctx);
1060
+ if ((x = BN_CTX_get(ctx)) == NULL ||
1061
+ (y = BN_CTX_get(ctx)) == NULL ||
1062
+ (z = BN_CTX_get(ctx)) == NULL ||
1063
+ (tmp_scalar = BN_CTX_get(ctx)) == NULL) {
1064
+ goto err;
1065
+ }
1066
+
1067
+ if (p != NULL && p_scalar != NULL) {
1068
+ // We treat NULL scalars as 0, and NULL points as points at infinity, i.e.,
1069
+ // they contribute nothing to the linear combination.
1070
+ OPENSSL_memset(&p_secret, 0, sizeof(p_secret));
1071
+ OPENSSL_memset(&p_pre_comp, 0, sizeof(p_pre_comp));
1072
+ size_t num_bytes;
1073
+ // reduce g_scalar to 0 <= g_scalar < 2^224
1074
+ if (BN_num_bits(p_scalar) > 224 || BN_is_negative(p_scalar)) {
1075
+ // this is an unusual input, and we don't guarantee
1076
+ // constant-timeness
1077
+ if (!BN_nnmod(tmp_scalar, p_scalar, &group->order, ctx)) {
1078
+ OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
1079
+ goto err;
1080
+ }
1081
+ num_bytes = BN_bn2bin(tmp_scalar, tmp);
1082
+ } else {
1083
+ num_bytes = BN_bn2bin(p_scalar, tmp);
1084
+ }
1085
+
1086
+ p224_flip_endian(p_secret, tmp, num_bytes);
1087
+ // precompute multiples
1088
+ if (!p224_BN_to_felem(x_out, &p->X) ||
1089
+ !p224_BN_to_felem(y_out, &p->Y) ||
1090
+ !p224_BN_to_felem(z_out, &p->Z)) {
1091
+ goto err;
1092
+ }
1093
+
1094
+ p224_felem_assign(p_pre_comp[1][0], x_out);
1095
+ p224_felem_assign(p_pre_comp[1][1], y_out);
1096
+ p224_felem_assign(p_pre_comp[1][2], z_out);
1097
+
1098
+ for (size_t j = 2; j <= 16; ++j) {
1099
+ if (j & 1) {
1100
+ p224_point_add(p_pre_comp[j][0], p_pre_comp[j][1], p_pre_comp[j][2],
1101
+ p_pre_comp[1][0], p_pre_comp[1][1], p_pre_comp[1][2],
1102
+ 0, p_pre_comp[j - 1][0], p_pre_comp[j - 1][1],
1103
+ p_pre_comp[j - 1][2]);
1104
+ } else {
1105
+ p224_point_double(p_pre_comp[j][0], p_pre_comp[j][1],
1106
+ p_pre_comp[j][2], p_pre_comp[j / 2][0],
1107
+ p_pre_comp[j / 2][1], p_pre_comp[j / 2][2]);
1108
+ }
1109
+ }
1110
+ }
1111
+
1112
+ if (g_scalar != NULL) {
1113
+ OPENSSL_memset(g_secret, 0, sizeof(g_secret));
1114
+ size_t num_bytes;
1115
+ // reduce g_scalar to 0 <= g_scalar < 2^224
1116
+ if (BN_num_bits(g_scalar) > 224 || BN_is_negative(g_scalar)) {
1117
+ // this is an unusual input, and we don't guarantee constant-timeness
1118
+ if (!BN_nnmod(tmp_scalar, g_scalar, &group->order, ctx)) {
1119
+ OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
1120
+ goto err;
1121
+ }
1122
+ num_bytes = BN_bn2bin(tmp_scalar, tmp);
1123
+ } else {
1124
+ num_bytes = BN_bn2bin(g_scalar, tmp);
1125
+ }
1126
+
1127
+ p224_flip_endian(g_secret, tmp, num_bytes);
1128
+ }
1129
+ p224_batch_mul(
1130
+ x_out, y_out, z_out, (p != NULL && p_scalar != NULL) ? p_secret : NULL,
1131
+ g_scalar != NULL ? g_secret : NULL, (const p224_felem(*)[3])p_pre_comp);
1132
+
1133
+ // reduce the output to its unique minimal representation
1134
+ p224_felem_contract(x_in, x_out);
1135
+ p224_felem_contract(y_in, y_out);
1136
+ p224_felem_contract(z_in, z_out);
1137
+ if (!p224_felem_to_BN(x, x_in) ||
1138
+ !p224_felem_to_BN(y, y_in) ||
1139
+ !p224_felem_to_BN(z, z_in)) {
1140
+ OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
1141
+ goto err;
1142
+ }
1143
+ ret = ec_point_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx);
1144
+
1145
+ err:
1146
+ BN_CTX_end(ctx);
1147
+ BN_CTX_free(new_ctx);
1148
+ return ret;
1149
+ }
1150
+
1151
+ DEFINE_METHOD_FUNCTION(EC_METHOD, EC_GFp_nistp224_method) {
1152
+ out->group_init = ec_GFp_simple_group_init;
1153
+ out->group_finish = ec_GFp_simple_group_finish;
1154
+ out->group_copy = ec_GFp_simple_group_copy;
1155
+ out->group_set_curve = ec_GFp_simple_group_set_curve;
1156
+ out->point_get_affine_coordinates =
1157
+ ec_GFp_nistp224_point_get_affine_coordinates;
1158
+ out->mul = ec_GFp_nistp224_points_mul;
1159
+ out->field_mul = ec_GFp_simple_field_mul;
1160
+ out->field_sqr = ec_GFp_simple_field_sqr;
1161
+ out->field_encode = NULL;
1162
+ out->field_decode = NULL;
1163
+ };
1164
+
1165
+ #endif // 64_BIT && !WINDOWS && !SMALL