epass2003: SM response with `87 81 01` fails to decode since 5ebb04ded (0.26.1 accepted it)
Les mainteneurs répondent en général sous 4 jours
Évaluation
- Difficulté
- 4/5
- Temps estimé
- 3-5 jours
- Accessibilité débutants
- 52/100
Piste de recherche
Read decrypt_response() and the existing workaround in epass2003_check_response_mac_and_sw() in src/libopensc/card-epass2003.c; compare the TLV parsing paths for the reported 87 81 01 response. Reproduce with the ePass2003 READ BINARY case described here. Done means pkcs15-tool -D reads all 4864 AODF bytes without -1200 and the dump output remains unchanged.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Description
Split out of #3892, as requested there.
Problem
When an SM response carries 112–127 bytes of plaintext, the ePass2003 encodes the cryptogram as 87 81 01 <128 bytes>. That is, 0x81 is sent as a short-form length byte. In DER that would be 87 81 81 01 .... Reproduced on current master (ccfa7600f) with a READ BINARY of the last 112 bytes of a 4864-byte AODF (offset 0x1290):
Outgoing APDU (19 bytes):
0C B0 12 90 0D 97 01 70 8E 08 ...
Incoming APDU (147 bytes):
87 81 01 28 0D D3 B4 6D ... (128 bytes cryptogram) 99 02 90 00 8E 08 <MAC> 90 00
- 0.26.1:
unwrapped APDU: resplen 112, SW 9000. - master:
epass2003_check_response_mac_and_sw()already has a workaround for this encoding (Workaround, wrong BER-TLV ?), so the MAC check passes.decrypt_response()then parses the same TLV withsc_asn1_read_tag(), which reads 0x81 as a long-form length. It returns -1,epass2003_sm_free_wrapped_apdu()returns -1200, and SM is stopped. sc_read_binary()then returns 4752 of 4864 bytes ("Subsequent read failed with -1200, returning what was read"). The short read is not reported to the caller. The next SELECT gets 6988 and re-establishes SM.
Trace (0.26.1 vs master): 7-sm-length-decoding.txt
This started with 5ebb04ded ("epass2003/iasecc: fixed possible heap over-reads"), together with bc2c29c4b ("Fix epass2003 regression with SM", #3693). Before those commits, decrypt_response() handled the 87 81 01 case itself, the same way epass2003_check_response_mac_and_sw() still does.
Proposed fix
I don't think sc_asn1_read_tag() should accept this encoding, since it is not valid BER. The card quirk belongs in the driver, next to the existing workaround. The patch below is tested on master (ccfa7600f) with an ePass2003: pkcs15-tool -D reads all 4864 bytes of the AODF (master: 4752), with no -1200, and the dump output is unchanged.
--- a/src/libopensc/card-epass2003.c
+++ b/src/libopensc/card-epass2003.c
@@ -1472,13 +1472,22 @@ decrypt_response(struct sc_card *card, unsigned char *in, size_t inlen, unsigned char *out, size_t * out_len)
exdata = (epass2003_exdata *)card->drv_data;
- if (SC_SUCCESS != sc_asn1_read_tag(&p, inlen, &cla, &tag, &cipher_len) || p == NULL) {
- return -1;
+ if (inlen > 3 && in[0] == 0x87 && in[1] == 0x81 && in[2] == 0x01) {
+ /* The card encodes a length of 0x81 as 81 instead of 81 81, see
+ * epass2003_check_response_mac_and_sw() */
+ cipher_len = in[1];
+ p = in + 2;
+ if (cipher_len > inlen - 2)
+ return -1;
+ } else {
+ if (SC_SUCCESS != sc_asn1_read_tag(&p, inlen, &cla, &tag, &cipher_len) || p == NULL) {
+ return -1;
+ }
+ if ((cla | tag) == 0x99)
+ return 0;
+ if ((cla | tag) != 0x87)
+ return -1;
}
- if ((cla | tag) == 0x99)
- return 0;
- if ((cla | tag) != 0x87)
- return -1;
if (cipher_len < 2 || cipher_len > sizeof plaintext)
return -1;
I have only seen the card do this for length 0x81, so the patch covers only that case. I can open this as a PR.
- Langage dominant
- C
- Étoiles
- 3.1k
- Forks
- 858
- Merge moyen
- 7 j 23 h
- PR mergées (30 j)
- 28
Préparer son environnement
- Aucun Dockerfile ni fichier Docker Compose
- Propose un modèle de pull request
- Lire le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de OpenSC/OpenSC
-
no reader max send/recv size if card has no limitPeut-être pris @mvogt1 l’a pris il y a 2 jours. Ouvertebug
Difficulté 2/5 1-3 heures Accessibilité débutants 35/100
Les mainteneurs répondent en général sous 4 jours
-
Difficulté 4/5 3-5 jours Accessibilité débutants 48/100
Les mainteneurs répondent en général sous 4 jours
-
ePass2003: first signature through the Windows minidriver fails with "wrong PIN" (SM session renewed by the PIN dialog process)Peut-être pris @Fabian-Aguilar l’a pris il y a 3 jours. Ouverte
Difficulté 5/5 Plus d'une semaine Accessibilité débutants 12/100
Les mainteneurs répondent en général sous 4 jours
-
minidriver: ECDSA signing via CNG fails with SCARD_E_UNSUPPORTED_FEATURE since abce0979dPeut-être pris @craftzbay l’a pris il y a 4 jours. Ouverte
Difficulté 3/5 1-2 jours Accessibilité débutants 22/100
OpenSC/OpenSC#3916 · 1 commentaire ·
Les mainteneurs répondent en général sous 4 jours
-
Costa Rica electronic signature smart cards supportPeut-être pris @fdelapena l’a pris il y a 2 jours. Ouverteenhancement
Difficulté 5/5 Plus d'une semaine Accessibilité débutants 25/100
OpenSC/OpenSC#3912 · 4 commentaires · 1 réaction ·
Les mainteneurs répondent en général sous 4 jours
Toutes les issues de OpenSC/OpenSC
Issues similaires
-
Difficulté 2/5 1-3 heures Accessibilité débutants 83/100
Les mainteneurs répondent en général sous 4 jours
-
area/docs
Difficulté 1/5 Moins d'une heure Accessibilité débutants 83/100
Clodmony/starship-coop#72 ·
Les mainteneurs répondent en général sous 1 jour
-
ospf6d: heap-use-after-free in seqnumber_mismatch()/bad_lsreq() when a neighbor is deleted with events pendingPeut-être pris @lichenlang89 l’a pris aujourd’hui. Ouverte
Difficulté 2/5 1-3 heures Accessibilité débutants 61/100
Les mainteneurs répondent en général sous 2 jours
-
5700模组网络优先级问题Ouverte
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
-
Difficulté 2/5 1-3 heures Accessibilité débutants 75/100
Les mainteneurs répondent en général sous 1 jour