aboutsummaryrefslogtreecommitdiff
path: root/libcmix-crypto/ed25519
diff options
context:
space:
mode:
Diffstat (limited to 'libcmix-crypto/ed25519')
-rw-r--r--libcmix-crypto/ed25519/CMakeLists.txt32
-rw-r--r--libcmix-crypto/ed25519/ed25519.c36
-rw-r--r--libcmix-crypto/ed25519/ed25519.h71
-rw-r--r--libcmix-crypto/ed25519/gcrypt/CMakeLists.txt46
-rw-r--r--libcmix-crypto/ed25519/gcrypt/gcrypt_ed25519.c526
5 files changed, 711 insertions, 0 deletions
diff --git a/libcmix-crypto/ed25519/CMakeLists.txt b/libcmix-crypto/ed25519/CMakeLists.txt
new file mode 100644
index 0000000..3aae9fe
--- /dev/null
+++ b/libcmix-crypto/ed25519/CMakeLists.txt
@@ -0,0 +1,32 @@
+add_library(ed25519-interface INTERFACE)
+
+target_include_directories(ed25519-interface
+ INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+target_sources(ed25519-interface
+ INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/ed25519.h
+)
+
+target_link_libraries(ed25519-interface
+ INTERFACE cmix-crypto-interface
+)
+
+foreach(impl ${libcmix_crypto_ed25519_implementations})
+ add_subdirectory(${impl})
+endforeach()
+
+add_library(ed25519-implementation
+ ed25519.h ed25519.c
+)
+
+target_include_directories(ed25519-implementation
+ PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+target_link_libraries(ed25519-implementation
+ PUBLIC ed25519-interface
+ PUBLIC ed25519-${libcmix_crypto_ed25519_implementation}
+)
+
+
diff --git a/libcmix-crypto/ed25519/ed25519.c b/libcmix-crypto/ed25519/ed25519.c
new file mode 100644
index 0000000..835edfa
--- /dev/null
+++ b/libcmix-crypto/ed25519/ed25519.c
@@ -0,0 +1,36 @@
+
+#include "ed25519.h"
+
+struct Api get_ed25519_implementation()
+{
+ ed25519_initialize();
+ return (struct Api) {
+ .initialize = ed25519_initialize,
+ .create_keypair = ed25519_create_keypair,
+ .free_keypair = ed25519_delete_keypair,
+ .element_to_array = ed25519_element_to_array,
+ .free_buffer = ed25519_free_buffer,
+ .array_to_element = ed25519_array_to_element,
+ .message_to_element = ed25519_message_to_element,
+ .element_to_message = ed25519_element_to_message,
+ .get_pub_key_hash = ed25519_get_pub_key_hash,
+ .get_pub_key_hash_length = ed25519_get_pub_key_hash_length,
+ .get_group_element = ed25519_get_group_element,
+ .get_group_element_array_size = ed25519_get_group_element_array_size,
+ .get_message_size = ed25519_get_message_size,
+ .free_group_element = ed25519_delete_group_element,
+ .get_key_exchange_value = ed25519_get_key_exchange_value,
+ .combine = ed25519_combine,
+ .uncombine = ed25519_uncombine,
+ .get_decryption_share = ed25519_get_decryption_share,
+ .add_public_share = ed25519_add_public_share,
+ .derive_shared_key = ed25519_derive_shared_key,
+ .free_shared_key = ed25519_delete_shared_key,
+ .encrypt = ed25519_encrypt,
+ .invert = ed25519_invert,
+ .get_uniform_int = ed25519_get_uniform_int,
+ .deinitialize = ed25519_deinitialize
+ };
+}
+
+ImplementationGetter get_implementation = &get_ed25519_implementation;
diff --git a/libcmix-crypto/ed25519/ed25519.h b/libcmix-crypto/ed25519/ed25519.h
new file mode 100644
index 0000000..1cd9e66
--- /dev/null
+++ b/libcmix-crypto/ed25519/ed25519.h
@@ -0,0 +1,71 @@
+#pragma once
+
+#include "api.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!
+ * \file
+ */
+
+extern Initializer ed25519_initialize;
+
+extern KeyPairCreator ed25519_create_keypair;
+
+extern KeyPairDeleter ed25519_delete_keypair;
+
+extern ElementToArray ed25519_element_to_array;
+
+extern BufferDeleter ed25519_free_buffer;
+
+extern ArrayToElement ed25519_array_to_element;
+
+extern MessageToElement ed25519_message_to_element;
+
+extern ElementToMessage ed25519_element_to_message;
+
+extern PubKeyHashGetter ed25519_get_pub_key_hash;
+
+extern PubKeyHashLengthGetter ed25519_get_pub_key_hash_length;
+
+extern GroupElementGetter ed25519_get_group_element;
+
+extern GroupElementDeleter ed25519_delete_group_element;
+
+extern KeyExchangeValueGetter ed25519_get_key_exchange_value;
+
+extern GroupElementCombiner ed25519_combine;
+
+extern GroupElementUncombiner ed25519_uncombine;
+
+extern DecryptionShareGetter ed25519_get_decryption_share;
+
+extern GroupElementArraySizeGetter ed25519_get_group_element_array_size;
+
+extern MessageSizeGetter ed25519_get_message_size;
+
+extern PublicShareAdder ed25519_add_public_share;
+
+extern SharedKeyDeriver ed25519_derive_shared_key;
+
+extern SharedKeyDeleter ed25519_delete_shared_key;
+
+extern Encrypter ed25519_encrypt;
+
+extern Inverter ed25519_invert;
+
+extern UniformIntGetter ed25519_get_uniform_int;
+
+extern Deinitializer ed25519_deinitialize;
+
+/*!
+ * \brief get_ed25519_implementation
+ * \return An Api struct filled with a ed25519 implementation.
+ */
+struct Api get_ed25519_implementation();
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/libcmix-crypto/ed25519/gcrypt/CMakeLists.txt b/libcmix-crypto/ed25519/gcrypt/CMakeLists.txt
new file mode 100644
index 0000000..d020e4b
--- /dev/null
+++ b/libcmix-crypto/ed25519/gcrypt/CMakeLists.txt
@@ -0,0 +1,46 @@
+include(get_target_name)
+
+get_target_name(target_name algo api)
+
+find_package(Gcrypt REQUIRED)
+
+option(trace_pointers "trace alloced pointers by gcrypt" OFF)
+
+add_library(${target_name} SHARED
+ gcrypt_ed25519.c
+)
+
+set_property(SOURCE gcrypt_ed25519.c PROPERTY COMPILE_DEFINITIONS
+ API=${api};ALGORITHM=${algo}
+)
+
+if(trace_pointers)
+ target_compile_definitions(${target_name}
+ PRIVATE "POINTER_TRACING"
+ )
+endif(trace_pointers)
+
+if(NOT Gcrypt_CFLAGS STREQUAL "")
+ IF(WIN32)
+ separate_arguments(flags WINDOWS_COMMAND ${Gcrypt_CFLAGS})
+ else(WIN32)
+ separate_arguments(flags UNIX_COMMAND ${Gcrypt_CFLAGS})
+ endif(WIN32)
+
+ foreach(flag ${flags})
+ target_compile_options(${target_name}
+ PUBLIC ${flag}
+ )
+ endforeach(flag)
+endif(NOT Gcrypt_CFLAGS STREQUAL "")
+
+if(UNIX)
+ target_link_libraries(${target_name}
+ PRIVATE m
+ )
+endif(UNIX)
+
+target_link_libraries(${target_name}
+ PRIVATE ed25519-interface
+ PUBLIC ${Gcrypt_LIBRARIES}
+)
diff --git a/libcmix-crypto/ed25519/gcrypt/gcrypt_ed25519.c b/libcmix-crypto/ed25519/gcrypt/gcrypt_ed25519.c
new file mode 100644
index 0000000..54202be
--- /dev/null
+++ b/libcmix-crypto/ed25519/gcrypt/gcrypt_ed25519.c
@@ -0,0 +1,526 @@
+#include "ed25519.h"
+
+#include "api.h"
+#include "impl_macros.h"
+
+#include "gcrypt.h"
+
+#include <stdint.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <math.h>
+
+#ifdef POINTER_TRACING
+ #define TRACE(FILE, LINE, PTR) \
+ fprintf(stderr, "%s %d %p\n", FILE, LINE, PTR);
+#else
+ #define TRACE(FILE, LINE, PTR)
+#endif
+
+static gcry_ctx_t ctx;
+
+static gcry_mpi_point_t g;
+static gcry_mpi_t p;
+
+static unsigned int nr_bits = 256;
+static unsigned int nr_point_bits = 256 * 2;
+static unsigned int nr_bytes = 256 / 8;
+static unsigned int stride = 16;
+
+void check(gcry_error_t error) {
+ if (error) {
+ fprintf (stderr, "Error: %s/%s\n", gcry_strsource (error), gcry_strerror (error));
+ exit(1);
+ }
+}
+
+void print_sexp(gcry_sexp_t exp) {
+ size_t required_size = gcry_sexp_sprint(exp, GCRYSEXP_FMT_ADVANCED, NULL, 0); //passing NULL as the buffer will return the size needed.
+
+ char* str = (char *) malloc(sizeof(char)*required_size);
+
+ gcry_sexp_sprint(exp, GCRYSEXP_FMT_ADVANCED, str, required_size); //So we ignore the size here.
+
+ printf("size = %zu\n", required_size);
+ for(size_t i = 0; i < required_size; i++)
+ printf("%c", str[i]);
+ printf("\n");
+
+ free(str);
+}
+
+void DEF(initialize)(void) {
+ if (!gcry_check_version (GCRYPT_VERSION)) {
+ fprintf(stderr, "libgcrypt version mismatch\n");
+ exit(-1);
+ }
+
+ gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
+ gcry_control (GCRYCTL_INIT_SECMEM, 32768, 0);
+ gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
+ gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+
+ gcry_error_t error;
+
+ error = gcry_mpi_ec_new(&ctx, NULL, "Ed25519");
+ check(error);
+
+ g = gcry_mpi_ec_get_point("g", ctx, false);
+ p = gcry_mpi_ec_get_mpi("p", ctx, false);
+}
+
+struct KeyPair DEF(create_keypair)(void) {
+ size_t parse_error_offset;
+ gcry_error_t error;
+
+ gcry_sexp_t key_gen_sexp;
+ error = gcry_sexp_build(&key_gen_sexp, &parse_error_offset, "(genkey (ecc (curve Ed25519)))", NULL);
+ check(error);
+
+ gcry_sexp_t key_pair;
+ error = gcry_pk_genkey(&key_pair, key_gen_sexp);
+ check(error);
+
+ gcry_mpi_t d;
+ gcry_mpi_t q_mpi;
+
+ gcry_sexp_extract_param(key_pair, "key-data!private-key", "q d", &q_mpi, &d, NULL);
+
+ gcry_mpi_point_t q = gcry_mpi_point_new(nr_point_bits);
+ error = gcry_mpi_ec_decode_point(q, q_mpi, ctx);
+ check(error);
+
+ assert(gcry_mpi_ec_curve_point(q, ctx));
+
+ gcry_mpi_release(q_mpi);
+ gcry_sexp_release(key_gen_sexp);
+ gcry_sexp_release(key_pair);
+
+ return (struct KeyPair) {
+ .sec = d,
+ .pub = q
+ };
+}
+
+void DEF(delete_keypair)(struct KeyPair* pair) {
+ gcry_mpi_release((gcry_mpi_t)pair->sec);
+ gcry_mpi_point_release((gcry_mpi_point_t)pair->pub);
+ pair->sec = NULL;
+ pair->pub = NULL;
+}
+
+void DEF(element_to_array)(unsigned char** buffer, size_t* len, GroupElement element) {
+ gcry_error_t error;
+
+ gcry_mpi_t x = gcry_mpi_new(nr_bits);
+ gcry_mpi_t y = gcry_mpi_new(nr_bits);
+
+ int ret = gcry_mpi_ec_get_affine(x, y, (gcry_mpi_point_t) element, ctx);
+
+ if(ret != 0) {
+ abort();
+ }
+
+ *len = nr_bytes * 2;
+ *buffer = (unsigned char*) calloc(*len, sizeof(unsigned char));
+
+ unsigned char* temp = (unsigned char*) calloc(nr_bytes, sizeof(unsigned char));
+ size_t nwritten = 0;
+
+ error = gcry_mpi_print(GCRYMPI_FMT_USG, temp, nr_bytes, &nwritten, (gcry_mpi_t) x);
+ check(error);
+ memcpy(*buffer + (nr_bytes - nwritten), temp, nwritten);
+
+ memset(temp, '\0', nr_bytes);
+ error = gcry_mpi_print(GCRYMPI_FMT_USG, temp, nr_bytes, &nwritten, (gcry_mpi_t) y);
+ check(error);
+ memcpy(*buffer + nr_bytes + (nr_bytes - nwritten), temp, nwritten);
+
+ free(temp);
+ gcry_mpi_release(y);
+ gcry_mpi_release(x);
+}
+
+GroupElement DEF(message_to_element)(char const* buffer, size_t len, bool secure) {
+ (void) secure;
+ gcry_error_t error;
+
+ assert(len == 31);
+
+ gcry_mpi_t mpi;
+ gcry_mpi_scan(&mpi, GCRYMPI_FMT_USG, buffer, len, NULL);
+
+ //mpi * stride
+ gcry_mpi_dump(mpi);
+ printf("\n");
+ gcry_mpi_lshift(mpi, mpi, (unsigned) lround(log2(stride)));
+ gcry_mpi_dump(mpi);
+ printf("\n");
+
+ char* encoded_point = (char*) calloc(nr_bytes+1, sizeof(char));
+ gcry_mpi_point_t point = gcry_mpi_point_new(0);
+ unsigned int count = 0;
+ do {
+ encoded_point[0] = 0x40;
+
+ unsigned int byte_size = (unsigned) ceil(gcry_mpi_get_nbits(mpi) / 8.0);
+ printf("byte_size: %i\n", byte_size);
+ //gcry_mpi_print(GCRYMPI_FMT_USG, (unsigned char*) encoded_point + 1 + (32 - byte_size), byte_size, NULL, mpi);
+ gcry_mpi_print(GCRYMPI_FMT_USG, (unsigned char*) encoded_point + 1, 32, NULL, mpi);
+
+ for(int i = 0; i < 16; i++) {
+ char temp = encoded_point[i+1];
+ encoded_point[i+1] = encoded_point[32-i];
+ encoded_point[32-i] = temp;
+ }
+
+ for(int i = 0; i < nr_bytes+1; i++) {
+ printf("%02x", 0xFF & (unsigned) encoded_point[i]);
+ }
+ printf("\n");
+
+ gcry_mpi_t encoded_mpi = gcry_mpi_new(0);
+ gcry_mpi_set_opaque_copy(encoded_mpi, encoded_point, (nr_bytes + 1) * sizeof(char) * 8);
+
+ error = gcry_mpi_ec_decode_point(point, encoded_mpi, ctx);
+ check(error);
+
+ gcry_mpi_t x = gcry_mpi_new(0);
+ gcry_mpi_t y = gcry_mpi_new(0);
+ gcry_mpi_ec_get_affine(x, y, point, ctx);
+
+ gcry_mpi_release(encoded_mpi);
+
+ printf("%i %i\n", count, stride);
+ gcry_mpi_dump(x);
+ printf(",\n");
+ gcry_mpi_dump(y);
+ printf("\n");
+ gcry_mpi_dump(mpi);
+ printf("\n");
+ gcry_mpi_dump(encoded_mpi);
+ printf("\n");
+ gcry_mpi_dump(p);
+ printf("\n");
+ assert(gcry_mpi_cmp(mpi, p) == -1);
+ assert(count < stride);
+ gcry_mpi_add_ui(mpi, mpi, 1);
+ count++;
+
+ if(!gcry_mpi_ec_curve_point(point, ctx)) {
+ gcry_mpi_point_release(point);
+ point = gcry_mpi_point_new(0);
+ }
+
+ } while(!gcry_mpi_ec_curve_point(point, ctx));
+
+ gcry_mpi_release(mpi);
+ free(encoded_point);
+
+ return point;
+}
+
+void DEF(element_to_message)(unsigned char** buffer, const GroupElement el) {
+ gcry_mpi_t y = gcry_mpi_new(0);
+ gcry_mpi_ec_get_affine(NULL, y, (gcry_mpi_point_t) el, ctx);
+
+ gcry_mpi_rshift(y, y, (unsigned) lround(log2(stride)));
+
+ size_t nr_written;
+ gcry_mpi_aprint(GCRYMPI_FMT_USG, buffer, &nr_written, y);
+
+ gcry_mpi_dump(y);
+ printf("\n");
+
+ assert(nr_written == 31);
+
+ gcry_mpi_release(y);
+}
+
+void DEF(free_buffer)(void* buffer) {
+ gcry_free(buffer);
+}
+
+GroupElement DEF(array_to_element)(char const* buffer, size_t len, bool secure) {
+ (void) secure;
+ size_t error_pos;
+ gcry_error_t error;
+
+ printf("%i\n", len);
+ for(int i = 0; i < len; i++) {
+ if(i == 32) { printf("\n"); }
+ printf("%02x", 0xFF & buffer[i]);
+ }
+ printf("\n");
+
+ gcry_mpi_t x;
+ error = gcry_mpi_scan(&x, GCRYMPI_FMT_USG, buffer, len/2, &error_pos);
+ check(error);
+
+ gcry_mpi_t y;
+ error = gcry_mpi_scan(&y, GCRYMPI_FMT_USG, buffer + len/2, len/2, &error_pos);
+
+ gcry_mpi_dump(y);
+ printf("\n");
+
+ gcry_mpi_point_t point = gcry_mpi_point_new(nr_point_bits);
+ gcry_mpi_point_set(point, x, y, GCRYMPI_CONST_ONE);
+
+ gcry_mpi_release(x);
+ gcry_mpi_release(y);
+
+ return point;
+}
+
+size_t DEF(get_pub_key_hash_length)(void) {
+ return 20;
+}
+
+//TODO: fix this up
+void DEF(get_pub_key_hash)(char** buffer, size_t* len, GroupElement const pub) {
+ (void)pub;
+ //gcry_sexp_t pubkey;
+ //gcry_error_t error;
+ //size_t err_off;
+
+ //error = gcry_sexp_build(&pubkey, &err_off, "(public-key (ecc (curve Curve25519) (flags eddsa) (q %M)))", (gcry_mpi_point_t) pub);
+ //check(error);
+
+ //*buffer = (char*) gcry_pk_get_keygrip(pubkey, NULL);
+ //TODO: see if we can instantiate a public key sexp;
+
+ gcry_mpi_t x = gcry_mpi_new(0);
+ gcry_mpi_t y = gcry_mpi_new(0);
+
+ gcry_mpi_point_get(x, y, NULL, (gcry_mpi_point_t)pub);
+
+ printf("pub: %p\n", pub);
+
+ fprintf(stderr, "lel1: ");
+ gcry_mpi_dump(x);
+ printf("\n");
+ fprintf(stderr, "lel2: ");
+ gcry_mpi_dump(y);
+ printf("\n");
+
+ *len = DEF(get_pub_key_hash_length)();
+ *buffer = (char*) calloc(*len, sizeof(char));
+
+ unsigned char* temp;
+ size_t len2;
+ DEF(element_to_array(&temp, &len2, pub));
+
+ if(len2 < *len) {
+ memcpy((*buffer) + (*len - len2), temp, len2);
+ } else {
+ memcpy(*buffer, temp, *len);
+ }
+ gcry_free(temp);
+
+ TRACE(__FILE__, __LINE__, *buffer);
+ //gcry_sexp_release(pubkey);
+}
+
+GroupElement DEF(get_group_element)(bool secure) {
+ (void) secure;
+ size_t parse_error_offset;
+ gcry_error_t error;
+
+ gcry_mpi_t a = NULL;
+ void* bytes = NULL;
+ do {
+ gcry_free(bytes);
+ gcry_mpi_release(a);
+ bytes = gcry_random_bytes_secure(nr_bytes, GCRY_VERY_STRONG_RANDOM);
+ TRACE(__FILE__, __LINE__, bytes);
+ error = gcry_mpi_scan(&a, GCRYMPI_FMT_USG, bytes, nr_bytes, &parse_error_offset);
+ check(error);
+ } while(gcry_mpi_cmp_ui(a, 0) == 0 || gcry_mpi_cmp(a, p) != -1);
+
+ char* encoded_point = (char*) calloc(nr_bytes+1, sizeof(char));
+ gcry_mpi_point_t point = gcry_mpi_point_new(0);
+ do {
+ encoded_point[0] = 0x40;
+
+ unsigned int byte_size = (unsigned) ceil(gcry_mpi_get_nbits(a) / 8.0);
+ gcry_mpi_print(GCRYMPI_FMT_USG, (unsigned char*) encoded_point + 1, 32, NULL, a);
+
+ for(int i = 0; i < 16; i++) {
+ char temp = encoded_point[i+1];
+ encoded_point[i+1] = encoded_point[32-i];
+ encoded_point[32-i] = temp;
+ }
+
+ gcry_mpi_t encoded_mpi = gcry_mpi_new(0);
+ gcry_mpi_set_opaque_copy(encoded_mpi, encoded_point, (nr_bytes + 1) * sizeof(char) * 8);
+
+ error = gcry_mpi_ec_decode_point(point, encoded_mpi, ctx);
+ check(error);
+
+ gcry_mpi_release(encoded_mpi);
+
+ if(!gcry_mpi_ec_curve_point(point, ctx)) {
+ gcry_mpi_point_release(point);
+ point = gcry_mpi_point_new(0);
+
+ gcry_mpi_add_ui(a, a, 1);
+ }
+
+ } while(!gcry_mpi_ec_curve_point(point, ctx));
+
+ gcry_mpi_release(a);
+ gcry_free(bytes);
+
+ return point;
+}
+
+GroupElement DEF(get_key_exchange_value)(GroupElement group_el) {
+ gcry_mpi_t x = gcry_mpi_new(nr_bits);
+ gcry_mpi_point_get(x, NULL, NULL, (gcry_mpi_point_t) group_el);
+
+ gcry_mpi_point_t mult = gcry_mpi_point_new(nr_point_bits);
+ gcry_mpi_ec_mul(mult, x, g, ctx);
+
+ gcry_mpi_release(x);
+
+ return mult;
+}
+
+GroupElement DEF(combine)(GroupElement lh, GroupElement rh, bool secure) {
+ (void) secure;
+ gcry_mpi_point_t addition = gcry_mpi_point_new(nr_point_bits);
+ gcry_mpi_ec_add(addition, (gcry_mpi_point_t)lh, (gcry_mpi_point_t)rh, ctx);
+ return addition;
+}
+
+GroupElement DEF(invert)(GroupElement const el) {
+ gcry_mpi_t x = gcry_mpi_new(nr_bits);
+ gcry_mpi_t y = gcry_mpi_new(nr_bits);
+
+ gcry_mpi_ec_get_affine(x, y, (gcry_mpi_point_t) el, ctx);
+
+ gcry_mpi_t neg_x = gcry_mpi_new(nr_bits);
+ gcry_mpi_subm(neg_x, p, x, p);
+
+ gcry_mpi_point_t point = gcry_mpi_point_set(NULL, neg_x, y, GCRYMPI_CONST_ONE);
+
+ gcry_mpi_release(neg_x);
+ gcry_mpi_release(x);
+ gcry_mpi_release(y);
+
+ return point;
+}
+
+void DEF(delete_group_element)(GroupElement element) {
+ gcry_mpi_point_release((gcry_mpi_point_t)element);
+}
+
+GroupElement DEF(uncombine)(GroupElement lh, GroupElement rh, bool secure) {
+ (void) secure;
+
+ gcry_mpi_point_t inv_rh = DEF(invert)(rh);
+ gcry_mpi_point_t ret = DEF(combine)(lh, inv_rh, secure);
+
+ //gcry_mpi_point_t ret = gcry_mpi_point_new(0);
+ //gcry_mpi_ec_sub(ret, (gcry_mpi_point_t)lh, (gcry_mpi_point_t)rh, ctx);
+ return ret;
+}
+
+GroupElement DEF(get_decryption_share)(GroupElement r, GroupElement e) {
+ gcry_mpi_point_t inv_d = gcry_mpi_point_new(nr_point_bits);
+ gcry_mpi_ec_mul(inv_d, (gcry_mpi_t)e, (gcry_mpi_point_t) r, ctx);
+
+ GroupElement d = DEF(invert)(inv_d);
+ gcry_mpi_point_release(inv_d);
+
+ return d;
+}
+
+size_t DEF(get_group_element_array_size)(void) {
+ return nr_bytes*2;
+}
+
+size_t DEF(get_message_size)(void) {
+ return nr_bytes-1;
+}
+
+void DEF(add_public_share)(GroupElement* el, char const* share, size_t in_len, GroupElement pubkey) {
+ GroupElement share_el = DEF(array_to_element)(share, in_len, false);
+ *el = DEF(combine)(share_el, pubkey, false);
+ gcry_mpi_point_release((gcry_mpi_point_t)share_el);
+}
+
+GroupElement DEF(derive_shared_key)(struct KeyPair keypair, unsigned char const* other_pub, size_t pub_len, unsigned char const* value, size_t value_len, void* priv_value, bool swap) {
+ (void)keypair;
+ (void)other_pub;
+ (void)pub_len;
+ (void)swap;
+
+ GroupElement ga = DEF(array_to_element)((const char*) value, value_len, false);
+
+ gcry_mpi_point_t gab = gcry_mpi_point_new(nr_point_bits);
+ gcry_mpi_ec_mul(gab, (gcry_mpi_t) priv_value, (gcry_mpi_point_t) ga, ctx);
+
+ gcry_mpi_point_release((gcry_mpi_point_t) ga);
+
+ return gab;
+}
+
+void DEF(delete_shared_key)(struct SharedKey* s) {
+ gcry_mpi_point_release((gcry_mpi_point_t)s->shared);
+ s->shared = NULL;
+}
+
+void DEF(encrypt)(GroupElement* random_element, GroupElement* message_element, GroupElement value, GroupElement key) {
+ GroupElement random = DEF(get_group_element)(true);
+
+ gcry_mpi_t random_mpi = gcry_mpi_new(nr_bits);
+ gcry_mpi_ec_get_affine(random_mpi, NULL, (gcry_mpi_point_t)random, ctx);
+
+ *random_element = gcry_mpi_point_new(nr_point_bits);
+ gcry_mpi_ec_mul((gcry_mpi_point_t)*random_element, random_mpi, g, ctx);
+
+ gcry_mpi_point_t c2 = gcry_mpi_point_new(nr_point_bits);
+ gcry_mpi_ec_mul(c2, random_mpi, (gcry_mpi_point_t) key, ctx);
+
+ *message_element = gcry_mpi_point_new(nr_point_bits);
+ gcry_mpi_ec_add((gcry_mpi_point_t)* message_element, c2, (gcry_mpi_point_t) value, ctx);
+
+ gcry_mpi_release(random_mpi);
+ gcry_mpi_point_release(c2);
+}
+
+unsigned int DEF(get_uniform_int)(unsigned int upper) {
+ unsigned int random_value;
+
+ if(upper == 0) {
+ void* buffer = gcry_random_bytes_secure(sizeof(unsigned int), GCRY_STRONG_RANDOM);
+ TRACE(__FILE__, __LINE__, buffer);
+ memcpy(&random_value, buffer, sizeof(unsigned int));
+ gcry_free(buffer);
+
+ return random_value;
+ }
+
+ unsigned int lower = -upper % upper;
+ do {
+ void* buffer = gcry_random_bytes_secure(sizeof(unsigned int), GCRY_STRONG_RANDOM);
+ TRACE(__FILE__, __LINE__, buffer);
+ memcpy(&random_value, buffer, sizeof(unsigned int));
+ gcry_free(buffer);
+
+ if (random_value >= lower)
+ return random_value % upper;
+
+
+ } while(true);
+}
+
+void DEF(deinitialize)(void) {
+ gcry_mpi_point_release(g);
+ gcry_mpi_release(p);
+ gcry_ctx_release(ctx);
+}
+
+LINK_IMPLEMENTATION \ No newline at end of file