Adding testing support (#3)

* adding a testing "framework", a few tests and fixing some minor bugs

* addressing easy PR comments, adding a .editorconfig to help maintain a consistent coding style, changing the tests indetation to tabs.

* preventing the compiler to optimize cc_clear

* fixing typo

Co-authored-by: Andrew Hyatt <ahyattdev@icloud.com>
This commit is contained in:
Fabrice 2020-01-14 13:14:12 -06:00 committed by Andrew Hyatt
parent 9c0ab18af9
commit 1da2274345
13 changed files with 267 additions and 28 deletions

9
.editorconfig Normal file
View File

@ -0,0 +1,9 @@
[*]
end_of_line = lf
insert_final_newline = true
[*.{c,h}]
indent_style = tab
[CMakeLists.txt]
indent_style = tab

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/build
/.idea/

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "external/ctest"]
path = external/ctest
url = git@github.com:farmisen/ctest.git

View File

@ -1,10 +1,41 @@
project(darling-corecrypto)
project(darling-corecrypto C)
add_compile_options(
-nostdinc
-Wno-return-type
-Werror
)
# User option to turn the corecrypto specific tests
option(CORECRYPTO_ENABLE_TESTS
"Enable the compilation and running of corecrypto's unit tests" OFF)
# Test are built only if BUILD_TESTING && CORECRYPTO_ENABLE_TESTS are set to ON
include(CTest)
if (BUILD_TESTING AND CORECRYPTO_ENABLE_TESTS)
set(BUILD_CORECRYPTO_TESTS ON)
else (BUILD_TESTING AND CORECRYPTO_ENABLE_TESTS)
set(BUILD_CORECRYPTO_TESTS OFF)
endif (BUILD_TESTING AND CORECRYPTO_ENABLE_TESTS)
# Set endianess for test builds
if (BUILD_CORECRYPTO_TESTS)
include (TestBigEndian)
TEST_BIG_ENDIAN(IS_BIG_ENDIAN)
if(IS_BIG_ENDIAN)
add_definitions(-D__BIG_ENDIAN__=1)
else(IS_BIG_ENDIAN)
add_definitions(-D__LITTLE_ENDIAN__=1)
endif(IS_BIG_ENDIAN)
endif (BUILD_CORECRYPTO_TESTS)
# Set env dependent compile options
if (NOT BUILD_CORECRYPTO_TESTS)
add_compile_options(
-nostdinc
-Wno-return-type
-Werror
)
else (NOT BUILD_CORECRYPTO_TESTS)
add_compile_options(
-Wno-return-type
-Werror
)
endif (NOT BUILD_CORECRYPTO_TESTS)
add_definitions(
-DDEBUG
@ -15,9 +46,8 @@ include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/include
)
set(DYLIB_INSTALL_NAME "/usr/lib/system/libcorecrypto.dylib")
add_circular(corecrypto FAT
SOURCES
set(corecrypto_sources
src/cc.c
src/ccdigest.c
src/ccmd2.c
@ -55,19 +85,40 @@ add_circular(corecrypto FAT
src/ccansikdf.c
src/ccecies.c
src/ccrng_pbkdf2.c
SIBLINGS
system_dyld
compiler_rt
system_kernel
platform
system_malloc
system_c
system_blocks
system_pthread
macho
libdispatch_shared
)
make_fat(corecrypto)
install(TARGETS corecrypto DESTINATION libexec/darling/usr/lib/system)
if (NOT BUILD_CORECRYPTO_TESTS)
set(DYLIB_INSTALL_NAME "/usr/lib/system/libcorecrypto.dylib")
add_circular(corecrypto FAT
SOURCES
${corecrypto_sources}
SIBLINGS
system_dyld
compiler_rt
system_kernel
platform
system_malloc
system_c
system_blocks
system_pthread
macho
libdispatch_shared
)
make_fat(corecrypto)
else (NOT BUILD_CORECRYPTO_TESTS)
add_library(corecrypto
SHARED
${corecrypto_sources}
)
endif (NOT BUILD_CORECRYPTO_TESTS)
if (NOT BUILD_CORECRYPTO_TESTS)
install(TARGETS corecrypto DESTINATION libexec/darling/usr/lib/system)
else (NOT BUILD_CORECRYPTO_TESTS)
enable_testing()
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/tests/include
)
add_subdirectory(external/ctest)
add_subdirectory(tests)
endif (NOT BUILD_CORECRYPTO_TESTS)

24
README.md Normal file
View File

@ -0,0 +1,24 @@
# Darling-CoreCrypto
Rewrite of Apple CoreCrypto for the Darling project.
## Testing
Setting the CORECRYPTO_ENABLE_TESTS CMake option to ON as shown below will build CoreCrypto and the test suite
for your native host instead of Darling. It has only been tested on Ubuntu 18.04 and OSX 10.14.
```
$ mkdir build
$ cd build
$ cmake -DCORECRYPTO_ENABLE_TESTS=ON ..
$ make
$ ./tests/test_corecrypto
```
### Continuous testing
The following command will watch for a any change in the CoreCrypto lib, CMake files or tests and will rebuild and run the test suite.
```
$ ./tests/watch.sh
```

1
external/ctest vendored Submodule

@ -0,0 +1 @@
Subproject commit 632ec756145658f060cc812b13860b0f490815e9

View File

@ -88,7 +88,7 @@ size_t ccoid_size(ccoid_t oid) {
return 2 + CCOID(oid)[1];
}
CC_INLINE CC_PURE CC_NONNULL((1)) CC_NONNULL((2))
CC_INLINE CC_PURE CC_NONNULL_TU((1)) CC_NONNULL_TU((2))
bool ccoid_equal(ccoid_t oid1, ccoid_t oid2) {
return (ccoid_size(oid1) == ccoid_size(oid2)
&& memcmp(CCOID(oid1), CCOID(oid2), ccoid_size(oid1))== 0);

View File

@ -33,7 +33,10 @@ struct ccrng_state * ccDRBGGetRngState(int *error) {
void cc_clear(size_t len, void *dst)
{
memset(dst, 0, len);
volatile unsigned char *ptr = (volatile unsigned char*) dst;
while (len--) {
*ptr++ = 0;
}
}
/* https://cryptocoding.net/index.php/Coding_rules#Avoid_branchings_controlled_by_secret_data */
@ -41,13 +44,16 @@ void* cc_muxp(int s, const void *a, const void *b)
{
uintptr_t mask = -(s != 0);
uintptr_t ret = mask & (((uintptr_t)a) ^ ((uintptr_t)b));
ret = ret ^ ((uintptr_t)a);
ret = ret ^ ((uintptr_t)b);
return (void*) ret;
}
/* https://cryptocoding.net/index.php/Coding_rules#Compare_secret_strings_in_constant_time */
int cc_cmp_safe(size_t size, const void* a, const void* b)
{
if ( size == 0) {
return 1;
}
const unsigned char *_a = (const unsigned char *) a;
const unsigned char *_b = (const unsigned char *) b;
unsigned char result = 0;
@ -55,9 +61,9 @@ int cc_cmp_safe(size_t size, const void* a, const void* b)
for (i = 0; i < size; i++)
{
result |= _a[i] ^ _b[i];
result |= (unsigned) _a[i] ^ _b[i];
}
return result;
return result ? 1 : 0;
}

11
tests/CMakeLists.txt Normal file
View File

@ -0,0 +1,11 @@
set(TEST_SOURCES
main.c
cc_tests.c
cc_priv_tests.c
)
add_executable(test_corecrypto ${TEST_SOURCES})
target_link_libraries(test_corecrypto ctest corecrypto)
add_test(TestCorecrypto test_corecrypto)

9
tests/cc_priv_tests.c Normal file
View File

@ -0,0 +1,9 @@
#include <ctest.h>
#include "../include/corecrypto/cc_priv.h"
CTEST(cc, cc_muxp) {
const unsigned char a;
const unsigned char b;
ASSERT_TRUE(&a == cc_muxp(1, (void *) &a, (void *) &b));
ASSERT_TRUE(&b == cc_muxp(0, (void *) &a, (void *) &b));
}

99
tests/cc_tests.c Normal file
View File

@ -0,0 +1,99 @@
#include <stdlib.h>
#include <ctest.h>
#include "../include/corecrypto/cc.h"
enum { SIZE = 256 };
CTEST(cc, cc_zero) {
unsigned char buffer[SIZE];
for(size_t i = 0 ; i < SIZE; ++i) {
buffer[i] = (unsigned char) i;
}
cc_zero(SIZE, buffer);
for (size_t i = 0; i < SIZE; ++i) {
ASSERT_EQUAL('\0', buffer[i]);
}
}
CTEST(cc, cc_clear) {
unsigned char buffer[SIZE];
for(size_t i = 0 ; i < SIZE; ++i) {
buffer[i] = (unsigned char) i;
}
cc_clear(SIZE, buffer);
for (size_t i = 0; i < SIZE; ++i) {
ASSERT_EQUAL('\0', buffer[i]);
}
}
CTEST(cc, cc_copy) {
unsigned char buffer1[SIZE];
unsigned char buffer2[SIZE];
for(size_t i = 0 ; i < SIZE; ++i) {
buffer1[i] = (unsigned char) rand();
}
cc_copy(SIZE, buffer2, buffer1);
for (size_t i = 0; i < SIZE; ++i) {
ASSERT_EQUAL(buffer1[i], buffer2[i]);
}
}
CTEST(cc, cc_xor) {
unsigned char buffer1[SIZE];
unsigned char buffer2[SIZE];
unsigned char buffer3[SIZE];
for(size_t i = 0 ; i < SIZE; ++i) {
buffer1[i] = (unsigned char) rand();
buffer2[i] = (unsigned char) rand();
}
cc_xor(SIZE, buffer3, buffer1, buffer2);
for (size_t i = 0; i < SIZE; ++i) {
ASSERT_EQUAL(buffer3[i], buffer1[i] ^ buffer2[i]);
}
cc_xor(SIZE, buffer3, buffer3, buffer2);
for (size_t i = 0; i < SIZE; ++i) {
ASSERT_EQUAL(buffer3[i], buffer1[i]);
}
cc_xor(SIZE, buffer3, buffer3, buffer3);
for (size_t i = 0; i < SIZE; ++i) {
ASSERT_EQUAL('\0', buffer3[i]);
}
}
CTEST(cc, cc_cmp_safe) {
unsigned char buffer1[SIZE];
unsigned char buffer2[SIZE];
for(size_t i = 0 ; i < SIZE; ++i) {
buffer1[i] = (unsigned char) rand();
buffer2[i] = (unsigned char) rand();
}
ASSERT_EQUAL(0, cc_cmp_safe(SIZE, buffer1, buffer1));
ASSERT_EQUAL(1,cc_cmp_safe(SIZE, buffer1, buffer2));
ASSERT_EQUAL(1,cc_cmp_safe(0, buffer1, buffer1));
}
CTEST(cc, CC_SWAP) {
unsigned int a = 127;
unsigned int b = 257;
CC_SWAP(a,b);
ASSERT_EQUAL(a, 257);
ASSERT_EQUAL(b, 127);
CC_SWAP(a,b);
ASSERT_EQUAL(a, 127);
ASSERT_EQUAL(b, 257);
}
CTEST(cc, CC_MAX) {
ASSERT_EQUAL(128, CC_MAX(63, 128));
ASSERT_EQUAL(-128, CC_MAX(-163, -128));
ASSERT_EQUAL(128, CC_MAX(128, -128));
}
CTEST(cc, CC_MIN) {
ASSERT_EQUAL(63, CC_MIN(63, 128));
ASSERT_EQUAL(-163, CC_MIN(-163, -128));
ASSERT_EQUAL(-128, CC_MIN(128, -128));
}

View File

@ -0,0 +1,12 @@
#if defined(__APPLE__)
#include <libkern/OSByteOrder.h>
#else
#ifndef _OS_BYTE_ORDER_H
#define _OS_BYTE_ORDER_H 1
#include <byteswap.h>
#define OSSwapInt32(x) __bswap_32(x)
#define _OSSwapInt64 __bswap_64
#endif // _OS_BYTE_ORDER_H
#endif // defined(__APPLE__)

12
tests/main.c Normal file
View File

@ -0,0 +1,12 @@
#define CTEST_MAIN
// uncomment lines below to enable/disable features. See README.md for details
#define CTEST_SEGFAULT
//#define CTEST_NO_COLORS
#define CTEST_COLOR_OK
#include <ctest.h>
int main(int argc, const char *argv[]) {
return ctest_main(argc, argv);
}