-ensure external symbols have proper prefix for conversation service
[oweals/gnunet.git] / src / revocation / revocation_api.c
1 /*
2       This file is part of GNUnet
3       (C) 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 Licerevocation 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 Licerevocation for more details.
14
15       You should have received a copy of the GNU General Public Licerevocation
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  * @file revocation/revocation_api.c
22  * @brief API to perform and access key revocations
23  * @author Christian Grothoff
24  */
25 #include "platform.h"
26 #include "gnunet_revocation_service.h"
27 #include "gnunet_signatures.h"
28 #include "gnunet_protocols.h"
29 #include "revocation.h"
30 #include <gcrypt.h>
31
32
33 /**
34  * Handle for the key revocation query.
35  */
36 struct GNUNET_REVOCATION_Query
37 {
38
39   /**
40    * Connection to the service.
41    */
42   struct GNUNET_CLIENT_Connection *client;
43   
44   /**
45    * Our configuration.
46    */
47   const struct GNUNET_CONFIGURATION_Handle *cfg;
48
49   /**
50    * Key to check.
51    */
52   struct GNUNET_CRYPTO_EccPublicSignKey key;
53
54   /**
55    * Function to call with the result.
56    */
57   GNUNET_REVOCATION_Callback func;
58
59   /**
60    * Closure for @e func.
61    */
62   void *func_cls;
63 };
64
65
66 /**
67  * Check if a key was revoked.
68  *
69  * @param cfg the configuration to use
70  * @param key key to check for revocation
71  * @param func funtion to call with the result of the check
72  * @param func_cls closure to pass to @a func
73  * @return handle to use in #GNUNET_REVOCATION_query_cancel to stop REVOCATION from invoking the callback
74  */
75 struct GNUNET_REVOCATION_Query *
76 GNUNET_REVOCATION_query (const struct GNUNET_CONFIGURATION_Handle *cfg,
77                          const struct GNUNET_CRYPTO_EccPublicSignKey *key,
78                          GNUNET_REVOCATION_Callback func, void *func_cls)
79 {
80   struct GNUNET_REVOCATION_Query *q;
81
82   q = GNUNET_new (struct GNUNET_REVOCATION_Query);
83   q->client = GNUNET_CLIENT_connect ("revocation", cfg);
84   q->cfg = cfg;
85   q->key = *key;
86   q->func = func;
87   q->func_cls = func_cls;
88   GNUNET_break (0);
89   return q;
90 }
91
92
93 /**
94  * Cancel key revocation check.
95  *
96  * @param q query to cancel
97  */
98 void
99 GNUNET_REVOCATION_query_cancel (struct GNUNET_REVOCATION_Query *q)
100 {
101   GNUNET_CLIENT_disconnect (q->client);
102   GNUNET_free (q);
103 }
104
105
106 /**
107  * Handle for the key revocation operation.
108  */
109 struct GNUNET_REVOCATION_Handle
110 {
111   
112   /**
113    * Connection to the service.
114    */
115   struct GNUNET_CLIENT_Connection *client;
116   
117   /**
118    * Our configuration.
119    */
120   const struct GNUNET_CONFIGURATION_Handle *cfg;
121
122   /**
123    * Key to revoke.
124    */
125   struct GNUNET_CRYPTO_EccPublicSignKey key;
126
127   /**
128    * Signature showing that we have the right to revoke.
129    */
130   struct GNUNET_CRYPTO_EccSignature sig;
131
132   /**
133    * Proof of work showing that we spent enough resources to broadcast revocation.
134    */
135   uint64_t pow;
136
137   /**
138    * Function to call once we are done.
139    */
140   GNUNET_REVOCATION_Callback func;
141
142   /**
143    * Closure for @e func.
144    */
145   void *func_cls;
146
147 };
148
149
150 /**
151  * Perform key revocation.
152  *
153  * @param cfg the configuration to use
154  * @param key public key of the key to revoke
155  * @param sig signature to use on the revocation (should have been
156  *            created using #GNUNET_REVOCATION_sign_revocation).
157  * @param pow proof of work to use (should have been created by
158  *            iteratively calling #GNUNET_REVOCATION_check_pow)
159  * @param func funtion to call with the result of the check
160  *             (called with `is_valid` being #GNUNET_NO if
161  *              the revocation worked).
162  * @param func_cls closure to pass to @a func
163  * @return handle to use in #GNUNET_REVOCATION_cancel to stop REVOCATION from invoking the callback
164  */
165 struct GNUNET_REVOCATION_Handle *
166 GNUNET_REVOCATION_revoke (const struct GNUNET_CONFIGURATION_Handle *cfg,
167                           const struct GNUNET_CRYPTO_EccPublicSignKey *key,
168                           const struct GNUNET_CRYPTO_EccSignature *sig,
169                           uint64_t pow,
170                           GNUNET_REVOCATION_Callback func, void *func_cls)
171 {
172   struct GNUNET_REVOCATION_Handle *h;
173
174   h = GNUNET_new (struct GNUNET_REVOCATION_Handle);
175   h->client = GNUNET_CLIENT_connect ("revocation", cfg);
176   h->cfg = cfg;
177   h->key = *key;
178   h->sig = *sig;
179   h->pow = pow;
180   h->func = func;
181   h->func_cls = func_cls;
182   GNUNET_break (0);
183   return h;
184 }
185
186
187 /**
188  * Cancel key revocation.
189  *
190  * @param h operation to cancel
191  */
192 void
193 GNUNET_REVOCATION_revoke_cancel (struct GNUNET_REVOCATION_Handle *h)
194 {
195   GNUNET_CLIENT_disconnect (h->client);
196   GNUNET_free (h);
197 }
198
199
200
201 /**
202  * Calculate the 'proof-of-work' hash (an expensive hash).
203  *
204  * @param buf data to hash
205  * @param buf_len number of bytes in @a buf
206  * @param result where to write the resulting hash
207  */
208 static void
209 pow_hash (const void *buf,
210           size_t buf_len,
211           struct GNUNET_HashCode *result)
212 {
213   GNUNET_break (0 == 
214                 gcry_kdf_derive (buf, buf_len,
215                                  GCRY_KDF_SCRYPT,
216                                  1 /* subalgo */,
217                                  "gnunet-revocation-proof-of-work", 
218                                  strlen ("gnunet-revocation-proof-of-work"),
219                                  2 /* iterations; keep cost of individual op small */,
220                                  sizeof (struct GNUNET_HashCode), result));
221 }
222
223
224 /**
225  * Count the leading zeroes in hash.
226  *
227  * @param hash to count leading zeros in
228  * @return the number of leading zero bits.
229  */
230 static unsigned int
231 count_leading_zeroes (const struct GNUNET_HashCode *hash)
232 {
233   unsigned int hash_count;
234
235   hash_count = 0;
236   while ((0 == GNUNET_CRYPTO_hash_get_bit (hash, hash_count)))
237     hash_count++;
238   return hash_count;
239 }
240
241
242 /**
243  * Check if the given proof-of-work value
244  * would be acceptable for revoking the given key.
245  *
246  * @param key key to check for
247  * @param pow proof of work value
248  * @param matching_bits how many bits must match (configuration)
249  * @return #GNUNET_YES if the @a pow is acceptable, #GNUNET_NO if not
250  */
251 int
252 GNUNET_REVOCATION_check_pow (const struct GNUNET_CRYPTO_EccPublicSignKey *key,
253                              uint64_t pow,
254                              unsigned int matching_bits)
255 {
256   char buf[sizeof (struct GNUNET_CRYPTO_EccPublicSignKey) +
257            sizeof (pow)] GNUNET_ALIGN;
258   struct GNUNET_HashCode result;
259
260   memcpy (buf, &pow, sizeof (pow));
261   memcpy (&buf[sizeof (pow)], key,
262           sizeof (struct GNUNET_CRYPTO_EccPublicSignKey));
263   pow_hash (buf, sizeof (buf), &result);
264   return (count_leading_zeroes (&result) >=
265           matching_bits) ? GNUNET_YES : GNUNET_NO;
266 }
267
268
269 /**
270  * Create a revocation signature.
271  *
272  * @param key private key of the key to revoke
273  * @param sig where to write the revocation signature
274  */
275 void
276 GNUNET_REVOCATION_sign_revocation (const struct GNUNET_CRYPTO_EccPrivateKey *key,
277                                    struct GNUNET_CRYPTO_EccSignature *sig)
278 {
279   struct GNUNET_REVOCATION_RevokeMessage rm;
280
281   rm.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_REVOCATION);
282   rm.purpose.size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
283                            sizeof (struct GNUNET_CRYPTO_EccPublicSignKey));
284   GNUNET_CRYPTO_ecc_key_get_public_for_signature (key, &rm.public_key);
285   GNUNET_assert (GNUNET_OK ==
286                  GNUNET_CRYPTO_ecc_sign (key,
287                                          &rm.purpose,
288                                          sig));
289 }
290
291
292 /* end of revocation_api.c */
293