From 10677d56a950dc190a03ab7ceb0a37c3591fb91d Mon Sep 17 00:00:00 2001 From: OuyangHang33 Date: Sun, 7 Apr 2024 13:32:31 +0800 Subject: [PATCH] add integer overflow check Signed-off-by: OuyangHang33 --- spdmlib/src/crypto/x509v3.rs | 88 +++++++++++++++++++++++++++++++----- 1 file changed, 77 insertions(+), 11 deletions(-) diff --git a/spdmlib/src/crypto/x509v3.rs b/spdmlib/src/crypto/x509v3.rs index 8b2843a..ed854c6 100644 --- a/spdmlib/src/crypto/x509v3.rs +++ b/spdmlib/src/crypto/x509v3.rs @@ -170,7 +170,8 @@ fn check_tbs_certificate( // extensions [3] EXPLICIT Extensions OPTIONAL // key_usage EXTENSIONS, - let (find_key_usage, key_usage_value) = get_key_usage_value(&data[t_walker..])?; + let (bytes_consumed, extension_data) = check_and_get_extensions(&data[t_walker..])?; + let (find_key_usage, key_usage_value) = get_key_usage_value(extension_data)?; // The digitalSignature bit SHOULD asserted when subject public key is used for verifying digital signatures // in an entity authentication service, a data origin authentication service, and/or an integrity service. let check_extensions_success = !(find_key_usage @@ -179,7 +180,6 @@ fn check_tbs_certificate( // when key usage digitalSignature bit unset, it SHOULD return false. //extensions EXTENSIONS, - let (bytes_consumed, extension_data) = check_and_get_extensions(&data[t_walker..])?; let check_extn_spdm_success = check_extensions_spdm_oid(extension_data, is_leaf_cert)?; t_walker += bytes_consumed; @@ -381,7 +381,7 @@ fn get_key_usage_value(data: &[u8]) -> SpdmResult<(bool, u8)> { let mut find_key_usage = false; let len = data.len(); let key_usage_oid_len = OID_KEY_USAGE.len(); - if len < 1 { + if len < 1 || data[0] != ASN1_TAG_SEQUENCE { return Err(SPDM_STATUS_VERIF_FAIL); } let (data_length, bytes_consumed) = check_length(&data[1..])?; @@ -389,10 +389,18 @@ fn get_key_usage_value(data: &[u8]) -> SpdmResult<(bool, u8)> { Err(SPDM_STATUS_VERIF_FAIL) } else { let mut index = 1 + bytes_consumed; - while index < data_length { + // search KEY_Usage OID in Extensions Sequence + while index < len { + if index + 1 > len { + return Err(SPDM_STATUS_VERIF_FAIL); + } let (payload_length, bytes_consumed) = check_length(&data[index + 1..])?; + if index + 1 + bytes_consumed + payload_length > len { + return Err(SPDM_STATUS_VERIF_FAIL); + } + // search in sequence, skip bytes consumed if data[index] == ASN1_TAG_SEQUENCE { - index += 1 + payload_length; + index += 1 + bytes_consumed; continue; } else if data[index] == ASN1_TAG_NUMBER_OBJECT_IDENTIFIER && payload_length == key_usage_oid_len @@ -402,23 +410,45 @@ fn get_key_usage_value(data: &[u8]) -> SpdmResult<(bool, u8)> { ) { index += 1 + bytes_consumed + payload_length; + if index > len { + return Err(SPDM_STATUS_VERIF_FAIL); + } + if data[index] == ASN1_TAG_EXTN_VALUE { + if index + 1 > len { + return Err(SPDM_STATUS_VERIF_FAIL); + } let (_, extnvalue_consumed) = check_length(&data[index + 1..])?; index += 1 + extnvalue_consumed; + + if index > len { + return Err(SPDM_STATUS_VERIF_FAIL); + } + if data[index] == ASN1_TAG_BIT_STRING { + if index + 1 > len { + return Err(SPDM_STATUS_VERIF_FAIL); + } let (string_length, string_consumed) = check_length(&data[index + 1..])?; index += string_consumed + string_length; + + if index > len { + return Err(SPDM_STATUS_VERIF_FAIL); + } find_key_usage = true; } else { find_key_usage = false; } break; } else { - index += 1 + bytes_consumed + payload_length; - continue; + return Err(SPDM_STATUS_VERIF_FAIL); } } else { + // if not Sequence or OID tag, skip index += 1 + bytes_consumed + payload_length; + if index > len { + return Err(SPDM_STATUS_VERIF_FAIL); + } continue; } } @@ -446,6 +476,9 @@ fn check_extensions_spdm_oid(extensions: &[u8], is_leaf_cert: bool) -> SpdmResul let mut index = 0; while index < payload_length { let (extnid, extn_sequence_len) = check_and_get_extn_id(&extn_sequences[index..])?; + if index + extn_sequence_len > sequences_len { + return Err(SPDM_STATUS_VERIF_FAIL); + } // find the first level extension identifiy from extensions sequence if object_identifiers_are_same(extnid, OID_SUBJECT_ALTERNATIVE_NAME) { if find_target_object_identifier_in_single_extension( @@ -508,12 +541,21 @@ fn find_target_object_identifier_in_single_extension( let mut target_oid_find_success = false; let len = data.len(); let target_oid_len = target_oid.len(); - if len < target_oid_len { + if len < 1 { + Err(SPDM_STATUS_VERIF_FAIL) + } else if len < target_oid_len { target_oid_find_success = false; + Ok(target_oid_find_success) } else { let mut index = 0; while index < len - target_oid_len { + if index + 1 > len { + return Err(SPDM_STATUS_VERIF_FAIL); + } let (payload_length, bytes_consumed) = check_length(&data[index + 1..])?; + if index + 1 + bytes_consumed + payload_length > len { + return Err(SPDM_STATUS_VERIF_FAIL); + } if data[index] == ASN1_TAG_NUMBER_OBJECT_IDENTIFIER { if object_identifiers_are_same( &data[index + 1 + bytes_consumed..index + 1 + bytes_consumed + payload_length], @@ -524,18 +566,27 @@ fn find_target_object_identifier_in_single_extension( break; } else { index += 1 + bytes_consumed + payload_length; + if index > len { + return Err(SPDM_STATUS_VERIF_FAIL); + } continue; } } else if data[index] == ASN1_TAG_SEQUENCE || data[index] == ASN1_TAG_EXTN_VALUE { index += 1 + bytes_consumed; + if index > len { + return Err(SPDM_STATUS_VERIF_FAIL); + } continue; } else { index += 1 + bytes_consumed + payload_length; + if index > len { + return Err(SPDM_STATUS_VERIF_FAIL); + } continue; } } + Ok(target_oid_find_success) } - Ok(target_oid_find_success) } // IN extension sequences slice @@ -1359,10 +1410,12 @@ mod tests { #[test] fn test_case0_get_key_usage_value() { let key_usage1 = &[ - 0x30, 0x0B, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x04, 0x04, 0x03, 0x02, 0x05, 0xE0, + 0x30, 0x0B, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x04, 0x04, 0x03, 0x02, 0x05, + 0xE0, ]; let key_usage2_wrong = &[ - 0x30, 0x0B, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x04, 0x03, 0x02, 0x05, 0xE0, + 0x30, 0x0B, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x04, 0x03, 0x02, 0x05, + 0xE0, ]; let key_usage3_wrong = &[0x30, 0x0B]; let key_usage4_wrong = &[ @@ -1380,6 +1433,19 @@ mod tests { ); } + #[test] + fn test_case1_get_key_usage_value() { + let key_usage1 = std::fs::read("../test_key/ecp384/end_responder.cert.der") + .expect("unable to read leaf cert!"); + let key_usage2 = std::fs::read("../test_key/rsa2048/end_requester_with_spdm_rsp_eku.cert.der") + .expect("unable to read leaf cert!"); + let key_usage3 = std::fs::read("../test_key/rsa2048/end_responder_with_spdm_req_eku.cert.der") + .expect("unable to read leaf cert!"); + assert_eq!(get_key_usage_value(&key_usage1[280..],), Ok((true, key_usage1[309]))); + assert_eq!(get_key_usage_value(&key_usage2[450..],), Ok((true, key_usage2[478]))); + assert_eq!(get_key_usage_value(&key_usage3[450..],), Ok((true, key_usage3[478]))); + } + #[test] fn test_case0_check_extensions_spdm_oid() { let e1 = std::fs::read("../test_key/ecp384/end_responder.cert.der")