aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt14
-rw-r--r--src/noscrypt.c32
-rw-r--r--src/noscrypt.h1
-rw-r--r--tests/test.c60
4 files changed, 78 insertions, 29 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3872f13..847f9fe 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -44,14 +44,10 @@ if(MSVC)
$<$<CONFIG:Debug>:/FC> #show full path in diagnostics
$<$<CONFIG:Debug>:/showIncludes> #show a list of all included header files during build
- )
-
- #only target our project
- target_compile_options(
- ${CMAKE_PROJECT_NAME}
- PRIVATE
+
$<$<CONFIG:Debug>:/wd4820> #disable warnings for struct padding and spectre mitigation wuen WX is enabled
+ $<$<CONFIG:Debug>:/wd5045> #disable warnings for spectre mitigation insertion
#for debug configs
$<$<CONFIG:Debug>:/options:strict>
@@ -78,12 +74,6 @@ elseif(CMAKE_COMPILER_IS_GNUCC)
$<$<CONFIG:Debug>:-Og>
$<$<CONFIG:Debug>:-Wall>
$<$<CONFIG:Debug>:-Werror>
- )
-
- #only target our project if building other 3rd party libs in current build
- target_compile_options(
- ${CMAKE_PROJECT_NAME}
- PRIVATE
$<$<CONFIG:Debug>:-Wall>
$<$<CONFIG:Debug>:-pedantic>
)
diff --git a/src/noscrypt.c b/src/noscrypt.c
index 6ef273f..55a098e 100644
--- a/src/noscrypt.c
+++ b/src/noscrypt.c
@@ -178,7 +178,8 @@ static NCResult _computeSharedSecret(
//Clean up sensitive data
ZERO_FILL(&pubKey, sizeof(secp256k1_pubkey));
- return (NCResult)result;
+ //Result should be 1 on success
+ return result > 0 ? NC_SUCCESS : E_OPERATION_FAILED;
}
static inline const mbedtls_md_info_t* _getSha256MdInfo(void)
@@ -198,14 +199,15 @@ static inline NCResult _computeConversationKey(
struct conversation_key* ck
)
{
+ int opResult;
//Validate internal args
DEBUG_ASSERT2(ctx != NULL, "Expected valid context")
DEBUG_ASSERT2(sharedSecret != NULL, "Expected a valid shared-point")
DEBUG_ASSERT2(mdInfo != NULL, "Expected valid md context")
DEBUG_ASSERT2(ck != NULL, "Expected a valid conversation key")
- //Derive the encryption key (returns 0 on success so it can be cast to an NCResult)
- return (NCResult)mbedtls_hkdf_extract(
+ //Derive the encryption key
+ opResult = mbedtls_hkdf_extract(
mdInfo,
Nip44ConstantSalt,
sizeof(Nip44ConstantSalt),
@@ -213,6 +215,9 @@ static inline NCResult _computeConversationKey(
NC_SHARED_SEC_SIZE,
(uint8_t*)ck //Output produces a conversation key
);
+
+ //Return success if the hkdf operation was successful
+ return opResult == 0 ? NC_SUCCESS : E_OPERATION_FAILED;
}
@@ -224,6 +229,7 @@ static inline void _expandKeysFromHkdf(const struct message_key* hkdf, struct nc
uint8_t* hkdfBytes;
DEBUG_ASSERT2(hkdf != NULL, "Expected valid hkdf")
+ DEBUG_ASSERT2(keys != NULL, "Expected valid key expand structure")
hkdfBytes = (uint8_t*)hkdf;
@@ -233,16 +239,20 @@ static inline void _expandKeysFromHkdf(const struct message_key* hkdf, struct nc
hkdfBytes,
CHACHA_KEY_SIZE
);
+
+ hkdfBytes += CHACHA_KEY_SIZE; //Offset by key size
MEMMOV(
keys->chacha_nonce,
- (hkdfBytes + CHACHA_KEY_SIZE),
+ hkdfBytes,
CHACHA_NONCE_SIZE
);
+ hkdfBytes += CHACHA_NONCE_SIZE; //Offset by nonce size
+
MEMMOV(
keys->hamc_key,
- (hkdfBytes + CHACHA_KEY_SIZE + CHACHA_NONCE_SIZE),
+ hkdfBytes,
HMAC_KEY_SIZE
);
}
@@ -254,7 +264,6 @@ static int _chachaEncipher(const struct nc_expand_keys* keys, NCCryptoData* args
DEBUG_ASSERT2(keys != NULL, "Expected valid keys")
DEBUG_ASSERT2(args != NULL, "Expected valid encryption args")
- DEBUG_ASSERT2(sizeof(keys->chacha_nonce) == 12, "Chacha nonce must be 12 exactly bytes in length")
//Init the chacha context
mbedtls_chacha20_init(&chachaCtx);
@@ -284,21 +293,24 @@ static inline NCResult _getMessageKey(
struct message_key* messageKey
)
{
+ int result;
DEBUG_ASSERT2(mdInfo != NULL, "Expected valid md context")
DEBUG_ASSERT2(nonce != NULL, "Expected valid nonce buffer")
DEBUG_ASSERT2(converstationKey != NULL, "Expected valid conversation key")
DEBUG_ASSERT2(messageKey != NULL, "Expected valid message key buffer")
//Another HKDF to derive the message key with nonce
- return (NCResult)mbedtls_hkdf_expand(
+ result = mbedtls_hkdf_expand(
mdInfo,
(uint8_t*)converstationKey, //Conversation key is the input key
NC_CONV_KEY_SIZE,
nonce,
nonceSize,
- (uint8_t*)messageKey, //Output produces a message key
+ (uint8_t*)messageKey, //Output produces a message key (write it directly to struct memory)
NC_MESSAGE_KEY_SIZE
);
+
+ return result == 0 ? NC_SUCCESS : E_OPERATION_FAILED;
}
static inline NCResult _encryptEx(
@@ -564,7 +576,7 @@ NC_EXPORT NCResult NC_CC NCSignData(
uint8_t digest[32];
CHECK_NULL_ARG(data, 2)
- //CHECK_ARG_RANGE(dataSize, 1, UINT32_MAX, 3)
+ CHECK_ARG_RANGE(dataSize, 1, UINT32_MAX, 3)
//Compute sha256 of the data before signing
if(_computeSha256Digest(data, dataSize, digest) != 0)
@@ -620,7 +632,7 @@ NC_EXPORT NCResult NC_CC NCVerifyData(
uint8_t digest[32];
CHECK_NULL_ARG(data, 2)
- //CHECK_ARG_RANGE(dataSize, 1, UINT32_MAX, 3)
+ CHECK_ARG_RANGE(dataSize, 1, UINT32_MAX, 3)
//Compute sha256 of the data before verifying
if (_computeSha256Digest(data, dataSize, digest) != 0)
diff --git a/src/noscrypt.h b/src/noscrypt.h
index 8a43743..2a2d051 100644
--- a/src/noscrypt.h
+++ b/src/noscrypt.h
@@ -121,6 +121,7 @@ static const uint8_t Nip44ConstantSalt[8] = { 0x6e, 0x69, 0x70, 0x34, 0x34, 0x2d
#define E_INVALID_ARG -2
#define E_INVALID_CONTEXT -3
#define E_ARGUMENT_OUT_OF_RANGE -4
+#define E_OPERATION_FAILED -5
/*
* Validation macros
diff --git a/tests/test.c b/tests/test.c
index 499ef50..b44f820 100644
--- a/tests/test.c
+++ b/tests/test.c
@@ -22,30 +22,41 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
+#include <stdlib.h>
#include "../src/noscrypt.h"
#include "../include/mbedtls/sha256.h"
+#include "../include/mbedtls/platform_util.h"
#if defined(_MSC_VER) || defined(WIN32) || defined(_WIN32)
#define IS_WINDOWS
#endif
#ifdef IS_WINDOWS
-
- #include <windows.h>
+ #include <windows.h>
#include <wincrypt.h>
+#endif
+
+#ifdef IS_WINDOWS
//Prints a string literal to the console
#define PRINTL(x) printf(x); printf("\r\n");
#define TEST(x) printf("Testing %s\n", #x); if(!(x)) { printf("Test failed!\n"); return 1; } else { printf("Test passed\n\n"); }
#define TASSERT(x) if(!(x)) { printf("ERROR! Internal test assumption failed: %s.\n Aborting tests...\n", #x); ExitProcess(1); }
+ #define ENSURE(x) if(!(x)) { printf("Assumption failed!\n"); return 1; }
#else
- #include <stdlib.h>
//Prints a string literal to the console
#define PRINTL(x) printf(x); printf("\n");
#define TEST(x) printf("Testing %s\n", #x); if(!(x)) { printf("Test failed!\n"); return 1; } else { printf("Test passed\n\n"); }
#define TASSERT(x) if(!(x)) { printf("Internal assumption failed: %s\n", #x); exit(1); }
+ #define ENSURE(x) if(!(x)) { printf("Assumption failed!\n"); return 1; }
+#endif
+
+#ifdef IS_WINDOWS
+ #define ZERO_FILL(x, size) SecureZeroMemory(x, size)
+#else
+ #define ZERO_FILL(x, size) memset(x, 0, size)
#endif
static void FillRandomData(uint8_t* pbBuffer, size_t length);
@@ -88,12 +99,15 @@ static void _sha256(const uint8_t* data, size_t length, uint8_t digest[32])
}
static const char* message = "Test message to sign";
+static const uint8_t zero32[32] = { 0 };
+static const uint8_t zero64[64] = { 0 };
static int TestEcdsa(NCContext* context)
{
- uint8_t digestToSign[32];
+
uint8_t secretKey[NC_SEC_KEY_SIZE];
uint8_t publicKey[NC_PUBKEY_SIZE];
+ uint8_t digestToSign[32];
uint8_t sigEntropy[32];
uint8_t invalidSig[64];
NCSecretKey* secKey;
@@ -112,18 +126,22 @@ static int TestEcdsa(NCContext* context)
FillRandomData(invalidSig, sizeof(invalidSig));
FillRandomData(sigEntropy, sizeof(sigEntropy));
+ //compute sha256 of the test string
+ _sha256((uint8_t*)message, strlen(message), digestToSign);
+
//Verify that the secret key is valid for the curve
TEST(NCValidateSecretKey(context, secKey) == NC_SUCCESS);
//Generate a public key from the secret key
TEST(NCGetPublicKey(context, secKey, pubKey) == NC_SUCCESS);
+ //Ensure not empty
+ TEST(memcmp(zero32, secretKey, 32) != 0);
+ TEST(memcmp(zero32, publicKey, 32) != 0);
+
//Sign and verify digest
{
uint8_t sig[64];
-
- //compute sha256 of the test string
- _sha256((uint8_t*)message, strlen(message), digestToSign);
TEST(NCSignDigest(context, secKey, sigEntropy, digestToSign, sig) == NC_SUCCESS);
TEST(NCVerifyDigest(context, pubKey, digestToSign, sig) == NC_SUCCESS);
@@ -136,8 +154,36 @@ static int TestEcdsa(NCContext* context)
TEST(NCVerifyData(context, pubKey, (uint8_t*)message, strlen(message), sig) == NC_SUCCESS);
}
+ //ensure the signature is the same for signing data and digest
+ {
+ uint8_t sig1[64];
+ uint8_t sig2[64];
+
+ //Ensure operations succeed but dont print them as test cases
+ ENSURE(NCSignData(context, secKey, sigEntropy, (uint8_t*)message, strlen(message), sig1) == NC_SUCCESS);
+ ENSURE(NCSignDigest(context, secKey, sigEntropy, digestToSign, sig2) == NC_SUCCESS);
+
+ //Perform test
+ TEST(memcmp(sig1, sig2, 64) == 0);
+ }
+
+ //Try signing data then veriyfing the digest
+ {
+ uint8_t sig[64];
+
+ ENSURE(NCSignData(context, secKey, sigEntropy, (uint8_t*)message, strlen(message), sig) == NC_SUCCESS);
+ TEST(NCVerifyDigest(context, pubKey, digestToSign, sig) == NC_SUCCESS);
+
+ //Now invert test, zero signature to ensure its overwritten
+ ZERO_FILL(sig, sizeof(sig));
+
+ ENSURE(NCSignDigest(context, secKey, sigEntropy, digestToSign, sig) == NC_SUCCESS);
+ TEST(NCVerifyData(context, pubKey, (uint8_t*)message, strlen(message), sig) == NC_SUCCESS);
+ }
+
//test verification of invalid signature
{
+
TEST(NCVerifyDigest(context, pubKey, digestToSign, invalidSig) == E_INVALID_ARG);
}