Infineon / optiga-trust-m

OPTIGA™ Trust M Software Framework
https://infineon.github.io/optiga-trust-m/
MIT License
117 stars 48 forks source link

optiga_crypt_ecdsa_sign creates invalid ASN.1 #106

Closed awidegreen closed 3 weeks ago

awidegreen commented 1 year ago

Prerequisites

Can you reproduce the problem reliably? Yes

Did you check current release notes for known issues? Yes

If this is not the latest release, have you checked newer releases? Yes

Description:

optiga_crypt_ecdsa_sign can be used to get a DER signature for given data. In order to make that a valid ASN.1 format, it needs to prepend with SEQ and length indicator (as done in the trustm_engine).

However, the output generated by the optiga_crypt_ecdsa_sign is sometimes not valid ASN.1. An ECDSA signature consist of two INTEGER r and s. When parsing those, certain rules need to be met, like 'when padded with 0x00 in the front in order to indicate a positive number, the next byte needs to be >0x80 (msb set)', see openssl3. This condition is sometimes not met.

We have seen that when using the trustm-engine, it couldn't perform key change due to that issue: the ECDSA_sig becomes NULL as d2i_ECDSA_SIG returns NULL due to the before mentioned ASN.1 issue (leading to an 'internal openssl error' during the TLS setup).

OID: 0xe0f1 curve: P512

Here an example signature output manually prefixed with the SEQ and length (0x30 0x81 0x88):

output_asn1
┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐
│00000000│ 30 81 88 02 42 00 b4 3c ┊ 77 88 af 10 82 5e e7 ce │0×וB0×<┊w×ו×^××│
│00000010│ 05 8d 0e fa 89 7b a0 7e ┊ 6f e0 80 e1 a4 e8 f6 c7 │•×•××{×~┊o×××××××│
│00000020│ fd aa c5 8d 69 76 65 b3 ┊ d8 7f 6e 56 2a 5b c9 42 │××××ive×┊וnV*[×B│
│00000030│ 2e 81 3b 23 c9 ce 1a e7 ┊ 37 24 50 5d a1 2e b2 a5 │.×;#×ו×┊7$P]×.××│
│00000040│ 64 fe 19 b4 70 98 1c 02 ┊ 42 00 46 3b 31 00 af e8 │dו×pו•┊B0F;10××│
│00000050│ 38 40 8e 8d 59 9d 34 de ┊ 44 90 a7 0d 55 6f 43 7b │8@××Y×4×┊D××_UoC{│
│00000060│ 7b 78 c0 58 a7 51 4a 17 ┊ d0 cc 82 48 fd ec 6d 60 │{x×X×QJ•┊×××H××m`│
│00000070│ fa 23 77 71 94 7c a7 1d ┊ f1 73 8b 61 83 bc 10 3b │×#wq×|ו┊×s×a×ו;│
│00000080│ 86 8f 95 36 c3 9b bc 47 ┊ 7c 21 18                │×××6×××G┊|!•     │
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘

and here there error reported by asn1parse:

openssl asn1parse -in output_asn1 -inform DER
    0:d=0  hl=3 l= 136 cons: SEQUENCE
    3:d=1  hl=2 l=  66 prim: INTEGER           :B43C7788AF10825EE7CE058D0EFA897BA07E6FE080E1A4E8F6C7FDAAC58D697665B3D87F6E562A5BC9422E813B23C9CE1AE73724505DA12EB2A564FE19B470981C
   71:d=1  hl=2 l=  66 prim: INTEGER           :BAD INTEGER:[00463B3100AFE838408E8D599D34DE4490A70D556F437B7B78C058A7514A17D0CC8248FDEC6D60FA237771947CA71DF1738B6183BC103B868F9536C39BBC477C2118]

The correct format of the signature should look like this:

output_asn1_fixed
┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐
│00000000│ 30 81 87 02 42 00 b4 3c ┊ 77 88 af 10 82 5e e7 ce │0×וB0×<┊w×ו×^××│
│00000010│ 05 8d 0e fa 89 7b a0 7e ┊ 6f e0 80 e1 a4 e8 f6 c7 │•×•××{×~┊o×××××××│
│00000020│ fd aa c5 8d 69 76 65 b3 ┊ d8 7f 6e 56 2a 5b c9 42 │××××ive×┊וnV*[×B│
│00000030│ 2e 81 3b 23 c9 ce 1a e7 ┊ 37 24 50 5d a1 2e b2 a5 │.×;#×ו×┊7$P]×.××│
│00000040│ 64 fe 19 b4 70 98 1c 02 ┊ 41 46 3b 31 00 af e8 38 │dו×pו•┊AF;10××8│
│00000050│ 40 8e 8d 59 9d 34 de 44 ┊ 90 a7 0d 55 6f 43 7b 7b │@××Y×4×D┊××_UoC{{│
│00000060│ 78 c0 58 a7 51 4a 17 d0 ┊ cc 82 48 fd ec 6d 60 fa │x×X×QJ•×┊××H××m`×│
│00000070│ 23 77 71 94 7c a7 1d f1 ┊ 73 8b 61 83 bc 10 3b 86 │#wq×|ו×┊s×a×ו;×│
│00000080│ 8f 95 36 c3 9b bc 47 7c ┊ 21 18                   │××6×××G|┊!•      │
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘

Note that 00 is removed at position 0x49 and that length indicator decreased from 0x42 to 0x41

openssl asn1parse -in output_asn1_fixed -inform DER
    0:d=0  hl=3 l= 135 cons: SEQUENCE
    3:d=1  hl=2 l=  66 prim: INTEGER           :B43C7788AF10825EE7CE058D0EFA897BA07E6FE080E1A4E8F6C7FDAAC58D697665B3D87F6E562A5BC9422E813B23C9CE1AE73724505DA12EB2A564FE19B470981C
   71:d=1  hl=2 l=  65 prim: INTEGER           :463B3100AFE838408E8D599D34DE4490A70D556F437B7B78C058A7514A17D0CC8248FDEC6D60FA237771947CA71DF1738B6183BC103B868F9536C39BBC477C2118

Steps to Reproduce:

  1. execute ecdsa signing

Expected Result: Always a valid result

Actual Result: r or s are sometimes converted into wrong ASN1 (depending on the value).

Frequency (1/1, 1/50, 1/100):

Build/Commit: release-v4.1.0

Target:

SLS32AIA010MK via I²C

Host OS and Version:

GNU/Linux 5.19.0-46 x86_64

Compiler:

aarch64-unknown-linux-gnu-gcc (GCC) 12

Environment

GNU/Linux 5.15 aarch64

sss551 commented 1 year ago

Hi @awidegreen,

According to my understanding, you are using NIST P521 curve for generating the signature. Can you please confirm?

Can you please try to generate signature by replacing it with another chip in order to find whether the issue is with silicon ?

awidegreen commented 1 year ago

Hi,

it seems that I've initialized the wrong type on the wrong OID. Re-generating the keypair (ecc) made that issue disappear?! I'll report back if I see it again!

/Armin

awidegreen commented 1 year ago

Well, it seems I was correct in first place.

I started over doing the following:

# generate a new keypair using OID 0xe0f1 and ECC P521 
trustm_ecc_keygen -g 0xe0f1 -t 0x15 -k 0x03 -o test_e0f3_pub.pem -s

# generate 16 bytes of random data
dd bs=1 count=16 if=/dev/urandom of=rand.bin

# sign given random data with ECC key.
trustm_ecc_sign -X -k 0xE0F1 -i rand.bin -o rand.bin.sig

The last command will randomly segfault. However, I enabled trustm debug traces and saw that every time the signing ends up in a segfault the following pal log was printed:

pal_loger_write :                     05 00 8E 08 20 00 00 00 88 02 42 01 CC 23 B8 23 17 E9 4B 75 96 7E 99 80 83 3D 0E 3D B7 AA C2 D7

pal_loger_write :                     7B D9 51 E0 BB A6 42 24 3C 4B 1A 6A 2D CD E3 07 C8 80 EB 37 0E 88 96 22 A0 0C F0 BB 31 FA 30 4F

pal_loger_write :                     5D 5F 69 F0 5C AA FA 46 2D 80 5E DE 32 02 42 00 03 1F 1F 32 E0 BE 7F 01 0E F0 4F 73 71 5B C9 BB

pal_loger_write :                     F8 88 0E B5 0E 86 BD 73 D2 C5 BD 4E 6B 9C AF EC 22 3C EE 3D B0 DE 37 8A 09 16 2B E8 05 44 DA 4E

pal_loger_write :                     57 B9 11 44 9C 19 D1 BE 4A 93 8E 6B F5 EC FB DF 70 A7 AD

Note: when the ASN1 was correct, the trustm_ecc_sign finished successfully!

As you can see, the second bigint, starts with 02 42 00 03 which is the same problem I initially described.

sss551 commented 1 year ago

Hi @awidegreen,

In the trustm_ecc_keygen command can you specify why you have used key type as 0x15 which is not from the available options mentioned in the repo. image

awidegreen commented 1 year ago

sorry for that; I was about to edit the text - it should be: trustm_ecc_keygen -X -k 0x05 -t 0x13 -g 0xe0f1 -o test_e0f3_pub.pem -s Further, I now tested on a different board and reproduced the problem.

sss551 commented 1 year ago

Hi @awidegreen ,

In the recent command that you have shared, the value of the key type is 0x13 which is not from the available options from the image shared in my previous reply.

In case you want to use the key for signing, can you please try to generate the key with the below command and check whether you are facing same error? trustm_ecc_keygen -X -k 0x05 -t 0x10 -g 0xe0f1 -o test_e0f3_pub.pem -s

awidegreen commented 1 year ago

trustm_ecc_keygen -X -k 0x05 -t 0x10 -g 0xe0f1 -o test_e0f3_pub.pem -s and a trustm_ecc_sign afterwards results in the same error:


> trustm_ecc_sign -X -k 0xe0f1 -i rand.bin -o rand.bin.sig

Bypass Shielded Communication.
18383:trustm_helper/trustm_helper.c:1115 trustm_Open: >
18383:trustm_helper/trustm_helper.c:1116 trustm_Open: trustm_Open with recovery

18383:trustm_helper/trustm_helper_ipc_lock.c:68 trustm_ipc_acquire: >
18383:trustm_helper/trustm_helper_ipc_lock.c:79 trustm_ipc_acquire: Lock Mutex:/trustm-mutex: b6f81000

18383:trustm_helper/trustm_helper_ipc_lock.c:85 trustm_ipc_acquire: process owner dead, make it consistent

18383:trustm_helper/trustm_helper.c:1041 _trustm_Open: >
18383:trustm_helper/trustm_helper.c:1057 _trustm_Open: TrustM util instance created.

18383:trustm_helper/trustm_helper.c:1069 _trustm_Open: TrustM crypt instance created.

18383:trustm_helper/trustm_helper.c:1075 _trustm_Open: TrustM Open.

18383:trustm_helper/trustm_helper.c:1083 _trustm_Open: optiga_util_open_application:Init

pal_loger_write : [optiga util]     : optiga_util_open_application
pal_loger_write :

pal_loger_write : [optiga cmd]      : optiga_cmd_open_application
pal_loger_write :

pal_loger_write : [optiga cmd]      : Sending open app command...
pal_loger_write :

pal_loger_write : [optiga comms]    : >>>>
pal_loger_write :

pal_loger_write :                     Length of data - 0x001B
pal_loger_write :

pal_loger_write :                     03 00 16 08 20 F0 00 00 10 D2 76 00 00 04 47 65 6E 41 75 74 68 41 70 70 6C BE 40

pal_loger_write : [optiga comms]    : <<<<
pal_loger_write :

pal_loger_write :                     Length of data - 0x000B
pal_loger_write :

pal_loger_write :                     00 00 06 08 20 00 00 00 00 19 04

pal_loger_write : [optiga cmd]      : Processing response for open app command...
pal_loger_write :

pal_loger_write : [optiga cmd]      : Response of open app command is processed...
pal_loger_write :

18383:trustm_helper/trustm_helper.c:72 helper_optiga_util_callback: optiga_lib_status: 0

18383:trustm_helper/trustm_helper.c:1025 trustm_WaitForCompletion:  max wait_time:6000, Tick Counter: 19
18383:trustm_helper/trustm_helper.c:1101 _trustm_Open: Success : optiga_util_open_application

18383:trustm_helper/trustm_helper.c:1104 _trustm_Open: <
18383:trustm_helper/trustm_helper.c:1131 trustm_Open: <
========================================================
OID Key          : 0xE0F1
Output File Name : rand.bin.sig
Input File Name  : rand.bin
Input data[16] :
        A5 D2 56 47 47 AD D7 56 7B F3 22 11 3F 4D AF 2B

pal_loger_write : [optiga crypt]    : optiga_crypt_ecdsa_sign
pal_loger_write :

pal_loger_write : [optiga cmd]      : optiga_cmd_calc_sign
pal_loger_write :

pal_loger_write : [optiga cmd]      : Sending calculate sign command..
pal_loger_write :

pal_loger_write : [optiga comms]    : >>>>
pal_loger_write :

pal_loger_write :                     Length of data - 0x0023
pal_loger_write :

pal_loger_write :                     04 00 1E 08 20 B1 11 00 18 01 00 10 A5 D2 56 47 47 AD D7 56 7B F3 22 11 3F 4D AF 2B 03 00 02 E0

pal_loger_write :                     F1 EF 47

pal_loger_write : [optiga comms]    : <<<<
pal_loger_write :

pal_loger_write :                     Length of data - 0x0093
pal_loger_write :

pal_loger_write :                     05 00 8E 08 20 00 00 00 88 02 42 00 4D AF 0F 2E BE D6 01 4C 7C 8D E6 42 44 75 F5 3F 54 40 AB FB

pal_loger_write :                     48 52 D7 47 79 D3 08 25 4D 06 94 A4 53 93 0D 8C BD A7 5B 9F F3 09 2A FC B3 02 DB D3 01 52 16 35

pal_loger_write :                     0D AF 59 C7 AF A9 98 3D 1D FA 0D 14 4B 02 42 01 A9 60 50 51 CC BB 75 0A 71 3A 22 87 2D 4C 48 F8

pal_loger_write :                     34 69 9B 0A B7 67 7A F5 57 00 77 2E 78 E4 F3 8B A7 F0 51 C1 B5 0F 8A DB 6E FE 91 1F 47 A4 60 3B

pal_loger_write :                     39 75 68 94 A6 41 CA D8 37 E2 F7 D0 E7 A3 B5 03 91 43 75

pal_loger_write : [optiga cmd]      : Processing response for calculate sign command...
pal_loger_write :

pal_loger_write : [optiga cmd]      : Response of calculate sign command is processed...
pal_loger_write :

18383:trustm_helper/trustm_helper.c:1025 trustm_WaitForCompletion:  max wait_time:6000, Tick Counter: 226
Segmentation fault
ying-css commented 1 year ago

Hi @awidegreen, Thank you for the log. We will look into this issue and resolve it very soon.

aoune-ayoub commented 3 weeks ago

Issue resolved with the introduction of version 5.1 :

https://github.com/Infineon/optiga-trust-m/blob/main/CHANGELOG.md#:~:text=Improved%20signature%20encoding%20for%20secp521r1%20signature.