diff --git a/wolfSSL/Makefile b/wolfSSL/Makefile index 85444077..d4d8660c 100644 --- a/wolfSSL/Makefile +++ b/wolfSSL/Makefile @@ -94,7 +94,7 @@ pdf-prep: api $(Q)cp -a api/md/*8h* build/pdf/ $(Q)perl -i -pe "s/^(#+ )/#\$$1/g" build/pdf/group* build/pdf/*8h* $(Q)perl -i -pe "s/(?<=md\#function\-)(.*)(?=\))/\$$1=~s#-#_#gr/ge" build/pdf/group* build/pdf/*8h* - $(Q)perl -i -pe "s/\/group_.*\.md//g" build/pdf/group* build/pdf/*8h* + $(Q)perl -i -pe "s/\/group_.*?\.md//g" build/pdf/group* build/pdf/*8h* $(Q)perl -i -pe "s/\/(ssl|wolfio|cryptocb|types|hash)_8h.md//g" build/pdf/group* build/pdf/*8h* $(Q)perl -i -pe "s/^-(-)+$$//" build/pdf/group* build/pdf/*8h* $(Q)perl -i -pe "s/^title:.*//" build/pdf/group* build/pdf/*8h* @@ -102,9 +102,9 @@ pdf-prep: api $(Q)perl -i -pe "s/dox_comments\/$(HEADER_FILES)\///" build/pdf/*8h* $(Q)perl -i -pe "s/^\\\\//" build/pdf/group* build/pdf/*8h* $(Q)perl -i -pe "s/\\\\par/par/g" build/pdf/group* build/pdf/*8h* - $(Q)perl -i -pe "s/group__.*.md//g" build/pdf/*8h* build/pdf/chapter* + $(Q)perl -i -pe "s/group__.*?\.md//g" build/pdf/*8h* build/pdf/chapter* $(Q)perl -i -pe "s/(ssl|wolfio|cryptocb|types|hash)_8h.md//g" build/pdf/chapter* $(Q)cat build/pdf/group__CertManager.md build/pdf/group__Memory.md build/pdf/group__openSSL.md build/pdf/group__CertsKeys.md build/pdf/group__IO.md build/pdf/group__Setup.md build/pdf/group__Debug.md build/pdf/group__TLS.md >> build/pdf/appendix01.md - $(Q)cat build/pdf/group__ASN.md build/pdf/group__Base__Encoding.md build/pdf/group__Compression.md build/pdf/group__Error.md build/pdf/group__IoTSafe.md build/pdf/group__Logging.md build/pdf/group__Math.md build/pdf/group__Random.md build/pdf/group__Signature.md build/pdf/group__wolfCrypt.md build/pdf/group__DES.md build/pdf/group__AES.md build/pdf/group__ARC4.md build/pdf/group__BLAKE2.md build/pdf/group__Camellia.md build/pdf/group__ChaCha.md build/pdf/group__ChaCha20Poly1305.md build/pdf/group__CMAC.md build/pdf/group__Crypto.md build/pdf/group__Curve25519.md build/pdf/group__Curve448.md build/pdf/group__DSA.md build/pdf/group__Diffie-Hellman.md build/pdf/group__ECC.md build/pdf/group__ED25519.md build/pdf/group__ED448.md build/pdf/group__ECCSI__Overview.md build/pdf/group__ECCSI__Setup.md build/pdf/group__ECCSI__Operations.md build/pdf/group__SAKKE__Overview.md build/pdf/group__SAKKE__Setup.md build/pdf/group__SAKKE__RSK.md build/pdf/group__SAKKE__Operations.md build/pdf/group__HMAC.md build/pdf/group__LMS.md build/pdf/group__MD2.md build/pdf/group__MD4.md build/pdf/group__MD5.md build/pdf/group__ML__DSA.md build/pdf/group__ML__KEM.md build/pdf/group__Password.md build/pdf/group__PKCS7.md build/pdf/group__PKCS11.md build/pdf/group__Poly1305.md build/pdf/group__PSA.md build/pdf/group__PUF.md build/pdf/group__RIPEMD.md build/pdf/group__RSA.md build/pdf/group__SHA.md build/pdf/group__SHE.md build/pdf/group__SipHash.md build/pdf/group__SLH__DSA.md build/pdf/group__SrtpKdf.md build/pdf/group__SRP.md build/pdf/group__XMSS.md >> build/pdf/appendix02.md - $(Q)cat build/pdf/aes_8h.md build/pdf/arc4_8h.md build/pdf/ascon_8h.md build/pdf/asn_8h.md build/pdf/asn__public_8h.md build/pdf/blake2_8h.md build/pdf/bn_8h.md build/pdf/camellia_8h.md build/pdf/chacha20__poly1305_8h.md build/pdf/chacha_8h.md build/pdf/cmac_8h.md build/pdf/coding_8h.md build/pdf/compress_8h.md build/pdf/cryptocb_8h.md build/pdf/curve25519_8h.md build/pdf/curve448_8h.md build/pdf/des3_8h.md build/pdf/dh_8h.md build/pdf/doxygen__groups_8h.md build/pdf/doxygen__pages_8h.md build/pdf/dsa_8h.md build/pdf/ecc_8h.md build/pdf/eccsi_8h.md build/pdf/ed25519_8h.md build/pdf/ed448_8h.md build/pdf/error-crypt_8h.md build/pdf/evp_8h.md build/pdf/hash_8h.md build/pdf/hmac_8h.md build/pdf/iotsafe_8h.md build/pdf/kdf_8h.md build/pdf/logging_8h.md build/pdf/md2_8h.md build/pdf/md4_8h.md build/pdf/md5_8h.md build/pdf/memory_8h.md build/pdf/ocsp_8h.md build/pdf/pem_8h.md build/pdf/pkcs11_8h.md build/pdf/pkcs7_8h.md build/pdf/poly1305_8h.md build/pdf/psa_8h.md build/pdf/puf_8h.md build/pdf/pwdbased_8h.md build/pdf/quic_8h.md build/pdf/random_8h.md build/pdf/ripemd_8h.md build/pdf/rsa_8h.md build/pdf/sakke_8h.md build/pdf/sha256_8h.md build/pdf/sha3_8h.md build/pdf/sha512_8h.md build/pdf/sha_8h.md build/pdf/signature_8h.md build/pdf/siphash_8h.md build/pdf/srp_8h.md build/pdf/ssl_8h.md build/pdf/tfm_8h.md build/pdf/types_8h.md build/pdf/wc__encrypt_8h.md build/pdf/wc__lms_8h.md build/pdf/wc__mldsa_8h.md build/pdf/wc__mlkem_8h.md build/pdf/wc__port_8h.md build/pdf/wc__she_8h.md build/pdf/wc__slhdsa_8h.md build/pdf/wc__xmss_8h.md build/pdf/wolfio_8h.md >> build/pdf/appendix03.md + $(Q)cat build/pdf/group__ASN.md build/pdf/group__Base__Encoding.md build/pdf/group__Compression.md build/pdf/group__Error.md build/pdf/group__IoTSafe.md build/pdf/group__Logging.md build/pdf/group__Math.md build/pdf/group__Random.md build/pdf/group__Signature.md build/pdf/group__wolfCrypt.md build/pdf/group__DES.md build/pdf/group__AES.md build/pdf/group__ARC4.md build/pdf/group__BLAKE2.md build/pdf/group__Camellia.md build/pdf/group__ChaCha.md build/pdf/group__ChaCha20Poly1305.md build/pdf/group__CMAC.md build/pdf/group__Crypto.md build/pdf/group__Curve25519.md build/pdf/group__Curve448.md build/pdf/group__DSA.md build/pdf/group__Diffie-Hellman.md build/pdf/group__ECC.md build/pdf/group__ED25519.md build/pdf/group__ED448.md build/pdf/group__ECCSI__Overview.md build/pdf/group__ECCSI__Setup.md build/pdf/group__ECCSI__Operations.md build/pdf/group__SAKKE__Overview.md build/pdf/group__SAKKE__Setup.md build/pdf/group__SAKKE__RSK.md build/pdf/group__SAKKE__Operations.md build/pdf/group__HMAC.md build/pdf/group__LMS.md build/pdf/group__MD2.md build/pdf/group__MD4.md build/pdf/group__MD5.md build/pdf/group__ML__DSA.md build/pdf/group__ML__KEM.md build/pdf/group__Password.md build/pdf/group__PKCS7.md build/pdf/group__PKCS11.md build/pdf/group__PKCS12.md build/pdf/group__Poly1305.md build/pdf/group__PSA.md build/pdf/group__PUF.md build/pdf/group__RIPEMD.md build/pdf/group__RSA.md build/pdf/group__SHA.md build/pdf/group__SHE.md build/pdf/group__SipHash.md build/pdf/group__SLH__DSA.md build/pdf/group__SrtpKdf.md build/pdf/group__SRP.md build/pdf/group__XMSS.md >> build/pdf/appendix02.md + $(Q)cat build/pdf/aes_8h.md build/pdf/arc4_8h.md build/pdf/ascon_8h.md build/pdf/asn_8h.md build/pdf/asn__public_8h.md build/pdf/blake2_8h.md build/pdf/bn_8h.md build/pdf/camellia_8h.md build/pdf/chacha20__poly1305_8h.md build/pdf/chacha_8h.md build/pdf/cmac_8h.md build/pdf/coding_8h.md build/pdf/compress_8h.md build/pdf/cryptocb_8h.md build/pdf/curve25519_8h.md build/pdf/curve448_8h.md build/pdf/des3_8h.md build/pdf/dh_8h.md build/pdf/doxygen__groups_8h.md build/pdf/doxygen__pages_8h.md build/pdf/dsa_8h.md build/pdf/ecc_8h.md build/pdf/eccsi_8h.md build/pdf/ed25519_8h.md build/pdf/ed448_8h.md build/pdf/error-crypt_8h.md build/pdf/evp_8h.md build/pdf/hash_8h.md build/pdf/hmac_8h.md build/pdf/iotsafe_8h.md build/pdf/kdf_8h.md build/pdf/logging_8h.md build/pdf/md2_8h.md build/pdf/md4_8h.md build/pdf/md5_8h.md build/pdf/memory_8h.md build/pdf/ocsp_8h.md build/pdf/pem_8h.md build/pdf/pkcs11_8h.md build/pdf/pkcs12_8h.md build/pdf/pkcs7_8h.md build/pdf/poly1305_8h.md build/pdf/psa_8h.md build/pdf/puf_8h.md build/pdf/pwdbased_8h.md build/pdf/quic_8h.md build/pdf/random_8h.md build/pdf/ripemd_8h.md build/pdf/rsa_8h.md build/pdf/sakke_8h.md build/pdf/sha256_8h.md build/pdf/sha3_8h.md build/pdf/sha512_8h.md build/pdf/sha_8h.md build/pdf/signature_8h.md build/pdf/siphash_8h.md build/pdf/srp_8h.md build/pdf/ssl_8h.md build/pdf/tfm_8h.md build/pdf/types_8h.md build/pdf/wc__encrypt_8h.md build/pdf/wc__lms_8h.md build/pdf/wc__mldsa_8h.md build/pdf/wc__mlkem_8h.md build/pdf/wc__port_8h.md build/pdf/wc__she_8h.md build/pdf/wc__slhdsa_8h.md build/pdf/wc__xmss_8h.md build/pdf/wolfio_8h.md >> build/pdf/appendix03.md diff --git a/wolfSSL/mkdocs-ja.yml b/wolfSSL/mkdocs-ja.yml index 1216d42f..637492bb 100644 --- a/wolfSSL/mkdocs-ja.yml +++ b/wolfSSL/mkdocs-ja.yml @@ -72,6 +72,7 @@ nav: - "暗号アルゴリズム - Password Based": group__Password.md - "暗号アルゴリズム - PKCS7": group__PKCS7.md - "暗号アルゴリズム - PKCS11": group__PKCS11.md + - "暗号アルゴリズム - PKCS12": group__PKCS12.md - "暗号アルゴリズム - Poly1305": group__Poly1305.md - "暗号アルゴリズム - PSA": group__PSA.md - "暗号アルゴリズム - RIPEMD": group__RIPEMD.md @@ -120,6 +121,7 @@ nav: - ocsp_8h.md - pem_8h.md - pkcs11_8h.md + - pkcs12_8h.md - pkcs7_8h.md - poly1305_8h.md - psa_8h.md diff --git a/wolfSSL/mkdocs.yml b/wolfSSL/mkdocs.yml index 8765fec9..139f92c8 100644 --- a/wolfSSL/mkdocs.yml +++ b/wolfSSL/mkdocs.yml @@ -79,6 +79,7 @@ nav: - "Algorithms - Password Based": group__Password.md - "Algorithms - PKCS7": group__PKCS7.md - "Algorithms - PKCS11": group__PKCS11.md + - "Algorithms - PKCS12": group__PKCS12.md - "Algorithms - Poly1305": group__Poly1305.md - "Algorithms - PSA": group__PSA.md - "Algorithms - PUF": group__PUF.md @@ -131,6 +132,7 @@ nav: - ocsp_8h.md - pem_8h.md - pkcs11_8h.md + - pkcs12_8h.md - pkcs7_8h.md - poly1305_8h.md - psa_8h.md diff --git a/wolfSSL/src-ja/chapter04.md b/wolfSSL/src-ja/chapter04.md index dfea8f69..8e55cac5 100644 --- a/wolfSSL/src-ja/chapter04.md +++ b/wolfSSL/src-ja/chapter04.md @@ -531,6 +531,128 @@ autoconfで行う場合は、 `./configure --enable-pkcs7 CFLAGS=-DNO_PKCS7_STRE **注意**:[`wc_PKCS7_VerifySignedData_ex`](group__PKCS7.md#function-wc_pkcs7_verifysigneddata_ex) を呼び出す場合、引数`pkiMsgFoot`は完全なバッファであることが想定されています。 内部構造は1つのバッファのストリーミングのみをサポートしており、この場合は`pkiMsgHead`になります。 +#### PKCS #12 + +PKCS #12はPFXバンドル形式を定義しています。 +これは、秘密鍵とその証明書、および任意でCAチェーンをまとめて格納する、パスワードで保護された単一のファイルです。 +OpenSSL、Javaのkeytool、WindowsのCertificate Exportなどが出力する`.p12`ファイルや`.pfx`ファイルはこの形式です。 +wolfSSLは[RFC 7292](https://www.rfc-editor.org/rfc/rfc7292)に記述された形式を実装しています。 + +PKCS #12のサポートは、configureオプション`--enable-pkcs12`を使用するか、マクロ`HAVE_PKCS12`を定義することで有効になります。 +パスワードベースの鍵導出に依存しているため、[`--enable-pwdbased`](chapter02.md#--enable-pwdbased)も必要です。 +どちらも通常のビルドではデフォルトで有効であり、[`--disable-pkcs12`](chapter02.md#--disable-pkcs12)で無効にできます。 +古いバンドルはRC2やシングルDESで暗号化されていることが多いため、旧来のツールが生成したファイルを読み込むには`--enable-rc2`や`--enable-des3`が追加で必要になる場合があります。 + +wolfCryptのAPIは``で宣言されており、不透明な`WC_PKCS12`構造体を操作します。 +各関数の詳細は[PKCS12 APIリファレンス](group__PKCS12.md)をご参照ください。 + +##### PKCS #12 バンドルの読み込み + +バンドルの読み込みは3つの手順で行います。 +`WC_PKCS12`構造体を割り当て、DERをその構造体にデコードし、MACを検証して内容を復号します。 + +```c +WC_PKCS12* pkcs12 = NULL; +byte* key = NULL; +byte* cert = NULL; +WC_DerCertList* ca = NULL; +word32 keySz = 0; +word32 certSz = 0; + +/* *pkcs12がNULLの場合、wc_d2i_PKCS12_fpがWC_PKCS12を割り当てます */ +if (wc_d2i_PKCS12_fp("./certs/test-servercert.p12", &pkcs12) != 0) { + /* ファイルの読み込みまたはデコードのエラー */ +} + +if (wc_PKCS12_parse(pkcs12, "password", &key, &keySz, &cert, &certSz, + &ca) != 0) { + /* バンドルの解析エラー。パスワード誤りが最も多い原因です */ +} + +/* ここでDER形式の鍵、証明書、CAチェーンを使用します。 + * 例えばwolfSSL_CTX_use_certificate_buffer()や + * wolfSSL_CTX_use_PrivateKey_buffer()に渡します */ + +XFREE(key, NULL, DYNAMIC_TYPE_PUBLIC_KEY); +XFREE(cert, NULL, DYNAMIC_TYPE_PKCS); +wc_FreeCertList(ca, NULL); +wc_PKCS12_free(pkcs12); +``` + +バンドルがファイルではなくメモリ上にある場合は、[`wc_PKCS12_new()`](group__PKCS12.md#function-wc_pkcs12_new)または[`wc_PKCS12_new_ex()`](group__PKCS12.md#function-wc_pkcs12_new_ex)で取得した`WC_PKCS12`と共に[`wc_d2i_PKCS12()`](group__PKCS12.md#function-wc_d2i_pkcs12)を使用します。 +`_ex`版はヒープヒントを受け取り、そのヒントは構造体に保存されて、その構造体のために行われるすべての割り当てに使用されます。 + +[`wc_PKCS12_parse()`](group__PKCS12.md#function-wc_pkcs12_parse)は秘密鍵と証明書を新たに割り当てたDERバッファで返し、呼び出し元が3つの結果すべての所有権を持ちます。 +鍵と証明書で解放時の動的タイプが異なること、およびCAリストには専用の解放関数があることにご注意ください。 + +| 出力 | 解放方法 | +| ---- | -------- | +| `pkey` | `XFREE(pkey, heap, DYNAMIC_TYPE_PUBLIC_KEY)` | +| `cert` | `XFREE(cert, heap, DYNAMIC_TYPE_PKCS)` | +| `ca` | [`wc_FreeCertList(ca, heap)`](group__PKCS12.md#function-wc_freecertlist) | + +上記の`heap`は`wc_PKCS12_new_ex()`に渡したヒープヒントと同じものです。 +`wc_PKCS12_new()`を使用した場合は`NULL`になります。 +`ca`引数は任意であり、追加の証明書が不要な場合は`NULL`を渡してください。 + +デフォルトでは、返される秘密鍵からPKCS #8ヘッダーが取り除かれます。 +ヘッダーを残したい場合は、[`wc_PKCS12_parse_ex()`](group__PKCS12.md#function-wc_pkcs12_parse_ex)を`keepKeyHeader`に0以外の値を指定して呼び出してください。 +それ以外の動作は`wc_PKCS12_parse()`と同じです。 + +##### PKCS #12 バンドルの作成 + +[`wc_PKCS12_create()`](group__PKCS12.md#function-wc_pkcs12_create)は、DER形式の秘密鍵、DER形式の証明書、および任意の追加証明書の`WC_DerCertList`からバンドルを構築します。 +作成された構造体は[`wc_i2d_PKCS12()`](group__PKCS12.md#function-wc_i2d_pkcs12)でシリアライズします。 + +```c +WC_PKCS12* pkcs12 = NULL; +byte* der = NULL; +int derSz = 0; +char pass[] = "password"; + +pkcs12 = wc_PKCS12_create(pass, sizeof(pass) - 1, NULL, + key, keySz, cert, certSz, ca, + PBE_AES256_CBC, /* 鍵の暗号化 */ + PBE_AES256_CBC, /* 証明書の暗号化 */ + WC_PKCS12_ITT_DEFAULT, /* 暗号化の反復回数 */ + WC_PKCS12_ITT_DEFAULT, /* MACの反復回数 */ + 0, NULL); +if (pkcs12 == NULL) { + /* バンドルの作成エラー */ +} + +/* *derにNULLを渡すと、wc_i2d_PKCS12がバッファを割り当てます */ +if ((derSz = wc_i2d_PKCS12(pkcs12, &der, NULL)) <= 0) { + /* バンドルのエンコードエラー */ +} + +/* ここでder/derSzを.p12ファイルに書き出します */ + +XFREE(der, NULL, DYNAMIC_TYPE_PKCS); +wc_PKCS12_free(pkcs12); +``` + +`nidKey`引数と`nidCert`引数は、秘密鍵と証明書に適用するパスワードベース暗号化を選択します。 +指定できる値は`PBE_SHA1_RC4_128`、`PBE_SHA1_DES`、`PBE_SHA1_DES3`、`PBE_AES128_CBC`、`PBE_AES256_CBC`です。 +`-1`を渡すと、そのパートは暗号化されずに格納されます。 +新規に作成するバンドルには`PBE_AES256_CBC`を推奨します。 +SHA-1ベースのオプションは、古いソフトウェアとの相互運用が必要な場合にのみ使用してください。 +`iter`が0以下の場合は`WC_PKCS12_ITT_DEFAULT`(2048)回の反復が使用されます。 + +`name`(friendlyName)引数と`keyType`引数はAPIの互換性のために受け付けられますが、現在は使用されていません。 + +`wc_i2d_PKCS12()`には、`der`引数と`derSz`引数によって選択される3つのモードがあります。 + +* `der`に`NULL`を渡すと、必要なサイズの計算のみを行います。必要な長さが`*derSz`に格納され、`LENGTH_ONLY_E`が返されます。 +* `*der`が`NULL`である`der`を渡すと、必要なサイズのバッファを割り当て、そのアドレスを`*der`に格納します。呼び出し元は`XFREE(*der, NULL, DYNAMIC_TYPE_PKCS)`で解放します。 +* `*der`が呼び出し元の用意したバッファを指している`der`を渡すと、そのバッファに書き込みます。`derSz`がバッファ不足を示している場合は`BUFFER_E`を返します。通常の`i2d`の慣例に従い、成功時には`*der`がエンコードされたDERの末尾の次のバイトへ進められるため、元のポインタは別途保持しておいてください。 + +##### OpenSSL互換レイヤー + +互換レイヤーが有効な場合、``から使い慣れたOpenSSL形式の名前も使用できます。 +`d2i_PKCS12_bio()`、`PKCS12_parse()`、`PKCS12_verify_mac()`、`PKCS12_create()`が該当します。 +これらは[`wolfSSL_d2i_PKCS12_bio()`](group__openSSL.md)や`wolfSSL_PKCS12_parse()`などに対応しており、上記のwolfCrypt関数をラップして、DERバッファの代わりに`WOLFSSL_X509`オブジェクトや`WOLFSSL_EVP_PKEY`オブジェクトを返します。 + ### 特定の暗号スイートの使用を強制する デフォルトでは、wolfSSLは接続の両側がサポートしている最良の暗号スイートを選択します。 diff --git a/wolfSSL/src-ja/chapter07.md b/wolfSSL/src-ja/chapter07.md index a80a61cb..63240b6c 100644 --- a/wolfSSL/src-ja/chapter07.md +++ b/wolfSSL/src-ja/chapter07.md @@ -19,6 +19,10 @@ DERフォーマットはASN.1エンコーディングです。 PEMフォーマットはBase64エンコードされ、人間が読めるヘッダーとフッターで囲まれています。 TLSは証明書をDERフォーマットで送信します。 +**PKCS #12**(PFXとも呼ばれます)は、秘密鍵とその証明書、CAチェーンを単一のファイルにまとめた、パスワードで保護されたバンドルです。 +通常は`.p12`または`.pfx`の拡張子を持ちます。 +wolfSSLはwolfCryptのPKCS #12 APIを通じてこれらのバンドルの読み書きができます。詳細は[PKCS #12](chapter04.md#pkcs-12)をご参照ください。 + ## サポートしている証明書拡張 サポートしていない、または未知の拡張機能がクリティカルとしてマークされている場合、エラーメッセージを出力します。 diff --git a/wolfSSL/src/chapter04.md b/wolfSSL/src/chapter04.md index 0a25073e..1a84438f 100644 --- a/wolfSSL/src/chapter04.md +++ b/wolfSSL/src/chapter04.md @@ -415,6 +415,106 @@ For streaming when decoding/verifying bundles the following functions are suppor **Note**: that when calling [`wc_PKCS7_VerifySignedData_ex`](group__PKCS7.md#function-wc_pkcs7_verifysigneddata_ex) it is expected that the argument pkiMsgFoot is the full buffer. The internal structure only supports streaming of one buffer, which in this case would be `pkiMsgHead`. +#### PKCS #12 + +PKCS #12 defines the PFX bundle format: a single, password-protected file that carries a private key together with its certificate and, optionally, the rest of the CA chain. It is the format behind the `.p12` and `.pfx` files commonly produced by OpenSSL, Java keytool, and Windows certificate export. wolfSSL implements the format as described in [RFC 7292](https://www.rfc-editor.org/rfc/rfc7292). + +PKCS #12 support is enabled by using the configure option `--enable-pkcs12` or by defining the macro [`HAVE_PKCS12`](chapter02.md#have_pkcs12). It relies on password-based key derivation, so [`--enable-pwdbased`](chapter02.md#--enable-pwdbased) is required as well; both are on by default in a normal build and can be turned off with [`--disable-pkcs12`](chapter02.md#--disable-pkcs12). Older bundles are frequently encrypted with RC2 or single DES, so reading files produced by legacy tools may additionally require `--enable-rc2` or `--enable-des3`. + +The wolfCrypt API is declared in `` and operates on an opaque `WC_PKCS12` structure. All of the functions are documented in the [PKCS12 API Reference](group__PKCS12.md). + +##### Reading a PKCS #12 Bundle + +Reading a bundle is a three step process: allocate a `WC_PKCS12` structure, decode the DER into it, then verify the MAC and decrypt the contents. + +```c +WC_PKCS12* pkcs12 = NULL; +byte* key = NULL; +byte* cert = NULL; +WC_DerCertList* ca = NULL; +word32 keySz = 0; +word32 certSz = 0; + +/* wc_d2i_PKCS12_fp allocates the WC_PKCS12 when *pkcs12 is NULL */ +if (wc_d2i_PKCS12_fp("./certs/test-servercert.p12", &pkcs12) != 0) { + /* error reading or decoding the file */ +} + +if (wc_PKCS12_parse(pkcs12, "password", &key, &keySz, &cert, &certSz, + &ca) != 0) { + /* error parsing the bundle, most commonly a wrong password */ +} + +/* use the DER key, cert, and ca chain here, for example with + * wolfSSL_CTX_use_certificate_buffer() and + * wolfSSL_CTX_use_PrivateKey_buffer() */ + +XFREE(key, NULL, DYNAMIC_TYPE_PUBLIC_KEY); +XFREE(cert, NULL, DYNAMIC_TYPE_PKCS); +wc_FreeCertList(ca, NULL); +wc_PKCS12_free(pkcs12); +``` + +If the bundle is already in memory rather than on disk, use [`wc_d2i_PKCS12()`](group__PKCS12.md#function-wc_d2i_pkcs12) with a `WC_PKCS12` obtained from [`wc_PKCS12_new()`](group__PKCS12.md#function-wc_pkcs12_new) or [`wc_PKCS12_new_ex()`](group__PKCS12.md#function-wc_pkcs12_new_ex). The `_ex` variant takes a heap hint, which is stored in the structure and used for every allocation made on its behalf. + +[`wc_PKCS12_parse()`](group__PKCS12.md#function-wc_pkcs12_parse) returns the private key and the certificate in newly allocated DER buffers, and the caller owns all three results. Note that the key and the certificate are freed with different dynamic types, and that the CA list has its own free function: + +| Output | How to free | +| ------ | ----------- | +| `pkey` | `XFREE(pkey, heap, DYNAMIC_TYPE_PUBLIC_KEY)` | +| `cert` | `XFREE(cert, heap, DYNAMIC_TYPE_PKCS)` | +| `ca` | [`wc_FreeCertList(ca, heap)`](group__PKCS12.md#function-wc_freecertlist) | + +The `heap` above is the same heap hint that was passed to `wc_PKCS12_new_ex()`, or `NULL` when `wc_PKCS12_new()` was used. The `ca` argument is optional; pass `NULL` if the extra certificates are not needed. + +By default the PKCS #8 header is stripped from the returned private key. To keep it, call [`wc_PKCS12_parse_ex()`](group__PKCS12.md#function-wc_pkcs12_parse_ex) with a non-zero `keepKeyHeader` argument; it is otherwise identical to `wc_PKCS12_parse()`. + +##### Creating a PKCS #12 Bundle + +[`wc_PKCS12_create()`](group__PKCS12.md#function-wc_pkcs12_create) builds a bundle from a DER private key, a DER certificate, and an optional `WC_DerCertList` of additional certificates. The resulting structure is then serialized with [`wc_i2d_PKCS12()`](group__PKCS12.md#function-wc_i2d_pkcs12). + +```c +WC_PKCS12* pkcs12 = NULL; +byte* der = NULL; +int derSz = 0; +char pass[] = "password"; + +pkcs12 = wc_PKCS12_create(pass, sizeof(pass) - 1, NULL, + key, keySz, cert, certSz, ca, + PBE_AES256_CBC, /* key encryption */ + PBE_AES256_CBC, /* cert encryption */ + WC_PKCS12_ITT_DEFAULT, /* encryption iterations */ + WC_PKCS12_ITT_DEFAULT, /* MAC iterations */ + 0, NULL); +if (pkcs12 == NULL) { + /* error creating the bundle */ +} + +/* passing a NULL *der asks wc_i2d_PKCS12 to allocate the buffer */ +if ((derSz = wc_i2d_PKCS12(pkcs12, &der, NULL)) <= 0) { + /* error encoding the bundle */ +} + +/* write der/derSz out to a .p12 file here */ + +XFREE(der, NULL, DYNAMIC_TYPE_PKCS); +wc_PKCS12_free(pkcs12); +``` + +The `nidKey` and `nidCert` arguments choose the password-based encryption applied to the private key and to the certificate. The supported values are `PBE_SHA1_RC4_128`, `PBE_SHA1_DES`, `PBE_SHA1_DES3`, `PBE_AES128_CBC`, and `PBE_AES256_CBC`; passing `-1` stores that part of the bundle unencrypted. `PBE_AES256_CBC` is recommended for new bundles, with the SHA-1 based options reserved for interoperability with older software. When `iter` is zero or negative, `WC_PKCS12_ITT_DEFAULT` (2048) iterations are used. + +The `name` (friendlyName) and `keyType` arguments are accepted for API compatibility but are not currently used. + +`wc_i2d_PKCS12()` has three modes, selected by its `der` and `derSz` arguments: + +* Passing `NULL` for `der` only computes the size. The required length is stored in `*derSz` and `LENGTH_ONLY_E` is returned. +* Passing a `der` whose `*der` is `NULL` allocates a buffer of the right size and stores its address in `*der`. The caller frees it with `XFREE(*der, NULL, DYNAMIC_TYPE_PKCS)`. +* Passing a `der` whose `*der` points to a caller-supplied buffer writes into that buffer, returning `BUFFER_E` if `derSz` indicates it is too small. Following the usual `i2d` convention, `*der` is advanced to one byte past the encoded DER on success, so keep a separate copy of the original pointer. + +##### OpenSSL Compatibility Layer + +When the compatibility layer is enabled, the familiar OpenSSL spellings are also available from ``: `d2i_PKCS12_bio()`, `PKCS12_parse()`, `PKCS12_verify_mac()`, and `PKCS12_create()`. These map onto [`wolfSSL_d2i_PKCS12_bio()`](group__openSSL.md), `wolfSSL_PKCS12_parse()`, and friends, which wrap the wolfCrypt functions described above and return `WOLFSSL_X509` and `WOLFSSL_EVP_PKEY` objects instead of DER buffers. + ### Forcing the Use of a Specific Cipher By default, wolfSSL will pick the “best” (highest security) cipher suite that both sides of the connection can support. To force a specific cipher, such as 128 bit AES, add something similar to: diff --git a/wolfSSL/src/chapter07.md b/wolfSSL/src/chapter07.md index b592d983..69f39564 100644 --- a/wolfSSL/src/chapter07.md +++ b/wolfSSL/src/chapter07.md @@ -12,6 +12,8 @@ wolfSSL (formerly CyaSSL) has support for **PEM**, and **DER** formats for certi An X.509 certificate is encoded using ASN.1 format. The DER format is the ASN.1 encoding. The PEM format is Base64 encoded and wrapped with a human readable header and footer. TLS sends certificates in DER format. +**PKCS #12**, also called PFX, is a password-protected bundle that carries a private key together with its certificate and CA chain in a single file, usually with a `.p12` or `.pfx` extension. wolfSSL can read and write these bundles through the wolfCrypt PKCS #12 API; see [PKCS #12](chapter04.md#pkcs-12) for details. + ## Supported Certificate Extensions