1 package com.android.cts.omapi.test;
2 
3 import javacard.framework.APDU;
4 import javacard.framework.ISO7816;
5 import javacard.framework.Applet;
6 import javacard.framework.ISOException;
7 import javacard.framework.Util;
8 
9 public class CtsAndroidOmapiTestApplet extends Applet {
10 
11   final private static byte NO_DATA_INS_1 = (byte) 0x06;
12   final private static byte NO_DATA_INS_2 = (byte) 0x0A;
13 
14   final private static byte DATA_INS_1 = (byte) 0x08;
15   final private static byte DATA_INS_2 = (byte) 0x0C;
16 
17   final private static byte SW_62xx_APDU_INS = (byte) 0xF3;
18   final private static byte SW_62xx_DATA_APDU_P2 = (byte) 0x08;
19   final private static byte SW_62xx_VALIDATE_DATA_P2 = (byte) 0x0C;
20   private final static byte[] SW_62xx_VALIDATE_DATA_RESP =
21             new byte[]{0x01, (byte) 0xF3, 0x00, 0x0C, 0x01, (byte) 0xAA, 0x00};
22   private final static short[] SW_62xx_resp = new short[]{
23       (short)0x6200, (short)0x6281, (short)0x6282, (short)0x6283,
24       (short)0x6285, (short)0x62F1, (short)0x62F2, (short)0x63F1,
25       (short)0x63F2, (short)0x63C2, (short)0x6202, (short)0x6280,
26       (short)0x6284, (short)0x6286, (short)0x6300, (short)0x6381,
27   };
28 
29   final public static byte SEGMENTED_RESP_INS_1 = (byte) 0xC2;
30   final public static byte SEGMENTED_RESP_INS_2 = (byte) 0xC4;
31   final public static byte SEGMENTED_RESP_INS_3 = (byte) 0xC6;
32   final public static byte SEGMENTED_RESP_INS_4 = (byte) 0xC8;
33   final public static byte SEGMENTED_RESP_INS_5 = (byte) 0xCF;
34 
35   final private static byte CHECK_SELECT_P2_APDU = (byte)0xF4;
36   final public static byte GET_RESPONSE_INS = (byte) 0xC0;
37 
38   final private static byte BER_TLV_TYPE = (byte) 0x1F;
39   final private static short SELECT_RESPONSE_DATA_LENGTH = (short)252;
40 
41   private byte[] respBuf;
42   private short respBuffOffset = 0;
43 
44   final private static short LENGTH_256 = (short) 0x0100;
45   private final static byte[] resp_bytes256 = new byte[]{
46     (byte)0x00, (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04, (byte)0x05,
47     (byte)0x06, (byte)0x07, (byte)0x08, (byte)0x09, (byte)0x0A, (byte)0x0B,
48     (byte)0x0C, (byte)0x0D, (byte)0x0E, (byte)0x0F,
49     (byte)0x10, (byte)0x11, (byte)0x12, (byte)0x13, (byte)0x14, (byte)0x15,
50     (byte)0x16, (byte)0x17, (byte)0x18, (byte)0x19, (byte)0x1A, (byte)0x1B,
51     (byte)0x1C, (byte)0x1D, (byte)0x1E, (byte)0x1F,
52     (byte)0x20, (byte)0x21, (byte)0x22, (byte)0x23, (byte)0x24, (byte)0x25,
53     (byte)0x26, (byte)0x27, (byte)0x28, (byte)0x29, (byte)0x2A, (byte)0x2B,
54     (byte)0x2C, (byte)0x2D, (byte)0x2E, (byte)0x2F,
55     (byte)0x30, (byte)0x31, (byte)0x32, (byte)0x33, (byte)0x34, (byte)0x35,
56     (byte)0x36, (byte)0x37, (byte)0x38, (byte)0x39, (byte)0x3A, (byte)0x3B,
57     (byte)0x3C, (byte)0x3D, (byte)0x3E, (byte)0x3F,
58     (byte)0x40, (byte)0x41, (byte)0x42, (byte)0x43, (byte)0x44, (byte)0x45,
59     (byte)0x46, (byte)0x47, (byte)0x48, (byte)0x49, (byte)0x4A, (byte)0x4B,
60     (byte)0x4C, (byte)0x4D, (byte)0x4E, (byte)0x4F,
61     (byte)0x50, (byte)0x51, (byte)0x52, (byte)0x53, (byte)0x54, (byte)0x55,
62     (byte)0x56, (byte)0x57, (byte)0x58, (byte)0x59, (byte)0x5A, (byte)0x5B,
63     (byte)0x5C, (byte)0x5D, (byte)0x5E, (byte)0x5F,
64     (byte)0x60, (byte)0x61, (byte)0x62, (byte)0x63, (byte)0x64, (byte)0x65,
65     (byte)0x66, (byte)0x67, (byte)0x68, (byte)0x69, (byte)0x6A, (byte)0x6B,
66     (byte)0x6C, (byte)0x6D, (byte)0x6E, (byte)0x6F,
67     (byte)0x70, (byte)0x71, (byte)0x72, (byte)0x73, (byte)0x74, (byte)0x75,
68     (byte)0x76, (byte)0x77, (byte)0x78, (byte)0x79, (byte)0x7A, (byte)0x7B,
69     (byte)0x7C, (byte)0x7D, (byte)0x7E, (byte)0x7F,
70     (byte)0x80, (byte)0x81, (byte)0x82, (byte)0x83, (byte)0x84, (byte)0x85,
71     (byte)0x86, (byte)0x87, (byte)0x88, (byte)0x89, (byte)0x8A, (byte)0x8B,
72     (byte)0x8C, (byte)0x8D, (byte)0x8E, (byte)0x8F,
73     (byte)0x90, (byte)0x91, (byte)0x92, (byte)0x93, (byte)0x94, (byte)0x95,
74     (byte)0x96, (byte)0x97, (byte)0x98, (byte)0x99, (byte)0x9A, (byte)0x9B,
75     (byte)0x9C, (byte)0x9D, (byte)0x9E, (byte)0x9F,
76     (byte)0xA0, (byte)0xA1, (byte)0xA2, (byte)0xA3, (byte)0xA4, (byte)0xA5,
77     (byte)0xA6, (byte)0xA7, (byte)0xA8, (byte)0xA9, (byte)0xAA, (byte)0xAB,
78     (byte)0xAC, (byte)0xAD, (byte)0xAE, (byte)0xAF,
79     (byte)0xB0, (byte)0xB1, (byte)0xB2, (byte)0xB3, (byte)0xB4, (byte)0xB5,
80     (byte)0xB6, (byte)0xB7, (byte)0xB8, (byte)0xB9, (byte)0xBA, (byte)0xBB,
81     (byte)0xBC, (byte)0xBD, (byte)0xBE, (byte)0xBF,
82     (byte)0xC0, (byte)0xC1, (byte)0xC2, (byte)0xC3, (byte)0xC4, (byte)0xC5,
83     (byte)0xC6, (byte)0xC7, (byte)0xC8, (byte)0xC9, (byte)0xCA, (byte)0xCB,
84     (byte)0xCC, (byte)0xCD, (byte)0xCE, (byte)0xCF,
85     (byte)0xD0, (byte)0xD1, (byte)0xD2, (byte)0xD3, (byte)0xD4, (byte)0xD5,
86     (byte)0xD6, (byte)0xD7, (byte)0xD8, (byte)0xD9, (byte)0xDA, (byte)0xDB,
87     (byte)0xDC, (byte)0xDD, (byte)0xDE, (byte)0xDF,
88     (byte)0xE0, (byte)0xE1, (byte)0xE2, (byte)0xE3, (byte)0xE4, (byte)0xE5,
89     (byte)0xE6, (byte)0xE7, (byte)0xE8, (byte)0xE9, (byte)0xEA, (byte)0xEB,
90     (byte)0xEC, (byte)0xED, (byte)0xEE, (byte)0xEF,
91     (byte)0xF0, (byte)0xF1, (byte)0xF2, (byte)0xF3, (byte)0xF4, (byte)0xF5,
92     (byte)0xF6, (byte)0xF7, (byte)0xF8, (byte)0xF9, (byte)0xFA, (byte)0xFB,
93     (byte)0xFC, (byte)0xFD, (byte)0xFE, (byte)0xFF
94   };
95 
install(byte[] bArray, short bOffset, byte bLength)96   public static void install(byte[] bArray, short bOffset, byte bLength) {
97     // GP-compliant JavaCard applet registration
98     new com.android.cts.omapi.test.CtsAndroidOmapiTestApplet().register(bArray, (short) (bOffset + 1), bArray[bOffset]);
99   }
100 
process(APDU apdu)101   public void process(APDU apdu) {
102     byte[] buf = apdu.getBuffer();
103     short le, lc;
104     short sendLen;
105     byte p1 = buf[ISO7816.OFFSET_P1];
106     byte p2 = buf[ISO7816.OFFSET_P2];
107 
108     if (selectingApplet()) {
109       lc = buf[ISO7816.OFFSET_LC];
110       if (buf[(short)(lc + ISO7816.OFFSET_CDATA - 1)]  == 0x31) {
111         //AID: A000000476416E64726F696443545331
112         ISOException.throwIt(ISO7816.SW_NO_ERROR);
113       } else {
114         //A000000476416E64726F696443545332
115         sendLen = fillBerTLVBytes(SELECT_RESPONSE_DATA_LENGTH);
116         le = apdu.setOutgoing();
117         apdu.setOutgoingLength((short)sendLen);
118         Util.arrayCopy(respBuf, (short)0, buf, (short)0, (short)respBuf.length);
119         apdu.sendBytesLong(buf, respBuffOffset, sendLen);
120         return;
121       }
122     }
123     switch (buf[ISO7816.OFFSET_INS]) {
124     case NO_DATA_INS_1:
125     case NO_DATA_INS_2:
126       ISOException.throwIt(ISO7816.SW_NO_ERROR);
127       break;
128     case DATA_INS_2:
129       apdu.setIncomingAndReceive();
130       //case 3 APDU, return 256 bytes data
131       sendLen = fillBytes((short)256);
132       le = apdu.setOutgoing();
133       apdu.setOutgoingLength((short)sendLen);
134       Util.arrayCopy(respBuf, (short)0, buf, (short)0, (short)respBuf.length);
135       apdu.sendBytesLong(buf, respBuffOffset, sendLen);
136       break;
137     case GET_RESPONSE_INS:
138       apdu.setIncomingAndReceive();
139         //ISO GET_RESPONSE command
140         if (respBuf == null) {
141           ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
142         } else {
143           le = apdu.setOutgoing();
144           sendLen = (short) (respBuf.length - respBuffOffset);
145           sendLen = le > sendLen ? sendLen : le;
146           apdu.setOutgoingLength(sendLen);
147           apdu.sendBytesLong(respBuf, respBuffOffset, sendLen);
148           respBuffOffset += sendLen;
149           sendLen = (short) (respBuf.length - respBuffOffset);
150           if (sendLen > 0) {
151             if (sendLen > 256) sendLen = 0x00;
152             ISOException.throwIt((short)(ISO7816.SW_BYTES_REMAINING_00 | sendLen));
153           } else {
154             respBuf = null;
155           }
156         }
157       break;
158     case DATA_INS_1:
159       // return 256 bytes data
160       sendLen = fillBytes((short)256);
161       le = apdu.setOutgoing();
162       apdu.setOutgoingLength((short) sendLen);
163       Util.arrayCopy(respBuf, (short)0, buf, (short)0, (short)respBuf.length);
164       apdu.sendBytesLong(buf, respBuffOffset, sendLen);
165       break;
166     case SW_62xx_APDU_INS:
167       if (p1 > 16 || p1 < 1) {
168         ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
169       } else if (p2 == SW_62xx_DATA_APDU_P2){
170         sendLen = fillBytes((short)3);
171         le = apdu.setOutgoing();
172         apdu.setOutgoingLength((short)sendLen);
173         Util.arrayCopy(respBuf, (short)0, buf, (short)0, (short) respBuf.length);
174         apdu.sendBytesLong(buf, respBuffOffset, sendLen);
175         ISOException.throwIt(SW_62xx_resp[p1 -1]);
176       } else if (p2 == SW_62xx_VALIDATE_DATA_P2){
177         le = apdu.setOutgoing();
178         apdu.setOutgoingLength((short) (SW_62xx_VALIDATE_DATA_RESP.length));
179         Util.arrayCopy(SW_62xx_VALIDATE_DATA_RESP, (short) 0, buf, (short) 0,
180           (short) SW_62xx_VALIDATE_DATA_RESP.length);
181         buf[ISO7816.OFFSET_P1] = p1;
182         apdu.sendBytesLong(buf, (short)0, (short) SW_62xx_VALIDATE_DATA_RESP.length);
183         ISOException.throwIt(SW_62xx_resp[p1 -1]);
184       } else {
185         ISOException.throwIt(SW_62xx_resp[p1 -1]);
186       }
187       break;
188     case SEGMENTED_RESP_INS_1:
189     case SEGMENTED_RESP_INS_2:
190       le = (short)((short)((p1 & 0xFF)<< 8) | (short)(p2 & 0xFF));
191       sendLen = fillBytes(le);
192       le = apdu.setOutgoing();
193       sendLen = le > sendLen ? sendLen : le;
194       if (sendLen > 0xFF) sendLen = 0xFF;
195       apdu.setOutgoingLength(sendLen);
196       apdu.sendBytesLong(respBuf, respBuffOffset, sendLen);
197       respBuffOffset += sendLen;
198       sendLen = (short) (respBuf.length - respBuffOffset);
199       if (sendLen > 0) {
200         if (sendLen > 256) sendLen = 0x00;
201         ISOException.throwIt((short) (ISO7816.SW_BYTES_REMAINING_00 | sendLen));
202       }
203       break;
204     case SEGMENTED_RESP_INS_3:
205     case SEGMENTED_RESP_INS_4:
206       le = (short)((short)((p1 & 0xFF)<< 8) | (short)(p2 & 0xFF));
207       sendLen = fillBytes(le);
208       le = apdu.setOutgoing();
209       sendLen = le > sendLen ? sendLen : le;
210       apdu.setOutgoingLength(sendLen);
211       apdu.sendBytesLong(respBuf, respBuffOffset, sendLen);
212       respBuffOffset += sendLen;
213       sendLen = (short) (respBuf.length - respBuffOffset);
214       if (sendLen > 0) {
215         if (sendLen > 256) sendLen = 0x00;
216         ISOException.throwIt((short) (ISO7816.SW_BYTES_REMAINING_00 | sendLen));
217       }
218       break;
219 
220     case SEGMENTED_RESP_INS_5:
221       le = apdu.setOutgoing();
222       if (le != 0xFF) {
223         short buffer_len = (short)((short)((p1 & 0xFF)<< 8) | (short)(p2 & 0xFF));
224         sendLen = fillBytes(buffer_len);
225         sendLen = le > sendLen ? sendLen : le;
226         apdu.setOutgoingLength(sendLen);
227         apdu.sendBytesLong(respBuf, respBuffOffset, sendLen);
228         respBuffOffset += sendLen;
229         sendLen = (short) (respBuf.length - respBuffOffset);
230         if (sendLen > 0) {
231           if (sendLen > 256) sendLen = 0x00;
232           ISOException.throwIt((short)(ISO7816.SW_BYTES_REMAINING_00 | sendLen));
233         }
234       } else {
235         ISOException.throwIt((short)(ISO7816.SW_CORRECT_LENGTH_00 | 0xFF));
236       }
237       break;
238     case CHECK_SELECT_P2_APDU:
239       byte[] p2_00 = new byte[] {0x00};
240       le = apdu.setOutgoing();
241       apdu.setOutgoingLength((short) p2_00.length);
242       Util.arrayCopy(p2_00, (short) 0, buf, (short) 0, (short) p2_00.length);
243       apdu.sendBytesLong(buf, (short)0, (short)p2_00.length);
244       break;
245     default:
246       // Case is not known.
247       ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
248     }
249   }
250 
251   /**
252    * Fills APDU buffer with a pattern.
253    *
254    * @param le - length of outgoing data.
255    */
fillBerTLVBytes(short le)256   public short fillBerTLVBytes(short le) {
257     //support length from 0x00 - 0x7FFF
258     short total_len;
259     short le_len = 1;
260     if (le < (short)0x80) {
261       le_len = 1;
262     } else if (le < (short)0x100) {
263       le_len = 2;
264     } else {
265       le_len = 3;
266     }
267     total_len = (short)(le + 2 + le_len);
268     short i = 0;
269     respBuf = new byte[total_len];
270     respBuf[(short)i] = BER_TLV_TYPE;
271     i = (short)(i + 1);
272     respBuf[(short)i] = 0x00; //second byte of Type
273     i = (short)(i + 1);
274     if (le < (short)0x80) {
275       respBuf[(short)i] = (byte)le;
276       i = (short)(i + 1);
277     } else if (le < (short)0x100) {
278       respBuf[(short)i] = (byte)0x81;
279       i = (short)(i + 1);
280       respBuf[(short)i] = (byte)le;
281       i = (short)(i + 1);
282     } else {
283       respBuf[(short)i] = (byte)0x82;
284       i = (short)(i + 1);
285       respBuf[(short)i] = (byte)(le >> 8);
286       i = (short)(i + 1);
287       respBuf[(short)i] = (byte)(le & 0xFF);
288       i = (short)(i + 1);
289     }
290     while (i < total_len) {
291       respBuf[i] = (byte)((i - 2 - le_len) & 0xFF);
292       i = (short)(i + 1);
293     }
294     respBuf[(short)(respBuf.length - 1)] = (byte)0xFF;
295     respBuffOffset = (short) 0;
296     return total_len;
297   }
298 
fillBytes(short total_len)299   public short fillBytes(short total_len) {
300     short i = 0;
301     short len = total_len;
302     respBuf = new byte[total_len];
303     while (i < total_len) {
304       if (len >= LENGTH_256) {
305         Util.arrayCopyNonAtomic(resp_bytes256, (short)0, respBuf,
306           (short)i, LENGTH_256);
307         i = (short)(i + LENGTH_256);
308         len = (short)(len - LENGTH_256);
309       } else {
310         respBuf[i] = (byte)(i & 0xFF);
311         i = (short)(i + 1);
312       }
313     }
314     respBuffOffset = (short) 0;
315     //set the last byte to 0xFF for CTS validation
316     respBuf[(short)(respBuf.length - 1)] = (byte)0xFF;
317     return total_len;
318   }
319 }
320