summaryrefslogtreecommitdiffstats
path: root/base/javacard/src/java/org/dogtagpki/javacard/ProxyApplet.java
blob: fd6c9d405ee73e09b41115ebcbcc595b07647491 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package org.dogtagpki.javacard;

import javacard.framework.*;

/**

 * @author Endi Sukma Dewata

 */
public class ProxyApplet extends Applet implements MultiSelectable {

    private final static byte[] TEST_APPLET_AID = {(byte) 0xa0, 0x00, 0x00, 0x00, 0x62, 0x03, 0x01, 0x0c, 0x01, 0x01 };

    private final static byte SAY_HELLO_INS = (byte) 0x01;
    private final static byte SAY_ECHO2_INS = (byte) 0x03;
    private final static byte SAY_IPARAMS_INS = (byte) 0x04;
    private final static byte NOP_INS = (byte) 0x02;

    private static byte[] helloMessage = new byte[] {
        'P', 'r', 'o', 'x', 'y',
        'A', 'p', 'p', 'l', 'e', 't'
    };

    private byte[] echoBytes;
    private byte[] initParamsBytes;
    private static final short LENGTH_ECHO_BYTES = 256;

    protected ProxyApplet(byte[] bArray, short bOffset, byte bLength) {
        echoBytes = new byte[LENGTH_ECHO_BYTES];
        if (bLength > 0) {
            byte iLen = bArray[bOffset]; // aid length

            bOffset = (short) (bOffset + iLen + 1);
            byte cLen = bArray[bOffset]; // info length

            bOffset = (short) (bOffset + cLen + 1);
            byte aLen = bArray[bOffset]; // applet data length

            initParamsBytes = new byte[aLen];
            Util.arrayCopyNonAtomic(bArray, (short) (bOffset + 1), initParamsBytes, (short) 0, aLen);
        }
        register();
    }

    public static void install(byte[] bArray, short bOffset, byte bLength)
            throws ISOException {
        new ProxyApplet(bArray, bOffset,bLength);
    }

    public void process(APDU apdu) {
        if(selectingApplet()) return;

        byte[] buffer = apdu.getBuffer();
        switch (buffer[ISO7816.OFFSET_INS]) {
            case SAY_HELLO_INS:
                sayHello(apdu);
                return;
            case SAY_ECHO2_INS:
                sayEcho2(apdu);
                return;
            case SAY_IPARAMS_INS:
                sayIParams(apdu);
                return;
            case NOP_INS:
                return;
            default:
                ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
        }
        return;
    }

    private void sayHello(APDU apdu) {
        byte[] buffer = apdu.getBuffer();
        short incomeBytes = apdu.setIncomingAndReceive();
        byte[] echo;

        if (buffer[ISO7816.OFFSET_P1] == 0x01) {
            echo = JCSystem.makeTransientByteArray(incomeBytes, JCSystem.CLEAR_ON_RESET);
            Util.arrayCopyNonAtomic(buffer, ISO7816.OFFSET_CDATA, echo, (short) 0, incomeBytes);
        } else {
            echo = JCSystem.makeTransientByteArray((short) helloMessage.length, JCSystem.CLEAR_ON_RESET);
            Util.arrayCopyNonAtomic(helloMessage, (short) 0, echo, (short) 0, (short) helloMessage.length);
        }

        apdu.setOutgoing();
        apdu.setOutgoingLength((short) echo.length);
        apdu.sendBytesLong(echo, (short) 0, (short) echo.length);
    }

    private void sayEcho2(APDU apdu) {
        byte buffer[] = apdu.getBuffer();
        short bytesRead = apdu.setIncomingAndReceive();
        short echoOffset = (short) 0;

        while (bytesRead > 0) {
            Util.arrayCopyNonAtomic(buffer, ISO7816.OFFSET_CDATA, echoBytes, echoOffset, bytesRead);
            echoOffset += bytesRead;
            bytesRead = apdu.receiveBytes(ISO7816.OFFSET_CDATA);
        }

        apdu.setOutgoing();
        apdu.setOutgoingLength((short) (echoOffset + 5));

        apdu.sendBytes((short) 0, (short) 5);
        apdu.sendBytesLong(echoBytes, (short) 0, echoOffset);
    }

    private void sayIParams(APDU apdu) {
        AID aid = JCSystem.lookupAID(TEST_APPLET_AID, (short)0, (byte)TEST_APPLET_AID.length);
        TestShareable shareable = (TestShareable)JCSystem.getAppletShareableInterfaceObject(aid, (byte)0);

        shareable.sayIParams(apdu);
    }

    public boolean select(boolean b) {
        return true;
    }

    public void deselect(boolean b) {
    }
}