4

这里有一些背景第一:

我正在尝试做一个概念验证的 Android 应用程序,它将检查我是否可以将一些 APDU 命令发送到 SIM 卡小程序并处理响应。

我使用SEEK for Android作为 Open Mobile API 的参考实现。

该应用程序应该可以在带有 Open Mobile API 的三星 Galaxy S3 智能手机上运行,​​如此所述。

我不允许使用自定义 ROM,也不允许对 Android 源代码进行任何修改。

到目前为止我做了什么:

  1. 我已经下载了带有 Open Mobile API 和 Open Mobile API 包的 Android API lvl 18。
  2. 我创建了一个示例应用程序,它应该尝试访问我的 SIM 卡上的小程序,如此所述。
  3. 单击按钮时,我收到 SecurityException

    06-23 12:57:15.620: I/HelloSmartcard(5386): creating SEService object
    06-23 12:57:15.655: I/SEService(5386): Connected
    06-23 12:57:22.525: I/HelloSmartcard(5386): Retrieve available readers...
    06-23 12:57:22.530: I/HelloSmartcard(5386): Create Session from the UICC reader...
    06-23 12:57:23.275: I/HelloSmartcard(5386): Create logical channel within the session...
    06-23 12:57:23.285: E/HelloSmartcard(5386): Error occured:
    06-23 12:57:23.285: E/HelloSmartcard(5386): java.lang.SecurityException: Access Control Enforcer: access denied: EF_DIR not found!!
    06-23 12:57:23.285: E/HelloSmartcard(5386):     at org.simalliance.openmobileapi.SEService.checkForException(SEService.java:234)
    06-23 12:57:23.285: E/HelloSmartcard(5386):     at org.simalliance.openmobileapi.Session.openLogicalChannel(Session.java:302)
    06-23 12:57:23.285: E/HelloSmartcard(5386):     at com.example.testsmartcardaccess2.MainActivity$1.onClick(MainActivity.java:81)
    06-23 12:57:23.285: E/HelloSmartcard(5386):     at android.view.View.performClick(View.java:4475)
    06-23 12:57:23.285: E/HelloSmartcard(5386):     at android.view.View$PerformClick.run(View.java:18786)
    06-23 12:57:23.285: E/HelloSmartcard(5386):     at android.os.Handler.handleCallback(Handler.java:730)
    06-23 12:57:23.285: E/HelloSmartcard(5386):     at android.os.Handler.dispatchMessage(Handler.java:92)
    06-23 12:57:23.285: E/HelloSmartcard(5386):     at android.os.Looper.loop(Looper.java:176)
    06-23 12:57:23.285: E/HelloSmartcard(5386):     at android.app.ActivityThread.main(ActivityThread.java:5419)
    06-23 12:57:23.285: E/HelloSmartcard(5386):     at java.lang.reflect.Method.invokeNative(Native Method)
    06-23 12:57:23.285: E/HelloSmartcard(5386):     at java.lang.reflect.Method.invoke(Method.java:525)
    06-23 12:57:23.285: E/HelloSmartcard(5386):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1046)
    06-23 12:57:23.285: E/HelloSmartcard(5386):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:862)
    06-23 12:57:23.285: E/HelloSmartcard(5386):     at dalvik.system.NativeStart.main(Native Method)
    06-23 12:57:23.285: I/Choreographer(5386): Skipped 45 frames!  The application may be doing too much work on its main thread.
    
  4. 我有 org.simalliance.openmobileapi.jar 作为依赖项:

  5. 我有权限:

    <uses-permission android:name="org.simalliance.openmobileapi.SMARTCARD"/>
    
  6. 我在 SIM 卡上有 3 个小程序,我正在尝试调用 AID 下的那个F9 F4 0F 65 18 C9 54 1E CD AD

这是我正在使用的粗略代码模板:

package com.example.testsmartcardaccess2;

import org.simalliance.openmobileapi.Channel;
import org.simalliance.openmobileapi.Reader;
import org.simalliance.openmobileapi.SEService;
import org.simalliance.openmobileapi.Session;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.Toast;

public class MainActivity extends Activity implements SEService.CallBack {

    private SEService seService;
    private Reader uuicReader;
    private boolean seServiceConnected;

    private Button button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        final String LOG_TAG = "HelloSmartcard";

        try {
            Log.i(LOG_TAG, "creating SEService object");
            this.seServiceConnected = false;
            seService = new SEService(MainActivity.this, MainActivity.this);
        } catch (SecurityException e) {
            Log.e(LOG_TAG,
                    "Binding not allowed, uses-permission org.simalliance.openmobileapi.SMARTCARD?");
        } catch (Exception e) {
            Log.e(LOG_TAG, "Exception: " + e.getMessage());
        }

        super.onCreate(savedInstanceState);

        LinearLayout layout = new LinearLayout(this);
        layout.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
                LayoutParams.WRAP_CONTENT));

        button = new Button(this);
        button.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
                LayoutParams.WRAP_CONTENT));

        button.setText("Click Me");
        button.setEnabled(false);
        button.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                try {
                    Log.i(LOG_TAG, "Retrieve available readers...");
                    Reader[] readers = seService.getReaders();
                    if (readers.length < 1)
                        return;

                    uuicReader = null;

                    for (Reader reader : readers) {
                        if (reader.getName().equalsIgnoreCase("SIM - UICC")) {
                            uuicReader = reader;
                            break;
                        }
                    }

                    Log.i(LOG_TAG, "Create Session from the UICC reader...");
                    Session session = uuicReader.openSession();

                    Log.i(LOG_TAG,
                            "Create logical channel within the session...");

                    Channel channel = session.openLogicalChannel(
                            new byte[] {
                                (byte) 0xF9, 
                                (byte) 0xF4, 
                                (byte) 0x0F,
                                (byte) 0x65,
                                (byte) 0x18, 
                                (byte) 0xC9,
                                (byte) 0x54, 
                                (byte) 0x1E, 
                                (byte) 0xCD, 
                                (byte) 0xAD
                            }
                    );

                    Log.d(LOG_TAG, "Send HelloWorld APDU command");
                    byte[] respApdu = channel.transmit(new byte[] {
                            (byte) 0x90, 0x10, 0x00, 0x00, 0x00 });

                    channel.close();

                    // Parse response APDU and show text but remove SW1 SW2
                    // first
                    byte[] helloStr = new byte[respApdu.length - 2];
                    System.arraycopy(respApdu, 0, helloStr, 0,
                            respApdu.length - 2);
                    Toast.makeText(MainActivity.this, new String(helloStr),
                            Toast.LENGTH_LONG).show();
                } catch (Exception e) {
                    Log.e(LOG_TAG, "Error occured:", e);
                    return;
                }

            }
        });

        layout.addView(button);
        setContentView(layout);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void serviceConnected(SEService arg0) {
        Log.i("SEService", "Connected");
        this.seServiceConnected = this.seService.isConnected();

        updateButtonStatus(button, this.seServiceConnected);
    }

    private void updateButtonStatus(Button button, boolean enabled) {
        button.setEnabled(enabled);
    }

    @Override
    protected void onDestroy() {
        if (seService != null && seService.isConnected()) {
            seService.shutdown();
            this.seServiceConnected = false;
            updateButtonStatus(button, this.seServiceConnected);
        }
        super.onDestroy();
    }

}

我相信我的 SIM 卡上没有设置有关小程序访问的内容,但由于那部分不是我的域,我不知道该怎么做才能解决这个问题。

我在 Google Groups 上遇到过这个与我的困境相似的讨论,但我不知道如何解释它。

任何帮助表示赞赏!

4

1 回答 1

4

错误

java.lang.SecurityException: Access Control Enforcer: access denied: EF_DIR not found!!

很清楚。S3 库存固件上的 Open Mobiel API 实施需要 PKCS#15 文件结构(访问控制文件系统,ARF)存在于安全元件 (UICC) 上。(而不是 GlobalPlatform 安全元素访问控制规范引入的访问控制小程序 (ARA)。)

因此,您需要在 UICC 上出现一个看起来像这样的文件系统(请参阅此示例并参阅 GlobalPlatform 安全元素访问控制规范以获取更多参考):

MF (3F00)
|- EF DIR (2F00) --> shall reference PKCS-15
|
|- DF PKCS-15
|
|- ODF --> shall reference DODF
|- DODF --> shall reference EF ACMain
|- EF ACMain --> shall reference EF ACRules
|- EF ACRules --> shall reference EF ACConditions files
|- EF ACConditions1
|- ...
于 2014-06-24T05:40:33.553 回答