aboutsummaryrefslogtreecommitdiff
path: root/src/fs/fs_publish_ublock.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fs/fs_publish_ublock.c')
-rw-r--r--src/fs/fs_publish_ublock.c262
1 files changed, 262 insertions, 0 deletions
diff --git a/src/fs/fs_publish_ublock.c b/src/fs/fs_publish_ublock.c
new file mode 100644
index 000000000..9ddff0655
--- /dev/null
+++ b/src/fs/fs_publish_ublock.c
@@ -0,0 +1,262 @@
1/*
2 This file is part of GNUnet.
3 (C) 2009, 2010, 2012, 2013 Christian Grothoff (and other contributing authors)
4
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.
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 General Public License for more details.
14
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.
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 * Decrypt the given UBlock, storing the result in output.
38 *
39 * @param input input data
40 * @param input_len number of bytes in input
41 * @param ns public key under which the UBlock was stored
42 * @param label label under which the UBlock was stored
43 * @param output where to write the result, has input_len bytes
44 */
45void
46GNUNET_FS_ublock_decrypt_ (const void *input,
47 size_t input_len,
48 const struct GNUNET_CRYPTO_EccPublicKey *ns,
49 const char *label,
50 void *output)
51{
52 GNUNET_break (0);
53}
54
55
56/**
57 * Context for 'ublock_put_cont'.
58 */
59struct GNUNET_FS_PublishUblockContext
60{
61
62 /**
63 * Function to call when done.
64 */
65 GNUNET_FS_UBlockContinuation cont;
66
67 /**
68 * Closure of 'cont'.
69 */
70 void *cont_cls;
71
72 /**
73 * Handle for active datastore operation.
74 */
75 struct GNUNET_DATASTORE_QueueEntry *qre;
76};
77
78
79/**
80 * Continuation of "GNUNET_FS_publish_ublock_".
81 *
82 * @param cls closure of type "struct GNUNET_FS_PublishUblockContext*"
83 * @param success GNUNET_SYSERR on failure (including timeout/queue drop)
84 * GNUNET_NO if content was already there
85 * GNUNET_YES (or other positive value) on success
86 * @param min_expiration minimum expiration time required for 0-priority content to be stored
87 * by the datacache at this time, zero for unknown, forever if we have no
88 * space for 0-priority content
89 * @param msg NULL on success, otherwise an error message
90 */
91static void
92ublock_put_cont (void *cls,
93 int32_t success,
94 struct GNUNET_TIME_Absolute min_expiration,
95 const char *msg)
96{
97 struct GNUNET_FS_PublishUblockContext *uc = cls;
98
99 uc->qre = NULL;
100 uc->cont (uc->cont_cls, msg);
101 GNUNET_free (uc);
102}
103
104
105/**
106 * Publish a UBlock.
107 *
108 * @param h handle to the file sharing subsystem
109 * @param dsh datastore handle to use for storage operation
110 * @param label identifier to use
111 * @param ulabel update label to use, may be an empty string for none
112 * @param ns namespace to publish in
113 * @param meta metadata to use
114 * @param uri URI to refer to in the UBlock
115 * @param bo per-block options
116 * @param options publication options
117 * @param cont continuation
118 * @param cont_cls closure for cont
119 * @return NULL on error ('cont' will still be called)
120 */
121struct GNUNET_FS_PublishUblockContext *
122GNUNET_FS_publish_ublock_ (struct GNUNET_FS_Handle *h,
123 struct GNUNET_DATASTORE_Handle *dsh,
124 const char *label,
125 const char *ulabel,
126 const struct GNUNET_CRYPTO_EccPrivateKey *ns,
127 const struct GNUNET_CONTAINER_MetaData *meta,
128 const struct GNUNET_FS_Uri *uri,
129 const struct GNUNET_FS_BlockOptions *bo,
130 enum GNUNET_FS_PublishOptions options,
131 GNUNET_FS_UBlockContinuation cont, void *cont_cls)
132{
133 struct GNUNET_FS_PublishUblockContext *uc;
134 struct GNUNET_HashCode key;
135 struct GNUNET_HashCode seed;
136 struct GNUNET_HashCode signing_key;
137 struct GNUNET_HashCode query;
138 struct GNUNET_CRYPTO_AesSessionKey skey;
139 struct GNUNET_CRYPTO_AesInitializationVector iv;
140 struct GNUNET_CRYPTO_EccPrivateKey *nsd;
141 struct GNUNET_CRYPTO_EccPublicKey pub;
142 char *uris;
143 size_t size;
144 char *kbe;
145 char *sptr;
146 ssize_t mdsize;
147 size_t slen;
148 size_t ulen;
149 struct UBlock *ub_plain;
150 struct UBlock *ub_enc;
151
152 /* compute ublock to publish */
153 if (NULL == meta)
154 mdsize = 0;
155 else
156 mdsize = GNUNET_CONTAINER_meta_data_get_serialized_size (meta);
157 GNUNET_assert (mdsize >= 0);
158 uris = GNUNET_FS_uri_to_string (uri);
159 slen = strlen (uris) + 1;
160 ulen = strlen (ulabel) + 1;
161 size = mdsize + sizeof (struct UBlock) + slen + ulen;
162 if (size > MAX_UBLOCK_SIZE)
163 {
164 size = MAX_UBLOCK_SIZE;
165 mdsize = size - sizeof (struct UBlock) - (slen + ulen);
166 }
167 ub_plain = GNUNET_malloc (size);
168 kbe = (char *) &ub_plain[1];
169 memcpy (kbe, ulabel, ulen);
170 kbe += ulen;
171 memcpy (kbe, uris, slen);
172 kbe += slen;
173 GNUNET_free (uris);
174 sptr = kbe;
175 if (NULL != meta)
176 mdsize =
177 GNUNET_CONTAINER_meta_data_serialize (meta, &sptr, mdsize,
178 GNUNET_CONTAINER_META_DATA_SERIALIZE_PART);
179 if (-1 == mdsize)
180 {
181 GNUNET_break (0);
182 GNUNET_free (ub_plain);
183 cont (cont_cls, _("Internal error."));
184 return NULL;
185 }
186 size = sizeof (struct UBlock) + slen + mdsize + ulen;
187
188 /* derive signing seed from plaintext */
189 GNUNET_CRYPTO_hash (&ub_plain[1],
190 ulen + slen + mdsize,
191 &seed);
192 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
193 "Publishing under identifier `%s'\n",
194 label);
195 /* get public key of the namespace */
196 GNUNET_CRYPTO_ecc_key_get_public (ns,
197 &pub);
198 /* derive key from 'label' and public key of the namespace */
199 GNUNET_assert (GNUNET_YES ==
200 GNUNET_CRYPTO_kdf (&key, sizeof (key),
201 "UBLOCK-ENC", strlen ("UBLOCK-ENC"),
202 label, strlen (label),
203 &pub, sizeof (pub),
204 NULL, 0));
205 GNUNET_CRYPTO_hash_to_aes_key (&key, &skey, &iv);
206
207 /* encrypt ublock */
208 ub_enc = GNUNET_malloc (size);
209 GNUNET_CRYPTO_aes_encrypt (&ub_plain[1],
210 ulen + slen + mdsize,
211 &skey, &iv,
212 &ub_enc[1]);
213 ub_enc->purpose.size = htonl (ulen + slen + mdsize +
214 sizeof (struct UBlock)
215 - sizeof (struct GNUNET_CRYPTO_EccSignature));
216 ub_enc->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_FS_UBLOCK);
217
218 /* derive signing-key from 'label' and public key of the namespace */
219 GNUNET_assert (GNUNET_YES ==
220 GNUNET_CRYPTO_kdf (&signing_key, sizeof (signing_key),
221 "UBLOCK-SIGN", strlen ("UBLOCK-SIGN"),
222 label, strlen (label),
223 &pub, sizeof (pub),
224 NULL, 0));
225 nsd = GNUNET_CRYPTO_ecc_key_derive (ns, label);
226 GNUNET_CRYPTO_ecc_key_get_public (nsd,
227 &ub_enc->verification_key);
228 GNUNET_assert (GNUNET_OK ==
229 GNUNET_CRYPTO_ecc_sign (nsd,
230 &ub_enc->purpose,
231 &ub_enc->signature));
232 GNUNET_CRYPTO_hash (&ub_enc->verification_key,
233 sizeof (ub_enc->verification_key),
234 &query);
235 GNUNET_CRYPTO_ecc_key_free (nsd);
236
237 uc = GNUNET_new (struct GNUNET_FS_PublishUblockContext);
238 uc->cont = cont;
239 uc->cont_cls = cont_cls;
240 uc->qre =
241 GNUNET_DATASTORE_put (dsh, 0, &query,
242 ulen + slen + mdsize + sizeof (struct UBlock),
243 ub_enc, GNUNET_BLOCK_TYPE_FS_UBLOCK,
244 bo->content_priority, bo->anonymity_level,
245 bo->replication_level, bo->expiration_time,
246 -2, 1, GNUNET_CONSTANTS_SERVICE_TIMEOUT,
247 &ublock_put_cont, uc);
248 return uc;
249}
250
251
252/**
253 * Abort UBlock publishing operation.
254 *
255 * @param uc operation to abort.
256 */
257void
258GNUNET_FS_publish_ublock_cancel_ (struct GNUNET_FS_PublishUblockContext *uc)
259{
260 GNUNET_DATASTORE_cancel (uc->qre);
261 GNUNET_free (uc);
262}