/* * Microsoft Copyright, 2017 * Author: pengland */ using System; using System.Threading; using System.IO; using System.Diagnostics; namespace DICETest { /// /// This command line program performs certificate validation for DICE certificate chains. /// class Program { static void Main(string[] args) { // Usage: // -option c0 c1 c2... // Examples: // -chain AliasCert.PEM DeviceIDCrt.PEM R00tCrt.PEM // -chain AliasCert.PEM DeviceIDCrt.PEM // -csr DeviceIDCrt.PEM if (args.Length == 0 || args[1] == "?") { PrintHelp(); return; } if (args[0] == "-chain") { if (args.Length < 2) { ParmCountError("At least two certs in chain"); return; } var certs = GetCertNames(args, 1); if (certs == null) { Finish(); return; } CertChecker c = new CertChecker(); bool ok = c.SetCerts(certs); if (!ok) { Finish(); return; }; ok = c.CheckChain(); if (!ok) { Program.Print("One or more errors in certificate chain.", NotifyType.Error); } else { Program.Print("Certificates and certificate chain are valid.", NotifyType.Success); } Finish(); return; } if (args[0] == "-pop") { if (args.Length != 4) { ParmCountError("challenge and cert needed"); return; } var certs = GetCertNames(args, 2); if (certs == null) { Finish(); return; } CertChecker c = new CertChecker(); bool ok = c.SetCerts(certs); if (!ok) { Finish(); return; }; string challengeCn = args[1]; ok = c.CheckPopCert(challengeCn); if (!ok) { Program.Print("One or more errors in PoP cert.", NotifyType.Error); } else { Program.Print("PoP cert is good", NotifyType.Success); } Finish(); return; } if (args[0] == "-csr") { if (args.Length != 2) { ParmCountError("Just CSR.PEM needed"); return; } bool ok = CertChecker.CheckCSR(args[1]); if (!ok) { Program.Print("One or more errors in CSR.", NotifyType.Error); } { Program.Print("CSR is well formed.", NotifyType.Success); } Finish(); return; } Program.Print($"Option not recognized: {args[0]}", NotifyType.Error); PrintHelp(); Finish(); } /// /// Helper message writer for argument errors /// /// static void ParmCountError(string message) { Program.Print($"Wrong number of parameters: {message}", NotifyType.Error); PrintHelp(); Finish(); return; } /// /// Print the help and usage message /// static void PrintHelp() { string eol = "\r\n"; String nm = System.IO.Path.GetFileName(System.Reflection.Assembly.GetExecutingAssembly().Location); String s = $"Validates DICE certificates and certificate chains. Usage:{eol}" + $"{nm} -chain AliasCert.PEM DeviceIDCert.PEM ... Root.PEM - Checks the alias, deviceID, and vendor cert chain (DevID may be self-signed){eol}" + $"{nm} -csr CSR.PEM - Checks a CSR (certificate signing request){eol}" + $"{nm} -pop SubjectName RootPOP.PEM - Checks a proof-of-possession cert{eol}"; Print(s, NotifyType.Error); return; } /// /// Print helper with color highlighing /// /// /// internal static void Print(string s, NotifyType tp) { switch(tp) { case NotifyType.Error: Console.ForegroundColor = ConsoleColor.Red; break; case NotifyType.Warning: Console.ForegroundColor = ConsoleColor.Yellow; break; case NotifyType.Success: Console.ForegroundColor = ConsoleColor.Green; break; case NotifyType.Notify: Console.ResetColor(); break; } Debug.WriteLine(s); Console.WriteLine(s); Console.ResetColor(); return; } /// /// Get file names from the command line parameters, and check that the files exist. /// /// Args parameter passed to main() /// Optionally skip one or more parms /// Array of cert file names static string[] GetCertNames(string[] args, int startAt) { int numCerts = args.Length - startAt; string[] certNames = new string[numCerts]; bool ok = true; for (int j = 0; j < numCerts;j++) { string fileName = args[j+startAt]; if(!File.Exists(fileName)) { Print($"File not found: {args[j+startAt]}", NotifyType.Error); ok = false; } else { certNames[j] = fileName; } } if (!ok) return null; return certNames; } /// /// Clean up prior to exit /// static void Finish() { if (Debugger.IsAttached) { Thread.Sleep(3000); } } } /// /// Type of message /// internal enum NotifyType { Error, Warning, Success, Notify } }