3
0
mirror of https://git.kernel.org/pub/scm/network/wireless/iwd.git synced 2024-11-25 17:59:25 +01:00

dpp: fix data corruption around prf_plus() call

Without the change test-dpp fails on aarch64-linux as:

    $ unit/test-dpp
    TEST: DPP test responder-only key derivation
    TEST: DPP test mutual key derivation
    TEST: DPP test PKEX key derivation
    test-dpp: unit/test-dpp.c:514: test_pkex_key_derivation: Assertion `!memcmp(tmp, __tmp, 32)' failed.

This happens due to int/size_t type mismatch passed to vararg
parameters to prf_plus():

    bool prf_plus(enum l_checksum_type type, const void *key, size_t key_len,
               void *out, size_t out_len,
               size_t n_extra, ...)
    {
       // ...
       va_start(va, n_extra);

       for (i = 0; i < n_extra; i++) {
               iov[i + 1].iov_base = va_arg(va, void *);
               iov[i + 1].iov_len = va_arg(va, size_t);
       // ...

Note that varargs here could only be a sequence of `void *` / `size_t`
values.

But in src/dpp-util.c `iwd` attempted to pass `int` there:

   prf_plus(sha, prk, bytes, z_out, bytes, 5,
            mac_i, 6, // <- here
            mac_r, 6, // <- and here
            m_x, bytes,
            n_x, bytes,
            key, strlen(key));

aarch64 stores only 32-bit value part of the register:

    mov     w7, #0x6
    str     w7, [sp, #...]

and loads full 64-bit form of the register:

    ldr     x3, [x3]

As a result higher bits of `iov[].iov_len` contain unexpected values and
sendmsg sends a lot more data than expected to the kernel.

The change fixes test-dpp test for me.

While at it fixed obvious `int` / `size_t` mismatch in src/erp.c.

Fixes: 6320d6db0f ("crypto: remove label from prf_plus, instead use va_args")
This commit is contained in:
Sergei Trofimovich 2023-12-16 21:16:33 +00:00 committed by Denis Kenzior
parent 5af1fe34b6
commit 688d277008
2 changed files with 4 additions and 3 deletions

View File

@ -1376,8 +1376,9 @@ bool dpp_derive_z(const uint8_t *mac_i, const uint8_t *mac_r,
hkdf_extract(sha, NULL, 0, 1, prk, k_x, bytes);
/* HKDF-Extract (since it doesn't take non-string arguments)*/
prf_plus(sha, prk, bytes, z_out, bytes, 5, mac_i, 6, mac_r, 6, m_x,
bytes, n_x, bytes, key, strlen(key));
prf_plus(sha, prk, bytes, z_out, bytes, 5,
mac_i, (size_t) 6, mac_r, (size_t) 6, m_x, bytes,
n_x, bytes, key, strlen(key));
*z_len = bytes;

View File

@ -325,7 +325,7 @@ static bool erp_derive_reauth_keys(const uint8_t *emsk, size_t emsk_len,
if (!prf_plus(L_CHECKSUM_SHA256, r_rk, emsk_len,
r_ik, emsk_len, 3, ERP_RIK_LABEL,
strlen(ERP_RIK_LABEL) + 1,
&cryptosuite, 1, &len, sizeof(len)))
&cryptosuite, (size_t) 1, &len, sizeof(len)))
return false;
return true;