mirror of
https://github.com/nsacyber/HIRS.git
synced 2025-01-31 08:25:39 +00:00
Merge pull request #506 from nsacyber/issue-493
[#493] Consolidated timestamp parameter
This commit is contained in:
commit
d18dc60adb
@ -2,8 +2,9 @@ package hirs.swid;
|
|||||||
|
|
||||||
import hirs.swid.utils.Commander;
|
import hirs.swid.utils.Commander;
|
||||||
import com.beust.jcommander.JCommander;
|
import com.beust.jcommander.JCommander;
|
||||||
|
import hirs.swid.utils.TimestampArgumentValidator;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.util.List;
|
||||||
|
|
||||||
public class Main {
|
public class Main {
|
||||||
|
|
||||||
@ -81,6 +82,17 @@ public class Main {
|
|||||||
} else {
|
} else {
|
||||||
gateway.setRimEventLog(rimEventLog);
|
gateway.setRimEventLog(rimEventLog);
|
||||||
}
|
}
|
||||||
|
List<String> timestampArguments = commander.getTimestampArguments();
|
||||||
|
if (timestampArguments.size() > 0) {
|
||||||
|
if (new TimestampArgumentValidator(timestampArguments).isValid()) {
|
||||||
|
gateway.setTimestampFormat(timestampArguments.get(0));
|
||||||
|
if (timestampArguments.size() > 1) {
|
||||||
|
gateway.setTimestampArgument(timestampArguments.get(1));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
gateway.generateSwidTag(commander.getOutFile());
|
gateway.generateSwidTag(commander.getOutFile());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -71,82 +71,68 @@ public class SwidTagConstants {
|
|||||||
public static final String TPM_PCR_ASSERTION = "TPM_PCR_Assertion";
|
public static final String TPM_PCR_ASSERTION = "TPM_PCR_Assertion";
|
||||||
public static final String SUPPORT_RIM_FORMAT_MISSING = "supportRIMFormat missing";
|
public static final String SUPPORT_RIM_FORMAT_MISSING = "supportRIMFormat missing";
|
||||||
public static final String SUPPORT_RIM_URI_GLOBAL = "supportRIMURIGlobal";
|
public static final String SUPPORT_RIM_URI_GLOBAL = "supportRIMURIGlobal";
|
||||||
|
public static final String DATETIME = "dateTime";
|
||||||
|
|
||||||
|
public static final String NIST_NS = "http://csrc.nist.gov/ns/swid/2015-extensions/1.0";
|
||||||
|
public static final String TCG_NS = "https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model";
|
||||||
|
public static final String RFC3852_NS = "https://www.ietf.org/rfc/rfc3852.txt";
|
||||||
|
public static final String RFC3339_NS = "https://www.ietf.org/rfc/rfc3339.txt";
|
||||||
|
|
||||||
|
public static final String N8060_PFX = "n8060";
|
||||||
|
public static final String RIM_PFX = "rim";
|
||||||
|
public static final String RFC3852_PFX = "rcf3852";
|
||||||
|
public static final String RFC3339_PFX = "rcf3339";
|
||||||
|
|
||||||
public static final QName _SHA256_HASH = new QName(
|
public static final QName _SHA256_HASH = new QName(
|
||||||
"http://www.w3.org/2001/04/xmlenc#sha256",
|
"http://www.w3.org/2001/04/xmlenc#sha256", HASH, "SHA256");
|
||||||
"hash", "SHA256");
|
|
||||||
public static final QName _COLLOQUIAL_VERSION = new QName(
|
public static final QName _COLLOQUIAL_VERSION = new QName(
|
||||||
"http://csrc.nist.gov/ns/swid/2015-extensions/1.0",
|
NIST_NS, COLLOQUIAL_VERSION, N8060_PFX);
|
||||||
"colloquialVersion", "n8060");
|
|
||||||
public static final QName _EDITION = new QName(
|
public static final QName _EDITION = new QName(
|
||||||
"http://csrc.nist.gov/ns/swid/2015-extensions/1.0",
|
NIST_NS, EDITION, N8060_PFX);
|
||||||
"edition", "n8060");
|
|
||||||
public static final QName _PRODUCT = new QName(
|
public static final QName _PRODUCT = new QName(
|
||||||
"http://csrc.nist.gov/ns/swid/2015-extensions/1.0",
|
NIST_NS, PRODUCT, N8060_PFX);
|
||||||
"product", "n8060");
|
|
||||||
public static final QName _REVISION = new QName(
|
public static final QName _REVISION = new QName(
|
||||||
"http://csrc.nist.gov/ns/swid/2015-extensions/1.0",
|
NIST_NS, REVISION, N8060_PFX);
|
||||||
"revision", "n8060");
|
|
||||||
public static final QName _PAYLOAD_TYPE = new QName(
|
public static final QName _PAYLOAD_TYPE = new QName(
|
||||||
"https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model",
|
TCG_NS, PAYLOAD_TYPE, RIM_PFX);
|
||||||
"PayloadType", "rim");
|
|
||||||
public static final QName _PLATFORM_MANUFACTURER_STR = new QName(
|
public static final QName _PLATFORM_MANUFACTURER_STR = new QName(
|
||||||
"https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model",
|
TCG_NS, PLATFORM_MANUFACTURER_STR, RIM_PFX);
|
||||||
"platformManufacturerStr", "rim");
|
|
||||||
public static final QName _PLATFORM_MANUFACTURER_ID = new QName(
|
public static final QName _PLATFORM_MANUFACTURER_ID = new QName(
|
||||||
"https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model",
|
TCG_NS, PLATFORM_MANUFACTURER_ID, RIM_PFX);
|
||||||
"platformManufacturerId", "rim");
|
|
||||||
public static final QName _PLATFORM_MODEL = new QName(
|
public static final QName _PLATFORM_MODEL = new QName(
|
||||||
"https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model",
|
TCG_NS, PLATFORM_MODEL, RIM_PFX);
|
||||||
"platformModel", "rim");
|
|
||||||
public static final QName _PLATFORM_VERSION = new QName(
|
public static final QName _PLATFORM_VERSION = new QName(
|
||||||
"https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model",
|
TCG_NS, PLATFORM_VERSION, RIM_PFX);
|
||||||
"platformVersion", "rim");
|
|
||||||
public static final QName _FIRMWARE_MANUFACTURER_STR = new QName(
|
public static final QName _FIRMWARE_MANUFACTURER_STR = new QName(
|
||||||
"https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model",
|
TCG_NS, FIRMWARE_MANUFACTURER_STR, RIM_PFX);
|
||||||
"firmwareManufacturerStr", "rim");
|
|
||||||
public static final QName _FIRMWARE_MANUFACTURER_ID = new QName(
|
public static final QName _FIRMWARE_MANUFACTURER_ID = new QName(
|
||||||
"https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model",
|
TCG_NS, FIRMWARE_MANUFACTURER_ID, RIM_PFX);
|
||||||
"firmwareManufacturerId", "rim");
|
|
||||||
public static final QName _FIRMWARE_MODEL = new QName(
|
public static final QName _FIRMWARE_MODEL = new QName(
|
||||||
"https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model",
|
TCG_NS, FIRMWARE_MODEL, RIM_PFX);
|
||||||
"firmwareModel", "rim");
|
|
||||||
public static final QName _FIRMWARE_VERSION = new QName(
|
public static final QName _FIRMWARE_VERSION = new QName(
|
||||||
"https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model",
|
TCG_NS, FIRMWARE_VERSION, RIM_PFX);
|
||||||
"firmwareVersion", "rim");
|
|
||||||
public static final QName _BINDING_SPEC = new QName(
|
public static final QName _BINDING_SPEC = new QName(
|
||||||
"https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model",
|
TCG_NS, BINDING_SPEC, RIM_PFX);
|
||||||
"BindingSpec", "rim");
|
|
||||||
public static final QName _BINDING_SPEC_VERSION = new QName(
|
public static final QName _BINDING_SPEC_VERSION = new QName(
|
||||||
"https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model",
|
TCG_NS, BINDING_SPEC_VERSION, RIM_PFX);
|
||||||
"BindingSpecVersion", "rim");
|
|
||||||
public static final QName _PC_URI_LOCAL = new QName(
|
public static final QName _PC_URI_LOCAL = new QName(
|
||||||
"https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model",
|
TCG_NS, PC_URI_LOCAL, RIM_PFX);
|
||||||
"pcURILocal", "rim");
|
|
||||||
public static final QName _PC_URI_GLOBAL = new QName(
|
public static final QName _PC_URI_GLOBAL = new QName(
|
||||||
"https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model",
|
TCG_NS, PC_URI_GLOBAL, RIM_PFX);
|
||||||
"pcURIGlobal", "rim");
|
|
||||||
public static final QName _RIM_LINK_HASH = new QName(
|
public static final QName _RIM_LINK_HASH = new QName(
|
||||||
"https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model",
|
TCG_NS, RIM_LINK_HASH, RIM_PFX);
|
||||||
"rimLinkHash", "rim");
|
|
||||||
public static final QName _SUPPORT_RIM_TYPE = new QName(
|
public static final QName _SUPPORT_RIM_TYPE = new QName(
|
||||||
"https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model",
|
TCG_NS, SUPPORT_RIM_TYPE, RIM_PFX);
|
||||||
"supportRIMType", "rim");
|
|
||||||
public static final QName _SUPPORT_RIM_FORMAT = new QName(
|
public static final QName _SUPPORT_RIM_FORMAT = new QName(
|
||||||
"https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model",
|
TCG_NS, SUPPORT_RIM_FORMAT, RIM_PFX);
|
||||||
"supportRIMFormat", "rim");
|
|
||||||
public static final QName _SUPPORT_RIM_URI_GLOBAL = new QName(
|
public static final QName _SUPPORT_RIM_URI_GLOBAL = new QName(
|
||||||
"https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model",
|
TCG_NS, SUPPORT_RIM_URI_GLOBAL, RIM_PFX);
|
||||||
"supportRIMURIGlobal", "rim");
|
|
||||||
public static final QName _N8060_ENVVARPREFIX = new QName(
|
public static final QName _N8060_ENVVARPREFIX = new QName(
|
||||||
"http://csrc.nist.gov/ns/swid/2015-extensions/1.0",
|
NIST_NS, "envVarPrefix", N8060_PFX);
|
||||||
"envVarPrefix", "n8060");
|
|
||||||
public static final QName _N8060_ENVVARSUFFIX = new QName(
|
public static final QName _N8060_ENVVARSUFFIX = new QName(
|
||||||
"http://csrc.nist.gov/ns/swid/2015-extensions/1.0",
|
NIST_NS, "envVarSuffix", N8060_PFX);
|
||||||
"envVarSuffix", "n8060");
|
|
||||||
public static final QName _N8060_PATHSEPARATOR = new QName(
|
public static final QName _N8060_PATHSEPARATOR = new QName(
|
||||||
"http://csrc.nist.gov/ns/swid/2015-extensions/1.0",
|
NIST_NS, "pathSeparator", N8060_PFX);
|
||||||
"pathSeparator", "n8060");
|
|
||||||
|
|
||||||
public static final String CA_ISSUERS = "1.3.6.1.5.5.7.48.2";
|
public static final String CA_ISSUERS = "1.3.6.1.5.5.7.48.2";
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import hirs.swid.xjc.ResourceCollection;
|
|||||||
import hirs.swid.xjc.SoftwareIdentity;
|
import hirs.swid.xjc.SoftwareIdentity;
|
||||||
import hirs.swid.xjc.SoftwareMeta;
|
import hirs.swid.xjc.SoftwareMeta;
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
import javax.json.Json;
|
import javax.json.Json;
|
||||||
import javax.json.JsonException;
|
import javax.json.JsonException;
|
||||||
@ -20,11 +21,15 @@ import javax.xml.bind.JAXBException;
|
|||||||
import javax.xml.bind.Marshaller;
|
import javax.xml.bind.Marshaller;
|
||||||
import javax.xml.crypto.MarshalException;
|
import javax.xml.crypto.MarshalException;
|
||||||
import javax.xml.crypto.XMLStructure;
|
import javax.xml.crypto.XMLStructure;
|
||||||
|
import javax.xml.crypto.dom.DOMStructure;
|
||||||
import javax.xml.crypto.dsig.CanonicalizationMethod;
|
import javax.xml.crypto.dsig.CanonicalizationMethod;
|
||||||
import javax.xml.crypto.dsig.DigestMethod;
|
import javax.xml.crypto.dsig.DigestMethod;
|
||||||
import javax.xml.crypto.dsig.Reference;
|
import javax.xml.crypto.dsig.Reference;
|
||||||
|
import javax.xml.crypto.dsig.SignatureProperties;
|
||||||
|
import javax.xml.crypto.dsig.SignatureProperty;
|
||||||
import javax.xml.crypto.dsig.SignedInfo;
|
import javax.xml.crypto.dsig.SignedInfo;
|
||||||
import javax.xml.crypto.dsig.Transform;
|
import javax.xml.crypto.dsig.Transform;
|
||||||
|
import javax.xml.crypto.dsig.XMLObject;
|
||||||
import javax.xml.crypto.dsig.XMLSignature;
|
import javax.xml.crypto.dsig.XMLSignature;
|
||||||
import javax.xml.crypto.dsig.XMLSignatureException;
|
import javax.xml.crypto.dsig.XMLSignatureException;
|
||||||
import javax.xml.crypto.dsig.XMLSignatureFactory;
|
import javax.xml.crypto.dsig.XMLSignatureFactory;
|
||||||
@ -53,13 +58,17 @@ import java.io.FileOutputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
import java.security.KeyException;
|
import java.security.KeyException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.PrivateKey;
|
import java.security.PrivateKey;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Base64;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -80,6 +89,8 @@ public class SwidTagGateway {
|
|||||||
private String pemCertificateFile;
|
private String pemCertificateFile;
|
||||||
private boolean embeddedCert;
|
private boolean embeddedCert;
|
||||||
private String rimEventLog;
|
private String rimEventLog;
|
||||||
|
private String timestampFormat;
|
||||||
|
private String timestampArgument;
|
||||||
private String errorRequiredFields;
|
private String errorRequiredFields;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -94,6 +105,8 @@ public class SwidTagGateway {
|
|||||||
pemCertificateFile = "";
|
pemCertificateFile = "";
|
||||||
embeddedCert = false;
|
embeddedCert = false;
|
||||||
rimEventLog = "";
|
rimEventLog = "";
|
||||||
|
timestampFormat = "";
|
||||||
|
timestampArgument = "";
|
||||||
errorRequiredFields = "";
|
errorRequiredFields = "";
|
||||||
} catch (JAXBException e) {
|
} catch (JAXBException e) {
|
||||||
System.out.println("Error initializing jaxbcontext: " + e.getMessage());
|
System.out.println("Error initializing jaxbcontext: " + e.getMessage());
|
||||||
@ -164,6 +177,22 @@ public class SwidTagGateway {
|
|||||||
this.rimEventLog = rimEventLog;
|
this.rimEventLog = rimEventLog;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter for timestamp format in XML signature
|
||||||
|
* @param timestampFormat
|
||||||
|
*/
|
||||||
|
public void setTimestampFormat(String timestampFormat) {
|
||||||
|
this.timestampFormat = timestampFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter for timestamp input - RFC3852 + file or RFC3339 + value
|
||||||
|
* @param timestampArgument
|
||||||
|
*/
|
||||||
|
public void setTimestampArgument(String timestampArgument) {
|
||||||
|
this.timestampArgument = timestampArgument;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method generates a base RIM from the values in a JSON file.
|
* This method generates a base RIM from the values in a JSON file.
|
||||||
*
|
*
|
||||||
@ -523,8 +552,13 @@ public class SwidTagGateway {
|
|||||||
private Document signXMLDocument(JAXBElement<SoftwareIdentity> swidTag) throws Exception {
|
private Document signXMLDocument(JAXBElement<SoftwareIdentity> swidTag) throws Exception {
|
||||||
Document doc = null;
|
Document doc = null;
|
||||||
try {
|
try {
|
||||||
|
doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
|
||||||
|
marshaller.marshal(swidTag, doc);
|
||||||
XMLSignatureFactory sigFactory = XMLSignatureFactory.getInstance("DOM");
|
XMLSignatureFactory sigFactory = XMLSignatureFactory.getInstance("DOM");
|
||||||
Reference reference = sigFactory.newReference(
|
List xmlObjectList = null;
|
||||||
|
String signatureId = null;
|
||||||
|
|
||||||
|
Reference documentRef = sigFactory.newReference(
|
||||||
"",
|
"",
|
||||||
sigFactory.newDigestMethod(DigestMethod.SHA256, null),
|
sigFactory.newDigestMethod(DigestMethod.SHA256, null),
|
||||||
Collections.singletonList(sigFactory.newTransform(Transform.ENVELOPED,
|
Collections.singletonList(sigFactory.newTransform(Transform.ENVELOPED,
|
||||||
@ -532,12 +566,26 @@ public class SwidTagGateway {
|
|||||||
null,
|
null,
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
|
|
||||||
|
List<Reference> refList = new ArrayList<Reference>();
|
||||||
|
refList.add(documentRef);
|
||||||
|
|
||||||
|
if (!timestampFormat.isEmpty()) {
|
||||||
|
Reference timestampRef = sigFactory.newReference(
|
||||||
|
"#TST",
|
||||||
|
sigFactory.newDigestMethod(DigestMethod.SHA256, null)
|
||||||
|
);
|
||||||
|
refList.add(timestampRef);
|
||||||
|
xmlObjectList = Collections.singletonList(createXmlTimestamp(doc, sigFactory));
|
||||||
|
signatureId = "RimSignature";
|
||||||
|
}
|
||||||
|
|
||||||
SignedInfo signedInfo = sigFactory.newSignedInfo(
|
SignedInfo signedInfo = sigFactory.newSignedInfo(
|
||||||
sigFactory.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE,
|
sigFactory.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE,
|
||||||
(C14NMethodParameterSpec) null),
|
(C14NMethodParameterSpec) null),
|
||||||
sigFactory.newSignatureMethod(SwidTagConstants.SIGNATURE_ALGORITHM_RSA_SHA256,
|
sigFactory.newSignatureMethod(SwidTagConstants.SIGNATURE_ALGORITHM_RSA_SHA256,
|
||||||
null),
|
null),
|
||||||
Collections.singletonList(reference)
|
refList
|
||||||
);
|
);
|
||||||
List<XMLStructure> keyInfoElements = new ArrayList<XMLStructure>();
|
List<XMLStructure> keyInfoElements = new ArrayList<XMLStructure>();
|
||||||
|
|
||||||
@ -565,10 +613,14 @@ public class SwidTagGateway {
|
|||||||
}
|
}
|
||||||
KeyInfo keyinfo = kiFactory.newKeyInfo(keyInfoElements);
|
KeyInfo keyinfo = kiFactory.newKeyInfo(keyInfoElements);
|
||||||
|
|
||||||
doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
|
|
||||||
marshaller.marshal(swidTag, doc);
|
|
||||||
DOMSignContext context = new DOMSignContext(privateKey, doc.getDocumentElement());
|
DOMSignContext context = new DOMSignContext(privateKey, doc.getDocumentElement());
|
||||||
XMLSignature signature = sigFactory.newXMLSignature(signedInfo, keyinfo);
|
XMLSignature signature = sigFactory.newXMLSignature(
|
||||||
|
signedInfo,
|
||||||
|
keyinfo,
|
||||||
|
xmlObjectList,
|
||||||
|
signatureId,
|
||||||
|
null
|
||||||
|
);
|
||||||
signature.sign(context);
|
signature.sign(context);
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
System.out.println("Keystore not found! " + e.getMessage());
|
System.out.println("Keystore not found! " + e.getMessage());
|
||||||
@ -590,4 +642,53 @@ public class SwidTagGateway {
|
|||||||
|
|
||||||
return doc;
|
return doc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method creates a timestamp element and populates it with data according to
|
||||||
|
* the RFC format set in timestampFormat. The element is returned within an XMLObject.
|
||||||
|
* @param doc the Document representing the XML to be signed
|
||||||
|
* @param sigFactory the SignatureFactory object
|
||||||
|
* @return an XMLObject containing the timestamp element
|
||||||
|
*/
|
||||||
|
private XMLObject createXmlTimestamp(Document doc, XMLSignatureFactory sigFactory) {
|
||||||
|
Element timeStampElement = doc.createElement("TimeStamp");
|
||||||
|
switch (timestampFormat.toUpperCase()) {
|
||||||
|
case "RFC3852":
|
||||||
|
try {
|
||||||
|
byte[] counterSignature = Base64.getEncoder().encode(
|
||||||
|
Files.readAllBytes(Paths.get(timestampArgument)));
|
||||||
|
timeStampElement.setAttributeNS("http://www.w3.org/2000/xmlns/",
|
||||||
|
"xmlns:" + SwidTagConstants.RFC3852_PFX,
|
||||||
|
SwidTagConstants.RFC3852_NS);
|
||||||
|
timeStampElement.setAttribute(SwidTagConstants.DATETIME,
|
||||||
|
new String(counterSignature));
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "RFC3339":
|
||||||
|
timeStampElement.setAttributeNS("http://www.w3.org/2000/xmlns/",
|
||||||
|
"xmlns:" + SwidTagConstants.RFC3339_PFX,
|
||||||
|
SwidTagConstants.RFC3339_NS);
|
||||||
|
if (timestampArgument.isEmpty()) {
|
||||||
|
timeStampElement.setAttribute(SwidTagConstants.DATETIME,
|
||||||
|
LocalDateTime.now().toString());
|
||||||
|
} else {
|
||||||
|
timeStampElement.setAttribute(SwidTagConstants.DATETIME,
|
||||||
|
timestampArgument);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
DOMStructure timestampObject = new DOMStructure(timeStampElement);
|
||||||
|
SignatureProperty signatureProperty = sigFactory.newSignatureProperty(
|
||||||
|
Collections.singletonList(timestampObject), "RimSignature", "TST"
|
||||||
|
);
|
||||||
|
SignatureProperties signatureProperties = sigFactory.newSignatureProperties(
|
||||||
|
Collections.singletonList(signatureProperty), null);
|
||||||
|
XMLObject xmlObject = sigFactory.newXMLObject(
|
||||||
|
Collections.singletonList(signatureProperties), null,null,null);
|
||||||
|
|
||||||
|
return xmlObject;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,9 @@ package hirs.swid.utils;
|
|||||||
import com.beust.jcommander.Parameter;
|
import com.beust.jcommander.Parameter;
|
||||||
import hirs.swid.SwidTagConstants;
|
import hirs.swid.SwidTagConstants;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Commander is a class that handles the command line arguments for the SWID
|
* Commander is a class that handles the command line arguments for the SWID
|
||||||
* Tags gateway by implementing the JCommander package.
|
* Tags gateway by implementing the JCommander package.
|
||||||
@ -45,6 +48,11 @@ public class Commander {
|
|||||||
@Parameter(names = {"-l", "--rimel <path>"}, order = 9,
|
@Parameter(names = {"-l", "--rimel <path>"}, order = 9,
|
||||||
description = "The TCG eventlog file to use as a support RIM.")
|
description = "The TCG eventlog file to use as a support RIM.")
|
||||||
private String rimEventLog = "";
|
private String rimEventLog = "";
|
||||||
|
@Parameter(names = {"--timestamp"}, order = 10, variableArity = true,
|
||||||
|
description = "Add a timestamp to the signature. " +
|
||||||
|
"Currently only RFC3339 and RFC3852 are supported:\n" +
|
||||||
|
"\tRFC3339 [yyyy-MM-ddThh:mm:ssZ]\n\tRFC3852 <counterSignature.bin>")
|
||||||
|
private List<String> timestampArguments = new ArrayList<String>(2);
|
||||||
|
|
||||||
public boolean isHelp() {
|
public boolean isHelp() {
|
||||||
return help;
|
return help;
|
||||||
@ -82,6 +90,10 @@ public class Commander {
|
|||||||
|
|
||||||
public String getRimEventLog() { return rimEventLog; }
|
public String getRimEventLog() { return rimEventLog; }
|
||||||
|
|
||||||
|
public List<String> getTimestampArguments() {
|
||||||
|
return timestampArguments;
|
||||||
|
}
|
||||||
|
|
||||||
public String printHelpExamples() {
|
public String printHelpExamples() {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append("Create a base RIM using the values in attributes.json; " +
|
sb.append("Create a base RIM using the values in attributes.json; " +
|
||||||
@ -93,6 +105,11 @@ public class Commander {
|
|||||||
sb.append("sign it using privateKey.pem; embed cert.pem in the signature block; ");
|
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("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("\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("Validate a base RIM using an external support RIM to override the ");
|
||||||
sb.append("payload file:\n\n");
|
sb.append("payload file:\n\n");
|
||||||
sb.append("\t\t-v base_rim.swidtag -l support_rim.bin\n\n\n");
|
sb.append("\t\t-v base_rim.swidtag -l support_rim.bin\n\n\n");
|
||||||
@ -123,6 +140,15 @@ public class Commander {
|
|||||||
sb.append("Signing credential: (none given)" + System.lineSeparator());
|
sb.append("Signing credential: (none given)" + System.lineSeparator());
|
||||||
}
|
}
|
||||||
sb.append("Event log support RIM: " + this.getRimEventLog() + System.lineSeparator());
|
sb.append("Event log support RIM: " + this.getRimEventLog() + System.lineSeparator());
|
||||||
|
List<String> timestampArguments = this.getTimestampArguments();
|
||||||
|
if (timestampArguments.size() > 0) {
|
||||||
|
sb.append("Timestamp format: " + timestampArguments.get(0));
|
||||||
|
if (timestampArguments.size() == 2) {
|
||||||
|
sb.append(", " + timestampArguments.get(1));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sb.append("No timestamp included");
|
||||||
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,124 @@
|
|||||||
|
package hirs.swid.utils;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.format.DateTimeParseException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class TimestampArgumentValidator {
|
||||||
|
List<String> args;
|
||||||
|
/**
|
||||||
|
* This class handles validation of the --timestamp commandline parameter.
|
||||||
|
* Currently only RFC3339 and RFC3852 formats are supported.
|
||||||
|
*
|
||||||
|
* @param args list of arguments from command line
|
||||||
|
*/
|
||||||
|
public TimestampArgumentValidator(List<String> args) {
|
||||||
|
this.args = args;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the public access method through which all other methods are called.
|
||||||
|
*
|
||||||
|
* @return true if all arguments are valid, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean isValid() {
|
||||||
|
if (isExactlyOneFormat(args)) {
|
||||||
|
if (args.get(0).equalsIgnoreCase("RFC3852")) {
|
||||||
|
if (args.size() > 1) {
|
||||||
|
if (isRfc3852FileValid(args.get(1))) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (args.size() == 1){
|
||||||
|
System.out.println("Countersignature file is required for RFC3852 timestamps");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (args.get(0).equalsIgnoreCase("RFC3339")) {
|
||||||
|
if (args.size() > 1) {
|
||||||
|
if (isRfc3339Format(args.get(1))) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (args.size() == 1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
System.out.println("Unsupported timestamp format specified");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method ensures that exactly one of RFC3339 and RFC3852 are specified.
|
||||||
|
*
|
||||||
|
* @param args list of command line arguments
|
||||||
|
* @return true if exactly one format is specified, false otherwise
|
||||||
|
*/
|
||||||
|
private boolean isExactlyOneFormat(List<String> args) {
|
||||||
|
Pattern pattern = Pattern.compile("(R|r)(F|f)(C|c)(3339|3852)");
|
||||||
|
String format = args.get(0);
|
||||||
|
Matcher formatMatcher = pattern.matcher(format);
|
||||||
|
|
||||||
|
if (!formatMatcher.matches()) {
|
||||||
|
System.out.println("Invalid timestamp format specified, expected RFC3339 or RFC3852.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (args.size() == 2) {
|
||||||
|
String argument = args.get(1);
|
||||||
|
Matcher argumentMatcher = pattern.matcher(argument);
|
||||||
|
if (argumentMatcher.matches()) {
|
||||||
|
System.out.println("Exactly one timestamp format must be specified.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method verifies a user-given RFC3339 timestamp
|
||||||
|
*
|
||||||
|
* @param timestamp the timestamp string
|
||||||
|
* @return true if valid RFC3339 format, false otherwise
|
||||||
|
*/
|
||||||
|
private boolean isRfc3339Format(String timestamp) {
|
||||||
|
try {
|
||||||
|
Instant instant = Instant.parse(timestamp);
|
||||||
|
} catch (DateTimeParseException e) {
|
||||||
|
System.out.println("Invalid RFC3339 timestamp given, " +
|
||||||
|
"expected yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method verifies the counter signature file
|
||||||
|
*
|
||||||
|
* @param file the counter signature
|
||||||
|
* @return true if file exists and is valid, false otherwise
|
||||||
|
*/
|
||||||
|
private boolean isRfc3852FileValid(String file) {
|
||||||
|
if (file != null && !file.isEmpty()) {
|
||||||
|
try {
|
||||||
|
Files.readAllBytes(Paths.get(file));
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
System.out.println("RFC3852 requires a filename input of the countersignature file.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -17,6 +17,8 @@ public class TestSwidTagGateway {
|
|||||||
private final String BASE_USER_CERT = "generated_user_cert.swidtag";
|
private final String BASE_USER_CERT = "generated_user_cert.swidtag";
|
||||||
private final String BASE_USER_CERT_EMBED = "generated_user_cert_embed.swidtag";
|
private final String BASE_USER_CERT_EMBED = "generated_user_cert_embed.swidtag";
|
||||||
private final String BASE_DEFAULT_CERT = "generated_default_cert.swidtag";
|
private final String BASE_DEFAULT_CERT = "generated_default_cert.swidtag";
|
||||||
|
private final String BASE_RFC3339_TIMESTAMP = "generated_timestamp_rfc3339.swidtag";
|
||||||
|
private final String BASE_RFC3852_TIMESTAMP = "generated_timestamp_rfc3852.swidtag";
|
||||||
private final String ATTRIBUTES_FILE = TestSwidTagGateway.class.getClassLoader()
|
private final String ATTRIBUTES_FILE = TestSwidTagGateway.class.getClassLoader()
|
||||||
.getResource("rim_fields.json").getPath();
|
.getResource("rim_fields.json").getPath();
|
||||||
private final String JKS_KEYSTORE_FILE = TestSwidTagGateway.class.getClassLoader()
|
private final String JKS_KEYSTORE_FILE = TestSwidTagGateway.class.getClassLoader()
|
||||||
@ -29,6 +31,8 @@ public class TestSwidTagGateway {
|
|||||||
.getResource("RimCertChain.pem").getPath();
|
.getResource("RimCertChain.pem").getPath();
|
||||||
private final String SUPPORT_RIM_FILE = TestSwidTagGateway.class.getClassLoader()
|
private final String SUPPORT_RIM_FILE = TestSwidTagGateway.class.getClassLoader()
|
||||||
.getResource("TpmLog.bin").getPath();
|
.getResource("TpmLog.bin").getPath();
|
||||||
|
private final String RFC3852_COUNTERSIGNATURE_FILE = TestSwidTagGateway.class.getClassLoader()
|
||||||
|
.getResource("counterSignature.file").getPath();
|
||||||
private InputStream expectedFile;
|
private InputStream expectedFile;
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
@ -87,7 +91,7 @@ public class TestSwidTagGateway {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This test corresponds to the arguments:
|
* This test corresponds to the arguments:
|
||||||
* -c base -l TpmLog.bin
|
* -c base -l TpmLog.bin -d
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testCreateBaseDefaultCert() {
|
public void testCreateBaseDefaultCert() {
|
||||||
@ -100,6 +104,40 @@ public class TestSwidTagGateway {
|
|||||||
Assert.assertTrue(validator.validateSwidTag(DEFAULT_OUTPUT));
|
Assert.assertTrue(validator.validateSwidTag(DEFAULT_OUTPUT));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This test corresponds to the arguments:
|
||||||
|
* -c base -l TpmLog.bin -d --timestamp rfc3339 2023-01-01T00:00:00Z
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testCreateTimestampRfc3339() {
|
||||||
|
gateway.setDefaultCredentials(true);
|
||||||
|
gateway.setJksTruststoreFile(JKS_KEYSTORE_FILE);
|
||||||
|
gateway.setTimestampFormat("RFC3339");
|
||||||
|
gateway.setTimestampArgument("2023-01-01T00:00:00Z");
|
||||||
|
gateway.generateSwidTag(DEFAULT_OUTPUT);
|
||||||
|
expectedFile = TestSwidTagGateway.class.getClassLoader()
|
||||||
|
.getResourceAsStream(BASE_RFC3339_TIMESTAMP);
|
||||||
|
Assert.assertTrue(compareFileBytesToExpectedFile(DEFAULT_OUTPUT));
|
||||||
|
Assert.assertTrue(validator.validateSwidTag(DEFAULT_OUTPUT));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This test corresponds to the arguments:
|
||||||
|
* -c base -l TpmLog.bin -d --timestamp rfc3852 countersignature.file
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testCreateTimestampRfc3852() {
|
||||||
|
gateway.setDefaultCredentials(true);
|
||||||
|
gateway.setJksTruststoreFile(JKS_KEYSTORE_FILE);
|
||||||
|
gateway.setTimestampFormat("RFC3852");
|
||||||
|
gateway.setTimestampArgument(RFC3852_COUNTERSIGNATURE_FILE);
|
||||||
|
gateway.generateSwidTag(DEFAULT_OUTPUT);
|
||||||
|
expectedFile = TestSwidTagGateway.class.getClassLoader()
|
||||||
|
.getResourceAsStream(BASE_RFC3852_TIMESTAMP);
|
||||||
|
Assert.assertTrue(compareFileBytesToExpectedFile(DEFAULT_OUTPUT));
|
||||||
|
Assert.assertTrue(validator.validateSwidTag(DEFAULT_OUTPUT));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This test corresponds to the arguments:
|
* This test corresponds to the arguments:
|
||||||
* -v <path>
|
* -v <path>
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
test
|
@ -2,7 +2,7 @@
|
|||||||
<SoftwareIdentity xmlns="http://standards.iso.org/iso/19770/-2/2015/schema.xsd" xmlns:ns2="http://www.w3.org/2000/09/xmldsig#" corpus="false" name="Example.com BIOS" patch="false" supplemental="false" tagId="94f6b457-9ac9-4d35-9b3f-78804173b65as" tagVersion="0" version="01" versionScheme="multipartnumeric" xml:lang="en">
|
<SoftwareIdentity xmlns="http://standards.iso.org/iso/19770/-2/2015/schema.xsd" xmlns:ns2="http://www.w3.org/2000/09/xmldsig#" corpus="false" name="Example.com BIOS" patch="false" supplemental="false" tagId="94f6b457-9ac9-4d35-9b3f-78804173b65as" tagVersion="0" version="01" versionScheme="multipartnumeric" xml:lang="en">
|
||||||
<Entity name="Example Inc" regid="http://Example.com" role="softwareCreator tagCreator"/>
|
<Entity name="Example Inc" regid="http://Example.com" role="softwareCreator tagCreator"/>
|
||||||
<Link href="https://Example.com/support/ProductA/firmware/installfiles" rel="installationmedia"/>
|
<Link href="https://Example.com/support/ProductA/firmware/installfiles" rel="installationmedia"/>
|
||||||
<Meta xmlns:n8060="http://csrc.nist.gov/ns/swid/2015-extensions/1.0" xmlns:rim="https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model" n8060:colloquialVersion="Firmware_2019" n8060:edition="12" n8060:product="ProductA" n8060:revision="r2" rim:BindingSpec="PC Client RIM" rim:BindingSpecVersion="1.2" rim:PayloadType="direct" rim:firmwareManufacturerId="00213022" rim:firmwareManufacturerStr="BIOSVendorA" rim:firmwareModel="A0" rim:firmwareVersion="12" rim:pcURIGlobal="https://Example.com/support/ProductA/" rim:pcURILocal="/boot/tcg/manifest/switag/" rim:platformManufacturerId="00201234" rim:platformManufacturerStr="Example.com" rim:platformModel="ProductA" rim:platformVersion="01"/>
|
<Meta xmlns:n8060="http://csrc.nist.gov/ns/swid/2015-extensions/1.0" xmlns:rim="https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model" n8060:colloquialVersion="Firmware_2019" n8060:edition="12" n8060:product="ProductA" n8060:revision="r2" rim:PayloadType="direct" rim:bindingSpec="PC Client RIM" rim:bindingSpecVersion="1.2" rim:firmwareManufacturerId="00213022" rim:firmwareManufacturerStr="BIOSVendorA" rim:firmwareModel="A0" rim:firmwareVersion="12" rim:pcURIGlobal="https://Example.com/support/ProductA/" rim:pcURIlocal="/boot/tcg/manifest/switag/" rim:platformManufacturerId="00201234" rim:platformManufacturerStr="Example.com" rim:platformModel="ProductA" rim:platformVersion="01"/>
|
||||||
<Payload>
|
<Payload>
|
||||||
<Directory name="rim">
|
<Directory name="rim">
|
||||||
<File xmlns:SHA256="http://www.w3.org/2001/04/xmlenc#sha256" SHA256:hash="4479ca722623f8c47b703996ced3cbd981b06b1ae8a897db70137e0b7c546848" name="Example.com.BIOS.01.rimel" size="7549"/>
|
<File xmlns:SHA256="http://www.w3.org/2001/04/xmlenc#sha256" SHA256:hash="4479ca722623f8c47b703996ced3cbd981b06b1ae8a897db70137e0b7c546848" name="Example.com.BIOS.01.rimel" size="7549"/>
|
||||||
@ -17,14 +17,14 @@
|
|||||||
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
|
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
|
||||||
</Transforms>
|
</Transforms>
|
||||||
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
|
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
|
||||||
<DigestValue>K3XoBeYvgJBAKl8z273sL7z38qLLVBKLfUPt/gPUzBI=</DigestValue>
|
<DigestValue>DJMc0n3VHHwU+F3HNpiY/l3EMcjRZAQOYlrjhD5v9qE=</DigestValue>
|
||||||
</Reference>
|
</Reference>
|
||||||
</SignedInfo>
|
</SignedInfo>
|
||||||
<SignatureValue>cIl1gPsUyEj2gDv3HTWNFDVxtcBjz4Revxxf2LJejtOXQW8mGepZH8CnvgO7zCAbZYlYUZXjYZ9M
|
<SignatureValue>ojJ6v8ToxLWWekCKmBoZ+Yg2V4MYMPbKB9FjDs/QG/AMP+LKjnb55Z7FSLhC8+CvvShKPAoS9mv1
|
||||||
jONVv8dcsAjVHRnP6YHywFfmSm8LUCwxsfuZQqn5jClqzu5VaqLzBhuJYvCpiEdIDJwDINQuORUB
|
QepwI17NEqbfnC1U4WH0u578A3J6wiHMXIDnIQqKAAXb8v2c/wjMDArzFl8CXmDA7HUDIt+3C4VC
|
||||||
nzul1CWc3Sm1Ms2wjlIq5ctWWJcddhdyIOjl8/oD4EC5E2rOSfNcRMZxldXtie9iinFGVbr0YNE+
|
tA598YY7o0Hf6hK5qO8oWGQxXUKfpUwvtGLxHpbDWYFuVSPa+uk6OTzutt/QyzTERzxyO9Le1i6K
|
||||||
+lQ7hAU+SyV8RMx9tGnnsO8otwV4ddF+OfemcbzWGYBenLs3A8ZqWZyTvWphCgGqDUbOLssYciCC
|
nrpzh4lgHn6EfGs6HR1ffdHQ069q0bE61zDx0VC18nK9DmszW6p6FlMzApiTVW/4PiVt+dSFeVGR
|
||||||
mnYm5QOeh4QcE9H2kqTgZvcyCgPL/hDC7xhyjQ==</SignatureValue>
|
9///OdtxcoBCeofDDFPRyO+s+kY1pXd92Q3nfg==</SignatureValue>
|
||||||
<KeyInfo>
|
<KeyInfo>
|
||||||
<KeyName>2fdeb8e7d030a2209daa01861a964fedecf2bcc1</KeyName>
|
<KeyName>2fdeb8e7d030a2209daa01861a964fedecf2bcc1</KeyName>
|
||||||
</KeyInfo>
|
</KeyInfo>
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<SoftwareIdentity xmlns="http://standards.iso.org/iso/19770/-2/2015/schema.xsd" xmlns:ns2="http://www.w3.org/2000/09/xmldsig#" corpus="false" name="Example.com BIOS" patch="false" supplemental="false" tagId="94f6b457-9ac9-4d35-9b3f-78804173b65as" tagVersion="0" version="01" versionScheme="multipartnumeric" xml:lang="en">
|
||||||
|
<Entity name="Example Inc" regid="http://Example.com" role="softwareCreator tagCreator"/>
|
||||||
|
<Link href="https://Example.com/support/ProductA/firmware/installfiles" rel="installationmedia"/>
|
||||||
|
<Meta xmlns:n8060="http://csrc.nist.gov/ns/swid/2015-extensions/1.0" xmlns:rim="https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model" n8060:colloquialVersion="Firmware_2019" n8060:edition="12" n8060:product="ProductA" n8060:revision="r2" rim:PayloadType="direct" rim:bindingSpec="PC Client RIM" rim:bindingSpecVersion="1.2" rim:firmwareManufacturerId="00213022" rim:firmwareManufacturerStr="BIOSVendorA" rim:firmwareModel="A0" rim:firmwareVersion="12" rim:pcURIGlobal="https://Example.com/support/ProductA/" rim:pcURIlocal="/boot/tcg/manifest/switag/" rim:platformManufacturerId="00201234" rim:platformManufacturerStr="Example.com" rim:platformModel="ProductA" rim:platformVersion="01"/>
|
||||||
|
<Payload>
|
||||||
|
<Directory name="rim">
|
||||||
|
<File xmlns:SHA256="http://www.w3.org/2001/04/xmlenc#sha256" SHA256:hash="4479ca722623f8c47b703996ced3cbd981b06b1ae8a897db70137e0b7c546848" name="Example.com.BIOS.01.rimel" size="7549"/>
|
||||||
|
</Directory>
|
||||||
|
</Payload>
|
||||||
|
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#" Id="RimSignature">
|
||||||
|
<SignedInfo>
|
||||||
|
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
|
||||||
|
<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
|
||||||
|
<Reference URI="">
|
||||||
|
<Transforms>
|
||||||
|
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
|
||||||
|
</Transforms>
|
||||||
|
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
|
||||||
|
<DigestValue>DJMc0n3VHHwU+F3HNpiY/l3EMcjRZAQOYlrjhD5v9qE=</DigestValue>
|
||||||
|
</Reference>
|
||||||
|
<Reference URI="#TST">
|
||||||
|
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
|
||||||
|
<DigestValue>j8sqX9NGt8DAPOvbhXKAT648BGdPnQnblai1PYDUryE=</DigestValue>
|
||||||
|
</Reference>
|
||||||
|
</SignedInfo>
|
||||||
|
<SignatureValue>N8QB5dMLnSLaDuCO8Ds/9nPlJGzsF1HJCthEXDXPrMTpfWBwmsVTqtNwoGzHIXlx8HDdDcfTLa3j
|
||||||
|
3rfFmDZNMqv6+6jjjJZerpN6XyWHGaVjVuPiNGmafE5SajTg53+6KlWXTGs3kcbbV5cTtjASz/A0
|
||||||
|
cz9gBYTwYXmWA3+V0USLA0MNYzPkKp83eDnizbrkGx824NU9qG1DetVFfZqotWoTGJ1Wz4J8D1yR
|
||||||
|
wUILS0DbtZalCNVv3kw9raIRKQ/CjlDztfP1SgiNuXu6IaVZKoVG9HGp3s8pQvFPHr0HD2sNrAkx
|
||||||
|
twKcg3XIzGrTc22Y2TYw9Dk3NxumQSp4kve6ow==</SignatureValue>
|
||||||
|
<KeyInfo>
|
||||||
|
<KeyName>2fdeb8e7d030a2209daa01861a964fedecf2bcc1</KeyName>
|
||||||
|
</KeyInfo>
|
||||||
|
<Object>
|
||||||
|
<SignatureProperties>
|
||||||
|
<SignatureProperty Id="TST" Target="RimSignature">
|
||||||
|
<TimeStamp xmlns:rcf3339="https://www.ietf.org/rfc/rfc3339.txt" dateTime="2023-01-01T00:00:00Z"/>
|
||||||
|
</SignatureProperty>
|
||||||
|
</SignatureProperties>
|
||||||
|
</Object>
|
||||||
|
</Signature>
|
||||||
|
</SoftwareIdentity>
|
@ -0,0 +1,43 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<SoftwareIdentity xmlns="http://standards.iso.org/iso/19770/-2/2015/schema.xsd" xmlns:ns2="http://www.w3.org/2000/09/xmldsig#" corpus="false" name="Example.com BIOS" patch="false" supplemental="false" tagId="94f6b457-9ac9-4d35-9b3f-78804173b65as" tagVersion="0" version="01" versionScheme="multipartnumeric" xml:lang="en">
|
||||||
|
<Entity name="Example Inc" regid="http://Example.com" role="softwareCreator tagCreator"/>
|
||||||
|
<Link href="https://Example.com/support/ProductA/firmware/installfiles" rel="installationmedia"/>
|
||||||
|
<Meta xmlns:n8060="http://csrc.nist.gov/ns/swid/2015-extensions/1.0" xmlns:rim="https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model" n8060:colloquialVersion="Firmware_2019" n8060:edition="12" n8060:product="ProductA" n8060:revision="r2" rim:PayloadType="direct" rim:bindingSpec="PC Client RIM" rim:bindingSpecVersion="1.2" rim:firmwareManufacturerId="00213022" rim:firmwareManufacturerStr="BIOSVendorA" rim:firmwareModel="A0" rim:firmwareVersion="12" rim:pcURIGlobal="https://Example.com/support/ProductA/" rim:pcURIlocal="/boot/tcg/manifest/switag/" rim:platformManufacturerId="00201234" rim:platformManufacturerStr="Example.com" rim:platformModel="ProductA" rim:platformVersion="01"/>
|
||||||
|
<Payload>
|
||||||
|
<Directory name="rim">
|
||||||
|
<File xmlns:SHA256="http://www.w3.org/2001/04/xmlenc#sha256" SHA256:hash="4479ca722623f8c47b703996ced3cbd981b06b1ae8a897db70137e0b7c546848" name="Example.com.BIOS.01.rimel" size="7549"/>
|
||||||
|
</Directory>
|
||||||
|
</Payload>
|
||||||
|
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#" Id="RimSignature">
|
||||||
|
<SignedInfo>
|
||||||
|
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
|
||||||
|
<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
|
||||||
|
<Reference URI="">
|
||||||
|
<Transforms>
|
||||||
|
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
|
||||||
|
</Transforms>
|
||||||
|
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
|
||||||
|
<DigestValue>DJMc0n3VHHwU+F3HNpiY/l3EMcjRZAQOYlrjhD5v9qE=</DigestValue>
|
||||||
|
</Reference>
|
||||||
|
<Reference URI="#TST">
|
||||||
|
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
|
||||||
|
<DigestValue>KC51x7iXfEjDYEieFP1lktWNGP6eCWpXe5/sr3V8PlU=</DigestValue>
|
||||||
|
</Reference>
|
||||||
|
</SignedInfo>
|
||||||
|
<SignatureValue>M6a+lIU7vIQmO0By/WCtocI4qzk4R4oXtduEpeyOfIH/xOTKkDI7E17v6dywLd7psZSKMPw8lRqp
|
||||||
|
AZCBvsU6zDXzLsAakO2ydmH2i5POWNArUq+GRw9KDnNPZWanmRSqjpV2mEjfx84IF2MaqXDPng1q
|
||||||
|
JrzKN8f00uHM+eOmXktyiBhJR9gT+htceMzAEzk8qeWCg6o6wFMx0JR1lUbGOXe070DtZCR7I0iQ
|
||||||
|
0iZfnNzMzuRf2GHw6aKnSyGwdr1pUeoxEVGR5jkY8a7mT/0mt+8kVq4FL1gikrSOzvotoZ+dGb0Q
|
||||||
|
JjzA2IgK+ti/Tc/FpLYKefXQwcVSUY+CD/HCvA==</SignatureValue>
|
||||||
|
<KeyInfo>
|
||||||
|
<KeyName>2fdeb8e7d030a2209daa01861a964fedecf2bcc1</KeyName>
|
||||||
|
</KeyInfo>
|
||||||
|
<Object>
|
||||||
|
<SignatureProperties>
|
||||||
|
<SignatureProperty Id="TST" Target="RimSignature">
|
||||||
|
<TimeStamp xmlns:rcf3852="https://www.ietf.org/rfc/rfc3852.txt" dateTime="dGVzdAo="/>
|
||||||
|
</SignatureProperty>
|
||||||
|
</SignatureProperties>
|
||||||
|
</Object>
|
||||||
|
</Signature>
|
||||||
|
</SoftwareIdentity>
|
@ -2,7 +2,7 @@
|
|||||||
<SoftwareIdentity xmlns="http://standards.iso.org/iso/19770/-2/2015/schema.xsd" xmlns:ns2="http://www.w3.org/2000/09/xmldsig#" corpus="false" name="Example.com BIOS" patch="false" supplemental="false" tagId="94f6b457-9ac9-4d35-9b3f-78804173b65as" tagVersion="0" version="01" versionScheme="multipartnumeric" xml:lang="en">
|
<SoftwareIdentity xmlns="http://standards.iso.org/iso/19770/-2/2015/schema.xsd" xmlns:ns2="http://www.w3.org/2000/09/xmldsig#" corpus="false" name="Example.com BIOS" patch="false" supplemental="false" tagId="94f6b457-9ac9-4d35-9b3f-78804173b65as" tagVersion="0" version="01" versionScheme="multipartnumeric" xml:lang="en">
|
||||||
<Entity name="Example Inc" regid="http://Example.com" role="softwareCreator tagCreator"/>
|
<Entity name="Example Inc" regid="http://Example.com" role="softwareCreator tagCreator"/>
|
||||||
<Link href="https://Example.com/support/ProductA/firmware/installfiles" rel="installationmedia"/>
|
<Link href="https://Example.com/support/ProductA/firmware/installfiles" rel="installationmedia"/>
|
||||||
<Meta xmlns:n8060="http://csrc.nist.gov/ns/swid/2015-extensions/1.0" xmlns:rim="https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model" n8060:colloquialVersion="Firmware_2019" n8060:edition="12" n8060:product="ProductA" n8060:revision="r2" rim:BindingSpec="PC Client RIM" rim:BindingSpecVersion="1.2" rim:PayloadType="direct" rim:firmwareManufacturerId="00213022" rim:firmwareManufacturerStr="BIOSVendorA" rim:firmwareModel="A0" rim:firmwareVersion="12" rim:pcURIGlobal="https://Example.com/support/ProductA/" rim:pcURILocal="/boot/tcg/manifest/switag/" rim:platformManufacturerId="00201234" rim:platformManufacturerStr="Example.com" rim:platformModel="ProductA" rim:platformVersion="01"/>
|
<Meta xmlns:n8060="http://csrc.nist.gov/ns/swid/2015-extensions/1.0" xmlns:rim="https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model" n8060:colloquialVersion="Firmware_2019" n8060:edition="12" n8060:product="ProductA" n8060:revision="r2" rim:PayloadType="direct" rim:bindingSpec="PC Client RIM" rim:bindingSpecVersion="1.2" rim:firmwareManufacturerId="00213022" rim:firmwareManufacturerStr="BIOSVendorA" rim:firmwareModel="A0" rim:firmwareVersion="12" rim:pcURIGlobal="https://Example.com/support/ProductA/" rim:pcURIlocal="/boot/tcg/manifest/switag/" rim:platformManufacturerId="00201234" rim:platformManufacturerStr="Example.com" rim:platformModel="ProductA" rim:platformVersion="01"/>
|
||||||
<Payload>
|
<Payload>
|
||||||
<Directory name="rim">
|
<Directory name="rim">
|
||||||
<File xmlns:SHA256="http://www.w3.org/2001/04/xmlenc#sha256" SHA256:hash="4479ca722623f8c47b703996ced3cbd981b06b1ae8a897db70137e0b7c546848" name="Example.com.BIOS.01.rimel" size="7549"/>
|
<File xmlns:SHA256="http://www.w3.org/2001/04/xmlenc#sha256" SHA256:hash="4479ca722623f8c47b703996ced3cbd981b06b1ae8a897db70137e0b7c546848" name="Example.com.BIOS.01.rimel" size="7549"/>
|
||||||
@ -17,14 +17,14 @@
|
|||||||
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
|
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
|
||||||
</Transforms>
|
</Transforms>
|
||||||
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
|
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
|
||||||
<DigestValue>K3XoBeYvgJBAKl8z273sL7z38qLLVBKLfUPt/gPUzBI=</DigestValue>
|
<DigestValue>DJMc0n3VHHwU+F3HNpiY/l3EMcjRZAQOYlrjhD5v9qE=</DigestValue>
|
||||||
</Reference>
|
</Reference>
|
||||||
</SignedInfo>
|
</SignedInfo>
|
||||||
<SignatureValue>cIl1gPsUyEj2gDv3HTWNFDVxtcBjz4Revxxf2LJejtOXQW8mGepZH8CnvgO7zCAbZYlYUZXjYZ9M
|
<SignatureValue>ojJ6v8ToxLWWekCKmBoZ+Yg2V4MYMPbKB9FjDs/QG/AMP+LKjnb55Z7FSLhC8+CvvShKPAoS9mv1
|
||||||
jONVv8dcsAjVHRnP6YHywFfmSm8LUCwxsfuZQqn5jClqzu5VaqLzBhuJYvCpiEdIDJwDINQuORUB
|
QepwI17NEqbfnC1U4WH0u578A3J6wiHMXIDnIQqKAAXb8v2c/wjMDArzFl8CXmDA7HUDIt+3C4VC
|
||||||
nzul1CWc3Sm1Ms2wjlIq5ctWWJcddhdyIOjl8/oD4EC5E2rOSfNcRMZxldXtie9iinFGVbr0YNE+
|
tA598YY7o0Hf6hK5qO8oWGQxXUKfpUwvtGLxHpbDWYFuVSPa+uk6OTzutt/QyzTERzxyO9Le1i6K
|
||||||
+lQ7hAU+SyV8RMx9tGnnsO8otwV4ddF+OfemcbzWGYBenLs3A8ZqWZyTvWphCgGqDUbOLssYciCC
|
nrpzh4lgHn6EfGs6HR1ffdHQ069q0bE61zDx0VC18nK9DmszW6p6FlMzApiTVW/4PiVt+dSFeVGR
|
||||||
mnYm5QOeh4QcE9H2kqTgZvcyCgPL/hDC7xhyjQ==</SignatureValue>
|
9///OdtxcoBCeofDDFPRyO+s+kY1pXd92Q3nfg==</SignatureValue>
|
||||||
<KeyInfo>
|
<KeyInfo>
|
||||||
<KeyValue>
|
<KeyValue>
|
||||||
<RSAKeyValue>
|
<RSAKeyValue>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<SoftwareIdentity xmlns="http://standards.iso.org/iso/19770/-2/2015/schema.xsd" xmlns:ns2="http://www.w3.org/2000/09/xmldsig#" corpus="false" name="Example.com BIOS" patch="false" supplemental="false" tagId="94f6b457-9ac9-4d35-9b3f-78804173b65as" tagVersion="0" version="01" versionScheme="multipartnumeric" xml:lang="en">
|
<SoftwareIdentity xmlns="http://standards.iso.org/iso/19770/-2/2015/schema.xsd" xmlns:ns2="http://www.w3.org/2000/09/xmldsig#" corpus="false" name="Example.com BIOS" patch="false" supplemental="false" tagId="94f6b457-9ac9-4d35-9b3f-78804173b65as" tagVersion="0" version="01" versionScheme="multipartnumeric" xml:lang="en">
|
||||||
<Entity name="Example Inc" regid="http://Example.com" role="softwareCreator tagCreator"/>
|
<Entity name="Example Inc" regid="http://Example.com" role="softwareCreator tagCreator"/>
|
||||||
<Link href="https://Example.com/support/ProductA/firmware/installfiles" rel="installationmedia"/>
|
<Link href="https://Example.com/support/ProductA/firmware/installfiles" rel="installationmedia"/>
|
||||||
<Meta xmlns:n8060="http://csrc.nist.gov/ns/swid/2015-extensions/1.0" xmlns:rim="https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model" n8060:colloquialVersion="Firmware_2019" n8060:edition="12" n8060:product="ProductA" n8060:revision="r2" rim:BindingSpec="PC Client RIM" rim:BindingSpecVersion="1.2" rim:PayloadType="direct" rim:firmwareManufacturerId="00213022" rim:firmwareManufacturerStr="BIOSVendorA" rim:firmwareModel="A0" rim:firmwareVersion="12" rim:pcURIGlobal="https://Example.com/support/ProductA/" rim:pcURILocal="/boot/tcg/manifest/switag/" rim:platformManufacturerId="00201234" rim:platformManufacturerStr="Example.com" rim:platformModel="ProductA" rim:platformVersion="01"/>
|
<Meta xmlns:n8060="http://csrc.nist.gov/ns/swid/2015-extensions/1.0" xmlns:rim="https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model" n8060:colloquialVersion="Firmware_2019" n8060:edition="12" n8060:product="ProductA" n8060:revision="r2" rim:PayloadType="direct" rim:bindingSpec="PC Client RIM" rim:bindingSpecVersion="1.2" rim:firmwareManufacturerId="00213022" rim:firmwareManufacturerStr="BIOSVendorA" rim:firmwareModel="A0" rim:firmwareVersion="12" rim:pcURIGlobal="https://Example.com/support/ProductA/" rim:pcURIlocal="/boot/tcg/manifest/switag/" rim:platformManufacturerId="00201234" rim:platformManufacturerStr="Example.com" rim:platformModel="ProductA" rim:platformVersion="01"/>
|
||||||
<Payload>
|
<Payload>
|
||||||
<Directory name="rim">
|
<Directory name="rim">
|
||||||
<File xmlns:SHA256="http://www.w3.org/2001/04/xmlenc#sha256" SHA256:hash="4479ca722623f8c47b703996ced3cbd981b06b1ae8a897db70137e0b7c546848" name="Example.com.BIOS.01.rimel" size="7549"/>
|
<File xmlns:SHA256="http://www.w3.org/2001/04/xmlenc#sha256" SHA256:hash="4479ca722623f8c47b703996ced3cbd981b06b1ae8a897db70137e0b7c546848" name="Example.com.BIOS.01.rimel" size="7549"/>
|
||||||
@ -17,14 +17,14 @@
|
|||||||
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
|
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
|
||||||
</Transforms>
|
</Transforms>
|
||||||
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
|
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
|
||||||
<DigestValue>K3XoBeYvgJBAKl8z273sL7z38qLLVBKLfUPt/gPUzBI=</DigestValue>
|
<DigestValue>DJMc0n3VHHwU+F3HNpiY/l3EMcjRZAQOYlrjhD5v9qE=</DigestValue>
|
||||||
</Reference>
|
</Reference>
|
||||||
</SignedInfo>
|
</SignedInfo>
|
||||||
<SignatureValue>cIl1gPsUyEj2gDv3HTWNFDVxtcBjz4Revxxf2LJejtOXQW8mGepZH8CnvgO7zCAbZYlYUZXjYZ9M
|
<SignatureValue>ojJ6v8ToxLWWekCKmBoZ+Yg2V4MYMPbKB9FjDs/QG/AMP+LKjnb55Z7FSLhC8+CvvShKPAoS9mv1
|
||||||
jONVv8dcsAjVHRnP6YHywFfmSm8LUCwxsfuZQqn5jClqzu5VaqLzBhuJYvCpiEdIDJwDINQuORUB
|
QepwI17NEqbfnC1U4WH0u578A3J6wiHMXIDnIQqKAAXb8v2c/wjMDArzFl8CXmDA7HUDIt+3C4VC
|
||||||
nzul1CWc3Sm1Ms2wjlIq5ctWWJcddhdyIOjl8/oD4EC5E2rOSfNcRMZxldXtie9iinFGVbr0YNE+
|
tA598YY7o0Hf6hK5qO8oWGQxXUKfpUwvtGLxHpbDWYFuVSPa+uk6OTzutt/QyzTERzxyO9Le1i6K
|
||||||
+lQ7hAU+SyV8RMx9tGnnsO8otwV4ddF+OfemcbzWGYBenLs3A8ZqWZyTvWphCgGqDUbOLssYciCC
|
nrpzh4lgHn6EfGs6HR1ffdHQ069q0bE61zDx0VC18nK9DmszW6p6FlMzApiTVW/4PiVt+dSFeVGR
|
||||||
mnYm5QOeh4QcE9H2kqTgZvcyCgPL/hDC7xhyjQ==</SignatureValue>
|
9///OdtxcoBCeofDDFPRyO+s+kY1pXd92Q3nfg==</SignatureValue>
|
||||||
<KeyInfo>
|
<KeyInfo>
|
||||||
<X509Data>
|
<X509Data>
|
||||||
<X509SubjectName>CN=example.RIM.signer,OU=PCClient,O=Example,ST=VA,C=US</X509SubjectName>
|
<X509SubjectName>CN=example.RIM.signer,OU=PCClient,O=Example,ST=VA,C=US</X509SubjectName>
|
||||||
|
@ -6,7 +6,7 @@ validate : validate a signed base rim's signature (NOTE: cryptographic validatio
|
|||||||
|
|
||||||
# Build and package
|
# Build and package
|
||||||
- Install Visual Studio
|
- Install Visual Studio
|
||||||
- The recommended project name is "xml_dsig_tool" so that the resulting executable file will be appropriately named xml_dsig_tool.exe.
|
- The recommended project name is "xml_dsig_tool" so that the resulting executable file will be appropriately named xml_dsig_tool.exe.
|
||||||
- Install NuGet packages:
|
- Install NuGet packages:
|
||||||
- System.CommandLine.2.0.0-beta4 (check "Include Prerelease" next to search bar)
|
- System.CommandLine.2.0.0-beta4 (check "Include Prerelease" next to search bar)
|
||||||
- System.Security.Cryptography.X509Certificates
|
- System.Security.Cryptography.X509Certificates
|
||||||
|
Loading…
x
Reference in New Issue
Block a user