mirror of
https://github.com/nsacyber/HIRS.git
synced 2024-12-18 20:47:58 +00:00
Implementing LDevID generation (#814)
This commit is contained in:
parent
a62e45ee2e
commit
3de50b0441
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,4 +1,4 @@
|
|||||||
# compiled python for systems tests
|
# compiled python for systems testsG
|
||||||
*.pyc
|
*.pyc
|
||||||
*.pydevproject
|
*.pydevproject
|
||||||
|
|
||||||
@ -147,4 +147,5 @@ HIRS_Provisioner.NET/**/.vs
|
|||||||
HIRS_Provisioner.NET/**/bin
|
HIRS_Provisioner.NET/**/bin
|
||||||
HIRS_Provisioner.NET/**/generated
|
HIRS_Provisioner.NET/**/generated
|
||||||
HIRS_Provisioner.NET/**/obj
|
HIRS_Provisioner.NET/**/obj
|
||||||
|
HIRS_Provisioner.NET/**/plugins
|
||||||
HIRS_Provisioner.NET/**/PublishProfiles
|
HIRS_Provisioner.NET/**/PublishProfiles
|
||||||
|
@ -114,7 +114,7 @@ public abstract class AttestationCertificateAuthority {
|
|||||||
|
|
||||||
this.certificateRequestHandler = new CertificateRequestProcessor(supplyChainValidationService,
|
this.certificateRequestHandler = new CertificateRequestProcessor(supplyChainValidationService,
|
||||||
certificateRepository, deviceRepository,
|
certificateRepository, deviceRepository,
|
||||||
privateKey, acaCertificate, validDays, tpm2ProvisionerStateRepository);
|
privateKey, acaCertificate, validDays, tpm2ProvisionerStateRepository, policyRepository);
|
||||||
this.identityClaimHandler = new IdentityClaimProcessor(supplyChainValidationService,
|
this.identityClaimHandler = new IdentityClaimProcessor(supplyChainValidationService,
|
||||||
certificateRepository, componentResultRepository, componentInfoRepository,
|
certificateRepository, componentResultRepository, componentInfoRepository,
|
||||||
referenceManifestRepository, referenceDigestValueRepository,
|
referenceManifestRepository, referenceDigestValueRepository,
|
||||||
|
@ -4,6 +4,7 @@ import hirs.attestationca.persist.entity.userdefined.Certificate;
|
|||||||
import hirs.attestationca.persist.entity.userdefined.certificate.EndorsementCredential;
|
import hirs.attestationca.persist.entity.userdefined.certificate.EndorsementCredential;
|
||||||
import hirs.attestationca.persist.entity.userdefined.certificate.IssuedAttestationCertificate;
|
import hirs.attestationca.persist.entity.userdefined.certificate.IssuedAttestationCertificate;
|
||||||
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
|
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.JpaRepository;
|
||||||
import org.springframework.data.jpa.repository.Query;
|
import org.springframework.data.jpa.repository.Query;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
@ -35,5 +36,6 @@ public interface CertificateRepository extends JpaRepository<Certificate, UUID>
|
|||||||
Certificate findByCertificateHash(int certificateHash, String dType);
|
Certificate findByCertificateHash(int certificateHash, String dType);
|
||||||
EndorsementCredential findByPublicKeyModulusHexValue(String publicKeyModulusHexValue);
|
EndorsementCredential findByPublicKeyModulusHexValue(String publicKeyModulusHexValue);
|
||||||
IssuedAttestationCertificate findByDeviceId(UUID deviceId);
|
IssuedAttestationCertificate findByDeviceId(UUID deviceId);
|
||||||
|
List<IssuedAttestationCertificate> findByDeviceIdAndIsLDevID(UUID deviceId, boolean isLDevID, Sort sort);
|
||||||
Certificate findByCertificateHash(int certificateHash);
|
Certificate findByCertificateHash(int certificateHash);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package hirs.attestationca.persist.entity.userdefined.certificate;
|
package hirs.attestationca.persist.entity.userdefined.certificate;
|
||||||
|
|
||||||
|
import jakarta.persistence.Column;
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.FetchType;
|
import jakarta.persistence.FetchType;
|
||||||
import jakarta.persistence.JoinColumn;
|
import jakarta.persistence.JoinColumn;
|
||||||
@ -35,6 +36,9 @@ public class IssuedAttestationCertificate extends DeviceAssociatedCertificate {
|
|||||||
@JoinColumn(name = "pc_id")
|
@JoinColumn(name = "pc_id")
|
||||||
private List<PlatformCredential> platformCredentials;
|
private List<PlatformCredential> platformCredentials;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
public boolean isLDevID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
* @param certificateBytes the issued certificate bytes
|
* @param certificateBytes the issued certificate bytes
|
||||||
@ -44,11 +48,12 @@ public class IssuedAttestationCertificate extends DeviceAssociatedCertificate {
|
|||||||
*/
|
*/
|
||||||
public IssuedAttestationCertificate(final byte[] certificateBytes,
|
public IssuedAttestationCertificate(final byte[] certificateBytes,
|
||||||
final EndorsementCredential endorsementCredential,
|
final EndorsementCredential endorsementCredential,
|
||||||
final List<PlatformCredential> platformCredentials)
|
final List<PlatformCredential> platformCredentials, boolean isLDevID)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
super(certificateBytes);
|
super(certificateBytes);
|
||||||
this.endorsementCredential = endorsementCredential;
|
this.endorsementCredential = endorsementCredential;
|
||||||
this.platformCredentials = new ArrayList<>(platformCredentials);
|
this.platformCredentials = new ArrayList<>(platformCredentials);
|
||||||
|
this.isLDevID = isLDevID;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -60,9 +65,10 @@ public class IssuedAttestationCertificate extends DeviceAssociatedCertificate {
|
|||||||
*/
|
*/
|
||||||
public IssuedAttestationCertificate(final Path certificatePath,
|
public IssuedAttestationCertificate(final Path certificatePath,
|
||||||
final EndorsementCredential endorsementCredential,
|
final EndorsementCredential endorsementCredential,
|
||||||
final List<PlatformCredential> platformCredentials)
|
final List<PlatformCredential> platformCredentials,
|
||||||
|
final boolean isLDevID)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
this(readBytes(certificatePath), endorsementCredential, platformCredentials);
|
this(readBytes(certificatePath), endorsementCredential, platformCredentials, isLDevID);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<PlatformCredential> getPlatformCredentials() {
|
public List<PlatformCredential> getPlatformCredentials() {
|
||||||
|
@ -27,6 +27,7 @@ import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
|
|||||||
import org.bouncycastle.operator.ContentSigner;
|
import org.bouncycastle.operator.ContentSigner;
|
||||||
import org.bouncycastle.operator.OperatorCreationException;
|
import org.bouncycastle.operator.OperatorCreationException;
|
||||||
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
|
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
|
||||||
|
import org.springframework.data.domain.Sort;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
@ -234,15 +235,17 @@ public class AbstractProcessor {
|
|||||||
* @param endorsementCredential the endorsement credential used to generate the AC
|
* @param endorsementCredential the endorsement credential used to generate the AC
|
||||||
* @param platformCredentials the platform credentials 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 device the device to which the attestation certificate is tied
|
||||||
|
* @param isLDevID whether the certificate is a ldevid
|
||||||
|
* @return whether the certificate was saved successfully
|
||||||
* @throws {@link CertificateProcessingException} if error occurs in persisting the Attestation
|
* @throws {@link CertificateProcessingException} if error occurs in persisting the Attestation
|
||||||
* Certificate
|
* Certificate
|
||||||
*/
|
*/
|
||||||
public void saveAttestationCertificate(final CertificateRepository certificateRepository,
|
public boolean saveAttestationCertificate(final CertificateRepository certificateRepository,
|
||||||
final byte[] derEncodedAttestationCertificate,
|
final byte[] derEncodedAttestationCertificate,
|
||||||
final EndorsementCredential endorsementCredential,
|
final EndorsementCredential endorsementCredential,
|
||||||
final List<PlatformCredential> platformCredentials,
|
final List<PlatformCredential> platformCredentials,
|
||||||
final Device device) {
|
final Device device, boolean isLDevID) {
|
||||||
IssuedAttestationCertificate issuedAc;
|
List<IssuedAttestationCertificate> issuedAc;
|
||||||
boolean generateCertificate = true;
|
boolean generateCertificate = true;
|
||||||
PolicyRepository scp = getPolicyRepository();
|
PolicyRepository scp = getPolicyRepository();
|
||||||
PolicySettings policySettings;
|
PolicySettings policySettings;
|
||||||
@ -251,19 +254,25 @@ public class AbstractProcessor {
|
|||||||
try {
|
try {
|
||||||
// save issued certificate
|
// save issued certificate
|
||||||
IssuedAttestationCertificate attCert = new IssuedAttestationCertificate(
|
IssuedAttestationCertificate attCert = new IssuedAttestationCertificate(
|
||||||
derEncodedAttestationCertificate, endorsementCredential, platformCredentials);
|
derEncodedAttestationCertificate, endorsementCredential, platformCredentials, isLDevID);
|
||||||
|
|
||||||
if (scp != null) {
|
if (scp != null) {
|
||||||
policySettings = scp.findByName("Default");
|
policySettings = scp.findByName("Default");
|
||||||
issuedAc = certificateRepository.findByDeviceId(device.getId());
|
|
||||||
|
|
||||||
generateCertificate = policySettings.isIssueAttestationCertificate();
|
Sort sortCriteria = Sort.by(Sort.Direction.DESC, "endValidity");
|
||||||
if (issuedAc != null && policySettings.isGenerateOnExpiration()) {
|
issuedAc = certificateRepository.findByDeviceIdAndIsLDevID(device.getId(), isLDevID, sortCriteria);
|
||||||
if (issuedAc.getEndValidity().after(currentDate)) {
|
|
||||||
|
generateCertificate = isLDevID ? policySettings.isIssueDevIdCertificate()
|
||||||
|
: policySettings.isIssueAttestationCertificate();
|
||||||
|
|
||||||
|
if (issuedAc != null && issuedAc.size() > 0 && (isLDevID ? policySettings.isDevIdExpirationFlag()
|
||||||
|
: policySettings.isGenerateOnExpiration())) {
|
||||||
|
if (issuedAc.get(0).getEndValidity().after(currentDate)) {
|
||||||
// so the issued AC is not expired
|
// so the issued AC is not expired
|
||||||
// however are we within the threshold
|
// however are we within the threshold
|
||||||
days = ProvisionUtils.daysBetween(currentDate, issuedAc.getEndValidity());
|
days = ProvisionUtils.daysBetween(currentDate, issuedAc.get(0).getEndValidity());
|
||||||
if (days < Integer.parseInt(policySettings.getReissueThreshold())) {
|
if (days < Integer.parseInt(isLDevID ? policySettings.getDevIdReissueThreshold()
|
||||||
|
: policySettings.getReissueThreshold())) {
|
||||||
generateCertificate = true;
|
generateCertificate = true;
|
||||||
} else {
|
} else {
|
||||||
generateCertificate = false;
|
generateCertificate = false;
|
||||||
@ -271,6 +280,7 @@ public class AbstractProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (generateCertificate) {
|
if (generateCertificate) {
|
||||||
attCert.setDeviceId(device.getId());
|
attCert.setDeviceId(device.getId());
|
||||||
attCert.setDeviceName(device.getName());
|
attCert.setDeviceName(device.getName());
|
||||||
@ -282,6 +292,8 @@ public class AbstractProcessor {
|
|||||||
"Encountered error while storing Attestation Certificate: "
|
"Encountered error while storing Attestation Certificate: "
|
||||||
+ e.getMessage(), e);
|
+ e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return generateCertificate;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<PlatformCredential> getPlatformCredentials(final CertificateRepository certificateRepository,
|
private List<PlatformCredential> getPlatformCredentials(final CertificateRepository certificateRepository,
|
||||||
|
@ -5,6 +5,7 @@ import com.google.protobuf.InvalidProtocolBufferException;
|
|||||||
import hirs.attestationca.configuration.provisionerTpm2.ProvisionerTpm2;
|
import hirs.attestationca.configuration.provisionerTpm2.ProvisionerTpm2;
|
||||||
import hirs.attestationca.persist.entity.manager.CertificateRepository;
|
import hirs.attestationca.persist.entity.manager.CertificateRepository;
|
||||||
import hirs.attestationca.persist.entity.manager.DeviceRepository;
|
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.manager.TPM2ProvisionerStateRepository;
|
||||||
import hirs.attestationca.persist.entity.tpm.TPM2ProvisionerState;
|
import hirs.attestationca.persist.entity.tpm.TPM2ProvisionerState;
|
||||||
import hirs.attestationca.persist.entity.userdefined.Device;
|
import hirs.attestationca.persist.entity.userdefined.Device;
|
||||||
@ -44,6 +45,7 @@ public class CertificateRequestProcessor extends AbstractProcessor {
|
|||||||
* @param acaCertificate object used to create credential
|
* @param acaCertificate object used to create credential
|
||||||
* @param validDays int for the time in which a certificate is valid.
|
* @param validDays int for the time in which a certificate is valid.
|
||||||
* @param tpm2ProvisionerStateRepository db connector for provisioner state.
|
* @param tpm2ProvisionerStateRepository db connector for provisioner state.
|
||||||
|
* @param policyRepository db connector for policies.
|
||||||
*/
|
*/
|
||||||
public CertificateRequestProcessor(final SupplyChainValidationService supplyChainValidationService,
|
public CertificateRequestProcessor(final SupplyChainValidationService supplyChainValidationService,
|
||||||
final CertificateRepository certificateRepository,
|
final CertificateRepository certificateRepository,
|
||||||
@ -51,13 +53,15 @@ public class CertificateRequestProcessor extends AbstractProcessor {
|
|||||||
final PrivateKey privateKey,
|
final PrivateKey privateKey,
|
||||||
final X509Certificate acaCertificate,
|
final X509Certificate acaCertificate,
|
||||||
final int validDays,
|
final int validDays,
|
||||||
final TPM2ProvisionerStateRepository tpm2ProvisionerStateRepository) {
|
final TPM2ProvisionerStateRepository tpm2ProvisionerStateRepository,
|
||||||
|
final PolicyRepository policyRepository) {
|
||||||
super(privateKey, validDays);
|
super(privateKey, validDays);
|
||||||
this.supplyChainValidationService = supplyChainValidationService;
|
this.supplyChainValidationService = supplyChainValidationService;
|
||||||
this.certificateRepository = certificateRepository;
|
this.certificateRepository = certificateRepository;
|
||||||
this.deviceRepository = deviceRepository;
|
this.deviceRepository = deviceRepository;
|
||||||
this.acaCertificate = acaCertificate;
|
this.acaCertificate = acaCertificate;
|
||||||
this.tpm2ProvisionerStateRepository = tpm2ProvisionerStateRepository;
|
this.tpm2ProvisionerStateRepository = tpm2ProvisionerStateRepository;
|
||||||
|
setPolicyRepository(policyRepository);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -107,6 +111,12 @@ public class CertificateRequestProcessor extends AbstractProcessor {
|
|||||||
List<PlatformCredential> platformCredentials = parsePcsFromIdentityClaim(claim,
|
List<PlatformCredential> platformCredentials = parsePcsFromIdentityClaim(claim,
|
||||||
endorsementCredential, certificateRepository);
|
endorsementCredential, certificateRepository);
|
||||||
|
|
||||||
|
// Get LDevID public key if it exists
|
||||||
|
RSAPublicKey ldevidPub = null;
|
||||||
|
if (claim.hasLdevidPublicArea()) {
|
||||||
|
ldevidPub = ProvisionUtils.parsePublicKey(claim.getLdevidPublicArea().toByteArray());
|
||||||
|
}
|
||||||
|
|
||||||
// Get device name and device
|
// Get device name and device
|
||||||
String deviceName = claim.getDv().getNw().getHostname();
|
String deviceName = claim.getDv().getNw().getHostname();
|
||||||
Device device = deviceRepository.findByName(deviceName);
|
Device device = deviceRepository.findByName(deviceName);
|
||||||
@ -142,24 +152,63 @@ public class CertificateRequestProcessor extends AbstractProcessor {
|
|||||||
// Create signed, attestation certificate
|
// Create signed, attestation certificate
|
||||||
X509Certificate attestationCertificate = generateCredential(akPub,
|
X509Certificate attestationCertificate = generateCredential(akPub,
|
||||||
endorsementCredential, platformCredentials, deviceName, acaCertificate);
|
endorsementCredential, platformCredentials, deviceName, acaCertificate);
|
||||||
byte[] derEncodedAttestationCertificate = ProvisionUtils.getDerEncodedCertificate(
|
if (ldevidPub != null) {
|
||||||
attestationCertificate);
|
// Create signed LDevID certificate
|
||||||
|
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
|
// We validated the nonce and made use of the identity claim so state can be deleted
|
||||||
tpm2ProvisionerStateRepository.delete(tpm2ProvisionerState);
|
tpm2ProvisionerStateRepository.delete(tpm2ProvisionerState);
|
||||||
|
|
||||||
// Package the signed certificate into a response
|
// Package the signed certificates into a response
|
||||||
ByteString certificateBytes = ByteString
|
ByteString certificateBytes = ByteString
|
||||||
.copyFrom(derEncodedAttestationCertificate);
|
.copyFrom(derEncodedAttestationCertificate);
|
||||||
ProvisionerTpm2.CertificateResponse response = ProvisionerTpm2.CertificateResponse
|
ByteString ldevidCertificateBytes = ByteString
|
||||||
.newBuilder().setCertificate(certificateBytes)
|
.copyFrom(derEncodedLdevidCertificate);
|
||||||
.setStatus(ProvisionerTpm2.ResponseStatus.PASS)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
saveAttestationCertificate(certificateRepository, derEncodedAttestationCertificate,
|
boolean generateAtt = saveAttestationCertificate(certificateRepository, derEncodedAttestationCertificate,
|
||||||
endorsementCredential, platformCredentials, device);
|
endorsementCredential, platformCredentials, device, false);
|
||||||
|
boolean generateLDevID = saveAttestationCertificate(certificateRepository, derEncodedLdevidCertificate,
|
||||||
|
endorsementCredential, platformCredentials, device, true);
|
||||||
|
|
||||||
return response.toByteArray();
|
ProvisionerTpm2.CertificateResponse.Builder builder = ProvisionerTpm2.CertificateResponse.
|
||||||
|
newBuilder().setStatus(ProvisionerTpm2.ResponseStatus.PASS);
|
||||||
|
if (generateAtt) {
|
||||||
|
builder = builder.setCertificate(certificateBytes);
|
||||||
|
}
|
||||||
|
if (generateLDevID) {
|
||||||
|
builder = builder.setLdevidCertificate(ldevidCertificateBytes);
|
||||||
|
}
|
||||||
|
ProvisionerTpm2.CertificateResponse response = builder.build();
|
||||||
|
|
||||||
|
return response.toByteArray();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
byte[] derEncodedAttestationCertificate = ProvisionUtils.getDerEncodedCertificate(
|
||||||
|
attestationCertificate);
|
||||||
|
|
||||||
|
// We validated the nonce and made use of the identity claim so state can be deleted
|
||||||
|
tpm2ProvisionerStateRepository.delete(tpm2ProvisionerState);
|
||||||
|
|
||||||
|
// Package the signed certificates into a response
|
||||||
|
ByteString certificateBytes = ByteString
|
||||||
|
.copyFrom(derEncodedAttestationCertificate);
|
||||||
|
ProvisionerTpm2.CertificateResponse.Builder builder = ProvisionerTpm2.CertificateResponse.
|
||||||
|
newBuilder().setStatus(ProvisionerTpm2.ResponseStatus.PASS);
|
||||||
|
|
||||||
|
boolean generateAtt = saveAttestationCertificate(certificateRepository, derEncodedAttestationCertificate,
|
||||||
|
endorsementCredential, platformCredentials, device, false);
|
||||||
|
if (generateAtt) {
|
||||||
|
builder = builder.setCertificate(certificateBytes);
|
||||||
|
}
|
||||||
|
ProvisionerTpm2.CertificateResponse response = builder.build();
|
||||||
|
|
||||||
|
return response.toByteArray();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
log.error("Supply chain validation did not succeed. "
|
log.error("Supply chain validation did not succeed. "
|
||||||
+ "Firmware Quote Validation failed. Result is: "
|
+ "Firmware Quote Validation failed. Result is: "
|
||||||
|
@ -160,7 +160,7 @@ public class AbstractUserdefinedEntityTest {
|
|||||||
return new PlatformCredential(certPath);
|
return new PlatformCredential(certPath);
|
||||||
case "IssuedAttestationCertificate":
|
case "IssuedAttestationCertificate":
|
||||||
return new IssuedAttestationCertificate(certPath,
|
return new IssuedAttestationCertificate(certPath,
|
||||||
endorsementCredential, platformCredentials);
|
endorsementCredential, platformCredentials, false);
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
String.format("Unknown certificate class %s", certificateClass.getName())
|
String.format("Unknown certificate class %s", certificateClass.getName())
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th rowspan="2">Hostname</th>
|
<th rowspan="2">Hostname</th>
|
||||||
|
<th rowspan="2">Type</th>
|
||||||
<th rowspan="2">Issuer</th>
|
<th rowspan="2">Issuer</th>
|
||||||
<th rowspan="2">Valid (begin)</th>
|
<th rowspan="2">Valid (begin)</th>
|
||||||
<th rowspan="2">Valid (end)</th>
|
<th rowspan="2">Valid (end)</th>
|
||||||
@ -51,6 +52,16 @@
|
|||||||
return full.deviceName;
|
return full.deviceName;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
data: 'isLDevID',
|
||||||
|
searchable:false,
|
||||||
|
render: function (data, type, full, meta) {
|
||||||
|
if (data === true) {
|
||||||
|
return "LDevID";
|
||||||
|
}
|
||||||
|
return "AK";
|
||||||
|
}
|
||||||
|
},
|
||||||
{data: 'issuer'},
|
{data: 'issuer'},
|
||||||
{
|
{
|
||||||
data: 'beginValidity',
|
data: 'beginValidity',
|
||||||
|
@ -189,7 +189,7 @@
|
|||||||
<br />
|
<br />
|
||||||
|
|
||||||
<%-- Generate LDevID Certificate--%>
|
<%-- Generate LDevID Certificate--%>
|
||||||
<div class="aca-input-box" style="display: none">
|
<div class="aca-input-box">
|
||||||
<form:form method="POST" modelAttribute="initialData" action="policy/update-issue-devid">
|
<form:form method="POST" modelAttribute="initialData" action="policy/update-issue-devid">
|
||||||
<li>Generate LDevID Certificate: ${initialData.issueDevIdCertificate ? 'Enabled' : 'Disabled'}
|
<li>Generate LDevID Certificate: ${initialData.issueDevIdCertificate ? 'Enabled' : 'Disabled'}
|
||||||
<my:editor id="issuedDevIdCertificatePolicyEditor" label="Edit Settings">
|
<my:editor id="issuedDevIdCertificatePolicyEditor" label="Edit Settings">
|
||||||
|
@ -215,4 +215,4 @@ function formatCertificateDate(dateText) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return new Date(date).toUTCString();
|
return new Date(date).toUTCString();
|
||||||
}
|
}
|
@ -169,7 +169,7 @@ public abstract class PageControllerTest {
|
|||||||
return new CertificateAuthorityCredential(fPath);
|
return new CertificateAuthorityCredential(fPath);
|
||||||
case "IssuedAttestationCertificate":
|
case "IssuedAttestationCertificate":
|
||||||
return new IssuedAttestationCertificate(fPath,
|
return new IssuedAttestationCertificate(fPath,
|
||||||
endorsementCredential, platformCredentials);
|
endorsementCredential, platformCredentials, false);
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
String.format("Unknown certificate class %s", certificateClass.getName())
|
String.format("Unknown certificate class %s", certificateClass.getName())
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
<Target Name="SetWixPath" BeforeTargets="Msi">
|
<Target Name="SetWixPath" BeforeTargets="Msi">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<ProductSourceFilePath>$(MSBuildThisFileDirectory)\Resources\Product.wxs</ProductSourceFilePath>
|
<ProductSourceFilePath>$(MSBuildThisFileDirectory)\Resources\Product.wxs</ProductSourceFilePath>
|
||||||
<WixInstallPath>$(NuGetPackageRoot)wix\3.14.0\tools\</WixInstallPath>
|
<WixInstallPath>$(NuGetPackageRoot)wix\3.14.1\tools\</WixInstallPath>
|
||||||
<Heat>$(WixInstallPath)heat.exe</Heat>
|
<Heat>$(WixInstallPath)heat.exe</Heat>
|
||||||
<Candle>$(WixInstallPath)candle.exe</Candle>
|
<Candle>$(WixInstallPath)candle.exe</Candle>
|
||||||
<Light>$(WixInstallPath)light.exe</Light>
|
<Light>$(WixInstallPath)light.exe</Light>
|
||||||
|
@ -70,7 +70,8 @@ message IdentityClaim {
|
|||||||
optional bytes endorsement_credential = 4;
|
optional bytes endorsement_credential = 4;
|
||||||
repeated bytes platform_credential = 5;
|
repeated bytes platform_credential = 5;
|
||||||
optional string client_version = 6;
|
optional string client_version = 6;
|
||||||
optional string paccorOutput = 7;
|
optional string paccorOutput = 7;
|
||||||
|
optional bytes ldevid_public_area = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
message TpmQuote {
|
message TpmQuote {
|
||||||
@ -96,5 +97,6 @@ message CertificateRequest {
|
|||||||
message CertificateResponse {
|
message CertificateResponse {
|
||||||
optional bytes certificate = 1;
|
optional bytes certificate = 1;
|
||||||
optional ResponseStatus status = 2 [default = FAIL];
|
optional ResponseStatus status = 2 [default = FAIL];
|
||||||
|
optional bytes ldevidCertificate = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
"auto_detect_tpm": "TRUE",
|
"auto_detect_tpm": "TRUE",
|
||||||
"aca_address_port": "https://127.0.0.1:8443",
|
"aca_address_port": "https://127.0.0.1:8443",
|
||||||
"efi_prefix": "",
|
"efi_prefix": "",
|
||||||
|
"certificate_output_directory": "",
|
||||||
"paccor_output_file": "",
|
"paccor_output_file": "",
|
||||||
"event_log_file": "",
|
"event_log_file": "",
|
||||||
"hardware_manifest_collectors": "paccor_scripts",
|
"hardware_manifest_collectors": "paccor_scripts",
|
||||||
|
@ -69,7 +69,7 @@ namespace hirs {
|
|||||||
|
|
||||||
public IdentityClaim CreateIdentityClaim(DeviceInfo dv, byte[] akPublicArea, byte[] ekPublicArea,
|
public IdentityClaim CreateIdentityClaim(DeviceInfo dv, byte[] akPublicArea, byte[] ekPublicArea,
|
||||||
byte[] endorsementCredential, List<byte[]> platformCredentials,
|
byte[] endorsementCredential, List<byte[]> platformCredentials,
|
||||||
string paccoroutput) {
|
string paccoroutput, byte[] ldevidPublicArea = null) {
|
||||||
IdentityClaim identityClaim = new();
|
IdentityClaim identityClaim = new();
|
||||||
identityClaim.Dv = dv;
|
identityClaim.Dv = dv;
|
||||||
identityClaim.AkPublicArea = ByteString.CopyFrom(akPublicArea);
|
identityClaim.AkPublicArea = ByteString.CopyFrom(akPublicArea);
|
||||||
@ -81,6 +81,7 @@ namespace hirs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
identityClaim.PaccorOutput = paccoroutput;
|
identityClaim.PaccorOutput = paccoroutput;
|
||||||
|
if (ldevidPublicArea != null) identityClaim.LdevidPublicArea = ByteString.CopyFrom(ldevidPublicArea);
|
||||||
|
|
||||||
return identityClaim;
|
return identityClaim;
|
||||||
}
|
}
|
||||||
|
@ -36,10 +36,12 @@ namespace hirs {
|
|||||||
/// <param name="platformCredentials">Any platform certificates relevant to the Device,
|
/// <param name="platformCredentials">Any platform certificates relevant to the Device,
|
||||||
/// encoded in DER or PEM.</param>
|
/// encoded in DER or PEM.</param>
|
||||||
/// <param name="paccoroutput">Platform Manifest in a JSON format.</param>
|
/// <param name="paccoroutput">Platform Manifest in a JSON format.</param>
|
||||||
|
/// <param name="ldevidPublicArea">The public LDevID retrieved as a TPM2B_PUBLIC.</param>
|
||||||
/// <returns>An <see cref="IdentityClaim"/> object that can be sent to the ACA.</returns>
|
/// <returns>An <see cref="IdentityClaim"/> object that can be sent to the ACA.</returns>
|
||||||
IdentityClaim CreateIdentityClaim(DeviceInfo dv, byte[] akPublicArea, byte[] ekPublicArea,
|
IdentityClaim CreateIdentityClaim(DeviceInfo dv, byte[] akPublicArea, byte[] ekPublicArea,
|
||||||
byte[] endorsementCredential,
|
byte[] endorsementCredential,
|
||||||
List<byte[]> platformCredentials, string paccoroutput);
|
List<byte[]> platformCredentials, string paccoroutput,
|
||||||
|
byte[] ldevidPublicArea);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Collect answers to verification requirements regarding a Device into an object that
|
/// Collect answers to verification requirements regarding a Device into an object that
|
||||||
/// can be interpreted by the ACA.
|
/// can be interpreted by the ACA.
|
||||||
|
@ -32,6 +32,11 @@ namespace hirs {
|
|||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Option("replaceLDevID", Default = false, HelpText = "Clear any existing hirs LDevID and create a new one.")]
|
||||||
|
public bool ReplaceLDevID {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
public static string[] SplitArgs(string argString) {
|
public static string[] SplitArgs(string argString) {
|
||||||
return argString.SplitArgs(true);
|
return argString.SplitArgs(true);
|
||||||
}
|
}
|
||||||
|
@ -24,13 +24,15 @@ namespace hirs {
|
|||||||
linux_sys_vendor_file,
|
linux_sys_vendor_file,
|
||||||
linux_product_name_file,
|
linux_product_name_file,
|
||||||
linux_product_version_file,
|
linux_product_version_file,
|
||||||
linux_product_serial_file
|
linux_product_serial_file,
|
||||||
|
certificate_output_directory
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly string DEFAULT_SETTINGS_FILE = "appsettings.json";
|
private static readonly string DEFAULT_SETTINGS_FILE = "appsettings.json";
|
||||||
private static readonly string EFI_ARTIFACT_PATH_COMPAT = "/boot/tcg/";
|
private static readonly string EFI_ARTIFACT_PATH_COMPAT = "/boot/tcg/";
|
||||||
private static readonly string EFI_ARTIFACT_PATH = "/EFI/tcg/";
|
private static readonly string EFI_ARTIFACT_PATH = "/EFI/tcg/";
|
||||||
private static readonly string EFI_ARTIFACT_LINUX_PREFIX = "/boot/efi";
|
private static readonly string EFI_ARTIFACT_LINUX_PREFIX = "/boot/efi";
|
||||||
|
private static readonly string DEFAULT_CERTIFICATE_OUTPUT_PATH = "/EFI/hirs";
|
||||||
|
|
||||||
private readonly string settingsFile;
|
private readonly string settingsFile;
|
||||||
private readonly IConfiguration configFromSettingsFile;
|
private readonly IConfiguration configFromSettingsFile;
|
||||||
@ -72,6 +74,9 @@ namespace hirs {
|
|||||||
public virtual string linux_product_serial {
|
public virtual string linux_product_serial {
|
||||||
get; private set;
|
get; private set;
|
||||||
}
|
}
|
||||||
|
public virtual string certificate_output_directory {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
private List<IHardwareManifest> hardwareManifests = new();
|
private List<IHardwareManifest> hardwareManifests = new();
|
||||||
private Dictionary<string, string> hardware_manifest_collectors_with_args = new();
|
private Dictionary<string, string> hardware_manifest_collectors_with_args = new();
|
||||||
private bool hardware_manifest_collection_swid_enforced = false;
|
private bool hardware_manifest_collection_swid_enforced = false;
|
||||||
@ -126,6 +131,8 @@ namespace hirs {
|
|||||||
|
|
||||||
CheckEfiPrefix();
|
CheckEfiPrefix();
|
||||||
|
|
||||||
|
CheckCertificateOutputDirectory();
|
||||||
|
|
||||||
IngestEventLogFromFile();
|
IngestEventLogFromFile();
|
||||||
|
|
||||||
StoreCustomDeviceInfoCollectorOptions();
|
StoreCustomDeviceInfoCollectorOptions();
|
||||||
@ -268,6 +275,55 @@ namespace hirs {
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region
|
||||||
|
private void CheckCertificateOutputDirectory() {
|
||||||
|
if (!string.IsNullOrWhiteSpace(configFromSettingsFile[Options.certificate_output_directory.ToString()])) {
|
||||||
|
Log.Debug("Checking Certificate Output Directory setting.");
|
||||||
|
certificate_output_directory = $"{ configFromSettingsFile[Options.certificate_output_directory.ToString()] }";
|
||||||
|
if (!string.IsNullOrWhiteSpace(certificate_output_directory)) {
|
||||||
|
// Attempt to write to Certificate Output Directory
|
||||||
|
if (!Directory.Exists(certificate_output_directory)) {
|
||||||
|
try {
|
||||||
|
Directory.CreateDirectory(certificate_output_directory);
|
||||||
|
Log.Debug(" Created directory: " + certificate_output_directory);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
Log.Debug(" Could not create directory: " + certificate_output_directory);
|
||||||
|
certificate_output_directory = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (certificate_output_directory == null) {
|
||||||
|
if (HasEfiPrefix()) {
|
||||||
|
certificate_output_directory = Path.GetFullPath(Path.Join(efi_prefix, DEFAULT_CERTIFICATE_OUTPUT_PATH));
|
||||||
|
Log.Debug(" Certificate Output Directory not set. Attempting to use EFI Prefix setting.");
|
||||||
|
// Attempt to write to default EFI path (fallback)
|
||||||
|
if (!Directory.Exists(certificate_output_directory)) {
|
||||||
|
try {
|
||||||
|
Directory.CreateDirectory(certificate_output_directory);
|
||||||
|
Log.Debug(" Created directory: " + certificate_output_directory);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
Log.Debug(" Could not create directory: " + certificate_output_directory);
|
||||||
|
certificate_output_directory = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (certificate_output_directory == null) {
|
||||||
|
// Use current working directory (fallback)
|
||||||
|
Log.Warning(Options.certificate_output_directory.ToString() + " not set in the settings file. Defaulting to current working directory.");
|
||||||
|
certificate_output_directory = "";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Log.Debug(" Will write certificates to " + certificate_output_directory);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.Debug(" Will write certificates to " + certificate_output_directory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region EFI
|
#region EFI
|
||||||
private void CheckEfiPrefix() {
|
private void CheckEfiPrefix() {
|
||||||
if (!string.IsNullOrWhiteSpace(configFromSettingsFile[Options.efi_prefix.ToString()])) {
|
if (!string.IsNullOrWhiteSpace(configFromSettingsFile[Options.efi_prefix.ToString()])) {
|
||||||
|
@ -5,6 +5,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace hirs {
|
namespace hirs {
|
||||||
@ -15,8 +16,11 @@ namespace hirs {
|
|||||||
private IHirsDeviceInfoCollector deviceInfoCollector = null;
|
private IHirsDeviceInfoCollector deviceInfoCollector = null;
|
||||||
private IHirsAcaClient acaClient = null;
|
private IHirsAcaClient acaClient = null;
|
||||||
|
|
||||||
private const string DefaultCertFileName = "attestationkey.pem";
|
private const string DefaultLDevIDPubKeyFileName = "ldevid.pub";
|
||||||
|
private const string DefaultLDevIDPrivKeyFileName = "ldevid.priv";
|
||||||
|
|
||||||
|
private const string DefaultAKCertFileName = "ak.pem";
|
||||||
|
private const string DefaultLDevIDCertFileName = "ldevid.pem";
|
||||||
|
|
||||||
public Provisioner() {
|
public Provisioner() {
|
||||||
}
|
}
|
||||||
@ -122,6 +126,20 @@ namespace hirs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string FormatCertificatePath(DeviceInfo dv, string certificateDirPath, string certificateFileName) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
if (dv?.Hw != null) {
|
||||||
|
if (dv.Hw.HasSystemSerialNumber && !dv.Hw.SystemSerialNumber.Equals(ClassicDeviceInfoCollector.NOT_SPECIFIED)) {
|
||||||
|
sb.AppendFormat("{0}-", dv.Hw.SystemSerialNumber);
|
||||||
|
}
|
||||||
|
if (dv.Hw.HasManufacturer && !dv.Hw.Manufacturer.Equals(ClassicDeviceInfoCollector.NOT_SPECIFIED)) {
|
||||||
|
sb.AppendFormat("{0}-", dv.Hw.Manufacturer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb.Append(certificateFileName);
|
||||||
|
return Path.GetFullPath(Path.Join(certificateDirPath, sb.ToString()));
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<int> Provision(IHirsAcaTpm tpm) {
|
public async Task<int> Provision(IHirsAcaTpm tpm) {
|
||||||
ClientExitCodes result = ClientExitCodes.SUCCESS;
|
ClientExitCodes result = ClientExitCodes.SUCCESS;
|
||||||
if (tpm != null) {
|
if (tpm != null) {
|
||||||
@ -140,6 +158,10 @@ namespace hirs {
|
|||||||
|
|
||||||
Log.Debug("Gathering AK PUBLIC.");
|
Log.Debug("Gathering AK PUBLIC.");
|
||||||
byte[] akPublicArea = tpm.ReadPublicArea(CommandTpm.DefaultAkHandle, out name, out qualifiedName);
|
byte[] akPublicArea = tpm.ReadPublicArea(CommandTpm.DefaultAkHandle, out name, out qualifiedName);
|
||||||
|
|
||||||
|
Log.Debug("Checking SRK PUBLIC");
|
||||||
|
tpm.CreateStorageRootKey(CommandTpm.DefaultSrkHandle); // Will not create key if obj already exists at handle
|
||||||
|
byte[] srkPublicArea = tpm.ReadPublicArea(CommandTpm.DefaultSrkHandle, out byte[] name2, out byte[] qualifiedName2);
|
||||||
|
|
||||||
List<byte[]> pcs = null, baseRims = null, supportRimELs = null, supportRimPCRs = null;
|
List<byte[]> pcs = null, baseRims = null, supportRimELs = null, supportRimPCRs = null;
|
||||||
if (settings.HasEfiPrefix()) {
|
if (settings.HasEfiPrefix()) {
|
||||||
@ -209,8 +231,16 @@ namespace hirs {
|
|||||||
Log.Debug("\n" + pcrsList);
|
Log.Debug("\n" + pcrsList);
|
||||||
dv.Pcrslist = ByteString.CopyFromUtf8(pcrsList);
|
dv.Pcrslist = ByteString.CopyFromUtf8(pcrsList);
|
||||||
|
|
||||||
|
Log.Information("----> " + (cli.ReplaceLDevID ? "Creating new" : "Verifying existence of") + " LDevID Key.");
|
||||||
|
string ldevidPubPath = FormatCertificatePath(dv, settings.certificate_output_directory, DefaultLDevIDPubKeyFileName);
|
||||||
|
string ldevidPrivPath = FormatCertificatePath(dv, settings.certificate_output_directory, DefaultLDevIDPrivKeyFileName);
|
||||||
|
tpm.CreateLDevIDKey(CommandTpm.DefaultSrkHandle, ldevidPubPath, ldevidPrivPath, cli.ReplaceLDevID);
|
||||||
|
|
||||||
|
Log.Debug("Gathering LDevID PUBLIC.");
|
||||||
|
byte[] ldevidPublicArea = tpm.ConvertLDevIDPublic(ldevidPubPath);
|
||||||
|
|
||||||
Log.Debug("Create identity claim");
|
Log.Debug("Create identity claim");
|
||||||
IdentityClaim idClaim = acaClient.CreateIdentityClaim(dv, akPublicArea, ekPublicArea, ekc, pcs, manifest);
|
IdentityClaim idClaim = acaClient.CreateIdentityClaim(dv, akPublicArea, ekPublicArea, ekc, pcs, manifest, ldevidPublicArea);
|
||||||
|
|
||||||
Log.Information("----> Sending identity claim to Attestation CA");
|
Log.Information("----> Sending identity claim to Attestation CA");
|
||||||
IdentityClaimResponse icr = await acaClient.PostIdentityClaim(idClaim);
|
IdentityClaimResponse icr = await acaClient.PostIdentityClaim(idClaim);
|
||||||
@ -271,7 +301,7 @@ namespace hirs {
|
|||||||
Log.Debug("Communicate certificate request to the ACA.");
|
Log.Debug("Communicate certificate request to the ACA.");
|
||||||
CertificateResponse cr = await acaClient.PostCertificateRequest(akCertReq);
|
CertificateResponse cr = await acaClient.PostCertificateRequest(akCertReq);
|
||||||
Log.Debug("Response received from the ACA regarding the certificate request.");
|
Log.Debug("Response received from the ACA regarding the certificate request.");
|
||||||
if (cr.HasStatus) {
|
if (cr.HasStatus) {
|
||||||
if (cr.Status == ResponseStatus.Pass) {
|
if (cr.Status == ResponseStatus.Pass) {
|
||||||
Log.Debug("ACA returned a positive response to the Certificate Request.");
|
Log.Debug("ACA returned a positive response to the Certificate Request.");
|
||||||
} else {
|
} else {
|
||||||
@ -282,22 +312,34 @@ namespace hirs {
|
|||||||
}
|
}
|
||||||
if (cr.HasCertificate) {
|
if (cr.HasCertificate) {
|
||||||
certificate = cr.Certificate.ToByteArray(); // contains certificate
|
certificate = cr.Certificate.ToByteArray(); // contains certificate
|
||||||
String certificateDirPath = settings.efi_prefix;
|
String certificateDirPath = settings.certificate_output_directory;
|
||||||
if (certificateDirPath != null) {
|
if (certificateDirPath != null) {
|
||||||
String certificateFilePath = certificateFilePath = certificateDirPath + DefaultCertFileName;
|
String certificateFilePath = FormatCertificatePath(dv, certificateDirPath, DefaultAKCertFileName);
|
||||||
try {
|
try {
|
||||||
if (!Directory.Exists(certificateDirPath)) {
|
|
||||||
Directory.CreateDirectory(certificateDirPath);
|
|
||||||
}
|
|
||||||
File.WriteAllBytes(certificateFilePath, certificate);
|
File.WriteAllBytes(certificateFilePath, certificate);
|
||||||
Log.Debug("Certificate written to local file system: ", certificateFilePath);
|
Log.Debug("Attestation key certificate written to local file system: {0}", certificateFilePath);
|
||||||
}
|
}
|
||||||
catch (Exception) {
|
catch (Exception) {
|
||||||
Log.Debug("Failed to write certificate to local file system.");
|
Log.Debug("Failed to write attestation key certificate to local file system.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Log.Debug("Printing attestation key certificate: " + BitConverter.ToString(certificate));
|
Log.Debug("Printing attestation key certificate: " + BitConverter.ToString(certificate));
|
||||||
}
|
}
|
||||||
|
if (cr.HasLdevidCertificate) {
|
||||||
|
certificate = cr.LdevidCertificate.ToByteArray(); // contains certificate
|
||||||
|
String certificateDirPath = settings.certificate_output_directory;
|
||||||
|
if (certificateDirPath != null) {
|
||||||
|
String certificateFilePath = FormatCertificatePath(dv, certificateDirPath, DefaultLDevIDCertFileName);
|
||||||
|
try {
|
||||||
|
File.WriteAllBytes(certificateFilePath, certificate);
|
||||||
|
Log.Debug("LDevID certificate written to local file system: {0}", certificateFilePath);
|
||||||
|
}
|
||||||
|
catch (Exception) {
|
||||||
|
Log.Debug("Failed to write LDevID certificate to local file system.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Log.Debug("Printing LDevID certificate: " + BitConverter.ToString(certificate));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
result = ClientExitCodes.MAKE_CREDENTIAL_BLOB_MALFORMED;
|
result = ClientExitCodes.MAKE_CREDENTIAL_BLOB_MALFORMED;
|
||||||
Log.Error("Credential elements could not be extracted from the ACA's response.");
|
Log.Error("Credential elements could not be extracted from the ACA's response.");
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using Serilog;
|
using Newtonsoft.Json.Converters;
|
||||||
|
using Serilog;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
@ -25,6 +26,7 @@ namespace hirs {
|
|||||||
public const uint DefaultEkcNvIndex = 0x1c00002;
|
public const uint DefaultEkcNvIndex = 0x1c00002;
|
||||||
public const uint DefaultEkHandle = 0x81010001;
|
public const uint DefaultEkHandle = 0x81010001;
|
||||||
public const uint DefaultAkHandle = 0x81010002;
|
public const uint DefaultAkHandle = 0x81010002;
|
||||||
|
public const uint DefaultSrkHandle = 0x81000001;
|
||||||
|
|
||||||
private readonly Tpm2 tpm;
|
private readonly Tpm2 tpm;
|
||||||
|
|
||||||
@ -197,6 +199,20 @@ namespace hirs {
|
|||||||
return inPublic;
|
return inPublic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static TpmPublic GenerateSRKTemplateL1() {
|
||||||
|
TpmAlgId nameAlg = TpmAlgId.Sha256;
|
||||||
|
ObjectAttr attributes = ObjectAttr.FixedTPM | ObjectAttr.FixedParent | ObjectAttr.SensitiveDataOrigin | ObjectAttr.UserWithAuth | ObjectAttr.Restricted | ObjectAttr.Decrypt | ObjectAttr.NoDA;
|
||||||
|
byte[] auth_policy = null;
|
||||||
|
// ASYM: RSA 2048 with NULL scheme, SYM: AES-128 with CFB mode
|
||||||
|
RsaParms rsa = new(new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb), new NullAsymScheme(), 2048, 0);
|
||||||
|
// unique buffer must be filled with 0 for the EK Template L-1.
|
||||||
|
byte[] zero256 = new byte[256];
|
||||||
|
Array.Fill<byte>(zero256, 0x00);
|
||||||
|
Tpm2bPublicKeyRsa unique = new(zero256);
|
||||||
|
TpmPublic inPublic = new(nameAlg, attributes, auth_policy, rsa, unique);
|
||||||
|
return inPublic;
|
||||||
|
}
|
||||||
|
|
||||||
public void CreateEndorsementKey(uint ekHandleInt) {
|
public void CreateEndorsementKey(uint ekHandleInt) {
|
||||||
TpmHandle ekHandle = new(ekHandleInt);
|
TpmHandle ekHandle = new(ekHandleInt);
|
||||||
|
|
||||||
@ -247,6 +263,25 @@ namespace hirs {
|
|||||||
return inPublic;
|
return inPublic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static RsaParms LDevIDRSAParms() {
|
||||||
|
TpmAlgId digestAlg = TpmAlgId.Sha256;
|
||||||
|
RsaParms parms = new(new SymDefObject(TpmAlgId.Null, 0, TpmAlgId.Null), null, 2048, 0);
|
||||||
|
return parms;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ObjectAttr LDevIDAttributes() {
|
||||||
|
ObjectAttr attrib = ObjectAttr.Sign | ObjectAttr.FixedParent | ObjectAttr.FixedTPM
|
||||||
|
| ObjectAttr.SensitiveDataOrigin | ObjectAttr.UserWithAuth;
|
||||||
|
return attrib;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TpmPublic GenerateLDevIDTemplate(TpmAlgId nameAlg) {
|
||||||
|
RsaParms rsa = LDevIDRSAParms();
|
||||||
|
ObjectAttr attributes = LDevIDAttributes();
|
||||||
|
TpmPublic inPublic = new(nameAlg, attributes, null, rsa, new Tpm2bPublicKeyRsa());
|
||||||
|
return inPublic;
|
||||||
|
}
|
||||||
|
|
||||||
public void CreateAttestationKey(uint ekHandleInt, uint akHandleInt, bool replace) {
|
public void CreateAttestationKey(uint ekHandleInt, uint akHandleInt, bool replace) {
|
||||||
TpmHandle ekHandle = new(ekHandleInt);
|
TpmHandle ekHandle = new(ekHandleInt);
|
||||||
TpmHandle akHandle = new(akHandleInt);
|
TpmHandle akHandle = new(akHandleInt);
|
||||||
@ -298,6 +333,75 @@ namespace hirs {
|
|||||||
tpm.FlushContext(sessEK);
|
tpm.FlushContext(sessEK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void CreateStorageRootKey(uint srkHandleInt) {
|
||||||
|
TpmHandle srkHandle = new(srkHandleInt);
|
||||||
|
|
||||||
|
TpmPublic existingObject;
|
||||||
|
try {
|
||||||
|
existingObject = tpm.ReadPublic(srkHandle, out byte[] name, out byte[] qualifiedName);
|
||||||
|
Log.Debug("SRK already exists.");
|
||||||
|
return;
|
||||||
|
} catch (TpmException) {
|
||||||
|
Log.Debug("Verified SRK does not exist at expected handle. Creating SRK.");
|
||||||
|
}
|
||||||
|
|
||||||
|
SensitiveCreate inSens = new(); // key password (no params = no key password)
|
||||||
|
TpmPublic inPublic = CommandTpm.GenerateSRKTemplateL1();
|
||||||
|
|
||||||
|
TpmHandle newTransientSrkHandle = tpm.CreatePrimary(TpmRh.Owner, inSens, inPublic,
|
||||||
|
new byte[] { }, new PcrSelection[] { }, out TpmPublic outPublic,
|
||||||
|
out CreationData creationData, out byte[] creationHash, out TkCreation ticket);
|
||||||
|
|
||||||
|
Log.Debug("New SRK Handle: " + BitConverter.ToString(newTransientSrkHandle));
|
||||||
|
Log.Debug("New SRK PUB Name: " + BitConverter.ToString(outPublic.GetName()));
|
||||||
|
Log.Debug("New SRK PUB 2BREP: " + BitConverter.ToString(outPublic.GetTpm2BRepresentation()));
|
||||||
|
|
||||||
|
// Make the object persistent
|
||||||
|
tpm.EvictControl(TpmRh.Owner, newTransientSrkHandle, srkHandle);
|
||||||
|
Log.Debug("Successfully made the new SRK persistent at handle " + BitConverter.ToString(srkHandle) + ".");
|
||||||
|
|
||||||
|
tpm.FlushContext(newTransientSrkHandle);
|
||||||
|
Log.Debug("Flushed the context for the transient SRK.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CreateLDevIDKey(uint srkHandleInt, string pubPath, string privPath, bool replace) {
|
||||||
|
TpmHandle srkHandle = new(srkHandleInt);
|
||||||
|
|
||||||
|
if (!replace && File.Exists(privPath) && File.Exists(pubPath)) {
|
||||||
|
// Do Nothing
|
||||||
|
Log.Debug("LDevID exists at local file system path. Flag to not replace the LDevID is set in the settings file.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new transient key
|
||||||
|
TpmAlgId nameAlg = TpmAlgId.Sha256;
|
||||||
|
|
||||||
|
SensitiveCreate inSens = new();
|
||||||
|
TpmPublic inPublic = GenerateLDevIDTemplate(nameAlg);
|
||||||
|
|
||||||
|
TpmPrivate kLDevID = tpm.Create(srkHandle, inSens, inPublic, null, null, out TpmPublic outPublic,
|
||||||
|
out CreationData creationData, out byte[] creationHash, out TkCreation ticket);
|
||||||
|
|
||||||
|
Log.Debug("New LDevID PUB Name: " + BitConverter.ToString(outPublic.GetName()));
|
||||||
|
Log.Debug("New LDevID PUB 2BREP: " + BitConverter.ToString(outPublic.GetTpm2BRepresentation()));
|
||||||
|
Log.Debug("New LDevID PUB unique: " + BitConverter.ToString((Tpm2bPublicKeyRsa)(outPublic.unique)));
|
||||||
|
|
||||||
|
Tpm2bPublic ldevidPublic = new Tpm2bPublic(outPublic);
|
||||||
|
|
||||||
|
File.WriteAllBytes(pubPath, ldevidPublic);
|
||||||
|
File.WriteAllBytes(privPath, kLDevID);
|
||||||
|
Log.Debug("Created new LDevID at local file system paths.");
|
||||||
|
Log.Debug(" LDevID Pub Path: {0}", pubPath);
|
||||||
|
Log.Debug(" LDevID Priv Path: {0}", privPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] ConvertLDevIDPublic(string ldevidPubPath) {
|
||||||
|
byte[] ldevidPubBytes = File.ReadAllBytes(ldevidPubPath);
|
||||||
|
var marshaller = new Marshaller(ldevidPubBytes, DataRepresentation.Tpm);
|
||||||
|
Tpm2bPublic ldevidPublic = marshaller.Get<Tpm2bPublic>();
|
||||||
|
return ldevidPublic.publicArea;
|
||||||
|
}
|
||||||
|
|
||||||
public Tpm2bDigest[] GetPcrList(TpmAlgId pcrBankDigestAlg, uint[] pcrs = null) {
|
public Tpm2bDigest[] GetPcrList(TpmAlgId pcrBankDigestAlg, uint[] pcrs = null) {
|
||||||
if (pcrs == null) {
|
if (pcrs == null) {
|
||||||
pcrs = new uint[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 };
|
pcrs = new uint[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 };
|
||||||
|
@ -9,6 +9,9 @@ namespace hirs {
|
|||||||
TpmPublic ReadPublicArea(uint handleInt, out byte[] name, out byte[] qualifiedName);
|
TpmPublic ReadPublicArea(uint handleInt, out byte[] name, out byte[] qualifiedName);
|
||||||
void CreateEndorsementKey(uint ekHandleInt);
|
void CreateEndorsementKey(uint ekHandleInt);
|
||||||
void CreateAttestationKey(uint ekHandleInt, uint akHandleInt, bool replace);
|
void CreateAttestationKey(uint ekHandleInt, uint akHandleInt, bool replace);
|
||||||
|
void CreateStorageRootKey(uint srkHandleInt);
|
||||||
|
void CreateLDevIDKey(uint srkHandleInt, string pubPath, string privPath, bool replace);
|
||||||
|
byte[] ConvertLDevIDPublic(string ldevidPubPath);
|
||||||
Tpm2bDigest[] GetPcrList(TpmAlgId pcrBankDigestAlg, uint[] pcrs = null);
|
Tpm2bDigest[] GetPcrList(TpmAlgId pcrBankDigestAlg, uint[] pcrs = null);
|
||||||
void GetQuote(uint akHandleInt, TpmAlgId pcrBankDigestAlg, byte[] nonce, out CommandTpmQuoteResponse ctqr, uint[] pcrs = null);
|
void GetQuote(uint akHandleInt, TpmAlgId pcrBankDigestAlg, byte[] nonce, out CommandTpmQuoteResponse ctqr, uint[] pcrs = null);
|
||||||
byte[] ActivateCredential(uint akHandleInt, uint ekHandleInt, byte[] integrityHMAC, byte[] encIdentity, byte[] encryptedSecret);
|
byte[] ActivateCredential(uint akHandleInt, uint ekHandleInt, byte[] integrityHMAC, byte[] encIdentity, byte[] encryptedSecret);
|
||||||
|
@ -16,12 +16,13 @@ namespace hirsTest {
|
|||||||
DeviceInfo dv = new DeviceInfo();
|
DeviceInfo dv = new DeviceInfo();
|
||||||
byte[] akPub = new byte[] { };
|
byte[] akPub = new byte[] { };
|
||||||
byte[] ekPub = new byte[] { };
|
byte[] ekPub = new byte[] { };
|
||||||
|
byte[] ldevidPub = new byte[] { };
|
||||||
byte[] ekc = new byte[] { };
|
byte[] ekc = new byte[] { };
|
||||||
List<byte[]> pcs = new List<byte[]>();
|
List<byte[]> pcs = new List<byte[]>();
|
||||||
pcs.Add(new byte[] { });
|
pcs.Add(new byte[] { });
|
||||||
string componentList= "";
|
string componentList= "";
|
||||||
|
|
||||||
IdentityClaim obj = client.CreateIdentityClaim(dv, akPub, ekPub, ekc, pcs, componentList);
|
IdentityClaim obj = client.CreateIdentityClaim(dv, akPub, ekPub, ekc, pcs, componentList, ldevidPub);
|
||||||
Assert.Multiple(() => {
|
Assert.Multiple(() => {
|
||||||
Assert.That(obj.Dv, Is.Not.Null);
|
Assert.That(obj.Dv, Is.Not.Null);
|
||||||
Assert.That(obj.HasAkPublicArea, Is.True);
|
Assert.That(obj.HasAkPublicArea, Is.True);
|
||||||
@ -29,6 +30,7 @@ namespace hirsTest {
|
|||||||
Assert.That(obj.HasEndorsementCredential, Is.True);
|
Assert.That(obj.HasEndorsementCredential, Is.True);
|
||||||
Assert.That(obj.PlatformCredential, Has.Count.EqualTo(1));
|
Assert.That(obj.PlatformCredential, Has.Count.EqualTo(1));
|
||||||
Assert.That(obj.HasPaccorOutput, Is.True);
|
Assert.That(obj.HasPaccorOutput, Is.True);
|
||||||
|
Assert.That(obj.HasLdevidPublicArea, Is.True);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,8 @@ namespace hirsTest {
|
|||||||
byte[] credentialBlob = Convert.FromBase64String("OAAAIFQLXnXNUZTQNcNF367cJoRNCCwZSCz+tet07q+R0SKN6e2oGBsK3H9Vzbj667ZsjnVOtvpSpQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATXpL5zl/ET0XcndP3MQSOBUwrjZIrtCgJ0tvMk+8mCVC+S8H3L+XLRCus0ANH6tCLF+U5QGEonRisawIpTksACyZifpu7DIl8DCq2Z9XHeIM1zm2REIpkKFoEhEGzzu636VJ9VHyPCuUs5lBVE8XOV9w/MxaJ2hAaekAo7XS3oChoIqAg3EBXc9tGNDxQGtSLboO2G2XQhaX4ree9HkEIp5qnVa8ojcp+gi0HTICHo7gcaBKaE0lrMweXhShHZ+YP/vMHL4aekaTQUNIYpBfuuvPEzlSv4/J9yQ8ClZbSf1jR41TvpcWtmiyDCUYLOWUbs7s+jkjH9dCqiY0lmRNOM=");
|
byte[] credentialBlob = Convert.FromBase64String("OAAAIFQLXnXNUZTQNcNF367cJoRNCCwZSCz+tet07q+R0SKN6e2oGBsK3H9Vzbj667ZsjnVOtvpSpQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATXpL5zl/ET0XcndP3MQSOBUwrjZIrtCgJ0tvMk+8mCVC+S8H3L+XLRCus0ANH6tCLF+U5QGEonRisawIpTksACyZifpu7DIl8DCq2Z9XHeIM1zm2REIpkKFoEhEGzzu636VJ9VHyPCuUs5lBVE8XOV9w/MxaJ2hAaekAo7XS3oChoIqAg3EBXc9tGNDxQGtSLboO2G2XQhaX4ree9HkEIp5qnVa8ojcp+gi0HTICHo7gcaBKaE0lrMweXhShHZ+YP/vMHL4aekaTQUNIYpBfuuvPEzlSv4/J9yQ8ClZbSf1jR41TvpcWtmiyDCUYLOWUbs7s+jkjH9dCqiY0lmRNOM=");
|
||||||
TpmPublic ekPublic = CommandTpm.GenerateEKTemplateL1();
|
TpmPublic ekPublic = CommandTpm.GenerateEKTemplateL1();
|
||||||
TpmPublic akPublic = new(TpmAlgId.Sha256, ObjectAttr.None, System.Text.Encoding.UTF8.GetBytes("AK PUBLIC AUTH POLICY"), new RsaParms(new SymDefObject(TpmAlgId.Null, 0, TpmAlgId.Null), new SchemeRsassa(TpmAlgId.Sha256), 2048, 0), new Tpm2bPublicKeyRsa());
|
TpmPublic akPublic = new(TpmAlgId.Sha256, ObjectAttr.None, System.Text.Encoding.UTF8.GetBytes("AK PUBLIC AUTH POLICY"), new RsaParms(new SymDefObject(TpmAlgId.Null, 0, TpmAlgId.Null), new SchemeRsassa(TpmAlgId.Sha256), 2048, 0), new Tpm2bPublicKeyRsa());
|
||||||
|
TpmPublic srkPublic = CommandTpm.GenerateSRKTemplateL1();
|
||||||
|
TpmPublic ldevidPublic = new(TpmAlgId.Sha256, ObjectAttr.None, System.Text.Encoding.UTF8.GetBytes("LDEVID PUBLIC AUTH POLICY"), new RsaParms(new SymDefObject(TpmAlgId.Null, 0, TpmAlgId.Null), new SchemeRsassa(TpmAlgId.Sha256), 2048, 0), new Tpm2bPublicKeyRsa());
|
||||||
Tpm2bDigest[] sha1Values = new Tpm2bDigest[] { new Tpm2bDigest(System.Text.Encoding.UTF8.GetBytes("SHA1 DIGEST1")) };
|
Tpm2bDigest[] sha1Values = new Tpm2bDigest[] { new Tpm2bDigest(System.Text.Encoding.UTF8.GetBytes("SHA1 DIGEST1")) };
|
||||||
Tpm2bDigest[] sha256Values = new Tpm2bDigest[] { new Tpm2bDigest(System.Text.Encoding.UTF8.GetBytes("SHA256 DIGEST1")) };
|
Tpm2bDigest[] sha256Values = new Tpm2bDigest[] { new Tpm2bDigest(System.Text.Encoding.UTF8.GetBytes("SHA256 DIGEST1")) };
|
||||||
DeviceInfo dv = new();
|
DeviceInfo dv = new();
|
||||||
@ -33,7 +35,7 @@ namespace hirsTest {
|
|||||||
CertificateResponse certResp = new();
|
CertificateResponse certResp = new();
|
||||||
certResp.Status = ResponseStatus.Pass;
|
certResp.Status = ResponseStatus.Pass;
|
||||||
certResp.Certificate = Google.Protobuf.ByteString.CopyFrom(acaIssuedCert);
|
certResp.Certificate = Google.Protobuf.ByteString.CopyFrom(acaIssuedCert);
|
||||||
|
|
||||||
IHirsAcaTpm tpm = A.Fake<IHirsAcaTpm>();
|
IHirsAcaTpm tpm = A.Fake<IHirsAcaTpm>();
|
||||||
byte[] name = null, qualifiedName = null;
|
byte[] name = null, qualifiedName = null;
|
||||||
A.CallTo(() => tpm.GetCertificateFromNvIndex(CommandTpm.DefaultEkcNvIndex)).Returns(ekCert);
|
A.CallTo(() => tpm.GetCertificateFromNvIndex(CommandTpm.DefaultEkcNvIndex)).Returns(ekCert);
|
||||||
@ -41,6 +43,9 @@ namespace hirsTest {
|
|||||||
A.CallTo(() => tpm.ReadPublicArea(CommandTpm.DefaultEkHandle, out name, out qualifiedName)).Returns(ekPublic);
|
A.CallTo(() => tpm.ReadPublicArea(CommandTpm.DefaultEkHandle, out name, out qualifiedName)).Returns(ekPublic);
|
||||||
A.CallTo(() => tpm.CreateAttestationKey(CommandTpm.DefaultEkHandle, CommandTpm.DefaultAkHandle, false)).DoesNothing();
|
A.CallTo(() => tpm.CreateAttestationKey(CommandTpm.DefaultEkHandle, CommandTpm.DefaultAkHandle, false)).DoesNothing();
|
||||||
A.CallTo(() => tpm.ReadPublicArea(CommandTpm.DefaultAkHandle, out name, out qualifiedName)).Returns(akPublic);
|
A.CallTo(() => tpm.ReadPublicArea(CommandTpm.DefaultAkHandle, out name, out qualifiedName)).Returns(akPublic);
|
||||||
|
A.CallTo(() => tpm.CreateStorageRootKey(CommandTpm.DefaultSrkHandle)).DoesNothing();
|
||||||
|
A.CallTo(() => tpm.ReadPublicArea(CommandTpm.DefaultSrkHandle, out name, out qualifiedName)).Returns(srkPublic);
|
||||||
|
A.CallTo(() => tpm.CreateLDevIDKey(CommandTpm.DefaultSrkHandle, "", "", false)).DoesNothing();
|
||||||
//A.CallTo(() => tpm.getPcrList(TpmAlgId.Sha1, A<uint[]>.Ignored)).Returns(sha1Values);
|
//A.CallTo(() => tpm.getPcrList(TpmAlgId.Sha1, A<uint[]>.Ignored)).Returns(sha1Values);
|
||||||
//A.CallTo(() => tpm.getPcrList(TpmAlgId.Sha256, A<uint[]>.Ignored)).Returns(sha256Values);
|
//A.CallTo(() => tpm.getPcrList(TpmAlgId.Sha256, A<uint[]>.Ignored)).Returns(sha256Values);
|
||||||
A.CallTo(() => tpm.GetQuote(CommandTpm.DefaultAkHandle, TpmAlgId.Sha256, secret, out ctqr, A<uint[]>.Ignored)).DoesNothing();
|
A.CallTo(() => tpm.GetQuote(CommandTpm.DefaultAkHandle, TpmAlgId.Sha256, secret, out ctqr, A<uint[]>.Ignored)).DoesNothing();
|
||||||
@ -49,7 +54,7 @@ namespace hirsTest {
|
|||||||
A.CallTo(() => collector.CollectDeviceInfo(address)).Returns(dv);
|
A.CallTo(() => collector.CollectDeviceInfo(address)).Returns(dv);
|
||||||
|
|
||||||
IHirsAcaClient client = A.Fake<IHirsAcaClient>();
|
IHirsAcaClient client = A.Fake<IHirsAcaClient>();
|
||||||
IdentityClaim idClaim = client.CreateIdentityClaim(dv, akPublic, ekPublic, ekCert, null, paccorOutput);
|
IdentityClaim idClaim = client.CreateIdentityClaim(dv, akPublic, ekPublic, ekCert, null, paccorOutput, ldevidPublic);
|
||||||
CertificateRequest certReq = client.CreateAkCertificateRequest(secret, ctqr);
|
CertificateRequest certReq = client.CreateAkCertificateRequest(secret, ctqr);
|
||||||
A.CallTo(() => client.PostIdentityClaim(idClaim)).Returns(Task.FromResult<IdentityClaimResponse>(idClaimResp));
|
A.CallTo(() => client.PostIdentityClaim(idClaim)).Returns(Task.FromResult<IdentityClaimResponse>(idClaimResp));
|
||||||
A.CallTo(() => client.PostCertificateRequest(certReq)).Returns(Task.FromResult<CertificateResponse>(certResp));
|
A.CallTo(() => client.PostCertificateRequest(certReq)).Returns(Task.FromResult<CertificateResponse>(certResp));
|
||||||
@ -79,6 +84,8 @@ namespace hirsTest {
|
|||||||
byte[] acaIssuedCert = Encoding.UTF8.GetBytes("ACA ISSUED CERTIFICATE");
|
byte[] acaIssuedCert = Encoding.UTF8.GetBytes("ACA ISSUED CERTIFICATE");
|
||||||
TpmPublic ekPublic = CommandTpm.GenerateEKTemplateL1();
|
TpmPublic ekPublic = CommandTpm.GenerateEKTemplateL1();
|
||||||
TpmPublic akPublic = new(TpmAlgId.Sha256, ObjectAttr.None, System.Text.Encoding.UTF8.GetBytes("AK PUBLIC AUTH POLICY"), new RsaParms(new SymDefObject(TpmAlgId.Null, 0, TpmAlgId.Null), new SchemeRsassa(TpmAlgId.Sha256), 2048, 0), new Tpm2bPublicKeyRsa());
|
TpmPublic akPublic = new(TpmAlgId.Sha256, ObjectAttr.None, System.Text.Encoding.UTF8.GetBytes("AK PUBLIC AUTH POLICY"), new RsaParms(new SymDefObject(TpmAlgId.Null, 0, TpmAlgId.Null), new SchemeRsassa(TpmAlgId.Sha256), 2048, 0), new Tpm2bPublicKeyRsa());
|
||||||
|
TpmPublic srkPublic = CommandTpm.GenerateSRKTemplateL1();
|
||||||
|
TpmPublic ldevidPublic = new(TpmAlgId.Sha256, ObjectAttr.None, System.Text.Encoding.UTF8.GetBytes("LDEVID PUBLIC AUTH POLICY"), new RsaParms(new SymDefObject(TpmAlgId.Null, 0, TpmAlgId.Null), new SchemeRsassa(TpmAlgId.Sha256), 2048, 0), new Tpm2bPublicKeyRsa());
|
||||||
Tpm2bDigest[] sha1Values = new Tpm2bDigest[] { new Tpm2bDigest(System.Text.Encoding.UTF8.GetBytes("SHA1 DIGEST1")) };
|
Tpm2bDigest[] sha1Values = new Tpm2bDigest[] { new Tpm2bDigest(System.Text.Encoding.UTF8.GetBytes("SHA1 DIGEST1")) };
|
||||||
Tpm2bDigest[] sha256Values = new Tpm2bDigest[] { new Tpm2bDigest(System.Text.Encoding.UTF8.GetBytes("SHA256 DIGEST1")) };
|
Tpm2bDigest[] sha256Values = new Tpm2bDigest[] { new Tpm2bDigest(System.Text.Encoding.UTF8.GetBytes("SHA256 DIGEST1")) };
|
||||||
DeviceInfo dv = new();
|
DeviceInfo dv = new();
|
||||||
@ -93,6 +100,9 @@ namespace hirsTest {
|
|||||||
A.CallTo(() => tpm.ReadPublicArea(CommandTpm.DefaultEkHandle, out name, out qualifiedName)).Returns(ekPublic);
|
A.CallTo(() => tpm.ReadPublicArea(CommandTpm.DefaultEkHandle, out name, out qualifiedName)).Returns(ekPublic);
|
||||||
A.CallTo(() => tpm.CreateAttestationKey(CommandTpm.DefaultEkHandle, CommandTpm.DefaultAkHandle, false)).DoesNothing();
|
A.CallTo(() => tpm.CreateAttestationKey(CommandTpm.DefaultEkHandle, CommandTpm.DefaultAkHandle, false)).DoesNothing();
|
||||||
A.CallTo(() => tpm.ReadPublicArea(CommandTpm.DefaultAkHandle, out name, out qualifiedName)).Returns(ekPublic);
|
A.CallTo(() => tpm.ReadPublicArea(CommandTpm.DefaultAkHandle, out name, out qualifiedName)).Returns(ekPublic);
|
||||||
|
A.CallTo(() => tpm.CreateStorageRootKey(CommandTpm.DefaultSrkHandle)).DoesNothing();
|
||||||
|
A.CallTo(() => tpm.ReadPublicArea(CommandTpm.DefaultSrkHandle, out name, out qualifiedName)).Returns(srkPublic);
|
||||||
|
A.CallTo(() => tpm.CreateLDevIDKey(CommandTpm.DefaultSrkHandle, "", "", false)).DoesNothing();
|
||||||
A.CallTo(() => tpm.GetPcrList(TpmAlgId.Sha1, A<uint[]>.Ignored)).Returns(sha1Values);
|
A.CallTo(() => tpm.GetPcrList(TpmAlgId.Sha1, A<uint[]>.Ignored)).Returns(sha1Values);
|
||||||
A.CallTo(() => tpm.GetPcrList(TpmAlgId.Sha256, A<uint[]>.Ignored)).Returns(sha256Values);
|
A.CallTo(() => tpm.GetPcrList(TpmAlgId.Sha256, A<uint[]>.Ignored)).Returns(sha256Values);
|
||||||
|
|
||||||
@ -100,7 +110,7 @@ namespace hirsTest {
|
|||||||
A.CallTo(() => collector.CollectDeviceInfo(address)).Returns(dv);
|
A.CallTo(() => collector.CollectDeviceInfo(address)).Returns(dv);
|
||||||
|
|
||||||
IHirsAcaClient client = A.Fake<IHirsAcaClient>();
|
IHirsAcaClient client = A.Fake<IHirsAcaClient>();
|
||||||
IdentityClaim idClaim = client.CreateIdentityClaim(dv, akPublic, ekPublic, ekCert, null, paccorOutput);
|
IdentityClaim idClaim = client.CreateIdentityClaim(dv, akPublic, ekPublic, ekCert, null, paccorOutput, ldevidPublic);
|
||||||
A.CallTo(() => client.PostIdentityClaim(idClaim)).WithAnyArguments().Returns(Task.FromResult<IdentityClaimResponse>(idClaimResp));
|
A.CallTo(() => client.PostIdentityClaim(idClaim)).WithAnyArguments().Returns(Task.FromResult<IdentityClaimResponse>(idClaimResp));
|
||||||
|
|
||||||
Settings settings = Settings.LoadSettingsFromFile("./Resources/test/settings_test/appsettings.json");
|
Settings settings = Settings.LoadSettingsFromFile("./Resources/test/settings_test/appsettings.json");
|
||||||
|
@ -71,6 +71,7 @@ message IdentityClaim {
|
|||||||
repeated bytes platform_credential = 5;
|
repeated bytes platform_credential = 5;
|
||||||
optional string client_version = 6;
|
optional string client_version = 6;
|
||||||
optional string paccorOutput = 7;
|
optional string paccorOutput = 7;
|
||||||
|
optional bytes ldevid_public_area = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
message TpmQuote {
|
message TpmQuote {
|
||||||
@ -96,5 +97,6 @@ message CertificateRequest {
|
|||||||
message CertificateResponse {
|
message CertificateResponse {
|
||||||
optional bytes certificate = 1;
|
optional bytes certificate = 1;
|
||||||
optional ResponseStatus status = 2 [default = FAIL];
|
optional ResponseStatus status = 2 [default = FAIL];
|
||||||
|
optional bytes ldevidCertificate = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user