mirror of
https://github.com/nsacyber/HIRS.git
synced 2024-12-19 04:58:00 +00:00
Merge branch 'master' into Unmatched-component-refactor
This commit is contained in:
commit
677716fa08
@ -67,11 +67,11 @@ import javax.crypto.spec.OAEPParameterSpec;
|
||||
import javax.crypto.spec.PSource;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.math.BigInteger;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.KeyFactory;
|
||||
@ -407,11 +407,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);
|
||||
}
|
||||
if (validationResult == AppraisalStatus.Status.PASS) {
|
||||
RSAPublicKey akPub = parsePublicKey(claim.getAkPublicArea().toByteArray());
|
||||
byte[] nonce = generateRandomBytes(NONCE_LENGTH);
|
||||
@ -551,19 +548,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(),
|
||||
@ -855,18 +848,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();
|
||||
}
|
||||
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,
|
||||
@ -1268,7 +1257,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;
|
||||
@ -784,27 +785,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);
|
||||
|
@ -322,6 +322,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<>();
|
||||
@ -341,6 +355,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;
|
||||
}
|
||||
|
||||
|
@ -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,11 +137,23 @@ 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()) {
|
||||
if (certificate.getAuthKeyId() != null
|
||||
&& !certificate.getAuthKeyId().isEmpty()) {
|
||||
byte[] bytes = Hex.decode(certificate.getAuthKeyId());
|
||||
skiCA = CertificateAuthorityCredential
|
||||
.select(certificateManager)
|
||||
.bySubjectKeyIdentifier(bytes).getCertificate();
|
||||
} else {
|
||||
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())
|
||||
@ -146,9 +161,12 @@ public final class CertificateStringMapBuilder {
|
||||
} else {
|
||||
//Get certificates by subject organization
|
||||
issuerCertificates = CertificateAuthorityCredential.select(certificateManager)
|
||||
.bySubjectOrganization(certificate.getIssuerOrganization())
|
||||
.bySubjectSorted(certificate.getIssuerSorted())
|
||||
.getCertificates();
|
||||
}
|
||||
} else {
|
||||
issuerCertificates.add(skiCA);
|
||||
}
|
||||
|
||||
for (Certificate issuerCert : issuerCertificates) {
|
||||
try {
|
||||
|
@ -41,8 +41,148 @@
|
||||
</c:choose>
|
||||
</div>
|
||||
</div>
|
||||
<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()" placeholder="Search for text..." /><br />
|
||||
<input type="text" id="eventInput" onkeyup="eventSearch(null)" placeholder="Search for text..." /><br />
|
||||
<table id="eventLog">
|
||||
<thead>
|
||||
<tr class="header">
|
||||
@ -361,14 +501,20 @@
|
||||
</c:otherwise>
|
||||
</c:choose>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function eventSearch() {
|
||||
function eventSearch(txtInput) {
|
||||
// Declare variables
|
||||
var input, filter, table, tr, td, i, txtValue, txtFound;
|
||||
|
||||
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,14 +754,10 @@ 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;
|
||||
// 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:
|
||||
@ -805,22 +770,24 @@ public abstract class Certificate extends ArchivableEntity {
|
||||
LOGGER.error(e);
|
||||
}
|
||||
break;
|
||||
|
||||
case ATTRIBUTE_CERTIFICATE:
|
||||
AttributeCertificate attCert = getAttributeCertificate();
|
||||
String algorith = "SHA256withRSA";
|
||||
String algorithm = "SHA256withRSA";
|
||||
try {
|
||||
Signature sig = Signature.getInstance(algorith);
|
||||
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) {
|
||||
} 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) {
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -100,7 +100,7 @@ public class CertificateSelectorTest extends SpringPersistenceTest {
|
||||
*/
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testNullByIssuerOrganization() {
|
||||
CertificateAuthorityCredential.select(certMan).byIssuerOrganization(null);
|
||||
CertificateAuthorityCredential.select(certMan).byIssuerSorted(null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -108,6 +108,6 @@ public class CertificateSelectorTest extends SpringPersistenceTest {
|
||||
*/
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testNullBySubjectOrganization() {
|
||||
CertificateAuthorityCredential.select(certMan).bySubjectOrganization(null);
|
||||
CertificateAuthorityCredential.select(certMan).bySubjectSorted(null);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -10,11 +10,11 @@ The ACA provides a “provisioner” application to be installed on all devices
|
||||
The ACA is a web based server which processes Attestation Identity Requests.
|
||||
![TPM Provisioning](images/TPM_Provisioning.jpg)
|
||||
|
||||
Version 1.1 added support for the [Platform Certificate v1.1 Specification](https://trustedcomputinggroup.org/wp-content/uploads/IWG_Platform_Certificate_Profile_v1p1_r15_pubrev.pdf). This allows entities that are part of the supply chain (System integrators and Value Added Resellers) the ability to create Delta Platform Certificate to compliment the Base Platform Certificate created by the Platform Manufacturer. See the [Article on Base and Delta Platform Certificates](https://github.com/nsacyber/HIRS/wiki/Base-and-Delta-Platform-Certificates) for details.
|
||||
Version 1.1 added support for the [Platform Certificate v1.1 Specification](https://trustedcomputinggroup.org/resource/tcg-platform-certificate-profile/). This allows entities that are part of the supply chain (System integrators and Value Added Resellers) the ability to create Delta Platform Certificate to compliment the Base Platform Certificate created by the Platform Manufacturer. See the [Article on Base and Delta Platform Certificates](https://github.com/nsacyber/HIRS/wiki/Base-and-Delta-Platform-Certificates) for details.
|
||||
|
||||
Version 2.0 will add support for the [PC Client Reference Integrity Manifest (RIM) Specification](https://trustedcomputinggroup.org/wp-content/uploads/TCG_PC_Client_RIM_r0p15_15june2020.pdf) to provide firmware validation capability to the HIRS ACA. This requires that the manufacturer of a device provide a digitally signed RIM "Bundle" for each device. The HIRS ACA has a new page for uploading and viewing RIM Bundles and a policy setting for requiring Firmware validation.
|
||||
Version 2.0 added support for the [PC Client Reference Integrity Manifest (RIM) Specification](https://trustedcomputinggroup.org/resource/tcg-pc-client-reference-integrity-manifest-specification/) to provide firmware validation capability to the HIRS ACA. This requires that the manufacturer of a device provide a digitally signed RIM "Bundle" for each device. The HIRS ACA has a new page for uploading and viewing RIM Bundles and a policy setting for requiring Firmware validation.
|
||||
|
||||
To support the TCG RIM concept a new tools folder has been added to the HIRS project which contains a tcg_rim_tool command line application. The tcg_rim_tool can be used to create NISTIR 8060 compatible SWID tags that adhere to the TCG PC Client RIM specification. It also supports the ability to digitally sign the Base RIM file as the HIRS ACA will require a valid signature in order to upload any RIM file. See the [tgc_rim_tool READ.md](https://github.com/nsacyber/HIRS/blob/master/tools/tcg_rim_tool/README.md) for more details.
|
||||
To support the TCG RIM concept a new [tools folder](https://github.com/nsacyber/HIRS/tree/master/tools) has been added to the HIRS project which contains a [tcg_rim_tool command line application](https://github.com/nsacyber/HIRS/tree/master/tools/tcg_rim_tool). The tcg_rim_tool can be used to create NISTIR 8060 compatible SWID tags that adhere to the TCG PC Client RIM specification. It also supports the ability to digitally sign the Base RIM file as the HIRS ACA will require a valid signature in order to upload any RIM file. See the [tgc_rim_tool READ.md](https://github.com/nsacyber/HIRS/blob/master/tools/tcg_rim_tool/README.md) for more details.
|
||||
|
||||
## Features
|
||||
|
||||
@ -30,8 +30,7 @@ To support the TCG RIM concept a new tools folder has been added to the HIRS pro
|
||||
* Performs TCG-based Supply Chain Validation of connecting clients
|
||||
* Optionally validates Endorsement and Platform Credentials
|
||||
* Endorsement Credential Certificate Chain Validation
|
||||
* Process EK Credentials per [TCG EK Credential Profile For TPM Family 2.0; Level 0
|
||||
Revision 14](https://www.trustedcomputinggroup.org/wp-content/uploads/Credential_Profile_EK_V2.0_R14_published.pdf)
|
||||
* Process EK Credentials per [TCG EK Credential Profile For TPM Family 2.0](https://trustedcomputinggroup.org/resource/tcg-ek-credential-profile-for-tpm-family-2-0/)
|
||||
* Verifies the endorsement key used by the TPM was placed there by the original equipment manufacturer (OEM)
|
||||
* Platform Credential Certificate Chain Validation
|
||||
* Process Platform Credentials per [TCG Platform Attribute Credential Profile Specification Version 1.1 Revision 15](https://trustedcomputinggroup.org/wp-content/uploads/IWG_Platform_Certificate_Profile_v1p1_r15_pubrev.pdf)
|
||||
|
Loading…
Reference in New Issue
Block a user