• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 5287468012

16 Jun 2023 08:16AM UTC coverage: 91.715%. Remained the same
5287468012

Pull #3549

github

web-flow
Merge 077c5be00 into 96fe3b96d
Pull Request #3549: SPHINCS+

78125 of 85182 relevant lines covered (91.72%)

12671627.9 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

84.69
/src/lib/pubkey/mce/mceliece_key.cpp
1
/*
2
 * (C) Copyright Projet SECRET, INRIA, Rocquencourt
3
 * (C) Bhaskar Biswas and  Nicolas Sendrier
4
 *
5
 * (C) 2014 cryptosource GmbH
6
 * (C) 2014 Falko Strenzke fstrenzke@cryptosource.de
7
 * (C) 2015 Jack Lloyd
8
 *
9
 * Botan is released under the Simplified BSD License (see license.txt)
10
 *
11
 */
12

13
#include <botan/mceliece.h>
14

15
#include <botan/ber_dec.h>
16
#include <botan/der_enc.h>
17
#include <botan/rng.h>
18
#include <botan/internal/bit_ops.h>
19
#include <botan/internal/code_based_util.h>
20
#include <botan/internal/loadstor.h>
21
#include <botan/internal/mce_internal.h>
22
#include <botan/internal/pk_ops_impl.h>
23
#include <botan/internal/polyn_gf2m.h>
24

25
namespace Botan {
26

27
McEliece_PrivateKey::McEliece_PrivateKey(const McEliece_PrivateKey&) = default;
×
28
McEliece_PrivateKey::McEliece_PrivateKey(McEliece_PrivateKey&&) noexcept = default;
×
29
McEliece_PrivateKey& McEliece_PrivateKey::operator=(const McEliece_PrivateKey&) = default;
×
30
McEliece_PrivateKey& McEliece_PrivateKey::operator=(McEliece_PrivateKey&&) noexcept = default;
98✔
31
McEliece_PrivateKey::~McEliece_PrivateKey() = default;
670✔
32

33
McEliece_PrivateKey::McEliece_PrivateKey(const polyn_gf2m& goppa_polyn,
98✔
34
                                         const std::vector<uint32_t>& parity_check_matrix_coeffs,
35
                                         const std::vector<polyn_gf2m>& square_root_matrix,
36
                                         const std::vector<gf2m>& inverse_support,
37
                                         const std::vector<uint8_t>& public_matrix) :
98✔
38
      McEliece_PublicKey(public_matrix, goppa_polyn.get_degree(), inverse_support.size()),
98✔
39
      m_g{goppa_polyn},
196✔
40
      m_sqrtmod(square_root_matrix),
98✔
41
      m_Linv(inverse_support),
98✔
42
      m_coeffs(parity_check_matrix_coeffs),
98✔
43
      m_codimension(static_cast<size_t>(ceil_log2(inverse_support.size())) * goppa_polyn.get_degree()),
196✔
44
      m_dimension(inverse_support.size() - m_codimension) {}
196✔
45

46
McEliece_PrivateKey::McEliece_PrivateKey(RandomNumberGenerator& rng, size_t code_length, size_t t) {
98✔
47
   uint32_t ext_deg = ceil_log2(code_length);
98✔
48
   *this = generate_mceliece_key(rng, ext_deg, code_length, t);
98✔
49
}
98✔
50

51
const polyn_gf2m& McEliece_PrivateKey::get_goppa_polyn() const {
10,584✔
52
   return m_g[0];
10,584✔
53
}
54

55
size_t McEliece_PublicKey::get_message_word_bit_length() const {
10,414✔
56
   size_t codimension = ceil_log2(m_code_length) * m_t;
10,414✔
57
   return m_code_length - codimension;
10,414✔
58
}
59

60
secure_vector<uint8_t> McEliece_PublicKey::random_plaintext_element(RandomNumberGenerator& rng) const {
2,646✔
61
   const size_t bits = get_message_word_bit_length();
2,646✔
62

63
   secure_vector<uint8_t> plaintext((bits + 7) / 8);
2,646✔
64
   rng.randomize(plaintext.data(), plaintext.size());
2,646✔
65

66
   // unset unused bits in the last plaintext byte
67
   if(uint32_t used = bits % 8) {
2,646✔
68
      const uint8_t mask = (1 << used) - 1;
1,933✔
69
      plaintext[plaintext.size() - 1] &= mask;
1,933✔
70
   }
71

72
   return plaintext;
2,646✔
73
}
×
74

75
AlgorithmIdentifier McEliece_PublicKey::algorithm_identifier() const {
13✔
76
   return AlgorithmIdentifier(object_identifier(), AlgorithmIdentifier::USE_EMPTY_PARAM);
13✔
77
}
78

79
std::vector<uint8_t> McEliece_PublicKey::public_key_bits() const {
267✔
80
   std::vector<uint8_t> output;
267✔
81
   DER_Encoder(output)
534✔
82
      .start_sequence()
267✔
83
      .start_sequence()
267✔
84
      .encode(static_cast<size_t>(get_code_length()))
267✔
85
      .encode(static_cast<size_t>(get_t()))
267✔
86
      .end_cons()
267✔
87
      .encode(m_public_matrix, ASN1_Type::OctetString)
267✔
88
      .end_cons();
267✔
89
   return output;
267✔
90
}
×
91

92
size_t McEliece_PublicKey::key_length() const {
×
93
   return m_code_length;
×
94
}
95

96
size_t McEliece_PublicKey::estimated_strength() const {
2✔
97
   return mceliece_work_factor(m_code_length, m_t);
2✔
98
}
99

100
McEliece_PublicKey::McEliece_PublicKey(std::span<const uint8_t> key_bits) {
86✔
101
   BER_Decoder dec(key_bits);
86✔
102
   size_t n;
86✔
103
   size_t t;
86✔
104
   dec.start_sequence()
86✔
105
      .start_sequence()
172✔
106
      .decode(n)
86✔
107
      .decode(t)
86✔
108
      .end_cons()
86✔
109
      .decode(m_public_matrix, ASN1_Type::OctetString)
86✔
110
      .end_cons();
86✔
111
   m_t = t;
86✔
112
   m_code_length = n;
86✔
113
}
86✔
114

115
secure_vector<uint8_t> McEliece_PrivateKey::private_key_bits() const {
270✔
116
   DER_Encoder enc;
270✔
117
   enc.start_sequence()
270✔
118
      .start_sequence()
270✔
119
      .encode(static_cast<size_t>(get_code_length()))
270✔
120
      .encode(static_cast<size_t>(get_t()))
270✔
121
      .end_cons()
270✔
122
      .encode(m_public_matrix, ASN1_Type::OctetString)
270✔
123
      .encode(m_g[0].encode(), ASN1_Type::OctetString);  // g as octet string
540✔
124
   enc.start_sequence();
270✔
125
   for(size_t i = 0; i < m_sqrtmod.size(); i++) {
4,544✔
126
      enc.encode(m_sqrtmod[i].encode(), ASN1_Type::OctetString);
12,822✔
127
   }
128
   enc.end_cons();
270✔
129
   secure_vector<uint8_t> enc_support;
270✔
130

131
   for(uint16_t Linv : m_Linv) {
387,758✔
132
      enc_support.push_back(get_byte<0>(Linv));
387,488✔
133
      enc_support.push_back(get_byte<1>(Linv));
387,488✔
134
   }
135
   enc.encode(enc_support, ASN1_Type::OctetString);
270✔
136
   secure_vector<uint8_t> enc_H;
270✔
137
   for(uint32_t coef : m_coeffs) {
8,999,790✔
138
      enc_H.push_back(get_byte<0>(coef));
8,999,520✔
139
      enc_H.push_back(get_byte<1>(coef));
8,999,520✔
140
      enc_H.push_back(get_byte<2>(coef));
8,999,520✔
141
      enc_H.push_back(get_byte<3>(coef));
8,999,520✔
142
   }
143
   enc.encode(enc_H, ASN1_Type::OctetString);
270✔
144
   enc.end_cons();
270✔
145
   return enc.get_contents();
540✔
146
}
540✔
147

148
bool McEliece_PrivateKey::check_key(RandomNumberGenerator& rng, bool /*unused*/) const {
85✔
149
   const secure_vector<uint8_t> plaintext = this->random_plaintext_element(rng);
85✔
150

151
   secure_vector<uint8_t> ciphertext;
85✔
152
   secure_vector<uint8_t> errors;
85✔
153
   mceliece_encrypt(ciphertext, errors, plaintext, *this, rng);
85✔
154

155
   secure_vector<uint8_t> plaintext_out;
85✔
156
   secure_vector<uint8_t> errors_out;
85✔
157
   mceliece_decrypt(plaintext_out, errors_out, ciphertext, *this);
85✔
158

159
   if(errors != errors_out || plaintext != plaintext_out) {
85✔
160
      return false;
×
161
   }
162

163
   return true;
164
}
425✔
165

166
McEliece_PrivateKey::McEliece_PrivateKey(std::span<const uint8_t> key_bits) {
89✔
167
   size_t n, t;
89✔
168
   secure_vector<uint8_t> enc_g;
89✔
169
   BER_Decoder dec_base(key_bits);
89✔
170
   BER_Decoder dec = dec_base.start_sequence()
89✔
171
                        .start_sequence()
178✔
172
                        .decode(n)
89✔
173
                        .decode(t)
89✔
174
                        .end_cons()
89✔
175
                        .decode(m_public_matrix, ASN1_Type::OctetString)
89✔
176
                        .decode(enc_g, ASN1_Type::OctetString);
89✔
177

178
   if(t == 0 || n == 0) {
89✔
179
      throw Decoding_Error("invalid McEliece parameters");
×
180
   }
181

182
   uint32_t ext_deg = ceil_log2(n);
89✔
183
   m_code_length = n;
89✔
184
   m_t = t;
89✔
185
   m_codimension = (ext_deg * t);
89✔
186
   m_dimension = (n - m_codimension);
89✔
187

188
   auto sp_field = std::make_shared<GF2m_Field>(ext_deg);
89✔
189
   m_g = {polyn_gf2m(enc_g, sp_field)};
267✔
190
   if(m_g[0].get_degree() != static_cast<int>(t)) {
89✔
191
      throw Decoding_Error("degree of decoded Goppa polynomial is incorrect");
×
192
   }
193
   BER_Decoder dec2 = dec.start_sequence();
89✔
194
   for(uint32_t i = 0; i < t / 2; i++) {
1,471✔
195
      secure_vector<uint8_t> sqrt_enc;
1,382✔
196
      dec2.decode(sqrt_enc, ASN1_Type::OctetString);
1,382✔
197
      while(sqrt_enc.size() < (t * 2)) {
1,382✔
198
         // ensure that the length is always t
199
         sqrt_enc.push_back(0);
×
200
         sqrt_enc.push_back(0);
×
201
      }
202
      if(sqrt_enc.size() != t * 2) {
1,382✔
203
         throw Decoding_Error("length of square root polynomial entry is too large");
×
204
      }
205
      m_sqrtmod.push_back(polyn_gf2m(sqrt_enc, sp_field));
2,764✔
206
   }
1,382✔
207
   secure_vector<uint8_t> enc_support;
89✔
208
   BER_Decoder dec3 = dec2.end_cons().decode(enc_support, ASN1_Type::OctetString);
89✔
209
   if(enc_support.size() % 2) {
89✔
210
      throw Decoding_Error("encoded support has odd length");
×
211
   }
212
   if(enc_support.size() / 2 != n) {
89✔
213
      throw Decoding_Error("encoded support has length different from code length");
×
214
   }
215
   for(uint32_t i = 0; i < n * 2; i += 2) {
124,057✔
216
      gf2m el = (enc_support[i] << 8) | enc_support[i + 1];
123,968✔
217
      m_Linv.push_back(el);
123,968✔
218
   }
219
   secure_vector<uint8_t> enc_H;
89✔
220
   dec3.decode(enc_H, ASN1_Type::OctetString).end_cons();
89✔
221
   if(enc_H.size() % 4) {
89✔
222
      throw Decoding_Error("encoded parity check matrix has length which is not a multiple of four");
×
223
   }
224
   if(enc_H.size() / 4 != bit_size_to_32bit_size(m_codimension) * m_code_length) {
89✔
225
      throw Decoding_Error("encoded parity check matrix has wrong length");
×
226
   }
227

228
   for(uint32_t i = 0; i < enc_H.size(); i += 4) {
2,801,081✔
229
      uint32_t coeff = (enc_H[i] << 24) | (enc_H[i + 1] << 16) | (enc_H[i + 2] << 8) | enc_H[i + 3];
2,800,992✔
230
      m_coeffs.push_back(coeff);
2,800,992✔
231
   }
232
}
356✔
233

234
bool McEliece_PrivateKey::operator==(const McEliece_PrivateKey& other) const {
×
235
   if(*static_cast<const McEliece_PublicKey*>(this) != *static_cast<const McEliece_PublicKey*>(&other)) {
×
236
      return false;
237
   }
238
   if(m_g != other.m_g) {
×
239
      return false;
240
   }
241

242
   if(m_sqrtmod != other.m_sqrtmod) {
×
243
      return false;
244
   }
245
   if(m_Linv != other.m_Linv) {
×
246
      return false;
247
   }
248
   if(m_coeffs != other.m_coeffs) {
×
249
      return false;
250
   }
251

252
   if(m_codimension != other.m_codimension || m_dimension != other.m_dimension) {
×
253
      return false;
×
254
   }
255

256
   return true;
257
}
258

259
std::unique_ptr<Public_Key> McEliece_PrivateKey::public_key() const {
2✔
260
   return std::make_unique<McEliece_PublicKey>(get_public_matrix(), get_t(), get_code_length());
2✔
261
}
262

263
bool McEliece_PublicKey::operator==(const McEliece_PublicKey& other) const {
×
264
   if(m_public_matrix != other.m_public_matrix) {
×
265
      return false;
266
   }
267
   if(m_t != other.m_t) {
×
268
      return false;
269
   }
270
   if(m_code_length != other.m_code_length) {
×
271
      return false;
×
272
   }
273
   return true;
274
}
275

276
namespace {
277

278
class MCE_KEM_Encryptor final : public PK_Ops::KEM_Encryption_with_KDF {
279
   public:
280
      MCE_KEM_Encryptor(const McEliece_PublicKey& key, std::string_view kdf) :
96✔
281
            KEM_Encryption_with_KDF(kdf), m_key(key) {}
96✔
282

283
   private:
284
      size_t raw_kem_shared_key_length() const override {
2,561✔
285
         const size_t err_sz = (m_key.get_code_length() + 7) / 8;
2,561✔
286
         const size_t ptext_sz = (m_key.get_message_word_bit_length() + 7) / 8;
2,561✔
287
         return ptext_sz + err_sz;
2,561✔
288
      }
289

290
      size_t encapsulated_key_length() const override { return (m_key.get_code_length() + 7) / 8; }
2,561✔
291

292
      void raw_kem_encrypt(secure_vector<uint8_t>& out_encapsulated_key,
2,561✔
293
                           secure_vector<uint8_t>& raw_shared_key,
294
                           RandomNumberGenerator& rng) override {
295
         secure_vector<uint8_t> plaintext = m_key.random_plaintext_element(rng);
2,561✔
296

297
         secure_vector<uint8_t> ciphertext, error_mask;
2,561✔
298
         mceliece_encrypt(ciphertext, error_mask, plaintext, m_key, rng);
2,561✔
299

300
         raw_shared_key.clear();
2,561✔
301
         raw_shared_key += plaintext;
2,561✔
302
         raw_shared_key += error_mask;
2,561✔
303

304
         out_encapsulated_key.swap(ciphertext);
2,561✔
305
      }
5,122✔
306

307
      const McEliece_PublicKey& m_key;
308
};
309

310
class MCE_KEM_Decryptor final : public PK_Ops::KEM_Decryption_with_KDF {
311
   public:
312
      MCE_KEM_Decryptor(const McEliece_PrivateKey& key, std::string_view kdf) :
96✔
313
            KEM_Decryption_with_KDF(kdf), m_key(key) {}
96✔
314

315
   private:
316
      size_t raw_kem_shared_key_length() const override {
2,561✔
317
         const size_t err_sz = (m_key.get_code_length() + 7) / 8;
2,561✔
318
         const size_t ptext_sz = (m_key.get_message_word_bit_length() + 7) / 8;
2,561✔
319
         return ptext_sz + err_sz;
2,561✔
320
      }
321

322
      secure_vector<uint8_t> raw_kem_decrypt(const uint8_t encap_key[], size_t len) override {
2,561✔
323
         secure_vector<uint8_t> plaintext, error_mask;
2,561✔
324
         mceliece_decrypt(plaintext, error_mask, encap_key, len, m_key);
2,561✔
325

326
         secure_vector<uint8_t> output;
2,561✔
327
         output.reserve(plaintext.size() + error_mask.size());
2,561✔
328
         output.insert(output.end(), plaintext.begin(), plaintext.end());
2,561✔
329
         output.insert(output.end(), error_mask.begin(), error_mask.end());
2,561✔
330
         return output;
2,561✔
331
      }
5,122✔
332

333
      const McEliece_PrivateKey& m_key;
334
};
335

336
}  // namespace
337

338
std::unique_ptr<PK_Ops::KEM_Encryption> McEliece_PublicKey::create_kem_encryption_op(std::string_view params,
96✔
339
                                                                                     std::string_view provider) const {
340
   if(provider == "base" || provider.empty()) {
96✔
341
      return std::make_unique<MCE_KEM_Encryptor>(*this, params);
96✔
342
   }
343
   throw Provider_Not_Found(algo_name(), provider);
×
344
}
345

346
std::unique_ptr<PK_Ops::KEM_Decryption> McEliece_PrivateKey::create_kem_decryption_op(RandomNumberGenerator& /*rng*/,
96✔
347
                                                                                      std::string_view params,
348
                                                                                      std::string_view provider) const {
349
   if(provider == "base" || provider.empty()) {
96✔
350
      return std::make_unique<MCE_KEM_Decryptor>(*this, params);
96✔
351
   }
352
   throw Provider_Not_Found(algo_name(), provider);
×
353
}
354

355
}  // namespace Botan
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc