M2Crypto.X509.new_extension() … unknown value in v2i _AUTHORITY_KEYID via X509V3_EXT_nconf_nid

Matěj Cepl <[email protected]> Wed, 10 Sep 2025 15:39:52 +0200
Newsgroups gmane.comp.encryption.openssl.user
Message-ID <[email protected]>
I am working on fixing https://todo.sr.ht/~mcepl/m2crypto/9
(the current WIP patch is at
https://git.sr.ht/~mcepl/m2crypto/log/9_X509-new_extension ), but
I have hard time to fix the last test.

This is the key function `new_extension`:

```python
def new_extension(
    name: str, value: str, critical: int = 0, _pyfree: int = 1
) -> X509_Extension:
    """
    Create new X509_Extension instance.
    """
    if not isinstance(name, str):
        raise TypeError("Extension name must be a string.")
    if not isinstance(critical, (int, bool)):
        raise TypeError("Critical flag must be an integer or boolean.")

    # This will be transformed for the final OpenSSL API call.
    api_value = value
    # This will be the value passed to the validator.
    value_to_validate = value

    log.debug(f"name = {name}")
    log.debug(f"api_value before processing = {api_value}")

    # Normalize value for specific extensions
    if name == "authorityKeyIdentifier":
        # The keyid prefix is required, and the colons in the hex
        # string MUST be preserved for the OpenSSL parser.
        if "keyid" not in api_value.lower():
            formatted_value = "keyid:" + api_value
            api_value = formatted_value
            value_to_validate = formatted_value

    elif name == "subjectKeyIdentifier":
        # For SKI, the colons must be stripped.
        if ":" in api_value:
            api_value = api_value.replace(":", "")

    log.debug(f"api_value after processing = {api_value}")
    log.debug(f"value_to_validate = {value_to_validate}")

    # Validate the value (after special handling)
    validator = _EXTENSION_VALIDATORS.get(name)
    if validator:
        validator(value_to_validate)

    # This C function now correctly initializes the context using X509V3_set_ctx_nodb
    ctx = m2.x509v3_ctx_new()
    if ctx is None:
        raise X509Error("Failed to create X509V3_CTX")

    conf = None
    try:
        # Create an empty CONF and bind it
        conf = m2.conf_new()
        if conf is None:
            raise X509Error("Failed to allocate CONF")
        m2.x509v3_set_nconf(ctx, conf)

        # Create the extension
        ext_nid = m2.obj_txt2nid(name)
        if ext_nid == 0:
            raise X509Error(f"Unknown extension name: {name}")

        x509_ext_ptr: Optional[C.X509_EXTENSION]
        # For authorityKeyIdentifier with a pre-computed key, we must use
        # x509v3_ext_nconf_nid, which reads from the CONF object.
        if name == "authorityKeyIdentifier" and "keyid:" in api_value.lower():
            section = "default"
            config_line = f"{name}={api_value}"
            m2.conf_add_string(conf, section, config_line)

            key_for_api = name
            x509_ext_ptr = m2.x509v3_ext_nconf_nid(conf, ctx, ext_nid, key_for_api)
        else:
            # For all other extensions, use the original function
            x509_ext_ptr = m2.x509v3_ext_conf_nid(ctx, ext_nid, api_value)

        if x509_ext_ptr is None:
            raise X509Error(f"Failed to create X509 extension for {name}")

        x509_ext = X509_Extension(x509_ext_ptr, _pyfree)

        if critical:
            x509_ext.set_critical(1)

        return x509_ext
    finally:
        if conf:
            m2.conf_free(conf)
        if ctx:
            m2.x509v3_ctx_free(ctx)
```

when running this test (which is basically the reproducer for the bug being fixed):

```python
    def test_multiple_extensions(self):
        # Testing for https://todo.sr.ht/~mcepl/m2crypto/9
        sub_key_id = "1C:E6:F0:58:58:32:BC:7B:BA:8E:E0:23:1B:FF:17:99:B0:4D:CF:64"
        auth_id = "1C:E6:F0:58:58:32:BC:7B:BA:8E:E0:23:1B:FF:17:99:B0:4D:CF:64"

        cert_pem_string = textwrap.dedent(
            """\
        -----BEGIN CERTIFICATE-----
        MIIGFjCCA/6gAwIBAgIJAO7rHaO9YDQDMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNV
        BAYTAlVTMQswCQYDVQQIDAJDQTESMBAGA1UEBwwJTG9zIEdhdG9zMRMwEQYDVQQK
        DApOYUplRGEgTExDMSMwIQYDVQQLDBpOYUplRGEgR2VvY2FjaGluZyBTZXJ2aWNl
        czERMA8GA1UEAwwIbG9jYWxfY2EwHhcNMTgwNTMxMTgwOTMwWhcNMzcxMjMxMTgw
        OTMwWjB7MQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExEjAQBgNVBAcMCUxvcyBH
        YXRvczETMBEGA1UECgwKTmFKZURhIExMQzEjMCEGA1UECwwaTmFKZURhIEdlb2Nh
        Y2hpbmcgU2VydmljZXMxETAPBgNVBAMMCGxvY2FsX2NhMIICIjANBgkqhkiG9w0B
        AQEFAAOCAg8AMIICCgKCAgEAwL4VBqghrv9DdUq+63Yty/kaNINIO+ldhY8GxrZd
        KXdJqanZN0nMZaW4lys7OTGKml2TzL1JiOueChky5H+8vbmXF8Mp2j3DIQRlYQae
        m/cijW4Q8QRiUNdsIcB6pB7Oa7JvyTxMsbwQC2MlE9ItNR2zJ1RMpzGvRoO+wheZ
        8zPtXquo+/rJfzoxd2G6/L9Rrwo3Izgwb6NiXbQadg675o/0shmhD1LJT5DcmvjL
        0shj+VasUKAOwgt/5GtkjjeE53VsExOkJKrH/RUodl6dXiXBq4ehtwdFGQnTDpyg
        bKSXI8M3FPU/zYjt4HYDW5R+VlkKYEdMaOwQ4b9waArCZPSh6SoSZ8SyjRN1wKqn
        da+vl5MrzPGTbnN8CXvs89+ti+iT+pdsCc/L3kdwqaV3HNE0pjTg3bChWJ/iNltF
        E3lqTmnUcMfvhHpAcj6txB4YqzvQgh7DQ4KnKwFgXvrS7t2fdgFxVe/Bl7ApXi1t
        Eg8AEjasuLqb/sTWLyvoWog1iJg7uWsv7F3DXloc7q80eAh610KtPTSzcCvOfd9I
        i6+P9yxcOZv4vCbX7rrCJt/scL2/Hz1qqQYA/DcKtvitA2hUAx6AJlMvW14Dw3tc
        nHny5lJ4Ty7ZiGN7Bg9Jj1uJusa0le2dkFwx5WjXZu2QMtjgJT8aBl3iM36jNtY7
        v6cCAwEAAaOBnDCBmTAdBgNVHQ4EFgQUHObwWFgyvHu6juAjG/8XmbBNz2QwHwYD
        VR0jBBgwFoAUHObwWFgyvHu6juAjG/8XmbBNz2QwDwYDVR0TAQH/BAUwAwEB/zAO
        BgNVHQ8BAf8EBAMCAQYwNgYDVR0fBC8wLTAroCmgJ4YlaHR0cHM6Ly9jcmwuc29t
        ZS51cmwuY29tL2xvY2FsX2NhLmNybDANBgkqhkiG9w0BAQsFAAOCAgEAepM/VwzI
        N3aWc08IgF0+J3wYAjDzq2y/ixDXwL/B/XOHElySaiDakiT6HM52Ek/LkFK67Llp
        TZIxCwViBxkkcTBS10ymGfsYY5R7lOx14SUIXPOS/Pvht1IZBuSp5J9woZjEZitk
        InmWYSmA2Q85JtFs86pNQD9gCOCd5hnKK2LqOwrPAcnOJ06FhZFT/psI5MR8XFjD
        /dJUfnkxbK6S77sCslALdsaYdWp6B4gnmZWF3tTxq1IkNKVJuGdcPLg33zFAXzmo
        POzjrTmr+1DUEahBbY/9oGcQQh0Ir9lTdd0Uym40FN/7jDA8G1CeK8lsL+TZ5dTU
        BPCI2LLd2p7c3SddMNM/GUZdoJ4LXKx3JnDu8lYpjOcL21QHjqfNSmAHzX8skery
        jawwi0yijJYwsyrB629ek0p/v16uTojs6JGddOmnz9z1/pBctRw6w83d0jNQc2yY
        g89xOl9q0Z7G6rThyNuJwworN5FaPJB2Pl7pHf2uJZEp0mq1SN3Lcfre2yXig8Tc
        rWjDY8k9VrEJG0G3n9FVv9hKvob9ngUMkmyxE5E4VWyab5gVt2m0XXJjz5Sc3530
        dQ9SXhFS7s3060/yl0BBWnTtfu9zGdKaz4lWo25Q0r7HD5y/MwUCbqpRVqXJxGHY
        d3PEYaXkdwhAi3EbarF7R8r3hKzYCpXxfI4=
        -----END CERTIFICATE-----"""
        )
        m2_x509_cert = X509.load_cert_string(cert_pem_string)

        local_ski = m2_x509_cert.get_ext("subjectKeyIdentifier")
        local_aki = m2_x509_cert.get_ext("authorityKeyIdentifier")

        X509.new_extension("subjectKeyIdentifier", sub_key_id)
        X509.new_extension("authorityKeyIdentifier", auth_id)
```

I get this:

```
mitmanek:m2crypto (9_X509-new_extension) $ python3 -munittest -v tests.test_x509.X509ExtTestCase.test_multiple_extensions
test_multiple_extensions (tests.test_x509.X509ExtTestCase.test_multiple_extensions) ... DEBUG:new_extension:name = subjectKeyIdentifier
DEBUG:new_extension:api_value before processing = 1C:E6:F0:58:58:32:BC:7B:BA:8E:E0:23:1B:FF:17:99:B0:4D:CF:64
DEBUG:new_extension:api_value after processing = 1CE6F0585832BC7BBA8EE0231BFF1799B04DCF64
DEBUG:new_extension:value_to_validate = 1C:E6:F0:58:58:32:BC:7B:BA:8E:E0:23:1B:FF:17:99:B0:4D:CF:64
DEBUG:validate_subject_key_identifier:value: 1C:E6:F0:58:58:32:BC:7B:BA:8E:E0:23:1B:FF:17:99:B0:4D:CF:64
DEBUG:validate_subject_key_identifier:cleaned_value: 1CE6F0585832BC7BBA8EE0231BFF1799B04DCF64
DEBUG:new_extension:name = authorityKeyIdentifier
DEBUG:new_extension:api_value before processing = 1C:E6:F0:58:58:32:BC:7B:BA:8E:E0:23:1B:FF:17:99:B0:4D:CF:64
DEBUG:new_extension:api_value after processing = keyid:1C:E6:F0:58:58:32:BC:7B:BA:8E:E0:23:1B:FF:17:99:B0:4D:CF:64
DEBUG:new_extension:value_to_validate = keyid:1C:E6:F0:58:58:32:BC:7B:BA:8E:E0:23:1B:FF:17:99:B0:4D:CF:64
DEBUG:validate_subject_key_identifier:value: 1C:E6:F0:58:58:32:BC:7B:BA:8E:E0:23:1B:FF:17:99:B0:4D:CF:64
DEBUG:validate_subject_key_identifier:cleaned_value: 1CE6F0585832BC7BBA8EE0231BFF1799B04DCF64
4076D136C37F0000:error:110000AC:X509 V3 routines:v2i_AUTHORITY_KEYID:unknown value:crypto/x509/v3_akid.c:142:name=authorityKeyIdentifier
ERROR

======================================================================
ERROR: test_multiple_extensions (tests.test_x509.X509ExtTestCase.test_multiple_extensions)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/matej/archiv/2014/projekty/m2crypto/tests/test_x509.py", line 845, in test_multiple_extensions
    X509.new_extension("authorityKeyIdentifier", auth_id)
    ~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/matej/archiv/2014/projekty/m2crypto/build/lib.linux-x86_64-cpython-313/M2Crypto/X509.py", line 270, in new_extension
    x509_ext_ptr = m2.x509v3_ext_nconf_nid(conf, ctx, ext_nid, key_for_api)
M2Crypto.X509.X509Error: Unknown error in function _wrap_x509v3_ext_nconf_nid.

----------------------------------------------------------------------
Ran 1 test in 0.004s

FAILED (errors=1)
mitmanek:m2crypto (9_X509-new_extension) $ 
```

What I am doing wrong? How can I correctly create that
`authorityKeyIdentifier` extension?

Any suggestion would be greatly appreciated.

Thank you,

Matěj

-- 
http://matej.ceplovi.cz/blog/, @[email protected]
GPG Finger: 3C76 A027 CA45 AD70 98B5  BC1D 7920 5802 880B C9D8
 
Ask yourself whether you’ve really obtained fullness of the Holy
Spirit, followed by gifts needed for your service.
    -- Francis MacNutt

-- 
You received this message because you are subscribed to the Google Groups "openssl-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to openssl-users+unsubscribe-MCmKBN63+Bmbup2nOX2J7Q@public.gmane.org
To view this discussion visit https://groups.google.com/a/openssl.org/d/msgid/openssl-users/DCP5V3HZJU7L.362SDNFYMTRLF%40cepl.eu.
E09FEF25D96484AC.asc (application/pgp-keys, 3 KB)
-----BEGIN PGP PUBLIC KEY BLOCK-----

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
wwCdEnRlCGlvnO78R0FgKXlt3RyzGuE=
=sxoW
-----END PGP PUBLIC KEY BLOCK-----
application_pgp-keys_17649572403176529298 (application/pgp-keys, 3 KB) - not displayed
signature.asc (application/pgp-signature, 252 B)
-----BEGIN PGP SIGNATURE-----

iIgEABECAEgWIQSJ70vGKIq/QxurJcPgn+8l2WSErAUCaMF/qBsUgAAAAAAEAA5t
YW51MiwyLjUrMS4xMSwyLDIOHG1jZXBsQGNlcGwuZXUACgkQ4J/vJdlkhKxMLQCf
TcTvw6f6cjX1+u96QYjoPVUiwLIAnj2cj+u+cTUzrTn2Vp9WOtB0kpy2
=g7tl
-----END PGP SIGNATURE-----