From fc58d9d4241ed2dcd4b492b4f922ba959449a697 Mon Sep 17 00:00:00 2001 From: Andreas Ebner Date: Sun, 7 Jul 2019 15:04:40 +0200 Subject: Implemented delegate sign and store function for GNS entries: - functions to store and sign delegates (all types) including serialization/string_to_value/.. - solved (almost) all TODOs - some renaming and cleanup in gnunet-credential.c - valgrind checked - test file adapted accordingly --- src/credential/delegate_misc.c | 250 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 src/credential/delegate_misc.c (limited to 'src/credential/delegate_misc.c') diff --git a/src/credential/delegate_misc.c b/src/credential/delegate_misc.c new file mode 100644 index 000000000..d900ccd1f --- /dev/null +++ b/src/credential/delegate_misc.c @@ -0,0 +1,250 @@ +/* + 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/delegate_misc.c + * @brief Misc API for delegate + * + * @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 "delegate.h" +#include + +char* +GNUNET_CREDENTIAL_delegate_to_string (const struct GNUNET_CREDENTIAL_Delegate *cred) +{ + char *cred_str; + char *subject_pkey; + char *issuer_pkey; + char *signature; + + subject_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key); + issuer_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key); + GNUNET_STRINGS_base64_encode ((char*)&cred->signature, + sizeof (struct GNUNET_CRYPTO_EcdsaSignature), + &signature); + if(0 == cred->subject_attribute_len){ + GNUNET_asprintf (&cred_str, + "%s.%s -> %s | %s | %"SCNu64, + issuer_pkey, + cred->issuer_attribute, + subject_pkey, + signature, + cred->expiration.abs_value_us); + } else { + GNUNET_asprintf (&cred_str, + "%s.%s -> %s.%s | %s | %"SCNu64, + issuer_pkey, + cred->issuer_attribute, + subject_pkey, + cred->subject_attribute, + signature, + cred->expiration.abs_value_us); + } + GNUNET_free (subject_pkey); + GNUNET_free (issuer_pkey); + GNUNET_free (signature); + + return cred_str; +} + +struct GNUNET_CREDENTIAL_Delegate* +GNUNET_CREDENTIAL_delegate_from_string (const char* s) +{ + struct GNUNET_CREDENTIAL_Delegate *cred; + size_t enclen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8; + if (enclen % 5 > 0) + enclen += 5 - enclen % 5; + enclen /= 5; /* 260/5 = 52 */ + char subject_pkey[enclen + 1]; + char issuer_pkey[enclen + 1]; + char iss_attr[253 + 1]; + // Needs to be initialized, in case of Type 1 credential (A.a <- B) + char sub_attr[253 + 1] = ""; + char signature[256]; //TODO max payload size + + struct GNUNET_CRYPTO_EcdsaSignature *sig; + struct GNUNET_TIME_Absolute etime_abs; + + // If it's A.a <- B.b... + if (6 != SSCANF (s, + "%52s.%253s -> %52s.%253s | %s | %"SCNu64, + issuer_pkey, + iss_attr, + subject_pkey, + sub_attr, + signature, + &etime_abs.abs_value_us)) + { + // Try if it's A.a <- B + if (5 != SSCANF (s, + "%52s.%253s -> %52s | %s | %"SCNu64, + issuer_pkey, + iss_attr, + subject_pkey, + signature, + &etime_abs.abs_value_us)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unable to parse DEL record string `%s'\n", s); + return NULL; + } + } + + // +1 for \0 + int attr_len; + if(strcmp(sub_attr,"") == 0) { + attr_len = strlen (iss_attr) + 1; + } else { + attr_len = strlen (iss_attr) + strlen(sub_attr) + 1; + } + cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Delegate) + attr_len); + + char tmp_str[attr_len]; + GNUNET_memcpy(tmp_str, iss_attr, strlen(iss_attr)); + if(strcmp(sub_attr,"") != 0) { + GNUNET_memcpy(tmp_str + strlen(iss_attr), sub_attr, strlen(sub_attr)); + } + tmp_str[attr_len - 1] = '\0'; + + GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_pkey, + strlen (subject_pkey), + &cred->subject_key); + GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_pkey, + strlen (issuer_pkey), + &cred->issuer_key); + GNUNET_assert (sizeof (struct GNUNET_CRYPTO_EcdsaSignature) == GNUNET_STRINGS_base64_decode (signature, + strlen (signature), + (char**)&sig)); + cred->signature = *sig; + cred->expiration = etime_abs; + GNUNET_free (sig); + GNUNET_memcpy (&cred[1], + tmp_str, + attr_len); + + cred->issuer_attribute_len = strlen (iss_attr); + cred->issuer_attribute = strdup(iss_attr); + if(strcmp(sub_attr,"") == 0) { + cred->subject_attribute_len = 0; + cred->subject_attribute = '\0'; + } else { + cred->subject_attribute_len = strlen (sub_attr); + cred->subject_attribute = strdup(sub_attr); + } + + return cred; +} + +/** + * Issue an attribute to a subject + * + * @param issuer the ego that should be used to issue the attribute + * @param subject the subject of the attribute + * @param attribute the name of the attribute + * @return handle to the queued request + */ + +struct GNUNET_CREDENTIAL_Delegate * +GNUNET_CREDENTIAL_delegate_issue (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer, + struct GNUNET_CRYPTO_EcdsaPublicKey *subject, + const char *iss_attr, + const char *sub_attr, + struct GNUNET_TIME_Absolute *expiration) +{ + struct DelegateEntry *crd; + struct GNUNET_CREDENTIAL_Delegate *cred; + size_t size; + int attr_len; + + if (NULL == sub_attr){ + // +1 for \0 + attr_len = strlen (iss_attr) + 1; + } else { + attr_len = strlen (iss_attr) + strlen(sub_attr) + 1; + } + size = sizeof (struct DelegateEntry) + attr_len; + + char tmp_str[attr_len]; + GNUNET_memcpy(tmp_str, iss_attr, strlen(iss_attr)); + if (NULL != sub_attr){ + GNUNET_memcpy(tmp_str + strlen(iss_attr), sub_attr, strlen(sub_attr)); + } + tmp_str[attr_len - 1] = '\0'; + + crd = GNUNET_malloc (size); + crd->purpose.size = htonl (size - sizeof (struct GNUNET_CRYPTO_EcdsaSignature)); + crd->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL); + GNUNET_CRYPTO_ecdsa_key_get_public (issuer, + &crd->issuer_key); + crd->subject_key = *subject; + crd->expiration = GNUNET_htonll (expiration->abs_value_us); + crd->issuer_attribute_len = htonl (strlen (iss_attr) + 1); + if (NULL == sub_attr){ + crd->subject_attribute_len = htonl (0); + } else { + crd->subject_attribute_len = htonl (strlen (sub_attr) + 1); + } + + GNUNET_memcpy (&crd[1], + tmp_str, + attr_len); + + if (GNUNET_OK != + GNUNET_CRYPTO_ecdsa_sign (issuer, + &crd->purpose, + &crd->signature)) + { + GNUNET_break (0); + GNUNET_free (crd); + return NULL; + } + + cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Delegate) + attr_len); + cred->signature = crd->signature; + cred->expiration = *expiration; + GNUNET_CRYPTO_ecdsa_key_get_public (issuer, + &cred->issuer_key); + + cred->subject_key = *subject; + cred->issuer_attribute = strdup(iss_attr); + cred->issuer_attribute_len = strlen(iss_attr); + if (NULL == sub_attr){ + cred->subject_attribute = '\0'; + cred->subject_attribute_len = 0; + } else { + cred->subject_attribute = strdup(sub_attr); + cred->subject_attribute_len = strlen(sub_attr); + } + + GNUNET_memcpy (&cred[1], + tmp_str, + attr_len); + + GNUNET_free (crd); + return cred; +} + + -- cgit v1.2.3