Skip to content

Commit

Permalink
Merge pull request #4190 from randombit/jack/pcurves-p192
Browse files Browse the repository at this point in the history
Add P-192 to pcurves
  • Loading branch information
randombit authored Jul 15, 2024
2 parents 5d42faa + 1648716 commit 5fd660b
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 1 deletion.
16 changes: 15 additions & 1 deletion src/lib/math/pcurves/pcurves.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@

namespace Botan::PCurve {

#if !defined(BOTAN_HAS_PCURVES_SECP192R1)
//static
std::shared_ptr<const PrimeOrderCurve> PCurveInstance::secp192r1() {
return nullptr;
}
#endif

#if !defined(BOTAN_HAS_PCURVES_SECP256R1)
//static
std::shared_ptr<const PrimeOrderCurve> PCurveInstance::secp256r1() {
Expand Down Expand Up @@ -79,6 +86,8 @@ std::shared_ptr<const PrimeOrderCurve> PCurveInstance::sm2p256v1() {

std::shared_ptr<const PrimeOrderCurve> PrimeOrderCurve::from_id(PrimeOrderCurveId id) {
switch(id.code()) {
case PrimeOrderCurveId::secp192r1:
return PCurveInstance::secp192r1();
case PrimeOrderCurveId::secp256r1:
return PCurveInstance::secp256r1();
case PrimeOrderCurveId::secp384r1:
Expand All @@ -103,6 +112,7 @@ std::shared_ptr<const PrimeOrderCurve> PrimeOrderCurve::from_id(PrimeOrderCurveI

std::vector<PrimeOrderCurveId> PrimeOrderCurveId::all() {
return {
PrimeOrderCurveId::secp192r1,
PrimeOrderCurveId::secp256r1,
PrimeOrderCurveId::secp384r1,
PrimeOrderCurveId::secp521r1,
Expand All @@ -117,6 +127,8 @@ std::vector<PrimeOrderCurveId> PrimeOrderCurveId::all() {

std::string PrimeOrderCurveId::to_string() const {
switch(this->code()) {
case PrimeOrderCurveId::secp192r1:
return "secp192r1";
case PrimeOrderCurveId::secp256r1:
return "secp256r1";
case PrimeOrderCurveId::secp384r1:
Expand All @@ -142,7 +154,9 @@ std::string PrimeOrderCurveId::to_string() const {

//static
std::optional<PrimeOrderCurveId> PrimeOrderCurveId::from_string(std::string_view name) {
if(name == "secp256r1") {
if(name == "secp192r1") {
return PCurve::PrimeOrderCurveId::secp192r1;
} else if(name == "secp256r1") {
return PCurve::PrimeOrderCurveId::secp256r1;
} else if(name == "secp384r1") {
return PCurve::PrimeOrderCurveId::secp384r1;
Expand Down
2 changes: 2 additions & 0 deletions src/lib/math/pcurves/pcurves_id.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ namespace Botan::PCurve {
class BOTAN_TEST_API PrimeOrderCurveId final {
public:
enum class Code : uint8_t {
/// secp192r1 aka P-192
secp192r1,
/// secp256r1 aka P-256
secp256r1,
/// secp384r1 aka P-384
Expand Down
2 changes: 2 additions & 0 deletions src/lib/math/pcurves/pcurves_instance.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ class PCurveInstance final {
* provided in pcurves_instance.cpp that returns a nullptr
*/

static std::shared_ptr<const PrimeOrderCurve> secp192r1();

static std::shared_ptr<const PrimeOrderCurve> secp256r1();

static std::shared_ptr<const PrimeOrderCurve> secp384r1();
Expand Down
13 changes: 13 additions & 0 deletions src/lib/math/pcurves/pcurves_secp192r1/info.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<defines>
PCURVES_SECP192R1 -> 20240709
</defines>

<module_info>
name -> "PCurve secp192r1"
brief -> "secp192r1"
type -> "Internal"
</module_info>

<requires>
pcurves_impl
</requires>
127 changes: 127 additions & 0 deletions src/lib/math/pcurves/pcurves_secp192r1/pcurves_secp192r1.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*
* (C) 2024 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/internal/pcurves_instance.h>

#include <botan/internal/pcurves_solinas.h>
#include <botan/internal/pcurves_wrap.h>

namespace Botan::PCurve {

namespace {

namespace secp192r1 {

template <typename Params>
class Secp192r1Rep final {
public:
static constexpr auto P = Params::P;
static constexpr size_t N = Params::N;
typedef typename Params::W W;

constexpr static std::array<W, N> redc(const std::array<W, 2 * N>& z) {
const int64_t X00 = get_uint32(z.data(), 0);
const int64_t X01 = get_uint32(z.data(), 1);
const int64_t X02 = get_uint32(z.data(), 2);
const int64_t X03 = get_uint32(z.data(), 3);
const int64_t X04 = get_uint32(z.data(), 4);
const int64_t X05 = get_uint32(z.data(), 5);
const int64_t X06 = get_uint32(z.data(), 6);
const int64_t X07 = get_uint32(z.data(), 7);
const int64_t X08 = get_uint32(z.data(), 8);
const int64_t X09 = get_uint32(z.data(), 9);
const int64_t X10 = get_uint32(z.data(), 10);
const int64_t X11 = get_uint32(z.data(), 11);

const int64_t S0 = X00 + X06 + X10;
const int64_t S1 = X01 + X07 + X11;
const int64_t S2 = X02 + X06 + X08 + X10;
const int64_t S3 = X03 + X07 + X09 + X11;
const int64_t S4 = X04 + X08 + X10;
const int64_t S5 = X05 + X09 + X11;

std::array<W, N> r = {};

SolinasAccum sum(r);

sum.accum(S0);
sum.accum(S1);
sum.accum(S2);
sum.accum(S3);
sum.accum(S4);
sum.accum(S5);
const auto S = sum.final_carry(0);

BOTAN_DEBUG_ASSERT(S <= 3);

const auto correction = p192_mul_mod_192(S);
W borrow = bigint_sub2(r.data(), N, correction.data(), N);

bigint_cnd_add(borrow, r.data(), N, P.data(), N);

return r;
}

constexpr static std::array<W, N> one() { return std::array<W, N>{1}; }

constexpr static std::array<W, N> to_rep(const std::array<W, N>& x) { return x; }

constexpr static std::array<W, N> wide_to_rep(const std::array<W, 2 * N>& x) { return redc(x); }

constexpr static std::array<W, N> from_rep(const std::array<W, N>& z) { return z; }

private:
// Return (i*P-192) % 2**192
//
// Assumes i is small
constexpr static std::array<W, N> p192_mul_mod_192(W i) {
static_assert(WordInfo<W>::bits == 32 || WordInfo<W>::bits == 64);

// For small i, multiples of P-192 have a simple structure so it's faster to
// compute the value directly vs a (constant time) table lookup

auto r = P;

if constexpr(WordInfo<W>::bits == 32) {
r[2] -= i;
r[0] -= i;
} else {
r[1] -= i;
r[0] -= i;
}
return r;
}
};

// clang-format off
class Params final : public EllipticCurveParameters<
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
"64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1",
"FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831",
"188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012",
"07192B95FFC8DA78631011ED6B24CDD573F977A11E794811"> {
};

// clang-format on

#if BOTAN_MP_WORD_BITS == 32
// Secp192r1Rep works for 64 bit also, but is at best marginally faster at least
// on compilers/CPUs tested so far
class Curve final : public EllipticCurve<Params, Secp192r1Rep> {};
#else
class Curve final : public EllipticCurve<Params> {};
#endif

} // namespace secp192r1

} // namespace

std::shared_ptr<const PrimeOrderCurve> PCurveInstance::secp192r1() {
return PrimeOrderCurveImpl<secp192r1::Curve>::instance();
}

} // namespace Botan::PCurve

0 comments on commit 5fd660b

Please sign in to comment.