From b56fb738019418e6329455cb298ce465fbd64333 Mon Sep 17 00:00:00 2001 From: Cyrus <24922493+cyrus-dev@users.noreply.github.com> Date: Wed, 2 Dec 2020 19:40:50 -0500 Subject: [PATCH 01/18] Updated the file to just use the fileName from the ReferenceManifest for the downloaded name. --- .../ReferenceManifestPageController.java | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/ReferenceManifestPageController.java b/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/ReferenceManifestPageController.java index 9f7c5c7c..243d1d8b 100644 --- a/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/ReferenceManifestPageController.java +++ b/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/ReferenceManifestPageController.java @@ -339,19 +339,7 @@ public class ReferenceManifestPageController response.sendError(HttpServletResponse.SC_NOT_FOUND); } else { StringBuilder fileName = new StringBuilder("filename=\""); - if (referenceManifest.getRimType().equals(ReferenceManifest.BASE_RIM)) { - BaseReferenceManifest bRim = (BaseReferenceManifest) referenceManifest; - fileName.append(bRim.getSwidName()); - fileName.append("_["); - fileName.append(referenceManifest.getRimHash()); - fileName.append("]"); - fileName.append(".swidTag\""); - } else { - // this needs to be updated for support rims - SupportReferenceManifest bRim = (SupportReferenceManifest) referenceManifest; - fileName.append(bRim.getFileName()); - } - + fileName.append(referenceManifest.getFileName()); // Set filename for download. response.setHeader("Content-Disposition", "attachment;" + fileName); response.setContentType("application/octet-stream"); From 62c7ca2d90eb03021759576ea0bce8f514effdd0 Mon Sep 17 00:00:00 2001 From: Cyrus <24922493+cyrus-dev@users.noreply.github.com> Date: Fri, 11 Dec 2020 14:47:46 -0500 Subject: [PATCH 02/18] This PR is to address issue #308. The ACA was pulling Issuer Certificates using the organization RDN of the subject string and getting this from the issuer string of the EC or PC. This presents a problem because it isn't a required field. The organization field cannot be null or empty. Pulling objects from a DB using null or empty would produce bad results. The main change of this issue (which has not been full tested) is pulling using the AKI for the db lookup. If this fails, instead of falling back on potentially left out fields like the O= RDN, the ACA takes the issuer/subject fields, breaks them apart and sorts them based on the key. It also changes the case. This way the lookup can be assured to match in case of some random situation in which the issuer or subject field don't match because RDN keys are just in different positions of the string. --- ...stractAttestationCertificateAuthority.java | 47 +++-- .../IssuedCertificateAttributeHelper.java | 35 +++- .../SupplyChainValidationServiceImpl.java | 47 +++-- .../SupplyChainValidationServiceImplTest.java | 10 +- .../util/CertificateStringMapBuilder.java | 42 +++-- HIRS_ProvisionerTPM2/src/TPM2_Provisioner.cpp | 2 +- .../client/collector/DeviceInfoCollector.java | 7 +- .../java/hirs/data/persist/PCRPolicy.java | 5 +- .../data/persist/certificate/Certificate.java | 178 +++++++++--------- .../CertificateAuthorityCredential.java | 24 ++- .../hirs/persist/CertificateSelector.java | 58 ++++-- .../java/hirs/tpm/eventlog/TCGEventLog.java | 11 +- .../tpm/eventlog/events/EvCompactHash.java | 3 +- .../tpm/eventlog/events/EvEfiSpecIdEvent.java | 12 +- .../tpm/eventlog/events/EvSCrtmVersion.java | 6 +- .../tpm/eventlog/uefi/UefiDevicePath.java | 7 +- .../hirs/tpm/eventlog/uefi/UefiPartition.java | 7 +- .../hirs/tpm/eventlog/uefi/UefiVariable.java | 16 +- .../utils/exec/AsynchronousExecResult.java | 3 +- .../persist/certificate/CertificateTest.java | 22 --- .../hirs/persist/CertificateSelectorTest.java | 4 +- .../persist/DBCertificateManagerTest.java | 8 +- 22 files changed, 315 insertions(+), 239 deletions(-) diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java index 25ea3f5b..ccb38c09 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java @@ -67,11 +67,11 @@ import javax.crypto.spec.OAEPParameterSpec; import javax.crypto.spec.PSource; import javax.crypto.spec.SecretKeySpec; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.math.BigInteger; import java.net.InetAddress; import java.net.UnknownHostException; import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.KeyFactory; @@ -411,11 +411,8 @@ public abstract class AbstractAttestationCertificateAuthority // and later tpm20MakeCredential function RSAPublicKey ekPub = parsePublicKey(claim.getEkPublicArea().toByteArray()); AppraisalStatus.Status validationResult = AppraisalStatus.Status.FAIL; - try { - validationResult = doSupplyChainValidation(claim, ekPub); - } catch (Exception ex) { - LOG.error(ex); - } + + validationResult = doSupplyChainValidation(claim, ekPub); if (validationResult == AppraisalStatus.Status.PASS) { RSAPublicKey akPub = parsePublicKey(claim.getAkPublicArea().toByteArray()); @@ -555,19 +552,15 @@ public abstract class AbstractAttestationCertificateAuthority if (request.getQuote() != null && !request.getQuote().isEmpty()) { parseTPMQuote(request.getQuote().toStringUtf8()); TPMInfo savedInfo = device.getDeviceInfo().getTPMInfo(); - TPMInfo tpmInfo = null; - try { - tpmInfo = new TPMInfo(savedInfo.getTPMMake(), + TPMInfo tpmInfo = new TPMInfo(savedInfo.getTPMMake(), savedInfo.getTPMVersionMajor(), savedInfo.getTPMVersionMinor(), savedInfo.getTPMVersionRevMajor(), savedInfo.getTPMVersionRevMinor(), savedInfo.getPcrValues(), - this.tpmQuoteHash.getBytes("UTF-8"), - this.tpmQuoteSignature.getBytes("UTF-8")); - } catch (UnsupportedEncodingException e) { - LOG.error(e); - } + this.tpmQuoteHash.getBytes(StandardCharsets.UTF_8), + this.tpmQuoteSignature.getBytes(StandardCharsets.UTF_8)); + DeviceInfoReport dvReport = new DeviceInfoReport( device.getDeviceInfo().getNetworkInfo(), device.getDeviceInfo().getOSInfo(), @@ -859,18 +852,14 @@ public abstract class AbstractAttestationCertificateAuthority // Get TPM info, currently unimplemented TPMInfo tpm; - try { - tpm = new TPMInfo(DeviceInfoReport.NOT_SPECIFIED, - (short) 0, - (short) 0, - (short) 0, - (short) 0, - this.pcrValues.getBytes("UTF-8"), - this.tpmQuoteHash.getBytes("UTF-8"), - this.tpmQuoteSignature.getBytes("UTF-8")); - } catch (UnsupportedEncodingException e) { - tpm = new TPMInfo(); - } + tpm = new TPMInfo(DeviceInfoReport.NOT_SPECIFIED, + (short) 0, + (short) 0, + (short) 0, + (short) 0, + this.pcrValues.getBytes(StandardCharsets.UTF_8), + this.tpmQuoteHash.getBytes(StandardCharsets.UTF_8), + this.tpmQuoteSignature.getBytes(StandardCharsets.UTF_8)); // Create final report DeviceInfoReport dvReport = new DeviceInfoReport(nw, os, fw, hw, tpm, @@ -1272,7 +1261,13 @@ public abstract class AbstractAttestationCertificateAuthority IssuedCertificateAttributeHelper.buildSubjectAlternativeNameFromCerts( endorsementCredential, platformCredentials, deviceName); + Extension authKeyIdentifier = IssuedCertificateAttributeHelper + .buildAuthorityKeyIdentifier(endorsementCredential); + builder.addExtension(subjectAlternativeName); + if (authKeyIdentifier != null) { + builder.addExtension(authKeyIdentifier); + } // identify cert as an AIK with this extension if (IssuedCertificateAttributeHelper.EXTENDED_KEY_USAGE_EXTENSION != null) { builder.addExtension(IssuedCertificateAttributeHelper.EXTENDED_KEY_USAGE_EXTENSION); diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/IssuedCertificateAttributeHelper.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/IssuedCertificateAttributeHelper.java index 4c98c3ad..1e1f27ea 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/IssuedCertificateAttributeHelper.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/IssuedCertificateAttributeHelper.java @@ -4,12 +4,14 @@ import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DERUTF8String; import org.bouncycastle.asn1.x500.AttributeTypeAndValue; import org.bouncycastle.asn1.x500.RDN; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x500.X500NameBuilder; +import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier; import org.bouncycastle.asn1.x509.ExtendedKeyUsage; import org.bouncycastle.asn1.x509.Extension; import org.bouncycastle.asn1.x509.Extensions; @@ -19,7 +21,6 @@ import org.bouncycastle.asn1.x509.GeneralNamesBuilder; import org.bouncycastle.asn1.x509.KeyPurposeId; import org.bouncycastle.asn1.x509.TBSCertificate; import org.bouncycastle.asn1.x509.AttributeCertificateInfo; -import org.springframework.util.CollectionUtils; import java.io.IOException; import java.security.cert.CertificateEncodingException; @@ -66,6 +67,28 @@ public final class IssuedCertificateAttributeHelper { // do not construct publicly } + /** + * This method builds the AKI extension that will be stored in the generated + * Attestation Issued Certificate. + * @param endorsementCredential EK object to pull AKI from. + * @return the AKI extension. + * @throws IOException on bad get instance for AKI. + */ + public static Extension buildAuthorityKeyIdentifier( + final EndorsementCredential endorsementCredential) throws IOException { + byte[] extValue = endorsementCredential.getX509Certificate() + .getExtensionValue(Extension.authorityKeyIdentifier.getId()); + + if (extValue == null) { + return null; + } + + byte[] authExtension = ASN1OctetString.getInstance(extValue).getOctets(); + AuthorityKeyIdentifier aki = AuthorityKeyIdentifier.getInstance(authExtension); + + return new Extension(Extension.authorityKeyIdentifier, true, aki.getEncoded()); + } + /** * Builds the subject alternative name based on the supplied certificates. * @param endorsementCredential the endorsement credential @@ -88,10 +111,8 @@ public final class IssuedCertificateAttributeHelper { // assemble AIK cert SAN, using info from EC and PC X500NameBuilder nameBuilder = new X500NameBuilder(); populateEndorsementCredentialAttributes(endorsementCredential, nameBuilder); - if (!CollectionUtils.isEmpty(platformCredentials)) { - for (PlatformCredential platformCredential : platformCredentials) { - populatePlatformCredentialAttributes(platformCredential, nameBuilder); - } + for (PlatformCredential platformCredential : platformCredentials) { + populatePlatformCredentialAttributes(platformCredential, nameBuilder); } // add the OID for the TCG-required TPM ID label @@ -112,7 +133,7 @@ public final class IssuedCertificateAttributeHelper { private static void populatePlatformCredentialAttributes( final PlatformCredential platformCredential, final X500NameBuilder nameBuilder) throws IOException { - if (null == platformCredential) { + if (platformCredential == null) { return; } @@ -134,7 +155,7 @@ public final class IssuedCertificateAttributeHelper { private static void populateEndorsementCredentialAttributes( final EndorsementCredential endorsementCredential, final X500NameBuilder nameBuilder) { - if (null == endorsementCredential) { + if (endorsementCredential == null) { return; } diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationServiceImpl.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationServiceImpl.java index 9cc6d494..30a79d1c 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationServiceImpl.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationServiceImpl.java @@ -16,10 +16,12 @@ import hirs.data.persist.PCRPolicy; import hirs.data.persist.ArchivableEntity; import hirs.tpm.eventlog.TCGEventLog; import hirs.tpm.eventlog.TpmPcrEvent; +import hirs.utils.BouncyCastleUtils; import hirs.utils.ReferenceManifestValidator; import hirs.validation.SupplyChainCredentialValidator; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.bouncycastle.util.encoders.Hex; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Import; import org.springframework.stereotype.Service; @@ -51,7 +53,6 @@ import hirs.data.persist.ReferenceManifest; import hirs.persist.AppraiserManager; import hirs.persist.CertificateManager; import hirs.persist.ReferenceManifestManager; -import hirs.persist.CertificateSelector; import hirs.persist.CrudManager; import hirs.persist.DBManagerException; import hirs.persist.PersistenceConfiguration; @@ -803,27 +804,49 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe * certs with an identical subject and issuer org) * * @param credential the credential whose CA chain should be retrieved - * @param previouslyQueriedOrganizations a list of organizations to refrain + * @param previouslyQueriedSubjects a list of organizations to refrain * from querying * @return a Set containing all relevant CA credentials to the given * certificate's organization */ private Set getCaChainRec( final Certificate credential, - final Set previouslyQueriedOrganizations - ) { - CertificateSelector caSelector - = CertificateAuthorityCredential.select(certificateManager) - .bySubjectOrganization(credential.getIssuerOrganization()); - Set certAuthsWithMatchingOrg = caSelector.getCertificates(); + final Set previouslyQueriedSubjects) { + CertificateAuthorityCredential skiCA = null; + Set certAuthsWithMatchingIssuer = new HashSet<>(); + if (credential.getAuthKeyId() != null + && !credential.getAuthKeyId().isEmpty()) { + byte[] bytes = Hex.decode(credential.getAuthKeyId()); + skiCA = CertificateAuthorityCredential + .select(certificateManager) + .bySubjectKeyIdentifier(bytes).getCertificate(); + } - Set queriedOrganizations = new HashSet<>(previouslyQueriedOrganizations); - queriedOrganizations.add(credential.getIssuerOrganization()); + if (skiCA == null) { + if (credential.getIssuerSorted() == null + || credential.getIssuerSorted().isEmpty()) { + certAuthsWithMatchingIssuer = CertificateAuthorityCredential + .select(certificateManager) + .bySubject(credential.getIssuer()) + .getCertificates(); + } else { + //Get certificates by subject organization + certAuthsWithMatchingIssuer = CertificateAuthorityCredential + .select(certificateManager) + .bySubjectSorted(credential.getIssuerSorted()) + .getCertificates(); + } + } else { + certAuthsWithMatchingIssuer.add(skiCA); + } + Set queriedOrganizations = new HashSet<>(previouslyQueriedSubjects); + queriedOrganizations.add(credential.getIssuer()); HashSet caCreds = new HashSet<>(); - for (CertificateAuthorityCredential cred : certAuthsWithMatchingOrg) { + for (CertificateAuthorityCredential cred : certAuthsWithMatchingIssuer) { caCreds.add(cred); - if (!queriedOrganizations.contains(cred.getIssuerOrganization())) { + if (!BouncyCastleUtils.x500NameCompare(cred.getIssuer(), + cred.getSubject())) { caCreds.addAll(getCaChainRec(cred, queriedOrganizations)); } } diff --git a/HIRS_AttestationCA/src/test/java/hirs/attestationca/service/SupplyChainValidationServiceImplTest.java b/HIRS_AttestationCA/src/test/java/hirs/attestationca/service/SupplyChainValidationServiceImplTest.java index 079547de..b4d0d7b1 100644 --- a/HIRS_AttestationCA/src/test/java/hirs/attestationca/service/SupplyChainValidationServiceImplTest.java +++ b/HIRS_AttestationCA/src/test/java/hirs/attestationca/service/SupplyChainValidationServiceImplTest.java @@ -119,7 +119,7 @@ public class SupplyChainValidationServiceImplTest extends SpringPersistenceTest // mock endorsement credential ec = mock(EndorsementCredential.class); when(ec.getEncodedPublicKey()).thenReturn(new byte[] {0x0}); - when(ec.getIssuerOrganization()).thenReturn("STMicroelectronics NV"); + when(ec.getIssuerSorted()).thenReturn("STMicroelectronics NV"); Set resultEcs = new HashSet<>(); resultEcs.add(ec); @@ -131,8 +131,8 @@ public class SupplyChainValidationServiceImplTest extends SpringPersistenceTest when(pc.getX509Certificate()).thenReturn(cert); when(pc.getSerialNumber()).thenReturn(BigInteger.ONE); when(pc.getPlatformSerial()).thenReturn(String.valueOf(Integer.MIN_VALUE)); - when(pc.getIssuerOrganization()).thenReturn("STMicroelectronics NV"); - when(ec.getSubjectOrganization()).thenReturn("STMicroelectronics NV"); + when(pc.getIssuerSorted()).thenReturn("STMicroelectronics NV"); + when(ec.getSubjectSorted()).thenReturn("STMicroelectronics NV"); pcs = new HashSet(); pcs.add(pc); @@ -142,8 +142,8 @@ public class SupplyChainValidationServiceImplTest extends SpringPersistenceTest when(delta.getId()).thenReturn(UUID.randomUUID()); when(delta.getX509Certificate()).thenReturn(deltaCert); //when(delta.getSerialNumber()).thenReturn(BigInteger.ONE); - when(delta.getIssuerOrganization()).thenReturn("STMicroelectronics NV"); - when(delta.getSubjectOrganization()).thenReturn("STMicroelectronics NV"); + when(delta.getIssuerSorted()).thenReturn("STMicroelectronics NV"); + when(delta.getSubjectSorted()).thenReturn("STMicroelectronics NV"); Set resultPcs = new HashSet<>(); resultPcs.add(pc); diff --git a/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/util/CertificateStringMapBuilder.java b/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/util/CertificateStringMapBuilder.java index 60c7a734..1fe8dc0c 100644 --- a/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/util/CertificateStringMapBuilder.java +++ b/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/util/CertificateStringMapBuilder.java @@ -7,6 +7,7 @@ import java.io.IOException; import java.math.BigInteger; import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.Set; import java.util.List; import java.util.Comparator; @@ -21,6 +22,8 @@ import hirs.data.persist.certificate.attributes.ComponentIdentifier; import hirs.data.persist.certificate.attributes.PlatformConfiguration; import hirs.persist.CertificateManager; import hirs.utils.BouncyCastleUtils; +import org.bouncycastle.util.encoders.Hex; + import java.util.Collections; /** @@ -134,20 +137,35 @@ public final class CertificateStringMapBuilder { public static Certificate containsAllChain( final Certificate certificate, final CertificateManager certificateManager) { - - Set issuerCertificates; + Set issuerCertificates = new HashSet<>(); + CertificateAuthorityCredential skiCA = null; //Check if there is a subject organization - if (certificate.getIssuerOrganization() == null - || certificate.getIssuerOrganization().isEmpty()) { - //Get certificates by subject - issuerCertificates = CertificateAuthorityCredential.select(certificateManager) - .bySubject(certificate.getIssuer()) - .getCertificates(); + if (certificate.getAuthKeyId() != null + && !certificate.getAuthKeyId().isEmpty()) { + byte[] bytes = Hex.decode(certificate.getAuthKeyId()); + skiCA = CertificateAuthorityCredential + .select(certificateManager) + .bySubjectKeyIdentifier(bytes).getCertificate(); } else { - //Get certificates by subject organization - issuerCertificates = CertificateAuthorityCredential.select(certificateManager) - .bySubjectOrganization(certificate.getIssuerOrganization()) - .getCertificates(); + LOGGER.info(String.format("Certificate (%s) for %s has no authority key identifier.", + certificate.getClass().toString(), certificate.getSubject())); + } + + if (skiCA == null) { + if (certificate.getIssuerSorted() == null + || certificate.getIssuerSorted().isEmpty()) { + //Get certificates by subject + issuerCertificates = CertificateAuthorityCredential.select(certificateManager) + .bySubject(certificate.getIssuer()) + .getCertificates(); + } else { + //Get certificates by subject organization + issuerCertificates = CertificateAuthorityCredential.select(certificateManager) + .bySubjectSorted(certificate.getIssuerSorted()) + .getCertificates(); + } + } else { + issuerCertificates.add(skiCA); } for (Certificate issuerCert : issuerCertificates) { diff --git a/HIRS_ProvisionerTPM2/src/TPM2_Provisioner.cpp b/HIRS_ProvisionerTPM2/src/TPM2_Provisioner.cpp index 5c185742..b4853705 100644 --- a/HIRS_ProvisionerTPM2/src/TPM2_Provisioner.cpp +++ b/HIRS_ProvisionerTPM2/src/TPM2_Provisioner.cpp @@ -130,7 +130,7 @@ int provision() { RestfulClientProvisioner provisioner; string nonceBlob = provisioner.sendIdentityClaim(identityClaim); if (nonceBlob == "") { - cout << "----> Provisioning failed."; + cout << "----> Provisioning failed." << endl; cout << "Please refer to the Attestation CA for details." << endl; return 0; } diff --git a/HIRS_Utils/src/main/java/hirs/client/collector/DeviceInfoCollector.java b/HIRS_Utils/src/main/java/hirs/client/collector/DeviceInfoCollector.java index 48e3e7f8..21ec45dc 100644 --- a/HIRS_Utils/src/main/java/hirs/client/collector/DeviceInfoCollector.java +++ b/HIRS_Utils/src/main/java/hirs/client/collector/DeviceInfoCollector.java @@ -32,6 +32,7 @@ import java.net.Inet6Address; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import java.security.cert.CertificateException; @@ -362,7 +363,7 @@ public class DeviceInfoCollector extends AbstractCollector { if (debianRelease.exists()) { try { reader = new BufferedReader(new InputStreamReader( - new FileInputStream(debianRelease), "UTF-8")); + new FileInputStream(debianRelease), StandardCharsets.UTF_8)); while ((line = reader.readLine()) != null) { String[] ubuntuTokens = line.split("="); if (ubuntuTokens.length == 2) { @@ -394,7 +395,7 @@ public class DeviceInfoCollector extends AbstractCollector { } else if (redhatRelease.exists()) { try { reader = new BufferedReader(new InputStreamReader( - new FileInputStream(redhatRelease), "UTF-8")); + new FileInputStream(redhatRelease), StandardCharsets.UTF_8)); while ((line = reader.readLine()) != null) { String[] redhatTokens = line.split("release"); if (redhatTokens.length == 2) { @@ -543,7 +544,7 @@ public class DeviceInfoCollector extends AbstractCollector { Process quoteProcess = processBuilder.start(); quoteReader = new BufferedReader(new InputStreamReader( - quoteProcess.getInputStream(), "utf-8")); + quoteProcess.getInputStream(), StandardCharsets.UTF_8)); } catch (IOException e) { LOGGER.info("IOException occurred while attempting to read " + "tpm_version command, assume the TPM is not present and " diff --git a/HIRS_Utils/src/main/java/hirs/data/persist/PCRPolicy.java b/HIRS_Utils/src/main/java/hirs/data/persist/PCRPolicy.java index 4f9722f6..e9ff4cc6 100644 --- a/HIRS_Utils/src/main/java/hirs/data/persist/PCRPolicy.java +++ b/HIRS_Utils/src/main/java/hirs/data/persist/PCRPolicy.java @@ -12,7 +12,7 @@ import org.apache.commons.codec.DecoderException; import org.apache.commons.codec.binary.Hex; import org.apache.logging.log4j.Logger; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.security.NoSuchAlgorithmException; import java.util.Arrays; @@ -100,8 +100,7 @@ public final class PCRPolicy extends Policy { LOGGER.info("Validating quote from associated device."); boolean validated = false; short localityAtRelease = 0; - Charset charset = Charset.forName("UTF-8"); - String quoteString = new String(tpmQuote, charset); + String quoteString = new String(tpmQuote, StandardCharsets.UTF_8); TPMMeasurementRecord[] measurements = new TPMMeasurementRecord[baselinePcrs.length]; try { diff --git a/HIRS_Utils/src/main/java/hirs/data/persist/certificate/Certificate.java b/HIRS_Utils/src/main/java/hirs/data/persist/certificate/Certificate.java index d483cbec..79146587 100644 --- a/HIRS_Utils/src/main/java/hirs/data/persist/certificate/Certificate.java +++ b/HIRS_Utils/src/main/java/hirs/data/persist/certificate/Certificate.java @@ -62,8 +62,10 @@ import java.security.cert.X509Certificate; import java.text.ParseException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.Date; import java.util.List; +import java.util.ListIterator; import java.util.Objects; import org.bouncycastle.asn1.x509.CRLDistPoint; import org.bouncycastle.asn1.x509.DistributionPoint; @@ -163,6 +165,12 @@ public abstract class Certificate extends ArchivableEntity { public static final String ISSUER_FIELD = "issuer"; @Column(nullable = false) private final String issuer; + /** + * Holds the name of the 'issuerSorted' field. + */ + public static final String ISSUER_SORTED_FIELD = "issuerSorted"; + @Column + private final String issuerSorted; /** * Holds the name of the 'subject' field. @@ -170,20 +178,12 @@ public abstract class Certificate extends ArchivableEntity { public static final String SUBJECT_FIELD = "subject"; @Column(nullable = true) private final String subject; - /** - * Holds the name of the 'issuerOrganization' field. + * Holds the name of the 'subjectSorted' field. */ - public static final String ISSUER_ORGANIZATION_FIELD = "issuerOrganization"; + public static final String SUBJECT_SORTED_FIELD = "subjectSorted"; @Column - private String issuerOrganization = null; - - /** - * Holds the name of the 'subjectOrganization' field. - */ - public static final String SUBJECT_ORGANIZATION_FIELD = "subjectOrganization"; - @Column - private String subjectOrganization = null; + private final String subjectSorted; /** * Holds the name of the 'encodedPublicKey' field. @@ -255,12 +255,15 @@ public abstract class Certificate extends ArchivableEntity { private String keyUsage; private String extendedKeyUsage; private byte[] policyConstraints; + /** + * Holds the name of the 'authorityKeyIdentifier' field. + */ + public static final String AUTHORITY_KEY_ID_FIELD = "authorityKeyIdentifier"; private String authorityKeyIdentifier; private String authorityInfoAccess; private String crlPoints; private int publicKeySize; - /** * Default constructor necessary for Hibernate. */ @@ -269,6 +272,8 @@ public abstract class Certificate extends ArchivableEntity { this.serialNumber = BigInteger.ZERO; this.issuer = null; this.subject = null; + this.issuerSorted = null; + this.subjectSorted = null; this.encodedPublicKey = null; this.publicKeyModulusHexValue = null; @@ -359,8 +364,8 @@ public abstract class Certificate extends ArchivableEntity { this.beginValidity = x509Certificate.getNotBefore(); this.endValidity = x509Certificate.getNotAfter(); this.holderSerialNumber = BigInteger.ZERO; - this.issuerOrganization = getOrganization(this.issuer); - this.subjectOrganization = getOrganization(this.subject); + this.issuerSorted = parseSortDNs(this.issuer); + this.subjectSorted = parseSortDNs(this.subject); this.policyConstraints = x509Certificate .getExtensionValue(POLICY_CONSTRAINTS); authKeyIdentifier = AuthorityKeyIdentifier @@ -395,7 +400,7 @@ public abstract class Certificate extends ArchivableEntity { // Set null values (Attribute certificates do not have this values) this.subject = null; - this.subjectOrganization = null; + this.subjectSorted = null; this.encodedPublicKey = null; this.publicKeyModulusHexValue = null; this.publicKeySize = 0; @@ -434,7 +439,7 @@ public abstract class Certificate extends ArchivableEntity { this.signature = attCert.getSignatureValue().getBytes(); this.issuer = getAttributeCertificateIssuerNames( attCertInfo.getIssuer())[0].toString(); - this.issuerOrganization = getOrganization(this.issuer); + this.issuerSorted = parseSortDNs(this.issuer); // Parse notBefore and notAfter dates this.beginValidity = recoverDate(attCertInfo @@ -536,39 +541,6 @@ public abstract class Certificate extends ArchivableEntity { return CertificateType.INVALID_CERTIFICATE; } - /** - * Extracts the organization field out of a distinguished name. Returns null if - * no organization field exists. - * @param distinguishedName distinguished name to extract the organization from - * @return the value of the organization field - */ - protected static String getOrganization(final String distinguishedName) { - String organization = null; - - // Return null for empty strings - if (distinguishedName.isEmpty()) { - return null; - } - - // Parse string to X500Name - X500Name name = new X500Name(distinguishedName); - if (name.getRDNs(RFC4519Style.o).length > 0) { - RDN rdn = name.getRDNs(RFC4519Style.o)[0]; - // For multivalue check the RDNs Attributes - if (rdn.isMultiValued()) { - for (AttributeTypeAndValue att: rdn.getTypesAndValues()) { - if (RFC4519Style.o.equals(att.getType())) { - organization = att.getValue().toString(); - } - } - } else { - organization = rdn.getFirst().getValue().toString(); - } - } - - return organization; - } - private boolean isPEM(final String possiblePEM) { return possiblePEM.contains(PEM_HEADER) || possiblePEM.contains(PEM_ATTRIBUTE_HEADER); } @@ -785,41 +757,39 @@ public abstract class Certificate extends ArchivableEntity { * @throws IOException if there is an issue deserializing either certificate */ public boolean isIssuer(final Certificate issuer) throws IOException { - CertificateType cType = issuer.getCertificateType(); - if (cType != CertificateType.X509_CERTIFICATE) { - throw new IllegalArgumentException("issuer cert must be X509Certificate"); - } - boolean isIssuer = false; - X509Certificate issuerX509 = issuer.getX509Certificate(); - - // Validate if it's the issuer - switch (getCertificateType()) { - case X509_CERTIFICATE: - X509Certificate certX509 = getX509Certificate(); - try { - certX509.verify(issuerX509.getPublicKey()); - isIssuer = true; - } catch (CertificateException | NoSuchAlgorithmException | InvalidKeyException - | NoSuchProviderException | SignatureException e) { - LOGGER.error(e); - } - break; - - case ATTRIBUTE_CERTIFICATE: - AttributeCertificate attCert = getAttributeCertificate(); - String algorith = "SHA256withRSA"; - try { - Signature sig = Signature.getInstance(algorith); - sig.initVerify(issuerX509.getPublicKey()); - sig.update(attCert.getAcinfo().getEncoded()); - isIssuer = sig.verify(attCert.getSignatureValue().getBytes()); - } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) { - LOGGER.error(e); - } - break; - default: - break; + // only run if of the correct type, otherwise false + if (issuer.getCertificateType() == CertificateType.X509_CERTIFICATE) { + X509Certificate issuerX509 = issuer.getX509Certificate(); + // Validate if it's the issuer + switch (getCertificateType()) { + case X509_CERTIFICATE: + X509Certificate certX509 = getX509Certificate(); + try { + certX509.verify(issuerX509.getPublicKey()); + isIssuer = true; + } catch (CertificateException | NoSuchAlgorithmException | InvalidKeyException + | NoSuchProviderException | SignatureException e) { + LOGGER.error(e); + } + break; + case ATTRIBUTE_CERTIFICATE: + AttributeCertificate attCert = getAttributeCertificate(); + String algorithm = "SHA256withRSA"; + try { + Signature sig = Signature.getInstance(algorithm); + sig.initVerify(issuerX509.getPublicKey()); + sig.update(attCert.getAcinfo().getEncoded()); + isIssuer = sig.verify(attCert.getSignatureValue().getBytes()); + } catch (NoSuchAlgorithmException + | InvalidKeyException + | SignatureException e) { + LOGGER.error(e); + } + break; + default: + break; + } } return isIssuer; @@ -1055,17 +1025,17 @@ public abstract class Certificate extends ArchivableEntity { } /** - * @return this certificate's associated issuer organization + * @return this certificate's associated issuer sorted */ - public String getIssuerOrganization() { - return issuerOrganization; + public String getIssuerSorted() { + return issuerSorted; } /** - * @return this certificate's associated subject organization + * @return this certificate's associated subject sorted */ - public String getSubjectOrganization() { - return subjectOrganization; + public String getSubjectSorted() { + return subjectSorted; } /** @@ -1187,6 +1157,36 @@ public abstract class Certificate extends ArchivableEntity { } } + /** + * This method is to take the DNs from certificates and sort them in an order + * that will be used to lookup issuer certificates. This will not be stored in + * the certificate, just the DB for lookup. + * @param distinguishedName the original DN string. + * @return a modified string of sorted DNs + */ + public static String parseSortDNs(final String distinguishedName) { + StringBuilder sb = new StringBuilder(); + String dnsString; + + if (distinguishedName == null || distinguishedName.isEmpty()) { + sb.append("BLANK"); + } else { + dnsString = distinguishedName.trim(); + dnsString = dnsString.toLowerCase(); + List dnValArray = Arrays.asList(dnsString.split(",")); + Collections.sort(dnValArray); + ListIterator dnListIter = dnValArray.listIterator(); + while (dnListIter.hasNext()) { + sb.append(dnListIter.next()); + if (dnListIter.hasNext()) { + sb.append(","); + } + } + } + + return sb.toString(); + } + /** * Retrieve the X509 Name array from the issuer in an Attribute Certificate. * diff --git a/HIRS_Utils/src/main/java/hirs/data/persist/certificate/CertificateAuthorityCredential.java b/HIRS_Utils/src/main/java/hirs/data/persist/certificate/CertificateAuthorityCredential.java index eb4c6e53..2557ba96 100644 --- a/HIRS_Utils/src/main/java/hirs/data/persist/certificate/CertificateAuthorityCredential.java +++ b/HIRS_Utils/src/main/java/hirs/data/persist/certificate/CertificateAuthorityCredential.java @@ -2,6 +2,7 @@ package hirs.data.persist.certificate; import hirs.persist.CertificateManager; import hirs.persist.CertificateSelector; +import org.apache.commons.codec.binary.Hex; import javax.persistence.Column; import javax.persistence.Entity; @@ -15,7 +16,8 @@ import java.util.Arrays; */ @Entity public class CertificateAuthorityCredential extends Certificate { - @SuppressWarnings("PMD.AvoidUsingHardCodedIP") // this is not an IP address; PMD thinks it is + + @SuppressWarnings("PMD.AvoidUsingHardCodedIP") private static final String SUBJECT_KEY_IDENTIFIER_EXTENSION = "2.5.29.14"; /** @@ -26,9 +28,12 @@ public class CertificateAuthorityCredential extends Certificate { @Column private final byte[] subjectKeyIdentifier; - /* + @Column + private String subjectKeyIdString; + + /** * this field is part of the TCG CA specification, but has not yet been found in - * manufacturer-provided CAs, and is therefore not currently parsed + * manufacturer-provided CAs, and is therefore not currently parsed. */ @Column private String credentialType = "TCPA Trusted Platform Module Endorsement"; @@ -82,6 +87,9 @@ public class CertificateAuthorityCredential extends Certificate { super(certificateBytes); this.subjectKeyIdentifier = getX509Certificate().getExtensionValue(SUBJECT_KEY_IDENTIFIER_EXTENSION); + if (this.subjectKeyIdentifier != null) { + this.subjectKeyIdString = Hex.encodeHexString(this.subjectKeyIdentifier); + } } /** @@ -119,12 +127,20 @@ public class CertificateAuthorityCredential extends Certificate { * @return this certificate's subject key identifier. */ public byte[] getSubjectKeyIdentifier() { - if (null != subjectKeyIdentifier) { + if (subjectKeyIdentifier != null) { return subjectKeyIdentifier.clone(); } return null; } + /** + * Getter for the string rep of the ID. + * @return a string + */ + public String getSubjectKeyIdString() { + return this.subjectKeyIdString; + } + @Override @SuppressWarnings("checkstyle:avoidinlineconditionals") public boolean equals(final Object o) { diff --git a/HIRS_Utils/src/main/java/hirs/persist/CertificateSelector.java b/HIRS_Utils/src/main/java/hirs/persist/CertificateSelector.java index 0527ef0a..c3c81f01 100644 --- a/HIRS_Utils/src/main/java/hirs/persist/CertificateSelector.java +++ b/HIRS_Utils/src/main/java/hirs/persist/CertificateSelector.java @@ -175,7 +175,8 @@ public abstract class CertificateSelector { public CertificateSelector byIssuer(final String issuer) { Preconditions.checkArgument( StringUtils.isNotEmpty(issuer), - "issuer cannot be null or empty." + String.format("%s: issuer cannot be null or empty.", + this.certificateClass.toString()) ); setFieldValue(Certificate.ISSUER_FIELD, issuer); @@ -192,7 +193,8 @@ public abstract class CertificateSelector { public CertificateSelector bySubject(final String subject) { Preconditions.checkArgument( StringUtils.isNotEmpty(subject), - "subject cannot be null or empty." + String.format("%s: subject cannot be null or empty.", + this.certificateClass.toString()) ); setFieldValue(Certificate.SUBJECT_FIELD, subject); @@ -200,36 +202,38 @@ public abstract class CertificateSelector { } /** - * Specify an issuer organization string that certificates must have to be considered + * Specify the sorted issuer string that certificates must have to be considered * as matching. * - * @param organization certificate issuer organization string to query, not empty or null + * @param issuerSorted certificate issuer organization string to query, not empty or null * @return this instance (for chaining further calls) */ - public CertificateSelector byIssuerOrganization(final String organization) { + public CertificateSelector byIssuerSorted(final String issuerSorted) { Preconditions.checkArgument( - StringUtils.isNotEmpty(organization), - "organization cannot be null or empty." + StringUtils.isNotEmpty(issuerSorted), + String.format("%s: issuerSorted cannot be null or empty.", + this.certificateClass.toString()) ); - setFieldValue(Certificate.ISSUER_ORGANIZATION_FIELD, organization); + setFieldValue(Certificate.ISSUER_SORTED_FIELD, issuerSorted); return this; } /** - * Specify a subject organization string that certificates must have to be considered + * Specify the sorted subject string that certificates must have to be considered * as matching. * - * @param organization certificate subject organization string to query, not empty or null + * @param subjectSorted certificate subject organization string to query, not empty or null * @return this instance (for chaining further calls) */ - public CertificateSelector bySubjectOrganization(final String organization) { + public CertificateSelector bySubjectSorted(final String subjectSorted) { Preconditions.checkArgument( - StringUtils.isNotEmpty(organization), - "organization cannot be null or empty." + StringUtils.isNotEmpty(subjectSorted), + String.format("%s: subjectSorted cannot be null or empty.", + this.certificateClass.toString()) ); - setFieldValue(Certificate.SUBJECT_ORGANIZATION_FIELD, organization); + setFieldValue(Certificate.SUBJECT_SORTED_FIELD, subjectSorted); return this; } @@ -243,7 +247,8 @@ public abstract class CertificateSelector { public CertificateSelector byEncodedPublicKey(final byte[] encodedPublicKey) { Preconditions.checkArgument( ArrayUtils.isNotEmpty(encodedPublicKey), - "publicKey cannot be null or empty." + String.format("%s: publicKey cannot be null or empty.", + this.certificateClass.toString()) ); setFieldValue( @@ -254,6 +259,23 @@ public abstract class CertificateSelector { return this; } + /** + * Specify the authority key identifier to find certificate(s). + * @param authorityKeyIdentifier the string of the AKI associated with the certificate. + * @return this instance + */ + public CertificateSelector byAuthorityKeyIdentifier(final String authorityKeyIdentifier) { + Preconditions.checkArgument( + StringUtils.isNotEmpty(authorityKeyIdentifier), + String.format("%s: authorityKeyIdentifier cannot be null or empty.", + this.certificateClass.toString()) + ); + + setFieldValue(Certificate.AUTHORITY_KEY_ID_FIELD, authorityKeyIdentifier); + + return this; + } + /** * Specify a public key modulus that certificates must have to be considered * as matching. @@ -264,7 +286,8 @@ public abstract class CertificateSelector { public CertificateSelector byPublicKeyModulus(final BigInteger publicKeyModulus) { Preconditions.checkArgument( publicKeyModulus != null, - "Public key modulus cannot be null" + String.format("%s: Public key modulus cannot be null", + this.certificateClass.toString()) ); setFieldValue( @@ -428,8 +451,7 @@ public abstract class CertificateSelector { // construct and execute query private Set execute() { - Set results = certificateManager.get(this); - return results; + return certificateManager.get(this); } /** diff --git a/HIRS_Utils/src/main/java/hirs/tpm/eventlog/TCGEventLog.java b/HIRS_Utils/src/main/java/hirs/tpm/eventlog/TCGEventLog.java index e7dc7199..92975056 100644 --- a/HIRS_Utils/src/main/java/hirs/tpm/eventlog/TCGEventLog.java +++ b/HIRS_Utils/src/main/java/hirs/tpm/eventlog/TCGEventLog.java @@ -2,8 +2,8 @@ package hirs.tpm.eventlog; import java.io.ByteArrayInputStream; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.math.BigInteger; +import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; @@ -350,9 +350,8 @@ public final class TCGEventLog { * * @param log The Event Log * @return true if EfiSpecIDEvent is found and indicates that the format is crypto agile - * @throws UnsupportedEncodingException if parsing error occurs. */ - private boolean isLogCrytoAgile(final byte[] log) throws UnsupportedEncodingException { + private boolean isLogCrytoAgile(final byte[] log) { byte[] eType = new byte[UefiConstants.SIZE_4]; System.arraycopy(log, UefiConstants.SIZE_4, eType, 0, UefiConstants.SIZE_4); byte[] eventType = HexUtils.leReverseByte(eType); @@ -361,8 +360,10 @@ public final class TCGEventLog { return false; } // Event Type should be EV_NO_ACTION byte[] signature = new byte[SIG_SIZE]; - System.arraycopy(log, SIG_OFFSET, signature, 0, SIG_SIZE); // should be "Spec ID Event03" - String sig = new String(signature, "UTF-8").substring(0, SIG_SIZE - 1); // remove null char + // should be "Spec ID Event03" + System.arraycopy(log, SIG_OFFSET, signature, 0, SIG_SIZE); + // remove null char + String sig = new String(signature, StandardCharsets.UTF_8).substring(0, SIG_SIZE - 1); return sig.equals("Spec ID Event03"); } diff --git a/HIRS_Utils/src/main/java/hirs/tpm/eventlog/events/EvCompactHash.java b/HIRS_Utils/src/main/java/hirs/tpm/eventlog/events/EvCompactHash.java index 1a2df0e2..0a94e997 100644 --- a/HIRS_Utils/src/main/java/hirs/tpm/eventlog/events/EvCompactHash.java +++ b/HIRS_Utils/src/main/java/hirs/tpm/eventlog/events/EvCompactHash.java @@ -1,6 +1,7 @@ package hirs.tpm.eventlog.events; import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; import hirs.tpm.eventlog.uefi.UefiConstants; import hirs.utils.HexUtils; @@ -38,7 +39,7 @@ public class EvCompactHash { if (event.length == UefiConstants.SIZE_4) { // older PFP defines as 4 byte ESI pointer. eventInfo = " ESI = " + HexUtils.byteArrayToHexString(event); } else { // otherwise assume the event content is a string - eventInfo = " " + new String(event, "UTF-8"); + eventInfo = " " + new String(event, StandardCharsets.UTF_8); } return eventInfo; } diff --git a/HIRS_Utils/src/main/java/hirs/tpm/eventlog/events/EvEfiSpecIdEvent.java b/HIRS_Utils/src/main/java/hirs/tpm/eventlog/events/EvEfiSpecIdEvent.java index 5e0f5682..332d2e28 100644 --- a/HIRS_Utils/src/main/java/hirs/tpm/eventlog/events/EvEfiSpecIdEvent.java +++ b/HIRS_Utils/src/main/java/hirs/tpm/eventlog/events/EvEfiSpecIdEvent.java @@ -1,6 +1,6 @@ package hirs.tpm.eventlog.events; -import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import hirs.tpm.eventlog.TcgTpmtHa; @@ -67,13 +67,13 @@ public class EvEfiSpecIdEvent { /** * EvEfiSpecIdEvent Constructor. * @param efiSpecId byte array holding the spec ID Event. - * @throws UnsupportedEncodingException if input fails to parse. */ - public EvEfiSpecIdEvent(final byte[] efiSpecId) throws UnsupportedEncodingException { + public EvEfiSpecIdEvent(final byte[] efiSpecId) { byte[] signatureBytes = new byte[UefiConstants.SIZE_16]; System.arraycopy(efiSpecId, 0, signatureBytes, 0, UefiConstants.SIZE_16); signature = HexUtils.byteArrayToHexString(signatureBytes); - signature = new String(signatureBytes, "UTF-8").substring(0, UefiConstants.SIZE_15); + signature = new String(signatureBytes, StandardCharsets.UTF_8) + .substring(0, UefiConstants.SIZE_15); byte[] platformClassBytes = new byte[UefiConstants.SIZE_4]; System.arraycopy(efiSpecId, UefiConstants.OFFSET_16, platformClassBytes, 0, @@ -167,12 +167,12 @@ public class EvEfiSpecIdEvent { */ public String toString() { String specInfo = ""; - if (signature == "Spec ID Event#") { + if (signature.equals("Spec ID Event#")) { specInfo += "Platform Profile Specification version = " + vMaj + "." + vMin + " using errata version" + errata; } else { specInfo = "EV_NO_ACTION event named " + signature - + " ecncountered but support for processing it has not been added to this application"; + + " encountered but support for processing it has not been added to this application"; } return specInfo; } diff --git a/HIRS_Utils/src/main/java/hirs/tpm/eventlog/events/EvSCrtmVersion.java b/HIRS_Utils/src/main/java/hirs/tpm/eventlog/events/EvSCrtmVersion.java index f0364aeb..8d3ee569 100644 --- a/HIRS_Utils/src/main/java/hirs/tpm/eventlog/events/EvSCrtmVersion.java +++ b/HIRS_Utils/src/main/java/hirs/tpm/eventlog/events/EvSCrtmVersion.java @@ -1,6 +1,7 @@ package hirs.tpm.eventlog.events; import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; import hirs.tpm.eventlog.uefi.UefiConstants; import hirs.tpm.eventlog.uefi.UefiGuid; @@ -25,10 +26,9 @@ public class EvSCrtmVersion { /** * Checks if event data is null and if not it converts to a String. * @param data byte array holding the vent content. - * @throws UnsupportedEncodingException if parsing issues exist. * @return String representation of the version. */ - public String sCrtmVersion(final byte[] data) throws UnsupportedEncodingException { + public String sCrtmVersion(final byte[] data) { UefiGuid guid = null; if (data == null) { description = "invalid content event data"; @@ -42,7 +42,7 @@ public class EvSCrtmVersion { } else if (data.length < UefiConstants.SIZE_4) { description = HexUtils.byteArrayToHexString(data); } else if (EvPostCode.isAscii(data)) { - description = new String(data, "UTF-8"); + description = new String(data, StandardCharsets.UTF_8); } else { description = "Unknown Version format"; } diff --git a/HIRS_Utils/src/main/java/hirs/tpm/eventlog/uefi/UefiDevicePath.java b/HIRS_Utils/src/main/java/hirs/tpm/eventlog/uefi/UefiDevicePath.java index cc0db02a..8fa223c1 100644 --- a/HIRS_Utils/src/main/java/hirs/tpm/eventlog/uefi/UefiDevicePath.java +++ b/HIRS_Utils/src/main/java/hirs/tpm/eventlog/uefi/UefiDevicePath.java @@ -1,6 +1,7 @@ package hirs.tpm.eventlog.uefi; import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; import hirs.utils.HexUtils; @@ -276,10 +277,8 @@ private String hardDriveSubType(final byte[] path, final int offset) { * @param path * @param offset * @return file path info. - * @throws UnsupportedEncodingException */ -private String filePathSubType(final byte[] path, final int offset) - throws UnsupportedEncodingException { +private String filePathSubType(final byte[] path, final int offset) { subType = "File Path = "; byte[] lengthBytes = new byte[UefiConstants.SIZE_2]; System.arraycopy(path, 2 + offset, lengthBytes, 0, UefiConstants.SIZE_2); @@ -287,7 +286,7 @@ private String filePathSubType(final byte[] path, final int offset) byte[] filePath = new byte[subTypeLength]; System.arraycopy(path, UefiConstants.OFFSET_4 + offset, filePath, 0, subTypeLength); byte[] fileName = convertChar16tobyteArray(filePath); - subType += new String(fileName, "UTF-8"); + subType += new String(fileName, StandardCharsets.UTF_8); return subType; } diff --git a/HIRS_Utils/src/main/java/hirs/tpm/eventlog/uefi/UefiPartition.java b/HIRS_Utils/src/main/java/hirs/tpm/eventlog/uefi/UefiPartition.java index 24af2bec..d0ade073 100644 --- a/HIRS_Utils/src/main/java/hirs/tpm/eventlog/uefi/UefiPartition.java +++ b/HIRS_Utils/src/main/java/hirs/tpm/eventlog/uefi/UefiPartition.java @@ -1,6 +1,6 @@ package hirs.tpm.eventlog.uefi; -import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; import hirs.utils.HexUtils; /** @@ -39,9 +39,8 @@ public class UefiPartition { /** * Processes a UEFI defined partition entry. * @param table byte array holding the partition table. - * @throws UnsupportedEncodingException if parsing of the data fails. */ - public UefiPartition(final byte[] table) throws UnsupportedEncodingException { + public UefiPartition(final byte[] table) { byte[] partitionGuidBytes = new byte[UefiConstants.SIZE_16]; System.arraycopy(table, 0, partitionGuidBytes, 0, UefiConstants.SIZE_16); partitionTypeGUID = new UefiGuid(partitionGuidBytes); @@ -56,7 +55,7 @@ public class UefiPartition { System.arraycopy(table, UefiConstants.PART_NAME_LENGTH, partitionNameBytes, 0, UefiConstants.UEFI_PT_LENGTH); byte[] pName = convertChar16tobyteArray(partitionNameBytes); - partitionName = new String(pName, "UTF-8").trim(); + partitionName = new String(pName, StandardCharsets.UTF_8).trim(); } /** diff --git a/HIRS_Utils/src/main/java/hirs/tpm/eventlog/uefi/UefiVariable.java b/HIRS_Utils/src/main/java/hirs/tpm/eventlog/uefi/UefiVariable.java index 4763328f..096e6655 100644 --- a/HIRS_Utils/src/main/java/hirs/tpm/eventlog/uefi/UefiVariable.java +++ b/HIRS_Utils/src/main/java/hirs/tpm/eventlog/uefi/UefiVariable.java @@ -3,6 +3,7 @@ package hirs.tpm.eventlog.uefi; import java.io.ByteArrayInputStream; import java.io.IOException; import java.math.BigInteger; +import java.nio.charset.StandardCharsets; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.util.ArrayList; @@ -24,7 +25,7 @@ public class UefiVariable { /** UEFI defined variable identifier GUID. */ private UefiGuid uefiGuid = null; /** List of Signature lists. */ - private ArrayList certSuperList = new ArrayList(); + private ArrayList certSuperList = new ArrayList<>(); /** Name of the UEFI variable. */ private String varName = ""; /** UEFI defined Boot Variable. */ @@ -70,15 +71,15 @@ public UefiVariable(final byte[] variableData) uefiVaribelData = new byte[variableLength]; System.arraycopy(variableData, UefiConstants.OFFSET_32 + nlength * UefiConstants.SIZE_2, uefiVaribelData, 0, variableLength); - varName = new String(name, "UTF-8"); + varName = new String(name, StandardCharsets.UTF_8); String tmpName = varName; if (varName.contains("Boot00")) { tmpName = "Boot00"; } switch (tmpName) { - case "PK": processSigList(uefiVaribelData); break; - case "KEK": processSigList(uefiVaribelData); break; - case "db": processSigList(uefiVaribelData); break; + case "PK": + case "KEK": + case "db": case "dbx": processSigList(uefiVaribelData); break; case "Boot00": bootv = new UefiBootVariable(uefiVaribelData); break; case "BootOrder": booto = new UefiBootOrder(uefiVaribelData); break; @@ -147,14 +148,15 @@ public String toString() { tmpName = varName; } switch (tmpName) { - case "Shim": efiVariable.append(printCert(uefiVaribelData, 0)); break; + case "Shim": case "MokList": efiVariable.append(printCert(uefiVaribelData, 0)); break; case "Boot00": efiVariable.append(bootv.toString()); break; case "BootOrder": efiVariable.append(booto.toString()); break; case "SecureBoot": efiVariable.append(sb.toString()); break; default: if (!tmpName.isEmpty()) { - efiVariable.append("Data not provided for UEFI variable named " + tmpName + " "); + efiVariable.append(String.format("Data not provided for UEFI variable named %s ", + tmpName)); } else { efiVariable.append("Data not provided "); } diff --git a/HIRS_Utils/src/main/java/hirs/utils/exec/AsynchronousExecResult.java b/HIRS_Utils/src/main/java/hirs/utils/exec/AsynchronousExecResult.java index 6675d8a6..02f0d891 100644 --- a/HIRS_Utils/src/main/java/hirs/utils/exec/AsynchronousExecResult.java +++ b/HIRS_Utils/src/main/java/hirs/utils/exec/AsynchronousExecResult.java @@ -5,6 +5,7 @@ import org.apache.commons.exec.DefaultExecuteResultHandler; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.nio.charset.StandardCharsets; /** * An implementation of ExecResult that facilitates working with @@ -84,7 +85,7 @@ public class AsynchronousExecResult implements ExecResult { checkFinished(); if (stdOut != null) { - return ((ByteArrayOutputStream) stdOut).toString("UTF-8"); + return ((ByteArrayOutputStream) stdOut).toString(StandardCharsets.UTF_8.toString()); } else { return null; } diff --git a/HIRS_Utils/src/test/java/hirs/data/persist/certificate/CertificateTest.java b/HIRS_Utils/src/test/java/hirs/data/persist/certificate/CertificateTest.java index f0fe3a1e..ee8f0bbd 100644 --- a/HIRS_Utils/src/test/java/hirs/data/persist/certificate/CertificateTest.java +++ b/HIRS_Utils/src/test/java/hirs/data/persist/certificate/CertificateTest.java @@ -481,28 +481,6 @@ public class CertificateTest { ); } - /** - * Tests that Certificate's getOrganization method can properly parse an organization - * from a comma separated RDN. - * @throws IOException unable to parse organization - */ - @Test - public void testGetSingleOrganization() throws IOException { - String parsedOrg = Certificate.getOrganization(RDN_COMMA_SEPARATED); - Assert.assertEquals(RDN_COMMA_SEPARATED_ORGANIZATION, parsedOrg); - } - - /** - * Tests that Certificate's getOrganization method can properly parse an organization - * from a multivalue RDN. - * @throws IOException unable to parse organization - */ - @Test - public void testGetMultiRdnOrganization() throws IOException { - String parsedOrg = Certificate.getOrganization(RDN_MULTIVALUE); - Assert.assertEquals(RDN_MULTIVALUE_ORGANIZATION, parsedOrg); - } - /** * Construct a CertificateAuthorityCredential from the given parameters. * diff --git a/HIRS_Utils/src/test/java/hirs/persist/CertificateSelectorTest.java b/HIRS_Utils/src/test/java/hirs/persist/CertificateSelectorTest.java index cfca83c8..f5a8c496 100644 --- a/HIRS_Utils/src/test/java/hirs/persist/CertificateSelectorTest.java +++ b/HIRS_Utils/src/test/java/hirs/persist/CertificateSelectorTest.java @@ -100,7 +100,7 @@ public class CertificateSelectorTest extends SpringPersistenceTest { */ @Test(expectedExceptions = IllegalArgumentException.class) public void testNullByIssuerOrganization() { - CertificateAuthorityCredential.select(certMan).byIssuerOrganization(null); + CertificateAuthorityCredential.select(certMan).byIssuerSorted(null); } /** @@ -108,6 +108,6 @@ public class CertificateSelectorTest extends SpringPersistenceTest { */ @Test(expectedExceptions = IllegalArgumentException.class) public void testNullBySubjectOrganization() { - CertificateAuthorityCredential.select(certMan).bySubjectOrganization(null); + CertificateAuthorityCredential.select(certMan).bySubjectSorted(null); } } diff --git a/HIRS_Utils/src/test/java/hirs/persist/DBCertificateManagerTest.java b/HIRS_Utils/src/test/java/hirs/persist/DBCertificateManagerTest.java index 60e67612..9695b8fe 100644 --- a/HIRS_Utils/src/test/java/hirs/persist/DBCertificateManagerTest.java +++ b/HIRS_Utils/src/test/java/hirs/persist/DBCertificateManagerTest.java @@ -344,7 +344,7 @@ public class DBCertificateManagerTest extends SpringPersistenceTest { Set retrievedCerts = CertificateAuthorityCredential.select(certMan) - .bySubjectOrganization(stmEkCert.getIssuerOrganization()) + .bySubjectSorted(stmEkCert.getIssuerSorted()) .getCertificates(); Assert.assertEquals( @@ -355,7 +355,7 @@ public class DBCertificateManagerTest extends SpringPersistenceTest { Set secondRetrievedCerts = CertificateAuthorityCredential.select(certMan) - .bySubjectOrganization(stmRootCaCert.getIssuerOrganization()) + .bySubjectSorted(stmRootCaCert.getIssuerSorted()) .getCertificates(); Assert.assertEquals( @@ -380,7 +380,7 @@ public class DBCertificateManagerTest extends SpringPersistenceTest { Set retrievedCerts = CertificateAuthorityCredential.select(certMan) - .byIssuerOrganization(stmRootCaCert.getIssuerOrganization()) + .byIssuerSorted(stmRootCaCert.getIssuerSorted()) .getCertificates(); Assert.assertEquals( @@ -706,7 +706,7 @@ public class DBCertificateManagerTest extends SpringPersistenceTest { /** * Tests that a {@link CertificateSelector} can be used to retrieve certificates in various - * forms, including {@link Certificate}, {@link X509Certificate}, and {@link KeyStore}. + * forms, including {@link Certificate}. * * @throws IOException if there is a problem creating the certificate * @throws KeyStoreException if there is a problem constructing the resultant KeyStore From 8fa5dfdd9e593d57c9c1ac58a43ac3de3fcd4a1a Mon Sep 17 00:00:00 2001 From: Cyrus <24922493+cyrus-dev@users.noreply.github.com> Date: Mon, 14 Dec 2020 10:57:35 -0500 Subject: [PATCH 03/18] Removed unused imports --- .../main/java/hirs/data/persist/certificate/Certificate.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/HIRS_Utils/src/main/java/hirs/data/persist/certificate/Certificate.java b/HIRS_Utils/src/main/java/hirs/data/persist/certificate/Certificate.java index 79146587..feafa223 100644 --- a/HIRS_Utils/src/main/java/hirs/data/persist/certificate/Certificate.java +++ b/HIRS_Utils/src/main/java/hirs/data/persist/certificate/Certificate.java @@ -12,9 +12,6 @@ import org.bouncycastle.asn1.ASN1Integer; import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.x500.X500Name; -import org.bouncycastle.asn1.x500.style.RFC4519Style; -import org.bouncycastle.asn1.x500.AttributeTypeAndValue; -import org.bouncycastle.asn1.x500.RDN; import org.bouncycastle.asn1.x509.AttributeCertificate; import org.bouncycastle.asn1.x509.AttributeCertificateInfo; import org.bouncycastle.asn1.x509.AttCertIssuer; From a7eae2fd770e976ef212228eaf296276d7bcc63e Mon Sep 17 00:00:00 2001 From: Cyrus <24922493+cyrus-dev@users.noreply.github.com> Date: Thu, 17 Dec 2020 13:09:03 -0500 Subject: [PATCH 04/18] Test out an potential exception --- .../AbstractAttestationCertificateAuthority.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java index ccb38c09..874157a7 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java @@ -1261,8 +1261,14 @@ public abstract class AbstractAttestationCertificateAuthority IssuedCertificateAttributeHelper.buildSubjectAlternativeNameFromCerts( endorsementCredential, platformCredentials, deviceName); - Extension authKeyIdentifier = IssuedCertificateAttributeHelper - .buildAuthorityKeyIdentifier(endorsementCredential); + Extension authKeyIdentifier = null; + + try { + authKeyIdentifier = IssuedCertificateAttributeHelper + .buildAuthorityKeyIdentifier(endorsementCredential); + } catch (Exception ex) { + LOG.error("Test"); + } builder.addExtension(subjectAlternativeName); if (authKeyIdentifier != null) { From 6dd948c828405f72ae7685485ad64c64162bdc54 Mon Sep 17 00:00:00 2001 From: Cyrus <24922493+cyrus-dev@users.noreply.github.com> Date: Fri, 18 Dec 2020 06:58:18 -0500 Subject: [PATCH 05/18] Added a null check for the endorsement credential for the tpm 1.2 --- .../AbstractAttestationCertificateAuthority.java | 8 ++------ .../attestationca/IssuedCertificateAttributeHelper.java | 3 +++ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java index 874157a7..353d7564 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java @@ -1263,12 +1263,8 @@ public abstract class AbstractAttestationCertificateAuthority Extension authKeyIdentifier = null; - try { - authKeyIdentifier = IssuedCertificateAttributeHelper - .buildAuthorityKeyIdentifier(endorsementCredential); - } catch (Exception ex) { - LOG.error("Test"); - } + authKeyIdentifier = IssuedCertificateAttributeHelper + .buildAuthorityKeyIdentifier(endorsementCredential); builder.addExtension(subjectAlternativeName); if (authKeyIdentifier != null) { diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/IssuedCertificateAttributeHelper.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/IssuedCertificateAttributeHelper.java index 1e1f27ea..8a642133 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/IssuedCertificateAttributeHelper.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/IssuedCertificateAttributeHelper.java @@ -76,6 +76,9 @@ public final class IssuedCertificateAttributeHelper { */ public static Extension buildAuthorityKeyIdentifier( final EndorsementCredential endorsementCredential) throws IOException { + if (endorsementCredential == null || endorsementCredential.getX509Certificate() == null) { + return null; + } byte[] extValue = endorsementCredential.getX509Certificate() .getExtensionValue(Extension.authorityKeyIdentifier.getId()); From 85254d9c4494a83ec92940bf33780f597afb5fe1 Mon Sep 17 00:00:00 2001 From: Cyrus <24922493+cyrus-dev@users.noreply.github.com> Date: Tue, 5 Jan 2021 08:14:18 -0500 Subject: [PATCH 06/18] Removed null assignment that isn't used --- .../AbstractAttestationCertificateAuthority.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java index 353d7564..ccb38c09 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java @@ -1261,9 +1261,7 @@ public abstract class AbstractAttestationCertificateAuthority IssuedCertificateAttributeHelper.buildSubjectAlternativeNameFromCerts( endorsementCredential, platformCredentials, deviceName); - Extension authKeyIdentifier = null; - - authKeyIdentifier = IssuedCertificateAttributeHelper + Extension authKeyIdentifier = IssuedCertificateAttributeHelper .buildAuthorityKeyIdentifier(endorsementCredential); builder.addExtension(subjectAlternativeName); From 08c0daf9bed92787dae047b9262e0477afe82419 Mon Sep 17 00:00:00 2001 From: Cyrus <24922493+cyrus-dev@users.noreply.github.com> Date: Wed, 6 Jan 2021 15:45:50 -0500 Subject: [PATCH 07/18] Initial Commit --- ...eferenceManifestDetailsPageController.java | 67 ++ .../main/webapp/WEB-INF/jsp/rim-details.jsp | 726 +++++++++++------- .../src/main/webapp/common/rim_details.css | 5 + 3 files changed, 505 insertions(+), 293 deletions(-) diff --git a/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/ReferenceManifestDetailsPageController.java b/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/ReferenceManifestDetailsPageController.java index 65298a58..20dc0199 100644 --- a/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/ReferenceManifestDetailsPageController.java +++ b/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/ReferenceManifestDetailsPageController.java @@ -324,6 +324,20 @@ public class ReferenceManifestDetailsPageController data.put("associatedRim", support.getAssociatedRim()); data.put("rimType", support.getRimType()); data.put("tagId", support.getTagId()); + boolean crtm = false; + boolean bootManager = false; + boolean osLoader = false; + boolean osKernel = false; + boolean acpiTables = false; + boolean smbiosTables = false; + boolean gptTable = false; + boolean bootOrder = false; + boolean defaultBootDevice = false; + boolean secureBoot = false; + boolean pk = false; + boolean kek = false; + boolean sigDb = false; + boolean forbiddenDbx = false; TCGEventLog logProcessor = new TCGEventLog(support.getRimBytes()); LinkedList tpmPcrEvents = new LinkedList<>(); @@ -343,6 +357,59 @@ public class ReferenceManifestDetailsPageController data.put("events", logProcessor.getEventList()); } + String contentStr; + for (TpmPcrEvent tpe : logProcessor.getEventList()) { + contentStr = tpe.getEventContentStr(); + // check for specific events + if (contentStr.contains("CRTM")) { + crtm = true; + } else if (contentStr.contains("shimx64.efi") + && contentStr.contains("bootmgfw.efi")) { + bootManager = true; + } else if (contentStr.contains("grubx64.efi") + && contentStr.contains("winload.efi")) { + osLoader = true; + } else if (contentStr.contains("vmlinuz") + && contentStr.contains("ntoskrnl.exe")) { + osKernel = true; + } else if (contentStr.contains("ACPI")) { + acpiTables = true; + } else if (contentStr.contains("SMBIOS")) { + smbiosTables = true; + } else if (contentStr.contains("GPT")) { + gptTable = true; + } else if (contentStr.contains("BootOrder")) { + bootOrder = true; + } else if (contentStr.contains("Boot0000")) { + defaultBootDevice = true; + } else if (contentStr.contains("PK")) { + pk = true; + } else if (contentStr.contains("KEK")) { + kek = true; + } else if (contentStr.contains("DB")) { + sigDb = true; + } else if (contentStr.contains("DBX")) { + forbiddenDbx = true; + } else if (contentStr.contains("Secure Boot is Enabled")) { + secureBoot = true; + } + } + + data.put("crtm", crtm); + data.put("bootManager", bootManager); + data.put("osLoader", osLoader); + data.put("osKernel", osKernel); + data.put("acpiTables", acpiTables); + data.put("smbiosTables", smbiosTables); + data.put("gptTable", gptTable); + data.put("bootOrder", bootOrder); + data.put("defaultBootDevice", defaultBootDevice); + data.put("secureBoot", secureBoot); + data.put("pk", pk); + data.put("kek", kek); + data.put("sigDb", sigDb); + data.put("forbiddenDbx", forbiddenDbx); + return data; } diff --git a/HIRS_AttestationCAPortal/src/main/webapp/WEB-INF/jsp/rim-details.jsp b/HIRS_AttestationCAPortal/src/main/webapp/WEB-INF/jsp/rim-details.jsp index 558dcb44..6a8492c5 100644 --- a/HIRS_AttestationCAPortal/src/main/webapp/WEB-INF/jsp/rim-details.jsp +++ b/HIRS_AttestationCAPortal/src/main/webapp/WEB-INF/jsp/rim-details.jsp @@ -17,13 +17,13 @@ - - - - - - -
+ + + + + + +
@@ -41,297 +41,431 @@
-
-
- - - - - - - - - - - - - - - - - +
+ +
+ +
+
+ +
+
+
Event #PCR IndexEvent TypeDigestEvent Content
+ + + + + + + + + + + + + + + + - + - - - - - - - - - - -
Event #PCR IndexEvent TypeDigestEvent Content
${count}PCR${event.getPcrIndex()}${event.getEventTypeStr()}${event.getEventDigestStr()}
${event.getEventContentStr()}
-
-
${initialData.events.size()} entries
- - -
-
-
Base/Support
-
- - - - - - -
+ ${count} + PCR${event.getPcrIndex()} + ${event.getEventTypeStr()} + ${event.getEventDigestStr()} +
${event.getEventContentStr()}
+ + + + + + +
+
${initialData.events.size()} entries
+ + +
+
+
Base/Support
+
+ + + + + +
-
-
-
-
Support
- - -
-
-
Event#:
-
${sEvent.getEventNumber()}
-
-
-
PCR Index:
-
${sEvent.getPcrIndex()}
-
-
-
Digest:
-
${sEvent.getEventDigestStr()}
-
-
-
Content:
-
${sEvent.getEventContentStr()}
-
+
+
+
+
+
Support
+ + +
+
+
Event#:
+
${sEvent.getEventNumber()}
+
+
+
PCR Index:
+
${sEvent.getPcrIndex()}
- - -
-
-
Client Log
- - -
-
-
Event#:
-
${lEvent.getEventNumber()}
-
-
-
PCR Index:
-
${lEvent.getPcrIndex()}
-
-
-
Digest:
-
${lEvent.getEventDigestStr()}
-
-
-
Content:
-
${lEvent.getEventContentStr()}
-
+
+
Digest:
+
${sEvent.getEventDigestStr()}
- - +
+
Content:
+
${sEvent.getEventContentStr()}
+
+
+
+
+
+
+
Client Log
+ + +
+
+
Event#:
+
${lEvent.getEventNumber()}
+
+
+
PCR Index:
+
${lEvent.getPcrIndex()}
+
+
+
Digest:
+
${lEvent.getEventDigestStr()}
+
+
+
Content:
+
${lEvent.getEventContentStr()}
+
+
+
+
+
+
+
+ + +
+
Software Identity
+
+
SWID Name: ${initialData.swidName}
+
SWID Version: ${initialData.swidVersion}
+
SWID Tag ID: ${initialData.swidTagId}
+
SWID Tag Version: ${initialData.swidTagVersion}
+ +
SWID Corpus: 
-
+ + +
SWID Patch:  +
+
+ +
SWID Supplemental:  +
+
- - -
-
Software Identity
-
-
SWID Name: ${initialData.swidName}
-
SWID Version: ${initialData.swidVersion}
-
SWID Tag ID: ${initialData.swidTagId}
-
SWID Tag Version: ${initialData.swidTagVersion}
- -
SWID Corpus:  -
-
- -
SWID Patch:  -
-
- -
SWID Supplemental:  -
-
-
+
+
+
Entity
+
+
Entity Name: ${initialData.entityName}
+ +
Entity Reg ID: ${initialData.entityRegId}
+
+
Entity Role: ${initialData.entityRole}
+
Entity Thumbprint: ${initialData.entityThumbprint}
-
-
Entity
-
-
Entity Name: ${initialData.entityName}
- -
Entity Reg ID: ${initialData.entityRegId}
-
-
Entity Role: ${initialData.entityRole}
-
Entity Thumbprint: ${initialData.entityThumbprint}
-
+
+
+
Link
+ -
-
Link
- -
-
-
Meta
- +
+
Meta
+ + +
Payload Type: ${initialData.payloadType}
+
+
Binding Spec: ${initialData.bindingSpec}
+
Binding Spec Version: ${initialData.bindingSpecVersion}
+ +
PC URI Global: ${initialData.pcUriGlobal}
+
+ +
PC URI Local: ${initialData.pcUriLocal}
+
+
Rim Link Hash: ${initialData.rimLinkHash}
-
-
Payload/Support RIM(s)
-
-
- -
-
- -
- -
- -
-
-
- - - - ${resource.getName()} - - - - - - - - - - - ${resource.getName()} - - - -
- - -
- File Size: - ${resource.getSize()}
- Hash: - ${resource.getHashValue()}
- - RIM Format: - ${resource.getRimFormat()}
-
- - RIM Type: - ${resource.getRimType()}
-
- - URI Global: - ${resource.getRimUriGlobal()}
-
- -
- -
-
- -
-
- ${pcrValue.key} - ${pcrValue.value} -
+
+
+
Payload/Support RIM(s)
+
+
+ +
+
+ +
+ +
+ +
+
+
+ + + + ${resource.getName()} + + + + + + + + + + + ${resource.getName()} + + + +
+ + +
+ File Size: + ${resource.getSize()}
+ Hash: + ${resource.getHashValue()}
+ + RIM Format: + ${resource.getRimFormat()}
+
+ + RIM Type: + ${resource.getRimType()}
+
+ + URI Global: + ${resource.getRimUriGlobal()}
+
+ +
+ +
+
+ +
+
+ ${pcrValue.key} + ${pcrValue.value}
- -
+
+
-
-
-
- -
Support RIM file named ${resource.getName()} was not imported via the Reference Integrity Manifest page.
-
-
-
-
-
-
-
-
+
+ +
+ + +
Support RIM file named ${resource.getName()} was not imported via the Reference Integrity Manifest page.
+
+ +
+
+ +
+ +
-
-
-
Signature
-
-
Validity:  +
+
+
Signature
+
+
Validity:  @@ -340,35 +474,41 @@ - -
-
- + +
+ -
- + +
+
+
Subject Key Identifier: ${initialData.skID}
-
-
+
- - -
+
+ +
+