2 This file is part of GNUnet.
3 Copyright (C) 2012-2015 GNUnet e.V.
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.
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.
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/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
22 * @author Martin Schanzenbach
23 * @file src/reclaim/gnunet-service-reclaim_tickets.c
24 * @brief reclaim tickets
27 #include "gnunet-service-reclaim_tickets.h"
30 * A reference to a ticket stored in GNS
32 struct TicketReference
37 struct TicketReference *next;
42 struct TicketReference *prev;
47 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
52 struct GNUNET_RECLAIM_Ticket ticket;
57 * Ticket issue request handle
59 struct TicketIssueHandle
64 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
69 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
74 struct GNUNET_RECLAIM_Ticket ticket;
79 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
82 * Ticket reference list
84 struct TicketReference *ticket_refs_head;
87 * Ticket reference list
89 struct TicketReference *ticket_refs_tail;
92 * Number of references
94 uint32_t ticket_ref_num;
99 RECLAIM_TICKETS_TicketResult cb;
108 static struct GNUNET_NAMESTORE_Handle *nsh;
111 * Cleanup ticket consume handle
112 * @param handle the handle to clean up
115 cleanup_issue_handle (struct TicketIssueHandle *handle)
117 struct TicketReference *tr;
118 struct TicketReference *tr_tmp;
119 if (NULL != handle->attrs)
120 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (handle->attrs);
121 if (NULL != handle->ns_qe)
122 GNUNET_NAMESTORE_cancel (handle->ns_qe);
123 for (tr = handle->ticket_refs_head; NULL != tr;)
125 if (NULL != tr->attrs)
126 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (tr->attrs);
129 GNUNET_free (tr_tmp);
131 GNUNET_free (handle);
137 store_ticket_refs_cont (void *cls,
141 struct TicketIssueHandle *handle = cls;
142 handle->ns_qe = NULL;
143 if (GNUNET_OK != success)
145 handle->cb (handle->cb_cls,
148 "Error storing updated ticket refs in GNS");
149 cleanup_issue_handle (handle);
152 handle->cb (handle->cb_cls,
156 cleanup_issue_handle (handle);
162 update_ticket_refs (void* cls)
164 struct TicketIssueHandle *handle = cls;
165 struct GNUNET_GNSRECORD_Data refs_rd[handle->ticket_ref_num];
166 struct TicketReference *tr;
170 tr = handle->ticket_refs_head;
171 for (int i = 0; i < handle->ticket_ref_num; i++)
173 buf_size = GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (tr->attrs);
174 buf_size += sizeof (struct GNUNET_RECLAIM_Ticket);
175 buf = GNUNET_malloc (buf_size);
176 memcpy (buf, &tr->ticket, sizeof (struct GNUNET_RECLAIM_Ticket));
177 GNUNET_RECLAIM_ATTRIBUTE_list_serialize (tr->attrs,
178 buf + sizeof (struct GNUNET_RECLAIM_Ticket));
179 refs_rd[i].data = buf;
180 refs_rd[i].data_size = buf_size;
181 refs_rd[i].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
182 refs_rd[i].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_TICKETREF;
183 refs_rd[i].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION |
184 GNUNET_GNSRECORD_RF_PRIVATE;
188 handle->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
190 GNUNET_GNS_EMPTY_LABEL_AT,
191 handle->ticket_ref_num,
193 &store_ticket_refs_cont,
195 for (int i = 0; i < handle->ticket_ref_num; i++)
196 GNUNET_free ((char*)refs_rd[i].data);
202 ticket_lookup_cb (void *cls,
203 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
205 unsigned int rd_count,
206 const struct GNUNET_GNSRECORD_Data *rd)
208 struct TicketIssueHandle *handle = cls;
209 struct TicketReference *tr;
210 const char* attr_data;
211 size_t attr_data_len;
212 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
213 "Received tickets from local namestore.\n");
214 handle->ns_qe = NULL;
215 for (int i = 0; i < rd_count; i++)
217 if (GNUNET_GNSRECORD_TYPE_RECLAIM_TICKETREF != rd[i].record_type)
219 tr = GNUNET_new (struct TicketReference);
220 memcpy (&tr->ticket, rd[i].data,
221 sizeof (struct GNUNET_RECLAIM_Ticket));
222 if (0 != memcmp (&tr->ticket.identity,
223 &handle->ticket.identity,
224 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
230 attr_data = rd[i].data + sizeof (struct GNUNET_RECLAIM_Ticket);
231 attr_data_len = rd[i].data_size - sizeof (struct GNUNET_RECLAIM_Ticket);
232 tr->attrs = GNUNET_RECLAIM_ATTRIBUTE_list_deserialize (attr_data,
234 GNUNET_CONTAINER_DLL_insert (handle->ticket_refs_head,
235 handle->ticket_refs_tail,
237 handle->ticket_ref_num++;
239 tr = GNUNET_new (struct TicketReference);
240 tr->ticket = handle->ticket;
241 tr->attrs = GNUNET_RECLAIM_ATTRIBUTE_list_dup (handle->attrs);
242 GNUNET_CONTAINER_DLL_insert (handle->ticket_refs_head,
243 handle->ticket_refs_tail,
245 handle->ticket_ref_num++;
246 GNUNET_SCHEDULER_add_now (&update_ticket_refs, handle);
250 ticket_lookup_error_cb (void *cls)
252 struct TicketIssueHandle *handle = cls;
253 handle->ns_qe = NULL;
254 handle->cb (handle->cb_cls,
257 "Error checking for ticketsin GNS\n");
258 cleanup_issue_handle (handle);
262 store_ticket_issue_cont (void *cls,
266 struct TicketIssueHandle *handle = cls;
268 handle->ns_qe = NULL;
269 if (GNUNET_SYSERR == success)
271 handle->cb (handle->cb_cls,
274 "Error storing AuthZ ticket in GNS");
277 /* First, local references to tickets */
278 handle->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh,
280 GNUNET_GNS_EMPTY_LABEL_AT,
281 &ticket_lookup_error_cb,
288 create_sym_key_from_ecdh (const struct GNUNET_HashCode *new_key_hash,
289 struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
290 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
292 struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str;
294 GNUNET_CRYPTO_hash_to_enc (new_key_hash,
296 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str);
297 static const char ctx_key[] = "gnuid-aes-ctx-key";
298 GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
299 new_key_hash, sizeof (struct GNUNET_HashCode),
300 ctx_key, strlen (ctx_key),
302 static const char ctx_iv[] = "gnuid-aes-ctx-iv";
303 GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
304 new_key_hash, sizeof (struct GNUNET_HashCode),
305 ctx_iv, strlen (ctx_iv),
312 serialize_authz_record (const struct GNUNET_RECLAIM_Ticket *ticket,
313 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
314 struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
317 struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
318 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
319 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
320 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
321 struct GNUNET_HashCode new_key_hash;
329 GNUNET_assert (NULL != attrs->list_head);
331 for (le = attrs->list_head; NULL != le; le = le->next) {
332 attrs_str_len += 15 + 1; //TODO propery calculate
334 buf = GNUNET_malloc (attrs_str_len);
336 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
337 "Writing attributes\n");
338 for (le = attrs->list_head; NULL != le; le = le->next) {
339 label = GNUNET_STRINGS_data_to_string_alloc (&le->claim->id,
341 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
342 "Adding attribute to record: %s\n", label);
344 GNUNET_memcpy (write_ptr,
347 write_ptr[strlen (label)] = ',';
348 write_ptr += strlen (label) + 1;
352 write_ptr[0] = '\0'; //replace last , with a 0-terminator
353 // ECDH keypair E = eG
354 *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
355 GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
357 enc_keyinfo = GNUNET_malloc (attrs_str_len);
358 // Derived key K = H(eB)
359 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
362 create_sym_key_from_ecdh (&new_key_hash, &skey, &iv);
363 enc_size = GNUNET_CRYPTO_symmetric_encrypt (buf,
367 *result = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+
369 GNUNET_memcpy (*result,
371 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
372 GNUNET_memcpy (*result + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
375 GNUNET_free (enc_keyinfo);
377 return sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+enc_size;
383 issue_ticket (struct TicketIssueHandle *ih)
385 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
386 struct GNUNET_GNSRECORD_Data code_record[1];
387 char *authz_record_data;
388 size_t authz_record_len;
391 //TODO rename function
392 authz_record_len = serialize_authz_record (&ih->ticket,
396 code_record[0].data = authz_record_data;
397 code_record[0].data_size = authz_record_len;
398 code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
399 code_record[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_AUTHZ;
400 code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
402 label = GNUNET_STRINGS_data_to_string_alloc (&ih->ticket.rnd,
405 ih->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
410 &store_ticket_issue_cont,
412 GNUNET_free (ecdhe_privkey);
414 GNUNET_free (authz_record_data);
421 RECLAIM_TICKETS_issue_ticket (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
422 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
423 const struct GNUNET_CRYPTO_EcdsaPublicKey *audience,
424 RECLAIM_TICKETS_TicketResult cb,
427 struct TicketIssueHandle *tih;
428 tih = GNUNET_new (struct TicketIssueHandle);
430 tih->cb_cls = cb_cls;
431 tih->attrs = GNUNET_RECLAIM_ATTRIBUTE_list_dup (attrs);
432 tih->identity = *identity;
433 GNUNET_CRYPTO_ecdsa_key_get_public (identity,
434 &tih->ticket.identity);
436 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
438 tih->ticket.audience = *audience;
444 RECLAIM_TICKETS_init (const struct GNUNET_CONFIGURATION_Handle *c)
446 //Connect to identity and namestore services
447 nsh = GNUNET_NAMESTORE_connect (c);
450 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
451 "Error connecting to namestore\n");
452 return GNUNET_SYSERR;