@@ -37,7 +37,8 @@ const u8_t level_2_tag_size[4] = {
3737};
3838#endif
3939
40- struct ieee802154_fcf_seq * ieee802154_validate_fc_seq (u8_t * buf , u8_t * * p_buf )
40+ struct ieee802154_fcf_seq * ieee802154_validate_fc_seq (u8_t * buf , u8_t * * p_buf ,
41+ u8_t * length )
4142{
4243 struct ieee802154_fcf_seq * fs = (struct ieee802154_fcf_seq * )buf ;
4344
@@ -81,17 +82,20 @@ struct ieee802154_fcf_seq *ieee802154_validate_fc_seq(u8_t *buf, u8_t **p_buf)
8182#endif
8283
8384 if (p_buf ) {
84- * p_buf = buf + 3 ;
85+ * length -= IEEE802154_FCF_SEQ_LENGTH ;
86+ * p_buf = buf + IEEE802154_FCF_SEQ_LENGTH ;
8587 }
8688
8789 return fs ;
8890}
8991
9092static inline struct ieee802154_address_field *
91- validate_addr (u8_t * buf , u8_t * * p_buf ,
93+ validate_addr (u8_t * buf , u8_t * * p_buf , u8_t * length ,
9294 enum ieee802154_addressing_mode mode ,
9395 bool pan_id_compression )
9496{
97+ u8_t len = 0 ;
98+
9599 * p_buf = buf ;
96100
97101 NET_DBG ("Buf %p - mode %d - pan id comp %d" ,
@@ -102,59 +106,76 @@ validate_addr(u8_t *buf, u8_t **p_buf,
102106 }
103107
104108 if (!pan_id_compression ) {
105- * p_buf + = IEEE802154_PAN_ID_LENGTH ;
109+ len = IEEE802154_PAN_ID_LENGTH ;
106110 }
107111
108112 if (mode == IEEE802154_ADDR_MODE_SHORT ) {
109- * p_buf += IEEE802154_SHORT_ADDR_LENGTH ;
113+ len += IEEE802154_SHORT_ADDR_LENGTH ;
110114 } else {
111115 /* IEEE802154_ADDR_MODE_EXTENDED */
112- * p_buf += IEEE802154_EXT_ADDR_LENGTH ;
116+ len += IEEE802154_EXT_ADDR_LENGTH ;
113117 }
114118
119+ if (len > * length ) {
120+ return NULL ;
121+ }
122+
123+ * p_buf += len ;
124+ * length -= len ;
125+
115126 return (struct ieee802154_address_field * )buf ;
116127}
117128
118129#ifdef CONFIG_NET_L2_IEEE802154_SECURITY
119130struct ieee802154_aux_security_hdr *
120- ieee802154_validate_aux_security_hdr (u8_t * buf , u8_t * * p_buf )
131+ ieee802154_validate_aux_security_hdr (u8_t * buf , u8_t * * p_buf , u8_t * length )
121132{
122133 struct ieee802154_aux_security_hdr * ash =
123134 (struct ieee802154_aux_security_hdr * )buf ;
135+ u8_t len = IEEE802154_SECURITY_CF_LENGTH +
136+ IEEE802154_SECURITY_FRAME_COUNTER_LENGTH ;
124137
125- * p_buf = buf ;
138+ /* At least the asf is sized of: control field + frame counter */
139+ if (* length < len ) {
140+ return NULL ;
141+ }
126142
127143 /* Only implicit key mode is supported for now */
128144 if (ash -> control .key_id_mode != IEEE802154_KEY_ID_MODE_IMPLICIT ) {
129145 return NULL ;
130146 }
131147
132- /* At least the asf is sized of: control field + frame counter */
133- * p_buf += sizeof (struct ieee802154_security_control_field ) +
134- sizeof (u32_t );
135-
136148 /* Explicit key must have a key index != 0x00, see Section 7.4.3.2 */
137149 switch (ash -> control .key_id_mode ) {
138150 case IEEE802154_KEY_ID_MODE_IMPLICIT :
139151 break ;
140152 case IEEE802154_KEY_ID_MODE_INDEX :
141- * p_buf += IEEE8021254_KEY_ID_FIELD_INDEX_LENGTH ;
153+ len += IEEE8021254_KEY_ID_FIELD_INDEX_LENGTH ;
154+ if (* length < len ) {
155+ return NULL ;
156+ }
142157
143158 if (!ash -> kif .mode_1 .key_index ) {
144159 return NULL ;
145160 }
146161
147162 break ;
148163 case IEEE802154_KEY_ID_MODE_SRC_4_INDEX :
149- * p_buf += IEEE8021254_KEY_ID_FIELD_SRC_4_INDEX_LENGTH ;
164+ len += IEEE8021254_KEY_ID_FIELD_SRC_4_INDEX_LENGTH ;
165+ if (* length < len ) {
166+ return NULL ;
167+ }
150168
151169 if (!ash -> kif .mode_2 .key_index ) {
152170 return NULL ;
153171 }
154172
155173 break ;
156174 case IEEE802154_KEY_ID_MODE_SRC_8_INDEX :
157- * p_buf += IEEE8021254_KEY_ID_FIELD_SRC_8_INDEX_LENGTH ;
175+ len += IEEE8021254_KEY_ID_FIELD_SRC_8_INDEX_LENGTH ;
176+ if (* length < len ) {
177+ return NULL ;
178+ }
158179
159180 if (!ash -> kif .mode_3 .key_index ) {
160181 return NULL ;
@@ -163,44 +184,52 @@ ieee802154_validate_aux_security_hdr(u8_t *buf, u8_t **p_buf)
163184 break ;
164185 }
165186
187+ * p_buf = buf + len ;
188+ * length -= len ;
189+
166190 return ash ;
167191}
168192#endif /* CONFIG_NET_L2_IEEE802154_SECURITY */
169193
170194static inline bool
171- validate_beacon (struct ieee802154_mpdu * mpdu , u8_t * buf , u8_t length )
195+ validate_beacon (struct ieee802154_mpdu * mpdu , u8_t * buf , u8_t * length )
172196{
173197 struct ieee802154_beacon * b = (struct ieee802154_beacon * )buf ;
174- u8_t * p_buf = buf ;
175198 struct ieee802154_pas_spec * pas ;
199+ u8_t len = IEEE802154_BEACON_SF_SIZE +
200+ IEEE802154_BEACON_GTS_SPEC_SIZE ;
201+
176202
177- if (length < IEEE802154_BEACON_MIN_SIZE ) {
203+ if (* length < len ) {
178204 return false;
179205 }
180206
181- p_buf += IEEE802154_BEACON_SF_SIZE + IEEE802154_BEACON_GTS_SPEC_SIZE ;
182-
183207 if (b -> gts .desc_count ) {
184- p_buf += IEEE802154_BEACON_GTS_DIR_SIZE +
208+ len += IEEE802154_BEACON_GTS_DIR_SIZE +
185209 b -> gts .desc_count * IEEE802154_BEACON_GTS_SIZE ;
186210 }
187211
188- if (length < ( p_buf - buf ) ) {
212+ if (* length < len ) {
189213 return false;
190214 }
191215
192- pas = (struct ieee802154_pas_spec * )p_buf ;
193- p_buf += IEEE802154_BEACON_PAS_SPEC_SIZE ;
216+ pas = (struct ieee802154_pas_spec * )buf + len ;
217+
218+ len += IEEE802154_BEACON_PAS_SPEC_SIZE ;
219+ if (* length < len ) {
220+ return false;
221+ }
194222
195223 if (pas -> nb_sap || pas -> nb_eap ) {
196- p_buf += (pas -> nb_sap * IEEE802154_SHORT_ADDR_LENGTH ) +
224+ len += (pas -> nb_sap * IEEE802154_SHORT_ADDR_LENGTH ) +
197225 (pas -> nb_eap * IEEE802154_EXT_ADDR_LENGTH );
198226 }
199227
200- if (length < ( p_buf - buf ) ) {
228+ if (* length < len ) {
201229 return false;
202230 }
203231
232+ * length -= len ;
204233 mpdu -> beacon = b ;
205234
206235 return true;
@@ -241,26 +270,37 @@ validate_mac_command_cfi_to_mhr(struct ieee802154_mhr *mhr,
241270}
242271
243272static inline bool
244- validate_mac_command (struct ieee802154_mpdu * mpdu , u8_t * buf , u8_t length )
273+ validate_mac_command (struct ieee802154_mpdu * mpdu , u8_t * buf , u8_t * length )
245274{
246275 struct ieee802154_command * c = (struct ieee802154_command * )buf ;
276+ u8_t len = IEEE802154_CMD_CFI_LENGTH ;
247277 bool src_pan_brdcst_chk = false;
248278 bool dst_brdcst_chk = false;
249279 u8_t comp = 0U ;
250280 u8_t ar = 0U ;
251281 u8_t src , dst ;
252282
283+ if (* length < len ) {
284+ return false;
285+ }
286+
253287 switch (c -> cfi ) {
254288 case IEEE802154_CFI_UNKNOWN :
255289 return false;
256290 case IEEE802154_CFI_ASSOCIATION_REQUEST :
291+ len += IEEE802154_CMD_ASSOC_REQ_LENGTH ;
257292 src = IEEE802154_EXT_ADDR_LENGTH ;
258293 src_pan_brdcst_chk = true;
259294 dst = IEEE802154_ADDR_MODE_SHORT |
260295 IEEE802154_ADDR_MODE_EXTENDED ;
296+
261297 break ;
262298 case IEEE802154_CFI_ASSOCIATION_RESPONSE :
299+ len += IEEE802154_CMD_ASSOC_RES_LENGTH ;
263300 case IEEE802154_CFI_DISASSOCIATION_NOTIFICATION :
301+ if (c -> cfi == IEEE802154_CFI_DISASSOCIATION_NOTIFICATION ) {
302+ len += IEEE802154_CMD_DISASSOC_NOTE_LENGTH ;
303+ }
264304 case IEEE802154_CFI_PAN_ID_CONLICT_NOTIFICATION :
265305 ar = 1U ;
266306 comp = 1U ;
@@ -296,6 +336,7 @@ validate_mac_command(struct ieee802154_mpdu *mpdu, u8_t *buf, u8_t length)
296336
297337 break ;
298338 case IEEE802154_CFI_COORDINATOR_REALIGNEMENT :
339+ len += IEEE802154_CMD_COORD_REALIGN_LENGTH ;
299340 src = IEEE802154_EXT_ADDR_LENGTH ;
300341
301342 if (mpdu -> mhr .fs -> fc .dst_addr_mode ==
@@ -308,6 +349,7 @@ validate_mac_command(struct ieee802154_mpdu *mpdu, u8_t *buf, u8_t length)
308349
309350 break ;
310351 case IEEE802154_CFI_GTS_REQUEST :
352+ len += IEEE802154_GTS_REQUEST_LENGTH ;
311353 ar = 1U ;
312354 src = IEEE802154_ADDR_MODE_SHORT ;
313355 dst = IEEE802154_ADDR_MODE_NONE ;
@@ -317,54 +359,60 @@ validate_mac_command(struct ieee802154_mpdu *mpdu, u8_t *buf, u8_t length)
317359 return false;
318360 }
319361
362+ if (* length < len ) {
363+ return false;
364+ }
365+
320366 if (!validate_mac_command_cfi_to_mhr (& mpdu -> mhr , ar , comp ,
321367 src , src_pan_brdcst_chk ,
322368 dst , dst_brdcst_chk )) {
323369 return false;
324370 }
325371
372+ * length -= len ;
326373 mpdu -> command = c ;
327374
328375 return true;
329376}
330377
331378static inline bool
332379validate_payload_and_mfr (struct ieee802154_mpdu * mpdu ,
333- u8_t * buf , u8_t * p_buf , u8_t length )
380+ u8_t * buf , u8_t * p_buf , u8_t * length )
334381{
335382 u8_t type = mpdu -> mhr .fs -> fc .frame_type ;
336- u8_t payload_length ;
337-
338- payload_length = length - (p_buf - buf );
339383
340- NET_DBG ("Header size: %u, vs total length %u: payload size %u" ,
341- (u32_t )(p_buf - buf ), length , payload_length );
384+ NET_DBG ("Header size: %u, payload size %u" ,
385+ (u32_t )(p_buf - buf ), * length );
342386
343387 if (type == IEEE802154_FRAME_TYPE_BEACON ) {
344- if (!validate_beacon (mpdu , p_buf , payload_length )) {
388+ if (!validate_beacon (mpdu , p_buf , length )) {
345389 return false;
346390 }
347391 } else if (type == IEEE802154_FRAME_TYPE_DATA ) {
348392 /** A data frame embeds a payload */
349- if (payload_length == 0U ) {
393+ if (* length == 0U ) {
350394 return false;
351395 }
352396
353397 mpdu -> payload = (void * )p_buf ;
354398 } else if (type == IEEE802154_FRAME_TYPE_ACK ) {
355399 /** An ACK frame has no payload */
356- if (payload_length ) {
400+ if (* length ) {
357401 return false;
358402 }
359403
360404 mpdu -> payload = NULL ;
361405 } else {
362- if (!validate_mac_command (mpdu , p_buf , payload_length )) {
406+ if (!validate_mac_command (mpdu , p_buf , length )) {
363407 return false;
364408 }
365409 }
366410
367- mpdu -> mfr = (struct ieee802154_mfr * )(p_buf + payload_length );
411+ if (* length ) {
412+ mpdu -> mfr = (struct ieee802154_mfr * )(p_buf + * length );
413+ } else {
414+ mpdu -> mfr = NULL ;
415+ }
368416
369417 return true;
370418}
@@ -379,7 +427,7 @@ bool ieee802154_validate_frame(u8_t *buf, u8_t length,
379427 return false;
380428 }
381429
382- mpdu -> mhr .fs = ieee802154_validate_fc_seq (buf , & p_buf );
430+ mpdu -> mhr .fs = ieee802154_validate_fc_seq (buf , & p_buf , & length );
383431 if (!mpdu -> mhr .fs ) {
384432 return false;
385433 }
@@ -389,25 +437,26 @@ bool ieee802154_validate_frame(u8_t *buf, u8_t length,
389437 return false;
390438 }
391439
392- mpdu -> mhr .dst_addr = validate_addr (p_buf , & p_buf ,
440+ mpdu -> mhr .dst_addr = validate_addr (p_buf , & p_buf , & length ,
393441 mpdu -> mhr .fs -> fc .dst_addr_mode ,
394442 false);
395443
396- mpdu -> mhr .src_addr = validate_addr (p_buf , & p_buf ,
444+ mpdu -> mhr .src_addr = validate_addr (p_buf , & p_buf , & length ,
397445 mpdu -> mhr .fs -> fc .src_addr_mode ,
398446 (mpdu -> mhr .fs -> fc .pan_id_comp ));
399447
400448#ifdef CONFIG_NET_L2_IEEE802154_SECURITY
401449 if (mpdu -> mhr .fs -> fc .security_enabled ) {
402450 mpdu -> mhr .aux_sec =
403- ieee802154_validate_aux_security_hdr (p_buf , & p_buf );
451+ ieee802154_validate_aux_security_hdr (p_buf , & p_buf ,
452+ & length );
404453 if (!mpdu -> mhr .aux_sec ) {
405454 return false;
406455 }
407456 }
408457#endif
409458
410- return validate_payload_and_mfr (mpdu , buf , p_buf , length );
459+ return validate_payload_and_mfr (mpdu , buf , p_buf , & length );
411460}
412461
413462u8_t ieee802154_compute_header_size (struct net_if * iface ,
0 commit comments