@@ -190,6 +190,41 @@ memarray_t dtlscontext_storage;
190190 P += dtls_ ## T ## _to_int(P) + sizeof(T); \
191191 }
192192
193+ /*
194+ * Get variable length field.
195+ *
196+ * A variable length field is encoded with a preceding length followed by
197+ * the value. That length itself is encoded in one to three bytes using uint8,
198+ * uint16, or uint24. Decoding a variable length field requires to check first,
199+ * if the length itself is within the bounds, and if so, if the value is also
200+ * within the bounds.
201+ *
202+ * The macro "returns" the calling context with an error when the bounds are
203+ * violated.
204+ *
205+ * \param VL value length, variable to assign the length of the field value.
206+ * \param P pointer to length of the var field. Will be forwarded to the
207+ * value of the field.
208+ * \param L left overall data of P. Will be reduced by the size of the field
209+ * length type
210+ * \param T field length type. e.g. uint8 or uint16
211+ * \param A alert description in case of a length violation
212+ * \param M logging message in case of a length violation
213+ */
214+ #define GET_VAR_FIELD (VL , P , L , T , A , M ) { \
215+ if (L < sizeof(T)) { \
216+ dtls_info("%s: field length exceeds buffer", M); \
217+ return dtls_alert_fatal_create(A); \
218+ } \
219+ VL = dtls_ ## T ## _to_int(P); \
220+ L -= sizeof(T); \
221+ P += sizeof(T); \
222+ if (L < VL) { \
223+ dtls_info("%s: field value exceeds buffer", M); \
224+ return dtls_alert_fatal_create(A); \
225+ } \
226+ }
227+
193228/* some constants for the PRF */
194229#define PRF_LABEL (Label ) prf_label_##Label
195230#define PRF_LABEL_SIZE (Label ) (sizeof(PRF_LABEL(Label)) - 1)
@@ -3470,39 +3505,37 @@ check_certificate_request(dtls_context_t *ctx,
34703505
34713506 assert (is_key_exchange_ecdhe_ecdsa (peer -> handshake_params -> cipher_index ));
34723507
3473- data += DTLS_HS_LENGTH ;
3474-
34753508 if (data_length < DTLS_HS_LENGTH + 5 ) {
34763509 dtls_alert ("the packet length does not match the expected\n" );
34773510 return dtls_alert_fatal_create (DTLS_ALERT_DECODE_ERROR );
34783511 }
34793512
3480- i = dtls_uint8_to_int (data );
3481- data += sizeof (uint8 );
3482- if (i + 1 > data_length ) {
3483- dtls_alert ("the certificate types are too long\n" );
3484- return dtls_alert_fatal_create (DTLS_ALERT_DECODE_ERROR );
3485- }
3513+ data += DTLS_HS_LENGTH ;
3514+ data_length -= DTLS_HS_LENGTH ;
3515+
3516+ GET_VAR_FIELD (i , data , data_length , uint8 , DTLS_ALERT_DECODE_ERROR ,
3517+ "CertificateRequest, certificate_types" );
34863518
34873519 auth_alg = 0 ;
34883520 for (; i > 0 ; i -= sizeof (uint8 )) {
3489- if (dtls_uint8_to_int (data ) == TLS_CLIENT_CERTIFICATE_TYPE_ECDSA_SIGN
3490- && auth_alg == 0 )
3491- auth_alg = dtls_uint8_to_int (data );
3521+ if (dtls_uint8_to_int (data ) == TLS_CLIENT_CERTIFICATE_TYPE_ECDSA_SIGN ) {
3522+ auth_alg = TLS_CLIENT_CERTIFICATE_TYPE_ECDSA_SIGN ;
3523+ /* skip the rest of the field value */
3524+ data += i ;
3525+ data_length -= i ;
3526+ break ;
3527+ }
34923528 data += sizeof (uint8 );
3529+ data_length -= sizeof (uint8 );
34933530 }
34943531
34953532 if (auth_alg != TLS_CLIENT_CERTIFICATE_TYPE_ECDSA_SIGN ) {
3496- dtls_alert ("the request authentication algorithm is not supproted \n" );
3533+ dtls_alert ("the request authentication algorithm is not supported \n" );
34973534 return dtls_alert_fatal_create (DTLS_ALERT_HANDSHAKE_FAILURE );
34983535 }
34993536
3500- i = dtls_uint16_to_int (data );
3501- data += sizeof (uint16 );
3502- if (i + 1 > data_length ) {
3503- dtls_alert ("the signature and hash algorithm list is too long\n" );
3504- return dtls_alert_fatal_create (DTLS_ALERT_DECODE_ERROR );
3505- }
3537+ GET_VAR_FIELD (i , data , data_length , uint16 , DTLS_ALERT_DECODE_ERROR ,
3538+ "CertificateRequest, signature_algorithms" );
35063539
35073540 hash_alg = 0 ;
35083541 sig_alg = 0 ;
@@ -3513,7 +3546,7 @@ check_certificate_request(dtls_context_t *ctx,
35133546 dtls_alert ("illegal certificate request\n" );
35143547 return dtls_alert_fatal_create (DTLS_ALERT_HANDSHAKE_FAILURE );
35153548 }
3516-
3549+
35173550 for (; i >= sizeof (uint16 ); i -= sizeof (uint16 )) {
35183551 int current_hash_alg ;
35193552 int current_sig_alg ;
@@ -3523,10 +3556,13 @@ check_certificate_request(dtls_context_t *ctx,
35233556 current_sig_alg = dtls_uint8_to_int (data );
35243557 data += sizeof (uint8 );
35253558
3559+ data_length -= sizeof (uint16 );
3560+
35263561 if (current_hash_alg == TLS_EXT_SIG_HASH_ALGO_SHA256 && hash_alg == 0 &&
35273562 current_sig_alg == TLS_EXT_SIG_HASH_ALGO_ECDSA && sig_alg == 0 ) {
35283563 hash_alg = current_hash_alg ;
35293564 sig_alg = current_sig_alg ;
3565+ break ;
35303566 }
35313567 }
35323568
0 commit comments