aws / aws-iot-device-sdk-embedded-C

SDK for connecting to AWS IoT from a device using embedded C.
MIT License
986 stars 634 forks source link

in demo fleet provisioning with CSR the reconstructed mbedtls_pk_context is incorrect #1878

Closed giuspen closed 1 year ago

giuspen commented 1 year ago

There is a bug in the fleet provisioning demo with CSR.

The demo, in pkcs11_operations.c, generateKeyAndCsr is creating a private key via

        pkcs11Ret = generateKeyPairEC( p11Session,
                                       pPrivKeyLabel,
                                       pPubKeyLabel,
                                       &privKeyHandle,
                                       &pubKeyHandle );

but then since the API of C_GenerateKeyPair is not exposing the mbedtls_pk_context of the generated private key (only privKeyHandle), it is somehow reconstructing it in order to pass that to mbedtls_x509write_csr_set_key:

    mbedtls_pk_context privKey = { 0 };
    //...
            mbedtls_pk_init( &privKey );
    //...
            if( mbedtlsRet == 0 )
            {
                mbedtlsRet = extractEcPublicKey( p11Session, &xEcdsaContext, pubKeyHandle );
            }
    //...
            privKeyInfo.sign_func = privateKeySigningCallback;
            privKey.pk_info = &privKeyInfo;
            privKey.pk_ctx = &xEcdsaContext;
    //...
            mbedtls_x509write_csr_set_key( &req, &privKey );

But then if I save the private key out of this mbedtls_pk_context that will fail to be reused as a valid private key in another demo (like mqtt mutual auth)

        if( mbedtlsRet == 0 )
        {
            mbedtlsRet = mbedtls_pk_write_key_pem( &privKey, pPrivateKey, privKeyBufferLength );

            if( mbedtlsRet == 0 )
            {
                *pOutPrivKeyLength = strlen( pPrivateKey );
            }
        }

If instead I use directly the private key mbedtls_pk_context as generated inside of C_GenerateKeyPair it works fine for reuse in another demo such as the mqtt mutual auth.

diff --git a/source/portable/mbedtls/core_pkcs11_mbedtls.c b/source/portable/mbedtls/core_pkcs11_mbedtls.c
index 31354fc..cf76d96 100644
--- a/source/portable/mbedtls/core_pkcs11_mbedtls.c
+++ b/source/portable/mbedtls/core_pkcs11_mbedtls.c
@@ -5659,6 +5659,13 @@ CK_DECLARE_FUNCTION( CK_RV, C_GenerateKeyPair )( CK_SESSION_HANDLE hSession,
                         mbedtlsLowLevelCodeOrDefault( lMbedTLSResult ) ) );
             xResult = CKR_FUNCTION_FAILED;
         }
+        else
+        {
+            #define PRIV_KEY_BUFFER_LENGTH                         2048
+            char privatekey[ PRIV_KEY_BUFFER_LENGTH ];
+            int ret_val = mbedtls_pk_write_key_pem( &xCtx, privatekey, PRIV_KEY_BUFFER_LENGTH );
+            printf("\n%s\n", privatekey);
+        }
     }

     if( xResult == CKR_OK )

The rebuilding of the private key mbedtls_pk_context in the demo is clearly the issue

Example of difference in the keys

diff private.pem.key __private.pem.key
2c2
< MHcCAQEEIJ6nQjn+8UpEye4YBZG/gEkudbe5W0aAGu27+sHqCCNFoAoGCCqGSM49
---
> MHcCAQEEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAoGCCqGSM49
kar-rahul-aws commented 1 year ago

Hi @giuspen Thank you for reporting the issue. We will check it and get back to you.

ncohen17 commented 1 year ago

Hi @giuspen Is there a reason for using the CBOR library instead of the standard JSON library in the fleet provisioning demos ? I saw that both fleet provisioning demos use CBOR and I wanted to know the reasoning for that, is there an advantage ? or is it just a preference ?

BR

giuspen commented 1 year ago

Hi @ncohen17 it wasn't me who chose the JSON library, I merely created the other demo (KeysCert) starting from a duplication of this one (CSR) so I inherited a choice already done.

ncohen17 commented 1 year ago

Hi @giuspen OK, Thank you for your reply. Would you be able to tell me what is the main difference between the 2 fleet provisioning demos CSR and KeyCert ?

Also, just to confirm are both fleet provisioning demos using CBOR or JSON ?

BR

giuspen commented 1 year ago

Sure @ncohen17 the difference is that the KeysCert has the client private key generated on the server and sent to the client while the CSR has the client private key generated locally either from the demo or (as an option I proposed in my PR) already existing prior to running the demo. I haven't analysed the JSON library sorry was not of interest to me.

paulbartell commented 1 year ago

@giuspen: CorePKCS#11 is meant to simulate how one would use a Secure Element / Hardware Security Module which provides key storage in a secure manner where the private key is not exportable. The restrictions you are running into are intentional.

The corePKCS#11 PAL implementation for linux actually stores keys and certificates on the filesystem.

As I mentioned in PR #1877, you're welcome to contribute a fleet provisioning demo which does not use pkcs11 and instead calls mbedtls or openssl libcrypto APIs directly to store keys and certificates on the filesystem.

giuspen commented 1 year ago

I see thanks @paulbartell I've been clearly trying to hijack the demo