aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNever <[email protected]>2018-03-23 20:09:56 +0100
committerNever <[email protected]>2018-03-27 19:14:48 +0200
commit899f108970483f8741073c3a7c48bfb71e5c9b27 (patch)
treeb412f112681f0fd1611f9005de2ac8456324e089
parentb85bab68f917339e406ba64fe3468d681699bca8 (diff)
add tls-custom-curve documentation + examples
-rw-r--r--doc/manual/tls.rst400
1 files changed, 394 insertions, 6 deletions
diff --git a/doc/manual/tls.rst b/doc/manual/tls.rst
index a41245448..e83fdcb24 100644
--- a/doc/manual/tls.rst
+++ b/doc/manual/tls.rst
@@ -149,6 +149,16 @@ information about the connection.
Optional logging for an debug value. (Not currently used)
+ .. cpp:function:: std::string tls_decode_group_param(TLS::Group_Params group_param)
+
+ Optional. Called by the server when a client hello includes a list of supported groups in the
+ supported_groups extension and by the client when decoding the server key exchange including the selected curve identifier.
+ The function should return the name of the DH group or elliptic curve the passed
+ TLS group identifier should be mapped to. Therefore this callback enables the use of custom
+ elliptic curves or DH groups in TLS, if both client and server map the custom identifiers correctly.
+ Please note that it is required to allow the group TLS identifier in
+ in the used :cpp:class:`TLS::Policy`.
+
Versions from 1.11.0 to 1.11.30 did not have ``TLS::Callbacks`` and instead
used independent std::functions to pass the various callback functions.
This interface is currently still included but is deprecated and will be removed
@@ -900,13 +910,18 @@ policy settings from a file.
DSA authentication is deprecated and will be removed in a future release.
- .. cpp:function:: std::vector<std::string> allowed_ecc_curves() const
+ .. cpp:function:: std::vector<Group_Params> key_exchange_groups() const
- Return a list of ECC curves we are willing to use, in order of preference.
+ Return a list of ECC curve and DH group TLS identifiers we are willing to use, in order of preference.
The default ordering puts the best performing ECC first.
- Default: "x25519", "secp256r1", "secp521r1", "secp384r1",
- "brainpool256r1", "brainpool384r1", "brainpool512r1"
+ Default:
+ Group_Params::X25519, Group_Params::SECP256R1,
+ Group_Params::SECP521R1, Group_Params::SECP384R1,
+ Group_Params::BRAINPOOL256R1, Group_Params::BRAINPOOL384R1,
+ Group_Params::BRAINPOOL512R1, Group_Params::FFDHE_2048,
+ Group_Params::FFDHE_3072, Group_Params::FFDHE_4096,
+ Group_Params::FFDHE_6144, Group_Params::FFDHE_8192
No other values are currently defined.
@@ -994,10 +1009,10 @@ policy settings from a file.
Default: true
- .. cpp:function:: std::string dh_group() const
+ .. cpp:function:: Group_Params default_dh_group() const
For ephemeral Diffie-Hellman key exchange, the server sends a
- group parameter. Return a string specifying the group parameter a
+ group parameter. Return the 2 Byte TLS group identifier specifying the group parameter a
server should use.
Default: 2048 bit IETF IPsec group ("modp/ietf/2048")
@@ -1154,3 +1169,376 @@ The ``TLS::Protocol_Version`` class represents a specific version:
Returns the latest version of the DTLS protocol known to the
library (currently DTLS v1.2)
+
+TLS Custom Curves
+----------------------------------------
+
+The supported_groups TLS extension is used in the client hello to advertise a list of supported elliptic curves
+and DH groups. The server subsequently selects one of the groups, which is supported by both endpoints.
+The groups are represented by their TLS identifier. This 2 Byte identifier is standardized for commonly used groups and curves.
+In addition, the standard reserves the identifiers 0xFE00 to 0xFEFF for custom groups or curves.
+
+Using non standardized custom curves is however not recommended and can be a serious risk if an
+insecure curve is used. Still, it might be desired in some scenarios to use custom curves or groups in the TLS handshake.
+
+To use custom curves with the Botan :cpp:class:`TLS::Client` or :cpp:class:`TLS::Server` the following additional adjustments have to be implemented
+as shown in the following code examples.
+
+1. Registration of the custom curve
+2. Implementation TLS callback ``tls_decode_group_param``
+3. Adjustment of the TLS policy by allowing the custom curve
+
+Client Code Example
+^^^^^^^^^^^^
+.. code-block:: cpp
+
+ #include <botan/tls_client.h>
+ #include <botan/tls_callbacks.h>
+ #include <botan/tls_session_manager.h>
+ #include <botan/tls_policy.h>
+ #include <botan/auto_rng.h>
+ #include <botan/certstor.h>
+
+ #include <botan/ec_group.h>
+ #include <botan/oids.h>
+
+
+ /**
+ * @brief Callbacks invoked by TLS::Channel.
+ *
+ * Botan::TLS::Callbacks is an abstract class.
+ * For improved readability, only the functions that are mandatory
+ * to implement are listed here. See src/lib/tls/tls_callbacks.h.
+ */
+ class Callbacks : public Botan::TLS::Callbacks
+ {
+ public:
+ void tls_emit_data(const uint8_t data[], size_t size) override
+ {
+ // send data to tls server, e.g., using BSD sockets or boost asio
+ }
+
+ void tls_record_received(uint64_t seq_no, const uint8_t data[], size_t size) override
+ {
+ // process full TLS record received by tls server, e.g.,
+ // by passing it to the application
+ }
+
+ void tls_alert(Botan::TLS::Alert alert) override
+ {
+ // handle a tls alert received from the tls server
+ }
+
+ bool tls_session_established(const Botan::TLS::Session& session) override
+ {
+ // the session with the tls server was established
+ // return false to prevent the session from being cached, true to
+ // cache the session in the configured session manager
+ return false;
+ }
+ std::string tls_decode_group_param(Botan::TLS::Group_Params group_param) override
+ {
+ // handle TLS group identifier decoding and return name as string
+ // return empty string to indicate decoding failure
+
+ switch(static_cast<uint16_t>(group_param))
+ {
+ case 0xFE00:
+ return "testcurve1102";
+ default:
+ //decode non-custom groups
+ return Botan::TLS::Callbacks::tls_decode_group_param(group_param);
+ }
+ }
+ };
+
+ /**
+ * @brief Credentials storage for the tls client.
+ *
+ * It returns a list of trusted CA certificates from a local directory.
+ * TLS client authentication is disabled. See src/lib/tls/credentials_manager.h.
+ */
+ class Client_Credentials : public Botan::Credentials_Manager
+ {
+ public:
+ std::vector<Botan::Certificate_Store*> trusted_certificate_authorities(
+ const std::string& type,
+ const std::string& context) override
+ {
+ // return a list of certificates of CAs we trust for tls server certificates,
+ // e.g., all the certificates in the local directory "cas"
+ return { new Botan::Certificate_Store_In_Memory("cas") };
+ }
+
+ std::vector<Botan::X509_Certificate> cert_chain(
+ const std::vector<std::string>& cert_key_types,
+ const std::string& type,
+ const std::string& context) override
+ {
+ // when using tls client authentication (optional), return
+ // a certificate chain being sent to the tls server,
+ // else an empty list
+ return std::vector<Botan::X509_Certificate>();
+ }
+
+ Botan::Private_Key* private_key_for(const Botan::X509_Certificate& cert,
+ const std::string& type,
+ const std::string& context) override
+ {
+ // when returning a chain in cert_chain(), return the private key
+ // associated with the leaf certificate here
+ return nullptr;
+ }
+ };
+
+ class Client_Policy : public Botan::TLS::Strict_Policy
+ {
+ public:
+ std::vector<Botan::TLS::Group_Params> key_exchange_groups() const override
+ {
+ // modified strict policy to allow our custom curves
+ return
+ {
+ static_cast<Botan::TLS::Group_Params>(0xFE00)
+ };
+ }
+ };
+
+ int main()
+ {
+ // prepare rng
+ Botan::AutoSeeded_RNG rng;
+
+ // prepare custom curve
+
+ // prepare curve parameters
+ const Botan::BigInt p("0x92309a3e88b94312f36891a2055725bb35ab51af96b3a651d39321b7bbb8c51575a76768c9b6b323");
+ const Botan::BigInt a("0x4f30b8e311f6b2dce62078d70b35dacb96aa84b758ab5a8dff0c9f7a2a1ff466c19988aa0acdde69");
+ const Botan::BigInt b("0x9045A513CFFF9AE1F1CC84039D852D240344A1D5C9DB203C844089F855C387823EB6FCDDF49C909C");
+
+ const Botan::BigInt x("0x9120f3779a31296cefcb5a5a08831f1a6d438ad5a3f2ce60585ac19c74eebdc65cadb96bb92622c7");
+ const Botan::BigInt y("0x836db8251c152dfee071b72c6b06c5387d82f1b5c30c5a5b65ee9429aa2687e8426d5d61276a4ede");
+ const Botan::BigInt order("0x248c268fa22e50c4bcda24688155c96ecd6ad46be5c82d7a6be6e7068cb5d1ca72b2e07e8b90d853");
+
+ const Botan::BigInt cofactor(4);
+
+ const Botan::OID oid("1.2.3.1");
+
+ // create EC_Group object to register the curve
+ Botan::EC_Group testcurve1102(p, a, b, x, y, order, cofactor, oid);
+
+ if(!testcurve1102.verify_group(rng))
+ {
+ // Warning: if verify_group returns false the curve parameters are insecure
+ }
+
+ // register name to specified oid
+ Botan::OIDS::add_oid(oid, "testcurve1102");
+
+ // prepare all the parameters
+ Callbacks callbacks;
+ Botan::TLS::Session_Manager_In_Memory session_mgr(rng);
+ Client_Credentials creds;
+ Client_Policy policy;
+
+ // open the tls connection
+ Botan::TLS::Client client(callbacks,
+ session_mgr,
+ creds,
+ policy,
+ rng,
+ Botan::TLS::Server_Information("botan.randombit.net", 443),
+ Botan::TLS::Protocol_Version::TLS_V12);
+
+
+ while(!client.is_closed())
+ {
+ // read data received from the tls server, e.g., using BSD sockets or boost asio
+ // ...
+
+ // send data to the tls server using client.send_data()
+
+ }
+ }
+
+Server Code Example
+^^^^^^^^^^^^
+.. code-block:: cpp
+
+ #include <botan/tls_server.h>
+ #include <botan/tls_callbacks.h>
+ #include <botan/tls_session_manager.h>
+ #include <botan/tls_policy.h>
+ #include <botan/auto_rng.h>
+ #include <botan/certstor.h>
+ #include <botan/pk_keys.h>
+ #include <botan/pkcs8.h>
+
+ #include <botan/ec_group.h>
+ #include <botan/oids.h>
+
+ #include <memory>
+
+ /**
+ * @brief Callbacks invoked by TLS::Channel.
+ *
+ * Botan::TLS::Callbacks is an abstract class.
+ * For improved readability, only the functions that are mandatory
+ * to implement are listed here. See src/lib/tls/tls_callbacks.h.
+ */
+ class Callbacks : public Botan::TLS::Callbacks
+ {
+ public:
+ void tls_emit_data(const uint8_t data[], size_t size) override
+ {
+ // send data to tls client, e.g., using BSD sockets or boost asio
+ }
+
+ void tls_record_received(uint64_t seq_no, const uint8_t data[], size_t size) override
+ {
+ // process full TLS record received by tls client, e.g.,
+ // by passing it to the application
+ }
+
+ void tls_alert(Botan::TLS::Alert alert) override
+ {
+ // handle a tls alert received from the tls server
+ }
+
+ bool tls_session_established(const Botan::TLS::Session& session) override
+ {
+ // the session with the tls client was established
+ // return false to prevent the session from being cached, true to
+ // cache the session in the configured session manager
+ return false;
+ }
+
+ std::string tls_decode_group_param(Botan::TLS::Group_Params group_param) override
+ {
+ // handle TLS group identifier decoding and return name as string
+ // return empty string to indicate decoding failure
+
+ switch(static_cast<uint16_t>(group_param))
+ {
+ case 0xFE00:
+ return "testcurve1102";
+ default:
+ //decode non-custom groups
+ return Botan::TLS::Callbacks::tls_decode_group_param(group_param);
+ }
+ }
+ };
+
+ /**
+ * @brief Credentials storage for the tls server.
+ *
+ * It returns a certificate and the associated private key to
+ * authenticate the tls server to the client.
+ * TLS client authentication is not requested.
+ * See src/lib/tls/credentials_manager.h.
+ */
+ class Server_Credentials : public Botan::Credentials_Manager
+ {
+ public:
+ Server_Credentials() : m_key(Botan::PKCS8::load_key("botan.randombit.net.key")
+ {
+ }
+
+ std::vector<Botan::Certificate_Store*> trusted_certificate_authorities(
+ const std::string& type,
+ const std::string& context) override
+ {
+ // if client authentication is required, this function
+ // shall return a list of certificates of CAs we trust
+ // for tls client certificates, otherwise return an empty list
+ return std::vector<Botan::Certificate_Store*>();
+ }
+
+ std::vector<Botan::X509_Certificate> cert_chain(
+ const std::vector<std::string>& cert_key_types,
+ const std::string& type,
+ const std::string& context) override
+ {
+ // return the certificate chain being sent to the tls client
+ // e.g., the certificate file "botan.randombit.net.crt"
+ return { Botan::X509_Certificate("botan.randombit.net.crt") };
+ }
+
+ Botan::Private_Key* private_key_for(const Botan::X509_Certificate& cert,
+ const std::string& type,
+ const std::string& context) override
+ {
+ // return the private key associated with the leaf certificate,
+ // in this case the one associated with "botan.randombit.net.crt"
+ return m_key.get();
+ }
+
+ private:
+ std::unique_ptr<Botan::Private_Key> m_key;
+ };
+
+ class Server_Policy : public Botan::TLS::Strict_Policy
+ {
+ public:
+ std::vector<Botan::TLS::Group_Params> key_exchange_groups() const override
+ {
+ // modified strict policy to allow our custom curves
+ return
+ {
+ static_cast<Botan::TLS::Group_Params>(0xFE00)
+ };
+ }
+ };
+
+ int main()
+ {
+
+ // prepare rng
+ Botan::AutoSeeded_RNG rng;
+
+ // prepare custom curve
+
+ // prepare curve parameters
+ const Botan::BigInt p("0x92309a3e88b94312f36891a2055725bb35ab51af96b3a651d39321b7bbb8c51575a76768c9b6b323");
+ const Botan::BigInt a("0x4f30b8e311f6b2dce62078d70b35dacb96aa84b758ab5a8dff0c9f7a2a1ff466c19988aa0acdde69");
+ const Botan::BigInt b("0x9045A513CFFF9AE1F1CC84039D852D240344A1D5C9DB203C844089F855C387823EB6FCDDF49C909C");
+
+ const Botan::BigInt x("0x9120f3779a31296cefcb5a5a08831f1a6d438ad5a3f2ce60585ac19c74eebdc65cadb96bb92622c7");
+ const Botan::BigInt y("0x836db8251c152dfee071b72c6b06c5387d82f1b5c30c5a5b65ee9429aa2687e8426d5d61276a4ede");
+ const Botan::BigInt order("0x248c268fa22e50c4bcda24688155c96ecd6ad46be5c82d7a6be6e7068cb5d1ca72b2e07e8b90d853");
+
+ const Botan::BigInt cofactor(4);
+
+ const Botan::OID oid("1.2.3.1");
+
+ // create EC_Group object to register the curve
+ Botan::EC_Group testcurve1102(p, a, b, x, y, order, cofactor, oid);
+
+ if(!testcurve1102.verify_group(rng))
+ {
+ // Warning: if verify_group returns false the curve parameters are insecure
+ }
+
+ // register name to specified oid
+ Botan::OIDS::add_oid(oid, "testcurve1102");
+
+ // prepare all the parameters
+ Callbacks callbacks;
+ Botan::TLS::Session_Manager_In_Memory session_mgr(rng);
+ Server_Credentials creds;
+ Server_Policy policy;
+
+ // accept tls connection from client
+ Botan::TLS::Server server(callbacks,
+ session_mgr,
+ creds,
+ policy,
+ rng);
+
+ // read data received from the tls client, e.g., using BSD sockets or boost asio
+ // and pass it to server.received_data().
+ // ...
+
+ // send data to the tls client using server.send_data()
+ // ...
+ }