ECDSA signing of 0 produces unverifiable signature
guidovranken opened this issue · 2 comments
guidovranken commented
#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 commented
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 commented