-
April 27th, 2019, 05:09 PM
#1
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
-
April 28th, 2019, 01:50 AM
#2
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
-
April 28th, 2019, 10:10 AM
#3
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|