/* * Copyright 2014 Robert Bachmann * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.licel.jcardsim.base; import javacard.framework.ISO7816; import javacard.framework.Util; /** * Case of an <code>APDU</code>. */ public enum ApduCase { /** * Case 1 APDU (CLA, INS, P1, P2) */ Case1(false), /** * Case 2 APDU (CLA, INS, P1, P2, 1 byte Le) */ Case2(false), /** * Case 2 extended APDU (CLA, INS, P1, P2, 0, 2 byte Le) */ Case2Extended(true), /** * Case 3 APDU (CLA, INS, P1, P2, 1 byte Lc, Data) */ Case3(false), /** * Case 3 extended APDU (CLA, INS, P1, P2, 2 byte Lc, Data) */ Case3Extended(true), /** * Case 4 APDU (CLA, INS, P1, P2, 1 byte Lc, Data, 1 byte Le) */ Case4(false), /** * Case 4 extended APDU (CLA, INS, P1, P2, 0, 2 byte Lc, Data, 2 byte Le) */ Case4Extended(true); private final boolean extended; ApduCase(boolean extended) { this.extended = extended; } /** * @return <code>true</code> for extended APDU */ public boolean isExtended() { return extended; } /** * Determine case of APDU * @param command command APDU byte buffer * @return Case of <code>command</code> * @throws java.lang.IllegalArgumentException if <code>command</code> is malformed * @throws java.lang.NullPointerException if <code>command</code> is null */ public static ApduCase getCase(byte[] command) { if (command == null) { throw new NullPointerException("command"); } if (command.length < 4) { throw new IllegalArgumentException("command: malformed APDU, length < 4"); } if (command.length == 4) { return Case1; } if (command.length == 5) { return Case2; } if (command.length == 7 && command[ISO7816.OFFSET_LC] == 0) { return Case2Extended; } if (command[ISO7816.OFFSET_LC] == 0) { int lc = Util.getShort(command, (short) (ISO7816.OFFSET_LC + 1)); int offset = ISO7816.OFFSET_LC + 3; if (lc + offset == command.length) { return Case3Extended; } else if (lc + offset + 2 == command.length) { return Case4Extended; } else { throw new IllegalArgumentException("Invalid extended C-APDU: Lc or Le is invalid"); } } else { int lc = (command[ISO7816.OFFSET_LC] & 0xFF); int offset = ISO7816.OFFSET_LC + 1; if (lc + offset == command.length) { return Case3; } else if (lc + offset + 1 == command.length) { return Case4; } else { throw new IllegalArgumentException("Invalid C-APDU: Lc or Le is invalid"); } } } }