| ナビゲーションリンクをスキップ | |
| 印刷ビューの終了 | |
|
Oracle Solaris 11 セキュリティーサービス開発ガイド Oracle Solaris 11.1 Information Library (日本語) |
1. Oracle Solaris の開発者向けセキュリティー機能 (概要)
3. PAM アプリケーションおよび PAM サービスの記述
8. Oracle Solaris 暗号化フレームワークの紹介
10. Oracle Solaris 鍵管理フレームワークの紹介
pktool アプリケーションは、KMF API の使用方法を示す優れた例です。
このセクションでは KMF を使用する単純なアプリケーションを示します。このセクションでは、アプリケーションが KMF 操作を実行するために実行する必要がある基本ステップについて説明します。この例では、読者が C プログラミングの経験を持ち、公開鍵技術およびその規格についての基礎的な理解があることを想定しています。この例では、使用する KMF を初期化するステップ全体を示し、自己署名付き X.509v3 証明書および関連付けられた RSA 鍵ペアを作成します。またこの例では、KMF 拡張された pktool コマンドを使用して、アプリケーションが正常であることを確認する方法も示します。
KMF 関数のプロトタイプおよび型定義へのプログラムアクセスを提供するには、kmfapi.h ファイルをインクルードします。
#include <stdio.h> #include <kmfapi.h>
KMF ライブラリをリンクステップでインクルードしてください。
$ cc -o kmftest kmftest.c -lkmf
構造体および型の定義については、kmftypes.h ファイルを参照してください。この例では、次の KMF 型の変数を使用します。
KMF 呼び出しのためのセッションハンドル
すべての KMF 呼び出しの戻りコード
KMF キーのハンドル
KMF 資格
これが十分な大きさであることを確認してください
キーストア型 (KMF_KEYSTORE_PK11TOKEN など)
鍵の種類 (KMF_RSA など)
署名されるデータレコード
識別名レコード
最終証明書データレコード
整数の変数の長さ
ユーザーは 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 API の定義については、libkmf(3LIB) のマニュアルページを参照してください。
このアプリケーションは次の手順を実行します。
KMF 関数を呼び出す前に、アプリケーションはまず kmf_initialize() を使用して、KMF セッション用のハンドルを初期化する必要があります。このハンドルは、ほとんどの KMF 関数呼び出しの最初の引数として使用されます。これは不透明なデータ型で、そのセッションの内部状態およびコンテキスト情報を保持するために使用されます。
このアプリケーション例では PKCS#11 キーストアを使用します。kmf_configure_keystore() を使用して、今後の操作のために使用するトークンを定義します。
証明書または PKCS#10 CSR を作成する最初のステップは鍵ペアを作成することです。kmf_create_keypair() を使用して、必要となる公開鍵および非公開鍵の両方を作成し、指定されたキーストアに非公開鍵を保管します。関数はアプリケーションにハンドルを返すため、呼び出し元は今後の操作で必要な場合に公開鍵および非公開鍵オブジェクトを参照できます。
鍵ペアが設定されたら、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 構造体を作成します。
これは自己証明証明書の作成演習であるため、このアプリケーションは上記で作成された証明書テンプレートを、証明書それ自身の公開鍵と合った秘密鍵で署名します。この kmf_sign_cert() 操作の結果は、ASN.1 でエンコードされた X.509v3 証明書データを格納する KMF_DATA レコードになります。
証明書は署名されて最終的なフォーマットになったため、証明書はどのキーストアにも保管できます。kmf_store_cert() を使用して、このアプリケーションの先頭で定義されている PKCS#11 トークンに証明書を保管します。証明書はこの時点で NSS または OpenSSL ファイルに保管することも可能です。
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);
}