2 This file is part of GNUnet
3 Copyright (C) 2013, 2016 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.
16 * @file revocation/revocation_api.c
17 * @brief API to perform and access key revocations
18 * @author Christian Grothoff
21 #include "gnunet_revocation_service.h"
22 #include "gnunet_signatures.h"
23 #include "gnunet_protocols.h"
24 #include "revocation.h"
29 * Handle for the key revocation query.
31 struct GNUNET_REVOCATION_Query
35 * Message queue to the service.
37 struct GNUNET_MQ_Handle *mq;
40 * Function to call with the result.
42 GNUNET_REVOCATION_Callback func;
45 * Closure for @e func.
53 * Generic error handler, called with the appropriate
54 * error code and the same closure specified at the creation of
56 * Not every message queue implementation supports an error handler.
58 * @param cls closure with the `struct GNUNET_NSE_Handle *`
59 * @param error error code
62 query_mq_error_handler (void *cls,
63 enum GNUNET_MQ_Error error)
65 struct GNUNET_REVOCATION_Query *q = cls;
67 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
68 "Revocation query MQ error\n");
71 GNUNET_REVOCATION_query_cancel (q);
76 * Handle response to our revocation query.
78 * @param cls our `struct GNUNET_REVOCATION_Query` handle
79 * @param qrm response we got
82 handle_revocation_query_response (void *cls,
83 const struct QueryResponseMessage *qrm)
85 struct GNUNET_REVOCATION_Query *q = cls;
87 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
88 "Revocation query result: %d\n",
89 (uint32_t) ntohl (qrm->is_valid));
91 ntohl (qrm->is_valid));
92 GNUNET_REVOCATION_query_cancel (q);
97 * Check if a key was revoked.
99 * @param cfg the configuration to use
100 * @param key key to check for revocation
101 * @param func funtion to call with the result of the check
102 * @param func_cls closure to pass to @a func
103 * @return handle to use in #GNUNET_REVOCATION_query_cancel to stop REVOCATION from invoking the callback
105 struct GNUNET_REVOCATION_Query *
106 GNUNET_REVOCATION_query (const struct GNUNET_CONFIGURATION_Handle *cfg,
107 const struct GNUNET_CRYPTO_EcdsaPublicKey *key,
108 GNUNET_REVOCATION_Callback func,
111 struct GNUNET_REVOCATION_Query *q
112 = GNUNET_new (struct GNUNET_REVOCATION_Query);
113 struct GNUNET_MQ_MessageHandler handlers[] = {
114 GNUNET_MQ_hd_fixed_size (revocation_query_response,
115 GNUNET_MESSAGE_TYPE_REVOCATION_QUERY_RESPONSE,
116 struct QueryResponseMessage,
118 GNUNET_MQ_handler_end ()
120 struct QueryMessage *qm;
121 struct GNUNET_MQ_Envelope *env;
123 q->mq = GNUNET_CLIENT_connect (cfg,
126 &query_mq_error_handler,
134 q->func_cls = func_cls;
135 env = GNUNET_MQ_msg (qm,
136 GNUNET_MESSAGE_TYPE_REVOCATION_QUERY);
137 qm->reserved = htonl (0);
139 GNUNET_MQ_send (q->mq,
146 * Cancel key revocation check.
148 * @param q query to cancel
151 GNUNET_REVOCATION_query_cancel (struct GNUNET_REVOCATION_Query *q)
155 GNUNET_MQ_destroy (q->mq);
163 * Handle for the key revocation operation.
165 struct GNUNET_REVOCATION_Handle
169 * Message queue to the service.
171 struct GNUNET_MQ_Handle *mq;
174 * Function to call once we are done.
176 GNUNET_REVOCATION_Callback func;
179 * Closure for @e func.
187 * Generic error handler, called with the appropriate
188 * error code and the same closure specified at the creation of
190 * Not every message queue implementation supports an error handler.
192 * @param cls closure with the `struct GNUNET_NSE_Handle *`
193 * @param error error code
196 revocation_mq_error_handler (void *cls,
197 enum GNUNET_MQ_Error error)
199 struct GNUNET_REVOCATION_Handle *h = cls;
201 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
202 "Revocation MQ error\n");
203 h->func (h->func_cls,
205 GNUNET_REVOCATION_revoke_cancel (h);
210 * Handle response to our revocation query.
212 * @param cls our `struct GNUNET_REVOCATION_Handle` handle
213 * @param rrm response we got
216 handle_revocation_response (void *cls,
217 const struct RevocationResponseMessage *rrm)
219 struct GNUNET_REVOCATION_Handle *h = cls;
221 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
222 "Revocation transmission result: %d\n",
223 (uint32_t) ntohl (rrm->is_valid));
224 h->func (h->func_cls,
225 ntohl (rrm->is_valid));
226 GNUNET_REVOCATION_revoke_cancel (h);
231 * Perform key revocation.
233 * @param cfg the configuration to use
234 * @param key public key of the key to revoke
235 * @param sig signature to use on the revocation (should have been
236 * created using #GNUNET_REVOCATION_sign_revocation).
237 * @param pow proof of work to use (should have been created by
238 * iteratively calling #GNUNET_REVOCATION_check_pow)
239 * @param func funtion to call with the result of the check
240 * (called with `is_valid` being #GNUNET_NO if
241 * the revocation worked).
242 * @param func_cls closure to pass to @a func
243 * @return handle to use in #GNUNET_REVOCATION_revoke_cancel to stop REVOCATION from invoking the callback
245 struct GNUNET_REVOCATION_Handle *
246 GNUNET_REVOCATION_revoke (const struct GNUNET_CONFIGURATION_Handle *cfg,
247 const struct GNUNET_CRYPTO_EcdsaPublicKey *key,
248 const struct GNUNET_CRYPTO_EcdsaSignature *sig,
250 GNUNET_REVOCATION_Callback func,
253 struct GNUNET_REVOCATION_Handle *h
254 = GNUNET_new (struct GNUNET_REVOCATION_Handle);
255 struct GNUNET_MQ_MessageHandler handlers[] = {
256 GNUNET_MQ_hd_fixed_size (revocation_response,
257 GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE_RESPONSE,
258 struct RevocationResponseMessage,
260 GNUNET_MQ_handler_end ()
262 unsigned long long matching_bits;
263 struct RevokeMessage *rm;
264 struct GNUNET_MQ_Envelope *env;
267 GNUNET_CONFIGURATION_get_value_number (cfg,
272 GNUNET_REVOCATION_check_pow (key,
274 (unsigned int) matching_bits)) )
281 h->mq = GNUNET_CLIENT_connect (cfg,
284 &revocation_mq_error_handler,
292 h->func_cls = func_cls;
293 env = GNUNET_MQ_msg (rm,
294 GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE);
295 rm->reserved = htonl (0);
296 rm->proof_of_work = pow;
297 rm->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_REVOCATION);
298 rm->purpose.size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
299 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
300 rm->public_key = *key;
301 rm->signature = *sig;
302 GNUNET_MQ_send (h->mq,
309 * Cancel key revocation.
311 * @param h operation to cancel
314 GNUNET_REVOCATION_revoke_cancel (struct GNUNET_REVOCATION_Handle *h)
318 GNUNET_MQ_destroy (h->mq);
326 * Calculate the 'proof-of-work' hash (an expensive hash).
328 * @param buf data to hash
329 * @param buf_len number of bytes in @a buf
330 * @param result where to write the resulting hash
333 pow_hash (const void *buf,
335 struct GNUNET_HashCode *result)
338 gcry_kdf_derive (buf, buf_len,
341 "gnunet-revocation-proof-of-work",
342 strlen ("gnunet-revocation-proof-of-work"),
343 2 /* iterations; keep cost of individual op small */,
344 sizeof (struct GNUNET_HashCode), result));
349 * Count the leading zeroes in hash.
351 * @param hash to count leading zeros in
352 * @return the number of leading zero bits.
355 count_leading_zeroes (const struct GNUNET_HashCode *hash)
357 unsigned int hash_count;
360 while ((0 == GNUNET_CRYPTO_hash_get_bit (hash, hash_count)))
367 * Check if the given proof-of-work value
368 * would be acceptable for revoking the given key.
370 * @param key key to check for
371 * @param pow proof of work value
372 * @param matching_bits how many bits must match (configuration)
373 * @return #GNUNET_YES if the @a pow is acceptable, #GNUNET_NO if not
376 GNUNET_REVOCATION_check_pow (const struct GNUNET_CRYPTO_EcdsaPublicKey *key,
378 unsigned int matching_bits)
380 char buf[sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) +
381 sizeof (pow)] GNUNET_ALIGN;
382 struct GNUNET_HashCode result;
384 GNUNET_memcpy (buf, &pow, sizeof (pow));
385 GNUNET_memcpy (&buf[sizeof (pow)], key,
386 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
387 pow_hash (buf, sizeof (buf), &result);
388 return (count_leading_zeroes (&result) >=
389 matching_bits) ? GNUNET_YES : GNUNET_NO;
394 * Create a revocation signature.
396 * @param key private key of the key to revoke
397 * @param sig where to write the revocation signature
400 GNUNET_REVOCATION_sign_revocation (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
401 struct GNUNET_CRYPTO_EcdsaSignature *sig)
403 struct RevokeMessage rm;
405 rm.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_REVOCATION);
406 rm.purpose.size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
407 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
408 GNUNET_CRYPTO_ecdsa_key_get_public (key, &rm.public_key);
409 GNUNET_assert (GNUNET_OK ==
410 GNUNET_CRYPTO_ecdsa_sign (key,
416 /* end of revocation_api.c */