diff --git a/src/include/arch_32/arch_intrinsics.h b/src/include/arch_32/arch_intrinsics.h index f3908a2..46be539 100644 --- a/src/include/arch_32/arch_intrinsics.h +++ b/src/include/arch_32/arch_intrinsics.h @@ -7,6 +7,11 @@ #define ARCH_WORD_BITS 32 +#if defined _MSC_VER +#define __attribute(x) +#define __inline__ __inline +#endif // MSVC + static __inline__ __attribute((always_inline,unused)) uint32_t word_is_zero(uint32_t a) { /* let's hope the compiler isn't clever enough to optimize this. */ diff --git a/src/include/keccak_internal.h b/src/include/keccak_internal.h index 15d1be4..62d199f 100644 --- a/src/include/keccak_internal.h +++ b/src/include/keccak_internal.h @@ -12,6 +12,13 @@ #include +/* Aliasing MSVC preprocessing to GNU preprocessing */ +#if defined _MSC_VER +#define __attribute__(x) // Turn off attribute code +#define __attribute(x) +#define __restrict__ __restrict // Use MSVC restrict code +#endif // MSVC + /* The internal, non-opaque definition of the decaf_sponge struct. */ typedef union { uint64_t w[25]; uint8_t b[25*8]; diff --git a/src/include/portable_endian.h b/src/include/portable_endian.h index 5cbfca7..100674e 100644 --- a/src/include/portable_endian.h +++ b/src/include/portable_endian.h @@ -21,8 +21,12 @@ # define htole64(x) LE_64(x) # define le64toh(x) LE_64(x) #elif defined(_WIN16) || defined(_WIN32) || defined(_WIN64) || defined(__WINDOWS__) +# if defined(_MSC_VER) +# define __builtin_bswap64(x) _byteswap_uint64((x)) +# else +# include +# endif # include -# include # if BYTE_ORDER == LITTLE_ENDIAN # define htole64(x) (x) # define le64toh(x) (x) diff --git a/src/include/word.h b/src/include/word.h index 7c7644a..de22693 100644 --- a/src/include/word.h +++ b/src/include/word.h @@ -13,6 +13,11 @@ extern int posix_memalign(void **, size_t, size_t); #endif +// MSVC has no posix_memalign +#if defined(_MSC_VER) +#define posix_memalign(p, a, s) (((*(p)) = _aligned_malloc((s), (a))), *(p) ?0 :errno) +#endif + #include #include #include "arch_intrinsics.h" diff --git a/src/per_curve/decaf.tmpl.c b/src/per_curve/decaf.tmpl.c index 9bfe4c0..833f301 100644 --- a/src/per_curve/decaf.tmpl.c +++ b/src/per_curve/decaf.tmpl.c @@ -7,6 +7,23 @@ #include #include +/* MSVC has no builtint ctz, this is a fix as in +https://stackoverflow.com/questions/355967/how-to-use-msvc-intrinsics-to-get-the-equivalent-of-this-gcc-code/5468852#5468852 +*/ +#ifdef _MSC_VER +#include + +uint32_t __inline ctz(uint32_t value) +{ + DWORD trailing_zero = 0; + if ( _BitScanForward( &trailing_zero, value ) ) + return trailing_zero; + else + return 32; // This is undefined, I better choose 32 than 0 +} +#define __builtin_ctz(x) ctz(x) +#endif + /* Template stuff */ #define API_NS(_id) $(c_ns)_##_id #define SCALAR_BITS $(C_NS)_SCALAR_BITS @@ -514,6 +531,7 @@ void API_NS(point_scalarmul) ( const point_t b, const scalar_t scalar ) { + const int WINDOW = DECAF_WINDOW_BITS, WINDOW_MASK = (1<> 1, @@ -524,7 +542,7 @@ void API_NS(point_scalarmul) ( API_NS(scalar_halve)(scalar1x,scalar1x); /* Set up a precomputed table with odd multiples of b. */ - pniels_t pn, multiples[NTABLE]; + pniels_t pn, multiples[1<<((int)(DECAF_WINDOW_BITS)-1)]; // == NTABLE (MSVC compatibility issue) point_t tmp; prepare_fixed_window(multiples, b, NTABLE); @@ -575,12 +593,13 @@ void API_NS(point_double_scalarmul) ( const scalar_t scalarb, const point_t c, const scalar_t scalarc -) { +) { + const int WINDOW = DECAF_WINDOW_BITS, WINDOW_MASK = (1<> 1, NTABLE = 1<<(WINDOW-1); - + scalar_t scalar1x, scalar2x; API_NS(scalar_add)(scalar1x, scalarb, point_scalarmul_adjustment); API_NS(scalar_halve)(scalar1x,scalar1x); @@ -588,9 +607,10 @@ void API_NS(point_double_scalarmul) ( API_NS(scalar_halve)(scalar2x,scalar2x); /* Set up a precomputed table with odd multiples of b. */ - pniels_t pn, multiples1[NTABLE], multiples2[NTABLE]; + pniels_t pn, multiples1[1<<((int)(DECAF_WINDOW_BITS)-1)], multiples2[1<<((int)(DECAF_WINDOW_BITS)-1)]; + // Array size above equal NTABLE (MSVC compatibility issue) point_t tmp; - prepare_fixed_window(multiples1, b, NTABLE); + prepare_fixed_window(multiples1, b, NTABLE); prepare_fixed_window(multiples2, c, NTABLE); /* Initialize. */ @@ -652,11 +672,13 @@ void API_NS(point_dual_scalarmul) ( const scalar_t scalar1, const scalar_t scalar2 ) { + const int WINDOW = DECAF_WINDOW_BITS, WINDOW_MASK = (1<> 1, NTABLE = 1<<(WINDOW-1); - + + scalar_t scalar1x, scalar2x; API_NS(scalar_add)(scalar1x, scalar1, point_scalarmul_adjustment); API_NS(scalar_halve)(scalar1x,scalar1x); @@ -664,7 +686,9 @@ void API_NS(point_dual_scalarmul) ( API_NS(scalar_halve)(scalar2x,scalar2x); /* Set up a precomputed table with odd multiples of b. */ - point_t multiples1[NTABLE], multiples2[NTABLE], working, tmp; + point_t multiples1[1<<((int)(DECAF_WINDOW_BITS)-1)], multiples2[1<<((int)(DECAF_WINDOW_BITS)-1)], working, tmp; + // Array sizes above equal NTABLE (MSVC compatibility issue) + pniels_t pn; API_NS(point_copy)(working, b); @@ -887,11 +911,11 @@ void API_NS(precompute) ( const unsigned int n = COMBS_N, t = COMBS_T, s = COMBS_S; assert(n*t*s >= SCALAR_BITS); - point_t working, start, doubles[t-1]; + point_t working, start, doubles[COMBS_T-1]; API_NS(point_copy)(working, base); pniels_t pn_tmp; - gf zs[n<<(t-1)], zis[n<<(t-1)]; + gf zs[(unsigned int)(COMBS_N)<<(unsigned int)(COMBS_T-1)], zis[(unsigned int)(COMBS_N)<<(unsigned int)(COMBS_T-1)]; unsigned int i,j,k; @@ -1511,13 +1535,13 @@ void API_NS(base_double_scalarmul_non_secret) ( ) { const int table_bits_var = DECAF_WNAF_VAR_TABLE_BITS, table_bits_pre = DECAF_WNAF_FIXED_TABLE_BITS; - struct smvt_control control_var[SCALAR_BITS/(table_bits_var+1)+3]; - struct smvt_control control_pre[SCALAR_BITS/(table_bits_pre+1)+3]; + struct smvt_control control_var[SCALAR_BITS/((int)(DECAF_WNAF_VAR_TABLE_BITS)+1)+3]; + struct smvt_control control_pre[SCALAR_BITS/((int)(DECAF_WNAF_FIXED_TABLE_BITS)+1)+3]; int ncb_pre = recode_wnaf(control_pre, scalar1, table_bits_pre); int ncb_var = recode_wnaf(control_var, scalar2, table_bits_var); - pniels_t precmp_var[1< +#if defined (__GNUC__) // File only exists for GNU compilers #include +#endif #ifdef __cplusplus extern "C" { @@ -25,11 +27,31 @@ extern "C" { #define __attribute__(x) #define NOINLINE #endif + +/* Aliasing MSVC preprocessing to GNU preprocessing */ +#if defined _MSC_VER +# define __attribute__(x) // Turn off attribute code +# define __attribute(x) +# define __restrict__ __restrict // Use MSVC restrict code +# if defined _DLL +# define DECAF_API_VIS __declspec(dllexport) // MSVC for visibility +# else +# define DECAF_API_VIS __declspec(dllimport) +# endif + +//# define DECAF_NOINLINE __declspec(noinline) // MSVC for noinline +//# define DECAF_INLINE __forceinline // MSVC for always inline +//# define DECAF_WARN_UNUSED _Check_return_ +#else // MSVC #define DECAF_API_VIS __attribute__((visibility("default"))) +#define DECAF_API_IMPORT +#endif + +// The following are disabled for MSVC #define DECAF_NOINLINE __attribute__((noinline)) -#define DECAF_WARN_UNUSED __attribute__((warn_unused_result)) -#define DECAF_NONNULL __attribute__((nonnull)) #define DECAF_INLINE inline __attribute__((always_inline,unused)) +#define DECAF_WARN_UNUSED __attribute__((warn_unused_result)) +#define DECAF_NONNULL __attribute__((nonnull)) // Cribbed from libnotmuch #if defined (__clang_major__) && __clang_major__ >= 3 \ || defined (__GNUC__) && __GNUC__ >= 5 \ @@ -98,17 +120,17 @@ decaf_successful(decaf_error_t e) { } /** Overwrite data with zeros. Uses memset_s if available. */ -void decaf_bzero ( +void DECAF_API_VIS decaf_bzero ( void *data, size_t size -) DECAF_NONNULL DECAF_API_VIS; +) DECAF_NONNULL; /** Compare two buffers, returning DECAF_TRUE if they are equal. */ -decaf_bool_t decaf_memeq ( +decaf_bool_t DECAF_API_VIS decaf_memeq ( const void *data1, const void *data2, size_t size -) DECAF_NONNULL DECAF_WARN_UNUSED DECAF_API_VIS; +) DECAF_NONNULL DECAF_WARN_UNUSED; #ifdef __cplusplus } /* extern "C" */ diff --git a/src/public_include/decaf/secure_buffer.hxx b/src/public_include/decaf/secure_buffer.hxx index 073a377..79aaff1 100644 --- a/src/public_include/decaf/secure_buffer.hxx +++ b/src/public_include/decaf/secure_buffer.hxx @@ -19,6 +19,10 @@ #include #include +#if defined(_MSC_VER) // MSVC does not have built in posix_memalign +#define posix_memalign(p, a, s) (((*(p)) = _aligned_malloc((s), (a))), *(p) ?0 :errno) +#endif + /** @cond internal */ #if __cplusplus >= 201103L #define DECAF_NOEXCEPT noexcept diff --git a/src/public_include/decaf/sha512.h b/src/public_include/decaf/sha512.h index ab810b4..dfe5808 100644 --- a/src/public_include/decaf/sha512.h +++ b/src/public_include/decaf/sha512.h @@ -28,17 +28,17 @@ typedef struct decaf_sha512_ctx_s { } decaf_sha512_ctx_s, decaf_sha512_ctx_t[1]; /** Initialize a SHA-512 context. */ -void decaf_sha512_init(decaf_sha512_ctx_t ctx) DECAF_NONNULL DECAF_API_VIS; +void DECAF_API_VIS decaf_sha512_init(decaf_sha512_ctx_t ctx) DECAF_NONNULL; /** Update context by hashing part of a message. */ -void decaf_sha512_update(decaf_sha512_ctx_t ctx, const uint8_t *message, size_t message_len) DECAF_NONNULL DECAF_API_VIS; +void DECAF_API_VIS decaf_sha512_update(decaf_sha512_ctx_t ctx, const uint8_t *message, size_t message_len) DECAF_NONNULL; /** Finalize context and write out hash. * @param [inout] ctx The context. Will be destroyed and re-initialized on return. * @param [out] output Place to store the output hash. * @param [in] output_len Length in bytes of the output hash. Must between 0 and 64, inclusive. */ -void decaf_sha512_final(decaf_sha512_ctx_t ctx, uint8_t *output, size_t output_len) DECAF_NONNULL DECAF_API_VIS; +void DECAF_API_VIS decaf_sha512_final(decaf_sha512_ctx_t ctx, uint8_t *output, size_t output_len) DECAF_NONNULL; /** Securely destroy a SHA512 context. */ static inline void decaf_sha512_destroy(decaf_sha512_ctx_t ctx) { diff --git a/src/public_include/decaf/shake.h b/src/public_include/decaf/shake.h index ae125b9..9e847d1 100644 --- a/src/public_include/decaf/shake.h +++ b/src/public_include/decaf/shake.h @@ -43,10 +43,10 @@ extern "C" { * @param [out] sponge The object to initialize. * @param [in] params The sponge's parameter description. */ -void decaf_sha3_init ( +void DECAF_API_VIS decaf_sha3_init ( decaf_keccak_sponge_t sponge, const struct decaf_kparams_s *params -) DECAF_API_VIS; +); /** * @brief Absorb data into a DECAF_SHA3 or DECAF_SHAKE hash context. @@ -56,11 +56,11 @@ void decaf_sha3_init ( * @return DECAF_FAILURE if the sponge has already been used for output. * @return DECAF_SUCCESS otherwise. */ -decaf_error_t decaf_sha3_update ( +decaf_error_t DECAF_API_VIS decaf_sha3_update ( struct decaf_keccak_sponge_s * __restrict__ sponge, const uint8_t *in, size_t len -) DECAF_API_VIS; +); /** * @brief Squeeze output data from a DECAF_SHA3 or DECAF_SHAKE hash context. @@ -73,11 +73,11 @@ decaf_error_t decaf_sha3_update ( * @return DECAF_FAILURE if the sponge has exhausted its output capacity. * @return DECAF_SUCCESS otherwise. */ -decaf_error_t decaf_sha3_output ( +decaf_error_t DECAF_API_VIS decaf_sha3_output ( decaf_keccak_sponge_t sponge, uint8_t * __restrict__ out, size_t len -) DECAF_API_VIS; +); /** * @brief Squeeze output data from a DECAF_SHA3 or DECAF_SHAKE hash context. @@ -87,20 +87,20 @@ decaf_error_t decaf_sha3_output ( * @param [out] out The output data. * @param [in] len The requested output data length in bytes. */ -decaf_error_t decaf_sha3_final ( +decaf_error_t DECAF_API_VIS decaf_sha3_final ( decaf_keccak_sponge_t sponge, uint8_t * __restrict__ out, size_t len -) DECAF_API_VIS; +); /** * @brief Reset the sponge to the empty string. * * @param [inout] sponge The context. */ -void decaf_sha3_reset ( +void DECAF_API_VIS decaf_sha3_reset ( decaf_keccak_sponge_t sponge -) DECAF_API_VIS; +); /** * @brief Return the default output length of the sponge construction, @@ -108,9 +108,9 @@ void decaf_sha3_reset ( * * Returns n/8 for DECAF_SHA3-n and 2n/8 for DECAF_SHAKE-n. */ -size_t decaf_sha3_default_output_bytes ( +size_t DECAF_API_VIS decaf_sha3_default_output_bytes ( const decaf_keccak_sponge_t sponge /**< [inout] The context. */ -) DECAF_API_VIS; +); /** * @brief Return the default output length of the sponge construction, @@ -118,17 +118,17 @@ size_t decaf_sha3_default_output_bytes ( * * Returns n/8 for DECAF_SHA3-n and SIZE_MAX for DECAF_SHAKE-n. */ -size_t decaf_sha3_max_output_bytes ( +size_t DECAF_API_VIS decaf_sha3_max_output_bytes ( const decaf_keccak_sponge_t sponge /**< [inout] The context. */ -) DECAF_API_VIS; +); /** * @brief Destroy a DECAF_SHA3 or DECAF_SHAKE sponge context by overwriting it with 0. * @param [out] sponge The context. */ -void decaf_sha3_destroy ( +void DECAF_API_VIS decaf_sha3_destroy ( decaf_keccak_sponge_t sponge -) DECAF_API_VIS; +); /** * @brief Hash (in) to (out) @@ -138,19 +138,78 @@ void decaf_sha3_destroy ( * @param [in] outlen The length of the output data. * @param [in] params The parameters of the sponge hash. */ -decaf_error_t decaf_sha3_hash ( +decaf_error_t DECAF_API_VIS decaf_sha3_hash ( uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen, const struct decaf_kparams_s *params -) DECAF_API_VIS; +); /* FUTURE: expand/doxygenate individual DECAF_SHAKE/DECAF_SHA3 instances? */ +#if defined _MSC_VER + +/** @cond internal */ +#define DECAF_DEC_SHAKE(n) \ + extern const struct DECAF_API_VIS decaf_kparams_s DECAF_SHAKE##n##_params_s; \ + typedef struct decaf_shake##n##_ctx_s { decaf_keccak_sponge_t s; } decaf_shake##n##_ctx_t[1]; \ + static inline void DECAF_NONNULL decaf_shake##n##_init(decaf_shake##n##_ctx_t sponge) { \ + decaf_sha3_init(sponge->s, &DECAF_SHAKE##n##_params_s); \ + } \ + static inline void DECAF_NONNULL decaf_shake##n##_gen_init(decaf_keccak_sponge_t sponge) { \ + decaf_sha3_init(sponge, &DECAF_SHAKE##n##_params_s); \ + } \ + static inline decaf_error_t DECAF_NONNULL decaf_shake##n##_update(decaf_shake##n##_ctx_t sponge, const uint8_t *in, size_t inlen ) { \ + return decaf_sha3_update(sponge->s, in, inlen); \ + } \ + static inline void DECAF_NONNULL decaf_shake##n##_final(decaf_shake##n##_ctx_t sponge, uint8_t *out, size_t outlen ) { \ + decaf_sha3_output(sponge->s, out, outlen); \ + decaf_sha3_init(sponge->s, &DECAF_SHAKE##n##_params_s); \ + } \ + static inline void DECAF_NONNULL decaf_shake##n##_output(decaf_shake##n##_ctx_t sponge, uint8_t *out, size_t outlen ) { \ + decaf_sha3_output(sponge->s, out, outlen); \ + } \ + static inline void DECAF_NONNULL decaf_shake##n##_hash(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen) { \ + decaf_sha3_hash(out,outlen,in,inlen,&DECAF_SHAKE##n##_params_s); \ + } \ + static inline void DECAF_NONNULL decaf_shake##n##_destroy( decaf_shake##n##_ctx_t sponge ) { \ + decaf_sha3_destroy(sponge->s); \ + } + +#define DECAF_DEC_SHA3(n) \ + extern const struct DECAF_API_VIS decaf_kparams_s DECAF_SHA3_##n##_params_s; \ + typedef struct decaf_sha3_##n##_ctx_s { decaf_keccak_sponge_t s; } decaf_sha3_##n##_ctx_t[1]; \ + static inline void DECAF_NONNULL decaf_sha3_##n##_init(decaf_sha3_##n##_ctx_t sponge) { \ + decaf_sha3_init(sponge->s, &DECAF_SHA3_##n##_params_s); \ + } \ + static inline void DECAF_NONNULL decaf_sha3_##n##_gen_init(decaf_keccak_sponge_t sponge) { \ + decaf_sha3_init(sponge, &DECAF_SHA3_##n##_params_s); \ + } \ + static inline decaf_error_t DECAF_NONNULL decaf_sha3_##n##_update(decaf_sha3_##n##_ctx_t sponge, const uint8_t *in, size_t inlen ) { \ + return decaf_sha3_update(sponge->s, in, inlen); \ + } \ + static inline decaf_error_t DECAF_NONNULL decaf_sha3_##n##_final(decaf_sha3_##n##_ctx_t sponge, uint8_t *out, size_t outlen ) { \ + decaf_error_t ret = decaf_sha3_output(sponge->s, out, outlen); \ + decaf_sha3_init(sponge->s, &DECAF_SHA3_##n##_params_s); \ + return ret; \ + } \ + static inline decaf_error_t DECAF_NONNULL decaf_sha3_##n##_output(decaf_sha3_##n##_ctx_t sponge, uint8_t *out, size_t outlen ) { \ + return decaf_sha3_output(sponge->s, out, outlen); \ + } \ + static inline decaf_error_t DECAF_NONNULL decaf_sha3_##n##_hash(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen) { \ + return decaf_sha3_hash(out,outlen,in,inlen,&DECAF_SHA3_##n##_params_s); \ + } \ + static inline void DECAF_NONNULL decaf_sha3_##n##_destroy(decaf_sha3_##n##_ctx_t sponge) { \ + decaf_sha3_destroy(sponge->s); \ + } +/** @endcond */ + +#else // _MSC_VER + /** @cond internal */ #define DECAF_DEC_SHAKE(n) \ - extern const struct decaf_kparams_s DECAF_SHAKE##n##_params_s DECAF_API_VIS; \ + DECAF_API_VIS extern const struct decaf_kparams_s DECAF_SHAKE##n##_params_s; \ typedef struct decaf_shake##n##_ctx_s { decaf_keccak_sponge_t s; } decaf_shake##n##_ctx_t[1]; \ static inline void DECAF_NONNULL decaf_shake##n##_init(decaf_shake##n##_ctx_t sponge) { \ decaf_sha3_init(sponge->s, &DECAF_SHAKE##n##_params_s); \ @@ -176,7 +235,7 @@ decaf_error_t decaf_sha3_hash ( } #define DECAF_DEC_SHA3(n) \ - extern const struct decaf_kparams_s DECAF_SHA3_##n##_params_s DECAF_API_VIS; \ + DECAF_API_VIS extern const struct decaf_kparams_s DECAF_SHA3_##n##_params_s; \ typedef struct decaf_sha3_##n##_ctx_s { decaf_keccak_sponge_t s; } decaf_sha3_##n##_ctx_t[1]; \ static inline void DECAF_NONNULL decaf_sha3_##n##_init(decaf_sha3_##n##_ctx_t sponge) { \ decaf_sha3_init(sponge->s, &DECAF_SHA3_##n##_params_s); \ @@ -202,6 +261,10 @@ decaf_error_t decaf_sha3_hash ( decaf_sha3_destroy(sponge->s); \ } /** @endcond */ + +#endif // _MSC_VER + + DECAF_DEC_SHAKE(128) DECAF_DEC_SHAKE(256) diff --git a/src/public_include/decaf/shake.hxx b/src/public_include/decaf/shake.hxx index 58e360b..7eda93c 100644 --- a/src/public_include/decaf/shake.hxx +++ b/src/public_include/decaf/shake.hxx @@ -173,6 +173,17 @@ public: } }; + +#if defined _MSC_VER // MSVC does not want tempalte<> syntax, gcc cannot live without it +/** @cond internal */ +inline const struct decaf_kparams_s *SHAKE<128>::get_params() { return &DECAF_SHAKE128_params_s; } +inline const struct decaf_kparams_s *SHAKE<256>::get_params() { return &DECAF_SHAKE256_params_s; } +inline const struct decaf_kparams_s *SHA3<224>::get_params() { return &DECAF_SHA3_224_params_s; } +inline const struct decaf_kparams_s *SHA3<256>::get_params() { return &DECAF_SHA3_256_params_s; } +inline const struct decaf_kparams_s *SHA3<384>::get_params() { return &DECAF_SHA3_384_params_s; } +inline const struct decaf_kparams_s *SHA3<512>::get_params() { return &DECAF_SHA3_512_params_s; } +/** @endcond */ +#else /** @cond internal */ template<> inline const struct decaf_kparams_s *SHAKE<128>::get_params() { return &DECAF_SHAKE128_params_s; } template<> inline const struct decaf_kparams_s *SHAKE<256>::get_params() { return &DECAF_SHAKE256_params_s; } @@ -181,6 +192,8 @@ template<> inline const struct decaf_kparams_s *SHA3<256>::get_params() { return template<> inline const struct decaf_kparams_s *SHA3<384>::get_params() { return &DECAF_SHA3_384_params_s; } template<> inline const struct decaf_kparams_s *SHA3<512>::get_params() { return &DECAF_SHA3_512_params_s; } /** @endcond */ +#endif + } /* namespace decaf */ diff --git a/src/public_include/decaf/spongerng.h b/src/public_include/decaf/spongerng.h index eaad167..7b0836a 100644 --- a/src/public_include/decaf/spongerng.h +++ b/src/public_include/decaf/spongerng.h @@ -27,12 +27,12 @@ typedef struct { typedef decaf_keccak_prng_s decaf_keccak_prng_t[1]; /** Initialize a sponge-based CSPRNG from a buffer. */ -void decaf_spongerng_init_from_buffer ( +void DECAF_API_VIS decaf_spongerng_init_from_buffer ( decaf_keccak_prng_t prng, /**< [out] The PRNG object. */ const uint8_t *__restrict__ in, /**< [in] The initialization data. */ size_t len, /**< [in] The length of the initialization data. */ int deterministic /**< [in] If zero, allow RNG to stir in nondeterministic data from RDRAND or RDTSC.*/ -) DECAF_NONNULL DECAF_API_VIS; +) DECAF_NONNULL; /** * @brief Initialize a sponge-based CSPRNG from a file. @@ -40,12 +40,12 @@ void decaf_spongerng_init_from_buffer ( * @retval DECAF_FAILURE failure. * @note On failure, errno can be used to determine the cause. */ -decaf_error_t decaf_spongerng_init_from_file ( +decaf_error_t DECAF_API_VIS decaf_spongerng_init_from_file ( decaf_keccak_prng_t prng, /**< [out] The PRNG object. */ const char *file, /**< [in] A name of a file containing initial data. */ size_t len, /**< [in] The length of the initial data. Must be positive. */ int deterministic /**< [in] If zero, allow RNG to stir in nondeterministic data from RDRAND or RDTSC. */ -) DECAF_NONNULL DECAF_API_VIS DECAF_WARN_UNUSED; +) DECAF_NONNULL DECAF_WARN_UNUSED; /** * @brief Initialize a nondeterministic sponge-based CSPRNG from /dev/urandom. @@ -53,23 +53,23 @@ decaf_error_t decaf_spongerng_init_from_file ( * @retval DECAF_FAILURE failure. * @note On failure, errno can be used to determine the cause. */ -decaf_error_t decaf_spongerng_init_from_dev_urandom ( +decaf_error_t DECAF_API_VIS decaf_spongerng_init_from_dev_urandom ( decaf_keccak_prng_t prng /**< [out] sponge The sponge object. */ -) DECAF_API_VIS DECAF_WARN_UNUSED; +) DECAF_WARN_UNUSED; /** Output bytes from a sponge-based CSPRNG. */ -void decaf_spongerng_next ( +void DECAF_API_VIS decaf_spongerng_next ( decaf_keccak_prng_t prng, /**< [inout] The PRNG object. */ uint8_t * __restrict__ out, /**< [out] Output buffer. */ size_t len /**< [in] Number of bytes to output. */ -) DECAF_API_VIS; +); /** Stir entropy data into a sponge-based CSPRNG from a buffer. */ -void decaf_spongerng_stir ( +void DECAF_API_VIS decaf_spongerng_stir ( decaf_keccak_prng_t prng, /**< [out] The PRNG object. */ const uint8_t * __restrict__ in, /**< [in] The entropy data. */ size_t len /**< [in] The length of the initial data. */ -) DECAF_NONNULL DECAF_API_VIS; +) DECAF_NONNULL; /** Securely destroy a sponge RNG object by overwriting it. */ static DECAF_INLINE void diff --git a/src/spongerng.c b/src/spongerng.c index 52630b5..fea7702 100644 --- a/src/spongerng.c +++ b/src/spongerng.c @@ -22,7 +22,13 @@ #include #include #include -#include +#if defined(_MSC_VER) +# include +#include +typedef SSIZE_T ssize_t; +#else +# include +#endif /** Get entropy from a CPU, preferably in the form of RDRAND, but possibly instead from RDTSC. */ static void get_cpu_entropy(uint8_t *entropy, size_t len) { diff --git a/test/bench_decaf.cxx b/test/bench_decaf.cxx index ed77640..88a26c8 100644 --- a/test/bench_decaf.cxx +++ b/test/bench_decaf.cxx @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -23,13 +22,31 @@ using namespace decaf; +#if defined _MSC_VER // Turn off attribute code and rename inline +#define __attribute__(x) // Turn off attribute code +#define __attribute(x) +#define __inline__ __inline // Use MSVC inline +#endif // MSVC static __inline__ void __attribute__((unused)) ignore_result ( int result ) { (void)result; } +#if defined _MSC_VER // MSVC does not have gettimeoftheday +#include +static double now(void) { + static const auto beg = std::chrono::high_resolution_clock::now(); + auto end_time = std::chrono::high_resolution_clock::now(); + auto time = end_time - beg; + double duration = 0.000001 * std::chrono::duration_cast(time).count(); + return duration; +} +#else +#include static double now(void) { struct timeval tv; gettimeofday(&tv, NULL); return tv.tv_sec + tv.tv_usec/1000000.0; } +#endif + // RDTSC from the chacha code #ifndef __has_builtin diff --git a/test/shakesum.c b/test/shakesum.c index e627797..7d9019a 100644 --- a/test/shakesum.c +++ b/test/shakesum.c @@ -9,7 +9,13 @@ */ #include +#if defined _MSC_VER // MSVC has not unistd.h +#include +#include +typedef SSIZE_T ssize_t; +#else #include +#endif #include #include #include