summaryrefslogtreecommitdiffstats
path: root/third_party/prio/include
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
commit43a97878ce14b72f0981164f87f2e35e14151312 (patch)
tree620249daf56c0258faa40cbdcf9cfba06de2a846 /third_party/prio/include
parentInitial commit. (diff)
downloadfirefox-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.h304
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