Skip to content

The s2n_hmac_digest_verify doesn't handle arguments of different length correctly. #205

@ntc2

Description

@ntc2

The current code for s2n_hmac_digest_verify:

int s2n_hmac_digest_verify(const void *a, uint32_t alen, const void *b, uint32_t blen)
{
    return 0 - (!s2n_constant_time_equals(a, b, alen) | !!(alen - blen));
}

Presumably alen and blen are allowed to be different here, since !!(alen - blen) is mixed into the result.

However, if blen were actually less than alen, then s2n_constant_time_equals would access out of bounds memory in b, potentially segfaulting:

int s2n_constant_time_equals(const uint8_t *a, const uint8_t *b, uint32_t len)
{
    uint8_t xor = 0;
    for (int i = 0; i < len; i++) {
        xor |= a[i] ^ b[i];
    }

    return !xor;
}

This is only a theoretical problem right now, since the only call to s2n_hmac_digest_verify has alen and blen equal. If alen and blen will always be equal in calls to s2n_hmac_digest_verify, then I suggest changing the interface of s2n_hmac_digest_verify to take a single length parameter, describing the equal length of a and b.

There was a check that alen and blen were equal, guarding the call to s2n_constant_time_equals, but it disappeared in 9675ddb.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions