This is an API-contract defect: doAA is documented to throw CardServiceException on error, but returns normally on a rejected INTERNAL AUTHENTICATE. A caller that verifies the AAResult signature still rejects the chip; a caller that relies on the documented exception does not.
Version: 0.8.9 (same code in 0.8.6 and current trunk).
When the chip answers INTERNAL AUTHENTICATE with an error status word, doAA returns normally with an empty (or non-signature) response, although its Javadoc says it throws CardServiceException on error.
Cause, in AAAPDUSender.sendInternalAuthenticate: for a status word other than 9000 (and not 61xx), the branch "If we got some data, return it, independent of what the status is" checks responseAPDU.getData() != null. For an error response that carries no data, getData() is an empty array, not null, so the empty data is returned.
Two ways to reach it:
Reproduction: after BAC, a chip answers INTERNAL AUTHENTICATE with an error status word returned under secure messaging (DO99 + MAC), then service.doAA(publicKey, "SHA-256", "SHA256withRSA", challenge). Expected: CardServiceException. Actual: doAA returns an AAResult with an empty response. I reproduced it against a scripted chip that returns the status word in a DO99+MAC response; for 6982 the protected INTERNAL AUTHENTICATE command (0C88...8E08...) is answered 9902 6982 8E08 ... 6982 and doAA returns success with no exception. All thirteen status words above behave the same.
Proposed patch (attached, 2 lines):
With the patch, doAA throws for twelve of the thirteen status words. 6700 is the exception: its status word matches the wrong-length shortcut, so transmit returns the response unparsed and doAA still returns it. PACE and BAC behaviour is unchanged in my tests (the PACE fault profiles — 32 status words in each of the two integration patterns — and the successful-read controls all unchanged).
Related effect on Chip Authentication (same transmit branch): when the chip rejects MSE:Set AT during doEACCA with 6700, 6F00 or 6FFF under secure messaging, transmit returns the response without unwrapping it, so the send-sequence counter is not advanced and the next protected command is rejected with 6988 — a caller that catches the CA exception and continues sees the failure only as a later SM error on an unrelated read. The attached mask change removes this for 6F00/6FFF but not 6700 itself; a check that the response carries SM data objects before taking the shortcut would cover all three.
Anonymous