WIP: attach detached signature as a sibling element to a signed base RIM

This commit is contained in:
chubtub 2022-12-06 06:47:24 -05:00
parent 379e1e1ce5
commit 2e4accde0b
2 changed files with 140 additions and 1 deletions

View File

@ -4,6 +4,7 @@ import com.beust.jcommander.JCommander;
import hirs.swid.utils.Commander;
import hirs.swid.utils.CredentialArgumentValidator;
import hirs.swid.utils.TimestampArgumentValidator;
import org.w3c.dom.Document;
import java.util.List;
@ -118,7 +119,28 @@ public class Main {
"are required, or the default key (-d) must be indicated.");
System.exit(1);
}
gateway.generateSwidTag(commander.getOutFile());
if (!commander.getSignFile().isEmpty()) {
Document doc = gateway.signXMLDocument(commander.getSignFile());
gateway.writeSwidTagFile(doc, "");
} else {
String createType = commander.getCreateType().toUpperCase();
String attributesFile = commander.getAttributesFile();
if (createType.equals("BASE")) {
if (!attributesFile.isEmpty()) {
gateway.setAttributesFile(attributesFile);
}
if (!rimEventLogFile.isEmpty()) {
gateway.setRimEventLog(rimEventLogFile);
} else {
System.out.println("Error: a support RIM is required!");
System.exit(1);
}
} else {
System.out.println("No create type given, nothing to do");
System.exit(1);
}
gateway.generateSwidTag(commander.getOutFile());
}
}
}
}

View File

@ -10,6 +10,10 @@ import hirs.swid.xjc.SoftwareIdentity;
import hirs.swid.xjc.SoftwareMeta;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import javax.json.Json;
import javax.json.JsonException;
@ -41,6 +45,7 @@ import javax.xml.crypto.dsig.keyinfo.X509Data;
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
@ -57,6 +62,7 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.math.BigInteger;
import java.nio.file.Files;
import java.nio.file.Paths;
@ -549,6 +555,117 @@ public class SwidTagGateway {
}
}
private void printXmlAttributes(Node node) {
org.w3c.dom.NamedNodeMap attributes = node.getAttributes();
if (attributes.getLength() <= 0) {
System.out.println("No attributes in this node");
} else {
for (int i = 0; i < attributes.getLength(); i++) {
System.out.println("SoftwareIdentity attribute: " + attributes.item(i).getNodeName());
}
}
}
public Document signXMLDocument(String signFile) {
//Read signFile contents
String xmlToSign = "";
try {
byte[] fileContents = Files.readAllBytes(Paths.get(signFile));
xmlToSign = new String(fileContents); //safe to assume default charset??
} catch (IOException e) {
System.out.println("Error reading contents of " + signFile);
System.exit(1);
}
//Parse SoftwareIdentity id
String tagId = "";
Document swidTag = null;
Element softwareIdentity = null;
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
swidTag = db.parse(new InputSource(new StringReader(xmlToSign)));
softwareIdentity = (Element) swidTag.getElementsByTagName(
SwidTagConstants.SOFTWARE_IDENTITY).item(0);
tagId = softwareIdentity.getAttributes()
.getNamedItem(SwidTagConstants.TAGID).getNodeValue();
//How to sign without an Id attribute?
} catch (ParserConfigurationException e) {
System.out.println("Error instantiating DocumentBuilder object: " + e.getMessage());
System.exit(1);
} catch (IOException | SAXException e) {
System.out.println("Error parsing XML from " + signFile);
}
//Create signature with a reference to SoftwareIdentity id
System.out.println("Referencing SoftwareIdentity with tagID " + tagId);
Document detachedSignature = null;
try {
XMLSignatureFactory sigFactory = XMLSignatureFactory.getInstance("DOM");
Reference ref = sigFactory.newReference("#" + tagId,
sigFactory.newDigestMethod(DigestMethod.SHA256, null));
SignedInfo signedInfo = sigFactory.newSignedInfo(
sigFactory.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE,
(C14NMethodParameterSpec) null),
sigFactory.newSignatureMethod(SwidTagConstants.SIGNATURE_ALGORITHM_RSA_SHA256,
null),
Collections.singletonList(ref)
);
List<XMLStructure> keyInfoElements = new ArrayList<XMLStructure>();
KeyInfoFactory kiFactory = sigFactory.getKeyInfoFactory();
PrivateKey privateKey;
CredentialParser cp = new CredentialParser();
if (defaultCredentials) {
cp.parseJKSCredentials(jksTruststoreFile);
privateKey = cp.getPrivateKey();
KeyName keyName = kiFactory.newKeyName(cp.getCertificateSubjectKeyIdentifier());
keyInfoElements.add(keyName);
} else {
cp.parsePEMCredentials(pemCertificateFile, pemPrivateKeyFile);
X509Certificate certificate = cp.getCertificate();
privateKey = cp.getPrivateKey();
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);
detachedSignature = DocumentBuilderFactory.newInstance()
.newDocumentBuilder().newDocument();
detachedSignature.appendChild(detachedSignature.createElement("root"));
DOMSignContext context = new DOMSignContext(privateKey,
detachedSignature.getDocumentElement());
XMLSignature signature = sigFactory.newXMLSignature(signedInfo, keyinfo);
signature.sign(context);
System.out.println("Detached signature: " + detachedSignature);
} catch (InvalidAlgorithmParameterException e) {
System.out.println("Digest method parameters are invalid: " + e.getMessage());
} catch (NoSuchAlgorithmException e) {
System.out.println("The digest algorithm could not be found: " + e.getMessage());
} catch (IOException e) {
System.out.println("Error getting SKID from signing credentials: " + e.getMessage());
} catch (ParserConfigurationException e) {
System.out.println("Error creating new document object: " + e.getMessage());
} catch (MarshalException | XMLSignatureException e) {
System.out.println("Error while signing SoftwareIdentity");
e.printStackTrace();
} catch (KeyException e) {
System.out.println("Public key algorithm not recognized or supported: "
+ e.getMessage());
} catch (Exception e) {
e.printStackTrace();
}
return swidTag;
}
/**
* This method signs a SoftwareIdentity with an xmldsig in compatibility mode.
* Current assumptions: digest method SHA256, signature method SHA256, enveloped signature