libkmipclient: Detect possible length overflow situations

A deeply nested or pathologically large KMIP node tree crafted by a
malicious server can wrap the length calculation around to a small
value. Detect this and return an error in this case.

Assisted-by: IBM Bob:2.0.0
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Finn Callies <fcallies@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
Ingo Franzki
2026-07-01 08:38:30 +02:00
committed by Jan Höppner
parent 66581d57f3
commit 7fd2421a2c
2 changed files with 17 additions and 6 deletions

View File

@@ -282,7 +282,7 @@ out:
static int kmip_node_get_length(struct kmip_node *node, size_t *length)
{
struct kmip_node *element;
size_t len;
size_t len, prev_len;
int rc;
if (node == NULL || length == NULL)
@@ -297,10 +297,13 @@ static int kmip_node_get_length(struct kmip_node *node, size_t *length)
if (rc != 0)
return rc;
prev_len = *length;
*length += KMIP_TTLV_HEADER_LENGTH + len;
if ((len % KMIP_TTLV_BLOCK_LENGTH) != 0)
*length += KMIP_TTLV_BLOCK_LENGTH -
(len % KMIP_TTLV_BLOCK_LENGTH);
if (*length < prev_len)
return -EOVERFLOW;
element = element->next;
}

View File

@@ -225,14 +225,18 @@ int kmip_parse_bignum(const char *str, bool has_prefix, BIGNUM **bn)
int kmip_format_bignum(const BIGNUM *bn, bool prefix, char **str)
{
unsigned char *buf;
uint32_t len;
uint32_t len, prev_len;
int rc;
len = kmip_encode_bignum_length(bn);
/* BIG INTEGERS must be a multiple of 8 bytes long */
if ((len % KMIP_BIG_INTEGER_BLOCK_LENGTH) != 0)
if ((len % KMIP_BIG_INTEGER_BLOCK_LENGTH) != 0) {
prev_len = len;
len += KMIP_BIG_INTEGER_BLOCK_LENGTH -
(len % KMIP_BIG_INTEGER_BLOCK_LENGTH);
if (len < prev_len)
return -EOVERFLOW;
}
buf = malloc(len);
if (buf == NULL)
@@ -407,10 +411,10 @@ int kmip_parse_mask(enum kmip_tag tag, const char *str, char separator,
return rc;
}
static int kmip_append_string(char **str, int *str_len, char separator,
static int kmip_append_string(char **str, size_t *str_len, char separator,
const char *append)
{
int new_len;
size_t new_len;
char *tmp;
if (str == NULL || str_len == NULL)
@@ -427,6 +431,9 @@ static int kmip_append_string(char **str, int *str_len, char separator,
if (append != NULL)
new_len += strlen(append);
if (new_len < *str_len)
return -EOVERFLOW;
tmp = realloc(*str, new_len);
if (tmp == NULL)
return -ENOMEM;
@@ -451,8 +458,9 @@ int kmip_format_mask(enum kmip_tag tag, int32_t value, char separator,
char **str)
{
const struct kmip_enum *info;
int rc = 0, i, s_len = 0;
char *s = NULL, *tmp;
size_t s_len = 0;
int rc = 0, i;
info = kmip_enum_info_by_tag(tag);
if (info == NULL || value == 0)