/* * ZeroTrace: Oblivious Memory Primitives from Intel SGX * Copyright (C) 2018 Sajin (sshsshy) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 3 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef __OASM_LIB__ #define __OASM_LIB__ #include #ifndef BEFTS_MODE #include "CONFIG.h" #endif #ifdef COUNT_OSWAPS extern thread_local uint64_t OSWAP_COUNTER; #endif // Oblivious Buffer move/swap functions: #if 0 extern "C" void oswap_buffer_16x(unsigned char *dest, unsigned char *source, uint32_t buffersize, uint8_t flag); extern "C" void oswap_buffer_byte(unsigned char *dest, unsigned char *source, uint32_t buffersize, uint8_t flag); extern "C" void oswap_buffer_byte_16x(unsigned char *dest, unsigned char *source, uint32_t buffersize, uint8_t flag); extern "C" void oswap_buffer_byte_v2(unsigned char *dest, unsigned char *source, uint8_t flag); extern "C" void ogt_comp_swap(uint64_t *key1, uint64_t *key2, unsigned char *buff1, unsigned char *buff2, uint32_t buffersize); #endif enum OSwap_Style { OSWAP_4, OSWAP_8, OSWAP_12, OSWAP_16X, OSWAP_8_16X }; template inline void oswap_buffer(unsigned char *dest, unsigned char *source, uint32_t buffersize, uint8_t flag); template inline void oswap_key(unsigned char *dest, unsigned char *source, uint8_t flag); template inline void omove_buffer(unsigned char *dest, unsigned char *source, uint32_t buffersize, uint8_t flag); inline uint8_t ogt_set_flag(uint64_t key1, uint64_t key2) { uint8_t flag; __asm__ ( "# inline ogt_set_flag\n" "cmp %[key2], %[key1]\n" //"# FOAV ogt_set_flag key1 (%[key1]):\n" "seta %[flag]\n" : [flag] "=r" (flag) : [key1] "r" (key1), [key2] "r" (key2) : "cc" ); return flag; } // A size-templated version of oblivious greater than for wide-key Bitonic Sort // Returns 1 if (*key1p) > (*key2p), and 0 otherwise, in a fully oblivious manner. template inline uint8_t ogt(const keytype *key1p, const keytype *key2p); template<> inline uint8_t ogt(const uint32_t *key1p, const uint32_t *key2p) { uint8_t flag; __asm__ ( "# inline ogt_uint32\n" "movl (%[key1p]), %%eax\n" "cmpl (%[key2p]), %%eax\n" "seta %[flag]\n" : [flag] "=r" (flag) : [key1p] "r" (key1p), [key2p] "r" (key2p) : "eax", "cc" ); return flag; } template<> inline uint8_t ogt(const uint64_t *key1p, const uint64_t *key2p) { __asm__ ("# inline ogt_uint64\n"); return ogt_set_flag(*key1p, *key2p); } template<> inline uint8_t ogt<__uint128_t>(const __uint128_t *key1p, const __uint128_t *key2p) { uint8_t flag; __asm__ ( "# inline ogt_uint128\n" "movq 8(%[key2p]), %%rcx\n" "movq (%[key1p]), %%rax\n" "cmpq %%rax, (%[key2p])\n" "sbbq 8(%[key1p]), %%rcx\n" "setc %[flag]\n" : [flag] "=r" (flag) : [key1p] "r" (key1p), [key2p] "r" (key2p) : "rax", "rcx", "cc" ); return flag; } inline uint8_t oge_set_flag(uint64_t key1, uint64_t key2) { uint8_t flag; __asm__ ( "# inline oge_set_flag\n" "cmp %[key2], %[key1]\n" //"# FOAV oge_set_flag key1 (%[key1]):\n" "setae %[flag]\n" : [flag] "=r" (flag) : [key1] "r" (key1), [key2] "r" (key2) : "cc" ); return flag; } inline uint8_t oe_set_flag(uint32_t key1, uint32_t key2) { uint8_t flag; __asm__ ( "# inline oe_set_flag\n" "cmp %[key2], %[key1]\n" //"# FOAV oe_set_flag key1 (%[key1]):\n" "sete %[flag]\n" : [flag] "=r" (flag) : [key1] "r" (key1), [key2] "r" (key2) : "cc" ); return flag; } inline void oset_value(uint64_t *dest, uint64_t value, uint32_t flag) { __asm__ ( "# inline oset_value\n" "mov (%[dest]), %%r10\n" "test %[flag], %[flag]\n" "cmovnz %[value], %%r10\n" "mov %%r10, (%[dest])\n" : : [dest] "r" (dest), [value] "r" (value), [flag] "r" (flag) : "cc", "memory", "r10" ); } inline void oset_value_uint32_t(uint32_t *dest, uint32_t value, uint8_t flag) { __asm__ ( "# inline oset_value_uint32_t\n" "mov (%[dest]), %%r10d\n" "test %[flag], %[flag]\n" "cmovnz %[value], %%r10d\n" "mov %%r10d, (%[dest])\n" : : [dest] "r" (dest), [value] "r" (value), [flag] "r" (flag) : "cc", "memory", "r10" ); } inline uint32_t oselect_uint32_t(uint32_t value_0, uint32_t value_1, uint8_t flag) { uint32_t out; __asm__ ( "# inline oselect_uint32_t\n" "mov %[value0], %[out]\n" "test %[flag], %[flag]\n" "cmovnz %[value1], %[out]\n" : [out] "=&r" (out) : [value0] "r" (value_0), [value1] "r" (value_1), [flag] "r" (flag) : "cc" ); return out; } #include "oasm_lib.tcc" #endif