awslabs / aws-crt-python

Python bindings for the AWS Common Runtime
Apache License 2.0
87 stars 43 forks source link

AWS_IO_FILE_VALIDATION_FAILURE when reading certificate or private key on Windows #589

Closed lautip closed 1 month ago

lautip commented 1 month ago

Describe the bug

When running a python script using certificates and private key to establish a connection with AWS IoT Core, using awsiot/mqtt_connection_builder.py, an exception "RuntimeError: 1038 (AWS_IO_FILE_VALIDATION_FAILURE): A file was read and the input did not match the expected value" is raised. This happens on Windows ONLY and works fine on OSX. the certificates are generated or download from a server during the script execution (not copied from OS to OS). Using other applications like Mosquitto on the same Windows machine, with the exact same files works fine. Also openssl and the windows Crypto Shell Extension can read the files content. The problem exists for in-memory variables (never stored on OS before reaching the 'mqtt_connection_builder.mtls_from_bytes') and filesystem-stored files (using 'mqtt_connection_builder.mtls_from_path').

Expected Behavior

The windows version should run in the same way as the OSX version: no exception raised.

Current Behavior

====================================================================== ERROR: test_01 (main.Test02IotClient.test_01) Test connection to IoT Core and JITP

Traceback (most recent call last): File "C:\Users\Administrator\tests\test_runner.py", line 215, in test_01 self.assertRaises(exceptions.AwsCrtError, self.iot_client.connect) File "C:\Users\Administrator\AppData\Local\Programs\Python\Python312\Lib\unittest\case.py", line 778, in assertRaises return context.handle('assertRaises', args, kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Administrator\AppData\Local\Programs\Python\Python312\Lib\unittest\case.py", line 238, in handle callable_obj(*args, kwargs) File "C:\Users\Administrator\tests\test_clients.py", line 503, in connect self.init_connection() File "C:\Users\Administrator\tests\test_clients.py", line 477, in init_connection self.mqtt_connection = mqtt_connection_builder.mtls_from_bytes( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Administrator\AppData\Local\Programs\Python\Python312\Lib\site-packages\awsiot\mqtt_connection_builder.py", line 294, in mtls_from_bytes return _builder(tls_ctx_options, kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Administrator\AppData\Local\Programs\Python\Python312\Lib\site-packages\awsiot\mqtt_connection_builder.py", line 231, in _builder tls_ctx = awscrt.io.ClientTlsContext(tls_ctx_options) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Administrator\AppData\Local\Programs\Python\Python312\Lib\site-packages\awscrt\io.py", line 596, in init self._binding = _awscrt.client_tls_ctx_new( ^^^^^^^^^^^^^^^^^^^^^^^^^^^ RuntimeError: 1038 (AWS_IO_FILE_VALIDATION_FAILURE): A file was read and the input did not match the expected value

Reproduction Steps

Hard to show how to reproduce since the certificates are provided by a server with private access and are only valid for a specific IoT Core endpoint. You can contact me if you need access, there is a sandbox version. I can also provide the test source code.

Possible Solution

No response

Additional Information/Context

awsiotsdk 1.22.0 crypto provided by cryptography 43.0.0

aws-crt-python version used

0.21.1

Python version used

3.12.5

Operating System and version

Windows Server 2022 (EC2 instance)

bretambrose commented 1 month ago

Try enabling CRT logging (https://github.com/awslabs/aws-crt-python/blob/main/awscrt/io.py#L28) and include the output from it.

In windows, that particular error is raised if

  1. utf-8 validation fails for the cert or key (https://github.com/awslabs/aws-c-io/blob/c345d77274db83c0c2e30331814093e7c84c45e2/source/windows/secure_channel_tls_handler.c#L2069-L2079)
  2. a Win32 call fails during the import process (various places in https://github.com/awslabs/aws-c-io/blob/c345d77274db83c0c2e30331814093e7c84c45e2/source/windows/windows_pki_utils.c)
lautip commented 1 month ago

OK - I found the "why". The key private bytes were exported in PKCS#8 format. Changing for PKCS#1 solved the issue. This related to the ticket: https://github.com/awslabs/aws-c-io/issues/260