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

Conditions of Use Not Satisfied when pulling a partial buffer #55

Open
mistial-dev opened this issue Mar 28, 2023 · 8 comments
Open

Conditions of Use Not Satisfied when pulling a partial buffer #55

mistial-dev opened this issue Mar 28, 2023 · 8 comments
Labels

Comments

@mistial-dev
Copy link

When reading the CHUID, it's often not necessary to grab the entire data structure if pre-enrollment has occurred.

SP 800-73-4 Appendix A states "For each container, compliant cards shall return all TLV elements of the container in the order listed in this appendix."

Looking at the Cardholder Unique Identifier, there is one optional element before the FASC-N (2 bytes), a 25-byte FASC-N, 4 bytes of Organizational Identifier, 9 bytes of DUNS, and 16 bytes of GUID at the beginning of the element. Thus, for a compliant card you can get the first 0x38 bytes of the CHUID and have both the FASC-N and GUID. With a pre-enrolled card, and signature verification at enrollment, this is fine. I successfully do this with other cards without issue.

When I attempt to do this with OpenFIPS201 cards, the following operation results in a "Conditions of use not satisfied."

This appears to be a result of ChainBuffer class.

// Make sure that we are not in the middle of some other outstanding transaction
if (context[CONTEXT_STATE] != STATE_NONE && context[CONTEXT_STATE] != STATE_INCOMING_APDU) {
// We have been called in the middle of another operation! call resetAbort in case there is
// some outstanding transaction
resetAbort();
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
}

This does not seem to be correct behaviour as far as I can tell. Is this how the applet is intended to behave?

[=] Session log /Users/mistial/.proxmark3/logs/log_20230328.txt
[+] loaded from JSON file /Users/mistial/.proxmark3/preferences.json
[=] Using UART port /dev/tty.usbmodem101
[=] Communicating with PM3 over USB-CDC
[+] executing commands from file: ec_sign.cmd

[usb|script] pm3 --> hf 14a apdu -stk 00A4040009A0000003080000100000
[+] ( select, keep, TLV )
[+] >>> 00A4040009A0000003080000100000
[+] <<< 61818F4F0BA00000030800001000010079074F05A000000308500B4F70656E464950533230315F5049687474703A2F2F6E766C707562732E6E6973742E676F762F6E697374707562732F5370656369616C5075626C69636174696F6E732F4E4953542E53502E3830302D37332D342E706466AC1E80010080010380010880010A80010C8001068001078001118001140601009000 | a..O............y.O......P.OpenFIPS201_PIhttp://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-73-4.pdf..................................
[+] <<< status: 90 00 - Command successfully executed (OK).
[=] -------------------- TLV decoded --------------------
[=]  --61[8f] 'Application Template':
[=]     --4f[0b] 'Application Dedicated File (ADF) Name':
[=]     00: A0 00 00 03 08 00 00 10 00 01 00                | ...........
[=]     --79[07] 'Unknown ???':
[=]         --4f[05] 'Application Dedicated File (ADF) Name':
[=]         00: A0 00 00 03 08                                  | .....
[=]     --50[0b] 'Application Label':    String value '4F70656E46495053323031'
[=]     00: 4F 70 65 6E 46 49 50 53 32 30 31                | OpenFIPS201
[=]     --5f50[49] 'Issuer URL':    String value '687474703A2F2F6E766C707562732E6E6973742E676F762F6E697374707562732F5370656369616C5075626C69636174696F6E732F4E4953542E53502E3830302D37332D342E706466'
[=]     00: 68 74 74 70 3A 2F 2F 6E 76 6C 70 75 62 73 2E 6E | http://nvlpubs.n
[=]     10: 69 73 74 2E 67 6F 76 2F 6E 69 73 74 70 75 62 73 | ist.gov/nistpubs
[=]     20: 2F 53 70 65 63 69 61 6C 50 75 62 6C 69 63 61 74 | /SpecialPublicat
[=]     30: 69 6F 6E 73 2F 4E 49 53 54 2E 53 50 2E 38 30 30 | ions/NIST.SP.800
[=]     40: 2D 37 33 2D 34 2E 70 64 66                      | -73-4.pdf
[=]     --ac[1e] 'Unknown ???':
[=]         --80[01] 'Response Message Template Format 1':
[=]         00: 00                                              | .
[=]         --80[01] 'Response Message Template Format 1':
[=]         00: 03                                              | .
[=]         --80[01] 'Response Message Template Format 1':
[=]         00: 08                                              | .
[=]         --80[01] 'Response Message Template Format 1':
[=]         00: 0A                                              | .
[=]         --80[01] 'Response Message Template Format 1':
[=]         00: 0C                                              | .
[=]         --80[01] 'Response Message Template Format 1':
[=]         00: 06                                              | .
[=]         --80[01] 'Response Message Template Format 1':
[=]         00: 07                                              | .
[=]         --80[01] 'Response Message Template Format 1':
[=]         00: 11                                              | .
[=]         --80[01] 'Response Message Template Format 1':
[=]         00: 14                                              | .
[=]         -- 6[01] 'Object Identifier (OID)':
[=]         00: 00                                              | .
[usb|script] pm3 --> hf 14a apdu -k 00CB3FFF055C035FC10238
[+] ( , keep )
[+] >>> 00CB3FFF055C035FC10238
[+] <<< 533B3019D4E739DA739CED39CE739D8360D82108421A9333CCE739A3E13410399990000000105483934F504E5048593508323033373132336105 | S;0...9.s..9.s..`.!.B..3..9..4.9......T..OPNPHY5.2037123a.
[+] <<< status: 61 05 - Command successfully executed; 'XX' bytes of data are available and can be requested using GET RESPONSE.
[usb|script] pm3 --> hf 14a apdu 0087119E267C2482008120000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
[+] (  )
[+] >>> 0087119E267C2482008120000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
[+] <<< 6985 | i.
[+] <<< status: 69 85 - Conditions of use not satisfied.
[usb|script] pm3 --> hf 14a list -u
[=] downloading tracelog data from device
[+] Recorded activity (trace len = 550 bytes)
[=] start = start of start frame end = end of frame. src = source of transfer
[=] ISO14443A - all times are in microseconds

      Start |        End | Src | Data (! denotes parity error)                                           | CRC | Annotation
------------+------------+-----+-------------------------------------------------------------------------+-----+--------------------
        0.0 |       73.2 | Rdr |52(7)                                                                    |     | WUPA
      156.0 |      330.7 | Tag |48  00                                                                   |     | 
      519.2 |      700.9 | Rdr |93  20                                                                   |     | ANTICOLL
      779.1 |     1213.3 | Tag |88  04  6c  47  a7                                                       |     | 
     1406.5 |     2182.9 | Rdr |93  70  88  04  6c  47  a7  30  01                                       |  ok | SELECT_UID
     2261.1 |     2520.6 | Tag |24  d8  36                                                               |     | 
     2624.2 |     2805.9 | Rdr |95  20                                                                   |     | ANTICOLL-2
     2884.1 |     3318.3 | Tag |b2  97  14  90  a1                                                       |     | 
     3511.5 |     4287.9 | Rdr |95  70  b2  97  14  90  a1  99  3b                                       |  ok | SELECT_UID-2
     4366.1 |     4630.4 | Tag |20  fc  70                                                               |     | 
     4757.5 |     5109.1 | Rdr |e0  80  31  73                                                           |  ok | RATS
     5206.2 |     6230.4 | Tag |0a  78  77  91  02  80  73  c8  21  10  56  4d                           |  ok | 
    28903.8 |    30444.8 | Rdr |02  00  a4  04  00  09  a0  00  00  03  08  00  00  10  00  00  b1  70   |  ok | 
    45248.7 |    45248.7 | Tag |02  61  81  8f  4f  0b  a0  00  00  03  08  00  00  10  00  01  00  79            |     | 
            |            |     |07  4f  05  a0  00  00  03  08  50  0b  4f  70  65  6e  46  49  50  53            |     | 
            |            |     |32  30  31  5f  50  49  68  74  74  70  3a  2f  2f  6e  76  6c  70  75            |     | 
            |            |     |62  73  2e  6e  69  73  74  2e  67  6f  76  2f  6e  69  73  74  70  75            |     | 
            |            |     |62  73  2f  53  70  65  63  69  61  6c  50  75  62  6c  69  63  61  74            |     | 
            |            |     |69  6f  6e  73  2f  4e  49  53  54  2e  53  50  2e  38  30  30  2d  37            |     | 
            |            |     |33  2d  34  2e  70  64  66  ac  1e  80  01  00  80  01  03  80  01  08            |     | 
            |            |     |80  01  0a  80  01  0c  80  01  06  80  01  07  80  01  11  80  01  14            |     | 
            |            |     |06  01  00  90  00  2b  c1                                               |  ok | 
    81642.5 |    82838.9 | Rdr |03  00  cb  3f  ff  05  5c  03  5f  c1  02  38  a5  0a                   |  ok | 
    90416.8 |    90416.8 | Tag |03  53  3b  30  19  d4  e7  39  da  73  9c  ed  39  ce  73  9d  83  60            |     | 
            |            |     |d8  21  08  42  1a  93  33  cc  e7  39  a3  e1  34  10  39  99  90  00            |     | 
            |            |     |00  00  10  54  83  93  4f  50  4e  50  48  59  35  08  32  30  33  37            |     | 
            |            |     |31  32  33  61  05  5c  ff                                               |  ok | 
   123638.9 |   127558.7 | Rdr |02  00  87  11  9e  26  7c  24  82  00  81  20  00  01  02  03  04  05                |     | 
            |            |     |06  07  08  09  0a  0b  0c  0d  0e  0f  10  11  12  13  14  15  16  17                |     | 
            |            |     |18  19  1a  1b  1c  1d  1e  1f  d8  70                                   |  ok | 
   132205.6 |   132635.1 | Tag |02  69  85  44  71                                                       |     | 
@mistial-dev
Copy link
Author

mistial-dev commented Mar 29, 2023

Looks like this is a potentially a duplicate of / related to #4. I've seen this behaviour in the wild as well as in the implementation I'm working on, so I can't help but wonder if there are compatibility issues out in the wild due to it.

@makinako
Copy link
Owner

Hi @mistial-dev, thanks for bringing this to our attention. Yes this was addressed by FEATURE_STRICT_APDU_CHAINING for issue #4. This was later reviewed and removed as it was clear enough that ISO 7816 intends remaining data to be skipped if not needed, so it wasn't necessary to be an option (From ISO 7816-4 5.3.4):

"contrary to command chaining, this possible termination is normal when the outside world considers that it has received enough data: the exchange should continue normally with an arbitrary C-RP."

So it looks like processIncomingObject behaves correctly, but not processIncomingAPDU. This is a bug and will be fixed. I will also add some specific regression tests to make sure this stays the case. ChainBuffer has been re-written for the FIPS version so I will make sure the fix goes in this too.

One additional note; 5.3.4 also states:

"however, this document does not define the behaviour of the card if the outside world tries to resume response chaining after e.g. the execution of a command on another logical channel. The behaviour may be defined by the application."

I believe the best approach here is to explicitly clear any remaining data if any other command breaks the response chain, but if you can think of any scenario where you might want to a) get the first part; b) issue some other command; c) get the remaining part, please let me know.

@mistial-dev
Copy link
Author

mistial-dev commented Mar 29, 2023

Thank you for your response.

I'm not intentionally chaining the APDUs. Class is 0x00, and I'm setting Le to a length less than the object length. It's terminating normally, just short of the full object length.

@makinako
Copy link
Owner

Understood, in this context I was using the term chaining to refer to both large command and response processing, though I know it's typically used just for commands. In any case I will review the functionality for both to make sure it covers the standard.

One big change being made for the FIPS accreditation is putting all testing in JIRA using Zephyr Scale to capture all tests and scripts. This helps change tracking so that any bugs or features that come up can be linked to the tests that cover them. Once I've got it migrated across I'll be progressively opening up access to it so that the community can also review issues and tests as well as code.

@dengert
Copy link

dengert commented Mar 29, 2023

I'm setting Le to a length less than the object length.

The current OpenSC PIV driver does this intentionally. It will do GET_DATA for 8 bytes, then determine the size of the object allocate a buffer then do GET_DATA followed by GET_RESPONSE(s) to read the full object. (This was done because of the way OpenSC code was doing GET_RESPONSE) OpenSC/OpenSC#2053 allocates a very large buffer first to avoid the extra operation.

If you can think of any scenario where you might want to a) get the first part; b) issue some other command; c) get the remaining part

That appears to violate ISO, especially if the other command returns any data. Any GET_RESPONSE would be for the last command - at least if on the same logical channel. I do not recall if PIV defines or intended to support logical channels. I don't see any use of logical channels other then 0 in any OpenSC card driver.

@dengert
Copy link

dengert commented Mar 29, 2023

The trace in original post does not appear to have anything to do with the CHUID, Is this the wrong trace?
The instruction in question:

00 87 11 9E 26 7C24 8200 8120 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F

Appears to be GENERAL AUTHENTICATE (sign) for key 9E with EC-256. over ISO14443A - contactless, which should work, but returns 6985 - "Conditions of use not satisfied" but 69 85 is not defined in 800-73-4

@mistial-dev
Copy link
Author

That's the next APDU, the one that shows the error. Doing a bit of an explanation in case someone comes across this later.

The trace in original post does not appear to have anything to do with the CHUID, Is this the wrong trace? The instruction in question:

00 87 11 9E 26 7C24 8200 8120 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F

Appears to be GENERAL AUTHENTICATE (sign) for key 9E with EC-256. over ISO14443A - contactless, which should work, but returns 6985 - "Conditions of use not satisfied" but 69 85 is not defined in 800-73-4

That's where the error occurs. We're basically trying to do a PIV auth as fast as it is possible to do.

Step 1: load PIV applet (if not implicit select). 00A4040009A0000003080000100000.

Step 2: identify card: 00CB3FFF055C035FC10238

Appendix A states:

The SP 800-73-4 specification does not provide mechanisms to read partial contents of a PIV data
object. Individual access to the TLV elements within a container is not supported. For each container,
compliant cards shall return all TLV elements of the container in the order listed in this appendix.

The CHUID is in 5FC102. That APDU gets the CHUID. We know the data is in order, and we know the maximum size of a field.

The optional but deprecated buffer length is 2 bytes. 25 bytes for the fasc-n, 4 bytes for the optional but deprecated organizational identifier, 9 for the DUNS, 16 for the GUID. Add the tags, and 5 more bytes (61 total) gets you the GUID and FASC-N for any PIV-compliant card (without the signatures or rest of the data). The sample APDU didn't add in the overhead of the tags themselves, a mistake that has since been corrected.

The reason we don't care about the CHUID's signature is that we're using attested, generated-on-card keys with pre-enrolled certificates. If the signature validates, the card is correct. So, the next APDU sends a challenge over the contactless, and lets the PKI path validation do the walking. 3 APDUs, and we've validated a PIV card. 2 with implicit select.

Unfortunately, this bug means that when we do this with current OpenFIPS201 cards, it just fails, because it thinks we're mid transaction for chaining. We're quite done with the data at this point, and read only what was necessary to identify the card, even for PIV-I cards that all use the same FASC-N and depend on the GUID.

@mistial-dev
Copy link
Author

if you can think of any scenario where you might want to a) get the first part; b) issue some other command; c) get the remaining part, please let me know.

I can’t, and that sounds like something that could cause problems, to be honest. By and large, within a logical channel, smart cards do one thing at a time.

@makinako makinako added the bug label Aug 25, 2023
mistial-dev added a commit to mistial-dev/OpenFIPS201 that referenced this issue Aug 28, 2023
@mistial-dev mistial-dev mentioned this issue Aug 28, 2023
makinako added a commit that referenced this issue Aug 29, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants