如何使用 TPM2 签署消息?

How to sign message with TPM2?

来自 MethodA()

首先我创建了模板,然后是签名密钥。然后使用 ContextSave(); 保存上下文并将其编组到文件。

来自 MethodB() :

我解组了文件,并做了 ContextLoad(); 这里它因完整性检查而失败。我做错了什么?

我这样创建了签名密钥:

var keyTemplate = new TpmPublic(TpmAlgId.Sha1,          // Name algorithm
     ObjectAttr.UserWithAuth | ObjectAttr.Sign |        // Signing key
     ObjectAttr.FixedParent | ObjectAttr.FixedTPM |     // Non-migratable 
     ObjectAttr.SensitiveDataOrigin,
     null,                                              // No policy
     new RsaParms(new SymDefObject(),
                  new SchemeRsassa(TpmAlgId.Sha1), 2048, 0),
     new Tpm2bPublicKeyRsa());


TpmHandle keyHandle = tpm[ownerAuth].CreatePrimary(
     TpmRh.Owner,                            // In the owner-hierarchy
     new SensitiveCreate(keyAuth, null),     // With this auth-value
     keyTemplate,                            // Describes key
     null,                                   // Extra data for creation ticket
     new PcrSelection[0],                    // Non-PCR-bound
     out keyPublic,                          // PubKey and attributes
     out creationData, out creationHash, out creationTicket);    // Not used here

编辑 1:

方法A();

        public static void MethodA()
    {
        try
        {
            Tpm2Device tpmDevice = new TcpTpmDevice(tpm_host, tpm_port);
            //Tpm2Device tpmDevice = new TbsDevice();
            tpmDevice.Connect();
            var tpm = new Tpm2(tpmDevice);
            if (tpmDevice is TcpTpmDevice)
            {
                tpmDevice.PowerCycle();
                tpm.Startup(Su.Clear);
            }


            // 
            // The TPM needs a template that describes the parameters of the key
            // or other object to be created.  The template below instructs the TPM 
            // to create a new 2048-bit non-migratable signing key.
            // 
            var keyTemplate = new TpmPublic(TpmAlgId.Sha1,                                  // Name algorithm
                                        ObjectAttr.UserWithAuth | ObjectAttr.Sign |     // Signing key
                                        ObjectAttr.FixedParent | ObjectAttr.FixedTPM | // Non-migratable 
                                        ObjectAttr.SensitiveDataOrigin,
                                        null,                                    // No policy
                                        new RsaParms(new SymDefObject(),
                                                     new SchemeRsassa(TpmAlgId.Sha1), 2048, 0),
                                        new Tpm2bPublicKeyRsa());



            //
            // AuthValue encapsulates an authorization value: essentially a byte-array.
            // OwnerAuth is the owner authorization value of the TPM-under-test.  We
            // assume that it (and other) auths are set to the default (null) value.
            // If running on a real TPM, which has been provisioned by Windows, this
            // value will be different. An administrator can retrieve the owner
            // authorization value from the registry.
            //
            //var ownerAuth = new AuthValue();

            // 
            // Authorization for the key we are about to create.
            // 
            var keyAuth = new byte[] { 1, 2, 3 };

            TpmPublic keyPublic;
            CreationData creationData;
            TkCreation creationTicket;
            byte[] creationHash;

            // 
            // Ask the TPM to create a new primary RSA signing key.
            // 
            TpmHandle keyHandle = tpm[ownerAuth].CreatePrimary(
                TpmRh.Owner,                            // In the owner-hierarchy
                new SensitiveCreate(keyAuth, null),     // With this auth-value
                keyTemplate,                            // Describes key
                null,                                   // Extra data for creation ticket
                new PcrSelection[0],                    // Non-PCR-bound
                out keyPublic,                          // PubKey and attributes
                out creationData, out creationHash, out creationTicket);    // Not used here



            // 
            // Print out text-versions of the public key just created
            // 
            //Console.WriteLine("New public key\n" + keyPublic.ToString());



            Context ctx = tpm.ContextSave(keyHandle);
            File.WriteAllBytes("key.bin", Marshaller.GetTpmRepresentation(ctx));






            // Clean up.
            tpm.FlushContext(keyHandle);
            tpm.Dispose();


        }
        catch (Exception e)
        {
            Console.WriteLine("Exception occurred: {0}", e.Message);
        }


    }

方法B():

public static void MethodB()
    {
       try
        {
            Tpm2Device tpmDevice = new TcpTpmDevice(tpm_host, tpm_port);
            //Tpm2Device tpmDevice = new TbsDevice();
            tpmDevice.Connect();
            var tpm = new Tpm2(tpmDevice);
            if (tpmDevice is TcpTpmDevice)
            {
                tpmDevice.PowerCycle();
                tpm.Startup(Su.Clear);
            }




            Context ctx2 = Marshaller.FromTpmRepresentation<Context>(File.ReadAllBytes("key.bin"));
            TpmHandle keyHandle = tpm.ContextLoad(ctx2); //integrity check fail

此代码同时出现在 MethodA()MethodB() 中:

if (tpmDevice is TcpTpmDevice)
{
    tpmDevice.PowerCycle();
    tpm.Startup(Su.Clear);
}

这是 TSS MSR 示例中的常见模式。它会检查您正在与之通话的 TPM 是否是模拟设备,如果是,则对其执行 Clear 命令,确保您从一个干净的平板开始。在 MethodA() 中这样做很好,但是在 MethodB() 中也这样做,你基本上是在撤销你在 MethodA() 中所做的事情:你刚刚创建的密钥被删除并且完整性检查因此失败了。