diff --git a/components/mbedtls/Kconfig b/components/mbedtls/Kconfig index 069b15c4672..bb132145484 100644 --- a/components/mbedtls/Kconfig +++ b/components/mbedtls/Kconfig @@ -516,6 +516,11 @@ menu "mbedTLS" Name of the custom certificate directory or file. This path is evaluated relative to the project root directory. + Certificates must be either PEM encoded with a .pem extension, or DER + encoded with a .der extension. Files with any other extension are not + parsed: pointing this option directly at such a file fails the build, + while such files inside a directory are skipped with a warning. + config MBEDTLS_CERTIFICATE_BUNDLE_DEPRECATED_LIST bool "Add deprecated root certificates" depends on MBEDTLS_CERTIFICATE_BUNDLE && !MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE diff --git a/components/mbedtls/esp_crt_bundle/gen_crt_bundle.py b/components/mbedtls/esp_crt_bundle/gen_crt_bundle.py index 62727057a57..c5e737ceaf2 100755 --- a/components/mbedtls/esp_crt_bundle/gen_crt_bundle.py +++ b/components/mbedtls/esp_crt_bundle/gen_crt_bundle.py @@ -46,6 +46,10 @@ except ImportError: ca_bundle_bin_file = 'x509_crt_bundle' +# Only files with these extensions are parsed, the extension has to match the encoding of the file +PEM_FILE_EXTENSION = '.pem' +DER_FILE_EXTENSION = '.der' + quiet = False @@ -70,27 +74,44 @@ class CertificateBundle: def add_from_path(self, crts_path): found = False for file_path in os.listdir(crts_path): - found |= self.add_from_file(os.path.join(crts_path, file_path)) + found |= self.add_from_file(os.path.join(crts_path, file_path), strict=False) if found is False: raise InputError('No valid x509 certificates found in %s' % crts_path) - def add_from_file(self, file_path): + def add_from_file(self, file_path, strict=True): + """Parse a certificate file + + Only files with a .pem or .der extension are parsed. If strict is True (the file was + given directly on the command line), any other extension is an error, otherwise + (while scanning a directory) the file is skipped with a warning. + """ try: - if file_path.endswith('.pem'): + if file_path.endswith(PEM_FILE_EXTENSION): status('Parsing certificates from %s' % file_path) with open(file_path, 'r', encoding='utf-8') as f: crt_str = f.read() self.add_from_pem(crt_str) return True - elif file_path.endswith('.der'): + elif file_path.endswith(DER_FILE_EXTENSION): status('Parsing certificates from %s' % file_path) with open(file_path, 'rb') as f: crt_str = f.read() self.add_from_der(crt_str) return True + elif os.path.isfile(file_path): + msg = ( + 'Unsupported file extension in %s, certificates are only parsed from files with a ' + '%s (PEM encoded) or %s (DER encoded) extension. ' + 'Please rename the file to match its encoding.' + % (file_path, PEM_FILE_EXTENSION, DER_FILE_EXTENSION) + ) + if strict: + raise InputError(msg) + critical('Warning: skipping file. %s' % msg) + except ValueError: critical('Invalid certificate in %s' % file_path) raise InputError('Invalid certificate') diff --git a/components/mbedtls/esp_crt_bundle/test_gen_crt_bundle/test_gen_crt_bundle.py b/components/mbedtls/esp_crt_bundle/test_gen_crt_bundle/test_gen_crt_bundle.py index 759aa656ca2..7cf9faa9402 100755 --- a/components/mbedtls/esp_crt_bundle/test_gen_crt_bundle/test_gen_crt_bundle.py +++ b/components/mbedtls/esp_crt_bundle/test_gen_crt_bundle/test_gen_crt_bundle.py @@ -1,6 +1,8 @@ #!/usr/bin/env python import os +import shutil import sys +import tempfile import unittest try: @@ -22,6 +24,7 @@ verified_der_bundle = 'baltimore_crt_bundle' verified_pem_bundle = 'entrust_crt_bundle' invalid_test_file = 'invalid_crt.pem' non_ascii_file = 'non_ascii_crt.pem' +unsupported_file = 'unsupported_ext_crt.crt' ca_crts_all_file = 'cacrt_all.pem' @@ -73,6 +76,37 @@ class GenCrtBundleTests(Py23TestCase): bundle.add_from_pem('') self.assertEqual(len(bundle.certificates), bundle_prev_len) + # A file given directly is expected to be a certificate, so an unknown extension is an error + def test_unsupported_extension_input(self): + bundle = gen_crt_bundle.CertificateBundle() + + with self.assertRaisesRegex(gen_crt_bundle.InputError, 'Unsupported file extension'): + bundle.add_from_file(test_crts_path + unsupported_file) + + self.assertEqual(len(bundle.certificates), 0) + + # While scanning a directory, files with an unknown extension are skipped instead + def test_unsupported_extension_in_dir(self): + bundle = gen_crt_bundle.CertificateBundle() + + self.assertFalse(bundle.add_from_file(test_crts_path + unsupported_file, strict=False)) + self.assertEqual(len(bundle.certificates), 0) + + # A directory holding both valid and unsupported files adds only the valid ones + with tempfile.TemporaryDirectory() as crts_dir: + shutil.copy(test_crts_path + unsupported_file, crts_dir) + shutil.copy(test_crts_path + pem_test_file, crts_dir) + + bundle.add_from_path(crts_dir) + self.assertEqual(len(bundle.certificates), 1) + + # A directory without any supported file is an error + with tempfile.TemporaryDirectory() as crts_dir: + shutil.copy(test_crts_path + unsupported_file, crts_dir) + + with self.assertRaisesRegex(gen_crt_bundle.InputError, 'No valid x509 certificates found'): + bundle.add_from_path(crts_dir) + def test_non_ascii_crt_input(self): bundle = gen_crt_bundle.CertificateBundle() diff --git a/components/mbedtls/esp_crt_bundle/test_gen_crt_bundle/unsupported_ext_crt.crt b/components/mbedtls/esp_crt_bundle/test_gen_crt_bundle/unsupported_ext_crt.crt new file mode 100644 index 00000000000..82e3bc0bf11 --- /dev/null +++ b/components/mbedtls/esp_crt_bundle/test_gen_crt_bundle/unsupported_ext_crt.crt @@ -0,0 +1,25 @@ +Entrust Root Certification Authority +==================================== +-----BEGIN CERTIFICATE----- +MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV +BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw +b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG +A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0 +MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu +MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu +Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v +dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz +A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww +Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68 +j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN +rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw +DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1 +MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH +hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA +A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM +Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa +v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS +W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0 +tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8 +-----END CERTIFICATE----- diff --git a/docs/en/api-reference/protocols/esp_crt_bundle.rst b/docs/en/api-reference/protocols/esp_crt_bundle.rst index ec10d5cb055..87f58700491 100644 --- a/docs/en/api-reference/protocols/esp_crt_bundle.rst +++ b/docs/en/api-reference/protocols/esp_crt_bundle.rst @@ -30,6 +30,10 @@ Most configuration is done through menuconfig. CMake generates the bundle accord * :menuitem:`CONFIG_MBEDTLS_DEFAULT_CERTIFICATE_BUNDLE`: decide which certificates to include from the complete root certificate list. * :menuitem:`CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH`: specify the path of any additional certificates to embed in the bundle. +.. note:: + + Only PEM encoded certificates with a ``.pem`` extension and DER encoded certificates with a ``.der`` extension are parsed. The extension must match the encoding of the file, for example a PEM encoded certificate saved as ``.crt`` is not accepted. If :ref:`CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH` points directly at a file with any other extension, the build fails; if such a file is found inside a certificate directory, it is skipped and a warning is printed. + To enable the bundle when using ESP-TLS simply pass the function pointer to the bundle attach function: .. code-block:: c diff --git a/docs/zh_CN/api-reference/protocols/esp_crt_bundle.rst b/docs/zh_CN/api-reference/protocols/esp_crt_bundle.rst index 4e16018de2b..c183c8e2960 100644 --- a/docs/zh_CN/api-reference/protocols/esp_crt_bundle.rst +++ b/docs/zh_CN/api-reference/protocols/esp_crt_bundle.rst @@ -30,6 +30,10 @@ ESP x509 证书包 API 提供了一种简便的方法,帮助你安装自定义 * :menuitem:`CONFIG_MBEDTLS_DEFAULT_CERTIFICATE_BUNDLE`:决定添加证书列表中的哪些证书。 * :menuitem:`CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH`:指定要在证书包中嵌入的其他证书的路径。 +.. note:: + + 只有扩展名为 ``.pem`` 的 PEM 编码证书和扩展名为 ``.der`` 的 DER 编码证书会被解析。扩展名必须与文件的编码格式一致,例如保存为 ``.crt`` 的 PEM 编码证书不会被接受。如果 :ref:`CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH` 直接指向其他扩展名的文件,构建将失败;如果证书目录中存在此类文件,该文件会被跳过并打印警告。 + 要在使用 ESP-TLS 时启用证书包,将函数指针指向证书包的 attach 函数: .. code-block:: c