Solaris 暗号化フレームワークは、Solaris オペレーティングシステム上のアプリケーションが暗号化サービスを使用または提供できるようにするためのアーキテクチャーです。このフレームワークとの相互作用はすべて、RSA Security Inc. PKCS#11 Cryptographic Token Interface (Cryptoki) に基づいています。PKCS#11 は、RSA Security Inc. の研究部門である RSA Laboratories によって開発された製品です。この章で説明する Solaris 暗号化フレームワークに関する内容は、次のとおりです。
暗号化サービスを取得するアプリケーション、ライブラリ、またはカーネルモジュールは「コンシューマ」と呼ばれます。フレームワーク経由でコンシューマに暗号化サービスを提供するアプリケーションは「プロバイダ」または「プラグイン」と呼ばれます。暗号化処理を実装するソフトウェアは「機構」と呼ばれます。機構は単なるアルゴリズムではなく、アルゴリズムの適用方法をも含みます。たとえば、DES アルゴリズムを認証に適用する場合、それは 1 つの独立した機構であるとみなされます。DES をブロック単位の暗号化に適用する場合、それは別の機構になります。
「トークン」とは、暗号化機能を持つデバイスを抽象化した概念です。 また、トークンには暗号化処理で使用する情報を格納することもできます。1 つのトークンで 1 つ以上の機構をサポートできます。トークンは、アクセラレータボードの場合と同様に、ハードウェアを表現できます。純粋なソフトウェアを表現するトークンは「ソフトトークン」と呼ばれます。トークンは溝穴 (スロット) に差し込む (プラグイン) ことができます (これも物理的なたとえです)。スロットは、暗号化サービスを使用するアプリケーションに対する接続ポイントです。
プロバイダ用の特定のスロットのほかに、Solaris 実装は「メタスロット」と呼ばれる特殊なスロットを提供します。メタスロットは、Solaris 暗号化フレームワークライブラリ (libpkcs11.so) のコンポーネントです。メタスロットは、フレームワークにインストールされているすべてのトークンとスロットの機能を結合させて単一の仮想スロットで提供するコンポーネントです。メタスロットにより、事実上、アプリケーションから利用可能なすべての暗号化サービスに単一のスロットを通じて透過的に接続できるようになります。アプリケーションが暗号化サービスを要求すると、メタスロットはもっとも適したスロットを示し、これによりスロットの選択処理が簡単になります。それとは異なるスロットが必要となる場合がありますが、その場合はアプリケーションが個別に明示的な検索を実行する必要があります。メタスロットは自動的に有効になり、システム管理者の明示的な操作によってのみ無効にできます。
「セッション」とは、暗号化サービスを使用するアプリケーションとトークン間に確立される接続のことです。PKCS #11 標準で使用されるオブジェクトには、次の 2 種類があります。 トークンオブジェクトとセッションオブジェクトです。「セッションオブジェクト」は一時的なオブジェクト、つまりセッション期間内でのみ存在できるオブジェクトです。セッション終了後も存続するオブジェクトが「トークンオブジェクト」と呼ばれます。
トークンオブジェクトのデフォルトの格納場所は、$HOME/.sunw/pkcs11_softtoken です。また、トークンオブジェクトを $SOFTTOKEN_DIR/pkcs11_softtoken に格納することも可能です。非公開のトークンオブジェクトは個人識別番号 (Personal Identification Number、PIN) によって保護されます。トークンオブジェクトを作成または変更するユーザーは、非公開のトークンオブジェクトにアクセスするのでない限り、必ず認証を受ける必要があります。
暗号化フレームワークは Solaris OS の一部であり、Sun Microsystems, Inc. および第三者の開発元による暗号化サービスを提供します。このフレームワークは、次のようなさまざまなサービスを提供します。
メッセージ暗号化とメッセージダイジェスト
メッセージ認証コード (Message authentication Code、MAC)
デジタル署名
暗号化サービスにアクセスするためのアプリケーションプログラミングインタフェース (API)
暗号化サービスを提供するためのサービスプロバイダインタフェース (SPI)
暗号化リソースを管理するための管理コマンド
次の図は、暗号化フレームワークの概要を示したものです。図の淡いグレーの部分は、暗号化フレームワークのユーザーレベル領域を示します。濃いグレーの部分は、フレームワークのカーネルレベル領域を表します。非公開のソフトウェアは、背景に斜線が入っています。
暗号化フレームワークの各コンポーネントの説明は、次のとおりです。
libpkcs11.so – このフレームワークは、RSA Security Inc. PKCS#11 Cryptographic Token Interface (Cryptoki) 経由でのアクセスを提供します。アプリケーションは libpkcs11.so ライブラリにリンクする必要があります。このライブラリは RSA PKCS#11 v2.11 標準を実装したものです。
プラグイン可能インタフェース – プラグイン可能インタフェースは、Sun Microsystems, Inc. および第三書の開発元が提供する PKCS #11 暗号化サービスのためのサービスプロバイダインタフェース (SPI) です。プロバイダはユーザーレベルのライブラリです。プロバイダは、ハードウェアまたはソフトウェアとして使用可能な暗号化サービスを利用して実装されます。
pkcs11_softtoken.so – Sun Microsystems, Inc. が提供する、ユーザーレベルの暗号化機構が含まれた非公開の共有オブジェクト。pkcs11_softtoken(5) ライブラリは RSA PKCS#11 v2.11 標準を実装しています。
pkcs11_kernel.so – カーネルレベルの暗号化機構にアクセスするための非公開の共有オブジェクト。pkcs11_kernel(5) は RSA PKCS#11 v2.11 仕様を実装しています。 pkcs11_kernel.so は、カーネルのサービスプロバイダインタフェースにプラグインされた暗号化サービスに対する PKCS#11 ユーザーインタフェースを提供します。
/dev/crypto 擬似デバイスドライバ – カーネルレベルの暗号化機構を使用するための非公開擬似デバイスドライバ。この情報を提供する目的は、擬似デバイスドライバを誤って削除しないように注意を促すことです。
スケジューラ/ロードバランサ – 暗号化サービス要求の使用、負荷分散、およびディスパッチを調整する役割を担うカーネルソフトウェア。
カーネルプログラマインタフェース – 暗号化サービスを使用するカーネルレベルコンシューマ用のインタフェース。IPSec プロトコルと kerberos GSS 機構は典型的な暗号化コンシューマです。
このインタフェースを利用するには、Sun Microsystems, Inc. と連絡を取る必要があります。詳細については、solaris-crypto-api@sun.com 宛てに電子メールをお送りください。
サービスプロバイダインタフェース – カーネルレベルの暗号化サービスプロバイダ用の SPI。これらのサービスは、ハードウェア上に実装することも、ソフトウェア上に実装することもできます。この SPI を使用するプロバイダは、Solaris カーネルから特殊なルーチンをインポートする必要があります。これらのルーチンを使用すれば、モジュールとデバイスドライバはサービスの登録と削除を行えます。また、これらのルーチンは状態の変化をフレームワークに通知します。このフレームワークでは、プロバイダが特定のルーチンをエクスポートする必要もあります。エクスポートされたルーチンを使用することで、暗号化フレームワークのコンシューマやその他のコンポーネントはプロバイダに要求を送信することができます。
Sun HW 暗号化プロバイダおよび Sun SW 暗号化プロバイダ – Sun Microsystems, Inc. が提供するカーネルレベルの暗号化サービス。HW は「ハードウェア」の暗号化サービス (アクセラレータボードなど) を指します。SW は、暗号化アルゴリズムの実装など、暗号化サービスを提供するカーネルモジュールを指します。
カーネル暗号化フレームワークデーモン – 暗号化処理で使用されるシステムリソースを管理する役割を担う非公開デーモン。また、暗号化プロバイダを検証するのも、このデーモンの役割です。
モジュール検証ライブラリ – Solaris 暗号化フレームワークがインポートするすべてのバイナリの整合性と認証性を検証するための非公開ライブラリ。
elfsign – 第三者の暗号化サービスプロバイダに提供されるユーティリティー。elfsign は、Sun の証明書を要求する場合に使用します。また、プロバイダは elfsign を使用することで、Solaris 暗号化フレームワークにプラグインされたバイナリ、つまり elf オブジェクトに実際に署名することもできます。
/dev/cryptoadm 擬似デバイスドライバ – cryptoadm(1M) がカーネルレベルの暗号化機構を管理する際に使用する非公開擬似デバイスドライバ。この情報を提供する目的は、擬似デバイスドライバを誤って削除しないように注意を促すことです。
cryptoadm – 管理者が暗号化サービスを管理するためのユーザーレベルのコマンド。 cryptoadm で行う一般的な作業は、暗号化プロバイダとその機能の一覧表示です。また、セキュリティーポリシーに従って暗号化機構を無効化および有効化する際も、cryptoadm を使用します。
ここでは、Solaris 暗号化フレームワークにプラグイン可能な 4 種類のアプリケーションを開発するための要件について説明します。
ユーザーレベルのコンシューマを開発する開発者は、次の点に留意する必要があります。
<security/cryptoki.h> をインクルードします。
すべての呼び出しを PKCS #11 インタフェース経由で行なってください。
libpkcs11.so をリンクします。
ライブラリ内で C_Finalize() 関数を呼び出すべきではありません。
詳細については、第 9 章ユーザーレベルの暗号化アプリケーションとプロバイダの記述を参照してください。
ユーザーレベルのプロバイダを開発する開発者は、次の点に留意する必要があります。
プロバイダをスタンドアロンとして設計します。プロバイダ共有オブジェクトはアプリケーションのリンク先になるような完全なライブラリでなくてもかまいませんが、必要なシンボルはすべてプロバイダ内に存在している必要があります。プロバイダが dlopen(3C) によって RTLD_GROUP モードおよび RTLD_NOW モードでオープンされることを前提にしてください。
PKCS #11 Cryptoki 実装を共有オブジェクトとして作成します。コンシューマアプリケーションに依存しないですむように、この共有オブジェクトには必要なシンボルが含まれている必要があります。
データクリーンアップ用の _fini() ルーチンを提供することを強くお勧めします。ただし、必須ではありません。この方法を使用すると、アプリケーションまたは共有ライブラリが libpkcs11 とほかのプロバイダライブラリを同時に読み込む場合に、複数の C_Finalize() 呼び出し間で衝突が発生するのを防ぐことができます。「ユーザーレベルのプロバイダにおけるデータクリーンアップ衝突の回避」を参照してください。
Sun Microsystems, Inc. に証明書を申請します。「プロバイダに署名するための証明書を要求するには」を参照してください。
証明書と elfsign を使ってバイナリに署名します。「プロバイダに署名するには」を参照してください。
Sun の規約に従って共有オブジェクトをパッケージ化します。付録 F 暗号化プロバイダのパッケージ化と署名を参照してください。
カーネルレベルのコンシューマを開発する開発者は、次の点に留意する必要があります。
<sys/crypto/common.h> と <sys/crypto/api.h> をインクルードします。
すべての呼び出しをカーネルプログラミングインタフェース経由で行います。
カーネルレベルのプロバイダを開発する開発者は、次の点に留意する必要があります。
<sys/crypto/common.h> と <sys/crypto/api.h> をインクルードします。
登録、登録解除、および状態提供に必要なルーチンをインポートします。
カーネル暗号化フレームワークに対してエントリポイントを提供するために、必要なルーチンをエクスポートします。
サポートされているアルゴリズムの説明を含むデータ構造をエクスポートします。
読み込み可能なカーネルモジュールを作成します。
Sun Microsystems, Inc. に証明書を申請します。「プロバイダに署名するための証明書を要求するには」を参照してください。
証明書と elfsign を使ってバイナリに署名します。「プロバイダに署名するには」を参照してください。
Sun の規約に従ってカーネルモジュールをパッケージ化します。付録 F 暗号化プロバイダのパッケージ化と署名を参照してください。
暗号化フレームワークにプラグインするユーザーレベルライブラリでは、_fini() 関数を提供する必要があります。_fini() 関数は、ライブラリの読み込み解除時にローダによって呼び出されます。_fini() 関数は、すべてのクリーンアップが正しいタイミングで正しく実行されるために必要です。libpkcs11 を使用するライブラリが C_Finalize() を呼び出すことは想定されていません。なぜなら、libpkcs11 はアプリケーションによって使用されている可能性がある共有ライブラリだからです。
_fini() 関数を提供するには、再配置可能オブジェクトのプログラムデータセクション内に .fini セクションを作成する必要があります。.fini セクションは実行時終了コードブロックを提供します。『リンカーとライブラリ』を参照してください。次のコード例は .fini セクションの設計方法を示しています。
#pragma fini(pkcs11_fini) static void pkcs11_fini(); /* [... (other library code omitted)] */ static void pkcs11_fini() { (void) pthread_mutex_lock(&pkcs11mutex); /* If CRYPTOKI is not initialized, do not clean up */ if (!initialized) { (void) pthread_mutex_unlock(&pkcs11mutex); return; } (void) finalize_routine(NULL_PTR); (void) pthread_mutex_unlock(&pkcs11mutex); }