implement ecdsa
This commit is contained in:
parent
15c48ab1dc
commit
eb01b304e3
@ -5,6 +5,7 @@
|
||||
#include "openssl_utils.hpp"
|
||||
#include "registration.hpp"
|
||||
#include "settings.hpp"
|
||||
#include "ref.hpp"
|
||||
#include "irc_coroutine.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 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({
|
||||
.nickname = settings.nickname,
|
||||
.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_authzid = settings.sasl_authzid,
|
||||
.sasl_password = settings.sasl_password,
|
||||
.sasl_key = std::move(sasl_key),
|
||||
}, 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_authzid = config["sasl_authzid"].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_certfile = config["tls_certfile"].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_authzid;
|
||||
std::string sasl_password;
|
||||
std::string sasl_key_file;
|
||||
std::string sasl_key_password;
|
||||
|
||||
std::string tls_hostname;
|
||||
std::string tls_certfile;
|
||||
|
@ -41,8 +41,10 @@ struct Ref : std::unique_ptr<T, RefDeleter<T>>
|
||||
explicit Ref(T *x) noexcept : base{x} {}
|
||||
|
||||
Ref(Ref &&ref) noexcept = default;
|
||||
Ref(const Ref &ref) noexcept {
|
||||
*this = ref;
|
||||
Ref(const Ref &ref) noexcept : base{ref.get()} {
|
||||
if (*this) {
|
||||
RefTraits<T>::UpRef(this->get());
|
||||
}
|
||||
}
|
||||
|
||||
Ref &operator=(Ref&&) noexcept = default;
|
||||
|
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "ref.hpp"
|
||||
|
||||
#include <boost/signals2.hpp>
|
||||
|
||||
#include <memory>
|
||||
@ -74,3 +76,35 @@ public:
|
||||
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 "ircmsg.hpp"
|
||||
#include "sasl_mechanism.hpp"
|
||||
#include "openssl_utils.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <random>
|
||||
@ -89,6 +90,11 @@ auto Registration::on_cap_list(const std::unordered_map<std::string, std::string
|
||||
settings_.sasl_password));
|
||||
} else if (do_sasl && settings_.sasl_mechanism == "EXTERNAL") {
|
||||
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 {
|
||||
client_->get_connection().send_cap_end();
|
||||
}
|
||||
|
@ -1,4 +1,7 @@
|
||||
#include "sasl_mechanism.hpp"
|
||||
#include "openssl_utils.hpp"
|
||||
|
||||
#include <openssl/evp.h>
|
||||
|
||||
auto SaslPlain::step(std::string_view msg) -> StepResult {
|
||||
if (complete_) {
|
||||
@ -13,7 +16,6 @@ auto SaslPlain::step(std::string_view msg) -> StepResult {
|
||||
reply += password_;
|
||||
|
||||
complete_ = true;
|
||||
|
||||
return std::move(reply);
|
||||
}
|
||||
}
|
||||
@ -22,6 +24,51 @@ auto SaslExternal::step(std::string_view msg) -> StepResult {
|
||||
if (complete_) {
|
||||
return Failure{};
|
||||
} else {
|
||||
complete_ = true;
|
||||
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