From 69c673adb73123c7d8c83420bd5788ebd7b6f887 Mon Sep 17 00:00:00 2001 From: iadgovuser59 <133057011+iadgovuser59@users.noreply.github.com> Date: Fri, 19 Jul 2024 18:31:56 -0400 Subject: [PATCH 1/8] Implementing LDevID generation --- .../AttestationCertificateAuthority.java | 2 +- .../entity/manager/CertificateRepository.java | 2 + .../IssuedAttestationCertificate.java | 12 +- .../persist/provision/AbstractProcessor.java | 28 ++-- .../CertificateRequestProcessor.java | 22 +++- .../AbstractUserdefinedEntityTest.java | 2 +- .../WEB-INF/jsp/issued-certificates.jsp | 11 ++ .../src/main/webapp/WEB-INF/jsp/policy.jsp | 2 +- .../src/main/webapp/common/common.js | 2 +- .../portal/page/PageControllerTest.java | 2 +- .../hirs/Resources/ProvisionerTpm2.proto | 4 +- .../hirs/src/client/Client.cs | 3 +- .../hirs/src/client/IHirsAcaClient.cs | 4 +- HIRS_Provisioner.NET/hirs/src/config/CLI.cs | 5 + .../hirs/src/config/Settings.cs | 2 +- .../hirs/src/provisioner/Provisioner.cs | 38 +++++- .../hirs/src/tpm/CommandTpm.cs | 120 +++++++++++++++++- .../hirs/src/tpm/IHirsAcaTpm.cs | 2 + .../hirsTest/src/client/ClientTests.cs | 4 +- .../src/provisioner/ProvisionerTests.cs | 18 ++- .../src/ProvisionerTpm2.proto | 2 + 21 files changed, 253 insertions(+), 34 deletions(-) diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/AttestationCertificateAuthority.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/AttestationCertificateAuthority.java index c1b898db2..6ca834f8b 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/AttestationCertificateAuthority.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/AttestationCertificateAuthority.java @@ -114,7 +114,7 @@ public AttestationCertificateAuthority( this.certificateRequestHandler = new CertificateRequestProcessor(supplyChainValidationService, certificateRepository, deviceRepository, - privateKey, acaCertificate, validDays, tpm2ProvisionerStateRepository); + privateKey, acaCertificate, validDays, tpm2ProvisionerStateRepository, policyRepository); this.identityClaimHandler = new IdentityClaimProcessor(supplyChainValidationService, certificateRepository, componentResultRepository, componentInfoRepository, referenceManifestRepository, referenceDigestValueRepository, diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/manager/CertificateRepository.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/manager/CertificateRepository.java index 900a30a64..cfdfd10ac 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/manager/CertificateRepository.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/manager/CertificateRepository.java @@ -4,6 +4,7 @@ import hirs.attestationca.persist.entity.userdefined.certificate.EndorsementCredential; import hirs.attestationca.persist.entity.userdefined.certificate.IssuedAttestationCertificate; import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential; +import org.springframework.data.domain.Sort; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; @@ -35,5 +36,6 @@ public interface CertificateRepository extends JpaRepository Certificate findByCertificateHash(int certificateHash, String dType); EndorsementCredential findByPublicKeyModulusHexValue(String publicKeyModulusHexValue); IssuedAttestationCertificate findByDeviceId(UUID deviceId); + List findByDeviceIdAndIsLDevID(UUID deviceId, boolean isLDevID, Sort sort); Certificate findByCertificateHash(int certificateHash); } diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/userdefined/certificate/IssuedAttestationCertificate.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/userdefined/certificate/IssuedAttestationCertificate.java index e37bd7c80..8c4c0e418 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/userdefined/certificate/IssuedAttestationCertificate.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/userdefined/certificate/IssuedAttestationCertificate.java @@ -1,5 +1,6 @@ package hirs.attestationca.persist.entity.userdefined.certificate; +import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; import jakarta.persistence.JoinColumn; @@ -35,6 +36,9 @@ public class IssuedAttestationCertificate extends DeviceAssociatedCertificate { @JoinColumn(name = "pc_id") private List platformCredentials; + @Column + public boolean isLDevID; + /** * Constructor. * @param certificateBytes the issued certificate bytes @@ -44,11 +48,12 @@ public class IssuedAttestationCertificate extends DeviceAssociatedCertificate { */ public IssuedAttestationCertificate(final byte[] certificateBytes, final EndorsementCredential endorsementCredential, - final List platformCredentials) + final List platformCredentials, boolean isLDevID) throws IOException { super(certificateBytes); this.endorsementCredential = endorsementCredential; this.platformCredentials = new ArrayList<>(platformCredentials); + this.isLDevID = isLDevID; } /** @@ -60,9 +65,10 @@ public IssuedAttestationCertificate(final byte[] certificateBytes, */ public IssuedAttestationCertificate(final Path certificatePath, final EndorsementCredential endorsementCredential, - final List platformCredentials) + final List platformCredentials, + final boolean isLDevID) throws IOException { - this(readBytes(certificatePath), endorsementCredential, platformCredentials); + this(readBytes(certificatePath), endorsementCredential, platformCredentials, isLDevID); } public List getPlatformCredentials() { diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/AbstractProcessor.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/AbstractProcessor.java index 5a305d970..6c83221e7 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/AbstractProcessor.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/AbstractProcessor.java @@ -9,6 +9,7 @@ import hirs.attestationca.persist.entity.userdefined.PolicySettings; import hirs.attestationca.persist.entity.userdefined.certificate.EndorsementCredential; import hirs.attestationca.persist.entity.userdefined.certificate.IssuedAttestationCertificate; +import hirs.attestationca.persist.entity.userdefined.certificate.IssuedLDevIDCertificate; import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential; import hirs.attestationca.persist.exceptions.CertificateProcessingException; import hirs.attestationca.persist.provision.helper.CredentialManagementHelper; @@ -27,6 +28,7 @@ import org.bouncycastle.operator.ContentSigner; import org.bouncycastle.operator.OperatorCreationException; import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; +import org.springframework.data.domain.Sort; import java.io.IOException; import java.math.BigInteger; @@ -234,6 +236,7 @@ private EndorsementCredential getEndorsementCredential( * @param endorsementCredential the endorsement credential used to generate the AC * @param platformCredentials the platform credentials used to generate the AC * @param device the device to which the attestation certificate is tied + * @param isLDevID whether the certificate is a ldevid * @throws {@link CertificateProcessingException} if error occurs in persisting the Attestation * Certificate */ @@ -241,8 +244,8 @@ public void saveAttestationCertificate(final CertificateRepository certificateRe final byte[] derEncodedAttestationCertificate, final EndorsementCredential endorsementCredential, final List platformCredentials, - final Device device) { - IssuedAttestationCertificate issuedAc; + final Device device, boolean isLDevID) { + List issuedAc; boolean generateCertificate = true; PolicyRepository scp = getPolicyRepository(); PolicySettings policySettings; @@ -251,19 +254,25 @@ public void saveAttestationCertificate(final CertificateRepository certificateRe try { // save issued certificate IssuedAttestationCertificate attCert = new IssuedAttestationCertificate( - derEncodedAttestationCertificate, endorsementCredential, platformCredentials); + derEncodedAttestationCertificate, endorsementCredential, platformCredentials, isLDevID); if (scp != null) { policySettings = scp.findByName("Default"); - issuedAc = certificateRepository.findByDeviceId(device.getId()); - generateCertificate = policySettings.isIssueAttestationCertificate(); - if (issuedAc != null && policySettings.isGenerateOnExpiration()) { - if (issuedAc.getEndValidity().after(currentDate)) { + Sort sortCriteria = Sort.by(Sort.Direction.DESC, "endValidity"); + issuedAc = certificateRepository.findByDeviceIdAndIsLDevID(device.getId(), isLDevID, sortCriteria); + + generateCertificate = isLDevID ? policySettings.isIssueDevIdCertificate() + : policySettings.isIssueAttestationCertificate(); + + if (issuedAc != null && (isLDevID ? policySettings.isDevIdExpirationFlag() + : policySettings.isGenerateOnExpiration())) { + if (issuedAc.get(0).getEndValidity().after(currentDate)) { // so the issued AC is not expired // however are we within the threshold - days = ProvisionUtils.daysBetween(currentDate, issuedAc.getEndValidity()); - if (days < Integer.parseInt(policySettings.getReissueThreshold())) { + days = ProvisionUtils.daysBetween(currentDate, issuedAc.get(0).getEndValidity()); + if (days < Integer.parseInt(isLDevID ? policySettings.getDevIdReissueThreshold() + : policySettings.getReissueThreshold())) { generateCertificate = true; } else { generateCertificate = false; @@ -271,6 +280,7 @@ public void saveAttestationCertificate(final CertificateRepository certificateRe } } } + if (generateCertificate) { attCert.setDeviceId(device.getId()); attCert.setDeviceName(device.getName()); diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/CertificateRequestProcessor.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/CertificateRequestProcessor.java index 793187f97..fb9cd00e8 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/CertificateRequestProcessor.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/CertificateRequestProcessor.java @@ -5,6 +5,7 @@ import hirs.attestationca.configuration.provisionerTpm2.ProvisionerTpm2; import hirs.attestationca.persist.entity.manager.CertificateRepository; import hirs.attestationca.persist.entity.manager.DeviceRepository; +import hirs.attestationca.persist.entity.manager.PolicyRepository; import hirs.attestationca.persist.entity.manager.TPM2ProvisionerStateRepository; import hirs.attestationca.persist.entity.tpm.TPM2ProvisionerState; import hirs.attestationca.persist.entity.userdefined.Device; @@ -44,6 +45,7 @@ public class CertificateRequestProcessor extends AbstractProcessor { * @param acaCertificate object used to create credential * @param validDays int for the time in which a certificate is valid. * @param tpm2ProvisionerStateRepository db connector for provisioner state. + * @param policyRepository db connector for policies. */ public CertificateRequestProcessor(final SupplyChainValidationService supplyChainValidationService, final CertificateRepository certificateRepository, @@ -51,13 +53,15 @@ public CertificateRequestProcessor(final SupplyChainValidationService supplyChai final PrivateKey privateKey, final X509Certificate acaCertificate, final int validDays, - final TPM2ProvisionerStateRepository tpm2ProvisionerStateRepository) { + final TPM2ProvisionerStateRepository tpm2ProvisionerStateRepository, + final PolicyRepository policyRepository) { super(privateKey, validDays); this.supplyChainValidationService = supplyChainValidationService; this.certificateRepository = certificateRepository; this.deviceRepository = deviceRepository; this.acaCertificate = acaCertificate; this.tpm2ProvisionerStateRepository = tpm2ProvisionerStateRepository; + setPolicyRepository(policyRepository); } /** @@ -107,6 +111,9 @@ public byte[] processCertificateRequest(final byte[] certificateRequest) { List platformCredentials = parsePcsFromIdentityClaim(claim, endorsementCredential, certificateRepository); + // Get LDevID public key if it exists + RSAPublicKey ldevidPub = ProvisionUtils.parsePublicKey(claim.getLdevidPublicArea().toByteArray()); + // Get device name and device String deviceName = claim.getDv().getNw().getHostname(); Device device = deviceRepository.findByName(deviceName); @@ -142,22 +149,31 @@ public byte[] processCertificateRequest(final byte[] certificateRequest) { // Create signed, attestation certificate X509Certificate attestationCertificate = generateCredential(akPub, endorsementCredential, platformCredentials, deviceName, acaCertificate); + X509Certificate ldevidCertificate = generateCredential(ldevidPub, + endorsementCredential, platformCredentials, deviceName, acaCertificate); byte[] derEncodedAttestationCertificate = ProvisionUtils.getDerEncodedCertificate( attestationCertificate); + byte[] derEncodedLdevidCertificate = ProvisionUtils.getDerEncodedCertificate( + ldevidCertificate); // We validated the nonce and made use of the identity claim so state can be deleted tpm2ProvisionerStateRepository.delete(tpm2ProvisionerState); - // Package the signed certificate into a response + // Package the signed certificates into a response ByteString certificateBytes = ByteString .copyFrom(derEncodedAttestationCertificate); + ByteString ldevidCertificateBytes = ByteString + .copyFrom(derEncodedLdevidCertificate); ProvisionerTpm2.CertificateResponse response = ProvisionerTpm2.CertificateResponse .newBuilder().setCertificate(certificateBytes) + .setLdevidCertificate(ldevidCertificateBytes) .setStatus(ProvisionerTpm2.ResponseStatus.PASS) .build(); saveAttestationCertificate(certificateRepository, derEncodedAttestationCertificate, - endorsementCredential, platformCredentials, device); + endorsementCredential, platformCredentials, device, false); + saveAttestationCertificate(certificateRepository, derEncodedLdevidCertificate, + endorsementCredential, platformCredentials, device, true); return response.toByteArray(); } else { diff --git a/HIRS_AttestationCA/src/test/java/hirs/attestationca/persist/entity/userdefined/AbstractUserdefinedEntityTest.java b/HIRS_AttestationCA/src/test/java/hirs/attestationca/persist/entity/userdefined/AbstractUserdefinedEntityTest.java index 01f1c7fb3..56ff99c82 100644 --- a/HIRS_AttestationCA/src/test/java/hirs/attestationca/persist/entity/userdefined/AbstractUserdefinedEntityTest.java +++ b/HIRS_AttestationCA/src/test/java/hirs/attestationca/persist/entity/userdefined/AbstractUserdefinedEntityTest.java @@ -160,7 +160,7 @@ public static Certificate getTestCertificate( return new PlatformCredential(certPath); case "IssuedAttestationCertificate": return new IssuedAttestationCertificate(certPath, - endorsementCredential, platformCredentials); + endorsementCredential, platformCredentials, false); default: throw new IllegalArgumentException( String.format("Unknown certificate class %s", certificateClass.getName()) diff --git a/HIRS_AttestationCAPortal/src/main/webapp/WEB-INF/jsp/issued-certificates.jsp b/HIRS_AttestationCAPortal/src/main/webapp/WEB-INF/jsp/issued-certificates.jsp index 0c37bc8c4..c82a00ca3 100644 --- a/HIRS_AttestationCAPortal/src/main/webapp/WEB-INF/jsp/issued-certificates.jsp +++ b/HIRS_AttestationCAPortal/src/main/webapp/WEB-INF/jsp/issued-certificates.jsp @@ -26,6 +26,7 @@ Hostname + Type Issuer Valid (begin) Valid (end) @@ -51,6 +52,16 @@ return full.deviceName; } }, + { + data: 'isLDevID', + searchable:false, + render: function (data, type, full, meta) { + if (data === true) { + return "LDevID"; + } + return "AK"; + } + }, {data: 'issuer'}, { data: 'beginValidity', diff --git a/HIRS_AttestationCAPortal/src/main/webapp/WEB-INF/jsp/policy.jsp b/HIRS_AttestationCAPortal/src/main/webapp/WEB-INF/jsp/policy.jsp index 077638da5..64ed88e90 100644 --- a/HIRS_AttestationCAPortal/src/main/webapp/WEB-INF/jsp/policy.jsp +++ b/HIRS_AttestationCAPortal/src/main/webapp/WEB-INF/jsp/policy.jsp @@ -189,7 +189,7 @@
<%-- Generate LDevID Certificate--%> -