Skip to content

Commit

Permalink
Classic McEliece implementation
Browse files Browse the repository at this point in the history
This is an implementation of the Classic McEliece KEM according to the
NIST Round 4 submission and the ISO draft 20230419.

Co-Authored-By: Amos Treiber <[email protected]>
  • Loading branch information
FAlbertDev and atreiber94 committed Jan 19, 2024
1 parent 8ca673c commit 04b9314
Show file tree
Hide file tree
Showing 31 changed files with 4,022 additions and 4 deletions.
48 changes: 48 additions & 0 deletions doc/api_ref/pubkey.rst
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,11 @@ McEliece
Post-quantum secure key encapsulation scheme based on the hardness of certain
decoding problems.

Classic McEliece
~~~~~~~~~~~~~~~~

Post-quantum secure, code-based key encapsulation scheme.

ElGamal
~~~~~~~~

Expand Down Expand Up @@ -1128,6 +1133,7 @@ Botan implements the following KEM schemes:
#. Kyber
#. FrodoKEM
#. McEliece
#. Classic McEliece

.. _kyber_example:

Expand Down Expand Up @@ -1193,6 +1199,48 @@ parameters n and t, and have the corresponding key sizes listed:
You can check the speed of McEliece with the suggested parameters above
using ``botan speed McEliece``

Classic McEliece KEM
--------------------

`Classic McEliece <https://classic.mceliece.org/>`_ is an IND-CCA2 secure key
encapsulation algorithm based on the McEliece cryptosystem introduced in 1978.
It is a code-based scheme that relies on conservative security assumptions and
is considered secure against quantum computers. It is an alternative to
lattice-based schemes.

Other advantages of Classic McEliece are the small ciphertext size and the fast
encapsulation. Key generation and decapsulation are slower than in lattice-based
schemes. The main disadvantage of Classic McEliece is the large public key size,
ranging from 0.26 MB to 1.36 MB, depending on the instance. Due to its large key
size, Classic McEliece is recommended for applications where the public key is
stored for a long time, and memory is not a critical resource. Usage with
ephemeral keys is not recommended.

Botan's implementation covers the parameter sets of the `NIST round 4
specification <https://classic.mceliece.org/mceliece-spec-20221023.pdf#page=15>`_
and the `Classic McEliece ISO draft specification
<https://classic.mceliece.org/iso-mceliece-20230419.pdf#page=13>`_.
These are the following:

+------------------+-------------------+-------------------+--------------------+-------------------+
| Set without f/pc | Set with f | Set with pc | Set with pcf | Public Key Size |
+==================+===================+===================+====================+===================+
| mceliece348864 | mceliece348864f | | | 0.26 MB |
+------------------+-------------------+-------------------+--------------------+-------------------+
| mceliece460896 | mceliece460896f | | | 0.52 MB |
+------------------+-------------------+-------------------+--------------------+-------------------+
| mceliece6688128 | mceliece6688128f | mceliece6688128pc | mceliece6688128pcf | 1.04 MB |
+------------------+-------------------+-------------------+--------------------+-------------------+
| mceliece6960119 | mceliece6960119f | mceliece6960119pc | mceliece6960119pcf | 1.05 MB |
+------------------+-------------------+-------------------+--------------------+-------------------+
| mceliece8192128 | mceliece8192128f | mceliece8192128pc | mceliece8192128pcf | 1.36 MB |
+------------------+-------------------+-------------------+--------------------+-------------------+

The instances with the suffix 'f' use a faster key generation algorithm that is more consistent in
runtime. The instances with the suffix 'pc' use plaintext confirmation, which is only specified in
the ISO document. The instances mceliece348864(f) and mceliece460896(f) are only defined in the
NIST round 4 submission.


eXtended Merkle Signature Scheme (XMSS)
----------------------------------------
Expand Down
19 changes: 19 additions & 0 deletions doc/dev_ref/oids.rst
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,25 @@ Values currently assigned are::
SphincsPlus-haraka-256s-r3.1 OBJECT IDENTIFIER ::= { SphincsPlus-haraka 5 }
SphincsPlus-haraka-256f-r3.1 OBJECT IDENTIFIER ::= { SphincsPlus-haraka 6 }

mceliece OBJECT IDENTIFIER ::= { publicKey 18 }

mceliece348864 OBJECT IDENTIFIER ::= { mceliece 1 }
mceliece348864f OBJECT IDENTIFIER ::= { mceliece 2 }
mceliece460896 OBJECT IDENTIFIER ::= { mceliece 3 }
mceliece460896f OBJECT IDENTIFIER ::= { mceliece 4 }
mceliece6688128 OBJECT IDENTIFIER ::= { mceliece 5 }
mceliece6688128f OBJECT IDENTIFIER ::= { mceliece 6 }
mceliece6688128pc OBJECT IDENTIFIER ::= { mceliece 7 }
mceliece6688128pcf OBJECT IDENTIFIER ::= { mceliece 8 }
mceliece6960119 OBJECT IDENTIFIER ::= { mceliece 9 }
mceliece6960119f OBJECT IDENTIFIER ::= { mceliece 10 }
mceliece6960119pc OBJECT IDENTIFIER ::= { mceliece 11 }
mceliece6960119pcf OBJECT IDENTIFIER ::= { mceliece 12 }
mceliece8192128 OBJECT IDENTIFIER ::= { mceliece 13 }
mceliece8192128f OBJECT IDENTIFIER ::= { mceliece 14 }
mceliece8192128pc OBJECT IDENTIFIER ::= { mceliece 15 }
mceliece8192128pcf OBJECT IDENTIFIER ::= { mceliece 16 }

symmetricKey OBJECT IDENTIFIER ::= { randombit 3 }

ocbModes OBJECT IDENTIFIER ::= { symmetricKey 2 }
Expand Down
24 changes: 21 additions & 3 deletions src/build-data/oids.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 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]
# Regenerate with ./src/scripts/dev_tools/gen_oids.py oids > src/lib/asn1/oid_maps.cpp
# AND ./src/scripts/dev_tools/gen_oids.py dn_ub > src/lib/x509/x509_dn_ub.cpp
# (if you modified something under [dn])

# Public key types
[pubkey]
Expand Down Expand Up @@ -63,6 +63,24 @@
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

# Classic McEliece OIDs are currently in Botan's private arc
1.3.6.1.4.1.25258.1.18.1 = mceliece348864
1.3.6.1.4.1.25258.1.18.2 = mceliece348864f
1.3.6.1.4.1.25258.1.18.3 = mceliece460896
1.3.6.1.4.1.25258.1.18.4 = mceliece460896f
1.3.6.1.4.1.25258.1.18.5 = mceliece6688128
1.3.6.1.4.1.25258.1.18.6 = mceliece6688128f
1.3.6.1.4.1.25258.1.18.7 = mceliece6688128pc
1.3.6.1.4.1.25258.1.18.8 = mceliece6688128pcf
1.3.6.1.4.1.25258.1.18.9 = mceliece6960119
1.3.6.1.4.1.25258.1.18.10 = mceliece6960119f
1.3.6.1.4.1.25258.1.18.11 = mceliece6960119pc
1.3.6.1.4.1.25258.1.18.12 = mceliece6960119pcf
1.3.6.1.4.1.25258.1.18.13 = mceliece8192128
1.3.6.1.4.1.25258.1.18.14 = mceliece8192128f
1.3.6.1.4.1.25258.1.18.15 = mceliece8192128pc
1.3.6.1.4.1.25258.1.18.16 = mceliece8192128pcf

# XMSS
1.3.6.1.4.1.25258.1.5 = XMSS-draft6
1.3.6.1.4.1.25258.1.8 = XMSS-draft12
Expand Down
44 changes: 44 additions & 0 deletions src/cli/speed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@
#include <botan/frodokem.h>
#endif

#if defined(BOTAN_HAS_CLASSICMCELIECE)
#include <botan/cmce.h>
#endif

#if defined(BOTAN_HAS_ECDSA)
#include <botan/ecdsa.h>
#endif
Expand Down Expand Up @@ -624,6 +628,11 @@ class Speed final : public Command {
bench_frodokem(provider, msec);
}
#endif
#if defined(BOTAN_HAS_CLASSICMCELIECE)
else if(algo == "ClassicMcEliece") {
bench_classic_mceliece(provider, msec);
}
#endif
#if defined(BOTAN_HAS_SCRYPT)
else if(algo == "scrypt") {
bench_scrypt(provider, msec);
Expand Down Expand Up @@ -2082,6 +2091,41 @@ class Speed final : public Command {
}
#endif

#if defined(BOTAN_HAS_CLASSICMCELIECE)
void bench_classic_mceliece(const std::string& provider, std::chrono::milliseconds msec) {
std::vector<Botan::Classic_McEliece_Parameter_Set> cmce_param_sets{
Botan::Classic_McEliece_Parameter_Set::mceliece348864,
Botan::Classic_McEliece_Parameter_Set::mceliece348864f,
Botan::Classic_McEliece_Parameter_Set::mceliece460896,
Botan::Classic_McEliece_Parameter_Set::mceliece460896f,
Botan::Classic_McEliece_Parameter_Set::mceliece6688128,
Botan::Classic_McEliece_Parameter_Set::mceliece6688128f,
Botan::Classic_McEliece_Parameter_Set::mceliece6688128pc,
Botan::Classic_McEliece_Parameter_Set::mceliece6688128pcf,
Botan::Classic_McEliece_Parameter_Set::mceliece6960119,
Botan::Classic_McEliece_Parameter_Set::mceliece6960119f,
Botan::Classic_McEliece_Parameter_Set::mceliece6960119pc,
Botan::Classic_McEliece_Parameter_Set::mceliece6960119pcf,
Botan::Classic_McEliece_Parameter_Set::mceliece8192128,
Botan::Classic_McEliece_Parameter_Set::mceliece8192128f,
Botan::Classic_McEliece_Parameter_Set::mceliece8192128pc,
Botan::Classic_McEliece_Parameter_Set::mceliece8192128pcf,
};

for(auto cmce_set : cmce_param_sets) {
auto cmce_set_str = Botan::cmce_str_from_param_set(cmce_set);

auto keygen_timer = make_timer(cmce_set_str, provider, "keygen");

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

record_result(keygen_timer);

bench_pk_kem(key, cmce_set_str, 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
34 changes: 33 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-11-02
* This file was automatically generated by ./src/scripts/dev_tools/gen_oids.py on 2024-01-10
*
* All manual edits to this file will be lost. Edit the script
* then regenerate this source file.
Expand Down Expand Up @@ -174,6 +174,22 @@ std::unordered_map<std::string, std::string> OID_Map::load_oid2str_map() {
{"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.18.1", "mceliece348864"},
{"1.3.6.1.4.1.25258.1.18.10", "mceliece6960119f"},
{"1.3.6.1.4.1.25258.1.18.11", "mceliece6960119pc"},
{"1.3.6.1.4.1.25258.1.18.12", "mceliece6960119pcf"},
{"1.3.6.1.4.1.25258.1.18.13", "mceliece8192128"},
{"1.3.6.1.4.1.25258.1.18.14", "mceliece8192128f"},
{"1.3.6.1.4.1.25258.1.18.15", "mceliece8192128pc"},
{"1.3.6.1.4.1.25258.1.18.16", "mceliece8192128pcf"},
{"1.3.6.1.4.1.25258.1.18.2", "mceliece348864f"},
{"1.3.6.1.4.1.25258.1.18.3", "mceliece460896"},
{"1.3.6.1.4.1.25258.1.18.4", "mceliece460896f"},
{"1.3.6.1.4.1.25258.1.18.5", "mceliece6688128"},
{"1.3.6.1.4.1.25258.1.18.6", "mceliece6688128f"},
{"1.3.6.1.4.1.25258.1.18.7", "mceliece6688128pc"},
{"1.3.6.1.4.1.25258.1.18.8", "mceliece6688128pcf"},
{"1.3.6.1.4.1.25258.1.18.9", "mceliece6960119"},
{"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 @@ -569,6 +585,22 @@ std::unordered_map<std::string, OID> OID_Map::load_str2oid_map() {
{"gost_256B", OID({1, 2, 643, 7, 1, 2, 1, 1, 2})},
{"gost_512A", OID({1, 2, 643, 7, 1, 2, 1, 2, 1})},
{"gost_512B", OID({1, 2, 643, 7, 1, 2, 1, 2, 2})},
{"mceliece348864", OID({1, 3, 6, 1, 4, 1, 25258, 1, 18, 1})},
{"mceliece348864f", OID({1, 3, 6, 1, 4, 1, 25258, 1, 18, 2})},
{"mceliece460896", OID({1, 3, 6, 1, 4, 1, 25258, 1, 18, 3})},
{"mceliece460896f", OID({1, 3, 6, 1, 4, 1, 25258, 1, 18, 4})},
{"mceliece6688128", OID({1, 3, 6, 1, 4, 1, 25258, 1, 18, 5})},
{"mceliece6688128f", OID({1, 3, 6, 1, 4, 1, 25258, 1, 18, 6})},
{"mceliece6688128pc", OID({1, 3, 6, 1, 4, 1, 25258, 1, 18, 7})},
{"mceliece6688128pcf", OID({1, 3, 6, 1, 4, 1, 25258, 1, 18, 8})},
{"mceliece6960119", OID({1, 3, 6, 1, 4, 1, 25258, 1, 18, 9})},
{"mceliece6960119f", OID({1, 3, 6, 1, 4, 1, 25258, 1, 18, 10})},
{"mceliece6960119pc", OID({1, 3, 6, 1, 4, 1, 25258, 1, 18, 11})},
{"mceliece6960119pcf", OID({1, 3, 6, 1, 4, 1, 25258, 1, 18, 12})},
{"mceliece8192128", OID({1, 3, 6, 1, 4, 1, 25258, 1, 18, 13})},
{"mceliece8192128f", OID({1, 3, 6, 1, 4, 1, 25258, 1, 18, 14})},
{"mceliece8192128pc", OID({1, 3, 6, 1, 4, 1, 25258, 1, 18, 15})},
{"mceliece8192128pcf", OID({1, 3, 6, 1, 4, 1, 25258, 1, 18, 16})},
{"secp160k1", OID({1, 3, 132, 0, 9})},
{"secp160r1", OID({1, 3, 132, 0, 8})},
{"secp160r2", OID({1, 3, 132, 0, 30})},
Expand Down
Loading

0 comments on commit 04b9314

Please sign in to comment.