implement ecdsa
This commit is contained in:
parent
15c48ab1dc
commit
eb01b304e3
@ -5,6 +5,7 @@
|
|||||||
#include "openssl_utils.hpp"
|
#include "openssl_utils.hpp"
|
||||||
#include "registration.hpp"
|
#include "registration.hpp"
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
|
#include "ref.hpp"
|
||||||
#include "irc_coroutine.hpp"
|
#include "irc_coroutine.hpp"
|
||||||
|
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
@ -36,6 +37,9 @@ static auto start(boost::asio::io_context &io, const Settings &settings) -> void
|
|||||||
|
|
||||||
const auto connection = std::make_shared<Connection>(io);
|
const auto connection = std::make_shared<Connection>(io);
|
||||||
const auto client = Client::start(*connection);
|
const auto client = Client::start(*connection);
|
||||||
|
Ref<EVP_PKEY> sasl_key;
|
||||||
|
if (not settings.sasl_key_file.empty())
|
||||||
|
sasl_key = key_from_file(settings.sasl_key_file, settings.sasl_key_password);
|
||||||
Registration::start({
|
Registration::start({
|
||||||
.nickname = settings.nickname,
|
.nickname = settings.nickname,
|
||||||
.realname = settings.realname,
|
.realname = settings.realname,
|
||||||
@ -45,6 +49,7 @@ static auto start(boost::asio::io_context &io, const Settings &settings) -> void
|
|||||||
.sasl_authcid = settings.sasl_authcid,
|
.sasl_authcid = settings.sasl_authcid,
|
||||||
.sasl_authzid = settings.sasl_authzid,
|
.sasl_authzid = settings.sasl_authzid,
|
||||||
.sasl_password = settings.sasl_password,
|
.sasl_password = settings.sasl_password,
|
||||||
|
.sasl_key = std::move(sasl_key),
|
||||||
}, client);
|
}, client);
|
||||||
|
|
||||||
const auto bot = Bot::start(client);
|
const auto bot = Bot::start(client);
|
||||||
|
@ -17,6 +17,8 @@ auto Settings::from_stream(std::istream &in) -> Settings
|
|||||||
.sasl_authcid = config["sasl_authcid"].value_or(std::string{}),
|
.sasl_authcid = config["sasl_authcid"].value_or(std::string{}),
|
||||||
.sasl_authzid = config["sasl_authzid"].value_or(std::string{}),
|
.sasl_authzid = config["sasl_authzid"].value_or(std::string{}),
|
||||||
.sasl_password = config["sasl_password"].value_or(std::string{}),
|
.sasl_password = config["sasl_password"].value_or(std::string{}),
|
||||||
|
.sasl_key_file = config["sasl_key_file"].value_or(std::string{}),
|
||||||
|
.sasl_key_password = config["sasl_key_password"].value_or(std::string{}),
|
||||||
.tls_hostname = config["tls_hostname"].value_or(std::string{}),
|
.tls_hostname = config["tls_hostname"].value_or(std::string{}),
|
||||||
.tls_certfile = config["tls_certfile"].value_or(std::string{}),
|
.tls_certfile = config["tls_certfile"].value_or(std::string{}),
|
||||||
.tls_keyfile = config["tls_keyfile"].value_or(std::string{}),
|
.tls_keyfile = config["tls_keyfile"].value_or(std::string{}),
|
||||||
|
@ -16,6 +16,8 @@ struct Settings
|
|||||||
std::string sasl_authcid;
|
std::string sasl_authcid;
|
||||||
std::string sasl_authzid;
|
std::string sasl_authzid;
|
||||||
std::string sasl_password;
|
std::string sasl_password;
|
||||||
|
std::string sasl_key_file;
|
||||||
|
std::string sasl_key_password;
|
||||||
|
|
||||||
std::string tls_hostname;
|
std::string tls_hostname;
|
||||||
std::string tls_certfile;
|
std::string tls_certfile;
|
||||||
|
@ -41,8 +41,10 @@ struct Ref : std::unique_ptr<T, RefDeleter<T>>
|
|||||||
explicit Ref(T *x) noexcept : base{x} {}
|
explicit Ref(T *x) noexcept : base{x} {}
|
||||||
|
|
||||||
Ref(Ref &&ref) noexcept = default;
|
Ref(Ref &&ref) noexcept = default;
|
||||||
Ref(const Ref &ref) noexcept {
|
Ref(const Ref &ref) noexcept : base{ref.get()} {
|
||||||
*this = ref;
|
if (*this) {
|
||||||
|
RefTraits<T>::UpRef(this->get());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref &operator=(Ref&&) noexcept = default;
|
Ref &operator=(Ref&&) noexcept = default;
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "ref.hpp"
|
||||||
|
|
||||||
#include <boost/signals2.hpp>
|
#include <boost/signals2.hpp>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -74,3 +76,35 @@ public:
|
|||||||
return complete_;
|
return complete_;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class SaslEcdsa final : public SaslMechanism
|
||||||
|
{
|
||||||
|
std::string message1_;
|
||||||
|
Ref<EVP_PKEY> key_;
|
||||||
|
int stage_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SaslEcdsa(std::string authcid, std::string authzid, Ref<EVP_PKEY> key)
|
||||||
|
: message1_{std::move(authcid)}
|
||||||
|
, key_{std::move(key)}
|
||||||
|
, stage_{0}
|
||||||
|
{
|
||||||
|
if (not authzid.empty()) {
|
||||||
|
message1_.push_back(0);
|
||||||
|
message1_.append(authzid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto mechanism_name() const -> std::string override
|
||||||
|
{
|
||||||
|
return "ECDSA-NIST256P-CHALLENGE";
|
||||||
|
}
|
||||||
|
|
||||||
|
auto step(std::string_view msg) -> StepResult override;
|
||||||
|
|
||||||
|
auto is_complete() const -> bool override
|
||||||
|
{
|
||||||
|
return stage_ == 2;;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "connection.hpp"
|
#include "connection.hpp"
|
||||||
#include "ircmsg.hpp"
|
#include "ircmsg.hpp"
|
||||||
#include "sasl_mechanism.hpp"
|
#include "sasl_mechanism.hpp"
|
||||||
|
#include "openssl_utils.hpp"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <random>
|
#include <random>
|
||||||
@ -89,6 +90,11 @@ auto Registration::on_cap_list(const std::unordered_map<std::string, std::string
|
|||||||
settings_.sasl_password));
|
settings_.sasl_password));
|
||||||
} else if (do_sasl && settings_.sasl_mechanism == "EXTERNAL") {
|
} else if (do_sasl && settings_.sasl_mechanism == "EXTERNAL") {
|
||||||
client_->start_sasl(std::make_unique<SaslExternal>(settings_.sasl_authzid));
|
client_->start_sasl(std::make_unique<SaslExternal>(settings_.sasl_authzid));
|
||||||
|
} else if (do_sasl && settings_.sasl_mechanism == "ECDSA") {
|
||||||
|
client_->start_sasl(std::make_unique<SaslEcdsa>(
|
||||||
|
settings_.sasl_authcid,
|
||||||
|
settings_.sasl_authzid,
|
||||||
|
settings_.sasl_key));
|
||||||
} else {
|
} else {
|
||||||
client_->get_connection().send_cap_end();
|
client_->get_connection().send_cap_end();
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
#include "sasl_mechanism.hpp"
|
#include "sasl_mechanism.hpp"
|
||||||
|
#include "openssl_utils.hpp"
|
||||||
|
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
|
||||||
auto SaslPlain::step(std::string_view msg) -> StepResult {
|
auto SaslPlain::step(std::string_view msg) -> StepResult {
|
||||||
if (complete_) {
|
if (complete_) {
|
||||||
@ -13,7 +16,6 @@ auto SaslPlain::step(std::string_view msg) -> StepResult {
|
|||||||
reply += password_;
|
reply += password_;
|
||||||
|
|
||||||
complete_ = true;
|
complete_ = true;
|
||||||
|
|
||||||
return std::move(reply);
|
return std::move(reply);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -22,6 +24,51 @@ auto SaslExternal::step(std::string_view msg) -> StepResult {
|
|||||||
if (complete_) {
|
if (complete_) {
|
||||||
return Failure{};
|
return Failure{};
|
||||||
} else {
|
} else {
|
||||||
|
complete_ = true;
|
||||||
return std::move(authzid_);
|
return std::move(authzid_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto SaslEcdsa::step(std::string_view msg) -> StepResult {
|
||||||
|
switch (stage_) {
|
||||||
|
case 0:
|
||||||
|
stage_ = 1;
|
||||||
|
return std::move(message1_);
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
stage_ = 2;
|
||||||
|
Ref<EVP_PKEY_CTX> ctx {EVP_PKEY_CTX_new(key_.get(), nullptr)};
|
||||||
|
if (not ctx) {
|
||||||
|
log_openssl_errors("ECDSA new context: ");
|
||||||
|
return Failure{};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 >= EVP_PKEY_sign_init(ctx.get()))
|
||||||
|
{
|
||||||
|
log_openssl_errors("ECDSA init: ");
|
||||||
|
return Failure{};
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto input = reinterpret_cast<const unsigned char *>(msg.data());
|
||||||
|
size_t siglen;
|
||||||
|
if (0 >= EVP_PKEY_sign(ctx.get(), nullptr, &siglen, input, msg.size()))
|
||||||
|
{
|
||||||
|
log_openssl_errors("ECDSA signature (presize): ");
|
||||||
|
return Failure{};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string result(siglen, '\0');
|
||||||
|
const auto output = reinterpret_cast<unsigned char *>(result.data());
|
||||||
|
if (0 >= EVP_PKEY_sign(ctx.get(), output, &siglen, input, msg.size()))
|
||||||
|
{
|
||||||
|
log_openssl_errors("ECDSA signature: ");
|
||||||
|
return Failure{};
|
||||||
|
}
|
||||||
|
result.resize(siglen);
|
||||||
|
|
||||||
|
return std::move(result);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return Failure{};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user