From 806a035d39199c4d666b733e74194c35f0ff8063 Mon Sep 17 00:00:00 2001 From: Alex Wilson Date: Thu, 29 Oct 2020 15:11:18 +1000 Subject: [PATCH] Handle arbitrary ordering of tags in GENERAL AUTH --- src/net/cooperi/pivapplet/PivApplet.java | 84 +++++++++++++++--------- 1 file changed, 52 insertions(+), 32 deletions(-) diff --git a/src/net/cooperi/pivapplet/PivApplet.java b/src/net/cooperi/pivapplet/PivApplet.java index 55ca5b0..c922a2a 100644 --- a/src/net/cooperi/pivapplet/PivApplet.java +++ b/src/net/cooperi/pivapplet/PivApplet.java @@ -167,6 +167,7 @@ public class PivApplet extends Applet private short outgoingLe = 0; private byte[] challenge = null; + private boolean[] chalValid = null; private byte[] iv = null; private byte[] certSerial = null; @@ -378,6 +379,8 @@ public class PivApplet extends Applet challenge = JCSystem.makeTransientByteArray((short)16, JCSystem.CLEAR_ON_DESELECT); + chalValid = JCSystem.makeTransientBooleanArray((short)1, + JCSystem.CLEAR_ON_DESELECT); iv = JCSystem.makeTransientByteArray((short)16, JCSystem.CLEAR_ON_DESELECT); @@ -1811,11 +1814,12 @@ else if (key == (byte)0x81) tlv.skip(); } - if (tlv.tagLength() == len) { + if (tlv.tagLength() == len && chalValid[0]) { tlv.read(tempBuf, len); comp = Util.arrayCompare(tempBuf.data(), tempBuf.rpos(), challenge, (short)0, len); + chalValid[0] = false; tlv.end(); } else { tlv.abort(); @@ -1824,7 +1828,7 @@ else if (key == (byte)0x81) return; } } - if (hasResp) { + if (hasResp && chalValid[0]) { tlv.rewind(); tlv.readTag(); /* The 0x7C outer tag */ @@ -1857,6 +1861,7 @@ else if (key == (byte)0x81) outBuf.rpos(), challenge, (short)0, cLen); tlv.end(); + chalValid[0] = false; } if (comp == 0) { @@ -1886,6 +1891,7 @@ else if (key == (byte)0x81) wtlv.useApdu((short)0, outgoingLe); randData.generateData(challenge, (short)0, len); + chalValid[0] = true; /*for (byte i = 0; i < (byte)len; ++i) challenge[i] = (byte)(i + 1);*/ @@ -1908,6 +1914,7 @@ else if (key == (byte)0x81) wtlv.useApdu((short)0, outgoingLe); randData.generateData(challenge, (short)0, len); + chalValid[0] = true; /*for (byte i = 0; i < (byte)len; ++i) challenge[i] = (byte)(i + 1);*/ @@ -2355,7 +2362,8 @@ else if (key == (byte)0x81) /* * First, scan through the TLVs to figure out what the host - * actually wants from us. + * actually wants from us, and mark which fields they gave us + * data for. */ while (!tlv.atEnd()) { tag = tlv.readTag(); @@ -2367,40 +2375,40 @@ else if (key == (byte)0x81) ISO7816.SW_WRONG_DATA); return; } + switch (tag) { + case GA_TAG_WITNESS: + case GA_TAG_RESPONSE: + case GA_TAG_CHALLENGE: + break; + default: + tlv.abort(); + ISOException.throwIt( + ISO7816.SW_WRONG_DATA); + return; + } wanted = tag; + } else { + switch (tag) { + case GA_TAG_WITNESS: + hasWitness = true; + break; + case GA_TAG_RESPONSE: + hasResp = true; + break; + case GA_TAG_CHALLENGE: + case GA_TAG_EXP: + hasChal = true; + break; + default: + tlv.abort(); + ISOException.throwIt( + ISO7816.SW_WRONG_DATA); + return; + } } tlv.skip(); } - /* Now rewind, let's figure out what fields they gave us. */ - tlv.rewind(); - tlv.readTag(); /* The 0x7C outer tag */ - - while (!tlv.atEnd()) { - tag = tlv.readTag(); - if (tag == wanted) { - tlv.skip(); - continue; - } - if (tag == GA_TAG_WITNESS) { - hasWitness = true; - tlv.skip(); - continue; - } - if (tag == GA_TAG_RESPONSE) { - hasResp = true; - tlv.skip(); - continue; - } - if (tag == GA_TAG_CHALLENGE || tag == GA_TAG_EXP) { - hasChal = true; - break; - } - tlv.abort(); - ISOException.throwIt(ISO7816.SW_WRONG_DATA); - return; - } - switch (alg) { case PIV_ALG_DEFAULT: case PIV_ALG_3DES: @@ -2423,6 +2431,18 @@ else if (key == (byte)0x81) return; } + /* Read through to the first non-wanted tag. */ + tlv.rewind(); + tlv.readTag(); /* Outer 0x7C tag */ + while (!tlv.atEnd()) { + tag = tlv.readTag(); + if (tag == wanted) { + tlv.skip(); + continue; + } + break; + } + switch (alg) { //#if PIV_SUPPORT_RSA case PIV_ALG_RSA1024: