aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authort3sserakt <t3ss@posteo.de>2022-04-01 15:08:41 +0200
committert3sserakt <t3ss@posteo.de>2022-04-03 14:29:27 +0200
commit8f5b71e500a10790bf72d42de03e2db4971bf772 (patch)
tree10507356b5df0d2d0ce0b3b60a91dc070ce1001d /src
parent027177be3bae0c60d530b0b88ed375b082c94d81 (diff)
parente6a0ea8cf388a05856aaedbc5444f266ae47a7ef (diff)
downloadgnunet-8f5b71e500a10790bf72d42de03e2db4971bf772.tar.gz
gnunet-8f5b71e500a10790bf72d42de03e2db4971bf772.zip
Merge branch 'master' of ssh://git.gnunet.org/gnunet
Diffstat (limited to 'src')
-rw-r--r--src/dhtu/Makefile.am9
-rw-r--r--src/fs/test_fs_uri.c2
-rw-r--r--src/fs/test_plugin_block_fs.c3
-rw-r--r--src/gns/gnunet-service-gns_resolver.c19
-rw-r--r--src/gns/plugin_block_gns.c4
-rw-r--r--src/gnsrecord/gnsrecord_crypto.c39
-rw-r--r--src/gnsrecord/gnunet-gnsrecord-tvg.c120
-rw-r--r--src/include/gnunet_crypto_lib.h281
-rw-r--r--src/include/gnunet_messenger_service.h23
-rw-r--r--src/include/gnunet_namestore_plugin.h65
-rw-r--r--src/include/gnunet_namestore_service.h156
-rw-r--r--src/include/gnunet_time_lib.h29
-rw-r--r--src/messenger/plugin_gnsrecord_messenger.c59
-rw-r--r--src/namestore/Makefile.am11
-rw-r--r--src/namestore/gnunet-service-namestore.c183
-rw-r--r--src/namestore/namestore.h10
-rw-r--r--src/namestore/namestore_api.c115
-rw-r--r--src/pq/pq_result_helper.c6
-rw-r--r--src/transport/Makefile.am1
-rw-r--r--src/util/.gitignore1
-rw-r--r--src/util/Makefile.am8
-rw-r--r--src/util/crypto_ecc_gnsrecord.c55
-rw-r--r--src/util/crypto_edx25519.c418
-rw-r--r--src/util/crypto_hkdf.c118
-rw-r--r--src/util/crypto_kdf.c61
-rw-r--r--src/util/crypto_rsa.c28
-rw-r--r--src/util/test_crypto_eddsa.c8
-rw-r--r--src/util/test_crypto_edx25519.c326
-rw-r--r--src/util/time.c30
29 files changed, 1642 insertions, 546 deletions
diff --git a/src/dhtu/Makefile.am b/src/dhtu/Makefile.am
index ebffa9ecf..4d210b71f 100644
--- a/src/dhtu/Makefile.am
+++ b/src/dhtu/Makefile.am
@@ -13,10 +13,11 @@ endif
13pkgcfg_DATA = \ 13pkgcfg_DATA = \
14 dhtu.conf 14 dhtu.conf
15 15
16
17plugin_LTLIBRARIES = \ 16plugin_LTLIBRARIES = \
18 libgnunet_plugin_dhtu_gnunet.la \ 17 libgnunet_plugin_dhtu_gnunet.la
19 libgnunet_plugin_dhtu_ip.la 18
19if !OPENBSD
20plugin_LTLIBRARIES += libgnunet_plugin_dhtu_ip.la
20 21
21libgnunet_plugin_dhtu_ip_la_SOURCES = \ 22libgnunet_plugin_dhtu_ip_la_SOURCES = \
22 plugin_dhtu_ip.c 23 plugin_dhtu_ip.c
@@ -26,7 +27,7 @@ libgnunet_plugin_dhtu_ip_la_LIBADD = \
26 $(LTLIBINTL) 27 $(LTLIBINTL)
27libgnunet_plugin_dhtu_ip_la_LDFLAGS = \ 28libgnunet_plugin_dhtu_ip_la_LDFLAGS = \
28 $(GN_PLUGIN_LDFLAGS) 29 $(GN_PLUGIN_LDFLAGS)
29 30endif
30 31
31 32
32libgnunet_plugin_dhtu_gnunet_la_SOURCES = \ 33libgnunet_plugin_dhtu_gnunet_la_SOURCES = \
diff --git a/src/fs/test_fs_uri.c b/src/fs/test_fs_uri.c
index 30eafab9a..aac7b1b97 100644
--- a/src/fs/test_fs_uri.c
+++ b/src/fs/test_fs_uri.c
@@ -80,7 +80,7 @@ testLocation ()
80 char *uric; 80 char *uric;
81 struct GNUNET_FS_Uri *uri2; 81 struct GNUNET_FS_Uri *uri2;
82 struct GNUNET_FS_Uri *baseURI; 82 struct GNUNET_FS_Uri *baseURI;
83 char *emsg; 83 char *emsg = NULL;
84 struct GNUNET_CRYPTO_EddsaPrivateKey pk; 84 struct GNUNET_CRYPTO_EddsaPrivateKey pk;
85 85
86 baseURI = 86 baseURI =
diff --git a/src/fs/test_plugin_block_fs.c b/src/fs/test_plugin_block_fs.c
index 727cc37c2..f15d10b17 100644
--- a/src/fs/test_plugin_block_fs.c
+++ b/src/fs/test_plugin_block_fs.c
@@ -43,7 +43,6 @@ test_fs (struct GNUNET_BLOCK_Context *ctx)
43 if (GNUNET_OK != 43 if (GNUNET_OK !=
44 GNUNET_BLOCK_check_block (ctx, 44 GNUNET_BLOCK_check_block (ctx,
45 GNUNET_BLOCK_TYPE_FS_DBLOCK, 45 GNUNET_BLOCK_TYPE_FS_DBLOCK,
46 &key,
47 block, 46 block,
48 sizeof(block))) 47 sizeof(block)))
49 return 2; 48 return 2;
@@ -54,7 +53,7 @@ test_fs (struct GNUNET_BLOCK_Context *ctx)
54 NULL, 0)) 53 NULL, 0))
55 return 4; 54 return 4;
56 GNUNET_log_skip (1, GNUNET_NO); 55 GNUNET_log_skip (1, GNUNET_NO);
57 if (GNUNET_BLOCK_EVALUATION_REQUEST_INVALID != 56 if (GNUNET_NO !=
58 GNUNET_BLOCK_check_query (ctx, 57 GNUNET_BLOCK_check_query (ctx,
59 GNUNET_BLOCK_TYPE_FS_DBLOCK, 58 GNUNET_BLOCK_TYPE_FS_DBLOCK,
60 &key, 59 &key,
diff --git a/src/gns/gnunet-service-gns_resolver.c b/src/gns/gnunet-service-gns_resolver.c
index 72b228f33..9d26e1777 100644
--- a/src/gns/gnunet-service-gns_resolver.c
+++ b/src/gns/gnunet-service-gns_resolver.c
@@ -623,6 +623,19 @@ resolver_lookup_get_next_label (struct GNS_ResolverHandle *rh)
623 rp = rh->name; 623 rp = rh->name;
624 rh->name_resolution_pos = 0; 624 rh->name_resolution_pos = 0;
625 } 625 }
626 else if (('_' == dot[1]) &&
627 ('_' == rh->name[0]) &&
628 (dot == memchr (rh->name, (int) '.', rh->name_resolution_pos)))
629 {
630 /**
631 * Do not advance a label. This seems to be a name only consisting
632 * of a BOX indicator (_443,_tcp).
633 * Which means, it is a BOX under the empty label.
634 * leaving name_resolution_pos as is and returning empty label.
635 */
636 rp = GNUNET_GNS_EMPTY_LABEL_AT;
637 len = strlen (GNUNET_GNS_EMPTY_LABEL_AT);
638 }
626 else 639 else
627 { 640 {
628 /* advance by one label */ 641 /* advance by one label */
@@ -683,7 +696,7 @@ resolver_lookup_get_next_label (struct GNS_ResolverHandle *rh)
683 } 696 }
684 else 697 else
685 { 698 {
686 rh->service = se->s_port; 699 rh->service = ntohs (se->s_port);
687 } 700 }
688 rh->protocol = pe->p_proto; 701 rh->protocol = pe->p_proto;
689 GNUNET_free (proto_name); 702 GNUNET_free (proto_name);
@@ -2237,6 +2250,10 @@ handle_gns_resolution_result (void *cls,
2237 const struct GNUNET_GNSRECORD_BoxRecord *box; 2250 const struct GNUNET_GNSRECORD_BoxRecord *box;
2238 2251
2239 box = rd[i].data; 2252 box = rd[i].data;
2253 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2254 "Got BOX record, checking if parameters match... %u/%u vs %u/%u\n",
2255 ntohs (box->protocol), ntohs (box->service),
2256 rh->protocol, rh->service);
2240 if ((ntohs (box->protocol) == rh->protocol) && 2257 if ((ntohs (box->protocol) == rh->protocol) &&
2241 (ntohs (box->service) == rh->service)) 2258 (ntohs (box->service) == rh->service))
2242 { 2259 {
diff --git a/src/gns/plugin_block_gns.c b/src/gns/plugin_block_gns.c
index fd9c99cb4..ffca16b6f 100644
--- a/src/gns/plugin_block_gns.c
+++ b/src/gns/plugin_block_gns.c
@@ -181,7 +181,7 @@ block_plugin_gns_check_block (void *cls,
181 size_t block_size) 181 size_t block_size)
182{ 182{
183 const struct GNUNET_GNSRECORD_Block *gblock; 183 const struct GNUNET_GNSRECORD_Block *gblock;
184 184
185 if (GNUNET_BLOCK_TYPE_GNS_NAMERECORD != type) 185 if (GNUNET_BLOCK_TYPE_GNS_NAMERECORD != type)
186 { 186 {
187 GNUNET_break (0); 187 GNUNET_break (0);
@@ -243,7 +243,7 @@ block_plugin_gns_check_reply (void *cls,
243 return GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED; 243 return GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED;
244 } 244 }
245 GNUNET_assert (reply_block_size >= sizeof(struct GNUNET_GNSRECORD_Block)); 245 GNUNET_assert (reply_block_size >= sizeof(struct GNUNET_GNSRECORD_Block));
246 GNUNET_assert (GNUNET_GNSRECORD_block_get_size (block) > reply_block_size); 246 GNUNET_assert (reply_block_size >= GNUNET_GNSRECORD_block_get_size (block));
247 GNUNET_CRYPTO_hash (reply_block, 247 GNUNET_CRYPTO_hash (reply_block,
248 reply_block_size, 248 reply_block_size,
249 &chash); 249 &chash);
diff --git a/src/gnsrecord/gnsrecord_crypto.c b/src/gnsrecord/gnsrecord_crypto.c
index ff92911de..b5e8be82b 100644
--- a/src/gnsrecord/gnsrecord_crypto.c
+++ b/src/gnsrecord/gnsrecord_crypto.c
@@ -219,7 +219,6 @@ block_create_ecdsa (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
219 rd); 219 rd);
220 struct GNUNET_GNSRECORD_EcdsaBlock *ecblock; 220 struct GNUNET_GNSRECORD_EcdsaBlock *ecblock;
221 struct GNRBlockPS *gnr_block; 221 struct GNRBlockPS *gnr_block;
222 struct GNUNET_CRYPTO_EcdsaPrivateKey *dkey;
223 unsigned char ctr[GNUNET_CRYPTO_AES_KEY_LENGTH / 2]; 222 unsigned char ctr[GNUNET_CRYPTO_AES_KEY_LENGTH / 2];
224 unsigned char skey[GNUNET_CRYPTO_AES_KEY_LENGTH]; 223 unsigned char skey[GNUNET_CRYPTO_AES_KEY_LENGTH];
225 struct GNUNET_GNSRECORD_Data rdc[GNUNET_NZL (rd_count)]; 224 struct GNUNET_GNSRECORD_Data rdc[GNUNET_NZL (rd_count)];
@@ -270,11 +269,10 @@ block_create_ecdsa (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
270 gnr_block->expiration_time = GNUNET_TIME_absolute_hton (expire); 269 gnr_block->expiration_time = GNUNET_TIME_absolute_hton (expire);
271 ecblock->expiration_time = gnr_block->expiration_time; 270 ecblock->expiration_time = gnr_block->expiration_time;
272 /* encrypt and sign */ 271 /* encrypt and sign */
273 dkey = GNUNET_CRYPTO_ecdsa_private_key_derive (key, 272 GNUNET_CRYPTO_ecdsa_public_key_derive (pkey,
274 label, 273 label,
275 "gns"); 274 "gns",
276 GNUNET_CRYPTO_ecdsa_key_get_public (dkey, 275 &ecblock->derived_key);
277 &ecblock->derived_key);
278 GNR_derive_block_aes_key (ctr, 276 GNR_derive_block_aes_key (ctr,
279 skey, 277 skey,
280 label, 278 label,
@@ -289,18 +287,18 @@ block_create_ecdsa (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
289 GNUNET_memcpy (&gnr_block[1], &ecblock[1], payload_len); 287 GNUNET_memcpy (&gnr_block[1], &ecblock[1], payload_len);
290 } 288 }
291 if (GNUNET_OK != 289 if (GNUNET_OK !=
292 GNUNET_CRYPTO_ecdsa_sign_ (dkey, 290 GNUNET_CRYPTO_ecdsa_sign_derived (key,
293 &gnr_block->purpose, 291 label,
294 &ecblock->signature)) 292 "gns",
293 &gnr_block->purpose,
294 &ecblock->signature))
295 { 295 {
296 GNUNET_break (0); 296 GNUNET_break (0);
297 GNUNET_free (*block); 297 GNUNET_free (*block);
298 GNUNET_free (dkey);
299 GNUNET_free (gnr_block); 298 GNUNET_free (gnr_block);
300 return GNUNET_SYSERR; 299 return GNUNET_SYSERR;
301 } 300 }
302 GNUNET_free (gnr_block); 301 GNUNET_free (gnr_block);
303 GNUNET_free (dkey);
304 return GNUNET_OK; 302 return GNUNET_OK;
305} 303}
306 304
@@ -344,7 +342,6 @@ block_create_eddsa (const struct GNUNET_CRYPTO_EddsaPrivateKey *key,
344 rd); 342 rd);
345 struct GNUNET_GNSRECORD_EddsaBlock *edblock; 343 struct GNUNET_GNSRECORD_EddsaBlock *edblock;
346 struct GNRBlockPS *gnr_block; 344 struct GNRBlockPS *gnr_block;
347 struct GNUNET_CRYPTO_EddsaPrivateScalar dkey;
348 unsigned char nonce[crypto_secretbox_NONCEBYTES]; 345 unsigned char nonce[crypto_secretbox_NONCEBYTES];
349 unsigned char skey[crypto_secretbox_KEYBYTES]; 346 unsigned char skey[crypto_secretbox_KEYBYTES];
350 struct GNUNET_GNSRECORD_Data rdc[GNUNET_NZL (rd_count)]; 347 struct GNUNET_GNSRECORD_Data rdc[GNUNET_NZL (rd_count)];
@@ -402,12 +399,10 @@ block_create_eddsa (const struct GNUNET_CRYPTO_EddsaPrivateKey *key,
402 gnr_block->expiration_time = GNUNET_TIME_absolute_hton (expire); 399 gnr_block->expiration_time = GNUNET_TIME_absolute_hton (expire);
403 edblock->expiration_time = gnr_block->expiration_time; 400 edblock->expiration_time = gnr_block->expiration_time;
404 /* encrypt and sign */ 401 /* encrypt and sign */
405 GNUNET_CRYPTO_eddsa_private_key_derive (key, 402 GNUNET_CRYPTO_eddsa_public_key_derive (pkey,
406 label, 403 label,
407 "gns", 404 "gns",
408 &dkey); 405 &edblock->derived_key);
409 GNUNET_CRYPTO_eddsa_key_get_public_from_scalar (&dkey,
410 &edblock->derived_key);
411 GNR_derive_block_xsalsa_key (nonce, 406 GNR_derive_block_xsalsa_key (nonce,
412 skey, 407 skey,
413 label, 408 label,
@@ -422,9 +417,11 @@ block_create_eddsa (const struct GNUNET_CRYPTO_EddsaPrivateKey *key,
422 GNUNET_memcpy (&gnr_block[1], &edblock[1], 417 GNUNET_memcpy (&gnr_block[1], &edblock[1],
423 payload_len + crypto_secretbox_MACBYTES); 418 payload_len + crypto_secretbox_MACBYTES);
424 419
425 GNUNET_CRYPTO_eddsa_sign_with_scalar (&dkey, 420 GNUNET_CRYPTO_eddsa_sign_derived (key,
426 &gnr_block->purpose, 421 label,
427 &edblock->signature); 422 "gns",
423 &gnr_block->purpose,
424 &edblock->signature);
428 } 425 }
429 return GNUNET_OK; 426 return GNUNET_OK;
430} 427}
diff --git a/src/gnsrecord/gnunet-gnsrecord-tvg.c b/src/gnsrecord/gnunet-gnsrecord-tvg.c
index 87de32066..7fef6f8e7 100644
--- a/src/gnsrecord/gnunet-gnsrecord-tvg.c
+++ b/src/gnsrecord/gnunet-gnsrecord-tvg.c
@@ -96,20 +96,22 @@ static void
96print_record (const struct GNUNET_GNSRECORD_Data *rd) 96print_record (const struct GNUNET_GNSRECORD_Data *rd)
97{ 97{
98 uint16_t flags = htons (rd->flags); 98 uint16_t flags = htons (rd->flags);
99 fprintf (stdout, 99 uint64_t abs_nbo = GNUNET_htonll (rd->expiration_time);
100 "EXPIRATION: %" PRIu64 "\n", rd->expiration_time); 100 uint16_t size_nbo = htons (rd->data_size);
101 fprintf (stdout, 101 uint32_t type_nbo = htonl (rd->record_type);
102 "DATA_SIZE: %zu\n", rd->data_size); 102 printf ("EXPIRATION:\n");
103 fprintf (stdout, 103 print_bytes (&abs_nbo, sizeof (abs_nbo), 8);
104 "TYPE: %d\n", rd->record_type); 104 printf ("\nDATA_SIZE:\n");
105 fprintf (stdout, 105 print_bytes (&size_nbo, sizeof (size_nbo), 8);
106 "FLAGS: "); 106 printf ("\nTYPE:\n");
107 print_bytes(&type_nbo, sizeof (type_nbo), 8);
108 printf ("\nFLAGS: ");
107 print_bytes ((void*) &flags, sizeof (flags), 8); 109 print_bytes ((void*) &flags, sizeof (flags), 8);
108 printf ("\n"); 110 printf ("\n");
109 fprintf (stdout, 111 fprintf (stdout,
110 "DATA:\n"); 112 "DATA:\n");
111 print_bytes ((char*) rd->data, rd->data_size, 8); 113 print_bytes ((char*) rd->data, rd->data_size, 8);
112 fprintf (stdout, "\n"); 114 printf ("\n");
113} 115}
114 116
115 117
@@ -133,6 +135,7 @@ run_pkey (struct GNUNET_GNSRECORD_Data *rd, int rd_count, const char *label)
133 struct GNUNET_IDENTITY_PublicKey pkey_data; 135 struct GNUNET_IDENTITY_PublicKey pkey_data;
134 struct GNUNET_HashCode query; 136 struct GNUNET_HashCode query;
135 char *rdata; 137 char *rdata;
138 char *conv_lbl;
136 size_t rdata_size; 139 size_t rdata_size;
137 char ztld[128]; 140 char ztld[128];
138 unsigned char ctr[GNUNET_CRYPTO_AES_KEY_LENGTH / 2]; 141 unsigned char ctr[GNUNET_CRYPTO_AES_KEY_LENGTH / 2];
@@ -146,34 +149,37 @@ run_pkey (struct GNUNET_GNSRECORD_Data *rd, int rd_count, const char *label)
146 149
147 GNUNET_IDENTITY_key_get_public (&id_priv, 150 GNUNET_IDENTITY_key_get_public (&id_priv,
148 &id_pub); 151 &id_pub);
149 fprintf (stdout, 152 printf ("Zone private key (d, big-endian):\n");
150 "Zone private key (d, big-endian):\n");
151 print_bytes_ (&id_priv.ecdsa_key, 153 print_bytes_ (&id_priv.ecdsa_key,
152 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey), 8, 1); 154 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey), 8, 1);
153 fprintf (stdout, "\n"); 155 printf ("\n");
154 fprintf (stdout, "Zone identifier (ztype|zkey):\n"); 156 printf ("Zone identifier (ztype|zkey):\n");
155 GNUNET_assert (0 < GNUNET_IDENTITY_key_get_length (&id_pub)); 157 GNUNET_assert (0 < GNUNET_IDENTITY_key_get_length (&id_pub));
156 print_bytes (&id_pub, GNUNET_IDENTITY_key_get_length (&id_pub), 8); 158 print_bytes (&id_pub, GNUNET_IDENTITY_key_get_length (&id_pub), 8);
157 GNUNET_STRINGS_data_to_string (&id_pub, 159 GNUNET_STRINGS_data_to_string (&id_pub,
158 GNUNET_IDENTITY_key_get_length (&id_pub), 160 GNUNET_IDENTITY_key_get_length (&id_pub),
159 ztld, 161 ztld,
160 sizeof (ztld)); 162 sizeof (ztld));
161 fprintf (stdout, "\n"); 163 printf ("\n");
162 fprintf (stdout, "zTLD:\n"); 164 printf ("zTLD:\n");
163 fprintf (stdout, "%s\n", ztld); 165 printf ("%s\n", ztld);
164 fprintf (stdout, "\n"); 166 printf ("\n");
165 167
166 pkey_data_p.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); 168 pkey_data_p.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
167 GNUNET_CRYPTO_ecdsa_key_create (&pkey_data_p.ecdsa_key); 169 GNUNET_CRYPTO_ecdsa_key_create (&pkey_data_p.ecdsa_key);
168 GNUNET_IDENTITY_key_get_public (&pkey_data_p, 170 GNUNET_IDENTITY_key_get_public (&pkey_data_p,
169 &pkey_data); 171 &pkey_data);
170 fprintf (stdout, 172 conv_lbl = GNUNET_GNSRECORD_string_normalize (label);
171 "Label: %s\nRRCOUNT: %d\n\n", label, rd_count); 173 printf ("Label:\n");
174 print_bytes (conv_lbl, strlen (conv_lbl), 8);
175 GNUNET_free (conv_lbl);
176 printf ("\nNumber of records (integer): %d\n\n", rd_count);
172 177
173 for (int i = 0; i < rd_count; i++) 178 for (int i = 0; i < rd_count; i++)
174 { 179 {
175 fprintf (stdout, "Record #%d\n", i); 180 printf ("Record #%d := (\n", i);
176 print_record (&rd[i]); 181 print_record (&rd[i]);
182 printf (")\n\n");
177 } 183 }
178 184
179 rdata_size = GNUNET_GNSRECORD_records_get_size (rd_count, 185 rdata_size = GNUNET_GNSRECORD_records_get_size (rd_count,
@@ -183,11 +189,11 @@ run_pkey (struct GNUNET_GNSRECORD_Data *rd, int rd_count, const char *label)
183 rd, 189 rd,
184 (size_t) rdata_size, 190 (size_t) rdata_size,
185 rdata); 191 rdata);
186 fprintf (stdout, "RDATA:\n"); 192 printf ("RDATA:\n");
187 print_bytes (rdata, 193 print_bytes (rdata,
188 (size_t) rdata_size, 194 (size_t) rdata_size,
189 8); 195 8);
190 fprintf (stdout, "\n"); 196 printf ("\n");
191 expire = GNUNET_GNSRECORD_record_get_expiration_time (rd_count, rd, 197 expire = GNUNET_GNSRECORD_record_get_expiration_time (rd_count, rd,
192 GNUNET_TIME_UNIT_ZERO_ABS); 198 GNUNET_TIME_UNIT_ZERO_ABS);
193 GNR_derive_block_aes_key (ctr, 199 GNR_derive_block_aes_key (ctr,
@@ -197,18 +203,18 @@ run_pkey (struct GNUNET_GNSRECORD_Data *rd, int rd_count, const char *label)
197 expire).abs_value_us__, 203 expire).abs_value_us__,
198 &id_pub.ecdsa_key); 204 &id_pub.ecdsa_key);
199 205
200 fprintf (stdout, "Encryption NONCE|EXPIRATION|BLOCK COUNTER:\n"); 206 printf ("Encryption NONCE|EXPIRATION|BLOCK COUNTER:\n");
201 print_bytes (ctr, sizeof (ctr), 8); 207 print_bytes (ctr, sizeof (ctr), 8);
202 fprintf (stdout, "\n"); 208 printf ("\n");
203 fprintf (stdout, "Encryption key (K):\n"); 209 printf ("Encryption key (K):\n");
204 print_bytes (skey, sizeof (skey), 8); 210 print_bytes (skey, sizeof (skey), 8);
205 fprintf (stdout, "\n"); 211 printf ("\n");
206 GNUNET_GNSRECORD_query_from_public_key (&id_pub, 212 GNUNET_GNSRECORD_query_from_public_key (&id_pub,
207 label, 213 label,
208 &query); 214 &query);
209 fprintf (stdout, "Storage key (q):\n"); 215 printf ("Storage key (q):\n");
210 print_bytes (&query, sizeof (query), 8); 216 print_bytes (&query, sizeof (query), 8);
211 fprintf (stdout, "\n"); 217 printf ("\n");
212 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create (&id_priv, 218 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create (&id_priv,
213 expire, 219 expire,
214 label, 220 label,
@@ -219,12 +225,12 @@ run_pkey (struct GNUNET_GNSRECORD_Data *rd, int rd_count, const char *label)
219 GNUNET_GNSRECORD_Block); 225 GNUNET_GNSRECORD_Block);
220 226
221 bdata = (char*) &(&rrblock->ecdsa_block)[1]; 227 bdata = (char*) &(&rrblock->ecdsa_block)[1];
222 fprintf (stdout, "BDATA:\n"); 228 printf ("BDATA:\n");
223 print_bytes (bdata, bdata_size, 8); 229 print_bytes (bdata, bdata_size, 8);
224 fprintf (stdout, "\n"); 230 printf ("\n");
225 fprintf (stdout, "RRBLOCK:\n"); 231 printf ("RRBLOCK:\n");
226 print_bytes (rrblock, ntohl (rrblock->size), 8); 232 print_bytes (rrblock, ntohl (rrblock->size), 8);
227 fprintf (stdout, "\n"); 233 printf ("\n");
228 GNUNET_free (rdata); 234 GNUNET_free (rdata);
229} 235}
230 236
@@ -249,6 +255,7 @@ run_edkey (struct GNUNET_GNSRECORD_Data *rd, int rd_count, const char*label)
249 struct GNUNET_IDENTITY_PublicKey pkey_data; 255 struct GNUNET_IDENTITY_PublicKey pkey_data;
250 struct GNUNET_HashCode query; 256 struct GNUNET_HashCode query;
251 char *rdata; 257 char *rdata;
258 char *conv_lbl;
252 size_t rdata_size; 259 size_t rdata_size;
253 260
254 char ztld[128]; 261 char ztld[128];
@@ -271,30 +278,35 @@ run_edkey (struct GNUNET_GNSRECORD_Data *rd, int rd_count, const char*label)
271 "Zone private key (d):\n"); 278 "Zone private key (d):\n");
272 print_bytes (&id_priv.eddsa_key, sizeof (struct 279 print_bytes (&id_priv.eddsa_key, sizeof (struct
273 GNUNET_CRYPTO_EddsaPrivateKey), 8); 280 GNUNET_CRYPTO_EddsaPrivateKey), 8);
274 fprintf (stdout, "\n"); 281 printf ("\n");
275 fprintf (stdout, "Zone identifier (ztype|zkey):\n"); 282 printf ("Zone identifier (ztype|zkey):\n");
276 GNUNET_assert (0 < GNUNET_IDENTITY_key_get_length (&id_pub)); 283 GNUNET_assert (0 < GNUNET_IDENTITY_key_get_length (&id_pub));
277 print_bytes (&id_pub, GNUNET_IDENTITY_key_get_length (&id_pub), 8); 284 print_bytes (&id_pub, GNUNET_IDENTITY_key_get_length (&id_pub), 8);
278 GNUNET_STRINGS_data_to_string (&id_pub, 285 GNUNET_STRINGS_data_to_string (&id_pub,
279 GNUNET_IDENTITY_key_get_length (&id_pub), 286 GNUNET_IDENTITY_key_get_length (&id_pub),
280 ztld, 287 ztld,
281 sizeof (ztld)); 288 sizeof (ztld));
282 fprintf (stdout, "\n"); 289 printf ("\n");
283 fprintf (stdout, "zTLD:\n"); 290 printf ("zTLD:\n");
284 fprintf (stdout, "%s\n", ztld); 291 printf ("%s\n", ztld);
285 fprintf (stdout, "\n"); 292 printf ("\n");
286 293
287 pkey_data_p.type = htonl (GNUNET_GNSRECORD_TYPE_EDKEY); 294 pkey_data_p.type = htonl (GNUNET_GNSRECORD_TYPE_EDKEY);
288 GNUNET_CRYPTO_eddsa_key_create (&pkey_data_p.eddsa_key); 295 GNUNET_CRYPTO_eddsa_key_create (&pkey_data_p.eddsa_key);
289 GNUNET_IDENTITY_key_get_public (&pkey_data_p, 296 GNUNET_IDENTITY_key_get_public (&pkey_data_p,
290 &pkey_data); 297 &pkey_data);
298 conv_lbl = GNUNET_GNSRECORD_string_normalize (label);
299 printf ("Label:\n");
300 print_bytes (conv_lbl, strlen (conv_lbl), 8);
301 GNUNET_free (conv_lbl);
291 fprintf (stdout, 302 fprintf (stdout,
292 "Label: %s\nRRCOUNT: %d\n\n", label, rd_count); 303 "\nNumber of records (integer): %d\n\n", rd_count);
293 304
294 for (int i = 0; i < rd_count; i++) 305 for (int i = 0; i < rd_count; i++)
295 { 306 {
296 fprintf (stdout, "Record #%d\n", i); 307 printf ("Record #%d := (\n", i);
297 print_record (&rd[i]); 308 print_record (&rd[i]);
309 printf (")\n\n");
298 } 310 }
299 311
300 rdata_size = GNUNET_GNSRECORD_records_get_size (rd_count, 312 rdata_size = GNUNET_GNSRECORD_records_get_size (rd_count,
@@ -308,29 +320,29 @@ run_edkey (struct GNUNET_GNSRECORD_Data *rd, int rd_count, const char*label)
308 rd, 320 rd,
309 (size_t) rdata_size, 321 (size_t) rdata_size,
310 rdata); 322 rdata);
311 fprintf (stdout, "RDATA:\n"); 323 printf ("RDATA:\n");
312 print_bytes (rdata, 324 print_bytes (rdata,
313 (size_t) rdata_size, 325 (size_t) rdata_size,
314 8); 326 8);
315 fprintf (stdout, "\n"); 327 printf ("\n");
316 GNR_derive_block_xsalsa_key (nonce, 328 GNR_derive_block_xsalsa_key (nonce,
317 skey, 329 skey,
318 label, 330 label,
319 GNUNET_TIME_absolute_hton ( 331 GNUNET_TIME_absolute_hton (
320 expire).abs_value_us__, 332 expire).abs_value_us__,
321 &id_pub.eddsa_key); 333 &id_pub.eddsa_key);
322 fprintf (stdout, "Encryption NONCE|EXPIRATION:\n"); 334 printf ("Encryption NONCE|EXPIRATION:\n");
323 print_bytes (nonce, sizeof (nonce), 8); 335 print_bytes (nonce, sizeof (nonce), 8);
324 fprintf (stdout, "\n"); 336 printf ("\n");
325 fprintf (stdout, "Encryption key (K):\n"); 337 printf ("Encryption key (K):\n");
326 print_bytes (skey, sizeof (skey), 8); 338 print_bytes (skey, sizeof (skey), 8);
327 fprintf (stdout, "\n"); 339 printf ("\n");
328 GNUNET_GNSRECORD_query_from_public_key (&id_pub, 340 GNUNET_GNSRECORD_query_from_public_key (&id_pub,
329 label, 341 label,
330 &query); 342 &query);
331 fprintf (stdout, "Storage key (q):\n"); 343 printf ("Storage key (q):\n");
332 print_bytes (&query, sizeof (query), 8); 344 print_bytes (&query, sizeof (query), 8);
333 fprintf (stdout, "\n"); 345 printf ("\n");
334 346
335 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create (&id_priv, 347 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create (&id_priv,
336 expire, 348 expire,
@@ -342,12 +354,12 @@ run_edkey (struct GNUNET_GNSRECORD_Data *rd, int rd_count, const char*label)
342 GNUNET_GNSRECORD_Block); 354 GNUNET_GNSRECORD_Block);
343 355
344 bdata = (char*) &(&rrblock->eddsa_block)[1]; 356 bdata = (char*) &(&rrblock->eddsa_block)[1];
345 fprintf (stdout, "BDATA:\n"); 357 printf ("BDATA:\n");
346 print_bytes (bdata, bdata_size, 8); 358 print_bytes (bdata, bdata_size, 8);
347 fprintf (stdout, "\n"); 359 printf ("\n");
348 fprintf (stdout, "RRBLOCK:\n"); 360 printf ("RRBLOCK:\n");
349 print_bytes (rrblock, ntohl (rrblock->size), 8); 361 print_bytes (rrblock, ntohl (rrblock->size), 8);
350 fprintf (stdout, "\n"); 362 printf ("\n");
351 GNUNET_free (rdata); 363 GNUNET_free (rdata);
352} 364}
353 365
@@ -424,9 +436,9 @@ run (void *cls,
424 | GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; 436 | GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
425 437
426 run_pkey (&rd_pkey, 1, "testdelegation"); 438 run_pkey (&rd_pkey, 1, "testdelegation");
427 run_pkey (rd, 3, "namesystem"); 439 run_pkey (rd, 3, "\u5929\u4e0b\u7121\u6575");
428 run_edkey (&rd_pkey, 1, "testdelegation"); 440 run_edkey (&rd_pkey, 1, "testdelegation");
429 run_edkey (rd, 3, "namesystem"); 441 run_edkey (rd, 3, "\u5929\u4e0b\u7121\u6575");
430} 442}
431 443
432 444
diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h
index 72d783148..582a58861 100644
--- a/src/include/gnunet_crypto_lib.h
+++ b/src/include/gnunet_crypto_lib.h
@@ -287,6 +287,59 @@ struct GNUNET_CRYPTO_EddsaPrivateScalar
287 unsigned char s[512 / 8]; 287 unsigned char s[512 / 8];
288}; 288};
289 289
290/**
291 * Private ECC key material encoded for transmission. To be used only for
292 * Edx25519 signatures. An inital key corresponds to data from the key
293 * expansion and clamping in the EdDSA key generation.
294 */
295struct GNUNET_CRYPTO_Edx25519PrivateKey
296{
297 /**
298 * a is a value mod n, where n has at most 256 bits. It is the first half of
299 * the seed-expansion of EdDSA and will be clamped.
300 */
301 unsigned char a[256 / 8];
302
303 /**
304 * b consists of 32 bytes which where originally the lower 32bytes of the key
305 * expansion. Subsequent calls to derive_private will change this value, too.
306 */
307 unsigned char b[256 / 8];
308};
309
310
311/**
312 * Public ECC key (always for curve Ed25519) encoded in a format suitable for
313 * network transmission and Edx25519 (same as EdDSA) signatures. Refer to
314 * section 5.1.3 of rfc8032, for a thorough explanation of how this value maps
315 * to the x- and y-coordinates.
316 */
317struct GNUNET_CRYPTO_Edx25519PublicKey
318{
319 /**
320 * Point Q consists of a y-value mod p (256 bits); the x-value is
321 * always positive. The point is stored in Ed25519 standard
322 * compact format.
323 */
324 unsigned char q_y[256 / 8];
325};
326
327/**
328 * @brief an ECC signature using Edx25519 (same as in EdDSA).
329 */
330struct GNUNET_CRYPTO_Edx25519Signature
331{
332 /**
333 * R value.
334 */
335 unsigned char r[256 / 8];
336
337 /**
338 * S value.
339 */
340 unsigned char s[256 / 8];
341};
342
290 343
291/** 344/**
292 * @brief type for session keys 345 * @brief type for session keys
@@ -1279,6 +1332,17 @@ GNUNET_CRYPTO_eddsa_key_get_public (
1279 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, 1332 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
1280 struct GNUNET_CRYPTO_EddsaPublicKey *pub); 1333 struct GNUNET_CRYPTO_EddsaPublicKey *pub);
1281 1334
1335/**
1336 * @ingroup crypto
1337 * Extract the public key for the given private key.
1338 *
1339 * @param priv the private key
1340 * @param pub where to write the public key
1341 */
1342void
1343GNUNET_CRYPTO_edx25519_key_get_public (
1344 const struct GNUNET_CRYPTO_Edx25519PrivateKey *priv,
1345 struct GNUNET_CRYPTO_Edx25519PublicKey *pub);
1282 1346
1283/** 1347/**
1284 * @ingroup crypto 1348 * @ingroup crypto
@@ -1465,6 +1529,30 @@ GNUNET_CRYPTO_eddsa_key_create (struct GNUNET_CRYPTO_EddsaPrivateKey *pk);
1465 1529
1466/** 1530/**
1467 * @ingroup crypto 1531 * @ingroup crypto
1532 * Create a new private key.
1533 *
1534 * @param[out] pk private key to initialize
1535 */
1536void
1537GNUNET_CRYPTO_edx25519_key_create (struct GNUNET_CRYPTO_Edx25519PrivateKey *pk);
1538
1539/**
1540 * @ingroup crypto
1541 * Create a new private key for Edx25519 from a given seed. After expanding
1542 * the seed, the first half of the key will be clamped according to EdDSA.
1543 *
1544 * @param seed seed input
1545 * @param seedsize size of the seed in bytes
1546 * @param[out] pk private key to initialize
1547 */
1548void
1549GNUNET_CRYPTO_edx25519_key_create_from_seed (
1550 const void *seed,
1551 size_t seedsize,
1552 struct GNUNET_CRYPTO_Edx25519PrivateKey *pk);
1553
1554/**
1555 * @ingroup crypto
1468 * Create a new private key. Clear with #GNUNET_CRYPTO_ecdhe_key_clear(). 1556 * Create a new private key. Clear with #GNUNET_CRYPTO_ecdhe_key_clear().
1469 * 1557 *
1470 * @param[out] pk set to fresh private key; 1558 * @param[out] pk set to fresh private key;
@@ -1492,6 +1580,14 @@ GNUNET_CRYPTO_eddsa_key_clear (struct GNUNET_CRYPTO_EddsaPrivateKey *pk);
1492void 1580void
1493GNUNET_CRYPTO_ecdsa_key_clear (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk); 1581GNUNET_CRYPTO_ecdsa_key_clear (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk);
1494 1582
1583/**
1584 * @ingroup crypto
1585 * Clear memory that was used to store a private key.
1586 *
1587 * @param pk location of the key
1588 */
1589void
1590GNUNET_CRYPTO_edx25519_key_clear (struct GNUNET_CRYPTO_Edx25519PrivateKey *pk);
1495 1591
1496/** 1592/**
1497 * @ingroup crypto 1593 * @ingroup crypto
@@ -1874,6 +1970,53 @@ GNUNET_CRYPTO_ecdsa_sign_ (
1874 sig)); \ 1970 sig)); \
1875} while (0) 1971} while (0)
1876 1972
1973/**
1974 * @ingroup crypto
1975 * @brief Edx25519 sign a given block.
1976 *
1977 * The @a purpose data is the beginning of the data of which the signature is
1978 * to be created. The `size` field in @a purpose must correctly indicate the
1979 * number of bytes of the data structure, including its header. If possible,
1980 * use #GNUNET_CRYPTO_edx25519_sign() instead of this function (only if @a
1981 * validate is not fixed-size, you must use this function directly).
1982 *
1983 * @param priv private key to use for the signing
1984 * @param purpose what to sign (size, purpose)
1985 * @param[out] sig where to write the signature
1986 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1987 */
1988enum GNUNET_GenericReturnValue
1989GNUNET_CRYPTO_edx25519_sign_ (
1990 const struct GNUNET_CRYPTO_Edx25519PrivateKey *priv,
1991 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
1992 struct GNUNET_CRYPTO_Edx25519Signature *sig);
1993
1994
1995/**
1996 * @ingroup crypto
1997 * @brief Edx25519 sign a given block. The resulting signature is compatible
1998 * with EdDSA.
1999 *
2000 * The @a ps data must be a fixed-size struct for which the signature is to be
2001 * created. The `size` field in @a ps->purpose must correctly indicate the
2002 * number of bytes of the data structure, including its header.
2003 *
2004 * @param priv private key to use for the signing
2005 * @param ps packed struct with what to sign, MUST begin with a purpose
2006 * @param[out] sig where to write the signature
2007 */
2008#define GNUNET_CRYPTO_edx25519_sign(priv,ps,sig) do { \
2009 /* check size is set correctly */ \
2010 GNUNET_assert (ntohl ((ps)->purpose.size) == sizeof (*(ps))); \
2011 /* check 'ps' begins with the purpose */ \
2012 GNUNET_static_assert (((void*) (ps)) == \
2013 ((void*) &(ps)->purpose)); \
2014 GNUNET_assert (GNUNET_OK == \
2015 GNUNET_CRYPTO_edx25519_sign_ (priv, \
2016 &(ps)->purpose, \
2017 sig)); \
2018} while (0)
2019
1877 2020
1878/** 2021/**
1879 * @ingroup crypto 2022 * @ingroup crypto
@@ -1917,7 +2060,7 @@ GNUNET_CRYPTO_eddsa_verify_ (
1917 */ 2060 */
1918#define GNUNET_CRYPTO_eddsa_verify(purp,ps,sig,pub) ({ \ 2061#define GNUNET_CRYPTO_eddsa_verify(purp,ps,sig,pub) ({ \
1919 /* check size is set correctly */ \ 2062 /* check size is set correctly */ \
1920 GNUNET_assert (ntohl ((ps)->purpose.size) == sizeof (*(ps))); \ 2063 GNUNET_assert (ntohl ((ps)->purpose.size) == sizeof (*(ps))); \
1921 /* check 'ps' begins with the purpose */ \ 2064 /* check 'ps' begins with the purpose */ \
1922 GNUNET_static_assert (((void*) (ps)) == \ 2065 GNUNET_static_assert (((void*) (ps)) == \
1923 ((void*) &(ps)->purpose)); \ 2066 ((void*) &(ps)->purpose)); \
@@ -1927,7 +2070,6 @@ GNUNET_CRYPTO_eddsa_verify_ (
1927 pub); \ 2070 pub); \
1928 }) 2071 })
1929 2072
1930
1931/** 2073/**
1932 * @ingroup crypto 2074 * @ingroup crypto
1933 * @brief Verify ECDSA signature. 2075 * @brief Verify ECDSA signature.
@@ -1982,6 +2124,58 @@ GNUNET_CRYPTO_ecdsa_verify_ (
1982 2124
1983/** 2125/**
1984 * @ingroup crypto 2126 * @ingroup crypto
2127 * @brief Verify Edx25519 signature.
2128 *
2129 * The @a validate data is the beginning of the data of which the signature
2130 * is to be verified. The `size` field in @a validate must correctly indicate
2131 * the number of bytes of the data structure, including its header. If @a
2132 * purpose does not match the purpose given in @a validate (the latter must be
2133 * in big endian), signature verification fails. If possible, use
2134 * #GNUNET_CRYPTO_edx25519_verify() instead of this function (only if @a
2135 * validate is not fixed-size, you must use this function directly).
2136 *
2137 * @param purpose what is the purpose that the signature should have?
2138 * @param validate block to validate (size, purpose, data)
2139 * @param sig signature that is being validated
2140 * @param pub public key of the signer
2141 * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
2142 */
2143enum GNUNET_GenericReturnValue
2144GNUNET_CRYPTO_edx25519_verify_ (
2145 uint32_t purpose,
2146 const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
2147 const struct GNUNET_CRYPTO_Edx25519Signature *sig,
2148 const struct GNUNET_CRYPTO_Edx25519PublicKey *pub);
2149
2150
2151/**
2152 * @ingroup crypto
2153 * @brief Verify Edx25519 signature.
2154 *
2155 * The @a ps data must be a fixed-size struct for which the signature is to be
2156 * created. The `size` field in @a ps->purpose must correctly indicate the
2157 * number of bytes of the data structure, including its header.
2158 *
2159 * @param purp purpose of the signature, must match 'ps->purpose.purpose'
2160 * (except in host byte order)
2161 * @param priv private key to use for the signing
2162 * @param ps packed struct with what to sign, MUST begin with a purpose
2163 * @param sig where to write the signature
2164 */
2165#define GNUNET_CRYPTO_edx25519_verify(purp,ps,sig,pub) ({ \
2166 /* check size is set correctly */ \
2167 GNUNET_assert (ntohl ((ps)->purpose.size) == sizeof (*(ps))); \
2168 /* check 'ps' begins with the purpose */ \
2169 GNUNET_static_assert (((void*) (ps)) == \
2170 ((void*) &(ps)->purpose)); \
2171 GNUNET_CRYPTO_edx25519_verify_ (purp, \
2172 &(ps)->purpose, \
2173 sig, \
2174 pub); \
2175 })
2176
2177/**
2178 * @ingroup crypto
1985 * Derive a private key from a given private key and a label. 2179 * Derive a private key from a given private key and a label.
1986 * Essentially calculates a private key 'h = H(l,P) * d mod n' 2180 * Essentially calculates a private key 'h = H(l,P) * d mod n'
1987 * where n is the size of the ECC group and P is the public 2181 * where n is the size of the ECC group and P is the public
@@ -2018,6 +2212,26 @@ GNUNET_CRYPTO_ecdsa_public_key_derive (
2018 const char *context, 2212 const char *context,
2019 struct GNUNET_CRYPTO_EcdsaPublicKey *result); 2213 struct GNUNET_CRYPTO_EcdsaPublicKey *result);
2020 2214
2215/**
2216 * This is a signature function for ECDSA which takes a
2217 * private key, derives/blinds it and signs the message.
2218 *
2219 * @param pkey original private key
2220 * @param label label to use for key deriviation
2221 * @param context additional context to use for HKDF of 'h';
2222 * typically the name of the subsystem/application
2223 * @param purp the signature purpose
2224 * @param sig the resulting signature
2225 * @return GNUNET_OK on success
2226 */
2227enum GNUNET_GenericReturnValue
2228GNUNET_CRYPTO_ecdsa_sign_derived (
2229 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
2230 const char *label,
2231 const char *context,
2232 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
2233 struct GNUNET_CRYPTO_EcdsaSignature *sig);
2234
2021 2235
2022/** 2236/**
2023 * @ingroup crypto 2237 * @ingroup crypto
@@ -2063,23 +2277,23 @@ GNUNET_CRYPTO_eddsa_public_key_derive (
2063 2277
2064 2278
2065/** 2279/**
2066 * This is a signature function for EdDSA which takes the 2280 * This is a signature function for EdDSA which takes a
2067 * secret scalar sk instead of the private seed which is 2281 * private key and derives it using the label and context
2068 * usually the case for crypto APIs. We require this functionality 2282 * before signing.
2069 * in order to use derived private keys for signatures we
2070 * cannot calculate the inverse of a sk to find the seed
2071 * efficiently.
2072 * 2283 *
2073 * The resulting signature is a standard EdDSA signature 2284 * @param pkey original private key
2074 * which can be verified using the usual APIs. 2285 * @param label label to use for key deriviation
2075 * 2286 * @param context additional context to use for HKDF of 'h';
2076 * @param sk the secret scalar 2287 * typically the name of the subsystem/application
2077 * @param purp the signature purpose 2288 * @param purp the signature purpose
2078 * @param sig the resulting signature 2289 * @param sig the resulting signature
2290 * @return GNUNET_OK on success
2079 */ 2291 */
2080void 2292enum GNUNET_GenericReturnValue
2081GNUNET_CRYPTO_eddsa_sign_with_scalar ( 2293GNUNET_CRYPTO_eddsa_sign_derived (
2082 const struct GNUNET_CRYPTO_EddsaPrivateScalar *priv, 2294 const struct GNUNET_CRYPTO_EddsaPrivateKey *pkey,
2295 const char *label,
2296 const char *context,
2083 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, 2297 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
2084 struct GNUNET_CRYPTO_EddsaSignature *sig); 2298 struct GNUNET_CRYPTO_EddsaSignature *sig);
2085 2299
@@ -2095,6 +2309,43 @@ GNUNET_CRYPTO_eddsa_key_get_public_from_scalar (
2095 const struct GNUNET_CRYPTO_EddsaPrivateScalar *s, 2309 const struct GNUNET_CRYPTO_EddsaPrivateScalar *s,
2096 struct GNUNET_CRYPTO_EddsaPublicKey *pkey); 2310 struct GNUNET_CRYPTO_EddsaPublicKey *pkey);
2097 2311
2312/**
2313 * @ingroup crypto
2314 * Derive a private scalar from a given private key and a label.
2315 * Essentially calculates a private key 'h = H(l,P) * d mod n'
2316 * where n is the size of the ECC group and P is the public
2317 * key associated with the private key 'd'.
2318 *
2319 * @param priv original private key
2320 * @param seed input seed
2321 * @param seedsize size of the seed
2322 * @param result derived private key
2323 */
2324void
2325GNUNET_CRYPTO_edx25519_private_key_derive (
2326 const struct GNUNET_CRYPTO_Edx25519PrivateKey *priv,
2327 const void *seed,
2328 size_t seedsize,
2329 struct GNUNET_CRYPTO_Edx25519PrivateKey *result);
2330
2331
2332/**
2333 * @ingroup crypto
2334 * Derive a public key from a given public key and a label.
2335 * Essentially calculates a public key 'V = H(l,P) * P'.
2336 *
2337 * @param pub original public key
2338 * @param seed input seed
2339 * @param seedsize size of the seed
2340 * @param result where to write the derived public key
2341 */
2342void
2343GNUNET_CRYPTO_edx25519_public_key_derive (
2344 const struct GNUNET_CRYPTO_Edx25519PublicKey *pub,
2345 const void *seed,
2346 size_t seedsize,
2347 struct GNUNET_CRYPTO_Edx25519PublicKey *result);
2348
2098 2349
2099/** 2350/**
2100 * Output the given MPI value to the given buffer in network 2351 * Output the given MPI value to the given buffer in network
diff --git a/src/include/gnunet_messenger_service.h b/src/include/gnunet_messenger_service.h
index 96d48b411..f8bbc7398 100644
--- a/src/include/gnunet_messenger_service.h
+++ b/src/include/gnunet_messenger_service.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 GNUnet e.V. 3 Copyright (C) 2020--2022 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -96,6 +96,27 @@ struct GNUNET_MESSENGER_RoomEntryRecord
96 96
97GNUNET_NETWORK_STRUCT_END 97GNUNET_NETWORK_STRUCT_END
98 98
99GNUNET_NETWORK_STRUCT_BEGIN
100
101/**
102 * A room details record specifies a custom name for a given room and
103 * some additional space for flags.
104 */
105struct GNUNET_MESSENGER_RoomDetailsRecord
106{
107 /**
108 * The custom name for the room.
109 */
110 char name [256];
111
112 /**
113 * The flags of the room.
114 */
115 uint32_t flags;
116};
117
118GNUNET_NETWORK_STRUCT_END
119
99/** 120/**
100 * Enum for the different supported kinds of messages 121 * Enum for the different supported kinds of messages
101 */ 122 */
diff --git a/src/include/gnunet_namestore_plugin.h b/src/include/gnunet_namestore_plugin.h
index 9cc8abc6e..3dca5a853 100644
--- a/src/include/gnunet_namestore_plugin.h
+++ b/src/include/gnunet_namestore_plugin.h
@@ -150,6 +150,71 @@ struct GNUNET_NAMESTORE_PluginFunctions
150 const struct GNUNET_IDENTITY_PublicKey *value_zone, 150 const struct GNUNET_IDENTITY_PublicKey *value_zone,
151 GNUNET_NAMESTORE_RecordIterator iter, 151 GNUNET_NAMESTORE_RecordIterator iter,
152 void *iter_cls); 152 void *iter_cls);
153
154 /** Transaction-based API draft **/
155
156 /**
157 * Start a transaction in the database
158 *
159 * @param cls closure (internal context for the plugin)
160 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
161 */
162 enum GNUNET_GenericReturnValue
163 (*transaction_begin) (void *cls);
164
165 /**
166 * Abort a transaction in the database
167 *
168 * @param cls closure (internal context for the plugin)
169 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
170 */
171 enum GNUNET_GenericReturnValue
172 (*transaction_abort) (void *cls);
173
174 /**
175 * Commit a transaction in the database
176 *
177 * @param cls closure (internal context for the plugin)
178 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
179 */
180 enum GNUNET_GenericReturnValue
181 (*transaction_commit) (void *cls);
182
183 /**
184 * Replace a record in the datastore for which we are the authority.
185 * Removes any existing record in the same zone with the same name.
186 *
187 * @param cls closure (internal context for the plugin)
188 * @param zone private key of the zone
189 * @param label name of the record in the zone
190 * @param rd_count number of entries in @a rd array, 0 to delete all records
191 * @param rd array of records with data to store
192 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
193 */
194 int
195 (*replace_records) (void *cls,
196 const struct GNUNET_IDENTITY_PrivateKey *zone,
197 const char *label,
198 unsigned int rd_count,
199 const struct GNUNET_GNSRECORD_Data *rd);
200
201 /**
202 * Lookup records in the datastore for which we are the authority.
203 *
204 * @param cls closure (internal context for the plugin)
205 * @param zone private key of the zone
206 * @param label name of the record in the zone
207 * @param iter function to call with the result
208 * @param iter_cls closure for @a iter
209 * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR
210 */
211 int
212 (*select_records) (void *cls,
213 const struct GNUNET_IDENTITY_PrivateKey *zone,
214 const char *label,
215 GNUNET_NAMESTORE_RecordIterator iter,
216 void *iter_cls);
217
153}; 218};
154 219
155 220
diff --git a/src/include/gnunet_namestore_service.h b/src/include/gnunet_namestore_service.h
index 619b81aed..86572803f 100644
--- a/src/include/gnunet_namestore_service.h
+++ b/src/include/gnunet_namestore_service.h
@@ -212,61 +212,6 @@ GNUNET_NAMESTORE_records_lookup (struct GNUNET_NAMESTORE_Handle *h,
212 212
213 213
214/** 214/**
215 * Open a record set for editing.
216 * Retrieves an exclusive lock on this set.
217 * Must be commited using @a GNUNET_NAMESTORE_records_commit
218 *
219 * @param h handle to the namestore
220 * @param pkey private key of the zone
221 * @param label name that is being mapped
222 * @param error_cb function to call on error (i.e. disconnect or unable to get lock)
223 * the handle is afterwards invalid
224 * @param error_cb_cls closure for @a error_cb
225 * @param rm function to call with the result (with 0 records if we don't have that label)
226 * @param rm_cls closure for @a rm
227 * @return handle to abort the request
228 */
229struct GNUNET_NAMESTORE_QueueEntry *
230GNUNET_NAMESTORE_records_open (struct GNUNET_NAMESTORE_Handle *h,
231 const struct
232 GNUNET_IDENTITY_PrivateKey *pkey,
233 const char *label,
234 GNUNET_SCHEDULER_TaskCallback error_cb,
235 void *error_cb_cls,
236 GNUNET_NAMESTORE_RecordMonitor rm,
237 void *rm_cls);
238
239/**
240 * Commit the record set to the namestore.
241 * Releases the lock on the record set.
242 * Use an empty array to
243 * remove all records under the given name.
244 *
245 * The continuation is called after the value has been stored in the
246 * database. Monitors may be notified asynchronously (basically with
247 * a buffer). However, if any monitor is consistently too slow to
248 * keep up with the changes, calling @a cont will be delayed until the
249 * monitors do keep up.
250 *
251 * @param h handle to the namestore
252 * @param pkey private key of the zone
253 * @param label name that is being mapped
254 * @param rd_count number of records in the 'rd' array
255 * @param rd array of records with data to store
256 * @param cont continuation to call when done
257 * @param cont_cls closure for @a cont
258 * @return handle to abort the request
259 */
260struct GNUNET_NAMESTORE_QueueEntry *
261GNUNET_NAMESTORE_records_commit (struct GNUNET_NAMESTORE_Handle *h,
262 const struct GNUNET_IDENTITY_PrivateKey *pkey,
263 const char *label,
264 unsigned int rd_count,
265 const struct GNUNET_GNSRECORD_Data *rd,
266 GNUNET_NAMESTORE_ContinuationWithStatus cont,
267 void *cont_cls);
268
269/**
270 * Look for an existing PKEY delegation record for a given public key. 215 * Look for an existing PKEY delegation record for a given public key.
271 * Returns at most one result to the processor. 216 * Returns at most one result to the processor.
272 * 217 *
@@ -448,6 +393,107 @@ void
448GNUNET_NAMESTORE_zone_monitor_stop (struct GNUNET_NAMESTORE_ZoneMonitor *zm); 393GNUNET_NAMESTORE_zone_monitor_stop (struct GNUNET_NAMESTORE_ZoneMonitor *zm);
449 394
450 395
396/**
397 * New API draft. Experimental
398 */
399
400/**
401 * Begin a namestore transaction.
402 *
403 * @param h handle to the namestore
404 * @param error_cb function to call on error (i.e. disconnect or unable to get lock)
405 * the handle is afterwards invalid
406 * @param error_cb_cls closure for @a error_cb
407 * @return handle to abort the request
408 */
409struct GNUNET_NAMESTORE_QueueEntry *
410GNUNET_NAMESTORE_transaction_begin (struct GNUNET_NAMESTORE_Handle *h,
411 GNUNET_SCHEDULER_TaskCallback error_cb,
412 void *error_cb_cls);
413
414/**
415 * Begin rollback all actions in a transaction.
416 * Reverts all actions performed since #GNUNET_NAMESTORE_transaction_begin
417 *
418 * @param h handle to the namestore
419 * @param error_cb function to call on error (i.e. disconnect or unable to get lock)
420 * the handle is afterwards invalid
421 * @param error_cb_cls closure for @a error_cb
422 * @return handle to abort the request
423 */
424struct GNUNET_NAMESTORE_QueueEntry *
425GNUNET_NAMESTORE_transaction_abort (struct GNUNET_NAMESTORE_Handle *h,
426 GNUNET_SCHEDULER_TaskCallback error_cb,
427 void *error_cb_cls);
428/**
429 * Commit a namestore transaction.
430 * Saves all actions performed since #GNUNET_NAMESTORE_transaction_begin
431 *
432 * @param h handle to the namestore
433 * @param error_cb function to call on error (i.e. disconnect or unable to get lock)
434 * the handle is afterwards invalid
435 * @param error_cb_cls closure for @a error_cb
436 * @return handle to abort the request
437 */
438struct GNUNET_NAMESTORE_QueueEntry *
439GNUNET_NAMESTORE_transaction_commit (struct GNUNET_NAMESTORE_Handle *h,
440 GNUNET_SCHEDULER_TaskCallback error_cb,
441 void *error_cb_cls);
442
443/**
444 * Lookup an item in the namestore.
445 *
446 * @param h handle to the namestore
447 * @param pkey private key of the zone
448 * @param label name that is being mapped
449 * @param error_cb function to call on error (i.e. disconnect)
450 * the handle is afterwards invalid
451 * @param error_cb_cls closure for @a error_cb
452 * @param rm function to call with the result (with 0 records if we don't have that label);
453 * the handle is afterwards invalid
454 * @param rm_cls closure for @a rm
455 * @return handle to abort the request
456 */
457struct GNUNET_NAMESTORE_QueueEntry *
458GNUNET_NAMESTORE_records_select (struct GNUNET_NAMESTORE_Handle *h,
459 const struct
460 GNUNET_IDENTITY_PrivateKey *pkey,
461 const char *label,
462 GNUNET_SCHEDULER_TaskCallback error_cb,
463 void *error_cb_cls,
464 GNUNET_NAMESTORE_RecordMonitor rm,
465 void *rm_cls);
466
467
468/**
469 * Creates, deletes or updates an item in the namestore.
470 * If the item is already present, it is replaced with the new record set.
471 * Use an empty array to remove all records under the given name.
472 *
473 * The continuation is called after the value has been stored in the
474 * database. Monitors may be notified asynchronously (basically with
475 * a buffer). However, if any monitor is consistently too slow to
476 * keep up with the changes, calling @a cont will be delayed until the
477 * monitors do keep up.
478 *
479 * @param h handle to the namestore
480 * @param pkey private key of the zone
481 * @param label name that is being mapped
482 * @param rd_count number of records in the 'rd' array
483 * @param rd array of records with data to store
484 * @param cont continuation to call when done
485 * @param cont_cls closure for @a cont
486 * @return handle to abort the request
487 */
488struct GNUNET_NAMESTORE_QueueEntry *
489GNUNET_NAMESTORE_records_replace (struct GNUNET_NAMESTORE_Handle *h,
490 const struct GNUNET_IDENTITY_PrivateKey *pkey,
491 const char *label,
492 unsigned int rd_count,
493 const struct GNUNET_GNSRECORD_Data *rd,
494 GNUNET_NAMESTORE_ContinuationWithStatus cont,
495 void *cont_cls);
496
451#if 0 /* keep Emacsens' auto-indent happy */ 497#if 0 /* keep Emacsens' auto-indent happy */
452{ 498{
453#endif 499#endif
diff --git a/src/include/gnunet_time_lib.h b/src/include/gnunet_time_lib.h
index 96413c3cc..d59eb984d 100644
--- a/src/include/gnunet_time_lib.h
+++ b/src/include/gnunet_time_lib.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2001-2013 GNUnet e.V. 3 Copyright (C) 2001-2022 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -482,6 +482,18 @@ GNUNET_TIME_absolute_max (struct GNUNET_TIME_Absolute t1,
482 482
483 483
484/** 484/**
485 * Round down absolute time @a at to multiple of @a rt.
486 *
487 * @param at absolute time to round
488 * @param rt multiple to round to (non-zero)
489 * @return rounded time
490 */
491struct GNUNET_TIME_Absolute
492GNUNET_TIME_absolute_round_down (struct GNUNET_TIME_Absolute at,
493 struct GNUNET_TIME_Relative rt);
494
495
496/**
485 * Return the maximum of two timestamps. 497 * Return the maximum of two timestamps.
486 * 498 *
487 * @param t1 first timestamp 499 * @param t1 first timestamp
@@ -517,6 +529,21 @@ GNUNET_TIME_absolute_get_remaining (struct GNUNET_TIME_Absolute future);
517 529
518 530
519/** 531/**
532 * Test if @a a1 and @a a2 are equal within a margin of
533 * error of @a t.
534 *
535 * @param a1 time to compare
536 * @param a2 time to compare
537 * @param t tolerance to apply
538 * @return true if "|a1-a2|<=t" holds.
539 */
540bool
541GNUNET_TIME_absolute_approx_eq (struct GNUNET_TIME_Absolute a1,
542 struct GNUNET_TIME_Absolute a2,
543 struct GNUNET_TIME_Relative t);
544
545
546/**
520 * Calculate the estimate time of arrival/completion 547 * Calculate the estimate time of arrival/completion
521 * for an operation. 548 * for an operation.
522 * 549 *
diff --git a/src/messenger/plugin_gnsrecord_messenger.c b/src/messenger/plugin_gnsrecord_messenger.c
index 2219f0bde..e09a0330d 100644
--- a/src/messenger/plugin_gnsrecord_messenger.c
+++ b/src/messenger/plugin_gnsrecord_messenger.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2021 GNUnet e.V. 3 Copyright (C) 2021--2022 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -63,12 +63,30 @@ messenger_value_to_string (void *cls,
63 char *key = GNUNET_STRINGS_data_to_string_alloc (&(record->key), sizeof(struct GNUNET_HashCode)); 63 char *key = GNUNET_STRINGS_data_to_string_alloc (&(record->key), sizeof(struct GNUNET_HashCode));
64 64
65 char *ret; 65 char *ret;
66 GNUNET_asprintf (&ret, "%s-%s", door, key); 66 GNUNET_asprintf (&ret, "%s-%s", key, door);
67 GNUNET_free (key); 67 GNUNET_free (key);
68 GNUNET_free (door); 68 GNUNET_free (door);
69 return ret; 69 return ret;
70 } 70 }
71 case GNUNET_GNSRECORD_TYPE_MESSENGER_ROOM_DETAILS:
72 {
73 if (data_size != sizeof(struct GNUNET_MESSENGER_RoomDetailsRecord))
74 {
75 GNUNET_break_op (0);
76 return NULL;
77 }
78
79 const struct GNUNET_MESSENGER_RoomDetailsRecord *record = data;
71 80
81 char *name = GNUNET_strndup(record->name, 256);
82 char *flags = GNUNET_STRINGS_data_to_string_alloc (&(record->flags), sizeof(uint32_t));
83
84 char *ret;
85 GNUNET_asprintf (&ret, "%s-%s", flags, name);
86 GNUNET_free (flags);
87 GNUNET_free (name);
88 return ret;
89 }
72 default: 90 default:
73 return NULL; 91 return NULL;
74 } 92 }
@@ -141,7 +159,43 @@ messenger_string_to_value (void *cls,
141 *data_size = sizeof(struct GNUNET_MESSENGER_RoomEntryRecord); 159 *data_size = sizeof(struct GNUNET_MESSENGER_RoomEntryRecord);
142 return GNUNET_OK; 160 return GNUNET_OK;
143 } 161 }
162 case GNUNET_GNSRECORD_TYPE_MESSENGER_ROOM_DETAILS:
163 {
164 char flags [7];
165 const char *dash;
166
167 if ((NULL == (dash = strchr (s, '-'))) ||
168 (1 != sscanf (s, "%7s-", flags)) ||
169 (strlen (dash + 1) > 256))
170 {
171 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
172 _ ("Unable to parse MESSENGER_ROOM_DETAILS record `%s'\n"),
173 s);
174 return GNUNET_SYSERR;
175 }
176
177 struct GNUNET_MESSENGER_RoomDetailsRecord *record = GNUNET_new (
178 struct GNUNET_MESSENGER_RoomDetailsRecord
179 );
180
181 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (flags,
182 strlen (flags),
183 &(record->flags),
184 sizeof(uint32_t)))
185 {
186 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
187 _ ("Unable to parse MESSENGER_ROOM_DETAILS record `%s'\n"),
188 s);
189 GNUNET_free (record);
190 return GNUNET_SYSERR;
191 }
144 192
193 GNUNET_memcpy(record->name, dash + 1, strlen(dash + 1));
194
195 *data = record;
196 *data_size = sizeof(struct GNUNET_MESSENGER_RoomDetailsRecord);
197 return GNUNET_OK;
198 }
145 default: 199 default:
146 return GNUNET_SYSERR; 200 return GNUNET_SYSERR;
147 } 201 }
@@ -158,6 +212,7 @@ static struct
158 uint32_t number; 212 uint32_t number;
159} name_map[] = { 213} name_map[] = {
160 { "MESSENGER_ROOM_ENTRY", GNUNET_GNSRECORD_TYPE_MESSENGER_ROOM_ENTRY }, 214 { "MESSENGER_ROOM_ENTRY", GNUNET_GNSRECORD_TYPE_MESSENGER_ROOM_ENTRY },
215 { "MESSENGER_ROOM_DETAILS", GNUNET_GNSRECORD_TYPE_MESSENGER_ROOM_DETAILS },
161 { NULL, UINT32_MAX } 216 { NULL, UINT32_MAX }
162}; 217};
163 218
diff --git a/src/namestore/Makefile.am b/src/namestore/Makefile.am
index 2441b864a..51708dd67 100644
--- a/src/namestore/Makefile.am
+++ b/src/namestore/Makefile.am
@@ -39,7 +39,6 @@ if HAVE_SQLITE
39SQLITE_PLUGIN = libgnunet_plugin_namestore_sqlite.la 39SQLITE_PLUGIN = libgnunet_plugin_namestore_sqlite.la
40SQLITE_TESTS = test_plugin_namestore_sqlite \ 40SQLITE_TESTS = test_plugin_namestore_sqlite \
41 test_namestore_api_store_sqlite \ 41 test_namestore_api_store_sqlite \
42 test_namestore_api_store_locking_sqlite \
43 test_namestore_api_store_update_sqlite \ 42 test_namestore_api_store_update_sqlite \
44 test_namestore_api_zone_iteration_sqlite \ 43 test_namestore_api_zone_iteration_sqlite \
45 test_namestore_api_remove_sqlite \ 44 test_namestore_api_remove_sqlite \
@@ -250,16 +249,6 @@ test_namestore_api_store_sqlite_LDADD = \
250 $(top_builddir)/src/identity/libgnunetidentity.la \ 249 $(top_builddir)/src/identity/libgnunetidentity.la \
251 libgnunetnamestore.la 250 libgnunetnamestore.la
252 251
253test_namestore_api_store_locking_sqlite_SOURCES = \
254 test_namestore_api_store_locking.c
255test_namestore_api_store_locking_sqlite_LDADD = \
256 $(top_builddir)/src/testing/libgnunettesting.la \
257 $(top_builddir)/src/util/libgnunetutil.la \
258 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
259 $(top_builddir)/src/identity/libgnunetidentity.la \
260 libgnunetnamestore.la
261
262
263test_namestore_api_store_postgres_SOURCES = \ 252test_namestore_api_store_postgres_SOURCES = \
264 test_namestore_api_store.c 253 test_namestore_api_store.c
265test_namestore_api_store_postgres_LDADD = \ 254test_namestore_api_store_postgres_LDADD = \
diff --git a/src/namestore/gnunet-service-namestore.c b/src/namestore/gnunet-service-namestore.c
index d735822fb..95260ff9c 100644
--- a/src/namestore/gnunet-service-namestore.c
+++ b/src/namestore/gnunet-service-namestore.c
@@ -122,24 +122,6 @@ struct ZoneIteration
122}; 122};
123 123
124/** 124/**
125 * Lock on a record set
126 */
127struct RecordsLock
128{
129 /* DLL */
130 struct RecordsLock *prev;
131
132 /* DLL */
133 struct RecordsLock *next;
134
135 /* Hash of the locked label */
136 struct GNUNET_HashCode label_hash;
137
138 /* Client locking the zone */
139 struct NamestoreClient *client;
140};
141
142/**
143 * A namestore client 125 * A namestore client
144 */ 126 */
145struct NamestoreClient 127struct NamestoreClient
@@ -411,16 +393,6 @@ static struct StoreActivity *sa_head;
411static struct StoreActivity *sa_tail; 393static struct StoreActivity *sa_tail;
412 394
413/** 395/**
414 * Head of the DLL of record set locks
415 */
416static struct RecordsLock *locks_head;
417
418/**
419 * Tail of the DLL of record set locks
420 */
421static struct RecordsLock *locks_tail;
422
423/**
424 * Notification context shared by all monitors. 396 * Notification context shared by all monitors.
425 */ 397 */
426static struct GNUNET_NotificationContext *monitor_nc; 398static struct GNUNET_NotificationContext *monitor_nc;
@@ -447,7 +419,6 @@ static void
447cleanup_task (void *cls) 419cleanup_task (void *cls)
448{ 420{
449 struct CacheOperation *cop; 421 struct CacheOperation *cop;
450 struct RecordsLock *lock;
451 422
452 (void) cls; 423 (void) cls;
453 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n"); 424 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n");
@@ -459,13 +430,6 @@ cleanup_task (void *cls)
459 GNUNET_CONTAINER_DLL_remove (cop_head, cop_tail, cop); 430 GNUNET_CONTAINER_DLL_remove (cop_head, cop_tail, cop);
460 GNUNET_free (cop); 431 GNUNET_free (cop);
461 } 432 }
462 while (NULL != (lock = locks_head))
463 {
464 GNUNET_CONTAINER_DLL_remove (locks_head,
465 locks_tail,
466 lock);
467 GNUNET_free (lock);
468 }
469 433
470 if (NULL != namecache) 434 if (NULL != namecache)
471 { 435 {
@@ -1154,7 +1118,6 @@ client_disconnect_cb (void *cls,
1154 struct NamestoreClient *nc = app_ctx; 1118 struct NamestoreClient *nc = app_ctx;
1155 struct ZoneIteration *no; 1119 struct ZoneIteration *no;
1156 struct CacheOperation *cop; 1120 struct CacheOperation *cop;
1157 struct RecordsLock *lock;
1158 1121
1159 (void) cls; 1122 (void) cls;
1160 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client); 1123 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client);
@@ -1205,15 +1168,6 @@ client_disconnect_cb (void *cls,
1205 for (cop = cop_head; NULL != cop; cop = cop->next) 1168 for (cop = cop_head; NULL != cop; cop = cop->next)
1206 if (nc == cop->nc) 1169 if (nc == cop->nc)
1207 cop->nc = NULL; 1170 cop->nc = NULL;
1208 for (lock = locks_head; NULL != lock; lock = lock->next)
1209 {
1210 if (nc != lock->client)
1211 continue;
1212 GNUNET_CONTAINER_DLL_remove (locks_head,
1213 locks_tail,
1214 lock);
1215 GNUNET_free (lock);
1216 }
1217 GNUNET_free (nc); 1171 GNUNET_free (nc);
1218} 1172}
1219 1173
@@ -1407,105 +1361,6 @@ check_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1407 return GNUNET_OK; 1361 return GNUNET_OK;
1408} 1362}
1409 1363
1410static void
1411calculate_lock_hash (const char *label,
1412 const struct GNUNET_IDENTITY_PrivateKey *zone,
1413 struct GNUNET_HashCode *result)
1414{
1415 struct GNUNET_HashContext *hctx;
1416
1417 hctx = GNUNET_CRYPTO_hash_context_start ();
1418 GNUNET_CRYPTO_hash_context_read (hctx, label, strlen (label));
1419 GNUNET_CRYPTO_hash_context_read (hctx, zone,
1420 sizeof (*zone));
1421 GNUNET_CRYPTO_hash_context_finish (hctx, result);
1422}
1423
1424/**
1425 * Release a lock on a record set.
1426 * Does nothing if lock not held.
1427 *
1428 * @param label the label of the record set
1429 * @param zone the zone
1430 * @param nc the client releasing the lock
1431 */
1432static void
1433NST_label_lock_release (const char *label,
1434 const struct GNUNET_IDENTITY_PrivateKey *zone,
1435 const struct NamestoreClient *nc)
1436{
1437 struct GNUNET_HashCode label_hash;
1438 struct RecordsLock *lock;
1439
1440 calculate_lock_hash (label, zone, &label_hash);
1441 for (lock = locks_head; NULL != lock; lock = lock->next)
1442 if (0 == memcmp (&label_hash, &lock->label_hash, sizeof (label_hash)))
1443 break;
1444 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1445 "Record locked: %s\n", (NULL == lock) ? "No" : "Yes");
1446 if (NULL == lock)
1447 return;
1448 if (lock->client != nc)
1449 {
1450 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1451 "Lock is held by other client on `%s'\n", label);
1452 return;
1453 }
1454 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1455 "Unocking %s\n", GNUNET_h2s (&label_hash));
1456 GNUNET_CONTAINER_DLL_remove (locks_head,
1457 locks_tail,
1458 lock);
1459 GNUNET_free (lock);
1460}
1461
1462/**
1463 * Get/set a lock on a record set.
1464 * May be called multiple times but will
1465 * not aquire additional locks.
1466 *
1467 * @param the label of the record set
1468 * @param the zone
1469 * @param the client doing the locking
1470 * @return GNUNET_YES if lock retrieved or set already.
1471 */
1472static enum GNUNET_GenericReturnValue
1473NST_label_lock (const char *label,
1474 const struct GNUNET_IDENTITY_PrivateKey *zone,
1475 struct NamestoreClient *nc)
1476{
1477 struct GNUNET_HashCode label_hash;
1478 struct RecordsLock *lock;
1479
1480 calculate_lock_hash (label, zone, &label_hash);
1481 for (lock = locks_head; NULL != lock; lock = lock->next)
1482 if (0 == memcmp (&label_hash, &lock->label_hash, sizeof (label_hash)))
1483 break;
1484 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1485 "Record locked: %s\n", (NULL == lock) ? "No" : "Yes");
1486 if (NULL != lock)
1487 {
1488 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1489 "Client holds lock: %s\n", (lock->client != nc) ? "No" : "Yes");
1490 if (lock->client != nc)
1491 {
1492 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1493 "Lock is held by other client on `%s'\n", label);
1494 return GNUNET_NO;
1495 }
1496 return GNUNET_YES;
1497 }
1498 lock = GNUNET_new (struct RecordsLock);
1499 lock->client = nc;
1500 memcpy (&lock->label_hash, &label_hash, sizeof (label_hash));
1501 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1502 "Locking %s\n", GNUNET_h2s (&label_hash));
1503 GNUNET_CONTAINER_DLL_insert (locks_head,
1504 locks_tail,
1505 lock);
1506 return GNUNET_YES;
1507}
1508
1509 1364
1510/** 1365/**
1511 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message 1366 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message
@@ -1520,7 +1375,6 @@ handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1520 struct GNUNET_MQ_Envelope *env; 1375 struct GNUNET_MQ_Envelope *env;
1521 struct LabelLookupResponseMessage *llr_msg; 1376 struct LabelLookupResponseMessage *llr_msg;
1522 struct RecordLookupContext rlc; 1377 struct RecordLookupContext rlc;
1523 struct RecordsLock *lock;
1524 struct GNUNET_HashCode label_hash; 1378 struct GNUNET_HashCode label_hash;
1525 const char *name_tmp; 1379 const char *name_tmp;
1526 char *res_name; 1380 char *res_name;
@@ -1544,28 +1398,6 @@ handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1544 return; 1398 return;
1545 } 1399 }
1546 name_len = strlen (conv_name) + 1; 1400 name_len = strlen (conv_name) + 1;
1547 if (GNUNET_YES == ntohl (ll_msg->locking))
1548 {
1549 if (GNUNET_NO == NST_label_lock (conv_name, &ll_msg->zone, nc))
1550 {
1551 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1552 "Lock is held by other client on `%s'\n", conv_name);
1553 env =
1554 GNUNET_MQ_msg_extra (llr_msg,
1555 name_len,
1556 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE);
1557 llr_msg->gns_header.r_id = ll_msg->gns_header.r_id;
1558 llr_msg->private_key = ll_msg->zone;
1559 llr_msg->name_len = htons (name_len);
1560 llr_msg->rd_count = htons (0);
1561 llr_msg->rd_len = htons (0);
1562 llr_msg->found = htons (GNUNET_SYSERR);
1563 GNUNET_memcpy (&llr_msg[1], conv_name, name_len);
1564 GNUNET_MQ_send (nc->mq, env);
1565 GNUNET_free (conv_name);
1566 return;
1567 }
1568 }
1569 rlc.label = conv_name; 1401 rlc.label = conv_name;
1570 rlc.found = GNUNET_NO; 1402 rlc.found = GNUNET_NO;
1571 rlc.res_rd_count = 0; 1403 rlc.res_rd_count = 0;
@@ -1699,7 +1531,6 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1699 unsigned int rd_count; 1531 unsigned int rd_count;
1700 int res; 1532 int res;
1701 struct StoreActivity *sa; 1533 struct StoreActivity *sa;
1702 struct RecordsLock *lock;
1703 struct GNUNET_HashCode label_hash; 1534 struct GNUNET_HashCode label_hash;
1704 struct GNUNET_TIME_Absolute existing_block_exp; 1535 struct GNUNET_TIME_Absolute existing_block_exp;
1705 struct GNUNET_TIME_Absolute new_block_exp; 1536 struct GNUNET_TIME_Absolute new_block_exp;
@@ -1753,20 +1584,6 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1753 GNUNET_SERVICE_client_continue (nc->client); 1584 GNUNET_SERVICE_client_continue (nc->client);
1754 return; 1585 return;
1755 } 1586 }
1756 if (GNUNET_YES == ntohl (rp_msg->locking))
1757 {
1758 if (GNUNET_NO == NST_label_lock (conv_name, &rp_msg->private_key, nc))
1759 {
1760 send_store_response (nc, GNUNET_SYSERR, _ ("Record set locked."), rid);
1761 GNUNET_SERVICE_client_continue (nc->client);
1762 GNUNET_free (conv_name);
1763 return;
1764 }
1765 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1766 "Client has lock on `%s', continuing.\n", conv_name);
1767 if (GNUNET_YES == ntohl (rp_msg->locking))
1768 NST_label_lock_release (conv_name, &rp_msg->private_key, nc);
1769 }
1770 1587
1771 GNUNET_STATISTICS_update (statistics, 1588 GNUNET_STATISTICS_update (statistics,
1772 "Well-formed store requests received", 1589 "Well-formed store requests received",
diff --git a/src/namestore/namestore.h b/src/namestore/namestore.h
index 0f3ffa837..583ec1e68 100644
--- a/src/namestore/namestore.h
+++ b/src/namestore/namestore.h
@@ -68,11 +68,6 @@ struct RecordStoreMessage
68 struct GNUNET_TIME_AbsoluteNBO expire; 68 struct GNUNET_TIME_AbsoluteNBO expire;
69 69
70 /** 70 /**
71 * Unock the label with this request.
72 */
73 uint32_t locking GNUNET_PACKED;
74
75 /**
76 * Name length 71 * Name length
77 */ 72 */
78 uint16_t name_len GNUNET_PACKED; 73 uint16_t name_len GNUNET_PACKED;
@@ -151,11 +146,6 @@ struct LabelLookupMessage
151 uint32_t label_len GNUNET_PACKED; 146 uint32_t label_len GNUNET_PACKED;
152 147
153 /** 148 /**
154 * Lock the label with this lookup
155 */
156 uint32_t locking GNUNET_PACKED;
157
158 /**
159 * The private key of the zone to look up in 149 * The private key of the zone to look up in
160 */ 150 */
161 struct GNUNET_IDENTITY_PrivateKey zone; 151 struct GNUNET_IDENTITY_PrivateKey zone;
diff --git a/src/namestore/namestore_api.c b/src/namestore/namestore_api.c
index a7380bbde..73f985803 100644
--- a/src/namestore/namestore_api.c
+++ b/src/namestore/namestore_api.c
@@ -411,7 +411,7 @@ handle_record_store_response (void *cls,
411 return; 411 return;
412 if (NULL != qe->cont) 412 if (NULL != qe->cont)
413 qe->cont (qe->cont_cls, res, 413 qe->cont (qe->cont_cls, res,
414 (GNUNET_OK == res) ? NULL : emsg); 414 (GNUNET_OK == res) ? NULL : emsg);
415 free_qe (qe); 415 free_qe (qe);
416} 416}
417 417
@@ -482,7 +482,7 @@ handle_lookup_result (void *cls, const struct LabelLookupResponseMessage *msg)
482 int16_t found = (int16_t) ntohs (msg->found); 482 int16_t found = (int16_t) ntohs (msg->found);
483 483
484 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received RECORD_LOOKUP_RESULT (found=%i)\n", 484 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received RECORD_LOOKUP_RESULT (found=%i)\n",
485 found); 485 found);
486 qe = find_qe (h, ntohl (msg->gns_header.r_id)); 486 qe = find_qe (h, ntohl (msg->gns_header.r_id));
487 if (NULL == qe) 487 if (NULL == qe)
488 return; 488 return;
@@ -820,9 +820,9 @@ reconnect (struct GNUNET_NAMESTORE_Handle *h)
820{ 820{
821 struct GNUNET_MQ_MessageHandler handlers[] = 821 struct GNUNET_MQ_MessageHandler handlers[] =
822 { GNUNET_MQ_hd_var_size (record_store_response, 822 { GNUNET_MQ_hd_var_size (record_store_response,
823 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE, 823 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE,
824 struct RecordStoreResponseMessage, 824 struct RecordStoreResponseMessage,
825 h), 825 h),
826 GNUNET_MQ_hd_var_size (zone_to_name_response, 826 GNUNET_MQ_hd_var_size (zone_to_name_response,
827 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE, 827 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE,
828 struct ZoneToNameResponseMessage, 828 struct ZoneToNameResponseMessage,
@@ -1013,16 +1013,16 @@ warn_delay (void *cls)
1013 GNUNET_NAMESTORE_cancel (qe); 1013 GNUNET_NAMESTORE_cancel (qe);
1014} 1014}
1015 1015
1016
1016struct GNUNET_NAMESTORE_QueueEntry * 1017struct GNUNET_NAMESTORE_QueueEntry *
1017records_store_ ( 1018GNUNET_NAMESTORE_records_store (
1018 struct GNUNET_NAMESTORE_Handle *h, 1019 struct GNUNET_NAMESTORE_Handle *h,
1019 const struct GNUNET_IDENTITY_PrivateKey *pkey, 1020 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1020 const char *label, 1021 const char *label,
1021 unsigned int rd_count, 1022 unsigned int rd_count,
1022 const struct GNUNET_GNSRECORD_Data *rd, 1023 const struct GNUNET_GNSRECORD_Data *rd,
1023 GNUNET_NAMESTORE_ContinuationWithStatus cont, 1024 GNUNET_NAMESTORE_ContinuationWithStatus cont,
1024 void *cont_cls, 1025 void *cont_cls)
1025 int locking)
1026{ 1026{
1027 struct GNUNET_NAMESTORE_QueueEntry *qe; 1027 struct GNUNET_NAMESTORE_QueueEntry *qe;
1028 struct GNUNET_MQ_Envelope *env; 1028 struct GNUNET_MQ_Envelope *env;
@@ -1067,9 +1067,8 @@ records_store_ (
1067 msg->name_len = htons (name_len); 1067 msg->name_len = htons (name_len);
1068 msg->rd_count = htons (rd_count); 1068 msg->rd_count = htons (rd_count);
1069 msg->rd_len = htons (rd_ser_len); 1069 msg->rd_len = htons (rd_ser_len);
1070 msg->reserved = ntohs(0); 1070 msg->reserved = ntohs (0);
1071 msg->private_key = *pkey; 1071 msg->private_key = *pkey;
1072 msg->locking = htonl (locking);
1073 1072
1074 name_tmp = (char *) &msg[1]; 1073 name_tmp = (char *) &msg[1];
1075 GNUNET_memcpy (name_tmp, label, name_len); 1074 GNUNET_memcpy (name_tmp, label, name_len);
@@ -1101,22 +1100,11 @@ records_store_ (
1101 return qe; 1100 return qe;
1102} 1101}
1103 1102
1103/**
1104 * TODO: Experimental API will replace API above.
1105 */
1104struct GNUNET_NAMESTORE_QueueEntry * 1106struct GNUNET_NAMESTORE_QueueEntry *
1105GNUNET_NAMESTORE_records_store ( 1107GNUNET_NAMESTORE_records_replace (
1106 struct GNUNET_NAMESTORE_Handle *h,
1107 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1108 const char *label,
1109 unsigned int rd_count,
1110 const struct GNUNET_GNSRECORD_Data *rd,
1111 GNUNET_NAMESTORE_ContinuationWithStatus cont,
1112 void *cont_cls)
1113{
1114 return records_store_ (h, pkey, label,
1115 rd_count, rd, cont, cont_cls, GNUNET_NO);
1116}
1117
1118struct GNUNET_NAMESTORE_QueueEntry *
1119GNUNET_NAMESTORE_records_commit (
1120 struct GNUNET_NAMESTORE_Handle *h, 1108 struct GNUNET_NAMESTORE_Handle *h,
1121 const struct GNUNET_IDENTITY_PrivateKey *pkey, 1109 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1122 const char *label, 1110 const char *label,
@@ -1125,21 +1113,19 @@ GNUNET_NAMESTORE_records_commit (
1125 GNUNET_NAMESTORE_ContinuationWithStatus cont, 1113 GNUNET_NAMESTORE_ContinuationWithStatus cont,
1126 void *cont_cls) 1114 void *cont_cls)
1127{ 1115{
1128 return records_store_ (h, pkey, label, 1116 return GNUNET_NAMESTORE_records_store (h, pkey, label, rd_count, rd,
1129 rd_count, rd, cont, cont_cls, GNUNET_YES); 1117 cont, cont_cls);
1130} 1118}
1131 1119
1132
1133struct GNUNET_NAMESTORE_QueueEntry * 1120struct GNUNET_NAMESTORE_QueueEntry *
1134records_lookup_ ( 1121GNUNET_NAMESTORE_records_lookup (
1135 struct GNUNET_NAMESTORE_Handle *h, 1122 struct GNUNET_NAMESTORE_Handle *h,
1136 const struct GNUNET_IDENTITY_PrivateKey *pkey, 1123 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1137 const char *label, 1124 const char *label,
1138 GNUNET_SCHEDULER_TaskCallback error_cb, 1125 GNUNET_SCHEDULER_TaskCallback error_cb,
1139 void *error_cb_cls, 1126 void *error_cb_cls,
1140 GNUNET_NAMESTORE_RecordMonitor rm, 1127 GNUNET_NAMESTORE_RecordMonitor rm,
1141 void *rm_cls, 1128 void *rm_cls)
1142 int locking)
1143{ 1129{
1144 struct GNUNET_NAMESTORE_QueueEntry *qe; 1130 struct GNUNET_NAMESTORE_QueueEntry *qe;
1145 struct GNUNET_MQ_Envelope *env; 1131 struct GNUNET_MQ_Envelope *env;
@@ -1167,7 +1153,6 @@ records_lookup_ (
1167 msg->gns_header.r_id = htonl (qe->op_id); 1153 msg->gns_header.r_id = htonl (qe->op_id);
1168 msg->zone = *pkey; 1154 msg->zone = *pkey;
1169 msg->label_len = htonl (label_len); 1155 msg->label_len = htonl (label_len);
1170 msg->locking = htonl (locking);
1171 GNUNET_memcpy (&msg[1], label, label_len); 1156 GNUNET_memcpy (&msg[1], label, label_len);
1172 if (NULL == h->mq) 1157 if (NULL == h->mq)
1173 qe->env = env; 1158 qe->env = env;
@@ -1176,22 +1161,12 @@ records_lookup_ (
1176 return qe; 1161 return qe;
1177} 1162}
1178 1163
1179struct GNUNET_NAMESTORE_QueueEntry *
1180GNUNET_NAMESTORE_records_lookup (
1181 struct GNUNET_NAMESTORE_Handle *h,
1182 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1183 const char *label,
1184 GNUNET_SCHEDULER_TaskCallback error_cb,
1185 void *error_cb_cls,
1186 GNUNET_NAMESTORE_RecordMonitor rm,
1187 void *rm_cls)
1188{
1189 return records_lookup_ (h, pkey, label,
1190 error_cb, error_cb_cls, rm, rm_cls, GNUNET_NO);
1191}
1192 1164
1165/**
1166 * TODO experimental API. Will replace old API above.
1167 */
1193struct GNUNET_NAMESTORE_QueueEntry * 1168struct GNUNET_NAMESTORE_QueueEntry *
1194GNUNET_NAMESTORE_records_open ( 1169GNUNET_NAMESTORE_records_select (
1195 struct GNUNET_NAMESTORE_Handle *h, 1170 struct GNUNET_NAMESTORE_Handle *h,
1196 const struct GNUNET_IDENTITY_PrivateKey *pkey, 1171 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1197 const char *label, 1172 const char *label,
@@ -1200,8 +1175,9 @@ GNUNET_NAMESTORE_records_open (
1200 GNUNET_NAMESTORE_RecordMonitor rm, 1175 GNUNET_NAMESTORE_RecordMonitor rm,
1201 void *rm_cls) 1176 void *rm_cls)
1202{ 1177{
1203 return records_lookup_ (h, pkey, label, 1178 return GNUNET_NAMESTORE_records_lookup (h, pkey, label,
1204 error_cb, error_cb_cls, rm, rm_cls, GNUNET_YES); 1179 error_cb, error_cb_cls,
1180 rm, rm_cls);
1205} 1181}
1206 1182
1207struct GNUNET_NAMESTORE_QueueEntry * 1183struct GNUNET_NAMESTORE_QueueEntry *
@@ -1364,5 +1340,48 @@ GNUNET_NAMESTORE_cancel (struct GNUNET_NAMESTORE_QueueEntry *qe)
1364 free_qe (qe); 1340 free_qe (qe);
1365} 1341}
1366 1342
1343/**
1344 * New API draft. Experimental
1345 */
1346
1347struct GNUNET_NAMESTORE_QueueEntry *
1348GNUNET_NAMESTORE_transaction_begin (struct GNUNET_NAMESTORE_Handle *h,
1349 GNUNET_SCHEDULER_TaskCallback error_cb,
1350 void *error_cb_cls)
1351{
1352 GNUNET_break (0);
1353 return NULL;
1354}
1355
1356
1357struct GNUNET_NAMESTORE_QueueEntry *
1358GNUNET_NAMESTORE_transaction_abort (struct GNUNET_NAMESTORE_Handle *h,
1359 GNUNET_SCHEDULER_TaskCallback error_cb,
1360 void *error_cb_cls)
1361{
1362 GNUNET_break (0);
1363 return NULL;
1364}
1365
1366
1367/**
1368 * Commit a namestore transaction.
1369 * Saves all actions performed since #GNUNET_NAMESTORE_transaction_begin
1370 *
1371 * @param h handle to the namestore
1372 * @param error_cb function to call on error (i.e. disconnect or unable to get lock)
1373 * the handle is afterwards invalid
1374 * @param error_cb_cls closure for @a error_cb
1375 * @return handle to abort the request
1376 */
1377struct GNUNET_NAMESTORE_QueueEntry *
1378GNUNET_NAMESTORE_transaction_commit (struct GNUNET_NAMESTORE_Handle *h,
1379 GNUNET_SCHEDULER_TaskCallback error_cb,
1380 void *error_cb_cls)
1381{
1382 GNUNET_break (0);
1383 return NULL;
1384}
1385
1367 1386
1368/* end of namestore_api.c */ 1387/* end of namestore_api.c */
diff --git a/src/pq/pq_result_helper.c b/src/pq/pq_result_helper.c
index 2c11f5202..f3d246c36 100644
--- a/src/pq/pq_result_helper.c
+++ b/src/pq/pq_result_helper.c
@@ -1086,6 +1086,12 @@ extract_uint64 (void *cls,
1086 fnum)) 1086 fnum))
1087 { 1087 {
1088 GNUNET_break (0); 1088 GNUNET_break (0);
1089 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1090 "Got length %u for field `%s'\n",
1091 PQgetlength (result,
1092 row,
1093 fnum),
1094 fname);
1089 return GNUNET_SYSERR; 1095 return GNUNET_SYSERR;
1090 } 1096 }
1091 res = (uint64_t *) PQgetvalue (result, 1097 res = (uint64_t *) PQgetvalue (result,
diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am
index 69b05fb13..2b09ccf63 100644
--- a/src/transport/Makefile.am
+++ b/src/transport/Makefile.am
@@ -1528,6 +1528,7 @@ test_transport_simple_send_string.sh \
1528test_transport_simple_send.sh \ 1528test_transport_simple_send.sh \
1529test_transport_simple_send_broadcast.sh \ 1529test_transport_simple_send_broadcast.sh \
1530test_transport_udp_backchannel.sh \ 1530test_transport_udp_backchannel.sh \
1531test_transport_simple_send_dv_circle.sh \
1531gnunet-transport-certificate-creation.in \ 1532gnunet-transport-certificate-creation.in \
1532communicator-unix.conf \ 1533communicator-unix.conf \
1533test_plugin_hostkey \ 1534test_plugin_hostkey \
diff --git a/src/util/.gitignore b/src/util/.gitignore
index 51eab71db..0e3449fed 100644
--- a/src/util/.gitignore
+++ b/src/util/.gitignore
@@ -36,6 +36,7 @@ test_crypto_ecdh_eddsa
36test_crypto_ecdhe 36test_crypto_ecdhe
37test_crypto_ecdsa 37test_crypto_ecdsa
38test_crypto_eddsa 38test_crypto_eddsa
39test_crypto_edx25519
39test_crypto_hash 40test_crypto_hash
40test_crypto_hash_context 41test_crypto_hash_context
41test_crypto_hkdf 42test_crypto_hkdf
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 406d42b1e..9cb7da15b 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -66,6 +66,7 @@ libgnunetutil_la_SOURCES = \
66 crypto_ecc_gnsrecord.c \ 66 crypto_ecc_gnsrecord.c \
67 $(DLOG) \ 67 $(DLOG) \
68 crypto_ecc_setup.c \ 68 crypto_ecc_setup.c \
69 crypto_edx25519.c \
69 crypto_hash.c \ 70 crypto_hash.c \
70 crypto_hash_file.c \ 71 crypto_hash_file.c \
71 crypto_hkdf.c \ 72 crypto_hkdf.c \
@@ -297,6 +298,7 @@ check_PROGRAMS = \
297 test_crypto_ecdhe \ 298 test_crypto_ecdhe \
298 test_crypto_ecdh_eddsa \ 299 test_crypto_ecdh_eddsa \
299 test_crypto_ecdh_ecdsa \ 300 test_crypto_ecdh_ecdsa \
301 test_crypto_edx25519 \
300 $(DLOG_TEST) \ 302 $(DLOG_TEST) \
301 test_crypto_hash \ 303 test_crypto_hash \
302 test_crypto_hash_context \ 304 test_crypto_hash_context \
@@ -470,6 +472,12 @@ test_crypto_eddsa_LDADD = \
470 libgnunetutil.la \ 472 libgnunetutil.la \
471 $(LIBGCRYPT_LIBS) 473 $(LIBGCRYPT_LIBS)
472 474
475test_crypto_edx25519_SOURCES = \
476 test_crypto_edx25519.c
477test_crypto_edx25519_LDADD = \
478 libgnunetutil.la \
479 $(LIBGCRYPT_LIBS)
480
473test_crypto_ecc_dlog_SOURCES = \ 481test_crypto_ecc_dlog_SOURCES = \
474 test_crypto_ecc_dlog.c 482 test_crypto_ecc_dlog.c
475test_crypto_ecc_dlog_LDADD = \ 483test_crypto_ecc_dlog_LDADD = \
diff --git a/src/util/crypto_ecc_gnsrecord.c b/src/util/crypto_ecc_gnsrecord.c
index ce41a4699..0ee0570c0 100644
--- a/src/util/crypto_ecc_gnsrecord.c
+++ b/src/util/crypto_ecc_gnsrecord.c
@@ -68,28 +68,15 @@ derive_h (const void *pub,
68} 68}
69 69
70 70
71/** 71enum GNUNET_GenericReturnValue
72 * This is a signature function for EdDSA which takes the 72GNUNET_CRYPTO_eddsa_sign_derived (
73 * secret scalar sk instead of the private seed which is 73 const struct GNUNET_CRYPTO_EddsaPrivateKey *pkey,
74 * usually the case for crypto APIs. We require this functionality 74 const char *label,
75 * in order to use derived private keys for signatures we 75 const char *context,
76 * cannot calculate the inverse of a sk to find the seed
77 * efficiently.
78 *
79 * The resulting signature is a standard EdDSA signature
80 * which can be verified using the usual APIs.
81 *
82 * @param sk the secret scalar
83 * @param purp the signature purpose
84 * @param sig the resulting signature
85 */
86void
87GNUNET_CRYPTO_eddsa_sign_with_scalar (
88 const struct GNUNET_CRYPTO_EddsaPrivateScalar *priv,
89 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, 76 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
90 struct GNUNET_CRYPTO_EddsaSignature *sig) 77 struct GNUNET_CRYPTO_EddsaSignature *sig)
91{ 78{
92 79 struct GNUNET_CRYPTO_EddsaPrivateScalar priv;
93 crypto_hash_sha512_state hs; 80 crypto_hash_sha512_state hs;
94 unsigned char sk[64]; 81 unsigned char sk[64];
95 unsigned char r[64]; 82 unsigned char r[64];
@@ -98,6 +85,14 @@ GNUNET_CRYPTO_eddsa_sign_with_scalar (
98 unsigned char zk[32]; 85 unsigned char zk[32];
99 unsigned char tmp[32]; 86 unsigned char tmp[32];
100 87
88 /**
89 * Derive the private key
90 */
91 GNUNET_CRYPTO_eddsa_private_key_derive (pkey,
92 label,
93 context,
94 &priv);
95
101 crypto_hash_sha512_init (&hs); 96 crypto_hash_sha512_init (&hs);
102 97
103 /** 98 /**
@@ -108,7 +103,7 @@ GNUNET_CRYPTO_eddsa_sign_with_scalar (
108 * sk[0..31] = h * SHA512 (d)[0..31] 103 * sk[0..31] = h * SHA512 (d)[0..31]
109 * sk[32..63] = SHA512 (d)[32..63] 104 * sk[32..63] = SHA512 (d)[32..63]
110 */ 105 */
111 memcpy (sk, priv->s, 64); 106 memcpy (sk, priv.s, 64);
112 107
113 /** 108 /**
114 * Calculate the derived zone key zk' from the 109 * Calculate the derived zone key zk' from the
@@ -172,8 +167,28 @@ GNUNET_CRYPTO_eddsa_sign_with_scalar (
172 sodium_memzero (sk, sizeof (sk)); 167 sodium_memzero (sk, sizeof (sk));
173 sodium_memzero (r, sizeof (r)); 168 sodium_memzero (r, sizeof (r));
174 sodium_memzero (r_mod, sizeof (r_mod)); 169 sodium_memzero (r_mod, sizeof (r_mod));
170 return GNUNET_OK;
175} 171}
176 172
173enum GNUNET_GenericReturnValue
174GNUNET_CRYPTO_ecdsa_sign_derived (
175 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
176 const char *label,
177 const char *context,
178 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
179 struct GNUNET_CRYPTO_EcdsaSignature *sig)
180{
181 struct GNUNET_CRYPTO_EcdsaPrivateKey *key;
182 enum GNUNET_GenericReturnValue res;
183 key = GNUNET_CRYPTO_ecdsa_private_key_derive (priv,
184 label,
185 context);
186 res = GNUNET_CRYPTO_ecdsa_sign_ (key,
187 purpose,
188 sig);
189 GNUNET_free (key);
190 return res;
191}
177 192
178struct GNUNET_CRYPTO_EcdsaPrivateKey * 193struct GNUNET_CRYPTO_EcdsaPrivateKey *
179GNUNET_CRYPTO_ecdsa_private_key_derive ( 194GNUNET_CRYPTO_ecdsa_private_key_derive (
diff --git a/src/util/crypto_edx25519.c b/src/util/crypto_edx25519.c
new file mode 100644
index 000000000..26b45407e
--- /dev/null
+++ b/src/util/crypto_edx25519.c
@@ -0,0 +1,418 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2022 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 util/crypto_edx25519.c
23 * @brief An variant of EdDSA which allows for iterative derivation of key pairs.
24 * @author Özgür Kesim
25 * @author Christian Grothoff
26 * @author Florian Dold
27 * @author Martin Schanzenbach
28 */
29#include "platform.h"
30#include <gcrypt.h>
31#include <sodium.h>
32#include "gnunet_crypto_lib.h"
33#include "gnunet_strings_lib.h"
34
35#define CURVE "Ed25519"
36
37void
38GNUNET_CRYPTO_edx25519_key_clear (struct GNUNET_CRYPTO_Edx25519PrivateKey *pk)
39{
40 memset (pk, 0, sizeof(struct GNUNET_CRYPTO_Edx25519PrivateKey));
41}
42
43
44void
45GNUNET_CRYPTO_edx25519_key_create_from_seed (
46 const void *seed,
47 size_t seedsize,
48 struct GNUNET_CRYPTO_Edx25519PrivateKey *pk)
49{
50
51 GNUNET_static_assert (sizeof(*pk) == sizeof(struct GNUNET_HashCode));
52 GNUNET_CRYPTO_hash (seed,
53 seedsize,
54 (struct GNUNET_HashCode *) pk);
55
56 /* Clamp the first half of the key. The second half is used in the signature
57 * process. */
58 pk->a[0] &= 248;
59 pk->a[31] &= 127;
60 pk->a[31] |= 64;
61}
62
63
64void
65GNUNET_CRYPTO_edx25519_key_create (
66 struct GNUNET_CRYPTO_Edx25519PrivateKey *pk)
67{
68 char seed[256 / 8];
69 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
70 seed,
71 sizeof (seed));
72 GNUNET_CRYPTO_edx25519_key_create_from_seed (seed,
73 sizeof(seed),
74 pk);
75}
76
77
78void
79GNUNET_CRYPTO_edx25519_key_get_public (
80 const struct GNUNET_CRYPTO_Edx25519PrivateKey *priv,
81 struct GNUNET_CRYPTO_Edx25519PublicKey *pub)
82{
83 crypto_scalarmult_ed25519_base_noclamp (pub->q_y,
84 priv->a);
85}
86
87
88/**
89 * This function operates the basically same way as the signature function for
90 * EdDSA. But instead of expanding a private seed (which is usually the case
91 * for crypto APIs) and using the resulting scalars, it takes the scalars
92 * directly from Edx25519PrivateKey. We require this functionality in order to
93 * use derived private keys for signatures.
94 *
95 * The resulting signature is a standard EdDSA signature
96 * which can be verified using the usual APIs.
97 *
98 * @param priv the private key (containing two scalars .a and .b)
99 * @param purp the signature purpose
100 * @param sig the resulting signature
101 */
102enum GNUNET_GenericReturnValue
103GNUNET_CRYPTO_edx25519_sign_ (
104 const struct GNUNET_CRYPTO_Edx25519PrivateKey *priv,
105 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
106 struct GNUNET_CRYPTO_Edx25519Signature *sig)
107{
108
109 crypto_hash_sha512_state hs;
110 unsigned char r[64];
111 unsigned char hram[64];
112 unsigned char P[32];
113 unsigned char r_mod[64];
114 unsigned char R[32];
115 unsigned char tmp[32];
116
117 crypto_hash_sha512_init (&hs);
118
119 /**
120 * Calculate the public key P from the private scalar in the key.
121 */
122 crypto_scalarmult_ed25519_base_noclamp (P,
123 priv->a);
124
125 /**
126 * Calculate r:
127 * r = SHA512 (b ∥ M)
128 * where M is our message (purpose).
129 */
130 crypto_hash_sha512_update (&hs,
131 priv->b,
132 sizeof(priv->b));
133 crypto_hash_sha512_update (&hs,
134 (uint8_t*) purpose,
135 ntohl (purpose->size));
136 crypto_hash_sha512_final (&hs,
137 r);
138
139 /**
140 * Temporarily put P into S
141 */
142 memcpy (sig->s, P, 32);
143
144 /**
145 * Reduce the scalar value r
146 */
147 crypto_core_ed25519_scalar_reduce (r_mod, r);
148
149 /**
150 * Calculate R := r * G of the signature
151 */
152 crypto_scalarmult_ed25519_base_noclamp (R, r_mod);
153 memcpy (sig->r, R, sizeof (R));
154
155 /**
156 * Calculate
157 * hram := SHA512 (R ∥ P ∥ M)
158 */
159 crypto_hash_sha512_init (&hs);
160 crypto_hash_sha512_update (&hs, (uint8_t*) sig, 64);
161 crypto_hash_sha512_update (&hs, (uint8_t*) purpose,
162 ntohl (purpose->size));
163 crypto_hash_sha512_final (&hs, hram);
164
165 /**
166 * Reduce the resulting scalar value
167 */
168 unsigned char hram_mod[64];
169 crypto_core_ed25519_scalar_reduce (hram_mod, hram);
170
171 /**
172 * Calculate
173 * S := r + hram * s mod L
174 */
175 crypto_core_ed25519_scalar_mul (tmp, hram_mod, priv->a);
176 crypto_core_ed25519_scalar_add (sig->s, tmp, r_mod);
177
178 sodium_memzero (r, sizeof (r));
179 sodium_memzero (r_mod, sizeof (r_mod));
180
181 return GNUNET_OK;
182}
183
184
185enum GNUNET_GenericReturnValue
186GNUNET_CRYPTO_edx25519_verify_ (
187 uint32_t purpose,
188 const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
189 const struct GNUNET_CRYPTO_Edx25519Signature *sig,
190 const struct GNUNET_CRYPTO_Edx25519PublicKey *pub)
191{
192 const unsigned char *m = (const void *) validate;
193 size_t mlen = ntohl (validate->size);
194 const unsigned char *s = (const void *) sig;
195
196 int res;
197
198 if (purpose != ntohl (validate->purpose))
199 return GNUNET_SYSERR; /* purpose mismatch */
200
201 res = crypto_sign_verify_detached (s, m, mlen, pub->q_y);
202 return (res == 0) ? GNUNET_OK : GNUNET_SYSERR;
203}
204
205
206/**
207 * Derive the 'h' value for key derivation, where
208 * 'h = H(P ∥ seed) mod n' and 'n' is the size of the cyclic subroup.
209 *
210 * @param pub public key for deriviation
211 * @param seed seed for key the deriviation
212 * @param seedsize the size of the seed
213 * @param n The value for the modulus 'n'
214 * @param[out] phc if not NULL, the output of H() will be written into
215 * return h_mod_n (allocated by this function)
216 */
217static gcry_mpi_t
218derive_h_mod_n (
219 const struct GNUNET_CRYPTO_Edx25519PublicKey *pub,
220 const void *seed,
221 size_t seedsize,
222 const gcry_mpi_t n,
223 struct GNUNET_HashCode *phc)
224{
225 static const char *const salt = "edx2559-derivation";
226 struct GNUNET_HashCode hc;
227 gcry_mpi_t h;
228 gcry_mpi_t h_mod_n;
229
230 if (NULL == phc)
231 phc = &hc;
232
233 GNUNET_CRYPTO_kdf (phc, sizeof(*phc),
234 salt, strlen (salt),
235 pub, sizeof(*pub),
236 seed, seedsize,
237 NULL, 0);
238
239 /* calculate h_mod_n = h % n */
240 GNUNET_CRYPTO_mpi_scan_unsigned (&h,
241 (unsigned char *) phc,
242 sizeof(*phc));
243 h_mod_n = gcry_mpi_new (256);
244 gcry_mpi_mod (h_mod_n, h, n);
245
246#ifdef CHECK_RARE_CASES
247 /**
248 * Note that the following cases would be problematic:
249 * 1.) h == 0 mod n
250 * 2.) h == 1 mod n
251 * 3.) [h] * P == E
252 * We assume that the probalities for these cases to occur are neglegible.
253 */
254 GNUNET_assert (! gcry_mpi_cmp_ui (h_mod_n, 0));
255 GNUNET_assert (! gcry_mpi_cmp_ui (h_mod_n, 1));
256#endif
257
258 gcry_mpi_release(h);
259 return h_mod_n;
260}
261
262
263void
264GNUNET_CRYPTO_edx25519_private_key_derive (
265 const struct GNUNET_CRYPTO_Edx25519PrivateKey *priv,
266 const void *seed,
267 size_t seedsize,
268 struct GNUNET_CRYPTO_Edx25519PrivateKey *result)
269{
270 struct GNUNET_CRYPTO_Edx25519PublicKey pub;
271 struct GNUNET_HashCode hc;
272 uint8_t a[32];
273 gcry_ctx_t ctx;
274 gcry_mpi_t h_mod_n;
275 gcry_mpi_t x;
276 gcry_mpi_t n;
277 gcry_mpi_t a1;
278 gcry_mpi_t a2;
279 gcry_mpi_t ap; // a'
280
281 GNUNET_CRYPTO_edx25519_key_get_public (priv, &pub);
282
283 /**
284 * Libsodium does not offer an API with arbitrary arithmetic.
285 * Hence we have to use libgcrypt here.
286 */
287 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, "Ed25519"));
288
289 /**
290 * Get our modulo
291 */
292 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
293 GNUNET_assert (NULL != n);
294
295 /**
296 * Get h mod n
297 */
298 h_mod_n = derive_h_mod_n (&pub,
299 seed,
300 seedsize,
301 n,
302 &hc);
303
304 /* Convert priv->a scalar to big endian for libgcrypt */
305 for (size_t i = 0; i < 32; i++)
306 a[i] = priv->a[31 - i];
307
308 /**
309 * dc now contains the private scalar "a".
310 * We carefully remove the clamping and derive a'.
311 * Calculate:
312 * a1 := a / 8
313 * a2 := h * a1 mod n
314 * a' := a2 * 8 mod n
315 */
316 GNUNET_CRYPTO_mpi_scan_unsigned (&x, a, sizeof(a)); // a
317 a1 = gcry_mpi_new (256);
318 gcry_mpi_t eight = gcry_mpi_set_ui (NULL, 8);
319 gcry_mpi_div (a1, NULL, x, eight, 0); // a1 := a / 8
320 a2 = gcry_mpi_new (256);
321 gcry_mpi_mulm (a2, h_mod_n, a1, n); // a2 := h * a1 mod n
322 ap = gcry_mpi_new (256);
323 gcry_mpi_mul (ap, a2, eight); // a' := a2 * 8
324
325#ifdef CHECK_RARE_CASES
326 /* The likelihood for a' == 0 or a' == 1 is neglegible */
327 GNUNET_assert (! gcry_mpi_cmp_ui (ap, 0));
328 GNUNET_assert (! gcry_mpi_cmp_ui (ap, 1));
329#endif
330
331 gcry_mpi_release (h_mod_n);
332 gcry_mpi_release (eight);
333 gcry_mpi_release (x);
334 gcry_mpi_release (n);
335 gcry_mpi_release (a1);
336 gcry_mpi_release (a2);
337 gcry_ctx_release (ctx);
338 GNUNET_CRYPTO_mpi_print_unsigned (a, sizeof(a), ap);
339 gcry_mpi_release (ap);
340
341 /**
342 * We hash the derived "h" parameter with the other half of the expanded
343 * private key (that is: priv->b). This ensures that for signature
344 * generation, the "R" is derived from the same derivation path as "h" and is
345 * not reused.
346 */
347 {
348 crypto_hash_sha256_state hs;
349 crypto_hash_sha256_init (&hs);
350 crypto_hash_sha256_update (&hs, priv->b, sizeof(priv->b));
351 crypto_hash_sha256_update (&hs, (unsigned char*) &hc, sizeof (hc));
352 crypto_hash_sha256_final (&hs, result->b);
353 }
354
355 /* Convert to little endian for libsodium */
356 for (size_t i = 0; i < 32; i++)
357 result->a[i] = a[31 - i];
358
359 sodium_memzero (a, sizeof(a));
360}
361
362
363void
364GNUNET_CRYPTO_edx25519_public_key_derive (
365 const struct GNUNET_CRYPTO_Edx25519PublicKey *pub,
366 const void *seed,
367 size_t seedsize,
368 struct GNUNET_CRYPTO_Edx25519PublicKey *result)
369{
370 gcry_ctx_t ctx;
371 gcry_mpi_t q_y;
372 gcry_mpi_t n;
373 gcry_mpi_t h_mod_n;
374 gcry_mpi_point_t q;
375 gcry_mpi_point_t v;
376
377 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, "Ed25519"));
378
379 /* obtain point 'q' from original public key. The provided 'q' is
380 compressed thus we first store it in the context and then get it
381 back as a (decompresssed) point. */
382 q_y = gcry_mpi_set_opaque_copy (NULL,
383 pub->q_y,
384 8 * sizeof(pub->q_y));
385 GNUNET_assert (NULL != q_y);
386 GNUNET_assert (0 == gcry_mpi_ec_set_mpi ("q", q_y, ctx));
387 gcry_mpi_release (q_y);
388 q = gcry_mpi_ec_get_point ("q", ctx, 0);
389 GNUNET_assert (q);
390
391 /**
392 * Get h mod n
393 */
394 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
395 GNUNET_assert (NULL != n);
396 GNUNET_assert (NULL != pub);
397 h_mod_n = derive_h_mod_n (pub,
398 seed,
399 seedsize,
400 n,
401 NULL /* We don't need hc here */);
402
403 /* calculate v = h_mod_n * q */
404 v = gcry_mpi_point_new (0);
405 gcry_mpi_ec_mul (v, h_mod_n, q, ctx);
406 gcry_mpi_release (h_mod_n);
407 gcry_mpi_release (n);
408 gcry_mpi_point_release (q);
409
410 /* convert point 'v' to public key that we return */
411 GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", v, ctx));
412 gcry_mpi_point_release (v);
413 q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
414 GNUNET_assert (q_y);
415 GNUNET_CRYPTO_mpi_print_unsigned (result->q_y, sizeof(result->q_y), q_y);
416 gcry_mpi_release (q_y);
417 gcry_ctx_release (ctx);
418}
diff --git a/src/util/crypto_hkdf.c b/src/util/crypto_hkdf.c
index 4e4496819..838e37d8d 100644
--- a/src/util/crypto_hkdf.c
+++ b/src/util/crypto_hkdf.c
@@ -74,16 +74,21 @@
74 * @return HMAC, freed by caller via gcry_md_close/_reset 74 * @return HMAC, freed by caller via gcry_md_close/_reset
75 */ 75 */
76static const void * 76static const void *
77doHMAC (gcry_md_hd_t mac, const void *key, size_t key_len, const void *buf, 77doHMAC (gcry_md_hd_t mac,
78 const void *key,
79 size_t key_len,
80 const void *buf,
78 size_t buf_len) 81 size_t buf_len)
79{ 82{
80 if (GPG_ERR_NO_ERROR != gcry_md_setkey (mac, key, key_len)) 83 if (GPG_ERR_NO_ERROR !=
84 gcry_md_setkey (mac, key, key_len))
81 { 85 {
82 GNUNET_break (0); 86 GNUNET_break (0);
83 return NULL; 87 return NULL;
84 } 88 }
85 gcry_md_write (mac, buf, buf_len); 89 gcry_md_write (mac,
86 90 buf,
91 buf_len);
87 return (const void *) gcry_md_read (mac, 0); 92 return (const void *) gcry_md_read (mac, 0);
88} 93}
89 94
@@ -98,9 +103,13 @@ doHMAC (gcry_md_hd_t mac, const void *key, size_t key_len, const void *buf,
98 * @param prk result buffer (allocated by caller; at least gcry_md_dlen() bytes) 103 * @param prk result buffer (allocated by caller; at least gcry_md_dlen() bytes)
99 * @return #GNUNET_YES on success 104 * @return #GNUNET_YES on success
100 */ 105 */
101static int 106static enum GNUNET_GenericReturnValue
102getPRK (gcry_md_hd_t mac, const void *xts, size_t xts_len, const void *skm, 107getPRK (gcry_md_hd_t mac,
103 size_t skm_len, void *prk) 108 const void *xts,
109 size_t xts_len,
110 const void *skm,
111 size_t skm_len,
112 void *prk)
104{ 113{
105 const void *ret; 114 const void *ret;
106 size_t dlen; 115 size_t dlen;
@@ -114,9 +123,10 @@ getPRK (gcry_md_hd_t mac, const void *xts, size_t xts_len, const void *skm,
114 * salt - optional salt value (a non-secret random value); 123 * salt - optional salt value (a non-secret random value);
115 * if not provided, it is set to a string of HashLen zeros. */ 124 * if not provided, it is set to a string of HashLen zeros. */
116 125
117 if (xts_len == 0) 126 if (0 == xts_len)
118 { 127 {
119 char zero_salt[dlen]; 128 char zero_salt[dlen];
129
120 memset (zero_salt, 0, dlen); 130 memset (zero_salt, 0, dlen);
121 ret = doHMAC (mac, zero_salt, dlen, skm, skm_len); 131 ret = doHMAC (mac, zero_salt, dlen, skm, skm_len);
122 } 132 }
@@ -124,22 +134,23 @@ getPRK (gcry_md_hd_t mac, const void *xts, size_t xts_len, const void *skm,
124 { 134 {
125 ret = doHMAC (mac, xts, xts_len, skm, skm_len); 135 ret = doHMAC (mac, xts, xts_len, skm, skm_len);
126 } 136 }
127 if (ret == NULL) 137 if (NULL == ret)
128 return GNUNET_SYSERR; 138 return GNUNET_SYSERR;
129 GNUNET_memcpy (prk, ret, dlen); 139 GNUNET_memcpy (prk,
130 140 ret,
141 dlen);
131 return GNUNET_YES; 142 return GNUNET_YES;
132} 143}
133 144
134 145
135#if DEBUG_HKDF 146#if DEBUG_HKDF
136static void 147static void
137dump (const char *src, const void *p, unsigned int l) 148dump (const char *src,
149 const void *p,
150 unsigned int l)
138{ 151{
139 unsigned int i;
140
141 printf ("\n%s: ", src); 152 printf ("\n%s: ", src);
142 for (i = 0; i < l; i++) 153 for (unsigned int i = 0; i < l; i++)
143 { 154 {
144 printf ("%2x", (int) ((const unsigned char *) p)[i]); 155 printf ("%2x", (int) ((const unsigned char *) p)[i]);
145 } 156 }
@@ -150,23 +161,16 @@ dump (const char *src, const void *p, unsigned int l)
150#endif 161#endif
151 162
152 163
153/** 164enum GNUNET_GenericReturnValue
154 * @brief Derive key 165GNUNET_CRYPTO_hkdf_v (void *result,
155 * @param result buffer for the derived key, allocated by caller 166 size_t out_len,
156 * @param out_len desired length of the derived key 167 int xtr_algo,
157 * @param xtr_algo hash algorithm for the extraction phase, GCRY_MD_... 168 int prf_algo,
158 * @param prf_algo hash algorithm for the expansion phase, GCRY_MD_... 169 const void *xts,
159 * @param xts salt 170 size_t xts_len,
160 * @param xts_len length of @a xts 171 const void *skm,
161 * @param skm source key material 172 size_t skm_len,
162 * @param skm_len length of @a skm 173 va_list argp)
163 * @param argp va_list of void * & size_t pairs for context chunks
164 * @return #GNUNET_YES on success
165 */
166int
167GNUNET_CRYPTO_hkdf_v (void *result, size_t out_len, int xtr_algo, int prf_algo,
168 const void *xts, size_t xts_len, const void *skm,
169 size_t skm_len, va_list argp)
170{ 174{
171 gcry_md_hd_t xtr; 175 gcry_md_hd_t xtr;
172 gcry_md_hd_t prf; 176 gcry_md_hd_t prf;
@@ -186,10 +190,14 @@ GNUNET_CRYPTO_hkdf_v (void *result, size_t out_len, int xtr_algo, int prf_algo,
186 if (0 == k) 190 if (0 == k)
187 return GNUNET_SYSERR; 191 return GNUNET_SYSERR;
188 if (GPG_ERR_NO_ERROR != 192 if (GPG_ERR_NO_ERROR !=
189 gcry_md_open (&xtr, xtr_algo, GCRY_MD_FLAG_HMAC)) 193 gcry_md_open (&xtr,
194 xtr_algo,
195 GCRY_MD_FLAG_HMAC))
190 return GNUNET_SYSERR; 196 return GNUNET_SYSERR;
191 if (GPG_ERR_NO_ERROR != 197 if (GPG_ERR_NO_ERROR !=
192 gcry_md_open (&prf, prf_algo, GCRY_MD_FLAG_HMAC)) 198 gcry_md_open (&prf,
199 prf_algo,
200 GCRY_MD_FLAG_HMAC))
193 { 201 {
194 gcry_md_close (xtr); 202 gcry_md_close (xtr);
195 return GNUNET_SYSERR; 203 return GNUNET_SYSERR;
@@ -221,7 +229,8 @@ GNUNET_CRYPTO_hkdf_v (void *result, size_t out_len, int xtr_algo, int prf_algo,
221 } 229 }
222 230
223 memset (result, 0, out_len); 231 memset (result, 0, out_len);
224 if (getPRK (xtr, xts, xts_len, skm, skm_len, prk) != GNUNET_YES) 232 if (GNUNET_YES !=
233 getPRK (xtr, xts, xts_len, skm, skm_len, prk))
225 goto hkdf_error; 234 goto hkdf_error;
226#if DEBUG_HKDF 235#if DEBUG_HKDF
227 dump ("PRK", prk, xtr_len); 236 dump ("PRK", prk, xtr_len);
@@ -276,7 +285,7 @@ GNUNET_CRYPTO_hkdf_v (void *result, size_t out_len, int xtr_algo, int prf_algo,
276 dump ("K(i+1)", plain, plain_len); 285 dump ("K(i+1)", plain, plain_len);
277#endif 286#endif
278 hc = doHMAC (prf, prk, xtr_len, plain, plain_len); 287 hc = doHMAC (prf, prk, xtr_len, plain, plain_len);
279 if (hc == NULL) 288 if (NULL == hc)
280 { 289 {
281 GNUNET_free (plain); 290 GNUNET_free (plain);
282 goto hkdf_error; 291 goto hkdf_error;
@@ -327,32 +336,31 @@ hkdf_ok:
327} 336}
328 337
329 338
330/** 339enum GNUNET_GenericReturnValue
331 * @brief Derive key 340GNUNET_CRYPTO_hkdf (void *result,
332 * @param result buffer for the derived key, allocated by caller 341 size_t out_len,
333 * @param out_len desired length of the derived key 342 int xtr_algo,
334 * @param xtr_algo hash algorithm for the extraction phase, GCRY_MD_... 343 int prf_algo,
335 * @param prf_algo hash algorithm for the expansion phase, GCRY_MD_... 344 const void *xts,
336 * @param xts salt 345 size_t xts_len,
337 * @param xts_len length of @a xts 346 const void *skm,
338 * @param skm source key material
339 * @param skm_len length of @a skm
340 * @return #GNUNET_YES on success
341 */
342int
343GNUNET_CRYPTO_hkdf (void *result, size_t out_len, int xtr_algo, int prf_algo,
344 const void *xts, size_t xts_len, const void *skm,
345 size_t skm_len, ...) 347 size_t skm_len, ...)
346{ 348{
347 va_list argp; 349 va_list argp;
348 int ret; 350 enum GNUNET_GenericReturnValue ret;
349 351
350 va_start (argp, skm_len); 352 va_start (argp, skm_len);
351 ret = 353 ret =
352 GNUNET_CRYPTO_hkdf_v (result, out_len, xtr_algo, prf_algo, xts, xts_len, 354 GNUNET_CRYPTO_hkdf_v (result,
353 skm, skm_len, argp); 355 out_len,
356 xtr_algo,
357 prf_algo,
358 xts,
359 xts_len,
360 skm,
361 skm_len,
362 argp);
354 va_end (argp); 363 va_end (argp);
355
356 return ret; 364 return ret;
357} 365}
358 366
diff --git a/src/util/crypto_kdf.c b/src/util/crypto_kdf.c
index 0dc734549..f577e0f7a 100644
--- a/src/util/crypto_kdf.c
+++ b/src/util/crypto_kdf.c
@@ -32,18 +32,8 @@
32 32
33#define LOG(kind, ...) GNUNET_log_from (kind, "util-crypto-kdf", __VA_ARGS__) 33#define LOG(kind, ...) GNUNET_log_from (kind, "util-crypto-kdf", __VA_ARGS__)
34 34
35/** 35
36 * @brief Derive key 36enum GNUNET_GenericReturnValue
37 * @param result buffer for the derived key, allocated by caller
38 * @param out_len desired length of the derived key
39 * @param xts salt
40 * @param xts_len length of @a xts
41 * @param skm source key material
42 * @param skm_len length of @a skm
43 * @param argp va_list of void * & size_t pairs for context chunks
44 * @return #GNUNET_YES on success
45 */
46int
47GNUNET_CRYPTO_kdf_v (void *result, 37GNUNET_CRYPTO_kdf_v (void *result,
48 size_t out_len, 38 size_t out_len,
49 const void *xts, 39 const void *xts,
@@ -62,7 +52,7 @@ GNUNET_CRYPTO_kdf_v (void *result,
62 * hash function." 52 * hash function."
63 * 53 *
64 * http://eprint.iacr.org/2010/264 54 * http://eprint.iacr.org/2010/264
65 */// 55 */
66 return GNUNET_CRYPTO_hkdf_v (result, 56 return GNUNET_CRYPTO_hkdf_v (result,
67 out_len, 57 out_len,
68 GCRY_MD_SHA512, 58 GCRY_MD_SHA512,
@@ -75,18 +65,7 @@ GNUNET_CRYPTO_kdf_v (void *result,
75} 65}
76 66
77 67
78/** 68enum GNUNET_GenericReturnValue
79 * @brief Derive key
80 * @param result buffer for the derived key, allocated by caller
81 * @param out_len desired length of the derived key
82 * @param xts salt
83 * @param xts_len length of @a xts
84 * @param skm source key material
85 * @param skm_len length of @a skm
86 * @param ... void * & size_t pairs for context chunks
87 * @return #GNUNET_YES on success
88 */
89int
90GNUNET_CRYPTO_kdf (void *result, 69GNUNET_CRYPTO_kdf (void *result,
91 size_t out_len, 70 size_t out_len,
92 const void *xts, 71 const void *xts,
@@ -111,18 +90,6 @@ GNUNET_CRYPTO_kdf (void *result,
111} 90}
112 91
113 92
114/**
115 * Deterministically generate a pseudo-random number uniformly from the
116 * integers modulo a libgcrypt mpi.
117 *
118 * @param[out] r MPI value set to the FDH
119 * @param n MPI to work modulo
120 * @param xts salt
121 * @param xts_len length of @a xts
122 * @param skm source key material
123 * @param skm_len length of @a skm
124 * @param ctx context string
125 */
126void 93void
127GNUNET_CRYPTO_kdf_mod_mpi (gcry_mpi_t *r, 94GNUNET_CRYPTO_kdf_mod_mpi (gcry_mpi_t *r,
128 gcry_mpi_t n, 95 gcry_mpi_t n,
@@ -137,32 +104,34 @@ GNUNET_CRYPTO_kdf_mod_mpi (gcry_mpi_t *r,
137 104
138 nbits = gcry_mpi_get_nbits (n); 105 nbits = gcry_mpi_get_nbits (n);
139 /* GNUNET_assert (nbits > 512); */ 106 /* GNUNET_assert (nbits > 512); */
140
141 ctr = 0; 107 ctr = 0;
142 while (1) 108 while (1)
143 { 109 {
144 /* Ain't clear if n is always divisible by 8 */ 110 /* Ain't clear if n is always divisible by 8 */
145 uint8_t buf[ (nbits - 1) / 8 + 1 ]; 111 size_t bsize = (nbits - 1) / 8 + 1;
112 uint8_t buf[bsize];
146 uint16_t ctr_nbo = htons (ctr); 113 uint16_t ctr_nbo = htons (ctr);
147 114
148 rc = GNUNET_CRYPTO_kdf (buf, 115 rc = GNUNET_CRYPTO_kdf (buf,
149 sizeof(buf), 116 bsize,
150 xts, xts_len, 117 xts, xts_len,
151 skm, skm_len, 118 skm, skm_len,
152 ctx, strlen (ctx), 119 ctx, strlen (ctx),
153 &ctr_nbo, sizeof(ctr_nbo), 120 &ctr_nbo, sizeof(ctr_nbo),
154 NULL, 0); 121 NULL, 0);
155 GNUNET_assert (GNUNET_YES == rc); 122 GNUNET_assert (GNUNET_YES == rc);
156
157 rc = gcry_mpi_scan (r, 123 rc = gcry_mpi_scan (r,
158 GCRYMPI_FMT_USG, 124 GCRYMPI_FMT_USG,
159 (const unsigned char *) buf, 125 (const unsigned char *) buf,
160 sizeof(buf), 126 bsize,
161 &rsize); 127 &rsize);
162 GNUNET_assert (0 == rc); /* Allocation error? */ 128 GNUNET_assert (GPG_ERR_NO_ERROR == rc); /* Allocation error? */
163 129 GNUNET_assert (rsize == bsize);
164 gcry_mpi_clear_highbit (*r, nbits); 130 gcry_mpi_clear_highbit (*r,
165 GNUNET_assert (0 == gcry_mpi_test_bit (*r, nbits)); 131 nbits);
132 GNUNET_assert (0 ==
133 gcry_mpi_test_bit (*r,
134 nbits));
166 ++ctr; 135 ++ctr;
167 /* We reject this FDH if either *r > n and retry with another ctr */ 136 /* We reject this FDH if either *r > n and retry with another ctr */
168 if (0 > gcry_mpi_cmp (*r, n)) 137 if (0 > gcry_mpi_cmp (*r, n))
diff --git a/src/util/crypto_rsa.c b/src/util/crypto_rsa.c
index 43e6eedac..4b8e5a5ce 100644
--- a/src/util/crypto_rsa.c
+++ b/src/util/crypto_rsa.c
@@ -497,7 +497,8 @@ GNUNET_CRYPTO_rsa_public_key_decode (const char *buf,
497 * @return True if gcd(r,n) = 1, False means RSA key is malicious 497 * @return True if gcd(r,n) = 1, False means RSA key is malicious
498 */ 498 */
499static int 499static int
500rsa_gcd_validate (gcry_mpi_t r, gcry_mpi_t n) 500rsa_gcd_validate (gcry_mpi_t r,
501 gcry_mpi_t n)
501{ 502{
502 gcry_mpi_t g; 503 gcry_mpi_t g;
503 int t; 504 int t;
@@ -520,29 +521,34 @@ static struct RsaBlindingKey *
520rsa_blinding_key_derive (const struct GNUNET_CRYPTO_RsaPublicKey *pkey, 521rsa_blinding_key_derive (const struct GNUNET_CRYPTO_RsaPublicKey *pkey,
521 const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks) 522 const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks)
522{ 523{
523 char *xts = "Blinding KDF extractor HMAC key"; /* Trusts bks' randomness more */ 524 const char *xts = "Blinding KDF extractor HMAC key"; /* Trusts bks' randomness more */
524 struct RsaBlindingKey *blind; 525 struct RsaBlindingKey *blind;
525 gcry_mpi_t n; 526 gcry_mpi_t n;
526 527
527 blind = GNUNET_new (struct RsaBlindingKey); 528 blind = GNUNET_new (struct RsaBlindingKey);
528 GNUNET_assert (NULL != blind);
529 529
530 /* Extract the composite n from the RSA public key */ 530 /* Extract the composite n from the RSA public key */
531 GNUNET_assert (0 == key_from_sexp (&n, pkey->sexp, "rsa", "n")); 531 GNUNET_assert (0 ==
532 key_from_sexp (&n,
533 pkey->sexp,
534 "rsa",
535 "n"));
532 /* Assert that it at least looks like an RSA key */ 536 /* Assert that it at least looks like an RSA key */
533 GNUNET_assert (0 == gcry_mpi_get_flag (n, GCRYMPI_FLAG_OPAQUE)); 537 GNUNET_assert (0 ==
534 538 gcry_mpi_get_flag (n,
539 GCRYMPI_FLAG_OPAQUE));
535 GNUNET_CRYPTO_kdf_mod_mpi (&blind->r, 540 GNUNET_CRYPTO_kdf_mod_mpi (&blind->r,
536 n, 541 n,
537 xts, strlen (xts), 542 xts, strlen (xts),
538 bks, sizeof(*bks), 543 bks, sizeof(*bks),
539 "Blinding KDF"); 544 "Blinding KDF");
540 if (0 == rsa_gcd_validate (blind->r, n)) 545 if (0 == rsa_gcd_validate (blind->r,
546 n))
541 { 547 {
548 gcry_mpi_release (blind->r);
542 GNUNET_free (blind); 549 GNUNET_free (blind);
543 blind = NULL; 550 blind = NULL;
544 } 551 }
545
546 gcry_mpi_release (n); 552 gcry_mpi_release (n);
547 return blind; 553 return blind;
548} 554}
@@ -760,8 +766,9 @@ rsa_full_domain_hash (const struct GNUNET_CRYPTO_RsaPublicKey *pkey,
760 /* We key with the public denomination key as a homage to RSA-PSS by * 766 /* We key with the public denomination key as a homage to RSA-PSS by *
761 * Mihir Bellare and Phillip Rogaway. Doing this lowers the degree * 767 * Mihir Bellare and Phillip Rogaway. Doing this lowers the degree *
762 * of the hypothetical polyomial-time attack on RSA-KTI created by a * 768 * of the hypothetical polyomial-time attack on RSA-KTI created by a *
763 * polynomial-time one-more forgary attack. Yey seeding! */ 769 * polynomial-time one-more forgary attack. Yey seeding! */
764 xts_len = GNUNET_CRYPTO_rsa_public_key_encode (pkey, &xts); 770 xts_len = GNUNET_CRYPTO_rsa_public_key_encode (pkey,
771 &xts);
765 772
766 GNUNET_CRYPTO_kdf_mod_mpi (&r, 773 GNUNET_CRYPTO_kdf_mod_mpi (&r,
767 n, 774 n,
@@ -769,7 +776,6 @@ rsa_full_domain_hash (const struct GNUNET_CRYPTO_RsaPublicKey *pkey,
769 hash, sizeof(*hash), 776 hash, sizeof(*hash),
770 "RSA-FDA FTpsW!"); 777 "RSA-FDA FTpsW!");
771 GNUNET_free (xts); 778 GNUNET_free (xts);
772
773 ok = rsa_gcd_validate (r, n); 779 ok = rsa_gcd_validate (r, n);
774 gcry_mpi_release (n); 780 gcry_mpi_release (n);
775 if (ok) 781 if (ok)
diff --git a/src/util/test_crypto_eddsa.c b/src/util/test_crypto_eddsa.c
index 459619ff2..e9573a307 100644
--- a/src/util/test_crypto_eddsa.c
+++ b/src/util/test_crypto_eddsa.c
@@ -130,9 +130,11 @@ testDeriveSignVerify (void)
130 return GNUNET_SYSERR; 130 return GNUNET_SYSERR;
131 } 131 }
132 132
133 GNUNET_CRYPTO_eddsa_sign_with_scalar (&dpriv, 133 GNUNET_CRYPTO_eddsa_sign_derived (&key,
134 &purp, 134 "test-derive",
135 &sig); 135 "test-CTX",
136 &purp,
137 &sig);
136 if (GNUNET_SYSERR == 138 if (GNUNET_SYSERR ==
137 GNUNET_CRYPTO_eddsa_verify_ (GNUNET_SIGNATURE_PURPOSE_TEST, 139 GNUNET_CRYPTO_eddsa_verify_ (GNUNET_SIGNATURE_PURPOSE_TEST,
138 &purp, 140 &purp,
diff --git a/src/util/test_crypto_edx25519.c b/src/util/test_crypto_edx25519.c
new file mode 100644
index 000000000..ead6f0bb9
--- /dev/null
+++ b/src/util/test_crypto_edx25519.c
@@ -0,0 +1,326 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2022 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 util/test_crypto_edx25519.c
23 * @brief testcase for ECC public key crypto for edx25519
24 * @author Özgür Kesim
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_signatures.h"
29#include <gcrypt.h>
30
31#define ITER 25
32
33#define KEYFILE "/tmp/test-gnunet-crypto-edx25519.key"
34
35#define PERF GNUNET_YES
36
37
38static struct GNUNET_CRYPTO_Edx25519PrivateKey key;
39
40
41static int
42testSignVerify (void)
43{
44 struct GNUNET_CRYPTO_Edx25519Signature sig;
45 struct GNUNET_CRYPTO_EccSignaturePurpose purp;
46 struct GNUNET_CRYPTO_Edx25519PublicKey pkey;
47 struct GNUNET_TIME_Absolute start;
48 int ok = GNUNET_OK;
49
50 fprintf (stderr, "%s", "W");
51 GNUNET_CRYPTO_edx25519_key_get_public (&key,
52 &pkey);
53 start = GNUNET_TIME_absolute_get ();
54 purp.size = htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose));
55 purp.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST);
56
57 for (unsigned int i = 0; i < ITER; i++)
58 {
59 fprintf (stderr, "%s", "."); fflush (stderr);
60 if (GNUNET_SYSERR == GNUNET_CRYPTO_edx25519_sign_ (&key,
61 &purp,
62 &sig))
63 {
64 fprintf (stderr,
65 "GNUNET_CRYPTO_edx25519_sign returned SYSERR\n");
66 ok = GNUNET_SYSERR;
67 continue;
68 }
69 if (GNUNET_SYSERR ==
70 GNUNET_CRYPTO_edx25519_verify_ (GNUNET_SIGNATURE_PURPOSE_TEST,
71 &purp,
72 &sig,
73 &pkey))
74 {
75 fprintf (stderr,
76 "GNUNET_CRYPTO_edx25519_verify failed!\n");
77 ok = GNUNET_SYSERR;
78 continue;
79 }
80 if (GNUNET_SYSERR !=
81 GNUNET_CRYPTO_edx25519_verify_ (
82 GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN,
83 &purp,
84 &sig,
85 &pkey))
86 {
87 fprintf (stderr,
88 "GNUNET_CRYPTO_edx25519_verify failed to fail!\n");
89 ok = GNUNET_SYSERR;
90 continue;
91 }
92 }
93 fprintf (stderr, "\n");
94 printf ("%d EdDSA sign/verify operations %s\n",
95 ITER,
96 GNUNET_STRINGS_relative_time_to_string (
97 GNUNET_TIME_absolute_get_duration (start),
98 GNUNET_YES));
99 return ok;
100}
101
102
103static int
104testDeriveSignVerify (void)
105{
106 struct GNUNET_CRYPTO_EccSignaturePurpose purp;
107 struct GNUNET_CRYPTO_Edx25519Signature sig;
108 struct GNUNET_CRYPTO_Edx25519PrivateKey dkey;
109 struct GNUNET_CRYPTO_Edx25519PublicKey pub;
110 struct GNUNET_CRYPTO_Edx25519PublicKey dpub;
111 struct GNUNET_CRYPTO_Edx25519PublicKey dpub2;
112
113 GNUNET_CRYPTO_edx25519_key_get_public (&key, &pub);
114 GNUNET_CRYPTO_edx25519_private_key_derive (&key,
115 "test-derive",
116 sizeof("test-derive"),
117 &dkey);
118 GNUNET_CRYPTO_edx25519_public_key_derive (&pub,
119 "test-derive",
120 sizeof("test-derive"),
121 &dpub);
122 GNUNET_CRYPTO_edx25519_key_get_public (&dkey, &dpub2);
123
124 if (0 != GNUNET_memcmp (&dpub.q_y, &dpub2.q_y))
125 {
126 fprintf (stderr, "key deriviation failed\n");
127 return GNUNET_SYSERR;
128 }
129
130 purp.size = htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose));
131 purp.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST);
132
133 GNUNET_CRYPTO_edx25519_sign_ (&dkey,
134 &purp,
135 &sig);
136
137 if (GNUNET_SYSERR ==
138 GNUNET_CRYPTO_edx25519_verify_ (GNUNET_SIGNATURE_PURPOSE_TEST,
139 &purp,
140 &sig,
141 &dpub))
142 {
143 fprintf (stderr,
144 "GNUNET_CRYPTO_edx25519_verify failed after derivation!\n");
145 return GNUNET_SYSERR;
146 }
147
148 if (GNUNET_SYSERR !=
149 GNUNET_CRYPTO_edx25519_verify_ (GNUNET_SIGNATURE_PURPOSE_TEST,
150 &purp,
151 &sig,
152 &pub))
153 {
154 fprintf (stderr,
155 "GNUNET_CRYPTO_edx25519_verify failed to fail after derivation!\n");
156 return GNUNET_SYSERR;
157 }
158
159 if (GNUNET_SYSERR !=
160 GNUNET_CRYPTO_edx25519_verify_ (
161 GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN,
162 &purp,
163 &sig,
164 &dpub))
165 {
166 fprintf (stderr,
167 "GNUNET_CRYPTO_edx25519_verify failed to fail after derivation!\n");
168 return GNUNET_SYSERR;
169 }
170 return GNUNET_OK;
171}
172
173
174#if PERF
175static int
176testSignPerformance ()
177{
178 struct GNUNET_CRYPTO_EccSignaturePurpose purp;
179 struct GNUNET_CRYPTO_Edx25519Signature sig;
180 struct GNUNET_CRYPTO_Edx25519PublicKey pkey;
181 struct GNUNET_TIME_Absolute start;
182 int ok = GNUNET_OK;
183
184 purp.size = htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose));
185 purp.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST);
186 fprintf (stderr, "%s", "W");
187 GNUNET_CRYPTO_edx25519_key_get_public (&key,
188 &pkey);
189 start = GNUNET_TIME_absolute_get ();
190 for (unsigned int i = 0; i < ITER; i++)
191 {
192 fprintf (stderr, "%s", ".");
193 fflush (stderr);
194 if (GNUNET_SYSERR ==
195 GNUNET_CRYPTO_edx25519_sign_ (&key,
196 &purp,
197 &sig))
198 {
199 fprintf (stderr, "%s", "GNUNET_CRYPTO_edx25519_sign returned SYSERR\n");
200 ok = GNUNET_SYSERR;
201 continue;
202 }
203 }
204 fprintf (stderr, "\n");
205 printf ("%d EdDSA sign operations %s\n",
206 ITER,
207 GNUNET_STRINGS_relative_time_to_string (
208 GNUNET_TIME_absolute_get_duration (start),
209 GNUNET_YES));
210 return ok;
211}
212
213
214#endif
215
216
217#if 0 /* not implemented */
218static int
219testCreateFromFile (void)
220{
221 struct GNUNET_CRYPTO_Edx25519PublicKey p1;
222 struct GNUNET_CRYPTO_Edx25519PublicKey p2;
223
224 /* do_create == GNUNET_YES and non-existing file MUST return GNUNET_YES */
225 GNUNET_assert (0 == unlink (KEYFILE) || ENOENT == errno);
226 GNUNET_assert (GNUNET_YES ==
227 GNUNET_CRYPTO_edx25519_key_from_file (KEYFILE,
228 GNUNET_YES,
229 &key));
230 GNUNET_CRYPTO_edx25519_key_get_public (&key,
231 &p1);
232
233 /* do_create == GNUNET_YES and _existing_ file MUST return GNUNET_NO */
234 GNUNET_assert (GNUNET_NO ==
235 GNUNET_CRYPTO_edx25519_key_from_file (KEYFILE,
236 GNUNET_YES,
237 &key));
238 GNUNET_CRYPTO_edx25519_key_get_public (&key,
239 &p2);
240 GNUNET_assert (0 ==
241 GNUNET_memcmp (&p1,
242 &p2));
243
244 /* do_create == GNUNET_NO and non-existing file MUST return GNUNET_SYSERR */
245 GNUNET_assert (0 == unlink (KEYFILE));
246 GNUNET_assert (GNUNET_SYSERR ==
247 GNUNET_CRYPTO_edx25519_key_from_file (KEYFILE,
248 GNUNET_NO,
249 &key));
250 return GNUNET_OK;
251}
252
253
254#endif
255
256
257static void
258perf_keygen (void)
259{
260 struct GNUNET_TIME_Absolute start;
261 struct GNUNET_CRYPTO_Edx25519PrivateKey pk;
262
263 fprintf (stderr, "%s", "W");
264 start = GNUNET_TIME_absolute_get ();
265 for (unsigned int i = 0; i < 10; i++)
266 {
267 fprintf (stderr, ".");
268 fflush (stderr);
269 GNUNET_CRYPTO_edx25519_key_create (&pk);
270 }
271 fprintf (stderr, "\n");
272 printf ("10 EdDSA keys created in %s\n",
273 GNUNET_STRINGS_relative_time_to_string (
274 GNUNET_TIME_absolute_get_duration (start), GNUNET_YES));
275}
276
277
278int
279main (int argc, char *argv[])
280{
281 int failure_count = 0;
282
283 if (! gcry_check_version ("1.6.0"))
284 {
285 fprintf (stderr,
286 "libgcrypt has not the expected version (version %s is required).\n",
287 "1.6.0");
288 return 0;
289 }
290 if (getenv ("GNUNET_GCRYPT_DEBUG"))
291 gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
292 GNUNET_log_setup ("test-crypto-edx25519",
293 "WARNING",
294 NULL);
295 GNUNET_CRYPTO_edx25519_key_create (&key);
296 if (GNUNET_OK != testDeriveSignVerify ())
297 {
298 failure_count++;
299 fprintf (stderr,
300 "\n\n%d TESTS FAILED!\n\n", failure_count);
301 return -1;
302 }
303#if PERF
304 if (GNUNET_OK != testSignPerformance ())
305 failure_count++;
306#endif
307 if (GNUNET_OK != testSignVerify ())
308 failure_count++;
309#if 0 /* not implemented */
310 if (GNUNET_OK != testCreateFromFile ())
311 failure_count++;
312#endif
313 perf_keygen ();
314
315 if (0 != failure_count)
316 {
317 fprintf (stderr,
318 "\n\n%d TESTS FAILED!\n\n",
319 failure_count);
320 return -1;
321 }
322 return 0;
323}
324
325
326/* end of test_crypto_edx25519.c */
diff --git a/src/util/time.c b/src/util/time.c
index 68a6937a0..cf072aebf 100644
--- a/src/util/time.c
+++ b/src/util/time.c
@@ -58,6 +58,22 @@ GNUNET_TIME_get_offset ()
58} 58}
59 59
60 60
61bool
62GNUNET_TIME_absolute_approx_eq (struct GNUNET_TIME_Absolute a1,
63 struct GNUNET_TIME_Absolute a2,
64 struct GNUNET_TIME_Relative t)
65{
66 struct GNUNET_TIME_Relative delta;
67
68 delta = GNUNET_TIME_relative_min (
69 GNUNET_TIME_absolute_get_difference (a1, a2),
70 GNUNET_TIME_absolute_get_difference (a2, a1));
71 return GNUNET_TIME_relative_cmp (delta,
72 <=,
73 t);
74}
75
76
61struct GNUNET_TIME_Timestamp 77struct GNUNET_TIME_Timestamp
62GNUNET_TIME_absolute_to_timestamp (struct GNUNET_TIME_Absolute at) 78GNUNET_TIME_absolute_to_timestamp (struct GNUNET_TIME_Absolute at)
63{ 79{
@@ -370,6 +386,20 @@ GNUNET_TIME_timestamp_min (struct GNUNET_TIME_Timestamp t1,
370} 386}
371 387
372 388
389struct GNUNET_TIME_Absolute
390GNUNET_TIME_absolute_round_down (struct GNUNET_TIME_Absolute at,
391 struct GNUNET_TIME_Relative rt)
392{
393 struct GNUNET_TIME_Absolute ret;
394
395 GNUNET_assert (! GNUNET_TIME_relative_is_zero (rt));
396 ret.abs_value_us
397 = at.abs_value_us
398 - at.abs_value_us % rt.rel_value_us;
399 return ret;
400}
401
402
373struct GNUNET_TIME_Relative 403struct GNUNET_TIME_Relative
374GNUNET_TIME_absolute_get_remaining (struct GNUNET_TIME_Absolute future) 404GNUNET_TIME_absolute_get_remaining (struct GNUNET_TIME_Absolute future)
375{ 405{