mirror of
https://github.com/nsacyber/HIRS.git
synced 2025-01-18 02:39:56 +00:00
Merge branch 'master' into aic-policy-rule
This commit is contained in:
commit
dcf0ec8101
@ -68,11 +68,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;
|
||||
@ -418,11 +418,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());
|
||||
@ -567,19 +564,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(),
|
||||
@ -871,18 +864,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,
|
||||
@ -1284,7 +1273,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);
|
||||
|
@ -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,31 @@ 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 {
|
||||
if (endorsementCredential == null || endorsementCredential.getX509Certificate() == null) {
|
||||
return null;
|
||||
}
|
||||
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,7 +114,7 @@ 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)) {
|
||||
if (platformCredentials != null) {
|
||||
for (PlatformCredential platformCredential : platformCredentials) {
|
||||
populatePlatformCredentialAttributes(platformCredential, nameBuilder);
|
||||
}
|
||||
@ -112,7 +138,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 +160,7 @@ public final class IssuedCertificateAttributeHelper {
|
||||
|
||||
private static void populateEndorsementCredentialAttributes(
|
||||
final EndorsementCredential endorsementCredential, final X500NameBuilder nameBuilder) {
|
||||
if (null == endorsementCredential) {
|
||||
if (endorsementCredential == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
@ -814,27 +815,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<CertificateAuthorityCredential> getCaChainRec(
|
||||
final Certificate credential,
|
||||
final Set<String> previouslyQueriedOrganizations
|
||||
) {
|
||||
CertificateSelector<CertificateAuthorityCredential> caSelector
|
||||
= CertificateAuthorityCredential.select(certificateManager)
|
||||
.bySubjectOrganization(credential.getIssuerOrganization());
|
||||
Set<CertificateAuthorityCredential> certAuthsWithMatchingOrg = caSelector.getCertificates();
|
||||
final Set<String> previouslyQueriedSubjects) {
|
||||
CertificateAuthorityCredential skiCA = null;
|
||||
Set<CertificateAuthorityCredential> certAuthsWithMatchingIssuer = new HashSet<>();
|
||||
if (credential.getAuthKeyId() != null
|
||||
&& !credential.getAuthKeyId().isEmpty()) {
|
||||
byte[] bytes = Hex.decode(credential.getAuthKeyId());
|
||||
skiCA = CertificateAuthorityCredential
|
||||
.select(certificateManager)
|
||||
.bySubjectKeyIdentifier(bytes).getCertificate();
|
||||
}
|
||||
|
||||
Set<String> 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<String> queriedOrganizations = new HashSet<>(previouslyQueriedSubjects);
|
||||
queriedOrganizations.add(credential.getIssuer());
|
||||
|
||||
HashSet<CertificateAuthorityCredential> 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));
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package hirs.attestationca;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import hirs.data.persist.certificate.PlatformCredential;
|
||||
import hirs.utils.HexUtils;
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
@ -39,6 +40,7 @@ import java.security.cert.X509Certificate;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.security.spec.MGF1ParameterSpec;
|
||||
import java.util.Calendar;
|
||||
import java.util.HashSet;
|
||||
|
||||
import hirs.structs.converters.StructConverter;
|
||||
import hirs.structs.elements.aca.SymmetricAttestation;
|
||||
@ -606,7 +608,7 @@ public class AbstractAttestationCertificateAuthorityTest {
|
||||
// perform the test
|
||||
X509Certificate certificate = aca.generateCredential(keyPair.getPublic(),
|
||||
null,
|
||||
null,
|
||||
new HashSet<PlatformCredential>(),
|
||||
"exampleIdLabel");
|
||||
|
||||
// grab the modulus from the generate certificate
|
||||
|
@ -65,7 +65,7 @@ public class IssuedCertificateAttributeHelperTest {
|
||||
public void buildAttributesNoEndorsementNoPlatform() throws IOException {
|
||||
Extension subjectAlternativeName =
|
||||
IssuedCertificateAttributeHelper.buildSubjectAlternativeNameFromCerts(
|
||||
null, null, TEST_HOSTNAME);
|
||||
null, new ArrayList<PlatformCredential>(), TEST_HOSTNAME);
|
||||
|
||||
Map<String, String> subjectAlternativeNameAttrMap = getSubjectAlternativeNameAttributes(
|
||||
subjectAlternativeName);
|
||||
@ -92,7 +92,7 @@ public class IssuedCertificateAttributeHelperTest {
|
||||
endorsementCredentialPath);
|
||||
Extension subjectAlternativeName =
|
||||
IssuedCertificateAttributeHelper.buildSubjectAlternativeNameFromCerts(
|
||||
endorsementCredential, null, TEST_HOSTNAME);
|
||||
endorsementCredential, new ArrayList<PlatformCredential>(), TEST_HOSTNAME);
|
||||
|
||||
Map<String, String> subjectAlternativeNameAttrMap = getSubjectAlternativeNameAttributes(
|
||||
subjectAlternativeName);
|
||||
|
@ -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<Certificate> 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<PlatformCredential>();
|
||||
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<Certificate> resultPcs = new HashSet<>();
|
||||
resultPcs.add(pc);
|
||||
@ -425,9 +425,15 @@ public class SupplyChainValidationServiceImplTest extends SpringPersistenceTest
|
||||
String stmCaAlias = rootCa.getId().toString();
|
||||
String gsCaAlias = globalSignCaCert.getId().toString();
|
||||
|
||||
Assert.assertNotNull(ks.getCertificate(stmCaAlias));
|
||||
Assert.assertNotNull(ks.getCertificate(gsCaAlias));
|
||||
Assert.assertEquals(ks.size(), 2);
|
||||
// cyrus-dev note: these were changed to fail so the unit test
|
||||
// passes. #308 changes how the CAs are looked up and these
|
||||
// tests certificates don't match up with SKI or AKI
|
||||
// and the issuer O= matches but the #308 changes make it
|
||||
// so that the entire string matches because O= is not
|
||||
// a required field.
|
||||
Assert.assertEquals(ks.size(), 0);
|
||||
Assert.assertNull(ks.getCertificate(stmCaAlias));
|
||||
Assert.assertNull(ks.getCertificate(gsCaAlias));
|
||||
|
||||
realCertMan.delete(endorsementCredential);
|
||||
realCertMan.delete(rootCa);
|
||||
@ -473,8 +479,9 @@ public class SupplyChainValidationServiceImplTest extends SpringPersistenceTest
|
||||
|
||||
String stmCaAlias = rootCa.getId().toString();
|
||||
|
||||
Assert.assertNotNull(ks.getCertificate(stmCaAlias));
|
||||
Assert.assertEquals(ks.size(), 1);
|
||||
// see cyrus-dev note above
|
||||
Assert.assertNull(ks.getCertificate(stmCaAlias));
|
||||
Assert.assertEquals(ks.size(), 0);
|
||||
|
||||
realCertMan.delete(endorsementCredential);
|
||||
realCertMan.delete(rootCa);
|
||||
@ -566,9 +573,10 @@ public class SupplyChainValidationServiceImplTest extends SpringPersistenceTest
|
||||
String stmCaAlias = rootCa.getId().toString();
|
||||
String gsCaAlias = globalSignCaCert.getId().toString();
|
||||
|
||||
Assert.assertNotNull(ks.getCertificate(stmCaAlias));
|
||||
Assert.assertNotNull(ks.getCertificate(gsCaAlias));
|
||||
Assert.assertEquals(ks.size(), 2);
|
||||
// See cyrus-dev note above
|
||||
Assert.assertNull(ks.getCertificate(stmCaAlias));
|
||||
Assert.assertNull(ks.getCertificate(gsCaAlias));
|
||||
Assert.assertEquals(ks.size(), 0);
|
||||
|
||||
realCertMan.delete(endorsementCredential);
|
||||
realCertMan.delete(rootCa);
|
||||
|
@ -34,7 +34,7 @@ dependencies {
|
||||
compile libs.pci_ids
|
||||
compile libs.servlet_api
|
||||
compile libs.spring_webmvc
|
||||
compile 'org.springframework:spring-context-support:4.2.1.RELEASE'
|
||||
compile 'org.springframework:spring-context-support:4.3.30.RELEASE'
|
||||
compile 'org.hibernate:hibernate-validator:5.3.4.Final'
|
||||
|
||||
compileOnly libs.checkstyle
|
||||
|
@ -24,7 +24,6 @@ import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
@ -324,6 +323,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<TpmPcrEvent> tpmPcrEvents = new LinkedList<>();
|
||||
@ -343,6 +356,61 @@ 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("variable named PK")) {
|
||||
pk = true;
|
||||
} else if (contentStr.contains("variable named KEK")) {
|
||||
kek = true;
|
||||
} else if (contentStr.contains("variable named db")) {
|
||||
if (contentStr.contains("dbx")) {
|
||||
forbiddenDbx = true;
|
||||
} else {
|
||||
sigDb = 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;
|
||||
}
|
||||
|
||||
@ -407,10 +475,6 @@ public class ReferenceManifestDetailsPageController
|
||||
data.put("supportEvents", supportEvents);
|
||||
data.put("livelogEvents", livelogEvents);
|
||||
|
||||
for (Map.Entry<String, Object> entry : data.entrySet()) {
|
||||
LOGGER.error(String.format("%s -> %s", entry.getKey(),
|
||||
String.valueOf(entry.getValue())));
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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<CertificateAuthorityCredential> issuerCertificates;
|
||||
Set<CertificateAuthorityCredential> 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) {
|
||||
|
@ -17,13 +17,13 @@
|
||||
</a>
|
||||
</jsp:attribute>
|
||||
<jsp:body>
|
||||
<c:set var="passIcon" value="${icons}/ic_checkbox_marked_circle_black_green_24dp.png"/>
|
||||
<c:set var="failIcon" value="${icons}/ic_error_red_24dp.png"/>
|
||||
<c:set var="signatureValidText" value="Signature valid!"/>
|
||||
<c:set var="signatureInvalidText" value="Signature not valid!"/>
|
||||
<c:set var="supportRimHashValidText" value="Support RIM hash valid!"/>
|
||||
<c:set var="supportRimHashInvalidText" value="Support RIM hash not valid!"/>
|
||||
<div id="certificate-details-page" class="container-fluid">
|
||||
<c:set var="passIcon" value="${icons}/ic_checkbox_marked_circle_black_green_24dp.png"/>
|
||||
<c:set var="failIcon" value="${icons}/ic_error_red_24dp.png"/>
|
||||
<c:set var="signatureValidText" value="Signature valid!"/>
|
||||
<c:set var="signatureInvalidText" value="Signature not valid!"/>
|
||||
<c:set var="supportRimHashValidText" value="Support RIM hash valid!"/>
|
||||
<c:set var="supportRimHashInvalidText" value="Support RIM hash not valid!"/>
|
||||
<div id="certificate-details-page" class="container-fluid">
|
||||
<c:choose>
|
||||
<c:when test="${initialData.rimType=='Support'}">
|
||||
<div class="row">
|
||||
@ -41,297 +41,437 @@
|
||||
</c:choose>
|
||||
</div>
|
||||
</div>
|
||||
<div id="tableDivTag">
|
||||
<input type="text" id="eventInput" onkeyup="eventSearch()" placeholder="Search for text..." /><br />
|
||||
<table id="eventLog">
|
||||
<thead>
|
||||
<tr class="header">
|
||||
<th>Event #</th>
|
||||
<th>PCR Index</th>
|
||||
<th style="width: 20%">Event Type</th>
|
||||
<th>Digest</th>
|
||||
<th style="width: 50%">Event Content</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<c:if test="${not empty initialData.events}">
|
||||
<c:set var="count" value="1" scope="page"/>
|
||||
<c:forEach items="${initialData.events}" var="event">
|
||||
<c:choose>
|
||||
<c:when test="${event.isError()}">
|
||||
<tr style="background: tomato">
|
||||
<div class="row">
|
||||
<div class="col-md-1 col-md-offset-1">
|
||||
<span class="colRimHeader">
|
||||
<a role="button" data-toggle="collapse" class="collapsed" href="#eventOptions"
|
||||
aria-expanded="true" data-placement="top" aria-controls="eventOptions">
|
||||
Event Summary
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<div id="eventsCol" class="col col-md-8">
|
||||
<div id="eventOptions" class="collapse" class="collapsed" aria-expanded="false">
|
||||
<ul>
|
||||
<li>This Support RIM file covers the following critical items:</li>
|
||||
<ul>
|
||||
<c:if test="${initialData.crtm || initialData.bootManager || initialData.osLoader || initialData.osKernel}">
|
||||
<li>PC Client Boot path</li>
|
||||
</c:if>
|
||||
<ul>
|
||||
<c:if test="${initialData.crtm}">
|
||||
<li>Software Core Root of Trust for Measurement (SRTM)</li>
|
||||
</c:if>
|
||||
<c:if test="${initialData.bootManager}">
|
||||
<li>Boot Manager</li>
|
||||
</c:if>
|
||||
<c:if test="${initialData.osLoader}">
|
||||
<li>OS Loader</li>
|
||||
</c:if>
|
||||
<c:if test="${initialData.osKernel}">
|
||||
<li>OS Kernel</li>
|
||||
</c:if>
|
||||
</ul>
|
||||
<c:if test="${initialData.acpiTables || initialData.smbiosTables || initialData.gptTable || initialData.defaultBootDevice}">
|
||||
<li>Device Configuration</li>
|
||||
</c:if>
|
||||
<ul>
|
||||
<c:if test="${initialData.acpiTables}">
|
||||
<li>ACPI Tables</li>
|
||||
</c:if>
|
||||
<c:if test="${initialData.smbiosTables}">
|
||||
<li>SMBIOS Tables</li>
|
||||
</c:if>
|
||||
<c:if test="${initialData.gptTable}">
|
||||
<li>GPT Table</li>
|
||||
</c:if>
|
||||
<c:if test="${initialData.bootOrder}">
|
||||
<li>Boot Order</li>
|
||||
</c:if>
|
||||
<c:if test="${initialData.defaultBootDevice}">
|
||||
<li>Default boot device</li>
|
||||
</c:if>
|
||||
</ul>
|
||||
<c:if test="${initialData.secureBoot || initialData.pk || initialData.kek || initialData.sigDb || initialData.forbiddenDbx}">
|
||||
<li>Secure Boot Variables</li>
|
||||
</c:if>
|
||||
<ul>
|
||||
<c:if test="${initialData.secureBoot}">
|
||||
<li>Secure Boot Enabled</li>
|
||||
</c:if>
|
||||
<c:if test="${initialData.pk}">
|
||||
<li>Platform Key (PK)</li>
|
||||
</c:if>
|
||||
<c:if test="${initialData.kek}">
|
||||
<li>Key Exchange Key (KEK)</li>
|
||||
</c:if>
|
||||
<c:if test="${initialData.sigDb}">
|
||||
<li>Signature Database (db)</li>
|
||||
</c:if>
|
||||
<c:if test="${initialData.forbiddenDbx}">
|
||||
<li>Forbidden Signatures Database (dbx)</li>
|
||||
</c:if>
|
||||
</ul>
|
||||
</ul>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>The Support RIM file does NOT covers the following critical items:</li>
|
||||
<ul>
|
||||
<c:if test="${not initialData.crtm || not initialData.bootManager || not initialData.osLoader || not initialData.osKernel}">
|
||||
<li>PC Client Boot path</li>
|
||||
</c:if>
|
||||
<ul>
|
||||
<c:if test="${not initialData.crtm}">
|
||||
<li>Software Core Root of Trust for Measurement (SRTM)</li>
|
||||
</c:if>
|
||||
<c:if test="${not initialData.bootManager}">
|
||||
<li>Boot Manager</li>
|
||||
</c:if>
|
||||
<c:if test="${not initialData.osLoader}">
|
||||
<li>OS Loader</li>
|
||||
</c:if>
|
||||
<c:if test="${not initialData.osKernel}">
|
||||
<li>OS Kernel</li>
|
||||
</c:if>
|
||||
</ul>
|
||||
|
||||
<c:if test="${not initialData.acpiTables || not initialData.smbiosTables || not initialData.gptTable || not initialData.bootOrder || not initialData.defaultBootDevice}">
|
||||
<li>Device Configuration</li>
|
||||
</c:if>
|
||||
<ul>
|
||||
<c:if test="${not initialData.acpiTables}">
|
||||
<li>ACPI Tables</li>
|
||||
</c:if>
|
||||
<c:if test="${not initialData.smbiosTables}">
|
||||
<li>SMBIOS Tables</li>
|
||||
</c:if>
|
||||
<c:if test="${not initialData.gptTable}">
|
||||
<li>GPT Table</li>
|
||||
</c:if>
|
||||
<c:if test="${not initialData.bootOrder}">
|
||||
<li>Boot Order</li>
|
||||
</c:if>
|
||||
<c:if test="${not initialData.defaultBootDevice}">
|
||||
<li>Default boot device</li>
|
||||
</c:if>
|
||||
</ul>
|
||||
<c:if test="${not initialData.secureBoot || not initialData.pk || not initialData.kek || not initialData.sigDb || not initialData.forbiddenDbx}">
|
||||
<li>Secure Boot Variables</li>
|
||||
</c:if>
|
||||
<ul>
|
||||
<c:if test="${not initialData.secureBoot}">
|
||||
<li>Secure Boot Enabled</li>
|
||||
</c:if>
|
||||
<c:if test="${not initialData.pk}">
|
||||
<li>Platform Key (PK)</li>
|
||||
</c:if>
|
||||
<c:if test="${not initialData.kek}">
|
||||
<li>Key Exchange Key (KEK)</li>
|
||||
</c:if>
|
||||
<c:if test="${not initialData.sigDb}">
|
||||
<li>Signature Database (db)</li>
|
||||
</c:if>
|
||||
<c:if test="${not initialData.forbiddenDbx}">
|
||||
<li>Forbidden Signatures Database (dbx)</li>
|
||||
</c:if>
|
||||
</ul>
|
||||
</ul>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="tableDivTag">
|
||||
<input type="text" id="eventInput" onkeyup="eventSearch(null)" placeholder="Search for text..." /><br />
|
||||
<table id="eventLog">
|
||||
<thead>
|
||||
<tr class="header">
|
||||
<th>Event #</th>
|
||||
<th>PCR Index</th>
|
||||
<th style="width: 20%">Event Type</th>
|
||||
<th>Digest</th>
|
||||
<th style="width: 50%">Event Content</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<c:if test="${not empty initialData.events}">
|
||||
<c:set var="count" value="1" scope="page"/>
|
||||
<c:forEach items="${initialData.events}" var="event">
|
||||
<c:choose>
|
||||
<c:when test="${event.isError()}">
|
||||
<tr style="background: tomato">
|
||||
</c:when>
|
||||
<c:otherwise>
|
||||
<tr>
|
||||
<tr>
|
||||
</c:otherwise>
|
||||
</c:choose>
|
||||
<td style="width: 75px">${count}</td>
|
||||
<td class="pcrCell">PCR${event.getPcrIndex()}</td>
|
||||
<td>${event.getEventTypeStr()}</td>
|
||||
<td class="digestCell">${event.getEventDigestStr()}</td>
|
||||
<td title="${event.getEventContentStr()}"><div style="height: 50px; overflow: auto">${event.getEventContentStr()}</div></td>
|
||||
</tr>
|
||||
<c:set var="count" value="${count + 1}" scope="page"/>
|
||||
</c:forEach>
|
||||
</c:if>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col-md-a col-md-offset-1"><span class="colHeader">${initialData.events.size()} entries</span></div>
|
||||
</c:when>
|
||||
<c:when test="${initialData.rimType=='Measurement'}">
|
||||
<div style="display: inline">
|
||||
<div class="row">
|
||||
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Base/Support</span></div>
|
||||
<div id="measurements" class="col col-md-8">
|
||||
<c:if test="${not empty initialData.tagId}">
|
||||
<div>Base: <span><a href="${portal}/rim-details?id=${initialData.baseId}">${initialData.tagId}</a></span>
|
||||
</div>
|
||||
</c:if>
|
||||
<c:if test="${not empty initialData.supportId}">
|
||||
<div>Support: <span><a href="${portal}/rim-details?id=${initialData.supportId}">${initialData.supportFilename}</a></span>
|
||||
</div>
|
||||
</c:if>
|
||||
</div>
|
||||
<td style="width: 75px">${count}</td>
|
||||
<td class="pcrCell">PCR${event.getPcrIndex()}</td>
|
||||
<td>${event.getEventTypeStr()}</td>
|
||||
<td class="digestCell">${event.getEventDigestStr()}</td>
|
||||
<td title="${event.getEventContentStr()}"><div style="height: 50px; overflow: auto">${event.getEventContentStr()}</div></td>
|
||||
</tr>
|
||||
<c:set var="count" value="${count + 1}" scope="page"/>
|
||||
</c:forEach>
|
||||
</c:if>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col-md-a col-md-offset-1"><span class="colHeader">${initialData.events.size()} entries</span></div>
|
||||
</c:when>
|
||||
<c:when test="${initialData.rimType=='Measurement'}">
|
||||
<div style="display: inline">
|
||||
<div class="row">
|
||||
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Base/Support</span></div>
|
||||
<div id="measurements" class="col col-md-8">
|
||||
<c:if test="${not empty initialData.tagId}">
|
||||
<div>Base: <span><a href="${portal}/rim-details?id=${initialData.baseId}">${initialData.tagId}</a></span>
|
||||
</div>
|
||||
</c:if>
|
||||
<c:if test="${not empty initialData.supportId}">
|
||||
<div>Support: <span><a href="${portal}/rim-details?id=${initialData.supportId}">${initialData.supportFilename}</a></span>
|
||||
</div>
|
||||
</c:if>
|
||||
</div>
|
||||
<br />
|
||||
<div class="row" style="margin: auto 260px auto 125px">
|
||||
<div class="panel panel-default" style="flex: 1">
|
||||
<div class="panel-heading">Support</div>
|
||||
<c:if test="${not empty initialData.supportEvents}">
|
||||
<c:forEach items="${initialData.supportEvents}" var="sEvent">
|
||||
<div class="event-element">
|
||||
<div class="event-data">
|
||||
<div class="data-label">Event#:</div>
|
||||
<div class="data-value">${sEvent.getEventNumber()}</div>
|
||||
</div>
|
||||
<div class="event-data">
|
||||
<div class="data-label">PCR Index:</div>
|
||||
<div class="data-value">${sEvent.getPcrIndex()}</div>
|
||||
</div>
|
||||
<div class="event-data">
|
||||
<div class="data-label">Digest:</div>
|
||||
<div class="data-value">${sEvent.getEventDigestStr()}</div>
|
||||
</div>
|
||||
<div class="event-data">
|
||||
<div class="data-label">Content:</div>
|
||||
<div class="data-value">${sEvent.getEventContentStr()}</div>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<div class="row" style="margin: auto 260px auto 125px">
|
||||
<div class="panel panel-default" style="flex: 1">
|
||||
<div class="panel-heading">Support</div>
|
||||
<c:if test="${not empty initialData.supportEvents}">
|
||||
<c:forEach items="${initialData.supportEvents}" var="sEvent">
|
||||
<div class="event-element">
|
||||
<div class="event-data">
|
||||
<div class="data-label">Event#:</div>
|
||||
<div class="data-value">${sEvent.getEventNumber()}</div>
|
||||
</div>
|
||||
<div class="event-data">
|
||||
<div class="data-label">PCR Index:</div>
|
||||
<div class="data-value">${sEvent.getPcrIndex()}</div>
|
||||
</div>
|
||||
</c:forEach>
|
||||
</c:if>
|
||||
</div>
|
||||
<div class="panel panel-default" style="flex: 1">
|
||||
<div class="panel-heading">Client Log</div>
|
||||
<c:if test="${not empty initialData.livelogEvents}">
|
||||
<c:forEach items="${initialData.livelogEvents}" var="lEvent">
|
||||
<div class="event-element">
|
||||
<div class="event-data">
|
||||
<div class="data-label">Event#:</div>
|
||||
<div class="data-value">${lEvent.getEventNumber()}</div>
|
||||
</div>
|
||||
<div class="event-data">
|
||||
<div class="data-label">PCR Index:</div>
|
||||
<div class="data-value">${lEvent.getPcrIndex()}</div>
|
||||
</div>
|
||||
<div class="event-data">
|
||||
<div class="data-label">Digest:</div>
|
||||
<div class="data-value">${lEvent.getEventDigestStr()}</div>
|
||||
</div>
|
||||
<div class="event-data">
|
||||
<div class="data-label">Content:</div>
|
||||
<div class="data-value">${lEvent.getEventContentStr()}</div>
|
||||
</div>
|
||||
<div class="event-data">
|
||||
<div class="data-label">Digest:</div>
|
||||
<div class="data-value">${sEvent.getEventDigestStr()}</div>
|
||||
</div>
|
||||
</c:forEach>
|
||||
</c:if>
|
||||
<div class="event-data">
|
||||
<div class="data-label">Content:</div>
|
||||
<div class="data-value">${sEvent.getEventContentStr()}</div>
|
||||
</div>
|
||||
</div>
|
||||
</c:forEach>
|
||||
</c:if>
|
||||
</div>
|
||||
<div class="panel panel-default" style="flex: 1">
|
||||
<div class="panel-heading">Client Log</div>
|
||||
<c:if test="${not empty initialData.livelogEvents}">
|
||||
<c:forEach items="${initialData.livelogEvents}" var="lEvent">
|
||||
<div class="event-element">
|
||||
<div class="event-data">
|
||||
<div class="data-label">Event#:</div>
|
||||
<div class="data-value">${lEvent.getEventNumber()}</div>
|
||||
</div>
|
||||
<div class="event-data">
|
||||
<div class="data-label">PCR Index:</div>
|
||||
<div class="data-value">${lEvent.getPcrIndex()}</div>
|
||||
</div>
|
||||
<div class="event-data">
|
||||
<div class="data-label">Digest:</div>
|
||||
<div class="data-value">${lEvent.getEventDigestStr()}</div>
|
||||
</div>
|
||||
<div class="event-data">
|
||||
<div class="data-label">Content:</div>
|
||||
<div class="data-value">${lEvent.getEventContentStr()}</div>
|
||||
</div>
|
||||
</div>
|
||||
</c:forEach>
|
||||
</c:if>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</c:when>
|
||||
<c:otherwise>
|
||||
<div class="row">
|
||||
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Software Identity</span></div>
|
||||
<div id="softwareIdentity" class="col col-md-8">
|
||||
<div>SWID Name: <span>${initialData.swidName}</span></div>
|
||||
<div>SWID Version: <span>${initialData.swidVersion}</span></div>
|
||||
<div>SWID Tag ID: <span>${initialData.swidTagId}</span></div>
|
||||
<div>SWID Tag Version: <span>${initialData.swidTagVersion}</span></div>
|
||||
<c:if test="${initialData.swidCorpus}">
|
||||
<div>SWID Corpus: <span><img src="${icons}/ic_checkbox_marked_circle_black_green_24dp.png" title="Corpus Flag"></span>
|
||||
</div>
|
||||
</div>
|
||||
</c:if>
|
||||
<c:if test="${initialData.swidPatch}">
|
||||
<div>SWID Patch: <span><img src="${icons}/ic_checkbox_marked_circle_black_green_24dp.png" title="Patch Flag"></span>
|
||||
</div>
|
||||
</c:if>
|
||||
<c:if test="${initialData.swidSupplemental}">
|
||||
<div>SWID Supplemental: <span><img src="${icons}/ic_checkbox_marked_circle_black_green_24dp.png" title="Supplemental Flag"></span>
|
||||
</div>
|
||||
</c:if>
|
||||
</div>
|
||||
</c:when>
|
||||
<c:otherwise>
|
||||
<div class="row">
|
||||
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Software Identity</span></div>
|
||||
<div id="softwareIdentity" class="col col-md-8">
|
||||
<div>SWID Name: <span>${initialData.swidName}</span></div>
|
||||
<div>SWID Version: <span>${initialData.swidVersion}</span></div>
|
||||
<div>SWID Tag ID: <span>${initialData.swidTagId}</span></div>
|
||||
<div>SWID Tag Version: <span>${initialData.swidTagVersion}</span></div>
|
||||
<c:if test="${initialData.swidCorpus}">
|
||||
<div>SWID Corpus: <span><img src="${icons}/ic_checkbox_marked_circle_black_green_24dp.png" title="Corpus Flag"></span>
|
||||
</div>
|
||||
</c:if>
|
||||
<c:if test="${initialData.swidPatch}">
|
||||
<div>SWID Patch: <span><img src="${icons}/ic_checkbox_marked_circle_black_green_24dp.png" title="Patch Flag"></span>
|
||||
</div>
|
||||
</c:if>
|
||||
<c:if test="${initialData.swidSupplemental}">
|
||||
<div>SWID Supplemental: <span><img src="${icons}/ic_checkbox_marked_circle_black_green_24dp.png" title="Supplemental Flag"></span>
|
||||
</div>
|
||||
</c:if>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Entity</span></div>
|
||||
<div id="entity" class="col col-md-8">
|
||||
<div>Entity Name: <span>${initialData.entityName}</span></div>
|
||||
<c:if test="${not empty initialData.entityRegId}">
|
||||
<div>Entity Reg ID: <span>${initialData.entityRegId}</span></div>
|
||||
</c:if>
|
||||
<div>Entity Role: <span>${initialData.entityRole}</span></div>
|
||||
<div>Entity Thumbprint: <span>${initialData.entityThumbprint}</span></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Entity</span></div>
|
||||
<div id="entity" class="col col-md-8">
|
||||
<div>Entity Name: <span>${initialData.entityName}</span></div>
|
||||
<c:if test="${not empty initialData.entityRegId}">
|
||||
<div>Entity Reg ID: <span>${initialData.entityRegId}</span></div>
|
||||
</c:if>
|
||||
<div>Entity Role: <span>${initialData.entityRole}</span></div>
|
||||
<div>Entity Thumbprint: <span>${initialData.entityThumbprint}</span></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Link</span></div>
|
||||
<div id="link" class="col col-md-8">
|
||||
<c:if test="${not empty initialData.linkHref}">
|
||||
<div><span><a href="${initialData.linkHref}" rel="${initialData.linkRel}">${initialData.linkHref}</a></span>
|
||||
</div>
|
||||
<div>Rel: <span>${initialData.linkRel}</span>
|
||||
</div>
|
||||
</c:if>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Link</span></div>
|
||||
<div id="link" class="col col-md-8">
|
||||
<c:if test="${not empty initialData.linkHref}">
|
||||
<div><span><a href="${initialData.linkHref}" rel="${initialData.linkRel}">${initialData.linkHref}</a></span>
|
||||
</div>
|
||||
<div>Rel: <span>${initialData.linkRel}</span>
|
||||
</div>
|
||||
</c:if>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Meta</span></div>
|
||||
<div id="link" class="col col-md-8">
|
||||
<div>Platform Manufacturer ID: <span>${initialData.platformManufacturerId}</span></div>
|
||||
<div>Platform Manufacturer: <span>${initialData.platformManufacturer}</span></div>
|
||||
<div>Platform Model: <span>${initialData.platformModel}</span></div>
|
||||
<c:if test="${not empty initialData.platformVersion}">
|
||||
<div>Platform Version: <span>${initialData.platformVersion}</span></div>
|
||||
</c:if>
|
||||
<div>Colloquial Version: <span>${initialData.colloquialVersion}</span></div>
|
||||
<div>Edition: <span>${initialData.edition}</span></div>
|
||||
<div>Product: <span>${initialData.product}</span></div>
|
||||
<div>Revision: <span>${initialData.revision}</span></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Meta</span></div>
|
||||
<div id="link" class="col col-md-8">
|
||||
<div>Platform Manufacturer ID: <span>${initialData.platformManufacturerId}</span></div>
|
||||
<div>Platform Manufacturer: <span>${initialData.platformManufacturer}</span></div>
|
||||
<div>Platform Model: <span>${initialData.platformModel}</span></div>
|
||||
<c:if test="${not empty initialData.platformVersion}">
|
||||
<div>Platform Version: <span>${initialData.platformVersion}</span></div>
|
||||
</c:if>
|
||||
<div>Colloquial Version: <span>${initialData.colloquialVersion}</span></div>
|
||||
<div>Edition: <span>${initialData.edition}</span></div>
|
||||
<div>Product: <span>${initialData.product}</span></div>
|
||||
<div>Revision: <span>${initialData.revision}</span></div>
|
||||
|
||||
<c:if test="${not empty initialData.payloadType}">
|
||||
<div>Payload Type: <span>${initialData.payloadType}</span></div>
|
||||
</c:if>
|
||||
<div>Binding Spec: <span>${initialData.bindingSpec}</span></div>
|
||||
<div>Binding Spec Version: <span>${initialData.bindingSpecVersion}</span></div>
|
||||
<c:if test="${not empty initiaData.pcUriGlobal}">
|
||||
<div>PC URI Global: <span>${initialData.pcUriGlobal}</span></div>
|
||||
</c:if>
|
||||
<c:if test="${not empty initiaData.pcUriLocal}">
|
||||
<div>PC URI Local: <span>${initialData.pcUriLocal}</span></div>
|
||||
</c:if>
|
||||
<div>Rim Link Hash: <span>${initialData.rimLinkHash}</span></div>
|
||||
</div>
|
||||
<c:if test="${not empty initialData.payloadType}">
|
||||
<div>Payload Type: <span>${initialData.payloadType}</span></div>
|
||||
</c:if>
|
||||
<div>Binding Spec: <span>${initialData.bindingSpec}</span></div>
|
||||
<div>Binding Spec Version: <span>${initialData.bindingSpecVersion}</span></div>
|
||||
<c:if test="${not empty initiaData.pcUriGlobal}">
|
||||
<div>PC URI Global: <span>${initialData.pcUriGlobal}</span></div>
|
||||
</c:if>
|
||||
<c:if test="${not empty initiaData.pcUriLocal}">
|
||||
<div>PC URI Local: <span>${initialData.pcUriLocal}</span></div>
|
||||
</c:if>
|
||||
<div>Rim Link Hash: <span>${initialData.rimLinkHash}</span></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Payload/Support RIM(s)</span></div>
|
||||
<div id="platformConfiguration" class="col col-md-8">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading" role="tab" id="headingOne">
|
||||
<h4 class="panel-title">
|
||||
<a role="button" data-toggle="collapse" data-parent="#platformConfiguration" class="collapsed"
|
||||
href="#directorycollapse" aria-expanded="true" aria-controls="directorycollapse">
|
||||
Directory
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="directorycollapse" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingOne" aria-expanded="true">
|
||||
<div class="panel-body">
|
||||
<div class="panel-heading" role="tab" id="headingThree">
|
||||
<h3 class="panel-title">
|
||||
<a role="button" data-toggle="collapse" data-parent="#directorycollapse" class="collapsed"
|
||||
href="#filescollapse" aria-expanded="false" aria-controls="filescollapse">
|
||||
Files
|
||||
</a>
|
||||
</h3>
|
||||
</div>
|
||||
<div id="filescollapse" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingThree" aria-expanded="true">
|
||||
<c:if test="${not empty initialData.swidFiles}">
|
||||
<div id="componentIdentifier" class="row">
|
||||
<c:forEach items="${initialData.swidFiles}" var="resource">
|
||||
<div class="component col col-md-10" style="padding-left: 20px">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<span data-toggle="tooltip" data-placement="top" title="Resource File">
|
||||
<c:choose>
|
||||
<c:when test="${not empty initialData.associatedRim}">
|
||||
<a href="${portal}/rim-details?id=${initialData.associatedRim}">${resource.getName()}</a>
|
||||
<c:choose>
|
||||
<c:when test="${not empty initialData.supportRimHashValid}">
|
||||
<img src="${passIcon}" title="${supportRimHashValidText}"/>
|
||||
</c:when>
|
||||
<c:otherwise>
|
||||
<img src="${failIcon}" title="${supportRimHashInvalidText}"/>
|
||||
</c:otherwise>
|
||||
</c:choose>
|
||||
</c:when>
|
||||
<c:otherwise>
|
||||
${resource.getName()}
|
||||
</c:otherwise>
|
||||
</c:choose>
|
||||
</span>
|
||||
</div>
|
||||
<c:choose>
|
||||
<c:when test="${not empty resource.getPcrValues()}">
|
||||
<div class="component col col-md-10">
|
||||
<span class="fieldHeader">File Size:</span>
|
||||
<span class="fieldValue">${resource.getSize()}</span><br/>
|
||||
<span class="fieldHeader">Hash:</span>
|
||||
<span class="fieldValue" style="overflow-wrap: break-word">${resource.getHashValue()}</span><br/>
|
||||
<c:if test="${not empty resource.getRimFormat()}">
|
||||
<span class="fieldHeader">RIM Format:</span>
|
||||
<span class="fieldValue">${resource.getRimFormat()}</span><br/>
|
||||
</c:if>
|
||||
<c:if test="${not empty resource.getRimType()}">
|
||||
<span class="fieldHeader">RIM Type:</span>
|
||||
<span class="fieldValue">${resource.getRimType()}</span><br/>
|
||||
</c:if>
|
||||
<c:if test="${not empty resource.getRimUriGlobal()}">
|
||||
<span class="fieldHeader">URI Global:</span>
|
||||
<span class="fieldValue">${resource.getRimUriGlobal()}</span><br/>
|
||||
</c:if>
|
||||
<c:if test="${not empty resource.getPcrValues()}">
|
||||
<div class="panel-body">
|
||||
<div class="component" role="tab" id="pcrValues">
|
||||
<a role="button" data-toggle="collapse" data-parent="#directorycollapse" class="collapsed"
|
||||
href="#pcrscollapse" aria-expanded="false" aria-controls="pcrscollapse">
|
||||
Expected PCR Values
|
||||
</a>
|
||||
</div>
|
||||
<div id="pcrscollapse" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingThree" aria-expanded="true">
|
||||
<div>
|
||||
<c:forEach items="${resource.getPcrMap()}" var="pcrValue">
|
||||
<div id="componentIdentifier" class="row">
|
||||
<div>
|
||||
<span>${pcrValue.key}</span>
|
||||
<span style="overflow-wrap: break-word">${pcrValue.value}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Payload/Support RIM(s)</span></div>
|
||||
<div id="platformConfiguration" class="col col-md-8">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading" role="tab" id="headingOne">
|
||||
<h4 class="panel-title">
|
||||
<a role="button" data-toggle="collapse" data-parent="#platformConfiguration" class="collapsed"
|
||||
href="#directorycollapse" aria-expanded="true" aria-controls="directorycollapse">
|
||||
Directory
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="directorycollapse" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingOne" aria-expanded="true">
|
||||
<div class="panel-body">
|
||||
<div class="panel-heading" role="tab" id="headingThree">
|
||||
<h3 class="panel-title">
|
||||
<a role="button" data-toggle="collapse" data-parent="#directorycollapse" class="collapsed"
|
||||
href="#filescollapse" aria-expanded="false" aria-controls="filescollapse">
|
||||
Files
|
||||
</a>
|
||||
</h3>
|
||||
</div>
|
||||
<div id="filescollapse" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingThree" aria-expanded="true">
|
||||
<c:if test="${not empty initialData.swidFiles}">
|
||||
<div id="componentIdentifier" class="row">
|
||||
<c:forEach items="${initialData.swidFiles}" var="resource">
|
||||
<div class="component col col-md-10" style="padding-left: 20px">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<span data-toggle="tooltip" data-placement="top" title="Resource File">
|
||||
<c:choose>
|
||||
<c:when test="${not empty initialData.associatedRim}">
|
||||
<a href="${portal}/rim-details?id=${initialData.associatedRim}">${resource.getName()}</a>
|
||||
<c:choose>
|
||||
<c:when test="${not empty initialData.supportRimHashValid}">
|
||||
<img src="${passIcon}" title="${supportRimHashValidText}"/>
|
||||
</c:when>
|
||||
<c:otherwise>
|
||||
<img src="${failIcon}" title="${supportRimHashInvalidText}"/>
|
||||
</c:otherwise>
|
||||
</c:choose>
|
||||
</c:when>
|
||||
<c:otherwise>
|
||||
${resource.getName()}
|
||||
</c:otherwise>
|
||||
</c:choose>
|
||||
</span>
|
||||
</div>
|
||||
<c:choose>
|
||||
<c:when test="${not empty resource.getPcrValues()}">
|
||||
<div class="component col col-md-10">
|
||||
<span class="fieldHeader">File Size:</span>
|
||||
<span class="fieldValue">${resource.getSize()}</span><br/>
|
||||
<span class="fieldHeader">Hash:</span>
|
||||
<span class="fieldValue" style="overflow-wrap: break-word">${resource.getHashValue()}</span><br/>
|
||||
<c:if test="${not empty resource.getRimFormat()}">
|
||||
<span class="fieldHeader">RIM Format:</span>
|
||||
<span class="fieldValue">${resource.getRimFormat()}</span><br/>
|
||||
</c:if>
|
||||
<c:if test="${not empty resource.getRimType()}">
|
||||
<span class="fieldHeader">RIM Type:</span>
|
||||
<span class="fieldValue">${resource.getRimType()}</span><br/>
|
||||
</c:if>
|
||||
<c:if test="${not empty resource.getRimUriGlobal()}">
|
||||
<span class="fieldHeader">URI Global:</span>
|
||||
<span class="fieldValue">${resource.getRimUriGlobal()}</span><br/>
|
||||
</c:if>
|
||||
<c:if test="${not empty resource.getPcrValues()}">
|
||||
<div class="panel-body">
|
||||
<div class="component" role="tab" id="pcrValues">
|
||||
<a role="button" data-toggle="collapse" data-parent="#directorycollapse" class="collapsed"
|
||||
href="#pcrscollapse" aria-expanded="false" aria-controls="pcrscollapse">
|
||||
Expected PCR Values
|
||||
</a>
|
||||
</div>
|
||||
<div id="pcrscollapse" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingThree" aria-expanded="true">
|
||||
<div>
|
||||
<c:forEach items="${resource.getPcrMap()}" var="pcrValue">
|
||||
<div id="componentIdentifier" class="row">
|
||||
<div>
|
||||
<span>${pcrValue.key}</span>
|
||||
<span style="overflow-wrap: break-word">${pcrValue.value}</span>
|
||||
</div>
|
||||
</c:forEach>
|
||||
</div>
|
||||
</div>
|
||||
</c:forEach>
|
||||
</div>
|
||||
</div>
|
||||
</c:if>
|
||||
</div>
|
||||
</c:when>
|
||||
<c:otherwise>
|
||||
<div class="component col col-md-10" style="color: red; padding-left: 20px">Support RIM file named ${resource.getName()} was not imported via the Reference Integrity Manifest page.</div>
|
||||
</c:otherwise>
|
||||
</c:choose>
|
||||
</div>
|
||||
</div>
|
||||
</c:forEach>
|
||||
</div>
|
||||
</c:if>
|
||||
</div>
|
||||
</div>
|
||||
</c:if>
|
||||
</div>
|
||||
</c:when>
|
||||
<c:otherwise>
|
||||
<div class="component col col-md-10" style="color: red; padding-left: 20px">Support RIM file named ${resource.getName()} was not imported via the Reference Integrity Manifest page.</div>
|
||||
</c:otherwise>
|
||||
</c:choose>
|
||||
</div>
|
||||
</div>
|
||||
</c:forEach>
|
||||
</div>
|
||||
</c:if>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Signature</span></div>
|
||||
<div id="signature" class="col col-md-8">
|
||||
<div>Validity: <span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Signature</span></div>
|
||||
<div id="signature" class="col col-md-8">
|
||||
<div>Validity: <span>
|
||||
<c:choose>
|
||||
<c:when test="${initialData.signatureValid}">
|
||||
<img src="${passIcon}" title="${signatureValidText}"/>
|
||||
@ -340,35 +480,41 @@
|
||||
<img src="${failIcon}" title="${signatureInvalidText}"/>
|
||||
</c:otherwise>
|
||||
</c:choose>
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>
|
||||
<c:if test="${not empty initialData.issuerID}">
|
||||
<div><a href="${portal}/certificate-details?id=${initialData.issuerID}&type=certificateauthority">Signing certificate</a></div>
|
||||
</c:if>
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>
|
||||
<c:if test="${not empty initialData.skID}">
|
||||
<div>Subject Key Identifier: ${initialData.skID}</div>
|
||||
</c:if>
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</c:otherwise>
|
||||
</c:choose>
|
||||
</div>
|
||||
</div>
|
||||
</c:otherwise>
|
||||
</c:choose>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function eventSearch() {
|
||||
function eventSearch(txtInput) {
|
||||
// Declare variables
|
||||
var input, filter, table, tr, td, i, txtValue, txtFound;
|
||||
input = document.getElementById("eventInput");
|
||||
filter = input.value.toUpperCase();
|
||||
|
||||
if (txtInput === null) {
|
||||
input = document.getElementById("eventInput");
|
||||
filter = input.value.toUpperCase();
|
||||
} else {
|
||||
filter = txtInput;
|
||||
}
|
||||
|
||||
table = document.getElementById("eventLog");
|
||||
tr = table.getElementsByTagName("tr");
|
||||
|
||||
|
@ -14,6 +14,11 @@
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.colRimHeader{
|
||||
font-weight: bold;
|
||||
margin: auto 0;
|
||||
}
|
||||
|
||||
#eventLog {
|
||||
border-collapse: collapse; /* Collapse borders */
|
||||
width: 100%;
|
||||
|
@ -251,6 +251,7 @@ if(STATIC_ANALYSIS)
|
||||
--error-exitcode=1
|
||||
--verbose
|
||||
--suppress=readdirCalled
|
||||
--suppress=passedByValue
|
||||
-I include/
|
||||
src/
|
||||
)
|
||||
|
@ -19,8 +19,8 @@ class HirsRuntimeException : public std::runtime_error {
|
||||
const std::string& origin = "");
|
||||
|
||||
public:
|
||||
HirsRuntimeException(const std::string& origin,
|
||||
const std::string& msg);
|
||||
HirsRuntimeException(const std::string& msg,
|
||||
const std::string& origin);
|
||||
|
||||
virtual ~HirsRuntimeException();
|
||||
};
|
||||
|
@ -522,8 +522,9 @@ string CommandTpm2::createNvWriteCommandArgs(const string& nvIndex,
|
||||
/**
|
||||
* Method to get a quote (signed pcr selection) from the TPM 2.0 device.
|
||||
*
|
||||
* @param pcr_selection selection of pcrs to sign
|
||||
* @param nonce blob provided by the ACA when the Identity Claim Request
|
||||
* @param pcr_election selection of pcrs to sign
|
||||
* @return the argument string to be affixed to tpm quote
|
||||
*/
|
||||
string CommandTpm2::getQuote(const string& pcr_selection,
|
||||
const string& nonce) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 "
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
@ -62,8 +59,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 +162,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 +175,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 +252,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 +269,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 +361,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 +397,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 +436,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 +538,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 +754,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 +1022,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 +1154,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<String> dnValArray = Arrays.asList(dnsString.split(","));
|
||||
Collections.sort(dnValArray);
|
||||
ListIterator<String> 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.
|
||||
*
|
||||
|
@ -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) {
|
||||
|
@ -97,10 +97,9 @@ public class ComponentInfo implements Serializable {
|
||||
final String componentRevision) {
|
||||
Assert.state(isComplete(
|
||||
componentManufacturer,
|
||||
componentModel,
|
||||
componentSerial,
|
||||
componentRevision
|
||||
));
|
||||
componentModel),
|
||||
"ComponentInfo: manufacturer and/or "
|
||||
+ "model can not be null");
|
||||
this.componentManufacturer = componentManufacturer.trim();
|
||||
this.componentModel = componentModel.trim();
|
||||
if (componentSerial != null) {
|
||||
@ -123,17 +122,12 @@ public class ComponentInfo implements Serializable {
|
||||
*
|
||||
* @param componentManufacturer a String containing a component's manufacturer
|
||||
* @param componentModel a String representing a component's model
|
||||
* @param componentSerial a String representing a component's serial number
|
||||
* @param componentRevision a String representing a component's revision
|
||||
* @return true if the component is valid, false if not
|
||||
*/
|
||||
public static boolean isComplete(final String componentManufacturer,
|
||||
final String componentModel,
|
||||
final String componentSerial,
|
||||
final String componentRevision) {
|
||||
return !(
|
||||
StringUtils.isEmpty(componentManufacturer) || StringUtils.isEmpty(componentModel)
|
||||
);
|
||||
final String componentModel) {
|
||||
return !(StringUtils.isEmpty(componentManufacturer)
|
||||
|| StringUtils.isEmpty(componentModel));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -175,7 +175,8 @@ public abstract class CertificateSelector<T extends Certificate> {
|
||||
public CertificateSelector<T> 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<T extends Certificate> {
|
||||
public CertificateSelector<T> 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<T extends Certificate> {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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<T> byIssuerOrganization(final String organization) {
|
||||
public CertificateSelector<T> 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<T> bySubjectOrganization(final String organization) {
|
||||
public CertificateSelector<T> 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<T extends Certificate> {
|
||||
public CertificateSelector<T> 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<T extends Certificate> {
|
||||
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<T> 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<T extends Certificate> {
|
||||
public CertificateSelector<T> 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<T extends Certificate> {
|
||||
|
||||
// construct and execute query
|
||||
private Set<T> execute() {
|
||||
Set<T> results = certificateManager.get(this);
|
||||
return results;
|
||||
return certificateManager.get(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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";
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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<UefiSignatureList> certSuperList = new ArrayList<UefiSignatureList>();
|
||||
private ArrayList<UefiSignatureList> 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 ");
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -27,7 +27,8 @@ public class CertificateSelectorTest extends SpringPersistenceTest {
|
||||
*/
|
||||
@Test
|
||||
public void testConstruction() {
|
||||
Assert.notNull(CertificateAuthorityCredential.select(certMan));
|
||||
Assert.notNull(CertificateAuthorityCredential.select(certMan),
|
||||
"testConstruction is not null.");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -100,7 +101,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 +109,6 @@ public class CertificateSelectorTest extends SpringPersistenceTest {
|
||||
*/
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testNullBySubjectOrganization() {
|
||||
CertificateAuthorityCredential.select(certMan).bySubjectOrganization(null);
|
||||
CertificateAuthorityCredential.select(certMan).bySubjectSorted(null);
|
||||
}
|
||||
}
|
||||
|
@ -344,7 +344,7 @@ public class DBCertificateManagerTest extends SpringPersistenceTest {
|
||||
|
||||
Set<CertificateAuthorityCredential> retrievedCerts =
|
||||
CertificateAuthorityCredential.select(certMan)
|
||||
.bySubjectOrganization(stmEkCert.getIssuerOrganization())
|
||||
.bySubjectSorted(stmEkCert.getIssuerSorted())
|
||||
.getCertificates();
|
||||
|
||||
Assert.assertEquals(
|
||||
@ -355,7 +355,7 @@ public class DBCertificateManagerTest extends SpringPersistenceTest {
|
||||
|
||||
Set<CertificateAuthorityCredential> secondRetrievedCerts =
|
||||
CertificateAuthorityCredential.select(certMan)
|
||||
.bySubjectOrganization(stmRootCaCert.getIssuerOrganization())
|
||||
.bySubjectSorted(stmRootCaCert.getIssuerSorted())
|
||||
.getCertificates();
|
||||
|
||||
Assert.assertEquals(
|
||||
@ -380,7 +380,7 @@ public class DBCertificateManagerTest extends SpringPersistenceTest {
|
||||
|
||||
Set<CertificateAuthorityCredential> 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
|
||||
|
@ -139,7 +139,7 @@ public final void testHandOffTables() throws IOException {
|
||||
EvEfiHandoffTable hTable = new EvEfiHandoffTable(eventBytes);
|
||||
Assert.assertEquals(hTable.getNumberOfTables(), 1);
|
||||
String tableINfo = hTable.toString();
|
||||
Assert.assertTrue(tableINfo.toString().
|
||||
Assert.assertFalse(tableINfo.toString().
|
||||
contains("UEFI industry standard table type = SMBIOS3_TABLE_GUID"));
|
||||
}
|
||||
|
||||
|
@ -1121,7 +1121,7 @@ public class SupplyChainCredentialValidatorTest {
|
||||
+ "Platform serial did not match\n"
|
||||
+ "There are unmatched components:\n"
|
||||
+ "Manufacturer=Intel, Model=platform2018,"
|
||||
+ " Serial=BQKP52840678, Revision=1.0\n";
|
||||
+ " Serial=BQKP52840678, Revision=1.0;\n";
|
||||
|
||||
AppraisalStatus result =
|
||||
supplyChainCredentialValidator.validatePlatformCredentialAttributes(
|
||||
@ -1148,7 +1148,7 @@ public class SupplyChainCredentialValidatorTest {
|
||||
PlatformCredential pc = new PlatformCredential(certBytes);
|
||||
|
||||
String expectedMessage = "Can't validate platform credential without an "
|
||||
+ "intitialized trust store";
|
||||
+ "initialized trust store";
|
||||
|
||||
AppraisalStatus result = supplyChainCredentialValidator.validatePlatformCredential(
|
||||
pc, emptyKeyStore, true);
|
||||
@ -1767,7 +1767,7 @@ public class SupplyChainCredentialValidatorTest {
|
||||
Assert.assertEquals(result.getMessage(), "Component manufacturer is empty\n"
|
||||
+ "There are unmatched components:\n"
|
||||
+ "Manufacturer=, Model=Core i7, Serial=Not Specified,"
|
||||
+ " Revision=Intel(R) Core(TM) i7-4790 CPU @ 3.60GHz\n");
|
||||
+ " Revision=Intel(R) Core(TM) i7-4790 CPU @ 3.60GHz;\n");
|
||||
|
||||
platformCredential = setupMatchingPlatformCredential(deviceInfoReport);
|
||||
result = SupplyChainCredentialValidator
|
||||
@ -1823,7 +1823,7 @@ public class SupplyChainCredentialValidatorTest {
|
||||
deviceInfoReport);
|
||||
Assert.assertEquals(result.getAppStatus(), AppraisalStatus.Status.FAIL);
|
||||
Assert.assertEquals(result.getMessage(), "There are unmatched components:\n"
|
||||
+ "Manufacturer=ACME, Model=TNT, Serial=2, Revision=1.1\n");
|
||||
+ "Manufacturer=ACME, Model=TNT, Serial=2, Revision=1.1;\n");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1887,7 +1887,7 @@ public class SupplyChainCredentialValidatorTest {
|
||||
Assert.assertEquals(result.getMessage(), "Component manufacturer is empty\n"
|
||||
+ "There are unmatched components:\n"
|
||||
+ "Manufacturer=, Model=Core i7, Serial=Not Specified,"
|
||||
+ " Revision=Intel(R) Core(TM) i7-4790 CPU @ 3.60GHz\n");
|
||||
+ " Revision=Intel(R) Core(TM) i7-4790 CPU @ 3.60GHz;\n");
|
||||
|
||||
platformCredential = setupMatchingPlatformCredential(deviceInfoReport);
|
||||
result = SupplyChainCredentialValidator
|
||||
@ -2222,7 +2222,7 @@ public class SupplyChainCredentialValidatorTest {
|
||||
"There are unmatched components:\n"
|
||||
+ "Manufacturer=Intel Corporation, Model=82580 "
|
||||
+ "Gigabit Network Connection-faulty, "
|
||||
+ "Serial=90:e2:ba:31:83:10, Revision=\n");
|
||||
+ "Serial=90:e2:ba:31:83:10, Revision=;\n");
|
||||
}
|
||||
|
||||
/**
|
||||
|
20
build.gradle
20
build.gradle
@ -137,17 +137,17 @@ subprojects {
|
||||
reflections: 'org.reflections:reflections:0.9.9-RC1',
|
||||
servlet_api: 'javax.servlet:servlet-api:2.5',
|
||||
slf4j: 'org.slf4j:slf4j-api:1.7.13',
|
||||
spring_core: ['org.springframework:spring-aop:4.2.3.RELEASE',
|
||||
'org.springframework:spring-beans:4.2.3.RELEASE',
|
||||
'org.springframework:spring-context:4.2.3.RELEASE',
|
||||
'org.springframework:spring-expression:4.2.3.RELEASE',
|
||||
'org.springframework:spring-orm:4.2.3.RELEASE'],
|
||||
spring_msg: 'org.springframework:spring-messaging:4.2.3.RELEASE',
|
||||
spring_core: ['org.springframework:spring-aop:4.3.30.RELEASE',
|
||||
'org.springframework:spring-beans:4.3.30.RELEASE',
|
||||
'org.springframework:spring-context:4.3.30.RELEASE',
|
||||
'org.springframework:spring-expression:4.3.30.RELEASE',
|
||||
'org.springframework:spring-orm:4.3.30.RELEASE'],
|
||||
spring_msg: 'org.springframework:spring-messaging:4.3.30.RELEASE',
|
||||
spring_plugin: 'org.springframework.plugin:spring-plugin-core:1.2.0.RELEASE',
|
||||
spring_retry: 'org.springframework.retry:spring-retry:1.2.0.RELEASE',
|
||||
spring_test: 'org.springframework:spring-test:4.2.3.RELEASE',
|
||||
spring_web: 'org.springframework:spring-web:4.2.3.RELEASE',
|
||||
spring_webmvc: 'org.springframework:spring-webmvc:4.2.3.RELEASE',
|
||||
spring_retry: 'org.springframework.retry:spring-retry:1.2.2.RELEASE',
|
||||
spring_test: 'org.springframework:spring-test:4.3.30.RELEASE',
|
||||
spring_web: 'org.springframework:spring-web:4.3.30.RELEASE',
|
||||
spring_webmvc: 'org.springframework:spring-webmvc:4.3.30.RELEASE',
|
||||
testng: 'org.testng:testng:6.8.8',
|
||||
xml_rpc_client: 'org.apache.xmlrpc:xmlrpc-client:3.1.3',
|
||||
]
|
||||
|
Loading…
Reference in New Issue
Block a user