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 
34 FSTATIC gboolean _signframe_isvalid(const Frame *, gconstpointer, gconstpointer);
35 FSTATIC void _signframe_updatedata(Frame* self, gpointer tlvptr, gconstpointer pktend, FrameSet* fs);
36 FSTATIC gpointer _signframe_compute_cksum(GChecksumType, gconstpointer tlvptr, gconstpointer pktend);
54 
61 FSTATIC gpointer
62 _signframe_compute_cksum(GChecksumType cksumtype,
63  gconstpointer tlvptr,
64  gconstpointer pktend)
65 {
66  guint16 framelen = get_generic_tlv_len(tlvptr, pktend);
67  const guint8* nextframe;
68  gssize cksumsize;
69  gssize remainsize;
70  gsize bufsize;
71  GChecksum* cksumobj;
72  guint8* cksumbuf = NULL;
73 
74  // Get the size of this type checksum
75  cksumsize = g_checksum_type_get_length(cksumtype);
76  g_return_val_if_fail(cksumsize > 1, NULL);
77  g_return_val_if_fail(framelen == (cksumsize + 2), NULL);
78 
79  // Find out what data is left after our frame - the data we operate on...
80  nextframe = get_generic_tlv_next(tlvptr, pktend);
81  g_return_val_if_fail(nextframe != NULL, NULL);
82 
83  // Compute size of remaining data (data after this frame)
84  remainsize = (const guint8*)pktend - nextframe;
85  g_return_val_if_fail(remainsize > 0, NULL);
86 
87  // Create a new checksum object
88  cksumobj = g_checksum_new(cksumtype);
89  g_return_val_if_fail(NULL != cksumobj, NULL);
90 
91  // Compute the checksum on the remainder of the packet
92  g_checksum_update(cksumobj, nextframe, remainsize);
93 
94  bufsize = cksumsize;
95  cksumbuf = MALLOC0(bufsize);
96  if (cksumbuf != NULL) {
97  // Accumulate the checksum itself - into binary digest form
98  g_checksum_get_digest(cksumobj, cksumbuf, &bufsize);
99 
100  if (bufsize != (gsize)cksumsize) {
101  FREE(cksumbuf);
102  cksumbuf=NULL;
103  }
104  }
105  g_checksum_free(cksumobj);
106  return cksumbuf;
107 }
108 
110 FSTATIC gboolean
111 _signframe_isvalid(const Frame * self,
112  gconstpointer tlvptr,
113  gconstpointer pktend)
114 {
115  const guint8* framedata;
116  guint16 framelen;
117  guint8 subtype;
118  GChecksumType cksumtype;
119  gssize cksumsize;
120  guint8* cksumbuf;
121  gboolean ret = TRUE;
122 
123  (void)self;
124 
125  if (tlvptr == NULL) {
126  const SignFrame* sframe = CASTTOCONSTCLASS(SignFrame, self);
127  return (g_checksum_type_get_length(sframe->signaturetype) >= 1);
128  }
129  framedata = get_generic_tlv_value(tlvptr, pktend);
130  framelen = get_generic_tlv_len(tlvptr, pktend);
131  g_return_val_if_fail(framedata != NULL, FALSE);
132  g_return_val_if_fail(framelen > 2, FALSE);
133 
134  // Verify that we are subtype 1 (byte 0)
135  subtype = tlv_get_guint8(framedata, pktend);
136  g_return_val_if_fail(subtype == 1, FALSE);
137 
138  // Get the type of the checksum (byte 1)
139  cksumtype = (GChecksumType)tlv_get_guint8(framedata+1, pktend);
140 
141  cksumsize = g_checksum_type_get_length(cksumtype);
142  if (cksumsize < 1) {
143  ret = FALSE;
144  }else{
145  cksumbuf = _signframe_compute_cksum(cksumtype, tlvptr, pktend);
146  if (cksumbuf == NULL) {
147  // Failed to compute checksum...
148  ret = FALSE;
149  }else{
150  if (memcmp(cksumbuf, framedata+2, cksumsize) != 0) {
151  // Checksum mismatch
152  ret = FALSE;
153  }
154  FREE(cksumbuf);
155  cksumbuf = NULL;
156  }
157  }
158  return ret;
159 }
160 
167 FSTATIC void
169  gpointer tlvptr,
170  gconstpointer pktend,
171  FrameSet* fs)
172 {
173  SignFrame* self = CASTTOCLASS(SignFrame, fself);
174  GChecksumType cksumtype = self->signaturetype;
175  gssize cksumsize;
176  guint8* cksumbuf;
177  guint8* framedata = get_generic_tlv_nonconst_value(tlvptr, pktend);
178 
179  (void)fs;
180  g_return_if_fail(framedata != NULL);
181 
182  // Compute the checksum
183  cksumbuf = _signframe_compute_cksum(cksumtype, tlvptr, pktend);
184  g_return_if_fail(cksumbuf != NULL);
185 
186  // Make sure our frame is sized exactly right
187  cksumsize = g_checksum_type_get_length(cksumtype);
188  g_return_if_fail(self->baseclass.length == (2 + cksumsize));
189 
190  // Put in the frame subtype (byte 0) - (0x01)
191  tlv_set_guint8(framedata, (guint8)1, pktend);
192 
193  // Put in the GChecksumType checksum type (byte 1)
194  tlv_set_guint8(framedata+1, (guint8)self->signaturetype, pktend);
195 
196  // Copy over the checksum data (bytes 2 through cksumsize+2)
197  memcpy(framedata+2, cksumbuf, cksumsize);
198 
199  // Free the computed checksum
200  FREE(cksumbuf); cksumbuf = NULL;
201  // That's it!
202 }
203 
204 
207 SignFrame*
208 signframe_new(GChecksumType sigtype,
209  gsize framesize)
210 {
211  Frame* baseframe;
212  SignFrame* ret;
213  gssize cksumsize;
214  guint16 frame_type = FRAMETYPE_SIG;
215 
216  if (framesize < sizeof(SignFrame)) {
217  framesize = sizeof(SignFrame);
218  }
219  cksumsize = g_checksum_type_get_length(sigtype);
220  if (cksumsize <= 1) {
221  return NULL;
222  }
223  baseframe = frame_new(frame_type, framesize);
224  baseframe->isvalid = _signframe_isvalid;
225  baseframe->updatedata = _signframe_updatedata;
226  baseframe->length = cksumsize + 2;
227  baseframe->value = NULL;
228  proj_class_register_subclassed (baseframe, "SignFrame");
229 
230  ret = CASTTOCLASS(SignFrame, baseframe);
231  ret->signaturetype = sigtype;
232  return ret;
233 }
234 
235 
240 Frame*
241 signframe_tlvconstructor(gconstpointer tlvstart,
242  gconstpointer pktend,
243  gpointer* ignorednewpkt,
244  gpointer* ignoredpktend)
245 {
246  guint16 framelength = get_generic_tlv_len(tlvstart, pktend);
247  const guint8* framevalue = get_generic_tlv_value(tlvstart, pktend);
248  //guint8 majortype = tlv_get_guint8(framevalue, pktend);
249  GChecksumType minortype = tlv_get_guint8(framevalue+1, pktend);
250  SignFrame * ret;
251 
252  (void)ignorednewpkt; (void)ignoredpktend;
253  g_return_val_if_fail(framelength > 2, NULL);
254 
256  ret = signframe_new(minortype, 0);
257  g_return_val_if_fail(NULL != ret, NULL);
258  ret->baseclass.length = framelength;
259  return CASTTOCLASS(Frame, ret);
260 }