-fixing main FS build, updating man page of gnunet-pseudonym
[oweals/gnunet.git] / src / fs / fs_publish_ublock.c
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  */ 
45 void
46 GNUNET_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  */
59 struct 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  */
91 static void
92 ublock_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  */
121 struct GNUNET_FS_PublishUblockContext *
122 GNUNET_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  */
257 void
258 GNUNET_FS_publish_ublock_cancel_ (struct GNUNET_FS_PublishUblockContext *uc)
259 {
260   GNUNET_DATASTORE_cancel (uc->qre);
261   GNUNET_free (uc);
262 }