0

requestObjectDeletion()メソッドの機能とカードの使用可能なメモリをチェックする簡単なプログラムを作成しました。

私のアプレットは、次のように 5 つの異なる種類の APDU コマンドに応答します。

  1. SELECT APDU コマンド: 応答:0X9000
  2. コマンド :XX 00 XX XX XX [...]応答 : 使用可能なメモリをバイト単位で返します。
  3. コマンド :XX 01 XX XX XX [...]応答 : 2000 要素 (つまり 2000 バイト) のローカル バイト配列を作成します。
  4. コマンド :XX 02 XX XX XX [...]レスポンス : オブジェクト削除メソッドのリクエスト
  5. その他のコマンド : 応答 :0x9000

使用可能なメモリを返すために、無限whileループを使用して100要素を持つ多数のバイト配列を作成し、counter同時に a を増やすメソッドを作成しました。Not enough memory例外をキャッチすると、メソッドは戻りますcounter *100(つまり、このメソッドを呼び出す前の空きメモリ)。

OK、これはプログラムです:

public class ObjDeletion extends Applet {
    public static short counter = 0x0000;

    private ObjDeletion() {
    }

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

    public void process(APDU arg0) throws ISOException {

        if (selectingApplet()) {
            return;
        }

        byte[] buffer = arg0.getBuffer();

        switch (buffer[ISO7816.OFFSET_INS]) {
        case 0x00:
            counter=0;
            ReturnAvailableMem();
            break;

        case 0x01:
            genLocalArray();
            break;

        case 0x02:
            JCSystem.requestObjectDeletion();
            break;

        default:
            return;

        }

    }

    public void genLocalArray() {
        byte[] LocalArray = new byte[2000];
    }

    public void ReturnAvailableMem() {
        try {
            while (true) {
                byte[] dump = new byte[100];
                counter += 1;
            }

        } catch (Exception e) {

            ISOException.throwIt((short) (counter * 100));
        }
    }
}

さて、問題があります。これは、いくつかの APDU コマンドをカードに送信したときのOpenSC-Toolの出力です。

OSC: opensc-tool.exe -s 00a404000b0102030405060708090000 -s 00000000 -s 00020000
 -s 00000000 -s 00020000 -s 00010000 -s 00000000 -s 00020000 -s 00000000 -s 0002
0000 -s 00010000 -s 00020000 -s 00000000

Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 0B 01 02 03 04 05 06 07 08 09 00 00
Received (SW1=0x90, SW2=0x00)

//0::returnAvailableMem()
Sending: 00 00 00 00 
Received (SW1=0xE3, SW2=0x58)

//1::returnAvailableMem()
Sending: 00 00 00 00 
Received (SW1=0x00, SW2=0x00)

//2::requestObjectDeletion()
Sending: 00 02 00 00
Received (SW1=0x90, SW2=0x00)

//3::returnAvailableMem()
Sending: 00 00 00 00
Received (SW1=0xE3, SW2=0x58)

//4::requestObjectDeletion()
Sending: 00 02 00 00
Received (SW1=0x90, SW2=0x00)

//5::genLocalArray()
Sending: 00 01 00 00
Received (SW1=0x90, SW2=0x00)

//6::returnAvailableMem()
Sending: 00 00 00 00
Received (SW1=0xDD, SW2=0x18)

//7::requestObjectDeletion()
Sending: 00 02 00 00
Received (SW1=0x90, SW2=0x00)

//8::returnAvailableMem()
Sending: 00 00 00 00
Received (SW1=0xE3, SW2=0x58)

//9::requestObjectDeletion()
Sending: 00 02 00 00
Received (SW1=0x90, SW2=0x00)

//10::genLocalArray()
Sending: 00 01 00 00
Received (SW1=0x90, SW2=0x00)

//11::requestObjectDeletion()
Sending: 00 02 00 00
Received (SW1=0x90, SW2=0x00)

//12::returnAvailableMem()
Sending: 00 00 00 00
Received (SW1=0xE3, SW2=0x58)

コマンド0リターン0xE358(=58200)。したがって、このメソッドを呼び出す前のメモリは58200バイトでした。

コマンドが を1返します。これは、現在空きメモリがバイト0x0000未満であることを意味します。100

コマンドが を2返す0x9000ため、requestObjectDeletion が正常に呼び出されました。

コマンドが再び3返されます。これは、正常に実行されたことを意味します。0xE358requestObjectDeletion

コマンドが を4返す0x9000ため、requestObjectDeletion が正常に呼び出されました。

コマンドは を5返す0x9000ので、要素を持つバイト配列2000が作成されます。

今、カードの空きメモリが0xE358 - 2000 = 0xDB88

しかし、次のコマンドでは:

コマンド6が返されます0xDD18! つまり0xDD18 + 2000 = 0xE4E8、カードにはバイトのメモリ空間があります!

これは誰が可能ですか?0xE4E8 - 0xE358カードが最初のコマンドでこの 400 バイト ( ) を認識できないのはなぜですか?

4

1 に答える 1

2

答えは単純で、各配列 (およびその他のオブジェクト) には、そのタイプやサイズなどを示す「ヘッダー」が必要だからです。これについては、JCRE および JCVM の仕様を注意深く読む必要があります。

(100 + 'header') * X「ヘッダー」の正確なサイズは確認していませんが、単純な ではなく、 として想像できます100 * X

これは、最適化のヒントについても説明しています。1 つの大きな配列を作成すると、多くの小さな配列を使用するよりも多くのメモリを節約できますが、もちろん、コードが読みにくくなるなどのトレードオフがあります。

于 2015-04-28T09:29:41.733 に答える