Merge branch 'main' into v3_issue-596

This commit is contained in:
chubtub 2023-10-17 16:50:40 -04:00
commit 98a56a3f41
117 changed files with 5184 additions and 2463 deletions

View File

@ -0,0 +1,19 @@
FROM ubuntu:22.04
RUN apt-get update -y && apt-get upgrade -y && apt-get clean -y
# Install packages for building HIRS ACA
RUN apt-get -y install openjdk-17-jdk mariadb-server
RUN apt-get -y install git curl nano cron
# Ports needed for system-level tests
EXPOSE 8080
EXPOSE 8443
# Checkout HIRS main branch and run gradlew to install gradlew dependencies, then delete HIRS
# Use '--depth=1' so as to not download the history of all commits
RUN git clone -b main --depth=1 https://github.com/nsacyber/HIRS.git /hirsTemp
WORKDIR "/hirsTemp"
RUN /bin/bash -c './gradlew clean build'
WORKDIR "/"
RUN rm -rf /hirsTemp

View File

@ -1,6 +1,7 @@
plugins {
id 'java'
id 'io.spring.dependency-management' version '1.1.0'
id 'com.google.protobuf' version '0.9.4'
}
java {
@ -36,6 +37,7 @@ dependencies {
implementation libs.jakarta.api
implementation libs.jakarta.xml
implementation libs.hibernate.core
implementation libs.pci
implementation libs.guava
implementation libs.jackson.core
implementation libs.jackson.databind
@ -43,20 +45,29 @@ dependencies {
implementation libs.protobuf.java
implementation 'org.apache.logging.log4j:log4j-core:2.19.0'
implementation 'org.apache.logging.log4j:log4j-api:2.19.0'
testImplementation 'org.junit.jupiter:junit-jupiter:5.9.3'
testImplementation 'org.junit.platform:junit-platform-launcher:1.9.3'
testImplementation 'org.hamcrest:hamcrest:2.2'
// spring management
compileOnly libs.lombok
implementation libs.lombok
annotationProcessor libs.lombok
}
task generateProtoBuf(type:Exec) {
workingDir 'config'
commandLine './genJavaProtoBuf.sh'
protobuf {
protoc {
artifact = 'com.google.protobuf:protoc:3.24.3'
}
}
sourceSets {
main {
proto {
srcDir '../HIRS_ProvisionerTPM2/src'
}
}
}
compileJava.dependsOn generateProtoBuf
test {
useJUnitPlatform()

View File

@ -8,9 +8,8 @@ import hirs.attestationca.persist.entity.manager.PolicyRepository;
import hirs.attestationca.persist.entity.manager.ReferenceDigestValueRepository;
import hirs.attestationca.persist.entity.manager.ReferenceManifestRepository;
import hirs.attestationca.persist.entity.manager.TPM2ProvisionerStateRepository;
import hirs.attestationca.persist.provision.CertificateRequestHandler;
import hirs.attestationca.persist.provision.IdentityClaimHandler;
import hirs.attestationca.persist.provision.IdentityRequestHandler;
import hirs.attestationca.persist.provision.CertificateRequestProcessor;
import hirs.attestationca.persist.provision.IdentityClaimProcessor;
import hirs.attestationca.persist.service.SupplyChainValidationService;
import hirs.structs.converters.StructConverter;
import lombok.extern.log4j.Log4j2;
@ -62,9 +61,8 @@ public abstract class AttestationCertificateAuthority {
private final PolicyRepository policyRepository;
private final TPM2ProvisionerStateRepository tpm2ProvisionerStateRepository;
private CertificateRequestHandler certificateRequestHandler;
private IdentityClaimHandler identityClaimHandler;
private IdentityRequestHandler identityRequestHandler;
private CertificateRequestProcessor certificateRequestHandler;
private IdentityClaimProcessor identityClaimHandler;
/**
* Constructor.
@ -109,19 +107,13 @@ public abstract class AttestationCertificateAuthority {
this.policyRepository = policyRepository;
this.tpm2ProvisionerStateRepository = tpm2ProvisionerStateRepository;
this.certificateRequestHandler = new CertificateRequestHandler(supplyChainValidationService,
this.certificateRequestHandler = new CertificateRequestProcessor(supplyChainValidationService,
certificateRepository, deviceRepository,
privateKey, acaCertificate, validDays, tpm2ProvisionerStateRepository);
this.identityClaimHandler = new IdentityClaimHandler(supplyChainValidationService,
this.identityClaimHandler = new IdentityClaimProcessor(supplyChainValidationService,
certificateRepository, referenceManifestRepository,
referenceDigestValueRepository,
deviceRepository, tpm2ProvisionerStateRepository, policyRepository);
this.identityRequestHandler = new IdentityRequestHandler(structConverter, certificateRepository,
deviceRepository, supplyChainValidationService, privateKey, validDays, acaCertificate);
}
byte[] processIdentityRequest(final byte[] identityRequest) {
return this.identityRequestHandler.processIdentityRequest(identityRequest);
}
byte[] processIdentityClaimTpm2(final byte[] identityClaim) {

View File

@ -1,223 +0,0 @@
package hirs.attestationca.persist;
import hirs.attestationca.persist.entity.userdefined.PolicySettings;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.extern.log4j.Log4j2;
/**
* The class handles the flags that ignore certain PCRs for validation.
*/
@Log4j2
@NoArgsConstructor
public class PCRQuoteValidator {
/**
* Minimum possible value for a PCR ID. This is 0.
*/
public static final int MIN_PCR_ID = 0;
/**
* Maximum possible value for a PCR ID. This is 23.
*/
public static final int MAX_PCR_ID = 23;
private static final int NUM_TO_SKIP = 1;
private static final int NUM_OF_TBOOT_PCR = 3;
// PCR 5-16
private static final int PXE_PCR_START = 5;
private static final int PXE_PCR_END = 16;
// PCR 10
private static final int IMA_PCR = 10;
// PCR 17-19
private static final int TBOOT_PCR_START = 17;
private static final int TBOOT_PCR_END = 19;
// PCR 5
private static final int GPT_PCR = 5;
private static final int IMA_MASK = 0xfffbff;
// Event Log Event Types
private static final String EVT_EFI_BOOT = "EV_EFI_BOOT_SERVICES_APPLICATION";
private static final String EVT_EFI_VAR = "EV_EFI_VARIABLE_BOOT";
private static final String EVT_EFI_GPT = "EV_EFI_GPT_EVENT";
private static final String EVT_EFI_CFG = "EV_EFI_VARIABLE_DRIVER_CONFIG";
private String[] baselinePCRS = new String[MAX_PCR_ID + 1];
@Getter
@Setter
private PolicySettings settings;
/**
* Constructor to parse PCR values.
* @param pcrValues pcrValues RIM provided baseline PCRs
* @param settings settings for the supply chain portal settings for provisioning
*/
public PCRQuoteValidator(final String[] pcrValues,
final PolicySettings settings) {
if (pcrValues != null) {
baselinePCRS = new String[MAX_PCR_ID + 1];
for (int i = 0; i <= MAX_PCR_ID; i++) {
baselinePCRS[i] = pcrValues[i];
}
}
this.settings = settings;
}
/**
* Getter for the array of baseline PCRs.
* @return instance of the PCRs.
*/
public String[] getBaselinePCRS() {
return baselinePCRS.clone();
}
/**
* Setter for the array of baseline PCRs.
* @param baselinePCRS instance of the PCRs.
*/
public void setBaselinePCRS(final String[] baselinePCRS) {
this.baselinePCRS = baselinePCRS.clone();
}
/**
* Compares the baseline pcr list and the quote pcr list. If the
* ignore flags are set, 10 and 17-19 will be skipped for comparison.
*
* @param storedPCRS non-baseline pcr list
* @return a StringBuilder that is empty if everything passes.
*/
public StringBuilder validatePCRS(final String[] storedPCRS) {
StringBuilder sb = new StringBuilder();
String failureMsg = "PCR %d does not match%n";
if (storedPCRS[0] == null || storedPCRS[0].isEmpty()) {
sb.append("failureMsg");
} else {
for (int i = 0; i <= MAX_PCR_ID; i++) {
if (settings.isIgnoreImaEnabled() && i == IMA_PCR) {
log.info("PCR Policy IMA Ignore enabled.");
i += NUM_TO_SKIP;
}
if (settings.isIgnoretBootEnabled() && i == TBOOT_PCR_START) {
log.info("PCR Policy TBoot Ignore enabled.");
i += NUM_OF_TBOOT_PCR;
}
if (settings.isIgnoreGptEnabled() && i == GPT_PCR) {
log.info("PCR Policy GPT Ignore enabled.");
i += NUM_TO_SKIP;
}
if (!baselinePCRS[i].equals(storedPCRS[i])) {
//error
log.error(String.format("%s =/= %s", baselinePCRS[i], storedPCRS[i]));
sb.append(String.format(failureMsg, i));
}
}
}
return sb;
}
/**
* Checks that the expected FM events occurring. There are policy options that
* will ignore certain PCRs, Event Types and Event Variables present.
* @param tcgMeasurementLog Measurement log from the client
* @param eventValueMap The events stored as baseline to compare
* @return the events that didn't pass
*/
// public List<TpmPcrEvent> validateTpmEvents(final TCGEventLog tcgMeasurementLog,
// final Map<String, ReferenceDigestValue> eventValueMap) {
// List<TpmPcrEvent> tpmPcrEvents = new LinkedList<>();
// for (TpmPcrEvent tpe : tcgMeasurementLog.getEventList()) {
// if (enableIgnoreIma && tpe.getPcrIndex() == IMA_PCR) {
// log.info(String.format("IMA Ignored -> %s", tpe));
// } else if (enableIgnoretBoot && (tpe.getPcrIndex() >= TBOOT_PCR_START
// && tpe.getPcrIndex() <= TBOOT_PCR_END)) {
// log.info(String.format("TBOOT Ignored -> %s", tpe));
// } else if (enableIgnoreOsEvt && (tpe.getPcrIndex() >= PXE_PCR_START
// && tpe.getPcrIndex() <= PXE_PCR_END)) {
// log.info(String.format("OS Evt Ignored -> %s", tpe));
// } else {
// if (enableIgnoreGpt && tpe.getEventTypeStr().contains(EVT_EFI_GPT)) {
// log.info(String.format("GPT Ignored -> %s", tpe));
// } else if (enableIgnoreOsEvt && (tpe.getEventTypeStr().contains(EVT_EFI_BOOT)
// || tpe.getEventTypeStr().contains(EVT_EFI_VAR))) {
// log.info(String.format("OS Evt Ignored -> %s", tpe));
// } else if (enableIgnoreOsEvt && (tpe.getEventTypeStr().contains(EVT_EFI_CFG)
// && tpe.getEventContentStr().contains("SecureBoot"))) {
// log.info(String.format("OS Evt Config Ignored -> %s", tpe));
// } else {
// if (!eventValueMap.containsKey(tpe.getEventDigestStr())) {
// tpmPcrEvents.add(tpe);
// }
// }
// }
// }
//
// return tpmPcrEvents;
// }
/**
* Compares hashes to validate the quote from the client.
*
* @param tpmQuote the provided quote
* @param storedPCRS values from the RIM file
* @return true if validated, false if not
*/
// public boolean validateQuote(final byte[] tpmQuote, final String[] storedPCRS) {
// System.out.println("Validating quote from associated device.");
// boolean validated = false;
// short localityAtRelease = 0;
// String quoteString = new String(tpmQuote, StandardCharsets.UTF_8);
// int pcrMaskSelection = PcrSelection.ALL_PCRS_ON;
//
// if (enableIgnoreIma) {
// pcrMaskSelection = IMA_MASK;
// }
//
// ArrayList<TPMMeasurementRecord> measurements = new ArrayList<>();
//
// try {
// for (int i = 0; i < storedPcrs.length; i++) {
// if (i == IMA_PCR && enableIgnoreIma) {
// log.info("Ignore IMA PCR policy is enabled.");
// } else {
// measurements.add(new TPMMeasurementRecord(i, storedPcrs[i]));
// }
// }
// } catch (DecoderException deEx) {
// //error
// System.out.println(deEx);
// }
//
// PcrSelection pcrSelection = new PcrSelection(pcrMaskSelection);
// PcrComposite pcrComposite = new PcrComposite(pcrSelection);
// PcrInfoShort pcrInfoShort = new PcrInfoShort(pcrSelection,
// localityAtRelease,
// tpmQuote, pcrComposite);
//
// try {
// /**
// * The calculated string is being used in the contains method
// * because the TPM Quote's hash isn't just for PCR values,
// * it contains the calculated digest of the PCRs, along with
// * other information.
// */
// String calculatedString = Hex.encodeHexString(
// pcrInfoShort.getCalculatedDigest());
// validated = quoteString.contains(calculatedString);
// if (!validated) {
// // warn
// System.out.println(calculatedString + " not found in " + quoteString);
// }
// } catch (NoSuchAlgorithmException naEx) {
// // error
// System.out.println(naEx);
// }
//
// return validated;
// }
}

View File

@ -71,28 +71,6 @@ public class RestfulAttestationCertificateAuthority extends AttestationCertifica
referenceDigestValueRepository, policyRepository, tpm2ProvisionerStateRepository);
}
/**
* Processes a given IdentityRequestEnvelope and
* generates a IdentityResponseEnvelope. In most cases,
* a client will generate the request using the TPM "Collate Identity" process.
*
* Wrap the {@link AttestationCertificateAuthority#processIdentityRequest(byte[])}
* with a Spring {@link org.springframework.web.bind.annotation.RequestMapping}. Effectively, this method then will allow spring to
* serialize and deserialize the request and responses on method invocation and
* return, respectively.
*
* @param identityRequest generated during the collate identity process with a Tpm
* @return response for the request
*/
@Override
@ResponseBody
@RequestMapping(value = "/identity-request/process",
method = RequestMethod.POST,
consumes = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public byte[] processIdentityRequest(@RequestBody final byte[] identityRequest) {
return super.processIdentityRequest(identityRequest);
}
/**
* Listener for identity requests from TPM 2.0 provisioning.
*

View File

@ -5,8 +5,6 @@ package hirs.attestationca.persist;
*/
public interface RestfulInterface {
byte[] processIdentityRequest(byte[] identityRequest);
byte[] processIdentityClaimTpm2(byte[] identityClaim);
byte[] processCertificateRequest(byte[] certificateRequest);

View File

@ -17,4 +17,5 @@ public interface CACredentialRepository extends JpaRepository<CertificateAuthori
List<CertificateAuthorityCredential> findBySubject(String subject);
List<CertificateAuthorityCredential> findBySubjectSorted(String subject);
CertificateAuthorityCredential findBySubjectKeyIdentifier(byte[] subjectKeyIdentifier);
CertificateAuthorityCredential findBySubjectKeyIdString(String subjectKeyIdString);
}

View File

@ -11,12 +11,9 @@ import java.util.UUID;
@Repository
public interface ReferenceDigestValueRepository extends JpaRepository<ReferenceDigestValue, UUID> {
@Query(value = "SELECT * FROM ReferenceDigestValue", nativeQuery = true)
List<ReferenceDigestValue> listAll();
List<ReferenceDigestValue> findByModel(String model);
List<ReferenceDigestValue> findByManufacturer(String manufacturer);
@Query(value = "SELECT * FROM ReferenceDigestValue WHERE baseRimId = '?1' OR supportRimId = '?1'", nativeQuery = true)
List<ReferenceDigestValue> getValuesByRimId(UUID associatedRimId);
List<ReferenceDigestValue> findValuesByBaseRimId(UUID associatedRimId);
List<ReferenceDigestValue> findBySupportRimId(UUID supportRimId);
List<ReferenceDigestValue> findBySupportRimHash(String supportRimHash);
List<ReferenceDigestValue> findByManufacturerAndModel(String manufacturer, String model);

View File

@ -39,4 +39,6 @@ public interface ReferenceManifestRepository extends JpaRepository<ReferenceMani
EventLogMeasurements byMeasurementDeviceName(String deviceName);
@Query(value = "SELECT * FROM ReferenceManifest WHERE platformManufacturer = ?1 AND platformModel = ?2 AND rimType = 'Support'", nativeQuery = true)
List<SupportReferenceManifest> getSupportByManufacturerModel(String manufacturer, String model);
@Query(value = "SELECT * FROM ReferenceManifest WHERE platformModel = ?1 AND DTYPE = 'EventLogMeasurements'", nativeQuery = true)
EventLogMeasurements getLogByModel(String model);
}

View File

@ -20,7 +20,7 @@ import java.util.Date;
@NoArgsConstructor
@Entity
public class TPM2ProvisionerState {
private static final int MAX_BLOB_SIZE = 65535;
private static final int MAX_BLOB_SIZE = 16777215;
@Id
private Long firstPartOfNonce;
@ -88,7 +88,7 @@ public class TPM2ProvisionerState {
/**
* Convenience method for finding the {@link TPM2ProvisionerState} associated with the nonce.
*
* @param TPM2ProvisionerStateRepository the {@link TPM2ProvisionerStateRepository} to use when looking for the
* @param tpm2ProvisionerStateRepository the {@link TPM2ProvisionerStateRepository} to use when looking for the
* {@link TPM2ProvisionerState}
* @param nonce the nonce to use as the key for the {@link TPM2ProvisionerState}
* @return the {@link TPM2ProvisionerState} associated with the nonce;

View File

@ -58,6 +58,16 @@ public class Device extends AbstractEntity {
@Column(name = "summary_id")
private String summaryId;
public Device(final DeviceInfoReport deviceInfoReport) {
super();
if (deviceInfoReport != null) {
this.name = deviceInfoReport.getNetworkInfo().getHostname();
this.deviceInfo = deviceInfoReport;
} else {
name = "";
}
}
public String toString() {
return String.format("Device Name: %s%nStatus: %s%nSummary: %s",
name, healthStatus.getStatus(),

View File

@ -176,6 +176,8 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
@Column(length = MAX_MESSAGE_LENGTH)
private String componentFailures = Strings.EMPTY;
@Column(length = MAX_MESSAGE_LENGTH)
private String componentFailureMessage = Strings.EMPTY;
@Transient
private EndorsementCredential endorsementCredential = null;

View File

@ -30,7 +30,7 @@ public class ComponentClass {
private static final String TCG_COMPONENT_REGISTRY = "2.23.133.18.3.1";
private static final String SMBIOS_COMPONENT_REGISTRY = "2.23.133.18.3.3";
private static final Path JSON_PATH = FileSystems.getDefault()
.getPath("/etc", "hirs/aca", "default-properties", "component-class.json");
.getPath("/etc", "hirs", "aca", "default-properties", "component-class.json");
private static final String OTHER_STRING = "Other";
private static final String UNKNOWN_STRING = "Unknown";

View File

@ -60,5 +60,4 @@ public class AppraisalStatus {
this.message = message;
this.additionalInfo = additionalInfo;
}
}

View File

@ -41,7 +41,7 @@ import java.util.List;
@Log4j2
@NoArgsConstructor
public class AbstractRequestHandler {
public class AbstractProcessor {
@Getter
private int validDays;
@ -51,8 +51,8 @@ public class AbstractRequestHandler {
@Getter
private PolicyRepository policyRepository;
public AbstractRequestHandler(final PrivateKey privateKey,
final int validDays) {
public AbstractProcessor(final PrivateKey privateKey,
final int validDays) {
this.privateKey = privateKey;
this.validDays = validDays;
}
@ -137,7 +137,8 @@ public class AbstractRequestHandler {
if (identityClaim.hasEndorsementCredential()) {
endorsementCredential = CredentialManagementHelper.storeEndorsementCredential(
certificateRepository,
identityClaim.getEndorsementCredential().toByteArray());
identityClaim.getEndorsementCredential().toByteArray(),
identityClaim.getDv().getNw().getHostname());
} else if (ekPub != null) {
log.warn("Endorsement Cred was not in the identity claim from the client."
+ " Checking for uploads.");
@ -233,8 +234,8 @@ public class AbstractRequestHandler {
final Device device) {
IssuedAttestationCertificate issuedAc;
boolean generateCertificate = true;
PolicyRepository scp = this.getPolicyRepository();
PolicySettings policySettings = scp.findByName("Default");
PolicyRepository scp = getPolicyRepository();
PolicySettings policySettings;
Date currentDate = new Date();
int days;
try {
@ -243,6 +244,7 @@ public class AbstractRequestHandler {
derEncodedAttestationCertificate, endorsementCredential, platformCredentials);
if (scp != null) {
policySettings = scp.findByName("Default");
issuedAc = certificateRepository.findByDeviceId(device.getId());
generateCertificate = policySettings.isIssueAttestationCertificate();
@ -260,6 +262,7 @@ public class AbstractRequestHandler {
}
}
if (generateCertificate) {
attCert.setDeviceId(device.getId());
attCert.setDeviceName(device.getName());
certificateRepository.save(attCert);
}

View File

@ -27,7 +27,7 @@ import java.security.interfaces.RSAPublicKey;
import java.util.List;
@Log4j2
public class CertificateRequestHandler extends AbstractRequestHandler {
public class CertificateRequestProcessor extends AbstractProcessor {
private SupplyChainValidationService supplyChainValidationService;
private CertificateRepository certificateRepository;
@ -42,13 +42,13 @@ public class CertificateRequestHandler extends AbstractRequestHandler {
* @param validDays int for the time in which a certificate is valid.
* @param tpm2ProvisionerStateRepository db connector for provisioner state.
*/
public CertificateRequestHandler(final SupplyChainValidationService supplyChainValidationService,
final CertificateRepository certificateRepository,
final DeviceRepository deviceRepository,
final PrivateKey privateKey,
final X509Certificate acaCertificate,
final int validDays,
final TPM2ProvisionerStateRepository tpm2ProvisionerStateRepository) {
public CertificateRequestProcessor(final SupplyChainValidationService supplyChainValidationService,
final CertificateRepository certificateRepository,
final DeviceRepository deviceRepository,
final PrivateKey privateKey,
final X509Certificate acaCertificate,
final int validDays,
final TPM2ProvisionerStateRepository tpm2ProvisionerStateRepository) {
super(privateKey, validDays);
this.supplyChainValidationService = supplyChainValidationService;
this.certificateRepository = certificateRepository;
@ -198,6 +198,7 @@ public class CertificateRequestHandler extends AbstractRequestHandler {
* @return the {@link AppraisalStatus} of the supply chain validation
*/
private AppraisalStatus.Status doQuoteValidation(final Device device) {
log.info("Beginning Quote Validation...");
// perform supply chain validation
SupplyChainValidationSummary scvs = supplyChainValidationService.validateQuote(
device);

View File

@ -57,7 +57,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Log4j2
public class IdentityClaimHandler extends AbstractRequestHandler {
public class IdentityClaimProcessor extends AbstractProcessor {
private static final String PCR_QUOTE_MASK = "0,1,2,3,4,5,6,7,8,9,10,11,12,13,"
+ "14,15,16,17,18,19,20,21,22,23";
@ -78,7 +78,7 @@ public class IdentityClaimHandler extends AbstractRequestHandler {
/**
* Constructor
*/
public IdentityClaimHandler(
public IdentityClaimProcessor(
final SupplyChainValidationService supplyChainValidationService,
final CertificateRepository certificateRepository,
final ReferenceManifestRepository referenceManifestRepository,
@ -105,7 +105,7 @@ public class IdentityClaimHandler extends AbstractRequestHandler {
* @return an identity claim response for the specified request containing a wrapped blob
*/
public byte[] processIdentityClaimTpm2(final byte[] identityClaim) {
log.error("Identity Claim received...");
log.info("Identity Claim received...");
if (ArrayUtils.isEmpty(identityClaim)) {
log.error("Identity claim empty throwing exception.");
@ -124,6 +124,7 @@ public class IdentityClaimHandler extends AbstractRequestHandler {
try {
validationResult = doSupplyChainValidation(claim, ekPub);
} catch (Exception ex) {
log.error(ex.getMessage());
for (StackTraceElement ste : ex.getStackTrace()) {
log.error(ste.toString());
}
@ -191,12 +192,15 @@ public class IdentityClaimHandler extends AbstractRequestHandler {
// this is to check what is in the platform object and pull
// additional information from the DB if information exists
if (platformCredentials.size() == 1) {
List<PlatformCredential> tempList = new LinkedList<>();
for (PlatformCredential pc : platformCredentials) {
if (pc != null && pc.getPlatformSerial() != null) {
platformCredentials.addAll(certificateRepository
tempList.addAll(certificateRepository
.byBoardSerialNumber(pc.getPlatformSerial()));
}
}
platformCredentials.addAll(tempList);
}
// perform supply chain validation
SupplyChainValidationSummary summary = supplyChainValidationService.validateSupplyChain(
@ -227,6 +231,9 @@ public class IdentityClaimHandler extends AbstractRequestHandler {
log.info("Processing Device Info Report");
// store device and device info report.
Device device = this.deviceRepository.findByName(deviceInfoReport.getNetworkInfo().getHostname());
if (device == null) {
device = new Device(deviceInfoReport);
}
device.setDeviceInfo(deviceInfoReport);
return this.deviceRepository.save(device);
}
@ -457,8 +464,8 @@ public class IdentityClaimHandler extends AbstractRequestHandler {
if (baseRim != null) {
// pull the base versions of the swidtag and rimel and set the
// event log hash for use during provision
SupportReferenceManifest sBaseRim = (SupportReferenceManifest) referenceManifestRepository
.findByBase64Hash(baseRim.getBase64Hash());
SupportReferenceManifest sBaseRim = referenceManifestRepository
.getSupportRimEntityById(baseRim.getAssociatedRim());
baseRim.setEventLogHash(temp.getHexDecHash());
sBaseRim.setEventLogHash(temp.getHexDecHash());
referenceManifestRepository.save(baseRim);

View File

@ -1,345 +0,0 @@
package hirs.attestationca.persist.provision;
import hirs.attestationca.persist.entity.manager.CertificateRepository;
import hirs.attestationca.persist.entity.manager.DeviceRepository;
import hirs.utils.Certificate;
import hirs.attestationca.persist.entity.userdefined.Device;
import hirs.attestationca.persist.entity.userdefined.SupplyChainValidationSummary;
import hirs.attestationca.persist.entity.userdefined.certificate.EndorsementCredential;
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
import hirs.attestationca.persist.entity.userdefined.report.DeviceInfoReport;
import hirs.attestationca.persist.enums.AppraisalStatus;
import hirs.attestationca.persist.exceptions.IdentityProcessingException;
import hirs.attestationca.persist.provision.helper.CredentialManagementHelper;
import hirs.attestationca.persist.provision.helper.ProvisionUtils;
import hirs.attestationca.persist.service.SupplyChainValidationService;
import hirs.structs.converters.SimpleStructBuilder;
import hirs.structs.converters.StructConverter;
import hirs.structs.elements.aca.IdentityRequestEnvelope;
import hirs.structs.elements.aca.IdentityResponseEnvelope;
import hirs.structs.elements.aca.SymmetricAttestation;
import hirs.structs.elements.tpm.EncryptionScheme;
import hirs.structs.elements.tpm.IdentityProof;
import hirs.structs.elements.tpm.IdentityRequest;
import hirs.structs.elements.tpm.SymmetricKey;
import hirs.structs.elements.tpm.SymmetricKeyParams;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.SerializationUtils;
import java.io.IOException;
import java.math.BigInteger;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
import java.util.LinkedList;
import java.util.List;
@Log4j2
public class IdentityRequestHandler extends AbstractRequestHandler {
/**
* Container wired ACA private key.
*/
private final PrivateKey privateKey;
private int validDays;
private StructConverter structConverter;
private CertificateRepository certificateRepository;
private DeviceRepository deviceRepository;
private SupplyChainValidationService supplyChainValidationService;
private X509Certificate acaCertificate;
/**
* Constructor.
* @param structConverter the struct converter
* @param certificateRepository
* @param deviceRepository
* @param supplyChainValidationService the supply chain service
* @param privateKey
* @param validDays int for the time in which a certificate is valid.
* @param acaCertificate object holding the x509 certificate
*/
public IdentityRequestHandler(final StructConverter structConverter,
final CertificateRepository certificateRepository,
final DeviceRepository deviceRepository,
final SupplyChainValidationService supplyChainValidationService,
final PrivateKey privateKey,
final int validDays, final X509Certificate acaCertificate) {
super(privateKey, validDays);
this.structConverter = structConverter;
this.certificateRepository = certificateRepository;
this.deviceRepository = deviceRepository;
this.supplyChainValidationService = supplyChainValidationService;
this.privateKey = privateKey;
this.acaCertificate = acaCertificate;
}
/**
* Basic implementation of the ACA processIdentityRequest method.
*
* @param identityRequest cannot be null
* @return an identity response for the specified request
*/
public byte[] processIdentityRequest(final byte[] identityRequest) {
log.info("Identity Request Received...");
if (ArrayUtils.isEmpty(identityRequest)) {
throw new IllegalArgumentException("The IdentityRequest sent by the client"
+ " cannot be null or empty.");
}
log.debug("received request to process identity request");
// translate the bytes into the challenge
IdentityRequestEnvelope challenge =
structConverter.convert(identityRequest, IdentityRequestEnvelope.class);
byte[] identityProof = unwrapIdentityRequest(structConverter.convert(challenge.getRequest(),
IdentityRequest.class));
// the decrypted symmetric blob should be in the format of an IdentityProof. Use the
// struct converter to generate it.
IdentityProof proof = structConverter.convert(identityProof, IdentityProof.class);
// convert the credential into an actual key.
log.debug("assembling public endorsement key");
PublicKey ekPublicKey = null;
// attempt to find an endorsement credential to validate
EndorsementCredential endorsementCredential = null;
// first check the identity request for the endorsement credential
byte[] ecBytesFromIdentityRequest = proof.getEndorsementCredential();
if (ArrayUtils.isNotEmpty(ecBytesFromIdentityRequest)) {
endorsementCredential = CredentialManagementHelper.storeEndorsementCredential(
this.certificateRepository, ecBytesFromIdentityRequest);
try {
BigInteger publicKeyModulus = Certificate.getPublicKeyModulus(
endorsementCredential.getX509Certificate());
if (publicKeyModulus != null) {
ekPublicKey = ProvisionUtils.assemblePublicKey(publicKeyModulus.toByteArray());
} else {
throw new IdentityProcessingException("TPM 1.2 Provisioning requires EK "
+ "Credentials to be created with RSA");
}
} catch (IOException ioEx) {
log.error("Could not retrieve the public key modulus from the EK cert");
}
} else if (ArrayUtils.isNotEmpty(challenge.getEndorsementCredentialModulus())) {
log.warn("EKC was not in the identity proof from the client. Checking for uploads.");
// Check if the EC was uploaded
ekPublicKey =
ProvisionUtils.assemblePublicKey(new String(challenge.getEndorsementCredentialModulus()));
endorsementCredential = getEndorsementCredential(ekPublicKey);
} else {
log.warn("Zero-length endorsement credential received in identity request.");
}
// get platform credential from the identity request
List<PlatformCredential> platformCredentials = new LinkedList<>();
byte[] pcBytesFromIdentityRequest = proof.getPlatformCredential();
if (ArrayUtils.isNotEmpty(pcBytesFromIdentityRequest)) {
platformCredentials.add(CredentialManagementHelper.storePlatformCredential(
this.certificateRepository, pcBytesFromIdentityRequest));
} else if (endorsementCredential != null) {
// if none in the identity request, look for uploaded platform credentials
log.warn("PC was not in the identity proof from the client. Checking for uploads.");
platformCredentials.addAll(getPlatformCredentials(endorsementCredential));
} else {
// if none in the identity request, look for uploaded platform credentials
log.warn("Zero-length platform credential received in identity request.");
}
log.debug("Processing serialized device info report structure of length {}",
challenge.getDeviceInfoReportLength());
DeviceInfoReport deviceInfoReport = (DeviceInfoReport)
SerializationUtils.deserialize(challenge.getDeviceInfoReport());
if (deviceInfoReport == null) {
log.error("Failed to deserialize Device Info Report");
throw new IdentityProcessingException("Device Info Report failed to deserialize "
+ "from Identity Request");
}
log.info("Processing Device Info Report");
// store device and device info report.
String deviceName = deviceInfoReport.getNetworkInfo().getHostname();
Device device = this.deviceRepository.findByName(deviceName);
device.setDeviceInfo(deviceInfoReport);
// perform supply chain validation. Note: It's possible that this should be done earlier
// in this method.
SupplyChainValidationSummary summary =
supplyChainValidationService.validateSupplyChain(endorsementCredential,
platformCredentials, device);
// update the validation result in the device
device.setSupplyChainValidationStatus(summary.getOverallValidationResult());
deviceRepository.save(device);
// check if supply chain validation succeeded.
// If it did not, do not provide the IdentityResponseEnvelope
if (summary.getOverallValidationResult() == AppraisalStatus.Status.PASS) {
IdentityResponseEnvelope identityResponse =
generateIdentityResponseEnvelopeAndStoreIssuedCert(challenge,
ekPublicKey, endorsementCredential, platformCredentials, device);
return structConverter.convert(identityResponse);
} else {
log.error("Supply chain validation did not succeed. Result is: "
+ summary.getOverallValidationResult());
return new byte[]{};
}
}
/**
* Given a successful supply chain validation, generate an Identity Response envelope and
* the issued certificate. The issued cert is stored in the database. The identity response
* envelope is returned, and sent back to the client using the struct converter.
* @param challenge the identity request envelope
* @param ekPublicKey the EK public key
* @param endorsementCredential the endorsement credential
* @param platformCredentials the set of platform credentials
* @param device the device associated
* @return the identity response envelope
*/
private IdentityResponseEnvelope generateIdentityResponseEnvelopeAndStoreIssuedCert(
final IdentityRequestEnvelope challenge, final PublicKey ekPublicKey,
final EndorsementCredential endorsementCredential,
final List<PlatformCredential> platformCredentials, final Device device) {
// decrypt the asymmetric / symmetric blobs
log.debug("unwrapping identity request");
byte[] identityProof = unwrapIdentityRequest(
structConverter.convert(challenge.getRequest(), IdentityRequest.class));
// the decrypted symmetric blob should be in the format of an IdentityProof. Use the
// struct converter to generate it.
IdentityProof proof = structConverter.convert(identityProof, IdentityProof.class);
// generate a session key and convert to byte array
log.debug("generating symmetric key for response");
SymmetricKey sessionKey = ProvisionUtils.generateSymmetricKey();
// generate the asymmetric contents for the identity response
log.debug("generating asymmetric contents for response");
byte[] asymmetricContents = ProvisionUtils.generateAsymmetricContents(
structConverter.convert(proof.getIdentityKey()),
structConverter.convert(sessionKey), ekPublicKey);
// generate the identity credential
log.debug("generating credential from identity proof");
// transform the public key struct into a public key
PublicKey publicKey = ProvisionUtils.assemblePublicKey(proof.getIdentityKey().getStorePubKey().getKey());
X509Certificate credential = generateCredential(publicKey, endorsementCredential,
platformCredentials, device.getDeviceInfo()
.getNetworkInfo()
.getIpAddress()
.getHostName(), acaCertificate);
// generate the attestation using the credential and the key for this session
log.debug("generating symmetric response");
SymmetricAttestation attestation = ProvisionUtils.generateAttestation(credential, sessionKey);
// construct the response with the both the asymmetric contents and the CA attestation
IdentityResponseEnvelope identityResponse =
new SimpleStructBuilder<>(IdentityResponseEnvelope.class)
.set("asymmetricContents", asymmetricContents)
.set("symmetricAttestation", attestation).build();
// save new attestation certificate
byte[] derEncodedAttestationCertificate = ProvisionUtils.getDerEncodedCertificate(credential);
saveAttestationCertificate(this.certificateRepository, derEncodedAttestationCertificate,
endorsementCredential, platformCredentials, device);
return identityResponse;
}
/**
* Unwraps a given identityRequest. That is to say, decrypt the asymmetric portion of a data
* structure to determine the method to decrypt the symmetric portion.
*
* @param request
* to be decrypted
* @return the decrypted symmetric portion of an identity request.
*/
private byte[] unwrapIdentityRequest(final IdentityRequest request) {
// in case the TPM did not specify the IV, it must be extracted from the symmetric blob.
// the IV will then be the the first block of the cipher text.
final byte[] iv;
SymmetricKeyParams symmetricKeyParams = request.getSymmetricAlgorithm();
if (symmetricKeyParams != null && symmetricKeyParams.getParams() != null) {
iv = symmetricKeyParams.getParams().getIv();
} else {
iv = ProvisionUtils.extractInitialValue(request);
}
// determine the encryption scheme from the algorithm
EncryptionScheme asymmetricScheme =
EncryptionScheme.fromInt(request.getAsymmetricAlgorithm().getEncryptionScheme());
// decrypt the asymmetric blob
byte[] decryptedAsymmetricBlob =
ProvisionUtils.decryptAsymmetricBlob(request.getAsymmetricBlob(), asymmetricScheme, getPrivateKey());
// construct our symmetric key structure from the decrypted asymmetric blob
SymmetricKey symmetricKey =
structConverter.convert(decryptedAsymmetricBlob, SymmetricKey.class);
byte[] decryptedSymmetricBlob =
ProvisionUtils.decryptSymmetricBlob(request.getSymmetricBlob(), symmetricKey.getKey(), iv,
"AES/CBC/PKCS5Padding");
// decrypt the symmetric blob
return decryptedSymmetricBlob;
}
/**
* Gets the Endorsement Credential from the DB given the EK public key.
* @param ekPublicKey the EK public key
* @return the Endorsement credential, if found, otherwise null
*/
private EndorsementCredential getEndorsementCredential(final PublicKey ekPublicKey) {
log.debug("Searching for endorsement credential based on public key: " + ekPublicKey);
if (ekPublicKey == null) {
throw new IllegalArgumentException("Cannot look up an EC given a null public key");
}
EndorsementCredential credential = null;
try {
credential = certificateRepository.findByPublicKeyModulusHexValue(Certificate
.getPublicKeyModulus(ekPublicKey)
.toString());
} catch (IOException ioEx) {
log.error("Could not extract public key modulus", ioEx);
}
if (credential == null) {
log.warn("Unable to find endorsement credential for public key.");
} else {
log.debug("Endorsement credential found.");
}
return credential;
}
private List<PlatformCredential> getPlatformCredentials(final EndorsementCredential ec) {
List<PlatformCredential> credentials = null;
if (ec == null) {
log.warn("Cannot look for platform credential(s). Endorsement credential was null.");
} else {
log.debug("Searching for platform credential(s) based on holder serial number: "
+ ec.getSerialNumber());
credentials = this.certificateRepository.getByHolderSerialNumber(ec.getSerialNumber());
if (credentials == null || credentials.isEmpty()) {
log.warn("No platform credential(s) found");
} else {
log.debug("Platform Credential(s) found: " + credentials.size());
}
}
return credentials;
}
}

View File

@ -27,12 +27,13 @@ public final class CredentialManagementHelper {
* it is unarchived.
* @param certificateRepository the certificate manager used for storage
* @param endorsementBytes the raw EK bytes used for parsing
* @param deviceName the host name
* @return the parsed, valid EK
* @throws IllegalArgumentException if the provided bytes are not a valid EK.
*/
public static EndorsementCredential storeEndorsementCredential(
final CertificateRepository certificateRepository,
final byte[] endorsementBytes) throws IllegalArgumentException {
final byte[] endorsementBytes, final String deviceName) throws IllegalArgumentException {
if (certificateRepository == null) {
throw new IllegalArgumentException("null certificate manager");
@ -64,6 +65,7 @@ public final class CredentialManagementHelper {
.findByCertificateHash(certificateHash);
if (existingCredential == null) {
log.info("No Endorsement Credential found with hash: " + certificateHash);
endorsementCredential.setDeviceName(deviceName);
return (EndorsementCredential) certificateRepository.save(endorsementCredential);
} else if (existingCredential.isArchived()) {
// if the EK is stored in the DB and it's archived, unarchive.

View File

@ -1,30 +1,266 @@
package hirs.attestationca.persist.service;
import hirs.attestationca.persist.DBManagerException;
import hirs.attestationca.persist.entity.ArchivableEntity;
import hirs.attestationca.persist.entity.manager.CACredentialRepository;
import hirs.attestationca.persist.entity.manager.CertificateRepository;
import hirs.attestationca.persist.entity.manager.ComponentResultRepository;
import hirs.attestationca.persist.entity.manager.PolicyRepository;
import hirs.attestationca.persist.entity.manager.ReferenceDigestValueRepository;
import hirs.attestationca.persist.entity.manager.ReferenceManifestRepository;
import hirs.attestationca.persist.entity.manager.SupplyChainValidationRepository;
import hirs.attestationca.persist.entity.manager.SupplyChainValidationSummaryRepository;
import hirs.attestationca.persist.entity.userdefined.Device;
import hirs.attestationca.persist.entity.userdefined.PolicySettings;
import hirs.attestationca.persist.entity.userdefined.SupplyChainValidation;
import hirs.attestationca.persist.entity.userdefined.SupplyChainValidationSummary;
import hirs.attestationca.persist.entity.userdefined.certificate.EndorsementCredential;
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
import hirs.attestationca.persist.entity.userdefined.rim.EventLogMeasurements;
import hirs.attestationca.persist.entity.userdefined.rim.SupportReferenceManifest;
import hirs.attestationca.persist.enums.AppraisalStatus;
import hirs.attestationca.persist.validation.PcrValidator;
import hirs.attestationca.persist.validation.SupplyChainCredentialValidator;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.security.KeyStore;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.apache.logging.log4j.Level;
import static hirs.attestationca.persist.enums.AppraisalStatus.Status.FAIL;
import static hirs.attestationca.persist.enums.AppraisalStatus.Status.PASS;
@Log4j2
@Service
public class SupplyChainValidationService {
private CACredentialRepository caCredentialRepository;
private PolicyRepository policyRepository;
private ReferenceManifestRepository referenceManifestRepository;
private ReferenceDigestValueRepository referenceDigestValueRepository;
private ComponentResultRepository componentResultRepository;
private CertificateRepository certificateRepository;
private SupplyChainValidationRepository supplyChainValidationRepository;
private SupplyChainValidationSummaryRepository supplyChainValidationSummaryRepository;
/**
* Interface defining a component that will perform supply chain validations, which yields a
* {@link SupplyChainValidationSummary}.
*/
public interface SupplyChainValidationService {
/**
* The "main" method of supply chain validation. Takes the credentials from an identity
* request and validates the supply chain in accordance to the current supply chain
* policy.
* Constructor.
*
* @param ec The endorsement credential from the identity request.
* @param pc The set of platform credentials from the identity request.
* @param device The device to be validated.
* @return True if validation is successful, false otherwise.
* @param caCredentialRepository ca credential repository
* @param policyRepository the policy manager
* @param certificateRepository the cert manager
* @param componentResultRepository the comp result manager
* @param referenceManifestRepository the RIM manager
* @param supplyChainValidationRepository the scv manager
* @param supplyChainValidationSummaryRepository the summary manager
* @param referenceDigestValueRepository the even manager
*/
SupplyChainValidationSummary validateSupplyChain(EndorsementCredential ec,
List<PlatformCredential> pc,
Device device);
@Autowired
@SuppressWarnings("ParameterNumberCheck")
public SupplyChainValidationService(
final CACredentialRepository caCredentialRepository,
final PolicyRepository policyRepository,
final CertificateRepository certificateRepository,
final ComponentResultRepository componentResultRepository,
final ReferenceManifestRepository referenceManifestRepository,
final SupplyChainValidationRepository supplyChainValidationRepository,
final SupplyChainValidationSummaryRepository supplyChainValidationSummaryRepository,
final ReferenceDigestValueRepository referenceDigestValueRepository) {
this.caCredentialRepository = caCredentialRepository;
this.policyRepository = policyRepository;
this.certificateRepository = certificateRepository;
this.componentResultRepository = componentResultRepository;
this.referenceManifestRepository = referenceManifestRepository;
this.supplyChainValidationRepository = supplyChainValidationRepository;
this.supplyChainValidationSummaryRepository = supplyChainValidationSummaryRepository;
this.referenceDigestValueRepository = referenceDigestValueRepository;
}
/**
* The "main" method of supply chain validation. Takes the credentials from
* an identity request and validates the supply chain in accordance to the
* current supply chain policy.
*
* @param ec The endorsement credential from the identity request.
* @param pcs The platform credentials from the identity request.
* @param device The device to be validated.
* @return A summary of the validation results.
*/
@SuppressWarnings("methodlength")
public SupplyChainValidationSummary validateSupplyChain(final EndorsementCredential ec,
final List<PlatformCredential> pcs,
final Device device) {
boolean acceptExpiredCerts = getPolicySettings().isExpiredCertificateValidationEnabled();
PlatformCredential baseCredential = null;
SupplyChainValidation platformScv = null;
SupplyChainValidation basePlatformScv = null;
boolean chkDeltas = false;
String pcErrorMessage = "";
List<SupplyChainValidation> validations = new LinkedList<>();
Map<PlatformCredential, SupplyChainValidation> deltaMapping = new HashMap<>();
SupplyChainValidation.ValidationType platformType = SupplyChainValidation
.ValidationType.PLATFORM_CREDENTIAL;
log.info("Beginning Supply Chain Validation...");
// Validate the Endorsement Credential
if (getPolicySettings().isEcValidationEnabled()) {
log.info("Beginning Endorsement Credential Validation...");
validations.add(ValidationService.evaluateEndorsementCredentialStatus(ec, this.caCredentialRepository, acceptExpiredCerts));
// store the device with the credential
if (ec != null) {
ec.setDeviceId(device.getId());
ec.setDeviceName(device.getDeviceInfo().getNetworkInfo().getHostname());
this.certificateRepository.save(ec);
}
}
// Validate Platform Credential signatures
if (getPolicySettings().isPcValidationEnabled()) {
log.info("Beginning Platform Credential Validation...");
// Ensure there are platform credentials to validate
if (pcs == null || pcs.isEmpty()) {
log.error("There were no Platform Credentials to validate.");
pcErrorMessage = "Platform credential(s) missing\n";
} else {
for (PlatformCredential pc : pcs) {
KeyStore trustedCa = ValidationService.getCaChain(pc, caCredentialRepository);
platformScv = ValidationService.evaluatePlatformCredentialStatus(
pc, trustedCa, acceptExpiredCerts);
if (platformScv.getValidationResult() == AppraisalStatus.Status.FAIL) {
pcErrorMessage = String.format("%s%s%n", pcErrorMessage,
platformScv.getMessage());
}
// set the base credential
if (pc.isPlatformBase()) {
baseCredential = pc;
basePlatformScv = platformScv;
} else {
chkDeltas = true;
deltaMapping.put(pc, null);
}
pc.setEndorsementCredential(ec);
pc.setDeviceId(device.getId());
pc.setDeviceName(device.getDeviceInfo().getNetworkInfo().getHostname());
this.certificateRepository.save(pc);
}
// check that the delta certificates validity date is after
// the base
if (baseCredential != null) {
for (PlatformCredential pc : pcs) {
int result = baseCredential.getBeginValidity()
.compareTo(pc.getBeginValidity());
if (!pc.isPlatformBase() && (result > 0)) {
pcErrorMessage = String.format("%s%s%n", pcErrorMessage,
"Delta Certificate's validity "
+ "date is not after Base");
break;
}
}
} else {
// we don't have a base cert, fail
pcErrorMessage = String.format("%s%s%n", pcErrorMessage,
"Base Platform credential missing");
}
}
if (pcErrorMessage.isEmpty()) {
validations.add(platformScv);
} else {
if (pcs == null) {
validations.add(new SupplyChainValidation(platformType,
AppraisalStatus.Status.FAIL, new ArrayList<>(), pcErrorMessage));
} else {
validations.add(new SupplyChainValidation(platformType,
AppraisalStatus.Status.FAIL, new ArrayList<>(pcs), pcErrorMessage));
}
}
}
// Validate Platform Credential attributes
if (getPolicySettings().isPcAttributeValidationEnabled()
&& pcErrorMessage.isEmpty()) {
log.info("Beginning Platform Attributes Validation...");
// Ensure there are platform credentials to validate
SupplyChainValidation attributeScv = null;
String attrErrorMessage = "";
List<ArchivableEntity> aes = new ArrayList<>();
// need to check if there are deltas, if not then just verify
// components of the base
if (baseCredential == null) {
validations.add(ValidationService.buildValidationRecord(
SupplyChainValidation.ValidationType.PLATFORM_CREDENTIAL,
AppraisalStatus.Status.FAIL,
"Base Platform credential missing."
+ " Cannot validate attributes",
null, Level.ERROR));
} else {
if (chkDeltas) {
aes.addAll(basePlatformScv.getCertificatesUsed());
Iterator<PlatformCredential> it = pcs.iterator();
while (it.hasNext()) {
PlatformCredential pc = it.next();
if (pc != null && !pc.isPlatformBase()) {
attributeScv = ValidationService.evaluateDeltaAttributesStatus(
pc, device.getDeviceInfo(),
baseCredential, deltaMapping, certificateRepository);
if (attributeScv.getValidationResult() == AppraisalStatus.Status.FAIL) {
attrErrorMessage = String.format("%s%s%n", attrErrorMessage,
attributeScv.getMessage());
}
}
}
} else {
aes.add(baseCredential);
validations.remove(platformScv);
// if there are no deltas, just check base credential
platformScv = ValidationService.evaluatePCAttributesStatus(
baseCredential, device.getDeviceInfo(), ec,
certificateRepository, componentResultRepository);
validations.add(new SupplyChainValidation(
SupplyChainValidation.ValidationType.PLATFORM_CREDENTIAL,
platformScv.getValidationResult(), aes, platformScv.getMessage()));
}
}
if (!attrErrorMessage.isEmpty()) {
//combine platform and platform attributes
validations.remove(platformScv);
validations.add(new SupplyChainValidation(
SupplyChainValidation.ValidationType.PLATFORM_CREDENTIAL,
attributeScv.getValidationResult(), aes, attributeScv.getMessage()));
}
}
if (getPolicySettings().isFirmwareValidationEnabled()) {
log.info("Beginning Firmware Validation...");
// may need to associated with device to pull the correct info
// compare tpm quote with what is pulled from RIM associated file
validations.add(ValidationService.evaluateFirmwareStatus(device, getPolicySettings(),
referenceManifestRepository, referenceDigestValueRepository,
caCredentialRepository));
}
log.info("The validation finished, summarizing...");
// Generate validation summary, save it, and return it.
SupplyChainValidationSummary summary
= new SupplyChainValidationSummary(device, validations);
try {
supplyChainValidationSummaryRepository.save(summary);
} catch (DBManagerException dbMEx) {
log.error("Failed to save Supply Chain Summary");
}
return summary;
}
/**
* A supplemental method that handles validating just the quote post main validation.
@ -32,11 +268,110 @@ public interface SupplyChainValidationService {
* @param device the associated device.
* @return True if validation is successful, false otherwise.
*/
SupplyChainValidationSummary validateQuote(Device device);
public SupplyChainValidationSummary validateQuote(final Device device) {
SupplyChainValidation quoteScv = null;
SupplyChainValidationSummary summary = null;
Level level = Level.ERROR;
AppraisalStatus fwStatus = new AppraisalStatus(FAIL,
"Unknown exception caught during quote validation.");
SupportReferenceManifest sRim = null;
EventLogMeasurements eventLog = null;
// check if the policy is enabled
if (getPolicySettings().isFirmwareValidationEnabled()) {
String[] baseline = new String[Integer.SIZE];
String deviceName = device.getDeviceInfo()
.getNetworkInfo().getHostname();
try {
List<SupportReferenceManifest> supportRims = referenceManifestRepository
.getSupportByManufacturerModel(
device.getDeviceInfo().getHardwareInfo().getManufacturer(),
device.getDeviceInfo().getHardwareInfo().getProductName());
for (SupportReferenceManifest support : supportRims) {
if (support.isBaseSupport()) {
sRim = support;
}
}
eventLog = (EventLogMeasurements) referenceManifestRepository
.findByHexDecHash(sRim.getEventLogHash());
if (sRim == null) {
fwStatus = new AppraisalStatus(FAIL,
String.format("Firmware Quote validation failed: "
+ "No associated Support RIM file "
+ "could be found for %s",
deviceName));
} else if (eventLog == null) {
fwStatus = new AppraisalStatus(FAIL,
String.format("Firmware Quote validation failed: "
+ "No associated Client Log file "
+ "could be found for %s",
deviceName));
} else {
baseline = sRim.getExpectedPCRList();
String[] storedPcrs = eventLog.getExpectedPCRList();
PcrValidator pcrValidator = new PcrValidator(baseline);
// grab the quote
byte[] hash = device.getDeviceInfo().getTpmInfo().getTpmQuoteHash();
if (pcrValidator.validateQuote(hash, storedPcrs, getPolicySettings())) {
level = Level.INFO;
fwStatus = new AppraisalStatus(PASS,
SupplyChainCredentialValidator.FIRMWARE_VALID);
fwStatus.setMessage("Firmware validation of TPM Quote successful.");
} else {
fwStatus.setMessage("Firmware validation of TPM Quote failed."
+ "\nPCR hash and Quote hash do not match.");
}
eventLog.setOverallValidationResult(fwStatus.getAppStatus());
this.referenceManifestRepository.save(eventLog);
}
} catch (Exception ex) {
log.error(ex);
}
quoteScv = ValidationService.buildValidationRecord(SupplyChainValidation
.ValidationType.FIRMWARE,
fwStatus.getAppStatus(), fwStatus.getMessage(), eventLog, level);
// Generate validation summary, save it, and return it.
List<SupplyChainValidation> validations = new ArrayList<>();
SupplyChainValidationSummary previous
= this.supplyChainValidationSummaryRepository.findByDevice(deviceName);
for (SupplyChainValidation scv : previous.getValidations()) {
if (scv.getValidationType() != SupplyChainValidation.ValidationType.FIRMWARE) {
validations.add(ValidationService.buildValidationRecord(scv.getValidationType(),
scv.getValidationResult(), scv.getMessage(),
scv.getCertificatesUsed().get(0), Level.INFO));
}
}
validations.add(quoteScv);
previous.archive();
supplyChainValidationSummaryRepository.save(previous);
summary = new SupplyChainValidationSummary(device, validations);
// try removing the supply chain validation as well and resaving that
try {
supplyChainValidationSummaryRepository.save(summary);
} catch (DBManagerException dbEx) {
log.error("Failed to save Supply Chain Summary", dbEx);
}
}
return summary;
}
/**
* Allows other service access to the policy information.
* @return supply chain policy
* Helper function to get a fresh load of the default policy from the DB.
*
* @return The default Supply Chain Policy
*/
// SupplyChainPolicy getPolicy();
private PolicySettings getPolicySettings() {
PolicySettings defaultSettings = this.policyRepository.findByName("Default");
if (defaultSettings == null) {
defaultSettings = new PolicySettings("Default", "Settings are configured for no validation flags set.");
}
return defaultSettings;
}
}

View File

@ -1,377 +0,0 @@
package hirs.attestationca.persist.service;
import hirs.utils.ArchivableEntity;
import hirs.attestationca.persist.DBManagerException;
import hirs.attestationca.persist.entity.manager.CACredentialRepository;
import hirs.attestationca.persist.entity.manager.CertificateRepository;
import hirs.attestationca.persist.entity.manager.ComponentResultRepository;
import hirs.attestationca.persist.entity.manager.PolicyRepository;
import hirs.attestationca.persist.entity.manager.ReferenceDigestValueRepository;
import hirs.attestationca.persist.entity.manager.ReferenceManifestRepository;
import hirs.attestationca.persist.entity.manager.SupplyChainValidationSummaryRepository;
import hirs.utils.Certificate;
import hirs.attestationca.persist.entity.userdefined.Device;
import hirs.attestationca.persist.entity.userdefined.PolicySettings;
import hirs.attestationca.persist.entity.userdefined.SupplyChainValidation;
import hirs.attestationca.persist.entity.userdefined.SupplyChainValidationSummary;
import hirs.utils.CertificateAuthorityCredential;
import hirs.attestationca.persist.entity.userdefined.certificate.EndorsementCredential;
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
import hirs.attestationca.persist.entity.userdefined.record.TPMMeasurementRecord;
import hirs.attestationca.persist.entity.userdefined.rim.EventLogMeasurements;
import hirs.attestationca.persist.entity.userdefined.rim.SupportReferenceManifest;
import hirs.attestationca.persist.enums.AppraisalStatus;
import hirs.attestationca.persist.validation.CredentialValidator;
import hirs.attestationca.persist.validation.PcrValidator;
import hirs.attestationca.persist.validation.SupplyChainCredentialValidator;
import hirs.utils.BouncyCastleUtils;
import lombok.extern.log4j.Log4j2;
import org.bouncycastle.util.encoders.Hex;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.apache.logging.log4j.Level;
import static hirs.attestationca.persist.enums.AppraisalStatus.Status.FAIL;
import static hirs.attestationca.persist.enums.AppraisalStatus.Status.PASS;
@Log4j2
@Service
public class SupplyChainValidationServiceImpl implements SupplyChainValidationService {
private CACredentialRepository caCredentialRepository;
private PolicyRepository policyRepository;
private ReferenceManifestRepository referenceManifestRepository;
private ReferenceDigestValueRepository referenceDigestValueRepository;
private ComponentResultRepository componentResultRepository;
private CertificateRepository certificateRepository;
private CredentialValidator supplyChainCredentialValidator;
private SupplyChainValidationSummaryRepository supplyChainValidationSummaryRepository;
/**
* Constructor to set just the CertificateRepository, so that cert chain validating
* methods can be called from outside classes.
*
* @param certificateRepository the cert repository
*/
public SupplyChainValidationServiceImpl(final CertificateRepository certificateRepository) {
this.certificateRepository = certificateRepository;
}
/**
* Constructor.
*
* @param caCredentialRepository ca credential repository
* @param policyRepository the policy manager
* @param certificateRepository the cert manager
* @param componentResultRepository the comp result manager
* @param referenceManifestRepository the RIM manager
* @param supplyChainValidationSummaryRepository the summary manager
* @param supplyChainCredentialValidator the credential validator
* @param referenceDigestValueRepository the even manager
*/
@Autowired
@SuppressWarnings("ParameterNumberCheck")
public SupplyChainValidationServiceImpl(
final CACredentialRepository caCredentialRepository,
final PolicyRepository policyRepository,
final CertificateRepository certificateRepository,
final ComponentResultRepository componentResultRepository,
final ReferenceManifestRepository referenceManifestRepository,
final SupplyChainValidationSummaryRepository supplyChainValidationSummaryRepository,
final CredentialValidator supplyChainCredentialValidator,
final ReferenceDigestValueRepository referenceDigestValueRepository) {
this.caCredentialRepository = caCredentialRepository;
this.policyRepository = policyRepository;
this.certificateRepository = certificateRepository;
this.componentResultRepository = componentResultRepository;
this.referenceManifestRepository = referenceManifestRepository;
this.supplyChainValidationSummaryRepository = supplyChainValidationSummaryRepository;
this.supplyChainCredentialValidator = supplyChainCredentialValidator;
this.referenceDigestValueRepository = referenceDigestValueRepository;
}
@Override
public SupplyChainValidationSummary validateSupplyChain(final EndorsementCredential ec,
final List<PlatformCredential> pc,
final Device device) {
return null;
}
/**
* A supplemental method that handles validating just the quote post main validation.
*
* @param device the associated device.
* @return True if validation is successful, false otherwise.
*/
@Override
public SupplyChainValidationSummary validateQuote(final Device device) {
SupplyChainValidation quoteScv = null;
SupplyChainValidationSummary summary = null;
Level level = Level.ERROR;
AppraisalStatus fwStatus = new AppraisalStatus(FAIL,
"Unknown exception caught during quote validation.");
SupportReferenceManifest sRim = null;
EventLogMeasurements eventLog = null;
// check if the policy is enabled
if (getPolicySettings().isFirmwareValidationEnabled()) {
String[] baseline = new String[Integer.SIZE];
String deviceName = device.getDeviceInfo()
.getNetworkInfo().getHostname();
try {
List<SupportReferenceManifest> supportRims = referenceManifestRepository.getSupportByManufacturerModel(
device.getDeviceInfo().getHardwareInfo().getManufacturer(),
device.getDeviceInfo().getHardwareInfo().getProductName());
for (SupportReferenceManifest support : supportRims) {
if (support.isBaseSupport()) {
sRim = support;
}
}
eventLog = (EventLogMeasurements) referenceManifestRepository
.findByHexDecHash(sRim.getEventLogHash());
if (sRim == null) {
fwStatus = new AppraisalStatus(FAIL,
String.format("Firmware Quote validation failed: "
+ "No associated Support RIM file "
+ "could be found for %s",
deviceName));
} else if (eventLog == null) {
fwStatus = new AppraisalStatus(FAIL,
String.format("Firmware Quote validation failed: "
+ "No associated Client Log file "
+ "could be found for %s",
deviceName));
} else {
baseline = sRim.getExpectedPCRList();
String[] storedPcrs = eventLog.getExpectedPCRList();
PcrValidator pcrValidator = new PcrValidator(baseline);
// grab the quote
byte[] hash = device.getDeviceInfo().getTpmInfo().getTpmQuoteHash();
if (pcrValidator.validateQuote(hash, storedPcrs, getPolicySettings())) {
level = Level.INFO;
fwStatus = new AppraisalStatus(PASS,
SupplyChainCredentialValidator.FIRMWARE_VALID);
fwStatus.setMessage("Firmware validation of TPM Quote successful.");
} else {
fwStatus.setMessage("Firmware validation of TPM Quote failed."
+ "\nPCR hash and Quote hash do not match.");
}
eventLog.setOverallValidationResult(fwStatus.getAppStatus());
this.referenceManifestRepository.save(eventLog);
}
} catch (Exception ex) {
log.error(ex);
}
quoteScv = buildValidationRecord(SupplyChainValidation
.ValidationType.FIRMWARE,
fwStatus.getAppStatus(), fwStatus.getMessage(), eventLog, level);
// Generate validation summary, save it, and return it.
List<SupplyChainValidation> validations = new ArrayList<>();
SupplyChainValidationSummary previous
= this.supplyChainValidationSummaryRepository.findByDevice(deviceName);
for (SupplyChainValidation scv : previous.getValidations()) {
if (scv.getValidationType() != SupplyChainValidation.ValidationType.FIRMWARE) {
validations.add(buildValidationRecord(scv.getValidationType(),
scv.getValidationResult(), scv.getMessage(),
scv.getCertificatesUsed().get(0), Level.INFO));
}
}
validations.add(quoteScv);
previous.archive();
supplyChainValidationSummaryRepository.save(previous);
summary = new SupplyChainValidationSummary(device, validations);
// try removing the supply chain validation as well and resaving that
try {
supplyChainValidationSummaryRepository.save(summary);
} catch (DBManagerException dbEx) {
log.error("Failed to save Supply Chain Summary", dbEx);
}
}
return summary;
}
/**
* Creates a supply chain validation record and logs the validation message
* at the specified log level.
*
* @param validationType the type of validation
* @param result the appraisal status
* @param message the validation message to include in the summary and log
* @param archivableEntity the archivableEntity associated with the
* validation
* @param logLevel the log level
* @return a SupplyChainValidation
*/
private SupplyChainValidation buildValidationRecord(
final SupplyChainValidation.ValidationType validationType,
final AppraisalStatus.Status result, final String message,
final ArchivableEntity archivableEntity, final Level logLevel) {
List<ArchivableEntity> aeList = new ArrayList<>();
if (archivableEntity != null) {
aeList.add(archivableEntity);
}
log.log(logLevel, message);
return new SupplyChainValidation(validationType, result, aeList, message);
}
/**
* This method is used to retrieve the entire CA chain (up to a trusted
* self-signed certificate) for the given certificate. This method will look
* up CA certificates that have a matching issuer organization as the given
* certificate, and will perform that operation recursively until all
* certificates for all relevant organizations have been retrieved. For that
* reason, the returned set of certificates may be larger than the the
* single trust chain for the queried certificate, but is guaranteed to
* include the trust chain if it exists in this class' CertificateManager.
* Returns the certificate authority credentials in a KeyStore.
*
* @param credential the credential whose CA chain should be retrieved
* @return A keystore containing all relevant CA credentials to the given
* certificate's organization or null if the keystore can't be assembled
*/
public KeyStore getCaChain(final Certificate credential) {
KeyStore caKeyStore = null;
try {
caKeyStore = caCertSetToKeystore(getCaChainRec(credential, Collections.emptySet()));
} catch (KeyStoreException | IOException e) {
log.error("Unable to assemble CA keystore", e);
}
return caKeyStore;
}
/**
* This is a recursive method which is used to retrieve the entire CA chain
* (up to a trusted self-signed certificate) for the given certificate. This
* method will look up CA certificates that have a matching issuer
* organization as the given certificate, and will perform that operation
* recursively until all certificates for all relevant organizations have
* been retrieved. For that reason, the returned set of certificates may be
* larger than the the single trust chain for the queried certificate, but
* is guaranteed to include the trust chain if it exists in this class'
* CertificateManager.
* <p>
* Implementation notes: 1. Queries for CA certs with a subject org matching
* the given (argument's) issuer org 2. Add that org to
* queriedOrganizations, so we don't search for that organization again 3.
* For each returned CA cert, add that cert to the result set, and recurse
* with that as the argument (to go up the chain), if and only if we haven't
* already queried for that organization (which prevents infinite loops on
* certs with an identical subject and issuer org)
*
* @param credential the credential whose CA chain should be retrieved
* @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> previouslyQueriedSubjects) {
CertificateAuthorityCredential skiCA = null;
List<CertificateAuthorityCredential> certAuthsWithMatchingIssuer = new LinkedList<>();
if (credential.getAuthorityKeyIdentifier() != null
&& !credential.getAuthorityKeyIdentifier().isEmpty()) {
byte[] bytes = Hex.decode(credential.getAuthorityKeyIdentifier());
// CYRUS is SKI unique?
skiCA = caCredentialRepository.findBySubjectKeyIdentifier(bytes);
}
if (skiCA == null) {
if (credential.getIssuerSorted() == null
|| credential.getIssuerSorted().isEmpty()) {
certAuthsWithMatchingIssuer = caCredentialRepository.findBySubject(credential.getIssuer());
} else {
//Get certificates by subject organization
certAuthsWithMatchingIssuer = caCredentialRepository.findBySubjectSorted(credential.getIssuerSorted());
}
} else {
certAuthsWithMatchingIssuer.add(skiCA);
}
Set<String> queriedOrganizations = new HashSet<>(previouslyQueriedSubjects);
queriedOrganizations.add(credential.getIssuer());
HashSet<CertificateAuthorityCredential> caCreds = new HashSet<>();
for (CertificateAuthorityCredential cred : certAuthsWithMatchingIssuer) {
caCreds.add(cred);
if (!BouncyCastleUtils.x500NameCompare(cred.getIssuer(),
cred.getSubject())) {
caCreds.addAll(getCaChainRec(cred, queriedOrganizations));
}
}
return caCreds;
}
private KeyStore caCertSetToKeystore(final Set<CertificateAuthorityCredential> certs)
throws KeyStoreException, IOException {
KeyStore keyStore = KeyStore.getInstance("JKS");
try {
keyStore.load(null, "".toCharArray());
for (Certificate cert : certs) {
keyStore.setCertificateEntry(cert.getId().toString(), cert.getX509Certificate());
}
} catch (IOException | CertificateException | NoSuchAlgorithmException e) {
throw new IOException("Could not create and populate keystore", e);
}
return keyStore;
}
private String[] buildStoredPcrs(final String pcrContent, final int algorithmLength) {
// we have a full set of PCR values
String[] pcrSet = pcrContent.split("\\n");
String[] storedPcrs = new String[TPMMeasurementRecord.MAX_PCR_ID + 1];
// we need to scroll through the entire list until we find
// a matching hash length
int offset = 1;
for (int i = 0; i < pcrSet.length; i++) {
if (pcrSet[i].contains("sha")) {
// entered a new set, check size
if (pcrSet[i + offset].split(":")[1].trim().length()
== algorithmLength) {
// found the matching set
for (int j = 0; j <= TPMMeasurementRecord.MAX_PCR_ID; j++) {
storedPcrs[j] = pcrSet[++i].split(":")[1].trim();
}
break;
}
}
}
return storedPcrs;
}
/**
* Helper function to get a fresh load of the default policy from the DB.
*
* @return The default Supply Chain Policy
*/
private PolicySettings getPolicySettings() {
PolicySettings defaultSettings = this.policyRepository.findByName("Default");
if (defaultSettings == null) {
defaultSettings = new PolicySettings("Default", "Settings are configured for no validation flags set.");
}
return defaultSettings;
}
}

View File

@ -0,0 +1,338 @@
package hirs.attestationca.persist.service;
import hirs.attestationca.persist.entity.ArchivableEntity;
import hirs.attestationca.persist.entity.manager.CACredentialRepository;
import hirs.attestationca.persist.entity.manager.CertificateRepository;
import hirs.attestationca.persist.entity.manager.ComponentResultRepository;
import hirs.attestationca.persist.entity.manager.ReferenceDigestValueRepository;
import hirs.attestationca.persist.entity.manager.ReferenceManifestRepository;
import hirs.attestationca.persist.entity.userdefined.Certificate;
import hirs.attestationca.persist.entity.userdefined.Device;
import hirs.attestationca.persist.entity.userdefined.PolicySettings;
import hirs.attestationca.persist.entity.userdefined.SupplyChainValidation;
import hirs.attestationca.persist.entity.userdefined.certificate.CertificateAuthorityCredential;
import hirs.attestationca.persist.entity.userdefined.certificate.ComponentResult;
import hirs.attestationca.persist.entity.userdefined.certificate.EndorsementCredential;
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
import hirs.attestationca.persist.entity.userdefined.report.DeviceInfoReport;
import hirs.attestationca.persist.enums.AppraisalStatus;
import hirs.attestationca.persist.validation.CertificateAttributeScvValidator;
import hirs.attestationca.persist.validation.CredentialValidator;
import hirs.attestationca.persist.validation.FirmwareScvValidator;
import hirs.utils.BouncyCastleUtils;
import lombok.extern.log4j.Log4j2;
import org.apache.logging.log4j.Level;
import org.bouncycastle.util.encoders.Hex;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Log4j2
public class ValidationService {
public static SupplyChainValidation evaluateEndorsementCredentialStatus(
final EndorsementCredential ec,
final CACredentialRepository caCredentialRepository,
final boolean acceptExpiredCerts) {
final SupplyChainValidation.ValidationType validationType
= SupplyChainValidation.ValidationType.ENDORSEMENT_CREDENTIAL;
log.info("Validating endorsement credential");
if (ec == null) {
log.error("No endorsement credential to validate");
return buildValidationRecord(validationType,
AppraisalStatus.Status.FAIL, "Endorsement credential is missing",
null, Level.ERROR);
}
KeyStore ecStore = getCaChain(ec, caCredentialRepository);
AppraisalStatus result = CredentialValidator.
validateEndorsementCredential(ec, ecStore, acceptExpiredCerts);
switch (result.getAppStatus()) {
case PASS:
return buildValidationRecord(validationType, AppraisalStatus.Status.PASS,
result.getMessage(), ec, Level.INFO);
case FAIL:
return buildValidationRecord(validationType, AppraisalStatus.Status.FAIL,
result.getMessage(), ec, Level.WARN);
case ERROR:
default:
return buildValidationRecord(validationType, AppraisalStatus.Status.ERROR,
result.getMessage(), ec, Level.ERROR);
}
}
public static SupplyChainValidation evaluatePlatformCredentialStatus(
final PlatformCredential pc,
final KeyStore trustedCertificateAuthority, final boolean acceptExpiredCerts) {
final SupplyChainValidation.ValidationType validationType
= SupplyChainValidation.ValidationType.PLATFORM_CREDENTIAL;
if (pc == null) {
log.error("No platform credential to validate");
return buildValidationRecord(validationType,
AppraisalStatus.Status.FAIL, "Empty Platform credential", null, Level.ERROR);
}
log.info("Validating Platform Credential");
AppraisalStatus result = CredentialValidator.validatePlatformCredential(pc,
trustedCertificateAuthority, acceptExpiredCerts);
switch (result.getAppStatus()) {
case PASS:
return buildValidationRecord(validationType, AppraisalStatus.Status.PASS,
result.getMessage(), pc, Level.INFO);
case FAIL:
return buildValidationRecord(validationType, AppraisalStatus.Status.FAIL,
result.getMessage(), pc, Level.WARN);
case ERROR:
default:
return buildValidationRecord(validationType, AppraisalStatus.Status.ERROR,
result.getMessage(), pc, Level.ERROR);
}
}
public static SupplyChainValidation evaluatePCAttributesStatus(
final PlatformCredential pc, final DeviceInfoReport deviceInfoReport,
final EndorsementCredential ec,
final CertificateRepository certificateRepository,
final ComponentResultRepository componentResultRepository) {
final SupplyChainValidation.ValidationType validationType
= SupplyChainValidation.ValidationType.PLATFORM_CREDENTIAL_ATTRIBUTES;
if (pc == null) {
log.error("No platform credential to validate");
return buildValidationRecord(validationType,
AppraisalStatus.Status.FAIL, "Platform credential is missing",
null, Level.ERROR);
}
log.info("Validating platform credential attributes");
AppraisalStatus result = CredentialValidator.
validatePlatformCredentialAttributes(pc, deviceInfoReport, ec);
switch (result.getAppStatus()) {
case PASS:
return buildValidationRecord(validationType, AppraisalStatus.Status.PASS,
result.getMessage(), pc, Level.INFO);
case FAIL:
if (!result.getAdditionalInfo().isEmpty()) {
pc.setComponentFailures(result.getAdditionalInfo());
pc.setComponentFailureMessage(result.getMessage());
certificateRepository.save(pc);
for (ComponentResult componentResult
: CertificateAttributeScvValidator.getComponentResultList()) {
componentResultRepository.save(componentResult);
}
}
return buildValidationRecord(validationType, AppraisalStatus.Status.FAIL,
result.getMessage(), pc, Level.WARN);
case ERROR:
default:
return buildValidationRecord(validationType, AppraisalStatus.Status.ERROR,
result.getMessage(), pc, Level.ERROR);
}
}
public static SupplyChainValidation evaluateDeltaAttributesStatus(
final PlatformCredential delta,
final DeviceInfoReport deviceInfoReport,
final PlatformCredential base,
final Map<PlatformCredential, SupplyChainValidation> deltaMapping,
final CertificateRepository certificateRepository) {
final SupplyChainValidation.ValidationType validationType
= SupplyChainValidation.ValidationType.PLATFORM_CREDENTIAL_ATTRIBUTES;
if (delta == null) {
log.error("No delta certificate to validate");
return buildValidationRecord(validationType,
AppraisalStatus.Status.FAIL, "Delta platform certificate is missing",
null, Level.ERROR);
}
log.info("Validating delta platform certificate attributes");
AppraisalStatus result = CertificateAttributeScvValidator.
validateDeltaPlatformCredentialAttributes(delta, deviceInfoReport,
base, deltaMapping);
switch (result.getAppStatus()) {
case PASS:
return buildValidationRecord(validationType, AppraisalStatus.Status.PASS,
result.getMessage(), delta, Level.INFO);
case FAIL:
if (!result.getAdditionalInfo().isEmpty()) {
base.setComponentFailures(result.getAdditionalInfo());
base.setComponentFailureMessage(result.getMessage());
certificateRepository.save(base);
}
// we are adding things to componentFailures
certificateRepository.save(delta);
return buildValidationRecord(validationType, AppraisalStatus.Status.FAIL,
result.getMessage(), delta, Level.WARN);
case ERROR:
default:
return buildValidationRecord(validationType, AppraisalStatus.Status.ERROR,
result.getMessage(), delta, Level.ERROR);
}
}
public static SupplyChainValidation evaluateFirmwareStatus(
final Device device,
final PolicySettings policySettings, final ReferenceManifestRepository rimRepo,
final ReferenceDigestValueRepository rdvRepo,
final CACredentialRepository caRepo) {
final SupplyChainValidation.ValidationType validationType
= SupplyChainValidation.ValidationType.FIRMWARE;
AppraisalStatus result = FirmwareScvValidator.validateFirmware(device, policySettings,
rimRepo, rdvRepo, caRepo);
Level logLevel;
switch (result.getAppStatus()) {
case PASS:
logLevel = Level.INFO;
break;
case FAIL:
logLevel = Level.WARN;
break;
case ERROR:
default:
logLevel = Level.ERROR;
}
return buildValidationRecord(validationType, result.getAppStatus(),
result.getMessage(), null, logLevel);
}
/**
* Creates a supply chain validation record and logs the validation message
* at the specified log level.
*
* @param validationType the type of validation
* @param result the appraisal status
* @param message the validation message to include in the summary and log
* @param archivableEntity the archivableEntity associated with the
* validation
* @param logLevel the log level
* @return a SupplyChainValidation
*/
public static SupplyChainValidation buildValidationRecord(
final SupplyChainValidation.ValidationType validationType,
final AppraisalStatus.Status result, final String message,
final ArchivableEntity archivableEntity, final Level logLevel) {
List<ArchivableEntity> aeList = new ArrayList<>();
if (archivableEntity != null) {
aeList.add(archivableEntity);
}
log.log(logLevel, message);
return new SupplyChainValidation(validationType, result, aeList, message);
}
/**
* This method is used to retrieve the entire CA chain (up to a trusted
* self-signed certificate) for the given certificate. This method will look
* up CA certificates that have a matching issuer organization as the given
* certificate, and will perform that operation recursively until all
* certificates for all relevant organizations have been retrieved. For that
* reason, the returned set of certificates may be larger than the the
* single trust chain for the queried certificate, but is guaranteed to
* include the trust chain if it exists in this class' CertificateManager.
* Returns the certificate authority credentials in a KeyStore.
*
* @param certificate the credential whose CA chain should be retrieved
* @param caCredentialRepository db service to get CA Certs
* @return A keystore containing all relevant CA credentials to the given
* certificate's organization or null if the keystore can't be assembled
*/
public static KeyStore getCaChain(final Certificate certificate,
final CACredentialRepository caCredentialRepository) {
KeyStore caKeyStore = null;
try {
caKeyStore = caCertSetToKeystore(getCaChainRec(certificate, Collections.emptySet(),
caCredentialRepository));
} catch (KeyStoreException | IOException e) {
log.error("Unable to assemble CA keystore", e);
}
return caKeyStore;
}
/**
* This is a recursive method which is used to retrieve the entire CA chain
* (up to a trusted self-signed certificate) for the given certificate. This
* method will look up CA certificates that have a matching issuer
* organization as the given certificate, and will perform that operation
* recursively until all certificates for all relevant organizations have
* been retrieved. For that reason, the returned set of certificates may be
* larger than the the single trust chain for the queried certificate, but
* is guaranteed to include the trust chain if it exists in this class'
* CertificateManager.
* <p>
* Implementation notes: 1. Queries for CA certs with a subject org matching
* the given (argument's) issuer org 2. Add that org to
* queriedOrganizations, so we don't search for that organization again 3.
* For each returned CA cert, add that cert to the result set, and recurse
* with that as the argument (to go up the chain), if and only if we haven't
* already queried for that organization (which prevents infinite loops on
* certs with an identical subject and issuer org)
*
* @param credential the credential whose CA chain should be retrieved
* @param previouslyQueriedSubjects a list of organizations to refrain
* from querying
* @return a Set containing all relevant CA credentials to the given
* certificate's organization
*/
public static Set<CertificateAuthorityCredential> getCaChainRec(
final Certificate credential,
final Set<String> previouslyQueriedSubjects,
final CACredentialRepository caCredentialRepository) {
CertificateAuthorityCredential skiCA = null;
List<CertificateAuthorityCredential> certAuthsWithMatchingIssuer = new LinkedList<>();
if (credential.getAuthorityKeyIdentifier() != null
&& !credential.getAuthorityKeyIdentifier().isEmpty()) {
byte[] bytes = Hex.decode(credential.getAuthorityKeyIdentifier());
skiCA = caCredentialRepository.findBySubjectKeyIdentifier(bytes);
}
if (skiCA == null) {
if (credential.getIssuerSorted() == null
|| credential.getIssuerSorted().isEmpty()) {
certAuthsWithMatchingIssuer = caCredentialRepository.findBySubject(credential.getIssuer());
} else {
//Get certificates by subject organization
certAuthsWithMatchingIssuer = caCredentialRepository.findBySubjectSorted(credential.getIssuerSorted());
}
} else {
certAuthsWithMatchingIssuer.add(skiCA);
}
Set<String> queriedOrganizations = new HashSet<>(previouslyQueriedSubjects);
queriedOrganizations.add(credential.getIssuer());
HashSet<CertificateAuthorityCredential> caCreds = new HashSet<>();
for (CertificateAuthorityCredential cred : certAuthsWithMatchingIssuer) {
caCreds.add(cred);
if (!BouncyCastleUtils.x500NameCompare(cred.getIssuer(),
cred.getSubject())) {
caCreds.addAll(getCaChainRec(cred, queriedOrganizations, caCredentialRepository));
}
}
return caCreds;
}
public static KeyStore caCertSetToKeystore(final Set<CertificateAuthorityCredential> certs)
throws KeyStoreException, IOException {
KeyStore keyStore = KeyStore.getInstance("JKS");
try {
keyStore.load(null, "".toCharArray());
for (Certificate cert : certs) {
keyStore.setCertificateEntry(cert.getId().toString(), cert.getX509Certificate());
}
} catch (IOException | CertificateException | NoSuchAlgorithmException e) {
throw new IOException("Could not create and populate keystore", e);
}
return keyStore;
}
}

View File

@ -1,19 +1,92 @@
package hirs.attestationca.persist.validation;
import hirs.attestationca.persist.entity.userdefined.SupplyChainValidation;
import hirs.attestationca.persist.entity.userdefined.certificate.EndorsementCredential;
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
import hirs.attestationca.persist.entity.userdefined.report.DeviceInfoReport;
import hirs.attestationca.persist.enums.AppraisalStatus;
import lombok.extern.log4j.Log4j2;
import org.bouncycastle.cert.X509AttributeCertificateHolder;
import java.io.IOException;
import java.security.KeyStore;
import java.util.Map;
import java.security.KeyStoreException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate;
import java.util.Date;
import static hirs.attestationca.persist.enums.AppraisalStatus.Status.ERROR;
import static hirs.attestationca.persist.enums.AppraisalStatus.Status.FAIL;
import static hirs.attestationca.persist.enums.AppraisalStatus.Status.PASS;
@Log4j2
public class CredentialValidator extends SupplyChainCredentialValidator {
/**
* Checks if the endorsement credential is valid.
*
* @param ec the endorsement credential to verify.
* @param trustStore trust store holding trusted trusted certificates.
* @param acceptExpired whether or not to accept expired and not yet valid certificates
* as valid.
* @return the result of the validation.
*/
public static AppraisalStatus validateEndorsementCredential(final EndorsementCredential ec,
final KeyStore trustStore,
final boolean acceptExpired) {
final String baseErrorMessage = "Can't validate endorsement credential attributes without ";
String message;
if (ec == null) {
message = baseErrorMessage + "an endorsement credential";
return new AppraisalStatus(FAIL, message);
}
if (trustStore == null) {
message = baseErrorMessage + "a trust store";
return new AppraisalStatus(FAIL, message);
}
boolean keyInStore = false;
try {
keyInStore = trustStore.size() < 1;
} catch (KeyStoreException ksEx) {
log.error(ksEx.getMessage());
}
if (keyInStore) {
message = baseErrorMessage + "keys in the trust store";
return new AppraisalStatus(FAIL, message);
}
try {
X509Certificate verifiableCert = ec.getX509Certificate();
// check validity period, currently acceptExpired will also accept not yet
// valid certificates
if (!acceptExpired) {
verifiableCert.checkValidity();
}
if (verifyCertificate(verifiableCert, trustStore)) {
return new AppraisalStatus(PASS, ENDORSEMENT_VALID);
} else {
return new AppraisalStatus(FAIL, "Endorsement credential does not have a valid "
+ "signature chain in the trust store");
}
} catch (IOException e) {
message = "Couldn't retrieve X509 certificate from endorsement credential";
return new AppraisalStatus(ERROR, message + " " + e.getMessage());
} catch (SupplyChainValidatorException e) {
message = "An error occurred indicating the credential is not valid";
return new AppraisalStatus(ERROR, message + " " + e.getMessage());
} catch (CertificateExpiredException e) {
message = "The endorsement credential is expired";
return new AppraisalStatus(FAIL, message + " " + e.getMessage());
} catch (CertificateNotYetValidException e) {
message = "The endorsement credential is not yet valid";
return new AppraisalStatus(FAIL, message + " " + e.getMessage());
}
}
/**
* A class used to support supply chain validation by performing the actual
* validation of credentials.
*/
public interface CredentialValidator {
/**
* Checks if the platform credential is valid.
*
@ -22,47 +95,106 @@ public interface CredentialValidator {
* @param acceptExpired whether or not to accept expired certificates as valid.
* @return The result of the validation.
*/
AppraisalStatus validatePlatformCredential(PlatformCredential pc,
KeyStore trustStore,
boolean acceptExpired);
public static AppraisalStatus validatePlatformCredential(final PlatformCredential pc,
final KeyStore trustStore,
final boolean acceptExpired) {
final String baseErrorMessage = "Can't validate platform credential without ";
String message;
String certVerifyMsg;
if (pc == null) {
message = baseErrorMessage + "a platform credential";
return new AppraisalStatus(FAIL, message);
}
try {
if (trustStore == null || trustStore.size() == 0) {
message = baseErrorMessage + "an Issuer Cert in the Trust Store";
return new AppraisalStatus(FAIL, message);
}
} catch (KeyStoreException e) {
message = baseErrorMessage + "an initialized trust store";
return new AppraisalStatus(FAIL, message);
}
X509AttributeCertificateHolder attributeCert = null;
try {
attributeCert = pc.getX509AttributeCertificateHolder();
} catch (IOException e) {
message = "Could not retrieve X509 Attribute certificate";
log.error(message, e);
return new AppraisalStatus(FAIL, message + " " + e.getMessage());
}
// check validity period, currently acceptExpired will also accept not yet
// valid certificates
if (!acceptExpired && !pc.isValidOn(new Date())) {
message = "Platform credential has expired";
// if not valid at the current time
log.debug(message);
return new AppraisalStatus(FAIL, message);
}
// verify cert against truststore
try {
certVerifyMsg = verifyCertificate(attributeCert, trustStore);
if (certVerifyMsg.isEmpty()) {
message = PLATFORM_VALID;
log.debug(message);
return new AppraisalStatus(PASS, message);
} else {
message = String.format("Platform credential failed verification%n%s",
certVerifyMsg);
log.debug(message);
return new AppraisalStatus(FAIL, message);
}
} catch (SupplyChainValidatorException scvEx) {
message = "An error occurred indicating the credential is not valid";
log.warn(message, scvEx);
return new AppraisalStatus(FAIL, message + " " + scvEx.getMessage());
}
}
/**
* Checks if the platform credential's attributes are valid.
* @param pc The platform credential to verify.
* @param deviceInfoReport Report containing the serial numbers of the platform to be validated.
* @param ec The endorsement credential supplied from the same identity request as
* the platform credential.
* @return The result of the validation.
*/
AppraisalStatus validatePlatformCredentialAttributes(PlatformCredential pc,
DeviceInfoReport deviceInfoReport,
EndorsementCredential ec);
/**
* Checks if the delta credential's attributes are valid.
* @param delta the delta credential to verify
* @param platformCredential The platform credential to verify.
* @param deviceInfoReport The device info report containing
* serial number of the platform to be validated.
* @param base the base credential from the same identity request
* as the delta credential.
* @param deltaMapping delta certificates associated with the
* delta supply validation.
* @return the result of the validation.
* @param endorsementCredential The endorsement credential supplied from the same
* identity request as the platform credential.
* @return The result of the validation.
*/
AppraisalStatus validateDeltaPlatformCredentialAttributes(PlatformCredential delta,
DeviceInfoReport deviceInfoReport,
PlatformCredential base,
Map<PlatformCredential,
SupplyChainValidation> deltaMapping);
/**
* Checks if the endorsement credential is valid.
*
* @param ec the endorsement credential to verify.
* @param trustStore trust store holding trusted trusted certificates.
* @param acceptExpired whether or not to accept expired certificates as valid.
* @return the result of the validation.
*/
AppraisalStatus validateEndorsementCredential(EndorsementCredential ec,
KeyStore trustStore,
boolean acceptExpired);
}
public static AppraisalStatus validatePlatformCredentialAttributes(
final PlatformCredential platformCredential,
final DeviceInfoReport deviceInfoReport,
final EndorsementCredential endorsementCredential) {
final String baseErrorMessage = "Can't validate platform credential attributes without ";
String message;
if (platformCredential == null) {
message = baseErrorMessage + "a platform credential";
return new AppraisalStatus(FAIL, message);
}
if (deviceInfoReport == null) {
message = baseErrorMessage + "a device info report";
return new AppraisalStatus(FAIL, message);
}
if (endorsementCredential == null) {
message = baseErrorMessage + "an endorsement credential";
return new AppraisalStatus(FAIL, message);
}
// Quick, early check if the platform credential references the endorsement credential
if (!endorsementCredential.getSerialNumber()
.equals(platformCredential.getHolderSerialNumber())) {
message = "Platform Credential holder serial number does not match "
+ "the Endorsement Credential's serial number";
return new AppraisalStatus(FAIL, message);
}
String credentialType = platformCredential.getCredentialType();
if (PlatformCredential.CERTIFICATE_TYPE_2_0.equals(credentialType)) {
return CertificateAttributeScvValidator.validatePlatformCredentialAttributesV2p0(
platformCredential, deviceInfoReport);
}
return CertificateAttributeScvValidator.validatePlatformCredentialAttributesV1p2(
platformCredential, deviceInfoReport);
}
}

View File

@ -0,0 +1,254 @@
package hirs.attestationca.persist.validation;
import hirs.attestationca.persist.entity.manager.CACredentialRepository;
import hirs.attestationca.persist.entity.manager.ReferenceDigestValueRepository;
import hirs.attestationca.persist.entity.manager.ReferenceManifestRepository;
import hirs.attestationca.persist.entity.userdefined.Device;
import hirs.attestationca.persist.entity.userdefined.PolicySettings;
import hirs.attestationca.persist.entity.userdefined.ReferenceManifest;
import hirs.attestationca.persist.entity.userdefined.certificate.CertificateAuthorityCredential;
import hirs.attestationca.persist.entity.userdefined.rim.BaseReferenceManifest;
import hirs.attestationca.persist.entity.userdefined.rim.EventLogMeasurements;
import hirs.attestationca.persist.entity.userdefined.rim.ReferenceDigestValue;
import hirs.attestationca.persist.enums.AppraisalStatus;
import hirs.attestationca.persist.service.ValidationService;
import hirs.utils.SwidResource;
import hirs.utils.tpm.eventlog.TCGEventLog;
import hirs.utils.tpm.eventlog.TpmPcrEvent;
import lombok.extern.log4j.Log4j2;
import java.io.IOException;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import static hirs.attestationca.persist.enums.AppraisalStatus.Status.FAIL;
import static hirs.attestationca.persist.enums.AppraisalStatus.Status.PASS;
@Log4j2
public class FirmwareScvValidator extends SupplyChainCredentialValidator {
private static PcrValidator pcrValidator;
@SuppressWarnings("methodlength")
public static AppraisalStatus validateFirmware(
final Device device, final PolicySettings policySettings,
final ReferenceManifestRepository referenceManifestRepository,
final ReferenceDigestValueRepository referenceDigestValueRepository,
final CACredentialRepository caCredentialRepository) {
boolean passed = true;
String[] baseline = new String[Integer.SIZE];
AppraisalStatus fwStatus = null;
String hostName = device.getDeviceInfo().getNetworkInfo().getHostname();
String manufacturer = device.getDeviceInfo()
.getHardwareInfo().getManufacturer();
ReferenceManifest validationObject;
List<BaseReferenceManifest> baseReferenceManifests = null;
BaseReferenceManifest baseReferenceManifest = null;
ReferenceManifest supportReferenceManifest = null;
EventLogMeasurements measurement = null;
baseReferenceManifests = referenceManifestRepository.findAllBaseRims();
for (BaseReferenceManifest bRim : baseReferenceManifests) {
if (bRim.getDeviceName().equals(hostName)
&& !bRim.isSwidSupplemental() && !bRim.isSwidPatch()) {
baseReferenceManifest = bRim;
}
}
String failedString = "";
if (baseReferenceManifest == null) {
failedString = "Base Reference Integrity Manifest\n";
passed = false;
} else {
measurement = (EventLogMeasurements) referenceManifestRepository.findByHexDecHash(
baseReferenceManifest.getEventLogHash());
if (measurement == null) {
measurement = referenceManifestRepository.byMeasurementDeviceName(
baseReferenceManifest.getDeviceName());
}
}
if (measurement == null) {
failedString += "Bios measurement";
passed = false;
}
validationObject = measurement;
if (passed) {
List<SwidResource> resources =
((BaseReferenceManifest) baseReferenceManifest).getFileResources();
fwStatus = new AppraisalStatus(PASS,
SupplyChainCredentialValidator.FIRMWARE_VALID);
// verify signatures
ReferenceManifestValidator referenceManifestValidator =
new ReferenceManifestValidator();
referenceManifestValidator.setRim(baseReferenceManifest);
//Validate signing cert
List<CertificateAuthorityCredential> allCerts = caCredentialRepository.findAll();
CertificateAuthorityCredential signingCert = null;
for (CertificateAuthorityCredential cert : allCerts) {
signingCert = cert;
KeyStore keyStore = ValidationService.getCaChain(signingCert,
caCredentialRepository);
if (referenceManifestValidator.validateXmlSignature(signingCert)) {
try {
if (!SupplyChainCredentialValidator.verifyCertificate(
signingCert.getX509Certificate(), keyStore)) {
passed = false;
fwStatus = new AppraisalStatus(FAIL,
"Firmware validation failed: invalid certificate path.");
validationObject = baseReferenceManifest;
}
} catch (IOException ioEx) {
log.error("Error getting X509 cert from manager: " + ioEx.getMessage());
} catch (SupplyChainValidatorException scvEx) {
log.error("Error validating cert against keystore: " + scvEx.getMessage());
fwStatus = new AppraisalStatus(FAIL,
"Firmware validation failed: invalid certificate path.");
}
break;
}
}
for (SwidResource swidRes : resources) {
supportReferenceManifest = referenceManifestRepository.findByHexDecHash(
swidRes.getHashValue());
if (supportReferenceManifest != null) {
// Removed the filename check from this if statement
referenceManifestValidator.validateSupportRimHash(
supportReferenceManifest.getRimBytes(), swidRes.getHashValue());
}
}
if (passed && signingCert == null) {
passed = false;
fwStatus = new AppraisalStatus(FAIL,
"Firmware validation failed: signing cert not found.");
}
if (passed && supportReferenceManifest == null) {
fwStatus = new AppraisalStatus(FAIL,
"Support Reference Integrity Manifest can not be found");
passed = false;
}
if (passed && !referenceManifestValidator.isSignatureValid()) {
passed = false;
fwStatus = new AppraisalStatus(FAIL,
"Firmware validation failed: Signature validation "
+ "failed for Base RIM.");
}
if (passed && !referenceManifestValidator.isSupportRimValid()) {
passed = false;
fwStatus = new AppraisalStatus(FAIL,
"Firmware validation failed: Hash validation "
+ "failed for Support RIM.");
}
if (passed) {
TCGEventLog logProcessor;
try {
logProcessor = new TCGEventLog(supportReferenceManifest.getRimBytes());
baseline = logProcessor.getExpectedPCRValues();
} catch (CertificateException cEx) {
log.error(cEx);
} catch (NoSuchAlgorithmException noSaEx) {
log.error(noSaEx);
} catch (IOException ioEx) {
log.error(ioEx);
}
// part 1 of firmware validation check: PCR baseline match
pcrValidator = new PcrValidator(baseline);
if (baseline.length > 0) {
String pcrContent = "";
pcrContent = new String(device.getDeviceInfo().getTpmInfo().getPcrValues());
if (pcrContent.isEmpty()) {
fwStatus = new AppraisalStatus(FAIL,
"Firmware validation failed: Client did not "
+ "provide pcr values.");
log.warn(String.format(
"Firmware validation failed: Client (%s) did not "
+ "provide pcr values.", device.getName()));
} else {
// we have a full set of PCR values
//int algorithmLength = baseline[0].length();
//String[] storedPcrs = buildStoredPcrs(pcrContent, algorithmLength);
//pcrPolicy.validatePcrs(storedPcrs);
// part 2 of firmware validation check: bios measurements
// vs baseline tcg event log
// find the measurement
TCGEventLog tcgMeasurementLog;
LinkedList<TpmPcrEvent> tpmPcrEvents = new LinkedList<>();
List<ReferenceDigestValue> eventValue;
HashMap<String, ReferenceDigestValue> eventValueMap = new HashMap<>();
try {
if (measurement.getDeviceName().equals(hostName)) {
tcgMeasurementLog = new TCGEventLog(measurement.getRimBytes());
eventValue = referenceDigestValueRepository
.findValuesByBaseRimId(baseReferenceManifest.getId());
for (ReferenceDigestValue rdv : eventValue) {
eventValueMap.put(rdv.getDigestValue(), rdv);
}
tpmPcrEvents.addAll(pcrValidator.validateTpmEvents(
tcgMeasurementLog, eventValueMap, policySettings));
}
} catch (CertificateException cEx) {
log.error(cEx);
} catch (NoSuchAlgorithmException noSaEx) {
log.error(noSaEx);
} catch (IOException ioEx) {
log.error(ioEx);
}
if (!tpmPcrEvents.isEmpty()) {
StringBuilder sb = new StringBuilder();
validationObject = measurement;
sb.append(String.format("%d digest(s) were not found:%n",
tpmPcrEvents.size()));
for (TpmPcrEvent tpe : tpmPcrEvents) {
sb.append(String.format("PCR Index %d - %s%n",
tpe.getPcrIndex(),
tpe.getEventTypeStr()));
}
if (fwStatus.getAppStatus().equals(FAIL)) {
fwStatus = new AppraisalStatus(FAIL, String.format("%s%n%s",
fwStatus.getMessage(), sb.toString()));
} else {
fwStatus = new AppraisalStatus(FAIL, sb.toString());
}
}
}
} else {
fwStatus = new AppraisalStatus(FAIL, "The RIM baseline could not be found.");
}
}
EventLogMeasurements eventLog = measurement;
eventLog.setOverallValidationResult(fwStatus.getAppStatus());
referenceManifestRepository.save(eventLog);
} else {
fwStatus = new AppraisalStatus(FAIL, String.format("Firmware Validation failed: "
+ "%s for %s can not be found", failedString, hostName));
if (measurement != null) {
measurement.setOverallValidationResult(fwStatus.getAppStatus());
referenceManifestRepository.save(measurement);
}
}
return fwStatus;
}
}

View File

@ -226,4 +226,30 @@ public class PcrValidator {
return validated;
}
public static String[] buildStoredPcrs(final String pcrContent, final int algorithmLength) {
// we have a full set of PCR values
String[] pcrSet = pcrContent.split("\\n");
String[] storedPcrs = new String[TPMMeasurementRecord.MAX_PCR_ID + 1];
// we need to scroll through the entire list until we find
// a matching hash length
int offset = 1;
for (int i = 0; i < pcrSet.length; i++) {
if (pcrSet[i].contains("sha")) {
// entered a new set, check size
if (pcrSet[i + offset].split(":")[1].trim().length()
== algorithmLength) {
// found the matching set
for (int j = 0; j <= TPMMeasurementRecord.MAX_PCR_ID; j++) {
storedPcrs[j] = pcrSet[++i].split(":")[1].trim();
}
break;
}
}
}
return storedPcrs;
}
}

View File

@ -1,23 +1,46 @@
package hirs.attestationca.persist.validation;
import hirs.attestationca.persist.entity.userdefined.SupplyChainValidation;
import hirs.attestationca.persist.entity.userdefined.certificate.ComponentResult;
import hirs.attestationca.persist.entity.userdefined.certificate.EndorsementCredential;
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
import hirs.attestationca.persist.entity.userdefined.report.DeviceInfoReport;
import hirs.attestationca.persist.enums.AppraisalStatus;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import hirs.attestationca.persist.entity.userdefined.info.ComponentInfo;
import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.cert.CertException;
import org.bouncycastle.cert.X509AttributeCertificateHolder;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.ContentVerifierProvider;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.jcajce.JcaContentVerifierProviderBuilder;
import javax.security.auth.x500.X500Principal;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PublicKey;
import java.security.Security;
import java.security.SignatureException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Log4j2
@NoArgsConstructor
public class SupplyChainCredentialValidator implements CredentialValidator {
public class SupplyChainCredentialValidator {
public static final int NUC_VARIABLE_BIT = 159;
/**
* AppraisalStatus message for a valid endorsement credential appraisal.
*/
@ -39,34 +62,447 @@ public class SupplyChainCredentialValidator implements CredentialValidator {
*/
public static final String FIRMWARE_VALID = "Firmware validated";
private static List<ComponentResult> componentResultList = new LinkedList<>();
/**
* Ensure that BouncyCastle is configured as a javax.security.Security provider, as this
* class expects it to be available.
*/
static {
Security.addProvider(new BouncyCastleProvider());
}
@Override
public AppraisalStatus validatePlatformCredential(final PlatformCredential pc,
final KeyStore trustStore,
final boolean acceptExpired) {
/**
* Attempts to check if the certificate is validated by certificates in a cert chain. The cert
* chain is expected to be stored in a non-ordered KeyStore (trust store). If the signing
* certificate for the target cert is found, but it is an intermediate cert, the validation will
* continue to try to find the signing cert of the intermediate cert. It will continue searching
* until it follows the chain up to a root (self-signed) cert.
*
* @param cert
* certificate to validate
* @param trustStore
* trust store holding trusted root certificates and intermediate certificates
* @return the certificate chain if validation is successful
* @throws SupplyChainValidatorException
* if the verification is not successful
*/
public static String verifyCertificate(final X509AttributeCertificateHolder cert,
final KeyStore trustStore) throws SupplyChainValidatorException {
try {
if (cert == null || trustStore == null) {
throw new SupplyChainValidatorException("Certificate or trust store is null");
} else if (trustStore.size() == 0) {
throw new SupplyChainValidatorException("Truststore is empty");
}
} catch (KeyStoreException e) {
log.error("Error accessing trust store: " + e.getMessage());
}
try {
Set<X509Certificate> trustedCerts = new HashSet<>();
Enumeration<String> alias = trustStore.aliases();
while (alias.hasMoreElements()) {
trustedCerts.add((X509Certificate) trustStore.getCertificate(alias.nextElement()));
}
String certChainValidated = validateCertChain(cert, trustedCerts);
if (!certChainValidated.isEmpty()) {
log.error("Cert chain could not be validated");
}
return certChainValidated;
} catch (KeyStoreException e) {
throw new SupplyChainValidatorException("Error with the trust store", e);
}
}
/**
* Attempts to check if the certificate is validated by certificates in a cert chain. The cert
* chain is expected to be stored in a non-ordered KeyStore (trust store). If the signing
* certificate for the target cert is found, but it is an intermediate cert, the validation will
* continue to try to find the signing cert of the intermediate cert. It will continue searching
* until it follows the chain up to a root (self-signed) cert.
*
* @param cert
* certificate to validate
* @param trustStore
* trust store holding trusted root certificates and intermediate certificates
* @return the certificate chain if validation is successful
* @throws SupplyChainValidatorException
* if the verification is not successful
*/
public static boolean verifyCertificate(final X509Certificate cert,
final KeyStore trustStore) throws SupplyChainValidatorException {
try {
if (cert == null || trustStore == null) {
throw new SupplyChainValidatorException("Certificate or trust store is null");
} else if (trustStore.size() == 0) {
throw new SupplyChainValidatorException("Truststore is empty");
}
} catch (KeyStoreException e) {
log.error("Error accessing trust store: " + e.getMessage());
}
try {
Set<X509Certificate> trustedCerts = new HashSet<>();
Enumeration<String> alias = trustStore.aliases();
while (alias.hasMoreElements()) {
trustedCerts.add((X509Certificate) trustStore.getCertificate(alias.nextElement()));
}
return validateCertChain(cert, trustedCerts).isEmpty();
} catch (KeyStoreException e) {
log.error("Error accessing keystore", e);
throw new SupplyChainValidatorException("Error with the trust store", e);
}
}
/**
* Attempts to check if an attribute certificate is validated by certificates in a cert chain.
* The cert chain is represented as a Set of X509Certificates. If the signing certificate for
* the target cert is found, but it is an intermediate cert, the validation will continue to try
* to find the signing cert of the intermediate cert. It will continue searching until it
* follows the chain up to a root (self-signed) cert.
*
* @param cert
* certificate to validate
* @param additionalCerts
* Set of certs to validate against
* @return String status of the cert chain validation -
* blank if successful, error message otherwise
* @throws SupplyChainValidatorException tried to validate using null certificates
*/
public static String validateCertChain(final X509AttributeCertificateHolder cert,
final Set<X509Certificate> additionalCerts)
throws SupplyChainValidatorException {
if (cert == null || additionalCerts == null) {
throw new SupplyChainValidatorException(
"Certificate or validation certificates are null");
}
final String intCAError = "Intermediate signing cert found, check for CA cert";
String foundRootOfCertChain = "";
X509Certificate nextInChain = null;
do {
for (X509Certificate trustedCert : additionalCerts) {
boolean issuerMatchesSubject = false;
boolean signatureMatchesPublicKey = false;
if (nextInChain != null) {
issuerMatchesSubject = issuerMatchesSubjectDN(nextInChain, trustedCert);
signatureMatchesPublicKey = signatureMatchesPublicKey(nextInChain,
trustedCert);
} else {
issuerMatchesSubject = issuerMatchesSubjectDN(cert, trustedCert);
signatureMatchesPublicKey = signatureMatchesPublicKey(cert, trustedCert);
}
if (issuerMatchesSubject && signatureMatchesPublicKey) {
if (isSelfSigned(trustedCert)) {
log.info("CA Root found.");
return "";
} else {
foundRootOfCertChain = intCAError;
nextInChain = trustedCert;
break;
}
} else {
if (!issuerMatchesSubject) {
foundRootOfCertChain = "Issuer DN does not match Subject DN";
}
if (!signatureMatchesPublicKey) {
foundRootOfCertChain = "Certificate signature failed to verify";
}
}
}
} while (foundRootOfCertChain.equals(intCAError));
log.error(foundRootOfCertChain);
return foundRootOfCertChain;
}
/**
* Attempts to check if a public-key certificate is validated by certificates in a cert chain.
* The cert chain is represented as a Set of X509Certificates. If the signing certificate for
* the target cert is found, but it is an intermediate cert, the validation will continue to try
* to find the signing cert of the intermediate cert. It will continue searching until it
* follows the chain up to a root (self-signed) cert.
*
* @param cert
* certificate to validate
* @param additionalCerts
* Set of certs to validate against
* @return String status of the cert chain validation -
* blank if successful, error message otherwise
* @throws SupplyChainValidatorException tried to validate using null certificates
*/
public static String validateCertChain(final X509Certificate cert,
final Set<X509Certificate> additionalCerts) throws SupplyChainValidatorException {
if (cert == null || additionalCerts == null) {
throw new SupplyChainValidatorException(
"Certificate or validation certificates are null");
}
final String intCAError = "Intermediate signing cert found, check for CA cert";
String foundRootOfCertChain = "";
X509Certificate startOfChain = cert;
do {
for (X509Certificate trustedCert : additionalCerts) {
boolean issuerMatchesSubject = issuerMatchesSubjectDN(startOfChain, trustedCert);
boolean signatureMatchesPublicKey = signatureMatchesPublicKey(startOfChain,
trustedCert);
if (issuerMatchesSubject && signatureMatchesPublicKey) {
if (isSelfSigned(trustedCert)) {
log.info("CA Root found.");
return "";
} else {
foundRootOfCertChain = intCAError;
startOfChain = trustedCert;
break;
}
} else {
if (!issuerMatchesSubject) {
foundRootOfCertChain = "Issuer DN does not match Subject DN";
}
if (!signatureMatchesPublicKey) {
foundRootOfCertChain = "Certificate signature failed to verify";
}
}
}
} while (foundRootOfCertChain.equals(intCAError));
log.warn(foundRootOfCertChain);
return foundRootOfCertChain;
}
/**
* Parses the output from PACCOR's allcomponents.sh script into ComponentInfo objects.
* @param paccorOutput the output from PACCOR's allcomoponents.sh
* @return a list of ComponentInfo objects built from paccorOutput
* @throws java.io.IOException if something goes wrong parsing the JSON
*/
public static List<ComponentInfo> getComponentInfoFromPaccorOutput(final String paccorOutput)
throws IOException {
List<ComponentInfo> componentInfoList = new ArrayList<>();
if (StringUtils.isNotEmpty(paccorOutput)) {
ObjectMapper objectMapper = new ObjectMapper(new JsonFactory());
JsonNode rootNode = objectMapper.readTree(paccorOutput);
Iterator<JsonNode> jsonComponentNodes
= rootNode.findValue("COMPONENTS").elements();
while (jsonComponentNodes.hasNext()) {
JsonNode next = jsonComponentNodes.next();
componentInfoList.add(new ComponentInfo(
getJSONNodeValueAsText(next, "MANUFACTURER"),
getJSONNodeValueAsText(next, "MODEL"),
getJSONNodeValueAsText(next, "SERIAL"),
getJSONNodeValueAsText(next, "REVISION")));
}
}
return componentInfoList;
}
/**
* Parses the output from PACCOR's allcomponents.sh script into ComponentInfo objects.
* @param paccorOutput the output from PACCOR's allcomoponents.sh
* @return a list of ComponentInfo objects built from paccorOutput
* @throws IOException if something goes wrong parsing the JSON
*/
public static List<ComponentInfo> getV2PaccorOutput(
final String paccorOutput) throws IOException {
List<ComponentInfo> ciList = new LinkedList<>();
String manufacturer, model, serial, revision;
String componentClass = Strings.EMPTY;
if (StringUtils.isNotEmpty(paccorOutput)) {
ObjectMapper objectMapper = new ObjectMapper(new JsonFactory());
JsonNode rootNode = objectMapper.readTree(paccorOutput);
Iterator<JsonNode> jsonComponentNodes
= rootNode.findValue("COMPONENTS").elements();
while (jsonComponentNodes.hasNext()) {
JsonNode next = jsonComponentNodes.next();
manufacturer = getJSONNodeValueAsText(next, "MANUFACTURER");
model = getJSONNodeValueAsText(next, "MODEL");
serial = getJSONNodeValueAsText(next, "SERIAL");
revision = getJSONNodeValueAsText(next, "REVISION");
List<JsonNode> compClassNodes = next.findValues("COMPONENTCLASS");
for (JsonNode subNode : compClassNodes) {
componentClass = getJSONNodeValueAsText(subNode,
"COMPONENTCLASSVALUE");
}
ciList.add(new ComponentInfo(manufacturer, model,
serial, revision, componentClass));
}
}
return ciList;
}
private static String getJSONNodeValueAsText(final JsonNode node, final String fieldName) {
if (node.hasNonNull(fieldName)) {
return node.findValue(fieldName).asText();
}
return null;
}
@Override
public AppraisalStatus validatePlatformCredentialAttributes(final PlatformCredential pc,
final DeviceInfoReport deviceInfoReport,
final EndorsementCredential ec) {
return null;
/**
* Checks if the issuer info of an attribute cert matches the supposed signing cert's
* distinguished name.
*
* @param cert
* the attribute certificate with the signature to validate
* @param signingCert
* the certificate with the public key to validate
* @return boolean indicating if the names
* @throws SupplyChainValidatorException tried to validate using null certificates
*/
public static boolean issuerMatchesSubjectDN(final X509AttributeCertificateHolder cert,
final X509Certificate signingCert) throws SupplyChainValidatorException {
if (cert == null || signingCert == null) {
throw new SupplyChainValidatorException("Certificate or signing certificate is null");
}
String signingCertSubjectDN = signingCert.getSubjectX500Principal().getName();
X500Name namedSubjectDN = new X500Name(signingCertSubjectDN);
X500Name issuerDN = cert.getIssuer().getNames()[0];
// equality check ignore DN component ordering
return issuerDN.equals(namedSubjectDN);
}
@Override
public AppraisalStatus validateDeltaPlatformCredentialAttributes(final PlatformCredential delta,
final DeviceInfoReport deviceInfoReport,
final PlatformCredential base,
final Map<PlatformCredential, SupplyChainValidation> deltaMapping) {
return null;
/**
* Checks if the issuer info of a public-key cert matches the supposed signing cert's
* distinguished name.
*
* @param cert
* the public-key certificate with the signature to validate
* @param signingCert
* the certificate with the public key to validate
* @return boolean indicating if the names
* @throws SupplyChainValidatorException tried to validate using null certificates
*/
public static boolean issuerMatchesSubjectDN(final X509Certificate cert,
final X509Certificate signingCert) throws SupplyChainValidatorException {
if (cert == null || signingCert == null) {
throw new SupplyChainValidatorException("Certificate or signing certificate is null");
}
String signingCertSubjectDN = signingCert.getSubjectX500Principal().
getName(X500Principal.RFC1779);
X500Name namedSubjectDN = new X500Name(signingCertSubjectDN);
String certIssuerDN = cert.getIssuerX500Principal().getName();
X500Name namedIssuerDN = new X500Name(certIssuerDN);
// equality check ignore DN component ordering
return namedIssuerDN.equals(namedSubjectDN);
}
@Override
public AppraisalStatus validateEndorsementCredential(final EndorsementCredential ec,
final KeyStore trustStore,
final boolean acceptExpired) {
return null;
/**
* Checks if the signature of an attribute cert is validated against the signing cert's public
* key.
*
* @param cert
* the public-key certificate with the signature to validate
* @param signingCert
* the certificate with the public key to validate
* @return boolean indicating if the validation passed
* @throws SupplyChainValidatorException tried to validate using null certificates
*/
public static boolean signatureMatchesPublicKey(final X509Certificate cert,
final X509Certificate signingCert) throws SupplyChainValidatorException {
if (cert == null || signingCert == null) {
throw new SupplyChainValidatorException("Certificate or signing certificate is null");
}
try {
cert.verify(signingCert.getPublicKey(), BouncyCastleProvider.PROVIDER_NAME);
return true;
} catch (InvalidKeyException e) {
log.info("Incorrect key given to validate this cert's signature");
} catch (CertificateException e) {
log.info("Encoding error while validating this cert's signature");
} catch (NoSuchAlgorithmException e) {
log.info("Unsupported signature algorithm found during validation");
} catch (NoSuchProviderException e) {
log.info("Incorrect provider for cert signature validation");
} catch (SignatureException e) {
log.info(String.format("%s.verify(%s)", cert.getSubjectX500Principal(),
signingCert.getSubjectX500Principal()));
}
return false;
}
/**
* Checks if the signature of a public-key cert is validated against the signing cert's public
* key.
*
* @param cert
* the attribute certificate with the signature to validate
* @param signingCert
* the certificate with the public key to validate
* @return boolean indicating if the validation passed
* @throws SupplyChainValidatorException tried to validate using null certificates
*/
public static boolean signatureMatchesPublicKey(final X509AttributeCertificateHolder cert,
final X509Certificate signingCert) throws SupplyChainValidatorException {
if (signingCert == null) {
throw new SupplyChainValidatorException("Signing certificate is null");
}
return signatureMatchesPublicKey(cert, signingCert.getPublicKey());
}
/**
* Checks if an X509 Attribute Certificate is valid directly against a public key.
*
* @param cert
* the attribute certificate with the signature to validate
* @param signingKey
* the key to use to check the attribute cert
* @return boolean indicating if the validation passed
* @throws SupplyChainValidatorException tried to validate using null certificates
*/
public static boolean signatureMatchesPublicKey(final X509AttributeCertificateHolder cert,
final PublicKey signingKey) throws SupplyChainValidatorException {
if (cert == null || signingKey == null) {
throw new SupplyChainValidatorException("Certificate or signing certificate is null");
}
ContentVerifierProvider contentVerifierProvider;
try {
contentVerifierProvider =
new JcaContentVerifierProviderBuilder().setProvider("BC").build(signingKey);
return cert.isSignatureValid(contentVerifierProvider);
} catch (OperatorCreationException | CertException e) {
log.info("Exception thrown while verifying certificate", e);
log.info(String.format("%s.isSignatureValid(%s)", cert.getSerialNumber(),
signingKey.getFormat()));
return false;
}
}
/**
* Checks whether given X.509 public-key certificate is self-signed. If the cert can be
* verified using its own public key, that means it was self-signed.
*
* @param cert
* X.509 Certificate
* @return boolean indicating if the cert was self-signed
*/
private static boolean isSelfSigned(final X509Certificate cert)
throws SupplyChainValidatorException {
if (cert == null) {
throw new SupplyChainValidatorException("Certificate is null");
}
try {
PublicKey key = cert.getPublicKey();
cert.verify(key);
return true;
} catch (SignatureException | InvalidKeyException e) {
return false;
} catch (CertificateException | NoSuchAlgorithmException | NoSuchProviderException e) {
log.error("Exception occurred while checking if cert is self-signed", e);
return false;
}
}
}

View File

@ -0,0 +1,605 @@
package hirs.attestationca.persist.entity.userdefined;
import hirs.attestationca.persist.entity.ArchivableEntity;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.NoSuchProviderException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.List;
import hirs.attestationca.persist.entity.userdefined.certificate.*;
import org.bouncycastle.cert.X509AttributeCertificateHolder;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
/**
* This class tests functionality of the {@link Certificate} class.
*/
public class CertificateTest {
/**
* Location of a test (fake) root CA certificate.
*/
public static final String FAKE_ROOT_CA_FILE = "/certificates/fakeRootCA.cer";
/**
* Location of a test (fake) Intel intermediate CA certificate.
*/
public static final String FAKE_INTEL_INT_CA_FILE =
"/certificates/fakeIntelIntermediateCA.cer";
/**
* Location of a test (fake) Intel intermediate CA certificate.
*/
public static final String INTEL_INT_CA_FILE =
"/validation/platform_credentials/intel_chain/root/intermediate2.cer";
/**
* Location of a test (fake) SGI intermediate CA certificate.
*/
public static final String FAKE_SGI_INT_CA_FILE = "/certificates/fakeSGIIntermediateCA.cer";
/**
* Location of another test self-signed certificate.
*/
public static final String ANOTHER_SELF_SIGNED_FILE =
"/certificates/fakeSelfSigned.cer";
/**
* Location of the NUC EC.
*/
public static final String STM_NUC1_EC = "/certificates/nuc-1/tpmcert.pem";
/**
* Location of the ST Micro Intermediate 02 CA certificate.
*/
public static final String STM_INT_02_CA = "/certificates/stMicroCaCerts/stmtpmekint02.crt";
/**
* Location of the ST Micro Root CA certificate.
*/
public static final String STM_ROOT_CA = "/certificates/stMicroCaCerts/stmtpmekroot.crt";
/**
* Location of the GlobalSign Root CA certificate.
*/
public static final String GS_ROOT_CA = "/certificates/stMicroCaCerts/gstpmroot.crt";
/**
* Hex-encoded subject key identifier for the FAKE_ROOT_CA_FILE.
*/
public static final String FAKE_ROOT_CA_SUBJECT_KEY_IDENTIFIER_HEX =
"58ec313a1699f94c1c8c4e2c6412402b258f0177";
/**
* Location of a test STM endorsement credential.
*/
public static final String TEST_EC = "/certificates/ab21ccf2-tpmcert.pem";
/**
* Location of a test client cert.
*/
public static final String ISSUED_CLIENT_CERT =
"/tpm/sample_identity_cert.cer";
private static final String INT_CA_CERT02 = "/certificates/fakestmtpmekint02.pem";
private static final String RDN_COMMA_SEPARATED =
"CN=STM TPM EK Intermediate CA 02, O=STMicroelectronics NV, C=CH";
private static final String RDN_MULTIVALUE =
"CN=Nuvoton TPM Root CA 2010+O=Nuvoton Technology Corporation+C=TW";
private static final String RDN_COMMA_SEPARATED_ORGANIZATION = "STMicroelectronics NV";
private static final String RDN_MULTIVALUE_ORGANIZATION = "Nuvoton Technology Corporation";
private static final String EK_CERT_WITH_PADDED_BYTES =
"/certificates/ek_cert_with_padded_bytes.cer";
/**
* Tests that a certificate can be constructed from a byte array.
*
* @throws IOException if there is a problem reading the cert file into a byte array
* @throws URISyntaxException if there is a problem constructing the URI
*/
@Test
public void testConstructCertFromByteArray() throws IOException, URISyntaxException {
Certificate certificate = new CertificateAuthorityCredential(
Files.readAllBytes(
Paths.get(this.getClass().getResource(FAKE_ROOT_CA_FILE).toURI())
)
);
assertEquals(
certificate.getX509Certificate().getIssuerDN().getName(),
"CN=Fake Root CA"
);
}
/**
* Ensure that a Certificate cannot be created from a null byte array.
*
* @throws IOException if the certificate could not be constructed properly
* @throws CertificateException if there is a problem de/serializing the certificate
*/
@Test
public void testConstructCertFromNullByteArray()
throws IOException, CertificateException {
assertThrows(IllegalArgumentException.class, () ->
new CertificateAuthorityCredential((byte[]) null));
}
/**
* Ensure that a Certificate cannot be created from an empty byte array.
*
* @throws IOException if the certificate could not be constructed properly
* @throws CertificateException if there is a problem de/serializing the certificate
*/
@Test
public void testConstructCertFromEmptyByteArray()
throws IOException, CertificateException {
assertThrows(IllegalArgumentException.class, () ->
new CertificateAuthorityCredential(new byte[]{}));
}
/**
* Tests that a certificate can be constructed from a path.
*
* @throws IOException if there is a problem reading the cert file at the given path
* @throws URISyntaxException if there is a problem constructing the URI
*/
@Test
public void testConstructCertFromPath() throws URISyntaxException, IOException {
Certificate certificate = new CertificateAuthorityCredential(
Paths.get(this.getClass().getResource(FAKE_ROOT_CA_FILE).toURI())
);
assertEquals(
certificate.getX509Certificate().getIssuerDN().getName(),
"CN=Fake Root CA"
);
}
/**
* Tests that a certificate cannot be constructed from a null path.
*
* @throws IOException if there is a problem reading the cert file at the given path
* @throws URISyntaxException if there is a problem constructing the URI
*/
@Test
public void testConstructCertFromNullPath() throws URISyntaxException, IOException {
assertThrows(IllegalArgumentException.class, () ->
new CertificateAuthorityCredential((Path) null));
}
/**
* Tests that Certificate correctly reports whether a certificate is a regular X509 cert or
* an X509 attribute certificate.
*
* @throws IOException if there is a problem reading the cert file at the given path
*/
@Test
public void testGetCertificateType() throws IOException {
assertEquals(getTestCertificate(FAKE_ROOT_CA_FILE).getCertificateType(),
Certificate.CertificateType.X509_CERTIFICATE);
assertNotEquals(getTestCertificate(FAKE_ROOT_CA_FILE).getCertificateType(),
Certificate.CertificateType.ATTRIBUTE_CERTIFICATE);
assertNotEquals(getTestCertificate(
PlatformCredential.class,
PlatformCredentialTest.TEST_PLATFORM_CERT_3).getCertificateType(),
Certificate.CertificateType.X509_CERTIFICATE);
assertEquals(getTestCertificate(
PlatformCredential.class,
PlatformCredentialTest.TEST_PLATFORM_CERT_3).getCertificateType(),
Certificate.CertificateType.ATTRIBUTE_CERTIFICATE);
}
/**
* Ensures a certificate can be parsed from a PEM file.
* Tests both standard and attribute certificate headers.
*
* @throws IOException if there is a problem reading the test certificate
*/
@Test
public void testImportPem() throws IOException {
Certificate platformCredential = getTestCertificate(
PlatformCredential.class, PlatformCredentialTest.TEST_PLATFORM_CERT_4
);
assertEquals(platformCredential.getCertificateType(),
Certificate.CertificateType.ATTRIBUTE_CERTIFICATE);
assertEquals(
((PlatformCredential) platformCredential).getPlatformSerial(),
"GETY421001GV"
);
platformCredential = getTestCertificate(
PlatformCredential.class, PlatformCredentialTest.TEST_PLATFORM_CERT_5
);
assertEquals(platformCredential.getCertificateType(),
Certificate.CertificateType.ATTRIBUTE_CERTIFICATE);
assertEquals(
((PlatformCredential) platformCredential).getPlatformSerial(),
"GETY42100160"
);
}
/**
* Tests that Certificate correctly parses out standard fields from an X509 Certificate.
*
* @throws IOException if there is a problem reading the cert file at the given path
*/
@Test
public void testX509CertificateParsing() throws IOException {
Certificate rootCert = getTestCertificate(FAKE_ROOT_CA_FILE);
X509Certificate certificate = readX509Certificate(FAKE_ROOT_CA_FILE);
assertEquals(rootCert.getSerialNumber(), certificate.getSerialNumber());
assertEquals(rootCert.getIssuer(),
certificate.getIssuerX500Principal().getName());
assertEquals(rootCert.getSubject(),
certificate.getSubjectX500Principal().getName());
assertArrayEquals(rootCert.getEncodedPublicKey(),
certificate.getPublicKey().getEncoded());
assertArrayEquals(rootCert.getSignature(), certificate.getSignature());
assertEquals(rootCert.getBeginValidity(), certificate.getNotBefore());
assertEquals(rootCert.getEndValidity(), certificate.getNotAfter());
}
/**
* Tests that Certificate correctly parses out non standard fields from an X509 Certificate.
*
* @throws IOException if there is a problem reading the cert file at the given path
*/
@Test
public void testX509CertificateParsingExtended() throws IOException {
Certificate rootCert = getTestCertificate(INTEL_INT_CA_FILE);
assertEquals(rootCert.getAuthorityInfoAccess(),
"https://trustedservices.intel.com/"
+ "content/TSC/certs/TSC_SS_RootCA_Certificate.cer\n");
assertEquals(rootCert.getAuthorityKeyIdentifier(),
"b56f72cdfd66ce839e1fdb40498f07291f5b99b7");
}
/**
* Tests that Certificate correctly parses out standard fields from an X509 attribute
* certificate.
*
* @throws IOException if there is a problem reading the cert file at the given path
* @throws URISyntaxException if there is a problem constructing the file's URI
*/
@Test
public void testX509AttributeCertificateParsing() throws IOException, URISyntaxException {
Certificate platformCert = getTestCertificate(
PlatformCredential.class,
PlatformCredentialTest.TEST_PLATFORM_CERT_3
);
X509AttributeCertificateHolder attrCertHolder = new X509AttributeCertificateHolder(
Files.readAllBytes(Paths.get(this.getClass().getResource(
PlatformCredentialTest.TEST_PLATFORM_CERT_3
).toURI()))
);
assertEquals(
platformCert.getSerialNumber(),
attrCertHolder.getSerialNumber()
);
assertEquals(
platformCert.getIssuer(),
attrCertHolder.getIssuer().getNames()[0].toString()
);
assertEquals(platformCert.getSubject(), null);
assertArrayEquals(platformCert.getEncodedPublicKey(), null);
assertArrayEquals(platformCert.getSignature(), attrCertHolder.getSignature());
assertEquals(platformCert.getBeginValidity(), attrCertHolder.getNotBefore());
assertEquals(platformCert.getEndValidity(), attrCertHolder.getNotAfter());
}
/**
* Tests that Certificate correctly parses out non-standard fields from an X509 attribute
* certificate.
*
* @throws IOException if there is a problem reading the cert file at the given path
* @throws URISyntaxException if there is a problem constructing the file's URI
*/
@Test
public void testX509AttributeCertificateParsingExtended()
throws IOException, URISyntaxException {
Certificate platformCert = getTestCertificate(
PlatformCredential.class, PlatformCredentialTest.TEST_PLATFORM_CERT_6);
assertEquals(platformCert.getAuthorityInfoAccess(),
"https://trustedservices.intel.com/"
+ "content/TSC/certs/TSC_IssuingCAIKGF_TEST.cer\n");
assertEquals(platformCert.getAuthorityKeyIdentifier(),
"a5ecc6c07da02c6af8764d4e5c16483610a0b040");
}
/**
* Tests that Certificate correctly trims out additional padding from a given certificate.
*
* @throws IOException if there is a problem reading the cert file at the given path
* @throws URISyntaxException if there is a problem constructing the file's URI
*/
@Test
public void testCertificateTrim() throws IOException, URISyntaxException {
byte[] rawFileBytes = Files.readAllBytes(Paths.get(CertificateTest.class
.getResource(EK_CERT_WITH_PADDED_BYTES).toURI()));
byte[] expectedCertBytes = Arrays.copyOfRange(rawFileBytes, 0, 908);
Certificate ekCert = getTestCertificate(EndorsementCredential.class,
EK_CERT_WITH_PADDED_BYTES);
assertEquals(ekCert.getSerialNumber(), new BigInteger("16842032579184247954"));
assertEquals(ekCert.getIssuer(),
"CN=Nuvoton TPM Root CA 2010+O=Nuvoton Technology Corporation+C=TW");
assertEquals(ekCert.getSubject(), "");
assertArrayEquals(ekCert.getRawBytes(), expectedCertBytes);
}
/**
* Tests that Certificate correctly throws IllegalArgumentException when no length field is
* found in the provided byte array.
*
* @throws IOException if there is a problem reading the cert file at the given path
* @throws URISyntaxException if there is a problem constructing the file's URI
*/
@Test
public void testCertificateTrimThrowsWhenNoLengthFieldFound() throws IOException,
URISyntaxException {
byte[] rawFileBytes = Files.readAllBytes(Paths.get(CertificateTest.class
.getResource(EK_CERT_WITH_PADDED_BYTES).toURI()));
assertThrows(IllegalArgumentException.class, () ->
new EndorsementCredential(Arrays.copyOfRange(rawFileBytes, 0, 2)),
".* No certificate length field could be found\\.");
}
/**
* Tests that Certificate correctly throws IllegalArgumentException when the byte array only
* contains a header for an ASN.1 Sequence.
*
* @throws IOException if there is a problem reading the cert file at the given path
* @throws URISyntaxException if there is a problem constructing the file's URI
*/
@Test
public void testCertificateTrimThrowsWhenOnlyASN1Sequence() throws IOException,
URISyntaxException {
byte[] rawFileBytes = Files.readAllBytes(Paths.get(CertificateTest.class
.getResource(EK_CERT_WITH_PADDED_BYTES).toURI()));
assertThrows(IllegalArgumentException.class, () ->
new EndorsementCredential(Arrays.copyOfRange(rawFileBytes, 0, 4)),
".* Certificate is nothing more than ASN.1 Sequence\\\\.");
}
/**
* Tests that Certificate correctly throws IllegalArgumentException when the provided
* Certificate has a length that extends beyond the byte array as a whole.
*
* @throws IOException if there is a problem reading the cert file at the given path
* @throws URISyntaxException if there is a problem constructing the file's URI
*/
@Test
public void testCertificateTrimThrowsWhenLengthIsTooLarge() throws IOException,
URISyntaxException {
byte[] rawFileBytes = Files.readAllBytes(Paths.get(CertificateTest.class
.getResource(EK_CERT_WITH_PADDED_BYTES).toURI()));
assertThrows(IllegalArgumentException.class, () ->
new EndorsementCredential(Arrays.copyOfRange(rawFileBytes, 0, 42)),
".* Value of certificate length field extends beyond"
+ " length of provided certificate\\.");
}
/**
* Tests that the equals method on {@link Certificate} works as expected.
*
* @throws IOException if the certificate could not be constructed properly
* @throws CertificateException if there is a problem with the KeyStore or de/serializing the
* certificate
* @throws URISyntaxException if there is a problem constructing the path to the certificate
*/
@Test
public void testEquals() throws CertificateException, IOException, URISyntaxException {
assertEquals(
getTestCertificate(FAKE_ROOT_CA_FILE),
getTestCertificate(FAKE_ROOT_CA_FILE)
);
assertEquals(
new CertificateAuthorityCredential(
Paths.get(this.getClass().getResource(FAKE_ROOT_CA_FILE).toURI())
),
new CertificateAuthorityCredential(
Files.readAllBytes(
Paths.get(this.getClass().getResource(FAKE_ROOT_CA_FILE).toURI())
)
)
);
assertNotEquals(
getTestCertificate(CertificateAuthorityCredential.class, FAKE_ROOT_CA_FILE),
getTestCertificate(CertificateAuthorityCredential.class, FAKE_INTEL_INT_CA_FILE)
);
assertNotEquals(
getTestCertificate(CertificateAuthorityCredential.class, FAKE_ROOT_CA_FILE),
getTestCertificate(ConformanceCredential.class, FAKE_ROOT_CA_FILE)
);
assertNotEquals(
getTestCertificate(CertificateAuthorityCredential.class, FAKE_ROOT_CA_FILE),
null
);
}
/**
* Tests that the isIssuer method on {@link Certificate} works as expected.
*
* @throws IOException if the certificate could not be constructed properly
* @throws CertificateException if there is a problem with the KeyStore or de/serializing the
* certificate
* @throws NoSuchProviderException if the Bouncy Castle security provider is unavailable
* @throws URISyntaxException if there is a problem constructing the path to the certificate
*/
@Test
public void testIsIssuer() throws CertificateException, IOException, NoSuchProviderException,
URISyntaxException {
Certificate issuerCert = getTestCertificate(FAKE_ROOT_CA_FILE);
Certificate cert = getTestCertificate(INT_CA_CERT02);
assertEquals(issuerCert.isIssuer(cert), "Certificate signature failed to verify");
assertTrue(cert.isIssuer(issuerCert).isEmpty());
}
/**
* Tests that the hashCode method on {@link Certificate} works as expected.
*
* @throws IOException if the certificate could not be constructed properly
* @throws CertificateException if there is a problem with the KeyStore or de/serializing the
* certificate
* @throws URISyntaxException if there is a problem constructing the path to the certificate
*/
@Test
public void testHashCode() throws CertificateException, IOException, URISyntaxException {
assertEquals(
getTestCertificate(FAKE_ROOT_CA_FILE).hashCode(),
getTestCertificate(FAKE_ROOT_CA_FILE).hashCode()
);
assertEquals(
new CertificateAuthorityCredential(
Paths.get(this.getClass().getResource(FAKE_ROOT_CA_FILE).toURI())
).hashCode(),
new CertificateAuthorityCredential(
Files.readAllBytes(
Paths.get(this.getClass().getResource(FAKE_ROOT_CA_FILE).toURI())
)
).hashCode()
);
assertNotEquals(
getTestCertificate(
CertificateAuthorityCredential.class, FAKE_ROOT_CA_FILE
).hashCode(),
getTestCertificate(
CertificateAuthorityCredential.class, FAKE_INTEL_INT_CA_FILE
).hashCode()
);
}
/**
* Construct a CertificateAuthorityCredential from the given parameters.
*
* @param filename the location of the certificate to be used
* @return the newly-constructed Certificate
* @throws IOException if there is a problem constructing the test certificate
*/
public static Certificate getTestCertificate(
final String filename) throws IOException {
return getTestCertificate(CertificateAuthorityCredential.class, filename);
}
/**
* Construct a test certificate from the given parameters.
*
* @param <T> the type of Certificate that will be created
* @param certificateClass the class of certificate to generate
* @param filename the location of the certificate to be used
* @return the newly-constructed Certificate
* @throws IOException if there is a problem constructing the test certificate
*/
public static <T extends ArchivableEntity> Certificate getTestCertificate(
final Class<T> certificateClass, final String filename)
throws IOException {
return getTestCertificate(certificateClass, filename, null, null);
}
/**
* Construct a test certificate from the given parameters.
*
* @param <T> the type of Certificate that will be created
* @param certificateClass the class of certificate to generate
* @param filename the location of the certificate to be used
* @param endorsementCredential the endorsement credentials (can be null)
* @param platformCredentials the platform credentials (can be null)
* @return the newly-constructed Certificate
* @throws IOException if there is a problem constructing the test certificate
*/
public static <T extends ArchivableEntity> Certificate getTestCertificate(
final Class<T> certificateClass, final String filename,
final EndorsementCredential endorsementCredential,
final List<PlatformCredential> platformCredentials)
throws IOException {
Path certPath;
try {
certPath = Paths.get(CertificateTest.class.getResource(filename).toURI());
} catch (URISyntaxException e) {
throw new IOException("Could not resolve path URI", e);
}
switch (certificateClass.getSimpleName()) {
case "CertificateAuthorityCredential":
return new CertificateAuthorityCredential(certPath);
case "ConformanceCredential":
return new ConformanceCredential(certPath);
case "EndorsementCredential":
return new EndorsementCredential(certPath);
case "PlatformCredential":
return new PlatformCredential(certPath);
case "IssuedAttestationCertificate":
return new IssuedAttestationCertificate(certPath,
endorsementCredential, platformCredentials);
default:
throw new IllegalArgumentException(
String.format("Unknown certificate class %s", certificateClass.getName())
);
}
}
/**
* Return a list of all test certificates.
*
* @return a list of all test certificates
* @throws IOException if there is a problem deserializing certificates
*/
public static List<ArchivableEntity> getAllTestCertificates() throws IOException {
return Arrays.asList(
getTestCertificate(CertificateAuthorityCredential.class, FAKE_SGI_INT_CA_FILE),
getTestCertificate(CertificateAuthorityCredential.class, FAKE_INTEL_INT_CA_FILE),
getTestCertificate(CertificateAuthorityCredential.class, FAKE_ROOT_CA_FILE)
);
}
private static X509Certificate readX509Certificate(final String resourceName)
throws IOException {
CertificateFactory cf;
try {
cf = CertificateFactory.getInstance("X.509");
} catch (CertificateException e) {
throw new IOException("Cannot get X509 CertificateFactory instance", e);
}
try (FileInputStream certInputStream = new FileInputStream(
Paths.get(CertificateTest.class.getResource(resourceName).toURI()).toFile()
)) {
return (X509Certificate) cf.generateCertificate(certInputStream);
} catch (CertificateException | URISyntaxException e) {
throw new IOException("Cannot read certificate", e);
}
}
}

View File

@ -0,0 +1,121 @@
package hirs.attestationca.persist.entity.userdefined;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import hirs.attestationca.persist.entity.ArchivableEntity;
import hirs.attestationca.persist.enums.AppraisalStatus;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.util.List;
/**
* Simple tests for the {@link SupplyChainValidation} class. Tests for the persistence of this
* class are located in { SupplyChainValidationSummaryTest}.
*/
class SupplyChainValidationTest {
private static final String MESSAGE = "Some message.";
/**
* Test that this class' getter methods work properly.
*
* @throws IOException if there is a problem deserializing certificates
*/
@Test
public void testGetters() throws IOException {
SupplyChainValidation validation = getTestSupplyChainValidation();
assertEquals(
validation.getValidationType(),
SupplyChainValidation.ValidationType.ENDORSEMENT_CREDENTIAL
);
assertEquals(
validation.getCertificatesUsed(),
CertificateTest.getAllTestCertificates()
);
assertEquals(validation.getMessage(), MESSAGE);
}
/**
* Test that a SupplyChainValidation can't be instantiated with a null validation type.
*
* @throws IOException if there is a problem deserializing certificates
*/
@Test
public void testNullValidationType() throws IOException {
assertThrows(IllegalArgumentException.class, () ->
new SupplyChainValidation(
null,
AppraisalStatus.Status.PASS,
CertificateTest.getAllTestCertificates(),
MESSAGE
));
}
/**
* Test that a SupplyChainValidation can't be instantiated with a null certificate list.
*
* @throws IOException if there is a problem deserializing certificates
*/
@Test
public void testNullCertificates() throws IOException {
assertThrows(IllegalArgumentException.class, () ->
new SupplyChainValidation(
SupplyChainValidation.ValidationType.ENDORSEMENT_CREDENTIAL,
AppraisalStatus.Status.PASS,
null,
MESSAGE
));
}
/**
* Test that a SupplyChainValidation can be instantiated with a null message.
*
* @throws IOException if there is a problem deserializing certificates
*/
@Test
public void testNullMessage() throws IOException {
new SupplyChainValidation(
SupplyChainValidation.ValidationType.ENDORSEMENT_CREDENTIAL,
AppraisalStatus.Status.PASS,
CertificateTest.getAllTestCertificates(),
MESSAGE
);
}
/**
* Construct a SupplyChainValidation for use in tests. It will have a validation
* type of ENDORSEMENT_CREDENTIAL, will represent a successful validation, and will use
* multiple test certificates.
*
* @return the test SupplyChainValidation
* @throws IOException if there si
*/
public static SupplyChainValidation getTestSupplyChainValidation() throws IOException {
return getTestSupplyChainValidation(
SupplyChainValidation.ValidationType.ENDORSEMENT_CREDENTIAL,
AppraisalStatus.Status.PASS,
CertificateTest.getAllTestCertificates()
);
}
/**
* Construct a SupplyChainValidation for use in tests according to the provided parameters.
*
* @param type the type of validation
* @param result the appraisal result
* @param certificates the certificates related to this validation
* @return the resulting SupplyChainValidation object
*/
public static SupplyChainValidation getTestSupplyChainValidation(
final SupplyChainValidation.ValidationType type,
final AppraisalStatus.Status result,
final List<ArchivableEntity> certificates) {
return new SupplyChainValidation(
type,
result,
certificates,
MESSAGE
);
}
}

View File

@ -0,0 +1,809 @@
package hirs.attestationca.persist.entity.userdefined.certificate;
import hirs.attestationca.persist.entity.userdefined.Certificate;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentIdentifier;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.PlatformConfiguration;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.PlatformProperty;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.TBBSecurityAssertion;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.URIReference;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.V2.PlatformConfigurationV2;
import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.util.encoders.Base64;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.fail;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Calendar;
import java.util.List;
import java.util.TimeZone;
/**
* Tests that a PlatformCredential parses its fields correctly.
*/
public class PlatformCredentialTest {
/**
* Location of a test platform attribute cert.
*/
public static final String TEST_PLATFORM_CERT_1 =
"/validation/platform_credentials/Intel_pc1.cer";
/**
* Location of another, slightly different platform attribute cert.
*/
public static final String TEST_PLATFORM_CERT_2 =
"/validation/platform_credentials/Intel_pc2.cer";
/**
* Location of another, slightly different platform attribute cert.
*/
public static final String TEST_PLATFORM_CERT_3 =
"/validation/platform_credentials/Intel_pc3.cer";
/**
* Platform cert with comma separated baseboard and chassis serial number.
*/
public static final String TEST_PLATFORM_CERT_4 =
"/validation/platform_credentials/Intel_pc4.pem";
/**
* Another platform cert with comma separated baseboard and chassis serial number.
*/
public static final String TEST_PLATFORM_CERT_5 =
"/validation/platform_credentials/Intel_pc5.pem";
/**
* Location of another, slightly different platform attribute cert.
*/
public static final String TEST_PLATFORM_CERT_6 =
"/validation/platform_credentials/TPM_INTC_Platform_Cert_RSA.txt";
/**
* Platform Certificate 2.0 with all the expected data.
*/
static final String TEST_PLATFORM_CERT2_1 =
"/validation/platform_credentials_2/basic_plat_cert.pem";
/**
* Platform Certificate spec 2.
*/
static final String TEST_PLATFORM_CERT2_SPEC2 =
"/validation/platform_credentials_2/large_attribute_spec2.txt";
/**
* Platform Certificate 2.0 with all the expected data.
*/
static final String TEST_PLATFORM_CERT2_2 =
"/validation/platform_credentials_2/small_plat_cert.pem";
/**
* Platform Certificate 2.0 with all the expected data.
*/
static final String TEST_PLATFORM_CERT2_3 =
"/validation/platform_credentials_2/medium_plat_cert.pem";
/**
* words.
*/
static final String TEST_BASE_PLATFORM_CERT_1 =
"/validation/platform_credentials/plat_base_cert1.pem";
/**
* words.
*/
static final String TEST_DELTA_PLATFORM_CERT_1 =
"/validation/platform_credentials/plat_delta_cert1.pem";
/**
* Platform Certificate 2.0 with all the expected data.
*/
static final String TEST_PLATFORM_CERT2_4 =
"/validation/platform_credentials_2/large_plat_cert.pem";
private static final String EXPECTED_CERT_SIGNATURE_FOR_CERTS_1 =
"425F6B2203EC6C651F3DA38416A39DB9B4D954A45FB1D1396D079ABE7"
+ "29E6299297CFB57A971559BB29E13E1AABBF5E99C11968FED7B53CE3F"
+ "4C71A889E893168A90C05F0F0D936B8D7E87531C616749DB647684DD2"
+ "E430B6FB3B62F286407E99B7EC2D20860528C4E4DB3C7617BC321DF1E"
+ "0E5F8DF601CB257BDE941E43CB0A8ED2B9EF1E95872C3FAE5A7195E16"
+ "9D14C05BD6051BA1AEED482E5322CA58D09CD9979EF8C166198C83BA7"
+ "243A2C79B9346B92ABB8C14E3AE950D5EB2E23CBEF1F124981949A413"
+ "7EBE52DB0F4C1E8DD515E9FF0A22CE852FA85C7648D160F39F391E868"
+ "74660B7FAA9ED150A36F0210B28AB6F840FCC61D81CD4F6FFF11B2A8";
private static final String EXPECTED_CERT_SIGNATURE_FOR_CERT_2 =
"67ABFBB91E0F061CA8CCE5DAA45104978D1020DE11DA65FD7DFD0E7C5"
+ "1B84218B033C32D82ACA0C14A48C39EE1603A5939F84711B1"
+ "95092ACB33FBA35B198019002C2326894ED0F7D17FA90450E"
+ "7ABDEEFD098C12838BEB4595B8A6B3E20D1164D4EF3D580AC"
+ "C16B8654B6E743B2A1D0397523870D0125EA90C3198C1C981"
+ "FFD5687EF8343EBC083388EC59301665677B05848CC5FABB1"
+ "E65C30F118DF391757D297BEA0197A4889A75969B4B3C1A52"
+ "D4AD7DB115D86D58513A512A2B771E8EC606D0485A3A6B334"
+ "88FC85CE84B40BEA7B73E7B56BA739344FCB6E7ADD6016623"
+ "F1680F2E021A6F5888197572BE226623262A0736AEE6E6724"
+ "BBD33AF8A068F6";
private static final String EXPECTED_CERT_SIGNATURE_FOR_CERT_3 =
"17342F73AB2B008707DE08CAD5C7974C0036004E4AABE6AA266823043"
+ "D0B9852A3E5B6BCB632F6363A025D0B6CA382512C04281432"
+ "D0B370D681804456ADF30B34EA4A8BA556110D3977D01B05B"
+ "3227E420CF7487AB133EE43CE6EA0C98BE10E6101DF9BFA71"
+ "61A464914530CB2A2F0BEB3E6CB7B9102816206B4CDB179CD"
+ "9B6C70B95F5CBABD225780B7F4164650F613A8BEAE4AA96DD"
+ "BFD60AA3CDFCD00753E9F70A08A7CDC69AF674C415836F6A8"
+ "73D5D481862029479AA73A275C9224D400115CF1C7DA64E57"
+ "9C0BD39D27671A1F2C9B241DB06353D54CF68C34A8935C6CD"
+ "E3C5D9D0847D3CFEB7EDA51DD31FBB77607CEE194C9B33BF5"
+ "ECF576F7E90484";
private static final String EXPECTED_CERT_SIGNATURE_FOR_CERT_4 =
"77A3B38CD85DE0A7F24CE86A3B83C371B8EA9438863CEDDB04C7B16AD59"
+ "3277B82E72D90B773CEC762A96F07A36D0AC0EE8189BAB87B607B"
+ "4288F38A17B81B78B41D098134215796C61E66224808B3E3941BD"
+ "48FB30066C01173E80CB531C5BE860EAFE17B6893A487F5FC512B"
+ "5E5C75BC8FF66F95741480C4DB3826C64E41EA";
private static final String EXPECTED_CERT_SIGNATURE_FOR_CERT_5 =
"05EE695EB9161CB40CCF89F8D992494307BBC7A81E2D8B81BAF755D33ACE429"
+ "277BA1453E900AF0C03BF1E5F09C886F7B86128CCD0CDF988FA469B"
+ "D397BA967A028F5E1ED899B7999FA437F4FB748B75C509017A1284A"
+ "D1098B0EB8C7E750D16FC99DADB0B32DF27B74F7BA1560DA56C3635"
+ "47E84124E560B71D40B729326FC5";
private static final String EXPECTED_CERT_SIGNATURE_FOR_CERT2_1 =
"MIIDZTCCAk2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBUMQswCQYDVQQGEwJVUzEUMBI"
+ "GA1UECgwLRXhhbXBsZS5vcmcxDTALBgNVBAsMBHRlc3QxIDAeBgNVBAMMF1BsYXRmb"
+ "3JtIENlcnRpZmljYXRlIENBMB4XDTE4MDQwNDE2NDUyMloXDTI4MDQwMzE2NDUyMlow"
+ "VDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0V4YW1wbGUub3JnMQ0wCwYDVQQLDAR0Z"
+ "XN0MSAwHgYDVQQDDBdQbGF0Zm9ybSBDZXJ0aWZpY2F0ZSBDQTCCASIwDQYJKoZIhv"
+ "cNAQEBBQADggEPADCCAQoCggEBAKYnSJ7gHWl9BytxJQWWaYQzuYWjoeQ8PnLkYMm"
+ "Kk8bV1v6hqRAg76p0QERubwtvDc3Rw0pVl5SqLku4ZzX7fzf3ra8IcrjR112f/ecAa"
+ "gf+f4855anoYvBC5hELHnh6PQSyjl7wJJZiVLsB61gsumqfos5DnlaxoriUfW8Th26"
+ "psnNIB+sbsn1f9WOHTDgXy81SGbgpG5+6joz1wXqpJvzZihIUNUSy8XQeusS22ZymI"
+ "abL/Gs1P4doiJMeF651MNwjB/vdyG46KT56pDzc6TKJqo80Gb6HaeDS5RcakA9dRHz"
+ "Vq7a3DOtzeNx84Cwl51tfE5MB/9mVP8grPjS5mQ8CAwEAAaNCMEAwDgYDVR0PAQH/B"
+ "AQDAgIEMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNszjDaflH5+feDx2e/3OHI"
+ "Fx/XrMA0GCSqGSIb3DQEBBQUAA4IBAQBkAGcfS3yLGQ4s/UXJjpyr8yGPJSvpbP87d"
+ "B+9dtncXhaHikOAXDXh+4uwhbU1vxWoatetJR0SYj+hFfPeyhqOz8NXP0L4IZFQOe7"
+ "23VNyTIhjpcbV/aqQq6wUC8FAvfsUc9FGZFjyKrWv/r454Wt3YSca6nlSOSWAU3xmW"
+ "32E3upuduJT4+a/VTvx2/4tPqPxe9fgQU+RkuZwWTL/1l0G/IbpnEVWB+BmY3VdNAy"
+ "au2zASSlprrEHQ4yr2u4QoOxbOmFx9aQIBHGw2srb4/iWegwfLxFLRnvqSTQp2ZU8i"
+ "AD2mtNMSHSGu26zfmjtu2EokCrFCa2cSbOZV9pTkQQ4";
/**
* Tests parsing of a platform credential.
*
* @throws URISyntaxException if there is a problem constructing the cert's URI
*/
@Test
public final void parseValidPlatformCertificate1() throws URISyntaxException {
URL resource = this.getClass().getResource(TEST_PLATFORM_CERT_1);
Path certPath = Paths.get(resource.toURI());
try {
new PlatformCredential(certPath);
//fail if it manage to parse the certificate
fail("Invalid certificate was parsed.");
} catch (IOException ex) {
if (ex == null || ex.getMessage().isEmpty()) {
//fail if the exception is empty or null
fail("Invalid Certificate produce null or empty exception");
} else {
Assertions.assertEquals(ex.getMessage(), "Invalid Attribute Credential Type: ");
}
}
}
/**
* Tests the parsing of a platform credential that has the subject directory attribute
* extension but is missing the subject alternative name extension. This certificate
* also has a policy extension, but it is not currently parsed.
*
* @throws IOException if an IO error occurs during processing
* @throws URISyntaxException if there is a problem constructing the cert's URI
*/
@Test
public final void parseValidPlatformCertificate3() throws IOException, URISyntaxException {
URL resource = this.getClass().getResource(TEST_PLATFORM_CERT_2);
Path certPath = Paths.get(resource.toURI());
PlatformCredential credential = new PlatformCredential(certPath);
Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
calendar.set(2017, 2, 23, 22, 34, 33);
calendar.set(Calendar.MILLISECOND, 0);
Assertions.assertEquals(credential.getBeginValidity().getTime(), calendar.getTime().getTime());
calendar.set(2030, 11, 31, 23, 59, 59);
Assertions.assertEquals(credential.getEndValidity().getTime(), calendar.getTime().getTime());
Assertions.assertNotNull(credential.getAttributeCertificate());
byte[] sig = credential.getAttributeCertificate().getSignatureValue().getBytes();
String sigStr = String.valueOf(Hex.encodeHex(sig));
Assertions.assertEquals(sigStr.toUpperCase(), EXPECTED_CERT_SIGNATURE_FOR_CERT_2);
String issuer = Certificate.getAttributeCertificateIssuerNames(
credential.getAttributeCertificate().getAcinfo().getIssuer()
)[0].toString();
Assertions.assertEquals(credential.getManufacturer(), "Intel");
Assertions.assertEquals(credential.getModel(), "DE3815TYKH");
Assertions.assertEquals(credential.getVersion(), "H26998-402");
Assertions.assertEquals(issuer,
"C=US,ST=CA,L=Santa Clara,O=Intel Corporation,"
+ "OU=Transparent Supply Chain,CN=www.intel.com");
Assertions.assertEquals(credential.getCredentialType(), "TCPA Trusted Platform Endorsement");
// the platform certificate in this test does not contain the following information
Assertions.assertEquals(credential.getPlatformSerial(), null);
Assertions.assertEquals(credential.getMajorVersion(), 1);
Assertions.assertEquals(credential.getMinorVersion(), 2);
Assertions.assertEquals(credential.getRevisionLevel(), 1);
Assertions.assertEquals(credential.getPlatformClass(), "1");
}
/**
* Tests the parsing of another platform credential that has the subject directory attribute
* extension but is missing the subject alternative name extension. This certificate
* also has a policy extension, but it is not currently parsed.
*
* @throws IOException if an IO error occurs during processing
* @throws URISyntaxException if there is a problem constructing the cert's URI
*/
@Test
public final void parseValidPlatformCertificate4() throws IOException, URISyntaxException {
URL resource = this.getClass().getResource(TEST_PLATFORM_CERT_3);
Path certPath = Paths.get(resource.toURI());
PlatformCredential credential = new PlatformCredential(certPath);
Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
calendar.set(2017, 2, 23, 22, 34, 33);
calendar.set(Calendar.MILLISECOND, 0);
Assertions.assertEquals(credential.getBeginValidity().getTime(), calendar.getTime().getTime());
calendar.set(2030, 11, 31, 23, 59, 59);
Assertions.assertEquals(credential.getEndValidity().getTime(), calendar.getTime().getTime());
Assertions.assertNotNull(credential.getAttributeCertificate());
byte[] sig = credential.getAttributeCertificate().getSignatureValue().getBytes();
String sigStr = String.valueOf(Hex.encodeHex(sig));
Assertions.assertEquals(sigStr.toUpperCase(), EXPECTED_CERT_SIGNATURE_FOR_CERT_3);
String issuer = Certificate.getAttributeCertificateIssuerNames(
credential.getAttributeCertificate().getAcinfo().getIssuer()
)[0].toString();
Assertions.assertEquals(credential.getManufacturer(), "Intel");
Assertions.assertEquals(credential.getModel(), "DE3815TYKH");
Assertions.assertEquals(credential.getVersion(), "H26998-402");
Assertions.assertEquals(issuer,
"C=US,ST=CA,L=Santa Clara,O=Intel Corporation,"
+ "OU=Transparent Supply Chain,CN=www.intel.com");
Assertions.assertEquals(credential.getCredentialType(), "TCPA Trusted Platform Endorsement");
// the platform certificate in this test does not contain the following information
Assertions.assertEquals(credential.getPlatformSerial(), null);
Assertions.assertEquals(credential.getMajorVersion(), 1);
Assertions.assertEquals(credential.getMinorVersion(), 2);
Assertions.assertEquals(credential.getRevisionLevel(), 1);
Assertions.assertEquals(credential.getPlatformClass(), "1");
}
/**
* Tests the parsing of a platform credential that has a combined baseboard and chassis
* serial number in one attribute can be parsed.
*
* @throws IOException if an IO error occurs during processing
* @throws URISyntaxException if there is a problem constructing the cert's URI
*/
@Test
public final void parseValidPlatformCertificate5() throws IOException, URISyntaxException {
URL resource = this.getClass().getResource(TEST_PLATFORM_CERT_4);
Path certPath = Paths.get(resource.toURI());
PlatformCredential credential = new PlatformCredential(certPath);
Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
calendar.set(2017, 3, 21, 17, 5, 29);
calendar.set(Calendar.MILLISECOND, 0);
Assertions.assertEquals(credential.getBeginValidity().getTime(), calendar.getTime().getTime());
calendar.set(2030, 11, 31, 23, 59, 59);
Assertions.assertEquals(credential.getEndValidity().getTime(), calendar.getTime().getTime());
Assertions.assertNotNull(credential.getAttributeCertificate());
byte[] sig = credential.getAttributeCertificate().getSignatureValue().getBytes();
String sigStr = String.valueOf(Hex.encodeHex(sig));
Assertions.assertEquals(sigStr.toUpperCase(), EXPECTED_CERT_SIGNATURE_FOR_CERT_4);
String issuer = Certificate.getAttributeCertificateIssuerNames(
credential.getAttributeCertificate().getAcinfo().getIssuer()
)[0].toString();
Assertions.assertEquals(credential.getManufacturer(), "Intel");
Assertions.assertEquals(credential.getModel(), "DE3815TYKH");
Assertions.assertEquals(credential.getVersion(), "H26998-402");
Assertions.assertEquals(issuer,
"C=US,ST=CA,L=Santa Clara,O=Intel Corporation,"
+ "OU=Transparent Supply Chain,CN=www.intel.com");
Assertions.assertEquals(credential.getCredentialType(), "TCPA Trusted Platform Endorsement");
Assertions.assertEquals(credential.getChassisSerialNumber(), "G6YK42300C87");
Assertions.assertEquals(credential.getPlatformSerial(), "GETY421001GV");
}
/**
* Tests the parsing another platform credential that has a combined baseboard and chassis
* serial number in one attribute can be parsed.
*
* @throws IOException if an IO error occurs during processing
* @throws URISyntaxException if there is a problem constructing the cert's URI
*/
@Test
public final void parseValidPlatformCertificate6() throws IOException, URISyntaxException {
URL resource = this.getClass().getResource(TEST_PLATFORM_CERT_5);
Path certPath = Paths.get(resource.toURI());
PlatformCredential credential = new PlatformCredential(certPath);
Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
calendar.set(2017, 3, 21, 17, 5, 30);
calendar.set(Calendar.MILLISECOND, 0);
Assertions.assertEquals(credential.getBeginValidity().getTime(), calendar.getTime().getTime());
calendar.set(2030, 11, 31, 23, 59, 59);
Assertions.assertEquals(credential.getEndValidity().getTime(), calendar.getTime().getTime());
Assertions.assertNotNull(credential.getAttributeCertificate());
byte[] sig = credential.getAttributeCertificate().getSignatureValue().getBytes();
String sigStr = String.valueOf(Hex.encodeHex(sig));
Assertions.assertEquals(sigStr.toUpperCase(), EXPECTED_CERT_SIGNATURE_FOR_CERT_5);
String issuer = Certificate.getAttributeCertificateIssuerNames(
credential.getAttributeCertificate().getAcinfo().getIssuer()
)[0].toString();
Assertions.assertEquals(credential.getManufacturer(), "Intel");
Assertions.assertEquals(credential.getModel(), "DE3815TYKH");
Assertions.assertEquals(credential.getVersion(), "H26998-402");
Assertions.assertEquals(issuer,
"C=US,ST=CA,L=Santa Clara,O=Intel Corporation,"
+ "OU=Transparent Supply Chain,CN=www.intel.com");
Assertions.assertEquals(credential.getCredentialType(), "TCPA Trusted Platform Endorsement");
Assertions.assertEquals(credential.getChassisSerialNumber(), "G6YK42300CB6");
Assertions.assertEquals(credential.getPlatformSerial(), "GETY42100160");
}
/**
* Tests isIssuer of a platform credential.
*
* @throws IOException if an IO error occurs during processing
* @throws URISyntaxException if there is a problem constructing the cert's URI
*/
@Test
public final void testIsIssuer() throws IOException, URISyntaxException {
URL resource = this.getClass().getResource(TEST_PLATFORM_CERT2_1);
Path certPath = Paths.get(resource.toURI());
PlatformCredential platformCert = new PlatformCredential(certPath);
Certificate issuer = new CertificateAuthorityCredential(
Base64.decode(EXPECTED_CERT_SIGNATURE_FOR_CERT2_1));
//Check if issuer certificate issued the platform credential
Assertions.assertTrue(platformCert.isIssuer(issuer).isEmpty());
}
/**
* Tests platform Configuration Values.
*
* @throws IOException if an IO error occurs during processing
* @throws URISyntaxException if there is a problem constructing the cert's URI
*/
@Test
public final void testPlatformConfiguration() throws IOException, URISyntaxException {
URL resource = this.getClass().getResource(TEST_PLATFORM_CERT2_1);
Path certPath = Paths.get(resource.toURI());
PlatformCredential platformCert = new PlatformCredential(certPath);
PlatformConfiguration platformConfig = platformCert.getPlatformConfiguration();
//Check component identifier
List<ComponentIdentifier> allComponents = platformConfig.getComponentIdentifier();
if (allComponents.isEmpty()) {
Assertions.fail("Component Identifier is empty.");
}
Assertions.assertEquals(allComponents.size(), 7);
ComponentIdentifier component;
//Check component #2
component = (ComponentIdentifier) allComponents.get(1);
Assertions.assertTrue(component.getComponentManufacturer()
.getString()
.equals("Intel Corporation"));
Assertions.assertTrue(component.getComponentModel()
.getString()
.equals("NUC7i5DNB"));
Assertions.assertTrue(component.getComponentSerial()
.getString()
.equals("BTDN732000QM"));
//Check component #3
component = (ComponentIdentifier) allComponents.get(2);
Assertions.assertTrue(component.getComponentManufacturer()
.getString()
.equals("Intel(R) Corporation"));
Assertions.assertTrue(component.getComponentModel().getString().equals("Core i5"));
Assertions.assertTrue(component.getFieldReplaceable().isTrue());
//Check component #5
component = (ComponentIdentifier) allComponents.get(4);
Assertions.assertTrue(component.getComponentModel()
.getString()
.equals("Ethernet Connection I219-LM"));
Assertions.assertTrue(component.getComponentAddress().get(0)
.getAddressValue()
.getString()
.equals("8c:0f:6f:72:c6:c5"));
Assertions.assertTrue(component.getComponentAddress().get(0)
.getAddressTypeValue()
.equals("ethernet mac"));
//Check Platform Properties
List<PlatformProperty> platformProperties = platformConfig.getPlatformProperties();
if (platformProperties.isEmpty()) {
Assertions.fail("Platform Properties is empty.");
}
Assertions.assertEquals(platformProperties.size(), 2);
PlatformProperty property;
//Check property #1
property = (PlatformProperty) platformProperties.get(0);
Assertions.assertTrue(property.getPropertyName().getString().equals("vPro"));
Assertions.assertTrue(property.getPropertyValue().getString().equals("true"));
//Check property #2
property = (PlatformProperty) platformProperties.get(1);
Assertions.assertTrue(property.getPropertyName().getString().equals("AMT"));
Assertions.assertTrue(property.getPropertyValue().getString().equals("true"));
//Check Platform Properties URI
URIReference platformPropertyUri = platformConfig.getPlatformPropertiesUri();
Assertions.assertNotNull(platformPropertyUri);
Assertions.assertTrue(platformPropertyUri.getUniformResourceIdentifier()
.getString()
.equals("https://www.intel.com/platformproperties.xml"));
Assertions.assertNull(platformPropertyUri.getHashAlgorithm());
Assertions.assertNull(platformPropertyUri.getHashValue());
}
/**
* Tests Platform Configuration Values. View platform Properties
*
* @throws IOException if an IO error occurs during processing
* @throws URISyntaxException if there is a problem constructing the cert's URI
*/
@Test
public final void testPlatformConfiguration2() throws IOException, URISyntaxException {
URL resource = this.getClass().getResource(TEST_PLATFORM_CERT2_2);
Path certPath = Paths.get(resource.toURI());
PlatformCredential platformCert = new PlatformCredential(certPath);
PlatformConfiguration platformConfig = platformCert.getPlatformConfiguration();
//Check component identifier
List<ComponentIdentifier> allComponents = platformConfig.getComponentIdentifier();
Assertions.assertTrue(allComponents.isEmpty());
List<PlatformProperty> platformProperties = platformConfig.getPlatformProperties();
if (platformProperties.isEmpty()) {
Assertions.fail("Platform Properties is empty.");
}
Assertions.assertEquals(platformProperties.size(), 2);
PlatformProperty property;
//Check property #1
property = (PlatformProperty) platformProperties.get(0);
Assertions.assertTrue(property.getPropertyName().getString().equals("vPro"));
Assertions.assertTrue(property.getPropertyValue().getString().equals("true"));
//Check property #2
property = (PlatformProperty) platformProperties.get(1);
Assertions.assertTrue(property.getPropertyName().getString().equals("AMT"));
Assertions.assertTrue(property.getPropertyValue().getString().equals("true"));
}
/**
* Tests Platform Configuration Values. View platform Properties
*
* @throws IOException if an IO error occurs during processing
* @throws URISyntaxException if there is a problem constructing the cert's URI
*/
@Test
public final void testPlatformConfiguration3() throws IOException, URISyntaxException {
URL resource = this.getClass().getResource(TEST_PLATFORM_CERT2_3);
Path certPath = Paths.get(resource.toURI());
PlatformCredential platformCert = new PlatformCredential(certPath);
PlatformConfiguration platformConfig = platformCert.getPlatformConfiguration();
//Check component identifier
List<ComponentIdentifier> allComponents = platformConfig.getComponentIdentifier();
if (allComponents.isEmpty()) {
Assertions.fail("Component Identifier is empty.");
}
Assertions.assertEquals(allComponents.size(), 3);
ComponentIdentifier component;
//Check component #2
component = (ComponentIdentifier) allComponents.get(1);
Assertions.assertTrue(component.getComponentManufacturer()
.getString()
.equals("Intel(R) Corporation"));
Assertions.assertTrue(component.getComponentModel()
.getString()
.equals("Intel(R) Core(TM) i5-7300U CPU @ 2.60GHz"));
//Check component #3
component = (ComponentIdentifier) allComponents.get(2);
Assertions.assertTrue(component.getComponentModel()
.getString()
.equals("BIOS"));
Assertions.assertTrue(component.getComponentSerial()
.getString()
.equals(""));
Assertions.assertTrue(component.getComponentRevision()
.getString()
.equals("DNKBLi5v.86A.0019.2017.0804.1146"));
//Check Platform Properties
List<PlatformProperty> platformProperties = platformConfig.getPlatformProperties();
if (platformProperties.isEmpty()) {
Assertions.fail("Platform Properties is empty.");
}
Assertions.assertEquals(platformProperties.size(), 2);
//Check Platform Properties URI
URIReference platformPropertyUri = platformConfig.getPlatformPropertiesUri();
Assertions.assertNotNull(platformPropertyUri);
Assertions.assertTrue(platformPropertyUri.getUniformResourceIdentifier()
.getString()
.equals("https://www.intel.com/platformproperties.xml"));
Assertions.assertNull(platformPropertyUri.getHashAlgorithm());
Assertions.assertNull(platformPropertyUri.getHashValue());
//Test TBBSecurityAssertion
TBBSecurityAssertion tbbSec = platformCert.getTBBSecurityAssertion();
Assertions.assertNotNull(tbbSec);
Assertions.assertTrue(tbbSec.getCcInfo().getVersion().getString().equals("3.1"));
Assertions.assertTrue(tbbSec.getCcInfo().getProfileOid().getId().equals("1.2.3.4.5.6"));
Assertions.assertTrue(tbbSec.getFipsLevel().getVersion().getString().equals("140-2"));
Assertions.assertTrue(tbbSec.getIso9000Uri().getString()
.equals("https://www.intel.com/isocertification.pdf"));
}
/**
* Tests Platform Configuration Values. View platform Properties
*
* @throws IOException if an IO error occurs during processing
* @throws URISyntaxException if there is a problem constructing the cert's URI
*/
@Test
public final void testPlatformConfiguration4() throws IOException, URISyntaxException {
URL resource = this.getClass().getResource(TEST_PLATFORM_CERT2_4);
Path certPath = Paths.get(resource.toURI());
PlatformCredential platformCert = new PlatformCredential(certPath);
PlatformConfiguration platformConfig = platformCert.getPlatformConfiguration();
//Check component identifier
List<ComponentIdentifier> allComponents = platformConfig.getComponentIdentifier();
if (allComponents.isEmpty()) {
Assertions.fail("Component Identifier is empty.");
}
Assertions.assertEquals(allComponents.size(), 7);
ComponentIdentifier component;
//Check component #1
component = (ComponentIdentifier) allComponents.get(0);
Assertions.assertTrue(component.getComponentModel()
.getString()
.equals("NUC7i5DNB"));
Assertions.assertTrue(component.getComponentRevision()
.getString()
.equals("J57626-401"));
//Check component #7
component = (ComponentIdentifier) allComponents.get(6);
Assertions.assertTrue(component.getComponentAddress().size() > 0);
Assertions.assertTrue(component.getComponentAddress().get(0)
.getAddressValue()
.getString()
.equals("8c:0f:6f:72:c6:c5"));
Assertions.assertTrue(component.getComponentAddress().get(0)
.getAddressTypeValue()
.equals("ethernet mac"));
//Check Platform Properties
List<PlatformProperty> platformProperties = platformConfig.getPlatformProperties();
if (platformProperties.isEmpty()) {
Assertions.fail("Platform Properties is empty.");
}
Assertions.assertEquals(platformProperties.size(), 2);
//Check Platform Properties URI
URIReference platformPropertyUri = platformConfig.getPlatformPropertiesUri();
Assertions.assertNotNull(platformPropertyUri);
Assertions.assertTrue(platformPropertyUri.getUniformResourceIdentifier()
.getString()
.equals("https://www.intel.com/platformproperties.xml"));
Assertions.assertNull(platformPropertyUri.getHashAlgorithm());
Assertions.assertNull(platformPropertyUri.getHashValue());
//Test TBBSecurityAssertion
TBBSecurityAssertion tbbSec = platformCert.getTBBSecurityAssertion();
Assertions.assertNotNull(tbbSec);
Assertions.assertTrue(tbbSec.getCcInfo().getVersion().getString().equals("3.1"));
Assertions.assertTrue(tbbSec.getCcInfo().getProfileOid().getId().equals("1.2.3.4.5.6"));
Assertions.assertTrue(tbbSec.getFipsLevel().getVersion().getString().equals("140-2"));
Assertions.assertTrue(tbbSec.getIso9000Uri().getString()
.equals("https://www.intel.com/isocertification.pdf"));
}
/**
* Tests Platform Configuration Values. View platform Properties
*
* @throws IOException if an IO error occurs during processing
* @throws URISyntaxException if there is a problem constructing the cert's URI
*/
@Test
public final void testPlatformConfiguration5() throws IOException, URISyntaxException {
URL resource = this.getClass().getResource(TEST_PLATFORM_CERT2_SPEC2);
Path certPath = Paths.get(resource.toURI());
PlatformCredential platformCert = new PlatformCredential(certPath);
PlatformConfiguration platformConfig = platformCert.getPlatformConfiguration();
//Check component identifier
List<ComponentIdentifier> allComponents = platformConfig.getComponentIdentifier();
Assertions.assertFalse(allComponents.isEmpty());
ComponentIdentifier component = allComponents.get(5);
Assertions.assertTrue(component.isVersion2());
List<PlatformProperty> platformProperties = platformConfig.getPlatformProperties();
if (platformProperties.isEmpty()) {
Assertions.fail("Platform Properties is empty.");
}
Assertions.assertEquals(platformProperties.size(), 3);
PlatformProperty property;
//Check property #1
property = (PlatformProperty) platformProperties.get(0);
Assertions.assertTrue(property.getPropertyName().getString().equals("AMT"));
Assertions.assertTrue(property.getPropertyValue().getString().equals("true"));
//Check property #2
property = (PlatformProperty) platformProperties.get(1);
Assertions.assertTrue(property.getPropertyName().getString().equals("vPro Enabled"));
Assertions.assertTrue(property.getPropertyValue().getString().equals("true"));
//Check property #3
property = (PlatformProperty) platformProperties.get(2);
Assertions.assertTrue(property.getPropertyName().getString().equals("DropShip Enabled"));
Assertions.assertTrue(property.getPropertyValue().getString().equals("false"));
}
/**
* Tests Platform Configuration Values. View platform Properties
*
* @throws IOException if an IO error occurs during processing
* @throws URISyntaxException if there is a problem constructing the cert's URI
*/
@Test
public final void testPlatformConfiguration6() throws IOException, URISyntaxException {
URL resource = this.getClass().getResource(TEST_BASE_PLATFORM_CERT_1);
Path certPath = Paths.get(resource.toURI());
PlatformCredential platformCert = new PlatformCredential(certPath);
PlatformConfiguration platformConfig = platformCert.getPlatformConfiguration();
Assertions.assertTrue(platformConfig instanceof PlatformConfigurationV2);
Assertions.assertEquals(platformConfig.getPlatformPropertiesUri()
.getUniformResourceIdentifier().toString(),
"https://www.intel.com/platformproperties.xml");
Assertions.assertNotNull(platformConfig.getComponentIdentifierUri());
Assertions.assertEquals(platformConfig.getComponentIdentifierUri()
.getUniformResourceIdentifier().toString(),
"https://www.intel.com/platformidentifiers.xml");
}
/**
* Tests Platform Configuration Values. View platform Properties
*
* @throws URISyntaxException if there is a problem constructing the cert's URI
* @throws IOException if there is a problem reading the cert file
*/
@Test
public final void testSmallNewPlatformCredential() throws URISyntaxException, IOException {
Path path = Paths.get(this.getClass().getResource(
"/validation/platform_credentials_2/small_attribute_cert_2187.pem").toURI());
PlatformCredential credential = new PlatformCredential(path);
Assertions.assertNotNull(credential);
}
/**
* Tests Platform Configuration Values. View platform Properties
*
* @throws IOException if an IO error occurs during processing
* @throws URISyntaxException if there is a problem constructing the cert's URI
*/
@Test
public final void testMediumNewPlatformCredential() throws URISyntaxException, IOException {
Path path = Paths.get(this.getClass().getResource(
"/validation/platform_credentials_2/medium_attribute_cert_2187.pem").toURI());
PlatformCredential credential = new PlatformCredential(path);
Assertions.assertNotNull(credential);
}
/**
* Tests Platform Configuration Values. View platform Properties
*
* @throws IOException if an IO error occurs during processing
* @throws URISyntaxException if there is a problem constructing the cert's URI
*/
@Test
public final void testLargeNewPlatformCredential() throws URISyntaxException, IOException {
Path path = Paths.get(this.getClass().getResource(
"/validation/platform_credentials_2/large_attribute_cert_2187.pem").toURI());
PlatformCredential credential = new PlatformCredential(path);
Assertions.assertNotNull(credential);
}
/**
* Tests Platform Configuration Values. View platform Properties
*
* @throws IOException if an IO error occurs during processing
* @throws URISyntaxException if there is a problem constructing the cert's URI
*/
@Test
public final void testFlawedNewPlatformCredential() throws URISyntaxException, IOException {
Path path = Paths.get(this.getClass().getResource(
"/validation/platform_credentials_2/flawed_attribute_cert_2187.pem").toURI());
PlatformCredential credential = new PlatformCredential(path);
Assertions.assertNotNull(credential);
}
}

View File

@ -0,0 +1,127 @@
package hirs.attestationca.persist.entity.userdefined.info;
import hirs.utils.enums.PortalScheme;
import java.net.InetAddress;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
import org.junit.jupiter.api.Test;
/**
* Provides tests for PortalInfo.
*/
public class PortalInfoTest {
/**
* Test the default state of the object, once constructed.
*/
@Test
public void testPortalInfoDefaults() {
PortalInfo info = new PortalInfo();
assertNull(info.getName());
assertNull(info.getIpAddress());
assertEquals(info.getPort(), 0);
}
/**
* Test that the scheme can be set and retrieved.
*/
@Test
public void testScheme() {
final PortalScheme scheme = PortalScheme.HTTPS;
PortalInfo info = new PortalInfo();
info.setSchemeName(scheme);
assertEquals(info.getName(), scheme.name());
}
/**
* Test that setSchemeName does not accept a null input.
*/
@Test
public void testSchemeNull() {
final PortalScheme scheme = null;
PortalInfo info = new PortalInfo();
try {
info.setSchemeName(scheme);
fail("The null scheme should have caused an error.");
} catch (NullPointerException e) {
assertNull(info.getName());
}
}
/**
* Test that the ip address can be set and retrieved via an InetAddress.
* @throws Exception If there is a problem with InetAddress.
*/
@Test
public void testIpAddressInetAddress() throws Exception {
final InetAddress address = InetAddress.getLocalHost();
PortalInfo info = new PortalInfo();
info.setIpAddress(address);
assertEquals(info.getIpAddress(), address);
}
/**
* Test that the ip address can be set and retrieved via a String.
* @throws Exception If there is a problem with InetAddress.
*/
@Test
public void testIpAddressString() throws Exception {
final String address = "localhost";
PortalInfo info = new PortalInfo();
info.setIpAddress(address);
assertEquals(info.getIpAddress().getHostName(), address);
}
/**
* Test that the scheme can be set and retrieved.
*/
@Test
public void testPort() {
final int port = 127;
PortalInfo info = new PortalInfo();
info.setPort(port);
assertEquals(info.getPort(), port);
}
/**
* Test that the context name can be set and retrieved.
*/
@Test
public void testContext() {
final String context = "Portal";
PortalInfo info = new PortalInfo();
info.setContextName(context);
assertEquals(info.getContext(), context);
}
/**
* Test that setContextName does not accept a null input.
*/
@Test
public void testContextNull() {
final String context = null;
PortalInfo info = new PortalInfo();
try {
info.setContextName(context);
fail("The null context should have caused an error.");
} catch (NullPointerException e) {
assertNull(info.getContext());
}
}
}

View File

@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDrzCCApegAwIBAgIEJVDCpzANBgkqhkiG9w0BAQUFADCBhzELMAkGA1UEBhMCVVMxCzAJBgNV
BAgTAkNBMRQwEgYDVQQHEwtTYW50YSBDbGFyYTEaMBgGA1UEChMRSW50ZWwgQ29ycG9yYXRpb24x
ITAfBgNVBAsTGFRyYW5zcGFyZW50IFN1cHBseSBDaGFpbjEWMBQGA1UEAxMNd3d3LmludGVsLmNv
bTAeFw0xNzA0MTkwMDAyMTBaFw0zNzEwMzEwMDAyMTBaMIGHMQswCQYDVQQGEwJVUzELMAkGA1UE
CBMCQ0ExFDASBgNVBAcTC1NhbnRhIENsYXJhMRowGAYDVQQKExFJbnRlbCBDb3Jwb3JhdGlvbjEh
MB8GA1UECxMYVHJhbnNwYXJlbnQgU3VwcGx5IENoYWluMRYwFAYDVQQDEw13d3cuaW50ZWwuY29t
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAo7Cu8Y3uWKoTQW/RnmNJG5h3PlYdvE2B
v0c2+WUz0AprrVMpUvbJaNoMx47ev9CYvoxuJU0t9JjMm2i1u6Ol6VlK5yAWqr/qySvkryKTUuSx
7sOtkayF4LqD16LlTIAmUhC0KabbrEitpBa1BtKsy8yhGjbm+bYs0D19jjqHH9rOT3I8j04tc5a4
r86dPuCZX8RJTV8tZd51ULFhl+70rIwPY/Ecbl5lzx786v9xW3XnC4/XplvMJXw2wkUo8G98qyeD
Odvha4Y49NswlqyUHnAlk+n4bIF7cvSDi+vb4YRaV2g5u2K3290ePUcNyzGTYgdpBnvOQlna/IZ0
NifXQQIDAQABoyEwHzAdBgNVHQ4EFgQUIQWBMO10djQycITwJ5XfZw6L13MwDQYJKoZIhvcNAQEF
BQADggEBADgcp+GI5S6HSVhQD7wyqKIBCLUk5nC0FzE0W1vBuLrwCagXHXwMC09uDXOXtfNOoQVZ
duS3oaju5i40lSbFmp7V2hewQo6vlum/M05Lg/O7vndKxnKss/PeT5jMyjJ4t00HQ3KEm2aZL1BR
AJZjbH+hZ08bh5pY5uP7husjjcur0xqhFw9Afq4SUbXtA47QBaUuJTtBwTf2r/Nesq4a6zRAtqF/
gmGD8VOSahBrtuIS30GRgcpsk6kKO4fLCvCZwyJ2/Mn+ySMB3+G6XqgDekkykCnnvMVUr+nzasug
d/4I62L3eZ2j5Xpa3O1kFZ+zIMrbLRh7Bu8OdjFdvodwmRU=
-----END CERTIFICATE-----

View File

@ -0,0 +1,16 @@
-----BEGIN CERTIFICATE-----
MIIDADCCAegCAQEwMKAuMBakFDASMRAwDgYDVQQDDAdTVE1pY3JvAhQrz0/5+zLfie1TVQpsz57k
yGtq3aCBkDCBjaSBijCBhzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRQwEgYDVQQHDAtTYW50
YSBDbGFyYTEaMBgGA1UECgwRSW50ZWwgQ29ycG9yYXRpb24xITAfBgNVBAsMGFRyYW5zcGFyZW50
IFN1cHBseSBDaGFpbjEWMBQGA1UEAwwNd3d3LmludGVsLmNvbTANBgkqhkiG9w0BAQUFAAIUQtCe
CYR41o33Qv3So+KiQIZviFAwIhgPMjAxNzAzMTUyMTA4MzBaGA8yMDMwMTIzMTIzNTk1OVowMTAZ
BgVngQUCETEQMA4wCQIBAQIBAgIBAQwBMTAUBgVngQUCEzELMAkCAQCCAQMBAQAwgaEwTQYDVR0g
AQH/BEMwQTA/BgoqhkiG+E0BBQIEMDEwLwYIKwYBBQUHAgIwIwwhVENQQSBUcnVzdGVkIFBsYXRm
b3JtIEVuZG9yc2VtZW50MFAGA1UdEQEB/wRGMESkQjBAMRAwDgYFZ4EFAgQMBUludGVsMRUwEwYF
Z4EFAgUMCkRFMzgxNVRZS0gxFTATBgVngQUCBgwKSDI2OTk4LTQwMjANBgkqhkiG9w0BAQUFAAOC
AQEAXPD46MxZy0vQlSQ7EOMRgBSDWUS9561Gc2IKM0FqXcYWi6YT4NAk1rx/j/ycA87fNiJzOjSC
D1qv5MAaI3IOuqE911Hk/lsZ9Xq25a5c6BeQjyCpwI/qNno0rnTINjOXYllurVzU6Dn109f1NQS/
m9ZkJ1gicMWkna2mEO842kH5CfqaskRqUGOO5nViO6Y094pzwT/Zp+W2CRqAo1BwDIV8OM6u4AZn
EagFlbpPqnU8IfFO2n4zeILADiJ9TkXJovvfemJnoZlzcUPO6+8wjjsbtojEiu4bQF9QwIc/VtDS
YUYstwwuACuSxE6jvhROuZHiTBE85623uE0eMQl5vA==
-----END CERTIFICATE-----

View File

@ -0,0 +1,16 @@
-----BEGIN CERTIFICATE-----
MIIDADCCAegCAQEwMKAuMBakFDASMRAwDgYDVQQDDAdTVE1pY3JvAhRrZ4VfPG34FALdQNaVQ0q4
szdWuKCBkDCBjaSBijCBhzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRQwEgYDVQQHDAtTYW50
YSBDbGFyYTEaMBgGA1UECgwRSW50ZWwgQ29ycG9yYXRpb24xITAfBgNVBAsMGFRyYW5zcGFyZW50
IFN1cHBseSBDaGFpbjEWMBQGA1UEAwwNd3d3LmludGVsLmNvbTANBgkqhkiG9w0BAQUFAAIUM1Nq
X1KDMb4erHbXmwv9sBEi9E8wIhgPMjAxNzAzMTQyMzUyMTBaGA8yMDMwMTIzMTIzNTk1OVowMTAZ
BgVngQUCETEQMA4wCQIBAQIBAgIBAQwBMTAUBgVngQUCEzELMAkCAQCCAQMBAQAwgaEwTQYDVR0g
AQH/BEMwQTA/BgoqhkiG+E0BBQIEMDEwLwYIKwYBBQUHAgIwIwwhVENQQSBUcnVzdGVkIFBsYXRm
b3JtIEVuZG9yc2VtZW50MFAGA1UdEQEB/wRGMESkQjBAMRAwDgYFZ4EFAgQMBUludGVsMRUwEwYF
Z4EFAgUMCkRFMzgxNVRZS0gxFTATBgVngQUCBgwKSDI2OTk4LTQwMjANBgkqhkiG9w0BAQUFAAOC
AQEALBdTOKTd4wyKOBvKUGsDwfjiKVir93XmTa1SW/B176ZAhfxasEnqD1idi051DHKyF9Sw4VDC
vQfc7XE5QqBsqIrt1Fqq88dDbrcCauinzG6KBApG+cIbKT6K/wYeBwbvhpuDEeytQmv4noYG1FnA
U+eSdVvwha/4f2QeMNlnNxDMvyvi11oeTeIG3LO5Bp0UYmPNuozsOyY8eztFmHJ27xq0QbYKh6dV
I5kwuIPZz4VK9E7AuhDZcYpp2JgyUBFdJUA2a156NGC1JnYmxJ+WBxd+oQ41SLSbMUpymsQyFwvQ
WxuOaLnGLiHwrxXgvhsisH8MO/WkOo+iBDxQrTpkAw==
-----END CERTIFICATE-----

View File

@ -0,0 +1,26 @@
-----BEGIN CERTIFICATE-----
MIIEXjCCA0agAwIBAgIUWGRkKsiikVUJWz+eO8Pz0lN6xUwwDQYJKoZIhvcNAQEF
BQAwVTELMAkGA1UEBhMCQ0gxHjAcBgNVBAoTFVNUTWljcm9lbGVjdHJvbmljcyBO
VjEmMCQGA1UEAxMdU1RNIFRQTSBFSyBJbnRlcm1lZGlhdGUgQ0EgMDIwHhcNMTQw
MTE3MDAwMDAwWhcNMjQwMTE3MDAwMDAwWjAAMIIBNzAiBgkqhkiG9w0BAQcwFaIT
MBEGCSqGSIb3DQEBCQQEVENQQQOCAQ8AMIIBCgKCAQEAqyHM8tOsFtL2QEEAX+Tq
HPdi6TOZQ3Dc1sgCgwms4jRzoIoVcTMmYZhLY2qHiM0lnFXKEwb/3ox3Hzw5/ZFW
aSizfykbGN5tSkHBlBq9i8vK5i6/WcmOk88ai+VP8+pYTiFQRVQjjnrTV8YDg0pT
HIo+ZcUHVT5shxXISu7QEQe4ZnhiNG6BQmJH2+ytcUkCDh3m3pMgGsWehEMvrOSi
IjxMgKtb8MLQ4pijB81x2Tb4Wun2O5J/uUie+QbdWbbfLWOaFcH72WV9KzHcliKm
ICNqgBO9OBbB4SSzsTZY/vZ7G/xAsDaTfQdacm/qgnoXpU33dXdmY1QJTxHc5lYc
PwIDAQABo4IBZDCCAWAwHwYDVR0jBBgwFoAUVx+Aa0fM55v6NZR87Yi40QBa4J4w
QgYDVR0gBDswOTA3BgRVHSAAMC8wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cuc3Qu
Y29tL1RQTS9yZXBvc2l0b3J5LzBVBgNVHREBAf8ESzBJpEcwRTEWMBQGBWeBBQIB
DAtpZDo1MzU0NEQyMDEXMBUGBWeBBQICDAxTVDMzWlAyNFBWU1AxEjAQBgVngQUC
AwwHaWQ6MEQwQzB/BgNVHQkEeDB2MBYGBWeBBQIQMQ0wCwwDMS4yAgECAgF0MCAG
BWeBBQISMRcwFQIBAAEB/6ADCgEBoQMKAQCiAwoBADA6BgNVBTQxMzAkMCIGCSqG
SIb3DQEBBzAVohMwEQYJKoZIhvcNAQEJBARUQ1BBMAswCQYFKw4DAhoFADAMBgNV
HRMBAf8EAjAAMBMGA1UdJQEB/wQJMAcGBWeBBQgBMA0GCSqGSIb3DQEBBQUAA4IB
AQCN1xBDK47IE+Hs5/GcC8GG55A9THUocrVwGCXi5rN1CT7QnlypzEgxAhVBFZKI
X+AZLjB5HRczAlCH7kqbfNEGjcSMLQP61+7bkvAPcdfJtr9nLR8eK/tIlRcsXX33
vE7HcnuDvuzyumb9x+RFT6tol/MhSVVA9/ETyTa4v9n2kZHQVo5KycU0fIUvQ0xe
CxU0kIdR8S6LcpBT1nSr8I8wgtaqKaoqQrMfBjAqVJYpogCUe2OLhRT8KzP/Ow3m
OarP5jgMM+rQpOHeqb/BxIrUl77ER2BJ7LIVIuCLl+cOUgsdTz46ZhY0HKVmKotu
0LThZ6mEE8+9rcaQtZsmYbRx
-----END CERTIFICATE-----

View File

@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE-----
MIIC5zCCAdGgAwIBAgIBATALBgkqhkiG9w0BAQswFzEVMBMGA1UEAwwMRmFrZSBS
b290IENBMB4XDTE3MDEyNDE1MjU0MVoXDTQ3MDEyNDE1MjU0MVowFzEVMBMGA1UE
AwwMRmFrZSBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
geIXUAtrlc+FY8FC/bAGC6Vg1lbok+kILT/ZmG/4vdigZ2hzFR3dVjmgWd4hp3uP
dY7E/JUEouBq24qDpPUWrHIxSCqGp9Rn+whGq6Yy7d1d0FGyskIJJ2aFr1QC+/jA
4CptLbQGhqmyALrmXFai3scUmNciuTbEb3Ap9829IdsD4F9hT557zRSocaelVCUw
6sNLU78fJfG7K3dKmKemvtprqlDlfM3nya5P6IzkRKiPpXN6Q1sL7FDkKQ3HuyBM
WqPU+AWhqhCR9hRenuTpwTxEPVPA8FRV78wkV3VLzXCG7lHPZ8xCDKAZzdbwymjU
wfm9Wr5KperE83suIcIHxQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud
DwEB/wQEAwIBBjAdBgNVHQ4EFgQUWOwxOhaZ+UwcjE4sZBJAKyWPAXcwCwYJKoZI
hvcNAQELA4IBAQBzEIk46ajACN11nMYXg/dIS21UMjfpkOhv8dYzE5WMMtMhiiUG
3PnvVt/THIWResw1iW7OGjX9dTQ0mMSK59dH/eDqbLyle6HqWHJnKuZWjP5h1W2a
vKUgOvr7Oh0NelYFGUmUD+zOBWnKhUidO+R/BE0AifnnR+WbyMgpAjlWv5ErhukY
NN+wi6X8O38GM9+Q+OjF83zKOdV5CmMb0KHGr8xfE0tiqHMiJoDt+Jk4XysLUnrR
7+8qS+30a+FwErt0/dhqHI3/iEwPNc1jtuA6yP+vt4IE4sSPXUPh2Z2pm8Je2goQ
ybWqhqtMT1QoTT2E2GzJ9JBSt3yEZPEQn+kt
-----END CERTIFICATE-----

View File

@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDGDCCAgKgAwIBAgIBAjALBgkqhkiG9w0BAQswFzEVMBMGA1UEAwwMRmFrZSBS
b290IENBMB4XDTE3MDEyNDE1MjU0MVoXDTI3MDEyNDE1MjU0MVowJzElMCMGA1UE
AwwcRmFrZSBJbnRlbCBJbnRlcm1lZGlhdGUgQ0EgMTCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBAKOwrvGN7liqE0Fv0Z5jSRuYdz5WHbxNgb9HNvllM9AK
a61TKVL2yWjaDMeO3r/QmL6MbiVNLfSYzJtotbujpelZSucgFqq/6skr5K8ik1Lk
se7DrZGsheC6g9ei5UyAJlIQtCmm26xIraQWtQbSrMvMoRo25vm2LNA9fY46hx/a
zk9yPI9OLXOWuK/OnT7gmV/ESU1fLWXedVCxYZfu9KyMD2PxHG5eZc8e/Or/cVt1
5wuP16ZbzCV8NsJFKPBvfKsngznb4WuGOPTbMJaslB5wJZPp+GyBe3L0g4vr2+GE
WldoObtit9vdHj1HDcsxk2IHaQZ7zkJZ2vyGdDYn10ECAwEAAaNjMGEwDwYDVR0T
AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFCEFgTDtdHY0MnCE
8CeV32cOi9dzMB8GA1UdIwQYMBaAFFjsMToWmflMHIxOLGQSQCsljwF3MAsGCSqG
SIb3DQEBCwOCAQEAb9OPfUQSOZG5JLNJTMJtBUXWPAAhR7xXvWtG17B3c8UrU4kN
bfqAQnVkya+7vUPpaxVP5KJjzud8hBg5xqgaf7MO5mq/P+3RmtudB/AunTiBApSL
f0nXEMl3UbGdfseWnrEC0QMetsBDgPyhUAJ+P+KwEWWndpaeZRV1pfvPc2OMqG3J
or8hmfEVk2k9Di3GThsA5PnKehYE+FGHtT2+YO5Tpn75PdhN8r2N6MU7kXVPN9yi
5RT5HKpee8ZmkzYdOhWe7+7W23j3Klh3yyVHW1Yk426PRuRym9RrPOZO8dSJY0n5
abPM8+BCy4GpK/wdUuZhKBo1BX/Mq7fMfR07kQ==
-----END CERTIFICATE-----

View File

@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDGDCCAgKgAwIBAgIBAjALBgkqhkiG9w0BAQswFzEVMBMGA1UEAwwMRmFrZSBS
b290IENBMB4XDTE3MDIwNDE2MTgyOVoXDTI3MDIwNDE2MTgyOVowJzElMCMGA1UE
AwwcRmFrZSBJbnRlbCBJbnRlcm1lZGlhdGUgQ0EgMTCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBAJazRiYf5J/QajAvSmUh+HYbBebXCaf7iIbYKEd1O0eF
qXGIbaWnNss53zyrBXos38fnIUl8NNFFywegnhtk2WgyF8fOgqwL0umr32Q1KMjS
bnDMwPqZFeWuDDt+JzxIz2GnI4JqqM/N/hWeEVqk4BzGeCCjFjuI5bypyvIWua3t
bV2Z4B36VHZ0pUz5wX3v86BLgRdHggBDpwPEMEp39A494X2k9YDuZdXjEsGf9i7a
yDoUBswOZfIubBweibXOd7slvR1utzPg5AfSfR6J8DPa9/hXmcQmezWroc6MX4TR
VJwv+Bv4g5rnPKxnYkEy5oEPgi+MqHYTpju0AhXqhysCAwEAAaNjMGEwDwYDVR0T
AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAgQwHQYDVR0OBBYEFLWs0BQDIqbT/Q7Z
dOWPEHF2opvqMB8GA1UdIwQYMBaAFFjsMToWmflMHIxOLGQSQCsljwF3MAsGCSqG
SIb3DQEBCwOCAQEAH5RkL203pAaKH03VtE0Fv3Hzv08M0aDBs7OcfNY8fNX38oPT
axdZ2hf9W5TyTfIMyfZde+Lo6C26LdfRT4YQE3h9O2TdCarU58FiYfRGf1n2QAHb
rMnItYpNRjDvqe0Om4jk2fUqzbVikDSS4Ca0yu86STO8+RIAKlro5dNyQ89GAMcj
LrtzDhQRxIhDQUUfH/brOqFulNx55Fbkd60eRAASIai7t4aWLIC7K/MKkC/Mn+aH
ayYbtXbHNEPsExkIN4i7wtsKklOoflBRPxHqe8iUd3MA3sYlh6kmVGGiElx8enUT
SQMwd2Eua7amb2mvpFhQ79BvzAarkIgFII2NXQ==
-----END CERTIFICATE-----

View File

@ -0,0 +1,20 @@
-----BEGIN ATTRIBUTE CERTIFICATE-----
MIIDUzCCAkECAQEwMKAuMBakFDASMRAwDgYDVQQDDAdTVE1pY3JvAhRYZGQqyKKR
VQlbP547w/PSU3rFTKCBkjCBj6SBjDCBiTEWMBQGA1UEAwwNd3d3LmludGVsLmNv
bTEbMBkGA1UECwwSVHJ1c3RlZFN1cHBseUNoYWluMRowGAYDVQQKDBFJbnRlbCBD
b3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExEzARBgNVBAgMCkNhbGlm
b3JuaWExCzAJBgNVBAYTAlVTMAcGBSsOAwIdAgEBMCIYDzIwMTYwODExMTgxOTM2
WhgPMjAxNzA4MTExODE5MzZaME4wTAYIKwYBBQUHAgIxQDA+MBkMFUNyZWRlbnRp
YWwgVHlwZSBMYWJlbDAADCFUQ1BBIFRydXN0ZWQgUGxhdGZvcm0gRW5kb3JzZW1l
bnQwgfQwXwYDVR0RBFgwVjEQMA4GBWeBBQIEDAVJbnRlbDESMBAGBWeBBQIFDAdT
MjYwMEtQMRUwEwYFZ4EFAgYMCkgxMzg4OC0zNTAxFzAVBgVngQUCFwwMRjAwRjAw
RjAwRjAwMHAGA1UdCQRpMGcwGQYFZ4EFAhExEDAOMAkCAQECAQICAQEMATEwSgYF
Z4EFAhMxQTA/AgEBMBgWCkNDIFZlcnNpb24KAQcKAQIBAQAKAQEKAQIBAf8WGlVS
TCB0byBpc285MDAwIGNlcnRpZmljYXRlMB8GA1UdIwQYMBaAFLWs0BQDIqbT/Q7Z
dOWPEHF2opvqMAcGBSsOAwIdA4IBAQAWMj17Bk+dNYR6IHUyp/vTAh8gvgUw2Nnb
fZzbnA8nC6gLeCQYBD3F5we4YVUh9+rVv0dBwiZu9a46K3v2+kZYp7AtxyNs8f/R
ANyIUWsKOxyptqTuwEzC5UybRrRg0qVEY9hPGfZ0cas8vlhrO8TdlSuCHEYfLsgt
fYIgn6MiSG5GrGdIhWRcdNdQfeXNPjIzyXfP+1MD0CFvaDvRSphHP99mXUUlQija
9oBG5+JVahnP/LLx5q7wZZMYQtMNa+yGo2ictu/mteVgRR9KJb8RwYVMP9rflSQC
8/VrySFZUJMzGY2bFqv8WOWG3nOjaZvMV30P0c00eevObmzxrCKD
-----END ATTRIBUTE CERTIFICATE-----

View File

@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDUzCCAkECAQEwMKAuMBakFDASMRAwDgYDVQQDDAdTVE1pY3JvAhRYZGQqyKKR
VQlbP547w/PSU3rFTKCBkjCBj6SBjDCBiTEWMBQGA1UEAwwNd3d3LmludGVsLmNv
bTEbMBkGA1UECwwSVHJ1c3RlZFN1cHBseUNoYWluMRowGAYDVQQKDBFJbnRlbCBD
b3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExEzARBgNVBAgMCkNhbGlm
b3JuaWExCzAJBgNVBAYTAlVTMAcGBSsOAwIdAgEBMCIYDzIwMTYwODExMTgxOTM2
WhgPMjAxNzA4MTExODE5MzZaME4wTAYIKwYBBQUHAgIxQDA+MBkMFUNyZWRlbnRp
YWwgVHlwZSBMYWJlbDAADCFUQ1BBIFRydXN0ZWQgUGxhdGZvcm0gRW5kb3JzZW1l
bnQwgfQwXwYDVR0RBFgwVjEQMA4GBWeBBQIEDAVJbnRlbDESMBAGBWeBBQIFDAdT
MjYwMEtQMRUwEwYFZ4EFAgYMCkgxMzg4OC0zNTAxFzAVBgVngQUCFwwMRjAwRjAw
RjAwRjAwMHAGA1UdCQRpMGcwGQYFZ4EFAhExEDAOMAkCAQECAQICAQEMATEwSgYF
Z4EFAhMxQTA/AgEBMBgWCkNDIFZlcnNpb24KAQcKAQIBAQAKAQEKAQIBAf8WGlVS
TCB0byBpc285MDAwIGNlcnRpZmljYXRlMB8GA1UdIwQYMBaAFLWs0BQDIqbT/Q7Z
dOWPEHF2opvqMAcGBSsOAwIdA4IBAQAWMj17Bk+dNYR6IHUyp/vTAh8gvgUw2Nnb
fZzbnA8nC6gLeCQYBD3F5we4YVUh9+rVv0dBwiZu9a46K3v2+kZYp7AtxyNs8f/R
ANyIUWsKOxyptqTuwEzC5UybRrRg0qVEY9hPGfZ0cas8vlhrO8TdlSuCHEYfLsgt
fYIgn6MiSG5GrGdIhWRcdNdQfeXNPjIzyXfP+1MD0CFvaDvRSphHP99mXUUlQija
9oBG5+JVahnP/LLx5q7wZZMYQtMNa+yGo2ictu/mteVgRR9KJb8RwYVMP9rflSQC
8/VrySFZUJMzGY2bFqv8WOWG3nOjaZvMV30P0c00eevObmzxrCKD
-----END CERTIFICATE-----

View File

@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE-----
MIIC5zCCAdGgAwIBAgIBATALBgkqhkiG9w0BAQswFzEVMBMGA1UEAwwMRmFrZSBS
b290IENBMB4XDTE3MDEyNDE1MjU0MVoXDTQ3MDEyNDE1MjU0MVowFzEVMBMGA1UE
AwwMRmFrZSBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
geIXUAtrlc+FY8FC/bAGC6Vg1lbok+kILT/ZmG/4vdigZ2hzFR3dVjmgWd4hp3uP
dY7E/JUEouBq24qDpPUWrHIxSCqGp9Rn+whGq6Yy7d1d0FGyskIJJ2aFr1QC+/jA
4CptLbQGhqmyALrmXFai3scUmNciuTbEb3Ap9829IdsD4F9hT557zRSocaelVCUw
6sNLU78fJfG7K3dKmKemvtprqlDlfM3nya5P6IzkRKiPpXN6Q1sL7FDkKQ3HuyBM
WqPU+AWhqhCR9hRenuTpwTxEPVPA8FRV78wkV3VLzXCG7lHPZ8xCDKAZzdbwymjU
wfm9Wr5KperE83suIcIHxQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud
DwEB/wQEAwIBBjAdBgNVHQ4EFgQUWOwxOhaZ+UwcjE4sZBJAKyWPAXcwCwYJKoZI
hvcNAQELA4IBAQA2qgdehg53y1ehnq9KKdV5JllGgPon1GigMrMJ8VMGo+zs7h2q
CYlqCyuCI5hYWzZTRzwX6OAfZkIVEgY0O2lYJgTzsC+kz4EFArzq5eLqw2/hsn8c
KveCz+6mIL9AoyAMx9NZB1IytkDWIOtIElxOoAojluEDp3L1gzr9PVHJkI9KMeVV
eaH6Hg+Wg6I0jS1546oJnheEmcrwYaLJ0pHZR9NGpkICxDNMpNTLW9yy8e/kK+iB
xzT6vc3p791ktO1UD5kfK0QW8oRyMX0eHdRlDK2so+VWA5pEka+ZPc9dPB5JSudm
HBfbguS1HVpYAfJslzj31UpSnxr7ZA4OWiLf
-----END CERTIFICATE-----

View File

@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDFjCCAgCgAwIBAgIBAzALBgkqhkiG9w0BAQswFzEVMBMGA1UEAwwMRmFrZSBS
b290IENBMB4XDTE3MDEyNDE1MjU0MVoXDTI3MDEyNDE1MjU0MVowJTEjMCEGA1UE
AwwaRmFrZSBTR0kgSW50ZXJtZWRpYXRlIENBIDEwggEiMA0GCSqGSIb3DQEBAQUA
A4IBDwAwggEKAoIBAQC7tS739kM5cCJBVXGJtTgiV30AKtnDXeF5uw40DYfiXf1H
H5QAHNdiLqiZpsYJPiTnS7drsdvlzT1zjkfu11cI0jdUjMqDfSP+2MfAvrcjpdSN
R2YlcIJSNTeJyydvkxl6l0keXKdaoUkrMoJ+O0BWbSy7jXbicmndh4aoscq0Qp6s
99n4bPwrKqV/GkuTRjaUqGoEx/h9gM05kUcO5kw9xwO21ogY1H+j3NNstmTAjko+
PNEhVEp5Ax6XpqTZOqbFpiWQdA7oXJsXar0tXi0DWBWcVz0EXqoOSxhH4cpnBmSZ
ioioIOCzcxitdcWIQS+phm/B+vhK4+YUKHCF2ds1AgMBAAGjYzBhMA8GA1UdEwEB
/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBQynzPkAJcEtxU2u0uy
YG2QqJ+U/zAfBgNVHSMEGDAWgBRY7DE6Fpn5TByMTixkEkArJY8BdzALBgkqhkiG
9w0BAQsDggEBAGs9uq0DKACdcgoNyJcHzyb11EhMe8+l/D+j8JjsRp3w6rXpw60U
ptZVMh7/SpRte7NjUBJ7wk76IIhntu6rcf/ik4ptyOgSUxDzGDffQzPRHRmXmjj0
eir+cVQP34O7gByj/n92S9GP4/0RYGt7X7PGGiNArSroeS83fUQMVHhN8PbFzcrk
y9NHNR/In90Le/tPsFwGdTYzirgnjmcaVZFgCQfKuU3xr9vjANc2i5+QzzApjZ1i
K3o3z1eLOz6x25C03J8MF6GRiSV9AjrP8P0vQc25zpsjKH/rvdwmLIC6IjprF3Wk
nqakIzC7ABXdKhS8pOLkbmcoPlyt1rP9RgA=
-----END CERTIFICATE-----

View File

@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDFjCCAgCgAwIBAgIBAzALBgkqhkiG9w0BAQswFzEVMBMGA1UEAwwMRmFrZSBS
b290IENBMB4XDTE3MDIwNDE2MjAyN1oXDTI3MDIwNDE2MjAyN1owJTEjMCEGA1UE
AwwaRmFrZSBTR0kgSW50ZXJtZWRpYXRlIENBIDEwggEiMA0GCSqGSIb3DQEBAQUA
A4IBDwAwggEKAoIBAQCZyYplXrOvY6ydbaGz2aQCZB/ua+8zV2xqC2FD642BUeJm
rHWWe4tP7O2xY9m0o2RQoRsKvP8ugYO4++wLsswvQjox67oeJowWKWks29hlpaA2
cC+VMJqbMdIr18BwHxadYViv1fVMw3KDkGYAOWc1D2FuGeloscx32g+g3HAUKx1W
VdbCjTUaRFtubJKdF7bmXrf/WuOCDceUclG7309Vm8xJJlRunhgp87jhXX+GSEjb
fp8V2Msw7pQN/oh4n8rvmMX3vlVvr9cdvoKz+PmRvXal+9wm4isNt8xQRnDI8NQh
L6SRJD2WpA2CaN5MZsnOXHwc9MBazRwC3sw1ayb3AgMBAAGjYzBhMA8GA1UdEwEB
/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBTmzRQ+smIRebtqGq3J
pTUXiaK11zAfBgNVHSMEGDAWgBRY7DE6Fpn5TByMTixkEkArJY8BdzALBgkqhkiG
9w0BAQsDggEBAH8IFAMl2VeQ1nnZm/U6EFMMHBWzd0MIn4fps+K2+JE+vJT2lmUd
s5cbvoj8ikC8czPrux+t53AGnRwpfQhuPa5UdLdtT8e1GX4O9oHeGcDZVrmfZasQ
rlJ46AmI1NO7Wi6dVb2YxKJKLPdxNpWuE8YXLnwkZYdQiNDBbVRlHIQk0PjPJkXJ
qTter5DWb1Pdca0b8JBI29jDdoI9kJ0eMM8YILdo4a5B0QKwN2OBWNvlBR8O5IB6
UOPAOpdzJhzbEYLpxkxiZU1HhHPBn1YVr4G6WnN78FgPBvQXEsg78pAJca5qeZYy
MyTRDBTBp/IjiybJetKti5mOzZHtSHdARqE=
-----END CERTIFICATE-----

View File

@ -0,0 +1,22 @@
-----BEGIN CERTIFICATE-----
MIIDkTCCAn8CAQEwc6BxMFmkVzBVMQswCQYDVQQGEwJDSDEeMBwGA1UECgwVU1RN
aWNyb2VsZWN0cm9uaWNzIE5WMSYwJAYDVQQDDB1TVE0gVFBNIEVLIEludGVybWVk
aWF0ZSBDQSAwMgIUWGRkKsiikVUJWz+eO8Pz0lN6xUyggZAwgY2kgYowgYcxFDAS
BgNVBAMMC3d3dy5zZ2kuY29tMRswGQYDVQQLDBJUcnVzdGVkIFN5c3RlbSBPRU0x
GDAWBgNVBAoMD1NHSSBGZWRlcmFsIExMQzEXMBUGA1UEBwwOQ2hpcHBld2EgRmFs
bHMxEjAQBgNVBAgMCVdpc2NvbnNpbjELMAkGA1UEBhMCVVMwBwYFKw4DAh0CBQCg
7/8RMCIYDzE5NzAwMTAxMDAwMDAwWhgPMjAyMTEyMzExMTU5NTlaMFAwTgYIKwYB
BQUHAgIxQgxAW1tDcmVkZW50aWFsIFR5cGUgTGFiZWwsIFtdXSwgVENQQSBUcnVz
dGVkIFBsYXRmb3JtIEVuZG9yc2VtZW50XTCB6zBWBgNVHREETzBNpEswSTEOMAwG
BWeBBQIEDANTR0kxEzARBgVngQUCBQwISnVwaXRlcjIxDTALBgVngQUCBgwCSjIx
EzARBgVngQUCFwwIRjAwRjAwRjAwcAYDVR0JBGkwZzBKBgVngQUCEzFBMD8CAQEw
GBYKQ0MgVmVyc2lvbgoBAQoBAgEBAAoBAQoBAgEB/xYaVVJMIHRvIGlzbzkwMDAg
Y2VydGlmaWNhdGUwGQYFZ4EFAhExEDAOMAkCAQECAQICAQEMATEwHwYDVR0jBBgw
FoAU5s0UPrJiEXm7ahqtyaU1F4mitdcwBwYFKw4DAh0DggEBAGW9m5fw1JtwaYQh
ASmBg6oRGBTjz0eCb9WX858ncq6eo+OjJKv0wM4Ris/T0qjGK9VMb+H6BYOQa8y3
gDFS/tiFGpgJTnwxYwxUPOmc36lZXP85XpdLJWF8LV09Eko0eFw8Lf1nyp0N8enY
W5Tj5YCuu/W4prC8OF9nrqfkDQ0f1gYEwxd+lJCXQuDfnQ2DcrQiM+Wm8pjpRKXh
FpbkdCTRLMJHgWF2l75rR5wejJ6Ww/HEEn4p+V160TsKKezV2M7mv5G2B4Kcx3MD
KkoBytPA+4G7cRu5dl9wcaDfB7gvCZzaH+GhuwrjBpJne9s3AihQwUP6+ardJA9W
p5E3as8=
-----END CERTIFICATE-----

View File

@ -0,0 +1,21 @@
-----BEGIN CERTIFICATE-----
MIIDXzCCAkegAwIBAgIJAO6HRjma9a4oMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
BAYTAlVTMQswCQYDVQQIDAJNRDEVMBMGA1UECgwMVGVzdCBDb21wYW55MRIwEAYD
VQQDDAlUZXN0IE5hbWUwIBcNMTcwMzAzMTkyNDI1WhgPMjI5MDEyMTcxOTI0MjVa
MEUxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJNRDEVMBMGA1UECgwMVGVzdCBDb21w
YW55MRIwEAYDVQQDDAlUZXN0IE5hbWUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
ggEKAoIBAQDAYXs6PlEDkqHMZPifar+SScjG245NoXxu+oeiaRTvoOBMgmit9pj/
ZWen2T2h/78EdmcHNr8KZaVkiAkA2vb0l5Lm6F73UoygS1nUsFPHIZ8pTRtWk5xG
A2GF5vmcWYtLMxM5VFVfXfm0VNZeTbbx5TxmdDjzVHnldsHtQNp7uRkAGMhuukQL
IkQ0+sJPwvYfieN9TgiHLqyV34ZmTPaIc15iALqXx8k7p6tKSkYMvXZjQBfe1rEJ
91QaQ9e+7t/a55RL/bwGXmp8p8ZlM6H1pXHzZGlHakMgYcs3m/amoYd4f5OG+U6t
Y6fFDBacZADwgMV/QN5F0FkhVwbrNa01AgMBAAGjUDBOMB0GA1UdDgQWBBQtJ6lZ
nJfJugfQvoStHdpvyXTldjAfBgNVHSMEGDAWgBQtJ6lZnJfJugfQvoStHdpvyXTl
djAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBgayv1fPLFgPyfpJtW
ey5atj3BDVD4o2zw1EWhrgepoUhamCEkyJ+1kSeWiBbYYlGpRjCd7/x51uAENwqf
rhYwwesMf/PAPFcATHBNwv0tHaslrnPgzUQd0RktO5fWKQnRcKfjp/b37YI3h1m0
iGkeA6JptvTA+9MTAdfniHXyOE5RhSDjsbpMRNmEcpNf07EGiOqz/fGC5dDbQzRM
Put56ZEz5KedrvhJtRHSHV6jkZQp24cBsq8sotlqBeTE938K7QglBxAF21mqcagP
MShJFsKqMygNNzFioBZXIteiZPrcufVLD2SGsh45DA6mKUs0M9sseHvFsTY2qq4G
snlO
-----END CERTIFICATE-----

View File

@ -0,0 +1,22 @@
-----BEGIN CERTIFICATE-----
MIIDjzCCAnmgAwIBAgIBBTALBgkqhkiG9w0BAQswFzEVMBMGA1UEAwwMRmFrZSBS
b290IENBMB4XDTExMDEyMTAwMDAwMFoXDTI5MTIzMTAwMDAwMFowVTELMAkGA1UE
BhMCQ0gxHjAcBgNVBAoTFVNUTWljcm9lbGVjdHJvbmljcyBOVjEmMCQGA1UEAxMd
U1RNIFRQTSBFSyBJbnRlcm1lZGlhdGUgQ0EgMDIwggEiMA0GCSqGSIb3DQEBAQUA
A4IBDwAwggEKAoIBAQCTt4oZ/7h4Fdx65T2ab/PtfsYPXHC396VVyaE+Z/Dxx4sT
emUQZn/zYPOfzg2c8Z6LQuuFg/BhzC8kNAp2tzCRfjBiWeUeSZLiUQeArYEz8HE1
WSLArrqdGg1pz82Kh8L32og9hQ9GmsQp0yiI1lPTs7Uw9iOtcVtiyhGOFXXvltwu
1mYEuU6apG4Sc8tjSY+qEjAypJXyN1/I1X+254DHAkd19zXCKN+PSA7da9Rn8Afq
Fq4aIGVZzBSSgKEmD/GkKyw1Ze0kDgIE189iAw+m6NY4Gv/Cm+9nQ4fA9qq5Kloe
x8HWrN46qm2/boqujtnSSWPOhY3341z6N4xpRY07AgMBAAGjgaswgagwDwYDVR0T
AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAgQwRQYDVR0gAQH/BDswOTA3BgRVHSAA
MC8wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cuc3QuY29tL1RQTS9yZXBvc2l0b3J5
LzAdBgNVHQ4EFgQUVx+Aa0fM55v6NZR87Yi40QBa4J4wHwYDVR0jBBgwFoAUWOwx
OhaZ+UwcjE4sZBJAKyWPAXcwCwYJKoZIhvcNAQELA4IBAQB8IaDIWicxm7m2qyDv
v4L253D3qRcx+sdM2GM0IpvK3u9z3BQraAhF6PPLlgFGP6slZdDY6ryrP8PEkvsH
tHoapB1MWe+eMrxw7dXQLnpzm/P++8AWMtY8roziiO7x3AYTbRb9lB2HjOWc2aGZ
1xW+su+aTnr9U4uYO1+HrDDKYgkypIcousRwUMW6c6szAZY2UtWS2e4346V3LVLz
sv22n4rqWWRzJ2tl+jIqLepChqOdgscDL+aO2iowmzTSWV/WLJRaTs0AsOYJkdlG
8wWRzygRbfGdIL7A/hKK42o0b7v3R/NI0nemwAzVN/QOYjTbkOCIUBg/6mT8CkYx
pmiq
-----END CERTIFICATE-----

View File

@ -0,0 +1,23 @@
-----BEGIN CERTIFICATE-----
MIID1zCCAr+gAwIBAgILBAAAAAABIBkJGa4wDQYJKoZIhvcNAQELBQAwgYcxOzA5
BgNVBAsTMkdsb2JhbFNpZ24gVHJ1c3RlZCBDb21wdXRpbmcgQ2VydGlmaWNhdGUg
QXV0aG9yaXR5MRMwEQYDVQQKEwpHbG9iYWxTaWduMTMwMQYDVQQDEypHbG9iYWxT
aWduIFRydXN0ZWQgUGxhdGZvcm0gTW9kdWxlIFJvb3QgQ0EwHhcNMDkwMzE4MTAw
MDAwWhcNNDkwMzE4MTAwMDAwWjCBhzE7MDkGA1UECxMyR2xvYmFsU2lnbiBUcnVz
dGVkIENvbXB1dGluZyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxEzARBgNVBAoTCkds
b2JhbFNpZ24xMzAxBgNVBAMTKkdsb2JhbFNpZ24gVHJ1c3RlZCBQbGF0Zm9ybSBN
b2R1bGUgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPi3
Gi0wHyTT7dq24caFAp31gXFDvALRGJrMiP+TunIYPacYD8eBVSNEiVoCUcVfYxzl
/DPTxmRyGXgQM8CVh9THrxDTW7N2PSAoZ7fvlmjTiBL/IQ7m1F+9wGI/FuaMTphz
w6lBda7HFlIYKTbM/vz24axCHLzJ8Xir2L889D9MMIerBRqouVsDGauH+TIOdw4o
IGKhorqfsDro57JHwViMWlbB1Ogad7PBX5X/e9GDNdZTdo4c0bZnKO+dEtzEgKCh
JmQ53Mxa9y4xPMGRRnjLsyxuM99vkkYXy7rnxctSo7GtGIJJVabNuXZ0peaY9ku0
CUgKAsQndLkTHz8bIh0CAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB
/wQFMAMBAf8wHQYDVR0OBBYEFB4jY/CFtfYlTu0awFC+ZXzH1BV6MA0GCSqGSIb3
DQEBCwUAA4IBAQCVb7lI4d49u7EtCX03/rUCCiaZ64NMxxqRmcSVdUx6yRrbl8NN
FNr6ym2kTvwe1+JkTCiDxKzJsOR/jcPczAFiYpFbZQYLA6RK0bzbL9RGcaw5LLhY
o/flqsu3N2/HNesWbekoxLosP6NLGEOnpj1B+R3y7HCQq/08U5l3Ete6TRKTAavc
0mty+uCFtLXf+tirl7xSaIGD0LwcYNdzLEB9g4je6FQSWL0QOXb+zR755QYupZAw
G1PnOgYWfqWowKcQQexFPrKGlzh0ncITV/nBEi++fnnZ7TFiwaKwe+WussrROV1S
DDF29dmoMcbSFDL+DgSMabVT6Qr6Ze1rbmSh
-----END CERTIFICATE-----

View File

@ -0,0 +1,26 @@
-----BEGIN CERTIFICATE-----
MIIEXjCCA0agAwIBAgIUS5gujeW5kYvYdMJZlIUT6s3F0cwwDQYJKoZIhvcNAQEF
BQAwVTELMAkGA1UEBhMCQ0gxHjAcBgNVBAoTFVNUTWljcm9lbGVjdHJvbmljcyBO
VjEmMCQGA1UEAxMdU1RNIFRQTSBFSyBJbnRlcm1lZGlhdGUgQ0EgMDIwHhcNMTQw
MjIyMDAwMDAwWhcNMjQwMjIyMDAwMDAwWjAAMIIBNzAiBgkqhkiG9w0BAQcwFaIT
MBEGCSqGSIb3DQEBCQQEVENQQQOCAQ8AMIIBCgKCAQEAsdTxu5pRjEOgA0tCNYgn
NmAqLzIxBTBft4pMBGdEk922dvBLvQySN13YnvVF6FnYCc0Y+5hSAZiRCcXpr/M3
6wx5YkePCPss06KQMujy3X9jwxTU0cDbKTjKCmFpQqCqiGIk2f7mss8yIABlwT3R
cBBbcDpGn2wYi5s9UhUfCOQ6D7qEPKJEi5IQC7/oyu5zT5FMUANdsebxrYpALcKK
8/mp5Rwj+xmaAg/+OC9jIeFGLYYu/hQr/1BPYSVicfuIFdc/0VzyJO5KMRozvV3I
2dbzQwqUD4xUxPR+f7VC+3p641Mb7WobIZH7wJm2k0M8HWeErytA66WtAoueU89O
iQIDAQABo4IBZDCCAWAwHwYDVR0jBBgwFoAUVx+Aa0fM55v6NZR87Yi40QBa4J4w
QgYDVR0gBDswOTA3BgRVHSAAMC8wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cuc3Qu
Y29tL1RQTS9yZXBvc2l0b3J5LzBVBgNVHREBAf8ESzBJpEcwRTEWMBQGBWeBBQIB
DAtpZDo1MzU0NEQyMDEXMBUGBWeBBQICDAxTVDMzWlAyNFBWU1AxEjAQBgVngQUC
AwwHaWQ6MEQwQzB/BgNVHQkEeDB2MBYGBWeBBQIQMQ0wCwwDMS4yAgECAgF0MCAG
BWeBBQISMRcwFQIBAAEB/6ADCgEBoQMKAQCiAwoBADA6BgNVBTQxMzAkMCIGCSqG
SIb3DQEBBzAVohMwEQYJKoZIhvcNAQEJBARUQ1BBMAswCQYFKw4DAhoFADAMBgNV
HRMBAf8EAjAAMBMGA1UdJQEB/wQJMAcGBWeBBQgBMA0GCSqGSIb3DQEBBQUAA4IB
AQAb50G/d9D18ahy6RScXObaazgrNZHcF0otH9W1uJzXgSQPjFFYbHAh2+EGI8uD
90Hj9XgZYmcGv0pUHcFw7msNamr3c/Or8+pLPnu5OZtr4jCEZ7/Z75v0Z825Ov8R
N+JIxB9RT0Yd3KAPQsp4d45NHWOPBQPgBi/pW/eJqPO2MJD0uraRqAlNrUD3ppc7
xxsmOoOhyUFcs14KyrgIWNazx+4EElAKU3PthU70cszFAQM2hw/EYBfRwQ5rVZd7
V2x9hMC4POgACE6gVIDV/mHoZe6AfGQKveblJEX9gOccI28vnT14d0CwhN/SvgZF
JigA9V7w26ecFRWXpm79utMU
-----END CERTIFICATE-----

View File

@ -0,0 +1,26 @@
-----BEGIN CERTIFICATE-----
MIIEXjCCA0agAwIBAgIUBwCBhWf/NXkWkNLUBJRd9WsObccwDQYJKoZIhvcNAQEF
BQAwVTELMAkGA1UEBhMCQ0gxHjAcBgNVBAoTFVNUTWljcm9lbGVjdHJvbmljcyBO
VjEmMCQGA1UEAxMdU1RNIFRQTSBFSyBJbnRlcm1lZGlhdGUgQ0EgMDIwHhcNMTQw
MjIzMDAwMDAwWhcNMjQwMjIzMDAwMDAwWjAAMIIBNzAiBgkqhkiG9w0BAQcwFaIT
MBEGCSqGSIb3DQEBCQQEVENQQQOCAQ8AMIIBCgKCAQEAvcrvqYUTomoUC5zk5Jhd
myVzoEe94eXX1YFHyElCCpLM4/86ZbADKTHeGwygR4AWClb0Jmmloj+aIRUY3pZD
2GVxDnmD9CBS+60doM1cN0+D01hhg7J/dnaigAbFxPZauSyV9XfTqq1MQlxWpUEf
J4IALc+MhVd0kqSzzqSDxoneu83w1Ssvmah73wqWpansqQRYr1D7ABbkvouO56iu
4z6UditUSbrk3FrZBs+e73tzy9OAzQBg617kU+BKhHCRuRIPYk3tPXHq53Y7Jwvf
CkiEVWAU+MEMZJc/RRIOnWdSdDMxHZVnaxywrC8KUKZ1G3id/GVJfeivPxZVRBdh
sQIDAQABo4IBZDCCAWAwHwYDVR0jBBgwFoAUVx+Aa0fM55v6NZR87Yi40QBa4J4w
QgYDVR0gBDswOTA3BgRVHSAAMC8wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cuc3Qu
Y29tL1RQTS9yZXBvc2l0b3J5LzBVBgNVHREBAf8ESzBJpEcwRTEWMBQGBWeBBQIB
DAtpZDo1MzU0NEQyMDEXMBUGBWeBBQICDAxTVDMzWlAyNFBWU1AxEjAQBgVngQUC
AwwHaWQ6MEQwQzB/BgNVHQkEeDB2MBYGBWeBBQIQMQ0wCwwDMS4yAgECAgF0MCAG
BWeBBQISMRcwFQIBAAEB/6ADCgEBoQMKAQCiAwoBADA6BgNVBTQxMzAkMCIGCSqG
SIb3DQEBBzAVohMwEQYJKoZIhvcNAQEJBARUQ1BBMAswCQYFKw4DAhoFADAMBgNV
HRMBAf8EAjAAMBMGA1UdJQEB/wQJMAcGBWeBBQgBMA0GCSqGSIb3DQEBBQUAA4IB
AQAAbZng7i2L22p05GpbURYk6o7bYH3LZ+nusEGvi0tRkpqr9Qc8vMp8fgYQMaZV
8QiDa5JfYD3vzOjQBRvUdqz8UrzemsuErk4w3yzsBh2lIY54jcXWmJFVk4HVp2wV
xL5EysIII9Fkt2gfcoPSGyIDX4p83Vou5nhNOQPowahMuS6BUfcBKzMM7pK40GUj
N+cijK61zPkvAQArEkAnVNuTxvLS41WW3x1kTtkLUPuTh7SynNAYwoVfl19uNPOs
UTxDrFA7But7Vo0xoj+zSBQqzk0Gp3Pldw6mOUc3uI1UBmVtQGRy7cgsbLJ3bu/6
fLuuAG5/ywVpo4MiG+PkFYXh
-----END CERTIFICATE-----

View File

@ -0,0 +1,23 @@
-----BEGIN CERTIFICATE-----
MIIDzDCCArSgAwIBAgIEAAAABTANBgkqhkiG9w0BAQsFADBKMQswCQYDVQQGEwJD
SDEeMBwGA1UEChMVU1RNaWNyb2VsZWN0cm9uaWNzIE5WMRswGQYDVQQDExJTVE0g
VFBNIEVLIFJvb3QgQ0EwHhcNMTEwMTIxMDAwMDAwWhcNMjkxMjMxMDAwMDAwWjBV
MQswCQYDVQQGEwJDSDEeMBwGA1UEChMVU1RNaWNyb2VsZWN0cm9uaWNzIE5WMSYw
JAYDVQQDEx1TVE0gVFBNIEVLIEludGVybWVkaWF0ZSBDQSAwMjCCASIwDQYJKoZI
hvcNAQEBBQADggEPADCCAQoCggEBAJO3ihn/uHgV3HrlPZpv8+1+xg9ccLf3pVXJ
oT5n8PHHixN6ZRBmf/Ng85/ODZzxnotC64WD8GHMLyQ0Cna3MJF+MGJZ5R5JkuJR
B4CtgTPwcTVZIsCuup0aDWnPzYqHwvfaiD2FD0aaxCnTKIjWU9OztTD2I61xW2LK
EY4Vde+W3C7WZgS5TpqkbhJzy2NJj6oSMDKklfI3X8jVf7bngMcCR3X3NcIo349I
Dt1r1GfwB+oWrhogZVnMFJKAoSYP8aQrLDVl7SQOAgTXz2IDD6bo1jga/8Kb72dD
h8D2qrkqWh7Hwdas3jqqbb9uiq6O2dJJY86FjffjXPo3jGlFjTsCAwEAAaOBrjCB
qzAdBgNVHQ4EFgQUVx+Aa0fM55v6NZR87Yi40QBa4J4wHwYDVR0jBBgwFoAUb+bF
bAe3bIsKgZKDXMtBHvaO0ScwRQYDVR0gAQH/BDswOTA3BgRVHSAAMC8wLQYIKwYB
BQUHAgEWIWh0dHA6Ly93d3cuc3QuY29tL1RQTS9yZXBvc2l0b3J5LzAOBgNVHQ8B
Af8EBAMCAAQwEgYDVR0TAQH/BAgwBgEB/wIBADANBgkqhkiG9w0BAQsFAAOCAQEA
Z0ndTDcOJ+N2Bd3jN1PrK7XVYFA1F8k32nMghdw0EKZpKiXq2cZxN3ddpZ1p59Ob
7HdoAab6u+iRAgECltO8IAD8ErSCgALHdBJAFE8U1VNiRoyu/HRtQI4sIBxNvDNk
5wJFjGHIBaOoIQwcKJ7jsSEp7Q2nRgJMLzC3ASCtYfnUd3nVXb9BLKw+Vow9NHUj
Rkch3aiOw1UinsV5Wan7ACR4tiz1Wei7WZJaVvichlh1h9IPbsp9q+9JI6eLK2op
Ftb19uKLOcqFqGPzGT8I11EM9+dwxBAkdP5RGV7SxDsmypp/jSGm8z/1GVjxHMmR
xrLFG6E70rpI/l63rlv52Q==
-----END CERTIFICATE-----

View File

@ -0,0 +1,9 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyGJpmVcVj6P+gZ0U8fvx
CixxPjNwW+dKXT9FaeIMpYvwfoQKlBdQNy9VH1CeV5ovUMTy/Z2dIKI+GZ2F2lUD
XLhMsN7N2P8pqQ7y3wkG8A2eP2WmOYtYj/Jg1h4TDtzxLcEaHuY9e9T7GQsVINPj
aXaUNpncns4+wgP9PE/9vasvSuj4JOAdaZ0AYE1nA+s3wfT9fbF92lUta0zRgDw5
o1D0uzciA3VnHePA0bSMq5onNLzdFXQwqvwHFE7hYGUbmmoun7t+g25YrYuk0wV+
AB0dIfiLNk5ySMNn4YkLkKQmbbeeG3nb6BiVFzVHdYsIVmre++8wTC0WWJq8SsIL
KQIDAQAB
-----END PUBLIC KEY-----

View File

@ -0,0 +1,46 @@
-----BEGIN CERTIFICATE-----
MIIIHTCCBAWgAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwSjELMAkGA1UEBhMCVVMx
EzARBgNVBAgMClNvbWUtU3RhdGUxDjAMBgNVBAoMBUludGVsMRYwFAYDVQQDDA1J
bnRlbCBSb290IENBMB4XDTE4MDcxMTE4MTAzMVoXDTIwMDcxMDE4MTAzMVowUjEe
MBwGA1UEAwwVSW50ZWwgSW50ZXJtZWRpYXRlIENBMRMwEQYDVQQIDApTb21lLVN0
YXRlMQswCQYDVQQGEwJVUzEOMAwGA1UECgwFSW50ZWwwggEiMA0GCSqGSIb3DQEB
AQUAA4IBDwAwggEKAoIBAQDHnFB0pCfGKgaJrmURmL/fjPHWwrycYH43XGypdxga
lLxnZAu1ydvrSYTwSsGYtXu4+o74qy4ntazTP/V04thrwzmKecDpwJzgO+Vs3OOT
X238Z6RAEhzx0lnigAWd5eFFLDV7GHjN36eHdEz7RKggoxkaSPu1XFbcamseyeSl
GpddMf7dBwyqrPFXf63gCacuQChVWA1sVFbR+IACgGQH/cVYUpoWF8JWAgvWAuIS
3Bb7nSF5SUl1aV7QMQLrJQxMr18vqX/0ajnad6jOeOHo+NFdnr/7kebuPpoVLpHo
27ny2Cp3kC9g7cQU0ijYHYmdhXayVPxJ/+T8QNWFp+2lAgMBAAGjggIDMIIB/zAP
BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSs0nif51+eoH1QlFkIe3uHcdfQhDAf
BgNVHSMEGDAWgBTz4tyrFw4DWPlY4DRglUoP6ZXsXTALBgNVHQ8EBAMCAaYwEwYD
VR0lBAwwCgYIKwYBBQUHAwEwbAYDVR0fBGUwYzAyoDCgLoYsaHR0cDovL3BraS5z
cGFya2xpbmdjYS5jb20vU3BhcmtsaW5nUm9vdC5jcmwwLaAroCmGJ2h0dHA6Ly9w
a2kuYmFja3VwLmNvbS9TcGFya2xpbmdSb290LmNybDBDBgNVHREEPDA6ghtTcGFy
a2xpbmcgSW50ZXJtaWRpYXRlIENBIDGCG1NwYXJrbGluZyBDQSBJbnRlcm1pZGlh
dGUgMTCB1gYIKwYBBQUHAQEEgckwgcYwOAYIKwYBBQUHMAKGLGh0dHA6Ly9wa2ku
c3BhcmtsaW5nY2EuY29tL1NwYXJrbGluZ1Jvb3QuY3J0MDMGCCsGAQUFBzAChido
dHRwOi8vcGtpLmJhY2t1cC5jb20vU3BhcmtsaW5nUm9vdC5jcnQwLAYIKwYBBQUH
MAGGIGh0dHA6Ly9wa2kuc3BhcmtsaW5nY2EuY29tL29jc3AvMCcGCCsGAQUFBzAB
hhtodHRwOi8vcGtpLmJhY2t1cC5jb20vb2NzcC8wDQYJKoZIhvcNAQEFBQADggQB
AE+ju9M/AvwP5IGOyK92rlPI3VhZ3xDZMHYorDfPCqydf9w+xDsnpbXop4Gdi//0
SlOJCEbFa2oCt04JOJE986HuTfBLVZT9CtoMxOUEN2jWRq5ZZgHNqNPKqp59cxTm
KgSjDv3ch/OnbmVNxxgH79obCnBI0lBy/tlC7GoeOyL9KtDZ6Kp13Fyyn9dtFxu9
i2nYlf2mq6RPQBW9ZXUVYDLSllASSy9FVoK0BfsWa3eHwwBgNJGH4ZpkbIuaXN+U
io4t1SnGHN3QLvDpNprK3mItkbC0BDAzbP/xDHFrjPSWS04HUyn8JHHHgUcnET+p
1SU+PJr82NbdPVl6/n+xMVMaaFdDlDyZx6D1jQNKOJDCemdujbW4ndpcUoFp/mds
IWulrYTu2IJQvuqOvXGSfg4AE5FqbAZDt0xvWOl7vcMkZuL5Sl4kWbzoV63KjMT5
o+YeMyF0ExIuCWhYJ4eI0f3S1e4hS/1h6wXXR5aCsnL7jMoFjD+zn8rfjaohof5Q
pV9xwDRrY3ySrpQ9cm8dJCeTeFzW4kqZgIiUlMMIh1VQExGNsnp9DHHGwqzqpyRC
vCj3UkaGgvth8elNATBdv8ONoHklpjQFSTnRAU/MSBE+kUrTdw/bETLU11Azn/bt
BTxikRssprLKxeExoa3jm+Vavkkfu+dY+NSHJVVIUXu8PkKjNNJbPeNx9qwAYgGA
AqgGGchZrBdvNhkoUKTJmDRIF5jM7DG34yC83x5T6lzp1OciGaXf3jRXghKBojI1
jxAvZG6FBHdzwPAOjsY21yU2TbXrxQ8j6Z9fOnQ9vmmpMM2oqthaCxGRAzDrDdFT
O2FRDt7d72rgj6oRIl3H39C0l4z5yXO6kd0uAz35aGxpKGIJTJY7nLtRx0Ajmhdf
/40si5xEgpFyzXA/ZIYy9TPJxZkOTlJI4G32Wvdhj2hZSwQOCWoI2cmQbnzkC0w4
ad1H/+YBiB2wqypuwpREwsjvo5GPVNhYg8S6dC7yfFMlKyNtAoPs4KdaatI4rgy3
av/zt9jxBC67LVIRuOM00wTLJzmfwcbMuOgr3p42x7MoZ6YRKd7yaAvTvmhPXaZV
dXiceCxofbbcTDputNakrrFRZ9Gijs85lDX+5/Ify4ageHfLxp17sDdYXN+13Jxd
ApI1vlEKlhJlyUCl+wYIVmh1h6X8gM5JIqWIuI5fUMzrD1Qw67vEhRTbDumL9JU6
IealkhroBbgZb04WTJ+5hqrYRcS38Z3Vxx3IbRnXx/nRpN6UkyP2JpgOj+oaea0k
yHloDdHH9JDQpHxrQ64aEtHJUEEdBIAvKD9pJCnQxuXx+SMvNr+bwdX0WnkkfuxG
sXy5JPb2g9iuxtRJpy+N6AM=
-----END CERTIFICATE-----

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpgIBAAKCAQEAx5xQdKQnxioGia5lEZi/34zx1sK8nGB+N1xsqXcYGpS8Z2QL
tcnb60mE8ErBmLV7uPqO+KsuJ7Ws0z/1dOLYa8M5innA6cCc4DvlbNzjk19t/Gek
QBIc8dJZ4oAFneXhRSw1exh4zd+nh3RM+0SoIKMZGkj7tVxW3GprHsnkpRqXXTH+
3QcMqqzxV3+t4AmnLkAoVVgNbFRW0fiAAoBkB/3FWFKaFhfCVgIL1gLiEtwW+50h
eUlJdWle0DEC6yUMTK9fL6l/9Go52neoznjh6PjRXZ6/+5Hm7j6aFS6R6Nu58tgq
d5AvYO3EFNIo2B2JnYV2slT8Sf/k/EDVhaftpQIDAQABAoIBAQC9dxOvAzl1kOJP
wSbRwwksqd3LGWBplfV3mtTRLefFIzSJdp7e2FFUTZ5PbsW/q1NaSwl14xWWP41h
nq3fWopODyoI1HRV66t7855a7HdepRACqmVvI0IyDpWetiGetFpUjBffVWUlFIsx
uSRww8RJ5kWne2rfxFv2L1SqDrxmMOAPrUpMegjxDqEYYZ/wTrTUrEiGlmU5UrBp
4WID6siJJFrAaHYeN7qo1OcOoYVk40q0g3kZarLyV5nlfQG+iC1oSHK5VJEJQbFm
xV8MiUFE2LJUM9DiDPm6OyTJMu+gFC/MsC+jxcXqleBEVBhpFfLcfTTN1PQEzJZk
yQ22j4XBAoGBAOaHsKhuefnka5Bm4Z6cXK8kIAIOsiF0aYNOrEa/q6Hb/bNSK2SC
jVxK9pomHmCvrt8GFq1hkA9y/GNR4+26WSb1XZcOUr9IGRFZ0oBbgYhm9zr+gcL+
QrtPyPPs8dMlyJz/QhO3/sgc1eCrQoAgahzrW+XqTt79nVjHGtFJpyatAoGBAN2q
GV4Hnci59eCvSYl9pFajQwBtc8GdQ7gT2svtVdjhd6vgsK9OS9VUD6q6VcKOecH4
+SAcancifYZwmfowAbNHrGfybTzI6m+nuK6X/JoFEGXZBql9Sg1CVnmixOTwrHGR
YrpTZOJ8kKusT5A8DKEbe3sF9gYledG6EZHDXlnZAoGBAIfiF4lQhWl88MJPQlJh
zGgYHR3ZV7pMih0x9G5HcH2Z1LMsjhNSuMxcC3vVWDaZl7QyPI+6YFYa6xYIIRfx
rbc/DgmKEdBaSRxnG6M5TOL//l6xwf8ULHWIk+TkF67kKJoSA/rni7Cc/pzNlgc8
FBAz0xl0wUTDrUm1IuOWTIaJAoGBAIX3/TboUYN0aNdv+Xjgd8dpCuCiRhjZbIk/
brhba8wVkNdPiFmbb5eyI3ni/lwE8i+6ww6WPf5c2RK80UL1asGo6tk0GrNnFtF+
w865yxBnSR7VCQK811mmI0+GgYuArihBXzMPneSItoMbNEcPE+73Bi03UBcs5TBN
TbsUId0ZAoGBAKnk0lqK5yBNIjUwHWut4kVu1m3vhSk3TjEiWYAqwbsVK4f4ilDg
CHoUq089If5eOuf57MZvvtFpQFD4aRVq8O+3regCD3iTHUVHS6zFAJOY02RultPc
7hmNyEiZb1W65IIqo1inFqytpaeYGF0yE0Q2ThN+b3sNp+VAcLlJFy3o
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,53 @@
-----BEGIN CERTIFICATE-----
MIIJZzCCBU+gAwIBAgIJAIFBJBb0YU91MA0GCSqGSIb3DQEBCwUAMEoxCzAJBgNV
BAYTAlVTMRMwEQYDVQQIDApTb21lLVN0YXRlMQ4wDAYDVQQKDAVJbnRlbDEWMBQG
A1UEAwwNSW50ZWwgUm9vdCBDQTAeFw0xODA3MTExNzI5NDVaFw0yMzA3MTExNzI5
NDVaMEoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApTb21lLVN0YXRlMQ4wDAYDVQQK
DAVJbnRlbDEWMBQGA1UEAwwNSW50ZWwgUm9vdCBDQTCCBCIwDQYJKoZIhvcNAQEB
BQADggQPADCCBAoCggQBAMaTbBGL71la9mGMquEKZHXOxCCznNOgRyYIlAANxHEu
lehj2wZ8BdUfezWyv1+/O3GPCGz2w389qW5h2Kb5omZQ4yRRYZrsaeBCJ2uoug08
mTfhX2IQvoOZbvx8RKfHbXz4Zx/9xkDcKOPdUWTXrkxp79HmdPcmmEbaZc4P4iMz
Yu91WHnW80el3iH5TlYIg8kIdT5AxBWN46gm8Y2LDKtcGZqUtPN+9Ge3LVt+Z6+f
5ZPsg4WcNubXiRHz8Y57b175chOslXenwumbPbXwDoLl0sonlP+BD25mQoVIFCNg
gknbgF9n1QPEGSp/hEYUIsOubcbJWyxMviBsn6iAXQV8YeYrLTR/hAmTwIDH0tK+
K/cwQ8FEvdMU1zAP466E5hyi5RWDl1r2dqoT6gvmkgFPo9Gt+w0mizeO8ZfaMRrU
jxbH8dwIuNmUY8yJytkNnoNbG10MH7MNDhyQOKUe9ix8U7bs5MHrxPZ1bGjVuIws
nqjsFaZRz7fqFV6vkSvyC0bAGcyUxKFG7L8H6GP8MzpwXTGh8sa1AbINx0URHBYl
b+PIC1njA/K+Y1n6ObWoDQ+H+0LQsVyAuFrdeYBPkFlDBzGlE0h1Bj1SV5Vw3+5g
WIZx36G/p0mw6PF+EaYgcUfwPjwlAlQ5GkN226YIwYj70NqvCl3ATH8SJZyB9FVH
8Rb6KgxVp421kQRHVo1vhKRPkuDT5/RfLvFjV818XcQV5JVKB53DFscNWvxC8lU6
d+a/kf/ZiW4sdr2zg4Jz9iHkiNJQW1LZ2dchefM6rJcvOF++3Q5PHC+3n3Fz2HKs
ik2CDtPHFN9Fs7Z2TbApQBhkd2E8U0ng4JamHmCTmcH8P5Eq7NbNOcFLmmp29wvB
DOednh4KFyS2iufogLN7ESKVwYkSIyhTQpcUGLAGUe1pQKM6xGDRZwuQ54tgQjDF
qiw8zgckd6lv8bSN2tCWO9Y90lOr/HsmWJZD9yqcPAwv+ca5AoRtUR/oXYkeFBx/
COZ22KDNpIzMnatCJytZZYpVw36NA+S6Wkl3BMtZuHdI//v9mfgyMEP2P8J1SqlO
bzOAjwRsQ9ShmjI8TbabPGeIa2/8gR7zb6QCSVLm3IDwIJg5XwlpoBpc3Ff/bvSx
LtIwURV3/QEg8Igqvz80ViPeideOARDhgMgiOPe40zZuQyUMKAnGe624KY8K5lqF
EEkcc/MNglO5vwuZ62e3H5fRDmL9dzqZj9MwDthJpn5bE3XkDB1JKeSbDtExAevC
QGBDbaHh9Gh5rSrzB11e/EJjN7M5yPWCD1edHav0qe4YYcoJrAa8J5+mX8KHCdQD
mq+SaMu6ztmfUWBbxvLXiOMuYp6QORZdRgxFOrLpOBsCAwEAAaNQME4wHQYDVR0O
BBYEFPPi3KsXDgNY+VjgNGCVSg/plexdMB8GA1UdIwQYMBaAFPPi3KsXDgNY+Vjg
NGCVSg/plexdMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggQBAAWDrJlS
VVTI6px2gIBAeZhjaYjvoJnpw/zliLE42stgPnQd6vx4iztq4IHnHxTUAT5IXRL2
llDZ9n80+NidIqiATrGzKfev804uetBn8kqzpgPRBVfELDGC4dlz9khre/1Qxx7x
zn08eFoDukzcYFfJuKRDQOhRfbEU50VjdtTRaqC2W8EziscDXYR6kWE7ngr9E3pd
MEOnBeNz6ETcMl1/shvg2vsOmJ05AUvfEn4Qp8Z1x9XuOOFKBOeErGMxafWuM/AJ
ZlRV1KVzWXHq71qZxhfEg9nJXEAUh+ydSXS0aik57EJ/X2DS5fjN6ne/S5VrtV75
OI14cIxRu76OpdYI3G3ZcZFkllQmYEfdXsr4C1otHUwC7bta8Ykno/vOQgGhGLQL
kdJ8ltXRfOw5DJtNr4qupClEFjNPNm4vCPCrnYZ7g4fJJgHxRUQZHQAsH+F9yUlb
KsAA1VczCEolF9Q9WLTDLxI6/Ikd69ILZwfkCO3RO3tnASMvmzKNgrPO8BgHgpMG
D9KLcu3Y/ISLjMOUJlarY2MU/8VV6TpyQmkw4Lubw/FgHnxKdyjFxpiU2ze8wt5/
qwXkIqSjoZhIhCQPpENGbejgxq5Ia/uvN3ME60d9vO+5afgfNPiBDcBJAp27VZwa
pAIR0ZiLxITqe8/FxlpjMjERe7Afj2uTf8oDidgD2hpi3jv899r8fRcTSDRM7vDA
RHKnpp8aGQPW2LzQSZ9ob6bsch7Uy/0CHJ054gw+aGKcGwIyQb0dR/FLiO3rT+65
7KxbLq76Qr42MItl/bLLdAnL8HoM1l6kKkvIQyqg8NDn3BipTUU4TIJdGlRnQ6S8
QuVMPj4bPg04BXiN/PKHDhh6EtD3Mwqwwv0lpcb61qvhjPBH3N02wh2SMdQ9HLMb
L03iR/XxQNhXp790DHpHNMmfJXAQ2ejgow5ZY1zDNKtZX9JA4FPzFDJD4ydmUDcg
CLD8NulW1U9oC+gMdwKdyn9gaQQ5W2yHr6pqWl2dVCmCa/kGowkTvOaet+syZEQJ
No7Usg0wWah3sKVlJy6AEJEec4Xe+45+Kr14Qbad0AHQvTHvALYL+LEKKGTA0mMv
0TftEOt05qPP8q+J6Edb1gDG6Nvv/q12uC0e5Vm7E3n0pFD4k60Gi/HFPOCX2KZQ
R1Rcv3DX8vDrrMdQA/Eh58guzGdilCvBgdVg6FeKgjTnGs+/LofaE25wQgy3Jiqs
aGS3LXvHXICMGF5UliFHoMSCR1qEPRqCUeVrFq+Guj+awTiVnHQ5MPMa7eKw0vfY
Yu3K5Sj3NtqNqrtGL1GcpYdADyDLcjIjKYJOOD1ZzQI2pUBdBZTf2fbmqcebV6dj
zfHGCye5GIHptPQ=
-----END CERTIFICATE-----

View File

@ -0,0 +1,99 @@
-----BEGIN RSA PRIVATE KEY-----
MIISKAIBAAKCBAEAxpNsEYvvWVr2YYyq4Qpkdc7EILOc06BHJgiUAA3EcS6V6GPb
BnwF1R97NbK/X787cY8IbPbDfz2pbmHYpvmiZlDjJFFhmuxp4EIna6i6DTyZN+Ff
YhC+g5lu/HxEp8dtfPhnH/3GQNwo491RZNeuTGnv0eZ09yaYRtplzg/iIzNi73VY
edbzR6XeIflOVgiDyQh1PkDEFY3jqCbxjYsMq1wZmpS08370Z7ctW35nr5/lk+yD
hZw25teJEfPxjntvXvlyE6yVd6fC6Zs9tfAOguXSyieU/4EPbmZChUgUI2CCSduA
X2fVA8QZKn+ERhQiw65txslbLEy+IGyfqIBdBXxh5istNH+ECZPAgMfS0r4r9zBD
wUS90xTXMA/jroTmHKLlFYOXWvZ2qhPqC+aSAU+j0a37DSaLN47xl9oxGtSPFsfx
3Ai42ZRjzInK2Q2eg1sbXQwfsw0OHJA4pR72LHxTtuzkwevE9nVsaNW4jCyeqOwV
plHPt+oVXq+RK/ILRsAZzJTEoUbsvwfoY/wzOnBdMaHyxrUBsg3HRREcFiVv48gL
WeMD8r5jWfo5tagND4f7QtCxXIC4Wt15gE+QWUMHMaUTSHUGPVJXlXDf7mBYhnHf
ob+nSbDo8X4RpiBxR/A+PCUCVDkaQ3bbpgjBiPvQ2q8KXcBMfxIlnIH0VUfxFvoq
DFWnjbWRBEdWjW+EpE+S4NPn9F8u8WNXzXxdxBXklUoHncMWxw1a/ELyVTp35r+R
/9mJbix2vbODgnP2IeSI0lBbUtnZ1yF58zqsly84X77dDk8cL7efcXPYcqyKTYIO
08cU30WztnZNsClAGGR3YTxTSeDglqYeYJOZwfw/kSrs1s05wUuaanb3C8EM552e
HgoXJLaK5+iAs3sRIpXBiRIjKFNClxQYsAZR7WlAozrEYNFnC5Dni2BCMMWqLDzO
ByR3qW/xtI3a0JY71j3SU6v8eyZYlkP3Kpw8DC/5xrkChG1RH+hdiR4UHH8I5nbY
oM2kjMydq0InK1llilXDfo0D5LpaSXcEy1m4d0j/+/2Z+DIwQ/Y/wnVKqU5vM4CP
BGxD1KGaMjxNtps8Z4hrb/yBHvNvpAJJUubcgPAgmDlfCWmgGlzcV/9u9LEu0jBR
FXf9ASDwiCq/PzRWI96J144BEOGAyCI497jTNm5DJQwoCcZ7rbgpjwrmWoUQSRxz
8w2CU7m/C5nrZ7cfl9EOYv13OpmP0zAO2EmmflsTdeQMHUkp5JsO0TEB68JAYENt
oeH0aHmtKvMHXV78QmM3sznI9YIPV50dq/Sp7hhhygmsBrwnn6ZfwocJ1AOar5Jo
y7rO2Z9RYFvG8teI4y5inpA5Fl1GDEU6suk4GwIDAQABAoIEAB28edRu1hrVakvV
Wsl0WvLhUbFr9DIksELbyf3wEdi5Fy3DtkrUS7NMkZDLAal+45Hvz10x3rixLSwg
buciPtV/i2Qm46zldj1k6q5Oh/3vcypRD42J4F2onlwk58sQLC8oq5i40fVogp8M
x2GIgstimc0e66kPGIKTtecTrdODoG8nbWZhb/Dsv8TqpnZvs/xozdXSsQphQxQt
MML3baBDnHnvhuFnw4W8gohO94vvL9vk8RUS/Y23/Qi5NRUXGuhoBlM35vISJzgA
TU9vcVzcuaIYJ1HTq9HmclOvJYTesOQKgMDItbdoqDQbAF3WKhaPilTYVlTd8SK9
4XLENinaJHbpRE22QrmEbLFcOw/f9ol/qsXIW3y+hDLoTjoWILdtFU0RdZrjiYWS
kdvSXU7g9DE0EoI3oWVifH8251+TMRJCQs+mZrf+Zqt8funeBjy5afGXHTAc5l4U
osbnSgoDXC3qb58yhT46+07/ojErhV7aa6uKWMa7wRN6ywx/pHyly7c9F+zmyBEb
SAug+rLnnK0QCWEEPgrB0XNgSopudMDxdfGx8ydop0wUEoxHbB1FSbUJt2WYyQKi
Y815HK6hQPSIOckB7TtFl2QDkSULPHZ1mv2Hy69XVKrFLDNqbExPh6JOEHk4S9yK
cf39Fa5Dt1ToHW9Imqv0tbkoJMSYS7ZpFuqeojI1kUvPejGpFxPBPBCo4nGsZfIz
KLCTEctaD1V05+uuy5SSKkWwI2KPhisSkSf/3PUElsKny25mdlFgfwmqyC3VTRne
nK1wXCtHOGbAvboCIh/lbpbraHXbTn1gd2Ur7mgsEVyQcyHQGYC9RvA1NwsaVLlX
gjpnD5Djtpb9fkqTXjv7Hjr6WAKZkWPiDz9mIBthjRJUo1mVDVpNHsFOuFZgcaGs
rleJEH/F7lZBIa4ChPOYWtK4emyxdUldB4uQ4GA5pUIguVHS9MFkhhb44yj0tD3r
8nGRjBap5QA/ud49gUdZrUXZiebVxytJDfumWQ4jc/HcDbhCoujGia5JozdTBNGh
yxE0w0PXUWzACEdeppKqXCvOKrSc+TFwmK4772nFA2yP1V++/HYcrBvRPTkIZwyE
Q4MIV6HckreGOWHrPg8ds8LWlxnmOwqXKfe/TRMpYPMSCfCb0AN4pbabSX50ofg9
eIbj2Tf/5leXNVcLizMzr0qJTiuHPDzrhk6v1tD9ILRSmpY6wMHO9QUmCpe+p0oF
DybnMuFTVhbRwMi5E/dpGodu5fgoe2Qehk/5MLRmRha0zm9h+dqYnnrsrKhFYnTa
Q9AXZpPw8M40ohBhO1+mk7Q5JBk7yqwlcVUa6vKtrrLWyADgKgkhb0IOPBe/p1Hd
mpEaoOECggIBAO9QC3e3VcON7tTmduQXwTVEsBW266nMw9/yca7558nlxewn1Srg
CAEqVRr3quHkKDKdL9kdPGyrNOTIOpU4wYYtghpezkq+vwMPCXWtitQGgvDXKf+I
kZk0bjjprR0iO0OMdmzybWy8Ci9oFV0hpN5Cn1DtFmow6Q+yv1aMeiLGnWfmpquH
wAHlvZyegsB2EJnjMxlwleauJ8LPaF0nakYIqv0iR8cWGJ6bWPruJDeHaE8AV9BS
pcj9KjK5PrHuktjNz80eOYIDpArJ59zuGeO73HRSgpp0H2MHB44VnvYP+/VO+n+Z
WzxKtzknMsBoqp+G372f+VKe+qvIVM1oyCYkRIq+wxzUKOOEsnrNYQDn4Np3lKW4
S50lkjTDziKy4RNbVht+/QxDdD5BlhBCCCjeGGouSR4l7r7tWQqAoxDgXTCsxnJm
ZI/FrFAIgNd3wCeL91bp4Qkk3nMdBkKdUoczDkB160b8BsLk/1Y9e4qoyIOjxRzB
MzFlXNhnt6zE5fo7YT+w56LXweSBG4yZZfbqqI12U0oyTeDNnKWrwjq1oQX+CDpK
5Qc+b/cIDqTrK1quBWLz5YONKBq/mjlvLcHdIuIspW3MAP2XTyz0hsiULEIm4VX5
/e15bw5WqCnlZezJfwnkCa5xjAzNaKzE5dXBvdSGvYWbG2l6ZptSHfgpAoICAQDU
bC/tWCQ7aihpIS9lpfUIqR93sEX20sF0faMRVKf5saiJrrcih5yIJIadMrOvwHNx
7fu1erdG5GuM+GEjjHpV36bQ5HYshps0tbzBpjoo6rwlx62Hhq7ZKpCMWD/Ieveo
gOcygYfkBsmJZwIMuMuPdlSF1aaHr+nJYuDKzfZAJvOX//gySCyNLFTOodZl7kkZ
nI8qH7kr4o8v6vagR95R+n+Hj0nSNV8bgKcicnF3ZXiD+CWTnV9zHfdPynr0ImCt
FsmiaeyUD3Dg0Y4PWPUaexIiSFlFmUOnfw7oi/19spdbzBWvXkd21q4S6vMbWUU0
Lx4+7iTM7xxxJdydarQDyIb1UtKTaRhfbnZD5rU/mtEh6mrOLkuGnZwoDKA0QSS+
H2JFOXVUh4O43dXSND0yz3kGTez0oBPeptG6lns8NKDMpmcpkWwMdfsGRU/mniOp
S0cZ0FzdklKONKagJLtXsqlWLr5Sh62acNh4f8x8/Q3fB3ivnRF74JEXf+UTKlKO
7acWJovGUQiOYvdvHQ8wl3Z6CQSKrw1CzYknpiEEKPm3Of0dWiRdfAn3X7Z9lMsv
CDioK0KXoUeYPKGNZAjQ5GDO4slfQki01F8I6g4T+UNimByx8pJpFGAHHCHaZGtj
ts5qQ46xWKsm7XqRFa44PFI74sdtrY5eHxIae1FGowKCAgANH6yhUhKH+N6iGklm
1M6ppyyo5DEkTLBpNZh6agYGEm26N6z+/u4xcircobxjSunRbMFU/L91jiYGbdyY
llY2j4RVAeH6Q1+iQU7Zfzzfx8OihYouE0U4y6FHybjOojPxzmAoNVs+3UkJtIGH
a/LopWqrO3VBOZFuZPUNQALqqU20hveY7IbhE8JENoUhHNhoOAdzW7M8xUw06L7m
bOTtFkiaPSkGh/WtrQNCL5EY4nob6v7l08J3tTp9MZ94jobLEO5WZ1PsB1sVpGDs
wrn0vTanwmabJcca3SXS6uiewd2lZEFkgfp44fgOUFH+Lz88JF9cvMsldsZ0aTYN
VbO0M8T2fuOgTxo27+4BwgWR0SWJlYk3VVYANjFAZ4SEbp7dOuML+vjRlVlomJws
JBLietuH5yXnW1kua0G4y7klkchKhQ8U8vyMzeBXO0AlkNGe2ZQk1gqbP8RbN7pC
KPJ/q5Magdz3NZcBVSGTjyeZQQxN+8sxen7eNJrU20s9VEbwZBU/MuphCcf+Sf5C
xZ7L3a6Eo3qJ1RxkOaJfi33JTnCYLYgx+i15KjllqLF05diozmZJOOrbPgB3Bw7k
G2689O2Wza/8x3U+cu/KnVZO5aFPt2YgGueMAF7QwHvUYFoolBw9ZJ4LTPrLMPCO
mPWptUg9wW3fR9RHAolh9yzhkQKCAgBYaXMFOTNTW1rYbsx4ZTt4UFPdkAt+sLd+
EbCmTPLg9TWtoH9uqrzW2UUB9pFdLB+goqmqHhpcMkQlV1eu4RAl38FhnkUlQR0m
MiIPA22fjBulKdeq2b66eoHROAXMHoonowcXOVxi5wRI4Qu0WdG3s0t4rLT0Mp5+
iF4Bavn8N3oZoJsf6nRIidP+cNN4d1YLh+L6aFu8zT5FdmkRyvfYbQdZV6UlDbu5
CbIGn1VkmWIwoz6Ykt6gXi+KET9dj1VnlV108NtbwJV9rRqQfrj9PY4NoMkvM5w6
AaMl3OYzw/pFZcr8w6PA7ZdkHk/y6RPppVbUYHAGr9rJqTWKe1fTX0n0n3Uvj4Vq
auJkXoi/oWM714J+sDwVGlJdROwE87wkOZHAOCsCdKi5b/NH2yBBnqLDoflm052R
hSMzouBF7a2jn/q+DV3ITe6d7IlV9innk4JTVyrfucAMmhNkAgXLeXwLd8cVOI1k
A2XFuYNV3klAs65igWA+i/g3rK6ebHYSMQ3jJUX109JY2Q4dPB4PXmscXdZ7FmLR
lBRq4TVKsvdEcKlN5y/NjQvk3vxohl6PA7/5FpBP5fuTfGDNJX6Z2wQD99ZShJcY
VG/9mNUlMRD/30nKMqkHfUh+jRH2AOfFh9ef2OByJfKOcDccXca2dzzO2hOhLaRc
vlfdl8f7OwKCAgEAsgT6xW6Qg7p0CHOOmrdDbrVHKfNi5xb7Ck6UA7K+GDbdo84Z
lHoN2JK+aKGJiNx8gTB/8T9JWuaHz8AbzPAs7B6UbcBu1gu73LHLBfPR/37SPzg0
cGS0EqLm/5S0C4ZTU8k8BcgD2yE56lryDE9P9lTV6FicRjWZE6nXFHHv1rG65Vw2
LPWV0DIPlaXuh2pi6n02OhmJnaHwd437pmQOYvL5vBXsu2e0Uq4CI/hD/YrMKTO6
VBxL8S8exEGXFXvp5wiMKdU4qCDzqOdrV2M40v9JTW358ZC7XfjiRLhegYJdR0W0
LdJpkcvMYnZkVo5HChClAAIC5aqRvojv15bqK2VYr6ATWrI5CHw0jdjn1BynbO4s
E54gJ8mtzfNdPnFwApPH0ABLyZsyyS0JEaCf1xu47l1Ak+O0aM5MrbUfdUZzH7+y
rMSfZAGnYax22/8CodAdk93oNDK3nQGvb3KIPdSzrlK9d4DS04Ew2yPaNa+CU6zd
7Z5b48+wiApVi2WGqVqUXT/9x506jzyBKQaYecactIzssChWSs9R2mgVHH7w7SYr
G6RInhOztFem1TBNVkeIs85gNpNx36OXFhmFVKH1Ud+aioDZDNxSgMGmGEd4DA2u
XUQx3zulcL05YGTmt+RB812pQJh8rB8MZZfCLz2dPr8OpPE0JiOvznu9fr4=
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,54 @@
-----BEGIN ATTRIBUTE CERTIFICATE-----
MIIJmDCCCIACAQEwgZaggZMwgYqkgYcwgYQxCzAJBgNVBAYTAlVTMQswCQYDVQQI
DAJDQTEUMBIGA1UEBwwLU2FudGEgQ2xhcmExGjAYBgNVBAoMEUludGVsIENvcnBv
cmF0aW9uMR4wHAYDVQQLDBVFSyBDZXJ0aWZpY2F0ZSBJc3N1ZXIxFjAUBgNVBAMM
DXd3dy5pbnRlbC5jb20CBDdAg3SggZ0wgZqkgZcwgZQxCzAJBgNVBAYTAlVTMQsw
CQYDVQQIDAJDQTEUMBIGA1UEBwwLU2FudGEgQ2xhcmExGjAYBgNVBAoMEUludGVs
IENvcnBvcmF0aW9uMS4wLAYDVQQLDCVQbGF0Zm9ybSBBdHRyaWJ1dGUgQ2VydGlm
aWNhdGUgSXNzdWVyMRYwFAYDVQQDDA13d3cuaW50ZWwuY29tMA0GCSqGSIb3DQEB
CwUAAhRgKWfqeST97mzBULkeg3d9H0J5mTAiGA8yMDE3MDgyMDIxMDgxMFoYDzIw
MjAwODIwMjEwODEwWjCCBK4wHAYFZ4EFAhExEzARMAkCAQICAQACASsEBAAAAAEw
EgYFZ4EFAhkxCTAHBgVngQUIAjAUBgVngQUCFzELMAkCAQECAQECAQswgccGBWeB
BQITMYG9MIG6AgEAoHQWAzMuMQoBBwoBAgEBAIABAYEFKgMEBQaiLRYraHR0cHM6
Ly93d3cuaW50ZWwuY29tL3Byb3RlY3Rpb25wcm9maWxlLnBkZoMFUwQFBgekJBYi
aHR0cHM6Ly93d3cuaW50ZWwuY29tL2NjdGFyZ2V0LnBkZqENFgUxNDAtMgoBBAEB
AIIBAwEBABYqaHR0cHM6Ly93d3cuaW50ZWwuY29tL2lzb2NlcnRpZmljYXRpb24u
cGRmMIIDagYHZ4EFBQEHAjGCA10wggNZoIIC1zCCAXYwDgYGZ4EFEgMBBAQAAAAK
DAdBQkMgT0VNDAxXUjA2WDc4NzFGVEyACUE1NTU1LTk5OYEDMS4xggcrBgEEAYIs
gwH/pDIwFwYFZ4EFEQEMDkFGOjNBOjk0OjEwOkE1MBcGBWeBBRECDA5BRjozNzox
MDpEMjpBOKWBz6AxMA0GCysGAQQBgbAaAQIBBCBgA6M0Mv2RS2ADozQy/ZFLYAOj
NDL9kUtgA6M0Mv2RS6GBmTCBj6SBjDCBiTELMAkGA1UEBhMCVVMxCzAJBgNVBAgM
AkZMMRcwFQYDVQQHDA5GdC4gTGF1ZGVyZGFsZTEYMBYGA1UECgwPQUJDIENvcnBv
cmF0aW9uMSQwIgYDVQQLDBtQbGF0Zm9ybSBDZXJ0aWZpY2F0ZSBJc3N1ZXIxFDAS
BgNVBAMMC3d3dy5hYmMuY29tAgUKNUzN26YrFilodHRwczovL3d3dy5hYmMuY29t
L2NlcnRzLzQzODQzODk4ODQzLmNlcjCCAVkwDgYGZ4EFEgMBBAQAAAAvDAdYWVog
T0VNDA5MTUJUMzkwNERXMVQxR4AJQzU1NTUtNTU1gQMzLjGCBysGAQQBgiyDAQCk
MjAXBgVngQURAQwOODI6ODk6RkE6RDM6NjEwFwYFZ4EFEQIMDkQ0OjgzOkI0OkYy
Ojc4pYG1oCUwDQYLKwYBBAGBsBoBAgEEFDQy4UFLYJc0NDI0MuFBS2CXNDQyoYGL
MIGDpIGAMH4xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJBWjEQMA4GA1UEBwwHUGhv
ZW5peDEUMBIGA1UECgwLWFlDIENvbXBhbnkxJDAiBgNVBAsMG1BsYXRmb3JtIENl
cnRpZmljYXRlIElzc3VlcjEUMBIGA1UEAwwLd3d3Lnh5ei5jb20CAw5TsKYmFiRo
dHRwczovL3d3dy54eXouY29tL2NlcnRzLzkzODkyOC5jZXKhLxYtaHR0cHM6Ly93
d3cuaW50ZWwuY29tL3BsYXRmb3JtaWRlbnRpZmllcnMueG1sohswDAwEdlBybwwE
dHJ1ZTALDANBTVQMBHRydWWjLhYsaHR0cHM6Ly93d3cuaW50ZWwuY29tL3BsYXRm
b3JtcHJvcGVydGllcy54bWwwLAYGZ4EFBQEDMSIwIBYeaHR0cHM6Ly93d3cuaW50
ZWwuY29tL1BDUnMueG1sMIICRTB8BgNVHSAEdTBzMHEGCiqGSIb4TQEFAgQwYzAx
BggrBgEFBQcCARYlaHR0cHM6Ly93d3cuaW50ZWwuY29tL3BsYXRjZXJ0Y3BzLnBk
ZjAuBggrBgEFBQcCAjAiDCBUQ0cgVHJ1c3RlZCBQbGF0Zm9ybSBFbmRvcnNlbWVu
dDB+BgNVHREEdzB1pHMwcTERMA8GBmeBBQUBAQwFSW50ZWwxFTATBgZngQUFAQIw
CQYHKwYBBAGCVzETMBEGBmeBBQUBBAwHUzI2MDBLUDEWMBQGBmeBBQUBBQwKSDc2
OTYyLTM1MDEYMBYGBmeBBQUBBgwMQlFLUDk5OTQwNjQzMIGyBgNVHTcBAf8Egacw
gaQwgaGggZ6kgZswgZgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEUMBIGA1UE
BwwLU2FudGEgQ2xhcmExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0aW9uMR4wHAYD
VQQLDBVFSyBDZXJ0aWZpY2F0ZSBJc3N1ZXIxFjAUBgNVBAMMDXd3dy5pbnRlbC5j
b20xEjAQBgNVBAUTCTEyODk0Mzc4NzAfBgNVHSMEGDAWgBTUaZAmAoHVXoNLA5du
q4qfj4TJgzA2BggrBgEFBQcBAQQqMCgwJgYIKwYBBQUHMAGGGmh0dHBzOi8vd3d3
LmludGVsLmNvbS9vY3NwMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHBzOi8vd3d3Lmlu
dGVsLmNvbS9wbGF0Zm9ybWNlcnQuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQBfbb0t
gb3flhGKbtQA6qSjO2L0+y20OfgmR4W6D4eIxaIHcF5ORjAt89ucyhIhfWd4uEh3
zwepC4q6RZZssXdI0qcTOAQVu0/T1O9DoP8AQVgQS/Lu+KAnlvaLWvxW+nv/NwMy
dh1mu/GrsZYc3Rodclcw1n/NKh+osvxq2/cGA9kJ3mdJsJ0WVBx3pbfmmWRAFa7D
Yoa/VQJTbPfbkO8fCCtlFwSUwN+u0ZsRen/dBzbfgFq/5yOB3zeoRiO1nPj4qs9r
nh24rEoHQfAoT5Caz4HSqQ9GoJ4L6glMlM0KAad29xaucIjxY3g8N2r1aEuJaXL2
N0NKMXmBpYWiInTX
-----END ATTRIBUTE CERTIFICATE-----

View File

@ -0,0 +1,33 @@
-----BEGIN ATTRIBUTE CERTIFICATE-----
MIIFuzCCBKMCAQEwd6B1MFmkVzBVMSYwJAYDVQQDDB1TVE0gVFBNIEVLIEludGVy
bWVkaWF0ZSBDQSAwMjEeMBwGA1UECgwVU1RNaWNyb2VsZWN0cm9uaWNzIE5WMQsw
CQYDVQQGEwJDSAIYUEYpmIE5STImCFSYGYVSORmEiCQiMCAooIGdMIGapIGXMIGU
MQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFDASBgNVBAcMC1NhbnRhIENsYXJh
MRowGAYDVQQKDBFJbnRlbCBDb3Jwb3JhdGlvbjEuMCwGA1UECwwlUGxhdGZvcm0g
QXR0cmlidXRlIENlcnRpZmljYXRlIElzc3VlcjEWMBQGA1UEAwwNd3d3LmludGVs
LmNvbTANBgkqhkiG9w0BAQsFAAIUYCln6nkk/e5swVC5HoN3fR9CeZkwIhgPMjAx
NzA4MjAxNTUzNDRaGA8yMDIwMDgyMDE1NTM0NFowggHfMBwGBWeBBQIRMRMwETAJ
AgECAgEAAgErBAQAAAABMBQGBWeBBQIXMQswCQIBAQIBAAIBCzCBxwYFZ4EFAhMx
gb0wgboCAQCgdBYDMy4xCgEHCgECAQEAgAEBgQUqAwQFBqItFitodHRwczovL3d3
dy5pbnRlbC5jb20vcHJvdGVjdGlvbnByb2ZpbGUucGRmgwUqAwQFB6QkFiJodHRw
czovL3d3dy5pbnRlbC5jb20vY2N0YXJnZXQucGRmoQ0WBTE0MC0yCgEEAQEAggED
AQEAFipodHRwczovL3d3dy5pbnRlbC5jb20vaXNvY2VydGlmaWNhdGlvbi5wZGYw
LAYGZ4EFBQEDMSIwIBYeaHR0cHM6Ly93d3cuaW50ZWwuY29tL1BDUnMueG1sMIGw
BgdngQUFAQcBMYGkMIGhoFIwUAwFSW50ZWwMDHBsYXRmb3JtMjAxOIAMQlFLUDUy
ODQwNjc4gQMxLjCCBysGAQQBgiyDAf+kGjAYBgZngQUFAQYMDjIuMjMuMTMzLjUu
MS42oRswDAwEdlBybwwEdHJ1ZTALDANBTVQMBHRydWWiLhYsaHR0cHM6Ly93d3cu
aW50ZWwuY29tL3BsYXRmb3JtcHJvcGVydGllcy54bWwwggFXMHwGA1UdIAR1MHMw
cQYKKoZIhvhNAQUCBDBjMDEGCCsGAQUFBwIBFiVodHRwczovL3d3dy5pbnRlbC5j
b20vcGxhdGNlcnRjcHMucGRmMC4GCCsGAQUFBwICMCIMIFRDRyBUcnVzdGVkIFBs
YXRmb3JtIEVuZG9yc2VtZW50MB8GA1UdIwQYMBaAFJmT1DnLMuKrlfc3o7d3KRzU
pDm2MDYGCCsGAQUFBwEBBCowKDAmBggrBgEFBQcwAYYaaHR0cHM6Ly93d3cuaW50
ZWwuY29tL29jc3AwfgYDVR0RBHcwdaRzMHExETAPBgZngQUFAQEMBUludGVsMRUw
EwYGZ4EFBQECMAkGBysGAQQBglcxEzARBgZngQUFAQQMB1MyNjAwS1AxFjAUBgZn
gQUFAQUMCkg3Njk2Mi0zNTAxGDAWBgZngQUFAQYMDEJRS1A1Mjg0MDY3ODANBgkq
hkiG9w0BAQsFAAOCAQEAoRr6ut9SqTqceNl96ok/YQ4Xh3TW2jX5sHm7h6K6/mb1
X+nLEP5BmAbjHCd5LNolNdiqhTyQyGmEiUu5SUyJyoCPAf6TZTK/nKlFx7Gf0vyu
DExw01EX5XKIINBhXZtmLqL3DCWvawuWnetbhkBpH97QuiPs6WDDC837fWvaV6OO
rBO/9+o8pDP4hwboX4uTQju2uWl+PujMTQVtfysbL3K7EVIZV1/tT7b494/VQglk
58M5h4hh5WttktIdGaT2otaF3V59NtKIugmeLk6Mj0J3y+sgsk8S3InYMuH6ckys
O3e6nA68Iah4TRe6mUhLet9c10/Yyl/NFkfobqK4Yw==
-----END ATTRIBUTE CERTIFICATE-----

View File

@ -0,0 +1,31 @@
-----BEGIN ATTRIBUTE CERTIFICATE-----
MIIFZDCCBEwCAQEwd6B1MFmkVzBVMSYwJAYDVQQDDB1TVE0gVFBNIEVLIEludGVy
bWVkaWF0ZSBDQSAwMjEeMBwGA1UECgwVU1RNaWNyb2VsZWN0cm9uaWNzIE5WMQsw
CQYDVQQGEwJDSAIYUEYpmIE5STImCFSYGYVSORmEiCQiMCAooIGdMIGapIGXMIGU
MQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFDASBgNVBAcMC1NhbnRhIENsYXJh
MRowGAYDVQQKDBFJbnRlbCBDb3Jwb3JhdGlvbjEuMCwGA1UECwwlUGxhdGZvcm0g
QXR0cmlidXRlIENlcnRpZmljYXRlIElzc3VlcjEWMBQGA1UEAwwNd3d3LmludGVs
LmNvbTANBgkqhkiG9w0BAQsFAAIUYCln6nkk/e5swVC5HoN3fR9CeZkwIhgPMjAx
NzA4MjAxNTUzNDRaGA8yMDIwMDgyMDE1NTM0NFowggGIMBwGBWeBBQIRMRMwETAJ
AgECAgEAAgErBAQAAAABMBQGBWeBBQIXMQswCQIBAQIBAAIBCzCBxwYFZ4EFAhMx
gb0wgboCAQCgdBYDMy4xCgEHCgECAQEAgAEBgQUqAwQFBqItFitodHRwczovL3d3
dy5pbnRlbC5jb20vcHJvdGVjdGlvbnByb2ZpbGUucGRmgwUqAwQFB6QkFiJodHRw
czovL3d3dy5pbnRlbC5jb20vY2N0YXJnZXQucGRmoQ0WBTE0MC0yCgEEAQEAggED
AQEAFipodHRwczovL3d3dy5pbnRlbC5jb20vaXNvY2VydGlmaWNhdGlvbi5wZGYw
LAYGZ4EFBQEDMSIwIBYeaHR0cHM6Ly93d3cuaW50ZWwuY29tL1BDUnMueG1sMFoG
B2eBBQUBBwExTzBNoRswDAwEdlBybwwEdHJ1ZTALDANBTVQMBHRydWWiLhYsaHR0
cHM6Ly93d3cuaW50ZWwuY29tL3BsYXRmb3JtcHJvcGVydGllcy54bWwwggFXMHwG
A1UdIAR1MHMwcQYKKoZIhvhNAQUCBDBjMDEGCCsGAQUFBwIBFiVodHRwczovL3d3
dy5pbnRlbC5jb20vcGxhdGNlcnRjcHMucGRmMC4GCCsGAQUFBwICMCIMIFRDRyBU
cnVzdGVkIFBsYXRmb3JtIEVuZG9yc2VtZW50MB8GA1UdIwQYMBaAFJmT1DnLMuKr
lfc3o7d3KRzUpDm2MDYGCCsGAQUFBwEBBCowKDAmBggrBgEFBQcwAYYaaHR0cHM6
Ly93d3cuaW50ZWwuY29tL29jc3AwfgYDVR0RBHcwdaRzMHExETAPBgZngQUFAQEM
BUludGVsMRUwEwYGZ4EFBQECMAkGBysGAQQBglcxEzARBgZngQUFAQQMB1MyNjAw
S1AxFjAUBgZngQUFAQUMCkg3Njk2Mi0zNTAxGDAWBgZngQUFAQYMDEJRS1A1Mjg0
MDY3ODANBgkqhkiG9w0BAQsFAAOCAQEAlqxlJPymdcXfQtLSyXaa7eAN68Zb4zhI
q1JT/VTbmPiGF4jvT629lNvULBr1plB6OkJoKO0m369pA1D5lrngiMXV64GAWNE/
fiRNHPPYx5wIbqu8FApk8BkZQv5POCR+7mKQUg7Z+iv3I7Gd36oGBK9KW0SY3gmD
5yACX5l9nXSaAEF9zb/qkIWoTNwnQXLPpcv11ksyTk6nPCZG3tEjNqLwPt1uNGTP
4TxlDDU0gLwo9vMHqet7WXDgKothNMIn6oRzjDi5UCeEidRvsngifNrrnwcY0F1t
j4qpg/95ZNDoXtYlL0DsWps5S/7/Xg60YOss0iOPPS3YKoE7tJRyrg==
-----END ATTRIBUTE CERTIFICATE-----

View File

@ -0,0 +1,30 @@
-----BEGIN ATTRIBUTE CERTIFICATE-----
MIIFHjCCBAYCAQEwd6B1MFmkVzBVMSYwJAYDVQQDDB1TVE0gVFBNIEVLIEludGVy
bWVkaWF0ZSBDQSAwMjEeMBwGA1UECgwVU1RNaWNyb2VsZWN0cm9uaWNzIE5WMQsw
CQYDVQQGEwJDSAIYUEYpmIE5STImCFSYGYVSORmEiCQiMCAooFgwVqRUMFIxCzAJ
BgNVBAYTAlVTMQ4wDAYDVQQKDAVJbnRlbDEeMBwGA1UEAwwVSW50ZWwgSW50ZXJt
ZWRpYXRlIENBMRMwEQYDVQQIDApTb21lLVN0YXRlMA0GCSqGSIb3DQEBCwUAAhRg
KWfqeST97mzBULkeg3d9H0J5mTAiGA8yMDE3MDgyMDE1NTM0NFoYDzIwMjAwODIw
MTU1MzQ0WjCCAYgwHAYFZ4EFAhExEzARMAkCAQICAQACASsEBAAAAAEwFAYFZ4EF
AhcxCzAJAgEBAgEAAgELMIHHBgVngQUCEzGBvTCBugIBAKB0FgMzLjEKAQcKAQIB
AQCAAQGBBSoDBAUGoi0WK2h0dHBzOi8vd3d3LmludGVsLmNvbS9wcm90ZWN0aW9u
cHJvZmlsZS5wZGaDBSoDBAUHpCQWImh0dHBzOi8vd3d3LmludGVsLmNvbS9jY3Rh
cmdldC5wZGahDRYFMTQwLTIKAQQBAQCCAQMBAQAWKmh0dHBzOi8vd3d3LmludGVs
LmNvbS9pc29jZXJ0aWZpY2F0aW9uLnBkZjAsBgZngQUFAQMxIjAgFh5odHRwczov
L3d3dy5pbnRlbC5jb20vUENScy54bWwwWgYHZ4EFBQEHATFPME2hGzAMDAR2UHJv
DAR0cnVlMAsMA0FNVAwEdHJ1ZaIuFixodHRwczovL3d3dy5pbnRlbC5jb20vcGxh
dGZvcm1wcm9wZXJ0aWVzLnhtbDCCAVcwfAYDVR0gBHUwczBxBgoqhkiG+E0BBQIE
MGMwMQYIKwYBBQUHAgEWJWh0dHBzOi8vd3d3LmludGVsLmNvbS9wbGF0Y2VydGNw
cy5wZGYwLgYIKwYBBQUHAgIwIgwgVENHIFRydXN0ZWQgUGxhdGZvcm0gRW5kb3Jz
ZW1lbnQwHwYDVR0jBBgwFoAUmZPUOcsy4quV9zejt3cpHNSkObYwNgYIKwYBBQUH
AQEEKjAoMCYGCCsGAQUFBzABhhpodHRwczovL3d3dy5pbnRlbC5jb20vb2NzcDB+
BgNVHREEdzB1pHMwcTERMA8GBmeBBQUBAQwFSW50ZWwxFTATBgZngQUFAQIwCQYH
KwYBBAGCVzETMBEGBmeBBQUBBAwHUzI2MDBLUDEWMBQGBmeBBQUBBQwKSDc2OTYy
LTM1MDEYMBYGBmeBBQUBBgwMQlFLUDUyODQwNjc4MA0GCSqGSIb3DQEBCwUAA4IB
AQCZKjzwWca3acJIj24JH7iLc/z70QGngQeA5ef2xPYlZq2c2e5PBiVSZndTKeX7
cCDIF1EGPeuu7avJ6OdJc/OoSGwfHindkvlYWdnpihbnQ1Vevwojd+VZqaJYv25X
47GYZahCST1G/fkI+rRzJL8/A7vM5MOGSEO/AW85ZKi+ih4hbECh+9RPn5JB6l4J
HU/lCR2OzTfQ8P+/G8BDJpZc0EymMtU6shrpVa1QY8OHHb7vzuzSrdQYutqCywV2
WhLML0AkB4PuOVCHC7CMBShJ8bavbJ2ajA+bxWOWdQAX7iYKU3k+JUkJiAayxSh7
FumhJCLiXGE6n6uV4td95a7e
-----END ATTRIBUTE CERTIFICATE-----

View File

@ -0,0 +1,59 @@
-----BEGIN ATTRIBUTE CERTIFICATE-----
MIIKkzCCCXsCAQEwgbaggbMwgZqkgZcwgZQxCzAJBgNVBAYTAlVTMQswCQYDVQQI
DAJDQTEUMBIGA1UEBwwLU2FudGEgQ2xhcmExGjAYBgNVBAoMEUludGVsIENvcnBv
cmF0aW9uMS4wLAYDVQQLDCVQbGF0Zm9ybSBBdHRyaWJ1dGUgQ2VydGlmaWNhdGUg
SXNzdWVyMRYwFAYDVQQDDA13d3cuaW50ZWwuY29tAhRgKWfqeST97mzBULkeg3d9
H0J5maCBpDCBoaSBnjCBmzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlRYMQ8wDQYD
VQQHDAZBdXN0aW4xFzAVBgNVBAoMDlhZWiBJbnRlZ3JhdG9yMTQwMgYDVQQLDCtE
ZWx0YSBQbGF0Zm9ybSBBdHRyaWJ1dGUgQ2VydGlmaWNhdGUgSXNzdWVyMR8wHQYD
VQQDDBZ3d3cueHl6aW50ZWdyYXRvcnMuY29tMA0GCSqGSIb3DQEBCwUAAgQCFPcE
MCIYDzIwMTgxMDE1MjEwODExWhgPMjAyMDA4MjAyMTA4MTFaMIIFeDASBgVngQUC
GTEJMAcGBWeBBQgFMBQGBWeBBQIXMQswCQIBAQIBAQIBDTCCBRAGB2eBBQUBBwIx
ggUDMIIE/6CCBF0wggF5MA4GBmeBBRIDAQQEAAAACgwHQUJDIE9FTQwMV1IwNlg3
ODcxRlRMgAlBNTU1NS05OTmBAzEuMYIHKwYBBAGCLIMB/6QyMBcGBWeBBREBDA5B
RjozQTo5NDoxMDpBNTAXBgVngQURAgwOQUY6Mzc6MTA6RDI6QTilgc+gMTANBgsr
BgEEAYGwGgECAQQgYAOjNDL9kUtgA6M0Mv2RS2ADozQy/ZFLYAOjNDL9kUuhgZkw
gY+kgYwwgYkxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJGTDEXMBUGA1UEBwwORnQu
IExhdWRlcmRhbGUxGDAWBgNVBAoMD0FCQyBDb3Jwb3JhdGlvbjEkMCIGA1UECwwb
UGxhdGZvcm0gQ2VydGlmaWNhdGUgSXNzdWVyMRQwEgYDVQQDDAt3d3cuYWJjLmNv
bQIFCjVMzdumKxYpaHR0cHM6Ly93d3cuYWJjLmNvbS9jZXJ0cy80Mzg0Mzg5ODg0
My5jZXKHAQIwggF8MA4GBmeBBRIDAQQEAAAAQQwOQ29tcG9uZW50IENvcnAMCVhU
OTgyODdMTIAHRjk4MS0wMYEDMi4xggcrBgEEAYNIgwH/pDIwFwYFZ4EFEQIMDjcz
OjlCOjkyOjQwOkZBMBcGBWeBBREDDA4xMzozRjo5ODpDNTo1OaWBzaAxMA0GCysG
AQQBgbAaAQIBBCCYqtWRg/qrkZiq1ZGD+quRmKrVkYP6q5GYqtWRg/qrkaGBlzCB
jqSBizCBiDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMREwDwYDVQQHDAhTYW4g
Sm9zZTEXMBUGA1UECgwOQ29tcG9uZW50IENvcnAxJDAiBgNVBAsMG1BsYXRmb3Jt
IENlcnRpZmljYXRlIElzc3VlcjEaMBgGA1UEAwwRd3d3LmNvbXBvbmVudC5jb20C
BAXek66mLhYsaHR0cHM6Ly93d3cuY29tcG9uZW50LmNvbS9jZXJ0cy85ODQ3Mjg3
OC5jZXKHAQAwggFcMA4GBmeBBRIDAQQEAAAALwwHWFlaIE9FTQwOTE1CVDM5MDRE
VzFUMUeACUM1NTU1LTU1NYEDNC4wggcrBgEEAYIsgwEApDIwFwYFZ4EFEQEMDjgy
Ojg5OkZBOkQzOjYxMBcGBWeBBRECDA5ENDo4MzpCNDpGMjo3OKWBtaAlMA0GCysG
AQQBgbAaAQIBBBQ0MuFBS2CXNDQyNDLhQUtglzQ0MqGBizCBg6SBgDB+MQswCQYD
VQQGEwJVUzELMAkGA1UECAwCQVoxEDAOBgNVBAcMB1Bob2VuaXgxFDASBgNVBAoM
C1hZQyBDb21wYW55MSQwIgYDVQQLDBtQbGF0Zm9ybSBDZXJ0aWZpY2F0ZSBJc3N1
ZXIxFDASBgNVBAMMC3d3dy54eXouY29tAgMOU7CmJhYkaHR0cHM6Ly93d3cueHl6
LmNvbS9jZXJ0cy85Mzg5MjguY2VyhwEBoTgWNmh0dHBzOi8vd3d3Lnh5emludGVn
cmF0b3JzLmNvbS9wbGF0Zm9ybWlkZW50aWZpZXJzLnhtbKIpMBYMC1RTQyBFbmFi
bGVkDAR0cnVlgAEAMA8MA0FNVAwFZmFsc2WAAQGjNxY1aHR0cHM6Ly93d3cueHl6
aW50ZWdyYXRvcnMuY29tL3BsYXRmb3JtcHJvcGVydGllcy54bWwwOAYGZ4EFBQED
MS4wLBYqaHR0cHM6Ly93d3cueHl6aW50ZWdyYXRvcnMuY29tL1BDUnNfVjIueG1s
MIICXzCBgwYDVR0gBHwwejB4BggqhkiXJwMBAjBsMDoGCCsGAQUFBwIBFi5odHRw
czovL3d3dy54eXppbnRlZ3JhdG9ycy5jb20vcGxhdGNlcnRjcHMucGRmMC4GCCsG
AQUFBwICMCIMIFRDRyBUcnVzdGVkIFBsYXRmb3JtIEVuZG9yc2VtZW50MH4GA1Ud
EQR3MHWkczBxMREwDwYGZ4EFBQEBDAVJbnRlbDEVMBMGBmeBBQUBAjAJBgcrBgEE
AYJXMRMwEQYGZ4EFBQEEDAdTMjYwMEtQMRYwFAYGZ4EFBQEFDApINzY5NjItMzUw
MRgwFgYGZ4EFBQEGDAxCUUtQOTk5NDA2NDMwgbIGA1UdNwEB/wSBpzCBpDCBoaCB
nqSBmzCBmDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlRYMQ8wDQYDVQQHDAZBdXN0
aW4xFzAVBgNVBAoMDlhZWiBJbnRlZ3JhdG9yMR4wHAYDVQQLDBVFSyBDZXJ0aWZp
Y2F0ZSBJc3N1ZXIxHzAdBgNVBAMMFnd3dy54eXppbnRlZ3JhdG9ycy5jb20xETAP
BgNVBAUTCDMyODczODcyMB8GA1UdIwQYMBaAFNRpkCYCgdVeg0sDl26rip+PhMmD
MD8GCCsGAQUFBwEBBDMwMTAvBggrBgEFBQcwAYYjaHR0cHM6Ly93d3cueHl6aW50
ZWdyYXRvcnMuY29tL29jc3AwQAYDVR0fBDkwNzA1oDOgMYYvaHR0cHM6Ly93d3cu
eHl6aW50ZWdyYXRvcnMuY29tL3BsYXRmb3JtY2VydC5jcmwwDQYJKoZIhvcNAQEL
BQADggEBAGx3K17RCixE32TPB4u52TeoQxla9zROywTOAVDLa0Na4mfqmt3mTYuE
hkCbYnYX9sqa0KCYmBTTjjO7LndOO7UisQsx8vKTDDVQ6E3etxeeqdiY8g4Rv+t1
nC8Hna+UZ+Lv+rUze/FaOiXH4rn6kxK7jsGe2lVIC7qvIzWnjcF5kgxOQ3SqFmWJ
VFXj2FUqauP4WbDQEH/H+Fgr8QU5Qq/k6nPZXs1CG3cKZfcSOQerF7nWOgCdClbQ
pmfS+PWz10RWbvx6s9+EI+3Ky0GXQrfq3kmbM6Owmfgr9WMkoHJTiBRx8kK+bObd
7GjNOTGvbrHYTslWFF5aDB78md+jJ8A=
-----END ATTRIBUTE CERTIFICATE-----

View File

@ -0,0 +1,42 @@
-----BEGIN ATTRIBUTE CERTIFICATE-----
MIIHVTCCBj0CAQEwgZWggZIwgYmkgYYwgYMxCzAJBgNVBAYTAkRFMSEwHwYDVQQK
DBhJbmZpbmVvbiBUZWNobm9sb2dpZXMgQUcxGjAYBgNVBAsMEU9QVElHQShUTSkg
VFBNMi4wMTUwMwYDVQQDDCxJbmZpbmVvbiBPUFRJR0EoVE0pIFJTQSBNYW51ZmFj
dHVyaW5nIENBIDAyMgIEewdr5KBaMFikVjBUMQswCQYDVQQGEwJVUzEUMBIGA1UE
CgwLRXhhbXBsZS5vcmcxDTALBgNVBAsMBHRlc3QxIDAeBgNVBAMMF1BsYXRmb3Jt
IENlcnRpZmljYXRlIENBMA0GCSqGSIb3DQEBCwUAAhRgKWfqeST97mzBULkeg3d9
H0J5mTAiGA8yMDE4MDEwMTE1NTM0NFoYDzIwMjUwMTAxMTU1MzQ0WjCCA5kwHAYF
Z4EFAhExEzARMAkCAQICAQACASsEBAAAAAEwFAYFZ4EFAhcxCzAJAgEBAgEAAgEL
MIHHBgVngQUCEzGBvTCBugIBAKB0FgMzLjEKAQcKAQIBAQCAAQGBBSoDBAUGoi0W
K2h0dHBzOi8vd3d3LmludGVsLmNvbS9wcm90ZWN0aW9ucHJvZmlsZS5wZGaDBSoD
BAUHpCQWImh0dHBzOi8vd3d3LmludGVsLmNvbS9jY3RhcmdldC5wZGahDRYFMTQw
LTIKAQQBAQCCAQMBAQAWKmh0dHBzOi8vd3d3LmludGVsLmNvbS9pc29jZXJ0aWZp
Y2F0aW9uLnBkZjAsBgZngQUFAQMxIjAgFh5odHRwczovL3d3dy5pbnRlbC5jb20v
UENScy54bWwwggJpBgdngQUFAQcBMYICXDCCAligggIHMDgMEUludGVsIENvcnBv
cmF0aW9uDAtPVVQgT0YgU1BFQ4AHKGJsYW5rKYEBMoIHKwYBBAGCV4MB/zBEDBFJ
bnRlbCBDb3Jwb3JhdGlvbgwJTlVDN2k1RE5CgAxCVERONzMyMDAwUU2BCko1NzYy
Ni00MDGCBysGAQQBgleDAf8wbQwUSW50ZWwoUikgQ29ycG9yYXRpb24MB0NvcmUg
aTWAFlRvIEJlIEZpbGxlZCBCeSBPLkUuTS6BKEludGVsKFIpIENvcmUoVE0pIGk1
LTczMDBVIENQVSBAIDIuNjBHSHqCBysGAQQBgleDAf8wQQwLSW50ZWwgQ29ycC4M
BEJJT1OBIEROS0JMaTV2Ljg2QS4wMDE5LjIwMTcuMDgwNC4xMTQ2ggcrBgEEAYJX
gwH/MHEMEUludGVsIENvcnBvcmF0aW9uDBtFdGhlcm5ldCBDb25uZWN0aW9uIEky
MTktTE2AEThjOjBmOjZmOjcyOmM2OmM1gQIyMYIHKwYBBAGCV4MB/6QcMBoGBWeB
BREBDBE4YzowZjo2Zjo3MjpjNjpjNTAtDAhLSU5HU1RPTgwMU0E0MDBTMzcxMjBH
gBA1MDAyNkI3Nzc4MDUyNzBCgwH/MDEMB1NhbXN1bmcMEE00NzFBNTE0M0VCMC1D
UEKACDk4NTBFQjJEggcrBgEEAYFsgwH/oRswDAwEdlBybwwEdHJ1ZTALDANBTVQM
BHRydWWiLhYsaHR0cHM6Ly93d3cuaW50ZWwuY29tL3BsYXRmb3JtcHJvcGVydGll
cy54bWwwggFcMGoGA1UdIARjMGEwXwYKKoZIhvhNAQUCBDBRMB8GCCsGAQUFBwIB
FhNodHRwczovL2V4YW1wbGUub3JnMC4GCCsGAQUFBwICMCIMIFRDRyBUcnVzdGVk
IFBsYXRmb3JtIEVuZG9yc2VtZW50MB8GA1UdIwQYMBaAFHAm0J7ZNdzcRNhNfadc
zwq8H94KMDYGCCsGAQUFBwEBBCowKDAmBggrBgEFBQcwAYYaaHR0cHM6Ly93d3cu
aW50ZWwuY29tL29jc3AwgZQGA1UdEQSBjDCBiaSBhjCBgzEdMBsGBmeBBQUBAQwR
SW50ZWwgQ29ycG9yYXRpb24xFTATBgZngQUFAQIwCQYHKwYBBAGCVzEWMBQGBmeB
BQUBBAwKTlVDN2k1RE5IRTEWMBQGBmeBBQUBBQwKSjcxNzM5LTQwMTEbMBkGBmeB
BQUBBgwPRFcxNjAwNDIwMzAwMTEwMA0GCSqGSIb3DQEBCwUAA4IBAQBdDVmlopIC
lt092SyqssVSHEZscNLb1C2bFmwJvlYX+8lzB1pI6wLEYccI3Vbz46g2k7dbb8ke
Ver126inffbm/3eJh+Dy4547xY3vijD0p0EZhLGW3hTnhkF91fD8VXYRSMJdCrJo
9MHE/kWTapmh9xidCGusCHlSG3v9OGvBuDEQhvnLKVLpR5ud9hqxccOr/VaB5gbo
16iW0ZD1U1l7bXkrRGqWWVK+TBKcnFy//mkhrEPed7+8gZUf/0G8MzXOPQvz55eH
3rSr8d1UQlv070uw9ly/pKp7blu1xJRnbjJmi8+NkPDRj6Hv4g8c5oVqkoHZJt3K
JLM5v9PY8uQn
-----END ATTRIBUTE CERTIFICATE-----

View File

@ -0,0 +1,3 @@
-----BEGIN ATTRIBUTE CERTIFICATE-----
MIIE7DCCA9QCAQEwV6BVMEukSTBHMQswCQYDVQQGEwJVUzELMAkGA1UECAwCU1QxEDAOBgNVBAcMB0VYQU1QTEUxDDAKBgNVBAoMA29yZzELMAkGA1UEAwwCY2ECBgFkKBN3iqBNMEukSTBHMQswCQYDVQQGEwJVUzELMAkGA1UECAwCU1QxEDAOBgNVBAcMB0VYQU1QTEUxDDAKBgNVBAoMA29yZzELMAkGA1UEAwwCY2EwDQYJKoZIhvcNAQELBQACEg6DxksIKEJVMptnqfSdd4xcqTAiGA8yMDE4MDYyODA0MDAwMFoYDzIwMjgwNjMwMDQwMDAwWjCCAaIwKgYFZ4EFAhMxITAfoA4WAzIuMgoBBgoBAYABAqEKFgUxNDAtMgoBAoIBADAcBgVngQUCETETMBEwCQIBAQIBAwIBFgQEAAAAATCCAT4GB2eBBQUBBwExggExMIIBLaCCAScwIQwST3JhY2xlIENvcnBvcmF0aW9uDAVPdGhlcoAAgQCkADAmDBJPcmFjbGUgQ29ycG9yYXRpb24MClZpcnR1YWxCb3iAAIEApAAwJAwMaW5ub3RlayBHbWJIDARCSU9TgApWaXJ0dWFsQm94gQCkADA+DBFJbnRlbCBDb3Jwb3JhdGlvbgwjODI1NDBFTSBHaWdhYml0IEV0aGVybmV0IENvbnRyb2xsZXKAAIEApAAwXAwiQWR2YW5jZWQgTWljcm8gRGV2aWNlcywgSW5jLiBbQU1EXQwWNzljOTcwIFtQQ25ldDMyIExBTkNFXYAac3VzcGljaW91c18zODJ1ODIzOWkyMzkzNTSBAKQAMBYMBFZCT1gMCEhBUkRESVNLgACBAKQAoQAwFAYFZ4EFAhcxCzAJAgEBAgEAAgEQMIIBODB0BgNVHSMEbTBrgBRGudxuHtihoLQVKHMF1KiHXd3fJaFLpEkwRzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlNUMRAwDgYDVQQHDAdFWEFNUExFMQwwCgYDVQQKDANvcmcxCzAJBgNVBAMMAmNhggYBZCgRrgMwXwYDVR0gBFgwVjBUBgIqAzBOMBwGCCsGAQUFBwIBFhBodHRwOi8vbG9jYWxob3N0MC4GCCsGAQUFBwICMCIMIFRDRyBUcnVzdGVkIFBsYXRmb3JtIEVuZG9yc2VtZW50MF8GA1UdEQRYMFakVDBSMRYwFAYGZ4EFBQEEDApWaXJ0dWFsQm94MRgwFgYGZ4EFBQEBDAxpbm5vdGVrIEdtYkgxDzANBgZngQUFAQUMAzEuMjENMAsGBmeBBQUBBgwBMDANBgkqhkiG9w0BAQsFAAOCAQEAXjdkl1b5WFX37xoooLYkUojN7Ekuc4hF/YywMhGZGw9N7fQtCfwTFwPGm+HwHCpuV0yCR3HPnfpMMMNtTsBUrH4yWxAYlXCU8gpJKk2K3uqDeNFrpPm6y2SPHvlQDLHnpw/0SlMUbBllbmIDraoY+t2acTHavCGO6pl0f9cHBek7GK9ovRtqaEfy6fHhRhuDqPF+KdOaoB9Aec0On0NkWuBdX0Le7M8H6LVwAhc1UCRBET7+fCpzHgE8RKdppbR+VXyQfq9p6UYeoxKrJJXH1xgH9pFcou9TUugIL7aEws6AogRaMU5LyHPq5flDNH00OrVRgoJllm0EzG3EXGIpQA==
-----END ATTRIBUTE CERTIFICATE-----

View File

@ -0,0 +1,3 @@
-----BEGIN ATTRIBUTE CERTIFICATE-----
MIIFATCCA+kCAQEwV6BVMEukSTBHMQswCQYDVQQGEwJVUzELMAkGA1UECAwCU1QxEDAOBgNVBAcMB0VYQU1QTEUxDDAKBgNVBAoMA29yZzELMAkGA1UEAwwCY2ECBgFkKBN3iqBNMEukSTBHMQswCQYDVQQGEwJVUzELMAkGA1UECAwCU1QxEDAOBgNVBAcMB0VYQU1QTEUxDDAKBgNVBAoMA29yZzELMAkGA1UEAwwCY2EwDQYJKoZIhvcNAQELBQACDgGu/H+usYn7Cxf59c33MCIYDzIwMTgwNjI4MDQwMDAwWhgPMjAyODA2MzAwNDAwMDBaMIIBuzAqBgVngQUCEzEhMB+gDhYDMi4yCgEGCgEBgAECoQoWBTE0MC0yCgECggEAMBwGBWeBBQIRMRMwETAJAgEBAgEDAgEWBAQAAAABMIIBVwYHZ4EFBQEHATGCAUowggFGoIIBQDA7DBJPcmFjbGUgQ29ycG9yYXRpb24MBU90aGVygA1Ob3QgU3BlY2lmaWVkgQ1Ob3QgU3BlY2lmaWVkpAAwKgwST3JhY2xlIENvcnBvcmF0aW9uDApWaXJ0dWFsQm94gAEwgQMxLjKkADAkDAxpbm5vdGVrIEdtYkgMBEJJT1OAClZpcnR1YWxCb3iBAKQAMFEMEUludGVsIENvcnBvcmF0aW9uDCM4MjU0MEVNIEdpZ2FiaXQgRXRoZXJuZXQgQ29udHJvbGxlcoARMDg6MDA6Mjc6NmQ6MmM6NmKBAjAypAAwRAwiQWR2YW5jZWQgTWljcm8gRGV2aWNlcywgSW5jLiBbQU1EXQwWNzljOTcwIFtQQ25ldDMyIExBTkNFXYAAgQI0MKQAMBYMBFZCT1gMCEhBUkRESVNLgACBAKQAoQAwFAYFZ4EFAhcxCzAJAgEBAgEAAgEQMIIBODB0BgNVHSMEbTBrgBRGudxuHtihoLQVKHMF1KiHXd3fJaFLpEkwRzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlNUMRAwDgYDVQQHDAdFWEFNUExFMQwwCgYDVQQKDANvcmcxCzAJBgNVBAMMAmNhggYBZCgRrgMwXwYDVR0gBFgwVjBUBgIqAzBOMBwGCCsGAQUFBwIBFhBodHRwOi8vbG9jYWxob3N0MC4GCCsGAQUFBwICMCIMIFRDRyBUcnVzdGVkIFBsYXRmb3JtIEVuZG9yc2VtZW50MF8GA1UdEQRYMFakVDBSMRYwFAYGZ4EFBQEEDApWaXJ0dWFsQm94MRgwFgYGZ4EFBQEBDAxpbm5vdGVrIEdtYkgxDzANBgZngQUFAQUMAzEuMjENMAsGBmeBBQUBBgwBMDANBgkqhkiG9w0BAQsFAAOCAQEAEWFYoI3hdBscf4h/iqH02w1iRkKKrwAdkctnTxI6fsIU+Mxj45qJ73wTav4Wz4lYJ2rTxH6DpWXVtn14JWfCHfd/szB6sv/f2kgCQ5QZUKEIY2NBPvMvSaAKV0ecNfccUW/FCtS90v1RRTgthzZyrjhVI621fX1KTkwmgNOfOefR6mrRxrye0LNUfYl+HfuMw1EuDL4H4lxuZepP8GJgpR3gP55F5GtVcVIZ1yMu6ujsbzxDPLhlEzjGJBBcoJOWhXmbp0BLKrjTKI09WEm2Jlp+7y4L7tur5qhWm8H4wSgehYGMEaFNVmAAZ1ELmtxDm+FABLSVOwoyFRTfoe/nuA==
-----END ATTRIBUTE CERTIFICATE-----

View File

@ -0,0 +1,43 @@
-----BEGIN ATTRIBUTE CERTIFICATE-----
MIIHgDCCBmgCAQEwgZWggZIwgYmkgYYwgYMxCzAJBgNVBAYTAkRFMSEwHwYDVQQK
DBhJbmZpbmVvbiBUZWNobm9sb2dpZXMgQUcxGjAYBgNVBAsMEU9QVElHQShUTSkg
VFBNMi4wMTUwMwYDVQQDDCxJbmZpbmVvbiBPUFRJR0EoVE0pIFJTQSBNYW51ZmFj
dHVyaW5nIENBIDAyMgIEewdr5KBaMFikVjBUMQswCQYDVQQGEwJVUzEUMBIGA1UE
CgwLRXhhbXBsZS5vcmcxDTALBgNVBAsMBHRlc3QxIDAeBgNVBAMMF1BsYXRmb3Jt
IENlcnRpZmljYXRlIENBMA0GCSqGSIb3DQEBCwUAAhRgKWfqeST97mzBULkeg3d9
H0J5mTAiGA8yMDE3MDgyMDE1NTM0NFoYDzIwMjAwODIwMTU1MzQ0WjCCA7QwHAYF
Z4EFAhExEzARMAkCAQICAQACASsEBAAAAAEwFAYFZ4EFAhcxCzAJAgEBAgEAAgEL
MIHHBgVngQUCEzGBvTCBugIBAKB0FgMzLjEKAQcKAQIBAQCAAQGBBSoDBAUGoi0W
K2h0dHBzOi8vd3d3LmludGVsLmNvbS9wcm90ZWN0aW9ucHJvZmlsZS5wZGaDBSoD
BAUHpCQWImh0dHBzOi8vd3d3LmludGVsLmNvbS9jY3RhcmdldC5wZGahDRYFMTQw
LTIKAQEBAQCCAQMBAQAWKmh0dHBzOi8vd3d3LmludGVsLmNvbS9pc29jZXJ0aWZp
Y2F0aW9uLnBkZjAsBgZngQUFAQMxIjAgFh5odHRwczovL3d3dy5pbnRlbC5jb20v
UENScy54bWwwggKEBgdngQUFAQcBMYICdzCCAnOgggIiMEQMEUludGVsIENvcnBv
cmF0aW9uDAlOVUM3aTVETkKADEJURE43MzIwMDBRTYEKSjU3NjI2LTQwMYIHKwYB
BAGCV4MB/zAxDBFJbnRlbCBDb3Jwb3JhdGlvbgwLT1VUIE9GIFNQRUOAAIEBMoIH
KwYBBAGCV4MB/zCBjgwUSW50ZWwoUikgQ29ycG9yYXRpb24MKEludGVsKFIpIENv
cmUoVE0pIGk1LTczMDBVIENQVSBAIDIuNjBHSHqAFlRvIEJlIEZpbGxlZCBCeSBP
LkUuTS6BKEludGVsKFIpIENvcmUoVE0pIGk1LTczMDBVIENQVSBAIDIuNjBHSHqC
BysGAQQBgleDAf8wQQwLSW50ZWwgQ29ycC4MBEJJT1OBIEROS0JMaTV2Ljg2QS4w
MDE5LjIwMTcuMDgwNC4xMTQ2ggcrBgEEAYJXgwH/MCgMB1NhbXN1bmcMEE00NzFB
NTE0M0VCMC1DUEKBCDk4NTBFQjJEgwH/MDYMCEtJTkdTVE9ODAxTQTQwMFMzNzEy
MEeAEDUwMDI2Qjc3NzgwNTI3MEKCBysGAQQBjBqDAf8wcQwRSW50ZWwgQ29ycG9y
YXRpb24MG0V0aGVybmV0IENvbm5lY3Rpb24gSTIxOS1MTYAROGM6MGY6NmY6NzI6
YzY6YzWBAjIxggcrBgEEAYJXgwH/pBwwGgYFZ4EFEQEMEThjOjBmOjZmOjcyOmM2
OmM1oRswDAwEdlBybwwEdHJ1ZTALDANBTVQMBHRydWWiLhYsaHR0cHM6Ly93d3cu
aW50ZWwuY29tL3BsYXRmb3JtcHJvcGVydGllcy54bWwwggFsMHwGA1UdIAR1MHMw
cQYKKoZIhvhNAQUCBDBjMDEGCCsGAQUFBwIBFiVodHRwczovL3d3dy5pbnRlbC5j
b20vcGxhdGNlcnRjcHMucGRmMC4GCCsGAQUFBwICMCIMIFRDRyBUcnVzdGVkIFBs
YXRmb3JtIEVuZG9yc2VtZW50MB8GA1UdIwQYMBaAFJmT1DnLMuKrlfc3o7d3KRzU
pDm2MDQGCCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYYaHR0cHM6Ly9leGFtcGxl
LmNvbS9vY3NwMIGUBgNVHREEgYwwgYmkgYYwgYMxHTAbBgZngQUFAQEMEUludGVs
IENvcnBvcmF0aW9uMRUwEwYGZ4EFBQECMAkGBysGAQQBglcxFjAUBgZngQUFAQQM
Ck5VQzdpNUROSEUxFjAUBgZngQUFAQUMCko3MTczOS00MDExGzAZBgZngQUFAQYM
D0RXMTYwMDQyMDMwMDExMDANBgkqhkiG9w0BAQsFAAOCAQEAgXjdUlD16jiwNEuc
MNTXKP9HrJfnihv5XXtnTdm3LrVhdaiyeKXgxI1/70FrNL7ZO37BhMnud4PIgbbU
320fxJBIcWO2rkwlPj7rR2S7fiaUTgO1NwCtW5QZ3TBJ0AU6XvFVSaEvi22JZjbJ
ZyOJuaAKlSyPPkRftAGDewJHxzfpaG9g0hZB4KdTYDYiSdU42L4izd/bY4nVyTia
SWjBWpxZpwZTLP2At4lEVkG7ifjlybGZkHUecjRogfvyzuJ3e05Y2/j4IzIqdmKv
20M/ogn0QP42rVSwYjgztHmkZfd6fbklltDDOdOV73q5NKc2l8vkx9GN2hItkWJ0
3zSQeA==
-----END ATTRIBUTE CERTIFICATE-----

View File

@ -0,0 +1,3 @@
-----BEGIN ATTRIBUTE CERTIFICATE-----
MIIFJTCCBA0CAQEwV6BVMEukSTBHMQswCQYDVQQGEwJVUzELMAkGA1UECAwCU1QxEDAOBgNVBAcMB0VYQU1QTEUxDDAKBgNVBAoMA29yZzELMAkGA1UEAwwCY2ECBgFkKBN3iqBNMEukSTBHMQswCQYDVQQGEwJVUzELMAkGA1UECAwCU1QxEDAOBgNVBAcMB0VYQU1QTEUxDDAKBgNVBAoMA29yZzELMAkGA1UEAwwCY2EwDQYJKoZIhvcNAQELBQACDgGu/H+usYn7Cxf59c33MCIYDzIwMTgwNjI4MDQwMDAwWhgPMjAyODA2MzAwNDAwMDBaMIIB3zAqBgVngQUCEzEhMB+gDhYDMi4yCgEGCgEBgAECoQoWBTE0MC0yCgECggEAMBwGBWeBBQIRMRMwETAJAgEBAgEDAgEWBAQAAAABMIIBewYHZ4EFBQEHATGCAW4wggFqoIIBZDA7DBJPcmFjbGUgQ29ycG9yYXRpb24MBU90aGVygA1Ob3QgU3BlY2lmaWVkgQ1Ob3QgU3BlY2lmaWVkpAAwKgwST3JhY2xlIENvcnBvcmF0aW9uDApWaXJ0dWFsQm94gAEwgQMxLjKkADAkDAxpbm5vdGVrIEdtYkgMBEJJT1OAAIEKVmlydHVhbEJveKQAMFEMEUludGVsIENvcnBvcmF0aW9uDCM4MjU0MEVNIEdpZ2FiaXQgRXRoZXJuZXQgQ29udHJvbGxlcoARMDg6MDA6Mjc6NmQ6MmM6NmKBAjAypAAwVQwiQWR2YW5jZWQgTWljcm8gRGV2aWNlcywgSW5jLiBbQU1EXQwWNzljOTcwIFtQQ25ldDMyIExBTkNFXYARMDg6MDA6Mjc6ZjU6MjE6OWWBAjQwpAAwKQwEVkJPWAwISEFSRERJU0uAE1ZCYmU5ZWYzYjAtZGNiYTA0YjaBAKQAoQAwFAYFZ4EFAhcxCzAJAgEBAgEAAgEQMIIBODB0BgNVHSMEbTBrgBRGudxuHtihoLQVKHMF1KiHXd3fJaFLpEkwRzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlNUMRAwDgYDVQQHDAdFWEFNUExFMQwwCgYDVQQKDANvcmcxCzAJBgNVBAMMAmNhggYBZCgRrgMwXwYDVR0gBFgwVjBUBgIqAzBOMBwGCCsGAQUFBwIBFhBodHRwOi8vbG9jYWxob3N0MC4GCCsGAQUFBwICMCIMIFRDRyBUcnVzdGVkIFBsYXRmb3JtIEVuZG9yc2VtZW50MF8GA1UdEQRYMFakVDBSMRYwFAYGZ4EFBQEEDApWaXJ0dWFsQm94MRgwFgYGZ4EFBQEBDAxpbm5vdGVrIEdtYkgxDzANBgZngQUFAQUMAzEuMjENMAsGBmeBBQUBBgwBMDANBgkqhkiG9w0BAQsFAAOCAQEAlH++UXf8MldFwLV3SHd+hmJyLsPxfY7at3tVo/qiwKTvUKOXJTZl/m/k1XysqCT1rqkKurIeBcYAYTRlVuAbeqvmn+8pjbiOh5eUn9MAvndZ1tDHCSBs85CyC6AHQpG2FnPAhMnrvCXcST/qxBUFPa+BayrORUjII7n0Ti3Y4dX8E2T5lI+xCEh1HM4V9DIoKLQhGUmNYd3jvl584cW3v5zBMVv3CxHHgBzVbqMHw0WXlgI6PELm1urseUfbHtK1JVU1s7C9H0YA9HvcQ/zxA8fcEuZAhRkzIsaVe5jAKWhpT3EL056IOhtI9vvOqiUQ0aoJJsBHUlRJNuscGdOolA==
-----END ATTRIBUTE CERTIFICATE-----

View File

@ -0,0 +1,3 @@
-----BEGIN ATTRIBUTE CERTIFICATE-----
MIIEzjCCA7YCAQEwV6BVMEukSTBHMQswCQYDVQQGEwJVUzELMAkGA1UECAwCU1QxEDAOBgNVBAcMB0VYQU1QTEUxDDAKBgNVBAoMA29yZzELMAkGA1UEAwwCY2ECBgFkKBN3iqBNMEukSTBHMQswCQYDVQQGEwJVUzELMAkGA1UECAwCU1QxEDAOBgNVBAcMB0VYQU1QTEUxDDAKBgNVBAoMA29yZzELMAkGA1UEAwwCY2EwDQYJKoZIhvcNAQELBQACDgTQbuZ+aGZ8yTKkIlGcMCIYDzIwMTgwNjI4MDQwMDAwWhgPMjAyODA2MzAwNDAwMDBaMIIBiDAqBgVngQUCEzEhMB+gDhYDMi4yCgEGCgEBgAECoQoWBTE0MC0yCgECggEAMBwGBWeBBQIRMRMwETAJAgEBAgEDAgEWBAQAAAABMIIBJAYHZ4EFBQEHATGCARcwggEToIIBDTAhDBJPcmFjbGUgQ29ycG9yYXRpb24MBU90aGVygACBAKQAMCYMEk9yYWNsZSBDb3Jwb3JhdGlvbgwKVmlydHVhbEJveIAAgQCkADAkDAxpbm5vdGVrIEdtYkgMBEJJT1OAAIEKVmlydHVhbEJveKQAMD4MEUludGVsIENvcnBvcmF0aW9uDCM4MjU0MEVNIEdpZ2FiaXQgRXRoZXJuZXQgQ29udHJvbGxlcoAAgQCkADBCDCJBZHZhbmNlZCBNaWNybyBEZXZpY2VzLCBJbmMuIFtBTURdDBY3OWM5NzAgW1BDbmV0MzIgTEFOQ0VdgACBAKQAMBYMBFZCT1gMCEhBUkRESVNLgACBAKQAoQAwFAYFZ4EFAhcxCzAJAgEBAgEAAgEQMIIBODB0BgNVHSMEbTBrgBRGudxuHtihoLQVKHMF1KiHXd3fJaFLpEkwRzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlNUMRAwDgYDVQQHDAdFWEFNUExFMQwwCgYDVQQKDANvcmcxCzAJBgNVBAMMAmNhggYBZCgRrgMwXwYDVR0gBFgwVjBUBgIqAzBOMBwGCCsGAQUFBwIBFhBodHRwOi8vbG9jYWxob3N0MC4GCCsGAQUFBwICMCIMIFRDRyBUcnVzdGVkIFBsYXRmb3JtIEVuZG9yc2VtZW50MF8GA1UdEQRYMFakVDBSMRYwFAYGZ4EFBQEEDApWaXJ0dWFsQm94MRgwFgYGZ4EFBQEBDAxpbm5vdGVrIEdtYkgxDzANBgZngQUFAQUMAzEuMjENMAsGBmeBBQUBBgwBMDANBgkqhkiG9w0BAQsFAAOCAQEAb/IhDAmWMU5xELnHQS/ZH0TjTxw5sBRJrs39/HW1xHLcYCjQa0n7tMCGqdaeXw2k/LX5GWy6SMXKgq6U6ZEYOAkn4CEkiKS8XgJuZlg+xPwYijefcrQOOWBA58mEcwN0Vhf2QgdcFBo0n19JZq9SrQ8JakUnYxzEByXD26dEZjUdGYiWamcoyOXT1wcV7oJhj9PnsYAZsGUxFv8YCChYBKE8qlgWvCuHbBpvaKmeguGbZiJZia0uBtoUfO2YFKYCOa2PNhKB3Vxt3nOoJCzOS3ACRcwFy7YoVUjUKClAzA9K7bdlSTkUBcYK6f7ncKjYCSjoBqQXjAx53OdKCPexvg==
-----END ATTRIBUTE CERTIFICATE-----

View File

@ -0,0 +1,37 @@
-----BEGIN ATTRIBUTE CERTIFICATE-----
MIIGeDCCBWACAQEwgZWggZIwgYmkgYYwgYMxCzAJBgNVBAYTAkRFMSEwHwYDVQQK
DBhJbmZpbmVvbiBUZWNobm9sb2dpZXMgQUcxGjAYBgNVBAsMEU9QVElHQShUTSkg
VFBNMi4wMTUwMwYDVQQDDCxJbmZpbmVvbiBPUFRJR0EoVE0pIFJTQSBNYW51ZmFj
dHVyaW5nIENBIDAyMgIEewdr5KBaMFikVjBUMQswCQYDVQQGEwJVUzEUMBIGA1UE
CgwLRXhhbXBsZS5vcmcxDTALBgNVBAsMBHRlc3QxIDAeBgNVBAMMF1BsYXRmb3Jt
IENlcnRpZmljYXRlIENBMA0GCSqGSIb3DQEBCwUAAhRgKWfqeST97mzBULkeg3d9
H0J5mTAiGA8yMDE3MDgyMDE1NTM0NFoYDzIwMjAwODIwMTU1MzQ0WjCCAqwwHAYF
Z4EFAhExEzARMAkCAQICAQACASsEBAAAAAEwFAYFZ4EFAhcxCzAJAgEBAgEAAgEL
MIHHBgVngQUCEzGBvTCBugIBAKB0FgMzLjEKAQcKAQIBAQCAAQGBBSoDBAUGoi0W
K2h0dHBzOi8vd3d3LmludGVsLmNvbS9wcm90ZWN0aW9ucHJvZmlsZS5wZGaDBSoD
BAUHpCQWImh0dHBzOi8vd3d3LmludGVsLmNvbS9jY3RhcmdldC5wZGahDRYFMTQw
LTIKAQEBAQCCAQMBAQAWKmh0dHBzOi8vd3d3LmludGVsLmNvbS9pc29jZXJ0aWZp
Y2F0aW9uLnBkZjAsBgZngQUFAQMxIjAgFh5odHRwczovL3d3dy5pbnRlbC5jb20v
UENScy54bWwwggF8BgdngQUFAQcBMYIBbzCCAWugggEaMEQMEUludGVsIENvcnBv
cmF0aW9uDAlOVUM3aTVETkKADEJURE43MzIwMDBRTYEKSjU3NjI2LTQwMYIHKwYB
BAGCV4MB/zCBjgwUSW50ZWwoUikgQ29ycG9yYXRpb24MKEludGVsKFIpIENvcmUo
VE0pIGk1LTczMDBVIENQVSBAIDIuNjBHSHqAFlRvIEJlIEZpbGxlZCBCeSBPLkUu
TS6BKEludGVsKFIpIENvcmUoVE0pIGk1LTczMDBVIENQVSBAIDIuNjBHSHqCBysG
AQQBgleDAf8wQQwLSW50ZWwgQ29ycC4MBEJJT1OBIEROS0JMaTV2Ljg2QS4wMDE5
LjIwMTcuMDgwNC4xMTQ2ggcrBgEEAYJXgwH/oRswDAwEdlBybwwEdHJ1ZTALDANB
TVQMBHRydWWiLhYsaHR0cHM6Ly93d3cuaW50ZWwuY29tL3BsYXRmb3JtcHJvcGVy
dGllcy54bWwwggFsMHwGA1UdIAR1MHMwcQYKKoZIhvhNAQUCBDBjMDEGCCsGAQUF
BwIBFiVodHRwczovL3d3dy5pbnRlbC5jb20vcGxhdGNlcnRjcHMucGRmMC4GCCsG
AQUFBwICMCIMIFRDRyBUcnVzdGVkIFBsYXRmb3JtIEVuZG9yc2VtZW50MB8GA1Ud
IwQYMBaAFJmT1DnLMuKrlfc3o7d3KRzUpDm2MDQGCCsGAQUFBwEBBCgwJjAkBggr
BgEFBQcwAYYYaHR0cHM6Ly9leGFtcGxlLmNvbS9vY3NwMIGUBgNVHREEgYwwgYmk
gYYwgYMxHTAbBgZngQUFAQEMEUludGVsIENvcnBvcmF0aW9uMRUwEwYGZ4EFBQEC
MAkGBysGAQQBglcxFjAUBgZngQUFAQQMCk5VQzdpNUROSEUxFjAUBgZngQUFAQUM
Cko3MTczOS00MDExGzAZBgZngQUFAQYMD0RXMTYwMDQyMDMwMDExMDANBgkqhkiG
9w0BAQsFAAOCAQEAcWts9N210lLj4HlSIzYVX46oZQWz7jaGfkatoiUBOJwTloAV
1ZwyFEq9VCFGj2qgXv2ndMQGQWjSUrBakmkZQcLU3SCuQkP4F3K8sg2tL+xJOu1s
UvTDMs7nJM8TAhlHUi2+j/u7tjWUPOxjoLkv5AfkZIPT+QD1+jXCPZjgsm+soQQb
x/LrydPk+qjXiD/w+VRshLpBgc7ob3k9/r+FqdrqTeAy6XhrsgOrY0J/bvGHnK4V
nIGBrtCkb6KJN7HCaUvxV9zC0R9IuWAWmBleKtX/OEg79rDNUXfDwoNoFcsM3faq
GmrMH1qGfLP344wOLJIgfwF6W/qr5152w9wliw==
-----END ATTRIBUTE CERTIFICATE-----

View File

@ -0,0 +1,3 @@
-----BEGIN ATTRIBUTE CERTIFICATE-----
MIIFJTCCBA0CAQEwV6BVMEukSTBHMQswCQYDVQQGEwJVUzELMAkGA1UECAwCU1QxEDAOBgNVBAcMB0VYQU1QTEUxDDAKBgNVBAoMA29yZzELMAkGA1UEAwwCY2ECBgFkKBN3iqBNMEukSTBHMQswCQYDVQQGEwJVUzELMAkGA1UECAwCU1QxEDAOBgNVBAcMB0VYQU1QTEUxDDAKBgNVBAoMA29yZzELMAkGA1UEAwwCY2EwDQYJKoZIhvcNAQELBQACDgGu/H+usYn7Cxf59c33MCIYDzIwMTgwNjI4MDQwMDAwWhgPMjAyODA2MzAwNDAwMDBaMIIB3zAqBgVngQUCEzEhMB+gDhYDMi4yCgEGCgEBgAECoQoWBTE0MC0yCgECggEAMBwGBWeBBQIRMRMwETAJAgEBAgEDAgEWBAQAAAABMIIBewYHZ4EFBQEHATGCAW4wggFqoIIBZDA7DBJPcmFjbGUgQ29ycG9yYXRpb24MBU90aGVygA1Ob3QgU3BlY2lmaWVkgQ1Ob3QgU3BlY2lmaWVkpAAwKgwST3JhY2xlIENvcnBvcmF0aW9uDApWaXJ0dWFsQm94gAEwgQMxLjKkADAkDAxpbm5vdGVrIEdtYkgMBEJJT1OAAIEKVmlydHVhbEJveKQAMFEMEUludGVsIENvcnBvcmF0aW9uDCM4MjU0MEVNIEdpZ2FiaXQgRXRoZXJuZXQgQ29udHJvbGxlcoARMDg6MDA6Mjc6NmQ6MmM6NmKBAjAypAAwVQwiQWR2YW5jZWQgTWljcm8gRGV2aWNlcywgSW5jLiBbQU1EXQwWNzljOTcwIFtQQ25ldDMyIExBTkNFXYARMDg6MDA6Mjc6ZjU6MjE6OWWBAjQwpAAwKQwEVkJPWAwISEFSRERJU0uAE1ZCYmU5ZWYzYjAtZGNiYTA0YjaBAKQAoQAwFAYFZ4EFAhcxCzAJAgEBAgEAAgEQMIIBODB0BgNVHSMEbTBrgBRGudxuHtihoLQVKHMF1KiHXd3fJaFLpEkwRzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlNUMRAwDgYDVQQHDAdFWEFNUExFMQwwCgYDVQQKDANvcmcxCzAJBgNVBAMMAmNhggYBZCgRrgMwXwYDVR0gBFgwVjBUBgIqAzBOMBwGCCsGAQUFBwIBFhBodHRwOi8vbG9jYWxob3N0MC4GCCsGAQUFBwICMCIMIFRDRyBUcnVzdGVkIFBsYXRmb3JtIEVuZG9yc2VtZW50MF8GA1UdEQRYMFakVDBSMRYwFAYGZ4EFBQEEDApWaXJ0dWFsQm94MRgwFgYGZ4EFBQEBDAxpbm5vdGVrIEdtYkgxDzANBgZngQUFAQUMAzEuMjENMAsGBmeBBQUBBgwBMDANBgkqhkiG9w0BAQsFAAOCAQEAlH++UXf8MldFwLV3SHd+hmJyLsPxfY7at3tVo/qiwKTvUKOXJTZl/m/k1XysqCT1rqkKurIeBcYAYTRlVuAbeqvmn+8pjbiOh5eUn9MAvndZ1tDHCSBs85CyC6AHQpG2FnPAhMnrvCXcST/qxBUFPa+BayrORUjII7n0Ti3Y4dX8E2T5lI+xCEh1HM4V9DIoKLQhGUmNYd3jvl584cW3v5zBMVv3CxHHgBzVbqMHw0WXlgI6PELm1urseUfbHtK1JVU1s7C9H0YA9HvcQ/zxA8fcEuZAhRkzIsaVe5jAKWhpT3EL056IOhtI9vvOqiUQ0aoJJsBHUlRJNuscGdOolA==
-----END ATTRIBUTE CERTIFICATE-----

View File

@ -0,0 +1,31 @@
-----BEGIN ATTRIBUTE CERTIFICATE-----
MIIFVDCCBDwCAQEwgZWggZIwgYmkgYYwgYMxCzAJBgNVBAYTAkRFMSEwHwYDVQQK
DBhJbmZpbmVvbiBUZWNobm9sb2dpZXMgQUcxGjAYBgNVBAsMEU9QVElHQShUTSkg
VFBNMi4wMTUwMwYDVQQDDCxJbmZpbmVvbiBPUFRJR0EoVE0pIFJTQSBNYW51ZmFj
dHVyaW5nIENBIDAyMgIEewdr5KBaMFikVjBUMQswCQYDVQQGEwJVUzEUMBIGA1UE
CgwLRXhhbXBsZS5vcmcxDTALBgNVBAsMBHRlc3QxIDAeBgNVBAMMF1BsYXRmb3Jt
IENlcnRpZmljYXRlIENBMA0GCSqGSIb3DQEBCwUAAhRgKWfqeST97mzBULkeg3d9
H0J5mTAiGA8yMDE3MDgyMDE1NTM0NFoYDzIwMjAwODIwMTU1MzQ0WjCCAYgwHAYF
Z4EFAhExEzARMAkCAQICAQACASsEBAAAAAEwFAYFZ4EFAhcxCzAJAgEBAgEAAgEL
MIHHBgVngQUCEzGBvTCBugIBAKB0FgMzLjEKAQcKAQIBAQCAAQGBBSoDBAUGoi0W
K2h0dHBzOi8vd3d3LmludGVsLmNvbS9wcm90ZWN0aW9ucHJvZmlsZS5wZGaDBSoD
BAUHpCQWImh0dHBzOi8vd3d3LmludGVsLmNvbS9jY3RhcmdldC5wZGahDRYFMTQw
LTIKAQEBAQCCAQMBAQAWKmh0dHBzOi8vd3d3LmludGVsLmNvbS9pc29jZXJ0aWZp
Y2F0aW9uLnBkZjAsBgZngQUFAQMxIjAgFh5odHRwczovL3d3dy5pbnRlbC5jb20v
UENScy54bWwwWgYHZ4EFBQEHATFPME2hGzAMDAR2UHJvDAR0cnVlMAsMA0FNVAwE
dHJ1ZaIuFixodHRwczovL3d3dy5pbnRlbC5jb20vcGxhdGZvcm1wcm9wZXJ0aWVz
LnhtbDCCAWwwfAYDVR0gBHUwczBxBgoqhkiG+E0BBQIEMGMwMQYIKwYBBQUHAgEW
JWh0dHBzOi8vd3d3LmludGVsLmNvbS9wbGF0Y2VydGNwcy5wZGYwLgYIKwYBBQUH
AgIwIgwgVENHIFRydXN0ZWQgUGxhdGZvcm0gRW5kb3JzZW1lbnQwHwYDVR0jBBgw
FoAUmZPUOcsy4quV9zejt3cpHNSkObYwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUF
BzABhhhodHRwczovL2V4YW1wbGUuY29tL29jc3AwgZQGA1UdEQSBjDCBiaSBhjCB
gzEdMBsGBmeBBQUBAQwRSW50ZWwgQ29ycG9yYXRpb24xFTATBgZngQUFAQIwCQYH
KwYBBAGCVzEWMBQGBmeBBQUBBAwKTlVDN2k1RE5IRTEWMBQGBmeBBQUBBQwKSjcx
NzM5LTQwMTEbMBkGBmeBBQUBBgwPRFcxNjAwNDIwMzAwMTEwMA0GCSqGSIb3DQEB
CwUAA4IBAQCUz+8hXVmwxdiM1l5nt5+hSuyB2ayNL2hYYOE5chwcjLavljb262Ya
yQLXNpPZy3mMkc7vf5PZzEcfsYzuGkj9oecyjX9E0E5K+rPvzsDgfm8a+fFYJJAC
aLAD9njg10gdLW59HEPaz137eGC+WfsylbOWX57P/cZBwzqiU4o28FNzSLzpHqCp
hizQCeGUkLn3f+YmH5tRCSXgf5atw1xXyrM1UkpNBu0EOF8AyiTpEr6aSZKT4sUe
2FBYha27sK7rKVDBL2aBHEuk0yZvqDFhH6K/0YbNkBDfz7jxHjs11jYQK7X3p1hI
oFzpTqh75a+njq1DgYBI0Lz/ETdVbktx
-----END ATTRIBUTE CERTIFICATE-----

View File

@ -73,6 +73,15 @@ ospackage {
addParentDirs = true
createDirectoryEntry true
// copy json tables
into ('/etc/hirs/aca/default-properties') {
from '../HIRS_AttestationCA/src/main/resources/component-class.json'
from '../HIRS_AttestationCA/src/main/resources/vendor-table.json'
}
// copy springboot property file
into ('/etc/hirs/aca/') {
from '../HIRS_AttestationCAPortal/src/main/resources/application.properties'
}
// copy setup scripts to /opt/hirs/aca
into ('/opt/hirs/aca/scripts/') {
from '../package/scripts/'
@ -85,21 +94,24 @@ ospackage {
}
// Post Install
postInstall 'sh /opt/hirs/aca/scripts/aca/aca_setup.sh -u'
postInstall 'bash /opt/hirs/aca/scripts/aca/aca_setup.sh -u'
// add chrontab to run ACA at boot
postInstall 'echo "@reboot root /opt/hirs/aca/scripts/aca/aca_bootRun.sh -w" >> /etc/crontab'
// run ACA after install
postInstall '/opt/hirs/aca/scripts/aca/aca_bootRun.sh -w'
postInstall '/opt/hirs/aca/scripts/aca/aca_bootRun.sh -w &'
postInstall 'chmod +x /opt/hirs/aca/scripts/aca/*'
postInstall 'bash /opt/hirs/aca/scripts/aca/check_for_aca.sh'
// Uninstall
preUninstall 'sh /opt/hirs/aca/scripts/aca/aca_remove_setup.sh'
preUninstall 'bash /opt/hirs/aca/scripts/aca/aca_remove_setup.sh'
postUninstall 'rm -rf /etc/hirs'
buildRpm {
arch = X86_64
}
buildDeb {
packageName = 'hirs-attestationca'
arch = 'amd64'
}
}

View File

@ -52,7 +52,7 @@ import java.util.Properties;
@PropertySource(value = "classpath:hibernate.properties"),
// detects if file exists, if not, ignore errors
@PropertySource(value = "file:/etc/hirs/aca/application.properties",
@PropertySource(value = "file:/etc/hirs/aca/aca.properties",
ignoreResourceNotFound = true)
})
@ComponentScan({"hirs.attestationca.portal", "hirs.attestationca.portal.page.controllers", "hirs.attestationca.persist", "hirs.attestationca.persist.entity", "hirs.attestationca.persist.service"})

View File

@ -234,16 +234,16 @@ public class CertificatePageController extends PageController<NoPageParams> {
// Add the EndorsementCredential for each PlatformCredential based on the
// serial number. (pc.HolderSerialNumber = ec.SerialNumber)
if (certificateType.equals(PLATFORMCREDENTIAL)) {
// records = OrderedListQueryDataTableAdapter.getOrderedList(
// getCertificateClass(certificateType), platformCertificateRepository,
// input, orderColumnName, criteriaModifier);
FilteredRecordsList<PlatformCredential> records = new FilteredRecordsList<>();
org.springframework.data.domain.Page<PlatformCredential> pagedResult = this.platformCertificateRepository.findAll(paging);
if (pagedResult.hasContent()) {
records.addAll(pagedResult.getContent());
records.setRecordsTotal(pagedResult.getContent().size());
} else {
records.setRecordsTotal(input.getLength());
}
records.setRecordsTotal(input.getLength());
records.setRecordsFiltered(platformCertificateRepository.count());
EndorsementCredential associatedEC;
@ -267,31 +267,31 @@ public class CertificatePageController extends PageController<NoPageParams> {
log.debug("Returning list of size: " + records.size());
return new DataTableResponse<>(records, input);
} else if (certificateType.equals(ENDORSEMENTCREDENTIAL)) {
// records = OrderedListQueryDataTableAdapter.getOrderedList(
// getCertificateClass(certificateType), endorsementCredentialRepository,
// input, orderColumnName, criteriaModifier);
FilteredRecordsList<EndorsementCredential> records = new FilteredRecordsList<>();
org.springframework.data.domain.Page<EndorsementCredential> pagedResult = this.endorsementCredentialRepository.findAll(paging);
if (pagedResult.hasContent()) {
records.addAll(pagedResult.getContent());
records.setRecordsTotal(pagedResult.getContent().size());
} else {
records.setRecordsTotal(input.getLength());
}
records.setRecordsTotal(input.getLength());
records.setRecordsFiltered(endorsementCredentialRepository.count());
log.debug("Returning list of size: " + records.size());
return new DataTableResponse<>(records, input);
} else if (certificateType.equals(TRUSTCHAIN)) {
// records = OrderedListQueryDataTableAdapter.getOrderedList(
// getCertificateClass(certificateType), caCredentialRepository,
// input, orderColumnName, criteriaModifier);
FilteredRecordsList<CertificateAuthorityCredential> records = new FilteredRecordsList<>();
org.springframework.data.domain.Page<CertificateAuthorityCredential> pagedResult = this.caCredentialRepository.findAll(paging);
if (pagedResult.hasContent()) {
records.addAll(pagedResult.getContent());
records.setRecordsTotal(pagedResult.getContent().size());
} else {
records.setRecordsTotal(input.getLength());
}
records.setRecordsTotal(input.getLength());
records.setRecordsFiltered(caCredentialRepository.count());
log.debug("Returning list of size: " + records.size());
@ -299,10 +299,14 @@ public class CertificatePageController extends PageController<NoPageParams> {
} else if (certificateType.equals(ISSUEDCERTIFICATES)) {
FilteredRecordsList<IssuedAttestationCertificate> records = new FilteredRecordsList<>();
org.springframework.data.domain.Page<IssuedAttestationCertificate> pagedResult = this.issuedCertificateRepository.findAll(paging);
if (pagedResult.hasContent()) {
records.addAll(pagedResult.getContent());
records.setRecordsTotal(pagedResult.getContent().size());
} else {
records.setRecordsTotal(input.getLength());
}
records.setRecordsTotal(input.getLength());
records.setRecordsFiltered(issuedCertificateRepository.count());
log.debug("Returning list of size: " + records.size());
@ -389,14 +393,14 @@ public class CertificatePageController extends PageController<NoPageParams> {
for (PlatformCredential pc : sharedCertificates) {
if (!pc.isPlatformBase()) {
pc.archive();
certificateRepository.delete(pc);
certificateRepository.save(pc);
}
}
}
}
certificate.archive();
certificateRepository.delete(certificate);
certificateRepository.save(certificate);
String deleteCompletedMessage = "Certificate successfully deleted";
messages.addInfo(deleteCompletedMessage);
@ -832,11 +836,11 @@ public class CertificatePageController extends PageController<NoPageParams> {
log.error(failMessage, dEx);
messages.addError(failMessage + dEx.getMessage());
return null;
} catch (IllegalArgumentException e) {
} catch (IllegalArgumentException iaEx) {
final String failMessage = String.format(
"Certificate format not recognized(%s): ", fileName);
log.error(failMessage, e);
messages.addError(failMessage + e.getMessage());
log.error(failMessage, iaEx);
messages.addError(failMessage + iaEx.getMessage());
return null;
}
}
@ -864,11 +868,11 @@ public class CertificatePageController extends PageController<NoPageParams> {
existingCertificate = getCertificateByHash(
certificateType,
certificate.getCertificateHash());
} catch (DBServiceException e) {
} catch (DBServiceException dbsEx) {
final String failMessage = "Querying for existing certificate failed ("
+ fileName + "): ";
messages.addError(failMessage + e.getMessage());
log.error(failMessage, e);
messages.addError(failMessage + dbsEx.getMessage());
log.error(failMessage, dbsEx);
return;
}
@ -924,11 +928,11 @@ public class CertificatePageController extends PageController<NoPageParams> {
log.info(successMsg);
return;
}
} catch (DBServiceException e) {
} catch (DBServiceException dbsEx) {
final String failMessage = String.format("Storing new certificate failed (%s): ",
fileName);
messages.addError(failMessage + e.getMessage());
log.error(failMessage, e);
messages.addError(failMessage + dbsEx.getMessage());
log.error(failMessage, dbsEx);
return;
}
@ -946,12 +950,12 @@ public class CertificatePageController extends PageController<NoPageParams> {
log.info(successMsg);
return;
}
} catch (DBServiceException e) {
} catch (DBServiceException dbsEx) {
final String failMessage = String.format("Found an identical"
+ " pre-existing certificate in the "
+ "archive, but failed to unarchive it (%s): ", fileName);
messages.addError(failMessage + e.getMessage());
log.error(failMessage, e);
messages.addError(failMessage + dbsEx.getMessage());
log.error(failMessage, dbsEx);
return;
}

View File

@ -84,10 +84,6 @@ public class DevicePageController extends PageController<NoPageParams> {
// get all the devices
FilteredRecordsList<Device> deviceList = new FilteredRecordsList<>();
// OrderedListQueryDataTableAdapter.getOrderedList(
// Device.class,
// deviceRepository,
// input, orderColumnName);
int currentPage = input.getStart() / input.getLength();
Pageable paging = PageRequest.of(currentPage, input.getLength(), Sort.by(orderColumnName));
@ -95,8 +91,10 @@ public class DevicePageController extends PageController<NoPageParams> {
if (pagedResult.hasContent()) {
deviceList.addAll(pagedResult.getContent());
deviceList.setRecordsTotal(pagedResult.getContent().size());
} else {
deviceList.setRecordsTotal(input.getLength());
}
deviceList.setRecordsTotal(input.getLength());
deviceList.setRecordsFiltered(deviceRepository.count());
FilteredRecordsList<HashMap<String, Object>> records
@ -131,10 +129,11 @@ public class DevicePageController extends PageController<NoPageParams> {
issuedCertificateList.addAll(issuedCertificateRepository.findByDeviceId(id));
}
HashMap<String, List<Object>> certificatePropertyMap;
// loop all the devices
for (Device device : deviceList) {
// hashmap containing the list of certificates based on the certificate type
HashMap<String, List<Object>> certificatePropertyMap = new HashMap<>();
certificatePropertyMap = new HashMap<>();
deviceCertMap.put("device", device);
String deviceName;
@ -179,8 +178,7 @@ public class DevicePageController extends PageController<NoPageParams> {
}
for (IssuedAttestationCertificate ic : issuedCertificateList) {
deviceName = deviceRepository.findById(ic.getDeviceId()).get().getName();
deviceName = ic.getDeviceName();
// set the certificate if it's the same ID
if (device.getName().equals(deviceName)) {
String certificateId = IssuedAttestationCertificate.class.getSimpleName();

View File

@ -14,7 +14,7 @@ import org.springframework.web.servlet.ModelAndView;
*/
@Controller
@Log4j2
@RequestMapping("/HIRS_AttestationCAPortal/portal/index")
@RequestMapping(value={"/", "/HIRS_AttestationCAPortal", "/HIRS_AttestationCAPortal/", "/HIRS_AttestationCAPortal/portal/index"})
public class IndexPageController extends PageController<NoPageParams> {
/**

View File

@ -1,6 +1,7 @@
package hirs.attestationca.portal.page.controllers;
import hirs.attestationca.persist.DBServiceException;
import hirs.attestationca.persist.entity.manager.CACredentialRepository;
import hirs.attestationca.persist.entity.manager.CertificateRepository;
import hirs.attestationca.persist.entity.manager.ReferenceDigestValueRepository;
import hirs.attestationca.persist.entity.manager.ReferenceManifestRepository;
@ -10,14 +11,14 @@ import hirs.utils.rim.BaseReferenceManifest;
import hirs.attestationca.persist.entity.userdefined.rim.EventLogMeasurements;
import hirs.attestationca.persist.entity.userdefined.rim.ReferenceDigestValue;
import hirs.attestationca.persist.entity.userdefined.rim.SupportReferenceManifest;
import hirs.attestationca.persist.service.SupplyChainValidationServiceImpl;
import hirs.utils.rim.ReferenceManifestValidator;
import hirs.attestationca.persist.service.ValidationService;
import hirs.attestationca.persist.validation.SupplyChainCredentialValidator;
import hirs.attestationca.persist.validation.SupplyChainValidatorException;
import hirs.attestationca.portal.page.Page;
import hirs.attestationca.portal.page.PageController;
import hirs.attestationca.portal.page.PageMessages;
import hirs.attestationca.portal.page.params.ReferenceManifestDetailsPageParams;
import hirs.attestationca.portal.page.utils.SupplyChainCredentialValidator;
import hirs.utils.SwidResource;
import hirs.utils.tpm.eventlog.TCGEventLog;
import hirs.utils.tpm.eventlog.TpmPcrEvent;
@ -31,6 +32,7 @@ import org.springframework.web.servlet.ModelAndView;
import java.io.IOException;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Arrays;
@ -52,6 +54,7 @@ public class ReferenceManifestDetailsPageController extends PageController<Refer
private final ReferenceManifestRepository referenceManifestRepository;
private final ReferenceDigestValueRepository referenceDigestValueRepository;
private final CertificateRepository certificateRepository;
private final CACredentialRepository caCertificateRepository;
private static final ReferenceManifestValidator RIM_VALIDATOR
= new ReferenceManifestValidator();
@ -61,15 +64,18 @@ public class ReferenceManifestDetailsPageController extends PageController<Refer
* @param referenceManifestRepository the repository for RIM.
* @param referenceDigestValueRepository the reference event manager.
* @param certificateRepository the certificate manager.
* @param caCertificateRepository the CA certificate manager.
*/
@Autowired
public ReferenceManifestDetailsPageController(final ReferenceManifestRepository referenceManifestRepository,
final ReferenceDigestValueRepository referenceDigestValueRepository,
final CertificateRepository certificateRepository) {
final CertificateRepository certificateRepository,
final CACredentialRepository caCertificateRepository) {
super(Page.RIM_DETAILS);
this.referenceManifestRepository = referenceManifestRepository;
this.referenceDigestValueRepository = referenceDigestValueRepository;
this.certificateRepository = certificateRepository;
this.caCertificateRepository = caCertificateRepository;
}
/**
@ -100,7 +106,8 @@ public class ReferenceManifestDetailsPageController extends PageController<Refer
try {
UUID uuid = UUID.fromString(params.getId());
data.putAll(getRimDetailInfo(uuid, referenceManifestRepository,
referenceDigestValueRepository, certificateRepository));
referenceDigestValueRepository, certificateRepository,
caCertificateRepository));
} catch (IllegalArgumentException iaEx) {
String uuidError = "Failed to parse ID from: " + params.getId();
messages.addError(uuidError);
@ -130,6 +137,7 @@ public class ReferenceManifestDetailsPageController extends PageController<Refer
* @param referenceManifestRepository the reference manifest manager.
* @param referenceDigestValueRepository the reference event manager.
* @param certificateRepository the certificate manager.
* @param caCertificateRepository the certificate manager.
* @return mapping of the RIM information from the database.
* @throws java.io.IOException error for reading file bytes.
* @throws NoSuchAlgorithmException If an unknown Algorithm is encountered.
@ -138,7 +146,8 @@ public class ReferenceManifestDetailsPageController extends PageController<Refer
public static HashMap<String, Object> getRimDetailInfo(final UUID uuid,
final ReferenceManifestRepository referenceManifestRepository,
final ReferenceDigestValueRepository referenceDigestValueRepository,
final CertificateRepository certificateRepository)
final CertificateRepository certificateRepository,
final CACredentialRepository caCertificateRepository)
throws IOException,
CertificateException, NoSuchAlgorithmException {
HashMap<String, Object> data = new HashMap<>();
@ -146,7 +155,7 @@ public class ReferenceManifestDetailsPageController extends PageController<Refer
BaseReferenceManifest bRim = referenceManifestRepository.getBaseRimEntityById(uuid);
if (bRim != null) {
data.putAll(getBaseRimInfo(bRim, referenceManifestRepository, certificateRepository));
data.putAll(getBaseRimInfo(bRim, referenceManifestRepository, certificateRepository, caCertificateRepository));
}
SupportReferenceManifest sRim = referenceManifestRepository.getSupportRimEntityById(uuid);
@ -172,6 +181,7 @@ public class ReferenceManifestDetailsPageController extends PageController<Refer
* @param baseRim established ReferenceManifest Type.
* @param referenceManifestRepository the reference manifest manager.
* @param certificateRepository the certificate manager.
* @param caCertificateRepository the certificate manager.
* @return mapping of the RIM information from the database.
* @throws java.io.IOException error for reading file bytes.
* @throws NoSuchAlgorithmException If an unknown Algorithm is encountered.
@ -180,7 +190,8 @@ public class ReferenceManifestDetailsPageController extends PageController<Refer
private static HashMap<String, Object> getBaseRimInfo(
final BaseReferenceManifest baseRim,
final ReferenceManifestRepository referenceManifestRepository,
final CertificateRepository certificateRepository)
final CertificateRepository certificateRepository,
final CACredentialRepository caCertificateRepository)
throws IOException, CertificateException, NoSuchAlgorithmException {
HashMap<String, Object> data = new HashMap<>();
@ -256,8 +267,8 @@ public class ReferenceManifestDetailsPageController extends PageController<Refer
baseRim.setAssociatedRim(support.getId());
}
} else {
support = (SupportReferenceManifest) referenceManifestRepository
.getReferenceById(baseRim.getAssociatedRim());
support = referenceManifestRepository
.getSupportRimEntityById(baseRim.getAssociatedRim());
}
// going to have to pull the filename and grab that from the DB
// to get the id to make the link
@ -288,9 +299,7 @@ public class ReferenceManifestDetailsPageController extends PageController<Refer
//Report invalid signature unless RIM_VALIDATOR validates it and cert path is valid
data.put("signatureValid", false);
for (CertificateAuthorityCredential cert : certificates) {
SupplyChainValidationServiceImpl scvsImpl =
new SupplyChainValidationServiceImpl(certificateRepository);
KeyStore keystore = scvsImpl.getCaChain(cert);
KeyStore keystore = ValidationService.getCaChain(cert, caCertificateRepository);
if (RIM_VALIDATOR.validateXmlSignature(cert)) {
try {
if (SupplyChainCredentialValidator.verifyCertificate(
@ -298,21 +307,23 @@ public class ReferenceManifestDetailsPageController extends PageController<Refer
data.replace("signatureValid", true);
break;
}
} catch (SupplyChainValidatorException e) {
log.error("Error verifying cert chain: " + e.getMessage());
} catch (SupplyChainValidatorException scvEx) {
log.error("Error verifying cert chain: " + scvEx.getMessage());
}
}
}
data.put("skID", RIM_VALIDATOR.getSubjectKeyIdentifier());
try {
for (CertificateAuthorityCredential cert : certificates) {
if (Arrays.equals(cert.getEncodedPublicKey(),
RIM_VALIDATOR.getPublicKey().getEncoded())) {
data.put("issuerID", cert.getId().toString());
if (RIM_VALIDATOR.getPublicKey() != null) {
for (CertificateAuthorityCredential cert : certificates) {
if (Arrays.equals(cert.getEncodedPublicKey(),
RIM_VALIDATOR.getPublicKey().getEncoded())) {
data.put("issuerID", cert.getId().toString());
}
}
}
} catch (NullPointerException e) {
log.warn("Unable to link signing certificate: " + e.getMessage());
} catch (NullPointerException npEx) {
log.warn("Unable to link signing certificate: " + npEx.getMessage());
}
return data;
}

View File

@ -1,18 +1,15 @@
package hirs.attestationca.portal.page.controllers;
import hirs.attestationca.persist.CriteriaModifier;
import hirs.attestationca.persist.DBManagerException;
import hirs.attestationca.persist.FilteredRecordsList;
import hirs.attestationca.persist.entity.manager.ReferenceDigestValueRepository;
import hirs.attestationca.persist.entity.manager.ReferenceManifestRepository;
import hirs.utils.Certificate;
import hirs.utils.rim.ReferenceManifest;
import hirs.utils.rim.BaseReferenceManifest;
import hirs.attestationca.persist.entity.userdefined.rim.ReferenceDigestValue;
import hirs.attestationca.persist.entity.userdefined.rim.SupportReferenceManifest;
import hirs.attestationca.portal.datatables.DataTableInput;
import hirs.attestationca.portal.datatables.DataTableResponse;
import hirs.attestationca.portal.datatables.OrderedListQueryDataTableAdapter;
import hirs.attestationca.portal.page.Page;
import hirs.attestationca.portal.page.PageController;
import hirs.attestationca.portal.page.PageMessages;
@ -20,13 +17,9 @@ import hirs.attestationca.portal.page.params.NoPageParams;
import hirs.utils.tpm.eventlog.TCGEventLog;
import hirs.utils.tpm.eventlog.TpmPcrEvent;
import jakarta.persistence.EntityManager;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Root;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import lombok.extern.log4j.Log4j2;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
@ -45,7 +38,6 @@ import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.springframework.web.servlet.view.RedirectView;
import java.io.IOException;
import java.lang.ref.Reference;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
@ -123,36 +115,27 @@ public class ReferenceManifestPageController extends PageController<NoPageParams
String orderColumnName = input.getOrderColumnName();
log.info("Ordering on column: " + orderColumnName);
// check that the alert is not archived and that it is in the specified report
CriteriaModifier criteriaModifier = new CriteriaModifier() {
@Override
public void modify(final CriteriaQuery criteriaQuery) {
Session session = entityManager.unwrap(Session.class);
CriteriaBuilder cb = session.getCriteriaBuilder();
Root<ReferenceManifest> rimRoot = criteriaQuery.from(Reference.class);
criteriaQuery.select(rimRoot).distinct(true).where(cb.isNull(rimRoot.get(Certificate.ARCHIVE_FIELD)));
}
};
log.info("Querying with the following dataTableInput: " + input.toString());
FilteredRecordsList<ReferenceManifest> records = new FilteredRecordsList<>();
int currentPage = input.getStart() / input.getLength();
Pageable paging = PageRequest.of(currentPage, input.getLength(), Sort.by(orderColumnName));
org.springframework.data.domain.Page<ReferenceManifest> pagedResult = referenceManifestRepository.findAll(paging);
int rimCount = 0;
if (pagedResult.hasContent()) {
records.addAll(pagedResult.getContent());
for (ReferenceManifest manifest : pagedResult.getContent()) {
if (!manifest.getRimType().equals(ReferenceManifest.MEASUREMENT_RIM)) {
records.add(manifest);
rimCount++;
}
}
records.setRecordsTotal(rimCount);
} else {
records.setRecordsTotal(input.getLength());
}
records.setRecordsTotal(input.getLength());
records.setRecordsFiltered(referenceManifestRepository.count());
// FilteredRecordsList<ReferenceManifest> records
// = OrderedListQueryDataTableAdapter.getOrderedList(
// ReferenceManifest.class,
// this.referenceManifestRepository,
// input, orderColumnName, criteriaModifier);
log.debug("Returning list of size: " + records.size());
return new DataTableResponse<>(records, input);

View File

@ -1,35 +0,0 @@
package hirs.attestationca.portal.page.controllers;
/**
* Restful implementation of the {@link }.
* Exposes the ACA methods as REST endpoints.
*/
//@RestController
//@RequestMapping("/")
public class RestfulAttestationCertificateAuthority {
// private final ReferenceManifestRepository referenceManifestRepository;
// private final ReferenceDigestValueRepository referenceDigestValueRepository;
//
// @Autowired
// public RestfulAttestationCertificateAuthority(
// final ReferenceManifestRepository referenceManifestRepository,
// final ReferenceDigestValueRepository referenceDigestValueRepository) {
//
// this.referenceManifestRepository = referenceManifestRepository;
// this.referenceDigestValueRepository = referenceDigestValueRepository;
//
// }
//
//
// @ResponseBody
// @RequestMapping(value = "/upload-swidtag", method = RequestMethod.POST, consumes = MediaType.APPLICATION_OCTET_STREAM_VALUE)
// public byte[] uploadSwidtag(@RequestBody final byte[] request) {
// return null;
// }
//
// @ResponseBody
// @RequestMapping(value = "/upload-rimel", method = RequestMethod.POST, consumes = MediaType.APPLICATION_OCTET_STREAM_VALUE)
// public byte[] uploadRimel(@RequestBody final byte[] request) {
// return null;
// }
}

View File

@ -116,15 +116,12 @@ public class RimDatabasePageController extends PageController<NoPageParams> {
if (pagedResult.hasContent()) {
referenceDigestValues.addAll(pagedResult.getContent());
referenceDigestValues.setRecordsTotal(pagedResult.getContent().size());
} else {
referenceDigestValues.setRecordsTotal(input.getLength());
}
referenceDigestValues.setRecordsTotal(input.getLength());
referenceDigestValues.setRecordsFiltered(referenceDigestValueRepository.count());
// FilteredRecordsList<ReferenceDigestValue> referenceDigestValues =
// OrderedListQueryDataTableAdapter.getOrderedList(
// referenceDigestValueRepository,
// input, orderColumnName, criteriaModifier, entityManager);
// might be able to get rid of this, maybe right a query that looks for not updated
SupportReferenceManifest support;
for (ReferenceDigestValue rdv : referenceDigestValues) {

View File

@ -2,13 +2,11 @@ package hirs.attestationca.portal.page.controllers;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import hirs.attestationca.persist.CriteriaModifier;
import hirs.attestationca.persist.FilteredRecordsList;
import hirs.attestationca.persist.entity.manager.CertificateRepository;
import hirs.attestationca.persist.entity.manager.DeviceRepository;
import hirs.attestationca.persist.entity.manager.PlatformCertificateRepository;
import hirs.attestationca.persist.entity.manager.SupplyChainValidationSummaryRepository;
import hirs.utils.Certificate;
import hirs.attestationca.persist.entity.userdefined.Device;
import hirs.attestationca.persist.entity.userdefined.SupplyChainValidationSummary;
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
@ -16,18 +14,13 @@ import hirs.attestationca.persist.entity.userdefined.certificate.attributes.Comp
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.V2.ComponentIdentifierV2;
import hirs.attestationca.portal.datatables.DataTableInput;
import hirs.attestationca.portal.datatables.DataTableResponse;
import hirs.attestationca.portal.datatables.OrderedListQueryDataTableAdapter;
import hirs.attestationca.portal.page.Page;
import hirs.attestationca.portal.page.PageController;
import hirs.attestationca.portal.page.params.NoPageParams;
import jakarta.persistence.EntityManager;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Root;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.log4j.Log4j2;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
@ -43,7 +36,6 @@ import org.springframework.web.servlet.ModelAndView;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.lang.ref.Reference;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.LocalDateTime;
@ -52,7 +44,6 @@ import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -128,20 +119,6 @@ public class ValidationReportsPageController extends PageController<NoPageParams
String orderColumnName = input.getOrderColumnName();
log.debug("Ordering on column: " + orderColumnName);
// define an alias so the composite object, device, can be used by the
// datatables / query. This is necessary so the device.name property can
// be used.
CriteriaModifier criteriaModifier = new CriteriaModifier() {
@Override
public void modify(final CriteriaQuery criteriaQuery) {
Session session = entityManager.unwrap(Session.class);
CriteriaBuilder cb = session.getCriteriaBuilder();
Root<Certificate> scvRoot = criteriaQuery.from(Reference.class);
criteriaQuery.select(scvRoot).distinct(true).where(cb.isNull(scvRoot.get(Certificate.ARCHIVE_FIELD)));
}
};
FilteredRecordsList<SupplyChainValidationSummary> records = new FilteredRecordsList<>();
int currentPage = input.getStart() / input.getLength();
Pageable paging = PageRequest.of(currentPage, input.getLength(), Sort.by(orderColumnName));
@ -149,15 +126,12 @@ public class ValidationReportsPageController extends PageController<NoPageParams
if (pagedResult.hasContent()) {
records.addAll(pagedResult.getContent());
records.setRecordsTotal(pagedResult.getContent().size());
} else {
records.setRecordsTotal(input.getLength());
}
records.setRecordsTotal(input.getLength());
records.setRecordsFiltered(supplyChainValidatorSummaryRepository.count());
// FilteredRecordsList<SupplyChainValidationSummary> records =
// OrderedListQueryDataTableAdapter.getOrderedList(
// SupplyChainValidationSummary.class,
// supplyChainValidatorSummaryRepository, input, orderColumnName,
// criteriaModifier);
records.setRecordsFiltered(supplyChainValidatorSummaryRepository.count());
return new DataTableResponse<>(records, input);
}

View File

@ -12,6 +12,7 @@ import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredent
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentIdentifier;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.PlatformConfiguration;
import hirs.utils.BouncyCastleUtils;
import hirs.attestationca.persist.util.PciIds;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;
@ -19,6 +20,7 @@ import org.bouncycastle.util.encoders.Hex;
import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
@ -148,15 +150,14 @@ public final class CertificateStringMapBuilder {
final Certificate certificate,
final CertificateRepository certificateRepository,
final CACredentialRepository caCredentialRepository) {
List<CertificateAuthorityCredential> issuerCertificates = new LinkedList<>();
List<CertificateAuthorityCredential> issuerCertificates = new ArrayList<>();
CertificateAuthorityCredential skiCA = null;
String issuerResult;
//Check if there is a subject organization
if (certificate.getAuthorityKeyIdentifier() != null
&& !certificate.getAuthorityKeyIdentifier().isEmpty()) {
byte[] bytes = Hex.decode(certificate.getAuthorityKeyIdentifier());
skiCA = caCredentialRepository.findBySubjectKeyIdentifier(bytes);
skiCA = caCredentialRepository.findBySubjectKeyIdString(certificate.getAuthorityKeyIdentifier());
} else {
log.error(String.format("Certificate (%s) for %s has no authority key identifier.",
certificate.getClass().toString(), certificate.getSubject()));
@ -184,7 +185,7 @@ public final class CertificateStringMapBuilder {
if (issuerResult.isEmpty()) {
//Check if it's root certificate
if (BouncyCastleUtils.x500NameCompare(issuerCert.getIssuerSorted(),
issuerCert.getSubject())) {
issuerCert.getSubjectSorted())) {
return null;
}
return containsAllChain(issuerCert, certificateRepository, caCredentialRepository);

View File

@ -1,4 +1,4 @@
#hibernate.connection.url=jdbc:mariadb://localhost:3306/hirs_db?autoReconnect=true&useSSL=false
hibernate.connection.url=jdbc:mariadb://localhost:3306/hirs_db?autoReconnect=true&sslMode=DISABLED
#hibernate.connection.username=hirs_db
#hibernate.connection.password=hirs_db
hibernate.connection.driver_class=org.mariadb.jdbc.Driver

View File

@ -52,13 +52,7 @@
data: 'deviceName',
render: function (data, type, full, meta) {
// if there's a device, display its name, otherwise
// display nothing
if (full.device) {
// TODO render a link to a device details page,
// passing the device.id
return full.deviceName;
}
return '';
return full.deviceName;
}
},
{data: 'issuer'},

View File

@ -1,3 +1,15 @@
<div class="container">
Page Not Found! <a href="/devices">Devices</a>
</div>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%-- JSP TAGS --%>
<%@taglib prefix="c" uri="jakarta.tags.core" %>
<%@taglib prefix="my" tagdir="/WEB-INF/tags"%>
<%-- CONTENT --%>
<my:page>
<jsp:attribute name="pageHeaderTitle">Error - 404</jsp:attribute>
<jsp:body>
<!--<div> Exception Message: <c:out value="${exception}"</c:out></div>
<div> from URL -> <span th:text="${url}"</span></div>-->
</jsp:body>
</my:page>

View File

@ -10,12 +10,16 @@
<jsp:body>
<h3 class="content-subhead" id="alerttype">Documentation</h3>
<!--
<ul>
<c:forEach items="${docs}" var="doc">
<li><a href="${baseURL}/docs/${doc.name}">${doc.name}</a></li>
</c:forEach>
</ul>
-->
<p>For more documentation on the project, you may visit the wiki section of our code repository.</p>
<p>
For more documentation on the project, you may visit the wiki section of our <a href="https://github.com/nsacyber/HIRS/wiki">code repository</a>.
</p>
</jsp:body>
</my:page>

View File

@ -48,12 +48,7 @@
render: function (data, type, full, meta) {
// if there's a device, display its name, otherwise
// display nothing
if (full.device) {
// TODO render a link to a device details page,
// passing the device.id
return full.deviceName;
}
return '';
return full.deviceName;
}
},
{data: 'issuer'},

Some files were not shown because too many files have changed in this diff Show More