Hash batchID with shared secret to get PRG seed. (#104)

This commit is contained in:
Henry Corrigan-Gibbs 2020-07-27 19:49:30 -04:00 коммит произвёл GitHub
Родитель 951cbd2b04
Коммит 80647f4887
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
5 изменённых файлов: 127 добавлений и 18 удалений

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

@ -218,7 +218,7 @@ PrioPacketClient_set_data(const_PrioConfig cfg,
return SECFailure;
P_CHECKC(PrioPRGSeed_randomize(&pB->shares.B.seed));
P_CHECKA(prgB = PRG_new(pB->shares.B.seed));
P_CHECKA(prgB = PRG_new(cfg, 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));

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

@ -9,6 +9,7 @@
#include <blapit.h>
#include <mprio.h>
#include <pk11pub.h>
#include <sechash.h>
#include <string.h>
#include "prg.h"
@ -29,8 +30,44 @@ PrioPRGSeed_randomize(PrioPRGSeed* key)
return rand_bytes((unsigned char*)key, PRG_SEED_LENGTH);
}
SECStatus
prg_seed_from_config_and_shared_secret(PrioPRGSeed key_out,
const_PrioConfig cfg,
const PrioPRGSeed shared_secret)
{
SECStatus rv = SECSuccess;
HASHContext* ctx = NULL;
const HASH_HashType hashType = HASH_GetHashTypeByOidTag(SEC_OID_SHA256);
P_CHECKA(ctx = HASH_Create(hashType));
HASH_Begin(ctx);
// Hash the shared_secret with the batch ID to
// get the PRG seed. We might also want to
// hash `num_data_fields` here, but since the
// batch ID should be distinct per batch, this
// should be enough.
HASH_Update(ctx, shared_secret, PRG_SEED_LENGTH);
HASH_Update(ctx, cfg->batch_id, cfg->batch_id_len);
unsigned int len;
HASH_End(ctx, key_out, &len, PRG_SEED_LENGTH);
// Ensure that hash routine wrote out the
// correct number of bytes.
P_CHECKCB(len == PRG_SEED_LENGTH);
cleanup:
if (ctx) {
HASH_Destroy(ctx);
}
return rv;
}
PRG
PRG_new(const PrioPRGSeed key_in)
PRG_new(const_PrioConfig cfg, const PrioPRGSeed shared_secret)
{
PRG prg = malloc(sizeof(struct prg));
if (!prg)
@ -44,9 +81,10 @@ PRG_new(const PrioPRGSeed key_in)
P_CHECKA(prg->slot = PK11_GetInternalSlot());
// Create a mutable copy of the key.
// Create the per-batch PRG key from the shared
// secret and the PrioConfig.
PrioPRGSeed key_mut;
memcpy(key_mut, key_in, PRG_SEED_LENGTH);
prg_seed_from_config_and_shared_secret(key_mut, cfg, shared_secret);
SECItem keyItem = { siBuffer, key_mut, PRG_SEED_LENGTH };

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

@ -22,7 +22,7 @@ typedef const struct prg* const_PRG;
* Initialize or destroy a pseudo-random generator.
*/
PRG
PRG_new(const PrioPRGSeed key);
PRG_new(const_PrioConfig cfg, const PrioPRGSeed shared_secret);
void
PRG_clear(PRG prg);

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

@ -42,7 +42,7 @@ PrioServer_new(const_PrioConfig cfg,
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->prg = PRG_new(s->cfg, seed));
cleanup:
if (rv != SECSuccess) {
@ -426,7 +426,7 @@ PrioVerifier_set_data(PrioVerifier v,
}
if (v->s->idx == PRIO_SERVER_B) {
P_CHECKA(prgB = PRG_new(v->clientp->shares.B.seed));
P_CHECKA(prgB = PRG_new(v->s->cfg, 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));
}

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

@ -19,13 +19,17 @@ mu_test__prg_simple(void)
SECStatus rv = SECSuccess;
PrioPRGSeed key;
PRG prg = NULL;
PrioConfig cfg = NULL;
PT_CHECKA(cfg = PrioConfig_newTest(1));
PT_CHECKC(PrioPRGSeed_randomize(&key));
PT_CHECKA(prg = PRG_new(key));
PT_CHECKA(prg = PRG_new(cfg, key));
cleanup:
mu_check(rv == SECSuccess);
PRG_clear(prg);
PrioConfig_clear(cfg);
}
void
@ -39,10 +43,13 @@ mu_test__prg_repeat(void)
PrioPRGSeed key;
PRG prg1 = NULL;
PRG prg2 = NULL;
PrioConfig cfg = NULL;
PT_CHECKA(cfg = PrioConfig_newTest(1));
PT_CHECKC(PrioPRGSeed_randomize(&key));
PT_CHECKA(prg1 = PRG_new(key));
PT_CHECKA(prg2 = PRG_new(key));
PT_CHECKA(prg1 = PRG_new(cfg, key));
PT_CHECKA(prg2 = PRG_new(cfg, key));
PT_CHECKA(buf1 = calloc(buflen, sizeof(unsigned char)));
PT_CHECKA(buf2 = calloc(buflen, sizeof(unsigned char)));
@ -68,6 +75,7 @@ cleanup:
free(buf2);
PRG_clear(prg1);
PRG_clear(prg2);
PrioConfig_clear(cfg);
}
void
@ -85,10 +93,13 @@ mu_test__prg_repeat_int(void)
PrioPRGSeed key;
PRG prg1 = NULL;
PRG prg2 = NULL;
PrioConfig cfg = NULL;
PT_CHECKA(cfg = PrioConfig_newTest(1));
PT_CHECKC(PrioPRGSeed_randomize(&key));
PT_CHECKA(prg1 = PRG_new(key));
PT_CHECKA(prg2 = PRG_new(key));
PT_CHECKA(prg1 = PRG_new(cfg, key));
PT_CHECKA(prg2 = PRG_new(cfg, key));
MPT_CHECKC(mp_init(&max));
MPT_CHECKC(mp_init(&out1));
@ -108,6 +119,7 @@ cleanup:
mp_clear(&max);
mp_clear(&out1);
mp_clear(&out2);
PrioConfig_clear(cfg);
}
void
@ -121,9 +133,12 @@ test_prg_once(int limit)
MP_DIGITS(&max) = NULL;
MP_DIGITS(&out) = NULL;
PrioConfig cfg = NULL;
PT_CHECKA(cfg = PrioConfig_newTest(1));
PT_CHECKC(PrioPRGSeed_randomize(&key));
PT_CHECKA(prg = PRG_new(key));
PT_CHECKA(prg = PRG_new(cfg, key));
MPT_CHECKC(mp_init(&max));
MPT_CHECKC(mp_init(&out));
@ -139,6 +154,7 @@ cleanup:
mp_clear(&max);
mp_clear(&out);
PRG_clear(prg);
PrioConfig_clear(cfg);
}
void
@ -189,9 +205,12 @@ test_prg_distribution(int limit)
MP_DIGITS(&max) = NULL;
MP_DIGITS(&out) = NULL;
PrioConfig cfg = NULL;
PT_CHECKA(cfg = PrioConfig_newTest(1));
PT_CHECKC(PrioPRGSeed_randomize(&key));
PT_CHECKA(prg = PRG_new(key));
PT_CHECKA(prg = PRG_new(cfg, key));
PT_CHECKA(bins = calloc(limit, sizeof(int)));
MPT_CHECKC(mp_init(&max));
@ -228,6 +247,7 @@ cleanup:
mp_clear(&max);
mp_clear(&out);
PRG_clear(prg);
PrioConfig_clear(cfg);
}
void
@ -259,9 +279,12 @@ test_prg_distribution_large(mp_int* max)
PRG prg = NULL;
MP_DIGITS(&out) = NULL;
PrioConfig cfg = NULL;
PT_CHECKA(cfg = PrioConfig_newTest(1));
PT_CHECKC(PrioPRGSeed_randomize(&key));
PT_CHECKA(prg = PRG_new(key));
PT_CHECKA(prg = PRG_new(cfg, key));
PT_CHECKA(bins = calloc(limit, sizeof(int)));
MPT_CHECKC(mp_init(&out));
@ -290,6 +313,7 @@ cleanup:
free(bins);
mp_clear(&out);
PRG_clear(prg);
PrioConfig_clear(cfg);
}
void
@ -323,7 +347,7 @@ mu_test__prg_share_arr(void)
PT_CHECKC(PrioPRGSeed_randomize(&seed));
PT_CHECKA(arr = MPArray_new(10));
PT_CHECKA(arr_share = MPArray_new(10));
PT_CHECKA(prg = PRG_new(seed));
PT_CHECKA(prg = PRG_new(cfg, seed));
for (int i = 0; i < 10; i++) {
mp_set(&arr->data[i], i);
@ -333,7 +357,7 @@ mu_test__prg_share_arr(void)
// Reset PRG
PRG_clear(prg);
PT_CHECKA(prg = PRG_new(seed));
PT_CHECKA(prg = PRG_new(cfg, seed));
// Read pseudorandom values into arr
PT_CHECKC(PRG_get_array(prg, arr, &cfg->modulus));
@ -366,9 +390,12 @@ test_prg_range_once(int bot, int limit)
MP_DIGITS(&lower) = NULL;
MP_DIGITS(&max) = NULL;
MP_DIGITS(&out) = NULL;
PrioConfig cfg = NULL;
PT_CHECKA(cfg = PrioConfig_newTest(1));
PT_CHECKC(PrioPRGSeed_randomize(&key));
PT_CHECKA(prg = PRG_new(key));
PT_CHECKA(prg = PRG_new(cfg, key));
MPT_CHECKC(mp_init(&max));
MPT_CHECKC(mp_init(&out));
@ -390,6 +417,7 @@ cleanup:
mp_clear(&max);
mp_clear(&out);
PRG_clear(prg);
PrioConfig_clear(cfg);
}
void
@ -413,3 +441,46 @@ mu_test_prg_range__odd(void)
test_prg_range_once(7, 123);
test_prg_range_once(99000, 993123);
}
void
mu_test_prg_uses_batch_id(void)
{
SECStatus rv = SECSuccess;
PrioPRGSeed key;
mp_int out1;
mp_int out2;
PRG prg1 = NULL;
PRG prg2 = NULL;
MP_DIGITS(&out1) = NULL;
MP_DIGITS(&out2) = NULL;
PrioConfig cfg1 = NULL;
PrioConfig cfg2 = NULL;
PT_CHECKA(cfg1 = PrioConfig_newTest(1));
PT_CHECKA(cfg2 = PrioConfig_newTest(1));
// Two batch IDs are different. Check that
// PRG outputs are actually different.
cfg2->batch_id[0] = '\0';
PT_CHECKC(PrioPRGSeed_randomize(&key));
PT_CHECKA(prg1 = PRG_new(cfg1, key));
PT_CHECKA(prg2 = PRG_new(cfg2, key));
MPT_CHECKC(mp_init(&out1));
MPT_CHECKC(mp_init(&out2));
PT_CHECKC(PRG_get_int(prg1, &out1, &cfg1->modulus));
PT_CHECKC(PRG_get_int(prg2, &out2, &cfg1->modulus));
mu_check(mp_cmp(&out1, &out2) != 0);
cleanup:
mu_check(rv == SECSuccess);
mp_clear(&out1);
mp_clear(&out2);
PRG_clear(prg1);
PRG_clear(prg2);
PrioConfig_clear(cfg1);
PrioConfig_clear(cfg2);
}