예제 #1
0
        /// <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;
        }
예제 #2
0
        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
예제 #3
0
        /// <summary>
        /// To be called after the TPM has returned the addedTo part of the certificate and the signature.  Assembles
        /// partialCert, addedTo, and the signature to form  an actual X.509 certificate encapsulated in a Bouncy Castle
        /// X509Certificate
        /// </summary>
        /// <param name="partialCert"></param>
        /// <param name="addedToCertificate"></param>
        /// <param name="signature"></param>
        /// <returns></returns>
        internal static X509Certificate AssembleCertificate(
            PartialCertificate partialCert, AddedToCertificate addedToCertificate,
            byte[] signatureBytes)
        {
            Debug.Assert(addedToCertificate.Version.ToString() == "2");
            var signature = new DerBitString(signatureBytes);
            var sigAlgID  = partialCert.SigAlgID ?? addedToCertificate.SigAlgID;

            // Assemble TBS.  Start with a vector which we will later convert to a sequence
            Asn1EncodableVector tbsContents = new Asn1EncodableVector();

            tbsContents.Add(new DerTaggedObject(0, new DerInteger(BigInteger.ValueOf(2))));
            tbsContents.Add(addedToCertificate.SerialNumber);
            tbsContents.Add(sigAlgID);
            tbsContents.Add(partialCert.Issuer);
            tbsContents.Add(new CertificateValidity(partialCert.NotBefore, partialCert.NotAfter));
            tbsContents.Add(partialCert.Subject);
            tbsContents.Add(addedToCertificate.SubjectPublicKeyInfo);
            // Add optional components
            if (partialCert.IssuerUniqueId != null)
            {
                tbsContents.Add(new DerTaggedObject(false, 1, new DerBitString(partialCert.IssuerUniqueId)));
            }
            if (partialCert.SubjectUniqueId != null)
            {
                tbsContents.Add(new DerTaggedObject(false, 2, new DerBitString(partialCert.SubjectUniqueId)));
            }
            if (partialCert.Extensions != null)
            {
                tbsContents.Add(new DerTaggedObject(3, partialCert.Extensions.ToAsn1Object()));
            }

            // Convert the vector to an ASN SEQUENCE
            var tbsCertificate = new DerSequence(tbsContents);

            // assemble the certificate.  Start with the components as a vector
            Asn1EncodableVector certContents = new Asn1EncodableVector();

            certContents.Add(tbsCertificate);
            certContents.Add(sigAlgID);
            certContents.Add(signature);

            // Convert to a SEQUENCE.  certSequence will contain the DER encoded certificate
            var certSequence = new DerSequence(certContents);

            // Convert to a first-class BC X509Certificate
            var certBytes = certSequence.GetEncoded();
            var cert      = new X509CertificateParser().ReadCertificate(certSequence.GetEncoded());

            // and return it
            return(cert);
        }
예제 #4
0
        /// <summary>
        /// Parses the AddedTo data that is returned from TPM2_CertifyX509()
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static AddedToCertificate FromDerEncoding(byte[] data)
        {
            var ret           = new AddedToCertificate();
            var sequence      = (DerSequence)DerSequence.FromByteArray(data);
            var taggedVersion = (DerTaggedObject)(sequence[0]);

            Debug.Assert(taggedVersion.TagNo == 0);
            ret.Version              = (DerInteger)taggedVersion.GetObject();
            ret.SerialNumber         = (DerInteger)sequence[1];
            ret.Signature            = AlgorithmIdentifier.GetInstance(sequence[2]);
            ret.SubjectPublicKeyInfo = SubjectPublicKeyInfo.GetInstance(sequence[3]);
            return(ret);
        }
예제 #5
0
        SimulateX509Certify(PartialCertificate partialCert, AsymmetricKeyParameter publicKeyToCertify,
                            AsymmetricKeyParameter signingKey, string signingAlgorithm)
        {
            // We can simulate ECDSA/SHA256 and RSA/SHA256

            ISignatureFactory   signatureFactory;
            DerObjectIdentifier sigAlgOid;

            if (signingKey is ECPrivateKeyParameters)
            {
                sigAlgOid = X9ObjectIdentifiers.ECDsaWithSha256;
            }
            else
            {
                sigAlgOid = PkcsObjectIdentifiers.Sha256WithRsaEncryption;
            }


            //signatureFactory = new Asn1SignatureFactory(sigAlgOid.ToString(), signingKey);
            signatureFactory = new Asn1SignatureFactory(sigAlgOid.ToString(), signingKey);

            // Make the certificate
            var certGenerator = new X509V3CertificateGenerator();

            certGenerator.SetIssuerDN(partialCert.Issuer);
            certGenerator.SetSubjectDN(partialCert.Subject);
            certGenerator.SetSerialNumber(BigInteger.ValueOf(1));
            certGenerator.SetNotBefore(partialCert.NotBefore);
            certGenerator.SetNotAfter(partialCert.NotAfter);
            certGenerator.SetPublicKey(publicKeyToCertify);
            if (partialCert.SubjectUniqueId != null)
            {
                certGenerator.SetSubjectUniqueID(ByteArrayToBoolArray(partialCert.SubjectUniqueId));
            }
            if (partialCert.IssuerUniqueId != null)
            {
                certGenerator.SetIssuerUniqueID(ByteArrayToBoolArray(partialCert.IssuerUniqueId));
            }

            // process the extensions.  Note that this will not preserve the order
            var extensions = partialCert.Extensions;

            if (extensions != null)
            {
                foreach (var critExtOid in extensions.GetCriticalExtensionOids())
                {
                    certGenerator.AddExtension(critExtOid.ToString(), true, extensions.GetExtension(critExtOid).GetParsedValue());
                }
                foreach (var nonCritExtOid in extensions.GetNonCriticalExtensionOids())
                {
                    certGenerator.AddExtension(nonCritExtOid.ToString(), false, extensions.GetExtension(nonCritExtOid).GetParsedValue());
                }
            }

            // and sign to make the cert
            var cert = certGenerator.Generate(signatureFactory);

            // take things apart again for addedToCert
            var subjectPubKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKeyToCertify);

            // get the exact bytes for the signature algorithm
            var tbsSequence = ((DerSequence)DerSequence.FromByteArray(cert.GetTbsCertificate()));
            var sigAlgBytes = tbsSequence[2];

            AddedToCertificate addedTo = new AddedToCertificate()
            {
                Version              = new DerInteger(BigInteger.ValueOf(cert.Version)),
                SerialNumber         = new DerInteger(cert.SerialNumber),
                Signature            = AlgorithmIdentifier.GetInstance(sigAlgBytes),
                SubjectPublicKeyInfo = subjectPubKeyInfo
            };

            return(System.ValueTuple.Create(cert, addedTo));
        }
예제 #6
0
        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);
        }