Skip to main content
Associate II
April 3, 2024
Question

ECC Signature Failure

  • April 3, 2024
  • 5 replies
  • 7748 views

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?

5 replies

Technical Moderator
April 4, 2024

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

 

 

rrooyenAuthor
Associate II
April 4, 2024

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);

 

Technical Moderator
April 26, 2024

Hello @rrooyen 

Sorry I missed your last comment, I'm working on your test vector :)

 

Best Regards,

Younes

rrooyenAuthor
Associate II
May 2, 2024

Hi Younes,

Thank you very much for trying my test vector and I am looking forward to your findings.

Cheers,

 

Robert

Tesla DeLorean
Guru
May 2, 2024

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

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
Technical Moderator
May 2, 2024

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

rrooyenAuthor
Associate II
May 2, 2024

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

Technical Moderator
May 3, 2024

Hello @rrooyen,

In my test vectors generated by OpenSSL, I discovered that I forget to discard the first byte of the public key. In line 9, we need to discard the first byte from the public key array as described in line 23. Once discarded, I got all my tests running well.  

>openssl ec -in private_R1.pem -pubout -noout -text
read EC key
Private-Key: (256 bit)
priv:
 1a:d2:75:8a:28:bd:82:74:4c:e8:16:ed:2b:ab:f7:
 4d:1b:9a:30:1a:89:6a:66:31:91:b1:e5:24:f5:85:
 27:77
pub:
 04:9f:3d:66:c0:dc:d2:e9:ca:56:3a:c8:fa:1d:31:
 d5:00:fd:fd:7d:94:83:16:ae:51:96:7c:72:15:bb:
 a1:95:bc:ff:42:88:5a:ed:98:48:2f:76:bd:e7:04:
 04:14:fa:0c:c8:7e:ea:09:fb:f5:c1:ea:88:22:6a:
 53:24:ed:32:2a
ASN1 OID: prime256v1
NIST CURVE: P-256

priv:
 0x1a, 0xd2, 0x75, 0x8a, 0x28, 0xbd, 0x82, 0x74, 0x4c, 0xe8, 0x16, 0xed, 0x2b, 0xab, 0xf7, 0x4d, 
	0x1b, 0x9a, 0x30, 0x1a, 0x89, 0x6a, 0x66, 0x31, 0x91, 0xb1, 0xe5, 0x24, 0xf5, 0x85, 0x27, 0x77
	
pub: (need to discard the first byte of public key)
uint8_t public_key[]= {
 /*0x04,*/ 0x9f, 0x3d, 0x66, 0xc0, 0xdc, 0xd2, 0xe9, 0xca, 0x56, 0x3a, 0xc8, 0xfa, 0x1d, 0x31, 0xd5, 
	0x00, 0xfd, 0xfd, 0x7d, 0x94, 0x83, 0x16, 0xae, 0x51, 0x96, 0x7c, 0x72, 0x15, 0xbb, 0xa1, 0x95, 
	0xbc, 0xff, 0x42, 0x88, 0x5a, 0xed, 0x98, 0x48, 0x2f, 0x76, 0xbd, 0xe7, 0x04, 0x04, 0x14, 0xfa, 
	0x0c, 0xc8, 0x7e, 0xea, 0x09, 0xfb, 0xf5, 0xc1, 0xea, 0x88, 0x22, 0x6a, 0x53, 0x24, 0xed, 0x32, 0x2a	
};

In the attached file I put all the OpenSSL commands that I used to generate ECC parameters and how were formatted in C.

Check if you followed the same commands when generating your vector test ? can you share the openssl commands used ?

Double check also that you pass the message.txt to sign or verify and not the hashed message !!! 

best regards,

Younes

Technical Moderator
May 3, 2024

Thank you @Tesla DeLorean for the shared github vector tests.

I ran your test and it is working, please find attached main.c corresponding file.

CMYL_0-1714770609144.png

 

Explorer II
July 8, 2024

Oh that's interesting. The reason I am using them is to store different public key versions to support key rolling in the future if we need it (without needing secure OTA firmware upgrade). I will look into some of these offset_of() and size_of() methods produce at runtime and see if that has some clues.