Skip to content

Commit

Permalink
Merge pull request #3679 from Rohde-Schwarz/pqc/frodokem
Browse files Browse the repository at this point in the history
PQC: FrodoKEM
  • Loading branch information
reneme authored Jan 4, 2024
2 parents 700202b + c256e53 commit a2cb135
Show file tree
Hide file tree
Showing 30 changed files with 4,187 additions and 13 deletions.
8 changes: 7 additions & 1 deletion doc/api_ref/pubkey.rst
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ Post-quantum secure signature scheme based on lattice problems.
Kyber
~~~~~~~~~~~

Post-quantum key encapsulation scheme based on lattices.
Post-quantum key encapsulation scheme based on (structured) lattices.

.. note::

Expand Down Expand Up @@ -131,6 +131,11 @@ security of a hash function. Unlike XMSS, it is a stateless signature
scheme, meaning that the private key does not change with each signature. It
has high security but very long signatures and high runtime.

FrodoKEM
~~~~~~~~

A post-quantum secure key encapsulation scheme based on (unstructured) lattices.

McEliece
~~~~~~~~~~

Expand Down Expand Up @@ -1121,6 +1126,7 @@ Botan implements the following KEM schemes:

1. RSA
#. Kyber
#. FrodoKEM
#. McEliece

.. _kyber_example:
Expand Down
18 changes: 18 additions & 0 deletions doc/dev_ref/oids.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,24 @@ Values currently assigned are::
-- { publicKey 5 } previously used for XMSS draft 6
gost-3410-with-sha256 OBJECT IDENTIFIER ::= { publicKey 6 1 }

frodokem-shake OBJECT IDENTIFIER ::= { publicKey 14 }
efrodokem-shake OBJECT IDENTIFIER ::= { publicKey 16 }
frodokem-aes OBJECT IDENTIFIER ::= { publicKey 15 }
efrodokem-aes OBJECT IDENTIFIER ::= { publicKey 17 }

frodokem-640-shake OBJECT_IDENTIFIER : { frodokem-shake 1 }
frodokem-976-shake OBJECT_IDENTIFIER : { frodokem-shake 2 }
frodokem-1344-shake OBJECT_IDENTIFIER : { frodokem-shake 3 }
frodokem-640-aes OBJECT_IDENTIFIER : { frodokem-aes 1 }
frodokem-976-aes OBJECT_IDENTIFIER : { frodokem-aes 2 }
frodokem-1344-aes OBJECT_IDENTIFIER : { frodokem-aes 3 }
efrodokem-640-shake OBJECT_IDENTIFIER : { efrodokem-shake 1 }
efrodokem-976-shake OBJECT_IDENTIFIER : { efrodokem-shake 2 }
efrodokem-1344-shake OBJECT_IDENTIFIER : { efrodokem-shake 3 }
efrodokem-640-aes OBJECT_IDENTIFIER : { efrodokem-aes 1 }
efrodokem-976-aes OBJECT_IDENTIFIER : { efrodokem-aes 2 }
efrodokem-1344-aes OBJECT_IDENTIFIER : { efrodokem-aes 3 }

kyber OBJECT IDENTIFIER ::= { publicKey 7 }
kyber-90s OBJECT IDENTIFIER ::= { publicKey 11 }

Expand Down
18 changes: 16 additions & 2 deletions src/build-data/oids.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Regenerate with ./src/scripts/oids.py oids > src/lib/asn1/oid_maps.cpp
# AND ./src/scripts/oids.py dn_ub > src/lib/x509/x509_dn_ub.cpp
# Regenerate with ./src/scripts/dev_tools/oids.py oids > src/lib/asn1/oid_maps.cpp
# AND ./src/scripts/dev_tools/oids.py dn_ub > src/lib/x509/x509_dn_ub.cpp
# (if you modified something under [dn]

# Public key types
Expand All @@ -13,6 +13,20 @@
1.3.101.110 = Curve25519
1.3.101.112 = Ed25519

# FrodoKEM OIDs are currently in Botan's private arc
1.3.6.1.4.1.25258.1.14.1 = FrodoKEM-640-SHAKE
1.3.6.1.4.1.25258.1.14.2 = FrodoKEM-976-SHAKE
1.3.6.1.4.1.25258.1.14.3 = FrodoKEM-1344-SHAKE
1.3.6.1.4.1.25258.1.15.1 = FrodoKEM-640-AES
1.3.6.1.4.1.25258.1.15.2 = FrodoKEM-976-AES
1.3.6.1.4.1.25258.1.15.3 = FrodoKEM-1344-AES
1.3.6.1.4.1.25258.1.16.1 = eFrodoKEM-640-SHAKE
1.3.6.1.4.1.25258.1.16.2 = eFrodoKEM-976-SHAKE
1.3.6.1.4.1.25258.1.16.3 = eFrodoKEM-1344-SHAKE
1.3.6.1.4.1.25258.1.17.1 = eFrodoKEM-640-AES
1.3.6.1.4.1.25258.1.17.2 = eFrodoKEM-976-AES
1.3.6.1.4.1.25258.1.17.3 = eFrodoKEM-1344-AES

# Kyber OIDs are currently in Botan's private arc
1.3.6.1.4.1.25258.1.7.1 = Kyber-512-r3
1.3.6.1.4.1.25258.1.7.2 = Kyber-768-r3
Expand Down
47 changes: 46 additions & 1 deletion src/cli/speed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,10 @@
#include <botan/sphincsplus.h>
#endif

#if defined(BOTAN_HAS_FRODOKEM)
#include <botan/frodokem.h>
#endif

#if defined(BOTAN_HAS_ECDSA)
#include <botan/ecdsa.h>
#endif
Expand Down Expand Up @@ -404,7 +408,8 @@ class Speed final : public Command {
"Curve25519",
"McEliece",
"Kyber",
"SPHINCS+"
"SPHINCS+",
"FrodoKEM"
};
// clang-format on
}
Expand Down Expand Up @@ -614,6 +619,11 @@ class Speed final : public Command {
bench_sphincs_plus(provider, msec);
}
#endif
#if defined(BOTAN_HAS_FRODOKEM)
else if(algo == "FrodoKEM") {
bench_frodokem(provider, msec);
}
#endif
#if defined(BOTAN_HAS_SCRYPT)
else if(algo == "scrypt") {
bench_scrypt(provider, msec);
Expand Down Expand Up @@ -2037,6 +2047,41 @@ class Speed final : public Command {
}
#endif

#if defined(BOTAN_HAS_FRODOKEM)
void bench_frodokem(const std::string& provider, std::chrono::milliseconds msec) {
std::vector<Botan::FrodoKEMMode> frodo_modes{
Botan::FrodoKEMMode::FrodoKEM640_SHAKE,
Botan::FrodoKEMMode::FrodoKEM976_SHAKE,
Botan::FrodoKEMMode::FrodoKEM1344_SHAKE,
Botan::FrodoKEMMode::eFrodoKEM640_SHAKE,
Botan::FrodoKEMMode::eFrodoKEM976_SHAKE,
Botan::FrodoKEMMode::eFrodoKEM1344_SHAKE,
Botan::FrodoKEMMode::FrodoKEM640_AES,
Botan::FrodoKEMMode::FrodoKEM976_AES,
Botan::FrodoKEMMode::FrodoKEM1344_AES,
Botan::FrodoKEMMode::eFrodoKEM640_AES,
Botan::FrodoKEMMode::eFrodoKEM976_AES,
Botan::FrodoKEMMode::eFrodoKEM1344_AES,
};

for(auto modet : frodo_modes) {
if(!modet.is_available()) {
continue;
}

Botan::FrodoKEMMode mode(modet);

auto keygen_timer = make_timer(mode.to_string(), provider, "keygen");

auto key = keygen_timer->run([&] { return Botan::FrodoKEM_PrivateKey(rng(), mode); });

record_result(keygen_timer);

bench_pk_kem(key, mode.to_string(), provider, "KDF2(SHA-256)", msec);
}
}
#endif

#if defined(BOTAN_HAS_XMSS_RFC8391)
void bench_xmss(const std::string& provider, std::chrono::milliseconds msec) {
/*
Expand Down
26 changes: 25 additions & 1 deletion src/lib/asn1/oid_maps.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* OID maps
*
* This file was automatically generated by src/scripts/dev_tools/gen_oids.py on 2023-05-30
* This file was automatically generated by ./src/scripts/dev_tools/gen_oids.py on 2023-11-02
*
* All manual edits to this file will be lost. Edit the script
* then regenerate this source file.
Expand Down Expand Up @@ -162,6 +162,18 @@ std::unordered_map<std::string, std::string> OID_Map::load_oid2str_map() {
{"1.3.6.1.4.1.25258.1.12.3.4", "SphincsPlus-haraka-192f-r3.1"},
{"1.3.6.1.4.1.25258.1.12.3.5", "SphincsPlus-haraka-256s-r3.1"},
{"1.3.6.1.4.1.25258.1.12.3.6", "SphincsPlus-haraka-256f-r3.1"},
{"1.3.6.1.4.1.25258.1.14.1", "FrodoKEM-640-SHAKE"},
{"1.3.6.1.4.1.25258.1.14.2", "FrodoKEM-976-SHAKE"},
{"1.3.6.1.4.1.25258.1.14.3", "FrodoKEM-1344-SHAKE"},
{"1.3.6.1.4.1.25258.1.15.1", "FrodoKEM-640-AES"},
{"1.3.6.1.4.1.25258.1.15.2", "FrodoKEM-976-AES"},
{"1.3.6.1.4.1.25258.1.15.3", "FrodoKEM-1344-AES"},
{"1.3.6.1.4.1.25258.1.16.1", "eFrodoKEM-640-SHAKE"},
{"1.3.6.1.4.1.25258.1.16.2", "eFrodoKEM-976-SHAKE"},
{"1.3.6.1.4.1.25258.1.16.3", "eFrodoKEM-1344-SHAKE"},
{"1.3.6.1.4.1.25258.1.17.1", "eFrodoKEM-640-AES"},
{"1.3.6.1.4.1.25258.1.17.2", "eFrodoKEM-976-AES"},
{"1.3.6.1.4.1.25258.1.17.3", "eFrodoKEM-1344-AES"},
{"1.3.6.1.4.1.25258.1.3", "McEliece"},
{"1.3.6.1.4.1.25258.1.5", "XMSS-draft6"},
{"1.3.6.1.4.1.25258.1.6.1", "GOST-34.10-2012-256/SHA-256"},
Expand Down Expand Up @@ -367,6 +379,12 @@ std::unordered_map<std::string, OID> OID_Map::load_str2oid_map() {
{"ECKCDSA/SHA-256", OID({1, 2, 410, 200004, 1, 100, 4, 5})},
{"Ed25519", OID({1, 3, 101, 112})},
{"ElGamal", OID({1, 3, 6, 1, 4, 1, 3029, 1, 2, 1})},
{"FrodoKEM-1344-AES", OID({1, 3, 6, 1, 4, 1, 25258, 1, 15, 3})},
{"FrodoKEM-1344-SHAKE", OID({1, 3, 6, 1, 4, 1, 25258, 1, 14, 3})},
{"FrodoKEM-640-AES", OID({1, 3, 6, 1, 4, 1, 25258, 1, 15, 1})},
{"FrodoKEM-640-SHAKE", OID({1, 3, 6, 1, 4, 1, 25258, 1, 14, 1})},
{"FrodoKEM-976-AES", OID({1, 3, 6, 1, 4, 1, 25258, 1, 15, 2})},
{"FrodoKEM-976-SHAKE", OID({1, 3, 6, 1, 4, 1, 25258, 1, 14, 2})},
{"GOST-34.10", OID({1, 2, 643, 2, 2, 19})},
{"GOST-34.10-2012-256", OID({1, 2, 643, 7, 1, 1, 1, 1})},
{"GOST-34.10-2012-256/SHA-256", OID({1, 3, 6, 1, 4, 1, 25258, 1, 6, 1})},
Expand Down Expand Up @@ -540,6 +558,12 @@ std::unordered_map<std::string, OID> OID_Map::load_str2oid_map() {
{"brainpool320r1", OID({1, 3, 36, 3, 3, 2, 8, 1, 1, 9})},
{"brainpool384r1", OID({1, 3, 36, 3, 3, 2, 8, 1, 1, 11})},
{"brainpool512r1", OID({1, 3, 36, 3, 3, 2, 8, 1, 1, 13})},
{"eFrodoKEM-1344-AES", OID({1, 3, 6, 1, 4, 1, 25258, 1, 17, 3})},
{"eFrodoKEM-1344-SHAKE", OID({1, 3, 6, 1, 4, 1, 25258, 1, 16, 3})},
{"eFrodoKEM-640-AES", OID({1, 3, 6, 1, 4, 1, 25258, 1, 17, 1})},
{"eFrodoKEM-640-SHAKE", OID({1, 3, 6, 1, 4, 1, 25258, 1, 16, 1})},
{"eFrodoKEM-976-AES", OID({1, 3, 6, 1, 4, 1, 25258, 1, 17, 2})},
{"eFrodoKEM-976-SHAKE", OID({1, 3, 6, 1, 4, 1, 25258, 1, 16, 2})},
{"frp256v1", OID({1, 2, 250, 1, 223, 101, 256, 1})},
{"gost_256A", OID({1, 2, 643, 7, 1, 2, 1, 1, 1})},
{"gost_256B", OID({1, 2, 643, 7, 1, 2, 1, 1, 2})},
Expand Down
40 changes: 40 additions & 0 deletions src/lib/pubkey/frodokem/frodokem/frodo_shake_generator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* FrodoKEM matrix generator based on SHAKE
*
* The Fellowship of the FrodoKEM:
* (C) 2023 Jack Lloyd
* 2023 René Meusel, Amos Treiber - Rohde & Schwarz Cybersecurity
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#ifndef BOTAN_FRODOKEM_SHAKE_GENERATOR_H_
#define BOTAN_FRODOKEM_SHAKE_GENERATOR_H_

#include <botan/internal/frodo_constants.h>
#include <botan/internal/frodo_types.h>
#include <botan/internal/loadstor.h>
#include <botan/internal/shake_xof.h>

#include <span>

namespace Botan {

inline auto create_shake_row_generator(const FrodoKEMConstants& constants, StrongSpan<const FrodoSeedA> seed_a) {
BOTAN_ASSERT_NOMSG(constants.mode().is_shake());

return [xof = SHAKE_128_XOF(), a = FrodoSeedA(seed_a)](std::span<uint8_t> out, uint16_t i) mutable {
xof.clear();
// TODO: update that once #3707 is merged
// potentially add a new method: std::array<uint8_t, XX> as_le(uintXX_t)
std::array<uint8_t, 2> le;
store_le(i, le.data());
xof.update(le);
xof.update(a);
xof.output(out);
};
}

} // namespace Botan

#endif
12 changes: 12 additions & 0 deletions src/lib/pubkey/frodokem/frodokem/info.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<defines>
FRODOKEM_SHAKE -> 20231114
</defines>

<module_info>
name -> "FrodoKEM"
</module_info>

<requires>
shake_xof
frodokem_common
</requires>
56 changes: 56 additions & 0 deletions src/lib/pubkey/frodokem/frodokem_aes/frodo_aes_generator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* FrodoKEM matrix generator based on AES
*
* The Fellowship of the FrodoKEM:
* (C) 2023 Jack Lloyd
* 2023 René Meusel, Amos Treiber - Rohde & Schwarz Cybersecurity
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#ifndef BOTAN_FRODOKEM_AES_GENERATOR_H_
#define BOTAN_FRODOKEM_AES_GENERATOR_H_

#include <botan/internal/aes.h>
#include <botan/internal/frodo_constants.h>
#include <botan/internal/frodo_types.h>
#include <botan/internal/loadstor.h>
#include <botan/internal/stl_util.h>

#include <functional>
#include <span>

namespace Botan {

inline auto create_aes_row_generator(const FrodoKEMConstants& constants, StrongSpan<const FrodoSeedA> seed_a) {
BOTAN_ASSERT_NOMSG(constants.mode().is_aes());

auto setup_aes = [](StrongSpan<const FrodoSeedA> seed) {
AES_128 aes;
aes.set_key(seed);
return aes;
};

return [n = constants.n(), aes = setup_aes(seed_a)](std::span<uint8_t> out, uint16_t i) {
BufferStuffer out_bs(out);

for(size_t j = 0; j < n; j += 8) {
// set up the to-be-encrypted 'b' value in the out variable
// for in-place encryption of the block cipher
auto out_coefs = out_bs.next(aes.block_size());

// b = i || j || 0000...
store_le(static_cast<uint16_t>(i), out_coefs.data());
store_le(static_cast<uint16_t>(j), out_coefs.data() + sizeof(uint16_t));
for(size_t ii = 4; ii < out_coefs.size(); ++ii) {
out_coefs[ii] = 0;
}

aes.encrypt(out_coefs);
}
};
}

} // namespace Botan

#endif
12 changes: 12 additions & 0 deletions src/lib/pubkey/frodokem/frodokem_aes/info.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<defines>
FRODOKEM_AES -> 20231103
</defines>

<module_info>
name -> "FrodoKEM (AES)"
</module_info>

<requires>
aes
frodokem_common
</requires>
Loading

0 comments on commit a2cb135

Please sign in to comment.