The Assimilation Project
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
signframe.c
Go to the documentation of this file.
1 
26 #include <string.h>
27 #include <projectcommon.h>
28 #include <frameset.h>
29 #include <signframe.h>
30 #include <frametypes.h>
31 #include <generic_tlv_min.h>
32 #include <tlvhelper.h>
33 #undef HAVE_SODIUM_H
34 #ifdef HAVE_SODIUM_H
35 # include <sodium.h>
36 #endif
37 
55 
60 FSTATIC gboolean _signframe_isvalid(const Frame *, gconstpointer, gconstpointer);
61 FSTATIC void _signframe_updatedata(Frame* self, gpointer tlvptr, gconstpointer pktend, FrameSet* fs);
62 FSTATIC gpointer _signframe_compute_cksum(GChecksumType, gconstpointer tlvptr, gconstpointer pktend);
63 FSTATIC gpointer _signframe_compute_cksum_glib(GChecksumType, gconstpointer tlvptr, gconstpointer pktend);
64 FSTATIC gboolean _signframe_isvalid_glib(const Frame * self, gconstpointer tlvptr, gconstpointer pktend);
65 FSTATIC guint16 _signframe_cksum_size(guint8 majortype, guint8 minortype);
66 #ifdef SODIUM_H
67 FSTATIC SignFrame* signframe_sodium_new(guint8 minortype, char * cksumname, gsize framesize);
68 FSTATIC gpointer _signframe_compute_cksum_sodium(GChecksumType, gconstpointer tlvptr, gconstpointer pktend);
69 FSTATIC Frame* _signframe_sodium_tlvconstructor(gpointer tlvstart, gconstpointer pktend, gpointer* ignorednewpkt, gpointer* ignoredpktend);
70 #endif
71 
72 static guint8 default_checksum_major_type = 0;
73 static guint8 default_checksum_minor_type = 0;
74 static char* default_checksum_keyname = NULL;
75 static guint8* default_checksum_signkey = NULL;
76 static guint8 default_checksum_keylen = 0;
77 
79 FSTATIC guint16
80 _signframe_cksum_size(guint8 majortype, guint8 minortype)
81 {
82  switch(majortype) {
83  case SIGNTYPE_GLIB:
84  return g_checksum_type_get_length(minortype);
85 #ifdef HAVE_SODIUM_H
86  case SIGNTYPE_SODIUM: {
87  switch(minortype) {
88  case SIGNTYPE_SODIUM_SHA512256:
89  return crypto_auth_KEYBYTES;
90 
91  case SIGNTYPE_SODIUM_ED25519:
92  return crypto_sign_BYTES;
93  }
94  break;
95  }
96 #endif
97  }
98  g_return_val_if_reached(0);
99 }
100 
101 
103 gboolean
104 signframe_setdefault(guint8 majortype
105  , guint8 minortype
106  , const char * keyname
107  , const guint8* signkey
108  , gsize keylen)
109 {
110  if (majortype == SIGNTYPE_GLIB) {
111  g_return_val_if_fail(keyname == NULL, FALSE);
112  g_return_val_if_fail(signkey == NULL, FALSE);
113  g_return_val_if_fail(keylen == 0, FALSE);
114  g_return_val_if_fail(g_checksum_type_get_length(minortype) > 0, FALSE);
115 #ifdef HAVE_SODIUM_H
116  }else if (majortype == SIGNTYPE_SODIUM) {
117  g_return_val_if_fail(keyname != NULL, FALSE);
118  g_return_val_if_fail(signkey != NULL, FALSE);
119  if (minortype == SIGNTYPE_SODIUM_SHA512256) {
120  g_return_val_if_fail(keylen == crypto_auth_KEYBYTES, FALSE);
121  }else if (minortype == SIGNTYPE_SODIUM_ED25519) {
122  g_return_val_if_fail(keylen == crypto_sign_PUBLICKEYBYTES, FALSE);
123  }else{
124  g_return_val_if_reached(FALSE);
125  }
126 #endif
127  }
128  default_checksum_major_type = majortype;
129  default_checksum_minor_type = minortype;
130  default_checksum_keylen = keylen;
131  if (keylen > 0) {
132  default_checksum_signkey = g_malloc(keylen);
133  memcpy(default_checksum_signkey, signkey, keylen);
134  }
135  if (keyname != NULL) {
136  default_checksum_keyname = g_strdup(keyname);
137  }
138  return TRUE;
139 }
140 FSTATIC gpointer
141 _signframe_compute_cksum(GChecksumType cksumtype,
142  gconstpointer tlvptr,
143  gconstpointer pktend)
144 {
145  return _signframe_compute_cksum_glib(cksumtype, tlvptr, pktend);
146 }
147 
150 FSTATIC gpointer
151 _signframe_compute_cksum_glib(GChecksumType cksumtype,
152  gconstpointer tlvptr,
153  gconstpointer pktend)
154 {
155  guint32 framelen = get_generic_tlv_len(tlvptr, pktend);
156  const guint8* nextframe;
157  gssize cksumsize;
158  gssize remainsize;
159  gsize bufsize;
160  GChecksum* cksumobj;
161  guint8* cksumbuf = NULL;
162 
163  // Get the size of this type checksum
164  cksumsize = g_checksum_type_get_length(cksumtype);
165  g_return_val_if_fail(cksumsize > 1, NULL);
166  g_return_val_if_fail((gssize)framelen == (cksumsize + 2), NULL);
167 
168  // Find out what data is left after our frame - the data we operate on...
169  nextframe = get_generic_tlv_next(tlvptr, pktend);
170  g_return_val_if_fail(nextframe != NULL, NULL);
171 
172  // Compute size of remaining data (data after this frame)
173  remainsize = (const guint8*)pktend - nextframe;
174  g_return_val_if_fail(remainsize > 0, NULL);
175 
176  // Create a new checksum object
177  cksumobj = g_checksum_new(cksumtype);
178  g_return_val_if_fail(NULL != cksumobj, NULL);
179 
180  // Compute the checksum on the remainder of the packet
181  g_checksum_update(cksumobj, nextframe, remainsize);
182 
183  bufsize = cksumsize;
184  cksumbuf = MALLOC0(bufsize);
185  if (cksumbuf != NULL) {
186  // Accumulate the checksum itself - into binary digest form
187  g_checksum_get_digest(cksumobj, cksumbuf, &bufsize);
188 
189  if (bufsize != (gsize)cksumsize) {
190  FREE(cksumbuf);
191  cksumbuf=NULL;
192  }
193  }
194  g_checksum_free(cksumobj);
195  return cksumbuf;
196 }
198 FSTATIC gboolean
199 _signframe_isvalid(const Frame * self,
200  gconstpointer tlvptr,
201  gconstpointer pktend)
202 {
203  const guint8* framedata;
204  guint32 framelen;
205  guint8 majortype;
206  if (tlvptr == NULL) {
207  const SignFrame* sframe = CASTTOCONSTCLASS(SignFrame, self);
208  if (sframe->majortype == SIGNTYPE_GLIB) {
209  return _signframe_isvalid_glib(self, tlvptr, pktend);
210 #ifdef HAVE_SODIUM_H
211  }else if (sframe->majortype == SIGNTYPE_SODIUM) {
212  return _signframe_isvalid_sodium(self, tlvptr, pktend);
213 #endif
214  }
215  return FALSE;
216  }
217  framedata = get_generic_tlv_value(tlvptr, pktend);
218  framelen = get_generic_tlv_len(tlvptr, pktend);
219  g_return_val_if_fail(framedata != NULL, FALSE);
220  g_return_val_if_fail(framelen > 2, FALSE);
221 
222  // Verify that we are majortype 1 (byte 0)
223  majortype = tlv_get_guint8(framedata, pktend);
224  if (majortype == SIGNTYPE_GLIB) {
225  return _signframe_isvalid_glib(self, tlvptr, pktend);
226 #ifdef SODIUM_H
227  }else if (majortype == SIGNTYPE_SODIUM) {
228  return _signframe_isvalid_sodium(self, tlvptr, pktend);
229 #endif
230  }
231  return FALSE;
232 }
233 
235 FSTATIC gboolean
237  gconstpointer tlvptr,
238  gconstpointer pktend)
239 {
240  const guint8* framedata;
241  guint32 framelen;
242  guint8 majortype;
243  GChecksumType cksumtype;
244  gssize cksumsize;
245  guint8* cksumbuf;
246  gboolean ret = TRUE;
247 
248 
249  if (tlvptr == NULL) {
250  const SignFrame* sframe = CASTTOCONSTCLASS(SignFrame, self);
251  g_return_val_if_fail(sframe->majortype == SIGNTYPE_GLIB, FALSE);
252  return (g_checksum_type_get_length(sframe->minortype) >= 1);
253  }
254  framedata = get_generic_tlv_value(tlvptr, pktend);
255  framelen = get_generic_tlv_len(tlvptr, pktend);
256  g_return_val_if_fail(framedata != NULL, FALSE);
257  g_return_val_if_fail(framelen > 2, FALSE);
258 
259  // Verify that we are majortype 1 (byte 0)
260  majortype = tlv_get_guint8(framedata, pktend);
261  g_return_val_if_fail(majortype == SIGNTYPE_GLIB, FALSE);
262 
263  // Get the type of the checksum (byte 1)
264  cksumtype = (GChecksumType)tlv_get_guint8(framedata+1, pktend);
265 
266  cksumsize = g_checksum_type_get_length(cksumtype);
267  if (cksumsize < 1) {
268  ret = FALSE;
269  }else{
270  cksumbuf = _signframe_compute_cksum_glib(cksumtype, tlvptr, pktend);
271  if (cksumbuf == NULL) {
272  // Failed to compute checksum...
273  ret = FALSE;
274  }else{
275  if (memcmp(cksumbuf, framedata+2, cksumsize) != 0) {
276  // Checksum mismatch
277  ret = FALSE;
278  }
279  FREE(cksumbuf);
280  cksumbuf = NULL;
281  }
282  }
283  return ret;
284 }
285 
292 FSTATIC void
294  gpointer tlvptr,
295  gconstpointer pktend,
296  FrameSet* fs)
297 {
298  SignFrame* self = CASTTOCLASS(SignFrame, fself);
299  GChecksumType cksumtype = self->minortype;
300  gssize cksumsize;
301  guint8* cksumbuf;
302  guint8* framedata = get_generic_tlv_nonconst_value(tlvptr, pktend);
303 
304  (void)fs;
305  g_return_if_fail(self->majortype == SIGNTYPE_GLIB);
306  g_return_if_fail(framedata != NULL);
307 
308  // Compute the checksum
309  cksumbuf = _signframe_compute_cksum(cksumtype, tlvptr, pktend);
310  g_return_if_fail(cksumbuf != NULL);
311 
312  // Make sure our frame is sized exactly right
313  cksumsize = g_checksum_type_get_length(cksumtype);
314  g_return_if_fail((gssize)(self->baseclass.length) == (2 + cksumsize));
315 
316  // Put in the major checksum type (byte 0)
317  tlv_set_guint8(framedata, self->majortype, pktend);
318 
319  // Put in the minor checksum type (byte 1)
320  tlv_set_guint8(framedata+1, self->minortype, pktend);
321 
322  // Copy over the checksum data (bytes 2 through cksumsize+2)
323  memcpy(framedata+2, cksumbuf, cksumsize);
324 
325  // Free the computed checksum
326  FREE(cksumbuf); cksumbuf = NULL;
327  // That's it!
328 }
329 
330 
334 signframe_glib_new(GChecksumType sigtype,
335  gsize framesize)
336 {
337  Frame* baseframe;
338  SignFrame* ret;
339  gssize cksumsize;
340  guint16 frame_type = FRAMETYPE_SIG;
341 
342  if (framesize < sizeof(SignFrame)) {
343  framesize = sizeof(SignFrame);
344  }
345  cksumsize = g_checksum_type_get_length(sigtype);
346  if (cksumsize <= 1) {
347  return NULL;
348  }
349  baseframe = frame_new(frame_type, framesize);
350  baseframe->isvalid = _signframe_isvalid;
351  baseframe->updatedata = _signframe_updatedata;
352  baseframe->length = cksumsize + 2;
353  baseframe->value = NULL;
354  proj_class_register_subclassed (baseframe, "SignFrame");
355 
356  ret = CASTTOCLASS(SignFrame, baseframe);
357  ret->majortype = SIGNTYPE_GLIB;
358  ret->minortype = sigtype;
359  return ret;
360 }
361 
362 
367 Frame*
368 signframe_tlvconstructor(gpointer tlvstart,
369  gconstpointer pktend,
370  gpointer* newpkt,
371  gpointer* newpktend)
372 {
373  guint32 framelength = get_generic_tlv_len(tlvstart, pktend);
374  const guint8* framevalue = get_generic_tlv_value(tlvstart, pktend);
375  guint8 majortype;
376  GChecksumType minortype;
377 
378  (void)newpkt; (void)newpktend;
379  g_return_val_if_fail(framelength > 2, NULL);
380  majortype = tlv_get_guint8(framevalue, pktend);
381  minortype = tlv_get_guint8(framevalue+1, pktend);
382 
384  if (majortype == SIGNTYPE_GLIB) {
385  SignFrame * ret = NULL;
386  ret = signframe_glib_new(minortype, 0);
387  g_return_val_if_fail(NULL != ret, NULL);
388  ret->baseclass.length = framelength;
389  //ret->baseclass.value = framevalue; // @TODO Should .value be set???
390  return CASTTOCLASS(Frame, ret);
391 #ifdef HAVE_SODIUM_H
392  }else if (majortype == SIGNTYPE_SODIUM) {
393  return signframe_sodium_tlvconstructor(tlvstart, pktend, newpkt, newpktend);
394 #endif
395  }else{
396  return NULL;
397  }
398 }
399 #ifdef HAVE_SODIUM_H
400 static GHashTable* pki_keys = NULL;
401 static GHashTable* sharedkeys = NULL;
402 
404 _signframe_sodium_new(guint8 minortype, char * signname, gsize framesize)
405 {
406 }
407 FSTATIC gpointer
408 _signframe_compute_cksum_sodium(GChecksumType, gconstpointer tlvptr, gconstpointer pktend)
409 {
410 }
411 
412 // Minimum packet: major, minor, checksum, {cksumname}, NULL byte
413 #define MINSODLEN(cksumsize) (2+(cksumsize)+1)
414 FSTATIC Frame*
415 signframe_sodium_tlvconstructor(gpointer tlvstart,
416  gconstpointer pktend,
417  gpointer* ignorednewpkt,
418  gpointer* ignoredpktend)
419 {
420  guint32 framelength = get_generic_tlv_len(tlvstart, pktend);
421  const guint8* framevalue = get_generic_tlv_value(tlvstart, pktend);
422  guint8 majortype = tlv_get_guint8(framevalue, pktend);
423  GChecksumType minortype = tlv_get_guint8(framevalue+1, pktend);
424  SignFrame * ret;
425  gint16 cksumlen;
426  gint16 namelen;
427  guint8* key;
428  char * cksumname;
429  g_return_val_if_fail (majortype == SIGNTYPE_GLIB, NULL);
430  cksumlen = _signframe_cksum_size(majortype, minortype);
431  g_return_val_if_fail (cksumlen < 1);
432  g_return_val_if_fail (framelength < MINSODLEN(cksumlen));
433  // Make sure it's NUL-terminated
434  g_return_val_if_fail(tlv_get_guint8(framevalue+framelength-1) == 0, NULL);
435  namelen = framelength - MINSODLEN(cksumlen);
436  g_return_val_if_fail(namelen < 1);
437  // Make sure it only exactly *one* NUL byte
438  cksumname = (char *) (framevalue+MINSODLEN(cksumlen))
439  g_return_val_if_fail(strnlen(cksumname, namelen) == namelen, NULL);
440  g_return_val_if_fail(SIGNTYPE_SODIUM_SHA512256 == minortype
441  || SIGNTYPE_SODIUM_ED25519 == minortype);
442  ret = _signframe_sodium_new(minortype, cksumname, 0);
443  g_return_val_if_fail(NULL != ret, NULL);
444  ret->baseclass.length = framelength;
445  //ret->baseclass.value = framevalue; // @TODO Should .value be set???
446  return CASTTOCLASS(Frame, ret);
447 }
448 #endif
449 
Frame * signframe_tlvconstructor(gpointer tlvstart, gconstpointer pktend, gpointer *newpkt, gpointer *newpktend)
Given marshalled data corresponding to a SignFrame (signature frame), return that corresponding Frame...
Definition: signframe.c:368
#define MALLOC0(nbytes)
should it just call g_malloc?
Definition: projectcommon.h:25
guint32 length
Frame Length.
Definition: frame.h:46
FSTATIC gboolean _signframe_isvalid(const Frame *, gconstpointer, gconstpointer)
SignFrame class 'isvalid' member function - verifies a Glib digital signature
Definition: signframe.c:199
#define SIGNTYPE_GLIB
Definition: signframe.h:33
guint8 majortype
Which signature module.
Definition: signframe.h:49
guint8 tlv_get_guint8(const void *vitem, const void *bufend)
Retrieve an unsigned 8 bit integer from the given location with error checking.
Definition: tlvhelper.c:30
Describes interfaces to Signature Frame (Signframe) C-Class - providing digital signatures.
WINEXPORT SignFrame * signframe_glib_new(GChecksumType sigtype, gsize framesize)
Construct a new SignFrame - allowing for "derived" frame types...
Definition: signframe.c:334
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
The SignFrame class object - implements digital signatures for FrameSets.
Definition: signframe.h:47
#define WINEXPORT
Definition: projectcommon.h:45
#define FSTATIC
Definition: projectcommon.h:31
gpointer value
Frame Value (pointer)
Definition: frame.h:47
gboolean signframe_setdefault(guint8 majortype, guint8 minortype, const char *keyname, const guint8 *signkey, gsize keylen)
Definition: signframe.c:104
guint8 minortype
signature subtype
Definition: signframe.h:50
Frame * frame_new(guint16 frame_type, gsize framesize)
Construct a new frame - allowing for "derived" frame types...
Definition: frame.c:124
gpointer proj_class_register_subclassed(gpointer object, const char *static_subclassname)
Log the creation of a subclassed object from a superclassed object.
Definition: proj_classes.c:192
gboolean(* isvalid)(const Frame *self, gconstpointer tlvptr, gconstpointer pktend)
TRUE if TLV data looks valid...
Definition: frame.h:50
#define FREE(m)
Our interface to free.
Definition: projectcommon.h:29
#define CASTTOCONSTCLASS(Cclass, obj)
Safely cast 'obj' to const C-class 'class' - verifying that it was registered as being of type class ...
Definition: proj_classes.h:71
guint32 get_generic_tlv_len(gconstpointer tlv_vp, gconstpointer pktend)
Return the 'Length' of the given generic TLV entry (first 3 bytes after type)
Project common header file.
Header file defining the data layouts for our Frames.
TLV helper interfaces definitions.
void tlv_set_guint8(void *vitem, guint8 item, const void *bufend)
Set an unsigned 8 bit integer to the given location with error checking.
Definition: tlvhelper.c:41
FSTATIC gpointer _signframe_compute_cksum_glib(GChecksumType, gconstpointer tlvptr, gconstpointer pktend)
Internal helper routine for computing checksum on data in a frame.
Definition: signframe.c:151
Provides definitions for using our generic TLV capabilities.
gconstpointer get_generic_tlv_value(gconstpointer tlv_vp, gconstpointer pktend)
Return a const pointer to the 'Value' of the given generic TLV entry.
FSTATIC gpointer _signframe_compute_cksum(GChecksumType, gconstpointer tlvptr, gconstpointer pktend)
Definition: signframe.c:141
FSTATIC void _signframe_updatedata(Frame *self, gpointer tlvptr, gconstpointer pktend, FrameSet *fs)
Write/update digital signature in packet.
Definition: signframe.c:293
void(* updatedata)(Frame *self, gpointer tlvptr, gconstpointer pktend, FrameSet *fs)
Update packet data.
Definition: frame.h:49
FrameSet class - used for collecting Frames when not on the wire, and for marshalling/demarshalling t...
Definition: frameset.h:46
#define FRAMETYPE_SIG
FRAMETYPE_SIG Frame (frametype 1) Frame subclass - SignFrame class.
Definition: frametypes.h:82
FSTATIC guint16 _signframe_cksum_size(guint8 majortype, guint8 minortype)
Set default outbound signing key.
Definition: signframe.c:80
gpointer get_generic_tlv_nonconst_value(gpointer tlv_vp, gconstpointer pktend)
Return a non-const (mutable) pointer to the 'Value' of the given generic TLV entry.
gconstpointer get_generic_tlv_next(gconstpointer tlv_vp, gconstpointer pktend)
Return pointer to the next generic TLV entry after the current location.
FSTATIC gboolean _signframe_isvalid_glib(const Frame *self, gconstpointer tlvptr, gconstpointer pktend)
SignFrame class 'isvalid' member function - verifies a Glib digital signature
Definition: signframe.c:236
Frame baseclass
Base Frame class object.
Definition: signframe.h:48
#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
struct _SignFrame SignFrame
Definition: signframe.h:40