From ea15299006cc2486c44fea72381e0c9e555c0d75 Mon Sep 17 00:00:00 2001 From: vnugent Date: Thu, 22 Aug 2024 21:57:51 -0400 Subject: Squashed commit of the following: commit 202585c270529a8fc52c5e5c811efe99b57eff53 Author: vnugent Date: Thu Aug 22 17:51:51 2024 -0400 update changelog and readme for 0.1.4 commit 2cc00996c79dd8b26c7d0aa91dc2bfe0bcfa8ec0 Author: vnugent Date: Sat Aug 17 21:53:16 2024 -0400 fix: #8 patched reusable cipher encryption bug commit 756a184762db4cb0a9945d066b59d0e2f58c18d8 Author: vnugent Date: Mon Aug 12 14:23:13 2024 -0400 fix changelog tags, whoops commit 489d90f565dc0b9e147ec248cccfd0b7c10fe0ab Merge: a639280 fa5e809 Author: vnugent Date: Mon Aug 12 13:58:15 2024 -0400 Merge branch 'master' into develop --- CHANGELOG.md | 20 ++++++++++---- README.md | 79 +++++++++++++++--------------------------------------- src/noscryptutil.c | 52 +++++++++++++++++++++++------------ 3 files changed, 71 insertions(+), 80 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38f1c09..2414a2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,10 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [0.1.3-beta] - 2024-08-6 +### Added +- C# .NET 8.0 library wrapper for noscrypt +- NIP44 vector testing for encryption + +## [0.1.4] + +### Fixed +- [#8](https://www.vaughnnugent.com/resources/software/modules/noscrypt-issues?id=51) - an issue where nip44 encryption fails on reusable cipher instances + +## [0.1.3] ### Added -- Utilities sidecar library for easy note encryption (noscryptutil.h) +- Utilities sidecar library for easy note encryption [(noscryptutil.h)](https://github.com/VnUgE/noscrypt/blob/v0.1.3/include/noscryptutil.h) - Utilities for padding calculations - Prints the name of the configured crypto backend during build - Many internal hardening improvments (span pass-by-value, span validation functions) @@ -35,7 +44,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `NC_ENCRYPTION_NONCE_SIZE` macro for better forward compatability - `NC_NIP04_AES_IV_SIZE` macro for better forward compatability -## [0.1.2] - 2024-05-29 +## [0.1.2] ### Added @@ -60,7 +69,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - NCContext structure defintion. - Internal headers from the public include directory. -[unreleased]: https://github.com/VnUgE/noscrypt/compare/v0.1.3-beta...HEAD -[0.1.3-beta]: https://github.com/VnUgE/noscrypt/compare/v0.1.2...v0.1.3-beta +[unreleased]: https://github.com/VnUgE/noscrypt/compare/v0.1.4...HEAD +[0.1.4]: https://github.com/VnUgE/noscrypt/compare/v0.1.3...v0.1.4 +[0.1.3]: https://github.com/VnUgE/noscrypt/compare/v0.1.2...v0.1.3 [0.1.2]: https://github.com/VnUgE/noscrypt/compare/v0.1.1...v0.1.2 [0.1.1]: https://github.com/VnUgE/noscrypt/compare/v0.1.0...v0.1.1 diff --git a/README.md b/README.md index f6fe93f..caea4af 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ NCVerifyMac() ``` ## Motivation -At the time of building this project I have not come across any C-only libraries that exposed functionality for nostr specific cryptography. IMO it is easy to use the secp256k1 library incorrectly. In the process of building [NVault](https://github.com/VnUgE/NVault) NIP-44 came out in December and I realized my libraries were falling short for my needs for proper and safe nostr cryptographic operations, and I needed to start over and start with a good base that has all the basic functionality built with trusted and tested libraries. +At the time of building this project I have not come across any C-only libraries that exposed functionality for nostr specific cryptography. IMO it is easy to use the secp256k1 library [incorrectly](https://www.vaughnnugent.com/Blog/d9ab8a46cfa8d6bd59cf048fec8d73ffc44f881c). In the process of building [NVault](https://github.com/VnUgE/NVault) NIP-44 came out in December and I realized my libraries were falling short for my needs for proper and safe nostr cryptographic operations, and I needed to start over and start with a good base that has all the basic functionality built with trusted and tested libraries. I wanted a compact and efficient utility library that was portable across systems and runtimes. I will primarily be using this library in a .NET environment, but would like to make a hardware signer sometime. @@ -41,7 +41,7 @@ Testing is an will be important to a cryptography library, I take that responsib ### Hardness - Time sensitive verification always uses fixed time comparison -- No explicit/dynamic memory allocations +- No explicit/dynamic memory allocations (in core library) - Public API function input validation is on by default - All stack allocated structures are securely zeroed before return - Stack protection is enabled by default for GCC and MSVC compilers @@ -60,65 +60,26 @@ The following table lists the supported platforms and cryptography libraries tha ## Getting started -GitHub is simply a mirror for my projects. Extended documentation, pre-compiled binaries and source code bundles are always available on my website, along with PGP signatures and checksums. +GitHub and Codeberg are only mirrors for my projects. Extended documentation, pre-compiled binaries and source code bundles are always available on my website, along with PGP signatures and checksums. -- **[Documentation](https://www.vaughnnugent.com/resources/software/articles?tags=docs,_noscrypt)** -- **[Signed builds and source code](https://www.vaughnnugent.com/resources/software/modules/noscrypt)** +[__Project homepage__](https://www.vaughnnugent.com/resources/software/modules/noscrypt) +[__Startup & Install Guide__](https://www.vaughnnugent.com/resources/software/articles/62ca932f68b8e0b1b99dca6e1c9ffe5538205efb) +[__Extended Documentation__](https://www.vaughnnugent.com/resources/software/articles?tags=docs,_noscrypt) -### Getting the package -There are 3 ways to get the source code to build this project. -1. Download the signed `noscrypt-src.tgz` package from my website above (recommended) -2. Clone the GitHub repo `git clone https://github.com/VnUgE/noscrypt.git` -3. Download a github archive or release when they are available +### Super quick start +If you are in a hurry to try out noscrypt these steps will get you by. Otherwise website documentation is authoritative and I encourage you read the docs. -## Building -**The following build commands may be incomplete.** Please read documentation (link above) for all custom build configurations and tips. +#### Prerequisites +- Supported operating system and compiler from table above +- [CMake](https://cmake.org/download) build system +- [Taskfile.dev](https://taskfile.dev) to execute build recipe -### Using CMake ```shell -cmake -S . -Bbuild/ -DCMAKE_BUILD_TYPE=Release -``` - -Enable built-in tests and debug mode -```shell -cmake -S . -Bbuild/test -DCMAKE_BUILD_TYPE=Debug -DNC_BUILD_TESTS=ON -``` - -Specify the crypto library -```shell -cmake -S . -Bbuild/ -DCMAKE_BUILD_TYPE=Release -DCRYPTO_LIB= -``` - -Install library globally -```shell -cmake --install build/ -``` - -### Using Task -A [Taskfile](https://taskfile.dev) file is included for easy building if you wish to build in easy mode! Use the `task --list` to see all available commands. The default command `task` will build the library locally in release mode using defaults. - -```shell -task -``` -Build in debug mode with tests enabled -```shell -task build-debug -``` - -Build in debug mode, with testing enabled, then runs the test executable after it's built -```shell -task test -``` - -Install globally. Run after running the default task or `build-debug` task -```shell -task install -``` - -Task accepts any extra arguments following `--` and passes them to the cmake build command. -Example: -```shell -task -- -DCMAKE_X_X=x +mkdir noscrypt/ && cd noscrypt/ +wget https://www.vaughnnugent.com/public/resources/software/builds/noscrypt//noscrypt/noscrypt-src.tgz +tar -xzf noscrypt-src.tgz +task +sudo task install ``` ## Notes @@ -129,13 +90,15 @@ Build packages on my website are "manual" I use an internal tool called *vnbuild There are currently 2 branches I use because of my build process. `develop` and `master`. All changes happen in develop, then are merged to master when I feel like they are stable enough. After some testing and time, a tag and release will become available. #### Windows Dlls -You may notice that I have msvc pre-compiled packages available for download. I have not compatibility tested them yet so they should only support Windows 10/Server version 1904 running amd64 processors. +msvc pre-compiled packages available for download on the website package page. I have not compatibility tested them yet so they should only support Windows NT version 1904 (10/Server 2016 and later) running amd64 processors. ## License The software in this repository is licensed to you under the GNU Lesser GPL v2.1 or later. `SPDX-License-Identifier: LGPL-2.1-or-later` see the [LICENSE](LICENSE) file for more details. ## Donations -If you feel so inclined to support me an this project, donations are welcome and much appreciated. +If you feel so inclined to support me an this project, donations are welcome and much appreciated. LNURL coming soon. BTC On-Chain: ``bc1qgj4fk6gdu8lnhd4zqzgxgcts0vlwcv3rqznxn9`` +I am also a member of [GitCitadel](https://next.nostrudel.ninja/#/wiki/topic/gitcitadel-project) so feel free to [send some sats](https://geyser.fund/project/gitcitadel) that way too! + diff --git a/src/noscryptutil.c b/src/noscryptutil.c index 89e0f35..115ad04 100644 --- a/src/noscryptutil.c +++ b/src/noscryptutil.c @@ -59,7 +59,7 @@ #define _nc_mem_free(x) if(x != NULL) { free(x); x = NULL; } -#define _nc_mem_alloc(elements, size) calloc(elements, size); +#define _nc_mem_alloc(elements, size) calloc(elements, size) #define ZERO_FILL ncCryptoSecureZero #ifndef NC_INPUT_VALIDATION_OFF @@ -129,8 +129,11 @@ static _nc_fn_inline span_t _ncUtilAllocSpan(uint32_t count, size_t size) #endif - span.data = _nc_mem_alloc((size_t)count, size); - span.size = (uint32_t)count; + ncSpanInit( + &span, + _nc_mem_alloc((size_t)count, size), + (uint32_t)count + ); return span; } @@ -233,7 +236,7 @@ static _nc_fn_inline span_t _nip44GetMacData(span_t payload) return ncSpanSlice( payload, NIP44_VERSION_SIZE, - payload.size - (NIP44_VERSION_SIZE + NC_ENCRYPTION_MAC_SIZE) + ncSpanGetSize(payload) - (NIP44_VERSION_SIZE + NC_ENCRYPTION_MAC_SIZE) ); } @@ -246,7 +249,7 @@ static _nc_fn_inline span_t _nip44GetMacOutput(span_t payload) */ return ncSpanSlice( payload, - payload.size - NC_ENCRYPTION_MAC_SIZE, + ncSpanGetSize(payload) - NC_ENCRYPTION_MAC_SIZE, NC_ENCRYPTION_MAC_SIZE ); } @@ -259,7 +262,7 @@ static _nc_fn_inline int _nip44ParseSegments( cspan_t* cipherText ) { - if (payload.size < NIP44_MIN_PAYLOAD_SIZE) + if (ncSpanGetSizeC(payload) < NIP44_MIN_PAYLOAD_SIZE) { return 0; } @@ -276,7 +279,7 @@ static _nc_fn_inline int _nip44ParseSegments( */ *mac = ncSpanSliceC( payload, - payload.size - NC_ENCRYPTION_MAC_SIZE, + ncSpanGetSizeC(payload) - NC_ENCRYPTION_MAC_SIZE, NC_ENCRYPTION_MAC_SIZE ); @@ -286,7 +289,7 @@ static _nc_fn_inline int _nip44ParseSegments( *macData = ncSpanSliceC( payload, NIP44_VERSION_SIZE, - payload.size - (NIP44_VERSION_SIZE + NC_ENCRYPTION_MAC_SIZE) + ncSpanGetSizeC(payload) - (NIP44_VERSION_SIZE + NC_ENCRYPTION_MAC_SIZE) ); /* @@ -295,7 +298,7 @@ static _nc_fn_inline int _nip44ParseSegments( *cipherText = ncSpanSliceC( payload, NIP44_VERSION_SIZE + NIP44_NONCE_SIZE, - payload.size - (NIP44_VERSION_SIZE + NIP44_NONCE_SIZE + NC_ENCRYPTION_MAC_SIZE) + ncSpanGetSizeC(payload) - (NIP44_VERSION_SIZE + NIP44_NONCE_SIZE + NC_ENCRYPTION_MAC_SIZE) ); return 1; @@ -351,8 +354,21 @@ static NCResult _nip44EncryptCompleteCore( outPos = 0; encArgs = state->encArgs; - message = state->buffer.output; plainText = state->buffer.input; + + /* + * Output buffer may be reused for multiple operations + * so it may be larger than the actual output size but + * it is always guaranteed to be large enough to hold the + * output data. + * + * slice has debug guards to ensure output is large enough + */ + message = ncSpanSlice( + state->buffer.output, + 0, + _calcNip44TotalOutSize(plainText.size) + ); DEBUG_ASSERT(encArgs.version == NC_ENC_VERSION_NIP44); @@ -440,7 +456,9 @@ static NCResult _nip44EncryptCompleteCore( ncSpanGetSizeC(plainText) ); - /* Move position pointer directly after final padding bytes */ + /* + * Move position pointer directly after final padding bytes + */ outPos += encArgs.dataSize; result = NCEncrypt(libContext, sk, pk, &encArgs); @@ -473,7 +491,7 @@ static NCResult _nip44EncryptCompleteCore( outPos += NC_ENCRYPTION_MAC_SIZE; - DEBUG_ASSERT2(outPos == message.size, "Buffer under/overflow detected"); + DEBUG_ASSERT2(outPos == ncSpanGetSize(message), "Buffer under/overflow detected"); /* publish all message bytes to output */ _cipherPublishOutput(state, 0, outPos); @@ -607,7 +625,7 @@ static NCResult _nip44DecryptCompleteCore( */ _cipherPublishOutput(state, NIP44_PT_LEN_SIZE, ptSize); - DEBUG_ASSERT(ncSpanGetSizeC(state->buffer.actualOutput) < cipherText.size); + DEBUG_ASSERT(ncSpanGetSizeC(state->buffer.actualOutput) < ncSpanGetSizeC(cipherText)); return NC_SUCCESS; } @@ -782,7 +800,7 @@ NC_EXPORT NCResult NC_CC NCUtilCipherInit( * data reuse it, otherwise free it and allocate a new buffer */ - if (outputSize <= encCtx->buffer.output.size) + if (outputSize <= ncSpanGetSize(encCtx->buffer.output)) { _ncUtilZeroSpan(encCtx->buffer.output); @@ -829,7 +847,7 @@ NC_EXPORT NCResult NC_CC NCUtilCipherGetOutputSize(const NCUtilCipherContext* en return E_CIPHER_NO_OUTPUT; } - return (NCResult)(encCtx->buffer.actualOutput.size); + return (NCResult)(ncSpanGetSizeC(encCtx->buffer.actualOutput)); } NC_EXPORT NCResult NC_CC NCUtilCipherReadOutput( @@ -847,7 +865,7 @@ NC_EXPORT NCResult NC_CC NCUtilCipherReadOutput( } /* Buffer must be as large as the output data */ - CHECK_ARG_RANGE(outputSize, encCtx->buffer.actualOutput.size, UINT32_MAX, 2); + CHECK_ARG_RANGE(outputSize, ncSpanGetSizeC(encCtx->buffer.actualOutput), UINT32_MAX, 2); ncSpanReadC( encCtx->buffer.actualOutput, @@ -855,7 +873,7 @@ NC_EXPORT NCResult NC_CC NCUtilCipherReadOutput( outputSize ); - return (NCResult)encCtx->buffer.actualOutput.size; + return (NCResult)(ncSpanGetSizeC(encCtx->buffer.actualOutput)); } NC_EXPORT NCResult NC_CC NCUtilCipherSetProperty( -- cgit