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.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/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