Skip to content

Commit 7e2103b

Browse files
DemiMarieashishverma2691
authored andcommitted
fix(auth): avoid out-of-bounds read in auth_nvctr()
auth_nvctr() does not check that the buffer provided is long enough to hold an ASN.1 INTEGER, or even that the buffer is non-empty. Since auth_nvctr() will only ever read 6 bytes, it is possible to read up to 6 bytes past the end of the buffer. This out-of-bounds read turns out to be harmless. The only caller of auth_nvctr() always passes a pointer into an X.509 TBSCertificate, and all in-tree chains of trust require that the certificate’s signature has already been validated. This means that the signature algorithm identifier is at least 4 bytes and the signature itself more than that. Therefore, the data read will be from the certificate itself. Even if the certificate signature has not been validated, an out-of-bounds read is still not possible. Since there are at least two bytes (tag and length) in both the signature algorithm ID and the signature itself, an out-of-bounds read would require that the tag byte of the signature algorithm ID would need to be either the tag or length byte of the DER-encoded nonvolatile counter. However, this byte must be (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) (0x30), which is greater than 4 and not equal to MBEDTLS_ASN1_INTEGER (2). Therefore, auth_nvctr() will error out before reading the integer itself, preventing an out-of-bounds read. Change-Id: Ibdf1af702fbeb98a94c0c96456ebddd3d392ad44 Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
1 parent 4f7da6c commit 7e2103b

File tree

1 file changed

+14
-6
lines changed

1 file changed

+14
-6
lines changed

drivers/auth/auth_mod.c

+14-6
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ static int auth_nvctr(const auth_method_param_nv_ctr_t *param,
243243
unsigned int *cert_nv_ctr,
244244
bool *need_nv_ctr_upgrade)
245245
{
246-
char *p;
246+
unsigned char *p;
247247
void *data_ptr = NULL;
248248
unsigned int data_len, len, i;
249249
unsigned int plat_nv_ctr;
@@ -258,16 +258,24 @@ static int auth_nvctr(const auth_method_param_nv_ctr_t *param,
258258

259259
/* Parse the DER encoded integer */
260260
assert(data_ptr);
261-
p = (char *)data_ptr;
262-
if (*p != ASN1_INTEGER) {
261+
p = (unsigned char *)data_ptr;
262+
263+
/*
264+
* Integers must be at least 3 bytes: 1 for tag, 1 for length, and 1
265+
* for value. The first byte (tag) must be ASN1_INTEGER.
266+
*/
267+
if ((data_len < 3) || (*p != ASN1_INTEGER)) {
263268
/* Invalid ASN.1 integer */
264269
return 1;
265270
}
266271
p++;
267272

268-
/* NV-counters are unsigned integers up to 32-bit */
269-
len = (unsigned int)(*p & 0x7f);
270-
if ((*p & 0x80) || (len > 4)) {
273+
/*
274+
* NV-counters are unsigned integers up to 31 bits. Trailing
275+
* padding is not allowed.
276+
*/
277+
len = (unsigned int)*p;
278+
if ((len > 4) || (data_len - 2 != len)) {
271279
return 1;
272280
}
273281
p++;

0 commit comments

Comments
 (0)