Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

atcab_ecdh function returns ATCA_EXECUTION_ERROR #11

Closed
lbabaly opened this issue May 20, 2018 · 4 comments
Closed

atcab_ecdh function returns ATCA_EXECUTION_ERROR #11

lbabaly opened this issue May 20, 2018 · 4 comments

Comments

@lbabaly
Copy link

lbabaly commented May 20, 2018

Hi Ben,

I'm trying to generate the preshared secret with output in the clear using an internal private key and an external public key to get it but the ecdh function returns ATCA_EXECUTION_ERROR.
Private key is stored in slot 0 with the following configs:

  • SlotConfig 0x00 0x87
  • KeyConfig 0x00 0x13

Every zone is locked except OTP.

The call is pretty simple and looks like this:
ret = atcab_ecdh(0, public_key, pms);

Anyway, I could use the key for ECDSA signing and worked well.
Do you have any idea what the problem could be?

Best regards,
Laszlo Babaly

@BenUdall-Microchip
Copy link
Collaborator

Hi Laszlo,
Your configuration for slot 0 as a private key with ECDH enabled looks fine. There are a number of other reasons why this might fail:

  1. Data zone must be locked for the ECDH command. You already mentioned this, but I wanted to clarify that the OTP zone isn't locked separately from the data zone. It would be better labeled as the data/otp lock.
  2. Slot 0 must have a valid private key in it. This is done by running GenKey with Mode=0x04 and KeyId=0x0000, which internally generates a new random private key for slot 0. Since your configuration disables GenKey after the data zone is locked, this must be run while the data zone is unlocked to initialize the private key.
  3. The public key must be a valid point on the P-256 curve. An improperly formatted public key or or one not on the P-256 curve may cause an execution error. Public keys will be the X and Y integers as big-endian, fixed-width, unsigned integers concatenated together. I've included a valid public key below for testing.
uint8_t public_key[64] = {
    0xb2, 0xbe, 0x34, 0x5a, 0xd7, 0x89, 0x93, 0x83,
    0xa9, 0xaa, 0xb4, 0xfb, 0x96, 0x8b, 0x1c, 0x78,
    0x35, 0xcb, 0x2c, 0xd4, 0x2c, 0x7e, 0x97, 0xc2,
    0x6f, 0x85, 0xdf, 0x8e, 0x20, 0x1f, 0x3b, 0xe8,
    0xa8, 0x29, 0x83, 0xf0, 0xa1, 0x1d, 0x6f, 0xf3,
    0x1d, 0x66, 0xce, 0x99, 0x32, 0x46, 0x6f, 0x0f,
    0x2c, 0xca, 0x21, 0xef, 0x96, 0xbe, 0xc9, 0xce,
    0x23, 0x5b, 0x3d, 0x87, 0xb0, 0xf8, 0xfa, 0x9e
};

Regards,
-Ben

@lbabaly
Copy link
Author

lbabaly commented May 21, 2018

Hi Ben,

Thanks for your help. I had the third issue what is weird because I used openssl to generate the key pair with prime256v1 curve option which should be the same curve as NIST P256 as far as I learnt. Do you have experience with generating keys with openssl that are comaptible with the ATECC508?

@BenUdall-Microchip
Copy link
Collaborator

Hi Laszlo,
That is odd, prime256v1 (a.k.a. secp256r1 and NIST P-256, depending on standards org), is the correct curve to use. That public key I used actually came from openssl. Here's the procedure I used to generated it:

Generate a key pair and generate the SubjectPublicKeyInfo for elliptic curve public keys per RFC5480:

$ openssl ecparam -name prime256v1 -genkey -out private-key.pem
$ openssl ec -in private-key.pem -pubout -outform DER -out public-key.der

The short answer is to just use the last 64-bytes of the public-key.der output file from the last command.

$ hexdump public-key.der
0000000 30 59 30 13 06 07 2a 86 48 ce 3d 02 01 06 08 2a
0000010 86 48 ce 3d 03 01 07 03 42 00 04 b2 be 34 5a d7
0000020 89 93 83 a9 aa b4 fb 96 8b 1c 78 35 cb 2c d4 2c
0000030 7e 97 c2 6f 85 df 8e 20 1f 3b e8 a8 29 83 f0 a1
0000040 1d 6f f3 1d 66 ce 99 32 46 6f 0f 2c ca 21 ef 96
0000050 be c9 ce 23 5b 3d 87 b0 f8 fa 9e              
000005b

Public key is:

b2 be 34 5a d7 89 93 83 a9 aa b4 fb 96 8b 1c 78 35 cb 2c d4 2c 7e 97 c2 6f 85 df 8e 20 1f 3b e8 a8 29 83 f0 a1 1d 6f f3 1d 66 ce 99 32 46 6f 0f 2c ca 21 ef 96 be c9 ce 23 5b 3d 87 b0 f8 fa 9e

For the long answer, we have to look at the raw X and Y integers that compose an elliptic curve public key. We can use openssl to dump the ASN.1 DER encoded SubjectPublicKeyInfo to see the X and Y values.

$ openssl asn1parse -dump -inform DER -in public-key.der 
    0:d=0  hl=2 l=  89 cons: SEQUENCE          
    2:d=1  hl=2 l=  19 cons: SEQUENCE          
    4:d=2  hl=2 l=   7 prim: OBJECT            :id-ecPublicKey
   13:d=2  hl=2 l=   8 prim: OBJECT            :prime256v1
   23:d=1  hl=2 l=  66 prim: BIT STRING        
      0000 - 00 04 b2 be 34 5a d7 89-93 83 a9 aa b4 fb 96 8b   ....4Z..........
      0010 - 1c 78 35 cb 2c d4 2c 7e-97 c2 6f 85 df 8e 20 1f   .x5.,.,~..o... .
      0020 - 3b e8 a8 29 83 f0 a1 1d-6f f3 1d 66 ce 99 32 46   ;..)....o..f..2F
      0030 - 6f 0f 2c ca 21 ef 96 be-c9 ce 23 5b 3d 87 b0 f8   o.,.!.....#[=...
      0040 - fa 9e  

The X and Y integers are in an unsigned big-endian fixed-width format. Integers will be the same as the key size, for the prime256v1 (NIST P-256) curve that will be 32 bytes. I've broken down the BIT STRING above into the following components:
Bit string unused bits: 00
Key compression byte: 04
X integer: b2 be 34 5a d7 89 93 83 a9 aa b4 fb 96 8b 1c 78 35 cb 2c d4 2c 7e 97 c2 6f 85 df 8e 20 1f 3b e8
Y integer: a8 29 83 f0 a1 1d 6f f3 1d 66 ce 99 32 46 6f 0f 2c ca 21 ef 96 be c9 ce 23 5b 3d 87 b0 f8 fa 9e

The key compression byte, 0x04, indicates an uncompressed public key. We don’t support or use the compressed format. More information can be found in RFC5480 section 2.2, which pulls from SECG SEC1 section 2.3.3.

The first raw format the ATECCx08A uses, is the X and Y integers concatenated together, exactly as found in the bit string (after the 0x04 byte), for a total of 64 bytes.

b2be345ad7899383a9aab4fb968b1c7835cb2cd42c7e97c26f85df8e201f3be8a82983f0a11d6ff31d66ce9932460f2cca21ef96bec9ce235b3d87b0f8fa9e

This is the format returned by the GenKey command when creating a new key pair or requesting the public key of an existing private key. It is also what is supplied to the Verify and ECDH commands.

The other format is only used when storing a public key in a slot. In this case, the X and Y integers are padded out to a 36 byte size for a total of 72 bytes.

00000000b2be345ad7899383a9aab4fb968b1c7835cb2cd42c7e97c26f85df8e201f3be800000000a82983f0a11d6ff31d66ce9932460f2cca21ef96bec9ce235b3d87b0f8fa9e

@lbabaly
Copy link
Author

lbabaly commented May 21, 2018

I managed to figure out that I generated the keys exactly with the same commands as you but I used a different tool to display and write the private key into a c file. And this made the trick, likely this tool uses a different curve and it generates the public key from the private key input. Thanks again for your support.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants