From 38cba335e92b7d528fa4df5eee674c7343bbd581 Mon Sep 17 00:00:00 2001 From: Sam Clark <3758302+goatgoose@users.noreply.github.com> Date: Thu, 19 Sep 2024 16:09:57 -0400 Subject: [PATCH 1/3] docs: Update certificate loading documentation --- api/s2n.h | 28 ++++++++++++++++---- docs/usage-guide/topics/ch09-certificates.md | 20 +++++++++++++- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/api/s2n.h b/api/s2n.h index 6a627aa6951..97982eb43c7 100644 --- a/api/s2n.h +++ b/api/s2n.h @@ -801,13 +801,13 @@ S2N_API extern int s2n_config_add_cert_chain_and_key(struct s2n_config *config, /** * The preferred method of associating a certificate chain and private key pair with an `s2n_config` object. - * This method may be called multiple times to support multiple key types(RSA, ECDSA) and multiple domains. - * On the server side, the certificate selected will be based on the incoming SNI value and the - * client's capabilities(supported ciphers). + * This method may be called multiple times to support multiple key types (RSA, RSA-PSS, ECDSA) and multiple + * domains. On the server side, the certificate selected will be based on the incoming SNI value and the + * client's capabilities (supported ciphers). * * In the case of no certificate matching the client's SNI extension or if no SNI extension was sent by - * the client, the certificate from the `first` call to `s2n_config_add_cert_chain_and_key_to_store` - * will be selected. + * the client, the certificate from the `first` call to `s2n_config_add_cert_chain_and_key_to_store()` + * will be selected. Use `s2n_config_set_cert_chain_and_key_defaults()` to set different defaults. * * @warning It is not recommended to free or modify the `cert_key_pair` as any subsequent changes will be * reflected in the config. @@ -849,6 +849,16 @@ S2N_API extern int s2n_config_set_cert_chain_and_key_defaults(struct s2n_config * * @note The trust store will be initialized with the common locations for the host * operating system by default. + * + * @warning This API will use the PEM parsing implementation from the linked libcrypto. This + * implementation will typically make a best-effort attempt to parse all of the certificates in the + * provided file or directory. This permissive approach may silently ignore malformed certificates, + * leading to possible connection failures if a certificate was expected to exist in the trust + * store but was skipped while parsing. As such, this API should only be used on PEMs that are + * known to be well-formed and parsable with the linked libcrypto, such as the system trust store. + * For all other PEMs, `s2n_config_add_pem_to_trust_store()` should be used instead, which parses + * more strictly. + * * @param config The configuration object being updated * @param ca_pem_filename A string for the file path of the CA PEM file. * @param ca_dir A string for the directory of the CA PEM files. @@ -863,6 +873,14 @@ S2N_API extern int s2n_config_set_verification_ca_location(struct s2n_config *co * system certificates. To completely override these certificates, call * `s2n_config_wipe_trust_store()` before calling this function. * + * @note This API will use the s2n-tls PEM parsing implementation, which is more strict than + * typical libcrypto implementations such as OpenSSL. If any unexpected data is encountered while + * parsing `pem`, an error will be returned. This allows applications to be made aware of any + * malformed certificates rather than attempting to negotiate with a partial trust store. However, + * some PEMs may need to be loaded that are not under the control of the application, such as + * system trust stores. In this case, `s2n_config_set_verification_ca_location()` may be used, + * which performs more widely compatible and permissive parsing from the linked libcrypto. + * * @param config The configuration object being updated * @param pem The string value of the PEM certificate. * @returns S2N_SUCCESS on success. S2N_FAILURE on failure diff --git a/docs/usage-guide/topics/ch09-certificates.md b/docs/usage-guide/topics/ch09-certificates.md index 2c81640d8fc..a4329e592b5 100644 --- a/docs/usage-guide/topics/ch09-certificates.md +++ b/docs/usage-guide/topics/ch09-certificates.md @@ -29,12 +29,30 @@ default system certificates to these configs, call `s2n_config_load_system_certs ## Server Authentication -A server must have a certificate and private key pair to prove its identity. s2n-tls supports RSA, RSA-PSS, and ECDSA certificates, and allows one of each type to be added to a config. +A server must have a certificate and private key pair to prove its identity. s2n-tls supports RSA, RSA-PSS, and ECDSA certificates, and allows one of each type to be added to a config for a given domain name. Create a new certificate and key pair by calling `s2n_cert_chain_and_key_new()`, then load the pem-encoded data with `s2n_cert_chain_and_key_load_pem_bytes()`. Call `s2n_config_add_cert_chain_and_key_to_store()` to add the certificate and key pair to the config. When a certificate and key pair is no longer needed, it must be cleaned up with `s2n_cert_chain_and_key_free()`. A client can add restrictions on the certificate’s hostname by setting a custom `s2n_verify_host_fn` with `s2n_config_set_verify_host_callback()` or `s2n_connection_set_verify_host_callback()`. The default behavior is to require that the hostname match the server name set with `s2n_set_server_name()`. +### SNI + +TLS servers will often serve multiple domains from a single IP address, with each domain potentially requiring its own certificate. When a TLS client receives a server's certificate, it will check to ensure that it was issued for the domain that it's connecting to. As such, the server needs to know which domain the client is connecting to in order to send the correct certificate. This information is communicated to the server via the Server Name Indication (SNI) extension. + +#### Client configuration + +`s2n_set_server_name()` is used on client connections to specify a domain name in the SNI extension. + +#### Server configuration + +Certificates loaded with `s2n_config_add_cert_chain_and_key_to_store()` are automatically associated with each domain indicated in the certificate's Subject Alternative Name (SAN) field. If a loaded certificate doesn't contain a SAN field, the Common Name (CN) field is used instead. While negotiating a TLS connection, s2n-tls servers will automatically send clients a loaded certificate that matches the value of the client's SNI extension. + +s2n-tls allows servers to load a maximum of 1 certificate chain per domain, per certificate type (RSA, RSA-PSS, and ECDSA). If a certificate is loaded that specifies a domain that has already been associated with an existing certificate, the existing certificate will remain associated with the overlapping domain. The `s2n_cert_tiebreak_callback` can be used to customize this behavior. + +When selecting a certificate to send to the client, s2n-tls servers will prefer an exact SNI match before falling back to a certificate with an associated wildcard domain (a domain starting with "*.", covering all subdomains). + +If no exact match or wildcard match exists, or if the client doesn't send an SNI extension, a default certificate is sent to the client. A default certificate is set when `s2n_config_add_cert_chain_and_key_to_store()` is called for the first time for a given certificate type (RSA, RSA-PSS, or ECDSA). `s2n_config_set_cert_chain_and_key_defaults()` can be used to override the default certificates. + ## Client / Mutual Authentication Client authentication is not enabled by default. However, the server can require that the client also provide a certificate, if the server needs to authenticate clients before accepting connections. From b95ba921967d02e6f92b2b37407c917172a924b9 Mon Sep 17 00:00:00 2001 From: Sam Clark <3758302+goatgoose@users.noreply.github.com> Date: Tue, 24 Sep 2024 13:35:50 -0400 Subject: [PATCH 2/3] pr feedback --- api/s2n.h | 16 ++++++++-------- docs/usage-guide/topics/ch09-certificates.md | 8 +++----- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/api/s2n.h b/api/s2n.h index 97982eb43c7..0ba344885aa 100644 --- a/api/s2n.h +++ b/api/s2n.h @@ -850,7 +850,7 @@ S2N_API extern int s2n_config_set_cert_chain_and_key_defaults(struct s2n_config * @note The trust store will be initialized with the common locations for the host * operating system by default. * - * @warning This API will use the PEM parsing implementation from the linked libcrypto. This + * @warning This API uses the PEM parsing implementation from the linked libcrypto. This * implementation will typically make a best-effort attempt to parse all of the certificates in the * provided file or directory. This permissive approach may silently ignore malformed certificates, * leading to possible connection failures if a certificate was expected to exist in the trust @@ -873,13 +873,13 @@ S2N_API extern int s2n_config_set_verification_ca_location(struct s2n_config *co * system certificates. To completely override these certificates, call * `s2n_config_wipe_trust_store()` before calling this function. * - * @note This API will use the s2n-tls PEM parsing implementation, which is more strict than - * typical libcrypto implementations such as OpenSSL. If any unexpected data is encountered while - * parsing `pem`, an error will be returned. This allows applications to be made aware of any - * malformed certificates rather than attempting to negotiate with a partial trust store. However, - * some PEMs may need to be loaded that are not under the control of the application, such as - * system trust stores. In this case, `s2n_config_set_verification_ca_location()` may be used, - * which performs more widely compatible and permissive parsing from the linked libcrypto. + * @note This API uses the s2n-tls PEM parsing implementation, which is more strict than typical + * libcrypto implementations such as OpenSSL. An error is returned if any unexpected data is + * encountered while parsing `pem`. This allows applications to be made aware of any malformed + * certificates rather than attempt to negotiate with a partial trust store. However, some PEMs may + * need to be loaded that are not under control of the application, such as system trust stores. In + * this case, `s2n_config_set_verification_ca_location()` may be used, which performs more widely + * compatible and permissive parsing from the linked libcrypto. * * @param config The configuration object being updated * @param pem The string value of the PEM certificate. diff --git a/docs/usage-guide/topics/ch09-certificates.md b/docs/usage-guide/topics/ch09-certificates.md index a4329e592b5..5331d1f3439 100644 --- a/docs/usage-guide/topics/ch09-certificates.md +++ b/docs/usage-guide/topics/ch09-certificates.md @@ -45,13 +45,11 @@ TLS servers will often serve multiple domains from a single IP address, with eac #### Server configuration -Certificates loaded with `s2n_config_add_cert_chain_and_key_to_store()` are automatically associated with each domain indicated in the certificate's Subject Alternative Name (SAN) field. If a loaded certificate doesn't contain a SAN field, the Common Name (CN) field is used instead. While negotiating a TLS connection, s2n-tls servers will automatically send clients a loaded certificate that matches the value of the client's SNI extension. +Each certificate loaded with `s2n_config_add_cert_chain_and_key_to_store()` is automatically associated with every domain name listed in its Subject Alternative Name (SAN) field. The domain names listed in the Common Name (CN) field are used instead if the certificate doesn't contain an SAN field. s2n-tls servers automatically send a certificate that matches the value of the client's SNI extension during the TLS handshake. -s2n-tls allows servers to load a maximum of 1 certificate chain per domain, per certificate type (RSA, RSA-PSS, and ECDSA). If a certificate is loaded that specifies a domain that has already been associated with an existing certificate, the existing certificate will remain associated with the overlapping domain. The `s2n_cert_tiebreak_callback` can be used to customize this behavior. +s2n-tls servers allow a maximum of 1 certificate to be loaded per domain, per certificate type (RSA, RSA-PSS, ECDSA). By default, a newly loaded certificate with an overlapping domain name will not replace the existing certificate associated with that domain. The `s2n_cert_tiebreak_callback` may be implemented to customize which certificate is selected when an overlapping domain is encountered. -When selecting a certificate to send to the client, s2n-tls servers will prefer an exact SNI match before falling back to a certificate with an associated wildcard domain (a domain starting with "*.", covering all subdomains). - -If no exact match or wildcard match exists, or if the client doesn't send an SNI extension, a default certificate is sent to the client. A default certificate is set when `s2n_config_add_cert_chain_and_key_to_store()` is called for the first time for a given certificate type (RSA, RSA-PSS, or ECDSA). `s2n_config_set_cert_chain_and_key_defaults()` can be used to override the default certificates. +When selecting a certificate to send to the client, s2n-tls servers prefer an exact SNI match before falling back to a certificate with an associated wildcard domain (a domain starting with "*.", covering all subdomains). A default certificate is selected if no SNI match exists, or if the client doesn't send an SNI extension. A default certificate is set when `s2n_config_add_cert_chain_and_key_to_store()` is called for the first time for a given certificate type (RSA, RSA-PSS, ECDSA). `s2n_config_set_cert_chain_and_key_defaults()` may be used to override the default certificates. ## Client / Mutual Authentication From 945b75b1f81f4d02a5019b65dc4036133462cf1f Mon Sep 17 00:00:00 2001 From: Sam Clark <3758302+goatgoose@users.noreply.github.com> Date: Thu, 26 Sep 2024 10:22:42 -0400 Subject: [PATCH 3/3] Update docs/usage-guide/topics/ch09-certificates.md Co-authored-by: Lindsay Stewart --- docs/usage-guide/topics/ch09-certificates.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage-guide/topics/ch09-certificates.md b/docs/usage-guide/topics/ch09-certificates.md index 5331d1f3439..d4281656f6f 100644 --- a/docs/usage-guide/topics/ch09-certificates.md +++ b/docs/usage-guide/topics/ch09-certificates.md @@ -37,7 +37,7 @@ A client can add restrictions on the certificate’s hostname by setting a custo ### SNI -TLS servers will often serve multiple domains from a single IP address, with each domain potentially requiring its own certificate. When a TLS client receives a server's certificate, it will check to ensure that it was issued for the domain that it's connecting to. As such, the server needs to know which domain the client is connecting to in order to send the correct certificate. This information is communicated to the server via the Server Name Indication (SNI) extension. +TLS servers will often serve multiple domains from a single IP address, with each domain potentially requiring its own certificate. When a TLS client receives a server's certificate, it will check to ensure that it was issued for the domain that the client is connecting to. As such, the server needs to know which domain the client is connecting to in order to send the correct certificate. This information is communicated to the server via the Server Name Indication (SNI) extension. #### Client configuration