From 0ffb9311127d6477f9f7d00f4300cc1146a7ae65 Mon Sep 17 00:00:00 2001 From: chubtub <43381989+chubtub@users.noreply.github.com> Date: Wed, 24 Jan 2024 00:31:11 -0500 Subject: [PATCH 01/14] Add commandline support for output verbosity --verbose --- .../src/main/java/hirs/swid/utils/Commander.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java index 855d9625..fd98ff39 100644 --- a/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java @@ -30,6 +30,11 @@ public class Commander { description = "The file to write the RIM out to. " + "The RIM will be written to stdout by default.") private String outFile = ""; + @Parameter(names = {"--verbose"}, description = "Control output verbosity.") + private boolean verbose = false; + @Parameter(names = {"-v", "--verify "}, order = 3, + description = "Specify a RIM file to verify.") + private String verifyFile = ""; @Parameter(names = {"-t", "--truststore "}, order = 4, description = "The truststore to sign the base RIM created " + "or to validate the signed base RIM.") From 81575ee08a9451e9d02281809c9b6437467f7d90 Mon Sep 17 00:00:00 2001 From: chubtub <43381989+chubtub@users.noreply.github.com> Date: Thu, 25 Jan 2024 12:44:03 -0500 Subject: [PATCH 02/14] Print command line arguments only if --verbose option is given --- tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java | 8 ++++++-- .../src/main/java/hirs/swid/utils/Commander.java | 4 +--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java index 688be2fb..b252b8cc 100644 --- a/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java @@ -36,7 +36,9 @@ public class Main { } else { if (!commander.getVerifyFile().isEmpty()) { validator = new ReferenceManifestValidator(); - System.out.println(commander.toString()); + if (commander.isVerbose()) { + System.out.println(commander.toString()); + } String verifyFile = commander.getVerifyFile(); String rimel = commander.getRimEventLog(); String certificateFile = commander.getPublicCertificate(); @@ -60,7 +62,9 @@ public class Main { } } else { gateway = new SwidTagGateway(); - System.out.println(commander.toString()); + if (commander.isVerbose()) { + System.out.println(commander.toString()); + } String createType = commander.getCreateType().toUpperCase(); String attributesFile = commander.getAttributesFile(); String jksTruststoreFile = commander.getTruststoreFile(); diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java index fd98ff39..4307083d 100644 --- a/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java @@ -32,9 +32,6 @@ public class Commander { private String outFile = ""; @Parameter(names = {"--verbose"}, description = "Control output verbosity.") private boolean verbose = false; - @Parameter(names = {"-v", "--verify "}, order = 3, - description = "Specify a RIM file to verify.") - private String verifyFile = ""; @Parameter(names = {"-t", "--truststore "}, order = 4, description = "The truststore to sign the base RIM created " + "or to validate the signed base RIM.") @@ -76,6 +73,7 @@ public class Commander { public boolean isVersion() { return version; } + public boolean isVerbose() { return verbose; } public String getAttributesFile() { return attributesFile; } From eb77981e41adf30d8ae166ae9b69e3b5ce444b41 Mon Sep 17 00:00:00 2001 From: chubtub <43381989+chubtub@users.noreply.github.com> Date: Thu, 1 Feb 2024 17:46:44 -0500 Subject: [PATCH 03/14] Unknown options are caught and reported to the user instead of throwing an exception --- .../src/main/java/hirs/swid/Main.java | 32 +++++++++++++------ .../main/java/hirs/swid/utils/Commander.java | 6 ++++ 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java index b252b8cc..9b3a2acd 100644 --- a/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java @@ -21,8 +21,15 @@ public class Main { jc.parse(args); SwidTagGateway gateway; ReferenceManifestValidator validator; + List unknownOpts = commander.getUnknownOptions(); - if (commander.isHelp()) { + if (!unknownOpts.isEmpty()) { + StringBuilder sb = new StringBuilder("Unknown options encountered: "); + for (String opt : unknownOpts) { + sb.append(opt + ", "); + } + exitWithErrorCode(sb.substring(0,sb.lastIndexOf(","))); + } else if (commander.isHelp()) { jc.usage(); System.out.println(commander.printHelpExamples()); } else if (commander.isVersion()) { @@ -57,8 +64,7 @@ public class Main { } validator.validateSwidtagFile(verifyFile); } else { - System.out.println("Need a RIM file to validate!"); - System.exit(1); + exitWithErrorCode("A RIM file was not found for validation."); } } else { gateway = new SwidTagGateway(); @@ -92,13 +98,11 @@ public class Main { gateway.setDefaultCredentials(true); gateway.setJksTruststoreFile(SwidTagConstants.DEFAULT_KEYSTORE_FILE); } else { - System.out.println("A private key (-k) and public certificate (-p) " + + exitWithErrorCode("A private key (-k) and public certificate (-p) " + "are required, or the default key (-d) must be indicated."); - System.exit(1); } if (rimEventLog.isEmpty()) { - System.out.println("Error: a support RIM is required!"); - System.exit(1); + exitWithErrorCode("A support RIM is required."); } else { gateway.setRimEventLog(rimEventLog); } @@ -110,18 +114,28 @@ public class Main { gateway.setTimestampArgument(timestampArguments.get(1)); } } else { - System.exit(1); + exitWithErrorCode("The provided timestamp argument(s) " + + "is/are not valid."); } } gateway.generateSwidTag(commander.getOutFile()); break; default: - System.out.println("No create type given, nothing to do"); + exitWithErrorCode("No create type given, nothing to do"); } } } } + /** + * Use cases that exit with an error code are redirected here. + */ + private static void exitWithErrorCode(String errorMessage) { + //TODO: log errorMessage + System.out.println(errorMessage); + System.exit(1); + } + /** * This method parses the version number from the jar filename in the absence of * the VERSION file expected with an rpm installation. diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java index 4307083d..85adc77b 100644 --- a/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java @@ -12,6 +12,8 @@ import java.util.List; */ public class Commander { + @Parameter(description = "This parameter catches all unrecognized arguments.") + private List unknownOptions = new ArrayList<>(); @Parameter(names = {"-h", "--help"}, help = true, description = "Print this help text.") private boolean help; @Parameter(names = {"-c", "--create \"base\""}, order = 0, @@ -58,6 +60,10 @@ public class Commander { "\tRFC3339 [yyyy-MM-ddThh:mm:ssZ]\n\tRFC3852 ") private List timestampArguments = new ArrayList(2); + public List getUnknownOptions() { + return unknownOptions; + } + public boolean isHelp() { return help; } From d7823b6b0b0835b9d213444ebbd267c7bf32aa89 Mon Sep 17 00:00:00 2001 From: chubtub <43381989+chubtub@users.noreply.github.com> Date: Fri, 16 Feb 2024 11:23:02 -0500 Subject: [PATCH 04/14] Log error messages instead of printing to console --- .../tcg_rim_tool/src/main/java/hirs/swid/Main.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java index 9b3a2acd..ef0a04a5 100644 --- a/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java @@ -4,6 +4,7 @@ import hirs.swid.utils.Commander; import hirs.swid.utils.TimestampArgumentValidator; import hirs.utils.rim.ReferenceManifestValidator; import com.beust.jcommander.JCommander; +import lombok.extern.log4j.Log4j2; import java.io.File; import java.io.IOException; @@ -12,13 +13,17 @@ import java.nio.file.Paths; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; - +@Log4j2 public class Main { public static void main(String[] args) { Commander commander = new Commander(); JCommander jc = JCommander.newBuilder().addObject(commander).build(); - jc.parse(args); + try { + jc.parse(args); + } catch (Exception e) { + exitWithErrorCode(e.getMessage()); + } SwidTagGateway gateway; ReferenceManifestValidator validator; List unknownOpts = commander.getUnknownOptions(); @@ -121,7 +126,7 @@ public class Main { gateway.generateSwidTag(commander.getOutFile()); break; default: - exitWithErrorCode("No create type given, nothing to do"); + exitWithErrorCode("Create type not recognized."); } } } @@ -131,8 +136,7 @@ public class Main { * Use cases that exit with an error code are redirected here. */ private static void exitWithErrorCode(String errorMessage) { - //TODO: log errorMessage - System.out.println(errorMessage); + log.error(errorMessage); System.exit(1); } From 3fbc0e743cd4e15431eccddab0dfc41ed3dba7bc Mon Sep 17 00:00:00 2001 From: chubtub <43381989+chubtub@users.noreply.github.com> Date: Fri, 23 Feb 2024 02:02:19 -0500 Subject: [PATCH 05/14] Validate file arguments with FileArgumentValidator --- .../src/main/java/hirs/swid/Main.java | 12 ++----- .../main/java/hirs/swid/utils/Commander.java | 14 ++++---- .../swid/utils/FileArgumentValidator.java | 33 +++++++++++++++++++ 3 files changed, 43 insertions(+), 16 deletions(-) create mode 100644 tools/tcg_rim_tool/src/main/java/hirs/swid/utils/FileArgumentValidator.java diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java index ef0a04a5..72db696c 100644 --- a/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java @@ -55,22 +55,14 @@ public class Main { String rimel = commander.getRimEventLog(); String certificateFile = commander.getPublicCertificate(); String trustStore = commander.getTruststoreFile(); - if (!verifyFile.isEmpty()) { validator.setRim(verifyFile); - if (!rimel.isEmpty()) { - validator.setRimEventLog(rimel); - } - if (!trustStore.isEmpty()) { - validator.setTrustStoreFile(trustStore); - } + validator.setRimEventLog(rimel); + validator.setTrustStoreFile(trustStore); if (!certificateFile.isEmpty()) { System.out.println("A single cert cannot be used for verification. " + "The signing cert will be searched for in the trust store."); } validator.validateSwidtagFile(verifyFile); - } else { - exitWithErrorCode("A RIM file was not found for validation."); - } } else { gateway = new SwidTagGateway(); if (commander.isVerbose()) { diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java index 85adc77b..af2e7354 100644 --- a/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java @@ -19,12 +19,12 @@ public class Commander { @Parameter(names = {"-c", "--create \"base\""}, order = 0, description = "The type of RIM to create. A base RIM will be created by default.") private String createType = ""; - @Parameter(names = {"-v", "--verify "}, order = 3, + @Parameter(names = {"-v", "--verify "}, validateWith = FileArgumentValidator.class, description = "Specify a RIM file to verify.") private String verifyFile = ""; @Parameter(names = {"-V", "--version"}, description = "Output the current version.") private boolean version = false; - @Parameter(names = {"-a", "--attributes "}, order = 1, + @Parameter(names = {"-a", "--attributes "}, validateWith = FileArgumentValidator.class, description = "The configuration file holding attributes " + "to populate the base RIM with.") private String attributesFile = ""; @@ -34,14 +34,16 @@ public class Commander { private String outFile = ""; @Parameter(names = {"--verbose"}, description = "Control output verbosity.") private boolean verbose = false; - @Parameter(names = {"-t", "--truststore "}, order = 4, + @Parameter(names = {"-t", "--truststore "}, validateWith = FileArgumentValidator.class, description = "The truststore to sign the base RIM created " + "or to validate the signed base RIM.") private String truststoreFile = ""; - @Parameter(names = {"-k", "--privateKeyFile "}, order = 5, + @Parameter(names = {"-k", "--privateKeyFile "}, + validateWith = FileArgumentValidator.class, description = "The private key used to sign the base RIM created by this tool.") private String privateKeyFile = ""; - @Parameter(names = {"-p", "--publicCertificate "}, order = 6, + @Parameter(names = {"-p", "--publicCertificate "}, + validateWith = FileArgumentValidator.class, description = "The public key certificate to embed in the base RIM created by " + "this tool.") private String publicCertificate = ""; @@ -51,7 +53,7 @@ public class Commander { @Parameter(names = {"-d", "--default-key"}, order = 8, description = "Use default signing credentials.") private boolean defaultKey = false; - @Parameter(names = {"-l", "--rimel "}, order = 9, + @Parameter(names = {"-l", "--rimel "}, validateWith = FileArgumentValidator.class, description = "The TCG eventlog file to use as a support RIM.") private String rimEventLog = ""; @Parameter(names = {"--timestamp"}, order = 10, variableArity = true, diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/FileArgumentValidator.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/FileArgumentValidator.java new file mode 100644 index 00000000..a06c019b --- /dev/null +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/FileArgumentValidator.java @@ -0,0 +1,33 @@ +package hirs.swid.utils; + +import com.beust.jcommander.IParameterValidator; +import com.beust.jcommander.ParameterException; + +import java.io.File; +import lombok.extern.log4j.Log4j2; + +/** + * This class validates arguments that take a String path to a file. + * The file path is checked for null, and if the file is found it is checked + * for validity, emptiness, and read permissions. + */ +@Log4j2 +public class FileArgumentValidator implements IParameterValidator { + public void validate(String name, String value) throws ParameterException { + try { + File file = new File(value); + if (!file.isFile()) { + throw new ParameterException("Invalid file path: " + value + + ". Please verify file path."); + } + if (file.length() == 0) { + throw new ParameterException("File " + value + " is empty."); + } + } catch (NullPointerException e) { + throw new ParameterException("File path cannot be null: " + e.getMessage()); + } catch (SecurityException e) { + throw new ParameterException("Read access denied for " + value + + ", please verify permissions."); + } + } +} \ No newline at end of file From f6f1ab4ee7c40f4be5cae186ea08d645caaa6986 Mon Sep 17 00:00:00 2001 From: chubtub <43381989+chubtub@users.noreply.github.com> Date: Thu, 1 Feb 2024 10:15:54 -0500 Subject: [PATCH 06/14] Log an error instead of throwing an exception when a signing key cannot be located in the provided truststore --- .../java/hirs/utils/rim/ReferenceManifestValidator.java | 5 +++++ tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/HIRS_Utils/src/main/java/hirs/utils/rim/ReferenceManifestValidator.java b/HIRS_Utils/src/main/java/hirs/utils/rim/ReferenceManifestValidator.java index 112c7168..cb3fdd48 100644 --- a/HIRS_Utils/src/main/java/hirs/utils/rim/ReferenceManifestValidator.java +++ b/HIRS_Utils/src/main/java/hirs/utils/rim/ReferenceManifestValidator.java @@ -257,6 +257,11 @@ public class ReferenceManifestValidator { X509Certificate signingCert = null; try { signingCert = getCertFromTruststore(); + if (signingCert == null) { + log.error("Unable to locate the signing cert in the provided truststore " + + trustStoreFile); + return false; + } } catch (IOException e) { log.warn("Error while parsing signing cert from truststore: " + e.getMessage()); return false; diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java index 72db696c..77e5470e 100644 --- a/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java @@ -62,7 +62,11 @@ public class Main { System.out.println("A single cert cannot be used for verification. " + "The signing cert will be searched for in the trust store."); } - validator.validateSwidtagFile(verifyFile); + if (validator.validateSwidtagFile(verifyFile)) { + System.out.println("Successfully verified " + verifyFile); + } else { + System.out.println("Failed to verify " + verifyFile); + } } else { gateway = new SwidTagGateway(); if (commander.isVerbose()) { From 6b44c550dcebd20cad85517a3044817b2b2d7fb4 Mon Sep 17 00:00:00 2001 From: chubtub <43381989+chubtub@users.noreply.github.com> Date: Thu, 1 Feb 2024 15:11:55 -0500 Subject: [PATCH 07/14] Exit with an error code if validate fails --- tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java index 77e5470e..45066e8d 100644 --- a/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java @@ -66,6 +66,7 @@ public class Main { System.out.println("Successfully verified " + verifyFile); } else { System.out.println("Failed to verify " + verifyFile); + System.exit(1); } } else { gateway = new SwidTagGateway(); From adb1da93b44ec8eaa5169b3f4d66a7cd56a5d0e1 Mon Sep 17 00:00:00 2001 From: chubtub <43381989+chubtub@users.noreply.github.com> Date: Mon, 5 Feb 2024 14:33:31 -0500 Subject: [PATCH 08/14] Log an error instead of throwing an exception when the truststore is omitted --- .../utils/rim/ReferenceManifestValidator.java | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/HIRS_Utils/src/main/java/hirs/utils/rim/ReferenceManifestValidator.java b/HIRS_Utils/src/main/java/hirs/utils/rim/ReferenceManifestValidator.java index cb3fdd48..9b72fb8c 100644 --- a/HIRS_Utils/src/main/java/hirs/utils/rim/ReferenceManifestValidator.java +++ b/HIRS_Utils/src/main/java/hirs/utils/rim/ReferenceManifestValidator.java @@ -253,25 +253,26 @@ public class ReferenceManifestValidator { Element fileElement = (Element) rim.getElementsByTagName("File").item(0); if (trustStoreFile != null && !trustStoreFile.isEmpty()) { trustStore = parseCertificatesFromPem(trustStoreFile); + } else { + return failWithError("File <" + trustStoreFile + "> is empty; " + + "a valid, non-empty truststore file is required for validation."); } X509Certificate signingCert = null; try { signingCert = getCertFromTruststore(); if (signingCert == null) { - log.error("Unable to locate the signing cert in the provided truststore " - + trustStoreFile); - return false; + return failWithError("Unable to locate the signing cert in the provided " + + "truststore " + trustStoreFile); } } catch (IOException e) { - log.warn("Error while parsing signing cert from truststore: " + e.getMessage()); - return false; + return failWithError("Error while parsing signing cert from truststore: " + + e.getMessage()); } String subjectKeyIdentifier = ""; try { subjectKeyIdentifier = getCertificateSubjectKeyIdentifier(signingCert); } catch (IOException e) { - log.warn("Error while parsing certificate data: " + e.getMessage()); - return false; + return failWithError("Error while parsing certificate data: " + e.getMessage()); } return validateXmlSignature(signingCert.getPublicKey(), subjectKeyIdentifier, @@ -312,8 +313,7 @@ public class ReferenceManifestValidator { System.out.println("Support RIM hash verified!" + System.lineSeparator()); return true; } else { - System.out.println("Support RIM hash does not match Base RIM!" + System.lineSeparator()); - return false; + return failWithError("Support RIM hash does not match Base RIM!"); } } @@ -776,4 +776,14 @@ public class ReferenceManifestValidator { return doc; } + + /** + * This method logs an error message and returns a false to signal failed validation. + * @param errorMessage String description of what went wrong + * @return false to represent failed validation + */ + private boolean failWithError(String errorMessage) { + log.error(errorMessage); + return false; + } } From fbf3de2517af0f99932c63e22ebeb2c876365707 Mon Sep 17 00:00:00 2001 From: chubtub <43381989+chubtub@users.noreply.github.com> Date: Wed, 7 Feb 2024 09:10:41 -0500 Subject: [PATCH 09/14] Validate signature and validation arguments, and output appropriate error messages --- .../src/main/java/hirs/swid/Main.java | 31 +++++--- .../main/java/hirs/swid/SwidTagGateway.java | 1 - .../utils/CredentialArgumentValidator.java | 76 +++++++++++++++++++ 3 files changed, 97 insertions(+), 11 deletions(-) create mode 100644 tools/tcg_rim_tool/src/main/java/hirs/swid/utils/CredentialArgumentValidator.java diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java index 45066e8d..d25f779c 100644 --- a/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java @@ -1,6 +1,7 @@ package hirs.swid; import hirs.swid.utils.Commander; +import hirs.swid.utils.CredentialArgumentValidator; import hirs.swid.utils.TimestampArgumentValidator; import hirs.utils.rim.ReferenceManifestValidator; import com.beust.jcommander.JCommander; @@ -27,6 +28,7 @@ public class Main { SwidTagGateway gateway; ReferenceManifestValidator validator; List unknownOpts = commander.getUnknownOptions(); + CredentialArgumentValidator credValidator; if (!unknownOpts.isEmpty()) { StringBuilder sb = new StringBuilder("Unknown options encountered: "); @@ -53,7 +55,6 @@ public class Main { } String verifyFile = commander.getVerifyFile(); String rimel = commander.getRimEventLog(); - String certificateFile = commander.getPublicCertificate(); String trustStore = commander.getTruststoreFile(); validator.setRim(verifyFile); validator.setRimEventLog(rimel); @@ -61,6 +62,13 @@ public class Main { if (!certificateFile.isEmpty()) { System.out.println("A single cert cannot be used for verification. " + "The signing cert will be searched for in the trust store."); + credValidator = new CredentialArgumentValidator(trustStore, + "","", true); + if (credValidator.isValid()) { + validator.setTrustStoreFile(trustStore); + } else { + System.out.println(credValidator.getErrorMessage()); + System.exit(1); } if (validator.validateSwidtagFile(verifyFile)) { System.out.println("Successfully verified " + verifyFile); @@ -75,7 +83,6 @@ public class Main { } String createType = commander.getCreateType().toUpperCase(); String attributesFile = commander.getAttributesFile(); - String jksTruststoreFile = commander.getTruststoreFile(); String certificateFile = commander.getPublicCertificate(); String privateKeyFile = commander.getPrivateKeyFile(); boolean embeddedCert = commander.isEmbedded(); @@ -86,22 +93,26 @@ public class Main { if (!attributesFile.isEmpty()) { gateway.setAttributesFile(attributesFile); } - if (!jksTruststoreFile.isEmpty()) { + if (!rimEventLog.isEmpty()) { + gateway.setRimEventLog(rimEventLog); + } else { + System.out.println("Error: a support RIM is required!"); + System.exit(1); + } + credValidator = new CredentialArgumentValidator("" , + certificateFile, privateKeyFile, false); + if (defaultKey){ gateway.setDefaultCredentials(true); - gateway.setJksTruststoreFile(jksTruststoreFile); - } else if (!certificateFile.isEmpty() && !privateKeyFile.isEmpty()) { + gateway.setJksTruststoreFile(SwidTagConstants.DEFAULT_KEYSTORE_FILE); + } else if (credValidator.isValid()) { gateway.setDefaultCredentials(false); gateway.setPemCertificateFile(certificateFile); gateway.setPemPrivateKeyFile(privateKeyFile); if (embeddedCert) { gateway.setEmbeddedCert(true); } - } else if (defaultKey){ - gateway.setDefaultCredentials(true); - gateway.setJksTruststoreFile(SwidTagConstants.DEFAULT_KEYSTORE_FILE); } else { - exitWithErrorCode("A private key (-k) and public certificate (-p) " + - "are required, or the default key (-d) must be indicated."); + exitWithErrorCode(credValidator.getErrorMessage()); } if (rimEventLog.isEmpty()) { exitWithErrorCode("A support RIM is required."); diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagGateway.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagGateway.java index 0cd4ffc1..b9027b27 100644 --- a/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagGateway.java +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagGateway.java @@ -64,7 +64,6 @@ import java.security.InvalidAlgorithmParameterException; import java.security.KeyException; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; -import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.time.LocalDateTime; import java.util.ArrayList; diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/CredentialArgumentValidator.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/CredentialArgumentValidator.java new file mode 100644 index 00000000..1b162349 --- /dev/null +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/CredentialArgumentValidator.java @@ -0,0 +1,76 @@ +package hirs.swid.utils; + +public class CredentialArgumentValidator { + private String truststoreFile; + private String certificateFile; + private String privateKeyFile; + private String format; + private boolean isValidating; + private String errorMessage; + private static final String PEM = "PEM"; + + public CredentialArgumentValidator(String truststoreFile, + String certificateFile, + String privateKeyFile, + boolean isValidating) { + this.truststoreFile = truststoreFile; + this.certificateFile = certificateFile; + this.privateKeyFile = privateKeyFile; + this.isValidating = isValidating; + errorMessage = ""; + } + + /** + * Getter for format property + * + * @return string + */ + public String getFormat() { + return format; + } + + /** + * Getter for error message + * + * @return string + */ + public String getErrorMessage() { + return errorMessage; + } + + /** + * This method checks for the following valid configurations of input arguments: + * 1. + * 2. truststore only for validating (PEM format) + * 3. certificate + private key for signing (PEM format) + * 4. + * + * @return true if the above are found, false otherwise + */ + public boolean isValid() { + if (isValidating) { + if (!truststoreFile.isEmpty()) { + format = PEM; + return true; + } else { + errorMessage = "Validation requires a valid truststore file."; + return false; + } + } else { + if (!certificateFile.isEmpty() && !privateKeyFile.isEmpty()) { + format = PEM; + return true; + } else { + if (certificateFile.isEmpty()) { + errorMessage = "A public certificate must be specified by \'-p\' " + + "for signing operations."; + } + if (privateKeyFile.isEmpty()) { + errorMessage = "A private key must be specified by \'-k\' " + + "for signing operations."; + } + return false; + } + } + } +} From 808e05b71cccf5bfc5938c5d3b9e11efcd2c2796 Mon Sep 17 00:00:00 2001 From: chubtub <43381989+chubtub@users.noreply.github.com> Date: Wed, 7 Feb 2024 09:48:51 -0500 Subject: [PATCH 10/14] Do not assign the default attributes file in the absence of a user-provided argument --- tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java | 5 ++++- .../tcg_rim_tool/src/main/java/hirs/swid/SwidTagGateway.java | 2 +- .../src/main/java/hirs/swid/utils/Commander.java | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java index d25f779c..f02c001d 100644 --- a/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java @@ -92,11 +92,14 @@ public class Main { case "BASE": if (!attributesFile.isEmpty()) { gateway.setAttributesFile(attributesFile); + } else { + System.out.println("An attribute file is required."); + System.exit(1); } if (!rimEventLog.isEmpty()) { gateway.setRimEventLog(rimEventLog); } else { - System.out.println("Error: a support RIM is required!"); + System.out.println("A support RIM is required."); System.exit(1); } credValidator = new CredentialArgumentValidator("" , diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagGateway.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagGateway.java index b9027b27..aa9b23d2 100644 --- a/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagGateway.java +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagGateway.java @@ -99,7 +99,7 @@ public class SwidTagGateway { try { JAXBContext jaxbContext = JAXBContext.newInstance(SwidTagConstants.SCHEMA_PACKAGE); marshaller = jaxbContext.createMarshaller(); - attributesFile = SwidTagConstants.DEFAULT_ATTRIBUTES_FILE; + attributesFile = ""; defaultCredentials = true; pemCertificateFile = ""; embeddedCert = false; diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java index af2e7354..222756fe 100644 --- a/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java @@ -26,7 +26,7 @@ public class Commander { private boolean version = false; @Parameter(names = {"-a", "--attributes "}, validateWith = FileArgumentValidator.class, description = "The configuration file holding attributes " - + "to populate the base RIM with.") + + "to populate the base RIM with. An example file can be found in /opt/rimtool/data.") private String attributesFile = ""; @Parameter(names = {"-o", "--out "}, order = 2, description = "The file to write the RIM out to. " @@ -51,7 +51,7 @@ public class Commander { description = "Embed the provided certificate in the signed swidtag.") private boolean embedded = false; @Parameter(names = {"-d", "--default-key"}, order = 8, - description = "Use default signing credentials.") + description = "Use the JKS keystore installed in /opt/rimtool/data.") private boolean defaultKey = false; @Parameter(names = {"-l", "--rimel "}, validateWith = FileArgumentValidator.class, description = "The TCG eventlog file to use as a support RIM.") From 2554b7d4530df9577b0ec4215307fcb28f347266 Mon Sep 17 00:00:00 2001 From: chubtub <43381989+chubtub@users.noreply.github.com> Date: Wed, 7 Feb 2024 10:07:34 -0500 Subject: [PATCH 11/14] Clean up help menu --- .../main/java/hirs/swid/utils/Commander.java | 31 +++++++------------ 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java index 222756fe..b9630e17 100644 --- a/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java @@ -112,26 +112,17 @@ public class Commander { public String printHelpExamples() { StringBuilder sb = new StringBuilder(); - sb.append("Create a base RIM using the values in attributes.json; " + - "sign it with the default keystore; "); - sb.append("and write the data to base_rim.swidtag:\n\n"); - sb.append("\t\t-c base -a attributes.json -d -l support_rim.bin -o base_rim.swidtag" + - "\n\n\n"); - sb.append("Create a base RIM using the default attribute values; "); - sb.append("sign it using privateKey.pem; embed cert.pem in the signature block; "); - sb.append("and write the data to console output:\n\n"); - sb.append("\t\t-c base -l support_rim.bin -k privateKey.pem -p cert.pem -e\n\n\n"); - sb.append("Create a base RIM using the values in attributes.json; " + - "sign it with the default keystore; add a RFC3852 timestamp; "); - sb.append("and write the data to base_rim.swidtag:\n\n"); - sb.append("\t\t-c base -a attributes.json -d -l support_rim.bin " + - "--timestamp RFC3852 counterSignature.bin -o base_rim.swidtag\n\n\n"); - sb.append("Validate a base RIM using an external support RIM to override the "); - sb.append("payload file:\n\n"); - sb.append("\t\t-v base_rim.swidtag -l support_rim.bin\n\n\n"); - sb.append("Validate a base RIM with its own payload file and a PEM truststore "); - sb.append("containing the signing cert:\n\n"); - sb.append("\t\t-v base_rim.swidtag -t ca.crt\n\n\n"); + sb.append("Create a base RIM: use the values in attributes.json; "); + sb.append("add support_rim.bin to the payload; "); + sb.append("sign it using privateKey.pem and cert.pem; embed cert.pem in the signature; "); + sb.append("add a RFC3852 timestamp; and write the data to base_rim.swidtag:\n\n"); + sb.append("\t\t-c base -a attributes.json -l support_rim.bin " + + "-k privateKey.pem -p cert.pem -e --timestamp RFC3852 counterSignature.bin " + + "-o base_rim.swidtag\n\n\n"); + sb.append("Validate base_rim.swidtag: " + + "the payload is validated with support_rim.bin; " + + "and the signature is validated with ca.crt:\n\n"); + sb.append("\t\t-v base_rim.swidtag -l support_rim.bin -t ca.crt\n\n\n"); return sb.toString(); } From c6bbe00d0f25c42cfa8bcef786df242fd4e77256 Mon Sep 17 00:00:00 2001 From: chubtub <43381989+chubtub@users.noreply.github.com> Date: Fri, 23 Feb 2024 02:28:13 -0500 Subject: [PATCH 12/14] Merge changes from issue-692. Implement CredentialArgumentValidator. Remove extraneous code with the additions of exitWithErrorCode(String) and FileArgumentValidator. --- .../src/main/java/hirs/swid/Main.java | 51 ++++++------------- 1 file changed, 15 insertions(+), 36 deletions(-) diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java index f02c001d..baa8412f 100644 --- a/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java @@ -56,26 +56,20 @@ public class Main { String verifyFile = commander.getVerifyFile(); String rimel = commander.getRimEventLog(); String trustStore = commander.getTruststoreFile(); - validator.setRim(verifyFile); - validator.setRimEventLog(rimel); + validator.setRim(verifyFile); + validator.setRimEventLog(rimel); + credValidator = new CredentialArgumentValidator(trustStore, + "","", true); + if (credValidator.isValid()) { validator.setTrustStoreFile(trustStore); - if (!certificateFile.isEmpty()) { - System.out.println("A single cert cannot be used for verification. " + - "The signing cert will be searched for in the trust store."); - credValidator = new CredentialArgumentValidator(trustStore, - "","", true); - if (credValidator.isValid()) { - validator.setTrustStoreFile(trustStore); - } else { - System.out.println(credValidator.getErrorMessage()); - System.exit(1); - } - if (validator.validateSwidtagFile(verifyFile)) { - System.out.println("Successfully verified " + verifyFile); - } else { - System.out.println("Failed to verify " + verifyFile); - System.exit(1); - } + } else { + exitWithErrorCode(credValidator.getErrorMessage()); + } + if (validator.validateSwidtagFile(verifyFile)) { + System.out.println("Successfully verified " + verifyFile); + } else { + exitWithErrorCode("Failed to verify " + verifyFile); + } } else { gateway = new SwidTagGateway(); if (commander.isVerbose()) { @@ -90,18 +84,8 @@ public class Main { String rimEventLog = commander.getRimEventLog(); switch (createType) { case "BASE": - if (!attributesFile.isEmpty()) { - gateway.setAttributesFile(attributesFile); - } else { - System.out.println("An attribute file is required."); - System.exit(1); - } - if (!rimEventLog.isEmpty()) { - gateway.setRimEventLog(rimEventLog); - } else { - System.out.println("A support RIM is required."); - System.exit(1); - } + gateway.setAttributesFile(attributesFile); + gateway.setRimEventLog(rimEventLog); credValidator = new CredentialArgumentValidator("" , certificateFile, privateKeyFile, false); if (defaultKey){ @@ -117,11 +101,6 @@ public class Main { } else { exitWithErrorCode(credValidator.getErrorMessage()); } - if (rimEventLog.isEmpty()) { - exitWithErrorCode("A support RIM is required."); - } else { - gateway.setRimEventLog(rimEventLog); - } List timestampArguments = commander.getTimestampArguments(); if (timestampArguments.size() > 0) { if (new TimestampArgumentValidator(timestampArguments).isValid()) { From 63e184f9a36d1676f712f711c58e415f4032acf5 Mon Sep 17 00:00:00 2001 From: chubtub <43381989+chubtub@users.noreply.github.com> Date: Fri, 23 Feb 2024 14:48:06 -0500 Subject: [PATCH 13/14] Parse the signing cert authority key identifier during signing and place in --- .../src/main/java/hirs/swid/CredentialParser.java | 12 +++++++----- .../src/main/java/hirs/swid/SwidTagGateway.java | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/CredentialParser.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/CredentialParser.java index 013095d8..5ab6dbfa 100644 --- a/tools/tcg_rim_tool/src/main/java/hirs/swid/CredentialParser.java +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/CredentialParser.java @@ -278,17 +278,19 @@ public class CredentialParser { } /** - * This method returns the subjectKeyIdentifier from the local X509Certificate. - * @return the String representation of the subjectKeyIdentifier + * This method returns the authorityKeyIdentifier from the local X509Certificate. + * @return the String representation of the AKI * @throws IOException */ - public String getCertificateSubjectKeyIdentifier() throws IOException { + public String getCertificateAuthorityKeyIdentifier() throws IOException { String decodedValue = null; - byte[] extension = certificate.getExtensionValue(Extension.subjectKeyIdentifier.getId()); + byte[] extension = certificate.getExtensionValue(Extension.authorityKeyIdentifier.getId()); if (extension != null && extension.length > 0) { decodedValue = JcaX509ExtensionUtils.parseExtensionValue(extension).toString(); } - return decodedValue.substring(1);//Drop the # at the beginning of the string + //decodedValue above is of the form [[CONTEXT 0]#e0f...], parse out the extraneous chars + decodedValue = decodedValue.substring(decodedValue.indexOf("#")+1,decodedValue.length()-1); + return decodedValue; } /** diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagGateway.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagGateway.java index aa9b23d2..45b72476 100644 --- a/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagGateway.java +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagGateway.java @@ -646,7 +646,7 @@ public class SwidTagGateway { } } try { - KeyName keyName = kiFactory.newKeyName(cp.getCertificateSubjectKeyIdentifier()); + KeyName keyName = kiFactory.newKeyName(cp.getCertificateAuthorityKeyIdentifier()); keyInfoElements.add(keyName); } catch (IOException e) { System.out.println("Error while getting SKID: " + e.getMessage()); From 74ab262bc080aa92257bf72047cfe166c2e7ff6a Mon Sep 17 00:00:00 2001 From: chubtub <43381989+chubtub@users.noreply.github.com> Date: Thu, 29 Feb 2024 10:43:11 -0500 Subject: [PATCH 14/14] Revert "Parse the signing cert authority key identifier during signing and place in " This reverts commit 63e184f9a36d1676f712f711c58e415f4032acf5. --- .../src/main/java/hirs/swid/CredentialParser.java | 12 +++++------- .../src/main/java/hirs/swid/SwidTagGateway.java | 2 +- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/CredentialParser.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/CredentialParser.java index 5ab6dbfa..013095d8 100644 --- a/tools/tcg_rim_tool/src/main/java/hirs/swid/CredentialParser.java +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/CredentialParser.java @@ -278,19 +278,17 @@ public class CredentialParser { } /** - * This method returns the authorityKeyIdentifier from the local X509Certificate. - * @return the String representation of the AKI + * This method returns the subjectKeyIdentifier from the local X509Certificate. + * @return the String representation of the subjectKeyIdentifier * @throws IOException */ - public String getCertificateAuthorityKeyIdentifier() throws IOException { + public String getCertificateSubjectKeyIdentifier() throws IOException { String decodedValue = null; - byte[] extension = certificate.getExtensionValue(Extension.authorityKeyIdentifier.getId()); + byte[] extension = certificate.getExtensionValue(Extension.subjectKeyIdentifier.getId()); if (extension != null && extension.length > 0) { decodedValue = JcaX509ExtensionUtils.parseExtensionValue(extension).toString(); } - //decodedValue above is of the form [[CONTEXT 0]#e0f...], parse out the extraneous chars - decodedValue = decodedValue.substring(decodedValue.indexOf("#")+1,decodedValue.length()-1); - return decodedValue; + return decodedValue.substring(1);//Drop the # at the beginning of the string } /** diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagGateway.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagGateway.java index 45b72476..aa9b23d2 100644 --- a/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagGateway.java +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagGateway.java @@ -646,7 +646,7 @@ public class SwidTagGateway { } } try { - KeyName keyName = kiFactory.newKeyName(cp.getCertificateAuthorityKeyIdentifier()); + KeyName keyName = kiFactory.newKeyName(cp.getCertificateSubjectKeyIdentifier()); keyInfoElements.add(keyName); } catch (IOException e) { System.out.println("Error while getting SKID: " + e.getMessage());