Skip to content

Commit

Permalink
Update the FileAttestationTrustStore to read a directory with der cer…
Browse files Browse the repository at this point in the history
…ts for certification declaration verification
  • Loading branch information
vivien-apple committed Sep 2, 2022
1 parent 2a22f9d commit e7d9f34
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -172,16 +172,24 @@ void DefaultDACVerifier::VerifyAttestationInformation(const DeviceAttestationVer
uint8_t akidBuf[Crypto::kAuthorityKeyIdentifierLength];
MutableByteSpan akid(akidBuf);
constexpr size_t paaCertAllocatedLen = kMaxDERCertLength;
CHIP_ERROR err = CHIP_NO_ERROR;

VerifyOrExit(ExtractAKIDFromX509Cert(info.paiDerBuffer, akid) == CHIP_NO_ERROR,
attestationError = AttestationVerificationResult::kPaiFormatInvalid);

VerifyOrExit(paaCert.Alloc(paaCertAllocatedLen), attestationError = AttestationVerificationResult::kNoMemory);

paaDerBuffer = MutableByteSpan(paaCert.Get(), paaCertAllocatedLen);
VerifyOrExit(mAttestationTrustStore->GetProductAttestationAuthorityCert(akid, paaDerBuffer) == CHIP_NO_ERROR,
err = mAttestationTrustStore->GetProductAttestationAuthorityCert(akid, paaDerBuffer);
VerifyOrExit(err == CHIP_NO_ERROR || err == CHIP_ERROR_NOT_IMPLEMENTED,
attestationError = AttestationVerificationResult::kPaaNotFound);

if (err == CHIP_ERROR_NOT_IMPLEMENTED)
{
VerifyOrExit(kTestAttestationTrustStore.GetProductAttestationAuthorityCert(akid, paaDerBuffer) == CHIP_NO_ERROR,
attestationError = AttestationVerificationResult::kPaaNotFound);
}

VerifyOrExit(ExtractVIDPIDFromX509Cert(paaDerBuffer, paaVidPid) == CHIP_NO_ERROR,
attestationError = AttestationVerificationResult::kPaaFormatInvalid);

Expand Down
77 changes: 68 additions & 9 deletions src/credentials/attestation_verifier/FileAttestationTrustStore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,31 @@ const char * GetFilenameExtension(const char * filename)
}
} // namespace

FileAttestationTrustStore::FileAttestationTrustStore(const char * paaTrustStorePath)
FileAttestationTrustStore::FileAttestationTrustStore(const char * paaTrustStorePath, const char * cdTrustStorePath)
{
VerifyOrReturn(paaTrustStorePath != nullptr || cdTrustStorePath != nullptr);

if (paaTrustStorePath != nullptr)
{
LoadTrustStore(paaTrustStorePath, mPAADerCerts);
VerifyOrReturn(paaCount());
}

if (cdTrustStorePath != nullptr)
{
LoadTrustStore(cdTrustStorePath, mCDDerCerts);
VerifyOrReturn(cdCount());
}

mIsInitialized = true;
}

void FileAttestationTrustStore::LoadTrustStore(const char * trustStorePath,
std::vector<std::array<uint8_t, kMaxDERCertLength>> & certs)
{
DIR * dir;

dir = opendir(paaTrustStorePath);
dir = opendir(trustStorePath);
if (dir != nullptr)
{
// Nested directories are not handled.
Expand All @@ -56,7 +76,7 @@ FileAttestationTrustStore::FileAttestationTrustStore(const char * paaTrustStoreP
FILE * file;

std::array<uint8_t, kMaxDERCertLength> certificate;
std::string filename(paaTrustStorePath);
std::string filename(trustStorePath);

filename += std::string("/") + std::string(entry->d_name);

Expand All @@ -66,14 +86,13 @@ FileAttestationTrustStore::FileAttestationTrustStore(const char * paaTrustStoreP
uint32_t certificateLength = fread(certificate.data(), sizeof(uint8_t), kMaxDERCertLength, file);
if (certificateLength > 0)
{
mDerCerts.push_back(certificate);
mIsInitialized = true;
certs.push_back(certificate);
}
fclose(file);
}
else
{
Cleanup();
certs.clear();
break;
}
}
Expand All @@ -89,18 +108,26 @@ FileAttestationTrustStore::~FileAttestationTrustStore()

void FileAttestationTrustStore::Cleanup()
{
mDerCerts.clear();
mPAADerCerts.clear();
mCDDerCerts.clear();
mIsInitialized = false;
}

CHIP_ERROR FileAttestationTrustStore::GetProductAttestationAuthorityCert(const ByteSpan & skid,
MutableByteSpan & outPaaDerBuffer) const
{
VerifyOrReturnError(!mDerCerts.empty(), CHIP_ERROR_CA_CERT_NOT_FOUND);
// If the constructor has not tried to initialize the PAA certificates database, return CHIP_ERROR_NOT_IMPLEMENTED to use the
// testing trust store if the DefaultAttestationVerifier is in use.
if (mIsInitialized && paaCount() == 0)
{
return CHIP_ERROR_NOT_IMPLEMENTED;
}

VerifyOrReturnError(!mPAADerCerts.empty(), CHIP_ERROR_CA_CERT_NOT_FOUND);
VerifyOrReturnError(!skid.empty() && (skid.data() != nullptr), CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(skid.size() == Crypto::kSubjectKeyIdentifierLength, CHIP_ERROR_INVALID_ARGUMENT);

for (auto candidate : mDerCerts)
for (auto candidate : mPAADerCerts)
{
uint8_t skidBuf[Crypto::kSubjectKeyIdentifierLength] = { 0 };
MutableByteSpan candidateSkidSpan{ skidBuf };
Expand All @@ -118,5 +145,37 @@ CHIP_ERROR FileAttestationTrustStore::GetProductAttestationAuthorityCert(const B
return CHIP_ERROR_CA_CERT_NOT_FOUND;
}

CHIP_ERROR FileAttestationTrustStore::GetCertificationDeclarationSigningKey(const ByteSpan & skid,
Crypto::P256PublicKey & pubKey) const
{
// If the constructor has not tried to initialize the certification declaration certificates database, return
// CHIP_ERROR_NOT_IMPLEMENTED to use the testing trust store if the DefaultAttestationVerifier is in use.
if (mIsInitialized && cdCount() == 0)
{
return CHIP_ERROR_NOT_IMPLEMENTED;
}

VerifyOrReturnError(!mCDDerCerts.empty(), CHIP_ERROR_CA_CERT_NOT_FOUND);
VerifyOrReturnError(!skid.empty() && (skid.data() != nullptr), CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(skid.size() == Crypto::kSubjectKeyIdentifierLength, CHIP_ERROR_INVALID_ARGUMENT);

for (auto candidate : mCDDerCerts)
{
uint8_t skidBuf[Crypto::kSubjectKeyIdentifierLength] = { 0 };
MutableByteSpan candidateSkidSpan{ skidBuf };
VerifyOrReturnError(CHIP_NO_ERROR ==
Crypto::ExtractSKIDFromX509Cert(ByteSpan{ candidate.data(), candidate.size() }, candidateSkidSpan),
CHIP_ERROR_INTERNAL);

if (skid.data_equal(candidateSkidSpan))
{
// Found a match
return Crypto::ExtractPubkeyFromX509Cert(ByteSpan{ candidate.data(), candidate.size() }, pubKey);
}
}

return CHIP_ERROR_CA_CERT_NOT_FOUND;
}

} // namespace Credentials
} // namespace chip
15 changes: 10 additions & 5 deletions src/credentials/attestation_verifier/FileAttestationTrustStore.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,23 @@ namespace Credentials {
class FileAttestationTrustStore : public AttestationTrustStore
{
public:
FileAttestationTrustStore(const char * paaTrustStorePath);
FileAttestationTrustStore(const char * paaTrustStorePath = nullptr, const char * cdTrustStoreKey = nullptr);
~FileAttestationTrustStore();

bool IsInitialized() { return mIsInitialized; }

CHIP_ERROR GetProductAttestationAuthorityCert(const ByteSpan & skid, MutableByteSpan & outPaaDerBuffer) const override;
size_t size() const { return mDerCerts.size(); }
CHIP_ERROR GetCertificationDeclarationSigningKey(const ByteSpan & skid, Crypto::P256PublicKey & pubKey) const override;

bool IsInitialized() const { return mIsInitialized; }
size_t paaCount() const { return mPAADerCerts.size(); };
size_t cdCount() const { return mCDDerCerts.size(); };

protected:
std::vector<std::array<uint8_t, kMaxDERCertLength>> mDerCerts;
std::vector<std::array<uint8_t, kMaxDERCertLength>> mPAADerCerts;
std::vector<std::array<uint8_t, kMaxDERCertLength>> mCDDerCerts;

private:
void LoadTrustStore(const char * trustStorePath, std::vector<std::array<uint8_t, kMaxDERCertLength>> & certs);

bool mIsInitialized = false;

void Cleanup();
Expand Down

0 comments on commit e7d9f34

Please sign in to comment.