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