github-af / SmartPGP

SmartPGP is a JavaCard implementation of the OpenPGP card specifications
GNU General Public License v2.0
232 stars 48 forks source link

Memory leak #29

Open bitlogik opened 3 years ago

bitlogik commented 3 years ago

We identified a memory leak in this applet. Memory management on Javacard is very hard, especially because the limited RAM resource of the card chip which is approximately 2-3kB free maximum.

We believe this issue affects all cards on all JCOP versions. This is just a matter of how many operations are required to fill up the memory. This is a very annoying bug, as the card for example can't no more sign after a given number of signatures. Our tests show that even a power cycle of the card doesn't free the memory. This is a "feature" of JCOP, hence requiring some special techniques about memory management. Also, a applet reset (Terminate+Activate) doesn't clear the transient memory. This issue can lead to disastrous consequences as this can prevent any new signatures or others cryptographic operations with keys which only exists in the secure applet. Only an applet re-installation put the applet on the right track.

We have even decreased some RAM constants parameters, and the issue is nearly the same. The signature crashes forever after around 20 signatures.

For now, our team doesn't have some much time to fix this issue. But here are some recommendations to fix this :

Note that the instantiation of nearly everything at the applet installation can lead to an other similar issue. The install function process is always performed in a transactional reversible process, which means every steps are saved in RAM. So the processing can't take too much memory. Most of the time this is OK. Still, if this happens, one should defer the instantiation at a later stage, like splitting the instantiation in 2 parts. For example at the very first select or at the first. The difficult part then in this case is to locate when this second instantiation part should happen.

Log details about the issue : Performs with https://gist.github.com/bitlogik/44a7502f0b303ec10a3f45a810ac82fa using OpenPGPpy on a J3R110.

$>python3 demo/signSmartPGP.py
Trying to reach OpenPGP app
Available readers :
 - Identiv uTrust 3700 F CL Reader 0
Trying with reader : Identiv uTrust 3700 F CL Reader 0
 Sending 0xA4 command with 6 bytes data
-> 00 A4 04 00 06 D2 76 00 01 24 01
 Received 0 bytes data : SW 0x9000 - duration: 11.5 ms
A device detected, using Identiv uTrust 3700 F CL Reader 0
Read Data  in 0x006E
 Sending 0xCA command with 0 bytes data
-> 00 CA 00 6E 00
 Received 220 bytes data : SW 0x9000 - duration: 20.0 ms
<- 6E 81 D9 4F 10 D2 76 00 01 24 01 03 04 AF AF 00 00 00 00 00 00 5F 52 0A 00 C1 C5 73 C0 01 80 05 90 00 73 81 B7 C0 0A FF 03 00 20 04 80 00 FF 00 00 C1 06 01 08 00 00 11 03 C2 06 01 08 00 00 11 03 C3 06 01 08 00 00 11 03 C4 07 00 7F 7F 7F 03 00 03 C5 3C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C6 3C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 CD 0C 00 00 00 00 00 00 00 00 00 00 00 00
Read Data  in 0x004F
 Sending 0xCA command with 0 bytes data
-> 00 CA 00 4F 00
 Received 16 bytes data : SW 0x9000 - duration: 8.7 ms
<- D2 76 00 01 24 01 03 04 AF AF 00 00 00 00 00 00
PGP version : 3.4
Manufacturer : ANSSI (0xAFAF)
Serial : 0
Read Data  in 0x7F66
 Sending 0xCA command with 0 bytes data
-> 00 CA 7F 66 00
 Received 11 bytes data : SW 0x9000 - duration: 9.0 ms
<- 7F 66 08 02 02 01 00 02 02 01 00
Read Data  in 0x7F74
 Sending 0xCA command with 0 bytes data
-> 00 CA 7F 74 00
 Received 0 bytes data : SW 0x6A88 - duration: 8.0 ms
Button ? No
OpenPGP device detected
 Sending 0x47 command with 2 bytes data
-> 00 47 81 00 02 B6 00
 Received 0 bytes data : SW 0x6A88 - duration: 8.1 ms
Setup the new device
Enter PIN3 (PUK) :
 Sending 0x20 command with 8 bytes data
-> 00 20 00 83 08 31 32 33 34 35 36 37 38
 Received 0 bytes data : SW 0x9000 - duration: 16.2 ms
Put data 132A8648CE3D030107 in 0x00C1
 Sending 0xDA command with 9 bytes data
-> 00 DA 00 C1 09 13 2A 86 48 CE 3D 03 01 07
 Received 0 bytes data : SW 0x9000 - duration: 25.7 ms
 Sending 0x47 command with 2 bytes data
-> 00 47 80 00 02 B6 00
 Received 70 bytes data : SW 0x9000 - duration: 256.8 ms
<- 7F 49 43 86 41 04 CD 39 E0 C9 A1 D0 FB 64 BC 4D 78 3C 92 D4 F6 91 B9 61 22 E2 7B C2 0B A1 1A 5F 80 C5 8F 76 8D 63 A0 6E 45 B7 AE 9B 96 1F 7E 82 32 21 D5 53 A7 92 F9 E2 E4 CB 0F 79 E4 C9 58 50 A1 5B 0A F6 58 97
Device "SIG" public key read
Enter PIN1 :

PublicKey for signature : 0x04cd39e0c9a1d0fb64bc4d783c92d4f691b96122e27bc20ba11a5f80c58f768d63a06e45b7ae9b961f7e823221d553a792f9e2e4cb0f79e4c95850a15b0af65897
 Sending 0x20 command with 6 bytes data
-> 00 20 00 81 06 31 32 33 34 35 36
 Received 0 bytes data : SW 0x9000 - duration: 16.7 ms
 Sending 0x2A command with 32 bytes data
-> 00 2A 9E 9A 20 F1 10 4E AD 6B 42 85 42 7C 67 8C C0 FC 85 D1 2C F6 7B 3F 20 78 B6 E3 4A 44 2F C5 F6 4E 01 30 EB
 Received 66 bytes data : SW 0x9000 - duration: 92.8 ms
<- 00 62 DE CC FA 8D E1 36 72 C0 5E 25 15 C8 5A 4A 22 FD E4 21 B9 5D 3B 81 51 1B 92 BB FD DE F5 78 13 00 D1 33 48 EC F1 DB 6E E9 A7 F3 C9 27 FF 3B 5E AC 55 88 52 2A 02 29 0D 09 3B 28 2F 74 E8 21 E1 36
Signature : 0x3045022062deccfa8de13672c05e2515c85a4a22fde421b95d3b81511b92bbfddef57813022100d13348ecf1db6ee9a7f3c927ff3b5eac5588522a02290d093b282f74e821e136
OK
 Sending 0x20 command with 6 bytes data
-> 00 20 00 81 06 31 32 33 34 35 36
 Received 0 bytes data : SW 0x9000 - duration: 17.7 ms
 Sending 0x2A command with 32 bytes data
-> 00 2A 9E 9A 20 F1 10 4E AD 6B 42 85 42 7C 67 8C C0 FC 85 D1 2C F6 7B 3F 20 78 B6 E3 4A 44 2F C5 F6 4E 01 30 EB
 Received 66 bytes data : SW 0x9000 - duration: 93.4 ms
<- 00 4C 47 9C 22 2E 24 C0 D0 89 9C 46 16 7A 19 02 72 98 0E 4B CF 1E 5B 3C 04 79 60 DA 1D 6C F5 B8 F1 00 E4 81 90 6C 65 AE D2 0E 3B 25 AB 5F 39 44 D8 BE 4D 4D FC 58 F8 A4 D6 86 6F 37 8C 82 35 B8 1E 76
Signature : 0x304502204c479c222e24c0d0899c46167a190272980e4bcf1e5b3c047960da1d6cf5b8f1022100e481906c65aed20e3b25ab5f3944d8be4d4dfc58f8a4d6866f378c8235b81e76
OK
 Sending 0x20 command with 6 bytes data
-> 00 20 00 81 06 31 32 33 34 35 36
 Received 0 bytes data : SW 0x9000 - duration: 17.0 ms
 Sending 0x2A command with 32 bytes data
-> 00 2A 9E 9A 20 F1 10 4E AD 6B 42 85 42 7C 67 8C C0 FC 85 D1 2C F6 7B 3F 20 78 B6 E3 4A 44 2F C5 F6 4E 01 30 EB
 Received 66 bytes data : SW 0x9000 - duration: 92.9 ms
<- 00 C6 06 ED 2E 42 CF 1C 75 74 57 57 BF 8A FD 49 7C 70 ED E8 A8 6F C2 1A 79 21 C8 A7 99 7B EC 62 79 00 02 52 39 49 49 E7 E1 BF D6 6E F3 DA EC 41 A5 84 72 E1 A1 73 20 19 7A 0A F0 B8 A1 47 4E 9D 8D 48
Signature : 0x3045022100c606ed2e42cf1c75745757bf8afd497c70ede8a86fc21a7921c8a7997bec627902200252394949e7e1bfd66ef3daec41a58472e1a17320197a0af0b8a1474e9d8d48
OK
 Sending 0x20 command with 6 bytes data
-> 00 20 00 81 06 31 32 33 34 35 36
 Received 0 bytes data : SW 0x9000 - duration: 17.4 ms
 Sending 0x2A command with 32 bytes data
-> 00 2A 9E 9A 20 F1 10 4E AD 6B 42 85 42 7C 67 8C C0 FC 85 D1 2C F6 7B 3F 20 78 B6 E3 4A 44 2F C5 F6 4E 01 30 EB
 Received 66 bytes data : SW 0x9000 - duration: 93.0 ms
<- 00 F8 46 17 AA A2 16 75 A0 AE 18 88 34 46 54 6A E3 01 77 EC CB B3 23 21 4A 33 54 AF CC EA 0E 05 5B 00 8D 20 4C BE E1 07 93 4C 30 FF 99 FD 47 20 64 C0 72 15 A5 3E 1F 45 1F 8F 9F FC 97 C4 DE C2 D6 D9
Signature : 0x3046022100f84617aaa21675a0ae18883446546ae30177eccbb323214a3354afccea0e055b0221008d204cbee107934c30ff99fd472064c07215a53e1f451f8f9ffc97c4dec2d6d9
OK
 Sending 0x20 command with 6 bytes data
-> 00 20 00 81 06 31 32 33 34 35 36
 Received 0 bytes data : SW 0x9000 - duration: 16.4 ms
 Sending 0x2A command with 32 bytes data
-> 00 2A 9E 9A 20 F1 10 4E AD 6B 42 85 42 7C 67 8C C0 FC 85 D1 2C F6 7B 3F 20 78 B6 E3 4A 44 2F C5 F6 4E 01 30 EB
 Received 66 bytes data : SW 0x9000 - duration: 92.8 ms
<- 00 3D 4A 9D E1 39 8E 5A B1 64 45 3A E3 E1 B7 6D FD CE B5 76 0C 30 07 A8 F0 88 5E 96 CC E6 8D 3B 1E 00 94 17 FE EB 0B 90 8D 77 8C BE 91 9A 96 5F 20 BD 98 84 20 59 03 58 97 DB E0 B5 87 6F 6E 88 D3 58
Signature : 0x304502203d4a9de1398e5ab164453ae3e1b76dfdceb5760c3007a8f0885e96cce68d3b1e0221009417feeb0b908d778cbe919a965f20bd98842059035897dbe0b5876f6e88d358
OK
 Sending 0x20 command with 6 bytes data
-> 00 20 00 81 06 31 32 33 34 35 36
 Received 0 bytes data : SW 0x9000 - duration: 17.0 ms
 Sending 0x2A command with 32 bytes data
-> 00 2A 9E 9A 20 F1 10 4E AD 6B 42 85 42 7C 67 8C C0 FC 85 D1 2C F6 7B 3F 20 78 B6 E3 4A 44 2F C5 F6 4E 01 30 EB
 Received 64 bytes data : SW 0x9000 - duration: 93.2 ms
<- 15 7D 16 F6 AC 89 A2 B6 C7 24 5C 0D F5 91 7A E6 CD 61 31 62 08 2A 9E 3D B6 DE 40 2F A2 00 21 3D 5D BE 71 23 2D ED 47 FC AA 0F AC AD 2B 93 7F B3 67 81 F8 B9 09 CA 32 83 0E 52 CF D4 5D B7 B6 E6
Signature : 0x30440220157d16f6ac89a2b6c7245c0df5917ae6cd613162082a9e3db6de402fa200213d02205dbe71232ded47fcaa0facad2b937fb36781f8b909ca32830e52cfd45db7b6e6
OK
 Sending 0x20 command with 6 bytes data
-> 00 20 00 81 06 31 32 33 34 35 36
 Received 0 bytes data : SW 0x9000 - duration: 17.1 ms
 Sending 0x2A command with 32 bytes data
-> 00 2A 9E 9A 20 F1 10 4E AD 6B 42 85 42 7C 67 8C C0 FC 85 D1 2C F6 7B 3F 20 78 B6 E3 4A 44 2F C5 F6 4E 01 30 EB
 Received 66 bytes data : SW 0x9000 - duration: 93.3 ms
<- 00 22 9E 13 E2 8B 0F F3 FE 5C C4 70 81 C8 33 11 D7 D6 FB 84 7C A9 11 F2 DF F1 65 7E 31 87 48 76 4A 00 88 7D 5A 45 C9 4B 97 3E DA 48 3D 98 E0 BD 2C 74 C7 CE C2 BE FA 9E AC A1 1C 51 26 8B AD 4E 87 F1
Signature : 0x30450220229e13e28b0ff3fe5cc47081c83311d7d6fb847ca911f2dff1657e318748764a022100887d5a45c94b973eda483d98e0bd2c74c7cec2befa9eaca11c51268bad4e87f1
OK
 Sending 0x20 command with 6 bytes data
-> 00 20 00 81 06 31 32 33 34 35 36
 Received 0 bytes data : SW 0x9000 - duration: 17.5 ms
 Sending 0x2A command with 32 bytes data
-> 00 2A 9E 9A 20 F1 10 4E AD 6B 42 85 42 7C 67 8C C0 FC 85 D1 2C F6 7B 3F 20 78 B6 E3 4A 44 2F C5 F6 4E 01 30 EB
 Received 64 bytes data : SW 0x9000 - duration: 93.3 ms
<- 7D CB 49 88 F2 99 F5 45 17 F3 87 58 F2 E1 35 4E A7 D1 D3 C1 8A 25 3C 14 89 3F 0E 0F FC 76 D1 CA 79 07 5E 2F 1D A6 69 26 A7 EE D9 65 33 98 07 5C 3F DA D4 EE ED 5D FE 82 09 78 70 10 CD 5E 2F CE
Signature : 0x304402207dcb4988f299f54517f38758f2e1354ea7d1d3c18a253c14893f0e0ffc76d1ca022079075e2f1da66926a7eed9653398075c3fdad4eeed5dfe8209787010cd5e2fce
OK
 Sending 0x20 command with 6 bytes data
-> 00 20 00 81 06 31 32 33 34 35 36
 Received 0 bytes data : SW 0x9000 - duration: 16.8 ms
 Sending 0x2A command with 32 bytes data
-> 00 2A 9E 9A 20 F1 10 4E AD 6B 42 85 42 7C 67 8C C0 FC 85 D1 2C F6 7B 3F 20 78 B6 E3 4A 44 2F C5 F6 4E 01 30 EB
 Received 64 bytes data : SW 0x9000 - duration: 92.5 ms
<- 5D A3 18 51 A1 4D B8 4D E3 7A 33 87 96 F8 E5 FE 2A 47 5C C9 35 F6 A3 EB 9F CC 75 5F 72 B7 27 E4 0E 69 D1 98 AB 72 3C 5B F2 94 F7 7F E2 B5 F2 7C 1C 96 A3 0F 9B 51 08 8A B8 0C D3 3D 33 AB 04 C2
Signature : 0x304402205da31851a14db84de37a338796f8e5fe2a475cc935f6a3eb9fcc755f72b727e402200e69d198ab723c5bf294f77fe2b5f27c1c96a30f9b51088ab80cd33d33ab04c2
OK
 Sending 0x20 command with 6 bytes data
-> 00 20 00 81 06 31 32 33 34 35 36
 Received 0 bytes data : SW 0x9000 - duration: 17.0 ms
 Sending 0x2A command with 32 bytes data
-> 00 2A 9E 9A 20 F1 10 4E AD 6B 42 85 42 7C 67 8C C0 FC 85 D1 2C F6 7B 3F 20 78 B6 E3 4A 44 2F C5 F6 4E 01 30 EB
 Received 66 bytes data : SW 0x9000 - duration: 93.4 ms
<- 00 E0 79 F5 1D 19 71 F1 DD 64 3C 66 6B 62 DF 20 F9 3D 24 45 C5 05 DE 67 EA 97 00 46 79 0C A7 06 17 00 9F C6 3D FC 82 72 DF 16 FF B1 72 4C 2E 23 49 AE FA C7 05 C6 A8 31 96 ED 6E 0D 94 63 3A D2 2F 6E
Signature : 0x3046022100e079f51d1971f1dd643c666b62df20f93d2445c505de67ea970046790ca706170221009fc63dfc8272df16ffb1724c2e2349aefac705c6a83196ed6e0d94633ad22f6e
OK
 Sending 0x20 command with 6 bytes data
-> 00 20 00 81 06 31 32 33 34 35 36
 Received 0 bytes data : SW 0x9000 - duration: 16.9 ms
 Sending 0x2A command with 32 bytes data
-> 00 2A 9E 9A 20 F1 10 4E AD 6B 42 85 42 7C 67 8C C0 FC 85 D1 2C F6 7B 3F 20 78 B6 E3 4A 44 2F C5 F6 4E 01 30 EB
 Received 66 bytes data : SW 0x9000 - duration: 93.4 ms
<- 00 FB 45 6E 04 FA E0 3D 00 43 36 94 BD 3F E1 E2 64 86 41 06 9B 48 3A 57 49 21 FD 20 86 9E F5 B5 EC 00 AF 14 D6 DE 59 7E 47 10 88 3B 7B 93 FC E9 86 DD 4B A8 B6 28 E9 52 9F 87 73 4C 15 7D 57 A9 B7 59
Signature : 0x3046022100fb456e04fae03d00433694bd3fe1e2648641069b483a574921fd20869ef5b5ec022100af14d6de597e4710883b7b93fce986dd4ba8b628e9529f87734c157d57a9b759
OK
 Sending 0x20 command with 6 bytes data
-> 00 20 00 81 06 31 32 33 34 35 36
 Received 0 bytes data : SW 0x9000 - duration: 18.0 ms
 Sending 0x2A command with 32 bytes data
-> 00 2A 9E 9A 20 F1 10 4E AD 6B 42 85 42 7C 67 8C C0 FC 85 D1 2C F6 7B 3F 20 78 B6 E3 4A 44 2F C5 F6 4E 01 30 EB
 Received 66 bytes data : SW 0x9000 - duration: 92.5 ms
<- 00 2F 12 A2 E0 2C E7 18 AF 31 AC 31 08 05 62 C7 83 02 BC 51 B9 DE B2 5D CD BA C0 3A 2F B1 D5 15 8A 00 E6 15 27 E5 86 49 25 97 E9 A7 AD C6 E3 E5 01 DB C9 96 67 20 5E 12 EB 74 6D 90 D7 38 64 C8 E8 E7
Signature : 0x304502202f12a2e02ce718af31ac31080562c78302bc51b9deb25dcdbac03a2fb1d5158a022100e61527e586492597e9a7adc6e3e501dbc99667205e12eb746d90d73864c8e8e7
OK
 Sending 0x20 command with 6 bytes data
-> 00 20 00 81 06 31 32 33 34 35 36
 Received 0 bytes data : SW 0x9000 - duration: 16.9 ms
 Sending 0x2A command with 32 bytes data
-> 00 2A 9E 9A 20 F1 10 4E AD 6B 42 85 42 7C 67 8C C0 FC 85 D1 2C F6 7B 3F 20 78 B6 E3 4A 44 2F C5 F6 4E 01 30 EB
 Received 66 bytes data : SW 0x9000 - duration: 92.5 ms
<- 00 DF 23 7D 89 A1 8D 34 1C BA C0 15 E7 C6 0F 28 74 2C FB 92 B8 A1 0A BA 35 02 CC AB 05 77 28 FA 71 00 20 99 9C 1E E7 22 CD 16 1D 7F F8 39 25 06 09 A1 4E E4 4A 34 90 13 8C FC 00 96 91 C3 27 8B 6F 85
Signature : 0x3045022100df237d89a18d341cbac015e7c60f28742cfb92b8a10aba3502ccab057728fa71022020999c1ee722cd161d7ff839250609a14ee44a3490138cfc009691c3278b6f85
OK
 Sending 0x20 command with 6 bytes data
-> 00 20 00 81 06 31 32 33 34 35 36
 Received 0 bytes data : SW 0x9000 - duration: 16.8 ms
 Sending 0x2A command with 32 bytes data
-> 00 2A 9E 9A 20 F1 10 4E AD 6B 42 85 42 7C 67 8C C0 FC 85 D1 2C F6 7B 3F 20 78 B6 E3 4A 44 2F C5 F6 4E 01 30 EB
 Received 66 bytes data : SW 0x9000 - duration: 92.7 ms
<- 00 53 1C 3D 04 0F 26 F3 74 7F FD C9 A7 36 E5 B7 1E 2B F4 F6 37 F2 30 69 CC 42 19 94 E3 E2 26 AF E7 00 97 42 77 3A C6 7E 27 1F 71 40 38 F4 4A F3 34 B3 5B 7E 7D B1 43 5B 88 13 E1 FA E6 17 56 B5 20 23
Signature : 0x30450220531c3d040f26f3747ffdc9a736e5b71e2bf4f637f23069cc421994e3e226afe70221009742773ac67e271f714038f44af334b35b7e7db1435b8813e1fae61756b52023
OK
 Sending 0x20 command with 6 bytes data
-> 00 20 00 81 06 31 32 33 34 35 36
 Received 0 bytes data : SW 0x9000 - duration: 17.0 ms
 Sending 0x2A command with 32 bytes data
-> 00 2A 9E 9A 20 F1 10 4E AD 6B 42 85 42 7C 67 8C C0 FC 85 D1 2C F6 7B 3F 20 78 B6 E3 4A 44 2F C5 F6 4E 01 30 EB
 Received 0 bytes data : SW 0x6F00 - duration: 36.7 ms
Crash, game over.
SFYL !
Error status : 0x6F00
af-anssi commented 3 years ago

Dynamic calls to getInstances have been removed in everydays' operations (sign, decipher). There are no setters in the KeyPair class, so it is mandatory to create new objects when needed, which occurs only when keys are changed (either imported or generated on board). We have no problem with our (older) JCOP card. Could you check if you still encounter the repeated signature problem on you J3R110 with v1.17 version of the applet ?

makkarpov commented 3 years ago

I had tested it with NIST P-521 keys and J3H145 card. Smart card did >5000 signatures successfully and without visible degradation.

Reader ...........: ACS ACR 38U-CCID 00 00
Application ID ...: D276000124010304AFAF00FF00000000
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: unknown
Serial number ....: 00FF0000
Name of cardholder: [not set]
Language prefs ...: en
Salutation .......: 
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: not forced
Key attributes ...: nistp521 nistp521 nistp521
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 5073
KDF setting ......: off
Signature key ....: 3428 871A 731A 4C2C 7084  6B0F EA47 D36E 2C6B 949B
      created ....: 2021-03-13 13:57:40
Encryption key....: 4127 CB21 4A1C 6584 E721  0BA2 24A9 A00E 4A92 3CD1
      created ....: 2021-03-13 13:57:40
Authentication key: F1E9 2D39 4182 4866 288A  EE75 DA6F 42C8 5C4F D9F2
      created ....: 2021-03-13 13:57:40
General key info..: 
pub  nistp521/EA47D36E2C6B949B 2021-03-13 Smart card test
sec>  nistp521/EA47D36E2C6B949B  created: 2021-03-13  expires: never     
                                 card-no: AFAF 00FF0000
ssb>  nistp521/DA6F42C85C4FD9F2  created: 2021-03-13  expires: never     
                                 card-no: AFAF 00FF0000
ssb>  nistp521/24A9A00E4A923CD1  created: 2021-03-13  expires: never     
                                 card-no: AFAF 00FF0000
dogtopus commented 2 years ago

Is J3R110 a real product form NXP? Smartcardfocus doesn't carry them and all sellers I can find for the card are Chinese which is really strange considering that they don't carry cards other than J2A040 and J3D081, and all of those are normally uninitialized.

I'm asking because it may be a buggy knockoff like the Feitian JavaCOS A22 and ACS ACOSJ. Both of those have serious memory management issues (with A22 using an abnormally huge amount of transient memory on any crypto operations and ACOSJ (speculatively) corrupting the EEPROM all the way until bricking the card).

bitlogik commented 2 years ago

This is JCOP "4" 3.0.5 on NXP P71 SmartMX3. The bigger J3R320 version might be more common by the way. We'll test with other chip in this familly, one day if we take time about this topic. Still, we are using NXP NDA proprietary JC package on these card for some applets, and oberving the compatbility and also the chip seped, we can be sure there are real NXP P71. This product seems to have a poor memory management, poorer than previsous versions. Or maybe just a reduced overhead because the JCOP system takes more resources, and that exacerbates this issue. Recently on a product we design, all was static except the PIN where it was created at each card reset cycle, and we ended up to put the PIN in "static" also to avoid this kind of issue.

For the KeyPair what you can do is :

private ECPrivateKey keyPrivate;
private ECPublicKey keyPublic;
private KeyPair keypair;

and in the applet or class object instanciation : (adjust memory type accordingly, here this example is for ephemeral keys such a secure channel key).

this.keyPrivate = (ECPrivateKey) KeyBuilder.buildKey(KeyBuilder.ALG_TYPE_EC_FP_PRIVATE,JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT, (short)256, false);
this.keyPublic = (ECPublicKey) KeyBuilder.buildKey(KeyBuilder.ALG_TYPE_EC_FP_PUBLIC, JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT, (short)256, false);
this.keypair = new KeyPair(this.keyPublic, this.keyPrivate);

Just as it is, but creating the object once. And during the generate methods, it only setup the key parameters. And clear the keys at reset.

But here for SmartPGP, the culprit is here, where a new signature object is created every time a signature is performed. This should be done with that in applet class : private Signature sig; And as a pointer initialization. self.sig = null;

af-anssi commented 2 years ago

@bitlogik you did not answer to my question in https://github.com/ANSSI-FR/SmartPGP/issues/29#issuecomment-782880025 : do you still have "batch" signatures issue on the J3R110 with version v1.17 of the applet ?

bitlogik commented 2 years ago

Sorry, we let this project aside since that time. We need to confirm. Because yes we just see there were some works relative to this issue, and I totally missed that. Not sure if the specific issue about signature was solved, maybe only a signature pointer during each signature is created and not a full object? The work about this issue can be pushed forward with RSA and EC keys set as "static" and using clearKey() and setXparam(), for the lifecycle management, with set parameters on the private/public counterpart objects of the keypair. We'll try to test if we have some time this week.

bitlogik commented 2 years ago

We tested the applet v1.17+ on J3R cards, and it fixed the signatures issue. No more hazardous memory leak for signatures. 👍

But, quite as expected, the key generation after a reset is affected by this issue.

After some a dozens of resets :

 Sending 0x20 command with 8 bytes data
-> 00 20 00 83 08 31 32 33 34 35 36 37 38
 Received 0 bytes data : SW 0x9000 - duration: 16.0 ms
 Sending 0xE6 command with 0 bytes data
-> 00 E6 00 00 00
 Received 0 bytes data : SW 0x9000 - duration: 10.8 ms
 Sending 0x44 command with 0 bytes data
-> 00 44 00 00 00
 Received 0 bytes data : SW 0x9000 - duration: 158.4 ms
PGP device reset
 Sending 0x47 command with 2 bytes data
-> 00 47 81 00 02 B6 00
 Received 0 bytes data : SW 0x6A88 - duration: 7.7 ms
Setup the new device
 Sending 0x20 command with 8 bytes data
-> 00 20 00 83 08 31 32 33 34 35 36 37 38
 Received 0 bytes data : SW 0x9000 - duration: 16.5 ms
Put data 132A8648CE3D030107 in 0x00C1
 Sending 0xDA command with 9 bytes data
-> 00 DA 00 C1 09 13 2A 86 48 CE 3D 03 01 07
 Received 0 bytes data : SW 0x9000 - duration: 23.6 ms
 Sending 0x47 command with 2 bytes data
-> 00 47 80 00 02 B6 00
 Received 0 bytes data : SW 0x6F00 - duration: 116.4 ms
Crash, game over.
SFYL !
Error: 0x6f00

And the card applet is bricked (requires new applet loading).

Tested on J3R110 and J3R200 (JCOP on NXP P71) with javacard-3.0.4 v1.21-3.0.4.

One last modification is required about the keys objects :

The good part is that keypair doesn't need to be used with initialized key, but only a key pair from KeyBuilder.buildKey, and can be instantiated once (right after the key pair instantiation, done once). And the setParams can be done on a key after a clearKey (or on a new key the first time).

af-anssi commented 2 years ago

Thank you for those tests. There is no simple solution for the key generation/import. The user can change the key attributes (RSA key size, switch to EC, change EC curve, ...) and we cannot create static instances for each possible value. We have created a branch named test-issue-29 where object deletion is requested if the card supports it. You can test if your card supports it with the TestApplet in the test_applet directory from that branch and the test.py script (you can comment out other tests). If your card supports object deletion, could you try the SmartPGPApplet from that branch for repeated key import/generation ?

wreps8Owt commented 1 year ago

We tested the applet v1.17+ on J3R cards, and it fixed the signatures issue. No more hazardous memory leak for signatures. +1

But, quite as expected, the key generation after a reset is affected by this issue.

After some a dozens of resets :

 Sending 0x20 command with 8 bytes data
-> 00 20 00 83 08 31 32 33 34 35 36 37 38
 Received 0 bytes data : SW 0x9000 - duration: 16.0 ms
 Sending 0xE6 command with 0 bytes data
-> 00 E6 00 00 00
 Received 0 bytes data : SW 0x9000 - duration: 10.8 ms
 Sending 0x44 command with 0 bytes data
-> 00 44 00 00 00
 Received 0 bytes data : SW 0x9000 - duration: 158.4 ms
PGP device reset
 Sending 0x47 command with 2 bytes data
-> 00 47 81 00 02 B6 00
 Received 0 bytes data : SW 0x6A88 - duration: 7.7 ms
Setup the new device
 Sending 0x20 command with 8 bytes data
-> 00 20 00 83 08 31 32 33 34 35 36 37 38
 Received 0 bytes data : SW 0x9000 - duration: 16.5 ms
Put data 132A8648CE3D030107 in 0x00C1
 Sending 0xDA command with 9 bytes data
-> 00 DA 00 C1 09 13 2A 86 48 CE 3D 03 01 07
 Received 0 bytes data : SW 0x9000 - duration: 23.6 ms
 Sending 0x47 command with 2 bytes data
-> 00 47 80 00 02 B6 00
 Received 0 bytes data : SW 0x6F00 - duration: 116.4 ms
Crash, game over.
SFYL !
Error: 0x6f00

And the card applet is bricked (requires new applet loading).

Tested on J3R110 and J3R200 (JCOP on NXP P71) with javacard-3.0.4 v1.21-3.0.4.

One last modification is required about the keys objects :

* define once in static part

* instantiate in applet initialization/installation, or at object module creation

* when reset use clearKey()

* when generate use setParams and generate and set also the secret value

The good part is that keypair doesn't need to be used with initialized key, but only a key pair from KeyBuilder.buildKey, and can be instantiated once (right after the key pair instantiation, done once). And the setParams can be done on a key after a clearKey (or on a new key the first time).

After rebasing test-issue-29 atop v1.22.1-3.0.4, test applet says that my J3R180 supports object deletion, and SmartPGPApplet built from rebased test-issue-29 can pass 300 times repeated key generation performed with https://gist.github.com/wreps8Owt/504234e0e09df2ca10e7c34ddcc225fb , while the latest release will fail on the 174th key generation (the index starts from 0):

PublicKey 173 for signature : 0x0454cabea466a4142e61c97d799ddeaba0a8b5789328f469321187ee041f96b646f4cdc84f9da87294ec3deb23f5c3ea94640e0226b3bc3fdb8d2bf55e211d288f Crash, game over. SFYL ! Error status : 0x6F00