Skip to content

Commit

Permalink
fields
Browse files Browse the repository at this point in the history
  • Loading branch information
carlweng committed Aug 2, 2023
1 parent 6e75f6d commit 8fc594b
Show file tree
Hide file tree
Showing 7 changed files with 489 additions and 1 deletion.
3 changes: 3 additions & 0 deletions emp-tool/emp-tool.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
#include "emp-tool/utils/aes_opt.h"
#include "emp-tool/utils/aes.h"
#include "emp-tool/utils/f2k.h"
#include "emp-tool/utils/fields/fp59.h"
#include "emp-tool/utils/fields/fp61.h"
#include "emp-tool/utils/fields/efp2r128.h"

#include "emp-tool/gc/halfgate_eva.h"
#include "emp-tool/gc/halfgate_gen.h"
Expand Down
72 changes: 72 additions & 0 deletions emp-tool/utils/fields/efp2r128.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#ifndef EMP_UTILS_FIELD_EFP2R128_H__
#define EMP_UTILS_FIELD_EFP2R128_H__

#include "emp-tool/utils/block.h"
#include "emp-tool/utils/f2k.h"
#include "emp-tool/utils/fields/utils.h"
#include <cstdint>
namespace emp {

// extension field Fpr, p = 2, r = 128
class EFP2R128 {
public:
static uint64_t PR_bit_len;

block val;

EFP2R128() { val = zero_block; }

EFP2R128(block input, bool mod_it = true) {
val = input;
}

void operator=(const block rhs) { this->val = rhs; }

void operator=(const EFP2R128 rhs) { this->val = rhs.val; }

bool operator==(const block rhs) {
block vcmp = _mm_xor_si128(this->val, rhs);
if(_mm_testz_si128(vcmp, vcmp))
return true;
return false;
}

bool operator==(const EFP2R128 rhs) {
block vcmp = _mm_xor_si128(this->val, rhs.val);
if(_mm_testz_si128(vcmp, vcmp))
return true;
return false;
}

bool operator!=(const block rhs) {
block vcmp = _mm_xor_si128(this->val, rhs);
if(_mm_testz_si128(vcmp, vcmp))
return false;
return true;
}

bool operator!=(const EFP2R128 rhs) {
block vcmp = _mm_xor_si128(this->val, rhs.val);
if(_mm_testz_si128(vcmp, vcmp))
return false;
return true;
}

EFP2R128 operator+(const EFP2R128 rhs) {
EFP2R128 res(*this);
res.val = res.val ^ rhs.val;
return res;
}

EFP2R128 operator*(const EFP2R128 rhs) {
EFP2R128 res(*this);
gfmul(this->val, rhs.val, &(res.val));
return res;
}

};

uint64_t EFP2R128::PR_bit_len = 61;

} // namespace emp
#endif // EMP_UTILS_FIELD_EFP2R128_H__
149 changes: 149 additions & 0 deletions emp-tool/utils/fields/fp59.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
#ifndef EMP_UTILS_FIELD_FP59_H__
#define EMP_UTILS_FIELD_FP59_H__

#include "emp-tool/utils/block.h"
#include "emp-tool/utils/fields/utils.h"
#include <cstdint>
namespace emp {

// finite field Fp, p = 2^59 - 2^28 + 1
class FP59 {
public:
static uint64_t PR_bit_len;
static uint64_t PR;
static block DoublePR;
static uint64_t Low59bMask;
static block DoubleLow59bMask;

uint64_t val;

FP59() { val = 0; }

FP59(uint64_t input, bool mod_it = true) {
if (mod_it)
val = mod(input);
else
val = input;
}

void operator=(const uint64_t rhs) { this->val = mod(rhs); }

void operator=(const FP59 rhs) { this->val = rhs.val; }

bool operator==(const uint64_t rhs) {
return (this->val == mod(rhs)) ? true : false;
}

bool operator==(const FP59 rhs) {
return (this->val == rhs.val) ? true : false;
}

bool operator!=(const uint64_t rhs) {
return (this->val == mod(rhs)) ? false : true;
}

bool operator!=(const FP59 rhs) {
return (this->val == rhs.val) ? false : true;
}

FP59 operator+(const FP59 rhs) {
FP59 res(*this);
res.val = add_mod(res.val, rhs.val);
return res;
}

FP59 operator*(const FP59 rhs) {
FP59 res(*this);
res.val = mult_mod(res.val, rhs.val);
return res;
}

uint64_t mod(uint64_t x) {
uint64_t i = x >> 59;
i = (i << 28) - i + (x & Low59bMask);
return (i >= PR) ? i - PR : i;
}

// c = val + a mod PR
uint64_t add_mod(uint64_t a, uint64_t b) {
uint64_t res = a + b;
return (res >= PR) ? (res - PR) : res;
}

// c = a * b mod PR
uint64_t mult_mod(uint64_t a, uint64_t b) {
uint64_t c = 0;
uint64_t e = mul64(a, b, (uint64_t *)&c);
uint64_t i = (c << 5) + (e >> 59);

uint64_t j = i >> 31;
j = (j << 28) - j + ((i << 28) & Low59bMask);
j = (j >= PR) ? j - PR : j;

i = j + (e & Low59bMask) + PR - i;
i = (i >= PR) ? (i - PR) : i;
return (i >= PR) ? (i - PR) : i;
}

// c = (a1 * b || a2 * b) mod PR
static block mult_mod(block a, uint64_t b) {
uint64_t H = _mm_extract_epi64(a, 1);
uint64_t L = _mm_extract_epi64(a, 0);
block bs[2];
uint64_t *is = (uint64_t *)(bs);
is[1] = mul64(H, b, (uint64_t *)(is + 3));
is[0] = mul64(L, b, (uint64_t *)(is + 2));
block t1 =
_mm_add_epi64(_mm_slli_epi64(bs[1], 5), _mm_srli_epi64(bs[0], 59));

block t2 = _mm_srli_epi64(t1, 31);
block t3 = _mm_slli_epi64(t2, 28);
t3 = _mm_sub_epi64(t3, t2);
t3 = _mm_add_epi64(t3, _mm_slli_epi64(t1, 28) & DoubleLow59bMask);
t3 = _mm_sub_epi64(
t3, _mm_andnot_si128(_mm_cmpgt_epi64(DoublePR, t3), DoublePR));

t3 = _mm_add_epi64(t3, bs[0] & DoubleLow59bMask);
t1 = _mm_sub_epi64(DoublePR, t1);
t3 = _mm_add_epi64(t3, t1);
t3 = _mm_sub_epi64(
t3, _mm_andnot_si128(_mm_cmpgt_epi64(DoublePR, t3), DoublePR));
return _mm_sub_epi64(
t3, _mm_andnot_si128(_mm_cmpgt_epi64(DoublePR, t3), DoublePR));
}

// c = (a1 + b || a2 + b) mod PR
static block add_mod(block a, uint64_t b) {
block res = _mm_add_epi64(a, _mm_set_epi64((__m64)b, (__m64)b));
return vec_partial_mod(res);
}

// c = (a1 + b1 || a2 + b2) mod PR
static block add_mod(block a, block b) {
block res = _mm_add_epi64(a, b);
return vec_partial_mod(res);
}

// c = (a1 + b1 || a2 + b2) mod PR
static block vec_mod(block i) {
block x = _mm_srli_epi64(i, 59);
x = _mm_sub_epi64(_mm_slli_epi64(x, 28), x);
x = _mm_add_epi64(x, i & DoubleLow59bMask);
return vec_partial_mod(x);
}

// (c1 || c2) = (a1 || a2) (partial) mod PR
static block vec_partial_mod(block i) {
return _mm_sub_epi64(
i, _mm_andnot_si128(_mm_cmpgt_epi64(DoublePR, i), DoublePR));
}
};

uint64_t FP59::PR_bit_len = 59;
uint64_t FP59::PR = 576460752034988033;
block FP59::DoublePR = makeBlock(576460752034988033, 576460752034988033);
uint64_t FP59::Low59bMask = (1ULL << 59) - 1;
block FP59::DoubleLow59bMask = makeBlock((1ULL << 59) - 1, (1ULL << 59) - 1);

} // namespace emp
#endif // EMP_UTILS_FIELD_FP59_H__
127 changes: 127 additions & 0 deletions emp-tool/utils/fields/fp61.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#ifndef EMP_UTILS_FIELD_FP61_H__
#define EMP_UTILS_FIELD_FP61_H__

#include "emp-tool/utils/block.h"
#include "emp-tool/utils/fields/utils.h"
#include <cstdint>
namespace emp {

// finite field Fp, p = 2^61 - 1
class FP61 {
public:
static uint64_t PR_bit_len;
static uint64_t PR;
static block DoublePR;
static uint64_t Low61bMask;
static block DoubleLow61bMask;

uint64_t val;

FP61() { val = 0; }

FP61(uint64_t input, bool mod_it = true) {
if (mod_it)
val = mod(input);
else
val = input;
}

void operator=(const uint64_t rhs) { this->val = mod(rhs); }

void operator=(const FP61 rhs) { this->val = rhs.val; }

bool operator==(const uint64_t rhs) {
return (this->val == mod(rhs)) ? true : false;
}

bool operator==(const FP61 rhs) {
return (this->val == rhs.val) ? true : false;
}

bool operator!=(const uint64_t rhs) {
return (this->val == mod(rhs)) ? false : true;
}

bool operator!=(const FP61 rhs) {
return (this->val == rhs.val) ? false : true;
}

FP61 operator+(const FP61 rhs) {
FP61 res(*this);
res.val = add_mod(res.val, rhs.val);
return res;
}

FP61 operator*(const FP61 rhs) {
FP61 res(*this);
res.val = mult_mod(res.val, rhs.val);
return res;
}

uint64_t mod(uint64_t x) {
uint64_t i = (x & PR) + (x >> PR_bit_len);
return (i >= PR) ? i - PR : i;
}

// c = val + a mod PR
uint64_t add_mod(uint64_t a, uint64_t b) {
uint64_t res = a + b;
return (res >= PR) ? (res - PR) : res;
}

// c = a * b mod PR
uint64_t mult_mod(uint64_t a, uint64_t b) {
uint64_t c = 0;
uint64_t e = mul64(a, b, (uint64_t *)&c);
uint64_t res = (e & PR) + ((e >> PR_bit_len) ^ (c << (64 - PR_bit_len)));
return (res >= PR) ? (res - PR) : res;
}

// c = (a1 * b || a2 * b) mod PR
static block mult_mod(block a, uint64_t b) {
uint64_t H = _mm_extract_epi64(a, 1);
uint64_t L = _mm_extract_epi64(a, 0);
block bs[2];
uint64_t *is = (uint64_t *)(bs);
is[1] = mul64(H, b, (uint64_t *)(is + 3));
is[0] = mul64(L, b, (uint64_t *)(is + 2));
block t1 = bs[0] & DoublePR;
block t2 = _mm_srli_epi64(bs[0], PR_bit_len) ^
_mm_slli_epi64(bs[1], 64 - PR_bit_len);
block res = _mm_add_epi64(t1, t2);
return vec_partial_mod(res);
}

// c = (a1 + b || a2 + b) mod PR
static block add_mod(block a, uint64_t b) {
block res = _mm_add_epi64(a, _mm_set_epi64((__m64)b, (__m64)b));
return vec_partial_mod(res);
}

// c = (a1 + b1 || a2 + b2) mod PR
static block add_mod(block a, block b) {
block res = _mm_add_epi64(a, b);
return vec_partial_mod(res);
}

// c = (a1 || a2) mod PR
static block vec_mod(block i) {
i = _mm_add_epi64((i & DoublePR), _mm_srli_epi64(i, PR_bit_len));
return vec_partial_mod(i);
}

// (c1 || c2) = (a1 || a2) (partial) mod PR
static block vec_partial_mod(block i) {
return _mm_sub_epi64(
i, _mm_andnot_si128(_mm_cmpgt_epi64(DoublePR, i), DoublePR));
}
};

uint64_t FP61::PR_bit_len = 61;
uint64_t FP61::PR = 2305843009213693951;
block FP61::DoublePR = makeBlock(2305843009213693951, 2305843009213693951);
uint64_t FP61::Low61bMask = (1ULL << 61) - 1;
block FP61::DoubleLow61bMask = makeBlock((1ULL << 61) - 1, (1ULL << 61) - 1);

} // namespace emp
#endif // EMP_UTILS_FIELD_FP61_H__
20 changes: 20 additions & 0 deletions emp-tool/utils/fields/utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#ifndef EMP_UTILS_FIELD_UTILS_H__
#define EMP_UTILS_FIELD_UTILS_H__

#if defined(__x86_64__) && defined(__BMI2__)
inline uint64_t mul64(uint64_t a, uint64_t b, uint64_t *c) {
return _mulx_u64((unsigned long long)a, (unsigned long long)b,
(unsigned long long *)c);
}
//
#else
inline uint64_t mul64(uint64_t a, uint64_t b, uint64_t *c) {
__uint128_t aa = a;
__uint128_t bb = b;
auto cc = aa * bb;
*c = cc >> 64;
return (uint64_t)cc;
}
#endif

#endif // EMP_UTILS_FIELD_UTILS_H__
3 changes: 2 additions & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@ add_test_case(f2k)
add_test_case(halfgate)
add_test_case(to_bool)
add_test_case(aes_opt)
add_test_case(fields)

IF(${CRYPTO_IN_CIRCUIT})
add_test_case(sha3_256)
add_test_case(aes_128_ctr)
ENDIF(${CRYPTO_IN_CIRCUIT})
ENDIF(${CRYPTO_IN_CIRCUIT})
Loading

0 comments on commit 8fc594b

Please sign in to comment.