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