0

I am trying to find a way to use a TPM to sign data using the private endorsement key (EK).

Using the samples from the TSS.MSR library in C#, I was able to assemble a small program:

private void ConnectTpmAndSign()
{
   //  ************************************************************
   //  Initializes the simulated TPM.
   //  ************************************************************

    const string DefaultSimulatorName = "127.0.0.1";
    const int DefaultSimulatorPort = 2321;

    var tpmDevice = new TcpTpmDevice(DefaultSimulatorName, DefaultSimulatorPort);
    tpmDevice.Connect();

    var tpm = new Tpm2(tpmDevice);

    tpmDevice.PowerCycle();
    tpm.Startup(Su.Clear);


    //  ****************************************************
    //  Extracts the public portion of the Endorsement key.
    //  *****************************************************

    var handleEK = new TpmHandle(0x81010001);
    TpmPublic EKpub = tpm._AllowErrors().ReadPublic(handleEK, out byte[] _, out byte[] _);

    if (!tpm._LastCommandSucceeded())
        EKpub = CreateEndorsementKey(tpm, handleEK);

    //  *********************************************************
    //  Signs the data with the TPM
    //  **********************************************************
    byte[] dataToSign = new byte[] { 0x01, 0x02, 0x03 };

    // --> Fails here <--
    var signature = tpm.Sign(handleEK, dataToSign, new SigSchemeRsassa(), TpmHashCheck.Null()) as SignatureRsassa;

    ...
}

private static TpmPublic CreateEndorsementKey(Tpm2 tpm2, TpmHandle tpmHandle)
{
    TpmHandle primary = tpm2.CreatePrimary(
                new TpmHandle(TpmHandle.RhEndorsement), 
                new SensitiveCreate(/*SecretPin, null*/),
                new TpmPublic(TpmAlgId.Sha256, ObjectAttr.FixedTPM | ObjectAttr.FixedParent | ObjectAttr.SensitiveDataOrigin | ObjectAttr.AdminWithPolicy | ObjectAttr.Restricted | ObjectAttr.Decrypt, new byte[32]
                {
                    (byte) 131,
                    (byte) 113,
                    (byte) 151,
                    (byte) 103,
                    (byte) 68,
                    (byte) 132,
                    (byte) 179,
                    (byte) 248,
                    (byte) 26,
                    (byte) 144,
                    (byte) 204,
                    (byte) 141,
                    (byte) 70,
                    (byte) 165,
                    (byte) 215,
                    (byte) 36,
                    (byte) 253,
                    (byte) 82,
                    (byte) 215,
                    (byte) 110,
                    (byte) 6,
                    (byte) 82,
                    (byte) 11,
                    (byte) 100,
                    (byte) 242,
                    (byte) 161,
                    (byte) 218,
                    (byte) 27,
                    (byte) 51,
                    (byte) 20,
                    (byte) 105,
                    (byte) 170
                }, (IPublicParmsUnion)new RsaParms(new SymDefObject(TpmAlgId.Aes, (ushort)128, TpmAlgId.Cfb), (IAsymSchemeUnion)new NullAsymScheme(), (ushort)2048, 0U), (IPublicIdUnion)new Tpm2bPublicKeyRsa(new byte[256])), Array.Empty<byte>(), Array.Empty<PcrSelection>(), out TpmPublic tpmPublic, out _, out _, out _);

     tpm2.EvictControl(TpmHandle.RhOwner, primary, tpmHandle);
     tpm2.FlushContext(primary);

     return tpmPublic;
}            

The program connects a TPM simulator, makes sure the EK is created and then, asks the TPM to sign data using the Endorsement Key. It fails with the following error:

Tpm2Lib.TpmException: 'Error {AuthUnavailable} was returned for command Sign.     
Details:     
[Code=TpmRc.AuthUnavailable],    
[RawCode=0x12F,303]    
[ErrorEntity=Unknown],     
[ParmNum=0]     
[ParmName=Unknown]'

Question

Can the EK be used to sign data and, if yes, what do I have to do to make it work?

Kzryzstof
  • 7,688
  • 10
  • 61
  • 108
  • 1
    No. EK is an encryption key, not a signing key. If you want to sign arbitrary data you need to create a signing key. – mnistic Jun 13 '19 at 23:12
  • The {AuthUnavailable} error from the code above is actually because you have to start an AuthSession with the policy (that byte array in the TpmPublic template). You need a PolicyTree, AuthSession, and call RunPolicy on that session. Then you would do tpm[session].Sign(), not tpm.Sign(), to attach that policy session. Only then you will get another error that the EK cannot be used for signing. – sun2sirius Nov 07 '20 at 01:32

1 Answers1

0

EK cannot be used to sign data. Only thing EK can pretty much be used for is for AIK enrollment.

Not sure about your use case. But if you are planning to use signing by EK as a proof of identity, you can instead use AIK for that.

  1. Generate AIK.
  2. Now encrypt some data with AIK public & ask TPM to decrypt it. Only a TPM that generated the AIK will be able to decrypt the data.
Water
  • 127
  • 8
  • But how do you prove that the AIK came from a real TPM and not a simulator? If AIK came from a simulator, it can perfectly load and decrypt data encrypted with its AIK, but it does not mean that the AIK was actually loaded under the trusted EK. There must be some protocol involving the EK decryption abilities to tie AIK to the EK. – sun2sirius Nov 07 '20 at 01:39
  • Yes, there is a protocol to tie the AIK to an EK. It's part of the [TCG specs](https://trustedcomputinggroup.org/wp-content/uploads/IWG_CMC_Profile_Cert_Enrollment_v1_r7.pdf) – Water Mar 25 '21 at 21:46