@@ -178,16 +178,39 @@ memarray_t dtlscontext_storage;
178178#define HANDSHAKE (M ) ((dtls_handshake_header_t *)((M) + DTLS_RH_LENGTH))
179179#define CLIENTHELLO (M ) ((dtls_client_hello_t *)((M) + HS_HDR_LENGTH))
180180
181- /* The length check here should work because dtls_*_to_int() works on
182- * unsigned char. Otherwise, broken messages could cause severe
183- * trouble. Note that this macro jumps out of the current program flow
184- * when the message is too short. Beware!
181+ /*
182+ * Skip variable length field.
183+ *
184+ * A variable length field is encoded with a preceding length followed by
185+ * the value. That length itself is encoded in one to three bytes using uint8,
186+ * uint16, or uint24. Decoding a variable length field requires to check first,
187+ * if the length itself is within the bounds, and if so, if the value is also
188+ * within the bounds.
189+ *
190+ * The macro "returns" the calling context with an error when the bounds are
191+ * violated.
192+ *
193+ * \param P pointer to length of the var field. Will be forwarded the end of
194+ * the var field.
195+ * \param L left overall data of P. Will be reduced by the size of the var
196+ * field.
197+ * \param T length type. e.g. uint8 or uint16
198+ * \param A alert description in case of a length violation
199+ * \param M logging message in case of a length violation
185200 */
186- #define SKIP_VAR_FIELD (P ,L ,T ) { \
187- if (L < dtls_ ## T ## _to_int(P) + sizeof(T)) \
188- goto error; \
189- L -= dtls_ ## T ## _to_int(P) + sizeof(T); \
190- P += dtls_ ## T ## _to_int(P) + sizeof(T); \
201+ #define SKIP_VAR_FIELD (P , L , T , A , M ) { \
202+ size_t skip_length = sizeof(T); \
203+ if (L < skip_length) { \
204+ dtls_info("%s: field length exceeds buffer", M); \
205+ return dtls_alert_fatal_create(A); \
206+ } \
207+ skip_length += dtls_ ## T ## _to_int(P); \
208+ if (L < skip_length) { \
209+ dtls_info("%s: field value exceeds buffer", M); \
210+ return dtls_alert_fatal_create(A); \
211+ } \
212+ L -= skip_length; \
213+ P += skip_length; \
191214 }
192215
193216/*
@@ -419,16 +442,15 @@ dtls_get_cookie(uint8 *msg, size_t msglen, uint8 **cookie) {
419442 msglen -= DTLS_HS_LENGTH + DTLS_CH_LENGTH ;
420443 msg += DTLS_HS_LENGTH + DTLS_CH_LENGTH ;
421444
422- SKIP_VAR_FIELD (msg , msglen , uint8 ); /* skip session id */
445+ /* skip session id */
446+ SKIP_VAR_FIELD (msg , msglen , uint8 , DTLS_ALERT_HANDSHAKE_FAILURE ,
447+ "get_cookie, session_id" );
423448
424449 if (msglen < (* msg & 0xff ) + sizeof (uint8 ))
425450 return dtls_alert_fatal_create (DTLS_ALERT_HANDSHAKE_FAILURE );
426451
427452 * cookie = msg + sizeof (uint8 );
428453 return dtls_uint8_to_int (msg );
429-
430- error :
431- return dtls_alert_fatal_create (DTLS_ALERT_HANDSHAKE_FAILURE );
432454}
433455
434456static int
@@ -1306,8 +1328,12 @@ dtls_update_parameters(dtls_context_t *ctx,
13061328 data_length -= DTLS_RANDOM_LENGTH ;
13071329
13081330 /* Caution: SKIP_VAR_FIELD may jump to error: */
1309- SKIP_VAR_FIELD (data , data_length , uint8 ); /* skip session id */
1310- SKIP_VAR_FIELD (data , data_length , uint8 ); /* skip cookie */
1331+ /* skip session_id */
1332+ SKIP_VAR_FIELD (data , data_length , uint8 , DTLS_ALERT_HANDSHAKE_FAILURE ,
1333+ "update_parameters, session_id" );
1334+ /* skip cookie */
1335+ SKIP_VAR_FIELD (data , data_length , uint8 , DTLS_ALERT_HANDSHAKE_FAILURE ,
1336+ "update_parameters, cookie" );
13111337
13121338 if (data_length < sizeof (uint16 )) {
13131339 dtls_debug ("cipher suites length exceeds record\n" );
@@ -3247,7 +3273,9 @@ check_server_hello(dtls_context_t *ctx,
32473273 data += DTLS_RANDOM_LENGTH ;
32483274 data_length -= DTLS_RANDOM_LENGTH ;
32493275
3250- SKIP_VAR_FIELD (data , data_length , uint8 ); /* skip session id */
3276+ /* skip session_id */
3277+ SKIP_VAR_FIELD (data , data_length , uint8 , DTLS_ALERT_DECODE_ERROR ,
3278+ "ServerHello, session_id" );
32513279 /*
32523280 * Need to re-check in case session id was not empty
32533281 * 2 bytes for the selected cipher suite
@@ -3282,9 +3310,6 @@ check_server_hello(dtls_context_t *ctx,
32823310 /* Server may not support extended master secret */
32833311 handshake -> extended_master_secret = 0 ;
32843312 return dtls_check_tls_extension (peer , data , data_length , 0 );
3285-
3286- error :
3287- return dtls_alert_fatal_create (DTLS_ALERT_DECODE_ERROR );
32883313}
32893314
32903315static int
0 commit comments