diff options
Diffstat (limited to 'src/gnsrecord')
-rw-r--r-- | src/gnsrecord/Makefile.am | 9 | ||||
-rw-r--r-- | src/gnsrecord/gnsrecord_crypto.c | 535 | ||||
-rw-r--r-- | src/gnsrecord/gnsrecord_crypto.h | 87 | ||||
-rw-r--r-- | src/gnsrecord/gnsrecord_misc.c | 19 | ||||
-rw-r--r-- | src/gnsrecord/gnsrecord_serialization.c | 56 | ||||
-rw-r--r-- | src/gnsrecord/gnunet-gnsrecord-tvg.c | 223 | ||||
-rw-r--r-- | src/gnsrecord/test_gnsrecord_crypto.c | 12 | ||||
-rw-r--r-- | src/gnsrecord/test_gnsrecord_testvectors.c | 128 |
8 files changed, 728 insertions, 341 deletions
diff --git a/src/gnsrecord/Makefile.am b/src/gnsrecord/Makefile.am index 42ac4ede4..4308d9c1a 100644 --- a/src/gnsrecord/Makefile.am +++ b/src/gnsrecord/Makefile.am | |||
@@ -20,6 +20,7 @@ check_PROGRAMS = \ | |||
20 | test_gnsrecord_crypto \ | 20 | test_gnsrecord_crypto \ |
21 | test_gnsrecord_serialization \ | 21 | test_gnsrecord_serialization \ |
22 | test_gnsrecord_block_expiration \ | 22 | test_gnsrecord_block_expiration \ |
23 | test_gnsrecord_testvectors \ | ||
23 | perf_gnsrecord_crypto | 24 | perf_gnsrecord_crypto |
24 | 25 | ||
25 | if ENABLE_TEST_RUN | 26 | if ENABLE_TEST_RUN |
@@ -85,6 +86,14 @@ libgnunet_plugin_gnsrecord_dns_la_LDFLAGS = \ | |||
85 | EXTRA_DIST = \ | 86 | EXTRA_DIST = \ |
86 | $(check_SCRIPTS) | 87 | $(check_SCRIPTS) |
87 | 88 | ||
89 | test_gnsrecord_testvectors_SOURCES = \ | ||
90 | test_gnsrecord_testvectors.c | ||
91 | test_gnsrecord_testvectors_LDADD = \ | ||
92 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
93 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
94 | libgnunetgnsrecord.la \ | ||
95 | $(top_builddir)/src/util/libgnunetutil.la | ||
96 | |||
88 | 97 | ||
89 | test_gnsrecord_serialization_SOURCES = \ | 98 | test_gnsrecord_serialization_SOURCES = \ |
90 | test_gnsrecord_serialization.c | 99 | test_gnsrecord_serialization.c |
diff --git a/src/gnsrecord/gnsrecord_crypto.c b/src/gnsrecord/gnsrecord_crypto.c index fe7db88b9..890ddb011 100644 --- a/src/gnsrecord/gnsrecord_crypto.c +++ b/src/gnsrecord/gnsrecord_crypto.c | |||
@@ -25,15 +25,7 @@ | |||
25 | * @author Matthias Wachs | 25 | * @author Matthias Wachs |
26 | * @author Christian Grothoff | 26 | * @author Christian Grothoff |
27 | */ | 27 | */ |
28 | #include "platform.h" | 28 | #include "gnsrecord_crypto.h" |
29 | #include "gnunet_util_lib.h" | ||
30 | #include "gnunet_constants.h" | ||
31 | #include "gnunet_signatures.h" | ||
32 | #include "gnunet_arm_service.h" | ||
33 | #include "gnunet_gnsrecord_lib.h" | ||
34 | #include "gnunet_dnsparser_lib.h" | ||
35 | #include "gnunet_tun_lib.h" | ||
36 | |||
37 | 29 | ||
38 | #define LOG(kind, ...) GNUNET_log_from (kind, "gnsrecord", __VA_ARGS__) | 30 | #define LOG(kind, ...) GNUNET_log_from (kind, "gnsrecord", __VA_ARGS__) |
39 | 31 | ||
@@ -103,8 +95,8 @@ eddsa_symmetric_decrypt ( | |||
103 | if (ctlen < 0) | 95 | if (ctlen < 0) |
104 | return GNUNET_SYSERR; | 96 | return GNUNET_SYSERR; |
105 | if (0 != crypto_secretbox_open_detached (result, | 97 | if (0 != crypto_secretbox_open_detached (result, |
106 | block, // Ciphertext | 98 | ((unsigned char*) block) + crypto_secretbox_MACBYTES, // Ciphertext |
107 | ((unsigned char*)block) + ctlen, // TAG | 99 | block, // Tag |
108 | ctlen, | 100 | ctlen, |
109 | nonce, key)) | 101 | nonce, key)) |
110 | { | 102 | { |
@@ -124,27 +116,19 @@ eddsa_symmetric_encrypt ( | |||
124 | { | 116 | { |
125 | if (size > crypto_secretbox_MESSAGEBYTES_MAX) | 117 | if (size > crypto_secretbox_MESSAGEBYTES_MAX) |
126 | return GNUNET_SYSERR; | 118 | return GNUNET_SYSERR; |
127 | crypto_secretbox_detached (result, // Ciphertext | 119 | crypto_secretbox_detached (result + crypto_secretbox_MACBYTES, // Ciphertext |
128 | result + size, // TAG | 120 | result, // TAG |
129 | block, size, nonce, key); | 121 | block, size, nonce, key); |
130 | return GNUNET_OK; | 122 | return GNUNET_OK; |
131 | } | 123 | } |
132 | 124 | ||
133 | 125 | ||
134 | /** | 126 | void |
135 | * Derive session key and iv from label and public key. | 127 | GNR_derive_block_aes_key (unsigned char *ctr, |
136 | * | 128 | unsigned char *key, |
137 | * @param iv initialization vector to initialize | 129 | const char *label, |
138 | * @param skey session key to initialize | 130 | uint64_t exp, |
139 | * @param label label to use for KDF | 131 | const struct GNUNET_CRYPTO_EcdsaPublicKey *pub) |
140 | * @param pub public key to use for KDF | ||
141 | */ | ||
142 | static void | ||
143 | derive_block_aes_key (unsigned char *ctr, | ||
144 | unsigned char *key, | ||
145 | const char *label, | ||
146 | uint64_t exp, | ||
147 | const struct GNUNET_CRYPTO_EcdsaPublicKey *pub) | ||
148 | { | 132 | { |
149 | static const char ctx_key[] = "gns-aes-ctx-key"; | 133 | static const char ctx_key[] = "gns-aes-ctx-key"; |
150 | static const char ctx_iv[] = "gns-aes-ctx-iv"; | 134 | static const char ctx_iv[] = "gns-aes-ctx-iv"; |
@@ -168,23 +152,15 @@ derive_block_aes_key (unsigned char *ctr, | |||
168 | } | 152 | } |
169 | 153 | ||
170 | 154 | ||
171 | /** | 155 | void |
172 | * Derive session key and iv from label and public key. | 156 | GNR_derive_block_xsalsa_key (unsigned char *nonce, |
173 | * | 157 | unsigned char *key, |
174 | * @param nonce initialization vector to initialize | 158 | const char *label, |
175 | * @param skey session key to initialize | 159 | uint64_t exp, |
176 | * @param label label to use for KDF | 160 | const struct GNUNET_CRYPTO_EddsaPublicKey *pub) |
177 | * @param pub public key to use for KDF | ||
178 | */ | ||
179 | static void | ||
180 | derive_block_xsalsa_key (unsigned char *nonce, | ||
181 | unsigned char *key, | ||
182 | const char *label, | ||
183 | uint64_t exp, | ||
184 | const struct GNUNET_CRYPTO_EddsaPublicKey *pub) | ||
185 | { | 161 | { |
186 | static const char ctx_key[] = "gns-aes-ctx-key"; | 162 | static const char ctx_key[] = "gns-xsalsa-ctx-key"; |
187 | static const char ctx_iv[] = "gns-aes-ctx-iv"; | 163 | static const char ctx_iv[] = "gns-xsalsa-ctx-iv"; |
188 | 164 | ||
189 | GNUNET_CRYPTO_kdf (key, crypto_secretbox_KEYBYTES, | 165 | GNUNET_CRYPTO_kdf (key, crypto_secretbox_KEYBYTES, |
190 | ctx_key, strlen (ctx_key), | 166 | ctx_key, strlen (ctx_key), |
@@ -204,6 +180,20 @@ derive_block_xsalsa_key (unsigned char *nonce, | |||
204 | } | 180 | } |
205 | 181 | ||
206 | 182 | ||
183 | static ssize_t | ||
184 | block_get_size_ecdsa (const struct GNUNET_GNSRECORD_Data *rd, | ||
185 | unsigned int rd_count) | ||
186 | { | ||
187 | ssize_t len; | ||
188 | |||
189 | len = GNUNET_GNSRECORD_records_get_size (rd_count, rd); | ||
190 | if (len < 0) | ||
191 | return -1; | ||
192 | len += sizeof(struct GNUNET_GNSRECORD_Block); | ||
193 | return len; | ||
194 | } | ||
195 | |||
196 | |||
207 | /** | 197 | /** |
208 | * Sign name and records | 198 | * Sign name and records |
209 | * | 199 | * |
@@ -213,20 +203,22 @@ derive_block_xsalsa_key (unsigned char *nonce, | |||
213 | * @param label the name for the records | 203 | * @param label the name for the records |
214 | * @param rd record data | 204 | * @param rd record data |
215 | * @param rd_count number of records | 205 | * @param rd_count number of records |
216 | * @return NULL on error (block too large) | 206 | * @param block the block result. Must be allocated sufficiently. |
207 | * @return GNUNET_SYSERR on error (otherwise GNUNET_OK) | ||
217 | */ | 208 | */ |
218 | static struct GNUNET_GNSRECORD_Block * | 209 | static enum GNUNET_GenericReturnValue |
219 | block_create_ecdsa (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key, | 210 | block_create_ecdsa (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key, |
220 | const struct GNUNET_CRYPTO_EcdsaPublicKey *pkey, | 211 | const struct GNUNET_CRYPTO_EcdsaPublicKey *pkey, |
221 | struct GNUNET_TIME_Absolute expire, | 212 | struct GNUNET_TIME_Absolute expire, |
222 | const char *label, | 213 | const char *label, |
223 | const struct GNUNET_GNSRECORD_Data *rd, | 214 | const struct GNUNET_GNSRECORD_Data *rd, |
224 | unsigned int rd_count) | 215 | unsigned int rd_count, |
216 | struct GNUNET_GNSRECORD_Block **block) | ||
225 | { | 217 | { |
226 | ssize_t payload_len = GNUNET_GNSRECORD_records_get_size (rd_count, | 218 | ssize_t payload_len = GNUNET_GNSRECORD_records_get_size (rd_count, |
227 | rd); | 219 | rd); |
228 | struct GNUNET_GNSRECORD_Block *block; | ||
229 | struct GNUNET_GNSRECORD_EcdsaBlock *ecblock; | 220 | struct GNUNET_GNSRECORD_EcdsaBlock *ecblock; |
221 | struct GNRBlockPS *gnr_block; | ||
230 | struct GNUNET_CRYPTO_EcdsaPrivateKey *dkey; | 222 | struct GNUNET_CRYPTO_EcdsaPrivateKey *dkey; |
231 | unsigned char ctr[GNUNET_CRYPTO_AES_KEY_LENGTH / 2]; | 223 | unsigned char ctr[GNUNET_CRYPTO_AES_KEY_LENGTH / 2]; |
232 | unsigned char skey[GNUNET_CRYPTO_AES_KEY_LENGTH]; | 224 | unsigned char skey[GNUNET_CRYPTO_AES_KEY_LENGTH]; |
@@ -237,12 +229,12 @@ block_create_ecdsa (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key, | |||
237 | if (payload_len < 0) | 229 | if (payload_len < 0) |
238 | { | 230 | { |
239 | GNUNET_break (0); | 231 | GNUNET_break (0); |
240 | return NULL; | 232 | return GNUNET_SYSERR; |
241 | } | 233 | } |
242 | if (payload_len > GNUNET_GNSRECORD_MAX_BLOCK_SIZE) | 234 | if (payload_len > GNUNET_GNSRECORD_MAX_BLOCK_SIZE) |
243 | { | 235 | { |
244 | GNUNET_break (0); | 236 | GNUNET_break (0); |
245 | return NULL; | 237 | return GNUNET_SYSERR; |
246 | } | 238 | } |
247 | /* convert relative to absolute times */ | 239 | /* convert relative to absolute times */ |
248 | now = GNUNET_TIME_absolute_get (); | 240 | now = GNUNET_TIME_absolute_get (); |
@@ -260,62 +252,70 @@ block_create_ecdsa (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key, | |||
260 | } | 252 | } |
261 | } | 253 | } |
262 | /* serialize */ | 254 | /* serialize */ |
255 | *block = GNUNET_malloc (sizeof (struct GNUNET_GNSRECORD_Block) + payload_len); | ||
256 | (*block)->size = htonl(sizeof (struct GNUNET_GNSRECORD_Block) + payload_len); | ||
263 | rd_count_nbo = htonl (rd_count); | 257 | rd_count_nbo = htonl (rd_count); |
264 | { | 258 | { |
265 | char payload[sizeof(uint32_t) + payload_len]; | 259 | char payload[payload_len]; |
266 | 260 | ||
267 | GNUNET_memcpy (payload, | ||
268 | &rd_count_nbo, | ||
269 | sizeof(uint32_t)); | ||
270 | GNUNET_assert (payload_len == | 261 | GNUNET_assert (payload_len == |
271 | GNUNET_GNSRECORD_records_serialize (rd_count, | 262 | GNUNET_GNSRECORD_records_serialize (rd_count, |
272 | rdc, | 263 | rdc, |
273 | payload_len, | 264 | payload_len, |
274 | &payload[sizeof(uint32_t) | 265 | payload)); |
275 | ])); | 266 | gnr_block = GNUNET_malloc (sizeof (struct GNRBlockPS) + payload_len); |
276 | block = GNUNET_malloc (sizeof(struct GNUNET_GNSRECORD_Block) | 267 | ecblock = &(*block)->ecdsa_block; |
277 | + sizeof(uint32_t) | 268 | (*block)->type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); |
278 | + payload_len); | 269 | gnr_block->purpose.size = htonl (sizeof(struct GNRBlockPS) + payload_len); |
279 | ecblock = &block->ecdsa_block; | 270 | gnr_block->purpose.purpose = |
280 | block->type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | 271 | htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN); |
281 | ecblock->purpose.size = htonl (sizeof(uint32_t) | 272 | gnr_block->expiration_time = GNUNET_TIME_absolute_hton (expire); |
282 | + payload_len | 273 | ecblock->expiration_time = gnr_block->expiration_time; |
283 | + sizeof(struct | ||
284 | GNUNET_CRYPTO_EccSignaturePurpose) | ||
285 | + sizeof(struct GNUNET_TIME_AbsoluteNBO)); | ||
286 | ecblock->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN); | ||
287 | ecblock->expiration_time = GNUNET_TIME_absolute_hton (expire); | ||
288 | /* encrypt and sign */ | 274 | /* encrypt and sign */ |
289 | dkey = GNUNET_CRYPTO_ecdsa_private_key_derive (key, | 275 | dkey = GNUNET_CRYPTO_ecdsa_private_key_derive (key, |
290 | label, | 276 | label, |
291 | "gns"); | 277 | "gns"); |
292 | GNUNET_CRYPTO_ecdsa_key_get_public (dkey, | 278 | GNUNET_CRYPTO_ecdsa_key_get_public (dkey, |
293 | &ecblock->derived_key); | 279 | &ecblock->derived_key); |
294 | derive_block_aes_key (ctr, | 280 | GNR_derive_block_aes_key (ctr, |
295 | skey, | 281 | skey, |
296 | label, | 282 | label, |
297 | ecblock->expiration_time.abs_value_us__, | 283 | ecblock->expiration_time.abs_value_us__, |
298 | pkey); | 284 | pkey); |
299 | GNUNET_break (payload_len + sizeof(uint32_t) == | 285 | GNUNET_break (payload_len == |
300 | ecdsa_symmetric_encrypt (payload, | 286 | ecdsa_symmetric_encrypt (payload, |
301 | payload_len | 287 | payload_len, |
302 | + sizeof(uint32_t), | ||
303 | skey, | 288 | skey, |
304 | ctr, | 289 | ctr, |
305 | &ecblock[1])); | 290 | &ecblock[1])); |
291 | GNUNET_memcpy (&gnr_block[1], &ecblock[1], payload_len); | ||
306 | } | 292 | } |
307 | if (GNUNET_OK != | 293 | if (GNUNET_OK != |
308 | GNUNET_CRYPTO_ecdsa_sign_ (dkey, | 294 | GNUNET_CRYPTO_ecdsa_sign_ (dkey, |
309 | &ecblock->purpose, | 295 | &gnr_block->purpose, |
310 | &ecblock->signature)) | 296 | &ecblock->signature)) |
311 | { | 297 | { |
312 | GNUNET_break (0); | 298 | GNUNET_break (0); |
299 | GNUNET_free (*block); | ||
313 | GNUNET_free (dkey); | 300 | GNUNET_free (dkey); |
314 | GNUNET_free (block); | 301 | return GNUNET_SYSERR; |
315 | return NULL; | ||
316 | } | 302 | } |
317 | GNUNET_free (dkey); | 303 | GNUNET_free (dkey); |
318 | return block; | 304 | return GNUNET_OK; |
305 | } | ||
306 | |||
307 | static ssize_t | ||
308 | block_get_size_eddsa (const struct GNUNET_GNSRECORD_Data *rd, | ||
309 | unsigned int rd_count) | ||
310 | { | ||
311 | ssize_t len; | ||
312 | |||
313 | len = GNUNET_GNSRECORD_records_get_size (rd_count, rd); | ||
314 | if (len < 0) | ||
315 | return -1; | ||
316 | len += sizeof(struct GNUNET_GNSRECORD_Block); | ||
317 | len += crypto_secretbox_MACBYTES; | ||
318 | return len; | ||
319 | } | 319 | } |
320 | 320 | ||
321 | 321 | ||
@@ -328,20 +328,22 @@ block_create_ecdsa (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key, | |||
328 | * @param label the name for the records | 328 | * @param label the name for the records |
329 | * @param rd record data | 329 | * @param rd record data |
330 | * @param rd_count number of records | 330 | * @param rd_count number of records |
331 | * @return NULL on error (block too large) | 331 | * @param block where to store the block. Must be allocated sufficiently. |
332 | * @return GNUNET_SYSERR on error (otherwise GNUNET_OK) | ||
332 | */ | 333 | */ |
333 | static struct GNUNET_GNSRECORD_Block * | 334 | enum GNUNET_GenericReturnValue |
334 | block_create_eddsa (const struct GNUNET_CRYPTO_EddsaPrivateKey *key, | 335 | block_create_eddsa (const struct GNUNET_CRYPTO_EddsaPrivateKey *key, |
335 | const struct GNUNET_CRYPTO_EddsaPublicKey *pkey, | 336 | const struct GNUNET_CRYPTO_EddsaPublicKey *pkey, |
336 | struct GNUNET_TIME_Absolute expire, | 337 | struct GNUNET_TIME_Absolute expire, |
337 | const char *label, | 338 | const char *label, |
338 | const struct GNUNET_GNSRECORD_Data *rd, | 339 | const struct GNUNET_GNSRECORD_Data *rd, |
339 | unsigned int rd_count) | 340 | unsigned int rd_count, |
341 | struct GNUNET_GNSRECORD_Block **block) | ||
340 | { | 342 | { |
341 | ssize_t payload_len = GNUNET_GNSRECORD_records_get_size (rd_count, | 343 | ssize_t payload_len = GNUNET_GNSRECORD_records_get_size (rd_count, |
342 | rd); | 344 | rd); |
343 | struct GNUNET_GNSRECORD_Block *block; | ||
344 | struct GNUNET_GNSRECORD_EddsaBlock *edblock; | 345 | struct GNUNET_GNSRECORD_EddsaBlock *edblock; |
346 | struct GNRBlockPS *gnr_block; | ||
345 | struct GNUNET_CRYPTO_EddsaPrivateScalar dkey; | 347 | struct GNUNET_CRYPTO_EddsaPrivateScalar dkey; |
346 | unsigned char nonce[crypto_secretbox_NONCEBYTES]; | 348 | unsigned char nonce[crypto_secretbox_NONCEBYTES]; |
347 | unsigned char skey[crypto_secretbox_KEYBYTES]; | 349 | unsigned char skey[crypto_secretbox_KEYBYTES]; |
@@ -352,12 +354,12 @@ block_create_eddsa (const struct GNUNET_CRYPTO_EddsaPrivateKey *key, | |||
352 | if (payload_len < 0) | 354 | if (payload_len < 0) |
353 | { | 355 | { |
354 | GNUNET_break (0); | 356 | GNUNET_break (0); |
355 | return NULL; | 357 | return GNUNET_SYSERR; |
356 | } | 358 | } |
357 | if (payload_len > GNUNET_GNSRECORD_MAX_BLOCK_SIZE) | 359 | if (payload_len > GNUNET_GNSRECORD_MAX_BLOCK_SIZE) |
358 | { | 360 | { |
359 | GNUNET_break (0); | 361 | GNUNET_break (0); |
360 | return NULL; | 362 | return GNUNET_SYSERR; |
361 | } | 363 | } |
362 | /* convert relative to absolute times */ | 364 | /* convert relative to absolute times */ |
363 | now = GNUNET_TIME_absolute_get (); | 365 | now = GNUNET_TIME_absolute_get (); |
@@ -375,33 +377,32 @@ block_create_eddsa (const struct GNUNET_CRYPTO_EddsaPrivateKey *key, | |||
375 | } | 377 | } |
376 | } | 378 | } |
377 | /* serialize */ | 379 | /* serialize */ |
380 | *block = GNUNET_malloc (sizeof (struct GNUNET_GNSRECORD_Block) | ||
381 | + payload_len + crypto_secretbox_MACBYTES); | ||
382 | (*block)->size = htonl(sizeof (struct GNUNET_GNSRECORD_Block) | ||
383 | + payload_len + crypto_secretbox_MACBYTES); | ||
378 | rd_count_nbo = htonl (rd_count); | 384 | rd_count_nbo = htonl (rd_count); |
379 | { | 385 | { |
380 | char payload[sizeof(uint32_t) + payload_len]; | 386 | char payload[payload_len]; |
381 | 387 | ||
382 | GNUNET_memcpy (payload, | ||
383 | &rd_count_nbo, | ||
384 | sizeof(uint32_t)); | ||
385 | GNUNET_assert (payload_len == | 388 | GNUNET_assert (payload_len == |
386 | GNUNET_GNSRECORD_records_serialize (rd_count, | 389 | GNUNET_GNSRECORD_records_serialize (rd_count, |
387 | rdc, | 390 | rdc, |
388 | payload_len, | 391 | payload_len, |
389 | &payload[sizeof(uint32_t) | 392 | payload)); |
390 | ])); | 393 | gnr_block = GNUNET_malloc (sizeof (struct GNRBlockPS) |
391 | block = GNUNET_malloc (sizeof(struct GNUNET_GNSRECORD_Block) | 394 | + payload_len |
392 | + sizeof(uint32_t) | 395 | + crypto_secretbox_MACBYTES); |
393 | + payload_len | 396 | edblock = &(*block)->eddsa_block; |
394 | + crypto_secretbox_MACBYTES); | 397 | (*block)->type = htonl (GNUNET_GNSRECORD_TYPE_EDKEY); |
395 | edblock = &block->eddsa_block; | 398 | gnr_block->purpose.size = |
396 | block->type = htonl (GNUNET_GNSRECORD_TYPE_EDKEY); | 399 | htonl (sizeof(struct GNRBlockPS) |
397 | edblock->purpose.size = htonl (sizeof(uint32_t) | 400 | + payload_len |
398 | + payload_len | 401 | + crypto_secretbox_MACBYTES); |
399 | + sizeof(struct | 402 | gnr_block->purpose.purpose = |
400 | GNUNET_CRYPTO_EccSignaturePurpose) | 403 | htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN); |
401 | + sizeof(struct GNUNET_TIME_AbsoluteNBO) | 404 | gnr_block->expiration_time = GNUNET_TIME_absolute_hton (expire); |
402 | + crypto_secretbox_MACBYTES); | 405 | edblock->expiration_time = gnr_block->expiration_time; |
403 | edblock->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN); | ||
404 | edblock->expiration_time = GNUNET_TIME_absolute_hton (expire); | ||
405 | /* encrypt and sign */ | 406 | /* encrypt and sign */ |
406 | GNUNET_CRYPTO_eddsa_private_key_derive (key, | 407 | GNUNET_CRYPTO_eddsa_private_key_derive (key, |
407 | label, | 408 | label, |
@@ -409,45 +410,63 @@ block_create_eddsa (const struct GNUNET_CRYPTO_EddsaPrivateKey *key, | |||
409 | &dkey); | 410 | &dkey); |
410 | GNUNET_CRYPTO_eddsa_key_get_public_from_scalar (&dkey, | 411 | GNUNET_CRYPTO_eddsa_key_get_public_from_scalar (&dkey, |
411 | &edblock->derived_key); | 412 | &edblock->derived_key); |
412 | derive_block_xsalsa_key (nonce, | 413 | GNR_derive_block_xsalsa_key (nonce, |
413 | skey, | 414 | skey, |
414 | label, | 415 | label, |
415 | edblock->expiration_time.abs_value_us__, | 416 | edblock->expiration_time.abs_value_us__, |
416 | pkey); | 417 | pkey); |
417 | GNUNET_break (GNUNET_OK == | 418 | GNUNET_break (GNUNET_OK == |
418 | eddsa_symmetric_encrypt (payload, | 419 | eddsa_symmetric_encrypt (payload, |
419 | payload_len | 420 | payload_len, |
420 | + sizeof(uint32_t), | ||
421 | skey, | 421 | skey, |
422 | nonce, | 422 | nonce, |
423 | &edblock[1])); | 423 | &edblock[1])); |
424 | GNUNET_memcpy (&gnr_block[1], &edblock[1], | ||
425 | payload_len + crypto_secretbox_MACBYTES); | ||
426 | |||
427 | GNUNET_CRYPTO_eddsa_sign_with_scalar (&dkey, | ||
428 | &gnr_block->purpose, | ||
429 | &edblock->signature); | ||
424 | } | 430 | } |
425 | GNUNET_CRYPTO_eddsa_sign_with_scalar (&dkey, | 431 | return GNUNET_OK; |
426 | &edblock->purpose, | ||
427 | &edblock->signature); | ||
428 | return block; | ||
429 | } | 432 | } |
430 | 433 | ||
434 | ssize_t | ||
435 | GNUNET_GNSRECORD_block_calculate_size (const struct | ||
436 | GNUNET_IDENTITY_PrivateKey *key, | ||
437 | const struct GNUNET_GNSRECORD_Data *rd, | ||
438 | unsigned int rd_count) | ||
439 | { | ||
440 | struct GNUNET_IDENTITY_PublicKey pkey; | ||
441 | ssize_t res; | ||
431 | 442 | ||
432 | /** | 443 | GNUNET_IDENTITY_key_get_public (key, |
433 | * Sign name and records | 444 | &pkey); |
434 | * | 445 | switch (ntohl (key->type)) |
435 | * @param key the private key | 446 | { |
436 | * @param expire block expiration | 447 | case GNUNET_GNSRECORD_TYPE_PKEY: |
437 | * @param label the name for the records | 448 | res = block_get_size_ecdsa (rd, rd_count); |
438 | * @param rd record data | 449 | break; |
439 | * @param rd_count number of records | 450 | case GNUNET_GNSRECORD_TYPE_EDKEY: |
440 | * @return NULL on error (block too large) | 451 | res = block_get_size_eddsa (rd, rd_count); |
441 | */ | 452 | break; |
442 | struct GNUNET_GNSRECORD_Block * | 453 | default: |
454 | GNUNET_assert (0); | ||
455 | } | ||
456 | return -1; | ||
457 | |||
458 | } | ||
459 | |||
460 | enum GNUNET_GenericReturnValue | ||
443 | GNUNET_GNSRECORD_block_create (const struct GNUNET_IDENTITY_PrivateKey *key, | 461 | GNUNET_GNSRECORD_block_create (const struct GNUNET_IDENTITY_PrivateKey *key, |
444 | struct GNUNET_TIME_Absolute expire, | 462 | struct GNUNET_TIME_Absolute expire, |
445 | const char *label, | 463 | const char *label, |
446 | const struct GNUNET_GNSRECORD_Data *rd, | 464 | const struct GNUNET_GNSRECORD_Data *rd, |
447 | unsigned int rd_count) | 465 | unsigned int rd_count, |
466 | struct GNUNET_GNSRECORD_Block **result) | ||
448 | { | 467 | { |
449 | struct GNUNET_IDENTITY_PublicKey pkey; | 468 | struct GNUNET_IDENTITY_PublicKey pkey; |
450 | struct GNUNET_GNSRECORD_Block *res = NULL; | 469 | enum GNUNET_GenericReturnValue res = GNUNET_SYSERR; |
451 | char *norm_label; | 470 | char *norm_label; |
452 | 471 | ||
453 | GNUNET_IDENTITY_key_get_public (key, | 472 | GNUNET_IDENTITY_key_get_public (key, |
@@ -456,24 +475,26 @@ GNUNET_GNSRECORD_block_create (const struct GNUNET_IDENTITY_PrivateKey *key, | |||
456 | 475 | ||
457 | switch (ntohl (key->type)) | 476 | switch (ntohl (key->type)) |
458 | { | 477 | { |
459 | case GNUNET_GNSRECORD_TYPE_PKEY: | 478 | case GNUNET_GNSRECORD_TYPE_PKEY: |
460 | res = block_create_ecdsa (&key->ecdsa_key, | 479 | res = block_create_ecdsa (&key->ecdsa_key, |
461 | &pkey.ecdsa_key, | 480 | &pkey.ecdsa_key, |
462 | expire, | 481 | expire, |
463 | norm_label, | 482 | norm_label, |
464 | rd, | 483 | rd, |
465 | rd_count); | 484 | rd_count, |
466 | break; | 485 | result); |
467 | case GNUNET_GNSRECORD_TYPE_EDKEY: | 486 | break; |
468 | res = block_create_eddsa (&key->eddsa_key, | 487 | case GNUNET_GNSRECORD_TYPE_EDKEY: |
469 | &pkey.eddsa_key, | 488 | res = block_create_eddsa (&key->eddsa_key, |
470 | expire, | 489 | &pkey.eddsa_key, |
471 | norm_label, | 490 | expire, |
472 | rd, | 491 | norm_label, |
473 | rd_count); | 492 | rd, |
474 | break; | 493 | rd_count, |
475 | default: | 494 | result); |
476 | GNUNET_assert (0); | 495 | break; |
496 | default: | ||
497 | GNUNET_assert (0); | ||
477 | } | 498 | } |
478 | GNUNET_free (norm_label); | 499 | GNUNET_free (norm_label); |
479 | return res; | 500 | return res; |
@@ -497,28 +518,17 @@ struct KeyCacheLine | |||
497 | }; | 518 | }; |
498 | 519 | ||
499 | 520 | ||
500 | /** | 521 | enum GNUNET_GenericReturnValue |
501 | * Sign name and records, cache derived public key (also keeps the | ||
502 | * private key in static memory, so do not use this function if | ||
503 | * keeping the private key in the process'es RAM is a major issue). | ||
504 | * | ||
505 | * @param key the private key | ||
506 | * @param expire block expiration | ||
507 | * @param label the name for the records | ||
508 | * @param rd record data | ||
509 | * @param rd_count number of records | ||
510 | * @return NULL on error (block too large) | ||
511 | */ | ||
512 | struct GNUNET_GNSRECORD_Block * | ||
513 | GNUNET_GNSRECORD_block_create2 (const struct GNUNET_IDENTITY_PrivateKey *pkey, | 522 | GNUNET_GNSRECORD_block_create2 (const struct GNUNET_IDENTITY_PrivateKey *pkey, |
514 | struct GNUNET_TIME_Absolute expire, | 523 | struct GNUNET_TIME_Absolute expire, |
515 | const char *label, | 524 | const char *label, |
516 | const struct GNUNET_GNSRECORD_Data *rd, | 525 | const struct GNUNET_GNSRECORD_Data *rd, |
517 | unsigned int rd_count) | 526 | unsigned int rd_count, |
527 | struct GNUNET_GNSRECORD_Block **result) | ||
518 | { | 528 | { |
519 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *key; | 529 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *key; |
520 | struct GNUNET_CRYPTO_EddsaPublicKey edpubkey; | 530 | struct GNUNET_CRYPTO_EddsaPublicKey edpubkey; |
521 | struct GNUNET_GNSRECORD_Block *res = NULL; | 531 | enum GNUNET_GenericReturnValue res = GNUNET_SYSERR; |
522 | char *norm_label; | 532 | char *norm_label; |
523 | 533 | ||
524 | norm_label = GNUNET_GNSRECORD_string_normalize (label); | 534 | norm_label = GNUNET_GNSRECORD_string_normalize (label); |
@@ -546,7 +556,8 @@ GNUNET_GNSRECORD_block_create2 (const struct GNUNET_IDENTITY_PrivateKey *pkey, | |||
546 | expire, | 556 | expire, |
547 | norm_label, | 557 | norm_label, |
548 | rd, | 558 | rd, |
549 | rd_count); | 559 | rd_count, |
560 | result); | ||
550 | } | 561 | } |
551 | else if (GNUNET_IDENTITY_TYPE_EDDSA == ntohl (pkey->type)) | 562 | else if (GNUNET_IDENTITY_TYPE_EDDSA == ntohl (pkey->type)) |
552 | { | 563 | { |
@@ -557,7 +568,8 @@ GNUNET_GNSRECORD_block_create2 (const struct GNUNET_IDENTITY_PrivateKey *pkey, | |||
557 | expire, | 568 | expire, |
558 | norm_label, | 569 | norm_label, |
559 | rd, | 570 | rd, |
560 | rd_count); | 571 | rd_count, |
572 | result); | ||
561 | } | 573 | } |
562 | GNUNET_free (norm_label); | 574 | GNUNET_free (norm_label); |
563 | return res; | 575 | return res; |
@@ -574,64 +586,76 @@ GNUNET_GNSRECORD_block_create2 (const struct GNUNET_IDENTITY_PrivateKey *pkey, | |||
574 | enum GNUNET_GenericReturnValue | 586 | enum GNUNET_GenericReturnValue |
575 | GNUNET_GNSRECORD_block_verify (const struct GNUNET_GNSRECORD_Block *block) | 587 | GNUNET_GNSRECORD_block_verify (const struct GNUNET_GNSRECORD_Block *block) |
576 | { | 588 | { |
589 | struct GNRBlockPS *purp; | ||
590 | size_t payload_len = ntohl (block->size) | ||
591 | - sizeof (struct GNUNET_GNSRECORD_Block); | ||
592 | enum GNUNET_GenericReturnValue res = GNUNET_NO; | ||
593 | purp = GNUNET_malloc (sizeof (struct GNRBlockPS) + payload_len); | ||
594 | purp->purpose.size = htonl (sizeof (struct GNRBlockPS) + payload_len); | ||
595 | purp->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN); | ||
596 | GNUNET_memcpy (&purp[1], &block[1], payload_len); | ||
597 | |||
577 | switch (ntohl (block->type)) | 598 | switch (ntohl (block->type)) |
578 | { | 599 | { |
579 | case GNUNET_GNSRECORD_TYPE_PKEY: | 600 | case GNUNET_GNSRECORD_TYPE_PKEY: |
580 | return GNUNET_CRYPTO_ecdsa_verify_ ( | 601 | purp->expiration_time = block->ecdsa_block.expiration_time; |
581 | GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN, | 602 | res = GNUNET_CRYPTO_ecdsa_verify_ ( |
582 | &block->ecdsa_block.purpose, | 603 | GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN, |
583 | &block->ecdsa_block.signature, | 604 | &purp->purpose, |
584 | &block->ecdsa_block.derived_key); | 605 | &block->ecdsa_block.signature, |
585 | case GNUNET_GNSRECORD_TYPE_EDKEY: | 606 | &block->ecdsa_block.derived_key); |
586 | return GNUNET_CRYPTO_eddsa_verify_ ( | 607 | break; |
587 | GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN, | 608 | case GNUNET_GNSRECORD_TYPE_EDKEY: |
588 | &block->eddsa_block.purpose, | 609 | purp->expiration_time = block->eddsa_block.expiration_time; |
589 | &block->eddsa_block.signature, | 610 | res = GNUNET_CRYPTO_eddsa_verify_ ( |
590 | &block->eddsa_block.derived_key); | 611 | GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN, |
591 | default: | 612 | &purp->purpose, |
592 | return GNUNET_NO; | 613 | &block->eddsa_block.signature, |
614 | &block->eddsa_block.derived_key); | ||
615 | break; | ||
616 | default: | ||
617 | res = GNUNET_NO; | ||
593 | } | 618 | } |
619 | GNUNET_free (purp); | ||
620 | return res; | ||
594 | } | 621 | } |
595 | 622 | ||
596 | 623 | ||
597 | enum GNUNET_GenericReturnValue | 624 | enum GNUNET_GenericReturnValue |
598 | block_decrypt_ecdsa (const struct GNUNET_GNSRECORD_EcdsaBlock *block, | 625 | block_decrypt_ecdsa (const struct GNUNET_GNSRECORD_Block *block, |
599 | const struct | 626 | const struct |
600 | GNUNET_CRYPTO_EcdsaPublicKey *zone_key, | 627 | GNUNET_CRYPTO_EcdsaPublicKey *zone_key, |
601 | const char *label, | 628 | const char *label, |
602 | GNUNET_GNSRECORD_RecordCallback proc, | 629 | GNUNET_GNSRECORD_RecordCallback proc, |
603 | void *proc_cls) | 630 | void *proc_cls) |
604 | { | 631 | { |
605 | size_t payload_len = ntohl (block->purpose.size) | 632 | size_t payload_len = ntohl (block->size) - sizeof (struct |
606 | - sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) | 633 | GNUNET_GNSRECORD_Block); |
607 | - sizeof(struct GNUNET_TIME_AbsoluteNBO); | ||
608 | unsigned char ctr[GNUNET_CRYPTO_AES_KEY_LENGTH / 2]; | 634 | unsigned char ctr[GNUNET_CRYPTO_AES_KEY_LENGTH / 2]; |
609 | unsigned char key[GNUNET_CRYPTO_AES_KEY_LENGTH]; | 635 | unsigned char key[GNUNET_CRYPTO_AES_KEY_LENGTH]; |
610 | 636 | ||
611 | if (ntohl (block->purpose.size) < | 637 | if (ntohl (block->size) < |
612 | sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) | 638 | sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) |
613 | + sizeof(struct GNUNET_TIME_AbsoluteNBO)) | 639 | + sizeof(struct GNUNET_TIME_AbsoluteNBO)) |
614 | { | 640 | { |
615 | GNUNET_break_op (0); | 641 | GNUNET_break_op (0); |
616 | return GNUNET_SYSERR; | 642 | return GNUNET_SYSERR; |
617 | } | 643 | } |
618 | derive_block_aes_key (ctr, | 644 | GNR_derive_block_aes_key (ctr, |
619 | key, | 645 | key, |
620 | label, | 646 | label, |
621 | block->expiration_time.abs_value_us__, | 647 | block->ecdsa_block.expiration_time.abs_value_us__, |
622 | zone_key); | 648 | zone_key); |
623 | { | 649 | { |
624 | char payload[payload_len]; | 650 | char payload[payload_len]; |
625 | uint32_t rd_count; | 651 | unsigned int rd_count; |
626 | 652 | ||
627 | GNUNET_break (payload_len == | 653 | GNUNET_break (payload_len == |
628 | ecdsa_symmetric_decrypt (&block[1], payload_len, | 654 | ecdsa_symmetric_decrypt (&block[1], payload_len, |
629 | key, ctr, | 655 | key, ctr, |
630 | payload)); | 656 | payload)); |
631 | GNUNET_memcpy (&rd_count, | 657 | rd_count = GNUNET_GNSRECORD_records_deserialize_get_size (payload_len, |
632 | payload, | 658 | payload); |
633 | sizeof(uint32_t)); | ||
634 | rd_count = ntohl (rd_count); | ||
635 | if (rd_count > 2048) | 659 | if (rd_count > 2048) |
636 | { | 660 | { |
637 | /* limit to sane value */ | 661 | /* limit to sane value */ |
@@ -644,8 +668,8 @@ block_decrypt_ecdsa (const struct GNUNET_GNSRECORD_EcdsaBlock *block, | |||
644 | struct GNUNET_TIME_Absolute now; | 668 | struct GNUNET_TIME_Absolute now; |
645 | 669 | ||
646 | if (GNUNET_OK != | 670 | if (GNUNET_OK != |
647 | GNUNET_GNSRECORD_records_deserialize (payload_len - sizeof(uint32_t), | 671 | GNUNET_GNSRECORD_records_deserialize (payload_len, |
648 | &payload[sizeof(uint32_t)], | 672 | payload, |
649 | rd_count, | 673 | rd_count, |
650 | rd)) | 674 | rd)) |
651 | { | 675 | { |
@@ -723,43 +747,42 @@ block_decrypt_ecdsa (const struct GNUNET_GNSRECORD_EcdsaBlock *block, | |||
723 | 747 | ||
724 | 748 | ||
725 | enum GNUNET_GenericReturnValue | 749 | enum GNUNET_GenericReturnValue |
726 | block_decrypt_eddsa (const struct GNUNET_GNSRECORD_EddsaBlock *block, | 750 | block_decrypt_eddsa (const struct GNUNET_GNSRECORD_Block *block, |
727 | const struct | 751 | const struct |
728 | GNUNET_CRYPTO_EddsaPublicKey *zone_key, | 752 | GNUNET_CRYPTO_EddsaPublicKey *zone_key, |
729 | const char *label, | 753 | const char *label, |
730 | GNUNET_GNSRECORD_RecordCallback proc, | 754 | GNUNET_GNSRECORD_RecordCallback proc, |
731 | void *proc_cls) | 755 | void *proc_cls) |
732 | { | 756 | { |
733 | size_t payload_len = ntohl (block->purpose.size) | 757 | const struct GNUNET_GNSRECORD_EddsaBlock *edblock = &block->eddsa_block; |
734 | - sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) | 758 | size_t payload_len = ntohl (block->size) - sizeof (struct |
735 | - sizeof(struct GNUNET_TIME_AbsoluteNBO); | 759 | GNUNET_GNSRECORD_Block); |
736 | unsigned char nonce[crypto_secretbox_NONCEBYTES]; | 760 | unsigned char nonce[crypto_secretbox_NONCEBYTES]; |
737 | unsigned char key[crypto_secretbox_KEYBYTES]; | 761 | unsigned char key[crypto_secretbox_KEYBYTES]; |
738 | 762 | ||
739 | if (ntohl (block->purpose.size) < | 763 | if (ntohl (block->size) < |
740 | sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) | 764 | sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) |
741 | + sizeof(struct GNUNET_TIME_AbsoluteNBO)) | 765 | + sizeof(struct GNUNET_TIME_AbsoluteNBO)) |
742 | { | 766 | { |
743 | GNUNET_break_op (0); | 767 | GNUNET_break_op (0); |
744 | return GNUNET_SYSERR; | 768 | return GNUNET_SYSERR; |
745 | } | 769 | } |
746 | derive_block_xsalsa_key (nonce, | 770 | GNR_derive_block_xsalsa_key (nonce, |
747 | key, | 771 | key, |
748 | label, | 772 | label, |
749 | block->expiration_time.abs_value_us__, | 773 | block->eddsa_block.expiration_time.abs_value_us__, |
750 | zone_key); | 774 | zone_key); |
751 | { | 775 | { |
752 | char payload[payload_len]; | 776 | char payload[payload_len]; |
753 | uint32_t rd_count; | 777 | unsigned int rd_count; |
754 | 778 | ||
755 | GNUNET_break (GNUNET_OK == | 779 | GNUNET_break (GNUNET_OK == |
756 | eddsa_symmetric_decrypt (&block[1], payload_len, | 780 | eddsa_symmetric_decrypt (&block[1], payload_len, |
757 | key, nonce, | 781 | key, nonce, |
758 | payload)); | 782 | payload)); |
759 | GNUNET_memcpy (&rd_count, | 783 | payload_len -= crypto_secretbox_MACBYTES; |
760 | payload, | 784 | rd_count = GNUNET_GNSRECORD_records_deserialize_get_size (payload_len, |
761 | sizeof(uint32_t)); | 785 | payload); |
762 | rd_count = ntohl (rd_count); | ||
763 | if (rd_count > 2048) | 786 | if (rd_count > 2048) |
764 | { | 787 | { |
765 | /* limit to sane value */ | 788 | /* limit to sane value */ |
@@ -772,8 +795,8 @@ block_decrypt_eddsa (const struct GNUNET_GNSRECORD_EddsaBlock *block, | |||
772 | struct GNUNET_TIME_Absolute now; | 795 | struct GNUNET_TIME_Absolute now; |
773 | 796 | ||
774 | if (GNUNET_OK != | 797 | if (GNUNET_OK != |
775 | GNUNET_GNSRECORD_records_deserialize (payload_len - sizeof(uint32_t), | 798 | GNUNET_GNSRECORD_records_deserialize (payload_len, |
776 | &payload[sizeof(uint32_t)], | 799 | payload, |
777 | rd_count, | 800 | rd_count, |
778 | rd)) | 801 | rd)) |
779 | { | 802 | { |
@@ -875,16 +898,18 @@ GNUNET_GNSRECORD_block_decrypt (const struct GNUNET_GNSRECORD_Block *block, | |||
875 | norm_label = GNUNET_GNSRECORD_string_normalize (label); | 898 | norm_label = GNUNET_GNSRECORD_string_normalize (label); |
876 | switch (ntohl (zone_key->type)) | 899 | switch (ntohl (zone_key->type)) |
877 | { | 900 | { |
878 | case GNUNET_IDENTITY_TYPE_ECDSA: | 901 | case GNUNET_IDENTITY_TYPE_ECDSA: |
879 | res = block_decrypt_ecdsa (&block->ecdsa_block, | 902 | res = block_decrypt_ecdsa (block, |
880 | &zone_key->ecdsa_key, norm_label, proc, proc_cls); | 903 | &zone_key->ecdsa_key, norm_label, proc, |
881 | break; | 904 | proc_cls); |
882 | case GNUNET_IDENTITY_TYPE_EDDSA: | 905 | break; |
883 | res = block_decrypt_eddsa (&block->eddsa_block, | 906 | case GNUNET_IDENTITY_TYPE_EDDSA: |
884 | &zone_key->eddsa_key, norm_label, proc, proc_cls); | 907 | res = block_decrypt_eddsa (block, |
885 | break; | 908 | &zone_key->eddsa_key, norm_label, proc, |
886 | default: | 909 | proc_cls); |
887 | return GNUNET_SYSERR; | 910 | break; |
911 | default: | ||
912 | return GNUNET_SYSERR; | ||
888 | } | 913 | } |
889 | GNUNET_free (norm_label); | 914 | GNUNET_free (norm_label); |
890 | return res; | 915 | return res; |
@@ -910,17 +935,17 @@ GNUNET_GNSRECORD_query_from_private_key (const struct | |||
910 | norm_label = GNUNET_GNSRECORD_string_normalize (label); | 935 | norm_label = GNUNET_GNSRECORD_string_normalize (label); |
911 | switch (ntohl (zone->type)) | 936 | switch (ntohl (zone->type)) |
912 | { | 937 | { |
913 | case GNUNET_GNSRECORD_TYPE_PKEY: | 938 | case GNUNET_GNSRECORD_TYPE_PKEY: |
914 | case GNUNET_GNSRECORD_TYPE_EDKEY: | 939 | case GNUNET_GNSRECORD_TYPE_EDKEY: |
915 | 940 | ||
916 | GNUNET_IDENTITY_key_get_public (zone, | 941 | GNUNET_IDENTITY_key_get_public (zone, |
917 | &pub); | 942 | &pub); |
918 | GNUNET_GNSRECORD_query_from_public_key (&pub, | 943 | GNUNET_GNSRECORD_query_from_public_key (&pub, |
919 | norm_label, | 944 | norm_label, |
920 | query); | 945 | query); |
921 | break; | 946 | break; |
922 | default: | 947 | default: |
923 | GNUNET_assert (0); | 948 | GNUNET_assert (0); |
924 | } | 949 | } |
925 | GNUNET_free (norm_label); | 950 | GNUNET_free (norm_label); |
926 | } | 951 | } |
@@ -947,28 +972,28 @@ GNUNET_GNSRECORD_query_from_public_key (const struct | |||
947 | 972 | ||
948 | switch (ntohl (pub->type)) | 973 | switch (ntohl (pub->type)) |
949 | { | 974 | { |
950 | case GNUNET_GNSRECORD_TYPE_PKEY: | 975 | case GNUNET_GNSRECORD_TYPE_PKEY: |
951 | pd.type = pub->type; | 976 | pd.type = pub->type; |
952 | GNUNET_CRYPTO_ecdsa_public_key_derive (&pub->ecdsa_key, | 977 | GNUNET_CRYPTO_ecdsa_public_key_derive (&pub->ecdsa_key, |
953 | norm_label, | 978 | norm_label, |
954 | "gns", | 979 | "gns", |
955 | &pd.ecdsa_key); | 980 | &pd.ecdsa_key); |
956 | GNUNET_CRYPTO_hash (&pd.ecdsa_key, | 981 | GNUNET_CRYPTO_hash (&pd.ecdsa_key, |
957 | sizeof (pd.ecdsa_key), | 982 | sizeof (pd.ecdsa_key), |
958 | query); | 983 | query); |
959 | break; | 984 | break; |
960 | case GNUNET_GNSRECORD_TYPE_EDKEY: | 985 | case GNUNET_GNSRECORD_TYPE_EDKEY: |
961 | pd.type = pub->type; | 986 | pd.type = pub->type; |
962 | GNUNET_CRYPTO_eddsa_public_key_derive (&pub->eddsa_key, | 987 | GNUNET_CRYPTO_eddsa_public_key_derive (&pub->eddsa_key, |
963 | norm_label, | 988 | norm_label, |
964 | "gns", | 989 | "gns", |
965 | &(pd.eddsa_key)); | 990 | &(pd.eddsa_key)); |
966 | GNUNET_CRYPTO_hash (&pd.eddsa_key, | 991 | GNUNET_CRYPTO_hash (&pd.eddsa_key, |
967 | sizeof (pd.eddsa_key), | 992 | sizeof (pd.eddsa_key), |
968 | query); | 993 | query); |
969 | break; | 994 | break; |
970 | default: | 995 | default: |
971 | GNUNET_assert (0); | 996 | GNUNET_assert (0); |
972 | } | 997 | } |
973 | GNUNET_free (norm_label); | 998 | GNUNET_free (norm_label); |
974 | } | 999 | } |
diff --git a/src/gnsrecord/gnsrecord_crypto.h b/src/gnsrecord/gnsrecord_crypto.h new file mode 100644 index 000000000..79a7e6fb9 --- /dev/null +++ b/src/gnsrecord/gnsrecord_crypto.h | |||
@@ -0,0 +1,87 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2009-2013, 2018 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file gnsrecord/gnsrecord_crypto.h | ||
23 | * @brief API for GNS record-related crypto | ||
24 | * @author Martin Schanzenbach | ||
25 | * @author Matthias Wachs | ||
26 | * @author Christian Grothoff | ||
27 | */ | ||
28 | #include "platform.h" | ||
29 | #include "gnunet_util_lib.h" | ||
30 | #include "gnunet_constants.h" | ||
31 | #include "gnunet_signatures.h" | ||
32 | #include "gnunet_arm_service.h" | ||
33 | #include "gnunet_gnsrecord_lib.h" | ||
34 | #include "gnunet_dnsparser_lib.h" | ||
35 | #include "gnunet_tun_lib.h" | ||
36 | |||
37 | /** | ||
38 | * Information we have in an encrypted block with record data (i.e. in the DHT). | ||
39 | */ | ||
40 | struct GNRBlockPS | ||
41 | { | ||
42 | /** | ||
43 | * Number of bytes signed; also specifies the number of bytes | ||
44 | * of encrypted data that follow. | ||
45 | */ | ||
46 | struct GNUNET_CRYPTO_EccSignaturePurpose purpose; | ||
47 | |||
48 | /** | ||
49 | * Expiration time of the block. | ||
50 | */ | ||
51 | struct GNUNET_TIME_AbsoluteNBO expiration_time; | ||
52 | |||
53 | /* followed by encrypted data */ | ||
54 | }; | ||
55 | |||
56 | |||
57 | /** | ||
58 | * Derive session key and iv from label and public key. | ||
59 | * | ||
60 | * @param iv initialization vector to initialize | ||
61 | * @param skey session key to initialize | ||
62 | * @param label label to use for KDF | ||
63 | * @param pub public key to use for KDF | ||
64 | */ | ||
65 | void | ||
66 | GNR_derive_block_aes_key (unsigned char *ctr, | ||
67 | unsigned char *key, | ||
68 | const char *label, | ||
69 | uint64_t exp, | ||
70 | const struct GNUNET_CRYPTO_EcdsaPublicKey *pub); | ||
71 | |||
72 | |||
73 | /** | ||
74 | * Derive session key and iv from label and public key. | ||
75 | * | ||
76 | * @param nonce initialization vector to initialize | ||
77 | * @param skey session key to initialize | ||
78 | * @param label label to use for KDF | ||
79 | * @param pub public key to use for KDF | ||
80 | */ | ||
81 | void | ||
82 | GNR_derive_block_xsalsa_key (unsigned char *nonce, | ||
83 | unsigned char *key, | ||
84 | const char *label, | ||
85 | uint64_t exp, | ||
86 | const struct GNUNET_CRYPTO_EddsaPublicKey *pub); | ||
87 | |||
diff --git a/src/gnsrecord/gnsrecord_misc.c b/src/gnsrecord/gnsrecord_misc.c index c6f07ccd0..61604c730 100644 --- a/src/gnsrecord/gnsrecord_misc.c +++ b/src/gnsrecord/gnsrecord_misc.c | |||
@@ -334,24 +334,7 @@ GNUNET_GNSRECORD_is_zonekey_type (uint32_t type) | |||
334 | size_t | 334 | size_t |
335 | GNUNET_GNSRECORD_block_get_size (const struct GNUNET_GNSRECORD_Block *block) | 335 | GNUNET_GNSRECORD_block_get_size (const struct GNUNET_GNSRECORD_Block *block) |
336 | { | 336 | { |
337 | switch (ntohl (block->type)) | 337 | return ntohl (block->size); |
338 | { | ||
339 | case GNUNET_GNSRECORD_TYPE_PKEY: | ||
340 | return sizeof (uint32_t) /* zone type */ | ||
341 | + sizeof (block->ecdsa_block) /* EcdsaBlock */ | ||
342 | + ntohl (block->ecdsa_block.purpose.size) /* Length of signed data */ | ||
343 | - sizeof (block->ecdsa_block.purpose); /* Purpose already in EcdsaBlock */ | ||
344 | break; | ||
345 | case GNUNET_GNSRECORD_TYPE_EDKEY: | ||
346 | return sizeof (uint32_t) /* zone type */ | ||
347 | + sizeof (block->eddsa_block) /* EddsaBlock */ | ||
348 | + ntohl (block->eddsa_block.purpose.size) /* Length of signed data */ | ||
349 | - sizeof (block->ecdsa_block.purpose); /* Purpose already in EcdsaBlock */ | ||
350 | |||
351 | default: | ||
352 | return 0; | ||
353 | } | ||
354 | return 0; | ||
355 | } | 338 | } |
356 | 339 | ||
357 | 340 | ||
diff --git a/src/gnsrecord/gnsrecord_serialization.c b/src/gnsrecord/gnsrecord_serialization.c index cb6957605..eaa3a9ab2 100644 --- a/src/gnsrecord/gnsrecord_serialization.c +++ b/src/gnsrecord/gnsrecord_serialization.c | |||
@@ -60,17 +60,18 @@ struct NetworkRecord | |||
60 | /** | 60 | /** |
61 | * Number of bytes in 'data', network byte order. | 61 | * Number of bytes in 'data', network byte order. |
62 | */ | 62 | */ |
63 | uint32_t data_size GNUNET_PACKED; | 63 | uint16_t data_size GNUNET_PACKED; |
64 | 64 | ||
65 | /** | 65 | /** |
66 | * Type of the GNS/DNS record, network byte order. | 66 | * Flags for the record, network byte order. |
67 | */ | 67 | */ |
68 | uint32_t record_type GNUNET_PACKED; | 68 | uint16_t flags GNUNET_PACKED; |
69 | 69 | ||
70 | /** | 70 | /** |
71 | * Flags for the record, network byte order. | 71 | * Type of the GNS/DNS record, network byte order. |
72 | */ | 72 | */ |
73 | uint32_t flags GNUNET_PACKED; | 73 | uint32_t record_type GNUNET_PACKED; |
74 | |||
74 | }; | 75 | }; |
75 | 76 | ||
76 | GNUNET_NETWORK_STRUCT_END | 77 | GNUNET_NETWORK_STRUCT_END |
@@ -169,9 +170,9 @@ GNUNET_GNSRECORD_records_serialize (unsigned int rd_count, | |||
169 | rd[i].flags, | 170 | rd[i].flags, |
170 | (unsigned long long) rd[i].expiration_time); | 171 | (unsigned long long) rd[i].expiration_time); |
171 | rec.expiration_time = GNUNET_htonll (rd[i].expiration_time); | 172 | rec.expiration_time = GNUNET_htonll (rd[i].expiration_time); |
172 | rec.data_size = htonl ((uint32_t) rd[i].data_size); | 173 | rec.data_size = htons ((uint16_t) rd[i].data_size); |
173 | rec.record_type = htonl (rd[i].record_type); | 174 | rec.record_type = htonl (rd[i].record_type); |
174 | rec.flags = htonl (rd[i].flags); | 175 | rec.flags = htons (rd[i].flags); |
175 | if ((off + sizeof(rec) > dest_size) || | 176 | if ((off + sizeof(rec) > dest_size) || |
176 | (off + sizeof(rec) < off)) | 177 | (off + sizeof(rec) < off)) |
177 | { | 178 | { |
@@ -214,13 +215,48 @@ GNUNET_GNSRECORD_records_serialize (unsigned int rd_count, | |||
214 | return dest_size; | 215 | return dest_size; |
215 | } | 216 | } |
216 | 217 | ||
218 | unsigned int | ||
219 | GNUNET_GNSRECORD_records_deserialize_get_size (size_t len, | ||
220 | const char *src) | ||
221 | { | ||
222 | struct NetworkRecord rec; | ||
223 | struct NetworkRecord rec_zero; | ||
224 | size_t off; | ||
225 | unsigned int rd_count = 0; | ||
226 | |||
227 | memset (&rec_zero, 0, sizeof (rec_zero)); | ||
228 | |||
229 | off = 0; | ||
230 | for (off = 0; (off + sizeof(rec) <= len) && (off + sizeof(rec) >= off);) | ||
231 | { | ||
232 | /* | ||
233 | * If we have found a byte string of zeroes, we have reached | ||
234 | * the padding | ||
235 | */ | ||
236 | if (0 == GNUNET_memcmp (&rec, &rec_zero)) | ||
237 | break; | ||
238 | GNUNET_memcpy (&rec, | ||
239 | &src[off], | ||
240 | sizeof(rec)); | ||
241 | off += sizeof(rec); | ||
242 | if ((off + ntohs ((uint16_t) rec.data_size) > len) || | ||
243 | (off + ntohs ((uint16_t) rec.data_size) < off)) | ||
244 | { | ||
245 | GNUNET_break_op (0); | ||
246 | return 0; | ||
247 | } | ||
248 | off += ntohs ((uint16_t) rec.data_size); | ||
249 | rd_count++; | ||
250 | } | ||
251 | return rd_count; | ||
252 | } | ||
217 | 253 | ||
218 | /** | 254 | /** |
219 | * Deserialize the given records to the given destination. | 255 | * Deserialize the given records to the given destination. |
220 | * | 256 | * |
221 | * @param len size of the serialized record data | 257 | * @param len size of the serialized record data |
222 | * @param src the serialized record data | 258 | * @param src the serialized record data |
223 | * @param rd_count number of records in the rd array | 259 | * @param rd_count number of records parsed |
224 | * @param dest where to put the data | 260 | * @param dest where to put the data |
225 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on error | 261 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on error |
226 | */ | 262 | */ |
@@ -246,9 +282,9 @@ GNUNET_GNSRECORD_records_deserialize (size_t len, | |||
246 | &src[off], | 282 | &src[off], |
247 | sizeof(rec)); | 283 | sizeof(rec)); |
248 | dest[i].expiration_time = GNUNET_ntohll (rec.expiration_time); | 284 | dest[i].expiration_time = GNUNET_ntohll (rec.expiration_time); |
249 | dest[i].data_size = ntohl ((uint32_t) rec.data_size); | 285 | dest[i].data_size = ntohs ((uint16_t) rec.data_size); |
250 | dest[i].record_type = ntohl (rec.record_type); | 286 | dest[i].record_type = ntohl (rec.record_type); |
251 | dest[i].flags = ntohl (rec.flags); | 287 | dest[i].flags = ntohs (rec.flags); |
252 | off += sizeof(rec); | 288 | off += sizeof(rec); |
253 | if ((off + dest[i].data_size > len) || | 289 | if ((off + dest[i].data_size > len) || |
254 | (off + dest[i].data_size < off)) | 290 | (off + dest[i].data_size < off)) |
diff --git a/src/gnsrecord/gnunet-gnsrecord-tvg.c b/src/gnsrecord/gnunet-gnsrecord-tvg.c index 16a360bdc..f9b83e48b 100644 --- a/src/gnsrecord/gnunet-gnsrecord-tvg.c +++ b/src/gnsrecord/gnunet-gnsrecord-tvg.c | |||
@@ -31,15 +31,43 @@ | |||
31 | #include "gnunet_dnsparser_lib.h" | 31 | #include "gnunet_dnsparser_lib.h" |
32 | #include "gnunet_testing_lib.h" | 32 | #include "gnunet_testing_lib.h" |
33 | #include <inttypes.h> | 33 | #include <inttypes.h> |
34 | #include "gnsrecord_crypto.h" | ||
34 | 35 | ||
35 | #define TEST_RECORD_LABEL "test" | 36 | #define TEST_RECORD_LABEL "test" |
36 | #define TEST_RECORD_A "1.2.3.4" | 37 | #define TEST_RECORD_A "1.2.3.4" |
37 | #define TEST_RRCOUNT 2 | 38 | #define TEST_RRCOUNT 2 |
38 | 39 | ||
40 | static char *d_pkey = | ||
41 | "50d7b652a4efeadff37396909785e5952171a02178c8e7d450fa907925fafd98"; | ||
42 | |||
43 | static char *d_edkey = | ||
44 | "5af7020ee19160328832352bbc6a68a8d71a7cbe1b929969a7c66d415a0d8f65"; | ||
45 | |||
46 | int parsehex (char *src, char *dst, size_t dstlen, int invert) | ||
47 | { | ||
48 | char *line = src; | ||
49 | char *data = line; | ||
50 | int off; | ||
51 | int read_byte; | ||
52 | int data_len = 0; | ||
53 | |||
54 | while (sscanf (data, " %02x%n", &read_byte, &off) == 1) | ||
55 | { | ||
56 | if (invert) | ||
57 | dst[dstlen - 1 - data_len++] = read_byte; | ||
58 | else | ||
59 | dst[data_len++] = read_byte; | ||
60 | data += off; | ||
61 | } | ||
62 | return data_len; | ||
63 | } | ||
64 | |||
65 | |||
39 | static void | 66 | static void |
40 | print_bytes (void *buf, | 67 | print_bytes_ (void *buf, |
41 | size_t buf_len, | 68 | size_t buf_len, |
42 | int fold) | 69 | int fold, |
70 | int in_be) | ||
43 | { | 71 | { |
44 | int i; | 72 | int i; |
45 | 73 | ||
@@ -47,11 +75,22 @@ print_bytes (void *buf, | |||
47 | { | 75 | { |
48 | if ((0 != i) && (0 != fold) && (i % fold == 0)) | 76 | if ((0 != i) && (0 != fold) && (i % fold == 0)) |
49 | printf ("\n"); | 77 | printf ("\n"); |
50 | printf ("%02x", ((unsigned char*) buf)[i]); | 78 | if (in_be) |
79 | printf ("%02x", ((unsigned char*) buf)[buf_len - 1 - i]); | ||
80 | else | ||
81 | printf ("%02x", ((unsigned char*) buf)[i]); | ||
51 | } | 82 | } |
52 | printf ("\n"); | 83 | printf ("\n"); |
53 | } | 84 | } |
54 | 85 | ||
86 | static void | ||
87 | print_bytes (void *buf, | ||
88 | size_t buf_len, | ||
89 | int fold) | ||
90 | { | ||
91 | print_bytes_ (buf, buf_len, fold, 0); | ||
92 | } | ||
93 | |||
55 | 94 | ||
56 | static void | 95 | static void |
57 | print_record (const struct GNUNET_GNSRECORD_Data *rd) | 96 | print_record (const struct GNUNET_GNSRECORD_Data *rd) |
@@ -84,28 +123,51 @@ static void | |||
84 | run_pkey (void) | 123 | run_pkey (void) |
85 | { | 124 | { |
86 | struct GNUNET_GNSRECORD_Data rd[2]; | 125 | struct GNUNET_GNSRECORD_Data rd[2]; |
87 | struct GNUNET_TIME_Absolute exp_abs = GNUNET_TIME_absolute_get (); | 126 | struct GNUNET_TIME_Absolute expire; |
127 | struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); | ||
128 | struct GNUNET_TIME_Absolute exp1; | ||
129 | struct GNUNET_TIME_Absolute exp2; | ||
130 | struct GNUNET_TIME_Relative delta1; | ||
131 | struct GNUNET_TIME_Relative delta2; | ||
88 | struct GNUNET_GNSRECORD_Block *rrblock; | 132 | struct GNUNET_GNSRECORD_Block *rrblock; |
89 | char *bdata; | 133 | char *bdata; |
90 | struct GNUNET_IDENTITY_PrivateKey id_priv; | 134 | struct GNUNET_IDENTITY_PrivateKey id_priv; |
91 | struct GNUNET_IDENTITY_PublicKey id_pub; | 135 | struct GNUNET_IDENTITY_PublicKey id_pub; |
92 | struct GNUNET_IDENTITY_PrivateKey pkey_data_p; | 136 | struct GNUNET_IDENTITY_PrivateKey pkey_data_p; |
93 | struct GNUNET_IDENTITY_PublicKey pkey_data; | 137 | struct GNUNET_IDENTITY_PublicKey pkey_data; |
138 | struct GNUNET_HashCode query; | ||
94 | void *data; | 139 | void *data; |
95 | size_t data_size; | 140 | size_t data_size; |
96 | char *rdata; | 141 | char *rdata; |
97 | size_t rdata_size; | 142 | size_t rdata_size; |
143 | uint32_t rd_count_nbo; | ||
98 | char ztld[128]; | 144 | char ztld[128]; |
145 | unsigned char ctr[GNUNET_CRYPTO_AES_KEY_LENGTH / 2]; | ||
146 | unsigned char skey[GNUNET_CRYPTO_AES_KEY_LENGTH]; | ||
147 | |||
148 | /* | ||
149 | * Make two different expiration times | ||
150 | */ | ||
151 | GNUNET_STRINGS_fancy_time_to_absolute ("2048-01-23 10:51:34", | ||
152 | &exp1); | ||
153 | GNUNET_STRINGS_fancy_time_to_absolute ("3540-05-22 07:55:01", | ||
154 | &exp2); | ||
155 | |||
99 | 156 | ||
100 | id_priv.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | 157 | id_priv.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); |
101 | GNUNET_CRYPTO_ecdsa_key_create (&id_priv.ecdsa_key); | 158 | GNUNET_CRYPTO_ecdsa_key_create (&id_priv.ecdsa_key); |
159 | parsehex (d_pkey, | ||
160 | (char*) &id_priv.ecdsa_key, | ||
161 | sizeof (id_priv.ecdsa_key), 1); | ||
162 | |||
102 | GNUNET_IDENTITY_key_get_public (&id_priv, | 163 | GNUNET_IDENTITY_key_get_public (&id_priv, |
103 | &id_pub); | 164 | &id_pub); |
104 | fprintf (stdout, | 165 | fprintf (stdout, |
105 | "Zone private key (d, little-endian, with ztype prepended):\n"); | 166 | "Zone private key (d, big-endian):\n"); |
106 | print_bytes (&id_priv, GNUNET_IDENTITY_key_get_length (&id_pub), 8); // FIXME length for privkey? | 167 | print_bytes_ (&id_priv.ecdsa_key, |
168 | sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey), 8, 1); | ||
107 | fprintf (stdout, "\n"); | 169 | fprintf (stdout, "\n"); |
108 | fprintf (stdout, "Zone identifier (zid):\n"); | 170 | fprintf (stdout, "Zone identifier (ztype|zkey):\n"); |
109 | print_bytes (&id_pub, GNUNET_IDENTITY_key_get_length (&id_pub), 8); | 171 | print_bytes (&id_pub, GNUNET_IDENTITY_key_get_length (&id_pub), 8); |
110 | GNUNET_STRINGS_data_to_string (&id_pub, | 172 | GNUNET_STRINGS_data_to_string (&id_pub, |
111 | GNUNET_IDENTITY_key_get_length (&id_pub), | 173 | GNUNET_IDENTITY_key_get_length (&id_pub), |
@@ -127,20 +189,20 @@ run_pkey (void) | |||
127 | GNUNET_DNSPARSER_TYPE_A, TEST_RECORD_A, &data, &data_size)); | 189 | GNUNET_DNSPARSER_TYPE_A, TEST_RECORD_A, &data, &data_size)); |
128 | rd[0].data = data; | 190 | rd[0].data = data; |
129 | rd[0].data_size = data_size; | 191 | rd[0].data_size = data_size; |
130 | rd[0].expiration_time = exp_abs.abs_value_us; | 192 | rd[0].expiration_time = exp1.abs_value_us; |
131 | rd[0].record_type = GNUNET_DNSPARSER_TYPE_A; | 193 | rd[0].record_type = GNUNET_DNSPARSER_TYPE_A; |
132 | fprintf (stdout, "Record #0\n"); | 194 | fprintf (stdout, "Record #0\n"); |
133 | print_record (&rd[0]); | 195 | print_record (&rd[0]); |
134 | 196 | ||
135 | rd[1].data = &pkey_data; | 197 | rd[1].data = "Some nick"; |
136 | rd[1].data_size = sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey); | 198 | rd[1].data_size = sizeof (struct GNUNET_IDENTITY_PublicKey); |
137 | rd[1].expiration_time = exp_abs.abs_value_us; | 199 | rd[1].expiration_time = exp2.abs_value_us; |
138 | rd[1].record_type = GNUNET_GNSRECORD_TYPE_PKEY; | 200 | rd[1].record_type = GNUNET_GNSRECORD_TYPE_NICK; |
139 | rd[1].flags = GNUNET_GNSRECORD_RF_PRIVATE; | 201 | rd[1].flags = GNUNET_GNSRECORD_RF_PRIVATE; |
140 | fprintf (stdout, "Record #1\n"); | 202 | fprintf (stdout, "Record #1\n"); |
141 | print_record (&rd[1]); | 203 | print_record (&rd[1]); |
142 | 204 | ||
143 | rdata_size = GNUNET_GNSRECORD_records_get_size (2, | 205 | rdata_size = GNUNET_GNSRECORD_records_get_size (TEST_RRCOUNT, |
144 | rd); | 206 | rd); |
145 | rdata = GNUNET_malloc (rdata_size); | 207 | rdata = GNUNET_malloc (rdata_size); |
146 | GNUNET_GNSRECORD_records_serialize (2, | 208 | GNUNET_GNSRECORD_records_serialize (2, |
@@ -150,25 +212,40 @@ run_pkey (void) | |||
150 | fprintf (stdout, "RDATA:\n"); | 212 | fprintf (stdout, "RDATA:\n"); |
151 | print_bytes (rdata, rdata_size, 8); | 213 | print_bytes (rdata, rdata_size, 8); |
152 | fprintf (stdout, "\n"); | 214 | fprintf (stdout, "\n"); |
153 | rrblock = GNUNET_GNSRECORD_block_create (&id_priv, | 215 | expire = GNUNET_GNSRECORD_record_get_expiration_time (TEST_RRCOUNT, rd); |
154 | exp_abs, | 216 | GNR_derive_block_aes_key (ctr, |
155 | TEST_RECORD_LABEL, | 217 | skey, |
156 | rd, | 218 | TEST_RECORD_LABEL, |
157 | TEST_RRCOUNT); | 219 | GNUNET_TIME_absolute_hton ( |
158 | size_t bdata_size = ntohl (rrblock->ecdsa_block.purpose.size) | 220 | expire).abs_value_us__, |
159 | - sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) | 221 | &id_pub.ecdsa_key); |
160 | - sizeof(struct GNUNET_TIME_AbsoluteNBO); | 222 | |
161 | size_t ecblock_size = ntohl (rrblock->ecdsa_block.purpose.size) | 223 | fprintf (stdout, "Encryption NONCE|EXPIRATION|BLOCK COUNTER:\n"); |
162 | + sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey) | 224 | print_bytes (ctr, sizeof (ctr), 8); |
163 | + sizeof(struct GNUNET_CRYPTO_EcdsaSignature); | 225 | fprintf (stdout, "\n"); |
164 | size_t block_size = ecblock_size + sizeof (uint32_t); | 226 | fprintf (stdout, "Encryption key (K):\n"); |
227 | print_bytes (skey, sizeof (skey), 8); | ||
228 | fprintf (stdout, "\n"); | ||
229 | GNUNET_GNSRECORD_query_from_public_key (&id_pub, | ||
230 | TEST_RECORD_LABEL, | ||
231 | &query); | ||
232 | fprintf (stdout, "Storage key (q):\n"); | ||
233 | print_bytes (&query, sizeof (query), 8); | ||
234 | fprintf (stdout, "\n"); | ||
235 | GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create (&id_priv, | ||
236 | expire, | ||
237 | TEST_RECORD_LABEL, | ||
238 | rd, | ||
239 | TEST_RRCOUNT, | ||
240 | &rrblock)); | ||
241 | size_t bdata_size = ntohl(rrblock->size) - sizeof (struct GNUNET_GNSRECORD_Block); | ||
165 | 242 | ||
166 | bdata = (char*) &(&rrblock->ecdsa_block)[1]; | 243 | bdata = (char*) &(&rrblock->ecdsa_block)[1]; |
167 | fprintf (stdout, "BDATA:\n"); | 244 | fprintf (stdout, "BDATA:\n"); |
168 | print_bytes (bdata, bdata_size, 8); | 245 | print_bytes (bdata, bdata_size, 8); |
169 | fprintf (stdout, "\n"); | 246 | fprintf (stdout, "\n"); |
170 | fprintf (stdout, "RRBLOCK:\n"); | 247 | fprintf (stdout, "RRBLOCK:\n"); |
171 | print_bytes (rrblock, block_size, 8); | 248 | print_bytes (rrblock, ntohl(rrblock->size), 8); |
172 | fprintf (stdout, "\n"); | 249 | fprintf (stdout, "\n"); |
173 | GNUNET_free (rdata); | 250 | GNUNET_free (rdata); |
174 | } | 251 | } |
@@ -186,28 +263,54 @@ static void | |||
186 | run_edkey (void) | 263 | run_edkey (void) |
187 | { | 264 | { |
188 | struct GNUNET_GNSRECORD_Data rd[2]; | 265 | struct GNUNET_GNSRECORD_Data rd[2]; |
189 | struct GNUNET_TIME_Absolute exp_abs = GNUNET_TIME_absolute_get (); | 266 | struct GNUNET_TIME_Absolute expire; |
267 | struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); | ||
268 | struct GNUNET_TIME_Absolute exp1; | ||
269 | struct GNUNET_TIME_Absolute exp2; | ||
270 | struct GNUNET_TIME_Relative delta1; | ||
271 | struct GNUNET_TIME_Relative delta2; | ||
190 | struct GNUNET_GNSRECORD_Block *rrblock; | 272 | struct GNUNET_GNSRECORD_Block *rrblock; |
191 | char *bdata; | 273 | char *bdata; |
192 | struct GNUNET_IDENTITY_PrivateKey id_priv; | 274 | struct GNUNET_IDENTITY_PrivateKey id_priv; |
193 | struct GNUNET_IDENTITY_PublicKey id_pub; | 275 | struct GNUNET_IDENTITY_PublicKey id_pub; |
194 | struct GNUNET_IDENTITY_PrivateKey pkey_data_p; | 276 | struct GNUNET_IDENTITY_PrivateKey pkey_data_p; |
195 | struct GNUNET_IDENTITY_PublicKey pkey_data; | 277 | struct GNUNET_IDENTITY_PublicKey pkey_data; |
278 | struct GNUNET_HashCode query; | ||
196 | void *data; | 279 | void *data; |
197 | size_t data_size; | 280 | size_t data_size; |
198 | char *rdata; | 281 | char *rdata; |
199 | size_t rdata_size; | 282 | size_t rdata_size; |
283 | uint32_t rd_count_nbo; | ||
200 | char ztld[128]; | 284 | char ztld[128]; |
285 | unsigned char nonce[crypto_secretbox_NONCEBYTES]; | ||
286 | unsigned char skey[crypto_secretbox_KEYBYTES]; | ||
287 | |||
288 | /* | ||
289 | * Make two different expiration times | ||
290 | */ | ||
291 | GNUNET_STRINGS_fancy_time_to_absolute ("%2048-01-23 10:51:34", | ||
292 | &exp1); | ||
293 | GNUNET_STRINGS_fancy_time_to_absolute ("3540-05-22 07:55:01", | ||
294 | &exp2); | ||
295 | |||
296 | id_priv.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
297 | GNUNET_CRYPTO_ecdsa_key_create (&id_priv.ecdsa_key); | ||
298 | GNUNET_IDENTITY_key_get_public (&id_priv, | ||
299 | &id_pub); | ||
201 | 300 | ||
202 | id_priv.type = htonl (GNUNET_IDENTITY_TYPE_EDDSA); | 301 | id_priv.type = htonl (GNUNET_IDENTITY_TYPE_EDDSA); |
203 | GNUNET_CRYPTO_eddsa_key_create (&id_priv.eddsa_key); | 302 | GNUNET_CRYPTO_eddsa_key_create (&id_priv.eddsa_key); |
303 | parsehex (d_edkey, | ||
304 | (char*) &id_priv.eddsa_key, | ||
305 | sizeof (id_priv.eddsa_key), 0); | ||
204 | GNUNET_IDENTITY_key_get_public (&id_priv, | 306 | GNUNET_IDENTITY_key_get_public (&id_priv, |
205 | &id_pub); | 307 | &id_pub); |
206 | fprintf (stdout, | 308 | fprintf (stdout, |
207 | "Zone private key (d, little-endian, with ztype prepended):\n"); | 309 | "Zone private key (d):\n"); |
208 | print_bytes (&id_priv, GNUNET_IDENTITY_key_get_length (&id_pub), 8); // FIXME length for privkey? | 310 | print_bytes (&id_priv.eddsa_key, sizeof (struct |
311 | GNUNET_CRYPTO_EddsaPrivateKey), 8); | ||
209 | fprintf (stdout, "\n"); | 312 | fprintf (stdout, "\n"); |
210 | fprintf (stdout, "Zone identifier (zid):\n"); | 313 | fprintf (stdout, "Zone identifier (ztype|zkey):\n"); |
211 | print_bytes (&id_pub, GNUNET_IDENTITY_key_get_length (&id_pub), 8); | 314 | print_bytes (&id_pub, GNUNET_IDENTITY_key_get_length (&id_pub), 8); |
212 | GNUNET_STRINGS_data_to_string (&id_pub, | 315 | GNUNET_STRINGS_data_to_string (&id_pub, |
213 | GNUNET_IDENTITY_key_get_length (&id_pub), | 316 | GNUNET_IDENTITY_key_get_length (&id_pub), |
@@ -229,21 +332,23 @@ run_edkey (void) | |||
229 | GNUNET_DNSPARSER_TYPE_A, TEST_RECORD_A, &data, &data_size)); | 332 | GNUNET_DNSPARSER_TYPE_A, TEST_RECORD_A, &data, &data_size)); |
230 | rd[0].data = data; | 333 | rd[0].data = data; |
231 | rd[0].data_size = data_size; | 334 | rd[0].data_size = data_size; |
232 | rd[0].expiration_time = exp_abs.abs_value_us; | 335 | rd[0].expiration_time = exp1.abs_value_us; |
233 | rd[0].record_type = GNUNET_DNSPARSER_TYPE_A; | 336 | rd[0].record_type = GNUNET_DNSPARSER_TYPE_A; |
234 | fprintf (stdout, "Record #0\n"); | 337 | fprintf (stdout, "Record #0\n"); |
235 | print_record (&rd[0]); | 338 | print_record (&rd[0]); |
236 | 339 | ||
237 | rd[1].data = &pkey_data; | 340 | rd[1].data = "My Nick"; |
238 | rd[1].data_size = sizeof (struct GNUNET_CRYPTO_EddsaPublicKey); | 341 | rd[1].data_size = sizeof (struct GNUNET_IDENTITY_PublicKey); |
239 | rd[1].expiration_time = exp_abs.abs_value_us; | 342 | rd[1].expiration_time = exp2.abs_value_us; |
240 | rd[1].record_type = GNUNET_GNSRECORD_TYPE_EDKEY; | 343 | rd[1].record_type = GNUNET_GNSRECORD_TYPE_NICK; |
241 | rd[1].flags = GNUNET_GNSRECORD_RF_PRIVATE; | 344 | rd[1].flags = GNUNET_GNSRECORD_RF_PRIVATE; |
242 | fprintf (stdout, "Record #1\n"); | 345 | fprintf (stdout, "Record #1\n"); |
243 | print_record (&rd[1]); | 346 | print_record (&rd[1]); |
244 | 347 | ||
245 | rdata_size = GNUNET_GNSRECORD_records_get_size (2, | 348 | rdata_size = GNUNET_GNSRECORD_records_get_size (TEST_RRCOUNT, |
246 | rd); | 349 | rd); |
350 | expire = GNUNET_GNSRECORD_record_get_expiration_time (TEST_RRCOUNT, | ||
351 | rd); | ||
247 | rdata = GNUNET_malloc (rdata_size); | 352 | rdata = GNUNET_malloc (rdata_size); |
248 | GNUNET_GNSRECORD_records_serialize (2, | 353 | GNUNET_GNSRECORD_records_serialize (2, |
249 | rd, | 354 | rd, |
@@ -252,25 +357,39 @@ run_edkey (void) | |||
252 | fprintf (stdout, "RDATA:\n"); | 357 | fprintf (stdout, "RDATA:\n"); |
253 | print_bytes (rdata, rdata_size, 8); | 358 | print_bytes (rdata, rdata_size, 8); |
254 | fprintf (stdout, "\n"); | 359 | fprintf (stdout, "\n"); |
255 | rrblock = GNUNET_GNSRECORD_block_create (&id_priv, | 360 | GNR_derive_block_xsalsa_key (nonce, |
256 | exp_abs, | 361 | skey, |
257 | TEST_RECORD_LABEL, | 362 | TEST_RECORD_LABEL, |
258 | rd, | 363 | GNUNET_TIME_absolute_hton ( |
259 | TEST_RRCOUNT); | 364 | expire).abs_value_us__, |
260 | size_t bdata_size = ntohl (rrblock->eddsa_block.purpose.size) | 365 | &id_pub.eddsa_key); |
261 | - sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) | 366 | fprintf (stdout, "Encryption NONCE|EXPIRATION:\n"); |
262 | - sizeof(struct GNUNET_TIME_AbsoluteNBO); | 367 | print_bytes (nonce, sizeof (nonce), 8); |
263 | size_t ecblock_size = ntohl (rrblock->eddsa_block.purpose.size) | 368 | fprintf (stdout, "\n"); |
264 | + sizeof(struct GNUNET_CRYPTO_EddsaPublicKey) | 369 | fprintf (stdout, "Encryption key (K):\n"); |
265 | + sizeof(struct GNUNET_CRYPTO_EddsaSignature); | 370 | print_bytes (skey, sizeof (skey), 8); |
266 | size_t block_size = ecblock_size + sizeof (uint32_t); | 371 | fprintf (stdout, "\n"); |
372 | GNUNET_GNSRECORD_query_from_public_key (&id_pub, | ||
373 | TEST_RECORD_LABEL, | ||
374 | &query); | ||
375 | fprintf (stdout, "Storage key (q):\n"); | ||
376 | print_bytes (&query, sizeof (query), 8); | ||
377 | fprintf (stdout, "\n"); | ||
378 | |||
379 | GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create (&id_priv, | ||
380 | expire, | ||
381 | TEST_RECORD_LABEL, | ||
382 | rd, | ||
383 | TEST_RRCOUNT, | ||
384 | &rrblock)); | ||
385 | size_t bdata_size = ntohl(rrblock->size) - sizeof (struct GNUNET_GNSRECORD_Block); | ||
267 | 386 | ||
268 | bdata = (char*) &(&rrblock->eddsa_block)[1]; | 387 | bdata = (char*) &(&rrblock->eddsa_block)[1]; |
269 | fprintf (stdout, "BDATA:\n"); | 388 | fprintf (stdout, "BDATA:\n"); |
270 | print_bytes (bdata, bdata_size, 8); | 389 | print_bytes (bdata, bdata_size, 8); |
271 | fprintf (stdout, "\n"); | 390 | fprintf (stdout, "\n"); |
272 | fprintf (stdout, "RRBLOCK:\n"); | 391 | fprintf (stdout, "RRBLOCK:\n"); |
273 | print_bytes (rrblock, block_size, 8); | 392 | print_bytes (rrblock, ntohl(rrblock->size), 8); |
274 | fprintf (stdout, "\n"); | 393 | fprintf (stdout, "\n"); |
275 | GNUNET_free (rdata); | 394 | GNUNET_free (rdata); |
276 | } | 395 | } |
@@ -290,8 +409,8 @@ run (void *cls, | |||
290 | const char *cfgfile, | 409 | const char *cfgfile, |
291 | const struct GNUNET_CONFIGURATION_Handle *cfg) | 410 | const struct GNUNET_CONFIGURATION_Handle *cfg) |
292 | { | 411 | { |
293 | run_pkey(); | 412 | run_pkey (); |
294 | run_edkey(); | 413 | run_edkey (); |
295 | } | 414 | } |
296 | 415 | ||
297 | 416 | ||
diff --git a/src/gnsrecord/test_gnsrecord_crypto.c b/src/gnsrecord/test_gnsrecord_crypto.c index 9e5a1aa7e..ee14fa904 100644 --- a/src/gnsrecord/test_gnsrecord_crypto.c +++ b/src/gnsrecord/test_gnsrecord_crypto.c | |||
@@ -123,12 +123,12 @@ test_with_type (struct GNUNET_IDENTITY_PrivateKey *privkey) | |||
123 | s_rd = create_record (RECORDS); | 123 | s_rd = create_record (RECORDS); |
124 | 124 | ||
125 | /* Create block */ | 125 | /* Create block */ |
126 | GNUNET_assert (NULL != (block = | 126 | GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create (privkey, |
127 | GNUNET_GNSRECORD_block_create (privkey, | 127 | expire, |
128 | expire, | 128 | s_name, |
129 | s_name, | 129 | s_rd, |
130 | s_rd, | 130 | RECORDS, |
131 | RECORDS))); | 131 | &block)); |
132 | GNUNET_assert (GNUNET_OK == | 132 | GNUNET_assert (GNUNET_OK == |
133 | GNUNET_GNSRECORD_query_from_block (block, | 133 | GNUNET_GNSRECORD_query_from_block (block, |
134 | &query_block)); | 134 | &query_block)); |
diff --git a/src/gnsrecord/test_gnsrecord_testvectors.c b/src/gnsrecord/test_gnsrecord_testvectors.c new file mode 100644 index 000000000..153c56261 --- /dev/null +++ b/src/gnsrecord/test_gnsrecord_testvectors.c | |||
@@ -0,0 +1,128 @@ | |||
1 | #include "platform.h" | ||
2 | #include "gnunet_util_lib.h" | ||
3 | #include "gnunet_signatures.h" | ||
4 | #include "gnunet_gns_service.h" | ||
5 | #include "gnunet_gnsrecord_lib.h" | ||
6 | #include "gnunet_dnsparser_lib.h" | ||
7 | #include "gnunet_testing_lib.h" | ||
8 | #include <inttypes.h> | ||
9 | |||
10 | |||
11 | |||
12 | static char *d = | ||
13 | "50d7b652a4efeadff37396909785e5952171a02178c8e7d450fa907925fafd98"; | ||
14 | |||
15 | |||
16 | static char *zid = | ||
17 | "00010000677c477d2d93097c85b195c6f96d84ff61f5982c2c4fe02d5a11fedfb0c2901f"; | ||
18 | |||
19 | #define RRCOUNT 2 | ||
20 | #define LABEL "test" | ||
21 | |||
22 | #define R0_EXPIRATION 14888744139323793 | ||
23 | #define R0_DATA_SIZE 4 | ||
24 | #define R0_TYPE 1 | ||
25 | #define R0_FLAGS 0 | ||
26 | #define R0_DATA "01020304" | ||
27 | |||
28 | /* Record #1*/ | ||
29 | #define R1_EXPIRATION 26147096139323793 | ||
30 | #define R1_DATA_SIZE 36 | ||
31 | #define R1_TYPE 65536 | ||
32 | #define R1_FLAGS 2 | ||
33 | #define R1_DATA \ | ||
34 | "000100000e601be42eb57fb4697610cf3a3b18347b65a33f025b5b174abefb30807bfecf" | ||
35 | |||
36 | #define R1_RRBLOCK \ | ||
37 | "000100008e16da87203b5159c5538e9b765742e968c54af9afbc0890dc80205ad14c84e107b0c115fc0089aa38b9c7ab9cbe1d77040d282a51a2ad493f61f3495f02d8170fe473a55ec6bdf9a509ab1701ffc37ea3bb4cac4a672520986df96e67cc1a73000000940000000f0034e53be193799100e4837eb5d04f92903de4b5234e8ccac5736c9793379a59c33375fc8951aca2eb7aad067bf9af60bf26758646a17f5e5c3b6215f94079545b1c4d4f1b2ebb22c2b4dad44126817b6f001530d476401dd67ac0148554e806353da9e4298079f3e1b16942c48d90c4360c61238c40d9d52911aea52cc0037ac7160bb3cf5b2f4a722fd96b" | ||
38 | |||
39 | int parsehex(char *src, char *dst, size_t dstlen, int invert) | ||
40 | { | ||
41 | char *line = src; | ||
42 | char *data = line; | ||
43 | int off; | ||
44 | int read_byte; | ||
45 | int data_len = 0; | ||
46 | |||
47 | while (sscanf(data, " %02x%n", &read_byte, &off) == 1) { | ||
48 | if (invert) | ||
49 | dst[dstlen - 1 - data_len++] = read_byte; | ||
50 | else | ||
51 | dst[data_len++] = read_byte; | ||
52 | data += off; | ||
53 | } | ||
54 | return data_len; | ||
55 | } | ||
56 | |||
57 | void | ||
58 | res_checker (void *cls, | ||
59 | unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) | ||
60 | { | ||
61 | int r0_found = 0; | ||
62 | int r1_found = 0; | ||
63 | char r0_data[R0_DATA_SIZE]; | ||
64 | char r1_data[R1_DATA_SIZE]; | ||
65 | parsehex(R0_DATA, (char*)r0_data, 0, 0); | ||
66 | parsehex(R1_DATA, (char*)r1_data, 0, 0); | ||
67 | GNUNET_assert (rd_count == RRCOUNT); | ||
68 | for (int i = 0; i < RRCOUNT; i++) | ||
69 | { | ||
70 | if (rd[i].record_type == R0_TYPE) | ||
71 | { | ||
72 | if (0 != memcmp (rd[i].data, r0_data, R0_DATA_SIZE)) | ||
73 | { | ||
74 | printf ("R0 Data mismatch\n"); | ||
75 | continue; | ||
76 | } | ||
77 | if (rd[i].expiration_time != R0_EXPIRATION) | ||
78 | { | ||
79 | printf ("R0 expiration mismatch\n"); | ||
80 | continue; | ||
81 | } | ||
82 | r0_found = 1; | ||
83 | } | ||
84 | if (rd[i].record_type == R1_TYPE) | ||
85 | { | ||
86 | if (0 != memcmp (rd[i].data, r1_data, R1_DATA_SIZE)) | ||
87 | { | ||
88 | printf ("R1 Data mismatch\n"); | ||
89 | continue; | ||
90 | } | ||
91 | if (rd[i].expiration_time != R1_EXPIRATION) | ||
92 | { | ||
93 | printf ("R1 expiration mismatch\n"); | ||
94 | continue; | ||
95 | } | ||
96 | |||
97 | r1_found = 1; | ||
98 | } | ||
99 | |||
100 | } | ||
101 | GNUNET_assert (r0_found); | ||
102 | GNUNET_assert (r1_found); | ||
103 | } | ||
104 | |||
105 | |||
106 | int | ||
107 | main() | ||
108 | { | ||
109 | struct GNUNET_IDENTITY_PrivateKey priv; | ||
110 | struct GNUNET_IDENTITY_PublicKey pub; | ||
111 | struct GNUNET_IDENTITY_PublicKey pub_parsed; | ||
112 | struct GNUNET_GNSRECORD_Block *rrblock; | ||
113 | char *bdata; | ||
114 | |||
115 | parsehex(d,(char*)&priv.ecdsa_key, sizeof (priv.ecdsa_key), 1); | ||
116 | priv.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
117 | parsehex(zid,(char*)&pub_parsed, 0, 0); | ||
118 | GNUNET_IDENTITY_key_get_public(&priv, &pub); | ||
119 | GNUNET_assert (0 == memcmp (&pub, &pub_parsed, sizeof (pub))); | ||
120 | rrblock = GNUNET_malloc (strlen (R1_RRBLOCK) / 2); | ||
121 | parsehex(R1_RRBLOCK, (char*)rrblock, 0, 0); | ||
122 | GNUNET_GNSRECORD_block_decrypt (rrblock, | ||
123 | &pub_parsed, | ||
124 | LABEL, | ||
125 | &res_checker, | ||
126 | NULL); | ||
127 | return 0; | ||
128 | } | ||