dcsimg
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 3 of 3

Thread: DTLS Server: Can't agree on ciphersuite ERROR - WinSocks and Botan

  1. #1
    Join Date
    Apr 2019
    Posts
    2

    DTLS Server: Can't agree on ciphersuite ERROR - WinSocks and Botan

    Hallo Users,

    I am writing a DTLS Server with Botan. I tested it with Botan-cli.exe and with the Qt DTLS Example Client. I am always receiving the Error can't agree on ciphersuite. On Windows and on Linux.

    My Windows code:
    https://pastebin.com/L59Fu9ey

    Same error if I use my DTLSPolicy or DefaultPolicy.

    Anyone can give me a tip how to resolve this problem?

    Thanks for help

  2. #2
    VictorN's Avatar
    VictorN is online now Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    19,378

    Re: DTLS Server: Can't agree on ciphersuite ERROR - WinSocks and Botan

    Please, attach code to your post. Read the Announcement: Before you post....
    Victor Nijegorodov

  3. #3
    Join Date
    Apr 2019
    Posts
    2

    Re: DTLS Server: Can't agree on ciphersuite ERROR - WinSocks and Botan

    OK here the code:
    Code:
    /****
        DTLSPolicy.hpp
    ****/
     
    #pragma once
     
    #include<botan/tls_policy.h>
    #include<array>
    #include<any>
     
    //ENUM Class for Future Versions
    //DTLS_ANY is for a possible future feature if you can exclude some Versions. DTLS_ANY will show that no Version is excluded.
    //e.g. if there were 1.0 , 1.2 , 1.5 ,2.0 you could set up DTLS_1_0 and exclude DTLS_1_5 as accepted. If DTLS_ANY is set it is not.
    enum class DTLSVersion : unsigned int {
        DTLS_ANY = 0,
        DTLS_1_0 = 1,
        DTLS_1_2 = 2
    };
     
    constexpr std::array<const char*,19> ACCEPT_ALL_CIPHERS{"AES-256/OCB(12)","AES-128/OCB(12)","ChaCha20Poly1305","AES-256/GCM","AES-128/GCM","AES-256/CCM","AES-128/CCM","AES-256/CCM(8)","AES-128/CCM(8)","Camellia-256/GCM","Camellia-128/GCM","ARIA-256/GCM", "ARIA-128/GCM", "AES-256", "AES-128","Camellia-256", "Camellia-128", "SEED","3DES" };
    constexpr std::array<const char*, 4> ACCEPT_ALL_SIGNATURE_HASHES{ "SHA-512","SHA-384","SHA-256","SHA-1", };
    constexpr std::array<const char*, 4> ACCEPT_ALL_MACS{ "AEAD","SHA-256","SHA-384","SHA-1" };
    constexpr std::array<const char*, 8> ACCEPT_ALL_KEY_EXCHANGE_METHODS{ "SRP_SHA", "ECDHE_PSK", "DHE_PSK", "PSK", "CECPQ1", "ECDH", "DH", "RSA" };
    constexpr std::array<const char*, 5> ACCEPT_ALL_SIGNATURE_METHODS{ "ECDSA","RSA","DSA","IMPLICIT","ANONYMOUS" };
     
    class DTLSPolicy : public Botan::TLS::Policy
    {
    public:
        enum class DTLSPolicyOptions : unsigned int {
            //1-9 ALLOWED FEATURES
            DTLS_OPTION_SET_ALLOWED_CIPHERS = 1,
            DTLS_OPTION_SET_ALLOWED_SIGNATURE_HASHES = 2,
            DTLS_OPTION_SET_ALLOWED_MACS = 3,
            DTLS_OPTION_SET_ALLOW_KEY_EXCHANGE_METHODS = 4,
            DTLS_OPTION_SET_ALLOW_SIGNATURE_METHODS = 5,
            //10+ OTHER FEATURES
            DTLS_OPTION_EXCLUDE_DTLS_VERSION = 10,
        };
        DTLSPolicy(DTLSVersion minimum);
        ~DTLSPolicy();
        void setOption(DTLSPolicy::DTLSPolicyOptions option, std::any data);
       
     
     
        //OVERRIDE FUNCTIONS
        bool allow_dtls10() const override {
            return this->dtls10_enabled;
        }
        bool allow_dtls12() const override {
            return this->dtls12_enabled;
        }
     
        bool allow_tls10() {
            return false;
        }
     
        bool allow_tls11() {
            return false;
        }
     
        std::vector<std::string> allowed_ciphers() const override {
            return this->allowedCiphersVec;
        }
     
        std::vector<std::string> allowed_signature_hashes() const override {
            return this->allowedSignatureHashesVec;
        }
     
        std::vector<std::string> allowed_macs() const override {
            return this->allowedMacsVec;
        }
     
        std::vector<std::string> allowed_key_exchange_methods() const override {
            return this->allowedKeyExchangeMethodsVec;
        }
     
        std::vector<std::string> allowed_signature_methods() const override {
            return this->allowedSignatureMethodsVec;
        }
     
     
     
    private:
        bool dtls10_enabled = false;
        bool dtls12_enabled = false;
        std::vector<std::string> allowedCiphersVec;
        std::vector<std::string> allowedSignatureHashesVec;
        std::vector<std::string> allowedMacsVec;
        std::vector<std::string> allowedKeyExchangeMethodsVec;
        std::vector<std::string> allowedSignatureMethodsVec;
        bool noexclusion = false;
     
        void excludeVersion(DTLSVersion version);
    };
     
    // END
     
    /***
            DTLSPolicy.cpp
    ***/
     
    #include "DTLSPolicy.hpp"
    #include<iostream>
     
     
    DTLSPolicy::DTLSPolicy(DTLSVersion minimum)
    {
        switch (minimum) {
        case DTLSVersion::DTLS_ANY:
            this->noexclusion = true;
        case DTLSVersion::DTLS_1_0:
            this->dtls10_enabled = true;
        case DTLSVersion::DTLS_1_2:
            this->dtls12_enabled = true;
            break;
        default:
            std::cerr << "This should not be reached!\n";
            break;
        }
    }
     
    DTLSPolicy::~DTLSPolicy()
    {
    }
     
     
    //std::any for future options!
    void DTLSPolicy::setOption(DTLSPolicy::DTLSPolicyOptions option, std::any data)
    {
        switch (option) {
            case DTLSPolicy::DTLSPolicyOptions::DTLS_OPTION_SET_ALLOWED_CIPHERS:
            {
                this->allowedCiphersVec = std::any_cast<std::vector<std::string>>(data);
            }
            return;
            case DTLSPolicy::DTLSPolicyOptions::DTLS_OPTION_SET_ALLOWED_SIGNATURE_HASHES:
            {
                this->allowedSignatureHashesVec = std::any_cast<std::vector<std::string>>(data);
            }
            return;
            case DTLSPolicy::DTLSPolicyOptions::DTLS_OPTION_SET_ALLOWED_MACS:
            {
                this->allowedMacsVec = std::any_cast<std::vector<std::string>>(data);
            }
            return;
            case DTLSPolicy::DTLSPolicyOptions::DTLS_OPTION_SET_ALLOW_KEY_EXCHANGE_METHODS:
            {
                this->allowedKeyExchangeMethodsVec = std::any_cast<std::vector<std::string>>(data);
            }
            return;
            case DTLSPolicy::DTLSPolicyOptions::DTLS_OPTION_SET_ALLOW_SIGNATURE_METHODS:
            {
                this->allowedSignatureMethodsVec = std::any_cast<std::vector<std::string>>(data);
            }
            return;
            case DTLSPolicy::DTLSPolicyOptions::DTLS_OPTION_EXCLUDE_DTLS_VERSION:
            {
                this->excludeVersion(std::any_cast<DTLSVersion>(data));
            }
            return;
            default:
                std::cerr << "This should not be reached!\n";
                return;
        }
    }
     
    void DTLSPolicy::excludeVersion(DTLSVersion version)
    {
        if (this->noexclusion) return;
        switch (version) {
        case DTLSVersion::DTLS_1_0:
            this->dtls10_enabled = false;
            return;
        case DTLSVersion::DTLS_1_2:
            this->dtls12_enabled = false;
            return;
        case DTLSVersion::DTLS_ANY:
        default:
            std::cerr << "OPERATION NOT POSSIBLE\n";
            return;
        }
    }
     
    //END
     
    /***
            DTLS.hpp
    ***/
    #pragma once
    #define _WINSOCKAPI_ // stop windows.h including winsock.h
     
    #pragma comment(lib,"botan.lib")
    #include<iostream>
    //BOTAN
    #include<botan/tls_server.h>
    #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/pk_keys.h>
    #include<botan/hex.h>
    #include<botan/certstor.h>
    #include<botan/pkcs8.h>
    #include<botan/data_src.h>
    #pragma comment(lib,"ws2_32.lib")
    #include<WinSock2.h>
    #include<fstream>
     
    #include"DTLSPolicy.hpp"
     
     
     
    class Server_Credentials : public Botan::Credentials_Manager
    {
    private:
        std::unique_ptr<Botan::Private_Key> m_key;
    //  Botan::DataSource_Stream stream;
        std::ifstream file;
    public:
        Server_Credentials()
        {
        }
     
        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;
        }
     
     
    };
     
    class DTLS : public Botan::TLS::Callbacks
    {
    public:
        DTLS(const std::string& ip, unsigned int port, Botan::TLS::Policy& policy);
        ~DTLS();
     
        void startReceiving();
        void tls_emit_data(const uint8_t buf[], size_t length) override {
            sendto(this->servSocket, (char*)buf, length, 0, (SOCKADDR*)& this->clientAddr, sizeof(SOCKADDR_IN));
            startReceiving();
        }
     
        void tls_alert(Botan::TLS::Alert alert) override {
            std::cout << alert.type_string();
        }
     
        void tls_record_received(uint64_t seq_no, const uint8_t input[], size_t length) override {
            std::string t = "";
            for (size_t i = 0; i < length; ++i) {
                t += static_cast<char>(input[i]);
     
                if (t[t.length() - 1] == '\t') {
                    std::cout << t << '\n';
                    t.clear();
                }
            }
        }
     
        bool tls_session_established(const Botan::TLS::Session& session) override {
            std::cout << "DETAILS:\n"
                << "SESSION ID=" << Botan::hex_encode(session.session_id()) << '\n'
                << "Session Ticket=" << Botan::hex_encode(session.session_ticket()) << '\n';
            return true;
        }
     
     
     
    private:
        Botan::AutoSeeded_RNG rng;
        Botan::TLS::Session_Manager_In_Memory session_mgr;
        Botan::Credentials_Manager creds;
        Botan::TLS::Policy policy;
        Botan::TLS::Server server;
        SOCKET servSocket;
        SOCKADDR_IN servAddr;
        SOCKADDR_IN clientAddr;
    };
     
    //END
     
    /***
            DTLS.cpp
    ***/
    #include "DTLS.hpp"
    #include<botan/exceptn.h>
     
    #include<ws2tcpip.h>
     
    DTLS::DTLS(const std::string& ip, unsigned int port, Botan::TLS::Policy& policy) : policy(policy),session_mgr(this->rng), server(*this,this->session_mgr,this->creds,this->policy,this->rng,true)
    {
        WSAData d;
        WSAStartup(MAKEWORD(2, 0), &d);
        this->servSocket = socket(AF_INET, SOCK_DGRAM, 0);
        this->servAddr.sin_family = AF_INET;
        this->servAddr.sin_port = htons(port);
        char addr[666];
        if (ip != "ANY")
            this->servAddr.sin_addr.S_un.S_addr = ADDR_ANY;
        else
            this->servAddr.sin_addr.S_un.S_addr = ADDR_ANY;
        auto rc = bind(this->servSocket, (SOCKADDR*)& this->servAddr, sizeof(SOCKADDR_IN));
    #ifndef _NO_DEBUG
        if (rc == SOCKET_ERROR)
            std::cout << "COULD NOT BIND!\n";
        else
            std::cout << "SUCCESSFULLY SOCKET BIND\n";
    #endif
     
    }
     
     
    DTLS::~DTLS()
    {
        WSACleanup();
    }
     
    void DTLS::startReceiving()
    {
        try {
            uint8_t buffer[1024];
            memset(buffer, 0, sizeof(buffer));
            int size = sizeof(SOCKADDR_IN);
            auto rc = recvfrom(this->servSocket, (char*)buffer, sizeof(buffer), 0, (SOCKADDR*)& this->clientAddr, &size);
            buffer[rc] = '\0';
            std::cout << buffer << '\n';
            this->server.received_data(buffer, rc);
        }
        catch (Botan::Exception & ex) {
            std::cout << ex.what();
            system("pause");
        }
    }
    //END
     
    /***
        Quelle.cpp TESTMAIN
    ***/
     
    #include"DTLS.hpp"
     
    int main() {
        DTLSPolicy policy(DTLSVersion::DTLS_ANY);
        policy.setOption(DTLSPolicy::DTLSPolicyOptions::DTLS_OPTION_SET_ALLOWED_CIPHERS, std::vector<std::string>(ACCEPT_ALL_CIPHERS.begin(), ACCEPT_ALL_CIPHERS.end()));
        policy.setOption(DTLSPolicy::DTLSPolicyOptions::DTLS_OPTION_SET_ALLOWED_MACS, std::vector<std::string>(ACCEPT_ALL_MACS.begin(), ACCEPT_ALL_MACS.end()));
        policy.setOption(DTLSPolicy::DTLSPolicyOptions::DTLS_OPTION_SET_ALLOWED_SIGNATURE_HASHES, std::vector<std::string>(ACCEPT_ALL_SIGNATURE_HASHES.begin(), ACCEPT_ALL_SIGNATURE_HASHES.end()));
        policy.setOption(DTLSPolicy::DTLSPolicyOptions::DTLS_OPTION_SET_ALLOW_KEY_EXCHANGE_METHODS, std::vector<std::string>(ACCEPT_ALL_KEY_EXCHANGE_METHODS.begin(), ACCEPT_ALL_KEY_EXCHANGE_METHODS.end()));
        policy.setOption(DTLSPolicy::DTLSPolicyOptions::DTLS_OPTION_SET_ALLOW_SIGNATURE_METHODS, std::vector<std::string>(ACCEPT_ALL_SIGNATURE_METHODS.begin(), ACCEPT_ALL_SIGNATURE_METHODS.end()));
        Botan::TLS::Default_Policy p;
        DTLS test("192.168.1.119", 999,p);
        while (true) {
            test.startReceiving();
            Sleep(500);
        }
        system("pause");
    }

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width




On-Demand Webinars (sponsored)