Skip to content

Commit 1793868

Browse files
tcarmelveilleuxrestyled-commitsbzbarsky-apple
authored andcommitted
Remove NOCSR Request size limits and fix ReadDerLength bugs (#28899)
* Increase available size for NOCSR Request - Some implementers ran out of space when adding even a single extension. - 400 is the same size as the max compressed cert format, which we use many places. The total increase is thus small, for a transient buffer. - ReadDerLength was private and insufficiently tested. Some issues were found by @bluebin14. Testing done: - Existing test coverage passes - Added exhaustive unit tests for ReadDerLength, covering all failing cases, and expanding it usability beyond 8 bits of range. * Restyled by clang-format * Replace Max CSR size with a Min CSR size. - Works in every situation. - Keeps existing constant as deprecated since main legacy usage will still work. - Remove a needless verification of size that was the root cause of issues with the constant before. * Update src/crypto/CHIPCryptoPAL.cpp Co-authored-by: Boris Zbarsky <bzbarsky@apple.com> * Restyled by clang-format --------- Co-authored-by: Restyled.io <commits@restyled.io> Co-authored-by: Boris Zbarsky <bzbarsky@apple.com>
1 parent 6275662 commit 1793868

15 files changed

+257
-92
lines changed

src/app/clusters/operational-credentials-server/operational-credentials-server.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -1038,7 +1038,7 @@ bool emberAfOperationalCredentialsClusterCSRRequestCallback(app::CommandHandler
10381038

10391039
// Prepare NOCSRElements structure
10401040
{
1041-
constexpr size_t csrLength = Crypto::kMAX_CSR_Length;
1041+
constexpr size_t csrLength = Crypto::kMIN_CSR_Buffer_Size;
10421042
size_t nocsrLengthEstimate = 0;
10431043
ByteSpan kNoVendorReserved;
10441044
Platform::ScopedMemoryBuffer<uint8_t> csr;
@@ -1060,7 +1060,7 @@ bool emberAfOperationalCredentialsClusterCSRRequestCallback(app::CommandHandler
10601060

10611061
err = fabricTable.AllocatePendingOperationalKey(fabricIndexForCsr, csrSpan);
10621062

1063-
if (csrSpan.size() > Crypto::kMAX_CSR_Length)
1063+
if (csrSpan.size() > csrLength)
10641064
{
10651065
err = CHIP_ERROR_INTERNAL;
10661066
}

src/credentials/FabricTable.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1540,7 +1540,7 @@ CHIP_ERROR FabricTable::AllocatePendingOperationalKey(Optional<FabricIndex> fabr
15401540
// We can only allocate a pending key if no pending state (NOC, ICAC) already present,
15411541
// since there can only be one pending state per fail-safe.
15421542
VerifyOrReturnError(!mStateFlags.Has(StateFlags::kIsPendingFabricDataPresent), CHIP_ERROR_INCORRECT_STATE);
1543-
VerifyOrReturnError(outputCsr.size() >= Crypto::kMAX_CSR_Length, CHIP_ERROR_BUFFER_TOO_SMALL);
1543+
VerifyOrReturnError(outputCsr.size() >= Crypto::kMIN_CSR_Buffer_Size, CHIP_ERROR_BUFFER_TOO_SMALL);
15441544

15451545
EnsureNextAvailableFabricIndexUpdated();
15461546
FabricIndex fabricIndexToUse = kUndefinedFabricIndex;

src/credentials/FabricTable.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -712,7 +712,7 @@ class DLL_EXPORT FabricTable
712712
* @param fabricIndex - Existing FabricIndex for which a new keypair must be made available. If it
713713
* doesn't have a value, the key will be marked pending for the next available
714714
* fabric index that would apply for `AddNewFabric`.
715-
* @param outputCsr - Buffer to contain the CSR. Must be at least `kMAX_CSR_Length` large.
715+
* @param outputCsr - Buffer to contain the CSR. Must be at least `kMIN_CSR_Buffer_Size` large.
716716
*
717717
* @retval CHIP_NO_ERROR on success
718718
* @retval CHIP_ERROR_BUFFER_TOO_SMALL if `outputCsr` buffer is too small

src/credentials/tests/TestFabricTable.cpp

+21-21
Original file line numberDiff line numberDiff line change
@@ -690,7 +690,7 @@ void TestBasicAddNocUpdateNocFlow(nlTestSuite * inSuite, void * inContext)
690690
FabricId fabricId = 44;
691691
NodeId nodeId = 999;
692692

693-
uint8_t csrBuf[chip::Crypto::kMAX_CSR_Length];
693+
uint8_t csrBuf[chip::Crypto::kMIN_CSR_Buffer_Size];
694694
MutableByteSpan csrSpan{ csrBuf };
695695
NL_TEST_ASSERT_SUCCESS(inSuite, fabricTable.AllocatePendingOperationalKey(chip::NullOptional, csrSpan));
696696

@@ -810,7 +810,7 @@ void TestBasicAddNocUpdateNocFlow(nlTestSuite * inSuite, void * inContext)
810810
NodeId nodeId = 1000;
811811
FabricIndex fabricIndex = 2;
812812

813-
uint8_t csrBuf[chip::Crypto::kMAX_CSR_Length];
813+
uint8_t csrBuf[chip::Crypto::kMIN_CSR_Buffer_Size];
814814
MutableByteSpan csrSpan{ csrBuf };
815815

816816
// Make sure to tag fabric index to pending opkey: otherwise the UpdateNOC fails
@@ -1070,7 +1070,7 @@ void TestAddMultipleSameRootDifferentFabricId(nlTestSuite * inSuite, void * inCo
10701070
FabricId fabricId = 1111;
10711071
NodeId nodeId = 55;
10721072

1073-
uint8_t csrBuf[chip::Crypto::kMAX_CSR_Length];
1073+
uint8_t csrBuf[chip::Crypto::kMIN_CSR_Buffer_Size];
10741074
MutableByteSpan csrSpan{ csrBuf };
10751075
NL_TEST_ASSERT_SUCCESS(inSuite, fabricTable.AllocatePendingOperationalKey(chip::NullOptional, csrSpan));
10761076

@@ -1113,7 +1113,7 @@ void TestAddMultipleSameRootDifferentFabricId(nlTestSuite * inSuite, void * inCo
11131113
FabricId fabricId = 2222;
11141114
NodeId nodeId = 66;
11151115

1116-
uint8_t csrBuf[chip::Crypto::kMAX_CSR_Length];
1116+
uint8_t csrBuf[chip::Crypto::kMIN_CSR_Buffer_Size];
11171117
MutableByteSpan csrSpan{ csrBuf };
11181118
NL_TEST_ASSERT_SUCCESS(inSuite, fabricTable.AllocatePendingOperationalKey(chip::NullOptional, csrSpan));
11191119

@@ -1177,7 +1177,7 @@ void TestAddMultipleSameFabricIdDifferentRoot(nlTestSuite * inSuite, void * inCo
11771177
FabricId fabricId = 1111;
11781178
NodeId nodeId = 55;
11791179

1180-
uint8_t csrBuf[chip::Crypto::kMAX_CSR_Length];
1180+
uint8_t csrBuf[chip::Crypto::kMIN_CSR_Buffer_Size];
11811181
MutableByteSpan csrSpan{ csrBuf };
11821182
NL_TEST_ASSERT_SUCCESS(inSuite, fabricTable.AllocatePendingOperationalKey(chip::NullOptional, csrSpan));
11831183

@@ -1220,7 +1220,7 @@ void TestAddMultipleSameFabricIdDifferentRoot(nlTestSuite * inSuite, void * inCo
12201220
FabricId fabricId = 1111;
12211221
NodeId nodeId = 66;
12221222

1223-
uint8_t csrBuf[chip::Crypto::kMAX_CSR_Length];
1223+
uint8_t csrBuf[chip::Crypto::kMIN_CSR_Buffer_Size];
12241224
MutableByteSpan csrSpan{ csrBuf };
12251225
NL_TEST_ASSERT_SUCCESS(inSuite, fabricTable.AllocatePendingOperationalKey(chip::NullOptional, csrSpan));
12261226

@@ -1302,7 +1302,7 @@ void TestPersistence(nlTestSuite * inSuite, void * inContext)
13021302
FabricId fabricId = 1111;
13031303
NodeId nodeId = 55;
13041304

1305-
uint8_t csrBuf[chip::Crypto::kMAX_CSR_Length];
1305+
uint8_t csrBuf[chip::Crypto::kMIN_CSR_Buffer_Size];
13061306
MutableByteSpan csrSpan{ csrBuf };
13071307
NL_TEST_ASSERT_SUCCESS(inSuite, fabricTable.AllocatePendingOperationalKey(chip::NullOptional, csrSpan));
13081308

@@ -1361,7 +1361,7 @@ void TestPersistence(nlTestSuite * inSuite, void * inContext)
13611361
FabricId fabricId = 2222;
13621362
NodeId nodeId = 66;
13631363

1364-
uint8_t csrBuf[chip::Crypto::kMAX_CSR_Length];
1364+
uint8_t csrBuf[chip::Crypto::kMIN_CSR_Buffer_Size];
13651365
MutableByteSpan csrSpan{ csrBuf };
13661366
NL_TEST_ASSERT_SUCCESS(inSuite, fabricTable.AllocatePendingOperationalKey(chip::NullOptional, csrSpan));
13671367

@@ -1614,7 +1614,7 @@ void TestAddNocFailSafe(nlTestSuite * inSuite, void * inContext)
16141614
FabricId fabricId = 11;
16151615
NodeId nodeId = 55;
16161616

1617-
uint8_t csrBuf[chip::Crypto::kMAX_CSR_Length];
1617+
uint8_t csrBuf[chip::Crypto::kMIN_CSR_Buffer_Size];
16181618
MutableByteSpan csrSpan{ csrBuf };
16191619
NL_TEST_ASSERT_SUCCESS(inSuite, fabricTable.AllocatePendingOperationalKey(chip::NullOptional, csrSpan));
16201620

@@ -1700,7 +1700,7 @@ void TestAddNocFailSafe(nlTestSuite * inSuite, void * inContext)
17001700
FabricId fabricId = 44;
17011701
NodeId nodeId = 999;
17021702

1703-
uint8_t csrBuf[chip::Crypto::kMAX_CSR_Length];
1703+
uint8_t csrBuf[chip::Crypto::kMIN_CSR_Buffer_Size];
17041704
MutableByteSpan csrSpan{ csrBuf };
17051705
NL_TEST_ASSERT_SUCCESS(inSuite, fabricTable.AllocatePendingOperationalKey(chip::NullOptional, csrSpan));
17061706

@@ -1846,7 +1846,7 @@ void TestUpdateNocFailSafe(nlTestSuite * inSuite, void * inContext)
18461846
FabricId fabricId = 44;
18471847
NodeId nodeId = 999;
18481848

1849-
uint8_t csrBuf[chip::Crypto::kMAX_CSR_Length];
1849+
uint8_t csrBuf[chip::Crypto::kMIN_CSR_Buffer_Size];
18501850
MutableByteSpan csrSpan{ csrBuf };
18511851
NL_TEST_ASSERT_SUCCESS(inSuite, fabricTable.AllocatePendingOperationalKey(chip::NullOptional, csrSpan));
18521852

@@ -1937,7 +1937,7 @@ void TestUpdateNocFailSafe(nlTestSuite * inSuite, void * inContext)
19371937
NodeId nodeId = 1000;
19381938
FabricIndex fabricIndex = 1;
19391939

1940-
uint8_t csrBuf[chip::Crypto::kMAX_CSR_Length];
1940+
uint8_t csrBuf[chip::Crypto::kMIN_CSR_Buffer_Size];
19411941
MutableByteSpan csrSpan{ csrBuf };
19421942

19431943
// Make sure to tag fabric index to pending opkey: otherwise the UpdateNOC fails
@@ -2049,7 +2049,7 @@ void TestUpdateNocFailSafe(nlTestSuite * inSuite, void * inContext)
20492049
NodeId nodeId = 1001;
20502050
FabricIndex fabricIndex = 1;
20512051

2052-
uint8_t csrBuf[chip::Crypto::kMAX_CSR_Length];
2052+
uint8_t csrBuf[chip::Crypto::kMIN_CSR_Buffer_Size];
20532053
MutableByteSpan csrSpan{ csrBuf };
20542054

20552055
// Make sure to tag fabric index to pending opkey: otherwise the UpdateNOC fails
@@ -2220,7 +2220,7 @@ void TestFabricLabelChange(nlTestSuite * inSuite, void * inContext)
22202220
FabricId fabricId = 1111;
22212221
NodeId nodeId = 55;
22222222

2223-
uint8_t csrBuf[chip::Crypto::kMAX_CSR_Length];
2223+
uint8_t csrBuf[chip::Crypto::kMIN_CSR_Buffer_Size];
22242224
MutableByteSpan csrSpan{ csrBuf };
22252225
NL_TEST_ASSERT_SUCCESS(inSuite, fabricTable.AllocatePendingOperationalKey(chip::NullOptional, csrSpan));
22262226

@@ -2291,7 +2291,7 @@ void TestFabricLabelChange(nlTestSuite * inSuite, void * inContext)
22912291
FabricId fabricId = 1111;
22922292
NodeId nodeId = 66; // Update node ID from 55 to 66
22932293

2294-
uint8_t csrBuf[chip::Crypto::kMAX_CSR_Length];
2294+
uint8_t csrBuf[chip::Crypto::kMIN_CSR_Buffer_Size];
22952295
MutableByteSpan csrSpan{ csrBuf };
22962296
NL_TEST_ASSERT_SUCCESS(inSuite,
22972297
fabricTable.AllocatePendingOperationalKey(chip::MakeOptional(static_cast<FabricIndex>(1)), csrSpan));
@@ -2449,7 +2449,7 @@ void TestAddNocRootCollision(nlTestSuite * inSuite, void * inContext)
24492449
FabricId fabricId = 1111;
24502450
NodeId nodeId = 55;
24512451

2452-
uint8_t csrBuf[chip::Crypto::kMAX_CSR_Length];
2452+
uint8_t csrBuf[chip::Crypto::kMIN_CSR_Buffer_Size];
24532453
MutableByteSpan csrSpan{ csrBuf };
24542454
NL_TEST_ASSERT_SUCCESS(inSuite, fabricTable.AllocatePendingOperationalKey(chip::NullOptional, csrSpan));
24552455

@@ -2502,7 +2502,7 @@ void TestAddNocRootCollision(nlTestSuite * inSuite, void * inContext)
25022502
FabricId fabricId = 1111;
25032503
NodeId nodeId = 55;
25042504

2505-
uint8_t csrBuf[chip::Crypto::kMAX_CSR_Length];
2505+
uint8_t csrBuf[chip::Crypto::kMIN_CSR_Buffer_Size];
25062506
MutableByteSpan csrSpan{ csrBuf };
25072507
NL_TEST_ASSERT_SUCCESS(inSuite, fabricTable.AllocatePendingOperationalKey(chip::NullOptional, csrSpan));
25082508

@@ -2556,7 +2556,7 @@ void TestAddNocRootCollision(nlTestSuite * inSuite, void * inContext)
25562556
FabricId fabricId = 2222;
25572557
NodeId nodeId = 55;
25582558

2559-
uint8_t csrBuf[chip::Crypto::kMAX_CSR_Length];
2559+
uint8_t csrBuf[chip::Crypto::kMIN_CSR_Buffer_Size];
25602560
MutableByteSpan csrSpan{ csrBuf };
25612561
NL_TEST_ASSERT_SUCCESS(inSuite, fabricTable.AllocatePendingOperationalKey(chip::NullOptional, csrSpan));
25622562

@@ -2629,7 +2629,7 @@ void TestInvalidChaining(nlTestSuite * inSuite, void * inContext)
26292629
FabricId fabricId = 1111;
26302630
NodeId nodeId = 55;
26312631

2632-
uint8_t csrBuf[chip::Crypto::kMAX_CSR_Length];
2632+
uint8_t csrBuf[chip::Crypto::kMIN_CSR_Buffer_Size];
26332633
MutableByteSpan csrSpan{ csrBuf };
26342634
NL_TEST_ASSERT_SUCCESS(inSuite, fabricTable.AllocatePendingOperationalKey(chip::NullOptional, csrSpan));
26352635

@@ -2816,7 +2816,7 @@ void TestCommitMarker(nlTestSuite * inSuite, void * inContext)
28162816
FabricId fabricId = 1111;
28172817
NodeId nodeId = 55;
28182818

2819-
uint8_t csrBuf[chip::Crypto::kMAX_CSR_Length];
2819+
uint8_t csrBuf[chip::Crypto::kMIN_CSR_Buffer_Size];
28202820
MutableByteSpan csrSpan{ csrBuf };
28212821
NL_TEST_ASSERT_SUCCESS(inSuite, fabricTable.AllocatePendingOperationalKey(chip::NullOptional, csrSpan));
28222822

@@ -2882,7 +2882,7 @@ void TestCommitMarker(nlTestSuite * inSuite, void * inContext)
28822882
FabricId fabricId = 2222;
28832883
NodeId nodeId = 66;
28842884

2885-
uint8_t csrBuf[chip::Crypto::kMAX_CSR_Length];
2885+
uint8_t csrBuf[chip::Crypto::kMIN_CSR_Buffer_Size];
28862886
MutableByteSpan csrSpan{ csrBuf };
28872887
NL_TEST_ASSERT_SUCCESS(inSuite, fabricTable.AllocatePendingOperationalKey(chip::NullOptional, csrSpan));
28882888

src/crypto/CHIPCryptoPAL.cpp

+59-42
Original file line numberDiff line numberDiff line change
@@ -44,39 +44,6 @@ constexpr uint8_t kIntegerTag = 0x02u;
4444
constexpr uint8_t kSeqTag = 0x30u;
4545
constexpr size_t kMinSequenceOverhead = 1 /* tag */ + 1 /* length */ + 1 /* actual data or second length byte*/;
4646

47-
/**
48-
* @brief Utility to read a length field after a tag in a DER-encoded stream.
49-
* @param[in] reader Reader instance from which the input will be read
50-
* @param[out] length Length of the following element read from the stream
51-
* @return CHIP_ERROR_INVALID_ARGUMENT or CHIP_ERROR_BUFFER_TOO_SMALL on error, CHIP_NO_ERROR otherwise
52-
*/
53-
CHIP_ERROR ReadDerLength(Reader & reader, uint8_t & length)
54-
{
55-
length = 0;
56-
57-
uint8_t cur_byte = 0;
58-
ReturnErrorOnFailure(reader.Read8(&cur_byte).StatusCode());
59-
60-
if ((cur_byte & (1u << 7)) == 0)
61-
{
62-
// 7 bit length, the rest of the byte is the length.
63-
length = cur_byte & 0x7Fu;
64-
return CHIP_NO_ERROR;
65-
}
66-
67-
// Did not early return: > 7 bit length, the number of bytes of the length is provided next.
68-
uint8_t length_bytes = cur_byte & 0x7Fu;
69-
70-
if ((length_bytes > 1) || !reader.HasAtLeast(length_bytes))
71-
{
72-
// We only support lengths of 0..255 over 2 bytes
73-
return CHIP_ERROR_INVALID_ARGUMENT;
74-
}
75-
76-
// Next byte has length 0..255.
77-
return reader.Read8(&length).StatusCode();
78-
}
79-
8047
/**
8148
* @brief Utility to convert DER-encoded INTEGER into a raw integer buffer in big-endian order
8249
* with leading zeroes if the output buffer is larger than needed.
@@ -94,8 +61,8 @@ CHIP_ERROR ReadDerUnsignedIntegerIntoRaw(Reader & reader, MutableByteSpan raw_in
9461
VerifyOrReturnError(cur_byte == kIntegerTag, CHIP_ERROR_INVALID_ARGUMENT);
9562

9663
// Read the length
97-
uint8_t integer_len = 0;
98-
ReturnErrorOnFailure(ReadDerLength(reader, integer_len));
64+
size_t integer_len = 0;
65+
ReturnErrorOnFailure(chip::Crypto::ReadDerLength(reader, integer_len));
9966

10067
// Clear the destination buffer, so we can blit the unsigned value into place
10168
memset(raw_integer_out.data(), 0, raw_integer_out.size());
@@ -580,6 +547,55 @@ CHIP_ERROR Spake2pVerifier::ComputeWS(uint32_t pbkdf2IterCount, const ByteSpan &
580547
pbkdf2IterCount, ws_len, ws);
581548
}
582549

550+
CHIP_ERROR ReadDerLength(Reader & reader, size_t & length)
551+
{
552+
length = 0;
553+
554+
uint8_t cur_byte = 0;
555+
ReturnErrorOnFailure(reader.Read8(&cur_byte).StatusCode());
556+
557+
if ((cur_byte & (1u << 7)) == 0)
558+
{
559+
// 7 bit length, the rest of the byte is the length.
560+
length = cur_byte & 0x7Fu;
561+
return CHIP_NO_ERROR;
562+
}
563+
564+
CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT;
565+
566+
// Did not early return: > 7 bit length, the number of bytes of the length is provided next.
567+
uint8_t length_bytes = cur_byte & 0x7Fu;
568+
VerifyOrReturnError((length_bytes >= 1) && (length_bytes <= sizeof(size_t)), CHIP_ERROR_INVALID_ARGUMENT);
569+
VerifyOrReturnError(reader.HasAtLeast(length_bytes), CHIP_ERROR_BUFFER_TOO_SMALL);
570+
571+
for (uint8_t i = 0; i < length_bytes; i++)
572+
{
573+
uint8_t cur_length_byte = 0;
574+
err = reader.Read8(&cur_length_byte).StatusCode();
575+
if (err != CHIP_NO_ERROR)
576+
break;
577+
578+
// Cannot have zero padding on multi-byte lengths in DER, so first
579+
// byte must always be > 0.
580+
if ((i == 0) && (cur_length_byte == 0))
581+
{
582+
return CHIP_ERROR_INVALID_ARGUMENT;
583+
}
584+
585+
length <<= 8;
586+
length |= cur_length_byte;
587+
}
588+
589+
// Single-byte long length cannot be < 128: DER always encodes on smallest size
590+
// possible, so length zero should have been a single byte short length.
591+
if ((length_bytes == 1) && (length < 128))
592+
{
593+
return CHIP_ERROR_INVALID_ARGUMENT;
594+
}
595+
596+
return CHIP_NO_ERROR;
597+
}
598+
583599
CHIP_ERROR ConvertIntegerRawToDerWithoutTag(const ByteSpan & raw_integer, MutableByteSpan & out_der_integer)
584600
{
585601
return ConvertIntegerRawToDerInternal(raw_integer, out_der_integer, /* include_tag_and_length = */ false);
@@ -672,7 +688,7 @@ CHIP_ERROR EcdsaAsn1SignatureToRaw(size_t fe_length_bytes, const ByteSpan & asn1
672688
VerifyOrReturnError(tag == kSeqTag, CHIP_ERROR_INVALID_ARGUMENT);
673689

674690
// Read length of sequence
675-
uint8_t tag_len = 0;
691+
size_t tag_len = 0;
676692
ReturnErrorOnFailure(ReadDerLength(reader, tag_len));
677693

678694
// Length of sequence must match what is left of signature
@@ -985,7 +1001,7 @@ static CHIP_ERROR GenerateCertificationRequestInformation(ASN1Writer & writer, c
9851001
CHIP_ERROR GenerateCertificateSigningRequest(const P256Keypair * keypair, MutableByteSpan & csr_span)
9861002
{
9871003
VerifyOrReturnError(keypair != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
988-
VerifyOrReturnError(csr_span.size() >= kMAX_CSR_Length, CHIP_ERROR_BUFFER_TOO_SMALL);
1004+
VerifyOrReturnError(csr_span.size() >= kMIN_CSR_Buffer_Size, CHIP_ERROR_BUFFER_TOO_SMALL);
9891005

9901006
// First pass: Generate the CertificatioRequestInformation inner
9911007
// encoding one time, to sign it, before re-generating it within the
@@ -1092,8 +1108,10 @@ CHIP_ERROR GenerateCertificateSigningRequest(const P256Keypair * keypair, Mutabl
10921108

10931109
CHIP_ERROR VerifyCertificateSigningRequestFormat(const uint8_t * csr, size_t csr_length)
10941110
{
1095-
// Ensure we have enough size to validate header
1096-
VerifyOrReturnError((csr_length >= 16) && (csr_length <= kMAX_CSR_Length), CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
1111+
// Ensure we have enough size to validate header, and that our assumptions are met
1112+
// for some tag computations below. A csr_length > 65535 would never be seen in
1113+
// practice.
1114+
VerifyOrReturnError((csr_length >= 16) && (csr_length <= 65535), CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
10971115

10981116
Reader reader(csr, csr_length);
10991117

@@ -1102,12 +1120,11 @@ CHIP_ERROR VerifyCertificateSigningRequestFormat(const uint8_t * csr, size_t csr
11021120
ReturnErrorOnFailure(reader.Read8(&seq_header).StatusCode());
11031121
VerifyOrReturnError(seq_header == kSeqTag, CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
11041122

1105-
uint8_t seq_length = 0;
1123+
size_t seq_length = 0;
11061124
VerifyOrReturnError(ReadDerLength(reader, seq_length) == CHIP_NO_ERROR, CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
1107-
11081125
// Ensure that outer length matches sequence length + tag overhead, otherwise
11091126
// we have trailing garbage
1110-
size_t header_overhead = (seq_length <= 127) ? 2 : 3;
1127+
size_t header_overhead = (seq_length <= 127) ? 2 : ((seq_length <= 255) ? 3 : 4);
11111128
VerifyOrReturnError(csr_length == (seq_length + header_overhead), CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
11121129

11131130
return CHIP_NO_ERROR;

0 commit comments

Comments
 (0)