2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2012, 2013 GNUnet e.V.
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.
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.
17 * @file fs/fs_publish_ublock.c
18 * @brief publish a UBLOCK in GNUnet
19 * @see https://gnunet.org/encoding and #2564
20 * @author Krista Bennett
21 * @author Christian Grothoff
24 #include "gnunet_constants.h"
25 #include "gnunet_signatures.h"
26 #include "fs_publish_ublock.h"
32 * Derive the key for symmetric encryption/decryption from
33 * the public key and the label.
35 * @param skey where to store symmetric key
36 * @param iv where to store the IV
37 * @param label label to use for key derivation
38 * @param pub public key to use for key derivation
41 derive_ublock_encryption_key (struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
42 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
44 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
46 struct GNUNET_HashCode key;
48 /* derive key from 'label' and public key of the namespace */
49 GNUNET_assert (GNUNET_YES ==
50 GNUNET_CRYPTO_kdf (&key, sizeof (key),
51 "UBLOCK-ENC", strlen ("UBLOCK-ENC"),
52 label, strlen (label),
55 GNUNET_CRYPTO_hash_to_aes_key (&key, skey, iv);
60 * Decrypt the given UBlock, storing the result in output.
62 * @param input input data
63 * @param input_len number of bytes in @a input
64 * @param ns public key under which the UBlock was stored
65 * @param label label under which the UBlock was stored
66 * @param output where to write the result, has input_len bytes
69 GNUNET_FS_ublock_decrypt_ (const void *input,
71 const struct GNUNET_CRYPTO_EcdsaPublicKey *ns,
75 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
76 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
78 derive_ublock_encryption_key (&skey, &iv,
80 GNUNET_CRYPTO_symmetric_decrypt (input, input_len,
87 * Context for 'ublock_put_cont'.
89 struct GNUNET_FS_PublishUblockContext
93 * Function to call when done.
95 GNUNET_FS_UBlockContinuation cont;
103 * Handle for active datastore operation.
105 struct GNUNET_DATASTORE_QueueEntry *qre;
108 * Task to run continuation asynchronously.
110 struct GNUNET_SCHEDULER_Task * task;
116 * Continuation of #GNUNET_FS_publish_ublock_().
118 * @param cls closure of type "struct GNUNET_FS_PublishUblockContext*"
119 * @param success #GNUNET_SYSERR on failure (including timeout/queue drop)
120 * #GNUNET_NO if content was already there
121 * #GNUNET_YES (or other positive value) on success
122 * @param min_expiration minimum expiration time required for 0-priority content to be stored
123 * by the datacache at this time, zero for unknown, forever if we have no
124 * space for 0-priority content
125 * @param msg NULL on success, otherwise an error message
128 ublock_put_cont (void *cls,
130 struct GNUNET_TIME_Absolute min_expiration,
133 struct GNUNET_FS_PublishUblockContext *uc = cls;
136 uc->cont (uc->cont_cls, msg);
142 * Run the continuation.
144 * @param cls the `struct GNUNET_FS_PublishUblockContext *`
149 struct GNUNET_FS_PublishUblockContext *uc = cls;
152 uc->cont (uc->cont_cls, NULL);
160 * @param h handle to the file sharing subsystem
161 * @param dsh datastore handle to use for storage operation
162 * @param label identifier to use
163 * @param ulabel update label to use, may be an empty string for none
164 * @param ns namespace to publish in
165 * @param meta metadata to use
166 * @param uri URI to refer to in the UBlock
167 * @param bo per-block options
168 * @param options publication options
169 * @param cont continuation
170 * @param cont_cls closure for @a cont
171 * @return NULL on error (@a cont will still be called)
173 struct GNUNET_FS_PublishUblockContext *
174 GNUNET_FS_publish_ublock_ (struct GNUNET_FS_Handle *h,
175 struct GNUNET_DATASTORE_Handle *dsh,
178 const struct GNUNET_CRYPTO_EcdsaPrivateKey *ns,
179 const struct GNUNET_CONTAINER_MetaData *meta,
180 const struct GNUNET_FS_Uri *uri,
181 const struct GNUNET_FS_BlockOptions *bo,
182 enum GNUNET_FS_PublishOptions options,
183 GNUNET_FS_UBlockContinuation cont, void *cont_cls)
185 struct GNUNET_FS_PublishUblockContext *uc;
186 struct GNUNET_HashCode query;
187 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
188 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
189 struct GNUNET_CRYPTO_EcdsaPrivateKey *nsd;
190 struct GNUNET_CRYPTO_EcdsaPublicKey pub;
198 struct UBlock *ub_plain;
199 struct UBlock *ub_enc;
201 /* compute ublock to publish */
205 mdsize = GNUNET_CONTAINER_meta_data_get_serialized_size (meta);
206 GNUNET_assert (mdsize >= 0);
207 uris = GNUNET_FS_uri_to_string (uri);
208 slen = strlen (uris) + 1;
212 ulen = strlen (ulabel) + 1;
213 size = mdsize + sizeof (struct UBlock) + slen + ulen;
214 if (size > MAX_UBLOCK_SIZE)
216 size = MAX_UBLOCK_SIZE;
217 mdsize = size - sizeof (struct UBlock) - (slen + ulen);
219 ub_plain = GNUNET_malloc (size);
220 kbe = (char *) &ub_plain[1];
222 GNUNET_memcpy (kbe, ulabel, ulen);
224 GNUNET_memcpy (kbe, uris, slen);
230 GNUNET_CONTAINER_meta_data_serialize (meta, &sptr, mdsize,
231 GNUNET_CONTAINER_META_DATA_SERIALIZE_PART);
235 GNUNET_free (ub_plain);
236 cont (cont_cls, _("Internal error."));
239 size = sizeof (struct UBlock) + slen + mdsize + ulen;
241 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
242 "Publishing under identifier `%s'\n",
244 /* get public key of the namespace */
245 GNUNET_CRYPTO_ecdsa_key_get_public (ns,
247 derive_ublock_encryption_key (&skey, &iv,
251 ub_enc = GNUNET_malloc (size);
252 GNUNET_CRYPTO_symmetric_encrypt (&ub_plain[1],
253 ulen + slen + mdsize,
256 GNUNET_free (ub_plain);
257 ub_enc->purpose.size = htonl (ulen + slen + mdsize +
258 sizeof (struct UBlock)
259 - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
260 ub_enc->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_FS_UBLOCK);
262 /* derive signing-key from 'label' and public key of the namespace */
263 nsd = GNUNET_CRYPTO_ecdsa_private_key_derive (ns, label, "fs-ublock");
264 GNUNET_CRYPTO_ecdsa_key_get_public (nsd,
265 &ub_enc->verification_key);
266 GNUNET_assert (GNUNET_OK ==
267 GNUNET_CRYPTO_ecdsa_sign (nsd,
269 &ub_enc->signature));
270 GNUNET_CRYPTO_hash (&ub_enc->verification_key,
271 sizeof (ub_enc->verification_key),
275 uc = GNUNET_new (struct GNUNET_FS_PublishUblockContext);
277 uc->cont_cls = cont_cls;
281 GNUNET_DATASTORE_put (dsh,
284 ulen + slen + mdsize + sizeof (struct UBlock),
286 GNUNET_BLOCK_TYPE_FS_UBLOCK,
287 bo->content_priority,
289 bo->replication_level,
292 &ublock_put_cont, uc);
296 uc->task = GNUNET_SCHEDULER_add_now (&run_cont,
299 GNUNET_free (ub_enc);
305 * Abort UBlock publishing operation.
307 * @param uc operation to abort.
310 GNUNET_FS_publish_ublock_cancel_ (struct GNUNET_FS_PublishUblockContext *uc)
313 GNUNET_DATASTORE_cancel (uc->qre);
314 if (NULL != uc->task)
315 GNUNET_SCHEDULER_cancel (uc->task);
319 /* end of fs_publish_ublock.c */