10

私の質問は、コード内から検出された操作への対策として、アプレット自体のコード内からアプレットをロックできるかどうかです。

明らかな選択は使用することGPSystem.lockCard();であり、それは機能しますが、アプレットのみをロックすることが可能かどうか疑問に思います。また、関連付けられたセキュリティ ドメインの認証済みセッションからアプレット自体をロックすることもできます。しかし、アプレットコード自体から可能ですか。GPSystem.setCardContentState();で使用されるメソッドを考えるとGPSystem.APPLICATION_LOCKED、それもテストしましたが、機能しません。

GP カード仕様 2.2 PDF の説明を読み直す:

OPEN は、ライフサイクル状態 LOCKEDからの移行要求を拒否します。

私のEclipseでは、JavaDocは次のように述べています:

OPEN は、ライフサイクル状態 LOCKEDの移行要求を拒否するものとします。

何が起きてる?

4

5 に答える 5

9

このメカニズムが GlobalPlatform Card 仕様 2.1.1 から 2.2.1 にどのように進化したかを見るのは興味深いことです (2.3 でも同じです)。

  1. GP 2.1.1 では、カード発行者 (オフカード エンティティ) または OPEN (「例外」の結果として) のみが、アプリケーションのロックを開始できます。

    カード発行者には、カード上のアプリケーションの継続的な実行ステータスを無効にするメカニズムがあります。このメカニズムは、OPEN によって処理される例外に基づいて、または外部から呼び出されたコマンドの使用から、OPEN 内から呼び出すことができます。カード発行者は、アプリケーションのロックを開始できる唯一のエンティティです。

    メソッドは、アプリケーション固有のライフサイクル状態 (および下位 3 ビットが設定されたGPSystem.setCardContentState()値) への状態変更のみを許可するように明確に定義されています。以降の仕様では定数が設定されているため、この状態は許可されません。これは、このメソッドの注記でも明確にされています。0x070x7FAPPLICATION_LOCKED0x80

    • OPEN は、ライフサイクル状態 INSTALLED またはLOCKEDの移行要求を拒否するものとします。

    したがって、GP 2.1.1 を実装するカードでは、アプリケーション自体からアプリケーションの状態をロックに設定しようとすると失敗する必要があります。

    更新 (2016-05-20):いくつかの NXP JCOP カード (GP 2.1.1 に準拠していると主張されている) でこれをテストし、上位ビットが設定されているか、下位 3 ビットのいずれかがクリアされている値を設定すると、実際に失敗します。

  2. これは GP 2.2 で変更されました。これで、アプリケーションは自分自身をロックできるようになりました:

    カードには、カード上のアプリケーションの継続的な実行ステータスを無効にしてから再度有効にするメカニズムがあります。このメカニズムは、OPEN によって処理される例外に基づいて、または外部から呼び出されたコマンドの使用から、OPEN 内から呼び出すことができます。グローバル ロック権限を持つアプリケーション、アプリケーション自体、または直接または間接的に関連付けられたセキュリティ ドメインは、アプリケーションのロックを開始できる唯一のエンティティです。

    GP カードの仕様では、アプリケーションが自身をロックするための特定の権限を保持する必要はありません。

    残念ながら、このメソッドの API 仕様GPSystem.setCardContentState()はまだ明確ではありません。まず、メソッドの説明では、設定された下位 3 ビットの間の値のみを許可する必要がある0x07とまだ述べています。0x7F

    このメソッドは、現在のアプレット コンテキストのアプリケーション固有のライフ サイクル状態を設定します。下位 3 ビットが設定されている限り、アプリケーション固有のライフサイクル状態の範囲は 0x07 から 0x7F です。

    第 2 に、GP カード仕様 2.2 ドキュメントの付録 A の一部である API ドキュメントと、API エクスポート ファイルの JavaDoc に、逸脱した注記があります。仕様の注記は次のように変更されました。

    • OPEN は、ライフサイクル状態 INSTALLED への移行要求を拒否します。
    • OPEN は、ライフサイクル状態LOCKEDからの移行要求を拒否します。

    API エクスポート ファイル (GPSystem.java および JavaDoc) の注記は、GP 2.1.1 と同じままです。

    したがって、このメソッドが仕様に従って実装された場合でも、アプリケーションのライフサイクル状態を に設定することを拒否する必要がありますAPPLICATION_LOCKED

    更新 (2016-05-20): NXP J3D081 (JCOP v2.4.2 R2) カード (GP 2.2 に準拠していると主張されている) でこれをテストしました。残念ながら、上位ビットが設定されているか、下位 3 ビットのいずれかがクリアされている値の設定は失敗します。

    ただし、方法もありGPRegistryEntry.setState()ます。このメソッドのドキュメントには、次のように記載されています。

    • APPLICATION_LOCKED および APPLICATION_UNLOCKED 以外のライフサイクル状態への遷移要求は、呼び出し元のアプリケーションがこの GPRegistryEntry に対応する場合にのみ受け入れられるものとします。
    • アプリケーションはロックできますが、それ自体をロック解除することはできません。

    したがって、使用setCardContentState()が失敗したのと同じカードで次のことが機能するかどうかを確認することは興味深いでしょう:

    GPSystem.getRegistryEntry(null).setState(GPSystem.APPLICATION_LOCKED);
    

    更新 (2016-05-20): NXP J3D081 (JCOP v2.4.2 R2) カード (GP 2.2 に準拠していると主張されている) でこれをテストしました。残念ながら、これも失敗します。ところで。nullまたはJCSystem.getAID()のパラメーターとして使用されている場合、違いはないようですgetRegistryEntry()

    更新 (2016-06-14): Paul Bastianによると、NXP の担当者は、アプリケーションが JCOP v2.4.x カードでロック状態に設定できないことを確認しました。

    更新 (2016-06-06): Infineon SLE97CNFX カード (GP 2.2.1 に準拠していると主張されている) でこれをテストしたところ、動作しました。APPLICATION_LOCKED(0x80)を使用して、状態を正常にロックに設定できました。その後、状態は に設定されprevious_state | 0x80ます。上位ビットが設定されている他の状態値 (0x8F など) を設定しようとしても機能しません (予想どおり)。

  3. GP 2.2.1 では、メソッドのドキュメントがGPSystem.setCardContentState()(再び) 変更されました。変更ノートは、アプリケーションがそれ自体をロックできるようにメソッドが更新されたことを明確に示しています (エクスポート ファイル バージョン 1.5. は GP 2.2.1 にマップされます)。

    • エクスポート ファイル バージョン 1.5: このメソッドにより、現在のアプレット コンテキストに関連付けられているアプリケーションが自身をロックできるようになりました。

    メソッド定義は次のように変更されました。

    このメソッドにより、現在のアプレット コンテキストに関連付けられているアプリケーションは、その状態をアプリケーション固有のライフ サイクル状態に変更したり、自身をロックしたりできます。アプリケーションは、このメソッドを使用して自分自身をロック解除することはできません。

    メソッドに渡される状態パラメーターの値の範囲には、APPLICATION_LOCKED次の値が明示的に含まれるようになりました。

    bState- アプリケーション固有のライフサイクル状態 (下位 3 ビットが設定された 0x07 から 0x7F)、またはAPPLICATION_LOCKED(0x80)。

    したがって、GP 2.2.1 以降を実装するカードは、最終的にアプリケーションがメソッドを使用して独自のライフサイクル状態をロックに変更できるようにする必要がありますGPSystem.setCardContentState()

    更新 (2016-06-06):これを Infineon SLE97CNFX カード (GP 2.2.1 (または 2.3 ですか?) に準拠していると主張されている) でテストしたところ、動作しました。APPLICATION_LOCKED(0x80)を使用して、状態を正常にロックに設定できました。その後、状態は に設定されprevious_state | 0x80ます。上位ビットが設定されている他の状態値 (0x8F など) を設定しようとしても機能しません (予想どおり)。

代替ソリューション

アプリケーションのライフサイクルを state に設定できずに問題を解決するためにできることは、アプリケーションAPPLICATION_LOCKED固有のライフサイクルの状態を使用することです。

public class LockableApplet extends Applet {

    [... applet installation / instantiation code ...]

    private static final byte APPLICATION_STATE_UNLOCKED = (byte)0x07;
    private static final byte APPLICATION_STATE_LOCKED = (byte)0x7F;

    public boolean select() {
        if (GPSystem.getCardContentState() == APPLICATION_STATE_LOCKED) {
            return false;
        }

        return true;
    }

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

        if (GPSystem.getCardContentState() == APPLICATION_STATE_LOCKED) {
            ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
        }

        [... applet logic code ...]

    }   
}

アプリケーションがロックされる原因となる問題を検出すると、次の呼び出しでアプレットをロックできます。

GPSystem.setCardContentState(APPLICATION_STATE_LOCKED);

後でセキュリティ ドメインを介して SET STATUS コマンドを使用して、アプリケーションを再度ロック解除できます。

于 2016-05-11T07:24:20.173 に答える
5

(バイヤーは注意してください: この方法は単に機能しないようです -- コメントを参照してください)

(GlobalPlatform カード仕様 2.2.1 のコンテキストで)

図 5-2 に示されているアプリケーション ライフ サイクル状態の規則に従う必要があります (ここでは「5」とマークされた矢印が適用されます)。

正しい方法は次のとおりです。

GPSystem.setCardContentState((byte)(GPSystem.getCardContentState() | GPSystem.APPLICATION_LOCKED));

また

GPSystem.getRegistryEntry(JCSystem.getAID()).setState((byte)(GPSystem.getCardCo‌​ntentState() | GPSystem.APPLICATION_LOCKED))

アプリケーションの0x80ライフサイクル状態が無効です。表 11-4 を参照してください (少なくともビットb1b2ビットが設定されている必要がありますb3。ビットもおそらく同様です)。

編集>

(私は、OPEN がエンティティがロックされた元の状態を保持しているという事実の記憶のみに基づいて、この回答を書くことを告白します)

私はこれについて非常に興味があるので、次のアプレットを使用していくつかのテストを行いました (抜粋):

public void process(APDU apdu) {
    byte[] buffer = apdu.getBuffer();

    if(selectingApplet()) {
        return;
    }

    short claIns = Util.getShort(buffer, ISO7816.OFFSET_CLA);
    switch(claIns) {
        case (short) 0x8007:
            buffer[0]=GPSystem.getCardContentState();
            if(buffer[0]==buffer[ISO7816.OFFSET_P1]) {
                if(GPSystem.setCardContentState(buffer[ISO7816.OFFSET_P2])) {
                    buffer[1]=0x01;
                } else {
                    buffer[1]=0x00;
                }
            } else {
                buffer[1]=(byte)0xFF;
            }
            buffer[2]=GPSystem.getCardContentState();
            apdu.setOutgoingAndSend((short)0, (short)3);
            return;
        default: {
            ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
            return;
        }
    }
}

そして、次の APDU:

8007070F03 // To test transition into Application Specific State
80070F8F03 // To test my theory
80070F8003 // To test the GPSystem.APPLICATION_LOCKED constant directly

私の一連のカード (Gemalto、Morpho、JCOP - 残念ながら、それらはすべて GP 2.1.1 です) の結果は、Michael Roland の優れた回答と GP 仕様と一致しています。アプリケーション自体をブロックしようとする試みは拒否されました。

すべての GP 2.1.1 カードの受信応答 APDU:

8007070F03 -> 07010F9000 // Succeeded in transition from `07` to `0F`
80070F8F03 -> 0F000F9000 // Failed transition from `0F` to `8F`
80070F8003 -> 0F000F9000 // Failed transition from `0F` to `80`

注意:このツールは、カード認識データを解析するため、実装されている GP のバージョンを判断するのに非常に役立ちます。

于 2016-05-11T16:53:56.347 に答える
3

GP コア仕様自体への準拠はありません。製品は GP構成に準拠した GPです。GP の設定は無料ではありません。JCOP 2.4.x 製品は、GP 2.2.x の「v2.2.1 での既存の GP 2.1.1 実装のマッピング ガイドライン」構成に準拠しています。名前が示すように、この構成は下位互換性マッピング用です。基本的に、JCOP 2.4.x 製品は GP 2.1.1 準拠の製品のみです (GP 2.2.x のいくつかの機能を備えています)。アプレットの場合、グローバル ロック権限はオプションです。

于 2016-06-14T11:40:55.207 に答える
2

はい、非常に簡単です。private static booleanフラグを使用して、process(APDU apdu)メソッドの最初でチェックします。

public class MiniApplet extends Applet {

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

    protected MiniApplet() {
        register();
    }

    private static final short SW_APPLET_IS_LOCKED = (short) 0x9199; //any error SW
    private static boolean appletLocked = false; //static -> faster access, this flag is checked each call! "private" modifier is VERY important!

    public void process(APDU apdu) {
        if (selectingApplet()) {
            return; //it is a good practice not to throw any exceptions on SELECT command
        }

        if (appletLocked) { 
            ISOException.throwIt(SW_APPLET_IS_LOCKED);
        }

        if (attackDetected()) { //implement your attack detection
            appletLocked = true;
        }
    }   
}
于 2016-05-10T20:29:47.937 に答える