aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/pubkey/mce/mceliece.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/pubkey/mce/mceliece.cpp')
-rw-r--r--src/lib/pubkey/mce/mceliece.cpp172
1 files changed, 172 insertions, 0 deletions
diff --git a/src/lib/pubkey/mce/mceliece.cpp b/src/lib/pubkey/mce/mceliece.cpp
new file mode 100644
index 000000000..69d5eb008
--- /dev/null
+++ b/src/lib/pubkey/mce/mceliece.cpp
@@ -0,0 +1,172 @@
+/**
+ * (C) Copyright Projet SECRET, INRIA, Rocquencourt
+ * (C) Bhaskar Biswas and Nicolas Sendrier
+ *
+ * (C) 2014 cryptosource GmbH
+ * (C) 2014 Falko Strenzke [email protected]
+ *
+ * Distributed under the terms of the Botan license
+ *
+ */
+
+#include <botan/mceliece.h>
+#include <botan/mceliece_key.h>
+#include <botan/internal/code_based_key_gen.h>
+#include <botan/polyn_gf2m.h>
+#include <botan/code_based_util.h>
+#include <botan/goppa_code.h>
+#include <botan/internal/bit_ops.h>
+#include <botan/internal/xor_buf.h>
+#include <iostream>
+
+namespace Botan {
+
+namespace {
+void concat_vectors(unsigned char* x, const unsigned char* a, const unsigned char* b, u32bit dimension, u32bit codimension)
+ {
+ if(dimension % 8 == 0)
+ {
+ std::memcpy(x, a, bit_size_to_byte_size(dimension));
+ std::memcpy(((unsigned char *) x) + bit_size_to_byte_size(dimension), b, bit_size_to_byte_size(codimension));
+ }
+ else
+ {
+ u32bit i, j, k, l;
+ i = dimension - 8 * (dimension/ 8);
+ j = 8 - i;
+ l = dimension / 8;
+ std::memcpy(x, a, 1 * (dimension / 8));
+ x[l] = ((byte) (a[l] & ((1 << i) - 1)));
+
+ for(k = 0; k < codimension / 8; ++k)
+ {
+ x[l] ^= ((byte) ( b[k] << i));
+ ++l;
+ x[l] = ((byte) (b[k] >> j));
+ }
+ x[l] ^= ((byte) ( b[k] << i));
+ }
+ }
+
+std::vector<byte> mult_by_pubkey(const byte *cleartext,
+ std::vector<byte> const& public_matrix,
+ u32bit code_length, u32bit t)
+ {
+ std::vector<byte> ciphertext(code_length);
+ u32bit i, j;
+ u32bit ext_deg = ceil_log2(code_length);
+ u32bit codimension = ext_deg * t;
+ u32bit dimension = code_length - codimension;
+ std::vector<byte> cR(bit_size_to_32bit_size(codimension)* sizeof(u32bit));
+
+ const byte* pt = &public_matrix[0];
+
+ for(i = 0; i < dimension / 8; ++i)
+ {
+ for(j = 0; j < 8; ++j)
+ {
+ if(cleartext[i] & (1 << j))
+ {
+ xor_buf(&cR[0], pt, cR.size());
+ }
+ pt += bit_size_to_32bit_size(codimension) * sizeof(u32bit);
+ }
+ }
+
+ for(j = 0; j < dimension % 8 ; ++j)
+ {
+ if(cleartext[i] & (1 << j))
+ {
+ xor_buf(&cR[0], pt, bit_size_to_byte_size(codimension));
+ }
+ pt += bit_size_to_32bit_size(codimension) * sizeof(u32bit);
+ }
+
+ concat_vectors( &ciphertext[0], cleartext, &cR[0], dimension, codimension);
+ return ciphertext;
+ }
+
+}
+
+secure_vector<gf2m> create_random_error_positions(unsigned code_length,
+ unsigned error_weight,
+ RandomNumberGenerator& rng)
+ {
+ secure_vector<gf2m> result(error_weight);
+ gf2m i;
+ for(i = 0; i < result.size(); i++)
+ {
+ unsigned j;
+ char try_again = 0;
+ do
+ {
+ try_again = 0;
+ gf2m new_pos = random_code_element(code_length, rng);
+ for(j = 0; j < i; j++)
+ {
+ if(new_pos == result[j])
+ {
+ try_again = 1;
+ break;
+ }
+ }
+ result[i] = new_pos;
+ } while(try_again);
+ }
+ return result;
+ }
+
+McEliece_Private_Operation::McEliece_Private_Operation(const McEliece_PrivateKey& private_key)
+ :m_priv_key(private_key)
+ {
+ }
+
+secure_vector<byte> McEliece_Private_Operation::decrypt(const byte msg[], size_t msg_len)
+ {
+ secure_vector<gf2m> err_pos;
+
+ secure_vector<byte> plaintext = mceliece_decrypt(
+ err_pos,
+ msg, msg_len,
+ m_priv_key
+ );
+
+ return mceliece_message_parts(err_pos, plaintext, m_priv_key.get_code_length()).get_concat();
+ }
+
+McEliece_Public_Operation::McEliece_Public_Operation(const McEliece_PublicKey& public_key, u32bit the_code_length)
+ :m_pub_key(public_key),
+ m_code_length(the_code_length)
+ {}
+
+secure_vector<byte> McEliece_Public_Operation::encrypt(const byte msg[], size_t msg_len, RandomNumberGenerator&)
+ {
+ mceliece_message_parts parts(msg, msg_len, m_pub_key.get_code_length());
+ secure_vector<gf2m> err_pos = parts.get_error_positions();
+ secure_vector<byte> message_word = parts.get_message_word();
+ secure_vector<byte> ciphertext((m_pub_key.get_code_length()+7)/8);
+
+
+ std::vector<byte> ciphertext_tmp = mceliece_encrypt( message_word, m_pub_key.get_public_matrix(), err_pos, m_code_length);
+
+ std::memcpy(&ciphertext[0], &ciphertext_tmp[0], ciphertext.size());
+ return ciphertext;
+ }
+
+std::vector<byte> mceliece_encrypt(const secure_vector<byte> & cleartext,
+ std::vector<byte> const& public_matrix,
+ const secure_vector<gf2m> & err_pos,
+ u32bit code_length)
+ {
+ std::vector<byte> ciphertext = mult_by_pubkey(&cleartext[0], public_matrix, code_length, err_pos.size());
+
+ // flip t error positions
+ for(size_t i = 0; i < err_pos.size(); ++i)
+ {
+ ciphertext[err_pos[i] / 8] ^= (1 << (err_pos[i] % 8));
+ }
+
+ return ciphertext;
+ }
+
+}