OP-TEE / optee_os

Trusted side of the TEE
Other
1.59k stars 1.07k forks source link

[PKCS11 TA] Incorrect result of ECDH1-DERIVE #6715

Closed maroueneboubakri closed 8 months ago

maroueneboubakri commented 8 months ago

Hello, Seems that xtest does not test CKM_ECDH1_DERIVE mechanism. In my TLS server I found that it generates a wrong shared secret compared to what client generated.
So I tried to replicate using some command line, and indeed it generates wrong data, could you please investigate ?

openssl ecparam -name prime256v1 -genkey -out 1.key
openssl ec -in 1.key -inform PEM -pubout -out  1.pub -outform PEM
openssl ecparam -name prime256v1 -genkey -out 2.key
openssl ec -in 2.key -inform PEM -pubout -out  2.pub -outform PEM

pkcs11-tool --module /usr/lib/libckteec.so.0 --token-label EasyEVSE -l --pin 12345678 --write-object 1.key --type privkey --label "AlicePriv" --sensitive --private --usage-sign --usage-decrypt --usage-derive
pkcs11-tool --module /usr/lib/libckteec.so.0 --token-label EasyEVSE -l --pin 12345678 --write-object 1.pub --type pubkey --label "AlicePub" --usage-sign --usage-decrypt

pkcs11-tool --module /usr/lib/libckteec.so.0 --token-label EasyEVSE -l --pin 12345678 --write-object 2.key --type privkey --label "BobPriv" --sensitive --private --usage-sign --usage-decrypt --usage-derive
pkcs11-tool --module /usr/lib/libckteec.so.0 --token-label EasyEVSE -l --pin 12345678 --write-object 2.pub --type pubkey --label "BobPub" --usage-sign --usage-decrypt

pkcs11-tool --module /usr/lib/libckteec.so.0 --read-object --type pubkey --label "AlicePub" --token-label EasyEVSE --pin 12345678 -o /tmp/pub.der
pkcs11-tool --module /usr/lib/libckteec.so.0 --derive -m ECDH1-DERIVE --label "BobPriv" --token-label EasyEVSE --pin 12345678 --input-file /tmp/pub.der --output-file /tmp/bytes

hexdump -C /tmp/bytes

00000000  d1 0f 88 29 fb 6f a6 91  f3 e3 da a4 32 5a 68 46  |...).o......2ZhF|
00000010  0d 81 7a 68 cf d8 3e 98  f4 0f cd 7e e7 5d 56 3c  |..zh..>....~.]V<|
00000020

pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so --token-label EasyEVSE -l --pin 12345678 --write-object 1.key --type privkey --label "AlicePriv" --sensitive --private --usage-sign --usage-decrypt --usage-derive
pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so --token-label EasyEVSE -l --pin 12345678 --write-object 1.pub --type pubkey --label "AlicePub" --usage-sign --usage-decrypt

pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so --token-label EasyEVSE -l --pin 12345678 --write-object 2.key --type privkey --label "BobPriv" --sensitive --private --usage-sign --usage-decrypt --usage-derive
pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so --token-label EasyEVSE -l --pin 12345678 --write-object 2.pub --type pubkey --label "BobPub" --usage-sign --usage-decrypt

pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so --read-object --type pubkey --label "AlicePub" --token-label EasyEVSE --pin 12345678 -o /tmp/pub.der
pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so --derive -m ECDH1-DERIVE --label "BobPriv" --token-label EasyEVSE --pin 12345678 --input-file /tmp/pub.der --output-file /tmp/bytes

hexdump -C /tmp/bytes
00000000  e0 68 65 b9 fc a7 84 66  b9 aa 28 fe ce 9f d4 af  |.he....f..(.....|
00000010  1c 4f 01 5e d8 80 54 28  ed 4c 9d e5 49 c0 48 4f  |.O.^..T(.L..I.HO|
00000020

Version is 3.21.

@etienne-lms @vesajaaskelainen

Best Maro

vesajaaskelainen commented 8 months ago

If I recall correctly when support was brought in there were a problem is there a example where the feature is used with pkcs#11 to be able to verify that it actually does what it is expected to do.

There are (at least) two modes:

Documentation refers it with following:

2.3.9 Elliptic curve Diffie-Hellman key derivation The elliptic curve Diffie-Hellman (ECDH) key derivation mechanism, denoted CKM_ECDH1_DERIVE, is a mechanism for key derivation based on the Diffie-Hellman version of the elliptic curve key agreement scheme, as defined in ANSI X9.63, where each party contributes one key pair all using the same EC domain parameters.

and

2.3.10 Elliptic curve Diffie-Hellman with cofactor key derivation The elliptic curve Diffie-Hellman (ECDH) with cofactor key derivation mechanism, denoted CKM_ECDH1_COFACTOR_DERIVE, is a mechanism for key derivation based on the cofactor Diffie-Hellman version of the elliptic curve key agreement scheme, as defined in ANSI X9.63, where each party contributes one key pair all using the same EC domain parameters. Cofactor multiplication is computationally efficient and helps to prevent security problems like small group attacks.

Now if you connect this problem to TEE Internal Core API then it gets a bit vague what you should actually do. And if I recall correctly there were even implementation differences what crypto backend was in use.

Here is the original PR: https://github.com/OP-TEE/optee_os/pull/5130

Perhaps related comments on the topic:

Thus if there is good authoritative source with what to verify that we are operating correctly that would be best.

maroueneboubakri commented 8 months ago

If I recall correctly when support was brought in there were a problem is there a example where the feature is used with pkcs#11 to be able to verify that it actually does what it is expected to do.

There are (at least) two modes:

  • CKM_ECDH1_DERIVE
  • CKM_ECDH1_COFACTOR_DERIVE

Documentation refers it with following:

2.3.9 Elliptic curve Diffie-Hellman key derivation The elliptic curve Diffie-Hellman (ECDH) key derivation mechanism, denoted CKM_ECDH1_DERIVE, is a mechanism for key derivation based on the Diffie-Hellman version of the elliptic curve key agreement scheme, as defined in ANSI X9.63, where each party contributes one key pair all using the same EC domain parameters.

and

2.3.10 Elliptic curve Diffie-Hellman with cofactor key derivation The elliptic curve Diffie-Hellman (ECDH) with cofactor key derivation mechanism, denoted CKM_ECDH1_COFACTOR_DERIVE, is a mechanism for key derivation based on the cofactor Diffie-Hellman version of the elliptic curve key agreement scheme, as defined in ANSI X9.63, where each party contributes one key pair all using the same EC domain parameters. Cofactor multiplication is computationally efficient and helps to prevent security problems like small group attacks.

Now if you connect this problem to TEE Internal Core API then it gets a bit vague what you should actually do. And if I recall correctly there were even implementation differences what crypto backend was in use.

Here is the original PR: #5130

Perhaps related comments on the topic:

Thus if there is good authoritative source with what to verify that we are operating correctly that would be best.

@vesajaaskelainen thank you, went through all comments and got confused, a lot of comments to digest at least, is it supposed to work or not ? in the example I provided it works using SoftHSMv2, I have 2 applications, a TLS server (using PKCS11) and TLS client, using crypto implemented in SW. TLS server does not generate a correct result for CKM_ECDH1_DERIVE on OP-TEE PKCS11 TA, while it does using SoftHSMv2. There should be bug. As user, not sure if going through all PKCS11 specs would help me.

vesajaaskelainen commented 8 months ago

Thus if there is good authoritative source with what to verify that we are operating correctly that would be best.

@vesajaaskelainen thank you, went through all comments and got confused, a lot of comments to digest at least, is it supposed to work or not ? in the example I provided it works using SoftHSMv2, I have 2 applications, a TLS server (using PKCS11) and TLS client, using crypto implemented in SW. TLS server does not generate a correct result for CKM_ECDH1_DERIVE on OP-TEE PKCS11 TA, while it does using SoftHSMv2. There should be bug. As user, not sure if going through all PKCS11 specs would help me.

Did some testing with latest op-tee:

<on ubuntu 22.04 lts>

$ openssl version
OpenSSL 3.0.2 15 Mar 2022 (Library: OpenSSL 3.0.2 15 Mar 2022)

openssl ecparam -name prime256v1 -genkey -out alice.key
openssl ec -in alice.key -inform PEM -pubout -out alice.pub -outform PEM
openssl ecparam -name prime256v1 -genkey -out bob.key
openssl ec -in bob.key -inform PEM -pubout -out bob.pub -outform PEM

<op-tee in qemu>

$ openssl version
OpenSSL 3.0.12 24 Oct 2023 (Library: OpenSSL 3.0.12 24 Oct 2023)

cat > /tmp/alice.key << EOF
-----BEGIN EC PARAMETERS-----
BggqhkjOPQMBBw==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIFgGcO/pY5x/QDzamMHinaylT/SHMycE/e9/kYCKwQ/5oAoGCCqGSM49
AwEHoUQDQgAE4XQSakKqwHL+jIEygDmjOSk34m4kDAXqFDZ80buTkhX31W3n6sa0
DIDcirSqZZ2csR/LRpDeoKGWOvd4Fl7zow==
-----END EC PRIVATE KEY-----
EOF

cat > /tmp/alice.pub << EOF
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4XQSakKqwHL+jIEygDmjOSk34m4k
DAXqFDZ80buTkhX31W3n6sa0DIDcirSqZZ2csR/LRpDeoKGWOvd4Fl7zow==
-----END PUBLIC KEY-----
EOF

cat > /tmp/bob.key << EOF
-----BEGIN EC PARAMETERS-----
BggqhkjOPQMBBw==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIBsrsnzgPgojO4px0Q1BG9brlvtV1GDvHMhWcFJP3Vu8oAoGCCqGSM49
AwEHoUQDQgAEuN2HtgwYrNcDC7rR7AAzc+ZtfNV2WPYgoo1qlozeW+2WsSTseCEj
iH38AqHvhswLY2pByCoF1rFghvuHH+XpgA==
-----END EC PRIVATE KEY-----
EOF

cat > /tmp/bob.pub << EOF
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuN2HtgwYrNcDC7rR7AAzc+ZtfNV2
WPYgoo1qlozeW+2WsSTseCEjiH38AqHvhswLY2pByCoF1rFghvuHH+XpgA==
-----END PUBLIC KEY-----
EOF

openssl ec -in /tmp/alice.key -outform DER -out /tmp/alice.key.der
openssl ec -in /tmp/alice.key -pubout -outform DER -out /tmp/alice.pub.der

openssl ec -in /tmp/bob.key -outform DER -out /tmp/bob.key.der
openssl ec -in /tmp/bob.key -pubout -outform DER -out /tmp/bob.pub.der

pkcs11-tool --module ${PKCS11_MODULE} --token ${PKCS11_TOKEN} --login --pin ${PKCS11_USER_PIN} --write-object /tmp/alice.key.der --type privkey --label "alice" --sensitive --private --usage-sign --usage-decrypt --usage-derive
pkcs11-tool --module ${PKCS11_MODULE} --token ${PKCS11_TOKEN} --login --pin ${PKCS11_USER_PIN} --write-object /tmp/alice.pub.der --type pubkey --label "alice" --usage-sign --usage-decrypt

pkcs11-tool --module ${PKCS11_MODULE} --token ${PKCS11_TOKEN} --login --pin ${PKCS11_USER_PIN} --write-object /tmp/bob.key.der --type privkey --label "bob" --sensitive --private --usage-sign --usage-decrypt --usage-derive
pkcs11-tool --module ${PKCS11_MODULE} --token ${PKCS11_TOKEN} --login --pin ${PKCS11_USER_PIN} --write-object /tmp/bob.pub.der --type pubkey --label "bob" --usage-sign --usage-decrypt

pkcs11-tool --module ${PKCS11_MODULE} --token ${PKCS11_TOKEN} --login --pin ${PKCS11_USER_PIN} --list-objects

Public Key Object; EC  EC_POINT 256 bits
  EC_POINT:   044104b8dd87b60c18acd7030bbad1ec003373e66d7cd57658f620a28d6a968cde5bed96b124ec782123887dfc02a1ef86cc0b636a41c82a05d6b16086fb871fe5e980
  EC_PARAMS:  06082a8648ce3d030107
  label:      bob
  Usage:      encrypt, verify
  Access:     none
Private Key Object; EC
  label:      bob
  Usage:      decrypt, sign, derive
  Access:     sensitive
Public Key Object; EC  EC_POINT 256 bits
  EC_POINT:   044104e174126a42aac072fe8c81328039a3392937e26e240c05ea14367cd1bb939215f7d56de7eac6b40c80dc8ab4aa659d9cb11fcb4690dea0a1963af778165ef3a3
  EC_PARAMS:  06082a8648ce3d030107
  label:      alice
  Usage:      encrypt, verify
  Access:     none
Private Key Object; EC
  label:      alice
  Usage:      decrypt, sign, derive
  Access:     sensitive

pkcs11-tool --module ${PKCS11_MODULE} --token ${PKCS11_TOKEN} --login --pin ${PKCS11_USER_PIN} --derive -m ECDH1-DERIVE --label "bob" --input-file /tmp/alice.pub.der --output-file /tmp/ecdh.secret

hexdump -C /tmp/ecdh.secret
00000000  18 38 d9 fb 9d c1 c2 b9  97 89 3e 1a 93 7f a4 5f  |.8........>...._|
00000010  7c 4f 89 8d 3c 3e 4d 4a  e4 82 d8 e6 40 31 14 c1  ||O..<>MJ....@1..|
00000020

openssl pkeyutl -derive -inkey /tmp/bob.key -peerkey /tmp/alice.pub -out /tmp/ecdh.openssl.secret
hexdump -C /tmp/ecdh.openssl.secret
00000000  18 38 d9 fb 9d c1 c2 b9  97 89 3e 1a 93 7f a4 5f  |.8........>...._|
00000010  7c 4f 89 8d 3c 3e 4d 4a  e4 82 d8 e6 40 31 14 c1  ||O..<>MJ....@1..|
00000020

At least with this test both op-tee and openssl seems to agree.

You could try to sniff out with pkcs11-spy what kind of PKCS11 API calls there are.

export PKCS11SPY=/usr/lib/libckteec.so.0
export PKCS11SPY_OUTPUT=/tmp/pkcs11-spy.log
export PKCS11_MODULE=/usr/lib/pkcs11-spy.so

Could you share your software setup so that one could try to replicate that?

If in example if you use openssl with libp11's pkcs11-engine or latchset's pkcs11-provider or something else is also of interest. Also please tell what versions of the software you are using.

maroueneboubakri commented 8 months ago

Upgrading to 4.0.0 it works, v3.21 does not work.

maroueneboubakri commented 8 months ago

Thank you for having investigating @vesajaaskelainen !

vesajaaskelainen commented 8 months ago

Upgrading to 4.0.0 it works, v3.21 does not work.

The fix might be this (and its friends): https://github.com/OP-TEE/optee_os/commit/7c24332175d8a3a60264f9de2929fd16591a0e0e

But good that it started working.

maroueneboubakri commented 8 months ago

Upgrading to 4.0.0 it works, v3.21 does not work.

The fix might be this (and its friends): 7c24332

But good that it started working.

That should be yes ! I raised another issue with regards to signing with an imported EC private key https://github.com/OP-TEE/optee_os/issues/6710 and found that PR. All is good then ! Have a nice weekend :)