зеркало из https://github.com/mozilla/libprio.git
* 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:
Родитель
4899697586
Коммит
ded8b1054b
|
@ -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]));
|
||||
}
|
||||
|
||||
|
|
191
include/mprio.h
191
include/mprio.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
|
||||
|
@ -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__ */
|
||||
|
||||
|
|
155
pclient/main.c
155
pclient/main.c
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
295
prio/client.c
295
prio/client.c
|
@ -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__ */
|
||||
|
||||
|
|
119
prio/config.c
119
prio/config.c
|
@ -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__ */
|
||||
|
||||
|
|
10
prio/debug.h
10
prio/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/.
|
||||
*/
|
||||
|
||||
#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__ */
|
||||
|
||||
|
|
287
prio/encrypt.c
287
prio/encrypt.c
|
@ -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 (¶mItem, ¶m, nonce, eph_pub, aadBuf);
|
||||
set_gcm_params(¶mItem, ¶m, 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, ¶mItem, output + offset,
|
||||
outputLen, maxOutputLen - offset, input, inputLen));
|
||||
P_CHECKC(PK11_Encrypt(aes_key, CKM_AES_GCM, ¶mItem, 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 (¶mItem, ¶m, nonce, eph_pub, aad_buf);
|
||||
|
||||
P_CHECKC (derive_dh_secret (&aes_key, privkey, eph_pub));
|
||||
set_gcm_params(¶mItem, ¶m, 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, ¶mItem, output,
|
||||
outputLen, maxOutputLen, input + offset, inputLen - offset));
|
||||
P_CHECKC(PK11_Decrypt(aes_key, CKM_AES_GCM, ¶mItem, 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__ */
|
||||
|
||||
|
|
112
prio/mparray.c
112
prio/mparray.c
|
@ -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__ */
|
||||
|
||||
|
|
16395
prio/params.h
16395
prio/params.h
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
144
prio/poly.c
144
prio/poly.c
|
@ -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;
|
||||
}
|
||||
|
|
33
prio/poly.h
33
prio/poly.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 _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
|
||||
|
|
127
prio/prg.c
127
prio/prg.c
|
@ -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 *)¶m, sizeof(CK_AES_CTR_PARAMS)};
|
||||
CK_AES_CTR_PARAMS param = { 128, {} };
|
||||
SECItem paramItem = { siBuffer, (void*)¶m, 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, ¶mItem));
|
||||
P_CHECKA(prg->ctx = PK11_CreateContextBySymKey(cipher, CKA_ENCRYPT, prg->key,
|
||||
¶mItem));
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
|
|
36
prio/prg.h
36
prio/prg.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 __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__ */
|
||||
|
||||
|
|
87
prio/rand.c
87
prio/rand.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
26
prio/rand.h
26
prio/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/.
|
||||
*/
|
||||
|
||||
#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__ */
|
||||
|
||||
|
|
376
prio/serial.c
376
prio/serial.c
|
@ -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__ */
|
||||
|
||||
|
|
387
prio/server.c
387
prio/server.c
|
@ -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__ */
|
||||
|
||||
|
|
80
prio/share.c
80
prio/share.c
|
@ -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);
|
||||
}
|
||||
|
|
30
prio/share.h
30
prio/share.h
|
@ -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__ */
|
||||
|
||||
|
|
101
prio/util.h
101
prio/util.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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
166
ptest/fft_test.c
166
ptest/fft_test.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
310
ptest/prg_test.c
310
ptest/prg_test.c
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
Загрузка…
Ссылка в новой задаче