/src/botan/src/lib/pubkey/classic_mceliece/cmce_parameters.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Classic McEliece Parameters |
3 | | * (C) 2023 Jack Lloyd |
4 | | * 2023,2024 Fabian Albert, Amos Treiber - Rohde & Schwarz Cybersecurity |
5 | | * |
6 | | * Botan is released under the Simplified BSD License (see license.txt) |
7 | | **/ |
8 | | |
9 | | #include <botan/internal/cmce_parameters.h> |
10 | | #include <botan/internal/cmce_poly.h> |
11 | | |
12 | | namespace Botan { |
13 | | |
14 | | namespace { |
15 | | |
16 | 0 | CmceGfMod determine_poly_f(Classic_McEliece_Parameter_Set param_set) { |
17 | 0 | switch(param_set.code()) { |
18 | 0 | case Classic_McEliece_Parameter_Set::mceliece348864: |
19 | 0 | case Classic_McEliece_Parameter_Set::mceliece348864f: |
20 | | // z^12 + z^3 + 1 |
21 | 0 | return CmceGfMod(0b0001000000001001); |
22 | 0 | case Classic_McEliece_Parameter_Set::mceliece460896: |
23 | 0 | case Classic_McEliece_Parameter_Set::mceliece460896f: |
24 | 0 | case Classic_McEliece_Parameter_Set::mceliece6688128: |
25 | 0 | case Classic_McEliece_Parameter_Set::mceliece6688128f: |
26 | 0 | case Classic_McEliece_Parameter_Set::mceliece6688128pc: |
27 | 0 | case Classic_McEliece_Parameter_Set::mceliece6688128pcf: |
28 | 0 | case Classic_McEliece_Parameter_Set::mceliece6960119: |
29 | 0 | case Classic_McEliece_Parameter_Set::mceliece6960119f: |
30 | 0 | case Classic_McEliece_Parameter_Set::mceliece6960119pc: |
31 | 0 | case Classic_McEliece_Parameter_Set::mceliece6960119pcf: |
32 | 0 | case Classic_McEliece_Parameter_Set::mceliece8192128: |
33 | 0 | case Classic_McEliece_Parameter_Set::mceliece8192128f: |
34 | 0 | case Classic_McEliece_Parameter_Set::mceliece8192128pc: |
35 | 0 | case Classic_McEliece_Parameter_Set::mceliece8192128pcf: |
36 | | // z^12 + z^3 + 1 |
37 | 0 | return CmceGfMod(0b0010000000011011); |
38 | 0 | } |
39 | 0 | BOTAN_ASSERT_UNREACHABLE(); |
40 | 0 | } |
41 | | |
42 | 0 | Classic_McEliece_Polynomial_Ring determine_poly_ring(Classic_McEliece_Parameter_Set param_set) { |
43 | 0 | CmceGfMod poly_f = determine_poly_f(param_set); |
44 | |
|
45 | 0 | switch(param_set.code()) { |
46 | 0 | case Classic_McEliece_Parameter_Set::mceliece348864: |
47 | 0 | case Classic_McEliece_Parameter_Set::mceliece348864f: |
48 | | // y^64 + y^3 + y + z |
49 | 0 | return {{{3, Classic_McEliece_GF(CmceGfElem(1), poly_f)}, |
50 | 0 | {1, Classic_McEliece_GF(CmceGfElem(1), poly_f)}, |
51 | 0 | {0, Classic_McEliece_GF(CmceGfElem(2), poly_f)}}, |
52 | 0 | poly_f, |
53 | 0 | 64}; |
54 | 0 | case Classic_McEliece_Parameter_Set::mceliece460896: |
55 | 0 | case Classic_McEliece_Parameter_Set::mceliece460896f: |
56 | | // y^96 + y^10 + y^9 + y^6 + 1 |
57 | 0 | return {{{10, Classic_McEliece_GF(CmceGfElem(1), poly_f)}, |
58 | 0 | {9, Classic_McEliece_GF(CmceGfElem(1), poly_f)}, |
59 | 0 | {6, Classic_McEliece_GF(CmceGfElem(1), poly_f)}, |
60 | 0 | {0, Classic_McEliece_GF(CmceGfElem(1), poly_f)}}, |
61 | 0 | poly_f, |
62 | 0 | 96}; |
63 | 0 | case Classic_McEliece_Parameter_Set::mceliece6960119: |
64 | 0 | case Classic_McEliece_Parameter_Set::mceliece6960119f: |
65 | 0 | case Classic_McEliece_Parameter_Set::mceliece6960119pc: |
66 | 0 | case Classic_McEliece_Parameter_Set::mceliece6960119pcf: |
67 | | // y^119 + y^8 + 1 |
68 | | // clang-format off |
69 | 0 | return {{{8, Classic_McEliece_GF(CmceGfElem(1), poly_f)}, |
70 | 0 | {0, Classic_McEliece_GF(CmceGfElem(1), poly_f)}}, |
71 | 0 | poly_f, |
72 | 0 | 119}; |
73 | | // clang-format on |
74 | 0 | case Classic_McEliece_Parameter_Set::mceliece6688128: |
75 | 0 | case Classic_McEliece_Parameter_Set::mceliece6688128f: |
76 | 0 | case Classic_McEliece_Parameter_Set::mceliece6688128pc: |
77 | 0 | case Classic_McEliece_Parameter_Set::mceliece6688128pcf: |
78 | 0 | case Classic_McEliece_Parameter_Set::mceliece8192128: |
79 | 0 | case Classic_McEliece_Parameter_Set::mceliece8192128f: |
80 | 0 | case Classic_McEliece_Parameter_Set::mceliece8192128pc: |
81 | 0 | case Classic_McEliece_Parameter_Set::mceliece8192128pcf: |
82 | | // y^128 + y^7 + y^2 + y + 1 |
83 | 0 | return {{{7, Classic_McEliece_GF(CmceGfElem(1), poly_f)}, |
84 | 0 | {2, Classic_McEliece_GF(CmceGfElem(1), poly_f)}, |
85 | 0 | {1, Classic_McEliece_GF(CmceGfElem(1), poly_f)}, |
86 | 0 | {0, Classic_McEliece_GF(CmceGfElem(1), poly_f)}}, |
87 | 0 | poly_f, |
88 | 0 | 128}; |
89 | 0 | } |
90 | 0 | BOTAN_ASSERT_UNREACHABLE(); |
91 | 0 | } |
92 | | |
93 | | } //namespace |
94 | | |
95 | 0 | Classic_McEliece_Parameters Classic_McEliece_Parameters::create(Classic_McEliece_Parameter_Set set) { |
96 | 0 | auto poly_ring = determine_poly_ring(set); |
97 | |
|
98 | 0 | switch(set.code()) { |
99 | 0 | case Classic_McEliece_Parameter_Set::mceliece348864: |
100 | 0 | case Classic_McEliece_Parameter_Set::mceliece348864f: |
101 | 0 | return Classic_McEliece_Parameters(set, 12, 3488, std::move(poly_ring)); |
102 | | |
103 | 0 | case Classic_McEliece_Parameter_Set::mceliece460896: |
104 | 0 | case Classic_McEliece_Parameter_Set::mceliece460896f: |
105 | 0 | return Classic_McEliece_Parameters(set, 13, 4608, std::move(poly_ring)); |
106 | | |
107 | 0 | case Classic_McEliece_Parameter_Set::mceliece6688128: |
108 | 0 | case Classic_McEliece_Parameter_Set::mceliece6688128f: |
109 | 0 | case Classic_McEliece_Parameter_Set::mceliece6688128pc: |
110 | 0 | case Classic_McEliece_Parameter_Set::mceliece6688128pcf: |
111 | 0 | return Classic_McEliece_Parameters(set, 13, 6688, std::move(poly_ring)); |
112 | | |
113 | 0 | case Classic_McEliece_Parameter_Set::mceliece6960119: |
114 | 0 | case Classic_McEliece_Parameter_Set::mceliece6960119f: |
115 | 0 | case Classic_McEliece_Parameter_Set::mceliece6960119pc: |
116 | 0 | case Classic_McEliece_Parameter_Set::mceliece6960119pcf: |
117 | 0 | return Classic_McEliece_Parameters(set, 13, 6960, std::move(poly_ring)); |
118 | | |
119 | 0 | case Classic_McEliece_Parameter_Set::mceliece8192128: |
120 | 0 | case Classic_McEliece_Parameter_Set::mceliece8192128f: |
121 | 0 | case Classic_McEliece_Parameter_Set::mceliece8192128pc: |
122 | 0 | case Classic_McEliece_Parameter_Set::mceliece8192128pcf: |
123 | 0 | return Classic_McEliece_Parameters(set, 13, 8192, std::move(poly_ring)); |
124 | 0 | } |
125 | 0 | BOTAN_ASSERT_UNREACHABLE(); |
126 | 0 | } |
127 | | |
128 | 0 | Classic_McEliece_Parameters Classic_McEliece_Parameters::create(std::string_view name) { |
129 | 0 | return Classic_McEliece_Parameters::create(Classic_McEliece_Parameter_Set::from_string(name)); |
130 | 0 | } |
131 | | |
132 | 0 | Classic_McEliece_Parameters Classic_McEliece_Parameters::create(const OID& oid) { |
133 | 0 | return create(Classic_McEliece_Parameter_Set::from_oid(oid)); |
134 | 0 | } |
135 | | |
136 | 0 | OID Classic_McEliece_Parameters::object_identifier() const { |
137 | 0 | return OID::from_string(m_set.to_string()); |
138 | 0 | } |
139 | | |
140 | | Classic_McEliece_Parameters::Classic_McEliece_Parameters(Classic_McEliece_Parameter_Set param_set, |
141 | | size_t m, |
142 | | size_t n, |
143 | | Classic_McEliece_Polynomial_Ring poly_ring) : |
144 | 0 | m_set(param_set), m_m(m), m_n(n), m_poly_ring(std::move(poly_ring)) { |
145 | 0 | BOTAN_ASSERT(n % 8 == 0, "We require that n is a multiple of 8"); |
146 | 0 | } |
147 | | |
148 | 0 | size_t Classic_McEliece_Parameters::estimated_strength() const { |
149 | | // Classic McEliece NIST Round 4 submission, Guide for security reviewers, Table 1: |
150 | | // For each instance, the minimal strength against the best attack (with free memory access) |
151 | | // is used as the overall security strength estimate. The strength is capped at 256, since the |
152 | | // seed is only 256 bits long. |
153 | 0 | switch(m_set.code()) { |
154 | 0 | case Botan::Classic_McEliece_Parameter_Set::mceliece348864: |
155 | 0 | case Botan::Classic_McEliece_Parameter_Set::mceliece348864f: |
156 | 0 | return 140; |
157 | 0 | case Botan::Classic_McEliece_Parameter_Set::mceliece460896: |
158 | 0 | case Botan::Classic_McEliece_Parameter_Set::mceliece460896f: |
159 | 0 | return 179; |
160 | 0 | case Botan::Classic_McEliece_Parameter_Set::mceliece6688128: |
161 | 0 | case Botan::Classic_McEliece_Parameter_Set::mceliece6688128f: |
162 | 0 | case Botan::Classic_McEliece_Parameter_Set::mceliece6688128pc: |
163 | 0 | case Botan::Classic_McEliece_Parameter_Set::mceliece6688128pcf: |
164 | 0 | return 246; |
165 | 0 | case Botan::Classic_McEliece_Parameter_Set::mceliece6960119: |
166 | 0 | case Botan::Classic_McEliece_Parameter_Set::mceliece6960119f: |
167 | 0 | case Botan::Classic_McEliece_Parameter_Set::mceliece6960119pc: |
168 | 0 | case Botan::Classic_McEliece_Parameter_Set::mceliece6960119pcf: |
169 | 0 | return 245; |
170 | 0 | case Botan::Classic_McEliece_Parameter_Set::mceliece8192128: |
171 | 0 | case Botan::Classic_McEliece_Parameter_Set::mceliece8192128f: |
172 | 0 | case Botan::Classic_McEliece_Parameter_Set::mceliece8192128pc: |
173 | 0 | case Botan::Classic_McEliece_Parameter_Set::mceliece8192128pcf: |
174 | 0 | return 256; // 275 in the document. Capped at 256 because of the seed length. |
175 | 0 | } |
176 | 0 | BOTAN_ASSERT_UNREACHABLE(); |
177 | 0 | } |
178 | | |
179 | 0 | std::unique_ptr<XOF> Classic_McEliece_Parameters::prg(std::span<const uint8_t> seed) const { |
180 | 0 | BOTAN_ASSERT_EQUAL(seed.size(), 32, "Valid seed length"); |
181 | 0 | auto xof = XOF::create_or_throw("SHAKE-256"); |
182 | |
|
183 | 0 | xof->update(std::array<uint8_t, 1>({64})); |
184 | 0 | xof->update(seed); |
185 | |
|
186 | 0 | return xof; |
187 | 0 | } |
188 | | |
189 | | } // namespace Botan |