Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
e9de693
Add an external mu variant of the ML-DSA API (65 and 87 variants)
fpseverino Jun 4, 2025
b5dde9c
Bring swift-crypto up to date with CryptoKit 2025 Beta 1 (#359)
Lukasa Jun 16, 2025
e09d149
Revert "Add an external mu variant of the ML-DSA API (65 and 87 varia…
fpseverino Jun 16, 2025
e25c941
Add an external mu variant of the ML-DSA API (65 and 87 variants)
fpseverino Jun 4, 2025
e016958
Revert "Add an external mu variant of the ML-DSA API (65 and 87 varia…
fpseverino Jun 16, 2025
2688efb
Merge branch 'mldsa-external-mu' of https://github.com/fpseverino/swi…
fpseverino Jun 16, 2025
74c97de
Add external mu variant of ML-DSA to BoringSSL implementation
fpseverino Jun 16, 2025
a6213d7
Add external mu API to wrapper with `package` level
fpseverino Jun 16, 2025
bc935ac
Expose external mu API in CryptoExtras
fpseverino Jun 16, 2025
f8ed3ee
Add tests for external mu variant
fpseverino Jun 16, 2025
64aa6ca
Small formatting fixes
fpseverino Jun 16, 2025
fdb09e2
Use computed variable to get BoringSSL implementation
fpseverino Jun 16, 2025
f8bb7ef
Add `@testable` back in tests
fpseverino Jun 16, 2025
8f06719
Make the linter happy
fpseverino Jun 16, 2025
67074c0
Update CMakeLists and use FoundationEssentials
fpseverino Jun 17, 2025
83a1500
Replace all Foundation imports with FoundationEssentials (#363)
Lukasa Jun 18, 2025
1eb3eec
Catch the WWDC-25 branch up to the tip of main (#365)
Lukasa Jun 18, 2025
2c12b1b
Merge branch 'wwdc-25' into mldsa-external-mu
fpseverino Jun 18, 2025
794dfa6
Update DocC
fpseverino Jun 19, 2025
8be1081
Perform another catch-up merge for the WWDC 2025 branch (#367)
Lukasa Jun 20, 2025
8e57f3e
Merge branch 'wwdc-25' into mldsa-external-mu
fpseverino Jun 20, 2025
9b06971
Adopt Swift 6 mode (#368)
Lukasa Jun 23, 2025
28350a9
Merge branch 'wwdc-25' into mldsa-external-mu
fpseverino Jun 23, 2025
63d96f1
Remove some warnings
fpseverino Jun 24, 2025
0434231
Format and remove warnings from MLKEM.swift
fpseverino Jun 24, 2025
66b1202
Remove `signature:` parameter label from `isValidSignature`
fpseverino Aug 6, 2025
d9f3641
[WWDC25] Add SHA-3 implementation backed by XKCP (#397)
simonjbeaumont Aug 11, 2025
478a430
Merge branch 'wwdc-25' into mldsa-external-mu
fpseverino Aug 18, 2025
890595d
Catch-up merge main into wwdc25 branch (#403)
Lukasa Sep 9, 2025
8ba4cb8
Merge branch 'wwdc-25' into mldsa-external-mu
fpseverino Sep 9, 2025
ea7f8fb
Update to RC SDK (#410)
Lukasa Sep 10, 2025
5247e53
Merge branch 'wwdc-25' into mldsa-external-mu
fpseverino Sep 10, 2025
d9638b0
Fix conflicts
fpseverino Sep 10, 2025
4a6a254
Remove unreleated stuff
fpseverino Sep 10, 2025
f9fa563
Fix conflicts
fpseverino Sep 10, 2025
1d62dfa
Move external mu methods to separate file
fpseverino Sep 12, 2025
47da0e2
Formatting
fpseverino Sep 12, 2025
3a8c300
Update CMakeLists.txt
fpseverino Sep 12, 2025
4e662b8
Rename _CryptoExtras Take 2 (#407)
0xTim Sep 15, 2025
d5fce84
Merge remote-tracking branch 'upstream/wwdc-25' into mldsa-external-mu
fpseverino Sep 15, 2025
46d7ce0
Move external mu files to new CryptoExtras module
fpseverino Sep 15, 2025
8ec37c7
Update `withUnsafeBytes` to `package` access level
fpseverino Sep 15, 2025
a34d9fb
Formatting
fpseverino Sep 15, 2025
2febca7
Update for macOS 26
fpseverino Sep 16, 2025
788c399
Make external mu work when `let development = false`
fpseverino Sep 16, 2025
981d583
Move MLDSA implementation to CryptoBoringWrapper
fpseverino Sep 16, 2025
97f7ce6
Update CMakeLists
fpseverino Sep 16, 2025
1d82983
Remove flag checks in CryptoBoringWrapper
fpseverino Sep 17, 2025
459adb9
Fix compiler guard for SHA-3 tests (#401)
simonjbeaumont Sep 22, 2025
e0883b4
Final catchup merge (#415)
Lukasa Sep 24, 2025
fc2e934
Merge branch 'wwdc-25' into mldsa-external-mu
fpseverino Sep 29, 2025
7bc3dcc
Merge branch 'main' into mldsa-external-mu
fpseverino Sep 29, 2025
6ebab68
Remove `MLDSA_boring.swift`
fpseverino Sep 29, 2025
d35c528
Merge branch 'main' into mldsa-external-mu
fpseverino Oct 8, 2025
ccde93d
Remove old `Optional+withUnsafeBytes`
fpseverino Oct 8, 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
8 changes: 5 additions & 3 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ let package = Package(
"Key Agreement/ECDH.swift.gyb",
"Signatures/ECDSA.swift.gyb",
"Signatures/MLDSA.swift.gyb",
"Signatures/BoringSSL/MLDSA_boring.swift.gyb",
"Signatures/BoringSSL/MLDSA+externalMu_boring.swift.gyb",
"KEM/MLKEM.swift.gyb",
"KEM/BoringSSL/MLKEM_boring.swift.gyb",
],
Expand All @@ -188,7 +188,8 @@ let package = Package(
.product(name: "SwiftASN1", package: "swift-asn1"),
],
exclude: privacyManifestExclude + [
"CMakeLists.txt"
"CMakeLists.txt",
"MLDSA/MLDSA+externalMu.swift.gyb",
],
resources: privacyManifestResource,
swiftSettings: swiftSettings
Expand All @@ -207,7 +208,8 @@ let package = Package(
"CCryptoBoringSSLShims",
],
exclude: privacyManifestExclude + [
"CMakeLists.txt"
"CMakeLists.txt",
"MLDSA/BoringSSLMLDSA.swift.gyb",
],
resources: privacyManifestResource
),
Expand Down
2 changes: 1 addition & 1 deletion Sources/Crypto/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ add_library(Crypto
"Signatures/BoringSSL/ECDSASignature_boring.swift"
"Signatures/BoringSSL/ECDSA_boring.swift"
"Signatures/BoringSSL/EdDSA_boring.swift"
"Signatures/BoringSSL/MLDSA_boring.swift"
"Signatures/BoringSSL/MLDSA+externalMu_boring.swift"
"Signatures/BoringSSL/MLDSA_wrapper.swift"
"Signatures/ECDSA.swift"
"Signatures/Ed25519.swift"
Expand Down
14 changes: 14 additions & 0 deletions Sources/Crypto/Docs.docc/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,25 @@ Swift Crypto is built on top of [BoringSSL](https://boringssl.googlesource.com/b
- ``P256``
- ``SharedSecret``
- ``HPKE``
- ``MLDSA65``
- ``MLDSA87``

### Key derivation functions

- ``HKDF``

### Key encapsulation mechanisms (KEM)

- ``KEM``
- ``MLKEM768``
- ``MLKEM1024``
- ``XWingMLKEM768X25519``

### KEM keys

- ``KEMPrivateKey``
- ``KEMPublicKey``

### Errors

- ``CryptoKitError``
Expand Down
145 changes: 145 additions & 0 deletions Sources/Crypto/Signatures/BoringSSL/MLDSA+externalMu_boring.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftCrypto open source project
//
// Copyright (c) 2025 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
//
//===----------------------------------------------------------------------===//

// MARK: - Generated file, do NOT edit
// any edits of this file WILL be overwritten and thus discarded
// see section `gyb` in `README` for details.

#if (!CRYPTO_IN_SWIFTPM) || CRYPTO_IN_SWIFTPM_FORCE_BUILD_API
#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif

@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *)
extension MLDSA65.PublicKey {
/// Generate a prehashed message representative (a.k.a. "external mu") for the given message.
///
/// - Parameter data: The message to prehash.
///
/// - Returns: The prehashed message representative (a.k.a. "external mu").
package func prehash_boring<D: DataProtocol>(for data: D) throws -> Data {
try self.boringSSLKey.prehash_boring(for: data)
}

/// Generate a prehashed message representative (a.k.a. "external mu") for the given message.
///
/// - Parameters:
/// - data: The message to prehash.
/// - context: The context of the message.
///
/// - Returns: The prehashed message representative (a.k.a. "external mu").
package func prehash_boring<D: DataProtocol, C: DataProtocol>(for data: D, context: C) throws -> Data {
try self.boringSSLKey.prehash_boring(for: data, context: context)
}

private var boringSSLKey: OpenSSLMLDSAPublicKeyImpl<MLDSA65> {
get throws {
#if (!CRYPTO_IN_SWIFTPM_FORCE_BUILD_API) || CRYPTOKIT_NO_ACCESS_TO_FOUNDATION
try OpenSSLMLDSAPublicKeyImpl<MLDSA65>(rawRepresentation: self.rawRepresentation)
#else
self.impl
#endif
}
}
}

@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *)
extension MLDSA65.PrivateKey {
/// Generate a signature for the prehashed message representative (a.k.a. "external mu").
///
/// > Note: The message representative should be obtained via calls to ``MLDSA87/PublicKey/prehash(for:context:)``.
///
/// - Parameter mu: The prehashed message representative (a.k.a. "external mu").
///
/// - Returns: The signature of the prehashed message representative.
package func signature_boring(forPrehashedMessageRepresentative mu: some DataProtocol) throws -> Data {
try self.boringSSLKey.signature_boring(forPrehashedMessageRepresentative: mu)
}

private var boringSSLKey: OpenSSLMLDSAPrivateKeyImpl<MLDSA65> {
get throws {
#if (!CRYPTO_IN_SWIFTPM_FORCE_BUILD_API) || CRYPTOKIT_NO_ACCESS_TO_FOUNDATION
try OpenSSLMLDSAPrivateKeyImpl<MLDSA65>(
seedRepresentation: self.seedRepresentation,
publicKey: nil
)
#else
self.impl
#endif
}
}
}

@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *)
extension MLDSA87.PublicKey {
/// Generate a prehashed message representative (a.k.a. "external mu") for the given message.
///
/// - Parameter data: The message to prehash.
///
/// - Returns: The prehashed message representative (a.k.a. "external mu").
package func prehash_boring<D: DataProtocol>(for data: D) throws -> Data {
try self.boringSSLKey.prehash_boring(for: data)
}

/// Generate a prehashed message representative (a.k.a. "external mu") for the given message.
///
/// - Parameters:
/// - data: The message to prehash.
/// - context: The context of the message.
///
/// - Returns: The prehashed message representative (a.k.a. "external mu").
package func prehash_boring<D: DataProtocol, C: DataProtocol>(for data: D, context: C) throws -> Data {
try self.boringSSLKey.prehash_boring(for: data, context: context)
}

private var boringSSLKey: OpenSSLMLDSAPublicKeyImpl<MLDSA87> {
get throws {
#if (!CRYPTO_IN_SWIFTPM_FORCE_BUILD_API) || CRYPTOKIT_NO_ACCESS_TO_FOUNDATION
try OpenSSLMLDSAPublicKeyImpl<MLDSA87>(rawRepresentation: self.rawRepresentation)
#else
self.impl
#endif
}
}
}

@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *)
extension MLDSA87.PrivateKey {
/// Generate a signature for the prehashed message representative (a.k.a. "external mu").
///
/// > Note: The message representative should be obtained via calls to ``MLDSA87/PublicKey/prehash(for:context:)``.
///
/// - Parameter mu: The prehashed message representative (a.k.a. "external mu").
///
/// - Returns: The signature of the prehashed message representative.
package func signature_boring(forPrehashedMessageRepresentative mu: some DataProtocol) throws -> Data {
try self.boringSSLKey.signature_boring(forPrehashedMessageRepresentative: mu)
}

private var boringSSLKey: OpenSSLMLDSAPrivateKeyImpl<MLDSA87> {
get throws {
#if (!CRYPTO_IN_SWIFTPM_FORCE_BUILD_API) || CRYPTOKIT_NO_ACCESS_TO_FOUNDATION
try OpenSSLMLDSAPrivateKeyImpl<MLDSA87>(
seedRepresentation: self.seedRepresentation,
publicKey: nil
)
#else
self.impl
#endif
}
}
}
#endif // Linux or !SwiftPM
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftCrypto open source project
//
// Copyright (c) 2025 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
//
//===----------------------------------------------------------------------===//

// MARK: - Generated file, do NOT edit
// any edits of this file WILL be overwritten and thus discarded
// see section `gyb` in `README` for details.

#if (!CRYPTO_IN_SWIFTPM) || CRYPTO_IN_SWIFTPM_FORCE_BUILD_API
#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif
%{
parameter_sets = ["65", "87"]
}%
% for parameter_set in parameter_sets:

@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *)
extension MLDSA${parameter_set}.PublicKey {
/// Generate a prehashed message representative (a.k.a. "external mu") for the given message.
///
/// - Parameter data: The message to prehash.
///
/// - Returns: The prehashed message representative (a.k.a. "external mu").
package func prehash_boring<D: DataProtocol>(for data: D) throws -> Data {
try self.boringSSLKey.prehash_boring(for: data)
}

/// Generate a prehashed message representative (a.k.a. "external mu") for the given message.
///
/// - Parameters:
/// - data: The message to prehash.
/// - context: The context of the message.
///
/// - Returns: The prehashed message representative (a.k.a. "external mu").
package func prehash_boring<D: DataProtocol, C: DataProtocol>(for data: D, context: C) throws -> Data {
try self.boringSSLKey.prehash_boring(for: data, context: context)
}

private var boringSSLKey: OpenSSLMLDSAPublicKeyImpl<MLDSA${parameter_set}> {
get throws {
#if (!CRYPTO_IN_SWIFTPM_FORCE_BUILD_API) || CRYPTOKIT_NO_ACCESS_TO_FOUNDATION
try OpenSSLMLDSAPublicKeyImpl<MLDSA${parameter_set}>(rawRepresentation: self.rawRepresentation)
#else
self.impl
#endif
}
}
}

@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *)
extension MLDSA${parameter_set}.PrivateKey {
/// Generate a signature for the prehashed message representative (a.k.a. "external mu").
///
/// > Note: The message representative should be obtained via calls to ``MLDSA87/PublicKey/prehash(for:context:)``.
///
/// - Parameter mu: The prehashed message representative (a.k.a. "external mu").
///
/// - Returns: The signature of the prehashed message representative.
package func signature_boring(forPrehashedMessageRepresentative mu: some DataProtocol) throws -> Data {
try self.boringSSLKey.signature_boring(forPrehashedMessageRepresentative: mu)
}

private var boringSSLKey: OpenSSLMLDSAPrivateKeyImpl<MLDSA${parameter_set}> {
get throws {
#if (!CRYPTO_IN_SWIFTPM_FORCE_BUILD_API) || CRYPTOKIT_NO_ACCESS_TO_FOUNDATION
try OpenSSLMLDSAPrivateKeyImpl<MLDSA${parameter_set}>(
seedRepresentation: self.seedRepresentation,
publicKey: nil
)
#else
self.impl
#endif
}
}
}
% end
#endif // Linux or !SwiftPM
37 changes: 28 additions & 9 deletions Sources/Crypto/Signatures/BoringSSL/MLDSA_wrapper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
@_exported import CryptoKit
#else
@_implementationOnly import CCryptoBoringSSL
import CryptoBoringWrapper
#if canImport(FoundationEssentials)
import FoundationEssentials
#else
Expand All @@ -34,6 +35,8 @@ protocol BoringSSLBackedMLDSAPrivateKey: Sendable {

func signature<D: DataProtocol, C: DataProtocol>(for data: D, context: C) throws -> Data

func signature(forPrehashedMessageRepresentative mu: some DataProtocol) throws -> Data

var publicKey: AssociatedPublicKey { get }

var seedRepresentation: Data { get }
Expand All @@ -48,6 +51,10 @@ protocol BoringSSLBackedMLDSAPublicKey: Sendable {
func isValidSignature<S: DataProtocol, D: DataProtocol, C: DataProtocol>(_: S, for data: D, context: C) -> Bool

var rawRepresentation: Data { get }

func prehash<D: DataProtocol>(for data: D) throws -> Data

func prehash<D: DataProtocol, C: DataProtocol>(for data: D, context: C) throws -> Data
}

@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *)
Expand All @@ -59,27 +66,27 @@ protocol BoringSSLBackedMLDSAParameters {

@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *)
extension MLDSA65: BoringSSLBackedMLDSAParameters {
typealias BackingPrivateKey = MLDSA65.InternalPrivateKey
typealias BackingPublicKey = MLDSA65.InternalPublicKey
typealias BackingPrivateKey = BoringSSLMLDSA65.InternalPrivateKey
typealias BackingPublicKey = BoringSSLMLDSA65.InternalPublicKey
}

@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *)
extension MLDSA87: BoringSSLBackedMLDSAParameters {
typealias BackingPrivateKey = MLDSA87.InternalPrivateKey
typealias BackingPublicKey = MLDSA87.InternalPublicKey
typealias BackingPrivateKey = BoringSSLMLDSA87.InternalPrivateKey
typealias BackingPublicKey = BoringSSLMLDSA87.InternalPublicKey
}

@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *)
extension MLDSA65.InternalPrivateKey: BoringSSLBackedMLDSAPrivateKey {}
extension BoringSSLMLDSA65.InternalPrivateKey: BoringSSLBackedMLDSAPrivateKey {}

@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *)
extension MLDSA65.InternalPublicKey: BoringSSLBackedMLDSAPublicKey {}
extension BoringSSLMLDSA65.InternalPublicKey: BoringSSLBackedMLDSAPublicKey {}

@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *)
extension MLDSA87.InternalPrivateKey: BoringSSLBackedMLDSAPrivateKey {}
extension BoringSSLMLDSA87.InternalPrivateKey: BoringSSLBackedMLDSAPrivateKey {}

@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *)
extension MLDSA87.InternalPublicKey: BoringSSLBackedMLDSAPublicKey {}
extension BoringSSLMLDSA87.InternalPublicKey: BoringSSLBackedMLDSAPublicKey {}

@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *)
struct OpenSSLMLDSAPrivateKeyImpl<Parameters: BoringSSLBackedMLDSAParameters> {
Expand Down Expand Up @@ -117,6 +124,10 @@ struct OpenSSLMLDSAPrivateKeyImpl<Parameters: BoringSSLBackedMLDSAParameters> {
try self.backing.signature(for: data, context: context)
}

func signature_boring(forPrehashedMessageRepresentative mu: some DataProtocol) throws -> Data {
try self.backing.signature(forPrehashedMessageRepresentative: mu)
}

var publicKey: OpenSSLMLDSAPublicKeyImpl<Parameters> {
.init(backing: self.backing.publicKey)
}
Expand All @@ -135,7 +146,7 @@ struct OpenSSLMLDSAPrivateKeyImpl<Parameters: BoringSSLBackedMLDSAParameters> {
}

static var seedSize: Int {
MLDSA.seedByteCount
BoringSSLMLDSA.seedByteCount
}
}

Expand Down Expand Up @@ -169,6 +180,14 @@ struct OpenSSLMLDSAPublicKeyImpl<Parameters: BoringSSLBackedMLDSAParameters> {
var rawRepresentation: Data {
self.backing.rawRepresentation
}

func prehash_boring<D: DataProtocol>(for data: D) throws -> Data {
try self.backing.prehash(for: data)
}

func prehash_boring<D: DataProtocol, C: DataProtocol>(for data: D, context: C) throws -> Data {
try self.backing.prehash(for: data, context: context)
}
}

#endif // CRYPTO_IN_SWIFTPM && !CRYPTO_IN_SWIFTPM_FORCE_BUILD_API
Loading