Azure / azure-iot-sdk-csharp

A C# SDK for connecting devices to Microsoft Azure IoT services
Other
466 stars 493 forks source link

Provisioning under Linux using SecurityProviderTpmHsm failed at ProvisioningDeviceClient.RegisterAsync() with TPM Exception #926

Closed MartinKutz closed 4 years ago

MartinKutz commented 5 years ago

Description of the issue:

We want to use TPM for provisioning under Linux with .netcore. The call RegisterAsync on the ProvisiongDeviceClient is failing with TpmException "Error {Binding} was returned for command ActivateCredential." The function GetEndorsementKey() on SecurityProviderTpmHsm for example is working.

As transport technology, HTTP is used (ProvisioningTransportHandlerHttp). The application is running in a docker container with mapped TPM device.

Exception details:

HTTP transport exception. (Tpm2Lib.TpmException) Error {Binding} was returned for command ActivateCredential.

[Code=TpmRc.Binding],[RawCode=0x2E5,741]
      [ErrorEntity=Parameter], [ParmNum=2]
      [ParmName=secret]
         at Tpm2Lib.Tpm2.ProcessError(TpmSt responseTag, UInt32 responseParamSize, TpmRc resultCode, TpmStructureBase inParms)
         at Tpm2Lib.Tpm2.DispatchMethod(TpmCc ordinal, TpmStructureBase inParms, Type expectedResponseType, TpmStructureBase& outParms, Int32 numInHandlesNotUsed, Int32 numOutHandlesNotUsed)
         at Tpm2Lib.Tpm2.ActivateCredential(TpmHandle activateHandle, TpmHandle keyHandle, IdObject credentialBlob, Byte[] secret)
         at Microsoft.Azure.Devices.Provisioning.Security.SecurityProviderTpmHsm.ActivateIdentityKey(Byte[] encryptedKey)
         at Microsoft.Azure.Devices.Provisioning.Client.Transport.ProvisioningSasBuilder.ExtractServiceAuthKey(SecurityProviderTpm securityProvider, String hostName, Byte[] activation)
         at Microsoft.Azure.Devices.Provisioning.Client.Transport.TpmDelegatingHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
         at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
         at Microsoft.Azure.Devices.Provisioning.Client.Transport.RuntimeRegistration.RegisterDeviceWithHttpMessagesAsync(String registrationId, String idScope, DeviceRegistration deviceRegistration, Nullable`1 forceRegistration, Dictionary`2 customHeaders, CancellationToken cancellationToken)
         at Microsoft.Azure.Devices.Provisioning.Client.Transport.RuntimeRegistrationExtensions.RegisterDeviceAsync(IRuntimeRegistration operations, String registrationId, String idScope, DeviceRegistration deviceRegistration, Nullable`1 forceRegistration, CancellationToken cancellationToken)
         at Microsoft.Azure.Devices.Provisioning.Client.Transport.ProvisioningTransportHandlerHttp.RegisterAsync(ProvisioningTransportRegisterMessage message, CancellationToken cancellationToken). Microsoft.Azure.Devices.Provisioning.Client.ProvisioningTransportException: HTTP transport exception ---> Tpm2Lib.TpmException: Error {Binding} was returned for command ActivateCredential.

Result of "tpm2_rc_decode 0x2E5":

error layer
  hex: 0x0
  identifier: TSS2_TPM_ERROR_LEVEL
  description: Error produced by the TPM
format 1 error code
  hex: 0x25
  identifier: TPM_RC_BINDING
  description: public and sensitive portions of an object are not cryptographically bound
parameter
  hex: 0x200
  identifier:  TPM_RC_2
  description:  (null)
amarochk commented 5 years ago

The error code means that a malformed EK is somehow used in the command. Either the public and private parts are from different keys, or the key bits are mangled. This looks like a TPM bug.

Three things to try are: 1) try a different device with the same setup; 2) try a different device with a different TPM type; 3) use the key handle that is passed as the second parameter to ActivateCredential() to encrypt and then decrypt a piece of data. If the decryption operation fails with TPM_RC_BINDING, then something is indeed wrong with the key (or the TPM).

bantoni commented 5 years ago

We tried different things, using the official example app for TPM based device provisioning provided by Microsoft.

  1. We booted Windows 10 on that device. Same error occurred. We used another device of the same type and the same error occurred.
  2. We tried out the app on a Windows 10 laptop (different device, different TPM). Provisioning was successful.
  3. I was not able do extract the key handle passed to ActivateCredentital(). I tried to use the handles listed as result of the tpm2_listpersistent handles to encrypt/decrypt data. This was not successful, but as we are not experienced with the tooling I assume that I did not issue the correct command in the right order.

The following handles are available after running the device provisioning example for the first time:

root@debian:~# tpm2_listpersistent -T device
2 persistent objects defined.

  0. Persistent handle: 0x81000001
  {
    Type: 0x1
    Hash algorithm(nameAlg): 0xb
    Attributes: 0x30472
  }

  1. Persistent handle: 0x81010001
  {
    Type: 0x1
    Hash algorithm(nameAlg): 0xb
    Attributes: 0x300b2
  }

Can you provide us an example how to encrypt/decrypt data on Debian? tpm2-tools are installed.

CIPop commented 5 years ago

@bantoni We have successfully tested with Ubuntu Server 16.04 running in Hyper-V with a virtual TPMv2. Two things to try out:

  1. Confirm that your setup works by using the sim docker container https://github.com/Azure/azure-iot-sdk-csharp/tree/master/e2e/test/prerequisites#tpm-simulator
  2. Update to the latest master and try again (might be fixed by #981 .
bantoni commented 5 years ago

@CIPop Tried out both of your proposals:

  1. The example is working with the sim docker container. I also checked with the TPM2 TSS simulator last week and it worked as expected.
  2. We cloned the SDK source and used it in the C# DPS TPM example. Got the same error as described in the initial post.

Beside of this we executed the TPM HSM integration tests provided by the TPM2 TSS library. All tests passed.

abhipsaMisra commented 4 years ago

If the sample and SDK work as expected with the TPM Simulator, but only fail on the actual device, it looks like a TPM bug and there isn't anything the SDK can do about that. I am closing this issue; feel free to re-open if there is an action item for the SDK.

az-iot-builder-01 commented 4 years ago

@MartinKutz, @amarochk, @bantoni, @CIPop, @abhipsaMisra, thank you for your contribution to our open-sourced project! Please help us improve by filling out this 2-minute customer satisfaction survey