Skip to content

Commit

Permalink
Fix for Extended APDUs
Browse files Browse the repository at this point in the history
Not all Java Cards that support extended APDUs have APDU buffer
lengths long enough to include the attestation certificate. This
causes registration to fail when extended APDUs are used, as is the
case with iOS.

The fix is to build the extended responses incrementally instead of
staging them all at once in the APDU buffer.
  • Loading branch information
darconeous committed Mar 20, 2020
1 parent 8493f8e commit 7a7dcc7
Showing 1 changed file with 10 additions and 8 deletions.
18 changes: 10 additions & 8 deletions src/main/java/com/ledger/u2f/U2FApplet.java
Original file line number Diff line number Diff line change
Expand Up @@ -190,18 +190,19 @@ private void handleEnroll(APDU apdu) throws ISOException {
attestationSignature.update(scratch, SCRATCH_KEY_HANDLE_OFFSET, keyHandleLength);
attestationSignature.update(scratch, SCRATCH_PUBLIC_KEY_OFFSET, (short)65);
outOffset = (short)(ENROLL_PUBLIC_KEY_OFFSET + 65 + 1 + keyHandleLength);
short signatureSize = attestationSignature.sign(buffer, (short)0, (short)0, scratch, SCRATCH_SIGNATURE_OFFSET);

if (extendedLength) {
// If using extended length, the message can be completed and sent immediately
scratch[SCRATCH_TRANSPORT_STATE] = TRANSPORT_EXTENDED;
outOffset = Util.arrayCopyNonAtomic(scratch, SCRATCH_PAD, buffer, (short)0, outOffset);
outOffset = Util.arrayCopyNonAtomic(attestationCertificate, (short)0, buffer, outOffset, (short)attestationCertificate.length);
short signatureSize = attestationSignature.sign(buffer, (short)0, (short)0, buffer, outOffset);
outOffset += signatureSize;
apdu.setOutgoingAndSend((short)0, outOffset);
apdu.setOutgoing();
apdu.setOutgoingLength((short)(outOffset + attestationCertificate.length + signatureSize));
apdu.sendBytesLong(scratch, SCRATCH_PAD, outOffset);
apdu.sendBytesLong(attestationCertificate, (short)0, (short)attestationCertificate.length);
apdu.sendBytesLong(scratch, SCRATCH_SIGNATURE_OFFSET, signatureSize);
}
else {
// Otherwise, keep the signature and proceed to send the first chunk
short signatureSize = attestationSignature.sign(buffer, (short)0, (short)0, scratch, SCRATCH_SIGNATURE_OFFSET);
scratch[SCRATCH_TRANSPORT_STATE] = TRANSPORT_NOT_EXTENDED;
Util.setShort(scratch, SCRATCH_CURRENT_OFFSET, (short)0);
Util.setShort(scratch, SCRATCH_SIGNATURE_LENGTH, signatureSize);
Expand Down Expand Up @@ -285,8 +286,9 @@ private void handleSign(APDU apdu) throws ISOException {
if (extendedLength) {
// If using extended length, the message can be completed and sent immediately
scratch[SCRATCH_TRANSPORT_STATE] = TRANSPORT_EXTENDED;
Util.arrayCopyNonAtomic(scratch, SCRATCH_PAD, buffer, (short)0, outOffset);
apdu.setOutgoingAndSend((short)0, (short)(outOffset - SCRATCH_PAD));
apdu.setOutgoing();
apdu.setOutgoingLength((short)(outOffset - SCRATCH_PAD));
apdu.sendBytesLong(scratch, SCRATCH_PAD, (short)(outOffset - SCRATCH_PAD));
}
else {
// Otherwise send the first chunk
Expand Down

0 comments on commit 7a7dcc7

Please sign in to comment.