The Assimilation Project  based on Assimilation version 0.5.1441048221
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
cryptframe.c
Go to the documentation of this file.
1 
25 #include <string.h>
26 #include <projectcommon.h>
27 #include <frameset.h>
28 #include <cryptframe.h>
29 #include <frametypes.h>
30 #include <generic_tlv_min.h>
31 #include <tlvhelper.h>
32 #include <misc.h>
33 #include <sodium.h>
34 
36 
37 
42 FSTATIC gboolean _cryptframe_default_isvalid(const Frame *, gconstpointer, gconstpointer);
46 static void (*_parentclass_finalize)(AssimObj*) = NULL;
47 
49 FSTATIC gboolean
51  gconstpointer tlvptr,
52  gconstpointer pktend)
53 {
54  (void)self;
55  (void)tlvptr;
56  (void)pktend;
57 
59  g_return_val_if_reached(FALSE);
60 }
61 
63 FSTATIC void
65 {
66  CryptFrame* self = CASTTOCLASS(CryptFrame, aself);
67  if (self->sender_key_id) {
68  g_free(self->sender_key_id);
69  self->sender_key_id = NULL;
70  }
71  if (self->receiver_key_id) {
72  g_free(self->receiver_key_id);
73  self->receiver_key_id = NULL;
74  }
75  _parentclass_finalize(aself);
76 }
77 
82 cryptframe_new( guint16 frame_type,
83  const char * sender_key_id,
84  const char * receiver_key_id,
85  gsize objsize)
86 {
87  Frame* baseframe;
88  CryptFrame* self;
89 
91  if (objsize < sizeof(CryptFrame)) {
92  objsize = sizeof(CryptFrame);
93  }
94  baseframe = frame_new(frame_type, objsize);
95  if (!_parentclass_finalize) {
96  _parentclass_finalize = baseframe->baseclass._finalize;
97  }
100  self = NEWSUBCLASS(CryptFrame, baseframe);
101  self->sender_key_id = g_strdup(sender_key_id);
102  self->receiver_key_id = g_strdup(receiver_key_id);
103  return self;
104 }
108 cryptframe_tlvconstructor(gpointer tlvstart,
109  gconstpointer pktend,
110  gpointer* ignorednewpkt,
111  gpointer* ignoredpktend)
112 {
113  (void)tlvstart;
114  (void)pktend;
115  (void)ignorednewpkt;
116  (void)ignoredpktend;
117  // Abstract base class - can't do this...
118  g_return_val_if_reached(NULL);
119 }
120 #define DEBUGCKSUM3(msg, buf) {if (DEBUG >= 3) _cryptframe_debug_checksum(__FUNCTION__, __LINE__, msg, buf);}
121 #define DEBUGCKSUM4(msg, buf) {if (DEBUG >= 4) _cryptframe_debug_checksum(__FUNCTION__, __LINE__, msg, buf);}
124 FSTATIC void _cryptframe_debug_checksum(const char * function, int lineno, const char * message, const guint8* buf);
126 // All our hash tables have strings for keys
127 static GHashTable* public_key_map = NULL;
128 static GHashTable* private_key_map = NULL;
129 static GHashTable* identity_map_by_key_id = NULL;
130 static GHashTable* key_id_map_by_identity = NULL;
131 GHashTable* addr_to_public_key_map = NULL;
136 static CryptFramePrivateKey* default_signing_key = NULL;
137 #define INITMAPS {if (!maps_inityet) {_cryptframe_initialize_maps();}}
138 static gboolean maps_inityet = FALSE;
139 
141 FSTATIC void
143 {
144  if (maps_inityet) {
145  return;
146  }
147  key_id_map_by_identity = g_hash_table_new_full(g_str_hash, g_str_equal
148  , NULL, (GDestroyNotify)g_hash_table_destroy);
149  identity_map_by_key_id = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
150  public_key_map = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, assim_g_notify_unref);
151  private_key_map = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, assim_g_notify_unref);
152  addr_to_public_key_map = g_hash_table_new_full(netaddr_g_hash_hash
154  maps_inityet = TRUE;
155 }
156 
158 WINEXPORT void
160 {
161  g_hash_table_destroy(key_id_map_by_identity); key_id_map_by_identity=NULL;
162  g_hash_table_destroy(identity_map_by_key_id); identity_map_by_key_id=NULL;
163  g_hash_table_destroy(public_key_map); public_key_map=NULL;
164  g_hash_table_destroy(private_key_map); private_key_map=NULL;
165  g_hash_table_destroy(addr_to_public_key_map); addr_to_public_key_map=NULL;
166  if (default_signing_key) {
167  UNREF(default_signing_key);
168  }
169  maps_inityet = FALSE;
170 }
171 
173 FSTATIC void
175 {
177  if (self->key_id) {
178  g_free(self->key_id);
179  self->key_id = NULL;
180  }
181  if (self->public_key) {
182  g_free(self->public_key);
183  self->public_key = NULL;
184  }
185  _assimobj_finalize(pubkey);
186 }
187 
189 FSTATIC void
191 {
193  if (self->key_id) {
194  g_free(self->key_id);
195  self->key_id = NULL;
196  }
197  if (self->private_key) {
198  g_free(self->private_key);
199  self->private_key = NULL;
200  }
201  _assimobj_finalize(privkey);
202 }
204 FSTATIC void
205 _cryptframe_debug_checksum( const char * function,
206  int lineno,
207  const char * message,
208  const guint8* buf)
209 {
210  char * checksum = g_compute_checksum_for_data(G_CHECKSUM_MD5, buf, 32); // HARDWIRED!!
211  g_debug("%s.%d: %s [%d]%s", function, lineno, message, 32, checksum);
212  g_free(checksum);
213 }
214 
216 
217 
220 cryptframe_publickey_new (const char *key_id,
221  gpointer public_key)
222 {
223  AssimObj* aself;
224  CryptFramePublicKey* self;
225  INITMAPS;
226  g_return_val_if_fail(key_id != NULL && public_key != NULL, NULL);
227  self = cryptframe_public_key_by_id(key_id);
228  if (self) {
229  return self;
230  }
231  aself = assimobj_new(sizeof(CryptFramePublicKey));
233  self = NEWSUBCLASS(CryptFramePublicKey, aself);
234  self->key_id = g_strdup(key_id);
235  self->key_size = crypto_box_PUBLICKEYBYTES;
236  self->frame_type = FRAMETYPE_PUBKEYCURVE25519;
237  self->public_key = public_key;
238  g_hash_table_insert(public_key_map, self->key_id, self);
239  DEBUGCKSUM3(self->key_id, public_key);
240  return self;
241 }
242 
245 cryptframe_privatekey_new(const char *key_id,
246  gpointer private_key)
247 {
248  AssimObj* aself;
249  CryptFramePrivateKey* self;
250  INITMAPS;
251  g_return_val_if_fail(key_id != NULL && private_key != NULL, NULL);
252  self = cryptframe_private_key_by_id(key_id);
253  if (self) {
254  g_warning("%s.%d: Private key %s Already IN private key map", __FUNCTION__, __LINE__, key_id);
255  return self;
256  }
257  aself = assimobj_new(sizeof(CryptFramePrivateKey));
259  self = NEWSUBCLASS(CryptFramePrivateKey, aself);
260  self->key_id = g_strdup(key_id);
261  self->key_size = crypto_box_SECRETKEYBYTES;
262  self->private_key = private_key;
263  g_hash_table_insert(private_key_map, self->key_id, self);
264  DEBUGCKSUM3(self->key_id, private_key);
265  return self;
266 }
267 
270 cryptframe_public_key_by_id(const char* key_id)
271 {
272  gpointer ret;
273  INITMAPS;
274  ret = (key_id ? g_hash_table_lookup(public_key_map, key_id): NULL);
275  return (ret ? CASTTOCLASS(CryptFramePublicKey, ret): NULL);
276 }
279 cryptframe_private_key_by_id(const char* key_id)
280 {
281  gpointer ret;
282  INITMAPS;
283  ret = (key_id ? g_hash_table_lookup(private_key_map, key_id): NULL);
284  return (ret ? CASTTOCLASS(CryptFramePrivateKey, ret): NULL);
285 }
286 
292 WINEXPORT gboolean
293 cryptframe_associate_identity(const char * identity,
294  const char * key_id)
295 {
296  GHashTable* key_id_map;
297  const char* found_identity;
298  char* key_id_duplicate;
299  char* identity_duplicate;
300  INITMAPS;
301  g_return_val_if_fail(key_id != NULL && identity != NULL, FALSE);
302  if (cryptframe_public_key_by_id(key_id) == NULL) {
303  g_critical("%s.%d: no public key associated with key id %s"
304  , __FUNCTION__, __LINE__, key_id);
305  return FALSE;
306  }
307  found_identity = cryptframe_whois_key_id(key_id);
308  if (found_identity) {
309  if (strcmp(found_identity, identity) != 0) {
310  g_critical("%s.%d: Key id %s cannot be associated with identity %s."
311  " Already associated with identity %s", __FUNCTION__, __LINE__
312  , key_id, identity, found_identity);
313  return FALSE;
314  }
315  return TRUE;
316  }
317  key_id_duplicate = g_strdup(key_id);
318  identity_duplicate = g_strdup(identity);
319  g_hash_table_insert(identity_map_by_key_id, key_id_duplicate, identity_duplicate);
320 
321  key_id_map = cryptframe_key_ids_for(identity);
322  if (NULL == key_id_map) {
323  key_id_map = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
324  g_hash_table_insert(key_id_map_by_identity, identity_duplicate, key_id_map);
325  }
326  if (!g_hash_table_lookup((GHashTable*)key_id_map, key_id)) {
327  g_hash_table_insert(key_id_map, key_id_duplicate, key_id_duplicate);
328  }
329  return TRUE;
330 }
331 
333 WINEXPORT gboolean
334 cryptframe_dissociate_identity(const char * identity,
335  const char * key_id)
336 {
337  char* found_identity;
338  GHashTable* key_id_map;
339  INITMAPS;
340 
341  g_return_val_if_fail(identity != NULL && key_id != NULL, FALSE);
342 
343  found_identity = g_hash_table_lookup(identity_map_by_key_id, key_id);
344  if (NULL == found_identity) {
345  return FALSE;
346  }
347  // The order of these deletions matters - because of shared data between tables.
348  key_id_map = cryptframe_key_ids_for(identity);
349  if (key_id_map) {
350  g_hash_table_remove(key_id_map, key_id);
351  if (g_hash_table_size(key_id_map) == 0) {
352  // This identity doesn't meaningfully exist any more...
353  g_hash_table_remove(key_id_map_by_identity, identity);
354  }
355  }
356  g_hash_table_remove(identity_map_by_key_id, key_id);
357  return TRUE;
358 }
359 
361 WINEXPORT const char*
363 {
365  INITMAPS;
366  return cryptframe_whois_key_id(public_key->key_id);
367 }
368 
370 WINEXPORT const char*
371 cryptframe_whois_key_id(const char * key_id)
372 {
373  INITMAPS;
374  return (key_id ? (const char *)g_hash_table_lookup(identity_map_by_key_id, key_id)
375  : NULL);
376 }
377 
379 WINEXPORT GHashTable*
380 cryptframe_key_ids_for(const char* identity)
381 {
382  INITMAPS;
383  return (identity? (GHashTable *)g_hash_table_lookup(key_id_map_by_identity, identity)
384  : NULL);
385 }
386 
388 WINEXPORT GList*
390 {
391  INITMAPS;
392  return g_hash_table_get_keys(key_id_map_by_identity);
393 }
394 
396 WINEXPORT GList*
398 {
399  INITMAPS;
400  return g_hash_table_get_keys(public_key_map);
401 }
402 
403 WINEXPORT void
404 cryptframe_purge_key_id(const char * key_id)
405 {
406  const char* whoarewe = cryptframe_whois_key_id(key_id);
407  if (NULL != whoarewe) {
408  cryptframe_dissociate_identity(whoarewe, key_id);
409  }
410  g_hash_table_remove(public_key_map, key_id);
411  g_hash_table_remove(private_key_map, key_id);
412 }
413 
415 WINEXPORT void
416 cryptframe_set_signing_key_id(const char * key_id)
417 {
419  if (secret_key) {
420  if (default_signing_key) {
421  UNREF(default_signing_key);
422  default_signing_key = NULL;
423  }
424  REF(secret_key);
425  default_signing_key = secret_key;
426  }else{
427  g_warning("%s.%d: Cannot set signing key to [%s] - no such private key"
428  , __FUNCTION__, __LINE__, key_id);
429  }
430 }
431 
433 WINEXPORT const char *
435 {
436  return (default_signing_key ? default_signing_key->key_id : NULL);
437 }
438 
442 {
443  return default_signing_key;
444 }
445 
446 static CryptFrame* (*current_encryption_method) (const char* sender_key_id,
447  const char * receiver_key_id,
448  gboolean forsending);
452 WINEXPORT void
454  CryptFramePublicKey*destkey)
455 {
456  INITMAPS;
457  g_return_if_fail(NULL != destaddr);
458  if (NULL == destkey) {
459  g_hash_table_remove(addr_to_public_key_map, destaddr);
460  }else{
461  REF(destaddr);
462  REF(destkey);
463  g_hash_table_insert(addr_to_public_key_map, destaddr, destkey);
464  }
465 }
469 WINEXPORT gboolean
471  const char * key_id)
472 {
473  CryptFramePublicKey* destkey;
474  INITMAPS;
475  g_return_val_if_fail(NULL != destaddr && NULL != key_id, FALSE);
476  destkey = g_hash_table_lookup(public_key_map, key_id);
477  if (NULL == destkey) {
478  g_critical("%s.%d: No key associated with key id %s"
479  , __FUNCTION__, __LINE__, key_id);
480  return FALSE;
481  }
483  return TRUE;
484 }
485 
489 {
490  const char * receiver_key_id;
491  INITMAPS;
492  if (NULL == current_encryption_method || NULL == default_signing_key) {
493  return NULL;
494  }
495  receiver_key_id = cryptframe_get_dest_key_id(destaddr);
496  if (NULL == receiver_key_id) {
497  return NULL;
498  }
499  return current_encryption_method(default_signing_key->key_id, receiver_key_id, TRUE);
500 }
501 
503 WINEXPORT const char *
505 {
506  gpointer g_receiver_key;
507  CryptFramePublicKey* receiver_key;
508  INITMAPS;
509  g_receiver_key = g_hash_table_lookup(addr_to_public_key_map, destaddr);
510  if (NULL == g_receiver_key) {
511  return NULL;
512  }
513  receiver_key = CASTTOCLASS(CryptFramePublicKey, g_receiver_key);
514  return receiver_key->key_id;
515 }
516 // Set the current encryption method
517 WINEXPORT void
519  (const char* sender_key_id,
520  const char * receiver_key_id,
521  gboolean forsending))
522 {
523  current_encryption_method = method;
524 }
525 
526 
WINEXPORT gboolean cryptframe_set_dest_key_id(NetAddr *destaddr, const char *key_id)
Set the encryption key to use when sending to destaddr Set destkey to NULL to stop encrypting to that...
Definition: cryptframe.c:470
void _assimobj_finalize(AssimObj *self)
Definition: assimobj.c:61
WINEXPORT GList * cryptframe_get_key_ids(void)
Return a GList of strings of all known key ids.
Definition: cryptframe.c:397
Defines miscellaneous interfaces.
WINEXPORT GList * cryptframe_get_identities(void)
Return a GList of strings of all known identities.
Definition: cryptframe.c:389
NetAddr * destaddr
Definition: nanomain.c:75
CryptFrame * cryptframe_new(guint16 frame_type, const char *sender_key_id, const char *receiver_key_id, gsize objsize)
Construct a new CryptFrame This can only be used directly for creating subclassed CryptFrame frames b...
Definition: cryptframe.c:82
AssimObj baseclass
Base object class for our Class system.
Definition: frame.h:44
FSTATIC void _cryptframe_privatekey_finalize(AssimObj *key)
Finalize (destructor) function for our CryptFramePrivateKey objects.
Definition: cryptframe.c:190
Implements minimal client-oriented Frame and Frameset capabilities.
This is the base Frame class object (in-memory TLV (type, length, value)) for every general component...
Definition: frame.h:43
WINEXPORT gboolean cryptframe_associate_identity(const char *identity, const char *key_id)
Associate the given key id with the given identity Note that it is OK to associate multiple key ids w...
Definition: cryptframe.c:293
WINEXPORT CryptFramePrivateKey * cryptframe_privatekey_new(const char *key_id, gpointer private_key)
Create a new private key - or return the existing private key with this id.
Definition: cryptframe.c:245
#define WINEXPORT
Definition: projectcommon.h:45
#define FSTATIC
Definition: projectcommon.h:31
char * key_id
unique name for this key
Definition: cryptframe.h:36
WINEXPORT CryptFrame * cryptframe_new_by_destaddr(const NetAddr *destaddr)
Construct a CryptFrame class appropriate for encrypting messages to destaddr
Definition: cryptframe.c:488
#define BINDDEBUG(Cclass)
BINDDEBUG is for telling the class system where the debug variable for this class is - put it in the ...
Definition: proj_classes.h:82
#define INITMAPS
Definition: cryptframe.c:137
WINEXPORT void cryptframe_shutdown(void)
Shut down our key caches and so on... (destroy our maps)
Definition: cryptframe.c:159
WINEXPORT const char * cryptframe_whois_key_id(const char *key_id)
Return the identity associated with the given key id.
Definition: cryptframe.c:371
FSTATIC void _cryptframe_debug_checksum(const char *function, int lineno, const char *message, const guint8 *buf)
Print a debug checksum message.
Definition: cryptframe.c:205
WINEXPORT const char * cryptframe_get_dest_key_id(const NetAddr *destaddr)
Return the key_id associated with the given destination address.
Definition: cryptframe.c:504
#define __FUNCTION__
WINEXPORT gboolean cryptframe_dissociate_identity(const char *identity, const char *key_id)
Dissociate the given key from the given identity (analogous to revoking the key)
Definition: cryptframe.c:334
#define DEBUGCKSUM3(msg, buf)
Definition: cryptframe.c:120
WINEXPORT void assim_g_notify_unref(gpointer assimobj)
Unref for glib notify.
Definition: misc.c:739
Describes interfaces to CryptFrame (encryption) C-Class It represents the abstract base class for Fra...
Frame * frame_new(guint16 frame_type, gsize framesize)
Construct a new frame - allowing for "derived" frame types...
Definition: frame.c:125
FSTATIC void _cryptframe_finalize(AssimObj *aself)
Finalize (destructor) function for our CryptFramePublicKey objects.
Definition: cryptframe.c:64
char * key_id
unique name for this key
Definition: cryptframe.h:45
gboolean(* isvalid)(const Frame *self, gconstpointer tlvptr, gconstpointer pktend)
TRUE if TLV data looks valid...
Definition: frame.h:50
FSTATIC CryptFramePublicKey * cryptframe_public_key_by_id(const char *key_id)
Return the non-const public key with the given id.
Definition: cryptframe.c:270
FSTATIC void _cryptframe_publickey_finalize(AssimObj *key)
Finalize (destructor) function for our CryptFramePublicKey objects.
Definition: cryptframe.c:174
#define REF(obj)
Definition: assimobj.h:39
FSTATIC CryptFramePrivateKey * cryptframe_private_key_by_id(const char *key_id)
Return the non-const private key with the given id.
Definition: cryptframe.c:279
WINEXPORT gboolean netaddr_g_hash_equal(gconstpointer lhs, gconstpointer rhs)
g_hash_table equal comparator for a NetAddr
Definition: netaddr.c:388
WINEXPORT CryptFramePrivateKey * cryptframe_get_signing_key(void)
Return the default signing key.
Definition: cryptframe.c:441
Project common header file.
struct _CryptFrame CryptFrame
Definition: cryptframe.h:32
Header file defining the data layouts for our Frames.
TLV helper interfaces definitions.
WINEXPORT const char * cryptframe_whois_public_key(const CryptFramePublicKey *public_key)
Return the identity associated with the given public key object.
Definition: cryptframe.c:362
GHashTable * addr_to_public_key_map
Maps NetAddr class to public key.
Definition: cryptframe.c:135
AssimObj * assimobj_new(guint objsize)
Definition: assimobj.c:74
#define FRAMETYPE_PUBKEYCURVE25519
FRAMETYPE_PUBKEYCURVE25519 Frame (frametype 30) Frame subclass - Frame class.
Definition: frametypes.h:443
WINEXPORT void cryptframe_set_encryption_method(CryptFrame *(*method)(const char *sender_key_id, const char *receiver_key_id, gboolean forsending))
Definition: cryptframe.c:518
FSTATIC gboolean _cryptframe_default_isvalid(const Frame *, gconstpointer, gconstpointer)
CryptFrame class 'isvalid' member function (checks for valid cryptframe objects)
Definition: cryptframe.c:50
void(* _finalize)(AssimObj *)
Free object (private)
Definition: assimobj.h:55
Provides definitions for using our generic TLV capabilities.
The NetAddr class class represents a general network address - whether IP, MAC, or any other type of ...
Definition: netaddr.h:43
WINEXPORT void cryptframe_set_dest_public_key(NetAddr *destaddr, CryptFramePublicKey *destkey)
Set the encryption key to use when sending to destaddr Set destkey to NULL to stop encrypting to that...
Definition: cryptframe.c:453
WINEXPORT guint netaddr_g_hash_hash(gconstpointer addrptr)
g_hash_table hash function for a NetAddr
Definition: netaddr.c:397
WINEXPORT void cryptframe_set_signing_key_id(const char *key_id)
Set the default signing key.
Definition: cryptframe.c:416
#define DEBUGDECLARATIONS
Definition: proj_classes.h:79
FSTATIC void _cryptframe_initialize_maps(void)
Initialize all our maps.
Definition: cryptframe.c:142
WINEXPORT GHashTable * cryptframe_key_ids_for(const char *identity)
Return a GHashTable of strings of all the key ids associated with the given identity.
Definition: cryptframe.c:380
This is our CryptFrame class object - representing an encryption method.
Definition: cryptframe.h:53
WINEXPORT const char * cryptframe_get_signing_key_id(void)
Return the key_id of the default signing key.
Definition: cryptframe.c:434
WINEXPORT Frame * cryptframe_tlvconstructor(gpointer tlvstart, gconstpointer pktend, gpointer *ignorednewpkt, gpointer *ignoredpktend)
Given marshalled packet data corresponding to an CryptFrame - which we can't do because we're an abst...
Definition: cryptframe.c:108
#define CASTTOCLASS(Cclass, obj)
Safely cast 'obj' to C-class 'class' - verifying that it was registerd as being of type class ...
Definition: proj_classes.h:66
#define UNREF(obj)
Definition: assimobj.h:35
#define NEWSUBCLASS(Cclass, obj)
Definition: proj_classes.h:67
WINEXPORT void cryptframe_purge_key_id(const char *key_id)
Definition: cryptframe.c:404
WINEXPORT CryptFramePublicKey * cryptframe_publickey_new(const char *key_id, gpointer public_key)
Create a persistent keypair and write it to disk.
Definition: cryptframe.c:220