SSL and TLS — Botan

# Botan

# SSL and TLS

New in version 1.9.4.

Botan supports both client and server implementations of the SSL/TLS protocols, including SSL v3, TLS v1.0, and TLS v1.1. The insecure and obsolete SSL v2 is not supported.

The implementation uses `std::tr1::function`, so it may not have been compiled into the version you are using; you can test for the feature macro `BOTAN_HAS_SSL_TLS` to check.

## TLS Clients

class `TLS_Client`
  `TLS_Client`(std::tr1::function<size_t, byte*, size_t> input_fn, std::tr1::function<void, const byte*, size_t> output_fn, const TLS_Policy& policy, RandomNumberGenerator& rng)

  Creates a TLS client. It will call input_fn to read bytes from the network and call output_fn when bytes need to be written to the network.

  size_t `read`(byte* buf, size_t buf_len)

  Reads up to buf_len bytes from the open connection into buf, returning the number of bytes actually written.

  void `write`(const byte* buf, size_t buf_len)

  Writes buf_len bytes in buf to the remote side

  void `close`()

  Closes the connection

  std::vector<X509_Certificate> `peer_cert_chain`()

  Returns the certificate chain of the server

A simple TLS client example:

    #include <botan/botan.h>
    #include <botan/tls_client.h>
    #include "socket.h"

    using namespace Botan;

    #include <stdio.h>
    #include <string>
    #include <iostream>
    #include <memory>

    class Client_TLS_Policy : public TLS_Policy
       {
       public:
          bool check_cert(const std::vector<X509_Certificate>& certs) const
             {
             for(size_t i = 0; i != certs.size(); ++i)
                {
                std::cout << certs[i].to_string();
                }

             std::cout << "Warning: not checking cert signatures\n";

             return true;
             }
       };

    int main(int argc, char* argv[])
       {
       if(argc != 2 && argc != 3)
          {
          printf("Usage: %s host [port]\n", argv[0]);
          return 1;
          }

       try
          {
          LibraryInitializer botan_init;

          std::string host = argv[1];
          u32bit port = argc == 3 ? Botan::to_u32bit(argv[2]) : 443;

          printf("Connecting to %s:%d...\n", host.c_str(), port);

          SocketInitializer socket_init;

          Socket sock(argv[1], port);

          AutoSeeded_RNG rng;

          Client_TLS_Policy policy;

          TLS_Client tls(std::tr1::bind(&Socket::read, std::tr1::ref(sock), _1, _2),
                         std::tr1::bind(&Socket::write, std::tr1::ref(sock), _1, _2),
                         policy, rng);

          printf("Handshake extablished...\n");

    #if 0
          std::string http_command = "GET / HTTP/1.1\r\n"
                                     "Server: " + host + ':' + to_string(port) + "\r\n\r\n";
    #else
          std::string http_command = "GET / HTTP/1.0\r\n\r\n";
    #endif

          tls.write((const Botan::byte*)http_command.c_str(),
                    http_command.length());

          size_t total_got = 0;

          while(true)
             {
             if(tls.is_closed())
                break;

             Botan::byte buf[128+1] = { 0 };
             size_t got = tls.read(buf, sizeof(buf)-1);
             printf("%s", buf);
             fflush(0);

             total_got += got;
             }

          printf("\nRetrieved %d bytes total\n", total_got);
       }
       catch(std::exception& e)
          {
          printf("%s\n", e.what());
          return 1;
          }
       return 0;
       }

## TLS Servers

A simple TLS server

    #include <botan/botan.h>
    #include <botan/tls_server.h>

    #include <botan/rsa.h>
    #include <botan/dsa.h>
    #include <botan/x509self.h>

    #include "socket.h"

    using namespace Botan;

    #include <stdio.h>
    #include <string>
    #include <iostream>
    #include <memory>

    class Server_TLS_Policy : public TLS_Policy
       {
       public:
          bool check_cert(const std::vector<X509_Certificate>& certs) const
             {
             for(size_t i = 0; i != certs.size(); ++i)
                {
                std::cout << certs[i].to_string();
                }

             std::cout << "Warning: not checking cert signatures\n";

             return true;
             }
       };

    int main(int argc, char* argv[])
       {
       int port = 4433;

       if(argc == 2)
          port = to_u32bit(argv[1]);

       try
          {
          LibraryInitializer botan_init;
          SocketInitializer socket_init;

          AutoSeeded_RNG rng;

          //RSA_PrivateKey key(rng, 1024);
          DSA_PrivateKey key(rng, DL_Group("dsa/jce/1024"));

          X509_Cert_Options options(
             "localhost/US/Syn Ack Labs/Mathematical Munitions Dept");

          X509_Certificate cert =
             X509::create_self_signed_cert(options, key, "SHA-1", rng);

          Server_Socket listener(port);

          Server_TLS_Policy policy;

          while(true)
             {
             try {
                printf("Listening for new connection on port %d\n", port);

                Socket* sock = listener.accept();

                printf("Got new connection\n");

                TLS_Server tls(
                  std::tr1::bind(&Socket::read, std::tr1::ref(sock), _1, _2),
                  std::tr1::bind(&Socket::write, std::tr1::ref(sock), _1, _2),
                  policy,
                  rng,
                  cert,
                  key);

                std::string hostname = tls.requested_hostname();

                if(hostname != "")
                   printf("Client requested host '%s'\n", hostname.c_str());

                printf("Writing some text\n");

                char msg[] = "Foo\nBar\nBaz\nQuux\n";
                tls.write((const Botan::byte*)msg, strlen(msg));

                printf("Now trying a read...\n");

                char buf[1024] = { 0 };
                u32bit got = tls.read((Botan::byte*)buf, sizeof(buf)-1);
                printf("%d: '%s'\n", got, buf);

                tls.close();
                }
             catch(std::exception& e) { printf("%s\n", e.what()); }
             }
       }
       catch(std::exception& e)
          {
          printf("%s\n", e.what());
          return 1;
          }
       return 0;
       }