Botan 3.5.0
Crypto and TLS for C&
x448_internal.cpp
Go to the documentation of this file.
1/*
2* X448 Internal
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#include <botan/internal/x448_internal.h>
9
10#include <botan/internal/ct_utils.h>
11#include <botan/internal/curve448_gf.h>
12
13namespace Botan {
14
15namespace {
16uint64_t get_bit(const ScalarX448& scalar, size_t bit) {
17 return (scalar[bit / 8] >> (bit % 8)) & 1;
18}
19} // namespace
20
22 return {p.begin(), p.end()};
23}
24
25Point448 decode_point(std::span<const uint8_t> p_bytes) {
26 BOTAN_ARG_CHECK(p_bytes.size() == X448_LEN, "Invalid size for X448 point");
27 return typecast_copy<Point448>(p_bytes);
28}
29
30ScalarX448 decode_scalar(std::span<const uint8_t> scalar_bytes) {
31 BOTAN_ARG_CHECK(scalar_bytes.size() == X448_LEN, "Invalid size for X448 scalar");
32 auto buf = typecast_copy<ScalarX448>(scalar_bytes);
33
34 buf[0] &= 0xfc;
35 buf[55] |= 0x80;
36
37 return buf;
38}
39
40/// Multiply a scalar with the base group element (5)
42 const Point448 u({5});
43 return x448(k, u);
44}
45
46// Algorithm see RFC 7748, Section 5:
47// https://datatracker.ietf.org/doc/html/rfc7748#section-5
48Point448 x448(const ScalarX448& k, const Point448& u) {
49 const Gf448Elem a24 = 39081;
50
51 Gf448Elem x_1 = Gf448Elem(u.get());
52 Gf448Elem x_2 = 1;
53 Gf448Elem z_2 = 0;
54 Gf448Elem x_3 = Gf448Elem(u.get());
55 Gf448Elem z_3 = 1;
56 auto swap = CT::Mask<uint64_t>::cleared();
57
58 for(int16_t t = 448 - 1; t >= 0; --t) {
59 auto k_t = CT::Mask<uint64_t>::expand(get_bit(k, t));
60 swap ^= k_t;
61
62 x_2.ct_cond_swap(swap.as_bool(), x_3);
63 z_2.ct_cond_swap(swap.as_bool(), z_3);
64 swap = k_t;
65
66 const auto A = x_2 + z_2;
67 const auto AA = square(A);
68 const auto B = x_2 - z_2;
69 const auto BB = square(B);
70 const auto E = AA - BB;
71 const auto C = x_3 + z_3;
72 const auto D = x_3 - z_3;
73 const auto DA = D * A;
74 const auto CB = C * B;
75 x_3 = square(DA + CB);
76 z_3 = x_1 * square(DA - CB);
77 x_2 = AA * BB;
78 z_2 = E * (AA + a24 * E);
79 }
80
81 x_2.ct_cond_swap(swap.as_bool(), x_3);
82 z_2.ct_cond_swap(swap.as_bool(), z_3);
83
84 const auto res = x_2 / z_2;
85
86 return Point448(res.to_bytes());
87}
88
89} // namespace Botan
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:29
static constexpr Mask< T > expand(T v)
Definition ct_utils.h:213
static constexpr Mask< T > cleared()
Definition ct_utils.h:208
void ct_cond_swap(bool b, Gf448Elem &other)
Swap this and other if b == true. Constant time for any b.
decltype(auto) begin() noexcept(noexcept(this->get().begin()))
Definition strong_type.h:99
decltype(auto) end() noexcept(noexcept(this->get().end()))
secure_vector< uint8_t > encode_point(const Point448 &p)
Encode a point to a 56 byte vector. RFC 7748 Section 5 (encodeUCoordinate)
BigInt square(const BigInt &x)
Definition numthry.cpp:157
constexpr void typecast_copy(ToR &&out, FromR &&in)
Definition mem_ops.h:178
Point448 x448_basepoint(const ScalarX448 &k)
Multiply a scalar with the base group element (5)
Strong< std::array< uint8_t, X448_LEN >, struct Point448_ > Point448
Strong< std::array< uint8_t, X448_LEN >, struct ScalarX448_ > ScalarX448
constexpr size_t X448_LEN
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:61
Point448 x448(const ScalarX448 &k, const Point448 &u)
Multiply a scalar k with a point u.
Point448 decode_point(std::span< const uint8_t > p_bytes)
Decode a point from a byte array. RFC 7748 Section 5 (decodeUCoordinate)
ScalarX448 decode_scalar(std::span< const uint8_t > scalar_bytes)
Decode a scalar from a byte array. RFC 7748 Section 5 (decodeScalar448)