0

I am working with mbedtls in a 32-bit microcontroller and have created a ECDH context. I put in the X and Y coordinates of the other party's public key, then attempt to create the shared secret. The shared secret that I am getting is all 0x00. The pertinent lines of code are shown below. key_size = 32. What am I missing/doing wrong?

  //Initialize the Static ECDH context and retrieve the static public key
  mbedtls_ecdh_init(&ECDH_Context_Static);
  mbedtls_ecp_group_load(&ECDH_Context_Static.grp, ElipticCurveID);
  mbedtls_ecdh_gen_public(&ECDH_Context_Static.grp, &ECDH_Context_Static.d, &ECDH_Context_Static.Q, mbedtls_ctr_drbg_random, &DRBG_Context);
  mbedtls_mpi_write_binary(&ECDH_Context_Static.Q.X, StaticPublicKey_X, key_size);  //Write to char array from ECDH context -> copy out static public key
  mbedtls_mpi_write_binary(&ECDH_Context_Static.Q.Y, StaticPublicKey_Y, key_size);

  //Generate a Static shared secret using local Static private key and Host's Static public key
  success = mbedtls_mpi_read_binary(&ECDH_Context_Static.Qp.X, HostStaticPublicKey_X, key_size); //Read to ECDH context from char array -> load in Host's public key
  success = mbedtls_mpi_read_binary(&ECDH_Context_Static.Qp.Y, HostStaticPublicKey_Y, key_size);
  success = mbedtls_ecdh_compute_shared(&ECDH_Context_Static.grp, &ECDH_Context_Static.z, &ECDH_Context_Static.Qp, &ECDH_Context_Static.d, NULL, NULL);
  success = mbedtls_mpi_write_binary(&ECDH_Context_Static.z, StaticSecret, key_size); //Write to char array from ECDH context -> copy out static shared secret
Lajos Arpad
  • 64,414
  • 37
  • 100
  • 175
russ
  • 65
  • 7
  • PS - Sorry about the code formatting, I just wasn't able to figure out how to insert the code with good formatting (and it looks even worse in the final version than in the review version). – russ Jul 26 '23 at 14:36
  • No worries, edited it. – Lajos Arpad Jul 26 '23 at 14:41
  • I have seen some discrepancy online as to whether the _compute_shared function should use .Q or .Qp for the third argument; though most show Qp. I tried with .Q and get a non-zero shared secret, but its value does not change with changes to Qp (the other party's public key) - so this does not seem correct. As an aside, I also noticed that the function returns almost immediately when using .Qp, but takes a long time to return with .Q; in both cases the return value is 0 (success). – russ Jul 26 '23 at 15:54
  • Correction: when using .Qp in the mbedtls_ecdh_compute_shared() function, the return value is 0xFFFFB380. I am not able to find what this means. – russ Jul 26 '23 at 17:14
  • I've found that 0xFFFFB380 = -0x4C80 which is MBEDTLS_ERR_ECP_INVALID_KEY. I populated Qp using the public key of a second ECDH context created in the same way as the first - so I don't know why it is invalid. If I use the public key of the second ECDH context directly as the argument to _compute_shared(), then it works. So, there seems to be an issue with putting the key values into Qp. – russ Jul 26 '23 at 18:22
  • What's in `HostStaticPublicKey_X` & `HostStaticPublicKey_Y`? – Maarten Bodewes Jul 26 '23 at 23:31
  • They contain the X and Y coordinates of the other party's public key. To aid in debugging, I now have them being loaded from another local ECDH context like this: mbedtls_mpi_read_binary(&ECDH_Context_Static.Q.X, HostStaticPublicKkey_X, key_size); – russ Jul 27 '23 at 12:41
  • The above was supposed to be "...write_binary..." – russ Jul 27 '23 at 12:52

1 Answers1

0

I was able to get the mbedtls_ecdh_compute_shared() function to work by placing the other party's public key into the PRIVATE key of a temporary ECDH context (created as shown in the first three lines of code in the original question post), then using that private key as the mbedtls_ecp_point argument:

with the other party's public key in arrays HostPublicX and HostPublicY,

mbedtls_mpi_read_binary(&TempECDHContext.Q.X, HostPublicX, key_size);
mbedtls_mpi_read_binary(&TempECDHContext.Q.Y, HostPublicY, key_size);

mbedtls_ecdh_compute_shared(&ECDH_Context_Static.grp, &ECDH_Context_Static.z, &TempECDHContext.Q, &ECDH_Context_Static.d, NULL, NULL);

While this works, I am still curious about the .Qp point in the ECDH context and why the mbedtls_ecdh_compute_shared() function fails if .Qp is used as the ecp_point argument.

russ
  • 65
  • 7