aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/noscrypt.c80
-rw-r--r--src/noscrypt.h84
2 files changed, 83 insertions, 81 deletions
diff --git a/src/noscrypt.c b/src/noscrypt.c
index 8aeeefe..3719a08 100644
--- a/src/noscrypt.c
+++ b/src/noscrypt.c
@@ -32,18 +32,13 @@
#include <mbedtls/sha256.h>
#include <mbedtls/constant_time.h>
-/* Non win platforms may need an inline override */
-#if !defined(_NC_IS_WINDOWS) && !defined(inline)
- #define inline __inline__
-#endif /* !IS_WINDOWS */
-
/* NULL */
#ifndef NULL
#define NULL ((void*)0)
#endif /* !NULL */
-#define CHACHA_NONCE_SIZE 12 /* Size of 12 is set by the cipher spec */
-#define CHACHA_KEY_SIZE 32 /* Size of 32 is set by the cipher spec */
+#define CHACHA_NONCE_SIZE 0x0cu /* Size of 12 is set by the cipher spec */
+#define CHACHA_KEY_SIZE 0x20u /* Size of 32 is set by the cipher spec */
/*
* Local macro for secure zero buffer fill
@@ -99,6 +94,12 @@
#define STATIC_ASSERT(x, m)
#endif
+/*
+* The Nip44 constant salt
+* https://github.com/nostr-protocol/nips/blob/master/44.md#encryption
+*/
+static const uint8_t Nip44ConstantSalt[8] = { 0x6e, 0x69, 0x70, 0x34, 0x34, 0x2d, 0x76, 0x32 };
+
struct shared_secret {
uint8_t value[NC_SHARED_SEC_SIZE];
};
@@ -131,7 +132,7 @@ STATIC_ASSERT(sizeof(struct nc_expand_keys) == sizeof(struct message_key), "Expe
* Internal helper functions to do common structure conversions
*/
-static inline int _convertToXonly(const NCContext* ctx, const NCPublicKey* compressedPubKey, secp256k1_xonly_pubkey* xonly)
+static _nc_fn_inline int _convertToXonly(const NCContext* ctx, const NCPublicKey* compressedPubKey, secp256k1_xonly_pubkey* xonly)
{
DEBUG_ASSERT2(ctx != NULL, "Expected valid context")
DEBUG_ASSERT2(compressedPubKey != NULL, "Expected a valid public 32byte key structure")
@@ -157,14 +158,13 @@ static int _convertToPubKey(const NCContext* ctx, const NCPublicKey* compressedP
MEMMOV((compressed + 1), compressedPubKey, sizeof(NCPublicKey));
result = secp256k1_ec_pubkey_parse(ctx->secpCtx, pubKey, compressed, sizeof(compressed));
-
- /* zero everything */
+
ZERO_FILL(compressed, sizeof(compressed));
return result;
}
-static inline int _convertFromXonly(const NCContext* ctx, const secp256k1_xonly_pubkey* xonly, NCPublicKey* compressedPubKey)
+static _nc_fn_inline int _convertFromXonly(const NCContext* ctx, const secp256k1_xonly_pubkey* xonly, NCPublicKey* compressedPubKey)
{
DEBUG_ASSERT2(ctx != NULL, "Expected valid context")
DEBUG_ASSERT2(xonly != NULL, "Expected valid X-only secp256k1 public key structure.")
@@ -239,15 +239,14 @@ static NCResult _computeSharedSecret(
&_edhHashFuncInternal,
NULL
);
-
- /* Clean up sensitive data */
+
ZERO_FILL(&pubKey, sizeof(pubKey));
/* Result should be 1 on success */
- return result > 0 ? NC_SUCCESS : E_OPERATION_FAILED;
+ return result == 1 ? NC_SUCCESS : E_OPERATION_FAILED;
}
-static inline const mbedtls_md_info_t* _getSha256MdInfo(void)
+static _nc_fn_inline const mbedtls_md_info_t* _getSha256MdInfo(void)
{
const mbedtls_md_info_t* info;
/* Get sha256 md info for hdkf operations */
@@ -257,7 +256,7 @@ static inline const mbedtls_md_info_t* _getSha256MdInfo(void)
}
-static inline NCResult _computeConversationKey(
+static _nc_fn_inline NCResult _computeConversationKey(
const NCContext* ctx,
const mbedtls_md_info_t* mdInfo,
const struct shared_secret* sharedSecret,
@@ -265,7 +264,7 @@ static inline NCResult _computeConversationKey(
)
{
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")
@@ -281,7 +280,7 @@ static inline NCResult _computeConversationKey(
(uint8_t*)ck /* Output produces a conversation key */
);
- /* Return success if the hkdf operation was successful */
+ /* 0 is a successful hdkf result */
return opResult == 0 ? NC_SUCCESS : E_OPERATION_FAILED;
}
@@ -289,7 +288,7 @@ static inline NCResult _computeConversationKey(
/*
* Explode the hkdf into the chacha key, chacha nonce, and hmac key.
*/
-static inline const struct nc_expand_keys* _expandKeysFromHkdf(const struct message_key* hkdf)
+static _nc_fn_inline const struct nc_expand_keys* _expandKeysFromHkdf(const struct message_key* hkdf)
{
return (const struct nc_expand_keys*)hkdf;
}
@@ -309,7 +308,7 @@ static int _chachaEncipher(const struct nc_expand_keys* keys, NCCryptoData* args
);
}
-static inline NCResult _getMessageKey(
+static _nc_fn_inline NCResult _getMessageKey(
const mbedtls_md_info_t* mdInfo,
const struct conversation_key* converstationKey,
const uint8_t* nonce,
@@ -337,7 +336,7 @@ static inline NCResult _getMessageKey(
return result == 0 ? NC_SUCCESS : E_OPERATION_FAILED;
}
-static inline NCResult _encryptEx(
+static _nc_fn_inline NCResult _encryptEx(
const NCContext* ctx,
const mbedtls_md_info_t* mdINfo,
const struct conversation_key* ck,
@@ -354,8 +353,8 @@ static inline NCResult _encryptEx(
DEBUG_ASSERT2(args != NULL, "Expected valid encryption args")
DEBUG_ASSERT2(mdINfo != NULL, "Expected valid md info struct")
DEBUG_ASSERT2(hmacKey != NULL, "Expected valid hmac key buffer")
-
- /* Failure, bail out */
+
+ /* Message key will be derrived on every encryption call */
if ((result = _getMessageKey(mdINfo, ck, args->nonce32, NC_ENCRYPTION_NONCE_SIZE, &messageKey)) != NC_SUCCESS)
{
goto Cleanup;
@@ -371,13 +370,12 @@ static inline NCResult _encryptEx(
result = (NCResult)_chachaEncipher(expandedKeys, args);
Cleanup:
- /* Clean up sensitive data */
ZERO_FILL(&messageKey, sizeof(messageKey));
return result;
}
-static inline NCResult _decryptEx(
+static _nc_fn_inline NCResult _decryptEx(
const NCContext* ctx,
const mbedtls_md_info_t* mdInfo,
const struct conversation_key* ck,
@@ -391,9 +389,8 @@ static inline NCResult _decryptEx(
DEBUG_ASSERT2(ctx != NULL, "Expected valid context")
DEBUG_ASSERT2(ck != NULL, "Expected valid conversation key")
DEBUG_ASSERT2(args != NULL, "Expected valid encryption args")
- DEBUG_ASSERT2(mdInfo != NULL, "Expected valid md info struct")
-
- /* Failure to get message keys, bail out */
+ DEBUG_ASSERT2(mdInfo != NULL, "Expected valid md info struct")
+
if ((result = _getMessageKey(mdInfo, ck, args->nonce32, NC_ENCRYPTION_NONCE_SIZE, &messageKey)) != NC_SUCCESS)
{
goto Cleanup;
@@ -406,13 +403,12 @@ static inline NCResult _decryptEx(
result = (NCResult) _chachaEncipher(cipherKeys, args);
Cleanup:
- /* Clean up sensitive data */
ZERO_FILL(&messageKey, sizeof(messageKey));
return result;
}
-static inline int _computeHmac(
+static _nc_fn_inline int _computeHmac(
const uint8_t key[NC_HMAC_KEY_SIZE],
const NCMacVerifyArgs* args,
uint8_t hmacOut[NC_ENCRYPTION_MAC_SIZE]
@@ -440,7 +436,6 @@ static NCResult _verifyMacEx(
)
{
NCResult result;
- const mbedtls_md_info_t* sha256Info;
const struct nc_expand_keys* keys;
struct message_key messageKey;
uint8_t hmacOut[NC_ENCRYPTION_MAC_SIZE];
@@ -449,14 +444,11 @@ static NCResult _verifyMacEx(
DEBUG_ASSERT2(conversationKey != NULL, "Expected valid conversation key")
DEBUG_ASSERT2(args != NULL, "Expected valid mac verification args")
- sha256Info = _getSha256MdInfo();
-
/*
- * We need to get the message key in order to
- * get the required hmac key
+ * Message key is again required for the hmac verification
*/
result = _getMessageKey(
- sha256Info,
+ _getSha256MdInfo(),
(struct conversation_key*)conversationKey,
args->nonce32,
NC_ENCRYPTION_NONCE_SIZE,
@@ -484,7 +476,6 @@ static NCResult _verifyMacEx(
result = mbedtls_ct_memcmp(hmacOut, args->mac32, NC_ENCRYPTION_MAC_SIZE) == 0 ? NC_SUCCESS : E_OPERATION_FAILED;
Cleanup:
- /* Clean up sensitive data */
ZERO_FILL(&messageKey, sizeof(messageKey));
ZERO_FILL(hmacOut, sizeof(hmacOut));
@@ -510,7 +501,10 @@ NC_EXPORT NCResult NC_CC NCInitContext(
ctx->secpCtx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
- /* Randomize once on init */
+ /*
+ * Randomize once on init, users can call reinit to
+ * randomize again as needed.
+ */
return secp256k1_context_randomize(ctx->secpCtx, entropy) ? NC_SUCCESS : E_INVALID_ARG;
}
@@ -520,8 +514,8 @@ NC_EXPORT NCResult NC_CC NCReInitContext(
)
{
CHECK_NULL_ARG(ctx, 0)
- CHECK_INVALID_ARG(ctx->secpCtx, 0)
CHECK_NULL_ARG(entropy, 1)
+ CHECK_INVALID_ARG(ctx->secpCtx, 0)
/* Only randomize again */
return secp256k1_context_randomize(ctx->secpCtx, entropy) ? NC_SUCCESS : E_INVALID_ARG;
@@ -612,7 +606,7 @@ NC_EXPORT NCResult NC_CC NCSignDigest(
CHECK_NULL_ARG(digest32, 3)
CHECK_NULL_ARG(sig64, 4)
- /* Generate the keypair */
+ /* Fill keypair structure from the callers secret key */
if (secp256k1_keypair_create(ctx->secpCtx, &keyPair, sk->key) != 1)
{
return E_INVALID_ARG;
@@ -628,8 +622,7 @@ NC_EXPORT NCResult NC_CC NCSignDigest(
/* Verify the signature is valid */
result = secp256k1_schnorrsig_verify(ctx->secpCtx, sig64, digest32, 32, &xonly);
-
- /* cleanup any sensitive data */
+
ZERO_FILL(&keyPair, sizeof(keyPair));
ZERO_FILL(&xonly, sizeof(xonly));
@@ -689,8 +682,7 @@ NC_EXPORT NCResult NC_CC NCVerifyDigest(
/* Verify the signature */
result = secp256k1_schnorrsig_verify(ctx->secpCtx, sig64, digest32, 32, &xonly);
-
- /* cleanup any sensitive data */
+
ZERO_FILL(&xonly, sizeof(xonly));
return result == 1 ? NC_SUCCESS : E_INVALID_ARG;
diff --git a/src/noscrypt.h b/src/noscrypt.h
index 6a40171..e5dd7aa 100644
--- a/src/noscrypt.h
+++ b/src/noscrypt.h
@@ -62,32 +62,37 @@
#endif /* !NOSCRYPT_EXPORTING */
#endif /* !NC_EXPORT */
+#if defined(_NC_IS_WINDOWS) || defined(inline) || defined(__clang__)
+ #define _nc_fn_inline inline
+#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 allows usage of inline keyword */
+ #define _nc_fn_inline inline
+#elif defined(__GNUC__) || defined(__GNUG__)
+ #define _nc_fn_inline __inline__
+#else
+ #define _nc_fn_inline
+ #pragma message("Warning: No inline keyword defined for this compiler")
+#endif
+
/*
* CONSTANTS
*/
-#define BIP340_PUBKEY_HEADER_BYTE 0x02
-#define NIP44_MESSAGE_KEY_SIZE 76
-#define NC_ENCRYPTION_NONCE_SIZE 32
-#define NC_SEC_KEY_SIZE 32
-#define NC_PUBKEY_SIZE 32
-#define NC_SHARED_SEC_SIZE 32
-#define NC_CONV_KEY_SIZE 32
-#define NC_HMAC_KEY_SIZE 32
-#define NC_ENCRYPTION_MAC_SIZE 32
+#define BIP340_PUBKEY_HEADER_BYTE 0x02
+#define NIP44_MESSAGE_KEY_SIZE 0x4c /*32 + 12 + 32 */
+#define NC_ENCRYPTION_NONCE_SIZE 0x20
+#define NC_SEC_KEY_SIZE 0x20
+#define NC_PUBKEY_SIZE 0x20
+#define NC_SHARED_SEC_SIZE 0x20
+#define NC_CONV_KEY_SIZE 0x20
+#define NC_HMAC_KEY_SIZE 0x20
+#define NC_ENCRYPTION_MAC_SIZE 0x20
#define NC_MESSAGE_KEY_SIZE NIP44_MESSAGE_KEY_SIZE
/*
* From spec
* https://github.com/nostr-protocol/nips/blob/master/44.md#decryption
*/
-#define NIP44_MIN_ENC_MESSAGE_SIZE 1
-#define NIP44_MAX_ENC_MESSAGE_SIZE 65535
-
-/*
-* The Nip44 constant salt
-* https://github.com/nostr-protocol/nips/blob/master/44.md#encryption
-*/
-static const uint8_t Nip44ConstantSalt[8] = { 0x6e, 0x69, 0x70, 0x34, 0x34, 0x2d, 0x76, 0x32 };
+#define NIP44_MIN_ENC_MESSAGE_SIZE 0x01
+#define NIP44_MAX_ENC_MESSAGE_SIZE 0xffff
/*
* ERROR CODES
@@ -100,15 +105,15 @@ static const uint8_t Nip44ConstantSalt[8] = { 0x6e, 0x69, 0x70, 0x34, 0x34, 0x2d
* operations that return a value count.
*/
-#define NC_ARG_POSITION_OFFSET 8
-#define NC_ERROR_CODE_MASK 0xFF
+#define NC_ARG_POSITION_OFFSET 0x08
+#define NC_ERROR_CODE_MASK 0xFF
-#define NC_SUCCESS 0
-#define E_NULL_PTR -1
-#define E_INVALID_ARG -2
-#define E_INVALID_CONTEXT -3
-#define E_ARGUMENT_OUT_OF_RANGE -4
-#define E_OPERATION_FAILED -5
+#define NC_SUCCESS 0x00
+#define E_NULL_PTR -1
+#define E_INVALID_ARG -2
+#define E_INVALID_CONTEXT -3
+#define E_ARGUMENT_OUT_OF_RANGE -4
+#define E_OPERATION_FAILED -5
/* A compressed resul/return value, negative values
are failure, 0 is success and positive values are
@@ -123,7 +128,7 @@ typedef struct secret_key_struct {
uint8_t key[NC_SEC_KEY_SIZE];
-}NCSecretKey;
+} NCSecretKey;
/*
An x-only secp256k1 public key
@@ -132,7 +137,7 @@ typedef struct xonly_pubkey_struct {
uint8_t key[NC_PUBKEY_SIZE];
-}NCPublicKey;
+} NCPublicKey;
/*
An opaque full library context object
@@ -141,7 +146,7 @@ typedef struct ctx_struct {
void* secpCtx;
-}NCContext;
+} NCContext;
/*
* The encryption arguments structure. This structure is used to pass
@@ -196,7 +201,7 @@ typedef struct nc_mac_verify {
* @param key The 32byte buffer to cast
* @return A pointer to the NCSecretKey struct
*/
-static inline NCSecretKey* NCToSecKey(uint8_t key[NC_SEC_KEY_SIZE])
+static _nc_fn_inline NCSecretKey* NCToSecKey(uint8_t key[NC_SEC_KEY_SIZE])
{
return (NCSecretKey*)key;
}
@@ -206,12 +211,12 @@ static inline NCSecretKey* NCToSecKey(uint8_t key[NC_SEC_KEY_SIZE])
* @param key The 32byte buffer to cast
* @return A pointer to the NCPublicKey struct
*/
-static inline NCPublicKey* NCToPubKey(uint8_t key[NC_PUBKEY_SIZE])
+static _nc_fn_inline NCPublicKey* NCToPubKey(uint8_t key[NC_PUBKEY_SIZE])
{
return (NCPublicKey*)key;
}
-static inline NCResult NCResultWithArgPosition(NCResult err, uint8_t argPosition)
+static _nc_fn_inline NCResult NCResultWithArgPosition(NCResult err, uint8_t argPosition)
{
return -(((NCResult)argPosition << NC_ARG_POSITION_OFFSET) | -err);
}
@@ -220,17 +225,22 @@ static inline NCResult NCResultWithArgPosition(NCResult err, uint8_t argPosition
* Parses an error code and returns the error code and the argument position
that caused the error.
* @param result The error code to parse
-* @param code A pointer to the error code to write to
-* @param argPosition A pointer to the argument position to write to
+* @param argPositionOut A pointer to the argument position to write to
+* @return The error code
*/
-NC_EXPORT void NC_CC NCParseErrorCode(NCResult result, int* code, uint8_t* argPosition)
+static _nc_fn_inline int NCParseErrorCode(NCResult result, uint8_t* argPositionOut)
{
/* convert result to a positive value*/
- NCResult asPositive = -result;
+ NCResult asPositive;
+ int code;
+
+ asPositive = -result;
/* Get the error code from the lower 8 bits and the argument position from the upper 8 bits*/
- *code = -(asPositive & NC_ERROR_CODE_MASK);
- *argPosition = (asPositive >> NC_ARG_POSITION_OFFSET) & 0xFF;
+ code = -(asPositive & NC_ERROR_CODE_MASK);
+ *argPositionOut = (asPositive >> NC_ARG_POSITION_OFFSET) & 0xFF;
+
+ return code;
}
/*--------------------------------------