internal void MakeCertChain(DeviceBundle bundle, int chainLen, int fwidSeed)
        {
            var aliasCert = bundle.AliasCert;

            DateTime now = DateTime.Now;

            byte[] fwid = Helpers.HashData(new byte[1] {
                0
            }, 0, 1);
            const int keyStrength           = 256;
            CryptoApiRandomGenerator rg     = new CryptoApiRandomGenerator();
            SecureRandom             random = new SecureRandom(rg);
            KeyGenerationParameters  keyGenerationParameters = new KeyGenerationParameters(random, keyStrength);
            var keyPairGenerator = new ECKeyPairGenerator();

            keyPairGenerator.Init(keyGenerationParameters);

            // Starting the loop we have a (not yet certified) DeviceID public key
            // and the Issuer of the Alias Cert (which we want to be the DevID-cert DN.)

            List <X509Certificate> certChain = new List <X509Certificate>();

            var lastCertIssuer = aliasCert.IssuerDN;
            var lastPubKey     = bundle.DeviceIDPublic;;
            AsymmetricCipherKeyPair lastKeyPair = null;

            for (int j = 0; j < chainLen; j++)
            {
                bool rootCert   = j == chainLen - 1;
                bool lastButOne = j == chainLen - 2;
                AsymmetricCipherKeyPair caKey = keyPairGenerator.GenerateKeyPair();

                X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
                certGen.SetSerialNumber(new BigInteger(new byte[] { 1, 2, 3, 4, 5 }));
                var issuerDn = lastButOne ?
                               new X509Name($"CN=Vendor Root CA O=MSR_TEST, C=US") :
                               new X509Name($"CN=Vendor Intermediate CA {j}, O=MSR_TEST, C=US");
                if (rootCert)
                {
                    issuerDn = lastCertIssuer;
                }

                certGen.SetIssuerDN(issuerDn);
                certGen.SetSubjectDN(lastCertIssuer);
                certGen.SetNotBefore(now);
                certGen.SetNotAfter(now + new TimeSpan(365 * 10, 0, 0, 0, 0));
                certGen.SetPublicKey(lastPubKey);



                int pathLengthConstraint = j + 1;
                certGen.AddExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(pathLengthConstraint));
                certGen.AddExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.KeyCertSign));
                X509Certificate certificate;

                if (rootCert)
                {
                    ISignatureFactory signatureFactory = new Asn1SignatureFactory("SHA256WITHECDSA", lastKeyPair.Private, random);
                    certificate = certGen.Generate(signatureFactory);
                }
                else
                {
                    ISignatureFactory signatureFactory = new Asn1SignatureFactory("SHA256WITHECDSA", caKey.Private, random);
                    certificate = certGen.Generate(signatureFactory);
                }


                lastCertIssuer = certificate.IssuerDN;
                lastPubKey     = caKey.Public;
                lastKeyPair    = caKey;
                certChain.Add(certificate);
            }


            // Chain including root, but not AliasCert.  NOTE, finishes with CA
            Helpers.WritePEMObjects(ToPath(Program.DeviceCertChain), certChain.ToArray());
            // cert chain including AliasCert (alias cert is first.  CA is last)
            JoinFiles(Program.AliasCert, Program.DeviceCertChain, Program.DeviceCertChainIncAlias);

            // just the device CA (for the server)
            Helpers.WritePEMObject(ToPath("DeviceCA.pem"), certChain.Last());


            // Now make some certs for the server to use
            string serverCaName = "CN=Server CA, C=US, O=MSR_TEST";
            string serverName   = "CN=Server Cert, C=US, O=MSR_TEST";

            var serverCA   = MakeCertInternal(serverCaName, serverCaName, true, null, null, 1);
            var serverCert = MakeCertInternal(serverCaName, serverName, false, serverCA.KeyPair, null, 0);

            Helpers.WritePEMObject(ToPath(Program.ServerCA), serverCA.Certificate);
            Helpers.WritePEMObjects(ToPath(Program.ServerChain), new Object[] { serverCA.Certificate, serverCert.Certificate });
            //Helpers.WritePEMObject(ToPath("T0_ServerCAKey.PEM", serverCA.KeyPair);
            Helpers.WritePEMObject(ToPath(Program.ServerCert), serverCert.Certificate);
            Helpers.WritePEMObject(ToPath(Program.ServerKey), serverCert.KeyPair);

            // OpenSSL needs a file with the Device CA AND the server CA
            JoinFiles(Program.DeviceCertChain, Program.ServerCA, Program.DeviceCertChainAndServerCA);

            // OpenSSL test scripts -

            // print a cert
            // openssl x509 -text -in T0_ServerCA.pem

            // Just verify the client chain
            // openssl verify -purpose sslclient -CAfile T0_DeviceCertChain.PEM DeviceAliasCert.PEM

            // Just verify the server chain
            // openssl verify -purpose sslserver -CAfile T0_ServerCA.PEM T0_ServerCert.PEM


            // openssl s_client -connect localhost: 5556 - cert T0_AliasCert.PEM - key T0_AliasKey.PEM - CAfile T0_DeviceCertChainAndServerCA.PEM
            // openssl s_client -connect localhost:5556 -cert T0_AliasCert.PEM -key T0_AliasKey.PEM -CAfile T0_DeviceCertChain.PEM
            // openssl s_server -cert T0_ServerCert.PEM -key T0_ServerKey.PEM -CAfile T0_DeviceCertChainAndServerCA.PEM -status_verbose -verify 10 -rev -accept 5556

            return;
        }