mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 03:00:34 +03:00
Merge branch 'fix/crt_bundle_unsupported_cert_extension' into 'master'
fix(mbedtls):report an error for certificate files with unsupported extension See merge request espressif/esp-idf!51518
This commit is contained in:
@@ -516,6 +516,11 @@ menu "mbedTLS"
|
|||||||
Name of the custom certificate directory or file. This path is evaluated
|
Name of the custom certificate directory or file. This path is evaluated
|
||||||
relative to the project root directory.
|
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
|
config MBEDTLS_CERTIFICATE_BUNDLE_DEPRECATED_LIST
|
||||||
bool "Add deprecated root certificates"
|
bool "Add deprecated root certificates"
|
||||||
depends on MBEDTLS_CERTIFICATE_BUNDLE && !MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE
|
depends on MBEDTLS_CERTIFICATE_BUNDLE && !MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE
|
||||||
|
|||||||
@@ -46,6 +46,10 @@ except ImportError:
|
|||||||
|
|
||||||
ca_bundle_bin_file = 'x509_crt_bundle'
|
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
|
quiet = False
|
||||||
|
|
||||||
|
|
||||||
@@ -70,27 +74,44 @@ class CertificateBundle:
|
|||||||
def add_from_path(self, crts_path):
|
def add_from_path(self, crts_path):
|
||||||
found = False
|
found = False
|
||||||
for file_path in os.listdir(crts_path):
|
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:
|
if found is False:
|
||||||
raise InputError('No valid x509 certificates found in %s' % crts_path)
|
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:
|
try:
|
||||||
if file_path.endswith('.pem'):
|
if file_path.endswith(PEM_FILE_EXTENSION):
|
||||||
status('Parsing certificates from %s' % file_path)
|
status('Parsing certificates from %s' % file_path)
|
||||||
with open(file_path, 'r', encoding='utf-8') as f:
|
with open(file_path, 'r', encoding='utf-8') as f:
|
||||||
crt_str = f.read()
|
crt_str = f.read()
|
||||||
self.add_from_pem(crt_str)
|
self.add_from_pem(crt_str)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
elif file_path.endswith('.der'):
|
elif file_path.endswith(DER_FILE_EXTENSION):
|
||||||
status('Parsing certificates from %s' % file_path)
|
status('Parsing certificates from %s' % file_path)
|
||||||
with open(file_path, 'rb') as f:
|
with open(file_path, 'rb') as f:
|
||||||
crt_str = f.read()
|
crt_str = f.read()
|
||||||
self.add_from_der(crt_str)
|
self.add_from_der(crt_str)
|
||||||
return True
|
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:
|
except ValueError:
|
||||||
critical('Invalid certificate in %s' % file_path)
|
critical('Invalid certificate in %s' % file_path)
|
||||||
raise InputError('Invalid certificate')
|
raise InputError('Invalid certificate')
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
import os
|
import os
|
||||||
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -22,6 +24,7 @@ verified_der_bundle = 'baltimore_crt_bundle'
|
|||||||
verified_pem_bundle = 'entrust_crt_bundle'
|
verified_pem_bundle = 'entrust_crt_bundle'
|
||||||
invalid_test_file = 'invalid_crt.pem'
|
invalid_test_file = 'invalid_crt.pem'
|
||||||
non_ascii_file = 'non_ascii_crt.pem'
|
non_ascii_file = 'non_ascii_crt.pem'
|
||||||
|
unsupported_file = 'unsupported_ext_crt.crt'
|
||||||
ca_crts_all_file = 'cacrt_all.pem'
|
ca_crts_all_file = 'cacrt_all.pem'
|
||||||
|
|
||||||
|
|
||||||
@@ -73,6 +76,37 @@ class GenCrtBundleTests(Py23TestCase):
|
|||||||
bundle.add_from_pem('')
|
bundle.add_from_pem('')
|
||||||
self.assertEqual(len(bundle.certificates), bundle_prev_len)
|
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):
|
def test_non_ascii_crt_input(self):
|
||||||
bundle = gen_crt_bundle.CertificateBundle()
|
bundle = gen_crt_bundle.CertificateBundle()
|
||||||
|
|
||||||
|
|||||||
@@ -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-----
|
||||||
@@ -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_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.
|
* :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:
|
To enable the bundle when using ESP-TLS simply pass the function pointer to the bundle attach function:
|
||||||
|
|
||||||
.. code-block:: c
|
.. code-block:: c
|
||||||
|
|||||||
@@ -30,6 +30,10 @@ ESP x509 证书包 API 提供了一种简便的方法,帮助你安装自定义
|
|||||||
* :menuitem:`CONFIG_MBEDTLS_DEFAULT_CERTIFICATE_BUNDLE`:决定添加证书列表中的哪些证书。
|
* :menuitem:`CONFIG_MBEDTLS_DEFAULT_CERTIFICATE_BUNDLE`:决定添加证书列表中的哪些证书。
|
||||||
* :menuitem:`CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH`:指定要在证书包中嵌入的其他证书的路径。
|
* :menuitem:`CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH`:指定要在证书包中嵌入的其他证书的路径。
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
只有扩展名为 ``.pem`` 的 PEM 编码证书和扩展名为 ``.der`` 的 DER 编码证书会被解析。扩展名必须与文件的编码格式一致,例如保存为 ``.crt`` 的 PEM 编码证书不会被接受。如果 :ref:`CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH` 直接指向其他扩展名的文件,构建将失败;如果证书目录中存在此类文件,该文件会被跳过并打印警告。
|
||||||
|
|
||||||
要在使用 ESP-TLS 时启用证书包,将函数指针指向证书包的 attach 函数:
|
要在使用 ESP-TLS 时启用证书包,将函数指针指向证书包的 attach 函数:
|
||||||
|
|
||||||
.. code-block:: c
|
.. code-block:: c
|
||||||
|
|||||||
Reference in New Issue
Block a user