aboutsummaryrefslogtreecommitdiff
path: root/src/service/fs/fs_publish_ublock.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/service/fs/fs_publish_ublock.c')
-rw-r--r--src/service/fs/fs_publish_ublock.c299
1 files changed, 299 insertions, 0 deletions
diff --git a/src/service/fs/fs_publish_ublock.c b/src/service/fs/fs_publish_ublock.c
new file mode 100644
index 000000000..ad12d9b08
--- /dev/null
+++ b/src/service/fs/fs_publish_ublock.c
@@ -0,0 +1,299 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2012, 2013 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 fs/fs_publish_ublock.c
23 * @brief publish a UBLOCK in GNUnet
24 * @see https://gnunet.org/encoding and #2564
25 * @author Krista Bennett
26 * @author Christian Grothoff
27 */
28#include "platform.h"
29#include "gnunet_constants.h"
30#include "gnunet_signatures.h"
31#include "fs_publish_ublock.h"
32#include "fs_api.h"
33#include "fs_tree.h"
34
35
36/**
37 * Derive the key for symmetric encryption/decryption from
38 * the public key and the label.
39 *
40 * @param skey where to store symmetric key
41 * @param iv where to store the IV
42 * @param label label to use for key derivation
43 * @param pub public key to use for key derivation
44 */
45static void
46derive_ublock_encryption_key (struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
47 struct GNUNET_CRYPTO_SymmetricInitializationVector
48 *iv,
49 const char *label,
50 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
51{
52 struct GNUNET_HashCode key;
53
54 /* derive key from 'label' and public key of the namespace */
55 GNUNET_assert (GNUNET_YES ==
56 GNUNET_CRYPTO_kdf (&key, sizeof(key),
57 "UBLOCK-ENC", strlen ("UBLOCK-ENC"),
58 label, strlen (label),
59 pub, sizeof(*pub),
60 NULL, 0));
61 GNUNET_CRYPTO_hash_to_aes_key (&key, skey, iv);
62}
63
64
65void
66GNUNET_FS_ublock_decrypt_ (const void *input,
67 size_t input_len,
68 const struct GNUNET_CRYPTO_EcdsaPublicKey *ns,
69 const char *label,
70 void *output)
71{
72 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
73 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
74
75 derive_ublock_encryption_key (&skey, &iv,
76 label, ns);
77 GNUNET_CRYPTO_symmetric_decrypt (input, input_len,
78 &skey, &iv,
79 output);
80}
81
82
83/**
84 * Context for 'ublock_put_cont'.
85 */
86struct GNUNET_FS_PublishUblockContext
87{
88 /**
89 * Function to call when done.
90 */
91 GNUNET_FS_UBlockContinuation cont;
92
93 /**
94 * Closure of 'cont'.
95 */
96 void *cont_cls;
97
98 /**
99 * Handle for active datastore operation.
100 */
101 struct GNUNET_DATASTORE_QueueEntry *qre;
102
103 /**
104 * Task to run continuation asynchronously.
105 */
106 struct GNUNET_SCHEDULER_Task *task;
107};
108
109
110/**
111 * Continuation of #GNUNET_FS_publish_ublock_().
112 *
113 * @param cls closure of type "struct GNUNET_FS_PublishUblockContext*"
114 * @param success #GNUNET_SYSERR on failure (including timeout/queue drop)
115 * #GNUNET_NO if content was already there
116 * #GNUNET_YES (or other positive value) on success
117 * @param min_expiration minimum expiration time required for 0-priority content to be stored
118 * by the datacache at this time, zero for unknown, forever if we have no
119 * space for 0-priority content
120 * @param msg NULL on success, otherwise an error message
121 */
122static void
123ublock_put_cont (void *cls,
124 int32_t success,
125 struct GNUNET_TIME_Absolute min_expiration,
126 const char *msg)
127{
128 struct GNUNET_FS_PublishUblockContext *uc = cls;
129
130 uc->qre = NULL;
131 uc->cont (uc->cont_cls, msg);
132 GNUNET_free (uc);
133}
134
135
136/**
137 * Run the continuation.
138 *
139 * @param cls the `struct GNUNET_FS_PublishUblockContext *`
140 */
141static void
142run_cont (void *cls)
143{
144 struct GNUNET_FS_PublishUblockContext *uc = cls;
145
146 uc->task = NULL;
147 uc->cont (uc->cont_cls, NULL);
148 GNUNET_free (uc);
149}
150
151
152struct GNUNET_FS_PublishUblockContext *
153GNUNET_FS_publish_ublock_ (struct GNUNET_FS_Handle *h,
154 struct GNUNET_DATASTORE_Handle *dsh,
155 const char *label,
156 const char *ulabel,
157 const struct GNUNET_CRYPTO_EcdsaPrivateKey *ns,
158 const struct GNUNET_FS_MetaData *meta,
159 const struct GNUNET_FS_Uri *uri,
160 const struct GNUNET_FS_BlockOptions *bo,
161 enum GNUNET_FS_PublishOptions options,
162 GNUNET_FS_UBlockContinuation cont, void *cont_cls)
163{
164 struct GNUNET_FS_PublishUblockContext *uc;
165 struct GNUNET_HashCode query;
166 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
167 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
168 struct GNUNET_CRYPTO_EcdsaPrivateKey *nsd;
169 struct GNUNET_CRYPTO_EcdsaPublicKey pub;
170 char *uris;
171 size_t size;
172 char *kbe;
173 char *sptr;
174 ssize_t mdsize;
175 size_t slen;
176 size_t ulen;
177 struct UBlock *ub_plain;
178 struct UBlock *ub_enc;
179
180 /* compute ublock to publish */
181 if (NULL == meta)
182 mdsize = 0;
183 else
184 mdsize = GNUNET_FS_meta_data_get_serialized_size (meta);
185 GNUNET_assert (mdsize >= 0);
186 uris = GNUNET_FS_uri_to_string (uri);
187 slen = strlen (uris) + 1;
188 if (NULL == ulabel)
189 ulen = 1;
190 else
191 ulen = strlen (ulabel) + 1;
192 size = mdsize + sizeof(struct UBlock) + slen + ulen;
193 if (size > MAX_UBLOCK_SIZE)
194 {
195 size = MAX_UBLOCK_SIZE;
196 mdsize = size - sizeof(struct UBlock) - (slen + ulen);
197 }
198 ub_plain = GNUNET_malloc (size);
199 kbe = (char *) &ub_plain[1];
200 if (NULL != ulabel)
201 GNUNET_memcpy (kbe, ulabel, ulen);
202 kbe += ulen;
203 GNUNET_memcpy (kbe, uris, slen);
204 kbe += slen;
205 GNUNET_free (uris);
206 sptr = kbe;
207 if (NULL != meta)
208 mdsize =
209 GNUNET_FS_meta_data_serialize (meta, &sptr, mdsize,
210 GNUNET_FS_META_DATA_SERIALIZE_PART);
211 if (-1 == mdsize)
212 {
213 GNUNET_break (0);
214 GNUNET_free (ub_plain);
215 cont (cont_cls, _ ("Internal error."));
216 return NULL;
217 }
218 size = sizeof(struct UBlock) + slen + mdsize + ulen;
219
220 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
221 "Publishing under identifier `%s'\n",
222 label);
223 /* get public key of the namespace */
224 GNUNET_CRYPTO_ecdsa_key_get_public (ns,
225 &pub);
226 derive_ublock_encryption_key (&skey, &iv,
227 label, &pub);
228
229 /* encrypt ublock */
230 ub_enc = GNUNET_malloc (size);
231 GNUNET_CRYPTO_symmetric_encrypt (&ub_plain[1],
232 ulen + slen + mdsize,
233 &skey, &iv,
234 &ub_enc[1]);
235 GNUNET_free (ub_plain);
236 ub_enc->purpose.size = htonl (ulen + slen + mdsize
237 + sizeof(struct UBlock)
238 - sizeof(struct GNUNET_CRYPTO_EcdsaSignature));
239 ub_enc->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_FS_UBLOCK);
240
241 /* derive signing-key from 'label' and public key of the namespace */
242 nsd = GNUNET_CRYPTO_ecdsa_private_key_derive (ns, label, "fs-ublock");
243 GNUNET_CRYPTO_ecdsa_key_get_public (nsd,
244 &ub_enc->verification_key);
245 GNUNET_assert (GNUNET_OK ==
246 GNUNET_CRYPTO_ecdsa_sign_ (nsd,
247 &ub_enc->purpose,
248 &ub_enc->signature));
249 GNUNET_CRYPTO_hash (&ub_enc->verification_key,
250 sizeof(ub_enc->verification_key),
251 &query);
252 GNUNET_free (nsd);
253
254 uc = GNUNET_new (struct GNUNET_FS_PublishUblockContext);
255 uc->cont = cont;
256 uc->cont_cls = cont_cls;
257 if (NULL != dsh)
258 {
259 uc->qre =
260 GNUNET_DATASTORE_put (dsh,
261 0,
262 &query,
263 ulen + slen + mdsize + sizeof(struct UBlock),
264 ub_enc,
265 GNUNET_BLOCK_TYPE_FS_UBLOCK,
266 bo->content_priority,
267 bo->anonymity_level,
268 bo->replication_level,
269 bo->expiration_time,
270 -2, 1,
271 &ublock_put_cont, uc);
272 }
273 else
274 {
275 uc->task = GNUNET_SCHEDULER_add_now (&run_cont,
276 uc);
277 }
278 GNUNET_free (ub_enc);
279 return uc;
280}
281
282
283/**
284 * Abort UBlock publishing operation.
285 *
286 * @param uc operation to abort.
287 */
288void
289GNUNET_FS_publish_ublock_cancel_ (struct GNUNET_FS_PublishUblockContext *uc)
290{
291 if (NULL != uc->qre)
292 GNUNET_DATASTORE_cancel (uc->qre);
293 if (NULL != uc->task)
294 GNUNET_SCHEDULER_cancel (uc->task);
295 GNUNET_free (uc);
296}
297
298
299/* end of fs_publish_ublock.c */