diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/noscrypt.h | 88 | ||||
-rw-r--r-- | include/noscryptutil.h | 194 |
2 files changed, 239 insertions, 43 deletions
diff --git a/include/noscrypt.h b/include/noscrypt.h index f408dfc..3702555 100644 --- a/include/noscrypt.h +++ b/include/noscrypt.h @@ -58,7 +58,7 @@ extern "C" { #ifdef _NC_IS_WINDOWS #define NC_EXPORT __declspec(dllimport) #else - #define NC_EXPORT + #define NC_EXPORT extern #endif /* _NC_IS_WINDOWS */ #endif /* !NOSCRYPT_EXPORTING */ #endif /* !NC_EXPORT */ @@ -68,7 +68,6 @@ extern "C" { */ #define BIP340_PUBKEY_HEADER_BYTE 0x02 #define NIP44_MESSAGE_KEY_SIZE 0x4c /*32 + 12 + 32 = 76 */ -#define NC_ENCRYPTION_NONCE_SIZE 0x20 #define NC_SEC_KEY_SIZE 0x20 #define NC_PUBKEY_SIZE 0x20 #define NC_CONTEXT_ENTROPY_SIZE 0x20 @@ -76,16 +75,17 @@ extern "C" { #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 -#define NC_NIP04_AES_IV_SIZE 0x10 /* AES IV size is 16 bytes (aka cipher block size) */ +#define NC_MESSAGE_KEY_SIZE NIP44_MESSAGE_KEY_SIZE #define NC_NIP04_AES_KEY_SIZE 0x20 /* AES 256 key size */ +#define NC_NIP44_IV_SIZE 0x20 /* 32 bytes */ +#define NC_NIP04_IV_SIZE 0x10 /* 16 bytes */ /* * From spec * https://github.com/nostr-protocol/nips/blob/master/44.md#decryption */ #define NIP44_MIN_ENC_MESSAGE_SIZE 0x01 -#define NIP44_MAX_ENC_MESSAGE_SIZE 0xffff +#define NIP44_MAX_ENC_MESSAGE_SIZE UINT16_MAX #define NC_ENC_VERSION_NIP04 0x04 #define NC_ENC_VERSION_NIP44 0x2c @@ -121,11 +121,31 @@ extern "C" { */ #define NC_ENC_SET_VERSION 0x01 -#define NC_ENC_SET_NIP44_NONCE 0x02 +#define NC_ENC_SET_IV 0x02 #define NC_ENC_SET_NIP44_MAC_KEY 0x03 #define NC_ENC_SET_NIP04_KEY 0x04 -#define NC_ENC_SET_NIP04_IV 0x05 +/* +* API NOTES: +* +* - Decisions on integer width +* Since noscrypt will target general purpose processors and embedded +* systems (future) I didn't want to risk word size issues causing under/overflow +* for the time being, so a fixed integer width was used and internal code +* supports and guards against the platform default integer width (size_t) +* +* I'd like to support 64bit stuff, but really the underlying systems don't +* need to support that size buffer, nor do I expect platforms to have more than +* 4GB sized buffers (int32_t), it's just not practial and most work is on +* digests anyway. +* +* - Decisions on unsigned vs signed +* Yeah, I know this is a popular squabble in C land, but implementation details +* should not trouble the user. If I expect an unsigned int, then it should be +* explicit, negative number guards are cumbersom to handle return codes with +* that IMO most engineers don't bother doing anyway or doing well at the very +* least, so I'm using unsgined integers. Sorry, not sorry. +*/ /* A compressed resul/return value, negative values are failure, 0 is success and positive values are @@ -212,51 +232,26 @@ typedef struct nc_mac_verify { */ /* -* A helper function to cast a buffer to a NCSecretKey struct -* @param key The buffer to cast -* @return A pointer to the NCSecretKey struct +* Casts a buffer pointer to a NCSecretKey pointer */ -static _nc_fn_inline NCSecretKey* NCToSecKey(uint8_t key[NC_SEC_KEY_SIZE]) -{ - return (NCSecretKey*)key; -} +#define NCByteCastToSecretKey(key) (NCSecretKey*)key /* -* A helper function to cast a buffer to a NCPublicKey struct -* @param key The buffer to cast -* @return A pointer to the NCPublicKey struct +* Casts a buffer pointer to a NCPublicKey pointer */ -static _nc_fn_inline NCPublicKey* NCToPubKey(uint8_t key[NC_PUBKEY_SIZE]) -{ - return (NCPublicKey*)key; -} +#define NCByteCastToPublicKey(key) (NCPublicKey*)key -static _nc_fn_inline NCResult NCResultWithArgPosition(NCResult err, uint8_t argPosition) -{ - return -(((NCResult)argPosition << NC_ARG_POSITION_OFFSET) | -err); -} + +NC_EXPORT NCResult NC_CC 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 argPositionOut A pointer to the argument position to write to +* @param argPositionOut A pointer to the argument position to write to (optionall, set to NULL of unobserved) * @return The error code */ -static _nc_fn_inline int NCParseErrorCode(NCResult result, uint8_t* argPositionOut) -{ - NCResult asPositive; - int code; - - /* convert result to a positive value*/ - 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); - *argPositionOut = (asPositive >> NC_ARG_POSITION_OFFSET) & 0xFF; - - return code; -} +NC_EXPORT int NC_CC NCParseErrorCode(NCResult result, uint8_t* argPositionOut); /*-------------------------------------- * LIB CONTEXT API @@ -603,7 +598,7 @@ NC_EXPORT NCResult NCComputeMac( * @return NC_SUCCESS if the operation was successful, otherwise an error code. Use NCParseErrorCode to * the error code and positional argument that caused the error. */ -NC_EXPORT NCResult NCSetEncryptionProperty( +NC_EXPORT NCResult NCEncryptionSetProperty( NCEncryptionArgs* args, uint32_t property, uint32_t value @@ -620,7 +615,7 @@ NC_EXPORT NCResult NCSetEncryptionProperty( * @return NC_SUCCESS if the operation was successful, otherwise an error code. Use NCParseErrorCode to * the error code and positional argument that caused the error. */ -NC_EXPORT NCResult NCSetEncryptionPropertyEx( +NC_EXPORT NCResult NCEncryptionSetPropertyEx( NCEncryptionArgs* args, uint32_t property, uint8_t* value, @@ -637,13 +632,20 @@ NC_EXPORT NCResult NCSetEncryptionPropertyEx( * @return NC_SUCCESS if the operation was successful, otherwise an error code. Use NCParseErrorCode to * the error code and positional argument that caused the error. */ -NC_EXPORT NCResult NCSetEncryptionData( +NC_EXPORT NCResult NCEncryptionSetData( NCEncryptionArgs* args, const uint8_t* input, uint8_t* output, uint32_t dataSize ); +/* +* Gets the size of the encryption nonce (iv) for the given encryption version +* @param version The encryption version to get the nonce size for +* @return The size of the nonce in bytes, or 0 if the version is not supported +*/ +NC_EXPORT uint32_t NCEncryptionGetIvSize(uint32_t version); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/include/noscryptutil.h b/include/noscryptutil.h new file mode 100644 index 0000000..63e08f8 --- /dev/null +++ b/include/noscryptutil.h @@ -0,0 +1,194 @@ +/* +* Copyright (c) 2024 Vaughn Nugent +* +* Package: noscrypt +* File: noscryptutil.h +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public License +* as published by the Free Software Foundation; either version 2.1 +* of the License, or (at your option) any later version. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public License +* along with noscrypt. If not, see http://www.gnu.org/licenses/. +*/ + +/* +* This header includes some optional high-level nostr crypto utility functions +* for much easer app development. +*/ + +#pragma once + +#ifndef NOSCRYPTUTIL_H +#define NOSCRYPTUTIL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "noscrypt.h" + +#define E_OUT_OF_MEMORY -10 + +#define E_CIPHER_INVALID_FORMAT -11 +#define E_CIPHER_BAD_NONCE -12 +#define E_CIPHER_MAC_INVALID -13 +#define E_CIPHER_NO_OUTPUT -14 +#define E_CIPHER_BAD_INPUT -15 +#define E_CIPHER_BAD_INPUT_SIZE -16 + +#define NC_UTIL_CIPHER_MODE 0x01u + +#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 +#define NC_UTIL_CIPHER_REUSEABLE 0x08u + +/* +* The encryption context structure. This structure is used to store the state +* of the encryption operation. The structure is opaque and should not be accessed +* directly. +*/ +typedef struct nc_util_enc_struct NCUtilCipherContext; + +/* +* Gets the size of the padded buffer required for an encryption operation. +* @param encVersion The encryption specification version to use +* @param plaintextSize The size of the plaintext buffer in bytes +* @return The size of the padded buffer in bytes +*/ +NC_EXPORT NCResult NC_CC NCUtilGetEncryptionPaddedSize(uint32_t encVersion, uint32_t plaintextSize); + +/* +* Gets the size of the payload buffer required for an encryption operation. +* @param encVersion The encryption specification version to use +* @param plaintextSize The size of the plaintext buffer in bytes +* @return The size of the payload buffer in bytes +* @note The payload buffer is the final buffer to be sent to a nostr user. For nip04 this +* is a raw AES message, for nip44 this is a mucher lager buffer. See the nostr specifications +* for more information. +*/ +NC_EXPORT NCResult NC_CC NCUtilGetEncryptionBufferSize(uint32_t encVersion, uint32_t plaintextSize); + +/* +* Allocates a new encryption context and sets the encryption version and flags. The encryption context +* must be freed with NCUtilCipherFree when it is no longer needed. +* @param encVersion The encryption specification version to use +* @param flags The flags to set on the encryption context +* @return A valid pointer to an encryption context or NULL if the operation failed +*/ +NC_EXPORT NCUtilCipherContext* NC_CC NCUtilCipherAlloc(uint32_t encVersion, uint32_t flags); + +/* +* Initializes the cipher context with the input data and size. This function will + internally allocate a the required output buffer for the cipher operation. You may only call + this function once. +* @param encCtx A valid pointer to an allocated encryption context +* @param inputData A pointer to the input data for the Cipher +* @param inputSize The size of the input data +* @return NC_SUCCESS if the operation was successful, otherwise an error code. Use NCParseErrorCode to +the error code and positional argument that caused the error +*/ +NC_EXPORT NCResult NC_CC NCUtilCipherInit( + NCUtilCipherContext* encCtx, + const uint8_t* inputData, + uint32_t inputSize +); + +/* +* Frees the encryption context and clears the memory if the NC_UTIL_CIPHER_ZERO_ON_FREE +* flag is set. +* @param encCtx A valid pointer to an allocated encryption context to free +*/ +NC_EXPORT void NC_CC NCUtilCipherFree(NCUtilCipherContext* encCtx); + +/* +* Gets the output size of the encryption context. This function will return the size of +* the output buffer that will be written to when calling NCUtilCipherReadOutput. +* @param encCtx A valid pointer to an allocated encryption context +* @return The size of the output buffer in bytes +*/ +NC_EXPORT NCResult NC_CC NCUtilCipherGetOutputSize(const NCUtilCipherContext* encCtx); + +/* +* Reads the output buffer from the encryption context. This function will copy the output +* buffer to the output buffer provided. The output buffer must be at least the size of the +* output buffer returned by NCUtilCipherGetOutputSize. +* @param encCtx A valid pointer to an initialized encryption context +* @param output A pointer to the output buffer to copy the output to +* @param outputSize The size of the output buffer in bytes +* @returns The number of bytes written to the output buffer or an error code. Use NCParseErrorCode +* to get the error code and positional argument that caused the error +*/ +NC_EXPORT NCResult NC_CC NCUtilCipherReadOutput( + const NCUtilCipherContext* encCtx, + uint8_t* output, + uint32_t outputSize +); + +/* +* Sets a property on the encryption context. Equivalent to calling NCEncryptionSetPropertyEx +* @param ctx A valid pointer to an encryption context +* @param property The property to set +* @param value A pointer to the value to set +* @param valueLen The length of the value +* @return NC_SUCCESS if the operation was successful, otherwise an error code. Use NCParseErrorCode to +* get the error code and positional argument that caused the error +*/ +NC_EXPORT NCResult NC_CC NCUtilCipherSetProperty( + NCUtilCipherContext* ctx, + uint32_t property, + uint8_t* value, + uint32_t valueLen +); + +/* +* Gets the flags set on the encryption context during initialization. +* @param ctx A valid pointer to an encryption context +* @return The flags set on the encryption context cast to a NCResult, or +* an error code if the context is invalid. Use NCParseErrorCode to get the error code +* and positional argument that caused the error. +*/ +NC_EXPORT NCResult NC_CC NCUtilCipherGetFlags(const NCUtilCipherContext* ctx); + +/* +* Performs the desired Cipher option once. This may either cause an encryption +* or decryption operation to be performed. Regardless of the operation, input data +* is consumed and output data is produced. +* @param encCtx A valid pointer to an initialized encryption context +* @param libContext A valid pointer to an NCContext structure +* @param sk A valid pointer to the sender's private key +* @param pk A valid pointer to the receivers public key +* @return NC_SUCCESS if the operation was successful, otherwise an error code. Use NCParseErrorCode to +* get the error code and positional argument that caused the error. +* @note This function should only be called once. However it is indempotent and deterministic +* so the exact same operation should happen if called again. +*/ +NC_EXPORT NCResult NC_CC NCUtilCipherUpdate( + NCUtilCipherContext* encCtx, + const NCContext* libContext, + const NCSecretKey* sk, + const NCPublicKey* pk +); + +/* +* Gets the size of the IV(nonce) required for the encryption context. +* @param encCtx A valid pointer to an initialized encryption context +* @return The size of the IV in bytes, or a negative error code if the context +* is invalid, or the version is not supported. Use NCParseErrorCode to get the error code +* and positional argument that caused the error. +*/ +NC_EXPORT NCResult NC_CC NCUtilCipherGetIvSize(const NCUtilCipherContext* encCtx); + +#ifdef __cplusplus +} +#endif + +#endif /* NOSCRYPTUTIL_H */
\ No newline at end of file |