2 This file is part of GNUnet.
3 (C) 2009, 2010, 2012, 2013 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 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 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
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
29 #include "gnunet_constants.h"
30 #include "gnunet_signatures.h"
31 #include "fs_publish_ublock.h"
37 * Derive the key for symmetric encryption/decryption from
38 * the public key and the label.
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
46 derive_ublock_encryption_key (struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
47 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
49 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
51 struct GNUNET_HashCode key;
53 /* derive key from 'label' and public key of the namespace */
54 GNUNET_assert (GNUNET_YES ==
55 GNUNET_CRYPTO_kdf (&key, sizeof (key),
56 "UBLOCK-ENC", strlen ("UBLOCK-ENC"),
57 label, strlen (label),
60 GNUNET_CRYPTO_hash_to_aes_key (&key, skey, iv);
65 * Decrypt the given UBlock, storing the result in output.
67 * @param input input data
68 * @param input_len number of bytes in @a input
69 * @param ns public key under which the UBlock was stored
70 * @param label label under which the UBlock was stored
71 * @param output where to write the result, has input_len bytes
74 GNUNET_FS_ublock_decrypt_ (const void *input,
76 const struct GNUNET_CRYPTO_EcdsaPublicKey *ns,
80 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
81 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
83 derive_ublock_encryption_key (&skey, &iv,
85 GNUNET_CRYPTO_symmetric_decrypt (input, input_len,
92 * Context for 'ublock_put_cont'.
94 struct GNUNET_FS_PublishUblockContext
98 * Function to call when done.
100 GNUNET_FS_UBlockContinuation cont;
108 * Handle for active datastore operation.
110 struct GNUNET_DATASTORE_QueueEntry *qre;
115 * Continuation of "GNUNET_FS_publish_ublock_".
117 * @param cls closure of type "struct GNUNET_FS_PublishUblockContext*"
118 * @param success GNUNET_SYSERR on failure (including timeout/queue drop)
119 * GNUNET_NO if content was already there
120 * GNUNET_YES (or other positive value) on success
121 * @param min_expiration minimum expiration time required for 0-priority content to be stored
122 * by the datacache at this time, zero for unknown, forever if we have no
123 * space for 0-priority content
124 * @param msg NULL on success, otherwise an error message
127 ublock_put_cont (void *cls,
129 struct GNUNET_TIME_Absolute min_expiration,
132 struct GNUNET_FS_PublishUblockContext *uc = cls;
135 uc->cont (uc->cont_cls, msg);
143 * @param h handle to the file sharing subsystem
144 * @param dsh datastore handle to use for storage operation
145 * @param label identifier to use
146 * @param ulabel update label to use, may be an empty string for none
147 * @param ns namespace to publish in
148 * @param meta metadata to use
149 * @param uri URI to refer to in the UBlock
150 * @param bo per-block options
151 * @param options publication options
152 * @param cont continuation
153 * @param cont_cls closure for @a cont
154 * @return NULL on error (@a cont will still be called)
156 struct GNUNET_FS_PublishUblockContext *
157 GNUNET_FS_publish_ublock_ (struct GNUNET_FS_Handle *h,
158 struct GNUNET_DATASTORE_Handle *dsh,
161 const struct GNUNET_CRYPTO_EcdsaPrivateKey *ns,
162 const struct GNUNET_CONTAINER_MetaData *meta,
163 const struct GNUNET_FS_Uri *uri,
164 const struct GNUNET_FS_BlockOptions *bo,
165 enum GNUNET_FS_PublishOptions options,
166 GNUNET_FS_UBlockContinuation cont, void *cont_cls)
168 struct GNUNET_FS_PublishUblockContext *uc;
169 struct GNUNET_HashCode query;
170 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
171 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
172 struct GNUNET_CRYPTO_EcdsaPrivateKey *nsd;
173 struct GNUNET_CRYPTO_EcdsaPublicKey pub;
181 struct UBlock *ub_plain;
182 struct UBlock *ub_enc;
184 /* compute ublock to publish */
188 mdsize = GNUNET_CONTAINER_meta_data_get_serialized_size (meta);
189 GNUNET_assert (mdsize >= 0);
190 uris = GNUNET_FS_uri_to_string (uri);
191 slen = strlen (uris) + 1;
195 ulen = strlen (ulabel) + 1;
196 size = mdsize + sizeof (struct UBlock) + slen + ulen;
197 if (size > MAX_UBLOCK_SIZE)
199 size = MAX_UBLOCK_SIZE;
200 mdsize = size - sizeof (struct UBlock) - (slen + ulen);
202 ub_plain = GNUNET_malloc (size);
203 kbe = (char *) &ub_plain[1];
205 memcpy (kbe, ulabel, ulen);
207 memcpy (kbe, uris, slen);
213 GNUNET_CONTAINER_meta_data_serialize (meta, &sptr, mdsize,
214 GNUNET_CONTAINER_META_DATA_SERIALIZE_PART);
218 GNUNET_free (ub_plain);
219 cont (cont_cls, _("Internal error."));
222 size = sizeof (struct UBlock) + slen + mdsize + ulen;
224 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
225 "Publishing under identifier `%s'\n",
227 /* get public key of the namespace */
228 GNUNET_CRYPTO_ecdsa_key_get_public (ns,
230 derive_ublock_encryption_key (&skey, &iv,
234 ub_enc = GNUNET_malloc (size);
235 GNUNET_CRYPTO_symmetric_encrypt (&ub_plain[1],
236 ulen + slen + mdsize,
239 GNUNET_free (ub_plain);
240 ub_enc->purpose.size = htonl (ulen + slen + mdsize +
241 sizeof (struct UBlock)
242 - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
243 ub_enc->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_FS_UBLOCK);
245 /* derive signing-key from 'label' and public key of the namespace */
246 nsd = GNUNET_CRYPTO_ecdsa_private_key_derive (ns, label, "fs-ublock");
247 GNUNET_CRYPTO_ecdsa_key_get_public (nsd,
248 &ub_enc->verification_key);
249 GNUNET_assert (GNUNET_OK ==
250 GNUNET_CRYPTO_ecdsa_sign (nsd,
252 &ub_enc->signature));
253 GNUNET_CRYPTO_hash (&ub_enc->verification_key,
254 sizeof (ub_enc->verification_key),
258 uc = GNUNET_new (struct GNUNET_FS_PublishUblockContext);
260 uc->cont_cls = cont_cls;
262 GNUNET_DATASTORE_put (dsh, 0, &query,
263 ulen + slen + mdsize + sizeof (struct UBlock),
264 ub_enc, GNUNET_BLOCK_TYPE_FS_UBLOCK,
265 bo->content_priority, bo->anonymity_level,
266 bo->replication_level, bo->expiration_time,
267 -2, 1, GNUNET_CONSTANTS_SERVICE_TIMEOUT,
268 &ublock_put_cont, uc);
274 * Abort UBlock publishing operation.
276 * @param uc operation to abort.
279 GNUNET_FS_publish_ublock_cancel_ (struct GNUNET_FS_PublishUblockContext *uc)
281 GNUNET_DATASTORE_cancel (uc->qre);