Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ECDSA signing of 0 produces unverifiable signature #4261

Closed
guidovranken opened this issue Mar 28, 2021 · 2 comments
Closed

ECDSA signing of 0 produces unverifiable signature #4261

guidovranken opened this issue Mar 28, 2021 · 2 comments
Labels
bug component-crypto Crypto primitives and low-level interfaces

Comments

@guidovranken
Copy link
Contributor

#include <mbedtls/ecdsa.h>

#define CF_CHECK_EQ(expr, res) if ( (expr) != (res) ) { goto end; }
#define CF_CHECK_NE(expr, res) if ( (expr) == (res) ) { goto end; }

static int RNG(void* arg, unsigned char* out, size_t size) {
    (void)arg;

    if ( size == 0 ) {
        return 0;
    }
    {
        FILE* fp = fopen("/dev/urandom", "rb");
        fread(out, size, 1, fp);
        fclose(fp);
        return 0;
    }
}

int main(void)
{
    const mbedtls_ecp_curve_info* curve_info = NULL;
    mbedtls_ecp_keypair keypair;
    mbedtls_mpi sig_r, sig_s;
    const unsigned char in[32] = { 0 };

    /* noret */ mbedtls_ecp_keypair_init(&keypair);
    /* noret */ mbedtls_mpi_init(&sig_r);
    /* noret */ mbedtls_mpi_init(&sig_s);

    CF_CHECK_NE(curve_info = mbedtls_ecp_curve_info_from_tls_id(23), NULL);
    CF_CHECK_EQ(mbedtls_ecp_group_load(&keypair.grp, curve_info->grp_id), 0);

    /* Private key */
    CF_CHECK_EQ(mbedtls_mpi_read_string(&keypair.d, 10, "20"), 0);

    /* Sign */
    CF_CHECK_EQ(mbedtls_ecdsa_sign(&keypair.grp, &sig_r, &sig_s, &keypair.d, in, sizeof(in), RNG, NULL), 0);

    /* Compute pubkey */
    CF_CHECK_EQ(mbedtls_ecp_mul(&keypair.grp, &keypair.Q, &keypair.d, &keypair.grp.G, NULL, NULL), 0);

    printf("Verify: %d\n", mbedtls_ecdsa_verify(&keypair.grp, in, sizeof(in), &keypair.Q, &sig_r, &sig_s));

end:
    /* noret */ mbedtls_ecp_keypair_free(&keypair);
    /* noret */ mbedtls_mpi_free(&sig_r);
    /* noret */ mbedtls_mpi_free(&sig_s);

    return 0;
}

The in array represents the value 0. Signing succeeds, but produces a signature that mbedtls_ecdsa_verify cannot verify.

@ronald-cron-arm ronald-cron-arm added bug component-crypto Crypto primitives and low-level interfaces labels Mar 29, 2021
@ronald-cron-arm
Copy link
Contributor

ronald-cron-arm commented Mar 29, 2021

Thanks for reporting this. I tested this independently by tweaking one of our test cases, namely test_suite_ecdsa.function:ecdsa_prim_random(). It seems there is indeed something special about all zeroes: tweaked test failing with input buffer with all zeroes but not if byte 0 or 2 is set to 1.

@gilles-peskine-arm
Copy link
Contributor

This is duplicate of #1792. There's a pending fix in #4199.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug component-crypto Crypto primitives and low-level interfaces
Projects
None yet
Development

No branches or pull requests

3 participants