NFC: Move eseclient to correct folder
Move the eseclient to the correct folder and delete currently
unused files.
Change-Id: Ia6941f3fcb1fdbfa6ed856797361b86676004c34
CRs-Fixed: 1008978
diff --git a/LTSMClient/Android.mk b/LTSMClient/Android.mk
deleted file mode 100644
index a8a436f..0000000
--- a/LTSMClient/Android.mk
+++ /dev/null
@@ -1,24 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_STATIC_JAVA_LIBRARIES += guava com.android.vcard \
- LTSMLibs \
- LTSMLibs1
-
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_PACKAGE_NAME := ltsmclient
-LOCAL_SRC_FILES +=src/com/nxp/ltsm/ltsmclient/ILTSMClient.aidl
-LOCAL_PRIVILEGED_MODULE := true
-
-#LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
-
-include $(CLEAR_VARS)
-
-LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := LTSMLibs:libs/gson-2.2.4.jar LTSMLibs1:libs/commons-codec-1.9.jar
-
-include $(BUILD_MULTI_PREBUILT)
diff --git a/LTSMClient/AndroidManifest.xml b/LTSMClient/AndroidManifest.xml
deleted file mode 100644
index 8ef9064..0000000
--- a/LTSMClient/AndroidManifest.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.nxp.ltsm.ltsmclient"
- android:versionCode="1"
- android:versionName="1.0" >
-
- <uses-sdk
- android:minSdkVersion="9"
- android:targetSdkVersion="18" />
- <uses-permission android:name="android.permission.NFC" />
- <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- <uses-permission android:name="android.permission.GET_TASKS"/>
-
- <application
- android:allowBackup="false"
- android:icon="@drawable/ic_launcher"
- android:label="@string/app_name"
- android:theme="@style/AppTheme" >
- <service
- android:name=".LTSMClient">
- <intent-filter>
- <action android:name="com.nxp.ltsm.ltsmclient" />
- </intent-filter>
- </service>
- </application>
-<debug/>
-</manifest>
\ No newline at end of file
diff --git a/LTSMClient/libs/android-support-v4.jar b/LTSMClient/libs/android-support-v4.jar
deleted file mode 100644
index 9056828..0000000
--- a/LTSMClient/libs/android-support-v4.jar
+++ /dev/null
Binary files differ
diff --git a/LTSMClient/libs/commons-codec-1.9.jar b/LTSMClient/libs/commons-codec-1.9.jar
deleted file mode 100644
index ef35f1c..0000000
--- a/LTSMClient/libs/commons-codec-1.9.jar
+++ /dev/null
Binary files differ
diff --git a/LTSMClient/libs/gson-2.2.4-javadoc.jar b/LTSMClient/libs/gson-2.2.4-javadoc.jar
deleted file mode 100644
index ce8fa7d..0000000
--- a/LTSMClient/libs/gson-2.2.4-javadoc.jar
+++ /dev/null
Binary files differ
diff --git a/LTSMClient/libs/gson-2.2.4-sources.jar b/LTSMClient/libs/gson-2.2.4-sources.jar
deleted file mode 100644
index 30b13f6..0000000
--- a/LTSMClient/libs/gson-2.2.4-sources.jar
+++ /dev/null
Binary files differ
diff --git a/LTSMClient/libs/gson-2.2.4.jar b/LTSMClient/libs/gson-2.2.4.jar
deleted file mode 100644
index 9478253..0000000
--- a/LTSMClient/libs/gson-2.2.4.jar
+++ /dev/null
Binary files differ
diff --git a/LTSMClient/project.properties b/LTSMClient/project.properties
deleted file mode 100644
index a3ee5ab..0000000
--- a/LTSMClient/project.properties
+++ /dev/null
@@ -1,14 +0,0 @@
-# This file is automatically generated by Android Tools.
-# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
-#
-# This file must be checked in Version Control Systems.
-#
-# To customize properties used by the Ant build system edit
-# "ant.properties", and override values to adapt the script to your
-# project structure.
-#
-# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
-#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
-
-# Project target.
-target=android-17
diff --git a/LTSMClient/res/drawable-hdpi/ic_launcher.png b/LTSMClient/res/drawable-hdpi/ic_launcher.png
deleted file mode 100644
index 288b665..0000000
--- a/LTSMClient/res/drawable-hdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/LTSMClient/res/drawable-mdpi/ic_launcher.png b/LTSMClient/res/drawable-mdpi/ic_launcher.png
deleted file mode 100644
index 6ae570b..0000000
--- a/LTSMClient/res/drawable-mdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/LTSMClient/res/drawable-xhdpi/ic_launcher.png b/LTSMClient/res/drawable-xhdpi/ic_launcher.png
deleted file mode 100644
index d4fb7cd..0000000
--- a/LTSMClient/res/drawable-xhdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/LTSMClient/res/drawable-xxhdpi/ic_launcher.png b/LTSMClient/res/drawable-xxhdpi/ic_launcher.png
deleted file mode 100644
index 85a6081..0000000
--- a/LTSMClient/res/drawable-xxhdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/LTSMClient/res/layout/activity_ltsmclient.xml b/LTSMClient/res/layout/activity_ltsmclient.xml
deleted file mode 100644
index e6b3d42..0000000
--- a/LTSMClient/res/layout/activity_ltsmclient.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingBottom="@dimen/activity_vertical_margin"
- android:paddingLeft="@dimen/activity_horizontal_margin"
- android:paddingRight="@dimen/activity_horizontal_margin"
- android:paddingTop="@dimen/activity_vertical_margin"
- tools:context=".LTSMClient" >
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/hello_world" />
-
-</RelativeLayout>
diff --git a/LTSMClient/res/menu/ltsmclient.xml b/LTSMClient/res/menu/ltsmclient.xml
deleted file mode 100644
index c002028..0000000
--- a/LTSMClient/res/menu/ltsmclient.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<menu xmlns:android="http://schemas.android.com/apk/res/android" >
-
- <item
- android:id="@+id/action_settings"
- android:orderInCategory="100"
- android:showAsAction="never"
- android:title="@string/action_settings"/>
-
-</menu>
diff --git a/LTSMClient/res/values-sw600dp/dimens.xml b/LTSMClient/res/values-sw600dp/dimens.xml
deleted file mode 100644
index 44f01db..0000000
--- a/LTSMClient/res/values-sw600dp/dimens.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<resources>
-
- <!--
- Customize dimensions originally defined in res/values/dimens.xml (such as
- screen margins) for sw600dp devices (e.g. 7" tablets) here.
- -->
-
-</resources>
diff --git a/LTSMClient/res/values-sw720dp-land/dimens.xml b/LTSMClient/res/values-sw720dp-land/dimens.xml
deleted file mode 100644
index 61e3fa8..0000000
--- a/LTSMClient/res/values-sw720dp-land/dimens.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<resources>
-
- <!--
- Customize dimensions originally defined in res/values/dimens.xml (such as
- screen margins) for sw720dp devices (e.g. 10" tablets) in landscape here.
- -->
- <dimen name="activity_horizontal_margin">128dp</dimen>
-
-</resources>
diff --git a/LTSMClient/res/values-v11/styles.xml b/LTSMClient/res/values-v11/styles.xml
deleted file mode 100644
index 3c02242..0000000
--- a/LTSMClient/res/values-v11/styles.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<resources>
-
- <!--
- Base application theme for API 11+. This theme completely replaces
- AppBaseTheme from res/values/styles.xml on API 11+ devices.
- -->
- <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
- <!-- API 11 theme customizations can go here. -->
- </style>
-
-</resources>
diff --git a/LTSMClient/res/values-v14/styles.xml b/LTSMClient/res/values-v14/styles.xml
deleted file mode 100644
index a91fd03..0000000
--- a/LTSMClient/res/values-v14/styles.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<resources>
-
- <!--
- Base application theme for API 14+. This theme completely replaces
- AppBaseTheme from BOTH res/values/styles.xml and
- res/values-v11/styles.xml on API 14+ devices.
- -->
- <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
- <!-- API 14 theme customizations can go here. -->
- </style>
-
-</resources>
diff --git a/LTSMClient/res/values/dimens.xml b/LTSMClient/res/values/dimens.xml
deleted file mode 100644
index 55c1e59..0000000
--- a/LTSMClient/res/values/dimens.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<resources>
-
- <!-- Default screen margins, per the Android Design guidelines. -->
- <dimen name="activity_horizontal_margin">16dp</dimen>
- <dimen name="activity_vertical_margin">16dp</dimen>
-
-</resources>
diff --git a/LTSMClient/res/values/strings.xml b/LTSMClient/res/values/strings.xml
deleted file mode 100644
index 788d824..0000000
--- a/LTSMClient/res/values/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-
- <string name="app_name">LTSMClient</string>
- <string name="action_settings">Settings</string>
- <string name="hello_world">Hello world!</string>
-
-</resources>
diff --git a/LTSMClient/res/values/styles.xml b/LTSMClient/res/values/styles.xml
deleted file mode 100644
index 6ce89c7..0000000
--- a/LTSMClient/res/values/styles.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<resources>
-
- <!--
- Base application theme, dependent on API level. This theme is replaced
- by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
- -->
- <style name="AppBaseTheme" parent="android:Theme.Light">
- <!--
- Theme customizations available in newer API levels can go in
- res/values-vXX/styles.xml, while customizations related to
- backward-compatibility can go here.
- -->
- </style>
-
- <!-- Application theme. -->
- <style name="AppTheme" parent="AppBaseTheme">
- <!-- All customizations that are NOT specific to a particular API-level can go here. -->
- </style>
-
-</resources>
diff --git a/LTSMClient/src/com/nxp/ltsm/ltsmclient/ILTSMClient.aidl b/LTSMClient/src/com/nxp/ltsm/ltsmclient/ILTSMClient.aidl
deleted file mode 100644
index cf72c77..0000000
--- a/LTSMClient/src/com/nxp/ltsm/ltsmclient/ILTSMClient.aidl
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2014 NXP Semiconductors
- *
- * 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.nxp.ltsm.ltsmclient;
-
-interface ILTSMClient{
- byte[] createVirtualCard(in byte[] vcData, in byte[] personalizeData);
- byte[] deleteVirtualCard(int vcEntry);
- byte[] activateVirtualCard(int vcEntry, boolean mode);
- byte[] addAndUpdateMdac(int vcEntry,in byte[] vcData);
- byte[] readMifareData(int vcEntry,in byte[] vcData);
- byte[] getVcList();
-}
\ No newline at end of file
diff --git a/LTSMClient/src/com/nxp/ltsm/ltsmclient/LTSMClient.java b/LTSMClient/src/com/nxp/ltsm/ltsmclient/LTSMClient.java
deleted file mode 100644
index 371c7b4..0000000
--- a/LTSMClient/src/com/nxp/ltsm/ltsmclient/LTSMClient.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2014 NXP Semiconductors
- *
- * 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.nxp.ltsm.ltsmclient;
-
-import java.io.File;
-import java.io.IOException;
-
-import android.app.Service;
-import android.content.Intent;
-import android.os.IBinder;
-import android.util.Log;
-
-public class LTSMClient extends Service {
-
- private LTSMCommunicator binder;
- @Override
- public void onCreate() {
- super.onCreate();
-
- binder = new LTSMCommunicator(this);
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- // Return the interface
- return binder;
- }
-
-}
diff --git a/LTSMClient/src/com/nxp/ltsm/ltsmclient/LTSMCommunicator.java b/LTSMClient/src/com/nxp/ltsm/ltsmclient/LTSMCommunicator.java
deleted file mode 100644
index 2647e87..0000000
--- a/LTSMClient/src/com/nxp/ltsm/ltsmclient/LTSMCommunicator.java
+++ /dev/null
@@ -1,2026 +0,0 @@
-/*
- * Copyright (C) 2014 NXP Semiconductors
- *
- * 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.nxp.ltsm.ltsmclient;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-import android.R.integer;
-import android.R.string;
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.content.pm.PackageInfo;
-import com.nxp.eseclient.LtsmService;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-import android.view.InflateException;
-
-import com.google.gson.Gson;
-import com.nxp.ltsm.ltsmclient.tools.Data;
-import com.nxp.ltsm.ltsmclient.tools.Utils;
-import com.nxp.ltsm.ltsmclient.tools.VCDescriptionFile;
-
-import java.util.Arrays;
-
-public class LTSMCommunicator extends ILTSMClient.Stub {
-
- private static final String LOG_TAG = "LTSMCommunicator";
- private static Context context;
- private static String CurrentPackage;
- private static Binder mBinder = new Binder();
- private static Bundle bundle;
- static int[] channelId = new int[10];
- static int[] isopened = new int[10];
- static int channelCnt = 0;
- static VCDescriptionFile vcDescriptionFile = new VCDescriptionFile();
- private static LtsmService mLtsmService = null;
- private static String currentProcess = "";
- static ltsmRegistry Registry;
- static int InitialVCEntry = 0;
- static int currentVcEntry = 0;
- static int DeleteVCEntry = 99;
- static short statusCode = 0;
-
- public LTSMCommunicator(Context context) {
- LTSMCommunicator.context = context;
-
- }
-
- /*******************************************************
- *
- * Responsible for creating the Virtual Card
- * The second argument-Personalise Data is optional and it is not mandatory to pass.
- * If VC Creation configuration is set to 1, then Personalise Data shall be also provided.
- *
- *@param vcData
- *@param Personalise Data
- *
- *@return If success then the VC entry number and VCUID are returned
- * to the SP Application along with status word. Otherwise an error code.
- *
- *******************************************************/
-
- @Override
- public synchronized byte[] createVirtualCard(byte[] vcData,byte[] personalizeData) throws RemoteException {
- String TAG = "LTSMCommunicator:CreateVirtualCard";
- Log.i(TAG, "Enter");
- statusCode = 0;
- byte[] rData = new byte[0];
- byte cData[] = new byte[0];
- currentProcess = "CreateVirtualCard";
- int stat = Data.FAILED;
- boolean personalize = false;
- Log.i(TAG, "vcData : " + Utils.bytArrayToHex(vcData));
-
- boolean available = Utils.checkRegistryAvail(context);
- if(!available){
- available = Utils.checkRegBackupAvail();
- if(available){
- Utils.importReg();
- }else{
- Log.i(TAG, "no backup available");
- //return Utils.createStatusCode(Data.SW_REGISTRY_IS_EMPTY);
- }
- }
- if(available){
-
- //If Registry is already available in SharedPreference Check for Uninstalled Wallet Apps
- stat = checkUninstalledApps();
- if(stat == Data.SUCCESS){
- Log.i(TAG, "Uninstalled App Found");
- }
- stat = getStatus();
- if(stat == Data.SUCCESS){
- Log.i(TAG, "getStatus success");
- }
- }
-
- // Initiate the LTSM. Open Logical Channel and Select LTSM
- stat = ltsmStart();
-
- if(stat == Data.FAILED){
- Log.i(TAG, "LTSMStart Failed");
- if(statusCode != 0){
- return Utils.createStatusCode(statusCode);
- }
- }
-
- // Get the VC Entry for Current Create VC
- stat = managecurrentVcEntry(Registry);
- if(stat == Data.FAILED){
- Log.i(TAG, "Registry Exceeds MaxVC Count");
- closeLogicalChannel();
- return Utils.createStatusCode(Data.SW_REGISTRY_FULL);
- }
-
- //Create the Registry Entries for New VC Entry
- Registry.vcCount = Registry.vcCount + 1;
- Registry.walletName.add(Utils.getCallingAppPkg(context));
- Registry.shaWalletName.add(Utils.createSha(Utils.getCallingAppPkg(context)));
- Registry.vcCreateStatus.add(false);
- Registry.vcActivatedStatus.add(false);
- Registry.vcEntry.add((currentVcEntry));
- Registry.vcType.add("");
- Registry.vcUid.add("");
- saveRegistry(Registry);
-
- CurrentPackage = Utils.getCallingAppPkg(context);
- //Check Registry is Proper
- stat = check(Registry);
- if(stat == Data.FAILED){
- closeLogicalChannel();
- return Utils.createStatusCode(Data.SW_IMPROPER_REGISTRY);
- }
-
- if(personalizeData != null){
- stat = handlePersonalize(personalizeData,CurrentPackage,(short)currentVcEntry);
- if(stat == Data.SW_PROCESSING_ERROR){
- closeLogicalChannel();
- Log.i(TAG, "Error Personalization : " + Utils.createStatusCode(statusCode));
- return Utils.createStatusCode(statusCode);
- }
- }
-
- //currentProcess used during Process Response if CreateVC is Success
- currentProcess = "CreateVirtualCard";
- Registry = loadRegistry();
- Log.i(TAG, "(short)Registry.vcEntry.get(Registry.vcCount-1).intValue() " + (short)Registry.vcEntry.get(Registry.vcCount-1).intValue());
- cData = vcDescriptionFile.createVc(vcData,Registry.shaWalletName.get(Registry.vcCount-1),(short)currentVcEntry);
-
- Log.i(TAG, "cData : " + Utils.bytArrayToHex(cData));
- exchangeLtsmProcessCommand(cData);
- closeLogicalChannel();
-
- //Form the Response Data
- Registry = loadRegistry();
- for( int i = 0;i<Registry.vcCount;i++){
- if(Registry.vcEntry.get(i).equals(currentVcEntry))
- {
- if(Registry.vcCreateStatus.get(i) == false){
- Log.i(TAG, "Create VC FAILED for VC Entry : "+Registry.vcEntry.get(i));
- Log.i(TAG, "cData : " + Utils.bytArrayToHex(Utils.createStatusCode(statusCode)));
- rData = Utils.createStatusCode(statusCode);
- }else{
- rData = vcDescriptionFile.CreateVCResp(currentVcEntry,Registry.vcUid.get(i));
- Log.i(TAG, "Create VC SUCCESS for VC Entry : "+Registry.vcEntry.get(i));
- }
- break;
- }
- }
- //Delete VC with Create Status False in the Registry.
- cleanUp();
-
- Log.i(TAG, "CreateVCResp : " + Utils.bytArrayToHex(rData));
- Utils.exportReg();
- Log.i(TAG, "Exit");
- return rData;
- }
-
- /*******************************************************
- *
- * Responsible for deleting the Virtual Card
- *
- *@param VC entry number to be deleted
- *
- *@return Status word informing success or failure
- *
- ********************************************************/
-
- @Override
- public synchronized byte[] deleteVirtualCard(int vcEntry) throws RemoteException {
- String TAG = "LTSMCommunicator:deleteVirtualCard";
- Log.i(TAG, "Enter");
- statusCode = 0;
- byte[] rData = new byte[0];
- boolean available = Utils.checkRegistryAvail(context);
- if(!available){
- available = Utils.checkRegBackupAvail();
- if(available){
- Utils.importReg();
- }else{
- Log.i(TAG, "no backup available");
- return Utils.createStatusCode(Data.SW_REGISTRY_IS_EMPTY);
- }
- }
- String CurrentPackage = Utils.getCallingAppPkg(context);
- currentProcess = "deleteVirtualCard";
- DeleteVCEntry = vcEntry;
- int i;
- boolean VC_Present = false;
- int stat = Data.FAILED;
- Registry = loadRegistry();
-
- //Check Registry is Proper
- stat = check(Registry);
- if(stat == Data.FAILED){
- Log.i(TAG, "Registry data is not proper");
- return Utils.createStatusCode(Data.SW_IMPROPER_REGISTRY);
- }
-
- stat = ltsmStart();
- if(stat == Data.FAILED){
- Log.i(TAG, "LTSMStart Failed");
- if(statusCode != 0){
- return Utils.createStatusCode(statusCode);
- }
- }
- byte[] cData = vcDescriptionFile.deleteVc(Utils.createSha(Utils.getCallingAppPkg(context)),(short)vcEntry);
-
- stat = exchangeLtsmProcessCommand(cData);
- if(stat == Data.SW_NO_ERROR){
- rData = Utils.createStatusCode(Data.SW_NO_ERROR);
- }
- else{
- rData = Utils.createStatusCode(statusCode);
- }
-
- closeLogicalChannel();
- Utils.exportReg();
- Log.i(TAG, "deleteVirtualCard : " + Utils.bytArrayToHex(rData));
- Log.i(TAG, "Exit");
- return rData;
- }
-
- /*******************************************************
- *
- * Activate/Deactivate Virtual Card.
- *
- *@param vcEntry
- *@param Activation mode - true/false for activate/deactivate the VC
- *
- *@return Status word informing Success or Failure
- *
- ********************************************************/
-
- @Override
- public synchronized byte[] activateVirtualCard(int vcEntry, boolean mode) throws RemoteException {
- String TAG = "LTSMCommunicator:ActivateVirtualCard";
- Log.i(TAG, "Enter");
- byte[] rData = new byte[0];
-
- statusCode = 0;
- boolean available = Utils.checkRegistryAvail(context);
- if(!available){
- available = Utils.checkRegBackupAvail();
- if(available){
- Utils.importReg();
- }else{
- Log.i(TAG, "no backup available");
- return Utils.createStatusCode(Data.SW_REGISTRY_IS_EMPTY);
- }
- }
-
- byte[] retStat = new byte[4];
- int stat = Data.FAILED;
- byte[] deactivatedvcEntry = new byte[2],Ret_Data = new byte[4];
- byte[] rcvData = new byte[]{};
-
- int i;
-
-
- Registry = loadRegistry();
- if(Registry.vcCount == 0){
- Log.i(TAG, "No VC is Present");
- return Utils.createStatusCode(Data.SW_REGISTRY_IS_EMPTY);
- }
- try {
- Thread.sleep(1000);
- } catch (Exception e) {
-
- }
-
- String pkg = Utils.getCallingAppPkg(context);
- Log.i(TAG, "vcEntry : " + vcEntry);
- Log.i(TAG, "pkg : " + pkg);
- //Check for Requested VC Entry's Current Status
- for( i = 0;i<Registry.vcCount;i++){
-
- if((Registry.vcEntry.get(i).intValue() == vcEntry)&&(Registry.shaWalletName.get(i).toString().equals(Utils.createSha(pkg)))){
- break;
- }
- }
- if(i == Registry.vcCount){
- Log.i(TAG, "Not a Valid VC Entry");
- return Utils.createStatusCode(Data.SW_INVALID_VC_ENTRY);
- }
- byte[] aid = vcDescriptionFile.createTlv(0x4F,Utils.append(Data.ACTV_LTSM_AID,Utils.shortToByteArr((short)vcEntry)));
- Log.i(TAG, "aid : " + Utils.bytArrayToHex(aid));
- try {
- openConnection();
- } catch (RemoteException e) {
- // closeLogicalChannel();
- e.printStackTrace();
- }
-
- //Select CRS Prior to Activate
- stat = crsSelect();
- if(stat == Data.FAILED){
- Log.i(TAG, "crsSelect Failed");
- return Utils.createStatusCode(Data.SW_CRS_SELECT_FAILED);
- }
-
- rcvData = gating(aid,mode);
-
- if(Utils.getSW(rcvData) == Data.SUCCESS){
- rData = Utils.createStatusCode(Data.SW_NO_ERROR);
- }
- else if (Utils.getSW(rcvData) == Data.SW_OTHER_ACTIVEVC_EXIST) {
- stat = parseSetStatusResp(rcvData);
- if (stat == Data.SUCCESS) {
- rcvData = gating(aid,mode);
- if(Utils.getSW(rcvData) == Data.SUCCESS){
- // retData = Utils.append(Utils.createStatusCode(Data.SW_OTHER_ACTIVEVC_EXIST), Utils.createStatusCode(Data.SW_NO_ERROR));
- rData = Utils.createStatusCode(Data.SW_NO_ERROR);
- }else{
- rData = rcvData;
- }
- }
- else{
- rData = Utils.createStatusCode(Data.SW_PROCESSING_ERROR);
- }
- }else{
- rData = rcvData;
- }
- Log.i(TAG, "retData : " + Utils.bytArrayToHex(rData));
- Utils.exportReg();
- try {
- closeConnection();
- } catch (RemoteException e) {
- // closeLogicalChannel();
- e.printStackTrace();
- }
- Log.i(TAG, "activateVirtualCard : " + Utils.bytArrayToHex(rData));
- Log.i(TAG, "Exit");
- return rData;
- }
-
- /*******************************************************
- *
- * Add and Updates MDAC used to define the MIFARE Data that
- * may be retrieved by the SP Application
- *
- *@param vcEntry
- *@param vcData
- *
- *@return Status word informing Success or Failure
- *
- ********************************************************/
-
- @Override
- public synchronized byte[] addAndUpdateMdac(int vcEntry,byte[] vcData) throws RemoteException {
- String TAG = "LTSMCommunicator:addAndUpdateMdac";
- currentProcess = "addAndUpdateMdac";
- Log.i(TAG, "Enter");
- statusCode = 0;
- byte[] rData = new byte[0];
- int stat = Data.FAILED;
-
- boolean available = Utils.checkRegistryAvail(context);
- if(!available){
- available = Utils.checkRegBackupAvail();
- if(available){
- Utils.importReg();
- }else{
- Log.i(TAG, "no backup available");
- return Utils.createStatusCode(Data.SW_REGISTRY_IS_EMPTY);
- }
- }
-
- String pkg = Utils.getCallingAppPkg(context);
- Registry = loadRegistry();
- int i;
- if(Registry.vcCount == 0){
- Log.i(TAG, "No VC is Present");
- return Utils.createStatusCode(Data.SW_REGISTRY_IS_EMPTY);
- }
- for( i = 0;i<Registry.vcCount;i++){
- if((Registry.vcEntry.get(i).intValue() == vcEntry)){//&&(Registry.shaWalletName.get(i).toString().equals(Utils.createSha(pkg)))){
- break;
- }
- }
- if(i == Registry.vcCount){
- Log.i(TAG, "Not a Valid VC Entry");
- return Utils.createStatusCode(Data.SW_INVALID_VC_ENTRY);
- }
-
- stat = ltsmStart();
- if(stat == Data.FAILED){
- Log.i(TAG, "LTSMStart Failed");
- if(statusCode != 0){
- return Utils.createStatusCode(statusCode);
- }
- }
-
- Registry = loadRegistry();
- byte[] cData = vcDescriptionFile.AddandUpdateMDAC(vcData,(short)vcEntry,Utils.createSha(pkg));
- Log.i(TAG, "cData : " + cData.length);
- stat = exchangeLtsmProcessCommand(cData);
- if(stat == Data.SW_NO_ERROR){
- rData = Utils.createStatusCode(Data.SW_NO_ERROR);
- // retStat = Utils.append(rData, Utils.createStatusCode(Data.SW_NO_ERROR));
- // rData = new byte[0];
- }
- else{
- rData = Utils.createStatusCode(statusCode);
- }
- closeLogicalChannel();
- Log.i(TAG, "retStat : " + Utils.arrayToHex(rData));
- Utils.exportReg();
- Log.i(TAG, "Exit");
- return rData;
- }
-
- /*******************************************************
- *
- * Read Mifare Data used to retrieve MIFARE data from a VC
- * under the condition that the MIFARE Data Access Control(s)
- * have been provided with Add and update MDAC
- *
- *@param vcData
- *@param vcEntry
- *
- *@return Read Mifare Data and Status Word
- *
- ********************************************************/
-
- @Override
- public synchronized byte[] readMifareData(int vcEntry,byte[] vcData)throws RemoteException {
- String TAG = "LTSMCommunicator:ReadMifareClassicData";
- Log.i(TAG, "Enter");
- statusCode = 0;
- byte[] rData = new byte[0];
- byte[] recvData = new byte[]{};
-
- boolean available = Utils.checkRegistryAvail(context);
- if(!available){
- available = Utils.checkRegBackupAvail();
- if(available){
- Utils.importReg();
- }else{
- Log.i(TAG, "no backup available");
- return Utils.createStatusCode(Data.SW_REGISTRY_IS_EMPTY);
- }
- }
-
- String pkg = Utils.getCallingAppPkg(context);
- Registry = loadRegistry();
- int i,stat;
- if(Registry.vcCount == 0){
- Log.i(TAG, "No VC is Present");
- return Utils.createStatusCode(Data.SW_REGISTRY_IS_EMPTY);
- }
- for( i = 0;i<Registry.vcCount;i++){
- if((Registry.vcEntry.get(i).intValue() == vcEntry)&&(Registry.shaWalletName.get(i).toString().equals(Utils.createSha(pkg)))){
- break;
- }
- }
- if(i == Registry.vcCount){
- Log.i(TAG, "Not a Valid VC Entry");
- return Utils.createStatusCode(Data.SW_INVALID_VC_ENTRY);
- }
- try {
- openConnection();
- } catch (RemoteException e) {
- closeConnection();
- e.printStackTrace();
- }
-
- byte[] cApdu = Utils.makeCAPDU(0x00, 0xA4, 0x04, 0x00, Utils.append(Data.serviceManagerAid, Utils.shortToByteArr((short)vcEntry)));
-
- recvData = exchangeWithSe(cApdu);
- // recvData = exchange(cApdu,channelId[channelCnt -1]);
- if(recvData == null)
- {
- Log.i(TAG, "SE transceive failed ");
- statusCode = Data.SW_SE_TRANSCEIVE_FAILED;
- stat = Data.FAILED;
- }
-
- Log.i(TAG, "Received Data : " + Utils.bytArrayToHex(recvData));
-
- Registry = loadRegistry();
- cApdu = Utils.makeCAPDU(0x80, 0xB0, 0x00, 0x00, vcData);
- recvData = exchangeWithSe(cApdu);
- rData = processReadMifareDataResponse(recvData);
-
- Log.i(TAG, "Exit");
- try {
- closeConnection();
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- Log.i(TAG, "recvData : " + Utils.bytArrayToHex(rData));
- Utils.exportReg();
- return rData;
- }
-
- /*******************************************************
- *
- * getVcList used to retrieve the list of couples VC entry
- * in used and associated SP Application
- *
- *@param none
- *
- *@return byte array containing List of VC entry in use
- *and associated SP Applications and status word.
- *
- ********************************************************/
-
- @Override
- public byte[] getVcList() throws RemoteException {
- String TAG = "LTSMCommunicator:getVcList";
- Log.i(TAG, "Enter");
- byte[] tempData = new byte[]{};
- int stat = Data.FAILED;
- statusCode = 0;
- byte[] rData = new byte[0];
-
- boolean available = Utils.checkRegistryAvail(context);
- if(!available){
- available = Utils.checkRegBackupAvail();
- if(available){
- Utils.importReg();
- }else{
- Log.i(TAG, "no backup available");
- return Utils.createStatusCode(Data.SW_REGISTRY_IS_EMPTY);
- }
- }
- //If Registry is already available in SharedPreference Check for Uninstalled Wallet Apps
- stat = checkUninstalledApps();
- if(stat == Data.SUCCESS){
- Log.i(TAG, "Uninstalled App Found");
- }
- cleanUp();
- stat = ltsmStart();
- if(stat == Data.FAILED){
- Log.i(TAG, "LTSMStart Failed");
- if(statusCode != 0){
- return Utils.createStatusCode(Data.SW_PROCESSING_ERROR);
- }
- }
- rData = retrieveStatus();
- if (Utils.getSW(rData) == (short)(0x6A88)) {
- if (rData.length == 2) {
- rData = Utils.createStatusCode(Data.SW_PROCESSING_ERROR);
- }
- else{
- rData = Utils.append(Utils.getRDATA(rData), Utils.createStatusCode(Data.SW_NO_ERROR));
- }
- }else{
- rData = Utils.append(rData, Utils.createStatusCode(Data.SW_NO_ERROR));
- }
- Log.i(TAG, "retData : " + Utils.bytArrayToHex(rData));
- closeLogicalChannel();
- Utils.exportReg();
- return rData;
- }
-
- /*******************************************************
- *
- *Get the virtual card status from SE
- *
- ********************************************************/
- private byte[] retrieveStatus(){
- String TAG = "LTSMCommunicator:getStatusApdu";
- Log.i(TAG, "Enter");
-
- byte[] capdu = Utils.makeCAPDU(0x80, 0xF2, 0x40, 0x00, null);
- byte[] rapdu = exchange(capdu, channelId[channelCnt -1]);
- byte[] status = new byte[0];
- int initLen = status.length;
- loop: for(;;)
- {
- Log.i(TAG, "rapdu : " + Utils.bytArrayToHex(rapdu));
- switch(Utils.getSW(rapdu))
- {
- case (short)(0x6310):
- status = Utils.append(status, Utils.getRDATA(rapdu));
- break;
-
- case (short)(0x9000):
- status = Utils.append(status, Utils.getRDATA(rapdu));
- break loop;
-
- case (short)(0x6A88):
- status = Utils.append(status, rapdu);
- break loop;
-
- default: // Unexpected error.
- // FALL THROUGH
- break loop;
- }
- capdu = Utils.makeCAPDU(0x80, 0xF2, 0x40, 0x01, null); // Next occurrence.
- rapdu = exchange(capdu, channelId[channelCnt -1]);
- }
- Log.i(TAG, "status : " + Utils.bytArrayToHex(status));
- return status;
- }
-
- /*******************************************************
- *
- *Get the virtual card status from SE and update the registry
- *
- ********************************************************/
-
- private int getStatus(){
-
- String TAG = "LTSMCommunicator:getStatus";
- Log.i(TAG, "Enter");
- byte[] retData = new byte[]{};
- byte[] tempData = new byte[]{};
- byte[] statusReturned = new byte[]{};
- int stat = Data.FAILED;
- int i = 0;
- stat = ltsmStart();
- if(stat == Data.FAILED){
- Log.i(TAG, "LTSMStart Failed");
- if(statusCode != 0){
- return Data.FAILED;
- }
- }
- statusReturned = retrieveStatus();
-
- if (Utils.getSW(statusReturned) == (short)(0x6A88)) {
- Log.i(TAG, " statusReturned.length " + statusReturned.length);
- if (statusReturned.length == 2) {
- Log.i(TAG, " no vc present ");
- Registry = loadRegistry();
- while(Registry.vcCount!=0){
- removeRegistryEntry(Registry.vcCount-1,Registry);
- Registry = loadRegistry();
- }
- closeLogicalChannel();
- return Data.SUCCESS;
- }else {
- statusReturned = Utils.getRDATA(statusReturned);
- }
-
- }
- Log.i(TAG, "Final rapdu : " + Utils.bytArrayToHex(statusReturned));
- byte[] resp = processGetStatus(statusReturned);
- if(Utils.getSW(resp) != Data.SW_NO_ERROR){
- Log.i(TAG, "processGetStatus Failed ");
-
- stat = Data.FAILED;
- }
- else {
- stat = Data.SUCCESS;
- }
- closeLogicalChannel();
- return stat;
- }
- private void removeRegistryEntry(int pos, ltsmRegistry Registry){
- int tmpVc = Registry.vcEntry.get(pos);
- String TAG = "LTSMCommunicator:removeRegistryEntry";
- Registry.shaWalletName.remove(pos);
- Registry.walletName.remove(pos);
- Registry.vcCreateStatus.remove(pos);
- Registry.vcActivatedStatus.remove(pos);
- Registry.vcEntry.remove(pos);
- Registry.vcType.remove(pos);
- Registry.vcUid.remove(pos);
- Registry.vcCount = Registry.vcCount - 1;
- Registry.deleteVcEntries.add(tmpVc);
- Log.i(TAG, " DeleteVCEntry " + tmpVc);
- saveRegistry(Registry);
- }
-
- /*******************************************************
- *
- * Initiate the LTSM. Opens the Logical Channel and Selects the LTSM
- *
- ********************************************************/
-
- public static int ltsmStart(){
- String TAG = "LTSMCommunicator:LTSMStart";
- Log.i(TAG, "Enter");
- int stat = Data.FAILED;
- stat = ltsmOpenChannel();
- if(stat == Data.FAILED){
- Log.i(TAG, "LTSM Open Channel Failed");
- return Data.FAILED;
- }
- stat = ltsmSelect();
- if(stat == Data.FAILED){
- Log.i(TAG, "LTSM select Failed");
- closeLogicalChannel();
- return Data.FAILED;
- }
- stat = Data.SUCCESS;
- Log.i(TAG, "Exit");
- return stat;
- }
-
- /*******************************************************
- *
- * Opens Logical Channel
- *
- ********************************************************/
-
- private static int ltsmOpenChannel() {
- String TAG = "LTSMCommunicator:openLogicalChannel";
- int stat = Data.FAILED;
- Log.i(TAG, "Enter");
- statusCode = 0;
- byte[] recvData = new byte[1024];
-
- try {
- openConnection();
- } catch (RemoteException e) {
- closeLogicalChannel();
- e.printStackTrace();
- }
- try {
- recvData = exchangeApdu(Data.openchannel, false);
- } catch (RemoteException e) {
- closeLogicalChannel();
- e.printStackTrace();
- }
- if(recvData == null)
- {
- Log.i(TAG, "SE transceive failed ");
- statusCode = Data.SW_SE_TRANSCEIVE_FAILED;
- return stat;
- }
- else if(Utils.getSW(recvData)!=Data.SW_NO_ERROR){
- statusCode = Utils.getSW(recvData);
- Log.i(TAG, "Invalid Response");
- return stat;
- }
- else{
- Log.i(TAG, "openLogicalChannel SUCCESS");
- channelId[channelCnt] = recvData[recvData.length - 3];
- isopened[channelCnt] = 1;
-
- Utils.saveArray(channelId, "channelId", context);
- Utils.saveArray(isopened, "isopened", context);
- channelCnt = channelCnt + 1;
- Utils.saveInt(channelCnt,"channelCnt",context);
- stat = Data.SUCCESS;
- }
-
- Log.i(TAG, "Exit");
- return stat;
- }
-
- /*******************************************************
- *
- *Selects LTSM with currently opened Logical channel
- *
- ********************************************************/
-
- private static int ltsmSelect() {
- String TAG = "LTSMCommunicator:ltsmSelect";
- int stat = Data.FAILED;
- boolean available = false;
- Log.i(TAG, "Enter");
- statusCode = 0;
- byte[] cApdu = Utils.makeCAPDU(0x00, 0xA4, 0x04, 0x00, Data.AID_M4M_LTSM);
- byte[] recvData = new byte[1024];
-
- recvData = exchange(cApdu,channelId[channelCnt -1]);
- if(recvData == null)
- {
- Log.i(TAG, "SE transceive failed ");
- statusCode = Data.SW_SE_TRANSCEIVE_FAILED;
- stat = Data.FAILED;
- }
- Log.i(TAG, "Received Data : " + Utils.bytArrayToHex(recvData));
-
- if (Utils.getSW(recvData) == Data.SW_NO_ERROR)
- {
- Log.i(TAG, "ltsmSelect SUCCESS ");
- byte[] vcCounts = Utils.getVcCount(recvData);
-
- InitialVCEntry = vcCounts[0] << 8 | vcCounts[1];
- int maxVcCount = vcCounts[2] << 8 | vcCounts[3];
-
- Log.i(TAG, "maxVcCount " + maxVcCount);
- Log.i(TAG, "InitialVCEntry " + InitialVCEntry);
- available = Utils.checkRegistryAvail(context);
- if(!available){
- Registry = new ltsmRegistry(maxVcCount);
- saveRegistry(Registry);
- }
- else{
- Registry = loadRegistry();
- Registry.maxVcCount = maxVcCount;
- }
-
- stat = Data.SUCCESS;
- }else{
- statusCode = Utils.getSW(recvData);
- stat = Data.FAILED;
- }
- Log.i(TAG, "Exit");
- return stat;
- }
-
- /*******************************************************
- *
- *Handles Exchange of Data during LTSM Process Command
- *
- ********************************************************/
-
- private static int exchangeLtsmProcessCommand(byte[] cdata)
- {
- String TAG = "LTSMCommunicator:exchangeLtsmProcessCommand";
- int stat = Data.SW_PROCESSING_ERROR;
- Log.i(TAG, "Enter");
- byte[] rData = new byte[0];
- Log.i(TAG, "(byte)cdata.length : "+(byte)cdata.length + "new byte[] {(byte)cdata.length} : " + Utils.bytArrayToHex(new byte[] {(byte)cdata.length}));
- byte[] cApdu = Utils.makeCAPDU(Data.CLA_M4M_LTSM, Data.INS_M4M_LTSM_PROCESS_COMMAND, 0x00, 0x00, cdata);
- Log.i(TAG, "cApdu : " + Utils.bytArrayToHex(cApdu));
- byte[] rapdu = exchange(cApdu,channelId[channelCnt -1]);
- switch(Utils.getSW(rapdu))
- {
- default:
- {
- statusCode = Utils.getSW(rapdu);
- stat = Data.SW_PROCESSING_ERROR;
- break;
- }
-
- case Data.SW_NO_ERROR:
- cApdu = Utils.getRDATA(rapdu);
- Log.i(TAG, "SW_NO_ERROR ");
- if(currentProcess.equals("CreateVirtualCard")){
- currentProcess = "";
- processCreateVcResponse(rapdu);
- }
- else if(currentProcess.equals("deleteVirtualCard")){
- currentProcess = "";
- processDeleteVcResponse();
- }
- else if(currentProcess.equals("addAndUpdateMdac")){
- currentProcess = "";
- rData = cApdu;
- }
- stat = Data.SW_NO_ERROR;
- statusCode = 0;
- break;
- case Data.SW_6310_COMMAND_AVAILABLE:
- process_se_response: for(;;){
- if (rapdu.length == 2)
- return Data.SW_NO_ERROR;
- cApdu = Utils.getRDATA(rapdu);
- Log.i(TAG, "SW_6310_COMMAND_AVAILABLE: Send Data back to SE ");
- // toLTSM = false;
- rapdu = exchangeWithSe(cApdu);
- if (rapdu.length < 256)
- {
- cApdu = Utils.makeCAPDU(Data.CLA_M4M_LTSM, Data.INS_M4M_LTSM_PROCESS_SE_RESPONSE, 0x00, 0x80, rapdu);
- // }
- rapdu = exchange(cApdu,channelId[channelCnt -1]);
-
- switch(Utils.getSW(rapdu))
- {
- default:
- {
- statusCode = Utils.getSW(rapdu);
- stat = Data.SW_PROCESSING_ERROR;
- break process_se_response;
- }
-
- case Data.SW_NO_ERROR:
- Log.i(TAG, "SW_NO_ERROR ");
- cApdu = Utils.getRDATA(rapdu);
- if(currentProcess.equals("CreateVirtualCard")){
- currentProcess = "";
- processCreateVcResponse(rapdu);
- }
- else if(currentProcess.equals("deleteVirtualCard")){
- currentProcess = "";
- processDeleteVcResponse();
- }
- else if(currentProcess.equals("addAndUpdateMdac")){
- currentProcess = "";
- rData = cApdu;
- }
- stat = Data.SW_NO_ERROR;
- statusCode = 0;
- break process_se_response;
-
- case Data.SW_6310_COMMAND_AVAILABLE:
- Log.i(TAG, "SW_6310_COMMAND_AVAILABLE: Send Data back to SE Again");
- }
- }
- else
- {
- byte[] rapdu1 = Utils.extract(rapdu, 0, 255);
- byte[] rapdu2 = Utils.extract(rapdu, 255, rapdu.length - 255);
-
- // First part
- cApdu = Utils.makeCAPDU(Data.CLA_M4M_LTSM, Data.INS_M4M_LTSM_PROCESS_SE_RESPONSE, 0x00, 0x00, rapdu1);
- rapdu = exchange(cApdu,channelId[channelCnt -1]);
-
- if (Utils.getSW(rapdu) != Data.SW_NO_ERROR)
- {
- System.err.println("FAILED: APDU exchange (PROCESS SE RESPONSE) (1 of 2) failed!");
- System.err.println(String.format("LTSM-SW: %04X", Utils.getSW(rapdu)));
- System.exit(1);
- }
-
- // Second part
- cApdu = Utils.makeCAPDU(Data.CLA_M4M_LTSM, Data.INS_M4M_LTSM_PROCESS_SE_RESPONSE, 0x00, 0x80, rapdu2);
- rapdu = exchange(cApdu,channelId[channelCnt -1]);
-
- switch(Utils.getSW(rapdu))
- {
- default:
- {
- statusCode = Utils.getSW(rapdu);
- stat = Data.SW_PROCESSING_ERROR;
- break process_se_response;
- }
-
- case Data.SW_NO_ERROR:
- cApdu = Utils.getRDATA(rapdu);
- if(currentProcess.equals("CreateVirtualCard")){
- currentProcess = "";
- processCreateVcResponse(rapdu);
- }
- else if(currentProcess.equals("deleteVirtualCard")){
- currentProcess = "";
- processDeleteVcResponse();
- }
- else if(currentProcess.equals("addAndUpdateMdac")){
- currentProcess = "";
- rData = cApdu;
- }
- stat = Data.SW_NO_ERROR;
- statusCode = 0;
- break process_se_response;
-
- case Data.SW_6310_COMMAND_AVAILABLE:
- // FALL THROUGH
- }
- }
- }
- }
-
- Log.i(TAG, "Exit");
- return stat;
- }
-
- /*******************************************************
- *
- *Exchange APDU With Secure Element
- *
- ********************************************************/
-
- private static byte[] exchangeWithSe(byte[] cdata)
- {
- String TAG = "LTSMCommunicator:exchangeWithSe";
- Log.i(TAG, "Enter");
- byte[] recvData = new byte[1024];
- boolean channel_open_cmd = false;
- if (cdata[1] == 0x70) // MANAGE CHANNEL ?
- {
- if (cdata[2] == 0x00) // [open]
- {
- cdata[4] = (byte) 0x01;
- channel_open_cmd = true;
- // SEChannel = 1;
- }
- else{
-
- }
- }
- recvData = exchange(cdata,(cdata[0] & 0x03));
- if(channel_open_cmd == true){
- }
- return recvData;
- }
-
- /*******************************************************
- *
- *Common Exchange method for Exchange with SE and Process LTSM Command
- *
- ********************************************************/
-
- private static byte[] exchange(byte[] cApdu,int chnl_id) {
- String TAG = "LTSMCommunicator:exchange";
- Log.i(TAG, "Enter");
- byte[] rData = new byte[0];
-
- // byte[] xchangeData = new byte[cApdu.length];
- try {
-
- cApdu[0] = Utils.adjustCLA(cApdu[0], (byte)chnl_id);
-
- Log.i(TAG, "Sending Data : " + Utils.bytArrayToHex(cApdu));
- rData = exchangeApdu(cApdu, false);
- if(rData.length == 0)
- {
- Log.i(TAG, "SE transceive failed ");
- rData = Utils.createStatusCode(Data.SW_NO_DATA_RECEIVED);
- }
- Log.i(TAG, " rData : " + Utils.bytArrayToHex(rData));
- } catch (RemoteException e) {
- closeLogicalChannel();
- e.printStackTrace();
- }
- return rData;
- }
-
- /*******************************************************
- *
- *Selects CRS during Activate VC
- *
- ********************************************************/
-
- private static int crsSelect() {
- String TAG = "LTSMCommunicator:crsSelect";
- byte[] rData = new byte[0];
- Log.i(TAG, "Enter");
- rData = exchangeWithSe(Data.selectCRS);
- //recvData = exchange(Data.selectCRS,channelId[channelCnt -1]);
- if(rData == null)
- {
- Log.i(TAG, "SE transceive failed ");
- rData = Utils.createStatusCode(Data.SW_NO_DATA_RECEIVED);
- }
- Log.i(TAG, "rData : " + Utils.bytArrayToHex(rData));
- if (Utils.getSW(rData) == (short)0x6300)
- {
- System.out.println("WARNING: The M4M LTSM Application is in DEBUG mode.");
- }
- else if (Utils.getSW(rData) == Data.SW_NO_ERROR)
- {
- Log.i(TAG, "ltsmSelectCRS SUCCESS ");
- return Data.SUCCESS;
- }
- else{
- return Data.FAILED;
- }
- Log.i(TAG, "Exit");
- return Data.FAILED;
- }
-
- /*******************************************************
- *
- *Closes currently opened Logical Channels
- *
- ********************************************************/
-
- public static void closeLogicalChannel() {
- String TAG = "LTSMCommunicator:closeLogicalChannel";
- Log.i(TAG, "Enter");
- byte[] rData = new byte[0];
- channelCnt = Utils.loadInt("channelCnt",context);
- channelId = Utils.loadArray("channelId",context);
- isopened = Utils.loadArray("isopened",context);
-
- Log.i(TAG, "channelCnt : " + channelCnt);
-
- byte[] send = new byte[5];
- int xx = 0;
-
- for(int cnt =0; (cnt < channelCnt); cnt++){
- if(isopened[cnt] == 1){
- xx = 0;
- Log.i(TAG, "Enter : isopened[cnt] == true");
- send[xx++] = (byte) channelId[cnt];
- send[xx++] = (byte) 0x70;
- send[xx++] = (byte) 0x80;
- send[xx++] = (byte) channelId[cnt];
- send[xx++] = (byte) 0x00;
-
- try {
- rData = exchangeApdu(send, true);
- } catch (RemoteException e) {
- e.printStackTrace();
- }
-
- if(rData == null){
- Log.i(TAG, "exchangeApdu FAILED");
- rData = Utils.createStatusCode(Data.SW_NO_DATA_RECEIVED);
- }
- else if(rData[rData.length - 2] == (byte) 0x90 &&
- rData[rData.length - 1] == (byte) 0x00){
- Log.i(TAG, "Close Channe id : " + channelId[cnt] + "is SUCCESS");
- channelCnt = channelCnt -1;
- }
- else{
- Log.i(TAG, "Close Channe id : " + channelId[cnt] + "is Failed");
- }
- }
- }
-
- Utils.saveInt(channelCnt,"channelCnt",context);
-
- try {
- closeConnection();
- } catch (RemoteException e) {
- e.printStackTrace();
- }
-
- Log.i(TAG, "Exit");
- }
-
- /*******************************************************
- *
- *Updates the VC Entry for current CreateVC
- *
- ********************************************************/
-
- private int managecurrentVcEntry(ltsmRegistry registry) {
- String TAG = "LTSMCommunicator:managecurrentVcEntry";
- Log.i(TAG, "Enter");
- Log.i(TAG, "Registry.vcCount : " + Registry.vcCount + "Registry.maxVcCount : " + Registry.maxVcCount);
- if(Registry.vcCount == 0){
-
- Registry.deleteVcEntries.clear();
- currentVcEntry = InitialVCEntry;
-
- }else if(Registry.vcCount < Registry.maxVcCount){
- Log.i(TAG, "vcCount "+Registry.vcCount);
- if(Registry.deleteVcEntries.size() != 0){
- currentVcEntry = Registry.deleteVcEntries.get(0);
- Registry.deleteVcEntries.remove(0);
- saveRegistry(Registry);
- }else{
- currentVcEntry = findVcEntryMax(Registry);//Check for max VC Entry Value
- currentVcEntry++;
- }
- }
- else{
- return Data.FAILED;
- }
- return Data.SUCCESS;
- }
-
- /*******************************************************
- *
- *Finds the maximum value in VC Entry List
- *
- ********************************************************/
-
- private int findVcEntryMax(ltsmRegistry registry) {
- int Max = 0;
- for(int i = 0;i<Registry.vcCount;i++){
- if(Registry.vcEntry.get(i) > Max){
- Max = Registry.vcEntry.get(i);
- }
- }
- return Max;
- }
-
- /*******************************************************
- *
- *Verifies Registry, Deletes VC and Updates the Registry for VC's Which are not Created Properly
- *
- ********************************************************/
-
- private void cleanUp(){
- String TAG = "LTSMCommunicator:cleanUp";
- Log.i(TAG, "Enter");
- boolean available = Utils.checkRegistryAvail(context);
- if(available){
- Registry = loadRegistry();
- int VC_Conut_temp;
- for(int i = 0;i<Registry.vcCount;i++){
- VC_Conut_temp = Registry.vcCount;
- if((Registry.vcCreateStatus.get(i)==false)){
- try{
- deleteTempVc(Registry.vcEntry.get(i).intValue(),Registry.shaWalletName.get(i));
- }catch(Exception e){
- closeLogicalChannel();
- e.printStackTrace();
- }
- Registry = loadRegistry();
- int j;
- if(VC_Conut_temp == Registry.vcCount){
- for(j = 0;j<Registry.deleteVcEntries.size();j++){
- if(Registry.vcEntry.get(i) == Registry.deleteVcEntries.get(j)){
- break;
- }
- }
- if(j == Registry.deleteVcEntries.size()){
- Registry.deleteVcEntries.add(Registry.vcEntry.get(i));
- }
-
- Registry.shaWalletName.remove(i);
- Registry.walletName.remove(i);
- Registry.vcCreateStatus.remove(i);
- Registry.vcActivatedStatus.remove(i);
- Registry.vcEntry.remove(i);
- Registry.vcType.remove(i);
- Registry.vcUid.remove(i);
- Registry.vcCount = Registry.vcCount - 1;
- saveRegistry(Registry);
- }
- }
- }
- }
- Utils.exportReg();
- Log.i(TAG, "Exit");
- }
-
- /*******************************************************
- *
- *Deletes VC's which are not Created Properly
- *
- ********************************************************/
-
- private int deleteTempVc(int vcEntry, String pkg) {
- String TAG = "LTSMCommunicator:deleteTempVc";
- Log.i(TAG, "Enter");
- int stat = Data.FAILED;
- DeleteVCEntry = vcEntry;
- Log.i(TAG, "DeleteVCEntry = vcEntry : " + DeleteVCEntry);
- currentProcess = "deleteVirtualCard";
- byte[] cData = vcDescriptionFile.deleteVc(pkg,(short)vcEntry);
-
- stat = ltsmStart();
- if(stat == Data.FAILED){
- Log.i(TAG, "DeleteVC Failed");
- return Data.FAILED;
- }
- stat = exchangeLtsmProcessCommand(cData);
-
- closeLogicalChannel();
- Log.i(TAG, "Exit");
- return stat;
- }
-
- /*******************************************************
- *
- *Handles Personalisation During CreateVC
- *
- *******************************************************/
-
- private int handlePersonalize(byte[] vcData, String pkg, short intValue) {
- String TAG = "LTSMCommunicator:handlePersonalize";
- int stat = Data.SW_PROCESSING_ERROR;
- Log.i(TAG, "Enter");
- currentProcess = "handlePersonalize";
- byte[] cData = vcDescriptionFile.CreatePersonalizeData(vcData,pkg,Utils.createSha(pkg),intValue,context);
- Log.i(TAG, "cData : " + Utils.bytArrayToHex(cData));
- stat = exchangeLtsmProcessCommand(cData);
- return stat;
- }
-
- /*******************************************************
- *
- *Opens Connection for Communication with SE
- *
- ********************************************************/
-
- public static boolean openConnection() throws RemoteException {
- String TAG = "LTSMCommunicator:openConnection";
- Log.i(TAG, "Enter");
- String errorCause = "";
-
- try {
-
- bundle = new Bundle();
- try {
- mLtsmService = LtsmService.createLtsmServiceInterface();
- errorCause = "Open Secure Element: Failed";
- if(mLtsmService != null){
- bundle = mLtsmService.open("com.nxp.ltsm.ltsmclient",mBinder);
- }
- Log.i(LOG_TAG, "openConnection() to ESe: Success Bundle : " + bundle);
- if (bundle == null) {
- Log.i(LOG_TAG,"openConnection() not successful");
- }
-
- } catch (Exception e) {
- Log.i(LOG_TAG, "openConnection() not successful");
-
- }
- } catch (Exception e) {
- e.printStackTrace();
- return false;
- }
- return true;
- }
-
- /*******************************************************
- *
- *Opens Connection for Communication with SE
- *
- ********************************************************/
-
- public static boolean closeConnection() throws RemoteException {
- // TODO Auto-generated method stub
- String TAG = "LTSMCommunicator:closeConnection";
- Log.i(TAG, "Enter");
- String errorCause = "";
-
- try {
-
- bundle = new Bundle();
-
- //mBinder = new Binder();
- try {
- if(mLtsmService != null){
- bundle = mLtsmService.close("com.nxp.ltsm.ltsmclient",mBinder);
- }
- Log.i(LOG_TAG, "closeConnection() to ESe: Success Bundle : " + bundle);
- if (bundle == null) {
- Log.i(LOG_TAG,"closeConnection() not successful");
- }
-
- } catch (Exception e) {
- Log.i(LOG_TAG, "closeConnection() not successful");
-
- }
- } catch (Exception e) {
- e.printStackTrace();
- return false;
- }
- return true;
- }
-
- /*******************************************************
- *
- *Transceives the APDU
- *
- ********************************************************/
-
- public static byte[] exchangeApdu(byte[] apdu, boolean addLeByte) throws RemoteException {
-
- byte[] apduToSend = null;
- Log.i(LOG_TAG,"exchange APDU ENTER");
- if (addLeByte) {
- // add a additional 0x00 to the end of the apdu
- apduToSend = new byte[apdu.length + 1];
- System.arraycopy(apdu, 0, apduToSend, 0, apdu.length);
- apduToSend[apduToSend.length - 1] = (byte) 0x00;
- } else {
- apduToSend = apdu;
- }
- try {
- if(mLtsmService != null){
- bundle = mLtsmService.transceive("com.nxp.ltsm.ltsmclient",apdu);
- }
- if (bundle == null) {
- Log.i(LOG_TAG,"exchange APDU failed");
- }
-
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- return bundle.getByteArray("out");
- }
-
- /*******************************************************
- *
- * Handles transceives for activate/deactivate VC
- *
- ********************************************************/
- public byte[] gating(byte[] aid, boolean mode){
- String TAG = "LTSMCommunicator:gating";
- Log.i(TAG, "Enter");
- byte[] tmpAid = new byte[]{};
- byte[] cData = new byte[]{};
- int tmpVcEntry = 99,i=0,stat = Data.FAILED;
- tmpAid = Utils.extract(aid, 2, aid.length-4);
-
- Registry = loadRegistry();
- if(Arrays.equals(tmpAid, Data.ACTV_LTSM_AID)){
- for( i = 0;i<Registry.vcCount;i++){
- if(Registry.vcEntry.get(i).intValue() == Utils.getSW(aid)){
- tmpVcEntry = Utils.getSW(aid);
- break;
- }
- }
- if (i == Registry.vcCount) {
- tmpVcEntry = 99;
- }
- }
- if (mode == true) {
- cData = Utils.makeCAPDU((byte) 0x80, (byte) 0xF0, 0x01, (byte) 0x01, aid);
- }else{
- cData = Utils.makeCAPDU((byte) 0x80, (byte) 0xF0, 0x01, (byte) 0x00, aid);
- }
-
- //Activate VC
- Registry = loadRegistry();
- byte[] rcvData = exchangeWithSe(cData);
- stat = processGatingResponse(tmpVcEntry,mode,rcvData);
- if (stat == Data.SW_OTHER_ACTIVEVC_EXIST) {
- return rcvData;
- }
- else if (stat == Data.SUCCESS) {
- return Utils.createStatusCode((short)Data.SUCCESS);
- }
- else{
- return Utils.createStatusCode(statusCode);
- }
-
- }
-
-
-
- /*******************************************************
- *
- *Processes Create VC Response
- *
- ********************************************************/
-
- private static void processCreateVcResponse(byte[] rapdu) {
- String TAG = "processCreateVcResponse";
- Log.i(TAG, "Enter");
- // String pkg = Utils.getCallingAppPkg(context);
- Log.i(TAG, "CurrentPackage : " + CurrentPackage);
- int i;
- for(i = 0;i<Registry.vcCount;i++){
- if((Registry.vcEntry.get(i) == currentVcEntry)&&(Utils.createSha(CurrentPackage).equals(Registry.shaWalletName.get(i))))
- {
- break;
- }
- }
-
- byte[] Value = Utils.getValue((byte)0x41,rapdu);
- Log.i(TAG, "After byte[] Value");
- Registry = loadRegistry();
- Log.i(TAG, "After Registry = loadRegistry()");
- Registry.vcUid.set(i, Utils.bytArrayToHex(Value));
- Registry.vcCreateStatus.set(i, true);
- saveRegistry(Registry);
- }
-
- /*******************************************************
- *
- *Processes Delete VC Response
- *
- ********************************************************/
-
- private static void processDeleteVcResponse() {
- String TAG = "processDeleteVcResponse";
- Log.i(TAG, "Enter");
- Registry = loadRegistry();
- for(int i = 0;i<Registry.vcCount;i++){
- Log.i(TAG, "Registry.vcEntry.get(i) "+Registry.vcEntry.get(i));
- if(Registry.vcEntry.get(i) == DeleteVCEntry){
- Registry.shaWalletName.remove(i);
- Registry.walletName.remove(i);
- Registry.vcCreateStatus.remove(i);
- Registry.vcActivatedStatus.remove(i);
- Registry.vcEntry.remove(i);
- Registry.vcType.remove(i);
- Registry.vcUid.remove(i);
- Registry.vcCount = Registry.vcCount - 1;
- Registry.deleteVcEntries.add(DeleteVCEntry);
- Log.i(TAG, "Inside if");
- saveRegistry(Registry);
- break;
- }
- }
- statusCode = Data.SW_NO_ERROR;
- Log.i(TAG, "Exit");
- }
-
- /*******************************************************
- *
- * Processes activate/deactivate VC response
- *
- ********************************************************/
- public int processGatingResponse(int vcEntry, boolean mode, byte[] rcvData){
- String TAG = "LTSMCommunicator:processGatingResponse";
- Log.i(TAG, "Enter");
- statusCode = 0;
- int stat = Data.FAILED;
- Registry = loadRegistry();
- int pos = 0;
- Log.i(TAG, "vcEntry : " +vcEntry );
- for( pos = 0;pos<Registry.vcCount;pos++){
- if(Registry.vcEntry.get(pos).intValue() == vcEntry){
- break;
- }
- }
- //Successfull Activation or Deactivation
- if (Utils.getSW(rcvData) == Data.SW_NO_ERROR)
- {
- if(mode == true){
- Log.i(TAG, "ActivateVirtualCard SUCCESS");
- if(pos < Registry.vcCount){
- Registry.vcActivatedStatus.set(pos,true);
- }
- stat = Data.SUCCESS;
- }
- else{
- Log.i(TAG, "DeActivateVirtualCard SUCCESS");
- if(pos < Registry.vcCount){
- Registry.vcActivatedStatus.set(pos,false);
- }
- stat = Data.SUCCESS;
- }
- }
- //Already one VC is Activated from other Wallet App
- else if((Utils.getSW(rcvData) == Data.SW_OTHER_ACTIVEVC_EXIST))
- {
- stat = Data.SW_OTHER_ACTIVEVC_EXIST;
-
- }
- else{
- statusCode = Utils.getSW(rcvData);
- stat = Data.FAILED;
- }
- saveRegistry(Registry);
- return stat;
-
- }
-
- /*******************************************************
- *
- *Processes Read Mifare Classic Data Response
- *
- ********************************************************/
-
- private byte[] processReadMifareDataResponse(byte[] rapdu) {
- statusCode = 0;
- statusCode = Utils.getSW(rapdu);
- byte[] retdata = new byte[1024];
-
- if(Utils.getSW(rapdu) == Data.SW_NO_ERROR){
- byte[] cApdu = Utils.getRDATA(rapdu);
- retdata = Utils.append(cApdu, Utils.createStatusCode(statusCode));
- }else{
- retdata = Utils.createStatusCode(statusCode);
- }
- return retdata;
- }
-
- /*******************************************************
- *
- *Check Registry whether all the entries matches with VC Count
- *
- ********************************************************/
-
- private int check(ltsmRegistry registry) {
- String TAG = "LTSMCommunicator:check";
- Log.i(TAG, "Enter" +registry.shaWalletName.size()+
- " "+registry.vcActivatedStatus.size()+
- " "+registry.vcCreateStatus.size()+
- " "+registry.vcEntry.size()+
- " "+registry.vcType.size()+
- " "+registry.vcUid.size());
- if((registry.vcCount == registry.shaWalletName.size())&&
- (registry.vcCount == registry.vcActivatedStatus.size())&&
- (registry.vcCount == registry.vcCreateStatus.size())&&
- (registry.vcCount == registry.vcEntry.size())&&
- (registry.vcCount == registry.vcType.size())&&
- (registry.vcCount == registry.vcUid.size())){
- return Data.SUCCESS;
- }
- else{
- return Data.FAILED;
- }
- }
-
- /*******************************************************
- *
- *Loads LTSM Registry from SharedPreference
- *
- ********************************************************/
-
- public static ltsmRegistry loadRegistry() {
- String TAG = "LTSMCommunicator:loadRegistry";
- Log.i(TAG, "Enter");
- SharedPreferences prefs = context.getSharedPreferences("Reg", Context.MODE_PRIVATE);
- Gson gson = new Gson();
- String json = prefs.getString("ltsmRegistry", "");
- ltsmRegistry RegObj = gson.fromJson(json, ltsmRegistry.class);
- Log.i(TAG, "Exit");
- return RegObj;
- }
-
- /*******************************************************
- *
- *Saves LTSM Registry to SharedPreference
- *
- ********************************************************/
-
- public static void saveRegistry(ltsmRegistry Registry) {
- SharedPreferences.Editor prefsEditor=context.getSharedPreferences("Reg", Context.MODE_PRIVATE).edit();
- Gson gson = new Gson();
- String json = gson.toJson(Registry);
- prefsEditor.putString("ltsmRegistry", json);
- if(Registry.vcCount==10){
- prefsEditor.clear();
- }
- prefsEditor.commit();
- }
-
- /*******************************************************
- *
- *Check and Process Uninstalled Wallet Apps
- *
- ********************************************************/
-
- private int checkUninstalledApps(){
- String TAG = "LTSMCommunicator:checkUninstalledApps";
- Log.i(TAG, "Enter");
- List<PackageInfo> InstalledApps = Utils.getINstalledApps(context);
- List<String> UninstalledApps = new ArrayList<String>();
- Registry = loadRegistry();
- int i,j;
- /*
- * Checking Registry entry against Currently installed app entries
- * */
- for(i = 0; i < Registry.vcCount; i++){
- for(j = 0; j < InstalledApps.size(); j++){
- if(InstalledApps.get(j).packageName.equals(Registry.walletName.get(i).toString())){
- Log.i(TAG, "CONTAINS : " + Registry.walletName.get(i).toString());
- break;
- }
- }
- /*
- * If Current Registry entry is not found in Currently installed app entries
- * */
- if(j == InstalledApps.size()){
- UninstalledApps.add( Registry.walletName.get(i).toString());
- Log.i(TAG, "inside if(j == InstalledApps.size()){");
- }
- }
- /*
- * Delete VCs which are in Uninstalled List
- * */
- if(!UninstalledApps.isEmpty()){
- for(i = 0; i < UninstalledApps.size(); i++){
- for(j = 0; j < Registry.vcCount; j++){
- if(UninstalledApps.get(i).equals(Registry.walletName.get(j).toString())){
- deleteTempVc(Registry.vcEntry.get(j).intValue(),Registry.shaWalletName.get(j));
- }
- }
- }
- Log.i(TAG, "Exit");
- return Data.SUCCESS;
- }
- else{
- Log.i(TAG, "Exit");
- return Data.FAILED;
- }
- }
-
- /*******************************************************
- *
- *Parse 61 Tag data and Update the registry accordingly
- *
- ********************************************************/
- private byte[] processGetStatus(byte[] apdu){
- String TAG = "LTSMCommunicator:processGetStatus";
- Log.i(TAG, "Enter");
- int arrLen = apdu.length;
- byte[] currentApdu = apdu;
- byte[] vcEntryList = new byte[]{};
- int progressLen = 0, offset = 0, lenTag61 = 0, lenTag40 = 0, lenTag4F = 0, lenTag9F70 = 0, lenTag42 = 0, lenTag43 = 0,i =0;
-
- if (apdu[0]!=(byte)0x61) {
- Log.i(TAG, "Tag 0x61 Not Found");
- return Utils.createStatusCode(Data.SW_PROCESSING_ERROR);
- }
- boolean tag61Exist = true;
-
- Log.i(TAG, "currentApdu : " + Utils.bytArrayToHex(currentApdu));
- while (tag61Exist) {
-
- lenTag61 = Utils.lenOfTLV(currentApdu, 1);
- offset = Utils.skipLenTLV(currentApdu, 1)+1;
- currentApdu = Utils.extract(currentApdu, offset, currentApdu.length-offset);
- progressLen = progressLen + offset;
- Log.i(TAG, "currentApdu tag61Exist : " + Utils.bytArrayToHex(currentApdu));
- Log.i(TAG, "progressLen : " + progressLen);
-
- /*Check and process tag 0x40*/
- if (currentApdu[0]!=(byte)0x40) {
- Log.i(TAG, "Tag 0x40 Not Found");
- return Utils.createStatusCode(Data.SW_PROCESSING_ERROR);
- }
- lenTag40 = 2;
- offset = 2;
- vcEntryList = Utils.append(vcEntryList, Utils.extract(currentApdu, offset, lenTag40));
- currentApdu = Utils.extract(currentApdu, offset+lenTag40, currentApdu.length-(offset+lenTag40));
- progressLen = progressLen + offset+lenTag40;
-
-
- /*Check and process tag 0x4F*/
- if (currentApdu[0]!=(byte)0x4F) {
- Log.i(TAG, "Tag 0x4F Not Found");
- return Utils.createStatusCode(Data.SW_PROCESSING_ERROR);
- }
- lenTag4F = Utils.lenOfTLV(currentApdu, 1);
- offset = Utils.skipLenTLV(currentApdu, 1)+1;
- currentApdu = Utils.extract(currentApdu, offset+lenTag4F, currentApdu.length-(offset+lenTag4F));
- progressLen = progressLen+offset+lenTag4F;
-
-
- /*Check and process tag 0x9F70*/
- if ((currentApdu[0]!=(byte)0x9F)&&(currentApdu[1]!=(byte)0x70)) {
- Log.i(TAG, "Tag 0x9F70 Not Found");
- return Utils.createStatusCode(Data.SW_PROCESSING_ERROR);
- }
- lenTag9F70 = 1;
- offset = 3;
- vcEntryList = Utils.append(vcEntryList, Utils.extract(currentApdu, offset, lenTag9F70));
- currentApdu = Utils.extract(currentApdu, offset+lenTag9F70, currentApdu.length-(offset+lenTag9F70));
- progressLen = progressLen+offset+lenTag9F70;
-
- if (currentApdu.length!=0) {
- Log.i(TAG, "currentApdu 0x42 : " + Utils.bytArrayToHex(currentApdu));
- /*Check and process tag 0x42*/
- if (currentApdu[0] == (byte)0x42) {
- lenTag42 = Utils.lenOfTLV(currentApdu, 1);
- offset = Utils.skipLenTLV(currentApdu, 1)+1;
- currentApdu = Utils.extract(currentApdu, offset+lenTag42, currentApdu.length-(offset+lenTag42));
- progressLen = progressLen+offset+lenTag42;
- }
-
- /*Check and process tag 0x43*/
- if (currentApdu[0] == (byte)0x43) {
- Log.i(TAG, "currentApdu 0x43 : " + Utils.bytArrayToHex(currentApdu));
- lenTag43 = Utils.lenOfTLV(currentApdu, 1);
- offset = Utils.skipLenTLV(currentApdu, 1)+1;
- currentApdu = Utils.extract(currentApdu, offset+lenTag43, currentApdu.length-(offset+lenTag43));
- progressLen = progressLen+offset+lenTag43;
-
- }
- }
- Log.i(TAG, "progressLen : " + progressLen + "arrLen : " + arrLen );
- /*break if no more tag 61 available*/
- if (progressLen == arrLen) {
- Log.i(TAG, "progressLen == arrLen");
- tag61Exist = false;
- }
- else if (currentApdu[0] != (byte)0x61) {
- return Utils.createStatusCode(Data.SW_PROCESSING_ERROR);
- }
- }
- Log.i(TAG, "vcEntryList : " + Utils.bytArrayToHex(vcEntryList));
- Registry = loadRegistry();
-
- for( i = 0;i<Registry.vcCount;i++){
- Log.i(TAG, "i : " + i + "Registry.vcCount :" + Registry.vcCount);
- if (findVcEntry(Registry.vcEntry.get(i),vcEntryList)==false) {
- int tempVc = Registry.vcEntry.get(i);
- Log.i(TAG, "i : " + i + " tempVc : " + tempVc);
- Registry = loadRegistry();
- Registry.shaWalletName.remove(i);
- Registry.walletName.remove(i);
- Registry.vcCreateStatus.remove(i);
- Registry.vcActivatedStatus.remove(i);
- Registry.vcEntry.remove(i);
- Registry.vcType.remove(i);
- Registry.vcUid.remove(i);
- Registry.vcCount = Registry.vcCount - 1;
- if (tempVc <= Registry.maxVcCount) {
- Registry.deleteVcEntries.add(tempVc);
- }
- //Log.i(TAG, "Removing registry : " + Registry.vcEntry.get(i));
- saveRegistry(Registry);
- Registry = loadRegistry();
- if (i==Registry.vcCount) {
- break;
- }
- }
- Log.i(TAG, "After");
- }
-
- return Utils.createStatusCode(Data.SW_NO_ERROR);
- }
-
- /*******************************************************
- *
- *Check for VC Entry in Registry
- *
- ********************************************************/
-
- boolean findVcEntry(int vcEntry, byte[] vcEntryList ){
- String TAG = "LTSMCommunicator:findVcEntry";
- Log.i(TAG, "Enter");
- Registry = loadRegistry();
- byte[] vcEntryArr =new byte[2];
- int i,j;
- for(i = 0; i < vcEntryList.length; i = i+3){
- vcEntryArr = Utils.extract(vcEntryList, i, 2);
- Log.i(TAG, "byteArrayToShort : " + Utils.byteArrayToShort(vcEntryArr) + "vcEntry : " + (short)vcEntry);
- if ((short)vcEntry == Utils.byteArrayToShort(vcEntryArr)) {
- if ((vcEntryList[i+2]&(byte)0x03)!= (byte)0x03) {
- loop: for( j = 0;j<Registry.vcCount;j++){
- if (Registry.vcEntry.get(j) == vcEntry) {
- Registry.vcCreateStatus.set(j, false);
- saveRegistry(Registry);
- closeLogicalChannel();
- cleanUp();
- ltsmOpenChannel();
- break loop;
- }
- }
- }
- Log.i(TAG, "Exit");
- return true;
- }
- }
- Log.i(TAG, "Exit");
- return false;
- }
-
- /*******************************************************
- *
- *Parse 61 Tag data and deactivate the AIDs present in
- *TAG A0 and TAG A2
- *
- ********************************************************/
- private int parseSetStatusResp(byte[] RcvData)
- {
- int tmpStat =0;
- int sReceivedLen = RcvData.length;
-
- if((sReceivedLen != 0) )
- {
- if(RcvData[0]== (byte)0x61)
- {
- /*Fetch size of length field of Tag 61 is 2 bytes*/
- int sLen61 = Utils.skipLenTLV(RcvData, 1);
-
- /*Get Length of Tag 61*/
- int sTag61Len = Utils.lenOfTLV(RcvData, 1);
-
- /*Check Tag61 length if Non-zero*/
- if(sTag61Len != 0)
- {
- if(RcvData[sLen61+1] == (byte)0x4F)
- {
- int sLenConfAID = RcvData[sLen61+2];
- int offA1 = 0;
- int currAidLen = 0;
- int tempLen = 0;
- int tempAidLen = 0;
- byte[] resp;
- // byte[] retStat=Data.SW_PROCESSING_ERROR;
-
- if(RcvData[sLen61+ sLenConfAID +3] == (byte)0xA0)
- {
- int sLenA0 = Utils.lenOfTLV(RcvData, (sLenConfAID+sLen61+4));
- int skipA0Len = Utils.skipLenTLV(RcvData, (sLenConfAID+sLen61+4));
- tempLen = sLenA0;
-
- int off4F = skipA0Len+sLenConfAID+sLen61+4;
-
-
-
- do
- {
- if(RcvData[currAidLen+off4F] == (byte)0x4F)
- {
- tempAidLen = RcvData[currAidLen+off4F+1];
-
- byte[] aid = Utils.findNextAID(RcvData, (currAidLen+off4F+1));
- /*Activate the requested VC entry*/
- resp = gating(aid,false);
-
-
-
- /*Do response validation
- tmpStat = processGatingResponse(resp,false,0);*/
-
- /*if(tmpStat == Data.SUCCESS){
- retStat = Data.NO_ERROR;
- }else{
- retStat = Data.Processing_Error;
- }*/
- /*To Reach 4F TAG*/
- currAidLen += tempAidLen+ 2;
-
- }
- else
- {
- /*Error case for 4F tag*/
- break;
- }
- }while(tempLen > currAidLen);
-
- /*Get offset of TAG A1 offA1*/
- offA1 = sLenConfAID+sLen61+4+skipA0Len+sLenA0;
- }
- else
- {
- offA1 = sLen61+ sLenConfAID +3;
- }
- int offA2 = 0;
-
- if(RcvData[offA1] == (byte)0xA1)
- {
- int lenTagA1 = Utils.lenOfTLV(RcvData, offA1+1);
-
- int skipLenTagA1 = Utils.skipLenTLV(RcvData, offA1+1);
-
- offA2 = offA1+ skipLenTagA1+lenTagA1+1;
- }
- else
- {
- /*since TAG presence is conditional*/
- offA2 = offA1;
- }
-
- if(RcvData[offA2] == (byte)0xA2)
- {
- int lenTagA2 = Utils.lenOfTLV(RcvData, offA2+1);
- int skipLenTagA2 = Utils.skipLenTLV(RcvData, offA2+1);
-
- int offTag48 = offA2+skipLenTagA2+1;
-
- tempLen = lenTagA2;
-
- do{
-
- if(RcvData[offTag48] == 0x48)
- {
- int offTag484F = offTag48+4;
-
- currAidLen = 0;
-
- tempAidLen = 0;
-
- do
- {
- if(RcvData[currAidLen+offTag484F] == 0x4F)
- {
- tempAidLen = RcvData[currAidLen+offTag484F+1];
-
- byte[] aid = Utils.findNextAID(RcvData, (currAidLen+offTag484F+1));
-
- /*Activate the requested VC entry*/
- resp = gating(aid,false);
-
- /*Do response validation
- tmpStat = processGatingResponse(resp,false,0);*/
-
- /*if(tmpStat == Data.SUCCESS){
- retStat = Data.NO_ERROR;
- }else{
- retStat = Data.Processing_Error;
- }*/
-
- /*To Reach 4F TAG*/
- currAidLen += tempAidLen+2;
- }
- else
- {
- /*End of Tag 4F*/
- break;
- }
- tempLen -=(tempAidLen+2);
-
- }while(tempLen>currAidLen);
-
- /*Skip the current 4F tags of particular 48 Tag*/
-
- }
- tempLen-=4;
- /*fetch next 48 tag*/
- offTag48 += currAidLen +4;
-
- }while(tempLen>0);
-
- }
- else
- {
- /*skip if Tag A2 is also not available*/
- }
- }
- else
- {
- /*If Tag A0 is optional*/
- }
- }
- }
- }
- else
- {
-
- }
- return tmpStat;
- }
-
-
-}/*NEW IMPLEMENTATION END*/
diff --git a/LTSMClient/src/com/nxp/ltsm/ltsmclient/ltsmRegistry.java b/LTSMClient/src/com/nxp/ltsm/ltsmclient/ltsmRegistry.java
deleted file mode 100644
index aef148c..0000000
--- a/LTSMClient/src/com/nxp/ltsm/ltsmclient/ltsmRegistry.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2014 NXP Semiconductors
- *
- * 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.nxp.ltsm.ltsmclient;
-
-import java.util.ArrayList;
-
-public class ltsmRegistry {
- public int maxVcCount;
- public int vcCount;
- ArrayList<Integer>vcEntry = new ArrayList<Integer>();
- ArrayList<String> shaWalletName = new ArrayList<String>();
- ArrayList<String> vcUid = new ArrayList<String>();
- ArrayList<String> walletName = new ArrayList<String>();
- ArrayList<Boolean> vcCreateStatus = new ArrayList<Boolean>();
- ArrayList<Boolean> vcActivatedStatus = new ArrayList<Boolean>();
- ArrayList<String> vcType = new ArrayList<String>();
- ArrayList<Integer> deleteVcEntries = new ArrayList<Integer>();
-
-
- public ltsmRegistry(int MaxVC) {
- maxVcCount = MaxVC;
- vcCount = 0;
- vcEntry.clear();
- shaWalletName.clear();
- walletName.clear();
- vcUid.clear();
- vcCreateStatus.clear();
- vcActivatedStatus.clear();
- vcType.clear();
- deleteVcEntries.clear();
- }
-
-
-}
diff --git a/LTSMClient/src/com/nxp/ltsm/ltsmclient/tools/Data.java b/LTSMClient/src/com/nxp/ltsm/ltsmclient/tools/Data.java
deleted file mode 100644
index 59e17bb..0000000
--- a/LTSMClient/src/com/nxp/ltsm/ltsmclient/tools/Data.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2014 NXP Semiconductors
- *
- * 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.nxp.ltsm.ltsmclient.tools;
-
-public class Data {
-
-
- /*Status values*/
- public static final int SUCCESS = 0;
- public static final int FAILED = 1;
-
- public static final byte CLA_M4M_LTSM = (byte)0x80;
- public static final byte INS_M4M_LTSM_PROCESS_COMMAND = (byte)0xA0;
- public static final byte INS_M4M_LTSM_PROCESS_SE_RESPONSE = (byte)0xA2;
- public static final short SW_6310_COMMAND_AVAILABLE = (short)0x6310;
-
- /**
- * Generic error codes (from ltsm client)
- * */
- public static final short SW_INVALID_VC_ENTRY = (short)0x69E0;
- public static final short SW_OPEN_LOGICAL_CHANNEL_FAILED = (short)0x69E1;
- public static final short SW_SELECT_LTSM_FAILED = (short)0x69E2;
- public static final short SW_REGISTRY_FULL = (short)0x69E3;
- public static final short SW_IMPROPER_REGISTRY = (short)0x69E4;
- public static final short SW_NO_SET_SP_SD = (short)0x69E5;
- public static final short SW_ALREADY_ACTIVATED = (short)0x69E6;
- public static final short SW_ALREADY_DEACTIVATED = (short)0x69E7;
- public static final short SW_CRS_SELECT_FAILED = (short)0x69E8;
- public static final short SW_SE_TRANSCEIVE_FAILED = (short)0x69E9;
- public static final short SW_REGISTRY_IS_EMPTY = (short)0x69EA;
- public static final short SW_NO_DATA_RECEIVED = (short)0x69EB;
-
- public static final short SW_OTHER_ACTIVEVC_EXIST = (short)0x6330;
- public static final short SW_PROCESSING_ERROR = (short)0x6A88;
-
- /**
- * createVc Response Error Codes (from ltsm application in SE)
- * */
- public static final short CREATEVC_PREPERSO_NOT_FOUND = (short)0x6F01;
- public static final short CREATEVC_SET_SP_SD_NOT_SENT = (short)0x6F02;
- public static final short CREATEVC_INVALID_SIGNATURE = (short)0x6F03;
- public static final short CREATEVC_SET_SP_SD_SENT = (short)0x6F04;
- public static final short CREATEVC_REGISTRY_ENTRY_CREATION_FAILED = (short)0x6F05;
-
- /**
- * addAndUpdate/deleteVc Response Error Codes (from ltsm application in SE)
- * */
- public static final short DELETEVC_INVALID_VC_ENTRY = (short)0x6F01; //Same for deleteVc
- public static final short DELETEVC_NO_LTSM_SD_PRESENT = (short)0x6F02;
-
- public static final byte[] openchannel = new byte[] {0x00, 0x70, 0x00, 0x00, 0x01};
- public static final byte[] SelectLTSM = new byte[] {0x00, (byte) 0xA4, 0x04, 0x00, 0x0D, (byte) 0xA0, 0x00, 0x00, 0x03, (byte) 0x96, 0x41, 0x4C, 0x41, 0x01, 0x43, 0x4F, 0x52, 0x01};
- public static final byte[] AID_M4M_LTSM = {(byte)0xA0, (byte)0x00, (byte)0x00, (byte)0x03, (byte)0x96, 0x4D, 0x46, 0x00, (byte)0x4C, 0x54, 0x53, 0x4D, 0x01};
- public static final byte[] selectCRS = new byte[] {(byte)0x00,(byte) 0xA4, 0x04, 0x00, 0x09,(byte) 0xA0, 0x00, 0x00, 0x01, 0x51, 0x43, 0x52, 0x53, 0x00, 0x00 };
- public static final byte[] serviceManagerAid= new byte[] {(byte)0xA0,(byte)0x00,(byte)0x00,(byte)0x03,(byte)0x96,(byte)0x4D,(byte)0x34,(byte)0x4D,(byte)0x24,(byte)0x00,(byte)0x81,(byte)0xDB,(byte)0x69,(byte)0x00};
-
- public static final byte[] ACTV_LTSM_AID = {(byte)0xA0, (byte)0x00, (byte)0x00, (byte)0x03, (byte)0x96,0x4D,0x34,0x4D, 0x14,0x00,(byte) 0x81,(byte) 0xDB, 0x69,0x00};
- public static final byte[] Set_Status_Activate_Cmd = new byte[] {(byte) 0x80,(byte) 0xF0, 0x01,(byte) 0x01};
- public static final byte[] Set_Status_DeActivate_Cmd = new byte[] {(byte) 0x80,(byte) 0xF0, 0x01,(byte) 0x00};
-
- public static final short SW_NO_ERROR = (short)0x9000;
- public static final short ACTV_VC_EXISTS = (short)0x6330;
- public static final short ACTV_OTHERVC_EXISTS = (short)0x6320;
-
- //public static final byte[] Processing_Error = new byte[] {(byte) 0x4E,(byte) 0x02,(byte) 0x00,(byte) 0x99};
- public static final byte[] NO_ERROR = new byte[] {(byte) 0x4E,(byte) 0x02,(byte) 0x90,(byte) 0x00};
-
- public static final byte[] ERROR_NO_VC_PRESENT = new byte[] {(byte) 0x4E,(byte) 0x02,(byte) 0x01,(byte) 0x99};
- public static final byte[] ERROR_ALREADY_ACTIVATED = new byte[] {(byte) 0x4E,(byte) 0x02,(byte) 0x02,(byte) 0x99};
- public static final byte[] ERROR_ALREADY_DEACTIVATED = new byte[] {(byte) 0x4E,(byte) 0x02,(byte) 0x03,(byte) 0x99};
- public static final byte[] ERROR_NO_VALID_INPUT = new byte[] {(byte) 0x4E,(byte) 0x02,(byte) 0x04,(byte) 0x99};
-
-
-
-}
diff --git a/LTSMClient/src/com/nxp/ltsm/ltsmclient/tools/Utils.java b/LTSMClient/src/com/nxp/ltsm/ltsmclient/tools/Utils.java
deleted file mode 100644
index f0ac219..0000000
--- a/LTSMClient/src/com/nxp/ltsm/ltsmclient/tools/Utils.java
+++ /dev/null
@@ -1,660 +0,0 @@
-/*
- * Copyright (C) 2014 NXP Semiconductors
- *
- * 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.nxp.ltsm.ltsmclient.tools;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
-import java.lang.reflect.Field;
-import java.security.MessageDigest;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-import java.util.regex.Pattern;
-
-import org.apache.commons.codec.Charsets;
-import org.apache.commons.codec.binary.Hex;
-
-import android.app.ActivityManager;
-import android.app.ActivityManager.RunningAppProcessInfo;
-import android.app.ActivityManager.RunningServiceInfo;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.Signature;
-import android.os.Build;
-import android.os.Environment;
-import android.util.Log;
-import android.view.InflateException;
-
-public class Utils {
- /**
- * Convert a byte array to an hexadecimal string
- *
- * @param data
- * the byte array to be converted
- * @return the output string
- */
- public static String arrayToHex(byte[] data) {
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < data.length; i++) {
- String bs = Integer.toHexString(data[i] & 0xFF).toUpperCase();
- if (bs.length() == 1) {
- sb.append(0);
- }
- sb.append(bs);
- sb.append(" ");
- }
- return sb.toString();
- }
-
- /**
- * Convert an hexadecimal string into a byte array. Each byte in ethe
- * hexadecimal string being separated by spaces or not (eg. s = "65 A0 12"
- * <=> "65A012").
- *
- * @param s
- * the string to be converted
- * @return the corresponding byte array
- * @throws IllegalArgumentException
- * if not a valid string representation of a byte array
- */
- public static byte[] hexToArray(String s) {
-
- // check the entry
- Pattern p = Pattern.compile("([a-fA-F0-9]{2}[ ]*)*");
- boolean valid = p.matcher(s).matches();
-
- if (!valid) {
- throw new IllegalArgumentException("not a valid string representation of a byte array :" + s);
- }
-
- String hex = s.replaceAll(" ", "");
- byte[] tab = new byte[hex.length() / 2];
- for (int i = 0; i < tab.length; i++) {
- tab[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16);
- }
- return tab;
- }
-
- /**
- * Convert a byte array into ASCII string representation.
- *
- * @param buf
- * The bytes to format.
- * @return ASCII string representation of the specified bytes.
- * @throws UnsupportedEncodingException
- */
- public static String toAsciiString(byte[] buf) throws UnsupportedEncodingException {
- String ascii = null;
- if (buf != null) {
- ascii = new String(buf, "US-ASCII");
- // Check the characters
- char[] charArray = ascii.toCharArray();
- for (int i = 0; i < charArray.length; i++) {
- // Show null character as blank space
- if (charArray[i] == (char) 0x00) {
- charArray[i] = ' ';
- }
- }
- ascii = new String(charArray);
- }
- return ascii;
- }
-
- /**
- * Convert the byte array to an int starting from the given offset.
- *
- * @param b
- * The byte array
- * @param offset
- * The array offset
- * @return The integer
- */
- public static int byteArrayToInt(byte[] b) {
- if (b.length == 1) {
- return b[0] & 0xFF;
- } else if (b.length == 2) {
- return ((b[0] & 0xFF) << 8) + (b[1] & 0xFF);
- } else if (b.length == 3) {
- return ((b[0] & 0xFF) << 16) + ((b[1] & 0xFF) << 8) + (b[2] & 0xFF);
- } else if (b.length == 4)
- return (b[0] << 24) + ((b[1] & 0xFF) << 16) + ((b[2] & 0xFF) << 8) + (b[3] & 0xFF);
- else
- throw new IndexOutOfBoundsException();
- }
-
- public static String getTimestampString(byte[] timestamp) {
- if (timestamp == null || timestamp.length < 6) {
- return "?";
- }
- Log.i("TimeStamp Parser", "Timestampbytes: " + Utils.arrayToHex(timestamp));
- String timestampSting = "";
- int day = timestamp[0] & 0xFF;
- int month = timestamp[1] & 0xFF;
- byte[] yearBytes = new byte[2];
- System.arraycopy(timestamp, 2, yearBytes, 0, 2);
- int year = Utils.byteArrayToInt(yearBytes);
- int hours = timestamp[4] & 0xFF;
- int mins = timestamp[5] & 0xFF;
-
- // Check for correct Values
- if (day < 1 || day > 31 || month < 1 || month > 12 || year < 1990 || hours < 0 || hours > 24 || mins < 0 || mins > 59) {
- return "?";
- } else {
- timestampSting = String.valueOf(day) + "." + String.valueOf(month) + "." + String.valueOf(year) + " " + String.valueOf(hours) + ":"
- + String.valueOf(mins);
- }
- SimpleDateFormat dateFormat = new SimpleDateFormat ("d.M.y H:m");
- try {
- Date timestampDate = dateFormat.parse(timestampSting);
- dateFormat = new SimpleDateFormat("dd.MM.yyyy HH:mm");
- return dateFormat.format(timestampDate);
- } catch (ParseException e) {
- return "?";
- }
- }
- public static int CompareArrays(short[] array1, int array1pos, short[] array2, int array2pos, int len) {
- int i, j;
- for (i = array1pos,j = array2pos; j < len; i++,j++) {
- if (array1[i] != array2[j]) {
- return Data.FAILED;
- }
- }
- if(((i - array1pos ) == len) && ((j - array2pos ) == len)){
- return Data.SUCCESS;
- }
- else{
- return Data.FAILED;
- }
- }
- public static int ShorttoByteArraycopy(short[] src, int srcpos, byte[] dest, int destpos, int len) {
- String TAG = "LTSMlib:ShorttoIntArraycopy";
-
- if( dest.length < len ){
- Log.i(TAG, "dest array length less than length to be copied ");
- return Data.FAILED;
- }
- int i, j;
- for (i = srcpos,j = destpos; j < len; i++,j++) {
- dest[j] = (byte) src[i];
- }
- if(j == len){
- return Data.SUCCESS;
- }
- else{
- return Data.FAILED;
- }
- }
- public static int BytetoShortArraycopy(byte[] src, int srcpos, short[] dest, int destpos, int len) {
- String TAG = "LTSMlib:ShorttoIntArraycopy";
-
- if( dest.length < len ){
- Log.i(TAG, "dest array length less than length to be copied ");
- return Data.FAILED;
- }
- int i, j;
- for (i = srcpos,j = destpos; j < len; i++,j++) {
- dest[j] = src[i];
- }
- if(j == len){
- return Data.SUCCESS;
- }
- else{
- return Data.FAILED;
- }
- }
-
- public static byte[] makeCAPDU(int cla, int ins, int p1, int p2, byte[] cdata)
- {
- byte[] l,t;
- if (cdata == null)
- {
- return new byte[] { (byte)cla, (byte)ins, (byte)p1, (byte)p2, 0 };
- }
- // else if (cdata.length > 128)
- // {
- // l = new byte[] { (byte)(0x81), (byte)cdata.length };
- // t = append(new byte[] { (byte)cla, (byte)ins, (byte)p1, (byte)p2}, l);
- // return append(t, cdata);
- // }
- else
- {
- return append(new byte[] { (byte)cla, (byte)ins, (byte)p1, (byte)p2, (byte)cdata.length}, cdata);
- }
- }
-
- public static byte[] append(byte[] a, byte[] b)
- {
- byte[] result = new byte[a.length + b.length];
- System.arraycopy(a, 0, result, 0, a.length);
- System.arraycopy(b, 0, result, a.length, b.length);
- return result;
- }
-
- public static byte[] extract(byte[] buffer, int offset, int length)
- {
- byte[] result = new byte[length];
- System.arraycopy(buffer, offset, result, 0, length);
- return result;
- }
-
- public static short getSW(byte[] rapdu)
- {
- byte sw1 = rapdu[rapdu.length - 2];
- byte sw2 = rapdu[rapdu.length - 1];
- return (short)((sw1 << 8) + (sw2 & 0xFF));
- }
-
- public static byte[] getRDATA(byte[] rapdu)
- {
- return extract(rapdu, 0, rapdu.length - 2);
- }
-
- public static byte adjustCLA(byte cla, byte lcnum)
- {
- return (byte)((cla & ~0x03) | (lcnum & 0x03));
- }
-
- public static void saveArray(int[] channel_id, String arrayName, Context mContext) {
- SharedPreferences.Editor edit= mContext.getSharedPreferences(arrayName, Context.MODE_PRIVATE).edit();
- edit.putInt("Count", channel_id.length);
- int count = 0;
- for (int i: channel_id){
- edit.putInt("IntValue_" + count++, i);
- }
- edit.commit();
- }
-
- public static int[] loadArray(String arrayName, Context mContext) {
- int[] ret;
- SharedPreferences prefs = mContext.getSharedPreferences(arrayName, Context.MODE_PRIVATE);
- int count = prefs.getInt("Count", 0);
- ret = new int[count];
- for (int i = 0; i < count; i++){
- ret[i] = prefs.getInt("IntValue_"+ i, i);
- }
- return ret;
- }
-
- public static void saveInt(int cnt, String name, Context mContext) {
- SharedPreferences.Editor edit= mContext.getSharedPreferences(name, Context.MODE_PRIVATE).edit();
- edit.putInt("chnl_cnt", cnt);
- edit.commit();
- }
-
-
- public static int loadInt(String name, Context mContext) {
- SharedPreferences prefs = mContext.getSharedPreferences(name, Context.MODE_PRIVATE);
- int savedCnt = prefs.getInt("chnl_cnt", 0);
- return savedCnt;
- }
-
- public static String bytArrayToHex(byte[] a) {
- StringBuilder sb = new StringBuilder();
- for(byte b: a)
- sb.append(String.format("%02X", b&0xff));
- return sb.toString();
- }
-
-
- public static boolean checkRegistryAvail(Context context) {
- String TAG = "Utils:checkRegistryAvail";
- Log.i(TAG, "Enter");
- File f = new File(
- "/data/data/com.nxp.ltsm.ltsmclient/shared_prefs/Reg.xml");
- if (f.exists()){
- Log.d(TAG, "LTSM Registry exist");
- return true;
- }
- else{
- Log.d(TAG, "not exists");
- return false;
- }
- }
-
- public static boolean checkRegBackupAvail(){
- String TAG = "Utils:checkRegistryAvail";
- Log.i(TAG, "Enter");
- File f = new File(
- Environment.getExternalStorageDirectory().getPath()+"/ltsmRegBackup/Reg.xml");
- if (f.exists()){
- Log.d(TAG, "LTSM Registry backup exist");
- return true;
- }
- else{
- Log.d(TAG, "LTSM Registry backup doesnt exist");
- return false;
- }
- }
-
-
- public static String shaSignature(String pkg, Context context){
- String TAG = "Utils:createSha";
- String hashString = "";
- PackageManager pm = context.getPackageManager();
- try {
- PackageInfo info = pm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES);
- Signature[] sigs = info.signatures;
- for (int i = 0; i < sigs.length; i++) {
- hashString = hashString+sigs[i].toCharsString();
- }
- Log.i(TAG,"pkg " + pkg);
- Log.i(TAG,"hashString " + hashString);
- if (hashString == "") {
- return hashString;
- }
- return makeShaSignature(hashString);
- }catch(Exception e){
- e.printStackTrace();
- }
- return null;
- }
-
- public static String makeShaSignature(String hashString){
- String TAG = "Utils:retSha";
- StringBuffer sb = new StringBuffer();
-
- try {
- MessageDigest md = MessageDigest.getInstance("SHA-1");
- md.update(hashString.getBytes());
-
- byte byteData[] = md.digest();
-
- for (int i = 0; i < byteData.length; i++) {
- sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
- }
- Log.i(TAG,"sb.toString() " + sb.toString());
- return new String(Hex.encodeHex(byteData));
- // return sb.toString();
- //return byteData.toString();
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
-
- }
-
- public static String createSha(String pkg){
- String TAG = "Utils:createSha";
- StringBuffer sb = new StringBuffer();
- try {
- MessageDigest md = MessageDigest.getInstance("SHA-1");
- md.update(pkg.getBytes());
-
- byte byteData[] = md.digest();
-
- for (int i = 0; i < byteData.length; i++) {
- sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
- }
- return new String(Hex.encodeHex(byteData));
- // return sb.toString();
- //return byteData.toString();
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
-
- }
-
- public static String getCallingAppPkg(Context context) {
- String TAG = "getCallingAppPkg";
- String packageName = null;
- if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT_WATCH) {
-
- packageName = getForeGroundL(context);
- }
- else
- {
- packageName = getForeGroundKK(context);
- }
- Log.i(TAG,"packageName : " + packageName);
- return packageName;
- }
-
- static String getForeGroundKK(Context context)
- {
- ActivityManager am = (ActivityManager) context.getSystemService(context.ACTIVITY_SERVICE);
- // get the info from the currently running task
- List< ActivityManager.RunningTaskInfo > taskInfo = am.getRunningTasks(1);
-
- Log.d("topActivity", "CURRENT Activity ::"
- + taskInfo.get(0).topActivity.getClassName());
- String s = taskInfo.get(0).topActivity.getClassName();
-
- ComponentName componentInfo = taskInfo.get(0).topActivity;
- componentInfo.getPackageName();
- return componentInfo.getPackageName();
- }
-
- static String getForeGroundL(Context context)
- {
- final int PROCESS_STATE_TOP = 2;
- RunningAppProcessInfo currentInfo = null;
- Field field = null;
- try {
- field = RunningAppProcessInfo.class.getDeclaredField("processState");
- } catch (Exception e) {e.printStackTrace(); }
- ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
- List<RunningAppProcessInfo> appList = am.getRunningAppProcesses();
- for (RunningAppProcessInfo app : appList) {
- if (app.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND &&
- app.importanceReasonCode == 0 ) {
- Integer state = null;
- try {
- state = field.getInt( app );
- } catch (Exception e) {e.printStackTrace(); }
- if (state != null && state == PROCESS_STATE_TOP) {
- currentInfo = app;
- break;
- }
- }
- }
- return currentInfo.processName;
- }
-
- public static List getINstalledApps(Context context){
- List<PackageInfo> apps = context.getPackageManager().getInstalledPackages(0);
- return apps;
- }
-
- public static byte[] shortToByteArr(short vC_Entry) {
- String TAG = "shortToByteArr";
- Log.i(TAG,"vC_Entry)" + vC_Entry);
- byte[] vcEntryBytes = new byte[2];
- vcEntryBytes[1] = (byte)(vC_Entry & 0xff);
- vcEntryBytes[0] = (byte)((vC_Entry >> 8) & 0xff);
- return vcEntryBytes;
-
- }
-
- public static byte[] getValue(byte Tag, byte[] rapdu) {
- String TAG = "Utils:getValue";
- byte[] retData = null;
- for(int i = 0 ; i< rapdu.length-1 ; i++ ){
- if(Tag == rapdu[i]){
- retData = new byte[rapdu[i+1]];
- System.arraycopy(rapdu, i+2, retData, 0, rapdu[i+1]);
- Log.i(TAG,"retData" + bytArrayToHex(retData));
- break;
- }
- }
- return retData;
- }
-
- public static byte[] getVcCount(byte[] recvData) {
- byte[] temp = getValue((byte)0x6F,recvData);
- byte[] temp1 = new byte[temp.length - (temp[1]+2)];
- System.arraycopy(temp, (temp[1]+2), temp1, 0, temp1.length);
- temp = getValue((byte)0xA5,temp1);
- temp = getValue((byte)0x10,temp);
- return temp;
- }
-
- public static boolean chekPersonalize(byte[] vCData) {
- String TAG = "Utils:getValue";
- Log.i(TAG,"Enter");
- byte[] temp = getValue((byte)0x46,vCData);
- if((temp[0]&(byte)0x02) == (byte)0x02){
- return true;
- }
- else{
- return false;
- }
- }
- public static byte[] createStatusCode(short statusCode){
- byte [] resp = Utils.shortToByteArr(statusCode);
- return Utils.append(new byte[]{(byte)0x4E,(byte)resp.length}, resp);
- }
-
-
- public static short byteArrayToShort(byte[] data)
- {
- return (short)((data[0]<<8) | (data[1]));
- }
-
- public static int lenOfTLV(byte[] tlv, int offset)
- {
- int tlvLen = 0;
-
- if(tlv != null)
- {
- if(tlv[offset] == 0x82)
- {
- tlvLen = tlv[offset+1]<<8|tlv[offset+2];
- }
- else if(tlv[offset] == 0x81)
- {
- tlvLen = tlv[offset+1];
- }
- else if(tlv[offset] <= 0x7F)
- {
- tlvLen = tlv[offset];
- }
- else
- {
- /*Error case*/
- }
- }
- return tlvLen;
- }
-
- public static int skipLenTLV(byte[] tlv, int offset)
- {
- int skipLen = 1;
-
- if(tlv != null)
- {
- if(tlv[offset] == 0x82)
- {
- skipLen = 3;
- }
- else if(tlv[offset] == 0x81)
- {
- skipLen = 2;
- }
- else if(tlv[offset] <= 0x7F)
- {
- skipLen = 1;
- }
- else
- {
- /*Error case*/
- }
- }
- return skipLen;
- }
-
- public static byte[] findNextAID(byte[] byteArr, int offset)
- {
- byte[] aidBytes = new byte[byteArr[offset]+2];
-
- for(int i=0;i< (byteArr[offset]+(byte)2);i++)
- {
- /*Modified for Including 0x4F tag and length*/
- aidBytes[i] = byteArr[offset-(byte)1+i];
- }
- return aidBytes;
- }
- public static void exportReg(){
- String pathsrc = "/data/data/com.nxp.ltsm.ltsmclient/shared_prefs/Reg.xml";
- String pathdest = Environment.getExternalStorageDirectory().getPath()+"/ltsmRegBackup/";
-
- File ip = new File(pathsrc);
- File op = new File(pathdest);
-
- copyFile(pathsrc,pathdest);
- }
-
- public static void importReg(){
- String pathdest = "/data/data/com.nxp.ltsm.ltsmclient/shared_prefs/";
- String pathsrc = Environment.getExternalStorageDirectory().getPath()+"/ltsmRegBackup/Reg.xml";
-
- File ip = new File(pathsrc);
- File op = new File(pathdest);
-
- copyFile(pathsrc,pathdest);
- }
-
- public static void copyFile(String pathsrc, String pathdest)
- throws InflateException {
- String TAG = "copyFile";
- String filepath = "";
- String filename = "Reg.xml";
-
- File sourceLocation = new File(pathsrc);
- File targetLocation = new File(pathdest);
- try {
- Log.i(TAG, "Enter");
- if(!sourceLocation.exists()){
- Log.i(TAG, "sourceLocation "+pathsrc+" Does not exist..!!");
- return;
- }
- if (!targetLocation.exists()) {
- Log.i(TAG, "Creating Target Directory");
- targetLocation.mkdirs();
- }
- filepath = pathdest+filename;
- targetLocation = new File(filepath);
- InputStream in = new FileInputStream(sourceLocation);
-
- OutputStream out = new FileOutputStream(targetLocation);
-
- // Copy the bits from instream to outstream
- byte[] buf = new byte[1024];
- int len;
- while ((len = in.read(buf)) > 0) {
- out.write(buf, 0, len);
- }
- in.close();
- out.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
-}
diff --git a/LTSMClient/src/com/nxp/ltsm/ltsmclient/tools/VCDescriptionFile.java b/LTSMClient/src/com/nxp/ltsm/ltsmclient/tools/VCDescriptionFile.java
deleted file mode 100644
index 81e1bef..0000000
--- a/LTSMClient/src/com/nxp/ltsm/ltsmclient/tools/VCDescriptionFile.java
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright (C) 2014 NXP Semiconductors
- *
- * 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.nxp.ltsm.ltsmclient.tools;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-import org.apache.commons.codec.binary.Hex;
-
-import android.content.Context;
-import android.util.Log;
-
-
-public class VCDescriptionFile {
-
-
- public VCDescriptionFile(){
- }
-
- public byte[] createVc(byte[] VCData,String appName, short VC_Entry)
- {
- String TAG = "VCDescriptionFile:createVC";
- Log.i(TAG, "Enter");
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- byte[] VC_EntryBytes = Utils.shortToByteArr(VC_Entry);
- try{
- out.write(createTlv(0x4F, Hex.decodeHex(appName.toCharArray())));
- out.write(createTlv(0x40, VC_EntryBytes));
- return(createTlv(0x70,Utils.append(out.toByteArray(),VCData)));
- }catch(Exception e){
- e.printStackTrace();
- }
- return null;
- }
-
-
- public byte[] deleteVc(String appName,short VC_Entry)
- {
- String TAG = "VCDescriptionFile:deleteVc";
- Log.i(TAG, "Enter");
- byte[] VC_EntryBytes = Utils.shortToByteArr(VC_Entry);
- try
- {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
-
- out.write(createTlv(0x4F, Hex.decodeHex(appName.toCharArray())));
- out.write(createTlv(0x40, VC_EntryBytes));
- Log.i(TAG, "Exit");
- return createTlv(0x71, out.toByteArray());
- }
- catch(Exception e)
- {
- e.printStackTrace();
- return null;
- }
- }
-
-
- public static byte[] createTlv(int tag, byte[] value)
- {
- if ((value == null) || (value.length == 0))
- {
- return new byte[0];
- }
- else
- {
- byte[] t, l;
-
- if ((tag & 0xFF00) == 0x0000)
- {
- t = new byte[] { (byte)tag };
- }
- else
- {
- t = new byte[] { (byte)(tag >> 8), (byte)tag };
- }
-
- if (value.length < 128)
- {
- l = new byte[] { (byte)value.length };
- }
- else if (value.length < 256)
- {
- l = new byte[] { (byte)(0x81), (byte)value.length };
- }
- else
- {
- l = new byte[] { (byte)(0x82), (byte)(value.length >> 8), (byte)value.length };
- }
-
- return Utils.append(Utils.append(t, l), value);
- }
- }
-
- static byte[] parseHexProperty(String name, String key)
- {
- String TAG = "VCDescriptionFile:parseHexProperty";
- String value = key;
-
- try
- {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
-
- while(value.length() > 0)
- {
- out.write(Integer.parseInt(value.substring(0, 2), 16));
- value = value.substring(2);
- }
-
- return out.toByteArray();
- }
- catch(Exception e)
- {
- e.printStackTrace();
- Log.i(TAG, "Property %s is malformed" + name);
- System.exit(1);
- return null;
- }
- }
-
- public byte[] CreateVCResp(int vCEntry, String VC_UID) {
- byte[] Rdata = new byte[2+VC_UID.length()];
- byte[] VC_EntryBytes = Utils.shortToByteArr((short)vCEntry);
- byte[] VCUID = parseHexProperty("VC_UID",VC_UID);
- byte[] stat = new byte[] {(byte)0x90,(byte)0x00};
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- try {
- out.write(createTlv(0x40, VC_EntryBytes));
- out.write(createTlv(0x41, VCUID));
- out.write(createTlv(0x4E, stat));
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- return out.toByteArray();
- }
-
- public byte[] CreatePersonalizeData(byte[] VCData, String pkgName,String appShaName, short VC_Entry, Context context) {
- String TAG = "VCDescriptionFile:cCreatePersonalizeData";
- Log.i(TAG, "Enter");
- int i = VCData.length;
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- byte[] VC_EntryBytes = Utils.shortToByteArr(VC_Entry);
- try{
- out.write(createTlv(0x4F, Hex.decodeHex(appShaName.toCharArray())));
- out.write(createTlv(0x40, VC_EntryBytes));
- out.write(Utils.append(VCData,createTlv(0xC1, Hex.decodeHex(Utils.shaSignature(pkgName, context).toCharArray()))));
- return(createTlv(0x73,out.toByteArray()));
- }catch(Exception e){
- e.printStackTrace();
- }
- return null;
- }
-
- public byte[] AddandUpdateMDAC(byte[] vCData, short vcEntry, String appName) {
- String TAG = "VCDescriptionFile:AddandUpdateMDAC";
- Log.i(TAG, "Enter");
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- byte[] VC_EntryBytes = Utils.shortToByteArr(vcEntry);
- try{
- out.write(createTlv(0x4F, Hex.decodeHex(appName.toCharArray())));
- out.write(createTlv(0x40, VC_EntryBytes));
- return(createTlv(0x72,Utils.append(out.toByteArray(),vCData)));
- }catch(Exception e){
- e.printStackTrace();
- }
- return null;
- }
-
- public byte[] CreateMFData(byte[] vCData, short vCEntry) {
- String TAG = "VCDescriptionFile:CreateMFData";
- Log.i(TAG, "Enter");
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- byte[] VC_EntryBytes = Utils.shortToByteArr(vCEntry);
- try{
- out.write(createTlv(0x40, VC_EntryBytes));
- out.write(vCData);
- return(createTlv(0x78, out.toByteArray()));
- }catch(Exception e){
- e.printStackTrace();
- }
- return null;
- }
-
- public byte[] formVCList(int VCEntry, String AppName){
- String TAG = "VCDescriptionFile:FormVCList";
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- byte[] VC_EntryBytes = Utils.shortToByteArr((short)VCEntry);
- try{
- out.write(createTlv(0x40, VC_EntryBytes));
- out.write(createTlv(0x4F, AppName.getBytes("UTF-8")));
- return createTlv(0x61, out.toByteArray());
-
- }catch(Exception e){
- e.printStackTrace();
- }
- return null;
-
-
-
- }
-}
diff --git a/LTSMClient2.0/Android.mk b/LTSMClient2.0/Android.mk
deleted file mode 100644
index a8a436f..0000000
--- a/LTSMClient2.0/Android.mk
+++ /dev/null
@@ -1,24 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_STATIC_JAVA_LIBRARIES += guava com.android.vcard \
- LTSMLibs \
- LTSMLibs1
-
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_PACKAGE_NAME := ltsmclient
-LOCAL_SRC_FILES +=src/com/nxp/ltsm/ltsmclient/ILTSMClient.aidl
-LOCAL_PRIVILEGED_MODULE := true
-
-#LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
-
-include $(CLEAR_VARS)
-
-LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := LTSMLibs:libs/gson-2.2.4.jar LTSMLibs1:libs/commons-codec-1.9.jar
-
-include $(BUILD_MULTI_PREBUILT)
diff --git a/LTSMClient2.0/AndroidManifest.xml b/LTSMClient2.0/AndroidManifest.xml
deleted file mode 100644
index 8ef9064..0000000
--- a/LTSMClient2.0/AndroidManifest.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.nxp.ltsm.ltsmclient"
- android:versionCode="1"
- android:versionName="1.0" >
-
- <uses-sdk
- android:minSdkVersion="9"
- android:targetSdkVersion="18" />
- <uses-permission android:name="android.permission.NFC" />
- <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- <uses-permission android:name="android.permission.GET_TASKS"/>
-
- <application
- android:allowBackup="false"
- android:icon="@drawable/ic_launcher"
- android:label="@string/app_name"
- android:theme="@style/AppTheme" >
- <service
- android:name=".LTSMClient">
- <intent-filter>
- <action android:name="com.nxp.ltsm.ltsmclient" />
- </intent-filter>
- </service>
- </application>
-<debug/>
-</manifest>
\ No newline at end of file
diff --git a/LTSMClient2.0/libs/android-support-v4.jar b/LTSMClient2.0/libs/android-support-v4.jar
deleted file mode 100644
index 9056828..0000000
--- a/LTSMClient2.0/libs/android-support-v4.jar
+++ /dev/null
Binary files differ
diff --git a/LTSMClient2.0/libs/commons-codec-1.9.jar b/LTSMClient2.0/libs/commons-codec-1.9.jar
deleted file mode 100644
index ef35f1c..0000000
--- a/LTSMClient2.0/libs/commons-codec-1.9.jar
+++ /dev/null
Binary files differ
diff --git a/LTSMClient2.0/libs/gson-2.2.4-javadoc.jar b/LTSMClient2.0/libs/gson-2.2.4-javadoc.jar
deleted file mode 100644
index ce8fa7d..0000000
--- a/LTSMClient2.0/libs/gson-2.2.4-javadoc.jar
+++ /dev/null
Binary files differ
diff --git a/LTSMClient2.0/libs/gson-2.2.4-sources.jar b/LTSMClient2.0/libs/gson-2.2.4-sources.jar
deleted file mode 100644
index 30b13f6..0000000
--- a/LTSMClient2.0/libs/gson-2.2.4-sources.jar
+++ /dev/null
Binary files differ
diff --git a/LTSMClient2.0/libs/gson-2.2.4.jar b/LTSMClient2.0/libs/gson-2.2.4.jar
deleted file mode 100644
index 9478253..0000000
--- a/LTSMClient2.0/libs/gson-2.2.4.jar
+++ /dev/null
Binary files differ
diff --git a/LTSMClient2.0/res/drawable-hdpi/ic_launcher.png b/LTSMClient2.0/res/drawable-hdpi/ic_launcher.png
deleted file mode 100644
index 288b665..0000000
--- a/LTSMClient2.0/res/drawable-hdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/LTSMClient2.0/res/drawable-mdpi/ic_launcher.png b/LTSMClient2.0/res/drawable-mdpi/ic_launcher.png
deleted file mode 100644
index 6ae570b..0000000
--- a/LTSMClient2.0/res/drawable-mdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/LTSMClient2.0/res/drawable-xhdpi/ic_launcher.png b/LTSMClient2.0/res/drawable-xhdpi/ic_launcher.png
deleted file mode 100644
index d4fb7cd..0000000
--- a/LTSMClient2.0/res/drawable-xhdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/LTSMClient2.0/res/drawable-xxhdpi/ic_launcher.png b/LTSMClient2.0/res/drawable-xxhdpi/ic_launcher.png
deleted file mode 100644
index 85a6081..0000000
--- a/LTSMClient2.0/res/drawable-xxhdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/LTSMClient2.0/res/layout/activity_ltsmclient.xml b/LTSMClient2.0/res/layout/activity_ltsmclient.xml
deleted file mode 100644
index e6b3d42..0000000
--- a/LTSMClient2.0/res/layout/activity_ltsmclient.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingBottom="@dimen/activity_vertical_margin"
- android:paddingLeft="@dimen/activity_horizontal_margin"
- android:paddingRight="@dimen/activity_horizontal_margin"
- android:paddingTop="@dimen/activity_vertical_margin"
- tools:context=".LTSMClient" >
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/hello_world" />
-
-</RelativeLayout>
diff --git a/LTSMClient2.0/res/menu/ltsmclient.xml b/LTSMClient2.0/res/menu/ltsmclient.xml
deleted file mode 100644
index c002028..0000000
--- a/LTSMClient2.0/res/menu/ltsmclient.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<menu xmlns:android="http://schemas.android.com/apk/res/android" >
-
- <item
- android:id="@+id/action_settings"
- android:orderInCategory="100"
- android:showAsAction="never"
- android:title="@string/action_settings"/>
-
-</menu>
diff --git a/LTSMClient2.0/res/values-sw600dp/dimens.xml b/LTSMClient2.0/res/values-sw600dp/dimens.xml
deleted file mode 100644
index 44f01db..0000000
--- a/LTSMClient2.0/res/values-sw600dp/dimens.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<resources>
-
- <!--
- Customize dimensions originally defined in res/values/dimens.xml (such as
- screen margins) for sw600dp devices (e.g. 7" tablets) here.
- -->
-
-</resources>
diff --git a/LTSMClient2.0/res/values-sw720dp-land/dimens.xml b/LTSMClient2.0/res/values-sw720dp-land/dimens.xml
deleted file mode 100644
index 61e3fa8..0000000
--- a/LTSMClient2.0/res/values-sw720dp-land/dimens.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<resources>
-
- <!--
- Customize dimensions originally defined in res/values/dimens.xml (such as
- screen margins) for sw720dp devices (e.g. 10" tablets) in landscape here.
- -->
- <dimen name="activity_horizontal_margin">128dp</dimen>
-
-</resources>
diff --git a/LTSMClient2.0/res/values-v11/styles.xml b/LTSMClient2.0/res/values-v11/styles.xml
deleted file mode 100644
index 3c02242..0000000
--- a/LTSMClient2.0/res/values-v11/styles.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<resources>
-
- <!--
- Base application theme for API 11+. This theme completely replaces
- AppBaseTheme from res/values/styles.xml on API 11+ devices.
- -->
- <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
- <!-- API 11 theme customizations can go here. -->
- </style>
-
-</resources>
diff --git a/LTSMClient2.0/res/values-v14/styles.xml b/LTSMClient2.0/res/values-v14/styles.xml
deleted file mode 100644
index a91fd03..0000000
--- a/LTSMClient2.0/res/values-v14/styles.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<resources>
-
- <!--
- Base application theme for API 14+. This theme completely replaces
- AppBaseTheme from BOTH res/values/styles.xml and
- res/values-v11/styles.xml on API 14+ devices.
- -->
- <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
- <!-- API 14 theme customizations can go here. -->
- </style>
-
-</resources>
diff --git a/LTSMClient2.0/res/values/dimens.xml b/LTSMClient2.0/res/values/dimens.xml
deleted file mode 100644
index 55c1e59..0000000
--- a/LTSMClient2.0/res/values/dimens.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<resources>
-
- <!-- Default screen margins, per the Android Design guidelines. -->
- <dimen name="activity_horizontal_margin">16dp</dimen>
- <dimen name="activity_vertical_margin">16dp</dimen>
-
-</resources>
diff --git a/LTSMClient2.0/res/values/strings.xml b/LTSMClient2.0/res/values/strings.xml
deleted file mode 100644
index 788d824..0000000
--- a/LTSMClient2.0/res/values/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-
- <string name="app_name">LTSMClient</string>
- <string name="action_settings">Settings</string>
- <string name="hello_world">Hello world!</string>
-
-</resources>
diff --git a/LTSMClient2.0/res/values/styles.xml b/LTSMClient2.0/res/values/styles.xml
deleted file mode 100644
index 6ce89c7..0000000
--- a/LTSMClient2.0/res/values/styles.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<resources>
-
- <!--
- Base application theme, dependent on API level. This theme is replaced
- by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
- -->
- <style name="AppBaseTheme" parent="android:Theme.Light">
- <!--
- Theme customizations available in newer API levels can go in
- res/values-vXX/styles.xml, while customizations related to
- backward-compatibility can go here.
- -->
- </style>
-
- <!-- Application theme. -->
- <style name="AppTheme" parent="AppBaseTheme">
- <!-- All customizations that are NOT specific to a particular API-level can go here. -->
- </style>
-
-</resources>
diff --git a/LTSMClient2.0/src/com/nxp/ltsm/ltsmclient/ILTSMClient.aidl b/LTSMClient2.0/src/com/nxp/ltsm/ltsmclient/ILTSMClient.aidl
deleted file mode 100644
index ba1fc77..0000000
--- a/LTSMClient2.0/src/com/nxp/ltsm/ltsmclient/ILTSMClient.aidl
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2014 NXP Semiconductors
- *
- * 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.nxp.ltsm.ltsmclient;
-
-interface ILTSMClient{
- byte[] createVirtualCard(in byte[] vcData, in byte[] personalizeData);
- byte[] deleteVirtualCard(int vcEntry);
- byte[] activateVirtualCard(int vcEntry, boolean mode, boolean concurrentActivationMode);
- byte[] addAndUpdateMdac(int vcEntry,in byte[] vcData);
- byte[] readMifareData(int vcEntry,in byte[] vcData);
- byte[] getVcList();
- byte[] getVirtualCardStatus(int vcEntry); /*Get VCStatus new api*/
-}
\ No newline at end of file
diff --git a/LTSMClient2.0/src/com/nxp/ltsm/ltsmclient/LTSMClient.java b/LTSMClient2.0/src/com/nxp/ltsm/ltsmclient/LTSMClient.java
deleted file mode 100644
index 371c7b4..0000000
--- a/LTSMClient2.0/src/com/nxp/ltsm/ltsmclient/LTSMClient.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2014 NXP Semiconductors
- *
- * 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.nxp.ltsm.ltsmclient;
-
-import java.io.File;
-import java.io.IOException;
-
-import android.app.Service;
-import android.content.Intent;
-import android.os.IBinder;
-import android.util.Log;
-
-public class LTSMClient extends Service {
-
- private LTSMCommunicator binder;
- @Override
- public void onCreate() {
- super.onCreate();
-
- binder = new LTSMCommunicator(this);
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- // Return the interface
- return binder;
- }
-
-}
diff --git a/LTSMClient2.0/src/com/nxp/ltsm/ltsmclient/LTSMCommunicator.java b/LTSMClient2.0/src/com/nxp/ltsm/ltsmclient/LTSMCommunicator.java
deleted file mode 100644
index 915ee1e..0000000
--- a/LTSMClient2.0/src/com/nxp/ltsm/ltsmclient/LTSMCommunicator.java
+++ /dev/null
@@ -1,2138 +0,0 @@
-/*
- * Copyright (C) 2014 NXP Semiconductors
- *
- * 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.nxp.ltsm.ltsmclient;
-
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.commons.codec.binary.Hex;
-
-import android.R.bool;
-import android.R.integer;
-import android.R.string;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.pm.PackageInfo;
-
-import com.nxp.eseclient.LtsmService;
-
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-import android.view.InflateException;
-
-import com.google.gson.Gson;
-import com.nxp.ltsm.ltsmclient.tools.Data;
-import com.nxp.ltsm.ltsmclient.tools.Utils;
-import com.nxp.ltsm.ltsmclient.tools.VCDescriptionFile;
-import com.nxp.ltsm.ltsmclient.tools.TLV;
-
-import java.util.Arrays;
-
-public class LTSMCommunicator extends ILTSMClient.Stub {
-
- private static final String LOG_TAG = "LTSMCommunicator";
- private static Context context;
- private static String CurrentPackage;
- private static Binder mBinder = new Binder();
- private static Bundle bundle;
- static int[] channelId = new int[10];
- static int[] isopened = new int[10];
- static int channelCnt = 0;
- private static LtsmService mLtsmService = null;
- private static String currentProcess = "";
- static ltsmRegistry Registry;
- static int InitialVCEntry = 0;
- static int currentVcEntry = 0;
- static int DeleteVCEntry = 99;
- static short statusCode = 0;
- static byte[] vcUid = new byte[]{};
- private static boolean previousConcurrentActivationMode = true;
-
- public LTSMCommunicator(Context context) {
- LTSMCommunicator.context = context;
-
- }
-
- /*******************************************************
- *
- * Responsible for creating the Virtual Card
- * The second argument-Personalise Data is optional and it is not mandatory to pass.
- * If VC Creation configuration is set to 1, then Personalise Data shall be also provided.
- *
- *@param vcData
- *@param Personalise Data
- *
- *@return If success then the VC entry number and VCUID are returned
- * to the SP Application along with status word. Otherwise an error code.
- *
- *******************************************************/
-
- @Override
- public synchronized byte[] createVirtualCard(byte[] vcData,byte[] personalizeData) throws RemoteException {
- String TAG = "LTSMCommunicator:CreateVirtualCard";
- Log.i(TAG, "Enter");
- statusCode = 0;
- byte[] rData = new byte[0];
- byte cData[] = new byte[0];
- currentProcess = "CreateVirtualCard";
- String currentWalletPkg = "";
- int status = Data.SW_REFERENCE_DATA_NOT_FOUND,rStatus;
- TLV tlvResult = null;
- TLV tlvResultF8 = null;
- TLV tlvResultE2 = null;
- boolean personalize = false;
- boolean saveRegistry = true;
- boolean addedintoRegistry = false;
- short vcEntry = 0;
- Log.i(TAG, "vcData : " + Utils.bytArrayToHex(vcData));
-
- try{
- createVcProcedure :
- {
- currentWalletPkg = Utils.getCallingAppPkg(context);
- boolean available = Utils.checkRegistryAvail(context);
- if(!available){
- available = Utils.checkRegBackupAvail();
- if(available){
- Utils.importReg();
- }else{
- Log.i(TAG, "no backup available");
- Registry = new ltsmRegistry();
- }
- }
-
- // Initiate the LTSM. Open Logical Channel and Select LTSM
- rStatus = ltsmStart();
- if(rStatus != Data.SW_NO_ERROR){
- Log.i(TAG, "LTSMStart Failed");
- status = rStatus;
- break createVcProcedure;
- }
-
- if(available){
- //If Registry is already available in SharedPreference Check for Uninstalled Wallet Apps
- rStatus = checkUninstalledApps();
- if(rStatus == Data.SW_NO_ERROR){
- Log.i(TAG, "Uninstalled App Found");
- }
- }
-
- /*get Virtual Card entry number*/
- cData = VCDescriptionFile.GetVC();
- byte[] rapdu = exchangeLtsmProcessCommand(cData);
- Log.i(TAG, "cData : " + Utils.bytArrayToHex(cData));
-
- List<TLV> listRapdu = TLV.parse(Utils.getRDATA(rapdu));
- tlvResult = TLV.find(listRapdu, 0x44); /*Tag contains VCEntry No. which is free */
- if(Utils.byteArrayToShort(tlvResult.getValue()) != Data.SW_NO_ERROR)
- {
- Log.i(TAG, "VCEntry Error : " + Utils.bytArrayToHex(tlvResult.getValue()));
- status = Utils.byteArrayToInt(tlvResult.getValue());
- break createVcProcedure;
- }
-
- tlvResult = TLV.find(listRapdu, 0x40);
-
- //check duplicate Registry Entry
- for(int i = 0; i < Registry.walletName.size(); i++){
- if(Registry.walletName.get(i).toString().equals(currentWalletPkg)){
- //duplicate Registry Entry
- saveRegistry = false;
- break;
- }
- }
- if(saveRegistry == true){
- Registry.walletName.add(currentWalletPkg);
- Registry.walletName_hash.add(Utils.createSha(currentWalletPkg));
- saveRegistry(Registry);
- addedintoRegistry = true;
- }
-
- vcEntry =Utils.byteArrayToShort(tlvResult.getValue());
- if(personalizeData != null){
- rStatus = handlePersonalize(personalizeData,
- currentWalletPkg,
- vcEntry);
-
- if(rStatus != Data.SW_NO_ERROR){
- Log.i(TAG, "Error Personalization : " + Utils.createStatusCode(statusCode));
- status = rStatus;
- break createVcProcedure;
- }
- }
- byte[] spData=null;
- byte[] mfdfaid = null;
- byte[] cltecap = null;
- //check for that f8 tag
- List<TLV> tag = TLV.parse(vcData,new int[]{0xA8,0xE2,0xF8});
- tlvResultF8 = TLV.find(tag, Data.TAG_MF_DF_AID);
- tlvResultE2 = TLV.find(tag, Data.TAG_MF_AID);
- // Strip E2/F8 tag (when present)
- vcData = removeTags(vcData, 0xE2, 0xF8);
- if(tlvResultE2 != null || tlvResultF8 !=null)
- {
- if(tlvResultF8!=null)
- {
- mfdfaid = tlvResultF8.getValue();
- }
- if(tlvResultE2!=null)
- {
- cltecap = tlvResultE2.getValue();
- }
- Log.i(TAG, "E2/F8 Present : " );
- cData =VCDescriptionFile.createF8Vc( Utils.createSha(currentWalletPkg),
- vcEntry,mfdfaid,cltecap);
- rData = exchangeLtsmProcessCommand(cData);
- status = Utils.getSW(rData);
- if(status != Data.SW_NO_ERROR)
- {
- rData = Utils.createStatusCode((short)status);
- return rData;
- }
- }
- //currentProcess used during Process Response if CreateVC is Success
- currentProcess = "CreateVirtualCard";
-
- cData = VCDescriptionFile.createVc(vcData, //vcData
- Utils.createSha(currentWalletPkg), //Sha of the SP Application
- vcEntry); //VC Entry
-
- Log.i(TAG, "cData : " + Utils.bytArrayToHex(cData));
- rData = exchangeLtsmProcessCommand(cData);
-
- status = Utils.getSW(rData);
- }
- /*createVcProcedure Ends*/
-
- if(status == Data.SW_NO_ERROR)
- {
- processCreateVcResponse(rData);
- rData = VCDescriptionFile.CreateVCResp(vcEntry,
- vcUid);
- }
- else
- {
- rData = Utils.createStatusCode((short)status);
- }
-
- Log.i(TAG, "CreateVCResp : " + Utils.bytArrayToHex(rData));
- Log.i(TAG, "Exit");
- return rData;
- }
- catch(Exception e)
- {
- e.printStackTrace();
- return Utils.createStatusCode(Data.SW_EXCEPTION);
- }
- finally
- {
- //Delete VC with Create Status False in the Registry.
- if(status != Data.SW_NO_ERROR && addedintoRegistry == true)
- {
- Registry.walletName.remove(Registry.walletName.size()-1);
- Registry.walletName_hash.remove(Registry.walletName_hash.size()-1);
- saveRegistry(Registry);
- }
- Utils.exportReg();
- closeLogicalChannel();
- }
-
- }
-
- /*******************************************************
- *
- * Responsible for deleting the Virtual Card
- *
- *@param VC entry number to be deleted
- *
- *@return Status word informing success or failure
- *
- ********************************************************/
-
- @Override
- public synchronized byte[] deleteVirtualCard(int vcEntry) throws RemoteException {
- String TAG = "LTSMCommunicator:deleteVirtualCard";
- Log.i(TAG, "Enter");
- int status,rStatus;
- String currentWalletPkg;
- String currentWalletPkg_hash;
- statusCode = 0;
- byte[] rData = new byte[0];
- boolean match_found = false;
- try
- {
- deleteVcProcedure :
- {
- /* On runtime if we try to get calling app pkg name,
- * sometime it is possible that some other app may come to foreground which will give wrong data
- * So get calling app pkg name as soon as it enters the method
- * */
- currentWalletPkg = Utils.getCallingAppPkg(context);
- currentWalletPkg_hash = Utils.createSha(currentWalletPkg);
-
- boolean available = Utils.checkRegistryAvail(context);
- if(!available){
- available = Utils.checkRegBackupAvail();
- if(available)
- {
- Utils.importReg();
- }
- else
- {
- Log.i(TAG, "no backup available");
- status = Data.SW_REGISTRY_IS_EMPTY;
- break deleteVcProcedure;
- }
- }
- Registry = loadRegistry();
-
- currentProcess = "deleteVirtualCard";
-
- rStatus = ltsmStart();
- if(rStatus != Data.SW_NO_ERROR){
- Log.i(TAG, "LTSMStart Failed");
- status = rStatus;
- break deleteVcProcedure;
- }
-
- byte[] cData = VCDescriptionFile.deleteVc(Utils.createSha(currentWalletPkg),(short)vcEntry);
-
- rData = exchangeLtsmProcessCommand(cData);
- status = Utils.getSW(rData);
-
- /*If status is success then remove the entry from registry*/
- if(status == Data.SW_NO_ERROR)
- {
- byte[] getStatusRsp =getStatus(null);
- List<TLV> getStatusRspTlvs = TLV.parse(Utils.getRDATA(getStatusRsp));
- if(getStatusRspTlvs!=null){
- for(TLV tlv: getStatusRspTlvs)
- {
- TLV tlvVCx = TLV.find(tlv.getNodes(), Data.TAG_VC_ENTRY);
- TLV tlvApkId = TLV.find(tlv.getNodes(), Data.TAG_SP_AID);
- byte ApkId[] = tlvApkId.getValue();
- byte regApkId[] = Hex.decodeHex(currentWalletPkg_hash.toCharArray());
- Log.i(TAG, "SEApkId : " + Utils.bytArrayToHex(ApkId));
- Log.i(TAG, "regApkId : " + Utils.bytArrayToHex(regApkId));
- if (Arrays.equals(ApkId,regApkId)){
- match_found = true;
- break;
- }
- }
- }
- if(!match_found){
- for(int i=0;i<Registry.walletName.size();i++){
- if(Registry.walletName.get(i).toString().equals(currentWalletPkg)){
- Registry.walletName.remove(i);
- Registry.walletName_hash.remove(i);
- saveRegistry(Registry);
- break;
- }
- }
- }
- }
- status = Utils.getSW(rData);
- }
- /*deleteVcProcedure Ends*/
-
- Log.i(TAG, "deleteVirtualCard : " + Utils.bytArrayToHex(Utils.createStatusCode((short)status)));
- Log.i(TAG, "Exit");
-
- return Utils.createStatusCode((short)status);
- }
- catch(Exception e)
- {
- e.printStackTrace();
- return Utils.createStatusCode(Data.SW_EXCEPTION);
- }
- finally
- {
- closeLogicalChannel();
- Utils.exportReg();
- }
- }
-
- /*******************************************************
- *
- * Responsible to retrieve the activation state of a VC
- *
- *@param VC entry number
- *
- *@return Status word informing success or failure
- *
- ********************************************************/
-
- @Override
- public synchronized byte[] getVirtualCardStatus(int vcEntry) throws RemoteException {
- String TAG = "LTSMCommunicator:getVirtualCardStatus";
- Log.i(TAG, "Enter");
- byte[] rData = new byte[0];
- byte[] rcvData = new byte[]{};
- byte[] activationState = new byte[]{};
- int status,rStatus;
- String currentWalletPkg = "";
- statusCode = 0;
- try{
- getVcStatusProcedure :
- {
- currentWalletPkg = Utils.getCallingAppPkg(context);
-
- Log.i(TAG, "vcEntry : " + vcEntry);
- Log.i(TAG, "pkg : " + currentWalletPkg);
-
- /*Selecting LTSM Application
- * */
- rStatus = ltsmStart();
- if(rStatus != Data.SW_NO_ERROR){
- Log.i(TAG, "LTSMStart Failed");
- status = rStatus;
- break getVcStatusProcedure;
- }
-
- /*If VC detail doesn't available status will not be success
- * */
- byte[] getStatusRsp = getStatus(TLV.make(Data.TAG_VC_ENTRY, Utils.shortToByteArr((short)vcEntry)));
- if(Utils.getSW(getStatusRsp) != Data.SW_NO_ERROR)
- {
- status = Data.SW_REFERENCE_DATA_NOT_FOUND;
- break getVcStatusProcedure;
- }
-
- List<TLV> getStatusRspTlvs = TLV.parse(Utils.getRDATA(getStatusRsp)).get(0).getNodes();
- TLV tlvResult = TLV.find(getStatusRspTlvs, Data.TAG_SP_AID);
-
- if (tlvResult != null)
- {
- byte[] spAid = tlvResult.getValue();
- if(!Arrays.equals(Utils.getApkHash(currentWalletPkg), spAid))
- {
- status = Data.SW_CONDITION_OF_USE_NOT_SATISFIED;
- break getVcStatusProcedure;
- }
- }
- else
- {
- status = Data.SW_NO_DATA_RECEIVED;
- break getVcStatusProcedure;
- }
-
- //Step6:Select CRS.If it is not selected return the CRS Select status failed
- rStatus = crsSelect();
- if(rStatus != Data.SW_NO_ERROR){
- Log.i(TAG, "crsSelect Failed");
- status = Data.SW_CRS_SELECT_FAILED;
- break getVcStatusProcedure;
- }
- //Step7:LTSM Client sends a GET STATUS to retrieve the state of VC Manager
- byte[] vcmAid = Utils.append(Data.VC_MANAGER_AID, Utils.shortToByteArr((short)vcEntry));
- byte[] capdu = Utils.makeCAPDU(0x80, 0xF2, 0x40, 0x00,
- Utils.append(
- TLV.make(0x4F, vcmAid),
- TLV.make(0x5C, Utils.parseHexString("9F70"))
- )
- );
-
- rcvData =exchangeWithSe(capdu);
-
- if(Utils.getSW(rcvData) != Data.SW_NO_ERROR)
- {
- status = Utils.getSW(rcvData);
- break getVcStatusProcedure;
- }
-
- getStatusRspTlvs = TLV.parse(Utils.getRDATA(rcvData)).get(0).getNodes();
- tlvResult = TLV.find(getStatusRspTlvs, Data.TAG_VC_STATE);
-
- if (tlvResult != null)
- {
- activationState = tlvResult.getValue();
- status = Data.SW_NO_ERROR;
- }
- else
- {
- status = Data.SW_REFERENCE_DATA_NOT_FOUND;
- }
- }
- /*
- * If success then return the activation status + status
- * else send the failed SW
- * */
- if(status == Data.SW_NO_ERROR)
- {
- rData = Utils.append(TLV.make(Data.TAG_VC_STATE, new byte[]{(byte)activationState[1]}), Utils.createStatusCode(Data.SW_NO_ERROR));
- Log.i(TAG, "getVirtualCardStatus RDATA: " + Utils.bytArrayToHex(rData));
-
- }
- else
- {
- rData = Utils.createStatusCode((short)status);
- }
-
- return rData;
- }
- catch(Exception e)
- {
- e.printStackTrace();
- return Utils.createStatusCode(Data.SW_EXCEPTION);
- }
- finally
- {
- closeLogicalChannel();
- }
- }
-
- /*******************************************************
- *
- * Activate/Deactivate Virtual Card.
- *
- *@param vcEntry
- *@param Activation mode - true/false for activate/deactivate the VC
- *
- *@return Status word informing Success or Failure
- *
- ********************************************************/
-
- @Override
- public synchronized byte[] activateVirtualCard(int vcEntry, boolean mode, boolean concurrentActivationMode) throws RemoteException {
- String TAG = "LTSMCommunicator:ActivateVirtualCard";
- Log.i(TAG, "Enter");
- byte[] rData = new byte[0];
- short status = Data.SW_REFERENCE_DATA_NOT_FOUND;
-
- try{
-
- activationProcedure :
- {
-
- int stat = Data.SW_UNEXPECTED_BEHAVIOR;
- TLV tlvResult;
- byte[] retStat = new byte[4];
- byte[] deactivatedvcEntry = new byte[2],Ret_Data = new byte[4];
- byte[] rcvData = new byte[]{};
- byte[] getStatusRsp = new byte[]{};
- byte[] setStatusRsp = new byte[]{};
-
- byte[] vcInfo = new byte[]{};
- byte[] vcmAid = new byte[]{};
- byte[] smAid = new byte[]{};
- byte[] vcState = new byte[]{};
- List<TLV> getStatusRspTlvs;
-
- String pkg = Utils.getCallingAppPkg(context);
- Log.i(TAG, "vcEntry : " + vcEntry);
- Log.i(TAG, "pkg : " + pkg);
-
- /*Selecting LTSM Application
- * */
- stat = ltsmStart();
- if(stat != Data.SW_NO_ERROR){
- Log.i(TAG, "LTSMStart Failed");
- closeLogicalChannel();
- status = (short)stat;
- break activationProcedure;
- }
-
- /*If VC detail doesn't available status will not be success
- * */
- getStatusRsp = getStatus(TLV.make(Data.TAG_VC_ENTRY, Utils.shortToByteArr((short)vcEntry)));
- if(Utils.getSW(getStatusRsp) != Data.SW_NO_ERROR)
- {
- status = Data.CONDITION_OF_USE_NOT_SATISFIED;
- break activationProcedure;
- }
-
- getStatusRspTlvs= TLV.parse(Utils.getRDATA(getStatusRsp)).get(0).getNodes();
- tlvResult = TLV.find(getStatusRspTlvs, Data.TAG_SP_AID);
-
- if (tlvResult != null)
- {
- byte[] spAid = tlvResult.getValue();
- Log.i(TAG, "spAid : " + Utils.bytArrayToHex(spAid));
- Log.i(TAG, "appid : " + Utils.bytArrayToHex(Utils.getApkHash(pkg)));
- if(!Arrays.equals(Utils.getApkHash(pkg), spAid))
- {
- status = Data.CONDITION_OF_USE_NOT_SATISFIED;
- break activationProcedure;
- }
- }
- else
- {
- //TODO confirm with else
- }
-
- /*Check VC state*/
- tlvResult = TLV.find(getStatusRspTlvs, Data.TAG_VC_STATE);
-
- if (tlvResult != null)
- {
- vcState = tlvResult.getValue();
-
- /* possible values for vcState,
- * x x x x 0 0 1 0 - VC_CREATED
- * x x x x 0 0 0 1 - VC_IN_PROGRESS
- * x x x x 0 1 1 0 - VC_DEAD
- * */
-
- if((vcState[0] & 0x02) != 0x02)
- {
- status = Data.SW_INVALID_VC_ENTRY;
- break activationProcedure;
- }
- else
- {
- tlvResult = TLV.find(getStatusRspTlvs, Data.TAG_SM_AID);
- if (tlvResult != null)
- {
- smAid = tlvResult.getValue();
- }else
- {
- smAid = Utils.append(Data.SERVICE_MANAGER_AID, Utils.shortToByteArr((short)vcEntry));
- }
-
- vcmAid = Utils.append(Data.VC_MANAGER_AID, Utils.shortToByteArr((short)vcEntry));
- }
- }
- else
- {
- //TODO confirm with else
- }
-
- //Select CRS Prior to Activate
- stat = crsSelect();
- if(stat != Data.SW_NO_ERROR){
- Log.i(TAG, "crsSelect Failed");
- status = Data.SW_CRS_SELECT_FAILED;
- break activationProcedure;
- }
-
- //If current request is Activation
- if(mode == true)
- {
- //Checking VCM can be activate
- // 4.a Issue GET STATUS (for the VCM)
- byte[] capdu = Utils.makeCAPDU(0x80, 0xF2, 0x40, 0x00,
- Utils.append(
- TLV.make(0x4F, vcmAid),
- TLV.make(0x5C, Utils.parseHexString("9F70"))
- )
- );
-
- getStatusRsp =exchangeWithSe(capdu);
- if(Utils.getSW(getStatusRsp) != Data.SW_NO_ERROR)
- {
- status = Data.SW_REFERENCE_DATA_NOT_FOUND;
- break activationProcedure;
- }
-
- getStatusRspTlvs = TLV.parse(Utils.getRDATA(getStatusRsp)).get(0).getNodes();
- tlvResult = TLV.find(getStatusRspTlvs, Data.TAG_VC_STATE);
-
- if (tlvResult != null)
- {
- vcState = tlvResult.getValue();
- if(vcState.length == 0x02)
- {
-
- if(((vcState[0] & 0x80)==0x80) //check if VCM_LOCKED
- || ((vcState[1] & 0x80)==0x80)) // Check if VCM_NON_ACTIVABLE
- {
- status = Data.SW_CONDITION_OF_USE_NOT_SATISFIED;
- break activationProcedure;
- }
-
- if(((vcState[0] & 0x80)!=0x80)
- && (vcState[1] == 0x01)) //Check if Already Activated
- {
- Log.i(TAG, "Already Activated");
- status = Data.SW_NO_ERROR;
- break activationProcedure;
- }
- }
- else
- {
- status = Data.CONDITION_OF_USE_NOT_SATISFIED;
- break activationProcedure;
- }
- }
- else
- {
- status = Data.SW_UNEXPECTED_BEHAVIOR;
- break activationProcedure;
- }
-
- //Checking SM can be activate
- capdu = Utils.makeCAPDU(0x80, 0xF2, 0x40, 0x00,
- Utils.append(
- TLV.make(0x4F, smAid),
- TLV.make(0x5C, Utils.parseHexString("9F70"))
- )
- );
-
- getStatusRsp =exchangeWithSe(capdu);
- if(Utils.getSW(getStatusRsp) != Data.SW_NO_ERROR)
- {
- status = Data.SW_REFERENCE_DATA_NOT_FOUND;
- break activationProcedure;
- }
-
- getStatusRspTlvs = TLV.parse(Utils.getRDATA(getStatusRsp)).get(0).getNodes();
- tlvResult = TLV.find(getStatusRspTlvs, Data.TAG_VC_STATE);
-
- if (tlvResult != null)
- {
- vcState = tlvResult.getValue();
- if(vcState.length == 0x02)
- {
-
- if(((vcState[0] & 0x80)==0x80) //check if VCM_LOCKED
- || ((vcState[1] & 0x80)==0x80)) // Check if VCM_NON_ACTIVABLE
- {
- status = Data.SW_CONDITION_OF_USE_NOT_SATISFIED;
- break activationProcedure;
- }
- }
- }
- else
- {
- status = Data.SW_UNEXPECTED_BEHAVIOR;
- break activationProcedure;
- }
-
- if(concurrentActivationMode == true)
- {
- status = (short)manageConcurrencyActivation(vcEntry);
- }
- else
- {
- status = (short)manageNonConcurrencyActivation(vcmAid);
- }
- }
- /*If current request is DeActivation
- * */
- else
- {
- setStatusRsp = setStatus(TLV.make(0x4F, vcmAid),false);
- status = Utils.getSW(setStatusRsp);
- }
-
- } //activationProcedure block ends
-
- Log.i(TAG, "activateVirtualCard : " + Utils.bytArrayToHex(rData));
- Log.i(TAG, "Exit");
- return Utils.createStatusCode(status);
-
- } // try block ends
- catch(Exception e)
- {
- e.printStackTrace();
- return Utils.createStatusCode(Data.SW_EXCEPTION);
- }
- finally
- {
- closeLogicalChannel();
- }
- }
-
- /*******************************************************
- *
- * Add and Updates MDAC used to define the MIFARE Data that
- * may be retrieved by the SP Application
- *
- *@param vcEntry
- *@param vcData
- *
- *@return Status word informing Success or Failure
- *
- ********************************************************/
-
- @Override
- public synchronized byte[] addAndUpdateMdac(int vcEntry,byte[] vcData) throws RemoteException {
- String TAG = "LTSMCommunicator:addAndUpdateMdac";
- currentProcess = "addAndUpdateMdac";
- Log.i(TAG, "Enter");
- statusCode = 0;
- byte[] rData = new byte[0];
- int stat = Data.FAILED;
-
- String pkg = Utils.getCallingAppPkg(context);
-
- stat = ltsmStart();
- if(stat != Data.SW_NO_ERROR){
- Log.i(TAG, "LTSMStart Failed");
- closeLogicalChannel();
- return Utils.createStatusCode((short)stat);
- }
-
- byte[] cData = VCDescriptionFile.AddandUpdateMDAC(vcData,(short)vcEntry,Utils.createSha(pkg));
- Log.i(TAG, "cData : " + cData.length);
- rData = exchangeLtsmProcessCommand(cData);
-
- if(Utils.getSW(rData) == Data.SW_NO_ERROR){
- rData = Utils.createStatusCode(Data.SW_NO_ERROR);
- }
- else{
- rData = Utils.createStatusCode(Utils.getSW(rData));
- }
- closeLogicalChannel();
- Log.i(TAG, "retStat : " + Utils.arrayToHex(rData));
- Utils.exportReg();
- Log.i(TAG, "Exit");
- return rData;
- }
-
- /*******************************************************
- *
- * Read Mifare Data used to retrieve MIFARE data from a VC
- * under the condition that the MIFARE Data Access Control(s)
- * have been provided with Add and update MDAC
- *
- *@param vcData
- *@param vcEntry
- *
- *@return Read Mifare Data and Status Word
- *
- ********************************************************/
-
- @Override
- public synchronized byte[] readMifareData(int vcEntry,byte[] vcData)throws RemoteException {
- String TAG = "LTSMCommunicator:ReadMifareClassicData";
- Log.i(TAG, "Enter");
- statusCode = 0;
- byte[] rData = new byte[0];
- byte[] recvData = new byte[]{};
- byte[] smAid = new byte[]{};
- TLV tlvResult = null;
-
- String pkg = Utils.getCallingAppPkg(context);
-
- int i,stat;
- stat = ltsmStart();
- if(stat != Data.SW_NO_ERROR){
- Log.i(TAG, "LTSMStart Failed");
- closeLogicalChannel();
- return Utils.createStatusCode((short)stat);
- }
-
- byte [] getStatusRsp = getStatus(TLV.make(Data.TAG_VC_ENTRY, Utils.shortToByteArr((short)vcEntry)));
- if(Utils.getSW(getStatusRsp) != Data.SW_NO_ERROR)
- {
- statusCode = Utils.getSW(getStatusRsp);
- closeLogicalChannel();
- return Utils.createStatusCode(statusCode);
- }
-
- List<TLV> getStatusRspTlvs= TLV.parse(Utils.getRDATA(getStatusRsp)).get(0).getNodes();
- tlvResult = TLV.find(getStatusRspTlvs, Data.TAG_SP_AID);
-
- if (tlvResult != null)
- {
- byte[] spAid = tlvResult.getValue();
- Log.i(TAG, "spAid : " + Utils.bytArrayToHex(spAid));
- Log.i(TAG, "appid : " + Utils.bytArrayToHex(Utils.getApkHash(pkg)));
- if(!Arrays.equals(Utils.getApkHash(pkg), spAid))
- {
- closeLogicalChannel();
- return Utils.createStatusCode(Data.SW_CONDITION_OF_USE_NOT_SATISFIED);
- }
- }
- else
- {
- //TODO confirm with else
- }
-
- TLV tlvResult1 = TLV.find(getStatusRspTlvs, Data.TAG_SM_AID);
- if (tlvResult1 != null)
- {
- smAid = tlvResult1.getValue();
- }
- else
- {
- smAid = Utils.append(Data.SERVICE_MANAGER_AID, Utils.shortToByteArr((short)vcEntry));//Modified
- }
- byte[] cApdu = Utils.makeCAPDU(0x00, 0xA4, 0x04, 0x00, smAid);
-
- recvData = exchange(cApdu, channelId[channelCnt -1]);
- if(recvData == null)
- {
- Log.i(TAG, "SE transceive failed ");
- closeLogicalChannel();
- return Utils.createStatusCode(Data.SW_NO_DATA_RECEIVED);
- }
-
- Log.i(TAG, "Received Data : " + Utils.bytArrayToHex(recvData));
-
- cApdu = Utils.makeCAPDU(0x80, 0xB0, 0x00, 0x00, vcData);
- recvData = exchange(cApdu, channelId[channelCnt -1]);
- rData = processReadMifareDataResponse(recvData);
-
- Log.i(TAG, "Exit");
- closeLogicalChannel();
- Log.i(TAG, "recvData : " + Utils.bytArrayToHex(rData));
- return rData;
- }
-
- /*******************************************************
- *
- * getVcList used to retrieve the list of couples VC entry
- * in used and associated SP Application
- *
- *@param none
- *
- *@return byte array containing List of VC entry in use
- *and associated SP Applications and status word.
- *
- ********************************************************/
-
- @Override
- public byte[] getVcList() throws RemoteException {
- String TAG = "LTSMCommunicator:getVcList";
- Log.i(TAG, "Enter");
- byte[] tempData = new byte[]{};
- int stat = Data.FAILED;
- statusCode = 0;
- byte[] rData = new byte[0];
- byte[] VcList= new byte[0];
-
- boolean available = Utils.checkRegistryAvail(context);
- if(!available){
- available = Utils.checkRegBackupAvail();
- if(available){
- Utils.importReg();
- }else{
- Log.i(TAG, "no backup available");
- return Utils.createStatusCode(Data.SW_REGISTRY_IS_EMPTY);
- }
- }
-
- stat = ltsmStart();
- if(stat != Data.SW_NO_ERROR){
- Log.i(TAG, "LTSMStart Failed");
- closeLogicalChannel();
- return Utils.createStatusCode((short)stat);
- }
-
- //If Registry is already available in SharedPreference Check for Uninstalled Wallet Apps
- stat = checkUninstalledApps();
- if(stat == Data.SW_NO_ERROR){
- Log.i(TAG, "Uninstalled App Found");
- }
- rData = getStatus(null);
- if(Utils.getSW(rData) == Data.SW_NO_ERROR)
- {
- List<TLV> getStatusRspTlvs = TLV.parse(Utils.getRDATA(rData));
- if(getStatusRspTlvs!=null)
- {
- VcList = VCDescriptionFile.getVcListResp(getStatusRspTlvs);
- }
-
- if (VcList.length !=0)
- {
- rData = Utils.append(VcList, Utils.createStatusCode(Utils.getSW(rData)));
- }
- else
- {
- rData = Utils.createStatusCode(Data.SW_REFERENCE_DATA_NOT_FOUND);
- }
- }
- else
- {
- rData = Utils.createStatusCode(Utils.getSW(rData));
- }
-
- Log.i(TAG, "retData : " + Utils.bytArrayToHex(rData));
- closeLogicalChannel();
- Utils.exportReg();
- return rData;
- }
-
- /*******************************************************
- *
- *Get the virtual card status from SE
- *
- ********************************************************/
- private byte[] getStatus(byte[] data){
- String TAG = "LTSMCommunicator:getStatus";
- Log.i(TAG, "Enter");
-
- byte[] capdu = Utils.makeCAPDU(0x80, 0xF2, 0x40, 0x00, data);
- byte[] rapdu = exchange(capdu, channelId[channelCnt -1]);
- byte[] status = new byte[0];
- int initLen = status.length;
- loop: for(;;)
- {
- Log.i(TAG, "rapdu : " + Utils.bytArrayToHex(rapdu));
- switch(Utils.getSW(rapdu))
- {
- case (short)(0x6310):
- status = Utils.append(status, Utils.getRDATA(rapdu));
- break;
-
- case (short)(0x9000):
- status = Utils.append(status, rapdu);
- break loop;
-
- case (short)(0x6A88):
- status = Utils.append(status, rapdu);
- break loop;
-
- default: // Unexpected error.
- // FALL THROUGH
- break loop;
- }
- capdu = Utils.makeCAPDU(0x80, 0xF2, 0x40, 0x01, null); // Next occurrence.
- rapdu = exchange(capdu, channelId[channelCnt -1]);
- }
- Log.i(TAG, "status : " + Utils.bytArrayToHex(status));
- return status;
- }
-
- /*******************************************************
- *
- *Set the virtual card status
- *
- ********************************************************/
- private byte[] setStatus(byte[] data, boolean mode){
- String TAG = "LTSMCommunicator:setStatus";
- Log.i(TAG, "Enter");
-
- byte[] cData = new byte[]{};
- byte[] rData = new byte[]{};
-
- if (mode == true) {
- cData = Utils.makeCAPDU((byte) 0x80, (byte) 0xF0, 0x01, (byte) 0x01, data);
- }else{
- cData = Utils.makeCAPDU((byte) 0x80, (byte) 0xF0, 0x01, (byte) 0x00, data);
- }
- rData = exchangeWithSe(cData);
- Log.i(TAG, "Exit");
- return rData;
- }
-
- /*******************************************************
- *
- *Manage concurrency Activation Procedure
- * @param vcEntry
- * @return status
- *
- ********************************************************/
- private int manageConcurrencyActivation(int vcEntry) {
- String TAG = "LTSMCommunicator:manageCuncurrencyActivation";
- Log.i(TAG, "Enter");
- byte[] setStatusRsp = new byte[]{};
- byte[] getStatusRsp = new byte[]{};
- byte[] conflictingAidsTagA2 = new byte[]{};
- int skipFirstTag48 = 1;
- List<TLV> setStatusRspTlvs,parseTlvs;
- TLV tlvResult;
- int status;
- byte[] vcmAidToActivate = Utils.append(Data.VC_MANAGER_AID, Utils.shortToByteArr((short)vcEntry));
-
- if (!previousConcurrentActivationMode)
- {
- // Deactivate all
- deactivateAllContactlessApplications();
- }
- previousConcurrentActivationMode = true;
-
- /* Try to activate the intended VC
- * */
- tryActivate : for(;;)
- {
- setStatusRsp = setStatus(TLV.make(0x4F, vcmAidToActivate),true);
-
- switch(Utils.getSW(setStatusRsp))
- {
- case Data.SW_NO_ERROR :
-
- Log.i(TAG, "Activated Successfully");
- status = Data.SW_NO_ERROR;
- break tryActivate;
-
- case Data.SW_6330_AVAILABLE :
-
- case Data.SW_6310_AVAILABLE :
- /*Activation not successful
- * Conflicting AIDs present
- * */
- tlvResult = getTlvA0A2(setStatusRsp);
-
- switch(tlvResult.getTag())
- {
- case Data.TAG_A0_AVAILABLE :
- byte[] conflictingAidsTagA0 = tlvResult.getValue();
- setStatusRsp = setStatus(conflictingAidsTagA0,false);
- if(Utils.getSW(setStatusRsp) == Data.SW_NO_ERROR)
- {
- /*
- * deActivation of conflictingAidsTagA0 successful
- * try to activate initial intended aid
- * */
- break;
- }
- else
- {
- Log.i(TAG, "Dactivation of conflicting Aids of TagA0 failed. Status : " + Utils.getSW(setStatusRsp));
- status = Data.SW_UNEXPECTED_BEHAVIOR;
- break tryActivate;
- }
-
- case Data.TAG_A2_AVAILABLE :
- parseTlvs = TLV.parse(tlvResult.getValue());
- tlvResult = TLV.find(parseTlvs, Data.TAG_48_AVAILABLE);
-
- switch(Utils.byteArrayToShort(tlvResult.getValue()))
- {
- case Data.REASON_CODE_800B :
- case Data.REASON_CODE_800C :
-
- status = Data.SW_VC_IN_CONTACTLESS_SESSION;
- break tryActivate;
-
- case Data.REASON_CODE_8002 :
- case Data.REASON_CODE_8003 :
- case Data.REASON_CODE_8004 :
- case Data.REASON_CODE_8005 :
-
- /*Tag format
- * A2 --
- * 48 -- Mandatory
- * 4F -- Mandatory
- * 4F -- Optional
- * ..... .....
- * 48 -- Optional
- * 4F -- Optional
- * 4F -- Optional
- * ..... .....
- * ..... .....
- * Get 4F Tag corresponding to only one Tag48
- * */
-
- conflictingAidsTagA2 = getSubsequentTlvs(skipFirstTag48, Data.TAG_4F_AVAILABLE, parseTlvs);
-
- setStatusRsp = setStatus(conflictingAidsTagA2,false);
-
- if(Utils.getSW(setStatusRsp) != Data.SW_NO_ERROR)
- {
- Log.i(TAG, "Dactivation of conflicting Aids of TagA0 failed. Status : " + Utils.getSW(setStatusRsp));
- status = Data.SW_UNEXPECTED_BEHAVIOR;
- break tryActivate;
- }
- /*
- * deActivation of conflictingAidsTagA2 successful
- * try to activate initial intended aid
- * */
- break;
-
- case Data.REASON_CODE_8009 :
- /*
- * Deactivate the VC that contains a Mifare Desfire AID conflicting with
- * Mifare Desfire AID of the VC to be activated
- * */
-
- TLV tlv4F,tlv;
- tlv4F = TLV.find(parseTlvs, Data.TAG_4F_AVAILABLE);
- byte[] aid = tlv4F.getValue();
-
- /*appending 0x5C,0xA6 will make restrict the return Tag to only A6 (avoids all unnecessary tags)
- * */
- byte[] capdu = Utils.makeCAPDU(0x80, 0xF2, 0x40, 0x00,
- Utils.append(
- TLV.make(0x4F, aid),
- TLV.make(0x5C, new byte[] { (byte)(0xA6) })
- )
- );
- getStatusRsp = exchangeWithSe(capdu);
- Log.i(TAG,"REASON_CODE_8009 getStatusRsp"+ Utils.bytArrayToHex(Utils.getRDATA(getStatusRsp)));
- parseTlvs = TLV.parse(Utils.getRDATA(getStatusRsp), new int[] { 0xF1 });
- tlv = TLV.find(parseTlvs, 0x61);
- parseTlvs = tlv.getNodes();
- tlv = TLV.find(parseTlvs, Data.TAG_A6_AVAILABLE);
- if(tlv == null)
- {
- Log.i(TAG, "Tag A6 missing");
- status = Data.SW_UNEXPECTED_BEHAVIOR;
- break tryActivate;
- }
- parseTlvs = tlv.getNodes();
- tlv = TLV.find(parseTlvs, Data.TAG_F1_AVAILABLE);
- if(tlv == null)
- {
- status = Data.SW_UNEXPECTED_BEHAVIOR;
- break tryActivate;
- }
-
- setStatusRsp = setStatus(TLV.make(Data.TAG_4F_AVAILABLE, tlv.getValue()),false);
- if(Utils.getSW(setStatusRsp) != Data.SW_NO_ERROR)
- {
- status = Data.SW_UNEXPECTED_BEHAVIOR;
- break tryActivate;
- }
- //TODO notify the application for deactivation of its VC
- break;
-
- default :
- status = Data.SW_CONDITION_OF_USE_NOT_SATISFIED;
- break tryActivate;
-
- }
- break;
-
- default :
- status = Data.SW_UNEXPECTED_BEHAVIOR;
- break tryActivate;
- }
- break;
-
- default :
- status = Data.SW_UNEXPECTED_BEHAVIOR;
- break tryActivate;
- }
- }
-
- Log.i(TAG, "Exit");
- return status;
-
- }
- /*******************************************************
- *
- *Manage Non-concurrency Activation Procedure
- * @param vcEntry
- * @return status
- *
- ********************************************************/
- private int manageNonConcurrencyActivation(byte[] vcmAid) {
- String TAG = "LTSMCommunicator:manageNonConcurrencyActivation";
- Log.i(TAG, "Enter");
- int status = 0;
- status = deactivateAllContactlessApplications();
- if( status!= Data.SW_NO_ERROR)
- {
- return status;
- }
- previousConcurrentActivationMode = false;
- // Activate VCM (Do not check SW).
- byte[] capdu = Utils.makeCAPDU(0x80, 0xF0, 0x01, 0x01, TLV.make(0x4F, vcmAid));
- byte[] rapdu = exchangeWithSe(capdu);
- return Utils.getSW(rapdu);
- }
-
- private static boolean isVCManagerAID(byte[] aid) {
- if (aid.length < Data.NONCONCURRENT_AID_PARTIAL.length)
- {
- return false;
- }
- for(int i = 0; i < Data.NONCONCURRENT_AID_PARTIAL.length - 1; i++)
- {
- if (aid[i] != Data.NONCONCURRENT_AID_PARTIAL[i])
- {
- return false;
- }
- }
- return (byte)(aid[Data.NONCONCURRENT_AID_PARTIAL.length - 1] & 0xF0) == 0x10;
- }
- private int deactivateAllContactlessApplications() {
- // First, deactivate all VCMs; Then deactivate all other applications.
- int status = 0;
- byte p2 = 0x00; // First
- for(boolean more = true; more; p2 = 0x01)
- {
- // 5. Get the list of activated VCMs.
- byte[] capdu = Utils.makeCAPDU(0x80, 0xF2, 0x40, p2,
- Utils.append(
- TLV.make(0x4F, Utils.parseHexString("A000000396")), // RID
- Utils.parseHexString("9F700207015C014F")
- )
- );
- byte[] rapdu = exchangeWithSe(capdu);
-
- switch(Utils.getSW(rapdu))
- {
- default:
- status = Data.SW_CONDITION_OF_USE_NOT_SATISFIED;
- return status;
-
- case Data.SW_6310_AVAILABLE:
- more = true;
- break;
-
- case Data.SW_NO_ERROR:
- more = false;
- status =Data.SW_NO_ERROR;
- break;
-
- case Data.SW_REFERENCE_DATA_NOT_FOUND:
- more = false;
- continue;
- }
-
- List<TLV> tlvs = TLV.parse(Utils.getRDATA(rapdu), new int[] { 0xF1 });
- for(TLV tlv61 : tlvs)
- {
- if (tlv61.getTag() != 0x61)
- {
- continue;
- }
-
- List<TLV> tlv61s;
- if ((tlv61s = tlv61.getNodes()) == null)
- {
- return 0;
- }
-
- for(TLV tlvAid: tlv61s)
- {
- if (tlvAid.getTag() == 0x4F)
- {
- byte[] aid = tlvAid.getValue();
- // VCM ?
- if (!isVCManagerAID(aid))
- {
- continue;
- }
-
- // Deactivate VCM (Do not check SW).
- capdu = Utils.makeCAPDU(0x80, 0xF0, 0x01, 0x00, TLV.make(0x4F, aid));
- rapdu = exchangeWithSe(capdu);
- Intent intent = new Intent();
- intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
- intent.setAction("com.nxp.ltsm.ltsmclient.VC_DEACTIVATED");
- intent.putExtra("VC_AID", aid);
- context.sendBroadcast(intent);
-
- }
- }
- }
- }
-
- p2 = 0x00;
- for(boolean more = true; more; p2 = 0x01)
- {
- // 6. List all remaining activated contactless applications
- byte[] capdu = Utils.makeCAPDU(0x80, 0xF2, 0x40,p2,
- Utils.parseHexString("4F009F700207015C014F")
- );
- byte[] rapdu = exchangeWithSe(capdu);
-
- switch(Utils.getSW(rapdu))
- {
- default:
- status = Data.SW_CONDITION_OF_USE_NOT_SATISFIED;
- return status;
-
- case Data.SW_6310_AVAILABLE:
- more = true;
- break;
-
- case Data.SW_NO_ERROR:
- more = false;
- status =Data.SW_NO_ERROR;
- break;
-
- case Data.SW_REFERENCE_DATA_NOT_FOUND:
- more = false;
- continue;
- }
-
- List<TLV> tlvs = TLV.parse(Utils.getRDATA(rapdu), new int[] { 0xF1 });
- for(TLV tlv61 : tlvs)
- {
- if (tlv61.getTag() != 0x61)
- {
- continue;
- }
-
- List<TLV> tlv61s;
- if ((tlv61s = tlv61.getNodes()) == null)
- {
- return 0;
- }
-
- for(TLV tlvAid: tlv61s)
- {
- if (tlvAid.getTag() == 0x4F)
- {
- byte[] aid = tlvAid.getValue();
-
- // Deactivate VCM (Do not check SW).
- capdu = Utils.makeCAPDU(0x80, 0xF0, 0x01, 0x00, TLV.make(0x4F, aid));
- rapdu = exchangeWithSe(capdu);
- Intent intent = new Intent();
- intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
- intent.setAction("com.nxp.ltsm.ltsmclient.VC_DEACTIVATED");
- intent.putExtra("VC_AID", aid);
- context.sendBroadcast(intent);
- }
- }
- }
- }
- return Data.SW_NO_ERROR;
- }
-
- /*******************************************************
- *
- *Returns subsequent Tags in parseTlvs
- *
- ********************************************************/
- private byte[] getSubsequentTlvs(int startNode, short tagToFind, List<TLV> parseTlvs) {
- byte[] foundTlvs = new byte[]{};
-
- for(int i = startNode; i<parseTlvs.size(); i++)
- {
- if(parseTlvs.get(i).getTag() == tagToFind)
- {
- foundTlvs = Utils.append(foundTlvs, parseTlvs.get(i).getTLV());
- }
- else
- {
- /*break from for loop*/
- break;
- }
- }
- return foundTlvs;
- }
-
- /*******************************************************
- *
- *Returns either TLV Tag A0 or Tag A1
- *
- ********************************************************/
- private TLV getTlvA0A2(byte[] setStatusRsp) {
- String TAG = "LTSMCommunicator:getTagsA0A2";
- Log.i(TAG, "Enter");
- List<TLV> setStatusRspTlvs;
- TLV tlvResult,retTlv = null;
- Log.i(TAG,"getTlvA0A2 setStatusRsp"+ Utils.bytArrayToHex(Utils.getRDATA(setStatusRsp)));
- setStatusRspTlvs = TLV.parse(Utils.getRDATA(setStatusRsp)).get(0).getNodes();
- tlvResult = TLV.find(setStatusRspTlvs, Data.TAG_A0_AVAILABLE);
- /*Tag A0 Present*/
- if (tlvResult != null)
- {
- retTlv= tlvResult;
- }
- else
- {
- tlvResult = TLV.find(setStatusRspTlvs, Data.TAG_A2_AVAILABLE);
- if (tlvResult != null)
- {
- retTlv = tlvResult;
- }
- }
- Log.i(TAG, "Exit");
-
- return retTlv;
- }
-
- /*******************************************************
- *
- * Remove Registry Entry
- *
- ********************************************************/
- private void removeRegistryEntry(int pos, ltsmRegistry Registry){
- // int tmpVc = Registry.walletName.get(pos);
- String TAG = "LTSMCommunicator:removeRegistryEntry";
- //Registry.vcEntry.remove(pos);
- // Log.i(TAG, " DeleteVCEntry " + tmpVc);
- saveRegistry(Registry);
- }
-
- /*******************************************************
- *
- * Initiate the LTSM. Opens the Logical Channel and Selects the LTSM
- *
- ********************************************************/
-
- public static int ltsmStart(){
- String TAG = "LTSMCommunicator:LTSMStart";
- Log.i(TAG, "Enter");
- int status;
- status = ltsmOpenChannel();
- if(status != Data.SW_NO_ERROR){
- Log.i(TAG, "LTSM Open Channel Failed");
- return status;
- }
- status = ltsmSelect();
- if(status != Data.SW_NO_ERROR){
- Log.i(TAG, "LTSM select Failed");
- closeLogicalChannel();
- return status;
- }
- status = Data.SW_NO_ERROR;
- Log.i(TAG, "Exit");
- return status;
- }
-
- /*******************************************************
- *
- * Opens Logical Channel
- *
- ********************************************************/
-
- private static int ltsmOpenChannel() {
- String TAG = "LTSMCommunicator:openLogicalChannel";
- int status;
- Log.i(TAG, "Enter");
- statusCode = 0;
- byte[] recvData = new byte[1024];
-
- try {
- openConnection();
- } catch (RemoteException e) {
- closeLogicalChannel();
- e.printStackTrace();
- }
- try {
- recvData = exchangeApdu(Data.openchannel);
- } catch (RemoteException e) {
- closeLogicalChannel();
- e.printStackTrace();
- }
- if(recvData == null)
- {
- Log.i(TAG, "SE transceive failed ");
- status = Data.SW_SE_TRANSCEIVE_FAILED;
- }
- else if(Utils.getSW(recvData)!=Data.SW_NO_ERROR){
- statusCode = Utils.getSW(recvData);
- Log.i(TAG, "Invalid Response");
- status = Utils.getSW(recvData);
- }
- else{
- Log.i(TAG, "openLogicalChannel SUCCESS");
- channelId[channelCnt] = recvData[recvData.length - 3];
- isopened[channelCnt] = 1;
-
- Utils.saveArray(channelId, "channelId", context);
- Utils.saveArray(isopened, "isopened", context);
- channelCnt = channelCnt + 1;
- Utils.saveInt(channelCnt,"channelCnt",context);
- status = Data.SW_NO_ERROR;
- }
-
- Log.i(TAG, "Exit");
- return status;
- }
-
- /*******************************************************
- *
- *Selects LTSM with currently opened Logical channel
- *
- ********************************************************/
-
- private static int ltsmSelect() {
- String TAG = "LTSMCommunicator:ltsmSelect";
- int status;
- boolean available = false;
- Log.i(TAG, "Enter");
- statusCode = 0;
- byte[] cApdu = Utils.makeCAPDU(0x00, 0xA4, 0x04, 0x00, Data.AID_M4M_LTSM);
- byte[] recvData = new byte[1024];
-
- recvData = exchange(cApdu,channelId[channelCnt -1]);
- if(recvData == null)
- {
- Log.i(TAG, "SE transceive failed ");
- statusCode = Data.SW_SE_TRANSCEIVE_FAILED;
- status = Data.SW_SE_TRANSCEIVE_FAILED;
- }
- else
- {
- Log.i(TAG, "Received Data : " + Utils.bytArrayToHex(recvData));
- if (Utils.getSW(recvData) == Data.SW_NO_ERROR)
- {
- Log.i(TAG, "ltsmSelect SUCCESS ");
- status = Data.SW_NO_ERROR;
- }else{
- statusCode = Utils.getSW(recvData);
- status = Utils.getSW(recvData);
- }
- }
- Log.i(TAG, "Exit");
- return status;
- }
-
- /*******************************************************
- *
- *Handles Exchange of Data during LTSM Process Command
- *
- ********************************************************/
-
- private static byte[] exchangeLtsmProcessCommand(byte[] cdata)
- {
- String TAG = "LTSMCommunicator:exchangeLtsmProcessCommand";
- int stat = Data.SW_REFERENCE_DATA_NOT_FOUND;
- Log.i(TAG, "Enter");
- byte[] rData = new byte[0];
- Log.i(TAG, "(byte)cdata.length : "+(byte)cdata.length + "new byte[] {(byte)cdata.length} : " + Utils.bytArrayToHex(new byte[] {(byte)cdata.length}));
- byte[] cApdu = Utils.makeCAPDU(Data.CLA_M4M_LTSM, Data.INS_M4M_LTSM_PROCESS_COMMAND, 0x00, 0x00, cdata);
- Log.i(TAG, "cApdu : " + Utils.bytArrayToHex(cApdu));
- byte[] rapdu = exchange(cApdu,channelId[channelCnt -1]);
-
- try{
-
- exchangeLtsmCmdbreak:
- {
- switch(Utils.getSW(rapdu))
- {
- default:
- {
- rData = rapdu;
- break;
- }
-
- case Data.SW_NO_ERROR:
- cApdu = Utils.getRDATA(rapdu);
- Log.i(TAG, "SW_NO_ERROR ");
- rData = rapdu;
- break;
- case Data.SW_6310_AVAILABLE:
- process_se_response: for(;;){
- if (rapdu.length == 2)
- {
- rData = rapdu;
- break;
- }
- cApdu = Utils.getRDATA(rapdu);
- Log.i(TAG, "SW_6310_AVAILABLE: Send Data back to SE ");
- // toLTSM = false;
- rapdu = exchangeWithSe(cApdu);
- if (rapdu.length < 256)
- {
- cApdu = Utils.makeCAPDU(Data.CLA_M4M_LTSM, Data.INS_M4M_LTSM_PROCESS_SE_RESPONSE, 0x00, 0x80, rapdu);
- // }
- rapdu = exchange(cApdu,channelId[channelCnt -1]);
-
- switch(Utils.getSW(rapdu))
- {
- default:
- {
- rData = rapdu;
- break process_se_response;
- }
-
- case Data.SW_NO_ERROR:
- Log.i(TAG, "SW_NO_ERROR ");
- rData = rapdu;
- break process_se_response;
-
- case Data.SW_6310_AVAILABLE:
- Log.i(TAG, "SW_6310_AVAILABLE: Send Data back to SE Again");
- }
- }
- else
- {
- byte[] rapdu1 = Utils.extract(rapdu, 0, 255);
- byte[] rapdu2 = Utils.extract(rapdu, 255, rapdu.length - 255);
-
- // First part
- cApdu = Utils.makeCAPDU(Data.CLA_M4M_LTSM, Data.INS_M4M_LTSM_PROCESS_SE_RESPONSE, 0x00, 0x00, rapdu1);
- rapdu = exchange(cApdu,channelId[channelCnt -1]);
-
- if (Utils.getSW(rapdu) != Data.SW_NO_ERROR)
- {
- System.err.println("FAILED: APDU exchange (PROCESS SE RESPONSE) (1 of 2) failed!");
- System.err.println(String.format("LTSM-SW: %04X", Utils.getSW(rapdu)));
- System.exit(1);
- }
-
- // Second part
- cApdu = Utils.makeCAPDU(Data.CLA_M4M_LTSM, Data.INS_M4M_LTSM_PROCESS_SE_RESPONSE, 0x00, 0x80, rapdu2);
- rapdu = exchange(cApdu,channelId[channelCnt -1]);
-
- switch(Utils.getSW(rapdu))
- {
- default:
- {
- rData = rapdu;
- break process_se_response;
- }
-
- case Data.SW_NO_ERROR:
- rData = rapdu;
- break process_se_response;
-
- case Data.SW_6310_AVAILABLE:
- // FALL THROUGH
- }
- }
- }
- }
- }//break block exit
- }//try exit
- catch(Exception e)
- {
- e.printStackTrace();
- }
- Log.i(TAG, "Exit");
- return rData;
- }
-
- /*******************************************************
- *
- *Exchange APDU With Secure Element
- *
- ********************************************************/
-
- private static byte[] exchangeWithSe(byte[] cdata)
- {
- String TAG = "LTSMCommunicator:exchangeWithSe";
- Log.i(TAG, "Enter");
- byte[] recvData = new byte[1024];
- boolean channel_open_cmd = false;
- if (cdata[1] == 0x70) // MANAGE CHANNEL ?
- {
- if (cdata[2] == 0x00) // [open]
- {
- cdata[4] = (byte) 0x01;
- }
- }
- recvData = exchange(cdata,(cdata[0] & 0x03));
- return recvData;
- }
-
- /*******************************************************
- *
- *Common Exchange method for Exchange with SE and Process LTSM Command
- *
- ********************************************************/
-
- private static byte[] exchange(byte[] cApdu,int chnl_id) {
- String TAG = "LTSMCommunicator:exchange";
- Log.i(TAG, "Enter");
- byte[] rData = new byte[0];
-
- // byte[] xchangeData = new byte[cApdu.length];
- try {
-
- cApdu[0] = Utils.adjustCLA(cApdu[0], (byte)chnl_id);
-
- Log.i(TAG, "Sending Data : " + Utils.bytArrayToHex(cApdu));
- rData = exchangeApdu(cApdu);
- if(rData.length == 0)
- {
- Log.i(TAG, "SE transceive failed ");
- rData = Utils.createStatusCode(Data.SW_NO_DATA_RECEIVED);
- }
- Log.i(TAG, " rData : " + Utils.bytArrayToHex(rData));
- } catch (RemoteException e) {
- closeLogicalChannel();
- e.printStackTrace();
- }
- return rData;
- }
-
- /*******************************************************
- *
- *Selects CRS during Activate VC
- *
- ********************************************************/
-
- private static int crsSelect() {
- String TAG = "LTSMCommunicator:crsSelect";
- byte[] rData = new byte[0];
- Log.i(TAG, "Enter");
- rData = exchangeWithSe(Data.selectCRS);
- if(rData == null)
- {
- Log.i(TAG, "SE transceive failed ");
- return Data.SW_NO_DATA_RECEIVED;
- }
- Log.i(TAG, "rData : " + Utils.bytArrayToHex(rData));
- Log.i(TAG, "Exit");
- return Utils.getSW(rData);
- }
-
- /*******************************************************
- *
- *Closes currently opened Logical Channels
- *
- ********************************************************/
-
- public static void closeLogicalChannel() {
- String TAG = "LTSMCommunicator:closeLogicalChannel";
- Log.i(TAG, "Enter");
- byte[] rData = new byte[0];
- byte[] closeChannelCmd = new byte[]{};
- channelCnt = Utils.loadInt("channelCnt",context);
- channelId = Utils.loadArray("channelId",context);
- isopened = Utils.loadArray("isopened",context);
-
- Log.i(TAG, "channelCnt : " + channelCnt);
-
-
- for(int cnt =0; (cnt < channelCnt); cnt++){
- if(isopened[cnt] == 1){
-
- closeChannelCmd = new byte[]{
- (byte) channelId[cnt],
- (byte) 0x70,
- (byte) 0x80,
- (byte) channelId[cnt],
- (byte) 0x00
- };
- try {
- rData = exchangeApdu(closeChannelCmd);
- } catch (RemoteException e) {
- e.printStackTrace();
- }
-
- if(rData == null){
- Log.i(TAG, "exchangeApdu FAILED");
- rData = Utils.createStatusCode(Data.SW_NO_DATA_RECEIVED);
- }
- else if(Utils.getSW(rData) == Data.SW_NO_ERROR){
- Log.i(TAG, "Close Channe id : " + channelId[cnt] + "is SUCCESS");
- channelCnt = channelCnt -1;
- }
- else{
- Log.i(TAG, "Close Channe id : " + channelId[cnt] + "is Failed");
- }
- }
- }
-
- Utils.saveInt(channelCnt,"channelCnt",context);
-
- try {
- closeConnection();
- } catch (RemoteException e) {
- e.printStackTrace();
- }
-
- Log.i(TAG, "Exit");
- }
-
- /*******************************************************
- *
- *Deletes VC's which are not Created Properly
- *
- ********************************************************/
-
- private int deleteTempVc(int vcEntry, String pkg) {
- String TAG = "LTSMCommunicator:deleteTempVc";
- Log.i(TAG, "Enter");
- int stat = Data.FAILED;
- DeleteVCEntry = vcEntry;
- Log.i(TAG, "DeleteVCEntry = vcEntry : " + DeleteVCEntry);
- currentProcess = "deleteVirtualCard";
- byte[] cData = VCDescriptionFile.deleteVc(pkg,(short)vcEntry);
- byte[] rData = exchangeLtsmProcessCommand(cData);
- Log.i(TAG, "Exit");
- return Utils.getSW(rData);
- }
-
- /*******************************************************
- *
- *Handles Personalisation During CreateVC
- *
- *******************************************************/
-
- private int handlePersonalize(byte[] vcData, String pkg, short intValue) {
- String TAG = "LTSMCommunicator:handlePersonalize";
- int stat = Data.SW_REFERENCE_DATA_NOT_FOUND;
- Log.i(TAG, "Enter");
- currentProcess = "handlePersonalize";
- byte[] cData = VCDescriptionFile.CreatePersonalizeData(vcData,pkg,Utils.createSha(pkg),intValue,context);
- Log.i(TAG, "cData : " + Utils.bytArrayToHex(cData));
- byte[] rData = exchangeLtsmProcessCommand(cData);
- return Utils.getSW(rData);
- }
-
- /*******************************************************
- *
- *Opens Connection for Communication with SE
- *
- ********************************************************/
-
- public static boolean openConnection() throws RemoteException {
- String TAG = "LTSMCommunicator:openConnection";
- Log.i(TAG, "Enter");
- String errorCause = "";
-
- try {
-
- bundle = new Bundle();
- try {
- mLtsmService = LtsmService.createLtsmServiceInterface();
- errorCause = "Open Secure Element: Failed";
- if(mLtsmService != null){
- bundle = mLtsmService.open("com.nxp.ltsm.ltsmclient",mBinder);
- }
- Log.i(LOG_TAG, "openConnection() to ESe: Success Bundle : " + bundle);
- if (bundle == null) {
- Log.i(LOG_TAG,"openConnection() not successful");
- }
-
- } catch (Exception e) {
- Log.i(LOG_TAG, "openConnection() not successful");
- e.printStackTrace();
- }
- } catch (Exception e) {
- e.printStackTrace();
- return false;
- }
- return true;
- }
-
- /*******************************************************
- *
- *Opens Connection for Communication with SE
- *
- ********************************************************/
-
- public static boolean closeConnection() throws RemoteException {
- // TODO Auto-generated method stub
- String TAG = "LTSMCommunicator:closeConnection";
- Log.i(TAG, "Enter");
- String errorCause = "";
-
- try {
-
- bundle = new Bundle();
-
- //mBinder = new Binder();
- try {
- if(mLtsmService != null){
- bundle = mLtsmService.close("com.nxp.ltsm.ltsmclient",mBinder);
- }
- Log.i(LOG_TAG, "closeConnection() to ESe: Success Bundle : " + bundle);
- if (bundle == null) {
- Log.i(LOG_TAG,"closeConnection() not successful");
- }
-
- } catch (Exception e) {
- Log.i(LOG_TAG, "closeConnection() not successful");
-
- }
- } catch (Exception e) {
- e.printStackTrace();
- return false;
- }
- return true;
- }
-
- /*******************************************************
- *
- *Transceives the APDU
- *
- ********************************************************/
-
- public static byte[] exchangeApdu(byte[] apdu) throws RemoteException {
-
- Log.i(LOG_TAG,"exchange APDU ENTER");
- try {
- if(mLtsmService != null){
- bundle = mLtsmService.transceive("com.nxp.ltsm.ltsmclient",apdu);
- }
- if (bundle == null) {
- Log.i(LOG_TAG,"exchange APDU failed");
- }
-
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- return bundle.getByteArray("out");
- }
-
-
- /*******************************************************
- *
- *Processes Create VC Response
- *
- ********************************************************/
-
- private static void processCreateVcResponse(byte[] rapdu) {
- String TAG = "processCreateVcResponse";
- Log.i(TAG, "Enter");
- // String pkg = Utils.getCallingAppPkg(context);
- Log.i(TAG, "CurrentPackage : " + CurrentPackage);
- int i;
-
- vcUid = Utils.getValue((byte)0x41,rapdu);
- }
-
- /*******************************************************
- *
- *Processes Read Mifare Classic Data Response
- *
- ********************************************************/
-
- private byte[] processReadMifareDataResponse(byte[] rapdu) {
- statusCode = 0;
- statusCode = Utils.getSW(rapdu);
- byte[] retdata = new byte[1024];
-
- if(Utils.getSW(rapdu) == Data.SW_NO_ERROR){
- byte[] cApdu = Utils.getRDATA(rapdu);
- retdata = Utils.append(cApdu, Utils.createStatusCode(statusCode));
- }else{
- retdata = Utils.createStatusCode(statusCode);
- }
- return retdata;
- }
-
- /*******************************************************
- *
- *Loads LTSM Registry from SharedPreference
- *
- ********************************************************/
-
- public static ltsmRegistry loadRegistry() {
- String TAG = "LTSMCommunicator:loadRegistry";
- Log.i(TAG, "Enter");
- SharedPreferences prefs = context.getSharedPreferences("Reg", Context.MODE_PRIVATE);
- Gson gson = new Gson();
- String json = prefs.getString("ltsmRegistry", "");
- ltsmRegistry RegObj = gson.fromJson(json, ltsmRegistry.class);
- Log.i(TAG, "Exit");
- return RegObj;
- }
-
- /*******************************************************
- *
- *Saves LTSM Registry to SharedPreference
- *
- ********************************************************/
-
- public static void saveRegistry(ltsmRegistry Registry) {
- SharedPreferences.Editor prefsEditor=context.getSharedPreferences("Reg", Context.MODE_PRIVATE).edit();
- Gson gson = new Gson();
- String json = gson.toJson(Registry);
- prefsEditor.putString("ltsmRegistry", json);
- // if(Registry.vcEntry.size()==10){
- // prefsEditor.clear();
- // }
- prefsEditor.commit();
- }
-
- /*******************************************************
- *
- *Check and Process Uninstalled Wallet Apps
- *
- ********************************************************/
-
- private int checkUninstalledApps(){
- String TAG = "LTSMCommunicator:checkUninstalledApps";
- Log.i(TAG, "Enter");
- List<PackageInfo> InstalledApps = Utils.getINstalledApps(context);
- List<String> UninstalledApps = new ArrayList<String>();
- Registry = loadRegistry();
- int i,j;
- byte regApkId[];
- /*
- * Checking Registry entry against Currently installed app entries
- * */
- for(i = 0; i < Registry.walletName.size(); i++){
- for(j = 0; j < InstalledApps.size(); j++){
- if(InstalledApps.get(j).packageName.equals(Registry.walletName.get(i).toString())){
- Log.i(TAG, "CONTAINS : " + Registry.walletName.get(i).toString());
- break;
- }
- }
- /*
- * If Current Registry entry is not found in Currently installed app entries
- * */
- if(j == InstalledApps.size()){
- UninstalledApps.add( Registry.walletName.get(i).toString());
- }
- }
- /*
- * Delete VCs which are in Uninstalled List
- * */
- if(!UninstalledApps.isEmpty()){
- byte[] getStatusRsp =getStatus(null);
- List<TLV> getStatusRspTlvs = TLV.parse(Utils.getRDATA(getStatusRsp));
- for(i = 0; i < UninstalledApps.size(); i++){
- for(j = 0; j < Registry.walletName.size(); j++){
- if(UninstalledApps.get(i).equals(Registry.walletName.get(j).toString())){
- String walletName_hash = Registry.walletName_hash.get(j).toString();
- try{
- regApkId = Hex.decodeHex(Registry.walletName_hash.get(j).toCharArray());
- }
- catch(Exception e)
- {
- e.printStackTrace();
- return Data.SW_EXCEPTION;
- }
- if(getStatusRspTlvs!=null){
- for(TLV tlv: getStatusRspTlvs)
- {
- TLV tlvVCx = TLV.find(tlv.getNodes(), Data.TAG_VC_ENTRY);
- TLV tlvApkId = TLV.find(tlv.getNodes(), Data.TAG_SP_AID);
- byte ApkId[] = tlvApkId.getValue();
- Log.i(TAG, "SEApkId : " + Utils.bytArrayToHex(ApkId));
- Log.i(TAG, "regApkId : " + Utils.bytArrayToHex(regApkId));
- if (Arrays.equals(ApkId,regApkId)){
- deleteTempVc(Utils.byteArrayToShort(tlvVCx.getValue()),walletName_hash);
- }
- }
- Registry.walletName.remove(j);
- Registry.walletName_hash.remove(j);
- saveRegistry(Registry);
- }
- else{
- Registry.walletName.remove(j);
- Registry.walletName_hash.remove(j);
- saveRegistry(Registry);
- }
- }
- }
- }
-
- Log.i(TAG, "Exit");
- return Data.SW_NO_ERROR;
- }
- else{
- Log.i(TAG, "Exit");
- return Data.SW_REFERENCE_DATA_NOT_FOUND;
- }
- }
- private static boolean inList(int value, int ... values) {
- for(int v: values)
- {
- if (v == value)
- {
- return true;
- }
- }
- return false;
- }
- private byte[] removeTags(byte[] vcData, int ... tags) {
- List<TLV> tlvs = new ArrayList<TLV>();
-
- for(TLV tlv: TLV.parse(vcData, new int[] { 0xA8, 0xE2, 0xF8 }))
- {
- if (!inList(tlv.getTag(), tags))
- {
- tlvs.add(tlv);
- }
- }
- return TLV.make(tlvs);
- }
- }
diff --git a/LTSMClient2.0/src/com/nxp/ltsm/ltsmclient/ltsmRegistry.java b/LTSMClient2.0/src/com/nxp/ltsm/ltsmclient/ltsmRegistry.java
deleted file mode 100644
index 2d1c4b8..0000000
--- a/LTSMClient2.0/src/com/nxp/ltsm/ltsmclient/ltsmRegistry.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2014 NXP Semiconductors
- *
- * 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.nxp.ltsm.ltsmclient;
-
-import java.util.ArrayList;
-
-public class ltsmRegistry {
-
- ArrayList<String> walletName = new ArrayList<String>();
- ArrayList<String> walletName_hash = new ArrayList<String>();
-
- public ltsmRegistry() {
- walletName.clear();
- walletName_hash.clear();
- }
-}
diff --git a/LTSMClient2.0/src/com/nxp/ltsm/ltsmclient/tools/Data.java b/LTSMClient2.0/src/com/nxp/ltsm/ltsmclient/tools/Data.java
deleted file mode 100644
index 82a0961..0000000
--- a/LTSMClient2.0/src/com/nxp/ltsm/ltsmclient/tools/Data.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2014 NXP Semiconductors
- *
- * 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.nxp.ltsm.ltsmclient.tools;
-
-public class Data {
-
-
- /*Status values*/
- public static final int SUCCESS = 0;
- public static final int FAILED = 1;
-
- public static final byte CLA_M4M_LTSM = (byte)0x80;
- public static final byte INS_M4M_LTSM_PROCESS_COMMAND = (byte)0xA0;
- public static final byte INS_M4M_LTSM_PROCESS_SE_RESPONSE = (byte)0xA2;
- public static final short SW_6310_AVAILABLE = (short)0x6310;
- public static final short SW_6330_AVAILABLE = (short)0x6330;
-
- /**
- * Generic Tags
- * */
- public static final short TAG_VC_ENTRY = (short)0x40;
- public static final short TAG_SM_AID = (short)0x42;
- public static final short TAG_SP_SD_AID = (short)0x43;
- public static final short TAG_SP_AID = (short)0x4F;
- public static final short TAG_MF_DF_AID = (short)0xF8;
- public static final short TAG_MF_AID = (short)0xE2;
-
- public static final short TAG_A0_AVAILABLE = (short)0xA0;
- public static final short TAG_A1_AVAILABLE = (short)0xA1;
- public static final short TAG_A2_AVAILABLE = (short)0xA2;
- public static final short TAG_A6_AVAILABLE = (short)0xA6;
- public static final short TAG_F1_AVAILABLE = (short)0xF1;
-
-
- public static final short TAG_48_AVAILABLE = (short)0x48;
- public static final short TAG_4F_AVAILABLE = (short)0x4F;
-
- /*check values*/
- public static final short TAG_PENDING_LOGICAL_CHANNEL = (short)0x56;
- public static final short TAG_PENDING_SE_CONNECTION = (short)0x57;
- public static final short TAG_NOT_PENDING = (short)0x58;
-
-
-
- /**
- *Activation : Reason Codes TAG48 of TAGA2
- * */
- public static final short REASON_CODE_8002 = (short)0x8002;
- public static final short REASON_CODE_8003 = (short)0x8003;
- public static final short REASON_CODE_8004 = (short)0x8004;
- public static final short REASON_CODE_8005 = (short)0x8005;
- public static final short REASON_CODE_8009 = (short)0x8009;
- public static final short REASON_CODE_800B = (short)0x800B;
- public static final short REASON_CODE_800C = (short)0x800C;
-
- public static final int TAG_VC_STATE = 0x9F70;
-
- /**
- * Generic error codes (from ltsm client)
- * */
- public static final short CONDITION_OF_USE_NOT_SATISFIED = (short)0x6980;
- public static final short SW_INVALID_VC_ENTRY = (short)0x69E0;
- public static final short SW_OPEN_LOGICAL_CHANNEL_FAILED = (short)0x69E1;
- public static final short SW_SELECT_LTSM_FAILED = (short)0x69E2;
- public static final short SW_REGISTRY_FULL = (short)0x69E3;
- public static final short SW_IMPROPER_REGISTRY = (short)0x69E4;
- public static final short SW_NO_SET_SP_SD = (short)0x69E5;
- public static final short SW_ALREADY_ACTIVATED = (short)0x69E6;
- public static final short SW_ALREADY_DEACTIVATED = (short)0x69E7;
- public static final short SW_CRS_SELECT_FAILED = (short)0x69E8;
- public static final short SW_SE_TRANSCEIVE_FAILED = (short)0x69E9;
- public static final short SW_REGISTRY_IS_EMPTY = (short)0x69EA;
- public static final short SW_NO_DATA_RECEIVED = (short)0x69EB;
- public static final short SW_EXCEPTION = (short)0x69EC;
- public static final short SW_CONDITION_OF_USE_NOT_SATISFIED = (short)0x6985;
-
-
- public static final short SW_OTHER_ACTIVEVC_EXIST = (short)0x6330;
-
- public static final short SW_CONDITIONAL_OF_USED_NOT_SATISFIED = (short)0x6A80;
- public static final short SW_INCORRECT_PARAM = (short)0x6A86;
- public static final short SW_REFERENCE_DATA_NOT_FOUND = (short)0x6A88;
-
- public static final short SW_VC_IN_CONTACTLESS_SESSION = (short)0x6230;
-
-
- public static final short SW_UNEXPECTED_BEHAVIOR = (short)0x6F00;
-
- /**
- * createVc Response Error Codes (from ltsm application in SE)
- * */
-
- public static final short CREATEVC_PREPERSO_NOT_FOUND = (short)0x6F01;
- public static final short CREATEVC_SET_SP_SD_NOT_SENT = (short)0x6F02;
- public static final short CREATEVC_INVALID_SIGNATURE = (short)0x6F03;
- public static final short CREATEVC_SET_SP_SD_SENT = (short)0x6F04;
- public static final short CREATEVC_REGISTRY_ENTRY_CREATION_FAILED = (short)0x6F05;
-
- /**
- * addAndUpdate/deleteVc Response Error Codes (from ltsm application in SE)
- * */
- public static final short DELETEVC_INVALID_VC_ENTRY = (short)0x6F01; //Same for deleteVc
- public static final short DELETEVC_NO_LTSM_SD_PRESENT = (short)0x6F02;
-
- public static final byte[] openchannel = new byte[] {0x00, 0x70, 0x00, 0x00, 0x01};
- public static final byte[] SelectLTSM = new byte[] {0x00, (byte) 0xA4, 0x04, 0x00, 0x0D, (byte) 0xA0, 0x00, 0x00, 0x03, (byte) 0x96, 0x41, 0x4C, 0x41, 0x01, 0x43, 0x4F, 0x52, 0x01};
- public static final byte[] AID_M4M_LTSM = {(byte)0xA0, (byte)0x00, (byte)0x00, (byte)0x03, (byte)0x96, 0x4D, 0x46, 0x00, (byte)0x4C, 0x54, 0x53, 0x4D, 0x01};
- public static final byte[] selectCRS = new byte[] {(byte)0x00,(byte) 0xA4, 0x04, 0x00, 0x09,(byte) 0xA0, 0x00, 0x00, 0x01, 0x51, 0x43, 0x52, 0x53, 0x00, 0x00 };
- public static final byte[] SERVICE_MANAGER_AID = new byte[] {(byte)0xA0,(byte)0x00,(byte)0x00,(byte)0x03,(byte)0x96,(byte)0x4D,(byte)0x34,(byte)0x4D,(byte)0x24,(byte)0x00,(byte)0x81,(byte)0xDB,(byte)0x69,(byte)0x00};
- public static final byte[] VC_MANAGER_AID = new byte[] {(byte)0xA0,(byte)0x00,(byte)0x00,(byte)0x03,(byte)0x96,(byte)0x4D,(byte)0x34,(byte)0x4D,(byte)0x14,(byte)0x00,(byte)0x81,(byte)0xDB,(byte)0x69,(byte)0x00};
- public static final byte[] NONCONCURRENT_AID_PARTIAL = new byte[] {(byte)0xA0,(byte)0x00,(byte)0x00,(byte)0x03,(byte)0x96,(byte)0x4D,(byte)0x34,(byte)0x4D,(byte)0x14};
-
- public static final byte[] ACTV_LTSM_AID = {(byte)0xA0, (byte)0x00, (byte)0x00, (byte)0x03, (byte)0x96,0x4D,0x34,0x4D, 0x14,0x00,(byte) 0x81,(byte) 0xDB, 0x69,0x00};
- public static final byte[] Set_Status_Activate_Cmd = new byte[] {(byte) 0x80,(byte) 0xF0, 0x01,(byte) 0x01};
- public static final byte[] Set_Status_DeActivate_Cmd = new byte[] {(byte) 0x80,(byte) 0xF0, 0x01,(byte) 0x00};
-
- public static final short SW_NO_ERROR = (short)0x9000;
- public static final short ACTV_VC_EXISTS = (short)0x6330;
- public static final short ACTV_OTHERVC_EXISTS = (short)0x6320;
-
- //public static final byte[] Processing_Error = new byte[] {(byte) 0x4E,(byte) 0x02,(byte) 0x00,(byte) 0x99};
- public static final byte[] NO_ERROR = new byte[] {(byte) 0x4E,(byte) 0x02,(byte) 0x90,(byte) 0x00};
-
- public static final byte[] ERROR_NO_VC_PRESENT = new byte[] {(byte) 0x4E,(byte) 0x02,(byte) 0x01,(byte) 0x99};
- public static final byte[] ERROR_ALREADY_ACTIVATED = new byte[] {(byte) 0x4E,(byte) 0x02,(byte) 0x02,(byte) 0x99};
- public static final byte[] ERROR_ALREADY_DEACTIVATED = new byte[] {(byte) 0x4E,(byte) 0x02,(byte) 0x03,(byte) 0x99};
- public static final byte[] ERROR_NO_VALID_INPUT = new byte[] {(byte) 0x4E,(byte) 0x02,(byte) 0x04,(byte) 0x99};
-
- //VC STATE
-
- public static final byte VC_CREATED = (byte)0x02;
-
-
-}
diff --git a/LTSMClient2.0/src/com/nxp/ltsm/ltsmclient/tools/TLV.java b/LTSMClient2.0/src/com/nxp/ltsm/ltsmclient/tools/TLV.java
deleted file mode 100644
index a640f72..0000000
--- a/LTSMClient2.0/src/com/nxp/ltsm/ltsmclient/tools/TLV.java
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Copyright (C) 2014 NXP Semiconductors
- *
- * 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.nxp.ltsm.ltsmclient.tools;
-import java.io.ByteArrayOutputStream;
-import java.nio.BufferUnderflowException;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.List;
-
-public class TLV
-{
- private final int tag;
- private List<TLV> nodes;
- private final byte[] value;
-
- private TLV(int tag, byte[] value, List<TLV> nodes)
- {
- this.tag = tag;
- this.value = value;
- this.nodes = nodes;
- }
-
- private TLV(int tag, byte[] value)
- {
- this.tag = tag;
- this.value = value;
- }
-
- public static byte[] make(int tag, byte[] value)
- {
- return new TLV(tag, value).getTLV();
- }
-
- public boolean isConstructed()
- {
- return this.nodes != null;
- }
-
- public boolean isPrimitive()
- {
- return this.nodes != null;
- }
-
- public int getTag()
- {
- return this.tag;
- }
-
- public List<TLV> getNodes()
- {
- if (nodes == null)
- {
- throw new RuntimeException("Bad call");
- }
-
- return this.nodes;
- }
-
- public byte[] getValue()
- {
- return this.value;
- }
-
- public byte[] getTLV()
- {
- byte[] t, l;
-
- if ((this.tag & 0xFF00) == 0x0000)
- {
- t = new byte[] { (byte)this.tag };
- }
- else
- {
- t = new byte[] { (byte)(this.tag >> 8), (byte)this.tag };
- }
-
- if (value.length < 128)
- {
- l = new byte[] { (byte)value.length };
- }
- else if (value.length < 256)
- {
- l = new byte[] { (byte)(0x81), (byte)value.length };
- }
- else
- {
- l = new byte[] { (byte)(0x82), (byte)(value.length >> 8), (byte)value.length };
- }
-
- return Utils.append(Utils.append(t, l), value);
- }
-
- public static List<TLV> parse(byte[] buffer)
- {
- return parse(ByteBuffer.wrap(buffer));
- }
-
- public static List<TLV> parse(byte[] buffer, int[] asPrimitiveTags)
- {
- return parse(ByteBuffer.wrap(buffer), asPrimitiveTags);
- }
-
- private static List<TLV> parse(ByteBuffer bb)
- {
- return parse(bb, null);
- }
-
- private static List<TLV> parse(ByteBuffer bb, int[] asPrimitiveTags)
- {
- List<TLV> list = new ArrayList<TLV>();
-
- for(;;)
- {
- int tag;
-
- try
- {
- tag = bb.get() & 0xFF;
- }
- catch(BufferUnderflowException e)
- {
- break;
- }
-
- boolean isPrimitive = (tag & 0x20) == 0x00;
-
- if ((tag & 0x1F) == 0x1F)
- {
- // 2-byte tag
- tag = (tag << 8) + (bb.get() & 0xFF);
- }
-
- if (!isPrimitive && (asPrimitiveTags != null))
- {
- for(int asPrimitiveTag: asPrimitiveTags)
- {
- if (tag == asPrimitiveTag)
- {
- isPrimitive = true;
- break;
- }
- }
- }
-
- int length = bb.get() & 0xFF;
- if (length <= 0x7F)
- {
- // 1-byte length
- }
- else if (length == 0x81)
- {
- length = bb.get() & 0xFF;
- }
- else if (length == 0x82)
- {
- int length1 = bb.get() & 0xFF;
- int length2 = bb.get() & 0xFF;
- length = (length1 << 8) + length2;
- }
- else
- {
- throw new RuntimeException("Bad length field");
- }
-
- byte[] value = new byte[length];
- bb.get(value, 0, value.length);
-
- if (isPrimitive)
- {
- list.add(new TLV(tag, value));
- }
- else
- {
- list.add(new TLV(tag, value, TLV.parse(value, asPrimitiveTags)));
- }
- }
-
- return list;
- }
-
- public static TLV find(List<TLV> nodes, int tag)
- {
- for(TLV tlv: nodes)
- {
- if (tlv.getTag() == tag)
- {
- return tlv;
- }
- }
-
- return null;
- }
-
- public static byte[] createTLV(int tag, byte[] value)
- {
- if (value == null)
- {
- return new byte[0];
- }
- else
- {
- byte[] t, l;
-
- if ((tag & 0xFF00) == 0x0000)
- {
- t = new byte[] { (byte)tag };
- }
- else
- {
- t = new byte[] { (byte)(tag >> 8), (byte)tag };
- }
-
- if (value.length < 128)
- {
- l = new byte[] { (byte)value.length };
- }
- else if (value.length < 256)
- {
- l = new byte[] { (byte)(0x81), (byte)value.length };
- }
- else
- {
- l = new byte[] { (byte)(0x82), (byte)(value.length >> 8), (byte)value.length };
- }
-
- return Utils.append(Utils.append(t, l), value);
- }
- }
-
- public static byte[] make(List<TLV> tlvs)
- {
- try
- {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
-
- for(TLV tlv: tlvs)
- {
- out.write(tlv.getTLV());
- }
-
- return out.toByteArray();
- }
- catch(Exception e)
- {
- return null;
- }
- }
-
-}
diff --git a/LTSMClient2.0/src/com/nxp/ltsm/ltsmclient/tools/Utils.java b/LTSMClient2.0/src/com/nxp/ltsm/ltsmclient/tools/Utils.java
deleted file mode 100644
index 0c33093..0000000
--- a/LTSMClient2.0/src/com/nxp/ltsm/ltsmclient/tools/Utils.java
+++ /dev/null
@@ -1,710 +0,0 @@
-/*
- * Copyright (C) 2014 NXP Semiconductors
- *
- * 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.nxp.ltsm.ltsmclient.tools;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
-import java.lang.reflect.Field;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-import java.util.regex.Pattern;
-
-import org.apache.commons.codec.Charsets;
-import org.apache.commons.codec.binary.Hex;
-
-import android.app.ActivityManager;
-import android.app.ActivityManager.RunningAppProcessInfo;
-import android.app.ActivityManager.RunningServiceInfo;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.Signature;
-import android.os.Build;
-import android.os.Environment;
-import android.util.Log;
-import android.view.InflateException;
-
-public class Utils {
- /**
- * Convert a byte array to an hexadecimal string
- *
- * @param data
- * the byte array to be converted
- * @return the output string
- */
- public static String arrayToHex(byte[] data) {
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < data.length; i++) {
- String bs = Integer.toHexString(data[i] & 0xFF).toUpperCase();
- if (bs.length() == 1) {
- sb.append(0);
- }
- sb.append(bs);
- sb.append(" ");
- }
- return sb.toString();
- }
-
- /**
- * Convert an hexadecimal string into a byte array. Each byte in ethe
- * hexadecimal string being separated by spaces or not (eg. s = "65 A0 12"
- * <=> "65A012").
- *
- * @param s
- * the string to be converted
- * @return the corresponding byte array
- * @throws IllegalArgumentException
- * if not a valid string representation of a byte array
- */
- public static byte[] hexToArray(String s) {
-
- // check the entry
- Pattern p = Pattern.compile("([a-fA-F0-9]{2}[ ]*)*");
- boolean valid = p.matcher(s).matches();
-
- if (!valid) {
- throw new IllegalArgumentException("not a valid string representation of a byte array :" + s);
- }
-
- String hex = s.replaceAll(" ", "");
- byte[] tab = new byte[hex.length() / 2];
- for (int i = 0; i < tab.length; i++) {
- tab[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16);
- }
- return tab;
- }
-
- /**
- * Convert a byte array into ASCII string representation.
- *
- * @param buf
- * The bytes to format.
- * @return ASCII string representation of the specified bytes.
- * @throws UnsupportedEncodingException
- */
- public static String toAsciiString(byte[] buf) throws UnsupportedEncodingException {
- String ascii = null;
- if (buf != null) {
- ascii = new String(buf, "US-ASCII");
- // Check the characters
- char[] charArray = ascii.toCharArray();
- for (int i = 0; i < charArray.length; i++) {
- // Show null character as blank space
- if (charArray[i] == (char) 0x00) {
- charArray[i] = ' ';
- }
- }
- ascii = new String(charArray);
- }
- return ascii;
- }
-
- /**
- * Convert the byte array to an int starting from the given offset.
- *
- * @param b
- * The byte array
- * @param offset
- * The array offset
- * @return The integer
- */
- public static int byteArrayToInt(byte[] b) {
- if (b.length == 1) {
- return b[0] & 0xFF;
- } else if (b.length == 2) {
- return ((b[0] & 0xFF) << 8) + (b[1] & 0xFF);
- } else if (b.length == 3) {
- return ((b[0] & 0xFF) << 16) + ((b[1] & 0xFF) << 8) + (b[2] & 0xFF);
- } else if (b.length == 4)
- return (b[0] << 24) + ((b[1] & 0xFF) << 16) + ((b[2] & 0xFF) << 8) + (b[3] & 0xFF);
- else
- throw new IndexOutOfBoundsException();
- }
-
- public static String getTimestampString(byte[] timestamp) {
- if (timestamp == null || timestamp.length < 6) {
- return "?";
- }
- Log.i("TimeStamp Parser", "Timestampbytes: " + Utils.arrayToHex(timestamp));
- String timestampSting = "";
- int day = timestamp[0] & 0xFF;
- int month = timestamp[1] & 0xFF;
- byte[] yearBytes = new byte[2];
- System.arraycopy(timestamp, 2, yearBytes, 0, 2);
- int year = Utils.byteArrayToInt(yearBytes);
- int hours = timestamp[4] & 0xFF;
- int mins = timestamp[5] & 0xFF;
-
- // Check for correct Values
- if (day < 1 || day > 31 || month < 1 || month > 12 || year < 1990 || hours < 0 || hours > 24 || mins < 0 || mins > 59) {
- return "?";
- } else {
- timestampSting = String.valueOf(day) + "." + String.valueOf(month) + "." + String.valueOf(year) + " " + String.valueOf(hours) + ":"
- + String.valueOf(mins);
- }
- SimpleDateFormat dateFormat = new SimpleDateFormat ("d.M.y H:m");
- try {
- Date timestampDate = dateFormat.parse(timestampSting);
- dateFormat = new SimpleDateFormat("dd.MM.yyyy HH:mm");
- return dateFormat.format(timestampDate);
- } catch (ParseException e) {
- return "?";
- }
- }
- public static int CompareArrays(short[] array1, int array1pos, short[] array2, int array2pos, int len) {
- int i, j;
- for (i = array1pos,j = array2pos; j < len; i++,j++) {
- if (array1[i] != array2[j]) {
- return Data.FAILED;
- }
- }
- if(((i - array1pos ) == len) && ((j - array2pos ) == len)){
- return Data.SUCCESS;
- }
- else{
- return Data.FAILED;
- }
- }
- public static int ShorttoByteArraycopy(short[] src, int srcpos, byte[] dest, int destpos, int len) {
- String TAG = "LTSMlib:ShorttoIntArraycopy";
-
- if( dest.length < len ){
- Log.i(TAG, "dest array length less than length to be copied ");
- return Data.FAILED;
- }
- int i, j;
- for (i = srcpos,j = destpos; j < len; i++,j++) {
- dest[j] = (byte) src[i];
- }
- if(j == len){
- return Data.SUCCESS;
- }
- else{
- return Data.FAILED;
- }
- }
- public static int BytetoShortArraycopy(byte[] src, int srcpos, short[] dest, int destpos, int len) {
- String TAG = "LTSMlib:ShorttoIntArraycopy";
-
- if( dest.length < len ){
- Log.i(TAG, "dest array length less than length to be copied ");
- return Data.FAILED;
- }
- int i, j;
- for (i = srcpos,j = destpos; j < len; i++,j++) {
- dest[j] = src[i];
- }
- if(j == len){
- return Data.SUCCESS;
- }
- else{
- return Data.FAILED;
- }
- }
-
- public static byte[] makeCAPDU(int cla, int ins, int p1, int p2, byte[] cdata)
- {
- byte[] l,t;
- if (cdata == null)
- {
- return new byte[] { (byte)cla, (byte)ins, (byte)p1, (byte)p2, 0 };
- }
- // else if (cdata.length > 128)
- // {
- // l = new byte[] { (byte)(0x81), (byte)cdata.length };
- // t = append(new byte[] { (byte)cla, (byte)ins, (byte)p1, (byte)p2}, l);
- // return append(t, cdata);
- // }
- else
- {
- return append(new byte[] { (byte)cla, (byte)ins, (byte)p1, (byte)p2, (byte)cdata.length}, cdata);
- }
- }
-
- public static byte[] append(byte[] a, byte[] b)
- {
- byte[] result = new byte[a.length + b.length];
- System.arraycopy(a, 0, result, 0, a.length);
- System.arraycopy(b, 0, result, a.length, b.length);
- return result;
- }
-
- public static byte[] extract(byte[] buffer, int offset, int length)
- {
- byte[] result = new byte[length];
- System.arraycopy(buffer, offset, result, 0, length);
- return result;
- }
-
- public static short getSW(byte[] rapdu)
- {
- String TAG = "Utils:checkRegistryAvail";
-
- if(rapdu.length == 0)
- {
- Log.d(TAG, "No SW available");
- return Data.SW_UNEXPECTED_BEHAVIOR;
-
- }
- byte sw1 = rapdu[rapdu.length - 2];
- byte sw2 = rapdu[rapdu.length - 1];
- return (short)((sw1 << 8) + (sw2 & 0xFF));
- }
-
- public static byte[] getRDATA(byte[] rapdu)
- {
- return extract(rapdu, 0, rapdu.length - 2);
- }
-
- public static byte adjustCLA(byte cla, byte lcnum)
- {
- return (byte)((cla & ~0x03) | (lcnum & 0x03));
- }
-
- public static void saveArray(int[] channel_id, String arrayName, Context mContext) {
- SharedPreferences.Editor edit= mContext.getSharedPreferences(arrayName, Context.MODE_PRIVATE).edit();
- edit.putInt("Count", channel_id.length);
- int count = 0;
- for (int i: channel_id){
- edit.putInt("IntValue_" + count++, i);
- }
- edit.commit();
- }
-
- public static int[] loadArray(String arrayName, Context mContext) {
- int[] ret;
- SharedPreferences prefs = mContext.getSharedPreferences(arrayName, Context.MODE_PRIVATE);
- int count = prefs.getInt("Count", 0);
- ret = new int[count];
- for (int i = 0; i < count; i++){
- ret[i] = prefs.getInt("IntValue_"+ i, i);
- }
- return ret;
- }
-
- public static void saveInt(int cnt, String name, Context mContext) {
- SharedPreferences.Editor edit= mContext.getSharedPreferences(name, Context.MODE_PRIVATE).edit();
- edit.putInt("chnl_cnt", cnt);
- edit.commit();
- }
-
-
- public static int loadInt(String name, Context mContext) {
- SharedPreferences prefs = mContext.getSharedPreferences(name, Context.MODE_PRIVATE);
- int savedCnt = prefs.getInt("chnl_cnt", 0);
- return savedCnt;
- }
-
- public static String bytArrayToHex(byte[] a) {
- StringBuilder sb = new StringBuilder();
- for(byte b: a)
- sb.append(String.format("%02X", b&0xff));
- return sb.toString();
- }
-
-
- public static boolean checkRegistryAvail(Context context) {
- String TAG = "Utils:checkRegistryAvail";
- Log.i(TAG, "Enter");
- File f = new File(
- "/data/data/com.nxp.ltsm.ltsmclient/shared_prefs/Reg.xml");
- if (f.exists()){
- Log.d(TAG, "LTSM Registry exist");
- return true;
- }
- else{
- Log.d(TAG, "not exists");
- return false;
- }
- }
-
- public static boolean checkRegBackupAvail(){
- String TAG = "Utils:checkRegistryAvail";
- Log.i(TAG, "Enter");
- File f = new File(
- Environment.getExternalStorageDirectory().getPath()+"/ltsmRegBackup/Reg.xml");
- if (f.exists()){
- Log.d(TAG, "LTSM Registry backup exist");
- return true;
- }
- else{
- Log.d(TAG, "LTSM Registry backup doesnt exist");
- return false;
- }
- }
-
-
- public static String shaSignature(String pkg, Context context){
- String TAG = "Utils:createSha";
- String hashString = "";
- PackageManager pm = context.getPackageManager();
- try {
- PackageInfo info = pm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES);
- Signature[] sigs = info.signatures;
- for (int i = 0; i < sigs.length; i++) {
- hashString = hashString+sigs[i].toCharsString();
- }
- Log.i(TAG,"pkg " + pkg);
- Log.i(TAG,"hashString " + hashString);
- if (hashString == "") {
- return hashString;
- }
- return makeShaSignature(hashString);
- }catch(Exception e){
- e.printStackTrace();
- }
- return null;
- }
-
- public static String makeShaSignature(String hashString){
- String TAG = "Utils:retSha";
- StringBuffer sb = new StringBuffer();
-
- try {
- MessageDigest md = MessageDigest.getInstance("SHA-1");
- md.update(hashString.getBytes());
-
- byte byteData[] = md.digest();
-
- for (int i = 0; i < byteData.length; i++) {
- sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
- }
- Log.i(TAG,"sb.toString() " + sb.toString());
- return new String(Hex.encodeHex(byteData));
- // return sb.toString();
- //return byteData.toString();
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
-
- }
-
- public static String createSha(String pkg){
- String TAG = "Utils:createSha";
- StringBuffer sb = new StringBuffer();
- try {
- MessageDigest md = MessageDigest.getInstance("SHA-1");
- md.update(pkg.getBytes());
-
- byte byteData[] = md.digest();
-
- for (int i = 0; i < byteData.length; i++) {
- sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
- }
- return new String(Hex.encodeHex(byteData));
- // return sb.toString();
- //return byteData.toString();
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
-
- }
- public static byte[] getApkHash(String apkName) {
- try
- {
- MessageDigest md = MessageDigest.getInstance("SHA-1");
- return md.digest(toUTF8(apkName));
- }
- catch(NoSuchAlgorithmException e)
- {
- return null;
- }
- }
- public static byte[] parseHexString(String s) {
- try
- {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- while(!s.isEmpty())
- {
- out.write(Integer.parseInt(s.substring(0, 2), 16));
- s = s.substring(2);
- }
- return out.toByteArray();
- }
- catch(Exception e)
- {
- return null;
- }
- }
- public static byte[] toUTF8(String s) {
- if (s != null)
- {
- try
- {
- return s.getBytes("UTF-8");
- }
- catch(UnsupportedEncodingException e)
- {
- // Should never occur!
- }
- }
- return null;
- }
- public static String getCallingAppPkg(Context context) {
- String TAG = "getCallingAppPkg";
- String packageName = null;
- if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT_WATCH) {
-
- packageName = getForeGroundL(context);
- }
- else
- {
- packageName = getForeGroundKK(context);
- }
- Log.i(TAG,"packageName : " + packageName);
- return packageName;
- }
-
- static String getForeGroundKK(Context context)
- {
- ActivityManager am = (ActivityManager) context.getSystemService(context.ACTIVITY_SERVICE);
- // get the info from the currently running task
- List< ActivityManager.RunningTaskInfo > taskInfo = am.getRunningTasks(1);
-
- Log.d("topActivity", "CURRENT Activity ::"
- + taskInfo.get(0).topActivity.getClassName());
- String s = taskInfo.get(0).topActivity.getClassName();
-
- ComponentName componentInfo = taskInfo.get(0).topActivity;
- componentInfo.getPackageName();
- return componentInfo.getPackageName();
- }
-
- static String getForeGroundL(Context context)
- {
- final int PROCESS_STATE_TOP = 2;
- RunningAppProcessInfo currentInfo = null;
- Field field = null;
- try {
- field = RunningAppProcessInfo.class.getDeclaredField("processState");
- } catch (Exception e) {e.printStackTrace(); }
- ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
- List<RunningAppProcessInfo> appList = am.getRunningAppProcesses();
- for (RunningAppProcessInfo app : appList) {
- if (app.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND &&
- app.importanceReasonCode == 0 ) {
- Integer state = null;
- try {
- state = field.getInt( app );
- } catch (Exception e) {e.printStackTrace(); }
- if (state != null && state == PROCESS_STATE_TOP) {
- currentInfo = app;
- break;
- }
- }
- }
- return currentInfo.processName;
- }
-
- public static List getINstalledApps(Context context){
- List<PackageInfo> apps = context.getPackageManager().getInstalledPackages(0);
- return apps;
- }
-
- public static byte[] shortToByteArr(short vC_Entry) {
- String TAG = "shortToByteArr";
- Log.i(TAG,"vC_Entry)" + vC_Entry);
- byte[] vcEntryBytes = new byte[2];
- vcEntryBytes[1] = (byte)(vC_Entry & 0xff);
- vcEntryBytes[0] = (byte)((vC_Entry >> 8) & 0xff);
- return vcEntryBytes;
-
- }
-
- public static byte[] getValue(byte Tag, byte[] rapdu) {
- String TAG = "Utils:getValue";
- byte[] retData = null;
- for(int i = 0 ; i< rapdu.length-1 ; i++ ){
- if(Tag == rapdu[i]){
- retData = new byte[rapdu[i+1]];
- System.arraycopy(rapdu, i+2, retData, 0, rapdu[i+1]);
- Log.i(TAG,"retData" + bytArrayToHex(retData));
- break;
- }
- }
- return retData;
- }
-
- public static byte[] getVcCount(byte[] recvData) {
- byte[] temp = getValue((byte)0x6F,recvData);
- byte[] temp1 = new byte[temp.length - (temp[1]+2)];
- System.arraycopy(temp, (temp[1]+2), temp1, 0, temp1.length);
- temp = getValue((byte)0xA5,temp1);
- temp = getValue((byte)0x10,temp);
- return temp;
- }
-
- public static boolean chekPersonalize(byte[] vCData) {
- String TAG = "Utils:getValue";
- Log.i(TAG,"Enter");
- byte[] temp = getValue((byte)0x46,vCData);
- if((temp[0]&(byte)0x02) == (byte)0x02){
- return true;
- }
- else{
- return false;
- }
- }
- public static byte[] createStatusCode(short statusCode){
- byte [] resp = Utils.shortToByteArr(statusCode);
- return Utils.append(new byte[]{(byte)0x4E,(byte)resp.length}, resp);
- }
-
-
- public static short byteArrayToShort(byte[] data)
- {
- return (short)((data[0]<<8) | (data[1]));
- }
-
- public static int lenOfTLV(byte[] tlv, int offset)
- {
- int tlvLen = 0;
-
- if(tlv != null)
- {
- if(tlv[offset] == 0x82)
- {
- tlvLen = tlv[offset+1]<<8|tlv[offset+2];
- }
- else if(tlv[offset] == 0x81)
- {
- tlvLen = tlv[offset+1];
- }
- else if(tlv[offset] <= 0x7F)
- {
- tlvLen = tlv[offset];
- }
- else
- {
- /*Error case*/
- }
- }
- return tlvLen;
- }
-
- public static int skipLenTLV(byte[] tlv, int offset)
- {
- int skipLen = 1;
-
- if(tlv != null)
- {
- if(tlv[offset] == 0x82)
- {
- skipLen = 3;
- }
- else if(tlv[offset] == 0x81)
- {
- skipLen = 2;
- }
- else if(tlv[offset] <= 0x7F)
- {
- skipLen = 1;
- }
- else
- {
- /*Error case*/
- }
- }
- return skipLen;
- }
-
- public static byte[] findNextAID(byte[] byteArr, int offset)
- {
- byte[] aidBytes = new byte[byteArr[offset]+2];
-
- for(int i=0;i< (byteArr[offset]+(byte)2);i++)
- {
- /*Modified for Including 0x4F tag and length*/
- aidBytes[i] = byteArr[offset-(byte)1+i];
- }
- return aidBytes;
- }
- public static void exportReg(){
- String pathsrc = "/data/data/com.nxp.ltsm.ltsmclient/shared_prefs/Reg.xml";
- String pathdest = Environment.getExternalStorageDirectory().getPath()+"/ltsmRegBackup/";
-
- File ip = new File(pathsrc);
- File op = new File(pathdest);
-
- copyFile(pathsrc,pathdest);
- }
-
- public static void importReg(){
- String pathdest = "/data/data/com.nxp.ltsm.ltsmclient/shared_prefs/";
- String pathsrc = Environment.getExternalStorageDirectory().getPath()+"/ltsmRegBackup/Reg.xml";
-
- File ip = new File(pathsrc);
- File op = new File(pathdest);
-
- copyFile(pathsrc,pathdest);
- }
-
- public static void copyFile(String pathsrc, String pathdest)
- throws InflateException {
- String TAG = "copyFile";
- String filepath = "";
- String filename = "Reg.xml";
-
- File sourceLocation = new File(pathsrc);
- File targetLocation = new File(pathdest);
- try {
- Log.i(TAG, "Enter");
- if(!sourceLocation.exists()){
- Log.i(TAG, "sourceLocation "+pathsrc+" Does not exist..!!");
- return;
- }
- if (!targetLocation.exists()) {
- Log.i(TAG, "Creating Target Directory");
- targetLocation.mkdirs();
- }
- filepath = pathdest+filename;
- targetLocation = new File(filepath);
- InputStream in = new FileInputStream(sourceLocation);
-
- OutputStream out = new FileOutputStream(targetLocation);
-
- // Copy the bits from instream to outstream
- byte[] buf = new byte[1024];
- int len;
- while ((len = in.read(buf)) > 0) {
- out.write(buf, 0, len);
- }
- in.close();
- out.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
-}
diff --git a/LTSMClient2.0/src/com/nxp/ltsm/ltsmclient/tools/VCDescriptionFile.java b/LTSMClient2.0/src/com/nxp/ltsm/ltsmclient/tools/VCDescriptionFile.java
deleted file mode 100644
index e443044..0000000
--- a/LTSMClient2.0/src/com/nxp/ltsm/ltsmclient/tools/VCDescriptionFile.java
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * Copyright (C) 2014 NXP Semiconductors
- *
- * 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.nxp.ltsm.ltsmclient.tools;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.List;
-
-import org.apache.commons.codec.DecoderException;
-import org.apache.commons.codec.binary.Hex;
-
-import android.content.Context;
-import android.util.Log;
-
-
-public class VCDescriptionFile {
-
-
- public VCDescriptionFile(){
- }
-
- public static byte[] createVc(byte[] VCData,String appName, short VC_Entry)
- {
- String TAG = "VCDescriptionFile:createVC";
- Log.i(TAG, "Enter");
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- byte[] VC_EntryBytes = Utils.shortToByteArr(VC_Entry);
- try{
- out.write(createTlv(0x4F, Hex.decodeHex(appName.toCharArray())));
- out.write(createTlv(0x40, VC_EntryBytes));
- return(createTlv(0x70,Utils.append(out.toByteArray(),VCData)));
- }catch(Exception e){
- e.printStackTrace();
- }
- return null;
- }
-
-
- public static byte[] createF8Vc(String appName, short vcEntry,byte[] mfdfaid, byte[] cltecap)
- {
- String TAG = "VCDescriptionFile:createVC";
- Log.i(TAG, "Enter");
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- byte[] apkId = null;
- try {
- apkId = Hex.decodeHex(appName.toCharArray());
- } catch (DecoderException e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
- return null;
- }
- try
- {
- out.write(TLV.createTLV(0x4F, apkId));
- out.write(TLV.createTLV(0x40, new byte[] { (byte)(vcEntry >> 8), (byte)(vcEntry) }));
- out.write(TLV.createTLV(0xF8, mfdfaid));
- out.write(TLV.createTLV(0xE2, cltecap));
- return TLV.createTLV(0x74, out.toByteArray());
- }
- catch(IOException e)
- {
- e.printStackTrace();
- System.exit(1);
- return null;
- }
- }
-
- public static byte[] deleteVc(String appName,short VC_Entry)
- {
- String TAG = "VCDescriptionFile:deleteVc";
- Log.i(TAG, "Enter");
- byte[] VC_EntryBytes = Utils.shortToByteArr(VC_Entry);
- try
- {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
-
- out.write(createTlv(0x4F, Hex.decodeHex(appName.toCharArray())));
- out.write(createTlv(0x40, VC_EntryBytes));
- Log.i(TAG, "Exit");
- return createTlv(0x71, out.toByteArray());
- }
- catch(Exception e)
- {
- e.printStackTrace();
- return null;
- }
- }
-
-
- public static byte[] createTlv(int tag, byte[] value)
- {
- if ((value == null) || (value.length == 0))
- {
- return new byte[0];
- }
- else
- {
- byte[] t, l;
-
- if ((tag & 0xFF00) == 0x0000)
- {
- t = new byte[] { (byte)tag };
- }
- else
- {
- t = new byte[] { (byte)(tag >> 8), (byte)tag };
- }
-
- if (value.length < 128)
- {
- l = new byte[] { (byte)value.length };
- }
- else if (value.length < 256)
- {
- l = new byte[] { (byte)(0x81), (byte)value.length };
- }
- else
- {
- l = new byte[] { (byte)(0x82), (byte)(value.length >> 8), (byte)value.length };
- }
-
- return Utils.append(Utils.append(t, l), value);
- }
- }
-
- public static byte[] parseHexProperty(String name, String key)
- {
- String TAG = "VCDescriptionFile:parseHexProperty";
- String value = key;
-
- try
- {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
-
- while(value.length() > 0)
- {
- out.write(Integer.parseInt(value.substring(0, 2), 16));
- value = value.substring(2);
- }
-
- return out.toByteArray();
- }
- catch(Exception e)
- {
- e.printStackTrace();
- Log.i(TAG, "Property %s is malformed" + name);
- System.exit(1);
- return null;
- }
- }
-
- public static byte[] CreateVCResp(short vCEntry, byte[] VC_UID) {
- byte[] VC_EntryBytes = Utils.shortToByteArr(vCEntry);
- byte[] stat = new byte[] {(byte)0x90,(byte)0x00};
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- try {
- out.write(createTlv(0x40, VC_EntryBytes));
- out.write(createTlv(0x41, VC_UID));
- out.write(createTlv(0x4E, stat));
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- return out.toByteArray();
- }
-
- public static byte[] CreatePersonalizeData(byte[] VCData, String pkgName,String appShaName, short VC_Entry, Context context) {
- String TAG = "VCDescriptionFile:cCreatePersonalizeData";
- Log.i(TAG, "Enter");
- int i = VCData.length;
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- byte[] VC_EntryBytes = Utils.shortToByteArr(VC_Entry);
- try{
- out.write(createTlv(0x4F, Hex.decodeHex(appShaName.toCharArray())));
- out.write(createTlv(0x40, VC_EntryBytes));
- out.write(Utils.append(VCData,createTlv(0xC1, Hex.decodeHex(Utils.shaSignature(pkgName, context).toCharArray()))));
- return(createTlv(0x73,out.toByteArray()));
- }catch(Exception e){
- e.printStackTrace();
- }
- return null;
- }
-
- public static byte[] AddandUpdateMDAC(byte[] vCData, short vcEntry, String appName) {
- String TAG = "VCDescriptionFile:AddandUpdateMDAC";
- Log.i(TAG, "Enter");
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- byte[] VC_EntryBytes = Utils.shortToByteArr(vcEntry);
- try{
- out.write(createTlv(0x4F, Hex.decodeHex(appName.toCharArray())));
- out.write(createTlv(0x40, VC_EntryBytes));
- return(createTlv(0x72,Utils.append(out.toByteArray(),vCData)));
- }catch(Exception e){
- e.printStackTrace();
- }
- return null;
- }
-
- public static byte[] CreateMFData(byte[] vCData, short vCEntry) {
- String TAG = "VCDescriptionFile:CreateMFData";
- Log.i(TAG, "Enter");
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- byte[] VC_EntryBytes = Utils.shortToByteArr(vCEntry);
- try{
- out.write(createTlv(0x40, VC_EntryBytes));
- out.write(vCData);
- return(createTlv(0x78, out.toByteArray()));
- }catch(Exception e){
- e.printStackTrace();
- }
- return null;
- }
-
- public static byte[] formVCList(int VCEntry, String AppName){
- String TAG = "VCDescriptionFile:FormVCList";
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- byte[] VC_EntryBytes = Utils.shortToByteArr((short)VCEntry);
- try{
- out.write(createTlv(0x40, VC_EntryBytes));
- out.write(createTlv(0x4F, AppName.getBytes("UTF-8")));
- return createTlv(0x61, out.toByteArray());
-
- }catch(Exception e){
- e.printStackTrace();
- }
- return null;
- }
-
- public static byte[] GetVC()
- {
- return TLV.createTLV(0x75, new byte[0]);
- }
- public static byte[] getVcListResp(List<TLV> getStatusRspTlvs) {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- try {
- for(TLV tlv: getStatusRspTlvs)
- {
- TLV tlv_VCstate = TLV.find(tlv.getNodes(), Data.TAG_VC_STATE);
- if(tlv_VCstate.getValue()[0] == Data.VC_CREATED){
- TLV tlvVCx = TLV.find(tlv.getNodes(), Data.TAG_VC_ENTRY);
- TLV tlvApkId = TLV.find(tlv.getNodes(), Data.TAG_SP_AID);
- out.write(
- TLV.createTLV(0x61, Utils.append(
- tlvVCx.getTLV(),
- tlvApkId.getTLV()
- ))
- );
- }
- }
- }catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return out.toByteArray();
- }
-}
diff --git a/Readme.txt b/Readme.txt
deleted file mode 100644
index 3c334cb..0000000
--- a/Readme.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-eseclient integration steps with the MW (Nfc/Spi)release
-
-1. Copy the intf folder from eseclient folder and place it under directory frameworks/base/core/java/com/nxp/
-2. Copy the eseclient folder and place it under directory frameworks/base/core/java/com/nxp/
-3. delete the intf folder from eseclient
-4. compile the framwork code base.
-
-smart-card-service
-
-1.Copy the files from smart-card-service/src/org/simalliance/openmobileapi/service/terminals_l_dev/ and replace in smart-card-service/src/org/simalliance/openmobileapi/service/terminals/
-2.Remove the folder smart-card-service/src/org/simalliance/openmobileapi/service/terminals_l_dev
-3.In Android.mk change LOCAL_JAVA_LIBRARIES := core framework org.simalliance.openmobileapi to LOCAL_JAVA_LIBRARIES := framework org.simalliance.openmobileapi
-
-ltsm-client
-
-1.Place LTSMClient directory under <Android build env>/packages/apps/
-2.Compile the application
-3.Install generated ltsmclient.apk
-
-
-
diff --git a/eseclient/EseClientManager.java b/com/nxp/eseclient/EseClientManager.java
similarity index 100%
rename from eseclient/EseClientManager.java
rename to com/nxp/eseclient/EseClientManager.java
diff --git a/eseclient/EseClientServicesAdapter.java b/com/nxp/eseclient/EseClientServicesAdapter.java
similarity index 100%
rename from eseclient/EseClientServicesAdapter.java
rename to com/nxp/eseclient/EseClientServicesAdapter.java
diff --git a/eseclient/EseClientServicesAdapterBuilder.java b/com/nxp/eseclient/EseClientServicesAdapterBuilder.java
similarity index 100%
rename from eseclient/EseClientServicesAdapterBuilder.java
rename to com/nxp/eseclient/EseClientServicesAdapterBuilder.java
diff --git a/eseclient/JCOPOsUpdater.java b/com/nxp/eseclient/JCOPOsUpdater.java
similarity index 100%
rename from eseclient/JCOPOsUpdater.java
rename to com/nxp/eseclient/JCOPOsUpdater.java
diff --git a/eseclient/LoaderService.java b/com/nxp/eseclient/LoaderService.java
similarity index 100%
rename from eseclient/LoaderService.java
rename to com/nxp/eseclient/LoaderService.java
diff --git a/eseclient/LtsmService.java b/com/nxp/eseclient/LtsmService.java
similarity index 100%
rename from eseclient/LtsmService.java
rename to com/nxp/eseclient/LtsmService.java
diff --git a/eseclient/intf/IJcopService.aidl b/eseclient/intf/IJcopService.aidl
deleted file mode 100644
index 0cad16c..0000000
--- a/eseclient/intf/IJcopService.aidl
+++ /dev/null
@@ -1,27 +0,0 @@
- /*
- * Copyright (C) 2015 NXP Semiconductors
- *
- * 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.nxp.intf;
-
-import android.os.Bundle;
-/**
- * {@hide}
- */
-interface IJcopService {
-
- /* JCOP Service API */
- int jcopOsDownload(in String pkg);
-}
diff --git a/eseclient/intf/ILoaderService.aidl b/eseclient/intf/ILoaderService.aidl
deleted file mode 100644
index 87de97f..0000000
--- a/eseclient/intf/ILoaderService.aidl
+++ /dev/null
@@ -1,31 +0,0 @@
- /*
- * Copyright (C) 2015 NXP Semiconductors
- *
- * 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.nxp.intf;
-
-import android.os.Bundle;
-/**
- * {@hide}
- */
-interface ILoaderService {
-
- /* Applet load applet API */
- int appletLoadApplet(in String pkg, in String choice);
- int getListofApplets(in String pkg, out String[] name);
- byte[] getKeyCertificate();
- byte[] lsExecuteScript(in String srcIn, in String rspOut);
- byte[] lsGetVersion();
-}
diff --git a/eseclient/intf/INxpExtrasService.aidl b/eseclient/intf/INxpExtrasService.aidl
deleted file mode 100644
index 702b92c..0000000
--- a/eseclient/intf/INxpExtrasService.aidl
+++ /dev/null
@@ -1,29 +0,0 @@
- /*
- * Copyright (C) 2015 NXP Semiconductors
- *
- * 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.nxp.intf;
-
-import android.os.Bundle;
-/**
- * {@hide}
- */
-interface INxpExtrasService{
- Bundle open(in String pkg, IBinder b);
- Bundle close(in String pkg, IBinder b);
- Bundle transceive(in String pkg, in byte[] data_in);
- byte[] getSecureElementUid(String pkg);
- boolean isEnabled();
- }
diff --git a/eseclient/intf/IeSEClientServicesAdapter.aidl b/eseclient/intf/IeSEClientServicesAdapter.aidl
deleted file mode 100644
index 300e6cd..0000000
--- a/eseclient/intf/IeSEClientServicesAdapter.aidl
+++ /dev/null
@@ -1,28 +0,0 @@
- /*
- * Copyright (C) 2015 NXP Semiconductors
- *
- * 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.nxp.intf;
-
-import com.nxp.intf.INxpExtrasService;
-import com.nxp.intf.ILoaderService;
-import com.nxp.intf.IJcopService;
- /**
- * {@hide}
- */
-interface IeSEClientServicesAdapter {
- INxpExtrasService getNxpExtrasService();
- ILoaderService getLoaderService();
- IJcopService getJcopService();
- }
\ No newline at end of file
diff --git a/smart-card-service/Android.mk b/smart-card-service/Android.mk
deleted file mode 100644
index 8e4f18c..0000000
--- a/smart-card-service/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_AIDL_INCLUDES := packages/apps/SmartCardService/openmobileapi/src/org/simalliance/openmobileapi/service
-
-LOCAL_PACKAGE_NAME := SmartcardService
-LOCAL_CERTIFICATE := platform
-
-LOCAL_JAVA_LIBRARIES := core framework org.simalliance.openmobileapi
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/smart-card-service/AndroidManifest.xml b/smart-card-service/AndroidManifest.xml
deleted file mode 100644
index 2a0780c..0000000
--- a/smart-card-service/AndroidManifest.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="org.simalliance.openmobileapi.service"
- android:sharedUserId="org.simalliance.uid.openmobileapi"
- android:versionCode="5"
- android:versionName="3.2.1">
-
- <permission android:label="SmartcardServicePermission label"
- android:protectionLevel="dangerous"
- android:name="org.simalliance.openmobileapi.SMARTCARD">
- </permission>
-
- <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
- <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
- <uses-permission android:name="android.permission.NFC" />
- <uses-permission android:name="com.android.nfc.permission.NFCEE_ADMIN" />
-
- <application android:label="SmartcardService">
- <uses-library android:name="org.simalliance.openmobileapi" android:required="true" />
- <service android:enabled="true"
- android:name="org.simalliance.openmobileapi.service.SmartcardService"
- android:process=":remote"
- android:permission="org.simalliance.openmobileapi.SMARTCARD">
- <intent-filter>
- <action android:name="org.simalliance.openmobileapi.service.ISmartcardService" />
- </intent-filter>
- </service>
- <receiver android:name="org.simalliance.openmobileapi.service.SmartcardServiceBootCompletedBroadcastReceiver">
- <intent-filter>
- <action android:name="android.intent.action.BOOT_COMPLETED"/>
- </intent-filter>
- </receiver>
- </application>
-</manifest>
diff --git a/smart-card-service/CleanSpec.mk b/smart-card-service/CleanSpec.mk
deleted file mode 100644
index f9dd75a..0000000
--- a/smart-card-service/CleanSpec.mk
+++ /dev/null
@@ -1,5 +0,0 @@
-$(call add-clean-step, rm -f $(PRODUCT_OUT)/system/app/SmartCardService.apk)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/APPS/SmartcardService_intermediates)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/ETC/org.simalliance.openmobileapi.xml_intermediates)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/JAVA_LIBRARIES/org.simalliance.openmobileapi_intermediates)
-
diff --git a/smart-card-service/jni/Android.mk b/smart-card-service/jni/Android.mk
deleted file mode 100644
index 5053e7d..0000000
--- a/smart-card-service/jni/Android.mk
+++ /dev/null
@@ -1 +0,0 @@
-include $(call all-subdir-makefiles)
diff --git a/smart-card-service/jni/assd/ASSDTerminal.cpp b/smart-card-service/jni/assd/ASSDTerminal.cpp
deleted file mode 100644
index ca61f1a..0000000
--- a/smart-card-service/jni/assd/ASSDTerminal.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2011, The Android Open Source Project
- *
- * 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.
- */
-
-#include "ASSDTerminal.h"
-
-#include <linux/ioctl.h>
-#include "assd.h"
-
-#include <stdlib.h>
-#include <fcntl.h>
-
-// #include <utils/Log.h>
-
-#define LOG_TAG "libassd"
-
-static int fd = -1;
-
-JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
- return JNI_VERSION_1_6;
-}
-
-/*
- * Class: android_smartcard_terminals_ASSDTerminal
- * Method: Close
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL Java_org_simalliance_openmobileapi_service_terminals_ASSDTerminal_Close
-(JNIEnv *env, jobject obj) {
- if (fd >= 0)
- close(fd);
- fd = -1;
-}
-
-/*
- * Class: android_smartcard_terminals_ASSDTerminal
- * Method: Open
- * Signature: (I)I
- */
-JNIEXPORT jboolean JNICALL Java_org_simalliance_openmobileapi_service_terminals_ASSDTerminal_Open
-(JNIEnv *env, jobject obj) {
- if (fd >= 0)
- return false;
-
- fd = open("/dev/assd", O_RDWR);
- if (fd < 0)
- return false;
-
- if (ioctl(fd, ASSD_IOC_ENABLE)) {
- close(fd);
- fd = -1;
- return false;
- }
-
- return true;
-}
-
-JNIEXPORT
-jboolean JNICALL Java_org_simalliance_openmobileapi_service_terminals_ASSDTerminal_IsPresent
-(JNIEnv *env, jobject obj) {
- int result;
- int f = fd;
- if (fd < 0)
- f = open("/dev/assd", O_RDWR);
- if (f < 0)
- return false;
-
- result = ioctl(f, ASSD_IOC_PROBE);
- if (fd < 0)
- close(f);
-
- if (result)
- return false;
-
- return true;
-}
-
-/*
- * Class: android_smartcard_terminals_ASSDTerminal
- * Method: Transmit
- * Signature: (I[B)[B
- */
-JNIEXPORT
-jbyteArray JNICALL Java_org_simalliance_openmobileapi_service_terminals_ASSDTerminal_Transmit
-(JNIEnv *env, jobject obj, jbyteArray jcommand) {
- uint8_t* buf = NULL;
- int resultLength;
- jbyteArray result = NULL;
- int commandLength = env->GetArrayLength(jcommand);
- jbyte* command = env->GetByteArrayElements(jcommand, NULL);
-
- if (command == NULL)
- return NULL;
- if ((fd < 0) || (commandLength < 1) || (commandLength > 510))
- goto clean_and_return;
-
- buf = (uint8_t*)malloc(512);
- if (buf == NULL)
- goto clean_and_return;
-
- buf[0] = ((commandLength + 2) >> 8) & 0xff;
- buf[1] = (commandLength + 2) & 0xff;
- memcpy(&buf[2], command, commandLength);
-
- if (ioctl(fd, ASSD_IOC_TRANSCEIVE, buf))
- goto clean_and_return;
-
- resultLength = ((buf[0] << 8) | buf[1]) - 2;
- if ((resultLength < 1) || (resultLength > 510))
- goto clean_and_return;
-
- result = env->NewByteArray(resultLength);
- if (result == NULL)
- goto clean_and_return;
-
- env->SetByteArrayRegion(result, 0, resultLength, (jbyte*)&buf[2]);
-
-clean_and_return:
- if (buf != NULL)
- free(buf);
-
- env->ReleaseByteArrayElements(jcommand, command, JNI_ABORT);
- return result;
-}
diff --git a/smart-card-service/jni/assd/ASSDTerminal.h b/smart-card-service/jni/assd/ASSDTerminal.h
deleted file mode 100644
index f99d7c2..0000000
--- a/smart-card-service/jni/assd/ASSDTerminal.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* DO NOT EDIT THIS FILE - it is machine generated */
-#include <jni.h>
-/* Header for class org_simalliance_openmobileapi_service_terminals_ASSDTerminal */
-
-#ifndef _Included_org_simalliance_openmobileapi_service_terminals_ASSDTerminal
-#define _Included_org_simalliance_openmobileapi_service_terminals_ASSDTerminal
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * Class: org_simalliance_openmobileapi_service_terminals_ASSDTerminal
- * Method: Close
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_org_simalliance_openmobileapi_service_terminals_ASSDTerminal_Close
- (JNIEnv *, jobject);
-
-/*
- * Class: org_simalliance_openmobileapi_service_terminals_ASSDTerminal
- * Method: Open
- * Signature: ()Z
- */
-JNIEXPORT jboolean JNICALL Java_org_simalliance_openmobileapi_service_terminals_ASSDTerminal_Open
- (JNIEnv *, jobject);
-
-/*
- * Class: org_simalliance_openmobileapi_service_terminals_ASSDTerminal
- * Method: IsPresent
- * Signature: ()Z
- */
-JNIEXPORT jboolean JNICALL Java_org_simalliance_openmobileapi_service_terminals_ASSDTerminal_IsPresent
- (JNIEnv *, jobject);
-
-/*
- * Class: org_simalliance_openmobileapi_service_terminals_ASSDTerminal
- * Method: Transmit
- * Signature: ([B)[B
- */
-JNIEXPORT jbyteArray JNICALL Java_org_simalliance_openmobileapi_service_terminals_ASSDTerminal_Transmit
- (JNIEnv *, jobject, jbyteArray);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/smart-card-service/jni/assd/Android.mk b/smart-card-service/jni/assd/Android.mk
deleted file mode 100644
index 72a530a..0000000
--- a/smart-card-service/jni/assd/Android.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_PRELINK_MODULE := false
-LOCAL_MODULE := libassd
-LOCAL_MODULE_TAGS := optional
-LOCAL_SRC_FILES := ASSDTerminal.cpp
-LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
-
-
-include $(BUILD_SHARED_LIBRARY)
-
diff --git a/smart-card-service/jni/assd/assd.h b/smart-card-service/jni/assd/assd.h
deleted file mode 100644
index b7d4e23..0000000
--- a/smart-card-service/jni/assd/assd.h
+++ /dev/null
@@ -1,43 +0,0 @@
-#define ASSD_IOC_MAGIC 'A'
-
-/*
- * Enable the ASSD capable card
- * - EBUSY - Function temporary not available
- * - ENODEV - No ASSD capable card is available
- */
-#define ASSD_IOC_ENABLE _IO(ASSD_IOC_MAGIC, 0)
-
-/*
- * Transceive secure token to secure element
- * - EBUSY - Function temporary not available
- * - ENODEV - No ASSD capable card is available
- * - EINVAL - The secure token is invalid
- * - ETIMEDOUT - Timeout for communication with secure element reached
- * - EIO - Error in communication with secure element
- */
-#define ASSD_IOC_TRANSCEIVE _IOWR(ASSD_IOC_MAGIC, 1, char *)
-
-/*
- * Probe if currently an ASSD capable card is available
- * - ENODEV - No ASSD capable card is available
- */
-#define ASSD_IOC_PROBE _IO(ASSD_IOC_MAGIC, 2)
-
-/*
- * Wait until an ASSD capable card is available
- * - ENODEV - No ASSD capable card is available
- * - ETIMEOUT - The timeout was reached
- */
-#define ASSD_IOC_WAIT _IOW(ASSD_IOC_MAGIC, 3, int)
-
-/*
- * Set timeout for communication with secure element
- * - EINVAL - The value is invalid
- */
-#define ASSD_IOC_SET_TIMEOUT _IOW(ASSD_IOC_MAGIC, 4, int)
-
-/*
- * Get version information
- * - EFAULT - The output buffer is invalid
- */
-#define ASSD_IOC_GET_VERSION _IOR(ASSD_IOC_MAGIC, 5, char *)
diff --git a/smart-card-service/openmobileapi/Android.mk b/smart-card-service/openmobileapi/Android.mk
deleted file mode 100644
index 0cefe39..0000000
--- a/smart-card-service/openmobileapi/Android.mk
+++ /dev/null
@@ -1,36 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := org.simalliance.openmobileapi.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/permissions
-LOCAL_SRC_FILES := $(LOCAL_MODULE)
-
-include $(BUILD_PREBUILT)
-
-
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_SRC_FILES += \
- src/org/simalliance/openmobileapi/service/ISmartcardServiceCallback.aidl \
- src/org/simalliance/openmobileapi/service/ISmartcardServiceReader.aidl \
- src/org/simalliance/openmobileapi/service/ISmartcardServiceChannel.aidl \
- src/org/simalliance/openmobileapi/service/ISmartcardServiceSession.aidl \
- src/org/simalliance/openmobileapi/service/ISmartcardService.aidl
-
-LOCAL_AIDL_INCLUDES := packages/apps/SmartCardService/openmobileapi/src/org/simalliance/openmobileapi/service
-
-LOCAL_MODULE:= org.simalliance.openmobileapi
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_JAVA_LIBRARY)
-
-
-# put the classes.jar, with full class files instead of classes.dex inside, into the dist directory
-$(call dist-for-goals, droidcore, $(full_classes_jar):org.simalliance.openmobileapi.jar)
-
-
diff --git a/smart-card-service/openmobileapi/org.simalliance.openmobileapi.xml b/smart-card-service/openmobileapi/org.simalliance.openmobileapi.xml
deleted file mode 100644
index 643684d..0000000
--- a/smart-card-service/openmobileapi/org.simalliance.openmobileapi.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
- 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.
--->
-
-<permissions>
- <library name="org.simalliance.openmobileapi"
- file="/system/framework/org.simalliance.openmobileapi.jar" />
-</permissions>
diff --git a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/AuthenticationProvider.java b/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/AuthenticationProvider.java
deleted file mode 100644
index ca291d0..0000000
--- a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/AuthenticationProvider.java
+++ /dev/null
@@ -1,787 +0,0 @@
-/*
- * Copyright 2013 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi;
-
-import java.io.IOException;
-
-import org.simalliance.openmobileapi.internal.ErrorStrings;
-import org.simalliance.openmobileapi.util.CommandApdu;
-import org.simalliance.openmobileapi.util.ResponseApdu;
-
-/**
- * This Authentication class can be used to privilege a certain communication
- * channel to the Secure Element for operations that requires a PIN
- * authentication. Besides the PIN verification for authentication this class
- * provides also PIN management command for changing, deactivating or activating
- * PINs.
- * <p>
- * <b>Prerequisites:</b> The PIN operations performed by this
- * AuthenticationProvider class are based on the ISO/IEC 7816-4 specification
- * and require a preselected applet on the specified communication channel to
- * the Secure Element that implements ISO/IEC 7816-4 compliant PIN commands.
- * <p>
- * <b>Notes:</b>
- * <ul>
- * <li>If used by multiple threads, synchronization is up to the application.
- * <li>Each operation needs an access to the Secure Element. If the access can
- * not be granted because of a closed channel or a missing security condition
- * the called method will return an error.</li>
- * </ul>
- */
-public class AuthenticationProvider extends Provider {
-
- /**
- * Encapsulates the defined channel by an AuthenticationProvider object that
- * can be used for applying PIN commands on it.
- *
- * @param channel The channel that should be privileged for operations that
- * requires a PIN authentication.
- *
- * @throws IllegalStateException if the defined channel is closed.
- */
- public AuthenticationProvider(Channel channel)
- throws IllegalStateException {
- super(channel);
- }
-
- /**
- * Performs a PIN verification.
- *
- * @param pinID The PIN ID references the PIN in the Secure Element which
- * shall be used for the verification.
- * @param pin The PIN that shall be verified.
- *
- * @return True if the authentication was successful, False if the
- * authentication fails.
- *
- * @throws IllegalArgumentException if the PIN reference as defined couldn't
- * be found in the Secure Element.
- * TODO: should be an IllegalReferenceError
- * @throws IllegalArgumentException if the PIN value has a bad coding or a
- * wrong length (empty or too long).
- * @throws IllegalStateException if the used channel is closed.
- * @throws UnsupportedOperationException if this operation is not supported.
- * @throws IOException Lower-lever API exception.
- */
- public boolean verifyPin(PinID pinID, byte[] pin)
- throws IllegalArgumentException, IllegalStateException,
- UnsupportedOperationException, IOException {
-
- if (pinID == null) {
- throw new IllegalArgumentException(
- ErrorStrings.paramNull("pinID"));
- }
- if (pin == null) {
- throw new IllegalArgumentException(
- ErrorStrings.paramNull("pin"));
- }
-
- if (pin.length == 0 || pin.length > CommandApdu.MAX_DATA_LENGTH) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidArrayLength("pin"));
- }
-
- // Prepare and send the APDU
- CommandApdu apdu = new CommandApdu(getChannel());
- apdu.setCla(CommandApdu.CLA_INTERINDUSTRY);
- apdu.setIns(CommandApdu.INS_VERIFY_20);
- apdu.setP1((byte) 0x00);
- byte p2 = (byte) pinID.getID();
- if (pinID.isLocal()) {
- // Set first bit to 1 to indicate that it is a local pin
- p2 = (byte) (p2 | 0x80);
- }
- apdu.setP2(p2);
- apdu.setData(pin);
- byte[] apduResponse = apdu.sendApdu();
-
- // Parse the response
- int swValue = ResponseApdu.getResponseStatusWordValue(apduResponse);
- switch (swValue) {
- case ResponseApdu.SW_NO_FURTHER_QUALIFICATION:
- return true;
- case ResponseApdu.SW_63_NO_INFO:
- // ISO/IEC 7816-4 7.5.1: "In this group of commands, SW1-SW2 set to
- // 6300 or 63CX indicates that the verification failed [...]"
- return false;
- case ResponseApdu.SW_AUTH_METHOD_BLOCKED:
- // PIN is blocked.
- return false;
- case ResponseApdu.SW_REF_DATA_NOT_USABLE:
- // PIN is blocked.
- return false;
- case ResponseApdu.SW_FUNC_NOT_SUPPORTED:
- throw new UnsupportedOperationException();
- case ResponseApdu.SW_INCORRECT_P1P2:
- // Wrong PIN ID.
- // TODO: should be an IllegalReferenceError
- throw new IllegalArgumentException(ErrorStrings.PIN_REF_NOT_FOUND);
- case ResponseApdu.SW_REF_NOT_FOUND:
- // Wrong PIN ID.
- // TODO: should be an IllegalReferenceError
- throw new IllegalArgumentException(ErrorStrings.PIN_REF_NOT_FOUND);
- case ResponseApdu.SW_WRONG_PARAMETERS_P1P2:
- // Wrong PIN ID.
- // TODO: should be an IllegalReferenceError
- throw new IllegalArgumentException(ErrorStrings.PIN_REF_NOT_FOUND);
- case ResponseApdu.SW_INS_NOT_SUPPORTED:
- throw new UnsupportedOperationException();
- default:
- // Check if SW is between 63C0 and 63CF
- if (ResponseApdu.SW_CTR_MIN <= swValue
- && swValue <= ResponseApdu.SW_CTR_MAX) {
- return false;
- } else {
- throw new IOException(
- ErrorStrings.unexpectedStatusWord(swValue));
- }
- }
- }
-
- /**
- * Changes the PIN.
- * <p>
- * <b>Note:</b> This method is based on the ISO/IEC 7816-4 command CHANGE
- * REFERENCE DATA.
- *
- * @param pinID The PIN ID references the PIN in the Secure Element which
- * shall be changed.
- * @param oldPin The old PIN that shall be changed.
- * @param newPin The PIN that shall be set as new PIN.
- *
- * @throws SecurityException if old PIN does not match with the PIN stored
- * in the SE. The PIN is not changed.
- * @throws IllegalArgumentException if the PIN reference as defined couldn't
- * be found in the Secure Element.
- * TODO: should be an IllegalReferenceError
- * @throws IllegalArgumentException if the value of oldPin or newPIN has a
- * bad coding or a wrong length (empty or too long).
- * @throws IllegalStateException if the used channel is closed.
- * @throws UnsupportedOperationException if this operation is not supported.
- * @throws IOException Lower-lever API exception.
- */
- public void changePin(PinID pinID, byte[] oldPin, byte[] newPin)
- throws SecurityException, IllegalArgumentException,
- IllegalStateException, UnsupportedOperationException, IOException {
-
- if (pinID == null) {
- throw new IllegalArgumentException(
- ErrorStrings.paramNull("pinID"));
- }
- if (oldPin == null) {
- throw new IllegalArgumentException(
- ErrorStrings.paramNull("oldPin"));
- }
- if (newPin == null) {
- throw new IllegalArgumentException(
- ErrorStrings.paramNull("newPin"));
- }
-
- if (oldPin.length == 0) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidArrayLength("oldPin"));
- }
- if (newPin.length == 0) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidArrayLength("newPin"));
- }
-
- // No need to check if pins are too long since it
- // will be done by setData
-
- // Prepare the APDU
- CommandApdu apdu = new CommandApdu(getChannel());
- apdu.setCla(CommandApdu.CLA_INTERINDUSTRY);
- apdu.setIns(CommandApdu.INS_CHANGE_REF_DATA);
- apdu.setP1((byte) 0x00);
- byte p2 = (byte) pinID.getID();
- if (pinID.isLocal()) {
- // Set first bit to 1 to indicate that is a local pin
- p2 = (byte) (p2 | 0x80);
- }
- apdu.setP2(p2);
- byte[] data = new byte[oldPin.length + newPin.length];
- System.arraycopy(oldPin, 0, data, 0, oldPin.length);
- System.arraycopy(newPin, 0, data, oldPin.length, newPin.length);
- apdu.setData(data);
- byte[] apduResponse = apdu.sendApdu();
-
- // Parse the response
- int swValue = ResponseApdu.getResponseStatusWordValue(apduResponse);
- switch (swValue) {
- case ResponseApdu.SW_NO_FURTHER_QUALIFICATION:
- // Everything is OK.
- break;
- case ResponseApdu.SW_63_NO_INFO:
- // ISO/IEC 7816-4 7.5.1: "In this group of commands, SW1-SW2 set to
- // 6300 or 63CX indicates that the verification failed [...]"
- throw new SecurityException(ErrorStrings.PIN_WRONG);
- case ResponseApdu.SW_SECURITY_STATUS_NOT_SATISFIED:
- throw new SecurityException(
- ErrorStrings.SECURITY_STATUS_NOT_SATISFIED);
- case ResponseApdu.SW_AUTH_METHOD_BLOCKED:
- // PIN is blocked.
- throw new SecurityException(ErrorStrings.PIN_BLOCKED);
- case ResponseApdu.SW_REF_DATA_NOT_USABLE:
- // PIN is blocked.
- throw new SecurityException(ErrorStrings.PIN_BLOCKED);
- case ResponseApdu.SW_FUNC_NOT_SUPPORTED:
- throw new UnsupportedOperationException();
- case ResponseApdu.SW_INCORRECT_P1P2:
- // Wrong PIN ID.
- // TODO: should be an IllegalReferenceError
- throw new IllegalArgumentException(ErrorStrings.PIN_REF_NOT_FOUND);
- case ResponseApdu.SW_WRONG_PARAMETERS_P1P2:
- // Wrong PIN ID.
- // TODO: should be an IllegalReferenceError
- throw new IllegalArgumentException(ErrorStrings.PIN_REF_NOT_FOUND);
- case ResponseApdu.SW_INS_NOT_SUPPORTED:
- throw new UnsupportedOperationException();
- default:
- // Check if SW is between 63C0 and 63CF
- if (ResponseApdu.SW_CTR_MIN <= swValue
- && swValue <= ResponseApdu.SW_CTR_MAX) {
- // oldPin is wrong
- throw new SecurityException(ErrorStrings.PIN_WRONG);
- } else {
- throw new IOException(
- ErrorStrings.unexpectedStatusWord(swValue));
- }
- }
- }
-
- /**
- * Resets the PIN with the reset PIN or just resets the retry counter.
- * <p>
- * <b>Note:</b> This method is based on the ISO/IEC 7816-4 command RESET
- * RETRY COUNTER.
- *
- * @param pinID The PIN ID references the PIN in the Secure Element which
- * shall be reset.
- * @param resetPin The reset PIN that shall be used for reset.
- * @param newPin The PIN that shall be set as new PIN. Can be omitted with
- * null if just the reset counter shall be reset.
- *
- * @throws SecurityException if resetPin does not match with the "resetPin"
- * stored in the SE. The PIN or reset counter is not changed.
- * @throws IllegalArgumentException if the PIN ID reference as defined
- * couldn't be found in the secure element.
- * TODO: should be an IllegalReferenceError
- * @throws IllegalArgumentException if the value of resetPin or newPin has a
- * bad coding or a wrong length (empty or too long).
- * @throws IllegalStateException if the used channel is closed.
- * @throws UnsupportedOperationException if the resetPin is not defined, or
- * if the operation is not supported.
- * @throws IOException Lower-lever API exception.
- */
- public void resetPin(PinID pinID, byte[] resetPin, byte[] newPin)
- throws SecurityException, IllegalArgumentException,
- IllegalStateException, UnsupportedOperationException, IOException {
-
- if (pinID == null) {
- throw new IllegalArgumentException(
- ErrorStrings.paramNull("pinID"));
- }
- if (resetPin == null) {
- throw new IllegalArgumentException(
- ErrorStrings.paramNull("resetPin"));
- }
-
- if (resetPin.length == 0) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidArrayLength("resetPin"));
- }
- if (newPin != null && newPin.length == 0) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidArrayLength("newPin"));
- }
-
- // No need to check if pins are too long since it will be done by
- // setData
-
- // Prepare and send the APDU
- CommandApdu apdu = new CommandApdu(getChannel());
- apdu.setCla(CommandApdu.CLA_INTERINDUSTRY);
- apdu.setIns(CommandApdu.INS_RESET_RETRY_CTR);
- // P1 depends on whether user wants to set a new PIN or only the
- // retry counter.
- if (newPin != null) {
- apdu.setP1((byte) 0x00);
- } else {
- apdu.setP1((byte) 0x01);
- }
- byte p2 = (byte) pinID.getID();
- if (pinID.isLocal()) {
- // Set first bit to 1 to indicate that it is a local pin
- p2 = (byte) (p2 | 0x80);
- }
- apdu.setP2(p2);
- byte[] data;
- // Data will be different depending on whether user wants to reset
- // PIN or only reset the retry counter.
- if (newPin != null) {
- data = new byte[resetPin.length + newPin.length];
- } else {
- data = new byte[resetPin.length];
- }
-
- System.arraycopy(resetPin, 0, data, 0, resetPin.length);
- if (newPin != null) {
- System.arraycopy(newPin, 0, data, resetPin.length, newPin.length);
- }
- apdu.setData(data);
- byte[] response = apdu.sendApdu();
-
- // Parse the response
- int swValue = ResponseApdu.getResponseStatusWordValue(response);
- switch (swValue) {
- case ResponseApdu.SW_NO_FURTHER_QUALIFICATION:
- // Everything is OK.
- break;
- case ResponseApdu.SW_63_NO_INFO:
- // ISO/IEC 7816-4 7.5.1: "In this group of commands, SW1-SW2 set to
- // 6300 or 63CX indicates that the verification failed [...]"
- throw new SecurityException(ErrorStrings.PIN_WRONG);
- case ResponseApdu.SW_SECURITY_STATUS_NOT_SATISFIED:
- throw new SecurityException(
- ErrorStrings.SECURITY_STATUS_NOT_SATISFIED);
- case ResponseApdu.SW_AUTH_METHOD_BLOCKED:
- // PIN is blocked.
- throw new SecurityException(ErrorStrings.PIN_BLOCKED);
- case ResponseApdu.SW_REF_DATA_NOT_USABLE:
- // PIN is blocked.
- throw new SecurityException(ErrorStrings.PIN_BLOCKED);
- case ResponseApdu.SW_FUNC_NOT_SUPPORTED:
- throw new UnsupportedOperationException();
- case ResponseApdu.SW_INCORRECT_P1P2:
- // Wrong PIN ID.
- // TODO: should be an IllegalReferenceError
- throw new IllegalArgumentException(ErrorStrings.PIN_REF_NOT_FOUND);
- case ResponseApdu.SW_WRONG_PARAMETERS_P1P2:
- // Wrong PIN ID.
- // TODO: should be an IllegalReferenceError
- throw new IllegalArgumentException(ErrorStrings.PIN_REF_NOT_FOUND);
- case ResponseApdu.SW_INS_NOT_SUPPORTED:
- throw new UnsupportedOperationException();
- default:
- if (ResponseApdu.SW_CTR_MIN <= swValue
- && swValue <= ResponseApdu.SW_CTR_MAX) {
- // resetPin is wrong
- throw new SecurityException(ErrorStrings.PIN_WRONG);
- } else {
-
- throw new IOException(
- ErrorStrings.unexpectedStatusWord(swValue));
- }
- }
- }
-
- /**
- * Returns the retry counter of the referenced PIN.
- * <p>
- * <b>Note: </b> This method is based on the ISO/IEC 7816-4 command VERIFY.
- *
- * @param pinID The PIN ID references the PIN in the Secure Element and its
- * retry counter.
- *
- * @return The retry counter of the referenced PIN.
- *
- * @throws IllegalArgumentException if the PIN reference as defined couldn't
- * be found in the Secure Element.
- * TODO: should be an IllegalReferenceError
- * @throws IllegalStateException if the used channel is closed or if PIN
- * PIN verification is not required for this pinID.
- * @throws UnsupportedOperationException if this operation is not supported.
- * @throws IOException Lower-lever API exception.
- * @throws IllegalArgumentException if pinID is null.
- */
- public int getRetryCounter(PinID pinID) throws IllegalArgumentException,
- IllegalStateException, UnsupportedOperationException, IOException {
-
- if (pinID == null) {
- throw new IllegalArgumentException(
- ErrorStrings.paramNull("pinID"));
- }
-
- // Prepare and send the APDU
- CommandApdu apdu = new CommandApdu(getChannel());
- apdu.setCla(CommandApdu.CLA_INTERINDUSTRY);
- apdu.setIns(CommandApdu.INS_VERIFY_20);
- apdu.setP1((byte) 0x00);
- byte p2 = (byte) pinID.getID();
- if (pinID.isLocal()) {
- // Set first bit to 1 to indicate that is a local pin
- p2 = (byte) (p2 | 0x80);
- }
- apdu.setP2(p2);
- byte[] response = apdu.sendApdu();
-
- // Parse the response
- int swValue = ResponseApdu.getResponseStatusWordValue(response);
- switch (swValue) {
- case ResponseApdu.SW_NO_FURTHER_QUALIFICATION:
- // This means that no PIN verification is required,
- // so we can't get the retry counter.
- throw new UnsupportedOperationException();
- case ResponseApdu.SW_63_NO_INFO:
- // ISO/IEC 7816-4 7.5.1: "In this group of commands, SW1-SW2 set to
- // 6300 or 63CX indicates that the verification failed [...]"
- throw new SecurityException(ErrorStrings.PIN_WRONG);
- case ResponseApdu.SW_AUTH_METHOD_BLOCKED:
- // PIN is blocked.
- throw new SecurityException(ErrorStrings.PIN_BLOCKED);
- case ResponseApdu.SW_REF_DATA_NOT_USABLE:
- // PIN is blocked.
- throw new SecurityException(ErrorStrings.PIN_BLOCKED);
- case ResponseApdu.SW_FUNC_NOT_SUPPORTED:
- throw new UnsupportedOperationException();
- case ResponseApdu.SW_INCORRECT_P1P2:
- // Wrong PIN ID.
- // TODO: should be an IllegalReferenceError
- throw new IllegalArgumentException(ErrorStrings.PIN_REF_NOT_FOUND);
- case ResponseApdu.SW_WRONG_PARAMETERS_P1P2:
- // Wrong PIN ID.
- // TODO: should be an IllegalReferenceError
- throw new IllegalArgumentException(ErrorStrings.PIN_REF_NOT_FOUND);
- case ResponseApdu.SW_INS_NOT_SUPPORTED:
- throw new UnsupportedOperationException();
- default:
- if (ResponseApdu.SW_CTR_MIN <= swValue
- && swValue <= ResponseApdu.SW_CTR_MAX) {
- // Get the last 4 bits of the SW (63CX)
- return (int) swValue & 0x000F;
- } else {
- throw new IOException(
- ErrorStrings.unexpectedStatusWord(swValue));
- }
- }
- }
-
- /**
- * Activates the PIN. Thus a deactivated PIN can be used again.
- * <p>
- * <b>Note:</b> This method is based on the ISO/IEC 7816-4 command ENABLE
- * VERIFICATION REQUIREMENT.
- *
- * @param pinID The PIN ID references the PIN in the Secure Element which
- * shall be activated
- * @param pin the verification PIN for activating the PIN if required. Can
- * be omitted with null if not required.
- *
- * @throws SecurityException if the defined pin does not match with the PIN
- * needed for the activation. The PIN state will not be changed.
- * @throws IllegalStateException if the used channel is closed.
- * @throws IllegalArgumentException if the PIN reference as defined couldn't
- * be found in the Secure Element
- * TODO: should be an IllegalReferenceError
- * @throws IllegalArgumentException if the PIN value has a bad coding or a
- * wrong length (empty or too long).
- * @throws UnsupportedOperationException if this operation is not supported.
- * @throws IOException Lower-lever API exception.
- */
- public void activatePin(PinID pinID, byte[] pin) throws SecurityException,
- IllegalStateException, IllegalArgumentException,
- UnsupportedOperationException, IOException {
-
- if (pinID == null) {
- throw new IllegalArgumentException(
- ErrorStrings.paramNull("pinID"));
- }
-
- if (pin != null) {
- if (pin.length == 0 || pin.length > CommandApdu.MAX_DATA_LENGTH) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidArrayLength("pin"));
- }
- }
-
- // Prepare and send the APDU
- CommandApdu apdu = new CommandApdu(getChannel());
- apdu.setCla(CommandApdu.CLA_INTERINDUSTRY);
- apdu.setIns(CommandApdu.INS_ENABLE_VERIF_REQ);
- if (pin != null) {
- apdu.setP1((byte) 0x00);
- } else {
- apdu.setP1((byte) 0x01);
- }
- byte p2 = (byte) pinID.getID();
- if (pinID.isLocal()) {
- // Set first bit to 1 to indicate that is a local pin
- p2 = (byte) (p2 | 0x80);
- }
- apdu.setP2(p2);
- if (pin != null) {
- apdu.setData(pin);
- }
- byte[] apduResponse = apdu.sendApdu();
-
- // Parse the response
- int swValue = ResponseApdu.getResponseStatusWordValue(apduResponse);
- switch (swValue) {
- case ResponseApdu.SW_NO_FURTHER_QUALIFICATION:
- // Everything is OK.
- break;
- case ResponseApdu.SW_63_NO_INFO:
- // Verification failed
- throw new SecurityException(ErrorStrings.PIN_WRONG);
- case ResponseApdu.SW_SECURITY_STATUS_NOT_SATISFIED:
- throw new SecurityException(
- ErrorStrings.SECURITY_STATUS_NOT_SATISFIED);
- case ResponseApdu.SW_AUTH_METHOD_BLOCKED:
- throw new SecurityException(ErrorStrings.AUTH_METHOD_BLOCKED);
- case ResponseApdu.SW_FUNC_NOT_SUPPORTED:
- throw new UnsupportedOperationException(
- ErrorStrings.OPERATION_NOT_SUPORTED);
- case ResponseApdu.SW_INCORRECT_P1P2:
- if (pin != null) {
- // pinID is wrong
- // TODO: should be an IllegalReferenceError
- throw new IllegalArgumentException(
- ErrorStrings.PIN_REF_NOT_FOUND);
- } else {
- // Either pinID is wrong (IllegalReferenceError), or
- // this pinID does not support activation with pin = null
- // (IllegalParameterError)
- // TODO: differentiate between cases
- // TODO: should be an IllegalReferenceError (in one case)
- throw new IllegalArgumentException(
- "Either pinID is wrong, or this pin does not "
- + "support activation with pin = null.");
- }
- case ResponseApdu.SW_REF_NOT_FOUND:
- // TODO: should be an IllegalReferenceError
- throw new IllegalArgumentException(ErrorStrings.PIN_REF_NOT_FOUND);
- case ResponseApdu.SW_WRONG_PARAMETERS_P1P2:
- if (pin != null) {
- // pinID is wrong
- // TODO: should be an IllegalReferenceError
- throw new IllegalArgumentException(
- ErrorStrings.PIN_REF_NOT_FOUND);
- } else {
- // Either pinID is wrong (IllegalReferenceError), or
- // this pinID does not support activation with pin = null
- // (IllegalParameterError)
- // TODO: differentiate between cases
- // TODO: should be an IllegalReferenceError (in one case)
- throw new IllegalArgumentException(
- "Either pinID is wrong, or this pin does not "
- + "support activation with pin = null.");
- }
- case ResponseApdu.SW_INS_NOT_SUPPORTED:
- throw new UnsupportedOperationException(
- ErrorStrings.OPERATION_NOT_SUPORTED);
- default:
- if (ResponseApdu.SW_CTR_MIN <= swValue
- && swValue <= ResponseApdu.SW_CTR_MAX) {
- throw new SecurityException(ErrorStrings.PIN_WRONG);
- } else {
- throw new IOException(
- ErrorStrings.unexpectedStatusWord(swValue));
- }
- }
- }
-
- /**
- * Deactivates the PIN. Thus the objects which are protected by the PIN can
- * now be used without this restriction until activatePin() is called.
- * <p>
- * <b>Note - </b> This method is based on the ISO/IEC 7816-4 command DISABLE
- * VERIFICATION REQUIREMENT.
- *
- * @param pinID The PIN ID references the PIN in the Secure Element which
- * shall be deactivated.
- * @param pin the verification PIN for deactivating the pin if required. Can
- * be omitted with null if not required.
- *
- * @throws SecurityException if the defined pin does not match with the PIN
- * needed for the deactivation. The PIN state will not be changed.
- * @throws IllegalStateException if the used channel is closed.
- * @throws IllegalArgumentException if the PIN reference as defined couldn't
- * be found in the Secure Element
- * TODO: should be an IllegalReferenceError
- * @throws IllegalArgumentException if the PIN value has a bad coding or a
- * wrong length (empty or too long).
- * @throws UnsupportedOperationException if this operation is not supported.
- * @throws IOException Lower-lever API exception.
- */
- public void deactivatePin(final PinID pinID, final byte[] pin)
- throws SecurityException, IllegalStateException,
- IllegalArgumentException, UnsupportedOperationException,
- IOException {
-
- if (pinID == null) {
- throw new IllegalArgumentException(
- ErrorStrings.paramNull("pinID"));
- }
-
- if (pin != null) {
- if (pin.length == 0 || pin.length > CommandApdu.MAX_DATA_LENGTH) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidArrayLength("pin"));
- }
- }
-
- // Prepare and send the APDU
- CommandApdu apdu = new CommandApdu(getChannel());
- apdu.setCla(CommandApdu.CLA_INTERINDUSTRY);
- apdu.setIns(CommandApdu.INS_DISABLE_VERIF_REQ);
- if (pin != null) {
- apdu.setP1((byte) 0x00);
- } else {
- apdu.setP1((byte) 0x01);
- }
- byte p2 = (byte) pinID.getID();
- if (pinID.isLocal()) {
- // Set first bit to 1 to indicate that is a local pin
- p2 = (byte) (p2 | 0x80);
- }
- apdu.setP2(p2);
- if (pin != null) {
- apdu.setData(pin);
- }
- byte[] apduResponse = apdu.sendApdu();
-
- // Parse the response
- int swValue = ResponseApdu.getResponseStatusWordValue(apduResponse);
- switch (swValue) {
- case ResponseApdu.SW_NO_FURTHER_QUALIFICATION:
- // Everything is OK.
- break;
- case ResponseApdu.SW_63_NO_INFO:
- // ISO/IEC 7816-4 7.5.1: "In this group of commands, SW1-SW2 set to
- // 6300 or 63CX indicates that the verification failed [...]"
- throw new SecurityException(ErrorStrings.PIN_WRONG);
- case ResponseApdu.SW_SECURITY_STATUS_NOT_SATISFIED:
- throw new SecurityException(
- ErrorStrings.SECURITY_STATUS_NOT_SATISFIED);
- case ResponseApdu.SW_AUTH_METHOD_BLOCKED:
- // PIN is blocked.
- throw new SecurityException(ErrorStrings.PIN_BLOCKED);
- case ResponseApdu.SW_REF_DATA_NOT_USABLE:
- // PIN is blocked.
- throw new SecurityException(ErrorStrings.PIN_BLOCKED);
- case ResponseApdu.SW_FUNC_NOT_SUPPORTED:
- throw new UnsupportedOperationException();
- case ResponseApdu.SW_INCORRECT_P1P2:
- // Wrong PIN ID.
- // TODO: should be an IllegalReferenceError
- throw new IllegalArgumentException(ErrorStrings.PIN_REF_NOT_FOUND);
- case ResponseApdu.SW_WRONG_PARAMETERS_P1P2:
- // Wrong PIN ID.
- // TODO: should be an IllegalReferenceError
- throw new IllegalArgumentException(ErrorStrings.PIN_REF_NOT_FOUND);
- case ResponseApdu.SW_INS_NOT_SUPPORTED:
- throw new UnsupportedOperationException();
- default:
- if (ResponseApdu.SW_CTR_MIN <= swValue
- && swValue <= ResponseApdu.SW_CTR_MAX) {
- throw new SecurityException(ErrorStrings.PIN_WRONG);
- } else {
- throw new IOException(
- ErrorStrings.unexpectedStatusWord(swValue));
- }
- }
- }
-
- /**
- * This PIN ID uniquely identifies a PIN in the Secure Element system. The
- * PIN ID is defined as specified in ISO/IEC 7816-4 and can be used to
- * reference a PIN in an ISO/IEC 7816-4 compliant system.
- */
- public class PinID {
-
- /**
- * The minimum possible value of a PIN ID.
- */
- public static final int MIN_ID_VALUE = 0x00;
-
- /**
- * The maximum possible value of a PIN ID.
- */
- public static final int MAX_ID_VALUE = 0x1F;
-
- /**
- * The ID of the PIN (value from 0x00 to 0x1F).
- */
- private int mId;
-
- /**
- * Defines the scope (global or local). True if the PIN is local.
- * Otherwise false.
- */
- private boolean mLocal;
-
- /**
- * Creates a PIN ID (reference) to identify a PIN within a Secure
- * Element. The created PIN ID (as immutable object) can be specified on
- * all PIN operation methods provided by the AuthenticationProvider
- * class.
- * <p>
- * <b>Note:</b> This constructor is based on the P2 reference data for
- * PIN related commands as specified in ISO/IEC 7816-4 in chapter 7.5
- * (Basic security handling). Local set to true indicates specific
- * reference data and local set to false indicates global reference data
- * according to ISO/IEC 7816-4. The ID indicates the number of the
- * reference data (qualifier) according to ISO/IEC 7816-4.
- *
- * @param id The ID of the PIN (value from 0x00 to 0x1F).
- * @param local Defines the scope (global or local). True if the PIN is
- * local. Otherwise false.
- *
- * @throws IllegalArgumentException if the defined ID is invalid.
- */
- public PinID(int id, boolean local)
- throws IllegalArgumentException {
- if ((id < MIN_ID_VALUE) || (id > MAX_ID_VALUE)) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidValue("id"));
- }
-
- mId = id;
- mLocal = local;
- }
-
- /**
- * Returns the PIN ID.
- * <p>
- * <b>Note:</b> This method is based on the P2 reference data for PIN
- * related commands as specified in ISO/IEC 7816-4 in chapter 7.5 (Basic
- * security handling). The ID indicates the number of the reference data
- * (qualifier) according to ISO/IEC 7816-4.
- *
- * @return The PIN ID.
- */
- public final int getID() {
- return mId;
- }
-
- /**
- * Identifies if the PIN is local or global.
- * <p>
- * <b>Note:</b> This method is based on the P2 reference data for PIN
- * related commands as specified in ISO/IEC 7816-4 in chapter 7.5 (Basic
- * security handling). Local set to true indicates specific reference
- * data and local set to false indicates global reference data according
- * to ISO/IEC 7816-4.
- *
- * @return True if the PIN is local. Otherwise false.
- */
- public final boolean isLocal() {
- return mLocal;
- }
- }
-}
diff --git a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/Channel.java b/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/Channel.java
deleted file mode 100644
index 473c2d3..0000000
--- a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/Channel.java
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright (C) 2011, The Android Open Source Project
- *
- * 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.
- */
-/*
- * Contributed by: Giesecke & Devrient GmbH.
- */
-
-package org.simalliance.openmobileapi;
-
-import java.io.IOException;
-
-import org.simalliance.openmobileapi.service.ISmartcardServiceChannel;
-import org.simalliance.openmobileapi.service.SmartcardError;
-
-import android.os.RemoteException;
-
-/**
- * Instances of this class represent an ISO7816-4 channel opened to a secure
- * element. It can be either a logical channel or the default channel. They can
- * be used to send APDUs to the secure element. Channels are opened by calling
- * the Session.openBasicChannel(byte[]) or Session.openLogicalChannel(byte[])
- * methods.
- *
- * @see <a href="http://simalliance.org">SIMalliance Open Mobile API v2.02</a>
- */
-public class Channel {
-
- private Session mSession;
-
- private final ISmartcardServiceChannel mChannel;
- private final SEService mService;
- private final Object mLock = new Object();
-
- Channel(SEService service, Session session, ISmartcardServiceChannel channel) {
- mService = service;
- mSession = session;
- mChannel = channel;
- }
-
- /**
- * Closes this channel to the Secure Element. If the method is called when
- * the channel is already closed, this method will be ignored. The close()
- * method shall wait for completion of any pending transmit(byte[] command)
- * before closing the channel.
- */
- public void close() {
- if (mService == null || !mService.isConnected()) {
- throw new IllegalStateException("service not connected to system");
- }
- if (mChannel == null) {
- throw new IllegalStateException("channel must not be null");
- }
- if (!isClosed()) {
- synchronized (mLock) {
- SmartcardError error = new SmartcardError();
- try {
- mChannel.close(error);
- } catch (RemoteException e) {
- throw new IllegalStateException(e.getMessage());
- }
- SEService.checkForException(error);
- }
- }
- }
-
- /**
- * Tells if this channel is closed.
- *
- * @return <code>true</code> if the channel is closed, <code>false</code> otherwise.
- */
- public boolean isClosed() {
- if (mService == null || mService.isConnected() == false) {
- throw new IllegalStateException("service not connected to system");
- }
- if (mChannel == null) {
- throw new IllegalStateException("channel must not be null");
- }
- try {
- return mChannel.isClosed();
- } catch (RemoteException e) {
- throw new IllegalStateException(e.getMessage());
- }
- }
-
- /**
- * Returns a boolean telling if this channel is the basic channel.
- *
- * @return <code>true</code> if this channel is a basic channel. <code>false</code> if
- * this channel is a logical channel.
- */
- public boolean isBasicChannel() {
- if (mService == null || mService.isConnected() == false) {
- throw new IllegalStateException("service not connected to system");
- }
- if (mChannel == null) {
- throw new IllegalStateException("channel must not be null");
- }
- try {
- return mChannel.isBasicChannel();
- } catch (RemoteException e) {
- throw new IllegalStateException(e.getMessage());
- }
- }
-
- /**
- * Transmit an APDU command (as per ISO7816-4) to the secure element and
- * wait for the response. The underlying layers might generate as much TPDUs
- * as necessary to transport this APDU. The transport part is invisible from
- * the application. <br>
- * The system ensures the synchronization between all the concurrent calls
- * to this method, and that only one APDU will be sent at a time,
- * irrespective of the number of TPDUs that might be required to transport
- * it to the SE. <br>
- * The channel information in the class byte in the APDU will be completely
- * ignored. The underlying system will add any required information to
- * ensure the APDU is transported on this channel. There are restrictions on
- * the set of commands that can be sent: <br>
- *
- * <ul>
- * <li>MANAGE_CHANNEL commands are not allowed.</li>
- * <li>SELECT by DF Name (p1=04) are not allowed.</li>
- * <li>CLA bytes with channel numbers are de-masked.</li>
- * </ul>
- *
- * @param command the APDU command to be transmitted, as a byte array.
- *
- * @return the response received, as a byte array.
- *
- * @throws IOException if there is a communication problem to the reader or the Secure Element.
- * @throws IllegalStateException if the channel is used after being closed.
- * @throws IllegalArgumentException if the command byte array is less than 4 bytes long.
- * @throws IllegalArgumentException if the length of the APDU is not coherent with the length of the command byte array.
- * @throws SecurityException if the command is filtered by the security
- * policy
- */
- public byte[] transmit(byte[] command) throws IOException {
- if (mService == null || mService.isConnected() == false) {
- throw new IllegalStateException("service not connected to system");
- }
- if (mChannel == null) {
- throw new IllegalStateException("channel must not be null");
- }
-
- // if channel is closed is checked within service transmit call.
-
- byte[] response;
- synchronized( mLock ) {
- SmartcardError error = new SmartcardError();
- try {
- response = mChannel.transmit(command, error);
- } catch (RemoteException e1) {
- throw new IllegalStateException(e1.getMessage());
- } catch (Exception e) {
- throw new IOException(e.getMessage());
- }
- SEService.checkForException(error);
- }
- return response;
- }
- /**
- * Get the session that has opened this channel.
- *
- * @return the session object this channel is bound to.
- */
- public Session getSession() {
- return mSession;
- }
- /**
- * Returns the data as received from the application select command inclusively the status word.
- * The returned byte array contains the data bytes in the following order:
- * [<first data byte>, ..., <last data byte>, <sw1>, <sw2>]
- * @return The data as returned by the application select command inclusively the status word.
- * Only the status word if the application select command has no returned data.
- * Returns null if an application select command has not been performed or the selection response can not
- * be retrieved by the reader implementation.
- */
- public byte[] getSelectResponse()
- {
- if (mService == null || mService.isConnected() == false) {
- throw new IllegalStateException("service not connected to system");
- }
- if (mChannel == null) {
- throw new IllegalStateException("channel must not be null");
- }
- try {
- if (mChannel.isClosed()) {
- throw new IllegalStateException("channel is closed");
- }
- } catch (RemoteException e1) {
- throw new IllegalStateException(e1.getMessage());
- }
-
- byte[] response;
- try {
- response = mChannel.getSelectResponse();
- } catch (RemoteException e) {
- throw new IllegalStateException(e.getMessage());
- }
-
- if(response != null && response.length == 0)
- response = null;
- return response;
- }
-
- /**
- * Performs a selection of the next Applet on this channel that matches to the partial AID specified
- * in the openBasicChannel(byte[] aid) or openLogicalChannel(byte[] aid) method.
- * This mechanism can be used by a device application to iterate through all Applets
- * matching to the same partial AID.
- * If selectNext() returns true a new Applet was successfully selected on this channel.
- * If no further Applet exists with matches to the partial AID this method returns false
- * and the already selected Applet stays selected.
- *
- * @return <code>true</code> if new Applet was successfully selected.
- <code>false</code> if no further Applet exists which matches the partial AID.
- *
- * @throws IOException if there is a communication problem to the reader or the Secure Element.
- * @throws IllegalStateException if the channel is used after being closed or it is not connected.
- * @throws SecurityException if the command is filtered by the security policy
- * @throws UnsupportedOperationException if selectNext is not supported by Secure Element.
- */
- public boolean selectNext() throws IOException {
- if (mService == null || mService.isConnected() == false) {
- throw new IllegalStateException("service not connected to system");
- }
- if (mChannel == null) {
- throw new IllegalStateException("channel must not be null");
- }
- try {
- if (mChannel.isClosed()) {
- throw new IllegalStateException("channel is closed");
- }
- } catch (RemoteException e1) {
- throw new IllegalStateException(e1.getMessage());
- }
-
- boolean response = false;
- synchronized( mLock ) {
- SmartcardError error = new SmartcardError();
- try {
- response = mChannel.selectNext(error);
- } catch (RemoteException e1) {
- throw new IllegalStateException(e1.getMessage());
- } catch (Exception e) {
- throw new IOException(e.getMessage());
- }
- SEService.checkForException(error);
- }
- return response;
- }
-
- // ******************************************************************
- // package private methods
- // ******************************************************************
-}
diff --git a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/FileViewProvider.java b/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/FileViewProvider.java
deleted file mode 100644
index cd56552..0000000
--- a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/FileViewProvider.java
+++ /dev/null
@@ -1,1476 +0,0 @@
-/*
- * Copyright 2013 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi;
-
-import java.io.IOException;
-
-import org.simalliance.openmobileapi.internal.BerTlvParser;
-import org.simalliance.openmobileapi.internal.ByteArrayConverter;
-import org.simalliance.openmobileapi.internal.ErrorStrings;
-import org.simalliance.openmobileapi.internal.TlvEntryWrapper;
-import org.simalliance.openmobileapi.util.CommandApdu;
-import org.simalliance.openmobileapi.util.ResponseApdu;
-
-/**
- * This Provider class simplifies file operations on Secure Elements with a file
- * structure specified in ISO/IEC 7816-4. Methods are provided that allow
- * reading or writing file content. If the read or write operation is not
- * allowed because security conditions are not satisfied a SecurityException
- * will be returned. It must be considered that a file operation can only be
- * applied onto a file which has a corresponding structure.
- * <p>
- * <b>Prerequisites:</b> This Provider requires an ISO/IEC 7816-4 compliant file
- * system on the SE. If this file system is implemented by an Applet within the
- * SE then this Applet must be preselected before this Provider can be used, in
- * case that the Applet is not default selected (e.g. the GSM Applet as default
- * selected Applet on UICC)
- * <p>
- * <b>Notes:</b>
- * <ul>
- * <li>If used by multiple threads, synchronization is up to the application.</li>
- * <li>Each operation needs an access to the Secure Element. If the access can
- * not be granted because of a closed channel or a missing security condition
- * the called method will return an error.</li>
- * <li>Using the basic channel for accessing the file system of the UICC
- * (provided by the default selected GSM Applet) implies the risk of
- * interferences from the baseband controller as the baseband controller works
- * internally on the basic channel and can modify the current file selected
- * state on the basic channel any time. This means a file selection performed by
- * this FileViewProvider does not guarantee a permanent file selection state on
- * the ICC's basic channel and the application using the FileViewProvider has to
- * take care of having the needed file selection state. The FileViewProvider
- * itself cannot avoid interferences from the baseband Open Mobile API
- * specification V2.0.2 29/63 controller on the basic channel but the risk could
- * be minimized if the application using the FileViewProvider performs implicit
- * selections for the file operation or performs the file selection immediately
- * before the file operation.</li>
- * </ul>
- */
-public class FileViewProvider extends Provider {
-
- /**
- * Indicates for file operation methods that the currently selected file
- * shall be used for the file operation.
- */
- public static final int CURRENT_FILE = 0;
-
- /**
- * Indicates that the demanded information is not available.
- */
- public static final int INFO_NOT_AVAILABLE = -1;
-
- /**
- * Indicates for record write operations that the record shell be appended.
- */
- public static final int APPEND_RECORD = -1;
-
- /**
- * The number of digits that should form a File ID.
- */
- private static final int FILE_ID_LENGTH = 4;
-
- /**
- * The minimum value for a short EF identifier.
- */
- private static final int SFI_MIN_VALUE = 1;
-
- /**
- * The maximum value for a short EF identifier.
- */
- private static final int SFI_MAX_VALUE = 30;
-
- /**
- * The minimum value for a record number.
- */
- private static final int REC_NUMBER_MIN_VALUE = 0x00;
-
- /**
- * The maximum value for a record number.
- */
- private static final int REC_NUMBER_MAX_VALUE = 0xFE;
-
- /**
- * The maximum value of a long offset.
- */
- private static final int OFFSET_LONG_MAX_VALUE = 0x7FFF;
-
- /**
- * The maximum value of a short offset.
- */
- private static final int OFFSET_SHORT_MAX_VALUE = 0xFF;
-
- /**
- * The minimum value for a File ID.
- */
- private static final int FID_MIN_VALUE = 0x0001;
-
- /**
- * The maximum value for a File ID.
- */
- private static final int FID_MAX_VALUE = 0xFFFE;
-
- /**
- * The byte length of a File ID.
- */
- private static final int FID_LENGTH = 0x02;
-
- /**
- * File Control Parameter contain information of a selected file. FCPs are
- * returned after a file select operation.
- * <p>
- * <b>Note:</b> This class is based on ISO/IEC 7816-4 FCP returned by the
- * SELECT command as specified in ISO/IEC 7816-4 in chapter 5.3.3 (File
- * control information) in table 12 (File control parameter data objects).
- */
- public class FCP {
-
- // FCP tags.
- /**
- * FCP template TLV tag.
- */
- public static final byte FCPTAG_FCP_TEMPLATE = (byte) 0x62;
- /**
- * FCP file size TLV tag.
- */
- public static final byte FCPTAG_FILE_SIZE = (byte) 0x80;
- /**
- * FCP total file size TLV tag.
- */
- public static final byte FCPTAG_TOTAL_FILE_SIZE = (byte) 0x81;
- /**
- * FCP file descriptor TLV tag.
- */
- public static final byte FCPTAG_FILE_DESCRIPTOR = (byte) 0x82;
- /**
- * FCP file ID TLV tag.
- */
- public static final byte FCPTAG_FILE_ID = (byte) 0x83;
- /**
- * FCP ShortFileIdentifier TLV tag.
- */
- public static final byte FCPTAG_SFI = (byte) 0x88;
- /**
- * FCP Life Cycle Status TLV tag.
- */
- public static final byte FCPTAG_LCS = (byte) 0x8A;
-
- // File types.
- /**
- * File type = DF.
- */
- public static final byte FILETYPE_DF = 0;
- /**
- * File type = EF.
- */
- public static final byte FILETYPE_EF = 1;
-
- // FileStructure types.
- /**
- * EF structure: No information given.
- */
- public static final int FILESTRUCTURE_NO_EF = 0;
- /**
- * EF structure: Transparent structure.
- */
- public static final int FILESTRUCTURE_TRANSPARENT = 1;
- /**
- * EF structure: Linear structure, fixed size.
- */
- public static final int FILESTRUCTURE_LINEAR_FIXED = 2;
- /**
- * EF structure: Linear structure, variable size.
- */
- public static final int FILESTRUCTURE_LINEAR_VARIABLE = 3;
- /**
- * EF structure: Cyclic structure, fixed size.
- */
- public static final int FILESTRUCTURE_CYCLIC = 4;
-
- // LCS values.
- /**
- * Life Cycle Status: No information given.
- */
- public static final int LCS_NO_INFORMATION_GIVEN = 0;
- /**
- * Life Cycle Status: Creation state.
- */
- public static final int LCS_CREATION_STATE = 1;
- /**
- * Life Cycle Status: Initialization state.
- */
- public static final int LCS_INITIALISATION_STATE = 2;
- /**
- * Life Cycle Status: Operational state (activated).
- */
- public static final int LCS_OPERATIONAL_STATE_ACTIVATED = 3;
- /**
- * Life Cycle Status: Operational state (deactivated).
- */
- public static final int LCS_OPERATIONAL_STATE_DEACTIVATED = 4;
- /**
- * Life Cycle Status: Termination state.
- */
- public static final int LCS_TERMINATION_STATE = 5;
-
- /**
- * The complete FCP data as byte array.
- */
- private byte[] mRawFcpData;
-
- /**
- * Initializes a new instance of the FCP class.
- *
- * @param rawTlvData The data to be used in the initialization.
- *
- * @throws IllegalArgumentException if the specified rawTlvData does not
- * contain valid FCP data.
- */
- public FCP(byte[] rawTlvData) throws IllegalArgumentException {
- // Find and get the FCP data
- BerTlvParser parser = new BerTlvParser();
- int fcpStartPosition = parser.searchTag(
- rawTlvData, new byte[] {FCPTAG_FCP_TEMPLATE}, 0);
- mRawFcpData = new TlvEntryWrapper(
- rawTlvData,
- fcpStartPosition,
- parser)
- .getValue();
- }
-
- /**
- * Returns the complete FCP as byte array.
- * <p>
- * <b>Note:</b> This method is based on the FCP control parameter as
- * specified in ISO/IEC 7816-4 in chapter 5.3.3 (File control
- * information) in table 12 (File control parameter data objects).
- *
- * @return The complete FCP as byte array.
- */
- public byte[] getFCP() {
- return mRawFcpData;
- }
-
- /**
- * Returns the file size of the selected file (Number of data bytes in
- * the file, excluding structural information).
- * <p>
- * <b>Note:</b> This method is based on the FCP control parameter as
- * specified in ISO/IEC 7816-4 in chapter 5.3.3 (File control
- * information) in table 12 (File control parameter data objects).
- *
- * @return The file size depending on the file type:
- * <ul>
- * <li>DF/MF: the total file size represents the sum of the file
- * sizes of all the EFs and DFs contained in this DF plus the
- * amount of available memory in this DF. The size of the
- * structural information of the selected DF itself is not
- * included.</li> <li>EF: the total file size represents the
- * allocated memory for the content and the structural
- * information (if any) of this EF.</li>
- * </ul>
- * <p>
- * INFO_NOT_AVAILABLE if the information is not available.
- */
- public int getFileSize() {
- BerTlvParser parser = new BerTlvParser();
- try {
- int position = parser.searchTag(
- mRawFcpData, new byte[] {FCPTAG_FILE_SIZE}, 0);
- byte[] fileSize = new TlvEntryWrapper(
- mRawFcpData, position, parser).getValue();
- return ByteArrayConverter.byteArrayToInt(fileSize);
- } catch (IllegalArgumentException e) {
- return INFO_NOT_AVAILABLE;
- }
- }
-
- /**
- * Returns the total file size of the selected file (Number of data
- * bytes in the file, including structural information if any).
- * <p>
- * <b>Note:</b> This method is based on the FCP control parameter as
- * specified in ISO/IEC 7816-4 in chapter 5.3.3 (File control
- * information) in table 12 (File control parameter data objects).
- *
- * @return The total file size depending on the file type:
- * <ul>
- * <li>DF/MF: the total file size represents the sum of the file
- * sizes of all the EFs and DFs contained in this DF plus the
- * amount of available memory in this DF. The size of the
- * structural information of the selected DF itself is not
- * included. </li> <li>EF: the total file size represents the
- * allocated memory for the content and the structural
- * information (if any) of this EF.</li>
- * </ul>
- * INFO_NOT_AVAILABLE if the information is not available.
- */
- public int getTotalFileSize() {
- BerTlvParser parser = new BerTlvParser();
- try {
- int position = parser.searchTag(
- mRawFcpData, new byte[] {FCPTAG_TOTAL_FILE_SIZE}, 0);
- byte[] totalFileSize = new TlvEntryWrapper(
- mRawFcpData, position, parser).getValue();
- return ByteArrayConverter.byteArrayToInt(totalFileSize);
- } catch (IllegalArgumentException e) {
- return INFO_NOT_AVAILABLE;
- }
- }
-
- /**
- * Returns the file identifier of the selected file.
- * <p>
- * <b>Note:</b> This method is based on the FCP control parameter as
- * specified in ISO/IEC 7816-4 in chapter 5.3.3 (File control
- * information) in table 12 (File control parameter data objects).
- *
- * @return The file identifier of the selected file. INFO_NOT_AVAILABLE
- * if the FID of the selected file is not available.
- */
- public int getFID() {
- BerTlvParser parser = new BerTlvParser();
- try {
- int position = parser.searchTag(
- mRawFcpData, new byte[] {FCPTAG_FILE_ID}, 0);
- byte[] fileId = new TlvEntryWrapper(
- mRawFcpData, position, parser).getValue();
- return ByteArrayConverter.byteArrayToInt(fileId);
- } catch (IllegalArgumentException e) {
- return INFO_NOT_AVAILABLE;
- }
- }
-
- /**
- * Returns the short file identifier of the selected EF file.
- * <p>
- * <b>Note:</b> This method is based on the FCP control parameter as
- * specified in ISO/IEC 7816-4 in chapter 5.3.3 (File control
- * information) in table 12 (File control parameter data objects).
- *
- * @return The short file identifier of the selected file.
- * INFO_NOT_AVAILABLE if selected file is not an EF or an SFI is
- * not available.
- */
- public int getSFI() {
- BerTlvParser parser = new BerTlvParser();
- try {
- int position = parser.searchTag(
- mRawFcpData, new byte[] {FCPTAG_SFI}, 0);
- byte[] sfi = new TlvEntryWrapper(
- mRawFcpData, position, parser).getValue();
-
- // If FCPTAG_SFI is present, there are two possibilities:
- if (sfi.length == 0) {
- // If the value length is 0, selection by SFI is not
- // supported
- return INFO_NOT_AVAILABLE;
- } else if (sfi.length == 1) {
- // From ISO/IEC 7816-9 5.3.3.1
- // If tag '88' is present with a length set to one and
- // if bits 8 to 4 of the data element are not all equal and
- // if bits 3 to 1 are set to 000, then bits 8 to 4 encode
- // the short EF identifier (a number from one to thirty).
- if ((sfi[0] & (byte) 0x07) == (byte) 0x00) {
- // Shift 3 bits to the right
- return (int) (sfi[0] >>> 3);
- } else {
- return INFO_NOT_AVAILABLE;
- }
- } else {
- return INFO_NOT_AVAILABLE;
- }
- } catch (IllegalArgumentException e) {
- // If FCPTAG_SFI is not present, there might be two reasons:
- // 1) If card supports selection by SFI, the bits 5 to 1 of FID
- // encode the SFI
- // TODO: implement this case
-
- // 2) Card might no support selection by SFI
- return INFO_NOT_AVAILABLE;
- }
- }
-
- /**
- * Returns the maximum record size in case of a record based EF.
- * <p>
- * <b>Note:</b> This method is based on the FCP control parameter as
- * specified in ISO/IEC 7816-4 in chapter 5.3.3 (File control
- * information) in table 12 (File control parameter data objects).
- *
- * @return The maximum record size in case of a record based EF.
- * INFO_NOT_AVAILABLE if the currently selected file is not
- * record based or the information can not be fetched.
- */
- public int getMaxRecordSize() {
- BerTlvParser parser = new BerTlvParser();
- try {
- int position = parser.searchTag(
- mRawFcpData, new byte[] {FCPTAG_FILE_DESCRIPTOR}, 0);
- byte[] fileDescriptor = new TlvEntryWrapper(
- mRawFcpData, position, parser).getValue();
- if (fileDescriptor.length < 3) {
- // No MaxRecordSize
- return INFO_NOT_AVAILABLE;
- } else {
- byte[] maxRecSize;
- if (fileDescriptor.length == 3) {
- maxRecSize = new byte[1];
- } else {
- maxRecSize = new byte[2];
- }
-
- System.arraycopy(fileDescriptor, 2, maxRecSize, 0,
- maxRecSize.length);
- return ByteArrayConverter.byteArrayToInt(maxRecSize);
- }
- } catch (IllegalArgumentException e) {
- return INFO_NOT_AVAILABLE;
- }
- }
-
- /**
- * Returns the number of records stored in the EF in case of a record
- * based EF.
- * <p>
- * <b>Note:</b> This method is based on the FCP control parameter as
- * specified in ISO/IEC 7816-4 in chapter 5.3.3 (File control
- * information) in table 12 (File control parameter data objects).
- *
- * @return The number of records stored in the EF in case of a record
- * based EF. INFO_NOT_AVAILABLE if the currently selected file
- * is not record based or the information can not be fetched.
- */
- public int getNumberOfRecords() {
- BerTlvParser parser = new BerTlvParser();
- try {
- int position = parser.searchTag(
- mRawFcpData, new byte[] {FCPTAG_FILE_DESCRIPTOR}, 0);
- byte[] fileDescriptor = new TlvEntryWrapper(
- mRawFcpData, position, parser).getValue();
-
- if (fileDescriptor.length < 5) {
- return INFO_NOT_AVAILABLE;
- } else {
- byte[] numberOfRecords;
- if (fileDescriptor.length == 5) {
- numberOfRecords = new byte[1];
- } else {
- numberOfRecords = new byte[2];
- }
-
- System.arraycopy(fileDescriptor, 4, numberOfRecords, 0,
- numberOfRecords.length);
- return ByteArrayConverter.byteArrayToInt(numberOfRecords);
- }
- } catch (IllegalArgumentException e) {
- return INFO_NOT_AVAILABLE;
- }
- }
-
- /**
- * Returns the file type of the currently selected file.
- * <p>
- * <b>Note: </b> This method is based on the FCP control parameter as
- * specified in ISO/IEC 7816-4 in chapter 5.3.3 (File control
- * information) in table 12 (File control parameter data objects). The
- * file type is based on the definition in table 14 (File descriptor
- * byte).
- *
- * @return The file type:
- * <ul>
- * <li>(0) DF</li> <li>(1) EF</li>
- * </ul>
- * INFO_NOT_AVAILABLE if the information can not be fetched.
- */
- public int getFileType() {
- BerTlvParser parser = new BerTlvParser();
- try {
- int position = parser.searchTag(
- mRawFcpData, new byte[] {FCPTAG_FILE_DESCRIPTOR}, 0);
- byte[] fileDescriptor = new TlvEntryWrapper(
- mRawFcpData, position, parser).getValue();
-
- // Mask interesting bits to decide if file type is DF.
- boolean isDf = ((fileDescriptor[0] & 0xBF) == 0x38);
-
- if (isDf) {
- return FILETYPE_DF;
- } else {
- return FILETYPE_EF;
- }
- } catch (IllegalArgumentException e) {
- return INFO_NOT_AVAILABLE;
- }
- }
-
- /**
- * Returns the structure type of the selected EF.
- * <p>
- * <b>Note:</b> This method is based on the FCP control parameter as
- * specified in ISO/IEC 7816-4 in chapter 5.3.3 (File control
- * information) in table 12 (File control parameter data objects). The
- * file type is based on the definition in table 14 (File descriptor
- * byte).
- *
- * @return The structure type of the selected file:
- * <ul>
- * <li>(0) NO_EF</li> <li>(1) TRANSPARENT</li> <li>(2)
- * LINEAR_FIXED</li> <li>(3) LINEAR_VARIABLE</li> <li>(4) CYCLIC
- * </li>
- * </ul>
- * INFO_NOT_AVAILABLE if the information can not be fetched.
- */
- public int getFileStructure() {
- BerTlvParser parser = new BerTlvParser();
- try {
- int position = parser.searchTag(
- mRawFcpData, new byte[] {FCPTAG_FILE_DESCRIPTOR}, 0);
- byte[] fileDescriptor = new TlvEntryWrapper(
- mRawFcpData, position, parser).getValue();
-
- switch (fileDescriptor[0] & 0x07) {
- case 0:
- return FILESTRUCTURE_NO_EF;
- case 1:
- return FILESTRUCTURE_TRANSPARENT;
- case 2:
- case 3:
- return FILESTRUCTURE_LINEAR_FIXED;
- case 4:
- case 5:
- return FILESTRUCTURE_LINEAR_VARIABLE;
- case 6:
- case 7:
- return FILESTRUCTURE_CYCLIC;
- default:
- return INFO_NOT_AVAILABLE;
- }
- } catch (IllegalArgumentException e) {
- return INFO_NOT_AVAILABLE;
- }
- }
-
- /**
- * Returns the life cycle state of the currently selected file.
- * <p>
- * <b>Note:</b> This method is based on the FCP control parameter as
- * specified in ISO/IEC 7816-4 in chapter 5.3.3 (File control
- * information) in table 12 (File control parameter data objects). The
- * LCS is based on the definition in table 13 (Life cycle status byte).
- *
- * @return Returns the life cycle state of the currently selected file.
- * <ul>
- * <li>(0) NO_INFORMATION_GIVEN</li> <li>(1) CREATION_STATE</li>
- * <li>(2) INITIALISATION_STATE</li> <li>(3)
- * OPERATIONAL_STATE_ACTIVATED</li> <li>(4)
- * OPERATIONAL_STATE_DEACTIVATED</li> <li>(5) TERMINATION_STATE
- * </li>
- * </ul>
- * INFO_NOT_AVAILABLE if the information can not be fetched.
- */
- public int getLCS() {
- BerTlvParser parser = new BerTlvParser();
- try {
- int position = parser.searchTag(
- mRawFcpData, new byte[] {FCPTAG_LCS}, 0);
- byte[] lcs = new TlvEntryWrapper(
- mRawFcpData, position, parser).getValue();
-
- switch (lcs[0]) {
- case 0:
- return LCS_NO_INFORMATION_GIVEN;
- case 1:
- return LCS_CREATION_STATE;
- case 3:
- return LCS_INITIALISATION_STATE;
- case 5:
- case 7:
- return LCS_OPERATIONAL_STATE_ACTIVATED;
- case 4:
- case 6:
- return LCS_OPERATIONAL_STATE_DEACTIVATED;
- case 12:
- case 13:
- case 14:
- case 15:
- return LCS_TERMINATION_STATE;
- default:
- return INFO_NOT_AVAILABLE;
- }
- } catch (IllegalArgumentException e) {
- return INFO_NOT_AVAILABLE;
- }
- }
- }
-
- /**
- * Record class serves as container for record data. The created Record (as
- * immutable object) can be used to read record data from a file or to write
- * record data to a file.
- */
- public class Record {
-
- /**
- * The number of this record.
- */
- private int mNumber;
-
- /**
- * The data of this record.
- */
- private byte[] mData;
-
- /**
- * Creates a Record instance which can be used to store record data.
- *
- * @param number The record number that shall be stored.
- * @param data The data that shall be stored.
- *
- * @throws IllegalArgumentException if the defined record ID is invalid
- * or if the data is too long.
- */
- public Record(int number, byte[] data) throws IllegalArgumentException {
-
- if (!(REC_NUMBER_MIN_VALUE <= number
- && number <= REC_NUMBER_MAX_VALUE)
- && !(number == APPEND_RECORD)) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidValue("number"));
- }
-
- if (data == null) {
- throw new IllegalArgumentException(
- ErrorStrings.paramNull("data"));
- }
-
- if (data.length == 0 || data.length > CommandApdu.MAX_DATA_LENGTH) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidArrayLength("data"));
- }
-
- mNumber = number;
- mData = data;
- }
-
- /**
- * Returns the data of this record.
- *
- * @return The data of this record.
- */
- public byte[] getData() {
- return mData;
- }
-
- /**
- * Returns the record number of this record.
- *
- * @return The record number of this record.
- */
- public int getNumber() {
- return mNumber;
- }
- }
-
- /**
- * Encapsulates the defined channel by a FileViewProvider object that can be
- * used for performing file operations on it.
- * <p>
- * <b>Note:</b> A file must be selected before a file operation can be
- * performed. The file can be implicitly selected via a short file
- * identifier (SFI) by the file operation method itself or explicitly by
- * defining the file ID (FID) with selectByFID(int) or path with
- * selectByPath(String, boolean).
- *
- * @param channel The channel that shall be used by this Provider for file
- * operations.
- *
- * @throws IllegalStateException if the defined channel is closed.
- */
- public FileViewProvider(Channel channel) throws IllegalStateException {
- super(channel);
- }
-
- /**
- * Selects the file specified by a path. The path references the Secure
- * Element file by a path (concatenation of file IDs and the order of the
- * file IDs is always in the direction "parent to child") in following
- * notation: "DF1:DF2:EF1". e.g. "0023:0034:0043". The defined path is
- * applied to the Secure Element as specified in ISO/IEC 7816-4. Note: For
- * performing read or write operations on a file the last knot in the path
- * must reference an EF that can be read or written.
- * <p>
- * <b>Note:</b>
- * <ul>
- * <li>A file must be selected before a file operation can be performed.</li>
- * <li>This method is based on the ISO/IEC 7816-4 command SELECT.</li>
- * </ul>
- *
- * @return The FCP containing information to the selected file.
- *
- * @param path The path that references a file (DF or EF) on the Secure
- * Element. This path shall not contain the current DF or MF at the
- * beginning of the path.
- * @param fromCurrentDF If true then the path is selected from the current
- * DF, if false then the path is selected from the MF.
- *
- * @throws IllegalStateException if the defined channel is closed.
- * @throws IllegalArgumentException if the file couldn't be selected.
- * TODO: should be an IllegalReferenceError
- * @throws IllegalArgumentException if the defined path is invalid.
- * @throws SecurityException if the operation is not allowed because the
- * security conditions are not satisfied.
- * @throws UnsupportedOperationException if this operation is not supported.
- * @throws IOException Lower-lever API exception.
- */
- public FCP selectByPath(String path, boolean fromCurrentDF)
- throws IllegalStateException,
- IllegalArgumentException, SecurityException,
- UnsupportedOperationException, IOException {
-
- if (path == null) {
- throw new IllegalArgumentException(
- ErrorStrings.paramNull("path"));
- }
-
- if (path.isEmpty()) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidArrayLength("path"));
- }
-
- String[] fileId = path.split(":");
- byte[] pathByteArray = new byte[fileId.length * FILE_ID_LENGTH / 2];
-
- for (int i = 0; i < fileId.length; i++) {
- // Check that fileId[i] has a valid coding
- if (fileId[i].length() != FILE_ID_LENGTH) {
- throw new IllegalArgumentException(
- "Path elements must be 4-characters long.");
- }
- int fid = Integer.parseInt(fileId[i], 16);
- if (!(FID_MIN_VALUE <= fid && fid <= FID_MAX_VALUE)
- || fid == 0x3FFF) {
- // 3FFF is reserved
- throw new IllegalArgumentException(ErrorStrings.INVALID_FID);
- }
-
- // Convert to bytes and copy to pathByteArray
- System.arraycopy(ByteArrayConverter.hexStringToByteArray(fileId[i]), 0,
- pathByteArray, i * FILE_ID_LENGTH / 2, FILE_ID_LENGTH / 2);
- }
-
- // Form and send the APDU
- CommandApdu apdu = new CommandApdu(getChannel());
- apdu.setCla(CommandApdu.CLA_INTERINDUSTRY);
- apdu.setIns(CommandApdu.INS_SELECT);
- if (fromCurrentDF) {
- apdu.setP1((byte) 0x09);
- } else {
- apdu.setP1((byte) 0x08);
- }
- apdu.setP2((byte) 0x04);
- apdu.setData(pathByteArray);
- byte[] responseApdu = apdu.sendApdu();
-
- // Parse the response
- int swValue = ResponseApdu.getResponseStatusWordValue(responseApdu);
- switch (swValue) {
- case ResponseApdu.SW_NO_FURTHER_QUALIFICATION:
- return new FCP(ResponseApdu.getResponseData(responseApdu));
- case ResponseApdu.SW_SECURITY_STATUS_NOT_SATISFIED:
- throw new SecurityException(
- ErrorStrings.SECURITY_STATUS_NOT_SATISFIED);
- case ResponseApdu.SW_FUNC_NOT_SUPPORTED:
- throw new UnsupportedOperationException();
- case ResponseApdu.SW_FILE_OR_APP_NOT_FOUND:
- // TODO: should be an IllegalReferenceError
- throw new IllegalArgumentException(ErrorStrings.FILE_NOT_FOUND);
- case ResponseApdu.SW_INS_NOT_SUPPORTED:
- throw new UnsupportedOperationException();
- default:
- throw new IOException(ErrorStrings.unexpectedStatusWord(swValue));
- }
- }
-
- /**
- * Selects the file specified by the FID. The file ID references the Secure
- * Element file (DF or EF) by a FID. The FID consists of a two byte value as
- * defined in ISO/IEC 7816-4.
- * <p>
- * <b>Notes:</b>
- * <ul>
- * <li>A file must be selected before a file operation can be performed.</li>
- * <li>This method is based on the ISO/IEC 7816-4 command SELECT.</li>
- * </ul>
- *
- * @return The FCP containing information of the selected file.
- *
- * @param fileID The FID that references the file (DF or EF) on the Secure
- * Element. The FID must be in the range of (0x0000-0xFFFF).
- *
- * @throws IllegalStateException if the defined channel is closed.
- * @throws IllegalArgumentException if the file couldn't be selected.
- * TODO: should be an IllegalReferenceError
- * @throws IllegalArgumentException if the defined fileID is not valid.
- * @throws SecurityException if the operation is not allowed because the
- * security conditions are not satisfied.
- * @throws UnsupportedOperationException if this operation is not supported.
- * @throws IOException Lower-lever API exception.
- */
- public FCP selectByFID(int fileID) throws IllegalStateException,
- IllegalArgumentException, SecurityException,
- UnsupportedOperationException, IOException {
-
- // Check that fileID is in the allowed ranges
- if (!(FID_MIN_VALUE <= fileID && fileID <= FID_MAX_VALUE)
- || (fileID == 0x3FFF)) {
- // 3FFF is reserved
- throw new IllegalArgumentException(ErrorStrings.INVALID_FID);
- }
-
- // Form and send the APDU
- CommandApdu apdu = new CommandApdu(getChannel());
- apdu.setCla(CommandApdu.CLA_INTERINDUSTRY);
- apdu.setIns(CommandApdu.INS_SELECT);
- apdu.setP1((byte) 0x00);
- apdu.setP2((byte) 0x04);
- byte[] data = new byte[FID_LENGTH];
- System.arraycopy(ByteArrayConverter.intToByteArray(fileID), 2, data, 0, data.length);
- apdu.setData(data);
- byte[] responseApdu = apdu.sendApdu();
-
- // Parse the response
- int swValue = ResponseApdu.getResponseStatusWordValue(responseApdu);
- switch (swValue) {
- case ResponseApdu.SW_NO_FURTHER_QUALIFICATION:
- return new FCP(ResponseApdu.getResponseData(responseApdu));
- case ResponseApdu.SW_SECURITY_STATUS_NOT_SATISFIED:
- throw new SecurityException(
- ErrorStrings.SECURITY_STATUS_NOT_SATISFIED);
- case ResponseApdu.SW_WRONG_DATA:
- // TODO: should be an IllegalReferenceError
- throw new IllegalArgumentException(ErrorStrings.FILE_NOT_FOUND);
- case ResponseApdu.SW_FUNC_NOT_SUPPORTED:
- throw new UnsupportedOperationException();
- case ResponseApdu.SW_FILE_OR_APP_NOT_FOUND:
- // TODO: should be an IllegalReferenceError
- throw new IllegalArgumentException(ErrorStrings.FILE_NOT_FOUND);
- case ResponseApdu.SW_INS_NOT_SUPPORTED:
- throw new UnsupportedOperationException();
- default:
- throw new IOException(ErrorStrings.unexpectedStatusWord(swValue));
- }
- }
-
- /**
- * Selects the parent DF of the current DF. The parent DF of the currently
- * selected file is selected according to ISO/IEC 7816-4. If the currently
- * selected file has no parent then nothing will be done.
- * <p>
- * <b>Note:</b>
- * <ul>
- * <li>A file must be selected before a file operation can be performed.</li>
- * <li>This method is based on the ISO/IEC 7816-4 command SELECT.</li>
- * </ul>
- *
- * @return The FCP containing information of the selected file.
- *
- * @throws IllegalStateException if the defined channel is closed.
- * @throws IllegalArgumentException if the file couldn't be selected.
- * TODO: should be an IllegalReferenceError
- * @throws SecurityException if the operation is not allowed because the
- * security conditions are not satisfied.
- * @throws UnsupportedOperationException if this operation is not supported.
- * @throws IOException Lower-lever API exception.
- */
- public FCP selectParent() throws IllegalStateException,
- SecurityException,
- UnsupportedOperationException, IOException {
-
- // Form and send the APDU
- CommandApdu apdu = new CommandApdu(getChannel());
- apdu.setCla(CommandApdu.CLA_INTERINDUSTRY);
- apdu.setIns(CommandApdu.INS_SELECT);
- apdu.setP1((byte) 0x03);
- apdu.setP2((byte) 0x04);
- apdu.setLE((byte) 0x00);
- byte[] responseApdu = apdu.sendApdu();
-
- // Parse response
- int swValue = ResponseApdu.getResponseStatusWordValue(responseApdu);
- switch (swValue) {
- case ResponseApdu.SW_NO_FURTHER_QUALIFICATION:
- return new FCP(ResponseApdu.getResponseData(responseApdu));
- case ResponseApdu.SW_FILE_OR_APP_NOT_FOUND:
- // TODO: should be an IllegalReferenceError
- throw new IllegalArgumentException(ErrorStrings.FILE_NOT_FOUND);
- case ResponseApdu.SW_SECURITY_STATUS_NOT_SATISFIED:
- throw new SecurityException(
- ErrorStrings.SECURITY_STATUS_NOT_SATISFIED);
- case ResponseApdu.SW_INS_NOT_SUPPORTED:
- throw new UnsupportedOperationException();
- default:
- throw new IOException(ErrorStrings.unexpectedStatusWord(swValue));
- }
- }
-
- /**
- * Returns the record which corresponds to the specified record number. If
- * the record is not found then null will be returned.
- * <p>
- * <b>Note:</b> This method is based on the ISO/IEC 7816-4 command READ
- * RECORD.
- *
- * @return The record which corresponds to the specified record ID.
- *
- * @param sfi The SFI of the file which shall be selected for this read
- * operation. CURRENT_FILE can be applied if the file is already
- * selected. The sfi must be in the range of (1-30).
- * @param recNumber The record number that references the record that should
- * be read.
- *
- * @throws IllegalStateException if the used channel is closed, if no file
- * is currently selected, if the currently selected file is not a
- * record based file or if the record couldn't be read.
- * @throws IllegalArgumentException if the file couldn't be selected via
- * SFI.
- * TODO: should be an IllegalReferenceError
- * @throws IllegalArgumentException if the defined sfi is not valid or if
- * the defined record ID is invalid.
- * @throws SecurityException if the operation is not allowed because the
- * security conditions are not satisfied.
- * @throws UnsupportedOperationException if this operation is not supported.
- * @throws IOException Lower-lever API exception.
- */
- public Record readRecord(int sfi, int recNumber)
- throws IllegalStateException,
- IllegalArgumentException, SecurityException,
- UnsupportedOperationException, IOException {
-
- if ((sfi < SFI_MIN_VALUE || sfi > SFI_MAX_VALUE)
- && (sfi != CURRENT_FILE)) {
- throw new IllegalArgumentException(ErrorStrings.INVALID_SFI);
- }
-
- if (recNumber < REC_NUMBER_MIN_VALUE
- || recNumber > REC_NUMBER_MAX_VALUE) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidValue("recordNumber"));
- }
-
- // Prepare and send the APDU
- CommandApdu apdu = new CommandApdu(getChannel());
- apdu.setCla(CommandApdu.CLA_INTERINDUSTRY);
- apdu.setIns(CommandApdu.INS_READ_RECORD_B2);
- apdu.setP1((byte) recNumber);
- // SFI represents the most significant 5 bits
- apdu.setP2((byte) ((sfi << 3) | 4));
- apdu.setLE((byte) 0x00);
- byte[] apduResponse = apdu.sendApdu();
-
- // Handle the response
- int swValue = ResponseApdu.getResponseStatusWordValue(apduResponse);
- switch (swValue) {
- case ResponseApdu.SW_NO_FURTHER_QUALIFICATION:
- return new Record(
- recNumber,
- ResponseApdu.getResponseData(apduResponse));
- case ResponseApdu.SW_COMMAND_INCOMPATIBLE:
- throw new IllegalStateException(ErrorStrings.NO_RECORD_BASED_FILE);
- case ResponseApdu.SW_SECURITY_STATUS_NOT_SATISFIED:
- throw new SecurityException(
- ErrorStrings.SECURITY_STATUS_NOT_SATISFIED);
- case ResponseApdu.SW_FUNC_NOT_SUPPORTED:
- throw new UnsupportedOperationException(
- ErrorStrings.OPERATION_NOT_SUPORTED);
- case ResponseApdu.SW_FILE_OR_APP_NOT_FOUND:
- if (sfi == CURRENT_FILE) {
- throw new IllegalStateException(
- ErrorStrings.FILE_NOT_FOUND);
- } else {
- // TODO: should be an IllegalReferenceError
- throw new IllegalArgumentException(
- ErrorStrings.FILE_NOT_FOUND);
- }
- case ResponseApdu.SW_RECORD_NOT_FOUND:
- // If the record is not found, return null.
- return null;
- case ResponseApdu.SW_INS_NOT_SUPPORTED:
- throw new UnsupportedOperationException(
- ErrorStrings.OPERATION_NOT_SUPORTED);
- default:
- throw new IOException(ErrorStrings.unexpectedStatusWord(swValue));
- }
- }
-
- /**
- * Writes a record into the specified file.
- * <p>
- * <b>Note:</b> This method is based on the ISO/IEC 7816-4 command APPEND
- * RECORD and UPDATE RECORD (which replaces existing bytes).
- *
- * @param sfi The SFI of the file which shall be selected for this write
- * operation. CURRENT_FILE can be applied if the file is already
- * selected. The SFI must be in the range of (1-30).
- * @param rec The Record that shall be written.
- *
- * @throws IllegalStateException if the used channel is closed, if no file
- * is currently selected, if the currently selected file is not a
- * record based file or if the record couldn't be written.
- * @throws IllegalArgumentException if the file couldn't be selected via
- * SFI.
- * TODO: should be an IllegalReferenceError
- * @throws IllegalArgumentException if the defined Record is invalid, if the
- * defined SFI is not valid.
- * @throws SecurityException if the operation is not allowed because the
- * security conditions are not satisfied.
- * @throws UnsupportedOperationException if this operation is not supported.
- * @throws IOException Lower-lever API exception.
- */
- public void writeRecord(int sfi, Record rec)
- throws IllegalArgumentException, IllegalStateException,
- SecurityException,
- UnsupportedOperationException, IOException {
-
- if (rec == null) {
- throw new IllegalArgumentException(
- ErrorStrings.paramNull("rec"));
- }
-
- if ((sfi < SFI_MIN_VALUE || sfi > SFI_MAX_VALUE)
- && (sfi != CURRENT_FILE)) {
- throw new IllegalArgumentException(ErrorStrings.INVALID_SFI);
- }
-
- // Prepare and send the APDU
- CommandApdu apdu = new CommandApdu(getChannel());
- byte[] apduResponse = {};
- if (rec.getNumber() == APPEND_RECORD) {
- apdu.setCla(CommandApdu.CLA_INTERINDUSTRY);
- apdu.setIns(CommandApdu.INS_APPEND_RECORD);
- apdu.setP1((byte) 0x00);
- // SFI is most significant 5 bits
- apdu.setP2((byte) ((sfi << 3) | 0));
- apdu.setData(rec.getData());
- } else {
- // Try to update record. If record is not found, try appending it.
- // Prepare and send the APDU
- apdu.setCla(CommandApdu.CLA_INTERINDUSTRY);
- apdu.setIns(CommandApdu.INS_UPDATE_RECORD_DC);
- apdu.setP1((byte) rec.getNumber());
- // SFI is most significant 5 bits
- apdu.setP2((byte) ((sfi << 3) | 4));
- apdu.setData(rec.getData());
- }
-
- apduResponse = apdu.sendApdu();
- // Handle the response
- int swValue = ResponseApdu.getResponseStatusWordValue(apduResponse);
- switch (swValue) {
- case ResponseApdu.SW_NO_FURTHER_QUALIFICATION:
- return;
- case ResponseApdu.SW_WRONG_LENGTH:
- throw new IllegalArgumentException(ErrorStrings.WRONG_LENGTH);
- case ResponseApdu.SW_MEMORY_FAILURE:
- throw new IllegalStateException(ErrorStrings.MEMORY_FAILURE);
- case ResponseApdu.SW_COMMAND_INCOMPATIBLE:
- throw new IllegalStateException(ErrorStrings.NO_RECORD_BASED_FILE);
- case ResponseApdu.SW_SECURITY_STATUS_NOT_SATISFIED:
- throw new SecurityException(
- ErrorStrings.SECURITY_STATUS_NOT_SATISFIED);
- case ResponseApdu.SW_COMMAND_NOT_ALLOWED:
- throw new IllegalStateException(ErrorStrings.NO_CURRENT_FILE);
- case ResponseApdu.SW_FUNC_NOT_SUPPORTED:
- throw new UnsupportedOperationException(
- ErrorStrings.OPERATION_NOT_SUPORTED);
- case ResponseApdu.SW_FILE_OR_APP_NOT_FOUND:
- if (sfi == CURRENT_FILE) {
- throw new IllegalStateException(
- ErrorStrings.NO_CURRENT_FILE);
- } else {
- // TODO: should be an IllegalReferenceError
- throw new IllegalArgumentException(
- ErrorStrings.FILE_NOT_FOUND);
- }
- case ResponseApdu.SW_RECORD_NOT_FOUND:
- throw new IllegalArgumentException(ErrorStrings.RECORD_NOT_FOUND);
- case ResponseApdu.SW_NOT_ENOUGH_MEMORY:
- throw new IllegalStateException(ErrorStrings.NOT_ENOUGH_MEMORY);
- case ResponseApdu.SW_INS_NOT_SUPPORTED:
- throw new UnsupportedOperationException(
- ErrorStrings.OPERATION_NOT_SUPORTED);
- default:
- // ISO/IEC 7816-4, Chapter 7.3.2:
- // In this group of commands, SW1-SW2 set to '63CX' indicates a
- // successful change of memory state, but after an internal retry
- // routine; 'X' > '0' encodes the number of retries; 'X' = '0'
- // means that no counter is provided.
- if (ResponseApdu.SW_CTR_MIN <= swValue
- && swValue <= ResponseApdu.SW_CTR_MAX) {
- return;
- } else {
- throw new IOException(
- ErrorStrings.unexpectedStatusWord(swValue));
- }
- }
- }
-
- /**
- * Returns the record numbers that contains the defined search pattern.
- * <p>
- * <b>Note:</b>This method is based on the ISO/IEC 7816-4 command SEARCH
- * RECORD with simple search.
- *
- * @return A list of record numbers (position 1..n of the record in the
- * file) of the records which match to the search pattern. If no
- * record matches then null will be returned.
- *
- * @param sfi The SFI of the file which shall be selected for this search
- * operation. CURRENT_FILE can be applied if the file is already
- * selected. The sfi must be in the range of (1-30).
- * @param searchPattern The pattern that shall match with Records.
- *
- * @throws IllegalStateException if the used channel is closed, if no file
- * is currently selected, if the currently selected file is not a
- * record based file or if the data couldn't be searched.
- * @throws IllegalArgumentException if the file couldn't be selected via
- * SFI.
- * TODO: should be an IllegalReferenceError
- * @throws IllegalArgumentException if the defined SFI is not valid, if the
- * search pattern is empty or if the search pattern is too long.
- * @throws SecurityException if the operation is not allowed because the
- * security conditions are not satisfied.
- * @throws UnsupportedOperationException if this operation is not supported.
- * @throws IOException Lower-lever API exception.
- */
- public int[] searchRecord(int sfi, byte[] searchPattern)
- throws IllegalStateException,
- IllegalArgumentException, SecurityException,
- UnsupportedOperationException, IOException {
-
- if ((sfi < SFI_MIN_VALUE || sfi > SFI_MAX_VALUE)
- && (sfi != CURRENT_FILE)) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidValue("sfi"));
- }
-
- if (searchPattern == null) {
- throw new IllegalArgumentException(
- ErrorStrings.paramNull("searchPattern"));
- }
-
- if (searchPattern.length == 0
- || searchPattern.length > CommandApdu.MAX_DATA_LENGTH) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidArrayLength("searchPattern"));
- }
-
- // Form the APDU.
- CommandApdu apdu = new CommandApdu(getChannel());
- apdu.setCla(CommandApdu.CLA_INTERINDUSTRY);
- apdu.setIns(CommandApdu.INS_SEARCH_RECORD);
- // Start search from Rec #1
- apdu.setP1((byte) 0x01);
- // SFI is most significant 5 bits
- // 0x04: Forward search from record in P1
- apdu.setP2((byte) ((sfi << 3) | 4));
- apdu.setData(searchPattern);
- apdu.setLE((byte) 0x00);
- byte[] apduResponse = apdu.sendApdu();
-
- // Handle the response
- int swValue = ResponseApdu.getResponseStatusWordValue(apduResponse);
- switch (swValue) {
- case ResponseApdu.SW_NO_FURTHER_QUALIFICATION:
- byte[] responseData = ResponseApdu.getResponseData(apduResponse);
- if (responseData.length > 0) {
- int[] recordNumbers = new int[responseData.length];
-
- for (int i = 0; i < responseData.length; i++) {
- // AND with 0xFF to erase sign information.
- recordNumbers[i] = (byte) (responseData[i] & (byte) 0xFF);
- }
-
- return recordNumbers;
- } else {
- return null;
- }
- case ResponseApdu.SW_COMMAND_INCOMPATIBLE:
- throw new IllegalStateException(ErrorStrings.NO_RECORD_BASED_FILE);
- case ResponseApdu.SW_SECURITY_STATUS_NOT_SATISFIED:
- throw new SecurityException(
- ErrorStrings.SECURITY_STATUS_NOT_SATISFIED);
- case ResponseApdu.SW_COMMAND_NOT_ALLOWED:
- throw new IllegalStateException(ErrorStrings.NO_CURRENT_FILE);
- case ResponseApdu.SW_FUNC_NOT_SUPPORTED:
- throw new UnsupportedOperationException(
- ErrorStrings.OPERATION_NOT_SUPORTED);
- case ResponseApdu.SW_FILE_OR_APP_NOT_FOUND:
- // TODO: should be an IllegalReferenceError
- throw new IllegalArgumentException(ErrorStrings.FILE_NOT_FOUND);
- case ResponseApdu.SW_INS_NOT_SUPPORTED:
- throw new UnsupportedOperationException(
- ErrorStrings.OPERATION_NOT_SUPORTED);
- default:
- throw new IOException(ErrorStrings.unexpectedStatusWord(swValue));
- }
- }
-
- /**
- * Reads content of the selected transparent file at the position specified
- * by offset and length.
- * <p>
- * <b>Note:</b>This method is based on the ISO/IEC 7816-4 command READ
- * BINARY.
- *
- * @return The data read from the file or null if no content is available.
- *
- * @param sfi The SFI of the file which shall be selected for this read
- * operation. CURRENT_FILE can be applied if the file is already
- * selected. The sfi must be in the range of (1-30).
- * @param offset Defines the start point of the file where the data should
- * be read.
- * @param length Defines the length of the data which should be read. If set
- * to 0, all possible data within the limit of
- * {@link CommandApdu#MAX_DATA_LENGTH} will be read.
- *
- * @throws IllegalStateException if the used channel is closed, if no file
- * is currently selected, if the currently selected file is not a
- * transparent file or if the data couldn't be read.
- * @throws IllegalArgumentException if the file couldn't be selected via
- * SFI.
- * TODO: should be an IllegalReferenceError
- * @throws IllegalArgumentException if the defined sfi is not valid or if
- * the defined offset and length couldn't be applied.
- * @throws SecurityException if the operation is not allowed because the
- * security conditions are not satisfied.
- * @throws UnsupportedOperationException if this operation is not supported.
- * @throws IOException Lower-lever API exception.
- */
- public byte[] readBinary(int sfi, int offset, int length)
- throws IllegalStateException,
- IllegalArgumentException, SecurityException,
- UnsupportedOperationException, IOException {
-
- if ((sfi < SFI_MIN_VALUE || sfi > SFI_MAX_VALUE)
- && (sfi != FileViewProvider.CURRENT_FILE)) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidValue("sfi"));
- }
-
- if (offset < 0) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidValue("offset"));
- }
-
- if (length < 0) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidValue("length"));
- }
-
- // Form the APDU
- CommandApdu apdu = new CommandApdu(getChannel());
- apdu.setCla(CommandApdu.CLA_INTERINDUSTRY);
- apdu.setIns(CommandApdu.INS_READ_BINARY_B0);
- if (sfi == CURRENT_FILE) {
- if (offset > OFFSET_LONG_MAX_VALUE) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidValue("offset"));
- }
- if (length > OFFSET_LONG_MAX_VALUE) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidValue("length"));
- }
-
- // b8 = 0. b7 to b1 encode the 7 MSBs of offset.
- apdu.setP1((byte) (0x7F & (offset >> 8)));
- apdu.setP2((byte) offset);
- } else {
- if (offset > OFFSET_SHORT_MAX_VALUE) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidValue("offset"));
- }
- if (length > OFFSET_SHORT_MAX_VALUE) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidValue("length"));
- }
-
- // Set b8 = 1, b7 = b6 = 0 and b5 to b1 encode sfi.
- apdu.setP1((byte) (0x80 | sfi));
- apdu.setP2((byte) offset);
- }
- apdu.setLE(length);
- // Send the APDU
- byte[] apduResponse = apdu.sendApdu();
-
- // Handle the response
- int swValue = ResponseApdu.getResponseStatusWordValue(apduResponse);
- switch (swValue) {
- case ResponseApdu.SW_NO_FURTHER_QUALIFICATION:
- return ResponseApdu.getResponseData(apduResponse);
- case ResponseApdu.SW_COMMAND_INCOMPATIBLE:
- // Not a binary file
- throw new IllegalStateException(
- ErrorStrings.NO_TRANSPARENT_FILE);
- case ResponseApdu.SW_SECURITY_STATUS_NOT_SATISFIED:
- throw new SecurityException(
- ErrorStrings.SECURITY_STATUS_NOT_SATISFIED);
- case ResponseApdu.SW_COMMAND_NOT_ALLOWED:
- // No file selected
- throw new IllegalStateException(
- ErrorStrings.NO_CURRENT_FILE);
- case ResponseApdu.SW_FUNC_NOT_SUPPORTED:
- throw new UnsupportedOperationException();
- case ResponseApdu.SW_FILE_OR_APP_NOT_FOUND:
- if (sfi == CURRENT_FILE) {
- throw new IllegalStateException(
- ErrorStrings.FILE_NOT_FOUND);
- } else {
- // TODO: should be an IllegalReferenceError
- throw new IllegalArgumentException(
- ErrorStrings.FILE_NOT_FOUND);
- }
- case ResponseApdu.SW_INS_NOT_SUPPORTED:
- throw new UnsupportedOperationException();
- default:
- throw new IOException(ErrorStrings.unexpectedStatusWord(swValue));
- }
- }
-
- /**
- * Writes the defined data into the selected file at the position specified
- * by offset and length.
- * <p>
- * <b>Note:</b>This method is based on the ISO/IEC 7816-4 command UPDATE
- * BINARY.
- *
- * @param sfi The SFI of the file which shall be selected for this write
- * operation. CURRENT_FILE can be applied if the file is already
- * selected. The sfi must be in the range of (1-30).
- * @param data The data which shall be written.
- *
- * @param offset Defines the position in the file where the data should be
- * stored.
- * @param length Defines the length of the data which shall be written.
- *
- * @throws IllegalStateException if the used channel is closed, if no file
- * is currently selected, if the currently selected file is not a
- * transparent file or if the record couldn't be written.
- * @throws IllegalArgumentException if the file couldn't be selected via
- * SFI.
- * TODO: should be an IllegalReferenceError
- * @throws IllegalArgumentException if the defined sfi is not valid, if the
- * defined data array is empty or too short or if the defined offset
- * and length couldn't be applied.
- * @throws SecurityException if the operation is not allowed because the
- * security conditions are not satisfied.
- * @throws UnsupportedOperationException if this operation is not supported.
- * @throws IOException Lower-lever API exception.
- */
- public void writeBinary(int sfi, byte[] data, int offset, int length)
- throws IllegalStateException,
- IllegalArgumentException, SecurityException,
- UnsupportedOperationException, IOException {
-
- if (data == null) {
- throw new IllegalArgumentException(
- ErrorStrings.paramNull("data"));
- }
-
- if (data.length == 0
- || data.length > CommandApdu.MAX_DATA_LENGTH
- || data.length != length) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidArrayLength("data"));
- }
-
- if ((sfi < SFI_MIN_VALUE || sfi > SFI_MAX_VALUE)
- && (sfi != FileViewProvider.CURRENT_FILE)) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidValue("sfi"));
- }
-
- if (offset < 0) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidValue("offset"));
- }
-
- if (length < 0) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidValue("length"));
- }
-
- CommandApdu apdu = new CommandApdu(getChannel());
- apdu.setCla(CommandApdu.CLA_INTERINDUSTRY);
- apdu.setIns(CommandApdu.INS_UPDATE_BINARY_D6);
- if (sfi == CURRENT_FILE) {
- if (offset > OFFSET_LONG_MAX_VALUE) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidValue("offset"));
- }
-
- // b8 = 0. b7 to b1 encode the 7 MSBs of offset.
- apdu.setP1((byte) (0x7F & (offset >> 8)));
- apdu.setP2((byte) offset);
- } else {
- if (offset > OFFSET_SHORT_MAX_VALUE) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidValue("offset"));
- }
-
- // Set b8 = 1, b7 = b6 = 0 and b5 to b1 encode sfi.
- apdu.setP1((byte) (0x80 | (0x9F & sfi)));
- apdu.setP2((byte) offset);
- }
- apdu.setData(data);
- byte[] apduResponse = apdu.sendApdu();
-
- int swValue = ResponseApdu.getResponseStatusWordValue(apduResponse);
- switch (swValue) {
- case ResponseApdu.SW_NO_FURTHER_QUALIFICATION:
- return;
- case ResponseApdu.SW_COMMAND_INCOMPATIBLE:
- // Not a binary file
- throw new IllegalStateException(
- ErrorStrings.NO_TRANSPARENT_FILE);
- case ResponseApdu.SW_SECURITY_STATUS_NOT_SATISFIED:
- throw new SecurityException(
- ErrorStrings.SECURITY_STATUS_NOT_SATISFIED);
- case ResponseApdu.SW_COMMAND_NOT_ALLOWED:
- // No file selected
- throw new IllegalStateException(
- ErrorStrings.NO_CURRENT_FILE);
- case ResponseApdu.SW_FUNC_NOT_SUPPORTED:
- throw new UnsupportedOperationException();
- case ResponseApdu.SW_FILE_OR_APP_NOT_FOUND:
- if (sfi == CURRENT_FILE) {
- throw new IllegalStateException(
- ErrorStrings.FILE_NOT_FOUND);
- } else {
- // TODO: should be an IllegalReferenceError
- throw new IllegalArgumentException(
- ErrorStrings.FILE_NOT_FOUND);
- }
- case ResponseApdu.SW_WRONG_PARAMETERS_P1P2:
- throw new IllegalArgumentException(
- ErrorStrings.OFFSET_OUTSIDE_EF);
- case ResponseApdu.SW_INS_NOT_SUPPORTED:
- throw new UnsupportedOperationException();
- default:
- throw new IOException(ErrorStrings.unexpectedStatusWord(swValue));
- }
- }
-}
diff --git a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/PKCS15Provider.java b/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/PKCS15Provider.java
deleted file mode 100644
index 075fdb1..0000000
--- a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/PKCS15Provider.java
+++ /dev/null
@@ -1,952 +0,0 @@
-/*
- * Copyright 2013 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-
-import org.simalliance.openmobileapi.FileViewProvider.FCP;
-import org.simalliance.openmobileapi.internal.ByteArrayConverter;
-import org.simalliance.openmobileapi.internal.DerTlvCoder;
-import org.simalliance.openmobileapi.internal.DerTlvParser;
-import org.simalliance.openmobileapi.internal.ErrorStrings;
-import org.simalliance.openmobileapi.internal.OidParser;
-import org.simalliance.openmobileapi.internal.TlvEntryWrapper;
-
-
-/**
- * This Provider class offers basic services to access a PKCS#15 file system.
- * This Provider requires a PKCS#15 data structure on the Secure Element and a
- * Channel instance allowing the access to this PKCS#15 data structure.
- */
-public class PKCS15Provider extends Provider {
-
- /**
- * The FileViewProvider object that will allow interaction with
- * the underlying file system.
- */
- private FileViewProvider mFileViewProvider;
-
- /**
- * The content of EF(ODF).
- */
- private byte[] mOdfContent;
- /**
- * The content of EF(TokenInfo).
- */
- private byte[] mTokenInfoContent;
-
- /**
- * Default PKCS#15 AID.
- */
- public static final byte[] AID_PKCS15 = {(byte) 0xA0, (byte) 0x00,
- (byte) 0x00, (byte) 0x00, (byte) 0x63, (byte) 0x50, (byte) 0x4B,
- (byte) 0x43, (byte) 0x53, (byte) 0x2D, (byte) 0x31, (byte) 0x35};
-
- // Relevant file identifiers
- /**
- * The FID of the EF(DIR).
- */
- private static final int FID_EF_DIR = 0x2F00;
- /**
- * The FID of the EF(ODF).
- */
- private static final int FID_EF_ODF = 0x5031;
- /**
- * The FID of the EF(TokenInfo).
- */
- private static final int FID_EF_TOKEN_INFO = 0x5032;
-
- // Relevant TLV tags
- /**
- * PKCS#15 application template TLV tag.
- */
- private static final byte[] TLV_TAG_PKCS15_APP_TEMPLATE = {(byte) 0x61};
- /**
- * PKCS#15 DF path TLV tag.
- */
- private static final byte[] TLV_TAG_PKCS15_PATH = {(byte) 0x51};
- /**
- * PKCS#15 OID TLV tag.
- */
- private static final byte[] TLV_TAG_OID = {(byte) 0x06};
- /**
- * PKCS#15 Sequence TLV tag.
- */
- private static final byte[] TLV_TAG_SEQUENCE = {(byte) 0x30};
- /**
- * PKCS#15 Private Key TLV tag.
- */
- private static final byte[] TLV_TAG_PRIVATE_KEY = {(byte) 0xA0};
- /**
- * PKCS#15 Public Key TLV tag.
- */
- private static final byte[] TLV_TAG_PUBLIC_KEY = {(byte) 0xA1};
- /**
- * PKCS#15 trusted Public Key TLV tag.
- */
- private static final byte[] TLV_TAG_PUBLIC_KEY_TRUSTED = {(byte) 0xA2};
- /**
- * PKCS#15 Secret Key TLV tag.
- */
- private static final byte[] TLV_TAG_SECRET_KEY = {(byte) 0xA3};
- /**
- * PKCS#15 Certificate TLV tag.
- */
- private static final byte[] TLV_TAG_CERTIFICATE = {(byte) 0xA4};
- /**
- * PKCS#15 trusted Certificate TLV tag.
- */
- private static final byte[] TLV_TAG_CERTIFICATE_TRUSTED = {(byte) 0xA5};
- /**
- * PKCS#15 useful Certificate TLV tag.
- */
- private static final byte[] TLV_TAG_CERTIFICATE_USEFUL = {(byte) 0xA6};
- /**
- * PKCS#15 Data Object TLV tag.
- */
- private static final byte[] TLV_TAG_DATA_OBJECT = {(byte) 0xA7};
- /**
- * PKCS#15 Authenticate Object TLV tag.
- */
- private static final byte[] TLV_TAG_AUTHENTICATE_OBJECT = {(byte) 0xA8};
-
- /**
- * Encapsulates the defined channel by a PKCS#15 file system object. This
- * method checks the presence of the EF(ODF) (Object Directory File) with
- * file identifier 5031 and of the EF(TokenInfo) with file identifier 5032.
- * Both files are mandatory and must be present in a valid PKCS#15 file
- * system. This method must first try to select EF(ODF) and EF(TokenInfo) on
- * the provided channel. If the select fails, this method must try to locate
- * a DF(PKCS#15) in the legacy file system using the EF(DIR) according to
- * the data structure described in chapter 5.4 of the PKCS#15 specification
- * (v1.1).
- *
- * @param channel The channel that shall be used by this Provider for file
- * operations.
- *
- * @throws IOException if no PKCS#15 file system is detected on the provided
- * channel.
- * @throws IllegalStateException if the defined channel is closed.
- */
- public PKCS15Provider(Channel channel) throws IOException,
- IllegalStateException {
-
- // Call super constructor and initialize the FVP
- super(channel);
- mFileViewProvider = new FileViewProvider(channel);
-
- // Check if the PKCS#15 file structure is present in the current DF
- if (currentDirIsPkcs15FileStructure()) {
- mOdfContent = readOdf();
- mTokenInfoContent = readTokenInfo();
- } else {
- // If not present, read EF(DIR)
- FCP fcpEfDir;
- try {
- // Try selecting EF(DIR)
- fcpEfDir = mFileViewProvider.selectByPath(
- Integer.toHexString(FID_EF_DIR), false);
- } catch (IllegalArgumentException e) {
- // TODO: should be an IllegalReferenceError
- throw new IOException(ErrorStrings.PKCS15_NO_FS);
- }
-
- // Look for path element in EF(DIR)
- int numberOfRecords = fcpEfDir.getNumberOfRecords();
- for (int i = 0; i < numberOfRecords; i++) {
- // Read the record and get the data
- byte[] recordData = mFileViewProvider.readRecord(
- FileViewProvider.CURRENT_FILE, i + 1).getData();
-
- // Check if this record contains a path to a valid
- // PKCS#15 File Structure
- // TODO: support referencing by ADF (not implemented)
- if (recordContainsValidPath(recordData)) {
- mOdfContent = readOdf();
- mTokenInfoContent = readTokenInfo();
- return;
- }
- }
-
- // If all records has been read and no valid path has been found...
- throw new IOException(ErrorStrings.PKCS15_NO_FS);
- }
- }
-
- /**
- * Returns the raw content of the EF(ODF) (Object Directory File).
- *
- * @return The EF(ODF) as a byte array. Must not be null.
- *
- * @throws IllegalStateException if the defined channel is closed.
- */
- public byte[] getODF() throws IllegalStateException {
- return mOdfContent;
- }
-
- /**
- * Returns the raw content of the EF(TokenInfo).
- *
- * @return The EF(TokenInfo) as a byte array. Must not be null.
- */
- public byte[] getTokenInfo() {
- return mTokenInfoContent;
- }
-
- /**
- * Returns an array of EF(PrKDF) paths (Private Key Directory Files). The
- * PKCS#15 file system may contain zero, one or several EF(PrKDF).
- *
- * @return The array of EF(PrKDF) paths. May be null if empty.
- */
- public Path[] getPrivateKeyPaths() {
- ArrayList<Path> paths = new ArrayList<Path>();
- int position = 0;
- DerTlvParser parser = new DerTlvParser();
- byte[] odfContent = parser.getValidTlvData(getODF());
-
- while (position < odfContent.length) {
- // Parse the next DER entry
- TlvEntryWrapper derObject
- = new TlvEntryWrapper(odfContent, position, parser);
- if (isPrivateKeyTag(derObject.getTag())) {
- try {
- paths.add(decodePath(derObject.getValue()));
- } catch (IllegalArgumentException e) {
- // If path could not be parsed, ignore it
- }
- }
-
- // Increase the position
- position += derObject.getTotalLength();
- }
-
- if (paths.size() > 0) {
- return paths.toArray(new Path[paths.size()]);
- } else {
- return null;
- }
- }
-
- /**
- * Returns an array of EF(PuKDF) paths (Public Key Directory Files). The
- * PKCS#15 file system may contain zero, one or several EF(PuKDF).
- *
- * @return The array of EF(PuKDF) paths. May be null if empty.
- */
- public Path[] getPublicKeyPaths() {
- ArrayList<Path> paths = new ArrayList<Path>();
- int position = 0;
- DerTlvParser parser = new DerTlvParser();
- byte[] odfContent = parser.getValidTlvData(getODF());
-
- while (position < odfContent.length) {
- // Parse the next DER entry
- TlvEntryWrapper derObject
- = new TlvEntryWrapper(odfContent, position, parser);
- if (isPublicKeyTag(derObject.getTag())) {
- try {
- paths.add(decodePath(derObject.getValue()));
- } catch (IllegalArgumentException e) {
- // If path could not be parsed, ignore it
- }
- }
-
- // Increase the position
- position += derObject.getTotalLength();
- }
-
- if (paths.size() > 0) {
- return paths.toArray(new Path[paths.size()]);
- } else {
- return null;
- }
- }
-
- /**
- * Returns an array of EF(CDF) paths (Certificate Directory Files). The
- * PKCS#15 file system may contain zero, one or several EF(CDF).
- *
- * @return The array of EF(CDF) paths. May be null if empty.
- */
- public Path[] getCertificatePaths() {
- ArrayList<Path> paths = new ArrayList<Path>();
- int position = 0;
- DerTlvParser parser = new DerTlvParser();
- byte[] odfContent = parser.getValidTlvData(getODF());
-
- while (position < odfContent.length) {
- // Parse the next DER entry
- TlvEntryWrapper derObject
- = new TlvEntryWrapper(odfContent, position, parser);
- if (isCertificateTag(derObject.getTag())) {
- try {
- paths.add(decodePath(derObject.getValue()));
- } catch (IllegalArgumentException e) {
- // If path could not be parsed, ignore it
- }
- }
-
- // Increase the position
- position += derObject.getTotalLength();
- }
-
- if (paths.size() > 0) {
- return paths.toArray(new Path[paths.size()]);
- } else {
- return null;
- }
- }
-
- /**
- * Returns an array of EF(DODF) paths (Data Object Directory Files). The
- * PKCS#15 file system may contain zero, one or several EF(DODF).
- *
- * @return The array of EF(DODF) paths. May be null if empty.
- */
- public Path[] getDataObjPaths() {
- ArrayList<Path> paths = new ArrayList<Path>();
- int position = 0;
- DerTlvParser parser = new DerTlvParser();
- byte[] odfContent = parser.getValidTlvData(getODF());
-
- while (position < odfContent.length) {
- // Parse the next DER entry
- TlvEntryWrapper derObject
- = new TlvEntryWrapper(odfContent, position, parser);
- if (isDataObjectTag(derObject.getTag())) {
- try {
- paths.add(decodePath(derObject.getValue()));
- } catch (IllegalArgumentException e) {
- // If path could not be parsed, ignore it
- }
- }
-
- // Increase the position
- position += derObject.getTotalLength();
- }
-
- if (paths.size() > 0) {
- return paths.toArray(new Path[paths.size()]);
- } else {
- return null;
- }
- }
-
- /**
- * Returns an array of EF(AODF) paths (Authentication Object Directory
- * Files). The PKCS#15 file system may contain zero, one or several
- * EF(AODF).
- *
- * @return The array of EF(AODF) paths. May be null if empty.
- */
- public Path[] getAuthObjPaths() {
- ArrayList<Path> paths = new ArrayList<Path>();
- int position = 0;
- DerTlvParser parser = new DerTlvParser();
- byte[] odfContent = parser.getValidTlvData(getODF());
-
- while (position < odfContent.length) {
- // Parse the next DER entry
- TlvEntryWrapper derObject
- = new TlvEntryWrapper(odfContent, position, parser);
- if (isAuthenticationObjectTag(derObject.getTag())) {
- try {
- paths.add(decodePath(derObject.getValue()));
- } catch (IllegalArgumentException e) {
- // If path could not be parsed, ignore it
- }
- }
-
- // Increase the position
- position += derObject.getTotalLength();
- }
-
- if (paths.size() > 0) {
- return paths.toArray(new Path[paths.size()]);
- } else {
- return null;
- }
- }
-
- /**
- * Selects and reads a PKCS#15 file. The file may be a transparent or linear
- * fixed EF. The 'index' and 'length' fields of the Path instance will be
- * used according to chapter 6.1.5 of the PKCS#15 specification (v1.1). In
- * case of transparent EF, 'index' is the start offset in the file and
- * 'length' is the length to read. In case of linear fixed EF, 'index' is
- * the record to read.
- *
- * @param path Path of the file.
- *
- * @return The file content as a byte array. Or null if the referenced path
- * does not exist.
- *
- * @throws UnsupportedOperationException if this operation is not supported.
- * @throws SecurityException if the operation cannot be performed if a
- * security condition is not satisfied.
- * @throws IllegalArgumentException if the PKCS#15 file cannot be selected
- * or read. TODO: should be an IllegalReferenceError
- * @throws IOException Lower-lever API exception.
- * @throws IllegalStateException if the used channel is closed.
- */
- public byte[] readFile(Path path) throws SecurityException,
- UnsupportedOperationException, IOException,
- IllegalArgumentException, IllegalStateException {
-
- FCP fcp = mFileViewProvider.selectByPath(
- ByteArrayConverter.byteArrayToPathString(path.getPath()), true);
-
- // Check that it is an EF
- if (fcp.getFileType() != FCP.FILETYPE_EF) {
- // TODO: should be an IllegalReferenceError
- throw new IllegalArgumentException(
- "Could not read file: not an EF.");
- }
-
- // Determine whether it is binary or record-based file.
- if (fcp.getFileStructure() == FCP.FILESTRUCTURE_TRANSPARENT) {
- int index, length;
- if (path.hasIndexLength()) {
- index = path.getIndex();
- length = path.getLength();
- } else {
- index = 0;
- length = 0;
- }
-
- return mFileViewProvider.readBinary(
- FileViewProvider.CURRENT_FILE, index, length);
- } else {
- // We need the index to know which record to read.
- if (!path.hasIndexLength()) {
- // TODO: should be an IllegalReferenceError
- throw new IllegalArgumentException(
- "Could not read file: index not specified"
- + " in a record-based file.");
- }
-
- return mFileViewProvider.readRecord(FileViewProvider.CURRENT_FILE,
- path.getIndex()).getData();
- }
- }
-
- /**
- * Parses the raw content of an EF(DODF) and searches for a specific OID
- * Data Object. This method is a convenience method to simplify the access
- * to OID Data Objects by applications, as described in chapter 6.7.4 of the
- * PKCS#15 specification (v1.1). In many cases, the EF(DODF) contains a
- * simple OID Data Object with a Path object, in order to reference an
- * application-specific EF. For example, the OMA-DM specification requires a
- * EF(DODF) containing the OID 2.23.43.7.1, followed by a Path object,
- * referencing the EF(DM_Bootstrap).
- *
- * @param dodf The raw content of an EF(DODF) to parse.
- * @param oid The searched OID value (e.g. OMA-DM bootstrap OID is
- * 2.23.43.7.1).
- *
- * @return The raw object value if OID has been found, null if not found.
- *
- * @throws IllegalArgumentException if the OID is not correct.
- * @throws UnsupportedOperationException if this operation is not supported.
- */
- public byte[] searchOID(byte[] dodf, String oid)
- throws IllegalArgumentException, UnsupportedOperationException {
- byte[] encodedOid = OidParser.encodeOid(oid);
- DerTlvParser parser = new DerTlvParser();
- TlvEntryWrapper entry;
- try {
- entry = new TlvEntryWrapper(dodf, 0, parser);
- } catch (Exception e) {
- return null;
- }
-
- // Ensure that the first tag is a DataObject
- if (!Arrays.equals(entry.getTag(), TLV_TAG_DATA_OBJECT)) {
- return null;
- }
-
- // Get the actual content and start parsing it
- byte[] outerContent = entry.getValue();
- int outerPosition = 0;
- while (outerPosition < outerContent.length) {
- TlvEntryWrapper outerTlvEntry;
- try {
- outerTlvEntry = new TlvEntryWrapper(
- outerContent, outerPosition, parser);
- } catch (Exception e) {
- return null;
- }
-
- // Check if it is a sequence object
- if (Arrays.equals(outerTlvEntry.getTag(), TLV_TAG_SEQUENCE)) {
- int innerPosition = 0;
- byte[] innerContent = outerTlvEntry.getValue();
- TlvEntryWrapper innerTlvEntry;
- try {
- innerTlvEntry = new TlvEntryWrapper(
- innerContent, innerPosition, parser);
- } catch (Exception e) {
- outerPosition += outerTlvEntry.getTotalLength();
- continue;
- }
-
- // Check if first inner entry is an OID
- if (Arrays.equals(innerTlvEntry.getTag(), TLV_TAG_OID)) {
- // Check if the OID is the desired one
- if (Arrays.equals(encodedOid, innerTlvEntry.getValue())) {
- // If it is, return the value besides this OID
- innerPosition += innerTlvEntry.getTotalLength();
- try {
- innerTlvEntry = new TlvEntryWrapper(
- innerContent, innerPosition, parser);
- } catch (Exception e) {
- outerPosition += outerTlvEntry.getTotalLength();
- continue;
- }
-
- return innerTlvEntry.getValue();
- }
- }
- }
-
- // If it was not what it was expected, move to the next outer entry.
- outerPosition += outerTlvEntry.getTotalLength();
- }
-
- // If OID was not found, return null
- return null;
- }
-
- /**
- * Builds a Path object using a DER-encoded (see ITU X.690 for DER-Coding)
- * buffer.
- *
- * @param der the DER-encoded Path object as a byte array.
- *
- * @return The Path object.
- *
- * @throws IllegalArgumentException if the defined path is not a correctly
- * DER-encoded buffer.
- */
- public Path decodePath(byte[] der) throws IllegalArgumentException {
-
- // Start reading the sequence object
- DerTlvParser parser = new DerTlvParser();
- TlvEntryWrapper derPathObject = new TlvEntryWrapper(der, 0, parser);
- if (!Arrays.equals(derPathObject.getTag(), DerTlvCoder.TAG_SEQUENCE)) {
- throw new IllegalArgumentException(ErrorStrings.TLV_TAG_UNEXPECTED);
- }
- byte[] sequenceBytes = derPathObject.getValue();
-
- int position = 0;
-
- // Parse the next DER entry, which should be the path value.
- TlvEntryWrapper derPathValue = new TlvEntryWrapper(
- sequenceBytes, position, parser);
- if (!Arrays.equals(
- derPathValue.getTag(),
- DerTlvCoder.TAG_OCTET_STRING)) {
- throw new IllegalArgumentException(ErrorStrings.TLV_TAG_UNEXPECTED);
- }
- position += derPathValue.getTotalLength();
-
- // Check if index and length are present
- if (position >= sequenceBytes.length) {
- // They are not
- return new Path(derPathValue.getValue());
- } else {
- // Parse index
- TlvEntryWrapper derIndex = new TlvEntryWrapper(sequenceBytes,
- position, parser);
- if (!Arrays.equals(derIndex.getTag(), DerTlvCoder.TAG_INTEGER)) {
- throw new IllegalArgumentException(
- ErrorStrings.TLV_TAG_UNEXPECTED);
- }
- int index = ByteArrayConverter.byteArrayToInt(derIndex.getValue());
- position += derIndex.getTotalLength();
-
- // Parse length
- TlvEntryWrapper derLength = new TlvEntryWrapper(sequenceBytes,
- position, parser);
- if (!Arrays.equals(derLength.getTag(), DerTlvCoder.TAG_INTEGER)) {
- throw new IllegalArgumentException(
- ErrorStrings.TLV_TAG_UNEXPECTED);
- }
- int length = ByteArrayConverter.byteArrayToInt(derLength.getValue());
-
- return new Path(derPathValue.getValue(), index, length);
- }
- }
-
- /**
- * This class represents a Path object as defined in chapter 6.1.5 of the
- * PKCS#15 specification (v1.1).
- */
- public class Path {
-
- /**
- * Undefined value.
- */
- public static final int VALUE_UNDEFINED = -1;
-
- /**
- * The path itself.
- */
- private byte[] mPath;
-
- /**
- * For linear record files, mIndex shall be the record number (in the
- * ISO/IEC 7816-4 definition).
- *
- * For transparent files, mIndex can be used to specify an offset within
- * the file.
- */
- private Integer mIndex;
-
- /**
- * For linear record file, mLength can be set to 0 (if the card's
- * operating system allows an Le parameter equal to 0 in a READ RECORD
- * command). Lengths of fixed records may be found in the TokenInfo file
- * as well (see Section 6.9).
- *
- * For transparent file, mLength is the length of the segment to read.
- */
- private Integer mLength;
-
- /**
- * Builds a Path object without index and length (the path can be
- * absolute as well as relative).
- *
- * @param path the path as a byte array.
- *
- * @throws IllegalArgumentException if the path is not correct.
- */
- public Path(byte[] path) throws IllegalArgumentException {
- if (path == null) {
- throw new IllegalArgumentException(
- ErrorStrings.paramNull("path"));
- }
-
- mPath = new byte[path.length];
- System.arraycopy(path, 0, mPath, 0, path.length);
- mIndex = null;
- mLength = null;
- }
-
- /**
- * Builds a Path object with index and length (the path can be absolute
- * as well as relative).
- *
- * @param path The path as a byte array.
- * @param index The index value.
- * @param length The length value.
- *
- * @throws IllegalArgumentException if the path is not correct.
- */
- public Path(byte[] path, int index, int length)
- throws IllegalArgumentException {
- if (path == null) {
- throw new IllegalArgumentException(
- ErrorStrings.paramNull("path"));
- }
-
- if (index < 1) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidValue("index"));
- }
- if (length < 1) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidValue("length"));
- }
-
- mPath = new byte[path.length];
- System.arraycopy(path, 0, mPath, 0, path.length);
- mIndex = Integer.valueOf(index);
- mLength = Integer.valueOf(length);
- }
-
- /**
- * Returns the path field of this Path object.
- *
- * @return The path field.
- */
- public byte[] getPath() {
- return mPath;
- }
-
- /**
- * Checks whether this Path object has an index and length fields.
- *
- * @return True if the index and length field is present, false
- * otherwise.
- */
- public boolean hasIndexLength() {
- return mIndex != null && mLength != null;
- }
-
- /**
- * Returns the index field of this Path object. The value of this field
- * is undefined if the method hasIndexLength() returns false.
- *
- * @return The index field.
- */
- public int getIndex() {
- if (hasIndexLength()) {
- return mIndex.intValue();
- } else {
- return VALUE_UNDEFINED;
- }
- }
-
- /**
- * Returns the length field of this Path object. The value of this field
- * is undefined if the method hasIndexLength() returns false.
- *
- * @return The length field.
- */
- public int getLength() {
- if (hasIndexLength()) {
- return mLength.intValue();
- } else {
- return VALUE_UNDEFINED;
- }
- }
-
- /**
- * Encodes this Path object according to DER (see ITU X.690 for
- * DER-Coding).
- *
- * @return This Path object as a DER-encoded byte array.
- */
- public byte[] encode() {
- byte[] derCodedPath = DerTlvCoder.encodeOctetString(mPath);
-
- byte[] derCodedIndex;
- byte[] derCodedLength;
- if (hasIndexLength()) {
- derCodedIndex = DerTlvCoder.encodeInteger(mIndex);
- derCodedLength = DerTlvCoder.encodeInteger(mLength);
- } else {
- derCodedIndex = new byte[0];
- derCodedLength = new byte[0];
- }
-
- byte[] encodedDer = new byte[derCodedPath.length
- + derCodedIndex.length
- + derCodedLength.length];
- System.arraycopy(derCodedPath, 0, encodedDer, 0,
- derCodedPath.length);
- System.arraycopy(derCodedIndex, 0, encodedDer, derCodedPath.length,
- derCodedIndex.length);
- System.arraycopy(derCodedLength, 0, encodedDer, derCodedPath.length
- + derCodedIndex.length, derCodedLength.length);
-
- return DerTlvCoder.encodeSequence(encodedDer);
- }
- }
-
- /* **************************************** */
- /* Private methods */
- /* **************************************** */
-
- /**
- * Checks whether the currently selected directory contains a valid PKCS#15
- * file structure.
- *
- * @return true if the currently selected directory contains a valid PKCS#15
- * file structure, false otherwise.
- *
- * @throws IllegalStateException if the used channel is closed.
- */
- private boolean currentDirIsPkcs15FileStructure()
- throws IllegalStateException {
- try {
- // Check that EF(ODF) and EF(TokenInfo) are present
- mFileViewProvider.selectByFID(FID_EF_ODF);
- mFileViewProvider.selectByFID(FID_EF_TOKEN_INFO);
- return true;
- } catch (IllegalStateException e) {
- // Channel is closed
- throw e;
- } catch (Exception e) {
- return false;
- }
- }
-
- /**
- * Checks if a record entry in EF(DIR) contains a reference to a valid
- * PKCS#15 file structure.
- *
- * @param recordData The already-parsed TLV structure of the record.
- *
- * @return true if there is a valid reference to a PKCS#15 files structure,
- * false otherwise.
- */
- private boolean recordContainsValidPath(
- byte[] recordData) {
- int startPosition;
- DerTlvParser parser = new DerTlvParser();
-
- // Search for the PKCS#15 application template tag.
- try {
- startPosition = parser.searchTag(
- recordData, TLV_TAG_PKCS15_APP_TEMPLATE, 0);
- } catch (IllegalArgumentException e) {
- // If tag is not found...
- return false;
- }
-
- // Get the content of the PKCS#15 application template
- byte[] pkcs15RawData = new TlvEntryWrapper(
- recordData, startPosition, parser).getValue();
-
- // Search for the "path" tag
- try {
- startPosition = parser.searchTag(
- pkcs15RawData, TLV_TAG_PKCS15_PATH, startPosition);
- } catch (IllegalArgumentException e) {
- // If tag is not found...
- return false;
- }
-
- // Get the content of the Path
- byte [] rawPath = new TlvEntryWrapper(
- pkcs15RawData, startPosition, parser).getValue();
- try {
- // Select the specified folder and check that
- // contains a valid PKCS#15 FS
- mFileViewProvider.selectByPath(
- ByteArrayConverter.byteArrayToPathString(rawPath), false);
- return currentDirIsPkcs15FileStructure();
- } catch (Exception e) {
- return false;
- }
- }
-
- /**
- * Reads the content of EF(ODF).
- *
- * @return The content of EF(ODF) as a byte array. Must not be null.
- *
- * @throws IOException if a lower-level exception occurs.
- * @throws IOException if read operation returns null.
- */
- private byte[] readOdf() throws IOException {
- mFileViewProvider.selectByFID(FID_EF_ODF);
- byte[] odfContent = mFileViewProvider.readBinary(
- FileViewProvider.CURRENT_FILE, 0, 0);
-
- if (odfContent == null) {
- throw new IOException(
- "Error reading EF(ODF): returned null.");
- }
-
- return odfContent;
- }
-
- /**
- * Reads the content of EF(TokenInfo).
- *
- * @return The content of EF(TokenInfo) as a byte array. Must not be null.
- *
- * @throws IOException if a lower-level exception occurs.
- * @throws IOException if read operation returns null.
- */
- private byte[] readTokenInfo() throws IOException {
- mFileViewProvider.selectByFID(FID_EF_TOKEN_INFO);
- byte[] tokenInfoContent = mFileViewProvider.readBinary(
- FileViewProvider.CURRENT_FILE, 0, 0);
-
- if (tokenInfoContent == null) {
- throw new IOException(
- "Error reading EF(TokenInfo): returned null.");
- }
-
- return tokenInfoContent;
- }
-
- /**
- * Decides whether the specified byte array is a DER tag for a private key
- * object.
- *
- * @param tag The tag.
- *
- * @return true if the specified tag represents a private key object, false
- * otherwise.
- */
- private boolean isPrivateKeyTag(byte[] tag) {
- return Arrays.equals(tag, TLV_TAG_PRIVATE_KEY);
- }
-
- /**
- * Decides whether the specified byte array is a DER tag for a public key
- * object.
- *
- * @param tag The tag.
- *
- * @return true if the specified tag represents a public key object, false
- * otherwise.
- */
- private boolean isPublicKeyTag(byte[] tag) {
- return Arrays.equals(tag, TLV_TAG_PUBLIC_KEY)
- || Arrays.equals(tag, TLV_TAG_PUBLIC_KEY_TRUSTED);
- }
-
- /**
- * Decides whether the specified byte array is a DER tag for a certificate
- * object.
- *
- * @param tag The tag.
- *
- * @return true if the specified tag represents a certificate object, false
- * otherwise.
- */
- private boolean isCertificateTag(byte[] tag) {
- return Arrays.equals(tag, TLV_TAG_CERTIFICATE)
- || Arrays.equals(tag, TLV_TAG_CERTIFICATE_TRUSTED)
- || Arrays.equals(tag, TLV_TAG_CERTIFICATE_USEFUL);
- }
-
- /**
- * Decides whether the specified byte array is a DER tag for a data
- * object.
- *
- * @param tag The tag.
- *
- * @return true if the specified tag represents a data object, false
- * otherwise.
- */
- private boolean isDataObjectTag(byte[] tag) {
- return Arrays.equals(tag, TLV_TAG_DATA_OBJECT);
- }
-
- /**
- * Decides whether the specified byte array is a DER tag for an
- * authentication object.
- *
- * @param tag The tag.
- *
- * @return true if the specified tag represents an authentication object,
- * false otherwise.
- */
- private boolean isAuthenticationObjectTag(byte[] tag) {
- return Arrays.equals(tag, TLV_TAG_AUTHENTICATE_OBJECT);
- }
-}
diff --git a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/Provider.java b/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/Provider.java
deleted file mode 100644
index 53da9cf..0000000
--- a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/Provider.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2013 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi;
-
-import org.simalliance.openmobileapi.internal.ErrorStrings;
-
-/**
- * This Provider abstract class is the base class for all service layer classes.
- * Each service layer class provides a set of methods for a certain aspect (file
- * management, PIN authentication, PKCS#15 structure handling, ...) and acts as
- * a provider for service routines. All Provider classes need an opened channel
- * for the SE communication. Hence before a certain Provider class can be used
- * for SE operations the channel has to be consigned. For performing different
- * operations (PIN authentication, file operation, ...) the Provider classes can
- * be easily combined by using the same channel for different Provider classes
- * and calling alternately methods of these different providers. It has to be
- * considered that each provider class needs a counterpart on SE side (e.g. an
- * Applet with a standardised APDU interface as required by the Provider class).
- * The application using a Provider class for SE interactions is in charge of
- * assigning a channel to the Provider where the Provider's SE counterpart
- * Applet is already preselected.
- */
-public abstract class Provider {
-
- /**
- * Currently used channel, while creating the object.
- */
- private Channel mChannel;
-
- /**
- * Encapsulates the defined channel by a Provider object that can be used
- * for performing a service operations on it. This constructor has to be
- * called by derived Provider classes during the instantiation.
- *
- * @param channel The channel that shall be used by this Provider for
- * service operations.
- *
- * @throws IllegalStateException if the used channel is closed.
- */
- public Provider(Channel channel) throws IllegalStateException {
- if (channel == null) {
- throw new IllegalStateException(ErrorStrings.paramNull("channel"));
- }
-
- if (channel.isClosed()) {
- throw new IllegalStateException(ErrorStrings.CHANNEL_CLOSED);
- }
-
- mChannel = channel;
- }
-
- /**
- * Returns the channel that is used by this provider. This returned channel
- * can also be used by other providers.
- *
- * @return The channel instance that is used by this provider.
- */
- public Channel getChannel() {
- return mChannel;
- }
-}
diff --git a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/Reader.java b/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/Reader.java
deleted file mode 100644
index 4100956..0000000
--- a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/Reader.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (C) 2011, The Android Open Source Project
- *
- * 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.
- */
-/*
- * Contributed by: Giesecke & Devrient GmbH.
- */
-
-package org.simalliance.openmobileapi;
-
-import java.io.IOException;
-import org.simalliance.openmobileapi.service.ISmartcardServiceReader;
-import org.simalliance.openmobileapi.service.ISmartcardServiceSession;
-import org.simalliance.openmobileapi.service.SmartcardError;
-import android.os.RemoteException;
-
-/**
- * Instances of this class represent Secure Element Readers connected to this
- * device. These Readers can be physical devices or virtual devices. They can be
- * removable or not. They can contain Secure Element that can or cannot be
- * removed.
- *
- * @see <a href="http://simalliance.org">SIMalliance Open Mobile API v2.02</a>
- */
-public class Reader {
-
- private final String mName;
- private final SEService mService;
- private ISmartcardServiceReader mReader;
-
- private final Object mLock = new Object();
-
-
- Reader(SEService service, String name ) {
- mName = name;
- mService = service;
- mReader = null;
- }
-
- /**
- * Return the user-friendly name of this reader.
- * <ul>
- * <li>If this reader is a SIM reader, then its name must start with the "SIM" prefix.</li>
- * <li>If the reader is a SD or micro SD reader, then its name must start with the "SD" prefix</li>
- * <li>If the reader is a embedded SE reader, then its name must start with the "eSE" prefix</li>
- * <ul>
- *
- * @return name of this Reader
- */
- public String getName() {
- return mName;
- }
-
- /**
- * Connects to a secure element in this reader. <br>
- * This method prepares (initialises) the Secure Element for communication
- * before the Session object is returned (e.g. powers the Secure Element by
- * ICC ON if its not already on). There might be multiple sessions opened at
- * the same time on the same reader. The system ensures the interleaving of
- * APDUs between the respective sessions.
- *
- * @throws IOException if something went wrong with the communicating to the
- * Secure Element or the reader.
- * @return a Session object to be used to create Channels.
- */
- public Session openSession() throws IOException {
- if( mService == null || mService.isConnected() == false ){
- throw new IllegalStateException("service is not connected");
- }
- if( mReader == null ){
- try {
- mReader = mService.getReader(mName);
- } catch (Exception e) {
- throw new IOException("service reader cannot be accessed.");
- }
- }
- synchronized (mLock) {
- SmartcardError error = new SmartcardError();
- ISmartcardServiceSession session;
- try {
- session = mReader.openSession(error);
- } catch (RemoteException e) {
- throw new IOException( e.getMessage() );
- }
- SEService.checkForException(error);
- if( session == null ){
- throw new IOException( "service session is null." );
- }
- return new Session(mService, session, this);
- }
- }
-
- /**
- * Check if a Secure Element is present in this reader.
- *
- * @return <code>true</code> if the SE is present, <code>false</code> otherwise.
- */
- public boolean isSecureElementPresent() {
- if( mService == null || mService.isConnected() == false ){
- throw new IllegalStateException("service is not connected");
- }
- if( mReader == null ){
- try {
- mReader = mService.getReader(mName);
- } catch (Exception e) {
- throw new IllegalStateException("service reader cannot be accessed. " + e.getLocalizedMessage());
- }
- }
- SmartcardError error = new SmartcardError();
- boolean flag;
- try {
- flag = mReader.isSecureElementPresent(error);
- } catch (RemoteException e) {
- throw new IllegalStateException(e.getMessage());
- }
- SEService.checkForException(error);
- return flag;
- }
-
- /**
- * Return the Secure Element service this reader is bound to.
- *
- * @return the SEService object.
- */
- public SEService getSEService() {
- return mService;
- }
-
- /**
- * Close all the sessions opened on this reader. All the channels opened by
- * all these sessions will be closed.
- */
- public void closeSessions() {
- if( mService == null || mService.isConnected() == false ){
- throw new IllegalStateException("service is not connected");
- }
- if( mReader != null ) {
- synchronized (mLock) {
- SmartcardError error = new SmartcardError();
- try {
- mReader.closeSessions(error);
- } catch (RemoteException e) {
- throw new IllegalStateException(e.getMessage());
- }
- SEService.checkForException(error);
- }
- }
- }
- // ******************************************************************
- // package private methods
- // ******************************************************************
-}
diff --git a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/SEDiscovery.java b/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/SEDiscovery.java
deleted file mode 100644
index 7238039..0000000
--- a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/SEDiscovery.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright 2013 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi;
-
-import java.io.IOException;
-
-import org.simalliance.openmobileapi.internal.ErrorStrings;
-
-/**
- * Instances of this class must be created by the applications to start a
- * discovery process. When created, they are configured with an SEService and an
- * object that will perform the discovery algorithm.
- */
-public class SEDiscovery {
-
- /**
- * The SEService in which to perform the recognition algorithm.
- */
- private SEService mService;
-
- /**
- * The Secure Element recognizer.
- */
- private SERecognizer mRecognizer;
-
- /**
- * The list of available readers in the SEService.
- */
- private Reader[] mReaders;
-
- /**
- * A counter specifying the last reader returned.
- */
- private int mCounter;
-
- /**
- * Creates a discovery object that will perform a discovery algorithm
- * specified by the recognizer object, and will be applied to the given
- * SEService.
- *
- * @param service The SEService used to perform the discovery. Cannot be
- * null.
- * @param recognizer An SERecognizer instance, whose isMatching method of
- * the SERecognizer will be called. Cannot be null.
- *
- * @throws IllegalArgumentException If any of the parameters is null.
- */
- public SEDiscovery(SEService service, SERecognizer recognizer)
- throws IllegalArgumentException {
- if (service == null) {
- throw new IllegalArgumentException(
- ErrorStrings.paramNull("service"));
- }
- if (recognizer == null) {
- throw new IllegalArgumentException(
- ErrorStrings.paramNull("recognizer"));
- }
-
- mService = service;
- mRecognizer = recognizer;
- // Counter = -1 means that getFirstMatch has not been called yet.
- mCounter = -1;
- }
-
- /**
- * Returns the first Secure Element reader containing a Secure Element that
- * matches the search criterion.
- * <p>
- * Actually starts a full discovery process:
- * <p>
- * - Secure Element readers are enumerated
- * <p>
- * - For the first reader, if a Secure Element is present, open a session
- * <p>
- * - On this session, call the isMatching method of the SERecognizer object
- * given at construction time.
- * <p>
- * - The session is closed.
- * <p>
- * - If the isMatching method returns false, the process is continued with
- * the next reader.
- * <p>
- * - If the isMatching method returns true, the reader object is returned
- * <p>
- * The sessions used by the discovery process are closed to avoid the risk
- * of leaks: if they were opened and returned to the caller, there would be
- * a risk for the caller to forget to close them.
- * <p>
- * Calling getFirstMatch twice simply restarts the discovery process (e.g.
- * probably returns the same result, unless a Secure Element has been
- * removed).
- *
- * @return The first matching Secure Element reader, or null if there is
- * none.
- */
- public Reader getFirstMatch() {
- // List all available readers
- mReaders = mService.getReaders();
-
- if ((mReaders == null) || (mReaders.length < 1)) {
- // If there are no readers, return null
- // Set counter to -1 to indicate that no match has been found.
- mCounter = -1;
- return null;
- }
-
- // Start an iteration through all the readers (notice that iteration
- // starts from counter = 0).
- mCounter = 0;
- try {
- return getNextMatch();
- } catch (IllegalStateException e) {
- // This will never happen since mCounter = 0.
- return null;
- }
- }
-
- /**
- * Returns the next Secure Element reader containing a Secure Element that
- * matches the search criterion.
- * <p>
- * Actually continues the discovery process:
- * <p>
- * - For the next reader in the enumeration, if a Secure Element is present,
- * open a session
- * <p>
- * - On this session, call the isMatching method of the SERecognizer object
- * given at construction time.
- * <p>
- * - The session is closed.
- * <p>
- * - If the isMatching method returns false, the process is continued with
- * the next reader.
- * <p>
- * - If the isMatching method returns true, the reader object is returned
- *
- * @return The next matching Secure Element reader, or null if there is
- * none.
- *
- * @throws IllegalStateException if the getNextMatch() method is called without
- * calling getFirstMatch() before, since the creation of the
- * SEDiscovery object, or since the last call to getFirstMatch or
- * getNextMatch that returned null.
- */
- public Reader getNextMatch() throws IllegalStateException {
- if (mCounter == -1) {
- throw new IllegalStateException(
- "getFirstMatch needs to be called before getNextMatch()");
- }
-
- Reader nextReader;
- // Continue with the iteration started in getFirstMatch()
- for (; mCounter < mReaders.length; mCounter++) {
- // Set the next reader to be looked at.
- nextReader = mReaders[mCounter];
- if (nextReader.isSecureElementPresent()) {
- // If secure element is present, open session and check if
- // it matches
- try {
- Session session = nextReader.openSession();
- if (mRecognizer.isMatching(session)) {
- session.close();
- // Increase counter since when re-taking the iteration
- // next reader must be get (not current one)
- mCounter++;
- return nextReader;
- } else {
- session.close();
- }
- } catch (IOException e) {
- // If session could not be opened, assume it is not matching
- e.printStackTrace();
- } catch (IllegalArgumentException e) {
- // If session is null, assume it is not matching
- e.printStackTrace();
- }
- }
- }
-
- // Set counter to -1 to indicate that no match has been found.
- mCounter = -1;
- return null;
- }
-}
diff --git a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/SERecognizer.java b/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/SERecognizer.java
deleted file mode 100644
index 57ba585..0000000
--- a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/SERecognizer.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2013 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi;
-
-/**
- * Base class for recognizer classes. Extended by system-provided recognizers,
- * or by custom recognizers.
- */
-public abstract class SERecognizer {
-
- /**
- * This is a call-back method that will be called during the discovery
- * process, once per Secure Element inserted in a reader. Application
- * developers can use the given session object to perform any discovery
- * algorithm they think is appropriate. They can use the Transport API or
- * any other API, conforming to access control rules & policy, like for
- * regular application code (i.e. this is not privileged code).
- *
- * @param session A Session object that is used to perform the discovery.
- * Never null.
- *
- * @return A boolean indicating whether the Secure Element to which the
- * given session has been open is matching with the recognition
- * criterion implemented by this method.
- *
- * @throws IllegalArgumentException if the used session is null.
- */
- public abstract boolean isMatching(Session session)
- throws IllegalArgumentException;
-}
diff --git a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/SERecognizerByAID.java b/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/SERecognizerByAID.java
deleted file mode 100644
index 2c3dbdc..0000000
--- a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/SERecognizerByAID.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright 2013 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi;
-
-import org.simalliance.openmobileapi.internal.ErrorStrings;
-
-/**
- * Instances of this class can be used to find a Secure Element implementing a
- * specific Applet, identified by its AID. The presence of such an Applet is
- * verified by trying to open a channel to this Applet. The opened channel, if
- * any, is closed before the end of the isMatching method.
- */
-public class SERecognizerByAID extends SERecognizer {
-
- /**
- * The minimum length of an AID.
- */
- public static final int AID_MIN_LENGTH = 5;
-
- /**
- * The maximum length of an AID.
- */
- public static final int AID_MAX_LENGTH = 16;
-
- /**
- * The expected AID.
- */
- private byte[] mAID;
-
- /**
- * Initializes a new instance of the SERecognizerByAID class.
- *
- * @param aid The expected AID.
- *
- * @throws IllegalArgumentException if the length of AID is not between
- * AID_MIN_LENGTH and AID_MAX_LENGTH or if it's null.
- */
- public SERecognizerByAID(byte[] aid) throws IllegalArgumentException {
-
- if (aid == null) {
- throw new IllegalArgumentException(ErrorStrings.paramNull("aid"));
- }
- if ((aid.length < AID_MIN_LENGTH) || (aid.length > AID_MAX_LENGTH)) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidValue("aid"));
- }
-
- mAID = new byte[aid.length];
- System.arraycopy(aid, 0, mAID, 0, aid.length);
- }
-
- /**
- * Tries to open a channel with the specified AID.
- *
- * @param session The session in which to open the channel.
- *
- * @return true if the channel could be opened, false otherwise.
- *
- * @throws IllegalArgumentException if the used session is null.
- */
- public boolean isMatching(Session session) throws IllegalArgumentException {
- if (session == null) {
- throw new IllegalArgumentException(
- ErrorStrings.paramNull("session"));
- }
- try {
- Channel channel = session.openLogicalChannel(mAID);
- if (channel != null) {
- channel.close();
- return true;
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- return false;
- }
-}
diff --git a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/SERecognizerByATR.java b/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/SERecognizerByATR.java
deleted file mode 100644
index 9487978..0000000
--- a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/SERecognizerByATR.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright 2013 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi;
-
-
-import java.util.Arrays;
-
-import org.simalliance.openmobileapi.internal.ErrorStrings;
-
-/**
- * Instances of this class can be used to find a Secure Element with a specific
- * ATR (or ATR pattern).
- */
-public class SERecognizerByATR extends SERecognizer {
-
- /**
- * The minimum length of an ATR (At least TS and t0 shall be present.
- */
- public static final int ATR_MIN_LENGTH = 2;
-
- /**
- * The maximum length of an ATR.
- */
- public static final int ATR_MAX_LENGTH = 32;
-
- /**
- * The ATR to look for.
- */
- private byte[] mAtr;
-
- /**
- * The mask that will be applied to the SE ATR.
- */
- private byte[] mMask;
-
- /**
- * Initializes a new instance of the SERecognizerByATR class.
- *
- * @param atr A byte array containing the ATR bytes values that are searched
- * for.
- * @param mask A byte array containing an AND-mask to be applied to the
- * Secure Element ATR values before to be compared with the searched
- * value.
- *
- * @throws IllegalArgumentException when either the ATR or the Mask parameters
- * have an invalid length, or if they are null.
- */
- public SERecognizerByATR(byte[] atr, byte[] mask)
- throws IllegalArgumentException {
- if (atr == null) {
- throw new IllegalArgumentException(ErrorStrings.paramNull("atr"));
- }
- if (mask == null) {
- throw new IllegalArgumentException(ErrorStrings.paramNull("mask"));
- }
-
- if (atr.length < ATR_MIN_LENGTH || atr.length > ATR_MAX_LENGTH) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidArrayLength("atr"));
- }
-
- if (atr.length != mask.length) {
- throw new IllegalArgumentException(
- "atr length and mask length must be equal.");
- }
-
- mAtr = new byte[atr.length];
- System.arraycopy(atr, 0, mAtr, 0, atr.length);
- mMask = new byte[mask.length];
- System.arraycopy(mask, 0, mMask, 0, mask.length);
- }
-
- /**
- * If the ATR length is correct, masks it and compares it with the expected
- * one.
- *
- * @param session The session from which the ATR will be get.
- *
- * @return true if the masked ATRs match, or false if either ATRs don't
- * match or session ATR has an invalid length.
- *
- * @throws IllegalArgumentException if session is null.
- */
- public boolean isMatching(Session session) throws IllegalArgumentException {
- if (session == null) {
- throw new IllegalArgumentException(
- ErrorStrings.paramNull("session"));
- }
- byte[] sessionAtr = session.getATR();
-
- if (sessionAtr.length != mAtr.length) {
- return false;
- }
-
- return Arrays.equals(maskAtr(mAtr, mMask), maskAtr(sessionAtr, mMask));
- }
-
- /**
- * Masks the specified ATR with the specified mask.
- *
- * @param atr The ATR to be masked.
- * @param mask The mask to be applied to the ATR.
- *
- * @return The masked ATR.
- */
- private byte[] maskAtr(byte[] atr, byte[] mask) {
- byte[] maskedAtr = new byte[atr.length];
-
- for (int i = 0; i < atr.length; i++) {
- maskedAtr[i] = (byte) (atr[i] & mask[i]);
- }
-
- return maskedAtr;
- }
-}
diff --git a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/SERecognizerByHistoricalBytes.java b/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/SERecognizerByHistoricalBytes.java
deleted file mode 100644
index 86d95c3..0000000
--- a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/SERecognizerByHistoricalBytes.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright 2013 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi;
-
-import java.util.Arrays;
-
-import org.simalliance.openmobileapi.internal.ErrorStrings;
-import org.simalliance.openmobileapi.internal.HistoricalBytesUtilities;
-
-/**
- * Instances of this class can be used to find a Secure Element with a specific
- * value in their historical bytes.
- */
-public class SERecognizerByHistoricalBytes extends SERecognizer {
-
- /**
- * The minimum length of the historical bytes.
- */
- public static final int HISTORICAL_BYTES_MIN_LENGTH = 0;
-
- /**
- * The maximum length of the historical bytes.
- */
- public static final int HISTORICAL_BYTES_MAX_LENGTH = 15;
-
- /**
- * The expected historical bytes.
- */
- private byte[] mHistBytes;
-
- /**
- * Initializes a new instance of the SERecognizerByHistoricalBytes class.
- *
- * @param values Byte array, to be checked for presence in the historical
- * bytes.
- *
- * @throws IllegalArgumentException if values has a wrong length or it's null.
- */
- public SERecognizerByHistoricalBytes(byte[] values)
- throws IllegalArgumentException {
- if (values == null) {
- throw new IllegalArgumentException(
- ErrorStrings.paramNull("values"));
- }
- if (values.length < HISTORICAL_BYTES_MIN_LENGTH
- || values.length > HISTORICAL_BYTES_MAX_LENGTH) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidArrayLength("values"));
- }
-
- mHistBytes = new byte[values.length];
- System.arraycopy(values, 0, mHistBytes, 0, values.length);
- }
-
- /**
- * Gets the historical bytes and compares them with the expected ones.
- *
- * @param session The session from which the historical bytes will be get.
- *
- * @return true if the historical bytes match, or false if either historical
- * bytes don't match or session ATR has an invalid length.
- *
- * @throws IllegalArgumentException if the used session is null.
- */
- public boolean isMatching(Session session) throws IllegalArgumentException {
- if (session == null) {
- throw new IllegalArgumentException(
- ErrorStrings.paramNull("session"));
- }
- byte[] sessionHistBytes = HistoricalBytesUtilities.getHistBytes(session
- .getATR());
- return Arrays.equals(mHistBytes, sessionHistBytes);
- }
-}
diff --git a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/SEService.java b/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/SEService.java
deleted file mode 100644
index d000606..0000000
--- a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/SEService.java
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * Copyright (C) 2011, The Android Open Source Project
- *
- * 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.
- */
-/*
- * Contributed by: Giesecke & Devrient GmbH.
- */
-
-package org.simalliance.openmobileapi;
-
-import java.security.AccessControlException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-
-import org.simalliance.openmobileapi.service.CardException;
-import org.simalliance.openmobileapi.service.ISmartcardService;
-import org.simalliance.openmobileapi.service.ISmartcardServiceCallback;
-import org.simalliance.openmobileapi.service.ISmartcardServiceReader;
-import org.simalliance.openmobileapi.service.SmartcardError;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-/**
- * The SEService realises the communication to available Secure Elements on the
- * device. This is the entry point of this API. It is used to connect to the
- * infrastructure and get access to a list of Secure Element Readers.
- *
- * @see <a href="http://simalliance.org">SIMalliance Open Mobile API v2.02</a>
- */
-public class SEService {
-
- private static final String SERVICE_TAG = "SEService";
-
- private final Object mLock = new Object();
-
- /** The client context (e.g. activity). */
- private final Context mContext;
-
- /** The backend system. */
- private volatile ISmartcardService mSmartcardService;
-
- /**
- * Class for interacting with the main interface of the backend.
- */
- private ServiceConnection mConnection;
-
- /**
- * Collection of available readers.
- */
- final private HashMap<String, Reader> mReaders
- = new HashMap<String, Reader>();
-
- /**
- * This implementation is used to receive callbacks from backend.
- */
- private final ISmartcardServiceCallback mCallback
- = new ISmartcardServiceCallback.Stub() {
- };
-
- /**
- * Callback object that allows the notification of the caller if this
- * SEService could be bound to the backend.
- */
- private CallBack mCallerCallback;
-
- /**
- * Interface to receive call-backs when the service is connected. If the
- * target language and environment allows it, then this shall be an inner
- * interface of the SEService class.
- */
- public interface CallBack {
-
- /**
- * Called by the framework when the service is connected.
- *
- * @param service
- * the connected service.
- */
- void serviceConnected(SEService service);
- }
-
- /**
- * Establishes a new connection that can be used to connect to all the
- * Secure Elements available in the system. The connection process can be
- * quite long, so it happens in an asynchronous way. It is usable only if
- * the specified listener is called or if isConnected() returns
- * <code>true</code>. <br>
- * The call-back object passed as a parameter will have its
- * serviceConnected() method called when the connection actually happen.
- *
- * @param context
- * the context of the calling application. Cannot be
- * <code>null</code>.
- * @param listener
- * a SEService.CallBack object. Can be <code>null</code>.
- */
- public SEService(Context context, SEService.CallBack listener) {
-
- if (context == null) {
- throw new NullPointerException("context must not be null");
- }
-
- mContext = context;
- mCallerCallback = listener;
-
- mConnection = new ServiceConnection() {
-
- public synchronized void onServiceConnected(
- ComponentName className, IBinder service) {
-
- mSmartcardService = ISmartcardService.Stub.asInterface(service);
- if (mCallerCallback != null) {
- mCallerCallback.serviceConnected(SEService.this);
- }
- Log.v(SERVICE_TAG, "Service onServiceConnected");
- }
-
- public void onServiceDisconnected(ComponentName className) {
- mSmartcardService = null;
- Log.v(SERVICE_TAG, "Service onServiceDisconnected");
- }
- };
-
- Intent intent = new Intent(ISmartcardService.class.getName());
- boolean bindingSuccessful = mContext.bindService(intent, mConnection,
- Context.BIND_AUTO_CREATE);
- if (bindingSuccessful) {
- Log.v(SERVICE_TAG, "bindService successful");
- }
- }
-
- /**
- * Tells whether or not the service is connected.
- *
- * @return <code>true</code> if the service is connected.
- */
- public boolean isConnected() {
- if (mSmartcardService == null) {
- return false;
- }
- return true;
- }
-
- /**
- * Returns the list of available Secure Element readers. More precisely it
- * returns the list of readers that the calling application has the
- * permission to connect to.
- *
- * @return The readers list, as an array of Readers. If there are no readers
- * the returned array is of length 0.
- */
- public Reader[] getReaders() {
- if (mSmartcardService == null) {
- throw new IllegalStateException("service not connected to system");
- }
-
- SmartcardError error = new SmartcardError();
- String[] readerNames;
- try {
- readerNames = mSmartcardService.getReaders(error);
- } catch (RemoteException e) {
- throw new IllegalStateException(e);
- }
-
- mReaders.clear();
- for (String readerName : readerNames) {
- mReaders.put(readerName, new Reader(this, readerName));
- }
-
- return sortReaders();
- }
-
- /**
- * Releases all Secure Elements resources allocated by this SEService. It is
- * recommended to call this method in the termination method of the calling
- * application (or part of this application) which is bound to this
- * SEService. The SEService becomes invalid after calling shutdown().
- */
- public void shutdown() {
- synchronized (mLock) {
- if (mSmartcardService != null) {
- Collection<Reader> col = mReaders.values();
- Iterator<Reader> iter = col.iterator();
- while (iter.hasNext()) {
- try {
- Reader reader = iter.next();
- reader.closeSessions();
- } catch (Exception ignore) {
- }
- }
- }
- try {
- mContext.unbindService(mConnection);
- } catch (IllegalArgumentException e) {
- // Do nothing and fail silently since an error here indicates
- // that binding never succeeded in the first place.
- }
- mSmartcardService = null;
- }
- }
-
- /**
- * Returns the version of the OpenMobile API specification this
- * implementation is based on.
- *
- * @return Version String.
- */
- public String getVersion() {
- return "2.05";
- }
-
- // ******************************************************************
- // package private methods
- // ******************************************************************
-
- ISmartcardServiceReader getReader(String name) {
-
- SmartcardError error = new SmartcardError();
- ISmartcardServiceReader reader = null;
- try {
- reader = mSmartcardService.getReader(name, error);
- } catch (RemoteException e) {
- throw new IllegalStateException(e.getMessage());
- }
- checkForException(error);
- return reader;
- }
-
- static void checkForException(SmartcardError error) {
- try {
- error.throwException();
- } catch (CardException exp) {
- throw new IllegalStateException(exp.getMessage());
- } catch (AccessControlException exp) {
- throw new SecurityException(exp.getMessage());
- }
- }
-
- ISmartcardServiceCallback getCallback() {
- return mCallback;
- }
-
- /**
- * Creates an array of sorted readers.
- *
- * @return An array of readers sorted according to its name.
- */
- private Reader[] sortReaders() {
- ArrayList<Reader> readersList = new ArrayList<Reader>();
- Reader reader;
-
- // Set SIMs at the top of the list
- for (int i = 1; (reader = mReaders.get("SIM" + i)) != null; i++) {
- readersList.add(reader);
- }
-
- // Then set eSE's
- for (int i = 1; (reader = mReaders.get("eSE" + i)) != null; i++) {
- readersList.add(reader);
- }
-
- // Then set SD cards
- for (int i = 1; (reader = mReaders.get("SD" + i)) != null; i++) {
- readersList.add(reader);
- }
-
- // Add other terminals at the end
- for (Reader r : mReaders.values()) {
- if (!readersList.contains(r)) {
- readersList.add(r);
- }
- }
-
- return readersList.toArray(new Reader[readersList.size()]);
- }
-}
diff --git a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/SecureStorageProvider.java b/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/SecureStorageProvider.java
deleted file mode 100644
index 41edb95..0000000
--- a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/SecureStorageProvider.java
+++ /dev/null
@@ -1,1085 +0,0 @@
-/*
- * Copyright 2013 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi;
-
-import java.io.IOException;
-import java.util.ArrayList;
-
-import org.simalliance.openmobileapi.internal.ByteArrayConverter;
-import org.simalliance.openmobileapi.internal.ErrorStrings;
-import org.simalliance.openmobileapi.util.CommandApdu;
-import org.simalliance.openmobileapi.util.ResponseApdu;
-
-/**
- * This class provides an API to store and retrieve data on the SE which is
- * protected in a secure environment. A default set of functionality that is
- * always provided on every platform enable application developers to rely on
- * this interface for secure data storage (e.g. credit cards numbers, private
- * phone numbers, passwords, ...). The interface should encapsulate any SE
- * specifics as it is intended for device application developers who might not
- * be familiar with SE or APDU internals.
- *
- * @author G&D Barcelona, 2013
- * @version 1.0
- */
-public class SecureStorageProvider extends Provider {
-
- // TODO check value of SES_SW_SECURITY_STATUS_NOT_SATISFIED (not ISO compliant).
-
- /**
- * Maximum length for a SS title.
- */
- public static final int MAX_TITLE_LENGTH = 60;
-
- /**
- * Creates a SecureStorageProvider instance which will be connected to the
- * preselected SE Secure Storage Applet on defined channel.
- *
- * @param channel the channel that shall be used by this Provider for
- * operations on the Secure Storage.
- *
- * @throws IllegalStateException if the defined channel is closed.
- * @throws IllegalStateException if the defined channel is not connected to
- * a Secure Storage applet.
- */
- public SecureStorageProvider(Channel channel) throws IllegalStateException {
- super(channel);
- if (!sendPingCommand()) {
- throw new IllegalStateException(ErrorStrings.SES_APP_NOT_PRESENT);
- }
- }
-
- /**
- * This command creates a Secure Storage entry with the defined title and
- * data. The data can contain an uninterpreted byte stream of an undefined
- * max length (e.g. names,numbers,image,media data,...).
- *
- * @param title The title of the entry that shall be written. The max. title
- * length is 60. All characters must be supported by UTF-8.
- * @param data The data of the entry that shall be written. If data is empty
- * or null then only the defined title will be assigned to the new
- * entry.
- *
- * @throws SecurityException if old PIN to access the Secure Storage Applet
- * was not verified.
- * @throws IllegalStateException if the used channel is closed.
- * @throws IllegalArgumentException if the title already exists, if the data
- * chain is too long or if the title has bad encoding or wrong
- * length (empty or too long).
- * @throws IOException if the entry couldn't be created because of an
- * incomplete write procedure.
- */
- public void create(String title, byte[] data) throws IllegalStateException,
- IllegalArgumentException, SecurityException, IOException {
-
- int id = 0;
-
- if (title == null) {
- throw new IllegalArgumentException(ErrorStrings.paramNull("title"));
- }
- if (title.length() == 0) {
- throw new IllegalArgumentException(ErrorStrings.SES_EMPTY_TITLE);
- }
- if (title.length() > MAX_TITLE_LENGTH) {
- throw new IllegalArgumentException(ErrorStrings.SES_LONG_TITLE);
- }
-
- // Try creating the entry
- try {
- id = sendCreateEntryCommand(title);
- } catch (ProcessingException e) {
- switch (e.getSwValue()) {
- case ResponseApdu.SES_SW_MEMORY_FAILURE:
- throw new IOException(ErrorStrings.SES_CREATE_FAILED_MEMORY);
- case ResponseApdu.SES_SW_INCORRECT_COMMAND_DATA:
- throw new IllegalArgumentException(
- ErrorStrings.SES_TITLE_EXISTS);
- case ResponseApdu.SES_SW_SECURITY_STATUS_NOT_SATISFIED:
- throw new SecurityException(
- ErrorStrings.SECURITY_STATUS_NOT_SATISFIED);
- case ResponseApdu.SES_SW_NOT_ENOUGH_MEMORY:
- throw new IOException(ErrorStrings.SES_NOT_ENOUGH_MEMORY);
- default:
- throw new IOException(ErrorStrings.unexpectedStatusWord(e
- .getSwValue()));
- }
- }
-
- // When entry is created, if there is data, start putting it.
- if (data != null && data.length != 0) {
- // Try selecting the entry
- try {
- sendSelectCommand(id);
- } catch (ProcessingException e) {
- // If an exception occurs during the select process,
- // then the create file action has to be undone.
- try {
- sendDeleteEntryCommand(id);
- } catch (ProcessingException t) {
- }
-
- throw new IOException(
- "Create process failed. Select operation failed: "
- + ErrorStrings.unexpectedStatusWord(e
- .getSwValue()));
- } catch (IOException e) {
- try {
- sendDeleteEntryCommand(id);
- } catch (ProcessingException t) {
- }
-
- throw e;
- }
-
- // Send the size of the data that will be sent
- try {
- sendPutDataCommand(data.length);
- } catch (ProcessingException e) {
- try {
- sendDeleteEntryCommand(id);
- } catch (ProcessingException t) {
- }
- if (e.getSwValue() == ResponseApdu.
- SES_SW_MEMORY_FAILURE) {
- throw new IllegalArgumentException(
- ErrorStrings.SES_CREATE_FAILED_MEMORY);
- }
- if (e.getSwValue() == ResponseApdu.
- SES_SW_MEMORY_FAILURE) {
- throw new IllegalArgumentException(
- ErrorStrings.SES_CREATE_FAILED_MEMORY);
- } else {
- throw new IOException(
- "Create process failed. Put data operation failed: "
- + ErrorStrings.unexpectedStatusWord(e
- .getSwValue()));
- }
- } catch (IOException e) {
- try {
- sendDeleteEntryCommand(id);
- } catch (ProcessingException t) {
- }
-
- throw e;
- }
-
- // Start sending effective data
- for (int position = 0; position < data.length;) {
- int remainingBytes = data.length - position;
- // Decide how many bytes will be sent in the next
- // iteration
- int currentBufferSize;
- if (remainingBytes < CommandApdu.MAX_DATA_LENGTH) {
- currentBufferSize = remainingBytes;
- } else {
- currentBufferSize = CommandApdu.MAX_DATA_LENGTH;
- }
-
- // Initialize and fill the buffer.
- byte[] buffer = new byte[currentBufferSize];
- System.arraycopy(data, position, buffer, 0, currentBufferSize);
-
- // Decide P1
- PutDataP1 p1;
- if (position == 0) {
- p1 = PutDataP1.First;
- } else {
- p1 = PutDataP1.Next;
- }
-
- // Put data
- try {
- sendPutDataCommand(p1, buffer);
- } catch (ProcessingException e) {
- try {
- sendDeleteEntryCommand(id);
- } catch (ProcessingException t) {
- }
- if (e.getSwValue() == ResponseApdu.
- SES_SW_MEMORY_FAILURE) {
- throw new IllegalArgumentException(
- ErrorStrings.SES_CREATE_FAILED_MEMORY);
- }
- if (e.getSwValue() == ResponseApdu.
- SES_SW_NOT_ENOUGH_MEMORY) {
- throw new IllegalArgumentException(
- ErrorStrings.SES_NOT_ENOUGH_MEMORY);
- } else {
- throw new IOException(
- "Create process failed. Put data operation "
- + "failed: "
- + ErrorStrings.unexpectedStatusWord(e
- .getSwValue()));
- }
- } catch (IOException e) {
- try {
- sendDeleteEntryCommand(id);
- } catch (ProcessingException t) {
- }
-
- throw e;
- }
-
- // If everything worked, update the position
- position += currentBufferSize;
- }
- }
- }
-
- /**
- * This command updates the data of the Secure Storage entry referenced by
- * the defined title. The data can contain an uninterpreted byte stream
- * of an undefined max length (e.g. names, numbers, image,
- * media data, ...).
- *
- * @param title the title of the entry that must already exist. The max.
- * title length is 60. All characters must be supported by UTF-8.
- * @param data the data of the entry that shall be written. If data is
- * empty or null then the data of the existing entry (referenced by the
- * title) will be deleted.
-
- *
- * @throws IllegalStateException if the used channel is closed.
- * @throws IllegalArgumentException if the title does not already exists.
- * @throws IllegalArgumentException if the title is incorrect: bad encoding
- * or wrong length (empty or too long).
- * @throws IllegalArgumentException if the data chain is too long.
-
- * @throws IOException if the entry couldn’t be updated because of an
- * incomplete write procedure.
- * @throws SecurityException if the PIN to access the Secure Storage Applet
- * was not verified.
- */
- public void update(String title, byte[] data) throws IllegalStateException,
- IllegalArgumentException, SecurityException, IOException {
-
- int id;
- if (title == null) {
- throw new IllegalArgumentException(ErrorStrings.paramNull("title"));
- }
- if (title.length() == 0) {
- throw new IllegalArgumentException(ErrorStrings.SES_EMPTY_TITLE);
- }
- if (title.length() > MAX_TITLE_LENGTH) {
- throw new IllegalArgumentException(ErrorStrings.SES_LONG_TITLE);
- }
-
- if (data == null) {
- data = new byte[0];
- }
-
- try {
- id = sendGetIdCommand(title);
- } catch (ProcessingException e) {
- switch (e.getSwValue()) {
- case ResponseApdu.SES_SW_SECURITY_STATUS_NOT_SATISFIED:
- throw new SecurityException(
- ErrorStrings.SECURITY_STATUS_NOT_SATISFIED);
- case ResponseApdu.SES_SW_REF_NOT_FOUND:
- throw new IllegalArgumentException(ErrorStrings.
- SES_NO_ENTRY_SELECTED);
- default:
- throw new IOException(ErrorStrings.unexpectedStatusWord(e
- .getSwValue()));
- }
- }
-
- try {
- sendSelectCommand(id);
- } catch (ProcessingException e) {
- switch (e.getSwValue()) {
- case ResponseApdu.SES_SW_SECURITY_STATUS_NOT_SATISFIED:
- throw new SecurityException(
- ErrorStrings.SECURITY_STATUS_NOT_SATISFIED);
- default:
- throw new IOException(ErrorStrings.unexpectedStatusWord(e
- .getSwValue()));
- }
- }
-
- // previous data has to be caught to undo changes if some action is
- // wrong done.
- byte[] previousData = read(title);
- // nothing to be done if an error occurs. Nothing was done before.
- try {
- sendPutDataCommand(data.length);
- } catch (ProcessingException e) {
- switch (e.getSwValue()) {
- case ResponseApdu.SES_SW_MEMORY_FAILURE:
- throw new IllegalArgumentException(
- ErrorStrings.SES_CREATE_FAILED_MEMORY);
- case ResponseApdu.SES_SW_NOT_ENOUGH_MEMORY:
- throw new IllegalArgumentException(
- ErrorStrings.SES_NOT_ENOUGH_MEMORY);
- default:
- throw new IOException(ErrorStrings.unexpectedStatusWord(e
- .getSwValue()));
- }
- }
-
- // Start sending effective data
- for (int position = 0; position < data.length;) {
- int remainingBytes = data.length - position;
- // Decide how many bytes will be sent in the next
- // iteration
- byte[] buffer;
- if (remainingBytes < CommandApdu.MAX_DATA_LENGTH) {
- buffer = new byte[remainingBytes];
- } else {
- buffer = new byte[remainingBytes];
- }
- // Initialize and fill the buffer.
- System.arraycopy(data, position, buffer, 0, buffer.length);
-
- // Decide P1
- PutDataP1 p1;
- if (position == 0) {
- p1 = PutDataP1.First;
- } else {
- p1 = PutDataP1.Next;
- }
-
- // Put data
- try {
- sendPutDataCommand(p1, buffer);
- } catch (ProcessingException e) {
- try {
- sendDeleteEntryCommand(id);
- create(title, previousData);
- } catch (ProcessingException t) {
- }
- if (e.getSwValue() == ResponseApdu.
- SES_SW_MEMORY_FAILURE) {
- throw new IllegalArgumentException(
- ErrorStrings.SES_CREATE_FAILED_MEMORY);
- }
- if (e.getSwValue() == ResponseApdu.
- SES_SW_NOT_ENOUGH_MEMORY) {
- throw new IllegalArgumentException(
- ErrorStrings.SES_NOT_ENOUGH_MEMORY);
- } else {
- throw new IOException(
- "Update process failed. Put data operation "
- + "failed: "
- + ErrorStrings.unexpectedStatusWord(e
- .getSwValue()));
- }
- } catch (IOException e) {
- try {
- sendDeleteEntryCommand(id);
- create(title, previousData);
- } catch (ProcessingException t) {
- }
-
- throw e;
- }
-
- // If everything worked, update the position
- position += buffer.length;
- }
- }
-
- /**
- * This command reads and returns the byte stream of a data entry stored in
- * the Secure Element referenced by the title.
- *
- * @param title the title of the entry that must already exist. The max.
- * title length is 60. All characters must be supported by UTF-8.
- *
- * @return the data contained in the file.
- *
- * @throws SecurityException if the PIN to access the Secure Storage Applet
- * was not verified.
- * @throws IllegalStateException if the used channel is closed.
- * @throws IllegalArgumentException if the title has bad encoding or wrong
- * length (empty or too long).
- * @throws IOException if the entry couldn't be read because of an
- * incomplete read procedure.
- * @throws IllegalArgumentException when there are incorrect P1 or P2.
- * TODO: should be an IllegalReferenceError
- */
- public byte[] read(String title) throws IllegalStateException, IOException,
- IllegalArgumentException, SecurityException {
-
- if (title == null) {
- throw new IllegalArgumentException(ErrorStrings.paramNull("title"));
- }
- if (title.length() == 0 || title.length() > MAX_TITLE_LENGTH) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidArrayLength("title"));
- }
-
- int id;
-
- try {
- id = sendGetIdCommand(title);
- } catch (ProcessingException e) {
- switch (e.getSwValue()) {
- case ResponseApdu.SES_SW_SECURITY_STATUS_NOT_SATISFIED:
- throw new SecurityException(
- ErrorStrings.SECURITY_STATUS_NOT_SATISFIED);
- case ResponseApdu.SES_SW_REF_NOT_FOUND:
- return new byte[0];
- default:
- throw new IOException(ErrorStrings.unexpectedStatusWord(
- e.getSwValue()));
- }
- }
-
- try {
- sendSelectCommand(id);
- } catch (ProcessingException e) {
- switch (e.getSwValue()) {
- case ResponseApdu.SES_SW_SECURITY_STATUS_NOT_SATISFIED:
- throw new SecurityException(
- ErrorStrings.SECURITY_STATUS_NOT_SATISFIED);
- default:
- throw new IOException(ErrorStrings.unexpectedStatusWord(
- e.getSwValue()));
- }
- }
-
- byte[] data;
- int dataSize;
- int bytesRecieved = 0;
-
- // Get the size of the entry
- try {
- dataSize = ByteArrayConverter.byteArrayToInt(sendGetDataCommand(GetDataP1.Size));
- data = new byte[dataSize];
- } catch (ProcessingException e) {
- switch (e.getSwValue()) {
- case ResponseApdu.SES_SW_SECURITY_STATUS_NOT_SATISFIED:
- throw new SecurityException(
- ErrorStrings.SECURITY_STATUS_NOT_SATISFIED);
- default:
- throw new IOException(ErrorStrings.unexpectedStatusWord(e
- .getSwValue()));
- }
- }
-
- while (bytesRecieved < dataSize) {
- GetDataP1 p1;
-
- // Decide P1
- if (bytesRecieved == 0) {
- p1 = GetDataP1.First;
- } else {
- p1 = GetDataP1.Next;
- }
-
- // Get data and save it to byte array
- try {
- byte[] buffer = sendGetDataCommand(p1);
- System.arraycopy(buffer, 0, data, bytesRecieved, buffer.length);
- bytesRecieved += buffer.length;
- } catch (ProcessingException e) {
- switch (e.getSwValue()) {
- case ResponseApdu.SES_SW_SECURITY_STATUS_NOT_SATISFIED:
- throw new SecurityException(
- ErrorStrings.SECURITY_STATUS_NOT_SATISFIED);
- default:
- throw new IOException(ErrorStrings.unexpectedStatusWord(e
- .getSwValue()));
- }
- }
- }
-
- return data;
- }
-
- /**
- * This command checks if the Secure Storage entry with the defined title
- * exists.
- *
- * @param title the title of the entry that shall be checked. The max. title
- * length is 60. All characters must be supported by UTF-8.
- *
- * @return True if the entry with the defined title exists. False if the
- * entry does not exist.
- *
- * @throws IllegalStateException if the used channel is closed.
- * @throws IllegalArgumentException if the title is incorrect: bad encoding
- * or wrong length (empty or too long).
- * @throws SecurityException if the PIN to access the Secure Storage Applet
- * was not verified.
- * @throws IOException lower-level API exception.
- */
- public boolean exist(String title) throws IllegalStateException,
- IllegalArgumentException, SecurityException, IOException {
-
- if (title == null) {
- throw new IllegalArgumentException(ErrorStrings.paramNull("title"));
- }
- if (title.length() == 0) {
- throw new IllegalArgumentException(ErrorStrings.SES_EMPTY_TITLE);
- }
- if (title.length() > MAX_TITLE_LENGTH) {
- throw new IllegalArgumentException(ErrorStrings.SES_LONG_TITLE);
- }
-
- try {
- sendGetIdCommand(title);
- return true;
- } catch (ProcessingException e) {
- switch (e.getSwValue()) {
- case ResponseApdu.SES_SW_REF_NOT_FOUND:
- return false;
- case ResponseApdu.SES_SW_SECURITY_STATUS_NOT_SATISFIED:
- throw new SecurityException(
- ErrorStrings.SECURITY_STATUS_NOT_SATISFIED);
- default:
- throw new IOException(ErrorStrings.unexpectedStatusWord(e
- .getSwValue()));
- }
- }
- }
-
- /**
- * This command deletes the Secure Storage entry referenced by the title. If
- * the entry does not exist nothing will be done.
- *
- * @param title The title of the entry that must already exist. The max.
- * title length is 60. All characters must be supported by UTF-8.
- *
- * @return True if the entry with the defined title is deleted. False if the
- * entry does not exist.
- *
- * @throws IllegalStateException if the used channel is closed.
- * @throws IllegalArgumentException if the title is incorrect: bad encoding
- * or wrong length (empty or too long).
- * @throws IOException if there is an error in the transport layer.
- * @throws SecurityException if old PIN to access the Secure Storage Applet
- * was not verified.
- */
- public boolean delete(String title) throws IllegalStateException,
- IllegalArgumentException, IOException, SecurityException {
-
- if (title == null) {
- throw new IllegalArgumentException(ErrorStrings.paramNull("title"));
- }
- if (title.length() == 0) {
- throw new IllegalArgumentException(ErrorStrings.SES_EMPTY_TITLE);
- }
- if (title.length() > MAX_TITLE_LENGTH) {
- throw new IllegalArgumentException(ErrorStrings.SES_LONG_TITLE);
- }
-
- int id;
- try {
- id = sendGetIdCommand(title);
- } catch (ProcessingException e) {
- switch (e.getSwValue()) {
- case ResponseApdu.SES_SW_SECURITY_STATUS_NOT_SATISFIED:
- throw new SecurityException(
- ErrorStrings.SECURITY_STATUS_NOT_SATISFIED);
- case ResponseApdu.SES_SW_REF_NOT_FOUND:
- return false;
- default:
- throw new IOException(ErrorStrings.unexpectedStatusWord(e
- .getSwValue()));
- }
- }
-
- try {
- return sendDeleteEntryCommand(id);
- } catch (ProcessingException e) {
- switch (e.getSwValue()) {
- case ResponseApdu.SES_SW_MEMORY_FAILURE:
- throw new IOException(ErrorStrings.MEMORY_FAILURE);
- case ResponseApdu.SES_SW_SECURITY_STATUS_NOT_SATISFIED:
- throw new SecurityException(
- ErrorStrings.SECURITY_STATUS_NOT_SATISFIED);
- default:
- throw new IOException(
- ErrorStrings.unexpectedStatusWord(e.getSwValue()));
- }
- }
- }
-
- /**
- * This command deletes all Secure Storage entry referenced. If no entries
- * exist, nothing will be done
- *
- * @throws SecurityException if the PIN to access the Secure Storage Applet
- * was not verified.
- * @throws IllegalStateException if the used channel is closed.
- * @throws IOException if there is an error in the transport layer.
- */
- public void deleteAll() throws IllegalStateException, SecurityException,
- IOException {
-
- CommandApdu apdu = new CommandApdu(getChannel());
- apdu.setCla(CommandApdu.CLA_PROPRIETARY);
- apdu.setIns(CommandApdu.INS_DELETE_ALL_SS_ENTRIES);
- apdu.setP1((byte) 0x00);
- apdu.setP2((byte) 0x00);
- byte[] apduResponse = apdu.sendApdu();
-
- int swValue = ResponseApdu.getResponseStatusWordValue(apduResponse);
- switch (swValue) {
- case ResponseApdu.SW_NO_FURTHER_QUALIFICATION:
- return;
- case ResponseApdu.SES_SW_MEMORY_FAILURE:
- throw new IOException(ErrorStrings.MEMORY_FAILURE);
- case ResponseApdu.SES_SW_SECURITY_STATUS_NOT_SATISFIED:
- throw new SecurityException(
- ErrorStrings.SECURITY_STATUS_NOT_SATISFIED);
- default:
- throw new IOException(ErrorStrings.unexpectedStatusWord(swValue));
- }
- }
-
- /**
- * This command returns an entry list with all title-identifier. The title
- * is intended for the users to identify and to reference the Secure Storage
- * entries.
- *
- * @return a list of all entries located in Secure Storage. An empty list
- * will be returned if no entries exist in the Secure Storage
- *
- * @throws SecurityException if the PIN to access the Secure Storage Applet
- * was not verified.
- * @throws IllegalStateException if the used channel is closed.
- * @throws IOException if there is an error in the transport layer.
- */
- public String[] list() throws IllegalStateException, SecurityException,
- IOException {
-
- // The list that will store the titles
- ArrayList<String> titles = new ArrayList<String>();
-
- boolean allEntriesHasBeenRead = false;
-
- // Read the first entry
- try {
- titles.add(sendSelectCommand(SelectP1.First));
- } catch (ProcessingException e) {
- switch (e.getSwValue()) {
- case ResponseApdu.SES_SW_REF_NOT_FOUND:
- // There are no more entries.
- allEntriesHasBeenRead = true;
- case ResponseApdu.SES_SW_SECURITY_STATUS_NOT_SATISFIED:
- throw new SecurityException(
- ErrorStrings.SECURITY_STATUS_NOT_SATISFIED);
- default:
- throw new IOException(ErrorStrings.unexpectedStatusWord(e
- .getSwValue()));
- }
- }
-
- // Read the next entries
- while (!allEntriesHasBeenRead) {
- try {
- titles.add(sendSelectCommand(SelectP1.Next));
- } catch (ProcessingException e) {
- switch (e.getSwValue()) {
- case ResponseApdu.SES_SW_REF_NOT_FOUND:
- // There are no more entries.
- allEntriesHasBeenRead = true;
- break;
- case ResponseApdu.SES_SW_SECURITY_STATUS_NOT_SATISFIED:
- throw new SecurityException(
- ErrorStrings.SECURITY_STATUS_NOT_SATISFIED);
- default:
- throw new IOException(ErrorStrings.unexpectedStatusWord(e
- .getSwValue()));
- }
- }
- }
-
- return (String[]) titles.toArray(new String[titles.size()]);
- }
-
- /* **************************************************************** */
- /* Private methods and fields */
- /* **************************************************************** */
-
- /**
- * Values for P1 field in a SELECT command.
- */
- private enum SelectP1 {
- /**
- * Select by ID.
- */
- Id,
- /**
- * Select first entry.
- */
- First,
- /**
- * Select next entry.
- */
- Next
- }
-
- /**
- * Values for P1 field in a PUT DATA command.
- */
- private enum PutDataP1 {
- /**
- * Data field contains the size of the data that shall be stored.
- */
- Size,
- /**
- * Data field contains the first data part.
- */
- First,
- /**
- * Data field contains the next data part.
- */
- Next
- }
-
- /**
- * Values for P1 field in a GET DATA command.
- */
- private enum GetDataP1 {
- /**
- * Response contains the whole size of the data to be read.
- */
- Size,
- /**
- * Response contains the first data part.
- */
- First,
- /**
- * Response contains the next data part.
- */
- Next
- }
-
- /**
- * Sends a SeS PING command.
- *
- * @return true if the response is 0x9000, false otherwise.
- */
- private boolean sendPingCommand() {
- CommandApdu apdu = new CommandApdu(getChannel());
- apdu.setCla(CommandApdu.CLA_PROPRIETARY);
- apdu.setIns(CommandApdu.INS_PING_SS_APPLET);
- apdu.setP1((byte) 0x00);
- apdu.setP2((byte) 0x00);
- try {
- byte[] response = apdu.sendApdu();
- return ResponseApdu.getResponseStatusWordValue(response)
- == ResponseApdu.SW_NO_FURTHER_QUALIFICATION;
- } catch (Exception e) {
- return false;
- }
- }
-
- /**
- * Sends a SeS CREATE ENTRY command.
- *
- * @param title The title of the SeS entry to be created.
- *
- * @return The ID of the new entry.
- *
- * @throws IOException lower-level API exception.
- * @throws ProcessingException when SW != 0x9000.
- */
- private int sendCreateEntryCommand(String title) throws IOException,
- ProcessingException {
-
- byte[] titleArray = title.getBytes();
- CommandApdu apdu = new CommandApdu(getChannel());
- apdu.setCla(CommandApdu.CLA_PROPRIETARY);
- apdu.setIns(CommandApdu.INS_CREATE_SS_ENTRY);
- apdu.setP1((byte) 0x00);
- apdu.setP2((byte) 0x00);
- apdu.setData(titleArray);
-
- byte[] apduResponse = apdu.sendApdu();
- int swValue = ResponseApdu.getResponseStatusWordValue(apduResponse);
- if (swValue == ResponseApdu.SW_NO_FURTHER_QUALIFICATION) {
- return ByteArrayConverter.byteArrayToInt(ResponseApdu
- .getResponseData(apduResponse));
- } else {
- throw new ProcessingException(swValue);
- }
- }
-
- /**
- * Sends a SeS DELETE ENTRY command.
- *
- * @param id The ID of the entry to be deleted.
- *
- * @return true if the entry was deleted, false if it didn't exist.
- *
- * @throws IOException lower-level API exception.
- * @throws ProcessingException when SW != 0x9000.
- */
- private boolean sendDeleteEntryCommand(int id)
- throws IOException, ProcessingException {
-
- byte[] idArray = ByteArrayConverter.intToByteArray(id);
- CommandApdu apdu = new CommandApdu(getChannel());
- apdu.setCla(CommandApdu.CLA_PROPRIETARY);
- apdu.setIns(CommandApdu.INS_DELETE_SS_ENTRY);
- apdu.setP1(idArray[0]);
- apdu.setP2(idArray[1]);
-
- byte[] apduResponse = apdu.sendApdu();
- int swValue = ResponseApdu.getResponseStatusWordValue(apduResponse);
- if (swValue == ResponseApdu.SW_NO_FURTHER_QUALIFICATION) {
- return true;
- } else if (swValue == ResponseApdu.SES_SW_REF_NOT_FOUND) {
- return false;
- } else {
- throw new ProcessingException(swValue);
- }
- }
-
- /**
- * Sends a SeS SELECT ENRTY command.
- *
- * @param p1 The value of the P1 field on the APDU to be sent.
- * @param id The ID of the entry to be selected (Only if p1 = SelectP1.ID).
- *
- * @return The title of the selected entry.
- *
- * @throws IOException lower-level API exception.
- * @throws ProcessingException when SW != 0x9000.
- */
- private String sendSelectCommand(SelectP1 p1, int id)
- throws IOException, ProcessingException {
-
- CommandApdu apdu = new CommandApdu(getChannel());
- apdu.setCla(CommandApdu.CLA_PROPRIETARY);
- apdu.setIns(CommandApdu.INS_SELECT_SS_ENTRY);
- switch(p1) {
- case Id:
- apdu.setP1((byte) 0x00);
- byte[] idByteArray = new byte[2];
- System.arraycopy(
- ByteArrayConverter.intToByteArray(id),
- 2,
- idByteArray,
- 0,
- 2);
- apdu.setData(idByteArray);
- break;
- case First:
- apdu.setP1((byte) 0x01);
- break;
- case Next:
- apdu.setP1((byte) 0x02);
- break;
- }
- apdu.setP2((byte) 0x00);
- apdu.setLE((byte) 0x00);
- byte[] apduResponse = apdu.sendApdu();
- int swValue = ResponseApdu.getResponseStatusWordValue(apduResponse);
- if (swValue == ResponseApdu.SW_NO_FURTHER_QUALIFICATION) {
- return ByteArrayConverter.byteArrayToCharString(ResponseApdu
- .getResponseData(apduResponse));
- } else {
- throw new ProcessingException(swValue);
- }
- }
-
- /**
- * Sends a SeS SELECT ENRTY command.
- *
- * @param p1 The value of the P1 field on the APDU to be sent.
- *
- * @return The title of the selected entry.
- *
- * @throws IOException
- *
- * @throws IOException lower-level API exception.
- * @throws ProcessingException when SW != 0x9000.
- * @throws IllegalArgumentException If P1 = SelectP1.Id is used.
- */
- private String sendSelectCommand(SelectP1 p1) throws
- IOException, ProcessingException, IllegalArgumentException {
- if (p1 == SelectP1.Id) {
- throw new IllegalArgumentException();
- }
- return sendSelectCommand(p1, 0);
- }
-
- /**
- * Sends a SeS SELECT ENRTY command.
- *
- * @param id The ID of the entry to be selected.
- *
- * @return The title of the selected entry.
- *
- * @throws IOException lower-level API exception.
- * @throws ProcessingException when SW != 0x9000.
- */
- private String sendSelectCommand(int id)
- throws IOException, ProcessingException {
- return sendSelectCommand(SelectP1.Id, id);
- }
-
- /**
- * Sends a SeS PUT DATA command.
- *
- * @param p1 The value for the P1 field.
- * @param data The data to be written.
- *
- * @throws IOException lower-level API exception.
- * @throws ProcessingException when SW != 0x9000.
- */
- private void sendPutDataCommand(PutDataP1 p1, byte[] data)
- throws IOException, ProcessingException {
-
- CommandApdu apdu = new CommandApdu(getChannel());
- apdu.setCla(CommandApdu.CLA_PROPRIETARY);
- apdu.setIns(CommandApdu.INS_PUT_SS_ENTRY_DATA);
- switch(p1) {
- case Size:
- apdu.setP1((byte) 0x00);
- break;
- case First:
- apdu.setP1((byte) 0x01);
- break;
- case Next:
- apdu.setP1((byte) 0x02);
- break;
- }
- apdu.setP2((byte) 0x00);
- apdu.setData(data);
- byte[] apduResponse = apdu.sendApdu();
- int swValue = ResponseApdu.getResponseStatusWordValue(apduResponse);
- if (swValue != ResponseApdu.SW_NO_FURTHER_QUALIFICATION) {
- throw new ProcessingException(swValue);
- }
- }
-
- /**
- * Sends a SeS PUT DATA command with P1 = PutDataP1.Size.
- *
- * @param dataSize the size of the data.
- *
- * @throws IOException lower-level API exception.
- * @throws ProcessingException when SW != 0x9000.
- */
- private void sendPutDataCommand(int dataSize)
- throws IOException, ProcessingException {
- byte[] baDataSize = new byte[2];
- System.arraycopy(
- ByteArrayConverter.intToByteArray(dataSize),
- 2,
- baDataSize,
- 0,
- 2);
- sendPutDataCommand(PutDataP1.Size, baDataSize);
- }
-
- /**
- * Sends a SeS GET DATA command.
- *
- * @param p1 The value for the P1 field.
- *
- * @return the data of the currently selected SeS entry.
- *
- * @throws IOException lower-level API exception.
- * @throws ProcessingException when SW != 0x9000.
- */
- private byte[] sendGetDataCommand(GetDataP1 p1)
- throws IOException, ProcessingException {
-
- CommandApdu apdu = new CommandApdu(getChannel());
- apdu.setCla(CommandApdu.CLA_PROPRIETARY);
- apdu.setIns(CommandApdu.INS_GET_SS_ENTRY_DATA);
- switch(p1) {
- case Size:
- apdu.setP1((byte) 0x00);
- break;
- case First:
- apdu.setP1((byte) 0x01);
- break;
- case Next:
- apdu.setP1((byte) 0x02);
- break;
- }
- apdu.setP2((byte) 0x00);
- apdu.setLE((byte) 0x00);
- byte[] apduResponse = apdu.sendApdu();
- int swValue = ResponseApdu.getResponseStatusWordValue(apduResponse);
- if (swValue == ResponseApdu.SW_NO_FURTHER_QUALIFICATION) {
- return ResponseApdu.getResponseData(apduResponse);
- } else {
- throw new ProcessingException(swValue);
- }
- }
-
- /**
- * Sends a SeS GET ID command.
- *
- * @param title The title of the entry.
- *
- * @return The ID of the specified entry.
- *
- * @throws IOException lower-level API exception.
- * @throws ProcessingException when SW != 0x9000.
- */
- private int sendGetIdCommand(String title)
- throws IOException, ProcessingException {
-
- CommandApdu apdu = new CommandApdu(getChannel());
- apdu.setCla(CommandApdu.CLA_PROPRIETARY);
- apdu.setIns(CommandApdu.INS_READ_RECORD_B2);
- apdu.setP1((byte) 0x00);
- apdu.setP2((byte) 0x00);
- apdu.setData(title.getBytes());
-
- byte[] apduResponse = apdu.sendApdu();
- int swValue = ResponseApdu.getResponseStatusWordValue(apduResponse);
- if (swValue == ResponseApdu.SW_NO_FURTHER_QUALIFICATION) {
- return ByteArrayConverter.byteArrayToInt(ResponseApdu
- .getResponseData(apduResponse));
- } else {
- throw new ProcessingException(swValue);
- }
- }
-
-
-
- /**
- * Exception that wraps "non-9000" response.
- */
- private class ProcessingException extends Exception {
-
- /**
- * Status word value.
- */
- private int mSwValue;
-
- /**
- * Constructor.
- *
- * @param swValue The value of the Status Word.
- */
- private ProcessingException(int swValue) {
- mSwValue = swValue;
- }
-
- /**
- * Returns the value of the Status Word.
- *
- * @return the status word value.
- */
- private int getSwValue() {
- return mSwValue;
- }
- }
-}
diff --git a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/Session.java b/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/Session.java
deleted file mode 100644
index 15cb559..0000000
--- a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/Session.java
+++ /dev/null
@@ -1,380 +0,0 @@
-/*
- * Copyright (C) 2011, The Android Open Source Project
- *
- * 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.
- */
-/*
- * Contributed by: Giesecke & Devrient GmbH.
- */
-
-package org.simalliance.openmobileapi;
-
-import java.io.IOException;
-import java.util.MissingResourceException;
-import java.util.NoSuchElementException;
-
-import org.simalliance.openmobileapi.service.ISmartcardServiceChannel;
-import org.simalliance.openmobileapi.service.ISmartcardServiceSession;
-import org.simalliance.openmobileapi.service.SmartcardError;
-
-import android.os.RemoteException;
-
-/**
- * Instances of this class represent a connection session to one of the secure
- * elements available on the device. These objects can be used to get a
- * communication channel with an application in the secure element. This channel
- * can be the basic channel or a logical channel.
- *
- * @see <a href="http://simalliance.org">SIMalliance Open Mobile API v2.02</a>
- */
-public class Session {
-
- private final Object mLock = new Object();
- private final SEService mService;
- private final Reader mReader;
- private final ISmartcardServiceSession mSession;
-
- Session(SEService service,
- ISmartcardServiceSession session,
- Reader reader) {
- mService = service;
- mReader = reader;
- mSession = session;
- }
-
- /**
- * Get the reader that provides this session.
- *
- * @return The Reader object.
- */
- public Reader getReader() {
- return mReader;
- }
-
- /**
- * Get the Answer to Reset of this Secure Element. <br>
- * The returned byte array can be null if the ATR for this Secure Element is
- * not available.
- *
- * @return the ATR as a byte array or null.
- */
- public byte[] getATR() {
- if (mService == null || !mService.isConnected()) {
- throw new IllegalStateException("service not connected to system");
- }
- if (mSession == null) {
- throw new IllegalStateException("service session is null");
- }
- try {
- return mSession.getAtr();
- } catch (RemoteException e) {
- throw new IllegalStateException(e.getMessage());
- } catch (Exception e) {
- return null;
- }
- }
-
- /**
- * Close the connection with the Secure Element. This will close any
- * channels opened by this application with this Secure Element.
- */
- public void close() {
- if (mService == null || !mService.isConnected()) {
- throw new IllegalStateException("service not connected to system");
- }
- if (mSession != null) {
- synchronized (mLock) {
- SmartcardError error = new SmartcardError();
- try {
- mSession.close(error);
- } catch (RemoteException e) {
- throw new IllegalStateException(e.getMessage());
- }
- SEService.checkForException(error);
- }
- }
- }
-
- /**
- * Tells if this session is closed.
- *
- * @return <code>true</code> if the session is closed, false otherwise.
- */
- public boolean isClosed() {
- try {
- if (mSession == null) {
- return true;
- }
- return mSession.isClosed();
- } catch (RemoteException e) {
- throw new IllegalStateException(e.getMessage());
- }
- }
-
- /**
- * Close any channel opened on this session.
- *
- * @throws IOException
- */
- public void closeChannels() {
-
- if (mService == null || !mService.isConnected()) {
- throw new IllegalStateException("service not connected to system");
- }
-
- if (mSession != null) {
- synchronized (mLock) {
- SmartcardError error = new SmartcardError();
- try {
- mSession.closeChannels(error);
- } catch (RemoteException e) {
- throw new IllegalStateException(e.getMessage());
- }
- SEService.checkForException(error);
- }
- }
- }
-
- /**
- * Get an access to the basic channel, as defined in the ISO/IEC 7816-4
- * specification (the one that has number 0). The obtained object is an
- * instance of the Channel class. If the AID is null, which means no Applet
- * is to be selected on this channel and the default Applet is used. If the
- * AID is defined then the corresponding Applet is selected. Once this
- * channel has been opened by a device application, it is considered as
- * "locked" by this device application, and other calls to this method will
- * return null, until the channel is closed. Some Secure Elements (like the
- * UICC) might always keep the basic channel locked (i.e. return null to
- * applications), to prevent access to the basic channel, while some other
- * might return a channel object implementing some kind of filtering on the
- * commands, restricting the set of accepted command to a smaller set. It is
- * recommended for the UICC to reject the opening of the basic channel to a
- * specific Applet, by always answering null to such a request. For other
- * Secure Elements, the recommendation is to accept opening the basic
- * channel on the default Applet until another Applet is selected on the
- * basic channel. As there is no other way than a reset to select again the
- * default Applet, the implementation of the transport API should guarantee
- * that the openBasicChannel(null) command will return null until a reset
- * occurs. If such a restriction is not possible, then
- * openBasicChannel(null) should always return null and therefore prevent
- * access to the default Applet on the basic channel.
- * <p>
- * The optional select response data of an applet can be retrieved with
- * byte[] getSelectResponse().
- *
- * @param aid the AID of the Applet to be selected on this channel, as a
- * byte array, or null if no Applet is to be selected.
- * @throws IOException if there is a communication problem to the reader or
- * the Secure Element (e.g. if the SE is not responding).
- * @throws IllegalStateException if the Secure Element session is used after
- * being closed.
- * @throws IllegalArgumentException if the aid's length is not within 5 to
- * 16 (inclusive).
- * @throws SecurityException if the calling application cannot be granted
- * access to this AID or the default application on this
- * session.
- * @throws NoSuchElementException if an Applet with the defined AID does not
- * exist in the SE
- * @return an instance of Channel if available or null.
- */
- public Channel openBasicChannel(byte[] aid) throws IOException {
-
- if (mService == null || !mService.isConnected()) {
- throw new IllegalStateException("service not connected to system");
- }
- if (mSession == null) {
- throw new IllegalStateException("service session is null");
- }
- if (getReader() == null) {
- throw new IllegalStateException("reader must not be null");
- }
-
- synchronized (mLock) {
- ISmartcardServiceChannel channel;
- SmartcardError error = new SmartcardError();
- try {
- channel = mSession.openBasicChannelAid(
- aid,
- mService.getCallback(),
- error);
- } catch (RemoteException e) {
- throw new IllegalStateException(e.getMessage());
- } catch (Exception e) {
- throw new IOException(e.getMessage());
- }
- if (isBasicChannelInUse(error)) {
- return null;
- }
- if (aid == null || aid.length == 0) {
- if (!isDefaultApplicationSelected(error)) {
- return null;
- }
- }
- SEService.checkForException(error);
- error.clear();
- boolean b = channelCannotBeEstablished(error);
- SEService.checkForException(error);
- if (b) {
- return null;
- }
- error.clear();
- checkIfAppletAvailable(error);
- SEService.checkForException(error);
-
- if (channel == null) {
- return null;
- }
-
- return new Channel(mService, this, channel);
- }
- }
-
- /**
- * Open a logical channel with the Secure Element, selecting the Applet
- * represented by the given AID. The AID can be null, which means no Applet
- * is to be selected on this channel, the default Applet is used. It's up to
- * the Secure Element to choose which logical channel will be used.
- * <p>
- * The optional select response data of an applet can be retrieved with
- * byte[] getSelectResponse().
- * <p>
- * A logical channel to an applet can be opened multiple times if the applet
- * implements MultiSelectable.
- *
- * @param aid the AID of the Applet to be selected on this channel, as a
- * byte array.
- * @throws IOException if there is a communication problem to the reader or
- * the Secure Element. (e.g. if the SE is not responding)
- * @throws IllegalStateException if the Secure Element is used after being
- * closed.
- * @throws IllegalArgumentException if the aid's length is not within 5 to
- * 16 (inclusive).
- * @throws SecurityException if the calling application cannot be granted
- * access to this AID or the default application on this
- * session.
- * @throws NoSuchElementException if an Applet with the defined AID does not
- * exist in the SE or a logical channel is already open to a
- * non-multiselectable applet
- * @return an instance of Channel. Null if the Secure Element is unable to
- * provide a new logical channel.
- */
- public Channel openLogicalChannel(byte[] aid) throws IOException {
-
- if (mService == null || !mService.isConnected()) {
- throw new IllegalStateException("service not connected to system");
- }
- if (mSession == null) {
- throw new IllegalStateException("service session is null");
- }
- if (getReader() == null) {
- throw new IllegalStateException("reader must not be null");
- }
- synchronized (mLock) {
- SmartcardError error = new SmartcardError();
- ISmartcardServiceChannel channel;
- try {
- channel = mSession.openLogicalChannel(
- aid,
- mService.getCallback(),
- error);
- } catch (RemoteException e) {
- throw new IllegalStateException(e.getMessage());
- } catch (Exception e) {
- throw new IOException(e.getMessage());
- }
- SEService.checkForException(error);
- error.clear();
- boolean b = channelCannotBeEstablished(error);
- SEService.checkForException(error);
- if (b) {
- return null;
- }
- error.clear();
- checkIfAppletAvailable(error);
- SEService.checkForException(error);
-
- if (channel == null) {
- return null;
- }
-
- return new Channel(mService, this, channel);
- }
- }
-
- // ******************************************************************
- // package private methods
- // ******************************************************************
-
- private boolean isDefaultApplicationSelected(SmartcardError error) {
- Exception exp = error.createException();
- if (exp != null) {
- String msg = exp.getMessage();
- if (msg != null) {
- if (msg.contains("default application is not selected")) {
- return false;
- }
- }
- }
- return true;
- }
-
- private boolean isBasicChannelInUse(SmartcardError error) {
- Exception exp = error.createException();
- if (exp != null) {
- String msg = exp.getMessage();
- if (msg != null) {
- if (msg.contains("basic channel in use")) {
- return true;
- }
- }
- }
- return false;
- }
-
- private boolean channelCannotBeEstablished(SmartcardError error) {
- Exception exp = error.createException();
- if (exp != null) {
- if (exp instanceof MissingResourceException) {
- return true;
- }
- String msg = exp.getMessage();
- if (msg != null) {
- if (msg.contains("channel in use")) {
- return true;
- }
- if (msg.contains("open channel failed")) {
- return true;
- }
- if (msg.contains("out of channels")) {
- return true;
- }
- if (msg.contains("MANAGE CHANNEL")) {
- return true;
- }
- }
- }
- return false;
- }
-
- private void checkIfAppletAvailable(SmartcardError error)
- throws NoSuchElementException {
- Exception exp = error.createException();
- if (exp != null) {
- if (exp instanceof NoSuchElementException) {
- throw new NoSuchElementException(
- "Applet with the defined aid does not exist in the SE");
- }
- }
- }
-
-}
diff --git a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/internal/BerTlvParser.java b/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/internal/BerTlvParser.java
deleted file mode 100644
index 8ff4731..0000000
--- a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/internal/BerTlvParser.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright 2013 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.internal;
-
-/**
- * Class that wraps the functionality to parse BER-TLV data.
- */
-public final class BerTlvParser extends TlvParser {
-
- @Override
- public byte[] getTagBytes(byte[] array, int position)
- throws IllegalArgumentException {
- byte[] tagBytes;
-
- if ((array[position] & 0x1F) != 0x1F) {
- // Tag is 1-byte long
- tagBytes = new byte[1];
- } else {
- // ISO-IEC 7816-4 5.2.2.1: In tag fields of two or more bytes,
- // the values '00' to '1E' and '80' are invalid for the second byte.
- if ((array[position + 1] >= 0x00 && array[position + 1] <= 0x1E)
- || ((array[position + 1] & 0xFF) == 0x80)) {
- throw new IllegalArgumentException(
- "Invalid \"tag\" field at position " + position + ".");
- }
-
- if ((array[position + 1] & 0x80) == 0) {
- // Tag is 2-byte long
- tagBytes = new byte[2];
- } else if ((array[position + 1] & 0x80) == 0x80
- && (array[position + 2] & 0x80) == 0x00) {
- // Tag is 3-byte long
- tagBytes = new byte[3];
- } else {
- throw new IllegalArgumentException(
- "Invalid \"tag\" field at position " + position + ".");
- }
- }
-
- System.arraycopy(array, position, tagBytes, 0, tagBytes.length);
- return tagBytes;
- }
-
- @Override
- public byte[] getLengthBytes(byte[] array, int position)
- throws IllegalArgumentException {
- byte[] length;
- if ((array[position] & 0xFF) < 0x80) {
- // Length is 1-byte long
- length = new byte[1];
- } else if ((array[position] & 0xFF) == 0x81) {
- // Length is 2-byte long
- length = new byte[2];
- } else if ((array[position] & 0xFF) == 0x82) {
- // Length is 3-byte long
- length = new byte[3];
- } else if ((array[position] & 0xFF) == 0x83) {
- // Length is 4-byte long
- length = new byte[4];
- } else if ((array[position] & 0xFF) == 0x84) {
- // Length is 5-byte long
- length = new byte[5];
- } else {
- throw new IllegalArgumentException(
- "Invalid length field at position " + position + ".");
- }
-
- System.arraycopy(array, position, length, 0, length.length);
- return length;
- }
-
- @Override
- public int getLengthValue(byte[] lengthBytes) {
- int valueStartPosition;
- byte[] lengthValue;
-
- if (lengthBytes.length == 1) {
- valueStartPosition = 0;
- lengthValue = new byte[1];
- } else {
- valueStartPosition = 1;
- lengthValue = new byte[lengthBytes.length - 1];
- }
-
- System.arraycopy(lengthBytes, valueStartPosition, lengthValue, 0,
- lengthValue.length);
- return ByteArrayConverter.byteArrayToInt(lengthValue);
- }
-}
diff --git a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/internal/ByteArrayConverter.java b/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/internal/ByteArrayConverter.java
deleted file mode 100644
index dea9b8e..0000000
--- a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/internal/ByteArrayConverter.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright 2013 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.internal;
-
-/**
- * Utilities class.
- *
- */
-public final class ByteArrayConverter {
-
- /**
- * Override the default constructor to make it private.
- */
- private ByteArrayConverter() {
- }
-
- /**
- * Indicate the length of a short.
- */
- public static final int SHORT_SIZE = 2;
-
- /**
- * Indicate the beginning of the Array.
- */
- public static final int BEGINNING_ARRAY = 0;
-
- /**
- * Forms a char string from the byte array. Mostly used to convert
- * ASCII characters.
- *
- * @param byteArray The byte array to be hex-encoded.
- *
- * @return the char string.
- */
- public static String byteArrayToCharString(byte[] byteArray) {
- if (byteArray == null) {
- return "";
- }
-
- StringBuffer sb = new StringBuffer();
-
- for (byte b : byteArray) {
- sb.append((char) b);
- }
-
- return sb.toString();
- }
-
- /**
- * Forms a FileViewProvider-compatible path String (i.e., transforms the
- * byte array {0x3F, 0x00, 0x2F, 0xE2} into the String "3F00:2FE2").
- *
- * @param rawPath The byte array containing the path component.
- *
- * @return A FileViewProvider-compatible path String.
- *
- * @throws IllegalArgumentException if the path has a bad coding.
- */
- public static String byteArrayToPathString(byte[] rawPath)
- throws IllegalArgumentException {
- if (rawPath.length % 2 != 0) {
- throw new IllegalArgumentException("Invald path");
- }
-
- byte[] buffer = new byte[2];
- String path = "";
- for (int i = 0; i < rawPath.length; i += 2) {
- System.arraycopy(rawPath, i, buffer, 0, 2);
- path = path.concat(byteArrayToHexString(buffer));
- if (i != rawPath.length - 2) {
- path = path.concat(":");
- }
- }
- return path;
- }
-
-
- /**
- * Forms an hex-encoded String of the specified byte array.
- *
- * @param byteArray The byte array to be hex-encoded.
- *
- * @return An hex-encoded String of the specified byte array.
- */
- public static String byteArrayToHexString(byte[] byteArray) {
- if (byteArray == null) {
- return "";
- }
-
- StringBuffer sb = new StringBuffer();
-
- for (byte b : byteArray) {
- sb.append(String.format("%02x", b & 0xFF));
- }
-
- return sb.toString();
- }
-
- /**
- * Forms a byte array containing the values of the hex-encoded string.
- *
- * @param str The hex-encoded string to be converted to byte-array.
- *
- * @return A byte array containing the values of the hex-encoded string.
- */
- public static byte[] hexStringToByteArray(String str) {
- if (str.length() % 2 != 0) {
- return null;
- }
-
- str = str.toUpperCase();
-
- byte[] outputBytes = new byte[str.length() / 2];
-
- for (int i = 0; i < str.length(); i += 2) {
-
- if (!isHexChar(str.charAt(i)) || !isHexChar(str.charAt(i + 1))) {
- // Return null if invalid characters
- return null;
- }
-
- outputBytes[i / 2] = (byte) (
- (Character.digit(str.charAt(i), 16) << 4)
- + Character.digit(str.charAt(i + 1), 16));
- }
-
- return outputBytes;
- }
-
- /**
- * Forms a byte array containing the specified integer value.
- *
- * @param value The integer value to be converted to byte array.
- *
- * @return A byte array containing the specified integer value.
- */
- public static byte[] intToByteArray(int value) {
- return new byte[] {
- (byte) (value >>> 24),
- (byte) (value >>> 16),
- (byte) (value >>> 8),
- (byte) value};
- }
-
- /**
- * Forms an integer from a byte array.
- *
- * @param byteArray The byte array from where to form the integer.
- *
- * @return The integer value representing the specified byte array. 0 if the
- * array is empty. If the array is longer than 4 bytes, only bytes 0
- * to 3 will be considered.
- */
- public static int byteArrayToInt(byte[] byteArray) {
- switch (byteArray.length) {
- case 0:
- return 0;
- case 1:
- return (byteArray[0] & 0xFF);
- case 2:
- return (byteArray[0] & 0xFF) << 8 | (byteArray[1] & 0xFF);
- case 3:
- return (byteArray[0] & 0xFF) << 16 | (byteArray[1] & 0xFF) << 8
- | (byteArray[2] & 0xFF);
- default:
- return (byteArray[0] & 0xFF) << 24 | (byteArray[1] & 0xFF) << 16
- | (byteArray[2] & 0xFF) << 8 | byteArray[3] & 0xFF;
-
- }
- }
-
- /**
- * Decides whether a char is a valid hex value or not.
- *
- * @param c The char to be evaluated.
- *
- * @return true if the specified char is a valid hex value, false otherwise.
- */
- public static boolean isHexChar(char c) {
- if (Character.isLowerCase(c)) {
- c = Character.toUpperCase(c);
- }
-
- return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F');
- }
-}
diff --git a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/internal/DerTlvCoder.java b/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/internal/DerTlvCoder.java
deleted file mode 100644
index 73bf4bd..0000000
--- a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/internal/DerTlvCoder.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright 2013 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.internal;
-
-// TODO: implement more type encoders.
-
-/**
- * Class that implements functionalities over DER-coded objects.
- */
-public final class DerTlvCoder {
-
- /**
- * Tag for INTEGER-type objects.
- */
- public static final byte[] TAG_INTEGER = {(byte) 0x02};
- /**
- * Tag for OCTET STRING-type objects.
- */
- public static final byte[] TAG_OCTET_STRING = {(byte) 0x04};
- /**
- * Tag for SEQUENCE-type objects.
- */
- public static final byte[] TAG_SEQUENCE = {(byte) 0x30};
-
- /**
- * Override default constructor to avoid instantiations.
- */
- private DerTlvCoder() {
- }
-
- /**
- * Returns an array of bytes representing the specified length.
- *
- * @param lengthValue The length to be represented.
- *
- * @return An array of bytes representing the specified length.
- *
- * @throws IllegalArgumentException if the length is less than 0.
- */
- public static byte[] encodeLength(int lengthValue)
- throws IllegalArgumentException {
- if (lengthValue < 0) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidValue("lengthValue"));
- }
- // Get the byte array representing the length
- byte[] rawLength = ByteArrayConverter.intToByteArray(lengthValue);
-
- byte[] encodedLength;
- if (lengthValue <= 0x7F) {
- // Use short form: bit 8 set to 0
- encodedLength = new byte[1];
- encodedLength[0] = (byte) (0x7F & rawLength[3]);
- } else if (lengthValue <= 0x0FF) {
- // Use long form (2 bytes)
- encodedLength = new byte[2];
- encodedLength[0] = (byte) 0x81;
- encodedLength[1] = rawLength[3];
- } else if (lengthValue <= 0xFFFF) {
- // Use long form (3 bytes)
- encodedLength = new byte[3];
- encodedLength[0] = (byte) 0x82;
- encodedLength[1] = rawLength[2];
- encodedLength[2] = rawLength[3];
- } else if (lengthValue <= 0xFFFFFF) {
- // Use long form (4 bytes)
- encodedLength = new byte[4];
- encodedLength[0] = (byte) 0x83;
- encodedLength[1] = rawLength[1];
- encodedLength[2] = rawLength[2];
- encodedLength[3] = rawLength[3];
- } else {
- // Use long form (5 bytes)
- encodedLength = new byte[5];
- encodedLength[0] = (byte) 0x84;
- encodedLength[1] = rawLength[0];
- encodedLength[2] = rawLength[1];
- encodedLength[3] = rawLength[2];
- encodedLength[4] = rawLength[3];
- }
-
- return encodedLength;
- }
-
- /**
- * Encodes an object of type "INTEGER".
- *
- * @param value The value of the integer to be encoded.
- *
- * @return A byte array representing the integer in DER format.
- */
- public static byte[] encodeInteger(int value) {
- byte[] valueByteArray = ByteArrayConverter.intToByteArray(value);
-
- // Delete leading bytes that are equal to 0 to
- // ensure that the minimum number of bytes is used
- while (valueByteArray[0] == 0x00) {
- byte[] tmp = new byte[valueByteArray.length - 1];
- System.arraycopy(valueByteArray, 1, tmp, 0, tmp.length);
- valueByteArray = new byte[tmp.length];
- System.arraycopy(tmp, 0, valueByteArray, 0, tmp.length);
- }
-
- byte[] lengthByteArray = encodeLength(valueByteArray.length);
-
- byte[] encodedInteger = new byte[TAG_INTEGER.length
- + lengthByteArray.length + valueByteArray.length];
-
- System.arraycopy(TAG_INTEGER, 0, encodedInteger, 0,
- TAG_INTEGER.length);
- System.arraycopy(lengthByteArray, 0, encodedInteger,
- TAG_INTEGER.length, lengthByteArray.length);
- System.arraycopy(valueByteArray, 0, encodedInteger,
- TAG_INTEGER.length + lengthByteArray.length,
- valueByteArray.length);
-
- return encodedInteger;
- }
-
- /**
- * Encodes an object of type "OCTET STRING".
- *
- * @param octetString the object to be encoded.
- *
- * @return A byte array representing the octet string in DER format.
- */
- public static byte[] encodeOctetString(byte[] octetString) {
- byte[] lengthByteArray = encodeLength(octetString.length);
-
- byte[] encodedOctetString = new byte[TAG_OCTET_STRING.length
- + lengthByteArray.length + octetString.length];
-
- System.arraycopy(TAG_OCTET_STRING, 0, encodedOctetString, 0,
- TAG_OCTET_STRING.length);
- System.arraycopy(lengthByteArray, 0, encodedOctetString,
- TAG_OCTET_STRING.length, lengthByteArray.length);
- System.arraycopy(octetString, 0, encodedOctetString,
- TAG_OCTET_STRING.length + lengthByteArray.length,
- octetString.length);
-
- return encodedOctetString;
- }
-
- /**
- * Encodes an object of type "SEQUENCE".
- *
- * @param sequence The sequence to be encoded.
- *
- * @return A byte array representing the sequence in DER format.
- */
- public static byte[] encodeSequence(byte[] sequence) {
- byte[] lengthByteArray = encodeLength(sequence.length);
-
- byte[] encodedSequence = new byte[TAG_SEQUENCE.length
- + lengthByteArray.length + sequence.length];
-
- System.arraycopy(TAG_SEQUENCE, 0, encodedSequence, 0,
- TAG_SEQUENCE.length);
- System.arraycopy(lengthByteArray, 0, encodedSequence,
- TAG_SEQUENCE.length, lengthByteArray.length);
- System.arraycopy(sequence, 0, encodedSequence, TAG_SEQUENCE.length
- + lengthByteArray.length, sequence.length);
-
- return encodedSequence;
- }
-}
diff --git a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/internal/DerTlvParser.java b/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/internal/DerTlvParser.java
deleted file mode 100644
index f42bf7c..0000000
--- a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/internal/DerTlvParser.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright 2013 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.internal;
-
-/**
- * Class that parses DER-Coded byte arrays.
- */
-public class DerTlvParser extends TlvParser {
-
- @Override
- public byte[] getTagBytes(byte[] array, int position)
- throws IllegalArgumentException {
- byte[] tagBytes;
-
- if ((array[position] & 0x1F) != 0x1F) {
- // Tag is 1-byte long
- tagBytes = new byte[1];
- } else {
- int tmpPosition = position;
- tmpPosition++;
- // ITU X.690: bits 7 to 1 of the first subsequent
- // octet shall not all be zero.
- if ((array[tmpPosition] & 0x7F) == 0x00) {
- throw new IllegalArgumentException(
- ErrorStrings.TLV_INVALID_TAG);
- }
-
- // The length of the tag
- int length = 2;
- // Loop until a zero is found in the bit 8 of the array
- while ((array[tmpPosition] & 0x80) == 0x80) {
- length++;
- tmpPosition++;
- }
-
- tagBytes = new byte[length];
- }
-
- System.arraycopy(array, position, tagBytes, 0, tagBytes.length);
- return tagBytes;
- }
-
- @Override
- public byte[] getLengthBytes(byte[] array, int position)
- throws IllegalArgumentException {
- byte[] lengthBytes;
-
- if ((array[position] & 0x80) != 0x80) {
- // Short form
- lengthBytes = new byte[1];
- } else {
- // ITU X.690: in the long form, [...] the value
- // 0xFF shall not be used [for the first byte].
- if ((array[position] & 0xFF) == 0xFF) {
- throw new IllegalArgumentException(
- ErrorStrings.TLV_INVALID_LENGTH);
- }
-
- // Bits 7 to 1 indicate the number of subsequent octets
- lengthBytes = new byte[1 + (array[position] & 0x7F)];
- }
-
- System.arraycopy(array, position, lengthBytes, 0, lengthBytes.length);
- return lengthBytes;
- }
-
- @Override
- public int getLengthValue(byte[] lengthBytes) {
- int valueStartPosition;
- byte[] lengthValue;
-
- if (lengthBytes.length == 1) {
- valueStartPosition = 0;
- lengthValue = new byte[1];
- } else {
- valueStartPosition = 1;
- lengthValue = new byte[lengthBytes.length - 1];
- }
-
- System.arraycopy(lengthBytes, valueStartPosition, lengthValue, 0,
- lengthValue.length);
- return ByteArrayConverter.byteArrayToInt(lengthValue);
- }
-}
diff --git a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/internal/ErrorStrings.java b/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/internal/ErrorStrings.java
deleted file mode 100644
index 0afdbb6..0000000
--- a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/internal/ErrorStrings.java
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * Copyright 2013 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.internal;
-
-/**
- * Class that contains the error strings that will be used throughout the APIs.
- */
-public final class ErrorStrings {
-
- /**
- * Override the default constructor to not allow the instantiation
- * of the class.
- */
- private ErrorStrings() {
- }
-
- // Errors related to parameters
-
- /**
- * Parameter <parameterName> must not be null.
- *
- * @param parameterName The name of the parameter that can't be null.
- *
- * @return Parameter <parameterName> must not be null.
- */
- public static String paramNull(String parameterName) {
- return "Parameter " + parameterName + " must not be null.";
- }
-
- /**
- * Parameter <parameterName> has an invalid length.
- *
- * @param parameterName The name of the parameter that has an
- * invalid length.
- *
- * @return Parameter <parameterName> has an invalid length.
- */
- public static String paramInvalidArrayLength(String parameterName) {
- return "Parameter " + parameterName + " has an invalid length.";
- }
-
- /**
- * Parameter <parameterName> has an invalid value.
- *
- * @param parameterName The name of the parameter that has an invalid value.
- *
- * @return Parameter <parameterName> has an invalid value.
- */
- public static String paramInvalidValue(String parameterName) {
- return "Parameter " + parameterName + " has an invalid value.";
- }
-
- // Errors related to APDU formation and exchange
-
- /**
- * APDU has an invalid format.
- */
- public static final String APDU_WRONG_FORMAT
- = "APDU has an invalid format.";
-
- /**
- * Response APDU has a bad coding.
- */
- public static final String APDU_BAD_RESPONSE
- = "Response APDU has a bad coding.";
-
- /**
- * Channel is closed.
- */
- public static final String CHANNEL_CLOSED = "Channel is closed.";
-
- // Errors related to PIN operations
-
- /**
- * Wrong PIN.
- */
- public static final String PIN_WRONG = "Wrong PIN.";
-
- /**
- * Referenced PIN could not be found.
- */
- public static final String PIN_REF_NOT_FOUND
- = "Referenced PIN could not be found.";
-
- /**
- * Referenced PIN is blocked.
- */
- public static final String PIN_BLOCKED
- = "Referenced PIN is blocked.";
-
-
- // Errors related to files
-
- /**
- * File not found.
- */
- public static final String FILE_NOT_FOUND
- = "File not found.";
-
- /**
- * Invalid File ID.
- * File ID must be between FID_MIN_VALUE and FID_MAX_VALUE.
- */
- public static final String INVALID_FID
- = "Invalid File ID. File ID must be between ";
- //+ FileViewProvider.FID_MIN_VALUE + " and "
- //+ FileViewProvider.FID_MAX_VALUE + ".";
-
- /**
- * Invalid Short File ID. SFI must be between
- * FileViewProvider.SFI_MIN_VALUE and FileViewProvider.SFI_MAX_VALUE,
- * or be FileViewProvider.CURRENT_FILE.
- */
- public static final String INVALID_SFI
- = "Invalid Short File ID. SFI must be between ";
- //+ FileViewProvider.SFI_MIN_VALUE + " and "
- //+ FileViewProvider.SFI_MAX_VALUE + ", or "
- //+ "be FileViewProvider.CURRENT_FILE.";
-
- /**
- * The selected file is not transparent.
- */
- public static final String NO_TRANSPARENT_FILE = "The selected file is not"
- + " transparent.";
-
- /**
- * The selected file is not record-based.
- */
- public static final String NO_RECORD_BASED_FILE = "The selected"
- + " file is not record-based.";
-
- /**
- * Offset outside EF.
- */
- public static final String OFFSET_OUTSIDE_EF = "Offset outside EF.";
-
- /**
- * Record not found.
- */
- public static final String RECORD_NOT_FOUND = "Record not found.";
-
- // Errors related to TLV parsing
-
- /**
- * Tag not found.
- */
- public static final String TLV_TAG_NOT_FOUND = "Tag not found.";
-
- /**
- * Unexpected tag.
- */
- public static final String TLV_TAG_UNEXPECTED = "Unexpected tag.";
-
- /**
- * Invalid tag.
- */
- public static final String TLV_INVALID_TAG = "Invalid tag.";
-
- /**
- * Invalid length field.
- */
- public static final String TLV_INVALID_LENGTH = "Invalid length field.";
-
- // Other messages
-
- /**
- * Referenced data not found.
- */
- public static final String REF_NOT_FOUND
- = "Referenced data not found.";
-
- /**
- * This operation is not supported by the selected Applet.
- */
- public static final String OPERATION_NOT_SUPORTED
- = "This operation is not supported by the selected Applet.";
-
- /**
- * Invalid CLA.
- */
- public static final String INVALID_CLA
- = "Invalid class";
-
- /**
- * Wrong length.
- */
- public static final String WRONG_LENGTH = "Wrong length.";
-
- /**
- * Security status not satisfied.
- */
- public static final String SECURITY_STATUS_NOT_SATISFIED
- = "Security status not satisfied.";
-
- /**
- * Memory failure.
- */
- public static final String MEMORY_FAILURE = "Memory failure.";
-
- /**
- * No file is currently selected.
- */
- public static final String NO_CURRENT_FILE =
- "No file is currently selected.";
-
- /**
- * Not enough memory space in the file.
- */
- public static final String NOT_ENOUGH_MEMORY =
- "Not enough memory space in the file.";
-
- /**
- * Authentication method blocked.
- */
- public static final String AUTH_METHOD_BLOCKED
- = "PIN is blocked.";
-
- /**
- * Unexpected Status Word: 0x<swValue>.
- *
- * @param swValue The value of the SW.
- *
- * @return Unexpected Status Word: 0x<swValue>.
- */
- public static String unexpectedStatusWord(int swValue) {
- return "Unexpected Status Word: 0x"
- + String.format("%02x", swValue) + ".";
- }
-
- // PKCS#15 error strings
-
- /**
- * No PKCS#15 file structure found.
- */
- public static final String PKCS15_NO_FS =
- "No PKCS#15 file structure found.";
-
- // Secure Storage error strings.
-
- /**
- * Channel is not connected to a Secure Storage applet.
- */
- public static final String SES_APP_NOT_PRESENT
- = "Channel is not connected to a Secure Storage applet.";
-
- /**
- * File creation failed due to memory issues.
- */
- public static final String SES_CREATE_FAILED_MEMORY
- = "File creation failed due to memory issues.";
-
- /**
- * Security exception.
- */
- public static final String SES_SECURITY_EXCEPTION =
- "The PIN to access the Secure Storage Applet has not been verified";
- /**
- * Channel is close.
- */
- public static final String SES_CHANNEL_CLOSE =
- "The channel is close";
- /**
- * There is an incorrect title of the file.
- */
- public static final String SES_INCORRECT_TITLE =
- "The title is incorrect: bad encoding or wrong length.";
-
- /**
- * IOError due to an incomplete read procedure.
- */
- public static final String SES_IOERROR_READ =
- "The entry could not be read because an incomplete read procedure.";
-
- /**
- * IOError due to an incomplete write procedure.
- */
- public static final String SES_IOERROR_WRITE =
- "The entry could'b be read because an incomplete write procedure.";
-
- /**
- * The title is repeated.
- */
- public static final String SES_TITLE_NOT_EXISTS =
- "The written title does not exist.";
-
- /**
- * Incorrect values in the command data.
- */
- public static final String SES_TITLE_EXISTS =
- "The specified title already exists.";
-
- /**
- * Not enough memory space.
- */
- public static final String SES_NOT_ENOUGH_MEMORY =
- "Not enough memory space";
-
- /**
- * Referenced data not found (if no SeS entry is currently selected.
- */
- public static final String SES_NO_ENTRY_SELECTED =
- "Referenced data not found (if no SeS entry is currently selected";
- /**
- * Referenced data not found (if no SeS entry not exists.
- */
- public static final String SES_ENTRY_NOT_EXISTS =
- "Referenced data not found (if no SeS entry not exists";
- /**
- * If title is empty.
- */
- public static final String SES_EMPTY_TITLE =
- "The title is empty";
-
- /**
- * If title is too long (max value 60 chars).
- */
- public static final String SES_LONG_TITLE =
- "The title is too long (max value 60 chars).";
-
-}
diff --git a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/internal/HistoricalBytesUtilities.java b/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/internal/HistoricalBytesUtilities.java
deleted file mode 100644
index 1cc9d5b..0000000
--- a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/internal/HistoricalBytesUtilities.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright 2013 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.internal;
-
-import java.util.ArrayList;
-
-/**
- * Class that wraps some functionalities for the HistoricalBytes.
- */
-public final class HistoricalBytesUtilities {
-
- /**
- * Override default constructor.
- */
- private HistoricalBytesUtilities() {
- }
-
- /**
- * Parses an ATR and returns its historical bytes.
- *
- * @param atr The ATR where to get the historical bytes from.
- *
- * @return The historical bytes of the ATR.
- */
- public static byte[] getHistBytes(byte[] atr) {
- // Set the next byte to be parsed. First byte is TS, so it will be
- // ignored.
- int position = 1;
-
- // Get byte T0 of ATR.
- byte tdi = atr[position];
-
- // Set the boolean that indicates whether any of TAi+1, TBi+1, TCi+1,
- // and TDi+1 are present
- boolean areNextInterfaceBytesPresent = (tdi & 0xF0) != 0;
-
- // Initialize a List of all "T" values present in T0, Y1, Y2...
- ArrayList<Integer> tValues = new ArrayList<Integer>();
- // and get the first value of T.
- tValues.add(tdi & 0x0F);
-
- // Set the next position to be parsed
- position++;
-
- while (areNextInterfaceBytesPresent) {
- // Start parsing the next Interface bytes.
-
- // If TAi+1 is present increase position
- if ((tdi & 0x10) != 0) {
- position++;
- }
-
- // If TBi+1 is present increase position
- if ((tdi & 0x20) != 0) {
- position++;
- }
-
- // If TCi+1 is present increase position
- if ((tdi & 0x40) != 0) {
- position++;
- }
-
- // If TDi+1 is present...
- if ((tdi & 0x80) != 0) {
- // Update TDi
- tdi = atr[position];
- // Check if next Interface bytes are present
- areNextInterfaceBytesPresent = (tdi & 0xF0) != 0;
- // Get the next value of T
- tValues.add(tdi & 0x0F);
- // Increase the position
- position++;
- } else {
- // If TD is not present, there are no more interface bytes.
- areNextInterfaceBytesPresent = false;
- }
- }
-
- // Decide the length of historical bytes
- int length = atr.length - position;
- // If TCK byte is present, historical bytes are one byte shorter.
- if (isTckPresent(tValues)) {
- length--;
- }
- byte[] historicalBytes = new byte[length];
- System.arraycopy(atr, position, historicalBytes, 0, length);
- return historicalBytes;
- }
-
- /**
- * Decides whether TCK should be present based in the ATR on the "T" values
- * found when parsing the ATR.
- *
- * From ISO/IEC 7816-3 8.2.5: "If only T=0 is indicated, possibly by
- * default, then TCK shall be absent. If T=0 and T=15 are present and in all
- * the other cases, TCK shall be present."
- *
- * @param tValues The values of "T" found when parsing the ATR.
- *
- * @return true if TCK should be present, false otherwise.
- */
- private static boolean isTckPresent(ArrayList<Integer> tValues) {
- return !((tValues.size() == 1) && tValues.contains(0));
- }
-}
diff --git a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/internal/OidParser.java b/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/internal/OidParser.java
deleted file mode 100644
index a9782da..0000000
--- a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/internal/OidParser.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright 2013 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.internal;
-
-import java.util.ArrayList;
-
-/**
- * Class for encoding OID objects.
- */
-public final class OidParser {
-
- /**
- * Override default constructor.
- */
- private OidParser() {
- }
-
- /**
- * Converts a dot-splitted OID string into the corresponding byte array.
- *
- * @param oid The String OID to be encoded.
- *
- * @return The OID as byte array.
- *
- * @throws IllegalArgumentException If oid has a bad coding.
- */
- public static byte[] encodeOid(String oid) throws IllegalArgumentException {
- ArrayList<Byte> byteList = new ArrayList<Byte>();
- String[] oidNumbers = oid.split("\\.");
-
- if (oidNumbers.length < 3) {
- throw new IllegalArgumentException();
- }
-
- int firstValue;
- int secondValue;
- try {
- firstValue = Integer.parseInt(oidNumbers[0]);
- secondValue = Integer.parseInt(oidNumbers[1]);
- } catch (Exception e) {
- throw new IllegalArgumentException();
- }
- byteList.add(encondeFirstDigits(firstValue, secondValue));
-
- for (int j = 2; j < oidNumbers.length; j++) {
- int number;
- try {
- number = Integer.parseInt(oidNumbers[j]);
- } catch (Exception e) {
- throw new IllegalArgumentException();
- }
- byte[] codification = encodeInteger(number);
- for (byte b : codification) {
- byteList.add(b);
- }
- }
-
- byte[] result = new byte[byteList.size()];
- for (int i = 0; i < byteList.size(); i++) {
- result[i] = byteList.get(i);
- }
- return result;
- }
-
- /**
- * Encodes the first two numbers of an oid.
- *
- * @param first The first number.
- * @param second The second number
- *
- * @return A byte representing the specified two digits
- * according to the encoding rules.
- *
- * @throws IllegalArgumentException if any parameter is lower than 0.
- */
- public static byte encondeFirstDigits(int first, int second)
- throws IllegalArgumentException {
- if (first < 0 || second < 0) {
- throw new IllegalArgumentException();
- }
- return (byte) ((40 * first) + second);
- }
-
- /**
- * Encodes a number according to OID codification rules.
- *
- * @param number The number to be encoded.
- *
- * @return A byte array containing the encoding.
- *
- * @throws IllegalArgumentException If number is lower than 0.
- */
- public static byte[] encodeInteger(int number)
- throws IllegalArgumentException {
- if (number < 0) {
- throw new IllegalArgumentException();
- }
- if (number == 0) {
- return new byte[] {(byte) 0};
- }
-
- boolean isFirstIteration = true;
- byte[] result = new byte[0];
- while (number != 0) {
- // Increase the size of the result array
- byte[] aux = new byte[result.length];
- System.arraycopy(result, 0, aux, 0, result.length);
- result = new byte[result.length + 1];
- System.arraycopy(aux, 0, result, 1, aux.length);
-
- // Get the first 7 bits
- byte value = (byte) (number & 0x7F);
- if (isFirstIteration) {
- // On the first iteration we are getting the last byte,
- // so bit 8 shall be set to 0.
- // Since we already applied the mask, it is 0.
- isFirstIteration = false;
- } else {
- // On subsequent iterations, bit 8 shall be set to 1
- value = (byte) (value | 0x80);
- }
- // Add the value to the array
- result[0] = value;
-
- // Remove the bits that has been already encoded
- number = number >> 7;
- }
-
- return result;
- }
-}
diff --git a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/internal/TlvEntryWrapper.java b/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/internal/TlvEntryWrapper.java
deleted file mode 100644
index 46fae22..0000000
--- a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/internal/TlvEntryWrapper.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright 2013 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.internal;
-
-
-/**
- * Class that wraps the values and basic functionality of a TLV entry.
- */
-public class TlvEntryWrapper {
- /**
- * The Tag of the TLV entry.
- */
- private byte[] mTag;
- /**
- * The value of the TLV entry.
- */
- private byte[] mValue;
- /**
- * The total length of the entry.
- */
- private int mTotalLength;
-
- /**
- * Initializes a new instance of the TlvEntryWrapper class.
- *
- * @param data The data where the TLV object is.
- * @param startPosition The position where the TLV object starts.
- * @param parser The parser to use.
- *
- * @throws IllegalArgumentException If no TLV object is found.
- */
- public TlvEntryWrapper(byte[] data, int startPosition, TlvParser parser)
- throws IllegalArgumentException {
- int position = startPosition;
-
- mTag = parser.getTagBytes(data, startPosition);
- position += mTag.length;
-
- byte[] lengthBytes = parser.getLengthBytes(data, position);
- position += lengthBytes.length;
-
- mValue = new byte[parser.getLengthValue(lengthBytes)];
- System.arraycopy(data, position, mValue, 0, mValue.length);
-
- mTotalLength = mTag.length + lengthBytes.length + mValue.length;
- }
-
- /**
- * Gets the tag of the entry.
- *
- * @return The tag of the entry.
- */
- public byte[] getTag() {
- return mTag;
- }
-
- /**
- * Gets the total length of the entry.
- *
- * @return The total length of the entry.
- */
- public int getTotalLength() {
- return mTotalLength;
- }
-
- /**
- * Gets the value of the entry.
- *
- * @return The value of the entry.
- */
- public byte[] getValue() {
- return mValue;
- }
-
- /**
- * Encodes the current object.
- *
- * @return An array of bytes representing the Der-codified object.
- */
- public byte[] encode() {
- byte[] encodedObject = new byte[mTotalLength];
- System.arraycopy(mTag, 0, encodedObject, 0, mTag.length);
- byte[] lengthBytes = DerTlvCoder.encodeLength(mValue.length);
- System.arraycopy(lengthBytes, mTag.length, encodedObject, mTag.length,
- lengthBytes.length);
- System.arraycopy(mValue, 0, encodedObject, mTag.length
- + lengthBytes.length, mValue.length);
- return encodedObject;
- }
-}
diff --git a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/internal/TlvParser.java b/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/internal/TlvParser.java
deleted file mode 100644
index 74e5e09..0000000
--- a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/internal/TlvParser.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright 2013 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.internal;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Abstract class that must be extended by any TLV parser.
- */
-public abstract class TlvParser {
-
- /**
- * Extracts the type field that starts at the specified position.
- *
- * @param array The array that contains the type field to be extracted.
- *
- * @param position The start position of the type field.
- *
- * @return A byte array containing the type field found at the specified
- * position.
- *
- * @throws IllegalArgumentException if no valid tag is found at the
- * specified position.
- */
- abstract byte[] getTagBytes(byte[] array, int position)
- throws IllegalArgumentException;
-
- /**
- * Extracts the length field that starts at the specified position.
- *
- * @param array The array that contains the length field to be extracted.
- *
- * @param position The position where the length field starts.
- *
- * @return A byte array containing the length field.
- *
- * @throws IllegalArgumentException if no valid length field is found at the
- * specified position.
- */
- abstract byte[] getLengthBytes(byte[] array, int position)
- throws IllegalArgumentException;
-
- /**
- * Converts a length field to an integer value.
- *
- * @param lengthBytes The length field.
- *
- * @return The integer value of the length field.
- */
- abstract int getLengthValue(byte[] lengthBytes);
-
- /**
- * Parses the full TLV array.
- *
- * @param array The array to be parsed.
- *
- * @return The list of TLV objects found in the array.
- */
- public List<TlvEntryWrapper> parseArray(byte[] array) {
- byte[] data = getValidTlvData(array);
-
- int position = 0;
- ArrayList<TlvEntryWrapper> list = new ArrayList<TlvEntryWrapper>();
-
- while (position < data.length) {
- TlvEntryWrapper nextEntry
- = new TlvEntryWrapper(data, position, this);
- list.add(nextEntry);
- position += nextEntry.getTotalLength();
- }
-
- return (List<TlvEntryWrapper>) list;
- }
-
- /**
- * Searches for the first occurrence of the specified tag after the
- * specified position.
- *
- * @param data The data where to find the tag.
- * @param tag The tag to search for.
- * @param startPosition The position where to start the search.
- *
- * @return The position where the tag is found.
- *
- * @throws IllegalArgumentException if startPosition is lower than 0.
- * @throws IllegalArgumentException if the tag could not be found.
- * @throws IllegalArgumentException if data is not correctly coded.
- */
- public int searchTag(byte[] data, byte[] tag, int startPosition)
- throws IllegalArgumentException {
- if (startPosition < 0) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidValue("startPosition"));
- }
-
- int position = startPosition;
- while (position < data.length) {
- TlvEntryWrapper derEntry
- = new TlvEntryWrapper(data, position, this);
- if (Arrays.equals(tag, derEntry.getTag())) {
- return position;
- } else {
- position += derEntry.getTotalLength();
- }
- }
-
- // If data array has been parsed and tag has not been found...
- throw new IllegalArgumentException(ErrorStrings.TLV_TAG_NOT_FOUND);
- }
-
- /**
- * Extracts a valid TLV array at the beginning of the specified array.
- *
- * @param rawData The data to extract the valid TLF from.
- *
- * @return A byte array containing a valid TLV structure found at the
- * beginning of rawData.
- */
- public byte[] getValidTlvData(byte[] rawData) {
- if (isValidTlvStructure(rawData)) {
- return rawData;
- } else {
- int position = 0;
- while (true) {
- try {
- int tmpPosition = position;
- byte[] tag = getTagBytes(rawData, tmpPosition);
- tmpPosition += tag.length;
-
- byte[] length = getLengthBytes(rawData, tmpPosition);
- tmpPosition += length.length;
-
- tmpPosition += getLengthValue(length);
-
- if (tmpPosition > rawData.length) {
- break;
- } else {
- position = tmpPosition;
- }
- } catch (Exception e) {
- // If parsing fails...
- break;
- }
- }
-
- byte[] validData = new byte[position];
- System.arraycopy(rawData, 0, validData, 0, position);
- return validData;
- }
- }
-
- /**
- * Checks that the length of the array is consistent with the TLV structure.
- *
- * @param data The data to be checked.
- *
- * @return true if the data contains a valid TLV structure, false otherwise.
- */
- public boolean isValidTlvStructure(byte[] data) {
- int position = 0;
- while (position < data.length) {
- try {
- // Parse tag
- byte[] tag = getTagBytes(data, position);
- position += tag.length;
-
- // Parse length
- byte[] length = getLengthBytes(data, position);
- position += length.length;
-
- // Increase position
- position += getLengthValue(length);
- } catch (Exception e) {
- // If parsing fails...
- return false;
- }
- }
-
- return position == data.length;
- }
-}
diff --git a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/service/CardException.java b/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/service/CardException.java
deleted file mode 100644
index 77e4af1..0000000
--- a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/service/CardException.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2011, The Android Open Source Project
- *
- * 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.
- */
-/*
- * Contributed by: Giesecke & Devrient GmbH.
- */
-
-package org.simalliance.openmobileapi.service;
-
-/**
- * Generic exception of the smartcard system.
- */
-public class CardException extends Exception {
-
- private static final long serialVersionUID = -5298933800369298346L;
-
- public CardException(String message) {
- super(message);
- }
-
- public CardException(String message, Throwable cause) {
- super(message, cause);
- }
-
- public CardException(Throwable cause) {
- super(cause);
- }
-
-}
diff --git a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/service/ISmartcardService.aidl b/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/service/ISmartcardService.aidl
deleted file mode 100644
index 85b78c7..0000000
--- a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/service/ISmartcardService.aidl
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2011, The Android Open Source Project
- *
- * 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.
- */
-/*
- * Contributed by: Giesecke & Devrient GmbH.
- */
-
-package org.simalliance.openmobileapi.service;
-
-import org.simalliance.openmobileapi.service.ISmartcardServiceCallback;
-import org.simalliance.openmobileapi.service.ISmartcardServiceReader;
-import org.simalliance.openmobileapi.service.SmartcardError;
-
-/**
- * Smartcard service interface.
- */
-interface ISmartcardService {
-
- /**
- * Returns the friendly names of available smart card readers.
- */
- String[] getReaders(out SmartcardError error);
-
- /**
- * Returns Smartcard Service reader object to the given name.
- */
- ISmartcardServiceReader getReader(String reader, out SmartcardError error);
-
- /**
- * Checks if the application defined by the package name is allowed to receive
- * NFC transaction events for the defined AID.
- */
- boolean[] isNFCEventAllowed(String reader, in byte[] aid, in String[] packageNames, ISmartcardServiceCallback callback, out SmartcardError error);
-}
diff --git a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/service/ISmartcardServiceCallback.aidl b/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/service/ISmartcardServiceCallback.aidl
deleted file mode 100644
index bb896ba..0000000
--- a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/service/ISmartcardServiceCallback.aidl
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2011, The Android Open Source Project
- *
- * 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.
- */
-/*
- * Contributed by: Giesecke & Devrient GmbH.
- */
-
-package org.simalliance.openmobileapi.service;
-
-/**
- * Callback interface used by ISmartcardService to check if clients are alive.
- */
-oneway interface ISmartcardServiceCallback {
-}
diff --git a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/service/ISmartcardServiceChannel.aidl b/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/service/ISmartcardServiceChannel.aidl
deleted file mode 100644
index c1690b5..0000000
--- a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/service/ISmartcardServiceChannel.aidl
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2011, The Android Open Source Project
- *
- * 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.
- */
-/*
- * Contributed by: Giesecke & Devrient GmbH.
- */
-
-package org.simalliance.openmobileapi.service;
-
-import org.simalliance.openmobileapi.service.ISmartcardServiceSession;
-import org.simalliance.openmobileapi.service.SmartcardError;
-
-interface ISmartcardServiceChannel {
-
- /**
- * Closes the specified connection and frees internal resources.
- * A logical channel will be closed.
- */
- void close(out SmartcardError error);
-
- /**
- * Tells if this channel is closed.
- *
- * @return <code>true</code> if the channel is closed, <code>false</code> otherwise.
- */
- boolean isClosed();
-
- /**
- * Returns a boolean telling if this channel is the basic channel.
- *
- * @return <code>true</code> if this channel is a basic channel. <code>false</code> if
- * this channel is a logical channel.
- */
- boolean isBasicChannel();
-
- /**
- * Returns the data as received from the application select command inclusively the status word.
- * The returned byte array contains the data bytes in the following order:
- * [<first data byte>, ..., <last data byte>, <sw1>, <sw2>]
- */
- byte[] getSelectResponse();
-
- /**
- * Get the session that has opened this channel.
- *
- * @return the session object this channel is bound to.
- */
- ISmartcardServiceSession getSession();
-
- /**
- * Transmits the specified command APDU and returns the response APDU.
- * MANAGE channel commands are not supported.
- * Selection of applets is not supported in logical channels.
- */
- byte[] transmit(in byte[] command, out SmartcardError error);
-
- /**
- * Performs a selection of the next Applet on this channel that matches to the partial AID specified
- * in the openBasicChannel(byte[] aid) or openLogicalChannel(byte[] aid) method.
- * This mechanism can be used by a device application to iterate through all Applets
- * matching to the same partial AID.
- * If selectNext() returns true a new Applet was successfully selected on this channel.
- * If no further Applet exists with matches to the partial AID this method returns false
- * and the already selected Applet stays selected.
- *
- * @return <code>true</code> if new Applet was successfully selected.
- <code>false</code> if no further Applet exists which matches the partial AID.
- */
- boolean selectNext(out SmartcardError error);
-}
\ No newline at end of file
diff --git a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/service/ISmartcardServiceReader.aidl b/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/service/ISmartcardServiceReader.aidl
deleted file mode 100644
index 2803cdb..0000000
--- a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/service/ISmartcardServiceReader.aidl
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2011, The Android Open Source Project
- *
- * 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.
- */
-/*
- * Contributed by: Giesecke & Devrient GmbH.
- */
-
-package org.simalliance.openmobileapi.service;
-
-import org.simalliance.openmobileapi.service.ISmartcardServiceSession;
-import org.simalliance.openmobileapi.service.ISmartcardServiceCallback;
-import org.simalliance.openmobileapi.service.SmartcardError;
-
-interface ISmartcardServiceReader {
- /**
- * Return the user-friendly name of this reader.
- * <ul>
- * <li>If this reader is a SIM reader, then its name must start with the "SIM" prefix.</li>
- * <li>If the reader is a SD or micro SD reader, then its name must start with the "SD" prefix</li>
- * <li>If the reader is a embedded SE reader, then its name must start with the "eSE" prefix</li>
- * <ul>
- *
- * @return name of this Reader
- */
- String getName(out SmartcardError error);
- /**
- * Returns true if a card is present in the specified reader.
- * Returns false if a card is not present in the specified reader.
- */
- boolean isSecureElementPresent(out SmartcardError error);
-
-
- /**
- * Connects to a secure element in this reader. <br>
- * This method prepares (initialises) the Secure Element for communication
- * before the Session object is returned (e.g. powers the Secure Element by
- * ICC ON if its not already on). There might be multiple sessions opened at
- * the same time on the same reader. The system ensures the interleaving of
- * APDUs between the respective sessions.
- *
- * @return a Session object to be used to create Channels.
- */
- ISmartcardServiceSession openSession(out SmartcardError error);
- /**
- * Close all the sessions opened on this reader. All the channels opened by
- * all these sessions will be closed.
- */
- void closeSessions(out SmartcardError error);
-}
\ No newline at end of file
diff --git a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/service/ISmartcardServiceSession.aidl b/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/service/ISmartcardServiceSession.aidl
deleted file mode 100644
index 3ecb8c7..0000000
--- a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/service/ISmartcardServiceSession.aidl
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2011, The Android Open Source Project
- *
- * 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.
- */
-/*
- * Contributed by: Giesecke & Devrient GmbH.
- */
-
-package org.simalliance.openmobileapi.service;
-
-import org.simalliance.openmobileapi.service.ISmartcardServiceChannel;
-import org.simalliance.openmobileapi.service.ISmartcardServiceReader;
-import org.simalliance.openmobileapi.service.ISmartcardServiceCallback;
-import org.simalliance.openmobileapi.service.SmartcardError;
-
-interface ISmartcardServiceSession {
-
- /**
- * Get the reader that provides this session.
- *
- * @return The Reader object.
- */
- ISmartcardServiceReader getReader();
-
- /**
- * Returns the ATR of the connected card or null if the ATR is not available.
- */
- byte[] getAtr();
-
- /**
- * Close the connection with the Secure Element. This will close any
- * channels opened by this application with this Secure Element.
- */
- void close(out SmartcardError error);
-
- /**
- * Close any channel opened on this session.
- */
- void closeChannels(out SmartcardError error);
-
-
- /**
- * Tells if this session is closed.
- *
- * @return <code>true</code> if the session is closed, false otherwise.
- */
- boolean isClosed();
-
- /**
- * Opens a connection using the basic channel of the card in the
- * specified reader and returns a channel handle.
- * Logical channels cannot be opened with this connection.
- * Use interface method openLogicalChannel() to open a logical channel.
- */
- ISmartcardServiceChannel openBasicChannel(ISmartcardServiceCallback callback, out SmartcardError error);
-
- /**
- * Opens a connection using the basic channel of the card in the
- * specified reader and returns a channel handle. Selects the specified applet.
- * Logical channels cannot be opened with this connection.
- * Selection of other applets with this connection is not supported.
- * Use interface method openLogicalChannel() to open a logical channel.
- */
- ISmartcardServiceChannel openBasicChannelAid(in byte[] aid, ISmartcardServiceCallback callback, out SmartcardError error);
-
- /**
- * Opens a connection using the next free logical channel of the card in the
- * specified reader. Selects the specified applet.
- * Selection of other applets with this connection is not supported.
- */
- ISmartcardServiceChannel openLogicalChannel(in byte[] aid, ISmartcardServiceCallback callback, out SmartcardError error);
-}
\ No newline at end of file
diff --git a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/service/SmartcardError.aidl b/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/service/SmartcardError.aidl
deleted file mode 100644
index 3aed68b..0000000
--- a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/service/SmartcardError.aidl
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2011, The Android Open Source Project
- *
- * 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.
- */
-/*
- * Contributed by: Giesecke & Devrient GmbH.
- */
-package org.simalliance.openmobileapi.service;
-
-parcelable SmartcardError;
diff --git a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/service/SmartcardError.java b/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/service/SmartcardError.java
deleted file mode 100644
index 10f5c3d..0000000
--- a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/service/SmartcardError.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2011, The Android Open Source Project
- *
- * 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.
- */
-/*
- * Contributed by: Giesecke & Devrient GmbH.
- */
-
-package org.simalliance.openmobileapi.service;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.lang.reflect.Constructor;
-
-/**
- * Smartcard service parameter class used to marshal exception information from
- * the smartcard service to clients.
- */
-public class SmartcardError implements Parcelable {
- private String mClazz;
-
- private String mMessage;
-
- public static final Parcelable.Creator<SmartcardError> CREATOR = new Parcelable.Creator<SmartcardError>() {
- public SmartcardError createFromParcel(Parcel in) {
- return new SmartcardError(in);
- }
-
- public SmartcardError[] newArray(int size) {
- return new SmartcardError[size];
- }
- };
-
- /**
- * Creates an empty smartcard error container.
- */
- public SmartcardError() {
- this.mClazz = "";
- this.mMessage = "";
- }
-
- private SmartcardError(Parcel in) {
- mClazz = in.readString();
- mMessage = in.readString();
- }
-
- /**
- * Creates a smartcard error which creates the specified exception.
- *
- * @param clazz the exception class. <code>null</code> to reset the error
- * information.
- * @param message the exception message.
- */
- public SmartcardError(String clazz, String message) {
- this.mClazz = (clazz == null) ? "" : clazz;
- this.mMessage = (message == null) ? "" : message;
- }
-
- /**
- * Clears the error.
- */
- public void clear() {
- this.mClazz = "";
- this.mMessage = "";
- }
-
- /**
- * Creates the encoded exception. Returns <code>null</code> if empty. If the
- * encoded exception is neither a RuntimeException nor a CardException, it
- * is encapsulated in a RuntimeException.
- *
- * @return the encoded exception or <code>null</code> if empty.
- */
- @SuppressWarnings({ "rawtypes" })
- public Exception createException() {
- try {
- if (mClazz.length() == 0) {
- return null;
- }
- if (mMessage.length() == 0) {
- return (Exception) Class.forName(mClazz).newInstance();
- }
- Constructor constructor = Class.forName(mClazz).getConstructor(String.class);
- return (Exception) constructor.newInstance(mMessage);
- } catch (Exception e) {
- return null;
- }
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void readFromParcel(Parcel in) {
- mClazz = in.readString();
- mMessage = in.readString();
- }
-
- /**
- * Sets the error information.
- *
- * @param clazz the exception class. <code>null</code> to reset the error
- * information.
- * @param message the exception message.
- */
- @SuppressWarnings({ "rawtypes" })
- public void setError(Class clazz, String message) {
- this.mClazz = (clazz == null) ? "" : clazz.getName();
- this.mMessage = (message == null) ? "" : message;
- }
-
- /**
- * Throws the encoded exception. Does not throw an exception if the
- * container is empty. If the encoded exception is neither a
- * RuntimeException nor a CardException, it is encapsulated in a
- * RuntimeException.
- *
- * @throws RuntimeException if the encoded exception is not a CardException.
- * @throws CardException if a CardException is encoded.
- */
- public void throwException() throws CardException {
- Exception e = createException();
- if (e == null) {
- return;
- }
- if (e instanceof CardException) {
- throw (CardException) e;
- }
- if (e instanceof RuntimeException) {
- throw (RuntimeException) e;
- }
- throw new RuntimeException(e);
- }
-
- public void writeToParcel(Parcel out, int flags) {
- out.writeString(mClazz);
- out.writeString(mMessage);
- }
-}
diff --git a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/util/CommandApdu.java b/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/util/CommandApdu.java
deleted file mode 100644
index 110839d..0000000
--- a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/util/CommandApdu.java
+++ /dev/null
@@ -1,399 +0,0 @@
-/*
- * Copyright 2013 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.util;
-
-import java.io.IOException;
-
-import org.simalliance.openmobileapi.Channel;
-import org.simalliance.openmobileapi.internal.ErrorStrings;
-
-/**
- * Class that wraps the functionality for forming and sending APDUs.
- */
-public class CommandApdu {
-
- /**
- * CLA values.
- */
-
- /**
- * Interindustry class value.
- */
- public static final byte CLA_INTERINDUSTRY = (byte) 0x00;
- /**
- * Proprietary class value.
- */
- public static final byte CLA_PROPRIETARY = (byte) 0x80;
-
- /**
- * ISO instruction values.
- */
-
- /**
- * ISO APPEND RECORD instruction value.
- */
- public static final byte INS_APPEND_RECORD = (byte) 0xE2;
- /**
- * ISO CHANGE REFERENCE DATA instruction value.
- */
- public static final byte INS_CHANGE_REF_DATA = (byte) 0x24;
- /**
- * ISO ENABLE VERIFICAITION REQUIREMENT instruction value.
- */
- public static final byte INS_ENABLE_VERIF_REQ = (byte) 0x28;
- /**
- * ISO DISABLE VERIFICATION REQUIREMENT instruction value.
- */
- public static final byte INS_DISABLE_VERIF_REQ = (byte) 0x26;
- /**
- * ISO READ BINARY instruction value (0xB0).
- */
- public static final byte INS_READ_BINARY_B0 = (byte) 0xB0;
- /**
- * ISO READ BINARY instruction value (0xB1).
- */
- public static final byte INS_READ_BINARY_B1 = (byte) 0xB1;
- /**
- * ISO READ RECORD instruction value (0xB2).
- */
- public static final byte INS_READ_RECORD_B2 = (byte) 0xB2;
- /**
- * ISO READ RECORD instruction value (0xB3).
- */
- public static final byte INS_READ_RECORD_B3 = (byte) 0xB3;
- /**
- * ISO RESET RETRY COUNTER instruction value.
- */
- public static final byte INS_RESET_RETRY_CTR = (byte) 0x2C;
- /**
- * ISO SEARCH RECORD instruction value.
- */
- public static final byte INS_SEARCH_RECORD = (byte) 0xA2;
- /**
- * ISO SELECT instruction value.
- */
- public static final byte INS_SELECT = (byte) 0xA4;
- /**
- * ISO UPDATE BINARY instruction value (0xD6).
- */
- public static final byte INS_UPDATE_BINARY_D6 = (byte) 0xD6;
- /**
- * ISO UPDATE RECORD instruction value (0xDC).
- */
- public static final byte INS_UPDATE_RECORD_DC = (byte) 0xDC;
- /**
- * ISO VERIFY instruction value (0x20).
- */
- public static final byte INS_VERIFY_20 = (byte) 0x20;
- /**
- * ISO VERIFY instruction value (0x21).
- */
- public static final byte INS_VERIFY_21 = (byte) 0x21;
- /**
- * ISO WRITE BINARY instruction value (0xD0).
- */
- public static final byte INS_WRITE_BINARY_D0 = (byte) 0xD0;
- /**
- * ISO WRITE BINARY instruction value (0xD1).
- */
- public static final byte INS_WRITE_BINARY_D1 = (byte) 0xD1;
- /**
- * ISO WRITE RECORD instruction value.
- */
- public static final byte INS_WRITE_RECORD = (byte) 0xD2;
-
- /**
- * Secure Storage INS values.
- */
-
- /**
- * SIM Alliance Secure Storage Applet instruction values.
- */
-
- /**
- * SIM Alliance Secure Storage PING SS APPLET instruction value.
- */
- public static final byte INS_PING_SS_APPLET = (byte) 0xAA;
- /**
- * SIM Alliance Secure Storage CREATE SS ENTRY instruction value.
- */
- public static final byte INS_CREATE_SS_ENTRY = (byte) 0xE0;
- /**
- * SIM Alliance Secure Storage DELETE ALL SS ENTRIES instruction value.
- */
- public static final byte INS_DELETE_ALL_SS_ENTRIES = (byte) 0xE5;
- /**
- * SIM Alliance Secure Storage DELETE SS ENTRY instruction value.
- */
- public static final byte INS_DELETE_SS_ENTRY = (byte) 0xE4;
- /**
- * SIM Alliance Secure Storage GET SS ENTRY DATA instruction value.
- */
- public static final byte INS_GET_SS_ENTRY_DATA = (byte) 0xCA;
- /**
- * SIM Alliance Secure Storage GET SS ENTRY ID instruction value.
- */
- public static final byte INS_GET_SS_ENTRY_ID = (byte) 0xB2;
- /**
- * SIM Alliance Secure Storage SELECT SS ENTRY instruction value.
- */
- public static final byte INS_SELECT_SS_ENTRY = (byte) 0xA5;
- /**
- * SIM Alliance Secure Storage PUT SS ENTRY DATA instruction value.
- */
- public static final byte INS_PUT_SS_ENTRY_DATA = (byte) 0xDA;
-
- /**
- * The maximum value of the data field of an APDU.
- * TODO: Extended data length APDUs not supported.
- */
- public static final int MAX_DATA_LENGTH = 255;
-
- /**
- * The channel over which the APDU will be sent.
- */
- private Channel mChannel;
-
- /**
- * The value of the CLA field.
- */
- private byte mCla;
-
- /**
- * The value of the INS field.
- */
- private byte mIns;
-
- /**
- * The value of the P1 field.
- */
- private byte mP1;
-
- /**
- * The value of the P2 field.
- */
- private byte mP2;
- /**
- * The value of the Data field.
- */
- private byte[] mData;
- /**
- * The value of the Le field.
- */
- private int mLe;
-
- /**
- * Indicate presence of CLA field in the APDU.
- */
- private boolean isClaPresent;
-
- /**
- * Indicate presence of INS field in the APDU.
- */
- private boolean isInsPresent;
-
- /**
- * Indicate presence of P1 field in the APDU.
- */
- private boolean isP1Present;
-
- /**
- * Indicate presence of P2 field in the APDU.
- */
- private boolean isP2Present;
-
- /**
- * Indicate presence of Data field in the APDU.
- */
- private boolean isDataPresent;
-
- /**
- * Indicate presence of Le field in the APDU.
- */
- private boolean isLePresent;
-
- /**
- * Initializes a new instance of the class.
- *
- * @param channel The Channel to be used.
- */
- public CommandApdu(Channel channel) {
- mChannel = channel;
- isClaPresent = false;
- isInsPresent = false;
- isP1Present = false;
- isP2Present = false;
- isDataPresent = false;
- isLePresent = false;
- }
-
- /**
- * Decides whether present fields will form a valid APDU.
- *
- * @return true if an APDU can be formed, false otherwise.
- */
- private boolean canApduBeFormed() {
- return isClaPresent && isInsPresent && isP1Present && isP2Present;
- }
-
- /**
- * Forms a byte array that represents an APDU with the already set fields in
- * the class.
- *
- * @return A byte array representing an APDU with the fields of this APDU
- * instance. null if the field combination is invalid.
- *
- * @throws IllegalArgumentException if the APDU has an invalid format.
- */
- public byte[] formApdu() throws IllegalArgumentException {
- if (canApduBeFormed()) {
- byte[] apdu;
- if (!isDataPresent && !isLePresent) {
- apdu = new byte[4];
- apdu[0] = mCla;
- apdu[1] = mIns;
- apdu[2] = mP1;
- apdu[3] = mP2;
- } else if (!isDataPresent && isLePresent) {
- apdu = new byte[5];
- apdu[0] = mCla;
- apdu[1] = mIns;
- apdu[2] = mP1;
- apdu[3] = mP2;
- apdu[4] = (byte) mLe;
- } else if (isDataPresent && !isLePresent) {
- apdu = new byte[5 + mData.length];
- apdu[0] = mCla;
- apdu[1] = mIns;
- apdu[2] = mP1;
- apdu[3] = mP2;
- apdu[4] = (byte) mData.length;
- System.arraycopy(mData, 0, apdu, 5, mData.length);
- } else {
- apdu = new byte[6 + mData.length];
- apdu[0] = mCla;
- apdu[1] = mIns;
- apdu[2] = mP1;
- apdu[3] = mP2;
- apdu[4] = (byte) mData.length;
- System.arraycopy(mData, 0, apdu, 5, mData.length);
- apdu[apdu.length - 1] = (byte) mLe;
- }
-
- return apdu;
- } else {
- throw new IllegalArgumentException("Invalid APDU format.");
- }
- }
-
- /**
- * Sets the CLA field.
- *
- * @param cla The value to be set.
- */
- public void setCla(byte cla) {
- mCla = cla;
- isClaPresent = true;
- }
-
- /**
- * Sets the INS field.
- *
- * @param ins The value to be set.
- */
- public void setIns(byte ins) {
- mIns = ins;
- isInsPresent = true;
- }
-
- /**
- * Sets the P1 field.
- *
- * @param p1 The value to be set.
- */
- public void setP1(byte p1) {
- mP1 = p1;
- isP1Present = true;
- }
-
- /**
- * Sets the P2 field.
- *
- * @param p2 The value to be set.
- */
- public void setP2(byte p2) {
- mP2 = p2;
- isP2Present = true;
- }
-
- /**
- * Sets the Data field.
- *
- * @param data The value to be set. Lc is automatically generated
- *
- * @throws IllegalArgumentException if the data length is invalid or data is
- * null.
- */
- public void setData(byte[] data) throws IllegalArgumentException {
- if (data == null) {
- throw new IllegalArgumentException(ErrorStrings.paramNull("data"));
- }
- if (data.length > MAX_DATA_LENGTH) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidArrayLength("data"));
- }
-
- mData = data;
- isDataPresent = true;
- }
-
- /**
- * Sets the Le field.
- *
- * @param le The value to be set.
- *
- * @throws IllegalArgumentException if the Le value is invalid.
- */
- public void setLE(int le) throws IllegalArgumentException {
- if ((le > CommandApdu.MAX_DATA_LENGTH) || (le < 0)) {
- throw new IllegalArgumentException(
- ErrorStrings.paramInvalidValue("le"));
- }
-
- mLe = le;
- isLePresent = true;
- }
-
- /**
- * Sends the APDU over the specified channel.
- *
- * @return The SmartCard response.
- *
- * @throws IllegalStateException if the channel is closed.
- * @throws IllegalArgumentException if the APDU has an invalid format.
- * @throws IOException Lower-level API exception.
- */
- public byte[] sendApdu() throws IllegalStateException, IOException,
- IllegalArgumentException {
-
- if (mChannel.isClosed()) {
- throw new IllegalStateException(ErrorStrings.CHANNEL_CLOSED);
- } else {
- return mChannel.transmit(formApdu());
- }
- }
-}
diff --git a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/util/ResponseApdu.java b/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/util/ResponseApdu.java
deleted file mode 100644
index 08bf6dd..0000000
--- a/smart-card-service/openmobileapi/src/org/simalliance/openmobileapi/util/ResponseApdu.java
+++ /dev/null
@@ -1,397 +0,0 @@
-/*
- * Copyright 2013 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.util;
-
-import org.simalliance.openmobileapi.internal.ByteArrayConverter;
-import org.simalliance.openmobileapi.internal.ErrorStrings;
-
-/**
- * Class that wraps the functionality for dealing with APDU responses.
- */
-public final class ResponseApdu {
-
- /**
- * Override default constructor to prevent instantiation.
- */
- private ResponseApdu() {
- }
-
- // 9000 - Normal processing - No further qualification.
- /**
- * No further qualification.
- */
- public static final int SW_NO_FURTHER_QUALIFICATION = 0x9000;
-
- // 61XX - Normal processing - SW2 encodes the number of data bytes still
- // available.
- /**
- * SW2 encodes the number of data bytes still available (minimum value).
- */
- public static final int SW_NORMAL_PROCESSING_MIN = 0x6100;
- /**
- * SW2 encodes the number of data bytes still available (maximum value).
- */
- public static final int SW_NORMAL_PROCESSING_MAX = 0x61FF;
-
- // 62XX - Warning processing - State of non-volatile memory is unchanged
- // (further qualification in SW2).
- /**
- * No information given.
- */
- public static final int SW_62_NO_INFO = 0x6200;
- /**
- * Triggering by the card (minimum value).
- */
- public static final int SW_62_TRIGGERING_CARD_MIN = 0x6202;
- /**
- * Triggering by the card (maximum value).
- */
- public static final int SW_62_TRIGGERING_CARD_MAX = 0x6280;
- /**
- * Part of returned data may be corrupted.
- */
- public static final int SW_DATA_CORRUPTED = 0x6281;
- /**
- * End of file or record reached before reading Ne bytes.
- */
- public static final int SW_UNEXPECTED_EOF = 0x6282;
- /**
- * Selected file deactivated.
- */
- public static final int SW_FILE_DEACTIVATED = 0x6283;
- /**
- * File control information not formatted according to 5.3.3.
- */
- public static final int SW_WRONG_FILE_CONTROL_FORMAT = 0x6284;
- /**
- * Selected file in termination state.
- */
- public static final int SW_FILE_STATE_TERMINATION = 0x6285;
- /**
- * No input data available from a sensor on the card.
- */
- public static final int SW_NO_INPUT_DATA_AVAILABLE = 0x6286;
-
- // 63XX - Warning processing - State of non-volatile memory has
- // changed (further qualification in SW2).
- /**
- * No information given.
- */
- public static final int SW_63_NO_INFO = 0x6300;
- /**
- * File filled up by the last write.
- */
- public static final int SW_FILE_FILLED_UP = 0x6381;
- /**
- * Counter from 0 to 15 encoded by X (exact meaning depending on the
- * command). Minimum value.
- */
- public static final int SW_CTR_MIN = 0x63C0;
- /**
- * Counter from 0 to 15 encoded by X (exact meaning depending on the
- * command). Maximum value.
- */
- public static final int SW_CTR_MAX = 0x63CF;
-
- // 64XX - Execution error - State of non-volatile memory is
- // unchanged (further qualification in SW2)
- /**
- * Execution error.
- */
- public static final int SW_EXEC_ERROR = 0x6400;
- /**
- * Immediate response required by the card.
- */
- public static final int SW_IMMEDIATE_RESPONSE_REQUIRED = 0x6401;
- /**
- * Triggering by the card (minimum value).
- */
- public static final int SW_64_TRIGGERING_CARD_MIN = 0x6402;
- /**
- * Triggering by the card (maximum value).
- */
- public static final int SW_64_TRIGGERING_CARD_MAX = 0x6480;
-
- // 65XX - Execution error - State of non-volatile memory has changed
- // (further qualification in SW2)
- /**
- * No information given.
- */
- public static final int SW_65_NO_INFO = 0x6500;
- /**
- * Memory failure.
- */
- public static final int SW_MEMORY_FAILURE = 0x6581;
-
- // 66XX - Execution error - Security-related issues
- /**
- * Security issue (minimum value).
- */
- public static final int SW_SECURITY_ISSUE_MIN = 0x6600;
- /**
- * Security issue (maximum value).
- */
- public static final int SW_SECURITY_ISSUE_MAX = 0x66FF;
-
- // 6700 - Checking error - Wrong length, no further indication
- /**
- * Wrong length, no further indication.
- */
- public static final int SW_WRONG_LENGTH = 0x6700;
-
- // 68XX - Checking error - Functions in CLA not supported
- // (further qualification in SW2)
- /**
- * No information given.
- */
- public static final int SW_68_NO_INFO = 0x6800;
- /**
- * Logical channel not supported.
- */
- public static final int SW_LOGICAL_CHANNEL_NOT_SUPPORTED = 0x6881;
- /**
- * Secure messaging not supported.
- */
- public static final int SW_SECURE_MESSAGING_NOT_SUPPORTED = 0x6882;
- /**
- * Last command of the chain expected.
- */
- public static final int SW_LAST_COMMAND_EXPECTED = 0x6883;
- /**
- * Command chaining not supported.
- */
- public static final int SW_COMMAND_CHAINING_NOT_SUPPORTED = 0x6884;
-
- // 69XX - Checking error - Command not allowed (further
- // qualification in SW2).
- /**
- * No information given.
- */
- public static final int SW_69_NO_INFO = 0x6900;
- /**
- * Command incompatible with file structure.
- */
- public static final int SW_COMMAND_INCOMPATIBLE = 0x6981;
- /**
- * Security status not satisfied.
- */
- public static final int SW_SECURITY_STATUS_NOT_SATISFIED = 0x6982;
- /**
- * Authentication method blocked.
- */
- public static final int SW_AUTH_METHOD_BLOCKED = 0x6983;
- /**
- * Reference data not usable.
- */
- public static final int SW_REF_DATA_NOT_USABLE = 0x6984;
- /**
- * Conditions of use not satisfied.
- */
- public static final int SW_CONDITIONS_NOT_SATISFIED = 0x6985;
- /**
- * Command not allowed (no current EF).
- */
- public static final int SW_COMMAND_NOT_ALLOWED = 0x6986;
- /**
- * Expected secure messaging data objects missing.
- */
- public static final int SW_SM_OBJECT_MISSING = 0x6987;
- /**
- * Incorrect secure messaging data objects.
- */
- public static final int SW_SM_INCORRECT_OBJECT = 0x6988;
-
- // 6AXX - Checking error - Wrong parameters P1-P2 (further
- // qualification in SW2)
- /**
- * No information given.
- */
- public static final int SW_6A_NO_INFO = 0x6A00;
- /**
- * Incorrect parameters in the command data field.
- */
- public static final int SW_WRONG_DATA = 0x6A80;
- /**
- * Function not supported.
- */
- public static final int SW_FUNC_NOT_SUPPORTED = 0x6A81;
- /**
- * File or application not found.
- */
- public static final int SW_FILE_OR_APP_NOT_FOUND = 0x6A82;
- /**
- * Record not found.
- */
- public static final int SW_RECORD_NOT_FOUND = 0x6A83;
- /**
- * Not enough memory space in the file.
- */
- public static final int SW_NOT_ENOUGH_MEMORY = 0x6A84;
- /**
- * Nc inconsistent with TLV structure.
- */
- public static final int SW_WRONG_NC_TLV = 0x6A85;
- /**
- * Incorrect parameters P1-P2.
- */
- public static final int SW_INCORRECT_P1P2 = 0x6A86;
- /**
- * Nc inconsistent with parameters P1-P2.
- */
- public static final int SW_WRONG_NC_P1P2 = 0x6A87;
- /**
- * Referenced data or reference data not found (exact meaning depending on
- * the command).
- */
- public static final int SW_REF_NOT_FOUND = 0x6A88;
- /**
- * File already exists.
- */
- public static final int SW_FILE_ALREADY_EXISTS = 0x6A89;
- /**
- * DF name already exists.
- */
- public static final int SW_DF_NAME_ALREADY_EXISTS = 0x6A8A;
-
- // 6B00 - Checking error - Wrong parameters P1-P2
- /**
- * Wrong parameters P1-P2.
- */
- public static final int SW_WRONG_PARAMETERS_P1P2 = 0x6B00;
-
- // 6CXX - Checking error - Wrong Le field; SW2 encodes the exact
- // number of available data bytes.
- /**
- * Wrong Le field; SW2 encodes the exact number of available data bytes
- * (minimum value).
- */
- public static final int SW_WRONG_LE_MIN = 0x6C00;
- /**
- * Wrong Le field; SW2 encodes the exact number of available data bytes
- * (maximum value).
- */
- public static final int SW_WRONG_LE_MAX = 0x6CFF;
-
- // 6D00 - Checking error - Instruction code not supported or
- // invalid.
- /**
- * Instruction code not supported or invalid.
- */
- public static final int SW_INS_NOT_SUPPORTED = 0x6D00;
-
- // 6E00 - Checking error - Class not supported.
- /**
- * Class not supported.
- */
- public static final int SW_CLA_NOT_SUPPORTED = 0x6E00;
-
- // 6F00 - Checking error - No precise diagnostic
- /**
- * No precise diagnostic.
- */
- public static final int SW_NO_PRECISE_DIAGNOSTIC = 0x6F00;
-
- /**
- * SW for Secure Storage.
- */
-
- /**
- * Incorrect values in the command data (if the defined title
- * does not exist).
- */
- public static final int SES_SW_INCORRECT_COMMAND_DATA = 0x6A80;
-
- /**
- * Security status not satisfied (if PIN verified state is not set).
- */
- public static final int SES_SW_SECURITY_STATUS_NOT_SATISFIED = 0x6A82;
-
- /**
- * Invalid instruction.
- */
- public static final int SES_SW_INVALID_INSTRUCTION = 0x6D00;
-
- /**
- * Memory failure (if the creation of the entry fails due to memory issues).
- */
- public static final int SES_SW_MEMORY_FAILURE = 0x6581;
-
- /**
- * Not enough memory space (if not enough memory resources are available).
- */
- public static final int SES_SW_NOT_ENOUGH_MEMORY = 0x6A84;
- /**
- * Referenced data not found (if no SeS entry is currently selected).
- */
- public static final int SES_SW_REF_NOT_FOUND = 0x6A88;
-
- /**
- * Returns the data of a response APDU.
- *
- * @param responseApdu The APDU from which the data is wanted.
- *
- * @return The data of the specified response APDU.
- *
- * @throws IllegalArgumentException if the response does not have SW.
- */
- public static byte[] getResponseData(byte[] responseApdu)
- throws IllegalArgumentException {
- if (responseApdu.length < 2) {
- throw new IllegalArgumentException(ErrorStrings.APDU_BAD_RESPONSE);
- }
-
- byte[] responseData = new byte[responseApdu.length - 2];
- System.arraycopy(responseApdu, 0, responseData, 0,
- responseApdu.length - 2);
- return responseData;
- }
-
- /**
- * Returns the SW of a response APDU.
- *
- * @param responseApdu The APDU from which the SW is wanted.
- *
- * @return The SW of the specified response APDU.
- *
- * @throws IllegalArgumentException if the response does not have SW.
- */
- public static byte[] getResponseStatusWordBytes(byte[] responseApdu)
- throws IllegalArgumentException {
- if (responseApdu.length < 2) {
- throw new IllegalArgumentException(ErrorStrings.APDU_BAD_RESPONSE);
- }
-
- byte[] statusWord = new byte[2];
- System.arraycopy(responseApdu, responseApdu.length - 2, statusWord, 0,
- 2);
- return statusWord;
- }
-
- /**
- * Returns the integer value of the StatusWord of a response APDU.
- *
- * @param responseApdu The APDU from which the SW value is wanted.
- *
- * @return The value of the SW of the specified response APDU.
- *
- * @throws IllegalArgumentException if the response does not have SW.
- */
- public static int getResponseStatusWordValue(byte[] responseApdu)
- throws IllegalArgumentException {
- return ByteArrayConverter.byteArrayToInt(getResponseStatusWordBytes(responseApdu));
- }
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/AddonTerminal.java b/smart-card-service/src/org/simalliance/openmobileapi/service/AddonTerminal.java
deleted file mode 100644
index 16f3520..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/AddonTerminal.java
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- * Copyright (C) 2011, The Android Open Source Project
- *
- * 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.
- */
-/*
- * Contributed by: Giesecke & Devrient GmbH.
- */
-
-package org.simalliance.openmobileapi.service;
-
-import android.content.Context;
-import android.content.pm.PackageInfo;
-
-import java.lang.reflect.Method;
-import java.util.LinkedList;
-import java.util.List;
-
-public class AddonTerminal extends Terminal {
-
- private Object mInstance = null;
-
- private Method mIsCardPresent = null;
-
- private Method mInternalConnect = null;
-
- private Method mInternalDisconnect = null;
-
- private Method mInternalTransmit = null;
-
- private Method mInternalOpenLogicalChannel = null;
-
- private Method mInternalOpenLogicalChannelAID = null;
-
- private Method mInternalCloseLogicalChannel = null;
-
- private Method mGetType = null;
-
- private Method mGetAtr = null;
-
- private Method mGetSelectResponse = null;
-
- public static String[] getPackageNames(Context context) {
- List<String> packageNameList = new LinkedList<String>();
- List<PackageInfo> pis = context.getPackageManager()
- .getInstalledPackages(0);
- for (PackageInfo p : pis) {
- if (p.packageName.startsWith(
- "org.simalliance.openmobileapi.service.terminals.")
- || p.packageName.startsWith(
- "org.simalliance.openmobileapi.cts")) {
- packageNameList.add(p.packageName);
- }
- }
-
- String[] rstrings = new String[packageNameList.size()];
- packageNameList.toArray(rstrings);
- return rstrings;
- }
-
- public AddonTerminal(
- Context context,
- String terminalType,
- String packageName,
- String className) {
- super(terminalType, context);
-
- try {
- Context ctx = context.createPackageContext(packageName,
- Context.CONTEXT_IGNORE_SECURITY
- | Context.CONTEXT_INCLUDE_CODE);
- ClassLoader cl = ctx.getClassLoader();
- Class<?> cls = cl.loadClass(className);
- mInstance = cls.getConstructor(new Class[] {Context.class})
- .newInstance(new Object[] {context});
- if (mInstance != null) {
- mGetAtr = mInstance.getClass().getDeclaredMethod(
- "getAtr", (Class<?>[]) null);
- mGetType = mInstance.getClass().getDeclaredMethod(
- "getType", (Class<?>[]) null);
- mIsCardPresent = mInstance.getClass().getDeclaredMethod(
- "isCardPresent", (Class<?>[]) null);
- mInternalConnect = mInstance.getClass().getDeclaredMethod(
- "internalConnect", (Class<?>[]) null);
- mInternalDisconnect = mInstance.getClass().getDeclaredMethod(
- "internalDisconnect", (Class<?>[]) null);
- mInternalTransmit = mInstance.getClass().getDeclaredMethod(
- "internalTransmit", new Class[] {byte[].class});
- mInternalOpenLogicalChannel = mInstance.getClass()
- .getDeclaredMethod(
- "internalOpenLogicalChannel", (Class<?>[]) null);
- mInternalOpenLogicalChannelAID = mInstance.getClass()
- .getDeclaredMethod(
- "internalOpenLogicalChannel",
- new Class[] {byte[].class});
- mInternalCloseLogicalChannel = mInstance.getClass()
- .getDeclaredMethod(
- "internalCloseLogicalChannel",
- new Class[] {int.class});
- mGetSelectResponse = mInstance.getClass().getDeclaredMethod(
- "getSelectResponse", (Class<?>[]) null);
- }
- } catch (Exception e) {
- throw new IllegalStateException("plugin internal error: " + e);
- }
- }
-
- /**
- * Returns the ATR of the connected card or null if the ATR is not
- * available.
- *
- * @return the ATR of the connected card or null if the ATR is not
- * available.
- */
- public byte[] getAtr() {
- if (mGetAtr == null) {
- throw new IllegalStateException(
- "plugin error: Function String getAtr() not found");
- }
- try {
- byte[] resp = (byte[]) mGetAtr.invoke(mInstance, (Object[]) null);
- return resp;
- } catch (Exception e) {
- throw new IllegalStateException(
- "plugin internal error: getAtr() execution: "
- + e.getCause());
- }
- }
-
- public String getType() {
- if (mGetType == null) {
- throw new IllegalStateException(
- "plugin error: Function String getType() not found");
- }
- try {
- String s = (String) mGetType.invoke(mInstance, (Object[]) null);
- return s;
- } catch (Exception e) {
- throw new IllegalStateException(
- "plugin internal error: getName() execution: "
- + e.getCause());
- }
- }
-
- public boolean isCardPresent() throws CardException {
- if (mIsCardPresent == null) {
- throw new IllegalStateException(
- "plugin error: Function String isCardPresent() not found");
- }
- try {
- Boolean v = (Boolean) mIsCardPresent.invoke(mInstance,
- (Object[]) null);
- return v.booleanValue();
- } catch (Exception e) {
- throw new CardException(
- "plugin internal error: isCardPresent() execution: "
- + e.getCause());
- }
- }
-
- protected void internalConnect() throws CardException {
- if (mInternalConnect == null) {
- throw new IllegalStateException(
- "plugin error: Function String internalConnect() not found");
- }
- try {
- mInternalConnect.invoke(mInstance, (Object[]) null);
- mIsConnected = true;
- } catch (Exception e) {
- throw new CardException(
- "plugin internal error: internalConnect() execution: "
- + e.getCause());
- }
- }
-
- protected void internalDisconnect() throws CardException {
- if (mInternalDisconnect == null) {
- throw new IllegalStateException(
- "plugin error: Function String internalDisconnect() not found");
- }
- try {
- mInternalDisconnect.invoke(mInstance, (Object[]) null);
- mIsConnected = false;
- } catch (Exception e) {
- throw new CardException(
- "plugin internal error: internalDisconnect() execution");
- }
- }
-
- protected byte[] internalTransmit(byte[] command) throws CardException {
- if (mInternalTransmit == null) {
- throw new IllegalStateException(
- "plugin error: Function String internalTransmit() not found");
- }
- try {
- byte[] resp = (byte[]) mInternalTransmit.invoke(mInstance,
- new Object[] { command });
- return resp;
- } catch (Exception e) {
- throw new CardException(
- "plugin internal error: internalTransmit() execution: "
- + e.getCause());
- }
- }
-
- protected int internalOpenLogicalChannel() throws Exception {
- mSelectResponse = null;
- if (mInternalOpenLogicalChannel == null) {
- throw new IllegalStateException(
- "plugin error: Function String internalOpenLogicalChannel()"
- + " not found");
- }
- try {
- Integer channel = (Integer) mInternalOpenLogicalChannel.invoke(
- mInstance, (Object[]) null);
- return channel.intValue();
- } catch (Exception e) {
- throw (Exception) e.getCause();
- }
- }
-
- protected int internalOpenLogicalChannel(byte[] aid) throws Exception {
- mSelectResponse = null;
- if (mInternalOpenLogicalChannelAID == null) {
- throw new IllegalStateException(
- "plugin error: Function internalOpenLogicalChannelAID() not"
- + " found");
- }
- try {
- Integer channel = (Integer) mInternalOpenLogicalChannelAID.invoke(
- mInstance, new Object[] {aid});
- mSelectResponse = (byte[]) mGetSelectResponse.invoke(
- mInstance, (Object[]) null);
- return channel.intValue();
- } catch (Exception e) {
- throw (Exception) e.getCause();
- }
- }
-
- protected void internalCloseLogicalChannel(int channelNumber)
- throws CardException {
- if (mInternalCloseLogicalChannel == null) {
- throw new IllegalStateException("plugin error: Function "
- + "internalCloseLogicalChannel not found");
- }
- try {
- mInternalCloseLogicalChannel.invoke(mInstance,
- new Object[] {channelNumber});
- } catch (Exception e) {
- throw new CardException(
- "plugin internal error: internalOpenLogicalChannel()"
- + " execution: " + e.getCause());
- }
- }
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/CardException.java b/smart-card-service/src/org/simalliance/openmobileapi/service/CardException.java
deleted file mode 100644
index 77e4af1..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/CardException.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2011, The Android Open Source Project
- *
- * 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.
- */
-/*
- * Contributed by: Giesecke & Devrient GmbH.
- */
-
-package org.simalliance.openmobileapi.service;
-
-/**
- * Generic exception of the smartcard system.
- */
-public class CardException extends Exception {
-
- private static final long serialVersionUID = -5298933800369298346L;
-
- public CardException(String message) {
- super(message);
- }
-
- public CardException(String message, Throwable cause) {
- super(message, cause);
- }
-
- public CardException(Throwable cause) {
- super(cause);
- }
-
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/Channel.java b/smart-card-service/src/org/simalliance/openmobileapi/service/Channel.java
deleted file mode 100644
index 77ab377..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/Channel.java
+++ /dev/null
@@ -1,471 +0,0 @@
-/*
- * Copyright (C) 2011, The Android Open Source Project
- *
- * 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.
- */
-/*
- * Contributed by: Giesecke & Devrient GmbH.
- */
-
-package org.simalliance.openmobileapi.service;
-
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.RemoteException;
-import org.simalliance.openmobileapi.service.ISmartcardServiceCallback;
-import org.simalliance.openmobileapi.service.SmartcardService.SmartcardServiceSession;
-
-import android.util.Log;
-
-
-import java.security.AccessControlException;
-import java.util.NoSuchElementException;
-
-import org.simalliance.openmobileapi.service.security.AccessControlEnforcer;
-import org.simalliance.openmobileapi.service.security.ChannelAccess;
-
-
-
-/**
- * Smartcard service base class for channel resources.
- */
-class Channel implements IChannel, IBinder.DeathRecipient {
-
- protected final int mChannelNumber;
-
- protected boolean mIsClosed;
-
- protected long mHandle;
-
- protected ISmartcardServiceSession mSession;
- protected Terminal mTerminal;
-
- protected byte[] mSelectResponse;
-
- protected final IBinder mBinder;
-
- protected ChannelAccess mChannelAccess = null;
- protected int mCallingPid = 0;
-
- protected ISmartcardServiceCallback mCallback;
-
- protected boolean mHasSelectedAid = false;
- protected byte[] mAid = null;
-
- Channel(SmartcardServiceSession session,
- Terminal terminal,
- int channelNumber,
- ISmartcardServiceCallback callback) {
- this.mChannelNumber = channelNumber;
- this.mSession = session;
- this.mTerminal = terminal;
- this.mCallback = callback;
- this.mBinder = callback.asBinder();
- this.mSelectResponse = terminal.getSelectResponse();
- this.mIsClosed = false;
- try {
- mBinder.linkToDeath(this, 0);
- } catch (RemoteException e) {
- Log.e(SmartcardService._TAG, "Failed to register client callback");
- }
- }
-
- public void binderDied() {
- // Close this channel if the client died.
- try {
- Log.e(SmartcardService._TAG, Thread.currentThread().getName()
- + " Client " + mBinder.toString() + " died");
- close();
- } catch (Exception ignore) {
- }
- }
-
- public synchronized void close() throws CardException {
-
- Terminal terminal = getTerminal();
- if (terminal == null) {
- throw new IllegalStateException(
- "channel is not attached to a terminal");
- }
-
- if (isBasicChannel() && hasSelectedAid()) {
- try {
- Log.v(SmartcardService._TAG, "Close basic channel - Select with out AID ...");
- terminal.select();
- } catch (NoSuchElementException exp) {
- // Selection of the default application fails
- try {
- Log.v(SmartcardService._TAG,
- "Close basic channel - Exception : "
- + exp.getLocalizedMessage());
- AccessControlEnforcer access =
- terminal.getAccessControlEnforcer();
- if (access != null) {
- terminal.select(AccessControlEnforcer
- .getDefaultAccessControlAid());
- }
- } catch (NoSuchElementException exp2) {
- // Access Control Applet not available => Don't care
- }
- }
- }
-
- try {
- terminal.closeChannel(this);
- this.mIsClosed = true;
- } finally {
- mBinder.unlinkToDeath(this, 0);
- }
- }
-
- public int getChannelNumber() {
- return mChannelNumber;
- }
-
- /**
- * Returns if this channel is a basic channel.
- *
- * @return true if this channel is a basic channel
- */
- public boolean isBasicChannel() {
- return (mChannelNumber == 0) ? true : false;
- }
-
- public ISmartcardServiceCallback getCallback() {
- return mCallback;
- }
-
- /**
- * Returns the handle assigned to this channel.
- *
- * @return the handle assigned to this channel.
- */
- long getHandle() {
- return mHandle;
- }
-
- /**
- * Returns the associated terminal.
- *
- * @return the associated terminal.
- */
- public Terminal getTerminal() {
- return mTerminal;
- }
-
- /**
- * Assigns the channel handle.
- *
- * @param handle the channel handle to be assigned.
- */
- void setHandle(long handle) {
- this.mHandle = handle;
- }
-
- public byte[] transmit(byte[] command) throws CardException {
-
- if (mChannelAccess == null) {
- throw new AccessControlException(" Channel access not set.");
- }
- if (mChannelAccess.getCallingPid() != mCallingPid) {
- throw new AccessControlException(" Wrong Caller PID. ");
- }
- if (command.length < 4) {
- throw new IllegalArgumentException(
- " command must not be smaller than 4 bytes");
- }
- if (((command[0] & (byte) 0x80) == 0)
- && ((byte) (command[0] & (byte) 0x60) != (byte) 0x20)) {
- // ISO command
- if (command[1] == (byte) 0x70) {
- throw new SecurityException(
- "MANAGE CHANNEL command not allowed");
- }
- if ((command[1] == (byte) 0xA4) && (command[2] == (byte) 0x04)) {
- throw new SecurityException(
- "SELECT by DF name command not allowed");
- }
-
- } else {
- // GlobalPlatform command
- }
- checkCommand(command);
-
- // set channel number bits
- command[0] = setChannelToClassByte(command[0], mChannelNumber);
-
- byte[] rsp = getTerminal().transmit(command, 2, 0, 0, null);
-
- return rsp;
- }
-
- public boolean selectNext() throws CardException {
-
- if (mChannelAccess == null) {
- throw new AccessControlException(" Channel access not set.");
- }
- if (mChannelAccess.getCallingPid() != mCallingPid) {
- throw new AccessControlException(" Wrong Caller PID. ");
- }
-
- if (mAid == null || mAid.length == 0) {
- throw new CardException(" no aid given");
- }
-
- mSelectResponse = null;
- byte[] selectCommand = new byte[5 + mAid.length];
- selectCommand[0] = 0x00;
- selectCommand[1] = (byte) 0xA4;
- selectCommand[2] = 0x04;
- selectCommand[3] = 0x02; // next occurrence
- selectCommand[4] = (byte) mAid.length;
- System.arraycopy(mAid, 0, selectCommand, 5, mAid.length);
-
- // set channel number bits
- selectCommand[0] = setChannelToClassByte(
- selectCommand[0], mChannelNumber);
-
- mSelectResponse = getTerminal().transmit(
- selectCommand, 2, 0, 0, "SELECT NEXT");
-
- int sw1 = mSelectResponse[mSelectResponse.length - 2] & 0xFF;
- int sw2 = mSelectResponse[mSelectResponse.length - 1] & 0xFF;
- int sw = (sw1 << 8) | sw2;
- if (((sw & 0xF000) == 0x9000) || ((sw & 0xFF00) == 0x6200)
- || ((sw & 0xFF00) == 0x6300)){
- return true;
- } else if (sw == 0x6A82) {
- mSelectResponse = null;
- return false;
- } else {
- throw new UnsupportedOperationException(" unsupported operation");
- }
- }
-
- /**
- * Returns a copy of the given CLA byte where the channel number bits are
- * set as specified by the given channel number See GlobalPlatform Card
- * Specification 2.2.0.7: 11.1.4 Class Byte Coding.
- *
- * @param cla the CLA byte. Won't be modified
- * @param channelNumber within [0..3] (for first interindustry class byte
- * coding) or [4..19] (for further interindustry class byte
- * coding)
- * @return the CLA byte with set channel number bits. The seventh bit
- * indicating the used coding (first/further interindustry class
- * byte coding) might be modified
- */
- private byte setChannelToClassByte(byte cla, int channelNumber) {
- if (channelNumber < 4) {
- // b7 = 0 indicates the first interindustry class byte coding
- cla = (byte) ((cla & 0xBC) | channelNumber);
- } else if (channelNumber < 20) {
- // b7 = 1 indicates the further interindustry class byte coding
- boolean isSM = (cla & 0x0C) != 0;
- cla = (byte) ((cla & 0xB0) | 0x40 | (channelNumber - 4));
- if (isSM) {
- cla |= 0x20;
- }
- } else {
- throw new IllegalArgumentException(
- "Channel number must be within [0..19]");
- }
- return cla;
- }
-
- public void setChannelAccess(ChannelAccess channelAccess) {
- this.mChannelAccess = channelAccess;
- }
-
- public ChannelAccess getChannelAccess() {
- return this.mChannelAccess;
- }
-
- public void setCallingPid(int pid) {
- mCallingPid = pid;
- }
-
- private void checkCommand(byte[] command) {
- if (getTerminal().getAccessControlEnforcer() != null) {
- // check command if it complies to the access rules.
- // if not an exception is thrown
- getTerminal().getAccessControlEnforcer()
- .checkCommand(this, command);
- } else {
- throw new AccessControlException(
- "FATAL: Access Controller not set for Terminal: "
- + getTerminal().getName());
- }
- }
-
- /**
- * true if aid during open xxx channel coud be selected. false if aid could
- * not be or was not selected.
- *
- * @return boolean.
- */
- public boolean hasSelectedAid() {
- return mHasSelectedAid;
- }
-
- /**
- * set selected aid flag and aid (may be null).
- */
- public void hasSelectedAid(boolean has, byte[] aid) {
- mHasSelectedAid = has;
- mAid = aid;
- }
-
- /**
- * Returns the data as received from the application select command
- * inclusively the status word. The returned byte array contains the data
- * bytes in the following order: [<first data byte>, ..., <last data byte>,
- * <sw1>, <sw2>]
- *
- * @return The data as returned by the application select command
- * inclusively the status word.
- * @return Only the status word if the application select command has no
- * returned data.
- * @return null if an application select command has not been performed or
- * the selection response can not be retrieved by the reader
- * implementation.
- */
- public byte[] getSelectResponse() {
- return mSelectResponse;
- }
-
- boolean isClosed() {
- return mIsClosed;
- }
-
- void setClosed() {
- mIsClosed = true;
- }
-
- /**
- * Implementation of the SmartcardService Channel interface according to
- * OMAPI.
- */
- final class SmartcardServiceChannel extends ISmartcardServiceChannel.Stub {
-
- private final SmartcardServiceSession mSession;
-
- public SmartcardServiceChannel(SmartcardServiceSession session) {
- mSession = session;
- }
-
- @Override
- public void close(SmartcardError error) throws RemoteException {
-
- SmartcardService.clearError(error);
- try {
- Channel.this.close();
- } catch (Exception e) {
- SmartcardService.setError(error, e);
- } finally {
- if (mSession != null) {
- mSession.removeChannel(Channel.this);
- }
- }
- }
-
- public void setClosed() {
- Channel.this.setClosed();
- }
-
- @Override
- public boolean isClosed() throws RemoteException {
- return Channel.this.isClosed();
- }
-
- @Override
- public boolean isBasicChannel()
- throws RemoteException {
- return Channel.this.isBasicChannel();
- }
-
- @Override
- public byte[] getSelectResponse()
- throws RemoteException {
- return Channel.this.getSelectResponse();
- }
-
- @Override
- public ISmartcardServiceSession getSession()
- throws RemoteException {
- return Channel.this.mSession;
- }
-
- @Override
- public byte[] transmit(byte[] command, SmartcardError error)
- throws RemoteException {
- SmartcardService.clearError(error);
-
- try {
- if (isClosed()) {
- SmartcardService.setError(
- error,
- IllegalStateException.class,
- "channel is closed");
- return null;
- }
-
- if (command == null) {
- SmartcardService.setError(
- error,
- IllegalArgumentException.class,
- "command must not be null");
- return null;
- }
- if (command.length < 4) {
- SmartcardService.setError(
- error,
- IllegalArgumentException.class,
- "command must have at least 4 bytes");
- return null;
- }
- Channel.this.setCallingPid(Binder.getCallingPid());
- byte[] response = Channel.this.transmit(command);
- return response;
- } catch (Exception e) {
- Log.v(SmartcardService._TAG, "transmit Exception: "
- + e.getMessage()
- + " (Command: " + Util.bytesToString(command) + ")");
- SmartcardService.setError(error, e);
- return null;
- }
- }
-
- @Override
- public boolean selectNext(SmartcardError error)
- throws RemoteException {
- SmartcardService.clearError(error);
-
- try {
- if (isClosed()) {
- SmartcardService.setError(
- error,
- IllegalStateException.class,
- "channel is closed");
- return false;
- }
- Channel.this.setCallingPid(Binder.getCallingPid());
- boolean response = Channel.this.selectNext();
- return response;
- } catch (Exception e) {
- SmartcardService.setError(error, e);
- return false;
- }
- }
- };
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/IChannel.java b/smart-card-service/src/org/simalliance/openmobileapi/service/IChannel.java
deleted file mode 100644
index b7bdfd2..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/IChannel.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2011, The Android Open Source Project
- *
- * 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.
- */
-/*
- * Contributed by: Giesecke & Devrient GmbH.
- */
-
-package org.simalliance.openmobileapi.service;
-
-
-import org.simalliance.openmobileapi.service.security.ChannelAccess;
-
-import org.simalliance.openmobileapi.service.ISmartcardServiceCallback;
-
-/**
- * Smartcard service interface for channel resources.
- */
-public interface IChannel {
-
- /**
- * Closes this channel.
- *
- * @throws CardException if closing the channel failed.
- */
- void close() throws CardException;
-
- /**
- * Returns the channel number according to ISO 7816-4.
- *
- * @return the channel number according to ISO 7816-4.
- */
- int getChannelNumber();
-
- /**
- * Returns if this channel is a basic channel
- *
- * @return true if this channel is a basic channel
- */
- boolean isBasicChannel();
-
- /**
- * Returns the associated terminal.
- *
- * @return the associated terminal.
- */
- ITerminal getTerminal();
-
- /**
- * Transmits the specified command APDU and returns the response APDU.
- * MANAGE channel commands are not allowed. Applet selection commands are
- * not allowed if this is a logical channel.
- *
- * @param command the command APDU to be transmitted.
- * @return the response APDU.
- * @throws CardException if command transmission failed or the command is
- * not allowed.
- */
- byte[] transmit(byte[] command) throws CardException;
-
-
- /**
- * @param channelAccess
- */
- void setChannelAccess(ChannelAccess channelAccess);
-
- /**
- * @return channelAccess
- */
- ChannelAccess getChannelAccess();
-
- /**
- * Sets calling pid for validation in checkCommand.
- * @param pid calling pid of the device application
- */
- void setCallingPid( int pid );
-
-
- /**
- * @return
- */
- ISmartcardServiceCallback getCallback();
-
- /**
- * true if aid during open xxx channel coud be selected.
- * false if aid could not be or was not selected.
- * @return
- */
- boolean hasSelectedAid();
-
- /**
- * set selected aid flag and aid (may be null)
- */
- void hasSelectedAid(boolean has, byte[] aid);
- /**
- * Returns the data as received from the application select command inclusively the status word.
- * The returned byte array contains the data bytes in the following order:
- * [<first data byte>, ..., <last data byte>, <sw1>, <sw2>]
- * @return The data as returned by the application select command inclusively the status word.
- * @return Only the status word if the application select command has no returned data.
- * @return null if an application select command has not been performed or the selection response can not
- * be retrieved by the reader implementation.
- */
- public byte[] getSelectResponse();
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/ITerminal.java b/smart-card-service/src/org/simalliance/openmobileapi/service/ITerminal.java
deleted file mode 100644
index 3961920..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/ITerminal.java
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright (C) 2011, The Android Open Source Project
- *
- * 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.
- */
-/*
- * Contributed by: Giesecke & Devrient GmbH.
- */
-
-package org.simalliance.openmobileapi.service;
-
-import java.io.PrintWriter;
-
-
-import org.simalliance.openmobileapi.service.SmartcardService.SmartcardServiceSession;
-import org.simalliance.openmobileapi.service.security.AccessControlEnforcer;
-import org.simalliance.openmobileapi.service.security.ChannelAccess;
-
-import android.content.pm.PackageManager;
-
-
-/**
- * Smartcard service interface for terminal resources.
- */
-public interface ITerminal {
-
- /**
- * Closes all open channels of this terminal.
- */
- void closeChannels();
-
- /**
- * Returns the channel for the specified handle or <code>null</code> if this
- * handle is not registered.
- *
- * @param hChannel the channel handle.
- * @return the channel for the specified handle or <code>null</code> if this
- * handle is not registered.
- */
- IChannel getChannel(long hChannel);
-
- /**
- * Returns the reader name, which will be of the form <type><index>.
- *
- * @return the reader name.
- */
- String getName();
-
- /**
- * Returns the type of the reader (SIM/eSE/SD/USB/Bluetooth...).
- *
- * @return the type of the reader.
- */
- String getType();
-
- /**
- * Sets the index for this reader.
- *
- * @param index The index to be set.
- */
- void setIndex(int index);
-
- /**
- * Sends a select command on the basic channel. With this command the
- * default application will be selected on the card. (e.g. CardManager)
- *
- * @throw NoSuchElementException if the default applet couldn't be found or
- * selected
- */
- void select();
-
- /**
- * Sends a select command on the basic channel.
- *
- * @param aid the aid which should be selected
- * @throw NoSuchElementException if the corresponding applet couldn't be
- * found
- */
- void select(byte[] aid);
-
- /**
- * Opens the basic channel to the card.
- *
- * @param callback the callback used to react on the death of the client.
- * @return a handle for the basic channel.
- * @throws CardException if opening the basic channel failed or the basic
- * channel is in use.
- */
- Channel openBasicChannel(
- SmartcardServiceSession session,
- ISmartcardServiceCallback callback)
- throws CardException;
-
- /**
- * Opens the basic channel to the card.
- *
- * @param aid the AID of the applet to be selected.
- * @param callback the callback used to react on the death of the client.
- * @return a handle for the basic channel.
- * @throws CardException if opening the basic channel failed or the basic
- * channel is in use.
- */
- Channel openBasicChannel(
- SmartcardServiceSession session,
- byte[] aid,
- ISmartcardServiceCallback callback)
- throws Exception;
-
- /**
- * Opens a logical channel to the card.
- *
- * @param callback the callback used to react on the death of the client.
- * @return a handle for the logical channel.
- * @throws CardException if opening the logical channel failed.
- */
- Channel openLogicalChannel(
- SmartcardServiceSession session,
- ISmartcardServiceCallback callback)
- throws Exception;
-
- /**
- * Opens a logical channel to the card.
- *
- * @param aid the AID of the applet to be selected.
- * @param callback the callback used to react on the death of the client.
- * @return a handle for the logical channel.
- * @throws CardException if opening the logical channel failed.
- */
- Channel openLogicalChannel(
- SmartcardServiceSession session,
- byte[] aid,
- ISmartcardServiceCallback callback)
- throws Exception;
-
- /**
- * Returns <code>true</code> if a card is present; <code>false</code>
- * otherwise.
- *
- * @return <code>true</code> if a card is present; <code>false</code>
- * otherwise.
- * @throws CardException if card presence information is not available.
- */
- boolean isCardPresent() throws CardException;
-
- /**
- * Returns <code>true</code> if terminal is connected <code>false</code>
- * otherwise.
- *
- * @return <code>true</code> if at least one terminal is connected.
- */
- public boolean isConnected();
-
- /**
- * Returns the ATR of the connected card or null if the ATR is not
- * available.
- *
- * @return the ATR of the connected card or null if the ATR is not
- * available.
- */
- public byte[] getAtr();
-
- /**
- * Returns the data as received from the application select command
- * inclusively the status word.
- * The returned byte array contains the data bytes in the following order:
- * [<first data byte>, ..., <last data byte>, <sw1>, <sw2>]
- *
- * @return The data as returned by the application select command
- * inclusively the status word.
- * @return Only the status word if the application select command has no
- * returned data.
- * @return null if an application select command has not been performed or
- * the selection response can not be retrieved by the reader
- * implementation.
- */
- public byte[] getSelectResponse();
-
- /**
- * Exchanges APDU (SELECT, READ/WRITE) to the
- * given EF by File ID and file path via iccIO.
- *
- * The given command is checked and might be rejected.
- *
- * @param fileID
- * @param filePath
- * @param cmd
- * @return
- */
- public byte[] simIOExchange(int fileID, String filePath, byte[] cmd)
- throws Exception;
-
-
- /**
- * Set ups the Channel Access object for access control
- * from the cached access rules
- * for the given packageNames and the AID of the applet to be accessed.
- *
- * @return ChannelAccess object containing the access flags/filter.
- */
- ChannelAccess setUpChannelAccess(
- PackageManager packageManager,
- byte[] aid,
- String packageName,
- ISmartcardServiceCallback callback);
-
- /**
- * Set up the correct access control hander ARA (or ARF)
- * and if indicated loads all accesses rules for the terminal.
- * @param boolean flag if Access Rules should be loaded.
- * @return true if rules have been successfully loaded
- */
- boolean initializeAccessControl(
- boolean loadAtStartup,
- ISmartcardServiceCallback callback);
-
- /**
- * Reset the access control: should be called when the card is changed.
- */
- void resetAccessControl();
-
- AccessControlEnforcer getAccessControlEnforcer();
-
-
- /**
- * Dump the terminal state (for debugging purpose and crash tools).
- * @param writer uses to print the dump
- * @param prefix to be added before any new line (mainly used for
- * indentation)
- */
- public void dump(PrintWriter writer, String prefix);
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/SmartcardError.java b/smart-card-service/src/org/simalliance/openmobileapi/service/SmartcardError.java
deleted file mode 100644
index 630342d..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/SmartcardError.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2011, The Android Open Source Project
- *
- * 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.
- */
-/*
- * Contributed by: Giesecke & Devrient GmbH.
- */
-
-package org.simalliance.openmobileapi.service;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.lang.reflect.Constructor;
-
-/**
- * Smartcard service parameter class used to marshal exception information from
- * the smartcard service to clients.
- */
-public class SmartcardError implements Parcelable {
- private String mClazz;
-
- private String mMessage;
-
- public static final Parcelable.Creator<SmartcardError> CREATOR = new Parcelable.Creator<SmartcardError>() {
- public SmartcardError createFromParcel(Parcel in) {
- return new SmartcardError(in);
- }
-
- public SmartcardError[] newArray(int size) {
- return new SmartcardError[size];
- }
- };
-
- /**
- * Creates an empty smartcard error container.
- */
- public SmartcardError() {
- this.mClazz = "";
- this.mMessage = "";
- }
-
- private SmartcardError(Parcel in) {
- mClazz = in.readString();
- mMessage = in.readString();
- }
-
- /**
- * Creates a smartcard error which creates the specified exception.
- *
- * @param clazz the exception class. <code>null</code> to reset the error
- * information.
- * @param message the exception message.
- */
- public SmartcardError(String clazz, String message) {
- this.mClazz = (clazz == null) ? "" : clazz;
- this.mMessage = (message == null) ? "" : message;
- }
-
- /**
- * Clears the error.
- */
- public void clear() {
- this.mClazz = "";
- this.mMessage = "";
- }
-
- /**
- * Creates the encoded exception. Returns <code>null</code> if empty. If the
- * encoded exception is neither a RuntimeException nor a CardException, it
- * is encapsulated in a RuntimeException.
- *
- * @return the encoded exception or <code>null</code> if empty.
- */
- @SuppressWarnings({ "rawtypes" })
- public Exception createException() {
- try {
- if (mClazz.length() == 0) {
- return null;
- }
- if (mMessage.length() == 0) {
- return (Exception) Class.forName(mClazz).newInstance();
- }
- Constructor constructor = Class.forName(mClazz).getConstructor(String.class);
- return (Exception) constructor.newInstance(mMessage);
- } catch (Exception e) {
- return null;
- }
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void readFromParcel(Parcel in) {
- mClazz = in.readString();
- mMessage = in.readString();
- }
-
- /**
- * Sets the error information.
- *
- * @param clazz the exception class. <code>null</code> to reset the error
- * information.
- * @param message the exception message.
- */
- @SuppressWarnings({ "rawtypes" })
- public void setError(Class clazz, String message) {
- this.mClazz = (clazz == null) ? "" : clazz.getName();
- this.mMessage = (message == null) ? "" : message;
- }
-
- /**
- * Throws the encoded exception. Does not throw an exception if the
- * container is empty. If the encoded exception is neither a
- * RuntimeException nor a CardException, it is encapsulated in a
- * RuntimeException.
- *
- * @throws RuntimeException if the encoded exception is not a CardException.
- * @throws CardException if a CardException is encoded.
- */
- public void throwException() throws CardException {
- Exception e = createException();
- if (e == null) {
- return;
- }
- if (e instanceof CardException) {
- throw (CardException) e;
- }
- if (e instanceof RuntimeException) {
- throw (RuntimeException) e;
- }
- throw new RuntimeException(e);
- }
-
- public void writeToParcel(Parcel out, int flags) {
- out.writeString(mClazz);
- out.writeString(mMessage);
- }
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/SmartcardService.java b/smart-card-service/src/org/simalliance/openmobileapi/service/SmartcardService.java
deleted file mode 100644
index 85f0375..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/SmartcardService.java
+++ /dev/null
@@ -1,1064 +0,0 @@
-/*
- * Copyright (C) 2011, The Android Open Source Project
- *
- * 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.
- */
-/*
- * Contributed by: Giesecke & Devrient GmbH.
- */
- /******************************************************************************
- *
- * The original Work has been changed by NXP Semiconductors.
- *
- * Copyright (C) 2015 NXP Semiconductors
- *
- * 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 org.simalliance.openmobileapi.service;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.lang.reflect.Constructor;
-import java.security.AccessControlException;
-import java.util.ArrayList;
-import android.util.Log;
-import dalvik.system.DexClassLoader;
-import dalvik.system.DexFile;
-import dalvik.system.PathClassLoader;
-import android.annotation.SuppressLint;
-import android.app.Service;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.os.AsyncTask;
-import android.os.Binder;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.os.RemoteException;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.Collection;
-
-import org.simalliance.openmobileapi.service.Channel.SmartcardServiceChannel;
-import org.simalliance.openmobileapi.service.Terminal.SmartcardServiceReader;
-import org.simalliance.openmobileapi.service.security.AccessControlEnforcer;
-import org.simalliance.openmobileapi.service.security.ChannelAccess;
-
-
-
-/**
- * The smartcard service is setup with privileges to access smart card hardware.
- * The service enforces the permission
- * 'org.simalliance.openmobileapi.service.permission.BIND'.
- */
-public final class SmartcardService extends Service {
-
- public static final String _TAG = "SmartcardService";
- public static final String _UICC_TERMINAL = "SIM";
- public static final String _eSE_TERMINAL = "eSE";
- public static final String _SD_TERMINAL = "SD";
- public static final String _P61Spi_TERMINAL = "P61Spi1";
-
- static void clearError(SmartcardError error) {
- if (error != null) {
- error.clear();
- }
- }
-
- @SuppressWarnings({ "rawtypes" })
- static void setError(SmartcardError error, Class clazz, String message) {
- if (error != null) {
- error.setError(clazz, message);
- }
- }
-
- static void setError(SmartcardError error, Exception e) {
- if (error != null) {
- error.setError(e.getClass(), e.getMessage());
- }
- }
-
- /**
- * For now this list is setup in onCreate(), not changed later and therefore
- * not synchronized.
- */
- private Map<String, ITerminal> mTerminals
- = new TreeMap<String, ITerminal>();
-
- /**
- * For now this list is setup in onCreate(), not changed later and therefore
- * not synchronized.
- */
- private Map<String, ITerminal> mAddOnTerminals
- = new TreeMap<String, ITerminal>();
-
- /* Broadcast receivers */
- private BroadcastReceiver mSimReceiver;
- private BroadcastReceiver mNfcReceiver;
- private BroadcastReceiver mMediaReceiver;
-
- /* Async task */
- InitialiseTask mInitialiseTask;
-
- /**
- * ServiceHandler use to load rules from the terminal.
- */
- private ServiceHandler mServiceHandler;
-
- public SmartcardService() {
- super();
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- Log.v(_TAG, Thread.currentThread().getName()
- + " smartcard service onBind");
- if (ISmartcardService.class.getName().equals(intent.getAction())) {
- return mSmartcardBinder;
- }
- return null;
- }
-
- @Override
- public void onCreate() {
- Log.v(_TAG, Thread.currentThread().getName()
- + " smartcard service onCreate");
-
- // Start up the thread running the service. Note that we create a
- // separate thread because the service normally runs in the process's
- // main thread, which we don't want to block. We also make it
- // background priority so CPU-intensive work will not disrupt our UI.
- HandlerThread thread = new HandlerThread("SmartCardServiceHandler");
- thread.start();
-
- // Get the HandlerThread's Looper and use it for our Handler
- mServiceHandler = new ServiceHandler(thread.getLooper());
-
- createTerminals();
- mInitialiseTask = new InitialiseTask();
- mInitialiseTask.execute();
- }
-
- @Override
- public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
- writer.println("SMARTCARD SERVICE (dumpsys activity "
- + "service org.simalliance.openmobileapi)");
- writer.println();
-
- String prefix = " ";
-
- if (!Build.IS_DEBUGGABLE) {
- writer.println(prefix + "Your build is not debuggable!");
- writer.println(prefix + "Smartcard service dump is only available"
- + "for userdebug and eng build");
- } else {
- writer.println(prefix + "List of terminals:");
- for (ITerminal terminal : mTerminals.values()) {
- writer.println(prefix + " " + terminal.getName());
- }
- writer.println();
-
- writer.println(prefix + "List of add-on terminals:");
- for (ITerminal terminal : mAddOnTerminals.values()) {
- writer.println(prefix + " " + terminal.getName());
- }
- writer.println();
-
- for (ITerminal terminal : mTerminals.values()) {
- terminal.dump(writer, prefix);
- }
- for (ITerminal terminal : mAddOnTerminals.values()) {
- terminal.dump(writer, prefix);
- }
- }
- }
-
- private class InitialiseTask extends AsyncTask<Void, Void, Void> {
-
- @Override
- protected void onPreExecute() {
- super.onPreExecute();
- }
-
- @Override
- protected Void doInBackground(Void... arg0) {
- try {
- initializeAccessControl(null, null);
- } catch (Exception e) {
- // do nothing since this is called where nobody can react.
- }
- return null;
- }
-
- @Override
- protected void onPostExecute(Void result) {
- super.onPostExecute(result);
- Log.i(_TAG, "OnPostExecute()");
- //registerSimStateChangedEvent(getApplicationContext());
- registerAdapterStateChangedEvent(getApplicationContext());
- registerSpiP61AdapterStateChangedEvent(getApplicationContext());
- //registerMediaMountedEvent(getApplicationContext());
- mInitialiseTask = null;
- }
- }
-
- private void registerSimStateChangedEvent(Context context) {
- Log.v(_TAG, "register SIM_STATE_CHANGED event");
-
- IntentFilter intentFilter = new IntentFilter(
- "android.intent.action.SIM_STATE_CHANGED");
- mSimReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if ("android.intent.action.SIM_STATE_CHANGED".equals(intent
- .getAction())) {
- final Bundle extras = intent.getExtras();
- final boolean simReady = (extras != null)
- && "READY".equals(extras.getString("ss"));
- final boolean simLoaded = (extras != null)
- && "LOADED".equals(extras.getString("ss"));
- if (simReady) {
- Log.i(_TAG, "SIM is ready. Checking access rules for"
- + " updates.");
- mServiceHandler.sendMessage(MSG_LOAD_UICC_RULES, 5);
- } else if (simLoaded) {
- Log.i(_TAG, "SIM is loaded. Checking access rules for"
- + " updates.");
- mServiceHandler.sendMessage(MSG_LOAD_UICC_RULES, 5);
- }
- }
- }
- };
-
- context.registerReceiver(mSimReceiver, intentFilter);
- }
-
- private void unregisterSimStateChangedEvent(Context context) {
- if (mSimReceiver != null) {
- Log.v(_TAG, "unregister SIM_STATE_CHANGED event");
- context.unregisterReceiver(mSimReceiver);
- mSimReceiver = null;
- }
- }
-
- private void registerAdapterStateChangedEvent(Context context) {
- Log.v(_TAG, "register ADAPTER_STATE_CHANGED event");
-
- IntentFilter intentFilter = new IntentFilter(
- "android.nfc.action.ADAPTER_STATE_CHANGED");
- mNfcReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final boolean nfcAdapterAction = intent.getAction().equals(
- "android.nfc.action.ADAPTER_STATE_CHANGED");
- // Is NFC Adapter turned on?
- final boolean nfcAdapterOn
- = nfcAdapterAction && intent.getIntExtra(
- "android.nfc.extra.ADAPTER_STATE", 1) == 3;
- if (nfcAdapterOn) {
- Log.i(_TAG, "NFC Adapter is ON. Checking access rules for"
- + " updates.");
- mServiceHandler.sendMessage(MSG_LOAD_ESE_RULES, 5);
- }
- }
- };
- context.registerReceiver(mNfcReceiver, intentFilter);
- }
-
- private void unregisterAdapterStateChangedEvent(Context context) {
- if (mNfcReceiver != null) {
- Log.v(_TAG, "unregister ADAPTER_STATE_CHANGED event");
- context.unregisterReceiver(mNfcReceiver);
- mNfcReceiver = null;
- }
- }
-
- private void registerSpiP61AdapterStateChangedEvent(Context context) {
- Log.v(_TAG, "register SPI_P61_ADAPTER_STATE_CHANGED event");
-
- IntentFilter intentFilter = new IntentFilter(
- "android.ese.spi.action.ADAPTER_STATE_CHANGED");
- mNfcReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final boolean nfcAdapterAction = intent.getAction().equals(
- "android.ese.spi.action.ADAPTER_STATE_CHANGED");
- // Is SPI service Adapter turned on?
- final boolean nfcAdapterOn
- = nfcAdapterAction && intent.getIntExtra(
- "android.ese.spi.extra.ADAPTER_STATE", 1) == 3;
- if (nfcAdapterOn) {
- Log.i(_TAG, "EseSpi Adapter is ON. Checking access rules for"
- + " updates.");
- mServiceHandler.sendMessage(MSG_LOAD_ESE_SPI_RULES, 5);
- }
- }
- };
- context.registerReceiver(mNfcReceiver, intentFilter);
- }
-
- private void registerMediaMountedEvent(Context context) {
- Log.v(_TAG, "register MEDIA_MOUNTED event");
-
- IntentFilter intentFilter = new IntentFilter(
- "android.intent.action.MEDIA_MOUNTED");
- mMediaReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final boolean mediaMounted = intent.getAction().equals(
- "android.intent.action.MEDIA_MOUNTED");
- if (mediaMounted) {
- Log.i(_TAG, "New Media is mounted. Checking access rules"
- + " for updates.");
- mServiceHandler.sendMessage(MSG_LOAD_SD_RULES, 5);
- }
- }
- };
- context.registerReceiver(mMediaReceiver, intentFilter);
- }
-
- private void unregisterMediaMountedEvent(Context context) {
- if (mMediaReceiver != null) {
- Log.v(_TAG, "unregister MEDIA_MOUNTED event");
- context.unregisterReceiver(mMediaReceiver);
- mMediaReceiver = null;
- }
- }
-
- /**
- * Initalizes Access Control. At least the refresh tag is read and if it
- * differs to the previous one (e.g. is null) the all access rules are read.
- *
- * @param se
- */
- public boolean initializeAccessControl(
- String se,
- ISmartcardServiceCallback callback) {
- return initializeAccessControl(false, se, callback);
- }
-
- public synchronized boolean initializeAccessControl(
- boolean reset,
- String se,
- ISmartcardServiceCallback callback) {
- boolean result = true;
- Log.i(_TAG, "Initializing Access Control");
-
- if (callback == null) {
- callback = new ISmartcardServiceCallback.Stub() {
- };
- }
-
- Collection<ITerminal> col = mTerminals.values();
- Iterator<ITerminal> iter = col.iterator();
- while (iter.hasNext()) {
- ITerminal terminal = iter.next();
- if (terminal == null) {
- continue;
- }
- if (se == null || terminal.getName().startsWith(se)) {
- boolean isCardPresent = false;
- try {
- isCardPresent = terminal.isCardPresent();
- } catch (CardException e) {
- isCardPresent = false;
- }
-
- Log.i(_TAG,"terminal Name " + terminal.getName());
- //if ((terminal.getName().equals("P61Spi11")) || isCardPresent ) {
- if ( isCardPresent ) {
- Log.i(_TAG, "Initializing Access Control for "
- + terminal.getName());
- if (reset) {
- terminal.resetAccessControl();
- }
- result &= terminal.initializeAccessControl(true, callback);
- } else {
- Log.i(_TAG, "NOT initializing Access Control for "
- + terminal.getName() + " SE not present.");
- }
- Log.i(_TAG, "Initialized Success Control for " + terminal.getName());
- }
- }
- col = this.mAddOnTerminals.values();
- iter = col.iterator();
- while (iter.hasNext()) {
- ITerminal terminal = iter.next();
- if (terminal == null) {
- continue;
- }
- if (se == null || terminal.getName().startsWith(se)) {
- boolean isCardPresent = false;
- try {
- isCardPresent = terminal.isCardPresent();
- } catch (CardException e) {
- isCardPresent = false;
- }
-
- if (isCardPresent) {
- Log.i(_TAG,
- "Initializing Access Control for "
- + terminal.getName());
- if (reset) {
- terminal.resetAccessControl();
- }
- result &= terminal.initializeAccessControl(true, callback);
- } else {
- Log.i(_TAG, "NOT initializing Access Control for "
- + terminal.getName() + " SE not present.");
- }
- }
- }
- Log.i(_TAG, "End of SmartCard initializeAccessControl ");
- return result;
- }
-
- public void onDestroy() {
- Log.v(_TAG, " smartcard service onDestroy ...");
- for (ITerminal terminal : mTerminals.values()) {
- terminal.closeChannels();
- }
- for (ITerminal terminal : mAddOnTerminals.values()) {
- terminal.closeChannels();
- }
-
- // Cancel the inialization background task if still running
- if (mInitialiseTask != null) {
- mInitialiseTask.cancel(true);
- }
- mInitialiseTask = null;
-
- // Unregister all the broadcast receivers
- unregisterSimStateChangedEvent(getApplicationContext());
- unregisterAdapterStateChangedEvent(getApplicationContext());
- unregisterMediaMountedEvent(getApplicationContext());
-
- mServiceHandler = null;
-
- Log.v(_TAG, Thread.currentThread().getName()
- + " ... smartcard service onDestroy");
-
- }
-
- private ITerminal getTerminal(String reader, SmartcardError error) {
- if (reader == null) {
- setError(error, NullPointerException.class,
- "reader must not be null");
- return null;
- }
- ITerminal terminal = mTerminals.get(reader);
- if (terminal == null) {
- terminal = mAddOnTerminals.get(reader);
- if (terminal == null) {
- setError(error, IllegalArgumentException.class,
- "unknown reader");
- }
- }
- return terminal;
- }
-
- private void createTerminals() {
- createBuildinTerminals();
- createAddonTerminals();
- }
-
- private String[] createTerminalNamesList() {
- Set<String> names = mTerminals.keySet();
- ArrayList<String> list = new ArrayList<String>(names);
-
- names = mAddOnTerminals.keySet();
- for (String name : names) {
- list.add(name);
- }
-
- return list.toArray(new String[list.size()]);
- }
-
- @SuppressWarnings({ "rawtypes", "unchecked" })
- private void createBuildinTerminals() {
- Class[] types = new Class[] {
- Context.class
- };
- Object[] args = new Object[] {
- this
- };
- Object[] classes = getBuildinTerminalClasses();
- for (Object clazzO : classes) {
- try {
- Class clazz = (Class) clazzO;
- Constructor constr = clazz.getDeclaredConstructor(types);
- ITerminal terminal = (ITerminal) constr.newInstance(args);
- terminal.setIndex(getIndexForTerminal(terminal));
- mTerminals.put(terminal.getName(), terminal);
- Log.v(_TAG, Thread.currentThread().getName() + " adding "
- + terminal.getName());
- } catch (Throwable t) {
- Log.e(_TAG, Thread.currentThread().getName()
- + " CreateReaders Error: "
- + ((t.getMessage() != null) ? t.getMessage()
- : "unknown"));
- }
- }
- }
-
- private void createAddonTerminals() {
- String[] packageNames = AddonTerminal.getPackageNames(this);
- for (String packageName : packageNames) {
- try {
- String apkName = getPackageManager().getApplicationInfo(
- packageName, 0).sourceDir;
- DexFile dexFile = new DexFile(apkName);
- Enumeration<String> classFileNames = dexFile.entries();
- while (classFileNames.hasMoreElements()) {
- String className = classFileNames.nextElement();
- if (className.endsWith("Terminal")) {
- PathClassLoader cl = new PathClassLoader(
- apkName, ClassLoader.getSystemClassLoader());
- String terminalType = (String) cl
- .loadClass(className)
- .getMethod("getType", (Class<?>[]) null)
- .invoke(null, (Object[]) null);
- ITerminal terminal = new AddonTerminal(
- this,
- terminalType,
- packageName,
- className);
- terminal.setIndex(getIndexForTerminal(terminal));
- mAddOnTerminals.put(terminal.getName(), terminal);
- Log.v(_TAG, Thread.currentThread().getName()
- + " adding " + terminal.getName());
- }
- }
- } catch (Throwable t) {
- Log.e(_TAG, Thread.currentThread().getName()
- + " CreateReaders Error: "
- + ((t.getMessage() != null) ? t.getMessage()
- : "unknown"));
- }
- }
- }
-
- /**
- * Computes the index that should be assigned to each terminal.
- *
- * @param terminal The terminal to compute the index for.
- *
- * @return The index that shall be assigned to the given terminal.
- */
- private int getIndexForTerminal(ITerminal terminal) {
- return getTerminalsOfType(terminal.getType()).length + 1;
- }
-
- /**
- * Returns an array of terminals of the specified type (SIM/eSE/SD/...).
- *
- * @param terminalType The type of the terminals to be retrieved.
- *
- * @return An array of terminals of the specified type.
- */
- private ITerminal[] getTerminalsOfType(String terminalType) {
- ArrayList<ITerminal> terminals = new ArrayList<ITerminal>();
- int index = 1;
- String name = terminalType + index;
- while (mTerminals.containsKey(name)
- || mAddOnTerminals.containsKey(name)) {
- if (mTerminals.containsKey(name)) {
- terminals.add(mTerminals.get(name));
- } else {
- terminals.add(mAddOnTerminals.get(name));
- }
- index++;
- name = terminalType + index;
- }
-
- return terminals.toArray(new ITerminal[terminals.size()]);
- }
-
- @SuppressWarnings({ "rawtypes", "unchecked" })
- private Object[] getBuildinTerminalClasses() {
- ArrayList classes = new ArrayList();
- try {
- String packageName = "org.simalliance.openmobileapi.service";
- String apkName = getPackageManager().getApplicationInfo(
- packageName, 0).sourceDir;
- DexClassLoader dexClassLoader = new DexClassLoader(apkName,
- getApplicationContext().getFilesDir().getAbsolutePath(),
- null, getClass().getClassLoader());
-
- Class terminalClass = Class.forName(
- "org.simalliance.openmobileapi.service.Terminal", true,
- dexClassLoader);
- if (terminalClass == null) {
- return classes.toArray();
- }
-
- DexFile dexFile = new DexFile(apkName);
- Enumeration<String> classFileNames = dexFile.entries();
- while (classFileNames.hasMoreElements()) {
- String className = classFileNames.nextElement();
- Class clazz = Class.forName(className);
- Class superClass = clazz.getSuperclass();
- if (superClass != null
- && superClass.equals(terminalClass)
- && !className.equals("org.simalliance.openmobileapi.service.AddonTerminal")) {
- classes.add(clazz);
- }
- }
- } catch (Throwable exp) {
- // nothing to to
- }
- return classes.toArray();
- }
-
- /**
- * Get package name from the user id.
- *
- * This shall fix the problem the issue that process name != package name
- * due to anndroid:process attribute in manifest file.
- *
- * But this call is not really secure either since a uid can be shared
- * between one and more apks
- *
- * @param uid
- * @return The first package name associated with this uid.
- */
- public String getPackageNameFromCallingUid(int uid) {
- PackageManager packageManager = getPackageManager();
- if (packageManager != null) {
- String packageName[] = packageManager.getPackagesForUid(uid);
- if (packageName != null && packageName.length > 0) {
- return packageName[0];
- }
- }
- throw new AccessControlException(
- "Caller PackageName can not be determined");
- }
-
- /**
- * The smartcard service interface implementation.
- */
- private final ISmartcardService.Stub mSmartcardBinder
- = new ISmartcardService.Stub() {
-
- @Override
- public String[] getReaders(SmartcardError error)
- throws RemoteException {
- clearError(error);
- Log.v(_TAG, "getReaders()");
- return createTerminalNamesList();
- }
-
- @Override
- public ISmartcardServiceReader getReader(String reader,
- SmartcardError error) throws RemoteException {
- clearError(error);
- Terminal terminal = (Terminal) getTerminal(reader, error);
- if (terminal != null) {
- return terminal.new SmartcardServiceReader(
- SmartcardService.this);
- }
- setError(error, IllegalArgumentException.class,
- "invalid reader name");
- return null;
- }
-
- @Override
- public synchronized boolean[] isNFCEventAllowed(String reader,
- byte[] aid, String[] packageNames,
- ISmartcardServiceCallback callback, SmartcardError error)
- throws RemoteException {
- clearError(error);
- try {
- if (callback == null) {
- setError(error, NullPointerException.class,
- "callback must not be null");
- return null;
- }
- ITerminal terminal = getTerminal(reader, error);
- if (terminal == null) {
- return null;
- }
- if (aid == null || aid.length == 0) {
- aid = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00 };
- }
- if (aid.length < 5 || aid.length > 16) {
- setError(error, IllegalArgumentException.class,
- "AID out of range");
- return null;
- }
- if (packageNames == null || packageNames.length == 0) {
- setError(error, IllegalArgumentException.class,
- "process names not specified");
- return null;
- }
- AccessControlEnforcer ac = null;
- if (terminal.getAccessControlEnforcer() == null) {
- ac = new AccessControlEnforcer(terminal);
- } else {
- ac = terminal.getAccessControlEnforcer();
- }
- ac.setPackageManager(getPackageManager());
- ac.initialize(true, callback);
- return ac.isNFCEventAllowed(aid, packageNames, callback);
- } catch (Exception e) {
- setError(error, e);
- Log.v(_TAG, "isNFCEventAllowed Exception: " + e.getMessage());
- return null;
- }
- }
- };
-
- /**
- * The smartcard service interface implementation.
- */
- final class SmartcardServiceSession extends ISmartcardServiceSession.Stub {
-
- private final SmartcardServiceReader mReader;
- /** List of open channels in use of by this client. */
- private final Set<Channel> mChannels = new HashSet<Channel>();
-
- private final Object mLock = new Object();
-
- private boolean mIsClosed;
-
- private byte[] mAtr;
-
- public SmartcardServiceSession(SmartcardServiceReader reader) {
- mReader = reader;
- mAtr = mReader.getAtr();
- mIsClosed = false;
- }
-
- @Override
- public ISmartcardServiceReader getReader() throws RemoteException {
- return mReader;
- }
-
- @Override
- public byte[] getAtr() throws RemoteException {
- return mAtr;
- }
-
- @Override
- public void close(SmartcardError error) throws RemoteException {
- clearError(error);
- if (mReader == null) {
- return;
- }
- try {
- mReader.closeSession(this);
- } catch (CardException e) {
- setError(error, e);
- }
- }
-
- @Override
- public void closeChannels(SmartcardError error) throws RemoteException {
- synchronized (mLock) {
- Iterator<Channel> iter = mChannels.iterator();
- try {
- while (iter.hasNext()) {
- Channel channel = iter.next();
- if (channel != null && !channel.isClosed()) {
- try {
- channel.close();
- // close changes indirectly mChannels, so we
- // need a new iterator.
- iter = mChannels.iterator();
- } catch (Exception ignore) {
- Log.e(_TAG, "ServiceSession channel - close"
- + " Exception " + ignore.getMessage());
- }
- channel.setClosed();
- }
- }
- mChannels.clear();
- } catch (Exception e) {
- Log.e(_TAG,
- "ServiceSession closeChannels Exception "
- + e.getMessage());
- }
- }
- }
-
- @Override
- public boolean isClosed() throws RemoteException {
- return mIsClosed;
- }
-
- @Override
- public ISmartcardServiceChannel openBasicChannel(
- ISmartcardServiceCallback callback, SmartcardError error)
- throws RemoteException {
- return openBasicChannelAid(null, callback, error);
- }
-
- @Override
- public ISmartcardServiceChannel openBasicChannelAid(byte[] aid,
- ISmartcardServiceCallback callback, SmartcardError error)
- throws RemoteException {
- clearError(error);
- if (isClosed()) {
- setError(error, IllegalStateException.class,
- "session is closed");
- return null;
- }
- if (callback == null) {
- setError(error, IllegalStateException.class,
- "callback must not be null");
- return null;
- }
- if (mReader == null) {
- setError(error, IllegalStateException.class,
- "reader must not be null");
- return null;
- }
-
- try {
- boolean noAid = false;
- if (aid == null || aid.length == 0) {
- aid = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00 };
- noAid = true;
- }
-
- if (aid.length < 5 || aid.length > 16) {
- setError(error, IllegalArgumentException.class,
- "AID out of range");
- return null;
- }
-
- String packageName = getPackageNameFromCallingUid(Binder
- .getCallingUid());
- Log.v(_TAG, "Enable access control on basic channel for "
- + packageName);
- ChannelAccess channelAccess = mReader.getTerminal()
- .setUpChannelAccess(getPackageManager(), aid,
- packageName, callback);
- Log.v(_TAG, "Access control successfully enabled.");
-
- channelAccess.setCallingPid(Binder.getCallingPid());
- Log.v(_TAG, "OpenBasicChannel(AID)");
- Channel channel = null;
- if (noAid) {
- channel = mReader.getTerminal().openBasicChannel(this,
- callback);
- } else {
- channel = mReader.getTerminal().openBasicChannel(this, aid,
- callback);
- }
- channel.setChannelAccess(channelAccess);
- Log.v(_TAG,
- "Open basic channel success. Channel: "
- + channel.getChannelNumber());
-
- SmartcardServiceChannel basicChannel
- = channel.new SmartcardServiceChannel(this);
- mChannels.add(channel);
- return basicChannel;
-
- } catch (Exception e) {
- setError(error, e);
- Log.v(_TAG, "OpenBasicChannel Exception: " + e.getMessage());
- return null;
- }
- }
-
- @Override
- public ISmartcardServiceChannel openLogicalChannel(byte[] aid,
- ISmartcardServiceCallback callback, SmartcardError error)
- throws RemoteException {
- clearError(error);
-
- if (isClosed()) {
- setError(error, IllegalStateException.class,
- "session is closed");
- return null;
- }
-
- if (callback == null) {
- setError(error, IllegalStateException.class,
- "callback must not be null");
- return null;
- }
- if (mReader == null) {
- setError(error, IllegalStateException.class,
- "reader must not be null");
- return null;
- }
-
- try {
- boolean noAid = false;
- if (aid == null || aid.length == 0) {
- aid = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00 };
- noAid = true;
- }
-
- if (aid.length < 5 || aid.length > 16) {
- setError(error, IllegalArgumentException.class,
- "AID out of range");
- return null;
- }
-
- String packageName = getPackageNameFromCallingUid(Binder
- .getCallingUid());
- Log.v(_TAG, "Enable access control on logical channel for "
- + packageName);
- ChannelAccess channelAccess = mReader.getTerminal()
- .setUpChannelAccess(getPackageManager(), aid,
- packageName, callback);
- Log.v(_TAG, "Access control successfully enabled.");
- channelAccess.setCallingPid(Binder.getCallingPid());
- Log.v(_TAG, "OpenLogicalChannel");
- Channel channel = null;
- if (noAid) {
- channel = mReader.getTerminal().openLogicalChannel(this,
- callback);
- } else {
- channel = mReader.getTerminal().openLogicalChannel(this,
- aid, callback);
- }
- channel.setChannelAccess(channelAccess);
- Log.v(_TAG, "Open logical channel successfull. Channel: "
- + channel.getChannelNumber());
- SmartcardServiceChannel logicalChannel
- = channel.new SmartcardServiceChannel(this);
- mChannels.add(channel);
- return logicalChannel;
- } catch (Exception e) {
- setError(error, e);
- Log.v(_TAG, "OpenLogicalChannel Exception: " + e.getMessage());
- return null;
- }
- }
-
- void setClosed() {
- mIsClosed = true;
- }
-
- /**
- * Closes the specified channel. <br>
- * After calling this method the session can not be used for the
- * communication with the secure element any more.
- *
- * @param channel the channel handle obtained by an open channel
- * command.
- */
- void removeChannel(Channel channel) {
- if (channel == null) {
- return;
- }
- mChannels.remove(channel);
- }
- }
-
- /*
- * Handler Thread used to load and initiate ChannelAccess condition
- */
- public static final int MSG_LOAD_UICC_RULES = 1;
- public static final int MSG_LOAD_ESE_RULES = 2;
- public static final int MSG_LOAD_SD_RULES = 3;
- public static final int MSG_LOAD_ESE_SPI_RULES = 4;
-
- public static final int NUMBER_OF_TRIALS = 3;
- public static final long WAIT_TIME = 1000;
-
- private final class ServiceHandler extends Handler {
-
- @SuppressLint("HandlerLeak")
- public ServiceHandler(Looper looper) {
- super(looper);
- }
-
- public void sendMessage(int what, int nbTries) {
- mServiceHandler.removeMessages(what);
- Message newMsg = mServiceHandler.obtainMessage(what, nbTries, 0);
- mServiceHandler.sendMessage(newMsg);
- }
-
- @Override
- public void handleMessage(Message msg) {
- boolean result = true;
-
- Log.i(_TAG, "Handle msg: what=" + msg.what + " nbTries="
- + msg.arg1);
-
- switch (msg.what) {
- case MSG_LOAD_UICC_RULES:
- try {
- result = initializeAccessControl(
- true, _UICC_TERMINAL, null);
- } catch (Exception e) {
- Log.e(_TAG, "Got exception:" + e);
- }
- break;
-
- case MSG_LOAD_ESE_RULES:
- try {
- result = initializeAccessControl(true, _eSE_TERMINAL, null);
- } catch (Exception e) {
- Log.e(_TAG, "Got exception:" + e);
- }
- break;
-
- case MSG_LOAD_SD_RULES:
- try {
- result = initializeAccessControl(true, _SD_TERMINAL, null);
- } catch (Exception e) {
- Log.e(_TAG, "Got exception:" + e);
- }
- break;
-
- case MSG_LOAD_ESE_SPI_RULES:
- try {
- result = initializeAccessControl(true, _P61Spi_TERMINAL, null);
- } catch (Exception e) {
- Log.e(_TAG, "Got exception:" + e);
- }
- break;
- }
-
- if (!result && msg.arg1 > 0) {
- // Try to re-post the message
- Log.e(_TAG, "Fail to load rules: Let's try another time ("
- + msg.arg1 + " remaining attempt");
- Message newMsg = mServiceHandler.obtainMessage(msg.what,
- msg.arg1 - 1, 0);
- mServiceHandler.sendMessageDelayed(newMsg, WAIT_TIME);
- }
- }
- }
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/SmartcardServiceBootCompletedBroadcastReceiver.java b/smart-card-service/src/org/simalliance/openmobileapi/service/SmartcardServiceBootCompletedBroadcastReceiver.java
deleted file mode 100644
index af009e5..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/SmartcardServiceBootCompletedBroadcastReceiver.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.simalliance.openmobileapi.service;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.util.Log;
-
-public class SmartcardServiceBootCompletedBroadcastReceiver extends BroadcastReceiver {
- public final static String _TAG = "SmartcardService";
-
- @Override
- public void onReceive(Context context, Intent intent) {
- final boolean bootCompleted = intent.getAction().equals("android.intent.action.BOOT_COMPLETED");
- Log.v(_TAG, Thread.currentThread().getName() + " Received broadcast");
- if( bootCompleted ){
- Log.v(_TAG, "Starting smartcard service after boot completed");
- Intent serviceIntent = new Intent(context, org.simalliance.openmobileapi.service.SmartcardService.class );
- context.startService(serviceIntent);
- } else {
-
- }
- }
-};
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/Terminal.java b/smart-card-service/src/org/simalliance/openmobileapi/service/Terminal.java
deleted file mode 100644
index f309ab8..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/Terminal.java
+++ /dev/null
@@ -1,776 +0,0 @@
-/*
- * Copyright (C) 2011, The Android Open Source Project
- *
- * 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.
- */
-/*
- * Contributed by: Giesecke & Devrient GmbH.
- */
-
-package org.simalliance.openmobileapi.service;
-
-import android.content.Context;
-
-import org.simalliance.openmobileapi.service.ISmartcardServiceCallback;
-import org.simalliance.openmobileapi.service.SmartcardService.SmartcardServiceSession;
-
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.security.AccessControlException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.Random;
-
-import android.content.pm.PackageManager;
-
-import org.simalliance.openmobileapi.service.security.AccessControlEnforcer;
-import org.simalliance.openmobileapi.service.security.ChannelAccess;
-
-
-/**
- * Smartcard service base class for terminal resources.
- */
-public abstract class Terminal implements ITerminal {
-
- /** Random number generator used for handle creation. */
- static Random mRandom = new Random();
-
- protected Context mContext;
-
- private final Map<Long, IChannel> mChannels = new HashMap<Long, IChannel>();
-
- protected final String mType;
-
- protected int mIndex;
-
- private boolean mHasIndexBeenSet;
-
- public volatile boolean mIsConnected;
-
- protected byte[] mSelectResponse;
-
- protected boolean mDefaultApplicationSelectedOnBasicChannel = true;
-
- /**
- * For each Terminal there will be one AccessController object.
- */
- private AccessControlEnforcer mAccessControlEnforcer;
-
-
- /**
- * Returns a concatenated response.
- *
- * @param r1 the first part of the response.
- * @param r2 the second part of the response.
- * @param length the number of bytes of the second part to be appended.
- * @return a concatenated response.
- */
- static byte[] appendResponse(byte[] r1, byte[] r2, int length) {
- byte[] rsp = new byte[r1.length + length];
- System.arraycopy(r1, 0, rsp, 0, r1.length);
- System.arraycopy(r2, 0, rsp, r1.length, length);
- return rsp;
- }
-
- /**
- * Creates a formatted exception message.
- *
- * @param commandName the name of the command. <code>null</code> if not
- * specified.
- * @param sw the response status word.
- * @return a formatted exception message.
- */
- static String createMessage(String commandName, int sw) {
- StringBuffer message = new StringBuffer();
- if (commandName != null) {
- message.append(commandName).append(" ");
- }
- message.append("SW1/2 error: ");
- message.append(Integer.toHexString(sw | 0x10000).substring(1));
- return message.toString();
- }
-
- /**
- * Creates a formatted exception message.
- *
- * @param commandName the name of the command. <code>null</code> if not
- * specified.
- * @param message the message to be formatted.
- * @return a formatted exception message.
- */
- static String createMessage(String commandName, String message) {
- if (commandName == null) {
- return message;
- }
- return commandName + " " + message;
- }
-
- public Terminal(String type, Context context) {
- mContext = context;
- mType = type;
- mHasIndexBeenSet = false;
- }
-
- /**
- * This method is called in SmartcardService:onDestroy
- * to clean up all open channels.
- */
- public synchronized void closeChannels() {
- Collection<IChannel> col = mChannels.values();
- IChannel[] channelList = col.toArray(new IChannel[col.size()]);
- for (IChannel channel : channelList) {
- try {
- closeChannel((Channel) channel);
- } catch (Exception ignore) {
- }
- }
- }
-
- /**
- * Closes the specified channel.
- *
- * @param channel the channel to be closed.
- * @throws CardException if closing the channel failed.
- */
- public synchronized void closeChannel(Channel channel)
- throws CardException {
- try {
- internalCloseLogicalChannel(channel.getChannelNumber());
- } finally {
- mChannels.remove(channel.getHandle());
- if (mIsConnected && mChannels.isEmpty()) {
- try {
- internalDisconnect();
- } catch (Exception ignore) {
- }
- }
- }
- }
-
- /**
- * Creates a channel instance.
- *
- * @param channelNumber the channel number according to ISO 7816-4.
- * @param callback the callback used to detect the death of the client.
- * @return a channel instance.
- */
- protected Channel createChannel(
- SmartcardServiceSession session,
- int channelNumber,
- ISmartcardServiceCallback callback) {
- return new Channel(session, this, channelNumber, callback);
- }
-
- private IChannel getBasicChannel() {
- for (IChannel channel : mChannels.values()) {
- if (channel.getChannelNumber() == 0) {
- return channel;
- }
- }
- return null;
- }
-
- public synchronized IChannel getChannel(long hChannel) {
- return mChannels.get(hChannel);
- }
-
- @Override
- public String getName() {
- if (mHasIndexBeenSet) {
- return mType + mIndex;
- } else {
- return mType;
- }
- }
-
- @Override
- public String getType() {
- return mType;
- }
-
- @Override
- public final void setIndex(int index) {
- // Index can only be set once.
- if (!mHasIndexBeenSet) {
- mIndex = index;
- mHasIndexBeenSet = true;
- }
- }
- /**
- * Implements the terminal specific connect operation.
- *
- * @throws CardException if connecting the card failed.
- */
- protected abstract void internalConnect() throws CardException;
-
- /**
- * Implements the terminal specific disconnect operation.
- *
- * @throws CardException if disconnecting from the card failed.
- */
- protected abstract void internalDisconnect() throws CardException;
-
- /**
- * Implementation of the SELECT command.
- *
- * @return the number of the logical channel according to ISO 7816-4.
- *
- * @throws Exception If the channel could not be opened.
- */
- protected abstract int internalOpenLogicalChannel() throws Exception;
-
- /**
- * Implementation of the MANAGE CHANNEL open and SELECT commands.
- *
- * @param aid The aid of the applet to be selected.
- *
- * @return the number of the logical channel according to ISO 7816-4.
- *
- * @throws Exception If the channel could not be opened.
- */
- protected abstract int internalOpenLogicalChannel(byte[] aid)
- throws Exception;
-
- /**
- * Implementation of the MANAGE CHANNEL close command.
- *
- * @param channelNumber The channel to be closed.
- *
- * @throws CardException If the channel could not be closed.
- */
- protected abstract void internalCloseLogicalChannel(int channelNumber)
- throws CardException;
-
- /**
- * Implements the terminal specific transmit operation.
- *
- * @param command the command APDU to be transmitted.
- * @return the response APDU received.
- * @throws CardException if the transmit operation failed.
- */
- protected abstract byte[] internalTransmit(byte[] command)
- throws CardException;
-
- /**
- * Returns the ATR of the connected card or null if the ATR is not
- * available.
- *
- * @return the ATR of the connected card or null if the ATR is not
- * available.
- */
- public abstract byte[] getAtr();
-
- /**
- * Performs a select command on the basic channel without an AID parameter.
- * <br>
- * The card manager will be selected.
- */
- public void select() {
- mSelectResponse = null;
- byte[] selectCommand = new byte[5];
- selectCommand[0] = 0x00;
- selectCommand[1] = (byte) 0xA4;
- selectCommand[2] = 0x04;
- selectCommand[3] = 0x00;
- selectCommand[4] = 0x00;
- try {
- mSelectResponse = transmit(
- selectCommand, 2, 0x9000, 0xFFFF, "SELECT");
- } catch (Exception exp) {
- throw new NoSuchElementException(exp.getMessage());
- }
- }
-
- /**
- * Performs a select command on the basic channel.
- *
- * @param aid the aid which should be selected.
- */
- public void select(byte[] aid) {
- if (aid == null) {
- throw new NullPointerException("aid must not be null");
- }
- mSelectResponse = null;
- byte[] selectCommand = new byte[aid.length + 6];
- selectCommand[0] = 0x00;
- selectCommand[1] = (byte) 0xA4;
- selectCommand[2] = 0x04;
- selectCommand[3] = 0x00;
- selectCommand[4] = (byte) aid.length;
- System.arraycopy(aid, 0, selectCommand, 5, aid.length);
- try {
- // TODO: also accept 62XX and 63XX as valid SW
- mSelectResponse = transmit(
- selectCommand, 2, 0x9000, 0xFFFF, "SELECT");
- } catch (Exception exp) {
- throw new NoSuchElementException(exp.getMessage());
- }
- }
-
- @Override
- public synchronized Channel openBasicChannel(
- SmartcardServiceSession session,
- ISmartcardServiceCallback callback)
- throws CardException {
- if (callback == null) {
- throw new NullPointerException("callback must not be null");
- }
-
- if (!mDefaultApplicationSelectedOnBasicChannel) {
- throw new CardException("default application is not selected");
- }
- if (getBasicChannel() != null) {
- throw new CardException("basic channel in use");
- }
- if (mChannels.isEmpty()) {
- internalConnect();
- }
-
-
- Channel basicChannel = createChannel(session, 0, callback);
- basicChannel.hasSelectedAid(false, null);
- registerChannel(basicChannel);
- return basicChannel;
- }
-
- @Override
- public Channel openBasicChannel(
- SmartcardServiceSession session,
- byte[] aid,
- ISmartcardServiceCallback callback)
- throws Exception {
- if (callback == null) {
- throw new NullPointerException("callback must not be null");
- }
- if (aid == null) {
- throw new NullPointerException("aid must not be null");
- }
-
- if (getBasicChannel() != null) {
- throw new CardException("basic channel in use");
- }
- if (mChannels.isEmpty()) {
- internalConnect();
- }
-
- try {
- select(aid);
- } catch (Exception e) {
- if (mIsConnected && mChannels.isEmpty()) {
- internalDisconnect();
- }
- throw e;
- }
-
-
- Channel basicChannel = createChannel(session, 0, callback);
- basicChannel.hasSelectedAid(true, aid);
- mDefaultApplicationSelectedOnBasicChannel = false;
- registerChannel(basicChannel);
- return basicChannel;
- }
-
- @Override
- public synchronized Channel openLogicalChannel(
- SmartcardServiceSession session,
- ISmartcardServiceCallback callback)
- throws Exception {
- if (callback == null) {
- throw new NullPointerException("callback must not be null");
- }
-
- if (mChannels.isEmpty()) {
- internalConnect();
- }
-
- int channelNumber = 0;
- try {
- channelNumber = internalOpenLogicalChannel();
- } catch (Exception e) {
- if (mIsConnected && mChannels.isEmpty()) {
- internalDisconnect();
- }
- throw e;
- }
-
-
- Channel logicalChannel = createChannel(
- session, channelNumber, callback);
- logicalChannel.hasSelectedAid(false, null);
- registerChannel(logicalChannel);
- return logicalChannel;
- }
-
- @Override
- public synchronized Channel openLogicalChannel(
- SmartcardServiceSession session,
- byte[] aid,
- ISmartcardServiceCallback callback)
- throws Exception {
- if (callback == null) {
- throw new NullPointerException("callback must not be null");
- }
- if (aid == null) {
- throw new NullPointerException("aid must not be null");
- }
-
- if (mChannels.isEmpty()) {
- internalConnect();
- }
-
- int channelNumber = 0;
- try {
- channelNumber = internalOpenLogicalChannel(aid);
- } catch (Exception e) {
- if (mIsConnected && mChannels.isEmpty()) {
- internalDisconnect();
- }
- throw e;
- }
-
-
- Channel logicalChannel = createChannel(
- session, channelNumber, callback);
- logicalChannel.hasSelectedAid(true, aid);
- registerChannel(logicalChannel);
- return logicalChannel;
- }
-
- @Override
- public boolean isConnected() {
- return mIsConnected;
- }
-
- /**
- * Protocol specific implementation of the transmit operation. This method
- * is synchronized in order to handle GET RESPONSE and command repetition
- * without interruption by other commands.
- *
- * @param cmd the command to be transmitted.
- * @return the response received.
- * @throws CardException if the transmit operation failed.
- */
- protected synchronized byte[] protocolTransmit(byte[] cmd)
- throws CardException {
- byte[] command = cmd;
- byte[] rsp = null;
- rsp = internalTransmit(command);
-
- if (rsp.length >= 2) {
- int sw1 = rsp[rsp.length - 2] & 0xFF;
- int sw2 = rsp[rsp.length - 1] & 0xFF;
- if (sw1 == 0x6C) {
- command[cmd.length - 1] = rsp[rsp.length - 1];
- rsp = internalTransmit(command);
- } else if (sw1 == 0x61) {
- byte[] getResponseCmd = new byte[] {
- command[0], (byte) 0xC0, 0x00, 0x00, 0x00
- };
- byte[] response = new byte[rsp.length - 2];
- System.arraycopy(rsp, 0, response, 0, rsp.length - 2);
- while (true) {
- getResponseCmd[4] = rsp[rsp.length - 1];
- rsp = internalTransmit(getResponseCmd);
- if (rsp.length >= 2 && rsp[rsp.length - 2] == 0x61) {
- response = appendResponse(
- response, rsp, rsp.length - 2);
- } else {
- response = appendResponse(response, rsp, rsp.length);
- break;
- }
- }
- rsp = response;
- }
- }
- return rsp;
- }
-
- /**
- * Creates a handle for the specified channel instances and adds the channel
- * instance to the channel list.
- *
- * @param channel
- * @return the channel handle.
- */
- private long registerChannel(Channel channel) {
- long hChannel = mRandom.nextInt();
- hChannel <<= 32;
- hChannel |= (((long) channel.hashCode()) & 0xFFFFFFFFL);
-
- channel.setHandle(hChannel);
-
- mChannels.put(hChannel, channel);
-
- return hChannel;
- }
-
- /**
- * Transmits the specified command and returns the response. Optionally
- * checks the response length and the response status word. The status word
- * check is implemented as follows (sw = status word of the response):
- * <p>
- * if ((sw & swMask) != (swExpected & swMask)) throw new CardException();
- * </p>
- *
- * @param cmd the command APDU to be transmitted.
- * @param minRspLength the minimum length of received response to be
- * checked.
- * @param swExpected the response status word to be checked.
- * @param swMask the mask to be used for response status word comparison.
- * @param commandName the name of the smart card command for logging
- * purposes. May be <code>null</code>.
- * @return the response received.
- * @throws CardException if the transmit operation or the minimum response
- * length check or the status word check failed.
- */
- public synchronized byte[] transmit(
- byte[] cmd,
- int minRspLength,
- int swExpected,
- int swMask,
- String commandName)
- throws CardException {
- byte[] rsp = null;
- try {
- rsp = protocolTransmit(cmd);
- } catch (CardException e) {
- if (commandName == null) {
- throw e;
- } else {
- throw new CardException(
- createMessage(commandName, "transmit failed"), e);
- }
- }
- if (minRspLength > 0) {
- if (rsp == null || rsp.length < minRspLength) {
- throw new CardException(
- createMessage(commandName, "response too small"));
- }
- }
- if (swMask != 0) {
- if (rsp == null || rsp.length < 2) {
- throw new CardException(
- createMessage(commandName, "SW1/2 not available"));
- }
- int sw1 = rsp[rsp.length - 2] & 0xFF;
- int sw2 = rsp[rsp.length - 1] & 0xFF;
- int sw = (sw1 << 8) | sw2;
- if ((sw & swMask) != (swExpected & swMask)) {
- throw new CardException(createMessage(commandName, sw));
- }
- }
- return rsp;
- }
-
- @Override
- public byte[] getSelectResponse() {
- return mSelectResponse;
- }
-
- @Override
- public byte[] simIOExchange(int fileID, String filePath, byte[] cmd)
- throws Exception {
- throw new Exception("SIM IO error!");
- }
-
- @Override
- public ChannelAccess setUpChannelAccess(
- PackageManager packageManager,
- byte[] aid,
- String packageName,
- ISmartcardServiceCallback callback) {
- if (mAccessControlEnforcer == null) {
- throw new AccessControlException(
- "Access Control Enforcer not properly set up");
- }
- mAccessControlEnforcer.setPackageManager(packageManager);
- return mAccessControlEnforcer.setUpChannelAccess(
- aid, packageName, callback);
- }
-
- @Override
- public synchronized boolean initializeAccessControl(
- boolean loadAtStartup,
- ISmartcardServiceCallback callback) {
- if (mAccessControlEnforcer == null) {
- mAccessControlEnforcer = new AccessControlEnforcer(this);
- }
- return mAccessControlEnforcer.initialize(loadAtStartup, callback);
- }
-
- @Override
- public AccessControlEnforcer getAccessControlEnforcer() {
- return mAccessControlEnforcer;
- }
-
- @Override
- public synchronized void resetAccessControl() {
- if (mAccessControlEnforcer != null) {
- mAccessControlEnforcer.reset();
- }
- }
-
-
- /**
- * Implementation of the SmartcardService Reader interface according to
- * OMAPI.
- */
- final class SmartcardServiceReader extends ISmartcardServiceReader.Stub {
-
- protected final SmartcardService mService;
-
- private final ArrayList<SmartcardServiceSession> mSessions
- = new ArrayList<SmartcardServiceSession>();
-
- private final Object mLock = new Object();
-
- public SmartcardServiceReader( SmartcardService service ){
- this.mService = service;
- }
-
- public byte[] getAtr(){
- return Terminal.this.getAtr();
- }
-
- @Override
- public String getName(SmartcardError error) throws RemoteException {
- SmartcardService.clearError(error);
- return Terminal.this.getName();
- }
-
- @Override
- public boolean isSecureElementPresent(SmartcardError error)
- throws RemoteException {
- SmartcardService.clearError(error);
- try {
- return Terminal.this.isCardPresent();
- } catch (Exception e) {
- SmartcardService.setError(error, e);
- }
- return false;
- }
-
- @Override
- public ISmartcardServiceSession openSession(SmartcardError error)
- throws RemoteException {
- SmartcardService.clearError(error);
- try {
- if (!Terminal.this.isCardPresent()) {
- SmartcardService.setError(error,
- new IOException("Secure Element is not presented.")
- );
- return null;
- }
- } catch (CardException e) {
- SmartcardService.setError(error, e);
- return null;
- }
-
- synchronized (mLock) {
- try {
- mService.initializeAccessControl(Terminal.this.getName(), null);
- } catch (Exception e) {
- SmartcardService.setError(error, e);
- // Reader.openSession() will throw an IOException when
- // session is null
- return null;
- }
- SmartcardServiceSession session = mService.new SmartcardServiceSession(this);
- mSessions.add(session);
- return session;
- }
- }
-
- @Override
- public void closeSessions(SmartcardError error) throws RemoteException {
- SmartcardService.clearError(error);
- synchronized (mLock) {
- for (SmartcardServiceSession session : mSessions) {
- if (session != null && !session.isClosed()) {
- session.closeChannels(error);
- session.setClosed();
- }
- }
- mSessions.clear();
- }
- }
-
- /**
- * Closes the defined Session and all its allocated resources. <br>
- * After calling this method the Session can not be used for the
- * communication with the Secure Element any more.
- *
- * @param session the Session that should be closed
- * @throws RemoteException
- * @throws CardException
- * @throws NullPointerException if Session is null
- */
- synchronized void closeSession(SmartcardServiceSession session)
- throws RemoteException, CardException {
- if (session == null) {
- throw new NullPointerException("session is null");
- }
- if (!session.isClosed()) {
- SmartcardError error = new SmartcardError();
- session.closeChannels(error);
- error.throwException();
- session.setClosed();
- }
- mSessions.remove(session);
- }
-
-
- Terminal getTerminal() {
- return Terminal.this;
- }
- }
-
- public void dump(PrintWriter writer, String prefix) {
- writer.println(prefix + "SMARTCARD SERVICE TERMINAL: " + getName());
- writer.println();
-
- prefix += " ";
-
- writer.println(prefix + "mIsConnected:" + mIsConnected);
- writer.println();
-
- /* Dump the list of currunlty openned channels */
- writer.println(prefix + "List of open channels:");
-
- for (IChannel channel : mChannels.values()) {
- writer.println(prefix + " channel " + channel.getChannelNumber()
- + ": ");
- writer.println(prefix + " package : "
- + channel.getChannelAccess().getPackageName());
- writer.println(prefix + " pid : "
- + channel.getChannelAccess().getCallingPid());
- writer.println(prefix + " aid selected : "
- + channel.hasSelectedAid());
- writer.println(prefix + " basic channel: "
- + channel.isBasicChannel());
- }
-
- writer.println();
-
- /* Dump ACE data */
- if (mAccessControlEnforcer != null) {
- mAccessControlEnforcer.dump(writer, prefix);
- }
- }
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/Util.java b/smart-card-service/src/org/simalliance/openmobileapi/service/Util.java
deleted file mode 100644
index f72cd0a..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/Util.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2011, The Android Open Source Project
- *
- * 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.
- */
-/*
- * Contributed by: Giesecke & Devrient GmbH.
- */
-
-package org.simalliance.openmobileapi.service;
-
-public class Util {
-
- public static final byte END = -1;
- public static byte[] mergeBytes(byte[] array1, byte[] array2) {
- byte[] data = new byte[array1.length + array2.length];
- int i = 0;
- for (; i < array1.length; i++)
- data[i] = array1[i];
- for (int j = 0; j < array2.length; j++)
- data[j + i] = array2[j];
- return data;
- }
-
- public static byte[] getMid(byte[] array, int start, int length) {
- byte[] data = new byte[length];
- System.arraycopy(array, start, data, 0, length);
- return data;
- }
-
- public static String bytesToString(byte[] bytes) {
- if(bytes == null)
- return "";
- StringBuffer sb = new StringBuffer();
- for (byte b : bytes) {
- sb.append(String.format("%02x ", b & 0xFF));
- }
- String str = sb.toString();
- if (str.length() > 0) {
- str = str.substring(0, str.length() - 1);
- }
- return str;
- }
-
- public static String bytesToString(byte[] array,int offset,int length, String prefix) {
- if (array==null) return null;
- if (length==-1) length=array.length-offset;
-
- StringBuffer buffer=new StringBuffer();
- for (int ind=offset;ind<offset+length;ind++)
- buffer.append(prefix+Integer.toHexString(0x100+(array[ind] & 0xFF)).substring(1));
- return buffer.toString();
- }
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/AccessControlEnforcer.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/AccessControlEnforcer.java
deleted file mode 100644
index 9647f37..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/AccessControlEnforcer.java
+++ /dev/null
@@ -1,512 +0,0 @@
-/*
- * Copyright 2012 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.service.security;
-
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.Signature;
-import android.os.Build;
-import android.os.SystemProperties;
-import android.util.Log;
-
-import java.io.ByteArrayInputStream;
-import java.io.PrintWriter;
-import java.security.AccessControlException;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.MissingResourceException;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateFactory;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import org.simalliance.openmobileapi.service.CardException;
-import org.simalliance.openmobileapi.service.IChannel;
-import org.simalliance.openmobileapi.service.ISmartcardServiceCallback;
-import org.simalliance.openmobileapi.service.ITerminal;
-import org.simalliance.openmobileapi.service.SmartcardService;
-import org.simalliance.openmobileapi.service.Util;
-import org.simalliance.openmobileapi.service.security.ChannelAccess.ACCESS;
-import org.simalliance.openmobileapi.service.security.ara.AraController;
-
-import org.simalliance.openmobileapi.service.security.arf.ArfController;
-
-
-public class AccessControlEnforcer {
-
- private PackageManager mPackageManager = null;
-
- private AraController mAraController = null;
- private boolean mUseAra = true;
-
- private ArfController mArfController = null;
- private boolean mUseArf = false;
-
- private AccessRuleCache mAccessRuleCache = null;
- private boolean mRulesRead = false;
-
- private ITerminal mTerminal = null;
-
- private ChannelAccess mInitialChannelAccess = new ChannelAccess();
- private boolean mFullAccess = false;
-
- protected boolean[] mNfcEventFlags = null;
-
- private final String ACCESS_CONTROL_ENFORCER = "Access Control Enforcer: ";
-
- public AccessControlEnforcer( ITerminal terminal ) {
-
- mTerminal = terminal;
- mAccessRuleCache = new AccessRuleCache();
- }
-
- public PackageManager getPackageManager() {
- return mPackageManager;
- }
-
- public void setPackageManager(PackageManager packageManager) {
- this.mPackageManager = packageManager;
- }
-
- public ITerminal getTerminal(){
- return mTerminal;
- }
-
- public AccessRuleCache getAccessRuleCache(){
- return mAccessRuleCache;
- }
-
- public static byte[] getDefaultAccessControlAid(){
- return AraController.getAraMAid();
- }
-
- public synchronized void reset() {
- // Destroy any previous Controler
- // in order to reset the ACE
- Log.i(SmartcardService._TAG, "Reset the ACE for terminal:" + mTerminal.getName());
- mAraController = null;
- mArfController = null;
- }
-
- public synchronized boolean initialize(boolean loadAtStartup, ISmartcardServiceCallback callback) {
- try {
-
- boolean status = true;
- String denyMsg = "";
- // allow access to set up access control for a channel
- mInitialChannelAccess.setApduAccess(ChannelAccess.ACCESS.ALLOWED);
- mInitialChannelAccess.setNFCEventAccess(ChannelAccess.ACCESS.ALLOWED);
- mInitialChannelAccess.setAccess(ChannelAccess.ACCESS.ALLOWED, "");
-
- readSecurityProfile();
-
- if(!mTerminal.getName().startsWith(SmartcardService._UICC_TERMINAL)) {
- // When SE is not the UICC then it's allowed to grant full access if no
- // rules can be retreived.
- mFullAccess = true;
- }
-
- // 1 - Let's try to use ARA
- if( mUseAra && mAraController == null)
- mAraController = new AraController(this);
-
- if( mUseAra && mAraController != null ){
- try {
- mAraController.initialize(loadAtStartup, callback);
- // disable other access methods
-
- Log.i(SmartcardService._TAG, "ARA applet is used for:" + mTerminal.getName());
- mUseArf = false;
- mFullAccess = false;
-
- } catch( Exception e ) {
-
- // ARA cannot be used since we got an exception during initialization
- mUseAra = false;
- denyMsg = e.getLocalizedMessage();
-
- if( e instanceof MissingResourceException ) {
- if(mTerminal.getName().startsWith(SmartcardService._UICC_TERMINAL)) {
- // If the SE is a UICC then a possible explanation could simply
- // be due to the fact that the UICC is old and doesn't
- // support logical channel (and is not compliant with GP spec).
- // in this case we should simply act as if no ARA was available
- Log.w(SmartcardService._TAG, "Got MissingResourceException: Does the UICC support logical channel?");
- Log.w(SmartcardService._TAG, "Full message: " + e.getMessage());
- } else {
- // If the SE is not a UICC then this exception means that something
- // wrong has occured!
- throw new MissingResourceException( e.getMessage(), "", "");
- }
- } else if( mAraController.isNoSuchElement() ) {
- Log.i(SmartcardService._TAG, "No ARA applet found in: " + mTerminal.getName());
- } else {
- // ARA is available but doesn't work properly.
- // We are going to disable everything per security req.
- Log.i(SmartcardService._TAG, "AccessControlEnforcer - Problem accessing ARA, Access DENIED. " + e.getLocalizedMessage());
-
- // access is denied for any terminal if exception during accessing ARA has any other reason.
- mUseArf = false;
- mFullAccess = false;
- status = false;
- }
- }
- }
-
- // 2 - Let's try to use ARF since ARA cannot be used
- if(mUseArf && !mTerminal.getName().startsWith(SmartcardService._UICC_TERMINAL)) {
- Log.i(SmartcardService._TAG, "Disable ARF for terminal: " + mTerminal.getName() + " (ARF is only available for UICC)");
- mUseArf = false; // Arf is only supproted on UICC
- }
-
- if( mUseArf && mArfController == null)
- mArfController = new ArfController(this);
-
- if( mUseArf && mArfController != null) {
- try {
- mArfController.initialize(callback);
- // disable other access methods
- Log.i(SmartcardService._TAG, "ARF rules are used for:" + mTerminal.getName());
- mFullAccess = false;
- } catch( Exception e ) {
- // ARF cannot be used since we got an exception
- mUseArf = false;
- status = false;
- denyMsg = e.getLocalizedMessage();
- Log.e(SmartcardService._TAG, e.getMessage() );
- }
- }
-
- /* 3 - Let's grant full access since neither ARA nor ARF can be used */
- if(mFullAccess) {
- mInitialChannelAccess.setApduAccess(ChannelAccess.ACCESS.ALLOWED);
- mInitialChannelAccess.setNFCEventAccess(ChannelAccess.ACCESS.ALLOWED);
- mInitialChannelAccess.setAccess(ChannelAccess.ACCESS.ALLOWED, "");
-
- Log.i(SmartcardService._TAG, "Full access granted for:" + mTerminal.getName());
- }
-
- /* 4 - Let's block everything since neither ARA, ARF or fullaccess can be used */
- if(!mUseArf && !mUseAra && !mFullAccess) {
- mInitialChannelAccess.setApduAccess(ChannelAccess.ACCESS.DENIED);
- mInitialChannelAccess.setNFCEventAccess(ChannelAccess.ACCESS.DENIED);
- mInitialChannelAccess.setAccess(ChannelAccess.ACCESS.DENIED, denyMsg);
-
- Log.i(SmartcardService._TAG, "Deny any access to:" + mTerminal.getName());
- }
- mRulesRead = status;
- return status;
- } finally {
-
- }
- }
-
- public static Certificate decodeCertificate(byte[] certData) throws CertificateException {
- CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
- X509Certificate cert = (X509Certificate) certFactory
- .generateCertificate(new ByteArrayInputStream(certData));
-
- return cert;
- }
-
- public synchronized void checkCommand(IChannel channel, byte[] command) {
-
- ChannelAccess ca = channel.getChannelAccess();
- if (ca == null) {
-
- throw new AccessControlException(ACCESS_CONTROL_ENFORCER + "Channel access not set");
- }
-
- String reason = ca.getReason();
- if (reason.length() == 0) {
- reason = "Command not allowed!";
- }
-
- if (ca.getAccess() != ACCESS.ALLOWED ) {
-
- throw new AccessControlException(ACCESS_CONTROL_ENFORCER + reason);
- }
- if (ca.isUseApduFilter()) {
- ApduFilter[] accessConditions = ca.getApduFilter();
- if (accessConditions == null || accessConditions.length == 0) {
-
- throw new AccessControlException(ACCESS_CONTROL_ENFORCER + "Access Rule not available: " + reason);
- }
- for (ApduFilter ac : accessConditions) {
- if (CommandApdu.compareHeaders(command, ac.getMask(), ac.getApdu())) {
-
- return;
- }
- }
-
- throw new AccessControlException(ACCESS_CONTROL_ENFORCER + "Access Rule does not match: " + reason);
- }
- if (ca.getApduAccess() == ChannelAccess.ACCESS.ALLOWED) {
-
- return;
- } else {
-
- throw new AccessControlException(ACCESS_CONTROL_ENFORCER + "APDU access NOT allowed" );
- }
- }
-
- public ChannelAccess setUpChannelAccess(
- byte[] aid,
- String packageName,
- ISmartcardServiceCallback callback) {
- ChannelAccess channelAccess = null;
-
- // check result of channel access during initialization procedure
- if( mInitialChannelAccess.getAccess() == ChannelAccess.ACCESS.DENIED ){
- throw new AccessControlException( ACCESS_CONTROL_ENFORCER + "access denied: " + mInitialChannelAccess.getReason() );
- }
- // this is the new GP Access Control Enforcer implementation
- if( mUseAra || mUseArf ){
-
- try {
- channelAccess = internal_setUpChannelAccess(aid, packageName, callback);
- } catch( Exception e ) {
- if( e instanceof MissingResourceException ) {
- throw new MissingResourceException( ACCESS_CONTROL_ENFORCER + e.getMessage(), "", "");
- } else {
- // access is denied for any terminal if exception during accessing ARA has any other reason.
- throw new AccessControlException( ACCESS_CONTROL_ENFORCER + "access denied: " + e.getMessage() );
- }
- }
- }
-
- if( channelAccess == null || // precautionary check
- (channelAccess.getApduAccess() != ChannelAccess.ACCESS.ALLOWED &&
- channelAccess.isUseApduFilter() == false)) {
-
- if( this.mFullAccess == true ){
- // if full access is set then we reuse the initial channel access,
- // since we got so far it allows everything with a descriptive reason.
- channelAccess = mInitialChannelAccess;
- } else {
- throw new AccessControlException( ACCESS_CONTROL_ENFORCER + "no APDU access allowed!" );
- }
- }
-
- channelAccess.setPackageName(packageName);
-
- return channelAccess.clone();
- }
-
- private synchronized ChannelAccess internal_setUpChannelAccess(byte[] aid, String packageName,
- ISmartcardServiceCallback callback) {
-
- ChannelAccess channelAccess = new ChannelAccess();
- if (packageName == null || packageName.isEmpty()) {
- throw new AccessControlException("package names must be specified");
- }
- if (aid == null || aid.length == 0) {
- throw new AccessControlException("AID must be specified");
- }
- if (aid.length < 5 || aid.length > 16) {
- throw new AccessControlException("AID has an invalid length");
- }
-
- try {
- // estimate SHA-1 hash value of the device application's certificate.
- Certificate[] appCerts = getAPPCerts(packageName);
-
- // APP certificates must be available => otherwise Exception
- if (appCerts == null || appCerts.length == 0) {
- throw new AccessControlException("Application certificates are invalid or do not exist.");
- }
-
-
- channelAccess = getAccessRule(aid, appCerts, callback );
-
- } catch (Throwable exp) {
-
-
- throw new AccessControlException(exp.getMessage());
- }
-
- return channelAccess;
- }
-
- public ChannelAccess getAccessRule( byte[] aid, Certificate[] appCerts, ISmartcardServiceCallback callback ) throws AccessControlException, CardException, CertificateEncodingException {
-
- ChannelAccess channelAccess = null;
-
- // if read all is true get rule from cache.
- if( mRulesRead ){
- // get rules from internal storage
- channelAccess = mAccessRuleCache.findAccessRule( aid, appCerts );
- }
-
- // if no rule was found return an empty access rule
- // with all access denied.
- if( channelAccess == null ){
- channelAccess = new ChannelAccess();
- channelAccess.setAccess(ChannelAccess.ACCESS.DENIED, "no access rule found!" );
- channelAccess.setApduAccess(ChannelAccess.ACCESS.DENIED);
- channelAccess.setNFCEventAccess(ChannelAccess.ACCESS.DENIED);
- }
- return channelAccess;
- }
-
-
- /**
- * Returns Certificate chain for one package.
- *
- * @param packageName
- * @return
- * @throws CertificateException
- * @throws NoSuchAlgorithmException
- * @throws AccessControlException
- * @throws CardException
- */
- public Certificate[] getAPPCerts(String packageName)
- throws CertificateException, NoSuchAlgorithmException, AccessControlException {
-
- if(packageName == null || packageName.length() == 0)
- throw new AccessControlException("Package Name not defined");
-
- PackageInfo foundPkgInfo;
-
- try {
- foundPkgInfo = mPackageManager.getPackageInfo(packageName,
- PackageManager.GET_SIGNATURES);
- } catch (NameNotFoundException ne) {
- throw new AccessControlException("Package does not exist");
- }
-
- if (foundPkgInfo == null) {
- throw new AccessControlException("Package does not exist");
- }
-
- ArrayList<Certificate> appCerts = new ArrayList<Certificate>();
-
- for (Signature signature : foundPkgInfo.signatures) {
- appCerts.add(decodeCertificate(signature.toByteArray()));
- }
- return appCerts.toArray(new Certificate[appCerts.size()]);
- }
-
- public static byte[] getAppCertHash(Certificate appCert) throws CertificateEncodingException
- {
- /**
- * Note: This loop is needed in Android 2.3.
- * After a failed certificate verification in a previous step the
- * MessageDigest.getInstance("SHA") call will fail with the
- * AlgorithmNotSupported exception. But a second try will normally
- * succeed.
- */
- MessageDigest md = null;
- for (int i = 0; i < 10; i++) {
- try {
- md = MessageDigest.getInstance("SHA");
- break;
- } catch (Exception e) {
- }
- }
- if (md == null) {
- throw new AccessControlException("Hash can not be computed");
- }
- return md.digest(appCert.getEncoded());
- }
-
- public synchronized boolean[] isNFCEventAllowed(
- byte[] aid,
- String[] packageNames,
- ISmartcardServiceCallback callback)
- throws CardException
- {
- if( mUseAra || mUseArf ){
- return internal_isNFCEventAllowed(aid, packageNames, callback);
- } else {
- // 2012-09-27
- // if ARA and ARF is not available and terminal DOES NOT belong to a UICC -> mFullAccess is true
- // if ARA and ARF is not available and terminal belongs to a UICC -> mFullAccess is false
- boolean[] ret = new boolean[packageNames.length];
- for( int i = 0; i < ret.length; i++ ){
- ret[i] = this.mFullAccess;
- }
- return ret;
- }
- }
-
- private synchronized boolean[] internal_isNFCEventAllowed(byte[] aid,
- String[] packageNames,
- ISmartcardServiceCallback callback)
- throws CardException
- {
- // the NFC Event Flags boolean array is created and filled in internal_enableAccessConditions.
- mNfcEventFlags = new boolean[packageNames.length];
- int i=0;
- ChannelAccess channelAccess = null;
- for( String packageName : packageNames ) {
- // estimate SHA-1 hash value of the device application's certificate.
- Certificate[] appCerts;
- try {
- appCerts = getAPPCerts(packageName);
-
- // APP certificates must be available => otherwise Exception
- if (appCerts == null || appCerts.length == 0) {
- throw new AccessControlException("Application certificates are invalid or do not exist.");
- }
-
- channelAccess = getAccessRule(aid, appCerts, callback);
- mNfcEventFlags[i] = (channelAccess.getNFCEventAccess() == ChannelAccess.ACCESS.ALLOWED);
-
- } catch (Exception e) {
- Log.w(SmartcardService._TAG, " Access Rules for NFC: " + e.getLocalizedMessage());
- mNfcEventFlags[i] = false;
- }
- i++;
- }
- return mNfcEventFlags;
- }
-
-
- public void dump(PrintWriter writer, String prefix) {
- writer.println(prefix + SmartcardService._TAG + ":");
- prefix += " ";
-
- writer.println(prefix + "mUseArf: " + mUseArf);
- writer.println(prefix + "mUseAra: " + mUseAra);
- writer.println(prefix + "mInitialChannelAccess:");
- writer.println(prefix + " " + mInitialChannelAccess.toString());
- writer.println();
-
- /* Dump the access rule cache */
- if(mAccessRuleCache != null) mAccessRuleCache.dump(writer, prefix);
- }
-
- private void readSecurityProfile() {
- if(!Build.IS_DEBUGGABLE) {
- mUseArf = true;
- mUseAra = true;
- mFullAccess = false; // Per default we don't grant full access.
- } else {
- String level = SystemProperties.get("service.seek", "useara usearf");
- level = SystemProperties.get("persist.service.seek", level);
-
- if(level.contains("usearf")) mUseArf = true; else mUseArf = false;
- if(level.contains("useara")) mUseAra = true; else mUseAra = false;
- if(level.contains("fullaccess")) mFullAccess = true; else mFullAccess = false;
- }
- Log.i(SmartcardService._TAG, "Allowed ACE mode: ara=" + mUseAra + " arf=" + mUseArf + " fullaccess=" + mFullAccess );
- }
-
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/AccessFilterUtil.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/AccessFilterUtil.java
deleted file mode 100644
index b962015..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/AccessFilterUtil.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2012 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.service.security;
-
-import org.simalliance.openmobileapi.service.Util;
-
-
-
-public class AccessFilterUtil {
-
- public static ApduFilter[] parseAccessConditions(byte[] accessConditions) {
- if (accessConditions.length == 0) {
- return new ApduFilter[0];
- }
-
- if ((accessConditions.length % 8) != 0) {
- throw new IllegalArgumentException("Access Conditions must have a length of 8 bytes");
- }
-
- int numOfACs = accessConditions.length / 8;
- ApduFilter[] acs = new ApduFilter[numOfACs];
- int offset = 0;
- int length = 8;
- int index = 0;
- while ((offset + length) <= accessConditions.length && length != 0) {
- acs[index] = new ApduFilter(Util.getMid(accessConditions, offset, length));
- offset += length;
- index++;
- }
- return acs;
- }
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/AccessRuleCache.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/AccessRuleCache.java
deleted file mode 100644
index 7f573fb..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/AccessRuleCache.java
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
- * Copyright 2012 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.service.security;
-
-import java.io.PrintWriter;
-import java.security.AccessControlException;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateEncodingException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-
-import org.simalliance.openmobileapi.service.SmartcardService;
-import org.simalliance.openmobileapi.service.Util;
-import org.simalliance.openmobileapi.service.security.gpac.dataobjects.AID_REF_DO;
-import org.simalliance.openmobileapi.service.security.gpac.dataobjects.AR_DO;
-import org.simalliance.openmobileapi.service.security.gpac.dataobjects.Hash_REF_DO;
-import org.simalliance.openmobileapi.service.security.gpac.dataobjects.REF_DO;
-
-import android.util.Log;
-
-
-public class AccessRuleCache {
- // Previous "RefreshTag"
- // 2012-09-25
- // the refresh tag has to be valid as long as AxxController is valid
- // a pure static element would cause that rules are not read any longer once the AxxController is recreated.
- private byte[] mRefreshTag=null;
-
-
- private Map<REF_DO, ChannelAccess> mRuleCache = new HashMap<REF_DO, ChannelAccess>();
-
- /**
- * Clears access rule cache and refresh tag.
- */
- public void reset(){
- mRefreshTag = null;
- mRuleCache.clear();
- }
-
- /**
- * Clears access rule cache only.
- */
- public void clearCache(){
- mRuleCache.clear();
- }
-
- public ChannelAccess put(REF_DO ref_do_key, AR_DO ar_do) {
-
- ChannelAccess channelAccess = mapArDo2ChannelAccess( ar_do );
- this.mRuleCache.put(ref_do_key, channelAccess);
- return channelAccess;
- }
-
- public void putWithMerge( REF_DO ref_do, AR_DO ar_do ) {
-
- ChannelAccess channelAccess = mapArDo2ChannelAccess( ar_do );
- putWithMerge( ref_do, channelAccess );
- }
-
- public void putWithMerge( REF_DO ref_do, ChannelAccess channelAccess ) {
-
- if( mRuleCache.containsKey(ref_do)){
- ChannelAccess ca = mRuleCache.get(ref_do);
- Log.v(SmartcardService._TAG, "Access Rule with " + ref_do.toString() + " already exists.");
-
- // if new ac condition is more restrictive then use their settings
-
- // if new rule says NFC is denied then use it
- // if current rule as undefined NFC rule then use setting of new rule.
- // current NFC new NFC resulting NFC
- // UNDEFINED x x
- // ALLOWED !DENIED ALLOWED
- // ALLOWED DENIED DENIED
- // DENIED !DENIED DENIED
- // DENEID DENIED DENIED
- if( channelAccess.getNFCEventAccess() == ChannelAccess.ACCESS.DENIED ||
- ca.getNFCEventAccess() == ChannelAccess.ACCESS.UNDEFINED ) {
- ca.setNFCEventAccess(channelAccess.getNFCEventAccess());
- }
-
- // if new rule says APUD is denied then use it
- // if current rule as undefined APDU rule then use setting of new rule.
- // current APDU new APDU resulting APDU
- // UNDEFINED x x
- // ALLOWED !DENIED ALLOWED
- // ALLOWED DENIED DENIED
- // DENIED !DENIED DENIED
- // DENEID DENIED DENIED
- if( channelAccess.getApduAccess() == ChannelAccess.ACCESS.DENIED ||
- ca.getApduAccess() == ChannelAccess.ACCESS.UNDEFINED ) {
- ca.setApduAccess(channelAccess.getApduAccess());
- }
-
-
- // put APDU filter together if resulting APDU access is allowed.
- if( ca.getApduAccess() == ChannelAccess.ACCESS.ALLOWED ){
- if( channelAccess.isUseApduFilter() ){
- ca.setUseApduFilter(true);
- ApduFilter[] filter = ca.getApduFilter();
- ApduFilter[] filter2 = channelAccess.getApduFilter();
- if( filter == null || filter.length == 0 ){
- ca.setApduFilter(filter2);
- } else if( filter2 == null || filter2.length == 0){
- ca.setApduFilter(filter);
- } else {
- ApduFilter[] sum = new ApduFilter[filter.length + filter2.length];
- int i = 0;
- for( ApduFilter f : filter ){
- sum[i++] = f;
- }
- for( ApduFilter f : filter2 ){
- sum[i++] = f;
- }
- ca.setApduFilter(sum);
- }
- }
- } else {
- // if APDU access is not allowed the remove also all apdu filter
- ca.setUseApduFilter(false);
- ca.setApduFilter(null);
- }
- Log.v(SmartcardService._TAG, "Merged Access Rule: " + ca.toString());
- return;
- }
- mRuleCache.put(ref_do, channelAccess);
- }
-
-
- public ChannelAccess findAccessRule( byte[] aid, Certificate[] appCerts) throws AccessControlException {
-
-
-
- // TODO: check difference between DeviceCertHash and Certificate Chain (EndEntityCertHash, IntermediateCertHash (1..n), RootCertHash)
- // The DeviceCertificate is equal to the EndEntityCertificate.
- // The android systems seems always to deliver only the EndEntityCertificate, but this seems not to be sure.
- // thats why we implement the whole chain.
-
- AID_REF_DO aid_ref_do = getAidRefDo(aid);
- Hash_REF_DO hash_ref_do = null;
- REF_DO ref_do = null;
-
- // Search Rule A ( Certificate(s); AID )
- // walk through certificate chain.
- for( Certificate appCert : appCerts ){
-
- try {
- hash_ref_do = new Hash_REF_DO(AccessControlEnforcer.getAppCertHash(appCert));
- ref_do = new REF_DO(aid_ref_do, hash_ref_do);
-
- if( mRuleCache.containsKey( ref_do ) ){
- return mRuleCache.get( ref_do );
- }
- } catch (CertificateEncodingException e) {
- throw new AccessControlException("Problem with Application Certificate.");
- }
- }
- // no rule found,
- // now we have to check if the given AID
- // is used together with another specific hash value (another device application)
- if( searchForRulesWithSpecificAidButOtherHash(aid_ref_do) != null ){
- Log.v(SmartcardService._TAG, "Conflict Resolution Case A returning access rule \'NEVER\'.");
- ChannelAccess ca = new ChannelAccess();
- ca.setApduAccess(ChannelAccess.ACCESS.DENIED);
- ca.setAccess(ChannelAccess.ACCESS.DENIED, "AID has a specific access rule with a different hash. (Case A)");
- ca.setNFCEventAccess(ChannelAccess.ACCESS.DENIED);
- return ca;
- }
-
-
- // SearchRule B ( <AllDeviceApplications>; AID)
- aid_ref_do = getAidRefDo(aid);
- hash_ref_do = new Hash_REF_DO(); // empty hash ref
- ref_do = new REF_DO(aid_ref_do, hash_ref_do);
-
- if( mRuleCache.containsKey( ref_do ) ){
- return mRuleCache.get( ref_do );
- }
-
- // Search Rule C ( Certificate(s); <AllSEApplications> )
- aid_ref_do = new AID_REF_DO(AID_REF_DO._TAG);
- for( Certificate appCert : appCerts ){
- try {
- hash_ref_do = new Hash_REF_DO(AccessControlEnforcer.getAppCertHash(appCert));
- ref_do = new REF_DO(aid_ref_do, hash_ref_do);
-
- if( mRuleCache.containsKey( ref_do ) ){
- return mRuleCache.get( ref_do );
- }
- } catch (CertificateEncodingException e) {
- throw new AccessControlException("Problem with Application Certificate.");
- }
- }
-
- // no rule found,
- // now we have to check if the all AID DO
- // is used together with another Hash
- if( this.searchForRulesWithAllAidButOtherHash() != null ){
- Log.v(SmartcardService._TAG, "Conflict Resolution Case C returning access rule \'NEVER\'.");
- ChannelAccess ca = new ChannelAccess();
- ca.setApduAccess(ChannelAccess.ACCESS.DENIED);
- ca.setAccess(ChannelAccess.ACCESS.DENIED, "An access rule with a different hash and all AIDs was found. (Case C)");
- ca.setNFCEventAccess(ChannelAccess.ACCESS.DENIED);
- return ca;
- }
-
-
- // SearchRule D ( <AllDeviceApplications>; <AllSEApplications>)
- aid_ref_do = new AID_REF_DO(AID_REF_DO._TAG);
- hash_ref_do = new Hash_REF_DO();
- ref_do = new REF_DO(aid_ref_do, hash_ref_do);
-
- if( mRuleCache.containsKey( ref_do ) ){
- return mRuleCache.get( ref_do );
- }
- return null;
- }
-
- public static AID_REF_DO getAidRefDo( byte[] aid ){
- AID_REF_DO aid_ref_do = null;
- byte[] defaultAid = new byte[]{ 0x00, 0x00, 0x00, 0x00, 0x00 }; // this is the placeholder for the default aid.
-
- if( aid == null || Arrays.equals( aid, defaultAid )){
- aid_ref_do = new AID_REF_DO(AID_REF_DO._TAG_DEFAULT_APPLICATION);
- } else {
- aid_ref_do = new AID_REF_DO(AID_REF_DO._TAG, aid);
- }
-
- return aid_ref_do;
- }
-
- public static REF_DO buildHashMapKey( byte[] aid, byte[] appCertHash ){
- // Build key
- Hash_REF_DO hash_ref_do = new Hash_REF_DO(appCertHash) ;
- REF_DO ref_do = new REF_DO(getAidRefDo(aid), hash_ref_do);
-
- return ref_do;
- }
-
-
-
- /*
- * The GP_SE_AC spec says:
- * According to the rule conflict resolution process defined in section 3.2.1, if a specific rule exists
- * that associates another device application with the SE application identified by AID (e.g. there is
- * a rule associating AID with the hash of another device application), then the ARA-M (when
- * using GET DATA [Specific]) or the Access Control Enforcer (when using GET DATA [All]) shall
- * set the result of SearchRuleFor(DeviceApplicationCertificate, AID) to NEVER (i.e. precedence
- * of specific rules over generic rules)
- *
- * In own words:
- * Search the rules cache for a rule that contains the wanted AID but with another specific Hash value.
- */
- private REF_DO searchForRulesWithSpecificAidButOtherHash(AID_REF_DO aid_ref_do) {
-
- // AID has to be specific
- if( aid_ref_do == null ){
- return null;
- }
- // C0 00 is specific -> default AID
- // 4F 00 is NOT specific -> all AIDs
- if( aid_ref_do.getTag() == AID_REF_DO._TAG &&
- (aid_ref_do.getAid() == null || aid_ref_do.getAid().length == 0)){
- return null;
- }
-
- Set<REF_DO> keySet = mRuleCache.keySet();
- Iterator<REF_DO> iter = keySet.iterator();
- while(iter.hasNext()){
- REF_DO ref_do = iter.next();
- if( aid_ref_do.equals(ref_do.getAidDo())) {
- if( ref_do.getHashDo() != null &&
- ref_do.getHashDo().getHash() != null &&
- ref_do.getHashDo().getHash().length > 0 ){
- // this ref_do contains the search AID and a specific hash value
- return ref_do;
- }
- }
- }
- return null;
- }
-
- /*
- * The GP_SE_AC spec says:
- * According to the rule conflict resolution process defined in section 3.2.1, if a specific rule exists
- * that associates another device application with the SE application identified by AID (e.g. there is
- * a rule associating AID with the hash of another device application), then the ARA-M (when
- * using GET DATA [Specific]) or the Access Control Enforcer (when using GET DATA [All]) shall
- * set the result of SearchRuleFor(DeviceApplicationCertificate, AID) to NEVER (i.e. precedence
- * of specific rules over generic rules)
- *
- * In own words:
- * Search the rules cache for a rule that contains a Hash with an all SE AID (4F 00).
- */
- private Object searchForRulesWithAllAidButOtherHash() {
-
- AID_REF_DO aid_ref_do = new AID_REF_DO(AID_REF_DO._TAG);
-
- Set<REF_DO> keySet = mRuleCache.keySet();
- Iterator<REF_DO> iter = keySet.iterator();
- while(iter.hasNext()){
- REF_DO ref_do = iter.next();
- if( aid_ref_do.equals(ref_do.getAidDo())){
- // aid tlv is equal
- if( ref_do.getHashDo() != null &&
- (ref_do.getHashDo().getHash() != null && ref_do.getHashDo().getHash().length > 0)) {
- // return ref_do if
- // a HASH value is available and has a length > 0 (SHA1_LEN)
- return ref_do;
- }
- }
- }
- return null;
- }
-
- public static ChannelAccess mapArDo2ChannelAccess(AR_DO ar_do ){
- ChannelAccess channelAccess = new ChannelAccess();
-
- // check apdu access allowance
- if( ar_do.getApduArDo() != null ){
- // first if there is a rule for access, reset the general deny flag.
- channelAccess.setAccess(ChannelAccess.ACCESS.ALLOWED, "");
- channelAccess.setUseApduFilter(false);
-
- if( ar_do.getApduArDo().isApduAllowed() ){
- // check the apdu filter
- ArrayList<byte[]> apduHeaders = ar_do.getApduArDo().getApduHeaderList();
- ArrayList<byte[]> filterMasks = ar_do.getApduArDo().getFilterMaskList();
- if( apduHeaders != null &&
- filterMasks != null &&
- apduHeaders.size() > 0 &&
- apduHeaders.size() == filterMasks.size() ){
-
- ApduFilter[] accessConditions = new ApduFilter[apduHeaders.size()];
- for( int i = 0; i < apduHeaders.size(); i++){
- accessConditions[i] = new ApduFilter( apduHeaders.get(i), filterMasks.get(i));
- }
- channelAccess.setUseApduFilter(true);
- channelAccess.setApduFilter(accessConditions);
- } else {
- // general APDU access
- channelAccess.setApduAccess(ChannelAccess.ACCESS.ALLOWED);
- }
- } else {
- // apdu access is not allowed at all.
- channelAccess.setApduAccess(ChannelAccess.ACCESS.DENIED);
- }
- } else {
- channelAccess.setAccess(ChannelAccess.ACCESS.DENIED, "No APDU access rule available.!");
- }
-
- // check for NFC Event allowance
- if( ar_do.getNfcArDo() != null ){
- channelAccess.setNFCEventAccess(ar_do.getNfcArDo().isNfcAllowed() ? ChannelAccess.ACCESS.ALLOWED : ChannelAccess.ACCESS.DENIED);
- } else {
- // GP says that by default NFC should have the same right as for APDU access
- channelAccess.setNFCEventAccess(channelAccess.getApduAccess());
- }
- return channelAccess;
- }
-
- public boolean isRefreshTagEqual(byte[] refreshTag ) {
- if( refreshTag == null || mRefreshTag == null )
- return false;
-
- return Arrays.equals(refreshTag,mRefreshTag);
- }
-
- public byte[] getRefreshTag() {
- return mRefreshTag;
- }
-
- public void setRefreshTag(byte[] refreshTag) {
- this.mRefreshTag = refreshTag;
- }
-
-
- public void dump(PrintWriter writer, String prefix) {
- writer.println(prefix + SmartcardService._TAG + ":");
- prefix += " ";
-
- /* Dump the refresh tag */
- writer.print(prefix + "Current refresh tag is: ");
- if(mRefreshTag == null) writer.print("<null>");
- else for(byte oneByte: mRefreshTag) writer.printf("%02X:", oneByte);
- writer.println();
-
- /* Dump the rules cache */
- writer.println(prefix + "rules dump:");
- prefix += " ";
-
- int i = 0;
- for (Map.Entry<REF_DO, ChannelAccess> entry : mRuleCache.entrySet()) {
- i++;
- writer.print(prefix + "rule " + i + ": ");
- writer.println(entry.getKey().toString());
-
- writer.print(prefix + " ->");
- writer.println(entry.getValue().toString());
- }
-
- writer.println();
- }
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/ApduFilter.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/ApduFilter.java
deleted file mode 100644
index 3219506..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/ApduFilter.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright 2012 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.service.security;
-
-import org.simalliance.openmobileapi.service.Util;
-
-
-public class ApduFilter {
-
- protected byte[] mApdu;
-
- protected byte[] mMask;
-
- public static final int LENGTH = 8;
-
- protected ApduFilter() {
-
- }
-
- public ApduFilter(byte[] apdu, byte[] mask) {
- if (apdu.length != 4) {
- throw new IllegalArgumentException("apdu length must be 4 bytes");
- }
- if (mask.length != 4) {
- throw new IllegalArgumentException("mask length must be 4 bytes");
- }
-
- mApdu = apdu;
- mMask = mask;
- }
-
- public ApduFilter clone() {
- ApduFilter apduFilter = new ApduFilter();
- apduFilter.setApdu(mApdu.clone());
- apduFilter.setMask(mMask.clone());
-
- return apduFilter;
- }
-
- public ApduFilter(byte[] apduAndMask) {
- if (apduAndMask.length != 8) {
- throw new IllegalArgumentException("filter length must be 8 bytes");
- }
-
- mApdu = Util.getMid(apduAndMask, 0, 4);
- mMask = Util.getMid(apduAndMask, 4, 4);
- }
-
- public byte[] getApdu() {
- return mApdu;
- }
-
- public void setApdu(byte[] apdu) {
- if (apdu.length != 4) {
- throw new IllegalArgumentException("apdu length must be 4 bytes");
- }
- mApdu = apdu;
- }
-
- public byte[] getMask() {
- return mMask;
- }
-
- public void setMask(byte[] mask) {
- if (mask.length != 4) {
- throw new IllegalArgumentException("mask length must be 4 bytes");
- }
- mMask = mask;
- }
-
- public byte[] toBytes() {
- return Util.mergeBytes(mApdu, mMask);
- }
-
- @Override
- public String toString() {
- return "APDU Filter [apdu=" + Util.bytesToString(mApdu) + ", mask="
- + Util.bytesToString(mMask) + "]";
- }
-
- public int getLength() {
- return 8;
- }
-
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/ChannelAccess.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/ChannelAccess.java
deleted file mode 100644
index f075fb6..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/ChannelAccess.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright 2012 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.service.security;
-
-
-public class ChannelAccess {
-
- public enum ACCESS {
- ALLOWED, DENIED, UNDEFINED;
- }
-
- protected String CHANNEL_ACCESS_TAG = "ChannelAccess";
-
- protected String mPackageName = "";
-
- protected ACCESS mAccess = ACCESS.UNDEFINED;
-
- protected ACCESS mApduAccess = ACCESS.UNDEFINED;
-
- protected boolean mUseApduFilter = false;
-
- protected int mCallingPid = 0;
-
- protected String mReason = "no access by default";
-
- protected ACCESS mNFCEventAccess = ACCESS.UNDEFINED;
-
- protected ApduFilter[] mApduFilter = null;
-
- public ChannelAccess clone(){
- ChannelAccess ca = new ChannelAccess();
- ca.setAccess(this.mAccess, this.mReason);
- ca.setPackageName( this.mPackageName);
- ca.setApduAccess(this.mApduAccess);
- ca.setCallingPid(this.mCallingPid);
- ca.setNFCEventAccess(this.mNFCEventAccess);
- ca.setUseApduFilter(this.mUseApduFilter);
- if( this.mApduFilter != null ) {
- ApduFilter[] apduFilter = new ApduFilter[this.mApduFilter.length];
- int i = 0;
- for( ApduFilter filter : mApduFilter ){
- apduFilter[i++] = filter.clone();
- }
- ca.setApduFilter(apduFilter);
- } else {
- ca.setApduFilter(null);
- }
- return ca;
- }
-
- public String getPackageName(){
- return mPackageName;
- }
-
- public void setPackageName( String name ){
- this.mPackageName = name;
- }
-
- public ACCESS getApduAccess() {
- return mApduAccess;
- }
-
- public void setApduAccess(ACCESS apduAccess) {
- this.mApduAccess = apduAccess;
- }
-
-
- public ACCESS getAccess() {
- return mAccess;
- }
-
- public void setAccess(ACCESS access, String reason) {
- this.mAccess = access;
- this.mReason = reason;
- }
-
- public boolean isUseApduFilter() {
- return mUseApduFilter;
- }
-
- public void setUseApduFilter(boolean useApduFilter) {
- this.mUseApduFilter = useApduFilter;
- }
-
- public void setCallingPid(int callingPid) {
- this.mCallingPid = callingPid;
- }
-
- public int getCallingPid() {
- return mCallingPid;
- }
-
- public String getReason() {
- return mReason;
- }
- public ApduFilter[] getApduFilter() {
- return mApduFilter;
- }
-
- public void setApduFilter(ApduFilter[] accessConditions) {
- mApduFilter = accessConditions;
- }
- public ACCESS getNFCEventAccess() {
- return mNFCEventAccess;
- }
-
- public void setNFCEventAccess(ACCESS access) {
- this.mNFCEventAccess = access;
- }
-
- @Override
- public String toString(){
- StringBuilder sb = new StringBuilder();
- sb.append(this.getClass().getName());
- sb.append("\n [mPackageName=");
- sb.append(mPackageName);
- sb.append(", mAccess=");
- sb.append(mAccess);
- sb.append(", mApduAccess=");
- sb.append(mApduAccess);
- sb.append(", mUseApduFilter=");
- sb.append(mUseApduFilter);
- sb.append(", mApduFilter=");
- if( mApduFilter != null ){
- for( ApduFilter f : mApduFilter ){
- sb.append(f.toString());
- sb.append(" ");
- }
- } else {
- sb.append("null");
- }
- sb.append(", mCallingPid=");
- sb.append(mCallingPid);
- sb.append(", mReason=");
- sb.append(mReason);
- sb.append(", mNFCEventAllowed=");
- sb.append(mNFCEventAccess);
- sb.append("]\n");
-
- return sb.toString();
-
- }
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/CommandApdu.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/CommandApdu.java
deleted file mode 100644
index 2a9aecb..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/CommandApdu.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright 2010 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.service.security;
-
-public class CommandApdu {
-
- protected int mCla = 0x00;
-
- protected int mIns = 0x00;
-
- protected int mP1 = 0x00;
-
- protected int mP2 = 0x00;
-
- protected int mLc = 0x00;
-
- protected byte[] mData = new byte[0];
-
- protected int mLe = 0x00;
-
- protected boolean mLeUsed = false;
-
- public CommandApdu(int cla, int ins, int p1, int p2) {
- mCla = cla;
- mIns = ins;
- mP1 = p1;
- mP2 = p2;
- }
-
- public CommandApdu() {
-
- }
-
- public CommandApdu(int cla, int ins, int p1, int p2, byte[] data) {
- mCla = cla;
- mIns = ins;
- mLc = data.length;
- mP1 = p1;
- mP2 = p2;
- mData = data;
- }
-
- public CommandApdu(int cla, int ins, int p1, int p2, byte[] data, int le) {
- mCla = cla;
- mIns = ins;
- mLc = data.length;
- mP1 = p1;
- mP2 = p2;
- mData = data;
- mLe = le;
- mLeUsed = true;
- }
-
- public CommandApdu(int cla, int ins, int p1, int p2, int le) {
- mCla = cla;
- mIns = ins;
- mP1 = p1;
- mP2 = p2;
- mLe = le;
- mLeUsed = true;
- }
-
- public void setP1(int p1) {
- mP1 = p1;
- }
-
- public void setP2(int p2) {
- mP2 = p2;
- }
-
- public void setData(byte[] data) {
- mLc = data.length;
- mData = data;
- }
-
- public void setLe(int le) {
- mLe = le;
- mLeUsed = true;
- }
-
- public int getP1() {
- return mP1;
- }
-
- public int getP2() {
- return mP2;
- }
-
- public int getLc() {
- return mLc;
- }
-
- public byte[] getData() {
- return mData;
- }
-
- public int getLe() {
- return mLe;
- }
-
- public byte[] toBytes() {
- int length = 4; // CLA, INS, P1, P2
- if (mData.length != 0) {
- length += 1; // LC
- length += mData.length; // DATA
- }
- if (mLeUsed) {
- length += 1; // LE
- }
-
- byte[] apdu = new byte[length];
-
- int index = 0;
- apdu[index] = (byte) mCla;
- index++;
- apdu[index] = (byte) mIns;
- index++;
- apdu[index] = (byte) mP1;
- index++;
- apdu[index] = (byte) mP2;
- index++;
- if (mData.length != 0) {
- apdu[index] = (byte) mLc;
- index++;
- System.arraycopy(mData, 0, apdu, index, mData.length);
- index += mData.length;
- }
- if (mLeUsed) {
- apdu[index] += (byte) mLe; // LE
- }
-
- return apdu;
- }
-
- public static boolean compareHeaders(byte[] header1, byte[] mask, byte[] header2) {
- if (header1.length < 4 || header2.length < 4) {
- return false;
- }
- byte[] compHeader = new byte[4];
- compHeader[0] = (byte) (header1[0] & mask[0]);
- compHeader[1] = (byte) (header1[1] & mask[1]);
- compHeader[2] = (byte) (header1[2] & mask[2]);
- compHeader[3] = (byte) (header1[3] & mask[3]);
-
- if (((byte) compHeader[0] == (byte) header2[0])
- && ((byte) compHeader[1] == (byte) header2[1])
- && ((byte) compHeader[2] == (byte) header2[2])
- && ((byte) compHeader[3] == (byte) header2[3])) {
- return true;
- }
- return false;
- }
-
- public CommandApdu clone() {
- CommandApdu apdu = new CommandApdu();
- apdu.mCla = mCla;
- apdu.mIns = mIns;
- apdu.mP1 = mP1;
- apdu.mP2 = mP2;
- apdu.mLc = mLc;
- apdu.mData = new byte[mData.length];
- System.arraycopy(mData, 0, apdu.mData, 0, mData.length);
- apdu.mLe = mLe;
- apdu.mLeUsed = mLeUsed;
- return apdu;
- }
-
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/ResponseApdu.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/ResponseApdu.java
deleted file mode 100644
index 0672d4b..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/ResponseApdu.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 2010 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.service.security;
-
-import java.security.AccessControlException;
-
-public class ResponseApdu {
-
- protected int mSw1 = 0x00;
-
- protected int mSw2 = 0x00;
-
- protected byte[] mData = new byte[0];
-
- public ResponseApdu(byte[] respApdu) {
- if (respApdu.length < 2) {
- return;
- }
- if (respApdu.length > 2) {
- mData = new byte[respApdu.length - 2];
- System.arraycopy(respApdu, 0, mData, 0, respApdu.length - 2);
- }
- mSw1 = 0x00FF & respApdu[respApdu.length - 2];
- mSw2 = 0x00FF & respApdu[respApdu.length - 1];
-
- }
-
- public int getSW1() {
- return mSw1;
- }
-
- public int getSW2() {
- return mSw2;
- }
-
- public int getSW1SW2() {
- return (mSw1 << 8) | mSw2;
- }
-
- public byte[] getData() {
- return mData;
- }
-
- public void checkLengthAndStatus(int length, int sw1sw2, String message)
- throws AccessControlException {
- if (getSW1SW2() != sw1sw2 || mData.length != length) {
- throw new AccessControlException("ResponseApdu is wrong at " + message);
- }
- }
-
- public void checkLengthAndStatus(int length, int[] sw1sw2List, String message)
- throws AccessControlException {
- if (mData.length != length) {
- throw new AccessControlException("ResponseApdu is wrong at " + message);
- }
- for (int sw1sw2 : sw1sw2List) {
- if (getSW1SW2() == sw1sw2) {
- return; // sw1sw2 matches => return
- }
- }
- throw new AccessControlException("ResponseApdu is wrong at " + message);
- }
-
- public void checkStatus(int[] sw1sw2List, String message) throws AccessControlException {
- for (int sw1sw2 : sw1sw2List) {
- if (getSW1SW2() == sw1sw2) {
- return; // sw1sw2 matches => return
- }
- }
- throw new AccessControlException("ResponseApdu is wrong at " + message);
- }
-
- public void checkStatus(int sw1sw2, String message) throws AccessControlException {
- if (getSW1SW2() != sw1sw2) {
- throw new AccessControlException("ResponseApdu is wrong at " + message);
- }
- }
-
- public boolean isStatus(int sw1sw2) {
- if (getSW1SW2() == sw1sw2) {
- return true;
- }
- else {
- return false;
- }
- }
-
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/ara/AccessRuleApplet.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/ara/AccessRuleApplet.java
deleted file mode 100644
index 5b46741..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/ara/AccessRuleApplet.java
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright 2010 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.service.security.ara;
-
-
-import android.util.Log;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.security.AccessControlException;
-
-import org.simalliance.openmobileapi.service.CardException;
-import org.simalliance.openmobileapi.service.IChannel;
-import org.simalliance.openmobileapi.service.Util;
-import org.simalliance.openmobileapi.service.security.CommandApdu;
-import org.simalliance.openmobileapi.service.security.ResponseApdu;
-import org.simalliance.openmobileapi.service.security.gpac.dataobjects.BerTlv;
-import org.simalliance.openmobileapi.service.security.gpac.dataobjects.ParserException;
-import org.simalliance.openmobileapi.service.security.gpac.dataobjects.Response_DO_Factory;
-import org.simalliance.openmobileapi.service.security.gpac.dataobjects.Response_RefreshTag_DO;
-
-public class AccessRuleApplet {
-
- final private static String ACCESS_RULE_APPLET_TAG = "AccessRuleApplet";
-
- final private static int _MAX_LEN = 0xF0; // should be adapted by OEM, this is a defensive value since some devices/modems have problems with Le=0x00 or 0xFF.
-
- final private static CommandApdu mGetAll = new CommandApdu(0x80, 0xCA, 0xFF, 0x40, _MAX_LEN);
-
- final private static CommandApdu mGetSpecific = new CommandApdu(0x80, 0xCA, 0xFF, 0x50, _MAX_LEN);
-
- final private static CommandApdu mGetNext = new CommandApdu(0x80, 0xCA, 0xFF, 0x60, _MAX_LEN);
-
- final private static CommandApdu mGetRefreshTag = new CommandApdu(0x80, 0xCA, 0xDF, 0x20, _MAX_LEN );
-
-
- private IChannel mChannel = null;
-
- public AccessRuleApplet(IChannel channel) {
- mChannel = channel;
- }
-
- public byte[] readSpecificAccessRule( byte[] aid_ref_do ) throws AccessControlException, CardException {
-
- if( aid_ref_do == null ){
- throw new AccessControlException("GET DATA (specific): Reference data object must not be null.");
- }
-
- ByteArrayOutputStream stream = new ByteArrayOutputStream();
- int overallLen = 0;
-
- // send GET DATA (specific)
- CommandApdu apdu = (CommandApdu) mGetSpecific.clone();
- apdu.setData(aid_ref_do);
- ResponseApdu response = send(apdu);
-
- // OK
- if( response.isStatus( 0x9000 ) ) {
- // check if more data has to be fetched
- BerTlv tempTlv = null;
- try {
- tempTlv = BerTlv.decode(response.getData(), 0, false);
- } catch (ParserException e) {
- throw new AccessControlException("GET DATA (specific) not successfull. Tlv encoding wrong.");
- }
-
- // the first data block contain the length of the TLV + Tag bytes + length bytes.
- overallLen = tempTlv.getValueLength() + tempTlv.getValueIndex();
- try {
- stream.write(response.getData());
- } catch (IOException e) {
- throw new AccessControlException("GET DATA (specific) IO problem. " + e.getMessage() );
- }
-
- int le;
- // send subsequent GET DATA (next) commands
- while( stream.size() < overallLen ){
- le = overallLen - stream.size();
- if( le > _MAX_LEN ){
- le = _MAX_LEN;
- }
- // send GET DATA (next)
- apdu = (CommandApdu) mGetNext.clone();
- apdu.setLe(le);
- response = send(apdu);
-
- // OK
- if( response.isStatus( 0x9000 ) ){
- try {
- stream.write(response.getData());
- } catch (IOException e) {
- throw new AccessControlException("GET DATA (next) IO problem. " + e.getMessage() );
- }
- } else {
- throw new AccessControlException( "GET DATA (next) not successfull, . SW1SW2=" + response.getSW1SW2());
- }
- }
-
- return stream.toByteArray();
- // referenced data not found
- } else if( response.isStatus( 0x6A88 )){
- return null;
- } else {
- throw new AccessControlException("GET DATA (specific) not successfull. SW1SW2=" + response.getSW1SW2());
- }
- }
-
- public byte[] readAllAccessRules() throws AccessControlException, CardException {
-
- ByteArrayOutputStream stream = new ByteArrayOutputStream();
- int overallLen = 0;
-
- // send GET DATA (specific)
- CommandApdu apdu = (CommandApdu) mGetAll.clone();
- ResponseApdu response = send(apdu);
-
- // OK
- if( response.isStatus( 0x9000 ) ){
-
- // check if more data has to be fetched
- BerTlv tempTlv = null;
- try {
- tempTlv = BerTlv.decode(response.getData(), 0, false);
- } catch (ParserException e) {
- throw new AccessControlException("GET DATA (all) not successfull. Tlv encoding wrong.");
- }
-
- // the first data block contain the length of the TLV + Tag bytes + length bytes.
- overallLen = tempTlv.getValueLength() + tempTlv.getValueIndex();
-
-
- try {
- stream.write(response.getData());
- } catch (IOException e) {
- throw new AccessControlException("GET DATA (all) IO problem. " + e.getMessage() );
- }
-
- int le;
- // send subsequent GET DATA (next) commands
- while( stream.size() < overallLen ){
- le = overallLen - stream.size();
-
- if( le > _MAX_LEN ){
- le = _MAX_LEN;
- }
- // send GET DATA (next)
- apdu = (CommandApdu) mGetNext.clone();
- apdu.setLe(le);
-
- response = send(apdu);
- // OK
- if( response.isStatus( 0x9000 ) ) {
- try {
- stream.write(response.getData());
- } catch (IOException e) {
- throw new AccessControlException("GET DATA (next) IO problem. " + e.getMessage() );
- }
- } else {
- throw new AccessControlException( "GET DATA (next) not successfull, . SW1SW2=" + response.getSW1SW2());
- }
- }
-
- return stream.toByteArray();
- // referenced data not found
- } else if( response.isStatus( 0x6A88 )){
- return null;
- } else {
- throw new AccessControlException("GET DATA (all) not successfull. SW1SW2=" + response.getSW1SW2());
- }
- }
-
- public byte[] readRefreshTag() throws AccessControlException, CardException {
-
- // send GET DATA (specific)
- CommandApdu apdu = (CommandApdu) mGetRefreshTag.clone();
- ResponseApdu response = send(apdu);
-
- // OK
- if( response.isStatus( 0x9000 ) ){
-
- // check if more data has to be fetched
- BerTlv tempTlv = null;
- Response_RefreshTag_DO refreshDo;
- try {
- tempTlv = Response_DO_Factory.createDO(response.getData());
- if( tempTlv instanceof Response_RefreshTag_DO ) {
- refreshDo = (Response_RefreshTag_DO)tempTlv;
- return refreshDo.getRefreshTagArray();
- } else {
- throw new AccessControlException("GET REFRESH TAG returned invalid Tlv.");
- }
- } catch (ParserException e) {
- throw new AccessControlException("GET REFRESH TAG not successfull. Tlv encoding wrong.");
- }
- }
- throw new AccessControlException("GET REFRESH TAG not successfull.");
- }
-
- private ResponseApdu send(CommandApdu cmdApdu) throws CardException {
-
- byte[] response = mChannel.transmit(cmdApdu.toBytes());
-
- ResponseApdu resApdu = new ResponseApdu(response);
- return resApdu;
- }
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/ara/AraController.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/ara/AraController.java
deleted file mode 100644
index 423bdda..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/ara/AraController.java
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Copyright 2012 Giesecke & Devrient GmbH.
- *
- * 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.
- */
- /******************************************************************************
- *
- * The original Work has been changed by NXP Semiconductors.
- *
- * Copyright (C) 2015 NXP Semiconductors
- *
- * 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 org.simalliance.openmobileapi.service.security.ara;
-
-import android.util.Log;
-
-import java.security.AccessControlException;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-import java.util.MissingResourceException;
-
-import org.simalliance.openmobileapi.service.CardException;
-import org.simalliance.openmobileapi.service.IChannel;
-import org.simalliance.openmobileapi.service.ISmartcardServiceCallback;
-import org.simalliance.openmobileapi.service.ITerminal;
-import org.simalliance.openmobileapi.service.SmartcardService;
-import org.simalliance.openmobileapi.service.security.AccessControlEnforcer;
-import org.simalliance.openmobileapi.service.security.AccessRuleCache;
-import org.simalliance.openmobileapi.service.security.ChannelAccess;
-import org.simalliance.openmobileapi.service.security.gpac.dataobjects.BerTlv;
-import org.simalliance.openmobileapi.service.security.gpac.dataobjects.ParserException;
-import org.simalliance.openmobileapi.service.security.gpac.dataobjects.REF_AR_DO;
-import org.simalliance.openmobileapi.service.security.gpac.dataobjects.Response_ALL_AR_DO;
-import org.simalliance.openmobileapi.service.security.gpac.dataobjects.Response_DO_Factory;
-
-public class AraController {
-
- private AccessControlEnforcer mMaster = null;
- private AccessRuleCache mAccessRuleCache = null;
-
- private ITerminal mTerminal = null;
- private AccessRuleApplet mApplet = null;
-
-
- private boolean mNoSuchElement = false;
-
- private String ACCESS_CONTROL_ENFORCER_TAG = "ACE ARA";
-
- public static final byte[] ARA_M_AID = new byte[] {
- (byte)0xA0, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x51, (byte)0x41, (byte)0x43, (byte)0x4C,
- (byte)0x00 };
-
- public AraController(AccessControlEnforcer master ) {
- mMaster = master;
- mAccessRuleCache = mMaster.getAccessRuleCache();
- mTerminal = mMaster.getTerminal();
-
- }
-
- public boolean isNoSuchElement(){
- return mNoSuchElement;
- }
-
- public static byte[] getAraMAid() {
- return ARA_M_AID;
- }
-
- public synchronized boolean initialize(
- boolean loadAtStartup,
- ISmartcardServiceCallback callback)
- {
-
- IChannel channel = null;
- try {
- channel = this.handleOpenChannel(callback);
- } catch( MissingResourceException e ){
- channel = null;
- }
-
- if( channel == null ){
- throw new AccessControlException("could not open channel");
- }
-
- try {
- // set new applet handler since a new channel is used.
- mApplet = new AccessRuleApplet(channel);
- byte[] tag = mApplet.readRefreshTag();
- // if refresh tag is equal to the previous one it is not
- // neccessary to read all rules again.
- if( mAccessRuleCache.isRefreshTagEqual(tag)) {
- Log.d(ACCESS_CONTROL_ENFORCER_TAG, "Refresh tag has not changed. Using access rules from cache.");
- return false;
- }
- Log.d(ACCESS_CONTROL_ENFORCER_TAG, "Refresh tag has changed.");
- // set new refresh tag and empty cache.
- mAccessRuleCache.setRefreshTag(tag);
- mAccessRuleCache.clearCache();
-
- if( loadAtStartup ) {
- // Read content from ARA
- Log.d(ACCESS_CONTROL_ENFORCER_TAG, "Read ARs from ARA");
- this.readAllAccessRules();
- }
- } catch (Exception e) {
- Log.d(ACCESS_CONTROL_ENFORCER_TAG, "ARA error: " + e.getLocalizedMessage());
- throw new AccessControlException(e.getLocalizedMessage()); // Throw Exception
- } finally {
- if( channel != null )
- {
- closeChannel(channel);
- }
- }
- return true;
- }
-
- private IChannel handleOpenChannel( ISmartcardServiceCallback callback ){
- IChannel channel = null;
- String reason = "";
-
- try {
- channel = openChannel(mTerminal, getAraMAid(), callback);
- } catch (Exception e) {
- String msg = e.toString();
- msg = " ARA-M couldn't be selected: " + msg;
- Log.d(ACCESS_CONTROL_ENFORCER_TAG, msg);
- if (e instanceof NoSuchElementException) {
- mNoSuchElement = true;
- // SELECT failed
- // Access Rule Applet is not available => deny any access
- reason = " No Access because ARA-M is not available";
- Log.d(ACCESS_CONTROL_ENFORCER_TAG, msg );
- throw new AccessControlException(reason);
- } else if( e instanceof MissingResourceException ){
- // re-throw exception
- // fixes issue 23
- // this indicates that no channel is left for accessing the SE element
- Log.d(ACCESS_CONTROL_ENFORCER_TAG, "no channels left to access ARA-M: " + e.getMessage() );
- throw (MissingResourceException)e;
- } else {
- // MANAGE CHANNEL failed or general error
- // In order to be compliant with any UICC/SIM card on the market
- // we are going to ignore the error and says that the ARA-M is not available.
- // This not fully compliant with GP spec by required for mass compatibility.
- mNoSuchElement = true;
-
- reason = msg;
- Log.d(ACCESS_CONTROL_ENFORCER_TAG," ARA-M can not be accessed: " + msg);
- throw new AccessControlException(reason);
- }
- } // End of Exception handling
- return channel;
- }
-
-
- /**
- *
- * @return true if rules are read, false if not necessary or not available, but no error
- * @throws AccessControlException
- * @throws CardException
- */
- private boolean readAllAccessRules() throws AccessControlException, CardException {
-
- try {
- byte[] data = mApplet.readAllAccessRules();
- // no data returned, but no exception
- // -> no rule.
- if( data == null ) {
- return false;
- }
-
- BerTlv tlv = Response_DO_Factory.createDO( data );
- if( tlv == null ) {
- throw new AccessControlException("No valid data object found" );
- } if( tlv instanceof Response_ALL_AR_DO ){
-
- ArrayList<REF_AR_DO> array = ((Response_ALL_AR_DO)tlv).getRefArDos();
- if( array == null || array.size() == 0 ){
- return false; // no rules
- } else {
- Iterator<REF_AR_DO> iter = array.iterator();
- while( iter.hasNext() ){
- REF_AR_DO ref_ar_do = iter.next();
- this.mAccessRuleCache.putWithMerge(ref_ar_do.getRefDo(), ref_ar_do.getArDo());
- }
- }
- } else {
- throw new AccessControlException( "Applet returned invalid or wrong data object!");
- }
- } catch (ParserException e) {
- throw new AccessControlException("Parsing Data Object Exception: " + e.getMessage());
- }
- return true;
- }
-
- private IChannel openChannel(ITerminal terminal, byte[] aid, ISmartcardServiceCallback callback) throws Exception
- {
-
-
- IChannel channel = terminal.openLogicalChannel(null, aid, callback);
-
- // set access conditions to access ARA-M.
- ChannelAccess araChannelAccess = new ChannelAccess();
- araChannelAccess.setAccess(ChannelAccess.ACCESS.ALLOWED, ACCESS_CONTROL_ENFORCER_TAG);
- araChannelAccess.setApduAccess(ChannelAccess.ACCESS.ALLOWED);
- channel.setChannelAccess(araChannelAccess);
-
- return channel;
-}
-
- private void closeChannel(IChannel channel) {
- try {
- if (channel != null && channel.getChannelNumber() != 0) {
-
- channel.close();
-
- }
- } catch (CardException e) {
- }
- }
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/ASN1.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/ASN1.java
deleted file mode 100644
index 069205e..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/ASN1.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2011 Deutsche Telekom, A.G.
- *
- * 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 org.simalliance.openmobileapi.service.security.arf;
-
-/**
- * Defines all tags for parsing PKCS#15 files
- ***************************************************/
-public abstract class ASN1 {
-
- // ASN.1 tags
- public static final byte TAG_Sequence = 0x30;
- public static final byte TAG_OctetString = 0x04;
- public static final byte TAG_OID = 0x06;
-
- // EF_DIR tags
- public static final byte TAG_ApplTemplate = 0x61;
- public static final byte TAG_ApplIdentifier = 0x4F;
- public static final byte TAG_ApplLabel = 0x50;
- public static final byte TAG_ApplPath = 0x51;
- public static final byte TAG_FCP = 0x62;
-
- // Others tags
- public static final byte TAG_Padding = (byte)0xFF;
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/ArfController.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/ArfController.java
deleted file mode 100644
index d3292fd..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/ArfController.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2012 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.service.security.arf;
-
-import android.util.Log;
-
-import org.simalliance.openmobileapi.service.ISmartcardServiceCallback;
-import org.simalliance.openmobileapi.service.ITerminal;
-import org.simalliance.openmobileapi.service.SmartcardService;
-import org.simalliance.openmobileapi.service.security.AccessControlEnforcer;
-import org.simalliance.openmobileapi.service.security.AccessRuleCache;
-import org.simalliance.openmobileapi.service.security.arf.SecureElement;
-import org.simalliance.openmobileapi.service.security.arf.PKCS15.PKCS15Handler;
-
-public class ArfController {
-
- private PKCS15Handler mPkcs15Handler = null;
- private SecureElement mSecureElement = null;
-
- private AccessControlEnforcer mMaster = null;
- private AccessRuleCache mAccessRuleCache = null;
- private ITerminal mTerminal = null;
-
- public ArfController(AccessControlEnforcer master) {
- mMaster = master;
- mAccessRuleCache = mMaster.getAccessRuleCache();
- mTerminal = mMaster.getTerminal();
-
- }
-
- public synchronized boolean initialize(ISmartcardServiceCallback callback) {
-
-
- if( mSecureElement == null ){
- mSecureElement = new SecureElement(this, mTerminal);
- }
- if( mPkcs15Handler == null ) {
- mPkcs15Handler = new PKCS15Handler(mSecureElement);
- }
- return mPkcs15Handler.loadAccessControlRules(mTerminal.getName());
- }
-
-
-
- public AccessRuleCache getAccessRuleCache(){
- return mAccessRuleCache;
- }
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/DERParser.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/DERParser.java
deleted file mode 100644
index ec2e0e3..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/DERParser.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright (C) 2011 Deutsche Telekom, A.G.
- *
- * 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 org.simalliance.openmobileapi.service.security.arf;
-
-import android.util.Log;
-import java.util.Arrays;
-
-import org.simalliance.openmobileapi.service.security.arf.PKCS15.PKCS15Exception;
-
-/**
- * Base class for parsing PKCS#15 files
- ***************************************************/
-public class DERParser {
-
- public static final String TAG = "AccessControl";
- // DER parameters
- private byte[] mDERBuffer;
- private short mDERSize,mDERIndex,mTLVDataSize=0;
-
- /**
- * Returns "Base 128" encoded integer
- * @return Converted integer
- */
- private int readIntBase128() {
- int value=0;
- // If the MSb is set to 0, it is the last byte
- do {
- value=(value<<7) + (mDERBuffer[mDERIndex] & 0x7F);
- } while ((mDERBuffer[mDERIndex++]&0x80) != 0);
- return value;
- }
-
- /**
- * Returns size of the TLV encoded value
- * @return Size of the TLV
- */
- private short getTLVSize()
- throws PKCS15Exception {
- int size,TLVSize=0;
-
- if (isEndofBuffer())
- throw new PKCS15Exception("[Parser] Cannot retreive size");
- // Determine data size
- if ((TLVSize=(mDERBuffer[mDERIndex++] & 0xff))>=128) {
- size=TLVSize-128;
- for(TLVSize=0;size>0;size--) {
- if (!isEndofBuffer())
- TLVSize=(TLVSize<<8)+(mDERBuffer[mDERIndex++] & 0xff);
- else throw new PKCS15Exception("[Parser] Cannot retreive size");
- }}
-
- // Check if the buffer contains enough data
- if ((mDERIndex+TLVSize)>mDERSize)
- throw new PKCS15Exception("[Parser] Not enough data");
- return (short)TLVSize;
- }
-
- /**
- * Returns type of the TLV encoded value
- * @return Type of the TLV
- */
- private byte getTLVType()
- throws PKCS15Exception {
- if (isEndofBuffer())
- throw new PKCS15Exception("[Parser] Cannot retreive type");
- return mDERBuffer[mDERIndex++];
- }
-
-
- /**
- * Constructor
- * @param buffer file data
- */
- public DERParser(byte[] buffer)
- throws PKCS15Exception {
- mDERBuffer=buffer;
- mDERIndex=0; mDERSize=0;
- if (mDERBuffer==null) return;
- mDERSize=(short)mDERBuffer.length;
- mTLVDataSize=mDERSize;
-
- // Remove padding
- if (mDERSize==0) return;
- if (mDERBuffer[mDERIndex]==ASN1.TAG_Padding) {
- mTLVDataSize=0;
- while(++mDERIndex<mDERSize) {
- if (mDERBuffer[mDERIndex]!=ASN1.TAG_Padding)
- throw new PKCS15Exception("[Parser] Incorrect file format");
- }}}
-
- /**
- * Determines if we reached the end of the buffer
- * @return True if end of buffer is reached; False otherwise
- */
- public boolean isEndofBuffer()
- throws PKCS15Exception {
- if (mDERIndex==mDERSize) return true;
- if (mDERBuffer[mDERIndex]==ASN1.TAG_Padding) {
- // Remove padding
- while(++mDERIndex<mDERSize) {
- if (mDERBuffer[mDERIndex]!=ASN1.TAG_Padding)
- throw new PKCS15Exception("[Parser] Incorrect file format");
- } return true;
- } return false;
- }
-
- /**
- * Parses TLV from current index
- * @return Type of TLV structure
- */
- public byte parseTLV()
- throws PKCS15Exception {
- byte type=getTLVType();
- mTLVDataSize=getTLVSize();
- return type;
- }
-
- /**
- * Parses TLV from current index and check if type is correct
- * @param type Type required
- * @return Length of TLV data structure
- */
- public short parseTLV(byte type)
- throws PKCS15Exception {
- if (getTLVType()==type) {
- mTLVDataSize=getTLVSize();
- } else throw new PKCS15Exception("[Parser] Unexpected type");
- return mTLVDataSize;
- }
-
- /**
- * Skips data of the current TLV structure
- */
- public void skipTLVData() {
- mDERIndex+=mTLVDataSize;
- }
-
- /**
- * Returns data of the current TLV structure
- * @return Data of current TLV structure
- */
- public byte[] getTLVData() {
- byte[] data=Arrays.copyOfRange(mDERBuffer,mDERIndex,
- mDERIndex+mTLVDataSize);
- mDERIndex+=mTLVDataSize;
- return data;
- }
-
- /**
- * Takes snaptshot of the current context
- * @return Saved context
- */
- public short[] saveContext() {
- short[] context=new short[2];
- context[0]=mDERIndex; context[1]=mTLVDataSize;
- return context;
- }
-
- /**
- * Restores a context from a snapshot previously saved
- * @param context Context snapshot
- */
- public void restoreContext(short[] context)
- throws PKCS15Exception {
- if ((context==null)||(context.length!=2))
- throw new PKCS15Exception("[Parser] Invalid context");
- if ((context[0]<0)||(context[0]>mDERSize))
- throw new PKCS15Exception("[Parser] Index out of bound");
- mDERIndex=context[0]; mTLVDataSize=context[1];
- }
-
- /**
- * Parses standardized OID
- * @return String containing OID
- */
- public String parseOID()
- throws PKCS15Exception {
- if (parseTLV(ASN1.TAG_OID)==0)
- throw new PKCS15Exception("[Parser] OID Length is null");
-
- int end=mDERIndex+mTLVDataSize;
- StringBuffer oid=new StringBuffer();
-
- // First subidentifier
- int subid=readIntBase128();
- // The first subidentifier contains the first two OID components
- // X.Y is encoded as (X*40)+Y (0<=X<=2 and 0<=Y<=39 for X=0 or X=1)
- if (subid<=79)
- oid.append(subid/40).append('.').append(subid%40);
- else oid.append("2.").append(subid-80);
-
- while (mDERIndex< end)
- oid.append('.').append(readIntBase128());
- Log.d(TAG,"Found OID: "+oid.toString());
- return oid.toString();
- }
-
- /**
- * Parses PKCS#15 path attribute
- * @return Path retreived from the attribute
- */
- public byte[] parsePathAttributes()
- throws PKCS15Exception {
- parseTLV(ASN1.TAG_Sequence);
- parseTLV(ASN1.TAG_OctetString);
- return getTLVData();
- }
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/PKCS15/EF.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/PKCS15/EF.java
deleted file mode 100644
index bbd009a..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/PKCS15/EF.java
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Contributed by: Giesecke & Devrient GmbH.
- */
-
-package org.simalliance.openmobileapi.service.security.arf.PKCS15;
-
-import java.util.Arrays;
-
-import org.simalliance.openmobileapi.service.Util;
-import org.simalliance.openmobileapi.service.security.arf.ASN1;
-import org.simalliance.openmobileapi.service.security.arf.DERParser;
-import org.simalliance.openmobileapi.service.security.arf.SecureElement;
-import org.simalliance.openmobileapi.service.security.arf.SecureElementException;
-
-import android.util.Log;
-
-public class EF {
-
- public static final String TAG = "SmartcardService ACE ARF";
-
- public static final int APDU_SUCCESS = 0x9000;
- private static final int BUFFER_LEN = 253;
-
- // 2012-04-13
- private static final short EF = 0x04;
- private static final short TRANSPARENT = 0x00;
- private static final short LINEAR_FIXED = 0x01;
- private static final short UNKNOWN = 0xFF;
-
- // Selected file parameters
- private short mFileType = UNKNOWN,mFileStructure = UNKNOWN, mFileNbRecords;
- private int mFileID,mFileSize,mFileRecordSize;
- private String mFilePath;
-
-
- // Handle to "Secure Element" object
- protected SecureElement mSEHandle=null;
-
- public EF( SecureElement handle ){
- mSEHandle = handle;
- }
-
- public int getFileId(){
- return mFileID;
- }
- public String getFilePath(){
- return mFilePath;
- }
-
- private void decodeFileProperties(byte[] data )
- throws SecureElementException
- {
- if( data != null ){
- // check if first byte is the FCP tag
- // then do USIM decoding
- if( data[0] == 0x62 ){
- decodeUSIMFileProps(data);
- } else {
- // otherwise sim decoding
- decodeSIMFileProps(data);
- }
- }
- }
-
- /**
- * Decodes file properties (SIM cards)
- * @param data TS 51.011 encoded characteristics
- */
- private void decodeSIMFileProps(byte[] data)
- throws SecureElementException
- {
- if ((data==null)||(data.length<15))
- throw new SecureElementException("Invalid Response data");
-
- // 2012-04-13
- // check type of file
- if( (short)(data[6] & 0xFF) == (short)0x04 ){
- mFileType = EF;
- } else {
- mFileType = UNKNOWN; // may also be DF or MF, but we are not interested in them.
- }
- if( (short)(data[13]&0xFF) == (short)0x00 ) {
- mFileStructure = TRANSPARENT;
- } else if( (short)(data[13]&0xFF) == (short)0x01 ) {
- mFileStructure = LINEAR_FIXED;
- } else {
- mFileStructure = UNKNOWN; // may also be cyclic
- }
- mFileSize=((data[2] & 0xFF)<<8)|(data[3] & 0xFF);
-
- // check if file is cyclic or linear fixed
- if (mFileType == EF && // is EF ?
- mFileStructure != TRANSPARENT ) {
- mFileRecordSize=data[14] & 0xFF;
- mFileNbRecords=(short)(mFileSize/mFileRecordSize);
- }
- }
-
- /**
- * Decodes file properties (USIM cards)
- * @param data TLV encoded characteristics
- */
- private void decodeUSIMFileProps(byte[] data)
- throws SecureElementException
- {
- try {
- byte[] buffer=null;
- DERParser DER=new DERParser(data);
-
- DER.parseTLV(ASN1.TAG_FCP);
- while(!DER.isEndofBuffer()) {
- switch(DER.parseTLV()) {
- case (byte)0x80: // File size
- buffer=DER.getTLVData();
- if ((buffer!=null)&&(buffer.length>=2))
- mFileSize=((buffer[0] & 0xFF)<<8)|(buffer[1] & 0xFF);
- break;
- case (byte)0x82: // File descriptor
- buffer=DER.getTLVData();
- if ((buffer!=null)&&(buffer.length>=2)) {
- if( (short)(buffer[0] & 0x07) == (short)0x01 ) {
- mFileStructure = TRANSPARENT;
- } else if( (short)(buffer[0] & 0x07) == (short)0x02 ) {
- mFileStructure = LINEAR_FIXED;
- } else {
- mFileStructure = UNKNOWN; // may also be cyclic
- }
-
- // check if bit 4,5,6 are set
- // then this is a DF or ADF, but we mark it with UNKNOWN,
- // since we are only interested in EFs.
- if( (short)(buffer[0] & 0x38) == (short)0x38 ) {
- mFileType=UNKNOWN;
- } else {
- mFileType=EF;
- }
- if (buffer.length==5) {
- mFileRecordSize=buffer[3] & 0xFF;
- mFileNbRecords=(short)(buffer[4] & 0xFF);
- }
- } break;
- default:
- DER.skipTLVData(); break;
- }
- }
- } catch(Exception e) {
- throw new SecureElementException("Invalid GetResponse");
- }
- }
-
-
- /**
- * Selects a file (INS 0xA4)
- * @param path Path of the file
- * @return Command status code [sw1 sw2]
- */
- public int selectFile(byte[] path)
- throws SecureElementException
- {
- if ((path==null) || (path.length==0) || ((path.length%2)!=0))
- throw new SecureElementException("Incorrect path");
-
- int index;
- int length=path.length;
- if ((mSEHandle.getSeInterface() == SecureElement.SIM_IO)&&(length>2)) {
- index=length-2; // Only FileID is usefull
- mFilePath=Util.bytesToString(path,0,index,"");
- } else {
- index=0;
- mFilePath="";
- }
-
-
- byte[] data=null;
- byte[] cmd= new byte[]{ 0x00,(byte)0xA4,0x00,0x04,0x02,0x00,0x00 };
-
- mFileType=UNKNOWN;
- mFileStructure = UNKNOWN;
- mFileSize=0;
- mFileRecordSize=0;
- mFileNbRecords=0;
-
- // iterate through path
- for(int sw1;index<length;index+=2) {
- mFileID=((path[index]&0xFF)<<8) | (path[index+1] & 0xFF);
- cmd[5]=(byte)(mFileID>>8);
- cmd[6]=(byte)mFileID;
-
- data=mSEHandle.exchangeAPDU( this, cmd);
-
- // Check ADPU status
- sw1=data[data.length-2] & 0xFF;
- if ( (sw1!=0x62) &&
- (sw1!=0x63) &&
- (sw1!=0x90) &&
- (sw1!=0x91) )
- {
- return (sw1<<8) | (data[data.length-1] & 0xFF);
- }
- }
-
- // Analyse file properties
- decodeFileProperties(data);
-
- if (mFileNbRecords==0)
- Log.d(TAG,"SelectFile ["+mFileSize+"b]");
- else
- Log.d(TAG,"SelectFile ["+mFileNbRecords+"*"+mFileRecordSize+"b]");
- return APDU_SUCCESS;
- }
-
- /**
- * Reads data from the current selected file (INS 0xB0)
- * @param offset Offset at which to start reading
- * @param nbBytes Number of bytes to read
- * @return Data retreived from the file
- */
- public byte[] readBinary(int offset,int nbBytes)
- throws SecureElementException {
- if (mFileSize==0) return null;
- if (nbBytes==-1) nbBytes=mFileSize;
- if (mFileType != EF)
- throw new SecureElementException("Incorrect file type");
- if (mFileStructure != TRANSPARENT )
- throw new SecureElementException("Incorrect file structure");
-
- int length,pos=0;
- byte[] result=new byte[nbBytes];
- byte[] cmd={ 0x00,(byte)0xB0,0x00,0x00,0x00 };
-
- while (nbBytes!=0) {
- if (nbBytes<BUFFER_LEN)
- length=nbBytes;
- else
- length=BUFFER_LEN; // Set to max buffer size
-
- Log.d(TAG,"ReadBinary ["+offset+".."+length+"b]");
-
- cmd[2]=(byte)(offset>>8);
- cmd[3]=(byte)offset;
- cmd[4]=(byte)length;
- System.arraycopy(mSEHandle.exchangeAPDU(this, cmd),0,result,pos,length);
- nbBytes-=length; offset+=length; pos+=length;
- }
- return result;
- }
-
- /**
- * Reads a record from the current selected file (INS 0xB2)
- * @param record Record ID [0..n]
- * @return Data from requested record
- */
- public byte[] readRecord(short record)
- throws SecureElementException {
- // Check the type of current selected file
- if (mFileType != EF)
- throw new SecureElementException("Incorrect file type");
- if (mFileStructure != LINEAR_FIXED)
- throw new SecureElementException("Incorrect file structure");
-
- // Check if requested record is valid
- if ((record<0) || (record>mFileNbRecords))
- throw new SecureElementException("Incorrect record number");
-
- Log.d(TAG,"ReadRecord ["+record+"/"+mFileRecordSize+"b]");
- byte[] cmd= { 0x00,(byte)0xB2,(byte)record,0x04,(byte)mFileRecordSize };
-
- return Arrays.copyOf(mSEHandle.exchangeAPDU(this, cmd),mFileRecordSize);
- }
-
- /**
- * Returns the number of records in the current selected file
- * @return Number of records [0..n]
- */
- public short getFileNbRecords()
- throws SecureElementException {
- // Check the type of current selected file
- if (mFileNbRecords<0)
- throw new SecureElementException("Incorrect file type");
- return mFileNbRecords;
- }
-
-
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/PKCS15/EFACConditions.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/PKCS15/EFACConditions.java
deleted file mode 100644
index 7c29304..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/PKCS15/EFACConditions.java
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * Copyright (C) 2011 Deutsche Telekom, A.G.
- *
- * 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.
- */
-
-/*
- * Contributed by: Giesecke & Devrient GmbH.
- */
-
-package org.simalliance.openmobileapi.service.security.arf.PKCS15;
-
-import android.util.Log;
-
-import java.util.Vector;
-
-import org.simalliance.openmobileapi.service.security.ApduFilter;
-import org.simalliance.openmobileapi.service.security.ChannelAccess;
-import org.simalliance.openmobileapi.service.security.arf.ASN1;
-import org.simalliance.openmobileapi.service.security.arf.DERParser;
-import org.simalliance.openmobileapi.service.security.arf.SecureElement;
-import org.simalliance.openmobileapi.service.SmartcardService;
-import org.simalliance.openmobileapi.service.Util;
-import org.simalliance.openmobileapi.service.security.arf.PKCS15.PKCS15Exception;
-import org.simalliance.openmobileapi.service.security.gpac.dataobjects.AID_REF_DO;
-import org.simalliance.openmobileapi.service.security.gpac.dataobjects.Hash_REF_DO;
-
-/**
- * EF_ACConditions related features
- ***************************************************/
-public class EFACConditions extends EF {
-
- public static final String TAG = "ACE ARF EF_ACConditions";
-
- // Identification of the cardlet
- private AID_REF_DO mAid_Ref_Do=null;
-
- private byte[] mData = null;
-
-
- /**
- * Constructor
- * @param secureElement SE on which ISO7816 commands are applied
- * @param AID Identification of the applet
- */
- public EFACConditions(SecureElement handle,AID_REF_DO Aid_Ref_Do) {
- super( handle );
-
- mAid_Ref_Do=Aid_Ref_Do;
- }
-
- /**
- * Decodes EF_ACConditions file
- * @param buffer ASN.1 data
- */
- private void decodeDER(byte[] buffer)
- throws PKCS15Exception
- {
-
- byte[] certificateHash=null;
- DERParser DER=new DERParser(buffer);
-
- // the default channelAccess will deny every access.
- ChannelAccess channelAccess = new ChannelAccess();
- Hash_REF_DO hash_ref_do = new Hash_REF_DO();
-
- // empty condition file
- if (DER.isEndofBuffer()) {
- mSEHandle.putAccessRule(mAid_Ref_Do, hash_ref_do, channelAccess);
- return;
- }
-
- //----
- // 2012-04-16
- /*
- Condition ::= SEQUENCE {
- cert CertHash OPTIONAL,
- accessRules [0]AccessRules OPTIONAL
- }
-
- AccessRules ::= SEQUENCE OF AccessRule
-
- AccessRule ::=CHOICE {
- apduAccessRule [0]APDUAccessRule,
- nfcAccessRule [1]NFCAccessRule
- }
-
- APDUAccessRule ::= CHOICE {
- apduPermission [0] APDUPermission,
- apduFilter [1] APDUFilter
- }
-
- APDUFilters ::= SEQUENCE OF APDUFilter
-
- NFCAccessRule ::= CHOICE {
- nfcPermission [0] NFCPermission
- }
- */
- while(!DER.isEndofBuffer()) {
-
- // if a hash value was found then access is allowed
- // even if NO more access rule is given.
- // missing APDU Permission will always allow APDU access
- // missing NFC Permission will always allow NFC event.
- // See GPAC Chapter 7.1.7
- // See Examples in Annex C of GPAC
- channelAccess = new ChannelAccess();
- channelAccess.setAccess(ChannelAccess.ACCESS.ALLOWED, "");
- channelAccess.setApduAccess(ChannelAccess.ACCESS.ALLOWED);
- channelAccess.setNFCEventAccess(ChannelAccess.ACCESS.ALLOWED);
- channelAccess.setUseApduFilter(false);
-
- if ( DER.parseTLV(ASN1.TAG_Sequence) > 0 ) { // Check for 0x30
- DERParser derRule = new DERParser( DER.getTLVData());
- short[] context = null;
- try {
-
- context = derRule.saveContext();
- derRule.parseTLV(ASN1.TAG_OctetString); // Check for 0x04 which is used for cert hash, throws exception if not found
- certificateHash=derRule.getTLVData();
-
- if (certificateHash.length!=Hash_REF_DO._SHA1_LEN &&
- certificateHash.length!=0) {
- // other hash than SHA-1 hash values are not supported.
- throw new PKCS15Exception("Invalid hash found!");
- } else {
- hash_ref_do =new Hash_REF_DO(certificateHash);
- }
- } catch ( PKCS15Exception e ) {
-
- // cert hash is OPTIONAL so TAG_OctetString might be missing
- // this means this access condiction applies to any device application.
- hash_ref_do =new Hash_REF_DO();
-
- // if a context could be stored, restore it so that we can continue parsing...
- if( context != null ){
-
- derRule.restoreContext(context);
- }
- }
-
- // 2012-04-16
- // parse optional Access Rule.
- if( !derRule.isEndofBuffer() ) {
-
- if( derRule.parseTLV() == (byte)0xA0 ) {
-
-
- DERParser derAccessRules = new DERParser(derRule.getTLVData());
-
- while(!derAccessRules.isEndofBuffer()) {
- switch( derAccessRules.parseTLV() ){
- // APDU Access Rule
- case (byte)0xA0:
-
- DERParser derApduRule = new DERParser( derAccessRules.getTLVData());
- byte tagApduAccessRule = derApduRule.parseTLV();
-
-
- if( tagApduAccessRule == (byte)0x80 ) { // APDU Permission (primitive)
-
- channelAccess.setApduAccess(
- derApduRule.getTLVData()[0] == 0x01 ? ChannelAccess.ACCESS.ALLOWED : ChannelAccess.ACCESS.DENIED);
-
- } else if( tagApduAccessRule == (byte)0xA1 ) { // APDU Filter (constructed)
-
- DERParser derApduFilter = new DERParser( derApduRule.getTLVData() );
- byte tag = derApduFilter.parseTLV();
-
- if( tag == ASN1.TAG_OctetString ) {
-
- Vector<ApduFilter> apduFilter = new Vector<ApduFilter>();
-
- // collect all apdu filter tlvs.
- apduFilter.add(new ApduFilter( derApduFilter.getTLVData()));
-
- while( !derApduFilter.isEndofBuffer()) {
- if( derApduFilter.parseTLV() == ASN1.TAG_OctetString ) {
- apduFilter.add(new ApduFilter( derApduFilter.getTLVData()));
- }
- }
- channelAccess.setUseApduFilter(true);
- channelAccess.setApduFilter(apduFilter.toArray(new ApduFilter[apduFilter.size()]));
- } else {
- throw new PKCS15Exception("Invalid element found!");
- }
-
- } else {
- throw new PKCS15Exception("Invalid element found!");
- }
- break;
- // NFC Access Rule
- case (byte)0xA1:
-
- DERParser derNfc = new DERParser(derAccessRules.getTLVData());
-
- if( derNfc.parseTLV() == (byte)0x80 ) { // NFC Permission (primitive)
-
- channelAccess.setNFCEventAccess(
- derNfc.getTLVData()[0] == (byte)0x01 ? ChannelAccess.ACCESS.ALLOWED : ChannelAccess.ACCESS.DENIED);
- } else {
- throw new PKCS15Exception("Invalid element found!");
- }
- break;
- default:
- throw new PKCS15Exception("Invalid element found!");
- }
- }
- } else {
- // no explicit access rule given.
- }
- }
- } else {
- // coding 30 00 -> empty hash value given (all applications)
- }
- //----
-
- mSEHandle.putAccessRule(mAid_Ref_Do, hash_ref_do, channelAccess);
- } ;
- }
-
-
- /**
- * Stores a restricted list of certificate hashes
- * @param path Path of the "EF_ACConditions" file
- */
- public void addRestrictedHashes(byte[] path) {
- try {
- Log.v(TAG,"Reading and analysing EF_ACConditions...");
- if (selectFile(path) == APDU_SUCCESS) {
- mData = readBinary(0,Util.END);
- decodeDER(mData);
- } else {
- Log.e(TAG,"EF_ACConditions not found!");
- }
- } catch (Exception e) {
- /*Nothing to do*/
- Log.e( TAG, "Exception: " + e.getMessage());
- }
- }
-
- /**
- * Stores a restricted list of certificate hashes
- * @param path Path of the "EF_ACConditions" file
- */
- public void addRestrictedHashesFromData(byte[] data) {
- try {
- Log.v(TAG,"Analysing cached EF_ACConditions data...");
- if( data != null ) {
- mData = data;
- decodeDER(mData);
- } else {
- Log.e(TAG,"EF_ACConditions data not available!");
- }
- } catch (Exception e) {
- /*Nothing to do*/
- Log.e( TAG, "Exception: " + e.getMessage());
- }
- }
-
- public byte[] getData() {
- return mData;
- }
-
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/PKCS15/EFACMain.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/PKCS15/EFACMain.java
deleted file mode 100644
index aa6adbe..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/PKCS15/EFACMain.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2011 Deutsche Telekom, A.G.
- *
- * 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.
- */
-
-/*
- * Contributed by: Giesecke & Devrient GmbH.
- */
-
-package org.simalliance.openmobileapi.service.security.arf.PKCS15;
-
-import android.util.Log;
-import java.util.Arrays;
-
-import org.simalliance.openmobileapi.service.security.arf.ASN1;
-import org.simalliance.openmobileapi.service.security.arf.DERParser;
-import org.simalliance.openmobileapi.service.security.arf.SecureElement;
-import org.simalliance.openmobileapi.service.security.arf.SecureElementException;
-import org.simalliance.openmobileapi.service.Util;
-import org.simalliance.openmobileapi.service.security.arf.PKCS15.PKCS15Exception;
-
-/**
- * EF_ACMain related features
- ***************************************************/
-public class EFACMain extends EF {
-
- public static final String TAG = "ACE ARF EF_ACMain";
- // Length of the "RefreshTag"
- public static final short REFRESH_TAG_LEN=8;
-
- // "EF Access Control Main" path
- private byte[] mACMainPath=null;
-
- /**
- * Decodes EF_ACMain file
- * @param buffer ASN.1 data
- * @return Path to "Access Control Rules"
- */
- private byte[] decodeDER(byte[] buffer)
- throws PKCS15Exception
- {
- DERParser DER=new DERParser(buffer);
- DER.parseTLV(ASN1.TAG_Sequence);
- if (DER.parseTLV(ASN1.TAG_OctetString)!=REFRESH_TAG_LEN)
- throw new PKCS15Exception("[Parser] RefreshTag length not valid");
-
- byte[] refreshTag=DER.getTLVData();
- if (!Arrays.equals(refreshTag,this.mSEHandle.getRefreshTag())) {
- mSEHandle.setRefreshTag(refreshTag);
- return DER.parsePathAttributes();
- }
- return null; // RefreshTag not updated
- }
-
-
- /**
- * Constructor
- * @param secureElement SE on which ISO7816 commands are applied
- */
- public EFACMain(SecureElement handle,byte[] path) {
- super(handle);
- mACMainPath=path;
- }
-
- /**
- * Selects and Analyses EF_ACMain file
- * @return Path to "EF_ACRules" if "RefreshTag" has been updated;
- * <code>null</code> otherwise
- */
- public byte[] analyseFile()
- throws PKCS15Exception,SecureElementException
- {
- Log.v(TAG,"Analysing EF_ACMain...");
- byte[] path = mACMainPath;
-
- /*
- // 2012-04-12
- // extend path if ODF path was determined from EF DIR.
- if( mSEHandle.getPKCS15Path() != null ) {
- path = new byte[mSEHandle.getPKCS15Path().length + mACMainPath.length];
- System.arraycopy(mSEHandle.getPKCS15Path(), 0, path, 0, mSEHandle.getPKCS15Path().length);
- System.arraycopy(mACMainPath, 0, path, mSEHandle.getPKCS15Path().length, mACMainPath.length );
- }
- //---
- *
- */
-
- if ( selectFile(path) != APDU_SUCCESS) {
- throw new PKCS15Exception("EF_ACMain not found!");
- }
- return decodeDER(readBinary(0,Util.END));
- }
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/PKCS15/EFACRules.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/PKCS15/EFACRules.java
deleted file mode 100644
index cc25cba..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/PKCS15/EFACRules.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2011 Deutsche Telekom, A.G.
- *
- * 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.
- */
-
-/*
- * Contributed by: Giesecke & Devrient GmbH.
- */
-
-package org.simalliance.openmobileapi.service.security.arf.PKCS15;
-
-import android.util.Log;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.simalliance.openmobileapi.service.Util;
-import org.simalliance.openmobileapi.service.security.arf.ASN1;
-import org.simalliance.openmobileapi.service.security.arf.DERParser;
-import org.simalliance.openmobileapi.service.security.arf.SecureElement;
-import org.simalliance.openmobileapi.service.security.arf.SecureElementException;
-import org.simalliance.openmobileapi.service.security.arf.PKCS15.EFACConditions;
-import org.simalliance.openmobileapi.service.security.arf.PKCS15.PKCS15Exception;
-import org.simalliance.openmobileapi.service.security.gpac.dataobjects.AID_REF_DO;
-
-/**
- * EF_ACRules related features
- ***************************************************/
-public class EFACRules extends EF {
-
- public static final String TAG = "ACE ARF EF_ACRules";
- // AID used to store rules for default application
- public static final byte[] DEFAULT_APP = new byte[0];
-
- protected Map<String, byte[]> mAcConditionDataCache = new HashMap<String, byte[]>();
-
-
- /**
- * Decodes EF_ACRules file
- * @param buffer ASN.1 data
- */
- private void decodeDER(byte[] buffer)
- throws PKCS15Exception
- {
- byte[] AID=null;
- DERParser DER=new DERParser(buffer);
-
- // mapping to GPAC data objects
- int tag = 0;
-
- while(!DER.isEndofBuffer()) {
- DER.parseTLV(ASN1.TAG_Sequence);
- switch(DER.parseTLV()) {
- case (byte)0xA0: // Restricted AID
- DER.parseTLV(ASN1.TAG_OctetString);
- AID=DER.getTLVData();
- tag = AID_REF_DO._TAG;
- break;
- case (byte)0x81: // Rules for default Application
- AID=null;
- tag = AID_REF_DO._TAG_DEFAULT_APPLICATION;
- break;
- case (byte)0x82: // Rules for default case
- AID=DEFAULT_APP;
- tag = AID_REF_DO._TAG;
- break;
- default:
- throw new PKCS15Exception("[Parser] Unexpected ACRules entry");
- }
- byte[] path = DER.parsePathAttributes();
-
- // 2012-09-04
- // optimization of reading EF ACCondition
- if( path != null ){
- String pathString = Util.bytesToString(path);
- EFACConditions temp = new EFACConditions(mSEHandle,new AID_REF_DO(tag, AID ));
- // check if EF was already read before
- if( this.mAcConditionDataCache.containsKey(pathString )){
- // yes, then reuse data
- temp.addRestrictedHashesFromData(this.mAcConditionDataCache.get(pathString));
- } else {
- // no, read EF and add to rules cache
- temp.addRestrictedHashes(path);
- if( temp.getData() != null ){
- // if data are read the put it into cache.
- this.mAcConditionDataCache.put(pathString, temp.getData());
- }
- }
- }
- }
- }
-
- /**
- * Constructor
- * @param secureElement SE on which ISO7816 commands are applied
- */
- public EFACRules(SecureElement handle) {
- super( handle );
- }
-
- /**
- * Selects and Analyses EF_ACRules file
- * @param path Path of the "EF_ACRules" file
- */
- public void analyseFile(byte[] path)
- throws PKCS15Exception,SecureElementException {
-
- Log.v(TAG,"Analysing EF_ACRules...");
-
- // clear EF AC Condition data cache.
- mAcConditionDataCache.clear();
-
- if ( selectFile(path)!= APDU_SUCCESS)
- throw new PKCS15Exception("EF_ACRules not found!!");
-
- try {
- decodeDER( readBinary(0,Util.END));
- } catch(PKCS15Exception e) {
- throw e;
- }}
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/PKCS15/EFDIR.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/PKCS15/EFDIR.java
deleted file mode 100644
index 0ea08af..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/PKCS15/EFDIR.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2011 Deutsche Telekom, A.G.
- *
- * 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 org.simalliance.openmobileapi.service.security.arf.PKCS15;
-
-import android.util.Log;
-import java.util.Arrays;
-
-import org.simalliance.openmobileapi.service.security.arf.ASN1;
-import org.simalliance.openmobileapi.service.security.arf.DERParser;
-import org.simalliance.openmobileapi.service.security.arf.SecureElement;
-import org.simalliance.openmobileapi.service.security.arf.SecureElementException;
-import org.simalliance.openmobileapi.service.security.arf.PKCS15.PKCS15Exception;
-
-/**
- * EF_DIR related features
- ***************************************************/
-public class EFDIR extends EF{
-
- public static final String TAG = "ACE ARF EF_Dir";
- // Standardized ID for EF_DIR file
- public static final byte[] EFDIR_PATH = { 0x3F,0x00,0x2F,0x00 };
-
-
- /**
- * Decodes EF_DIR file
- * @param buffer ASN.1 data
- * @param AID Record key to search for
- * @return Path to "EF_ODF" when an expected record is found;
- * <code>null</code> otherwise
- */
- private byte[] decodeDER(byte[] buffer,byte[] AID)
- throws PKCS15Exception {
- DERParser DER=new DERParser(buffer);
- DER.parseTLV(ASN1.TAG_ApplTemplate);
- // Application Identifier
- DER.parseTLV(ASN1.TAG_ApplIdentifier);
- if (!Arrays.equals(DER.getTLVData(),AID))
- return null; // Record for another AID
-
- // Application Label or Application Path
- byte objectType=DER.parseTLV();
- if (objectType==ASN1.TAG_ApplLabel) {
- // Application Label [Optional]
- DER.getTLVData();
- DER.parseTLV(ASN1.TAG_ApplPath);
- } else if (objectType!=ASN1.TAG_ApplPath)
- throw new PKCS15Exception("[Parser] Application Tag expected");
- // Application Path
- return DER.getTLVData();
- }
-
-
- /**
- * Constructor
- * @param secureElement SE on which ISO7816 commands are applied
- */
- public EFDIR(SecureElement handle) {
- super(handle);
- }
-
- /**
- * Analyses DIR file and lookups for AID record
- * @param AID Record key to search for
- * @return Path to "EF_ODF" when an expected record is found;
- * <code>null</code> otherwise
- */
- public byte[] lookupAID(byte[] AID) throws PKCS15Exception,SecureElementException {
- Log.v(TAG,"Analysing EF_DIR...");
-
- if (selectFile(EFDIR_PATH)!= APDU_SUCCESS)
- throw new PKCS15Exception("EF_DIR not found!!");
-
- byte[] data,ODFPath=null;
- short index=1;
- while(index<=getFileNbRecords()) {
- data=readRecord(index++);
- if ((ODFPath=decodeDER(data,AID))!=null)
- break;
- }
- return ODFPath;
- }
-
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/PKCS15/EFDODF.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/PKCS15/EFDODF.java
deleted file mode 100644
index 9da26f3..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/PKCS15/EFDODF.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2011 Deutsche Telekom, A.G.
- *
- * 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 org.simalliance.openmobileapi.service.security.arf.PKCS15;
-
-import org.simalliance.openmobileapi.service.security.arf.ASN1;
-import org.simalliance.openmobileapi.service.security.arf.DERParser;
-import org.simalliance.openmobileapi.service.security.arf.SecureElement;
-import org.simalliance.openmobileapi.service.security.arf.SecureElementException;
-import org.simalliance.openmobileapi.service.Util;
-import org.simalliance.openmobileapi.service.security.arf.PKCS15.PKCS15Exception;
-
-import android.util.Log;
-
-/**
- * EF_DODF related features
- ***************************************************/
-public class EFDODF extends EF{
-
- public static final String TAG = "ACE ARF EF_DODF";
- // OID defined by Global Platform for the "Access Control"
- public static final String AC_OID = "1.2.840.114283.200.1.1";
-
- /**
- * Decodes EF_DODF file
- * @param buffer ASN.1 data
- * @return Path to "Access Control Main" from "Access Control" OID;
- * <code>null</code> otherwise
- */
- private byte[] decodeDER(byte[] buffer)
- throws PKCS15Exception {
- byte objectType;
- short[] context=null;
- DERParser DER=new DERParser(buffer);
-
- while(!DER.isEndofBuffer()) {
- if (DER.parseTLV()==(byte)0xA1) { // OidDO Data Object
- // Common Object Attributes
- DER.parseTLV(ASN1.TAG_Sequence);
- DER.skipTLVData();
- // Common Data Object Attributes
- DER.parseTLV(ASN1.TAG_Sequence);
- DER.skipTLVData();
-
- objectType=DER.parseTLV();
- if (objectType==(byte)0xA0) { // SubClassAttributes [Optional]
- DER.skipTLVData();
- objectType=DER.parseTLV();
- }
- if (objectType==(byte)0xA1) { // OidDO
- DER.parseTLV(ASN1.TAG_Sequence);
- context=DER.saveContext();
- if (DER.parseOID().compareTo(AC_OID)!=0) {
- DER.restoreContext(context);
- DER.skipTLVData();
- } else return DER.parsePathAttributes();
- } else throw new PKCS15Exception("[Parser] OID Tag expected");
- } else DER.skipTLVData();
- }
- return null; // No "Access Control" OID found
- }
-
-
- /**
- * Constructor
- * @param secureElement SE on which ISO7816 commands are applied
- */
- public EFDODF(SecureElement handle) {
- super(handle);
- }
-
- /**
- * Selects and Analyses EF_DODF file
- * @param path Path of the "EF_DODF" file
- * @return Path to "EF_ACMain" from "Access Control" OID;
- * <code>null</code> otherwise
- */
- public byte[] analyseFile(byte[] path)
- throws PKCS15Exception,SecureElementException
- {
- Log.v(TAG,"Analysing EF_DODF...");
-
- if (selectFile(path)!=APDU_SUCCESS)
- throw new PKCS15Exception("EF_DODF not found!");
-
- return decodeDER(readBinary(0,Util.END));
- }
-
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/PKCS15/EFODF.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/PKCS15/EFODF.java
deleted file mode 100644
index bf6cfe0..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/PKCS15/EFODF.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2011 Deutsche Telekom, A.G.
- *
- * 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.
- */
-
-/*
- * Contributed by: Giesecke & Devrient GmbH.
- */
-
-package org.simalliance.openmobileapi.service.security.arf.PKCS15;
-
-import org.simalliance.openmobileapi.service.security.arf.DERParser;
-import org.simalliance.openmobileapi.service.security.arf.SecureElement;
-import org.simalliance.openmobileapi.service.security.arf.SecureElementException;
-import org.simalliance.openmobileapi.service.Util;
-import org.simalliance.openmobileapi.service.security.arf.PKCS15.PKCS15Exception;
-
-import android.util.Log;
-
-/**
- * EF_ODF related features
- ***************************************************/
-public class EFODF extends EF {
-
- public static final String TAG = "SmartcardService ACE ARF";
- // Standardized ID for EF_ODF file
- public static final byte[] EFODF_PATH = { 0x50,0x31 };
-
- /**
- * Decodes EF_ODF file
- * @param buffer ASN.1 data
- * @return Path to "EF_DODF" from "DODF Tag" entry;
- * <code>null</code> otherwise
- */
- private byte[] decodeDER(byte[] buffer)
- throws PKCS15Exception {
- DERParser DER=new DERParser(buffer);
- while(!DER.isEndofBuffer()) {
- if (DER.parseTLV()==(byte)0xA7) { // DODF
- return DER.parsePathAttributes();
- } else DER.skipTLVData();
- } return null; // No "DODF Tag" entry found
- }
-
-
- /**
- * Constructor
- * @param secureElement SE on which ISO7816 commands are applied
- */
- public EFODF(SecureElement handle) {
- super(handle);
- }
-
- /**
- * Selects and Analyses EF_ODF file
- * @return Path to "EF_DODF" from "DODF Tag" entry;
- * <code>null</code> otherwise
- */
- public byte[] analyseFile( byte[] pkcs15Path ) throws PKCS15Exception,SecureElementException {
- Log.v(TAG,"Analysing EF_ODF...");
-
-
- // 2012-04-12
- // extend path if ODF path was determined from EF DIR.
- byte[] path = null;
- if( pkcs15Path != null ){
- path = new byte[pkcs15Path.length + EFODF_PATH.length];
- System.arraycopy(pkcs15Path, 0, path, 0, pkcs15Path.length);
- System.arraycopy(EFODF_PATH, 0, path, pkcs15Path.length, EFODF_PATH.length );
- } else {
- path = EFODF_PATH;
- }
- //---
-
- if ( selectFile(path)!= APDU_SUCCESS)
- throw new PKCS15Exception("EF_ODF not found!!");
-
- return decodeDER(readBinary(0,Util.END));
- }
-
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/PKCS15/PKCS15Exception.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/PKCS15/PKCS15Exception.java
deleted file mode 100644
index 2eb0b95..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/PKCS15/PKCS15Exception.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2011 Deutsche Telekom, A.G.
- *
- * 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 org.simalliance.openmobileapi.service.security.arf.PKCS15;
-
-/**
- * Handles PKCS#15 errors
- ***************************************************/
-public class PKCS15Exception extends Exception {
-
- private static final long serialVersionUID = 1556408586814064005L;
-
- public PKCS15Exception(String message) {
- super(message);
- }
-
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/PKCS15/PKCS15Handler.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/PKCS15/PKCS15Handler.java
deleted file mode 100644
index 3adaccc..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/PKCS15/PKCS15Handler.java
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright (C) 2011 Deutsche Telekom, A.G.
- *
- * 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.
- */
-
-/*
- * Contributed by: Giesecke & Devrient GmbH.
- */
-
-package org.simalliance.openmobileapi.service.security.arf.PKCS15;
-
-import java.security.AccessControlException;
-import java.util.MissingResourceException;
-
-import org.simalliance.openmobileapi.service.IChannel;
-import org.simalliance.openmobileapi.service.security.arf.SecureElement;
-import org.simalliance.openmobileapi.service.security.arf.SecureElementException;
-import org.simalliance.openmobileapi.service.security.arf.PKCS15.EFACMain;
-import org.simalliance.openmobileapi.service.security.arf.PKCS15.EFACRules;
-import org.simalliance.openmobileapi.service.security.arf.PKCS15.EFDIR;
-import org.simalliance.openmobileapi.service.security.arf.PKCS15.EFDODF;
-import org.simalliance.openmobileapi.service.security.arf.PKCS15.EFODF;
-import org.simalliance.openmobileapi.service.security.arf.PKCS15.PKCS15Exception;
-
-import android.os.Build;
-import android.os.SystemProperties;
-import android.util.Log;
-
-/**
- * Handles PKCS#15 topology
- ***************************************************/
-public class PKCS15Handler {
-
- public static final String TAG = "SmartcardService ACE ARF";
-
- // AID of the GPAC Applet/ADF
- public static final byte[] GPAC_ARF_AID =
- {(byte)0xA0,0x00,0x00,0x00,0x18,0x47,0x50,0x41,0x43,0x2D,0x31,0x35};
- // AID of the PKCS#15 ADF
- public static final byte[] PKCS15_AID =
- { (byte)0xA0,0x00,0x00,0x00,0x63,0x50,0x4B,0x43,0x53,0x2D,0x31,0x35 };
-
- // AIDs of "Access Control Rules" containers
- public static final byte[][] CONTAINER_AIDS= {
- PKCS15_AID,
- GPAC_ARF_AID,
- null
- };
-
- // Handle to "Secure Element"
- private SecureElement mSEHandle;
- // "Secure Element" label
- private String mSELabel=null;
-
- // Handle to "Logical Channel" allocated by the SE
- private IChannel mArfChannel=null;
-
- // "EF Access Control Main" object
- private EFACMain mACMainObject=null;
- // EF AC Rules object
- private EFACRules mACRulesObject=null;
-
- private byte[] mPkcs15Path = null;
- private byte[] mACMainPath = null;
-
- // SIM Allowed modes:
- private boolean mSimIoAllowed;
- private boolean mSimAllianceAllowed;
-
- /**
- * Updates "Access Control Rules"
- */
- private boolean updateACRules()
- throws Exception, PKCS15Exception, SecureElementException
- {
- byte[] ACRulesPath=null;
- try {
- ACRulesPath=mACMainObject.analyseFile();
- } catch (Exception e) {
- mACMainObject=null;
- mSEHandle.resetAccessRules();
- throw e;
- }
- // Check if rules must be updated
- if (ACRulesPath != null) {
- Log.d(TAG, "Access Rules needs to be updated...");
- if (mACRulesObject==null) {
- mACRulesObject=new EFACRules(mSEHandle);
- }
- mSEHandle.clearAccessRuleCache();
- mACRulesObject.analyseFile(ACRulesPath);
- return true;
- } else {
- Log.d(TAG, "Refresh Tag has not been changed...");
- return false;
- }
- }
-
- /**
- * Initializes "Access Control" entry point [ACMain]
- */
- private void initACEntryPoint()
- throws PKCS15Exception, SecureElementException
- {
-
- byte[] DODFPath=null;
-
- readAllowedSimMode();
-
- for(int ind=0;ind<CONTAINER_AIDS.length;ind++) {
- if (selectACRulesContainer(CONTAINER_AIDS[ind])) {
-
- byte[] acMainPath = null;
- if( mACMainPath==null){
- EFODF ODFObject=new EFODF(mSEHandle);
- DODFPath=ODFObject.analyseFile(mPkcs15Path);
- EFDODF DODFObject=new EFDODF(mSEHandle);
- acMainPath=DODFObject.analyseFile(DODFPath);
- mACMainPath = acMainPath;
- } else {
- if( mPkcs15Path != null ) {
- acMainPath = new byte[mPkcs15Path.length + mACMainPath.length];
- System.arraycopy(mPkcs15Path, 0, acMainPath, 0, mPkcs15Path.length);
- System.arraycopy(mACMainPath, 0, acMainPath, mPkcs15Path.length, mACMainPath.length );
- } else {
- acMainPath = mACMainPath;
- }
- }
- mACMainObject=new EFACMain(mSEHandle,acMainPath);
- break;
- }
- }
- }
-
- /**
- * Selects "Access Control Rules" container
- * @param AID Identification of the GPAC Applet/PKCS#15 ADF;
- * <code>null</code> for EF_DIR file
- * @return <code>true</code> when container is active;
- * <code>false</code> otherwise
- */
- private boolean selectACRulesContainer(byte[] aid)
- throws PKCS15Exception,SecureElementException
- {
- boolean isActiveContainer=true;
-
- if (aid==null) {
- mArfChannel = null;
-
- // some devices use logical channels to access filesystem directly. This is done with an empty byte array.
- // if open logical channel does not work, last fallback is using SIM_IO (AT-CRSM).
- // 2012-11-08
- if(mSimAllianceAllowed)
- mArfChannel = mSEHandle.openLogicalArfChannel(new byte[]{});
-
- if (mArfChannel != null) {
- Log.i(TAG, "Logical channels are used to access to PKC15");
- mSEHandle.setSeInterface(SecureElement.SIM_ALLIANCE);
- }
- else {
- if(mSimIoAllowed) {
- // Since ARF gets only active if the terminal belongs to a SIM/UICC
- // we have to switch to SIM_IO
- Log.i(TAG, "Fall back into ARF with SIM_IO");
- mSEHandle.setSeInterface(SecureElement.SIM_IO);
- }
- else {
- Log.i(TAG, "SIM IO is not allowed: cannot access to ARF");
- isActiveContainer = false;
- }
- }
-
- if(isActiveContainer && mPkcs15Path == null ) { // estimate PKCS15 path only if it is not known already.
- mACMainPath = null;
- // EF_DIR parsing
- EFDIR DIRObject=new EFDIR(mSEHandle);
- mPkcs15Path=DIRObject.lookupAID(PKCS15_AID);
- if( mPkcs15Path == null ) {
- Log.i(TAG, "Cannot use ARF: cannot select PKCS#15 directory via EF Dir");
- // TODO: Here it might be possible to set a default path
- // so that SIMs without EF-Dir could be supported.
- throw new PKCS15Exception("Cannot select PKCS#15 directory via EF Dir");
- }
- }
- }
- // if an AID is given use logical channel.
- else {
- if(!mSimAllianceAllowed) {
- isActiveContainer = false;
- }
- else {
- // Selection of Applet/ADF via AID is done via SCAPI and logical Channels
- mSEHandle.setSeInterface(SecureElement.SIM_ALLIANCE);
- if ((mArfChannel=mSEHandle.openLogicalArfChannel(aid))==null) {
- isActiveContainer=false;
- Log.w(TAG,"GPAC/PKCS#15 ADF not found!!");
- }
- else {
- // ARF is selected via AID.
- if( mPkcs15Path != null ){ // if there is a change from path selection to AID selection, then reset AC Main path.
- mACMainPath = null;
- }
- mPkcs15Path = null; // selection is done via AID
- }
- }
- }
- return isActiveContainer;
- }
-
- /**
- * Constructor
- * @param handle Handle to "Secure Element"
- */
- public PKCS15Handler(SecureElement handle) {
- mSEHandle=handle;
- }
-
- /**
- * Loads "Access Control Rules" from container
- * @return false if access rules where not read due to constant refresh tag.
- */
- public synchronized boolean loadAccessControlRules(String secureElement) {
- mSELabel=secureElement;
- Log.v(TAG,"- Loading "+mSELabel+" rules...");
- try {
- initACEntryPoint();
- return updateACRules();
- } catch (Exception e) {
- if( e instanceof MissingResourceException ){
- // this indicates that no channel is left for accessing the SE element
- throw (MissingResourceException)e;
- }
- Log.e(TAG,mSELabel+" rules not correctly initialized! " + e.getLocalizedMessage());
- throw new AccessControlException(e.getLocalizedMessage());
- } finally {
- // Close previously opened channel
- if (mArfChannel!=null)
- mSEHandle.closeArfChannel();
- }
- }
-
- /**
- * Read security allowed sim mode
- */
- private void readAllowedSimMode() {
- if(!Build.IS_DEBUGGABLE) {
- mSimIoAllowed = true;
- mSimAllianceAllowed = true;
- } else {
- String level = SystemProperties.get("service.seek.arf", "simio simalliance");
- level = SystemProperties.get("persist.service.seek.arf", level);
-
- if(level.contains("simio")) mSimIoAllowed = true; else mSimIoAllowed = false;
- if(level.contains("simalliance")) mSimAllianceAllowed = true; else mSimAllianceAllowed = false;
- }
-
- Log.i(TAG, "Allowed SIM mode: SimIo=" + mSimIoAllowed + " SimAlliance=" + mSimAllianceAllowed );
- }
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/SecureElement.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/SecureElement.java
deleted file mode 100644
index 6c51d91..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/SecureElement.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (C) 2011 Deutsche Telekom, A.G.
- *
- * 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.
- */
-
-/*
- * Contributed by: Giesecke & Devrient GmbH.
- */
-
-package org.simalliance.openmobileapi.service.security.arf;
-
-import android.util.Log;
-import java.util.MissingResourceException;
-import org.simalliance.openmobileapi.service.IChannel;
-import org.simalliance.openmobileapi.service.ISmartcardServiceCallback;
-import org.simalliance.openmobileapi.service.ITerminal;
-import org.simalliance.openmobileapi.service.SmartcardService;
-import org.simalliance.openmobileapi.service.Util;
-import org.simalliance.openmobileapi.service.security.ChannelAccess;
-import org.simalliance.openmobileapi.service.security.arf.SecureElementException;
-import org.simalliance.openmobileapi.service.security.arf.PKCS15.EF;
-import org.simalliance.openmobileapi.service.security.gpac.dataobjects.AID_REF_DO;
-import org.simalliance.openmobileapi.service.security.gpac.dataobjects.Hash_REF_DO;
-import org.simalliance.openmobileapi.service.security.gpac.dataobjects.REF_DO;
-
-/**
- * Provides high-level functions for SE communication
- ***************************************************/
-public class SecureElement {
-
- public static final String TAG = "SmartcardService ACE ARF";
-
- // Logical channel used for SE communication (optional)
- private IChannel mArfChannel=null;
- // Handle to a built-in "Secure Element"
- private ITerminal mTerminalHandle=null;
- // Arf Controller within the SCAPI handler
- private ArfController mArfHandler=null;
- // Callback used during "Secure Element" communication
- private final ISmartcardServiceCallback mCallback =
- new ISmartcardServiceCallback.Stub(){};
-
- public static final short SIM_IO = 1;
- public static final short SIM_ALLIANCE = 0;
-
- // Interface for exchanging APDU commands
- private short mSEInterface=SIM_ALLIANCE;
-
- /**
- * Constructor
- *
- * @param arfHandler - handle to the owning arf controller object
- * @param handle - handle to the SE terminal to be accessed.
- */
- public SecureElement(ArfController arfHandler,ITerminal handle) {
- mTerminalHandle=handle;
- mArfHandler=arfHandler;
- }
-
- public short getSeInterface(){
- return mSEInterface;
- }
-
- public void setSeInterface(short seInterface){
- mSEInterface = seInterface;
- }
-
- /**
- * Transmits ADPU commands
- * @param cmd APDU command
- * @return Data returned by the APDU command
- */
- public byte[] exchangeAPDU(EF ef, byte[] cmd)
- throws SecureElementException {
- try {
- if (mSEInterface==SIM_IO) {
-
- return mTerminalHandle.simIOExchange(ef.getFileId(),ef.getFilePath(),cmd);
- } else {
-
- return mArfChannel.transmit(cmd);
- }
- } catch (Exception e) {
- throw new SecureElementException("Secure Element access error " + e.getLocalizedMessage());
- }
- }
-
- /**
- * Opens a logical channel to ARF Applet or ADF
- * @param AID Applet identifier
- * @return Handle to "Logical Channel" allocated by the SE;
- * <code>0</code> if error occurred
- */
- public IChannel openLogicalArfChannel(byte[] AID) {
- try {
-
- mArfChannel=mTerminalHandle.openLogicalChannel(null,AID,mCallback);
- setUpChannelAccess(mArfChannel);
- return mArfChannel;
- } catch(Exception e) {
- if( e instanceof MissingResourceException ){
- // this indicates that no channel is left for accessing the SE element
- Log.d(TAG, "no channels left to access ARF: " + e.getMessage() );
- throw (MissingResourceException)e;
- } else {
- Log.e(TAG,"Error opening logical channel " + e.getLocalizedMessage());
- }
- mArfChannel = null;
- return null;
- }
- }
-
- /**
- * Closes a logical channel previously allocated by the SE
- * @param handle Handle to open channel
- */
- public void closeArfChannel() {
- try {
- if( mArfChannel != null){
-
- mArfChannel.close();
- mArfChannel = null;
- } else {
-
- }
-
- } catch(Exception e) {
- Log.e(TAG,"Error closing channel " + e.getLocalizedMessage());
- }
- }
-
- /**
- * Set up channel access to allow,
- * so that PKCS15 files can be read.
- *
- * @param channel
- */
- private void setUpChannelAccess( IChannel channel ){
- // set access conditions to access ARF.
- ChannelAccess arfChannelAccess = new ChannelAccess();
- arfChannelAccess.setAccess(ChannelAccess.ACCESS.ALLOWED, "");
- arfChannelAccess.setApduAccess(ChannelAccess.ACCESS.ALLOWED);
- channel.setChannelAccess(arfChannelAccess);
-
- }
-
- public byte[] getRefreshTag() {
- if( mArfHandler != null ){
- return mArfHandler.getAccessRuleCache().getRefreshTag();
- }
- return null;
- }
-
- public void setRefreshTag(byte[] refreshTag) {
- if( mArfHandler != null ) {
- mArfHandler.getAccessRuleCache().setRefreshTag(refreshTag);
- }
- }
-
- public void putAccessRule( AID_REF_DO aid_ref_do, Hash_REF_DO hash_ref_do, ChannelAccess channelAccess ) {
-
- REF_DO ref_do = new REF_DO(aid_ref_do, hash_ref_do);
- mArfHandler.getAccessRuleCache().putWithMerge(ref_do, channelAccess);
- }
-
- public void resetAccessRules() {
- this.mArfHandler.getAccessRuleCache().reset();
- }
- public void clearAccessRuleCache() {
- this.mArfHandler.getAccessRuleCache().clearCache();
- }
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/SecureElementException.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/SecureElementException.java
deleted file mode 100644
index 3ad324f..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/arf/SecureElementException.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2011 Deutsche Telekom, A.G.
- *
- * 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 org.simalliance.openmobileapi.service.security.arf;
-
-/**
- * Handles "Secure Element" access errors
- ***************************************************/
-public class SecureElementException extends Exception {
-
- private static final long serialVersionUID = 530360632436123998L;
-
- public SecureElementException(String message) {
- super(message);
- }
-
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/AID_REF_DO.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/AID_REF_DO.java
deleted file mode 100644
index a631872..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/AID_REF_DO.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright 2012 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.service.security.gpac.dataobjects;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Arrays;
-
-
-/**
- * The AID-REF-DO is used for retrieving and storing
- * the corresponding access rules for an SE application
- * (which is identified by its AID) from and to the ARA.
- * Two different AID reference data objects exist and one
- * of these can be chosen and applied for
- * a GET DATA and STORE DATA command
- *
- *
- *
- */
-public class AID_REF_DO extends BerTlv {
-
- public final static int _TAG = 0x4F;
- public final static int _TAG_DEFAULT_APPLICATION = 0xC0;
-
- private byte[] mAid = null;
-
- public AID_REF_DO(byte[] rawData, int tag, int valueIndex, int valueLength) {
- super(rawData, tag, valueIndex, valueLength);
- }
-
-
- public AID_REF_DO( int tag, byte[] aid){
- super( aid, tag, 0, (aid==null ? 0 : aid.length));
- mAid = aid;
- }
-
- public AID_REF_DO( int tag){
- super( null, tag, 0, 0);
- mAid = tag == _TAG_DEFAULT_APPLICATION ? null : new byte[0];
- }
-
- @Override
- public String toString(){
- StringBuilder b = new StringBuilder();
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- b.append("AID_REF_DO: ");
- try {
- this.build(out);
- b.append(BerTlv.toHex(out.toByteArray()));
- } catch (Exception e ){
- b.append(e.getLocalizedMessage());
- }
- return b.toString();
- }
-
- public byte[] getAid(){
- return mAid;
- }
-
- /**
- * Tags: C0 -> Length: 0 -> Default selected application (all channels)
- * 4F -> Length: 0 or 5 - 16 bytes
- *
- * Value:
- * AID: identifies a specific application
- * Empty: refers to all SE applications
- *
- * Length:
- * 5-16 for an AID according to ISO/IEC7816-5
- * 0 for empty value field
- */
- @Override
- public void interpret()
- throws ParserException {
-
- mAid = null;
-
- byte[] data = getRawData();
- int index = getValueIndex();
-
- if( getTag() == _TAG_DEFAULT_APPLICATION ) {
- if( getValueLength() != 0 ){
- throw new ParserException("Invalid value length for AID-REF-DO!");
- }
- } else if( getTag() == _TAG ){
-
- // sanity checks
- if( (getValueLength() < 5 || getValueLength() > 16) && getValueLength() != 0) {
- throw new ParserException("Invalid value length for AID-REF-DO!");
- }
-
- if( index + getValueLength() > data.length){
- throw new ParserException( "Not enough data for AID-REF-DO!");
- }
-
- mAid = new byte[getValueLength()];
- System.arraycopy(data, index, mAid, 0, getValueLength());
-
- } else {
- throw new ParserException( "Invalid Tag for AID-REF-DO!");
- }
- }
-
- /**
- * Tags: C0 -> Length: 0 -> Default selected application (all channels)
- * 4F -> Length: 0 or 5 - 16 bytes
- *
- * Value:
- * AID: identifies a specific application
- * Empty: refers to all SE applications
- *
- * Length:
- * 5-16 for an AID according to ISO/IEC7816-5
- * 0 for empty value field
- */
- @Override
- public void build( ByteArrayOutputStream stream)
- throws DO_Exception {
-
- if( getTag() == _TAG_DEFAULT_APPLICATION ) {
- if( mAid != null ){
- throw new DO_Exception("No value allowed for default selected application!");
- }
- stream.write(getTag());
- stream.write(0x00);
- } else if( getTag() == _TAG ){
-
- // sanity check
- if( getValueLength() != 0 ) {
- if (getValueLength() < 5 || getValueLength() > 16) {
- throw new DO_Exception("Invalid length of AID!");
- }
- }
-
- stream.write(getTag());
- if( mAid != null && mAid.length > 0 ) {
- stream.write(mAid.length);
- try {
- stream.write(mAid);
- } catch( IOException ioe ){
- throw new DO_Exception("AID could not be written!");
- }
- } else {
- stream.write(0x00);
- }
-
- } else {
- throw new DO_Exception( "AID-REF-DO must either be C0 or 4F!");
- }
- }
-
- @Override
- public boolean equals( Object obj ){
- boolean equals = false;
-
- if( obj instanceof AID_REF_DO ){
- equals = super.equals(obj);
-
- if( equals ){
- AID_REF_DO aid_ref_do = (AID_REF_DO)obj;
- if( this.mAid == null && aid_ref_do.mAid == null )
- equals &= true;
- else {
- equals &= Arrays.equals(mAid, aid_ref_do.mAid);
- }
- }
- }
- return equals;
- }
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/APDU_AR_DO.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/APDU_AR_DO.java
deleted file mode 100644
index e09fc7a..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/APDU_AR_DO.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright 2012 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.service.security.gpac.dataobjects;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-
-
-/**
- * APDU-AR-DO:
- * An APDU access rule data object defines an access rule for APDU access.
- * The APDU access can either be restricted by a general rule
- * based on an access is NEVER/ ALWAYS allowed policy or
- * by a specific rule based on APDU filters which defines the range
- * of allowed APDUs more precisely.
- *
- *
- *
- */
-public class APDU_AR_DO extends BerTlv {
-
- public final static int _TAG = 0xD0;
-
- private boolean mApduAllowed = false;
- private ArrayList<byte[]> mApduHeader = new ArrayList<byte[]>();
- private ArrayList<byte[]> mFilterMask = new ArrayList<byte[]>();
-
- public APDU_AR_DO(byte[] rawData, int valueIndex, int valueLength) {
- super(rawData, _TAG, valueIndex, valueLength);
- }
-
- public APDU_AR_DO( boolean allowed ){
- super( null, _TAG, 0, 0);
- mApduAllowed = allowed;
- }
-
- public APDU_AR_DO( ArrayList<byte[]> apduHeader, ArrayList<byte[]> filterMask ){
- super( null, _TAG, 0, 0);
- mApduHeader = apduHeader;
- mFilterMask = filterMask;
- }
-
- public boolean isApduAllowed(){
- return mApduAllowed;
- }
-
- public ArrayList<byte[]> getApduHeaderList(){
- return mApduHeader;
- }
-
- public ArrayList<byte[]> getFilterMaskList(){
- return mFilterMask;
- }
-
- @Override
- /**
- * Tag: D0
- * Length: 1 or n*8
- * 1 if value contains a general APDU access rule.
- * n*8 if value contains a specific APDU access rule.
-
- * Value:
- * Contains a general APDU access rule:
- * NEVER (00): APDU access is not allowed
- * ALWAYS(01): APDU access is allowed
- * or
- * contains a specific APDU access rule based on one or more APDU filter(s):
- * APDU filter: 8 bytes APDU filter mask consists of:
- * 4 bytes APDU header (defines the header of allowed APDUs)
- * 4 bytes APDU mask (bit set defines the bits which shall be considered
- * for the APDU header comparison)
- * An APDU filter has to be applied as follows:
- * if((APDUHeader & FilterMask) == FilterAPDUHeader)
- * then allow APDU
- */
- public void interpret()
- throws ParserException {
-
- mApduAllowed = false;
- mApduHeader.clear();
- mFilterMask.clear();
-
- byte[] data = getRawData();
- int index = getValueIndex();
-
- if( index + getValueLength() > data.length){
- throw new ParserException( "Not enough data for APDU_AR_DO!");
- }
-
- // APDU-AR-DO contains either a flag which allows/disallows APDU communication
- // or
- // it contains APDU filter (APDUHeader | FilterMask) which should have length n*8.
- if( getValueLength() == 1 ){
- mApduAllowed = (data[index] == 0x01);
- } else if(getValueLength() % 8 == 0 ) {
- mApduAllowed = true;
-
- for( int i = index; i < index + getValueLength(); i +=8 ){
- byte[] apduHeader = new byte[4];
- byte[] filterMask = new byte[4];
-
- apduHeader[0] = data[i+0];
- apduHeader[1] = data[i+1];
- apduHeader[2] = data[i+2];
- apduHeader[3] = data[i+3];
- filterMask[0] = data[i+4];
- filterMask[1] = data[i+5];
- filterMask[2] = data[i+6];
- filterMask[3] = data[i+7];
-
- mApduHeader.add(apduHeader);
- mFilterMask.add(filterMask);
- }
- } else {
- throw new ParserException( "Invalid length of APDU-AR-DO!" );
- }
- }
-
- @Override
- /**
- * Tag: D0
- * Length: 1 or n*8
- * 1 if value contains a general APDU access rule.
- * n*8 if value contains a specific APDU access rule.
-
- * Value:
- * Contains a general APDU access rule:
- * NEVER (00): APDU access is not allowed
- * ALWAYS(01): APDU access is allowed
- * or
- * contains a specific APDU access rule based on one or more APDU filter(s):
- * APDU filter: 8 bytes APDU filter mask consists of:
- * 4 bytes APDU header (defines the header of allowed APDUs)
- * 4 bytes APDU mask (bit set defines the bits which shall be considered
- * for the APDU header comparison)
- * An APDU filter has to be applied as follows:
- * if((APDUHeader & FilterMask) == FilterAPDUHeader)
- * then allow APDU
- */
- public void build( ByteArrayOutputStream stream )
- throws DO_Exception {
-
- // APDU header and filter mask has to have the same size
- // even if they are not used (then size() == 0 ).
- if(mApduHeader.size() != this.mFilterMask.size()){
- throw new DO_Exception( "APDU filter is invalid");
- }
-
- // write tag
- stream.write(getTag());
-
- // check if APDU Flag shall be written
- if( mApduHeader.size() == 0){
- stream.write(0x01);
- stream.write(this.mApduAllowed ? 0x01 : 0x00 );
- } else {
- ByteArrayOutputStream temp = new ByteArrayOutputStream();
- for( int i = 0; i < mApduHeader.size(); i++ ){
- byte[] apduHeader = mApduHeader.get(i);
- byte[] filterMask = mFilterMask.get(i);
-
- if( apduHeader.length != 4 || filterMask.length != 4 ){
- throw new DO_Exception("APDU filter is invalid!");
- }
-
- try {
- temp.write(apduHeader);
- temp.write(filterMask);
- } catch (IOException e) {
- throw new DO_Exception("APDU Filter Memory IO problem! " + e.getMessage());
- }
- }
-
- BerTlv.encodeLength(temp.size(), stream);
- try {
- stream.write(temp.toByteArray());
- } catch (IOException e) {
- throw new DO_Exception("APDU Filter Memory IO problem! " + e.getMessage());
- }
- }
- }
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/AR_DO.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/AR_DO.java
deleted file mode 100644
index 46d86e1..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/AR_DO.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright 2012 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.service.security.gpac.dataobjects;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-
-/**
- * This class represents the Access rule data object (AR-DO), according
- * to GP Secure Element Control Access.
- *
- * The AR-DO contains one or two access rules of type APDU or NFC.
- *
- *
- *
- */
-public class AR_DO extends BerTlv{
-
- public final static int _TAG = 0xE3;
-
- private APDU_AR_DO mApduAr = null;
- private NFC_AR_DO mNfcAr = null;
-
- public AR_DO(byte[] rawData, int valueIndex, int valueLength) {
- super(rawData, _TAG, valueIndex, valueLength);
- }
-
- public AR_DO( APDU_AR_DO apdu_ar_do, NFC_AR_DO nfc_ar_do ){
- super( null, _TAG, 0, 0);
- mApduAr = apdu_ar_do;
- mNfcAr = nfc_ar_do;
- }
-
- public APDU_AR_DO getApduArDo(){
- return mApduAr;
- }
-
- public NFC_AR_DO getNfcArDo(){
- return mNfcAr;
- }
-
- @Override
- /**
- * Interpret value.
- *
- * Tag: E3
- *
- * Value:
- * Value can contain APDU-AR-DO or NFC-AR-DO or APDU-AR-DO | NFC-AR-DO
- * A concatenation of one or two AR-DO(s). If two AR-DO(s) are present
- * these must have different types.
- */
- public void interpret()
- throws ParserException {
-
- this.mApduAr = null;
- this.mNfcAr = null;
-
- byte[] data = getRawData();
- int index = getValueIndex();
-
- if( index + getValueLength() > data.length){
- throw new ParserException( "Not enough data for AR_DO!");
- }
-
- do {
- BerTlv temp = BerTlv.decode(data, index);
-
- if( temp.getTag() == APDU_AR_DO._TAG ) { // APDU-AR-DO
- mApduAr = new APDU_AR_DO( data, temp.getValueIndex(), temp.getValueLength());
- mApduAr.interpret();
- } else if( temp.getTag() == NFC_AR_DO._TAG ) { // NFC-AR-DO
- mNfcAr = new NFC_AR_DO( data, temp.getValueIndex(), temp.getValueLength());
- mNfcAr.interpret();
- } else {
- // un-comment following line if a more restrictive
- // behavior is necessary.
- //throw new ParserException("Invalid DO in AR-DO!");
- }
- index = temp.getValueIndex() + temp.getValueLength();
- } while ( getValueIndex() + getValueLength() > index );
-
- if( mApduAr == null && mNfcAr == null ){
- throw new ParserException("No valid DO in AR-DO!");
- }
- }
-
- @Override
- /**
- * Interpret value.
- *
- * Tag: E3
- *
- * Value:
- * Value can contain APDU-AR-DO or NFC-AR-DO or APDU-AR-DO | NFC-AR-DO
- * A concatenation of one or two AR-DO(s). If two AR-DO(s) are present
- * these must have different types.
- */
- public void build( ByteArrayOutputStream stream )
- throws DO_Exception {
-
- // write tag
- stream.write(getTag());
-
- ByteArrayOutputStream temp = new ByteArrayOutputStream();
- if( mApduAr != null ){
- mApduAr.build(temp);
- }
-
- if( mNfcAr != null ){
- mNfcAr.build(temp);
- }
-
- BerTlv.encodeLength(temp.size(), stream);
- try {
- stream.write(temp.toByteArray());
- } catch (IOException e) {
- throw new DO_Exception("AR-DO Memory IO problem! " + e.getMessage());
- }
- }
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/BerTlv.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/BerTlv.java
deleted file mode 100644
index 13a49a5..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/BerTlv.java
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * Copyright 2012 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.service.security.gpac.dataobjects;
-
-import java.io.ByteArrayOutputStream;
-import java.util.Arrays;
-
-
-public class BerTlv {
-
- private byte[] mRawData = null;
-
- private int mTag = 0;
-
- private int mValueIndex = 0;
- private int mValueLength = 0;
-
- public BerTlv( byte[] rawData, int tag, int valueIndex, int valueLength ) {
- mRawData = rawData;
- mTag = tag;
- mValueIndex = valueIndex;
- mValueLength = valueLength;
- }
-
- public static String toHex(byte[] digest) {
- String digits = "0123456789abcdef";
- StringBuilder sb = new StringBuilder(digest.length * 2);
- for (byte b : digest) {
- int bi = b & 0xff;
- sb.append(digits.charAt(bi >> 4));
- sb.append(digits.charAt(bi & 0xf));
- }
- return sb.toString();
- }
-
- public static BerTlv decode( byte[] data, int startIndex )
- throws ParserException {
- return BerTlv.decode(data, startIndex, true);
- }
-
- public static BerTlv decode( byte[] data, int startIndex, boolean containsAllData )
- throws ParserException {
-
- if( data == null || data.length == 0 ){
- throw new ParserException("No data given!");
- }
-
- int curIndex = startIndex;
- int tag = 0;
-
- /* tag */
- if( curIndex < data.length ) {
- int temp = data[curIndex++] & 0xff;
- switch (temp) {
- case 0xff: // tag is in two byte format
- case 0xdf:
- if( curIndex < data.length ) {
- tag = ((temp & 0xff) << 8) | (data[curIndex++] & 0xff);
- } else {
- throw new ParserException("Index " + curIndex + " out of range! [0..[" + data.length);
- }
- break;
-
- default: // tag is in single-byte format
- tag = temp;
- break;
- }
- } else {
- throw new ParserException("Index " + curIndex + " out of range! [0..[" + data.length);
- }
-
- /* length */
- int length;
- if( curIndex < data.length ) {
- int temp = data[curIndex++] & 0xff;
- if (temp < 0x80) {
- length = temp;
- } else if (temp == 0x81) {
- if( curIndex < data.length ) {
- length = data[curIndex++] & 0xff;
- if (length < 0x80) {
- throw new ParserException("Invalid TLV length encoding!");
- }
- if(containsAllData &&
- data.length < length + curIndex) {
- throw new ParserException("Not enough data provided!");
- }
- } else {
- throw new ParserException("Index " + curIndex + " out of range! [0..[" + data.length);
- }
- } else if (temp == 0x82) {
- if( (curIndex + 1)< data.length ) {
- length = ((data[curIndex] & 0xff) << 8) | (data[curIndex + 1] & 0xff);
- } else {
- throw new ParserException("Index out of range! [0..[" + data.length);
- }
- curIndex += 2;
- if (length < 0x100) {
- throw new ParserException("Invalid TLV length encoding!");
- }
- if (containsAllData &&
- data.length < length + curIndex) {
- throw new ParserException("Not enough data provided!");
- }
- } else if (temp == 0x83) {
- if( (curIndex + 2)< data.length ) {
- length = ((data[curIndex] & 0xff) << 16)
- | ((data[curIndex + 1] & 0xff) << 8)
- | (data[curIndex + 2] & 0xff);
- } else {
- throw new ParserException("Index out of range! [0..[" + data.length);
- }
- curIndex += 3;
- if (length < 0x10000) {
- throw new ParserException("Invalid TLV length encoding!");
- }
- if (containsAllData &&
- data.length < length + curIndex) {
- throw new ParserException("Not enough data provided!");
- }
- } else {
- throw new ParserException("Unsupported TLV length encoding!");
- }
- } else {
- throw new ParserException("Index " + curIndex + " out of range! [0..[" + data.length);
- }
- // create object
- return new BerTlv( data, tag, curIndex, length);
- }
-
- public void interpret()
- throws ParserException {
- // has to be overwritten in derived classes.
- }
-
- /**
- * Builds up the TLV into a byte stream.
- *
- * Tags can be encoded as one or two bytes
- *
- * @param stream
- * @throws DO_Exception
- */
- public void build( ByteArrayOutputStream stream )
- throws DO_Exception {
-
- // put tag into stream
- if( mTag > 0xFF ){
- stream.write(((mTag & 0x0000FF00)>>8));
- stream.write((mTag & 0x000000FF));
- } else {
- stream.write((mTag & 0x000000FF));
- }
-
- // write length
- encodeLength( mValueLength, stream );
-
- // write value
- if( mValueLength > 0 ){
- stream.write(mRawData, mValueIndex, mValueLength);
- }
- }
-
- public int getTag(){
- return mTag;
- }
-
-
- public int getValueIndex(){
- return mValueIndex;
- }
-
-
- public byte[] getValue(){
- // sanity checks
- if( mRawData == null ||
- mValueLength == 0 ||
- mValueIndex < 0 || mValueIndex > mRawData.length ||
- mValueIndex + mValueLength > mRawData.length )
- return null;
-
- byte[] data = new byte[mValueLength];
-
- System.arraycopy(mRawData, mValueIndex, data, 0, mValueLength);
-
- return data;
- }
-
- protected byte[] getRawData(){
- return mRawData;
- }
-
- public int getValueLength() {
- return mValueLength;
- }
-
- /**
- * Encodes length according to ASN1.
- * Supported are length values up to 3 bytes -> 83 xx yy zz.
- *
- * @param length
- * @param stream
- */
- public static void encodeLength( int length, ByteArrayOutputStream stream){
-
- if (length > 0x0000FFFF ) {
- stream.write(0x83);
- stream.write(((length & 0x00FF0000)>>16));
- stream.write(((length & 0x0000FF00)>>8));
- stream.write((length & 0x000000FF));
- } else if( length > 0x000000FF){
- stream.write(0x82);
- stream.write(((length & 0x0000FF00)>>8));
- stream.write((length & 0x000000FF));
- } else if( length > 0x0000007F){
- stream.write(0x81);
- stream.write((length & 0x000000FF));
- } else {
- stream.write((length & 0x000000FF));
- }
- }
-
- @Override
- public boolean equals(Object obj){
- boolean equals = false;
-
- if( obj instanceof BerTlv ){
- BerTlv berTlv = (BerTlv)obj;
-
- equals = this.mTag == berTlv.mTag;
-
- if(equals ){
- byte[] test1 = this.getValue();
- byte[] test2 = berTlv.getValue();
-
- if( test1 != null ){
- //equals &= test1.equals(test2);
- equals &= Arrays.equals(test1, test2);
- } else if( test1 == null && test2 == null ){
- equals &= true;
- }
- }
- }
- return equals;
- }
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/DO_Exception.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/DO_Exception.java
deleted file mode 100644
index b2aded6..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/DO_Exception.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2012 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.service.security.gpac.dataobjects;
-
-public class DO_Exception extends Exception {
-
- /**
- *
- */
- private static final long serialVersionUID = -3917637590082486538L;
-
- public DO_Exception() {
- super();
- // TODO Auto-generated constructor stub
- }
-
-
- public DO_Exception(String arg0, Throwable arg1) {
- super(arg0, arg1);
- // TODO Auto-generated constructor stub
- }
-
- public DO_Exception(String arg0) {
- super(arg0);
- // TODO Auto-generated constructor stub
- }
-
- public DO_Exception(Throwable arg0) {
- super(arg0);
- // TODO Auto-generated constructor stub
- }
-
-
-
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/Hash_REF_DO.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/Hash_REF_DO.java
deleted file mode 100644
index 95aaae1..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/Hash_REF_DO.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright 2012 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.service.security.gpac.dataobjects;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Arrays;
-
-/**
- * Hash-REF-DO:
- * The Hash-REF-DO is used for retrieving and storing
- * the corresponding access rules for a device application
- * (which is identified by the hash value of its certificate)
- * from and to the ARA
- *
- *
- *
- */
-public class Hash_REF_DO extends BerTlv {
-
- public final static int _TAG = 0xC1;
- public final static int _SHA1_LEN = 20;
-
- private byte[] mHash = null;
-
- public Hash_REF_DO(byte[] rawData, int valueIndex, int valueLength){
- super(rawData, _TAG, valueIndex, valueLength);
- }
-
- public Hash_REF_DO(byte[] hash){
- super(hash, _TAG, 0, (hash == null ? 0 : hash.length));
- mHash = hash;
- }
-
- public Hash_REF_DO(){
- super(null, _TAG, 0, 0);
- mHash = null;
- }
-
- public byte[] getHash(){
- return mHash;
- }
-
- @Override
- public String toString(){
- StringBuilder b = new StringBuilder();
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- b.append("Hash_REF_DO: ");
- try {
- this.build(out);
- b.append(BerTlv.toHex(out.toByteArray()));
- } catch (Exception e ){
- b.append(e.getLocalizedMessage());
- }
- return b.toString();
- }
-
- /**
- * Tags: C1
- * Length: 0 or _SHA1_LEN bytes
- *
- * Value:
- * Hash: identifies a specific device application
- * Empty: refers to all device applications
- *
- * Length:
- * _SHA1_LEN for 20 bytes SHA-1 hash value
- * 0 for empty value field
- */
- @Override
- public void interpret()
- throws ParserException {
-
- mHash = null;
-
- byte[] data = getRawData();
- int index = getValueIndex();
-
- // sanity checks
- if( getValueLength() != 0 && getValueLength() != _SHA1_LEN ) {
- throw new ParserException("Invalid value length for Hash-REF-DO!");
- }
-
- if( getValueLength() == _SHA1_LEN ) {
- if( index + getValueLength() > data.length){
- throw new ParserException( "Not enough data for Hash-REF-DO!");
- }
-
- mHash = new byte[getValueLength()];
- System.arraycopy(data, index, mHash, 0, getValueLength());
- }
- }
-
- /**
- * Tags: C1
- * Length: 0 or 20 bytes
- *
- * Value:
- * Hash: identifies a specific device application
- * Empty: refers to all device applications
- *
- * Length:
- * _SHA1_LEN for 20 bytes SHA-1 hash value
- * 0 for empty value field
- */
- @Override
- public void build( ByteArrayOutputStream stream)
- throws DO_Exception {
-
- // sanity checks
- if( mHash != null &&
- !(mHash.length != _SHA1_LEN || mHash.length != 0) ) {
- throw new DO_Exception("Hash value must be " + _SHA1_LEN + " bytes in length!");
- }
-
- stream.write(getTag());
-
- if( mHash == null ) {
- stream.write(0x00);
- } else {
- try {
- stream.write(mHash.length);
- stream.write(mHash);
- } catch( IOException ioe ){
- throw new DO_Exception("Hash could not be written!");
- }
- }
- }
-
- @Override
- public boolean equals( Object obj ){
- boolean equals = false;
-
- if( obj instanceof Hash_REF_DO ){
- equals = super.equals(obj);
-
- if( equals ){
- Hash_REF_DO hash_ref_do = (Hash_REF_DO)obj;
- if( this.mHash == null && hash_ref_do.mHash == null )
- equals &= true;
- else {
- if( this.mHash == null && hash_ref_do.mHash != null ){
- equals &= (hash_ref_do.mHash.length == 0);
- } else if( this.mHash != null && hash_ref_do.mHash == null ){
- equals &= (this.mHash.length == 0);
- } else {
- //equals &= this.mHash.equals(hash_ref_do.mHash);
- equals &= Arrays.equals(mHash, hash_ref_do.mHash);
- }
- }
- }
- }
- return equals;
- }
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/NFC_AR_DO.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/NFC_AR_DO.java
deleted file mode 100644
index 2506874..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/NFC_AR_DO.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright 2012 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.service.security.gpac.dataobjects;
-
-import java.io.ByteArrayOutputStream;
-
-
-/**
- * NFC-AR-DO:
- * In the NFC use case, mobile device application gather information
- * from their associated card application using the SE access API.
- * However, when the card application needs to trigger its associated mobile application,
- * it sends an HCI EVT_TRANSACTION according to ETSI TS 102 622 [102 622] over SWP to the device.
- * This event is handled by the NFC chipset stack which has to start
- * the corresponding device application. Disclosure of this event to malicious applications
- * can lead to phishing and denial of service attacks.
- * To prevent this, it shall be possible to use the applications signature to authorize
- * device applications to receive HCI events issued by the secure element application.
- * An NFC event data object defines an access rule for generating NFC events for
- * a specific terminal application. The NFC event access can be restricted by a rule based
- * on an event access is NEVER/ ALWAYS allowed policy.
- *
- *
- *
- */
-public class NFC_AR_DO extends BerTlv {
-
- public final static int _TAG = 0xD1;
-
- private boolean mNfcAllowed = false;
-
- public NFC_AR_DO(byte[] rawData, int valueIndex, int valueLength) {
- super(rawData, _TAG, valueIndex, valueLength);
- }
-
- public NFC_AR_DO( boolean allowed ){
- super( null, _TAG, 0, 0);
- mNfcAllowed = allowed;
- }
-
- public boolean isNfcAllowed(){
- return mNfcAllowed;
- }
-
- @Override
- /**
- * Tag: D1
- * Length: 1
- * Value:
- * Contains a NFC event access rule:
- * NEVER (00): NFC event access is not allowed
- * ALWAYS(01): NFC event access is allowed
- *
- */
- public void interpret()
- throws ParserException {
-
- mNfcAllowed = false;
-
- byte[] data = getRawData();
- int index = getValueIndex();
-
- if( index + getValueLength() > data.length){
- throw new ParserException( "Not enough data for NFC_AR_DO!");
- }
-
- if( getValueLength() != 1 ){
- throw new ParserException( "Invalid length of NFC-AR-DO!" );
- }
- mNfcAllowed = (data[index] == 0x01);
- }
-
- @Override
- /**
- * Tag: D1
- * Length: 1
- * Value:
- * Contains a NFC event access rule:
- * NEVER (00): NFC event access is not allowed
- * ALWAYS(01): NFC event access is allowed
- *
- */
- public void build( ByteArrayOutputStream stream )
- throws DO_Exception {
-
- // write tag
- stream.write(getTag());
- stream.write(0x01);
- stream.write(mNfcAllowed ? 0x01 : 0x00 );
- }
-
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/ParserException.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/ParserException.java
deleted file mode 100644
index 561f444..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/ParserException.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2012 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.service.security.gpac.dataobjects;
-
-public class ParserException extends Exception {
-
- /**
- *
- */
- private static final long serialVersionUID = -3917637590082486538L;
-
- public ParserException() {
- super();
- // TODO Auto-generated constructor stub
- }
-
-
- public ParserException(String arg0, Throwable arg1) {
- super(arg0, arg1);
- // TODO Auto-generated constructor stub
- }
-
- public ParserException(String arg0) {
- super(arg0);
- // TODO Auto-generated constructor stub
- }
-
- public ParserException(Throwable arg0) {
- super(arg0);
- // TODO Auto-generated constructor stub
- }
-
-
-
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/REF_AR_DO.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/REF_AR_DO.java
deleted file mode 100644
index 9b6f8bf..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/REF_AR_DO.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright 2012 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.service.security.gpac.dataobjects;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-
-/**
- * REF-AR_DO:
- * The REF-AR-DO contains access rules inclusively its corresponding references
- * for the SE application (AID reference) and device application (hash reference).
- *
- *
- *
- */
-public class REF_AR_DO extends BerTlv {
-
- public final static int _TAG = 0xE2;
-
- private REF_DO mRefDo = null;
- private AR_DO mArDo = null;
-
- public REF_AR_DO(byte[] rawData, int valueIndex, int valueLength) {
- super(rawData, _TAG, valueIndex, valueLength);
- }
-
- public REF_AR_DO() {
- super(null, _TAG, 0, 0);
- }
-
- public REF_AR_DO(REF_DO ref_do, AR_DO ar_do ) {
- super(null, _TAG, 0, 0);
- mRefDo = ref_do;
- mArDo = ar_do;
- }
-
- public REF_DO getRefDo() {
- return mRefDo;
- }
-
- public AR_DO getArDo() {
- return mArDo;
- }
-
- /**
- * Interpret data.
- *
- * Tags: E2
- * Length: n
- *
- * Value:
- * REF-DO | AR-DO: A concatenation of an REF-DO and an AR-DO.
- * The REF-DO must correspond to the succeeding AR-DO.
- *
- * Length:
- * n bytes.
- */
- @Override
- public void interpret()
- throws ParserException {
-
- mRefDo = null;
- mArDo = null;
-
- byte[] data = getRawData();
- int index = getValueIndex();
-
- if( index + getValueLength() > data.length){
- throw new ParserException( "Not enough data for AR_DO!");
- }
-
- do {
- BerTlv temp = BerTlv.decode(data, index);
- if( temp.getTag() == REF_DO._TAG ) { // REF-DO
- mRefDo = new REF_DO( data, temp.getValueIndex(), temp.getValueLength());
- mRefDo.interpret();
- } else if( temp.getTag() == AR_DO._TAG ) { // AR-DO
- mArDo = new AR_DO( data, temp.getValueIndex(), temp.getValueLength());
- mArDo.interpret();
- } else {
- // uncomment following line if a more restrictive
- // behavior is necessary.
- //throw new ParserException("Invalid DO in REF-AR-DO!");
- }
- index = temp.getValueIndex() + temp.getValueLength();
- } while( getValueIndex() + getValueLength() > index );
-
- // check for mandatory TLVs.
- if( mRefDo == null ) {
- throw new ParserException("Missing Ref-DO in REF-AR-DO!");
- }
- if( mArDo == null ) {
- throw new ParserException("Missing AR-DO in REF-AR-DO!");
- }
- }
-
-
- /**
- * Tag: E2
- * Length: n
- * Value:
- * REF-DO | AR-DO: A concatenation of an REF-DO and an AR-DO.
- */
- @Override
- public void build(ByteArrayOutputStream stream )
- throws DO_Exception {
- ByteArrayOutputStream temp = new ByteArrayOutputStream();
-
- if( mRefDo == null || mArDo == null ){
- throw new DO_Exception( "REF-AR-DO: Required DO missing!");
- }
- stream.write(getTag());
-
- mRefDo.build(temp);
- mArDo.build(temp);
-
- byte[] data = temp.toByteArray();
- BerTlv.encodeLength(data.length, stream);
- try {
- stream.write(data);
- } catch (IOException e) {
- throw new DO_Exception("REF-AR-DO Memory IO problem! " + e.getMessage());
- }
- }
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/REF_DO.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/REF_DO.java
deleted file mode 100644
index a36b71a..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/REF_DO.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright 2012 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.service.security.gpac.dataobjects;
-
-import java.io.ByteArrayOutputStream;
-import java.util.Arrays;
-
-/**
- * REF-DO:
- * The REF-DO contains a reference to uniquely assign
- * or identify an access rule for an SE application (with an AID reference)
- * and for a device application (with a hash reference).
- *
- *
- *
- */
-public class REF_DO extends BerTlv {
-
- public final static int _TAG = 0xE1;
-
- private AID_REF_DO mAidDo = null;
- private Hash_REF_DO mHashDo = null;
-
- public REF_DO(byte[] rawData, int valueIndex, int valueLength) {
- super(rawData, _TAG, valueIndex, valueLength);
- }
-
- public REF_DO(AID_REF_DO aid_ref_do, Hash_REF_DO hash_ref_do ) {
- super(null, _TAG, 0, 0);
- mAidDo = aid_ref_do;
- mHashDo = hash_ref_do;
- }
-
- @Override
- public String toString(){
- StringBuilder b = new StringBuilder();
- b.append("REF_DO: ");
- if( mAidDo != null ){
- b.append(mAidDo.toString());
- b.append(' ' );
- }
- if( mHashDo != null ){
- b.append(mHashDo.toString());
- }
- return b.toString();
- }
-
-
- public AID_REF_DO getAidDo() {
- return mAidDo;
- }
-
- public Hash_REF_DO getHashDo() {
- return mHashDo;
- }
-
- /**
- * Interpret data.
- *
- * Tags: E1 -> Length: n
- *
- * Value:
- * AID-REF-DO | Hash-REF-DO: A concatenation of an AID-REF-DO and a Hash-REF-DO.
- *
- * Length:
- * n bytes.
- */
- @Override
- public void interpret()
- throws ParserException {
-
- mAidDo = null;
- mHashDo = null;
-
- byte[] data = getRawData();
- int index = getValueIndex();
-
- if( index + getValueLength() > data.length){
- throw new ParserException( "Not enough data for AR_DO!");
- }
-
- do {
- BerTlv temp = BerTlv.decode(data, index);
-
- if( temp.getTag() == AID_REF_DO._TAG || temp.getTag() == AID_REF_DO._TAG_DEFAULT_APPLICATION ) { // AID-REF-DO
- mAidDo = new AID_REF_DO( data, temp.getTag(), temp.getValueIndex(), temp.getValueLength());
- mAidDo.interpret();
- } else if( temp.getTag() == Hash_REF_DO._TAG ) { // Hash-REF-DO
- mHashDo = new Hash_REF_DO( data, temp.getValueIndex(), temp.getValueLength());
- mHashDo.interpret();
- } else {
- // uncomment following line if a more restrictive
- // behaviour is necessary.
- // throw new ParserException("Invalid DO in REF-DO!");
- }
- index = temp.getValueIndex() + temp.getValueLength();
- } while( getValueIndex() + getValueLength() > index );
-
- // check if there is a AID-REF-DO
- if( mAidDo == null ){
- throw new ParserException("Missing AID-REF-DO in REF-DO!");
- }
- // check if there is a Hash-REF-DO
- if( mHashDo == null ){
- throw new ParserException("Missing Hash-REF-DO in REF-DO!");
- }
- }
-
- /**
- * Tag: E1
- * Length: n
- * Value:
- * AID-REF-DO | Hash-REF-DO: A concatenation of an AID-REF-DO and a Hash-REF-DO.
- */
- @Override
- public void build(ByteArrayOutputStream stream )
- throws DO_Exception {
- ByteArrayOutputStream temp = new ByteArrayOutputStream();
-
- if( mAidDo == null || mHashDo == null ){
- throw new DO_Exception( "REF-DO: Required DO missing!");
- }
-
- mAidDo.build(temp);
- mHashDo.build(temp);
-
- byte[] data = temp.toByteArray();
- BerTlv tlv = new BerTlv( data, getTag(), 0, data.length );
- tlv.build(stream);
- }
-
- @Override
- public boolean equals(Object obj ){
- boolean equals = false;
- if( obj instanceof REF_DO ){
- equals = super.equals(obj);
- REF_DO ref_do = (REF_DO)obj;
- if( mAidDo == null && ref_do.mAidDo == null ){
- equals &= true;
- } else if( mAidDo != null && ref_do.mAidDo != null ){
- equals &= mAidDo.equals(ref_do.mAidDo);
- } else {
- equals = false;
- }
- if( mHashDo == null && ref_do.mHashDo == null ){
- equals &= true;
- } else if( mHashDo != null && ref_do.mHashDo != null ){
- equals &= mHashDo.equals(ref_do.mHashDo);
- } else {
- equals = false;
- }
- }
- return equals;
- }
-
- @Override
- public int hashCode () {
- ByteArrayOutputStream stream = new ByteArrayOutputStream();
- try {
- this.build(stream);
- } catch (DO_Exception e) {
- return 1;
- }
- byte[] data = stream.toByteArray();
- int hash = Arrays.hashCode(data);
- //int hash = data.hashCode();
- return hash;
- }
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/Response_ALL_AR_DO.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/Response_ALL_AR_DO.java
deleted file mode 100644
index 685765c..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/Response_ALL_AR_DO.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright 2012 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.service.security.gpac.dataobjects;
-
-import java.util.ArrayList;
-
-/**
- * Response-ALL-AR-DO
- * All access rules stored in the Secure Element have to be returned by the ARA-M
- * after a GET DATA (All) command in the response data field within a Response-ALL-AR-DO.
- * The GET DATA command can also be applied iteratively with subsequent GET DATA (Next) commands
- * if the Response-ALL-AR-DO is too large for the GET DATA (All) command.
- * The length field of the Response-ALL-AR-DO shall always contain the full length
- * of the DOs value to determine on device side if a subsequent GET DATA (Next) command
- * is needed.
- *
- *
- *
- */
-public class Response_ALL_AR_DO extends BerTlv {
-
- public final static int _TAG = 0xFF40;
-
- private ArrayList<REF_AR_DO> mRefArDos = new ArrayList<REF_AR_DO>();
-
- public Response_ALL_AR_DO(byte[] rawData, int valueIndex,
- int valueLength) {
- super(rawData, _TAG, valueIndex, valueLength);
- }
-
- public ArrayList<REF_AR_DO> getRefArDos(){
- return mRefArDos;
- }
-
- @Override
- /**
- * Tag: FF 40
- *
- * Length: n or 0
- * If n is equal to zero, then there are no rules to fetch.
- *
- * Value:
- * REF-AR-DO 1..n or empty
- * An REF-AR-DO if access rules exist.
- * REF-AR-DOs can occur several times in a concatenated DO chain if several REF-AR-DO exist
- * on the SE.
- * The value is empty if access rules do not exist.
- */
- public void interpret()
- throws ParserException {
-
- mRefArDos.clear();
-
- byte[] data = getRawData();
- int index = getValueIndex();
-
- if( getValueLength() == 0 ){
- // No Access rule available for the requested reference.
- return;
- }
-
- if( index + getValueLength() > data.length){
- throw new ParserException( "Not enough data for Response_AR_DO!");
- }
-
- BerTlv temp;
- int currentPos = index;
- int endPos = index + getValueLength();
- do {
- temp = BerTlv.decode(data, currentPos);
-
- REF_AR_DO tempRefArDo;
-
- if( temp.getTag() == REF_AR_DO._TAG) { // REF-AR-DO tag
- tempRefArDo = new REF_AR_DO( data, temp.getValueIndex(), temp.getValueLength());
- tempRefArDo.interpret();
- mRefArDos.add(tempRefArDo);
- } else {
- // uncomment following line if a more restrictive
- // behavior is necessary.
- //throw new ParserException("Invalid DO in Response-ALL-AR-DO!");
- }
- // get REF-AR-DOs as long as data is available.
- currentPos = temp.getValueIndex() + temp.getValueLength();
- } while( currentPos < endPos );
- }
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/Response_ARAC_AID_DO.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/Response_ARAC_AID_DO.java
deleted file mode 100644
index 0d16ec0..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/Response_ARAC_AID_DO.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright 2012 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.service.security.gpac.dataobjects;
-
-import java.util.ArrayList;
-
-
-
-/**
- * Response_ARAC_AID_DO
- *
- * A list of AIDs containing an AID for each ARA-C.
- *
- * In response to STORE DATA (Command-Get-ClientAIDs-DO),
- * the ARA-M shall return the AID of each of the ARA-Cs
- * currently registered within a Response-ARAC-AID-DO.
- *
- *
- *
- */
-public class Response_ARAC_AID_DO extends BerTlv {
-
- public final static int _TAG = 0xFF70;
-
- private ArrayList<AID_REF_DO> mAidDos = new ArrayList<AID_REF_DO>();
-
- public Response_ARAC_AID_DO(byte[] rawData, int valueIndex,
- int valueLength) {
- super(rawData, _TAG, valueIndex, valueLength);
- }
-
- public ArrayList<AID_REF_DO> getAidRefDos(){
- return mAidDos;
- }
-
- @Override
- /**
- * Tag: FF 70
- *
- * Length: n or 0
- * If n is equal to zero, then there are no rules to fetch.
- *
- * Value:
- * AID-REF-DO 1..n or empty
- * AID-REF-DOs can occur several times in a concatenated DO chain if several ARA-C instances exist
- * on the SE.
- * The value is empty if no ARA-C instance exist.
- */
- public void interpret()
- throws ParserException {
-
- mAidDos.clear();
-
- byte[] data = getRawData();
- int index = getValueIndex();
-
- if( getValueLength() == 0 ){
- // No Access rule available for the requested reference.
- return;
- }
-
- if( index + getValueLength() > data.length){
- throw new ParserException( "Not enough data for Response_ARAC_AID_DO!");
- }
-
- BerTlv temp;
- int currentPos = index;
- int endPos = index + getValueLength();
- do {
- temp = BerTlv.decode(data, currentPos);
-
- AID_REF_DO tempAidDo;
-
- if( temp.getTag() == AID_REF_DO._TAG ||
- temp.getTag() == AID_REF_DO._TAG_DEFAULT_APPLICATION ) {
- tempAidDo = new AID_REF_DO( data, temp.getTag(), temp.getValueIndex(), temp.getValueLength());
- tempAidDo.interpret();
- mAidDos.add(tempAidDo);
- } else {
- // uncomment following line if a more restrictive
- // behavior is necessary.
- //throw new ParserException("Invalid DO in Response_ARAC_AID_DO!");
- }
- // get AID-REF-DOs as long as data is available.
- currentPos = temp.getValueIndex() + temp.getValueLength();
- } while( currentPos < endPos );
- }
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/Response_AR_DO.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/Response_AR_DO.java
deleted file mode 100644
index 2d11acf..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/Response_AR_DO.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright 2012 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.service.security.gpac.dataobjects;
-
-
-
-/**
- * Response-AR-DO
- * If access rules can be found in the Secure Element which corresponds to the specified AR-DO
- * in the GET DATA (Specific) command these must be returned by the ARA-M
- * in the response data field within a Response-AR-DO.
- * The GET DATA command can also be applied iteratively with subsequent GET DATA (next) commands
- * if the Response-AR-DO is too large for the GET DATA (Specific) command.
- * The length field of the Response-AR-DO shall always contain the full length of the DOs value
- * to determine on device side if a subsequent GET DATA (Next) command is needed.
- *
- *
- *
- */
-public class Response_AR_DO extends BerTlv {
-
- public final static int _TAG = 0xFF50;
-
- private AR_DO mArDo = null;
-
- public Response_AR_DO(byte[] rawData, int valueIndex,
- int valueLength) {
- super(rawData, _TAG, valueIndex, valueLength);
- }
-
- public AR_DO getArDo(){
- return mArDo;
- }
-
- @Override
- /**
- * Tag: FF 50
- *
- * Length: n or 0
- * If n is equal to zero, then there are no rules to fetch.
- *
- * Value:
- * An AR-DO if the referenced access rules exist.
- * The value is empty if access rules do not exist to the defined reference
- */
- public void interpret()
- throws ParserException {
-
- byte[] data = getRawData();
- int index = getValueIndex();
-
- if( getValueLength() == 0 ){
- // No Access rule available for the requested reference.
- return;
- }
-
- if( index + getValueLength() > data.length){
- throw new ParserException( "Not enough data for Response_AR_DO!");
- }
-
- int currentPos = index;
- int endPos = index + getValueLength();
- do {
- BerTlv temp = BerTlv.decode(data, currentPos);
-
- if( temp.getTag() == AR_DO._TAG) { // AR-DO tag
- mArDo = new AR_DO( data, temp.getValueIndex(), temp.getValueLength());
- mArDo.interpret();
- } else {
- // un-comment following line if a more restrictive
- // behavior is necessary.
- //throw new ParserException("Invalid DO in Response-AR-DO!");
- }
- // get REF-AR-DOs as long as data is available.
- currentPos = temp.getValueIndex() + temp.getValueLength();
- } while( currentPos < endPos );
- }
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/Response_DO_Factory.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/Response_DO_Factory.java
deleted file mode 100644
index a419a44..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/Response_DO_Factory.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2012 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.service.security.gpac.dataobjects;
-
-
-
-public class Response_DO_Factory {
-
- public static BerTlv createDO( byte[] data ) throws ParserException{
-
- BerTlv tempTlv = BerTlv.decode(data, 0 );
-
- BerTlv retTlv = null;
-
- switch( tempTlv.getTag() ){
-
- case Response_RefreshTag_DO._TAG:
- retTlv = new Response_RefreshTag_DO( data, tempTlv.getValueIndex(), tempTlv.getValueLength());
- break;
- case Response_ARAC_AID_DO._TAG:
- retTlv = new Response_ARAC_AID_DO( data, tempTlv.getValueIndex(), tempTlv.getValueLength());
- break;
-
- case Response_ALL_AR_DO._TAG:
- retTlv = new Response_ALL_AR_DO( data, tempTlv.getValueIndex(), tempTlv.getValueLength());
- break;
- case Response_AR_DO._TAG:
- retTlv = new Response_AR_DO( data, tempTlv.getValueIndex(), tempTlv.getValueLength());
- break;
- default:
- retTlv = tempTlv;
- }
-
- retTlv.interpret();
-
- return retTlv;
- }
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/Response_RefreshTag_DO.java b/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/Response_RefreshTag_DO.java
deleted file mode 100644
index 801fd60..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/security/gpac/dataobjects/Response_RefreshTag_DO.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2012 Giesecke & Devrient GmbH.
- *
- * 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 org.simalliance.openmobileapi.service.security.gpac.dataobjects;
-
-
-/**
- * Response-RefreshTag DO
- * The GET DATA (RefreshTag) command has to return a refresh tag indicating changes
- * in the access control data in a RefreshTag DO.
- * This refresh tag is an attribute (8-byte random number) of the ARA-M which is
- * newly generated if the ARA-M detects an update of access control data
- * in the Secure Element.
- *
- *
- *
- */
-public class Response_RefreshTag_DO extends BerTlv {
-
- public final static int _TAG = 0xDF20;
-
- private long mRefreshTag;
- private byte[] mRefreshTagArray = null;
-
- public Response_RefreshTag_DO(byte[] rawData, int valueIndex,
- int valueLength) {
- super(rawData, _TAG, valueIndex, valueLength);
-
- }
-
- public long getRefreshTag(){
- return mRefreshTag;
- }
-
- public byte[] getRefreshTagArray(){
- return mRefreshTagArray;
- }
-
- @Override
- /**
- * Tag: DF 20
- * Length: 8 bytes
- * Value:
- * The RefreshTag is an 8 bytes random number.
- * A new RefreshTag value indicates changes in the access control data
- * stored in the SE.
- */
- public void interpret()
- throws ParserException {
-
- mRefreshTag = 0;
-
- if( super.getValueLength() != 8 ){
- throw new ParserException( "Invalid length of RefreshTag DO!" );
- }
-
- byte[] data = super.getRawData();
- int index = super.getValueIndex();
-
- if( index + super.getValueLength() > data.length ){
- throw new ParserException( "Not enough data for RefreshTag DO!" );
- }
- mRefreshTagArray = new byte[super.getValueLength()];
- System.arraycopy(data, index, mRefreshTagArray, 0, mRefreshTagArray.length);
-
- long temp;
- temp = data[index++];
- mRefreshTag =(temp << 56L);
- temp = data[index++];
- mRefreshTag +=(temp << 48L);
- temp = data[index++];
- mRefreshTag +=(temp << 40L);
- temp = data[index++];
- mRefreshTag +=(temp << 32L);
- temp = data[index++];
- mRefreshTag +=(temp << 24L);
- temp = data[index++];
- mRefreshTag +=(temp << 16L);
- temp = data[index++];
- mRefreshTag +=(temp << 8L);
- temp = data[index++];
- mRefreshTag +=(temp);
- }
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/terminals/ASSDTerminal.java b/smart-card-service/src/org/simalliance/openmobileapi/service/terminals/ASSDTerminal.java
deleted file mode 100644
index 4407476..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/terminals/ASSDTerminal.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright (C) 2011, The Android Open Source Project
- *
- * 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.
-
-
- * Contributed by: Giesecke & Devrient GmbH.
-*/
-
-package org.simalliance.openmobileapi.service.terminals;
-
-import android.content.Context;
-
-
-import java.util.MissingResourceException;
-import java.util.NoSuchElementException;
-
-import org.simalliance.openmobileapi.service.CardException;
-import org.simalliance.openmobileapi.service.SmartcardService;
-import org.simalliance.openmobileapi.service.Terminal;
-
-final class ASSDTerminal extends Terminal {
-
- private static boolean JNILoaded = false;
-
- public ASSDTerminal(Context context) {
- super(SmartcardService._SD_TERMINAL, context);
- }
-
- @Override
- protected void internalConnect() throws CardException {
- if (JNILoaded == false) {
- throw new CardException("JNI failed");
- }
-
- try {
- if (Open() == false) {
- throw new CardException("open SE failed");
- }
- } catch (Exception e) {
- throw new CardException("open SE failed");
- }
- mDefaultApplicationSelectedOnBasicChannel = true;
- mIsConnected = true;
- }
-
- @Override
- protected void internalDisconnect() throws CardException {
- if (JNILoaded == false) {
- throw new CardException("JNI failed");
- }
-
- try {
- Close();
- } catch (Exception e) {
- } finally {
- mIsConnected = false;
- }
- }
-
- public boolean isCardPresent() throws CardException {
- if (JNILoaded == false) {
- return false;
- }
-
- try {
- return IsPresent();
- } catch (Exception e) {
- return false;
- }
- }
-
- @Override
- protected byte[] internalTransmit(byte[] command) throws CardException {
- if (JNILoaded == false) {
- throw new CardException("JNI failed");
- }
-
- try {
- byte[] response = Transmit(command);
- if (response == null) {
- throw new CardException("transmit failed");
- }
- return response;
- } catch (Exception e) {
- throw new CardException("transmit failed");
- }
- }
-
- @Override
- protected void internalCloseLogicalChannel(int channelNumber) throws CardException {
- if (channelNumber > 0) {
- byte cla = (byte) channelNumber;
- if (channelNumber > 3) {
- cla |= 0x40;
- }
- byte[] manageChannelClose = new byte[] {
- cla, 0x70, (byte) 0x80, (byte) channelNumber
- };
- transmit(manageChannelClose, 2, 0x9000, 0xFFFF, "MANAGE CHANNEL");
- }
- }
-
- @Override
- protected int internalOpenLogicalChannel() throws Exception {
-
- mSelectResponse = null;
- byte[] manageChannelCommand = new byte[] {
- 0x00, 0x70, 0x00, 0x00, 0x01
- };
- byte[] rsp = transmit(manageChannelCommand, 3, 0x9000, 0xFFFF, "MANAGE CHANNEL");
- if (rsp.length != 3) {
- throw new MissingResourceException("unsupported MANAGE CHANNEL response data", "", "");
- }
- int channelNumber = rsp[0] & 0xFF;
- if (channelNumber == 0 || channelNumber > 19) {
- throw new MissingResourceException("invalid logical channel number returned", "", "");
- }
-
- return channelNumber;
- }
-
- @Override
- protected int internalOpenLogicalChannel(byte[] aid) throws Exception {
- int channelNumber = internalOpenLogicalChannel();
-
- if (aid == null) {
- throw new NullPointerException("aid must not be null");
- }
- mSelectResponse = null;
- byte[] selectCommand = new byte[aid.length + 6];
- selectCommand[0] = (byte) channelNumber;
- if (channelNumber > 3) {
- selectCommand[0] |= 0x40;
- }
- selectCommand[1] = (byte) 0xA4;
- selectCommand[2] = 0x04;
- selectCommand[4] = (byte) aid.length;
- System.arraycopy(aid, 0, selectCommand, 5, aid.length);
- try {
- mSelectResponse = transmit(selectCommand, 2, 0x9000, 0xFFFF, "SELECT");
- } catch (CardException e) {
- internalCloseLogicalChannel(channelNumber);
- throw new NoSuchElementException(e.getMessage());
- }
-
- return channelNumber;
- }
-
- static {
- try {
- Runtime.getRuntime().loadLibrary("assd");
- JNILoaded = true;
- } catch (Throwable t) {
- }
- }
-
- @Override
- public byte[] getAtr() {
- return null;
- }
-
- private native void Close() throws Exception;
-
- private native boolean Open() throws Exception;
-
- private native boolean IsPresent() throws Exception;
-
- private native byte[] Transmit(byte[] command) throws Exception;
-}
\ No newline at end of file
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/terminals/P61SpiTerminal.java b/smart-card-service/src/org/simalliance/openmobileapi/service/terminals/P61SpiTerminal.java
deleted file mode 100644
index e46676d..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/terminals/P61SpiTerminal.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright (C) 2011, The Android Open Source Project
- *
- * 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.
- */
-/*
- * Contributed by: Giesecke & Devrient GmbH.
- */
-
-package src.org.simalliance.openmobileapi.service.terminals;
-
-import android.content.Context;
-import android.os.Binder;
-import android.os.Bundle;
-import android.util.Log;
-import android.content.pm.PackageManager;
-import android.ese.spi.EseSpiAdapter;
-
-import java.util.MissingResourceException;
-import java.util.NoSuchElementException;
-import org.simalliance.openmobileapi.service.Terminal;
-import org.simalliance.openmobileapi.service.CardException;
-import org.simalliance.openmobileapi.service.SmartcardService;
-
-
-
-public class P61SpiTerminal extends Terminal {
-
- private Binder binder = new Binder();
- private String TAG = "P61SPITerminal";
- EseSpiAdapter mSpiAdapter;
-
- public P61SpiTerminal(Context context) {
- super(SmartcardService._P61Spi_TERMINAL, context);
-
- try {
- mSpiAdapter = EseSpiAdapter.getSpiAdapter(mContext);
- if(mSpiAdapter == null) {
- throw new CardException("Cannot get SPI Default Adapter");
- }
-
- } catch (Exception e) {
- }
- }
-
- public boolean isCardPresent() throws CardException {
-
- return true; //mSpiAdapter.isEnabled(); // Enabled always for testing
- }
-
- @Override
- protected void internalConnect() throws CardException {
- //spi initialization
- try {
- if(!mSpiAdapter.isEnabled()){
- mSpiAdapter.enable();
- }
- } catch (Exception e) {
- throw new CardException("open SE failed");
- }
- mDefaultApplicationSelectedOnBasicChannel = true;
- mIsConnected = true;
- }
-
- @Override
- protected void internalDisconnect() throws CardException {
- //spi deinitialization
- try {
- if(mSpiAdapter.isEnabled()){
- // mSpiAdapter.disable();
- }
- } catch (Exception e) {
- throw new CardException("close SE failed");
- }
- }
-
- @Override
- protected byte[] internalTransmit(byte[] command) throws CardException {
-
- try {
- byte[] respData = mSpiAdapter.exchangeData("org.simalliance.openmobileapi.service", command);
- if (respData == null) {
- throw new CardException("exchange APDU failed");
- }
- return respData;
- } catch (Exception e) {
- throw new CardException("exchange APDU failed");
- }
- }
-
-
-// SPI won't support getAtr()
- @Override
- public byte[] getAtr() {
- return null;
- }
-
- @Override
- protected int internalOpenLogicalChannel() throws Exception {
-
- mSelectResponse = null;
- byte[] manageChannelCommand = new byte[] {
- 0x00, 0x70, 0x00, 0x00, 0x01
- };
- byte[] rsp = transmit(manageChannelCommand, 2, 0x9000, 0, "MANAGE CHANNEL");
- if ((rsp.length == 2) && ((rsp[0] == (byte) 0x68) && (rsp[1] == (byte) 0x81))) {
- throw new NoSuchElementException("logical channels not supported");
- }
- if (rsp.length == 2 && (rsp[0] == (byte) 0x6A && rsp[1] == (byte) 0x81)) {
- throw new MissingResourceException("no free channel available", "", "");
- }
- if (rsp.length != 3) {
- throw new MissingResourceException("unsupported MANAGE CHANNEL response data", "", "");
- }
- int channelNumber = rsp[0] & 0xFF;
- if (channelNumber == 0 || channelNumber > 19) {
- throw new MissingResourceException("invalid logical channel number returned", "", "");
- }
-
- return channelNumber;
- }
-
- @Override
- protected int internalOpenLogicalChannel(byte[] aid) throws Exception {
-
- if (aid == null) {
- throw new NullPointerException("aid must not be null");
- }
- mSelectResponse = null;
-
- byte[] manageChannelCommand = new byte[] {
- 0x00, 0x70, 0x00, 0x00, 0x01
- };
- byte[] rsp = transmit(manageChannelCommand, 2, 0x9000, 0, "MANAGE CHANNEL");
- if ((rsp.length == 2) && ((rsp[0] == (byte) 0x68) && (rsp[1] == (byte) 0x81))) {
- throw new NoSuchElementException("logical channels not supported");
- }
- if (rsp.length == 2 && (rsp[0] == (byte) 0x6A && rsp[1] == (byte) 0x81)) {
- throw new MissingResourceException("no free channel available", "", "");
- }
- if (rsp.length != 3) {
- throw new MissingResourceException("unsupported MANAGE CHANNEL response data", "", "");
- }
- int channelNumber = rsp[0] & 0xFF;
- if (channelNumber == 0 || channelNumber > 19) {
- throw new MissingResourceException("invalid logical channel number returned", "", "");
- }
-
- byte[] selectCommand = new byte[aid.length + 6];
- selectCommand[0] = (byte) channelNumber;
- if (channelNumber > 3) {
- selectCommand[0] |= 0x40;
- }
- selectCommand[1] = (byte) 0xA4;
- selectCommand[2] = 0x04;
- selectCommand[4] = (byte) aid.length;
- System.arraycopy(aid, 0, selectCommand, 5, aid.length);
- try {
- mSelectResponse = transmit(selectCommand, 2, 0x9000, 0xFFFF, "SELECT");
- } catch (CardException exp) {
- internalCloseLogicalChannel(channelNumber);
- throw new NoSuchElementException(exp.getMessage());
- }
-
- return channelNumber;
- }
-
- @Override
- protected void internalCloseLogicalChannel(int channelNumber) throws CardException {
- if (channelNumber > 0) {
- byte cla = (byte) channelNumber;
- if (channelNumber > 3) {
- cla |= 0x40;
- }
- byte[] manageChannelClose = new byte[] {
- cla, 0x70, (byte) 0x80, (byte) channelNumber
- };
- transmit(manageChannelClose, 2, 0x9000, 0xFFFF, "MANAGE CHANNEL");
- }
- }
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/terminals/SmartMxTerminal.java b/smart-card-service/src/org/simalliance/openmobileapi/service/terminals/SmartMxTerminal.java
deleted file mode 100644
index be5d49f..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/terminals/SmartMxTerminal.java
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright (C) 2011, The Android Open Source Project
- *
- * 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.
-
-
- * Contributed by: Giesecke & Devrient GmbH.*/
- /******************************************************************************
- *
- * The original Work has been changed by NXP Semiconductors.
- *
- * Copyright (C) 2015 NXP Semiconductors
- *
- * 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 org.simalliance.openmobileapi.service.terminals;
-
-import android.content.Context;
-import android.nfc.INfcAdapterExtras;
-import android.nfc.NfcAdapter;
-import android.os.Binder;
-import android.os.Bundle;
-import android.util.Log;
-
-import java.util.MissingResourceException;
-import java.util.NoSuchElementException;
-
-import org.simalliance.openmobileapi.service.CardException;
-import org.simalliance.openmobileapi.service.SmartcardService;
-import org.simalliance.openmobileapi.service.Terminal;
-
-
-
-public class SmartMxTerminal extends Terminal {
-
- private INfcAdapterExtras ex;
- private Binder binder = new Binder();
- private String TAG = "SmartMxTerminal";
- public SmartMxTerminal(Context context) {
- super(SmartcardService._eSE_TERMINAL, context);
- }
-
- public boolean isCardPresent() throws CardException {
- try {
- NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
- if(adapter == null) {
- throw new CardException("Cannot get NFC Default Adapter");
- }
- return adapter.isEnabled();
- } catch (Exception e) {
- return false;
- }
- }
-
- @Override
- protected void internalConnect() throws CardException {
- NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
- if(adapter == null) {
- throw new CardException("Cannot get NFC Default Adapter");
- }
-
- ex = adapter.getNfcAdapterExtrasInterface();
- if(ex == null) {
- throw new CardException("Cannot get NFC Extra interface");
- }
-
- try {
- Bundle b = ex.open("org.simalliance.openmobileapi.service", binder);
- if (b == null) {
- throw new CardException("open SE failed");
- }
- } catch (Exception e) {
- throw new CardException("open SE failed");
- }
- mDefaultApplicationSelectedOnBasicChannel = true;
- mIsConnected = true;
- }
-
- @Override
- protected void internalDisconnect() throws CardException {
- try {
- Bundle b = ex.close("org.simalliance.openmobileapi.service", binder);
- if (b == null) {
- throw new CardException("close SE failed");
- }
- } catch (Exception e) {
- throw new CardException("close SE failed");
- }
- }
-
- @Override
- protected byte[] internalTransmit(byte[] command) throws CardException {
- try {
- Bundle b = ex.transceive("org.simalliance.openmobileapi.service", command);
- if (b == null) {
- throw new CardException("exchange APDU failed");
- }
- return b.getByteArray("out");
- } catch (Exception e) {
- throw new CardException("exchange APDU failed");
- }
- }
-
- @Override
- public byte[] getAtr() {
- byte uid[] = null;
- try {
- uid = ex.getSecureElementUid("org.simalliance.openmobileapi.service");
- return uid;
- } catch (Exception e) {
- Log.d(TAG, e.toString());
- Log.d(TAG,"getAtr: get Secure Element Uid failed");
- }
- return uid;
- }
-
- @Override
- protected int internalOpenLogicalChannel() throws Exception {
- mSelectResponse = null;
- byte[] manageChannelCommand = new byte[] {
- 0x00, 0x70, 0x00, 0x00, 0x01
- };
- byte[] rsp = transmit(manageChannelCommand, 2, 0x9000, 0, "MANAGE CHANNEL");
- if ((rsp.length == 2) && ((rsp[0] == (byte) 0x68) && (rsp[1] == (byte) 0x81))) {
- throw new NoSuchElementException("logical channels not supported");
- }
- if (rsp.length == 2 && (rsp[0] == (byte) 0x6A && rsp[1] == (byte) 0x81)) {
- throw new MissingResourceException("no free channel available", "", "");
- }
- if (rsp.length != 3) {
- throw new MissingResourceException("unsupported MANAGE CHANNEL response data", "", "");
- }
- int channelNumber = rsp[0] & 0xFF;
- if (channelNumber == 0 || channelNumber > 19) {
- throw new MissingResourceException("invalid logical channel number returned", "", "");
- }
-
- return channelNumber;
- }
-
- @Override
- protected int internalOpenLogicalChannel(byte[] aid) throws Exception {
- if (aid == null) {
- throw new NullPointerException("aid must not be null");
- }
- mSelectResponse = null;
-
- byte[] manageChannelCommand = new byte[] {
- 0x00, 0x70, 0x00, 0x00, 0x01
- };
- byte[] rsp = transmit(manageChannelCommand, 2, 0x9000, 0, "MANAGE CHANNEL");
- if ((rsp.length == 2) && ((rsp[0] == (byte) 0x68) && (rsp[1] == (byte) 0x81))) {
- throw new NoSuchElementException("logical channels not supported");
- }
- if (rsp.length == 2 && (rsp[0] == (byte) 0x6A && rsp[1] == (byte) 0x81)) {
- throw new MissingResourceException("no free channel available", "", "");
- }
- if (rsp.length != 3) {
- throw new MissingResourceException("unsupported MANAGE CHANNEL response data", "", "");
- }
- int channelNumber = rsp[0] & 0xFF;
- if (channelNumber == 0 || channelNumber > 19) {
- throw new MissingResourceException("invalid logical channel number returned", "", "");
- }
-
- byte[] selectCommand = new byte[aid.length + 6];
- selectCommand[0] = (byte) channelNumber;
- if (channelNumber > 3) {
- selectCommand[0] |= 0x40;
- }
- selectCommand[1] = (byte) 0xA4;
- selectCommand[2] = 0x04;
- selectCommand[4] = (byte) aid.length;
- System.arraycopy(aid, 0, selectCommand, 5, aid.length);
- try {
- mSelectResponse = transmit(selectCommand, 2, 0x9000, 0xFFFF, "SELECT");
- } catch (CardException exp) {
- internalCloseLogicalChannel(channelNumber);
- throw new NoSuchElementException(exp.getMessage());
- }
-
- return channelNumber;
- }
-
- @Override
- protected void internalCloseLogicalChannel(int channelNumber) throws CardException {
- if (channelNumber > 0) {
- byte cla = (byte) channelNumber;
- if (channelNumber > 3) {
- cla |= 0x40;
- }
- byte[] manageChannelClose = new byte[] {
- cla, 0x70, (byte) 0x80, (byte) channelNumber
- };
- transmit(manageChannelClose, 2, 0x9000, 0xFFFF, "MANAGE CHANNEL");
- }
- }
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/terminals/UiccTerminal.java b/smart-card-service/src/org/simalliance/openmobileapi/service/terminals/UiccTerminal.java
deleted file mode 100644
index df82011..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/terminals/UiccTerminal.java
+++ /dev/null
@@ -1,341 +0,0 @@
-/*
- Copyright (C) 2011, The Android Open Source Project
- *
- * 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.
-
-
- * Contributed by: Giesecke & Devrient GmbH.
-
-
-package org.simalliance.openmobileapi.service.terminals;
-
-import android.content.Context;
-import org.simalliance.openmobileapi.service.CardException;
-import org.simalliance.openmobileapi.service.SmartcardService;
-import org.simalliance.openmobileapi.service.Terminal;
-import org.simalliance.openmobileapi.service.Util;
-import org.simalliance.openmobileapi.service.security.arf.SecureElementException;
-
-
-import android.os.ServiceManager;
-import android.os.SystemProperties;
-import android.util.Log;
-
-import com.android.internal.telephony.ITelephony;
-import com.android.internal.telephony.TelephonyProperties;
-
-import java.util.MissingResourceException;
-import java.util.NoSuchElementException;
-
-public class UiccTerminal extends Terminal {
-
- private ITelephony manager = null;
-
- private int[] channelId = new int[20];
-
- private String currentSelectedFilePath = "";
-
- private byte[] mAtr = null;
-
- public UiccTerminal(Context context) {
- super(SmartcardService._UICC_TERMINAL, context);
-
- try {
- manager = ITelephony.Stub.asInterface(ServiceManager
- .getService(Context.TELEPHONY_SERVICE));
- } catch (Exception ex) {
- }
-
- for (int i = 0; i < channelId.length; i++) {
- channelId[i] = 0;
- }
- }
-
- @Override
- public boolean isCardPresent() throws CardException {
- String prop = SystemProperties
- .get(TelephonyProperties.PROPERTY_SIM_STATE);
- if ("READY".equals(prop)) {
- return true;
- }
- return false;
- }
-
- @Override
- protected void internalConnect() throws CardException {
- if (manager == null) {
- throw new CardException("Cannot connect to Telephony Service");
- }
- mIsConnected = true;
- }
-
- @Override
- protected void internalDisconnect() throws CardException {
- }
-
- private byte[] stringToByteArray(String s) {
- byte[] b = new byte[s.length() / 2];
- for (int i = 0; i < b.length; i++) {
- b[i] = (byte) Integer.parseInt(s.substring(2 * i, 2 * i + 2), 16);
- }
- return b;
- }
-
- private String byteArrayToString(byte[] b, int start) {
- StringBuffer s = new StringBuffer();
- for (int i = start; i < b.length; i++) {
- s.append(Integer.toHexString(0x100 + (b[i] & 0xff)).substring(1));
- }
- return s.toString();
- }
-
- *//**
- * Clear the channel number.
- *
- * @param cla
- *
- * @return the cla without channel number
- *//*
- private byte clearChannelNumber(byte cla) {
- // bit 7 determines which standard is used
- boolean isFirstInterindustryClassByteCoding = ((cla & 0x40) == 0x00);
-
- if (isFirstInterindustryClassByteCoding) {
- // First Interindustry Class Byte Coding
- // see 11.1.4.1: channel number is encoded in the 2 rightmost bits
- return (byte) (cla & 0xFC);
- } else {
- // Further Interindustry Class Byte Coding
- // see 11.1.4.2: channel number is encoded in the 4 rightmost bits
- return (byte) (cla & 0xF0);
- }
- }
-
- @Override
- protected byte[] internalTransmit(byte[] command) throws CardException {
- int cla = clearChannelNumber(command[0]) & 0xff;
- int ins = command[1] & 0xff;
- int p1 = command[2] & 0xff;
- int p2 = command[3] & 0xff;
- int p3 = -1;
- if (command.length > 4) {
- p3 = command[4] & 0xff;
- }
- String data = null;
- if (command.length > 5) {
- data = byteArrayToString(command, 5);
- }
-
- int channelNumber = parseChannelNumber(command[0]);
-
- if (channelNumber == 0) {
-
- try {
- String response = manager.transmitIccBasicChannel(cla, ins, p1,
- p2, p3, data);
- return stringToByteArray(response);
- } catch (Exception ex) {
- throw new CardException("transmit command failed");
- }
-
- } else {
- if ((channelNumber > 0) && (channelId[channelNumber] == 0)) {
- throw new CardException("channel not open");
- }
-
- try {
- String response = manager.transmitIccLogicalChannel(
- cla, ins, channelId[channelNumber], p1, p2, p3, data);
- return stringToByteArray(response);
- } catch (Exception ex) {
- throw new CardException("transmit command failed");
- }
- }
- }
-
- @Override
- public byte[] getAtr() {
- if (mAtr == null) {
- try {
- String atr = manager.getIccAtr();
- if (atr.equals("")) {
- mAtr = null;
- } else {
- mAtr = stringToByteArray(atr);
- }
- } catch (Exception ex) {
- mAtr = null;
- }
- }
- return mAtr;
- }
-
- *//**
- * Exchanges APDU (SELECT, READ/WRITE) to the given EF by File ID and file
- * path via iccIO.
- *
- * The given command is checked and might be rejected.
- *
- * @param fileID
- * @param filePath
- * @param cmd
- * @return
- *//*
- @Override
- public byte[] simIOExchange(int fileID, String filePath, byte[] cmd)
- throws Exception {
- try {
- int ins = 0;
- int p1 = cmd[2] & 0xff;
- int p2 = cmd[3] & 0xff;
- int p3 = cmd[4] & 0xff;
- switch(cmd[1]) {
- case (byte) 0xB0:
- ins = 176;
- break;
- case (byte) 0xB2:
- ins = 178;
- break;
- case (byte) 0xA4:
- ins = 192;
- p1 = 0;
- p2 = 0;
- p3 = 15;
- break;
- default:
- throw new SecureElementException("Unknown SIM_IO command");
- }
-
- if (filePath != null && filePath.length() > 0) {
- currentSelectedFilePath = filePath;
- }
-
- byte[] ret = manager.transmitIccSimIO(
- fileID, ins, p1, p2, p3, currentSelectedFilePath);
-
- return ret;
- } catch (Exception e) {
- throw new Exception("SIM IO access error");
- }
- }
-
- *//**
- * Extracts the channel number from a CLA byte. Specified in GlobalPlatform
- * Card Specification 2.2.0.7: 11.1.4 Class Byte Coding.
- *
- * @param cla
- * the command's CLA byte
- * @return the channel number within [0x00..0x0F]
- *//*
- private int parseChannelNumber(byte cla) {
- // bit 7 determines which standard is used
- boolean isFirstInterindustryClassByteCoding = ((cla & 0x40) == 0x00);
-
- if (isFirstInterindustryClassByteCoding) {
- // First Interindustry Class Byte Coding
- // see 11.1.4.1: channel number is encoded in the 2 rightmost bits
- return cla & 0x03;
- } else {
- // Further Interindustry Class Byte Coding
- // see 11.1.4.2: channel number is encoded in the 4 rightmost bits
- return (cla & 0x0F) + 4;
- }
- }
-
- @Override
- protected int internalOpenLogicalChannel() throws Exception {
- // Select response will always be null because no select command will be
- // issued.
- mSelectResponse = null;
- for (int i = 1; i < channelId.length; i++) {
- if (channelId[i] == 0) {
- channelId[i] = manager.openIccLogicalChannel("");
-
- if (!(channelId[i] > 0)) {
- // channelId[i] == 0, means an error occured.
- channelId[i] = 0;
- int lastError = manager.getLastError();
-
- if (lastError == 2) {
- throw new MissingResourceException(
- "all channels are used", "", "");
- }
- if (lastError == 3) {
- throw new NoSuchElementException("applet not found");
- }
- throw new CardException("open channel failed");
- }
-
- return i;
- }
- }
- throw new MissingResourceException("out of channels", "", "");
- }
-
- @Override
- protected int internalOpenLogicalChannel(byte[] aid) throws Exception {
-
- if (aid == null) {
- throw new NullPointerException("aid must not be null");
- }
- mSelectResponse = null;
- for (int i = 1; i < channelId.length; i++) {
- if (channelId[i] == 0) {
- channelId[i] = manager.openIccLogicalChannel(
- byteArrayToString(aid, 0));
-
- if (!(channelId[i] > 0)) {
- // channelId[i] == 0, means an error occured.
- channelId[i] = 0;
- int lastError = manager.getLastError();
-
- if (lastError == 2) {
- throw new MissingResourceException(
- "all channels are used", "", "");
- }
- if (lastError == 3) {
- throw new NoSuchElementException("applet not found");
- }
- throw new CardException("open channel failed");
- }
-
- // If everything succeeded, set the select response.
- mSelectResponse = stringToByteArray(
- manager.getIccSelectResponse());
- return i;
- }
- }
- throw new MissingResourceException("out of channels", "", "");
- }
-
- @Override
- protected void internalCloseLogicalChannel(int channelNumber)
- throws CardException {
- if (channelNumber == 0) {
- return;
- }
- if (channelId[channelNumber] == 0) {
- throw new CardException("channel not open");
- }
- try {
- if (!manager.closeIccLogicalChannel(channelId[channelNumber])) {
- throw new CardException("close channel failed");
- }
- } catch (Exception ex) {
- throw new CardException("close channel failed");
- }
- channelId[channelNumber] = 0;
- }
-}
-
-*/
\ No newline at end of file
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/terminals_l_dev/ASSDTerminal.java b/smart-card-service/src/org/simalliance/openmobileapi/service/terminals_l_dev/ASSDTerminal.java
deleted file mode 100644
index ba1796f..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/terminals_l_dev/ASSDTerminal.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (C) 2011, The Android Open Source Project
- *
- * 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.
-
-
- * Contributed by: Giesecke & Devrient GmbH.
-
-package org.simalliance.openmobileapi.service.terminals;
-
-import android.content.Context;
-
-
-import java.util.MissingResourceException;
-import java.util.NoSuchElementException;
-
-import org.simalliance.openmobileapi.service.CardException;
-import org.simalliance.openmobileapi.service.SmartcardService;
-import org.simalliance.openmobileapi.service.Terminal;
-
-final class ASSDTerminal extends Terminal {
-
- private static boolean JNILoaded = false;
-
- public ASSDTerminal(Context context) {
- super(SmartcardService._SD_TERMINAL, context);
- }
-
- @Override
- protected void internalConnect() throws CardException {
- if (JNILoaded == false) {
- throw new CardException("JNI failed");
- }
-
- try {
- if (Open() == false) {
- throw new CardException("open SE failed");
- }
- } catch (Exception e) {
- throw new CardException("open SE failed");
- }
- mDefaultApplicationSelectedOnBasicChannel = true;
- mIsConnected = true;
- }
-
- @Override
- protected void internalDisconnect() throws CardException {
- if (JNILoaded == false) {
- throw new CardException("JNI failed");
- }
-
- try {
- Close();
- } catch (Exception e) {
- } finally {
- mIsConnected = false;
- }
- }
-
- public boolean isCardPresent() throws CardException {
- if (JNILoaded == false) {
- return false;
- }
-
- try {
- return IsPresent();
- } catch (Exception e) {
- return false;
- }
- }
-
- @Override
- protected byte[] internalTransmit(byte[] command) throws CardException {
- if (JNILoaded == false) {
- throw new CardException("JNI failed");
- }
-
- try {
- byte[] response = Transmit(command);
- if (response == null) {
- throw new CardException("transmit failed");
- }
- return response;
- } catch (Exception e) {
- throw new CardException("transmit failed");
- }
- }
-
- @Override
- protected void internalCloseLogicalChannel(int channelNumber) throws CardException {
- if (channelNumber > 0) {
- byte cla = (byte) channelNumber;
- if (channelNumber > 3) {
- cla |= 0x40;
- }
- byte[] manageChannelClose = new byte[] {
- cla, 0x70, (byte) 0x80, (byte) channelNumber
- };
- transmit(manageChannelClose, 2, 0x9000, 0xFFFF, "MANAGE CHANNEL");
- }
- }
-
- @Override
- protected int internalOpenLogicalChannel() throws Exception {
-
- mSelectResponse = null;
- byte[] manageChannelCommand = new byte[] {
- 0x00, 0x70, 0x00, 0x00, 0x01
- };
- byte[] rsp = transmit(manageChannelCommand, 3, 0x9000, 0xFFFF, "MANAGE CHANNEL");
- if (rsp.length != 3) {
- throw new MissingResourceException("unsupported MANAGE CHANNEL response data", "", "");
- }
- int channelNumber = rsp[0] & 0xFF;
- if (channelNumber == 0 || channelNumber > 19) {
- throw new MissingResourceException("invalid logical channel number returned", "", "");
- }
-
- return channelNumber;
- }
-
- @Override
- protected int internalOpenLogicalChannel(byte[] aid) throws Exception {
- int channelNumber = internalOpenLogicalChannel();
-
- if (aid == null) {
- throw new NullPointerException("aid must not be null");
- }
- mSelectResponse = null;
- byte[] selectCommand = new byte[aid.length + 6];
- selectCommand[0] = (byte) channelNumber;
- if (channelNumber > 3) {
- selectCommand[0] |= 0x40;
- }
- selectCommand[1] = (byte) 0xA4;
- selectCommand[2] = 0x04;
- selectCommand[4] = (byte) aid.length;
- System.arraycopy(aid, 0, selectCommand, 5, aid.length);
- try {
- mSelectResponse = transmit(selectCommand, 2, 0x9000, 0xFFFF, "SELECT");
- } catch (CardException e) {
- internalCloseLogicalChannel(channelNumber);
- throw new NoSuchElementException(e.getMessage());
- }
-
- return channelNumber;
- }
-
- static {
- try {
- Runtime.getRuntime().loadLibrary("assd");
- JNILoaded = true;
- } catch (Throwable t) {
- }
- }
-
- @Override
- public byte[] getAtr() {
- return null;
- }
-
- private native void Close() throws Exception;
-
- private native boolean Open() throws Exception;
-
- private native boolean IsPresent() throws Exception;
-
- private native byte[] Transmit(byte[] command) throws Exception;
-}*/
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/terminals_l_dev/P61SpiTerminal.java b/smart-card-service/src/org/simalliance/openmobileapi/service/terminals_l_dev/P61SpiTerminal.java
deleted file mode 100644
index f725f33..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/terminals_l_dev/P61SpiTerminal.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright (C) 2011, The Android Open Source Project
- *
- * 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.
- */
-/*
- * Contributed by: Giesecke & Devrient GmbH.
- */
- /******************************************************************************
- *
- * The original Work has been changed by NXP Semiconductors.
- *
- * Copyright (C) 2015 NXP Semiconductors
- *
- * 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 src.org.simalliance.openmobileapi.service.terminals;
-
-import android.content.Context;
-import android.os.Binder;
-import android.os.Bundle;
-import android.util.Log;
-import android.content.pm.PackageManager;
-import com.nxp.eseclient.EseClientManager;
-import com.nxp.eseclient.EseClientServicesAdapterBuilder;
-import com.nxp.eseclient.EseClientServicesAdapter;
-import com.nxp.intf.INxpExtrasService;
-
-import java.util.MissingResourceException;
-import java.util.NoSuchElementException;
-import org.simalliance.openmobileapi.service.Terminal;
-import org.simalliance.openmobileapi.service.CardException;
-import org.simalliance.openmobileapi.service.SmartcardService;
-
-
-
-public class P61SpiTerminal extends Terminal {
-
- private Binder binder = new Binder();
- private String TAG = "P61SPITerminal";
- private static EseClientManager mEseManager;
- private static EseClientServicesAdapter mEseClientServicesAdapter;
- private static EseClientServicesAdapterBuilder mEseClientServicesAdapterBuilder;
- private static INxpExtrasService mINxpExtrasService;
- public static Integer type = EseClientManager.SPI;
-
-
- public P61SpiTerminal(Context context) {
- super(SmartcardService._P61Spi_TERMINAL, context);
-
- try{
- mEseManager = EseClientManager.getInstance();
- mEseManager.initialize();
- INxpExtrasService NxpExtrasServiceIntf = null;
- mEseClientServicesAdapterBuilder = new EseClientServicesAdapterBuilder();
- mEseClientServicesAdapter = mEseClientServicesAdapterBuilder.getEseClientServicesAdapterInstance(type);
- NxpExtrasServiceIntf = mEseClientServicesAdapter.getNxpExtrasService();
- mINxpExtrasService = NxpExtrasServiceIntf;
- }
- catch(Exception e)
- {
- Log.d(TAG, e.getMessage());
- }
- }
-
- public boolean isCardPresent() throws CardException {
-
- return true; //mSpiAdapter.isEnabled(); // Enabled always for testing
- }
-
- @Override
- protected void internalConnect() throws CardException {
- //spi initialization
- try {
- if(!mINxpExtrasService.isEnabled()){
- mINxpExtrasService.open("org.simalliance.openmobileapi.service", binder);
- }
- } catch (Exception e) {
- throw new CardException("open SE failed");
- }
- mDefaultApplicationSelectedOnBasicChannel = true;
- mIsConnected = true;
- }
-
- @Override
- protected void internalDisconnect() throws CardException {
- //spi deinitialization
- try {
- if(mINxpExtrasService.isEnabled()){
- // mSpiAdapter.disable();
- }
- } catch (Exception e) {
- throw new CardException("close SE failed");
- }
- }
-
- @Override
- protected byte[] internalTransmit(byte[] command) throws CardException {
-
- try {
- Bundle b = mINxpExtrasService.transceive("org.simalliance.openmobileapi.service", command);
- if (b == null) {
- throw new CardException("exchange APDU failed");
- }
- return b.getByteArray("out");
- } catch (Exception e) {
- throw new CardException("exchange APDU failed");
- }
- }
-
-
-// SPI won't support getAtr()
- @Override
- public byte[] getAtr() {
- return null;
- }
-
- @Override
- protected int internalOpenLogicalChannel() throws Exception {
-
- mSelectResponse = null;
- byte[] manageChannelCommand = new byte[] {
- 0x00, 0x70, 0x00, 0x00, 0x01
- };
- byte[] rsp = transmit(manageChannelCommand, 2, 0x9000, 0, "MANAGE CHANNEL");
- if ((rsp.length == 2) && ((rsp[0] == (byte) 0x68) && (rsp[1] == (byte) 0x81))) {
- throw new NoSuchElementException("logical channels not supported");
- }
- if (rsp.length == 2 && (rsp[0] == (byte) 0x6A && rsp[1] == (byte) 0x81)) {
- throw new MissingResourceException("no free channel available", "", "");
- }
- if (rsp.length != 3) {
- throw new MissingResourceException("unsupported MANAGE CHANNEL response data", "", "");
- }
- int channelNumber = rsp[0] & 0xFF;
- if (channelNumber == 0 || channelNumber > 19) {
- throw new MissingResourceException("invalid logical channel number returned", "", "");
- }
-
- return channelNumber;
- }
-
- @Override
- protected int internalOpenLogicalChannel(byte[] aid) throws Exception {
-
- if (aid == null) {
- throw new NullPointerException("aid must not be null");
- }
- mSelectResponse = null;
-
- byte[] manageChannelCommand = new byte[] {
- 0x00, 0x70, 0x00, 0x00, 0x01
- };
- byte[] rsp = transmit(manageChannelCommand, 2, 0x9000, 0, "MANAGE CHANNEL");
- if ((rsp.length == 2) && ((rsp[0] == (byte) 0x68) && (rsp[1] == (byte) 0x81))) {
- throw new NoSuchElementException("logical channels not supported");
- }
- if (rsp.length == 2 && (rsp[0] == (byte) 0x6A && rsp[1] == (byte) 0x81)) {
- throw new MissingResourceException("no free channel available", "", "");
- }
- if (rsp.length != 3) {
- throw new MissingResourceException("unsupported MANAGE CHANNEL response data", "", "");
- }
- int channelNumber = rsp[0] & 0xFF;
- if (channelNumber == 0 || channelNumber > 19) {
- throw new MissingResourceException("invalid logical channel number returned", "", "");
- }
-
- byte[] selectCommand = new byte[aid.length + 6];
- selectCommand[0] = (byte) channelNumber;
- if (channelNumber > 3) {
- selectCommand[0] |= 0x40;
- }
- selectCommand[1] = (byte) 0xA4;
- selectCommand[2] = 0x04;
- selectCommand[4] = (byte) aid.length;
- System.arraycopy(aid, 0, selectCommand, 5, aid.length);
- try {
- mSelectResponse = transmit(selectCommand, 2, 0x9000, 0xFFFF, "SELECT");
- } catch (CardException exp) {
- internalCloseLogicalChannel(channelNumber);
- throw new NoSuchElementException(exp.getMessage());
- }
-
- return channelNumber;
- }
-
- @Override
- protected void internalCloseLogicalChannel(int channelNumber) throws CardException {
- if (channelNumber > 0) {
- byte cla = (byte) channelNumber;
- if (channelNumber > 3) {
- cla |= 0x40;
- }
- byte[] manageChannelClose = new byte[] {
- cla, 0x70, (byte) 0x80, (byte) channelNumber
- };
- transmit(manageChannelClose, 2, 0x9000, 0xFFFF, "MANAGE CHANNEL");
- }
- }
-}
diff --git a/smart-card-service/src/org/simalliance/openmobileapi/service/terminals_l_dev/SmartMxTerminal.java b/smart-card-service/src/org/simalliance/openmobileapi/service/terminals_l_dev/SmartMxTerminal.java
deleted file mode 100644
index 4ab8369..0000000
--- a/smart-card-service/src/org/simalliance/openmobileapi/service/terminals_l_dev/SmartMxTerminal.java
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Copyright (C) 2011, The Android Open Source Project
- *
- * 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.
-
-
- * Contributed by: Giesecke & Devrient GmbH.*/
- /******************************************************************************
- *
- * The original Work has been changed by NXP Semiconductors.
- *
- * Copyright (C) 2015 NXP Semiconductors
- *
- * 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 org.simalliance.openmobileapi.service.terminals;
-
-import android.content.Context;
-import com.nxp.eseclient.EseClientManager;
-import com.nxp.eseclient.EseClientServicesAdapterBuilder;
-import com.nxp.eseclient.EseClientServicesAdapter;
-import com.nxp.intf.INxpExtrasService;
-import java.io.IOException;
-import android.os.Binder;
-import android.os.Bundle;
-import android.util.Log;
-import java.util.MissingResourceException;
-import java.util.NoSuchElementException;
-
-import org.simalliance.openmobileapi.service.CardException;
-import org.simalliance.openmobileapi.service.SmartcardService;
-import org.simalliance.openmobileapi.service.Terminal;
-
-
-public class SmartMxTerminal extends Terminal {
-
- private static EseClientManager mEseManager;
- private static EseClientServicesAdapter mEseClientServicesAdapter;
- private static EseClientServicesAdapterBuilder mEseClientServicesAdapterBuilder;
- private static INxpExtrasService mINxpExtrasService;
- public static int type = EseClientManager.NFC;
- private Binder binder = new Binder();
- private String TAG = "SmartMxTerminal";
-
- public SmartMxTerminal(Context context) {
- super(SmartcardService._eSE_TERMINAL, context);
- try{
- mEseManager = EseClientManager.getInstance();
- mEseManager.initialize();
- INxpExtrasService NxpExtrasServiceIntf = null;
- mEseClientServicesAdapterBuilder = new EseClientServicesAdapterBuilder();
- mEseClientServicesAdapter = mEseClientServicesAdapterBuilder.getEseClientServicesAdapterInstance(type);
- NxpExtrasServiceIntf = mEseClientServicesAdapter.getNxpExtrasService();
- mINxpExtrasService = NxpExtrasServiceIntf;
- }
- catch(Exception e)
- {
- Log.d(TAG, e.getMessage());
- }
- }
-
- public boolean isCardPresent() throws CardException {
- try {
- if(mINxpExtrasService == null) {
- throw new CardException("Cannot get NFC Default Adapter");
- }
- return mINxpExtrasService.isEnabled();
- } catch (Exception e) {
- return false;
- }
- }
-
- @Override
- protected void internalConnect() throws CardException {
- if(mINxpExtrasService == null) {
- throw new CardException("Cannot get NFC Default Adapter");
- }
-
- try {
- Bundle b = mINxpExtrasService.open("org.simalliance.openmobileapi.service", binder);
- if (b == null) {
- throw new CardException("open SE failed");
- }
- } catch (Exception e) {
- throw new CardException("open SE failed");
- }
- mDefaultApplicationSelectedOnBasicChannel = true;
- mIsConnected = true;
- }
-
- @Override
- protected void internalDisconnect() throws CardException {
-
- try {
- Bundle b = mINxpExtrasService.close("org.simalliance.openmobileapi.service", binder);
- if (b == null) {
- throw new CardException("close SE failed");
- }
- } catch (Exception e) {
- throw new CardException("close SE failed");
- }
- }
-
- @Override
- protected byte[] internalTransmit(byte[] command) throws CardException {
-
- try {
- Bundle b = mINxpExtrasService.transceive("org.simalliance.openmobileapi.service", command);
- if (b == null) {
- throw new CardException("exchange APDU failed");
- }
- return b.getByteArray("out");
- } catch (Exception e) {
- throw new CardException("exchange APDU failed");
- }
- }
-
- @Override
- public byte[] getAtr() {
- byte uid[] = null;
- try {
- uid = mINxpExtrasService.getSecureElementUid("org.simalliance.openmobileapi.service");
- return uid;
- } catch (Exception e) {
- Log.d(TAG, e.toString());
- Log.d(TAG,"getAtr: get Secure Element Uid failed");
- }
- return uid;
- }
-
- @Override
- protected int internalOpenLogicalChannel() throws Exception {
- mSelectResponse = null;
- byte[] manageChannelCommand = new byte[] {
- 0x00, 0x70, 0x00, 0x00, 0x01
- };
- byte[] rsp = transmit(manageChannelCommand, 2, 0x9000, 0, "MANAGE CHANNEL");
- if ((rsp.length == 2) && ((rsp[0] == (byte) 0x68) && (rsp[1] == (byte) 0x81))) {
- throw new NoSuchElementException("logical channels not supported");
- }
- if (rsp.length == 2 && (rsp[0] == (byte) 0x6A && rsp[1] == (byte) 0x81)) {
- throw new MissingResourceException("no free channel available", "", "");
- }
- if (rsp.length != 3) {
- throw new MissingResourceException("unsupported MANAGE CHANNEL response data", "", "");
- }
- int channelNumber = rsp[0] & 0xFF;
- if (channelNumber == 0 || channelNumber > 19) {
- throw new MissingResourceException("invalid logical channel number returned", "", "");
- }
-
- return channelNumber;
- }
-
- @Override
- protected int internalOpenLogicalChannel(byte[] aid) throws Exception {
- if (aid == null) {
- throw new NullPointerException("aid must not be null");
- }
- mSelectResponse = null;
-
- byte[] manageChannelCommand = new byte[] {
- 0x00, 0x70, 0x00, 0x00, 0x01
- };
- byte[] rsp = transmit(manageChannelCommand, 2, 0x9000, 0, "MANAGE CHANNEL");
- if ((rsp.length == 2) && ((rsp[0] == (byte) 0x68) && (rsp[1] == (byte) 0x81))) {
- throw new NoSuchElementException("logical channels not supported");
- }
- if (rsp.length == 2 && (rsp[0] == (byte) 0x6A && rsp[1] == (byte) 0x81)) {
- throw new MissingResourceException("no free channel available", "", "");
- }
- if (rsp.length != 3) {
- throw new MissingResourceException("unsupported MANAGE CHANNEL response data", "", "");
- }
- int channelNumber = rsp[0] & 0xFF;
- if (channelNumber == 0 || channelNumber > 19) {
- throw new MissingResourceException("invalid logical channel number returned", "", "");
- }
-
- byte[] selectCommand = new byte[aid.length + 6];
- selectCommand[0] = (byte) channelNumber;
- if (channelNumber > 3) {
- selectCommand[0] |= 0x40;
- }
- selectCommand[1] = (byte) 0xA4;
- selectCommand[2] = 0x04;
- selectCommand[4] = (byte) aid.length;
- System.arraycopy(aid, 0, selectCommand, 5, aid.length);
- try {
- mSelectResponse = transmit(selectCommand, 2, 0x9000, 0xFFFF, "SELECT");
- } catch (CardException exp) {
- internalCloseLogicalChannel(channelNumber);
- throw new NoSuchElementException(exp.getMessage());
- }
-
- return channelNumber;
- }
-
- @Override
- protected void internalCloseLogicalChannel(int channelNumber) throws CardException {
- if (channelNumber > 0) {
- byte cla = (byte) channelNumber;
- if (channelNumber > 3) {
- cla |= 0x40;
- }
- byte[] manageChannelClose = new byte[] {
- cla, 0x70, (byte) 0x80, (byte) channelNumber
- };
- transmit(manageChannelClose, 2, 0x9000, 0xFFFF, "MANAGE CHANNEL");
- }
- }
-}