/// <summary> /// Validate the tester by emulating the actions of the TPM /// </summary> internal static void TestTester() { var random = new SecureRandom(); // Algorithms to test var algInfo = new[] { new { genner = (IAsymmetricCipherKeyPairGenerator) new ECKeyPairGenerator(), strength = 256, signingAlgorithm = "SHA256WITHECDSA" }, new { genner = (IAsymmetricCipherKeyPairGenerator) new RsaKeyPairGenerator(), strength = 2048, signingAlgorithm = "SHA256WITHRSAENCRYPTION" } }; foreach (var keyType in algInfo) { // Make a two keys of the specified algorithm var keyGenerationParameters = new KeyGenerationParameters(random, keyType.strength); keyType.genner.Init(keyGenerationParameters); var signingKey = keyType.genner.GenerateKeyPair(); var toBeCertifiedKeyPair = keyType.genner.GenerateKeyPair(); // Make the partial certificate that is input to the TPM PartialCertificate partialCert = MakeExemplarPartialCert(); // Simulate the actions of the TPM. This returns both the full and partial (AddedTo) certificate // The full certitificate is just for debugging var certTuple /*(CompleteCertificate, AddedTo)*/ = SimulateX509Certify(partialCert, toBeCertifiedKeyPair.Public, signingKey.Private, keyType.signingAlgorithm); X509Certificate CompleteCertificate = certTuple.Item1; AddedToCertificate AddedTo = certTuple.Item2; // Is the full certificate OK (it certainly should be) CompleteCertificate.Verify(signingKey.Public); // Debugging help... DebugPrintHex(CompleteCertificate.GetEncoded(), "ActualCert"); // When using TPM2_CertifyX509() the TPM does not return the whole certificate: it returns the // parts of the certificate that were not originally provided in partialCertificate in a data // structure called AddedTo, as well as the signature. The caller/TSS has to recosntruct // the full certificate. var signature = CompleteCertificate.GetSignature(); var finishedCert = AssembleCertificate(partialCert, AddedTo, signature); DebugPrintHex(finishedCert.GetEncoded(), "AssembledCert"); // sanity check that we can parse a DER encoded AddedTo (this is what the TPM will return.) var addedToBytes = AddedTo.GetDerEncoded(); var reconstructedAddedTo = AddedToCertificate.FromDerEncoding(addedToBytes); AssertByteArraysTheSame(addedToBytes, reconstructedAddedTo.ToAsn1Object().GetDerEncoded()); // Sanity AssertByteArraysTheSame(CompleteCertificate.GetEncoded(), finishedCert.GetEncoded()); // and more sanity finishedCert.Verify(signingKey.Public); } return; }
void TestCertifyX509_1(Tpm2 tpm, TestContext testCtx) { testCtx.ReportParams("Test phase: TestCertifyX509_1"); var policy = new PolicyTree(TpmAlgId.Sha256); policy.SetPolicyRoot(new TpmPolicyCommand(TpmCc.CertifyX509)); var keyTemplate = new TpmPublic( TpmAlgId.Sha256, ObjectAttr.Restricted | ObjectAttr.Sign | ObjectAttr.FixedParent | ObjectAttr.FixedTPM | ObjectAttr.UserWithAuth | ObjectAttr.AdminWithPolicy | ObjectAttr.SensitiveDataOrigin, policy.GetPolicyDigest(), new RsaParms(new SymDefObject(), new SchemeRsassa(TpmAlgId.Sha256), 2048, 0), new Tpm2bPublicKeyRsa() ); // Make two keys TpmPublic certifyingKeyPub, keyToBeCertifiedPub; TpmHandle hCertifyingKey = Substrate.CreatePrimary(tpm, keyTemplate, out certifyingKeyPub); TpmHandle hKeyToBeCertified = Substrate.CreatePrimary(tpm, keyTemplate, out keyToBeCertifiedPub); var partialCert = CertifyX509Support.MakeExemplarPartialCert(); var partialCertBytes = partialCert.GetDerEncoded(); // If you want to paste in your own hex put it here and s //var partialCertBytes = Globs.ByteArrayFromHex("01020304"); AuthSession sess = tpm.StartAuthSessionEx(TpmSe.Policy, TpmAlgId.Sha256); sess.RunPolicy(tpm, policy); // I used this to test that the auth is OK. Of course you need to change the PolicyCommandCode above //var attestInfo = tpm[sess].Certify(hKeyToBeCertified, hCertifyingKey, new byte[0], new NullSigScheme(), out var legacySignature); byte[] tbsHash; ISignatureUnion signature; byte[] addedTo = tpm[sess].CertifyX509(hKeyToBeCertified, hCertifyingKey, new byte[0], new NullSigScheme(), partialCertBytes, out tbsHash, out signature); var addedToCert = AddedToCertificate.FromDerEncoding(addedTo); var returnedCert = CertifyX509Support.AssembleCertificate(partialCert, addedToCert, ((SignatureRsa)signature).GetTpmRepresentation()); // Does the expected hash match the returned hash? var tbsBytes = returnedCert.GetTbsCertificate(); var expectedTbsHash = TpmHash.FromData(TpmAlgId.Sha256, tbsBytes); Debug.Assert(Globs.ArraysAreEqual(expectedTbsHash.HashData, tbsHash)); // If you get this far we can check the cert is properly signed but we'll need to do a // bit of TPM<->Bouncy Castle data type conversion. tpm.FlushContext(hCertifyingKey); tpm.FlushContext(hKeyToBeCertified); } // TestCertifyX509_1
void TestCertifyX509Impl(Tpm2 tpm, TestContext testCtx, TpmPublic subjectTemplate, TpmPublic sigKeyTemplate, PolicyTree policy, string testLabel) { var partialCert = X509Helpers.MakePartialCert(subjectTemplate); var partialCertBytes = partialCert.GetDerEncoded(); // If you want to paste in your own hex put it here and s //var partialCertBytes = Globs.ByteArrayFromHex("01020304"); // Certify RSA with RSA TpmPublic certifyingKeyPub, keyToBeCertifiedPub; TpmHandle hSigKey = Substrate.CreatePrimary(tpm, sigKeyTemplate, out certifyingKeyPub); TpmHandle hSubjectKey = Substrate.CreatePrimary(tpm, subjectTemplate, out keyToBeCertifiedPub); AuthSession sess = tpm.StartAuthSessionEx(TpmSe.Policy, TpmAlgId.Sha256); sess.RunPolicy(tpm, policy); ISignatureUnion sig; byte[] tbsHash; byte[] addedTo = tpm[sess].CertifyX509(hSubjectKey, hSigKey, null, new NullSigScheme(), partialCertBytes, out tbsHash, out sig); tpm.FlushContext(sess); tpm.FlushContext(hSubjectKey); var addedToCert = AddedToCertificate.FromDerEncoding(addedTo); X509Certificate returnedCert = X509Helpers.AssembleCertificate(partialCert, addedToCert, sig is SignatureRsa ? ((SignatureRsa)sig).GetTpmRepresentation() : ((SignatureEcc)sig).GetTpmRepresentation()); // Does the expected hash match the returned hash? var tbsBytes = returnedCert.GetTbsCertificate(); var expectedTbsHash = TpmHash.FromData(TpmAlgId.Sha256, tbsBytes); Debug.Assert(Globs.ArraysAreEqual(expectedTbsHash.HashData, tbsHash)); // Is the cert properly signed? if (TpmHelper.GetScheme(sigKeyTemplate).GetUnionSelector() != TpmAlgId.Rsapss) { // Software crypto layer does not support PSS bool sigOk = certifyingKeyPub.VerifySignatureOverHash(tbsHash, sig); if (sigKeyTemplate.type == TpmAlgId.Ecc) { #if !__NETCOREAPP2__ // No ECC in .Net Core testCtx.Assert("Sign" + testLabel, sigOk); #endif } else { testCtx.Assert("Sign" + testLabel, sigOk); } } tpm.VerifySignature(hSigKey, tbsHash, sig); tpm.FlushContext(hSigKey); }