From 46b73f8d138ade01499165f62edb683c87c777c4 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Fri, 6 Oct 2017 21:35:55 +0200 Subject: [PATCH] -towards ticket revocation --- .../gnunet-service-identity-provider.c | 357 ++++++++++++++++-- src/identity-provider/identity_provider.h | 31 +- src/identity-provider/identity_provider_api.c | 4 +- src/include/gnunet_protocols.h | 16 +- 4 files changed, 374 insertions(+), 34 deletions(-) diff --git a/src/identity-provider/gnunet-service-identity-provider.c b/src/identity-provider/gnunet-service-identity-provider.c index 863423cac..95d8b93b2 100644 --- a/src/identity-provider/gnunet-service-identity-provider.c +++ b/src/identity-provider/gnunet-service-identity-provider.c @@ -441,6 +441,56 @@ struct ParallelLookup char *label; }; +/** + * Ticket revocation request handle + */ +struct TicketRevocationHandle +{ + + /** + * Client connection + */ + struct IdpClient *client; + + /** + * Attributes to issue + */ + struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs; + + /** + * Issuer Key + */ + struct GNUNET_CRYPTO_EcdsaPrivateKey identity; + + /** + * Ticket to issue + */ + struct GNUNET_IDENTITY_PROVIDER_Ticket ticket; + + /** + * QueueEntry + */ + struct GNUNET_NAMESTORE_QueueEntry *ns_qe; + + /** + * Namestore iterator + */ + struct GNUNET_NAMESTORE_ZoneIterator *ns_it; + + /** + * The ABE master key + */ + struct GNUNET_CRYPTO_AbeMasterKey *abe_key; + + + /** + * request id + */ + uint32_t r_id; +}; + + + /** * Ticket issue request handle */ @@ -652,11 +702,13 @@ bootstrap_abe_result (void *cls, /** * Bootstrap ABE master if it does not yet exists. * Will call the AbeBootstrapResult processor when done. + * will always recreate the ABE key of GNUNET_YES == recreate */ static void bootstrap_abe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, AbeBootstrapResult proc, - void* cls) + void* cls, + int recreate) { struct AbeBootstrapHandle *abh; @@ -664,14 +716,19 @@ bootstrap_abe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, abh->proc = proc; abh->proc_cls = cls; abh->identity = *identity; - abh->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle, - identity, - "+", - &bootstrap_abe_error, - abh, - &bootstrap_abe_result, - abh); - + if (GNUNET_YES == recreate) + { + abh->abe_key = GNUNET_CRYPTO_cpabe_create_master_key (); + GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh); + } else { + abh->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle, + identity, + "+", + &bootstrap_abe_error, + abh, + &bootstrap_abe_result, + abh); + } } @@ -903,13 +960,13 @@ issue_ticket_after_abe_bootstrap (void *cls, * @return #GNUNET_OK if @a im is well-formed */ static int -check_ticket_issue_message(void *cls, - const struct TicketIssueMessage *im) +check_issue_ticket_message(void *cls, + const struct IssueTicketMessage *im) { uint16_t size; size = ntohs (im->header.size); - if (size <= sizeof (struct TicketIssueMessage)) + if (size <= sizeof (struct IssueTicketMessage)) { GNUNET_break (0); return GNUNET_SYSERR; @@ -927,8 +984,8 @@ check_ticket_issue_message(void *cls, * @param message the message */ static void -handle_ticket_issue_message (void *cls, - const struct TicketIssueMessage *im) +handle_issue_ticket_message (void *cls, + const struct IssueTicketMessage *im) { struct TicketIssueHandle *ih; struct IdpClient *idp = cls; @@ -946,11 +1003,260 @@ handle_ticket_issue_message (void *cls, ih->ticket.rnd = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX); - bootstrap_abe (&ih->identity, &issue_ticket_after_abe_bootstrap, ih); + bootstrap_abe (&ih->identity, &issue_ticket_after_abe_bootstrap, ih, GNUNET_NO); GNUNET_SERVICE_client_continue (idp->client); } +static void +attr_reenc_cont (void *cls, + int32_t success, + const char *emsg) +{ + struct TicketRevocationHandle *rh = cls; + struct GNUNET_GNSRECORD_Data rd[1]; + size_t buf_size; + char *buf; + + if (GNUNET_SYSERR == success) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to reencrypt attribute %s\n", + emsg); + GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); + return; + } + GNUNET_CONTAINER_DLL_remove (rh->attrs->list_head, + rh->attrs->list_tail, + rh->attrs->list_head); + if (NULL == rh->attrs->list_head) + { + /* Done, issue new keys */ + GNUNET_break (0); //TODO + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Re-encrypting attribute\n"); + buf_size = attribute_serialize_get_size (rh->attrs->list_head->attribute); + buf = GNUNET_malloc (buf_size); + + attribute_serialize (rh->attrs->list_head->attribute, + buf); + + /** + * Encrypt the attribute value and store in namestore + */ + rd[0].data_size = GNUNET_CRYPTO_cpabe_encrypt (buf, + buf_size, + rh->attrs->list_head->attribute->name, //Policy + rh->abe_key, + (void**)&rd[0].data); + GNUNET_free (buf); + rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR; + rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; + rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane? + rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle, + &rh->identity, + rh->attrs->list_head->attribute->name, + 1, + rd, + &attr_reenc_cont, + rh); + GNUNET_free ((void*)rd[0].data); + +} + + +static void +reenc_after_abe_bootstrap (void *cls, + struct GNUNET_CRYPTO_AbeMasterKey *abe_key) +{ + struct TicketRevocationHandle *rh = cls; + struct GNUNET_GNSRECORD_Data rd[1]; + char* buf; + size_t buf_size; + + + rh->abe_key = abe_key; + GNUNET_assert (NULL != abe_key); + + if (NULL == rh->attrs->list_head) + { + /* No attributes to reencrypt, this is odd... */ + } else { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Re-encrypting attribute\n"); + buf_size = attribute_serialize_get_size (rh->attrs->list_head->attribute); + buf = GNUNET_malloc (buf_size); + + attribute_serialize (rh->attrs->list_head->attribute, + buf); + + /** + * Encrypt the attribute value and store in namestore + */ + rd[0].data_size = GNUNET_CRYPTO_cpabe_encrypt (buf, + buf_size, + rh->attrs->list_head->attribute->name, //Policy + rh->abe_key, + (void**)&rd[0].data); + GNUNET_free (buf); + rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR; + rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; + rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane? + rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle, + &rh->identity, + rh->attrs->list_head->attribute->name, + 1, + rd, + &attr_reenc_cont, + rh); + GNUNET_free ((void*)rd[0].data); + + } +} + + +static void +revoke_collect_iter_error (void *cls) +{ + //struct AttributeIterator *ai = cls; + //TODO + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to iterate over attributes\n"); + GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); +} + +static void +revoke_collect_iter_finished (void *cls) +{ + struct TicketRevocationHandle *rh = cls; + + /* Bootstrap new abe key */ + bootstrap_abe (&rh->identity, &reenc_after_abe_bootstrap, rh, GNUNET_YES); +} + +static void +revoke_collect_iter_cb (void *cls, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, + const char *label, + unsigned int rd_count, + const struct GNUNET_GNSRECORD_Data *rd) +{ + struct TicketRevocationHandle *rh = cls; + struct GNUNET_CRYPTO_AbeKey *key; + struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le; + ssize_t attr_len; + char* attr_ser; + char* attrs[2]; + + if (rd_count != 1) + { + GNUNET_NAMESTORE_zone_iterator_next (rh->ns_it); + return; + } + + if (GNUNET_GNSRECORD_TYPE_ID_ATTR != rd->record_type) { + GNUNET_NAMESTORE_zone_iterator_next (rh->ns_it); + return; + } + attrs[0] = (char*)label; + attrs[1] = 0; + key = GNUNET_CRYPTO_cpabe_create_key (rh->abe_key, + attrs); + attr_len = GNUNET_CRYPTO_cpabe_decrypt (rd->data, + rd->data_size, + key, + (void**)&attr_ser); + GNUNET_CRYPTO_cpabe_delete_key (key); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Attribute to reencrypt: %s\n", label); + le = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry); + le->attribute = attribute_deserialize (attr_ser, attr_len); + GNUNET_CONTAINER_DLL_insert_tail (rh->attrs->list_head, + rh->attrs->list_tail, + le); + GNUNET_NAMESTORE_zone_iterator_next (rh->ns_it); +} + + +static void +collect_after_abe_bootstrap (void *cls, + struct GNUNET_CRYPTO_AbeMasterKey *abe_key) +{ + struct TicketRevocationHandle *rh = cls; + + rh->abe_key = cls; + GNUNET_assert (NULL != abe_key); + + /* Reencrypt all attributes with new key */ + rh->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle, + &rh->identity, + &revoke_collect_iter_error, + rh, + &revoke_collect_iter_cb, + rh, + &revoke_collect_iter_finished, + rh); + +} + + +/** + * Checks a ticket revocation message + * + * @param cls client sending the message + * @param im message of type `struct RevokeTicketMessage` + * @return #GNUNET_OK if @a im is well-formed + */ +static int +check_revoke_ticket_message(void *cls, + const struct RevokeTicketMessage *im) +{ + uint16_t size; + + size = ntohs (im->header.size); + if (size <= sizeof (struct RevokeTicketMessage)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +/** + * + * Handler for ticket revocation message + * + * @param cls unused + * @param client who sent the message + * @param message the message + */ +static void +handle_revoke_ticket_message (void *cls, + const struct RevokeTicketMessage *rm) +{ + struct TicketRevocationHandle *rh; + struct IdpClient *idp = cls; + struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket; + size_t attrs_len; + + rh = GNUNET_new (struct TicketRevocationHandle); + attrs_len = ntohs (rm->attrs_len); + ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket*)&rm[1]; + if (0 < attrs_len) + rh->attrs = attribute_list_deserialize ((char*)&ticket[1], attrs_len); + rh->ticket = *ticket; + rh->r_id = ntohl (rm->id); + rh->client = idp; + rh->identity = rm->identity; + GNUNET_CRYPTO_ecdsa_key_get_public (&rh->identity, + &rh->ticket.identity); + bootstrap_abe (&rh->identity, &collect_after_abe_bootstrap, rh, GNUNET_NO); + GNUNET_SERVICE_client_continue (idp->client); + +} static void @@ -1034,7 +1340,7 @@ process_parallel_lookup2 (void *cls, uint32_t rd_count, "Unable to store ticket after consume\n"); GNUNET_break (0); } - + GNUNET_SCHEDULER_cancel (handle->kill_task); attrs_len = attribute_list_serialize_get_size (handle->attrs); env = GNUNET_MQ_msg_extra (crm, @@ -1217,7 +1523,7 @@ handle_consume_ticket_message (void *cls, GNUNET_SERVICE_client_continue (idp->client); } -void +static void attr_store_cont (void *cls, int32_t success, const char *emsg) @@ -1351,7 +1657,7 @@ handle_attribute_store_message (void *cls, GNUNET_SERVICE_client_continue (idp->client); as_handle->client = idp; - bootstrap_abe (&as_handle->identity, &store_after_abe_bootstrap, as_handle); + bootstrap_abe (&as_handle->identity, &store_after_abe_bootstrap, as_handle, GNUNET_NO); } static void @@ -1483,7 +1789,7 @@ handle_iteration_start (void *cls, GNUNET_CONTAINER_DLL_insert (idp->op_head, idp->op_tail, ai); - bootstrap_abe (&ai->identity, &iterate_after_abe_bootstrap, ai); + bootstrap_abe (&ai->identity, &iterate_after_abe_bootstrap, ai, GNUNET_NO); GNUNET_SERVICE_client_continue (idp->client); } @@ -1937,9 +2243,9 @@ GNUNET_SERVICE_MAIN GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP, struct AttributeIterationStopMessage, NULL), - GNUNET_MQ_hd_var_size (ticket_issue_message, - GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ISSUE, - struct TicketIssueMessage, + GNUNET_MQ_hd_var_size (issue_ticket_message, + GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET, + struct IssueTicketMessage, NULL), GNUNET_MQ_hd_var_size (consume_ticket_message, GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET, @@ -1957,6 +2263,9 @@ GNUNET_SERVICE_MAIN GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP, struct TicketIterationStopMessage, NULL), - + GNUNET_MQ_hd_var_size (revoke_ticket_message, + GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET, + struct RevokeTicketMessage, + NULL), GNUNET_MQ_handler_end()); - /* end of gnunet-service-identity-provider.c */ +/* end of gnunet-service-identity-provider.c */ diff --git a/src/identity-provider/identity_provider.h b/src/identity-provider/identity_provider.h index 9361854ad..a4cdd694e 100644 --- a/src/identity-provider/identity_provider.h +++ b/src/identity-provider/identity_provider.h @@ -245,7 +245,7 @@ struct TicketIterationStopMessage /** * Ticket issue message */ -struct TicketIssueMessage +struct IssueTicketMessage { /** * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ISSUE @@ -275,6 +275,35 @@ struct TicketIssueMessage //Followed by a serialized attribute list }; +/** + * Ticket revoke message + */ +struct RevokeTicketMessage +{ + /** + * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ISSUE + */ + struct GNUNET_MessageHeader header; + + /** + * Unique identifier for this request (for key collisions). + */ + uint32_t id GNUNET_PACKED; + + /** + * Identity. + */ + struct GNUNET_CRYPTO_EcdsaPrivateKey identity; + + /** + * length of serialized attribute list + */ + uint32_t attrs_len GNUNET_PACKED; + + //Followed by a ticket and serialized attribute list +}; + + /** * Ticket result message */ diff --git a/src/identity-provider/identity_provider_api.c b/src/identity-provider/identity_provider_api.c index 33468cc13..97ecc691c 100644 --- a/src/identity-provider/identity_provider_api.c +++ b/src/identity-provider/identity_provider_api.c @@ -1035,7 +1035,7 @@ GNUNET_IDENTITY_PROVIDER_ticket_issue (struct GNUNET_IDENTITY_PROVIDER_Handle *h void *cb_cls) { struct GNUNET_IDENTITY_PROVIDER_Operation *op; - struct TicketIssueMessage *tim; + struct IssueTicketMessage *tim; size_t attr_len; op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation); @@ -1049,7 +1049,7 @@ GNUNET_IDENTITY_PROVIDER_ticket_issue (struct GNUNET_IDENTITY_PROVIDER_Handle *h attr_len = attribute_list_serialize_get_size (attrs); op->env = GNUNET_MQ_msg_extra (tim, attr_len, - GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ISSUE); + GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET); tim->identity = *iss; tim->rp = *rp; tim->id = htonl (op->r_id); diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h index dd806fcac..bf643a9fd 100644 --- a/src/include/gnunet_protocols.h +++ b/src/include/gnunet_protocols.h @@ -2632,19 +2632,21 @@ extern "C" #define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT 966 -#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ISSUE 967 +#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET 967 -#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT 968 +#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET 968 -#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET 969 +#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT 969 -#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT 970 +#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET 970 -#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START 971 +#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT 971 -#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP 972 +#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START 972 -#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT 973 +#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP 973 + +#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT 974 /************************************************** * -- 2.25.1