@@ -1007,6 +1007,54 @@ prepare_for_validation(signed_video_t *self)
10071007 return status ;
10081008}
10091009
1010+ static void
1011+ extract_optional_info_from_sei (signed_video_t * self , bu_list_item_t * item )
1012+ {
1013+ bu_info_t * bu = item -> bu ;
1014+ if (!bu -> is_sv_sei ) {
1015+ return ;
1016+ }
1017+ // Even if a SEI without signature (signing multiple GOPs) could include optional
1018+ // information like the public key it is not safe to use that until the SEI can be
1019+ // verified. Therefore, a SEI is not decoded to get the cryptographic information if it
1020+ // is not signed directly.
1021+ if (!bu -> is_signed ) {
1022+ return ;
1023+ }
1024+
1025+ const uint8_t * tlv_data = bu -> tlv_data ;
1026+ size_t tlv_size = bu -> tlv_size ;
1027+ size_t num_of_tags = 0 ;
1028+ const sv_tlv_tag_t * optional_tags = sv_get_optional_tags (& num_of_tags );
1029+ sv_tlv_find_and_decode_tags (self , tlv_data , tlv_size , optional_tags , num_of_tags );
1030+ }
1031+
1032+ // If this is a Signed Video generated SEI, including a signature, decode all the
1033+ // optional TLV information and verify the signature.
1034+ static svrc_t
1035+ verify_sei_signature (signed_video_t * self , bu_list_item_t * item , int * verified_result )
1036+ {
1037+ bu_info_t * bu = item -> bu ;
1038+ if (!bu -> is_sv_sei || !bu -> is_signed ) {
1039+ return SV_OK ;
1040+ }
1041+ const sv_tlv_tag_t signature_tag = SIGNATURE_TAG ;
1042+ if (!sv_tlv_find_and_decode_tags (
1043+ self , item -> bu -> tlv_data , item -> bu -> tlv_size , & signature_tag , 1 )) {
1044+ return SV_OK ;
1045+ }
1046+ if (!self -> has_public_key ) {
1047+ // If no public key has been set, validation is not supported. This can happen if the
1048+ // Public key was not added to the SEI and the validation side has not set it
1049+ // manually.
1050+ return SV_NOT_SUPPORTED ;
1051+ }
1052+
1053+ memcpy (self -> verify_data -> hash , item -> hash , self -> verify_data -> hash_size );
1054+
1055+ return sv_openssl_verify_hash (self -> verify_data , verified_result );
1056+ }
1057+
10101058// If public_key is not received then try to decode all recurrent tags.
10111059static bool
10121060is_recurrent_data_decoded (signed_video_t * self )
@@ -1267,8 +1315,22 @@ register_bu(signed_video_t *self, bu_list_item_t *item)
12671315
12681316 if (bu -> is_valid == 0 ) return SV_OK ;
12691317
1318+ extract_optional_info_from_sei (self , item );
12701319 sv_update_hashable_data (bu );
1271- return hash_and_add_for_auth (self , item );
1320+
1321+ svrc_t status = SV_UNKNOWN_FAILURE ;
1322+ SV_TRY ()
1323+ SV_THROW (hash_and_add_for_auth (self , item ));
1324+ if (bu -> is_signed ) {
1325+ SV_THROW (verify_sei_signature (self , item , & item -> verified_signature ));
1326+ // TODO: Decide what to do if verification fails. Should mark public key as not
1327+ // present?
1328+ DEBUG_LOG ("Verified SEI signature with result %d" , item -> verified_signature );
1329+ }
1330+ SV_CATCH ()
1331+ SV_DONE (status )
1332+
1333+ return status ;
12721334}
12731335
12741336/* All Bitstream Units in the |bu_list| are re-registered by hashing them. */
@@ -1399,6 +1461,7 @@ add_bitstream_unit(signed_video_t *self, const uint8_t *bu_data, size_t bu_data_
13991461 validation_flags -> has_auth_result = false;
14001462
14011463 self -> accumulated_validation -> number_of_received_nalus ++ ;
1464+ const bool nalus_pending_registration = !self -> validation_flags .hash_algo_known ;
14021465
14031466 svrc_t status = SV_UNKNOWN_FAILURE ;
14041467 SV_TRY ()
@@ -1414,22 +1477,19 @@ add_bitstream_unit(signed_video_t *self, const uint8_t *bu_data, size_t bu_data_
14141477 // As soon as the first Signed Video SEI arrives (|signing_present| is true) and the
14151478 // crypto TLV tag has been decoded it is feasible to hash the temporarily stored
14161479 // Bitstream Units.
1417- if (!validation_flags -> hash_algo_known &&
1418- ((validation_flags -> signing_present && is_recurrent_data_decoded (self )) ||
1419- (bu_list -> num_gops > MAX_UNHASHED_GOPS ))) {
1420- if (!validation_flags -> hash_algo_known ) {
1421- DEBUG_LOG ("No cryptographic information found in SEI. Using default hash algo" );
1422- validation_flags -> hash_algo_known = true;
1423- }
1424- if (bu .is_golden_sei ) SV_THROW (prepare_golden_sei (self , bu_list -> last_item ));
1425-
1426- // Determine if legacy validation should be applied, that is, if the legacy way of
1427- // using linked hashes and recursive GOP hash is detected.
1428- if (validation_flags -> signing_present && (!(bu .reserved_byte & 0x30 ) && !bu .is_golden_sei )) {
1429- self -> legacy_sv = legacy_sv_create (self );
1430- SV_THROW_IF (!self -> legacy_sv , SV_MEMORY );
1431- sv_accumulated_validation_init (self -> accumulated_validation );
1432- }
1480+ if (!validation_flags -> signing_present && (bu_list -> num_gops > MAX_UNHASHED_GOPS )) {
1481+ validation_flags -> hash_algo_known = true;
1482+ }
1483+ if (bu .is_golden_sei ) SV_THROW (prepare_golden_sei (self , bu_list -> last_item ));
1484+
1485+ // Determine if legacy validation should be applied, that is, if the legacy way of
1486+ // using linked hashes and recursive GOP hash is detected.
1487+ if (bu .is_sv_sei && (!(bu .reserved_byte & 0x30 ) && !bu .is_golden_sei )) {
1488+ self -> legacy_sv = legacy_sv_create (self );
1489+ SV_THROW_IF (!self -> legacy_sv , SV_MEMORY );
1490+ sv_accumulated_validation_init (self -> accumulated_validation );
1491+ }
1492+ if (nalus_pending_registration && self -> validation_flags .hash_algo_known ) {
14331493 SV_THROW (reregister_bu (self ));
14341494 }
14351495 SV_THROW (maybe_validate_gop (self , & bu ));
0 commit comments