TLS

    TLS is a cryptographic security layer “on top” of TCP that makes the data
    tamper proof and guarantees server authenticity, based on strong public key
    cryptography and digital signatures.

    When curl connections to a TLS server, it negotiates how to speak the protocol
    and that negotiation involves several parameters and variables that both
    parties need to agree to. One of the parameters is which cryptography
    algorithms to use, the so called cipher. Over time, security researchers
    figure out flaws and weaknesses in existing ciphers and they are gradually
    phased out over time.

    Using the verbose option, , you can get information about which cipher and
    TLS version are negotiated. By using the --ciphers option, you can change
    what cipher to prefer in the negotiation, but mind you, this is a power feature
    that takes knowledge to know how to use in ways that don’t just make things
    worse.

    Enable TLS

    curl supports the TLS version of many protocols. HTTP has HTTPS,
    FTP has FTPS, LDAP has LDAPS, POP3 has POP3S, IMAP has IMAPS and SMTP has
    SMTPS.

    If the server side supports it, you can use the TLS version of these protocols
    with curl.

    There are two general approaches to do TLS with protocols. One of them is to
    speak TLS already from the first connection handshake while the other is to
    “upgrade” the connection from plain-text to TLS using protocol specific
    instructions.

    With curl, if you explicitly specify the TLS version of the protocol (the one
    that has a name that ends with an ‘S’ character) in the URL, curl will try to
    connect with TLS from start, while if you specify the non-TLS version in the
    URL you can usually upgrade the connection to TLS-based with the --ssl
    option.

    The support table looks like this:

    The protocols that can do --ssl all favor that method. Using --ssl means
    that curl will attempt to upgrade the connection to TLS but if that fails,
    it will still continue with the transfer using the plain-text version of the
    protocol. To make the --ssl option require TLS to continue, there’s
    instead the option which will make the transfer fail if curl
    cannot successfully negotiate TLS.

    Require TLS security for your FTP transfer:

    Suggest TLS to be used for your FTP transfer:

    1. curl --ssl ftp://ftp.example.com/file.txt

    Connecting directly with TLS (to HTTPS://, LDAPS://, FTPS:// etc) means that
    TLS is mandatory and curl will return an error if TLS isn’t negotiated.

    Get a file over HTTPS:

    SSL and TLS versions

    TLS version 1.0 was the first “standard”. RFC 2246 was published 1999. After
    that, TLS 1.1 came and and in 2017, TLS 1.2 is still the gold standard. TLS
    1.3 is in the works and we expect to see it finalized and published as a
    standard by the IETF at some point during 2018.

    curl is designed to use a “safe version” of SSL/TLS by default. It means that
    it will not negotiate SSLv2 or SSLv3 unless specifically told to, and in fact
    several TLS libraries no longer provide support for those protocols so in many
    cases curl is not even able to speak those protocol versions unless you make a
    serious effort.

    Option Use
    —sslv2 SSL version 2
    —sslv3 SSL version 3
    —tlsv1 TLS >= version 1.0
    —tlsv1.0 TLS version 1.0
    —tlsv1.1 TLS version 1.1
    —tlsv1.2 TLS version 1.2
    —tlsv1.3 TLS version 1.3

    NOTE: TLS version 1.3 is only supported in selected very recent
    development versions of certain TLS libraries and requires curl 7.52.0 or
    later.

    Having a secure connection to a server is not worth a lot if you cannot also
    be certain that you are communicating with the correct host. If we don’t
    know that, we could just as well be talking with an imposter that just
    appears to be who we think it is.

    To check that it communicates with the right TLS server, curl uses a set of
    locally stored CA certificates to verify the signature of the server’s
    certificate. All servers provide a certificate to the client as part of the
    TLS handshake and all public TLS-using servers have acquired that certificate
    from an established Certificate Authority.

    After some applied crypto magic, curl knows that the server is in fact the
    correct one that acquired that certificate for the host name that curl used to
    connect to it. Failing to verify the server’s certificate is a TLS handshake
    failure and curl exits with an error.

    In rare circumstances, you may decide that you still want to communicate with
    a TLS server even if the certificate verification fails. You then accept the
    fact that your communication may be subject to Man-In-The-Middle attacks. You
    lower your guards with the -k or --insecure option.

    CA store

    curl needs a “CA store”, a collection of CA certificates, to verify the TLS
    server it talks to.

    If curl is built to use a TLS library that is “native” to your platform,
    chances are that library will use the native CA store as well. If not, curl
    has to either have been built to know where the local CA store is, or users
    need to provide a path to the CA store when curl is invoked.

    You can point out a specific CA bundle to use in the TLS handshake with the
    --cacert command line option. That bundle needs to be in PEM format. You can
    also set the environment variable CURL_CA_BUNDLE to the full path.

    curl built on windows that isn’t using the native TLS library (Schannel), have
    an extra sequence for how the CA store can be found and used.

    curl will search for a CA cert file named “curl-ca-bundle.crt” in these
    directories and in this order:

    1. current working directory
    2. Windows System directory (e.g. )
    3. Windows Directory (e.g. C:\windows)
    4. all directories along %PATH%

    Certificate pinning

    TLS certificate pinning is a way to verify that the public key used to sign
    the servers certificate has not changed. It is “pinned”.

    You tell curl a file name to read the sha256 value from, or you specify the
    base64 encoded hash directly in the command line with a “sha256//“ prefix. You
    can specify one or more hashes like that, separated with semicolons (;).

    1. curl --pinnedpubkey "sha256//83d34tasd3rt..." https://example.com/

    This feature is not supported by all TLS backends.

    This uses the TLS extension called Certificate Status Request to ask the
    server to provide a fresh “proof” from the CA in the handshake, that the
    certificate that it returns is still valid. This is a way to make really sure
    the server’s certificate hasn’t been revoked.

    If the server doesn’t support this extension, the test will fail and curl
    returns an error. And it is still far too common that servers don’t support
    this.

    Ask for the handshake to use the status request like this:

    This feature is only supported by the OpenSSL, GnuTLS and NSS backends.

    Client certificates

    TLS client certificates are a way for clients to cryptographically prove to
    servers that they are truly the right peer. A command line that uses a client
    certificate specifies the certificate and the corresponding key, and they are
    then passed on the TLS handshake with the server.

    You need to have your client certificate already stored in a file when doing
    this and you should supposedly have gotten it from the right instance via a
    different channel previously.

    The key is typically protected by a password that you need to provide or get
    prompted for interactively.

    curl offers options to let you specify a single file that is both the client
    certificate and the private key concatenated using --cert, or you can
    specify the key file independently with --key:

    For some TLS backends you can also pass in the key and certificate using
    different types:

    TLS auth

    TBD

    TBD

    Multiple TLS backends