c++sslnetwork-programmingbotan

How to encrypt data using Botan library and a specific cipher suite?


I had used Botan::TLS::Callbacks and also Botan::TLS::Client Botan::TLS::Server in order to get a secure channel between client and server. Also in order to encrypt-decrypt data I had used <botan/pubkeys.h> <botan/pk_keys.h> and other include headers in Botan library.

My questions are:

  1. Why Botan::PK_Encryptor_EME objects don't get the encryption algorithm negotiated between two sides as a cipher suite in Server_Hello_Message. They just get the Public key, Random number generator and optimal encryption padding algorithm as input. Mention that the algorithm is not being taken by the key which is obvious and true(By the algorithm I mean the bulk encryption algorithm like AES-128).

  2. How a tls channel is secured? As I discovered through the source code there is a function Botan::TLS::Callbacks tls_emit_data(const uint8_t[], size_t) which is going to send data through a secured channel! Even if the client and server had negotiated and exchanged the asymmetric keys earlier, data should be encrypted using symmetric keys that had been agreed on by the both sides.


Solution

  • The Botan::TLS::Client / Botan::TLS::Server classes implement the TLS protocol operations. Specifically they handle the cryptographic operations for you. However, they don't know anything about the transport layer, like reading from / writing to a socket. This part has to be implemented by you.

    In a typical implementation, after connection has been established, you would call client.send(buf, len) with some data you want to send to the server. The client internally builds the TLS records and invokes your tls_emit_data callback for sending them to the transport layer, so you can write it to some socket. On the server side, you would listens to a socket and read this TLS record. You would then pass it to server.received_data(buf, len). The server internally extracts the actual data from the TLS record and gives it to you via the tls_record_received callback.

    More details can be found in the Botan API documentation.

    Regarding your questions:

    1. I'm not sure which part of code you mean. The only usage of PK_Encryptor_EME I can find in the Botan tls module is here during the client key exchange. The key exchange does not involve encryption with the block cipher used for transmitting data. This happens e.g. here.

    2. tls_emit_data will be called by the client/server when it has constructed a TLS record. The encryption has been handled internally, you only have to pass the TLS record to the transport layer.

    Example implementation

    Botan includes an example implementation of a basic TLS client/server: tls_server, tls_client.

    This can be tested via the Botan command line interface:

    $ mkdir certdir
    $ botan keygen > ca_key.pem
    $ botan gen_self_signed --ca ca_key.pem my_root_authority > certdir/ca_cert.pem
    
    $ botan keygen > server_key.pem
    $ botan gen_pkcs10 server_key.pem localhost > server_csr.pem
    $ botan sign_cert certdir/ca_cert.pem ca_key.pem server_csr.pem > server_cert.pem
    
    # botan tls_server server_cert.pem server_key.pem
    
    $ botan tls_client localhost --trusted-cas=certdir
    Certificate validation status: Verified
    Handshake complete, TLS v1.2 using CECPQ1_RSA_WITH_CHACHA20_POLY1305_SHA256
    Session ID ...
    

    Some points of interests from the example code: