次の方法で共有


カード PIN 操作

PIN は、ATM (現金自動預払機) のテンキーで初めて使われた、銀行業界が発祥の用語です。 その他の業界ドキュメントでは、カード保有者本人照合 (CHV) という用語が使われることもあります。 データ形式は単なる数値ではなく、ユーザーが自由に手段を指定して提供できるものだと理解されています。 PIN データとして渡される値は、ANSI 1 バイト文字セットとの相互運用性に関する考慮事項に制約されます。

ユーザーが通常は管理認証シークレットを所有する権限を持たないという点で、ユーザーの認証は管理者の認証とは大きく異なります。 このことは、ユーザーの認証に使用できるデータの種類と、その処理方法に関して多くの意味を持ちます。 中央当局の支援を受けてユーザーのカードのブロックを解除する場合など、クライアント コンピューターで管理者シークレットを使用する際には、このデータは、漏えいの可能性がない状態で安全にカードへ送信するか、さもなければ現在のトランザクションの外部では無価値になるように完全にエフェメラルにする必要があります。 安全にカードへ送信するしくみを構築することの難しさが、管理者の認証に PIN を使用することが推奨されない理由です。

認証されたセッションが別のアプリケーションによってハイジャックされるのを防ぐために、認証の有効性はトランザクション内に限定されます。 トランザクションが終了すると、認証は自動的に解除されます。

PIN を変更すると、セキュア トークンが無効になるようにする必要があります。

一般的な定義

PIN には 2 つのデータ型が定義されています。ロールに関連付けられている個々の PIN を記述するためのデータ型と、PIN 識別子を持つビット マスクに使用される PIN_SET です。 また、文字列でのユーザー名は廃止され、PIN 識別子に変換するロール番号が導入されています。 また、この仕様内で解説する、PIN 変更操作のための 2 つのフラグも定義されています。

typedef     DWORD                      PIN_ID, *PPIN_ID;
typedef     DWORD                      PIN_SET, *PPIN_SET;

#define     MAX_PINS                   8

#define     ROLE_EVERYONE              0
#define     ROLE_USER                  1
#define     ROLE_ADMIN                 2

#define     PIN_SET_ALL_ROLES          0xFF
#define     CREATE_PIN_SET(PinId)      (1 << PinId)
#define     SET_PIN(PinSet, PinId)     PinSet |= CREATE_PIN_SET(PinId)
#define     IS_PIN_SET(PinSet, PinId)  (0 != (PinSet & CREATE_PIN_SET(PinId)))
#define     CLEAR_PIN(PinSet, PinId)   PinSet &= ~CREATE_PIN_SET(PinId)

#define     PIN_CHANGE_FLAG_UNBLOCK    0x01
#define     PIN_CHANGE_FLAG_CHANGEPIN  0x02

現行のカード ミニドライバー カードと機能的に同等にするには、すべてのカードに少なくとも 3 つのロール (ROLE_EVERYONE、ROLE_USER、ROLE_ADMIN) をプロビジョニングする必要があります。 それぞれのロールは、カードの PIN_ID 1 つに相当します。 カードの真の管理者ロールは 1 つだけですが、他のロールのブロックを解除できる複数のロールが存在できます。 ただし、ファイル システムの削除など、管理者レベルの操作を実行するためのアクセスを制御するロールは 1 つしかありません。それが ROLE_ADMIN です。 さらに ROLE_ADMIN は、ROLE_USER のブロックを解除できる必要があります。 カードにファイル システムへのアクセス権を付与するユーザー ロールも、1 つだけです。 追加のロール 3 から 7 は省略可能であり、キー コンテナーにのみ関連付けることができます。

読み取り専用カードに適用できる特殊な考慮事項については、後出の「読み取り専用カード」を参照してください。

SECRET_TYPE

次の列挙体は、PIN の種類を表します。

typedef enum
{
    AlphaNumericPinType = 0,    // Regular PIN
    ExternalPinType,            // External PIN
    ChallengeResponsePinType,   // Challenge/Response PIN
    EmptyPinType                // No PIN
} SECRET_TYPE;

注: PIN "SECRET_TYPEEmptyPinType" に遭遇すると、Windows は PIN の入力を求めず、また、CardAuthenticatePinCardAuthenticatePinEx も呼び出しません。 この設定は、カード上のマテリアルへの無条件アクセスが必要な場合に便利です。

SECRET_PURPOSE

次の列挙体は、ユーザーに対して PIN の目的を説明するために、PIN_INFO データ構造で使用されます。

typedef enum
{
    AuthenticationPin,      // Authentication PIN
    DigitalSignaturePin,    // Digital Signature PIN
    EncryptionPin,          // Encryption PIN
    NonRepudiationPin,      // Non Repudiation PIN
    AdministratorPin,       // Administrator PIN
    PrimaryCardPin,
    UnblockOnlyPin          // Unblocking other PINs
} SECRET_PURPOSE;

Windows は、現在要求されているカード PIN を記載した適切なメッセージをユーザーに向けて表示するために、列挙値を使用します。 どの SECRET_TYPE を使用するのかは、ミニドライバーが完全に制御します。 下の画像は、サンプルのコンテキスト文字列を含む PIN プロンプト ダイアログ ボックスです。

pin dialog box.

画像の最初の文字列 ("Enter PIN. Enrolling for: BaseRSASmartcardLogon" (BaseRSASmartcardLogon に登録するために PIN を入力してください)) は、アプリケーション コンテキストがわかるように、呼び出し元アプリケーションによって提供されます。 アプリケーション コンテキスト文字列が存在しない場合は、標準テキストがダイアログ ボックスに表示されます。

2 番目の文字列 ("Please enter your authentication PIN" (認証 PIN を入力してください)) は、以下のいずれかの方法で SECRET_PURPOSE によって決定されます。

  • 既定のコンテキスト文字列

    既定では、適切にローカライズされた次の定義済み文字列が Base CSP に表示されます。

    文字列名 String
    AuthenticationPin "Please enter your authentication PIN." (認証 PIN を入力してください)
    DigitalSignaturePin "Please enter your digital signature PIN." (デジタル署名 PIN を入力してください)
    EncryptionPin "Please enter your encryption PIN." (暗号化 PIN を入力してください)
    NonRepudiationPin "Please enter your non repudiation PIN." (否認防止 PIN を入力してください)
    AdministratorPin "Please enter your administrator PIN." (管理者 PIN を入力してください)
    PrimaryCardPin "Please enter your PIN." (PIN を入力してください)
    UnblockOnlyPin "Please enter your PIN to unblock the user PIN." (ユーザー PIN のブロックを解除するには PIN を入力してください)
  • カスタム文字列

    開発者は、ミニドライバーのレジストリ キー (HKLM\Software\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards\XYZ、"XYZ" はカード ミニドライバー名) の以下のレジストリ値にカスタム文字列を設定することで、既定のコンテキスト文字列をオーバーライドできます。

    定義済みのコンテキスト文字列をオーバーライドするには、カスタム文字列を使用して、ミニドライバーのレジストリ キーにレジストリ文字列値を追加します。 SECRET_PURPOSE のどの定義済みコンテキスト文字列を上書きするのかは、キーの名前で設定します。0x80000100 は SECRET_TYPE の 1 番目のメンバーに対応し、以下同様です。 文字列を 1 つだけ、複数、またはすべてのコンテキスト文字列をオーバーライドすることはできません。

    文字列の値は、次の形式に従う必要があります。

    “LangID,xxxx;LangID,xxxxx”
    

    注: カスタム文字列を囲んでいる引用符は適切に処理されません。文字列内の特殊文字の解析の妨げになるので使用しないでください。

注: 同じロケールに 2 つの異なるカスタム文字列を含めると、1 つ目のカスタム文字列が採用されます。

ダイアログ ボックスの 3 番目の文字列 ("Digital Signature PIN" (デジタル署名 PIN)) は、PIN_INFO データ構造の SECRET_PURPOSE 値によって決定される、定義済み文字列です。

UnblockOnlyPin の場合、その目的はユーザー PIN のブロック解除です。 この PIN は、他の目的には使用しないでください。

PIN_CACHE_POLICY_TYPE

次の列挙体は、この PIN に関連付ける PIN キャッシュ ポリシーを表します。

typedef enum
{
    PinCacheNormal = 0,
    PinCacheTimed,
    PinCacheNone,
    PinCacheAlwaysPrompt
} PIN_CACHE_POLICY_TYPE;

次の表は、3 つの異なるキャッシュ モードでの Base CSP の動作をまとめたものです。

キャッシュ モード 説明
PinCacheNormal このモードでは、それぞれのログオン ID でプロセスごとに Base CSP によって PIN がキャッシュされます。
PinCacheTimed このモードでは、指定された期間 (値は秒単位) が経過すると PIN が無効になります。 無効化は、PIN がキャッシュに追加されたときのタイムスタンプを記録し、このタイムスタンプと PIN がアクセスされたタイムスタンプを確認することによって実行されます。 つまり、PIN は指定されたタイムスタンプより長くキャッシュに保存される可能性がありますが、有効期限が切れた後は使用されません。 保護された状態を維持するため、PIN はメモリ内で暗号化されます。
PinCacheNone PIN をキャッシュできない場合、Base CSP は PIN をキャッシュに追加しません。 PIN を設定するために CryptSetProvParam で Base CSP/KSP が呼び出されると、PIN は検証のためにカードに送信されますが、キャッシュはされません。 つまり、Base CSP トランザクションがタイムアウトになる前に、後続の操作を実行する必要があります。
PinCacheAlwaysPrompt PinCacheNone とは異なり、このキャッシュ モードが設定されていると、Base CSP のトランザクション タイムアウトは適用されません。 PIN はユーザーから収集され、認証を必要とする各呼び出しの前に、検証のためにカードに送信されます。 PIN を設定するために CryptSetProvParamNcryptSetProperty を呼び出すと、PIN の検証とキャッシュは行われずに ERROR_SUCCESS が返されます。 つまり、サイレント コンテキストを使用するアプリケーションからの呼び出しは、呼び出しに認証が必要な場合には失敗するということです。

注: PIN がキャッシュされていない場合には、Windows ログオンが正しく機能しない可能性があります。 この動作は仕様によるものです。 そのため、PIN キャッシュ モードを PinCacheNormal 以外の値に設定する場合は、慎重に検討するようにしてください。

PIN_CACHE_POLICY

PIN キャッシュ ポリシー構造には、PIN のキャッシュ ポリシーを表す情報が含まれています。 この PIN のキャッシュ ポリシーに関連付けられている情報に加えて、PIN キャッシュの種類も表します。 関連付けられている情報の一例としては、ポリシーに PinCacheTimed が含まれる場合の PIN キャッシュのタイムアウト値などがあります。

#define      PIN_CACHE_POLICY_CURRENT_VERSION   6

typedef struct _PIN_CACHE_POLICY
{
    DWORD                   dwVersion;
    PIN_CACHE_POLICY_TYPE   PinCachePolicyType;
    DWORD                   dwPinCachePolicyInfo;
} PIN_CACHE_POLICY, *PPIN_CACHE_POLICY;

PIN_INFO

PIN オブジェクト構造には、PIN を説明する情報が含まれています。 PIN の種類、このターゲット PIN のブロックを解除できる PIN、PIN のキャッシュ ポリシーを表します。 Base CSP/KSP によって取得された PIN 情報構造は、データ ファイルのキャッシュ方法と同様に、データ キャッシュにキャッシュする必要があります。

#define      PIN_INFO_REQUIRE_SECURE_ENTRY       1

typedef struct _PIN_INFO
{
    DWORD                   dwVersion;
    SECRET_TYPE             PinType;
    SECRET_PURPOSE          PinPurpose;
    PIN_SET                 dwChangePermission;
    PIN_SET                 dwUnblockPermission;
    PIN_CACHE_POLICY        PinCachePolicy;
    DWORD                   dwFlags;
} PIN_INFO, *PPIN_INFO;

dwUnblockPermission メンバーは、PIN のブロックを解除する権限を持つ PIN を表すビット マスクです。 権限は、指定された PIN のビットごとの "or" に基づきます。 ブロック解除操作では、カード ミニドライバーは、自己参照を無視する必要があります。 ROLE_USER の更新権限ビットマスクは 0x00000100 になります。 これは、ROLE_ADMIN によってブロックを解除できることを意味します。 ROLE_ADMIN の更新権限は 0x00000000 です。 これは、ブロックを解除できないことを意味します。

dwFlags メンバーには PIN フラグが含まれています。 現時点では、PIN_INFO_REQUIRE_SECURE_ENTRY という 1 つのフラグだけが定義されています。 このフラグは、PIN エントリにセキュリティで保護されたデスクトップが必要かどうかを Base CSP/KSP に示します。

注: この構造体を使用すれば、PIN を変更またはブロック解除する権限を ROLE_EVERYONE に付与できます。 これは推奨されません。また、ミニドライバー API には、ROLE_EVERYONE による PIN の変更またはブロック解除を許可するメカニズムは用意されていません。