From da534de75edd1b3628a28908d30b0efbaa01be09 Mon Sep 17 00:00:00 2001 From: Jon Shallow Date: Thu, 4 Sep 2025 13:26:06 +0100 Subject: [PATCH] OSCORE: Fix OSCORE configuration file parsing issue With a large boolean parameter value, (longer than "false"), memory would be read past the "true" or "false" string boundaries in the ".rodata" section when doing a memcmp(), potetially causing the application to crash when calling coap_new_oscore_conf() with a specially crafted configuration file. It also can provide a mechanism to determine the byte values following the "true" or "false" string boundaries which could lead to accessing sensitive information. The standard libcoap library does not have defined keys or certificates. This can only be done by a specially crafted local application. Discovered by SecMate (https://secmate.dev). Now fixed. --- src/coap_oscore.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/coap_oscore.c b/src/coap_oscore.c index 964d8e21..f8fd6ffb 100644 --- a/src/coap_oscore.c +++ b/src/coap_oscore.c @@ -1758,6 +1758,7 @@ get_split_entry(const char **start, const char *kend; const char *split; size_t i; + size_t len; retry: kend = end = memchr(begin, '\n', size); @@ -1834,9 +1835,10 @@ retry: value->u.value_str.length = end - begin; break; case COAP_ENC_BOOL: - if (memcmp("true", begin, end - begin) == 0) + len = (size_t)(end - begin); + if (len == 4 && memcmp("true", begin, len) == 0) value->u.value_int = 1; - else if (memcmp("false", begin, end - begin) == 0) + else if (len == 5 && memcmp("false", begin, len) == 0) value->u.value_int = 0; else goto bad_entry; @@ -1851,7 +1853,7 @@ bad_entry: coap_log_warn("oscore_conf: Unrecognized configuration entry '%.*s'\n", (int)(end - begin), begin); - return 0; + return -1; } #undef CONFIG_ENTRY @@ -1923,6 +1925,7 @@ coap_parse_oscore_conf_mem(coap_str_const_t conf_mem) { coap_str_const_t keyword; oscore_value_t value; coap_oscore_conf_t *oscore_conf; + int split_ok = -1; oscore_conf = coap_malloc_type(COAP_STRING, sizeof(coap_oscore_conf_t)); if (oscore_conf == NULL) @@ -1941,7 +1944,7 @@ coap_parse_oscore_conf_mem(coap_str_const_t conf_mem) { oscore_conf->break_recipient_key = 0; while (end > start && - get_split_entry(&start, end - start, &keyword, &value)) { + (split_ok = get_split_entry(&start, end - start, &keyword, &value)) > 0) { size_t i; size_t j; @@ -2027,6 +2030,8 @@ coap_parse_oscore_conf_mem(coap_str_const_t conf_mem) { goto error; } } + if (split_ok == -1) + goto error; if (!oscore_conf->master_secret) { coap_log_warn("oscore_conf: master_secret not defined\n"); goto error;