Skip to content

Commit

Permalink
Initial import
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastinas committed Apr 9, 2023
0 parents commit 181b17b
Show file tree
Hide file tree
Showing 9 changed files with 1,020 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build*/
19 changes: 19 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Copyright (c) 2019-2023 Sebastian Ramacher, AIT Austrian Institute of Technology

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the ""Software""), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
144 changes: 144 additions & 0 deletions compat.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/*
* SPDX-License-Identifier: MIT
*/

#ifdef HAVE_CONFIG_H
#include <config.h>
#else
#include "macros.h"

/* define HAVE_* for more known good configurations */
#if !defined(HAVE_POSIX_MEMALIGN) && \
((defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) || defined(__APPLE__))
/* defined in POSIX and available on OS X */
#define HAVE_POSIX_MEMALIGN
#endif /* HAVE_POSIX_MEMALIGN */

#if !defined(HAVE_MEMALIGN) && defined(__linux__)
/* always available on Linux */
#define HAVE_MEMALIGN
#endif /* HAVE_MEMALIGN */

#if !defined(HAVE_CONSTTIME_MEMEQUAL) && NETBSD_CHECK(7, 0)
/* consttime_memequal was introduced in NetBSD 7.0 */
#define HAVE_CONSTTIME_MEMEQUAL
#endif /* HAVE_CONSTTIME_MEMEQUAL */
#endif /* HAVE_CONFIG_H */

#include "compat.h"

#if !defined(HAVE_ALIGNED_ALLOC)
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#if !defined(HAVE_POSIX_MEMALIGN) || defined(__MING32__) || defined(__MING64__) || defined(_MSC_VER)
#include <malloc.h>
#endif

#if defined(HAVE_POSIX_MEMALIGN)
static_assert((sizeof(void*) & (sizeof(void*) - 1)) == 0, "sizeof void* is not a power of 2");
#endif

/* The fallback implementation tries to be as generic as possible. While all callers in this code
* base satisfy all requirements, we still check them. Thereby, the fallback implementation may be
* of use for others as well. */
void* faest_aligned_alloc(size_t alignment, size_t size) {
/* check alignment (power of 2) and size (multiple of alignment) */
if (alignment & (alignment - 1) || size & (alignment - 1)) {
errno = EINVAL;
return NULL;
}

#if defined(HAVE_POSIX_MEMALIGN)
/* check alignment (needs to be multiple of sizeof(void*)); posix_memalign has this additional
* requirement */
if (alignment < sizeof(void*)) {
alignment = sizeof(void*);
/* fix up size; needs to be a multiple of alignment, i.e., sizeof(void*) */
size = (size + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
}

void* ptr = NULL;
const int err = posix_memalign(&ptr, alignment, size);
if (err) {
errno = err;
}
return ptr;
#elif defined(HAVE_MEMALIGN)
return memalign(alignment, size);
#elif defined(__MINGW32__) || defined(__MINGW64__)
return __mingw_aligned_malloc(size, alignment);
#elif defined(_MSC_VER)
return _aligned_malloc(size, alignment);
#else
if (!size) {
return NULL;
}
const size_t offset = alignment - 1 + sizeof(uint8_t);
uint8_t* buffer = malloc(size + offset);
if (!buffer) {
return NULL;
}

uint8_t* ptr = (uint8_t*)(((uintptr_t)(buffer) + offset) & ~(alignment - 1));
ptrdiff_t diff = ptr - buffer;
if (diff > UINT8_MAX) {
/* this should never happen in our code, but just to be safe */
free(buffer);
errno = EINVAL;
return NULL;
}
ptr[-1] = diff;
return ptr;
#endif
}

void faest_aligned_free(void* ptr) {
#if defined(HAVE_POSIX_MEMALIGN) || defined(HAVE_MEMALIGN)
free(ptr);
#elif defined(__MINGW32__) || defined(__MINGW64__)
__mingw_aligned_free(ptr);
#elif defined(_MSC_VER)
_aligned_free(ptr);
#else
if (ptr) {
uint8_t* u8ptr = ptr;
free(u8ptr - u8ptr[-1]);
}
#endif
}
#endif /* HAVE_ALIGNED_ALLOC */

#if !defined(HAVE_TIMINGSAFE_BCMP)
int faest_timingsafe_bcmp(const void* a, const void* b, size_t len) {
#if defined(HAVE_CONSTTIME_MEMEQUAL)
return !consttime_memequal(a, b, len);
#else
const unsigned char* p1 = a;
const unsigned char* p2 = b;

unsigned int res = 0;
for (; len; --len, ++p1, ++p2) {
res |= *p1 ^ *p2;
}
return res;
#endif
}
#endif /* HAVE_TIMINGSAFE_BCMP */

#if !defined(HAVE_EXPLICIT_BZERO)
#if defined(_WIN32)
#include <windows.h>
#endif

void faest_explicit_bzero(void* a, size_t len) {
#if defined(_WIN32)
SecureZeroMemory(a, len);
#else
volatile char* p = a;
for (; len; ++p, --len) {
*p = 0;
}
#endif
}
#endif /* HAVE_EXPLICIT_BZERO */
197 changes: 197 additions & 0 deletions compat.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
/*
* SPDX-License-Identifier: MIT
*/

#ifndef FAEST_COMPAT_H
#define FAEST_COMPAT_H

#if defined(HAVE_CONFIG_H)
#include <config.h>
#endif

#include "macros.h"

#include <stddef.h>

#if !defined(HAVE_CONFIG_H) && !defined(OQS)
/* In case cmake checks were not run, define HAVE_* for known good configurations. We skip those if
* building for OQS, as the compat functions from there can be used instead. */
#if defined(__OpenBSD__)
#include <sys/param.h>
#endif /* __OpenBSD__ */

#if !defined(HAVE_ALIGNED_ALLOC) && !defined(__APPLE__) && !defined(__MINGW32__) && \
!defined(__MINGW64__) && !defined(_MSC_VER) && !defined(__ANDROID__) && \
(defined(_ISOC11_SOURCE) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L))
/* aligned_alloc was introduced in ISO C 2011. Even if building with -std=c11, some toolchains do
* not provide aligned_alloc, including toolchains for Android, OS X, MinGW, and others. */
#define HAVE_ALIGNED_ALLOC
#endif /* HAVE_ALIGNED_ALLOC */

#if !defined(HAVE_EXPLICIT_BZERO) && \
(GLIBC_CHECK(2, 25) || (defined(__OpenBSD__) && OpenBSD >= 201405) || FREEBSD_CHECK(11, 0) || \
NETBSD_CHECK(8, 0))
/* explicit_bzero was introduced in glibc 2.35, OpenBSD 5.5, FreeBSD 11.0 and NetBSD 8.0 */
#define HAVE_EXPLICIT_BZERO
#endif /* HAVE_EXPLICIT_BZERO */

#if !defined(HAVE_TIMINGSAFE_BCMP) && ((defined(__OpenBSD__) && OpenBSD >= 201105) || \
FREEBSD_CHECK(12, 0) || MACOSX_CHECK(10, 12, 1))
/* timingsafe_bcmp was introduced in OpenBSD 4.9, FreeBSD 12.0, and MacOS X 10.12 */
#define HAVE_TIMINGSAFE_BCMP
#endif /* HAVE_TIMINGSAFE_BCMP */
#endif /* !HAVE_CONFIG_H && !OQS */

#if defined(HAVE_ALIGNED_ALLOC)
#include <stdlib.h>

#define faest_aligned_alloc(alignment, size) aligned_alloc((alignment), (size))
#define faest_aligned_free(ptr) free((ptr))
#else
FAEST_BEGIN_C_DECL

/**
* Some aligned_alloc compatbility implementations require custom free
* functions, so we provide one too.
*/
void faest_aligned_free(void* ptr);
/**
* Compatibility implementation of aligned_alloc from ISO C 2011.
*/
void* faest_aligned_alloc(size_t alignment, size_t size) ATTR_MALLOC(faest_aligned_free)
ATTR_ALLOC_ALIGN(1) ATTR_ALLOC_SIZE(2);

FAEST_END_C_DECL
#endif /* HAVE_ALIGNED_ALLOC */

#include "endian_compat.h"

#if defined(HAVE_TIMINGSAFE_BCMP)
#define faest_timingsafe_bcmp(a, b, len) timingsafe_bcmp((a), (b), (len))
#else
FAEST_BEGIN_C_DECL

/**
* Compatibility implementation of timingsafe_bcmp from OpenBSD 4.9 and FreeBSD 12.0.
*/
int faest_timingsafe_bcmp(const void* a, const void* b, size_t len);

FAEST_END_C_DECL
#endif /* HAVE_TIMINGSAFE_BCMP */

#if defined(HAVE_EXPLICIT_BZERO)
#define faest_explicit_bzero(ptr, len) explicit_bzero((ptr), (len))
#else
FAEST_BEGIN_C_DECL

/**
* Compatibility implementation of explicit_bzero
*/
void faest_explicit_bzero(void* a, size_t len);

FAEST_END_C_DECL
#endif /* HAVE_EXPLICIT_BZERO */

#if defined(OQS)
#define faest_aligned_alloc(alignment, size) OQS_MEM_aligned_alloc((alignment), (size))
#define faest_aligned_free(ptr) OQS_MEM_aligned_free((ptr))
#define faest_timingsafe_bcmp(a, b, len) OQS_MEM_secure_bcmp((a), (b), (len))
#define faest_explicit_bzero(ptr, len) OQS_MEM_cleanse(ptr, len)
#endif

/* helper macros/functions for checked integer subtraction */
#if GNUC_CHECK(5, 0) || __has_builtin(__builtin_add_overflow)
#define sub_overflow_size_t(x, y, diff) __builtin_sub_overflow(x, y, diff)
#else
#include <stdbool.h>
#include <stddef.h>

ATTR_ARTIFICIAL
static inline bool sub_overflow_size_t(const size_t x, const size_t y, size_t* diff) {
*diff = x - y;
return x < y;
}
#endif

#include <stdint.h>

/* helper functions for parity computations */
#if GNUC_CHECK(4, 9) || __has_builtin(__builtin_parity)
ATTR_CONST ATTR_ARTIFICIAL static inline uint64_t parity64_uint64(uint64_t in) {
return __builtin_parityll(in);
}
#else
/* byte parity from: https://graphics.stanford.edu/~seander/bithacks.html#ParityWith64Bits */
ATTR_CONST ATTR_ARTIFICIAL static inline uint64_t parity64_uint64(uint64_t in) {
in ^= in >> 1;
in ^= in >> 2;
in = (in & 0x1111111111111111) * 0x1111111111111111;
return (in >> 60) & 1;
}
#endif

/* helper functions to compute number of leading zeroes */
#if GNUC_CHECK(4, 7) || __has_builtin(__builtin_clz)
ATTR_CONST ATTR_ARTIFICIAL static inline uint32_t clz(uint32_t x) {
return x ? __builtin_clz(x) : 32;
}
#elif defined(_MSC_VER)
#include <intrin.h>
ATTR_CONST ATTR_ARTIFICIAL static inline uint32_t clz(uint32_t x) {
unsigned long index = 0;
if (_BitScanReverse(&index, x)) {
return 31 - index;
}
return 32;
}
#else
/* Number of leading zeroes of x.
* From the book
* H.S. Warren, *Hacker's Delight*, Pearson Education, 2003.
* http://www.hackersdelight.org/hdcodetxt/nlz.c.txt
*/
ATTR_CONST ATTR_ARTIFICIAL static inline uint32_t clz(uint32_t x) {
if (!x) {
return 32;
}

uint32_t n = 1;
if (!(x >> 16)) {
n = n + 16;
x = x << 16;
}
if (!(x >> 24)) {
n = n + 8;
x = x << 8;
}
if (!(x >> 28)) {
n = n + 4;
x = x << 4;
}
if (!(x >> 30)) {
n = n + 2;
x = x << 2;
}
n = n - (x >> 31);

return n;
}
#endif

ATTR_CONST ATTR_ARTIFICIAL static inline uint32_t ceil_log2(uint32_t x) {
if (!x) {
return 0;
}
return 32 - clz(x - 1);
}

#if !defined(__cplusplus)
#include <assert.h>

/* static_assert fallback */
#if !defined(_MSC_VER) && !defined(static_assert)
#define static_assert _Static_assert
#endif
#endif

#endif
Loading

0 comments on commit 181b17b

Please sign in to comment.