Botan 3.12.0
Crypto and TLS for C&
x448.cpp
Go to the documentation of this file.
1/*
2* X448
3* (C) 2024 Jack Lloyd
4* 2024 Fabian Albert - Rohde & Schwarz Cybersecurity
5*
6* Botan is released under the Simplified BSD License (see license.txt)
7*/
8
9#include <botan/x448.h>
10
11#include <botan/ber_dec.h>
12#include <botan/der_enc.h>
13#include <botan/mem_ops.h>
14#include <botan/rng.h>
15#include <botan/internal/ct_utils.h>
16#include <botan/internal/pk_ops_impl.h>
17#include <botan/internal/x448_internal.h>
18
19namespace Botan {
20
21namespace {
22void x448_basepoint_from_data(std::span<uint8_t, X448_LEN> mypublic, std::span<const uint8_t, X448_LEN> secret) {
23 auto bp = x448_basepoint(decode_scalar(secret));
24 auto bp_bytes = encode_point(bp);
25 copy_mem(mypublic, bp_bytes);
26}
27
28secure_vector<uint8_t> ber_decode_sk(std::span<const uint8_t> key_bits) {
29 secure_vector<uint8_t> decoded_bits;
31 if(decoded_bits.size() != X448_LEN) {
32 throw Decoding_Error("Invalid size for X448 private key");
33 }
34 return decoded_bits;
35}
36
37} // namespace
38
42
43bool X448_PublicKey::check_key(RandomNumberGenerator& /*rng*/, bool /*strong*/) const {
44 return true; // no tests possible?
45}
46
47std::vector<uint8_t> X448_PublicKey::raw_public_key_bits() const {
48 return {m_public.begin(), m_public.end()};
49}
50
51std::vector<uint8_t> X448_PublicKey::public_key_bits() const {
52 return raw_public_key_bits();
53}
54
55std::unique_ptr<Private_Key> X448_PublicKey::generate_another(RandomNumberGenerator& rng) const {
56 return std::make_unique<X448_PrivateKey>(rng);
57}
58
59X448_PublicKey::X448_PublicKey(const AlgorithmIdentifier& /*alg_id*/, std::span<const uint8_t> key_bits) :
60 X448_PublicKey(key_bits) {}
61
62X448_PublicKey::X448_PublicKey(std::span<const uint8_t> pub) {
63 BOTAN_ARG_CHECK(pub.size() == X448_LEN, "Invalid size for X448 public key");
64 copy_mem(m_public, pub);
65}
66
67X448_PrivateKey::X448_PrivateKey(const AlgorithmIdentifier& /*alg_id*/, std::span<const uint8_t> key_bits) :
68 X448_PrivateKey(ber_decode_sk(key_bits)) {}
69
70X448_PrivateKey::X448_PrivateKey(std::span<const uint8_t> secret_key) {
71 BOTAN_ARG_CHECK(secret_key.size() == X448_LEN, "Invalid size for X448 private key");
72 m_private.assign(secret_key.begin(), secret_key.end());
73 auto scope = CT::scoped_poison(m_private);
74 x448_basepoint_from_data(m_public, std::span(m_private).first<X448_LEN>());
76}
77
79
80std::unique_ptr<Public_Key> X448_PrivateKey::public_key() const {
81 return std::make_unique<X448_PublicKey>(public_value());
82}
83
87
88bool X448_PrivateKey::check_key(RandomNumberGenerator& /*rng*/, bool /*strong*/) const {
89 std::array<uint8_t, X448_LEN> public_point{};
90 BOTAN_ASSERT_NOMSG(m_private.size() == X448_LEN);
91 auto scope = CT::scoped_poison(m_private);
92 x448_basepoint_from_data(public_point, std::span(m_private).first<X448_LEN>());
93 return CT::is_equal(public_point.data(), m_public.data(), m_public.size()).as_bool();
94}
95
96namespace {
97
98/**
99* X448 operation
100*/
101class X448_KA_Operation final : public PK_Ops::Key_Agreement_with_KDF {
102 public:
103 X448_KA_Operation(std::span<const uint8_t> sk, std::string_view kdf) :
104 PK_Ops::Key_Agreement_with_KDF(kdf), m_sk(sk.begin(), sk.end()) {
105 BOTAN_ARG_CHECK(sk.size() == X448_LEN, "Invalid size for X448 private key");
106 }
107
108 size_t agreed_value_size() const override { return X448_LEN; }
109
110 secure_vector<uint8_t> raw_agree(const uint8_t w_data[], size_t w_len) override {
111 auto scope = CT::scoped_poison(m_sk);
112
113 const std::span<const uint8_t> w(w_data, w_len);
114 if(w.size() != X448_LEN) {
115 throw Decoding_Error("Invalid size for X448 public key");
116 }
117 const auto k = decode_scalar(m_sk);
118 const auto u = decode_point(w);
119
120 auto shared_secret = encode_point(x448(k, u));
121 CT::unpoison(shared_secret);
122
123 // RFC 7748 Section 6.2
124 // As with X25519, both sides MAY check, without leaking extra
125 // information about the value of K, whether the resulting shared K
126 // is the all-zero value and abort if so.
127 //
128 // TODO: once the generic Key Agreement operation creation is equipped
129 // with a more flexible parameterization, this check could be
130 // made optional.
131 // For instance: `sk->agree().with_optional_sanity_checks(true)`.
132 // See also: https://github.com/randombit/botan/pull/4318
133 if(CT::all_zeros(shared_secret.data(), shared_secret.size()).as_bool()) {
134 throw Invalid_Argument("X448 public point appears to be of low order");
135 }
136
137 return shared_secret;
138 }
139
140 private:
142};
143
144} // namespace
145
146std::unique_ptr<PK_Ops::Key_Agreement> X448_PrivateKey::create_key_agreement_op(RandomNumberGenerator& /*rng*/,
147 std::string_view params,
148 std::string_view provider) const {
149 if(provider == "base" || provider.empty()) {
150 return std::make_unique<X448_KA_Operation>(m_private, params);
151 }
152 throw Provider_Not_Found(algo_name(), provider);
153}
154
155} // namespace Botan
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:33
virtual OID object_identifier() const
Definition pk_keys.cpp:22
static Limits DER()
Definition ber_dec.h:35
BER_Decoder & decode(bool &out)
Definition ber_dec.h:220
BER_Decoder & verify_end()
Definition ber_dec.cpp:381
secure_vector< uint8_t > get_contents()
Definition der_enc.cpp:134
DER_Encoder & encode(bool b)
Definition der_enc.cpp:245
std::unique_ptr< Public_Key > public_key() const override
Definition x448.cpp:80
secure_vector< uint8_t > private_key_bits() const override
Definition x448.cpp:84
X448_PrivateKey(const AlgorithmIdentifier &alg_id, std::span< const uint8_t > key_bits)
Definition x448.cpp:67
std::vector< uint8_t > public_value() const override
Definition x448.h:90
std::unique_ptr< PK_Ops::Key_Agreement > create_key_agreement_op(RandomNumberGenerator &rng, std::string_view params, std::string_view provider) const override
Definition x448.cpp:146
bool check_key(RandomNumberGenerator &rng, bool strong) const override
Definition x448.cpp:88
AlgorithmIdentifier algorithm_identifier() const override
Definition x448.cpp:39
std::unique_ptr< Private_Key > generate_another(RandomNumberGenerator &rng) const final
Definition x448.cpp:55
std::vector< uint8_t > raw_public_key_bits() const override
Definition x448.cpp:47
std::array< uint8_t, 56 > m_public
Definition x448.h:58
bool check_key(RandomNumberGenerator &rng, bool strong) const override
Definition x448.cpp:43
X448_PublicKey(const AlgorithmIdentifier &alg_id, std::span< const uint8_t > key_bits)
Definition x448.cpp:59
std::vector< uint8_t > public_key_bits() const override
Definition x448.cpp:51
std::string algo_name() const override
Definition x448.h:34
constexpr auto scoped_poison(const Ts &... xs)
Definition ct_utils.h:222
constexpr CT::Mask< T > is_equal(const T x[], const T y[], size_t len)
Definition ct_utils.h:798
constexpr void unpoison(const T *p, size_t n)
Definition ct_utils.h:67
constexpr CT::Mask< T > all_zeros(const T elem[], size_t len)
Definition ct_utils.h:785
Point448 x448_basepoint(const ScalarX448 &k)
Multiply a scalar with the base group element (5).
constexpr void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:144
Point448 decode_point(std::span< const uint8_t > p_bytes)
Decode a point from a byte array. RFC 7748 Section 5 (decodeUCoordinate).
constexpr size_t X448_LEN
secure_vector< uint8_t > encode_point(const Point448 &p)
Encode a point to a 56 byte vector. RFC 7748 Section 5 (encodeUCoordinate).
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:68
ScalarX448 decode_scalar(std::span< const uint8_t > scalar_bytes)
Decode a scalar from a byte array. RFC 7748 Section 5 (decodeScalar448).
Point448 x448(const ScalarX448 &k, const Point448 &u)
Multiply a scalar k with a point u.