diff --git a/src/rust/src/x509/common.rs b/src/rust/src/x509/common.rs index 29dba6dd2d04..f8925865b685 100644 --- a/src/rust/src/x509/common.rs +++ b/src/rust/src/x509/common.rs @@ -234,7 +234,13 @@ fn parse_name_attribute<'p>( "Long-form tags are not supported in NameAttribute values", )) })?; - let py_tag = types::ASN1_TYPE_TO_ENUM.get(py)?.get_item(tag_val)?; + // A value whose tag is not one of the recognised string types is not a + // valid AttributeValue; surface it as a parse error rather than letting the + // dict lookup raise a bare KeyError. + let py_tag = types::ASN1_TYPE_TO_ENUM + .get(py)? + .get_item(tag_val) + .map_err(|_| asn1::ParseError::new(asn1::ParseErrorKind::InvalidValue))?; let py_data = match attribute.value { AttributeValue::AnyString(s) => { if s.tag() == asn1::BitString::TAG { diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index aa3ff0bdfb12..a15abfb3027c 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -1334,6 +1334,34 @@ def test_invalid_unicode_name(self, backend): with pytest.raises(ValueError, match="issuer"): cert.issuer + def test_name_attribute_unsupported_type_tag(self, backend): + # A name attribute value whose ASN.1 tag is not one of the recognised + # string types must raise a ValueError, not a bare KeyError. + key = ec.generate_private_key(ec.SECP256R1()) + cert = ( + x509.CertificateBuilder() + .subject_name( + x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, "PyCA")]) + ) + .issuer_name( + x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, "PyCA")]) + ) + .public_key(key.public_key()) + .serial_number(1) + .not_valid_before(datetime.datetime(2020, 1, 1)) + .not_valid_after(datetime.datetime(2030, 1, 1)) + .sign(key, hashes.SHA256()) + ) + der = bytearray(cert.public_bytes(serialization.Encoding.DER)) + # Find id-at-commonName (2.5.4.3) and replace the following + # UTF8String tag with an unsupported tag value. The first occurrence + # is the issuer name. + idx = der.index(b"\x06\x03\x55\x04\x03") + der[idx + 5] = 0x69 + cert = x509.load_der_x509_certificate(bytes(der)) + with pytest.raises(ValueError, match="issuer"): + cert.issuer + def test_non_ascii_dns_name(self, backend): cert = _load_cert( os.path.join("x509", "utf8-dnsname.pem"),