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; }