aboutsummaryrefslogtreecommitdiff
path: root/libcmix/cmix.c
diff options
context:
space:
mode:
Diffstat (limited to 'libcmix/cmix.c')
-rw-r--r--libcmix/cmix.c180
1 files changed, 180 insertions, 0 deletions
diff --git a/libcmix/cmix.c b/libcmix/cmix.c
index e0256cf..6a39767 100644
--- a/libcmix/cmix.c
+++ b/libcmix/cmix.c
@@ -2,6 +2,7 @@
#include "cmix.h"
#include <string.h>
+#include <stdlib.h>
enum cmix_error permutation(struct CMixBuffer b) {
return no_error;
@@ -36,3 +37,182 @@ enum cmix_error calculate_shared_key_part(struct Bignum* result, struct Bignum p
}
return no_error;
}
+
+struct CMixContext initialize_cmix_context(struct Api api) {
+ return (struct CMixContext){
+ .api = api,
+ .nr_participants = 0,
+ .r = NULL,
+ .s = NULL,
+ .permutation = NULL,
+ .pirs = NULL
+ };
+}
+
+void release_mix(struct CMixContext* ctx) {
+ for(size_t i = 0; i < ctx->nr_participants; ++i) {
+ ctx->api.free_group_element(ctx->r[i]);
+ ctx->api.free_group_element(ctx->s[i]);
+ ctx->api.free_group_element(ctx->pirs[i]);
+ }
+ free(ctx->r);
+ free(ctx->s);
+ free(ctx->permutation);
+ free(ctx->pirs);
+}
+
+void deinitialize(struct CMixContext* ctx)
+{
+ ctx->api.free_keypair(&ctx->keypair);
+ release_mix(ctx);
+}
+
+void element_to_buffer(struct CMixContext const* ctx, char* out_buffer, GroupElement element) {
+ size_t el_size = get_group_element_array_size(ctx);
+
+ unsigned char* buffer;
+ size_t len;
+
+ ctx->api.element_to_array(&buffer, &len, element);
+ size_t diff = el_size - len;
+ memcpy(out_buffer + diff, buffer, len);
+ ctx->api.free_buffer(buffer);
+}
+
+enum cmix_error initialize_keypair(struct CMixContext* ctx)
+{
+ ctx->keypair = ctx->api.create_keypair();
+ return no_error;
+}
+
+enum cmix_error get_public_key(struct CMixContext const* ctx, char* buffer)
+{
+ element_to_buffer(ctx, buffer, ctx->keypair.pub);
+ return no_error;
+}
+
+enum cmix_error add_public_share(struct CMixContext const* ctx, char* buffer, char const* share) {
+ size_t len = get_group_element_array_size(ctx);
+
+ GroupElement el;
+ ctx->api.add_public_share(&el, share, len, ctx->keypair.pub);
+
+ element_to_buffer(ctx, buffer, el);
+ ctx->api.free_group_element(el);
+}
+
+enum cmix_error alloc_mix(struct CMixContext* ctx) {
+ ctx->r = (GroupElement*) calloc(ctx->nr_participants, sizeof(GroupElement));
+ ctx->s = (GroupElement*) calloc(ctx->nr_participants, sizeof(GroupElement));
+ ctx->permutation = (unsigned int*) calloc(ctx->nr_participants, sizeof(unsigned int));
+ ctx->pirs = (GroupElement*) calloc(ctx->nr_participants, sizeof(GroupElement));
+ if(!ctx->r || !ctx->s || !ctx->permutation || !ctx->pirs) {
+ return out_of_memory;
+ }
+ return no_error;
+}
+
+enum cmix_error start_mix(struct CMixContext* ctx, size_t nr_participants) {
+ release_mix(ctx);
+ ctx->nr_participants = nr_participants;
+ return alloc_mix(ctx);
+}
+
+enum cmix_error initialize_mix_randomness(struct CMixContext* ctx) {
+ for(size_t i = 0; i < ctx->nr_participants; ++i) {
+ ctx->r[i] = ctx->api.get_group_element(true);
+ ctx->s[i] = ctx->api.get_group_element(true);
+ ctx->permutation[i] = i;
+ }
+ return no_error;
+}
+
+size_t get_group_element_array_size(struct CMixContext const* ctx) {
+ return ctx->api.get_group_element_array_size();
+}
+
+enum cmix_error set_network_key(struct CMixContext* ctx, char const* buffer, size_t len) {
+ ctx->network_key = ctx->api.array_to_element(buffer, len, true);
+ return no_error;
+}
+
+enum cmix_error encrypt_r(struct CMixContext const* ctx, char* random_buffer, char* message_buffer, size_t index) {
+ GroupElement random_element;
+ GroupElement message_element;
+
+ ctx->api.encrypt(&random_element, &message_element, ctx->r[index], ctx->network_key);
+
+ element_to_buffer(ctx, random_buffer, random_element);
+ element_to_buffer(ctx, message_buffer, message_element);
+
+ return no_error;
+}
+
+enum cmix_error encrypt_r_and_multiply(struct CMixContext const* ctx, char* random_buffer, char* message_buffer, const char* random_element, const char* message_element, size_t index) {
+ GroupElement enc_random_element;
+ GroupElement enc_message_element;
+
+ ctx->api.encrypt(&enc_random_element, &enc_message_element, ctx->r[index], ctx->network_key);
+
+ size_t el_size = get_group_element_array_size(ctx);
+
+ GroupElement other_random_element = ctx->api.array_to_element(random_element, el_size, true);
+ GroupElement other_message_element = ctx->api.array_to_element(message_element, el_size, true);
+
+ GroupElement new_random_element = ctx->api.multiply(enc_random_element, other_random_element, true);
+ GroupElement new_message_element = ctx->api.multiply(enc_message_element, other_message_element, true);
+
+ element_to_buffer(ctx, random_buffer, new_random_element);
+ element_to_buffer(ctx, message_buffer, new_message_element);
+
+ ctx->api.free_group_element(enc_random_element);
+ ctx->api.free_group_element(enc_message_element);
+ ctx->api.free_group_element(other_random_element);
+ ctx->api.free_group_element(other_message_element);
+ ctx->api.free_group_element(new_random_element);
+ ctx->api.free_group_element(new_message_element);
+
+ return no_error;
+}
+
+enum cmix_error multiply_s(struct CMixContext const* ctx, char* r_out_buffer, char* m_out_buffer, char const* r_in_buffer, char const* m_in_buffer, size_t index) {
+ size_t el_size = get_group_element_array_size(ctx);
+
+ GroupElement random_r = ctx->api.array_to_element(r_in_buffer, el_size, true);
+ GroupElement message_r = ctx->api.array_to_element(m_in_buffer, el_size, true);
+
+ GroupElement random_s;
+ GroupElement message_s;
+
+ ctx->api.encrypt(&random_s, &message_s, ctx->s[index], ctx->network_key);
+
+ GroupElement random_pirs = ctx->api.multiply(random_r, random_s, true);
+ GroupElement message_pirs = ctx->api.multiply(message_r, message_s, true);
+
+ element_to_buffer(ctx, r_out_buffer, random_pirs);
+ element_to_buffer(ctx, m_out_buffer, message_pirs);
+
+ ctx->api.free_group_element(random_r);
+ ctx->api.free_group_element(message_r);
+ ctx->api.free_group_element(random_s);
+ ctx->api.free_group_element(message_s);
+
+ return no_error;
+}
+
+enum cmix_error key_exchange(struct CMixContext const* ctx, GroupElement* shared_key, char* public_key_buffer, char* exchange_value_buffer, char const* pubkey, char const* value) {
+ GroupElement priv_el = ctx->api.get_group_element(true);
+ GroupElement ex_val = ctx->api.get_key_exchange_value(priv_el);
+
+ size_t el_len = get_group_element_array_size(ctx);
+
+ *shared_key = ctx->api.derive_shared_key(ctx->keypair, (unsigned char*)pubkey, el_len, (unsigned char*)value, el_len, priv_el, true);
+
+ element_to_buffer(ctx, public_key_buffer, ctx->keypair.pub);
+ element_to_buffer(ctx, exchange_value_buffer, ex_val);
+
+ ctx->api.free_group_element(priv_el);
+ ctx->api.free_group_element(ex_val);
+
+ return no_error;
+}