Skip to content

Commit 5445278

Browse files
authored
Merge pull request #715 from nsacyber/v3_issue-661_updated
[#661] Output handling should be more concise
2 parents ac093d3 + 74ab262 commit 5445278

File tree

6 files changed

+215
-78
lines changed

6 files changed

+215
-78
lines changed

HIRS_Utils/src/main/java/hirs/utils/rim/ReferenceManifestValidator.java

+21-6
Original file line numberDiff line numberDiff line change
@@ -253,20 +253,26 @@ public boolean validateSwidtagFile(String path) {
253253
Element fileElement = (Element) rim.getElementsByTagName("File").item(0);
254254
if (trustStoreFile != null && !trustStoreFile.isEmpty()) {
255255
trustStore = parseCertificatesFromPem(trustStoreFile);
256+
} else {
257+
return failWithError("File <" + trustStoreFile + "> is empty; " +
258+
"a valid, non-empty truststore file is required for validation.");
256259
}
257260
X509Certificate signingCert = null;
258261
try {
259262
signingCert = getCertFromTruststore();
263+
if (signingCert == null) {
264+
return failWithError("Unable to locate the signing cert in the provided " +
265+
"truststore " + trustStoreFile);
266+
}
260267
} catch (IOException e) {
261-
log.warn("Error while parsing signing cert from truststore: " + e.getMessage());
262-
return false;
268+
return failWithError("Error while parsing signing cert from truststore: " +
269+
e.getMessage());
263270
}
264271
String subjectKeyIdentifier = "";
265272
try {
266273
subjectKeyIdentifier = getCertificateSubjectKeyIdentifier(signingCert);
267274
} catch (IOException e) {
268-
log.warn("Error while parsing certificate data: " + e.getMessage());
269-
return false;
275+
return failWithError("Error while parsing certificate data: " + e.getMessage());
270276
}
271277
return validateXmlSignature(signingCert.getPublicKey(),
272278
subjectKeyIdentifier,
@@ -307,8 +313,7 @@ private boolean validateFile(final Element file) {
307313
System.out.println("Support RIM hash verified!" + System.lineSeparator());
308314
return true;
309315
} else {
310-
System.out.println("Support RIM hash does not match Base RIM!" + System.lineSeparator());
311-
return false;
316+
return failWithError("Support RIM hash does not match Base RIM!");
312317
}
313318
}
314319

@@ -771,4 +776,14 @@ private Document removeXMLWhitespace(final StreamSource source) throws IOExcepti
771776

772777
return doc;
773778
}
779+
780+
/**
781+
* This method logs an error message and returns a false to signal failed validation.
782+
* @param errorMessage String description of what went wrong
783+
* @return false to represent failed validation
784+
*/
785+
private boolean failWithError(String errorMessage) {
786+
log.error(errorMessage);
787+
return false;
788+
}
774789
}

tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java

+54-42
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package hirs.swid;
22

33
import hirs.swid.utils.Commander;
4+
import hirs.swid.utils.CredentialArgumentValidator;
45
import hirs.swid.utils.TimestampArgumentValidator;
56
import hirs.utils.rim.ReferenceManifestValidator;
67
import com.beust.jcommander.JCommander;
8+
import lombok.extern.log4j.Log4j2;
79

810
import java.io.File;
911
import java.io.IOException;
@@ -12,17 +14,29 @@
1214
import java.util.List;
1315
import java.util.regex.Matcher;
1416
import java.util.regex.Pattern;
15-
17+
@Log4j2
1618
public class Main {
1719

1820
public static void main(String[] args) {
1921
Commander commander = new Commander();
2022
JCommander jc = JCommander.newBuilder().addObject(commander).build();
21-
jc.parse(args);
23+
try {
24+
jc.parse(args);
25+
} catch (Exception e) {
26+
exitWithErrorCode(e.getMessage());
27+
}
2228
SwidTagGateway gateway;
2329
ReferenceManifestValidator validator;
30+
List<String> unknownOpts = commander.getUnknownOptions();
31+
CredentialArgumentValidator credValidator;
2432

25-
if (commander.isHelp()) {
33+
if (!unknownOpts.isEmpty()) {
34+
StringBuilder sb = new StringBuilder("Unknown options encountered: ");
35+
for (String opt : unknownOpts) {
36+
sb.append(opt + ", ");
37+
}
38+
exitWithErrorCode(sb.substring(0,sb.lastIndexOf(",")));
39+
} else if (commander.isHelp()) {
2640
jc.usage();
2741
System.out.println(commander.printHelpExamples());
2842
} else if (commander.isVersion()) {
@@ -36,67 +50,56 @@ public static void main(String[] args) {
3650
} else {
3751
if (!commander.getVerifyFile().isEmpty()) {
3852
validator = new ReferenceManifestValidator();
39-
System.out.println(commander.toString());
53+
if (commander.isVerbose()) {
54+
System.out.println(commander.toString());
55+
}
4056
String verifyFile = commander.getVerifyFile();
4157
String rimel = commander.getRimEventLog();
42-
String certificateFile = commander.getPublicCertificate();
4358
String trustStore = commander.getTruststoreFile();
44-
if (!verifyFile.isEmpty()) {
45-
validator.setRim(verifyFile);
46-
if (!rimel.isEmpty()) {
47-
validator.setRimEventLog(rimel);
48-
}
49-
if (!trustStore.isEmpty()) {
50-
validator.setTrustStoreFile(trustStore);
51-
}
52-
if (!certificateFile.isEmpty()) {
53-
System.out.println("A single cert cannot be used for verification. " +
54-
"The signing cert will be searched for in the trust store.");
55-
}
56-
validator.validateSwidtagFile(verifyFile);
59+
validator.setRim(verifyFile);
60+
validator.setRimEventLog(rimel);
61+
credValidator = new CredentialArgumentValidator(trustStore,
62+
"","", true);
63+
if (credValidator.isValid()) {
64+
validator.setTrustStoreFile(trustStore);
5765
} else {
58-
System.out.println("Need a RIM file to validate!");
59-
System.exit(1);
66+
exitWithErrorCode(credValidator.getErrorMessage());
67+
}
68+
if (validator.validateSwidtagFile(verifyFile)) {
69+
System.out.println("Successfully verified " + verifyFile);
70+
} else {
71+
exitWithErrorCode("Failed to verify " + verifyFile);
6072
}
6173
} else {
6274
gateway = new SwidTagGateway();
63-
System.out.println(commander.toString());
75+
if (commander.isVerbose()) {
76+
System.out.println(commander.toString());
77+
}
6478
String createType = commander.getCreateType().toUpperCase();
6579
String attributesFile = commander.getAttributesFile();
66-
String jksTruststoreFile = commander.getTruststoreFile();
6780
String certificateFile = commander.getPublicCertificate();
6881
String privateKeyFile = commander.getPrivateKeyFile();
6982
boolean embeddedCert = commander.isEmbedded();
7083
boolean defaultKey = commander.isDefaultKey();
7184
String rimEventLog = commander.getRimEventLog();
7285
switch (createType) {
7386
case "BASE":
74-
if (!attributesFile.isEmpty()) {
75-
gateway.setAttributesFile(attributesFile);
76-
}
77-
if (!jksTruststoreFile.isEmpty()) {
87+
gateway.setAttributesFile(attributesFile);
88+
gateway.setRimEventLog(rimEventLog);
89+
credValidator = new CredentialArgumentValidator("" ,
90+
certificateFile, privateKeyFile, false);
91+
if (defaultKey){
7892
gateway.setDefaultCredentials(true);
79-
gateway.setJksTruststoreFile(jksTruststoreFile);
80-
} else if (!certificateFile.isEmpty() && !privateKeyFile.isEmpty()) {
93+
gateway.setJksTruststoreFile(SwidTagConstants.DEFAULT_KEYSTORE_FILE);
94+
} else if (credValidator.isValid()) {
8195
gateway.setDefaultCredentials(false);
8296
gateway.setPemCertificateFile(certificateFile);
8397
gateway.setPemPrivateKeyFile(privateKeyFile);
8498
if (embeddedCert) {
8599
gateway.setEmbeddedCert(true);
86100
}
87-
} else if (defaultKey){
88-
gateway.setDefaultCredentials(true);
89-
gateway.setJksTruststoreFile(SwidTagConstants.DEFAULT_KEYSTORE_FILE);
90-
} else {
91-
System.out.println("A private key (-k) and public certificate (-p) " +
92-
"are required, or the default key (-d) must be indicated.");
93-
System.exit(1);
94-
}
95-
if (rimEventLog.isEmpty()) {
96-
System.out.println("Error: a support RIM is required!");
97-
System.exit(1);
98101
} else {
99-
gateway.setRimEventLog(rimEventLog);
102+
exitWithErrorCode(credValidator.getErrorMessage());
100103
}
101104
List<String> timestampArguments = commander.getTimestampArguments();
102105
if (timestampArguments.size() > 0) {
@@ -106,18 +109,27 @@ public static void main(String[] args) {
106109
gateway.setTimestampArgument(timestampArguments.get(1));
107110
}
108111
} else {
109-
System.exit(1);
112+
exitWithErrorCode("The provided timestamp argument(s) " +
113+
"is/are not valid.");
110114
}
111115
}
112116
gateway.generateSwidTag(commander.getOutFile());
113117
break;
114118
default:
115-
System.out.println("No create type given, nothing to do");
119+
exitWithErrorCode("Create type not recognized.");
116120
}
117121
}
118122
}
119123
}
120124

125+
/**
126+
* Use cases that exit with an error code are redirected here.
127+
*/
128+
private static void exitWithErrorCode(String errorMessage) {
129+
log.error(errorMessage);
130+
System.exit(1);
131+
}
132+
121133
/**
122134
* This method parses the version number from the jar filename in the absence of
123135
* the VERSION file expected with an rpm installation.

tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagGateway.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@
6464
import java.security.KeyException;
6565
import java.security.NoSuchAlgorithmException;
6666
import java.security.PrivateKey;
67-
import java.security.cert.CertificateException;
6867
import java.security.cert.X509Certificate;
6968
import java.time.LocalDateTime;
7069
import java.util.ArrayList;
@@ -100,7 +99,7 @@ public SwidTagGateway() {
10099
try {
101100
JAXBContext jaxbContext = JAXBContext.newInstance(SwidTagConstants.SCHEMA_PACKAGE);
102101
marshaller = jaxbContext.createMarshaller();
103-
attributesFile = SwidTagConstants.DEFAULT_ATTRIBUTES_FILE;
102+
attributesFile = "";
104103
defaultCredentials = true;
105104
pemCertificateFile = "";
106105
embeddedCert = false;

tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java

+30-28
Original file line numberDiff line numberDiff line change
@@ -12,42 +12,48 @@
1212
*/
1313
public class Commander {
1414

15+
@Parameter(description = "This parameter catches all unrecognized arguments.")
16+
private List<String> unknownOptions = new ArrayList<>();
1517
@Parameter(names = {"-h", "--help"}, help = true, description = "Print this help text.")
1618
private boolean help;
1719
@Parameter(names = {"-c", "--create \"base\""}, order = 0,
1820
description = "The type of RIM to create. A base RIM will be created by default.")
1921
private String createType = "";
20-
@Parameter(names = {"-v", "--verify <path>"}, order = 3,
22+
@Parameter(names = {"-v", "--verify <path>"}, validateWith = FileArgumentValidator.class,
2123
description = "Specify a RIM file to verify.")
2224
private String verifyFile = "";
2325
@Parameter(names = {"-V", "--version"}, description = "Output the current version.")
2426
private boolean version = false;
25-
@Parameter(names = {"-a", "--attributes <path>"}, order = 1,
27+
@Parameter(names = {"-a", "--attributes <path>"}, validateWith = FileArgumentValidator.class,
2628
description = "The configuration file holding attributes "
27-
+ "to populate the base RIM with.")
29+
+ "to populate the base RIM with. An example file can be found in /opt/rimtool/data.")
2830
private String attributesFile = "";
2931
@Parameter(names = {"-o", "--out <path>"}, order = 2,
3032
description = "The file to write the RIM out to. "
3133
+ "The RIM will be written to stdout by default.")
3234
private String outFile = "";
33-
@Parameter(names = {"-t", "--truststore <path>"}, order = 4,
35+
@Parameter(names = {"--verbose"}, description = "Control output verbosity.")
36+
private boolean verbose = false;
37+
@Parameter(names = {"-t", "--truststore <path>"}, validateWith = FileArgumentValidator.class,
3438
description = "The truststore to sign the base RIM created "
3539
+ "or to validate the signed base RIM.")
3640
private String truststoreFile = "";
37-
@Parameter(names = {"-k", "--privateKeyFile <path>"}, order = 5,
41+
@Parameter(names = {"-k", "--privateKeyFile <path>"},
42+
validateWith = FileArgumentValidator.class,
3843
description = "The private key used to sign the base RIM created by this tool.")
3944
private String privateKeyFile = "";
40-
@Parameter(names = {"-p", "--publicCertificate <path>"}, order = 6,
45+
@Parameter(names = {"-p", "--publicCertificate <path>"},
46+
validateWith = FileArgumentValidator.class,
4147
description = "The public key certificate to embed in the base RIM created by "
4248
+ "this tool.")
4349
private String publicCertificate = "";
4450
@Parameter(names = {"-e", "--embed-cert"}, order = 7,
4551
description = "Embed the provided certificate in the signed swidtag.")
4652
private boolean embedded = false;
4753
@Parameter(names = {"-d", "--default-key"}, order = 8,
48-
description = "Use default signing credentials.")
54+
description = "Use the JKS keystore installed in /opt/rimtool/data.")
4955
private boolean defaultKey = false;
50-
@Parameter(names = {"-l", "--rimel <path>"}, order = 9,
56+
@Parameter(names = {"-l", "--rimel <path>"}, validateWith = FileArgumentValidator.class,
5157
description = "The TCG eventlog file to use as a support RIM.")
5258
private String rimEventLog = "";
5359
@Parameter(names = {"--timestamp"}, order = 10, variableArity = true,
@@ -56,6 +62,10 @@ public class Commander {
5662
"\tRFC3339 [yyyy-MM-ddThh:mm:ssZ]\n\tRFC3852 <counterSignature.bin>")
5763
private List<String> timestampArguments = new ArrayList<String>(2);
5864

65+
public List<String> getUnknownOptions() {
66+
return unknownOptions;
67+
}
68+
5969
public boolean isHelp() {
6070
return help;
6171
}
@@ -71,6 +81,7 @@ public String getVerifyFile() {
7181
public boolean isVersion() {
7282
return version;
7383
}
84+
public boolean isVerbose() { return verbose; }
7485
public String getAttributesFile() {
7586
return attributesFile;
7687
}
@@ -101,26 +112,17 @@ public List<String> getTimestampArguments() {
101112

102113
public String printHelpExamples() {
103114
StringBuilder sb = new StringBuilder();
104-
sb.append("Create a base RIM using the values in attributes.json; " +
105-
"sign it with the default keystore; ");
106-
sb.append("and write the data to base_rim.swidtag:\n\n");
107-
sb.append("\t\t-c base -a attributes.json -d -l support_rim.bin -o base_rim.swidtag" +
108-
"\n\n\n");
109-
sb.append("Create a base RIM using the default attribute values; ");
110-
sb.append("sign it using privateKey.pem; embed cert.pem in the signature block; ");
111-
sb.append("and write the data to console output:\n\n");
112-
sb.append("\t\t-c base -l support_rim.bin -k privateKey.pem -p cert.pem -e\n\n\n");
113-
sb.append("Create a base RIM using the values in attributes.json; " +
114-
"sign it with the default keystore; add a RFC3852 timestamp; ");
115-
sb.append("and write the data to base_rim.swidtag:\n\n");
116-
sb.append("\t\t-c base -a attributes.json -d -l support_rim.bin " +
117-
"--timestamp RFC3852 counterSignature.bin -o base_rim.swidtag\n\n\n");
118-
sb.append("Validate a base RIM using an external support RIM to override the ");
119-
sb.append("payload file:\n\n");
120-
sb.append("\t\t-v base_rim.swidtag -l support_rim.bin\n\n\n");
121-
sb.append("Validate a base RIM with its own payload file and a PEM truststore ");
122-
sb.append("containing the signing cert:\n\n");
123-
sb.append("\t\t-v base_rim.swidtag -t ca.crt\n\n\n");
115+
sb.append("Create a base RIM: use the values in attributes.json; ");
116+
sb.append("add support_rim.bin to the payload; ");
117+
sb.append("sign it using privateKey.pem and cert.pem; embed cert.pem in the signature; ");
118+
sb.append("add a RFC3852 timestamp; and write the data to base_rim.swidtag:\n\n");
119+
sb.append("\t\t-c base -a attributes.json -l support_rim.bin "
120+
+ "-k privateKey.pem -p cert.pem -e --timestamp RFC3852 counterSignature.bin "
121+
+ "-o base_rim.swidtag\n\n\n");
122+
sb.append("Validate base_rim.swidtag: "
123+
+ "the payload <File> is validated with support_rim.bin; "
124+
+ "and the signature is validated with ca.crt:\n\n");
125+
sb.append("\t\t-v base_rim.swidtag -l support_rim.bin -t ca.crt\n\n\n");
124126

125127
return sb.toString();
126128
}

0 commit comments

Comments
 (0)