bugfixes
[oweals/gnunet.git] / src / credential / credential_misc.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2009-2013, 2016 GNUnet e.V.
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, USA.
19 */
20
21
22 /**
23  * @file credential/credential_misc.c
24  * @brief Misc API for credentials
25  *
26  * @author Martin Schanzenbach
27  */
28 #include "platform.h"
29 #include "gnunet_util_lib.h"
30 #include "gnunet_constants.h"
31 #include "gnunet_credential_service.h"
32 #include "gnunet_signatures.h"
33 #include "credential.h"
34 #include <inttypes.h>
35
36 char*
37 GNUNET_CREDENTIAL_credential_to_string (const struct GNUNET_CREDENTIAL_Credential *cred)
38 {
39   char *cred_str;
40   char *subject_pkey;
41   char *issuer_pkey;
42   char *signature;
43
44
45   subject_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
46   issuer_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
47   GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
48                                 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
49                                 &signature);
50   GNUNET_asprintf (&cred_str,
51                    "%s.%s -> %s | %s | %"SCNu64,
52                    issuer_pkey,
53                    cred->issuer_attribute,
54                    subject_pkey,
55                    signature,
56                    cred->expiration.abs_value_us);
57   GNUNET_free (subject_pkey);
58   GNUNET_free (issuer_pkey);
59   GNUNET_free (signature);
60   return cred_str;
61 }
62
63 struct GNUNET_CREDENTIAL_Credential*
64 GNUNET_CREDENTIAL_credential_from_string (const char* s)
65 {
66   struct GNUNET_CREDENTIAL_Credential *cred;
67   size_t enclen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
68   if (enclen % 5 > 0)
69     enclen += 5 - enclen % 5;
70   enclen /= 5; /* 260/5 = 52 */
71   char subject_pkey[enclen + 1];
72   char issuer_pkey[enclen + 1];
73   char name[253 + 1];
74   char signature[256]; //TODO max payload size
75
76   struct GNUNET_CRYPTO_EcdsaSignature *sig;
77   struct GNUNET_TIME_Absolute etime_abs;
78
79   if (5 != SSCANF (s,
80                    "%52s.%253s -> %52s | %s | %"SCNu64,
81                    issuer_pkey,
82                    name,
83                    subject_pkey,
84                    signature,
85                    &etime_abs.abs_value_us))
86   {
87     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
88                 _("Unable to parse CRED record string `%s'\n"),
89                 s);
90     return NULL;
91   }
92   cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + strlen (name) + 1);
93   GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_pkey,
94                                               strlen (subject_pkey),
95                                               &cred->subject_key);
96   GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_pkey,
97                                               strlen (issuer_pkey),
98                                               &cred->issuer_key);
99   GNUNET_assert (sizeof (struct GNUNET_CRYPTO_EcdsaSignature) == GNUNET_STRINGS_base64_decode (signature,
100                                 strlen (signature),
101                                 (char**)&sig));
102   cred->signature = *sig;
103   cred->expiration = etime_abs;
104   GNUNET_free (sig);
105   GNUNET_memcpy (&cred[1],
106                  name,
107                  strlen (name)+1);
108   cred->issuer_attribute_len = strlen ((char*)&cred[1]);
109   cred->issuer_attribute = (char*)&cred[1];
110   return cred;
111 }
112
113 /**
114  * Issue an attribute to a subject
115  *
116  * @param issuer the ego that should be used to issue the attribute
117  * @param subject the subject of the attribute
118  * @param attribute the name of the attribute
119  * @return handle to the queued request
120  */
121 struct GNUNET_CREDENTIAL_Credential *
122 GNUNET_CREDENTIAL_credential_issue (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
123                                     struct GNUNET_CRYPTO_EcdsaPublicKey *subject,
124                                     const char *attribute,
125                                     struct GNUNET_TIME_Absolute *expiration)
126 {
127   struct CredentialEntry *crd;
128   struct GNUNET_CREDENTIAL_Credential *cred;
129   size_t size;
130
131   size = sizeof (struct CredentialEntry) + strlen (attribute) + 1;
132   crd = GNUNET_malloc (size);
133   cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + strlen (attribute) + 1);
134   crd->purpose.size = htonl (size - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
135
136   crd->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
137   GNUNET_CRYPTO_ecdsa_key_get_public (issuer,
138                                       &crd->issuer_key);
139   crd->subject_key = *subject;
140   crd->expiration = GNUNET_htonll (expiration->abs_value_us);
141   crd->issuer_attribute_len = htonl (strlen (attribute)+1);
142   GNUNET_memcpy ((char*)&crd[1],
143                  attribute,
144                  strlen (attribute)+1);
145   if (GNUNET_OK !=
146       GNUNET_CRYPTO_ecdsa_sign (issuer,
147                                 &crd->purpose,
148                                 &crd->signature))
149   {
150     GNUNET_break (0);
151     GNUNET_free (crd);
152     GNUNET_free (cred);
153     return NULL;
154   }
155   cred->signature = crd->signature;
156   cred->expiration = *expiration;
157   GNUNET_CRYPTO_ecdsa_key_get_public (issuer,
158                                       &cred->issuer_key);
159
160   cred->subject_key = *subject;
161   GNUNET_memcpy (&cred[1],
162                  attribute,
163                  strlen (attribute)+1);
164   cred->issuer_attribute = (char*)&cred[1];
165   GNUNET_free (crd);
166   return cred;
167 }
168
169