diff --git a/HIRS_AttestationCA/src/test/java/hirs/attestationca/persist/entity/userdefined/DeviceTest.java b/HIRS_AttestationCA/src/test/java/hirs/attestationca/persist/entity/userdefined/DeviceTest.java new file mode 100644 index 000000000..9363281e9 --- /dev/null +++ b/HIRS_AttestationCA/src/test/java/hirs/attestationca/persist/entity/userdefined/DeviceTest.java @@ -0,0 +1,155 @@ +package hirs.attestationca.persist.entity.userdefined; + +import hirs.attestationca.persist.entity.userdefined.report.DeviceInfoReport; +import hirs.attestationca.persist.entity.userdefined.report.DeviceInfoReportTest; +import hirs.attestationca.persist.enums.AppraisalStatus; +import hirs.attestationca.persist.enums.HealthStatus; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; + +/** + * This is the test class for the Device class. + * + */ +public final class DeviceTest { + /** + * Utility method for getting a Device that can be used for + * testing. + * + * @param name name for the Device + * + * @return device + */ + public static Device getTestDevice(final String name) { + final DeviceInfoReport deviceInfo = DeviceInfoReportTest.getTestReport(); + return new Device(name, deviceInfo, HealthStatus.UNKNOWN, AppraisalStatus.Status.UNKNOWN, null, false, null, null); + } + + /** + * Tests that the device constructor can take a name. + */ + @Test + public void testDevice() { + final String name = "my-laptop"; + final Device device = new Device(name, null, HealthStatus.UNKNOWN, AppraisalStatus.Status.UNKNOWN, null, false, null , null); + assertNotNull(device); + } + + /** + * Tests that a name and device info report can be passed into the + * constructor. + */ + @Test + public void testDeviceNameAndInfo() { + final String name = "my-laptop"; + final DeviceInfoReport deviceInfo = DeviceInfoReportTest.getTestReport(); + new Device(name, deviceInfo, HealthStatus.UNKNOWN, AppraisalStatus.Status.UNKNOWN, null, false, null, null); + } + + /** + * Tests that the device name can be supplied and device info be null. + */ + @Test + public void testDeviceNameAndNullInfo() { + final String name = "my-laptop"; + final DeviceInfoReport deviceInfo = null; + new Device(name, deviceInfo, HealthStatus.UNKNOWN, AppraisalStatus.Status.UNKNOWN, null, false, null, null); + } + + /** + * Tests that get device info report returns the device info report. + */ + @Test + public void testGetDeviceInfo() { + final String name = "my-laptop"; + final DeviceInfoReport deviceInfo = DeviceInfoReportTest.getTestReport(); + final Device device = new Device(name, deviceInfo, HealthStatus.UNKNOWN, AppraisalStatus.Status.UNKNOWN, null, false, null, null); + assertEquals(deviceInfo, device.getDeviceInfo()); + } + + /** + * Tests that device info can be set. + */ + @Test + public void testSetDeviceInfo() { + final String name = "my-laptop"; + final Device device = new Device(name, null, HealthStatus.UNKNOWN, AppraisalStatus.Status.UNKNOWN, null, false, null, null); + assertNull(device.getDeviceInfo()); + final DeviceInfoReport deviceInfo = DeviceInfoReportTest.getTestReport(); + device.setDeviceInfo(deviceInfo); + assertEquals(deviceInfo, device.getDeviceInfo()); + } + + /** + * Tests that get device info report returns the device info report. + */ + @Test + public void testSetNullDeviceInfo() { + final String name = "my-laptop"; + final DeviceInfoReport deviceInfo = DeviceInfoReportTest.getTestReport(); + final Device device = new Device(name, deviceInfo, HealthStatus.UNKNOWN, AppraisalStatus.Status.UNKNOWN, null, false, null, null); + assertEquals(deviceInfo, device.getDeviceInfo()); + device.setDeviceInfo(null); + assertNull(device.getDeviceInfo()); + } + + /** + * Tests that retrieving a null LastReportTimestamp will not trigger an exception. + */ + @Test + public void testNullLastReportTimeStamp() { + final String name = "my-laptop"; + final DeviceInfoReport deviceInfo = DeviceInfoReportTest.getTestReport(); + final Device device = new Device(name, deviceInfo, HealthStatus.UNKNOWN, AppraisalStatus.Status.UNKNOWN, null, false, null, null); + assertNull(device.getLastReportTimestamp()); + } + + /** + * Tests that setting and getting the health status works correctly. + */ + @Test + public void testSetHealthStatus() { + final Device device = new Device("test-device", null, HealthStatus.UNKNOWN, AppraisalStatus.Status.UNKNOWN, null, false, null, null); + device.setHealthStatus(HealthStatus.TRUSTED); + assertEquals(HealthStatus.TRUSTED, device.getHealthStatus()); + } + + /** + * Tests equals returns true for two devices that have the same name. + */ + @Test + public void testDeviceEquals() { + final String name = "my-laptop"; + final String otherName = "my-laptop"; + final DeviceInfoReport deviceInfo = DeviceInfoReportTest.getTestReport(); + final Device device = new Device(name, deviceInfo, HealthStatus.UNKNOWN, AppraisalStatus.Status.UNKNOWN, null, false, null, null); + final Device other = new Device(otherName, deviceInfo, HealthStatus.UNKNOWN, AppraisalStatus.Status.UNKNOWN, null, false, null, null); + assertEquals(device, other); + } + + /** + * Tests that the default setting of the supply chain validation status is unknown. + */ + @Test + public void testGetDefaultSupplyChainStatus() { + String name = "my-laptop"; + DeviceInfoReport deviceInfo = DeviceInfoReportTest.getTestReport(); + final Device device = new Device(name, deviceInfo, HealthStatus.UNKNOWN, AppraisalStatus.Status.UNKNOWN, null, false, null, null); + assertEquals(AppraisalStatus.Status.UNKNOWN, device.getSupplyChainValidationStatus()); + } + + /** + * Tests that the supply chain validation status getters and setters work. + */ + @Test + public void testSetAndGetSupplyChainStatus() { + String name = "my-laptop"; + DeviceInfoReport deviceInfo = DeviceInfoReportTest.getTestReport(); + final Device device = new Device(name, deviceInfo, HealthStatus.UNKNOWN, AppraisalStatus.Status.UNKNOWN, null, false, null, null); + device.setSupplyChainValidationStatus(AppraisalStatus.Status.PASS); + assertEquals(AppraisalStatus.Status.PASS, device.getSupplyChainValidationStatus()); + } +} diff --git a/HIRS_AttestationCA/src/test/java/hirs/attestationca/persist/entity/userdefined/record/TPMMeasurementRecordTest.java b/HIRS_AttestationCA/src/test/java/hirs/attestationca/persist/entity/userdefined/record/TPMMeasurementRecordTest.java new file mode 100644 index 000000000..d77c23fda --- /dev/null +++ b/HIRS_AttestationCA/src/test/java/hirs/attestationca/persist/entity/userdefined/record/TPMMeasurementRecordTest.java @@ -0,0 +1,284 @@ +package hirs.attestationca.persist.entity.userdefined.record; + +import hirs.attestationca.persist.entity.userdefined.ExaminableRecord; +import hirs.utils.digest.Digest; +import hirs.utils.digest.DigestAlgorithm; +import org.apache.commons.codec.DecoderException; +import org.apache.commons.codec.binary.Hex; +import org.junit.jupiter.api.Test; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +/** + * PCRMeasurementRecordTest represents a unit test class for + * PCRMeasurementRecord. + */ +public class TPMMeasurementRecordTest { + + private static final Logger LOGGER + = LogManager.getLogger(TPMMeasurementRecordTest.class); + private static final int DEFAULT_PCR_ID = 3; + private static final String DEFAULT_HASH = + "3d5f3c2f7f3003d2e4baddc46ed4763a4954f648"; + private static final ExaminableRecord.ExamineState DEFAULT_STATE = ExaminableRecord.ExamineState.UNEXAMINED; + + /** + * Tests instantiation of new PCRMeasurementRecord. + */ + @Test + public final void tpmMeasurementRecord() { + TPMMeasurementRecord pcrRecord = new TPMMeasurementRecord(0, + getDigest(DEFAULT_HASH)); + assertNotNull(pcrRecord); + } + + /** + * Tests that PCRMeasurementRecord constructor throws a + * NullPointerException with null hash. + */ + @Test + public final void tpmMeasurementRecordNullHash() { + Digest digest = null; + assertThrows(NullPointerException.class, () -> + new TPMMeasurementRecord(0, digest)); + } + + /** + * Tests that PCRMeasurementRecord constructor throws a + * IllegalArgumentException with negative value for pcr id. + */ + @Test + public final void tpmMeasurementRecordNegativePcrId() { + assertThrows(IllegalArgumentException.class, () -> + new TPMMeasurementRecord(-1, getDigest(DEFAULT_HASH))); + } + + /** + * Tests that PCRMeasurementRecord constructor throws a + * IllegalArgumentException with pcr id greater than 23. + */ + @Test + public final void tpmMeasurementRecordInvalidPcrId() { + final int invalidPCR = 24; + assertThrows(IllegalArgumentException.class, () -> + new TPMMeasurementRecord(invalidPCR, getDigest(DEFAULT_HASH))); + } + + /** + * Tests that getHash() returns the measurement hash. + */ + @Test + public final void getHash() { + TPMMeasurementRecord pcrRecord = new TPMMeasurementRecord(0, + getDigest(DEFAULT_HASH)); + assertNotNull(pcrRecord.getHash()); + } + + /** + * Tests that getPcrId() returns the pcr id. + */ + @Test + public final void getPcrId() { + int id; + TPMMeasurementRecord pcrRecord = new TPMMeasurementRecord(0, + getDigest(DEFAULT_HASH)); + id = pcrRecord.getPcrId(); + assertNotNull(id); + } + + /** + * Tests that getExamineState returns the correct state. + */ + @Test + public final void getExamineState() { + final TPMMeasurementRecord record = getDefaultRecord(); + assertEquals(DEFAULT_STATE, record.getExamineState()); + } + + /** + * Tests that two IMAMeasurementRecords are equal if they have + * the same name and the same path. + */ + @Test + public final void testEquals() { + TPMMeasurementRecord r1 = getDefaultRecord(); + TPMMeasurementRecord r2 = getDefaultRecord(); + assertEquals(r1, r2); + assertEquals(r2, r1); + assertEquals(r1, r1); + assertEquals(r2, r2); + } + + /** + * Tests that two TPMMeasurementRecords are not equal if the + * PCR IDs are different. + */ + @Test + public final void testNotEqualsPcr() { + final int pcrId = 5; + TPMMeasurementRecord r1 = getDefaultRecord(); + TPMMeasurementRecord r2 = new TPMMeasurementRecord(pcrId, + getDigest(DEFAULT_HASH)); + assertNotEquals(r1, r2); + assertNotEquals(r2, r1); + assertEquals(r1, r1); + assertEquals(r2, r2); + } + + /** + * Tests that two TPMMeasurementRecords are not equal if the + * hashes are different. + */ + @Test + public final void testNotEqualsHash() { + final String hash = "aacc3c2f7f3003d2e4baddc46ed4763a4954f648"; + TPMMeasurementRecord r1 = getDefaultRecord(); + TPMMeasurementRecord r2 = + new TPMMeasurementRecord(DEFAULT_PCR_ID, getDigest(hash)); + assertNotEquals(r1, r2); + assertNotEquals(r2, r1); + assertEquals(r1, r1); + assertEquals(r2, r2); + } + + /** + * Tests that the hash code of two TPMMeasurementRecords are + * the same. + */ + @Test + public final void testHashCodeEquals() { + TPMMeasurementRecord r1 = getDefaultRecord(); + TPMMeasurementRecord r2 = getDefaultRecord(); + assertEquals(r1.hashCode(), r2.hashCode()); + assertEquals(r2.hashCode(), r1.hashCode()); + assertEquals(r1.hashCode(), r1.hashCode()); + assertEquals(r2.hashCode(), r2.hashCode()); + } + + /** + * Tests that the hash code of two TPMBaselineRecords is + * different if they have different names. + */ + @Test + public final void testHashCodeNotEqualsPcrs() { + final int pcrId = 5; + TPMMeasurementRecord r1 = getDefaultRecord(); + TPMMeasurementRecord r2 = new TPMMeasurementRecord(pcrId, + getDigest(DEFAULT_HASH)); + assertNotEquals(r1.hashCode(), r2.hashCode()); + assertNotEquals(r2.hashCode(), r1.hashCode()); + assertEquals(r1.hashCode(), r1.hashCode()); + assertEquals(r2.hashCode(), r2.hashCode()); + } + + /** + * Tests that the hash code of two TPMMeasurementRecords is + * different if they have different hashes. + */ + @Test + public final void testHashCodeNotEqualsHashes() { + final String hash = "aacc3c2f7f3003d2e4baddc46ed4763a4954f648"; + TPMMeasurementRecord r1 = getDefaultRecord(); + TPMMeasurementRecord r2 = + new TPMMeasurementRecord(DEFAULT_PCR_ID, getDigest(hash)); + assertNotEquals(r1.hashCode(), r2.hashCode()); + assertNotEquals(r2.hashCode(), r1.hashCode()); + assertEquals(r1.hashCode(), r1.hashCode()); + assertEquals(r2.hashCode(), r2.hashCode()); + } + + /** + * Tests that the expected valid PCR IDs do not throw an IllegalArgumentException. + */ + @Test + public final void testCheckForValidPcrId() { + final int minPcrId = TPMMeasurementRecord.MIN_PCR_ID; + final int maxPcrId = TPMMeasurementRecord.MAX_PCR_ID; + for (int i = minPcrId; i < maxPcrId; i++) { + TPMMeasurementRecord.checkForValidPcrId(i); + } + } + + /** + * Tests that a negative PCR ID throws an IllegalArgumentException. + */ + @Test + public final void testCheckForValidPcrIdNegative() { + final int pcrId = -1; + assertThrows(IllegalArgumentException.class, () -> + TPMMeasurementRecord.checkForValidPcrId(pcrId)); + } + + /** + * Tests that a high invalid PCR ID throws an IllegalArgumentException. + */ + @Test + public final void testCheckForValidPcrIdInvalidId() { + final int pcrId = 35; + assertThrows(IllegalArgumentException.class, () -> + TPMMeasurementRecord.checkForValidPcrId(pcrId)); + } + + /** + * Tests that the ExamineState can be successfully set to EXAMINED. + */ + @Test + public final void testSetExamineStateExamined() { + final ExaminableRecord.ExamineState state = ExaminableRecord.ExamineState.EXAMINED; + TPMMeasurementRecord r1 = getDefaultRecord(); + r1.setExamineState(state); + assertEquals(state, r1.getExamineState()); + } + + /** + * Tests that the ExamineState can be successfully set to IGNORED. + */ + @Test + public final void testSetExamineStateIgnored() { + final ExaminableRecord.ExamineState state = ExaminableRecord.ExamineState.IGNORED; + TPMMeasurementRecord r1 = getDefaultRecord(); + r1.setExamineState(state); + assertEquals(state, r1.getExamineState()); + } + + /** + * Tests that the ExamineState is successfully initialized to UNEXAMINED. + */ + @Test + public final void testSetExamineStateInitial() { + TPMMeasurementRecord r1 = getDefaultRecord(); + assertEquals(ExaminableRecord.ExamineState.UNEXAMINED, r1.getExamineState()); + } + + /** + * Tests that setting the ExamineState to UNEXAMINED throws an IllegalArgumentException. + */ + @Test + public final void testSetExamineStateUnexamined() { + final ExaminableRecord.ExamineState state = ExaminableRecord.ExamineState.UNEXAMINED; + TPMMeasurementRecord r1 = getDefaultRecord(); + assertThrows(IllegalArgumentException.class, () -> + r1.setExamineState(state)); + } + + private TPMMeasurementRecord getDefaultRecord() { + return new TPMMeasurementRecord(DEFAULT_PCR_ID, + getDigest(DEFAULT_HASH)); + } + + private Digest getDigest(final String hash) { + try { + final byte[] bytes = Hex.decodeHex(hash.toCharArray()); + return new Digest(DigestAlgorithm.SHA1, bytes); + } catch (DecoderException e) { + LOGGER.error("unable to create digest", e); + throw new RuntimeException("unable to create digest", e); + } + } +} diff --git a/HIRS_AttestationCA/src/test/java/hirs/attestationca/persist/entity/userdefined/report/DeviceInfoReportTest.java b/HIRS_AttestationCA/src/test/java/hirs/attestationca/persist/entity/userdefined/report/DeviceInfoReportTest.java new file mode 100644 index 000000000..a51f94da1 --- /dev/null +++ b/HIRS_AttestationCA/src/test/java/hirs/attestationca/persist/entity/userdefined/report/DeviceInfoReportTest.java @@ -0,0 +1,209 @@ +package hirs.attestationca.persist.entity.userdefined.report; + +import hirs.attestationca.persist.entity.userdefined.info.OSInfo; +import hirs.attestationca.persist.entity.userdefined.info.TPMInfo; +import hirs.attestationca.persist.entity.userdefined.info.NetworkInfo; +import hirs.attestationca.persist.entity.userdefined.info.HardwareInfo; +import hirs.attestationca.persist.entity.userdefined.info.FirmwareInfo; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; + +/** + * DeviceInfoReportTest is a unit test class for DeviceInfoReports. + */ +public class DeviceInfoReportTest { + private final NetworkInfo networkInfo = createTestNetworkInfo(); + private final OSInfo osInfo = createTestOSInfo(); + private final FirmwareInfo firmwareInfo = createTestFirmwareInfo(); + private final HardwareInfo hardwareInfo = createTestHardwareInfo(); + private final TPMInfo tpmInfo = createTPMInfo(); + private static final String TEST_IDENTITY_CERT = "/tpm/sample_identity_cert.cer"; + + private static final Logger LOGGER = LogManager.getLogger(DeviceInfoReportTest.class); + + private static final String EXPECTED_CLIENT_VERSION = "Test.Version"; + + /** + * Tests instantiation of a DeviceInfoReport. + */ + @Test + public final void deviceInfoReport() { + new DeviceInfoReport(networkInfo, osInfo, firmwareInfo, hardwareInfo, tpmInfo); + } + + /** + * Tests that NetworkInfo cannot be null. + */ + @Test + public final void networkInfoNull() { + assertThrows(NullPointerException.class, () -> + new DeviceInfoReport(null, osInfo, firmwareInfo, hardwareInfo, tpmInfo)); + } + + /** + * Tests that OSInfo cannot be null. + */ + @Test + public final void osInfoNull() { + assertThrows(NullPointerException.class, () -> + new DeviceInfoReport(networkInfo, null, firmwareInfo, hardwareInfo, tpmInfo)); + } + + /** + * Tests that FirmwareInfo cannot be null. + */ + @Test + public final void firmwareInfoNull() { + assertThrows(NullPointerException.class, () -> + new DeviceInfoReport(networkInfo, osInfo, null, hardwareInfo, tpmInfo)); + } + + /** + * Tests that HardwareInfo cannot be null. + */ + @Test + public final void hardwareInfoNull() { + assertThrows(NullPointerException.class, () -> + new DeviceInfoReport(networkInfo, osInfo, firmwareInfo, null, tpmInfo)); + } + + /** + * Tests that TPMInfo may be null. + */ + @Test + public final void tpmInfoNull() { + new DeviceInfoReport(networkInfo, osInfo, firmwareInfo, hardwareInfo, null); + } + + /** + * Tests that the getters for DeviceInfoReport work as expected. + */ + @Test + public final void testGetters() { + DeviceInfoReport deviceInfoReport = + new DeviceInfoReport(networkInfo, osInfo, firmwareInfo, hardwareInfo, tpmInfo); + assertEquals(networkInfo, deviceInfoReport.getNetworkInfo()); + assertEquals(osInfo, deviceInfoReport.getOSInfo()); + assertEquals(firmwareInfo, deviceInfoReport.getFirmwareInfo()); + assertEquals(hardwareInfo, deviceInfoReport.getHardwareInfo()); + assertEquals(tpmInfo, deviceInfoReport.getTpmInfo()); + assertEquals(EXPECTED_CLIENT_VERSION, deviceInfoReport.getClientApplicationVersion()); + } + + /** + * Creates a DeviceInfoReport instance usable for testing. + * + * @return a test DeviceInfoReport + */ + public static DeviceInfoReport getTestReport() { + return new DeviceInfoReport( + createTestNetworkInfo(), createTestOSInfo(), createTestFirmwareInfo(), + createTestHardwareInfo(), createTPMInfo() + ); + } + + /** + * Creates a test instance of NetworkInfo. + * + * @return network information for a fake device + */ + public static NetworkInfo createTestNetworkInfo() { + try { + final String hostname = "test.hostname"; + final InetAddress ipAddress = + InetAddress.getByAddress(new byte[] {127, 0, 0, 1}); + final byte[] macAddress = new byte[] {11, 22, 33, 44, 55, 66}; + return new NetworkInfo(hostname, ipAddress, macAddress); + + } catch (UnknownHostException e) { + LOGGER.error("error occurred while creating InetAddress"); + return null; + } + + } + + /** + * Creates a test instance of OSInfo. + * + * @return OS information for a fake device + */ + public static OSInfo createTestOSInfo() { + return new OSInfo("test os name", "test os version", "test os arch", + "test distribution", "test distribution release"); + } + + /** + * Creates a test instance of FirmwareInfo. + * + * @return Firmware information for a fake device + */ + public static FirmwareInfo createTestFirmwareInfo() { + return new FirmwareInfo("test bios vendor", "test bios version", "test bios release date"); + } + + /** + * Creates a test instance of HardwareInfo. + * + * @return Hardware information for a fake device + */ + public static HardwareInfo createTestHardwareInfo() { + return new HardwareInfo("test manufacturer", "test product name", "test version", + "test really long serial number with many characters", "test really long chassis " + + "serial number with many characters", + "test really long baseboard serial number with many characters"); + } + + /** + * Creates a test instance of TPMInfo. + * + * @return TPM information for a fake device + */ + public static final TPMInfo createTPMInfo() { + final short num1 = 1; + final short num2 = 2; + final short num3 = 3; + final short num4 = 4; + return new TPMInfo("test os make", num1, num2, num3, num4, + getTestIdentityCertificate()); + } + + private static X509Certificate getTestIdentityCertificate() { + X509Certificate certificateValue = null; + InputStream istream = null; + istream = DeviceInfoReportTest.class.getResourceAsStream( + TEST_IDENTITY_CERT + ); + try { + if (istream == null) { + throw new FileNotFoundException(TEST_IDENTITY_CERT); + } + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + certificateValue = (X509Certificate) cf.generateCertificate( + istream); + + } catch (Exception e) { + return null; + } finally { + if (istream != null) { + try { + istream.close(); + } catch (IOException e) { + LOGGER.error("test certificate file could not be closed"); + } + } + } + return certificateValue; + } +} diff --git a/HIRS_AttestationCA/src/test/resources/VERSION b/HIRS_AttestationCA/src/test/resources/VERSION new file mode 100644 index 000000000..b20b9417e --- /dev/null +++ b/HIRS_AttestationCA/src/test/resources/VERSION @@ -0,0 +1 @@ +Test.Version