Oracle® Solaris 11 セキュリティー開発者ガイド

印刷ビューの終了

更新: 2014 年 7 月
 
 

GSS-API における保護されたデータの送信

2 つのピア間でコンテキストが確立されたあと、メッセージを送信する前にそのメッセージを保護できます。

    コンテキストの確立時に使用されるのは、もっとも基本的な GSS-API 保護である認証だけです。実際のセキュリティーメカニズムによって異なりますが、GSS-API は次の 2 つの保護も提供します。

  • 整合性gss_get_mic() 関数によってメッセージに対するメッセージ整合性コード (MIC) が生成されます。受信側は、MIC を検査することで、受信したメッセージが送信されたメッセージと同じかどうかを確認できます。

  • 機密性 – MIC の使用に加え、メッセージが暗号化されます。暗号化を実行するのは、GSS-API の gss_wrap() 関数です。

gss_get_mic()gss_wrap() の違いを、次の図に示します。gss_get_mic() を使用した場合、受信側はメッセージが変更されていないことを示すタグを受け取ります。gss_wrap() を使用した場合、受信側は暗号化されたメッセージとタグを受け取ります。

図 4-7  gss_get_mic()gss_wrap()

image:gss_get_mic 関数と gss_wrap 関数の違いを示しています。

使用すべき関数はユーザーの状況に応じて異なります。gss_wrap() は整合性サービスも含むため、多くのプログラムは gss_wrap() を使用します。プログラムは、機密性サービスが利用可能かどうかを判定できます。続いてプログラムは、その利用可能性に応じて、機密性を指定して、あるいは指定しないで、gss_wrap()を呼び出すことができます。使用例については、Wrapping and Sending a Messageを参照してください。ただし、gss_get_mic() を使用するとメッセージをラップ解除する必要がないため、gss_wrap() を使用する場合よりも CPU サイクルを節約できます。したがって、機密性が必要ないプログラムは 、gss_get_mic() でメッセージを保護する可能性があります。

gss_get_mic() によるメッセージのタグ付け

gss_get_mic() を使用すると、プログラムは暗号化 MIC をメッセージに追加できます。受信側は、gss_verify_mic() でメッセージの MIC を検査できます。

gss_get_mic()gss_wrap() とは対照的に、メッセージと MIC を別々に出力します。この分離は、送信側アプリケーションがメッセージと対応する MIC の両方を送信する必要があることを意味します。さらに重要なのは、受信側がメッセージと MIC を区別できる必要がある、という点です。

    メッセージと MIC を適切に処理するには、次のいずれかの方法を使用します。

  • プログラム制御 (つまり、状態) を通じて。受信側アプリケーションは受信関数を 2 回呼び出す (つまり、1 回目はメッセージを取得するため、2 回目はメッセージの MIC を取得するため) ことをあらかじめ知ることができます。

  • フラグを通じて。送信側と受信側は、どの種類のトークンを含めるかをフラグで示すことができます。

  • メッセージと MIC の両方を含むユーザー定義トークン構造体を通じて。

gss_get_mic() が正常終了すると、GSS_S_COMPLETE が返されます。指定された QOP が有効でない場合、GSS_S_BAD_QOP が返されます。詳細は、gss_get_mic(3GSS) を参照してください。

gss_wrap() によるメッセージのラップ

メッセージは、gss_wrap() 関数でラップすることが可能です。gss_get_mic() と同様に、gss_wrap() は MIC を提供します。また、機密性が要求され、かつ実際のメカニズムで利用可能である場合には、gss_wrap() は指定されたメッセージの暗号化も行います。メッセージの受信側は gss_unwrap() でメッセージをラップ解除します。

gss_wrap()gss_get_mic() とは違い、メッセージと MIC をいっしょにラップし、1 つの出力メッセージにします。このバンドルを送信する関数の呼び出しは、1 回だけですみます。これに対し、gss_unwrap() はメッセージを抽出します。MIC はアプリケーションからは見えません。

メッセージが正常にラップされた場合、gss_wrap() は GSS_S_COMPLETE を戻します。要求された QOP が有効でない場合、GSS_S_BAD_QOP が返されます。gss_wrap() の使用例については、Wrapping and Sending a Messageを参照してください。

GSS-API におけるラップサイズ問題への対処法

gss_wrap() でメッセージをラップすると、送信すべきデータのサイズが増加します。保護されたメッセージパケットは、指定された転送プロトコルを通過するのに適したサイズである必要があります。したがって、GSS-API は関数 gss_wrap_size_limit() を提供しています。 gss_wrap_size_limit() は、プロトコルにとって大きすぎないサイズにラップ可能なメッセージの最大サイズを計算します。この最大サイズを超える場合、アプリケーションは gss_wrap() を呼び出す前にメッセージを分割できます。メッセージを実際にラップする前にラップサイズの制限値を必ず検査してください。

    サイズの増加量は次の 2 つの要因に依存します。

  • 変形を行うためにどの QOP アルゴリズムを使用するか

  • 機密性を呼び出すかどうか

デフォルトの QOP は、GSS-API の実装ごとに異なる可能性があります。したがって、デフォルトの QOP を指定した場合でも、ラップ後のメッセージのサイズが異なる可能性があります。この可能性を示したのが次の図です。

image:選択された QOP がメッセージのサイズに影響を与えることを示しています。

機密性を適用するかどうかにかかわらず、gss_wrap() によってメッセージのサイズが増加します。gss_wrap() は、転送メッセージ内に MIC を埋め込みます。しかし、メッセージを暗号化すると (機密性を適用すると)、メッセージのサイズはさらに増加します。このプロセスを示したのが次の図です。

image:機密性を適用するとメッセージサイズが増加することを示しています。

gss_wrap_size_limit() が正常終了すると、GSS_S_COMPLETE が返されます。指定された QOP が有効でない場合、GSS_S_BAD_QOP が返されます。gss_wrap_size_limit で元のメッセージの最大サイズを求める例については、Wrapping and Sending a Message() を参照してください。

この呼び出しが正常に終了したとしても、gss_wrap()max-input-size バイトの長さを持つメッセージを必ず保護できるという保証はありません。この機能は、gss_wrap() の呼び出し時点で必要なシステムリソースが利用可能かどうかに依存します。詳細は、gss_wrap_size_limit(3GSS) のマニュアルページを参照してください。

GSS-API における順序の問題の検出

コンテキスト起動側がコンテキスト受け入れ側に一連のデータパケットを順次転送する際、一部のメカニズムでは、その順序が正しいかどうかをコンテキスト受け入れ側が検査できるようになっています。これらの検査には、「パケットが正しい順序で到着したか」、「パケットが不必要に重複していないか」が含まれます。次の図を参照してください。受け入れ側がこれら 2 つの状態を検査するのは、パケットの検証時とパケットのラップ解除時です。詳細は、Unwrapping the Messageを参照してください。

図 4-8  リプレイされたメッセージと順序が正しくないメッセージ

image:メッセージが重複しているエラー状態と、順序が正しくないエラー状態を示しています。

起動側は gss_init_sec_context() で順序を検査できます。それには、GSS_C_REPLAY_FLAG または GSS_C_SEQUENCE_FLAG を論理 ORreq_flags 引数に設定します。

GSS-API におけるメッセージ転送の確認

受信側は、転送メッセージのラップ解除後または検証後に、確認を送信側に返すことができます。つまり、そのメッセージの MIC を返送します。送信側がラップはしなかったが gss_get_mic() で MIC をタグ付けしているメッセージの場合を考えます。

    実行手順 (Figure 4–9) は次のようになります。

  1. 起動側は gss_get_mic() でメッセージにタグ付けします。

  2. 起動側はメッセージと MIC を受け入れ側に送信します。

  3. 受け入れ側は gss_verify_mic() でメッセージを検証します。

  4. 受け入れ側は MIC を起動側に返送します。

  5. 起動側は gss_verify_mic() で、元のメッセージに対して受信した MIC を検証します。

図 4-9  MIC データの確認

image:MIC の確認方法を示しています。

ラップされたデータの場合、gss_unwrap() 関数はメッセージと MIC を別々に生成しません。したがって、受信側は、受信した (およびラップ解除した) メッセージから MIC を生成する必要があります。

    実行手順 (Figure 4–10) は次のようになります。

  1. 起動側は gss_wrap() でメッセージをラップします。

  2. 起動側はラップしたメッセージを送信します。

  3. 受け入れ側は gss_unwrap() でメッセージをラップ解除します。

  4. 受け入れ側は gss_get_mic() でラップ解除されたメッセージの MIC を生成します。

  5. 受け入れ側は抽出した MIC を起動側に返信します。

  6. 起動側は gss_verify_mic() で、元のメッセージに対して受信した MIC を検証します。

アプリケーションは、GSS-API データ用に割り当てられたすべてのデータ領域を解放します。これに関係する関数は、gss_release_buffer(3GSS)gss_release_cred(3GSS)gss_release_name(3GSS)、および gss_release_oid_set(3GSS) です。

図 4-10  ラップされたデータの確認

image:MIC 付きのラップされたメッセージの確認方法を示しています。