gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnunet] 02/02: reclaim: Attestations now called credentials. Credential


From: gnunet
Subject: [gnunet] 02/02: reclaim: Attestations now called credentials. Credentials are presented to third parties as presentations.
Date: Thu, 20 Aug 2020 18:05:33 +0200

This is an automated email from the git hooks/post-receive script.

martin-schanzenbach pushed a commit to branch master
in repository gnunet.

commit a57d476abbe857365aff157f389cc1188b5dd090
Author: Martin Schanzenbach <mschanzenbach@posteo.de>
AuthorDate: Wed Aug 19 23:53:02 2020 +0200

    reclaim: Attestations now called credentials. Credentials are presented to 
third parties as presentations.
---
 src/include/gnunet_gnsrecord_lib.h           |   7 +-
 src/include/gnunet_reclaim_lib.h             |  13 +-
 src/include/gnunet_reclaim_plugin.h          |  10 +
 src/include/gnunet_reclaim_service.h         |  18 +-
 src/reclaim/gnunet-reclaim.c                 |   5 +-
 src/reclaim/gnunet-service-reclaim.c         |  33 +-
 src/reclaim/gnunet-service-reclaim_tickets.c | 197 ++++++++---
 src/reclaim/gnunet-service-reclaim_tickets.h |   7 +-
 src/reclaim/json_reclaim.c                   |  12 +-
 src/reclaim/json_reclaim.h                   |   2 +-
 src/reclaim/oidc_helper.c                    |  22 +-
 src/reclaim/oidc_helper.h                    |  16 +-
 src/reclaim/plugin_gnsrecord_reclaim.c       |  12 +-
 src/reclaim/plugin_reclaim_credential_jwt.c  | 159 +++++++--
 src/reclaim/plugin_rest_openid_connect.c     |  68 ++--
 src/reclaim/plugin_rest_reclaim.c            |   6 +-
 src/reclaim/reclaim.h                        |   7 +
 src/reclaim/reclaim_api.c                    |  58 +++-
 src/reclaim/reclaim_credential.c             | 501 ++++++++++++++++++++++++++-
 src/reclaim/reclaim_credential.h             |  35 ++
 20 files changed, 1010 insertions(+), 178 deletions(-)

diff --git a/src/include/gnunet_gnsrecord_lib.h 
b/src/include/gnunet_gnsrecord_lib.h
index c976c89c5..960203fb1 100644
--- a/src/include/gnunet_gnsrecord_lib.h
+++ b/src/include/gnunet_gnsrecord_lib.h
@@ -143,12 +143,13 @@ extern "C" {
 /**
  * Record type for an attribute attestation
  */
-#define GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION 65554
+#define GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL 65554
 
 /**
- * Record type for an attestation reference in a ticket
+ * Record type for a presentation of a credential (used
+ * in a ticket record set)
  */
-#define GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION_REF 65555
+#define GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION 65555
 
 
 /**
diff --git a/src/include/gnunet_reclaim_lib.h b/src/include/gnunet_reclaim_lib.h
index f5c3d3864..bbf1c3ad3 100644
--- a/src/include/gnunet_reclaim_lib.h
+++ b/src/include/gnunet_reclaim_lib.h
@@ -780,6 +780,11 @@ GNUNET_RECLAIM_presentation_value_to_string (uint32_t type,
                                              const void *data,
                                              size_t data_size);
 
+struct GNUNET_RECLAIM_Presentation *
+GNUNET_RECLAIM_presentation_new (uint32_t type,
+                                 const void *data,
+                                 size_t data_size);
+
 /**
  * Convert human-readable version of a 'claim' of a presentation to the binary
  * representation
@@ -828,14 +833,16 @@ GNUNET_RECLAIM_presentation_get_expiration (const struct
  *
  * @param cred the credential to use
  * @param attrs the attributes to present from the credential
- * @return the credential presentation presenting the attributes according
+ * @param presentation the credential presentation presenting the attributes 
according
  *         to the presentation mechanism of the credential
  *         or NULL on error.
+ * @return GNUNET_OK on success.
  */
-struct GNUNET_RECLAIM_Presentation*
+int
 GNUNET_RECLAIM_credential_get_presentation (
                               const struct GNUNET_RECLAIM_Credential *cred,
-                              const struct GNUNET_RECLAIM_AttributeList 
*attrs);
+                              const struct GNUNET_RECLAIM_AttributeList *attrs,
+                              struct GNUNET_RECLAIM_Presentation 
**presentation);
 
 
 #if 0 /* keep Emacsens' auto-indent happy */
diff --git a/src/include/gnunet_reclaim_plugin.h 
b/src/include/gnunet_reclaim_plugin.h
index af6c74e0b..2ba8fc8a0 100644
--- a/src/include/gnunet_reclaim_plugin.h
+++ b/src/include/gnunet_reclaim_plugin.h
@@ -301,6 +301,11 @@ typedef int 
(*GNUNET_RECLAIM_PresentationGetExpirationFunction) (
   const struct GNUNET_RECLAIM_Presentation *cred,
   struct GNUNET_TIME_Absolute *expiration);
 
+typedef int (*GNUNET_RECLAIM_CredentialToPresentation) (
+  void *cls,
+  const struct GNUNET_RECLAIM_Credential *cred,
+  const struct GNUNET_RECLAIM_AttributeList *attrs,
+  struct GNUNET_RECLAIM_Presentation **presentation);
 
 /**
  * Each plugin is required to return a pointer to a struct of this
@@ -416,6 +421,11 @@ struct GNUNET_RECLAIM_CredentialPluginFunctions
    */
   GNUNET_RECLAIM_PresentationGetExpirationFunction get_expiration_p;
 
+  /**
+   * Get presentation
+   */
+  GNUNET_RECLAIM_CredentialToPresentation create_presentation;
+
 };
 
 
diff --git a/src/include/gnunet_reclaim_service.h 
b/src/include/gnunet_reclaim_service.h
index 8387c79b0..368058f56 100644
--- a/src/include/gnunet_reclaim_service.h
+++ b/src/include/gnunet_reclaim_service.h
@@ -92,7 +92,21 @@ struct GNUNET_RECLAIM_Ticket
  * @param ticket the ticket
  */
 typedef void (*GNUNET_RECLAIM_TicketCallback) (
-  void *cls, const struct GNUNET_RECLAIM_Ticket *ticket);
+  void *cls,
+  const struct GNUNET_RECLAIM_Ticket *ticket);
+
+/**
+ * Method called when a token has been issued.
+ * On success returns a ticket that can be given to a relying party
+ * in order for it retrive identity attributes
+ *
+ * @param cls closure
+ * @param ticket the ticket
+ */
+typedef void (*GNUNET_RECLAIM_IssueTicketCallback) (
+  void *cls,
+  const struct GNUNET_RECLAIM_Ticket *ticket,
+  const struct GNUNET_RECLAIM_PresentationList *presentations);
 
 
 /**
@@ -369,7 +383,7 @@ GNUNET_RECLAIM_ticket_issue (
   const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss,
   const struct GNUNET_CRYPTO_EcdsaPublicKey *rp,
   const struct GNUNET_RECLAIM_AttributeList *attrs,
-  GNUNET_RECLAIM_TicketCallback cb, void *cb_cls);
+  GNUNET_RECLAIM_IssueTicketCallback cb, void *cb_cls);
 
 
 /**
diff --git a/src/reclaim/gnunet-reclaim.c b/src/reclaim/gnunet-reclaim.c
index a59053f5f..ab281a645 100644
--- a/src/reclaim/gnunet-reclaim.c
+++ b/src/reclaim/gnunet-reclaim.c
@@ -227,7 +227,9 @@ do_cleanup (void *cls)
 
 
 static void
-ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
+ticket_issue_cb (void *cls,
+                 const struct GNUNET_RECLAIM_Ticket *ticket,
+                 const struct GNUNET_RECLAIM_PresentationList *presentations)
 {
   char *ticket_str;
 
@@ -456,6 +458,7 @@ iter_finished (void *cls)
     if (NULL == attr_to_delete)
     {
       fprintf (stdout, "No such attribute ``%s''\n", attr_delete);
+      GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
       return;
     }
     reclaim_op = GNUNET_RECLAIM_attribute_delete (reclaim_handle,
diff --git a/src/reclaim/gnunet-service-reclaim.c 
b/src/reclaim/gnunet-service-reclaim.c
index 30a84b3e8..d2cdc62a2 100644
--- a/src/reclaim/gnunet-service-reclaim.c
+++ b/src/reclaim/gnunet-service-reclaim.c
@@ -646,19 +646,33 @@ static void
 send_ticket_result (const struct IdpClient *client,
                     uint32_t r_id,
                     const struct GNUNET_RECLAIM_Ticket *ticket,
+                    const struct GNUNET_RECLAIM_PresentationList 
*presentations,
                     uint32_t success)
 {
   struct TicketResultMessage *irm;
   struct GNUNET_MQ_Envelope *env;
+  size_t pres_len = 0;
 
-  env = GNUNET_MQ_msg (irm,
-                       GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
+  if (NULL != presentations)
+  {
+    pres_len =
+      GNUNET_RECLAIM_presentation_list_serialize_get_size (presentations);
+  }
+  env = GNUNET_MQ_msg_extra (irm,
+                             pres_len,
+                             GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
   if (NULL != ticket)
   {
     irm->ticket = *ticket;
   }
   // TODO add success member
   irm->id = htonl (r_id);
+  irm->presentations_len = htons (pres_len);
+  if (NULL != presentations)
+  {
+    GNUNET_RECLAIM_presentation_list_serialize (presentations,
+                                                (char*) &irm[1]);
+  }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending TICKET_RESULT message\n");
   GNUNET_MQ_send (client->mq, env);
 }
@@ -669,12 +683,14 @@ send_ticket_result (const struct IdpClient *client,
  *
  * @param cls out ticket issue operation handle
  * @param ticket the issued ticket
+ * @param presentations newly created credential presentations (NULL on error)
  * @param success issue success status (GNUNET_OK if successful)
  * @param emsg error message (NULL of success is GNUNET_OK)
  */
 static void
 issue_ticket_result_cb (void *cls,
                         struct GNUNET_RECLAIM_Ticket *ticket,
+                        struct GNUNET_RECLAIM_PresentationList *presentations,
                         int32_t success,
                         const char *emsg)
 {
@@ -682,7 +698,7 @@ issue_ticket_result_cb (void *cls,
 
   if (GNUNET_OK != success)
   {
-    send_ticket_result (tio->client, tio->r_id, NULL, GNUNET_SYSERR);
+    send_ticket_result (tio->client, tio->r_id, NULL, NULL, GNUNET_SYSERR);
     GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head,
                                  tio->client->issue_op_tail,
                                  tio);
@@ -690,7 +706,8 @@ issue_ticket_result_cb (void *cls,
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error issuing ticket: %s\n", emsg);
     return;
   }
-  send_ticket_result (tio->client, tio->r_id, ticket, GNUNET_SYSERR);
+  send_ticket_result (tio->client, tio->r_id,
+                      ticket, presentations, GNUNET_SYSERR);
   GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head,
                                tio->client->issue_op_tail,
                                tio);
@@ -871,7 +888,7 @@ consume_result_cb (void *cls,
                              
GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT);
   crm->id = htonl (cop->r_id);
   crm->attrs_len = htons (attrs_len);
-  crm->pres_len = htons (pres_len);
+  crm->presentations_len = htons (pres_len);
   crm->identity = *identity;
   crm->result = htonl (success);
   data_tmp = (char *) &crm[1];
@@ -1152,7 +1169,7 @@ cred_add_cb (void *cls,
 
   buf_size = GNUNET_RECLAIM_credential_serialize_get_size (ash->credential);
   buf = GNUNET_malloc (buf_size);
-  GNUNET_RECLAIM_presentation_serialize (ash->credential, buf);
+  GNUNET_RECLAIM_credential_serialize (ash->credential, buf);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Storing new credential under `%s'.\n",
               label);
@@ -1611,8 +1628,8 @@ cred_delete_cont (void *cls, int32_t success, const char 
*emsg)
  * @dam message to check
  */
 static int
-check_cred_delete_message (void *cls,
-                                  const struct AttributeDeleteMessage *dam)
+check_credential_delete_message (void *cls,
+                                 const struct AttributeDeleteMessage *dam)
 {
   uint16_t size;
 
diff --git a/src/reclaim/gnunet-service-reclaim_tickets.c 
b/src/reclaim/gnunet-service-reclaim_tickets.c
index 18b173aaa..4dd8100f9 100644
--- a/src/reclaim/gnunet-service-reclaim_tickets.c
+++ b/src/reclaim/gnunet-service-reclaim_tickets.c
@@ -114,9 +114,9 @@ struct RECLAIM_TICKETS_ConsumeHandle
   struct GNUNET_RECLAIM_AttributeList *attrs;
 
   /**
-   * Credentials
+   * Presentations
    */
-  struct GNUNET_RECLAIM_CredentialList *credentials;
+  struct GNUNET_RECLAIM_PresentationList *presentations;
 
   /**
    * Lookup time
@@ -172,6 +172,11 @@ struct TicketIssueHandle
    */
   struct GNUNET_RECLAIM_AttributeList *attrs;
 
+  /**
+   * Presentations to add
+   */
+  struct GNUNET_RECLAIM_PresentationList *presentations;
+
   /**
    * Issuer Key
    */
@@ -981,8 +986,8 @@ cleanup_cth (struct RECLAIM_TICKETS_ConsumeHandle *cth)
 
   if (NULL != cth->attrs)
     GNUNET_RECLAIM_attribute_list_destroy (cth->attrs);
-  if (NULL != cth->credentials)
-    GNUNET_RECLAIM_credential_list_destroy (cth->credentials);
+  if (NULL != cth->presentations)
+    GNUNET_RECLAIM_presentation_list_destroy (cth->presentations);
   GNUNET_free (cth);
 }
 
@@ -1040,7 +1045,7 @@ process_parallel_lookup_result (void *cls,
     return; // Wait for more
   /* Else we are done */
   cth->cb (cth->cb_cls, &cth->ticket.identity,
-           cth->attrs, cth->credentials, GNUNET_OK, NULL);
+           cth->attrs, cth->presentations, GNUNET_OK, NULL);
   cleanup_cth (cth);
 }
 
@@ -1090,6 +1095,7 @@ lookup_authz_cb (void *cls,
   struct RECLAIM_TICKETS_ConsumeHandle *cth = cls;
   struct ParallelLookup *parallel_lookup;
   char *lbl;
+  struct GNUNET_RECLAIM_PresentationListEntry *ale;
 
   cth->lookup_request = NULL;
 
@@ -1113,13 +1119,12 @@ lookup_authz_cb (void *cls,
     switch (rd[i].record_type)
     {
     case GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION:
-      struct GNUNET_RECLAIM_CredentialListEntry *ale;
-      ale = GNUNET_new (struct GNUNET_RECLAIM_CredentialListEntry);
-      ale->credential =
-        GNUNET_RECLAIM_credential_deserialize (rd[i].data,
-                                               rd[i].data_size);
-      GNUNET_CONTAINER_DLL_insert (cth->credentials->list_head,
-                                   cth->credentials->list_tail,
+      ale = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
+      ale->presentation =
+        GNUNET_RECLAIM_presentation_deserialize (rd[i].data,
+                                                 rd[i].data_size);
+      GNUNET_CONTAINER_DLL_insert (cth->presentations->list_head,
+                                   cth->presentations->list_tail,
                                    ale);
       break;
     case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF:
@@ -1162,7 +1167,7 @@ lookup_authz_cb (void *cls,
    * No references found, return empty attribute list
    */
   cth->cb (cth->cb_cls, &cth->ticket.identity,
-           cth->attrs, cth->credentials, GNUNET_OK, NULL);
+           cth->attrs, NULL, GNUNET_OK, NULL);
   cleanup_cth (cth);
 }
 
@@ -1192,7 +1197,7 @@ RECLAIM_TICKETS_consume (const struct 
GNUNET_CRYPTO_EcdsaPrivateKey *id,
   cth->identity = *id;
   GNUNET_CRYPTO_ecdsa_key_get_public (&cth->identity, &cth->identity_pub);
   cth->attrs = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
-  cth->credentials = GNUNET_new (struct GNUNET_RECLAIM_CredentialList);
+  cth->presentations = GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
   cth->ticket = *ticket;
   cth->cb = cb;
   cth->cb_cls = cb_cls;
@@ -1230,8 +1235,8 @@ RECLAIM_TICKETS_consume_cancel (struct 
RECLAIM_TICKETS_ConsumeHandle *cth)
 
 
 /*******************************
-* Ticket issue
-*******************************/
+ * Ticket issue
+ *******************************/
 
 /**
  * Cleanup ticket consume handle
@@ -1264,11 +1269,15 @@ store_ticket_issue_cont (void *cls, int32_t success, 
const char *emsg)
   {
     handle->cb (handle->cb_cls,
                 &handle->ticket,
+                NULL,
                 GNUNET_SYSERR,
                 "Error storing AuthZ ticket in GNS");
     return;
   }
-  handle->cb (handle->cb_cls, &handle->ticket, GNUNET_OK, NULL);
+  handle->cb (handle->cb_cls,
+              &handle->ticket,
+              handle->presentations,
+              GNUNET_OK, NULL);
   cleanup_issue_handle (handle);
 }
 
@@ -1284,15 +1293,17 @@ static void
 issue_ticket (struct TicketIssueHandle *ih)
 {
   struct GNUNET_RECLAIM_AttributeListEntry *le;
+  struct GNUNET_RECLAIM_PresentationListEntry *ple;
   struct GNUNET_GNSRECORD_Data *attrs_record;
   char *label;
   int i;
+  int j;
   int attrs_count = 0;
 
   for (le = ih->attrs->list_head; NULL != le; le = le->next)
     attrs_count++;
 
-  // Worst case we have one credential per attribute
+  // Worst case we have one presentation per attribute
   attrs_record =
     GNUNET_malloc (2 * attrs_count * sizeof(struct GNUNET_GNSRECORD_Data));
   i = 0;
@@ -1309,31 +1320,65 @@ issue_ticket (struct TicketIssueHandle *ih)
     i++;
     if (GNUNET_NO == GNUNET_RECLAIM_id_is_zero (&le->attribute->credential))
     {
-      struct GNUNET_RECLAIM_Presentation *pres;
-      int j;
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Attribute is backed by credential. Adding...\n");
+      struct GNUNET_RECLAIM_Presentation *pres = NULL;
       for (j = 0; j < i; j++)
       {
         if (attrs_record[j].record_type
             != GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION)
           continue;
-        pres = attrs_record[j].data;
-        if (0 == memcmp (pres->credential_id,
+        pres = GNUNET_RECLAIM_presentation_deserialize (attrs_record[j].data,
+                                                        attrs_record[j].
+                                                        data_size);
+        if (NULL == pres)
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                      "Failed to deserialize presentation\n");
+          continue;
+        }
+        if (0 == memcmp (&pres->credential_id,
                          &le->attribute->credential,
                          sizeof (le->attribute->credential)))
           break;
+        GNUNET_free (pres);
+        pres = NULL;
       }
-      if (j < i)
+      if (NULL != pres)
+      {
+        GNUNET_free (pres);
         continue; // Skip as we have already added this credential 
presentation.
-      /**
-       * FIXME: Create a new presentation from the credential.
-       */
-      attrs_record[i].data = &le->attribute->credential;
-      attrs_record[i].data_size = sizeof(le->attribute->credential);
-      attrs_record[i].expiration_time = ticket_refresh_interval.rel_value_us;
-      attrs_record[i].record_type =
-        GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION;
-      attrs_record[i].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
-      i++;
+      }
+      for (ple = ih->presentations->list_head; NULL != ple; ple = ple->next)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "Checking presentation....\n");
+
+        if (0 != memcmp (&le->attribute->credential,
+                         &ple->presentation->credential_id,
+                         sizeof (le->attribute->credential)))
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                      "Presentation does not match credential ID.\n");
+          continue;
+        }
+        char *pres_buf;
+        size_t pres_size;
+        pres_size =
+          GNUNET_RECLAIM_presentation_serialize_get_size (ple->presentation);
+        pres_buf = GNUNET_malloc (pres_size);
+        GNUNET_RECLAIM_presentation_serialize (ple->presentation,
+                                               pres_buf);
+        attrs_record[i].data = pres_buf;
+        attrs_record[i].data_size = pres_size;
+        attrs_record[i].expiration_time =
+          ticket_refresh_interval.rel_value_us;
+        attrs_record[i].record_type =
+          GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION;
+        attrs_record[i].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
+        i++;
+        break;
+      }
     }
   }
   attrs_record[i].data = &ih->ticket;
@@ -1355,14 +1400,23 @@ issue_ticket (struct TicketIssueHandle *ih)
                                               attrs_record,
                                               &store_ticket_issue_cont,
                                               ih);
+  for (j = 0; j > i; j++)
+  {
+    if (attrs_record[j].record_type
+        != GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION)
+      continue;
+    // Yes, we are allowed to do this because we allocated it above
+    char *ptr = (char*) attrs_record[j].data;
+    GNUNET_free (ptr);
+  }
   GNUNET_free (attrs_record);
   GNUNET_free (label);
 }
 
 
 /*************************************************
-* Ticket iteration (finding a specific ticket)
-*************************************************/
+ * Ticket iteration (finding a specific ticket)
+ *************************************************/
 
 
 /**
@@ -1378,6 +1432,7 @@ filter_tickets_error_cb (void *cls)
   tih->ns_it = NULL;
   tih->cb (tih->cb_cls,
            &tih->ticket,
+           NULL,
            GNUNET_SYSERR,
            "Error storing AuthZ ticket in GNS");
   cleanup_issue_handle (tih);
@@ -1406,11 +1461,12 @@ filter_tickets_cb (void *cls,
   struct TicketIssueHandle *tih = cls;
   struct GNUNET_RECLAIM_Ticket *ticket = NULL;
   struct GNUNET_RECLAIM_Presentation *pres;
-
-  // figure out the number of requested attributes
+  struct GNUNET_RECLAIM_PresentationList *ticket_presentations;
+  struct GNUNET_RECLAIM_Credential *cred;
+  struct GNUNET_RECLAIM_PresentationListEntry *ple;
   struct GNUNET_RECLAIM_AttributeListEntry *le;
   unsigned int attr_cnt = 0;
-  unsigned int cred_cnt = 0;
+  unsigned int pres_cnt = 0;
 
   for (le = tih->attrs->list_head; NULL != le; le = le->next)
   {
@@ -1422,6 +1478,7 @@ filter_tickets_cb (void *cls,
   // ticket search
   unsigned int found_attrs_cnt = 0;
   unsigned int found_pres_cnt = 0;
+  ticket_presentations = GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
 
   for (int i = 0; i < rd_count; i++)
   {
@@ -1450,15 +1507,65 @@ filter_tickets_cb (void *cls,
           found_attrs_cnt++;
       }
     }
+    if (GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL == rd[i].record_type)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Found credential...\n");
+
+      for (le = tih->attrs->list_head; NULL != le; le = le->next)
+      {
+        cred = GNUNET_RECLAIM_credential_deserialize (rd[i].data,
+                                                      rd[i].data_size);
+        if (GNUNET_YES != GNUNET_RECLAIM_id_is_equal (&cred->id,
+                                                      
&le->attribute->credential))
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                      "No match.\n");
+          GNUNET_free (cred);
+          continue;
+        }
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "Match, creating presentation...\n");
+        if (GNUNET_OK != GNUNET_RECLAIM_credential_get_presentation (
+              cred,
+              tih->attrs,
+              &pres))
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                      "Unable to retrieve presentation from credential\n");
+          GNUNET_free (cred);
+          continue;
+        }
+        ple = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
+        ple->presentation = pres;
+        GNUNET_CONTAINER_DLL_insert (tih->presentations->list_head,
+                                     tih->presentations->list_tail,
+                                     ple);
+        GNUNET_free (cred);
+      }
+    }
     if (GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION == rd[i].record_type)
     {
       for (le = tih->attrs->list_head; NULL != le; le = le->next)
       {
-        pres = rd[i].data;
-        if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (pres->credential_id,
+        pres = GNUNET_RECLAIM_presentation_deserialize (rd[i].data,
+                                                        rd[i].data_size);
+        if (NULL == pres)
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                      "Failed to deserialize presentation\n");
+          continue;
+        }
+        if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (&pres->credential_id,
                                                       
&le->attribute->credential))
+        {
           found_pres_cnt++;
-        // FIXME should we store credentials here for later use??
+          ple = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
+          ple->presentation = pres;
+          GNUNET_CONTAINER_DLL_insert (ticket_presentations->list_head,
+                                       ticket_presentations->list_tail,
+                                       ple);
+        }
       }
     }
   }
@@ -1472,7 +1579,8 @@ filter_tickets_cb (void *cls,
       (NULL != ticket))
   {
     GNUNET_NAMESTORE_zone_iteration_stop (tih->ns_it);
-    tih->cb (tih->cb_cls, &tih->ticket, GNUNET_OK, NULL);
+    tih->cb (tih->cb_cls, &tih->ticket, ticket_presentations, GNUNET_OK, NULL);
+    GNUNET_RECLAIM_presentation_list_destroy (ticket_presentations);
     cleanup_issue_handle (tih);
     return;
   }
@@ -1524,6 +1632,7 @@ RECLAIM_TICKETS_issue (const struct 
GNUNET_CRYPTO_EcdsaPrivateKey *identity,
   tih->cb = cb;
   tih->cb_cls = cb_cls;
   tih->attrs = GNUNET_RECLAIM_attribute_list_dup (attrs);
+  tih->presentations = GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
   tih->identity = *identity;
   tih->ticket.audience = *audience;
 
@@ -1541,8 +1650,8 @@ RECLAIM_TICKETS_issue (const struct 
GNUNET_CRYPTO_EcdsaPrivateKey *identity,
 
 
 /************************************
-* Ticket iteration
-************************************/
+ * Ticket iteration
+ ************************************/
 
 /**
  * Cleanup ticket iterator
diff --git a/src/reclaim/gnunet-service-reclaim_tickets.h 
b/src/reclaim/gnunet-service-reclaim_tickets.h
index 404b9c837..0dd790fc7 100644
--- a/src/reclaim/gnunet-service-reclaim_tickets.h
+++ b/src/reclaim/gnunet-service-reclaim_tickets.h
@@ -113,6 +113,7 @@ typedef void (*RECLAIM_TICKETS_TicketIter) (
  *
  * @param cls closure
  * @param ticket the ticket
+ * @param presentations new presentations for ticket (NULL on error)
  * @param success #GNUNET_SYSERR on failure (including timeout/queue
  * drop/failure to validate) #GNUNET_OK on success
  * @param emsg NULL on success, otherwise an error message
@@ -120,6 +121,7 @@ typedef void (*RECLAIM_TICKETS_TicketIter) (
 typedef void (*RECLAIM_TICKETS_TicketResult) (
   void *cls,
   struct GNUNET_RECLAIM_Ticket *ticket,
+  struct GNUNET_RECLAIM_PresentationList *presentations,
   int32_t success,
   const char *emsg);
 
@@ -129,7 +131,8 @@ typedef void (*RECLAIM_TICKETS_TicketResult) (
  *
  * @param cls closure
  * @param identity the issuer of the ticket/attributes
- * @param l attribute list retrieved through ticket
+ * @param attributes attribute list retrieved through ticket
+ * @param presentations attribute presentations (may be NULL)
  * @param success GNUNET_OK on success
  * @param emsg error message (NULL on success)
  */
@@ -137,7 +140,7 @@ typedef void (*RECLAIM_TICKETS_ConsumeCallback) (
   void *cls,
   const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
   const struct GNUNET_RECLAIM_AttributeList *attributes,
-  const struct GNUNET_RECLAIM_CredentialList *credentials,
+  const struct GNUNET_RECLAIM_PresentationList *presentations,
   int32_t success,
   const char *emsg);
 
diff --git a/src/reclaim/json_reclaim.c b/src/reclaim/json_reclaim.c
index c8b944326..8a3479b8a 100644
--- a/src/reclaim/json_reclaim.c
+++ b/src/reclaim/json_reclaim.c
@@ -335,16 +335,16 @@ parse_credential (void *cls, json_t *root, struct 
GNUNET_JSON_Specification *spe
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Credential value invalid!\n");
     return GNUNET_SYSERR;
   }
-  attr = GNUNET_RECLAIM_credential_new (name_str, type, data, data_size);
+  cred = GNUNET_RECLAIM_credential_new (name_str, type, data, data_size);
   if ((NULL == id_str) || (0 == strlen (id_str)))
-    memset (&attr->id, 0, sizeof (attr->id));
+    memset (&cred->id, 0, sizeof (cred->id));
   else
     GNUNET_STRINGS_string_to_data (id_str,
                                    strlen (id_str),
-                                   &attr->id,
-                                   sizeof(attr->id));
+                                   &cred->id,
+                                   sizeof(cred->id));
 
-  *(struct GNUNET_RECLAIM_Credential **) spec->ptr = attr;
+  *(struct GNUNET_RECLAIM_Credential **) spec->ptr = cred;
   return GNUNET_OK;
 }
 
@@ -383,7 +383,7 @@ GNUNET_RECLAIM_JSON_spec_credential (struct
                                            .cleaner = &clean_credential,
                                            .cls = NULL,
                                            .field = NULL,
-                                           .ptr = attr,
+                                           .ptr = cred,
                                            .ptr_size = 0,
                                            .size_ptr = NULL };
 
diff --git a/src/reclaim/json_reclaim.h b/src/reclaim/json_reclaim.h
index 8911cf92d..613ddf873 100644
--- a/src/reclaim/json_reclaim.h
+++ b/src/reclaim/json_reclaim.h
@@ -54,4 +54,4 @@ GNUNET_RECLAIM_JSON_spec_ticket (struct GNUNET_RECLAIM_Ticket 
**ticket);
     * @return JSON Specification
     */
 struct GNUNET_JSON_Specification
-GNUNET_RECLAIM_JSON_spec_credential (struct  GNUNET_RECLAIM_Attestation 
**cred);
+GNUNET_RECLAIM_JSON_spec_credential (struct  GNUNET_RECLAIM_Credential **cred);
diff --git a/src/reclaim/oidc_helper.c b/src/reclaim/oidc_helper.c
index 9c7e79c41..b307a358c 100644
--- a/src/reclaim/oidc_helper.c
+++ b/src/reclaim/oidc_helper.c
@@ -156,8 +156,8 @@ fix_base64 (char *str)
 
 static json_t*
 generate_userinfo_json(const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
-                       struct GNUNET_RECLAIM_AttributeList *attrs,
-                       struct GNUNET_RECLAIM_PresentationList *presentations)
+                       const struct GNUNET_RECLAIM_AttributeList *attrs,
+                       const struct GNUNET_RECLAIM_PresentationList 
*presentations)
 {
   struct GNUNET_RECLAIM_AttributeListEntry *le;
   struct GNUNET_RECLAIM_PresentationListEntry *ple;
@@ -296,8 +296,8 @@ generate_userinfo_json(const struct 
GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
  */
 char *
 OIDC_generate_userinfo (const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
-                        struct GNUNET_RECLAIM_AttributeList *attrs,
-                        struct GNUNET_RECLAIM_PresentationList *presentations)
+                        const struct GNUNET_RECLAIM_AttributeList *attrs,
+                        const struct GNUNET_RECLAIM_PresentationList 
*presentations)
 {
   char *body_str;
   json_t* body = generate_userinfo_json (sub_key,
@@ -323,8 +323,8 @@ OIDC_generate_userinfo (const struct 
GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
 char *
 OIDC_generate_id_token (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
                         const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
-                        struct GNUNET_RECLAIM_AttributeList *attrs,
-                        struct GNUNET_RECLAIM_PresentationList *presentations,
+                        const struct GNUNET_RECLAIM_AttributeList *attrs,
+                        const struct GNUNET_RECLAIM_PresentationList 
*presentations,
                         const struct GNUNET_TIME_Relative *expiration_time,
                         const char *nonce,
                         const char *secret_key)
@@ -440,8 +440,8 @@ OIDC_generate_id_token (const struct 
GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
 char *
 OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
                        const struct GNUNET_RECLAIM_Ticket *ticket,
-                       struct GNUNET_RECLAIM_AttributeList *attrs,
-                       struct GNUNET_RECLAIM_PresentationList *presentations,
+                       const struct GNUNET_RECLAIM_AttributeList *attrs,
+                       const struct GNUNET_RECLAIM_PresentationList 
*presentations,
                        const char *nonce_str,
                        const char *code_challenge)
 {
@@ -596,7 +596,7 @@ OIDC_parse_authz_code (const struct 
GNUNET_CRYPTO_EcdsaPublicKey *audience,
   struct GNUNET_CRYPTO_EcdsaSignature *signature;
   uint32_t code_challenge_len;
   uint32_t attrs_ser_len;
-  uint32_t presentations_ser_len;
+  uint32_t pres_ser_len;
   size_t plaintext_len;
   size_t code_payload_len;
   uint32_t nonce_len = 0;
@@ -702,8 +702,8 @@ OIDC_parse_authz_code (const struct 
GNUNET_CRYPTO_EcdsaPublicKey *audience,
   presentations_ser = ((char*) attrs_ser) + attrs_ser_len;
   pres_ser_len = ntohl (params->pres_list_len);
   *presentations =
-    GNUNET_RECLAIM_presentations_list_deserialize (presentations_ser,
-                                                   pres_ser_len);
+    GNUNET_RECLAIM_presentation_list_deserialize (presentations_ser,
+                                                  pres_ser_len);
 
   GNUNET_free (code_payload);
   return GNUNET_OK;
diff --git a/src/reclaim/oidc_helper.h b/src/reclaim/oidc_helper.h
index 789a2acc7..10a6f3d1f 100644
--- a/src/reclaim/oidc_helper.h
+++ b/src/reclaim/oidc_helper.h
@@ -52,8 +52,8 @@
 char*
 OIDC_generate_id_token (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
                    const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
-                   struct GNUNET_RECLAIM_AttributeList *attrs,
-                   struct GNUNET_RECLAIM_PresentationList *presentations,
+                   const struct GNUNET_RECLAIM_AttributeList *attrs,
+                   const struct GNUNET_RECLAIM_PresentationList *presentations,
                    const struct GNUNET_TIME_Relative *expiration_time,
                    const char *nonce,
                    const char *secret_key);
@@ -73,8 +73,8 @@ OIDC_generate_id_token (const struct 
GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
 char*
 OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
                        const struct GNUNET_RECLAIM_Ticket *ticket,
-                       struct GNUNET_RECLAIM_AttributeList *attrs,
-                       struct GNUNET_RECLAIM_PresentationList *presentations,
+                       const struct GNUNET_RECLAIM_AttributeList *attrs,
+                       const struct GNUNET_RECLAIM_PresentationList 
*presentations,
                        const char *nonce,
                        const char *code_challenge);
 
@@ -139,8 +139,8 @@ OIDC_access_token_parse (const char* token,
  * @return GNUNET_YES if attribute is implcitly requested
  */
 enum GNUNET_GenericReturnValue
-OIDC_check_scopes_for_claim_request (const char*scopes,
-                                     const char*attr);
+OIDC_check_scopes_for_claim_request (const char *scopes,
+                                     const char *attr);
 
 
 /**
@@ -153,7 +153,7 @@ OIDC_check_scopes_for_claim_request (const char*scopes,
  */
 char *
 OIDC_generate_userinfo (const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
-                        struct GNUNET_RECLAIM_AttributeList *attrs,
-                        struct GNUNET_RECLAIM_PresentationList *presentations);
+                        const struct GNUNET_RECLAIM_AttributeList *attrs,
+                        const struct GNUNET_RECLAIM_PresentationList 
*presentations);
 
 #endif
diff --git a/src/reclaim/plugin_gnsrecord_reclaim.c 
b/src/reclaim/plugin_gnsrecord_reclaim.c
index b91e123a3..60c49fd6a 100644
--- a/src/reclaim/plugin_gnsrecord_reclaim.c
+++ b/src/reclaim/plugin_gnsrecord_reclaim.c
@@ -51,8 +51,8 @@ value_to_string (void *cls, uint32_t type, const void *data, 
size_t data_size)
   case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF:
   case GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET:
   case GNUNET_GNSRECORD_TYPE_RECLAIM_MASTER:
-  case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION:
-  case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION_REF:
+  case GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL:
+  case GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION:
     return GNUNET_STRINGS_data_to_string_alloc (data, data_size);
 
   default:
@@ -89,8 +89,8 @@ string_to_value (void *cls, uint32_t type, const char *s, 
void **data,
   case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF:
   case GNUNET_GNSRECORD_TYPE_RECLAIM_MASTER:
   case GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET:
-  case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION:
-  case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION_REF:
+  case GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL:
+  case GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION:
     return GNUNET_STRINGS_string_to_data (s, strlen (s), *data, *data_size);
 
   default:
@@ -110,8 +110,8 @@ static struct
 } name_map[] = {
   { "RECLAIM_ATTRIBUTE", GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE },
   { "RECLAIM_ATTRIBUTE_REF", GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF },
-  { "RECLAIM_ATTESTATION", GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION },
-  { "RECLAIM_ATTESTATION_REF", GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION_REF },
+  { "RECLAIM_CREDENTIAL", GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL },
+  { "RECLAIM_PRESENTATION", GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION },
   { "RECLAIM_MASTER", GNUNET_GNSRECORD_TYPE_RECLAIM_MASTER },
   { "RECLAIM_OIDC_CLIENT", GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_CLIENT },
   { "RECLAIM_OIDC_REDIRECT", GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT },
diff --git a/src/reclaim/plugin_reclaim_credential_jwt.c 
b/src/reclaim/plugin_reclaim_credential_jwt.c
index 38effcf78..148865223 100644
--- a/src/reclaim/plugin_reclaim_credential_jwt.c
+++ b/src/reclaim/plugin_reclaim_credential_jwt.c
@@ -48,7 +48,7 @@ jwt_value_to_string (void *cls,
 {
   switch (type)
   {
-  case GNUNET_RECLAIM_credential_TYPE_JWT:
+  case GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT:
     return GNUNET_strndup (data, data_size);
 
   default:
@@ -79,7 +79,7 @@ jwt_string_to_value (void *cls,
     return GNUNET_SYSERR;
   switch (type)
   {
-  case GNUNET_RECLAIM_credential_TYPE_JWT:
+  case GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT:
     *data = GNUNET_strdup (s);
     *data_size = strlen (s);
     return GNUNET_OK;
@@ -98,8 +98,8 @@ static struct
 {
   const char *name;
   uint32_t number;
-} jwt_cred_name_map[] = { { "JWT", GNUNET_RECLAIM_credential_TYPE_JWT },
-                            { NULL, UINT32_MAX } };
+} jwt_cred_name_map[] = { { "JWT", GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT },
+                          { NULL, UINT32_MAX } };
 
 /**
    * Convert a type name to the corresponding number.
@@ -135,8 +135,8 @@ jwt_number_to_typename (void *cls, uint32_t type)
 
   i = 0;
   while ((NULL != jwt_cred_name_map[i].name) && (type !=
-                                                   jwt_cred_name_map[i].
-                                                   number))
+                                                 jwt_cred_name_map[i].
+                                                 number))
     i++;
   return jwt_cred_name_map[i].name;
 }
@@ -151,7 +151,7 @@ jwt_number_to_typename (void *cls, uint32_t type)
  */
 struct GNUNET_RECLAIM_AttributeList *
 jwt_parse_attributes (void *cls,
-                      const struct GNUNET_RECLAIM_Credential *cred)
+                      const char *data)
 {
   char *jwt_string;
   struct GNUNET_RECLAIM_AttributeList *attrs;
@@ -162,17 +162,14 @@ jwt_parse_attributes (void *cls,
   json_t *json_val;
   json_error_t *json_err = NULL;
 
-  /* GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%s\n", cred->data); (not OK: 
'data' is not defined as 0-terminated text, but binary) */
-  if (GNUNET_RECLAIM_credential_TYPE_JWT != cred->type)
-    return NULL;
   attrs = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
 
-  jwt_string = GNUNET_strdup (cred->data);
+  jwt_string = GNUNET_strdup (data);
   const char *jwt_body = strtok (jwt_string, delim);
   jwt_body = strtok (NULL, delim);
   GNUNET_STRINGS_base64url_decode (jwt_body, strlen (jwt_body),
                                    (void **) &decoded_jwt);
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", decoded_jwt);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Decoded JWT: %s\n", decoded_jwt);
   GNUNET_assert (NULL != decoded_jwt);
   json_val = json_loads (decoded_jwt, JSON_DECODE_ANY, json_err);
   const char *key;
@@ -202,6 +199,36 @@ jwt_parse_attributes (void *cls,
 }
 
 
+/**
+ * Parse a JWT and return the respective claim value as Attribute
+ *
+ * @param cls the plugin
+ * @param cred the jwt credential
+ * @return a GNUNET_RECLAIM_Attribute, containing the new value
+ */
+struct GNUNET_RECLAIM_AttributeList *
+jwt_parse_attributes_c (void *cls,
+                        const struct GNUNET_RECLAIM_Credential *cred)
+{
+  return jwt_parse_attributes (cls, cred->data);
+}
+
+
+/**
+ * Parse a JWT and return the respective claim value as Attribute
+ *
+ * @param cls the plugin
+ * @param cred the jwt credential
+ * @return a GNUNET_RECLAIM_Attribute, containing the new value
+ */
+struct GNUNET_RECLAIM_AttributeList *
+jwt_parse_attributes_p (void *cls,
+                        const struct GNUNET_RECLAIM_Presentation *cred)
+{
+  return jwt_parse_attributes (cls, cred->data);
+}
+
+
 /**
  * Parse a JWT and return the issuer
  *
@@ -211,7 +238,7 @@ jwt_parse_attributes (void *cls,
  */
 char *
 jwt_get_issuer (void *cls,
-                const struct GNUNET_RECLAIM_Credential *cred)
+                const char *data)
 {
   const char *jwt_body;
   char *jwt_string;
@@ -223,9 +250,7 @@ jwt_get_issuer (void *cls,
   json_t *json_val;
   json_error_t *json_err = NULL;
 
-  if (GNUNET_RECLAIM_credential_TYPE_JWT != cred->type)
-    return NULL;
-  jwt_string = GNUNET_strdup (cred->data);
+  jwt_string = GNUNET_strdup (data);
   jwt_body = strtok (jwt_string, delim);
   jwt_body = strtok (NULL, delim);
   GNUNET_STRINGS_base64url_decode (jwt_body, strlen (jwt_body),
@@ -240,6 +265,40 @@ jwt_get_issuer (void *cls,
 }
 
 
+/**
+ * Parse a JWT and return the issuer
+ *
+ * @param cls the plugin
+ * @param cred the jwt credential
+ * @return a string, containing the isser
+ */
+char *
+jwt_get_issuer_c (void *cls,
+                  const struct GNUNET_RECLAIM_Credential *cred)
+{
+  if (GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT != cred->type)
+    return NULL;
+  return jwt_get_issuer (cls, cred->data);
+}
+
+
+/**
+ * Parse a JWT and return the issuer
+ *
+ * @param cls the plugin
+ * @param cred the jwt credential
+ * @return a string, containing the isser
+ */
+char *
+jwt_get_issuer_p (void *cls,
+                  const struct GNUNET_RECLAIM_Presentation *cred)
+{
+  if (GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT != cred->type)
+    return NULL;
+  return jwt_get_issuer (cls, cred->data);
+}
+
+
 /**
  * Parse a JWT and return the expiration
  *
@@ -249,7 +308,7 @@ jwt_get_issuer (void *cls,
  */
 int
 jwt_get_expiration (void *cls,
-                    const struct GNUNET_RECLAIM_Credential *cred,
+                    const char *data,
                     struct GNUNET_TIME_Absolute *exp)
 {
   const char *jwt_body;
@@ -261,9 +320,7 @@ jwt_get_expiration (void *cls,
   json_t *json_val;
   json_error_t *json_err = NULL;
 
-  if (GNUNET_RECLAIM_credential_TYPE_JWT != cred->type)
-    return GNUNET_NO;
-  jwt_string = GNUNET_strdup (cred->data);
+  jwt_string = GNUNET_strdup (data);
   jwt_body = strtok (jwt_string, delim);
   jwt_body = strtok (NULL, delim);
   GNUNET_STRINGS_base64url_decode (jwt_body, strlen (jwt_body),
@@ -278,6 +335,54 @@ jwt_get_expiration (void *cls,
 }
 
 
+/**
+ * Parse a JWT and return the expiration
+ *
+ * @param cls the plugin
+ * @param cred the jwt credential
+ * @return a string, containing the isser
+ */
+int
+jwt_get_expiration_c (void *cls,
+                      const struct GNUNET_RECLAIM_Credential *cred,
+                      struct GNUNET_TIME_Absolute *exp)
+{
+  return jwt_get_expiration (cls, cred->data, exp);
+}
+
+
+/**
+ * Parse a JWT and return the expiration
+ *
+ * @param cls the plugin
+ * @param cred the jwt credential
+ * @return a string, containing the isser
+ */
+int
+jwt_get_expiration_p (void *cls,
+                      const struct GNUNET_RECLAIM_Presentation *cred,
+                      struct GNUNET_TIME_Absolute *exp)
+{
+  return jwt_get_expiration (cls, cred->data, exp);
+}
+
+
+int
+jwt_create_presentation (void *cls,
+                         const struct GNUNET_RECLAIM_Credential *cred,
+                         const struct GNUNET_RECLAIM_AttributeList *attrs,
+                         struct GNUNET_RECLAIM_Presentation **pres)
+{
+  // FIXME sanity checks??
+  if (GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT != cred->type)
+    return GNUNET_NO;
+  *pres = GNUNET_RECLAIM_presentation_new (GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT,
+                                           cred->data,
+                                           cred->data_size);
+  return GNUNET_OK;
+}
+
+
 /**
  * Entry point for the plugin.
  *
@@ -294,9 +399,17 @@ libgnunet_plugin_reclaim_credential_jwt_init (void *cls)
   api->string_to_value = &jwt_string_to_value;
   api->typename_to_number = &jwt_typename_to_number;
   api->number_to_typename = &jwt_number_to_typename;
-  api->get_attributes = &jwt_parse_attributes;
-  api->get_issuer = &jwt_get_issuer;
-  api->get_expiration = &jwt_get_expiration;
+  api->get_attributes = &jwt_parse_attributes_c;
+  api->get_issuer = &jwt_get_issuer_c;
+  api->get_expiration = &jwt_get_expiration_c;
+  api->value_to_string_p = &jwt_value_to_string;
+  api->string_to_value_p = &jwt_string_to_value;
+  api->typename_to_number_p = &jwt_typename_to_number;
+  api->number_to_typename_p = &jwt_number_to_typename;
+  api->get_attributes_p = &jwt_parse_attributes_p;
+  api->get_issuer_p = &jwt_get_issuer_p;
+  api->get_expiration_p = &jwt_get_expiration_p;
+  api->create_presentation = &jwt_create_presentation;
   return api;
 }
 
diff --git a/src/reclaim/plugin_rest_openid_connect.c 
b/src/reclaim/plugin_rest_openid_connect.c
index 5ae6565af..5b0bb2b6f 100644
--- a/src/reclaim/plugin_rest_openid_connect.c
+++ b/src/reclaim/plugin_rest_openid_connect.c
@@ -439,10 +439,14 @@ struct RequestHandle
   struct GNUNET_RECLAIM_AttributeList *attr_userinfo_list;
 
   /**
-   * Credential list
+   * Credentials
    */
-  struct GNUNET_RECLAIM_CredentialList *creds_list;
+  struct GNUNET_RECLAIM_CredentialList *credentials;
 
+  /**
+   * Presentations
+   */
+  struct GNUNET_RECLAIM_PresentationList *presentations;
 
   /**
    * IDENTITY Operation
@@ -590,8 +594,10 @@ cleanup_handle (struct RequestHandle *handle)
     GNUNET_RECLAIM_attribute_list_destroy (handle->attr_idtoken_list);
   if (NULL!=handle->attr_userinfo_list)
     GNUNET_RECLAIM_attribute_list_destroy (handle->attr_userinfo_list);
-  if (NULL!=handle->creds_list)
-    GNUNET_RECLAIM_credential_list_destroy (handle->creds_list);
+  if (NULL!=handle->credentials)
+    GNUNET_RECLAIM_credential_list_destroy (handle->credentials);
+  if (NULL!=handle->presentations)
+    GNUNET_RECLAIM_presentation_list_destroy (handle->presentations);
   GNUNET_CONTAINER_DLL_remove (requests_head,
                                requests_tail,
                                handle);
@@ -934,7 +940,9 @@ oidc_iteration_error (void *cls)
  * parameter. Otherwise redirects with error
  */
 static void
-oidc_ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
+oidc_ticket_issue_cb (void *cls,
+                      const struct GNUNET_RECLAIM_Ticket *ticket,
+                      const struct GNUNET_RECLAIM_PresentationList *pres)
 {
   struct RequestHandle *handle = cls;
   struct MHD_Response *resp;
@@ -957,7 +965,7 @@ oidc_ticket_issue_cb (void *cls, const struct 
GNUNET_RECLAIM_Ticket *ticket)
   code_string = OIDC_build_authz_code (&handle->priv_key,
                                        &handle->ticket,
                                        handle->attr_idtoken_list,
-                                       handle->creds_list,
+                                       pres,
                                        handle->oidc->nonce,
                                        handle->oidc->code_challenge);
   if ((NULL != handle->redirect_prefix) && (NULL != handle->redirect_suffix) &&
@@ -1086,7 +1094,7 @@ oidc_cred_collect (void *cls,
   struct GNUNET_RECLAIM_AttributeListEntry *le;
   struct GNUNET_RECLAIM_CredentialListEntry *ale;
 
-  for (ale = handle->creds_list->list_head; NULL != ale; ale = ale->next)
+  for (ale = handle->credentials->list_head; NULL != ale; ale = ale->next)
   {
     if (GNUNET_NO == GNUNET_RECLAIM_id_is_equal (&ale->credential->id,
                                                  &cred->id))
@@ -1107,8 +1115,8 @@ oidc_cred_collect (void *cls,
                                                      cred->type,
                                                      cred->data,
                                                      cred->data_size);
-    GNUNET_CONTAINER_DLL_insert (handle->creds_list->list_head,
-                                 handle->creds_list->list_tail,
+    GNUNET_CONTAINER_DLL_insert (handle->credentials->list_head,
+                                 handle->credentials->list_tail,
                                  ale);
   }
   GNUNET_RECLAIM_get_credentials_next (handle->cred_it);
@@ -1129,7 +1137,7 @@ oidc_attr_collect_finished_cb (void *cls)
     GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
     return;
   }
-  handle->creds_list = GNUNET_new (struct GNUNET_RECLAIM_CredentialList);
+  handle->credentials = GNUNET_new (struct GNUNET_RECLAIM_CredentialList);
   handle->cred_it =
     GNUNET_RECLAIM_get_credentials_start (idp,
                                           &handle->priv_key,
@@ -1982,7 +1990,7 @@ token_endpoint (struct GNUNET_REST_RequestHandle 
*con_handle,
   const struct EgoEntry *ego_entry;
   struct GNUNET_TIME_Relative expiration_time;
   struct GNUNET_RECLAIM_AttributeList *cl = NULL;
-  struct GNUNET_RECLAIM_CredentialList *al = NULL;
+  struct GNUNET_RECLAIM_PresentationList *pl = NULL;
   struct GNUNET_RECLAIM_Ticket ticket;
   struct GNUNET_CRYPTO_EcdsaPublicKey cid;
   struct GNUNET_HashCode cache_key;
@@ -2068,7 +2076,7 @@ token_endpoint (struct GNUNET_REST_RequestHandle 
*con_handle,
 
   // decode code
   if (GNUNET_OK != OIDC_parse_authz_code (&cid, code, code_verifier, &ticket,
-                                          &cl, &al, &nonce))
+                                          &cl, &pl, &nonce))
   {
     handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST);
     handle->edesc = GNUNET_strdup ("invalid code");
@@ -2108,7 +2116,7 @@ token_endpoint (struct GNUNET_REST_RequestHandle 
*con_handle,
   id_token = OIDC_generate_id_token (&ticket.audience,
                                      &ticket.identity,
                                      cl,
-                                     al,
+                                     pl,
                                      &expiration_time,
                                      (NULL != nonce) ? nonce : NULL,
                                      jwt_secret);
@@ -2124,7 +2132,7 @@ token_endpoint (struct GNUNET_REST_RequestHandle 
*con_handle,
   MHD_add_response_header (resp, "Content-Type", "application/json");
   handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
   GNUNET_RECLAIM_attribute_list_destroy (cl);
-  GNUNET_RECLAIM_credential_list_destroy (al);
+  GNUNET_RECLAIM_presentation_list_destroy (pl);
   GNUNET_free (access_token);
   GNUNET_free (json_response);
   GNUNET_free (id_token);
@@ -2139,11 +2147,11 @@ static void
 consume_ticket (void *cls,
                 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
                 const struct GNUNET_RECLAIM_Attribute *attr,
-                const struct GNUNET_RECLAIM_Credential *cred)
+                const struct GNUNET_RECLAIM_Presentation *pres)
 {
   struct RequestHandle *handle = cls;
   struct GNUNET_RECLAIM_AttributeListEntry *ale;
-  struct GNUNET_RECLAIM_CredentialListEntry *atle;
+  struct GNUNET_RECLAIM_PresentationListEntry *atle;
   struct MHD_Response *resp;
   char *result_str;
   handle->idp_op = NULL;
@@ -2152,7 +2160,7 @@ consume_ticket (void *cls,
   {
     result_str = OIDC_generate_userinfo (&handle->ticket.identity,
                                          handle->attr_userinfo_list,
-                                         handle->creds_list);
+                                         handle->presentations);
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Userinfo: %s\n", result_str);
     resp = GNUNET_REST_create_response (result_str);
     handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
@@ -2172,25 +2180,25 @@ consume_ticket (void *cls,
   GNUNET_CONTAINER_DLL_insert (handle->attr_userinfo_list->list_head,
                                handle->attr_userinfo_list->list_tail,
                                ale);
-  if (NULL == cred)
+  if (NULL == pres)
     return;
-  for (atle = handle->creds_list->list_head; NULL != atle; atle = atle->next)
+  for (atle = handle->presentations->list_head;
+       NULL != atle; atle = atle->next)
   {
-    if (GNUNET_NO == GNUNET_RECLAIM_id_is_equal (&atle->credential->id,
-                                                 &cred->id))
+    if (GNUNET_NO == GNUNET_RECLAIM_id_is_equal 
(&atle->presentation->credential_id,
+                                                 &pres->credential_id))
       continue;
     break; /** already in list **/
   }
   if (NULL == atle)
   {
     /** Credential matches for attribute, add **/
-    atle = GNUNET_new (struct GNUNET_RECLAIM_CredentialListEntry);
-    atle->credential = GNUNET_RECLAIM_credential_new (cred->name,
-                                                      cred->type,
-                                                      cred->data,
-                                                      cred->data_size);
-    GNUNET_CONTAINER_DLL_insert (handle->creds_list->list_head,
-                                 handle->creds_list->list_tail,
+    atle = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
+    atle->presentation = GNUNET_RECLAIM_presentation_new (pres->type,
+                                                         pres->data,
+                                                         pres->data_size);
+    GNUNET_CONTAINER_DLL_insert (handle->presentations->list_head,
+                                 handle->presentations->list_tail,
                                  atle);
   }
 }
@@ -2289,8 +2297,8 @@ userinfo_endpoint (struct GNUNET_REST_RequestHandle 
*con_handle,
   privkey = GNUNET_IDENTITY_ego_get_private_key (aud_ego->ego);
   handle->attr_userinfo_list =
     GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
-  handle->creds_list =
-    GNUNET_new (struct GNUNET_RECLAIM_CredentialList);
+  handle->presentations =
+    GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
 
   handle->idp_op = GNUNET_RECLAIM_ticket_consume (idp,
                                                   privkey,
diff --git a/src/reclaim/plugin_rest_reclaim.c 
b/src/reclaim/plugin_rest_reclaim.c
index a51d992e1..ff11d2a56 100644
--- a/src/reclaim/plugin_rest_reclaim.c
+++ b/src/reclaim/plugin_rest_reclaim.c
@@ -474,7 +474,7 @@ add_credential_cont (struct GNUNET_REST_RequestHandle 
*con_handle,
   json_t *data_json;
   json_error_t err;
   struct GNUNET_JSON_Specification attrspec[] =
-  { GNUNET_RECLAIM_JSON_spec_claim_cred (&attribute),
+  { GNUNET_RECLAIM_JSON_spec_credential (&attribute),
     GNUNET_JSON_spec_end () };
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -811,7 +811,7 @@ add_attribute_cont (struct GNUNET_REST_RequestHandle 
*con_handle,
   json_t *data_json;
   json_error_t err;
   struct GNUNET_JSON_Specification attrspec[] =
-  { GNUNET_RECLAIM_JSON_spec_claim (&attribute), GNUNET_JSON_spec_end () };
+  { GNUNET_RECLAIM_JSON_spec_attribute (&attribute), GNUNET_JSON_spec_end () };
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Adding an attribute for %s.\n",
@@ -1180,7 +1180,7 @@ static void
 consume_cont (void *cls,
               const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
               const struct GNUNET_RECLAIM_Attribute *attr,
-              const struct GNUNET_RECLAIM_Credential *cred)
+              const struct GNUNET_RECLAIM_Presentation *pres)
 {
   struct RequestHandle *handle = cls;
   char *val_str;
diff --git a/src/reclaim/reclaim.h b/src/reclaim/reclaim.h
index 6ba9fdcd7..bc7f34365 100644
--- a/src/reclaim/reclaim.h
+++ b/src/reclaim/reclaim.h
@@ -462,10 +462,17 @@ struct TicketResultMessage
    */
   uint32_t id GNUNET_PACKED;
 
+  /**
+   * Length of new presentations created
+   */
+  uint32_t presentations_len GNUNET_PACKED;
+
   /**
    * The new ticket
    */
   struct GNUNET_RECLAIM_Ticket ticket;
+
+  /* Followed by the serialized GNUNET_RECLAIM_PresentationList */
 };
 
 /**
diff --git a/src/reclaim/reclaim_api.c b/src/reclaim/reclaim_api.c
index 2cfcbad09..1e0251519 100644
--- a/src/reclaim/reclaim_api.c
+++ b/src/reclaim/reclaim_api.c
@@ -91,6 +91,11 @@ struct GNUNET_RECLAIM_Operation
    */
   GNUNET_RECLAIM_TicketCallback tr_cb;
 
+  /**
+   * Ticket issue result callback
+   */
+  GNUNET_RECLAIM_IssueTicketCallback ti_cb;
+
   /**
    * Envelope with the message for this queue entry.
    */
@@ -866,6 +871,30 @@ handle_credential_result (void *cls, const struct
   GNUNET_assert (0);
 }
 
+/**
+   * Handle an incoming message of type
+   * #GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT
+   *
+   * @param cls
+   * @param msg the message we received
+   * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+   */
+static int
+check_ticket_result (void *cls, const struct TicketResultMessage *msg)
+{
+  size_t msg_len;
+  size_t pres_len;
+
+  msg_len = ntohs (msg->header.size);
+  pres_len = ntohs (msg->presentations_len);
+  if (msg_len != sizeof(struct TicketResultMessage) + pres_len)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
 
 /**
  * Handle an incoming message of type
@@ -880,8 +909,10 @@ handle_ticket_result (void *cls, const struct 
TicketResultMessage *msg)
   struct GNUNET_RECLAIM_Handle *handle = cls;
   struct GNUNET_RECLAIM_Operation *op;
   struct GNUNET_RECLAIM_TicketIterator *it;
+  struct GNUNET_RECLAIM_PresentationList *pres;
   uint32_t r_id = ntohl (msg->id);
   static const struct GNUNET_RECLAIM_Ticket ticket;
+  uint32_t pres_len = ntohs (msg->presentations_len);
 
   for (op = handle->op_head; NULL != op; op = op->next)
     if (op->r_id == r_id)
@@ -893,18 +924,25 @@ handle_ticket_result (void *cls, const struct 
TicketResultMessage *msg)
     return;
   if (NULL != op)
   {
+    if (0 < pres_len)
+      pres = GNUNET_RECLAIM_presentation_list_deserialize ((char*)&msg[1],
+                                                           pres_len);
     GNUNET_CONTAINER_DLL_remove (handle->op_head, handle->op_tail, op);
     if (0 ==
         memcmp (&msg->ticket, &ticket, sizeof(struct GNUNET_RECLAIM_Ticket)))
     {
-      if (NULL != op->tr_cb)
-        op->tr_cb (op->cls, NULL);
+      if (NULL != op->ti_cb)
+        op->ti_cb (op->cls, NULL, NULL);
     }
     else
     {
-      if (NULL != op->tr_cb)
-        op->tr_cb (op->cls, &msg->ticket);
+      if (NULL != op->ti_cb)
+        op->ti_cb (op->cls,
+                   &msg->ticket,
+                   (0 < pres_len) ? pres : NULL);
     }
+    if (0 < pres_len)
+      GNUNET_RECLAIM_presentation_list_destroy (pres);
     free_op (op);
     return;
   }
@@ -989,10 +1027,10 @@ reconnect (struct GNUNET_RECLAIM_Handle *h)
                            GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_RESULT,
                            struct CredentialResultMessage,
                            h),
-    GNUNET_MQ_hd_fixed_size (ticket_result,
-                             GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT,
-                             struct TicketResultMessage,
-                             h),
+    GNUNET_MQ_hd_var_size (ticket_result,
+                           GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT,
+                           struct TicketResultMessage,
+                           h),
     GNUNET_MQ_hd_var_size (consume_ticket_result,
                            GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT,
                            struct ConsumeTicketResultMessage,
@@ -1506,7 +1544,7 @@ GNUNET_RECLAIM_ticket_issue (
   const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss,
   const struct GNUNET_CRYPTO_EcdsaPublicKey *rp,
   const struct GNUNET_RECLAIM_AttributeList *attrs,
-  GNUNET_RECLAIM_TicketCallback cb,
+  GNUNET_RECLAIM_IssueTicketCallback cb,
   void *cb_cls)
 {
   struct GNUNET_RECLAIM_Operation *op;
@@ -1516,7 +1554,7 @@ GNUNET_RECLAIM_ticket_issue (
   fprintf (stderr, "Issuing ticket\n");
   op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
   op->h = h;
-  op->tr_cb = cb;
+  op->ti_cb = cb;
   op->cls = cb_cls;
   op->r_id = h->r_id_gen++;
   GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
diff --git a/src/reclaim/reclaim_credential.c b/src/reclaim/reclaim_credential.c
index 10b17ae96..5c8974400 100644
--- a/src/reclaim/reclaim_credential.c
+++ b/src/reclaim/reclaim_credential.c
@@ -165,9 +165,9 @@ GNUNET_RECLAIM_credential_number_to_typename (uint32_t type)
  */
 int
 GNUNET_RECLAIM_credential_string_to_value (uint32_t type,
-                                            const char *s,
-                                            void **data,
-                                            size_t *data_size)
+                                           const char *s,
+                                           void **data,
+                                           size_t *data_size)
 {
   unsigned int i;
   struct Plugin *plugin;
@@ -197,8 +197,8 @@ GNUNET_RECLAIM_credential_string_to_value (uint32_t type,
  */
 char *
 GNUNET_RECLAIM_credential_value_to_string (uint32_t type,
-                                            const void *data,
-                                            size_t data_size)
+                                           const void *data,
+                                           size_t data_size)
 {
   unsigned int i;
   struct Plugin *plugin;
@@ -229,9 +229,9 @@ GNUNET_RECLAIM_credential_value_to_string (uint32_t type,
    */
 struct GNUNET_RECLAIM_Credential *
 GNUNET_RECLAIM_credential_new (const char *attr_name,
-                                uint32_t type,
-                                const void *data,
-                                size_t data_size)
+                               uint32_t type,
+                               const void *data,
+                               size_t data_size)
 {
   struct GNUNET_RECLAIM_Credential *attr;
   char *write_ptr;
@@ -335,7 +335,7 @@ GNUNET_RECLAIM_credential_list_deserialize (const char 
*data, size_t data_size)
     ale = GNUNET_new (struct GNUNET_RECLAIM_CredentialListEntry);
     ale->credential =
       GNUNET_RECLAIM_credential_deserialize (read_ptr,
-                                              data_size - (read_ptr - data));
+                                             data_size - (read_ptr - data));
     if (NULL == ale->credential)
     {
       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -371,9 +371,9 @@ GNUNET_RECLAIM_credential_list_dup (
     GNUNET_assert (NULL != ale->credential);
     result_ale->credential =
       GNUNET_RECLAIM_credential_new (ale->credential->name,
-                                      ale->credential->type,
-                                      ale->credential->data,
-                                      ale->credential->data_size);
+                                     ale->credential->type,
+                                     ale->credential->data,
+                                     ale->credential->data_size);
     result_ale->credential->id = ale->credential->id;
     GNUNET_CONTAINER_DLL_insert (result->list_head,
                                  result->list_tail,
@@ -490,7 +490,7 @@ GNUNET_RECLAIM_credential_deserialize (const char *data, 
size_t data_size)
     return NULL;
   }
   credential = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Credential)
-                               + data_len + name_len + 1);
+                              + data_len + name_len + 1);
   credential->type = ntohs (atts->credential_type);
   credential->flag = ntohl (atts->credential_flag);
   credential->id = atts->credential_id;
@@ -511,7 +511,7 @@ GNUNET_RECLAIM_credential_deserialize (const char *data, 
size_t data_size)
 
 struct GNUNET_RECLAIM_AttributeList*
 GNUNET_RECLAIM_credential_get_attributes (const struct
-                                           GNUNET_RECLAIM_Credential 
*credential)
+                                          GNUNET_RECLAIM_Credential 
*credential)
 {
   unsigned int i;
   struct Plugin *plugin;
@@ -531,7 +531,7 @@ GNUNET_RECLAIM_credential_get_attributes (const struct
 
 char*
 GNUNET_RECLAIM_credential_get_issuer (const struct
-                                       GNUNET_RECLAIM_Credential *credential)
+                                      GNUNET_RECLAIM_Credential *credential)
 {
   unsigned int i;
   struct Plugin *plugin;
@@ -551,8 +551,8 @@ GNUNET_RECLAIM_credential_get_issuer (const struct
 
 int
 GNUNET_RECLAIM_credential_get_expiration (const struct
-                                           GNUNET_RECLAIM_Credential 
*credential,
-                                           struct GNUNET_TIME_Absolute*exp)
+                                          GNUNET_RECLAIM_Credential 
*credential,
+                                          struct GNUNET_TIME_Absolute*exp)
 {
   unsigned int i;
   struct Plugin *plugin;
@@ -568,3 +568,470 @@ GNUNET_RECLAIM_credential_get_expiration (const struct
   }
   return GNUNET_SYSERR;
 }
+
+
+/**
+ * Convert an presentation type name to the corresponding number
+ *
+ * @param typename name to convert
+ * @return corresponding number, UINT32_MAX on error
+ */
+uint32_t
+GNUNET_RECLAIM_presentation_typename_to_number (const char *typename)
+{
+  unsigned int i;
+  struct Plugin *plugin;
+  uint32_t ret;
+  init ();
+  for (i = 0; i < num_plugins; i++)
+  {
+    plugin = credential_plugins[i];
+    if (UINT32_MAX !=
+        (ret = plugin->api->typename_to_number_p (plugin->api->cls,
+                                                  typename)))
+      return ret;
+  }
+  return UINT32_MAX;
+}
+
+
+/**
+ * Convert an presentation type number to the corresponding presentation type 
string
+ *
+ * @param type number of a type
+ * @return corresponding typestring, NULL on error
+ */
+const char *
+GNUNET_RECLAIM_presentation_number_to_typename (uint32_t type)
+{
+  unsigned int i;
+  struct Plugin *plugin;
+  const char *ret;
+
+  init ();
+  for (i = 0; i < num_plugins; i++)
+  {
+    plugin = credential_plugins[i];
+    if (NULL !=
+        (ret = plugin->api->number_to_typename_p (plugin->api->cls, type)))
+      return ret;
+  }
+  return NULL;
+}
+
+
+/**
+ * Convert human-readable version of a 'claim' of an presentation to the binary
+ * representation
+ *
+ * @param type type of the claim
+ * @param s human-readable string
+ * @param data set to value in binary encoding (will be allocated)
+ * @param data_size set to number of bytes in @a data
+ * @return #GNUNET_OK on success
+ */
+int
+GNUNET_RECLAIM_presentation_string_to_value (uint32_t type,
+                                             const char *s,
+                                             void **data,
+                                             size_t *data_size)
+{
+  unsigned int i;
+  struct Plugin *plugin;
+
+  init ();
+  for (i = 0; i < num_plugins; i++)
+  {
+    plugin = credential_plugins[i];
+    if (GNUNET_OK == plugin->api->string_to_value_p (plugin->api->cls,
+                                                     type,
+                                                     s,
+                                                     data,
+                                                     data_size))
+      return GNUNET_OK;
+  }
+  return GNUNET_SYSERR;
+}
+
+
+/**
+ * Convert the 'claim' of an presentation to a string
+ *
+ * @param type the type of presentation
+ * @param data claim in binary encoding
+ * @param data_size number of bytes in @a data
+ * @return NULL on error, otherwise human-readable representation of the claim
+ */
+char *
+GNUNET_RECLAIM_presentation_value_to_string (uint32_t type,
+                                             const void *data,
+                                             size_t data_size)
+{
+  unsigned int i;
+  struct Plugin *plugin;
+  char *ret;
+
+  init ();
+  for (i = 0; i < num_plugins; i++)
+  {
+    plugin = credential_plugins[i];
+    if (NULL != (ret = plugin->api->value_to_string_p (plugin->api->cls,
+                                                       type,
+                                                       data,
+                                                       data_size)))
+      return ret;
+  }
+  return NULL;
+}
+
+
+struct GNUNET_RECLAIM_Presentation *
+GNUNET_RECLAIM_presentation_new (uint32_t type,
+                                 const void *data,
+                                 size_t data_size)
+{
+  struct GNUNET_RECLAIM_Presentation *attr;
+  char *write_ptr;
+
+  attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Presentation)
+                        + data_size);
+  attr->type = type;
+  attr->data_size = data_size;
+  write_ptr = (char *) &attr[1];
+  GNUNET_memcpy (write_ptr, data, data_size);
+  attr->data = write_ptr;
+  return attr;
+}
+
+
+/**
+ * Get required size for serialization buffer
+ *
+ * @param attrs the attribute list to serialize
+ * @return the required buffer size
+ */
+size_t
+GNUNET_RECLAIM_presentation_list_serialize_get_size (
+  const struct GNUNET_RECLAIM_PresentationList *presentations)
+{
+  struct GNUNET_RECLAIM_PresentationListEntry *le;
+  size_t len = 0;
+
+  for (le = presentations->list_head; NULL != le; le = le->next)
+  {
+    GNUNET_assert (NULL != le->presentation);
+    len += GNUNET_RECLAIM_presentation_serialize_get_size (le->presentation);
+    len += sizeof(struct GNUNET_RECLAIM_PresentationListEntry);
+  }
+  return len;
+}
+
+
+/**
+ * Serialize an attribute list
+ *
+ * @param attrs the attribute list to serialize
+ * @param result the serialized attribute
+ * @return length of serialized data
+ */
+size_t
+GNUNET_RECLAIM_presentation_list_serialize (
+  const struct GNUNET_RECLAIM_PresentationList *presentations,
+  char *result)
+{
+  struct GNUNET_RECLAIM_PresentationListEntry *le;
+  size_t len;
+  size_t total_len;
+  char *write_ptr;
+  write_ptr = result;
+  total_len = 0;
+  for (le = presentations->list_head; NULL != le; le = le->next)
+  {
+    GNUNET_assert (NULL != le->presentation);
+    len = GNUNET_RECLAIM_presentation_serialize (le->presentation, write_ptr);
+    total_len += len;
+    write_ptr += len;
+  }
+  return total_len;
+}
+
+
+/**
+ * Deserialize an presentation list
+ *
+ * @param data the serialized attribute list
+ * @param data_size the length of the serialized data
+ * @return a GNUNET_IDENTITY_PROVIDER_AttributeList, must be free'd by caller
+ */
+struct GNUNET_RECLAIM_PresentationList *
+GNUNET_RECLAIM_presentation_list_deserialize (const char *data, size_t
+                                              data_size)
+{
+  struct GNUNET_RECLAIM_PresentationList *al;
+  struct GNUNET_RECLAIM_PresentationListEntry *ale;
+  size_t att_len;
+  const char *read_ptr;
+
+  al = GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
+
+  if ((data_size < sizeof(struct Presentation)
+       + sizeof(struct GNUNET_RECLAIM_PresentationListEntry)))
+    return al;
+
+  read_ptr = data;
+  while (((data + data_size) - read_ptr) >= sizeof(struct Presentation))
+  {
+    ale = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
+    ale->presentation =
+      GNUNET_RECLAIM_presentation_deserialize (read_ptr,
+                                               data_size - (read_ptr - data));
+    if (NULL == ale->presentation)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  "Failed to deserialize malformed presentation.\n");
+      GNUNET_free (ale);
+      return al;
+    }
+    GNUNET_CONTAINER_DLL_insert (al->list_head, al->list_tail, ale);
+    att_len = GNUNET_RECLAIM_presentation_serialize_get_size (
+      ale->presentation);
+    read_ptr += att_len;
+  }
+  return al;
+}
+
+
+/**
+ * Make a (deep) copy of the presentation list
+ * @param attrs claim list to copy
+ * @return copied claim list
+ */
+struct GNUNET_RECLAIM_PresentationList *
+GNUNET_RECLAIM_presentation_list_dup (
+  const struct GNUNET_RECLAIM_PresentationList *al)
+{
+  struct GNUNET_RECLAIM_PresentationListEntry *ale;
+  struct GNUNET_RECLAIM_PresentationListEntry *result_ale;
+  struct GNUNET_RECLAIM_PresentationList *result;
+
+  result = GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
+  for (ale = al->list_head; NULL != ale; ale = ale->next)
+  {
+    result_ale = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
+    GNUNET_assert (NULL != ale->presentation);
+    result_ale->presentation =
+      GNUNET_RECLAIM_presentation_new (ale->presentation->type,
+                                       ale->presentation->data,
+                                       ale->presentation->data_size);
+    result_ale->presentation->credential_id = ale->presentation->credential_id;
+    GNUNET_CONTAINER_DLL_insert (result->list_head,
+                                 result->list_tail,
+                                 result_ale);
+  }
+  return result;
+}
+
+
+/**
+ * Destroy presentation list
+ *
+ * @param attrs list to destroy
+ */
+void
+GNUNET_RECLAIM_presentation_list_destroy (
+  struct GNUNET_RECLAIM_PresentationList *al)
+{
+  struct GNUNET_RECLAIM_PresentationListEntry *ale;
+  struct GNUNET_RECLAIM_PresentationListEntry *tmp_ale;
+
+  for (ale = al->list_head; NULL != ale;)
+  {
+    if (NULL != ale->presentation)
+      GNUNET_free (ale->presentation);
+    tmp_ale = ale;
+    ale = ale->next;
+    GNUNET_free (tmp_ale);
+  }
+  GNUNET_free (al);
+}
+
+
+/**
+ * Get required size for serialization buffer
+ *
+ * @param attr the presentation to serialize
+ * @return the required buffer size
+ */
+size_t
+GNUNET_RECLAIM_presentation_serialize_get_size (
+  const struct GNUNET_RECLAIM_Presentation *presentation)
+{
+  return sizeof(struct Presentation) + presentation->data_size;
+}
+
+
+/**
+ * Serialize an presentation
+ *
+ * @param attr the presentation to serialize
+ * @param result the serialized presentation
+ * @return length of serialized data
+ */
+size_t
+GNUNET_RECLAIM_presentation_serialize (
+  const struct GNUNET_RECLAIM_Presentation *presentation,
+  char *result)
+{
+  struct Presentation *atts;
+  char *write_ptr;
+
+  atts = (struct Presentation *) result;
+  atts->presentation_type = htons (presentation->type);
+  atts->credential_id = presentation->credential_id;
+  write_ptr = (char *) &atts[1];
+  GNUNET_memcpy (write_ptr, presentation->data, presentation->data_size);
+  atts->data_size = htons (presentation->data_size);
+
+  return sizeof(struct Presentation) + presentation->data_size;
+}
+
+
+/**
+ * Deserialize an presentation
+ *
+ * @param data the serialized presentation
+ * @param data_size the length of the serialized data
+ *
+ * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
+ */
+struct GNUNET_RECLAIM_Presentation *
+GNUNET_RECLAIM_presentation_deserialize (const char *data, size_t data_size)
+{
+  struct GNUNET_RECLAIM_Presentation *presentation;
+  struct Presentation *atts;
+  size_t data_len;
+  char *write_ptr;
+
+  if (data_size < sizeof(struct Presentation))
+    return NULL;
+
+  atts = (struct Presentation *) data;
+  data_len = ntohs (atts->data_size);
+  if (data_size < sizeof(struct Presentation) + data_len)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Buffer too small to deserialize\n");
+    return NULL;
+  }
+  presentation = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Presentation)
+                                + data_len);
+  presentation->type = ntohs (atts->presentation_type);
+  presentation->credential_id = atts->credential_id;
+  presentation->data_size = data_len;
+
+  write_ptr = (char *) &presentation[1];
+  GNUNET_memcpy (write_ptr, &atts[1], data_len);
+  presentation->data = write_ptr;
+  return presentation;
+}
+
+
+struct GNUNET_RECLAIM_AttributeList*
+GNUNET_RECLAIM_presentation_get_attributes (const struct
+                                            GNUNET_RECLAIM_Presentation *
+                                            presentation)
+{
+  unsigned int i;
+  struct Plugin *plugin;
+  struct GNUNET_RECLAIM_AttributeList *ret;
+  init ();
+  for (i = 0; i < num_plugins; i++)
+  {
+    plugin = credential_plugins[i];
+    if (NULL !=
+        (ret = plugin->api->get_attributes_p (plugin->api->cls,
+                                              presentation)))
+      return ret;
+  }
+  return NULL;
+}
+
+
+char*
+GNUNET_RECLAIM_presentation_get_issuer (const struct
+                                        GNUNET_RECLAIM_Presentation *
+                                        presentation)
+{
+  unsigned int i;
+  struct Plugin *plugin;
+  char *ret;
+  init ();
+  for (i = 0; i < num_plugins; i++)
+  {
+    plugin = credential_plugins[i];
+    if (NULL !=
+        (ret = plugin->api->get_issuer_p (plugin->api->cls,
+                                          presentation)))
+      return ret;
+  }
+  return NULL;
+}
+
+
+int
+GNUNET_RECLAIM_presentation_get_expiration (const struct
+                                            GNUNET_RECLAIM_Presentation *
+                                            presentation,
+                                            struct GNUNET_TIME_Absolute*exp)
+{
+  unsigned int i;
+  struct Plugin *plugin;
+  init ();
+  for (i = 0; i < num_plugins; i++)
+  {
+    plugin = credential_plugins[i];
+    if (GNUNET_OK !=  plugin->api->get_expiration_p (plugin->api->cls,
+                                                     presentation,
+                                                     exp))
+      continue;
+    return GNUNET_OK;
+  }
+  return GNUNET_SYSERR;
+}
+
+/**
+ * Create a presentation from a credential and a lift of (selected)
+ * attributes in the credential.
+ * FIXME not yet implemented
+ *
+ * @param cred the credential to use
+ * @param attrs the attributes to present from the credential
+ * @return the credential presentation presenting the attributes according
+ *         to the presentation mechanism of the credential
+ *         or NULL on error.
+ */
+int
+GNUNET_RECLAIM_credential_get_presentation (
+                              const struct GNUNET_RECLAIM_Credential *cred,
+                              const struct GNUNET_RECLAIM_AttributeList *attrs,
+                              struct GNUNET_RECLAIM_Presentation **pres)
+{
+  unsigned int i;
+  struct Plugin *plugin;
+  init ();
+  for (i = 0; i < num_plugins; i++)
+  {
+    plugin = credential_plugins[i];
+    if (GNUNET_OK !=  plugin->api->create_presentation (plugin->api->cls,
+                                                        cred,
+                                                        attrs,
+                                                        pres))
+      continue;
+    (*pres)->credential_id = cred->id;
+    return GNUNET_OK;
+  }
+  return GNUNET_SYSERR;
+}
+
+
+
diff --git a/src/reclaim/reclaim_credential.h b/src/reclaim/reclaim_credential.h
index cd3a9539a..7704ed968 100644
--- a/src/reclaim/reclaim_credential.h
+++ b/src/reclaim/reclaim_credential.h
@@ -61,4 +61,39 @@ struct Credential
   // followed by data_size Credential value data
 };
 
+
+/**
+ * Serialized presentation claim
+ */
+struct Presentation
+{
+  /**
+   * Presentation type
+   */
+  uint32_t presentation_type;
+
+  /**
+   * Presentation flag
+   */
+  uint32_t presentation_flag;
+
+  /**
+   * Credential ID
+   */
+  struct GNUNET_RECLAIM_Identifier credential_id;
+
+  /**
+   * Name length
+   */
+  uint32_t name_len;
+
+  /**
+   * Data size
+   */
+  uint32_t data_size;
+
+  // followed by data_size Presentation value data
+};
+
+
 #endif

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]