The Assimilation Project
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups 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 
35 FSTATIC gboolean _cryptframe_default_isvalid(const Frame *, gconstpointer, gconstpointer);
39 static void (*_parentclass_finalize)(AssimObj*) = NULL;
40 
45 
47 FSTATIC gboolean
49  gconstpointer tlvptr,
50  gconstpointer pktend)
51 {
52  (void)self;
53  (void)tlvptr;
54  (void)pktend;
55 
57  g_return_val_if_reached(FALSE);
58 }
59 
61 FSTATIC void
63 {
64  CryptFrame* self = CASTTOCLASS(CryptFrame, aself);
65  if (self->sender_key_id) {
66  g_free(self->sender_key_id);
67  self->sender_key_id = NULL;
68  }
69  if (self->receiver_key_id) {
70  g_free(self->receiver_key_id);
71  self->receiver_key_id = NULL;
72  }
73  _parentclass_finalize(aself);
74 }
75 
80 cryptframe_new( guint16 frame_type,
81  const char * sender_key_id,
82  const char * receiver_key_id,
83  gsize objsize)
84 {
85  Frame* baseframe;
86  CryptFrame* self;
87 
88  if (objsize < sizeof(CryptFrame)) {
89  objsize = sizeof(CryptFrame);
90  }
91  baseframe = frame_new(frame_type, objsize);
92  if (!_parentclass_finalize) {
93  _parentclass_finalize = baseframe->baseclass._finalize;
94  }
96  self = NEWSUBCLASS(CryptFrame, baseframe);
97  self->sender_key_id = g_strdup(sender_key_id);
98  self->receiver_key_id = g_strdup(receiver_key_id);
99  return self;
100 }
104 cryptframe_tlvconstructor(gpointer tlvstart,
105  gconstpointer pktend,
106  gpointer* ignorednewpkt,
107  gpointer* ignoredpktend)
108 {
109  (void)tlvstart;
110  (void)pktend;
111  (void)ignorednewpkt;
112  (void)ignoredpktend;
113  // Abstract base class - can't do this...
114  g_return_val_if_reached(NULL);
115 }
119 // All our hash tables have strings for keys
120 static GHashTable* public_key_map = NULL;
121 static GHashTable* private_key_map = NULL;
122 static GHashTable* identity_map_by_key_id = NULL;
123 static GHashTable* key_id_map_by_identity = NULL;
124 GHashTable* addr_to_public_key_map = NULL;
129 static CryptFramePrivateKey* default_signing_key = NULL;
130 #define INITMAPS {if (!maps_inityet) {_cryptframe_initialize_maps();}}
131 static gboolean maps_inityet = FALSE;
132 
134 FSTATIC void
136 {
137  if (maps_inityet) {
138  return;
139  }
140  key_id_map_by_identity = g_hash_table_new_full(g_str_hash, g_str_equal
141  , NULL, (GDestroyNotify)g_hash_table_destroy);
142  identity_map_by_key_id = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
143  public_key_map = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, assim_g_notify_unref);
144  private_key_map = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, assim_g_notify_unref);
145  addr_to_public_key_map = g_hash_table_new_full(netaddr_g_hash_hash
147  maps_inityet = TRUE;
148 }
149 
151 WINEXPORT void
153 {
154  g_hash_table_destroy(key_id_map_by_identity); key_id_map_by_identity=NULL;
155  g_hash_table_destroy(identity_map_by_key_id); identity_map_by_key_id=NULL;
156  g_hash_table_destroy(public_key_map); public_key_map=NULL;
157  g_hash_table_destroy(private_key_map); private_key_map=NULL;
158  g_hash_table_destroy(addr_to_public_key_map); addr_to_public_key_map=NULL;
159  if (default_signing_key) {
160  UNREF(default_signing_key);
161  }
162  maps_inityet = FALSE;
163 }
164 
166 FSTATIC void
168 {
170  if (self->key_id) {
171  g_free(self->key_id);
172  self->key_id = NULL;
173  }
174  if (self->public_key) {
175  g_free(self->public_key);
176  self->public_key = NULL;
177  }
178  _assimobj_finalize(pubkey);
179 }
180 
182 FSTATIC void
184 {
186  if (self->key_id) {
187  g_free(self->key_id);
188  self->key_id = NULL;
189  }
190  if (self->private_key) {
191  g_free(self->private_key);
192  self->private_key = NULL;
193  }
194  _assimobj_finalize(privkey);
195 }
196 
197 
200 cryptframe_publickey_new (const char *key_id,
201  gpointer public_key)
202 {
203  AssimObj* aself;
204  CryptFramePublicKey* self;
205  INITMAPS;
206  self = cryptframe_public_key_by_id(key_id);
207  if (self) {
208  return self;
209  }
210  aself = assimobj_new(sizeof(CryptFramePublicKey));
212  self = NEWSUBCLASS(CryptFramePublicKey, aself);
213  self->key_id = g_strdup(key_id);
214  self->key_size = crypto_box_PUBLICKEYBYTES;
215  self->frame_type = FRAMETYPE_PUBKEYCURVE25519;
216  self->public_key = public_key;
217  g_hash_table_insert(public_key_map, self->key_id, self);
218  return self;
219 }
220 
223 cryptframe_privatekey_new(const char *key_id,
224  gpointer private_key)
225 {
226  AssimObj* aself;
227  CryptFramePrivateKey* self;
228  INITMAPS;
229  self = cryptframe_private_key_by_id(key_id);
230  if (self) {
231  g_warning("%s.%d: Private key %s Already IN private key map", __FUNCTION__, __LINE__, key_id);
232  return self;
233  }
234  aself = assimobj_new(sizeof(CryptFramePrivateKey));
236  self = NEWSUBCLASS(CryptFramePrivateKey, aself);
237  self->key_id = g_strdup(key_id);
238  self->key_size = crypto_box_SECRETKEYBYTES;
239  self->private_key = private_key;
240  g_hash_table_insert(private_key_map, self->key_id, self);
241  return self;
242 }
243 
246 cryptframe_public_key_by_id(const char* key_id)
247 {
248  gpointer ret;
249  INITMAPS;
250  ret = g_hash_table_lookup(public_key_map, key_id);
251  return (ret ? CASTTOCLASS(CryptFramePublicKey, ret): NULL);
252 }
255 cryptframe_private_key_by_id(const char* key_id)
256 {
257  gpointer ret;
258  INITMAPS;
259  ret = g_hash_table_lookup(private_key_map, key_id);
260  return (ret ? CASTTOCLASS(CryptFramePrivateKey, ret): NULL);
261 }
262 
268 WINEXPORT gboolean
269 cryptframe_associate_identity(const char * identity,
270  const char * key_id)
271 {
272  GHashTable* key_id_map;
273  const char* found_identity;
274  char* key_id_duplicate;
275  char* identity_duplicate;
276  INITMAPS;
277  g_return_val_if_fail(cryptframe_public_key_by_id(key_id)!= NULL, FALSE);
278  found_identity = cryptframe_whois_key_id(key_id);
279  if (found_identity) {
280  if (strcmp(found_identity, key_id) != 0) {
281  g_critical("%s.%d: Key id %s cannot be associated with identity %s."
282  " Already associated with identity %s", __FUNCTION__, __LINE__
283  , key_id, identity, found_identity);
284  return FALSE;
285  }
286  return TRUE;
287  }
288  key_id_duplicate = g_strdup(key_id);
289  identity_duplicate = g_strdup(identity);
290  g_hash_table_insert(identity_map_by_key_id, key_id_duplicate, identity_duplicate);
291 
292  key_id_map = cryptframe_key_ids_for(identity);
293  if (NULL == key_id_map) {
294  key_id_map = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
295  g_hash_table_insert(key_id_map_by_identity, identity_duplicate, key_id_map);
296  }
297  if (!g_hash_table_lookup((GHashTable*)key_id_map, key_id)) {
298  g_hash_table_insert(key_id_map, key_id_duplicate, key_id_duplicate);
299  }
300  return TRUE;
301 }
302 
304 WINEXPORT gboolean
305 cryptframe_dissociate_identity(const char * identity,
306  const char * key_id)
307 {
308  char* found_identity;
309  GHashTable* key_id_map;
310  INITMAPS;
311 
312  found_identity = g_hash_table_lookup(identity_map_by_key_id, key_id);
313  if (NULL == found_identity) {
314  return FALSE;
315  }
316  // The order of these deletions matters - because of shared data between tables.
317  key_id_map = cryptframe_key_ids_for(identity);
318  if (key_id_map) {
319  g_hash_table_remove(key_id_map, key_id);
320  if (g_hash_table_size(key_id_map) == 0) {
321  // This identity doesn't meaningfully exist any more...
322  g_hash_table_remove(key_id_map_by_identity, identity);
323  }
324  }
325  g_hash_table_remove(identity_map_by_key_id, key_id);
326  return TRUE;
327 }
328 
330 WINEXPORT const char*
332 {
334  INITMAPS;
335  return cryptframe_whois_key_id(public_key->key_id);
336 }
337 
339 WINEXPORT const char*
340 cryptframe_whois_key_id(const char * key_id)
341 {
342  INITMAPS;
343  return (const char *)g_hash_table_lookup(identity_map_by_key_id, key_id);
344 }
345 
347 WINEXPORT GHashTable*
348 cryptframe_key_ids_for(const char* identity)
349 {
350  INITMAPS;
351  return (GHashTable *)g_hash_table_lookup(key_id_map_by_identity, identity);
352 }
353 
355 WINEXPORT GList*
357 {
358  INITMAPS;
359  return g_hash_table_get_keys(key_id_map_by_identity);
360 }
361 
363 WINEXPORT GList*
365 {
366  INITMAPS;
367  return g_hash_table_get_keys(public_key_map);
368 }
369 
370 WINEXPORT void
371 cryptframe_purge_key_id(const char * key_id)
372 {
373  const char* whoarewe = cryptframe_whois_key_id(key_id);
374  if (NULL != whoarewe) {
375  cryptframe_dissociate_identity(whoarewe, key_id);
376  }
377  g_hash_table_remove(public_key_map, key_id);
378  g_hash_table_remove(private_key_map, key_id);
379 }
380 
382 WINEXPORT void
383 cryptframe_set_signing_key_id(const char * key_id)
384 {
386  if (secret_key) {
387  if (default_signing_key) {
388  UNREF(default_signing_key);
389  default_signing_key = NULL;
390  }
391  REF(secret_key);
392  default_signing_key = secret_key;
393  }else{
394  g_warning("%s.%d: Cannot set signing key to [%s] - no such private key"
395  , __FUNCTION__, __LINE__, key_id);
396  }
397 }
398 
400 WINEXPORT const char *
402 {
403  return (default_signing_key ? default_signing_key->key_id : NULL);
404 }
405 
409 {
410  return default_signing_key;
411 }
412 
413 static CryptFrame* (*current_encryption_method) (const char* sender_key_id,
414  const char * receiver_key_id);
418 WINEXPORT void
420  CryptFramePublicKey*destkey)
421 {
422  INITMAPS;
423  g_return_if_fail(NULL != destaddr);
424  if (NULL == destkey) {
425  g_hash_table_remove(addr_to_public_key_map, destaddr);
426  }else{
427  REF(destaddr);
428  REF(destkey);
429  g_hash_table_insert(addr_to_public_key_map, destaddr, destkey);
430  }
431 }
435 WINEXPORT void
437  const char * key_id)
438 {
439  CryptFramePublicKey* destkey;
440  INITMAPS;
441  g_return_if_fail(NULL != destaddr && NULL != key_id);
442  destkey = g_hash_table_lookup(public_key_map, key_id);
443  g_return_if_fail(NULL != destkey);
444  cryptframe_set_dest_public_key(destaddr, destkey);
445 }
446 
450 {
451  CryptFramePublicKey* receiver_key;
452  if (NULL == current_encryption_method || NULL == default_signing_key) {
453  return NULL;
454  }
455  receiver_key = g_hash_table_lookup(addr_to_public_key_map, destaddr);
456  if (NULL == receiver_key) {
457  return NULL;
458  }
459  return current_encryption_method(default_signing_key->key_id, receiver_key->key_id);
460 }
461 // Set the current encryption method
462 WINEXPORT void
464  (const char* sender_key_id,
465  const char * receiver_key_id))
466 {
467  current_encryption_method = method;
468 }
469 
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:364
Defines miscellaneous interfaces.
WINEXPORT GList * cryptframe_get_identities(void)
Return a GList of strings of all known identities.
Definition: cryptframe.c:356
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:80
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:183
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:269
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:223
#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:449
#define INITMAPS
Definition: cryptframe.c:130
WINEXPORT void cryptframe_shutdown(void)
Shut down our key caches and so on... (destroy our maps)
Definition: cryptframe.c:152
WINEXPORT const char * cryptframe_whois_key_id(const char *key_id)
Return the identity associated with the given key id.
Definition: cryptframe.c:340
#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:305
WINEXPORT void assim_g_notify_unref(gpointer assimobj)
Unref for glib notify.
Definition: misc.c:720
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:124
FSTATIC void _cryptframe_finalize(AssimObj *aself)
Finalize (destructor) function for our CryptFramePublicKey objects.
Definition: cryptframe.c:62
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:246
FSTATIC void _cryptframe_publickey_finalize(AssimObj *key)
Finalize (destructor) function for our CryptFramePublicKey objects.
Definition: cryptframe.c:167
#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:255
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:408
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:331
WINEXPORT void cryptframe_set_dest_public_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:436
GHashTable * addr_to_public_key_map
Maps NetAddr class to public key.
Definition: cryptframe.c:128
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
FSTATIC gboolean _cryptframe_default_isvalid(const Frame *, gconstpointer, gconstpointer)
CryptFrame class 'isvalid' member function (checks for valid cryptframe objects)
Definition: cryptframe.c:48
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_encryption_method(CryptFrame *(*method)(const char *sender_key_id, const char *receiver_key_id))
Definition: cryptframe.c:463
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:419
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:383
FSTATIC void _cryptframe_initialize_maps(void)
Initialize all our maps.
Definition: cryptframe.c:135
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:348
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:401
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:104
#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:371
WINEXPORT CryptFramePublicKey * cryptframe_publickey_new(const char *key_id, gpointer public_key)
Create a new public key - or return the existing public key with this id.
Definition: cryptframe.c:200