JavaScript is required to for searching.
ナビゲーションリンクをスキップ
印刷ビューの終了
Oracle Solaris 11 セキュリティーサービス開発ガイド     Oracle Solaris 11 Information Library (日本語)
search filter icon
search icon

ドキュメントの情報

はじめに

1.  Oracle Solaris の開発者向けセキュリティー機能 (概要)

2.  特権付きアプリケーションの開発

3.  PAM アプリケーションおよび PAM サービスの記述

4.  GSS-API を使用するアプリケーションの記述

5.  GSS-API クライアント例

6.  GSS-API サーバー例

7.  SASL を使用するアプリケーションの記述

8.  Oracle Solaris 暗号化フレームワークの紹介

9.  ユーザーレベルの暗号化アプリケーションとプロバイダの記述

10.  Oracle Solaris 鍵管理フレームワークの紹介

Oracle Solaris 鍵管理フレームワーク機能

Oracle Solaris 鍵管理フレームワークのコンポーネント

KMF 鍵管理ツール

KMF ポリシー実施機構

KMF アプリケーションプログラミングインタフェース

Oracle Solaris 鍵管理フレームワークのアプリケーション例

KMF ヘッダーおよびライブラリ

KMF 基本データ型

KMF アプリケーション結果の確認

KMF アプリケーションの完全なソースコード

A.  C ベース の GSS-API プログラム例

B.  GSS-API リファレンス

C.  OID の指定

D.  SASL ソースコード例

E.  SASL リファレンス

用語集

索引

Oracle Solaris 鍵管理フレームワークのアプリケーション例

pktool アプリケーションは、KMF API の使用方法を示す優れた例です。

この節では KMF を使用する単純なアプリケーションを示します。 この節では、アプリケーションが KMF 操作を実行するために実行する必要がある基本ステップについて説明します。 この例では、読者が C プログラミングの経験を持ち、公開鍵技術およびその規格についての基礎的な理解があることを想定しています。 この例では、使用する KMF を初期化するステップ全体を示し、自己署名付き X.509v3 証明書および関連付けられた RSA 鍵ペアを作成します。 またこの例では、KMF 拡張された pktool コマンドを使用して、アプリケーションが正常であることを確認する方法も示します。

KMF ヘッダーおよびライブラリ

KMF 関数のプロトタイプおよび型定義へのプログラムアクセスを提供するには、kmfapi.h ファイルをインクルードします。

#include <stdio.h>
#include <kmfapi.h>

KMF ライブラリをリンクステップでインクルードしてください。

$ cc -o kmftest kmftest.c -lkmf

KMF 基本データ型

構造体および型の定義については、kmftypes.h ファイルを参照してください。 この例では、次の KMF 型の変数を使用します。

KMF_HANDLE_T

KMF 呼び出しのためのセッションハンドル

KMF_RETURN

すべての KMF 呼び出しの戻りコード

KMF_KEY_HANDLE

KMF キーのハンドル

KMF_CREDENTIAL

KMF 資格

KMF_ATTRIBUTE

これが十分な大きさであることを確認してください

KMF_KEYSTORE_TYPE

キーストア型 (KMF_KEYSTORE_PK11TOKEN など)

KMF_KEY_ALG

鍵の種類 (KMF_RSA など)

KMF_X509_CERTIFICATE

署名されるデータレコード

KMF_X509_NAME

識別名レコード

KMF_DATA

最終証明書データレコード

KMF_BIGINT

整数の変数の長さ

KMF アプリケーション結果の確認

ユーザーは pktool(1M) ユーティリティーを使用することによって、プログラムが証明書および鍵ペアを正しく作成したことを確認できます。

$ pktool list objtype=both
Enter pin for Sun Software PKCS#11 softtoken :
Found 1 certificates.
1. (X.509 certificate)
        Label: admin@foobar.com
        ID:
09:ac:7f:1a:01:f7:fc:a9:1a:cd:fd:8f:d4:92:4c:25:bf:b1:97:fe
        Subject: C=US, ST=CA, L=Menlo Park, O=Foobar Inc., OU=Foobar
IT Office, CN=admin@foobar.com
        Issuer: C=US, ST=CA, L=Menlo Park, O=Foobar Inc., OU=Foobar IT
Office, CN=admin@foobar.com
        Serial: 0x452BF693
        X509v3 Subject Alternative Name:
    email:admin@foobar.com

Found 1 keys.
Key #1 - RSA private key: admin@foobar.com

KMF アプリケーションの完全なソースコード

KMF API の定義については、libkmf(3LIB) のマニュアルページを参照してください。

このアプリケーションは次の手順を実行します。

  1. KMF 関数を呼び出す前に、アプリケーションはまず kmf_initialize() を使用して、KMF セッション用のハンドルを初期化する必要があります。 このハンドルは、ほとんどの KMF 関数呼び出しの最初の引数として使用されます。 これは不透明なデータ型で、そのセッションの内部状態およびコンテキスト情報を保持するために使用されます。

  2. このアプリケーション例では PKCS#11 キーストアを使用します。 kmf_configure_keystore() を使用して、今後の操作のために使用するトークンを定義します。

  3. 証明書または PKCS#10 CSR を作成する最初のステップは鍵ペアを作成することです。 kmf_create_keypair() を使用して、必要となる公開鍵および非公開鍵の両方を作成し、指定されたキーストアに非公開鍵を保管します。 関数はアプリケーションにハンドルを返すため、呼び出し元は今後の操作で必要な場合に公開鍵および非公開鍵オブジェクトを参照できます。

  4. 鍵ペアが設定されたら、kmf_set_cert_pubkey() および kmf_set_cert_version() を使用して、最終証明書を生成するために使用するテンプレートレコードにデータを取り込みます。 KMF は拡張機能を含め、X.509v3 証明書の各種フィールドを設定するためのさまざまな API を提供します。 kmf_hexstr_to_bytes()kmf_set_cert_serial()kmf_set_cert_validity()、および kmf_set_cert_sig_alg() を使用してシリアル番号を設定します。 シリアル番号は KMF_BIGINT レコードです。 kmf_dn_parser()kmf_set_cert_subject()、および kmf_set_cert_issuer() を使用して KMF_X509_NAME 構造体を作成します。

  5. これは自己証明証明書の作成演習であるため、このアプリケーションは上記で作成された証明書テンプレートを、証明書それ自身の公開鍵と合った秘密鍵で署名します。 この kmf_sign_cert() 操作の結果は、ASN.1 でエンコードされた X.509v3 証明書データを格納する KMF_DATA レコードになります。

  6. 証明書は署名されて最終的なフォーマットになったため、証明書はどのキーストアにも保管できます。 kmf_store_cert() を使用して、このアプリケーションの先頭で定義されている PKCS#11 トークンに証明書を保管します。 証明書はこの時点で NSS または OpenSSL ファイルに保管することも可能です。

  7. KMF によって生成されたデータ構造体に対して割り当てられたメモリーは、データ構造体が不要になったときにクリーンアップする必要があります。 KMF には、これらのオブジェクトに関連付けられたメモリーを適切に割り当て解除するための便利な API が提供されています。 リソースを節約するためにメモリーを適切にクリーンアップすることを強くお勧めします。 クリーンアップインタフェースは、kmf_free_data()kmf_free_dn()、および kmf_finalize() を含んでいます。

次に、すべてのデータ型およびヘルパー関数を含むアプリケーション例の完全なソースコードを示します。 コンパイルの後、KMF ライブラリをインクルードしてください。

/*
 * KMF Example code for generating a self-signed X.509 certificate.
 * This is completely unsupported and is just to be used as an example.
 *
 * Compile:
 * $ cc -o keytest keytest.c -lkmf
 *
 * Run:
 * $  ./keytest
 *
 * Once complete, the results can be verified using the pktool(1) command:
 *
 * $ pktool list 
 * This should show an RSA public key labeled "keytest" and a cert labeled "keytest".
 *
 * The objects created by this program can be deleted from the keystore
 * using pktool(1) also:
 *
 * $ pktool delete label=keytest
 *
 */ 
#include <stdio.h>
#include <strings.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <tzfile.h>

#include <kmfapi.h>

int
main(int argc, char *argv[])
{
    KMF_HANDLE_T         kmfhandle;
    KMF_RETURN           ret;
    char                 opt, *str = NULL;
    extern char          *optarg;
    KMF_KEY_HANDLE       prikey, pubkey;
    KMF_CREDENTIAL       cred;
    KMF_ATTRIBUTE        attrlist[16]; /* this needs to be big enough */
    KMF_KEYSTORE_TYPE    kstype;
    KMF_KEY_ALG          keytype;
    KMF_KEY_HANDLE       prik, pubk;
    KMF_X509_CERTIFICATE certstruct;
    KMF_X509_NAME        certsubject, certissuer;
    KMF_DATA             rawcert;
    KMF_BIGINT           serno;
    char                 *token = "Sun Software PKCS#11 softtoken";
    char                 *keylabel = "keytest";
    boolean_t            readonly = B_FALSE;
    uint32_t             keylen = 1024;
    uint32_t             ltime = SECSPERDAY * DAYSPERNYEAR; /* seconds in a
                             year (see tzfile.h) */
    char                 prompt[1024];
    int                  numattrs;

    (void) memset(&certstruct, 0, sizeof (certstruct));
    (void) memset(&rawcert, 0, sizeof (rawcert));
    (void) memset(&certissuer, 0, sizeof (certissuer));
    (void) memset(&certsubject, 0, sizeof (certsubject));

    /*
     * Initialize a KMF handle for use in future calls.
     */
    ret = kmf_initialize(&kmfhandle, NULL, NULL);
    if (ret != KMF_OK) {
        printf("kmf_initialize failed: 0x%0x\n", ret);
        exit(1);
    }

    /* We want to use the PKCS11 keystore */
    kstype = KMF_KEYSTORE_PK11TOKEN;
    numattrs = 0;
    kmf_set_attr_at_index(attrlist, numattrs, KMF_KEYSTORE_TYPE_ATTR,
        &kstype, sizeof (kstype));
    numattrs++;

    /* Indicate which PKCS11 token will be used */
    kmf_set_attr_at_index(attrlist, numattrs, KMF_TOKEN_LABEL_ATTR,
        token, strlen(token));
    numattrs++;

    kmf_set_attr_at_index(attrlist, numattrs, KMF_READONLY_ATTR,
        &readonly, sizeof (readonly));
    numattrs++;

    ret = kmf_configure_keystore(kmfhandle, numattrs, attrlist);
    if (ret != KMF_OK)
        exit (ret);

    /* Reset the attribute count for a new command */
    numattrs = 0;

    /*
     * Get the PIN to access the token.
     */
    (void) snprintf(prompt, sizeof (prompt), "Enter PIN for %s:", token);
    cred.cred = getpassphrase(prompt);
    if (cred.cred != NULL) {
        cred.credlen = strlen(cred.cred);
        kmf_set_attr_at_index(attrlist, numattrs, KMF_CREDENTIAL_ATTR,
            &cred, sizeof (cred));
        numattrs++;
    }

    kmf_set_attr_at_index(attrlist, numattrs, KMF_KEYSTORE_TYPE_ATTR,
        &kstype, sizeof (kstype));
    numattrs++;

    keytype = KMF_RSA;
    keylen = 1024;
    keylabel = "keytest";

    kmf_set_attr_at_index(attrlist, numattrs, KMF_KEYALG_ATTR,
        &keytype, sizeof (keytype));
    numattrs++;

    kmf_set_attr_at_index(attrlist, numattrs, KMF_KEYLENGTH_ATTR,
        &keylen, sizeof (keylen));
    numattrs++;

    kmf_set_attr_at_index(attrlist, numattrs, KMF_KEYLABEL_ATTR,
        keylabel, strlen(keylabel));
    numattrs++;

    kmf_set_attr_at_index(attrlist, numattrs, KMF_CREDENTIAL_ATTR,
        &cred, sizeof (cred));
    numattrs++;

    /*
     * Set the handles so they can be used later.
     */
    kmf_set_attr_at_index(attrlist, numattrs, KMF_PRIVKEY_HANDLE_ATTR,
        &prik, sizeof (prik));
    numattrs++;

    kmf_set_attr_at_index(attrlist, numattrs, KMF_PUBKEY_HANDLE_ATTR,
        &pubk, sizeof (pubk));
    numattrs++;

    ret = kmf_create_keypair(kmfhandle, numattrs, attrlist);
    if (ret != KMF_OK) {
        printf("kmf_create_keypair error: 0x%02x\n", ret);
        goto cleanup;
    }

    /*
     * Now the keys have been created, generate an X.509 certificate
     * by populating the template and signing it.
     */
    if ((ret = kmf_set_cert_pubkey(kmfhandle, &pubk, &certstruct))) {
        printf("kmf_set_cert_pubkey error: 0x%02x\n", ret);
        goto cleanup;
    }

    /* Version "2" is for an x509.v3 certificate */
    if ((ret = kmf_set_cert_version(&certstruct, 2))) {
        printf("kmf_set_cert_version error: 0x%02x\n", ret);
        goto cleanup;
    }

    /*
     * Set up the serial number, it must be a KMF_BIGINT record.
     */
    if ((ret = kmf_hexstr_to_bytes((uchar_t *)"0x010203", &serno.val, \
            &serno.len))) {
        printf("kmf_hexstr_to_bytes error: 0x%02x\n", ret);
        goto cleanup;
    }

    if ((ret = kmf_set_cert_serial(&certstruct, &serno))) {
        printf("kmf_set_cert_serial error: 0x%02x\n", ret);
        goto cleanup;
    }

    if ((ret = kmf_set_cert_validity(&certstruct, NULL, ltime))) {
        printf("kmf_set_cert_validity error: 0x%02x\n", ret);
        goto cleanup;
    }

    if ((ret = kmf_set_cert_sig_alg(&certstruct, KMF_ALGID_SHA1WithRSA))) {
        printf("kmf_set_cert_sig_alg error: 0x%02x\n", ret);
        goto cleanup;
    }

    /*
     * Create a KMF_X509_NAME struct by parsing a distinguished name.
     */
    if ((ret = kmf_dn_parser("cn=testcert", &certsubject))) {
        printf("kmf_dn_parser error: 0x%02x\n", ret);
        goto cleanup;
    }

    if ((ret = kmf_dn_parser("cn=testcert", &certissuer))) {
        printf("kmf_dn_parser error: 0x%02x\n", ret);
        goto cleanup;
    }

    if ((ret = kmf_set_cert_subject(&certstruct, &certsubject))) {
        printf("kmf_set_cert_sig_alg error: 0x%02x\n", ret);
        goto cleanup;
    }

    if ((ret = kmf_set_cert_issuer(&certstruct, &certissuer))) {
        printf("kmf_set_cert_sig_alg error: 0x%02x\n", ret);
        goto cleanup;
    }

    /*
     * Now we have the certstruct setup with the minimal amount needed
     * to generate a self-signed cert.  Put together the attributes to 
     * call kmf_sign_cert.
     */
    numattrs = 0;
    kmf_set_attr_at_index(attrlist, numattrs, KMF_KEYSTORE_TYPE_ATTR,
            &kstype, sizeof (kstype));
    numattrs++;

    kmf_set_attr_at_index(attrlist, numattrs, KMF_KEY_HANDLE_ATTR,
            &prik, sizeof (KMF_KEY_HANDLE_ATTR));
    numattrs++;

    /* The X509 template structure to be signed goes here. */
    kmf_set_attr_at_index(attrlist, numattrs, KMF_X509_CERTIFICATE_ATTR,
            &certstruct, sizeof (KMF_X509_CERTIFICATE));
    numattrs++;

    /*
     * Set the output buffer for the signed cert.
     * This will be a block of raw ASN.1 data.
     */
    kmf_set_attr_at_index(attrlist, numattrs, KMF_CERT_DATA_ATTR,
            &rawcert, sizeof (KMF_DATA));
    numattrs++;

    if ((ret = kmf_sign_cert(kmfhandle, numattrs, attrlist))) {
        printf("kmf_sign_cert error: 0x%02x\n", ret);
        goto cleanup;
    }

    /*
     * Now we have the certificate and we want to store it in the
     * keystore (which is the PKCS11 token in this example).
     */
    numattrs = 0;
    kmf_set_attr_at_index(attrlist, numattrs, KMF_KEYSTORE_TYPE_ATTR,
            &kstype, sizeof (kstype));
    numattrs++;
    kmf_set_attr_at_index(attrlist, numattrs, KMF_CERT_DATA_ATTR,
            &rawcert, sizeof (KMF_DATA));
    numattrs++;

    /* Use the same label as the public key */
    kmf_set_attr_at_index(attrlist, numattrs, KMF_CERT_LABEL_ATTR,
        keylabel, strlen(keylabel));
    numattrs++;

    if ((ret = kmf_store_cert(kmfhandle, numattrs, attrlist))) {
        printf("kmf_store_cert error: 0x%02x\n", ret);
                goto cleanup;
    }

cleanup:
    kmf_free_data(&rawcert);
    kmf_free_dn(&certissuer);
    kmf_free_dn(&certsubject);
    kmf_finalize(kmfhandle);

    return (ret);
}