-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
remove javacardx.framework.tlv reimplementation
Remove the javacardx.framework.tlv reimplementation and move most functions into our own NeoBERParser. The main reason for this is that some APDUs of the OpenPGP specification cannot be parsed with the official implementation. Therefore, if a card will implement the javacardx.framework.tlv and we do not use our own, things will go sideways. Our own NeoBERParser will process the TLVs in a more relaxed way. On a sidenote, I also bricked one JCOP4 card with a library reimplementation, where you now cannot remove the applet nor the library anymore. Signed-off-by: Michael Walle <[email protected]>
- Loading branch information
Showing
17 changed files
with
140 additions
and
543 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
// SPDX-License-Identifier: GPL-3.0-or-later | ||
package cc.walle.neopgp; | ||
|
||
import javacard.framework.Util; | ||
|
||
/* | ||
* This is bascially a reimplementation of javacardx.framework.tlv. | ||
* | ||
* Unfortunately, the OpenPGP specification has some APDUs that look | ||
* like BER encoded, but aren't. For example, the original implementation | ||
* will throw a TLVException(MALFORMED_TLV) when parsing the APDU to | ||
* import keys (instruction DBh). | ||
* | ||
* This implementation doesn't verify the TLVs nor will it enforce that | ||
* a tag will match the constructed bit (20h). | ||
*/ | ||
|
||
public class NeoBERParser { | ||
private NeoBERParser() {} | ||
|
||
public static byte size(byte[] berTagArray, short bOff) throws TLVException { | ||
return tagNumber(berTagArray, bOff) < 31 ? (byte)1 : (byte)2; | ||
} | ||
|
||
public static short tagNumber(byte[] berTagArray, short bOff) throws TLVException { | ||
short number; | ||
|
||
number = (short)(berTagArray[bOff] & 0x1f); | ||
if (number < 31) | ||
return number; | ||
|
||
number = (short)(berTagArray[(short)(bOff + 1)] & 0xff); | ||
if (number < 31) | ||
TLVException.throwIt(TLVException.MALFORMED_TAG); | ||
|
||
/* for simplicity this only supports two byte tags */ | ||
if (number >= 128) | ||
TLVException.throwIt(TLVException.ILLEGAL_SIZE); | ||
|
||
return number; | ||
} | ||
|
||
public static boolean isConstructed(byte[] berTagArray, short bOff) { | ||
return (berTagArray[bOff] & 0x20) != 0; | ||
} | ||
|
||
public static byte tagClass(byte[] berTagArray, short bOff) { | ||
return (byte)((berTagArray[bOff] >> 6) & 0x03); | ||
} | ||
|
||
public static short getLengthOffset(byte[] berTLVArray, short bOff) { | ||
return (short)(bOff + size(berTLVArray, bOff)); | ||
} | ||
|
||
public static short getValueOffset(byte[] berTLVArray, short bOff) { | ||
bOff = getLengthOffset(berTLVArray, bOff); | ||
|
||
if ((berTLVArray[bOff] & (byte)0x80) == (byte)0x80) { | ||
byte tmp = (byte)(berTLVArray[bOff] & (byte)0x7f); | ||
if (tmp > 2) | ||
TLVException.throwIt(TLVException.TLV_SIZE_GREATER_THAN_32767); | ||
|
||
bOff += tmp; | ||
} | ||
|
||
return (short)(bOff + (short)1); | ||
} | ||
|
||
public static short getLength(byte[] berTLVArray, short bOff) { | ||
bOff = getLengthOffset(berTLVArray, bOff); | ||
|
||
if ((berTLVArray[bOff] & 0x80) == 0) | ||
return berTLVArray[bOff]; | ||
|
||
switch ((berTLVArray[bOff] & 0x7f)) { | ||
case 1: | ||
return (short)(berTLVArray[(short)(bOff + 1)] & 0xff); | ||
case 2: | ||
return Util.getShort(berTLVArray, (short)(bOff + 1)); | ||
default: | ||
TLVException.throwIt(TLVException.ILLEGAL_SIZE); | ||
return 0; | ||
} | ||
} | ||
|
||
public static short getTag(byte[] berTLVArray, short bTLVOff, byte[] berTagArray, short bTagOff) { | ||
short size = size(berTLVArray, bTLVOff); | ||
Util.arrayCopyNonAtomic(berTLVArray, bTLVOff, berTagArray, bTagOff, size); | ||
return size; | ||
} | ||
|
||
public static short find(byte[] berTLVArray, short bTLVOff, byte[] berTagArray, short bTagOff) { | ||
short startOffset = getValueOffset(berTLVArray, bTLVOff); | ||
return findCommon(berTLVArray, bTLVOff, startOffset, berTagArray, bTagOff); | ||
} | ||
|
||
public static short findNext(byte[] berTLVArray, short bTLVOff, short startOffset, byte[] berTagArray, short bTagOff) { | ||
startOffset = next(berTLVArray, startOffset); | ||
return findCommon(berTLVArray, bTLVOff, startOffset, berTagArray, bTagOff); | ||
} | ||
|
||
private static short next(byte[] berTLVArray, short startOffset) { | ||
return (short)(getValueOffset(berTLVArray, startOffset) + getLength(berTLVArray, startOffset)); | ||
} | ||
|
||
private static short findCommon(byte[] berTLVArray, short bTLVOff, short startOffset, byte[] berTagArray, short bTagOff) { | ||
short valueLength = getLength(berTLVArray, bTLVOff); | ||
short valueOffset = getValueOffset(berTLVArray, bTLVOff); | ||
|
||
while (startOffset < (short)(valueOffset + valueLength)) { | ||
if (tagNumber(berTagArray, bTagOff) == tagNumber(berTLVArray, startOffset) && | ||
isConstructed(berTagArray, bTagOff) == isConstructed(berTLVArray, startOffset) && | ||
tagClass(berTagArray, bTagOff) == tagClass(berTLVArray, startOffset)) | ||
return startOffset; | ||
|
||
startOffset = next(berTLVArray, startOffset); | ||
} | ||
|
||
return -1; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.