cancel
Showing results for 
Search instead for 
Did you mean: 

ECC Signature Failure

rrooyen
Associate III

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?

20 REPLIES 20

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

Hello @Tesla DeLorean 

[P-256,SHA-224] or [P-256,SHA-256] are for SECP256R1 curves, SECG curve over a 256 prime field. P for prime field and K for binary field. 

Verification will fail using SECP256K1 with [P-256,SHA-224] test vectors. 

The file SigGen.txt contains values for ECDSA signature generation for K-233, K-283, K-409 and K-571 (example [K-233,SHA-224])

Test files for FIPS 186-3 ECDSA Updated May 5, 2015 doesn't include examples for K-256 and K-163 curves. That's why we need to use OpenSSL or python scripts based on crypto libraries to generate tests.

Best regards

 

Thanks @CMYL Younes, in fishing around I found these that I could use to test public key generation, signing and verifying. I like to validate and sanity check, end-to-end, both on the PC and the MCU

https://github.com/pyca/cryptography/blob/main/vectors/cryptography_vectors/asymmetric/ECDSA/SECP256K1/SigGen.txt#L6314

#if (FIPS_TEST == 123) // secp256k1

// https://github.com/pyca/cryptography/blob/main/vectors/cryptography_vectors/asymmetric/ECDSA/SECP256K1/SigGen.txt#L6314

// [K-256,SHA-256]

// Msg = 5c868fedb8026979ebd26f1ba07c27eedf4ff6d10443505a96ecaf21ba8c4f0937b3cd23ffdc3dd429d4cd1905fb8dbcceeff1350020e18b58d2ba70887baa3a9b783ad30d3fbf210331cdd7df8d77defa398cdacdfc2e359c7ba4cae46bb74401deb417f8b912a1aa966aeeba9c39c7dd22479ae2b30719dca2f2206c5eb4b7
// d   = 42202a98374f6dca439c0af88140e41f8eced3062682ec7f9fc8ac9ea83c7cb2
// Qx  = 131ca4e5811267fa90fc631d6298c2d7a4ecccc45cc60d378e0660b61f82fe8d
// Qy  = cf5acf8ed3e0bbf735308cc415604bd34ab8f7fc8b4a22741117a7fbc72a7949
// R   = d89f9586070230bb03e625cca18c89bb3117cd472ff6ee2a50809f0e89039309
// S   = 45972842e92e3a41abeea1089d812eb5343ca8f075ac9c66e13f3db287048638

static uint8_t msg[] = { // Message
0x5c,0x86,0x8f,0xed,0xb8,0x02,0x69,0x79,0xeb,0xd2,0x6f,0x1b,0xa0,0x7c,0x27,0xee, // Msg
0xdf,0x4f,0xf6,0xd1,0x04,0x43,0x50,0x5a,0x96,0xec,0xaf,0x21,0xba,0x8c,0x4f,0x09,
0x37,0xb3,0xcd,0x23,0xff,0xdc,0x3d,0xd4,0x29,0xd4,0xcd,0x19,0x05,0xfb,0x8d,0xbc,
0xce,0xef,0xf1,0x35,0x00,0x20,0xe1,0x8b,0x58,0xd2,0xba,0x70,0x88,0x7b,0xaa,0x3a,
0x9b,0x78,0x3a,0xd3,0x0d,0x3f,0xbf,0x21,0x03,0x31,0xcd,0xd7,0xdf,0x8d,0x77,0xde,
0xfa,0x39,0x8c,0xda,0xcd,0xfc,0x2e,0x35,0x9c,0x7b,0xa4,0xca,0xe4,0x6b,0xb7,0x44,
0x01,0xde,0xb4,0x17,0xf8,0xb9,0x12,0xa1,0xaa,0x96,0x6a,0xee,0xba,0x9c,0x39,0xc7,
0xdd,0x22,0x47,0x9a,0xe2,0xb3,0x07,0x19,0xdc,0xa2,0xf2,0x20,0x6c,0x5e,0xb4,0xb7 };

static uint8_t digest[] = { // Digest (sha256) Actual
0x5a,0xe8,0x31,0x7d,0x34,0xd1,0xe5,0x95,0xe3,0xfa,0x72,0x47,0xdb,0x80,0xc0,0xaf, // sha256(Msg)
0x43,0x20,0xcc,0xe1,0x11,0x6d,0xe1,0x87,0xf8,0xf7,0xe2,0xe0,0x99,0xc0,0xd8,0xd0 };

static uint8_t keyprivate[] = { // Private Key
0x42,0x20,0x2a,0x98,0x37,0x4f,0x6d,0xca,0x43,0x9c,0x0a,0xf8,0x81,0x40,0xe4,0x1f, // d
0x8e,0xce,0xd3,0x06,0x26,0x82,0xec,0x7f,0x9f,0xc8,0xac,0x9e,0xa8,0x3c,0x7c,0xb2 };

static uint8_t key[] = { // Public Key
0x13,0x1c,0xa4,0xe5,0x81,0x12,0x67,0xfa,0x90,0xfc,0x63,0x1d,0x62,0x98,0xc2,0xd7, // Qx
0xa4,0xec,0xcc,0xc4,0x5c,0xc6,0x0d,0x37,0x8e,0x06,0x60,0xb6,0x1f,0x82,0xfe,0x8d,
0xcf,0x5a,0xcf,0x8e,0xd3,0xe0,0xbb,0xf7,0x35,0x30,0x8c,0xc4,0x15,0x60,0x4b,0xd3, // Qy
0x4a,0xb8,0xf7,0xfc,0x8b,0x4a,0x22,0x74,0x11,0x17,0xa7,0xfb,0xc7,0x2a,0x79,0x49 };

static uint8_t signature[] = { // Signature (sha256)
0xd8,0x9f,0x95,0x86,0x07,0x02,0x30,0xbb,0x03,0xe6,0x25,0xcc,0xa1,0x8c,0x89,0xbb, // R
0x31,0x17,0xcd,0x47,0x2f,0xf6,0xee,0x2a,0x50,0x80,0x9f,0x0e,0x89,0x03,0x93,0x09,
0x45,0x97,0x28,0x42,0xe9,0x2e,0x3a,0x41,0xab,0xee,0xa1,0x08,0x9d,0x81,0x2e,0xb5, // S
0x34,0x3c,0xa8,0xf0,0x75,0xac,0x9c,0x66,0xe1,0x3f,0x3d,0xb2,0x87,0x04,0x86,0x38 };

char sQx[] = "131ca4e5811267fa90fc631d6298c2d7a4ecccc45cc60d378e0660b61f82fe8d";
char sQy[] = "cf5acf8ed3e0bbf735308cc415604bd34ab8f7fc8b4a22741117a7fbc72a7949";

#endif // FIPS_TEST == 123

  

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
CMYL
ST Employee

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

 

Hi CYML,

Agreed, the first byte in the public key must be removed and this is the case in in my existing code. I reviewed your attachment (message.txt), but it does not include all of the OpenSSL commands that were used to generate the ECC parameters. Can you reply with a new attachment that has all of your OpenSSL commands?

Below is the sequence to generate the firmware update image that was based on the St Cryptolib examples. Everything works correctly in the firmware expect signature verification.

1. Derive public key from private key (first byte must be removed):

openssl pkey -in <private key> -pubout -out <public key>
openssl ec -pubin -in <public key> -text -noout

read EC key
Public-Key: (256 bit)
pub:
04:6c:5a:d7:93:8c:29:05:82:5f:4b:1b:c8:37:93:
9e:9e:64:cf:15:fe:3d:03:75:9c:06:6b:66:eb:24:
32:a5:12:79:ca:e0:45:52:bb:3e:cd:45:2b:e4:27:
4a:45:9f:b0:f3:f9:79:81:0c:fd:8e:f2:2a:c9:7f:
24:1f:ee:24:b5
ASN1 OID: prime256v1
NIST CURVE: P-256

2. Generate firmware image hash:

openssl dgst -sha256 -binary <firmware> 1><firmware hash>

3. Generate metadata.

4. Generate hash of metadata:

openssl dgst -sha256 -binary <metadata> 1><metadata hash>

5. Sign the metadata hash:

openssl dgst -sha256 -sign <private key> -out <metadata signature> <metadata hash>

6. Verify metadata signature:

openssl dgst -sha256 -verify <public key> -signature <metadata signature> <metadata hash>

7. Extract binary signature:

openssl asn1parse -in <metadata signature> -inform DER

8. Append files:

copy /B <firmware>+<metadata>+<metadata hash>+<metadata signature binary> <update binary>

9. Encrypt update:

openssl enc -aes-256-ctr -pbkdf2 -kfile <password> -nosalt -p -in <update binary> -out  <update image>

 

 

 

 

 

Hello CMYL,

I have the same problem as everyone else, the projects I use are: STM32CubeExpansion_Crypto_V4.1.0 with "NUCLEO-G071RB\Applications\ECC\ECDSA_SignVerify".

 

I used the openssl to generated the ecc256 key pairs and signing the binary data to generated a signature file.

After ecc verifying, I got the CMOX_ECC_AUTH_FAIL error message and fault_check=0x0006C726 result.

 

Do you have an update on this issue or other professional advice? Many thanks.

Is there any update on a fix for this?  I'm seeing the same issue on my CMOX usage on an STM32 MCU.

Do the Test Vectors work?

If they work and the others don't you'll need to start paying attention for how the keys and signing was achieved, especially byte ordering

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

@Tesla DeLorean - thanks for the reply. So I wrote my own application specific test vectors last year when we were switching to CMOX, I ran those and they pass just fine. It turns out that for some reason, declaring a bunch of const arrays before invoking the CMOX ECDSA caused this error. When we removed the array declarations things seemed to go back to a working state. 

Probably some kind of memory shortage issue in the MCU? I'm surprised that my code didn't just crash altogether, this error seemed to be the consistent result. 

>>Probably some kind of memory shortage issue in the MCU?

Yeah, I'd expect something to flag up as failing.

Now alignment, and copying statics to RAM might have some issues. For example if the data is shorter than imagined, the padding data becomes a point of contention.

Also watch the Keil MDK V6 compilers align structures and content differently, so check sizeof() and offsetof() type operations. Some 64-bit / 8-byte packing caught me off guard as I migrated from V5

At least one of the use cases I track has different endian ordering for ECDSA and a unique hash folding for SHA-256 to SECP192R1

Several encryption methods I track use 256-bit / 16-byte line widths, so padding and terminal cases had to be watched.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..