Page MenuHome GnuPG

scdaemon does not handle extended APDUs correctly
Closed, InvalidPublic

Description

In 2009, iso7816_*() functions in scd/iso7816.c got a new argument called extended_mode to support handling extended APDUs. However, this argument is often hardcoded to zero. When the card responds with a long APDU, transaction fails with following error:

scdaemon[28578] DBG: ccid-driver: provided buffer too short for received data (263/258)
scdaemon[28578] ccid_transceive failed: (0x10002)
scdaemon[28578] apdu_send_simple(0) failed: invalid value

This happens for example during key generation. Function does_key_exist() from scd/app-openpgp.c calls iso7816_get_data() with extended_mode = 0 (second argument):

if (iso7816_get_data (app->slot, 0, 0x006E, &buffer, &buflen))

This works only if the response happens to be short enough. But if the DO under tag 0x6E can't fit into a short APDU, key generation fails because of short rx buffer.

Event Timeline

gniibe triaged this task as Normal priority.

I don't understand the reason why 0x6E (Application Related Data) can be so long. What OpenPGP card implementation do you have?

In our implementation, DO 0x6E contains:

TagDescriptionValue size
0x004FOpenPGP AID16 B
0x5F52Historical bytes10 B
0x00C0Extended capabilities10 B
0x00C1Algorithm Attributes Signature (ed25519)10 B
0x00C2Algorithm Attributes Decryption (curve25519)11 B
0x00C3Algorithm Attributes Authentication (ed25519)10 B
0x00C4PW Status Bytes7 B
0x00C5Fingerprints60 B
0x00C6CA Fingerprints60 B
0x00CDPubkey timestamp12 B
Total value size206 B

Each DO has its own tag (2 bytes) and length (3 bytes). This makes total constructed DO length 206 + 11*(3+2) = 261 bytes. Add two status bytes (0x90 0x00) and you have 263 B long APDU.

Thanks for the information.

When the tag and length field can be smaller representation, card does so. <-- This is I assumed.

Currently, I don't know how to fix scdaemon correctly.

Please note that the OpenPGP card specification does not assume this particular case.
In GnuPG scdaemon, large objects are "Login Data", "URL", and "Private DO 1-4", which size is specified by extended capability max_special_do
and "Cardholder certificate" which size is specified by extended capability max_certlen.

Perhaps, you need to ask modification to the OpenPGP card specification, I suppose.

Thank you for the clarification. For now, I'll modify our implementation to use shorter length representation and close this bug as Invalid.
However, I'm still not convinced that using hard-coded arguments is the right way to handle requests. I'll do some more testing and if I discover a legitimate use-case that requires long APDUs, I'll reopen the issue.