Skip to content

Commit a11e4b3

Browse files
committed
Added an interface for revocation checks to DeviceAttestationVerifier
1 parent 020b0e0 commit a11e4b3

12 files changed

+365
-7
lines changed

examples/chip-tool/BUILD.gn

+1
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ static_library("chip-tool-utils") {
109109
"${chip_root}/src/app/tests/suites/commands/interaction_model",
110110
"${chip_root}/src/controller/data_model",
111111
"${chip_root}/src/credentials:file_attestation_trust_store",
112+
"${chip_root}/src/credentials:json_file_revocation_set",
112113
"${chip_root}/src/lib",
113114
"${chip_root}/src/lib/core:types",
114115
"${chip_root}/src/lib/support/jsontlv",

examples/chip-tool/commands/common/CHIPCommand.h

+5
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ class CHIPCommand : public Command
6969
CHIPCommand(const char * commandName, CredentialIssuerCommands * credIssuerCmds, const char * helpText = nullptr) :
7070
Command(commandName, helpText), mCredIssuerCmds(credIssuerCmds)
7171
{
72+
AddArgument(
73+
"revocation-set-path", &mRevocationSetPath,
74+
"Path to file holding a list of Revoked Certificates. Can be absolute or relative to the current working directory.");
7275
AddArgument("paa-trust-store-path", &mPaaTrustStorePath,
7376
"Path to directory holding PAA certificate information. Can be absolute or relative to the current working "
7477
"directory.");
@@ -218,6 +221,7 @@ class CHIPCommand : public Command
218221
chip::Optional<chip::NodeId> mCommissionerNodeId;
219222
chip::Optional<chip::VendorId> mCommissionerVendorId;
220223
chip::Optional<uint16_t> mBleAdapterId;
224+
chip::Optional<char *> mRevocationSetPath;
221225
chip::Optional<char *> mPaaTrustStorePath;
222226
chip::Optional<char *> mCDTrustStorePath;
223227
chip::Optional<bool> mUseMaxSizedCerts;
@@ -226,6 +230,7 @@ class CHIPCommand : public Command
226230
// Cached trust store so commands other than the original startup command
227231
// can spin up commissioners as needed.
228232
static const chip::Credentials::AttestationTrustStore * sTrustStore;
233+
static const chip::Credentials::RevocationSet * sRevocationSet;
229234

230235
static void RunQueuedCommand(intptr_t commandArg);
231236
typedef decltype(RunQueuedCommand) MatterWorkCallback;

examples/chip-tool/commands/common/CredentialIssuerCommands.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ class CredentialIssuerCommands
5959
* @return CHIP_ERROR CHIP_NO_ERROR on success, or corresponding error code.
6060
*/
6161
virtual CHIP_ERROR SetupDeviceAttestation(chip::Controller::SetupParams & setupParams,
62-
const chip::Credentials::AttestationTrustStore * trustStore) = 0;
62+
const chip::Credentials::AttestationTrustStore * trustStore,
63+
const chip::Credentials::RevocationSet * revocationSet) = 0;
6364

6465
/**
6566
* @brief Add a list of additional non-default CD verifying keys (by certificate)

examples/chip-tool/commands/example/ExampleCredentialIssuerCommands.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,12 @@ class ExampleCredentialIssuerCommands : public CredentialIssuerCommands
3434
return mOpCredsIssuer.Initialize(storage);
3535
}
3636
CHIP_ERROR SetupDeviceAttestation(chip::Controller::SetupParams & setupParams,
37-
const chip::Credentials::AttestationTrustStore * trustStore) override
37+
const chip::Credentials::AttestationTrustStore * trustStore,
38+
const chip::Credentials::RevocationSet * revocationSet) override
3839
{
3940
chip::Credentials::SetDeviceAttestationCredentialsProvider(chip::Credentials::Examples::GetExampleDACProvider());
4041

41-
mDacVerifier = chip::Credentials::GetDefaultDACVerifier(trustStore);
42+
mDacVerifier = chip::Credentials::GetDefaultDACVerifier(trustStore, revocationSet);
4243
setupParams.deviceAttestationVerifier = mDacVerifier;
4344
mDacVerifier->EnableCdTestKeySupport(mAllowTestCdSigningKey);
4445

src/controller/python/BUILD.gn

+1
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ shared_library("ChipDeviceCtrl") {
136136
public_deps += [
137137
"${chip_root}/src/controller/data_model",
138138
"${chip_root}/src/credentials:file_attestation_trust_store",
139+
"${chip_root}/src/credentials:json_file_revocation_set",
139140
"${chip_root}/src/lib/support:testing",
140141
"${chip_root}/src/tracing/json",
141142
"${chip_root}/src/tracing/perfetto",

src/credentials/BUILD.gn

+15
Original file line numberDiff line numberDiff line change
@@ -185,3 +185,18 @@ static_library("file_attestation_trust_store") {
185185
"${nlassert_root}:nlassert",
186186
]
187187
}
188+
189+
static_library("json_file_revocation_set") {
190+
output_name = "libJSONFileRevocationSet"
191+
192+
sources = [
193+
"attestation_verifier/JSONFileRevocationSet.cpp",
194+
"attestation_verifier/JSONFileRevocationSet.h",
195+
]
196+
197+
public_deps = [
198+
":credentials",
199+
"${chip_root}/third_party/jsoncpp",
200+
"${nlassert_root}:nlassert",
201+
]
202+
}

src/credentials/attestation_verifier/DefaultDeviceAttestationVerifier.cpp

+55-2
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,50 @@ void DefaultDACVerifier::VerifyAttestationInformation(const DeviceAttestationVer
458458
VerifyOrExit(attestationError == AttestationVerificationResult::kSuccess, attestationError = attestationError);
459459
}
460460

461+
{
462+
uint8_t issuerBuf[kMaxCertificateDistinguishedNameLength] = { 0 };
463+
MutableByteSpan paaIssuer(issuerBuf);
464+
MutableByteSpan paiIssuer(issuerBuf);
465+
MutableByteSpan dacIssuer(issuerBuf);
466+
uint8_t akidBuf[kAuthorityKeyIdentifierLength];
467+
MutableByteSpan akid(akidBuf);
468+
uint8_t serialNumberBuf[kMaxCertificateSerialNumberLength];
469+
MutableByteSpan serialNumber(serialNumberBuf);
470+
471+
VerifyOrExit(ExtractIssuerFromX509Cert(paaDerBuffer, paaIssuer) == CHIP_NO_ERROR,
472+
attestationError = AttestationVerificationResult::kPaaFormatInvalid);
473+
VerifyOrExit(ExtractAKIDFromX509Cert(paaDerBuffer, akid) == CHIP_NO_ERROR,
474+
attestationError = AttestationVerificationResult::kPaaFormatInvalid);
475+
VerifyOrExit(ExtractSerialNumberFromX509Cert(paaDerBuffer, serialNumber) == CHIP_NO_ERROR,
476+
attestationError = AttestationVerificationResult::kPaaFormatInvalid);
477+
478+
attestationError = IsCertificateRevoked(true, paaVidPid, paaIssuer, akid, serialNumber);
479+
VerifyOrExit(attestationError == AttestationVerificationResult::kSuccess,
480+
attestationError = AttestationVerificationResult::kPaaRevoked);
481+
482+
VerifyOrExit(ExtractIssuerFromX509Cert(info.paiDerBuffer, paiIssuer) == CHIP_NO_ERROR,
483+
attestationError = AttestationVerificationResult::kPaiFormatInvalid);
484+
VerifyOrExit(ExtractAKIDFromX509Cert(info.paiDerBuffer, akid) == CHIP_NO_ERROR,
485+
attestationError = AttestationVerificationResult::kPaiFormatInvalid);
486+
VerifyOrExit(ExtractSerialNumberFromX509Cert(info.paiDerBuffer, serialNumber) == CHIP_NO_ERROR,
487+
attestationError = AttestationVerificationResult::kPaiFormatInvalid);
488+
489+
attestationError = IsCertificateRevoked(false, paiVidPid, paiIssuer, akid, serialNumber);
490+
VerifyOrExit(attestationError == AttestationVerificationResult::kSuccess,
491+
attestationError = AttestationVerificationResult::kPaiRevoked);
492+
493+
VerifyOrExit(ExtractIssuerFromX509Cert(info.dacDerBuffer, dacIssuer) == CHIP_NO_ERROR,
494+
attestationError = AttestationVerificationResult::kDacFormatInvalid);
495+
VerifyOrExit(ExtractAKIDFromX509Cert(info.dacDerBuffer, akid) == CHIP_NO_ERROR,
496+
attestationError = AttestationVerificationResult::kDacFormatInvalid);
497+
VerifyOrExit(ExtractSerialNumberFromX509Cert(info.dacDerBuffer, serialNumber) == CHIP_NO_ERROR,
498+
attestationError = AttestationVerificationResult::kDacFormatInvalid);
499+
500+
attestationError = IsCertificateRevoked(false, dacVidPid, dacIssuer, akid, serialNumber);
501+
VerifyOrExit(attestationError == AttestationVerificationResult::kSuccess,
502+
attestationError = AttestationVerificationResult::kDacRevoked);
503+
}
504+
461505
exit:
462506
onCompletion->mCall(onCompletion->mContext, info, attestationError);
463507
}
@@ -607,6 +651,15 @@ CHIP_ERROR DefaultDACVerifier::VerifyNodeOperationalCSRInformation(const ByteSpa
607651
return CHIP_NO_ERROR;
608652
}
609653

654+
AttestationVerificationResult DefaultDACVerifier::IsCertificateRevoked(bool isPaa, AttestationCertVidPid vidPidUnderTest,
655+
ByteSpan issuer, ByteSpan authorityKeyId,
656+
ByteSpan serialNumber)
657+
{
658+
VerifyOrReturnError(mRevocationSet != nullptr, AttestationVerificationResult::kNotImplemented);
659+
660+
return mRevocationSet->IsCertificateRevoked(isPaa, vidPidUnderTest, issuer, authorityKeyId, serialNumber);
661+
}
662+
610663
bool CsaCdKeysTrustStore::IsCdTestKey(const ByteSpan & kid) const
611664
{
612665
return kid.data_equal(ByteSpan{ gTestCdPubkeyKid });
@@ -683,9 +736,9 @@ const AttestationTrustStore * GetTestAttestationTrustStore()
683736
return &gTestAttestationTrustStore.get();
684737
}
685738

686-
DeviceAttestationVerifier * GetDefaultDACVerifier(const AttestationTrustStore * paaRootStore)
739+
DeviceAttestationVerifier * GetDefaultDACVerifier(const AttestationTrustStore * paaRootStore, const RevocationSet * revocationSet)
687740
{
688-
static DefaultDACVerifier defaultDACVerifier{ paaRootStore };
741+
static DefaultDACVerifier defaultDACVerifier{ paaRootStore, revocationSet };
689742

690743
return &defaultDACVerifier;
691744
}

src/credentials/attestation_verifier/DefaultDeviceAttestationVerifier.h

+8-2
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ class CsaCdKeysTrustStore : public WellKnownKeysTrustStore
5757
class DefaultDACVerifier : public DeviceAttestationVerifier
5858
{
5959
public:
60-
DefaultDACVerifier(const AttestationTrustStore * paaRootStore) : mAttestationTrustStore(paaRootStore) {}
60+
DefaultDACVerifier(const AttestationTrustStore * paaRootStore, const RevocationSet * revocationSet) :
61+
mAttestationTrustStore(paaRootStore), mRevocationSet(revocationSet)
62+
{}
6163

6264
void VerifyAttestationInformation(const DeviceAttestationVerifier::AttestationInfo & info,
6365
Callback::Callback<OnAttestationInformationVerification> * onCompletion) override;
@@ -74,13 +76,17 @@ class DefaultDACVerifier : public DeviceAttestationVerifier
7476
const ByteSpan & attestationSignatureBuffer,
7577
const Crypto::P256PublicKey & dacPublicKey, const ByteSpan & csrNonce) override;
7678

79+
AttestationVerificationResult IsCertificateRevoked(bool isPaa, Crypto::AttestationCertVidPid vidPidUnderTest, ByteSpan issuer,
80+
ByteSpan authorityKeyId, ByteSpan serialNumber) override;
81+
7782
CsaCdKeysTrustStore * GetCertificationDeclarationTrustStore() override { return &mCdKeysTrustStore; }
7883

7984
protected:
8085
DefaultDACVerifier() {}
8186

8287
CsaCdKeysTrustStore mCdKeysTrustStore;
8388
const AttestationTrustStore * mAttestationTrustStore;
89+
const RevocationSet * mRevocationSet;
8490
};
8591

8692
/**
@@ -109,7 +115,7 @@ const AttestationTrustStore * GetTestAttestationTrustStore();
109115
* process lifetime. In particular, after the first call it's not
110116
* possible to change which AttestationTrustStore is used by this verifier.
111117
*/
112-
DeviceAttestationVerifier * GetDefaultDACVerifier(const AttestationTrustStore * paaRootStore);
118+
DeviceAttestationVerifier * GetDefaultDACVerifier(const AttestationTrustStore * paaRootStore, const RevocationSet * revocationSet);
113119

114120
} // namespace Credentials
115121
} // namespace chip

src/credentials/attestation_verifier/DeviceAttestationVerifier.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@ class UnimplementedDACVerifier : public DeviceAttestationVerifier
6969
(void) csrNonce;
7070
return CHIP_ERROR_NOT_IMPLEMENTED;
7171
}
72+
73+
AttestationVerificationResult IsCertificateRevoked(bool isPaa, Crypto::AttestationCertVidPid vidPidUnderTest, ByteSpan issuer,
74+
ByteSpan authorityKeyId, ByteSpan serialNumber) override
75+
{
76+
return AttestationVerificationResult::kNotImplemented;
77+
}
7278
};
7379

7480
// Default to avoid nullptr on getter and cleanly handle new products/clients before

src/credentials/attestation_verifier/DeviceAttestationVerifier.h

+22
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,25 @@ class ArrayAttestationTrustStore : public AttestationTrustStore
259259
const size_t mNumCerts;
260260
};
261261

262+
/**
263+
* @brief Helper utility to model a basic Revocation Set usable for device attestation verifiers.
264+
*
265+
*/
266+
class RevocationSet
267+
{
268+
public:
269+
RevocationSet() = default;
270+
virtual ~RevocationSet() = default;
271+
272+
// Not copyable
273+
RevocationSet(const RevocationSet &) = delete;
274+
RevocationSet & operator=(const RevocationSet &) = delete;
275+
276+
virtual AttestationVerificationResult IsCertificateRevoked(bool isPaa, Crypto::AttestationCertVidPid vidPidUnderTest,
277+
ByteSpan issuer, ByteSpan authorityKeyId,
278+
ByteSpan serialNumber) const = 0;
279+
};
280+
262281
class DeviceAttestationVerifier
263282
{
264283
public:
@@ -386,6 +405,9 @@ class DeviceAttestationVerifier
386405
const Crypto::P256PublicKey & dacPublicKey,
387406
const ByteSpan & csrNonce) = 0;
388407

408+
virtual AttestationVerificationResult IsCertificateRevoked(bool isPaa, Crypto::AttestationCertVidPid vidPidUnderTest,
409+
ByteSpan issuer, ByteSpan authorityKeyId, ByteSpan serialNumber) = 0;
410+
389411
/**
390412
* @brief Get the trust store used for the attestation verifier.
391413
*

0 commit comments

Comments
 (0)