initial cryptography implementation

This commit is contained in:
Daniel Wagner 2019-09-24 06:50:02 -07:00 коммит произвёл Joey Dodds
Родитель 647510887e
Коммит e666de2826
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: D135B87AB5B74652
98 изменённых файлов: 1718 добавлений и 627 удалений

3
.gitignore поставляемый
Просмотреть файл

@ -6,3 +6,6 @@ main
compile_commands.json
html
doxygen
result
build
/src/electionguard/random_source.h

4
.gitmodules поставляемый
Просмотреть файл

@ -1,3 +1,3 @@
[submodule "doc/sphinx-typlog-theme"]
path = doc/sphinx-typlog-theme
[submodule "docs/sphinx-typlog-theme"]
path = docs/sphinx-typlog-theme
url = https://github.com/jbaum98/sphinx-typlog-theme

Просмотреть файл

@ -1,37 +1,64 @@
cmake_minimum_required(VERSION 3.13)
cmake_minimum_required(VERSION 3.14)
project("ElectionGuard SDK" LANGUAGES C)
project("ElectionGuard SDK" VERSION 0.0.1 LANGUAGES C)
enable_testing()
# Allow us to import cmake scripts from ./cmake
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS OFF)
add_library(electionguard STATIC
${PROJECT_SOURCE_DIR}/src/voting/coordinator.c
${PROJECT_SOURCE_DIR}/src/keyceremony/coordinator.c
${PROJECT_SOURCE_DIR}/src/keyceremony/trustee.c
${PROJECT_SOURCE_DIR}/src/voting/nouns.c
${PROJECT_SOURCE_DIR}/src/voting/tracker.c
${PROJECT_SOURCE_DIR}/src/voting/encrypter.c
${PROJECT_SOURCE_DIR}/src/decryption/coordinator.c
${PROJECT_SOURCE_DIR}/src/decryption/trustee.c
${PROJECT_SOURCE_DIR}/src/serialize/builtins.c
${PROJECT_SOURCE_DIR}/src/serialize/state.c
${PROJECT_SOURCE_DIR}/src/serialize/decryption.c
${PROJECT_SOURCE_DIR}/src/serialize/trustee_state.c
${PROJECT_SOURCE_DIR}/src/serialize/voting.c
${PROJECT_SOURCE_DIR}/src/serialize/keyceremony.c
${PROJECT_SOURCE_DIR}/src/serialize/crypto.c
${PROJECT_SOURCE_DIR}/src/crypto.c)
target_include_directories(electionguard
PUBLIC
$<INSTALL_INTERFACE:include>
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
PRIVATE
${PROJECT_SOURCE_DIR}/src)
add_library(electionguard
${PROJECT_SOURCE_DIR}/src/electionguard/crypto_reps.h
${PROJECT_SOURCE_DIR}/src/electionguard/voting/coordinator.c
${PROJECT_SOURCE_DIR}/src/electionguard/voting/num_ballots.h
${PROJECT_SOURCE_DIR}/src/electionguard/voting/message_reps.h
${PROJECT_SOURCE_DIR}/src/electionguard/voting/nouns.c
${PROJECT_SOURCE_DIR}/src/electionguard/voting/tracker.c
${PROJECT_SOURCE_DIR}/src/electionguard/voting/nouns.h
${PROJECT_SOURCE_DIR}/src/electionguard/voting/encrypter.c
${PROJECT_SOURCE_DIR}/src/electionguard/serialize/builtins.c
${PROJECT_SOURCE_DIR}/src/electionguard/serialize/trustee_state.h
${PROJECT_SOURCE_DIR}/src/electionguard/serialize/state.c
${PROJECT_SOURCE_DIR}/src/electionguard/serialize/keyceremony.h
${PROJECT_SOURCE_DIR}/src/electionguard/serialize/decryption.c
${PROJECT_SOURCE_DIR}/src/electionguard/serialize/voting.h
${PROJECT_SOURCE_DIR}/src/electionguard/serialize/crypto.h
${PROJECT_SOURCE_DIR}/src/electionguard/serialize/builtins.h
${PROJECT_SOURCE_DIR}/src/electionguard/serialize/trustee_state.c
${PROJECT_SOURCE_DIR}/src/electionguard/serialize/voting.c
${PROJECT_SOURCE_DIR}/src/electionguard/serialize/decryption.h
${PROJECT_SOURCE_DIR}/src/electionguard/serialize/keyceremony.c
${PROJECT_SOURCE_DIR}/src/electionguard/serialize/state.h
${PROJECT_SOURCE_DIR}/src/electionguard/serialize/crypto.c
${PROJECT_SOURCE_DIR}/src/electionguard/decryption/coordinator.c
${PROJECT_SOURCE_DIR}/src/electionguard/decryption/message_reps.h
${PROJECT_SOURCE_DIR}/src/electionguard/decryption/trustee.c
${PROJECT_SOURCE_DIR}/src/electionguard/keyceremony/coordinator.c
${PROJECT_SOURCE_DIR}/src/electionguard/keyceremony/message_reps.h
${PROJECT_SOURCE_DIR}/src/electionguard/keyceremony/trustee.c
${PROJECT_SOURCE_DIR}/src/electionguard/uint4096.c
${PROJECT_SOURCE_DIR}/src/electionguard/crypto.c
${PROJECT_SOURCE_DIR}/src/electionguard/random_source.h
${PROJECT_SOURCE_DIR}/src/electionguard/random_source.c
${PROJECT_SOURCE_DIR}/src/electionguard/trustee_state_rep.h
${PROJECT_SOURCE_DIR}/include/electionguard/max_values.h
${PROJECT_SOURCE_DIR}/include/electionguard/trustee_state.h
${PROJECT_SOURCE_DIR}/include/electionguard/voting/messages.h
${PROJECT_SOURCE_DIR}/include/electionguard/voting/encrypter.h
${PROJECT_SOURCE_DIR}/include/electionguard/voting/coordinator.h
${PROJECT_SOURCE_DIR}/include/electionguard/voting/tracker.h
${PROJECT_SOURCE_DIR}/include/electionguard/decryption/messages.h
${PROJECT_SOURCE_DIR}/include/electionguard/decryption/coordinator.h
${PROJECT_SOURCE_DIR}/include/electionguard/decryption/trustee.h
${PROJECT_SOURCE_DIR}/include/electionguard/crypto.h
${PROJECT_SOURCE_DIR}/include/electionguard/keyceremony/messages.h
${PROJECT_SOURCE_DIR}/include/electionguard/keyceremony/coordinator.h
${PROJECT_SOURCE_DIR}/include/electionguard/keyceremony/trustee.h
)
# Compiler flags
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
@ -44,13 +71,54 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
target_compile_options(electionguard PRIVATE -Wenum-compare)
endif()
# examples
add_subdirectory(examples)
# Set the public include directory depending on if the target is being exported
# or installed
target_include_directories(electionguard
SYSTEM PUBLIC
$<INSTALL_INTERFACE:include>
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
PRIVATE
${PROJECT_SOURCE_DIR}/src/electionguard
)
# documentation
set(DOXYGEN_INPUT ${PROJECT_SOURCE_DIR}/Doxyfile)
set(DOCS_OUTPUT ${PROJECT_BINARY_DIR}/html)
add_custom_target(docs
COMMAND doxygen ${DOXYGEN_INPUT}
COMMAND sphinx-build -b html ${PROJECT_SOURCE_DIR}/doc ${DOCS_OUTPUT}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
# Install the electionguard library in the default location, and associate
# electionguard with the ElectionGuard export
install(TARGETS electionguard EXPORT ElectionGuard)
# Install public header files
install(
DIRECTORY ${PROJECT_SOURCE_DIR}/include/electionguard
TYPE INCLUDE
FILES_MATCHING PATTERN "*.h*"
)
# Generate the build-tree ElectionGuardConfig.cmake for use in other cmake
# projects without needing to install
export(
EXPORT ElectionGuard
FILE "${CMAKE_CURRENT_BINARY_DIR}/ElectionGuard/ElectionGuardConfig.cmake"
)
# Generate the install-tree ElectionGuardConfig.cmake for use in other cmake
# projects after this library has been installed
install(
EXPORT ElectionGuard
FILE ElectionGuardConfig.cmake
DESTINATION lib/cmake/ElectionGuard
)
add_subdirectory(docs)
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/simple_build")
add_test(NAME build_simple
COMMAND "${CMAKE_COMMAND}"
-E env ElectionGuard_DIR=${CMAKE_CURRENT_BINARY_DIR}/ElectionGuard
"${CMAKE_CTEST_COMMAND}"
--build-and-test "${PROJECT_SOURCE_DIR}/examples/simple" "${CMAKE_CURRENT_BINARY_DIR}/simple_build"
--build-generator ${CMAKE_GENERATOR}
--test-command simple
)
include(CheckIncludeFiles)
check_include_files(bcrypt.h HAVE_BCRYPTGENRANDOM)
configure_file(${PROJECT_SOURCE_DIR}/src/electionguard/random_source.h.in ${PROJECT_SOURCE_DIR}/src/electionguard/random_source.h)

Просмотреть файл

@ -1,8 +1,14 @@
ElectionGuard SDK Mock Implementation
ElectionGuard SDK No-Cryptography Implementation
=====================================
This implementation of the ElectionGuard SDK serves to showcase the API
provided by the SDK. For more details about that API, see the
provided by the SDK. It focuses on specifying and fixing the API.
Although it currently doesn't have encryption, programming against the
header files presented in the include document should allow you to
develop a voting system that is automatically improved with encryption
as the develoment of the ElectionGuard SDK continues.
For more details about that API, see the
:ref:`include`.
.. _building:
@ -10,45 +16,34 @@ provided by the SDK. For more details about that API, see the
Building
--------
To enable cross-platform building, we use `cmake <https://cmake.org/>`_. Here
we describe how to use Microsoft Visual Studio and :program:`make`, but other
backends like :program:`ninja` should work as well.
To enable cross-platform building, we use `cmake
<https://cmake.org/>`_. Any generator should work, but we describe
here how build using `Visual Studio
<https://visualstudio.microsoft.com/>`_ and using a Unix-like shell.
Visual Studio
~~~~~~~~~~~~~
As long as you have the C++ CMake tools for Windows installed, :program:`cmake`
should automatically integrate with Visual Studio. This means you can build the
project from the IDE, for example by right-clicking :file:`CMakeLists.txt` and
then selecting ``Build``.
As long as you have the C++ CMake tools for Windows installed,
:program:`cmake` should automatically integrate with Visual Studio.
This means you can build the project from the IDE, for example by
selecting ``Build > Build All`` in the menu.
Unix-like Systems
~~~~~~~~~~~~~~~~~
First use :program:`cmake` to generate build instructions for some
generator like :program:`make` or :program:`ninja`. You can see a list
of available generators by running ``cmake -G``. We will assume from
now on that you are using the :program:`make` generator, but it should
be straightforward to build the corresponding targets with whatever
generator you choose to use.
First create a build directory and configure the build.
.. code:: sh
mkdir build
cd build
cmake ..
cmake -S . -B build
To build the SDK static library ``libelectionguard.a``, run
.. code:: sh
make electionguard
To build an example client of the SDK, run
.. code:: sh
make simple
cmake --build build
Testing
--------
@ -75,28 +70,45 @@ also execute the client directly to better examine the output it produces.
Visual Studio
~~~~~~~~~~~~~
As with building, you should be able to use the IDE to run the tests, for
example by right-clicking :file:`CMakeLists.txt` and then selecing ``Run Tests``.
To build and execute an example client of the SDK, run the tests,
for example by selecting ``Test > Run CTests for ElectionGuard SDK``.
The example client can also be built as a standalone project if it is
configured with the location of the SDK, but this is not covered here.
Unix-like Systems
~~~~~~~~~~~~~~~~~
From the build directory, run
To build and run an example client of the SDK, run the tests:
.. code:: sh
make test
cmake --build build --target test
Alternatively you can build the client as a stand-alone project.
Create a separate build directory for the client, configure the build
to refer to the built library, and build the client.
.. code:: sh
mkdir simple_build
ElectionGuard_DIR="$PWD/build/ElectionGuard" cmake -S examples/simple -B simple_build
cmake --build simple_build --target simple
The built binary should be located at :file:`simple_build/simple`.
Debugging
---------
To enable debug builds suitable for running with debuggers like
:program:`lldb`, set the ``CMAKE_BUILD_TYPE`` cmake variable to
``Debug``. From the command-line, this looks like
``Debug`` when configuring. From the command-line, this looks like
.. code:: sh
cmake -DCMAKE_BUILD_TYPE=Debug ..
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug
Developing
----------
@ -109,31 +121,15 @@ From the command-line, this looks like
.. code:: sh
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 ..
cmake -S . -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
Documentation
-------------
To build the HTML documentation, you will need to have
:program:`doxygen` installed, as well as :program:`python` with the
``sphinx`` and ``breathe`` packages. Then run
.. code:: sh
make docs
and the documentation will be built in the :file:`html` directory. You
can browse it locally by opening :file:`html/index.html`, or by
running a local server
.. code::sh
# python2
(cd html && python -m SimpleHTTPServer)
# python3
python3 -m http.server --directory html
``sphinx`` and ``breathe`` packages. Then configure your build with
the ``BUILD_DOCUMENTATION`` variable set and rebuild.
.. note::
@ -144,6 +140,24 @@ running a local server
git submodule update --init --recursive
.. code:: sh
cmake -S . -B build -DBUILD_DOCUMENTATION=ON
cmake --build build
and the documentation will be built in the :file:`build/docs/html`
directory. You can browse it locally by opening
:file:`build/docs/html/index.html`, or by running a local server
.. code::sh
# python2
(cd build/docs/html && python -m SimpleHTTPServer)
# python3
python3 -m http.server --directory build/docs/html
Memory Management/Ownership: Who frees what?
--------------------------------------------

8
cmake/FindSphinx.cmake Normal file
Просмотреть файл

@ -0,0 +1,8 @@
find_program(SPHINX_EXECUTABLE
NAMES sphinx-build
DOC "Sphinx documentation generator"
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Sphinx DEFAULT_MSG SPHINX_EXECUTABLE)

10
default.nix Normal file
Просмотреть файл

@ -0,0 +1,10 @@
let
rev = "ed27ba064ca6f8c783";
nixpkgs = builtins.fetchTarball {
url = "https://github.com/NixOS/nixpkgs/archive/${rev}.tar.gz";
sha256 = "1lhpbgi8gcdmwwwkgdvlqdk1n4hr5fri8vracl3axzh9n9qrdrxr";
};
in with import nixpkgs {}; rec {
electionguard = callPackages ./derivation.nix { };
simple = callPackages ./examples/simple { inherit electionguard; };
}

15
derivation.nix Normal file
Просмотреть файл

@ -0,0 +1,15 @@
{ stdenv, nix-gitignore, cmake, doxygen, pythonPackages }:
stdenv.mkDerivation {
pname = "electionguard-sdk";
version = "0.0.1";
nativeBuildInputs = with pythonPackages; [ cmake doxygen sphinx breathe ];
cmakeFlags = "-DBUILD_DOCUMENTATION=ON";
enableParallelBuilding = true;
doCheck = true;
src = nix-gitignore.gitignoreSource ["*.nix"] ./.;
}

Просмотреть файл

@ -1 +0,0 @@
.. include:: /../include/decryption/README.rst

Просмотреть файл

@ -1 +0,0 @@
.. include:: /../include/keyceremony/README.rst

Просмотреть файл

@ -1 +0,0 @@
.. include:: /../include/voting/README.rst

0
doc/.gitignore → docs/.gitignore поставляемый
Просмотреть файл

77
docs/CMakeLists.txt Normal file
Просмотреть файл

@ -0,0 +1,77 @@
option(BUILD_DOCUMENTATION
"Create and install the HTML based API documentation (requires Doxygen and Shinx)" OFF)
IF(BUILD_DOCUMENTATION)
find_package(Doxygen REQUIRED)
find_package(Sphinx REQUIRED)
set(DOXYGEN_INPUT_DIR ${PROJECT_SOURCE_DIR}/include)
set(DOXYGEN_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/doxygen)
set(DOXYGEN_INDEX_FILE ${DOXYGEN_OUTPUT_DIR}/xml/index.xml)
set(DOXYFILE_IN ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in)
set(DOXYFILE_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
configure_file(${DOXYFILE_IN} ${DOXYFILE_OUT} @ONLY)
get_target_property(ELECTIONGUARD_PUBLIC_HEADER_DIR electionguard INTERFACE_INCLUDE_DIRECTORIES)
file(GLOB_RECURSE ELECTIONGUARD_PUBLIC_HEADERS ${ELECTIONGUARD_PUBLIC_HEADER_DIR}/*.h)
add_custom_command(
OUTPUT ${DOXYGEN_INDEX_FILE}
DEPENDS ${ELECTIONGUARD_PUBLIC_HEADERS}
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYFILE_OUT}
MAIN_DEPENDENCY ${DOXYFILE_OUT} ${DOXYFILE_IN}
COMMENT "Generating doxygen XML"
)
add_custom_target(Doxygen ALL DEPENDS ${DOXYGEN_INDEX_FILE})
set(SPHINX_SOURCE ${CMAKE_CURRENT_SOURCE_DIR})
set(SPHINX_BUILD ${CMAKE_CURRENT_BINARY_DIR}/html)
set(SPHINX_CACHE ${CMAKE_CURRENT_BINARY_DIR}/_doctrees)
set(SPHINX_INDEX_FILE ${SPHINX_BUILD}/index.html)
set(ELECTIONGUARD_RST
${PROJECT_SOURCE_DIR}/README.rst
${PROJECT_SOURCE_DIR}/include/electionguard/README.rst
${PROJECT_SOURCE_DIR}/include/electionguard/keyceremony/README.rst
${PROJECT_SOURCE_DIR}/include/electionguard/voting/README.rst
${PROJECT_SOURCE_DIR}/include/electionguard/decryption/README.rst
${CMAKE_CURRENT_SOURCE_DIR}/index.rst
${CMAKE_CURRENT_SOURCE_DIR}/examples.rst
${CMAKE_CURRENT_SOURCE_DIR}/voting.rst
${CMAKE_CURRENT_SOURCE_DIR}/keyceremony.rst
${CMAKE_CURRENT_SOURCE_DIR}/examples/simple.rst
${CMAKE_CURRENT_SOURCE_DIR}/api/index.rst
${CMAKE_CURRENT_SOURCE_DIR}/api/crypto.rst
${CMAKE_CURRENT_SOURCE_DIR}/api/trustee_state.rst
${CMAKE_CURRENT_SOURCE_DIR}/api/voting/coordinator.rst
${CMAKE_CURRENT_SOURCE_DIR}/api/voting/encrypter.rst
${CMAKE_CURRENT_SOURCE_DIR}/api/voting/messages.rst
${CMAKE_CURRENT_SOURCE_DIR}/api/voting/tracker.rst
${CMAKE_CURRENT_SOURCE_DIR}/api/decryption/coordinator.rst
${CMAKE_CURRENT_SOURCE_DIR}/api/decryption/trustee.rst
${CMAKE_CURRENT_SOURCE_DIR}/api/decryption/messages.rst
${CMAKE_CURRENT_SOURCE_DIR}/api/keyceremony/coordinator.rst
${CMAKE_CURRENT_SOURCE_DIR}/api/keyceremony/trustee.rst
${CMAKE_CURRENT_SOURCE_DIR}/api/keyceremony/messages.rst
${CMAKE_CURRENT_SOURCE_DIR}/api/max_values.rst
${CMAKE_CURRENT_SOURCE_DIR}/decryption.rst
)
add_custom_command(
OUTPUT ${SPHINX_INDEX_FILE}
COMMAND ${SPHINX_EXECUTABLE} -b html
-Dbreathe_projects.ElectionGuardSDK=${DOXYGEN_OUTPUT_DIR}/xml
-d ${SPHINX_CACHE}
${SPHINX_SOURCE} ${SPHINX_BUILD}
WORKING_DIRECTORY ${SPHINX_SOURCE}
MAIN_DEPENDENCY ${SPHINX_SOURCE}/conf.py
DEPENDS ${ELECTIONGUARD_RST} ${DOXYGEN_INDEX_FILE}
COMMENT "Generating HTML documentation"
)
add_custom_target(Sphinx ALL DEPENDS ${SPHINX_INDEX_FILE})
install(DIRECTORY ${SPHINX_BUILD} TYPE DOC)
endif()

Просмотреть файл

@ -58,7 +58,7 @@ PROJECT_LOGO =
# entered, it will be relative to the location where doxygen was started. If
# left blank the current directory will be used.
OUTPUT_DIRECTORY = "doxygen"
OUTPUT_DIRECTORY = "@DOXYGEN_OUTPUT_DIR@"
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
# directories (in 2 levels) under the output directory of each output format and
@ -813,7 +813,7 @@ WARN_LOGFILE =
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.
INPUT = ./include
INPUT = "@DOXYGEN_INPUT_DIR@"
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -1,6 +1,6 @@
.. _include:
.. include:: ../../include/README.rst
.. include:: /../include/electionguard/README.rst
.. toctree::
:hidden:

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -52,8 +52,7 @@ extensions = [
]
# Breathe Configuration
breathe_projects = { "ElectionGuard SDK": "../doxygen/xml" }
breathe_default_project = "ElectionGuard SDK"
breathe_default_project = "ElectionGuardSDK"
breathe_domain_by_extension = {"h" : "c", "c" : "c"}
# Add any paths that contain templates here, relative to this directory.

1
docs/decryption.rst Normal file
Просмотреть файл

@ -0,0 +1 @@
.. include:: /../include/electionguard/decryption/README.rst

Просмотреть файл

Просмотреть файл

Просмотреть файл

1
docs/keyceremony.rst Normal file
Просмотреть файл

@ -0,0 +1 @@
.. include:: /../include/electionguard/keyceremony/README.rst

1
docs/voting.rst Normal file
Просмотреть файл

@ -0,0 +1 @@
.. include:: /../include/electionguard/voting/README.rst

Просмотреть файл

@ -1,19 +0,0 @@
# simple example
add_executable(simple
${CMAKE_CURRENT_SOURCE_DIR}/simple/main.c
${CMAKE_CURRENT_SOURCE_DIR}/simple/main_keyceremony.c
${CMAKE_CURRENT_SOURCE_DIR}/simple/main_voting.c
${CMAKE_CURRENT_SOURCE_DIR}/simple/main_decryption.c)
target_include_directories(simple PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(simple electionguard)
add_test(NAME simple COMMAND simple)
add_test(NAME build_simple
COMMAND "${CMAKE_COMMAND}"
--build "${CMAKE_BINARY_DIR}"
--target simple
)
set_tests_properties(simple PROPERTIES FIXTURES_REQUIRED simple)
set_tests_properties(build_simple PROPERTIES FIXTURES_SETUP simple)

Просмотреть файл

@ -0,0 +1,27 @@
cmake_minimum_required(VERSION 3.13)
project("ElectionGuard Simple Example Client" VERSION 0.0.1 LANGUAGES C)
enable_testing()
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS ON)
add_executable(simple
${PROJECT_SOURCE_DIR}/main_params.h
${PROJECT_SOURCE_DIR}/main_voting.h
${PROJECT_SOURCE_DIR}/main_decryption.c
${PROJECT_SOURCE_DIR}/main_keyceremony.c
${PROJECT_SOURCE_DIR}/main.c
${PROJECT_SOURCE_DIR}/main_voting.c
${PROJECT_SOURCE_DIR}/main_keyceremony.h
${PROJECT_SOURCE_DIR}/main_decryption.h
)
find_package(ElectionGuard REQUIRED)
target_link_libraries(simple electionguard)
add_test(NAME simple COMMAND simple)
install(TARGETS simple)

Просмотреть файл

@ -0,0 +1,13 @@
{ stdenv, nix-gitignore, cmake, electionguard }:
stdenv.mkDerivation {
pname = "electionguard-sdk";
version = "0.0.1";
nativeBuildInputs = [ cmake electionguard ];
enableParallelBuilding = true;
doCheck = true;
src = nix-gitignore.gitignoreSourcePure ["*.nix" ../../.gitignore] ./.;
}

Просмотреть файл

@ -6,7 +6,7 @@
#include <io.h>
#endif
#include "max_values.h"
#include <electionguard/max_values.h>
#include "main_decryption.h"
#include "main_keyceremony.h"
@ -104,9 +104,10 @@ FILE *fmkstemps(char const *template, const char *mode)
{
bool ok = true;
int result_fd = -1;
FILE *result = NULL;
// Duplicate the template. It needs to be mutable for mkstemps.
// Duplicate the template. It needs to be mutable for mkstemp.
char *template_mut = strdup(template);
if (template_mut == NULL)
ok = false;
@ -114,15 +115,15 @@ FILE *fmkstemps(char const *template, const char *mode)
// Create and open the temporary file
if (ok)
{
template_mut = mktemp(template_mut);
if (template_mut == NULL)
result_fd = mkstemp(template_mut);
if (-1 == result_fd)
ok = false;
}
// Convert the file descripter to a FILE*
// Convert the file descriptor to a FILE*
if (ok)
{
result = fopen(template_mut, mode);
result = fdopen(result_fd, mode);
if (result == NULL)
ok = false;
}

Просмотреть файл

@ -2,8 +2,8 @@
#include <stdlib.h>
#include <string.h>
#include "decryption/coordinator.h"
#include "decryption/trustee.h"
#include <electionguard/decryption/coordinator.h>
#include <electionguard/decryption/trustee.h>
#include "main_decryption.h"
#include "main_params.h"

Просмотреть файл

@ -5,9 +5,9 @@
#include <stdint.h>
#include <stdio.h>
#include "crypto.h"
#include "max_values.h"
#include "trustee_state.h"
#include <electionguard/crypto.h>
#include <electionguard/max_values.h>
#include <electionguard/trustee_state.h>
bool decryption(FILE *in, FILE *out, struct trustee_state *trustee_states);

Просмотреть файл

@ -1,9 +1,9 @@
#ifndef __MAIN_KEY_CEREMONY_H__
#define __MAIN_KEY_CEREMONY_H__
#include "keyceremony/coordinator.h"
#include "keyceremony/messages.h"
#include "keyceremony/trustee.h"
#include <electionguard/keyceremony/coordinator.h>
#include <electionguard/keyceremony/messages.h>
#include <electionguard/keyceremony/trustee.h>
/* Carry out the key ceremony phase of an election, storing the joint
key and trustee_states in the provided pointers. */

Просмотреть файл

@ -1,8 +1,9 @@
#include <stdlib.h>
#include <electionguard/voting/tracker.h>
#include "main_params.h"
#include "main_voting.h"
#include "voting/tracker.h"
static bool initialize_encrypters(struct joint_public_key joint_key);
@ -151,6 +152,7 @@ bool simulate_random_votes(uint32_t encrypter_ix, uint64_t num_ballots)
{
char *tracker_string = display_ballot_tracker(tracker);
int status = puts(tracker_string);
free(tracker_string);
if (status == EOF)
ok = false;
}

Просмотреть файл

@ -1,8 +1,8 @@
#ifndef __MAIN_VOTING_H__
#define __MAIN_VOTING_H__
#include "voting/coordinator.h"
#include "voting/encrypter.h"
#include <electionguard/voting/coordinator.h>
#include <electionguard/voting/encrypter.h>
bool voting(struct joint_public_key joint_key, FILE *out);

Просмотреть файл

Просмотреть файл

@ -3,7 +3,7 @@
#include <stddef.h>
#include "max_values.h"
#include <electionguard/max_values.h>
/** Size of a key in bytes. */
enum KEY_SIZE_e

Просмотреть файл

@ -5,8 +5,8 @@
#include <stdint.h>
#include <stdio.h>
#include "decryption/messages.h"
#include "max_values.h"
#include <electionguard/decryption/messages.h>
#include <electionguard/max_values.h>
// @design jwaksbaum Should we have separate entities to decrypt
// totals and spoiled ballots? The types are different, but maybe we
@ -28,6 +28,7 @@ enum Decryption_Coordinator_status
DECRYPTION_COORDINATOR_IO_ERROR,
DECRYPTION_COORDINATOR_SERIALIZE_ERROR,
DECRYPTION_COORDINATOR_DESERIALIZE_ERROR,
DECRYPTION_COORDINATOR_CONFUSED_DECRYPTION_TRUSTEE,
};
/************************** INITIALIZATION & FREEING ***************************/

Просмотреть файл

@ -4,8 +4,8 @@
#include <stdint.h>
#include <stdio.h>
#include "decryption/messages.h"
#include "trustee_state.h"
#include <electionguard/decryption/messages.h>
#include <electionguard/trustee_state.h>
typedef struct Decryption_Trustee_s *Decryption_Trustee;

Просмотреть файл

@ -4,8 +4,8 @@
#include <stdbool.h>
#include <stddef.h>
#include "crypto.h"
#include "keyceremony/messages.h"
#include <electionguard/crypto.h>
#include <electionguard/keyceremony/messages.h>
/**
* Responsible for coordinating communication between the trustees

Просмотреть файл

@ -3,10 +3,10 @@
#include <stdint.h>
#include "crypto.h"
#include "keyceremony/messages.h"
#include "max_values.h"
#include "trustee_state.h"
#include <electionguard/crypto.h>
#include <electionguard/keyceremony/messages.h>
#include <electionguard/max_values.h>
#include <electionguard/trustee_state.h>
typedef struct KeyCeremony_Trustee_s *KeyCeremony_Trustee;

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -3,7 +3,7 @@
#include <stdio.h>
#include "voting/messages.h"
#include <electionguard/voting/messages.h>
// @todo jwaksbaum What sort of assurances do we make about the
// machine being shut off? How does it persist votes?

Просмотреть файл

@ -3,8 +3,8 @@
#include <stdbool.h>
#include "crypto.h"
#include "voting/messages.h"
#include <electionguard/crypto.h>
#include <electionguard/voting/messages.h>
typedef struct Voting_Encrypter_s *Voting_Encrypter;
@ -14,6 +14,9 @@ enum Voting_Encrypter_status
VOTING_ENCRYPTER_INSUFFICIENT_MEMORY,
VOTING_ENCRYPTER_SERIALIZE_ERROR,
VOTING_ENCRYPTER_DESERIALIZE_ERROR,
VOTING_ENCRYPTER_IO_ERROR,
// It is a bug for the SDK to produce one of these.
VOTING_ENCRYPTER_UNKNOWN_ERROR
};
/************************** INITIALIZATION & FREEING ***************************/

Просмотреть файл

Просмотреть файл

@ -1,5 +1,5 @@
#pragma once
#include "messages.h"
#include <electionguard/voting/messages.h>
/**
* Produce a character representation of a ballot tracker, suitable

Просмотреть файл

@ -1,89 +0,0 @@
#include <stdlib.h>
#include <string.h>
#include "crypto.h"
#include "crypto_reps.h"
bool Crypto_public_key_equal(struct public_key const *key1,
struct public_key const *key2)
{
bool ok = true;
if (key1->threshold != key2->threshold)
ok = false;
for (uint32_t i = 0; i < key1->threshold && ok; i++)
for (uint32_t j = 0; j < KEY_SIZE && ok; j++)
if (key1->coef_committments[i].bytes[j] !=
key2->coef_committments[i].bytes[j])
ok = false;
return ok;
}
struct Crypto_gen_keypair_r Crypto_gen_keypair(uint32_t num_coefficients)
{
struct Crypto_gen_keypair_r result;
result.status = CRYPTO_SUCCESS;
result.private_key.threshold = num_coefficients;
result.public_key.threshold = num_coefficients;
// Set all bytes to a non-zero value to help catch bugs. Before I
// did this, I had a couple of bugs related to actually copying
// the keys around, but because everything was zeroes nothing
// broke.
for (uint32_t i = 0; i < num_coefficients; i++)
{
for (uint32_t j = 0; j < KEY_SIZE; j++)
{
result.private_key.coefficients[i].bytes[j] = rand();
result.public_key.coef_committments[i].bytes[j] = rand();
}
}
return result;
}
void Crypto_private_key_copy(struct private_key *dst,
struct private_key const *src)
{
dst->threshold = src->threshold;
for (uint32_t i = 0; i < src->threshold; i++)
memcpy(&dst->coefficients[i].bytes, &src->coefficients[i].bytes,
KEY_SIZE * sizeof(uint8_t));
}
void Crypto_public_key_copy(struct public_key *dst,
struct public_key const *src)
{
dst->threshold = src->threshold;
for (uint32_t i = 0; i < src->threshold; i++)
memcpy(&dst->coef_committments[i].bytes,
&src->coef_committments[i].bytes, KEY_SIZE * sizeof(uint8_t));
}
void Crypto_encrypted_key_share_copy(struct encrypted_key_share *dst,
struct encrypted_key_share const *src)
{
Crypto_private_key_copy(&dst->private_key, &src->private_key);
Crypto_public_key_copy(&dst->recipient_public_key,
&src->recipient_public_key);
}
void Crypto_joint_public_key_copy(struct joint_public_key_rep *dst,
struct joint_public_key_rep const *src)
{
dst->num_trustees = src->num_trustees;
for (uint32_t i = 0; i < src->num_trustees; i++)
Crypto_public_key_copy(&dst->public_keys[i], &src->public_keys[i]);
}
void Crypto_generate_joint_public_key(struct joint_public_key_rep *dst,
struct public_key const *public_keys,
uint32_t num_keys)
{
dst->num_trustees = num_keys;
for (uint32_t i = 0; i < num_keys; i++)
Crypto_public_key_copy(&dst->public_keys[i], &public_keys[i]);
}

162
src/electionguard/crypto.c Normal file
Просмотреть файл

@ -0,0 +1,162 @@
#include <stdlib.h>
#include <string.h>
#include <electionguard/crypto.h>
#include "random_source.h"
#include "crypto_reps.h"
bool Crypto_public_key_equal(struct public_key const *key1,
struct public_key const *key2)
{
bool ok = true;
if (key1->threshold != key2->threshold)
ok = false;
for (uint32_t i = 0; i < key1->threshold && ok; i++)
ok = ok && uint4096_eq(&key1->coef_commitments[i],
&key2->coef_commitments[i]);
return ok;
}
enum Crypto_status Crypto_RandomSource_status_convert(enum RandomSource_status status) {
switch(status) {
case RANDOM_SOURCE_SUCCESS: return CRYPTO_SUCCESS;
case RANDOM_SOURCE_INSUFFICIENT_MEMORY: return CRYPTO_INSUFFICIENT_MEMORY;
case RANDOM_SOURCE_IO_ERROR: return CRYPTO_IO_ERROR;
// should never happen
default: return CRYPTO_UNKNOWN_ERROR;
}
}
struct Crypto_gen_keypair_r Crypto_gen_keypair(uint32_t num_coefficients)
{
struct Crypto_gen_keypair_r result;
result.status = CRYPTO_SUCCESS;
result.private_key.threshold = num_coefficients;
result.public_key.threshold = num_coefficients;
RandomSource source;
if(CRYPTO_SUCCESS == result.status) {
struct RandomSource_new_r source_r = RandomSource_new();
source = source_r.source;
result.status = Crypto_RandomSource_status_convert(source_r.status);
}
// Set all bytes to a non-zero value to help catch bugs. Before I
// did this, I had a couple of bugs related to actually copying
// the keys around, but because everything was zeroes nothing
// broke.
for (uint32_t i = 0; i < num_coefficients; i++)
{
if(CRYPTO_SUCCESS == result.status) {
result.status = Crypto_RandomSource_status_convert(RandomSource_uniform_o(source, &result.private_key.coefficients[i]));
if(CRYPTO_SUCCESS != result.status) {
RandomSource_free(source);
}
}
if(CRYPTO_SUCCESS == result.status) {
uint4096_powmod_o
( &result.public_key.coef_commitments[i]
, uint4096_generator_default
, &result.private_key.coefficients[i]
, Modulus4096_modulus_default
);
}
}
if(CRYPTO_SUCCESS == result.status) {
RandomSource_free(source);
}
return result;
}
void Crypto_private_key_copy(struct private_key *dst,
struct private_key const *src)
{
dst->threshold = src->threshold;
for (uint32_t i = 0; i < src->threshold; i++)
uint4096_copy_o(&dst->coefficients[i], &src->coefficients[i]);
}
void Crypto_public_key_copy(struct public_key *dst,
struct public_key const *src)
{
dst->threshold = src->threshold;
for (uint32_t i = 0; i < src->threshold; i++)
uint4096_copy_o(&dst->coef_commitments[i], &src->coef_commitments[i]);
}
void Crypto_encrypted_key_share_copy(struct encrypted_key_share *dst,
struct encrypted_key_share const *src)
{
Crypto_private_key_copy(&dst->private_key, &src->private_key);
Crypto_public_key_copy(&dst->recipient_public_key,
&src->recipient_public_key);
}
void Crypto_joint_public_key_copy(struct joint_public_key_rep *dst,
struct joint_public_key_rep const *src)
{
dst->num_trustees = src->num_trustees;
uint4096_copy_o(&dst->public_key, &src->public_key);
}
void Crypto_generate_joint_public_key(struct joint_public_key_rep *dst,
struct public_key const *public_keys,
uint32_t num_keys)
{
dst->num_trustees = num_keys;
uint4096_zext_o(&dst->public_key, (uint8_t[]){1}, 1);
for (uint32_t i = 0; i < num_keys; i++)
uint4096_multmod_o(&dst->public_key, &dst->public_key, &public_keys[i].coef_commitments[0], Modulus4096_modulus_default);
}
void Crypto_encrypt(struct encryption_rep *out, RandomSource source, const struct joint_public_key_rep *key, const_uint4096 message) {
struct uint4096_s r;
RandomSource_uniform_o(source, &r);
uint4096_powmod_o(&out->nonce_encoding, uint4096_generator_default, &r, Modulus4096_modulus_default);
uint4096_powmod_o(&out->message_encoding, &key->public_key, &r, Modulus4096_modulus_default);
uint4096_multmod_o(&out->message_encoding, &out->message_encoding, message, Modulus4096_modulus_default);
}
void Crypto_encryption_homomorphic_zero(struct encryption_rep *out) {
uint4096_zext_o(&out->nonce_encoding, (uint8_t[]){1}, 1);
uint4096_zext_o(&out->message_encoding, (uint8_t[]){1}, 1);
}
void Crypto_encryption_homomorphic_add(struct encryption_rep *out, const struct encryption_rep *a, const struct encryption_rep *b) {
uint4096_multmod_o(&out->nonce_encoding, &a->nonce_encoding, &b->nonce_encoding, Modulus4096_modulus_default);
uint4096_multmod_o(&out->message_encoding, &a->message_encoding, &b->message_encoding, Modulus4096_modulus_default);
}
bool Crypto_encryption_fprint(FILE *out, const struct encryption_rep *rep) {
bool ok = true;
if(ok) ok = fprintf(out, "(") == 1;
if(ok) ok = uint4096_fprint(out, &rep->nonce_encoding);
if(ok) ok = fprintf(out, ",") == 1;
if(ok) ok = uint4096_fprint(out, &rep->message_encoding);
if(ok) ok = fprintf(out, ")") == 1;
return ok;
}
struct Crypto_encrypted_ballot_new_r Crypto_encrypted_ballot_new(uint32_t num_selections, uint64_t id) {
struct Crypto_encrypted_ballot_new_r result;
result.result.id = id;
result.result.num_selections = num_selections;
result.result.selections = malloc(num_selections * sizeof(*result.result.selections));
if(NULL == result.result.selections)
result.status = CRYPTO_INSUFFICIENT_MEMORY;
return result;
}
void Crypto_encrypted_ballot_free(struct encrypted_ballot_rep *ballot) {
free(ballot->selections);
}

Просмотреть файл

@ -5,27 +5,25 @@
#include <stddef.h>
#include <stdint.h>
// @todo jwaksbaum Fix name clashes with MSC
#include "../include/crypto.h"
#include "max_values.h"
#include <electionguard/crypto.h>
#include <electionguard/max_values.h>
#include "random_source.h"
#include "uint4096.h"
enum Crypto_status
{
CRYPTO_SUCCESS,
CRYPTO_INSUFFICIENT_MEMORY,
};
/* A single secret or coefficient, ie. a 4096 bit number for now. */
struct key
{
uint8_t bytes[KEY_SIZE];
CRYPTO_IO_ERROR,
// it is a bug for the SDK to generate one of these
CRYPTO_UNKNOWN_ERROR
};
/* A private key, including coefficients */
struct private_key
{
uint32_t threshold;
struct key coefficients[MAX_TRUSTEES];
struct uint4096_s coefficients[MAX_TRUSTEES];
};
void Crypto_private_key_copy(struct private_key *dst,
@ -35,7 +33,7 @@ void Crypto_private_key_copy(struct private_key *dst,
struct public_key
{
uint32_t threshold;
struct key coef_committments[MAX_TRUSTEES];
struct uint4096_s coef_commitments[MAX_TRUSTEES];
};
/* Check if two public keys are equal. */
@ -72,7 +70,7 @@ void Crypto_encrypted_key_share_copy(struct encrypted_key_share *dst,
struct joint_public_key_rep
{
uint32_t num_trustees;
struct public_key public_keys[MAX_TRUSTEES];
struct uint4096_s public_key;
};
void Crypto_joint_public_key_copy(struct joint_public_key_rep *dst,
@ -84,4 +82,31 @@ void Crypto_generate_joint_public_key(struct joint_public_key_rep *dst,
struct public_key const *public_keys,
uint32_t num_keys);
struct encryption_rep
{
struct uint4096_s nonce_encoding;
struct uint4096_s message_encoding;
};
void Crypto_encrypt(struct encryption_rep *out, RandomSource source, const struct joint_public_key_rep *key, const_uint4096 message);
void Crypto_encryption_homomorphic_zero(struct encryption_rep *out);
void Crypto_encryption_homomorphic_add(struct encryption_rep *out, const struct encryption_rep *a, const struct encryption_rep *b);
bool Crypto_encryption_fprint(FILE *out, const struct encryption_rep *rep);
struct encrypted_ballot_rep
{
uint64_t id;
uint32_t num_selections;
struct encryption_rep *selections;
};
struct Crypto_encrypted_ballot_new_r {
enum Crypto_status status;
struct encrypted_ballot_rep result;
};
struct Crypto_encrypted_ballot_new_r Crypto_encrypted_ballot_new(uint32_t num_selections, uint64_t id);
void Crypto_encrypted_ballot_free(struct encrypted_ballot_rep *ballot);
#endif /* __CRYPTO_REPS_H__ */

Просмотреть файл

@ -3,9 +3,10 @@
#include <stdlib.h>
#include <string.h>
#include "decryption/coordinator.h"
#include <electionguard/decryption/coordinator.h>
#include <electionguard/max_values.h>
#include "decryption/message_reps.h"
#include "max_values.h"
#include "serialize/decryption.h"
struct Decryption_Coordinator_s
@ -20,7 +21,7 @@ struct Decryption_Coordinator_s
// Record the tallies from any trustee to return
bool tallies_initialized;
uint64_t num_tallies;
uint64_t tallies[MAX_SELECTIONS];
struct encryption_rep tallies[MAX_SELECTIONS]; // \Prod_i M_i in the spec
// Which trustees have responded, and with which decryption_fragments
bool responded[MAX_TRUSTEES];
@ -95,19 +96,25 @@ Decryption_Coordinator_receive_share(Decryption_Coordinator c,
status = DECRYPTION_COORDINATOR_DUPLICATE_TRUSTEE_INDEX;
}
if (status == DECRYPTION_COORDINATOR_SUCCESS)
if (status == DECRYPTION_COORDINATOR_SUCCESS) {
c->anounced[share_rep.trustee_index] = true;
// If this is the first trustee we've seen, record the tallies
// @todo jwaksbaum We could check that everyone agrees, but for
// this version I don't think it's worth the trouble
if (!c->tallies_initialized)
{
memcpy(c->tallies, share_rep.tallies,
share_rep.num_tallies * sizeof(uint64_t));
c->num_tallies = share_rep.num_tallies;
c->tallies_initialized = true;
if(c->tallies_initialized) {
if(share_rep.num_tallies != c->num_tallies) {
status = DECRYPTION_COORDINATOR_CONFUSED_DECRYPTION_TRUSTEE;
}
for(size_t i = 0; i < share_rep.num_tallies && DECRYPTION_COORDINATOR_SUCCESS == status; i++) {
uint4096_multmod_o(&c->tallies[i].nonce_encoding, &c->tallies[i].nonce_encoding, &share_rep.tally_share[i].nonce_encoding, Modulus4096_modulus_default);
if(!uint4096_eq(&c->tallies[i].message_encoding, &share_rep.tally_share[i].message_encoding))
status = DECRYPTION_COORDINATOR_CONFUSED_DECRYPTION_TRUSTEE;
}
} else {
c->num_tallies = share_rep.num_tallies;
for(size_t i = 0; i < share_rep.num_tallies; i++) {
uint4096_copy_o(&c->tallies[i].nonce_encoding, &share_rep.tally_share[i].nonce_encoding);
uint4096_copy_o(&c->tallies[i].message_encoding, &share_rep.tally_share[i].message_encoding);
}
c->tallies_initialized = true;
}
}
return status;
@ -305,9 +312,24 @@ Decryption_Coordinator_all_fragments_received(Decryption_Coordinator c,
for (uint64_t i = 0;
i < c->num_tallies && status == DECRYPTION_COORDINATOR_SUCCESS; i++)
{
int io_status = fprintf(out, "%" PRIu64 "\n", c->tallies[i]);
if (io_status < 0)
// TODO: the division and discrete log parts of the decryption
const char *preamble_format = "tally %" PRIu64 ": ";
const int expected_len = snprintf(NULL, 0, preamble_format, i);
if(fprintf(out, preamble_format, i) < expected_len)
status = DECRYPTION_COORDINATOR_IO_ERROR;
if(DECRYPTION_COORDINATOR_SUCCESS == status) {
if(!Crypto_encryption_fprint(out, &c->tallies[i])) {
status = DECRYPTION_COORDINATOR_IO_ERROR;
}
}
if(DECRYPTION_COORDINATOR_SUCCESS == status) {
if(fprintf(out, "\n") < 1) {
status = DECRYPTION_COORDINATOR_IO_ERROR;
}
}
}
return status;

Просмотреть файл

@ -4,13 +4,14 @@
#include <stdbool.h>
#include <stdint.h>
#include "max_values.h"
#include <electionguard/max_values.h>
#include "crypto_reps.h"
struct decryption_share_rep
{
uint32_t trustee_index;
uint64_t num_tallies;
uint64_t tallies[MAX_SELECTIONS];
struct encryption_rep tally_share[MAX_SELECTIONS];
};
struct decryption_fragments_request_rep

Просмотреть файл

@ -2,9 +2,10 @@
#include <stdlib.h>
#include <string.h>
#include <electionguard/decryption/trustee.h>
#include "crypto_reps.h"
#include "decryption/message_reps.h"
#include "decryption/trustee.h"
#include "serialize/decryption.h"
#include "serialize/trustee_state.h"
#include "trustee_state_rep.h"
@ -15,7 +16,7 @@ struct Decryption_Trustee_s
uint32_t threshold;
uint32_t num_selections;
uint32_t index;
uint64_t tallies[MAX_SELECTIONS];
struct encryption_rep tallies[MAX_SELECTIONS];
//@secret the private key must not be leaked from the system
struct private_key private_key;
};
@ -63,7 +64,9 @@ Decryption_Trustee_new(uint32_t num_trustees, uint32_t threshold,
result.decryptor->threshold = threshold;
result.decryptor->num_selections = num_selections;
result.decryptor->index = state_rep.index;
memset(result.decryptor->tallies, 0, MAX_SELECTIONS * sizeof(uint64_t));
for(size_t i = 0; i < MAX_SELECTIONS; i++) {
Crypto_encryption_homomorphic_zero(&result.decryptor->tallies[i]);
}
Crypto_private_key_copy(&result.decryptor->private_key,
&state_rep.private_key);
}
@ -75,7 +78,7 @@ void Decryption_Trustee_free(Decryption_Trustee d) { free(d); }
static enum Decryption_Trustee_status
Decryption_Trustee_read_ballot(FILE *in, uint64_t *ballot_id, bool *cast,
uint32_t num_selections, bool *selections)
uint32_t num_selections, struct encryption_rep *selections)
{
enum Decryption_Trustee_status status = DECRYPTION_TRUSTEE_SUCCESS;
@ -91,22 +94,39 @@ Decryption_Trustee_read_ballot(FILE *in, uint64_t *ballot_id, bool *cast,
for (uint32_t i = 0;
i < num_selections && status == DECRYPTION_TRUSTEE_SUCCESS; i++)
{
int selection;
int num_read = fscanf(in, "\t%d", &selection);
if (num_read != 1)
int num_read = fscanf(in, "\t(");
if (0 != num_read) // can this actually happen????
status = DECRYPTION_TRUSTEE_IO_ERROR;
else
selections[i] = selection;
if(DECRYPTION_TRUSTEE_SUCCESS == status) {
if(!uint4096_fscan(in, &selections[i].nonce_encoding))
status = DECRYPTION_TRUSTEE_IO_ERROR;
}
if(DECRYPTION_TRUSTEE_SUCCESS == status) {
num_read = fscanf(in, ",");
if(0 != num_read) status = DECRYPTION_TRUSTEE_IO_ERROR;
}
if(DECRYPTION_TRUSTEE_SUCCESS == status) {
if(!uint4096_fscan(in, &selections[i].message_encoding))
status = DECRYPTION_TRUSTEE_IO_ERROR;
}
if(DECRYPTION_TRUSTEE_SUCCESS == status) {
num_read = fscanf(in, ")");
if(0 != num_read) status = DECRYPTION_TRUSTEE_IO_ERROR;
}
}
return status;
}
static void Decryption_Trustee_accum_tally(Decryption_Trustee d,
bool *selections)
struct encryption_rep *selections)
{
for (size_t i = 0; i < d->num_selections; i++)
d->tallies[i] += selections[i];
Crypto_encryption_homomorphic_add(&d->tallies[i], &d->tallies[i], &selections[i]);
}
enum Decryption_Trustee_status
@ -135,7 +155,7 @@ Decryption_Trustee_tally_voting_record(Decryption_Trustee d, FILE *in)
{
uint64_t ballot_id;
bool cast;
bool selections[MAX_SELECTIONS];
struct encryption_rep selections[MAX_SELECTIONS];
status = Decryption_Trustee_read_ballot(in, &ballot_id, &cast,
d->num_selections, selections);
@ -158,8 +178,10 @@ Decryption_Trustee_compute_share(Decryption_Trustee d)
struct decryption_share_rep share_rep;
share_rep.trustee_index = d->index;
share_rep.num_tallies = d->num_selections;
memcpy(share_rep.tallies, d->tallies,
d->num_selections * sizeof(uint64_t));
for(size_t i = 0; i < d->num_selections; i++) {
uint4096_powmod_o(&share_rep.tally_share[i].nonce_encoding, &d->tallies[i].nonce_encoding, &d->private_key.coefficients[0], Modulus4096_modulus_default);
uint4096_copy_o(&share_rep.tally_share[i].message_encoding, &d->tallies[i].message_encoding);
}
// Serialize the message
struct serialize_state state = {

Просмотреть файл

@ -3,9 +3,10 @@
#include <stdlib.h>
#include <string.h>
#include "keyceremony/coordinator.h"
#include <electionguard/keyceremony/coordinator.h>
#include <electionguard/max_values.h>
#include "keyceremony/message_reps.h"
#include "max_values.h"
#include "serialize/crypto.h"
#include "serialize/keyceremony.h"

Просмотреть файл

@ -4,9 +4,10 @@
#include <stdlib.h>
#include <string.h>
#include <electionguard/keyceremony/trustee.h>
#include <electionguard/max_values.h>
#include "keyceremony/message_reps.h"
#include "keyceremony/trustee.h"
#include "max_values.h"
#include "serialize/keyceremony.h"
#include "serialize/trustee_state.h"
#include "trustee_state_rep.h"

Просмотреть файл

@ -0,0 +1,101 @@
#include <stdlib.h>
#include <stdio.h>
#include "random_source.h"
struct RandomSource_s {
#ifdef HAVE_BCRYPTGENRANDOM
// These links will be helpful for fixing this error:
// https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom
// https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptopenalgorithmprovider
#error Support for generating random byte sequences on Windows is not yet implemented.
#else
FILE *dev_random;
#endif
};
struct RandomSource_new_r RandomSource_new(void) {
struct RandomSource_new_r result;
result.status = RANDOM_SOURCE_SUCCESS;
if(RANDOM_SOURCE_SUCCESS == result.status) {
result.source = malloc(sizeof(*result.source));
if(NULL == result.source) {
result.status = RANDOM_SOURCE_INSUFFICIENT_MEMORY;
}
}
if(RANDOM_SOURCE_SUCCESS == result.status) {
#ifdef HAVE_BCRYPTGENRANDOM
#error Support for generating random byte sequences on Windows is not yet implemented.
#else
result.source->dev_random = fopen("/dev/urandom", "r");
if(NULL == result.source->dev_random) {
result.status = RANDOM_SOURCE_IO_ERROR;
free(result.source);
}
#endif
}
return result;
}
void RandomSource_free(RandomSource source) {
#ifdef HAVE_BCRYPTGENRANDOM
#error Support for generating random byte sequences on Windows is not yet implemented.
#else
fclose(source->dev_random);
free(source);
#endif
}
enum RandomSource_status RandomSource_uniform_o(RandomSource source, uint4096 out) {
uint8_t raw_bytes[UINT4096_SIZE_BYTES];
size_t item_count;
enum RandomSource_status result = RANDOM_SOURCE_SUCCESS;
struct uint4096_s zero;
uint4096_zext_o(&zero, NULL, 0);
do {
if(RANDOM_SOURCE_SUCCESS == result) {
#ifdef HAVE_BCRYPTGENRANDOM
#error Support for generating random byte sequences on Windows is not yet implemented.
#else
item_count = fread(raw_bytes, UINT4096_SIZE_BYTES, 1, source->dev_random);
if(1 != item_count) {
result = RANDOM_SOURCE_IO_ERROR;
}
#endif
}
if(RANDOM_SOURCE_SUCCESS == result) {
uint4096_zext_o(out, raw_bytes, UINT4096_SIZE_BYTES);
}
} while(RANDOM_SOURCE_SUCCESS == result &&
(uint4096_le(out, &zero) ||
!uint4096_lt(out, uint4096_modulus_default)
)
);
return result;
}
struct RandomSource_uniform_r RandomSource_uniform(RandomSource source) {
struct RandomSource_uniform_r result;
result.status = RANDOM_SOURCE_SUCCESS;
if(RANDOM_SOURCE_SUCCESS == result.status) {
result.result = uint4096_zext(NULL,0);
if(NULL == result.result) {
result.status = RANDOM_SOURCE_INSUFFICIENT_MEMORY;
}
}
if(RANDOM_SOURCE_SUCCESS == result.status) {
result.status = RandomSource_uniform_o(source, result.result);
if(RANDOM_SOURCE_SUCCESS != result.status) {
uint4096_free(result.result);
}
}
return result;
}

Просмотреть файл

@ -0,0 +1,32 @@
#pragma once
#include "uint4096.h"
#cmakedefine HAVE_BCRYPTGENRANDOM
// You should create one of these for each thread that may run.
typedef struct RandomSource_s *RandomSource;
enum RandomSource_status {
RANDOM_SOURCE_SUCCESS,
RANDOM_SOURCE_INSUFFICIENT_MEMORY,
RANDOM_SOURCE_IO_ERROR
};
struct RandomSource_new_r {
enum RandomSource_status status;
RandomSource source;
};
struct RandomSource_new_r RandomSource_new(void);
void RandomSource_free(RandomSource source);
struct RandomSource_uniform_r {
enum RandomSource_status status;
uint4096 result;
};
// Uses rejection sampling to pick a number between 1 and modulus_default-1,
// inclusive.
struct RandomSource_uniform_r RandomSource_uniform(RandomSource source);
enum RandomSource_status RandomSource_uniform_o(RandomSource source, uint4096 out);

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -0,0 +1,168 @@
#include <stdlib.h>
#include "serialize/crypto.h"
#include "serialize/builtins.h"
void Serialize_reserve_uint4096(struct serialize_state *state, const_uint4096 data)
{
for (uint32_t i = 0; i < UINT4096_WORD_COUNT; i++)
Serialize_reserve_uint64(state, &data->words[i]);
}
void Serialize_write_uint4096(struct serialize_state *state, const_uint4096 data)
{
for (uint32_t i = 0; i < UINT4096_WORD_COUNT; i++)
Serialize_write_uint64(state, &data->words[i]);
}
void Serialize_read_uint4096(struct serialize_state *state, uint4096 data)
{
for (uint32_t i = 0; i < UINT4096_WORD_COUNT; i++)
Serialize_read_uint64(state, &data->words[i]);
// TODO: check that the key is in the right range??
}
void Serialize_reserve_private_key(struct serialize_state *state,
struct private_key const *data)
{
Serialize_reserve_uint32(state, &data->threshold);
for (uint32_t i = 0; i < data->threshold; i++)
Serialize_reserve_uint4096(state, &data->coefficients[i]);
}
void Serialize_write_private_key(struct serialize_state *state,
struct private_key const *data)
{
Serialize_write_uint32(state, &data->threshold);
for (uint32_t i = 0; i < data->threshold; i++)
Serialize_write_uint4096(state, &data->coefficients[i]);
}
void Serialize_read_private_key(struct serialize_state *state,
struct private_key *data)
{
Serialize_read_uint32(state, &data->threshold);
for (uint32_t i = 0; i < data->threshold; i++)
Serialize_read_uint4096(state, &data->coefficients[i]);
}
void Serialize_reserve_public_key(struct serialize_state *state,
struct public_key const *data)
{
Serialize_reserve_uint32(state, &data->threshold);
for (uint32_t i = 0; i < data->threshold; i++)
Serialize_reserve_uint4096(state, &data->coef_commitments[i]);
}
void Serialize_write_public_key(struct serialize_state *state,
struct public_key const *data)
{
Serialize_write_uint32(state, &data->threshold);
for (uint32_t i = 0; i < data->threshold; i++)
Serialize_write_uint4096(state, &data->coef_commitments[i]);
}
void Serialize_read_public_key(struct serialize_state *state,
struct public_key *data)
{
Serialize_read_uint32(state, &data->threshold);
for (uint32_t i = 0; i < data->threshold; i++)
Serialize_read_uint4096(state, &data->coef_commitments[i]);
}
void Serialize_reserve_encrypted_key_share(
struct serialize_state *state, struct encrypted_key_share const *data)
{
Serialize_reserve_private_key(state, &data->private_key);
Serialize_reserve_public_key(state, &data->recipient_public_key);
}
void Serialize_write_encrypted_key_share(struct serialize_state *state,
struct encrypted_key_share const *data)
{
Serialize_write_private_key(state, &data->private_key);
Serialize_write_public_key(state, &data->recipient_public_key);
}
void Serialize_read_encrypted_key_share(struct serialize_state *state,
struct encrypted_key_share *data)
{
Serialize_read_private_key(state, &data->private_key);
Serialize_read_public_key(state, &data->recipient_public_key);
}
void Serialize_reserve_joint_public_key(struct serialize_state *state,
struct joint_public_key_rep const *data)
{
Serialize_reserve_uint32(state, &data->num_trustees);
Serialize_reserve_uint4096(state, &data->public_key);
}
void Serialize_write_joint_public_key(struct serialize_state *state,
struct joint_public_key_rep const *data)
{
Serialize_write_uint32(state, &data->num_trustees);
Serialize_write_uint4096(state, &data->public_key);
}
void Serialize_read_joint_public_key(struct serialize_state *state,
struct joint_public_key_rep *data)
{
Serialize_read_uint32(state, &data->num_trustees);
Serialize_read_uint4096(state, &data->public_key);
}
void Serialize_reserve_encryption(struct serialize_state *state,
struct encryption_rep const *data)
{
Serialize_reserve_uint4096(state, &data->nonce_encoding);
Serialize_reserve_uint4096(state, &data->message_encoding);
}
void Serialize_write_encryption(struct serialize_state *state,
struct encryption_rep const *data)
{
Serialize_write_uint4096(state, &data->nonce_encoding);
Serialize_write_uint4096(state, &data->message_encoding);
}
void Serialize_read_encryption(struct serialize_state *state,
struct encryption_rep *data)
{
Serialize_read_uint4096(state, &data->nonce_encoding);
Serialize_read_uint4096(state, &data->message_encoding);
}
void Serialize_reserve_encrypted_ballot(struct serialize_state *state,
struct encrypted_ballot_rep const *data)
{
Serialize_reserve_uint64(state, &data->id);
Serialize_reserve_uint32(state, &data->num_selections);
for(uint32_t i = 0; i < data->num_selections; i++) {
Serialize_reserve_encryption(state, &data->selections[i]);
}
}
void Serialize_write_encrypted_ballot(struct serialize_state *state,
struct encrypted_ballot_rep const *data)
{
Serialize_write_uint64(state, &data->id);
Serialize_write_uint32(state, &data->num_selections);
for(uint32_t i = 0; i < data->num_selections; i++) {
Serialize_write_encryption(state, &data->selections[i]);
}
}
void Serialize_read_encrypted_ballot(struct serialize_state *state,
struct encrypted_ballot_rep *data)
{
Serialize_read_uint64(state, &data->id);
Serialize_read_uint32(state, &data->num_selections);
data->selections = malloc(data->num_selections * sizeof(*data->selections));
if(NULL == data->selections) {
state->status = SERIALIZE_STATE_INSUFFICIENT_MEMORY;
}
for(uint32_t i = 0; i < data->num_selections && SERIALIZE_STATE_READING == state->status; i++) {
Serialize_read_encryption(state, &data->selections[i]);
}
}

Просмотреть файл

@ -1,16 +1,16 @@
#ifndef __SERIALIZE_CRYPTO_H__
#define __SERIALIZE_CRYPTO_H__
#include "crypto.h"
#include <electionguard/crypto.h>
#include "crypto_reps.h"
#include "serialize/state.h"
void Serialize_reserve_key(struct serialize_state *state,
struct key const *data);
void Serialize_reserve_uint4096(struct serialize_state *state, const_uint4096 data);
void Serialize_write_key(struct serialize_state *state, struct key const *data);
void Serialize_write_uint4096(struct serialize_state *state, const_uint4096 data);
void Serialize_read_key(struct serialize_state *state, struct key *data);
void Serialize_read_uint4096(struct serialize_state *state, uint4096 data);
void Serialize_reserve_private_key(struct serialize_state *state,
struct private_key const *data);
@ -48,4 +48,22 @@ void Serialize_write_joint_public_key(struct serialize_state *state,
void Serialize_read_joint_public_key(struct serialize_state *state,
struct joint_public_key_rep *data);
void Serialize_reserve_encryption(struct serialize_state *state,
struct encryption_rep const *data);
void Serialize_write_encryption(struct serialize_state *state,
struct encryption_rep const *data);
void Serialize_read_encryption(struct serialize_state *state,
struct encryption_rep *data);
void Serialize_reserve_encrypted_ballot(struct serialize_state *state,
struct encrypted_ballot_rep const *data);
void Serialize_write_encrypted_ballot(struct serialize_state *state,
struct encrypted_ballot_rep const *data);
void Serialize_read_encrypted_ballot(struct serialize_state *state,
struct encrypted_ballot_rep *data);
#endif /* __CRYPTO_SERIALIZE_H__ */

Просмотреть файл

@ -8,7 +8,7 @@ void Serialize_reserve_decryption_share(struct serialize_state *state,
Serialize_reserve_uint32(state, &data->trustee_index);
Serialize_reserve_uint64(state, &data->num_tallies);
for (uint64_t i = 0; i < data->num_tallies; i++)
Serialize_reserve_uint64(state, &data->tallies[i]);
Serialize_reserve_encryption(state, &data->tally_share[i]);
}
void Serialize_write_decryption_share(struct serialize_state *state,
@ -17,7 +17,7 @@ void Serialize_write_decryption_share(struct serialize_state *state,
Serialize_write_uint32(state, &data->trustee_index);
Serialize_write_uint64(state, &data->num_tallies);
for (uint64_t i = 0; i < data->num_tallies; i++)
Serialize_write_uint64(state, &data->tallies[i]);
Serialize_write_encryption(state, &data->tally_share[i]);
}
void Serialize_read_decryption_share(struct serialize_state *state,
@ -26,7 +26,7 @@ void Serialize_read_decryption_share(struct serialize_state *state,
Serialize_read_uint32(state, &data->trustee_index);
Serialize_read_uint64(state, &data->num_tallies);
for (uint64_t i = 0; i < data->num_tallies; i++)
Serialize_read_uint64(state, &data->tallies[i]);
Serialize_read_encryption(state, &data->tally_share[i]);
}
void Serialize_reserve_decryption_fragments_request(

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -1,33 +1,6 @@
#include "serialize/voting.h"
#include "serialize/builtins.h"
void Serialize_reserve_register_ballot(struct serialize_state *state,
struct register_ballot_rep const *data)
{
Serialize_reserve_uint64(state, &data->id);
Serialize_reserve_uint32(state, &data->num_selections);
for (uint32_t i = 0; i < data->num_selections; i++)
Serialize_reserve_bool(state, &data->selections[i]);
}
void Serialize_write_register_ballot(struct serialize_state *state,
struct register_ballot_rep const *data)
{
Serialize_write_uint64(state, &data->id);
Serialize_write_uint32(state, &data->num_selections);
for (uint32_t i = 0; i < data->num_selections; i++)
Serialize_write_bool(state, &data->selections[i]);
}
void Serialize_read_register_ballot(struct serialize_state *state,
struct register_ballot_rep *data)
{
Serialize_read_uint64(state, &data->id);
Serialize_read_uint32(state, &data->num_selections);
for (uint32_t i = 0; i < data->num_selections; i++)
Serialize_read_bool(state, &data->selections[i]);
}
void Serialize_reserve_ballot_tracker(struct serialize_state *state,
struct ballot_tracker_rep const *data)
{

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -0,0 +1,410 @@
// This file was written under the assumption that timing attacks were not
// dangerous. If this changes in the future, I have left the comment
// // timing
// at points where there are conditions that may depend on sensitive data, so
// you should begin your code audit by reviewing the code near these comments.
#include <stdlib.h>
#include <string.h>
#include "uint4096.h"
// =============================================================================
//
// Type Definitions
//
// =============================================================================
typedef struct uint8192_s { UINT4096_WORD_T words[2*UINT4096_WORD_COUNT]; } *uint8192;
typedef struct uint8192_s const *const_uint8192;
// Algorithms which use one of these assume that
// reciprocal = floor(2^8192/modulus)
// without checking it. Violating this assumption is safe (you will still get
// the right answer) but slow (the function may not finish before the universe
// does).
typedef struct Modulus4096_s {
const struct uint4096_s modulus;
const struct uint8192_s reciprocal;
} const *const Modulus4096;
// =============================================================================
//
// Dynamically-sized operations that work for arbitrary word-counts
//
// =============================================================================
// Returns whether the addition overflowed or not.
bool uintnwords_add_o(size_t n, UINT4096_WORD_T *out, const UINT4096_WORD_T *a, const UINT4096_WORD_T *b) {
// Simple ripple-carry adder.
UINT4096_WORD_T carry = 0;
while(n-- > 0) {
UINT4096_WORD_T new_carry = 0;
new_carry |= !!__builtin_add_overflow(a[n], b[n], out+n);
new_carry |= !!__builtin_add_overflow(out[n], carry, out+n);
carry = new_carry;
}
return carry;
}
// Returns whether the successor operation overflowed or not.
bool uintnwords_succ_o(size_t n, UINT4096_WORD_T *out, const UINT4096_WORD_T *a) {
bool carry = true;
// timing
while(carry && n-- > 0) {
carry = __builtin_add_overflow(a[n], 1, a+n);
}
return carry;
}
void uintnwords_negate_o(size_t n, UINT4096_WORD_T *out, const UINT4096_WORD_T *a) {
for(size_t i = 0; i < n; i++) {
out[i] = ~a[i];
}
uintnwords_succ_o(n, out, out);
}
int uintnwords_cmp(size_t n, const UINT4096_WORD_T *a, const UINT4096_WORD_T *b) {
for(size_t i = 0; i < n; i++) {
// timing
if(a[i] < b[i]) return -1;
if(a[i] > b[i]) return 1;
}
return 0;
}
bool uintnwords_le(size_t n, const UINT4096_WORD_T *a, const UINT4096_WORD_T *b) {
return uintnwords_cmp(n, a, b) <= 0;
}
// =============================================================================
//
// Dynamically-sized operations that work on power-of-two word counts only
//
// Define the function f this way:
// f(n) = 2^n * UINT4096_WORD_SIZE_BITS
// Then we will use uintfn as the name of a dynamically-sized uint with f(n)
// bits; e.g. if n=0 then uintfn is a representation of a uint64_t; n=6 gets
// you a uint4096_s.
//
// =============================================================================
const int UINT4096_HALFWORD_SIZE_BYTES = UINT4096_WORD_SIZE_BYTES/2;
const int UINT4096_HALFWORD_SIZE_BITS = UINT4096_WORD_SIZE_BITS/2;
const UINT4096_WORD_T UINT4096_HALFWORD_BOTTOM_MASK = ((UINT4096_WORD_T)1<<(UINT4096_WORD_SIZE_BITS/2))-1;
// Contract: a and b are 2^n-word-long numbers, and out has enough space for a
// 2^(n+1)-word-long number.
void uintfn_mult_o(unsigned n, UINT4096_WORD_T *out, const UINT4096_WORD_T *a, const UINT4096_WORD_T *b) {
if(n == 0) {
// Textbook multiplication on half-word values, because I believe
// saving one hardware multiplication at the cost of a conditional
// branch (for the sign stuff) is probably a loss.
const UINT4096_WORD_T a_upper_halfword = a[0] >> UINT4096_HALFWORD_SIZE_BITS;
const UINT4096_WORD_T b_upper_halfword = b[0] >> UINT4096_HALFWORD_SIZE_BITS;
const UINT4096_WORD_T a_lower_halfword = a[0] & UINT4096_HALFWORD_BOTTOM_MASK;
const UINT4096_WORD_T b_lower_halfword = b[0] & UINT4096_HALFWORD_BOTTOM_MASK;
out[0] = a_upper_halfword * b_upper_halfword;
out[1] = a_lower_halfword * b_lower_halfword;
const UINT4096_WORD_T out_middle_word_1 = a_upper_halfword * b_lower_halfword;
const UINT4096_WORD_T out_middle_word_2 = b_upper_halfword * a_lower_halfword;
uintnwords_add_o(2, out, out, (UINT4096_WORD_T []){out_middle_word_1 >> UINT4096_HALFWORD_SIZE_BITS, out_middle_word_1 << UINT4096_HALFWORD_SIZE_BITS});
uintnwords_add_o(2, out, out, (UINT4096_WORD_T []){out_middle_word_2 >> UINT4096_HALFWORD_SIZE_BITS, out_middle_word_2 << UINT4096_HALFWORD_SIZE_BITS});
}
else {
// Karatsuba multiplication.
const size_t SMALL = (size_t)1 << (n-1), MEDIUM = SMALL << 1, LARGE = MEDIUM << 1;
UINT4096_WORD_T out_tmp[LARGE];
uintfn_mult_o(n-1, out_tmp, a, b);
uintfn_mult_o(n-1, out_tmp + MEDIUM, a + SMALL, b + SMALL);
UINT4096_WORD_T sign = -1, diff1[SMALL], diff2[SMALL], addend[MEDIUM+1], sum[LARGE];
UINT4096_WORD_T *const middle_of_sum = sum+SMALL-1;
if(uintnwords_le(SMALL, a, a+SMALL)) {
sign *= 1;
uintnwords_negate_o(SMALL, diff1, a);
uintnwords_add_o(SMALL, diff1, diff1, a+SMALL);
}
else {
sign *= -1;
uintnwords_negate_o(SMALL, diff1, a+SMALL);
uintnwords_add_o(SMALL, diff1, diff1, a);
}
if(uintnwords_le(SMALL, b, b+SMALL)) {
sign *= 1;
uintnwords_negate_o(SMALL, diff2, b);
uintnwords_add_o(SMALL, diff2, diff2, b+SMALL);
}
else {
sign *= -1;
uintnwords_negate_o(SMALL, diff2, b+SMALL);
uintnwords_add_o(SMALL, diff2, diff2, b);
}
memset(sum, 0, sizeof(sum));
uintfn_mult_o(n-1, sum+SMALL, diff1, diff2);
// timing
if(-1 == sign) uintnwords_negate_o(MEDIUM+1, middle_of_sum, middle_of_sum);
addend[0] = 0;
memmove(addend+1, out_tmp, MEDIUM*UINT4096_WORD_SIZE_BYTES);
uintnwords_add_o(MEDIUM+1, middle_of_sum, middle_of_sum, addend);
memmove(addend+1, out_tmp+MEDIUM, MEDIUM*UINT4096_WORD_SIZE_BYTES);
uintnwords_add_o(MEDIUM+1, middle_of_sum, middle_of_sum, addend);
uintnwords_add_o(LARGE, out, out_tmp, sum);
}
}
// =============================================================================
//
// 8192-bit operations
//
// =============================================================================
void uint8192_mod_o(uint4096 out, const_uint8192 a, Modulus4096 modulus) {
UINT4096_WORD_T result[4*UINT4096_WORD_COUNT];
UINT4096_WORD_T *lores = result + 2*UINT4096_WORD_COUNT;
UINT4096_WORD_T promoted_modulus[2*UINT4096_WORD_COUNT];
memset(promoted_modulus, 0, UINT4096_WORD_COUNT*sizeof(UINT4096_WORD_T));
memcpy(promoted_modulus+UINT4096_WORD_COUNT, modulus->modulus.words, UINT4096_WORD_COUNT*sizeof(UINT4096_WORD_T));
uintfn_mult_o(UINT4096_LOG2_WORD_COUNT+1, result, a->words, modulus->reciprocal.words);
uintfn_mult_o(UINT4096_LOG2_WORD_COUNT+1, result, result, promoted_modulus);
uintnwords_negate_o(2*UINT4096_WORD_COUNT, lores, lores);
uintnwords_add_o(2*UINT4096_WORD_COUNT, lores, lores, a->words);
// If I've done my algebra correctly, this loop runs at most once. (If this
// turns out not to be the case, and you can't restore that property by
// fixing the algebra, you might want to revisit the decision to allocate
// and negate the modulus inside the loop.)
// timing
while(uintnwords_le(2*UINT4096_WORD_COUNT, promoted_modulus, lores)) {
UINT4096_WORD_T negated_modulus[2*UINT4096_WORD_COUNT];
uintnwords_negate_o(2*UINT4096_WORD_COUNT, negated_modulus, promoted_modulus);
uintnwords_add_o(2*UINT4096_WORD_COUNT, lores, lores, negated_modulus);
}
memcpy(out->words, lores + UINT4096_WORD_COUNT, UINT4096_WORD_COUNT*sizeof(UINT4096_WORD_T));
}
// =============================================================================
//
// 4096-bit operations that do not need to dynamically allocate
//
// =============================================================================
void uint4096_zext_o(uint4096 out, const uint8_t *bytes, size_t num_bytes) {
// ub = upper bound
const size_t ub = UINT4096_WORD_COUNT*UINT4096_WORD_SIZE_BYTES;
if(num_bytes > ub) {
bytes += num_bytes - ub;
num_bytes = ub;
}
memset(out->words, 0, sizeof(out->words));
for(size_t i = 0; i < num_bytes; i++)
out->words[UINT4096_WORD_COUNT-1 - i/UINT4096_WORD_SIZE_BYTES] |= (UINT4096_WORD_T)bytes[num_bytes-1 - i] << 8 * (i%UINT4096_WORD_SIZE_BYTES);
}
void uint4096_downcast_o(uint4096 out, Modulus4096 modulus) {
memmove(out->words, modulus->modulus.words, UINT4096_WORD_COUNT*UINT4096_WORD_SIZE_BYTES);
}
bool uint4096_eq(const_uint4096 a, const_uint4096 b) { return 0 == uintnwords_cmp(UINT4096_WORD_COUNT, a->words, b->words); }
bool uint4096_le(const_uint4096 a, const_uint4096 b) { return 0 >= uintnwords_cmp(UINT4096_WORD_COUNT, a->words, b->words); }
bool uint4096_lt(const_uint4096 a, const_uint4096 b) { return 0 > uintnwords_cmp(UINT4096_WORD_COUNT, a->words, b->words); }
bool uint4096_ge(const_uint4096 a, const_uint4096 b) { return 0 <= uintnwords_cmp(UINT4096_WORD_COUNT, a->words, b->words); }
bool uint4096_gt(const_uint4096 a, const_uint4096 b) { return 0 < uintnwords_cmp(UINT4096_WORD_COUNT, a->words, b->words); }
void uint4096_multmod_o(uint4096 out, const_uint4096 a, const_uint4096 b, Modulus4096 modulus) {
struct uint8192_s product;
uintfn_mult_o(UINT4096_LOG2_WORD_COUNT, product.words, a->words, b->words);
uint8192_mod_o(out, &product, modulus);
}
void uint4096_powmod_o(uint4096 out, const_uint4096 base, const_uint4096 exponent, Modulus4096 modulus) {
// Scan from the left to find the highest set bit.
int max_bit;
for(max_bit = 0; max_bit < UINT4096_WORD_COUNT && exponent->words[max_bit] == 0; max_bit++) {}
UINT4096_WORD_T word = max_bit < UINT4096_WORD_COUNT ? exponent->words[max_bit] : 0;
max_bit = (UINT4096_WORD_COUNT-1 - max_bit) * UINT4096_WORD_SIZE_BITS; // change from most-significant word index to least-significant bit index
while(word) { word >>= 1; max_bit++; }
struct uint4096_s out_tmp;
struct uint4096_s base_tmp;
uint4096_zext_o(&out_tmp, (uint8_t[]){1}, 1);
memcpy(&base_tmp, base, sizeof(struct uint4096_s));
// Now do some repeated squaring.
// timing
for(int i = 0; i < max_bit; i++) {
if(exponent->words[UINT4096_WORD_COUNT-1 - i/UINT4096_WORD_SIZE_BITS] & (UINT4096_WORD_T)1<<i%UINT4096_WORD_SIZE_BITS)
uint4096_multmod_o(&out_tmp, &out_tmp, &base_tmp, modulus);
uint4096_multmod_o(&base_tmp, &base_tmp, &base_tmp, modulus);
}
memcpy(out, &out_tmp, sizeof(struct uint4096_s));
}
uint64_t uint4096_logmod(const_uint4096 base, const_uint4096 a, Modulus4096 modulus) {
uint64_t exponent = 0;
struct uint4096_s powmod;
uint4096_zext_o(&powmod, (uint8_t[]){1}, 1);
while(!uint4096_eq(&powmod, a)) {
exponent++;
uint4096_multmod_o(&powmod, &powmod, base, modulus);
}
return exponent;
}
void uint4096_copy_o(uint4096 out, const_uint4096 src) {
memmove(out, src, sizeof(*src));
}
// Currently just a wrapper around free; exists for abstraction boundary's sake.
void uint4096_free(uint4096 a) { free(a); }
bool uint4096_fprint(FILE *out, const_uint4096 a) {
if(2 != fprintf(out, "0x")) return false;
for(size_t i = 0; i < UINT4096_WORD_COUNT; i++) {
if(2*UINT4096_WORD_SIZE_BYTES != fprintf(out, PRIxUINT4096_WORD_T, a->words[i]))
return false;
}
return true;
}
bool uint4096_fscan(FILE *in, uint4096 out) {
int num_read = fscanf(in, "0x");
if(0 != num_read) return false;
for(size_t i = 0; i < UINT4096_WORD_COUNT; i++) {
num_read = fscanf(in, PRIxUINT4096_WORD_T, &out->words[i]);
if(1 != num_read) return false;
}
return true;
}
// =============================================================================
//
// Dynamically-allocating wrappers around the core 4096-bit operations
//
// =============================================================================
uint4096 uint4096_zext(const uint8_t *bytes, size_t num_bytes) {
uint4096 out = malloc(sizeof(struct uint4096_s));
if(out != NULL) uint4096_zext_o(out, bytes, num_bytes);
return out;
}
uint4096 uint4096_downcast(Modulus4096 modulus) {
uint4096 out = malloc(sizeof(struct uint4096_s));
if(out != NULL) uint4096_downcast_o(out, modulus);
return out;
}
uint4096 uint4096_multmod(const_uint4096 a, const_uint4096 b, Modulus4096 modulus) {
uint4096 out = malloc(sizeof(struct uint4096_s));
if(out != NULL) uint4096_multmod_o(out, a, b, modulus);
return out;
}
uint4096 uint4096_powmod(const_uint4096 base, const_uint4096 exponent, Modulus4096 modulus) {
uint4096 out = malloc(sizeof(struct uint4096_s));
if(out != NULL) uint4096_powmod_o(out, base, exponent, modulus);
return out;
}
uint4096 uint4096_copy(const_uint4096 src) {
uint4096 out = malloc(sizeof(struct uint4096_s));
if(out != NULL) uint4096_copy_o(out, src);
return out;
}
// =============================================================================
//
// Static data
//
// =============================================================================
struct Modulus4096_s p = {
.modulus = {
.words = {
0xFFFFFFFFFFFFFFFF, 0xC90FDAA22168C234, 0xC4C6628B80DC1CD1, 0x29024E088A67CC74,
0x020BBEA63B139B22, 0x514A08798E3404DD, 0xEF9519B3CD3A431B, 0x302B0A6DF25F1437,
0x4FE1356D6D51C245, 0xE485B576625E7EC6, 0xF44C42E9A637ED6B, 0x0BFF5CB6F406B7ED,
0xEE386BFB5A899FA5, 0xAE9F24117C4B1FE6, 0x49286651ECE45B3D, 0xC2007CB8A163BF05,
0x98DA48361C55D39A, 0x69163FA8FD24CF5F, 0x83655D23DCA3AD96, 0x1C62F356208552BB,
0x9ED529077096966D, 0x670C354E4ABC9804, 0xF1746C08CA18217C, 0x32905E462E36CE3B,
0xE39E772C180E8603, 0x9B2783A2EC07A28F, 0xB5C55DF06F4C52C9, 0xDE2BCBF695581718,
0x3995497CEA956AE5, 0x15D2261898FA0510, 0x15728E5A8AAAC42D, 0xAD33170D04507A33,
0xA85521ABDF1CBA64, 0xECFB850458DBEF0A, 0x8AEA71575D060C7D, 0xB3970F85A6E1E4C7,
0xABF5AE8CDB0933D7, 0x1E8C94E04A25619D, 0xCEE3D2261AD2EE6B, 0xF12FFA06D98A0864,
0xD87602733EC86A64, 0x521F2B18177B200C, 0xBBE117577A615D6C, 0x770988C0BAD946E2,
0x08E24FA074E5AB31, 0x43DB5BFCE0FD108E, 0x4B82D120A9210801, 0x1A723C12A787E6D7,
0x88719A10BDBA5B26, 0x99C327186AF4E23C, 0x1A946834B6150BDA, 0x2583E9CA2AD44CE8,
0xDBBBC2DB04DE8EF9, 0x2E8EFC141FBECAA6, 0x287C59474E6BC05D, 0x99B2964FA090C3A2,
0x233BA186515BE7ED, 0x1F612970CEE2D7AF, 0xB81BDD762170481C, 0xD0069127D5B05AA9,
0x93B4EA988D8FDDC1, 0x86FFB7DC90A6C08F, 0x4DF435C934063199, 0xFFFFFFFFFFFFFFFF
}
},
.reciprocal = {
.words = {
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000001,
0x0000000000000000, 0x36F0255DDE973DCB, 0x4703CE7E2E815197, 0xA6DB0F588448B611,
0x64CFCAC5F1872E51, 0xB1F9FBB5BF16FBE7, 0x9689FC0903A801E3, 0xD4802FB8D329550D,
0xC8C9D3D922EECE9A, 0x5475DB33DB7B83BB, 0x5C0E13D168049BBC, 0x86C5817647B088D1,
0x7AA5CC40E0203558, 0x8EDB2DE189934137, 0x19FC258D79BC217A, 0xC4B8739CBEA038AA,
0xA88D0D2F78A77A8A, 0x6FC7FAA8B2BDCA9B, 0xE7502D2F5F6A7B65, 0xF5E4F07AB8B286E4,
0x1115F024A6E976BD, 0x2BCE3E5190B891AB, 0xBF2331E9C94DE91F, 0xBE8574370494A354,
0xEAC9BE0B31EB3185, 0x40E4069D556E9DD0, 0x9D5D89D7DE4A75C8, 0x8BB49316C106E4E0,
0x14B636E60FEBC292, 0xE6249105F5B195FE, 0x906EEF7D26CAF052, 0x9A3E0BC10E100CE0,
0xA899C59999BF877D, 0xBA72C59BF5CCF326, 0x2EB59041E144783A, 0xEE4CD860EE0B6450,
0x6DAB2569611BADDB, 0x6B78E82043041716, 0xDEC14CC95569811E, 0x498FDEC9D54BD071,
0x1EC97A0B25201C17, 0x763900498B0F0308, 0x746D18CEEDB565FF, 0x29964AFA53E3C1B9,
0x67ED5909172FB4D7, 0xF345A315C4768765, 0x5294F5E127281391, 0x0C258E7E91556CE5,
0xC145E09DAE0A5C7E, 0xEDE843F90F5DA834, 0x399A4ECB4B05F36F, 0xE586ABCAEF7FA12E,
0x18B7F0A5564A1616, 0x5D4680FE70FC2A3F, 0xEDFD7374A1D9CA9A, 0xEFBDDF3F3060E354,
0x8E1CD71EA518F66B, 0x9725EFEC54AEDB55, 0xAE1CF670C7E28D82, 0x07F6D09E269060E5,
0x591A0721ADFEA421, 0x8E27DA72BF177212, 0x072053629D931252, 0xC14AB0DDCC03AA20
}
}
};
Modulus4096 Modulus4096_modulus_default = &p;
const_uint4096 uint4096_modulus_default = &p.modulus;
struct uint4096_s g = {
.words = {
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000002
}
};
const_uint4096 uint4096_generator_default = &g;

Просмотреть файл

@ -0,0 +1,73 @@
#pragma once
#include <inttypes.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
// Important invariants:
// UINT4096_SIZE_BYTES * 8 = UINT4096_SIZE_BITS = 4096
// WORD_SIZE_BITS = WORD_SIZE_BYTES * 8
// WORD_COUNT * WORD_SIZE_BITS = UINT4096_SIZE_BITS
// WORD_T = uintWORD_SIZE_BITS_t
// 2^LOG2_WORD_COUNT = WORD_COUNT
// PRIxUINT4096_WORD_T uses the right format string for a UINT4096_WORD_T
#define UINT4096_SIZE_BITS 4096
#define UINT4096_SIZE_BYTES 512
#define UINT4096_WORD_COUNT 64
#define UINT4096_WORD_SIZE_BYTES 8
#define UINT4096_WORD_SIZE_BITS 64
#define UINT4096_WORD_T uint64_t
#define UINT4096_LOG2_WORD_COUNT 6
#define PRIxUINT4096_WORD_T ("%016" PRIx64)
struct uint4096_s { UINT4096_WORD_T words[UINT4096_WORD_COUNT]; };
// Some discussion of naming here. There are two conflicts to resolve:
//
// 1. The ElectionGuard convention uses upper case, but the base integer types
// in C are all uint*_t (lower-case).
// 2. The ElectionGuard convention only includes _r and _s as possible
// suffixes, preferring no suffix at all for abstract types, but the base
// integer types use a _t suffix to indicate they are types.
//
// There's no solution that will please everybody, I suspect. I choose the
// ElectionGuard convention everywhere except that I keep uint lower-case,
// because the lower-case uint naming convention is so widespread and
// well-known.
typedef struct uint4096_s *uint4096;
typedef struct uint4096_s const *const_uint4096;
typedef struct Modulus4096_s const *const Modulus4096;
// The functions below that return a uint4096 use NULL to signal out-of-memory
// conditions.
// The first byte is the most-significant byte. If there are too many bytes,
// the most-significant ones are dropped.
uint4096 uint4096_zext(const uint8_t *bytes, size_t num_bytes);
uint4096 uint4096_downcast(Modulus4096 modulus);
bool uint4096_eq(const_uint4096 a, const_uint4096 b);
bool uint4096_le(const_uint4096 a, const_uint4096 b);
bool uint4096_lt(const_uint4096 a, const_uint4096 b);
bool uint4096_ge(const_uint4096 a, const_uint4096 b);
bool uint4096_gt(const_uint4096 a, const_uint4096 b);
uint4096 uint4096_multmod(const_uint4096 a, const_uint4096 b, Modulus4096 modulus);
uint4096 uint4096_powmod(const_uint4096 base, const_uint4096 exponent, Modulus4096 modulus);
uint64_t uint4096_logmod(const_uint4096 base, const_uint4096 a, Modulus4096 modulus);
uint4096 uint4096_copy(const_uint4096 src);
void uint4096_free(uint4096 a);
// _o suffix: overwrite an existing, already-allocated uint4096
void uint4096_zext_o(uint4096 out, const uint8_t *bytes, size_t num_bytes);
void uint4096_downcast_o(uint4096 out, Modulus4096 modulus);
void uint4096_multmod_o(uint4096 out, const_uint4096 a, const_uint4096 b, Modulus4096 modulus);
void uint4096_powmod_o(uint4096 out, const_uint4096 base, const_uint4096 exponent, Modulus4096 modulus);
void uint4096_copy_o(uint4096 out, const_uint4096 src);
bool uint4096_fprint(FILE *out, const_uint4096 a);
bool uint4096_fscan(FILE *in, uint4096 out);
// The prime modulus and generator given in the ElectionGuard specification.
extern Modulus4096 Modulus4096_modulus_default;
extern const_uint4096 uint4096_modulus_default;
extern const_uint4096 uint4096_generator_default;

Просмотреть файл

@ -2,9 +2,12 @@
#include <stdlib.h>
#include <string.h>
#include <electionguard/voting/coordinator.h>
#include "serialize/crypto.h"
#include "serialize/voting.h"
#include "voting/coordinator.h"
#include "voting/message_reps.h"
#include "crypto_reps.h"
#include "voting/num_ballots.h"
// @design jwaksbaum This implementation relies on the fact that the
@ -17,7 +20,7 @@ struct Voting_Coordinator_s
{
// The number of selections on each ballot
uint32_t num_selections;
bool selections[MAX_BALLOTS][MAX_SELECTIONS];
struct encryption_rep *selections[MAX_BALLOTS];
bool registered[MAX_BALLOTS];
bool cast[MAX_BALLOTS];
bool spoiled[MAX_BALLOTS];
@ -46,6 +49,9 @@ struct Voting_Coordinator_new_r Voting_Coordinator_new(uint32_t num_selections)
void Voting_Coordinator_free(Voting_Coordinator ballot_box)
{
for(size_t i = 0; i < MAX_BALLOTS; i++)
if(ballot_box->registered[i])
free(ballot_box->selections[i]);
free(ballot_box);
}
@ -55,7 +61,7 @@ Voting_Coordinator_register_ballot(Voting_Coordinator c,
{
enum Voting_Coordinator_status status = VOTING_COORDINATOR_SUCCESS;
struct register_ballot_rep message_rep;
struct encrypted_ballot_rep message_rep;
// Deserialize the message
if (status == VOTING_COORDINATOR_SUCCESS)
@ -67,7 +73,7 @@ Voting_Coordinator_register_ballot(Voting_Coordinator c,
.buf = (uint8_t *)message.bytes,
};
Serialize_read_register_ballot(&state, &message_rep);
Serialize_read_encrypted_ballot(&state, &message_rep);
if (state.status != SERIALIZE_STATE_READING)
status = VOTING_COORDINATOR_DESERIALIZE_ERROR;
@ -86,9 +92,8 @@ Voting_Coordinator_register_ballot(Voting_Coordinator c,
if (status == VOTING_COORDINATOR_SUCCESS)
{
// Copy the ballot into the ballot box state
memcpy(c->selections[message_rep.id], message_rep.selections,
c->num_selections * sizeof(bool));
// Move the ballot into the ballot box state
c->selections[message_rep.id] = message_rep.selections;
// Mark it as registered but unspoiled and uncast
c->registered[message_rep.id] = true;
@ -171,7 +176,7 @@ Voting_Coordinator_spoil_ballot(Voting_Coordinator coordinator,
*/
static enum Voting_Coordinator_status
Voting_Coordinator_write_ballot(FILE *out, uint64_t ballot_id, bool cast,
uint32_t num_selections, bool *selections)
uint32_t num_selections, struct encryption_rep *selections)
{
enum Voting_Coordinator_status status = VOTING_COORDINATOR_SUCCESS;
@ -186,8 +191,16 @@ Voting_Coordinator_write_ballot(FILE *out, uint64_t ballot_id, bool cast,
// Write the selections
for (uint32_t i = 0;
i < num_selections && status == VOTING_COORDINATOR_SUCCESS; i++)
fprintf(out, "\t%d", selections[i]);
i < num_selections && status == VOTING_COORDINATOR_SUCCESS; i++) {
if(fprintf(out, "\t") < 1)
status = VOTING_COORDINATOR_IO_ERROR;
if(VOTING_COORDINATOR_SUCCESS == status) {
if(!Crypto_encryption_fprint(out, &selections[i])) {
status = VOTING_COORDINATOR_IO_ERROR;
}
}
}
// Write the newline
if (status == VOTING_COORDINATOR_SUCCESS)

Просмотреть файл

@ -0,0 +1,229 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <electionguard/voting/encrypter.h>
#include "crypto_reps.h"
#include "random_source.h"
#include "serialize/crypto.h"
#include "serialize/state.h"
#include "serialize/voting.h"
#include "voting/message_reps.h"
#include "voting/num_ballots.h"
uint64_t Voting_num_ballots = 0;
struct Voting_Encrypter_s
{
struct uid uid;
struct joint_public_key_rep joint_key;
uint32_t num_selections;
RandomSource source;
};
enum Voting_Encrypter_status Voting_Encrypter_RandomSource_status_convert(enum RandomSource_status status) {
switch(status) {
case RANDOM_SOURCE_SUCCESS: return VOTING_ENCRYPTER_SUCCESS;
case RANDOM_SOURCE_INSUFFICIENT_MEMORY: return VOTING_ENCRYPTER_INSUFFICIENT_MEMORY;
case RANDOM_SOURCE_IO_ERROR: return VOTING_ENCRYPTER_IO_ERROR;
default: return VOTING_ENCRYPTER_UNKNOWN_ERROR;
}
}
enum Voting_Encrypter_status Voting_Encrypter_serialize_read_status_convert(enum serialize_status status) {
switch(status) {
case SERIALIZE_STATE_READING: return VOTING_ENCRYPTER_SUCCESS;
case SERIALIZE_STATE_INSUFFICIENT_MEMORY: return VOTING_ENCRYPTER_INSUFFICIENT_MEMORY;
case SERIALIZE_STATE_BUFFER_TOO_SMALL: return VOTING_ENCRYPTER_DESERIALIZE_ERROR;
default: return VOTING_ENCRYPTER_UNKNOWN_ERROR;
}
}
struct Voting_Encrypter_new_r
Voting_Encrypter_new(struct uid uid, struct joint_public_key joint_key,
uint32_t num_selections)
{
struct Voting_Encrypter_new_r result;
result.encrypter = NULL;
result.status = VOTING_ENCRYPTER_SUCCESS;
// Allocate the Encrypter
result.encrypter = malloc(sizeof(struct Voting_Encrypter_s));
if (result.encrypter == NULL)
result.status = VOTING_ENCRYPTER_INSUFFICIENT_MEMORY;
// Clone the uid
uint8_t *uid_buf = NULL;
if (result.status == VOTING_ENCRYPTER_SUCCESS)
{
uid_buf = malloc(uid.len);
if (uid_buf == NULL)
result.status = VOTING_ENCRYPTER_INSUFFICIENT_MEMORY;
else
memcpy(uid_buf, uid.bytes, uid.len);
result.encrypter->uid = (struct uid){
.len = uid.len,
.bytes = uid_buf,
};
}
// Clone the joint key
if (result.status == VOTING_ENCRYPTER_SUCCESS)
{
struct serialize_state state =
{ .status = SERIALIZE_STATE_READING
, .len = joint_key.len
, .offset = 0
, .buf = (uint8_t *)joint_key.bytes // discard const-ness and pray
};
Serialize_read_joint_public_key(&state, &result.encrypter->joint_key);
result.status = Voting_Encrypter_serialize_read_status_convert(state.status);
}
// Get a random source
RandomSource source = NULL;
if (result.status == VOTING_ENCRYPTER_SUCCESS) {
struct RandomSource_new_r rs = RandomSource_new();
result.status = Voting_Encrypter_RandomSource_status_convert(rs.status);
if(VOTING_ENCRYPTER_SUCCESS == result.status) {
source = rs.source;
result.encrypter->source = rs.source;
}
}
if (result.status == VOTING_ENCRYPTER_SUCCESS)
result.encrypter->num_selections = num_selections;
if (VOTING_ENCRYPTER_SUCCESS != result.status) {
if (NULL != source) RandomSource_free(source);
if (NULL != uid_buf) free(uid_buf);
if (NULL != result.encrypter) free(result.encrypter);
}
return result;
}
void Voting_Encrypter_free(Voting_Encrypter encrypter)
{
free((void *)encrypter->uid.bytes);
RandomSource_free(encrypter->source);
free((void *)encrypter);
}
enum Voting_Encrypter_status Voting_Encrypter_Crypto_status_convert(enum Crypto_status status) {
switch(status) {
case CRYPTO_SUCCESS: return VOTING_ENCRYPTER_SUCCESS;
case CRYPTO_INSUFFICIENT_MEMORY: return VOTING_ENCRYPTER_INSUFFICIENT_MEMORY;
case CRYPTO_IO_ERROR: return VOTING_ENCRYPTER_IO_ERROR;
default: return VOTING_ENCRYPTER_UNKNOWN_ERROR;
}
}
struct Voting_Encrypter_encrypt_ballot_r
Voting_Encrypter_encrypt_ballot(Voting_Encrypter encrypter,
bool const *selections)
{
struct Voting_Encrypter_encrypt_ballot_r result;
result.status = VOTING_ENCRYPTER_SUCCESS;
// Construct the ballot id
{
struct ballot_identifier_rep rep = {.id = Voting_num_ballots};
struct serialize_state state = {
.status = SERIALIZE_STATE_RESERVING,
.len = 0,
.offset = 0,
.buf = NULL,
};
Serialize_reserve_ballot_identifier(&state, &rep);
Serialize_allocate(&state);
Serialize_write_ballot_identifier(&state, &rep);
if (state.status != SERIALIZE_STATE_WRITING)
result.status = VOTING_ENCRYPTER_SERIALIZE_ERROR;
else
{
result.id = (struct ballot_identifier){
.len = state.len,
.bytes = state.buf,
};
}
}
// Construct the ballot tracker
if (result.status == VOTING_ENCRYPTER_SUCCESS)
{
struct ballot_tracker_rep rep = {.id = Voting_num_ballots};
struct serialize_state state = {
.status = SERIALIZE_STATE_RESERVING,
.len = 0,
.offset = 0,
.buf = NULL,
};
Serialize_reserve_ballot_tracker(&state, &rep);
Serialize_allocate(&state);
Serialize_write_ballot_tracker(&state, &rep);
if (state.status != SERIALIZE_STATE_WRITING)
result.status = VOTING_ENCRYPTER_SERIALIZE_ERROR;
else
{
result.tracker = (struct ballot_tracker){
.len = state.len,
.bytes = state.buf,
};
}
}
// Construct the message
struct encrypted_ballot_rep encrypted_ballot;
if (result.status == VOTING_ENCRYPTER_SUCCESS)
{
struct Crypto_encrypted_ballot_new_r result = Crypto_encrypted_ballot_new(encrypter->num_selections, Voting_num_ballots);
encrypted_ballot = result.result;
result.status = Voting_Encrypter_Crypto_status_convert(result.status);
}
if (result.status == VOTING_ENCRYPTER_SUCCESS)
{
struct uint4096_s uint4096_false_s;
uint4096_zext_o(&uint4096_false_s, (uint8_t[]){1}, 1);
const_uint4096 uint4096_true = uint4096_generator_default, uint4096_false = &uint4096_false_s;
for(uint32_t i = 0; i < encrypter->num_selections; i++) {
Crypto_encrypt(&encrypted_ballot.selections[i], encrypter->source, &encrypter->joint_key,
selections[i] ? uint4096_true : uint4096_false);
}
struct serialize_state state =
{ .status = SERIALIZE_STATE_RESERVING
, .len = 0
, .offset = 0
, .buf = NULL
};
Serialize_reserve_encrypted_ballot(&state, &encrypted_ballot);
Serialize_allocate(&state);
Serialize_write_encrypted_ballot(&state, &encrypted_ballot);
if (state.status != SERIALIZE_STATE_WRITING)
result.status = VOTING_ENCRYPTER_SERIALIZE_ERROR;
else
{
result.message = (struct register_ballot_message){
.len = state.len,
.bytes = state.buf,
};
}
}
if (result.status == VOTING_ENCRYPTER_SUCCESS)
Voting_num_ballots++;
return result;
}

Просмотреть файл

@ -4,15 +4,8 @@
#include <stdbool.h>
#include <stddef.h>
#include "max_values.h"
#include "voting/messages.h"
struct register_ballot_rep
{
uint64_t id;
uint32_t num_selections;
bool selections[MAX_SELECTIONS];
};
#include <electionguard/max_values.h>
#include <electionguard/voting/messages.h>
struct ballot_tracker_rep
{

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -1,8 +1,10 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "voting/tracker.h"
#include "nouns.h"
#include <electionguard/voting/tracker.h>
#include "voting/nouns.h"
const char chars[16] = "2346789BCDFGHJKM";

Просмотреть файл

@ -1,114 +0,0 @@
#include "serialize/crypto.h"
#include "serialize/builtins.h"
void Serialize_reserve_key(struct serialize_state *state,
struct key const *data)
{
for (uint32_t i = 0; i < KEY_SIZE; i++)
Serialize_reserve_uint8(state, &data->bytes[i]);
}
void Serialize_write_key(struct serialize_state *state, struct key const *data)
{
for (uint32_t i = 0; i < KEY_SIZE; i++)
Serialize_write_uint8(state, &data->bytes[i]);
}
void Serialize_read_key(struct serialize_state *state, struct key *data)
{
for (uint32_t i = 0; i < KEY_SIZE; i++)
Serialize_read_uint8(state, &data->bytes[i]);
}
void Serialize_reserve_private_key(struct serialize_state *state,
struct private_key const *data)
{
Serialize_reserve_uint32(state, &data->threshold);
for (uint32_t i = 0; i < data->threshold; i++)
Serialize_reserve_key(state, &data->coefficients[i]);
}
void Serialize_write_private_key(struct serialize_state *state,
struct private_key const *data)
{
Serialize_write_uint32(state, &data->threshold);
for (uint32_t i = 0; i < data->threshold; i++)
Serialize_write_key(state, &data->coefficients[i]);
}
void Serialize_read_private_key(struct serialize_state *state,
struct private_key *data)
{
Serialize_read_uint32(state, &data->threshold);
for (uint32_t i = 0; i < data->threshold; i++)
Serialize_read_key(state, &data->coefficients[i]);
}
void Serialize_reserve_public_key(struct serialize_state *state,
struct public_key const *data)
{
Serialize_reserve_uint32(state, &data->threshold);
for (uint32_t i = 0; i < data->threshold; i++)
Serialize_reserve_key(state, &data->coef_committments[i]);
}
void Serialize_write_public_key(struct serialize_state *state,
struct public_key const *data)
{
Serialize_write_uint32(state, &data->threshold);
for (uint32_t i = 0; i < data->threshold; i++)
Serialize_write_key(state, &data->coef_committments[i]);
}
void Serialize_read_public_key(struct serialize_state *state,
struct public_key *data)
{
Serialize_read_uint32(state, &data->threshold);
for (uint32_t i = 0; i < data->threshold; i++)
Serialize_read_key(state, &data->coef_committments[i]);
}
void Serialize_reserve_encrypted_key_share(
struct serialize_state *state, struct encrypted_key_share const *data)
{
Serialize_reserve_private_key(state, &data->private_key);
Serialize_reserve_public_key(state, &data->recipient_public_key);
}
void Serialize_write_encrypted_key_share(struct serialize_state *state,
struct encrypted_key_share const *data)
{
Serialize_write_private_key(state, &data->private_key);
Serialize_write_public_key(state, &data->recipient_public_key);
}
void Serialize_read_encrypted_key_share(struct serialize_state *state,
struct encrypted_key_share *data)
{
Serialize_read_private_key(state, &data->private_key);
Serialize_read_public_key(state, &data->recipient_public_key);
}
void Serialize_reserve_joint_public_key(struct serialize_state *state,
struct joint_public_key_rep const *data)
{
Serialize_reserve_uint32(state, &data->num_trustees);
for (size_t i = 0; i < data->num_trustees; i++)
Serialize_reserve_public_key(state, &data->public_keys[i]);
}
void Serialize_write_joint_public_key(struct serialize_state *state,
struct joint_public_key_rep const *data)
{
Serialize_write_uint32(state, &data->num_trustees);
for (size_t i = 0; i < data->num_trustees; i++)
Serialize_write_public_key(state, &data->public_keys[i]);
}
void Serialize_read_joint_public_key(struct serialize_state *state,
struct joint_public_key_rep *data)
{
Serialize_read_uint32(state, &data->num_trustees);
for (size_t i = 0; i < data->num_trustees; i++)
Serialize_read_public_key(state, &data->public_keys[i]);
}

Просмотреть файл

@ -1,174 +0,0 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "crypto_reps.h"
#include "serialize/state.h"
#include "serialize/voting.h"
#include "voting/encrypter.h"
#include "voting/message_reps.h"
#include "voting/num_ballots.h"
uint64_t Voting_num_ballots = 0;
struct Voting_Encrypter_s
{
struct uid uid;
struct joint_public_key joint_key;
uint32_t num_selections;
};
struct Voting_Encrypter_new_r
Voting_Encrypter_new(struct uid uid, struct joint_public_key joint_key,
uint32_t num_selections)
{
struct Voting_Encrypter_new_r result;
result.status = VOTING_ENCRYPTER_SUCCESS;
// Allocate the Encrypter
result.encrypter = malloc(sizeof(struct Voting_Encrypter_s));
if (result.encrypter == NULL)
result.status = VOTING_ENCRYPTER_INSUFFICIENT_MEMORY;
// Clone the uid
if (result.status == VOTING_ENCRYPTER_SUCCESS)
{
uint8_t *buf = malloc(uid.len);
if (buf == NULL)
result.status = VOTING_ENCRYPTER_INSUFFICIENT_MEMORY;
else
memcpy(buf, uid.bytes, uid.len);
result.encrypter->uid = (struct uid){
.len = uid.len,
.bytes = buf,
};
}
// Clone the joint key
if (result.status == VOTING_ENCRYPTER_SUCCESS)
{
uint8_t *buf = malloc(joint_key.len);
if (buf == NULL)
result.status = VOTING_ENCRYPTER_INSUFFICIENT_MEMORY;
else
memcpy(buf, joint_key.bytes, joint_key.len);
result.encrypter->joint_key = (struct joint_public_key){
.len = joint_key.len,
.bytes = buf,
};
}
if (result.status == VOTING_ENCRYPTER_SUCCESS)
result.encrypter->num_selections = num_selections;
return result;
}
void Voting_Encrypter_free(Voting_Encrypter encrypter)
{
free((void *)encrypter->uid.bytes);
free((void *)encrypter->joint_key.bytes);
free((void *)encrypter);
}
struct Voting_Encrypter_encrypt_ballot_r
Voting_Encrypter_encrypt_ballot(Voting_Encrypter encrypter,
bool const *selections)
{
// Suppress compiler warning that encrypter is unused
(void)encrypter;
struct Voting_Encrypter_encrypt_ballot_r result;
result.status = VOTING_ENCRYPTER_SUCCESS;
// Construct the ballot id
{
struct ballot_identifier_rep rep = {.id = Voting_num_ballots};
struct serialize_state state = {
.status = SERIALIZE_STATE_RESERVING,
.len = 0,
.offset = 0,
.buf = NULL,
};
Serialize_reserve_ballot_identifier(&state, &rep);
Serialize_allocate(&state);
Serialize_write_ballot_identifier(&state, &rep);
if (state.status != SERIALIZE_STATE_WRITING)
result.status = VOTING_ENCRYPTER_SERIALIZE_ERROR;
else
{
result.id = (struct ballot_identifier){
.len = state.len,
.bytes = state.buf,
};
}
}
// Construct the ballot tracker
if (result.status == VOTING_ENCRYPTER_SUCCESS)
{
struct ballot_tracker_rep rep = {.id = Voting_num_ballots};
struct serialize_state state = {
.status = SERIALIZE_STATE_RESERVING,
.len = 0,
.offset = 0,
.buf = NULL,
};
Serialize_reserve_ballot_tracker(&state, &rep);
Serialize_allocate(&state);
Serialize_write_ballot_tracker(&state, &rep);
if (state.status != SERIALIZE_STATE_WRITING)
result.status = VOTING_ENCRYPTER_SERIALIZE_ERROR;
else
{
result.tracker = (struct ballot_tracker){
.len = state.len,
.bytes = state.buf,
};
}
}
// Construct the message
if (result.status == VOTING_ENCRYPTER_SUCCESS)
{
struct register_ballot_rep rep;
rep.id = Voting_num_ballots;
rep.num_selections = encrypter->num_selections;
memcpy(&rep.selections, selections,
encrypter->num_selections * sizeof(bool));
struct serialize_state state = {
.status = SERIALIZE_STATE_RESERVING,
.len = 0,
.offset = 0,
.buf = NULL,
};
Serialize_reserve_register_ballot(&state, &rep);
Serialize_allocate(&state);
Serialize_write_register_ballot(&state, &rep);
if (state.status != SERIALIZE_STATE_WRITING)
result.status = VOTING_ENCRYPTER_SERIALIZE_ERROR;
else
{
result.message = (struct register_ballot_message){
.len = state.len,
.bytes = state.buf,
};
}
}
if (result.status == VOTING_ENCRYPTER_SUCCESS)
Voting_num_ballots++;
return result;
}