Skip to content

Commit

Permalink
add dilithium standalone functionality
Browse files Browse the repository at this point in the history
correction of dilithium based on rnp feedback
  • Loading branch information
TJ-91 authored and antonsviridenko committed Sep 25, 2023
1 parent 15207d5 commit 4fdff8a
Show file tree
Hide file tree
Showing 9 changed files with 452 additions and 0 deletions.
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ tristate_feature_auto(ENABLE_CAST5 "Enable CAST5 cipher support.")
tristate_feature_auto(ENABLE_RIPEMD160 "Enable RIPEMD-160 hash support.")

option(ENABLE_CRYPTO_REFRESH "Enable crypto-refresh support (v6)")
option(ENABLE_PQC "Enable PQC support - requires ENABLE_CRYPTO_REFRESH")

if((NOT ENABLE_CRYPTO_REFRESH) AND ENABLE_PQC)
message(FATAL_ERROR "ENABLE_PQC requires ENABLE_CRYPTO_REFRESH")
endif()


set(ENABLE_DOC Auto CACHE STRING "Enable building documentation.")
Expand Down
17 changes: 17 additions & 0 deletions src/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,15 @@ if(CRYPTO_BACKEND_BOTAN3)
set(CMAKE_CXX_STANDARD 20)
endif()

if(ENABLE_PQC)
if (NOT CRYPTO_BACKEND_BOTAN3)
message(FATAL_ERROR "ENABLE_PQC requires Botan 3 as crypto backend")
endif()
if (NOT ENABLE_CRYPTO_REFRESH)
message(FATAL_ERROR "ENABLE_PQC requires ENABLE_CRYPTO_REFRESH")
endif()
endif()

# check that AEAD is enabled and not turned off for ENABLE_CRYPTO_REFRESH
if(ENABLE_CRYPTO_REFRESH AND (NOT ENABLE_AEAD))
message(FATAL_ERROR "ENABLE_CRYPTO_REFRESH requires ENABLE_AEAD, but it's either Off or Auto and got turned off")
Expand Down Expand Up @@ -179,6 +188,7 @@ if(CRYPTO_BACKEND_BOTAN)
resolve_feature_state(ENABLE_TWOFISH "TWOFISH")
resolve_feature_state(ENABLE_IDEA "IDEA")
resolve_feature_state(ENABLE_CRYPTO_REFRESH "HKDF")
resolve_feature_state(ENABLE_PQC "DILITHIUM")
resolve_feature_state(ENABLE_BLOWFISH "BLOWFISH")
resolve_feature_state(ENABLE_CAST5 "CAST_128")
resolve_feature_state(ENABLE_RIPEMD160 "RIPEMD_160")
Expand Down Expand Up @@ -221,6 +231,7 @@ if(CRYPTO_BACKEND_OPENSSL)
#resolve_feature_state(ENABLE_SM2 "SM2;SM3;SM4-ECB")
openssl_nope(ENABLE_TWOFISH "Twofish isn't and won't be supported by OpenSSL, see https://github.com/openssl/openssl/issues/2046")
openssl_nope(ENABLE_CRYPTO_REFRESH, "not yet implemented")
openssl_nope(ENABLE_PQC, "not yet implemented")
endif()

configure_file(config.h.in config.h)
Expand Down Expand Up @@ -289,6 +300,12 @@ elseif(CRYPTO_BACKEND_BOTAN)
crypto/exdsa_ecdhkem.cpp
)
endif()
if(ENABLE_PQC)
list(APPEND CRYPTO_SOURCES
crypto/dilithium.cpp
crypto/dilithium_common.cpp
)
endif()
else()
message(FATAL_ERROR "Unknown crypto backend: ${CRYPTO_BACKEND}.")
endif()
Expand Down
1 change: 1 addition & 0 deletions src/lib/config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
#cmakedefine ENABLE_BRAINPOOL
#cmakedefine ENABLE_IDEA
#cmakedefine ENABLE_CRYPTO_REFRESH
#cmakedefine ENABLE_PQC
#cmakedefine ENABLE_BLOWFISH
#cmakedefine ENABLE_CAST5
#cmakedefine ENABLE_RIPEMD160
Expand Down
122 changes: 122 additions & 0 deletions src/lib/crypto/dilithium.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
* Copyright (c) 2023 MTG AG
* All rights reserved.
*
* This code is originally derived from software contributed to
* The NetBSD Foundation by Alistair Crooks ([email protected]), and
* carried further by Ribose Inc (https://www.ribose.com).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

#include "dilithium.h"
#include <cassert>

namespace {

Botan::DilithiumMode
rnp_dilithium_param_to_botan_dimension(dilithium_parameter_e mode)
{
Botan::DilithiumMode result = Botan::DilithiumMode::Dilithium8x7;
if (mode == dilithium_parameter_e::dilithium_L3) {
result = Botan::DilithiumMode::Dilithium6x5;
}
return result;
}

} // namespace

std::vector<uint8_t>
pgp_dilithium_private_key_t::sign(rnp::RNG *rng, const uint8_t *msg, size_t msg_len) const
{
assert(is_initialized_);
auto priv_key = botan_key();

auto signer = Botan::PK_Signer(priv_key, *rng->obj(), "");
std::vector<uint8_t> signature = signer.sign_message(msg, msg_len, *rng->obj());
// std::vector<uint8_t> signature;

return signature;
}

Botan::Dilithium_PublicKey
pgp_dilithium_public_key_t::botan_key() const
{
return Botan::Dilithium_PublicKey(key_encoded_,
rnp_dilithium_param_to_botan_dimension(dilithium_param_));
}

Botan::Dilithium_PrivateKey
pgp_dilithium_private_key_t::botan_key() const
{
Botan::secure_vector<uint8_t> priv_sv(key_encoded_.data(),
key_encoded_.data() + key_encoded_.size());
return Botan::Dilithium_PrivateKey(
priv_sv, rnp_dilithium_param_to_botan_dimension(this->dilithium_param_));
}

bool
pgp_dilithium_public_key_t::verify_signature(const uint8_t *msg,
size_t msg_len,
const uint8_t *signature,
size_t signature_len) const
{
assert(is_initialized_);
auto pub_key = botan_key();

auto verificator = Botan::PK_Verifier(pub_key, "");
return verificator.verify_message(msg, msg_len, signature, signature_len);
}

std::pair<pgp_dilithium_public_key_t, pgp_dilithium_private_key_t>
dilithium_generate_keypair(
rnp::RNG *rng, dilithium_parameter_e dilithium_param)
{
Botan::Dilithium_PrivateKey priv_key(*rng->obj(),
rnp_dilithium_param_to_botan_dimension(dilithium_param));

std::unique_ptr<Botan::Public_Key> pub_key = priv_key.public_key();
Botan::secure_vector<uint8_t> priv_bits = priv_key.private_key_bits();
return std::make_pair(
pgp_dilithium_public_key_t(pub_key->public_key_bits(), dilithium_param),
pgp_dilithium_private_key_t(priv_bits.data(), priv_bits.size(), dilithium_param));
}

bool
pgp_dilithium_public_key_t::is_valid(rnp::RNG *rng) const {
if(!is_initialized_) {
return false;
}

auto key = botan_key();
return key.check_key(*(rng->obj()), false);
}

bool
pgp_dilithium_private_key_t::is_valid(rnp::RNG *rng) const {
if(!is_initialized_) {
return false;
}

auto key = botan_key();
return key.check_key(*(rng->obj()), false);
}
114 changes: 114 additions & 0 deletions src/lib/crypto/dilithium.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
* Copyright (c) 2023 MTG AG
* All rights reserved.
*
* This code is originally derived from software contributed to
* The NetBSD Foundation by Alistair Crooks ([email protected]), and
* carried further by Ribose Inc (https://www.ribose.com).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef DILITHIUM_H_
#define DILITHIUM_H_

#include "config.h"
#include <rnp/rnp_def.h>
#include <vector>
#include <repgp/repgp_def.h>
#include "crypto/rng.h"
#include <botan/dilithium.h>
#include <botan/pubkey.h>

enum dilithium_parameter_e { dilithium_L3, dilithium_L5 };

class pgp_dilithium_private_key_t {
public:
pgp_dilithium_private_key_t(const uint8_t * key_encoded,
size_t key_encoded_len,
dilithium_parameter_e param);
pgp_dilithium_private_key_t(std::vector<uint8_t> const &key_encoded,
dilithium_parameter_e param);
pgp_dilithium_private_key_t() = default;

bool is_valid(rnp::RNG *rng) const;

dilithium_parameter_e
param() const
{
return dilithium_param_;
}

std::vector<uint8_t> sign(rnp::RNG *rng, const uint8_t *msg, size_t msg_len) const;
std::vector<uint8_t>
get_encoded() const
{
return Botan::unlock(key_encoded_);
};

private:
Botan::Dilithium_PrivateKey botan_key() const;

Botan::secure_vector<uint8_t> key_encoded_;
dilithium_parameter_e dilithium_param_;
bool is_initialized_ = false;
};

class pgp_dilithium_public_key_t {
public:
pgp_dilithium_public_key_t(const uint8_t * key_encoded,
size_t key_encoded_len,
dilithium_parameter_e mode);
pgp_dilithium_public_key_t(std::vector<uint8_t> const &key_encoded,
dilithium_parameter_e mode);
pgp_dilithium_public_key_t() = default;

bool operator==(const pgp_dilithium_public_key_t &rhs) const
{
return (dilithium_param_ == rhs.dilithium_param_) && (key_encoded_ == rhs.key_encoded_);
}

bool verify_signature(const uint8_t *msg,
size_t msg_len,
const uint8_t *signature,
size_t signature_len) const;

bool is_valid(rnp::RNG *rng) const;

std::vector<uint8_t>
get_encoded() const
{
return key_encoded_;
};

private:
Botan::Dilithium_PublicKey botan_key() const;

std::vector<uint8_t> key_encoded_;
dilithium_parameter_e dilithium_param_;
bool is_initialized_ = false;
};

std::pair<pgp_dilithium_public_key_t, pgp_dilithium_private_key_t> dilithium_generate_keypair(
rnp::RNG *rng, dilithium_parameter_e dilithium_param);

#endif
Loading

0 comments on commit 4fdff8a

Please sign in to comment.