aboutsummaryrefslogtreecommitdiff
path: root/src/service/reclaim/did_core.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/service/reclaim/did_core.c')
-rw-r--r--src/service/reclaim/did_core.c270
1 files changed, 270 insertions, 0 deletions
diff --git a/src/service/reclaim/did_core.c b/src/service/reclaim/did_core.c
new file mode 100644
index 000000000..5804a0d7e
--- /dev/null
+++ b/src/service/reclaim/did_core.c
@@ -0,0 +1,270 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2010-2015 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 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file reclaim/did_core.c
23 * @brief Core functionality for DID
24 * @author Tristan Schwieren
25 */
26
27// TODO: DID documents do not have an expiration date. Still we add one
28// TODO: Store DID document with empty label and own type (maybe DID-Document or JSON??)
29
30#include "did_core.h"
31
32struct DID_resolve_return
33{
34 DID_resolve_callback *cb;
35 void *cls;
36};
37
38struct DID_action_return
39{
40 DID_action_callback *cb;
41 void *cls;
42};
43
44// ------------------------------------------------ //
45// -------------------- Resolve ------------------- //
46// ------------------------------------------------ //
47
48/**
49 * @brief GNS lookup callback. Calls the given callback function
50 * and gives it the DID Document.
51 * Fails if there is more than one DID record.
52 *
53 * @param cls closure
54 * @param rd_count number of records in rd
55 * @param rd the records in the reply
56 */
57static void
58DID_resolve_gns_lookup_cb (
59 void *cls,
60 uint32_t rd_count,
61 const struct GNUNET_GNSRECORD_Data *rd)
62{
63 char *did_document;
64 DID_resolve_callback *cb = ((struct DID_resolve_return *) cls)->cb;
65 void *cls_did_resolve_cb = ((struct DID_resolve_return *) cls)->cls;
66 free (cls);
67
68 for (int i = 0; i < rd_count; i++)
69 {
70 if (rd[i].record_type != GNUNET_GNSRECORD_TYPE_DID_DOCUMENT)
71 continue;
72 did_document = (char *) rd[i].data;
73 cb (GNUNET_OK, did_document, cls_did_resolve_cb);
74 return;
75 }
76 cb (GNUNET_NO, "DID Document is not a DID_DOCUMENT record\n",
77 cls_did_resolve_cb);
78}
79
80
81/**
82 * @brief Resolve a DID.
83 * Calls the given callback function with the resolved DID Document and the given closure.
84 * If the did can not be resolved did_document is NULL.
85 *
86 * @param did DID that is resolve
87 */
88enum GNUNET_GenericReturnValue
89DID_resolve (const char *did,
90 struct GNUNET_GNS_Handle *gns_handle,
91 DID_resolve_callback *cont,
92 void *cls)
93{
94 struct GNUNET_CRYPTO_PublicKey pkey;
95
96 // did, gns_handle and cont must me set
97 if ((did == NULL) || (gns_handle == NULL) || (cont == NULL))
98 return GNUNET_NO;
99
100 if (GNUNET_OK != DID_did_to_pkey (did, &pkey))
101 return GNUNET_NO;
102
103 // Create closure for lookup callback
104 struct DID_resolve_return *cls_gns_lookup_cb
105 = malloc (sizeof(struct DID_resolve_return));
106 cls_gns_lookup_cb->cb = cont;
107 cls_gns_lookup_cb->cls = cls;
108
109 GNUNET_GNS_lookup (gns_handle,
110 DID_DOCUMENT_LABEL,
111 &pkey,
112 GNUNET_GNSRECORD_TYPE_DID_DOCUMENT,
113 GNUNET_GNS_LO_DEFAULT,
114 &DID_resolve_gns_lookup_cb,
115 cls_gns_lookup_cb);
116
117 return GNUNET_OK;
118}
119
120
121// ------------------------------------------------ //
122// -------------------- Create -------------------- //
123// ------------------------------------------------ //
124
125static void
126DID_create_did_store_cb (void *cls,
127 enum GNUNET_ErrorCode ec)
128{
129 DID_action_callback *cb = ((struct DID_action_return *) cls)->cb;
130 void *cls_did_create_cb = ((struct DID_action_return *) cls)->cls;
131 free (cls);
132
133 if (GNUNET_EC_NONE == ec)
134 {
135 cb (GNUNET_OK, (void *) cls_did_create_cb);
136 }
137 else
138 {
139 // TODO: Log emsg. Not writing it to STDOUT
140 printf ("%s\n", GNUNET_ErrorCode_get_hint (ec));
141 cb (GNUNET_NO, (void *) cls_did_create_cb);
142 }
143}
144
145
146struct DID_create_namestore_lookup_closure
147{
148 const char *did_document;
149 struct GNUNET_TIME_Relative expire_time;
150 struct GNUNET_NAMESTORE_Handle *namestore_handle;
151 struct DID_action_return *ret;
152};
153
154static void
155DID_create_namestore_lookup_cb (void *cls,
156 const struct
157 GNUNET_CRYPTO_PrivateKey *zone,
158 const char *label,
159 unsigned int rd_count,
160 const struct GNUNET_GNSRECORD_Data *rd)
161{
162 struct GNUNET_GNSRECORD_Data record_data;
163 struct GNUNET_CRYPTO_PublicKey pkey;
164
165 const char *did_document
166 = ((struct DID_create_namestore_lookup_closure *) cls)->did_document;
167
168 const struct GNUNET_TIME_Relative expire_time
169 = ((struct DID_create_namestore_lookup_closure *) cls)->expire_time;
170
171 struct GNUNET_NAMESTORE_Handle *namestore_handle
172 = ((struct DID_create_namestore_lookup_closure *) cls)->namestore_handle;
173
174 struct DID_action_return *cls_record_store_cb
175 = ((struct DID_create_namestore_lookup_closure *) cls)->ret;
176
177 free (cls);
178
179 if (rd_count > 0)
180 {
181 printf ("Ego already has a DID Document. Abort.\n");
182 cls_record_store_cb->cb (GNUNET_NO, cls_record_store_cb->cls);
183 }
184 else
185 {
186 // Get public key
187 GNUNET_CRYPTO_key_get_public (zone, &pkey);
188
189 // If no DID Document is given a default one is created
190 if (did_document != NULL)
191 printf (
192 "DID Docuement is read from \"DID-document\" argument (EXPERIMENTAL)\n");
193 else
194 did_document = DID_pkey_to_did_document (&pkey);
195
196 // Create record
197 record_data.data = did_document;
198 record_data.expiration_time = expire_time.rel_value_us;
199 record_data.data_size = strlen (did_document) + 1;
200 record_data.record_type = GNUNET_GNSRECORD_typename_to_number ("TXT"),
201 record_data.flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
202
203 // Store record
204 GNUNET_NAMESTORE_record_set_store (namestore_handle,
205 zone,
206 DID_DOCUMENT_LABEL,
207 1, // FIXME what if GNUNET_GNS_EMPTY_LABEL_AT has records
208 &record_data,
209 &DID_create_did_store_cb,
210 (void *) cls_record_store_cb);
211 }
212}
213
214
215/**
216 * @brief Creates a DID and saves DID Document in Namestore.
217 *
218 * @param ego ego for which the DID should be created.
219 * @param did_document did_document that should be saved in namestore.
220 * If did_document==NULL -> Default DID document is created.
221 * @param namestore_handle
222 * @param cont callback function
223 * @param cls closure
224 */
225enum GNUNET_GenericReturnValue
226DID_create (const struct GNUNET_IDENTITY_Ego *ego,
227 const char *did_document,
228 const struct GNUNET_TIME_Relative *expire_time,
229 struct GNUNET_NAMESTORE_Handle *namestore_handle,
230 DID_action_callback *cont,
231 void *cls)
232{
233 struct GNUNET_CRYPTO_PublicKey pkey;
234
235 // Ego, namestore_handle and cont must be set
236 if ((ego == NULL) || (namestore_handle == NULL) || (cont == NULL))
237 return GNUNET_NO;
238
239 // Check if ego has EdDSA key
240 GNUNET_IDENTITY_ego_get_public_key ((struct GNUNET_IDENTITY_Ego *) ego,
241 &pkey);
242 if (ntohl (pkey.type) != GNUNET_GNSRECORD_TYPE_EDKEY)
243 {
244 printf ("The EGO has to have an EdDSA key pair\n");
245 return GNUNET_NO;
246 }
247
248 struct DID_action_return *ret
249 = malloc (sizeof(struct DID_action_return));
250 ret->cb = cont;
251 ret->cls = cls;
252
253 struct DID_create_namestore_lookup_closure *cls_name_store_lookup_cb
254 = malloc (sizeof(struct DID_create_namestore_lookup_closure));
255 cls_name_store_lookup_cb->did_document = did_document;
256 cls_name_store_lookup_cb->expire_time = (*expire_time);
257 cls_name_store_lookup_cb->namestore_handle = namestore_handle;
258 cls_name_store_lookup_cb->ret = ret;
259
260 // Check if ego already has a DID Document
261 GNUNET_NAMESTORE_records_lookup (namestore_handle,
262 GNUNET_IDENTITY_ego_get_private_key (ego),
263 DID_DOCUMENT_LABEL,
264 NULL,
265 NULL,
266 DID_create_namestore_lookup_cb,
267 (void *) cls_name_store_lookup_cb);
268
269 return GNUNET_OK;
270}