mirror of
https://github.com/nsacyber/HIRS.git
synced 2024-12-23 14:52:31 +00:00
Merge branch 'main' into v3_issue_847-update-hirs_attestationca-caportal-for-checkstyle2
This commit is contained in:
commit
99188f17c1
.ci/docker
HIRS_Utils/src
main/java/hirs/utils
BannerConfiguration.javaHexUtils.javaJsonUtils.javaPciIds.javaSwidResource.java
digest
enums
exception
package-info.javarim
swid
tpm/eventlog
events
DeviceSecurityEventDataHeader.javaDeviceSecurityEventDataHeader2.javaDeviceSecurityEventDataPciContext.javaDeviceSecurityEventDataSubHeaderCertChain.javaDeviceSecurityEventDataSubHeaderSpdmMeasurementBlock.javaDeviceSecurityEventHeader.javaEvConstants.javaEvNoAction.javaNvIndexDynamicEventLogData.javaNvIndexInstanceEventLogData.java
spdm
uefi
test/java/hirs
data/persist
DigestTest.javaFirmwareInfoTest.javaHardwareInfoTest.javaNetworkInfoTest.javaOSInfoTest.javapackage-info.java
tpm/eventlog/uefi
utils
@ -12,6 +12,7 @@ services:
|
|||||||
hat:
|
hat:
|
||||||
image: ghcr.io/nsacyber/hirs/hat
|
image: ghcr.io/nsacyber/hirs/hat
|
||||||
container_name: hat
|
container_name: hat
|
||||||
|
privileged: true
|
||||||
ports:
|
ports:
|
||||||
- 53:53/tcp
|
- 53:53/tcp
|
||||||
- 53:53/udp
|
- 53:53/udp
|
||||||
|
@ -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,9 +40,6 @@ 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
|
||||||
@ -52,7 +51,7 @@ public class BannerConfiguration {
|
|||||||
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,6 +72,7 @@ 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)
|
||||||
@ -81,6 +86,7 @@ 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
|
||||||
*/
|
*/
|
||||||
@ -94,6 +100,7 @@ public final class HexUtils {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
*/
|
*/
|
||||||
@ -104,6 +111,7 @@ 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
|
||||||
*/
|
*/
|
||||||
|
@ -21,9 +21,10 @@ 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
|
||||||
@ -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());
|
||||||
|
@ -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,6 +124,7 @@ 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.
|
||||||
@ -146,6 +150,7 @@ 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.
|
||||||
@ -169,6 +174,7 @@ 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"
|
||||||
@ -184,9 +190,23 @@ public final class PciIds {
|
|||||||
|
|
||||||
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);
|
||||||
|
@ -19,14 +19,30 @@ import java.util.Map;
|
|||||||
public class SwidResource {
|
public class SwidResource {
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
private static final boolean VALID_FILE_SIZE = false;
|
||||||
private String name, size, hashValue;
|
|
||||||
@Getter
|
@Getter
|
||||||
private String rimFormat, rimType, rimUriGlobal;
|
@Setter
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private String size;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private String hashValue;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private String rimFormat;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private String rimType;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private String rimUriGlobal;
|
||||||
// private TpmWhiteListBaseline tpmWhiteList;
|
// private TpmWhiteListBaseline tpmWhiteList;
|
||||||
private DigestAlgorithm digest = DigestAlgorithm.SHA1;
|
private DigestAlgorithm digest = DigestAlgorithm.SHA1;
|
||||||
@Getter
|
|
||||||
private boolean validFileSize = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default constructor.
|
* Default constructor.
|
||||||
|
@ -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,8 +50,7 @@ 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) {
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
package hirs.utils.digest;
|
@ -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() {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
package hirs.utils.enums;
|
@ -0,0 +1 @@
|
|||||||
|
package hirs.utils.exception;
|
1
HIRS_Utils/src/main/java/hirs/utils/package-info.java
Normal file
1
HIRS_Utils/src/main/java/hirs/utils/package-info.java
Normal file
@ -0,0 +1 @@
|
|||||||
|
package hirs.utils;
|
@ -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,6 +134,38 @@ 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
|
||||||
@ -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,25 +224,26 @@ 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,7 +305,7 @@ 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
|
||||||
@ -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;
|
||||||
@ -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,13 +452,14 @@ 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
|
||||||
@ -512,6 +475,7 @@ 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
|
||||||
@ -528,6 +492,7 @@ 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
|
||||||
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
package hirs.utils.rim;
|
@ -8,26 +8,19 @@ import javax.xml.namespace.QName;
|
|||||||
* class. It is expected that member properties of this class will expand as
|
* class. It is expected that member properties of this class will expand as
|
||||||
* more functionality is added to SwidTagGateway.
|
* more functionality is added to SwidTagGateway.
|
||||||
*/
|
*/
|
||||||
public class SwidTagConstants {
|
public final class SwidTagConstants {
|
||||||
|
|
||||||
/**
|
|
||||||
* 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_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,48 +69,43 @@ 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 +
|
+ PRODUCT;
|
||||||
PRODUCT;
|
public static final String _REVISION_STR = N8060_PFX + FX_SEPARATOR
|
||||||
public static final String _REVISION_STR = N8060_PFX + FX_SEPARATOR +
|
+ REVISION;
|
||||||
REVISION;
|
public static final String _EDITION_STR = N8060_PFX + FX_SEPARATOR
|
||||||
public static final String _EDITION_STR = N8060_PFX + FX_SEPARATOR +
|
+ EDITION;
|
||||||
EDITION;
|
public static final String _RIM_LINK_HASH_STR = RIM_PFX + FX_SEPARATOR
|
||||||
public static final String _RIM_LINK_HASH_STR = RIM_PFX + FX_SEPARATOR +
|
+ RIM_LINK_HASH;
|
||||||
RIM_LINK_HASH;
|
public static final String _BINDING_SPEC_STR = RIM_PFX + FX_SEPARATOR
|
||||||
public static final String _BINDING_SPEC_STR = RIM_PFX + FX_SEPARATOR +
|
+ BINDING_SPEC;
|
||||||
BINDING_SPEC;
|
public static final String _BINDING_SPEC_VERSION_STR = RIM_PFX + FX_SEPARATOR
|
||||||
public static final String _BINDING_SPEC_VERSION_STR = RIM_PFX + FX_SEPARATOR +
|
+ BINDING_SPEC_VERSION;
|
||||||
BINDING_SPEC_VERSION;
|
public static final String _PLATFORM_MANUFACTURER_STR = RIM_PFX + FX_SEPARATOR
|
||||||
public static final String _PLATFORM_MANUFACTURER_STR = RIM_PFX + FX_SEPARATOR +
|
+ PLATFORM_MANUFACTURER_STR;
|
||||||
PLATFORM_MANUFACTURER_STR;
|
public static final String _PLATFORM_MANUFACTURER_ID_STR = RIM_PFX + FX_SEPARATOR
|
||||||
public static final String _PLATFORM_MANUFACTURER_ID_STR = RIM_PFX + FX_SEPARATOR +
|
+ PLATFORM_MANUFACTURER_ID;
|
||||||
PLATFORM_MANUFACTURER_ID;
|
public static final String _PLATFORM_MODEL_STR = RIM_PFX + FX_SEPARATOR
|
||||||
public static final String _PLATFORM_MODEL_STR = RIM_PFX + FX_SEPARATOR +
|
+ PLATFORM_MODEL;
|
||||||
PLATFORM_MODEL;
|
public static final String _PLATFORM_VERSION_STR = RIM_PFX + FX_SEPARATOR
|
||||||
public static final String _PLATFORM_VERSION_STR = RIM_PFX + FX_SEPARATOR +
|
+ PLATFORM_VERSION;
|
||||||
PLATFORM_VERSION;
|
public static final String _PAYLOAD_TYPE_STR = RIM_PFX + FX_SEPARATOR
|
||||||
public static final String _PAYLOAD_TYPE_STR = RIM_PFX + FX_SEPARATOR +
|
+ PAYLOAD_TYPE;
|
||||||
PAYLOAD_TYPE;
|
public static final String _PC_URI_LOCAL_STR = RIM_PFX + FX_SEPARATOR
|
||||||
public static final String _PC_URI_LOCAL_STR = RIM_PFX + FX_SEPARATOR +
|
+ 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() {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
package hirs.utils.swid;
|
@ -13,7 +13,7 @@ import java.io.IOException;
|
|||||||
* Class to process the DEVICE_SECURITY_EVENT_DATA_HEADER.
|
* Class to process the DEVICE_SECURITY_EVENT_DATA_HEADER.
|
||||||
* DEVICE_SECURITY_EVENT_DATA_HEADER contains the measurement(s) and hash algorithm identifier
|
* DEVICE_SECURITY_EVENT_DATA_HEADER contains the measurement(s) and hash algorithm identifier
|
||||||
* returned by the SPDM "GET_MEASUREMENTS" function.
|
* returned by the SPDM "GET_MEASUREMENTS" function.
|
||||||
*
|
* <p>
|
||||||
* HEADERS defined by PFP v1.06 Rev 52:
|
* HEADERS defined by PFP v1.06 Rev 52:
|
||||||
* <p>
|
* <p>
|
||||||
* typedef struct tdDEVICE_SECURITY_EVENT_DATA_HEADER {
|
* typedef struct tdDEVICE_SECURITY_EVENT_DATA_HEADER {
|
||||||
@ -62,8 +62,9 @@ public class DeviceSecurityEventDataHeader extends DeviceSecurityEventHeader {
|
|||||||
|
|
||||||
super(dsedBytes);
|
super(dsedBytes);
|
||||||
|
|
||||||
|
final int dsedBytesSrcIndex1 = 18;
|
||||||
byte[] lengthBytes = new byte[UefiConstants.SIZE_2];
|
byte[] lengthBytes = new byte[UefiConstants.SIZE_2];
|
||||||
System.arraycopy(dsedBytes, 18, lengthBytes, 0,
|
System.arraycopy(dsedBytes, dsedBytesSrcIndex1, lengthBytes, 0,
|
||||||
UefiConstants.SIZE_2);
|
UefiConstants.SIZE_2);
|
||||||
length = HexUtils.leReverseInt(lengthBytes);
|
length = HexUtils.leReverseInt(lengthBytes);
|
||||||
|
|
||||||
@ -72,18 +73,22 @@ public class DeviceSecurityEventDataHeader extends DeviceSecurityEventHeader {
|
|||||||
UefiConstants.SIZE_4);
|
UefiConstants.SIZE_4);
|
||||||
spdmHashAlgo = HexUtils.leReverseInt(spdmHashAlgoBytes);
|
spdmHashAlgo = HexUtils.leReverseInt(spdmHashAlgoBytes);
|
||||||
|
|
||||||
extractDeviceType(dsedBytes, 24);
|
final int dsedBytesStartByte = 24;
|
||||||
|
extractDeviceType(dsedBytes, dsedBytesStartByte);
|
||||||
|
|
||||||
// get the size of the SPDM Measurement Block
|
// get the size of the SPDM Measurement Block
|
||||||
|
final int dsedBytesSrcIndex2 = 30;
|
||||||
byte[] sizeOfSpdmMeasBlockBytes = new byte[UefiConstants.SIZE_2];
|
byte[] sizeOfSpdmMeasBlockBytes = new byte[UefiConstants.SIZE_2];
|
||||||
System.arraycopy(dsedBytes, 30, sizeOfSpdmMeasBlockBytes, 0,
|
System.arraycopy(dsedBytes, dsedBytesSrcIndex2, sizeOfSpdmMeasBlockBytes, 0,
|
||||||
UefiConstants.SIZE_2);
|
UefiConstants.SIZE_2);
|
||||||
int sizeOfSpdmMeas = HexUtils.leReverseInt(sizeOfSpdmMeasBlockBytes);
|
final int sizeOfSpdmMeas = HexUtils.leReverseInt(sizeOfSpdmMeasBlockBytes);
|
||||||
int sizeOfSpdmMeasBlock = sizeOfSpdmMeas + 4; // header is 4 bytes
|
final int offSetBytesForSpdm = 4;
|
||||||
|
final int sizeOfSpdmMeasBlock = sizeOfSpdmMeas + offSetBytesForSpdm; // header is 4 bytes
|
||||||
|
|
||||||
// extract the bytes that comprise the SPDM Measurement Block
|
// extract the bytes that comprise the SPDM Measurement Block
|
||||||
|
final int dsedBytesSrcIndex3 = 28;
|
||||||
byte[] spdmMeasBlockBytes = new byte[sizeOfSpdmMeasBlock];
|
byte[] spdmMeasBlockBytes = new byte[sizeOfSpdmMeasBlock];
|
||||||
System.arraycopy(dsedBytes, 28, spdmMeasBlockBytes, 0,
|
System.arraycopy(dsedBytes, dsedBytesSrcIndex3, spdmMeasBlockBytes, 0,
|
||||||
sizeOfSpdmMeasBlock);
|
sizeOfSpdmMeasBlock);
|
||||||
|
|
||||||
ByteArrayInputStream spdmMeasurementBlockData =
|
ByteArrayInputStream spdmMeasurementBlockData =
|
||||||
@ -96,7 +101,8 @@ public class DeviceSecurityEventDataHeader extends DeviceSecurityEventHeader {
|
|||||||
spdmMeasurementBlockInfo = " Error reading SPDM Measurement Block";
|
spdmMeasurementBlockInfo = " Error reading SPDM Measurement Block";
|
||||||
}
|
}
|
||||||
|
|
||||||
int devPathLenStartByte = 28 + sizeOfSpdmMeasBlock;
|
final int offSetBytesForDevPath = 28;
|
||||||
|
final int devPathLenStartByte = offSetBytesForDevPath + sizeOfSpdmMeasBlock;
|
||||||
extractDevicePathAndFinalSize(dsedBytes, devPathLenStartByte);
|
extractDevicePathAndFinalSize(dsedBytes, devPathLenStartByte);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ import lombok.Getter;
|
|||||||
* Class to process the DEVICE_SECURITY_EVENT_DATA_HEADER2.
|
* Class to process the DEVICE_SECURITY_EVENT_DATA_HEADER2.
|
||||||
* DEVICE_SECURITY_EVENT_DATA_HEADER2 contains the measurement(s) and hash algorithm identifier
|
* DEVICE_SECURITY_EVENT_DATA_HEADER2 contains the measurement(s) and hash algorithm identifier
|
||||||
* returned by the SPDM "GET_MEASUREMENTS" function.
|
* returned by the SPDM "GET_MEASUREMENTS" function.
|
||||||
*
|
* <p>
|
||||||
* HEADERS defined by PFP v1.06 Rev 52:
|
* HEADERS defined by PFP v1.06 Rev 52:
|
||||||
* <p>
|
* <p>
|
||||||
* typedef struct tdDEVICE_SECURITY_EVENT_DATA_HEADER2 {
|
* typedef struct tdDEVICE_SECURITY_EVENT_DATA_HEADER2 {
|
||||||
@ -27,6 +27,32 @@ import lombok.Getter;
|
|||||||
*/
|
*/
|
||||||
public class DeviceSecurityEventDataHeader2 extends DeviceSecurityEventHeader {
|
public class DeviceSecurityEventDataHeader2 extends DeviceSecurityEventHeader {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auth state - success.
|
||||||
|
*/
|
||||||
|
public static final int AUTH_SUCCESS = 0;
|
||||||
|
/**
|
||||||
|
* Auth state - digital signature of the data is valid, but the public key certificate chain is not
|
||||||
|
* validated with the entry in the UEFI device signature variable.
|
||||||
|
*/
|
||||||
|
public static final int AUTH_NO_AUTHORITY = 1;
|
||||||
|
/**
|
||||||
|
* Auth state - digital signature of the measurement data is valid, but the reported device capabilities,
|
||||||
|
* negotiated parameters or certificate chains were not validated by a transcript.
|
||||||
|
*/
|
||||||
|
public static final int AUTH_NO_BINDING = 2;
|
||||||
|
/**
|
||||||
|
* Auth state - data has no digital signature.
|
||||||
|
*/
|
||||||
|
public static final int AUTH_FAIL_NO_SIG = 3;
|
||||||
|
/**
|
||||||
|
* Auth state - data is invalid.
|
||||||
|
*/
|
||||||
|
public static final int AUTH_FAIL_INVALID = 4;
|
||||||
|
/**
|
||||||
|
* Auth state - device is not an SPDM-capable device.
|
||||||
|
*/
|
||||||
|
public static final int AUTH_NO_SPDM = 0xFF;
|
||||||
/**
|
/**
|
||||||
* Event auth state.
|
* Event auth state.
|
||||||
*/
|
*/
|
||||||
@ -55,33 +81,6 @@ public class DeviceSecurityEventDataHeader2 extends DeviceSecurityEventHeader {
|
|||||||
@Getter
|
@Getter
|
||||||
private String subHeaderUid = "";
|
private String subHeaderUid = "";
|
||||||
|
|
||||||
/**
|
|
||||||
* Auth state - success.
|
|
||||||
*/
|
|
||||||
public static final int AUTH_SUCCESS = 0;
|
|
||||||
/**
|
|
||||||
* Auth state - digital signature of the data is valid, but the public key certificate chain is not
|
|
||||||
* validated with the entry in the UEFI device signature variable.
|
|
||||||
*/
|
|
||||||
public static final int AUTH_NO_AUTHORITY = 1;
|
|
||||||
/**
|
|
||||||
* Auth state - digital signature of the measurement data is valid, but the reported device capabilities,
|
|
||||||
* negotiated parameters or certificate chains were not validated by a transcript.
|
|
||||||
*/
|
|
||||||
public static final int AUTH_NO_BINDING = 2;
|
|
||||||
/**
|
|
||||||
* Auth state - data has no digital signature.
|
|
||||||
*/
|
|
||||||
public static final int AUTH_FAIL_NO_SIG = 3;
|
|
||||||
/**
|
|
||||||
* Auth state - data is invalid.
|
|
||||||
*/
|
|
||||||
public static final int AUTH_FAIL_INVALID = 4;
|
|
||||||
/**
|
|
||||||
* Auth state - device is not an SPDM-capable device.
|
|
||||||
*/
|
|
||||||
public static final int AUTH_NO_SPDM = 0xFF;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DeviceSecurityEventDataHeader2 Constructor.
|
* DeviceSecurityEventDataHeader2 Constructor.
|
||||||
*
|
*
|
||||||
@ -91,33 +90,43 @@ public class DeviceSecurityEventDataHeader2 extends DeviceSecurityEventHeader {
|
|||||||
|
|
||||||
super(dsedBytes);
|
super(dsedBytes);
|
||||||
|
|
||||||
|
final int dsedBytesSrcIndex = 18;
|
||||||
byte[] authStateBytes = new byte[1];
|
byte[] authStateBytes = new byte[1];
|
||||||
System.arraycopy(dsedBytes, 18, authStateBytes, 0, 1);
|
System.arraycopy(dsedBytes, dsedBytesSrcIndex, authStateBytes, 0, 1);
|
||||||
authState = HexUtils.leReverseInt(authStateBytes);
|
authState = HexUtils.leReverseInt(authStateBytes);
|
||||||
|
|
||||||
// byte[] reserved[Bytes]: 1 byte
|
// byte[] reserved[Bytes]: 1 byte
|
||||||
|
|
||||||
byte[] lengthBytes = new byte[4];
|
final int dsedBytesSrcIndex2 = 20;
|
||||||
System.arraycopy(dsedBytes, 20, lengthBytes, 0, 4);
|
final int lengthBytesSize = 4;
|
||||||
|
byte[] lengthBytes = new byte[lengthBytesSize];
|
||||||
|
System.arraycopy(dsedBytes, dsedBytesSrcIndex2, lengthBytes, 0, lengthBytesSize);
|
||||||
length = HexUtils.leReverseInt(lengthBytes);
|
length = HexUtils.leReverseInt(lengthBytes);
|
||||||
|
|
||||||
extractDeviceType(dsedBytes, 24);
|
final int dsedBytesStartByte1 = 24;
|
||||||
|
extractDeviceType(dsedBytes, dsedBytesStartByte1);
|
||||||
|
|
||||||
byte[] subHeaderTypeBytes = new byte[4];
|
final int dsedBytesSrcIndex3 = 28;
|
||||||
System.arraycopy(dsedBytes, 28, subHeaderTypeBytes, 0, 4);
|
final int subHeaderTypeBytesSize = 4;
|
||||||
|
byte[] subHeaderTypeBytes = new byte[subHeaderTypeBytesSize];
|
||||||
|
System.arraycopy(dsedBytes, dsedBytesSrcIndex3, subHeaderTypeBytes, 0, subHeaderTypeBytesSize);
|
||||||
subHeaderType = HexUtils.leReverseInt(subHeaderTypeBytes);
|
subHeaderType = HexUtils.leReverseInt(subHeaderTypeBytes);
|
||||||
|
|
||||||
byte[] subHeaderLengthBytes = new byte[4];
|
final int dsedBytesSrcIndex4 = 32;
|
||||||
System.arraycopy(dsedBytes, 32, subHeaderLengthBytes, 0, 4);
|
final int subHeaderLengthBytesSize = 4;
|
||||||
|
byte[] subHeaderLengthBytes = new byte[subHeaderLengthBytesSize];
|
||||||
|
System.arraycopy(dsedBytes, dsedBytesSrcIndex4, subHeaderLengthBytes, 0, subHeaderLengthBytesSize);
|
||||||
subHeaderLength = HexUtils.leReverseInt(subHeaderLengthBytes);
|
subHeaderLength = HexUtils.leReverseInt(subHeaderLengthBytes);
|
||||||
|
|
||||||
byte[] subHeaderUidBytes = new byte[8];
|
final int dsedBytesSrcIndex5 = 36;
|
||||||
System.arraycopy(dsedBytes, 36, subHeaderUidBytes, 0, 8);
|
final int subHeaderUidBytesSize = 8;
|
||||||
|
byte[] subHeaderUidBytes = new byte[subHeaderUidBytesSize];
|
||||||
|
System.arraycopy(dsedBytes, dsedBytesSrcIndex5, subHeaderUidBytes, 0, subHeaderUidBytesSize);
|
||||||
subHeaderUidBytes = HexUtils.leReverseByte(subHeaderUidBytes);
|
subHeaderUidBytes = HexUtils.leReverseByte(subHeaderUidBytes);
|
||||||
subHeaderUid = HexUtils.byteArrayToHexString(subHeaderUidBytes);
|
subHeaderUid = HexUtils.byteArrayToHexString(subHeaderUidBytes);
|
||||||
|
|
||||||
int devPathLenStartByte = 44;
|
final int dsedBytesStartByte2 = 44;
|
||||||
extractDevicePathAndFinalSize(dsedBytes, devPathLenStartByte);
|
extractDevicePathAndFinalSize(dsedBytes, dsedBytesStartByte2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -139,22 +148,14 @@ public class DeviceSecurityEventDataHeader2 extends DeviceSecurityEventHeader {
|
|||||||
* @return a description of the auth state.
|
* @return a description of the auth state.
|
||||||
*/
|
*/
|
||||||
public String getAuthStateString() {
|
public String getAuthStateString() {
|
||||||
|
return switch (authState) {
|
||||||
switch (authState) {
|
case AUTH_SUCCESS -> ("AUTH_SUCCESS");
|
||||||
case AUTH_SUCCESS:
|
case AUTH_NO_AUTHORITY -> ("AUTH_NO_AUTHORITY");
|
||||||
return ("AUTH_SUCCESS");
|
case AUTH_NO_BINDING -> ("AUTH_NO_BINDING");
|
||||||
case AUTH_NO_AUTHORITY:
|
case AUTH_FAIL_NO_SIG -> ("AUTH_FAIL_NO_SIG");
|
||||||
return ("AUTH_NO_AUTHORITY");
|
case AUTH_FAIL_INVALID -> ("AUTH_FAIL_INVALID");
|
||||||
case AUTH_NO_BINDING:
|
case AUTH_NO_SPDM -> ("AUTH_NO_SPDM");
|
||||||
return ("AUTH_NO_BINDING");
|
default -> ("Auth State unknown");
|
||||||
case AUTH_FAIL_NO_SIG:
|
};
|
||||||
return ("AUTH_FAIL_NO_SIG");
|
|
||||||
case AUTH_FAIL_INVALID:
|
|
||||||
return ("AUTH_FAIL_INVALID");
|
|
||||||
case AUTH_NO_SPDM:
|
|
||||||
return ("AUTH_NO_SPDM");
|
|
||||||
default:
|
|
||||||
return ("Auth State unknown");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,28 +78,36 @@ public class DeviceSecurityEventDataPciContext extends DeviceSecurityEventDataDe
|
|||||||
|
|
||||||
super(dSEDpciContextBytes);
|
super(dSEDpciContextBytes);
|
||||||
|
|
||||||
|
final int dSEDpciContextBytesSrcIndex1 = 4;
|
||||||
byte[] pciVendorIdBytes = new byte[2];
|
byte[] pciVendorIdBytes = new byte[2];
|
||||||
System.arraycopy(dSEDpciContextBytes, 4, pciVendorIdBytes, 0, 2);
|
System.arraycopy(dSEDpciContextBytes, dSEDpciContextBytesSrcIndex1, pciVendorIdBytes, 0, 2);
|
||||||
vendorId = HexUtils.byteArrayToHexString(HexUtils.leReverseByte(pciVendorIdBytes));
|
vendorId = HexUtils.byteArrayToHexString(HexUtils.leReverseByte(pciVendorIdBytes));
|
||||||
|
|
||||||
|
final int dSEDpciContextBytesSrcIndex2 = 6;
|
||||||
byte[] pciDeviceIdBytes = new byte[2];
|
byte[] pciDeviceIdBytes = new byte[2];
|
||||||
System.arraycopy(dSEDpciContextBytes, 6, pciDeviceIdBytes, 0, 2);
|
System.arraycopy(dSEDpciContextBytes, dSEDpciContextBytesSrcIndex2, pciDeviceIdBytes, 0, 2);
|
||||||
deviceId = HexUtils.byteArrayToHexString(HexUtils.leReverseByte(pciDeviceIdBytes));
|
deviceId = HexUtils.byteArrayToHexString(HexUtils.leReverseByte(pciDeviceIdBytes));
|
||||||
|
|
||||||
|
final int dSEDpciContextBytesSrcIndex3 = 8;
|
||||||
byte[] pciRevisionIdBytes = new byte[1];
|
byte[] pciRevisionIdBytes = new byte[1];
|
||||||
System.arraycopy(dSEDpciContextBytes, 8, pciRevisionIdBytes, 0, 1);
|
System.arraycopy(dSEDpciContextBytes, dSEDpciContextBytesSrcIndex3, pciRevisionIdBytes, 0, 1);
|
||||||
revisionId = HexUtils.byteArrayToHexString(HexUtils.leReverseByte(pciRevisionIdBytes));
|
revisionId = HexUtils.byteArrayToHexString(HexUtils.leReverseByte(pciRevisionIdBytes));
|
||||||
|
|
||||||
byte[] pciClassCodeBytes = new byte[3];
|
final int dSEDpciContextBytesSrcIndex4 = 9;
|
||||||
System.arraycopy(dSEDpciContextBytes, 9, pciClassCodeBytes, 0, 3);
|
final int pciClassCodeBytesSize = 3;
|
||||||
|
byte[] pciClassCodeBytes = new byte[pciClassCodeBytesSize];
|
||||||
|
System.arraycopy(dSEDpciContextBytes, dSEDpciContextBytesSrcIndex4, pciClassCodeBytes, 0,
|
||||||
|
pciClassCodeBytesSize);
|
||||||
classCode = HexUtils.byteArrayToHexString(HexUtils.leReverseByte(pciClassCodeBytes));
|
classCode = HexUtils.byteArrayToHexString(HexUtils.leReverseByte(pciClassCodeBytes));
|
||||||
|
|
||||||
|
final int dSEDpciContextBytesSrcIndex5 = 12;
|
||||||
byte[] pciSubsystemVendorIdBytes = new byte[2];
|
byte[] pciSubsystemVendorIdBytes = new byte[2];
|
||||||
System.arraycopy(dSEDpciContextBytes, 12, pciSubsystemVendorIdBytes, 0, 2);
|
System.arraycopy(dSEDpciContextBytes, dSEDpciContextBytesSrcIndex5, pciSubsystemVendorIdBytes, 0, 2);
|
||||||
subsystemVendorId = HexUtils.byteArrayToHexString(HexUtils.leReverseByte(pciSubsystemVendorIdBytes));
|
subsystemVendorId = HexUtils.byteArrayToHexString(HexUtils.leReverseByte(pciSubsystemVendorIdBytes));
|
||||||
|
|
||||||
|
final int dSEDpciContextBytesSrcIndex6 = 14;
|
||||||
byte[] pciSubsystemIdBytes = new byte[2];
|
byte[] pciSubsystemIdBytes = new byte[2];
|
||||||
System.arraycopy(dSEDpciContextBytes, 14, pciSubsystemIdBytes, 0, 2);
|
System.arraycopy(dSEDpciContextBytes, dSEDpciContextBytesSrcIndex6, pciSubsystemIdBytes, 0, 2);
|
||||||
subsystemId = HexUtils.byteArrayToHexString(HexUtils.leReverseByte(pciSubsystemIdBytes));
|
subsystemId = HexUtils.byteArrayToHexString(HexUtils.leReverseByte(pciSubsystemIdBytes));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,8 +126,9 @@ public class DeviceSecurityEventDataPciContext extends DeviceSecurityEventDataDe
|
|||||||
dSEDpciContextInfo += " RevisionID = " + revisionId + "\n";
|
dSEDpciContextInfo += " RevisionID = " + revisionId + "\n";
|
||||||
|
|
||||||
List<String> classCodeList = translateDeviceClass(classCode);
|
List<String> classCodeList = translateDeviceClass(classCode);
|
||||||
|
final int validClassCodeListSize = 3;
|
||||||
dSEDpciContextInfo += " Device Class: \n";
|
dSEDpciContextInfo += " Device Class: \n";
|
||||||
if (classCodeList.size() == 3) {
|
if (classCodeList.size() == validClassCodeListSize) {
|
||||||
dSEDpciContextInfo += " Class = " + classCodeList.get(0) + "\n";
|
dSEDpciContextInfo += " Class = " + classCodeList.get(0) + "\n";
|
||||||
dSEDpciContextInfo += " Subclass = " + classCodeList.get(1) + "\n";
|
dSEDpciContextInfo += " Subclass = " + classCodeList.get(1) + "\n";
|
||||||
dSEDpciContextInfo += " Programming Interface = " + classCodeList.get(2) + "\n";
|
dSEDpciContextInfo += " Programming Interface = " + classCodeList.get(2) + "\n";
|
||||||
|
@ -61,16 +61,21 @@ public class DeviceSecurityEventDataSubHeaderCertChain extends DeviceSecurityEve
|
|||||||
|
|
||||||
// byte[] reserved[Bytes]: 1 byte
|
// byte[] reserved[Bytes]: 1 byte
|
||||||
|
|
||||||
byte[] spdmBaseHashAlgoBytes = new byte[4];
|
final int dsedSybHBytesSrcIndex1 = 4;
|
||||||
System.arraycopy(dsedSubHBytes, 4, spdmBaseHashAlgoBytes, 0, 4);
|
final int spdmBaseHashAlgoBytesSize = 4;
|
||||||
|
byte[] spdmBaseHashAlgoBytes = new byte[spdmBaseHashAlgoBytesSize];
|
||||||
|
System.arraycopy(dsedSubHBytes, dsedSybHBytesSrcIndex1, spdmBaseHashAlgoBytes, 0,
|
||||||
|
spdmBaseHashAlgoBytesSize);
|
||||||
spdmBaseHashAlgo = HexUtils.leReverseInt(spdmBaseHashAlgoBytes);
|
spdmBaseHashAlgo = HexUtils.leReverseInt(spdmBaseHashAlgoBytes);
|
||||||
|
|
||||||
// get the size of the SPDM Cert Chain
|
// get the size of the SPDM Cert Chain
|
||||||
int spdmCertChainSize = dsedSubHBytes.length - 8;
|
final int offsetForSpdmCertChain = 8;
|
||||||
|
int spdmCertChainSize = dsedSubHBytes.length - offsetForSpdmCertChain;
|
||||||
|
|
||||||
// extract the bytes that comprise the SPDM Cert Chain
|
// extract the bytes that comprise the SPDM Cert Chain
|
||||||
|
final int dsedSybHBytesSrcIndex2 = 8;
|
||||||
byte[] spdmCertChainBytes = new byte[spdmCertChainSize];
|
byte[] spdmCertChainBytes = new byte[spdmCertChainSize];
|
||||||
System.arraycopy(dsedSubHBytes, 8, spdmCertChainBytes, 0,
|
System.arraycopy(dsedSubHBytes, dsedSybHBytesSrcIndex2, spdmCertChainBytes, 0,
|
||||||
spdmCertChainSize);
|
spdmCertChainSize);
|
||||||
|
|
||||||
int spdmBaseHashAlgoSize = SpdmHa.tcgAlgIdToByteSize(spdmBaseHashAlgo);
|
int spdmBaseHashAlgoSize = SpdmHa.tcgAlgIdToByteSize(spdmBaseHashAlgo);
|
||||||
|
@ -22,7 +22,7 @@ import java.util.List;
|
|||||||
* SPDM_MEASUREMENT_BLOCK SpdmMeasurementBlock[SpdmMeasurementBlockCount];
|
* SPDM_MEASUREMENT_BLOCK SpdmMeasurementBlock[SpdmMeasurementBlockCount];
|
||||||
* } DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_MEASUREMENT_BLOCK;
|
* } DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_MEASUREMENT_BLOCK;
|
||||||
* <p>
|
* <p>
|
||||||
*
|
* <p>
|
||||||
* SpdmMeasurementBlock is an array of SPDM_MEASUREMENT_BLOCKs
|
* SpdmMeasurementBlock is an array of SPDM_MEASUREMENT_BLOCKs
|
||||||
* The size of each block is the same and can be found by either:
|
* The size of each block is the same and can be found by either:
|
||||||
* 1) 4 + SpdmMeasurementBlock MeasurementSize
|
* 1) 4 + SpdmMeasurementBlock MeasurementSize
|
||||||
@ -33,6 +33,10 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class DeviceSecurityEventDataSubHeaderSpdmMeasurementBlock extends DeviceSecurityEventDataSubHeader {
|
public class DeviceSecurityEventDataSubHeaderSpdmMeasurementBlock extends DeviceSecurityEventDataSubHeader {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of SPDM Measurement Blocks.
|
||||||
|
*/
|
||||||
|
private final List<SpdmMeasurementBlock> spdmMeasurementBlockList;
|
||||||
/**
|
/**
|
||||||
* SPDM version.
|
* SPDM version.
|
||||||
*/
|
*/
|
||||||
@ -48,11 +52,6 @@ public class DeviceSecurityEventDataSubHeaderSpdmMeasurementBlock extends Device
|
|||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
private int spdmMeasurementHashAlgo = -1;
|
private int spdmMeasurementHashAlgo = -1;
|
||||||
|
|
||||||
/**
|
|
||||||
* List of SPDM Measurement Blocks.
|
|
||||||
*/
|
|
||||||
private List<SpdmMeasurementBlock> spdmMeasurementBlockList;
|
|
||||||
/**
|
/**
|
||||||
* Error reading SPDM Measurement Block.
|
* Error reading SPDM Measurement Block.
|
||||||
*/
|
*/
|
||||||
@ -77,16 +76,21 @@ public class DeviceSecurityEventDataSubHeaderSpdmMeasurementBlock extends Device
|
|||||||
|
|
||||||
// byte[] reserved[Bytes]: 1 byte
|
// byte[] reserved[Bytes]: 1 byte
|
||||||
|
|
||||||
byte[] spdmMeasurementHashAlgoBytes = new byte[4];
|
final int spdmMeasurementHashAlgoBytesSize = 4;
|
||||||
System.arraycopy(dsedSubHBytes, 4, spdmMeasurementHashAlgoBytes, 0, 4);
|
final int dsedSubHBytesSrcIndex1 = 4;
|
||||||
|
byte[] spdmMeasurementHashAlgoBytes = new byte[spdmMeasurementHashAlgoBytesSize];
|
||||||
|
System.arraycopy(dsedSubHBytes, dsedSubHBytesSrcIndex1, spdmMeasurementHashAlgoBytes, 0,
|
||||||
|
spdmMeasurementHashAlgoBytesSize);
|
||||||
spdmMeasurementHashAlgo = HexUtils.leReverseInt(spdmMeasurementHashAlgoBytes);
|
spdmMeasurementHashAlgo = HexUtils.leReverseInt(spdmMeasurementHashAlgoBytes);
|
||||||
|
|
||||||
// get the total size of the SPDM Measurement Block List
|
// get the total size of the SPDM Measurement Block List
|
||||||
int spdmMeasurementBlockListSize = dsedSubHBytes.length - 8;
|
final int offsetForspdmMeasurementBlockList = 8;
|
||||||
|
final int spdmMeasurementBlockListSize = dsedSubHBytes.length - offsetForspdmMeasurementBlockList;
|
||||||
|
|
||||||
// extract the bytes that comprise the SPDM Measurement Block List
|
// extract the bytes that comprise the SPDM Measurement Block List
|
||||||
|
final int dsedSubHBytesSrcIndex2 = 8;
|
||||||
byte[] spdmMeasurementBlockListBytes = new byte[spdmMeasurementBlockListSize];
|
byte[] spdmMeasurementBlockListBytes = new byte[spdmMeasurementBlockListSize];
|
||||||
System.arraycopy(dsedSubHBytes, 8, spdmMeasurementBlockListBytes, 0,
|
System.arraycopy(dsedSubHBytes, dsedSubHBytesSrcIndex2, spdmMeasurementBlockListBytes, 0,
|
||||||
spdmMeasurementBlockListSize);
|
spdmMeasurementBlockListSize);
|
||||||
|
|
||||||
ByteArrayInputStream spdmMeasurementBlockListData =
|
ByteArrayInputStream spdmMeasurementBlockListData =
|
||||||
|
@ -12,7 +12,7 @@ import java.nio.charset.StandardCharsets;
|
|||||||
* The first 16 bytes of the event data header MUST be a String based identifier (Signature),
|
* The first 16 bytes of the event data header MUST be a String based identifier (Signature),
|
||||||
* NUL-terminated, per PFP. The only currently defined Signature is "SPDM Device Sec",
|
* NUL-terminated, per PFP. The only currently defined Signature is "SPDM Device Sec",
|
||||||
* which implies the data is a DEVICE_SECURITY_EVENT_DATA or ..DATA2.
|
* which implies the data is a DEVICE_SECURITY_EVENT_DATA or ..DATA2.
|
||||||
*
|
* <p>
|
||||||
* HEADERS defined by PFP v1.06 Rev 52.
|
* HEADERS defined by PFP v1.06 Rev 52.
|
||||||
* Certain fields are common to both ..HEADER and ..HEADER2, and are noted below the structures.
|
* Certain fields are common to both ..HEADER and ..HEADER2, and are noted below the structures.
|
||||||
* <p>
|
* <p>
|
||||||
@ -51,12 +51,16 @@ import java.nio.charset.StandardCharsets;
|
|||||||
*/
|
*/
|
||||||
public abstract class DeviceSecurityEventHeader {
|
public abstract class DeviceSecurityEventHeader {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UEFI Device Path Length.
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
private static final int DEVICE_PATH_LENGTH = 0;
|
||||||
/**
|
/**
|
||||||
* Contains the size (in bytes) of the header.
|
* Contains the size (in bytes) of the header.
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
private Integer dsedHeaderLength = 0;
|
private Integer dsedHeaderLength = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signature (text) data.
|
* Signature (text) data.
|
||||||
*/
|
*/
|
||||||
@ -73,11 +77,6 @@ public abstract class DeviceSecurityEventHeader {
|
|||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
private int deviceType = -1;
|
private int deviceType = -1;
|
||||||
/**
|
|
||||||
* UEFI Device Path Length.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private int devicePathLength = 0;
|
|
||||||
/**
|
/**
|
||||||
* UEFI Device path.
|
* UEFI Device path.
|
||||||
*/
|
*/
|
||||||
@ -129,21 +128,23 @@ public abstract class DeviceSecurityEventHeader {
|
|||||||
int startByteUpdated = startByte;
|
int startByteUpdated = startByte;
|
||||||
|
|
||||||
// get the device path length
|
// get the device path length
|
||||||
byte[] devicePathLengthBytes = new byte[8];
|
final int devicePathLengthBytesSize = 8;
|
||||||
System.arraycopy(dsedBytes, startByteUpdated, devicePathLengthBytes, 0, 8);
|
byte[] devicePathLengthBytes = new byte[devicePathLengthBytesSize];
|
||||||
int devicePathLength = HexUtils.leReverseInt(devicePathLengthBytes);
|
System.arraycopy(dsedBytes, startByteUpdated, devicePathLengthBytes, 0, devicePathLengthBytesSize);
|
||||||
|
int retrievedDevicePathLength = HexUtils.leReverseInt(devicePathLengthBytes);
|
||||||
|
|
||||||
// get the device path
|
// get the device path
|
||||||
if (devicePathLength > 0) {
|
if (retrievedDevicePathLength > 0) {
|
||||||
startByteUpdated = startByteUpdated + 8;
|
final int startByteUpdatedOffset = 8;
|
||||||
byte[] devPathBytes = new byte[devicePathLength];
|
startByteUpdated = startByteUpdated + startByteUpdatedOffset;
|
||||||
|
byte[] devPathBytes = new byte[retrievedDevicePathLength];
|
||||||
System.arraycopy(dsedBytes, startByteUpdated, devPathBytes,
|
System.arraycopy(dsedBytes, startByteUpdated, devPathBytes,
|
||||||
0, devicePathLength);
|
0, retrievedDevicePathLength);
|
||||||
devicePath = new UefiDevicePath(devPathBytes);
|
devicePath = new UefiDevicePath(devPathBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
// header total size
|
// header total size
|
||||||
dsedHeaderLength = startByteUpdated + devicePathLength;
|
dsedHeaderLength = startByteUpdated + retrievedDevicePathLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -154,16 +155,12 @@ public abstract class DeviceSecurityEventHeader {
|
|||||||
* @return name of the device type
|
* @return name of the device type
|
||||||
*/
|
*/
|
||||||
public String deviceTypeToString(final int deviceTypeInt) {
|
public String deviceTypeToString(final int deviceTypeInt) {
|
||||||
switch (deviceTypeInt) {
|
return switch (deviceTypeInt) {
|
||||||
case DeviceSecurityEventDataDeviceContext.DEVICE_TYPE_NONE:
|
case DeviceSecurityEventDataDeviceContext.DEVICE_TYPE_NONE -> "No device type";
|
||||||
return "No device type";
|
case DeviceSecurityEventDataDeviceContext.DEVICE_TYPE_PCI -> "PCI";
|
||||||
case DeviceSecurityEventDataDeviceContext.DEVICE_TYPE_PCI:
|
case DeviceSecurityEventDataDeviceContext.DEVICE_TYPE_USB -> "USB";
|
||||||
return "PCI";
|
default -> "Unknown or invalid Device Type";
|
||||||
case DeviceSecurityEventDataDeviceContext.DEVICE_TYPE_USB:
|
};
|
||||||
return "USB";
|
|
||||||
default:
|
|
||||||
return "Unknown or invalid Device Type";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -6,11 +6,6 @@ package hirs.utils.tpm.eventlog.events;
|
|||||||
*/
|
*/
|
||||||
public final class EvConstants {
|
public final class EvConstants {
|
||||||
|
|
||||||
/**
|
|
||||||
* Default private constructor so checkstyles doesn't complain
|
|
||||||
*/
|
|
||||||
private EvConstants() { }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type length = 4 bytes.
|
* Type length = 4 bytes.
|
||||||
*/
|
*/
|
||||||
@ -39,11 +34,11 @@ public final class EvConstants {
|
|||||||
* Each PCR bank holds 24 registers.
|
* Each PCR bank holds 24 registers.
|
||||||
*/
|
*/
|
||||||
public static final int PCR_COUNT = 24;
|
public static final int PCR_COUNT = 24;
|
||||||
// Event IDs
|
|
||||||
/**
|
/**
|
||||||
* Pre boot cert Event ID.
|
* Pre boot cert Event ID.
|
||||||
*/
|
*/
|
||||||
public static final int EV_PREBOOT_CERT = 0x00000000;
|
public static final int EV_PREBOOT_CERT = 0x00000000;
|
||||||
|
// Event IDs
|
||||||
/**
|
/**
|
||||||
* POST Code Event ID.
|
* POST Code Event ID.
|
||||||
*/
|
*/
|
||||||
@ -180,4 +175,9 @@ public final class EvConstants {
|
|||||||
* EFI SPDM Device Authority Event ID.
|
* EFI SPDM Device Authority Event ID.
|
||||||
*/
|
*/
|
||||||
public static final int EV_EFI_SPDM_DEVICE_AUTHORITY = 0x800000E4;
|
public static final int EV_EFI_SPDM_DEVICE_AUTHORITY = 0x800000E4;
|
||||||
|
/**
|
||||||
|
* Default private constructor so checkstyles doesn't complain.
|
||||||
|
*/
|
||||||
|
private EvConstants() {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ public class EvNoAction {
|
|||||||
signature = signature.replaceAll("[^\\P{C}\t\r\n]", ""); // remove null characters
|
signature = signature.replaceAll("[^\\P{C}\t\r\n]", ""); // remove null characters
|
||||||
if (signature.contains("Spec ID Event03")) { // implies CryptAgileFormat
|
if (signature.contains("Spec ID Event03")) { // implies CryptAgileFormat
|
||||||
EvEfiSpecIdEvent specIDEvent = new EvEfiSpecIdEvent(eventData);
|
EvEfiSpecIdEvent specIDEvent = new EvEfiSpecIdEvent(eventData);
|
||||||
noActionInfo += specIDEventToString(specIDEvent).toString();
|
noActionInfo += specIDEventToString(specIDEvent);
|
||||||
bSpecIDEvent = true;
|
bSpecIDEvent = true;
|
||||||
specVersion = String.format("%s.%s",
|
specVersion = String.format("%s.%s",
|
||||||
specIDEvent.getVersionMajor(),
|
specIDEvent.getVersionMajor(),
|
||||||
@ -126,25 +126,21 @@ public class EvNoAction {
|
|||||||
* @return a description of the locality.
|
* @return a description of the locality.
|
||||||
*/
|
*/
|
||||||
private String getLocality(final byte[] eventData) {
|
private String getLocality(final byte[] eventData) {
|
||||||
String localityInfo = "";
|
final int eventDataSrcIndex = 16;
|
||||||
byte[] localityBytes = new byte[1];
|
byte[] localityBytes = new byte[1];
|
||||||
System.arraycopy(eventData, 16, localityBytes, 0, 1);
|
System.arraycopy(eventData, eventDataSrcIndex, localityBytes, 0, 1);
|
||||||
int locality = HexUtils.leReverseInt(localityBytes);
|
final int locality = HexUtils.leReverseInt(localityBytes);
|
||||||
|
|
||||||
switch (locality) {
|
final int locality0 = 0;
|
||||||
case 0:
|
final int locality3 = 3;
|
||||||
localityInfo += "Locality 0 without an H-CRTM sequence";
|
final int locality4 = 4;
|
||||||
break;
|
|
||||||
case 3:
|
return switch (locality) {
|
||||||
localityInfo += "Locality 3 without an H-CRTM sequence";
|
case locality0 -> "Locality 0 without an H-CRTM sequence";
|
||||||
break;
|
case locality3 -> "Locality 3 without an H-CRTM sequence";
|
||||||
case 4:
|
case locality4 -> "Locality 4 with an H-CRTM sequence initialized";
|
||||||
localityInfo += "Locality 4 with an H-CRTM sequence initialized";
|
default -> "Unknown";
|
||||||
break;
|
};
|
||||||
default:
|
|
||||||
localityInfo += "Unknown";
|
|
||||||
}
|
|
||||||
return localityInfo;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -8,7 +8,7 @@ import java.nio.charset.StandardCharsets;
|
|||||||
* Class to process the NV_INDEX_DYNAMIC_EVENT_LOG_DATA per PFP.
|
* Class to process the NV_INDEX_DYNAMIC_EVENT_LOG_DATA per PFP.
|
||||||
* Per PFP, the first 16 bytes of the structure are a String based identifier (Signature),
|
* Per PFP, the first 16 bytes of the structure are a String based identifier (Signature),
|
||||||
* which are a NULL-terminated ASCII string "NvIndexDynamic".
|
* which are a NULL-terminated ASCII string "NvIndexDynamic".
|
||||||
*
|
* <p>
|
||||||
* HEADERS defined by PFP v1.06 Rev 52.
|
* HEADERS defined by PFP v1.06 Rev 52.
|
||||||
* Certain fields are common to both ..HEADER and ..HEADER2, and are noted below the structures.
|
* Certain fields are common to both ..HEADER and ..HEADER2, and are noted below the structures.
|
||||||
* <p>
|
* <p>
|
||||||
@ -43,13 +43,16 @@ public class NvIndexDynamicEventLogData {
|
|||||||
*/
|
*/
|
||||||
public NvIndexDynamicEventLogData(final byte[] eventData) {
|
public NvIndexDynamicEventLogData(final byte[] eventData) {
|
||||||
|
|
||||||
byte[] signatureBytes = new byte[16];
|
final int signatureBytesSize = 16;
|
||||||
System.arraycopy(eventData, 0, signatureBytes, 0, 16);
|
byte[] signatureBytes = new byte[signatureBytesSize];
|
||||||
|
System.arraycopy(eventData, 0, signatureBytes, 0, signatureBytesSize);
|
||||||
signature = new String(signatureBytes, StandardCharsets.UTF_8);
|
signature = new String(signatureBytes, StandardCharsets.UTF_8);
|
||||||
signature = signature.replaceAll("[^\\P{C}\t\r\n]", ""); // remove null characters
|
signature = signature.replaceAll("[^\\P{C}\t\r\n]", ""); // remove null characters
|
||||||
|
|
||||||
byte[] versionBytes = new byte[2];
|
final int versionBytesSize = 2;
|
||||||
System.arraycopy(eventData, 16, versionBytes, 0, 2);
|
final int eventDataSrcIndex1 = 16;
|
||||||
|
byte[] versionBytes = new byte[versionBytesSize];
|
||||||
|
System.arraycopy(eventData, eventDataSrcIndex1, versionBytes, 0, versionBytesSize);
|
||||||
String nvIndexVersion = HexUtils.byteArrayToHexString(versionBytes);
|
String nvIndexVersion = HexUtils.byteArrayToHexString(versionBytes);
|
||||||
if (nvIndexVersion.isEmpty()) {
|
if (nvIndexVersion.isEmpty()) {
|
||||||
nvIndexVersion = "version not readable";
|
nvIndexVersion = "version not readable";
|
||||||
@ -58,23 +61,28 @@ public class NvIndexDynamicEventLogData {
|
|||||||
nvIndexDynamicInfo += " Nv Index Dynamic Version = " + nvIndexVersion + "\n";
|
nvIndexDynamicInfo += " Nv Index Dynamic Version = " + nvIndexVersion + "\n";
|
||||||
|
|
||||||
// 6 bytes of Reserved data
|
// 6 bytes of Reserved data
|
||||||
|
final int uidBytesSize = 8;
|
||||||
byte[] uidBytes = new byte[8];
|
final int eventDataSrcIndex2 = 24;
|
||||||
System.arraycopy(eventData, 24, uidBytes, 0, 8);
|
byte[] uidBytes = new byte[uidBytesSize];
|
||||||
|
System.arraycopy(eventData, eventDataSrcIndex2, uidBytes, 0, uidBytesSize);
|
||||||
String uid = HexUtils.byteArrayToHexString(uidBytes);
|
String uid = HexUtils.byteArrayToHexString(uidBytes);
|
||||||
nvIndexDynamicInfo += " UID = " + uid + "\n";
|
nvIndexDynamicInfo += " UID = " + uid + "\n";
|
||||||
|
|
||||||
byte[] descriptionSizeBytes = new byte[2];
|
final int descriptionSizeBytesLength = 2;
|
||||||
System.arraycopy(eventData, 32, descriptionSizeBytes, 0, 2);
|
final int eventDataSrcIndex3 = 32;
|
||||||
|
byte[] descriptionSizeBytes = new byte[descriptionSizeBytesLength];
|
||||||
|
System.arraycopy(eventData, eventDataSrcIndex3, descriptionSizeBytes, 0, descriptionSizeBytesLength);
|
||||||
int descriptionSize = HexUtils.leReverseInt(descriptionSizeBytes);
|
int descriptionSize = HexUtils.leReverseInt(descriptionSizeBytes);
|
||||||
|
|
||||||
|
final int eventDataSrcIndex4 = 34;
|
||||||
byte[] descriptionBytes = new byte[descriptionSize];
|
byte[] descriptionBytes = new byte[descriptionSize];
|
||||||
System.arraycopy(eventData, 34, descriptionBytes, 0, descriptionSize);
|
System.arraycopy(eventData, eventDataSrcIndex4, descriptionBytes, 0, descriptionSize);
|
||||||
String description = new String(descriptionBytes, StandardCharsets.UTF_8);
|
String description = new String(descriptionBytes, StandardCharsets.UTF_8);
|
||||||
description = description.replaceAll("[^\\P{C}\t\r\n]", ""); // remove null characters
|
description = description.replaceAll("[^\\P{C}\t\r\n]", ""); // remove null characters
|
||||||
nvIndexDynamicInfo += " Description = " + description + "\n";
|
nvIndexDynamicInfo += " Description = " + description + "\n";
|
||||||
|
|
||||||
int dataSizeStartByte = 34 + descriptionSize;
|
final int dataSizeOffset = 34;
|
||||||
|
int dataSizeStartByte = dataSizeOffset + descriptionSize;
|
||||||
byte[] dataSizeBytes = new byte[2];
|
byte[] dataSizeBytes = new byte[2];
|
||||||
System.arraycopy(eventData, dataSizeStartByte, dataSizeBytes, 0, 2);
|
System.arraycopy(eventData, dataSizeStartByte, dataSizeBytes, 0, 2);
|
||||||
int dataSize = HexUtils.leReverseInt(dataSizeBytes);
|
int dataSize = HexUtils.leReverseInt(dataSizeBytes);
|
||||||
|
@ -8,7 +8,7 @@ import java.nio.charset.StandardCharsets;
|
|||||||
* Class to process the NV_INDEX_INSTANCE_EVENT_LOG_DATA per PFP.
|
* Class to process the NV_INDEX_INSTANCE_EVENT_LOG_DATA per PFP.
|
||||||
* Per PFP, the first 16 bytes of the structure are a String based identifier (Signature),
|
* Per PFP, the first 16 bytes of the structure are a String based identifier (Signature),
|
||||||
* which are a NULL-terminated ASCII string "NvIndexInstance".
|
* which are a NULL-terminated ASCII string "NvIndexInstance".
|
||||||
*
|
* <p>
|
||||||
* HEADERS defined by PFP v1.06 Rev 52.
|
* HEADERS defined by PFP v1.06 Rev 52.
|
||||||
* Certain fields are common to both ..HEADER and ..HEADER2, and are noted below the structures.
|
* Certain fields are common to both ..HEADER and ..HEADER2, and are noted below the structures.
|
||||||
* <p>
|
* <p>
|
||||||
@ -45,13 +45,15 @@ public class NvIndexInstanceEventLogData {
|
|||||||
*/
|
*/
|
||||||
public NvIndexInstanceEventLogData(final byte[] eventData) {
|
public NvIndexInstanceEventLogData(final byte[] eventData) {
|
||||||
|
|
||||||
byte[] signatureBytes = new byte[16];
|
final int signatureBytesSize = 16;
|
||||||
System.arraycopy(eventData, 0, signatureBytes, 0, 16);
|
byte[] signatureBytes = new byte[signatureBytesSize];
|
||||||
|
System.arraycopy(eventData, 0, signatureBytes, 0, signatureBytesSize);
|
||||||
signature = new String(signatureBytes, StandardCharsets.UTF_8);
|
signature = new String(signatureBytes, StandardCharsets.UTF_8);
|
||||||
signature = signature.replaceAll("[^\\P{C}\t\r\n]", ""); // remove null characters
|
signature = signature.replaceAll("[^\\P{C}\t\r\n]", ""); // remove null characters
|
||||||
|
|
||||||
|
final int eventDataSrcIndex1 = 16;
|
||||||
byte[] versionBytes = new byte[2];
|
byte[] versionBytes = new byte[2];
|
||||||
System.arraycopy(eventData, 16, versionBytes, 0, 2);
|
System.arraycopy(eventData, eventDataSrcIndex1, versionBytes, 0, 2);
|
||||||
String nvIndexVersion = HexUtils.byteArrayToHexString(versionBytes);
|
String nvIndexVersion = HexUtils.byteArrayToHexString(versionBytes);
|
||||||
if (nvIndexVersion == "") {
|
if (nvIndexVersion == "") {
|
||||||
nvIndexVersion = "version not readable";
|
nvIndexVersion = "version not readable";
|
||||||
@ -60,14 +62,16 @@ public class NvIndexInstanceEventLogData {
|
|||||||
nvIndexInstanceInfo += " Nv Index Instance Version = " + nvIndexVersion + "\n";
|
nvIndexInstanceInfo += " Nv Index Instance Version = " + nvIndexVersion + "\n";
|
||||||
|
|
||||||
// 6 bytes of Reserved data
|
// 6 bytes of Reserved data
|
||||||
|
final int eventDataSrcIndex2 = 24;
|
||||||
byte[] dsedSignatureBytes = new byte[16];
|
final int dsedSignatureBytesSize = 16;
|
||||||
System.arraycopy(eventData, 24, dsedSignatureBytes, 0, 16);
|
byte[] dsedSignatureBytes = new byte[dsedSignatureBytesSize];
|
||||||
|
System.arraycopy(eventData, eventDataSrcIndex2, dsedSignatureBytes, 0, dsedSignatureBytesSize);
|
||||||
String dsedSignature = new String(dsedSignatureBytes, StandardCharsets.UTF_8);
|
String dsedSignature = new String(dsedSignatureBytes, StandardCharsets.UTF_8);
|
||||||
dsedSignature = dsedSignature.replaceAll("[^\\P{C}\t\r\n]", ""); // remove null characters
|
dsedSignature = dsedSignature.replaceAll("[^\\P{C}\t\r\n]", ""); // remove null characters
|
||||||
|
|
||||||
|
final int eventDataSrcIndex3 = 40;
|
||||||
byte[] dsedVersionBytes = new byte[2];
|
byte[] dsedVersionBytes = new byte[2];
|
||||||
System.arraycopy(eventData, 40, dsedVersionBytes, 0, 2);
|
System.arraycopy(eventData, eventDataSrcIndex3, dsedVersionBytes, 0, 2);
|
||||||
String dsedVersion = HexUtils.byteArrayToHexString(dsedVersionBytes);
|
String dsedVersion = HexUtils.byteArrayToHexString(dsedVersionBytes);
|
||||||
if (dsedVersion == "") {
|
if (dsedVersion == "") {
|
||||||
dsedVersion = "version not readable";
|
dsedVersion = "version not readable";
|
||||||
@ -75,9 +79,10 @@ public class NvIndexInstanceEventLogData {
|
|||||||
|
|
||||||
if (dsedSignature.contains("SPDM Device Sec2")) {
|
if (dsedSignature.contains("SPDM Device Sec2")) {
|
||||||
|
|
||||||
int dsedEventDataSize = eventData.length - 24;
|
final int eventDataSrcIndex4 = 24;
|
||||||
|
final int dsedEventDataSize = eventData.length - eventDataSrcIndex4;
|
||||||
byte[] dsedEventData = new byte[dsedEventDataSize];
|
byte[] dsedEventData = new byte[dsedEventDataSize];
|
||||||
System.arraycopy(eventData, 24, dsedEventData, 0, dsedEventDataSize);
|
System.arraycopy(eventData, eventDataSrcIndex4, dsedEventData, 0, dsedEventDataSize);
|
||||||
|
|
||||||
nvIndexInstanceInfo += " Signature = SPDM Device Sec2\n";
|
nvIndexInstanceInfo += " Signature = SPDM Device Sec2\n";
|
||||||
|
|
||||||
@ -89,7 +94,7 @@ public class NvIndexInstanceEventLogData {
|
|||||||
+ dsedVersion + "\n";
|
+ dsedVersion + "\n";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
nvIndexInstanceInfo = " Signature error: should be \'SPDM Device Sec2\' but is "
|
nvIndexInstanceInfo = " Signature error: should be 'SPDM Device Sec2' but is "
|
||||||
+ signature + "\n";
|
+ signature + "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,10 @@ public class SpdmCertificateChain {
|
|||||||
// * Length of the certificate chain to include all fields in this structure.
|
// * Length of the certificate chain to include all fields in this structure.
|
||||||
// */
|
// */
|
||||||
//private int length = 0;
|
//private int length = 0;
|
||||||
|
/**
|
||||||
|
* Array List of certs found in the chain.
|
||||||
|
*/
|
||||||
|
private final ArrayList<UefiX509Cert> certList = new ArrayList<UefiX509Cert>();
|
||||||
/**
|
/**
|
||||||
* Root hash.
|
* Root hash.
|
||||||
*/
|
*/
|
||||||
@ -46,10 +50,6 @@ public class SpdmCertificateChain {
|
|||||||
* Number of certs in the SPDM cert chain.
|
* Number of certs in the SPDM cert chain.
|
||||||
*/
|
*/
|
||||||
private int numberOfCerts = 0;
|
private int numberOfCerts = 0;
|
||||||
/**
|
|
||||||
* Array List of certs found in the chain.
|
|
||||||
*/
|
|
||||||
private ArrayList<UefiX509Cert> certList = new ArrayList<UefiX509Cert>();
|
|
||||||
/**
|
/**
|
||||||
* Human-readable description of any error associated with SPDM base hash alg.
|
* Human-readable description of any error associated with SPDM base hash alg.
|
||||||
*/
|
*/
|
||||||
@ -76,11 +76,13 @@ public class SpdmCertificateChain {
|
|||||||
|
|
||||||
// Reserved: 2 bytes
|
// Reserved: 2 bytes
|
||||||
|
|
||||||
|
final int spdmCertChainBytesSrcIndex = 4;
|
||||||
rootHash = new byte[rootHashLength];
|
rootHash = new byte[rootHashLength];
|
||||||
System.arraycopy(spdmCertChainBytes, 4, rootHash, 0, rootHashLength);
|
System.arraycopy(spdmCertChainBytes, spdmCertChainBytesSrcIndex, rootHash, 0, rootHashLength);
|
||||||
|
|
||||||
int certChainStartPos = 4 + rootHashLength;
|
final int offsetForCertChain = 4;
|
||||||
int certChainLength = spdmCertChainBytes.length - certChainStartPos;
|
final int certChainStartPos = offsetForCertChain + rootHashLength;
|
||||||
|
final int certChainLength = spdmCertChainBytes.length - certChainStartPos;
|
||||||
byte[] certChainBytes = new byte[certChainLength];
|
byte[] certChainBytes = new byte[certChainLength];
|
||||||
System.arraycopy(spdmCertChainBytes, certChainStartPos, certChainBytes, 0, certChainLength);
|
System.arraycopy(spdmCertChainBytes, certChainStartPos, certChainBytes, 0, certChainLength);
|
||||||
|
|
||||||
@ -113,10 +115,11 @@ public class SpdmCertificateChain {
|
|||||||
byte[] certData = new byte[cLength];
|
byte[] certData = new byte[cLength];
|
||||||
certChainDataIS.read(certData);
|
certChainDataIS.read(certData);
|
||||||
// put the cert back together
|
// put the cert back together
|
||||||
byte[] certBlob = new byte[cLength + 4];
|
final int certBlobStartIndex = 4;
|
||||||
|
byte[] certBlob = new byte[cLength + certBlobStartIndex];
|
||||||
System.arraycopy(certType, 0, certBlob, 0, 2);
|
System.arraycopy(certType, 0, certBlob, 0, 2);
|
||||||
System.arraycopy(certLength, 0, certBlob, 2, 2);
|
System.arraycopy(certLength, 0, certBlob, 2, 2);
|
||||||
System.arraycopy(certData, 0, certBlob, 4, cLength);
|
System.arraycopy(certData, 0, certBlob, certBlobStartIndex, cLength);
|
||||||
cert = new UefiX509Cert(certBlob);
|
cert = new UefiX509Cert(certBlob);
|
||||||
//cert = new X509Certificate(certBlob);
|
//cert = new X509Certificate(certBlob);
|
||||||
certList.add(cert);
|
certList.add(cert);
|
||||||
|
@ -4,12 +4,7 @@ package hirs.utils.tpm.eventlog.spdm;
|
|||||||
* Class for defining hash algorithms referenced in the DMTF SPDM specification.
|
* Class for defining hash algorithms referenced in the DMTF SPDM specification.
|
||||||
* SPDM 1.3.0, Table 21, MeasurementHashAlgo.
|
* SPDM 1.3.0, Table 21, MeasurementHashAlgo.
|
||||||
*/
|
*/
|
||||||
public class SpdmHa {
|
public final class SpdmHa {
|
||||||
|
|
||||||
/**
|
|
||||||
* Default private constructor so checkstyles doesn't complain
|
|
||||||
*/
|
|
||||||
private SpdmHa() { }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Spdm Hash Alg = Raw bit stream.
|
* Spdm Hash Alg = Raw bit stream.
|
||||||
@ -40,6 +35,12 @@ public class SpdmHa {
|
|||||||
*/
|
*/
|
||||||
public static final int TPM_ALG_SHA3_512 = 64;
|
public static final int TPM_ALG_SHA3_512 = 64;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default private constructor so checkstyles doesn't complain.
|
||||||
|
*/
|
||||||
|
private SpdmHa() {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the hash name via a lookup.
|
* Returns the hash name via a lookup.
|
||||||
* Lookup based upon SPDM Spec v1.03 section 10.4.
|
* Lookup based upon SPDM Spec v1.03 section 10.4.
|
||||||
@ -48,32 +49,16 @@ public class SpdmHa {
|
|||||||
* @return name of the algorithm
|
* @return name of the algorithm
|
||||||
*/
|
*/
|
||||||
public static String tcgAlgIdToString(final int algId) {
|
public static String tcgAlgIdToString(final int algId) {
|
||||||
String alg;
|
String alg = switch (algId) {
|
||||||
switch (algId) {
|
case TPM_ALG_RAW -> "Raw Bit Stream";
|
||||||
case TPM_ALG_RAW:
|
case TPM_ALG_SHA_256 -> "TPM_ALG_SHA_256";
|
||||||
alg = "Raw Bit Stream";
|
case TPM_ALG_SHA_384 -> "TPM_ALG_SHA_384";
|
||||||
break;
|
case TPM_ALG_SHA_512 -> "TPM_ALG_SHA_512";
|
||||||
case TPM_ALG_SHA_256:
|
case TPM_ALG_SHA3_256 -> "TPM_ALG_SHA3_256";
|
||||||
alg = "TPM_ALG_SHA_256";
|
case TPM_ALG_SHA3_384 -> "TPM_ALG_SHA3_384";
|
||||||
break;
|
case TPM_ALG_SHA3_512 -> "TPM_ALG_SHA3_512";
|
||||||
case TPM_ALG_SHA_384:
|
default -> "Unknown or invalid Hash";
|
||||||
alg = "TPM_ALG_SHA_384";
|
};
|
||||||
break;
|
|
||||||
case TPM_ALG_SHA_512:
|
|
||||||
alg = "TPM_ALG_SHA_512";
|
|
||||||
break;
|
|
||||||
case TPM_ALG_SHA3_256:
|
|
||||||
alg = "TPM_ALG_SHA3_256";
|
|
||||||
break;
|
|
||||||
case TPM_ALG_SHA3_384:
|
|
||||||
alg = "TPM_ALG_SHA3_384";
|
|
||||||
break;
|
|
||||||
case TPM_ALG_SHA3_512:
|
|
||||||
alg = "TPM_ALG_SHA3_512";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
alg = "Unknown or invalid Hash";
|
|
||||||
}
|
|
||||||
return alg;
|
return alg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,32 +70,17 @@ public class SpdmHa {
|
|||||||
* @return size of the algorithm output
|
* @return size of the algorithm output
|
||||||
*/
|
*/
|
||||||
public static int tcgAlgIdToByteSize(final int algId) {
|
public static int tcgAlgIdToByteSize(final int algId) {
|
||||||
int byteSize;
|
final int byteSize256 = 32;
|
||||||
switch (algId) {
|
final int byteSize384 = 48;
|
||||||
|
final int byteSize512 = 64;
|
||||||
|
|
||||||
|
return switch (algId) {
|
||||||
// case TPM_ALG_RAW: // add this when have more test data
|
// case TPM_ALG_RAW: // add this when have more test data
|
||||||
// byteSize = ;
|
// return ;
|
||||||
// break;
|
case TPM_ALG_SHA_256, TPM_ALG_SHA3_256 -> byteSize256;
|
||||||
case TPM_ALG_SHA_256:
|
case TPM_ALG_SHA_384, TPM_ALG_SHA3_384 -> byteSize384;
|
||||||
byteSize = 32;
|
case TPM_ALG_SHA_512, TPM_ALG_SHA3_512 -> byteSize512;
|
||||||
break;
|
default -> -1;
|
||||||
case TPM_ALG_SHA_384:
|
};
|
||||||
byteSize = 48;
|
|
||||||
break;
|
|
||||||
case TPM_ALG_SHA_512:
|
|
||||||
byteSize = 64;
|
|
||||||
break;
|
|
||||||
case TPM_ALG_SHA3_256:
|
|
||||||
byteSize = 32;
|
|
||||||
break;
|
|
||||||
case TPM_ALG_SHA3_384:
|
|
||||||
byteSize = 48;
|
|
||||||
break;
|
|
||||||
case TPM_ALG_SHA3_512:
|
|
||||||
byteSize = 64;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
byteSize = -1;
|
|
||||||
}
|
|
||||||
return byteSize;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,15 +27,70 @@ import lombok.Getter;
|
|||||||
*/
|
*/
|
||||||
public class SpdmMeasurement {
|
public class SpdmMeasurement {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MEASUREMENT_VALUE_0 = Immutable ROM.
|
||||||
|
*/
|
||||||
|
private static final int MEASUREMENT_VALUE_0 = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MEASUREMENT_VALUE_1 = Mutable firmware.
|
||||||
|
*/
|
||||||
|
private static final int MEASUREMENT_VALUE_1 = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MEASUREMENT_VALUE_2 = Hardware configuration.
|
||||||
|
*/
|
||||||
|
private static final int MEASUREMENT_VALUE_2 = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MEASUREMENT_VALUE_3 = Firmware configuration.
|
||||||
|
*/
|
||||||
|
private static final int MEASUREMENT_VALUE_3 = 3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MEASUREMENT_VALUE_4 = Freeform measurement manifest.
|
||||||
|
*/
|
||||||
|
private static final int MEASUREMENT_VALUE_4 = 4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MEASUREMENT_VALUE_5 = Structured representation of debug and device mode.
|
||||||
|
*/
|
||||||
|
private static final int MEASUREMENT_VALUE_5 = 5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MEASUREMENT_VALUE_6 = Mutable firmware's version number.
|
||||||
|
*/
|
||||||
|
private static final int MEASUREMENT_VALUE_6 = 6;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MEASUREMENT_VALUE_7 = Mutable firmware's security version number.
|
||||||
|
*/
|
||||||
|
private static final int MEASUREMENT_VALUE_7 = 7;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MEASUREMENT_VALUE_8 = Hash-extended measurement.
|
||||||
|
*/
|
||||||
|
private static final int MEASUREMENT_VALUE_8 = 8;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MEASUREMENT_VALUE_9 = Informational.
|
||||||
|
*/
|
||||||
|
private static final int MEASUREMENT_VALUE_9 = 9;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MEASUREMENT_VALUE_10 = Structured measurement manifest.
|
||||||
|
*/
|
||||||
|
private static final int MEASUREMENT_VALUE_10 = 10;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Measurement value (digest).
|
||||||
|
*/
|
||||||
|
private final byte[] dmtfSpecMeasurementValue;
|
||||||
/**
|
/**
|
||||||
* Measurement value type (such as mutable firmware, etc).
|
* Measurement value type (such as mutable firmware, etc).
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
private int dmtfSpecMeasurementValueType = 0;
|
private int dmtfSpecMeasurementValueType = 0;
|
||||||
/**
|
|
||||||
* Measurement value (digest).
|
|
||||||
*/
|
|
||||||
private byte[] dmtfSpecMeasurementValue;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SpdmMeasurement Constructor.
|
* SpdmMeasurement Constructor.
|
||||||
@ -49,14 +104,16 @@ public class SpdmMeasurement {
|
|||||||
1);
|
1);
|
||||||
dmtfSpecMeasurementValueType = HexUtils.leReverseInt(dmtfSpecMeasurementValueTypeBytes);
|
dmtfSpecMeasurementValueType = HexUtils.leReverseInt(dmtfSpecMeasurementValueTypeBytes);
|
||||||
|
|
||||||
// in future, can crosscheck this value size + 3 with the spdm block MeasurementSize size
|
// in the future, can crosscheck this value size + 3 with the spdm block MeasurementSize size
|
||||||
byte[] dmtfSpecMeasurementValueSizeBytes = new byte[2];
|
byte[] dmtfSpecMeasurementValueSizeBytes = new byte[2];
|
||||||
System.arraycopy(spdmMeasBytes, 1, dmtfSpecMeasurementValueSizeBytes, 0,
|
System.arraycopy(spdmMeasBytes, 1, dmtfSpecMeasurementValueSizeBytes, 0,
|
||||||
2);
|
2);
|
||||||
int dmtfSpecMeasurementValueSize = HexUtils.leReverseInt(dmtfSpecMeasurementValueSizeBytes);
|
int dmtfSpecMeasurementValueSize = HexUtils.leReverseInt(dmtfSpecMeasurementValueSizeBytes);
|
||||||
|
|
||||||
dmtfSpecMeasurementValue = new byte[dmtfSpecMeasurementValueSize];
|
dmtfSpecMeasurementValue = new byte[dmtfSpecMeasurementValueSize];
|
||||||
System.arraycopy(spdmMeasBytes, 3, dmtfSpecMeasurementValue, 0,
|
|
||||||
|
final int sourceIndex = 3;
|
||||||
|
System.arraycopy(spdmMeasBytes, sourceIndex, dmtfSpecMeasurementValue, 0,
|
||||||
dmtfSpecMeasurementValueSize);
|
dmtfSpecMeasurementValueSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,50 +121,23 @@ public class SpdmMeasurement {
|
|||||||
* Lookup for SPDM measurement value type.
|
* Lookup for SPDM measurement value type.
|
||||||
*
|
*
|
||||||
* @param measValType the numerical representation of the measurement value type.
|
* @param measValType the numerical representation of the measurement value type.
|
||||||
*
|
|
||||||
* @return a description of the measurement value type.
|
* @return a description of the measurement value type.
|
||||||
*/
|
*/
|
||||||
public String dmtfSpecMeasurementValueTypeToString(final int measValType) {
|
public String dmtfSpecMeasurementValueTypeToString(final int measValType) {
|
||||||
|
return switch (measValType) {
|
||||||
String measValTypeStr;
|
case MEASUREMENT_VALUE_0 -> "Immutable ROM";
|
||||||
switch (measValType) {
|
case MEASUREMENT_VALUE_1 -> "Mutable firmware";
|
||||||
case 0:
|
case MEASUREMENT_VALUE_2 -> "Hardware configuration";
|
||||||
measValTypeStr = "Immutable ROM";
|
case MEASUREMENT_VALUE_3 -> "Firmware configuration";
|
||||||
break;
|
case MEASUREMENT_VALUE_4 -> "Freeform measurement manifest";
|
||||||
case 1:
|
case MEASUREMENT_VALUE_5 -> "Structured representation of debug and device mode";
|
||||||
measValTypeStr = "Mutable firmware";
|
case MEASUREMENT_VALUE_6 -> "Mutable firmware's version number";
|
||||||
break;
|
case MEASUREMENT_VALUE_7 -> "Mutable firmware's security version number";
|
||||||
case 2:
|
case MEASUREMENT_VALUE_8 -> "Hash-extended measurement";
|
||||||
measValTypeStr = "Hardware configuration";
|
case MEASUREMENT_VALUE_9 -> "Informational";
|
||||||
break;
|
case MEASUREMENT_VALUE_10 -> "Structured measurement manifest";
|
||||||
case 3:
|
default -> "Unknown or invalid DMTF Spec Measurement Value Type";
|
||||||
measValTypeStr = "Firmware configuration";
|
};
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
measValTypeStr = "Freeform measurement manifest";
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
measValTypeStr = "Structured representation of debug and device mode";
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
measValTypeStr = "Mutable firmware's version number";
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
measValTypeStr = "Mutable firmware's security version number";
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
measValTypeStr = "Hash-extended measurement";
|
|
||||||
break;
|
|
||||||
case 9:
|
|
||||||
measValTypeStr = "Informational";
|
|
||||||
break;
|
|
||||||
case 10:
|
|
||||||
measValTypeStr = "Structured measurement manifest";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
measValTypeStr = "Unknown or invalid DMTF Spec Measurement Value Type";
|
|
||||||
}
|
|
||||||
return measValTypeStr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -7,11 +7,6 @@ package hirs.utils.tpm.eventlog.uefi;
|
|||||||
*/
|
*/
|
||||||
public final class UefiConstants {
|
public final class UefiConstants {
|
||||||
|
|
||||||
/**
|
|
||||||
* Default private constructor so checkstyles doesn't complain
|
|
||||||
*/
|
|
||||||
private UefiConstants() { }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 2 byte size.
|
* 2 byte size.
|
||||||
*/
|
*/
|
||||||
@ -287,4 +282,9 @@ public final class UefiConstants {
|
|||||||
* file status, where file is not accessible (either not found, or no access permission).
|
* file status, where file is not accessible (either not found, or no access permission).
|
||||||
*/
|
*/
|
||||||
public static final String FILESTATUS_NOT_ACCESSIBLE = "fileNotAccessible";
|
public static final String FILESTATUS_NOT_ACCESSIBLE = "fileNotAccessible";
|
||||||
|
/**
|
||||||
|
* Default private constructor so checkstyles doesn't complain.
|
||||||
|
*/
|
||||||
|
private UefiConstants() {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,436 +1,20 @@
|
|||||||
package hirs.data.persist;
|
package hirs.data.persist;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
import hirs.utils.digest.Digest;
|
import hirs.utils.digest.Digest;
|
||||||
import hirs.utils.digest.DigestAlgorithm;
|
import hirs.utils.digest.DigestAlgorithm;
|
||||||
import hirs.utils.digest.DigestComparisonResultType;
|
import hirs.utils.digest.DigestComparisonResultType;
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests for the <code>Digest</code> class.
|
* Unit tests for the <code>Digest</code> class.
|
||||||
*/
|
*/
|
||||||
public class DigestTest {
|
public class DigestTest {
|
||||||
private static final int DIGEST_LENGTH_BYTES = 20;
|
private static final int DIGEST_LENGTH_BYTES = 20;
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that constructor throws a <code>IllegalArgumentException</code> when a
|
|
||||||
* null <code>DigestAlgorithm</code> is passed into constructor.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void nullAlgorithm() {
|
|
||||||
final byte[] digest = getTestDigest(16);
|
|
||||||
Assertions.assertThrows(IllegalArgumentException.class,
|
|
||||||
() -> new Digest(null, digest));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that constructor throws a <code>IllegalArgumentException</code> when a
|
|
||||||
* null digest is passed into constructor.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void nullDigest() {
|
|
||||||
Assertions.assertThrows(IllegalArgumentException.class,
|
|
||||||
() -> new Digest(DigestAlgorithm.MD2, null));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that constructor throws a <code>IllegalArgumentException</code> when an
|
|
||||||
* digest that is an empty array is passed into constructor.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void emptyArrayDigest() {
|
|
||||||
Assertions.assertThrows(IllegalArgumentException.class,
|
|
||||||
() -> new Digest(DigestAlgorithm.MD2, new byte[0]));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that MD2 digest can be created.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void md2() {
|
|
||||||
final byte[] digest = getTestDigest(16);
|
|
||||||
final Digest d = new Digest(DigestAlgorithm.MD2, digest);
|
|
||||||
Assertions.assertNotNull(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that an MD2 digest can be recreated from a string.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void testFromStringMD2() {
|
|
||||||
final byte[] digestBytes = getTestDigest(16);
|
|
||||||
Digest digest = new Digest(DigestAlgorithm.MD2, digestBytes);
|
|
||||||
String digestString = digest.toString();
|
|
||||||
Digest digestFromString = Digest.fromString(digestString);
|
|
||||||
Assertions.assertEquals(digest, digestFromString);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that MD2 digest cannot be created with a digest that has extra
|
|
||||||
* bytes.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void md2IllegalDigest() {
|
|
||||||
final byte[] digest = getTestDigest(17);
|
|
||||||
Assertions.assertThrows(IllegalArgumentException.class,
|
|
||||||
() -> new Digest(DigestAlgorithm.MD2, digest));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that MD5 digest can be created.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void md5() {
|
|
||||||
final byte[] digest = getTestDigest(16);
|
|
||||||
final Digest d = new Digest(DigestAlgorithm.MD5, digest);
|
|
||||||
Assertions.assertNotNull(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that an MD5 digest can be recreated from a string.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void testFromStringMD5() {
|
|
||||||
final byte[] digestBytes = getTestDigest(16);
|
|
||||||
Digest digest = new Digest(DigestAlgorithm.MD5, digestBytes);
|
|
||||||
String digestString = digest.toString();
|
|
||||||
Digest digestFromString = Digest.fromString(digestString);
|
|
||||||
Assertions.assertEquals(digest, digestFromString);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that MD5 digest cannot be created with a digest that has extra
|
|
||||||
* bytes.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void md5IllegalDigest() {
|
|
||||||
final byte[] digest = getTestDigest(17);
|
|
||||||
Assertions.assertThrows(IllegalArgumentException.class,
|
|
||||||
() -> new Digest(DigestAlgorithm.MD5, digest));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that SHA1 digest can be created.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void sha1() {
|
|
||||||
final byte[] digest = getTestDigest(20);
|
|
||||||
final Digest d = new Digest(DigestAlgorithm.SHA1, digest);
|
|
||||||
Assertions.assertNotNull(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that SHA1 digest can be recreated from a string.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void testFromStringSHA1() {
|
|
||||||
final byte[] digestBytes = getTestDigest(20);
|
|
||||||
Digest digest = new Digest(DigestAlgorithm.SHA1, digestBytes);
|
|
||||||
String digestString = digest.toString();
|
|
||||||
Digest digestFromString = Digest.fromString(digestString);
|
|
||||||
Assertions.assertEquals(digest, digestFromString);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that SHA1 digest cannot be created with a digest that has extra
|
|
||||||
* bytes.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void sha1IllegalDigest() {
|
|
||||||
final byte[] digest = getTestDigest(21);
|
|
||||||
Assertions.assertThrows(IllegalArgumentException.class,
|
|
||||||
() -> new Digest(DigestAlgorithm.SHA1, digest));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that SHA256 digest can be created.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void sha256() {
|
|
||||||
final byte[] digest = getTestDigest(32);
|
|
||||||
final Digest d = new Digest(DigestAlgorithm.SHA256, digest);
|
|
||||||
Assertions.assertNotNull(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that SHA256 digest can be recreated from a string.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void testFromStringSHA256() {
|
|
||||||
final byte[] digestBytes = getTestDigest(32);
|
|
||||||
Digest digest = new Digest(DigestAlgorithm.SHA256, digestBytes);
|
|
||||||
String digestString = digest.toString();
|
|
||||||
Digest digestFromString = Digest.fromString(digestString);
|
|
||||||
Assertions.assertEquals(digest, digestFromString);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that SHA256 digest cannot be created with a digest that has extra
|
|
||||||
* bytes.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void sha256IllegalDigest() {
|
|
||||||
final byte[] digest = getTestDigest(33);
|
|
||||||
Assertions.assertThrows(IllegalArgumentException.class,
|
|
||||||
() -> new Digest(DigestAlgorithm.SHA256, digest));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that SHA384 digest can be created.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void sha384() {
|
|
||||||
final byte[] digest = getTestDigest(48);
|
|
||||||
final Digest d = new Digest(DigestAlgorithm.SHA384, digest);
|
|
||||||
Assertions.assertNotNull(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that SHA384 digest can be recreated from a string.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void testFromStringSHA384() {
|
|
||||||
final byte[] digestBytes = getTestDigest(48);
|
|
||||||
Digest digest = new Digest(DigestAlgorithm.SHA384, digestBytes);
|
|
||||||
String digestString = digest.toString();
|
|
||||||
Digest digestFromString = Digest.fromString(digestString);
|
|
||||||
Assertions.assertEquals(digest, digestFromString);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that SHA384 digest cannot be created with a digest that has extra
|
|
||||||
* bytes.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void sha384IllegalDigest() {
|
|
||||||
final byte[] digest = getTestDigest(49);
|
|
||||||
Assertions.assertThrows(IllegalArgumentException.class,
|
|
||||||
() -> new Digest(DigestAlgorithm.SHA384, digest));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that SHA512 digest can be created.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void sha512() {
|
|
||||||
final byte[] digest = getTestDigest(64);
|
|
||||||
final Digest d = new Digest(DigestAlgorithm.SHA512, digest);
|
|
||||||
Assertions.assertNotNull(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that SHA512 digest can be recreated from a string.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void testFromStringSHA512() {
|
|
||||||
final byte[] digestBytes = getTestDigest(64);
|
|
||||||
Digest digest = new Digest(DigestAlgorithm.SHA512, digestBytes);
|
|
||||||
String digestString = digest.toString();
|
|
||||||
Digest digestFromString = Digest.fromString(digestString);
|
|
||||||
Assertions.assertEquals(digest, digestFromString);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that SHA512 digest cannot be created with a digest that has extra
|
|
||||||
* bytes.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void sha512IllegalDigest() {
|
|
||||||
final byte[] digest = getTestDigest(65);
|
|
||||||
Assertions.assertThrows(IllegalArgumentException.class,
|
|
||||||
() -> new Digest(DigestAlgorithm.SHA512, digest));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that the correct <code>DigestAlgorithm</code> is returned by
|
|
||||||
* {@link Digest#getAlgorithm()}.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void testGetAlgorithm() {
|
|
||||||
final Digest d = new Digest(DigestAlgorithm.SHA1, getTestDigest(20));
|
|
||||||
Assertions.assertEquals(d.getAlgorithm(), DigestAlgorithm.SHA1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that the bytes of the digest are created and do not affect the
|
|
||||||
* underlying state of the <code>Digest</code> instance.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void testGetDigest() {
|
|
||||||
final Digest d = new Digest(DigestAlgorithm.SHA1, getTestDigest(20));
|
|
||||||
final byte[] digestBytes = d.getDigest();
|
|
||||||
final byte[] testBytes = getTestDigest(20);
|
|
||||||
Assertions.assertArrayEquals(digestBytes, testBytes);
|
|
||||||
digestBytes[0] = (byte) (digestBytes[0] + 1);
|
|
||||||
Assertions.assertArrayEquals(d.getDigest(), testBytes);
|
|
||||||
Assertions.assertFalse(Arrays.equals(d.getDigest(), digestBytes));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that two <code>Digest</code>s have equal hash code for same
|
|
||||||
* algorithm and digest.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void testHashCodeEqual() {
|
|
||||||
final Digest d1 = new Digest(DigestAlgorithm.SHA1, getTestDigest(20));
|
|
||||||
final Digest d2 = new Digest(DigestAlgorithm.SHA1, getTestDigest(20));
|
|
||||||
Assertions.assertEquals(d2.hashCode(), d1.hashCode());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that two <code>Digest</code>s indicate MATCH when compared.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void testMatchedComparison() {
|
|
||||||
final Digest d1 = new Digest(DigestAlgorithm.SHA1, getTestDigest(20));
|
|
||||||
final Digest d2 = new Digest(DigestAlgorithm.SHA1, getTestDigest(20));
|
|
||||||
Assertions.assertEquals(DigestComparisonResultType.MATCH, d1.compare(d2));
|
|
||||||
Assertions.assertEquals(DigestComparisonResultType.MATCH, d2.compare(d1));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that two <code>Digest</code>s have unequal hash code for same
|
|
||||||
* digest but different algorithm.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void testHashCodeNotEqualAlgorithm() {
|
|
||||||
final Digest d1 = new Digest(DigestAlgorithm.MD2, getTestDigest(16));
|
|
||||||
final Digest d2 = new Digest(DigestAlgorithm.MD5, getTestDigest(16));
|
|
||||||
Assertions.assertNotEquals(d2.hashCode(), d1.hashCode());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that two <code>Digest</code>s indicate MISMATCH when compared.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void testMismatchAlgorithm() {
|
|
||||||
final Digest d1 = new Digest(DigestAlgorithm.MD2, getTestDigest(16));
|
|
||||||
final Digest d2 = new Digest(DigestAlgorithm.MD5, getTestDigest(16));
|
|
||||||
Assertions.assertEquals(DigestComparisonResultType.MISMATCH, d1.compare(d2));
|
|
||||||
Assertions.assertEquals(DigestComparisonResultType.MISMATCH, d2.compare(d1));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that two <code>Digest</code>s have unequal hash code for same
|
|
||||||
* algorithm but different digest.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void testHashCodeNotEqualDigest() {
|
|
||||||
final byte[] digest = getTestDigest(20);
|
|
||||||
final Digest d1 = new Digest(DigestAlgorithm.SHA1, digest);
|
|
||||||
digest[0] += 1;
|
|
||||||
final Digest d2 = new Digest(DigestAlgorithm.SHA1, digest);
|
|
||||||
Assertions.assertNotEquals(d2.hashCode(), d1.hashCode());
|
|
||||||
Assertions.assertEquals(DigestComparisonResultType.MISMATCH, d1.compare(d2));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that two <code>Digest</code>s are equal for same algorithm and
|
|
||||||
* digest.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void testEqual() {
|
|
||||||
final Digest d1 = new Digest(DigestAlgorithm.SHA1, getTestDigest(20));
|
|
||||||
final Digest d2 = new Digest(DigestAlgorithm.SHA1, getTestDigest(20));
|
|
||||||
Assertions.assertEquals(d2, d1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that two <code>Digest</code>s are unequal for same digest but
|
|
||||||
* different algorithm.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void testNotEqualAlgorithm() {
|
|
||||||
final Digest d1 = new Digest(DigestAlgorithm.MD2, getTestDigest(16));
|
|
||||||
final Digest d2 = new Digest(DigestAlgorithm.MD5, getTestDigest(16));
|
|
||||||
Assertions.assertNotEquals(d2, d1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that two <code>Digest</code>s are unequal for same algorithm but
|
|
||||||
* different digest.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void testNotEqualDigest() {
|
|
||||||
final byte[] digest = getTestDigest(20);
|
|
||||||
final Digest d1 = new Digest(DigestAlgorithm.SHA1, digest);
|
|
||||||
digest[0] += 1;
|
|
||||||
final Digest d2 = new Digest(DigestAlgorithm.SHA1, digest);
|
|
||||||
Assertions.assertNotEquals(d2, d1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that comparing a null Digest to a Digest indicates an UNKNOWN
|
|
||||||
* comparison type.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void testCompareToNull() {
|
|
||||||
final Digest d1 = new Digest(DigestAlgorithm.MD2, getTestDigest(16));
|
|
||||||
Assertions.assertEquals(DigestComparisonResultType.UNKNOWN, d1.compare(null));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that comparing two Digests with hashes with values of zero gives a MATCH
|
|
||||||
* comparison result.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void testCompareToDigestWithBothZeroizedHash() {
|
|
||||||
final Digest d1 = new Digest(DigestAlgorithm.SHA1, getZeroValueDigest(20));
|
|
||||||
final Digest d2 = new Digest(DigestAlgorithm.SHA1, getZeroValueDigest(20));
|
|
||||||
Assertions.assertEquals(DigestComparisonResultType.MATCH, d1.compare(d2));
|
|
||||||
Assertions.assertEquals(DigestComparisonResultType.MATCH, d2.compare(d1));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that comparing two Digests, one with a hash of value zero, gives a MISMATCH
|
|
||||||
* comparison result.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void testCompareToDigestWithOneZeroizedHash() {
|
|
||||||
final Digest d1 = new Digest(DigestAlgorithm.SHA1, getTestDigest(20));
|
|
||||||
final Digest d2 = new Digest(DigestAlgorithm.SHA1, getZeroValueDigest(20));
|
|
||||||
Assertions.assertEquals(DigestComparisonResultType.MISMATCH, d1.compare(d2));
|
|
||||||
Assertions.assertEquals(DigestComparisonResultType.MISMATCH, d2.compare(d1));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that comparing two Digests with a hash of no data gives a MATCH
|
|
||||||
* comparison result.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void testCompareToDigestWithBothEmptyHash() {
|
|
||||||
final Digest d1 = new Digest(DigestAlgorithm.SHA1, getEmptySHA1Digest());
|
|
||||||
final Digest d2 = new Digest(DigestAlgorithm.SHA1, getEmptySHA1Digest());
|
|
||||||
Assertions.assertEquals(DigestComparisonResultType.MATCH, d1.compare(d2));
|
|
||||||
Assertions.assertEquals(DigestComparisonResultType.MATCH, d2.compare(d1));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that comparing two Digests, one with a hash of no data, gives a MISMATCH
|
|
||||||
* comparison result.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void testCompareToDigestWithOneEmptyHash() {
|
|
||||||
final Digest d1 = new Digest(DigestAlgorithm.SHA1, getTestDigest(20));
|
|
||||||
final Digest d2 = new Digest(DigestAlgorithm.SHA1, getEmptySHA1Digest());
|
|
||||||
Assertions.assertEquals(DigestComparisonResultType.MISMATCH, d1.compare(d2));
|
|
||||||
Assertions.assertEquals(DigestComparisonResultType.MISMATCH, d2.compare(d1));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that if someone tries to recreate a Digest using an invalid String, an error is thrown.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public final void testFromStringInvalid() {
|
|
||||||
String invalidDigestString = "SHA1 00000000000000000000";
|
|
||||||
Assertions.assertThrows(IllegalArgumentException.class,
|
|
||||||
() -> Digest.fromString(invalidDigestString));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a test SHA1 digest.
|
* Get a test SHA1 digest.
|
||||||
*
|
*
|
||||||
@ -464,6 +48,454 @@ public class DigestTest {
|
|||||||
return new byte[count];
|
return new byte[count];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that constructor throws a <code>IllegalArgumentException</code> when a
|
||||||
|
* null <code>DigestAlgorithm</code> is passed into constructor.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void nullAlgorithm() {
|
||||||
|
final int count = 16;
|
||||||
|
final byte[] digest = getTestDigest(count);
|
||||||
|
Assertions.assertThrows(IllegalArgumentException.class,
|
||||||
|
() -> new Digest(null, digest));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that constructor throws a <code>IllegalArgumentException</code> when a
|
||||||
|
* null digest is passed into constructor.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void nullDigest() {
|
||||||
|
Assertions.assertThrows(IllegalArgumentException.class,
|
||||||
|
() -> new Digest(DigestAlgorithm.MD2, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that constructor throws a <code>IllegalArgumentException</code> when an
|
||||||
|
* digest that is an empty array is passed into constructor.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void emptyArrayDigest() {
|
||||||
|
Assertions.assertThrows(IllegalArgumentException.class,
|
||||||
|
() -> new Digest(DigestAlgorithm.MD2, new byte[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that MD2 digest can be created.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void md2() {
|
||||||
|
final int count = 16;
|
||||||
|
final byte[] digest = getTestDigest(count);
|
||||||
|
final Digest d = new Digest(DigestAlgorithm.MD2, digest);
|
||||||
|
Assertions.assertNotNull(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that an MD2 digest can be recreated from a string.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void testFromStringMD2() {
|
||||||
|
final int count = 16;
|
||||||
|
final byte[] digestBytes = getTestDigest(count);
|
||||||
|
Digest digest = new Digest(DigestAlgorithm.MD2, digestBytes);
|
||||||
|
String digestString = digest.toString();
|
||||||
|
Digest digestFromString = Digest.fromString(digestString);
|
||||||
|
Assertions.assertEquals(digest, digestFromString);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that MD2 digest cannot be created with a digest that has extra
|
||||||
|
* bytes.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void md2IllegalDigest() {
|
||||||
|
final int count = 17;
|
||||||
|
final byte[] digest = getTestDigest(count);
|
||||||
|
Assertions.assertThrows(IllegalArgumentException.class,
|
||||||
|
() -> new Digest(DigestAlgorithm.MD2, digest));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that MD5 digest can be created.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void md5() {
|
||||||
|
final int count = 16;
|
||||||
|
final byte[] digest = getTestDigest(count);
|
||||||
|
final Digest d = new Digest(DigestAlgorithm.MD5, digest);
|
||||||
|
Assertions.assertNotNull(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that an MD5 digest can be recreated from a string.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void testFromStringMD5() {
|
||||||
|
final int count = 16;
|
||||||
|
final byte[] digestBytes = getTestDigest(count);
|
||||||
|
Digest digest = new Digest(DigestAlgorithm.MD5, digestBytes);
|
||||||
|
String digestString = digest.toString();
|
||||||
|
Digest digestFromString = Digest.fromString(digestString);
|
||||||
|
Assertions.assertEquals(digest, digestFromString);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that MD5 digest cannot be created with a digest that has extra
|
||||||
|
* bytes.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void md5IllegalDigest() {
|
||||||
|
final int count = 17;
|
||||||
|
final byte[] digest = getTestDigest(count);
|
||||||
|
Assertions.assertThrows(IllegalArgumentException.class,
|
||||||
|
() -> new Digest(DigestAlgorithm.MD5, digest));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that SHA1 digest can be created.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void sha1() {
|
||||||
|
final int count = 20;
|
||||||
|
final byte[] digest = getTestDigest(count);
|
||||||
|
final Digest d = new Digest(DigestAlgorithm.SHA1, digest);
|
||||||
|
Assertions.assertNotNull(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that SHA1 digest can be recreated from a string.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void testFromStringSHA1() {
|
||||||
|
final int count = 20;
|
||||||
|
final byte[] digestBytes = getTestDigest(count);
|
||||||
|
Digest digest = new Digest(DigestAlgorithm.SHA1, digestBytes);
|
||||||
|
String digestString = digest.toString();
|
||||||
|
Digest digestFromString = Digest.fromString(digestString);
|
||||||
|
Assertions.assertEquals(digest, digestFromString);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that SHA1 digest cannot be created with a digest that has extra
|
||||||
|
* bytes.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void sha1IllegalDigest() {
|
||||||
|
final int count = 21;
|
||||||
|
final byte[] digest = getTestDigest(count);
|
||||||
|
Assertions.assertThrows(IllegalArgumentException.class,
|
||||||
|
() -> new Digest(DigestAlgorithm.SHA1, digest));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that SHA256 digest can be created.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void sha256() {
|
||||||
|
final int count = 32;
|
||||||
|
final byte[] digest = getTestDigest(count);
|
||||||
|
final Digest d = new Digest(DigestAlgorithm.SHA256, digest);
|
||||||
|
Assertions.assertNotNull(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that SHA256 digest can be recreated from a string.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void testFromStringSHA256() {
|
||||||
|
final int count = 32;
|
||||||
|
final byte[] digestBytes = getTestDigest(count);
|
||||||
|
Digest digest = new Digest(DigestAlgorithm.SHA256, digestBytes);
|
||||||
|
String digestString = digest.toString();
|
||||||
|
Digest digestFromString = Digest.fromString(digestString);
|
||||||
|
Assertions.assertEquals(digest, digestFromString);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that SHA256 digest cannot be created with a digest that has extra
|
||||||
|
* bytes.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void sha256IllegalDigest() {
|
||||||
|
final int count = 33;
|
||||||
|
final byte[] digest = getTestDigest(count);
|
||||||
|
Assertions.assertThrows(IllegalArgumentException.class,
|
||||||
|
() -> new Digest(DigestAlgorithm.SHA256, digest));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that SHA384 digest can be created.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void sha384() {
|
||||||
|
final int count = 48;
|
||||||
|
final byte[] digest = getTestDigest(count);
|
||||||
|
final Digest d = new Digest(DigestAlgorithm.SHA384, digest);
|
||||||
|
Assertions.assertNotNull(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that SHA384 digest can be recreated from a string.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void testFromStringSHA384() {
|
||||||
|
final int count = 48;
|
||||||
|
final byte[] digestBytes = getTestDigest(count);
|
||||||
|
Digest digest = new Digest(DigestAlgorithm.SHA384, digestBytes);
|
||||||
|
String digestString = digest.toString();
|
||||||
|
Digest digestFromString = Digest.fromString(digestString);
|
||||||
|
Assertions.assertEquals(digest, digestFromString);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that SHA384 digest cannot be created with a digest that has extra
|
||||||
|
* bytes.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void sha384IllegalDigest() {
|
||||||
|
final int count = 49;
|
||||||
|
final byte[] digest = getTestDigest(count);
|
||||||
|
Assertions.assertThrows(IllegalArgumentException.class,
|
||||||
|
() -> new Digest(DigestAlgorithm.SHA384, digest));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that SHA512 digest can be created.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void sha512() {
|
||||||
|
final int count = 64;
|
||||||
|
final byte[] digest = getTestDigest(count);
|
||||||
|
final Digest d = new Digest(DigestAlgorithm.SHA512, digest);
|
||||||
|
Assertions.assertNotNull(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that SHA512 digest can be recreated from a string.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void testFromStringSHA512() {
|
||||||
|
final int count = 64;
|
||||||
|
final byte[] digestBytes = getTestDigest(count);
|
||||||
|
Digest digest = new Digest(DigestAlgorithm.SHA512, digestBytes);
|
||||||
|
String digestString = digest.toString();
|
||||||
|
Digest digestFromString = Digest.fromString(digestString);
|
||||||
|
Assertions.assertEquals(digest, digestFromString);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that SHA512 digest cannot be created with a digest that has extra
|
||||||
|
* bytes.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void sha512IllegalDigest() {
|
||||||
|
final int count = 65;
|
||||||
|
final byte[] digest = getTestDigest(count);
|
||||||
|
Assertions.assertThrows(IllegalArgumentException.class,
|
||||||
|
() -> new Digest(DigestAlgorithm.SHA512, digest));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that the correct <code>DigestAlgorithm</code> is returned by
|
||||||
|
* {@link Digest#getAlgorithm()}.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void testGetAlgorithm() {
|
||||||
|
final int count = 20;
|
||||||
|
final Digest d = new Digest(DigestAlgorithm.SHA1, getTestDigest(count));
|
||||||
|
Assertions.assertEquals(d.getAlgorithm(), DigestAlgorithm.SHA1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that the bytes of the digest are created and do not affect the
|
||||||
|
* underlying state of the <code>Digest</code> instance.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void testGetDigest() {
|
||||||
|
final int count = 20;
|
||||||
|
final Digest d = new Digest(DigestAlgorithm.SHA1, getTestDigest(count));
|
||||||
|
final byte[] digestBytes = d.getDigest();
|
||||||
|
final byte[] testBytes = getTestDigest(count);
|
||||||
|
Assertions.assertArrayEquals(digestBytes, testBytes);
|
||||||
|
digestBytes[0] = (byte) (digestBytes[0] + 1);
|
||||||
|
Assertions.assertArrayEquals(d.getDigest(), testBytes);
|
||||||
|
Assertions.assertFalse(Arrays.equals(d.getDigest(), digestBytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that two <code>Digest</code>s have equal hash code for same
|
||||||
|
* algorithm and digest.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void testHashCodeEqual() {
|
||||||
|
final int count = 20;
|
||||||
|
final Digest d1 = new Digest(DigestAlgorithm.SHA1, getTestDigest(count));
|
||||||
|
final Digest d2 = new Digest(DigestAlgorithm.SHA1, getTestDigest(count));
|
||||||
|
Assertions.assertEquals(d2.hashCode(), d1.hashCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that two <code>Digest</code>s indicate MATCH when compared.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void testMatchedComparison() {
|
||||||
|
final int count = 20;
|
||||||
|
final Digest d1 = new Digest(DigestAlgorithm.SHA1, getTestDigest(count));
|
||||||
|
final Digest d2 = new Digest(DigestAlgorithm.SHA1, getTestDigest(count));
|
||||||
|
Assertions.assertEquals(DigestComparisonResultType.MATCH, d1.compare(d2));
|
||||||
|
Assertions.assertEquals(DigestComparisonResultType.MATCH, d2.compare(d1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that two <code>Digest</code>s have unequal hash code for same
|
||||||
|
* digest but different algorithm.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void testHashCodeNotEqualAlgorithm() {
|
||||||
|
final int count = 16;
|
||||||
|
final Digest d1 = new Digest(DigestAlgorithm.MD2, getTestDigest(count));
|
||||||
|
final Digest d2 = new Digest(DigestAlgorithm.MD5, getTestDigest(count));
|
||||||
|
Assertions.assertNotEquals(d2.hashCode(), d1.hashCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that two <code>Digest</code>s indicate MISMATCH when compared.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void testMismatchAlgorithm() {
|
||||||
|
final int count = 16;
|
||||||
|
final Digest d1 = new Digest(DigestAlgorithm.MD2, getTestDigest(count));
|
||||||
|
final Digest d2 = new Digest(DigestAlgorithm.MD5, getTestDigest(count));
|
||||||
|
Assertions.assertEquals(DigestComparisonResultType.MISMATCH, d1.compare(d2));
|
||||||
|
Assertions.assertEquals(DigestComparisonResultType.MISMATCH, d2.compare(d1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that two <code>Digest</code>s have unequal hash code for same
|
||||||
|
* algorithm but different digest.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void testHashCodeNotEqualDigest() {
|
||||||
|
final int count = 20;
|
||||||
|
final byte[] digest = getTestDigest(count);
|
||||||
|
final Digest d1 = new Digest(DigestAlgorithm.SHA1, digest);
|
||||||
|
digest[0] += 1;
|
||||||
|
final Digest d2 = new Digest(DigestAlgorithm.SHA1, digest);
|
||||||
|
Assertions.assertNotEquals(d2.hashCode(), d1.hashCode());
|
||||||
|
Assertions.assertEquals(DigestComparisonResultType.MISMATCH, d1.compare(d2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that two <code>Digest</code>s are equal for same algorithm and
|
||||||
|
* digest.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void testEqual() {
|
||||||
|
final int count = 20;
|
||||||
|
final Digest d1 = new Digest(DigestAlgorithm.SHA1, getTestDigest(count));
|
||||||
|
final Digest d2 = new Digest(DigestAlgorithm.SHA1, getTestDigest(count));
|
||||||
|
Assertions.assertEquals(d2, d1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that two <code>Digest</code>s are unequal for same digest but
|
||||||
|
* different algorithm.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void testNotEqualAlgorithm() {
|
||||||
|
final int count = 16;
|
||||||
|
final Digest d1 = new Digest(DigestAlgorithm.MD2, getTestDigest(count));
|
||||||
|
final Digest d2 = new Digest(DigestAlgorithm.MD5, getTestDigest(count));
|
||||||
|
Assertions.assertNotEquals(d2, d1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that two <code>Digest</code>s are unequal for same algorithm but
|
||||||
|
* different digest.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void testNotEqualDigest() {
|
||||||
|
final int count = 20;
|
||||||
|
final byte[] digest = getTestDigest(count);
|
||||||
|
final Digest d1 = new Digest(DigestAlgorithm.SHA1, digest);
|
||||||
|
digest[0] += 1;
|
||||||
|
final Digest d2 = new Digest(DigestAlgorithm.SHA1, digest);
|
||||||
|
Assertions.assertNotEquals(d2, d1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that comparing a null Digest to a Digest indicates an UNKNOWN
|
||||||
|
* comparison type.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void testCompareToNull() {
|
||||||
|
final int count = 16;
|
||||||
|
final Digest d1 = new Digest(DigestAlgorithm.MD2, getTestDigest(count));
|
||||||
|
Assertions.assertEquals(DigestComparisonResultType.UNKNOWN, d1.compare(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that comparing two Digests with hashes with values of zero gives a MATCH
|
||||||
|
* comparison result.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void testCompareToDigestWithBothZeroizedHash() {
|
||||||
|
final int count = 20;
|
||||||
|
final Digest d1 = new Digest(DigestAlgorithm.SHA1, getZeroValueDigest(count));
|
||||||
|
final Digest d2 = new Digest(DigestAlgorithm.SHA1, getZeroValueDigest(count));
|
||||||
|
Assertions.assertEquals(DigestComparisonResultType.MATCH, d1.compare(d2));
|
||||||
|
Assertions.assertEquals(DigestComparisonResultType.MATCH, d2.compare(d1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that comparing two Digests, one with a hash of value zero, gives a MISMATCH
|
||||||
|
* comparison result.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void testCompareToDigestWithOneZeroizedHash() {
|
||||||
|
final int count = 20;
|
||||||
|
final Digest d1 = new Digest(DigestAlgorithm.SHA1, getTestDigest(count));
|
||||||
|
final Digest d2 = new Digest(DigestAlgorithm.SHA1, getZeroValueDigest(count));
|
||||||
|
Assertions.assertEquals(DigestComparisonResultType.MISMATCH, d1.compare(d2));
|
||||||
|
Assertions.assertEquals(DigestComparisonResultType.MISMATCH, d2.compare(d1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that comparing two Digests with a hash of no data gives a MATCH
|
||||||
|
* comparison result.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void testCompareToDigestWithBothEmptyHash() {
|
||||||
|
final Digest d1 = new Digest(DigestAlgorithm.SHA1, getEmptySHA1Digest());
|
||||||
|
final Digest d2 = new Digest(DigestAlgorithm.SHA1, getEmptySHA1Digest());
|
||||||
|
Assertions.assertEquals(DigestComparisonResultType.MATCH, d1.compare(d2));
|
||||||
|
Assertions.assertEquals(DigestComparisonResultType.MATCH, d2.compare(d1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that comparing two Digests, one with a hash of no data, gives a MISMATCH
|
||||||
|
* comparison result.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void testCompareToDigestWithOneEmptyHash() {
|
||||||
|
final int count = 20;
|
||||||
|
final Digest d1 = new Digest(DigestAlgorithm.SHA1, getTestDigest(count));
|
||||||
|
final Digest d2 = new Digest(DigestAlgorithm.SHA1, getEmptySHA1Digest());
|
||||||
|
Assertions.assertEquals(DigestComparisonResultType.MISMATCH, d1.compare(d2));
|
||||||
|
Assertions.assertEquals(DigestComparisonResultType.MISMATCH, d2.compare(d1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that if someone tries to recreate a Digest using an invalid String, an error is thrown.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public final void testFromStringInvalid() {
|
||||||
|
String invalidDigestString = "SHA1 00000000000000000000";
|
||||||
|
Assertions.assertThrows(IllegalArgumentException.class,
|
||||||
|
() -> Digest.fromString(invalidDigestString));
|
||||||
|
}
|
||||||
|
|
||||||
private byte[] getEmptySHA1Digest() {
|
private byte[] getEmptySHA1Digest() {
|
||||||
return DigestUtils.sha1(new byte[] {});
|
return DigestUtils.sha1(new byte[] {});
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,11 @@ package hirs.data.persist;
|
|||||||
|
|
||||||
import hirs.attestationca.persist.entity.userdefined.info.FirmwareInfo;
|
import hirs.attestationca.persist.entity.userdefined.info.FirmwareInfo;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import static hirs.utils.enums.DeviceInfoEnums.NOT_SPECIFIED;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static hirs.utils.enums.DeviceInfoEnums.NOT_SPECIFIED;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FirmwareInfoTest is a unit test class for FirmwareInfo.
|
* FirmwareInfoTest is a unit test class for FirmwareInfo.
|
||||||
*/
|
*/
|
||||||
@ -15,18 +15,20 @@ public class FirmwareInfoTest {
|
|||||||
private static final String BIOS_VENDOR = "test bios vendor";
|
private static final String BIOS_VENDOR = "test bios vendor";
|
||||||
private static final String BIOS_VERSION = "test bios version";
|
private static final String BIOS_VERSION = "test bios version";
|
||||||
private static final String BIOS_RELEASE_DATE = "test bios release date";
|
private static final String BIOS_RELEASE_DATE = "test bios release date";
|
||||||
|
private static final int PRIMARY_SIZE = 257;
|
||||||
|
private static final int SECONDARY_SIZE = 33;
|
||||||
|
|
||||||
private static final String LONG_BIOS_VENDOR = StringUtils.rightPad(
|
private static final String LONG_BIOS_VENDOR = StringUtils.rightPad(
|
||||||
"test bios vendor",
|
BIOS_VENDOR,
|
||||||
257
|
PRIMARY_SIZE
|
||||||
);
|
);
|
||||||
private static final String LONG_BIOS_VERSION = StringUtils.rightPad(
|
private static final String LONG_BIOS_VERSION = StringUtils.rightPad(
|
||||||
"test bios version",
|
BIOS_VERSION,
|
||||||
257
|
PRIMARY_SIZE
|
||||||
);
|
);
|
||||||
private static final String LONG_BIOS_RELEASE_DATE = StringUtils.rightPad(
|
private static final String LONG_BIOS_RELEASE_DATE = StringUtils.rightPad(
|
||||||
"test bios release date",
|
BIOS_RELEASE_DATE,
|
||||||
33
|
SECONDARY_SIZE
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
package hirs.data.persist;
|
package hirs.data.persist;
|
||||||
|
|
||||||
import hirs.attestationca.persist.entity.userdefined.info.HardwareInfo;
|
import hirs.attestationca.persist.entity.userdefined.info.HardwareInfo;
|
||||||
import static hirs.utils.enums.DeviceInfoEnums.NOT_SPECIFIED;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static hirs.utils.enums.DeviceInfoEnums.NOT_SPECIFIED;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HardwareInfoTest is a unit test class for HardwareInfo.
|
* HardwareInfoTest is a unit test class for HardwareInfo.
|
||||||
*/
|
*/
|
||||||
@ -18,30 +18,32 @@ public class HardwareInfoTest {
|
|||||||
private static final String SERIAL_NUMBER = "test serial number";
|
private static final String SERIAL_NUMBER = "test serial number";
|
||||||
private static final String CHASSIS_SERIAL_NUMBER = "test chassis serial number";
|
private static final String CHASSIS_SERIAL_NUMBER = "test chassis serial number";
|
||||||
private static final String BASEBOARD_SERIAL_NUMBER = "test baseboard serial number";
|
private static final String BASEBOARD_SERIAL_NUMBER = "test baseboard serial number";
|
||||||
|
private static final int PRIMARY_SIZE = 257;
|
||||||
|
private static final int SECONDARY_SIZE = 65;
|
||||||
|
|
||||||
private static final String LONG_MANUFACTURER = StringUtils.rightPad(
|
private static final String LONG_MANUFACTURER = StringUtils.rightPad(
|
||||||
"test manufacturer",
|
MANUFACTURER,
|
||||||
257
|
PRIMARY_SIZE
|
||||||
);
|
);
|
||||||
private static final String LONG_PRODUCT_NAME = StringUtils.rightPad(
|
private static final String LONG_PRODUCT_NAME = StringUtils.rightPad(
|
||||||
"test product name",
|
PRODUCT_NAME,
|
||||||
257
|
PRIMARY_SIZE
|
||||||
);
|
);
|
||||||
private static final String LONG_VERSION = StringUtils.rightPad(
|
private static final String LONG_VERSION = StringUtils.rightPad(
|
||||||
"test version",
|
VERSION,
|
||||||
65
|
SECONDARY_SIZE
|
||||||
);
|
);
|
||||||
private static final String LONG_SERIAL_NUMBER = StringUtils.rightPad(
|
private static final String LONG_SERIAL_NUMBER = StringUtils.rightPad(
|
||||||
"test serial number",
|
SERIAL_NUMBER,
|
||||||
257
|
PRIMARY_SIZE
|
||||||
);
|
);
|
||||||
private static final String LONG_CHASSIS_SERIAL_NUMBER = StringUtils.rightPad(
|
private static final String LONG_CHASSIS_SERIAL_NUMBER = StringUtils.rightPad(
|
||||||
"test chassis serial number",
|
CHASSIS_SERIAL_NUMBER,
|
||||||
257
|
PRIMARY_SIZE
|
||||||
);
|
);
|
||||||
private static final String LONG_BASEBOARD_SERIAL_NUMBER = StringUtils.rightPad(
|
private static final String LONG_BASEBOARD_SERIAL_NUMBER = StringUtils.rightPad(
|
||||||
"test baseboard serial number",
|
BASEBOARD_SERIAL_NUMBER,
|
||||||
257
|
PRIMARY_SIZE
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
package hirs.data.persist;
|
package hirs.data.persist;
|
||||||
|
|
||||||
import hirs.attestationca.persist.entity.userdefined.info.NetworkInfo;
|
import hirs.attestationca.persist.entity.userdefined.info.NetworkInfo;
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.net.UnknownHostException;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NetworkInfoTest is a unit test class for NetworkInfo.
|
* NetworkInfoTest is a unit test class for NetworkInfo.
|
||||||
*/
|
*/
|
||||||
@ -17,6 +17,15 @@ public class NetworkInfoTest {
|
|||||||
private static final byte[] MAC_ADDRESS = new byte[] {11, 22, 33, 44, 55,
|
private static final byte[] MAC_ADDRESS = new byte[] {11, 22, 33, 44, 55,
|
||||||
66};
|
66};
|
||||||
|
|
||||||
|
private static InetAddress getTestIpAddress() {
|
||||||
|
try {
|
||||||
|
final byte[] byteAddress = new byte[] {127, 0, 0, 1};
|
||||||
|
return InetAddress.getByAddress(byteAddress);
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests instantiation of a NetworkInfo object.
|
* Tests instantiation of a NetworkInfo object.
|
||||||
*/
|
*/
|
||||||
@ -103,14 +112,14 @@ public class NetworkInfoTest {
|
|||||||
* Tests that hashcodes generated by NetworkInfo objects with different IP
|
* Tests that hashcodes generated by NetworkInfo objects with different IP
|
||||||
* addresses are not equal.
|
* addresses are not equal.
|
||||||
*
|
*
|
||||||
* @throws UnknownHostException
|
* @throws UnknownHostException in case the InetAddress is not created correctly
|
||||||
* in case the InetAddress is not created correctly
|
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public final void testHashCodeNotEqualsIpAddress()
|
public final void testHashCodeNotEqualsIpAddress()
|
||||||
throws UnknownHostException {
|
throws UnknownHostException {
|
||||||
|
final byte[] byteAddress = new byte[] {127, 0, 0, 2};
|
||||||
final InetAddress ipAddress2 =
|
final InetAddress ipAddress2 =
|
||||||
InetAddress.getByAddress(new byte[] {127, 0, 0, 2});
|
InetAddress.getByAddress(byteAddress);
|
||||||
NetworkInfo ni1 = new NetworkInfo(HOSTNAME, IP_ADDRESS, MAC_ADDRESS);
|
NetworkInfo ni1 = new NetworkInfo(HOSTNAME, IP_ADDRESS, MAC_ADDRESS);
|
||||||
NetworkInfo ni2 = new NetworkInfo(HOSTNAME, ipAddress2, MAC_ADDRESS);
|
NetworkInfo ni2 = new NetworkInfo(HOSTNAME, ipAddress2, MAC_ADDRESS);
|
||||||
Assertions.assertNotEquals(ni2.hashCode(), ni1.hashCode());
|
Assertions.assertNotEquals(ni2.hashCode(), ni1.hashCode());
|
||||||
@ -155,13 +164,13 @@ public class NetworkInfoTest {
|
|||||||
* Tests that two NetworkInfo objects are not equal if they have different
|
* Tests that two NetworkInfo objects are not equal if they have different
|
||||||
* IP addresses.
|
* IP addresses.
|
||||||
*
|
*
|
||||||
* @throws UnknownHostException
|
* @throws UnknownHostException in case InetAddress is not created correctly
|
||||||
* in case InetAddress is not created correctly
|
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public final void testNotEqualsIpAddress() throws UnknownHostException {
|
public final void testNotEqualsIpAddress() throws UnknownHostException {
|
||||||
|
final byte[] byteAddress = new byte[] {127, 0, 0, 2};
|
||||||
final InetAddress ipAddress2 =
|
final InetAddress ipAddress2 =
|
||||||
InetAddress.getByAddress(new byte[] {127, 0, 0, 2});
|
InetAddress.getByAddress(byteAddress);
|
||||||
NetworkInfo ni1 = new NetworkInfo(HOSTNAME, IP_ADDRESS, MAC_ADDRESS);
|
NetworkInfo ni1 = new NetworkInfo(HOSTNAME, IP_ADDRESS, MAC_ADDRESS);
|
||||||
NetworkInfo ni2 = new NetworkInfo(HOSTNAME, ipAddress2, MAC_ADDRESS);
|
NetworkInfo ni2 = new NetworkInfo(HOSTNAME, ipAddress2, MAC_ADDRESS);
|
||||||
Assertions.assertNotEquals(ni2, ni1);
|
Assertions.assertNotEquals(ni2, ni1);
|
||||||
@ -178,12 +187,4 @@ public class NetworkInfoTest {
|
|||||||
NetworkInfo ni2 = new NetworkInfo(HOSTNAME, IP_ADDRESS, macAddress2);
|
NetworkInfo ni2 = new NetworkInfo(HOSTNAME, IP_ADDRESS, macAddress2);
|
||||||
Assertions.assertNotEquals(ni2, ni1);
|
Assertions.assertNotEquals(ni2, ni1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static InetAddress getTestIpAddress() {
|
|
||||||
try {
|
|
||||||
return InetAddress.getByAddress(new byte[] {127, 0, 0, 1});
|
|
||||||
} catch (UnknownHostException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
package hirs.data.persist;
|
package hirs.data.persist;
|
||||||
|
|
||||||
import hirs.attestationca.persist.entity.userdefined.info.OSInfo;
|
import hirs.attestationca.persist.entity.userdefined.info.OSInfo;
|
||||||
import static hirs.utils.enums.DeviceInfoEnums.NOT_SPECIFIED;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static hirs.utils.enums.DeviceInfoEnums.NOT_SPECIFIED;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OSInfoTest is a unit test class for OSInfo.
|
* OSInfoTest is a unit test class for OSInfo.
|
||||||
*/
|
*/
|
||||||
@ -17,10 +17,12 @@ public class OSInfoTest {
|
|||||||
private static final String OS_ARCH = "test osArch";
|
private static final String OS_ARCH = "test osArch";
|
||||||
private static final String DISTRIBUTION = "test distribution";
|
private static final String DISTRIBUTION = "test distribution";
|
||||||
private static final String DISTRIBUTION_RELEASE = "test distribution release";
|
private static final String DISTRIBUTION_RELEASE = "test distribution release";
|
||||||
|
private static final int PRIMARY_SIZE = 257;
|
||||||
|
private static final int SECONDARY_SIZE = 33;
|
||||||
|
|
||||||
private static final String LONG_OS_NAME = StringUtils.rightPad("test os", 257);
|
private static final String LONG_OS_NAME = StringUtils.rightPad(OS_NAME, PRIMARY_SIZE);
|
||||||
private static final String LONG_OS_VERSION = StringUtils.rightPad("test osVersion", 257);
|
private static final String LONG_OS_VERSION = StringUtils.rightPad(OS_VERSION, PRIMARY_SIZE);
|
||||||
private static final String LONG_OS_ARCH = StringUtils.rightPad("test osArch", 33);
|
private static final String LONG_OS_ARCH = StringUtils.rightPad(OS_ARCH, SECONDARY_SIZE);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests instantiation of an OSInfo object.
|
* Tests instantiation of an OSInfo object.
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
package hirs.data.persist;
|
@ -1,25 +1,29 @@
|
|||||||
package hirs.tpm.eventlog.uefi;
|
package hirs.tpm.eventlog.uefi;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URISyntaxException;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.security.cert.CertificateException;
|
|
||||||
|
|
||||||
import com.eclipsesource.json.JsonObject;
|
import com.eclipsesource.json.JsonObject;
|
||||||
|
import hirs.utils.HexUtils;
|
||||||
import hirs.utils.JsonUtils;
|
import hirs.utils.JsonUtils;
|
||||||
import hirs.utils.tpm.eventlog.uefi.*;
|
import hirs.utils.tpm.eventlog.uefi.UefiDevicePath;
|
||||||
|
import hirs.utils.tpm.eventlog.uefi.UefiFirmware;
|
||||||
|
import hirs.utils.tpm.eventlog.uefi.UefiGuid;
|
||||||
|
import hirs.utils.tpm.eventlog.uefi.UefiPartition;
|
||||||
|
import hirs.utils.tpm.eventlog.uefi.UefiVariable;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import hirs.utils.HexUtils;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for testing TCG Event Log processing of UEFI defined Data.
|
* Class for testing TCG Event Log processing of UEFI defined Data.
|
||||||
*/
|
*/
|
||||||
@ -70,7 +74,7 @@ public class UefiProcessingTest {
|
|||||||
Path jsonPath = Paths.get(this.getClass()
|
Path jsonPath = Paths.get(this.getClass()
|
||||||
.getResource(JSON_FILE).toURI());
|
.getResource(JSON_FILE).toURI());
|
||||||
String uefiTxt = IOUtils.toString(this.getClass().getResourceAsStream(UEFI_VARIABLE_BOOT),
|
String uefiTxt = IOUtils.toString(this.getClass().getResourceAsStream(UEFI_VARIABLE_BOOT),
|
||||||
"UTF-8");
|
StandardCharsets.UTF_8);
|
||||||
byte[] uefiVariableBytes = HexUtils.hexStringToByteArray(uefiTxt);
|
byte[] uefiVariableBytes = HexUtils.hexStringToByteArray(uefiTxt);
|
||||||
UefiVariable uefiVariable = new UefiVariable(uefiVariableBytes);
|
UefiVariable uefiVariable = new UefiVariable(uefiVariableBytes);
|
||||||
UefiGuid guid = uefiVariable.getUefiVarGuid();
|
UefiGuid guid = uefiVariable.getUefiVarGuid();
|
||||||
@ -83,7 +87,7 @@ public class UefiProcessingTest {
|
|||||||
|
|
||||||
uefiTxt = IOUtils.toString(this.getClass()
|
uefiTxt = IOUtils.toString(this.getClass()
|
||||||
.getResourceAsStream(UEFI_VARIABLE_BOOT_SECURE_BOOT),
|
.getResourceAsStream(UEFI_VARIABLE_BOOT_SECURE_BOOT),
|
||||||
"UTF-8");
|
StandardCharsets.UTF_8);
|
||||||
uefiVariableBytes = HexUtils.hexStringToByteArray(uefiTxt);
|
uefiVariableBytes = HexUtils.hexStringToByteArray(uefiTxt);
|
||||||
uefiVariable = new UefiVariable(uefiVariableBytes);
|
uefiVariable = new UefiVariable(uefiVariableBytes);
|
||||||
guid = uefiVariable.getUefiVarGuid();
|
guid = uefiVariable.getUefiVarGuid();
|
||||||
@ -94,7 +98,7 @@ public class UefiProcessingTest {
|
|||||||
Assertions.assertEquals("SecureBoot", varName);
|
Assertions.assertEquals("SecureBoot", varName);
|
||||||
|
|
||||||
uefiTxt = IOUtils.toString(this.getClass().getResourceAsStream(
|
uefiTxt = IOUtils.toString(this.getClass().getResourceAsStream(
|
||||||
UEFI_VARIABLE_BOOT_DRIVER_CONFIG_KEK), "UTF-8");
|
UEFI_VARIABLE_BOOT_DRIVER_CONFIG_KEK), StandardCharsets.UTF_8);
|
||||||
uefiVariableBytes = HexUtils.hexStringToByteArray(uefiTxt);
|
uefiVariableBytes = HexUtils.hexStringToByteArray(uefiTxt);
|
||||||
uefiVariable = new UefiVariable(uefiVariableBytes);
|
uefiVariable = new UefiVariable(uefiVariableBytes);
|
||||||
varName = uefiVariable.getEfiVarName();
|
varName = uefiVariable.getEfiVarName();
|
||||||
@ -116,7 +120,7 @@ public class UefiProcessingTest {
|
|||||||
Path jsonPath = Paths.get(this.getClass()
|
Path jsonPath = Paths.get(this.getClass()
|
||||||
.getResource(JSON_FILE).toURI());
|
.getResource(JSON_FILE).toURI());
|
||||||
String uefiTxt = IOUtils.toString(this.getClass().getResourceAsStream(UEFI_GPT_EVENT),
|
String uefiTxt = IOUtils.toString(this.getClass().getResourceAsStream(UEFI_GPT_EVENT),
|
||||||
"UTF-8");
|
StandardCharsets.UTF_8);
|
||||||
byte[] uefiPartitionBytes = HexUtils.hexStringToByteArray(uefiTxt);
|
byte[] uefiPartitionBytes = HexUtils.hexStringToByteArray(uefiTxt);
|
||||||
UefiPartition gptPart = new UefiPartition(uefiPartitionBytes);
|
UefiPartition gptPart = new UefiPartition(uefiPartitionBytes);
|
||||||
String gptPartName = gptPart.getPartitionName();
|
String gptPartName = gptPart.getPartitionName();
|
||||||
@ -143,13 +147,17 @@ public class UefiProcessingTest {
|
|||||||
CertificateException, NoSuchAlgorithmException {
|
CertificateException, NoSuchAlgorithmException {
|
||||||
LOGGER.debug("Testing the parsing of Uefi Firmware Blob");
|
LOGGER.debug("Testing the parsing of Uefi Firmware Blob");
|
||||||
String uefiTxt = IOUtils.toString(this.getClass()
|
String uefiTxt = IOUtils.toString(this.getClass()
|
||||||
.getResourceAsStream(UEFI_FW_BLOB), "UTF-8");
|
.getResourceAsStream(UEFI_FW_BLOB), StandardCharsets.UTF_8);
|
||||||
byte[] uefiFwBlobBytes = HexUtils.hexStringToByteArray(uefiTxt);
|
byte[] uefiFwBlobBytes = HexUtils.hexStringToByteArray(uefiTxt);
|
||||||
UefiFirmware uefiFWBlob = new UefiFirmware(uefiFwBlobBytes);
|
UefiFirmware uefiFWBlob = new UefiFirmware(uefiFwBlobBytes);
|
||||||
int fwAddress = uefiFWBlob.getPhysicalBlobAddress();
|
int fwAddress = uefiFWBlob.getPhysicalBlobAddress();
|
||||||
int fwLength = uefiFWBlob.getBlobLength();
|
int fwLength = uefiFWBlob.getBlobLength();
|
||||||
Assertions.assertEquals(1797287936, fwAddress);
|
|
||||||
Assertions.assertEquals(851968, fwLength);
|
final int expectedFwAddress = 1797287936;
|
||||||
|
Assertions.assertEquals(expectedFwAddress, fwAddress);
|
||||||
|
|
||||||
|
final int expectedFwLength = 851968;
|
||||||
|
Assertions.assertEquals(expectedFwLength, fwLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -162,7 +170,7 @@ public class UefiProcessingTest {
|
|||||||
public final void testUefiDevicePath() throws IOException, URISyntaxException {
|
public final void testUefiDevicePath() throws IOException, URISyntaxException {
|
||||||
LOGGER.debug("Testing the parsing of Uefi Device Path");
|
LOGGER.debug("Testing the parsing of Uefi Device Path");
|
||||||
String uefiTxt = IOUtils.toString(this.getClass().getResourceAsStream(UEFI_DEVICE_PATH),
|
String uefiTxt = IOUtils.toString(this.getClass().getResourceAsStream(UEFI_DEVICE_PATH),
|
||||||
"UTF-8");
|
StandardCharsets.UTF_8);
|
||||||
byte[] uefiFwBlobBytes = HexUtils.hexStringToByteArray(uefiTxt);
|
byte[] uefiFwBlobBytes = HexUtils.hexStringToByteArray(uefiTxt);
|
||||||
UefiDevicePath uefiDevPath = new UefiDevicePath(uefiFwBlobBytes);
|
UefiDevicePath uefiDevPath = new UefiDevicePath(uefiFwBlobBytes);
|
||||||
String devPathType = uefiDevPath.getType();
|
String devPathType = uefiDevPath.getType();
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
package hirs.tpm.eventlog.uefi;
|
@ -2,8 +2,9 @@ package hirs.utils;
|
|||||||
|
|
||||||
import org.apache.logging.log4j.util.Strings;
|
import org.apache.logging.log4j.util.Strings;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests methods in the (@link BouncyCastleUtils) utility class.
|
* Tests methods in the (@link BouncyCastleUtils) utility class.
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package hirs.utils;
|
package hirs.utils;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
@ -14,11 +15,10 @@ public class HexUtilsTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testHexStringToByteArray() {
|
public void testHexStringToByteArray() {
|
||||||
String s = "abcd1234";
|
final String testString = "abcd1234";
|
||||||
byte[] target = {-85, -51, 18, 52};
|
final byte[] expectedBytes = {-85, -51, 18, 52};
|
||||||
|
final byte[] actualBytes = HexUtils.hexStringToByteArray(testString);
|
||||||
byte[] b = HexUtils.hexStringToByteArray(s);
|
assertArrayEquals(expectedBytes, actualBytes);
|
||||||
assertArrayEquals(b, target);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -26,11 +26,10 @@ public class HexUtilsTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testByteArrayToHexString() {
|
public void testByteArrayToHexString() {
|
||||||
String target = "abcd1234";
|
final byte[] byteArray = {-85, -51, 18, 52};
|
||||||
byte[] b = {-85, -51, 18, 52};
|
final String expectedString = "abcd1234";
|
||||||
|
final String actualString = HexUtils.byteArrayToHexString(byteArray);
|
||||||
String s = HexUtils.byteArrayToHexString(b);
|
assertEquals(expectedString, actualString);
|
||||||
assertEquals(s, target);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,11 +37,10 @@ public class HexUtilsTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testByteArrayToHexStringConditional() {
|
public void testByteArrayToHexStringConditional() {
|
||||||
String target = "abcd0100";
|
final byte[] byteArray = {-85, -51, 1, 0};
|
||||||
byte[] b = {-85, -51, 1, 0};
|
final String expectedHexString = "abcd0100";
|
||||||
|
final String actualHexString = HexUtils.byteArrayToHexString(byteArray);
|
||||||
String s = HexUtils.byteArrayToHexString(b);
|
assertEquals(expectedHexString, actualHexString);
|
||||||
assertEquals(s, target);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,9 +48,10 @@ public class HexUtilsTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testHexToInt() {
|
public void testHexToInt() {
|
||||||
String s = "ff";
|
final String testString = "ff";
|
||||||
Integer i = HexUtils.hexToInt(s);
|
final int expectedInt = HexUtils.FF_BYTE;
|
||||||
assertEquals((int) i, HexUtils.FF_BYTE);
|
final Integer actualInt = HexUtils.hexToInt(testString);
|
||||||
|
assertEquals(expectedInt, (int) actualInt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -60,14 +59,11 @@ public class HexUtilsTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testSubarray() {
|
public void testSubarray() {
|
||||||
byte[] b = {-85, -51, 18, 52};
|
final byte[] b = {-85, -51, 18, 52};
|
||||||
byte[] target = {-51, 18};
|
final byte[] expectedSubArray = {-51, 18};
|
||||||
|
final byte[] actualSubArray = HexUtils.subarray(b, 1, 2);
|
||||||
byte[] sub = HexUtils.subarray(b, 1, 2);
|
assertArrayEquals(expectedSubArray, actualSubArray);
|
||||||
|
|
||||||
assertArrayEquals(sub, target);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
package hirs.utils;
|
package hirs.utils;
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.mockito.Mockito;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import org.mockito.Mockito;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
1
HIRS_Utils/src/test/java/hirs/utils/package-info.java
Normal file
1
HIRS_Utils/src/test/java/hirs/utils/package-info.java
Normal file
@ -0,0 +1 @@
|
|||||||
|
package hirs.utils;
|
@ -1,20 +1,20 @@
|
|||||||
package hirs.utils.tpm.eventlog;
|
package hirs.utils.tpm.eventlog;
|
||||||
|
|
||||||
|
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.junit.jupiter.api.AfterAll;
|
||||||
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import static hirs.utils.tpm.eventlog.TCGEventLog.PCR_COUNT;
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.AfterAll;
|
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import static org.hamcrest.CoreMatchers.equalTo;
|
import static org.hamcrest.CoreMatchers.equalTo;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
@ -36,7 +36,6 @@ public class TCGEventLogTest {
|
|||||||
@BeforeAll
|
@BeforeAll
|
||||||
public static final void setup() {
|
public static final void setup() {
|
||||||
LOGGER.debug("retrieving session factory");
|
LOGGER.debug("retrieving session factory");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -49,6 +48,7 @@ public class TCGEventLogTest {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests the processing of a crypto agile event log.
|
* Tests the processing of a crypto agile event log.
|
||||||
|
*
|
||||||
* @throws IOException when processing the test fails
|
* @throws IOException when processing the test fails
|
||||||
* @throws NoSuchAlgorithmException if an unknown algorithm is encountered.
|
* @throws NoSuchAlgorithmException if an unknown algorithm is encountered.
|
||||||
* @throws CertificateException if a certificate fails to parse.
|
* @throws CertificateException if a certificate fails to parse.
|
||||||
@ -57,28 +57,33 @@ public class TCGEventLogTest {
|
|||||||
public final void testCryptoAgileTCGEventLog() throws IOException, CertificateException,
|
public final void testCryptoAgileTCGEventLog() throws IOException, CertificateException,
|
||||||
NoSuchAlgorithmException {
|
NoSuchAlgorithmException {
|
||||||
LOGGER.debug("Testing the parsing of a Crypto Agile formatted TCG Event Log");
|
LOGGER.debug("Testing the parsing of a Crypto Agile formatted TCG Event Log");
|
||||||
InputStream log, pcrs;
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
// setup
|
||||||
|
final InputStream log = this.getClass().getResourceAsStream(DEFAULT_EVENT_LOG);
|
||||||
|
final InputStream pcrs = this.getClass().getResourceAsStream(DEFAULT_EXPECTED_PCRS);
|
||||||
|
final byte[] rawLogBytes = IOUtils.toByteArray(log);
|
||||||
|
final TCGEventLog evlog = new TCGEventLog(rawLogBytes, false, false, false);
|
||||||
|
final String[] pcrFromLog = evlog.getExpectedPCRValues();
|
||||||
|
final Object[] pcrObj = IOUtils.readLines(pcrs, "UTF-8").toArray();
|
||||||
|
final String[] pcrTxt = Arrays.copyOf(pcrObj, pcrObj.length, String[].class);
|
||||||
|
|
||||||
boolean testPass = true;
|
boolean testPass = true;
|
||||||
log = this.getClass().getResourceAsStream(DEFAULT_EVENT_LOG);
|
|
||||||
byte[] rawLogBytes = IOUtils.toByteArray(log);
|
|
||||||
TCGEventLog evlog = new TCGEventLog(rawLogBytes, false, false, false);
|
|
||||||
String[] pcrFromLog = evlog.getExpectedPCRValues();
|
|
||||||
pcrs = this.getClass().getResourceAsStream(DEFAULT_EXPECTED_PCRS);
|
|
||||||
Object[] pcrObj = IOUtils.readLines(pcrs, "UTF-8").toArray();
|
|
||||||
String[] pcrTxt = Arrays.copyOf(pcrObj, pcrObj.length, String[].class);
|
|
||||||
|
|
||||||
// Test 1 get all PCRs
|
// Test 1 get all PCRs
|
||||||
for (int i = 0; i < 24; i++) {
|
for (int i = 0; i < PCR_COUNT; i++) {
|
||||||
if (pcrFromLog[i].compareToIgnoreCase(pcrTxt[i]) != 0) {
|
if (pcrFromLog[i].compareToIgnoreCase(pcrTxt[i]) != 0) {
|
||||||
testPass = false;
|
testPass = false;
|
||||||
LOGGER.error("\ntestTCGEventLogProcessorParser error with PCR " + i);
|
LOGGER.error("\ntestTCGEventLogProcessorParser error with PCR {}", i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assertTrue(testPass);
|
assertTrue(testPass);
|
||||||
|
|
||||||
// Test 2 get an individual PCR
|
// Test 2 get an individual PCR
|
||||||
String pcr3 = evlog.getExpectedPCRValue(3);
|
final int pcrIndex = 3;
|
||||||
assertThat(pcrFromLog[3], equalTo(pcr3));
|
String pcr3 = evlog.getExpectedPCRValue(pcrIndex);
|
||||||
|
assertThat(pcrFromLog[pcrIndex], equalTo(pcr3));
|
||||||
|
|
||||||
// Test 3 check the Algorithm String Identifier used in the log
|
// Test 3 check the Algorithm String Identifier used in the log
|
||||||
String algStr = evlog.getEventLogHashAlgorithm();
|
String algStr = evlog.getEventLogHashAlgorithm();
|
||||||
@ -89,10 +94,14 @@ public class TCGEventLogTest {
|
|||||||
assertThat(TcgTpmtHa.TPM_ALG_SHA256, equalTo(id));
|
assertThat(TcgTpmtHa.TPM_ALG_SHA256, equalTo(id));
|
||||||
|
|
||||||
LOGGER.debug("OK. Parsing of a Crypto Agile Format Success");
|
LOGGER.debug("OK. Parsing of a Crypto Agile Format Success");
|
||||||
|
} catch (Throwable throwable) {
|
||||||
|
throw throwable;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests the processing of a SHA1 formatted Event log.
|
* Tests the processing of a SHA1 formatted Event log.
|
||||||
|
*
|
||||||
* @throws IOException when processing the test fails
|
* @throws IOException when processing the test fails
|
||||||
* @throws NoSuchAlgorithmException if an unknown algorithm is encountered.
|
* @throws NoSuchAlgorithmException if an unknown algorithm is encountered.
|
||||||
* @throws CertificateException if a certificate fails to parse.
|
* @throws CertificateException if a certificate fails to parse.
|
||||||
@ -101,21 +110,24 @@ public class TCGEventLogTest {
|
|||||||
public final void testSHA1TCGEventLog() throws IOException, CertificateException,
|
public final void testSHA1TCGEventLog() throws IOException, CertificateException,
|
||||||
NoSuchAlgorithmException {
|
NoSuchAlgorithmException {
|
||||||
LOGGER.debug("Testing the parsing of a SHA1 formated TCG Event Log");
|
LOGGER.debug("Testing the parsing of a SHA1 formated TCG Event Log");
|
||||||
InputStream log, pcrs;
|
|
||||||
|
try {
|
||||||
|
// setup
|
||||||
|
final InputStream log = this.getClass().getResourceAsStream(SHA1_EVENT_LOG);
|
||||||
|
final InputStream pcrs = this.getClass().getResourceAsStream(SHA1_EXPECTED_PCRS);
|
||||||
|
final byte[] rawLogBytes = IOUtils.toByteArray(log);
|
||||||
|
final TCGEventLog evlog = new TCGEventLog(rawLogBytes, false, false, false);
|
||||||
|
final String[] pcrFromLog = evlog.getExpectedPCRValues();
|
||||||
|
final Object[] pcrObj = IOUtils.readLines(pcrs, "UTF-8").toArray();
|
||||||
|
final String[] pcrTxt = Arrays.copyOf(pcrObj, pcrObj.length, String[].class);
|
||||||
|
|
||||||
boolean testPass = true;
|
boolean testPass = true;
|
||||||
log = this.getClass().getResourceAsStream(SHA1_EVENT_LOG);
|
|
||||||
byte[] rawLogBytes = IOUtils.toByteArray(log);
|
|
||||||
TCGEventLog evlog = new TCGEventLog(rawLogBytes, false, false, false);
|
|
||||||
String[] pcrFromLog = evlog.getExpectedPCRValues();
|
|
||||||
pcrs = this.getClass().getResourceAsStream(SHA1_EXPECTED_PCRS);
|
|
||||||
Object[] pcrObj = IOUtils.readLines(pcrs, "UTF-8").toArray();
|
|
||||||
String[] pcrTxt = Arrays.copyOf(pcrObj, pcrObj.length, String[].class);
|
|
||||||
|
|
||||||
// Test 1 get all PCRs
|
// Test 1 get all PCRs
|
||||||
for (int i = 0; i < 24; i++) {
|
for (int i = 0; i < PCR_COUNT; i++) {
|
||||||
if (pcrFromLog[i].compareToIgnoreCase(pcrTxt[i]) != 0) {
|
if (pcrFromLog[i].compareToIgnoreCase(pcrTxt[i]) != 0) {
|
||||||
testPass = false;
|
testPass = false;
|
||||||
LOGGER.error("\ntestTCGEventLogProcessorParser error with PCR " + i);
|
LOGGER.error("\ntestTCGEventLogProcessorParser error with PCR {}", i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assertTrue(testPass);
|
assertTrue(testPass);
|
||||||
@ -133,6 +145,8 @@ public class TCGEventLogTest {
|
|||||||
assertThat(TcgTpmtHa.TPM_ALG_SHA1, equalTo(id));
|
assertThat(TcgTpmtHa.TPM_ALG_SHA1, equalTo(id));
|
||||||
|
|
||||||
LOGGER.debug("OK. Parsing of a SHA1 formatted TCG Event Log Success");
|
LOGGER.debug("OK. Parsing of a SHA1 formatted TCG Event Log Success");
|
||||||
|
} catch (Throwable throwable) {
|
||||||
|
throw throwable;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
package hirs.utils.tpm.eventlog;
|
14
build.gradle
14
build.gradle
@ -1,5 +1,4 @@
|
|||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import org.gradle.api.tasks.Copy
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
// Apply the application plugin to add support for building a CLI application in Java.
|
// Apply the application plugin to add support for building a CLI application in Java.
|
||||||
@ -19,13 +18,12 @@ subprojects {
|
|||||||
|
|
||||||
tasks.withType(com.github.spotbugs.snom.SpotBugsTask) {
|
tasks.withType(com.github.spotbugs.snom.SpotBugsTask) {
|
||||||
reports {
|
reports {
|
||||||
html {
|
html.required = true
|
||||||
enabled = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
repositories {
|
repositories {
|
||||||
// Use Maven Central for resolving dependencies.
|
// Use Maven Central for resolving dependencies.
|
||||||
@ -36,10 +34,10 @@ dependencies {
|
|||||||
def projectVersion = rootProject.file('VERSION').text.trim()
|
def projectVersion = rootProject.file('VERSION').text.trim()
|
||||||
|
|
||||||
def buildTime = { ->
|
def buildTime = { ->
|
||||||
Date latestdate = new Date();
|
Date latestdate = new Date()
|
||||||
def time = latestdate.getTime();
|
def time = latestdate.getTime()
|
||||||
long seconds = TimeUnit.MILLISECONDS.toSeconds(time);
|
long seconds = TimeUnit.MILLISECONDS.toSeconds(time)
|
||||||
return seconds;
|
return seconds
|
||||||
}
|
}
|
||||||
|
|
||||||
def gitHash = { ->
|
def gitHash = { ->
|
||||||
|
Loading…
Reference in New Issue
Block a user