2024-04-03 09:55 AM
Reference: STM32CubeExpansion_Crypto_V4..1.0, MCU: STM32G474RE
The cmox_ecdsa_verify(...) function is failing with a fault code of 0x6c706, which is not contained within cmox_ecc_retvals.h header file. All arguments to the cmox_ecdsa_verify(...) function have been verified and the generated signature has been verified on the development platform. Perhaps the fault code definition in the source code (not available) will provide some insight into the problem? Are there any additional steps I can take to debug this issue?
2024-04-03 05:55 PM - edited 2024-04-03 06:00 PM
Hello @rrooyen
Are you running the same vector test [P-256,SHA-224] as in the following project example ? "~\STM32CubeExpansion_Crypto_V4.0.1\Projects\NUCLEO-G474RE\Applications\ECC\ECDSA_SignVerify"
or another vector test ?
If another vector test, could you share it with me ? I will get a board to test.
Best Regards
2024-04-03 10:39 PM
Hi CMYL,
Thank you very much for having a look at this issue. As mentioned above, the fault code is 0x6c706, which is not in the cmox_ecc_retvals.h header file.
Signature (DER):
$ openssl asn1parse -in meta.sign -inform DER
0:d=0 hl=2 l= 69 cons: SEQUENCE
2:d=1 hl=2 l= 33 prim: INTEGER :DFEF764BAA19B0D3F24EA250E522D853FD7426351A6DC92C4192F775BD040717
37:d=1 hl=2 l= 32 prim: INTEGER :06B702D318F3BEE865FE3B2F1F7E182DEE7E6437CB203DAE29D76F207E407117
BAT file for generating the binary signature (see signature[] below):
for /F "tokens=4 delims=:" %%A IN ('%OPENSSL% asn1parse -in meta.sign -inform=DER') do >>temp.txt echo(%%A
%certutil% -f -decodehex temp.txt meta.sign.bin >nul
Public key (EC):
static uint8_t key[] =
{
0x6c, 0x5a, 0xd7, 0x93, 0x8c, 0x29, 0x05, 0x82, 0x5f, 0x4b, 0x1b, 0xc8, 0x37, 0x93, 0x9e, 0x9e,
0x64, 0xcf, 0x15, 0xfe, 0x3d, 0x03, 0x75, 0x9c, 0x06, 0x6b, 0x66, 0xeb, 0x24, 0x32, 0xa5, 0x12,
0x79, 0xca, 0xe0, 0x45, 0x52, 0xbb, 0x3e, 0xcd, 0x45, 0x2b, 0xe4, 0x27, 0x4a, 0x45, 0x9f, 0xb0,
0xf3, 0xf9, 0x79, 0x81, 0x0c, 0xfd, 0x8e, 0xf2, 0x2a, 0xc9, 0x7f, 0x24, 0x1f, 0xee, 0x24, 0xb5
};
Digest (sha256):
static uint8_t digest[] =
{
0x3d, 0xef, 0x6a, 0xcc, 0x33, 0xa8, 0x36, 0x8b, 0x12, 0x70, 0x84, 0xb0, 0x49, 0x27, 0xb9, 0x2a,
0xce, 0x98, 0x1c, 0xe8, 0xd5, 0x3a, 0xc4, 0xaf, 0xb5, 0x2a, 0xaa, 0xbf, 0x19, 0x3a, 0x50, 0xcd
};
Signature (sha256):
static uint8_t signature[] =
{
0xdf, 0xef, 0x76, 0x4b, 0xaa, 0x19, 0xb0, 0xd3, 0xf2, 0x4e, 0xa2, 0x50, 0xe5, 0x22, 0xd8, 0x53,
0xfd, 0x74, 0x26, 0x35, 0x1a, 0x6d, 0xc9, 0x2c, 0x41, 0x92, 0xf7, 0x75, 0xbd, 0x04, 0x07, 0x17,
0x06, 0xb7, 0x02, 0xd3, 0x18, 0xf3, 0xbe, 0xe8, 0x65, 0xfe, 0x3b, 0x2f, 0x1f, 0x7e, 0x18, 0x2d,
0xee, 0x7e, 0x64, 0x37, 0xcb, 0x20, 0x3d, 0xae, 0x29, 0xd7, 0x6f, 0x20, 0x7e, 0x40, 0x71, 0x17
};
Basic code snippet from the firmware:
static uint8_t buffer[2048];
uint32_t fault = CMOX_ECC_AUTH_FAIL;
cmox_ecc_handle_t rEcc;
cmox_ecc_retval_t status;
cmox_ecc_construct(&rEcc, CMOX_ECC256_MATH_FUNCS, buffer, sizeof(buffer));
if (CMOX_ECC_AUTH_SUCCESS != (status = cmox_ecdsa_verify(&rEcc, CMOX_ECC_CURVE_SECP256R1, key, sizeof(key), digest, sizeof(digest), signature, sizeof(signature), &fault)))
{
return -1;
}
cmox_ecc_cleanup(&rEcc);
2024-04-26 07:34 AM
Hello @rrooyen
Sorry I missed your last comment, I'm working on your test vector :)
Best Regards,
Younes
2024-05-02 12:48 PM
Hi Younes,
Thank you very much for trying my test vector and I am looking forward to your findings.
Cheers,
Robert
2024-05-02 01:45 PM
Hi Robert,
I tried your example and found the same issue.
The problem is that the sign/verify is working with provided NIST vector tests but not working with tests generated by openssl. I even generated more test vectors, signatures for a other supported ECC curves and got the same issues.
I created a CR Ticket asking the Cryptolib team to help how to format and integrate opensl-based vectors. I'm waiting their support.
best Regards
2024-05-02 02:17 PM
Hi Younes,
Thank you so very much for finding root cause in the Cryptolib and forwarding it to the appropriate team for review. I am looking forward to applying the patch when it becomes available.
Cheers,
Robert
2024-05-02 02:33 PM
I was able to confirm the private key was valid with MicroECC, the version I'm using I had the byte-reverse the key.
I was unable to validate the signature.
What you might want to try is to use CMOX to sign and then validate locally on the STM32, basically proving the path end-to-end. As I recall the signature will be different each time due to the injection of a random pattern.
If you can generate a couple of patterns that way I can check.
I'm currently using SECP192R1 in a different application
2024-05-02 05:47 PM - edited 2024-05-03 09:51 AM
I tested this FIPS test pattern with my MicroECC build for SECP256R1
//[P-256,SHA-256]
//
// Msg = 5905238877c77421f73e43ee3da6f2d9e2ccad5fc942dcec0cbd25482935faaf416983fe165b1a045ee2bcd2e6dca3bdf46c4310a7461f9a37960ca672d3feb5473e253605fb1ddfd28065b53cb5858a8ad28175bf9bd386a5e471ea7a65c17cc934a9d791e91491eb3754d03799790fe2d308d16146d5c9b0d0debd97d79ce8
// d = 519b423d715f8b581f4fa8ee59f4771a5b44c8130b4e3eacca54a56dda72b464
// Qx = 1ccbe91c075fc7f4f033bfa248db8fccd3565de94bbfb12f3c59ff46c271bf83
// Qy = ce4014c68811f9a21a1fdb2c0e6113e06db7ca93b7404e78dc7ccd5ca89a4ca9
// k = 94a1bbb14b906a61a280f245f9e93c7f3b4a6247824f5d33b9670787642a68de
// R = f3ac8061b514795b8843e3d6629527ed2afd6b1f6a555a7acabb5e6f79c8c2ac
// S = 8bf77819ca05a6b2786c76262bf7371cef97b218e96f175a3ccdda2acc058903
static uint8_t msg[] = { // Message
0x59,0x05,0x23,0x88,0x77,0xc7,0x74,0x21,0xf7,0x3e,0x43,0xee,0x3d,0xa6,0xf2,0xd9,
0xe2,0xcc,0xad,0x5f,0xc9,0x42,0xdc,0xec,0x0c,0xbd,0x25,0x48,0x29,0x35,0xfa,0xaf,
0x41,0x69,0x83,0xfe,0x16,0x5b,0x1a,0x04,0x5e,0xe2,0xbc,0xd2,0xe6,0xdc,0xa3,0xbd,
0xf4,0x6c,0x43,0x10,0xa7,0x46,0x1f,0x9a,0x37,0x96,0x0c,0xa6,0x72,0xd3,0xfe,0xb5,
0x47,0x3e,0x25,0x36,0x05,0xfb,0x1d,0xdf,0xd2,0x80,0x65,0xb5,0x3c,0xb5,0x85,0x8a,
0x8a,0xd2,0x81,0x75,0xbf,0x9b,0xd3,0x86,0xa5,0xe4,0x71,0xea,0x7a,0x65,0xc1,0x7c,
0xc9,0x34,0xa9,0xd7,0x91,0xe9,0x14,0x91,0xeb,0x37,0x54,0xd0,0x37,0x99,0x79,0x0f,
0xe2,0xd3,0x08,0xd1,0x61,0x46,0xd5,0xc9,0xb0,0xd0,0xde,0xbd,0x97,0xd7,0x9c,0xe8 };
static uint8_t digest[] = { // Digest (sha256) Actual
0x44,0xac,0xf6,0xb7,0xe3,0x6c,0x13,0x42,0xc2,0xc5,0x89,0x72,0x04,0xfe,0x09,0x50, // sha256(msg)
0x4e,0x1e,0x2e,0xfb,0x1a,0x90,0x03,0x77,0xdb,0xc4,0xe7,0xa6,0xa1,0x33,0xec,0x56 };
static uint8_t keyprivate[] = { // Private Key
0x51,0x9b,0x42,0x3d,0x71,0x5f,0x8b,0x58,0x1f,0x4f,0xa8,0xee,0x59,0xf4,0x77,0x1a, // d
0x5b,0x44,0xc8,0x13,0x0b,0x4e,0x3e,0xac,0xca,0x54,0xa5,0x6d,0xda,0x72,0xb4,0x64 };
static uint8_t key[] = { // Public Key
0x1c,0xcb,0xe9,0x1c,0x07,0x5f,0xc7,0xf4,0xf0,0x33,0xbf,0xa2,0x48,0xdb,0x8f,0xcc, // Qx
0xd3,0x56,0x5d,0xe9,0x4b,0xbf,0xb1,0x2f,0x3c,0x59,0xff,0x46,0xc2,0x71,0xbf,0x83,
0xce,0x40,0x14,0xc6,0x88,0x11,0xf9,0xa2,0x1a,0x1f,0xdb,0x2c,0x0e,0x61,0x13,0xe0, // Qy
0x6d,0xb7,0xca,0x93,0xb7,0x40,0x4e,0x78,0xdc,0x7c,0xcd,0x5c,0xa8,0x9a,0x4c,0xa9 };
static uint8_t k[] = {
0x94,0xa1,0xbb,0xb1,0x4b,0x90,0x6a,0x61,0xa2,0x80,0xf2,0x45,0xf9,0xe9,0x3c,0x7f, // k
0x3b,0x4a,0x62,0x47,0x82,0x4f,0x5d,0x33,0xb9,0x67,0x07,0x87,0x64,0x2a,0x68,0xde };
static uint8_t signature[] = { // Signature (sha256)
0xf3,0xac,0x80,0x61,0xb5,0x14,0x79,0x5b,0x88,0x43,0xe3,0xd6,0x62,0x95,0x27,0xed, // R
0x2a,0xfd,0x6b,0x1f,0x6a,0x55,0x5a,0x7a,0xca,0xbb,0x5e,0x6f,0x79,0xc8,0xc2,0xac,
0x8b,0xf7,0x78,0x19,0xca,0x05,0xa6,0xb2,0x78,0x6c,0x76,0x26,0x2b,0xf7,0x37,0x1c, // S
0xef,0x97,0xb2,0x18,0xe9,0x6f,0x17,0x5a,0x3c,0xcd,0xda,0x2a,0xcc,0x05,0x89,0x03 };
#if (FIPS_TEST == 2)
// Msg = c35e2f092553c55772926bdbe87c9796827d17024dbb9233a545366e2e5987dd344deb72df987144b8c6c43bc41b654b94cc856e16b96d7a821c8ec039b503e3d86728c494a967d83011a0e090b5d54cd47f4e366c0912bc808fbb2ea96efac88fb3ebec9342738e225f7c7c2b011ce375b56621a20642b4d36e060db4524af1
// d = 0f56db78ca460b055c500064824bed999a25aaf48ebb519ac201537b85479813
// Qx = e266ddfdc12668db30d4ca3e8f7749432c416044f2d2b8c10bf3d4012aeffa8a
// Qy = bfa86404a2e9ffe67d47c587ef7a97a7f456b863b4d02cfc6928973ab5b1cb39
// k = 6d3e71882c3b83b156bb14e0ab184aa9fb728068d3ae9fac421187ae0b2f34c6
// R = 976d3a4e9d23326dc0baa9fa560b7c4e53f42864f508483a6473b6a11079b2db
// S = 1b766e9ceb71ba6c01dcd46e0af462cd4cfa652ae5017d4555b8eeefe36e1932
static uint8_t msg[] = { // Message
0xc3,0x5e,0x2f,0x09,0x25,0x53,0xc5,0x57,0x72,0x92,0x6b,0xdb,0xe8,0x7c,0x97,0x96, // Msg
0x82,0x7d,0x17,0x02,0x4d,0xbb,0x92,0x33,0xa5,0x45,0x36,0x6e,0x2e,0x59,0x87,0xdd,
0x34,0x4d,0xeb,0x72,0xdf,0x98,0x71,0x44,0xb8,0xc6,0xc4,0x3b,0xc4,0x1b,0x65,0x4b,
0x94,0xcc,0x85,0x6e,0x16,0xb9,0x6d,0x7a,0x82,0x1c,0x8e,0xc0,0x39,0xb5,0x03,0xe3,
0xd8,0x67,0x28,0xc4,0x94,0xa9,0x67,0xd8,0x30,0x11,0xa0,0xe0,0x90,0xb5,0xd5,0x4c,
0xd4,0x7f,0x4e,0x36,0x6c,0x09,0x12,0xbc,0x80,0x8f,0xbb,0x2e,0xa9,0x6e,0xfa,0xc8,
0x8f,0xb3,0xeb,0xec,0x93,0x42,0x73,0x8e,0x22,0x5f,0x7c,0x7c,0x2b,0x01,0x1c,0xe3,
0x75,0xb5,0x66,0x21,0xa2,0x06,0x42,0xb4,0xd3,0x6e,0x06,0x0d,0xb4,0x52,0x4a,0xf1 };
static uint8_t digest[] = { // Digest (sha256) Actual
0x9b,0x2d,0xb8,0x9c,0xb0,0xe8,0xfa,0x3c,0xc7,0x60,0x8b,0x4d,0x6c,0xc1,0xde,0xc0, // sha256(Msg)
0x11,0x4e,0x0b,0x9f,0xf4,0x08,0x0b,0xea,0x12,0xb1,0x34,0xf4,0x89,0xab,0x2b,0xbc };
static uint8_t keyprivate[] = { // Private Key
0x0f,0x56,0xdb,0x78,0xca,0x46,0x0b,0x05,0x5c,0x50,0x00,0x64,0x82,0x4b,0xed,0x99, // d
0x9a,0x25,0xaa,0xf4,0x8e,0xbb,0x51,0x9a,0xc2,0x01,0x53,0x7b,0x85,0x47,0x98,0x13 };
static uint8_t key[] = { // Public Key
0xe2,0x66,0xdd,0xfd,0xc1,0x26,0x68,0xdb,0x30,0xd4,0xca,0x3e,0x8f,0x77,0x49,0x43, // Qx
0x2c,0x41,0x60,0x44,0xf2,0xd2,0xb8,0xc1,0x0b,0xf3,0xd4,0x01,0x2a,0xef,0xfa,0x8a,
0xbf,0xa8,0x64,0x04,0xa2,0xe9,0xff,0xe6,0x7d,0x47,0xc5,0x87,0xef,0x7a,0x97,0xa7, // Qy
0xf4,0x56,0xb8,0x63,0xb4,0xd0,0x2c,0xfc,0x69,0x28,0x97,0x3a,0xb5,0xb1,0xcb,0x39 };
static uint8_t k[] = {
0x6d,0x3e,0x71,0x88,0x2c,0x3b,0x83,0xb1,0x56,0xbb,0x14,0xe0,0xab,0x18,0x4a,0xa9, // k
0xfb,0x72,0x80,0x68,0xd3,0xae,0x9f,0xac,0x42,0x11,0x87,0xae,0x0b,0x2f,0x34,0xc6 };
static uint8_t signature[] = { // Signature (sha256)
0x97,0x6d,0x3a,0x4e,0x9d,0x23,0x32,0x6d,0xc0,0xba,0xa9,0xfa,0x56,0x0b,0x7c,0x4e, // R
0x53,0xf4,0x28,0x64,0xf5,0x08,0x48,0x3a,0x64,0x73,0xb6,0xa1,0x10,0x79,0xb2,0xdb,
0x1b,0x76,0x6e,0x9c,0xeb,0x71,0xba,0x6c,0x01,0xdc,0xd4,0x6e,0x0a,0xf4,0x62,0xcd, // S
0x4c,0xfa,0x65,0x2a,0xe5,0x01,0x7d,0x45,0x55,0xb8,0xee,0xef,0xe3,0x6e,0x19,0x32 };
#endif // FIPS_TEST == 2
2024-05-03 10:01 AM
Well the NIST/FIPS test vectors should be definitive. I wonder what OPENSSL is doing here?
Some kind of Byte/Endian swap expectations?
[P-256,SHA-224] or [P-256,SHA-256] being attempted? SECP256R1 curve or SECP256K1 ?