Add option to explicitly embed a user-provided public key into signed swidtag.

This commit is contained in:
chubtub 2022-03-07 17:51:37 -05:00
parent 5088bf7107
commit 392821a2b9
3 changed files with 72 additions and 30 deletions

View File

@ -49,6 +49,7 @@ public class Main {
String jksTruststoreFile = commander.getTruststoreFile();
String certificateFile = commander.getPublicCertificate();
String privateKeyFile = commander.getPrivateKeyFile();
boolean embeddedCert = commander.isEmbedded();
boolean defaultKey = commander.isDefaultKey();
String rimEventLog = commander.getRimEventLog();
switch (createType) {
@ -63,6 +64,9 @@ public class Main {
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);

View File

@ -53,6 +53,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.cert.CertificateException;
@ -76,6 +77,7 @@ public class SwidTagGateway {
private String jksTruststoreFile;
private String pemPrivateKeyFile;
private String pemCertificateFile;
private boolean embeddedCert;
private String rimEventLog;
/**
@ -88,6 +90,7 @@ public class SwidTagGateway {
attributesFile = SwidTagConstants.DEFAULT_ATTRIBUTES_FILE;
defaultCredentials = true;
pemCertificateFile = "";
embeddedCert = false;
rimEventLog = "";
} catch (JAXBException e) {
System.out.println("Error initializing jaxbcontext: " + e.getMessage());
@ -99,7 +102,7 @@ public class SwidTagGateway {
*
* @param attributesFile
*/
public void setAttributesFile(String attributesFile) {
public void setAttributesFile(final String attributesFile) {
this.attributesFile = attributesFile;
}
@ -109,7 +112,7 @@ public class SwidTagGateway {
* @param defaultCredentials
* @return
*/
public void setDefaultCredentials(boolean defaultCredentials) {
public void setDefaultCredentials(final boolean defaultCredentials) {
this.defaultCredentials = defaultCredentials;
}
@ -118,7 +121,7 @@ public class SwidTagGateway {
*
* @param jksTruststoreFile
*/
public void setJksTruststoreFile(String jksTruststoreFile) {
public void setJksTruststoreFile(final String jksTruststoreFile) {
this.jksTruststoreFile = jksTruststoreFile;
}
@ -127,7 +130,7 @@ public class SwidTagGateway {
*
* @param pemPrivateKeyFile
*/
public void setPemPrivateKeyFile(String pemPrivateKeyFile) {
public void setPemPrivateKeyFile(final String pemPrivateKeyFile) {
this.pemPrivateKeyFile = pemPrivateKeyFile;
}
@ -136,16 +139,25 @@ public class SwidTagGateway {
*
* @param pemCertificateFile
*/
public void setPemCertificateFile(String pemCertificateFile) {
public void setPemCertificateFile(final String pemCertificateFile) {
this.pemCertificateFile = pemCertificateFile;
}
/**
* Setter to embed certificate file in signature block
*
* @param embeddedCert
*/
public void setEmbeddedCert(final boolean embeddedCert) {
this.embeddedCert = embeddedCert;
}
/**
* Setter for event log support RIM
*
* @param rimEventLog
*/
public void setRimEventLog(String rimEventLog) {
public void setRimEventLog(final String rimEventLog) {
this.rimEventLog = rimEventLog;
}
@ -210,7 +222,7 @@ public class SwidTagGateway {
*
* @param swidTag
*/
public void writeSwidTagFile(Document swidTag, String output) {
public void writeSwidTagFile(final Document swidTag, final String output) {
try {
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
@ -238,7 +250,7 @@ public class SwidTagGateway {
* @param jsonObject the Properties object containing parameters from file
* @return SoftwareIdentity object created from the properties
*/
private SoftwareIdentity createSwidTag(JsonObject jsonObject) {
private SoftwareIdentity createSwidTag(final JsonObject jsonObject) {
SoftwareIdentity swidTag = objectFactory.createSoftwareIdentity();
swidTag.setLang(SwidTagConstants.DEFAULT_ENGLISH);
String name = jsonObject.getString(SwidTagConstants.NAME, "");
@ -271,7 +283,7 @@ public class SwidTagGateway {
* @param jsonObject the Properties object containing parameters from file
* @return Entity object created from the properties
*/
private Entity createEntity(JsonObject jsonObject) {
private Entity createEntity(final JsonObject jsonObject) {
boolean isTagCreator = false;
Entity entity = objectFactory.createEntity();
String name = jsonObject.getString(SwidTagConstants.NAME, "");
@ -309,7 +321,7 @@ public class SwidTagGateway {
* @param jsonObject the Properties object containing parameters from file
* @return Link element created from the properties
*/
private Link createLink(JsonObject jsonObject) {
private Link createLink(final JsonObject jsonObject) {
Link link = objectFactory.createLink();
String href = jsonObject.getString(SwidTagConstants.HREF, "");
if (!href.isEmpty()) {
@ -330,7 +342,7 @@ public class SwidTagGateway {
* @param jsonObject the Properties object containing parameters from file
* @return the Meta element created from the properties
*/
private SoftwareMeta createSoftwareMeta(JsonObject jsonObject) {
private SoftwareMeta createSoftwareMeta(final JsonObject jsonObject) {
SoftwareMeta softwareMeta = objectFactory.createSoftwareMeta();
Map<QName, String> attributes = softwareMeta.getOtherAttributes();
addNonNullAttribute(attributes, SwidTagConstants._COLLOQUIAL_VERSION,
@ -379,7 +391,7 @@ public class SwidTagGateway {
* @param jsonObject the Properties object containing parameters from file
* @return the Payload object created
*/
private ResourceCollection createPayload(JsonObject jsonObject) {
private ResourceCollection createPayload(final JsonObject jsonObject) {
ResourceCollection payload = objectFactory.createResourceCollection();
Map<QName, String> attributes = payload.getOtherAttributes();
addNonNullAttribute(attributes, SwidTagConstants._N8060_ENVVARPREFIX,
@ -388,6 +400,12 @@ public class SwidTagGateway {
jsonObject.getString(SwidTagConstants._N8060_ENVVARSUFFIX.getLocalPart(), ""));
addNonNullAttribute(attributes, SwidTagConstants._N8060_PATHSEPARATOR,
jsonObject.getString(SwidTagConstants._N8060_PATHSEPARATOR.getLocalPart(), ""));
addNonNullAttribute(attributes, SwidTagConstants._SUPPORT_RIM_FORMAT,
jsonObject.getString(SwidTagConstants.SUPPORT_RIM_FORMAT, ""));
addNonNullAttribute(attributes, SwidTagConstants._SUPPORT_RIM_TYPE,
jsonObject.getString(SwidTagConstants.SUPPORT_RIM_TYPE, ""));
addNonNullAttribute(attributes, SwidTagConstants._SUPPORT_RIM_URI_GLOBAL,
jsonObject.getString(SwidTagConstants.SUPPORT_RIM_URI_GLOBAL, ""));
return payload;
}
@ -398,7 +416,7 @@ public class SwidTagGateway {
* @param jsonObject the Properties object containing parameters from file
* @return Directory object created from the properties
*/
private Directory createDirectory(JsonObject jsonObject) {
private Directory createDirectory(final JsonObject jsonObject) {
Directory directory = objectFactory.createDirectory();
directory.setName(jsonObject.getString(SwidTagConstants.NAME, ""));
Map<QName, String> attributes = directory.getOtherAttributes();
@ -428,7 +446,7 @@ public class SwidTagGateway {
* @param jsonObject the Properties object containing parameters from file
* @return File object created from the properties
*/
private hirs.swid.xjc.File createFile(JsonObject jsonObject) {
private hirs.swid.xjc.File createFile(final JsonObject jsonObject) {
hirs.swid.xjc.File file = objectFactory.createFile();
file.setName(jsonObject.getString(SwidTagConstants.NAME, ""));
Map<QName, String> attributes = file.getOtherAttributes();
@ -448,7 +466,8 @@ public class SwidTagGateway {
jsonObject.getString(SwidTagConstants.SUPPORT_RIM_URI_GLOBAL, ""));
File rimEventLogFile = new File(rimEventLog);
file.setSize(new BigInteger(Long.toString(rimEventLogFile.length())));
addNonNullAttribute(attributes, SwidTagConstants._SHA256_HASH, HashSwid.get256Hash(rimEventLog));
addNonNullAttribute(attributes, SwidTagConstants._SHA256_HASH,
HashSwid.get256Hash(rimEventLog));
return file;
}
@ -460,7 +479,8 @@ public class SwidTagGateway {
* @param key
* @param value
*/
private void addNonNullAttribute(Map<QName, String> attributes, QName key, String value) {
private void addNonNullAttribute(final Map<QName, String> attributes,
final QName key, String value) {
if (!value.isEmpty()) {
attributes.put(key, value);
}
@ -470,20 +490,23 @@ public class SwidTagGateway {
* This method signs a SoftwareIdentity with an xmldsig in compatibility mode.
* Current assumptions: digest method SHA256, signature method SHA256, enveloped signature
*/
private Document signXMLDocument(JAXBElement<SoftwareIdentity> swidTag) {
private Document signXMLDocument(final JAXBElement<SoftwareIdentity> swidTag) {
Document doc = null;
try {
XMLSignatureFactory sigFactory = XMLSignatureFactory.getInstance("DOM");
Reference reference = sigFactory.newReference(
"",
sigFactory.newDigestMethod(DigestMethod.SHA256, null),
Collections.singletonList(sigFactory.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null)),
Collections.singletonList(sigFactory.newTransform(Transform.ENVELOPED,
(TransformParameterSpec) null)),
null,
null
);
SignedInfo signedInfo = sigFactory.newSignedInfo(
sigFactory.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE, (C14NMethodParameterSpec) null),
sigFactory.newSignatureMethod(SwidTagConstants.SIGNATURE_ALGORITHM_RSA_SHA256, null),
sigFactory.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE,
(C14NMethodParameterSpec) null),
sigFactory.newSignatureMethod(SwidTagConstants.SIGNATURE_ALGORITHM_RSA_SHA256,
null),
Collections.singletonList(reference)
);
List<XMLStructure> keyInfoElements = new ArrayList<XMLStructure>();
@ -500,11 +523,15 @@ public class SwidTagGateway {
cp.parsePEMCredentials(pemCertificateFile, pemPrivateKeyFile);
X509Certificate certificate = cp.getCertificate();
privateKey = cp.getPrivateKey();
ArrayList<Object> x509Content = new ArrayList<Object>();
x509Content.add(certificate.getSubjectX500Principal().getName());
x509Content.add(certificate);
X509Data data = kiFactory.newX509Data(x509Content);
keyInfoElements.add(data);
if (embeddedCert) {
ArrayList<Object> x509Content = new ArrayList<Object>();
x509Content.add(certificate.getSubjectX500Principal().getName());
x509Content.add(certificate);
X509Data data = kiFactory.newX509Data(x509Content);
keyInfoElements.add(data);
} else {
keyInfoElements.add(kiFactory.newKeyValue(certificate.getPublicKey()));
}
}
KeyInfo keyinfo = kiFactory.newKeyInfo(keyInfoElements);
@ -526,6 +553,9 @@ public class SwidTagGateway {
System.out.println("Error marshaling signed swidtag: " + e.getMessage());
} catch (MarshalException | XMLSignatureException e) {
System.out.println("Error while signing SoftwareIdentity: " + e.getMessage());
} catch (KeyException e) {
System.out.println("Public key algorithm not recognized or supported: "
+ e.getMessage());
}
return doc;

View File

@ -36,10 +36,13 @@ public class Commander {
description = "The public key certificate to embed in the base RIM created by "
+ "this tool.")
private String publicCertificate = "";
@Parameter(names = {"-d", "--default-key"},
@Parameter(names = {"-e", "--embed-cert"}, order = 7,
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.")
private boolean defaultKey = false;
@Parameter(names = {"-l", "--rimel <path>"}, order = 7,
@Parameter(names = {"-l", "--rimel <path>"}, order = 9,
description = "The TCG eventlog file to use as a support RIM.")
private String rimEventLog = "";
@ -73,6 +76,8 @@ public class Commander {
return publicCertificate;
}
public boolean isEmbedded() { return embedded; }
public boolean isDefaultKey() { return defaultKey; }
public String getRimEventLog() { return rimEventLog; }
@ -82,11 +87,12 @@ public class Commander {
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("\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\n\n\n");
sb.append("\t\t-c base -l support_rim.bin -k privateKey.pem -p cert.pem -e\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");
@ -107,7 +113,9 @@ public class Commander {
} else if (!this.getPrivateKeyFile().isEmpty() &&
!this.getPublicCertificate().isEmpty()) {
sb.append("Private key file: " + this.getPrivateKeyFile() + System.lineSeparator());
sb.append("Public certificate: " + this.getPublicCertificate() + System.lineSeparator());
sb.append("Public certificate: " + this.getPublicCertificate()
+ System.lineSeparator());
sb.append("Embedded certificate: " + this.isEmbedded() + System.lineSeparator());
} else if (this.isDefaultKey()){
sb.append("Truststore file: default (" + SwidTagConstants.DEFAULT_KEYSTORE_FILE + ")"
+ System.lineSeparator());