Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
833dda4
Add vendor-xkcp.sh script
simonjbeaumont Aug 6, 2025
f938d7e
Revendor xkcp#master (heads/master-0-g11297f5)
simonjbeaumont Aug 6, 2025
532279f
Add CXCKP target with modulemap and umbrella header
simonjbeaumont Aug 6, 2025
a59f707
Add CXKCPTests test target with simple test vectors
simonjbeaumont Aug 6, 2025
7cbd6b6
Add CXKCPShims with function wrappers for macros to call from Swift
simonjbeaumont Jun 5, 2025
f6bc4cb
Remove #if false guard from HashFunctions_SHA3.swift
simonjbeaumont Aug 6, 2025
f876bdb
Add SHA-3 implementation backed by libXKCP
simonjbeaumont Jun 5, 2025
fb4e268
Add new DigestImplSHA3 platform-specific type alias
simonjbeaumont Aug 6, 2025
907790e
Remove #if false from DigestsTests.swift to get SHA-3 tests
simonjbeaumont Aug 6, 2025
05f0f57
Add PrivacyInfo.xcprivacy files to new targets
simonjbeaumont Aug 6, 2025
5180b02
Add check for buffer size in both BoringSSL and XKCP hash finalize
simonjbeaumont Aug 6, 2025
d899836
Update path of vendored-sources.txt output file
simonjbeaumont Aug 7, 2025
5f6e5b3
Revendor xkcp#master (heads/master-0-g11297f5)
simonjbeaumont Aug 11, 2025
c2ee39e
Update .unacceptablelanguageignore to exclude Sources/CXKCP/
simonjbeaumont Aug 11, 2025
5bef2f7
Update .licenseignore to exclude Sources/CXKCP/
simonjbeaumont Aug 11, 2025
e546473
Update CMake lists
simonjbeaumont Aug 11, 2025
c736b6a
Fix formatting
simonjbeaumont Aug 11, 2025
13075b8
Add licence header to vendoring script
simonjbeaumont Aug 11, 2025
5d1c1ba
Add CMakeLists for new modules
simonjbeaumont Aug 11, 2025
7413d58
Only include SHA-3 digests in DigestTests when available in the SDK
simonjbeaumont Aug 11, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/pull_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ jobs:
{ "name": "CCryptoBoringSSL", "type": "source", "exceptions": [] },
{ "name": "CCryptoBoringSSLShims", "type": "source", "exceptions": [] },
{ "name": "CryptoBoringWrapper", "type": "source", "exceptions": [] },
{ "name": "CXKCP", "type": "source", "exceptions": [] },
{ "name": "CXKCPShims", "type": "source", "exceptions": [] },
{ "name": "Crypto", "type": "source", "exceptions": [] },
{ "name": "_CryptoExtras", "type": "source", "exceptions": [] },
{ "name": "CCryptoBoringSSL", "type": "assembly", "exceptions": [ "*/AES/*.swift" ] }
Expand Down
1 change: 1 addition & 0 deletions .licenseignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ dev/update-benchmark-thresholds
**/*.der
.swiftformat
Sources/CCryptoBoringSSL/*
Sources/CXKCP/*
**/*.swift.gyb
scripts/*.patch
scripts/gyb
Expand Down
3 changes: 2 additions & 1 deletion .unacceptablelanguageignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
Sources/CCryptoBoringSSL/*
Sources/CCryptoBoringSSL/*
Sources/CXKCP/*
28 changes: 28 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ if development || isFreeBSD {
"CCryptoBoringSSL",
"CCryptoBoringSSLShims",
"CryptoBoringWrapper",
"CXKCP",
"CXKCPShims",
]
} else {
let platforms: [Platform] = [
Expand All @@ -66,6 +68,8 @@ if development || isFreeBSD {
.target(name: "CCryptoBoringSSL", condition: .when(platforms: platforms)),
.target(name: "CCryptoBoringSSLShims", condition: .when(platforms: platforms)),
.target(name: "CryptoBoringWrapper", condition: .when(platforms: platforms)),
.target(name: "CXKCP", condition: .when(platforms: platforms)),
.target(name: "CXKCPShims", condition: .when(platforms: platforms)),
]
}

Expand Down Expand Up @@ -125,6 +129,21 @@ let package = Package(
.define("OPENSSL_NO_ASM", .when(platforms: [Platform.wasi])),
]
),
.target(
name: "CXKCP",
exclude: [
"CMakeLists.txt"
],
cSettings: [
.define("XKCP_has_KeccakP1600"),
.headerSearchPath("include"),
.headerSearchPath("high"),
.headerSearchPath("low"),
.headerSearchPath("low/KeccakP-1600"),
.headerSearchPath("low/common"),
.headerSearchPath("common"),
]
),
.target(
name: "CCryptoBoringSSLShims",
dependencies: ["CCryptoBoringSSL"],
Expand All @@ -133,6 +152,14 @@ let package = Package(
],
resources: privacyManifestResource
),
.target(
name: "CXKCPShims",
dependencies: ["CXKCP"],
exclude: privacyManifestExclude + [
"CMakeLists.txt"
],
resources: privacyManifestResource
),
.target(
name: "Crypto",
dependencies: dependencies,
Expand Down Expand Up @@ -205,6 +232,7 @@ let package = Package(
swiftSettings: swiftSettings
),
.testTarget(name: "CryptoBoringWrapperTests", dependencies: ["CryptoBoringWrapper"]),
.testTarget(name: "CXKCPTests", dependencies: ["CXKCP"]),
],
cxxLanguageStandard: .cxx17
)
Expand Down
2 changes: 2 additions & 0 deletions Sources/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

add_subdirectory(CCryptoBoringSSL)
add_subdirectory(CCryptoBoringSSLShims)
add_subdirectory(CXKCP)
add_subdirectory(CXKCPShims)
add_subdirectory(CryptoBoringWrapper)
add_subdirectory(Crypto)
add_subdirectory(_CryptoExtras)
34 changes: 34 additions & 0 deletions Sources/CXKCP/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
##===----------------------------------------------------------------------===##
##
## This source file is part of the SwiftCrypto open source project
##
## Copyright (c) 2021 Apple Inc. and the SwiftCrypto project authors
## Licensed under Apache License v2.0
##
## See LICENSE.txt for license information
## See CONTRIBUTORS.txt for the list of SwiftCrypto project authors
##
## SPDX-License-Identifier: Apache-2.0
##
##===----------------------------------------------------------------------===##

add_library(CXKCP STATIC
"FIPS202-opt64/KeccakHash.c"
"FIPS202-opt64/KeccakP-1600-opt64.c"
"FIPS202-opt64/KeccakSponge.c"
"FIPS202-opt64/SimpleFIPS202.c"
)

target_include_directories(CXKCP PUBLIC
include)

target_compile_definitions(CXKCP PRIVATE
$<$<PLATFORM_ID:Windows>:WIN32_LEAN_AND_MEAN>)
target_link_libraries(CXKCP PUBLIC
$<$<NOT:$<PLATFORM_ID:Darwin>>:dispatch>
$<$<NOT:$<PLATFORM_ID:Darwin>>:Foundation>
SwiftASN1)
set_target_properties(CXKCP PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/include;${CMAKE_Swift_MODULE_DIRECTORY}")

set_property(GLOBAL APPEND PROPERTY SWIFT_CRYPTO_EXPORTS CXKCP)
81 changes: 81 additions & 0 deletions Sources/CXKCP/FIPS202-opt64/KeccakHash.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
The eXtended Keccak Code Package (XKCP)
https://github.com/XKCP/XKCP

Keccak, designed by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche.

Implementation by the designers, hereby denoted as "the implementer".

For more information, feedback or questions, please refer to the Keccak Team website:
https://keccak.team/

To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/

#include <string.h>
#include "KeccakHash.h"

/* ---------------------------------------------------------------- */

HashReturn Keccak_HashInitialize(Keccak_HashInstance *instance, unsigned int rate, unsigned int capacity, unsigned int hashbitlen, unsigned char delimitedSuffix)
{
HashReturn result;

if (delimitedSuffix == 0)
return KECCAK_FAIL;
result = (HashReturn)KeccakWidth1600_SpongeInitialize(&instance->sponge, rate, capacity);
if (result != KECCAK_SUCCESS)
return result;
instance->fixedOutputLength = hashbitlen;
instance->delimitedSuffix = delimitedSuffix;
return KECCAK_SUCCESS;
}

/* ---------------------------------------------------------------- */

HashReturn Keccak_HashUpdate(Keccak_HashInstance *instance, const BitSequence *data, BitLength databitlen)
{
if ((databitlen % 8) == 0)
return (HashReturn)KeccakWidth1600_SpongeAbsorb(&instance->sponge, data, databitlen/8);
else {
HashReturn ret = (HashReturn)KeccakWidth1600_SpongeAbsorb(&instance->sponge, data, databitlen/8);
if (ret == KECCAK_SUCCESS) {
/* The last partial byte is assumed to be aligned on the least significant bits */
unsigned char lastByte = data[databitlen/8];
/* Concatenate the last few bits provided here with those of the suffix */
unsigned short delimitedLastBytes = (unsigned short)((unsigned short)(lastByte & ((1 << (databitlen % 8)) - 1)) | ((unsigned short)instance->delimitedSuffix << (databitlen % 8)));
if ((delimitedLastBytes & 0xFF00) == 0x0000) {
instance->delimitedSuffix = delimitedLastBytes & 0xFF;
}
else {
unsigned char oneByte[1];
oneByte[0] = delimitedLastBytes & 0xFF;
ret = (HashReturn)KeccakWidth1600_SpongeAbsorb(&instance->sponge, oneByte, 1);
instance->delimitedSuffix = (delimitedLastBytes >> 8) & 0xFF;
}
}
return ret;
}
}

/* ---------------------------------------------------------------- */

HashReturn Keccak_HashFinal(Keccak_HashInstance *instance, BitSequence *hashval)
{
HashReturn ret = (HashReturn)KeccakWidth1600_SpongeAbsorbLastFewBits(&instance->sponge, instance->delimitedSuffix);
if (ret == KECCAK_SUCCESS)
return (HashReturn)KeccakWidth1600_SpongeSqueeze(&instance->sponge, hashval, instance->fixedOutputLength/8);
else
return ret;
}

/* ---------------------------------------------------------------- */

HashReturn Keccak_HashSqueeze(Keccak_HashInstance *instance, BitSequence *data, BitLength databitlen)
{
if ((databitlen % 8) != 0)
return KECCAK_FAIL;
return (HashReturn)KeccakWidth1600_SpongeSqueeze(&instance->sponge, data, databitlen/8);
}
125 changes: 125 additions & 0 deletions Sources/CXKCP/FIPS202-opt64/KeccakHash.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*
The eXtended Keccak Code Package (XKCP)
https://github.com/XKCP/XKCP

Keccak, designed by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche.

Implementation by the designers, hereby denoted as "the implementer".

For more information, feedback or questions, please refer to the Keccak Team website:
https://keccak.team/

To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/

#ifndef _KeccakHashInterface_h_
#define _KeccakHashInterface_h_

#include "config.h"
#ifdef XKCP_has_KeccakP1600

#include <stdint.h>
#include <string.h>
#include "KeccakSponge.h"

#ifndef _Keccak_BitTypes_
#define _Keccak_BitTypes_
typedef uint8_t BitSequence;

typedef size_t BitLength;
#endif

typedef enum { KECCAK_SUCCESS = 0, KECCAK_FAIL = 1, KECCAK_BAD_HASHLEN = 2 } HashReturn;

typedef struct {
KeccakWidth1600_SpongeInstance sponge;
unsigned int fixedOutputLength;
unsigned char delimitedSuffix;
} Keccak_HashInstance;

/**
* Function to initialize the Keccak[r, c] sponge function instance used in sequential hashing mode.
* @param hashInstance Pointer to the hash instance to be initialized.
* @param rate The value of the rate r.
* @param capacity The value of the capacity c.
* @param hashbitlen The desired number of output bits,
* or 0 for an arbitrarily-long output.
* @param delimitedSuffix Bits that will be automatically appended to the end
* of the input message, as in domain separation.
* This is a byte containing from 0 to 7 bits
* formatted like the @a delimitedData parameter of
* the Keccak_SpongeAbsorbLastFewBits() function.
* @pre One must have r+c=1600 and the rate a multiple of 8 bits in this implementation.
* @return KECCAK_SUCCESS if successful, KECCAK_FAIL otherwise.
*/
HashReturn Keccak_HashInitialize(Keccak_HashInstance *hashInstance, unsigned int rate, unsigned int capacity, unsigned int hashbitlen, unsigned char delimitedSuffix);

/** Macro to initialize a SHAKE128 instance as specified in the FIPS 202 standard.
*/
#define Keccak_HashInitialize_SHAKE128(hashInstance) Keccak_HashInitialize(hashInstance, 1344, 256, 0, 0x1F)

/** Macro to initialize a SHAKE256 instance as specified in the FIPS 202 standard.
*/
#define Keccak_HashInitialize_SHAKE256(hashInstance) Keccak_HashInitialize(hashInstance, 1088, 512, 0, 0x1F)

/** Macro to initialize a SHA3-224 instance as specified in the FIPS 202 standard.
*/
#define Keccak_HashInitialize_SHA3_224(hashInstance) Keccak_HashInitialize(hashInstance, 1152, 448, 224, 0x06)

/** Macro to initialize a SHA3-256 instance as specified in the FIPS 202 standard.
*/
#define Keccak_HashInitialize_SHA3_256(hashInstance) Keccak_HashInitialize(hashInstance, 1088, 512, 256, 0x06)

/** Macro to initialize a SHA3-384 instance as specified in the FIPS 202 standard.
*/
#define Keccak_HashInitialize_SHA3_384(hashInstance) Keccak_HashInitialize(hashInstance, 832, 768, 384, 0x06)

/** Macro to initialize a SHA3-512 instance as specified in the FIPS 202 standard.
*/
#define Keccak_HashInitialize_SHA3_512(hashInstance) Keccak_HashInitialize(hashInstance, 576, 1024, 512, 0x06)

/**
* Function to give input data to be absorbed.
* @param hashInstance Pointer to the hash instance initialized by Keccak_HashInitialize().
* @param data Pointer to the input data.
* When @a databitLen is not a multiple of 8, the last bits of data must be
* in the least significant bits of the last byte (little-endian convention).
* In this case, the (8 - @a databitLen mod 8) most significant bits
* of the last byte are ignored.
* @param databitLen The number of input bits provided in the input data.
* @pre In the previous call to Keccak_HashUpdate(), databitlen was a multiple of 8.
* @return KECCAK_SUCCESS if successful, KECCAK_FAIL otherwise.
*/
HashReturn Keccak_HashUpdate(Keccak_HashInstance *hashInstance, const BitSequence *data, BitLength databitlen);

/**
* Function to call after all input blocks have been input and to get
* output bits if the length was specified when calling Keccak_HashInitialize().
* @param hashInstance Pointer to the hash instance initialized by Keccak_HashInitialize().
* If @a hashbitlen was not 0 in the call to Keccak_HashInitialize(), the number of
* output bits is equal to @a hashbitlen.
* If @a hashbitlen was 0 in the call to Keccak_HashInitialize(), the output bits
* must be extracted using the Keccak_HashSqueeze() function.
* @param hashval Pointer to the buffer where to store the output data.
* @return KECCAK_SUCCESS if successful, KECCAK_FAIL otherwise.
*/
HashReturn Keccak_HashFinal(Keccak_HashInstance *hashInstance, BitSequence *hashval);

/**
* Function to squeeze output data.
* @param hashInstance Pointer to the hash instance initialized by Keccak_HashInitialize().
* @param data Pointer to the buffer where to store the output data.
* @param databitlen The number of output bits desired (must be a multiple of 8).
* @pre Keccak_HashFinal() must have been already called.
* @pre @a databitlen is a multiple of 8.
* @return KECCAK_SUCCESS if successful, KECCAK_FAIL otherwise.
*/
HashReturn Keccak_HashSqueeze(Keccak_HashInstance *hashInstance, BitSequence *data, BitLength databitlen);

#else
#error This requires an implementation of Keccak-p[1600]
#endif

#endif
Loading
Loading