#include "cmix.h" #include #include enum cmix_error permutation(struct CMixBuffer b) { return no_error; } enum cmix_error get_message(char* message, struct CMixBuffer b, unsigned int index) { if(index >= b.message_length) { return index_out_of_range; } strncpy(message, b.buffer + index * b.message_length, b.message_length); return no_error; } enum cmix_error set_message(char const* message, struct CMixBuffer b, unsigned int index) { if(index >= b.message_length) { return index_out_of_range; } strncpy(b.buffer + index * b.message_length, message, b.message_length); return no_error; } enum cmix_error calculate_shared_key_part(struct Bignum* result, struct Bignum partial_shared, struct Bignum my_share, struct Bignum mod) { if(multiply_mod(result, partial_shared, my_share, mod) != NoError) { return cmix_bignum_error; } 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[ctx->permutation[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; }