/src/php-src/ext/hash/hash_gost.c
Line | Count | Source |
1 | | /* |
2 | | +----------------------------------------------------------------------+ |
3 | | | Copyright (c) The PHP Group | |
4 | | +----------------------------------------------------------------------+ |
5 | | | This source file is subject to version 3.01 of the PHP license, | |
6 | | | that is bundled with this package in the file LICENSE, and is | |
7 | | | available through the world-wide-web at the following url: | |
8 | | | https://www.php.net/license/3_01.txt | |
9 | | | If you did not receive a copy of the PHP license and are unable to | |
10 | | | obtain it through the world-wide-web, please send a note to | |
11 | | | license@php.net so we can mail you a copy immediately. | |
12 | | +----------------------------------------------------------------------+ |
13 | | | Authors: Michael Wallner <mike@php.net> | |
14 | | | Sara Golemon <pollita@php.net> | |
15 | | +----------------------------------------------------------------------+ |
16 | | */ |
17 | | |
18 | | #include "php_hash.h" |
19 | | #include "php_hash_gost.h" |
20 | | #include "php_hash_gost_tables.h" |
21 | | |
22 | | /* {{{ Gost() |
23 | | * derived from gost_compress() by Markku-Juhani Saarinen <mjos@ssh.fi> |
24 | | */ |
25 | | |
26 | | #define round(tables, k1, k2) \ |
27 | 2.84M | t = (k1) + r; \ |
28 | 2.84M | l ^= tables[0][t & 0xff] ^ tables[1][(t >> 8) & 0xff] ^ \ |
29 | 2.84M | tables[2][(t >> 16) & 0xff] ^ tables[3][t >> 24]; \ |
30 | 2.84M | t = (k2) + l; \ |
31 | 2.84M | r ^= tables[0][t & 0xff] ^ tables[1][(t >> 8) & 0xff] ^ \ |
32 | 2.84M | tables[2][(t >> 16) & 0xff] ^ tables[3][t >> 24]; |
33 | | |
34 | | #define R(tables, key, h, i, t, l, r) \ |
35 | 177k | r = h[i]; \ |
36 | 177k | l = h[i + 1]; \ |
37 | 177k | round(tables, key[0], key[1]) \ |
38 | 177k | round(tables, key[2], key[3]) \ |
39 | 177k | round(tables, key[4], key[5]) \ |
40 | 177k | round(tables, key[6], key[7]) \ |
41 | 177k | round(tables, key[0], key[1]) \ |
42 | 177k | round(tables, key[2], key[3]) \ |
43 | 177k | round(tables, key[4], key[5]) \ |
44 | 177k | round(tables, key[6], key[7]) \ |
45 | 177k | round(tables, key[0], key[1]) \ |
46 | 177k | round(tables, key[2], key[3]) \ |
47 | 177k | round(tables, key[4], key[5]) \ |
48 | 177k | round(tables, key[6], key[7]) \ |
49 | 177k | round(tables, key[7], key[6]) \ |
50 | 177k | round(tables, key[5], key[4]) \ |
51 | 177k | round(tables, key[3], key[2]) \ |
52 | 177k | round(tables, key[1], key[0]) \ |
53 | 177k | t = r; \ |
54 | 177k | r = l; \ |
55 | 177k | l = t; \ |
56 | | |
57 | | #define X(w, u, v) \ |
58 | 177k | w[0] = u[0] ^ v[0]; \ |
59 | 177k | w[1] = u[1] ^ v[1]; \ |
60 | 177k | w[2] = u[2] ^ v[2]; \ |
61 | 177k | w[3] = u[3] ^ v[3]; \ |
62 | 177k | w[4] = u[4] ^ v[4]; \ |
63 | 177k | w[5] = u[5] ^ v[5]; \ |
64 | 177k | w[6] = u[6] ^ v[6]; \ |
65 | 177k | w[7] = u[7] ^ v[7]; |
66 | | |
67 | | #define P(key, w) \ |
68 | 177k | key[0] = (w[0] & 0x000000ff) | ((w[2] & 0x000000ff) << 8) | \ |
69 | 177k | ((w[4] & 0x000000ff) << 16) | ((w[6] & 0x000000ff) << 24); \ |
70 | 177k | key[1] = ((w[0] & 0x0000ff00) >> 8) | (w[2] & 0x0000ff00) | \ |
71 | 177k | ((w[4] & 0x0000ff00) << 8) | ((w[6] & 0x0000ff00) << 16); \ |
72 | 177k | key[2] = ((w[0] & 0x00ff0000) >> 16) | ((w[2] & 0x00ff0000) >> 8) | \ |
73 | 177k | (w[4] & 0x00ff0000) | ((w[6] & 0x00ff0000) << 8); \ |
74 | 177k | key[3] = ((w[0] & 0xff000000) >> 24) | ((w[2] & 0xff000000) >> 16) | \ |
75 | 177k | ((w[4] & 0xff000000) >> 8) | (w[6] & 0xff000000); \ |
76 | 177k | key[4] = (w[1] & 0x000000ff) | ((w[3] & 0x000000ff) << 8) | \ |
77 | 177k | ((w[5] & 0x000000ff) << 16) | ((w[7] & 0x000000ff) << 24); \ |
78 | 177k | key[5] = ((w[1] & 0x0000ff00) >> 8) | (w[3] & 0x0000ff00) | \ |
79 | 177k | ((w[5] & 0x0000ff00) << 8) | ((w[7] & 0x0000ff00) << 16); \ |
80 | 177k | key[6] = ((w[1] & 0x00ff0000) >> 16) | ((w[3] & 0x00ff0000) >> 8) | \ |
81 | 177k | (w[5] & 0x00ff0000) | ((w[7] & 0x00ff0000) << 8); \ |
82 | 177k | key[7] = ((w[1] & 0xff000000) >> 24) | ((w[3] & 0xff000000) >> 16) | \ |
83 | 177k | ((w[5] & 0xff000000) >> 8) | (w[7] & 0xff000000); |
84 | | |
85 | | #define A(x, l, r) \ |
86 | 133k | l = x[0] ^ x[2]; \ |
87 | 133k | r = x[1] ^ x[3]; \ |
88 | 133k | x[0] = x[2]; \ |
89 | 133k | x[1] = x[3]; \ |
90 | 133k | x[2] = x[4]; \ |
91 | 133k | x[3] = x[5]; \ |
92 | 133k | x[4] = x[6]; \ |
93 | 133k | x[5] = x[7]; \ |
94 | 133k | x[6] = l; \ |
95 | 133k | x[7] = r; |
96 | | |
97 | | #define AA(x, l, r) \ |
98 | 133k | l = x[0]; \ |
99 | 133k | r = x[2]; \ |
100 | 133k | x[0] = x[4]; \ |
101 | 133k | x[2] = x[6]; \ |
102 | 133k | x[4] = l ^ r; \ |
103 | 133k | x[6] = x[0] ^ r; \ |
104 | 133k | l = x[1]; \ |
105 | 133k | r = x[3]; \ |
106 | 133k | x[1] = x[5]; \ |
107 | 133k | x[3] = x[7]; \ |
108 | 133k | x[5] = l ^ r; \ |
109 | 133k | x[7] = x[1] ^ r; |
110 | | |
111 | | #define C(x) \ |
112 | 44.4k | x[0] ^= 0xff00ff00; \ |
113 | 44.4k | x[1] ^= 0xff00ff00; \ |
114 | 44.4k | x[2] ^= 0x00ff00ff; \ |
115 | 44.4k | x[3] ^= 0x00ff00ff; \ |
116 | 44.4k | x[4] ^= 0x00ffff00; \ |
117 | 44.4k | x[5] ^= 0xff0000ff; \ |
118 | 44.4k | x[6] ^= 0x000000ff; \ |
119 | 44.4k | x[7] ^= 0xff00ffff; |
120 | | |
121 | | #define S(s, l, r) \ |
122 | 177k | s[i] = r; \ |
123 | 177k | s[i + 1] = l; |
124 | | |
125 | | #define SHIFT12(u, m, s) \ |
126 | 44.4k | u[0] = m[0] ^ s[6]; \ |
127 | 44.4k | u[1] = m[1] ^ s[7]; \ |
128 | 44.4k | u[2] = m[2] ^ (s[0] << 16) ^ (s[0] >> 16) ^ (s[0] & 0xffff) ^ \ |
129 | 44.4k | (s[1] & 0xffff) ^ (s[1] >> 16) ^ (s[2] << 16) ^ s[6] ^ (s[6] << 16) ^ \ |
130 | 44.4k | (s[7] & 0xffff0000) ^ (s[7] >> 16); \ |
131 | 44.4k | u[3] = m[3] ^ (s[0] & 0xffff) ^ (s[0] << 16) ^ (s[1] & 0xffff) ^ \ |
132 | 44.4k | (s[1] << 16) ^ (s[1] >> 16) ^ (s[2] << 16) ^ (s[2] >> 16) ^ \ |
133 | 44.4k | (s[3] << 16) ^ s[6] ^ (s[6] << 16) ^ (s[6] >> 16) ^ (s[7] & 0xffff) ^ \ |
134 | 44.4k | (s[7] << 16) ^ (s[7] >> 16); \ |
135 | 44.4k | u[4] = m[4] ^ \ |
136 | 44.4k | (s[0] & 0xffff0000) ^ (s[0] << 16) ^ (s[0] >> 16) ^ \ |
137 | 44.4k | (s[1] & 0xffff0000) ^ (s[1] >> 16) ^ (s[2] << 16) ^ (s[2] >> 16) ^ \ |
138 | 44.4k | (s[3] << 16) ^ (s[3] >> 16) ^ (s[4] << 16) ^ (s[6] << 16) ^ \ |
139 | 44.4k | (s[6] >> 16) ^(s[7] & 0xffff) ^ (s[7] << 16) ^ (s[7] >> 16); \ |
140 | 44.4k | u[5] = m[5] ^ (s[0] << 16) ^ (s[0] >> 16) ^ (s[0] & 0xffff0000) ^ \ |
141 | 44.4k | (s[1] & 0xffff) ^ s[2] ^ (s[2] >> 16) ^ (s[3] << 16) ^ (s[3] >> 16) ^ \ |
142 | 44.4k | (s[4] << 16) ^ (s[4] >> 16) ^ (s[5] << 16) ^ (s[6] << 16) ^ \ |
143 | 44.4k | (s[6] >> 16) ^ (s[7] & 0xffff0000) ^ (s[7] << 16) ^ (s[7] >> 16); \ |
144 | 44.4k | u[6] = m[6] ^ s[0] ^ (s[1] >> 16) ^ (s[2] << 16) ^ s[3] ^ (s[3] >> 16) ^ \ |
145 | 44.4k | (s[4] << 16) ^ (s[4] >> 16) ^ (s[5] << 16) ^ (s[5] >> 16) ^ s[6] ^ \ |
146 | 44.4k | (s[6] << 16) ^ (s[6] >> 16) ^ (s[7] << 16); \ |
147 | 44.4k | u[7] = m[7] ^ (s[0] & 0xffff0000) ^ (s[0] << 16) ^ (s[1] & 0xffff) ^ \ |
148 | 44.4k | (s[1] << 16) ^ (s[2] >> 16) ^ (s[3] << 16) ^ s[4] ^ (s[4] >> 16) ^ \ |
149 | 44.4k | (s[5] << 16) ^ (s[5] >> 16) ^ (s[6] >> 16) ^ (s[7] & 0xffff) ^ \ |
150 | 44.4k | (s[7] << 16) ^ (s[7] >> 16); |
151 | | |
152 | | #define SHIFT16(h, v, u) \ |
153 | 44.4k | v[0] = h[0] ^ (u[1] << 16) ^ (u[0] >> 16); \ |
154 | 44.4k | v[1] = h[1] ^ (u[2] << 16) ^ (u[1] >> 16); \ |
155 | 44.4k | v[2] = h[2] ^ (u[3] << 16) ^ (u[2] >> 16); \ |
156 | 44.4k | v[3] = h[3] ^ (u[4] << 16) ^ (u[3] >> 16); \ |
157 | 44.4k | v[4] = h[4] ^ (u[5] << 16) ^ (u[4] >> 16); \ |
158 | 44.4k | v[5] = h[5] ^ (u[6] << 16) ^ (u[5] >> 16); \ |
159 | 44.4k | v[6] = h[6] ^ (u[7] << 16) ^ (u[6] >> 16); \ |
160 | 44.4k | v[7] = h[7] ^ (u[0] & 0xffff0000) ^ (u[0] << 16) ^ (u[7] >> 16) ^ \ |
161 | 44.4k | (u[1] & 0xffff0000) ^ (u[1] << 16) ^ (u[6] << 16) ^ (u[7] & 0xffff0000); |
162 | | |
163 | | #define SHIFT61(h, v) \ |
164 | 44.4k | h[0] = (v[0] & 0xffff0000) ^ (v[0] << 16) ^ (v[0] >> 16) ^ (v[1] >> 16) ^ \ |
165 | 44.4k | (v[1] & 0xffff0000) ^ (v[2] << 16) ^ (v[3] >> 16) ^ (v[4] << 16) ^ \ |
166 | 44.4k | (v[5] >> 16) ^ v[5] ^ (v[6] >> 16) ^ (v[7] << 16) ^ (v[7] >> 16) ^ \ |
167 | 44.4k | (v[7] & 0xffff); \ |
168 | 44.4k | h[1] = (v[0] << 16) ^ (v[0] >> 16) ^ (v[0] & 0xffff0000) ^ (v[1] & 0xffff) ^ \ |
169 | 44.4k | v[2] ^ (v[2] >> 16) ^ (v[3] << 16) ^ (v[4] >> 16) ^ (v[5] << 16) ^ \ |
170 | 44.4k | (v[6] << 16) ^ v[6] ^ (v[7] & 0xffff0000) ^ (v[7] >> 16); \ |
171 | 44.4k | h[2] = (v[0] & 0xffff) ^ (v[0] << 16) ^ (v[1] << 16) ^ (v[1] >> 16) ^ \ |
172 | 44.4k | (v[1] & 0xffff0000) ^ (v[2] << 16) ^ (v[3] >> 16) ^ v[3] ^ (v[4] << 16) ^ \ |
173 | 44.4k | (v[5] >> 16) ^ v[6] ^ (v[6] >> 16) ^ (v[7] & 0xffff) ^ (v[7] << 16) ^ \ |
174 | 44.4k | (v[7] >> 16); \ |
175 | 44.4k | h[3] = (v[0] << 16) ^ (v[0] >> 16) ^ (v[0] & 0xffff0000) ^ \ |
176 | 44.4k | (v[1] & 0xffff0000) ^ (v[1] >> 16) ^ (v[2] << 16) ^ (v[2] >> 16) ^ v[2] ^ \ |
177 | 44.4k | (v[3] << 16) ^ (v[4] >> 16) ^ v[4] ^ (v[5] << 16) ^ (v[6] << 16) ^ \ |
178 | 44.4k | (v[7] & 0xffff) ^ (v[7] >> 16); \ |
179 | 44.4k | h[4] = (v[0] >> 16) ^ (v[1] << 16) ^ v[1] ^ (v[2] >> 16) ^ v[2] ^ \ |
180 | 44.4k | (v[3] << 16) ^ (v[3] >> 16) ^ v[3] ^ (v[4] << 16) ^ (v[5] >> 16) ^ \ |
181 | 44.4k | v[5] ^ (v[6] << 16) ^ (v[6] >> 16) ^ (v[7] << 16); \ |
182 | 44.4k | h[5] = (v[0] << 16) ^ (v[0] & 0xffff0000) ^ (v[1] << 16) ^ (v[1] >> 16) ^ \ |
183 | 44.4k | (v[1] & 0xffff0000) ^ (v[2] << 16) ^ v[2] ^ (v[3] >> 16) ^ v[3] ^ \ |
184 | 44.4k | (v[4] << 16) ^ (v[4] >> 16) ^ v[4] ^ (v[5] << 16) ^ (v[6] << 16) ^ \ |
185 | 44.4k | (v[6] >> 16) ^ v[6] ^ (v[7] << 16) ^ (v[7] >> 16) ^ (v[7] & 0xffff0000); \ |
186 | 44.4k | h[6] = v[0] ^ v[2] ^ (v[2] >> 16) ^ v[3] ^ (v[3] << 16) ^ v[4] ^ \ |
187 | 44.4k | (v[4] >> 16) ^ (v[5] << 16) ^ (v[5] >> 16) ^ v[5] ^ (v[6] << 16) ^ \ |
188 | 44.4k | (v[6] >> 16) ^ v[6] ^ (v[7] << 16) ^ v[7]; \ |
189 | 44.4k | h[7] = v[0] ^ (v[0] >> 16) ^ (v[1] << 16) ^ (v[1] >> 16) ^ (v[2] << 16) ^ \ |
190 | 44.4k | (v[3] >> 16) ^ v[3] ^ (v[4] << 16) ^ v[4] ^ (v[5] >> 16) ^ v[5] ^ \ |
191 | 44.4k | (v[6] << 16) ^ (v[6] >> 16) ^ (v[7] << 16) ^ v[7]; |
192 | | |
193 | | #define PASS(tables) \ |
194 | 177k | X(w, u, v); \ |
195 | 177k | P(key, w); \ |
196 | 177k | R((tables), key, h, i, t, l, r); \ |
197 | 177k | S(s, l, r); \ |
198 | 177k | if (i != 6) { \ |
199 | 133k | A(u, l, r); \ |
200 | 133k | if (i == 2) { \ |
201 | 44.4k | C(u); \ |
202 | 44.4k | } \ |
203 | 133k | AA(v, l, r); \ |
204 | 133k | } |
205 | | |
206 | | static inline void Gost(PHP_GOST_CTX *context, uint32_t data[8]) |
207 | 44.4k | { |
208 | 44.4k | int i; |
209 | 44.4k | uint32_t l, r, t, key[8], u[8], v[8], w[8], s[8], *h = context->state, *m = data; |
210 | | |
211 | 44.4k | memcpy(u, context->state, sizeof(u)); |
212 | 44.4k | memcpy(v, data, sizeof(v)); |
213 | | |
214 | 222k | for (i = 0; i < 8; i += 2) { |
215 | 177k | PASS(*context->tables); |
216 | 177k | } |
217 | 44.4k | SHIFT12(u, m, s); |
218 | 44.4k | SHIFT16(h, v, u); |
219 | 44.4k | SHIFT61(h, v); |
220 | 44.4k | } |
221 | | /* }}} */ |
222 | | |
223 | | static inline void GostTransform(PHP_GOST_CTX *context, const unsigned char input[32]) |
224 | 44.0k | { |
225 | 44.0k | int i, j; |
226 | 44.0k | uint32_t data[8], temp = 0; |
227 | | |
228 | 396k | for (i = 0, j = 0; i < 8; ++i, j += 4) { |
229 | 352k | data[i] = ((uint32_t) input[j]) | (((uint32_t) input[j + 1]) << 8) | |
230 | 352k | (((uint32_t) input[j + 2]) << 16) | (((uint32_t) input[j + 3]) << 24); |
231 | 352k | context->state[i + 8] += data[i] + temp; |
232 | 352k | temp = context->state[i + 8] < data[i] ? 1 : (context->state[i + 8] == data[i] ? temp : 0); |
233 | 352k | } |
234 | | |
235 | 44.0k | Gost(context, data); |
236 | 44.0k | } |
237 | | |
238 | | PHP_HASH_API void PHP_GOSTInit(PHP_GOST_CTX *context, ZEND_ATTRIBUTE_UNUSED HashTable *args) |
239 | 179 | { |
240 | 179 | memset(context, 0, sizeof(*context)); |
241 | 179 | context->tables = &tables_test; |
242 | 179 | } |
243 | | |
244 | | PHP_HASH_API void PHP_GOSTInitCrypto(PHP_GOST_CTX *context, ZEND_ATTRIBUTE_UNUSED HashTable *args) |
245 | 2 | { |
246 | 2 | PHP_GOSTInit(context, NULL); |
247 | 2 | context->tables = &tables_crypto; |
248 | 2 | } |
249 | | |
250 | | static const uint32_t MAX32 = 0xffffffffLU; |
251 | | |
252 | | PHP_HASH_API void PHP_GOSTUpdate(PHP_GOST_CTX *context, const unsigned char *input, size_t len) |
253 | 175 | { |
254 | 175 | if ((MAX32 - context->count[0]) < (len * 8)) { |
255 | 57 | context->count[1]++; |
256 | 57 | context->count[0] = MAX32 - context->count[0]; |
257 | 57 | context->count[0] = (len * 8) - context->count[0]; |
258 | 118 | } else { |
259 | 118 | context->count[0] += len * 8; |
260 | 118 | } |
261 | | |
262 | 175 | if (context->length + len < 32) { |
263 | 21 | memcpy(&context->buffer[context->length], input, len); |
264 | 21 | context->length += (unsigned char)len; |
265 | 154 | } else { |
266 | 154 | size_t i = 0, r = (context->length + len) % 32; |
267 | | |
268 | 154 | if (context->length) { |
269 | 126 | i = 32 - context->length; |
270 | 126 | memcpy(&context->buffer[context->length], input, i); |
271 | 126 | GostTransform(context, context->buffer); |
272 | 126 | } |
273 | | |
274 | 43.9k | for (; i + 32 <= len; i += 32) { |
275 | 43.7k | GostTransform(context, input + i); |
276 | 43.7k | } |
277 | | |
278 | 154 | memcpy(context->buffer, input + i, r); |
279 | 154 | ZEND_SECURE_ZERO(&context->buffer[r], 32 - r); |
280 | 154 | context->length = (unsigned char)r; |
281 | 154 | } |
282 | 175 | } |
283 | | |
284 | | PHP_HASH_API void PHP_GOSTFinal(unsigned char digest[32], PHP_GOST_CTX *context) |
285 | 175 | { |
286 | 175 | uint32_t i, j, l[8] = {0}; |
287 | | |
288 | 175 | if (context->length) { |
289 | 134 | GostTransform(context, context->buffer); |
290 | 134 | } |
291 | | |
292 | 175 | memcpy(l, context->count, sizeof(context->count)); |
293 | 175 | Gost(context, l); |
294 | 175 | memcpy(l, &context->state[8], sizeof(l)); |
295 | 175 | Gost(context, l); |
296 | | |
297 | 1.57k | for (i = 0, j = 0; j < 32; i++, j += 4) { |
298 | 1.40k | digest[j] = (unsigned char) (context->state[i] & 0xff); |
299 | 1.40k | digest[j + 1] = (unsigned char) ((context->state[i] >> 8) & 0xff); |
300 | 1.40k | digest[j + 2] = (unsigned char) ((context->state[i] >> 16) & 0xff); |
301 | 1.40k | digest[j + 3] = (unsigned char) ((context->state[i] >> 24) & 0xff); |
302 | 1.40k | } |
303 | | |
304 | 175 | ZEND_SECURE_ZERO(context, sizeof(*context)); |
305 | 175 | } |
306 | | |
307 | | static int php_gost_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv) |
308 | 179 | { |
309 | 179 | PHP_GOST_CTX *ctx = (PHP_GOST_CTX *) hash->context; |
310 | 179 | int r = FAILURE; |
311 | 179 | if (magic == PHP_HASH_SERIALIZE_MAGIC_SPEC |
312 | 179 | && (r = php_hash_unserialize_spec(hash, zv, PHP_GOST_SPEC)) == SUCCESS |
313 | 179 | && ctx->length < sizeof(ctx->buffer)) { |
314 | 175 | return SUCCESS; |
315 | 175 | } else { |
316 | 4 | return r != SUCCESS ? r : -2000; |
317 | 4 | } |
318 | 179 | } |
319 | | |
320 | | const php_hash_ops php_hash_gost_ops = { |
321 | | "gost", |
322 | | (php_hash_init_func_t) PHP_GOSTInit, |
323 | | (php_hash_update_func_t) PHP_GOSTUpdate, |
324 | | (php_hash_final_func_t) PHP_GOSTFinal, |
325 | | php_hash_copy, |
326 | | php_hash_serialize, |
327 | | php_gost_unserialize, |
328 | | PHP_GOST_SPEC, |
329 | | 32, |
330 | | 32, |
331 | | sizeof(PHP_GOST_CTX), |
332 | | 1 |
333 | | }; |
334 | | |
335 | | const php_hash_ops php_hash_gost_crypto_ops = { |
336 | | "gost-crypto", |
337 | | (php_hash_init_func_t) PHP_GOSTInitCrypto, |
338 | | (php_hash_update_func_t) PHP_GOSTUpdate, |
339 | | (php_hash_final_func_t) PHP_GOSTFinal, |
340 | | php_hash_copy, |
341 | | php_hash_serialize, |
342 | | php_gost_unserialize, |
343 | | PHP_GOST_SPEC, |
344 | | 32, |
345 | | 32, |
346 | | sizeof(PHP_GOST_CTX), |
347 | | 1 |
348 | | }; |