aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar vnugent <public@vaughnnugent.com>2024-07-13 22:13:13 -0400
committerLibravatar vnugent <public@vaughnnugent.com>2024-07-13 22:13:13 -0400
commitffe42b6858f112a00405be4f0605ab1163063749 (patch)
tree53b0e36bf3bcb4349d0566427d856bb2f89c76e8
parent5dfafbc5a9214587533ec8b1dae2a962118d3650 (diff)
test: Add decryption test cases and fixes
-rw-r--r--include/noscryptutil.h8
-rw-r--r--src/noscryptutil.c50
-rw-r--r--tests/test.c86
3 files changed, 108 insertions, 36 deletions
diff --git a/include/noscryptutil.h b/include/noscryptutil.h
index 20384c4..13b9231 100644
--- a/include/noscryptutil.h
+++ b/include/noscryptutil.h
@@ -40,10 +40,10 @@ extern "C" {
#define E_CIPHER_BAD_NONCE -12
#define E_CIPHER_MAC_INVALID -13
-#define NC_UTIL_CIPHER_MODE_ENCRYPT 0x00ui32
-#define NC_UTIL_CIPHER_MODE_DECRYPT 0x01ui32
-#define NC_UTIL_CIPHER_ZERO_ON_FREE 0x02ui32
-#define NC_UTIL_CIPHER_MAC_NO_VERIFY 0x04ui32
+#define NC_UTIL_CIPHER_MODE_ENCRYPT 0x00u
+#define NC_UTIL_CIPHER_MODE_DECRYPT 0x01u
+#define NC_UTIL_CIPHER_ZERO_ON_FREE 0x02u
+#define NC_UTIL_CIPHER_MAC_NO_VERIFY 0x04u
/*
* The encryption context structure. This structure is used to store the state
diff --git a/src/noscryptutil.c b/src/noscryptutil.c
index 09b7c92..97526d9 100644
--- a/src/noscryptutil.c
+++ b/src/noscryptutil.c
@@ -20,7 +20,6 @@
#include <stdlib.h>
-#include <math.h>
#include "nc-util.h"
#include "nc-crypto.h"
@@ -53,8 +52,26 @@
#endif /* !NC_DISABLE_INPUT_VALIDATION */
-/* performs a log2 on integer types */
-#define _math_int_log2(x) (int32_t)log2((double)x)
+#ifdef _NC_IS_WINDOWS
+
+ #include <math.h>
+
+ /* performs a log2 on integer types */
+ #define _math_int_log2(x) (uint32_t)log2((double)x)
+
+#else
+ /*
+ * GCC/clang does not expose log2 so we can use the __builtin_clz
+ * to find leading zeros of an integer and subtract that from 31
+ * (bit positions) for int32
+ */
+ static _nc_fn_inline uint32_t _math_int_log2(uint32_t val)
+ {
+ DEBUG_ASSERT(val < UINT32_MAX);
+
+ return 31 - __builtin_clz(val);
+ }
+#endif
#define MIN_PADDING_SIZE 0x20u
#define NIP44_VERSION_SIZE 0x01u
@@ -66,10 +83,15 @@
*/
#define NIP44_MIN_PAYLOAD_SIZE (NIP44_VERSION_SIZE + 0x20 + 0x02 + 0x20 + 0x02)
+/*
+* The minimum ciphertext size is the minimum padded size + the minimum
+* size of the plaintext length field
+*/
+#define NIP44_MIN_CIPHERTEXT_SIZE (MIN_PADDING_SIZE + NIP44_PT_LEN_SIZE)
/* Currently were on nip44 version 2 */
-const static uint8_t Nip44VersionValue[1] = { 0x02u };
+static const uint8_t Nip44VersionValue[1] = { 0x02u };
struct nc_util_enc_struct {
@@ -217,7 +239,7 @@ static _nc_fn_inline span_t _nip44GetMacOutput(span_t payload)
static _nc_fn_inline cspan_t _nip44ParseMac(cspan_t payload)
{
- DEBUG_ASSERT(payload.size > NC_ENCRYPTION_MAC_SIZE);
+ DEBUG_ASSERT(payload.size >= NIP44_MIN_PAYLOAD_SIZE);
/*
* Mac is the final 32 bytes of the ciphertext buffer
@@ -231,30 +253,26 @@ static _nc_fn_inline cspan_t _nip44ParseMac(cspan_t payload)
static _nc_fn_inline cspan_t _nip44ParseCipherText(cspan_t payload)
{
- DEBUG_ASSERT(payload.size < NIP44_MIN_PAYLOAD_SIZE);
+ DEBUG_ASSERT(payload.size >= NIP44_MIN_PAYLOAD_SIZE);
- /* slice after the nonce and before the mac segments */
+ /* ct is all of the data after the nonce and before the mac segment */
return ncSpanSliceC(
payload,
NIP44_VERSION_SIZE + NC_ENCRYPTION_NONCE_SIZE,
- payload.size - NC_ENCRYPTION_MAC_SIZE
+ payload.size - (NIP44_VERSION_SIZE + NC_ENCRYPTION_NONCE_SIZE + NC_ENCRYPTION_MAC_SIZE)
);
}
static _nc_fn_inline cspan_t _nip44ParseNonce(cspan_t payload)
{
- cspan_t nonceData;
-
- DEBUG_ASSERT(payload.size > NIP44_MIN_PAYLOAD_SIZE);
+ DEBUG_ASSERT(payload.size >= NIP44_MIN_PAYLOAD_SIZE);
/* slice after the version and before the mac segments */
- nonceData = ncSpanSliceC(
+ return ncSpanSliceC(
payload,
NIP44_VERSION_SIZE,
NC_ENCRYPTION_NONCE_SIZE
);
-
- return nonceData;
}
static NCResult _nip44EncryptCompleteCore(
@@ -325,7 +343,7 @@ static NCResult _nip44EncryptCompleteCore(
result = NCSetEncryptionData(
&encArgs,
- (payload.data + outPos),
+ (payload.data + outPos), /* in place encryption */
(payload.data + outPos),
paddedCtSize + NIP44_PT_LEN_SIZE /* Plaintext + pt size must be encrypted */
);
@@ -458,7 +476,7 @@ static NCResult _nip44DecryptCompleteCore(
cipherText = _nip44ParseCipherText(cipher->cipherInput);
- DEBUG_ASSERT2(cipherText.size > 0x20, "Cipertext segment was parsed incorrectly. Too small");
+ DEBUG_ASSERT2(cipherText.size >= MIN_PADDING_SIZE, "Cipertext segment was parsed incorrectly. Too small");
/* manually sign nonce */
encArgs.nonceData = nonce.data;
diff --git a/tests/test.c b/tests/test.c
index c917f52..80b8704 100644
--- a/tests/test.c
+++ b/tests/test.c
@@ -607,15 +607,9 @@ static int TestCorrectEncryption(const NCContext* context)
#include <noscryptutil.h>
-/*
-* This function is not currently public, but we can access it for testing
-* purposes because it is used to calculate the output buffer size for encryption
-*/
-extern NCResult NCUtilGetEncryptionPaddedSize(uint32_t encVersion, int32_t plaintextSize);
-
/* Padding tests taken from the nip44 repo vectors.json file */
-const uint32_t _padTestActual[24] = { 16, 32, 33, 37, 45, 49, 64, 65, 100, 111, 200, 250, 320, 383, 384, 400, 500, 512, 515, 700, 800, 900, 1020, 65536 };
-const uint32_t _padTestExpected[24] = { 32, 32, 64, 64, 64, 64, 64, 96, 128, 128, 224, 256, 320, 384, 384, 448, 512, 512, 640, 768, 896, 1024, 1024, 65536 };
+static const uint32_t _padTestActual[24] = { 16, 32, 33, 37, 45, 49, 64, 65, 100, 111, 200, 250, 320, 383, 384, 400, 500, 512, 515, 700, 800, 900, 1020, 65536 };
+static const uint32_t _padTestExpected[24] = { 32, 32, 64, 64, 64, 64, 64, 96, 128, 128, 224, 256, 320, 384, 384, 448, 512, 512, 640, 768, 896, 1024, 1024, 65536 };
static int TestUtilNip44Encryption(
const NCContext* libCtx,
@@ -627,7 +621,7 @@ static int TestUtilNip44Encryption(
)
{
NCPublicKey recvPubKey;
- span_t outData;
+ uint8_t* outData;
ENSURE(NCValidateSecretKey(libCtx, NCByteCastToSecretKey(sendKey.data)) == NC_SUCCESS);
ENSURE(NCGetPublicKey(libCtx, NCByteCastToSecretKey(recvKey.data), &recvPubKey) == NC_SUCCESS);
@@ -645,25 +639,70 @@ static int TestUtilNip44Encryption(
/* Nonce is required for nip44 encryption */
TEST(NCUtilCipherSetProperty(ctx, NC_ENC_SET_NIP44_NONCE, nonce.data, nonce.size), NC_SUCCESS);
- /* Ciper update should return the */
+ /* Cipher update should return the */
TEST(NCUtilCipherUpdate(ctx, libCtx, NCByteCastToSecretKey(sendKey.data), &recvPubKey), NC_SUCCESS);
NCResult cipherOutputSize = NCUtilCipherGetOutputSize(ctx);
TEST(cipherOutputSize, expected.size);
- outData.data = (uint8_t*)malloc(cipherOutputSize);
- outData.size = (uint32_t)cipherOutputSize;
+ outData = (uint8_t*)malloc(cipherOutputSize);
+ TASSERT(outData != NULL);
+
+ /* Read the encrypted payload to test */
+ TEST(NCUtilCipherReadOutput(ctx, outData, cipherOutputSize), cipherOutputSize);
+
+ /* Ensure encrypted payload matches */
+ TEST(memcmp(outData, expected.data, cipherOutputSize), 0);
+
+ free(outData);
+
+ /* Free encryption memory */
+ NCUtilCipherFree(ctx);
+}
+
+static int TestUtilNip44Decryption(
+ const NCContext* libCtx,
+ span_t sendKey,
+ span_t recvKey,
+ span_t payload,
+ const char* expectedPt
+)
+{
+ NCPublicKey recvPubKey;
+ uint8_t* outData;
- TASSERT(outData.data != NULL);
+ ENSURE(NCValidateSecretKey(libCtx, NCByteCastToSecretKey(sendKey.data)) == NC_SUCCESS);
+ ENSURE(NCGetPublicKey(libCtx, NCByteCastToSecretKey(recvKey.data), &recvPubKey) == NC_SUCCESS);
+
+ /* Alloc cipher in nip44 decryption mode */
+ NCUtilCipherContext* ctx = NCUtilCipherAlloc(
+ NC_ENC_VERSION_NIP44,
+ NC_UTIL_CIPHER_MODE_DECRYPT | NC_UTIL_CIPHER_ZERO_ON_FREE
+ );
+
+ ENSURE(ctx != NULL);
+
+ /* submit encrypted payload for ciphertext */
+ TEST(NCUtilCipherInit(ctx, payload.data, payload.size), NC_SUCCESS);
+
+ TEST(NCUtilCipherUpdate(ctx, libCtx, NCByteCastToSecretKey(sendKey.data), &recvPubKey), NC_SUCCESS);
+
+ NCResult plaintextSize = NCUtilCipherGetOutputSize(ctx);
+
+ TEST(plaintextSize, strlen(expectedPt));
+
+ outData = (uint8_t*)malloc(plaintextSize);
+
+ TASSERT(outData != NULL);
/* Read the encrypted payload to test */
- TEST(NCUtilCipherReadOutput(ctx, outData.data, cipherOutputSize), cipherOutputSize);
+ TEST(NCUtilCipherReadOutput(ctx, outData, plaintextSize), plaintextSize);
/* Ensure encrypted payload matches */
- TEST(memcmp(outData.data, expected.data, cipherOutputSize), 0);
+ TEST(memcmp(outData, expectedPt, plaintextSize), 0);
- free(outData.data);
+ free(outData);
/* Free encryption memory */
NCUtilCipherFree(ctx);
@@ -695,6 +734,21 @@ static int TestUtilFunctions(const NCContext* libCtx)
return 1;
}
}
+ {
+ PRINTL("TEST: NIP-44 util decryption");
+
+ /* From the nip44 vectors file */
+ span_t sendKey = FromHexString("0000000000000000000000000000000000000000000000000000000000000001", sizeof(NCSecretKey));
+ span_t recvKey = FromHexString("0000000000000000000000000000000000000000000000000000000000000002", sizeof(NCSecretKey));
+ span_t nonce = FromHexString("0000000000000000000000000000000000000000000000000000000000000001", NC_ENCRYPTION_NONCE_SIZE);
+ span_t payload = FromHexString("02000000000000000000000000000000000000000000000000000000000000000179ed06e5548ad3ff58ca920e6c0b4329f6040230f7e6e5641f20741780f0adc35a09794259929a02bb06ad8e8cf709ee4ccc567e9d514cdf5781af27a3e905e55b1b", 99);
+ const char* plainText = "a";
+
+ if (TestUtilNip44Decryption(libCtx, sendKey, recvKey, payload, plainText) != 0)
+ {
+ return 1;
+ }
+ }
PRINTL("\nPASSED: Util functions tests completed")
return 0;