mirror of
https://github.com/nsacyber/HIRS.git
synced 2024-12-20 05:28:22 +00:00
issue_844: Made updates using the checkstyle configuration to various files. Have also made some config changes to the checkstyle.xml file.
This commit is contained in:
parent
2dcdc15c54
commit
b80d7221c1
@ -23,14 +23,16 @@ import java.util.Properties;
|
|||||||
public class BannerConfiguration {
|
public class BannerConfiguration {
|
||||||
|
|
||||||
private static final Path BANNER_PROPERTIES_PATH = FileSystems.getDefault()
|
private static final Path BANNER_PROPERTIES_PATH = FileSystems.getDefault()
|
||||||
.getPath("/opt/tomcat/webapps/HIRS_AttestationCAPortal", "WEB-INF", "classes", "banner.properties");
|
.getPath("/opt/tomcat/webapps/HIRS_AttestationCAPortal",
|
||||||
|
"WEB-INF", "classes", "banner.properties");
|
||||||
|
|
||||||
private static final String BANNER_COLOR = "banner.color";
|
private static final String BANNER_COLOR = "banner.color";
|
||||||
private static final String BANNER_STRING = "banner.string";
|
private static final String BANNER_STRING = "banner.string";
|
||||||
private static final String BANNER_DYNAMIC = "banner.dynamic";
|
private static final String BANNER_DYNAMIC = "banner.dynamic";
|
||||||
private static final String LEFT_CONTENT = "left.content";
|
private static final String LEFT_CONTENT = "left.content";
|
||||||
private static final String RIGHT_CONTENT = "right.content";
|
private static final String RIGHT_CONTENT = "right.content";
|
||||||
|
private final ArrayList<String> leftContent = new ArrayList<>();
|
||||||
|
private final ArrayList<String> rightContent = new ArrayList<>();
|
||||||
@Getter
|
@Getter
|
||||||
private String bannerColor = "";
|
private String bannerColor = "";
|
||||||
@Getter
|
@Getter
|
||||||
@ -38,21 +40,18 @@ public class BannerConfiguration {
|
|||||||
@Getter
|
@Getter
|
||||||
private String bannerDynamic = "";
|
private String bannerDynamic = "";
|
||||||
|
|
||||||
private final ArrayList<String> leftContent = new ArrayList<>();
|
|
||||||
private final ArrayList<String> rightContent = new ArrayList<>();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Banner Configuration default constructor.
|
* Banner Configuration default constructor.
|
||||||
* Verify if the file exist, if it does it will get all the
|
* Verify if the file exist, if it does it will get all the
|
||||||
* properties values and save them on the class.
|
* properties values and save them on the class.
|
||||||
*
|
*
|
||||||
* @throws IOException the banner level for the web site.
|
* @throws IOException the banner level for the website.
|
||||||
*/
|
*/
|
||||||
public BannerConfiguration() throws IOException {
|
public BannerConfiguration() throws IOException {
|
||||||
if (!Files.exists(BANNER_PROPERTIES_PATH)) {
|
if (!Files.exists(BANNER_PROPERTIES_PATH)) {
|
||||||
log.info(String.format(
|
log.info(String.format(
|
||||||
"No file found at %s. Banner will not display.",
|
"No file found at %s. Banner will not display.",
|
||||||
BANNER_PROPERTIES_PATH.toString()
|
BANNER_PROPERTIES_PATH
|
||||||
));
|
));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -69,8 +68,8 @@ public class BannerConfiguration {
|
|||||||
/**
|
/**
|
||||||
* This method applies any dynamically configuration found in the properties file,
|
* This method applies any dynamically configuration found in the properties file,
|
||||||
* if it exists.
|
* if it exists.
|
||||||
* @param bannerProps
|
*
|
||||||
* @return the banner level for the web site.
|
* @param bannerProps banner props
|
||||||
*/
|
*/
|
||||||
private void setBannerProperties(final Properties bannerProps) {
|
private void setBannerProperties(final Properties bannerProps) {
|
||||||
|
|
||||||
@ -103,10 +102,7 @@ public class BannerConfiguration {
|
|||||||
* @return if the banner was set.
|
* @return if the banner was set.
|
||||||
*/
|
*/
|
||||||
public Boolean getHasBanner() {
|
public Boolean getHasBanner() {
|
||||||
if (!bannerColor.isEmpty() || !bannerString.isEmpty()) {
|
return !bannerColor.isEmpty() || !bannerString.isEmpty();
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -7,22 +7,24 @@ import java.math.BigInteger;
|
|||||||
*/
|
*/
|
||||||
public final class HexUtils {
|
public final class HexUtils {
|
||||||
|
|
||||||
/**
|
|
||||||
* Default private constructor so checkstyles doesn't complain
|
|
||||||
*/
|
|
||||||
private HexUtils() { }
|
|
||||||
/**
|
/**
|
||||||
* The mathematical base for the hexadecimal representation.
|
* The mathematical base for the hexadecimal representation.
|
||||||
*/
|
*/
|
||||||
public static final int HEX_BASIS = 16;
|
public static final int HEX_BASIS = 16;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An integer representation of the byte 0xff or 255.
|
* An integer representation of the byte 0xff or 255.
|
||||||
*/
|
*/
|
||||||
public static final int FF_BYTE = 0xff;
|
public static final int FF_BYTE = 0xff;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default private constructor so checkstyles doesn't complain.
|
||||||
|
*/
|
||||||
|
private HexUtils() {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a binary hex string to a byte array.
|
* Converts a binary hex string to a byte array.
|
||||||
|
*
|
||||||
* @param s string to convert
|
* @param s string to convert
|
||||||
* @return byte array representation of s
|
* @return byte array representation of s
|
||||||
*/
|
*/
|
||||||
@ -40,6 +42,7 @@ public final class HexUtils {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a byte array to a hex represented binary string.
|
* Converts a byte array to a hex represented binary string.
|
||||||
|
*
|
||||||
* @param b byte array to convert
|
* @param b byte array to convert
|
||||||
* @return hex string representation of array
|
* @return hex string representation of array
|
||||||
*/
|
*/
|
||||||
@ -58,6 +61,7 @@ public final class HexUtils {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts an individual hex string to an integer.
|
* Converts an individual hex string to an integer.
|
||||||
|
*
|
||||||
* @param s an individual hex string
|
* @param s an individual hex string
|
||||||
* @return an integer representation of a hex string
|
* @return an integer representation of a hex string
|
||||||
*/
|
*/
|
||||||
@ -68,9 +72,10 @@ public final class HexUtils {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes a byte array returns a subset of the array.
|
* Takes a byte array returns a subset of the array.
|
||||||
* @param b the array to take a subset of
|
*
|
||||||
|
* @param b the array to take a subset of
|
||||||
* @param start the first index to copy
|
* @param start the first index to copy
|
||||||
* @param end the last index to copy (inclusive)
|
* @param end the last index to copy (inclusive)
|
||||||
* @return a new array of bytes from start to end
|
* @return a new array of bytes from start to end
|
||||||
*/
|
*/
|
||||||
public static byte[] subarray(final byte[] b, final int start, final int end) {
|
public static byte[] subarray(final byte[] b, final int start, final int end) {
|
||||||
@ -81,20 +86,22 @@ public final class HexUtils {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes in a byte array and reverses the order.
|
* Takes in a byte array and reverses the order.
|
||||||
* @param in byte array to reverse
|
*
|
||||||
|
* @param in byte array to reverse
|
||||||
* @return reversed byte array
|
* @return reversed byte array
|
||||||
*/
|
*/
|
||||||
public static byte[] leReverseByte(final byte[] in) {
|
public static byte[] leReverseByte(final byte[] in) {
|
||||||
byte[] finished = new byte[in.length];
|
byte[] finished = new byte[in.length];
|
||||||
for (int i = 0; i < finished.length; i++) {
|
for (int i = 0; i < finished.length; i++) {
|
||||||
finished[i] = in[(in.length - 1) - i];
|
finished[i] = in[(in.length - 1) - i];
|
||||||
}
|
}
|
||||||
return finished;
|
return finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes in a byte array and reverses the order then converts to an int.
|
* Takes in a byte array and reverses the order then converts to an int.
|
||||||
* @param in byte array to reverse
|
*
|
||||||
|
* @param in byte array to reverse
|
||||||
* @return integer that represents the reversed byte array
|
* @return integer that represents the reversed byte array
|
||||||
*/
|
*/
|
||||||
public static int leReverseInt(final byte[] in) {
|
public static int leReverseInt(final byte[] in) {
|
||||||
@ -104,12 +111,13 @@ public final class HexUtils {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes in a byte array of 4 bytes and returns a long.
|
* Takes in a byte array of 4 bytes and returns a long.
|
||||||
* @param bytes byte array to convert
|
*
|
||||||
|
* @param bytes byte array to convert
|
||||||
* @return long representation of the bytes
|
* @return long representation of the bytes
|
||||||
*/
|
*/
|
||||||
public static long bytesToLong(final byte[] bytes) {
|
public static long bytesToLong(final byte[] bytes) {
|
||||||
BigInteger lValue = new BigInteger(bytes);
|
BigInteger lValue = new BigInteger(bytes);
|
||||||
|
|
||||||
return lValue.abs().longValue();
|
return lValue.abs().longValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,16 +21,17 @@ import java.nio.file.Path;
|
|||||||
public final class JsonUtils {
|
public final class JsonUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default private constructor so checkstyles doesn't complain
|
* Default private constructor so checkstyles doesn't complain.
|
||||||
*/
|
*/
|
||||||
private JsonUtils() { }
|
private JsonUtils() {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Getter for the JSON Object that is associated with the elementName value
|
* Getter for the JSON Object that is associated with the elementName value
|
||||||
* mapped in the associated JSON file.
|
* mapped in the associated JSON file.
|
||||||
* Default {@link java.nio.charset.Charset} is UTF 8
|
* Default {@link java.nio.charset.Charset} is UTF 8
|
||||||
*
|
*
|
||||||
* @param jsonPath the object holding the location of the file to parse.
|
* @param jsonPath the object holding the location of the file to parse.
|
||||||
* @param elementName the specific object to pull from the file
|
* @param elementName the specific object to pull from the file
|
||||||
* @return a JSON object
|
* @return a JSON object
|
||||||
*/
|
*/
|
||||||
@ -44,9 +45,9 @@ public final class JsonUtils {
|
|||||||
* mapped in the associated JSON file.
|
* mapped in the associated JSON file.
|
||||||
* Default {@link java.nio.charset.Charset} is UTF 8
|
* Default {@link java.nio.charset.Charset} is UTF 8
|
||||||
*
|
*
|
||||||
* @param jsonPath the object holding the location of the file to parse.
|
* @param jsonPath the object holding the location of the file to parse.
|
||||||
* @param elementName the specific object to pull from the file
|
* @param elementName the specific object to pull from the file
|
||||||
* @param charset the character set to use
|
* @param charset the character set to use
|
||||||
* @return a JSON object
|
* @return a JSON object
|
||||||
*/
|
*/
|
||||||
public static JsonObject getSpecificJsonObject(final Path jsonPath,
|
public static JsonObject getSpecificJsonObject(final Path jsonPath,
|
||||||
@ -77,7 +78,7 @@ public final class JsonUtils {
|
|||||||
* Getter for the JSON Object that is mapped in the associated JSON file.
|
* Getter for the JSON Object that is mapped in the associated JSON file.
|
||||||
*
|
*
|
||||||
* @param jsonPath the object holding the location of the file to parse.
|
* @param jsonPath the object holding the location of the file to parse.
|
||||||
* @param charset the character set to use
|
* @param charset the character set to use
|
||||||
* @return a JSON object
|
* @return a JSON object
|
||||||
*/
|
*/
|
||||||
public static JsonObject getJsonObject(final Path jsonPath, final Charset charset) {
|
public static JsonObject getJsonObject(final Path jsonPath, final Charset charset) {
|
||||||
@ -85,7 +86,7 @@ public final class JsonUtils {
|
|||||||
JsonObject jsonObject = new JsonObject();
|
JsonObject jsonObject = new JsonObject();
|
||||||
|
|
||||||
if (Files.notExists(jsonPath)) {
|
if (Files.notExists(jsonPath)) {
|
||||||
log.warn(String.format("No file found at %s.", jsonPath.toString()));
|
log.warn("No file found at {}.", jsonPath.toString());
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
InputStream inputStream = new FileInputStream(jsonPath.toString());
|
InputStream inputStream = new FileInputStream(jsonPath.toString());
|
||||||
@ -106,7 +107,7 @@ public final class JsonUtils {
|
|||||||
* Default {@link java.nio.charset.Charset} is UTF 8
|
* Default {@link java.nio.charset.Charset} is UTF 8
|
||||||
*
|
*
|
||||||
* @param jsonFilename the object holding the name of the file in classpath to parse.
|
* @param jsonFilename the object holding the name of the file in classpath to parse.
|
||||||
* @param elementName the specific object to pull from the file
|
* @param elementName the specific object to pull from the file
|
||||||
* @return a JSON object
|
* @return a JSON object
|
||||||
*/
|
*/
|
||||||
public static JsonObject getSpecificJsonObject(final String jsonFilename, final String elementName) {
|
public static JsonObject getSpecificJsonObject(final String jsonFilename, final String elementName) {
|
||||||
@ -120,8 +121,8 @@ public final class JsonUtils {
|
|||||||
* Default {@link java.nio.charset.Charset} is UTF 8
|
* Default {@link java.nio.charset.Charset} is UTF 8
|
||||||
*
|
*
|
||||||
* @param jsonFilename the object holding the name of the file in classpath to parse.
|
* @param jsonFilename the object holding the name of the file in classpath to parse.
|
||||||
* @param elementName the specific object to pull from the file
|
* @param elementName the specific object to pull from the file
|
||||||
* @param charset the character set to use
|
* @param charset the character set to use
|
||||||
* @return a JSON object
|
* @return a JSON object
|
||||||
*/
|
*/
|
||||||
public static JsonObject getSpecificJsonObject(final String jsonFilename,
|
public static JsonObject getSpecificJsonObject(final String jsonFilename,
|
||||||
@ -152,7 +153,7 @@ public final class JsonUtils {
|
|||||||
* Getter for the JSON Object that is mapped in the associated JSON file.
|
* Getter for the JSON Object that is mapped in the associated JSON file.
|
||||||
*
|
*
|
||||||
* @param jsonFilename the object holding the name of the file in classpath to parse.
|
* @param jsonFilename the object holding the name of the file in classpath to parse.
|
||||||
* @param charset the character set to use
|
* @param charset the character set to use
|
||||||
* @return a JSON object
|
* @return a JSON object
|
||||||
*/
|
*/
|
||||||
public static JsonObject getJsonObject(final String jsonFilename, final Charset charset) {
|
public static JsonObject getJsonObject(final String jsonFilename, final Charset charset) {
|
||||||
|
@ -25,29 +25,24 @@ import java.util.List;
|
|||||||
@Log4j2
|
@Log4j2
|
||||||
public final class PciIds {
|
public final class PciIds {
|
||||||
|
|
||||||
/**
|
|
||||||
* Default private constructor so checkstyles doesn't complain
|
|
||||||
*/
|
|
||||||
private PciIds() { }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This pci ids file can be in different places on different distributions.
|
* This pci ids file can be in different places on different distributions.
|
||||||
*/
|
*/
|
||||||
public static final List<String> PCI_IDS_PATH =
|
public static final List<String> PCI_IDS_PATH =
|
||||||
Collections.unmodifiableList(new ArrayList<>() {
|
Collections.unmodifiableList(new ArrayList<>() {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
{
|
{
|
||||||
add("/usr/share/hwdata/pci.ids");
|
add("/usr/share/hwdata/pci.ids");
|
||||||
add("/usr/share/misc/pci.ids");
|
add("/usr/share/misc/pci.ids");
|
||||||
add("/tmp/pci.ids");
|
add("/tmp/pci.ids");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The PCI IDs Database object.
|
* The PCI IDs Database object.
|
||||||
*
|
* <p>
|
||||||
* This only needs to be loaded one time.
|
* This only needs to be loaded one time.
|
||||||
*
|
* <p>
|
||||||
* The pci ids library protects the data inside the object by making it immutable.
|
* The pci ids library protects the data inside the object by making it immutable.
|
||||||
*/
|
*/
|
||||||
public static final PciIdsDatabase DB = new PciIdsDatabase();
|
public static final PciIdsDatabase DB = new PciIdsDatabase();
|
||||||
@ -65,7 +60,7 @@ public final class PciIds {
|
|||||||
if (dbFile != null) {
|
if (dbFile != null) {
|
||||||
InputStream is = null;
|
InputStream is = null;
|
||||||
try {
|
try {
|
||||||
is = new FileInputStream(new File(dbFile));
|
is = new FileInputStream(dbFile);
|
||||||
DB.loadStream(is);
|
DB.loadStream(is);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// DB will not be ready, hardware IDs will not be translated
|
// DB will not be ready, hardware IDs will not be translated
|
||||||
@ -83,9 +78,16 @@ public final class PciIds {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default private constructor so checkstyles doesn't complain.
|
||||||
|
*/
|
||||||
|
private PciIds() {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Look up the vendor name from the PCI IDs list, if the input string contains an ID.
|
* Look up the vendor name from the PCI IDs list, if the input string contains an ID.
|
||||||
* If any part of this fails, return the original manufacturer value.
|
* If any part of this fails, return the original manufacturer value.
|
||||||
|
*
|
||||||
* @param refManufacturer DERUTF8String, likely from a ComponentIdentifier
|
* @param refManufacturer DERUTF8String, likely from a ComponentIdentifier
|
||||||
* @return DERUTF8String with the discovered vendor name, or the original manufacturer value.
|
* @return DERUTF8String with the discovered vendor name, or the original manufacturer value.
|
||||||
*/
|
*/
|
||||||
@ -103,6 +105,7 @@ public final class PciIds {
|
|||||||
/**
|
/**
|
||||||
* Look up the vendor name from the PCI IDs list, if the input string contains an ID.
|
* Look up the vendor name from the PCI IDs list, if the input string contains an ID.
|
||||||
* If any part of this fails, return the original manufacturer value.
|
* If any part of this fails, return the original manufacturer value.
|
||||||
|
*
|
||||||
* @param refManufacturer String, likely from a ComponentResult
|
* @param refManufacturer String, likely from a ComponentResult
|
||||||
* @return String with the discovered vendor name, or the original manufacturer value.
|
* @return String with the discovered vendor name, or the original manufacturer value.
|
||||||
*/
|
*/
|
||||||
@ -121,8 +124,9 @@ public final class PciIds {
|
|||||||
* Look up the device name from the PCI IDs list, if the input strings contain IDs.
|
* Look up the device name from the PCI IDs list, if the input strings contain IDs.
|
||||||
* The Device lookup requires the Vendor ID AND the Device ID to be valid values.
|
* The Device lookup requires the Vendor ID AND the Device ID to be valid values.
|
||||||
* If any part of this fails, return the original model value.
|
* If any part of this fails, return the original model value.
|
||||||
|
*
|
||||||
* @param refManufacturer ASN1UTF8String, likely from a ComponentIdentifier
|
* @param refManufacturer ASN1UTF8String, likely from a ComponentIdentifier
|
||||||
* @param refModel ASN1UTF8String, likely from a ComponentIdentifier
|
* @param refModel ASN1UTF8String, likely from a ComponentIdentifier
|
||||||
* @return ASN1UTF8String with the discovered device name, or the original model value.
|
* @return ASN1UTF8String with the discovered device name, or the original model value.
|
||||||
*/
|
*/
|
||||||
public static ASN1UTF8String translateDevice(final ASN1UTF8String refManufacturer,
|
public static ASN1UTF8String translateDevice(final ASN1UTF8String refManufacturer,
|
||||||
@ -146,8 +150,9 @@ public final class PciIds {
|
|||||||
* Look up the device name from the PCI IDs list, if the input strings contain IDs.
|
* Look up the device name from the PCI IDs list, if the input strings contain IDs.
|
||||||
* The Device lookup requires the Vendor ID AND the Device ID to be valid values.
|
* The Device lookup requires the Vendor ID AND the Device ID to be valid values.
|
||||||
* If any part of this fails, return the original model value.
|
* If any part of this fails, return the original model value.
|
||||||
|
*
|
||||||
* @param refManufacturer String, likely from a ComponentResult
|
* @param refManufacturer String, likely from a ComponentResult
|
||||||
* @param refModel String, likely from a ComponentResult
|
* @param refModel String, likely from a ComponentResult
|
||||||
* @return String with the discovered device name, or the original model value.
|
* @return String with the discovered device name, or the original model value.
|
||||||
*/
|
*/
|
||||||
public static String translateDevice(final String refManufacturer,
|
public static String translateDevice(final String refManufacturer,
|
||||||
@ -169,24 +174,39 @@ public final class PciIds {
|
|||||||
/**
|
/**
|
||||||
* Look up the device class name from the PCI IDs list, if the input string contains an ID.
|
* Look up the device class name from the PCI IDs list, if the input string contains an ID.
|
||||||
* If any part of this fails, return the original manufacturer value.
|
* If any part of this fails, return the original manufacturer value.
|
||||||
|
*
|
||||||
* @param refClassCode String, formatted as 2 characters (1 byte) for each of the 3 categories
|
* @param refClassCode String, formatted as 2 characters (1 byte) for each of the 3 categories
|
||||||
* Example "010802":
|
* Example "010802":
|
||||||
* Class: "01"
|
* Class: "01"
|
||||||
* Subclass: "08"
|
* Subclass: "08"
|
||||||
* Programming Interface: "02"
|
* Programming Interface: "02"
|
||||||
* @return List<String> 3-element list with the class code
|
* @return List<String> 3-element list with the class code
|
||||||
* 1st element: human-readable description of Class
|
* 1st element: human-readable description of Class
|
||||||
* 2nd element: human-readable description of Subclass
|
* 2nd element: human-readable description of Subclass
|
||||||
* 3rd element: human-readable description of Programming Interface
|
* 3rd element: human-readable description of Programming Interface
|
||||||
*/
|
*/
|
||||||
public static List<String> translateDeviceClass(final String refClassCode) {
|
public static List<String> translateDeviceClass(final String refClassCode) {
|
||||||
List<String> translatedClassCode = new ArrayList<>();
|
List<String> translatedClassCode = new ArrayList<>();
|
||||||
|
|
||||||
String classCode = refClassCode;
|
String classCode = refClassCode;
|
||||||
if (classCode != null && classCode.trim().matches("^[0-9A-Fa-f]{6}$")) {
|
if (classCode != null && classCode.trim().matches("^[0-9A-Fa-f]{6}$")) {
|
||||||
String deviceClass = classCode.substring(0, 2).toLowerCase();
|
final int startIndexOfDeviceClass = 0;
|
||||||
String deviceSubclass = classCode.substring(2, 4).toLowerCase();
|
final int endIndexOfDeviceClass = 2;
|
||||||
String programInterface = classCode.substring(4, 6).toLowerCase();
|
String deviceClass =
|
||||||
|
classCode.substring(startIndexOfDeviceClass, endIndexOfDeviceClass).toLowerCase();
|
||||||
|
|
||||||
|
final int startIndexOfDeviceSubclass = 2;
|
||||||
|
final int endIndexOfDeviceSubclass = 4;
|
||||||
|
String deviceSubclass =
|
||||||
|
classCode.substring(startIndexOfDeviceSubclass, endIndexOfDeviceSubclass)
|
||||||
|
.toLowerCase();
|
||||||
|
|
||||||
|
final int startIndexOfProgramInterface = 4;
|
||||||
|
final int endIndexOfProgramInterface = 6;
|
||||||
|
final String programInterface =
|
||||||
|
classCode.substring(startIndexOfProgramInterface, endIndexOfProgramInterface)
|
||||||
|
.toLowerCase();
|
||||||
|
|
||||||
translatedClassCode.add(deviceClass);
|
translatedClassCode.add(deviceClass);
|
||||||
translatedClassCode.add(deviceSubclass);
|
translatedClassCode.add(deviceSubclass);
|
||||||
translatedClassCode.add(programInterface);
|
translatedClassCode.add(programInterface);
|
||||||
|
@ -18,15 +18,31 @@ import java.util.Map;
|
|||||||
@ToString
|
@ToString
|
||||||
public class SwidResource {
|
public class SwidResource {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final boolean validFileSize = false;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
private String name, size, hashValue;
|
private String name;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private String rimFormat, rimType, rimUriGlobal;
|
@Setter
|
||||||
// private TpmWhiteListBaseline tpmWhiteList;
|
private String size;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private String hashValue;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private String rimFormat;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private String rimType;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private String rimUriGlobal;
|
||||||
|
// private TpmWhiteListBaseline tpmWhiteList;
|
||||||
private DigestAlgorithm digest = DigestAlgorithm.SHA1;
|
private DigestAlgorithm digest = DigestAlgorithm.SHA1;
|
||||||
@Getter
|
|
||||||
private boolean validFileSize = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default constructor.
|
* Default constructor.
|
||||||
@ -43,7 +59,7 @@ public class SwidResource {
|
|||||||
/**
|
/**
|
||||||
* The main constructor that processes a {@code hirs.utils.xjc.File}.
|
* The main constructor that processes a {@code hirs.utils.xjc.File}.
|
||||||
*
|
*
|
||||||
* @param file {@link File}
|
* @param file {@link File}
|
||||||
* @param digest algorithm associated with pcr values
|
* @param digest algorithm associated with pcr values
|
||||||
*/
|
*/
|
||||||
public SwidResource(final File file, final DigestAlgorithm digest) {
|
public SwidResource(final File file, final DigestAlgorithm digest) {
|
||||||
|
@ -15,8 +15,8 @@ import java.util.regex.Pattern;
|
|||||||
* <p>
|
* <p>
|
||||||
* Two classes were made to facilitate persisting them with Hibernate in different ways.
|
* Two classes were made to facilitate persisting them with Hibernate in different ways.
|
||||||
* To persist non-nullable entries in an embedded collection, use {@link hirs.utils.digest.Digest} (see
|
* To persist non-nullable entries in an embedded collection, use {@link hirs.utils.digest.Digest} (see
|
||||||
* {@link TPMBaseline} for reference.) To persist nullable entries, use {@link hirs.utils.digest.OptionalDigest}
|
* {@link TPMBaseline} for reference.) To persist nullable entries,
|
||||||
* (see {@link ImaBlacklistRecord} for reference.)
|
* use {@link hirs.utils.digest.OptionalDigest} (see {@link ImaBlacklistRecord} for reference.)
|
||||||
*/
|
*/
|
||||||
@Log4j2
|
@Log4j2
|
||||||
public abstract class AbstractDigest {
|
public abstract class AbstractDigest {
|
||||||
@ -45,30 +45,6 @@ public abstract class AbstractDigest {
|
|||||||
*/
|
*/
|
||||||
public static final int SHA512_DIGEST_LENGTH = 64;
|
public static final int SHA512_DIGEST_LENGTH = 64;
|
||||||
|
|
||||||
/**
|
|
||||||
* Ensures the given algorithm type and digest byte array represent a valid digest.
|
|
||||||
* This includes ensuring they are both not null or empty and ensuring that the length of the
|
|
||||||
* digest matches the expected amount of data for the given algorithm.
|
|
||||||
*
|
|
||||||
* @param algorithm a digest algorithm
|
|
||||||
* @param digest the digest computed by this algorithm
|
|
||||||
* @throws IllegalArgumentException if the provided input does not represent a valid digest
|
|
||||||
*/
|
|
||||||
void validateInput(final DigestAlgorithm algorithm, final byte[] digest)
|
|
||||||
throws IllegalArgumentException {
|
|
||||||
if (algorithm == null) {
|
|
||||||
throw new IllegalArgumentException("Algorithm must not be null");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ArrayUtils.isEmpty(digest)) {
|
|
||||||
throw new IllegalArgumentException("Digest must have at least one byte");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (digest.length != algorithm.getLengthInBytes()) {
|
|
||||||
throw new AbstractDigest.IllegalDigestLength(algorithm, digest);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method will help class determine the algorithm associated with the
|
* This method will help class determine the algorithm associated with the
|
||||||
* pcr values given.
|
* pcr values given.
|
||||||
@ -114,6 +90,61 @@ public abstract class AbstractDigest {
|
|||||||
return DigestAlgorithm.UNSPECIFIED;
|
return DigestAlgorithm.UNSPECIFIED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a {@link DigestAlgorithm} from a String returned by {@link AbstractDigest#toString()}.
|
||||||
|
*
|
||||||
|
* @param digest the digest string as computed above
|
||||||
|
* @return the DigestAlgorithm component of the String
|
||||||
|
*/
|
||||||
|
static DigestAlgorithm algorithmFromString(final String digest) {
|
||||||
|
return DigestAlgorithm.findByString(matchString(digest).group(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a digest from a String returned by {@link AbstractDigest#toString()}.
|
||||||
|
*
|
||||||
|
* @param digest the digest string as computed above
|
||||||
|
* @return the byte array representing the actual digest
|
||||||
|
*/
|
||||||
|
static byte[] digestFromString(final String digest) {
|
||||||
|
return DatatypeConverter.parseHexBinary(matchString(digest).group(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Matcher matchString(final String digest) {
|
||||||
|
Pattern digestPattern = Pattern.compile("(.*) - 0x(.*)");
|
||||||
|
Matcher matcher = digestPattern.matcher(digest);
|
||||||
|
if (!matcher.matches()) {
|
||||||
|
String message = String.format("String \"%s\" did not match pattern \"%s\"", digest,
|
||||||
|
digestPattern);
|
||||||
|
throw new IllegalArgumentException(message);
|
||||||
|
}
|
||||||
|
return matcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensures the given algorithm type and digest byte array represent a valid digest.
|
||||||
|
* This includes ensuring they are both not null or empty and ensuring that the length of the
|
||||||
|
* digest matches the expected amount of data for the given algorithm.
|
||||||
|
*
|
||||||
|
* @param algorithm a digest algorithm
|
||||||
|
* @param digest the digest computed by this algorithm
|
||||||
|
* @throws IllegalArgumentException if the provided input does not represent a valid digest
|
||||||
|
*/
|
||||||
|
void validateInput(final DigestAlgorithm algorithm, final byte[] digest)
|
||||||
|
throws IllegalArgumentException {
|
||||||
|
if (algorithm == null) {
|
||||||
|
throw new IllegalArgumentException("Algorithm must not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ArrayUtils.isEmpty(digest)) {
|
||||||
|
throw new IllegalArgumentException("Digest must have at least one byte");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (digest.length != algorithm.getLengthInBytes()) {
|
||||||
|
throw new AbstractDigest.IllegalDigestLength(algorithm, digest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the <code>DigestAlgorithm</code> that identifies which hash
|
* Retrieves the <code>DigestAlgorithm</code> that identifies which hash
|
||||||
* function generated the digest.
|
* function generated the digest.
|
||||||
@ -140,6 +171,7 @@ public abstract class AbstractDigest {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Compares this digest's hash with another digest's hash.
|
* Compares this digest's hash with another digest's hash.
|
||||||
|
*
|
||||||
* @param otherDigest a Digest to compare to.
|
* @param otherDigest a Digest to compare to.
|
||||||
* @return the comparison result type.
|
* @return the comparison result type.
|
||||||
*/
|
*/
|
||||||
@ -155,37 +187,6 @@ public abstract class AbstractDigest {
|
|||||||
return DigestComparisonResultType.MISMATCH;
|
return DigestComparisonResultType.MISMATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses a {@link DigestAlgorithm} from a String returned by {@link AbstractDigest#toString()}.
|
|
||||||
*
|
|
||||||
* @param digest the digest string as computed above
|
|
||||||
* @return the DigestAlgorithm component of the String
|
|
||||||
*/
|
|
||||||
static DigestAlgorithm algorithmFromString(final String digest) {
|
|
||||||
return DigestAlgorithm.findByString(matchString(digest).group(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses a digest from a String returned by {@link AbstractDigest#toString()}.
|
|
||||||
*
|
|
||||||
* @param digest the digest string as computed above
|
|
||||||
* @return the byte array representing the actual digest
|
|
||||||
*/
|
|
||||||
static byte[] digestFromString(final String digest) {
|
|
||||||
return DatatypeConverter.parseHexBinary(matchString(digest).group(2));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Matcher matchString(final String digest) {
|
|
||||||
Pattern digestPattern = Pattern.compile("(.*) - 0x(.*)");
|
|
||||||
Matcher matcher = digestPattern.matcher(digest);
|
|
||||||
if (!matcher.matches()) {
|
|
||||||
String message = String.format("String \"%s\" did not match pattern \"%s\"", digest,
|
|
||||||
digestPattern.toString());
|
|
||||||
throw new IllegalArgumentException(message);
|
|
||||||
}
|
|
||||||
return matcher;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final int hashCode() {
|
public final int hashCode() {
|
||||||
final int prime = 31;
|
final int prime = 31;
|
||||||
@ -201,21 +202,15 @@ public abstract class AbstractDigest {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (obj == null || !(obj instanceof AbstractDigest)) {
|
if (obj == null || !(obj instanceof AbstractDigest other)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractDigest other = (AbstractDigest) obj;
|
|
||||||
|
|
||||||
if (getAlgorithm() != other.getAlgorithm()) {
|
if (getAlgorithm() != other.getAlgorithm()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Arrays.equals(getDigest(), other.getDigest())) {
|
return Arrays.equals(getDigest(), other.getDigest());
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -50,12 +50,11 @@ public enum DigestAlgorithm {
|
|||||||
* options for standardAlgorithmName. Throws an IllegalArgumentException if no Enum exists with
|
* options for standardAlgorithmName. Throws an IllegalArgumentException if no Enum exists with
|
||||||
* that value.
|
* that value.
|
||||||
*
|
*
|
||||||
* @param standardAlgorithmName
|
* @param standardAlgorithmName String value of the Enum
|
||||||
* String value of the Enum
|
|
||||||
* @return DigestAlgorithm object
|
* @return DigestAlgorithm object
|
||||||
*/
|
*/
|
||||||
public static DigestAlgorithm findByString(final String standardAlgorithmName) {
|
public static DigestAlgorithm findByString(final String standardAlgorithmName) {
|
||||||
for (DigestAlgorithm algorithm: DigestAlgorithm.values()) {
|
for (DigestAlgorithm algorithm : DigestAlgorithm.values()) {
|
||||||
if (algorithm.getStandardAlgorithmName().equals(standardAlgorithmName)) {
|
if (algorithm.getStandardAlgorithmName().equals(standardAlgorithmName)) {
|
||||||
return algorithm;
|
return algorithm;
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,6 @@ package hirs.utils.enums;
|
|||||||
|
|
||||||
public final class DeviceInfoEnums {
|
public final class DeviceInfoEnums {
|
||||||
|
|
||||||
/**
|
|
||||||
* Default private constructor so checkstyles doesn't complain
|
|
||||||
*/
|
|
||||||
private DeviceInfoEnums() { }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A variable used to describe unavailable hardware, firmware, or OS info.
|
* A variable used to describe unavailable hardware, firmware, or OS info.
|
||||||
*/
|
*/
|
||||||
@ -23,4 +18,9 @@ public final class DeviceInfoEnums {
|
|||||||
* Constant variable representing the various Long sized strings.
|
* Constant variable representing the various Long sized strings.
|
||||||
*/
|
*/
|
||||||
public static final int LONG_STRING_LENGTH = 255;
|
public static final int LONG_STRING_LENGTH = 255;
|
||||||
|
/**
|
||||||
|
* Default private constructor so checkstyles doesn't complain.
|
||||||
|
*/
|
||||||
|
private DeviceInfoEnums() {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,10 +5,11 @@ import jakarta.xml.bind.JAXBContext;
|
|||||||
import jakarta.xml.bind.JAXBException;
|
import jakarta.xml.bind.JAXBException;
|
||||||
import jakarta.xml.bind.UnmarshalException;
|
import jakarta.xml.bind.UnmarshalException;
|
||||||
import jakarta.xml.bind.Unmarshaller;
|
import jakarta.xml.bind.Unmarshaller;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import org.bouncycastle.asn1.x509.Extension;
|
import org.bouncycastle.asn1.x509.Extension;
|
||||||
import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils;
|
import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils;
|
||||||
import org.bouncycastle.jcajce.provider.asymmetric.X509;
|
|
||||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
@ -47,7 +48,7 @@ import java.io.File;
|
|||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
@ -86,105 +87,29 @@ public class ReferenceManifestValidator {
|
|||||||
|
|
||||||
private Document rim;
|
private Document rim;
|
||||||
private Unmarshaller unmarshaller;
|
private Unmarshaller unmarshaller;
|
||||||
|
|
||||||
|
@Getter
|
||||||
private PublicKey publicKey;
|
private PublicKey publicKey;
|
||||||
|
|
||||||
private Schema schema;
|
private Schema schema;
|
||||||
|
|
||||||
|
@Getter
|
||||||
private String subjectKeyIdentifier;
|
private String subjectKeyIdentifier;
|
||||||
|
|
||||||
|
@Setter
|
||||||
private String rimEventLog;
|
private String rimEventLog;
|
||||||
|
|
||||||
|
@Setter
|
||||||
private String trustStoreFile;
|
private String trustStoreFile;
|
||||||
|
|
||||||
|
@Setter
|
||||||
private List<X509Certificate> trustStore;
|
private List<X509Certificate> trustStore;
|
||||||
private boolean signatureValid, supportRimValid;
|
|
||||||
|
|
||||||
/**
|
@Getter
|
||||||
* Setter for the RIM to be validated. The ReferenceManifest object is converted into a
|
private boolean signatureValid;
|
||||||
* Document for processing.
|
|
||||||
*
|
|
||||||
* @param rimBytes ReferenceManifest object bytes
|
|
||||||
*/
|
|
||||||
public void setRim(final byte[] rimBytes) {
|
|
||||||
try {
|
|
||||||
Document doc = validateSwidtagSchema(removeXMLWhitespace(new StreamSource(
|
|
||||||
new ByteArrayInputStream(rimBytes))));
|
|
||||||
this.rim = doc;
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.error("Error while unmarshalling rim bytes: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
@Getter
|
||||||
* Setter for the swidtag XML to be validated. The XML is passed in via a filepath
|
private boolean supportRimValid;
|
||||||
* and converted into a Document for processing.
|
|
||||||
*
|
|
||||||
* @param path String filepath
|
|
||||||
*/
|
|
||||||
public void setRim(final String path) {
|
|
||||||
File swidtagFile = new File(path);
|
|
||||||
try {
|
|
||||||
Document doc = validateSwidtagSchema(removeXMLWhitespace(new StreamSource(swidtagFile)));
|
|
||||||
this.rim = doc;
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.error("Error while unmarshalling rim bytes: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Getter for signatureValid.
|
|
||||||
*
|
|
||||||
* @return true if valid, false if not.
|
|
||||||
*/
|
|
||||||
public boolean isSignatureValid() {
|
|
||||||
return signatureValid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Getter for supportRimValid.
|
|
||||||
*
|
|
||||||
* @return true if valid, false if not.
|
|
||||||
*/
|
|
||||||
public boolean isSupportRimValid() {
|
|
||||||
return supportRimValid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Getter for certificate PublicKey.
|
|
||||||
*
|
|
||||||
* @return PublicKey
|
|
||||||
*/
|
|
||||||
public PublicKey getPublicKey() {
|
|
||||||
return publicKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Getter for subjectKeyIdentifier.
|
|
||||||
*
|
|
||||||
* @return subjectKeyIdentifier
|
|
||||||
*/
|
|
||||||
public String getSubjectKeyIdentifier() {
|
|
||||||
return subjectKeyIdentifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setter for the truststore file path.
|
|
||||||
* @param trustStoreFile the file path to reference
|
|
||||||
*/
|
|
||||||
public void setTrustStoreFile(String trustStoreFile) {
|
|
||||||
this.trustStoreFile = trustStoreFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setter for truststore
|
|
||||||
* @param trustStore the List of X509Certificates
|
|
||||||
*/
|
|
||||||
public void setTrustStore(List<X509Certificate> trustStore) {
|
|
||||||
this.trustStore = trustStore;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setter for rimel file path.
|
|
||||||
* @param rimEventLog the rimel file
|
|
||||||
*/
|
|
||||||
public void setRimEventLog(String rimEventLog) {
|
|
||||||
this.rimEventLog = rimEventLog;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This default constructor creates the Schema object from SCHEMA_URL immediately to save
|
* This default constructor creates the Schema object from SCHEMA_URL immediately to save
|
||||||
@ -209,15 +134,47 @@ public class ReferenceManifestValidator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter for the RIM to be validated. The ReferenceManifest object is converted into a
|
||||||
|
* Document for processing.
|
||||||
|
*
|
||||||
|
* @param rimBytes ReferenceManifest object bytes
|
||||||
|
*/
|
||||||
|
public void setRim(final byte[] rimBytes) {
|
||||||
|
try {
|
||||||
|
Document doc = validateSwidtagSchema(removeXMLWhitespace(new StreamSource(
|
||||||
|
new ByteArrayInputStream(rimBytes))));
|
||||||
|
this.rim = doc;
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("Error while unmarshalling rim bytes: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter for the swidtag XML to be validated. The XML is passed in via a filepath
|
||||||
|
* and converted into a Document for processing.
|
||||||
|
*
|
||||||
|
* @param path String filepath
|
||||||
|
*/
|
||||||
|
public void setRim(final String path) {
|
||||||
|
File swidtagFile = new File(path);
|
||||||
|
try {
|
||||||
|
Document doc = validateSwidtagSchema(removeXMLWhitespace(new StreamSource(swidtagFile)));
|
||||||
|
this.rim = doc;
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("Error while unmarshalling rim bytes: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method attempts to validate the signature element of the instance's RIM
|
* This method attempts to validate the signature element of the instance's RIM
|
||||||
* using a given cert. The cert is compared to either the RIM's embedded certificate
|
* using a given cert. The cert is compared to either the RIM's embedded certificate
|
||||||
* or the RIM's subject key identifier. If the cert is matched then validation proceeds,
|
* or the RIM's subject key identifier. If the cert is matched then validation proceeds,
|
||||||
* otherwise validation ends.
|
* otherwise validation ends.
|
||||||
*
|
*
|
||||||
* @param publicKey public key from the CA credential
|
* @param publicKey public key from the CA credential
|
||||||
* @param subjectKeyIdString string version of the subjet key id of the CA credential
|
* @param subjectKeyIdString string version of the subjet key id of the CA credential
|
||||||
* @param encodedPublicKey the encoded public key
|
* @param encodedPublicKey the encoded public key
|
||||||
* @return true if the signature element is validated, false otherwise
|
* @return true if the signature element is validated, false otherwise
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("magicnumber")
|
@SuppressWarnings("magicnumber")
|
||||||
@ -257,7 +214,7 @@ public class ReferenceManifestValidator {
|
|||||||
return signatureValid;
|
return signatureValid;
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.warn("Error while parsing certificate data: " + e.getMessage());
|
log.warn("Error while parsing certificate data: {}", e.getMessage());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@ -267,26 +224,27 @@ public class ReferenceManifestValidator {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This method validates the rim with a public key cert.
|
* This method validates the rim with a public key cert.
|
||||||
|
*
|
||||||
* @param signingCertPath to the public key certificate used to sign the rim
|
* @param signingCertPath to the public key certificate used to sign the rim
|
||||||
* @return true if both the file element and signature are valid, false otherwise
|
* @return true if both the file element and signature are valid, false otherwise
|
||||||
*/
|
*/
|
||||||
public boolean validateRim(String signingCertPath) {
|
public boolean validateRim(final String signingCertPath) {
|
||||||
Element fileElement = (Element) rim.getElementsByTagNameNS(
|
Element fileElement = (Element) rim.getElementsByTagNameNS(
|
||||||
SwidTagConstants.SWIDTAG_NAMESPACE, "File").item(0);
|
SwidTagConstants.SWIDTAG_NAMESPACE, "File").item(0);
|
||||||
X509Certificate signingCert = parseCertificatesFromPem(signingCertPath).get(0);
|
X509Certificate signingCert = parseCertificatesFromPem(signingCertPath).get(0);
|
||||||
if (signingCert == null) {
|
if (signingCert == null) {
|
||||||
return failWithError("Unable to parse the signing cert from " + signingCertPath);
|
return failWithError("Unable to parse the signing cert from " + signingCertPath);
|
||||||
}
|
}
|
||||||
String subjectKeyIdentifier = "";
|
String retrievedSubjectKeyIdentifier = "";
|
||||||
try {
|
try {
|
||||||
subjectKeyIdentifier = getCertificateSubjectKeyIdentifier(signingCert);
|
retrievedSubjectKeyIdentifier = getCertificateSubjectKeyIdentifier(signingCert);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
return failWithError("Error while parsing SKID: " + e.getMessage());
|
return failWithError("Error while parsing SKID: " + e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isSignatureValid = validateXmlSignature(signingCert.getPublicKey(),
|
boolean isSignatureValid = validateXmlSignature(signingCert.getPublicKey(),
|
||||||
subjectKeyIdentifier,
|
retrievedSubjectKeyIdentifier,
|
||||||
signingCert.getPublicKey().getEncoded());
|
signingCert.getPublicKey().getEncoded());
|
||||||
return isSignatureValid && validateFile(fileElement);
|
return isSignatureValid && validateFile(fileElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,13 +259,15 @@ public class ReferenceManifestValidator {
|
|||||||
String calculatedHash = getHashValue(input, SHA256);
|
String calculatedHash = getHashValue(input, SHA256);
|
||||||
supportRimValid = calculatedHash.equals(expected);
|
supportRimValid = calculatedHash.equals(expected);
|
||||||
if (!supportRimValid) {
|
if (!supportRimValid) {
|
||||||
log.info("Unmatched support RIM hash! Expected: " + expected
|
log.info("Unmatched support RIM hash! Expected: {}, actual: {}", expected, calculatedHash);
|
||||||
+ ", actual: " + calculatedHash);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method validates a hirs.swid.xjc.File from an indirect payload
|
* This method validates a hirs.swid.xjc.File from an indirect payload.
|
||||||
|
*
|
||||||
|
* @param file file extracted from element
|
||||||
|
* @return true if the provided file is valid, false otherwise
|
||||||
*/
|
*/
|
||||||
private boolean validateFile(final Element file) {
|
private boolean validateFile(final Element file) {
|
||||||
String filepath;
|
String filepath;
|
||||||
@ -317,9 +277,9 @@ public class ReferenceManifestValidator {
|
|||||||
filepath = file.getAttribute(SwidTagConstants.NAME);
|
filepath = file.getAttribute(SwidTagConstants.NAME);
|
||||||
}
|
}
|
||||||
if (getHashValue(filepath, "SHA256").equals(
|
if (getHashValue(filepath, "SHA256").equals(
|
||||||
file.getAttribute(SwidTagConstants._SHA256_HASH.getPrefix() + ":" +
|
file.getAttribute(SwidTagConstants._SHA256_HASH.getPrefix() + ":"
|
||||||
SwidTagConstants._SHA256_HASH.getLocalPart()))) {
|
+ SwidTagConstants._SHA256_HASH.getLocalPart()))) {
|
||||||
log.info("Support RIM hash verified for " + filepath);
|
log.info("Support RIM hash verified for {}", filepath);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return failWithError("Support RIM hash does not match Base RIM!");
|
return failWithError("Support RIM hash does not match Base RIM!");
|
||||||
@ -333,10 +293,10 @@ public class ReferenceManifestValidator {
|
|||||||
* @return X509Certificate signing cert
|
* @return X509Certificate signing cert
|
||||||
*/
|
*/
|
||||||
private X509Certificate getCertFromTruststore() throws IOException {
|
private X509Certificate getCertFromTruststore() throws IOException {
|
||||||
String subjectKeyIdentifier = getKeyName(rim);
|
String retrievedSubjectKeyIdentifier = getKeyName(rim);
|
||||||
for (X509Certificate trustedCert : trustStore) {
|
for (X509Certificate trustedCert : trustStore) {
|
||||||
String trustedSubjectKeyIdentifier = getCertificateSubjectKeyIdentifier(trustedCert);
|
String trustedSubjectKeyIdentifier = getCertificateSubjectKeyIdentifier(trustedCert);
|
||||||
if (subjectKeyIdentifier.equals(trustedSubjectKeyIdentifier)) {
|
if (retrievedSubjectKeyIdentifier.equals(trustedSubjectKeyIdentifier)) {
|
||||||
return trustedCert;
|
return trustedCert;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -345,10 +305,10 @@ public class ReferenceManifestValidator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method calculates the digest of the file at filepath based on algorithm sha
|
* This method calculates the digest of the file at filepath based on algorithm sha.
|
||||||
*
|
*
|
||||||
* @param filepath the file to hash
|
* @param filepath the file to hash
|
||||||
* @param sha the algorithm to use
|
* @param sha the algorithm to use
|
||||||
* @return String digest
|
* @return String digest
|
||||||
*/
|
*/
|
||||||
private String getHashValue(final String filepath, final String sha) {
|
private String getHashValue(final String filepath, final String sha) {
|
||||||
@ -359,11 +319,12 @@ public class ReferenceManifestValidator {
|
|||||||
} catch (NoSuchAlgorithmException e) {
|
} catch (NoSuchAlgorithmException e) {
|
||||||
log.warn(e.getMessage());
|
log.warn(e.getMessage());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.warn("Error reading " + filepath + " for hashing: " + e.getMessage());
|
log.warn("Error reading {} for hashing: {}", filepath, e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method calculates the digest of a byte array based on the hashing algorithm passed in.
|
* This method calculates the digest of a byte array based on the hashing algorithm passed in.
|
||||||
*
|
*
|
||||||
@ -401,9 +362,9 @@ public class ReferenceManifestValidator {
|
|||||||
whySignatureInvalid(signature, context);
|
whySignatureInvalid(signature, context);
|
||||||
}
|
}
|
||||||
} catch (MarshalException e) {
|
} catch (MarshalException e) {
|
||||||
log.warn("Error while unmarshalling XML signature: " + e.getMessage());
|
log.warn("Error while unmarshalling XML signature: {}", e.getMessage());
|
||||||
} catch (XMLSignatureException e) {
|
} catch (XMLSignatureException e) {
|
||||||
log.warn("Error while validating XML signature: " + e.getMessage());
|
log.warn("Error while validating XML signature: {}", e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -415,11 +376,11 @@ public class ReferenceManifestValidator {
|
|||||||
* results are logged.
|
* results are logged.
|
||||||
*
|
*
|
||||||
* @param signature the signature that failed to validate
|
* @param signature the signature that failed to validate
|
||||||
* @param context the context used for validation
|
* @param context the context used for validation
|
||||||
* @throws XMLSignatureException
|
* @throws XMLSignatureException
|
||||||
*/
|
*/
|
||||||
private void whySignatureInvalid(final XMLSignature signature, final DOMValidateContext context)
|
private void whySignatureInvalid(final XMLSignature signature, final DOMValidateContext context)
|
||||||
throws XMLSignatureException{
|
throws XMLSignatureException {
|
||||||
boolean cryptoValidity = signature.getSignatureValue().validate(context);
|
boolean cryptoValidity = signature.getSignatureValue().validate(context);
|
||||||
if (cryptoValidity) {
|
if (cryptoValidity) {
|
||||||
log.error("Signature value is valid.");
|
log.error("Signature value is valid.");
|
||||||
@ -435,9 +396,9 @@ public class ReferenceManifestValidator {
|
|||||||
refUri = "whole document";
|
refUri = "whole document";
|
||||||
}
|
}
|
||||||
if (refValidity) {
|
if (refValidity) {
|
||||||
log.error("Reference for " + refUri + " is valid.");
|
log.error("Reference for {} is valid.", refUri);
|
||||||
} else {
|
} else {
|
||||||
log.error("Reference for " + refUri + " is invalid!");
|
log.error("Reference for {} is invalid!", refUri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -445,6 +406,7 @@ public class ReferenceManifestValidator {
|
|||||||
/**
|
/**
|
||||||
* This method validates the cert chain for a given certificate. The truststore is iterated
|
* This method validates the cert chain for a given certificate. The truststore is iterated
|
||||||
* over until a root CA is found, otherwise an error is returned.
|
* over until a root CA is found, otherwise an error is returned.
|
||||||
|
*
|
||||||
* @param cert the certificate at the start of the chain
|
* @param cert the certificate at the start of the chain
|
||||||
* @return true if the chain is valid
|
* @return true if the chain is valid
|
||||||
* @throws Exception if a valid chain is not found in the truststore
|
* @throws Exception if a valid chain is not found in the truststore
|
||||||
@ -462,7 +424,7 @@ public class ReferenceManifestValidator {
|
|||||||
boolean isChainCertValid;
|
boolean isChainCertValid;
|
||||||
do {
|
do {
|
||||||
isChainCertValid = false;
|
isChainCertValid = false;
|
||||||
log.info("Validating " + chainCert.getSubjectX500Principal().getName());
|
log.info("Validating {}", chainCert.getSubjectX500Principal().getName());
|
||||||
for (X509Certificate trustedCert : trustStore) {
|
for (X509Certificate trustedCert : trustStore) {
|
||||||
boolean isIssuer = areYouMyIssuer(chainCert, trustedCert);
|
boolean isIssuer = areYouMyIssuer(chainCert, trustedCert);
|
||||||
boolean isSigner = areYouMySigner(chainCert, trustedCert);
|
boolean isSigner = areYouMySigner(chainCert, trustedCert);
|
||||||
@ -490,14 +452,15 @@ public class ReferenceManifestValidator {
|
|||||||
}
|
}
|
||||||
} while (isChainCertValid);
|
} while (isChainCertValid);
|
||||||
|
|
||||||
log.error("CA chain validation failed to validate "
|
log.error("CA chain validation failed to validate {}, {}",
|
||||||
+ chainCert.getSubjectX500Principal().getName() + ", " + errorMessage);
|
chainCert.getSubjectX500Principal().getName(), errorMessage);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method checks if cert's issuerDN matches issuer's subjectDN.
|
* This method checks if cert's issuerDN matches issuer's subjectDN.
|
||||||
* @param cert the signed certificate
|
*
|
||||||
|
* @param cert the signed certificate
|
||||||
* @param issuer the signing certificate
|
* @param issuer the signing certificate
|
||||||
* @return true if they match, false if not
|
* @return true if they match, false if not
|
||||||
* @throws Exception if either argument is null
|
* @throws Exception if either argument is null
|
||||||
@ -512,7 +475,8 @@ public class ReferenceManifestValidator {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This method checks if cert's issuerDN matches issuer's subjectDN.
|
* This method checks if cert's issuerDN matches issuer's subjectDN.
|
||||||
* @param cert the signed certificate
|
*
|
||||||
|
* @param cert the signed certificate
|
||||||
* @param issuer the signing certificate
|
* @param issuer the signing certificate
|
||||||
* @return true if they match, false if not
|
* @return true if they match, false if not
|
||||||
* @throws Exception if either argument is null
|
* @throws Exception if either argument is null
|
||||||
@ -528,7 +492,8 @@ public class ReferenceManifestValidator {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This method checks if cert's signature matches signer's public key.
|
* This method checks if cert's signature matches signer's public key.
|
||||||
* @param cert the signed certificate
|
*
|
||||||
|
* @param cert the signed certificate
|
||||||
* @param signer the signing certificate
|
* @param signer the signing certificate
|
||||||
* @return true if they match
|
* @return true if they match
|
||||||
* @throws Exception if an error occurs or there is no match
|
* @throws Exception if an error occurs or there is no match
|
||||||
@ -562,6 +527,7 @@ public class ReferenceManifestValidator {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This method checks if a given certificate is self signed or not.
|
* This method checks if a given certificate is self signed or not.
|
||||||
|
*
|
||||||
* @param cert the cert to check
|
* @param cert the cert to check
|
||||||
* @return true if self signed, false if not
|
* @return true if self signed, false if not
|
||||||
*/
|
*/
|
||||||
@ -569,128 +535,6 @@ public class ReferenceManifestValidator {
|
|||||||
return cert.getIssuerX500Principal().equals(cert.getSubjectX500Principal());
|
return cert.getIssuerX500Principal().equals(cert.getSubjectX500Principal());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This internal class handles selecting an X509 certificate embedded in a KeyInfo element.
|
|
||||||
* It is passed as a parameter to a DOMValidateContext that uses it to validate
|
|
||||||
* an XML signature.
|
|
||||||
*/
|
|
||||||
public class X509KeySelector extends KeySelector {
|
|
||||||
PublicKey publicKey;
|
|
||||||
X509Certificate signingCert;
|
|
||||||
/**
|
|
||||||
* This method selects a public key for validation.
|
|
||||||
* PKs are parsed preferentially from the following elements:
|
|
||||||
* - X509Data
|
|
||||||
* - KeyValue
|
|
||||||
* The parsed PK is then verified based on the provided algorithm before
|
|
||||||
* being returned in a KeySelectorResult.
|
|
||||||
*
|
|
||||||
* @param keyinfo object containing the cert.
|
|
||||||
* @param purpose purpose.
|
|
||||||
* @param algorithm algorithm.
|
|
||||||
* @param context XMLCryptoContext.
|
|
||||||
* @return KeySelectorResult holding the PublicKey.
|
|
||||||
* @throws KeySelectorException exception.
|
|
||||||
*/
|
|
||||||
public KeySelectorResult select(final KeyInfo keyinfo,
|
|
||||||
final KeySelector.Purpose purpose,
|
|
||||||
final AlgorithmMethod algorithm,
|
|
||||||
final XMLCryptoContext context)
|
|
||||||
throws KeySelectorException {
|
|
||||||
Iterator keyinfoItr = keyinfo.getContent().iterator();
|
|
||||||
while (keyinfoItr.hasNext()) {
|
|
||||||
XMLStructure element = (XMLStructure) keyinfoItr.next();
|
|
||||||
if (element instanceof X509Data) {
|
|
||||||
X509Data data = (X509Data) element;
|
|
||||||
Iterator dataItr = data.getContent().iterator();
|
|
||||||
while (dataItr.hasNext()) {
|
|
||||||
Object object = dataItr.next();
|
|
||||||
if (object instanceof X509Certificate) {
|
|
||||||
X509Certificate embeddedCert = (X509Certificate) object;
|
|
||||||
try {
|
|
||||||
if (isCertChainValid(embeddedCert)) {
|
|
||||||
publicKey = ((X509Certificate) embeddedCert).getPublicKey();
|
|
||||||
signingCert = embeddedCert;
|
|
||||||
log.info("Certificate chain valid.");
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Certificate chain invalid: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (element instanceof KeyValue) {
|
|
||||||
try {
|
|
||||||
PublicKey pk = ((KeyValue) element).getPublicKey();
|
|
||||||
if (isPublicKeyTrusted(pk)) {
|
|
||||||
publicKey = pk;
|
|
||||||
try {
|
|
||||||
if (isCertChainValid(signingCert)) {
|
|
||||||
log.info("Certificate chain valid.");
|
|
||||||
} else {
|
|
||||||
log.error("Certificate chain invalid.");
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Certificate chain invalid: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (KeyException e) {
|
|
||||||
log.error("Unable to convert KeyValue data to PK.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (publicKey != null) {
|
|
||||||
if (areAlgorithmsEqual(algorithm.getAlgorithm(), publicKey.getAlgorithm())) {
|
|
||||||
return new ReferenceManifestValidator.X509KeySelector
|
|
||||||
.RIMKeySelectorResult(publicKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new KeySelectorException("No key found!");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method checks that the signature and public key algorithms match.
|
|
||||||
* @param uri to match the signature algorithm
|
|
||||||
* @param name to match the public key algorithm
|
|
||||||
* @return true if both match, false otherwise
|
|
||||||
*/
|
|
||||||
public boolean areAlgorithmsEqual(String uri, String name) {
|
|
||||||
return uri.equals(SwidTagConstants.SIGNATURE_ALGORITHM_RSA_SHA256)
|
|
||||||
&& name.equalsIgnoreCase("RSA");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method compares a public key against those in the truststore.
|
|
||||||
* @param pk a public key
|
|
||||||
* @return true if pk is found in the trust store, false otherwise
|
|
||||||
*/
|
|
||||||
private boolean isPublicKeyTrusted(final PublicKey pk) {
|
|
||||||
for (X509Certificate trustedCert : trustStore) {
|
|
||||||
if (Arrays.equals(trustedCert.getPublicKey().getEncoded(),
|
|
||||||
pk.getEncoded())) {
|
|
||||||
signingCert = trustedCert;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This internal class creates a KeySelectorResult from the public key.
|
|
||||||
*/
|
|
||||||
private static class RIMKeySelectorResult implements KeySelectorResult {
|
|
||||||
private Key key;
|
|
||||||
|
|
||||||
RIMKeySelectorResult(final Key key) {
|
|
||||||
this.key = key;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Key getKey() {
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method extracts certificate bytes from a string. The bytes are assumed to be
|
* This method extracts certificate bytes from a string. The bytes are assumed to be
|
||||||
* PEM format, and a header and footer are concatenated with the input string to
|
* PEM format, and a header and footer are concatenated with the input string to
|
||||||
@ -709,12 +553,10 @@ public class ReferenceManifestValidator {
|
|||||||
+ System.lineSeparator()
|
+ System.lineSeparator()
|
||||||
+ pemString
|
+ pemString
|
||||||
+ System.lineSeparator()
|
+ System.lineSeparator()
|
||||||
+ certificateFooter).getBytes("UTF-8"));
|
+ certificateFooter).getBytes(StandardCharsets.UTF_8));
|
||||||
return (X509Certificate) factory.generateCertificate(inputStream);
|
return (X509Certificate) factory.generateCertificate(inputStream);
|
||||||
} catch (CertificateException e) {
|
} catch (CertificateException e) {
|
||||||
log.warn("Error creating CertificateFactory instance: " + e.getMessage());
|
log.warn("Error creating CertificateFactory instance: {}", e.getMessage());
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
log.warn("Error while parsing cert from PEM string: " + e.getMessage());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@ -724,11 +566,12 @@ public class ReferenceManifestValidator {
|
|||||||
* This method returns the X509Certificates found in a PEM file.
|
* This method returns the X509Certificates found in a PEM file.
|
||||||
* Unchecked type case warnings are suppressed because the CertificateFactory
|
* Unchecked type case warnings are suppressed because the CertificateFactory
|
||||||
* implements X509Certificate objects explicitly.
|
* implements X509Certificate objects explicitly.
|
||||||
|
*
|
||||||
* @param filename pem file
|
* @param filename pem file
|
||||||
* @return a list containing all X509Certificates extracted
|
* @return a list containing all X509Certificates extracted
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private List<X509Certificate> parseCertificatesFromPem(String filename) {
|
private List<X509Certificate> parseCertificatesFromPem(final String filename) {
|
||||||
List<X509Certificate> certificates = null;
|
List<X509Certificate> certificates = null;
|
||||||
FileInputStream fis = null;
|
FileInputStream fis = null;
|
||||||
BufferedInputStream bis = null;
|
BufferedInputStream bis = null;
|
||||||
@ -742,14 +585,14 @@ public class ReferenceManifestValidator {
|
|||||||
(List<X509Certificate>) certificateFactory.generateCertificates(bis);
|
(List<X509Certificate>) certificateFactory.generateCertificates(bis);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (certificates.size() < 1) {
|
if (certificates.isEmpty()) {
|
||||||
System.out.println("ERROR: No certificates parsed from " + filename);
|
System.out.println("ERROR: No certificates parsed from " + filename);
|
||||||
}
|
}
|
||||||
bis.close();
|
bis.close();
|
||||||
} catch (CertificateException e) {
|
} catch (CertificateException e) {
|
||||||
log.error("Error in certificate factory: " + e.getMessage());
|
log.error("Error in certificate factory: {}", e.getMessage());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error("Error reading from input stream: " + e.getMessage());
|
log.error("Error reading from input stream: {}", e.getMessage());
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
if (fis != null) {
|
if (fis != null) {
|
||||||
@ -759,7 +602,7 @@ public class ReferenceManifestValidator {
|
|||||||
bis.close();
|
bis.close();
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.warn("Error closing input stream: " + e.getMessage());
|
log.warn("Error closing input stream: {}", e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -854,11 +697,135 @@ public class ReferenceManifestValidator {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This method logs an error message and returns a false to signal failed validation.
|
* This method logs an error message and returns a false to signal failed validation.
|
||||||
|
*
|
||||||
* @param errorMessage String description of what went wrong
|
* @param errorMessage String description of what went wrong
|
||||||
* @return false to represent failed validation
|
* @return false to represent failed validation
|
||||||
*/
|
*/
|
||||||
private boolean failWithError(String errorMessage) {
|
private boolean failWithError(final String errorMessage) {
|
||||||
log.error(errorMessage);
|
log.error(errorMessage);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This internal class handles selecting an X509 certificate embedded in a KeyInfo element.
|
||||||
|
* It is passed as a parameter to a DOMValidateContext that uses it to validate
|
||||||
|
* an XML signature.
|
||||||
|
*/
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
public class X509KeySelector extends KeySelector {
|
||||||
|
|
||||||
|
private PublicKey publicKey;
|
||||||
|
private X509Certificate signingCert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method selects a public key for validation.
|
||||||
|
* PKs are parsed preferentially from the following elements:
|
||||||
|
* - X509Data
|
||||||
|
* - KeyValue
|
||||||
|
* The parsed PK is then verified based on the provided algorithm before
|
||||||
|
* being returned in a KeySelectorResult.
|
||||||
|
*
|
||||||
|
* @param keyinfo object containing the cert.
|
||||||
|
* @param purpose purpose.
|
||||||
|
* @param algorithm algorithm.
|
||||||
|
* @param context XMLCryptoContext.
|
||||||
|
* @return KeySelectorResult holding the PublicKey.
|
||||||
|
* @throws KeySelectorException exception.
|
||||||
|
*/
|
||||||
|
public KeySelectorResult select(final KeyInfo keyinfo,
|
||||||
|
final KeySelector.Purpose purpose,
|
||||||
|
final AlgorithmMethod algorithm,
|
||||||
|
final XMLCryptoContext context)
|
||||||
|
throws KeySelectorException {
|
||||||
|
Iterator keyinfoItr = keyinfo.getContent().iterator();
|
||||||
|
while (keyinfoItr.hasNext()) {
|
||||||
|
XMLStructure element = (XMLStructure) keyinfoItr.next();
|
||||||
|
if (element instanceof X509Data data) {
|
||||||
|
Iterator dataItr = data.getContent().iterator();
|
||||||
|
while (dataItr.hasNext()) {
|
||||||
|
Object object = dataItr.next();
|
||||||
|
if (object instanceof X509Certificate embeddedCert) {
|
||||||
|
try {
|
||||||
|
if (isCertChainValid(embeddedCert)) {
|
||||||
|
publicKey = embeddedCert.getPublicKey();
|
||||||
|
signingCert = embeddedCert;
|
||||||
|
log.info("Certificate chain valid.");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Certificate chain invalid: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (element instanceof KeyValue) {
|
||||||
|
try {
|
||||||
|
PublicKey pk = ((KeyValue) element).getPublicKey();
|
||||||
|
if (isPublicKeyTrusted(pk)) {
|
||||||
|
publicKey = pk;
|
||||||
|
try {
|
||||||
|
if (isCertChainValid(signingCert)) {
|
||||||
|
log.info("Certificate chain valid.");
|
||||||
|
} else {
|
||||||
|
log.error("Certificate chain invalid.");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Certificate chain invalid: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (KeyException e) {
|
||||||
|
log.error("Unable to convert KeyValue data to PK.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (publicKey != null) {
|
||||||
|
if (areAlgorithmsEqual(algorithm.getAlgorithm(), publicKey.getAlgorithm())) {
|
||||||
|
return new ReferenceManifestValidator.X509KeySelector
|
||||||
|
.RIMKeySelectorResult(publicKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new KeySelectorException("No key found!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method checks that the signature and public key algorithms match.
|
||||||
|
*
|
||||||
|
* @param uri to match the signature algorithm
|
||||||
|
* @param name to match the public key algorithm
|
||||||
|
* @return true if both match, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean areAlgorithmsEqual(final String uri, final String name) {
|
||||||
|
return uri.equals(SwidTagConstants.SIGNATURE_ALGORITHM_RSA_SHA256)
|
||||||
|
&& name.equalsIgnoreCase("RSA");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method compares a public key against those in the truststore.
|
||||||
|
*
|
||||||
|
* @param pk a public key
|
||||||
|
* @return true if pk is found in the trust store, false otherwise
|
||||||
|
*/
|
||||||
|
private boolean isPublicKeyTrusted(final PublicKey pk) {
|
||||||
|
for (X509Certificate trustedCert : trustStore) {
|
||||||
|
if (Arrays.equals(trustedCert.getPublicKey().getEncoded(),
|
||||||
|
pk.getEncoded())) {
|
||||||
|
signingCert = trustedCert;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This internal class creates a KeySelectorResult from the public key.
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
private static class RIMKeySelectorResult implements KeySelectorResult {
|
||||||
|
private final Key key;
|
||||||
|
|
||||||
|
RIMKeySelectorResult(final Key key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,24 +10,17 @@ import javax.xml.namespace.QName;
|
|||||||
*/
|
*/
|
||||||
public class SwidTagConstants {
|
public class SwidTagConstants {
|
||||||
|
|
||||||
/**
|
public static final String DEFAULT_KEYSTORE_FILE = "keystore.jks"; //"/opt/hirs/rimtool/keystore.jks";
|
||||||
* Default private constructor so checkstyles doesn't complain
|
|
||||||
*/
|
|
||||||
private SwidTagConstants() { }
|
|
||||||
|
|
||||||
public static final String DEFAULT_KEYSTORE_FILE = "keystore.jks";//"/opt/hirs/rimtool/keystore.jks";
|
|
||||||
public static final String DEFAULT_KEYSTORE_PASSWORD = "password";
|
public static final String DEFAULT_KEYSTORE_PASSWORD = "password";
|
||||||
public static final String DEFAULT_PRIVATE_KEY_ALIAS = "1";
|
public static final String DEFAULT_PRIVATE_KEY_ALIAS = "1";
|
||||||
public static final String DEFAULT_ATTRIBUTES_FILE = "/opt/hirs/rimtool/rim_fields.json";
|
public static final String DEFAULT_ATTRIBUTES_FILE = "/opt/hirs/rimtool/rim_fields.json";
|
||||||
public static final String DEFAULT_ENGLISH = "en";
|
public static final String DEFAULT_ENGLISH = "en";
|
||||||
|
public static final String SIGNATURE_ALGORITHM_RSA_SHA256 =
|
||||||
public static final String SIGNATURE_ALGORITHM_RSA_SHA256 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
|
"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
|
||||||
|
|
||||||
public static final String SCHEMA_PACKAGE = "hirs.swid.xjc";
|
public static final String SCHEMA_PACKAGE = "hirs.swid.xjc";
|
||||||
public static final String SCHEMA_LANGUAGE = XMLConstants.W3C_XML_SCHEMA_NS_URI;
|
public static final String SCHEMA_LANGUAGE = XMLConstants.W3C_XML_SCHEMA_NS_URI;
|
||||||
public static final String SCHEMA_URL = "swid_schema.xsd";
|
public static final String SCHEMA_URL = "swid_schema.xsd";
|
||||||
public static final String SWIDTAG_NAMESPACE = "http://standards.iso.org/iso/19770/-2/2015/schema.xsd";
|
public static final String SWIDTAG_NAMESPACE = "http://standards.iso.org/iso/19770/-2/2015/schema.xsd";
|
||||||
|
|
||||||
public static final String SOFTWARE_IDENTITY = "SoftwareIdentity";
|
public static final String SOFTWARE_IDENTITY = "SoftwareIdentity";
|
||||||
public static final String ENTITY = "Entity";
|
public static final String ENTITY = "Entity";
|
||||||
public static final String LINK = "Link";
|
public static final String LINK = "Link";
|
||||||
@ -76,18 +69,15 @@ public class SwidTagConstants {
|
|||||||
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 DATETIME = "dateTime";
|
||||||
|
|
||||||
public static final String NIST_NS = "http://csrc.nist.gov/ns/swid/2015-extensions/1.0";
|
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 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 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 RFC3339_NS = "https://www.ietf.org/rfc/rfc3339.txt";
|
||||||
|
|
||||||
public static final String N8060_PFX = "n8060";
|
public static final String N8060_PFX = "n8060";
|
||||||
public static final String RIM_PFX = "rim";
|
public static final String RIM_PFX = "rim";
|
||||||
public static final String FX_SEPARATOR = ":";
|
public static final String FX_SEPARATOR = ":";
|
||||||
public static final String RFC3852_PFX = "rcf3852";
|
public static final String RFC3852_PFX = "rcf3852";
|
||||||
public static final String RFC3339_PFX = "rcf3339";
|
public static final String RFC3339_PFX = "rcf3339";
|
||||||
|
|
||||||
public static final String _COLLOQUIAL_VERSION_STR = N8060_PFX + FX_SEPARATOR +
|
public static final String _COLLOQUIAL_VERSION_STR = N8060_PFX + FX_SEPARATOR +
|
||||||
COLLOQUIAL_VERSION;
|
COLLOQUIAL_VERSION;
|
||||||
public static final String _PRODUCT_STR = N8060_PFX + FX_SEPARATOR +
|
public static final String _PRODUCT_STR = N8060_PFX + FX_SEPARATOR +
|
||||||
@ -116,8 +106,6 @@ public class SwidTagConstants {
|
|||||||
PC_URI_LOCAL;
|
PC_URI_LOCAL;
|
||||||
public static final String _PC_URI_GLOBAL_STR = RIM_PFX + FX_SEPARATOR +
|
public static final String _PC_URI_GLOBAL_STR = RIM_PFX + FX_SEPARATOR +
|
||||||
PC_URI_GLOBAL;
|
PC_URI_GLOBAL;
|
||||||
|
|
||||||
|
|
||||||
public static final QName _SHA256_HASH = new QName(
|
public static final QName _SHA256_HASH = new QName(
|
||||||
"http://www.w3.org/2001/04/xmlenc#sha256", HASH, "SHA256");
|
"http://www.w3.org/2001/04/xmlenc#sha256", HASH, "SHA256");
|
||||||
public static final QName _COLLOQUIAL_VERSION = new QName(
|
public static final QName _COLLOQUIAL_VERSION = new QName(
|
||||||
@ -168,6 +156,11 @@ public class SwidTagConstants {
|
|||||||
NIST_NS, "envVarSuffix", N8060_PFX);
|
NIST_NS, "envVarSuffix", N8060_PFX);
|
||||||
public static final QName _N8060_PATHSEPARATOR = new QName(
|
public static final QName _N8060_PATHSEPARATOR = new QName(
|
||||||
NIST_NS, "pathSeparator", N8060_PFX);
|
NIST_NS, "pathSeparator", N8060_PFX);
|
||||||
|
|
||||||
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";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default private constructor so checkstyles doesn't complain.
|
||||||
|
*/
|
||||||
|
private SwidTagConstants() {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,7 +109,10 @@
|
|||||||
|
|
||||||
<!-- Checks for Naming Conventions. -->
|
<!-- Checks for Naming Conventions. -->
|
||||||
<!-- See https://checkstyle.org/checks/naming/index.html -->
|
<!-- See https://checkstyle.org/checks/naming/index.html -->
|
||||||
<module name="ConstantName"/>
|
<module name="ConstantName">
|
||||||
|
<property name="format"
|
||||||
|
value="[A-Z_][A-Z0-9]*(_[A-Z0-9]+)*$"/>
|
||||||
|
</module>
|
||||||
<module name="LocalFinalVariableName"/>
|
<module name="LocalFinalVariableName"/>
|
||||||
<module name="LocalVariableName"/>
|
<module name="LocalVariableName"/>
|
||||||
<module name="MemberName"/>
|
<module name="MemberName"/>
|
||||||
@ -163,7 +166,9 @@
|
|||||||
<!-- See https://checkstyle.org/checks/coding/index.html -->
|
<!-- See https://checkstyle.org/checks/coding/index.html -->
|
||||||
<module name="EmptyStatement"/>
|
<module name="EmptyStatement"/>
|
||||||
<module name="EqualsHashCode"/>
|
<module name="EqualsHashCode"/>
|
||||||
<module name="HiddenField"/>
|
<module name="HiddenField">
|
||||||
|
<property name="tokens" value="VARIABLE_DEF"/>
|
||||||
|
</module>
|
||||||
<module name="IllegalInstantiation"/>
|
<module name="IllegalInstantiation"/>
|
||||||
<module name="InnerAssignment"/>
|
<module name="InnerAssignment"/>
|
||||||
<module name="MagicNumber"/>
|
<module name="MagicNumber"/>
|
||||||
|
Loading…
Reference in New Issue
Block a user