issue #25 - format libprio with clang-format, using Mozilla style (#26)

* issue #25 - format libprio with clang-format, using Mozilla style

* force clang 3.9 (latest available on Ubuntu Trusty)

* remove clang-format file, 3.9 is confused by some settings. try using built-in Mozilla style instead
This commit is contained in:
Robert Helmer 2018-08-29 13:47:18 -07:00 коммит произвёл GitHub
Родитель 4899697586
Коммит ded8b1054b
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
39 изменённых файлов: 10714 добавлений и 10644 удалений

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

@ -12,8 +12,10 @@ addons:
packages:
- libnspr4-dev
- libnss3-dev
- clang-format-3.9
script:
- ./scripts/clang-format.sh
- scons
- export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
- ./build/ptest/ptest -v

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

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
@ -17,25 +17,25 @@
#include "prio/encrypt.h"
#include "prio/util.h"
static void
init_data (bool *data, int datalen)
static void
init_data(bool* data, int datalen)
{
// The client's data submission is an arbitrary boolean vector.
for (int i=0; i < datalen; i++) {
for (int i = 0; i < datalen; i++) {
// Arbitrary data
data[i] = rand () % 2;
data[i] = rand() % 2;
}
}
static SECStatus
read_string_from_hex (unsigned char **str_out, unsigned int *strLen,
const char *input, const char **new_input)
read_string_from_hex(unsigned char** str_out, unsigned int* strLen,
const char* input, const char** new_input)
{
SECStatus rv = SECSuccess;
*strLen = 0;
int read = 0;
int outCount = 0;
const char *inp = input;
const char* inp = input;
while (true) {
unsigned char byte = '\0';
@ -57,44 +57,46 @@ read_string_from_hex (unsigned char **str_out, unsigned int *strLen,
}
static SECStatus
read_browser_reply (FILE *infile,
unsigned char **for_server_a, unsigned int *aLen,
unsigned char **for_server_b, unsigned int *bLen)
read_browser_reply(FILE* infile, unsigned char** for_server_a,
unsigned int* aLen, unsigned char** for_server_b,
unsigned int* bLen)
{
SECStatus rv = SECFailure;
char *raw_input = NULL;
char* raw_input = NULL;
size_t rawLen = 0;
puts ("Getting line of input.");
P_CHECKCB (getline (&raw_input, &rawLen, infile) > 0);
puts ("Got line of input.");
puts("Getting line of input.");
P_CHECKCB(getline(&raw_input, &rawLen, infile) > 0);
puts("Got line of input.");
P_CHECKA (*for_server_a = malloc (rawLen * sizeof (unsigned char)));
P_CHECKA (*for_server_b = malloc (rawLen * sizeof (unsigned char)));
P_CHECKA(*for_server_a = malloc(rawLen * sizeof(unsigned char)));
P_CHECKA(*for_server_b = malloc(rawLen * sizeof(unsigned char)));
*aLen = 0;
*bLen = 0;
P_CHECKCB (rawLen > 14);
P_CHECKCB(rawLen > 14);
// Header is 14 chars long
const char *new_input;
puts ("Reading string A");
P_CHECKC (read_string_from_hex (for_server_a, aLen, raw_input + 14, &new_input));
puts ("Read string A");
const char* new_input;
puts("Reading string A");
P_CHECKC(
read_string_from_hex(for_server_a, aLen, raw_input + 14, &new_input));
puts("Read string A");
// Skip over for_server_a string and one-char delimeter
puts ("Reading string B");
P_CHECKC (read_string_from_hex (for_server_b, bLen, new_input, NULL));
puts ("Read string B");
puts("Reading string B");
P_CHECKC(read_string_from_hex(for_server_b, bLen, new_input, NULL));
puts("Read string B");
cleanup:
if (raw_input) free (raw_input);
if (raw_input)
free(raw_input);
return rv;
}
static int
verify_full (const char *path_to_xpcshell, int pathlen)
verify_full(const char* path_to_xpcshell, int pathlen)
{
SECStatus rv = SECSuccess;
@ -115,97 +117,97 @@ verify_full (const char *path_to_xpcshell, int pathlen)
PrioTotalShare tA = NULL;
PrioTotalShare tB = NULL;
FILE *shell = NULL;
int cmdlen = pathlen + 2*CURVE25519_KEY_LEN_HEX + 128;
FILE* shell = NULL;
int cmdlen = pathlen + 2 * CURVE25519_KEY_LEN_HEX + 128;
char cmd[cmdlen];
memset (cmd, 0, cmdlen);
memset(cmd, 0, cmdlen);
unsigned char *for_server_a = NULL;
unsigned char *for_server_b = NULL;
unsigned char* for_server_a = NULL;
unsigned char* for_server_b = NULL;
const int seed = time (NULL);
srand (seed);
printf ("Using srand seed %d\n", seed);
const int seed = time(NULL);
srand(seed);
printf("Using srand seed %d\n", seed);
// Number of different boolean data fields we collect.
const int ndata = 3;
//unsigned char batch_id_str[] = "abcde";
// unsigned char batch_id_str[] = "abcde";
unsigned char batch_id_str[32];
memset (batch_id_str, 0, sizeof batch_id_str);
snprintf ((char *)batch_id_str, sizeof batch_id_str, "%d", rand());
memset(batch_id_str, 0, sizeof batch_id_str);
snprintf((char*)batch_id_str, sizeof batch_id_str, "%d", rand());
bool data_items[ndata];
unsigned long output[ndata];
init_data (data_items, ndata);
init_data(data_items, ndata);
// Initialize NSS random number generator.
P_CHECKC (Prio_init ());
P_CHECKC(Prio_init());
// Generate keypairs for servers
P_CHECKC (Keypair_new (&skA, &pkA));
P_CHECKC (Keypair_new (&skB, &pkB));
P_CHECKC(Keypair_new(&skA, &pkA));
P_CHECKC(Keypair_new(&skB, &pkB));
// Export public keys to hex and print to stdout
unsigned char pk_hexA[CURVE25519_KEY_LEN_HEX+1];
unsigned char pk_hexB[CURVE25519_KEY_LEN_HEX+1];
P_CHECKC (PublicKey_export_hex (pkA, pk_hexA));
P_CHECKC (PublicKey_export_hex (pkB, pk_hexB));
unsigned char pk_hexA[CURVE25519_KEY_LEN_HEX + 1];
unsigned char pk_hexB[CURVE25519_KEY_LEN_HEX + 1];
P_CHECKC(PublicKey_export_hex(pkA, pk_hexA));
P_CHECKC(PublicKey_export_hex(pkB, pk_hexB));
snprintf (cmd, cmdlen, "%s %s %s %s %s %d %d %d",
path_to_xpcshell, "encode-once.js",
pk_hexA, pk_hexB, batch_id_str,
data_items[0], data_items[1], data_items[2]);
snprintf(cmd, cmdlen, "%s %s %s %s %s %d %d %d", path_to_xpcshell,
"encode-once.js", pk_hexA, pk_hexB, batch_id_str, data_items[0],
data_items[1], data_items[2]);
printf ("> %s\n", cmd);
P_CHECKA (shell = popen(cmd, "r"));
printf("> %s\n", cmd);
P_CHECKA(shell = popen(cmd, "r"));
puts("Ran command.");
// Use the default configuration parameters.
P_CHECKA (cfg = PrioConfig_new (ndata, pkA, pkB, batch_id_str,
strlen ((char *)batch_id_str)));
P_CHECKA(cfg = PrioConfig_new(ndata, pkA, pkB, batch_id_str,
strlen((char*)batch_id_str)));
PrioPRGSeed server_secret;
P_CHECKC (PrioPRGSeed_randomize (&server_secret));
P_CHECKC(PrioPRGSeed_randomize(&server_secret));
// Initialize two server objects. The role of the servers need not
// be symmetric. In a deployment, we envision that:
// * Server A is the main telemetry server that is always online.
// * Server A is the main telemetry server that is always online.
// Clients send their encrypted data packets to Server A and
// Server A stores them.
// * Server B only comes online when the two servers want to compute
// the final aggregate statistics.
P_CHECKA (sA = PrioServer_new (cfg, PRIO_SERVER_A, skA, server_secret));
P_CHECKA (sB = PrioServer_new (cfg, PRIO_SERVER_B, skB, server_secret));
P_CHECKA(sA = PrioServer_new(cfg, PRIO_SERVER_A, skA, server_secret));
P_CHECKA(sB = PrioServer_new(cfg, PRIO_SERVER_B, skB, server_secret));
// Initialize empty verifier objects
P_CHECKA (vA = PrioVerifier_new (sA));
P_CHECKA (vB = PrioVerifier_new (sB));
P_CHECKA(vA = PrioVerifier_new(sA));
P_CHECKA(vB = PrioVerifier_new(sB));
// Initialize shares of final aggregate statistics
P_CHECKA (tA = PrioTotalShare_new ());
P_CHECKA (tB = PrioTotalShare_new ());
P_CHECKA(tA = PrioTotalShare_new());
P_CHECKA(tB = PrioTotalShare_new());
// Initialize shares of verification packets
P_CHECKA (p1A = PrioPacketVerify1_new ());
P_CHECKA (p1B = PrioPacketVerify1_new ());
P_CHECKA (p2A = PrioPacketVerify2_new ());
P_CHECKA (p2B = PrioPacketVerify2_new ());
P_CHECKA(p1A = PrioPacketVerify1_new());
P_CHECKA(p1B = PrioPacketVerify1_new());
P_CHECKA(p2A = PrioPacketVerify2_new());
P_CHECKA(p2B = PrioPacketVerify2_new());
// I. CLIENT DATA SUBMISSION.
//
// Read in the client data packets
unsigned int aLen = 0, bLen = 0;
puts ("Reading...");
P_CHECKC (read_browser_reply (shell, &for_server_a, &aLen, &for_server_b, &bLen));
printf ("Read reply from browser. LenA: %u, LenB: %u\n", aLen, bLen);
puts("Reading...");
P_CHECKC(
read_browser_reply(shell, &for_server_a, &aLen, &for_server_b, &bLen));
printf("Read reply from browser. LenA: %u, LenB: %u\n", aLen, bLen);
// II. VALIDATION PROTOCOL. (at servers)
//
// The servers now run a short 2-step protocol to check each
// The servers now run a short 2-step protocol to check each
// client's packet:
// 1) Servers A and B broadcast one message (PrioPacketVerify1)
// 1) Servers A and B broadcast one message (PrioPacketVerify1)
// to each other.
// 2) Servers A and B broadcast another message (PrioPacketVerify2)
// to each other.
@ -214,107 +216,108 @@ verify_full (const char *path_to_xpcshell, int pathlen)
// running total of aggregate statistics) or ill-formed
// (in which case they ignore it).
// These messages must be sent over an authenticated channel, so
// that each server is assured that every received message came
// that each server is assured that every received message came
// from its peer.
// Set up a Prio verifier object.
P_CHECKC (PrioVerifier_set_data (vA, for_server_a, aLen));
P_CHECKC (PrioVerifier_set_data (vB, for_server_b, bLen));
P_CHECKC(PrioVerifier_set_data(vA, for_server_a, aLen));
P_CHECKC(PrioVerifier_set_data(vB, for_server_b, bLen));
puts("Imported data.");
// Both servers produce a packet1. Server A sends p1A to Server B
// and vice versa.
P_CHECKC (PrioPacketVerify1_set_data (p1A, vA));
P_CHECKC (PrioPacketVerify1_set_data (p1B, vB));
P_CHECKC(PrioPacketVerify1_set_data(p1A, vA));
P_CHECKC(PrioPacketVerify1_set_data(p1B, vB));
puts("Set data.");
// Both servers produce a packet2. Server A sends p2A to Server B
// and vice versa.
P_CHECKC (PrioPacketVerify2_set_data(p2A, vA, p1A, p1B));
P_CHECKC (PrioPacketVerify2_set_data(p2B, vB, p1A, p1B));
P_CHECKC(PrioPacketVerify2_set_data(p2A, vA, p1A, p1B));
P_CHECKC(PrioPacketVerify2_set_data(p2B, vB, p1A, p1B));
// Using p2A and p2B, the servers can determine whether the request
// is valid. (In fact, only Server A needs to perform this
// check, since Server A can just tell Server B whether the check
// succeeded or failed.)
puts ("Checking validity.");
P_CHECKC (PrioVerifier_isValid (vA, p2A, p2B));
P_CHECKC (PrioVerifier_isValid (vB, p2A, p2B));
puts ("Are valid.");
// is valid. (In fact, only Server A needs to perform this
// check, since Server A can just tell Server B whether the check
// succeeded or failed.)
puts("Checking validity.");
P_CHECKC(PrioVerifier_isValid(vA, p2A, p2B));
P_CHECKC(PrioVerifier_isValid(vB, p2A, p2B));
puts("Are valid.");
// If we get here, the client packet is valid, so add it to the aggregate
// statistic counter for both servers.
P_CHECKC (PrioServer_aggregate (sA, vA));
P_CHECKC (PrioServer_aggregate (sB, vB));
P_CHECKC(PrioServer_aggregate(sA, vA));
P_CHECKC(PrioServer_aggregate(sB, vB));
// The servers repeat the steps above for each client submission.
// III. PRODUCTION OF AGGREGATE STATISTICS.
//
// After collecting aggregates from MANY clients, the servers can compute
// their shares of the aggregate statistics.
// their shares of the aggregate statistics.
//
// Server B can send tB to Server A.
P_CHECKC (PrioTotalShare_set_data (tA, sA));
P_CHECKC (PrioTotalShare_set_data (tB, sB));
P_CHECKC(PrioTotalShare_set_data(tA, sA));
P_CHECKC(PrioTotalShare_set_data(tB, sB));
// Once Server A has tA and tB, it can learn the aggregate statistics
// in the clear.
P_CHECKC (PrioTotalShare_final (cfg, output, tA, tB));
for (int i=0; i < ndata; i++) {
//printf("output[%d] = %lu\n", i, output[i]);
//printf("data[%d] = %d\n", i, (int)data_items[i]);
P_CHECKCB (output[i] == data_items[i]);
P_CHECKC(PrioTotalShare_final(cfg, output, tA, tB));
for (int i = 0; i < ndata; i++) {
// printf("output[%d] = %lu\n", i, output[i]);
// printf("data[%d] = %d\n", i, (int)data_items[i]);
P_CHECKCB(output[i] == data_items[i]);
}
puts ("Success!");
puts("Success!");
cleanup:
if (rv != SECSuccess) {
fprintf (stderr, "Warning: unexpected failure.\n");
fprintf(stderr, "Warning: unexpected failure.\n");
}
if (for_server_a) free (for_server_a);
if (for_server_b) free (for_server_b);
if (for_server_a)
free(for_server_a);
if (for_server_b)
free(for_server_b);
PrioTotalShare_clear (tA);
PrioTotalShare_clear (tB);
PrioTotalShare_clear(tA);
PrioTotalShare_clear(tB);
PrioPacketVerify2_clear (p2A);
PrioPacketVerify2_clear (p2B);
PrioPacketVerify2_clear(p2A);
PrioPacketVerify2_clear(p2B);
PrioPacketVerify1_clear (p1A);
PrioPacketVerify1_clear (p1B);
PrioPacketVerify1_clear(p1A);
PrioPacketVerify1_clear(p1B);
PrioVerifier_clear (vA);
PrioVerifier_clear (vB);
PrioVerifier_clear(vA);
PrioVerifier_clear(vB);
PrioServer_clear (sA);
PrioServer_clear (sB);
PrioConfig_clear (cfg);
PrioServer_clear(sA);
PrioServer_clear(sB);
PrioConfig_clear(cfg);
PublicKey_clear (pkA);
PublicKey_clear (pkB);
PublicKey_clear(pkA);
PublicKey_clear(pkB);
PrivateKey_clear (skA);
PrivateKey_clear (skB);
PrivateKey_clear(skA);
PrivateKey_clear(skB);
Prio_clear ();
Prio_clear();
return !(rv == SECSuccess);
}
int
main (int argc, char **argv)
int
main(int argc, char** argv)
{
puts("== Prio browser test utility. ==");
puts("(Note: Expects to be run in the same directory as encode-once.js.)");
if (argc != 2) {
fprintf (stderr, "Usage ./%s <path_to_xpcshell>\n", argv[0]);
fprintf(stderr, "Usage ./%s <path_to_xpcshell>\n", argv[0]);
return 1;
}
return verify_full (argv[1], strlen (argv[1]));
return verify_full(argv[1], strlen(argv[1]));
}

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

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@ -33,47 +33,44 @@ typedef unsigned char PrioPRGSeed[PRG_SEED_LENGTH];
/*
* Type for each of the two servers.
*/
typedef enum {
PRIO_SERVER_A,
PRIO_SERVER_B
} PrioServerId;
typedef enum { PRIO_SERVER_A, PRIO_SERVER_B } PrioServerId;
/*
* Opaque types
*/
typedef struct prio_config *PrioConfig;
typedef const struct prio_config *const_PrioConfig;
typedef struct prio_config* PrioConfig;
typedef const struct prio_config* const_PrioConfig;
typedef struct prio_server *PrioServer;
typedef const struct prio_server *const_PrioServer;
typedef struct prio_server* PrioServer;
typedef const struct prio_server* const_PrioServer;
typedef struct prio_verifier *PrioVerifier;
typedef const struct prio_verifier *const_PrioVerifier;
typedef struct prio_verifier* PrioVerifier;
typedef const struct prio_verifier* const_PrioVerifier;
typedef struct prio_packet_verify1 *PrioPacketVerify1;
typedef const struct prio_packet_verify1 *const_PrioPacketVerify1;
typedef struct prio_packet_verify1* PrioPacketVerify1;
typedef const struct prio_packet_verify1* const_PrioPacketVerify1;
typedef struct prio_packet_verify2 *PrioPacketVerify2;
typedef const struct prio_packet_verify2 *const_PrioPacketVerify2;
typedef struct prio_packet_verify2* PrioPacketVerify2;
typedef const struct prio_packet_verify2* const_PrioPacketVerify2;
typedef struct prio_total_share *PrioTotalShare;
typedef const struct prio_total_share *const_PrioTotalShare;
typedef struct prio_total_share* PrioTotalShare;
typedef const struct prio_total_share* const_PrioTotalShare;
typedef SECKEYPublicKey *PublicKey;
typedef const SECKEYPublicKey *const_PublicKey;
typedef SECKEYPublicKey* PublicKey;
typedef const SECKEYPublicKey* const_PublicKey;
typedef SECKEYPrivateKey *PrivateKey;
typedef const SECKEYPrivateKey *const_PrivateKey;
typedef SECKEYPrivateKey* PrivateKey;
typedef const SECKEYPrivateKey* const_PrivateKey;
/*
/*
* Initialize and clear random number generator state.
* You must call Prio_init() before using the library.
* To avoid memory leaks, call Prio_clear() afterwards.
*/
SECStatus Prio_init ();
SECStatus Prio_init();
void Prio_clear();
/*
/*
* PrioConfig holds the system parameters. The two relevant things determined
* by the config object are:
* (1) the number of data fields we are collecting, and
@ -87,35 +84,37 @@ void Prio_clear();
* Each set of aggregate statistics should use a different `batch_id`.
*
* `PrioConfig_new` does not keep a pointer to the `batch_id` string that the
* caller passes in, so you may free the `batch_id` string as soon as
* caller passes in, so you may free the `batch_id` string as soon as
* `PrioConfig_new` returns.
*/
PrioConfig PrioConfig_new (int n_fields, PublicKey server_a, PublicKey server_b,
const unsigned char *batch_id, unsigned int batch_id_len);
void PrioConfig_clear (PrioConfig cfg);
int PrioConfig_numDataFields (const_PrioConfig cfg);
PrioConfig PrioConfig_new(int n_fields, PublicKey server_a, PublicKey server_b,
const unsigned char* batch_id,
unsigned int batch_id_len);
void PrioConfig_clear(PrioConfig cfg);
int PrioConfig_numDataFields(const_PrioConfig cfg);
/*
* Create a PrioConfig object with no encryption keys. This routine is
* Create a PrioConfig object with no encryption keys. This routine is
* useful for testing, but PrioClient_encode() will always fail when used with
* this config.
*/
PrioConfig PrioConfig_newTest (int n_fields);
PrioConfig PrioConfig_newTest(int n_fields);
/*
/*
* We use the PublicKey and PrivateKey objects for public-key encryption. Each
* Prio server has an associated public key, and the clients use these keys to
* encrypt messages to the servers.
*/
SECStatus Keypair_new (PrivateKey *pvtkey, PublicKey *pubkey);
SECStatus Keypair_new(PrivateKey* pvtkey, PublicKey* pubkey);
/*
* Import a new curve25519 public key from the raw bytes given. The key passed in
* Import a new curve25519 public key from the raw bytes given. The key passed
* in
* as `data` should be of length `CURVE25519_KEY_LEN`. This function allocates
* a new PublicKey object, which the caller must free using `PublicKey_clear`.
*/
SECStatus PublicKey_import (PublicKey *pk, const unsigned char *data, unsigned int dataLen);
SECStatus PublicKey_import(PublicKey* pk, const unsigned char* data,
unsigned int dataLen);
/*
* Import a new curve25519 public key from a hex string that contains only the
@ -123,138 +122,136 @@ SECStatus PublicKey_import (PublicKey *pk, const unsigned char *data, unsigned i
* length `CURVE25519_KEY_LEN_HEX`. This function allocates a new PublicKey
* object, which the caller must free using `PublicKey_clear`.
*/
SECStatus PublicKey_import_hex (PublicKey *pk, const unsigned char *hex_data,
unsigned int dataLen);
SECStatus PublicKey_import_hex(PublicKey* pk, const unsigned char* hex_data,
unsigned int dataLen);
/*
* Export a curve25519 public key as a raw byte-array.
*/
SECStatus PublicKey_export (const_PublicKey pk, unsigned char data[CURVE25519_KEY_LEN]);
SECStatus PublicKey_export(const_PublicKey pk,
unsigned char data[CURVE25519_KEY_LEN]);
/*
* Export a curve25519 public key as a NULL-terminated hex string.
*/
SECStatus PublicKey_export_hex (const_PublicKey pk,
unsigned char data[CURVE25519_KEY_LEN_HEX+1]);
void PublicKey_clear (PublicKey pubkey);
void PrivateKey_clear (PrivateKey pvtkey);
SECStatus PublicKey_export_hex(const_PublicKey pk,
unsigned char data[CURVE25519_KEY_LEN_HEX + 1]);
void PublicKey_clear(PublicKey pubkey);
void PrivateKey_clear(PrivateKey pvtkey);
/*
* PrioPacketClient_encode
*
* Takes as input a pointer to an array (`data_in`) of boolean values
* whose length is equal to the number of data fields specified in
* Takes as input a pointer to an array (`data_in`) of boolean values
* whose length is equal to the number of data fields specified in
* the config. It then encodes the data for servers A and B into a
* string.
* string.
*
* NOTE: The caller must free() the strings `for_server_a` and
* `for_server_b` to avoid memory leaks.
*/
SECStatus
PrioClient_encode (const_PrioConfig cfg, const bool *data_in,
unsigned char **for_server_a, unsigned int *aLen,
unsigned char **for_server_b, unsigned int *bLen);
SECStatus PrioClient_encode(const_PrioConfig cfg, const bool* data_in,
unsigned char** for_server_a, unsigned int* aLen,
unsigned char** for_server_b, unsigned int* bLen);
/*
* Generate a new PRG seed using the NSS global randomness source.
* Use this routine to initialize the secret that the two Prio servers
* share.
*/
SECStatus PrioPRGSeed_randomize (PrioPRGSeed *seed);
SECStatus PrioPRGSeed_randomize(PrioPRGSeed* seed);
/*
* The PrioServer object holds the state of the Prio servers.
* Pass in the _same_ secret PRGSeed when initializing the two servers.
* The PRGSeed must remain secret to the two servers.
*/
PrioServer PrioServer_new (const_PrioConfig cfg, PrioServerId server_idx,
PrivateKey server_priv, const PrioPRGSeed server_shared_secret);
void PrioServer_clear (PrioServer s);
PrioServer PrioServer_new(const_PrioConfig cfg, PrioServerId server_idx,
PrivateKey server_priv,
const PrioPRGSeed server_shared_secret);
void PrioServer_clear(PrioServer s);
/*
/*
* After receiving a client packet, each of the servers generate
* a PrioVerifier object that they use to check whether the client's
* encoded packet is well formed.
*/
PrioVerifier PrioVerifier_new (PrioServer s);
void PrioVerifier_clear (PrioVerifier v);
PrioVerifier PrioVerifier_new(PrioServer s);
void PrioVerifier_clear(PrioVerifier v);
/*
/*
* Read in encrypted data from the client, decrypt it, and prepare to check the
* request for validity.
*/
SECStatus PrioVerifier_set_data (PrioVerifier v,
unsigned char *data, unsigned int dataLen);
SECStatus PrioVerifier_set_data(PrioVerifier v, unsigned char* data,
unsigned int dataLen);
/*
* Generate the first packet that servers need to exchange to verify the
* client's submission. This should be sent over a TLS connection between the
* servers.
*/
PrioPacketVerify1 PrioPacketVerify1_new (void);
void PrioPacketVerify1_clear (PrioPacketVerify1 p1);
PrioPacketVerify1 PrioPacketVerify1_new(void);
void PrioPacketVerify1_clear(PrioPacketVerify1 p1);
SECStatus PrioPacketVerify1_set_data (PrioPacketVerify1 p1,
const_PrioVerifier v);
SECStatus PrioPacketVerify1_set_data(PrioPacketVerify1 p1,
const_PrioVerifier v);
SECStatus PrioPacketVerify1_write (const_PrioPacketVerify1 p,
msgpack_packer *pk);
SECStatus PrioPacketVerify1_read (PrioPacketVerify1 p,
msgpack_unpacker *upk, const_PrioConfig cfg);
SECStatus PrioPacketVerify1_write(const_PrioPacketVerify1 p,
msgpack_packer* pk);
SECStatus PrioPacketVerify1_read(PrioPacketVerify1 p, msgpack_unpacker* upk,
const_PrioConfig cfg);
/*
/*
* Generate the second packet that the servers need to exchange to verify the
* client's submission. The routine takes as input the PrioPacketVerify1
* packets from both server A and server B.
*
* This should be sent over a TLS connection between the servers.
*/
PrioPacketVerify2 PrioPacketVerify2_new (void);
void PrioPacketVerify2_clear (PrioPacketVerify2 p);
PrioPacketVerify2 PrioPacketVerify2_new(void);
void PrioPacketVerify2_clear(PrioPacketVerify2 p);
SECStatus PrioPacketVerify2_set_data (PrioPacketVerify2 p2, const_PrioVerifier v,
const_PrioPacketVerify1 p1A, const_PrioPacketVerify1 p1B);
SECStatus PrioPacketVerify2_set_data(PrioPacketVerify2 p2, const_PrioVerifier v,
const_PrioPacketVerify1 p1A,
const_PrioPacketVerify1 p1B);
SECStatus PrioPacketVerify2_write (const_PrioPacketVerify2 p,
msgpack_packer *pk);
SECStatus PrioPacketVerify2_read (PrioPacketVerify2 p,
msgpack_unpacker *upk, const_PrioConfig cfg);
SECStatus PrioPacketVerify2_write(const_PrioPacketVerify2 p,
msgpack_packer* pk);
SECStatus PrioPacketVerify2_read(PrioPacketVerify2 p, msgpack_unpacker* upk,
const_PrioConfig cfg);
/*
/*
* Use the PrioPacketVerify2s from both servers to check whether
* the client's submission is well formed.
*/
SECStatus PrioVerifier_isValid (const_PrioVerifier v,
const_PrioPacketVerify2 pA, const_PrioPacketVerify2 pB);
SECStatus PrioVerifier_isValid(const_PrioVerifier v, const_PrioPacketVerify2 pA,
const_PrioPacketVerify2 pB);
/*
* Each of the two servers calls this routine to aggregate the data
* submission from a client that is included in the PrioVerifier object.
*
* IMPORTANT: This routine does *not* check the validity of the client's
* data packet. The servers must execute the verification checks
* data packet. The servers must execute the verification checks
* above before aggregating any client data.
*/
SECStatus PrioServer_aggregate (PrioServer s, PrioVerifier v);
SECStatus PrioServer_aggregate(PrioServer s, PrioVerifier v);
/*
/*
* After the servers have aggregated data packets from "enough" clients
* (this determines the anonymity set size), each server runs this routine
* to get a share of the aggregate statistics.
* to get a share of the aggregate statistics.
*/
PrioTotalShare PrioTotalShare_new (void);
void PrioTotalShare_clear (PrioTotalShare t);
PrioTotalShare PrioTotalShare_new(void);
void PrioTotalShare_clear(PrioTotalShare t);
SECStatus PrioTotalShare_set_data (PrioTotalShare t, const_PrioServer s);
SECStatus PrioTotalShare_set_data(PrioTotalShare t, const_PrioServer s);
SECStatus PrioTotalShare_write (const_PrioTotalShare t,
msgpack_packer *pk);
SECStatus PrioTotalShare_read (PrioTotalShare t,
msgpack_unpacker *upk, const_PrioConfig cfg);
SECStatus PrioTotalShare_write(const_PrioTotalShare t, msgpack_packer* pk);
SECStatus PrioTotalShare_read(PrioTotalShare t, msgpack_unpacker* upk,
const_PrioConfig cfg);
/*
* Read the output data into an array of unsigned longs. You should
@ -262,9 +259,9 @@ SECStatus PrioTotalShare_read (PrioTotalShare t,
* the pointer `output` points to a buffer large enough to store
* one long per data field.
*/
SECStatus PrioTotalShare_final (const_PrioConfig cfg, unsigned long *output,
const_PrioTotalShare tA, const_PrioTotalShare tB);
SECStatus PrioTotalShare_final(const_PrioConfig cfg, unsigned long* output,
const_PrioTotalShare tA,
const_PrioTotalShare tB);
#endif /* __PRIO_H__ */

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

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
@ -13,7 +13,7 @@
#include "prio/util.h"
int
verify_full (void)
verify_full(void)
{
SECStatus rv = SECSuccess;
@ -34,14 +34,14 @@ verify_full (void)
PrioTotalShare tA = NULL;
PrioTotalShare tB = NULL;
unsigned char *for_server_a = NULL;
unsigned char *for_server_b = NULL;
unsigned char* for_server_a = NULL;
unsigned char* for_server_b = NULL;
const unsigned char *batch_id = (unsigned char *)"prio_batch_2018-04-17";
const unsigned int batch_id_len = strlen ((char *)batch_id);
const unsigned char* batch_id = (unsigned char*)"prio_batch_2018-04-17";
const unsigned int batch_id_len = strlen((char*)batch_id);
// Initialize NSS random number generator.
P_CHECKC (Prio_init ());
P_CHECKC(Prio_init());
// Number of different boolean data fields we collect.
const int ndata = 100;
@ -49,50 +49,49 @@ verify_full (void)
// Number of clients to simulate.
const int nclients = 10;
// New scope to avoid goto weirdness
{
bool data_items[ndata];
// Generate keypairs for servers
P_CHECKC (Keypair_new (&skA, &pkA));
P_CHECKC (Keypair_new (&skB, &pkB));
P_CHECKC(Keypair_new(&skA, &pkA));
P_CHECKC(Keypair_new(&skB, &pkB));
// Use the default configuration parameters.
P_CHECKA (cfg = PrioConfig_new (ndata, pkA, pkB, batch_id, batch_id_len));
P_CHECKA(cfg = PrioConfig_new(ndata, pkA, pkB, batch_id, batch_id_len));
PrioPRGSeed server_secret;
P_CHECKC (PrioPRGSeed_randomize (&server_secret));
P_CHECKC(PrioPRGSeed_randomize(&server_secret));
// Initialize two server objects. The role of the servers need not
// be symmetric. In a deployment, we envision that:
// * Server A is the main telemetry server that is always online.
// * Server A is the main telemetry server that is always online.
// Clients send their encrypted data packets to Server A and
// Server A stores them.
// * Server B only comes online when the two servers want to compute
// the final aggregate statistics.
P_CHECKA (sA = PrioServer_new (cfg, PRIO_SERVER_A, skA, server_secret));
P_CHECKA (sB = PrioServer_new (cfg, PRIO_SERVER_B, skB, server_secret));
P_CHECKA(sA = PrioServer_new(cfg, PRIO_SERVER_A, skA, server_secret));
P_CHECKA(sB = PrioServer_new(cfg, PRIO_SERVER_B, skB, server_secret));
// Initialize empty verifier objects
P_CHECKA (vA = PrioVerifier_new (sA));
P_CHECKA (vB = PrioVerifier_new (sB));
P_CHECKA(vA = PrioVerifier_new(sA));
P_CHECKA(vB = PrioVerifier_new(sB));
// Initialize shares of final aggregate statistics
P_CHECKA (tA = PrioTotalShare_new ());
P_CHECKA (tB = PrioTotalShare_new ());
P_CHECKA(tA = PrioTotalShare_new());
P_CHECKA(tB = PrioTotalShare_new());
// Initialize shares of verification packets
P_CHECKA (p1A = PrioPacketVerify1_new ());
P_CHECKA (p1B = PrioPacketVerify1_new ());
P_CHECKA (p2A = PrioPacketVerify2_new ());
P_CHECKA (p2B = PrioPacketVerify2_new ());
P_CHECKA(p1A = PrioPacketVerify1_new());
P_CHECKA(p1B = PrioPacketVerify1_new());
P_CHECKA(p2A = PrioPacketVerify2_new());
P_CHECKA(p2B = PrioPacketVerify2_new());
// Generate client data packets.
for (int c=0; c < nclients; c++) {
for (int c = 0; c < nclients; c++) {
// The client's data submission is an arbitrary boolean vector.
for (int i=0; i < ndata; i++) {
for (int i = 0; i < ndata; i++) {
// Arbitrary data
data_items[i] = (i % 3 == 1) || (c % 5 == 3);
}
@ -101,25 +100,24 @@ verify_full (void)
//
// Construct the client data packets.
unsigned int aLen, bLen;
P_CHECKC (PrioClient_encode (cfg, data_items,
&for_server_a, &aLen, &for_server_b, &bLen));
P_CHECKC(PrioClient_encode(cfg, data_items, &for_server_a, &aLen,
&for_server_b, &bLen));
// The Prio servers A and B can come online later (e.g., at the end of
// each day) to download the encrypted telemetry packets from the
// telemetry server and run the protocol that computes the aggregate
// statistics. In this way, the client only needs to send a
// single message (the pair of encrypted ClientPacketData packets)
// statistics. In this way, the client only needs to send a
// single message (the pair of encrypted ClientPacketData packets)
// to a single server (the telemetry-data-collection server).
// THE CLIENT'S JOB IS DONE. The rest of the processing just takes place
// between the two servers A and B.
// II. VALIDATION PROTOCOL. (at servers)
//
// The servers now run a short 2-step protocol to check each
// The servers now run a short 2-step protocol to check each
// client's packet:
// 1) Servers A and B broadcast one message (PrioPacketVerify1)
// 1) Servers A and B broadcast one message (PrioPacketVerify1)
// to each other.
// 2) Servers A and B broadcast another message (PrioPacketVerify2)
// to each other.
@ -128,37 +126,37 @@ verify_full (void)
// running total of aggregate statistics) or ill-formed
// (in which case they ignore it).
// These messages must be sent over an authenticated channel, so
// that each server is assured that every received message came
// that each server is assured that every received message came
// from its peer.
// Set up a Prio verifier object.
P_CHECKC (PrioVerifier_set_data (vA, for_server_a, aLen));
P_CHECKC (PrioVerifier_set_data (vB, for_server_b, bLen));
P_CHECKC(PrioVerifier_set_data(vA, for_server_a, aLen));
P_CHECKC(PrioVerifier_set_data(vB, for_server_b, bLen));
// Both servers produce a packet1. Server A sends p1A to Server B
// and vice versa.
P_CHECKC (PrioPacketVerify1_set_data (p1A, vA));
P_CHECKC (PrioPacketVerify1_set_data (p1B, vB));
P_CHECKC(PrioPacketVerify1_set_data(p1A, vA));
P_CHECKC(PrioPacketVerify1_set_data(p1B, vB));
// Both servers produce a packet2. Server A sends p2A to Server B
// and vice versa.
P_CHECKC (PrioPacketVerify2_set_data(p2A, vA, p1A, p1B));
P_CHECKC (PrioPacketVerify2_set_data(p2B, vB, p1A, p1B));
P_CHECKC(PrioPacketVerify2_set_data(p2A, vA, p1A, p1B));
P_CHECKC(PrioPacketVerify2_set_data(p2B, vB, p1A, p1B));
// Using p2A and p2B, the servers can determine whether the request
// is valid. (In fact, only Server A needs to perform this
// check, since Server A can just tell Server B whether the check
// succeeded or failed.)
P_CHECKC (PrioVerifier_isValid (vA, p2A, p2B));
P_CHECKC (PrioVerifier_isValid (vB, p2A, p2B));
// is valid. (In fact, only Server A needs to perform this
// check, since Server A can just tell Server B whether the check
// succeeded or failed.)
P_CHECKC(PrioVerifier_isValid(vA, p2A, p2B));
P_CHECKC(PrioVerifier_isValid(vB, p2A, p2B));
// If we get here, the client packet is valid, so add it to the aggregate
// statistic counter for both servers.
P_CHECKC (PrioServer_aggregate (sA, vA));
P_CHECKC (PrioServer_aggregate (sB, vB));
P_CHECKC(PrioServer_aggregate(sA, vA));
P_CHECKC(PrioServer_aggregate(sB, vB));
free (for_server_a);
free (for_server_b);
free(for_server_a);
free(for_server_b);
for_server_a = NULL;
for_server_b = NULL;
}
@ -168,62 +166,63 @@ verify_full (void)
// III. PRODUCTION OF AGGREGATE STATISTICS.
//
// After collecting aggregates from MANY clients, the servers can compute
// their shares of the aggregate statistics.
// their shares of the aggregate statistics.
//
// Server B can send tB to Server A.
P_CHECKC (PrioTotalShare_set_data (tA, sA));
P_CHECKC (PrioTotalShare_set_data (tB, sB));
P_CHECKC(PrioTotalShare_set_data(tA, sA));
P_CHECKC(PrioTotalShare_set_data(tB, sB));
// Once Server A has tA and tB, it can learn the aggregate statistics
// in the clear.
unsigned long output[ndata];
P_CHECKC (PrioTotalShare_final (cfg, output, tA, tB));
P_CHECKC(PrioTotalShare_final(cfg, output, tA, tB));
// Now the output[i] contains a counter that indicates how many clients
// submitted TRUE for data value i. We print out this data.
for (int i=0; i < ndata; i++)
for (int i = 0; i < ndata; i++)
printf("output[%d] = %lu\n", i, output[i]);
}
cleanup:
if (rv != SECSuccess) {
fprintf (stderr, "Warning: unexpected failure.\n");
fprintf(stderr, "Warning: unexpected failure.\n");
}
if (for_server_a) free (for_server_a);
if (for_server_b) free (for_server_b);
if (for_server_a)
free(for_server_a);
if (for_server_b)
free(for_server_b);
PrioTotalShare_clear (tA);
PrioTotalShare_clear (tB);
PrioTotalShare_clear(tA);
PrioTotalShare_clear(tB);
PrioPacketVerify2_clear (p2A);
PrioPacketVerify2_clear (p2B);
PrioPacketVerify2_clear(p2A);
PrioPacketVerify2_clear(p2B);
PrioPacketVerify1_clear (p1A);
PrioPacketVerify1_clear (p1B);
PrioPacketVerify1_clear(p1A);
PrioPacketVerify1_clear(p1B);
PrioVerifier_clear (vA);
PrioVerifier_clear (vB);
PrioVerifier_clear(vA);
PrioVerifier_clear(vB);
PrioServer_clear (sA);
PrioServer_clear (sB);
PrioConfig_clear (cfg);
PrioServer_clear(sA);
PrioServer_clear(sB);
PrioConfig_clear(cfg);
PublicKey_clear (pkA);
PublicKey_clear (pkB);
PublicKey_clear(pkA);
PublicKey_clear(pkB);
PrivateKey_clear (skA);
PrivateKey_clear (skB);
PrivateKey_clear(skA);
PrivateKey_clear(skB);
Prio_clear ();
Prio_clear();
return !(rv == SECSuccess);
}
int
main (void)
int
main(void)
{
puts ("This utility demonstrates how to invoke the Prio API.");
return verify_full ();
puts("This utility demonstrates how to invoke the Prio API.");
return verify_full();
}

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

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@ -21,7 +21,7 @@
#include "util.h"
// Let the points of data_in be [x1, x2, x3, ... ].
// We construct the polynomial f such that
// We construct the polynomial f such that
// (a) f(0) = random,
// (b) f(i) = x_i for all i >= 1,
// (c) degree(f)+1 is a power of two.
@ -30,10 +30,10 @@
// and we return f(0) as `const_term`.
static SECStatus
data_polynomial_evals(const_PrioConfig cfg, const_MPArray data_in,
MPArray evals_out, mp_int *const_term)
MPArray evals_out, mp_int* const_term)
{
SECStatus rv = SECSuccess;
const mp_int *mod = &cfg->modulus;
const mp_int* mod = &cfg->modulus;
MPArray points_f = NULL;
MPArray poly_f = NULL;
@ -43,88 +43,87 @@ data_polynomial_evals(const_PrioConfig cfg, const_MPArray data_in,
// Little n is the number of points on the polynomials.
// The constant term is randomized, so it's (mul_gates + 1).
const int n = mul_gates + 1;
// Big N is n rounded up to a power of two.
const int N = next_power_of_two (n);
P_CHECKA (points_f = MPArray_new (N));
P_CHECKA (poly_f = MPArray_new (N));
// Big N is n rounded up to a power of two.
const int N = next_power_of_two(n);
P_CHECKA(points_f = MPArray_new(N));
P_CHECKA(poly_f = MPArray_new(N));
// Set constant term f(0) to random
P_CHECKC (rand_int (&points_f->data[0], mod));
MP_CHECKC (mp_copy (&points_f->data[0], const_term));
P_CHECKC(rand_int(&points_f->data[0], mod));
MP_CHECKC(mp_copy(&points_f->data[0], const_term));
// Set other values of f(x)
for (int i=1; i<n; i++) {
MP_CHECKC (mp_copy (&data_in->data[i-1], &points_f->data[i]));
for (int i = 1; i < n; i++) {
MP_CHECKC(mp_copy(&data_in->data[i - 1], &points_f->data[i]));
}
// Interpolate through the Nth roots of unity
P_CHECKC (poly_fft(poly_f, points_f, cfg, true));
P_CHECKC(poly_fft(poly_f, points_f, cfg, true));
// Evaluate at all 2N-th roots of unity.
// Evaluate at all 2N-th roots of unity.
// To do so, first resize the eval arrays and fill upper
// values with zeros.
P_CHECKC (MPArray_resize (poly_f, 2*N));
P_CHECKC (MPArray_resize (evals_out, 2*N));
P_CHECKC(MPArray_resize(poly_f, 2 * N));
P_CHECKC(MPArray_resize(evals_out, 2 * N));
// Evaluate at the 2N-th roots of unity
P_CHECKC (poly_fft(evals_out, poly_f, cfg, false));
P_CHECKC(poly_fft(evals_out, poly_f, cfg, false));
cleanup:
MPArray_clear (points_f);
MPArray_clear (poly_f);
MPArray_clear(points_f);
MPArray_clear(poly_f);
return rv;
}
static SECStatus
share_polynomials (const_PrioConfig cfg, const_MPArray data_in,
PrioPacketClient pA, PrioPacketClient pB, PRG prgB)
share_polynomials(const_PrioConfig cfg, const_MPArray data_in,
PrioPacketClient pA, PrioPacketClient pB, PRG prgB)
{
SECStatus rv = SECSuccess;
const mp_int *mod = &cfg->modulus;
const mp_int* mod = &cfg->modulus;
const_MPArray points_f = data_in;
mp_int f0, g0;
MP_DIGITS (&f0) = NULL;
MP_DIGITS (&g0) = NULL;
MP_DIGITS(&f0) = NULL;
MP_DIGITS(&g0) = NULL;
MPArray points_g = NULL;
MPArray evals_f_2N = NULL;
MPArray evals_g_2N = NULL;
P_CHECKA (points_g = MPArray_dup (points_f));
P_CHECKA (evals_f_2N = MPArray_new (0));
P_CHECKA (evals_g_2N = MPArray_new (0));
MP_CHECKC (mp_init (&f0));
MP_CHECKC (mp_init (&g0));
P_CHECKA(points_g = MPArray_dup(points_f));
P_CHECKA(evals_f_2N = MPArray_new(0));
P_CHECKA(evals_g_2N = MPArray_new(0));
MP_CHECKC(mp_init(&f0));
MP_CHECKC(mp_init(&g0));
for (int i=0; i<points_f->len; i++) {
for (int i = 0; i < points_f->len; i++) {
// For each input value x_i, we compute x_i * (x_i-1).
// f(i) = x_i
// g(i) = x_i - 1
MP_CHECKC (mp_sub_d (&points_g->data[i], 1, &points_g->data[i]));
MP_CHECKC (mp_mod (&points_g->data[i], mod, &points_g->data[i]));
MP_CHECKC(mp_sub_d(&points_g->data[i], 1, &points_g->data[i]));
MP_CHECKC(mp_mod(&points_g->data[i], mod, &points_g->data[i]));
}
P_CHECKC (data_polynomial_evals(cfg, points_f, evals_f_2N, &f0));
P_CHECKC (data_polynomial_evals(cfg, points_g, evals_g_2N, &g0));
P_CHECKC(data_polynomial_evals(cfg, points_f, evals_f_2N, &f0));
P_CHECKC(data_polynomial_evals(cfg, points_g, evals_g_2N, &g0));
// The values f(0) and g(0) are set to random values.
// We must send to each server a share of the points
// f(0), g(0), and h(0) = f(0)*g(0)
P_CHECKC (share_int (cfg, &f0, &pA->f0_share, &pB->f0_share));
P_CHECKC (share_int (cfg, &g0, &pA->g0_share, &pB->g0_share));
P_CHECKC(share_int(cfg, &f0, &pA->f0_share, &pB->f0_share));
P_CHECKC(share_int(cfg, &g0, &pA->g0_share, &pB->g0_share));
// Compute h(0) = f(0)*g(0).
MP_CHECKC (mp_mulmod (&f0, &g0, mod, &f0));
MP_CHECKC(mp_mulmod(&f0, &g0, mod, &f0));
// Give one share of h(0) to each server.
P_CHECKC (share_int (cfg, &f0, &pA->h0_share, &pB->h0_share));
P_CHECKC(share_int(cfg, &f0, &pA->h0_share, &pB->h0_share));
//const int lenN = (evals_f_2N->len/2);
//P_CHECKC (MPArray_resize (pA->shares.A.h_points, lenN));
// const int lenN = (evals_f_2N->len/2);
// P_CHECKC (MPArray_resize (pA->shares.A.h_points, lenN));
// We need to send to the servers the evaluations of
// f(r) * g(r)
@ -135,34 +134,35 @@ share_polynomials (const_PrioConfig cfg, const_MPArray data_in,
// send a share of this value to each server.
int j = 0;
for (int i = 1; i < evals_f_2N->len; i += 2) {
MP_CHECKC (mp_mulmod (&evals_f_2N->data[i], &evals_g_2N->data[i], mod, &f0));
P_CHECKC (PRG_share_int (prgB, &pA->shares.A.h_points->data[j], &f0, cfg));
MP_CHECKC(mp_mulmod(&evals_f_2N->data[i], &evals_g_2N->data[i], mod, &f0));
P_CHECKC(PRG_share_int(prgB, &pA->shares.A.h_points->data[j], &f0, cfg));
j++;
}
cleanup:
MPArray_clear (evals_f_2N);
MPArray_clear (evals_g_2N);
MPArray_clear (points_g);
mp_clear (&f0);
mp_clear (&g0);
MPArray_clear(evals_f_2N);
MPArray_clear(evals_g_2N);
MPArray_clear(points_g);
mp_clear(&f0);
mp_clear(&g0);
return rv;
}
PrioPacketClient
PrioPacketClient_new (const_PrioConfig cfg, PrioServerId for_server)
PrioPacketClient_new(const_PrioConfig cfg, PrioServerId for_server)
{
SECStatus rv = SECSuccess;
SECStatus rv = SECSuccess;
const int data_len = cfg->num_data_fields;
PrioPacketClient p = NULL;
p = malloc (sizeof (*p));
if (!p) return NULL;
p = malloc(sizeof(*p));
if (!p)
return NULL;
p->for_server = for_server;
p->triple = NULL;
MP_DIGITS (&p->f0_share) = NULL;
MP_DIGITS (&p->g0_share) = NULL;
MP_DIGITS (&p->h0_share) = NULL;
MP_DIGITS(&p->f0_share) = NULL;
MP_DIGITS(&p->g0_share) = NULL;
MP_DIGITS(&p->h0_share) = NULL;
switch (p->for_server) {
case PRIO_SERVER_A:
@ -170,7 +170,7 @@ PrioPacketClient_new (const_PrioConfig cfg, PrioServerId for_server)
p->shares.A.h_points = NULL;
break;
case PRIO_SERVER_B:
memset (p->shares.B.seed, 0, PRG_SEED_LENGTH);
memset(p->shares.B.seed, 0, PRG_SEED_LENGTH);
break;
default:
// Should never get here
@ -178,20 +178,20 @@ PrioPacketClient_new (const_PrioConfig cfg, PrioServerId for_server)
goto cleanup;
}
MP_CHECKC (mp_init (&p->f0_share));
MP_CHECKC (mp_init (&p->g0_share));
MP_CHECKC (mp_init (&p->h0_share));
P_CHECKA (p->triple = BeaverTriple_new ());
MP_CHECKC(mp_init(&p->f0_share));
MP_CHECKC(mp_init(&p->g0_share));
MP_CHECKC(mp_init(&p->h0_share));
P_CHECKA(p->triple = BeaverTriple_new());
if (p->for_server == PRIO_SERVER_A) {
const int num_h_points = PrioConfig_hPoints (cfg);
P_CHECKA (p->shares.A.data_shares = MPArray_new (data_len));
P_CHECKA (p->shares.A.h_points = MPArray_new (num_h_points));
const int num_h_points = PrioConfig_hPoints(cfg);
P_CHECKA(p->shares.A.data_shares = MPArray_new(data_len));
P_CHECKA(p->shares.A.h_points = MPArray_new(num_h_points));
}
cleanup:
if (rv != SECSuccess) {
PrioPacketClient_clear (p);
PrioPacketClient_clear(p);
return NULL;
}
@ -199,69 +199,74 @@ cleanup:
}
SECStatus
PrioPacketClient_set_data (const_PrioConfig cfg, const bool *data_in,
PrioPacketClient pA, PrioPacketClient pB)
PrioPacketClient_set_data(const_PrioConfig cfg, const bool* data_in,
PrioPacketClient pA, PrioPacketClient pB)
{
MPArray client_data = NULL;
PRG prgB = NULL;
SECStatus rv = SECSuccess;
const int data_len = cfg->num_data_fields;
if (!data_in) return SECFailure;
if (!data_in)
return SECFailure;
P_CHECKC (PrioPRGSeed_randomize (&pB->shares.B.seed));
P_CHECKA (prgB = PRG_new (pB->shares.B.seed));
P_CHECKC(PrioPRGSeed_randomize(&pB->shares.B.seed));
P_CHECKA(prgB = PRG_new(pB->shares.B.seed));
P_CHECKC (BeaverTriple_set_rand (cfg, pA->triple, pB->triple));
P_CHECKA (client_data = MPArray_new_bool (data_len, data_in));
P_CHECKC (PRG_share_array (prgB, pA->shares.A.data_shares,
client_data, cfg));
P_CHECKC (share_polynomials (cfg, client_data, pA, pB, prgB));
P_CHECKC(BeaverTriple_set_rand(cfg, pA->triple, pB->triple));
P_CHECKA(client_data = MPArray_new_bool(data_len, data_in));
P_CHECKC(PRG_share_array(prgB, pA->shares.A.data_shares, client_data, cfg));
P_CHECKC(share_polynomials(cfg, client_data, pA, pB, prgB));
cleanup:
MPArray_clear (client_data);
PRG_clear (prgB);
MPArray_clear(client_data);
PRG_clear(prgB);
return rv;
}
void
PrioPacketClient_clear (PrioPacketClient p)
PrioPacketClient_clear(PrioPacketClient p)
{
if (p == NULL) return;
if (p == NULL)
return;
if (p->for_server == PRIO_SERVER_A) {
MPArray_clear (p->shares.A.h_points);
MPArray_clear (p->shares.A.data_shares);
MPArray_clear(p->shares.A.h_points);
MPArray_clear(p->shares.A.data_shares);
}
BeaverTriple_clear (p->triple);
mp_clear (&p->f0_share);
mp_clear (&p->g0_share);
mp_clear (&p->h0_share);
free (p);
BeaverTriple_clear(p->triple);
mp_clear(&p->f0_share);
mp_clear(&p->g0_share);
mp_clear(&p->h0_share);
free(p);
}
bool
PrioPacketClient_areEqual (const_PrioPacketClient p1,
const_PrioPacketClient p2)
bool
PrioPacketClient_areEqual(const_PrioPacketClient p1, const_PrioPacketClient p2)
{
if (!BeaverTriple_areEqual (p1->triple, p2->triple)) return false;
if (mp_cmp (&p1->f0_share, &p2->f0_share)) return false;
if (mp_cmp (&p1->g0_share, &p2->g0_share)) return false;
if (mp_cmp (&p1->h0_share, &p2->h0_share)) return false;
if (p1->for_server != p2->for_server) return false;
if (!BeaverTriple_areEqual(p1->triple, p2->triple))
return false;
if (mp_cmp(&p1->f0_share, &p2->f0_share))
return false;
if (mp_cmp(&p1->g0_share, &p2->g0_share))
return false;
if (mp_cmp(&p1->h0_share, &p2->h0_share))
return false;
if (p1->for_server != p2->for_server)
return false;
switch (p1->for_server) {
case PRIO_SERVER_A:
if (!MPArray_areEqual (p1->shares.A.data_shares,
p2->shares.A.data_shares)) return false;
if (!MPArray_areEqual (p1->shares.A.h_points,
p2->shares.A.h_points)) return false;
break;
if (!MPArray_areEqual(p1->shares.A.data_shares, p2->shares.A.data_shares))
return false;
if (!MPArray_areEqual(p1->shares.A.h_points, p2->shares.A.h_points))
return false;
break;
case PRIO_SERVER_B:
if (memcmp (p1->shares.B.seed, p2->shares.B.seed,
PRG_SEED_LENGTH)) return false;
if (memcmp(p1->shares.B.seed, p2->shares.B.seed, PRG_SEED_LENGTH))
return false;
break;
default:
// Should never get here.
@ -271,83 +276,85 @@ PrioPacketClient_areEqual (const_PrioPacketClient p1,
return true;
}
SECStatus
PrioClient_encode (const_PrioConfig cfg, const bool *data_in,
unsigned char **for_server_a, unsigned int *aLen,
unsigned char **for_server_b, unsigned int *bLen)
SECStatus
PrioClient_encode(const_PrioConfig cfg, const bool* data_in,
unsigned char** for_server_a, unsigned int* aLen,
unsigned char** for_server_b, unsigned int* bLen)
{
SECStatus rv = SECSuccess;
PrioPacketClient pA = NULL;
PrioPacketClient pB = NULL;
*for_server_a = NULL;
*for_server_b = NULL;
P_CHECKA (pA = PrioPacketClient_new (cfg, PRIO_SERVER_A));
P_CHECKA (pB = PrioPacketClient_new (cfg, PRIO_SERVER_B));
P_CHECKA(pA = PrioPacketClient_new(cfg, PRIO_SERVER_A));
P_CHECKA(pB = PrioPacketClient_new(cfg, PRIO_SERVER_B));
msgpack_sbuffer sbufA, sbufB;
msgpack_packer packerA, packerB;
msgpack_sbuffer_init (&sbufA);
msgpack_sbuffer_init (&sbufB);
msgpack_packer_init (&packerA, &sbufA, msgpack_sbuffer_write);
msgpack_packer_init (&packerB, &sbufB, msgpack_sbuffer_write);
msgpack_sbuffer_init(&sbufA);
msgpack_sbuffer_init(&sbufB);
msgpack_packer_init(&packerA, &sbufA, msgpack_sbuffer_write);
msgpack_packer_init(&packerB, &sbufB, msgpack_sbuffer_write);
P_CHECKC (PrioPacketClient_set_data (cfg, data_in, pA, pB));
P_CHECKC (serial_write_packet_client (&packerA, pA, cfg));
P_CHECKC (serial_write_packet_client (&packerB, pB, cfg));
P_CHECKC(PrioPacketClient_set_data(cfg, data_in, pA, pB));
P_CHECKC(serial_write_packet_client(&packerA, pA, cfg));
P_CHECKC(serial_write_packet_client(&packerB, pB, cfg));
P_CHECKC (PublicKey_encryptSize (sbufA.size, aLen));
P_CHECKC (PublicKey_encryptSize (sbufB.size, bLen));
P_CHECKC(PublicKey_encryptSize(sbufA.size, aLen));
P_CHECKC(PublicKey_encryptSize(sbufB.size, bLen));
P_CHECKA (*for_server_a = malloc (*aLen));
P_CHECKA (*for_server_b = malloc (*bLen));
P_CHECKA(*for_server_a = malloc(*aLen));
P_CHECKA(*for_server_b = malloc(*bLen));
unsigned int writtenA;
unsigned int writtenB;
P_CHECKC (PublicKey_encrypt (cfg->server_a_pub, *for_server_a, &writtenA, *aLen,
(unsigned char *)sbufA.data, sbufA.size));
P_CHECKC (PublicKey_encrypt (cfg->server_b_pub, *for_server_b, &writtenB, *bLen,
(unsigned char *)sbufB.data, sbufB.size));
P_CHECKC(PublicKey_encrypt(cfg->server_a_pub, *for_server_a, &writtenA, *aLen,
(unsigned char*)sbufA.data, sbufA.size));
P_CHECKC(PublicKey_encrypt(cfg->server_b_pub, *for_server_b, &writtenB, *bLen,
(unsigned char*)sbufB.data, sbufB.size));
P_CHECKCB (writtenA == *aLen);
P_CHECKCB (writtenB == *bLen);
P_CHECKCB(writtenA == *aLen);
P_CHECKCB(writtenB == *bLen);
cleanup:
if (rv != SECSuccess) {
if (*for_server_a) free (*for_server_a);
if (*for_server_b) free (*for_server_b);
if (*for_server_a)
free(*for_server_a);
if (*for_server_b)
free(*for_server_b);
*for_server_a = NULL;
*for_server_b = NULL;
}
PrioPacketClient_clear (pA);
PrioPacketClient_clear (pB);
msgpack_sbuffer_destroy (&sbufA);
msgpack_sbuffer_destroy (&sbufB);
PrioPacketClient_clear(pA);
PrioPacketClient_clear(pB);
msgpack_sbuffer_destroy(&sbufA);
msgpack_sbuffer_destroy(&sbufB);
return rv;
}
SECStatus
PrioPacketClient_decrypt (PrioPacketClient p, const_PrioConfig cfg,
PrivateKey server_priv, const unsigned char *data_in, unsigned int data_len)
SECStatus
PrioPacketClient_decrypt(PrioPacketClient p, const_PrioConfig cfg,
PrivateKey server_priv, const unsigned char* data_in,
unsigned int data_len)
{
SECStatus rv = SECSuccess;
msgpack_unpacker upk;
P_CHECKCB (msgpack_unpacker_init (&upk, data_len));
P_CHECKCB(msgpack_unpacker_init(&upk, data_len));
// Decrypt the ciphertext into dec_buf
unsigned int bytes_decrypted;
P_CHECKC (PrivateKey_decrypt (server_priv,
(unsigned char *)msgpack_unpacker_buffer (&upk), &bytes_decrypted,
data_len, data_in, data_len));
msgpack_unpacker_buffer_consumed (&upk, bytes_decrypted);
P_CHECKC(PrivateKey_decrypt(server_priv,
(unsigned char*)msgpack_unpacker_buffer(&upk),
&bytes_decrypted, data_len, data_in, data_len));
msgpack_unpacker_buffer_consumed(&upk, bytes_decrypted);
P_CHECKC (serial_read_packet_client (&upk, p, cfg));
P_CHECKC(serial_read_packet_client(&upk, p, cfg));
cleanup:
msgpack_unpacker_destroy (&upk);
msgpack_unpacker_destroy(&upk);
return rv;
}

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

@ -1,9 +1,9 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef __CLIENT_H__
@ -13,23 +13,24 @@
#include "prg.h"
#include "share.h"
/*
* The PrioPacketClient object holds the encoded client data.
* The client sends one packet to server A and one packet to
* server B. The `for_server` parameter determines which server
* the packet is for.
*/
typedef struct prio_packet_client *PrioPacketClient;
typedef const struct prio_packet_client *const_PrioPacketClient;
typedef struct prio_packet_client* PrioPacketClient;
typedef const struct prio_packet_client* const_PrioPacketClient;
struct server_a_data {
struct server_a_data
{
// These values are only set for server A.
MPArray data_shares;
MPArray h_points;
};
struct server_b_data {
struct server_b_data
{
// This value is only used for server B.
//
// We use a pseudo-random generator to compress the secret-shared data
@ -39,9 +40,10 @@ struct server_b_data {
};
/*
* The data that a Prio client sends to each server.
* The data that a Prio client sends to each server.
*/
struct prio_packet_client {
struct prio_packet_client
{
// TODO: Can also use a PRG to avoid need for sending Beaver triple shares.
// Since this optimization only saves ~30 bytes of communication, we haven't
// bothered implementing it yet.
@ -50,25 +52,26 @@ struct prio_packet_client {
mp_int f0_share, g0_share, h0_share;
PrioServerId for_server;
union {
union
{
struct server_a_data A;
struct server_b_data B;
} shares;
};
PrioPacketClient PrioPacketClient_new(const_PrioConfig cfg,
PrioServerId for_server);
void PrioPacketClient_clear(PrioPacketClient p);
SECStatus PrioPacketClient_set_data(const_PrioConfig cfg, const bool* data_in,
PrioPacketClient for_server_a,
PrioPacketClient for_server_b);
PrioPacketClient PrioPacketClient_new (const_PrioConfig cfg, PrioServerId for_server);
void PrioPacketClient_clear (PrioPacketClient p);
SECStatus PrioPacketClient_set_data (const_PrioConfig cfg, const bool *data_in,
PrioPacketClient for_server_a, PrioPacketClient for_server_b);
SECStatus PrioPacketClient_decrypt (PrioPacketClient p,
const_PrioConfig cfg, PrivateKey server_priv,
const unsigned char *data_in, unsigned int data_len);
bool PrioPacketClient_areEqual (const_PrioPacketClient p1,
const_PrioPacketClient p2);
SECStatus PrioPacketClient_decrypt(PrioPacketClient p, const_PrioConfig cfg,
PrivateKey server_priv,
const unsigned char* data_in,
unsigned int data_len);
bool PrioPacketClient_areEqual(const_PrioPacketClient p1,
const_PrioPacketClient p2);
#endif /* __CLIENT_H__ */

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

@ -1,47 +1,47 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <mprio.h>
#include <stdlib.h>
#include "config.h"
#include "params.h"
#include "mparray.h"
#include "params.h"
#include "rand.h"
#include "util.h"
// The PrioConfig object stores "2^k-th roots of unity" modulo
// the prime modulus we use for all arithmetic. We use
// these roots to perform fast FFT-style polynomial
// the prime modulus we use for all arithmetic. We use
// these roots to perform fast FFT-style polynomial
// interpolation and evaluation.
//
// In particular, we use a prime modulus p such that
// In particular, we use a prime modulus p such that
// p = (2^k)q + 1.
// The roots are integers such that r^{2^k} = 1 mod p.
static SECStatus
initialize_roots (MPArray arr, const char *values[])
initialize_roots(MPArray arr, const char* values[])
{
// TODO: Read in only the number of roots of unity we need.
// Right now we read in all 4096 roots whether or not we use
// them all.
for (int i=0; i < arr->len; i++) {
MP_CHECK (mp_read_radix (&arr->data[i], values[i], 16));
for (int i = 0; i < arr->len; i++) {
MP_CHECK(mp_read_radix(&arr->data[i], values[i], 16));
}
return SECSuccess;
}
PrioConfig
PrioConfig_new (int n_fields, PublicKey server_a, PublicKey server_b,
const unsigned char *batch_id, unsigned int batch_id_len)
PrioConfig
PrioConfig_new(int n_fields, PublicKey server_a, PublicKey server_b,
const unsigned char* batch_id, unsigned int batch_id_len)
{
SECStatus rv = SECSuccess;
PrioConfig cfg = malloc (sizeof (*cfg));
PrioConfig cfg = malloc(sizeof(*cfg));
if (!cfg)
return NULL;
@ -61,72 +61,73 @@ PrioConfig_new (int n_fields, PublicKey server_a, PublicKey server_b,
goto cleanup;
}
P_CHECKA (cfg->batch_id = malloc (batch_id_len));
strncpy ((char *)cfg->batch_id, (char *)batch_id, batch_id_len);
P_CHECKA(cfg->batch_id = malloc(batch_id_len));
strncpy((char*)cfg->batch_id, (char*)batch_id, batch_id_len);
MP_CHECKC (mp_init (&cfg->modulus));
MP_CHECKC (mp_read_radix (&cfg->modulus, Modulus, 16));
MP_CHECKC(mp_init(&cfg->modulus));
MP_CHECKC(mp_read_radix(&cfg->modulus, Modulus, 16));
// Compute 2^{-1} modulo M
MP_CHECKC (mp_init (&cfg->inv2));
mp_set (&cfg->inv2, 2);
MP_CHECKC (mp_invmod (&cfg->inv2, &cfg->modulus, &cfg->inv2));
MP_CHECKC(mp_init(&cfg->inv2));
mp_set(&cfg->inv2, 2);
MP_CHECKC(mp_invmod(&cfg->inv2, &cfg->modulus, &cfg->inv2));
P_CHECKA (cfg->roots = MPArray_new (cfg->n_roots));
P_CHECKA (cfg->rootsInv = MPArray_new (cfg->n_roots));
MP_CHECKC (initialize_roots (cfg->roots, Roots));
MP_CHECKC (initialize_roots (cfg->rootsInv, RootsInv));
P_CHECKA(cfg->roots = MPArray_new(cfg->n_roots));
P_CHECKA(cfg->rootsInv = MPArray_new(cfg->n_roots));
MP_CHECKC(initialize_roots(cfg->roots, Roots));
MP_CHECKC(initialize_roots(cfg->rootsInv, RootsInv));
cleanup:
if (rv != SECSuccess) {
PrioConfig_clear (cfg);
PrioConfig_clear(cfg);
return NULL;
}
return cfg;
}
PrioConfig
PrioConfig_newTest (int nFields)
PrioConfig
PrioConfig_newTest(int nFields)
{
return PrioConfig_new (nFields, NULL, NULL,
(unsigned char *)"testBatch", 9);
}
void
PrioConfig_clear (PrioConfig cfg)
{
if (!cfg) return;
if (cfg->batch_id) free (cfg->batch_id);
MPArray_clear (cfg->roots);
MPArray_clear (cfg->rootsInv);
mp_clear (&cfg->modulus);
mp_clear (&cfg->inv2);
free (cfg);
}
int
PrioConfig_numDataFields (const_PrioConfig cfg)
{
return cfg->num_data_fields;
}
SECStatus
Prio_init (void)
{
return rand_init ();
return PrioConfig_new(nFields, NULL, NULL, (unsigned char*)"testBatch", 9);
}
void
Prio_clear (void)
PrioConfig_clear(PrioConfig cfg)
{
rand_clear ();
if (!cfg)
return;
if (cfg->batch_id)
free(cfg->batch_id);
MPArray_clear(cfg->roots);
MPArray_clear(cfg->rootsInv);
mp_clear(&cfg->modulus);
mp_clear(&cfg->inv2);
free(cfg);
}
int PrioConfig_hPoints (const_PrioConfig cfg)
int
PrioConfig_numDataFields(const_PrioConfig cfg)
{
return cfg->num_data_fields;
}
SECStatus
Prio_init(void)
{
return rand_init();
}
void
Prio_clear(void)
{
rand_clear();
}
int
PrioConfig_hPoints(const_PrioConfig cfg)
{
const int mul_gates = cfg->num_data_fields + 1;
const int N = next_power_of_two (mul_gates);
const int N = next_power_of_two(mul_gates);
return N;
}

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

@ -1,9 +1,9 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef __CONFIG_H__
@ -13,12 +13,12 @@
#include "mparray.h"
struct prio_config {
struct prio_config
{
int num_data_fields;
unsigned char *batch_id;
unsigned char* batch_id;
unsigned int batch_id_len;
PublicKey server_a_pub;
PublicKey server_b_pub;
@ -30,7 +30,6 @@ struct prio_config {
MPArray rootsInv;
};
int PrioConfig_hPoints (const_PrioConfig cfg);
int PrioConfig_hPoints(const_PrioConfig cfg);
#endif /* __CONFIG_H__ */

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

@ -1,9 +1,9 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef __DEBUG_H__
@ -12,10 +12,12 @@
#include <stdio.h>
#ifdef DEBUG
#define PRIO_DEBUG(msg) do { fprintf(stderr, "Error: %s\n", msg); } while(false);
#define PRIO_DEBUG(msg) \
do { \
fprintf(stderr, "Error: %s\n", msg); \
} while (false);
#else
#define PRIO_DEBUG(msg) ;
#endif
#endif /* __DEBUG_H__ */

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

@ -1,9 +1,9 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <nss/keyhi.h>
@ -24,31 +24,30 @@
#define GCM_TAG_LEN_BYTES 16
#define PRIO_TAG "PrioPacket"
#define AAD_LEN (strlen (PRIO_TAG) + CURVE25519_KEY_LEN + GCM_IV_LEN_BYTES)
#define AAD_LEN (strlen(PRIO_TAG) + CURVE25519_KEY_LEN + GCM_IV_LEN_BYTES)
// The all-zeros curve25519 public key, as DER-encoded SKPI blob.
static const uint8_t curve25519_spki_zeros[] = {
0x30, 0x39, 0x30, 0x14, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x09, 0x2b,
0x06, 0x01, 0x04, 0x01, 0xda, 0x47, 0x0f, 0x01, 0x03, 0x21,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00,
0x30, 0x39, 0x30, 0x14, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
0x01, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xda, 0x47, 0x0f, 0x01,
0x03, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
// Note that we do not use isxdigit because it is locale-dependent
// See: https://github.com/mozilla/libprio/issues/20
static inline char
is_hex_digit (char c)
is_hex_digit(char c)
{
return ('0' <= c && c <= '9') ||
('a' <= c && c <= 'f') ||
('A' <= c && c <= 'F');
return ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') ||
('A' <= c && c <= 'F');
}
// Note that we do not use toupper because it is locale-dependent
// See: https://github.com/mozilla/libprio/issues/20
static inline char
to_upper (char c)
to_upper(char c)
{
if (c >= 'a' && c <= 'z') {
return (c + 'A' - 'a');
@ -58,210 +57,218 @@ to_upper (char c)
}
static inline uint8_t
hex_to_int (char h)
hex_to_int(char h)
{
return (h > '9') ? to_upper (h) - 'A' + 10 : (h - '0');
return (h > '9') ? to_upper(h) - 'A' + 10 : (h - '0');
}
static inline unsigned char
int_to_hex (uint8_t i)
static inline unsigned char
int_to_hex(uint8_t i)
{
return (i > 0x09) ? ((i - 10) + 'A') : i + '0';
}
static SECStatus
derive_dh_secret (PK11SymKey **shared_secret, PrivateKey priv, PublicKey pub)
static SECStatus
derive_dh_secret(PK11SymKey** shared_secret, PrivateKey priv, PublicKey pub)
{
if (priv == NULL) return SECFailure;
if (pub == NULL) return SECFailure;
if (shared_secret == NULL) return SECFailure;
if (priv == NULL)
return SECFailure;
if (pub == NULL)
return SECFailure;
if (shared_secret == NULL)
return SECFailure;
SECStatus rv = SECSuccess;
*shared_secret = NULL;
P_CHECKA (*shared_secret = PK11_PubDeriveWithKDF (priv, pub, PR_FALSE,
NULL, NULL, CKM_ECDH1_DERIVE, CKM_AES_GCM,
CKA_ENCRYPT | CKA_DECRYPT, 16,
CKD_SHA256_KDF, NULL, NULL));
P_CHECKA(*shared_secret = PK11_PubDeriveWithKDF(
priv, pub, PR_FALSE, NULL, NULL, CKM_ECDH1_DERIVE, CKM_AES_GCM,
CKA_ENCRYPT | CKA_DECRYPT, 16, CKD_SHA256_KDF, NULL, NULL));
cleanup:
return rv;
}
SECStatus
PublicKey_import (PublicKey *pk, const unsigned char *data, unsigned int dataLen)
PublicKey_import(PublicKey* pk, const unsigned char* data, unsigned int dataLen)
{
SECStatus rv = SECSuccess;
CERTSubjectPublicKeyInfo *pkinfo = NULL;
CERTSubjectPublicKeyInfo* pkinfo = NULL;
*pk = NULL;
if (dataLen != CURVE25519_KEY_LEN)
return SECFailure;
unsigned char key_bytes[dataLen];
memcpy (key_bytes, data, dataLen);
memcpy(key_bytes, data, dataLen);
const int spki_len = sizeof (curve25519_spki_zeros);
const int spki_len = sizeof(curve25519_spki_zeros);
uint8_t spki_data[spki_len];
memcpy (spki_data, curve25519_spki_zeros, spki_len);
memcpy(spki_data, curve25519_spki_zeros, spki_len);
SECItem spki_item = { siBuffer, spki_data, spki_len };
// Import the all-zeros curve25519 public key.
P_CHECKA (pkinfo = SECKEY_DecodeDERSubjectPublicKeyInfo (&spki_item));
P_CHECKA (*pk = SECKEY_ExtractPublicKey (pkinfo));
// Import the all-zeros curve25519 public key.
P_CHECKA(pkinfo = SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item));
P_CHECKA(*pk = SECKEY_ExtractPublicKey(pkinfo));
// Overwrite the all-zeros public key with the 32-byte curve25519 public key
// given as input.
memcpy ((*pk)->u.ec.publicValue.data, data, CURVE25519_KEY_LEN);
memcpy((*pk)->u.ec.publicValue.data, data, CURVE25519_KEY_LEN);
cleanup:
if (pkinfo)
SECKEY_DestroySubjectPublicKeyInfo (pkinfo);
if (pkinfo)
SECKEY_DestroySubjectPublicKeyInfo(pkinfo);
if (rv != SECSuccess)
PublicKey_clear (*pk);
PublicKey_clear(*pk);
return rv;
}
SECStatus
PublicKey_import_hex (PublicKey *pk, const unsigned char *hex_data, unsigned int dataLen)
PublicKey_import_hex(PublicKey* pk, const unsigned char* hex_data,
unsigned int dataLen)
{
unsigned char raw_bytes[CURVE25519_KEY_LEN];
if (dataLen != CURVE25519_KEY_LEN_HEX)
return SECFailure;
for (unsigned int i=0; i<dataLen; i++) {
if (!is_hex_digit (hex_data[i]))
for (unsigned int i = 0; i < dataLen; i++) {
if (!is_hex_digit(hex_data[i]))
return SECFailure;
}
const unsigned char *p = hex_data;
for (unsigned int i=0; i<CURVE25519_KEY_LEN; i++) {
uint8_t d0 = hex_to_int (p[0]);
uint8_t d1 = hex_to_int (p[1]);
const unsigned char* p = hex_data;
for (unsigned int i = 0; i < CURVE25519_KEY_LEN; i++) {
uint8_t d0 = hex_to_int(p[0]);
uint8_t d1 = hex_to_int(p[1]);
raw_bytes[i] = (d0 << 4) | d1;
p += 2;
}
return PublicKey_import (pk, raw_bytes, CURVE25519_KEY_LEN);
return PublicKey_import(pk, raw_bytes, CURVE25519_KEY_LEN);
}
SECStatus
PublicKey_export (const_PublicKey pk, unsigned char data[CURVE25519_KEY_LEN])
SECStatus
PublicKey_export(const_PublicKey pk, unsigned char data[CURVE25519_KEY_LEN])
{
if (pk == NULL) return SECFailure;
if (pk == NULL)
return SECFailure;
memcpy (data, pk->u.ec.publicValue.data, CURVE25519_KEY_LEN);
memcpy(data, pk->u.ec.publicValue.data, CURVE25519_KEY_LEN);
return SECSuccess;
}
SECStatus
PublicKey_export_hex (const_PublicKey pk, unsigned char data[(2*CURVE25519_KEY_LEN)+1])
SECStatus
PublicKey_export_hex(const_PublicKey pk,
unsigned char data[(2 * CURVE25519_KEY_LEN) + 1])
{
unsigned char raw_data[CURVE25519_KEY_LEN];
if (PublicKey_export (pk, raw_data) != SECSuccess)
if (PublicKey_export(pk, raw_data) != SECSuccess)
return SECFailure;
const unsigned char *p = raw_data;
for (unsigned int i=0; i<CURVE25519_KEY_LEN; i++) {
const unsigned char* p = raw_data;
for (unsigned int i = 0; i < CURVE25519_KEY_LEN; i++) {
unsigned char bytel = p[0] & 0x0f;
unsigned char byteu = (p[0] & 0xf0) >> 4;
data[2*i] = int_to_hex (byteu);
data[2*i + 1] = int_to_hex (bytel);
data[2 * i] = int_to_hex(byteu);
data[2 * i + 1] = int_to_hex(bytel);
p++;
}
data[2*CURVE25519_KEY_LEN] = '\0';
data[2 * CURVE25519_KEY_LEN] = '\0';
return SECSuccess;
}
SECStatus
Keypair_new (PrivateKey *pvtkey, PublicKey *pubkey)
SECStatus
Keypair_new(PrivateKey* pvtkey, PublicKey* pubkey)
{
if (pvtkey == NULL) return SECFailure;
if (pubkey == NULL) return SECFailure;
if (pvtkey == NULL)
return SECFailure;
if (pubkey == NULL)
return SECFailure;
SECStatus rv = SECSuccess;
SECOidData *oid_data = NULL;
SECOidData* oid_data = NULL;
*pubkey = NULL;
*pvtkey = NULL;
SECKEYECParams ecp;
ecp.data = NULL;
PK11SlotInfo *slot = NULL;
PK11SlotInfo* slot = NULL;
P_CHECKA (oid_data = SECOID_FindOIDByTag (CURVE_OID_TAG));
P_CHECKA(oid_data = SECOID_FindOIDByTag(CURVE_OID_TAG));
const int oid_struct_len = 2 + oid_data->oid.len;
P_CHECKA (ecp.data = malloc (oid_struct_len));
P_CHECKA(ecp.data = malloc(oid_struct_len));
ecp.len = oid_struct_len;
ecp.type = siDEROID;
ecp.data[0] = SEC_ASN1_OBJECT_ID;
ecp.data[1] = oid_data->oid.len;
memcpy (&ecp.data[2], oid_data->oid.data, oid_data->oid.len);
memcpy(&ecp.data[2], oid_data->oid.data, oid_data->oid.len);
P_CHECKA (slot = PK11_GetInternalSlot ());
P_CHECKA (*pvtkey = PK11_GenerateKeyPair(slot, CKM_EC_KEY_PAIR_GEN, &ecp,
(SECKEYPublicKey **)pubkey, PR_FALSE, PR_FALSE, NULL));
PK11_FreeSlot (slot);
P_CHECKA(slot = PK11_GetInternalSlot());
P_CHECKA(*pvtkey = PK11_GenerateKeyPair(slot, CKM_EC_KEY_PAIR_GEN, &ecp,
(SECKEYPublicKey**)pubkey, PR_FALSE,
PR_FALSE, NULL));
PK11_FreeSlot(slot);
cleanup:
if (ecp.data)
free (ecp.data);
free(ecp.data);
if (rv != SECSuccess) {
PublicKey_clear (*pubkey);
PrivateKey_clear (*pvtkey);
PublicKey_clear(*pubkey);
PrivateKey_clear(*pvtkey);
}
return rv;
}
void
PublicKey_clear (PublicKey pubkey)
void
PublicKey_clear(PublicKey pubkey)
{
if (pubkey)
if (pubkey)
SECKEY_DestroyPublicKey(pubkey);
}
void
PrivateKey_clear (PrivateKey pvtkey)
void
PrivateKey_clear(PrivateKey pvtkey)
{
if (pvtkey)
SECKEY_DestroyPrivateKey(pvtkey);
if (pvtkey)
SECKEY_DestroyPrivateKey(pvtkey);
}
const SECItem *
PublicKey_toBytes (const_PublicKey pubkey)
const SECItem*
PublicKey_toBytes(const_PublicKey pubkey)
{
return &pubkey->u.ec.publicValue;
}
SECStatus
PublicKey_encryptSize (unsigned int inputLen, unsigned int *outputLen)
PublicKey_encryptSize(unsigned int inputLen, unsigned int* outputLen)
{
if (outputLen == NULL || inputLen >= MAX_ENCRYPT_LEN)
return SECFailure;
// public key, IV, tag, and input
*outputLen = CURVE25519_KEY_LEN + GCM_IV_LEN_BYTES + GCM_TAG_LEN_BYTES + inputLen;
*outputLen =
CURVE25519_KEY_LEN + GCM_IV_LEN_BYTES + GCM_TAG_LEN_BYTES + inputLen;
return SECSuccess;
}
static void
set_gcm_params (SECItem *paramItem, CK_GCM_PARAMS *param, unsigned char *nonce,
const_PublicKey pubkey, unsigned char *aadBuf)
static void
set_gcm_params(SECItem* paramItem, CK_GCM_PARAMS* param, unsigned char* nonce,
const_PublicKey pubkey, unsigned char* aadBuf)
{
int offset = 0;
memcpy (aadBuf, PRIO_TAG, strlen (PRIO_TAG));
offset += strlen (PRIO_TAG);
memcpy (aadBuf + offset, PublicKey_toBytes (pubkey)->data, CURVE25519_KEY_LEN);
memcpy(aadBuf, PRIO_TAG, strlen(PRIO_TAG));
offset += strlen(PRIO_TAG);
memcpy(aadBuf + offset, PublicKey_toBytes(pubkey)->data, CURVE25519_KEY_LEN);
offset += CURVE25519_KEY_LEN;
memcpy (aadBuf + offset, nonce, GCM_IV_LEN_BYTES);
memcpy(aadBuf + offset, nonce, GCM_IV_LEN_BYTES);
param->pIv = nonce;
param->ulIvLen = GCM_IV_LEN_BYTES;
param->pAAD = aadBuf;
@ -269,17 +276,14 @@ set_gcm_params (SECItem *paramItem, CK_GCM_PARAMS *param, unsigned char *nonce,
param->ulTagBits = GCM_TAG_LEN_BYTES * 8;
paramItem->type = siBuffer;
paramItem->data = (void *)param;
paramItem->len = sizeof (*param);
paramItem->data = (void*)param;
paramItem->len = sizeof(*param);
}
SECStatus
PublicKey_encrypt (PublicKey pubkey,
unsigned char *output,
unsigned int *outputLen,
unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen)
SECStatus
PublicKey_encrypt(PublicKey pubkey, unsigned char* output,
unsigned int* outputLen, unsigned int maxOutputLen,
const unsigned char* input, unsigned int inputLen)
{
if (pubkey == NULL)
return SECFailure;
@ -288,55 +292,53 @@ PublicKey_encrypt (PublicKey pubkey,
return SECFailure;
unsigned int needLen;
if (PublicKey_encryptSize (inputLen, &needLen) != SECSuccess)
if (PublicKey_encryptSize(inputLen, &needLen) != SECSuccess)
return SECFailure;
if (maxOutputLen < needLen)
if (maxOutputLen < needLen)
return SECFailure;
SECStatus rv = SECSuccess;
PublicKey eph_pub = NULL;
PrivateKey eph_priv = NULL;
PK11SymKey *aes_key = NULL;
PublicKey eph_pub = NULL;
PrivateKey eph_priv = NULL;
PK11SymKey* aes_key = NULL;
unsigned char nonce[GCM_IV_LEN_BYTES];
unsigned char aadBuf[AAD_LEN];
P_CHECKC (rand_bytes (nonce, GCM_IV_LEN_BYTES));
P_CHECKC(rand_bytes(nonce, GCM_IV_LEN_BYTES));
P_CHECKC (Keypair_new (&eph_priv, &eph_pub));
P_CHECKC (derive_dh_secret (&aes_key, eph_priv, pubkey));
P_CHECKC(Keypair_new(&eph_priv, &eph_pub));
P_CHECKC(derive_dh_secret(&aes_key, eph_priv, pubkey));
CK_GCM_PARAMS param;
SECItem paramItem;
set_gcm_params (&paramItem, &param, nonce, eph_pub, aadBuf);
set_gcm_params(&paramItem, &param, nonce, eph_pub, aadBuf);
const SECItem *pk = PublicKey_toBytes (eph_pub);
P_CHECKCB (pk->len == CURVE25519_KEY_LEN);
memcpy (output, pk->data, pk->len);
memcpy (output + CURVE25519_KEY_LEN, param.pIv, param.ulIvLen);
const SECItem* pk = PublicKey_toBytes(eph_pub);
P_CHECKCB(pk->len == CURVE25519_KEY_LEN);
memcpy(output, pk->data, pk->len);
memcpy(output + CURVE25519_KEY_LEN, param.pIv, param.ulIvLen);
const int offset = CURVE25519_KEY_LEN + param.ulIvLen;
P_CHECKC (PK11_Encrypt (aes_key, CKM_AES_GCM, &paramItem, output + offset,
outputLen, maxOutputLen - offset, input, inputLen));
P_CHECKC(PK11_Encrypt(aes_key, CKM_AES_GCM, &paramItem, output + offset,
outputLen, maxOutputLen - offset, input, inputLen));
*outputLen = *outputLen + CURVE25519_KEY_LEN + GCM_IV_LEN_BYTES;
cleanup:
PublicKey_clear (eph_pub);
PrivateKey_clear (eph_priv);
if (aes_key)
PK11_FreeSymKey (aes_key);
PublicKey_clear(eph_pub);
PrivateKey_clear(eph_priv);
if (aes_key)
PK11_FreeSymKey(aes_key);
return rv;
}
SECStatus
PrivateKey_decrypt (PrivateKey privkey,
unsigned char *output,
unsigned int *outputLen,
unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen)
SECStatus
PrivateKey_decrypt(PrivateKey privkey, unsigned char* output,
unsigned int* outputLen, unsigned int maxOutputLen,
const unsigned char* input, unsigned int inputLen)
{
PK11SymKey *aes_key = NULL;
PK11SymKey* aes_key = NULL;
PublicKey eph_pub = NULL;
unsigned char aad_buf[AAD_LEN];
@ -345,34 +347,33 @@ PrivateKey_decrypt (PrivateKey privkey,
SECStatus rv = SECSuccess;
unsigned int headerLen;
if (PublicKey_encryptSize (0, &headerLen) != SECSuccess)
if (PublicKey_encryptSize(0, &headerLen) != SECSuccess)
return SECFailure;
if (inputLen < headerLen)
if (inputLen < headerLen)
return SECFailure;
const unsigned int msglen = inputLen - headerLen;
if (maxOutputLen < msglen || msglen >= MAX_ENCRYPT_LEN)
return SECFailure;
P_CHECKC (PublicKey_import (&eph_pub, input, CURVE25519_KEY_LEN));
P_CHECKC(PublicKey_import(&eph_pub, input, CURVE25519_KEY_LEN));
unsigned char nonce[GCM_IV_LEN_BYTES];
memcpy (nonce, input + CURVE25519_KEY_LEN, GCM_IV_LEN_BYTES);
memcpy(nonce, input + CURVE25519_KEY_LEN, GCM_IV_LEN_BYTES);
SECItem paramItem;
CK_GCM_PARAMS param;
set_gcm_params (&paramItem, &param, nonce, eph_pub, aad_buf);
P_CHECKC (derive_dh_secret (&aes_key, privkey, eph_pub));
set_gcm_params(&paramItem, &param, nonce, eph_pub, aad_buf);
P_CHECKC(derive_dh_secret(&aes_key, privkey, eph_pub));
const int offset = CURVE25519_KEY_LEN + GCM_IV_LEN_BYTES;
P_CHECKC (PK11_Decrypt (aes_key, CKM_AES_GCM, &paramItem, output,
outputLen, maxOutputLen, input + offset, inputLen - offset));
P_CHECKC(PK11_Decrypt(aes_key, CKM_AES_GCM, &paramItem, output, outputLen,
maxOutputLen, input + offset, inputLen - offset));
cleanup:
PublicKey_clear (eph_pub);
if (aes_key)
PK11_FreeSymKey (aes_key);
PublicKey_clear(eph_pub);
if (aes_key)
PK11_FreeSymKey(aes_key);
return rv;
}

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

@ -1,12 +1,11 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef __ENCRYPT_H__
#define __ENCRYPT_H__
@ -15,7 +14,7 @@
/*******
* These functions attempt to implement CCA-secure public-key encryption using
* the NSS library. We use hashed-ElGamal encryption with Curve25519 as the
* the NSS library. We use hashed-ElGamal encryption with Curve25519 as the
* underlying group and AES128-GCM as the bulk encryption mode of operation.
*
* I make no guarantees that I am using NSS correctly or that this encryption
@ -25,7 +24,7 @@
* to implement these functions.
*/
/*
/*
* Messages encrypted using this library must be smaller than MAX_ENCRYPT_LEN.
* Enforcing this length limit helps avoid integer overflow.
*/
@ -38,12 +37,12 @@
* is too large (larger than `MAX_ENCRYPT_LEN`), this function returns
* an error.
*/
SECStatus PublicKey_encryptSize (unsigned int inputLen, unsigned int *outputLen);
SECStatus PublicKey_encryptSize(unsigned int inputLen, unsigned int* outputLen);
/*
* Generate a new keypair for public-key encryption.
*/
SECStatus Keypair_new (PrivateKey *pvtkey, PublicKey *pubkey);
SECStatus Keypair_new(PrivateKey* pvtkey, PublicKey* pubkey);
/*
* Encrypt an arbitrary bitstring to the specified public key. The buffer
@ -53,22 +52,17 @@ SECStatus Keypair_new (PrivateKey *pvtkey, PublicKey *pubkey);
*
* The value `inputLen` must be smaller than `MAX_ENCRYPT_LEN`.
*/
SECStatus PublicKey_encrypt (PublicKey pubkey,
unsigned char *output,
unsigned int *outputLen,
unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen);
SECStatus PublicKey_encrypt(PublicKey pubkey, unsigned char* output,
unsigned int* outputLen, unsigned int maxOutputLen,
const unsigned char* input, unsigned int inputLen);
/*
* Decrypt an arbitrary bitstring using the specified private key. The output
* buffer should be at least 16 bytes larger than the plaintext you expect. If
* `outputLen` >= `inputLen`, you should be safe.
*/
SECStatus PrivateKey_decrypt (PrivateKey privkey,
unsigned char *output,
unsigned int *outputLen,
unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen);
SECStatus PrivateKey_decrypt(PrivateKey privkey, unsigned char* output,
unsigned int* outputLen, unsigned int maxOutputLen,
const unsigned char* input, unsigned int inputLen);
#endif /* __ENCRYPT_H__ */

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

@ -1,9 +1,9 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <mprio.h>
@ -15,31 +15,31 @@
#include "util.h"
MPArray
MPArray_new (int len)
MPArray_new(int len)
{
SECStatus rv = SECSuccess;
MPArray arr = malloc (sizeof *arr);
if (!arr)
MPArray arr = malloc(sizeof *arr);
if (!arr)
return NULL;
arr->data = NULL;
arr->len = len;
P_CHECKA(arr->data = calloc (len, sizeof (mp_int)));
P_CHECKA(arr->data = calloc(len, sizeof(mp_int)));
// Initialize these to NULL so that we can figure
// out which allocations failed (if any)
for (int i=0; i<len; i++) {
MP_DIGITS (&arr->data[i]) = NULL;
for (int i = 0; i < len; i++) {
MP_DIGITS(&arr->data[i]) = NULL;
}
for (int i=0; i<len; i++) {
MP_CHECKC (mp_init(&arr->data[i]));
for (int i = 0; i < len; i++) {
MP_CHECKC(mp_init(&arr->data[i]));
}
cleanup:
if (rv != SECSuccess) {
MPArray_clear (arr);
MPArray_clear(arr);
return NULL;
}
@ -47,87 +47,89 @@ cleanup:
}
MPArray
MPArray_new_bool (int len, const bool *data_in)
MPArray_new_bool(int len, const bool* data_in)
{
MPArray arr = MPArray_new (len);
if (arr == NULL) return NULL;
MPArray arr = MPArray_new(len);
if (arr == NULL)
return NULL;
for (int i=0; i<len; i++) {
mp_set (&arr->data[i], data_in[i]);
for (int i = 0; i < len; i++) {
mp_set(&arr->data[i], data_in[i]);
}
return arr;
}
SECStatus
MPArray_resize (MPArray arr, int newlen)
MPArray_resize(MPArray arr, int newlen)
{
SECStatus rv = SECSuccess;
const int oldlen = arr->len;
if (oldlen == newlen)
return rv;
return rv;
// TODO: Use realloc for this?
mp_int *newdata = calloc (newlen, sizeof (mp_int));
mp_int* newdata = calloc(newlen, sizeof(mp_int));
if (newdata == NULL)
return SECFailure;
for (int i = 0; i < newlen; i++) {
MP_DIGITS (&newdata[i]) = NULL;
MP_DIGITS(&newdata[i]) = NULL;
}
// Initialize new array
for (int i = 0; i < newlen; i++) {
MP_CHECKC (mp_init (&newdata[i]));
MP_CHECKC(mp_init(&newdata[i]));
}
// Copy old data into new array
for (int i = 0; i < newlen && i < oldlen; i++) {
MP_CHECKC (mp_copy (&arr->data[i], &newdata[i]));
MP_CHECKC(mp_copy(&arr->data[i], &newdata[i]));
}
// Free old data
for (int i = 0; i < oldlen; i++) {
mp_clear (&arr->data[i]);
mp_clear(&arr->data[i]);
}
free (arr->data);
free(arr->data);
arr->data = newdata;
arr->len = newlen;
cleanup:
if (rv != SECSuccess) {
for (int i=0; i < newlen; i++) {
mp_clear (&newdata[i]);
for (int i = 0; i < newlen; i++) {
mp_clear(&newdata[i]);
}
free (newdata);
free(newdata);
}
return rv;
}
MPArray
MPArray_dup (const_MPArray src)
MPArray_dup(const_MPArray src)
{
MPArray dst = MPArray_new (src->len);
if (!dst) return NULL;
MPArray dst = MPArray_new(src->len);
if (!dst)
return NULL;
SECStatus rv = MPArray_copy (dst, src);
SECStatus rv = MPArray_copy(dst, src);
if (rv == SECSuccess) {
return dst;
} else {
MPArray_clear (dst);
MPArray_clear(dst);
return NULL;
}
}
SECStatus
MPArray_copy (MPArray dst, const_MPArray src)
MPArray_copy(MPArray dst, const_MPArray src)
{
if (dst->len != src->len)
return SECFailure;
for (int i=0; i<src->len; i++) {
for (int i = 0; i < src->len; i++) {
if (mp_copy(&src->data[i], &dst->data[i]) != MP_OKAY) {
return SECFailure;
}
@ -136,10 +138,9 @@ MPArray_copy (MPArray dst, const_MPArray src)
return SECSuccess;
}
SECStatus
MPArray_set_share (MPArray arrA, MPArray arrB,
const_MPArray src, const_PrioConfig cfg)
MPArray_set_share(MPArray arrA, MPArray arrB, const_MPArray src,
const_PrioConfig cfg)
{
SECStatus rv = SECSuccess;
if (arrA->len != src->len || arrB->len != src->len)
@ -147,48 +148,49 @@ MPArray_set_share (MPArray arrA, MPArray arrB,
const int len = src->len;
for (int i=0; i < len; i++) {
P_CHECK(share_int (cfg, &src->data[i], &arrA->data[i], &arrB->data[i]));
for (int i = 0; i < len; i++) {
P_CHECK(share_int(cfg, &src->data[i], &arrA->data[i], &arrB->data[i]));
}
return rv;
}
void
MPArray_clear (MPArray arr)
void
MPArray_clear(MPArray arr)
{
if (arr == NULL) return;
if (arr == NULL)
return;
if (arr->data != NULL) {
for (int i=0; i<arr->len; i++) {
for (int i = 0; i < arr->len; i++) {
mp_clear(&arr->data[i]);
}
free (arr->data);
free(arr->data);
}
free (arr);
free(arr);
}
SECStatus
MPArray_addmod (MPArray dst, const_MPArray to_add, const mp_int *mod)
MPArray_addmod(MPArray dst, const_MPArray to_add, const mp_int* mod)
{
if (dst->len != to_add->len)
return SECFailure;
for (int i=0; i<dst->len; i++) {
MP_CHECK (mp_addmod (&dst->data[i], &to_add->data[i], mod, &dst->data[i]));
for (int i = 0; i < dst->len; i++) {
MP_CHECK(mp_addmod(&dst->data[i], &to_add->data[i], mod, &dst->data[i]));
}
return SECSuccess;
}
bool
MPArray_areEqual (const_MPArray arr1, const_MPArray arr2)
bool
MPArray_areEqual(const_MPArray arr1, const_MPArray arr2)
{
if (arr1->len != arr2->len) return false;
if (arr1->len != arr2->len)
return false;
for (int i=0; i<arr1->len; i++) {
if (mp_cmp (&arr1->data[i], &arr2->data[i]))
for (int i = 0; i < arr1->len; i++) {
if (mp_cmp(&arr1->data[i], &arr2->data[i]))
return false;
}

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

@ -1,9 +1,9 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef __MPARRAY_H__
@ -12,60 +12,59 @@
#include <mpi.h>
#include <mprio.h>
struct mparray {
struct mparray
{
int len;
mp_int *data;
mp_int* data;
};
typedef struct mparray *MPArray;
typedef const struct mparray *const_MPArray;
typedef struct mparray* MPArray;
typedef const struct mparray* const_MPArray;
/*
* Initialize an array of `mp_int`s of the given length.
*/
MPArray MPArray_new (int len);
void MPArray_clear (MPArray arr);
MPArray MPArray_new(int len);
void MPArray_clear(MPArray arr);
/*
/*
* Copies secret sharing of data from src into arrays
* arrA and arrB. The lengths of the three input arrays
* must be identical.
*/
SECStatus MPArray_set_share (MPArray arrA, MPArray arrB,
const_MPArray src, const_PrioConfig cfg);
SECStatus MPArray_set_share(MPArray arrA, MPArray arrB, const_MPArray src,
const_PrioConfig cfg);
/*
/*
* Initializes array with 0/1 values specified in boolean array `data_in`
*/
MPArray MPArray_new_bool (int len, const bool *data_in);
MPArray MPArray_new_bool(int len, const bool* data_in);
/*
/*
* Expands or shrinks the MPArray to the desired size. If shrinking,
* will clear the values on the end of array.
*/
SECStatus MPArray_resize (MPArray arr, int newlen);
SECStatus MPArray_resize(MPArray arr, int newlen);
/*
* Initializes dst and creates a duplicate of the array in src.
* Initializes dst and creates a duplicate of the array in src.
*/
MPArray MPArray_dup (const_MPArray src);
MPArray MPArray_dup(const_MPArray src);
/*
* Copies array from src to dst. Arrays must have the same length.
*/
SECStatus MPArray_copy (MPArray dst, const_MPArray src);
SECStatus MPArray_copy(MPArray dst, const_MPArray src);
/* For each index i into the array, set:
* dst[i] = dst[i] + to_add[i] (modulo mod)
*/
SECStatus MPArray_addmod (MPArray dst, const_MPArray to_add,
const mp_int *mod);
SECStatus MPArray_addmod(MPArray dst, const_MPArray to_add, const mp_int* mod);
/*
* Return true iff the two arrays are equal in length
* and contents. This comparison is NOT constant time.
*/
bool MPArray_areEqual (const_MPArray arr1, const_MPArray arr2);
bool MPArray_areEqual(const_MPArray arr1, const_MPArray arr2);
#endif /* __MPARRAY_H__ */

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -1,9 +1,9 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <mprio.h>
@ -16,109 +16,110 @@
* A nice exposition of the recursive FFT/DFT algorithm we implement
* is in the book:
*
* "Modern Computer Algebra"
* by Von zur Gathen and Gerhard.
* "Modern Computer Algebra"
* by Von zur Gathen and Gerhard.
* Cambridge University Press, 2013.
*
* They present this algorithm as Algorithm 8.14.
*/
static SECStatus
fft_recurse (mp_int *out, const mp_int *mod, int n,
const mp_int *roots, const mp_int *ys,
mp_int *tmp, mp_int *ySub, mp_int *rootsSub)
fft_recurse(mp_int* out, const mp_int* mod, int n, const mp_int* roots,
const mp_int* ys, mp_int* tmp, mp_int* ySub, mp_int* rootsSub)
{
if (n == 1) {
MP_CHECK (mp_copy (&ys[0], &out[0]));
MP_CHECK(mp_copy(&ys[0], &out[0]));
return SECSuccess;
}
// Recurse on the first half
for (int i=0; i<n/2; i++) {
MP_CHECK (mp_addmod (&ys[i], &ys[i+(n/2)], mod, &ySub[i]));
MP_CHECK (mp_copy (&roots[2*i], &rootsSub[i]));
// Recurse on the first half
for (int i = 0; i < n / 2; i++) {
MP_CHECK(mp_addmod(&ys[i], &ys[i + (n / 2)], mod, &ySub[i]));
MP_CHECK(mp_copy(&roots[2 * i], &rootsSub[i]));
}
MP_CHECK (fft_recurse (tmp, mod, n/2, rootsSub, ySub, &tmp[n/2], &ySub[n/2], &rootsSub[n/2]));
for (int i=0; i<n/2; i++) {
MP_CHECK (mp_copy (&tmp[i], &out[2*i]));
MP_CHECK(fft_recurse(tmp, mod, n / 2, rootsSub, ySub, &tmp[n / 2],
&ySub[n / 2], &rootsSub[n / 2]));
for (int i = 0; i < n / 2; i++) {
MP_CHECK(mp_copy(&tmp[i], &out[2 * i]));
}
// Recurse on the second half
for (int i=0; i<n/2; i++) {
MP_CHECK (mp_submod (&ys[i], &ys[i+(n/2)], mod, &ySub[i]));
MP_CHECK (mp_mulmod (&ySub[i], &roots[i], mod, &ySub[i]));
// Recurse on the second half
for (int i = 0; i < n / 2; i++) {
MP_CHECK(mp_submod(&ys[i], &ys[i + (n / 2)], mod, &ySub[i]));
MP_CHECK(mp_mulmod(&ySub[i], &roots[i], mod, &ySub[i]));
}
MP_CHECK (fft_recurse (tmp, mod, n/2, rootsSub, ySub, &tmp[n/2], &ySub[n/2], &rootsSub[n/2]));
for (int i=0; i<n/2; i++) {
MP_CHECK (mp_copy (&tmp[i], &out[2*i + 1]));
MP_CHECK(fft_recurse(tmp, mod, n / 2, rootsSub, ySub, &tmp[n / 2],
&ySub[n / 2], &rootsSub[n / 2]));
for (int i = 0; i < n / 2; i++) {
MP_CHECK(mp_copy(&tmp[i], &out[2 * i + 1]));
}
return SECSuccess;
}
static SECStatus
fft_interpolate_raw (mp_int *out,
const mp_int *ys, int nPoints, const mp_int *roots,
const mp_int *mod, bool invert)
fft_interpolate_raw(mp_int* out, const mp_int* ys, int nPoints,
const mp_int* roots, const mp_int* mod, bool invert)
{
SECStatus rv = SECSuccess;
mp_int tmp[nPoints];
mp_int ySub[nPoints];
mp_int rootsSub[nPoints];
for (int i=0; i<nPoints;i++) {
MP_DIGITS (&tmp[i]) = NULL;
MP_DIGITS (&ySub[i]) = NULL;
MP_DIGITS (&rootsSub[i]) = NULL;
for (int i = 0; i < nPoints; i++) {
MP_DIGITS(&tmp[i]) = NULL;
MP_DIGITS(&ySub[i]) = NULL;
MP_DIGITS(&rootsSub[i]) = NULL;
}
mp_int n_inverse;
MP_DIGITS (&n_inverse) = NULL;
MP_DIGITS(&n_inverse) = NULL;
for (int i=0; i<nPoints;i++) {
MP_CHECKC (mp_init (&tmp[i]));
MP_CHECKC (mp_init (&ySub[i]));
MP_CHECKC (mp_init (&rootsSub[i]));
for (int i = 0; i < nPoints; i++) {
MP_CHECKC(mp_init(&tmp[i]));
MP_CHECKC(mp_init(&ySub[i]));
MP_CHECKC(mp_init(&rootsSub[i]));
}
MP_CHECK (fft_recurse(out, mod, nPoints, roots, ys, tmp, ySub, rootsSub));
MP_CHECK(fft_recurse(out, mod, nPoints, roots, ys, tmp, ySub, rootsSub));
if (invert) {
MP_CHECKC (mp_init (&n_inverse));
MP_CHECKC(mp_init(&n_inverse));
mp_set (&n_inverse, nPoints);
MP_CHECKC (mp_invmod (&n_inverse, mod, &n_inverse));
for (int i=0; i<nPoints;i++) {
MP_CHECKC (mp_mulmod(&out[i], &n_inverse, mod, &out[i]));
mp_set(&n_inverse, nPoints);
MP_CHECKC(mp_invmod(&n_inverse, mod, &n_inverse));
for (int i = 0; i < nPoints; i++) {
MP_CHECKC(mp_mulmod(&out[i], &n_inverse, mod, &out[i]));
}
}
cleanup:
mp_clear (&n_inverse);
for (int i=0; i<nPoints;i++) {
mp_clear(&n_inverse);
for (int i = 0; i < nPoints; i++) {
mp_clear(&tmp[i]);
mp_clear(&ySub[i]);
mp_clear(&rootsSub[i]);
}
return rv;
}
}
/*
* The PrioConfig object has a list of N-th roots of unity for large N.
* This routine returns the n-th roots of unity for n < N, where n is
* This routine returns the n-th roots of unity for n < N, where n is
* a power of two. If the `invert` flag is set, it returns the inverses
* of the n-th roots of unity.
*/
SECStatus
poly_fft_get_roots (mp_int *roots_out, int n_points, const_PrioConfig cfg, bool invert)
poly_fft_get_roots(mp_int* roots_out, int n_points, const_PrioConfig cfg,
bool invert)
{
if (n_points > cfg->n_roots)
if (n_points > cfg->n_roots)
return SECFailure;
const mp_int *roots_in = invert ? cfg->rootsInv->data : cfg->roots->data;
const mp_int* roots_in = invert ? cfg->rootsInv->data : cfg->roots->data;
const int step_size = cfg->n_roots / n_points;
for (int i=0; i < n_points; i++) {
for (int i = 0; i < n_points; i++) {
roots_out[i] = roots_in[i * step_size];
}
@ -126,63 +127,62 @@ poly_fft_get_roots (mp_int *roots_out, int n_points, const_PrioConfig cfg, bool
}
SECStatus
poly_fft (MPArray points_out, const_MPArray points_in,
const_PrioConfig cfg, bool invert)
poly_fft(MPArray points_out, const_MPArray points_in, const_PrioConfig cfg,
bool invert)
{
SECStatus rv = SECSuccess;
const int n_points = points_in->len;
if (points_out->len != points_in->len)
return SECFailure;
if (n_points > cfg->n_roots)
if (n_points > cfg->n_roots)
return SECFailure;
if (cfg->n_roots % n_points != 0)
if (cfg->n_roots % n_points != 0)
return SECFailure;
mp_int scaled_roots[n_points];
P_CHECK (poly_fft_get_roots (scaled_roots, n_points, cfg, invert));
P_CHECK(poly_fft_get_roots(scaled_roots, n_points, cfg, invert));
MP_CHECK (fft_interpolate_raw (points_out->data, points_in->data, n_points,
scaled_roots, &cfg->modulus, invert));
MP_CHECK(fft_interpolate_raw(points_out->data, points_in->data, n_points,
scaled_roots, &cfg->modulus, invert));
return SECSuccess;
}
SECStatus
poly_eval (mp_int *value, const_MPArray coeffs, const mp_int *eval_at,
const_PrioConfig cfg)
{
SECStatus
poly_eval(mp_int* value, const_MPArray coeffs, const mp_int* eval_at,
const_PrioConfig cfg)
{
SECStatus rv = SECSuccess;
const int n = coeffs->len;
// Use Horner's method to evaluate the polynomial at the point
// `eval_at`
mp_copy (&coeffs->data[n-1], value);
for (int i=n-2; i >= 0; i--) {
MP_CHECK (mp_mulmod (value, eval_at, &cfg->modulus, value));
MP_CHECK (mp_addmod (value, &coeffs->data[i], &cfg->modulus, value));
mp_copy(&coeffs->data[n - 1], value);
for (int i = n - 2; i >= 0; i--) {
MP_CHECK(mp_mulmod(value, eval_at, &cfg->modulus, value));
MP_CHECK(mp_addmod(value, &coeffs->data[i], &cfg->modulus, value));
}
return rv;
}
SECStatus
poly_interp_evaluate (mp_int *value, const_MPArray poly_points,
const mp_int *eval_at, const_PrioConfig cfg)
poly_interp_evaluate(mp_int* value, const_MPArray poly_points,
const mp_int* eval_at, const_PrioConfig cfg)
{
SECStatus rv;
MPArray coeffs = NULL;
const int N = poly_points->len;
mp_int roots[N];
P_CHECKA (coeffs = MPArray_new (N));
P_CHECKC (poly_fft_get_roots (roots, N, cfg, false));
P_CHECKA(coeffs = MPArray_new(N));
P_CHECKC(poly_fft_get_roots(roots, N, cfg, false));
// Interpolate polynomial through roots of unity
P_CHECKC (poly_fft (coeffs, poly_points, cfg, true))
P_CHECKC (poly_eval (value, coeffs, eval_at, cfg));
P_CHECKC(poly_fft(coeffs, poly_points, cfg, true))
P_CHECKC(poly_eval(value, coeffs, eval_at, cfg));
cleanup:
MPArray_clear (coeffs);
MPArray_clear(coeffs);
return rv;
}

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

@ -1,9 +1,9 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef _FFT__H
@ -21,39 +21,36 @@
* of two and must be no longer than the number of precomputed
* roots in the PrioConfig object passed in.
*/
SECStatus poly_fft(MPArray points_out, const_MPArray points_in,
const_PrioConfig cfg, bool invert);
SECStatus poly_fft(MPArray points_out, const_MPArray points_in,
const_PrioConfig cfg, bool invert);
/*
/*
* Get an array
* (r^0, r^1, r^2, ... )
* (r^0, r^1, r^2, ... )
* where r is an n-th root of unity, for n a power of two
* less than cfg->n_roots.
*
* Do NOT mp_clear() the mp_ints stored in roots_out.
* Do NOT mp_clear() the mp_ints stored in roots_out.
* These are owned by the PrioConfig object.
*/
SECStatus poly_fft_get_roots (mp_int *roots_out, int n_points,
const_PrioConfig cfg, bool invert);
SECStatus poly_fft_get_roots(mp_int* roots_out, int n_points,
const_PrioConfig cfg, bool invert);
/*
* Evaluate the polynomial specified by the coefficients
* at the point `eval_at` and return the result as `value`.
*/
SECStatus poly_eval (mp_int *value, const_MPArray coeffs,
const mp_int *eval_at, const_PrioConfig cfg);
SECStatus poly_eval(mp_int* value, const_MPArray coeffs, const mp_int* eval_at,
const_PrioConfig cfg);
/*
* Interpolate the polynomial through the points
* Interpolate the polynomial through the points
* (x_1, y_1), ..., (x_N, y_N),
* where x_i is an N-th root of unity and the y_i values are
* specified by `poly_points`. Evaluate the resulting polynomial
* specified by `poly_points`. Evaluate the resulting polynomial
* at the point `eval_at`. Return the result as `value`.
*/
SECStatus poly_interp_evaluate (mp_int *value, const_MPArray poly_points,
const mp_int *eval_at, const_PrioConfig cfg);
SECStatus poly_interp_evaluate(mp_int* value, const_MPArray poly_points,
const mp_int* eval_at, const_PrioConfig cfg);
#endif

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

@ -1,9 +1,9 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <mprio.h>
@ -16,23 +16,25 @@
#include "share.h"
#include "util.h"
struct prg {
PK11SlotInfo *slot;
PK11SymKey *key;
PK11Context *ctx;
struct prg
{
PK11SlotInfo* slot;
PK11SymKey* key;
PK11Context* ctx;
};
SECStatus
PrioPRGSeed_randomize (PrioPRGSeed *key)
SECStatus
PrioPRGSeed_randomize(PrioPRGSeed* key)
{
return rand_bytes ((unsigned char *)key, PRG_SEED_LENGTH);
return rand_bytes((unsigned char*)key, PRG_SEED_LENGTH);
}
PRG
PRG_new (const PrioPRGSeed key_in)
PRG
PRG_new(const PrioPRGSeed key_in)
{
PRG prg = malloc (sizeof (struct prg));
if (!prg) return NULL;
PRG prg = malloc(sizeof(struct prg));
if (!prg)
return NULL;
prg->slot = NULL;
prg->key = NULL;
prg->ctx = NULL;
@ -40,106 +42,104 @@ PRG_new (const PrioPRGSeed key_in)
SECStatus rv = SECSuccess;
const CK_MECHANISM_TYPE cipher = CKM_AES_CTR;
P_CHECKA (prg->slot = PK11_GetInternalSlot ());
P_CHECKA(prg->slot = PK11_GetInternalSlot());
// Create a mutable copy of the key.
PrioPRGSeed key_mut;
memcpy (key_mut, key_in, PRG_SEED_LENGTH);
memcpy(key_mut, key_in, PRG_SEED_LENGTH);
SECItem keyItem = {siBuffer, key_mut, PRG_SEED_LENGTH};
SECItem keyItem = { siBuffer, key_mut, PRG_SEED_LENGTH };
// The IV can be all zeros since we only encrypt once with
// each AES key.
CK_AES_CTR_PARAMS param = {128, {}};
SECItem paramItem = {siBuffer, (void *)&param, sizeof(CK_AES_CTR_PARAMS)};
CK_AES_CTR_PARAMS param = { 128, {} };
SECItem paramItem = { siBuffer, (void*)&param, sizeof(CK_AES_CTR_PARAMS) };
P_CHECKA (prg->key = PK11_ImportSymKey (prg->slot, cipher, PK11_OriginUnwrap,
CKA_ENCRYPT, &keyItem, NULL));
P_CHECKA(prg->key = PK11_ImportSymKey(prg->slot, cipher, PK11_OriginUnwrap,
CKA_ENCRYPT, &keyItem, NULL));
P_CHECKA (prg->ctx = PK11_CreateContextBySymKey(cipher, CKA_ENCRYPT,
prg->key, &paramItem));
P_CHECKA(prg->ctx = PK11_CreateContextBySymKey(cipher, CKA_ENCRYPT, prg->key,
&paramItem));
cleanup:
if (rv != SECSuccess) {
PRG_clear (prg);
PRG_clear(prg);
prg = NULL;
}
return prg;
}
void
PRG_clear (PRG prg)
void
PRG_clear(PRG prg)
{
if (!prg) return;
if (!prg)
return;
if (prg->key)
PK11_FreeSymKey (prg->key);
PK11_FreeSymKey(prg->key);
if (prg->slot)
PK11_FreeSlot (prg->slot);
PK11_FreeSlot(prg->slot);
if (prg->ctx)
PK11_DestroyContext (prg->ctx, PR_TRUE);
PK11_DestroyContext(prg->ctx, PR_TRUE);
free (prg);
free(prg);
}
static SECStatus
PRG_get_bytes_internal (void *prg_vp, unsigned char *bytes, size_t len)
static SECStatus
PRG_get_bytes_internal(void* prg_vp, unsigned char* bytes, size_t len)
{
PRG prg = (PRG)prg_vp;
unsigned char in[len];
memset (in, 0, len);
memset(in, 0, len);
int outlen;
SECStatus rv = PK11_CipherOp (prg->ctx, bytes, &outlen, len, in, len);
return (rv != SECSuccess || (size_t)outlen != len) ? SECFailure: SECSuccess;
}
SECStatus
PRG_get_bytes (PRG prg, unsigned char *bytes, size_t len)
{
return PRG_get_bytes_internal ((void *)prg, bytes, len);
}
SECStatus
PRG_get_int (PRG prg, mp_int *out, const mp_int *max)
{
return rand_int_rng (out, max, &PRG_get_bytes_internal, (void *)prg);
SECStatus rv = PK11_CipherOp(prg->ctx, bytes, &outlen, len, in, len);
return (rv != SECSuccess || (size_t)outlen != len) ? SECFailure : SECSuccess;
}
SECStatus
PRG_get_array (PRG prg, MPArray dst, const mp_int *mod)
PRG_get_bytes(PRG prg, unsigned char* bytes, size_t len)
{
return PRG_get_bytes_internal((void*)prg, bytes, len);
}
SECStatus
PRG_get_int(PRG prg, mp_int* out, const mp_int* max)
{
return rand_int_rng(out, max, &PRG_get_bytes_internal, (void*)prg);
}
SECStatus
PRG_get_array(PRG prg, MPArray dst, const mp_int* mod)
{
SECStatus rv;
for (int i=0; i<dst->len; i++) {
P_CHECK (PRG_get_int (prg, &dst->data[i], mod));
for (int i = 0; i < dst->len; i++) {
P_CHECK(PRG_get_int(prg, &dst->data[i], mod));
}
return SECSuccess;
}
SECStatus
PRG_share_int (PRG prgB, mp_int *shareA, const mp_int *src, const_PrioConfig cfg)
PRG_share_int(PRG prgB, mp_int* shareA, const mp_int* src, const_PrioConfig cfg)
{
SECStatus rv = SECSuccess;
mp_int tmp;
MP_DIGITS (&tmp) = NULL;
MP_DIGITS(&tmp) = NULL;
MP_CHECKC (mp_init (&tmp));
P_CHECKC (PRG_get_int (prgB, &tmp, &cfg->modulus));
MP_CHECKC (mp_submod (src, &tmp, &cfg->modulus, shareA));
MP_CHECKC(mp_init(&tmp));
P_CHECKC(PRG_get_int(prgB, &tmp, &cfg->modulus));
MP_CHECKC(mp_submod(src, &tmp, &cfg->modulus, shareA));
cleanup:
mp_clear (&tmp);
mp_clear(&tmp);
return rv;
}
SECStatus
PRG_share_array (PRG prgB, MPArray arrA,
const_MPArray src, const_PrioConfig cfg)
SECStatus
PRG_share_array(PRG prgB, MPArray arrA, const_MPArray src, const_PrioConfig cfg)
{
SECStatus rv = SECSuccess;
if (arrA->len != src->len)
@ -147,10 +147,9 @@ PRG_share_array (PRG prgB, MPArray arrA,
const int len = src->len;
for (int i=0; i < len; i++) {
P_CHECK(PRG_share_int (prgB, &arrA->data[i], &src->data[i], cfg));
for (int i = 0; i < len; i++) {
P_CHECK(PRG_share_int(prgB, &arrA->data[i], &src->data[i], cfg));
}
return rv;
}

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

@ -1,9 +1,9 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef __PRG_H__
@ -15,48 +15,46 @@
#include "config.h"
typedef struct prg *PRG;
typedef const struct prg *const_PRG;
typedef struct prg* PRG;
typedef const struct prg* const_PRG;
/*
/*
* Initialize or destroy a pseudo-random generator.
*/
PRG PRG_new (const PrioPRGSeed key);
void PRG_clear (PRG prg);
PRG PRG_new(const PrioPRGSeed key);
void PRG_clear(PRG prg);
/*
/*
* Produce the next bytes of output from the PRG.
*/
SECStatus PRG_get_bytes (PRG prg, unsigned char *bytes, size_t len);
SECStatus PRG_get_bytes(PRG prg, unsigned char* bytes, size_t len);
/*
* Use the PRG output to sample a big integer x in the range
* 0 <= x < max.
*/
SECStatus PRG_get_int (PRG prg, mp_int *out, const mp_int *max);
SECStatus PRG_get_int(PRG prg, mp_int* out, const mp_int* max);
/*
* Use secret sharing to split the int src into two shares.
* Use PRG to generate the value `shareB`.
* The mp_ints must be initialized.
*/
SECStatus PRG_share_int (PRG prg, mp_int *shareA, const mp_int *src,
const_PrioConfig cfg);
SECStatus PRG_share_int(PRG prg, mp_int* shareA, const mp_int* src,
const_PrioConfig cfg);
/*
/*
* Set each item in the array to a pseudorandom value in the range
* [0, mod), where the values are generated using the PRG.
*/
SECStatus PRG_get_array (PRG prg, MPArray arr, const mp_int *mod);
SECStatus PRG_get_array(PRG prg, MPArray arr, const mp_int* mod);
/*
/*
* Secret shares the array in `src` into `arrA` using randomness
* provided by `prgB`. The arrays `src` and `arrA` must be the same
* length.
*/
SECStatus PRG_share_array (PRG prgB, MPArray arrA,
const_MPArray src, const_PrioConfig cfg);
SECStatus PRG_share_array(PRG prgB, MPArray arrA, const_MPArray src,
const_PrioConfig cfg);
#endif /* __PRG_H__ */

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

@ -1,16 +1,16 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <limits.h>
#include <mprio.h>
#include <nspr/prinit.h>
#include <nss/nss.h>
#include <nss/pk11pub.h>
#include <nspr/prinit.h>
#include "debug.h"
#include "rand.h"
@ -18,44 +18,41 @@
#define CHUNK_SIZE 8192
static NSSInitContext *prioGlobalContext = NULL;
static NSSInitContext* prioGlobalContext = NULL;
SECStatus
rand_init (void)
rand_init(void)
{
if (prioGlobalContext)
if (prioGlobalContext)
return SECSuccess;
prioGlobalContext = NSS_InitContext ("", "", "", "", NULL,
NSS_INIT_READONLY |
NSS_INIT_NOCERTDB |
NSS_INIT_NOMODDB |
NSS_INIT_FORCEOPEN |
NSS_INIT_NOROOTINIT);
prioGlobalContext =
NSS_InitContext("", "", "", "", NULL,
NSS_INIT_READONLY | NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB |
NSS_INIT_FORCEOPEN | NSS_INIT_NOROOTINIT);
return (prioGlobalContext != NULL) ? SECSuccess : SECFailure;
}
static SECStatus
rand_bytes_internal (void *user_data, unsigned char *out, size_t n_bytes)
static SECStatus
rand_bytes_internal(void* user_data, unsigned char* out, size_t n_bytes)
{
// No pointer should ever be passed in.
if (user_data != NULL)
return SECFailure;
if (!NSS_IsInitialized ()) {
PRIO_DEBUG ("NSS not initialized. Call rand_init() first.");
if (!NSS_IsInitialized()) {
PRIO_DEBUG("NSS not initialized. Call rand_init() first.");
return SECFailure;
}
SECStatus rv = SECFailure;
int to_go = n_bytes;
unsigned char *cp = out;
unsigned char* cp = out;
while (to_go) {
int to_gen = MIN (CHUNK_SIZE, to_go);
if ((rv = PK11_GenerateRandom (cp, to_gen)) != SECSuccess)
{
PRIO_DEBUG ("Error calling PK11_GenerateRandom");
int to_gen = MIN(CHUNK_SIZE, to_go);
if ((rv = PK11_GenerateRandom(cp, to_gen)) != SECSuccess) {
PRIO_DEBUG("Error calling PK11_GenerateRandom");
return SECFailure;
}
@ -66,67 +63,67 @@ rand_bytes_internal (void *user_data, unsigned char *out, size_t n_bytes)
return rv;
}
SECStatus
rand_bytes (unsigned char *out, size_t n_bytes)
SECStatus
rand_bytes(unsigned char* out, size_t n_bytes)
{
return rand_bytes_internal (NULL, out, n_bytes);
return rand_bytes_internal(NULL, out, n_bytes);
}
SECStatus
rand_int (mp_int *out, const mp_int *max)
rand_int(mp_int* out, const mp_int* max)
{
return rand_int_rng (out, max, &rand_bytes_internal, NULL);
return rand_int_rng(out, max, &rand_bytes_internal, NULL);
}
SECStatus
rand_int_rng (mp_int *out, const mp_int *max,
RandBytesFunc rng_func, void *user_data)
rand_int_rng(mp_int* out, const mp_int* max, RandBytesFunc rng_func,
void* user_data)
{
SECStatus rv = SECSuccess;
// Ensure max value is > 0
if (mp_cmp_z (max) == 0)
if (mp_cmp_z(max) == 0)
return SECFailure;
// Compute max-1, which tells us the largest
// value we will ever need to generate.
MP_CHECK (mp_sub_d (max, 1, out));
MP_CHECK(mp_sub_d(max, 1, out));
const int nbytes = mp_unsigned_octet_size (out);
const int nbytes = mp_unsigned_octet_size(out);
// Figure out how many MSBs we need to get in the
// most-significant byte.
// Figure out how many MSBs we need to get in the
// most-significant byte.
unsigned char max_bytes[nbytes];
MP_CHECK (mp_to_fixlen_octets (out, max_bytes, nbytes));
const unsigned char mask = msb_mask (max_bytes[0]);
MP_CHECK(mp_to_fixlen_octets(out, max_bytes, nbytes));
const unsigned char mask = msb_mask(max_bytes[0]);
// Buffer to store the pseudo-random bytes
unsigned char buf[nbytes];
do {
// Use rejection sampling to find a value strictly less than max.
P_CHECK (rng_func (user_data, buf, nbytes));
P_CHECK(rng_func(user_data, buf, nbytes));
// Mask off high-order bits that we will never need.
P_CHECK (rng_func (user_data, &buf[0], 1));
if (mask) buf[0] &= mask;
P_CHECK(rng_func(user_data, &buf[0], 1));
if (mask)
buf[0] &= mask;
MP_CHECK (mp_read_unsigned_octets (out, buf, nbytes));
} while (mp_cmp (out, max) != -1);
MP_CHECK(mp_read_unsigned_octets(out, buf, nbytes));
} while (mp_cmp(out, max) != -1);
return 0;
}
void
rand_clear (void)
rand_clear(void)
{
if (prioGlobalContext) {
NSS_ShutdownContext (prioGlobalContext);
NSS_ShutdownContext(prioGlobalContext);
#ifdef DO_PR_CLEANUP
PR_Cleanup ();
#endif
PR_Cleanup();
#endif
}
prioGlobalContext = NULL;
}

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

@ -1,9 +1,9 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef __RAND_H__
@ -17,27 +17,28 @@
* Typedef for function pointer. A function pointer of type RandBytesFunc
* points to a function that fills the buffer `out` of with `len` random bytes.
*/
typedef SECStatus (*RandBytesFunc) (void *user_data, unsigned char *out, size_t len);
typedef SECStatus (*RandBytesFunc)(void* user_data, unsigned char* out,
size_t len);
/*
/*
* Initialize or cleanup the global random number generator
* state that NSS uses.
*/
SECStatus rand_init (void);
void rand_clear (void);
SECStatus rand_init(void);
void rand_clear(void);
/*
/*
* Generate the specified number of random bytes using the
* NSS random number generator.
*/
SECStatus rand_bytes (unsigned char *out, size_t n_bytes);
*/
SECStatus rand_bytes(unsigned char* out, size_t n_bytes);
/*
* Generate a random number x such that
* 0 <= x < max
* using the NSS random number generator.
*/
SECStatus rand_int (mp_int *out, const mp_int *max);
SECStatus rand_int(mp_int* out, const mp_int* max);
/*
* Generate a random number x such that
@ -47,8 +48,7 @@ SECStatus rand_int (mp_int *out, const mp_int *max);
* The pointer user_data is passed to RandBytesFung `rng` as a first
* argument.
*/
SECStatus rand_int_rng (mp_int *out, const mp_int *max,
RandBytesFunc rng, void *user_data);
SECStatus rand_int_rng(mp_int* out, const mp_int* max, RandBytesFunc rng,
void* user_data);
#endif /* __RAND_H__ */

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

@ -1,9 +1,9 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <mprio.h>
@ -17,277 +17,277 @@
#define MSGPACK_OK 0
static SECStatus
serial_write_mp_int (msgpack_packer *pk, const mp_int *n)
static SECStatus
serial_write_mp_int(msgpack_packer* pk, const mp_int* n)
{
SECStatus rv = SECSuccess;
unsigned int n_size = mp_unsigned_octet_size (n);
unsigned int n_size = mp_unsigned_octet_size(n);
unsigned char data[n_size];
MP_CHECK (mp_to_fixlen_octets (n, data, n_size));
MP_CHECK(mp_to_fixlen_octets(n, data, n_size));
P_CHECK (msgpack_pack_str (pk, n_size));
P_CHECK (msgpack_pack_str_body (pk, data, n_size));
P_CHECK(msgpack_pack_str(pk, n_size));
P_CHECK(msgpack_pack_str_body(pk, data, n_size));
return rv;
}
static SECStatus
object_to_mp_int (msgpack_object *obj, mp_int *n, const mp_int *max)
object_to_mp_int(msgpack_object* obj, mp_int* n, const mp_int* max)
{
SECStatus rv = SECSuccess;
P_CHECKCB (obj != NULL);
P_CHECKCB (obj->type == MSGPACK_OBJECT_STR);
P_CHECKCB (n != NULL);
P_CHECKCB(obj != NULL);
P_CHECKCB(obj->type == MSGPACK_OBJECT_STR);
P_CHECKCB(n != NULL);
msgpack_object_str s = obj->via.str;
P_CHECKCB (s.ptr != NULL);
MP_CHECKC (mp_read_unsigned_octets (n, (unsigned char *)s.ptr, s.size));
P_CHECKCB(s.ptr != NULL);
MP_CHECKC(mp_read_unsigned_octets(n, (unsigned char*)s.ptr, s.size));
P_CHECKCB (mp_cmp_z (n) >= 0);
P_CHECKCB (mp_cmp (n, max) < 0);
P_CHECKCB(mp_cmp_z(n) >= 0);
P_CHECKCB(mp_cmp(n, max) < 0);
cleanup:
return rv;
}
static SECStatus
serial_read_mp_int (msgpack_unpacker *upk, mp_int *n, const mp_int *max)
static SECStatus
serial_read_mp_int(msgpack_unpacker* upk, mp_int* n, const mp_int* max)
{
SECStatus rv = SECSuccess;
P_CHECKCB (upk != NULL);
P_CHECKCB (n != NULL);
P_CHECKCB (max != NULL);
P_CHECKCB(upk != NULL);
P_CHECKCB(n != NULL);
P_CHECKCB(max != NULL);
msgpack_unpacked res;
msgpack_unpacked_init (&res);
UP_CHECK (msgpack_unpacker_next (upk, &res))
msgpack_unpacked_init(&res);
UP_CHECK(msgpack_unpacker_next(upk, &res))
msgpack_object obj = res.data;
P_CHECKC (object_to_mp_int (&obj, n, max));
P_CHECKC(object_to_mp_int(&obj, n, max));
cleanup:
msgpack_unpacked_destroy (&res);
msgpack_unpacked_destroy(&res);
return rv;
}
static SECStatus
serial_read_int (msgpack_unpacker *upk, int *n)
static SECStatus
serial_read_int(msgpack_unpacker* upk, int* n)
{
SECStatus rv = SECSuccess;
P_CHECKCB (upk != NULL);
P_CHECKCB (n != NULL);
P_CHECKCB(upk != NULL);
P_CHECKCB(n != NULL);
msgpack_unpacked res;
msgpack_unpacked_init (&res);
UP_CHECK (msgpack_unpacker_next (upk, &res))
msgpack_unpacked_init(&res);
UP_CHECK(msgpack_unpacker_next(upk, &res))
msgpack_object obj = res.data;
P_CHECKCB (obj.type == MSGPACK_OBJECT_POSITIVE_INTEGER);
P_CHECKCB(obj.type == MSGPACK_OBJECT_POSITIVE_INTEGER);
*n = obj.via.i64;
cleanup:
msgpack_unpacked_destroy (&res);
msgpack_unpacked_destroy(&res);
return rv;
}
static SECStatus
serial_write_mp_array (msgpack_packer *pk, const_MPArray arr)
static SECStatus
serial_write_mp_array(msgpack_packer* pk, const_MPArray arr)
{
SECStatus rv = SECSuccess;
P_CHECKCB (pk != NULL);
P_CHECKCB (arr != NULL);
P_CHECKCB(pk != NULL);
P_CHECKCB(arr != NULL);
P_CHECK (msgpack_pack_array (pk, arr->len));
P_CHECK(msgpack_pack_array(pk, arr->len));
for (int i = 0; i < arr->len; i++) {
P_CHECK (serial_write_mp_int (pk, &arr->data[i]));
P_CHECK(serial_write_mp_int(pk, &arr->data[i]));
}
cleanup:
return rv;
}
static SECStatus
serial_read_mp_array (msgpack_unpacker *upk, MPArray arr, size_t len, const mp_int
*max)
static SECStatus
serial_read_mp_array(msgpack_unpacker* upk, MPArray arr, size_t len,
const mp_int* max)
{
SECStatus rv = SECSuccess;
P_CHECKCB (upk != NULL);
P_CHECKCB (arr != NULL);
P_CHECKCB (max != NULL);
P_CHECKCB(upk != NULL);
P_CHECKCB(arr != NULL);
P_CHECKCB(max != NULL);
msgpack_unpacked res;
msgpack_unpacked_init (&res);
UP_CHECK (msgpack_unpacker_next (upk, &res))
msgpack_unpacked_init(&res);
UP_CHECK(msgpack_unpacker_next(upk, &res))
msgpack_object obj = res.data;
P_CHECKCB (obj.type == MSGPACK_OBJECT_ARRAY);
P_CHECKCB(obj.type == MSGPACK_OBJECT_ARRAY);
msgpack_object_array objarr = obj.via.array;
P_CHECKCB (objarr.size == len);
P_CHECKCB(objarr.size == len);
P_CHECKC (MPArray_resize (arr, len));
for (unsigned int i=0; i<len; i++) {
P_CHECKC (object_to_mp_int (&objarr.ptr[i], &arr->data[i], max));
P_CHECKC(MPArray_resize(arr, len));
for (unsigned int i = 0; i < len; i++) {
P_CHECKC(object_to_mp_int(&objarr.ptr[i], &arr->data[i], max));
}
cleanup:
msgpack_unpacked_destroy (&res);
msgpack_unpacked_destroy(&res);
return rv;
}
static SECStatus
serial_write_beaver_triple (msgpack_packer *pk, const_BeaverTriple t)
static SECStatus
serial_write_beaver_triple(msgpack_packer* pk, const_BeaverTriple t)
{
SECStatus rv = SECSuccess;
P_CHECKCB (pk != NULL);
P_CHECKCB (t != NULL);
P_CHECKCB(pk != NULL);
P_CHECKCB(t != NULL);
P_CHECK (serial_write_mp_int (pk, &t->a));
P_CHECK (serial_write_mp_int (pk, &t->b));
P_CHECK (serial_write_mp_int (pk, &t->c));
P_CHECK(serial_write_mp_int(pk, &t->a));
P_CHECK(serial_write_mp_int(pk, &t->b));
P_CHECK(serial_write_mp_int(pk, &t->c));
cleanup:
return rv;
}
static SECStatus
serial_read_beaver_triple (msgpack_unpacker *pk, BeaverTriple t, const mp_int *max)
static SECStatus
serial_read_beaver_triple(msgpack_unpacker* pk, BeaverTriple t,
const mp_int* max)
{
SECStatus rv = SECSuccess;
P_CHECKCB (pk != NULL);
P_CHECKCB (t != NULL);
P_CHECKCB (max != NULL);
P_CHECKCB(pk != NULL);
P_CHECKCB(t != NULL);
P_CHECKCB(max != NULL);
P_CHECK (serial_read_mp_int (pk, &t->a, max));
P_CHECK (serial_read_mp_int (pk, &t->b, max));
P_CHECK (serial_read_mp_int (pk, &t->c, max));
P_CHECK(serial_read_mp_int(pk, &t->a, max));
P_CHECK(serial_read_mp_int(pk, &t->b, max));
P_CHECK(serial_read_mp_int(pk, &t->c, max));
cleanup:
return rv;
}
static SECStatus
serial_write_server_a_data (msgpack_packer *pk, const struct server_a_data *A)
static SECStatus
serial_write_server_a_data(msgpack_packer* pk, const struct server_a_data* A)
{
SECStatus rv = SECSuccess;
P_CHECKCB (pk != NULL);
P_CHECKCB (A != NULL);
P_CHECKCB(pk != NULL);
P_CHECKCB(A != NULL);
P_CHECK (serial_write_mp_array (pk, A->data_shares));
P_CHECK (serial_write_mp_array (pk, A->h_points));
P_CHECK(serial_write_mp_array(pk, A->data_shares));
P_CHECK(serial_write_mp_array(pk, A->h_points));
cleanup:
return rv;
}
static SECStatus
serial_read_server_a_data (msgpack_unpacker *upk, struct server_a_data *A,
const_PrioConfig cfg)
static SECStatus
serial_read_server_a_data(msgpack_unpacker* upk, struct server_a_data* A,
const_PrioConfig cfg)
{
SECStatus rv = SECSuccess;
P_CHECKCB (upk != NULL);
P_CHECKCB (A != NULL);
P_CHECKCB(upk != NULL);
P_CHECKCB(A != NULL);
P_CHECK (serial_read_mp_array (upk, A->data_shares, cfg->num_data_fields,
&cfg->modulus));
P_CHECK (serial_read_mp_array (upk, A->h_points, PrioConfig_hPoints (cfg),
&cfg->modulus));
P_CHECK(serial_read_mp_array(upk, A->data_shares, cfg->num_data_fields,
&cfg->modulus));
P_CHECK(serial_read_mp_array(upk, A->h_points, PrioConfig_hPoints(cfg),
&cfg->modulus));
cleanup:
return rv;
}
static SECStatus
serial_write_prg_seed (msgpack_packer *pk, const PrioPRGSeed *seed)
static SECStatus
serial_write_prg_seed(msgpack_packer* pk, const PrioPRGSeed* seed)
{
SECStatus rv = SECSuccess;
P_CHECKCB (pk != NULL);
P_CHECKCB (seed != NULL);
P_CHECKCB(pk != NULL);
P_CHECKCB(seed != NULL);
P_CHECK (msgpack_pack_str (pk, PRG_SEED_LENGTH));
P_CHECK (msgpack_pack_str_body (pk, seed, PRG_SEED_LENGTH));
P_CHECK(msgpack_pack_str(pk, PRG_SEED_LENGTH));
P_CHECK(msgpack_pack_str_body(pk, seed, PRG_SEED_LENGTH));
cleanup:
return rv;
}
static SECStatus
serial_read_prg_seed (msgpack_unpacker *upk, PrioPRGSeed *seed)
static SECStatus
serial_read_prg_seed(msgpack_unpacker* upk, PrioPRGSeed* seed)
{
SECStatus rv = SECSuccess;
P_CHECKCB (upk != NULL);
P_CHECKCB (seed != NULL);
P_CHECKCB(upk != NULL);
P_CHECKCB(seed != NULL);
msgpack_unpacked res;
msgpack_unpacked_init (&res);
UP_CHECK (msgpack_unpacker_next (upk, &res))
msgpack_unpacked_init(&res);
UP_CHECK(msgpack_unpacker_next(upk, &res))
msgpack_object obj = res.data;
P_CHECKCB (obj.type == MSGPACK_OBJECT_STR);
P_CHECKCB(obj.type == MSGPACK_OBJECT_STR);
msgpack_object_str s = obj.via.str;
P_CHECKCB (s.size == PRG_SEED_LENGTH);
memcpy (seed, s.ptr, PRG_SEED_LENGTH);
P_CHECKCB(s.size == PRG_SEED_LENGTH);
memcpy(seed, s.ptr, PRG_SEED_LENGTH);
cleanup:
msgpack_unpacked_destroy (&res);
msgpack_unpacked_destroy(&res);
return rv;
}
static SECStatus
serial_write_server_b_data (msgpack_packer *pk, const struct server_b_data *B)
static SECStatus
serial_write_server_b_data(msgpack_packer* pk, const struct server_b_data* B)
{
SECStatus rv = SECSuccess;
P_CHECKCB (pk != NULL);
P_CHECKCB (B != NULL);
P_CHECKCB(pk != NULL);
P_CHECKCB(B != NULL);
rv = serial_write_prg_seed (pk, &B->seed);
rv = serial_write_prg_seed(pk, &B->seed);
cleanup:
return rv;
}
static SECStatus
serial_read_server_b_data (msgpack_unpacker *upk, struct server_b_data *B)
static SECStatus
serial_read_server_b_data(msgpack_unpacker* upk, struct server_b_data* B)
{
SECStatus rv = SECSuccess;
P_CHECKCB (upk != NULL);
P_CHECKCB (B != NULL);
rv =serial_read_prg_seed (upk, &B->seed);
P_CHECKCB(upk != NULL);
P_CHECKCB(B != NULL);
rv = serial_read_prg_seed(upk, &B->seed);
cleanup:
return rv;
}
SECStatus
serial_write_packet_client (msgpack_packer *pk, const_PrioPacketClient p,
const_PrioConfig cfg)
SECStatus
serial_write_packet_client(msgpack_packer* pk, const_PrioPacketClient p,
const_PrioConfig cfg)
{
SECStatus rv = SECSuccess;
P_CHECKCB (pk != NULL);
P_CHECKCB (p != NULL);
P_CHECKCB(pk != NULL);
P_CHECKCB(p != NULL);
P_CHECK (msgpack_pack_str (pk, cfg->batch_id_len));
P_CHECK (msgpack_pack_str_body (pk, cfg->batch_id, cfg->batch_id_len));
P_CHECK(msgpack_pack_str(pk, cfg->batch_id_len));
P_CHECK(msgpack_pack_str_body(pk, cfg->batch_id, cfg->batch_id_len));
P_CHECK (serial_write_beaver_triple (pk, p->triple));
P_CHECK(serial_write_beaver_triple(pk, p->triple));
P_CHECK (serial_write_mp_int (pk, &p->f0_share));
P_CHECK (serial_write_mp_int (pk, &p->g0_share));
P_CHECK (serial_write_mp_int (pk, &p->h0_share));
P_CHECK(serial_write_mp_int(pk, &p->f0_share));
P_CHECK(serial_write_mp_int(pk, &p->g0_share));
P_CHECK(serial_write_mp_int(pk, &p->h0_share));
P_CHECK (msgpack_pack_int (pk, p->for_server));
P_CHECK(msgpack_pack_int(pk, p->for_server));
switch (p->for_server) {
case PRIO_SERVER_A:
P_CHECK (serial_write_server_a_data (pk, &p->shares.A));
P_CHECK(serial_write_server_a_data(pk, &p->shares.A));
break;
case PRIO_SERVER_B:
P_CHECK (serial_write_server_b_data (pk, &p->shares.B));
P_CHECK(serial_write_server_b_data(pk, &p->shares.B));
break;
default:
return SECFailure;
@ -297,146 +297,144 @@ cleanup:
return rv;
}
SECStatus
serial_read_server_id (msgpack_unpacker *upk, PrioServerId *s)
SECStatus
serial_read_server_id(msgpack_unpacker* upk, PrioServerId* s)
{
SECStatus rv = SECSuccess;
P_CHECKCB (upk != NULL);
P_CHECKCB (s != NULL);
P_CHECKCB(upk != NULL);
P_CHECKCB(s != NULL);
int serv;
P_CHECK (serial_read_int (upk, &serv));
P_CHECKCB (serv == PRIO_SERVER_A || serv == PRIO_SERVER_B);
P_CHECK(serial_read_int(upk, &serv));
P_CHECKCB(serv == PRIO_SERVER_A || serv == PRIO_SERVER_B);
*s = serv;
cleanup:
return rv;
}
SECStatus
serial_read_packet_client (msgpack_unpacker *upk, PrioPacketClient p,
const_PrioConfig cfg)
SECStatus
serial_read_packet_client(msgpack_unpacker* upk, PrioPacketClient p,
const_PrioConfig cfg)
{
SECStatus rv = SECSuccess;
P_CHECKCB (upk != NULL);
P_CHECKCB (p != NULL);
P_CHECKCB(upk != NULL);
P_CHECKCB(p != NULL);
msgpack_unpacked res;
msgpack_unpacked_init (&res);
UP_CHECK (msgpack_unpacker_next (upk, &res))
msgpack_unpacked_init(&res);
UP_CHECK(msgpack_unpacker_next(upk, &res))
msgpack_object obj = res.data;
P_CHECKCB (obj.type == MSGPACK_OBJECT_STR);
P_CHECKCB(obj.type == MSGPACK_OBJECT_STR);
msgpack_object_str s = obj.via.str;
P_CHECKCB (s.size == cfg->batch_id_len);
P_CHECKCB (!memcmp (s.ptr, (char *)cfg->batch_id, cfg->batch_id_len));
P_CHECKCB(s.size == cfg->batch_id_len);
P_CHECKCB(!memcmp(s.ptr, (char*)cfg->batch_id, cfg->batch_id_len));
P_CHECK (serial_read_beaver_triple (upk, p->triple, &cfg->modulus));
P_CHECK(serial_read_beaver_triple(upk, p->triple, &cfg->modulus));
P_CHECK (serial_read_mp_int (upk, &p->f0_share, &cfg->modulus));
P_CHECK (serial_read_mp_int (upk, &p->g0_share, &cfg->modulus));
P_CHECK (serial_read_mp_int (upk, &p->h0_share, &cfg->modulus));
P_CHECK(serial_read_mp_int(upk, &p->f0_share, &cfg->modulus));
P_CHECK(serial_read_mp_int(upk, &p->g0_share, &cfg->modulus));
P_CHECK(serial_read_mp_int(upk, &p->h0_share, &cfg->modulus));
P_CHECK (serial_read_server_id (upk, &p->for_server));
P_CHECK(serial_read_server_id(upk, &p->for_server));
switch (p->for_server) {
case PRIO_SERVER_A:
P_CHECK (serial_read_server_a_data (upk, &p->shares.A, cfg));
P_CHECK(serial_read_server_a_data(upk, &p->shares.A, cfg));
break;
case PRIO_SERVER_B:
P_CHECK (serial_read_server_b_data (upk, &p->shares.B));
P_CHECK(serial_read_server_b_data(upk, &p->shares.B));
break;
default:
return SECFailure;
}
cleanup:
msgpack_unpacked_destroy (&res);
msgpack_unpacked_destroy(&res);
return rv;
}
SECStatus
PrioPacketVerify1_write (const_PrioPacketVerify1 p, msgpack_packer *pk)
SECStatus
PrioPacketVerify1_write(const_PrioPacketVerify1 p, msgpack_packer* pk)
{
SECStatus rv = SECSuccess;
P_CHECKCB (pk != NULL);
P_CHECKCB (p != NULL);
P_CHECKCB(pk != NULL);
P_CHECKCB(p != NULL);
P_CHECK (serial_write_mp_int (pk, &p->share_d));
P_CHECK (serial_write_mp_int (pk, &p->share_e));
P_CHECK(serial_write_mp_int(pk, &p->share_d));
P_CHECK(serial_write_mp_int(pk, &p->share_e));
cleanup:
return rv;
}
SECStatus
PrioPacketVerify1_read (PrioPacketVerify1 p, msgpack_unpacker *upk,
const_PrioConfig cfg)
SECStatus
PrioPacketVerify1_read(PrioPacketVerify1 p, msgpack_unpacker* upk,
const_PrioConfig cfg)
{
SECStatus rv = SECSuccess;
P_CHECKCB (upk != NULL);
P_CHECKCB (p != NULL);
P_CHECKCB(upk != NULL);
P_CHECKCB(p != NULL);
P_CHECK (serial_read_mp_int (upk, &p->share_d, &cfg->modulus));
P_CHECK (serial_read_mp_int (upk, &p->share_e, &cfg->modulus));
P_CHECK(serial_read_mp_int(upk, &p->share_d, &cfg->modulus));
P_CHECK(serial_read_mp_int(upk, &p->share_e, &cfg->modulus));
cleanup:
return rv;
}
SECStatus
PrioPacketVerify2_write (const_PrioPacketVerify2 p, msgpack_packer *pk)
SECStatus
PrioPacketVerify2_write(const_PrioPacketVerify2 p, msgpack_packer* pk)
{
SECStatus rv = SECSuccess;
P_CHECKCB (pk != NULL);
P_CHECKCB (p != NULL);
P_CHECKCB(pk != NULL);
P_CHECKCB(p != NULL);
P_CHECK (serial_write_mp_int (pk, &p->share_out));
P_CHECK(serial_write_mp_int(pk, &p->share_out));
cleanup:
return rv;
}
SECStatus
PrioPacketVerify2_read (PrioPacketVerify2 p, msgpack_unpacker *upk,
const_PrioConfig cfg)
SECStatus
PrioPacketVerify2_read(PrioPacketVerify2 p, msgpack_unpacker* upk,
const_PrioConfig cfg)
{
SECStatus rv = SECSuccess;
P_CHECKCB (upk != NULL);
P_CHECKCB (p != NULL);
P_CHECKCB(upk != NULL);
P_CHECKCB(p != NULL);
P_CHECK (serial_read_mp_int (upk, &p->share_out, &cfg->modulus));
P_CHECK(serial_read_mp_int(upk, &p->share_out, &cfg->modulus));
cleanup:
return rv;
}
SECStatus
PrioTotalShare_write (const_PrioTotalShare t, msgpack_packer *pk)
SECStatus
PrioTotalShare_write(const_PrioTotalShare t, msgpack_packer* pk)
{
SECStatus rv = SECSuccess;
P_CHECKCB (t != NULL);
P_CHECKCB (pk != NULL);
P_CHECK (msgpack_pack_int (pk, t->idx));
P_CHECK (serial_write_mp_array (pk, t->data_shares));
P_CHECKCB(t != NULL);
P_CHECKCB(pk != NULL);
P_CHECK(msgpack_pack_int(pk, t->idx));
P_CHECK(serial_write_mp_array(pk, t->data_shares));
cleanup:
return rv;
}
SECStatus
PrioTotalShare_read (PrioTotalShare t, msgpack_unpacker *upk,
const_PrioConfig cfg)
SECStatus
PrioTotalShare_read(PrioTotalShare t, msgpack_unpacker* upk,
const_PrioConfig cfg)
{
SECStatus rv = SECSuccess;
P_CHECKCB (t != NULL);
P_CHECKCB (upk != NULL);
P_CHECK (serial_read_server_id (upk, &t->idx));
P_CHECK (serial_read_mp_array (upk, t->data_shares, cfg->num_data_fields,
&cfg->modulus));
P_CHECKCB(t != NULL);
P_CHECKCB(upk != NULL);
P_CHECK(serial_read_server_id(upk, &t->idx));
P_CHECK(serial_read_mp_array(upk, t->data_shares, cfg->num_data_fields,
&cfg->modulus));
cleanup:
return rv;
}

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

@ -1,9 +1,9 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef __SERIAL_H__
@ -11,11 +11,11 @@
#include <mprio.h>
SECStatus serial_write_packet_client (msgpack_packer *pk, const_PrioPacketClient p,
const_PrioConfig cfg);
SECStatus serial_write_packet_client(msgpack_packer* pk,
const_PrioPacketClient p,
const_PrioConfig cfg);
SECStatus serial_read_packet_client (msgpack_unpacker *upk, PrioPacketClient p,
const_PrioConfig cfg);
SECStatus serial_read_packet_client(msgpack_unpacker* upk, PrioPacketClient p,
const_PrioConfig cfg);
#endif /* __SERIAL_H__ */

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

@ -1,9 +1,9 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <mpi.h>
@ -12,49 +12,51 @@
#include <stdlib.h>
#include "client.h"
#include "prg.h"
#include "poly.h"
#include "mparray.h"
#include "poly.h"
#include "prg.h"
#include "server.h"
#include "util.h"
PrioServer
PrioServer_new (const_PrioConfig cfg, PrioServerId server_idx,
PrivateKey server_priv, const PrioPRGSeed seed)
PrioServer
PrioServer_new(const_PrioConfig cfg, PrioServerId server_idx,
PrivateKey server_priv, const PrioPRGSeed seed)
{
SECStatus rv = SECSuccess;
PrioServer s = malloc (sizeof (*s));
if (!s) return NULL;
PrioServer s = malloc(sizeof(*s));
if (!s)
return NULL;
s->cfg = cfg;
s->idx = server_idx;
s->priv_key = server_priv;
s->data_shares = NULL;
s->prg = NULL;
P_CHECKA (s->data_shares = MPArray_new (s->cfg->num_data_fields));
P_CHECKA (s->prg = PRG_new (seed));
P_CHECKA(s->data_shares = MPArray_new(s->cfg->num_data_fields));
P_CHECKA(s->prg = PRG_new(seed));
cleanup:
if (rv != SECSuccess) {
PrioServer_clear (s);
PrioServer_clear(s);
return NULL;
}
return s;
}
void
PrioServer_clear (PrioServer s)
void
PrioServer_clear(PrioServer s)
{
if (!s) return;
if (!s)
return;
PRG_clear (s->prg);
MPArray_clear (s->data_shares);
PRG_clear(s->prg);
MPArray_clear(s->data_shares);
free(s);
}
SECStatus
PrioServer_aggregate (PrioServer s, PrioVerifier v)
PrioServer_aggregate(PrioServer s, PrioVerifier v)
{
MPArray arr = NULL;
switch (s->idx) {
@ -69,48 +71,49 @@ PrioServer_aggregate (PrioServer s, PrioVerifier v)
return SECFailure;
}
return MPArray_addmod (s->data_shares, arr, &s->cfg->modulus);
return MPArray_addmod(s->data_shares, arr, &s->cfg->modulus);
}
PrioTotalShare
PrioTotalShare_new (void)
PrioTotalShare
PrioTotalShare_new(void)
{
PrioTotalShare t = malloc (sizeof (*t));
if (!t) return NULL;
PrioTotalShare t = malloc(sizeof(*t));
if (!t)
return NULL;
t->data_shares = MPArray_new (0);
t->data_shares = MPArray_new(0);
if (!t->data_shares) {
free (t);
free(t);
return NULL;
}
return t;
}
void
PrioTotalShare_clear (PrioTotalShare t)
void
PrioTotalShare_clear(PrioTotalShare t)
{
if (!t) return;
MPArray_clear (t->data_shares);
free (t);
if (!t)
return;
MPArray_clear(t->data_shares);
free(t);
}
SECStatus
PrioTotalShare_set_data (PrioTotalShare t, const_PrioServer s)
PrioTotalShare_set_data(PrioTotalShare t, const_PrioServer s)
{
t->idx = s->idx;
SECStatus rv = SECSuccess;
P_CHECK (MPArray_resize (t->data_shares, s->data_shares->len));
P_CHECK (MPArray_copy (t->data_shares, s->data_shares));
P_CHECK(MPArray_resize(t->data_shares, s->data_shares->len));
P_CHECK(MPArray_copy(t->data_shares, s->data_shares));
return rv;
}
SECStatus
PrioTotalShare_final (const_PrioConfig cfg,
unsigned long *output,
const_PrioTotalShare tA, const_PrioTotalShare tB)
PrioTotalShare_final(const_PrioConfig cfg, unsigned long* output,
const_PrioTotalShare tA, const_PrioTotalShare tB)
{
if (tA->data_shares->len != cfg->num_data_fields)
return SECFailure;
@ -122,24 +125,24 @@ PrioTotalShare_final (const_PrioConfig cfg,
SECStatus rv = SECSuccess;
mp_int tmp;
MP_DIGITS (&tmp) = NULL;
MP_CHECKC (mp_init (&tmp));
MP_DIGITS(&tmp) = NULL;
MP_CHECKC(mp_init(&tmp));
for (int i=0; i<cfg->num_data_fields; i++) {
MP_CHECKC (mp_addmod(&tA->data_shares->data[i], &tB->data_shares->data[i],
&cfg->modulus, &tmp));
for (int i = 0; i < cfg->num_data_fields; i++) {
MP_CHECKC(mp_addmod(&tA->data_shares->data[i], &tB->data_shares->data[i],
&cfg->modulus, &tmp));
output[i] = tmp.dp[0];
}
cleanup:
mp_clear (&tmp);
mp_clear(&tmp);
return rv;
}
inline static mp_int *
get_data_share (const_PrioVerifier v, int i) {
inline static mp_int*
get_data_share(const_PrioVerifier v, int i)
{
switch (v->s->idx) {
case PRIO_SERVER_A:
return &v->clientp->shares.A.data_shares->data[i];
@ -150,8 +153,9 @@ get_data_share (const_PrioVerifier v, int i) {
return NULL;
}
inline static mp_int *
get_h_share (const_PrioVerifier v, int i) {
inline static mp_int*
get_h_share(const_PrioVerifier v, int i)
{
switch (v->s->idx) {
case PRIO_SERVER_A:
return &v->clientp->shares.A.h_points->data[i];
@ -168,118 +172,122 @@ get_h_share (const_PrioVerifier v, int i) {
* by the shared secret. Store the evaluations in the verifier object.
*/
static SECStatus
compute_shares (PrioVerifier v, const_PrioPacketClient p)
compute_shares(PrioVerifier v, const_PrioPacketClient p)
{
SECStatus rv;
const int n = v->s->cfg->num_data_fields + 1;
const int N = next_power_of_two (n);
const int N = next_power_of_two(n);
mp_int eval_at;
MP_DIGITS (&eval_at) = NULL;
MP_DIGITS(&eval_at) = NULL;
MPArray points_f = NULL;
MPArray points_g = NULL;
MPArray points_h = NULL;
MP_CHECKC (mp_init (&eval_at));
P_CHECKA (points_f = MPArray_new (N));
P_CHECKA (points_g = MPArray_new (N));
P_CHECKA (points_h = MPArray_new (2*N));
MP_CHECKC(mp_init(&eval_at));
P_CHECKA(points_f = MPArray_new(N));
P_CHECKA(points_g = MPArray_new(N));
P_CHECKA(points_h = MPArray_new(2 * N));
// Use PRG to generate random point
MP_CHECKC (PRG_get_int (v->s->prg, &eval_at, &v->s->cfg->modulus));
// Reduce value into the field we're using. This
MP_CHECKC(PRG_get_int(v->s->prg, &eval_at, &v->s->cfg->modulus));
// Reduce value into the field we're using. This
// doesn't yield exactly a uniformly random point,
// but for values this large, it will be close
// enough.
MP_CHECKC (mp_mod (&eval_at, &v->s->cfg->modulus, &eval_at));
MP_CHECKC(mp_mod(&eval_at, &v->s->cfg->modulus, &eval_at));
// Client sends us the values of f(0) and g(0)
MP_CHECKC (mp_copy(&p->f0_share, &points_f->data[0]));
MP_CHECKC (mp_copy(&p->g0_share, &points_g->data[0]));
MP_CHECKC (mp_copy(&p->h0_share, &points_h->data[0]));
MP_CHECKC(mp_copy(&p->f0_share, &points_f->data[0]));
MP_CHECKC(mp_copy(&p->g0_share, &points_g->data[0]));
MP_CHECKC(mp_copy(&p->h0_share, &points_h->data[0]));
for (int i=1; i<n; i++) {
for (int i = 1; i < n; i++) {
// [f](i) = i-th data share
const mp_int *data_i_minus_1 = get_data_share(v, i-1);
MP_CHECKC (mp_copy(data_i_minus_1, &points_f->data[i]));
const mp_int* data_i_minus_1 = get_data_share(v, i - 1);
MP_CHECKC(mp_copy(data_i_minus_1, &points_f->data[i]));
// [g](i) = i-th data share minus 1
// Only need to shift the share for 0-th server
MP_CHECKC (mp_copy(&points_f->data[i], &points_g->data[i]));
MP_CHECKC(mp_copy(&points_f->data[i], &points_g->data[i]));
if (!v->s->idx) {
MP_CHECKC (mp_sub_d(&points_g->data[i], 1, &points_g->data[i]));
MP_CHECKC (mp_mod(&points_g->data[i], &v->s->cfg->modulus, &points_g->data[i]));
MP_CHECKC(mp_sub_d(&points_g->data[i], 1, &points_g->data[i]));
MP_CHECKC(
mp_mod(&points_g->data[i], &v->s->cfg->modulus, &points_g->data[i]));
}
}
int j = 0;
for (int i=1; i<2*N; i+=2) {
const mp_int *h_point_j = get_h_share (v, j++);
MP_CHECKC (mp_copy(h_point_j, &points_h->data[i]));
for (int i = 1; i < 2 * N; i += 2) {
const mp_int* h_point_j = get_h_share(v, j++);
MP_CHECKC(mp_copy(h_point_j, &points_h->data[i]));
}
P_CHECKC (poly_interp_evaluate (&v->share_fR, points_f, &eval_at, v->s->cfg));
P_CHECKC (poly_interp_evaluate (&v->share_gR, points_g, &eval_at, v->s->cfg));
P_CHECKC (poly_interp_evaluate (&v->share_hR, points_h, &eval_at, v->s->cfg));
P_CHECKC(poly_interp_evaluate(&v->share_fR, points_f, &eval_at, v->s->cfg));
P_CHECKC(poly_interp_evaluate(&v->share_gR, points_g, &eval_at, v->s->cfg));
P_CHECKC(poly_interp_evaluate(&v->share_hR, points_h, &eval_at, v->s->cfg));
cleanup:
MPArray_clear (points_f);
MPArray_clear (points_g);
MPArray_clear (points_h);
mp_clear (&eval_at);
MPArray_clear(points_f);
MPArray_clear(points_g);
MPArray_clear(points_h);
mp_clear(&eval_at);
return rv;
}
PrioVerifier PrioVerifier_new (PrioServer s)
PrioVerifier
PrioVerifier_new(PrioServer s)
{
SECStatus rv = SECSuccess;
PrioVerifier v = malloc (sizeof *v);
if (!v) return NULL;
PrioVerifier v = malloc(sizeof *v);
if (!v)
return NULL;
v->s = s;
v->clientp = NULL;
v->data_sharesB = NULL;
v->h_pointsB = NULL;
MP_DIGITS (&v->share_fR) = NULL;
MP_DIGITS (&v->share_gR) = NULL;
MP_DIGITS (&v->share_hR) = NULL;
MP_DIGITS(&v->share_fR) = NULL;
MP_DIGITS(&v->share_gR) = NULL;
MP_DIGITS(&v->share_hR) = NULL;
MP_CHECKC (mp_init (&v->share_fR));
MP_CHECKC (mp_init (&v->share_gR));
MP_CHECKC (mp_init (&v->share_hR));
MP_CHECKC(mp_init(&v->share_fR));
MP_CHECKC(mp_init(&v->share_gR));
MP_CHECKC(mp_init(&v->share_hR));
P_CHECKA (v->clientp = PrioPacketClient_new (s->cfg, s->idx));
P_CHECKA(v->clientp = PrioPacketClient_new(s->cfg, s->idx));
const int N = next_power_of_two (s->cfg->num_data_fields + 1);
const int N = next_power_of_two(s->cfg->num_data_fields + 1);
if (v->s->idx == PRIO_SERVER_B) {
P_CHECKA (v->data_sharesB = MPArray_new (v->s->cfg->num_data_fields));
P_CHECKA (v->h_pointsB = MPArray_new (N));
P_CHECKA(v->data_sharesB = MPArray_new(v->s->cfg->num_data_fields));
P_CHECKA(v->h_pointsB = MPArray_new(N));
}
cleanup:
if (rv != SECSuccess) {
PrioVerifier_clear (v);
PrioVerifier_clear(v);
return NULL;
}
return v;
}
SECStatus
PrioVerifier_set_data (PrioVerifier v, unsigned char *data, unsigned int data_len)
SECStatus
PrioVerifier_set_data(PrioVerifier v, unsigned char* data,
unsigned int data_len)
{
SECStatus rv = SECSuccess;
PRG prgB = NULL;
P_CHECKC (PrioPacketClient_decrypt (v->clientp, v->s->cfg,
v->s->priv_key, data, data_len));
P_CHECKC(PrioPacketClient_decrypt(v->clientp, v->s->cfg, v->s->priv_key, data,
data_len));
PrioPacketClient p = v->clientp;
if (p->for_server != v->s->idx)
return SECFailure;
const int N = next_power_of_two (v->s->cfg->num_data_fields + 1);
const int N = next_power_of_two(v->s->cfg->num_data_fields + 1);
if (v->s->idx == PRIO_SERVER_A) {
// Check that packet has the correct number of data fields
if (p->shares.A.data_shares->len != v->s->cfg->num_data_fields)
@ -289,70 +297,73 @@ PrioVerifier_set_data (PrioVerifier v, unsigned char *data, unsigned int data_le
}
if (v->s->idx == PRIO_SERVER_B) {
P_CHECKA (prgB = PRG_new (v->clientp->shares.B.seed));
P_CHECKC (PRG_get_array (prgB, v->data_sharesB, &v->s->cfg->modulus));
P_CHECKC (PRG_get_array (prgB, v->h_pointsB, &v->s->cfg->modulus));
P_CHECKA(prgB = PRG_new(v->clientp->shares.B.seed));
P_CHECKC(PRG_get_array(prgB, v->data_sharesB, &v->s->cfg->modulus));
P_CHECKC(PRG_get_array(prgB, v->h_pointsB, &v->s->cfg->modulus));
}
// TODO: This can be done much faster by using the combined
// interpolate-and-evaluate optimization described in the
// interpolate-and-evaluate optimization described in the
// Prio paper.
//
// Compute share of f(r), g(r), h(r)
P_CHECKC (compute_shares (v, p));
P_CHECKC(compute_shares(v, p));
cleanup:
PRG_clear (prgB);
PRG_clear(prgB);
return rv;
}
void PrioVerifier_clear (PrioVerifier v)
void
PrioVerifier_clear(PrioVerifier v)
{
if (v == NULL) return;
PrioPacketClient_clear (v->clientp);
MPArray_clear (v->data_sharesB);
MPArray_clear (v->h_pointsB);
mp_clear (&v->share_fR);
mp_clear (&v->share_gR);
mp_clear (&v->share_hR);
free (v);
if (v == NULL)
return;
PrioPacketClient_clear(v->clientp);
MPArray_clear(v->data_sharesB);
MPArray_clear(v->h_pointsB);
mp_clear(&v->share_fR);
mp_clear(&v->share_gR);
mp_clear(&v->share_hR);
free(v);
}
PrioPacketVerify1
PrioPacketVerify1_new (void)
PrioPacketVerify1
PrioPacketVerify1_new(void)
{
SECStatus rv = SECSuccess;
PrioPacketVerify1 p = malloc (sizeof *p);
if (!p) return NULL;
PrioPacketVerify1 p = malloc(sizeof *p);
if (!p)
return NULL;
MP_DIGITS (&p->share_d) = NULL;
MP_DIGITS (&p->share_e) = NULL;
MP_DIGITS(&p->share_d) = NULL;
MP_DIGITS(&p->share_e) = NULL;
MP_CHECKC (mp_init (&p->share_d));
MP_CHECKC (mp_init (&p->share_e));
MP_CHECKC(mp_init(&p->share_d));
MP_CHECKC(mp_init(&p->share_e));
cleanup:
if (rv != SECSuccess) {
PrioPacketVerify1_clear (p);
PrioPacketVerify1_clear(p);
return NULL;
}
return p;
}
void
PrioPacketVerify1_clear (PrioPacketVerify1 p)
void
PrioPacketVerify1_clear(PrioPacketVerify1 p)
{
if (!p) return;
mp_clear (&p->share_d);
mp_clear (&p->share_e);
free (p);
if (!p)
return;
mp_clear(&p->share_d);
mp_clear(&p->share_e);
free(p);
}
SECStatus
PrioPacketVerify1_set_data (PrioPacketVerify1 p1, const_PrioVerifier v)
PrioPacketVerify1_set_data(PrioPacketVerify1 p1, const_PrioVerifier v)
{
// See the Prio paper for details on how this works.
// Appendix C descrives the MPC protocol used here.
@ -361,121 +372,121 @@ PrioPacketVerify1_set_data (PrioPacketVerify1 p1, const_PrioVerifier v)
// Compute corrections.
// [d] = [f(r)] - [a]
MP_CHECK (mp_sub (&v->share_fR, &v->clientp->triple->a, &p1->share_d));
MP_CHECK (mp_mod (&p1->share_d, &v->s->cfg->modulus, &p1->share_d));
MP_CHECK(mp_sub(&v->share_fR, &v->clientp->triple->a, &p1->share_d));
MP_CHECK(mp_mod(&p1->share_d, &v->s->cfg->modulus, &p1->share_d));
// [e] = [g(r)] - [b]
MP_CHECK (mp_sub (&v->share_gR, &v->clientp->triple->b, &p1->share_e));
MP_CHECK (mp_mod (&p1->share_e, &v->s->cfg->modulus, &p1->share_e));
MP_CHECK(mp_sub(&v->share_gR, &v->clientp->triple->b, &p1->share_e));
MP_CHECK(mp_mod(&p1->share_e, &v->s->cfg->modulus, &p1->share_e));
return rv;
}
PrioPacketVerify2
PrioPacketVerify2_new (void)
PrioPacketVerify2
PrioPacketVerify2_new(void)
{
SECStatus rv = SECSuccess;
PrioPacketVerify2 p = malloc (sizeof *p);
if (!p) return NULL;
PrioPacketVerify2 p = malloc(sizeof *p);
if (!p)
return NULL;
MP_DIGITS (&p->share_out) = NULL;
MP_CHECKC (mp_init (&p->share_out));
MP_DIGITS(&p->share_out) = NULL;
MP_CHECKC(mp_init(&p->share_out));
cleanup:
if (rv != SECSuccess) {
PrioPacketVerify2_clear (p);
PrioPacketVerify2_clear(p);
return NULL;
}
return p;
}
void
PrioPacketVerify2_clear (PrioPacketVerify2 p)
void
PrioPacketVerify2_clear(PrioPacketVerify2 p)
{
if (!p) return;
mp_clear (&p->share_out);
free (p);
if (!p)
return;
mp_clear(&p->share_out);
free(p);
}
SECStatus
PrioPacketVerify2_set_data (PrioPacketVerify2 p2, const_PrioVerifier v,
const_PrioPacketVerify1 p1A, const_PrioPacketVerify1 p1B)
PrioPacketVerify2_set_data(PrioPacketVerify2 p2, const_PrioVerifier v,
const_PrioPacketVerify1 p1A,
const_PrioPacketVerify1 p1B)
{
SECStatus rv = SECSuccess;
mp_int d, e, tmp;
MP_DIGITS (&d) = NULL;
MP_DIGITS (&e) = NULL;
MP_DIGITS (&tmp) = NULL;
MP_DIGITS(&d) = NULL;
MP_DIGITS(&e) = NULL;
MP_DIGITS(&tmp) = NULL;
MP_CHECKC (mp_init (&d));
MP_CHECKC (mp_init (&e));
MP_CHECKC (mp_init (&tmp));
MP_CHECKC(mp_init(&d));
MP_CHECKC(mp_init(&e));
MP_CHECKC(mp_init(&tmp));
const mp_int *mod = &v->s->cfg->modulus;
const mp_int* mod = &v->s->cfg->modulus;
// Compute share of f(r)*g(r)
// [f(r)*g(r)] = [d*e/2] + d[b] + e[a] + [c]
// Compute d
MP_CHECKC (mp_addmod (&p1A->share_d, &p1B->share_d, mod, &d));
// Compute d
MP_CHECKC(mp_addmod(&p1A->share_d, &p1B->share_d, mod, &d));
// Compute e
MP_CHECKC (mp_addmod (&p1A->share_e, &p1B->share_e, mod, &e));
MP_CHECKC(mp_addmod(&p1A->share_e, &p1B->share_e, mod, &e));
// Compute d*e
MP_CHECKC (mp_mulmod (&d, &e, mod, &p2->share_out));
MP_CHECKC(mp_mulmod(&d, &e, mod, &p2->share_out));
// out = d*e/2
MP_CHECKC (mp_mulmod (&p2->share_out, &v->s->cfg->inv2,
mod, &p2->share_out));
MP_CHECKC(mp_mulmod(&p2->share_out, &v->s->cfg->inv2, mod, &p2->share_out));
// Compute d[b]
MP_CHECKC (mp_mulmod (&d, &v->clientp->triple->b, mod, &tmp));
// out = d*e/2 + d[b]
MP_CHECKC (mp_addmod (&p2->share_out, &tmp, mod, &p2->share_out));
// Compute d[b]
MP_CHECKC(mp_mulmod(&d, &v->clientp->triple->b, mod, &tmp));
// out = d*e/2 + d[b]
MP_CHECKC(mp_addmod(&p2->share_out, &tmp, mod, &p2->share_out));
// Compute e[a]
MP_CHECKC (mp_mulmod (&e, &v->clientp->triple->a, mod, &tmp));
// Compute e[a]
MP_CHECKC(mp_mulmod(&e, &v->clientp->triple->a, mod, &tmp));
// out = d*e/2 + d[b] + e[a]
MP_CHECKC (mp_addmod (&p2->share_out, &tmp, mod, &p2->share_out));
MP_CHECKC(mp_addmod(&p2->share_out, &tmp, mod, &p2->share_out));
// out = d*e/2 + d[b] + e[a] + [c]
MP_CHECKC (mp_addmod (&p2->share_out, &v->clientp->triple->c, mod, &p2->share_out));
MP_CHECKC(
mp_addmod(&p2->share_out, &v->clientp->triple->c, mod, &p2->share_out));
// We want to compute f(r)*g(r) - h(r),
// so subtract off [h(r)]:
// out = d*e/2 + d[b] + e[a] + [c] - [h(r)]
MP_CHECKC (mp_sub (&p2->share_out, &v->share_hR, &p2->share_out));
MP_CHECKC (mp_mod (&p2->share_out, mod, &p2->share_out));
MP_CHECKC(mp_sub(&p2->share_out, &v->share_hR, &p2->share_out));
MP_CHECKC(mp_mod(&p2->share_out, mod, &p2->share_out));
cleanup:
mp_clear (&d);
mp_clear (&e);
mp_clear (&tmp);
mp_clear(&d);
mp_clear(&e);
mp_clear(&tmp);
return rv;
}
int
PrioVerifier_isValid (const_PrioVerifier v,
const_PrioPacketVerify2 pA, const_PrioPacketVerify2 pB)
int
PrioVerifier_isValid(const_PrioVerifier v, const_PrioPacketVerify2 pA,
const_PrioPacketVerify2 pB)
{
SECStatus rv = SECSuccess;
mp_int res;
MP_DIGITS (&res) = NULL;
MP_CHECKC (mp_init (&res));
MP_DIGITS(&res) = NULL;
MP_CHECKC(mp_init(&res));
// Add up the shares of the output wire value and
// Add up the shares of the output wire value and
// ensure that the sum is equal to zero, which indicates
// that
// f(r) * g(r) == h(r).
MP_CHECKC (mp_addmod (&pA->share_out, &pB->share_out,
&v->s->cfg->modulus, &res));
MP_CHECKC(
mp_addmod(&pA->share_out, &pB->share_out, &v->s->cfg->modulus, &res));
rv = (mp_cmp_d (&res, 0) == 0) ? SECSuccess : SECFailure;
rv = (mp_cmp_d(&res, 0) == 0) ? SECSuccess : SECFailure;
cleanup:
mp_clear (&res);
mp_clear(&res);
return rv;
}

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

@ -1,9 +1,9 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef __SERVER_H__
@ -13,12 +13,14 @@
#include "prg.h"
#include "share.h"
struct prio_total_share {
struct prio_total_share
{
PrioServerId idx;
MPArray data_shares;
};
struct prio_server {
struct prio_server
{
const_PrioConfig cfg;
PrioServerId idx;
@ -34,7 +36,8 @@ struct prio_server {
PRG prg;
};
struct prio_verifier {
struct prio_verifier
{
PrioServer s;
PrioPacketClient clientp;
@ -47,14 +50,15 @@ struct prio_verifier {
mp_int share_out;
};
struct prio_packet_verify1 {
struct prio_packet_verify1
{
mp_int share_d;
mp_int share_e;
};
struct prio_packet_verify2 {
struct prio_packet_verify2
{
mp_int share_out;
};
#endif /* __SERVER_H__ */

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

@ -1,9 +1,9 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <mprio.h>
@ -12,86 +12,85 @@
#include "share.h"
#include "util.h"
SECStatus
share_int (const struct prio_config *cfg, const mp_int *src,
mp_int *shareA, mp_int *shareB)
share_int(const struct prio_config* cfg, const mp_int* src, mp_int* shareA,
mp_int* shareB)
{
SECStatus rv;
P_CHECK (rand_int (shareA, &cfg->modulus));
MP_CHECK (mp_submod (src, shareA, &cfg->modulus, shareB));
P_CHECK(rand_int(shareA, &cfg->modulus));
MP_CHECK(mp_submod(src, shareA, &cfg->modulus, shareB));
return rv;
}
BeaverTriple
BeaverTriple_new (void)
BeaverTriple_new(void)
{
BeaverTriple triple = malloc (sizeof *triple);
BeaverTriple triple = malloc(sizeof *triple);
if (!triple)
return NULL;
MP_DIGITS (&triple->a) = NULL;
MP_DIGITS (&triple->b) = NULL;
MP_DIGITS (&triple->c) = NULL;
MP_DIGITS(&triple->a) = NULL;
MP_DIGITS(&triple->b) = NULL;
MP_DIGITS(&triple->c) = NULL;
SECStatus rv = SECSuccess;
MP_CHECKC (mp_init (&triple->a));
MP_CHECKC (mp_init (&triple->b));
MP_CHECKC (mp_init (&triple->c));
MP_CHECKC(mp_init(&triple->a));
MP_CHECKC(mp_init(&triple->b));
MP_CHECKC(mp_init(&triple->c));
cleanup:
if (rv != SECSuccess) {
BeaverTriple_clear (triple);
BeaverTriple_clear(triple);
return NULL;
}
return triple;
}
void
BeaverTriple_clear (BeaverTriple triple)
BeaverTriple_clear(BeaverTriple triple)
{
if (!triple) return;
mp_clear (&triple->a);
mp_clear (&triple->b);
mp_clear (&triple->c);
free (triple);
if (!triple)
return;
mp_clear(&triple->a);
mp_clear(&triple->b);
mp_clear(&triple->c);
free(triple);
}
SECStatus
BeaverTriple_set_rand (const struct prio_config *cfg,
struct beaver_triple *triple_1,
struct beaver_triple *triple_2)
BeaverTriple_set_rand(const struct prio_config* cfg,
struct beaver_triple* triple_1,
struct beaver_triple* triple_2)
{
SECStatus rv = SECSuccess;
// TODO: Can shorten this code using share_int()
// We need that
// (a1 + a2)(b1 + b2) = c1 + c2 (mod p)
P_CHECK (rand_int (&triple_1->a, &cfg->modulus));
P_CHECK (rand_int (&triple_1->b, &cfg->modulus));
P_CHECK (rand_int (&triple_2->a, &cfg->modulus));
P_CHECK (rand_int (&triple_2->b, &cfg->modulus));
// (a1 + a2)(b1 + b2) = c1 + c2 (mod p)
P_CHECK(rand_int(&triple_1->a, &cfg->modulus));
P_CHECK(rand_int(&triple_1->b, &cfg->modulus));
P_CHECK(rand_int(&triple_2->a, &cfg->modulus));
P_CHECK(rand_int(&triple_2->b, &cfg->modulus));
// We are trying to be a little clever here to avoid the use of temp
// variables.
// c1 = a1 + a2
MP_CHECK (mp_addmod (&triple_1->a, &triple_2->a, &cfg->modulus, &triple_1->c));
MP_CHECK(mp_addmod(&triple_1->a, &triple_2->a, &cfg->modulus, &triple_1->c));
// c2 = b1 + b2
MP_CHECK (mp_addmod (&triple_1->b, &triple_2->b, &cfg->modulus, &triple_2->c));
MP_CHECK(mp_addmod(&triple_1->b, &triple_2->b, &cfg->modulus, &triple_2->c));
// c1 = c1 * c2 = (a1 + a2) (b1 + b2)
MP_CHECK (mp_mulmod (&triple_1->c, &triple_2->c, &cfg->modulus, &triple_1->c));
MP_CHECK(mp_mulmod(&triple_1->c, &triple_2->c, &cfg->modulus, &triple_1->c));
// Set c2 to random blinding value
MP_CHECK (rand_int (&triple_2->c, &cfg->modulus));
MP_CHECK(rand_int(&triple_2->c, &cfg->modulus));
// c1 = c1 - c2
MP_CHECK (mp_submod (&triple_1->c, &triple_2->c, &cfg->modulus, &triple_1->c));
MP_CHECK(mp_submod(&triple_1->c, &triple_2->c, &cfg->modulus, &triple_1->c));
// Now we should have random tuples satisfying:
// (a1 + a2) (b1 + b2) = c1 + c2
@ -99,10 +98,9 @@ BeaverTriple_set_rand (const struct prio_config *cfg,
return rv;
}
bool
BeaverTriple_areEqual (const_BeaverTriple t1, const_BeaverTriple t2)
bool
BeaverTriple_areEqual(const_BeaverTriple t1, const_BeaverTriple t2)
{
return (mp_cmp (&t1->a, &t2->a) == 0 &&
mp_cmp (&t1->b, &t2->b) == 0 &&
mp_cmp (&t1->c, &t2->c) == 0);
return (mp_cmp(&t1->a, &t2->a) == 0 && mp_cmp(&t1->b, &t2->b) == 0 &&
mp_cmp(&t1->c, &t2->c) == 0);
}

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

@ -1,12 +1,11 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef __SHARE_H__
#define __SHARE_H__
@ -14,23 +13,22 @@
#include "config.h"
struct beaver_triple {
struct beaver_triple
{
mp_int a;
mp_int b;
mp_int c;
};
typedef struct beaver_triple *BeaverTriple;
typedef const struct beaver_triple *const_BeaverTriple;
typedef struct beaver_triple* BeaverTriple;
typedef const struct beaver_triple* const_BeaverTriple;
/*
* Use secret sharing to split the int src into two shares.
* The mp_ints must be initialized.
*/
SECStatus share_int (const_PrioConfig cfg, const mp_int *src,
mp_int *shareA, mp_int *shareB);
SECStatus share_int(const_PrioConfig cfg, const mp_int* src, mp_int* shareA,
mp_int* shareB);
/*
* Prio uses Beaver triples to implement one step of the
@ -38,14 +36,12 @@ SECStatus share_int (const_PrioConfig cfg, const mp_int *src,
* a sharing of random values a, b, c such that
* a * b = c
*/
BeaverTriple BeaverTriple_new (void);
void BeaverTriple_clear (BeaverTriple t);
BeaverTriple BeaverTriple_new(void);
void BeaverTriple_clear(BeaverTriple t);
SECStatus BeaverTriple_set_rand (const_PrioConfig cfg,
BeaverTriple triple_a,
BeaverTriple triple_b);
SECStatus BeaverTriple_set_rand(const_PrioConfig cfg, BeaverTriple triple_a,
BeaverTriple triple_b);
bool BeaverTriple_areEqual (const_BeaverTriple t1, const_BeaverTriple t2);
bool BeaverTriple_areEqual(const_BeaverTriple t1, const_BeaverTriple t2);
#endif /* __SHARE_H__ */

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

@ -1,9 +1,9 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef __UTIL_H__
@ -16,80 +16,88 @@
#define MIN(a, b) ((a) < (b) ? (a) : (b))
// Check a Prio error code and return failure if the call fails.
#define P_CHECK(s) \
do { \
if((rv = (s)) != SECSuccess) \
return rv; \
} while(0);
#define P_CHECK(s) \
do { \
if ((rv = (s)) != SECSuccess) \
return rv; \
} while (0);
// Check an allocation that should not return NULL. If the allocation returns
// NULL, set the return value and jump to the cleanup label to free memory.
#define P_CHECKA(s) \
do { \
if((s) == NULL) {\
rv = SECFailure;\
goto cleanup;\
}\
} while(0);
// NULL, set the return value and jump to the cleanup label to free memory.
#define P_CHECKA(s) \
do { \
if ((s) == NULL) { \
rv = SECFailure; \
goto cleanup; \
} \
} while (0);
// Check a Prio library call that should return SECSuccess. If it doesn't,
// jump to the cleanup label.
#define P_CHECKC(s) \
do { \
if((rv = (s)) != SECSuccess) { \
goto cleanup; \
}\
} while(0);
#define P_CHECKC(s) \
do { \
if ((rv = (s)) != SECSuccess) { \
goto cleanup; \
} \
} while (0);
// Check a boolean that should be true. If it not,
// jump to the cleanup label.
#define P_CHECKCB(s) \
do { \
if(!(s)) { \
rv = SECFailure; \
goto cleanup; \
}\
} while(0);
#define P_CHECKCB(s) \
do { \
if (!(s)) { \
rv = SECFailure; \
goto cleanup; \
} \
} while (0);
// Check an MPI library call and return failure if it fails.
#define MP_CHECK(s) do { if((s) != MP_OKAY) return SECFailure; } while(0);
#define MP_CHECK(s) \
do { \
if ((s) != MP_OKAY) \
return SECFailure; \
} while (0);
// Check a msgpack object unpacked correctly
#define UP_CHECK(s) do { int r = (s); if(r != MSGPACK_UNPACK_SUCCESS &&\
r != MSGPACK_UNPACK_EXTRA_BYTES) \
return SECFailure; } while(0);
#define UP_CHECK(s) \
do { \
int r = (s); \
if (r != MSGPACK_UNPACK_SUCCESS && r != MSGPACK_UNPACK_EXTRA_BYTES) \
return SECFailure; \
} while (0);
// Check an MPI library call. If it fails, set the return code and jump
// to the cleanup label.
#define MP_CHECKC(s) \
do { \
if((s) != MP_OKAY) { \
rv = SECFailure; \
goto cleanup; \
}\
} while(0);
#define MP_CHECKC(s) \
do { \
if ((s) != MP_OKAY) { \
rv = SECFailure; \
goto cleanup; \
} \
} while (0);
static inline int
next_power_of_two (int val)
next_power_of_two(int val)
{
int i = val;
int out = 0;
for ( ; i > 0; i >>= 1) {
for (; i > 0; i >>= 1) {
out++;
}
int pow = 1 << out;
return (pow > 1 && pow/2 == val) ? val : pow;
}
return (pow > 1 && pow / 2 == val) ? val : pow;
}
/*
/*
* Return a mask that masks out all of the zero bits
*/
static inline unsigned char
msb_mask (unsigned char val)
msb_mask(unsigned char val)
{
unsigned char mask;
for (mask = 0x00; (val & mask) != val; mask = (mask << 1) + 1);
for (mask = 0x00; (val & mask) != val; mask = (mask << 1) + 1)
;
return mask;
}
@ -99,4 +107,3 @@ msb_mask (unsigned char val)
#define UNUSED(x) (void)(x)
#endif /* __UTIL_H__ */

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

@ -1,52 +1,52 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <mprio.h>
#include "mutest.h"
#include "prio/client.h"
#include "prio/server.h"
#include "prio/util.h"
#include "mutest.h"
void
mu_test_client__new (void)
void
mu_test_client__new(void)
{
SECStatus rv = SECSuccess;
PrioConfig cfg = NULL;
PrioPacketClient pA = NULL;
PrioPacketClient pB = NULL;
P_CHECKA (cfg = PrioConfig_newTest(23));
P_CHECKA (pA = PrioPacketClient_new (cfg, PRIO_SERVER_A));
P_CHECKA (pB = PrioPacketClient_new (cfg, PRIO_SERVER_B));
P_CHECKA(cfg = PrioConfig_newTest(23));
P_CHECKA(pA = PrioPacketClient_new(cfg, PRIO_SERVER_A));
P_CHECKA(pB = PrioPacketClient_new(cfg, PRIO_SERVER_B));
{
const int ndata = PrioConfig_numDataFields (cfg);
bool data_items[ndata];
const int ndata = PrioConfig_numDataFields(cfg);
bool data_items[ndata];
for (int i=0; i < ndata; i++) {
// Arbitrary data
data_items[i] = (i % 3 == 1) || (i % 5 == 3);
}
for (int i = 0; i < ndata; i++) {
// Arbitrary data
data_items[i] = (i % 3 == 1) || (i % 5 == 3);
}
P_CHECKC (PrioPacketClient_set_data (cfg, data_items, pA, pB));
P_CHECKC(PrioPacketClient_set_data(cfg, data_items, pA, pB));
}
cleanup:
mu_check (rv == SECSuccess);
mu_check(rv == SECSuccess);
PrioPacketClient_clear (pA);
PrioPacketClient_clear (pB);
PrioConfig_clear (cfg);
PrioPacketClient_clear(pA);
PrioPacketClient_clear(pB);
PrioConfig_clear(cfg);
}
void
test_client_agg (int nclients)
void
test_client_agg(int nclients)
{
SECStatus rv = SECSuccess;
PublicKey pkA = NULL;
@ -60,101 +60,102 @@ test_client_agg (int nclients)
PrioTotalShare tB = NULL;
PrioVerifier vA = NULL;
PrioVerifier vB = NULL;
unsigned char *for_a = NULL;
unsigned char *for_b = NULL;
const unsigned char *batch_id = (unsigned char *)"test_batch";
unsigned int batch_id_len = strlen ((char *)batch_id);
unsigned char* for_a = NULL;
unsigned char* for_b = NULL;
const unsigned char* batch_id = (unsigned char*)"test_batch";
unsigned int batch_id_len = strlen((char*)batch_id);
PrioPRGSeed seed;
P_CHECKC (PrioPRGSeed_randomize (&seed));
P_CHECKC(PrioPRGSeed_randomize(&seed));
P_CHECKC (Keypair_new (&skA, &pkA));
P_CHECKC (Keypair_new (&skB, &pkB));
P_CHECKA (cfg = PrioConfig_new (133, pkA, pkB, batch_id, batch_id_len));
P_CHECKA (sA = PrioServer_new (cfg, 0, skA, seed));
P_CHECKA (sB = PrioServer_new (cfg, 1, skB, seed));
P_CHECKA (tA = PrioTotalShare_new ());
P_CHECKA (tB = PrioTotalShare_new ());
P_CHECKA (vA = PrioVerifier_new (sA));
P_CHECKA (vB = PrioVerifier_new (sB));
P_CHECKC(Keypair_new(&skA, &pkA));
P_CHECKC(Keypair_new(&skB, &pkB));
P_CHECKA(cfg = PrioConfig_new(133, pkA, pkB, batch_id, batch_id_len));
P_CHECKA(sA = PrioServer_new(cfg, 0, skA, seed));
P_CHECKA(sB = PrioServer_new(cfg, 1, skB, seed));
P_CHECKA(tA = PrioTotalShare_new());
P_CHECKA(tB = PrioTotalShare_new());
P_CHECKA(vA = PrioVerifier_new(sA));
P_CHECKA(vB = PrioVerifier_new(sB));
const int ndata = PrioConfig_numDataFields (cfg);
const int ndata = PrioConfig_numDataFields(cfg);
{
bool data_items[ndata];
for (int i=0; i < ndata; i++) {
for (int i = 0; i < ndata; i++) {
// Arbitrary data
data_items[i] = (i % 3 == 1) || (i % 5 == 3);
}
for (int i=0; i < nclients; i++) {
for (int i = 0; i < nclients; i++) {
unsigned int aLen, bLen;
P_CHECKC (PrioClient_encode (cfg, data_items, &for_a, &aLen,
&for_b, &bLen));
P_CHECKC (PrioVerifier_set_data (vA, for_a, aLen));
P_CHECKC (PrioVerifier_set_data (vB, for_b, bLen));
P_CHECKC(
PrioClient_encode(cfg, data_items, &for_a, &aLen, &for_b, &bLen));
mu_check (PrioServer_aggregate (sA, vA) == SECSuccess);
mu_check (PrioServer_aggregate (sB, vB) == SECSuccess);
P_CHECKC(PrioVerifier_set_data(vA, for_a, aLen));
P_CHECKC(PrioVerifier_set_data(vB, for_b, bLen));
free (for_a);
free (for_b);
mu_check(PrioServer_aggregate(sA, vA) == SECSuccess);
mu_check(PrioServer_aggregate(sB, vB) == SECSuccess);
free(for_a);
free(for_b);
for_a = NULL;
for_b = NULL;
}
mu_check (PrioTotalShare_set_data (tA, sA) == SECSuccess);
mu_check (PrioTotalShare_set_data (tB, sB) == SECSuccess);
mu_check(PrioTotalShare_set_data(tA, sA) == SECSuccess);
mu_check(PrioTotalShare_set_data(tB, sB) == SECSuccess);
unsigned long output[ndata];
mu_check (PrioTotalShare_final (cfg, output, tA, tB) == SECSuccess);
for (int i=0; i < ndata; i++) {
mu_check(PrioTotalShare_final(cfg, output, tA, tB) == SECSuccess);
for (int i = 0; i < ndata; i++) {
unsigned long v = ((i % 3 == 1) || (i % 5 == 3));
mu_check (output[i] == v*nclients);
mu_check(output[i] == v * nclients);
}
}
//rv = SECFailure;
//goto cleanup;
// rv = SECFailure;
// goto cleanup;
cleanup:
mu_check (rv == SECSuccess);
if (for_a) free (for_a);
if (for_b) free (for_b);
mu_check(rv == SECSuccess);
if (for_a)
free(for_a);
if (for_b)
free(for_b);
PublicKey_clear (pkA);
PublicKey_clear (pkB);
PrivateKey_clear (skA);
PrivateKey_clear (skB);
PublicKey_clear(pkA);
PublicKey_clear(pkB);
PrivateKey_clear(skA);
PrivateKey_clear(skB);
PrioVerifier_clear (vA);
PrioVerifier_clear (vB);
PrioVerifier_clear(vA);
PrioVerifier_clear(vB);
PrioTotalShare_clear (tA);
PrioTotalShare_clear (tB);
PrioTotalShare_clear(tA);
PrioTotalShare_clear(tB);
PrioServer_clear (sA);
PrioServer_clear (sB);
PrioConfig_clear (cfg);
PrioServer_clear(sA);
PrioServer_clear(sB);
PrioConfig_clear(cfg);
}
void
mu_test_client__agg_1 (void)
void
mu_test_client__agg_1(void)
{
test_client_agg (1);
test_client_agg(1);
}
void
mu_test_client__agg_2 (void)
void
mu_test_client__agg_2(void)
{
test_client_agg (2);
test_client_agg(2);
}
void
mu_test_client__agg_10 (void)
void
mu_test_client__agg_10(void)
{
test_client_agg (10);
test_client_agg(10);
}

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

@ -1,43 +1,42 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <nspr.h>
#include <nss/nss.h>
#include <nss/secoidt.h>
#include <nss/keyhi.h>
#include <nss/pk11pub.h>
#include <nss/cert.h>
#include <nss/keyhi.h>
#include <nss/nss.h>
#include <nss/pk11pub.h>
#include <nss/secoidt.h>
#include "mutest.h"
#include "prio/encrypt.h"
#include "prio/rand.h"
#include "prio/util.h"
void
mu_test_keygen (void)
void
mu_test_keygen(void)
{
SECStatus rv = SECSuccess;
PublicKey pubkey = NULL;
PrivateKey pvtkey = NULL;
P_CHECKC (Keypair_new (&pvtkey, &pubkey));
mu_check (SECKEY_PublicKeyStrength (pubkey) == 32);
P_CHECKC(Keypair_new(&pvtkey, &pubkey));
mu_check(SECKEY_PublicKeyStrength(pubkey) == 32);
cleanup:
mu_check (rv == SECSuccess);
PublicKey_clear (pubkey);
PrivateKey_clear (pvtkey);
mu_check(rv == SECSuccess);
PublicKey_clear(pubkey);
PrivateKey_clear(pvtkey);
return;
}
void
test_encrypt_once (int bad, unsigned int inlen)
void
test_encrypt_once(int bad, unsigned int inlen)
{
SECStatus rv = SECSuccess;
PublicKey pubkey = NULL;
@ -45,31 +44,30 @@ test_encrypt_once (int bad, unsigned int inlen)
PublicKey pubkey2 = NULL;
PrivateKey pvtkey2 = NULL;
unsigned char *bytes_in = NULL;
unsigned char *bytes_enc = NULL;
unsigned char *bytes_dec = NULL;
unsigned char* bytes_in = NULL;
unsigned char* bytes_enc = NULL;
unsigned char* bytes_dec = NULL;
unsigned int enclen;
P_CHECKC (PublicKey_encryptSize (inlen, &enclen));
P_CHECKC(PublicKey_encryptSize(inlen, &enclen));
unsigned int declen = enclen;
P_CHECKA (bytes_in = malloc (inlen));
P_CHECKA (bytes_enc = malloc (enclen));
P_CHECKA (bytes_dec= malloc (enclen));
P_CHECKC (rand_bytes (bytes_in, inlen));
P_CHECKA(bytes_in = malloc(inlen));
P_CHECKA(bytes_enc = malloc(enclen));
P_CHECKA(bytes_dec = malloc(enclen));
P_CHECKC(rand_bytes(bytes_in, inlen));
memset (bytes_dec, 0, declen);
memset(bytes_dec, 0, declen);
unsigned int encryptedBytes;
P_CHECKC (Keypair_new (&pvtkey, &pubkey));
P_CHECKC (Keypair_new (&pvtkey2, &pubkey2));
P_CHECKC (PublicKey_encrypt (pubkey, bytes_enc,
&encryptedBytes, enclen,
bytes_in, inlen));
mu_check (encryptedBytes == enclen);
P_CHECKC(Keypair_new(&pvtkey, &pubkey));
P_CHECKC(Keypair_new(&pvtkey2, &pubkey2));
P_CHECKC(PublicKey_encrypt(pubkey, bytes_enc, &encryptedBytes, enclen,
bytes_in, inlen));
mu_check(encryptedBytes == enclen);
if (bad == 1)
enclen = 30;
if (bad == 1)
enclen = 30;
if (bad == 2) {
bytes_enc[4] = 6;
@ -83,146 +81,149 @@ test_encrypt_once (int bad, unsigned int inlen)
unsigned int decryptedBytes;
PrivateKey key_to_use = (bad == 4) ? pvtkey2 : pvtkey;
P_CHECKC (PrivateKey_decrypt (key_to_use, bytes_dec, &decryptedBytes, declen,
bytes_enc, enclen));
mu_check (decryptedBytes == inlen);
mu_check (!strncmp ((char *)bytes_in, (char *)bytes_dec, inlen));
P_CHECKC(PrivateKey_decrypt(key_to_use, bytes_dec, &decryptedBytes, declen,
bytes_enc, enclen));
mu_check(decryptedBytes == inlen);
mu_check(!strncmp((char*)bytes_in, (char*)bytes_dec, inlen));
cleanup:
mu_check (bad ? (rv == SECFailure) : (rv == SECSuccess));
if (bytes_in) free (bytes_in);
if (bytes_enc) free (bytes_enc);
if (bytes_dec) free (bytes_dec);
mu_check(bad ? (rv == SECFailure) : (rv == SECSuccess));
if (bytes_in)
free(bytes_in);
if (bytes_enc)
free(bytes_enc);
if (bytes_dec)
free(bytes_dec);
PublicKey_clear (pubkey);
PrivateKey_clear (pvtkey);
PublicKey_clear (pubkey2);
PrivateKey_clear (pvtkey2);
PublicKey_clear(pubkey);
PrivateKey_clear(pvtkey);
PublicKey_clear(pubkey2);
PrivateKey_clear(pvtkey2);
return;
}
void
mu_test_encrypt_good (void)
void
mu_test_encrypt_good(void)
{
test_encrypt_once (0, 100);
test_encrypt_once(0, 100);
}
void
mu_test_encrypt_good_long (void)
void
mu_test_encrypt_good_long(void)
{
test_encrypt_once (0, 1000000);
test_encrypt_once(0, 1000000);
}
void
mu_test_encrypt_too_short (void)
void
mu_test_encrypt_too_short(void)
{
test_encrypt_once (1, 87);
test_encrypt_once(1, 87);
}
void
mu_test_encrypt_garbage (void)
void
mu_test_encrypt_garbage(void)
{
test_encrypt_once (2, 10023);
test_encrypt_once(2, 10023);
}
void
mu_test_encrypt_garbage2 (void)
void
mu_test_encrypt_garbage2(void)
{
test_encrypt_once (3, 8123);
test_encrypt_once(3, 8123);
}
void
mu_test_decrypt_wrong_key (void)
void
mu_test_decrypt_wrong_key(void)
{
test_encrypt_once (4, 81230);
test_encrypt_once(4, 81230);
}
void
mu_test_export (void)
void
mu_test_export(void)
{
SECStatus rv = SECSuccess;
PublicKey pubkey = NULL;
unsigned char raw_bytes[CURVE25519_KEY_LEN];
unsigned char raw_bytes2[CURVE25519_KEY_LEN];
for (int i=0; i< CURVE25519_KEY_LEN; i++) {
raw_bytes[i] = (3*i+7) % 0xFF;
for (int i = 0; i < CURVE25519_KEY_LEN; i++) {
raw_bytes[i] = (3 * i + 7) % 0xFF;
}
P_CHECKC (PublicKey_import (&pubkey, raw_bytes, CURVE25519_KEY_LEN));
P_CHECKC (PublicKey_export (pubkey, raw_bytes2));
P_CHECKC(PublicKey_import(&pubkey, raw_bytes, CURVE25519_KEY_LEN));
P_CHECKC(PublicKey_export(pubkey, raw_bytes2));
for (int i=0; i< CURVE25519_KEY_LEN; i++) {
mu_check (raw_bytes[i] == raw_bytes2[i]);
for (int i = 0; i < CURVE25519_KEY_LEN; i++) {
mu_check(raw_bytes[i] == raw_bytes2[i]);
}
cleanup:
mu_check (rv == SECSuccess);
PublicKey_clear (pubkey);
mu_check(rv == SECSuccess);
PublicKey_clear(pubkey);
return;
}
void
mu_test_export_hex (void)
void
mu_test_export_hex(void)
{
SECStatus rv = SECSuccess;
PublicKey pubkey = NULL;
const unsigned char hex_bytes[2*CURVE25519_KEY_LEN] = \
"102030405060708090A0B0C0D0E0F00000FFEEDDCCBBAA998877665544332211";
const unsigned char hex_bytesl[2*CURVE25519_KEY_LEN] = \
"102030405060708090a0B0C0D0E0F00000FfeEddcCbBaa998877665544332211";
const unsigned char hex_bytes[2 * CURVE25519_KEY_LEN] =
"102030405060708090A0B0C0D0E0F00000FFEEDDCCBBAA998877665544332211";
const unsigned char hex_bytesl[2 * CURVE25519_KEY_LEN] =
"102030405060708090a0B0C0D0E0F00000FfeEddcCbBaa998877665544332211";
const unsigned char raw_bytes_should[CURVE25519_KEY_LEN] = {
0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0, 0x00,
0x00, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99,
0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11 };
0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xA0, 0xB0,
0xC0, 0xD0, 0xE0, 0xF0, 0x00, 0x00, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB,
0xAA, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11
};
unsigned char raw_bytes[CURVE25519_KEY_LEN];
unsigned char hex_bytes2[2*CURVE25519_KEY_LEN+1];
unsigned char hex_bytes2[2 * CURVE25519_KEY_LEN + 1];
// Make sure that invalid lengths are rejected.
mu_check (PublicKey_import_hex (&pubkey, hex_bytes,
2*CURVE25519_KEY_LEN-1) == SECFailure);
mu_check (PublicKey_import_hex (&pubkey, hex_bytes,
2*CURVE25519_KEY_LEN+1) == SECFailure);
mu_check(PublicKey_import_hex(&pubkey, hex_bytes,
2 * CURVE25519_KEY_LEN - 1) == SECFailure);
mu_check(PublicKey_import_hex(&pubkey, hex_bytes,
2 * CURVE25519_KEY_LEN + 1) == SECFailure);
// Import a key in upper-case hex
P_CHECKC (PublicKey_import_hex (&pubkey, hex_bytes, 2*CURVE25519_KEY_LEN));
P_CHECKC (PublicKey_export (pubkey, raw_bytes));
PublicKey_clear (pubkey);
P_CHECKC(PublicKey_import_hex(&pubkey, hex_bytes, 2 * CURVE25519_KEY_LEN));
P_CHECKC(PublicKey_export(pubkey, raw_bytes));
PublicKey_clear(pubkey);
pubkey = NULL;
for (int i=0; i<CURVE25519_KEY_LEN; i++) {
mu_check (raw_bytes[i] == raw_bytes_should[i]);
for (int i = 0; i < CURVE25519_KEY_LEN; i++) {
mu_check(raw_bytes[i] == raw_bytes_should[i]);
}
// Import a key in mixed-case hex
P_CHECKC (PublicKey_import_hex (&pubkey, hex_bytesl, 2*CURVE25519_KEY_LEN));
P_CHECKC (PublicKey_export (pubkey, raw_bytes));
PublicKey_clear (pubkey);
P_CHECKC(PublicKey_import_hex(&pubkey, hex_bytesl, 2 * CURVE25519_KEY_LEN));
P_CHECKC(PublicKey_export(pubkey, raw_bytes));
PublicKey_clear(pubkey);
pubkey = NULL;
for (int i=0; i<CURVE25519_KEY_LEN; i++) {
mu_check (raw_bytes[i] == raw_bytes_should[i]);
for (int i = 0; i < CURVE25519_KEY_LEN; i++) {
mu_check(raw_bytes[i] == raw_bytes_should[i]);
}
mu_check (PublicKey_import (&pubkey, raw_bytes_should,
CURVE25519_KEY_LEN-1) == SECFailure);
mu_check (PublicKey_import (&pubkey, raw_bytes_should,
CURVE25519_KEY_LEN+1) == SECFailure);
mu_check(PublicKey_import(&pubkey, raw_bytes_should,
CURVE25519_KEY_LEN - 1) == SECFailure);
mu_check(PublicKey_import(&pubkey, raw_bytes_should,
CURVE25519_KEY_LEN + 1) == SECFailure);
// Import a raw key and export as hex
P_CHECKC (PublicKey_import (&pubkey, raw_bytes_should, CURVE25519_KEY_LEN));
P_CHECKC (PublicKey_export_hex (pubkey, hex_bytes2));
P_CHECKC(PublicKey_import(&pubkey, raw_bytes_should, CURVE25519_KEY_LEN));
P_CHECKC(PublicKey_export_hex(pubkey, hex_bytes2));
for (int i=0; i<2*CURVE25519_KEY_LEN; i++) {
mu_check (hex_bytes[i] == hex_bytes2[i]);
for (int i = 0; i < 2 * CURVE25519_KEY_LEN; i++) {
mu_check(hex_bytes[i] == hex_bytes2[i]);
}
mu_ensure (hex_bytes2[2*CURVE25519_KEY_LEN] == '\0');
mu_ensure(hex_bytes2[2 * CURVE25519_KEY_LEN] == '\0');
cleanup:
mu_check (rv == SECSuccess);
PublicKey_clear (pubkey);
mu_check(rv == SECSuccess);
PublicKey_clear(pubkey);
return;
}

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

@ -1,21 +1,16 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
//#include <stdio.h>
#include "mutest.h"
void
mu_test_example (void)
void
mu_test_example(void)
{
mu_check (1);
mu_check(1);
}

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

@ -1,9 +1,9 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <mpi.h>
@ -16,59 +16,59 @@
#include "prio/poly.h"
#include "prio/util.h"
void
mu_test__fft_one (void)
void
mu_test__fft_one(void)
{
SECStatus rv = SECSuccess;
PrioConfig cfg = NULL;
MPArray points_in = NULL;
MPArray points_out = NULL;
P_CHECKA (cfg = PrioConfig_newTest (123));
P_CHECKA (points_in = MPArray_new (1));
P_CHECKA (points_out = MPArray_new (1));
P_CHECKA(cfg = PrioConfig_newTest(123));
P_CHECKA(points_in = MPArray_new(1));
P_CHECKA(points_out = MPArray_new(1));
mp_set (&points_in->data[0], 3);
mu_check (poly_fft (points_out, points_in, cfg, false) == SECSuccess);
mp_set(&points_in->data[0], 3);
mu_check(poly_fft(points_out, points_in, cfg, false) == SECSuccess);
mu_check (mp_cmp_d(&points_in->data[0], 3) == 0);
mu_check (mp_cmp_d(&points_out->data[0], 3) == 0);
mu_check(mp_cmp_d(&points_in->data[0], 3) == 0);
mu_check(mp_cmp_d(&points_out->data[0], 3) == 0);
cleanup:
mu_check (rv == SECSuccess);
MPArray_clear (points_in);
MPArray_clear (points_out);
mu_check(rv == SECSuccess);
MPArray_clear(points_in);
MPArray_clear(points_out);
PrioConfig_clear (cfg);
PrioConfig_clear(cfg);
}
void
mu_test__fft_roots (void)
void
mu_test__fft_roots(void)
{
SECStatus rv = SECSuccess;
PrioConfig cfg = NULL;
mp_int tmp;
MP_DIGITS (&tmp) = NULL;
MP_DIGITS(&tmp) = NULL;
P_CHECKA (cfg = PrioConfig_newTest (90));
MP_CHECKC (mp_init (&tmp));
P_CHECKA(cfg = PrioConfig_newTest(90));
MP_CHECKC(mp_init(&tmp));
mp_int roots[4];
poly_fft_get_roots (roots, 4, cfg, false);
poly_fft_get_roots(roots, 4, cfg, false);
for (int i=0; i<4; i++) {
for (int i = 0; i < 4; i++) {
mp_exptmod_d(&roots[i], 4, &cfg->modulus, &tmp);
mu_check (mp_cmp_d( &tmp, 1) == 0);
mu_check(mp_cmp_d(&tmp, 1) == 0);
}
cleanup:
mu_check (rv == SECSuccess);
mp_clear (&tmp);
PrioConfig_clear (cfg);
mu_check(rv == SECSuccess);
mp_clear(&tmp);
PrioConfig_clear(cfg);
}
void
mu_test__fft_simple (void)
void
mu_test__fft_simple(void)
{
SECStatus rv = SECSuccess;
const int nPoints = 4;
@ -79,32 +79,34 @@ mu_test__fft_simple (void)
mp_int should_be, tmp;
mp_int roots[nPoints];
MP_DIGITS (&should_be) = NULL;
MP_DIGITS (&tmp) = NULL;
for (int i=0; i<nPoints; i++) {
MP_DIGITS (&roots[i]) = NULL;
MP_DIGITS(&should_be) = NULL;
MP_DIGITS(&tmp) = NULL;
for (int i = 0; i < nPoints; i++) {
MP_DIGITS(&roots[i]) = NULL;
}
P_CHECKA (cfg = PrioConfig_newTest (140));
P_CHECKA (points_in = MPArray_new (nPoints));
P_CHECKA (points_out = MPArray_new (nPoints));
MP_CHECKC (mp_init (&should_be));
MP_CHECKC (mp_init (&tmp));
poly_fft_get_roots (roots, nPoints, cfg, false);
P_CHECKA(cfg = PrioConfig_newTest(140));
P_CHECKA(points_in = MPArray_new(nPoints));
P_CHECKA(points_out = MPArray_new(nPoints));
MP_CHECKC(mp_init(&should_be));
MP_CHECKC(mp_init(&tmp));
mp_set (&points_in->data[0], 3);
mp_set (&points_in->data[1], 8);
mp_set (&points_in->data[2], 7);
mp_set (&points_in->data[3], 9);
mu_check (poly_fft (points_out, points_in, cfg, false) == SECSuccess);
poly_fft_get_roots(roots, nPoints, cfg, false);
for (int i=0; i<nPoints; i++) {
mp_set (&should_be, 0);
for (int j=0; j<nPoints; j++) {
mu_check (mp_exptmod_d(&roots[i], j, &cfg->modulus, &tmp) == MP_OKAY);
mu_check (mp_mulmod(&tmp, &points_in->data[j], &cfg->modulus, &tmp) == MP_OKAY);
mu_check (mp_addmod(&should_be, &tmp, &cfg->modulus, &should_be) == MP_OKAY);
mp_set(&points_in->data[0], 3);
mp_set(&points_in->data[1], 8);
mp_set(&points_in->data[2], 7);
mp_set(&points_in->data[3], 9);
mu_check(poly_fft(points_out, points_in, cfg, false) == SECSuccess);
for (int i = 0; i < nPoints; i++) {
mp_set(&should_be, 0);
for (int j = 0; j < nPoints; j++) {
mu_check(mp_exptmod_d(&roots[i], j, &cfg->modulus, &tmp) == MP_OKAY);
mu_check(mp_mulmod(&tmp, &points_in->data[j], &cfg->modulus, &tmp) ==
MP_OKAY);
mu_check(mp_addmod(&should_be, &tmp, &cfg->modulus, &should_be) ==
MP_OKAY);
}
/*
@ -114,20 +116,20 @@ mu_test__fft_simple (void)
mp_print(&points_out[i], stdout);
puts("");
*/
mu_check (mp_cmp (&should_be, &points_out->data[i]) == 0);
mu_check(mp_cmp(&should_be, &points_out->data[i]) == 0);
}
cleanup:
mu_check (rv == SECSuccess);
mp_clear (&tmp);
mp_clear (&should_be);
MPArray_clear (points_in);
MPArray_clear (points_out);
PrioConfig_clear (cfg);
mu_check(rv == SECSuccess);
mp_clear(&tmp);
mp_clear(&should_be);
MPArray_clear(points_in);
MPArray_clear(points_out);
PrioConfig_clear(cfg);
}
void
mu_test__fft_invert (void)
void
mu_test__fft_invert(void)
{
SECStatus rv = SECSuccess;
const int nPoints = 8;
@ -137,34 +139,34 @@ mu_test__fft_invert (void)
MPArray points_out = NULL;
MPArray points_out2 = NULL;
mp_int roots[nPoints];
P_CHECKA (cfg = PrioConfig_newTest (91));
P_CHECKA (points_in = MPArray_new (nPoints));
P_CHECKA (points_out = MPArray_new (nPoints));
P_CHECKA (points_out2 = MPArray_new (nPoints));
poly_fft_get_roots (roots, nPoints, cfg, false);
P_CHECKA(cfg = PrioConfig_newTest(91));
P_CHECKA(points_in = MPArray_new(nPoints));
P_CHECKA(points_out = MPArray_new(nPoints));
P_CHECKA(points_out2 = MPArray_new(nPoints));
mp_set (&points_in->data[0], 3);
mp_set (&points_in->data[1], 8);
mp_set (&points_in->data[2], 7);
mp_set (&points_in->data[3], 9);
mp_set (&points_in->data[4], 123);
mp_set (&points_in->data[5], 123123987);
mp_set (&points_in->data[6], 2);
mp_set (&points_in->data[7], 0);
mu_check (poly_fft(points_out, points_in, cfg, false) == SECSuccess);
mu_check (poly_fft(points_out2, points_out, cfg, true) == SECSuccess);
poly_fft_get_roots(roots, nPoints, cfg, false);
for (int i=0; i<nPoints; i++) {
mu_check (mp_cmp (&points_out2->data[i], &points_in->data[i]) == 0);
mp_set(&points_in->data[0], 3);
mp_set(&points_in->data[1], 8);
mp_set(&points_in->data[2], 7);
mp_set(&points_in->data[3], 9);
mp_set(&points_in->data[4], 123);
mp_set(&points_in->data[5], 123123987);
mp_set(&points_in->data[6], 2);
mp_set(&points_in->data[7], 0);
mu_check(poly_fft(points_out, points_in, cfg, false) == SECSuccess);
mu_check(poly_fft(points_out2, points_out, cfg, true) == SECSuccess);
for (int i = 0; i < nPoints; i++) {
mu_check(mp_cmp(&points_out2->data[i], &points_in->data[i]) == 0);
}
cleanup:
mu_check (rv == SECSuccess);
mu_check(rv == SECSuccess);
MPArray_clear (points_in);
MPArray_clear (points_out);
MPArray_clear (points_out2);
PrioConfig_clear (cfg);
MPArray_clear(points_in);
MPArray_clear(points_out);
MPArray_clear(points_out2);
PrioConfig_clear(cfg);
}

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

@ -1,38 +1,34 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <mpi.h>
#include "mutest.h"
void
mu_test_mpi__add (void)
void
mu_test_mpi__add(void)
{
mp_int a;
mp_int b;
mp_int c;
mu_check (mp_init (&a) == MP_OKAY);
mu_check (mp_init (&b) == MP_OKAY);
mu_check (mp_init (&c) == MP_OKAY);
mu_check(mp_init(&a) == MP_OKAY);
mu_check(mp_init(&b) == MP_OKAY);
mu_check(mp_init(&c) == MP_OKAY);
mp_set (&a, 10);
mp_set (&b, 7);
mp_add (&a, &b, &c);
mp_set(&a, 10);
mp_set(&b, 7);
mp_add(&a, &b, &c);
mp_set (&a, 17);
mu_check (mp_cmp (&a, &c) == 0);
mp_set(&a, 17);
mu_check(mp_cmp(&a, &c) == 0);
mp_clear (&a);
mp_clear (&b);
mp_clear (&c);
mp_clear(&a);
mp_clear(&b);
mp_clear(&c);
}

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

@ -14,7 +14,7 @@
*/
#include <mprio.h>
#include <stdio.h> /* printf(), fprintf() */
#include <stdio.h> /* printf(), fprintf() */
#include <string.h> /* strncmp() */
#include "mutest.h" /* MU_* constants, mu_print() */
@ -32,63 +32,59 @@ int mutest_passed_suites;
int mutest_skipped_suites;
int mutest_suite_failed;
/* globals for managing test cases */
const char* mutest_case_name;
int mutest_failed_cases;
int mutest_passed_cases;
int mutest_case_failed;
/* globals for managing checks */
int mutest_failed_checks;
int mutest_passed_checks;
/* verbosity level, see mutest.h */
int mutest_verbose_level = 1; /* exported for use in test suites */
/*
* only -v is supported right now, both "-v -v" and "-vv" are accepted for
* increasing the verbosity by 2.
*/
void parse_args(__attribute__((unused)) int argc, char* argv[]) {
while (*++argv) {
if (strncmp(*argv, "-v", 2) == 0) {
++mutest_verbose_level;
char* c = (*argv) + 1;
while (*++c) {
if (*c != 'v')
break;
++mutest_verbose_level;
}
}
}
void
parse_args(__attribute__((unused)) int argc, char* argv[])
{
while (*++argv) {
if (strncmp(*argv, "-v", 2) == 0) {
++mutest_verbose_level;
char* c = (*argv) + 1;
while (*++c) {
if (*c != 'v')
break;
++mutest_verbose_level;
}
}
}
}
int
main(int argc, char* argv[])
{
int main(int argc, char* argv[]) {
Prio_init();
parse_args(argc, argv);
Prio_init ();
parse_args(argc, argv);
mu_run_suites();
mu_run_suites();
Prio_clear();
Prio_clear ();
mu_print(MU_SUMMARY, "\n"
"Tests done:\n"
"\t%d test suite(s) passed, %d failed, %d skipped.\n"
"\t%d test case(s) passed, %d failed.\n"
"\t%d check(s) passed, %d failed.\n"
"\n",
mutest_passed_suites, mutest_failed_suites, mutest_skipped_suites,
mutest_passed_cases, mutest_failed_cases, mutest_passed_checks,
mutest_failed_checks);
mu_print(MU_SUMMARY, "\n"
"Tests done:\n"
"\t%d test suite(s) passed, %d failed, %d skipped.\n"
"\t%d test case(s) passed, %d failed.\n"
"\t%d check(s) passed, %d failed.\n"
"\n",
mutest_passed_suites, mutest_failed_suites,
mutest_skipped_suites,
mutest_passed_cases, mutest_failed_cases,
mutest_passed_checks, mutest_failed_checks);
return (mutest_failed_suites + mutest_skipped_suites) ? 1 : 0;
return (mutest_failed_suites + mutest_skipped_suites) ? 1 : 0;
}

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

@ -1,9 +1,9 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <mpi.h>
@ -13,22 +13,22 @@
#include "prio/util.h"
void
mu_test__prg_simple (void)
mu_test__prg_simple(void)
{
SECStatus rv = SECSuccess;
PrioPRGSeed key;
PRG prg = NULL;
P_CHECKC (PrioPRGSeed_randomize (&key));
P_CHECKA (prg = PRG_new (key));
P_CHECKC(PrioPRGSeed_randomize(&key));
P_CHECKA(prg = PRG_new(key));
cleanup:
mu_check (rv == SECSuccess);
PRG_clear (prg);
mu_check(rv == SECSuccess);
PRG_clear(prg);
}
void
mu_test__prg_repeat (void)
mu_test__prg_repeat(void)
{
SECStatus rv = SECSuccess;
const int buflen = 10000;
@ -42,69 +42,69 @@ mu_test__prg_repeat (void)
buf1[3] = 'a';
buf2[3] = 'b';
P_CHECKC (PrioPRGSeed_randomize (&key));
P_CHECKA (prg1 = PRG_new (key));
P_CHECKA (prg2 = PRG_new (key));
P_CHECKC(PrioPRGSeed_randomize(&key));
P_CHECKA(prg1 = PRG_new(key));
P_CHECKA(prg2 = PRG_new(key));
P_CHECKC (PRG_get_bytes (prg1, buf1, buflen));
P_CHECKC (PRG_get_bytes (prg2, buf2, buflen));
P_CHECKC(PRG_get_bytes(prg1, buf1, buflen));
P_CHECKC(PRG_get_bytes(prg2, buf2, buflen));
bool all_zero = true;
for (int i=0; i<buflen; i++) {
mu_check (buf1[i] == buf2[i]);
if (buf1[i]) all_zero = false;
for (int i = 0; i < buflen; i++) {
mu_check(buf1[i] == buf2[i]);
if (buf1[i])
all_zero = false;
}
mu_check (!all_zero);
mu_check(!all_zero);
cleanup:
mu_check (rv == SECSuccess);
PRG_clear (prg1);
PRG_clear (prg2);
mu_check(rv == SECSuccess);
PRG_clear(prg1);
PRG_clear(prg2);
}
void
mu_test__prg_repeat_int (void)
mu_test__prg_repeat_int(void)
{
SECStatus rv = SECSuccess;
const int tries = 10000;
mp_int max;
mp_int out1;
mp_int out2;
MP_DIGITS (&max) = NULL;
MP_DIGITS (&out1) = NULL;
MP_DIGITS (&out2) = NULL;
MP_DIGITS(&max) = NULL;
MP_DIGITS(&out1) = NULL;
MP_DIGITS(&out2) = NULL;
PrioPRGSeed key;
PRG prg1 = NULL;
PRG prg2 = NULL;
P_CHECKC (PrioPRGSeed_randomize (&key));
P_CHECKA (prg1 = PRG_new (key));
P_CHECKA (prg2 = PRG_new (key));
P_CHECKC(PrioPRGSeed_randomize(&key));
P_CHECKA(prg1 = PRG_new(key));
P_CHECKA(prg2 = PRG_new(key));
MP_CHECKC (mp_init (&max));
MP_CHECKC (mp_init (&out1));
MP_CHECKC (mp_init (&out2));
MP_CHECKC(mp_init(&max));
MP_CHECKC(mp_init(&out1));
MP_CHECKC(mp_init(&out2));
for (int i=0; i<tries; i++) {
mp_set (&max, i+1);
P_CHECKC (PRG_get_int (prg1, &out1, &max));
P_CHECKC (PRG_get_int (prg2, &out2, &max));
mu_check (mp_cmp (&out1, &out2) == 0);
for (int i = 0; i < tries; i++) {
mp_set(&max, i + 1);
P_CHECKC(PRG_get_int(prg1, &out1, &max));
P_CHECKC(PRG_get_int(prg2, &out2, &max));
mu_check(mp_cmp(&out1, &out2) == 0);
}
cleanup:
mu_check (rv == SECSuccess);
PRG_clear (prg1);
PRG_clear (prg2);
mp_clear (&max);
mp_clear (&out1);
mp_clear (&out2);
mu_check(rv == SECSuccess);
PRG_clear(prg1);
PRG_clear(prg2);
mp_clear(&max);
mp_clear(&out1);
mp_clear(&out2);
}
void
test_prg_once (int limit)
void
test_prg_once(int limit)
{
SECStatus rv = SECSuccess;
PrioPRGSeed key;
@ -112,67 +112,66 @@ test_prg_once (int limit)
mp_int out;
PRG prg = NULL;
MP_DIGITS (&max) = NULL;
MP_DIGITS (&out) = NULL;
MP_DIGITS(&max) = NULL;
MP_DIGITS(&out) = NULL;
P_CHECKC (PrioPRGSeed_randomize (&key));
P_CHECKA (prg = PRG_new (key));
P_CHECKC(PrioPRGSeed_randomize(&key));
P_CHECKA(prg = PRG_new(key));
MP_CHECKC (mp_init (&max));
MP_CHECKC (mp_init (&out));
MP_CHECKC(mp_init(&max));
MP_CHECKC(mp_init(&out));
mp_set (&max, limit);
mp_set(&max, limit);
P_CHECKC (PRG_get_int (prg, &out, &max));
mu_check (mp_cmp_d (&out, limit) == -1);
mu_check (mp_cmp_z (&out) > -1);
P_CHECKC(PRG_get_int(prg, &out, &max));
mu_check(mp_cmp_d(&out, limit) == -1);
mu_check(mp_cmp_z(&out) > -1);
cleanup:
mu_check (rv == SECSuccess);
mp_clear (&max);
mp_clear (&out);
PRG_clear (prg);
mu_check(rv == SECSuccess);
mp_clear(&max);
mp_clear(&out);
PRG_clear(prg);
}
void
mu_test_prg__multiple_of_8 (void)
void
mu_test_prg__multiple_of_8(void)
{
test_prg_once (256);
test_prg_once (256*256);
test_prg_once(256);
test_prg_once(256 * 256);
}
void
mu_test_prg__near_multiple_of_8 (void)
void
mu_test_prg__near_multiple_of_8(void)
{
test_prg_once (256+1);
test_prg_once (256*256+1);
test_prg_once(256 + 1);
test_prg_once(256 * 256 + 1);
}
void
mu_test_prg__odd (void)
void
mu_test_prg__odd(void)
{
test_prg_once (39);
test_prg_once (123);
test_prg_once (993123);
test_prg_once(39);
test_prg_once(123);
test_prg_once(993123);
}
void
mu_test_prg__large (void)
void
mu_test_prg__large(void)
{
test_prg_once (1231239933);
test_prg_once(1231239933);
}
void
mu_test_prg__bit(void)
void
mu_test_prg__bit(void)
{
test_prg_once (1);
test_prg_once(1);
for (int i = 0; i < 100; i++)
test_prg_once (2);
test_prg_once(2);
}
void
test_prg_distribution (int limit)
void
test_prg_distribution(int limit)
{
int bins[limit];
SECStatus rv = SECSuccess;
@ -181,67 +180,66 @@ test_prg_distribution (int limit)
mp_int out;
PRG prg = NULL;
MP_DIGITS (&max) = NULL;
MP_DIGITS (&out) = NULL;
MP_DIGITS(&max) = NULL;
MP_DIGITS(&out) = NULL;
P_CHECKC (PrioPRGSeed_randomize (&key));
P_CHECKA (prg = PRG_new (key));
P_CHECKC(PrioPRGSeed_randomize(&key));
P_CHECKA(prg = PRG_new(key));
MP_CHECKC (mp_init (&max));
MP_CHECKC (mp_init (&out));
MP_CHECKC(mp_init(&max));
MP_CHECKC(mp_init(&out));
mp_set (&max, limit);
mp_set(&max, limit);
for (int i = 0; i < limit; i++) {
bins[i] = 0;
}
for (int i = 0; i < limit*limit; i++) {
P_CHECKC (PRG_get_int (prg, &out, &max));
mu_check (mp_cmp_d (&out, limit) == -1);
mu_check (mp_cmp_z (&out) > -1);
for (int i = 0; i < limit * limit; i++) {
P_CHECKC(PRG_get_int(prg, &out, &max));
mu_check(mp_cmp_d(&out, limit) == -1);
mu_check(mp_cmp_z(&out) > -1);
unsigned char ival[2] = {0x00, 0x00};
MP_CHECKC (mp_to_fixlen_octets (&out, ival, 2));
if (ival[1] + 256*ival[0] < limit) {
bins[ival[1] + 256*ival[0]] += 1;
unsigned char ival[2] = { 0x00, 0x00 };
MP_CHECKC(mp_to_fixlen_octets(&out, ival, 2));
if (ival[1] + 256 * ival[0] < limit) {
bins[ival[1] + 256 * ival[0]] += 1;
} else {
mu_check (false);
mu_check(false);
}
}
for (int i = 0; i < limit; i++) {
mu_check (bins[i] > limit/2);
mu_check(bins[i] > limit / 2);
}
cleanup:
mu_check (rv == SECSuccess);
mp_clear (&max);
mp_clear (&out);
PRG_clear (prg);
mu_check(rv == SECSuccess);
mp_clear(&max);
mp_clear(&out);
PRG_clear(prg);
}
void
mu_test__prg_distribution123 (void)
void
mu_test__prg_distribution123(void)
{
test_prg_distribution(123);
}
void
mu_test__prg_distribution257 (void)
void
mu_test__prg_distribution257(void)
{
test_prg_distribution(257);
}
void
mu_test__prg_distribution259 (void)
void
mu_test__prg_distribution259(void)
{
test_prg_distribution(259);
}
void
test_prg_distribution_large (mp_int *max)
void
test_prg_distribution_large(mp_int* max)
{
const int limit = 16;
int bins[limit];
@ -250,57 +248,56 @@ test_prg_distribution_large (mp_int *max)
mp_int out;
PRG prg = NULL;
MP_DIGITS (&out) = NULL;
MP_DIGITS(&out) = NULL;
P_CHECKC (PrioPRGSeed_randomize (&key));
P_CHECKA (prg = PRG_new (key));
P_CHECKC(PrioPRGSeed_randomize(&key));
P_CHECKA(prg = PRG_new(key));
MP_CHECKC (mp_init (&out));
MP_CHECKC(mp_init(&out));
for (int i = 0; i < limit; i++) {
bins[i] = 0;
}
for (int i = 0; i < 100*limit*limit; i++) {
MP_CHECKC (PRG_get_int (prg, &out, max));
mu_check (mp_cmp (&out, max) == -1);
mu_check (mp_cmp_z (&out) > -1);
for (int i = 0; i < 100 * limit * limit; i++) {
MP_CHECKC(PRG_get_int(prg, &out, max));
mu_check(mp_cmp(&out, max) == -1);
mu_check(mp_cmp_z(&out) > -1);
unsigned long res;
MP_CHECKC (mp_mod_d (&out, limit, &res));
unsigned long res;
MP_CHECKC(mp_mod_d(&out, limit, &res));
bins[res] += 1;
}
for (int i = 0; i < limit; i++) {
mu_check (bins[i] > limit/2);
mu_check(bins[i] > limit / 2);
}
cleanup:
mu_check (rv == SECSuccess);
mp_clear (&out);
PRG_clear (prg);
mu_check(rv == SECSuccess);
mp_clear(&out);
PRG_clear(prg);
}
void
mu_test__prg_distribution_large (void)
void
mu_test__prg_distribution_large(void)
{
SECStatus rv = SECSuccess;
mp_int max;
MP_DIGITS (&max) = NULL;
MP_CHECKC (mp_init (&max));
MP_DIGITS(&max) = NULL;
MP_CHECKC(mp_init(&max));
char bytes[] = "FF1230985198451798EDC8123";
MP_CHECKC (mp_read_radix (&max, bytes, 16));
test_prg_distribution_large (&max);
MP_CHECKC(mp_read_radix(&max, bytes, 16));
test_prg_distribution_large(&max);
cleanup:
mu_check (rv == SECSuccess);
mp_clear (&max);
mu_check(rv == SECSuccess);
mp_clear(&max);
}
void
mu_test__prg_share_arr (void)
mu_test__prg_share_arr(void)
{
SECStatus rv = SECSuccess;
PrioConfig cfg = NULL;
@ -309,37 +306,36 @@ mu_test__prg_share_arr (void)
PRG prg = NULL;
PrioPRGSeed seed;
P_CHECKA (cfg = PrioConfig_newTest (72));
P_CHECKC (PrioPRGSeed_randomize (&seed));
P_CHECKA (arr = MPArray_new (10));
P_CHECKA (arr_share = MPArray_new (10));
P_CHECKA (prg = PRG_new (seed));
P_CHECKA(cfg = PrioConfig_newTest(72));
P_CHECKC(PrioPRGSeed_randomize(&seed));
P_CHECKA(arr = MPArray_new(10));
P_CHECKA(arr_share = MPArray_new(10));
P_CHECKA(prg = PRG_new(seed));
for (int i=0; i<10; i++) {
mp_set (&arr->data[i], i);
for (int i = 0; i < 10; i++) {
mp_set(&arr->data[i], i);
}
P_CHECKC (PRG_share_array (prg, arr_share, arr, cfg));
P_CHECKC(PRG_share_array(prg, arr_share, arr, cfg));
// Reset PRG
PRG_clear (prg);
P_CHECKA (prg = PRG_new (seed));
// Reset PRG
PRG_clear(prg);
P_CHECKA(prg = PRG_new(seed));
// Read pseudorandom values into arr
P_CHECKC (PRG_get_array (prg, arr, &cfg->modulus));
P_CHECKC(PRG_get_array(prg, arr, &cfg->modulus));
for (int i=0; i<10; i++) {
MP_CHECKC (mp_addmod (&arr->data[i], &arr_share->data[i],
&cfg->modulus, &arr->data[i]));
mu_check (mp_cmp_d (&arr->data[i], i) == 0);
for (int i = 0; i < 10; i++) {
MP_CHECKC(mp_addmod(&arr->data[i], &arr_share->data[i], &cfg->modulus,
&arr->data[i]));
mu_check(mp_cmp_d(&arr->data[i], i) == 0);
}
cleanup:
mu_check (rv == SECSuccess);
mu_check(rv == SECSuccess);
PRG_clear (prg);
MPArray_clear (arr);
MPArray_clear (arr_share);
PrioConfig_clear (cfg);
PRG_clear(prg);
MPArray_clear(arr);
MPArray_clear(arr_share);
PrioConfig_clear(cfg);
}

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

@ -1,9 +1,9 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <mpi.h>
@ -12,74 +12,73 @@
#include "prio/rand.h"
#include "prio/util.h"
void
mu_test__util_msb_mast (void)
void
mu_test__util_msb_mast(void)
{
mu_check (msb_mask (0x01) == 0x01);
mu_check (msb_mask (0x02) == 0x03);
mu_check (msb_mask (0x0C) == 0x0F);
mu_check (msb_mask (0x1C) == 0x1F);
mu_check (msb_mask (0xFF) == 0xFF);
mu_check(msb_mask(0x01) == 0x01);
mu_check(msb_mask(0x02) == 0x03);
mu_check(msb_mask(0x0C) == 0x0F);
mu_check(msb_mask(0x1C) == 0x1F);
mu_check(msb_mask(0xFF) == 0xFF);
}
void
test_rand_once (int limit)
void
test_rand_once(int limit)
{
mp_int max;
mp_int out;
mu_check (mp_init (&max) == MP_OKAY);
mu_check (mp_init (&out) == MP_OKAY);
mu_check(mp_init(&max) == MP_OKAY);
mu_check(mp_init(&out) == MP_OKAY);
mp_set (&max, limit);
mp_set(&max, limit);
mu_check (rand_int (&out, &max) == MP_OKAY);
mu_check (mp_cmp_d (&out, limit) == -1);
mu_check (mp_cmp_z (&out) > -1);
mu_check(rand_int(&out, &max) == MP_OKAY);
mu_check(mp_cmp_d(&out, limit) == -1);
mu_check(mp_cmp_z(&out) > -1);
mp_clear (&max);
mp_clear (&out);
mp_clear(&max);
mp_clear(&out);
}
void
mu_test_rand__multiple_of_8 (void)
void
mu_test_rand__multiple_of_8(void)
{
test_rand_once (256);
test_rand_once (256*256);
test_rand_once(256);
test_rand_once(256 * 256);
}
void
mu_test_rand__near_multiple_of_8 (void)
void
mu_test_rand__near_multiple_of_8(void)
{
test_rand_once (256+1);
test_rand_once (256*256+1);
test_rand_once(256 + 1);
test_rand_once(256 * 256 + 1);
}
void
mu_test_rand__odd (void)
void
mu_test_rand__odd(void)
{
test_rand_once (39);
test_rand_once (123);
test_rand_once (993123);
test_rand_once(39);
test_rand_once(123);
test_rand_once(993123);
}
void
mu_test_rand__large (void)
void
mu_test_rand__large(void)
{
test_rand_once (1231239933);
test_rand_once(1231239933);
}
void
mu_test_rand__bit(void)
void
mu_test_rand__bit(void)
{
test_rand_once (1);
test_rand_once(1);
for (int i = 0; i < 100; i++)
test_rand_once (2);
test_rand_once(2);
}
void
test_rand_distribution (int limit)
void
test_rand_distribution(int limit)
{
SECStatus rv = SECSuccess;
int bins[limit];
@ -87,108 +86,107 @@ test_rand_distribution (int limit)
mp_int max;
mp_int out;
MP_DIGITS (&max) = NULL;
MP_DIGITS (&out) = NULL;
MP_DIGITS(&max) = NULL;
MP_DIGITS(&out) = NULL;
MP_CHECKC (mp_init (&max));
MP_CHECKC (mp_init (&out));
MP_CHECKC(mp_init(&max));
MP_CHECKC(mp_init(&out));
mp_set (&max, limit);
mp_set(&max, limit);
for (int i = 0; i < limit; i++) {
bins[i] = 0;
}
for (int i = 0; i < limit*limit; i++) {
mu_check (rand_int (&out, &max) == MP_OKAY);
mu_check (mp_cmp_d (&out, limit) == -1);
mu_check (mp_cmp_z (&out) > -1);
for (int i = 0; i < limit * limit; i++) {
mu_check(rand_int(&out, &max) == MP_OKAY);
mu_check(mp_cmp_d(&out, limit) == -1);
mu_check(mp_cmp_z(&out) > -1);
unsigned char ival[2] = {0x00, 0x00};
MP_CHECKC (mp_to_fixlen_octets (&out, ival, 2));
if (ival[1] + 256*ival[0] < limit) {
bins[ival[1] + 256*ival[0]] += 1;
unsigned char ival[2] = { 0x00, 0x00 };
MP_CHECKC(mp_to_fixlen_octets(&out, ival, 2));
if (ival[1] + 256 * ival[0] < limit) {
bins[ival[1] + 256 * ival[0]] += 1;
} else {
mu_check (false);
mu_check(false);
}
}
for (int i = 0; i < limit; i++) {
mu_check (bins[i] > limit/2);
mu_check(bins[i] > limit / 2);
}
cleanup:
mu_check (rv == SECSuccess);
mp_clear (&max);
mp_clear (&out);
mu_check(rv == SECSuccess);
mp_clear(&max);
mp_clear(&out);
}
void
mu_test__rand_distribution123 (void)
void
mu_test__rand_distribution123(void)
{
test_rand_distribution(123);
}
void
mu_test__rand_distribution257 (void)
void
mu_test__rand_distribution257(void)
{
test_rand_distribution(257);
}
void
mu_test__rand_distribution259 (void)
void
mu_test__rand_distribution259(void)
{
test_rand_distribution(259);
}
void
test_rand_distribution_large (mp_int *max)
void
test_rand_distribution_large(mp_int* max)
{
SECStatus rv = SECSuccess;
int limit = 16;
int bins[limit];
mp_int out;
MP_DIGITS (&out) = NULL;
MP_CHECKC (mp_init (&out));
MP_DIGITS(&out) = NULL;
MP_CHECKC(mp_init(&out));
for (int i = 0; i < limit; i++) {
bins[i] = 0;
}
for (int i = 0; i < 100*limit*limit; i++) {
MP_CHECKC (rand_int (&out, max));
mu_check (mp_cmp (&out, max) == -1);
mu_check (mp_cmp_z (&out) > -1);
for (int i = 0; i < 100 * limit * limit; i++) {
MP_CHECKC(rand_int(&out, max));
mu_check(mp_cmp(&out, max) == -1);
mu_check(mp_cmp_z(&out) > -1);
unsigned long res;
MP_CHECKC (mp_mod_d (&out, limit, &res));
unsigned long res;
MP_CHECKC(mp_mod_d(&out, limit, &res));
bins[res] += 1;
}
for (int i = 0; i < limit; i++) {
mu_check (bins[i] > limit/2);
mu_check(bins[i] > limit / 2);
}
cleanup:
mu_check (rv == SECSuccess);
mp_clear (&out);
mu_check(rv == SECSuccess);
mp_clear(&out);
}
void
mu_test__rand_distribution_large (void)
void
mu_test__rand_distribution_large(void)
{
SECStatus rv = SECSuccess;
mp_int max;
MP_DIGITS (&max) = NULL;
MP_CHECKC (mp_init (&max));
MP_DIGITS(&max) = NULL;
MP_CHECKC(mp_init(&max));
char bytes[] = "FF1230985198451798EDC8123";
MP_CHECKC (mp_read_radix (&max, bytes, 16));
test_rand_distribution_large (&max);
MP_CHECKC(mp_read_radix(&max, bytes, 16));
test_rand_distribution_large(&max);
cleanup:
mu_check (rv == SECSuccess);
mp_clear (&max);
mu_check(rv == SECSuccess);
mp_clear(&max);
}

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

@ -1,9 +1,9 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <mprio.h>
@ -18,25 +18,26 @@
#include "prio/util.h"
SECStatus
gen_client_packets (const_PrioConfig cfg, PrioPacketClient pA, PrioPacketClient pB)
gen_client_packets(const_PrioConfig cfg, PrioPacketClient pA,
PrioPacketClient pB)
{
SECStatus rv = SECSuccess;
const int ndata = cfg->num_data_fields;
bool data_items[ndata];
for (int i=0; i < ndata; i++) {
for (int i = 0; i < ndata; i++) {
data_items[i] = (i % 3 == 1) || (i % 5 == 3);
}
P_CHECKC (PrioPacketClient_set_data (cfg, data_items, pA, pB));
P_CHECKC(PrioPacketClient_set_data(cfg, data_items, pA, pB));
cleanup:
return rv;
}
void serial_client (int bad)
void
serial_client(int bad)
{
SECStatus rv = SECSuccess;
PrioConfig cfg = NULL;
@ -46,274 +47,285 @@ void serial_client (int bad)
PrioPacketClient qA = NULL;
PrioPacketClient qB = NULL;
const unsigned char *batch_id1 = (unsigned char *)"my_test_prio_batch1";
const unsigned char *batch_id2 = (unsigned char *)"my_test_prio_batch2";
const unsigned int batch_id_len = strlen ((char *)batch_id1);
const unsigned char* batch_id1 = (unsigned char*)"my_test_prio_batch1";
const unsigned char* batch_id2 = (unsigned char*)"my_test_prio_batch2";
const unsigned int batch_id_len = strlen((char*)batch_id1);
msgpack_sbuffer sbufA, sbufB;
msgpack_packer pkA, pkB;
msgpack_unpacker upkA, upkB;
msgpack_sbuffer_init (&sbufA);
msgpack_packer_init (&pkA, &sbufA, msgpack_sbuffer_write);
msgpack_sbuffer_init(&sbufA);
msgpack_packer_init(&pkA, &sbufA, msgpack_sbuffer_write);
msgpack_sbuffer_init (&sbufB);
msgpack_packer_init (&pkB, &sbufB, msgpack_sbuffer_write);
msgpack_sbuffer_init(&sbufB);
msgpack_packer_init(&pkB, &sbufB, msgpack_sbuffer_write);
P_CHECKA (cfg = PrioConfig_new (100, NULL, NULL, batch_id1, batch_id_len));
P_CHECKA (cfg2 = PrioConfig_new (100, NULL, NULL, batch_id2, batch_id_len));
P_CHECKA (pA = PrioPacketClient_new (cfg, PRIO_SERVER_A));
P_CHECKA (pB = PrioPacketClient_new (cfg, PRIO_SERVER_B));
P_CHECKA (qA = PrioPacketClient_new (cfg, PRIO_SERVER_A));
P_CHECKA (qB = PrioPacketClient_new (cfg, PRIO_SERVER_B));
P_CHECKA(cfg = PrioConfig_new(100, NULL, NULL, batch_id1, batch_id_len));
P_CHECKA(cfg2 = PrioConfig_new(100, NULL, NULL, batch_id2, batch_id_len));
P_CHECKA(pA = PrioPacketClient_new(cfg, PRIO_SERVER_A));
P_CHECKA(pB = PrioPacketClient_new(cfg, PRIO_SERVER_B));
P_CHECKA(qA = PrioPacketClient_new(cfg, PRIO_SERVER_A));
P_CHECKA(qB = PrioPacketClient_new(cfg, PRIO_SERVER_B));
P_CHECKC (gen_client_packets (cfg, pA, pB));
P_CHECKC(gen_client_packets(cfg, pA, pB));
P_CHECKC (serial_write_packet_client (&pkA, pA, cfg));
P_CHECKC (serial_write_packet_client (&pkB, pB, cfg));
P_CHECKC(serial_write_packet_client(&pkA, pA, cfg));
P_CHECKC(serial_write_packet_client(&pkB, pB, cfg));
if (bad == 1) {
sbufA.size = 1;
}
if (bad == 2) {
memset (sbufA.data, 0, sbufA.size);
memset(sbufA.data, 0, sbufA.size);
}
const int size_a = sbufA.size;
const int size_b = sbufB.size;
P_CHECKCB (msgpack_unpacker_init (&upkA, 0));
P_CHECKCB (msgpack_unpacker_init (&upkB, 0));
P_CHECKCB(msgpack_unpacker_init(&upkA, 0));
P_CHECKCB(msgpack_unpacker_init(&upkB, 0));
P_CHECKCB (msgpack_unpacker_reserve_buffer (&upkA, size_a));
P_CHECKCB (msgpack_unpacker_reserve_buffer (&upkB, size_b));
P_CHECKCB(msgpack_unpacker_reserve_buffer(&upkA, size_a));
P_CHECKCB(msgpack_unpacker_reserve_buffer(&upkB, size_b));
memcpy (msgpack_unpacker_buffer (&upkA), sbufA.data, size_a);
memcpy (msgpack_unpacker_buffer (&upkB), sbufB.data, size_b);
memcpy(msgpack_unpacker_buffer(&upkA), sbufA.data, size_a);
memcpy(msgpack_unpacker_buffer(&upkB), sbufB.data, size_b);
msgpack_unpacker_buffer_consumed (&upkA, size_a);
msgpack_unpacker_buffer_consumed (&upkB, size_b);
msgpack_unpacker_buffer_consumed(&upkA, size_a);
msgpack_unpacker_buffer_consumed(&upkB, size_b);
P_CHECKC (serial_read_packet_client (&upkA, qA, cfg));
P_CHECKC (serial_read_packet_client (&upkB, qB, (bad == 3) ? cfg2 : cfg));
P_CHECKC(serial_read_packet_client(&upkA, qA, cfg));
P_CHECKC(serial_read_packet_client(&upkB, qB, (bad == 3) ? cfg2 : cfg));
if (!bad) {
mu_check (PrioPacketClient_areEqual (pA, qA));
mu_check (PrioPacketClient_areEqual (pB, qB));
mu_check (!PrioPacketClient_areEqual (pB, qA));
mu_check (!PrioPacketClient_areEqual (pA, qB));
mu_check(PrioPacketClient_areEqual(pA, qA));
mu_check(PrioPacketClient_areEqual(pB, qB));
mu_check(!PrioPacketClient_areEqual(pB, qA));
mu_check(!PrioPacketClient_areEqual(pA, qB));
}
cleanup:
PrioPacketClient_clear (pA);
PrioPacketClient_clear (pB);
PrioPacketClient_clear (qA);
PrioPacketClient_clear (qB);
PrioConfig_clear (cfg);
PrioConfig_clear (cfg2);
msgpack_sbuffer_destroy (&sbufA);
msgpack_sbuffer_destroy (&sbufB);
msgpack_unpacker_destroy (&upkA);
msgpack_unpacker_destroy (&upkB);
mu_check (bad ? rv == SECFailure : rv == SECSuccess);
cleanup:
PrioPacketClient_clear(pA);
PrioPacketClient_clear(pB);
PrioPacketClient_clear(qA);
PrioPacketClient_clear(qB);
PrioConfig_clear(cfg);
PrioConfig_clear(cfg2);
msgpack_sbuffer_destroy(&sbufA);
msgpack_sbuffer_destroy(&sbufB);
msgpack_unpacker_destroy(&upkA);
msgpack_unpacker_destroy(&upkB);
mu_check(bad ? rv == SECFailure : rv == SECSuccess);
}
void mu_test__serial_client (void)
void
mu_test__serial_client(void)
{
serial_client (0);
serial_client(0);
}
void mu_test__serial_client_bad1 (void)
void
mu_test__serial_client_bad1(void)
{
serial_client (1);
serial_client(1);
}
void mu_test__serial_client_bad2 (void)
void
mu_test__serial_client_bad2(void)
{
serial_client (2);
serial_client(2);
}
void mu_test__serial_client_bad3 (void)
void
mu_test__serial_client_bad3(void)
{
serial_client (3);
serial_client(3);
}
void test_verify1 (int bad)
void
test_verify1(int bad)
{
SECStatus rv = SECSuccess;
PrioPacketVerify1 v1 = NULL;
PrioPacketVerify1 v2 = NULL;
PrioConfig cfg = NULL;
P_CHECKA (cfg = PrioConfig_newTest (1));
P_CHECKA (v1 = PrioPacketVerify1_new());
P_CHECKA (v2 = PrioPacketVerify1_new());
mp_set (&v1->share_d, 4);
mp_set (&v1->share_e, 10);
P_CHECKA(cfg = PrioConfig_newTest(1));
P_CHECKA(v1 = PrioPacketVerify1_new());
P_CHECKA(v2 = PrioPacketVerify1_new());
mp_set(&v1->share_d, 4);
mp_set(&v1->share_e, 10);
msgpack_sbuffer sbuf;
msgpack_packer pk;
msgpack_unpacker upk;
msgpack_sbuffer_init (&sbuf);
msgpack_packer_init (&pk, &sbuf, msgpack_sbuffer_write);
msgpack_sbuffer_init(&sbuf);
msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write);
P_CHECKC (PrioPacketVerify1_write (v1, &pk));
P_CHECKC(PrioPacketVerify1_write(v1, &pk));
if (bad == 1) {
mp_set (&cfg->modulus, 6);
mp_set(&cfg->modulus, 6);
}
P_CHECKCB (msgpack_unpacker_init (&upk, 0));
P_CHECKCB (msgpack_unpacker_reserve_buffer (&upk, sbuf.size));
memcpy (msgpack_unpacker_buffer (&upk), sbuf.data, sbuf.size);
msgpack_unpacker_buffer_consumed (&upk, sbuf.size);
P_CHECKCB(msgpack_unpacker_init(&upk, 0));
P_CHECKCB(msgpack_unpacker_reserve_buffer(&upk, sbuf.size));
memcpy(msgpack_unpacker_buffer(&upk), sbuf.data, sbuf.size);
msgpack_unpacker_buffer_consumed(&upk, sbuf.size);
P_CHECKC (PrioPacketVerify1_read (v2, &upk, cfg));
P_CHECKC(PrioPacketVerify1_read(v2, &upk, cfg));
mu_check (!mp_cmp (&v1->share_d, &v2->share_d));
mu_check (!mp_cmp (&v1->share_e, &v2->share_e));
mu_check (!mp_cmp_d (&v2->share_d, 4));
mu_check (!mp_cmp_d (&v2->share_e, 10));
mu_check(!mp_cmp(&v1->share_d, &v2->share_d));
mu_check(!mp_cmp(&v1->share_e, &v2->share_e));
mu_check(!mp_cmp_d(&v2->share_d, 4));
mu_check(!mp_cmp_d(&v2->share_e, 10));
cleanup:
mu_check (bad ? rv == SECFailure : rv == SECSuccess);
PrioConfig_clear (cfg);
PrioPacketVerify1_clear (v1);
PrioPacketVerify1_clear (v2);
msgpack_unpacker_destroy (&upk);
msgpack_sbuffer_destroy (&sbuf);
mu_check(bad ? rv == SECFailure : rv == SECSuccess);
PrioConfig_clear(cfg);
PrioPacketVerify1_clear(v1);
PrioPacketVerify1_clear(v2);
msgpack_unpacker_destroy(&upk);
msgpack_sbuffer_destroy(&sbuf);
}
void mu_test_verify1_good (void)
void
mu_test_verify1_good(void)
{
test_verify1 (0);
test_verify1(0);
}
void mu_test_verify1_bad (void)
void
mu_test_verify1_bad(void)
{
test_verify1 (1);
test_verify1(1);
}
void test_verify2 (int bad)
void
test_verify2(int bad)
{
SECStatus rv = SECSuccess;
PrioPacketVerify2 v1 = NULL;
PrioPacketVerify2 v2 = NULL;
PrioConfig cfg = NULL;
P_CHECKA (cfg = PrioConfig_newTest (1));
P_CHECKA (v1 = PrioPacketVerify2_new());
P_CHECKA (v2 = PrioPacketVerify2_new());
mp_set (&v1->share_out, 4);
P_CHECKA(cfg = PrioConfig_newTest(1));
P_CHECKA(v1 = PrioPacketVerify2_new());
P_CHECKA(v2 = PrioPacketVerify2_new());
mp_set(&v1->share_out, 4);
msgpack_sbuffer sbuf;
msgpack_packer pk;
msgpack_unpacker upk;
msgpack_sbuffer_init (&sbuf);
msgpack_packer_init (&pk, &sbuf, msgpack_sbuffer_write);
msgpack_sbuffer_init(&sbuf);
msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write);
P_CHECKC (PrioPacketVerify2_write (v1, &pk));
P_CHECKC(PrioPacketVerify2_write(v1, &pk));
if (bad == 1) {
mp_set (&cfg->modulus, 4);
mp_set(&cfg->modulus, 4);
}
P_CHECKCB (msgpack_unpacker_init (&upk, 0));
P_CHECKCB (msgpack_unpacker_reserve_buffer (&upk, sbuf.size));
memcpy (msgpack_unpacker_buffer (&upk), sbuf.data, sbuf.size);
msgpack_unpacker_buffer_consumed (&upk, sbuf.size);
P_CHECKCB(msgpack_unpacker_init(&upk, 0));
P_CHECKCB(msgpack_unpacker_reserve_buffer(&upk, sbuf.size));
memcpy(msgpack_unpacker_buffer(&upk), sbuf.data, sbuf.size);
msgpack_unpacker_buffer_consumed(&upk, sbuf.size);
P_CHECKC (PrioPacketVerify2_read (v2, &upk, cfg));
P_CHECKC(PrioPacketVerify2_read(v2, &upk, cfg));
mu_check (!mp_cmp (&v1->share_out, &v2->share_out));
mu_check (!mp_cmp_d (&v2->share_out, 4));
mu_check(!mp_cmp(&v1->share_out, &v2->share_out));
mu_check(!mp_cmp_d(&v2->share_out, 4));
cleanup:
mu_check (bad ? rv == SECFailure : rv == SECSuccess);
PrioConfig_clear (cfg);
PrioPacketVerify2_clear (v1);
PrioPacketVerify2_clear (v2);
msgpack_unpacker_destroy (&upk);
msgpack_sbuffer_destroy (&sbuf);
mu_check(bad ? rv == SECFailure : rv == SECSuccess);
PrioConfig_clear(cfg);
PrioPacketVerify2_clear(v1);
PrioPacketVerify2_clear(v2);
msgpack_unpacker_destroy(&upk);
msgpack_sbuffer_destroy(&sbuf);
}
void mu_test_verify2_good (void)
void
mu_test_verify2_good(void)
{
test_verify2 (0);
test_verify2(0);
}
void mu_test_verify2_bad (void)
void
mu_test_verify2_bad(void)
{
test_verify2 (1);
test_verify2(1);
}
void test_total_share (int bad)
void
test_total_share(int bad)
{
SECStatus rv = SECSuccess;
PrioTotalShare t1 = NULL;
PrioTotalShare t2 = NULL;
PrioConfig cfg = NULL;
P_CHECKA (cfg = PrioConfig_newTest ((bad == 2 ? 4 : 3)));
P_CHECKA (t1 = PrioTotalShare_new ());
P_CHECKA (t2 = PrioTotalShare_new ());
P_CHECKA(cfg = PrioConfig_newTest((bad == 2 ? 4 : 3)));
P_CHECKA(t1 = PrioTotalShare_new());
P_CHECKA(t2 = PrioTotalShare_new());
t1->idx = PRIO_SERVER_A;
P_CHECKC (MPArray_resize (t1->data_shares, 3));
P_CHECKC(MPArray_resize(t1->data_shares, 3));
mp_set (&t1->data_shares->data[0], 10);
mp_set (&t1->data_shares->data[1], 20);
mp_set (&t1->data_shares->data[2], 30);
mp_set(&t1->data_shares->data[0], 10);
mp_set(&t1->data_shares->data[1], 20);
mp_set(&t1->data_shares->data[2], 30);
msgpack_sbuffer sbuf;
msgpack_packer pk;
msgpack_unpacker upk;
msgpack_sbuffer_init (&sbuf);
msgpack_packer_init (&pk, &sbuf, msgpack_sbuffer_write);
msgpack_sbuffer_init(&sbuf);
msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write);
P_CHECKC (PrioTotalShare_write (t1, &pk));
P_CHECKC(PrioTotalShare_write(t1, &pk));
if (bad == 1) {
mp_set (&cfg->modulus, 4);
mp_set(&cfg->modulus, 4);
}
P_CHECKCB (msgpack_unpacker_init (&upk, 0));
P_CHECKCB (msgpack_unpacker_reserve_buffer (&upk, sbuf.size));
memcpy (msgpack_unpacker_buffer (&upk), sbuf.data, sbuf.size);
msgpack_unpacker_buffer_consumed (&upk, sbuf.size);
P_CHECKCB(msgpack_unpacker_init(&upk, 0));
P_CHECKCB(msgpack_unpacker_reserve_buffer(&upk, sbuf.size));
memcpy(msgpack_unpacker_buffer(&upk), sbuf.data, sbuf.size);
msgpack_unpacker_buffer_consumed(&upk, sbuf.size);
P_CHECKC (PrioTotalShare_read (t2, &upk, cfg));
P_CHECKC(PrioTotalShare_read(t2, &upk, cfg));
mu_check (t1->idx == t2->idx);
mu_check (MPArray_areEqual (t1->data_shares, t2->data_shares));
mu_check(t1->idx == t2->idx);
mu_check(MPArray_areEqual(t1->data_shares, t2->data_shares));
cleanup:
mu_check (bad ? rv == SECFailure : rv == SECSuccess);
PrioConfig_clear (cfg);
PrioTotalShare_clear (t1);
PrioTotalShare_clear (t2);
msgpack_unpacker_destroy (&upk);
msgpack_sbuffer_destroy (&sbuf);
mu_check(bad ? rv == SECFailure : rv == SECSuccess);
PrioConfig_clear(cfg);
PrioTotalShare_clear(t1);
PrioTotalShare_clear(t2);
msgpack_unpacker_destroy(&upk);
msgpack_sbuffer_destroy(&sbuf);
}
void mu_test_total_good (void)
void
mu_test_total_good(void)
{
test_total_share (0);
test_total_share(0);
}
void mu_test_total_bad1 (void)
void
mu_test_total_bad1(void)
{
test_total_share (1);
test_total_share(1);
}
void mu_test_total_bad2 (void)
void
mu_test_total_bad2(void)
{
test_total_share (2);
test_total_share(2);
}

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

@ -1,9 +1,9 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <mpi.h>
@ -11,44 +11,45 @@
#include "mutest.h"
#include "prio/client.h"
#include "prio/server.h"
#include "prio/server.c"
#include "prio/server.h"
void mu_test__eval_poly (void)
void
mu_test__eval_poly(void)
{
SECStatus rv = SECSuccess;
PrioConfig cfg = NULL;
MPArray coeffs = NULL;
mp_int eval_at, out;
MP_DIGITS (&eval_at) = NULL;
MP_DIGITS (&out) = NULL;
MP_DIGITS(&eval_at) = NULL;
MP_DIGITS(&out) = NULL;
P_CHECKA (cfg = PrioConfig_newTest (54));
P_CHECKA (coeffs = MPArray_new (3));
P_CHECKA(cfg = PrioConfig_newTest(54));
P_CHECKA(coeffs = MPArray_new(3));
mp_set (&coeffs->data[0], 2);
mp_set (&coeffs->data[1], 8);
mp_set (&coeffs->data[2], 3);
mp_set(&coeffs->data[0], 2);
mp_set(&coeffs->data[1], 8);
mp_set(&coeffs->data[2], 3);
MP_CHECKC (mp_init (&eval_at));
MP_CHECKC (mp_init (&out));
mp_set (&eval_at, 7);
MP_CHECKC(mp_init(&eval_at));
MP_CHECKC(mp_init(&out));
mp_set(&eval_at, 7);
const int val = 3*7*7 + 8*7 + 2;
mu_check (poly_eval (&out, coeffs, &eval_at, cfg) == SECSuccess);
mu_check (mp_cmp_d (&out, val) == 0);
const int val = 3 * 7 * 7 + 8 * 7 + 2;
mu_check(poly_eval(&out, coeffs, &eval_at, cfg) == SECSuccess);
mu_check(mp_cmp_d(&out, val) == 0);
cleanup:
mu_check (rv == SECSuccess);
mp_clear (&out);
mp_clear (&eval_at);
MPArray_clear (coeffs);
PrioConfig_clear (cfg);
mu_check(rv == SECSuccess);
mp_clear(&out);
mp_clear(&eval_at);
MPArray_clear(coeffs);
PrioConfig_clear(cfg);
}
void
mu_test__verify_new (void)
void
mu_test__verify_new(void)
{
SECStatus rv = SECSuccess;
PublicKey pkA = NULL;
@ -60,94 +61,93 @@ mu_test__verify_new (void)
PrioServer sB = NULL;
PrioVerifier vA = NULL;
PrioVerifier vB = NULL;
unsigned char *for_a = NULL;
unsigned char *for_b = NULL;
unsigned char* for_a = NULL;
unsigned char* for_b = NULL;
mp_int fR, gR, hR;
MP_DIGITS (&fR) = NULL;
MP_DIGITS (&gR) = NULL;
MP_DIGITS (&hR) = NULL;
MP_DIGITS(&fR) = NULL;
MP_DIGITS(&gR) = NULL;
MP_DIGITS(&hR) = NULL;
PrioPRGSeed seed;
P_CHECKC (PrioPRGSeed_randomize (&seed));
P_CHECKC(PrioPRGSeed_randomize(&seed));
P_CHECKC (Keypair_new (&skA, &pkA));
P_CHECKC (Keypair_new (&skB, &pkB));
P_CHECKA (cfg = PrioConfig_new (214, pkA, pkB,
(unsigned char *)"testbatch", 9));
P_CHECKC(Keypair_new(&skA, &pkA));
P_CHECKC(Keypair_new(&skB, &pkB));
P_CHECKA(cfg = PrioConfig_new(214, pkA, pkB, (unsigned char*)"testbatch", 9));
const int ndata = PrioConfig_numDataFields (cfg);
const int ndata = PrioConfig_numDataFields(cfg);
{
bool data_items[ndata];
for (int i=0; i < ndata; i++) {
// Arbitrary data
data_items[i] = (i % 3 == 1) || (i % 5 == 3);
}
bool data_items[ndata];
for (int i = 0; i < ndata; i++) {
// Arbitrary data
data_items[i] = (i % 3 == 1) || (i % 5 == 3);
}
P_CHECKA (sA = PrioServer_new (cfg, 0, skA, seed));
P_CHECKA (sB = PrioServer_new (cfg, 1, skB, seed));
P_CHECKA(sA = PrioServer_new(cfg, 0, skA, seed));
P_CHECKA(sB = PrioServer_new(cfg, 1, skB, seed));
unsigned int aLen, bLen;
P_CHECKC (PrioClient_encode (cfg, data_items, &for_a, &aLen, &for_b, &bLen));
unsigned int aLen, bLen;
P_CHECKC(PrioClient_encode(cfg, data_items, &for_a, &aLen, &for_b, &bLen));
MP_CHECKC (mp_init (&fR));
MP_CHECKC (mp_init (&gR));
MP_CHECKC (mp_init (&hR));
MP_CHECKC(mp_init(&fR));
MP_CHECKC(mp_init(&gR));
MP_CHECKC(mp_init(&hR));
P_CHECKA (vA = PrioVerifier_new (sA));
P_CHECKA (vB = PrioVerifier_new (sB));
P_CHECKC (PrioVerifier_set_data (vA, for_a, aLen));
P_CHECKC (PrioVerifier_set_data (vB, for_b, bLen));
P_CHECKA(vA = PrioVerifier_new(sA));
P_CHECKA(vB = PrioVerifier_new(sB));
P_CHECKC(PrioVerifier_set_data(vA, for_a, aLen));
P_CHECKC(PrioVerifier_set_data(vB, for_b, bLen));
PrioPacketClient pA = vA->clientp;
PrioPacketClient pB = vB->clientp;
MP_CHECKC (mp_addmod (&pA->f0_share, &pB->f0_share, &cfg->modulus, &fR));
MP_CHECKC (mp_addmod (&pA->g0_share, &pB->g0_share, &cfg->modulus, &gR));
MP_CHECKC (mp_addmod (&pA->h0_share, &pB->h0_share, &cfg->modulus, &hR));
PrioPacketClient pA = vA->clientp;
PrioPacketClient pB = vB->clientp;
MP_CHECKC(mp_addmod(&pA->f0_share, &pB->f0_share, &cfg->modulus, &fR));
MP_CHECKC(mp_addmod(&pA->g0_share, &pB->g0_share, &cfg->modulus, &gR));
MP_CHECKC(mp_addmod(&pA->h0_share, &pB->h0_share, &cfg->modulus, &hR));
MP_CHECKC (mp_mulmod (&fR, &gR, &cfg->modulus, &fR));
mu_check (mp_cmp (&fR, &hR) == 0);
MP_CHECKC(mp_mulmod(&fR, &gR, &cfg->modulus, &fR));
mu_check(mp_cmp(&fR, &hR) == 0);
MP_CHECKC(mp_addmod(&vA->share_fR, &vB->share_fR, &cfg->modulus, &fR));
MP_CHECKC(mp_addmod(&vA->share_gR, &vB->share_gR, &cfg->modulus, &gR));
MP_CHECKC(mp_addmod(&vA->share_hR, &vB->share_hR, &cfg->modulus, &hR));
MP_CHECKC (mp_addmod (&vA->share_fR, &vB->share_fR, &cfg->modulus, &fR));
MP_CHECKC (mp_addmod (&vA->share_gR, &vB->share_gR, &cfg->modulus, &gR));
MP_CHECKC (mp_addmod (&vA->share_hR, &vB->share_hR, &cfg->modulus, &hR));
MP_CHECKC(mp_mulmod(&fR, &gR, &cfg->modulus, &fR));
MP_CHECKC (mp_mulmod (&fR, &gR, &cfg->modulus, &fR));
//puts ("fR");
//mp_print (&fR, stdout);
//puts ("hR");
//mp_print (&hR, stdout);
mu_check (mp_cmp (&fR, &hR) == 0);
// puts ("fR");
// mp_print (&fR, stdout);
// puts ("hR");
// mp_print (&hR, stdout);
mu_check(mp_cmp(&fR, &hR) == 0);
}
cleanup:
mu_check (rv == SECSuccess);
mu_check(rv == SECSuccess);
if (for_a) free (for_a);
if (for_b) free (for_b);
if (for_a)
free(for_a);
if (for_b)
free(for_b);
mp_clear (&fR);
mp_clear (&gR);
mp_clear (&hR);
mp_clear(&fR);
mp_clear(&gR);
mp_clear(&hR);
PrioVerifier_clear (vA);
PrioVerifier_clear (vB);
PrioVerifier_clear(vA);
PrioVerifier_clear(vB);
PrioServer_clear (sA);
PrioServer_clear (sB);
PrioConfig_clear (cfg);
PublicKey_clear (pkA);
PublicKey_clear (pkB);
PrivateKey_clear (skA);
PrivateKey_clear (skB);
PrioServer_clear(sA);
PrioServer_clear(sB);
PrioConfig_clear(cfg);
PublicKey_clear(pkA);
PublicKey_clear(pkB);
PrivateKey_clear(skA);
PrivateKey_clear(skB);
}
void
verify_full (int tweak)
verify_full(int tweak)
{
SECStatus rv = SECSuccess;
PublicKey pkA = NULL;
@ -163,136 +163,138 @@ verify_full (int tweak)
PrioPacketVerify1 p1B = NULL;
PrioPacketVerify2 p2A = NULL;
PrioPacketVerify2 p2B = NULL;
unsigned char *for_a = NULL;
unsigned char *for_b = NULL;
unsigned char* for_a = NULL;
unsigned char* for_b = NULL;
mp_int fR, gR, hR;
MP_DIGITS (&fR) = NULL;
MP_DIGITS (&gR) = NULL;
MP_DIGITS (&hR) = NULL;
MP_DIGITS(&fR) = NULL;
MP_DIGITS(&gR) = NULL;
MP_DIGITS(&hR) = NULL;
PrioPRGSeed seed;
P_CHECKC (PrioPRGSeed_randomize (&seed));
P_CHECKC(PrioPRGSeed_randomize(&seed));
P_CHECKC (Keypair_new (&skA, &pkA));
P_CHECKC (Keypair_new (&skB, &pkB));
P_CHECKA (cfg = PrioConfig_new (47, pkA, pkB, (unsigned char *)"test4", 5));
P_CHECKC(Keypair_new(&skA, &pkA));
P_CHECKC(Keypair_new(&skB, &pkB));
P_CHECKA(cfg = PrioConfig_new(47, pkA, pkB, (unsigned char*)"test4", 5));
const int ndata = PrioConfig_numDataFields (cfg);
const int ndata = PrioConfig_numDataFields(cfg);
{
bool data_items[ndata];
for (int i=0; i < ndata; i++) {
// Arbitrary data
data_items[i] = (i % 3 == 1) || (i % 5 == 3);
}
bool data_items[ndata];
for (int i = 0; i < ndata; i++) {
// Arbitrary data
data_items[i] = (i % 3 == 1) || (i % 5 == 3);
}
P_CHECKA (sA = PrioServer_new (cfg, 0, skA, seed));
P_CHECKA (sB = PrioServer_new (cfg, 1, skB, seed));
P_CHECKA(sA = PrioServer_new(cfg, 0, skA, seed));
P_CHECKA(sB = PrioServer_new(cfg, 1, skB, seed));
unsigned int aLen, bLen;
P_CHECKC (PrioClient_encode (cfg, data_items, &for_a, &aLen, &for_b, &bLen));
unsigned int aLen, bLen;
P_CHECKC(PrioClient_encode(cfg, data_items, &for_a, &aLen, &for_b, &bLen));
if (tweak == 5) {
for_a[3] = 3;
for_a[4] = 4;
}
if (tweak == 5) {
for_a[3] = 3;
for_a[4] = 4;
}
P_CHECKA (vA = PrioVerifier_new (sA));
P_CHECKA (vB = PrioVerifier_new (sB));
P_CHECKC (PrioVerifier_set_data (vA, for_a, aLen));
P_CHECKC (PrioVerifier_set_data (vB, for_b, bLen));
P_CHECKA(vA = PrioVerifier_new(sA));
P_CHECKA(vB = PrioVerifier_new(sB));
P_CHECKC(PrioVerifier_set_data(vA, for_a, aLen));
P_CHECKC(PrioVerifier_set_data(vB, for_b, bLen));
if (tweak == 3) {
mp_add_d (&vA->share_fR, 1, &vA->share_fR);
}
if (tweak == 3) {
mp_add_d(&vA->share_fR, 1, &vA->share_fR);
}
if (tweak == 4) {
mp_add_d (&vB->share_gR, 1, &vB->share_gR);
}
if (tweak == 4) {
mp_add_d(&vB->share_gR, 1, &vB->share_gR);
}
P_CHECKA (p1A = PrioPacketVerify1_new ());
P_CHECKA (p1B = PrioPacketVerify1_new ());
P_CHECKA(p1A = PrioPacketVerify1_new());
P_CHECKA(p1B = PrioPacketVerify1_new());
P_CHECKC (PrioPacketVerify1_set_data (p1A, vA));
P_CHECKC (PrioPacketVerify1_set_data (p1B, vB));
P_CHECKC(PrioPacketVerify1_set_data(p1A, vA));
P_CHECKC(PrioPacketVerify1_set_data(p1B, vB));
if (tweak == 1) {
mp_add_d (&p1B->share_d, 1, &p1B->share_d);
}
if (tweak == 1) {
mp_add_d(&p1B->share_d, 1, &p1B->share_d);
}
P_CHECKA (p2A = PrioPacketVerify2_new ());
P_CHECKA (p2B = PrioPacketVerify2_new ());
P_CHECKC (PrioPacketVerify2_set_data (p2A, vA, p1A, p1B));
P_CHECKC (PrioPacketVerify2_set_data (p2B, vB, p1A, p1B));
P_CHECKA(p2A = PrioPacketVerify2_new());
P_CHECKA(p2B = PrioPacketVerify2_new());
P_CHECKC(PrioPacketVerify2_set_data(p2A, vA, p1A, p1B));
P_CHECKC(PrioPacketVerify2_set_data(p2B, vB, p1A, p1B));
if (tweak == 2) {
mp_add_d (&p2A->share_out, 1, &p2B->share_out);
}
if (tweak == 2) {
mp_add_d(&p2A->share_out, 1, &p2B->share_out);
}
int shouldBe = tweak ? SECFailure : SECSuccess;
mu_check (PrioVerifier_isValid (vA, p2A, p2B) == shouldBe);
mu_check (PrioVerifier_isValid (vB, p2A, p2B) == shouldBe);
int shouldBe = tweak ? SECFailure : SECSuccess;
mu_check(PrioVerifier_isValid(vA, p2A, p2B) == shouldBe);
mu_check(PrioVerifier_isValid(vB, p2A, p2B) == shouldBe);
}
cleanup:
if (!tweak) {
mu_check (rv == SECSuccess);
mu_check(rv == SECSuccess);
}
if (for_a) free (for_a);
if (for_b) free (for_b);
if (for_a)
free(for_a);
if (for_b)
free(for_b);
PrioPacketVerify2_clear (p2A);
PrioPacketVerify2_clear (p2B);
PrioPacketVerify2_clear(p2A);
PrioPacketVerify2_clear(p2B);
PrioPacketVerify1_clear (p1A);
PrioPacketVerify1_clear (p1B);
PrioPacketVerify1_clear(p1A);
PrioPacketVerify1_clear(p1B);
PrioVerifier_clear (vA);
PrioVerifier_clear (vB);
PrioVerifier_clear(vA);
PrioVerifier_clear(vB);
PrioServer_clear (sA);
PrioServer_clear (sB);
PrioConfig_clear (cfg);
PrioServer_clear(sA);
PrioServer_clear(sB);
PrioConfig_clear(cfg);
PublicKey_clear (pkA);
PublicKey_clear (pkB);
PrivateKey_clear (skA);
PrivateKey_clear (skB);
PublicKey_clear(pkA);
PublicKey_clear(pkB);
PrivateKey_clear(skA);
PrivateKey_clear(skB);
}
void
mu_test__verify_full_good (void)
void
mu_test__verify_full_good(void)
{
verify_full (0);
verify_full(0);
}
void
mu_test__verify_full_bad1 (void)
void
mu_test__verify_full_bad1(void)
{
verify_full (1);
verify_full(1);
}
void
mu_test__verify_full_bad2 (void)
void
mu_test__verify_full_bad2(void)
{
verify_full (2);
verify_full(2);
}
void
mu_test__verify_full_bad3 (void)
void
mu_test__verify_full_bad3(void)
{
verify_full (3);
verify_full(3);
}
void
mu_test__verify_full_bad4 (void)
void
mu_test__verify_full_bad4(void)
{
verify_full (4);
verify_full(4);
}
void
mu_test__verify_full_bad5 (void)
void
mu_test__verify_full_bad5(void)
{
verify_full (5);
verify_full(5);
}

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

@ -1,91 +1,91 @@
/*
* Copyright (c) 2018, Henry Corrigan-Gibbs
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <mpi.h>
#include <mprio.h>
#include "mutest.h"
#include "prio/client.h"
#include "prio/config.h"
#include "prio/mparray.h"
#include "prio/share.h"
#include "prio/util.h"
#include "mutest.h"
void
mu_test_share (void)
void
mu_test_share(void)
{
SECStatus rv = SECSuccess;
PrioConfig cfg = NULL;
mp_int a, b, c;
BeaverTriple t1 = NULL, t2 = NULL;
MP_DIGITS (&a) = NULL;
MP_DIGITS (&b) = NULL;
MP_DIGITS (&c) = NULL;
MP_DIGITS(&a) = NULL;
MP_DIGITS(&b) = NULL;
MP_DIGITS(&c) = NULL;
P_CHECKA (cfg = PrioConfig_newTest (93));
P_CHECKA (t1 = BeaverTriple_new ());
P_CHECKA (t2 = BeaverTriple_new ());
P_CHECKA(cfg = PrioConfig_newTest(93));
P_CHECKA(t1 = BeaverTriple_new());
P_CHECKA(t2 = BeaverTriple_new());
mu_check (BeaverTriple_set_rand (cfg, t1, t2) == SECSuccess);
mu_check(BeaverTriple_set_rand(cfg, t1, t2) == SECSuccess);
MP_CHECKC (mp_init (&a));
MP_CHECKC (mp_init (&b));
MP_CHECKC (mp_init (&c));
MP_CHECKC(mp_init(&a));
MP_CHECKC(mp_init(&b));
MP_CHECKC(mp_init(&c));
mu_check (mp_addmod (&t1->a, &t2->a, &cfg->modulus, &a) == MP_OKAY);
mu_check (mp_addmod (&t1->b, &t2->b, &cfg->modulus, &b) == MP_OKAY);
mu_check (mp_addmod (&t1->c, &t2->c, &cfg->modulus, &c) == MP_OKAY);
mu_check (mp_mulmod (&a, &b, &cfg->modulus, &a) == MP_OKAY);
mu_check (mp_cmp (&a, &c) == 0);
mu_check(mp_addmod(&t1->a, &t2->a, &cfg->modulus, &a) == MP_OKAY);
mu_check(mp_addmod(&t1->b, &t2->b, &cfg->modulus, &b) == MP_OKAY);
mu_check(mp_addmod(&t1->c, &t2->c, &cfg->modulus, &c) == MP_OKAY);
mu_check(mp_mulmod(&a, &b, &cfg->modulus, &a) == MP_OKAY);
mu_check(mp_cmp(&a, &c) == 0);
cleanup:
mu_check (rv == SECSuccess);
mp_clear (&a);
mp_clear (&b);
mp_clear (&c);
mu_check(rv == SECSuccess);
mp_clear(&a);
mp_clear(&b);
mp_clear(&c);
PrioConfig_clear (cfg);
BeaverTriple_clear (t1);
BeaverTriple_clear (t2);
PrioConfig_clear(cfg);
BeaverTriple_clear(t1);
BeaverTriple_clear(t2);
}
void
mu_test_arr (void)
void
mu_test_arr(void)
{
SECStatus rv = SECSuccess;
MPArray arr = NULL;
MPArray arr2 = NULL;
P_CHECKA (arr = MPArray_new (10));
P_CHECKA (arr2 = MPArray_new (7));
P_CHECKA(arr = MPArray_new(10));
P_CHECKA(arr2 = MPArray_new(7));
for (int i=0; i<10; i++) {
mp_set (&arr->data[i], i);
for (int i = 0; i < 10; i++) {
mp_set(&arr->data[i], i);
}
P_CHECKC (MPArray_resize (arr, 15));
for (int i=10; i<15; i++) {
mu_check (mp_cmp_d (&arr->data[i], 0) == 0);
mp_set (&arr->data[i], i);
P_CHECKC(MPArray_resize(arr, 15));
for (int i = 10; i < 15; i++) {
mu_check(mp_cmp_d(&arr->data[i], 0) == 0);
mp_set(&arr->data[i], i);
}
P_CHECKC (MPArray_resize (arr, 7));
for (int i=10; i<7; i++) {
mu_check (mp_cmp_d (&arr->data[i], i) == 0);
P_CHECKC(MPArray_resize(arr, 7));
for (int i = 10; i < 7; i++) {
mu_check(mp_cmp_d(&arr->data[i], i) == 0);
}
P_CHECKC (MPArray_copy (arr2, arr));
for (int i=10; i<7; i++) {
mu_check (mp_cmp (&arr->data[i], &arr2->data[i]) == 0);
P_CHECKC(MPArray_copy(arr2, arr));
for (int i = 10; i < 7; i++) {
mu_check(mp_cmp(&arr->data[i], &arr2->data[i]) == 0);
}
cleanup:
mu_check (rv == SECSuccess);
MPArray_clear (arr);
MPArray_clear (arr2);
mu_check(rv == SECSuccess);
MPArray_clear(arr);
MPArray_clear(arr2);
}

62
scripts/clang-format.sh Executable file
Просмотреть файл

@ -0,0 +1,62 @@
#!/bin/sh
#
# Originally from Godot Engine project (MIT License)
#
die() {
echo " *** ERROR: " $*
exit 1
}
CLANG_FORMAT_VERSION="clang-format version 3.9"
if which clang-format-3.9 > /dev/null; then
alias clang-format=clang-format-3.9
elif which clang-format > /dev/null; then
case "$(clang-format --version)" in
"$CLANG_FORMAT_VERSION"*)
;;
*)
die "clang-format 3.9 required"
;;
esac
else
die "$CLANG_FORMAT_VERSION required"
fi
if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
# Check the whole commit range against $TRAVIS_BRANCH, the base merge branch
# We could use $TRAVIS_COMMIT_RANGE but it doesn't play well with force pushes
RANGE="$(git rev-parse $TRAVIS_BRANCH) HEAD"
else
# Test only the last commit
RANGE=HEAD
fi
FILES=$(git diff-tree --no-commit-id --name-only -r $RANGE | grep -v mpi/ | grep -E "\.(c|h|cpp|hpp|cc|hh|cxx|m|mm|inc|java|glsl)$")
echo "Checking files:\n$FILES"
# create a random filename to store our generated patch
prefix="static-check-clang-format"
suffix="$(date +%s)"
patch="/tmp/$prefix-$suffix.patch"
for file in $FILES; do
clang-format -style=Mozilla "$file" | \
diff -u "$file" - | \
sed -e "1s|--- |--- a/|" -e "2s|+++ -|+++ b/$file|" >> "$patch"
done
# if no patch has been generated all is ok, clean up the file stub and exit
if [ ! -s "$patch" ] ; then
printf "Files in this commit comply with the clang-format rules.\n"
rm -f "$patch"
exit 0
fi
# a patch has been created, notify the user and exit
printf "\n*** The following differences were found between the code to commit "
printf "and the clang-format rules:\n\n"
cat "$patch"
printf "\n*** Aborting, please fix your commit(s) with 'git commit --amend' or 'git rebase -i <hash>'\n"
exit 1