Skip to content

Commit 45f544b

Browse files
shubhamdpandy31415
andauthored
da_revocation: Follow ups in TestDACRevocationDelegateImpl and revocation set generation script (#36680)
* serialize the crl signer and crl signer delegator cert as DER * use enum instead of bool for keyid and rdns * use std::string in internal APIs * update impl and tests to use pure base64 DER encoded data * restyler changes * Apply suggestions from code review Co-authored-by: Andrei Litvin <[email protected]> --------- Co-authored-by: Andrei Litvin <[email protected]>
1 parent 9e671ad commit 45f544b

File tree

4 files changed

+114
-143
lines changed

4 files changed

+114
-143
lines changed

credentials/generate-revocation-set.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import requests
3333
from click_option_group import RequiredMutuallyExclusiveOptionGroup, optgroup
3434
from cryptography import x509
35+
from cryptography.hazmat.primitives import serialization
3536
from cryptography.hazmat.primitives.asymmetric import ec
3637
from cryptography.x509.oid import NameOID
3738

@@ -510,12 +511,12 @@ def main(use_main_net_dcld: str, use_test_net_dcld: str, use_main_net_http: bool
510511
"issuer_subject_key_id": certificate_akid_hex,
511512
"issuer_name": certificate_authority_name_b64,
512513
"revoked_serial_numbers": serialnumber_list,
513-
"crl_signer_cert": revocation_point["crlSignerCertificate"],
514+
"crl_signer_cert": base64.b64encode(crl_signer_certificate.public_bytes(serialization.Encoding.DER)).decode('utf-8'),
514515
}
515516

516-
if "crlSignerDelegator" in revocation_point:
517-
entry["crl_signer_delegator"] = revocation_point["crlSignerDelegator"]
518-
517+
if crl_signer_delegator_cert:
518+
entry["crl_signer_delegator"] = base64.b64encode(
519+
crl_signer_delegator_cert.public_bytes(serialization.Encoding.DER)).decode('utf-8'),
519520
logging.debug(f"Entry to append: {entry}")
520521
revocation_set.append(entry)
521522

src/credentials/attestation_verifier/TestDACRevocationDelegateImpl.cpp

+76-116
Original file line numberDiff line numberDiff line change
@@ -32,49 +32,13 @@ namespace Credentials {
3232

3333
namespace {
3434

35-
static constexpr uint32_t kMaxIssuerBase64Len = BASE64_ENCODED_LEN(kMaxCertificateDistinguishedNameLength);
36-
37-
CHIP_ERROR BytesToHexStr(const ByteSpan & bytes, MutableCharSpan & outHexStr)
35+
CHIP_ERROR BytesToHexStr(const ByteSpan & bytes, std::string & outHexStr)
3836
{
39-
Encoding::HexFlags flags = Encoding::HexFlags::kUppercase;
40-
ReturnErrorOnFailure(BytesToHex(bytes.data(), bytes.size(), outHexStr.data(), outHexStr.size(), flags));
41-
outHexStr.reduce_size(2 * bytes.size());
42-
return CHIP_NO_ERROR;
43-
}
44-
45-
CHIP_ERROR X509_PemToDer(const std::string & pemCert, MutableByteSpan & derCert)
46-
{
47-
std::string beginMarker = "-----BEGIN CERTIFICATE-----";
48-
std::string endMarker = "-----END CERTIFICATE-----";
49-
50-
std::size_t beginPos = pemCert.find(beginMarker);
51-
VerifyOrReturnError(beginPos != std::string::npos, CHIP_ERROR_INVALID_ARGUMENT);
37+
size_t hexLength = bytes.size() * 2;
38+
outHexStr.resize(hexLength);
5239

53-
std::size_t endPos = pemCert.find(endMarker);
54-
VerifyOrReturnError(endPos != std::string::npos, CHIP_ERROR_INVALID_ARGUMENT);
55-
56-
VerifyOrReturnError(beginPos < endPos, CHIP_ERROR_INVALID_ARGUMENT);
57-
58-
// Extract content between markers
59-
std::string plainB64Str = pemCert.substr(beginPos + beginMarker.length(), endPos - (beginPos + beginMarker.length()));
60-
61-
// Remove all newline characters '\n' and '\r'
62-
plainB64Str.erase(std::remove(plainB64Str.begin(), plainB64Str.end(), '\n'), plainB64Str.end());
63-
plainB64Str.erase(std::remove(plainB64Str.begin(), plainB64Str.end(), '\r'), plainB64Str.end());
64-
65-
VerifyOrReturnError(!plainB64Str.empty(), CHIP_ERROR_INVALID_ARGUMENT);
66-
67-
// Verify we have enough room to store the decoded certificate
68-
size_t maxDecodeLen = BASE64_MAX_DECODED_LEN(plainB64Str.size());
69-
VerifyOrReturnError(derCert.size() >= maxDecodeLen, CHIP_ERROR_BUFFER_TOO_SMALL);
70-
71-
// decode b64
72-
uint16_t derLen = Base64Decode(plainB64Str.c_str(), static_cast<uint16_t>(plainB64Str.size()), derCert.data());
73-
VerifyOrReturnError(derLen != UINT16_MAX, CHIP_ERROR_INVALID_ARGUMENT);
74-
75-
derCert.reduce_size(derLen);
76-
77-
return CHIP_NO_ERROR;
40+
Encoding::HexFlags flags = Encoding::HexFlags::kUppercase;
41+
return BytesToHex(bytes.data(), bytes.size(), &outHexStr[0], hexLength, flags);
7842
}
7943

8044
} // anonymous namespace
@@ -92,51 +56,40 @@ void TestDACRevocationDelegateImpl::ClearDeviceAttestationRevocationSetPath()
9256
mDeviceAttestationRevocationSetPath = mDeviceAttestationRevocationSetPath.substr(0, 0);
9357
}
9458

95-
// outSubject is subject encoded as base64 string
96-
// outKeyId is SKID encoded as hex string
97-
CHIP_ERROR TestDACRevocationDelegateImpl::GetSubjectAndKeyIdFromPEMCert(const std::string & certPEM, std::string & outSubject,
98-
std::string & outKeyId)
99-
{
100-
// buffers and spans for storing crl signer delegator OR crl signer cert info
101-
char subjectBuf[kMaxIssuerBase64Len] = { 0 };
102-
char skidBuf[2 * kAuthorityKeyIdentifierLength] = { 0 };
103-
uint8_t certDerBuf[kMax_x509_Certificate_Length] = { 0 };
104-
105-
MutableCharSpan subject(subjectBuf);
106-
MutableCharSpan keyId(skidBuf);
107-
MutableByteSpan certDER(certDerBuf);
108-
109-
ReturnLogErrorOnFailure(X509_PemToDer(certPEM, certDER));
110-
ReturnErrorOnFailure(GetSubjectNameBase64Str(certDER, subject));
111-
ReturnErrorOnFailure(GetSKIDHexStr(certDER, keyId));
112-
113-
outSubject = std::string(subject.data(), subject.size());
114-
outKeyId = std::string(keyId.data(), keyId.size());
115-
116-
return CHIP_NO_ERROR;
117-
}
118-
11959
// Check if issuer and AKID matches with the crl signer OR crl signer delegator's subject and SKID
12060
bool TestDACRevocationDelegateImpl::CrossValidateCert(const Json::Value & revokedSet, const std::string & akidHexStr,
12161
const std::string & issuerNameBase64Str)
12262
{
123-
std::string certPEM;
63+
std::string certBase64;
12464
[[maybe_unused]] std::string certType;
12565

12666
if (revokedSet.isMember("crl_signer_delegator"))
12767
{
128-
certPEM = revokedSet["crl_signer_delegator"].asString();
129-
certType = "CRL Signer delegator";
68+
certBase64 = revokedSet["crl_signer_delegator"].asString();
69+
certType = "CRL Signer delegator";
13070
}
13171
else
13272
{
133-
certPEM = revokedSet["crl_signer_cert"].asString();
134-
certType = "CRL Signer";
73+
certBase64 = revokedSet["crl_signer_cert"].asString();
74+
certType = "CRL Signer";
13575
}
13676

137-
std::string subject; // crl signer or crl signer delegator subject
138-
std::string keyId; // crl signer or crl signer delegator SKID
139-
VerifyOrReturnValue(CHIP_NO_ERROR == GetSubjectAndKeyIdFromPEMCert(certPEM, subject, keyId), false);
77+
uint8_t certDerBuf[kMax_x509_Certificate_Length] = { 0 };
78+
MutableByteSpan certDER(certDerBuf);
79+
80+
// Verify we have enough room to store the decoded certificate
81+
size_t maxDecodeLen = BASE64_MAX_DECODED_LEN(certBase64.size());
82+
VerifyOrReturnValue(certDER.size() >= maxDecodeLen, false);
83+
84+
uint16_t derLen = Base64Decode(certBase64.c_str(), static_cast<uint16_t>(certBase64.size()), certDER.data());
85+
VerifyOrReturnValue(derLen != UINT16_MAX, false);
86+
certDER.reduce_size(derLen);
87+
88+
std::string subject;
89+
std::string keyId;
90+
91+
VerifyOrReturnValue(CHIP_NO_ERROR == GetSubjectNameBase64Str(certDER, subject), false);
92+
VerifyOrReturnValue(CHIP_NO_ERROR == GetSKIDHexStr(certDER, keyId), false);
14093

14194
ChipLogDetail(NotSpecified, "%s: Subject: %s", certType.c_str(), subject.c_str());
14295
ChipLogDetail(NotSpecified, "%s: SKID: %s", certType.c_str(), keyId.c_str());
@@ -154,13 +107,13 @@ bool TestDACRevocationDelegateImpl::CrossValidateCert(const Json::Value & revoke
154107
// "serial1 bytes as base64",
155108
// "serial2 bytes as base64"
156109
// ]
157-
// "crl_signer_cert": "<PEM incoded CRL signer certificate>",
158-
// "crl_signer_delegator": <PEM incoded CRL signer delegator certificate>,
110+
// "crl_signer_cert": "<base64 encoded DER certificate>",
111+
// "crl_signer_delegator": "<base64 encoded DER certificate>",
159112
// }
160113
// ]
161114
//
162-
bool TestDACRevocationDelegateImpl::IsEntryInRevocationSet(const CharSpan & akidHexStr, const CharSpan & issuerNameBase64Str,
163-
const CharSpan & serialNumberHexStr)
115+
bool TestDACRevocationDelegateImpl::IsEntryInRevocationSet(const std::string & akidHexStr, const std::string & issuerNameBase64Str,
116+
const std::string & serialNumberHexStr)
164117
{
165118
std::ifstream file(mDeviceAttestationRevocationSetPath.c_str());
166119
if (!file.is_open())
@@ -185,30 +138,26 @@ bool TestDACRevocationDelegateImpl::IsEntryInRevocationSet(const CharSpan & akid
185138
return false;
186139
}
187140

188-
std::string issuerName = std::string(issuerNameBase64Str.data(), issuerNameBase64Str.size());
189-
std::string serialNumber = std::string(serialNumberHexStr.data(), serialNumberHexStr.size());
190-
std::string akid = std::string(akidHexStr.data(), akidHexStr.size());
191-
192141
// 6.2.4.2. Determining Revocation Status of an Entity
193142
for (const auto & revokedSet : jsonData)
194143
{
195-
if (revokedSet["issuer_name"].asString() != issuerName)
144+
if (revokedSet["issuer_name"].asString() != issuerNameBase64Str)
196145
{
197146
continue;
198147
}
199-
if (revokedSet["issuer_subject_key_id"].asString() != akid)
148+
if (revokedSet["issuer_subject_key_id"].asString() != akidHexStr)
200149
{
201150
continue;
202151
}
203152

204153
// 4.a cross validate PAI with crl signer OR crl signer delegator
205154
// 4.b cross validate DAC with crl signer OR crl signer delegator
206-
VerifyOrReturnValue(CrossValidateCert(revokedSet, akid, issuerName), false);
155+
VerifyOrReturnValue(CrossValidateCert(revokedSet, akidHexStr, issuerNameBase64Str), false);
207156

208157
// 4.c check if serial number is revoked
209158
for (const auto & revokedSerialNumber : revokedSet["revoked_serial_numbers"])
210159
{
211-
if (revokedSerialNumber.asString() == serialNumber)
160+
if (revokedSerialNumber.asString() == serialNumberHexStr)
212161
{
213162
return true;
214163
}
@@ -217,36 +166,42 @@ bool TestDACRevocationDelegateImpl::IsEntryInRevocationSet(const CharSpan & akid
217166
return false;
218167
}
219168

220-
CHIP_ERROR TestDACRevocationDelegateImpl::GetKeyIDHexStr(const ByteSpan & certDer, MutableCharSpan & outKeyIDHexStr, bool isAKID)
169+
CHIP_ERROR TestDACRevocationDelegateImpl::GetKeyIDHexStr(const ByteSpan & certDer, std::string & outKeyIDHexStr,
170+
KeyIdType keyIdType)
221171
{
222172
static_assert(kAuthorityKeyIdentifierLength == kSubjectKeyIdentifierLength, "AKID and SKID length mismatch");
223173

224174
uint8_t keyIdBuf[kAuthorityKeyIdentifierLength];
225175
MutableByteSpan keyId(keyIdBuf);
226176

227-
if (isAKID)
177+
switch (keyIdType)
228178
{
179+
case KeyIdType::kAKID:
229180
ReturnErrorOnFailure(ExtractAKIDFromX509Cert(certDer, keyId));
230-
}
231-
else
232-
{
181+
break;
182+
183+
case KeyIdType::kSKID:
233184
ReturnErrorOnFailure(ExtractSKIDFromX509Cert(certDer, keyId));
185+
break;
186+
187+
default:
188+
return CHIP_ERROR_INVALID_ARGUMENT;
234189
}
235190

236191
return BytesToHexStr(keyId, outKeyIDHexStr);
237192
}
238193

239-
CHIP_ERROR TestDACRevocationDelegateImpl::GetAKIDHexStr(const ByteSpan & certDer, MutableCharSpan & outAKIDHexStr)
194+
CHIP_ERROR TestDACRevocationDelegateImpl::GetAKIDHexStr(const ByteSpan & certDer, std::string & outAKIDHexStr)
240195
{
241-
return GetKeyIDHexStr(certDer, outAKIDHexStr, true);
196+
return GetKeyIDHexStr(certDer, outAKIDHexStr, KeyIdType::kAKID);
242197
}
243198

244-
CHIP_ERROR TestDACRevocationDelegateImpl::GetSKIDHexStr(const ByteSpan & certDer, MutableCharSpan & outSKIDHexStr)
199+
CHIP_ERROR TestDACRevocationDelegateImpl::GetSKIDHexStr(const ByteSpan & certDer, std::string & outSKIDHexStr)
245200
{
246-
return GetKeyIDHexStr(certDer, outSKIDHexStr, false /* isAKID */);
201+
return GetKeyIDHexStr(certDer, outSKIDHexStr, KeyIdType::kSKID);
247202
}
248203

249-
CHIP_ERROR TestDACRevocationDelegateImpl::GetSerialNumberHexStr(const ByteSpan & certDer, MutableCharSpan & outSerialNumberHexStr)
204+
CHIP_ERROR TestDACRevocationDelegateImpl::GetSerialNumberHexStr(const ByteSpan & certDer, std::string & outSerialNumberHexStr)
250205
{
251206
uint8_t serialNumberBuf[kMaxCertificateSerialNumberLength] = { 0 };
252207
MutableByteSpan serialNumber(serialNumberBuf);
@@ -255,50 +210,55 @@ CHIP_ERROR TestDACRevocationDelegateImpl::GetSerialNumberHexStr(const ByteSpan &
255210
return BytesToHexStr(serialNumber, outSerialNumberHexStr);
256211
}
257212

258-
CHIP_ERROR TestDACRevocationDelegateImpl::GetRDNBase64Str(const ByteSpan & certDer, MutableCharSpan & outRDNBase64String,
259-
bool isIssuer)
213+
CHIP_ERROR TestDACRevocationDelegateImpl::GetRDNBase64Str(const ByteSpan & certDer, std::string & outRDNBase64String,
214+
RDNType rdnType)
260215
{
261216
uint8_t rdnBuf[kMaxCertificateDistinguishedNameLength] = { 0 };
262217
MutableByteSpan rdn(rdnBuf);
263218

264-
if (isIssuer)
219+
switch (rdnType)
265220
{
221+
case RDNType::kIssuer:
266222
ReturnErrorOnFailure(ExtractIssuerFromX509Cert(certDer, rdn));
267-
}
268-
else
269-
{
223+
break;
224+
225+
case RDNType::kSubject:
270226
ReturnErrorOnFailure(ExtractSubjectFromX509Cert(certDer, rdn));
227+
break;
228+
229+
default:
230+
return CHIP_ERROR_INVALID_ARGUMENT;
271231
}
272232

273-
VerifyOrReturnError(outRDNBase64String.size() >= BASE64_ENCODED_LEN(rdn.size()), CHIP_ERROR_BUFFER_TOO_SMALL);
233+
// calculate the b64 length needed
234+
size_t b64LenNeeded = BASE64_ENCODED_LEN(rdn.size());
235+
236+
// Ensure string has enough capacity for base64 encoded data
237+
outRDNBase64String.resize(b64LenNeeded);
238+
239+
uint16_t encodedLen = Base64Encode(rdn.data(), static_cast<uint16_t>(rdn.size()), &outRDNBase64String[0]);
240+
outRDNBase64String.resize(encodedLen);
274241

275-
uint16_t encodedLen = Base64Encode(rdn.data(), static_cast<uint16_t>(rdn.size()), outRDNBase64String.data());
276-
outRDNBase64String.reduce_size(encodedLen);
277242
return CHIP_NO_ERROR;
278243
}
279244

280-
CHIP_ERROR TestDACRevocationDelegateImpl::GetIssuerNameBase64Str(const ByteSpan & certDer,
281-
MutableCharSpan & outIssuerNameBase64String)
245+
CHIP_ERROR TestDACRevocationDelegateImpl::GetIssuerNameBase64Str(const ByteSpan & certDer, std::string & outIssuerNameBase64String)
282246
{
283-
return GetRDNBase64Str(certDer, outIssuerNameBase64String, true /* isIssuer */);
247+
return GetRDNBase64Str(certDer, outIssuerNameBase64String, RDNType::kIssuer);
284248
}
285249

286250
CHIP_ERROR TestDACRevocationDelegateImpl::GetSubjectNameBase64Str(const ByteSpan & certDer,
287-
MutableCharSpan & outSubjectNameBase64String)
251+
std::string & outSubjectNameBase64String)
288252
{
289-
return GetRDNBase64Str(certDer, outSubjectNameBase64String, false /* isIssuer */);
253+
return GetRDNBase64Str(certDer, outSubjectNameBase64String, RDNType::kSubject);
290254
}
291255

292256
// @param certDer Certificate, in DER format, to check for revocation
293257
bool TestDACRevocationDelegateImpl::IsCertificateRevoked(const ByteSpan & certDer)
294258
{
295-
char issuerNameBuffer[kMaxIssuerBase64Len] = { 0 };
296-
char serialNumberHexStrBuffer[2 * kMaxCertificateSerialNumberLength] = { 0 };
297-
char akidHexStrBuffer[2 * kAuthorityKeyIdentifierLength] = { 0 };
298-
299-
MutableCharSpan issuerName(issuerNameBuffer);
300-
MutableCharSpan serialNumber(serialNumberHexStrBuffer);
301-
MutableCharSpan akid(akidHexStrBuffer);
259+
std::string serialNumber;
260+
std::string akid;
261+
std::string issuerName;
302262

303263
VerifyOrReturnValue(CHIP_NO_ERROR == GetIssuerNameBase64Str(certDer, issuerName), false);
304264
ChipLogDetail(NotSpecified, "Issuer: %.*s", static_cast<int>(issuerName.size()), issuerName.data());

src/credentials/attestation_verifier/TestDACRevocationDelegateImpl.h

+21-11
Original file line numberDiff line numberDiff line change
@@ -53,22 +53,32 @@ class TestDACRevocationDelegateImpl : public DeviceAttestationRevocationDelegate
5353
void ClearDeviceAttestationRevocationSetPath();
5454

5555
private:
56-
bool CrossValidateCert(const Json::Value & revokedSet, const std::string & akIdHexStr, const std::string & issuerNameBase64Str);
56+
enum class KeyIdType : uint8_t
57+
{
58+
kSKID = 0,
59+
kAKID = 1,
60+
};
61+
62+
enum class RDNType : uint8_t
63+
{
64+
kIssuer = 0,
65+
kSubject = 1,
66+
};
5767

58-
CHIP_ERROR GetKeyIDHexStr(const ByteSpan & certDer, MutableCharSpan & outKeyIDHexStr, bool isAKID);
59-
CHIP_ERROR GetAKIDHexStr(const ByteSpan & certDer, MutableCharSpan & outAKIDHexStr);
60-
CHIP_ERROR GetSKIDHexStr(const ByteSpan & certDer, MutableCharSpan & outSKIDHexStr);
68+
bool CrossValidateCert(const Json::Value & revokedSet, const std::string & akIdHexStr, const std::string & issuerNameBase64Str);
6169

62-
CHIP_ERROR GetSerialNumberHexStr(const ByteSpan & certDer, MutableCharSpan & outSerialNumberHexStr);
70+
CHIP_ERROR GetKeyIDHexStr(const ByteSpan & certDer, std::string & outKeyIDHexStr, KeyIdType keyIdType);
71+
CHIP_ERROR GetAKIDHexStr(const ByteSpan & certDer, std::string & outAKIDHexStr);
72+
CHIP_ERROR GetSKIDHexStr(const ByteSpan & certDer, std::string & outSKIDHexStr);
6373

64-
CHIP_ERROR GetRDNBase64Str(const ByteSpan & certDer, MutableCharSpan & outRDNBase64String, bool isIssuer);
65-
CHIP_ERROR GetIssuerNameBase64Str(const ByteSpan & certDer, MutableCharSpan & outIssuerNameBase64String);
66-
CHIP_ERROR GetSubjectNameBase64Str(const ByteSpan & certDer, MutableCharSpan & outSubjectNameBase64String);
74+
CHIP_ERROR GetSerialNumberHexStr(const ByteSpan & certDer, std::string & outSerialNumberHexStr);
6775

68-
CHIP_ERROR GetSubjectAndKeyIdFromPEMCert(const std::string & certPEM, std::string & outSubject, std::string & outKeyId);
76+
CHIP_ERROR GetRDNBase64Str(const ByteSpan & certDer, std::string & outRDNBase64String, RDNType rdnType);
77+
CHIP_ERROR GetIssuerNameBase64Str(const ByteSpan & certDer, std::string & outIssuerNameBase64String);
78+
CHIP_ERROR GetSubjectNameBase64Str(const ByteSpan & certDer, std::string & outSubjectNameBase64String);
6979

70-
bool IsEntryInRevocationSet(const CharSpan & akidHexStr, const CharSpan & issuerNameBase64Str,
71-
const CharSpan & serialNumberHexStr);
80+
bool IsEntryInRevocationSet(const std::string & akidHexStr, const std::string & issuerNameBase64Str,
81+
const std::string & serialNumberHexStr);
7282

7383
bool IsCertificateRevoked(const ByteSpan & certDer);
7484

0 commit comments

Comments
 (0)