/* * Copyright 2015 Licel Corporation. * * 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.framework; import com.licel.jcardsim.base.SimulatorSystem; import com.licel.jcardsim.utils.BiConsumer; import javacard.framework.AID; import javacard.framework.Applet; import javacard.framework.ISO7816; import javacard.framework.ISOException; import javacard.framework.Shareable; import javacard.framework.SystemException; /** * ProxyClass for <code>AppletProxy</code> * @see Applet */ public class AppletProxy { /** * The current registration callback, set by SimulatorRuntime via reflection. */ private static final ThreadLocal<BiConsumer<AppletProxy,AID>> registrationCallback = new ThreadLocal<BiConsumer<AppletProxy,AID>>(); /** * Only this class's <code>install()</code> method should create the applet object. */ protected AppletProxy() { } /** * To create an instance of the <code>Applet</code> subclass, the Java Card runtime environment * will call this static method first. * <p>The applet should * perform any necessary initializations and must call one of the <code>register()</code> methods. * Only one Applet instance can be successfully registered from within this install. * The installation is considered successful when the call to <code>register()</code> * completes without an exception. The installation is deemed unsuccessful if the * <code>install</code> method does not call a * <code>register()</code> method, or if an exception is thrown from within * the <code>install</code> method prior to the call to a <code>register()</code> * method, or if every call to the <code>register()</code> method results in an exception. * If the installation is unsuccessful, the Java Card runtime environment must perform all the necessary clean up * when it receives control. * Successful installation makes the applet instance capable of being selected via a * SELECT APDU command.<p> * Installation parameters are supplied in the byte array parameter and * must be in a format using length-value (LV) pairs as defined below: * <pre> * bArray[0] = length(Li) of instance AID, bArray[1..Li] = instance AID bytes, * bArray[Li+1]= length(Lc) of control info, bArray[Li+2..Li+Lc+1] = control info, * bArray[Li+Lc+2] = length(La) of applet data, bArray[Li+Lc+2..Li+Lc+La+1] = applet data * </pre> * In the above format, any of the lengths: Li, Lc or La may be zero. The control * information is implementation dependent. * <p> * The <code>bArray</code> object is a global array. If the applet * desires to preserve any of this data, it should copy * the data into its own object. * <p><code>bArray</code> is zeroed by the Java Card runtime environment after the return from the * <code>install()</code> method.<p> * References to the <code>bArray</code> object * cannot be stored in class variables or instance variables or array components. * See <em>Runtime Environment Specification for the Java Card Platform</em>, section 6.2.2 for details.<p> * The implementation of this method provided by * <code>Applet</code> class throws an <code>ISOException</code> with * reason code = <code>ISO7816.SW_FUNC_NOT_SUPPORTED</code>. * <p>Note:<ul> * <li><em>Exceptions thrown by this method after successful installation are caught * by the Java Card runtime environment and processed by the Installer.</em> * </ul> * @param bArray the array containing installation parameters * @param bOffset the starting offset in bArray * @param bLength the length in bytes of the parameter data in bArray * The maximum value of bLength is 127. * @throws ISOException if the install method failed */ public static void install(byte bArray[], short bOffset, byte bLength) throws ISOException { ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED); } /** * Called by the Java Card runtime environment to inform this applet that it has been selected when * no applet from the same package is active on any other logical channel. * <p>It is called when a SELECT APDU command or MANAGE CHANNEL OPEN APDU * command is received and before the applet is selected. * SELECT APDU commands use instance AID bytes for applet selection. * See <em>Runtime Environment Specification for the Java Card Platform</em>, section 4.5 for details.<p> * A subclass of <code>Applet</code> should override this method * if it should perform any initialization that may be required to * process APDU commands that may follow. * This method returns a boolean to indicate that it is ready to accept incoming APDU * commands via its <code>process()</code> method. If this method returns false, it indicates to * the Java Card runtime environment that this Applet declines to be selected. * <p>Note:<ul> * <li><em>The <CODE>javacard.framework.MultiSelectable.select(</CODE>) method is not * called if this method is invoked.</em> * </ul> * <p> * The implementation of this method provided by * <code>Applet</code> class returns <code>true</code>.<p> * @return <code>true</code> to indicate success, <code>false</code> otherwise */ public boolean select() { return true; } /** * Called by the Java Card runtime environment to inform that this currently selected applet is * being deselected on this logical channel and no applet from the same package * is still active on any other logical channel. * After deselection, this logical channel will be closed or another applet * (or the same applet) will be selected on this logical channel. * It is called when a SELECT APDU command or a MANAGE CHANNEL CLOSE APDU * command is received by the Java Card runtime environment. This method is invoked prior to another * applet's or this very applet's <code>select()</code> method being invoked. * <p> * A subclass of <code>Applet</code> should override this method if * it has any cleanup or bookkeeping work to be performed before another * applet is selected. * <p> * The default implementation of this method provided by <code>Applet</code> class does nothing.<p> * Notes:<ul> * <li><em>The <CODE>javacard.framework.MultiSelectable.deselect(</CODE>) method is not * called if this method is invoked.</em> * <li><em>Unchecked exceptions thrown by this method are caught by the Java Card runtime environment but the * applet is deselected.</em> * <li><em>Transient objects of </em><code>JCSystem.CLEAR_ON_DESELECT</code><em> clear event type * are cleared to their default value by the Java Card runtime environment after this method.</em> * <li><em>This method is NOT called on reset or power loss.</em> * </ul> */ public void deselect() { } /** * Called by the Java Card runtime environment to obtain a shareable interface object from this server applet, on * behalf of a request from a client applet. This method executes in the applet context of * <code>this</code> applet instance. * The client applet initiated this request by calling the * <code>JCSystem.getAppletShareableInterfaceObject()</code> method. * See <em>Runtime Environment Specification for the Java Card Platform</em>, section 6.2.4 for details. * <p>Note:<ul> * <li><em>The </em><code>clientAID</code><em> parameter is a Java Card runtime environment-owned </em><code>AID</code><em> * instance. Java Card runtime environment-owned instances of <code>AID</code> are permanent Java Card runtime environment * Entry Point Objects and can be accessed from any applet context. * References to these permanent objects can be stored and re-used.</em> * </ul> * @param clientAID the <code>AID</code> object of the client applet * @param parameter optional parameter byte. The parameter byte may be used by the client to specify * which shareable interface object is being requested. * @return the shareable interface object or <code>null</code> */ public Shareable getShareableInterfaceObject(AID clientAID, byte parameter) { return null; } /** * This method is used by the applet to register <code>this</code> applet instance with * the Java Card runtime environment and to * assign the Java Card platform name of the applet as its instance AID bytes. * One of the <code>register()</code> methods must be called from within <code>install()</code> * to be registered with the Java Card runtime environment. * See <em>Runtime Environment Specification for the Java Card Platform</em>, section 3.1 for details. * <p>Note:<ul> * <li><em>The phrase "Java Card platform name of the applet" is a reference to the </em><code>AID[AID_length]</code><em> * item in the </em><code>applets[]</code><em> item of the </em><code>applet_component</code><em>, as documented in Section 6.5 * Applet Component in the Virtual Machine Specification for the Java Card Platform.</em> * </ul> * @throws SystemException with the following reason codes:<ul> * <li><code>SystemException.ILLEGAL_AID</code> if the <code>Applet</code> subclass AID bytes are in use or * if the applet instance has previously successfully registered with the Java Card runtime environment via one of the * <code>register()</code> methods or if a Java Card runtime environment initiated <code>install()</code> method execution is not in progress. * </ul> */ protected final void register() throws SystemException { BiConsumer<AppletProxy,AID> callback = registrationCallback.get(); if (callback == null) { // not called from install() SystemException.throwIt(SystemException.ILLEGAL_AID); } else { callback.accept(this, null); } } /** * This method is used by the applet to register <code>this</code> applet instance with the Java Card runtime environment and * assign the specified AID bytes as its instance AID bytes. * One of the <code>register()</code> methods must be called from within <code>install()</code> * to be registered with the Java Card runtime environment. * See <em>Runtime Environment Specification for the Java Card Platform</em>, section 3.1 for details. * <p>Note:<ul> * <li><em>The implementation may require that the instance AID bytes specified are the same as that * supplied in the install parameter data. An ILLEGAL_AID exception may be thrown otherwise.</em> * </ul> * @param bArray the byte array containing the AID bytes * @param bOffset the start of AID bytes in bArray * @param bLength the length of the AID bytes in bArray * @throws SystemException with the following reason code:<ul> *<li><code>SystemException.ILLEGAL_VALUE</code> if the <code>bLength</code> parameter is *less than <code>5</code> or greater than <code>16</code>. *<li><code>SystemException.ILLEGAL_AID</code> if the specified instance AID bytes are in use or *if the applet instance has previously successfully registered with the Java Card runtime environment via one of the *<code>register()</code> methods or if a Java Card runtime environment-initiated <code>install()</code> method execution is not in progress. *</ul> */ protected final void register(byte bArray[], short bOffset, byte bLength) throws SystemException { if (bLength < 5 || bLength > 16) { throw new SystemException(SystemException.ILLEGAL_VALUE); } BiConsumer<AppletProxy,AID> callback = registrationCallback.get(); if (callback == null) { // not called from install() throw new SystemException(SystemException.ILLEGAL_AID); } callback.accept(this, new AID(bArray, bOffset, bLength)); } /** * This method is used by the applet <code>process()</code> method to distinguish * the SELECT APDU command which selected <code>this</code> applet, from all other * other SELECT APDU commands which may relate to file or internal applet state selection. * @return <code>true</code> if <code>this</code> applet is being selected */ protected final boolean selectingApplet() { return SimulatorSystem.instance().isAppletSelecting(this); } }