diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
commit | 43a97878ce14b72f0981164f87f2e35e14151312 (patch) | |
tree | 620249daf56c0258faa40cbdcf9cfba06de2a846 /third_party/prio/include | |
parent | Initial commit. (diff) | |
download | firefox-43a97878ce14b72f0981164f87f2e35e14151312.tar.xz firefox-43a97878ce14b72f0981164f87f2e35e14151312.zip |
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/prio/include')
-rw-r--r-- | third_party/prio/include/mprio.h | 304 |
1 files changed, 304 insertions, 0 deletions
diff --git a/third_party/prio/include/mprio.h b/third_party/prio/include/mprio.h new file mode 100644 index 0000000000..7a53703e1d --- /dev/null +++ b/third_party/prio/include/mprio.h @@ -0,0 +1,304 @@ +/* + * 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/. */ + +#ifndef __PRIO_H__ +#define __PRIO_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <blapit.h> +#include <msgpack.h> +#include <pk11pub.h> +#include <seccomon.h> +#include <stdbool.h> +#include <stddef.h> + +/* Seed for a pseudo-random generator (PRG). */ +#define PRG_SEED_LENGTH AES_128_KEY_LENGTH +typedef unsigned char PrioPRGSeed[PRG_SEED_LENGTH]; + +/* Length of a raw curve25519 public key, in bytes. */ +#define CURVE25519_KEY_LEN 32 + +/* Length of a hex-encoded curve25519 public key, in bytes. */ +#define CURVE25519_KEY_LEN_HEX 64 + +/* + * Type for each of the two servers. + */ +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_server* PrioServer; +typedef const struct prio_server* const_PrioServer; + +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_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 SECKEYPublicKey* PublicKey; +typedef const SECKEYPublicKey* const_PublicKey; + +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(); +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 + * (2) the modulus we use for modular arithmetic. + * The default configuration uses an 87-bit modulus. + * + * The value `nFields` must be in the range `0 < nFields <= max`, where `max` + * is the value returned by the function `PrioConfig_maxDataFields()` below. + * + * The `batch_id` field specifies which "batch" of aggregate statistics we are + * computing. For example, if the aggregate statistics are computed every 24 + * hours, the `batch_id` might be set to an encoding of the date. The clients + * and servers must all use the same `batch_id` for each run of the protocol. + * 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 + * `PrioConfig_new` returns. + */ +PrioConfig PrioConfig_new(int nFields, PublicKey serverA, PublicKey serverB, + const unsigned char* batchId, + unsigned int batchIdLen); +void PrioConfig_clear(PrioConfig cfg); +int PrioConfig_numDataFields(const_PrioConfig cfg); + +/* + * Return the maximum number of data fields that the implementation supports. + */ +int PrioConfig_maxDataFields(void); + +/* + * 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 nFields); + +/* + * 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); + +/* + * Import a new curve25519 public/private key from the raw bytes given. When + * importing a private key, you must pass in the corresponding public key as + * well. The byte arrays given as input should be of length + * `CURVE25519_KEY_LEN`. + * + * These functions will allocate a new `PublicKey`/`PrivateKey` object, which + * the caller must free using `PublicKey_clear`/`PrivateKey_clear`. + */ +SECStatus PublicKey_import(PublicKey* pk, const unsigned char* data, + unsigned int dataLen); +SECStatus PrivateKey_import(PrivateKey* sk, const unsigned char* privData, + unsigned int privDataLen, + const unsigned char* pubData, + unsigned int pubDataLen); + +/* + * Import a new curve25519 public/private key from a hex string that contains + * only the characters 0-9a-fA-F. + * + * The hex strings passed in must each be of length `CURVE25519_KEY_LEN_HEX`. + * These functions will allocate a new `PublicKey`/`PrivateKey` object, which + * the caller must free using `PublicKey_clear`/`PrivateKey_clear`. + */ +SECStatus PublicKey_import_hex(PublicKey* pk, const unsigned char* hexData, + unsigned int dataLen); +SECStatus PrivateKey_import_hex(PrivateKey* sk, + const unsigned char* privHexData, + unsigned int privDataLen, + const unsigned char* pubHexData, + unsigned int pubDataLen); + +/* + * Export a curve25519 key as a raw byte-array. + * + * The output buffer `data` must have length exactly `CURVE25519_KEY_LEN`. + */ +SECStatus PublicKey_export(const_PublicKey pk, unsigned char* data, + unsigned int dataLen); +SECStatus PrivateKey_export(PrivateKey sk, unsigned char* data, + unsigned int dataLen); + +/* + * Export a curve25519 key as a NULL-terminated hex string. + * + * The output buffer `data` must have length exactly `CURVE25519_KEY_LEN_HEX + + * 1`. + */ +SECStatus PublicKey_export_hex(const_PublicKey pk, unsigned char* data, + unsigned int dataLen); +SECStatus PrivateKey_export_hex(PrivateKey sk, unsigned char* data, + unsigned int dataLen); + +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 + * the config. It then encodes the data for servers A and B into a + * 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** forServerA, unsigned int* aLen, + unsigned char** forServerB, 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); + +/* + * 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 serverIdx, + PrivateKey serverPriv, + const PrioPRGSeed serverSharedSecret); +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); + +/* + * 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); + +/* + * 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); + +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); + +/* + * 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); + +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); + +/* + * 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); + +/* + * 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 + * above before aggregating any client data. + */ +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. + */ +PrioTotalShare PrioTotalShare_new(void); +void PrioTotalShare_clear(PrioTotalShare t); + +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); + +/* + * Read the output data into an array of unsigned longs. You should + * be sure that each data value can fit into a single `unsigned long` + * and that the pointer `output` points to a buffer large enough to + * store one long per data field. + * + * This function returns failure if some final data value is too + * long to fit in an `unsigned long`. + */ +SECStatus PrioTotalShare_final(const_PrioConfig cfg, unsigned long long* output, + const_PrioTotalShare tA, + const_PrioTotalShare tB); + +#endif /* __PRIO_H__ */ + +#ifdef __cplusplus +} +#endif |