/*
This file is part of GNUnet.
Copyright (C) 2009-2013, 2016 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License,
or (at your option) any later version.
GNUnet is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
SPDX-License-Identifier: AGPL3.0-or-later
*/
/**
* @file credential/credential_serialization.c
* @brief API to serialize and deserialize delegation chains
* and credentials
* @author Martin Schanzenbach
*/
#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_constants.h"
#include "gnunet_credential_service.h"
#include "gnunet_signatures.h"
#include "credential.h"
/**
* Calculate how many bytes we will need to serialize
* the given delegation chain
*
* @param ds_count number of delegation chain entries
* @param dsr array of #GNUNET_CREDENTIAL_DelegationSet
* @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= 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 dsr array of #GNUNET_CREDENTIAL_DelegationSet
* @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 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;
}
/**
* 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 dsr where to put the delegation chain entries
* @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)
{
struct DelegationRecordData rec;
unsigned int i;
size_t off;
off = 0;
for (i=0;i 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= 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 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 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
* the given delegation chain and credential
*
* @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 ChainEntry) * (d_count);
for (i=0; i= ret);
ret += dd[i].issuer_attribute_len + dd[i].subject_attribute_len;
}
return ret+GNUNET_CREDENTIAL_credentials_get_size(c_count, cd);
}
/**
* Serizalize the given delegation chain entries and credential
*
* @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
* @return the size of the data, -1 on failure
*/
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 ChainEntry rec;
unsigned int i;
size_t off;
off = 0;
for (i=0;i dest_size)
return -1;
GNUNET_memcpy (&dest[off],
&rec,
sizeof (rec));
off += sizeof (rec);
if (off + dd[i].issuer_attribute_len > dest_size)
return -1;
GNUNET_memcpy (&dest[off],
dd[i].issuer_attribute,
dd[i].issuer_attribute_len);
off += dd[i].issuer_attribute_len;
if (0 == dd[i].subject_attribute_len)
continue;
if (off + dd[i].subject_attribute_len > dest_size)
return -1;
GNUNET_memcpy (&dest[off],
dd[i].subject_attribute,
dd[i].subject_attribute_len);
off += dd[i].subject_attribute_len;
}
return off+GNUNET_CREDENTIAL_credentials_serialize (c_count,
cd,
dest_size-off,
&dest[off]);
}
/**
* 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 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_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 ChainEntry rec;
unsigned int i;
size_t off;
off = 0;
for (i=0;i len)
return GNUNET_SYSERR;
GNUNET_memcpy (&rec, &src[off], sizeof (rec));
dd[i].issuer_attribute_len = ntohl ((uint32_t) rec.issuer_attribute_len);
dd[i].issuer_key = rec.issuer_key;
dd[i].subject_key = rec.subject_key;
off += sizeof (rec);
if (off + dd[i].issuer_attribute_len > len)
return GNUNET_SYSERR;
dd[i].issuer_attribute = &src[off];
off += dd[i].issuer_attribute_len;
dd[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
if (off + dd[i].subject_attribute_len > len)
return GNUNET_SYSERR;
dd[i].subject_attribute = &src[off];
off += dd[i].subject_attribute_len;
}
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 */