This is a stopping point because the code can't be fully worked out because the data (certificates) aren't correct.

This commit is contained in:
Cyrus 2020-12-17 07:24:51 -05:00
parent 640966ae8c
commit 1db52cebf9
5 changed files with 155 additions and 44 deletions

View File

@ -90,7 +90,9 @@ import java.security.spec.RSAPublicKeySpec;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -101,7 +103,6 @@ import java.util.regex.Pattern;
*/
public abstract class AbstractAttestationCertificateAuthority
implements AttestationCertificateAuthority {
/**
* Logger instance for for subclass instances.
*/
@ -122,7 +123,6 @@ public abstract class AbstractAttestationCertificateAuthority
* Number of bytes to include in the TPM2.0 nonce.
*/
public static final int NONCE_LENGTH = 20;
private static final int SEED_LENGTH = 32;
private static final int MAX_SECRET_LENGTH = 32;
private static final int RSA_MODULUS_LENGTH = 256;
@ -130,13 +130,11 @@ public abstract class AbstractAttestationCertificateAuthority
private static final int HMAC_KEY_LENGTH_BYTES = 32;
private static final int HMAC_SIZE_LENGTH_BYTES = 2;
private static final int TPM2_CREDENTIAL_BLOB_SIZE = 392;
// Constants used to parse out the ak name from the ak public data. Used in generateAkName
private static final String AK_NAME_PREFIX = "000b";
private static final String AK_NAME_HASH_PREFIX =
"0001000b00050072000000100014000b0800000000000100";
private static final String TPM_SIGNATURE_ALG = "sha";
private static final int MAC_BYTES = 6;
/**
@ -165,7 +163,6 @@ public abstract class AbstractAttestationCertificateAuthority
* certificates issued by this ACA are valid for.
*/
private final Integer validDays;
private final CertificateManager certificateManager;
private final ReferenceManifestManager referenceManifestManager;
private final DeviceRegister deviceRegister;
@ -456,6 +453,12 @@ public abstract class AbstractAttestationCertificateAuthority
// attempt to find platform credentials to validate
Set<PlatformCredential> platformCredentials = parsePcsFromIdentityClaim(claim,
endorsementCredential);
Map<BigInteger, PlatformCredential> correctedMap = new HashMap<>();
for (PlatformCredential pc : platformCredentials) {
correctedMap.put(pc.getSerialNumber(), pc);
}
platformCredentials.clear();
platformCredentials.addAll(correctedMap.values());
// Parse and save device info
Device device = processDeviceInfo(claim);

View File

@ -135,6 +135,12 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
List<SupplyChainValidation> validations = new LinkedList<>();
Map<PlatformCredential, SupplyChainValidation> deltaMapping = new HashMap<>();
SupplyChainValidation platformScv = null;
SupplyChainValidation.ValidationType platformType = SupplyChainValidation
.ValidationType.PLATFORM_CREDENTIAL;
SupplyChainValidation.ValidationType platformAttrType = SupplyChainValidation
.ValidationType.PLATFORM_CREDENTIAL_ATTRIBUTES;
Map<SupplyChainValidation.ValidationType, SupplyChainValidation> validationTypeMap
= new HashMap<>();
LOGGER.info("Validating supply chain.");
// Validate the Endorsement Credential
@ -153,7 +159,7 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
if (pcs == null || pcs.isEmpty()) {
LOGGER.error("There were no Platform Credentials to validate.");
validations.add(buildValidationRecord(
SupplyChainValidation.ValidationType.PLATFORM_CREDENTIAL,
platformType,
AppraisalStatus.Status.FAIL,
"Platform credential(s) missing", null, Level.ERROR));
} else {
@ -170,16 +176,63 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
platformScv = validatePcPolicy(pc, platformScv,
deltaMapping, acceptExpiredCerts);
validations.add(platformScv);
validations.addAll(deltaMapping.values());
/**
* Alright, this should work but because the test material is bad
* I can't finish it. Currently the delta certificate has the same
* serial number as the base, the same validity and so on. I will
* attempt to generate my own but for right now, I'm going to move
* on to something else.
*/
if (validationTypeMap.containsKey(
platformType)) {
SupplyChainValidation tmpScv = validationTypeMap.get(platformType);
if (tmpScv.getResult() == PASS && platformScv.getResult() == FAIL) {
validationTypeMap.put(platformType, platformScv);
}
} else {
validationTypeMap.put(platformType, platformScv);
}
if (pc.isBase()) {
baseCredential = pc;
LOGGER.error("Found the base Certificate");
}
pc.setDevice(device);
this.certificateManager.update(pc);
}
}
// check that the delta certificates validity date is after
// the base
if (baseCredential != null) {
for (PlatformCredential pc : pcs) {
int result = pc.getBeginValidity()
.compareTo(baseCredential.getBeginValidity());
if (!pc.isBase() && (result <= 0)) {
LOGGER.error("You are not crazy");
validationTypeMap.put(platformType,
buildValidationRecord(
platformType,
AppraisalStatus.Status.FAIL,
"Delta Certificate's validity "
+ "date is not after Base",
null, Level.ERROR));
break;
}
}
} else {
// we don't have a base cert, fail
validationTypeMap.put(platformType,
buildValidationRecord(
platformType,
AppraisalStatus.Status.FAIL,
"Base Platform credential missing",
null,
Level.ERROR));
}
validations.add(validationTypeMap.get(
platformType));
}
}
@ -189,17 +242,23 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
if (pcs == null || pcs.isEmpty()) {
LOGGER.error("There were no Platform Credentials to validate attributes.");
validations.add(buildValidationRecord(
SupplyChainValidation.ValidationType.PLATFORM_CREDENTIAL,
platformAttrType,
AppraisalStatus.Status.FAIL,
"Platform credential(s) missing."
+ " Cannot validate attributes",
null, Level.ERROR));
} else {
platformScv = validationTypeMap.get(
platformType);
SupplyChainValidation attributeScv = null;
List<ArchivableEntity> aes = new ArrayList<>();
if (platformScv != null) {
aes.addAll(platformScv.getCertificatesUsed());
}
Iterator<PlatformCredential> it = pcs.iterator();
while (it.hasNext()) {
PlatformCredential pc = it.next();
SupplyChainValidation attributeScv = null;
if (pc != null) {
if (pc.isDeltaChain()) {
// this check validates the delta changes and re-compares
@ -211,38 +270,69 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
attributeScv = validatePlatformCredentialAttributes(
pc, device.getDeviceInfo(), ec);
}
if (platformScv != null) {
// have to make sure the attribute validation isn't ignored and
// doesn't override general validation status
if (platformScv.getResult() == PASS
&& attributeScv.getResult() != PASS) {
// if the platform trust store validated but the attribute didn't
// replace
validations.remove(platformScv);
validations.add(attributeScv);
} else if ((platformScv.getResult() == PASS
&& attributeScv.getResult() == PASS)
|| (platformScv.getResult() != PASS
&& attributeScv.getResult() != PASS)) {
// if both trust store and attributes validated or failed
// combine messages
validations.remove(platformScv);
List<ArchivableEntity> aes = new ArrayList<>();
for (Certificate cert : platformScv.getCertificatesUsed()) {
aes.add(cert);
}
validations.add(new SupplyChainValidation(
platformScv.getValidationType(),
platformScv.getResult(), aes,
String.format("%s%n%s", platformScv.getMessage(),
// update the attribute SCV
if (validationTypeMap.containsKey(platformAttrType)) {
SupplyChainValidation tmpScv = validationTypeMap.get(
platformAttrType);
if (tmpScv.getResult() == PASS && attributeScv.getResult() == FAIL) {
validationTypeMap.put(platformAttrType, attributeScv);
} else if (tmpScv.getResult() == FAIL
&& attributeScv.getResult() == FAIL) {
validationTypeMap.put(platformAttrType, new SupplyChainValidation(
attributeScv.getValidationType(),
attributeScv.getResult(), aes,
String.format("%s%n%s", tmpScv.getMessage(),
attributeScv.getMessage())));
}
} else {
validationTypeMap.put(platformAttrType, attributeScv);
}
// if (platformScv != null) {
// // have to make sure the attribute validation isn't ignored and
// // doesn't override general validation status
// if (platformScv.getResult() == PASS
// && attributeScv.getResult() != PASS) {
// // if the platform trust store validated but the attribute didn't
// // replace
// validationTypeMap.put(
// SupplyChainValidation.ValidationType
// .PLATFORM_CREDENTIAL_ATTRIBUTES,
// attributeScv);
// } else if ((platformScv.getResult() == PASS
// && attributeScv.getResult() == PASS)
// || (platformScv.getResult() != PASS
// && attributeScv.getResult() != PASS)) {
// // if both trust store and attributes validated or failed
// // combine messages
// validations.add(new SupplyChainValidation(
// platformScv.getValidationType(),
// platformScv.getResult(), aes,
// String.format("%s%n%s", platformScv.getMessage(),
// attributeScv.getMessage())));
// }
// }
pc.setDevice(device);
this.certificateManager.update(pc);
}
}
//combine platform and platform attributes
validations.remove(platformScv);
attributeScv = validationTypeMap.get(
platformAttrType);
if (platformScv.getResult() == PASS && attributeScv.getResult() == FAIL) {
validations.add(new SupplyChainValidation(
platformScv.getValidationType(),
attributeScv.getResult(), aes, attributeScv.getMessage()));
} else if (platformScv.getResult() == FAIL && attributeScv.getResult() == FAIL) {
validations.add(new SupplyChainValidation(
platformScv.getValidationType(),
platformScv.getResult(), aes,
String.format("%s%n%s", platformScv.getMessage(),
attributeScv.getMessage())));
}
}
}
@ -645,7 +735,7 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
final PlatformCredential pc, final DeviceInfoReport deviceInfoReport,
final EndorsementCredential ec) {
final SupplyChainValidation.ValidationType validationType
= SupplyChainValidation.ValidationType.PLATFORM_CREDENTIAL;
= SupplyChainValidation.ValidationType.PLATFORM_CREDENTIAL_ATTRIBUTES;
if (pc == null) {
LOGGER.error("No platform credential to validate");
@ -676,7 +766,7 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
final PlatformCredential base,
final Map<PlatformCredential, SupplyChainValidation> deltaMapping) {
final SupplyChainValidation.ValidationType validationType
= SupplyChainValidation.ValidationType.PLATFORM_CREDENTIAL;
= SupplyChainValidation.ValidationType.PLATFORM_CREDENTIAL_ATTRIBUTES;
if (delta == null) {
LOGGER.error("No delta certificate to validate");

View File

@ -40,8 +40,7 @@ public class AppraisalStatus {
* @param message description of result
*/
public AppraisalStatus(final Status appStatus, final String message) {
this.appStatus = appStatus;
this.message = message;
this(appStatus, message, "");
}
/**

View File

@ -235,6 +235,14 @@ public class ComponentIdentifierV2 extends ComponentIdentifier {
return getAttributeStatus() == AttributeStatus.REMOVED;
}
/**
* @return true if the component status wasn't set.
*/
public final boolean isEmpty() {
return (getAttributeStatus() == AttributeStatus.EMPTY_STATUS)
|| (getAttributeStatus() == null);
}
/**
* @return indicates the type of platform certificate.
*/

View File

@ -633,7 +633,7 @@ public final class SupplyChainCredentialValidator implements CredentialValidator
List<ArchivableEntity> certificateList = null;
SupplyChainValidation scv = null;
resultMessage.append("There are errors with Delta "
+ "Component Statuses components:\n");
+ "Component Statuses:\n");
// go through the leaf and check the changes against the valid components
// forget modifying validOrigPcComponents
for (PlatformCredential delta : chainCertificates) {
@ -744,12 +744,24 @@ public final class SupplyChainCredentialValidator implements CredentialValidator
} else {
builtMatchList.add(ci);
}
} else if (ciV2.isEmpty()) {
fieldValidation = false;
LOGGER.warn(String.format("%s for delta %s has empty status",
ciV2.getComponentClass().toString(),
delta.getSerialNumber().toString()));
failureMsg.append(String.format("Empty component status "
+ "in delta certificate. (%s)%n",
delta.getSerialNumber().toString()));
deltaMapping.put(delta, new SupplyChainValidation(
SupplyChainValidation.ValidationType.PLATFORM_CREDENTIAL,
FAIL, certificateList,
failureMsg.toString()
));
}
}
}
// each delta has a change to change or modify what was just modified
modifiedClassValues.clear();
resultMessage.append(failureMsg.toString());
}
@ -809,11 +821,10 @@ public final class SupplyChainCredentialValidator implements CredentialValidator
for (ComponentIdentifier cId : fullDeltaChainComponents) {
ciV2 = (ComponentIdentifierV2) cId;
if (ciV2.getComponentClass().getClassValueString()
.contains(cInfo.getComponentClass())) {
if (isMatch(cId, cInfo)) {
.contains(cInfo.getComponentClass())
&& isMatch(cId, cInfo)) {
subCompIdList.remove(cId);
subCompInfoList.remove(cInfo);
}
}
}
}