Botan 3.13.0
Crypto and TLS for C&
mceliece.cpp
Go to the documentation of this file.
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 *
8 * Botan is released under the Simplified BSD License (see license.txt)
9 *
10 */
11
12#include <botan/internal/mce_internal.h>
13
14#include <botan/mceliece.h>
15#include <botan/mem_ops.h>
16#include <botan/internal/bit_ops.h>
17#include <botan/internal/code_based_util.h>
18
19namespace Botan {
20
21namespace {
22
25 size_t dimension,
26 size_t codimension) {
28
29 const size_t final_bits = dimension % 8;
30
31 if(final_bits == 0) {
32 const size_t dim_bytes = bit_size_to_byte_size(dimension);
33 copy_mem(&x[0], a.data(), dim_bytes); // NOLINT(*container-data-pointer)
34 copy_mem(&x[dim_bytes], b.data(), bit_size_to_byte_size(codimension));
35 } else {
36 copy_mem(&x[0], a.data(), (dimension / 8)); // NOLINT(*container-data-pointer)
37 size_t l = dimension / 8;
38 x[l] = static_cast<uint8_t>(a[l] & ((1 << final_bits) - 1));
39
40 for(size_t k = 0; k < codimension / 8; ++k) {
41 x[l] ^= static_cast<uint8_t>(b[k] << final_bits);
42 ++l;
43 x[l] = static_cast<uint8_t>(b[k] >> (8 - final_bits));
44 }
45 if(const size_t remaining_codim_bits = codimension % 8) {
46 const uint8_t final_codim_byte = b[codimension / 8];
47 x[l] ^= static_cast<uint8_t>(final_codim_byte << final_bits);
48 if(final_bits + remaining_codim_bits > 8) {
49 ++l;
50 x[l] = static_cast<uint8_t>(final_codim_byte >> (8 - final_bits));
51 }
52 }
53 }
54
55 return x;
56}
57
58secure_vector<uint8_t> mult_by_pubkey(const secure_vector<uint8_t>& cleartext,
59 const std::vector<uint8_t>& public_matrix,
60 size_t code_length,
61 size_t t) {
62 const size_t ext_deg = ceil_log2(code_length);
63 const size_t codimension = ext_deg * t;
64 const size_t dimension = code_length - codimension;
65 secure_vector<uint8_t> cR(bit_size_to_32bit_size(codimension) * sizeof(uint32_t));
66
67 BOTAN_ARG_CHECK(cleartext.size() == bit_size_to_byte_size(dimension), "Invalid McEliece plaintext length");
68 BOTAN_ARG_CHECK(public_matrix.size() == dimension * cR.size(), "Invalid McEliece public matrix length");
69
70 const uint8_t* pt = public_matrix.data();
71
72 for(size_t i = 0; i < dimension / 8; ++i) {
73 for(size_t j = 0; j < 8; ++j) {
74 if((cleartext[i] & (1 << j)) != 0) {
75 xor_buf(cR.data(), pt, cR.size());
76 }
77 pt += cR.size();
78 }
79 }
80
81 for(size_t i = 0; i < dimension % 8; ++i) {
82 if((cleartext[dimension / 8] & (1 << i)) != 0) {
83 xor_buf(cR.data(), pt, cR.size());
84 }
85 pt += cR.size();
86 }
87
88 secure_vector<uint8_t> ciphertext = concat_vectors(cleartext, cR, dimension, codimension);
89 ciphertext.resize((code_length + 7) / 8);
90 return ciphertext;
91}
92
93secure_vector<uint8_t> create_random_error_vector(size_t code_length, size_t error_weight, RandomNumberGenerator& rng) {
94 secure_vector<uint8_t> result((code_length + 7) / 8);
95
96 size_t bits_set = 0;
97
98 while(bits_set < error_weight) {
99 const gf2m x = random_code_element(static_cast<uint16_t>(code_length), rng);
100
101 const size_t byte_pos = x / 8;
102 const size_t bit_pos = x % 8;
103
104 const uint8_t mask = (1 << bit_pos);
105
106 if((result[byte_pos] & mask) != 0) {
107 continue; // already set this bit
108 }
109
110 result[byte_pos] |= mask;
111 bits_set++;
112 }
113
114 return result;
115}
116
117} // namespace
118
120 secure_vector<uint8_t>& error_mask_out,
121 const secure_vector<uint8_t>& plaintext,
124 const uint16_t code_length = static_cast<uint16_t>(key.code_length());
125
126 secure_vector<uint8_t> error_mask = create_random_error_vector(code_length, key.t(), rng);
127
128 secure_vector<uint8_t> ciphertext = mult_by_pubkey(plaintext, key.public_matrix(), key.code_length(), key.t());
129
130 ciphertext ^= error_mask;
131
132 ciphertext_out.swap(ciphertext);
133 error_mask_out.swap(error_mask);
134}
135
136} // namespace Botan
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:33
const std::vector< uint8_t > & public_matrix() const
gf2m random_code_element(uint16_t code_length, RandomNumberGenerator &rng)
constexpr void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:144
constexpr uint8_t ceil_log2(T x)
Definition bit_ops.h:140
constexpr void xor_buf(ranges::contiguous_output_range< uint8_t > auto &&out, ranges::contiguous_range< uint8_t > auto &&in)
Definition mem_ops.h:403
void mceliece_encrypt(secure_vector< uint8_t > &ciphertext_out, secure_vector< uint8_t > &error_mask_out, const secure_vector< uint8_t > &plaintext, const McEliece_PublicKeyInternal &key, RandomNumberGenerator &rng)
Definition mceliece.cpp:119
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:128
size_t bit_size_to_32bit_size(size_t bit_size)
size_t bit_size_to_byte_size(size_t bit_size)
uint16_t gf2m