Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unify FourQlib #162

Merged
merged 4 commits into from
Jul 31, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions bazel/microsoft_apsi.BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ psi_cmake_external(
deps = [
"@com_github_facebook_zstd//:zstd",
"@com_github_log4cplus_log4cplus//:log4cplus",
"@com_github_microsoft_FourQlib//:FourQlib",
"@com_github_microsoft_gsl//:Microsoft.GSL",
"@com_github_microsoft_kuku//:kuku",
"@com_github_microsoft_seal//:seal",
Expand Down
75 changes: 75 additions & 0 deletions bazel/patches/apsi-fourq.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 78d54a6..166047c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -273,10 +273,9 @@ if(APSI_USE_ZMQ)
target_link_libraries(apsi PUBLIC libzmq-static cppzmq-static)
endif()

-# Configurations for FourQlib: system, arch, SIMD, and assembler
-target_compile_options(apsi PUBLIC -DHAVE_CONFIG)
-target_compile_options(apsi PUBLIC -DUSE_SECURE_SEED)
-target_compile_options(apsi PUBLIC -DUSE_ENDO=true)
+# Add FourQlib
+target_include_directories(apsi PUBLIC ${EXT_BUILD_DEPS}/FourQlib/include)
+target_link_libraries(apsi PUBLIC FourQ)

# Set system
if(MSVC)
diff --git a/common/apsi/CMakeLists.txt b/common/apsi/CMakeLists.txt
index a65bbfe..60e246e 100644
--- a/common/apsi/CMakeLists.txt
+++ b/common/apsi/CMakeLists.txt
@@ -28,7 +28,6 @@ install(
${APSI_INCLUDES_INSTALL_DIR}/apsi
)

-add_subdirectory(fourq)
add_subdirectory(network)
add_subdirectory(oprf)
add_subdirectory(util)
diff --git a/common/apsi/network/zmq/zmq_channel.cpp b/common/apsi/network/zmq/zmq_channel.cpp
index bcaa013..93e2b4a 100644
--- a/common/apsi/network/zmq/zmq_channel.cpp
+++ b/common/apsi/network/zmq/zmq_channel.cpp
@@ -8,7 +8,7 @@
#include <stdexcept>

// APSI
-#include "apsi/fourq/random.h"
+#include "random.h"
#include "apsi/log.h"
#include "apsi/network/result_package_generated.h"
#include "apsi/network/sop_generated.h"
diff --git a/common/apsi/oprf/ecpoint.cpp b/common/apsi/oprf/ecpoint.cpp
index d12313f..5fd9be1 100644
--- a/common/apsi/oprf/ecpoint.cpp
+++ b/common/apsi/oprf/ecpoint.cpp
@@ -10,10 +10,10 @@
#include "apsi/util/utils.h"

// FourQ
-#include "apsi/fourq/FourQ.h"
-#include "apsi/fourq/FourQ_api.h"
-#include "apsi/fourq/FourQ_internal.h"
-#include "apsi/fourq/random.h"
+#include "FourQ.h"
+#include "FourQ_api.h"
+#include "FourQ_internal.h"
+#include "random.h"

// SEAL
#include "seal/randomgen.h"
diff --git a/common/apsi/util/label_encryptor.cpp b/common/apsi/util/label_encryptor.cpp
index 3e00b5e..57a5b40 100644
--- a/common/apsi/util/label_encryptor.cpp
+++ b/common/apsi/util/label_encryptor.cpp
@@ -9,7 +9,7 @@
#include <vector>

// APSI
-#include "apsi/fourq/random.h"
+#include "random.h"
#include "apsi/util/label_encryptor.h"
#include "apsi/util/utils.h"

305 changes: 0 additions & 305 deletions bazel/patches/apsi.patch
Original file line number Diff line number Diff line change
@@ -1,295 +1,3 @@
diff --git a/common/apsi/fourq/CMakeLists.txt b/common/apsi/fourq/CMakeLists.txt
index 3b15780..5085038 100644
--- a/common/apsi/fourq/CMakeLists.txt
+++ b/common/apsi/fourq/CMakeLists.txt
@@ -8,8 +8,21 @@ set(APSI_SOURCE_FILES ${APSI_SOURCE_FILES}
${CMAKE_CURRENT_LIST_DIR}/eccp2_no_endo.c
${CMAKE_CURRENT_LIST_DIR}/eccp2.c
${CMAKE_CURRENT_LIST_DIR}/hash_to_curve.c
+ ${CMAKE_CURRENT_LIST_DIR}/kex.c
${CMAKE_CURRENT_LIST_DIR}/random.c
)
+# Add header files for installation
+install(
+ FILES
+ ${CMAKE_CURRENT_LIST_DIR}/FourQ_api.h
+ ${CMAKE_CURRENT_LIST_DIR}/FourQ_internal.h
+ ${CMAKE_CURRENT_LIST_DIR}/FourQ_params.h
+ ${CMAKE_CURRENT_LIST_DIR}/FourQ_tables.h
+ ${CMAKE_CURRENT_LIST_DIR}/FourQ.h
+ ${CMAKE_CURRENT_LIST_DIR}/table_lookup.h
+ DESTINATION
+ ${APSI_INCLUDES_INSTALL_DIR}/apsi/fourq
+)

if(APSI_FOURQ_AMD64)
add_subdirectory(amd64)
diff --git a/common/apsi/fourq/FourQ_internal.h b/common/apsi/fourq/FourQ_internal.h
index 009bb1d..5aa9886 100644
--- a/common/apsi/fourq/FourQ_internal.h
+++ b/common/apsi/fourq/FourQ_internal.h
@@ -143,7 +143,7 @@ static __inline unsigned int is_digit_lessthan_ct(digit_t x, digit_t y)

// 64x64-bit multiplication
#define MUL128(multiplier, multiplicand, product) \
- mp_mul( \
+ fq_mp_mul( \
(digit_t *)&(multiplier), \
(digit_t *)&(multiplicand), \
(digit_t *)&(product), \
@@ -151,12 +151,12 @@ static __inline unsigned int is_digit_lessthan_ct(digit_t x, digit_t y)

// 128-bit addition, inputs < 2^127
#define ADD128(addend1, addend2, addition) \
- mp_add((digit_t *)(addend1), (digit_t *)(addend2), (digit_t *)(addition), NWORDS_FIELD);
+ fq_mp_add((digit_t *)(addend1), (digit_t *)(addend2), (digit_t *)(addition), NWORDS_FIELD);

// 128-bit addition with output carry
#define ADC128(addend1, addend2, carry, addition) \
(carry) = \
- mp_add((digit_t *)(addend1), (digit_t *)(addend2), (digit_t *)(addition), NWORDS_FIELD);
+ fq_mp_add((digit_t *)(addend1), (digit_t *)(addend2), (digit_t *)(addition), NWORDS_FIELD);

#elif (TARGET == TARGET_AMD64 && OS_TARGET == OS_WIN)

@@ -257,10 +257,10 @@ static __inline unsigned int is_digit_lessthan_ct(digit_t x, digit_t y)
bool is_zero_ct(digit_t *a, unsigned int nwords);

// Multiprecision addition, c = a+b. Returns the carry bit
-unsigned int mp_add(digit_t *a, digit_t *b, digit_t *c, unsigned int nwords);
+unsigned int fq_mp_add(digit_t *a, digit_t *b, digit_t *c, unsigned int nwords);

// Schoolbook multiprecision multiply, c = a*b
-void mp_mul(const digit_t *a, const digit_t *b, digit_t *c, const unsigned int nwords);
+void fq_mp_mul(const digit_t *a, const digit_t *b, digit_t *c, const unsigned int nwords);

// Multiprecision subtraction, c = a-b. Returns the borrow bit
#if defined(GENERIC_IMPLEMENTATION)
diff --git a/common/apsi/fourq/generic/fp.h b/common/apsi/fourq/generic/fp.h
index f475de1..e24a26a 100644
--- a/common/apsi/fourq/generic/fp.h
+++ b/common/apsi/fourq/generic/fp.h
@@ -172,7 +172,7 @@ void mod1271(felm_t a)
ADDC(borrow, a[NWORDS_FIELD - 1], (mask >> 1), borrow, a[NWORDS_FIELD - 1]);
}

-void mp_mul(const digit_t *a, const digit_t *b, digit_t *c, const unsigned int nwords)
+void fq_mp_mul(const digit_t *a, const digit_t *b, digit_t *c, const unsigned int nwords)
{ // Schoolbook multiprecision multiply, c = a*b
unsigned int i, j;
digit_t u, v, UV[2];
@@ -195,7 +195,7 @@ void mp_mul(const digit_t *a, const digit_t *b, digit_t *c, const unsigned int n
}
}

-unsigned int mp_add(digit_t *a, digit_t *b, digit_t *c, unsigned int nwords)
+unsigned int fq_mp_add(digit_t *a, digit_t *b, digit_t *c, unsigned int nwords)
{ // Multiprecision addition, c = a+b, where lng(a) = lng(b) = nwords. Returns the carry bit
unsigned int i, carry = 0;

@@ -263,13 +263,13 @@ void fpinv1271(felm_t a)
static void multiply(const digit_t *a, const digit_t *b, digit_t *c)
{ // Schoolbook multiprecision multiply, c = a*b

- mp_mul(a, b, c, NWORDS_ORDER);
+ fq_mp_mul(a, b, c, NWORDS_ORDER);
}

static unsigned int add(const digit_t *a, const digit_t *b, digit_t *c, const unsigned int nwords)
{ // Multiprecision addition, c = a+b, where lng(a) = lng(b) = nwords. Returns the carry bit

- return mp_add((digit_t *)a, (digit_t *)b, c, (unsigned int)nwords);
+ return fq_mp_add((digit_t *)a, (digit_t *)b, c, (unsigned int)nwords);
}

unsigned int subtract(const digit_t *a, const digit_t *b, digit_t *c, const unsigned int nwords)
diff --git a/common/apsi/fourq/kex.c b/common/apsi/fourq/kex.c
new file mode 100644
index 0000000..d59af6d
--- /dev/null
+++ b/common/apsi/fourq/kex.c
@@ -0,0 +1,181 @@
+/********************************************************************************
+* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
+*
+* Copyright (c) Microsoft Corporation. All rights reserved.
+*
+* Abstract: Diffie-Hellman key exchange based on FourQ
+* option 1: co-factor ecdh using compressed 32-byte public keys,
+* (see https://datatracker.ietf.org/doc/draft-ladd-cfrg-4q/).
+* option 2: co-factor ecdh using uncompressed, 64-byte public keys.
+*********************************************************************************/
+
+#include "apsi/fourq/FourQ_internal.h"
+#include "apsi/fourq/FourQ_params.h"
+#include "apsi/fourq/random.h"
+#include <string.h>
+
+
+static __inline bool is_neutral_point(point_t P)
+{ // Is P the neutral point (0,1)?
+ // SECURITY NOTE: this function does not run in constant time (input point P is assumed to be public).
+
+ if (is_zero_ct((digit_t*)P->x, 2*NWORDS_FIELD) && is_zero_ct(&((digit_t*)P->y)[1], 2*NWORDS_FIELD-1) && is_digit_zero_ct(P->y[0][0] - 1)) {
+ return true;
+ }
+ return false;
+}
+
+
+/*************** ECDH USING COMPRESSED, 32-BYTE PUBLIC KEYS ***************/
+
+ECCRYPTO_STATUS CompressedPublicKeyGeneration(const unsigned char* SecretKey, unsigned char* PublicKey)
+{ // Compressed public key generation for key exchange
+ // It produces a public key PublicKey, which is the encoding of P = SecretKey*G (G is the generator).
+ // Input: 32-byte SecretKey
+ // Output: 32-byte PublicKey
+ point_t P;
+
+ ecc_mul_fixed((digit_t*)SecretKey, P); // Compute public key
+ encode(P, PublicKey); // Encode public key
+
+ return ECCRYPTO_SUCCESS;
+}
+
+
+ECCRYPTO_STATUS CompressedKeyGeneration(unsigned char* SecretKey, unsigned char* PublicKey)
+{ // Keypair generation for key exchange. Public key is compressed to 32 bytes
+ // It produces a private key SecretKey and a public key PublicKey, which is the encoding of P = SecretKey*G (G is the generator).
+ // Outputs: 32-byte SecretKey and 32-byte PublicKey
+ ECCRYPTO_STATUS Status = ECCRYPTO_ERROR_UNKNOWN;
+
+ Status = RandomBytesFunction(SecretKey, 32);
+ if (Status != ECCRYPTO_SUCCESS) {
+ goto cleanup;
+ }
+
+ Status = CompressedPublicKeyGeneration(SecretKey, PublicKey);
+ if (Status != ECCRYPTO_SUCCESS) {
+ goto cleanup;
+ }
+
+ return ECCRYPTO_SUCCESS;
+
+cleanup:
+ clear_words((unsigned int*)SecretKey, 256/(sizeof(unsigned int)*8));
+ clear_words((unsigned int*)PublicKey, 256/(sizeof(unsigned int)*8));
+
+ return Status;
+}
+
+
+ECCRYPTO_STATUS CompressedSecretAgreement(const unsigned char* SecretKey, const unsigned char* PublicKey, unsigned char* SharedSecret)
+{ // Secret agreement computation for key exchange using a compressed, 32-byte public key
+ // The output is the y-coordinate of SecretKey*A, where A is the decoding of the public key PublicKey.
+ // Inputs: 32-byte SecretKey and 32-byte PublicKey
+ // Output: 32-byte SharedSecret
+ point_t A;
+ ECCRYPTO_STATUS Status = ECCRYPTO_ERROR_UNKNOWN;
+
+ if ((PublicKey[15] & 0x80) != 0) { // Is bit128(PublicKey) = 0?
+ Status = ECCRYPTO_ERROR_INVALID_PARAMETER;
+ goto cleanup;
+ }
+
+ Status = decode(PublicKey, A); // Also verifies that A is on the curve. If it is not, it fails
+ if (Status != ECCRYPTO_SUCCESS) {
+ goto cleanup;
+ }
+
+ Status = ecc_mul(A, (digit_t*)SecretKey, A, true);
+ if (Status != ECCRYPTO_SUCCESS) {
+ goto cleanup;
+ }
+
+ if (is_neutral_point(A)) { // Is output = neutral point (0,1)?
+ Status = ECCRYPTO_ERROR_SHARED_KEY;
+ goto cleanup;
+ }
+
+ memmove(SharedSecret, (unsigned char*)A->y, 32);
+
+ return ECCRYPTO_SUCCESS;
+
+cleanup:
+ clear_words((unsigned int*)SharedSecret, 256/(sizeof(unsigned int)*8));
+
+ return Status;
+}
+
+
+/*************** ECDH USING UNCOMPRESSED PUBLIC KEYS ***************/
+
+ECCRYPTO_STATUS PublicKeyGeneration(const unsigned char* SecretKey, unsigned char* PublicKey)
+{ // Public key generation for key exchange
+ // It produces the public key PublicKey = SecretKey*G, where G is the generator.
+ // Input: 32-byte SecretKey
+ // Output: 64-byte PublicKey
+
+ ecc_mul_fixed((digit_t*)SecretKey, (point_affine*)PublicKey); // Compute public key
+
+ return ECCRYPTO_SUCCESS;
+}
+
+
+ECCRYPTO_STATUS KeyGeneration(unsigned char* SecretKey, unsigned char* PublicKey)
+{ // Keypair generation for key exchange
+ // It produces a private key SecretKey and computes the public key PublicKey = SecretKey*G, where G is the generator.
+ // Outputs: 32-byte SecretKey and 64-byte PublicKey
+ ECCRYPTO_STATUS Status = ECCRYPTO_ERROR_UNKNOWN;
+
+ Status = RandomBytesFunction(SecretKey, 32);
+ if (Status != ECCRYPTO_SUCCESS) {
+ goto cleanup;
+ }
+
+ Status = PublicKeyGeneration(SecretKey, PublicKey);
+ if (Status != ECCRYPTO_SUCCESS) {
+ goto cleanup;
+ }
+
+ return ECCRYPTO_SUCCESS;
+
+cleanup:
+ clear_words((unsigned int*)SecretKey, 256/(sizeof(unsigned int)*8));
+ clear_words((unsigned int*)PublicKey, 512/(sizeof(unsigned int)*8));
+
+ return Status;
+}
+
+
+ECCRYPTO_STATUS SecretAgreement(const unsigned char* SecretKey, const unsigned char* PublicKey, unsigned char* SharedSecret)
+{ // Secret agreement computation for key exchange
+ // The output is the y-coordinate of SecretKey*PublicKey.
+ // Inputs: 32-byte SecretKey and 64-byte PublicKey
+ // Output: 32-byte SharedSecret
+ point_t A;
+ ECCRYPTO_STATUS Status = ECCRYPTO_ERROR_UNKNOWN;
+
+ if (((PublicKey[15] & 0x80) != 0) || ((PublicKey[31] & 0x80) != 0) || ((PublicKey[47] & 0x80) != 0) || ((PublicKey[63] & 0x80) != 0)) { // Are PublicKey_x[i] and PublicKey_y[i] < 2^127?
+ Status = ECCRYPTO_ERROR_INVALID_PARAMETER;
+ goto cleanup;
+ }
+
+ Status = ecc_mul((point_affine*)PublicKey, (digit_t*)SecretKey, A, true); // Also verifies that PublicKey is a point on the curve. If it is not, it fails
+ if (Status != ECCRYPTO_SUCCESS) {
+ goto cleanup;
+ }
+
+ if (is_neutral_point(A)) { // Is output = neutral point (0,1)?
+ Status = ECCRYPTO_ERROR_SHARED_KEY;
+ goto cleanup;
+ }
+
+ memmove(SharedSecret, (unsigned char*)A->y, 32);
+
+ return ECCRYPTO_SUCCESS;
+
+cleanup:
+ clear_words((unsigned int*)SharedSecret, 256/(sizeof(unsigned int)*8));
+
+ return Status;
+}
diff --git a/receiver/apsi/itt.h b/receiver/apsi/itt.h
index e683045..067d244 100644
--- a/receiver/apsi/itt.h
Expand Down Expand Up @@ -398,16 +106,3 @@ index 4c4e116..8eb34fc 100644
}

union Request { ParmsRequest, OPRFRequest, QueryRequest }
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 78d54a6..46a452e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -326,7 +326,7 @@ else()
endif()

# Use optimized assembly on UNIX
-if(APSI_USE_ASM AND UNIX AND NOT APPLE AND NOT CYGWIN AND NOT MINGW)
+if(APSI_USE_ASM AND UNIX AND APSI_FOURQ_AMD64 AND NOT APPLE AND NOT CYGWIN AND NOT MINGW)
check_language(ASM)
if(CMAKE_ASM_COMPILER)
enable_language(ASM)
Loading
Loading