/src/botan/src/lib/pubkey/mce/mceliece.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | |
19 | | namespace Botan { |
20 | | |
21 | | namespace { |
22 | | |
23 | | secure_vector<uint8_t> concat_vectors(const secure_vector<uint8_t>& a, |
24 | | const secure_vector<uint8_t>& b, |
25 | | size_t dimension, |
26 | 0 | size_t codimension) { |
27 | 0 | secure_vector<uint8_t> x(bit_size_to_byte_size(dimension) + bit_size_to_byte_size(codimension)); |
28 | |
|
29 | 0 | const size_t final_bits = dimension % 8; |
30 | |
|
31 | 0 | if(final_bits == 0) { |
32 | 0 | const size_t dim_bytes = bit_size_to_byte_size(dimension); |
33 | 0 | copy_mem(&x[0], a.data(), dim_bytes); |
34 | 0 | copy_mem(&x[dim_bytes], b.data(), bit_size_to_byte_size(codimension)); |
35 | 0 | } else { |
36 | 0 | copy_mem(&x[0], a.data(), (dimension / 8)); |
37 | 0 | size_t l = dimension / 8; |
38 | 0 | x[l] = static_cast<uint8_t>(a[l] & ((1 << final_bits) - 1)); |
39 | |
|
40 | 0 | for(size_t k = 0; k < codimension / 8; ++k) { |
41 | 0 | x[l] ^= static_cast<uint8_t>(b[k] << final_bits); |
42 | 0 | ++l; |
43 | 0 | x[l] = static_cast<uint8_t>(b[k] >> (8 - final_bits)); |
44 | 0 | } |
45 | 0 | x[l] ^= static_cast<uint8_t>(b[codimension / 8] << final_bits); |
46 | 0 | } |
47 | |
|
48 | 0 | return x; |
49 | 0 | } |
50 | | |
51 | | secure_vector<uint8_t> mult_by_pubkey(const secure_vector<uint8_t>& cleartext, |
52 | | const std::vector<uint8_t>& public_matrix, |
53 | | size_t code_length, |
54 | 0 | size_t t) { |
55 | 0 | const size_t ext_deg = ceil_log2(code_length); |
56 | 0 | const size_t codimension = ext_deg * t; |
57 | 0 | const size_t dimension = code_length - codimension; |
58 | 0 | secure_vector<uint8_t> cR(bit_size_to_32bit_size(codimension) * sizeof(uint32_t)); |
59 | |
|
60 | 0 | const uint8_t* pt = public_matrix.data(); |
61 | |
|
62 | 0 | for(size_t i = 0; i < dimension / 8; ++i) { |
63 | 0 | for(size_t j = 0; j < 8; ++j) { |
64 | 0 | if(cleartext[i] & (1 << j)) { |
65 | 0 | xor_buf(cR.data(), pt, cR.size()); |
66 | 0 | } |
67 | 0 | pt += cR.size(); |
68 | 0 | } |
69 | 0 | } |
70 | |
|
71 | 0 | for(size_t i = 0; i < dimension % 8; ++i) { |
72 | 0 | if(cleartext[dimension / 8] & (1 << i)) { |
73 | 0 | xor_buf(cR.data(), pt, cR.size()); |
74 | 0 | } |
75 | 0 | pt += cR.size(); |
76 | 0 | } |
77 | |
|
78 | 0 | secure_vector<uint8_t> ciphertext = concat_vectors(cleartext, cR, dimension, codimension); |
79 | 0 | ciphertext.resize((code_length + 7) / 8); |
80 | 0 | return ciphertext; |
81 | 0 | } |
82 | | |
83 | 0 | secure_vector<uint8_t> create_random_error_vector(size_t code_length, size_t error_weight, RandomNumberGenerator& rng) { |
84 | 0 | secure_vector<uint8_t> result((code_length + 7) / 8); |
85 | |
|
86 | 0 | size_t bits_set = 0; |
87 | |
|
88 | 0 | while(bits_set < error_weight) { |
89 | 0 | gf2m x = random_code_element(static_cast<uint16_t>(code_length), rng); |
90 | |
|
91 | 0 | const size_t byte_pos = x / 8; |
92 | 0 | const size_t bit_pos = x % 8; |
93 | |
|
94 | 0 | const uint8_t mask = (1 << bit_pos); |
95 | |
|
96 | 0 | if(result[byte_pos] & mask) { |
97 | 0 | continue; // already set this bit |
98 | 0 | } |
99 | | |
100 | 0 | result[byte_pos] |= mask; |
101 | 0 | bits_set++; |
102 | 0 | } |
103 | |
|
104 | 0 | return result; |
105 | 0 | } |
106 | | |
107 | | } // namespace |
108 | | |
109 | | void mceliece_encrypt(secure_vector<uint8_t>& ciphertext_out, |
110 | | secure_vector<uint8_t>& error_mask_out, |
111 | | const secure_vector<uint8_t>& plaintext, |
112 | | const McEliece_PublicKey& key, |
113 | 0 | RandomNumberGenerator& rng) { |
114 | 0 | const uint16_t code_length = static_cast<uint16_t>(key.get_code_length()); |
115 | |
|
116 | 0 | secure_vector<uint8_t> error_mask = create_random_error_vector(code_length, key.get_t(), rng); |
117 | |
|
118 | 0 | secure_vector<uint8_t> ciphertext = |
119 | 0 | mult_by_pubkey(plaintext, key.get_public_matrix(), key.get_code_length(), key.get_t()); |
120 | |
|
121 | 0 | ciphertext ^= error_mask; |
122 | |
|
123 | 0 | ciphertext_out.swap(ciphertext); |
124 | 0 | error_mask_out.swap(error_mask); |
125 | 0 | } |
126 | | |
127 | | } // namespace Botan |