SPDZ2k offline phase.

This commit is contained in:
Nikolaj Volgushev
2019-03-26 18:36:07 +11:00
committed by Marcel Keller
parent 5a0413de7a
commit 881b4403ac
49 changed files with 2125 additions and 380 deletions

View File

@@ -122,7 +122,7 @@ namespace Config {
pubkeys[i].resize(crypto_sign_PUBLICKEYBYTES);
infile.read((char*)&pubkeys[i][0],pubkeys[i].size());
}
} catch (ConfigError e) {
} catch (ConfigError& e) {
pubkeys.resize(0);
}

View File

@@ -10,20 +10,27 @@
#include "Math/gf2n.h"
#include "Math/gfp.h"
#include "Math/bigint.h"
#include "Math/Z2k.h"
#include <unistd.h>
void MMO::zeroIV()
{
octet key[AES_BLK_SIZE];
memset(key,0,AES_BLK_SIZE*sizeof(octet));
setIV(key);
if (N_KEYS > (1 << 8))
throw not_implemented();
for (int i = 0; i < N_KEYS; i++)
{
octet key[AES_BLK_SIZE];
memset(key, 0, AES_BLK_SIZE * sizeof(octet));
key[i] = i;
setIV(i, key);
}
}
void MMO::setIV(octet key[AES_BLK_SIZE])
void MMO::setIV(int i, octet key[AES_BLK_SIZE])
{
aes_schedule(IV,key);
aes_schedule(IV[i],key);
}
@@ -50,26 +57,91 @@ void MMO::encrypt_and_xor(void* output, const void* input, const octet* key,
_mm_storeu_si128(((__m128i*)output) + indices[i], out[i]);
}
template <>
void MMO::hashOneBlock<gf2n>(octet* output, octet* input)
template <class T, int N>
void MMO::hashBlocks(void* output, const void* input)
{
encrypt_and_xor<1>(output, input, IV);
int n_blocks = DIV_CEIL(T::size(), 16);
if (n_blocks > N_KEYS)
throw runtime_error("not enough MMO keys");
__m128i tmp[N];
int block_size = sizeof(tmp[0]);
for (int i = 0; i < n_blocks; i++)
{
encrypt_and_xor<N>(tmp, input, IV[i]);
for (int j = 0; j < N; j++)
memcpy((char*)output + j * sizeof(T) + i * block_size, &tmp[j],
min(T::size() - i * block_size, block_size));
}
}
template <>
void MMO::hashOneBlock<gfp>(octet* output, octet* input)
void MMO::hashBlocks<gfp, 1>(void* output, const void* input)
{
encrypt_and_xor<1>(output, input, IV);
if (gfp::get_ZpD().get_t() != 2)
throw not_implemented();
encrypt_and_xor<1>(output, input, IV[0]);
while (mpn_cmp((mp_limb_t*)output, gfp::get_ZpD().get_prA(), gfp::t()) >= 0)
encrypt_and_xor<1>(output, output, IV);
encrypt_and_xor<1>(output, output, IV[0]);
}
template <>
void MMO::hashBlockWise<gf2n,128>(octet* output, octet* input)
{
for (int i = 0; i < 16; i++)
encrypt_and_xor<8>(&((__m128i*)output)[i*8], &((__m128i*)input)[i*8], IV);
encrypt_and_xor<8>(&((__m128i*)output)[i*8], &((__m128i*)input)[i*8], IV[0]);
}
template <>
void MMO::hashBlocks<gfp, 8>(void* output, const void* input)
{
if (gfp::get_ZpD().get_t() != 2)
throw not_implemented();
__m128i* in = (__m128i*)input;
__m128i* out = (__m128i*)output;
encrypt_and_xor<8>(out, in, IV[0]);
int left = 8;
int indices[8] = {0, 1, 2, 3, 4, 5, 6, 7};
while (left)
{
int now_left = 0;
for (int j = 0; j < left; j++)
if (mpn_cmp((mp_limb_t*)&out[indices[j]], gfp::get_ZpD().get_prA(), gfp::t()) >= 0)
{
indices[now_left] = indices[j];
now_left++;
}
left = now_left;
// and now my favorite hack
switch (left) {
case 8:
ecb_aes_128_encrypt<8>(out, out, IV[0], indices);
break;
case 7:
ecb_aes_128_encrypt<7>(out, out, IV[0], indices);
break;
case 6:
ecb_aes_128_encrypt<6>(out, out, IV[0], indices);
break;
case 5:
ecb_aes_128_encrypt<5>(out, out, IV[0], indices);
break;
case 4:
ecb_aes_128_encrypt<4>(out, out, IV[0], indices);
break;
case 3:
ecb_aes_128_encrypt<3>(out, out, IV[0], indices);
break;
case 2:
ecb_aes_128_encrypt<2>(out, out, IV[0], indices);
break;
case 1:
ecb_aes_128_encrypt<1>(out, out, IV[0], indices);
break;
default:
break;
}
}
}
template <>
@@ -79,49 +151,11 @@ void MMO::hashBlockWise<gfp,128>(octet* output, octet* input)
{
__m128i* in = &((__m128i*)input)[i*8];
__m128i* out = &((__m128i*)output)[i*8];
encrypt_and_xor<8>(out, in, IV);
int left = 8;
int indices[8] = {0, 1, 2, 3, 4, 5, 6, 7};
while (left)
{
int now_left = 0;
for (int j = 0; j < left; j++)
if (mpn_cmp((mp_limb_t*)&out[indices[j]], gfp::get_ZpD().get_prA(), gfp::t()) >= 0)
{
indices[now_left] = indices[j];
now_left++;
}
left = now_left;
// and now my favorite hack
switch (left) {
case 8:
ecb_aes_128_encrypt<8>(out, out, IV, indices);
break;
case 7:
ecb_aes_128_encrypt<7>(out, out, IV, indices);
break;
case 6:
ecb_aes_128_encrypt<6>(out, out, IV, indices);
break;
case 5:
ecb_aes_128_encrypt<5>(out, out, IV, indices);
break;
case 4:
ecb_aes_128_encrypt<4>(out, out, IV, indices);
break;
case 3:
ecb_aes_128_encrypt<3>(out, out, IV, indices);
break;
case 2:
ecb_aes_128_encrypt<2>(out, out, IV, indices);
break;
case 1:
ecb_aes_128_encrypt<1>(out, out, IV, indices);
break;
default:
break;
}
}
hashBlocks<gfp,8>(out, in);
}
}
#define ZZ(F,N) \
template void MMO::hashBlocks<F,N>(void*, const void*);
#define Z(F) ZZ(F,1) ZZ(F,2) ZZ(F,8)
Z(gf2n) Z(Z2<64>) Z(Z2<128>) Z(Z2<160>) Z(Z2<256>)

View File

@@ -13,7 +13,8 @@
// Matyas-Meyer-Oseas hashing
class MMO
{
octet IV[176] __attribute__((aligned (16)));
static const int N_KEYS = 2;
octet IV[N_KEYS][176] __attribute__((aligned (16)));
template<int N>
static void encrypt_and_xor(void* output, const void* input,
@@ -25,9 +26,11 @@ class MMO
public:
MMO() { zeroIV(); }
void zeroIV();
void setIV(octet key[AES_BLK_SIZE]);
void setIV(int i, octet key[AES_BLK_SIZE]);
template <class T>
void hashOneBlock(octet* output, octet* input);
void hashOneBlock(void* output, const void* input) { hashBlocks<T, 1>((T*)output, input); }
template <class T, int N>
void hashBlocks(void* output, const void* input);
template <class T, int N>
void hashBlockWise(octet* output, octet* input);
template <class T>

View File

@@ -18,7 +18,6 @@ typedef unsigned char octet;
typedef unsigned long word;
#endif
inline int CEIL_LOG2(int x)
{
int result = 0;

19
Tools/oct.h Normal file
View File

@@ -0,0 +1,19 @@
#ifndef TOOLS_OCT_H_
#define TOOLS_OCT_H_
typedef unsigned char octet;
inline void PRINT_OCTET(const octet* bytes, size_t size) {
for (size_t i = 0; i < size; ++i)
cout << hex << (int) bytes[i];
cout << flush << endl;
}
inline bool OCTETS_EQUAL(const octet* left, const octet* right, int size) {
for (int i = 0; i < size; ++i)
if (left[i] != right[i])
return false;
return true;
}
#endif

View File

@@ -36,16 +36,6 @@ void octetStream::assign(const octetStream& os)
}
void octetStream::swap(octetStream& os)
{
const size_t size = sizeof(octetStream);
char tmp[size];
memcpy(tmp, this, size);
memcpy(this, &os, size);
memcpy(&os, tmp, size);
}
octetStream::octetStream(size_t maxlen)
{
mxlen=maxlen; len=0; ptr=0;

View File

@@ -42,10 +42,10 @@ class octetStream
void resize(size_t l);
void resize_precise(size_t l);
void reserve(size_t l);
void clear();
void assign(const octetStream& os);
void swap(octetStream& os);
octetStream() : len(0), mxlen(0), ptr(0), data(0) {}
octetStream(size_t maxlen);
@@ -177,6 +177,11 @@ inline void octetStream::resize_precise(size_t l)
mxlen=l;
}
inline void octetStream::reserve(size_t l)
{
if (len + l > mxlen)
resize_precise(len + l);
}
inline void octetStream::append(const octet* x, const size_t l)
{

View File

@@ -3,6 +3,7 @@
#include "Tools/random.h"
#include "Math/bigint.h"
#include "Auth/Subroutines.h"
#include <stdio.h>
#include <sodium.h>
@@ -38,6 +39,12 @@ void PRNG::SetSeed(PRNG& G)
SetSeed(tmp);
}
void PRNG::SecureSeed(Player& player)
{
Create_Random_Seed(seed, player, SEED_SIZE);
InitSeed();
}
void PRNG::InitSeed()
{
#ifdef USE_AES
@@ -136,7 +143,25 @@ unsigned int PRNG::get_uint()
return ans;
}
unsigned int PRNG::get_uint(int upper)
{
// adopting Java 7 implementation of bounded nextInt here
if (upper <= 0)
throw invalid_argument("Must be positive");
// power of 2 case
if ((upper & (upper - 1)) == 0) {
unsigned int r = (upper < 255) ? get_uchar() : get_uint();
// zero out higher order bits
return r % upper;
}
// not power of 2
int r, reduced;
do {
r = (upper < 255) ? get_uchar() : get_uint();
reduced = r % upper;
} while (r - reduced + (upper - 1) < 0);
return reduced;
}
unsigned char PRNG::get_uchar()
{
@@ -147,7 +172,6 @@ unsigned char PRNG::get_uchar()
return ans;
}
__m128i PRNG::get_doubleword()
{
if (cnt > RAND_SIZE - 16)

View File

@@ -6,6 +6,7 @@
#include "Tools/octetStream.h"
#include "Tools/sha1.h"
#include "Tools/aes.h"
#include "Tools/avx_memcpy.h"
#define USE_AES
@@ -19,6 +20,7 @@
#define RAND_SIZE (PIPELINES * AES_BLK_SIZE)
#endif
class Player;
/* This basically defines a randomness expander, if using
* as a real PRG on an input stream you should first collapse
@@ -62,12 +64,14 @@ class PRNG
// Set seed from array
void SetSeed(const unsigned char*);
void SetSeed(PRNG& G);
void SecureSeed(Player& player);
void InitSeed();
double get_double();
bool get_bit() { return get_uchar() & 1; }
unsigned char get_uchar();
unsigned int get_uint();
unsigned int get_uint(int upper);
void get_bigint(bigint& res, int n_bits, bool positive = true);
void get(bigint& res, int n_bits, bool positive = true);
void get(int& res, int n_bits, bool positive = true);
@@ -82,9 +86,34 @@ class PRNG
__m128i get_doubleword();
void get_octetStream(octetStream& ans,int len);
void get_octets(octet* ans, int len);
template <int L>
void get_octets_(octet* ans);
template <class T>
T get();
const octet* get_seed() const
{ return seed; }
};
template <class T>
T PRNG::get()
{
T res;
res.randomize(*this);
return res;
}
template<int L>
inline void PRNG::get_octets_(octet* ans)
{
if (L < RAND_SIZE - cnt)
{
avx_memcpy(ans, random + cnt, L);
cnt += L;
}
else
get_octets(ans, L);
}
#endif