Merge remote-tracking branch 'origin/master' into identity_abe
[oweals/gnunet.git] / src / credential / credential_serialization.c
index 2fbcebd9ff62bc86f1c03bf52ebf79c2a1d63479..1fc72c2033f37ce0d2e4fe015dbb60a3fc46457a 100644 (file)
 #include "gnunet_util_lib.h"
 #include "gnunet_constants.h"
 #include "gnunet_credential_service.h"
+#include "gnunet_signatures.h"
+#include "credential.h"
 
-GNUNET_NETWORK_STRUCT_BEGIN
+/**
+ * Calculate how many bytes we will need to serialize
+ * the given delegation chain and credential
+ *
+ * @param d_count number of delegation chain entries
+ * @param dd array of #GNUNET_CREDENTIAL_Delegation
+ * @param cd a #GNUNET_CREDENTIAL_Credential
+ * @return the required size to serialize
+ */
+size_t
+GNUNET_CREDENTIAL_delegation_set_get_size (unsigned int ds_count,
+                                           const struct GNUNET_CREDENTIAL_DelegationSet *dsr)
+{
+  unsigned int i;
+  size_t ret;
+
+  ret = sizeof (struct DelegationRecordData) * (ds_count);
+
+  for (i=0; i<ds_count;i++)
+  {
+    GNUNET_assert ((ret + dsr[i].subject_attribute_len) >= ret);
+    ret += dsr[i].subject_attribute_len;
+  }
+  return ret;
+}
+
+/**
+ * Serizalize the given delegation chain entries and credential
+ *
+ * @param d_count number of delegation chain entries
+ * @param dd array of #GNUNET_CREDENTIAL_Delegation
+ * @param cd a #GNUNET_CREDENTIAL_Credential
+ * @param dest_size size of the destination
+ * @param dest where to store the result
+ * @return the size of the data, -1 on failure
+ */
+ssize_t
+GNUNET_CREDENTIAL_delegation_set_serialize (unsigned int d_count,
+                                            const struct GNUNET_CREDENTIAL_DelegationSet *dsr,
+                                            size_t dest_size,
+                                            char *dest)
+{
+  struct DelegationRecordData rec;
+  unsigned int i;
+  size_t off;
+
+  off = 0;
+  for (i=0;i<d_count;i++)
+  {
+    rec.subject_attribute_len = htonl ((uint32_t) dsr[i].subject_attribute_len);
+    rec.subject_key = dsr[i].subject_key;
+    if (off + sizeof (rec) > dest_size)
+      return -1;
+    GNUNET_memcpy (&dest[off],
+                   &rec,
+                   sizeof (rec));
+    off += sizeof (rec);
+    if (0 == dsr[i].subject_attribute_len)
+      continue;
+    if (off + dsr[i].subject_attribute_len > dest_size)
+      return -1;
+    GNUNET_memcpy (&dest[off],
+                   dsr[i].subject_attribute,
+                   dsr[i].subject_attribute_len);
+    off += dsr[i].subject_attribute_len;
+  }
+  return off;
+}
 
-struct NetworkRecord
+
+/**
+ * Deserialize the given destination
+ *
+ * @param len size of the serialized delegation chain and cred
+ * @param src the serialized data
+ * @param d_count the number of delegation chain entries
+ * @param dd where to put the delegation chain entries
+ * @param cd where to put the credential data
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+int
+GNUNET_CREDENTIAL_delegation_set_deserialize (size_t len,
+                                              const char *src,
+                                              unsigned int d_count,
+                                              struct GNUNET_CREDENTIAL_DelegationSet *dsr)
 {
-  /**
-   * Issuer key
-   */
-  struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
-  
-  /**
-   * Subject key
-   */
-  struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
-  
-  /**
-   * Issuer attributes
-   */
-  uint32_t issuer_attribute_len GNUNET_PACKED;
-  
-  /**
-   * Subject attributes
-   */
-  uint32_t subject_attribute_len GNUNET_PACKED;
-};
-
-GNUNET_NETWORK_STRUCT_END
+  struct DelegationRecordData rec;
+  unsigned int i;
+  size_t off;
+
+  off = 0;
+  for (i=0;i<d_count;i++)
+  {
+    if (off + sizeof (rec) > len)
+      return GNUNET_SYSERR;
+    GNUNET_memcpy (&rec, &src[off], sizeof (rec));
+    dsr[i].subject_key = rec.subject_key;
+    off += sizeof (rec);
+    dsr[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
+    if (off + dsr[i].subject_attribute_len > len)
+      return GNUNET_SYSERR;
+    dsr[i].subject_attribute = (char*)&src[off];
+    off += dsr[i].subject_attribute_len;
+  }
+  return GNUNET_OK;
+}
+
+
+/**
+ * Calculate how many bytes we will need to serialize
+ * the credentials
+ *
+ * @param c_count number of credential entries
+ * @param cd a #GNUNET_CREDENTIAL_Credential
+ * @return the required size to serialize
+ */
+size_t
+GNUNET_CREDENTIAL_credentials_get_size (unsigned int c_count,
+                                        const struct GNUNET_CREDENTIAL_Credential *cd)
+{
+  unsigned int i;
+  size_t ret;
+
+  ret = sizeof (struct CredentialEntry) * (c_count);
+
+  for (i=0; i<c_count;i++)
+  {
+    GNUNET_assert ((ret + cd[i].issuer_attribute_len) >= ret);
+    ret += cd[i].issuer_attribute_len;
+  }
+  return ret;
+}
+/**
+ * Serizalize the given credentials
+ *
+ * @param c_count number of credential entries
+ * @param cd a #GNUNET_CREDENTIAL_Credential
+ * @param dest_size size of the destination
+ * @param dest where to store the result
+ * @return the size of the data, -1 on failure
+ */
+ssize_t
+GNUNET_CREDENTIAL_credentials_serialize (unsigned int c_count,
+                                         const struct GNUNET_CREDENTIAL_Credential *cd,
+                                         size_t dest_size,
+                                         char *dest)
+{
+  struct CredentialEntry c_rec;
+  unsigned int i;
+  size_t off;
+
+  off = 0;
+  for (i=0;i<c_count;i++)
+  {
+    c_rec.issuer_attribute_len = htonl ((uint32_t) cd[i].issuer_attribute_len);
+    c_rec.issuer_key = cd[i].issuer_key;
+    c_rec.subject_key = cd[i].subject_key;
+    c_rec.signature = cd[i].signature;
+    c_rec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
+    c_rec.purpose.size = htonl ((sizeof (struct CredentialEntry) + cd[i].issuer_attribute_len) - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
+    c_rec.expiration = GNUNET_htonll (cd[i].expiration.abs_value_us);
+    if (off + sizeof (c_rec) > dest_size)
+      return -1;
+    GNUNET_memcpy (&dest[off],
+                   &c_rec,
+                   sizeof (c_rec));
+    off += sizeof (c_rec);
+    if (off + cd[i].issuer_attribute_len > dest_size)
+      return -1;
+    GNUNET_memcpy (&dest[off],
+                   cd[i].issuer_attribute,
+                   cd[i].issuer_attribute_len);
+    off += cd[i].issuer_attribute_len;
+  }
+
+  return off;
+}
+
+
+
+/**
+ * Deserialize the given destination
+ *
+ * @param len size of the serialized creds
+ * @param src the serialized data
+ * @param c_count the number of credential entries
+ * @param cd where to put the credential data
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+int
+GNUNET_CREDENTIAL_credentials_deserialize (size_t len,
+                                           const char *src,
+                                           unsigned int c_count,
+                                           struct GNUNET_CREDENTIAL_Credential *cd)
+{
+  struct CredentialEntry c_rec;
+  unsigned int i;
+  size_t off;
+
+  off = 0;
+  for (i=0;i<c_count;i++)
+  {
+    if (off + sizeof (c_rec) > len)
+      return GNUNET_SYSERR;
+    GNUNET_memcpy (&c_rec, &src[off], sizeof (c_rec));
+    cd[i].issuer_attribute_len = ntohl ((uint32_t) c_rec.issuer_attribute_len);
+    cd[i].issuer_key = c_rec.issuer_key;
+    cd[i].subject_key = c_rec.subject_key;
+    cd[i].signature = c_rec.signature;
+    cd[i].expiration.abs_value_us = GNUNET_ntohll(c_rec.expiration);
+    off += sizeof (c_rec);
+    if (off + cd[i].issuer_attribute_len > len)
+      return GNUNET_SYSERR;
+    cd[i].issuer_attribute = &src[off];
+    off += cd[i].issuer_attribute_len;
+  }
+  return GNUNET_OK;
+}
+
+
 
 /**
  * Calculate how many bytes we will need to serialize
@@ -63,18 +259,20 @@ GNUNET_NETWORK_STRUCT_END
  *
  * @param d_count number of delegation chain entries
  * @param dd array of #GNUNET_CREDENTIAL_Delegation
+ * @param c_count number of credential entries
  * @param cd a #GNUNET_CREDENTIAL_Credential
  * @return the required size to serialize
  */
 size_t
 GNUNET_CREDENTIAL_delegation_chain_get_size (unsigned int d_count,
                                              const struct GNUNET_CREDENTIAL_Delegation *dd,
+                                             unsigned int c_count,
                                              const struct GNUNET_CREDENTIAL_Credential *cd)
 {
   unsigned int i;
   size_t ret;
 
-  ret = sizeof (struct NetworkRecord) * (d_count + 1);
+  ret = sizeof (struct ChainEntry) * (d_count);
 
   for (i=0; i<d_count;i++)
   {
@@ -83,8 +281,7 @@ GNUNET_CREDENTIAL_delegation_chain_get_size (unsigned int d_count,
                     dd[i].subject_attribute_len) >= ret);
     ret += dd[i].issuer_attribute_len + dd[i].subject_attribute_len;
   }
-  GNUNET_assert ((ret + cd->issuer_attribute_len) >= ret);
-  ret += cd->issuer_attribute_len;
+  return ret+GNUNET_CREDENTIAL_credentials_get_size(c_count, cd);
   return ret;
 }
 
@@ -93,6 +290,7 @@ GNUNET_CREDENTIAL_delegation_chain_get_size (unsigned int d_count,
  *
  * @param d_count number of delegation chain entries
  * @param dd array of #GNUNET_CREDENTIAL_Delegation
+ * @param c_count number of credential entries
  * @param cd a #GNUNET_CREDENTIAL_Credential
  * @param dest_size size of the destination
  * @param dest where to store the result
@@ -101,11 +299,12 @@ GNUNET_CREDENTIAL_delegation_chain_get_size (unsigned int d_count,
 ssize_t
 GNUNET_CREDENTIAL_delegation_chain_serialize (unsigned int d_count,
                                               const struct GNUNET_CREDENTIAL_Delegation *dd,
+                                              unsigned int c_count,
                                               const struct GNUNET_CREDENTIAL_Credential *cd,
                                               size_t dest_size,
                                               char *dest)
 {
-  struct NetworkRecord rec;
+  struct ChainEntry rec;
   unsigned int i;
   size_t off;
 
@@ -137,23 +336,10 @@ GNUNET_CREDENTIAL_delegation_chain_serialize (unsigned int d_count,
                    dd[i].subject_attribute_len);
     off += dd[i].subject_attribute_len;
   }
-  rec.issuer_attribute_len = htonl ((uint32_t) cd->issuer_attribute_len);
-  rec.subject_attribute_len = htonl (0);
-  rec.issuer_key = cd->issuer_key;
-  if (off + sizeof (rec) > dest_size)
-    return -1;
-  GNUNET_memcpy (&dest[off],
-                 &rec,
-                 sizeof (rec));
-  off += sizeof (rec);
-  if (off + cd->issuer_attribute_len > dest_size)
-    return -1;
-  GNUNET_memcpy (&dest[off],
-                 cd->issuer_attribute,
-                 cd->issuer_attribute_len);
-  off += cd->issuer_attribute_len;
-
-  return off;
+  return off+GNUNET_CREDENTIAL_credentials_serialize (c_count,
+                                                      cd,
+                                                      dest_size-off,
+                                                      &dest[off]);
 }
 
 
@@ -164,6 +350,7 @@ GNUNET_CREDENTIAL_delegation_chain_serialize (unsigned int d_count,
  * @param src the serialized data
  * @param d_count the number of delegation chain entries
  * @param dd where to put the delegation chain entries
+ * @param c_count the number of credential entries
  * @param cd where to put the credential data
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
@@ -172,9 +359,10 @@ GNUNET_CREDENTIAL_delegation_chain_deserialize (size_t len,
                                                 const char *src,
                                                 unsigned int d_count,
                                                 struct GNUNET_CREDENTIAL_Delegation *dd,
+                                                unsigned int c_count,
                                                 struct GNUNET_CREDENTIAL_Credential *cd)
 {
-  struct NetworkRecord rec;
+  struct ChainEntry rec;
   unsigned int i;
   size_t off;
 
@@ -198,18 +386,78 @@ GNUNET_CREDENTIAL_delegation_chain_deserialize (size_t len,
     dd[i].subject_attribute = &src[off];
     off += dd[i].subject_attribute_len;
   }
-  if (off + sizeof (rec) > len)
-    return GNUNET_SYSERR;
-  GNUNET_memcpy (&rec, &src[off], sizeof (rec));
-  cd->issuer_attribute_len = ntohl ((uint32_t) rec.issuer_attribute_len);
-  cd->issuer_key = rec.issuer_key;
-  cd->subject_key = rec.subject_key;
-  off += sizeof (rec);
-  if (off + cd->issuer_attribute_len > len)
-    return GNUNET_SYSERR;
-  cd->issuer_attribute = &src[off];
-  off += cd->issuer_attribute_len;
-  return GNUNET_OK;
+  return GNUNET_CREDENTIAL_credentials_deserialize (len-off,
+                                                    &src[off],
+                                                    c_count,
+                                                    cd);
+}
+int
+GNUNET_CREDENTIAL_credential_serialize (struct GNUNET_CREDENTIAL_Credential *cred,
+                                        char **data)
+{
+  size_t size;
+  struct CredentialEntry *cdata;
+
+  size = sizeof (struct CredentialEntry) + strlen (cred->issuer_attribute) + 1;
+  *data = GNUNET_malloc (size);
+  cdata = (struct CredentialEntry*)*data;
+  cdata->subject_key = cred->subject_key;
+  cdata->issuer_key = cred->issuer_key;
+  cdata->expiration = GNUNET_htonll (cred->expiration.abs_value_us);
+  cdata->signature = cred->signature;
+  cdata->issuer_attribute_len = htonl (strlen (cred->issuer_attribute) + 1);
+  cdata->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
+  cdata->purpose.size = htonl (size - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
+  GNUNET_memcpy (&cdata[1],
+                 cred->issuer_attribute,
+                 strlen (cred->issuer_attribute));
+
+  if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL, 
+                                             &cdata->purpose,
+                                             &cdata->signature,
+                                             &cdata->issuer_key))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Invalid credential\n");
+    //return NULL;
+  }
+  return size;
 }
 
+struct GNUNET_CREDENTIAL_Credential*
+GNUNET_CREDENTIAL_credential_deserialize (const char* data,
+                                          size_t data_size)
+{
+  struct GNUNET_CREDENTIAL_Credential *cred;
+  struct CredentialEntry *cdata;
+  char *issuer_attribute;
+
+  if (data_size < sizeof (struct CredentialEntry))
+    return NULL;
+  cdata = (struct CredentialEntry*)data;
+  if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL, 
+                                             &cdata->purpose,
+                                             &cdata->signature,
+                                             &cdata->issuer_key))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Invalid credential\n");
+    //return NULL;
+  }
+  issuer_attribute = (char*)&cdata[1];
+
+  cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + ntohl(cdata->issuer_attribute_len));
+
+  cred->issuer_key = cdata->issuer_key;
+  cred->subject_key = cdata->subject_key;
+  GNUNET_memcpy (&cred[1],
+                 issuer_attribute,
+                 ntohl (cdata->issuer_attribute_len));
+  cred->signature = cdata->signature;
+  cred->issuer_attribute = (char*)&cred[1];
+  cred->expiration.abs_value_us = GNUNET_ntohll (cdata->expiration);
+  return cred;
+}
+
+
 /* end of credential_serialization.c */