How do I encrypt my message with Microsofts TPM-Library in .net

Viewed 125

i want to encrypt and decrypt my messages with TPM. I use Microsofts TSS-Library. The documentation (including examples) can be found here: https://github.com/microsoft/TSS.MSR/tree/master/TSS.NET
Here is my CodeSnippet:

public byte[] encryptData(byte[] message)
    {
      TpmHandle handle = new TpmHandle();
      byte[] keyAuth = new byte[] { 1, 2, 3 };
      SigSchemeRsassa scheme = new SigSchemeRsassa(TpmAlgId.Rsa);
      byte[] label = Encoding.Unicode.GetBytes("Label");
      return Tpm[keyAuth].RsaEncrypt(handle, message, scheme,label);
    }

The error is:

Error {Value} was returned for command RsaEncrypt. Details: [Code=TpmRc.Value],[RawCode=0x184,388] [ErrorEntity=Handle], [ParmNum=1]

I modified my Code from my signature Method (found in Samples). I just added my own SignatureData-class which stores the output information from CreatePrimary(): (I have had the same error in this Method as well with a wrong authValue, but now it works)

public void Sign(string message)
    {
      AuthValue ownerAuth = new AuthValue();
      signatureData = new TpmSignatureData();           
      //Transform Message in byte-form
      signatureData.ByteMessage = Encoding.Unicode.GetBytes(message);
      //create keyTepmplate
      TpmPublic keyTemplate = new TpmPublic(TpmAlgId.Sha1, ObjectAttr.UserWithAuth | ObjectAttr.Sign |
        ObjectAttr.FixedParent | ObjectAttr.FixedTPM | ObjectAttr.SensitiveDataOrigin, null,                                    // No policy
        new RsaParms(new SymDefObject(), new SchemeRsassa(TpmAlgId.Sha1), 2048, 0), new Tpm2bPublicKeyRsa());
      byte[] keyAuth = new byte[] { 1, 2, 3 };

      #region Temporary Variables
      TpmPublic tpmPublic;
      CreationData creationData;
      byte[] creationHash;
      TkCreation creationTicket;
      #endregion
      //Create keyHandle based on keyTemplate
      TpmHandle keyHandl = 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 tpmPublic,                          // PubKey and attributes
                      out creationData, out creationHash, out creationTicket);    // Not used here
      //create Hash to be signed
      TpmHash digestToSign = TpmHash.FromData(TpmAlgId.Sha1, signatureData.ByteMessage);
      //Sign the hash-Value
      signatureData.signature = Tpm[keyAuth].Sign(keyHandl, digestToSign, null, TpmHashCheck.Null()) as SignatureRsassa;
    }

There is also another Method to Encryp it. You can also use the EncryptDecrypt-Method, but did not work for me as well. Am I missing something simple or do I need to change my Code completely. I guess my main problem is the TpmHandle. I am not sure how to handle with it. Any help would be great. Thanks in Advance.

1 Answers

In the meantime I found the solution myself. The problem was the handle. If I understand it correctly, you need to create a rsa-primary-handle and afterwards modify the handle. Here are the two Methods that are necessary:

public static TpmHandle CreateRsaPrimaryKey(Tpm2 tpm)
    {
      var sensCreate = new SensitiveCreate(new byte[] { 0xa, 0xb, 0xc }, null);
      TpmPublic parms = new TpmPublic(
                TpmAlgId.Sha1,
                ObjectAttr.Restricted | ObjectAttr.Decrypt | ObjectAttr.FixedParent | ObjectAttr.FixedTPM
                    | ObjectAttr.UserWithAuth | ObjectAttr.SensitiveDataOrigin,
                null,
                new RsaParms(
                    new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb),
                    new NullAsymScheme(),
                    2048,
                    0),
                new Tpm2bPublicKeyRsa());
      byte[] outsideInfo = Globs.GetRandomBytes(8);
      var creationPcr = new PcrSelection(TpmAlgId.Sha1, new uint[] { 0, 1, 2 });
      TpmPublic pubCreated;
      CreationData creationData;
      TkCreation creationTicket;
      byte[] creationHash;
      TpmHandle h = tpm.CreatePrimary(TpmRh.Owner, sensCreate, parms, outsideInfo, new PcrSelection[] { creationPcr },
                    out pubCreated, out creationData, out creationHash, out creationTicket);
      return h;
    }
    public static TpmHandle CreateSigningDecryptionKey(Tpm2 tpm, TpmHandle primHandle, out TpmPublic keyPublic)
    {
      TpmPublic keyInPublic = new TpmPublic(
          TpmAlgId.Sha1,
          ObjectAttr.Decrypt | ObjectAttr.Sign | ObjectAttr.FixedParent | ObjectAttr.FixedTPM
              | ObjectAttr.UserWithAuth | ObjectAttr.SensitiveDataOrigin,
          null,
          new RsaParms(
              new SymDefObject(),
              new NullAsymScheme(),
              2048, 0),
         new Tpm2bPublicKeyRsa());

      SensitiveCreate sensCreate = new SensitiveCreate(new byte[] { 1, 2, 3 }, null);
      CreationData keyCreationData;
      TkCreation creationTicket;
      byte[] creationHash;

      Console.WriteLine("Automatic authorization of a primary storage key.");

      //
      // An auth session is added automatically to authorize access to primHandle.
      //
      TpmPrivate keyPrivate = tpm.Create(primHandle,
                                         sensCreate,
                                         keyInPublic,
                                         null,
                                         new PcrSelection[0],
                                         out keyPublic,
                                         out keyCreationData,
                                         out creationHash,
                                         out creationTicket);

      TpmHandle keyHandle = null;

      Console.WriteLine("Strict mode.");

      //
      // Switch TPM object to the strict mode. (Note that this is a TSS.Net
      // specific piece of functionality, not a part of TPM 2.0 specification).
      //
      tpm._Behavior.Strict = true;

      //
      // No auth session is added automatically when TPM object is in strict mode.
      //
      tpm._ExpectError(TpmRc.AuthMissing)
         .Load(primHandle, keyPrivate, keyPublic);

      //
      // Now explicitly request an auth session of a desired type.
      // The actual auth value will be supplied by TSS.Net implicitly.
      //
      keyHandle = tpm[Auth.Default].Load(primHandle, keyPrivate, keyPublic);

      Console.WriteLine("Signing decryption key created.");

      //
      // Switch TPM object back to the normal mode.
      //
      tpm._Behavior.Strict = false;

      return keyHandle;
    }

I call the Methods in the constructor like this:

handle = CreateSigningDecryptionKey(Tpm, CreateRsaPrimaryKey(Tpm), out keyPublic);

Afterwards encryption and decryption is very easy.
Encryption:

return Tpm.RsaEncrypt(handle, data, new SchemeOaep(TpmAlgId.Sha1), null);

Decryption:

return Tpm.RsaDecrypt(handle, ciphertext, new SchemeOaep(TpmAlgId.Sha1), null);
Related