3

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.

AmirH.
  • 63
  • 6

1 Answers1

2

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:

  • Generate CA cert:
$ mkdir certdir
$ botan keygen > ca_key.pem
$ botan gen_self_signed --ca ca_key.pem my_root_authority > certdir/ca_cert.pem
  • Generate server cert:
$ 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
  • Start the TLS server (likely requires privileged user):
# botan tls_server server_cert.pem server_key.pem
  • Start the TLS client:
$ 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:

  • The Botan::TLS::Client is created here, the Botan::TLS::Server is created here.
  • Botan::TLS::Policy can be used for restricting e.g. which TLS versions and cipher modes can be used: Link
  • The client gets data read from stdin here. It constructs TLS records internally and passes them to the tls_emit_data callback, defined here for writing the TLS record to the socket.
  • The TLS record is read from the socket and passed to the server here.
  • The server internally extracts the data from the TLS record and passes it to tls_record_received here.