diff --git a/.clang-format b/.clang-format index 48b2c67..55a5250 100644 --- a/.clang-format +++ b/.clang-format @@ -1,7 +1,13 @@ --- -Language: Cpp -# BasedOnStyle: LLVM -AccessModifierOffset: -2 +# ---- line ---- +ColumnLimit: 80 +TabWidth: 8 +UseTab: Never +DeriveLineEnding: true +MaxEmptyLinesToKeep: 1 +KeepEmptyLinesAtTheStartOfBlocks: true + +# ---- alignment / tidying ---- AlignAfterOpenBracket: Align AlignArrayOfStructures: None AlignConsecutiveMacros: None @@ -11,182 +17,84 @@ AlignConsecutiveDeclarations: None AlignEscapedNewlines: Right AlignOperands: Align AlignTrailingComments: true -AllowAllArgumentsOnNextLine: true -AllowAllParametersOfDeclarationOnNextLine: true -AllowShortEnumsOnASingleLine: true -AllowShortBlocksOnASingleLine: Never -AllowShortCaseLabelsOnASingleLine: false -AllowShortFunctionsOnASingleLine: All -AllowShortLambdasOnASingleLine: All -AllowShortIfStatementsOnASingleLine: Never -AllowShortLoopsOnASingleLine: false -AlwaysBreakAfterDefinitionReturnType: None -AlwaysBreakAfterReturnType: None -AlwaysBreakBeforeMultilineStrings: false -AlwaysBreakTemplateDeclarations: MultiLine -AttributeMacros: - - __capability -BinPackArguments: true -BinPackParameters: true + +# ---- brace style ---- +BreakBeforeBraces: Attach BraceWrapping: - AfterCaseLabel: false - AfterClass: false + AfterCaseLabel: false AfterControlStatement: Never - AfterEnum: false - AfterFunction: false - AfterNamespace: false - AfterObjCDeclaration: false - AfterStruct: false - AfterUnion: false - AfterExternBlock: false - BeforeCatch: false - BeforeElse: false - BeforeLambdaBody: false - BeforeWhile: false - IndentBraces: false - SplitEmptyFunction: true - SplitEmptyRecord: true - SplitEmptyNamespace: true + AfterEnum: false + AfterFunction: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeElse: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + +# ---- line breaking / operators ---- BreakBeforeBinaryOperators: None -BreakBeforeConceptDeclarations: true -BreakBeforeBraces: Attach -BreakBeforeInheritanceComma: false -BreakInheritanceList: BeforeColon BreakBeforeTernaryOperators: true -BreakConstructorInitializersBeforeComma: false -BreakConstructorInitializers: BeforeColon -BreakAfterJavaFieldAnnotations: false BreakStringLiterals: true -ColumnLimit: 80 -CommentPragmas: '^ IWYU pragma:' -QualifierAlignment: Leave -CompactNamespaces: false -ConstructorInitializerIndentWidth: 4 -ContinuationIndentWidth: 4 -Cpp11BracedListStyle: true -DeriveLineEnding: true -DerivePointerAlignment: false -DisableFormat: false -EmptyLineAfterAccessModifier: Never -EmptyLineBeforeAccessModifier: LogicalBlock -ExperimentalAutoDetectBinPacking: false -PackConstructorInitializers: BinPack -BasedOnStyle: '' -ConstructorInitializerAllOnOneLineOrOnePerLine: false -AllowAllConstructorInitializersOnNextLine: true -FixNamespaceComments: true -ForEachMacros: - - foreach - - Q_FOREACH - - BOOST_FOREACH -IfMacros: - - KJ_IF_MAYBE -IncludeBlocks: Preserve -IncludeCategories: - - Regex: '^"(llvm|llvm-c|clang|clang-c)/' - Priority: 2 - SortPriority: 0 - CaseSensitive: false - - Regex: '^(<|"(gtest|gmock|isl|json)/)' - Priority: 3 - SortPriority: 0 - CaseSensitive: false - - Regex: '.*' - Priority: 1 - SortPriority: 0 - CaseSensitive: false -IncludeIsMainRegex: '(Test)?$' -IncludeIsMainSourceRegex: '' -IndentAccessModifiers: false + +# ---- indent related ---- IndentCaseLabels: false IndentCaseBlocks: false IndentGotoLabels: true IndentPPDirectives: None IndentExternBlock: AfterExternBlock -IndentRequires: false -IndentWidth: 2 -IndentWrappedFunctionNames: false -InsertTrailingCommas: None -JavaScriptQuotes: Leave -JavaScriptWrapImports: true -KeepEmptyLinesAtTheStartOfBlocks: true -LambdaBodyIndentation: Signature -MacroBlockBegin: '' -MacroBlockEnd: '' -MaxEmptyLinesToKeep: 1 -NamespaceIndentation: None -ObjCBinPackProtocolList: Auto -ObjCBlockIndentWidth: 2 -ObjCBreakBeforeNestedBlockParam: true -ObjCSpaceAfterProperty: false -ObjCSpaceBeforeProtocolList: true -PenaltyBreakAssignment: 2 -PenaltyBreakBeforeFirstCallParameter: 19 -PenaltyBreakComment: 300 -PenaltyBreakFirstLessLess: 120 -PenaltyBreakOpenParenthesis: 0 -PenaltyBreakString: 1000 -PenaltyBreakTemplateDeclaration: 10 -PenaltyExcessCharacter: 1000000 -PenaltyReturnTypeOnItsOwnLine: 60 -PenaltyIndentedWhitespace: 0 +IndentWidth: 2 +ContinuationIndentWidth: 4 +PPIndentWidth: -1 + +# ---- pointer / reference ---- +DerivePointerAlignment: false PointerAlignment: Right -PPIndentWidth: -1 -ReferenceAlignment: Pointer -ReflowComments: true -RemoveBracesLLVM: false -SeparateDefinitionBlocks: Leave -ShortNamespaceLines: 1 -SortIncludes: CaseSensitive -SortJavaStaticImport: Before -SortUsingDeclarations: true -SpaceAfterCStyleCast: false -SpaceAfterLogicalNot: false -SpaceAfterTemplateKeyword: true -SpaceBeforeAssignmentOperators: true -SpaceBeforeCaseColon: false -SpaceBeforeCpp11BracedList: false -SpaceBeforeCtorInitializerColon: true -SpaceBeforeInheritanceColon: true -SpaceBeforeParens: ControlStatements -SpaceBeforeParensOptions: - AfterControlStatements: true - AfterForeachMacros: true - AfterFunctionDefinitionName: false - AfterFunctionDeclarationName: false - AfterIfMacros: true - AfterOverloadedOperator: false - BeforeNonEmptyParentheses: false SpaceAroundPointerQualifiers: Default -SpaceBeforeRangeBasedForLoopColon: true -SpaceInEmptyBlock: false -SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 1 -SpacesInAngles: Never -SpacesInConditionalStatement: false -SpacesInContainerLiterals: true -SpacesInCStyleCastParentheses: false + +# ---- spacing ---- +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeParens: ControlStatements +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: Never +SpacesInConditionalStatement: false +SpacesInCStyleCastParentheses: false SpacesInLineCommentPrefix: - Minimum: 1 - Maximum: -1 -SpacesInParentheses: false -SpacesInSquareBrackets: false -SpaceBeforeSquareBrackets: false + Minimum: 1 + Maximum: -1 +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false + +# ---- include sorting ---- +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '.*' + Priority: 1 + SortPriority: 0 + CaseSensitive: false +SortIncludes: CaseSensitive +IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' + +# ---- others ---- +DisableFormat: false +ReflowComments: true +CommentPragmas: '^ IWYU pragma:' BitFieldColonSpacing: Both -Standard: Latest -StatementAttributeLikeMacros: - - Q_EMIT -StatementMacros: - - Q_UNUSED - - QT_REQUIRE_VERSION -TabWidth: 8 -UseCRLF: false -UseTab: Never WhitespaceSensitiveMacros: - STRINGIZE - PP_STRINGIZE - BOOST_PP_STRINGIZE - NS_SWIFT_NAME - CF_SWIFT_NAME -... +UseCRLF: false +... diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..7a47840 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,79 @@ +# ~~~ +# Copyright 2025 CryptoLab, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ~~~ + +name: alea main + +on: + push: + branches: ["main"] + pull_request: + branches: ["main"] + +concurrency: + group: ${{ github.event.pull_request.number || github.sha }} + cancel-in-progress: true + +jobs: + pre-commit: + runs-on: ubuntu-latest + steps: + - name: Install pre-commit + run: | + pip install --upgrade pip + pip install pre-commit + + - uses: actions/checkout@v4 + with: + # Include previous commit + fetch-depth: 2 + + - name: Select target SHA to compare and fetch if required + run: | + if [[ "${{ github.event_name }}" == "pull_request" ]]; then + TARGET_SHA=${{ github.event.pull_request.base.sha }} + # Additionally, as checkout action does not fetch the target PR, we do. + git fetch --no-tags --prune --depth=1 origin $TARGET_SHA + else + TARGET_SHA=$( git rev-parse HEAD^ ) + fi + echo "TARGET_SHA=$TARGET_SHA" >> $GITHUB_ENV + + - name: Generate compile commands + shell: bash -l {0} + run: cmake -S . -B build + + - name: Run pre-commit for commit and push stages. + shell: bash -l {0} + run: pre-commit install && pre-commit run -s $TARGET_SHA -o HEAD --hook-stage commit --hook-stage push + + build-and-test: + runs-on: ${{ matrix.os }} + + strategy: + matrix: + os: [ubuntu-latest, macos-latest] + + defaults: + run: + shell: bash -l {0} + steps: + - uses: actions/checkout@v4 + + - name: Configure Cmake and build + run: cmake --preset release && cmake --build build + + - name: Run tests + run: ctest --test-dir build diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e2a2c4..8a20a36 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -108,11 +108,8 @@ if(ALEA_INSTALL) ${CMAKE_CURRENT_SOURCE_DIR}/cmake/aleaConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/aleaConfig.cmake INSTALL_DESTINATION lib/cmake/alea - PATH_VARS CMAKE_INSTALL_PREFIX - ) + PATH_VARS CMAKE_INSTALL_PREFIX) - install(FILES - ${CMAKE_CURRENT_BINARY_DIR}/aleaConfig.cmake - DESTINATION lib/cmake/alea - ) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/aleaConfig.cmake + DESTINATION lib/cmake/alea) endif() diff --git a/CMakePresets.json b/CMakePresets.json index 0b5c38e..8a496f0 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -21,4 +21,4 @@ } } ] -} \ No newline at end of file +} diff --git a/cmake/aleaConfig.cmake.in b/cmake/aleaConfig.cmake.in index 79632fd..d731332 100644 --- a/cmake/aleaConfig.cmake.in +++ b/cmake/aleaConfig.cmake.in @@ -16,4 +16,4 @@ @PACKAGE_INIT@ -include("${CMAKE_CURRENT_LIST_DIR}/aleaTargets.cmake") \ No newline at end of file +include("${CMAKE_CURRENT_LIST_DIR}/aleaTargets.cmake") diff --git a/include/alea/alea.h b/include/alea/alea.h index d06cdda..5d5fc39 100644 --- a/include/alea/alea.h +++ b/include/alea/alea.h @@ -1,12 +1,12 @@ /* * Copyright 2025 CryptoLab, Inc. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -329,7 +329,7 @@ ALEA_API alea_return alea_get_random_uint32_array_in_range( * @brief Fills an array with random 64-bit integers of specified Hamming * weight. * - * This function fills an array of 64-bit integers where exactly `hwt` entries + * This function fills an array of 64-bit integers where exactly `hwt` entries * in the entire array are 1 or -1 (equidistributed), * and the remaining entries are zero. The positions and * signs of the nonzero values are chosen uniformly at random. @@ -354,7 +354,7 @@ ALEA_API alea_return alea_sample_hwt_int64_array(alea_state *state, * @brief Fills an array with random 32-bit integers of specified Hamming * weight. * - * This function fills an array of 32-bit integers where exactly `hwt` entries + * This function fills an array of 32-bit integers where exactly `hwt` entries * in the entire array are 1 or -1 (equidistributed), * and the remaining entries are zero. The positions and * signs of the nonzero values are chosen uniformly at random. @@ -537,25 +537,27 @@ ALEA_API alea_return alea_sample_gaussian_int32_array(alea_state *state, const double stdev); /** - * @brief Generates a key using the HMAC-based Key Derivation Function (HKDF). - * - * This function implements the HKDF algorithm as defined in RFC 5869, using - * HMAC with SHA-256 as the underlying pseudorandom function (PRF). - * @param ikm Pointer to the input key material (IKM). - * @param ikm_len Length of the input key material in bytes. - * @param salt Pointer to the optional salt value. If NULL, a default salt is used. - * @param salt_len Length of the salt in bytes. If 0, a default salt is used. - * @param info Pointer to the optional context and application-specific information. - * @param info_len Length of the info in bytes. If 0, no info is used. - * @param okm Pointer to the output key material (OKM) buffer. - * @param okm_len Length of the output key material in bytes. - * Must be less than or equal to 255 * SHA3_256_OUTLEN = 8160. - * @return An `alea_return` code indicating success or failure of the operation. -*/ + * @brief Generates a key using the HMAC-based Key Derivation Function (HKDF). + * + * This function implements the HKDF algorithm as defined in RFC 5869, using + * HMAC with SHA-256 as the underlying pseudorandom function (PRF). + * @param ikm Pointer to the input key material (IKM). + * @param ikm_len Length of the input key material in bytes. + * @param salt Pointer to the optional salt value. If NULL, a default salt is + * used. + * @param salt_len Length of the salt in bytes. If 0, a default salt is used. + * @param info Pointer to the optional context and application-specific + * information. + * @param info_len Length of the info in bytes. If 0, no info is used. + * @param okm Pointer to the output key material (OKM) buffer. + * @param okm_len Length of the output key material in bytes. + * Must be less than or equal to 255 * SHA3_256_OUTLEN = 8160. + * @return An `alea_return` code indicating success or failure of the operation. + */ ALEA_API alea_return alea_hkdf(const uint8_t *ikm, size_t ikm_len, - const uint8_t *salt, size_t salt_len, - const uint8_t *info, size_t info_len, - uint8_t *okm, size_t okm_len); + const uint8_t *salt, size_t salt_len, + const uint8_t *info, size_t info_len, + uint8_t *okm, size_t okm_len); #ifdef __cplusplus } diff --git a/include/alea/algorithms.h b/include/alea/algorithms.h index e6a2399..b9dcc60 100644 --- a/include/alea/algorithms.h +++ b/include/alea/algorithms.h @@ -1,12 +1,12 @@ /* * Copyright 2025 CryptoLab, Inc. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/src/alea-builtin.c b/src/alea-builtin.c index 0845f6c..96d68ca 100644 --- a/src/alea-builtin.c +++ b/src/alea-builtin.c @@ -1,12 +1,12 @@ - /* +/* * Copyright 2025 CryptoLab, Inc. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/src/alea-builtin.h b/src/alea-builtin.h index d790749..036b218 100644 --- a/src/alea-builtin.h +++ b/src/alea-builtin.h @@ -1,12 +1,12 @@ /* * Copyright 2025 CryptoLab, Inc. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/src/alea-hkdf.c b/src/alea-hkdf.c index dd7ec82..bcf23c9 100644 --- a/src/alea-hkdf.c +++ b/src/alea-hkdf.c @@ -1,12 +1,12 @@ /* * Copyright 2025 CryptoLab, Inc. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,87 +23,84 @@ #define SHA3_256_OUTLEN 32 #define SHA3_256_BLOCK_SIZE SHA3_256_RATE // 136 -void hmac_sha3_256(const uint8_t *key, size_t key_len, - const uint8_t *data, size_t data_len, - uint8_t *out) { - uint8_t k_ipad[SHA3_256_BLOCK_SIZE]; - uint8_t k_opad[SHA3_256_BLOCK_SIZE]; - uint8_t key_pad[SHA3_256_BLOCK_SIZE]; - uint8_t temp[SHA3_256_OUTLEN]; - size_t i; +void hmac_sha3_256(const uint8_t *key, size_t key_len, const uint8_t *data, + size_t data_len, uint8_t *out) { + uint8_t k_ipad[SHA3_256_BLOCK_SIZE]; + uint8_t k_opad[SHA3_256_BLOCK_SIZE]; + uint8_t key_pad[SHA3_256_BLOCK_SIZE]; + uint8_t temp[SHA3_256_OUTLEN]; + size_t i; - // TODO: Can be optimized by hashing only if key_len > SHA3_256_BLOCK_SIZE - //if (key_len > SHA3_256_BLOCK_SIZE) { - // sha3_256(key_pad, key, key_len); - // memset(key_pad + SHA3_256_OUTLEN, 0, SHA3_256_BLOCK_SIZE - SHA3_256_OUTLEN); - //} else { - // memcpy(key_pad, key, key_len); - // memset(key_pad + key_len, 0, SHA3_256_BLOCK_SIZE - key_len); - //} - sha3_256(key_pad, key, key_len); - memset(key_pad + SHA3_256_OUTLEN, 0, SHA3_256_BLOCK_SIZE - SHA3_256_OUTLEN); + // TODO: Can be optimized by hashing only if key_len > SHA3_256_BLOCK_SIZE + // if (key_len > SHA3_256_BLOCK_SIZE) { + // sha3_256(key_pad, key, key_len); + // memset(key_pad + SHA3_256_OUTLEN, 0, SHA3_256_BLOCK_SIZE - + // SHA3_256_OUTLEN); + //} else { + // memcpy(key_pad, key, key_len); + // memset(key_pad + key_len, 0, SHA3_256_BLOCK_SIZE - key_len); + //} + sha3_256(key_pad, key, key_len); + memset(key_pad + SHA3_256_OUTLEN, 0, SHA3_256_BLOCK_SIZE - SHA3_256_OUTLEN); - for (i = 0; i < SHA3_256_BLOCK_SIZE; i++) { - k_ipad[i] = key_pad[i] ^ 0x36; - k_opad[i] = key_pad[i] ^ 0x5c; - } + for (i = 0; i < SHA3_256_BLOCK_SIZE; i++) { + k_ipad[i] = key_pad[i] ^ 0x36; + k_opad[i] = key_pad[i] ^ 0x5c; + } - // inner hash - uint8_t *inner = malloc(SHA3_256_BLOCK_SIZE + data_len); - memcpy(inner, k_ipad, SHA3_256_BLOCK_SIZE); - memcpy(inner + SHA3_256_BLOCK_SIZE, data, data_len); - sha3_256(temp, inner, SHA3_256_BLOCK_SIZE + data_len); - free(inner); + // inner hash + uint8_t *inner = malloc(SHA3_256_BLOCK_SIZE + data_len); + memcpy(inner, k_ipad, SHA3_256_BLOCK_SIZE); + memcpy(inner + SHA3_256_BLOCK_SIZE, data, data_len); + sha3_256(temp, inner, SHA3_256_BLOCK_SIZE + data_len); + free(inner); - // outer hash - uint8_t outer[SHA3_256_BLOCK_SIZE + SHA3_256_OUTLEN]; - memcpy(outer, k_opad, SHA3_256_BLOCK_SIZE); - memcpy(outer + SHA3_256_BLOCK_SIZE, temp, SHA3_256_OUTLEN); - sha3_256(out, outer, SHA3_256_BLOCK_SIZE + SHA3_256_OUTLEN); + // outer hash + uint8_t outer[SHA3_256_BLOCK_SIZE + SHA3_256_OUTLEN]; + memcpy(outer, k_opad, SHA3_256_BLOCK_SIZE); + memcpy(outer + SHA3_256_BLOCK_SIZE, temp, SHA3_256_OUTLEN); + sha3_256(out, outer, SHA3_256_BLOCK_SIZE + SHA3_256_OUTLEN); } -void hkdf_extract(const uint8_t *ikm, size_t ikm_len, - const uint8_t *salt, size_t salt_len, - uint8_t *prk) { - hmac_sha3_256(salt, salt_len, ikm, ikm_len, prk); +void hkdf_extract(const uint8_t *ikm, size_t ikm_len, const uint8_t *salt, + size_t salt_len, uint8_t *prk) { + hmac_sha3_256(salt, salt_len, ikm, ikm_len, prk); } -void hkdf_expand(const uint8_t *prk, size_t prk_len, - const uint8_t *info, size_t info_len, - uint8_t *okm, size_t okm_len) { - size_t hash_len = SHA3_256_OUTLEN; // SHA3-256 output size - size_t n = (okm_len + hash_len - 1) / hash_len; - uint8_t t[SHA3_256_OUTLEN]; - uint8_t prev[SHA3_256_OUTLEN]; - size_t pos = 0; - uint8_t *tmp = malloc(SHA3_256_OUTLEN + info_len + 1); - for (size_t i = 1; i <= n; ++i) { - // Concatenate: prev | info | counter - size_t tmplen = 0; - if (i != 1) { - memcpy(tmp, prev, hash_len); - tmplen += hash_len; - } - memcpy(tmp + tmplen, info, info_len); - tmplen += info_len; - tmp[tmplen] = (uint8_t)i; - tmplen += 1; +void hkdf_expand(const uint8_t *prk, size_t prk_len, const uint8_t *info, + size_t info_len, uint8_t *okm, size_t okm_len) { + size_t hash_len = SHA3_256_OUTLEN; // SHA3-256 output size + size_t n = (okm_len + hash_len - 1) / hash_len; + uint8_t t[SHA3_256_OUTLEN]; + uint8_t prev[SHA3_256_OUTLEN]; + size_t pos = 0; + uint8_t *tmp = malloc(SHA3_256_OUTLEN + info_len + 1); + for (size_t i = 1; i <= n; ++i) { + // Concatenate: prev | info | counter + size_t tmplen = 0; + if (i != 1) { + memcpy(tmp, prev, hash_len); + tmplen += hash_len; + } + memcpy(tmp + tmplen, info, info_len); + tmplen += info_len; + tmp[tmplen] = (uint8_t)i; + tmplen += 1; - hmac_sha3_256(prk, prk_len, tmp, tmplen, t); - memcpy(prev, t, hash_len); + hmac_sha3_256(prk, prk_len, tmp, tmplen, t); + memcpy(prev, t, hash_len); - size_t copylen = (pos + hash_len > okm_len) ? (okm_len - pos) : hash_len; - memcpy(okm + pos, t, copylen); - pos += copylen; - } - free(tmp); + size_t copylen = (pos + hash_len > okm_len) ? (okm_len - pos) : hash_len; + memcpy(okm + pos, t, copylen); + pos += copylen; + } + free(tmp); } -void hkdf(const uint8_t *ikm, size_t ikm_len, - const uint8_t *salt, size_t salt_len, - const uint8_t *info, size_t info_len, - uint8_t *okm, size_t okm_len) { - uint8_t prk[SHA3_256_OUTLEN]; - hkdf_extract(ikm, ikm_len, salt, salt_len, prk); - hkdf_expand(prk, sizeof(prk), info, info_len, okm, okm_len); +void hkdf(const uint8_t *ikm, size_t ikm_len, const uint8_t *salt, + size_t salt_len, const uint8_t *info, size_t info_len, uint8_t *okm, + size_t okm_len) { + uint8_t prk[SHA3_256_OUTLEN]; + hkdf_extract(ikm, ikm_len, salt, salt_len, prk); + hkdf_expand(prk, sizeof(prk), info, info_len, okm, okm_len); } diff --git a/src/alea-hkdf.h b/src/alea-hkdf.h index fe74aad..4c09107 100644 --- a/src/alea-hkdf.h +++ b/src/alea-hkdf.h @@ -1,12 +1,12 @@ /* * Copyright 2025 CryptoLab, Inc. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -19,21 +19,17 @@ #include "alea/alea.h" -void hmac_sha3_256(const uint8_t *key, size_t key_len, - const uint8_t *data, size_t data_len, - uint8_t *out); +void hmac_sha3_256(const uint8_t *key, size_t key_len, const uint8_t *data, + size_t data_len, uint8_t *out); -void hkdf_extract(const uint8_t *ikm, size_t ikm_len, - const uint8_t *salt, size_t salt_len, - uint8_t *prk); +void hkdf_extract(const uint8_t *ikm, size_t ikm_len, const uint8_t *salt, + size_t salt_len, uint8_t *prk); -void hkdf_expand(const uint8_t *prk, size_t prk_len, - const uint8_t *info, size_t info_len, - uint8_t *okm, size_t okm_len); +void hkdf_expand(const uint8_t *prk, size_t prk_len, const uint8_t *info, + size_t info_len, uint8_t *okm, size_t okm_len); -void hkdf(const uint8_t *ikm, size_t ikm_len, - const uint8_t *salt, size_t salt_len, - const uint8_t *info, size_t info_len, - uint8_t *okm, size_t okm_len); +void hkdf(const uint8_t *ikm, size_t ikm_len, const uint8_t *salt, + size_t salt_len, const uint8_t *info, size_t info_len, uint8_t *okm, + size_t okm_len); #endif // ALEA_ALEA_HKDF_H diff --git a/src/alea-internal.h b/src/alea-internal.h index c9b3375..de440b7 100644 --- a/src/alea-internal.h +++ b/src/alea-internal.h @@ -1,12 +1,12 @@ /* * Copyright 2025 CryptoLab, Inc. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/src/alea.c b/src/alea.c index 46e48a4..c894591 100644 --- a/src/alea.c +++ b/src/alea.c @@ -15,8 +15,8 @@ */ #include "alea/alea.h" -#include "alea-internal.h" #include "alea-hkdf.h" +#include "alea-internal.h" #include #include @@ -380,9 +380,8 @@ alea_return alea_sample_gaussian_int32_array(alea_state *state, return ALEA_RETURN_OK; } -alea_return alea_hkdf(const uint8_t *ikm, size_t ikm_len, - const uint8_t *salt, size_t salt_len, - const uint8_t *info, size_t info_len, +alea_return alea_hkdf(const uint8_t *ikm, size_t ikm_len, const uint8_t *salt, + size_t salt_len, const uint8_t *info, size_t info_len, uint8_t *okm, size_t okm_len) { assert(okm_len <= 8160); // 255 * SHA3_256_OUTLEN = 255 * 32 = 8160 diff --git a/src/fips202.h b/src/fips202.h index 314a7c8..9211b31 100644 --- a/src/fips202.h +++ b/src/fips202.h @@ -1,12 +1,12 @@ /* * Copyright 2025 CryptoLab, Inc. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/test/dudect_wrapper.c b/test/dudect_wrapper.c index fb267ee..8cab0c2 100644 --- a/test/dudect_wrapper.c +++ b/test/dudect_wrapper.c @@ -1,12 +1,12 @@ /* * Copyright 2025 CryptoLab, Inc. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/test/dudect_wrapper.h b/test/dudect_wrapper.h index 96fe3f6..0788ba2 100644 --- a/test/dudect_wrapper.h +++ b/test/dudect_wrapper.h @@ -1,12 +1,12 @@ /* * Copyright 2025 CryptoLab, Inc. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/test/functionality-test.c b/test/functionality-test.c index 68f2cb9..4200997 100644 --- a/test/functionality-test.c +++ b/test/functionality-test.c @@ -1,12 +1,12 @@ /* * Copyright 2025 CryptoLab, Inc. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -80,7 +80,7 @@ count_out_of_range++; \ } \ } \ - TEST_ASSERT_LESS_OR_EQUAL(range *VERIFY_SIGMA_TOLER, count_out_of_range); \ + TEST_ASSERT_LESS_OR_EQUAL(range * VERIFY_SIGMA_TOLER, count_out_of_range); \ } #define CHECK_HWT(bit) \ diff --git a/test/lowlevel-test.c b/test/lowlevel-test.c index 45bb34e..928b81f 100644 --- a/test/lowlevel-test.c +++ b/test/lowlevel-test.c @@ -1,12 +1,12 @@ /* * Copyright 2025 CryptoLab, Inc. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -149,7 +149,7 @@ static void resqueezing_shake256(void) { // force resqueezing by requesting random bytes again and again for (int i = 0; i < NBLOCKS; ++i) { alea_get_random_bytes(g_state_256, get, SHAKE256_RATE); - //printf("%02hhx %02hhx\n", get[0], get[1]); + // printf("%02hhx %02hhx\n", get[0], get[1]); } alea_get_random_bytes(g_state_256, get, SHAKE256_RATE); // for test @@ -188,13 +188,10 @@ static void hkdf_sha3_256(void) { alea_hkdf(ikm, 22, salt, 16, info, 10, okm, 42); const uint8_t expected[42] = { - 0x6b, 0x1c, 0x2e, 0x66, 0xd3, 0x3c, 0x85, 0xe1, - 0x47, 0x28, 0xe5, 0x6a, 0xb0, 0xde, 0x32, 0x18, - 0xee, 0x2f, 0x20, 0xe1, 0x7d, 0xb5, 0x6e, 0x7c, - 0x91, 0x00, 0x49, 0x03, 0xce, 0x94, 0xcf, 0xe9, - 0x69, 0x09, 0xf4, 0x9b, 0x41, 0x27, 0xe2, 0x30, - 0x85, 0xcb - }; + 0x6b, 0x1c, 0x2e, 0x66, 0xd3, 0x3c, 0x85, 0xe1, 0x47, 0x28, 0xe5, + 0x6a, 0xb0, 0xde, 0x32, 0x18, 0xee, 0x2f, 0x20, 0xe1, 0x7d, 0xb5, + 0x6e, 0x7c, 0x91, 0x00, 0x49, 0x03, 0xce, 0x94, 0xcf, 0xe9, 0x69, + 0x09, 0xf4, 0x9b, 0x41, 0x27, 0xe2, 0x30, 0x85, 0xcb}; TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, okm, 42); } diff --git a/test/timing-test.c b/test/timing-test.c index bcb79f0..a794588 100644 --- a/test/timing-test.c +++ b/test/timing-test.c @@ -1,12 +1,12 @@ /* * Copyright 2025 CryptoLab, Inc. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.