Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 11 additions & 0 deletions .swiftformatignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Sources/Crypto/Digests/Digest.swift
Sources/Crypto/Digests/Digests.swift
Sources/Crypto/Digests/HashFunctions.swift
Sources/Crypto/Digests/HashFunctions_SHA2.swift
Sources/Crypto/Digests/HashFunctions_SHA3.swift
Sources/Crypto/HPKE/Ciphersuite/HPKE-AEAD.swift
Sources/Crypto/HPKE/Ciphersuite/HPKE-Ciphersuite.swift
Sources/Crypto/HPKE/Ciphersuite/HPKE-KDF.swift
Expand All @@ -43,8 +44,12 @@ Sources/Crypto/HPKE/Modes/HPKE-Modes.swift
Sources/Crypto/Insecure/Insecure.swift
Sources/Crypto/Insecure/Insecure_HashFunctions.swift
Sources/Crypto/KEM/KEM.swift
Sources/Crypto/KEM/KEM-Errors.swift
Sources/Crypto/KEM/MLKEM.swift
Sources/Crypto/KEM/XWing.swift
Sources/Crypto/Key Agreement/DH.swift
Sources/Crypto/Key Agreement/ECDH.swift
Sources/Crypto/Key Derivation/ANSIx963.swift
Sources/Crypto/Key Derivation/HKDF.swift
Sources/Crypto/Key Wrapping/AESWrap.swift
Sources/Crypto/Keys/EC/Curve25519.swift
Expand All @@ -58,6 +63,7 @@ Sources/Crypto/Message Authentication Codes/MessageAuthenticationCode.swift
Sources/Crypto/PRF/AES.swift
Sources/Crypto/Signatures/ECDSA.swift
Sources/Crypto/Signatures/Ed25519.swift
Sources/Crypto/Signatures/MLDSA.swift
Sources/Crypto/Signatures/Signature.swift
Sources/Crypto/Util/PrettyBytes.swift
Sources/Crypto/Util/SafeCompare.swift
Expand Down Expand Up @@ -116,6 +122,9 @@ Tests/CryptoTests/Encodings/DERTests.swift
Tests/CryptoTests/Encodings/ECKeyEncodingsTests.swift
Tests/CryptoTests/HPKE/HPKETests-TestVectors.swift
Tests/CryptoTests/HPKE/HPKETests.swift
Tests/CryptoTests/KEM/MLKEMKeyGenTests.swift
Tests/CryptoTests/KEM/MLKEMTests.swift
Tests/CryptoTests/KEM/XWingTests.swift
Tests/CryptoTests/Key Derivation/ECprivateKeysFromSeeds.swift
Tests/CryptoTests/Key Derivation/HKDFTests.swift
Tests/CryptoTests/Key Derivation/SharedSecretTests.swift
Expand All @@ -126,6 +135,8 @@ Tests/CryptoTests/SecureBytes/SecureBytesTests.swift
Tests/CryptoTests/Signatures/ECDSA/ECDSASignatureTests.swift
Tests/CryptoTests/Signatures/ECDSA/RawECDSASignaturesTests.swift
Tests/CryptoTests/Signatures/EdDSA/Ed25519-Runner.swift
Tests/CryptoTests/Signatures/MLDSA/MLDSAKeyGenTests.swift
Tests/CryptoTests/Signatures/MLDSA/MLDSATests.swift
Tests/CryptoTests/Utils/PrettyBytes.swift
Tests/CryptoTests/Utils/RFCVector.swift
Tests/CryptoTests/Utils/SplitData.swift
Expand Down
9 changes: 8 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,14 @@ let package = Package(
name: "CryptoTests",
dependencies: ["Crypto"],
resources: [
.copy("HPKE/hpke-test-vectors.json")
.copy("HPKE/hpke-test-vectors.json"),
.copy("KEM/MLKEM768_BSSLKAT.json"),
.copy("KEM/MLKEM768KAT.json"),
.copy("KEM/MLKEM1024_BSSLKAT.json"),
.copy("KEM/MLKEM1024KAT.json"),
.copy("KEM/test-vectors.json"),
.copy("Signatures/MLDSA/MLDSA65_KeyGen_KAT.json"),
.copy("Signatures/MLDSA/MLDSA87_KeyGen_KAT.json"),
],
swiftSettings: swiftSettings
),
Expand Down
2 changes: 2 additions & 0 deletions Sources/CCryptoBoringSSL/include/CCryptoBoringSSL.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "CCryptoBoringSSL_cmac.h"
#include "CCryptoBoringSSL_conf.h"
#include "CCryptoBoringSSL_cpu.h"
#include "CCryptoBoringSSL_ctrdrbg.h"
#include "CCryptoBoringSSL_curve25519.h"
#include "CCryptoBoringSSL_des.h"
#include "CCryptoBoringSSL_e_os2.h"
Expand Down Expand Up @@ -62,5 +63,6 @@
#include "CCryptoBoringSSL_siphash.h"
#include "CCryptoBoringSSL_trust_token.h"
#include "CCryptoBoringSSL_x509v3.h"
#include "CCryptoBoringSSL_xwing.h"

#endif // C_CRYPTO_BORINGSSL_H
35 changes: 21 additions & 14 deletions Sources/Crypto/AEADs/AES/GCM/AES-GCM.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,26 @@
#if CRYPTO_IN_SWIFTPM && !CRYPTO_IN_SWIFTPM_FORCE_BUILD_API
@_exported import CryptoKit
#else
#if !CRYPTO_IN_SWIFTPM_FORCE_BUILD_API
#if (!CRYPTO_IN_SWIFTPM_FORCE_BUILD_API) || CRYPTOKIT_NO_ACCESS_TO_FOUNDATION
@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *)
typealias AESGCMImpl = CoreCryptoGCMImpl
import Security
#else
@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *)
typealias AESGCMImpl = OpenSSLAESGCMImpl
#endif

import Foundation
#if CRYPTOKIT_NO_ACCESS_TO_FOUNDATION
public import SwiftSystem
#else
public import Foundation
#endif

@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *)
extension AES {
/// The Advanced Encryption Standard (AES) Galois Counter Mode (GCM) cipher
/// suite.
@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *)
public enum GCM: Cipher {
public enum GCM: Cipher, Sendable {
static let tagByteCount = 16
static let defaultNonceByteCount = 12

Expand All @@ -41,12 +44,12 @@ extension AES {
/// - Parameters:
/// - message: The plaintext data to seal.
/// - key: A cryptographic key used to seal the message.
/// - nonce: The nonce the sealing process requires. If you don't provide a nonce, the method generates a random one by invoking ``AES.GCM.Nonce()``.
/// - nonce: The nonce the sealing process requires. If you don't provide a nonce, the method generates a random one by invoking ``AES/GCM/Nonce/init()``.
/// - authenticatedData: Additional data to be authenticated.
///
/// - Returns: The sealed message.
public static func seal<Plaintext: DataProtocol, AuthenticatedData: DataProtocol>
(_ message: Plaintext, using key: SymmetricKey, nonce: Nonce? = nil, authenticating authenticatedData: AuthenticatedData) throws -> SealedBox {
(_ message: Plaintext, using key: SymmetricKey, nonce: Nonce? = nil, authenticating authenticatedData: AuthenticatedData) throws(CryptoKitMetaError) -> SealedBox {
return try AESGCMImpl.seal(key: key, message: message, nonce: nonce, authenticatedData: authenticatedData)
}

Expand All @@ -56,11 +59,11 @@ extension AES {
/// - Parameters:
/// - message: The plaintext data to seal.
/// - key: A cryptographic key used to seal the message.
/// - nonce: The nonce the sealing process requires. If you don't provide a nonce, the method generates a random one by invoking ``AES.GCM.Nonce()``.
/// - nonce: The nonce the sealing process requires. If you don't provide a nonce, the method generates a random one by invoking ``AES/GCM/Nonce/init()``.
///
/// - Returns: The sealed message.
public static func seal<Plaintext: DataProtocol>
(_ message: Plaintext, using key: SymmetricKey, nonce: Nonce? = nil) throws -> SealedBox {
(_ message: Plaintext, using key: SymmetricKey, nonce: Nonce? = nil) throws(CryptoKitMetaError) -> SealedBox {
return try AESGCMImpl.seal(key: key, message: message, nonce: nonce, authenticatedData: Data?.none)
}

Expand All @@ -76,7 +79,7 @@ extension AES {
/// box, as long as the correct key is used and authentication succeeds.
/// The call throws an error if decryption or authentication fail.
public static func open<AuthenticatedData: DataProtocol>
(_ sealedBox: SealedBox, using key: SymmetricKey, authenticating authenticatedData: AuthenticatedData) throws -> Data {
(_ sealedBox: SealedBox, using key: SymmetricKey, authenticating authenticatedData: AuthenticatedData) throws(CryptoKitMetaError) -> Data {
return try AESGCMImpl.open(key: key, sealedBox: sealedBox, authenticatedData: authenticatedData)
}

Expand All @@ -89,7 +92,7 @@ extension AES {
/// - Returns: The original plaintext message that was sealed in the
/// box, as long as the correct key is used and authentication succeeds.
/// The call throws an error if decryption or authentication fail.
public static func open(_ sealedBox: SealedBox, using key: SymmetricKey) throws -> Data {
public static func open(_ sealedBox: SealedBox, using key: SymmetricKey) throws(CryptoKitMetaError) -> Data {
return try AESGCMImpl.open(key: key, sealedBox: sealedBox, authenticatedData: Data?.none)
}
}
Expand All @@ -112,7 +115,7 @@ extension AES.GCM {
/// The receiver uses another instance of the same cipher, like the
/// ``open(_:using:)`` method, to open the box.
@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *)
public struct SealedBox: AEADSealedBox {
public struct SealedBox: AEADSealedBox, Sendable {
private let combinedRepresentation: Data
private let nonceByteCount: Int

Expand Down Expand Up @@ -167,13 +170,17 @@ extension AES.GCM {
/// - combined: The combined bytes of the nonce, encrypted data, and
/// authentication tag.
@inlinable
public init<D: DataProtocol>(combined: D) throws {
public init<D: DataProtocol>(combined: D) throws(CryptoKitMetaError) {
// AES minimum nonce (12 bytes) + AES tag (16 bytes)
// While we have these values in the internal APIs, we can't use it in inlinable code.
let aesGCMOverhead = 12 + 16

if combined.count < aesGCMOverhead {
#if hasFeature(Embedded)
throw CryptoKitMetaError.cryptoKitError(underlyingError: CryptoKitError.incorrectParameterSize)
#else
throw CryptoKitError.incorrectParameterSize
#endif
}

self.init(combined: Data(combined))
Expand All @@ -185,9 +192,9 @@ extension AES.GCM {
/// - nonce: The nonce.
/// - ciphertext: The encrypted data.
/// - tag: The authentication tag.
public init<C: DataProtocol, T: DataProtocol>(nonce: AES.GCM.Nonce, ciphertext: C, tag: T) throws {
public init<C: DataProtocol, T: DataProtocol>(nonce: AES.GCM.Nonce, ciphertext: C, tag: T) throws(CryptoKitMetaError) {
guard tag.count == AES.GCM.tagByteCount else {
throw CryptoKitError.incorrectParameterSize
throw error(CryptoKitError.incorrectParameterSize)
}

let nonceByteCount = nonce.bytes.count
Expand Down
18 changes: 11 additions & 7 deletions Sources/Crypto/AEADs/ChachaPoly/ChaChaPoly.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,24 @@
#if CRYPTO_IN_SWIFTPM && !CRYPTO_IN_SWIFTPM_FORCE_BUILD_API
@_exported import CryptoKit
#else
#if !CRYPTO_IN_SWIFTPM_FORCE_BUILD_API
#if (!CRYPTO_IN_SWIFTPM_FORCE_BUILD_API) || CRYPTOKIT_NO_ACCESS_TO_FOUNDATION
@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *)
typealias ChaChaPolyImpl = CoreCryptoChaChaPolyImpl
import Security
#else
@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *)
typealias ChaChaPolyImpl = OpenSSLChaChaPolyImpl
#endif

import Foundation
#if CRYPTOKIT_NO_ACCESS_TO_FOUNDATION
public import SwiftSystem
#else
public import Foundation
#endif


/// An implementation of the ChaCha20-Poly1305 cipher.
@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *)
public enum ChaChaPoly: Cipher {
public enum ChaChaPoly: Cipher, Sendable {
static let tagByteCount = 16
static let keyBitsCount = 256
static let nonceByteCount = 12
Expand All @@ -39,7 +43,7 @@ public enum ChaChaPoly: Cipher {
/// - Parameters:
/// - message: The plaintext data to seal.
/// - key: A cryptographic key used to seal the message.
/// - nonce: The nonce the sealing process requires. If you don't provide a nonce, the method generates a random one by invoking ``ChaChaPoly.Nonce()``.
/// - nonce: The nonce the sealing process requires. If you don't provide a nonce, the method generates a random one by invoking ``ChaChaPoly/Nonce/init()``.
/// - authenticatedData: Additional data to be authenticated.
///
/// - Returns: The sealed message.
Expand All @@ -54,7 +58,7 @@ public enum ChaChaPoly: Cipher {
/// - Parameters:
/// - message: The plaintext data to seal.
/// - key: A cryptographic key used to seal the message.
/// - nonce: The nonce the sealing process requires. If you don't provide a nonce, the method generates a random one by invoking ``ChaChaPoly.Nonce()``.
/// - nonce: The nonce the sealing process requires. If you don't provide a nonce, the method generates a random one by invoking ``ChaChaPoly/Nonce/init()``.
///
/// - Returns: The sealed message.
public static func seal<Plaintext: DataProtocol>
Expand Down Expand Up @@ -111,7 +115,7 @@ extension ChaChaPoly {
/// ``open(_:using:)`` method, to open the box.
@frozen
@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *)
public struct SealedBox: AEADSealedBox {
public struct SealedBox: AEADSealedBox, Sendable {
/// A combined element composed of the tag, the nonce, and the
/// ciphertext.
///
Expand Down
12 changes: 9 additions & 3 deletions Sources/Crypto/AEADs/Cipher.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,16 @@
#if CRYPTO_IN_SWIFTPM && !CRYPTO_IN_SWIFTPM_FORCE_BUILD_API
@_exported import CryptoKit
#else

#if CRYPTOKIT_NO_ACCESS_TO_FOUNDATION
import SwiftSystem
#else
import Foundation
#endif


@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *)
protocol AEADSealedBox {
protocol AEADSealedBox: Sendable {
associatedtype Nonce: Sequence
/// The authentication tag
var tag: Data { get }
Expand Down Expand Up @@ -52,7 +58,7 @@ protocol Cipher {
/// - Returns: The sealed box containing the ciphertext and authentication tag
/// - Throws: An error occurred while encrypting or authenticating.
static func seal<Plaintext: DataProtocol, AuthenticatedData: DataProtocol>
(_ message: Plaintext, using key: SymmetricKey, nonce: Nonce?, authenticating: AuthenticatedData) throws -> SealedBox
(_ message: Plaintext, using key: SymmetricKey, nonce: Nonce?, authenticating: AuthenticatedData) throws(CryptoKitMetaError) -> SealedBox

/// Opens the sealed box. This decrypts and verifies the authenticity of the message,
/// and optionally verifies the authenticity of the authenticated data.
Expand All @@ -65,6 +71,6 @@ protocol Cipher {
/// - Returns: Returns the data, if the correct key is used and the authenticated data matches the one from the seal operation.
/// - Throws: An error occurred while decrypting or authenticating.
static func open<AuthenticatedData: DataProtocol>
(_ sealedBox: SealedBox, using key: Key, authenticating: AuthenticatedData) throws -> Data
(_ sealedBox: SealedBox, using key: Key, authenticating: AuthenticatedData) throws(CryptoKitMetaError) -> Data
}
#endif
45 changes: 32 additions & 13 deletions Sources/Crypto/AEADs/Nonces.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,18 @@
#if CRYPTO_IN_SWIFTPM && !CRYPTO_IN_SWIFTPM_FORCE_BUILD_API
@_exported import CryptoKit
#else
import Foundation
#if CRYPTOKIT_NO_ACCESS_TO_FOUNDATION
public import SwiftSystem
#else
public import Foundation
#endif
// MARK: - Generated file, do NOT edit
// any edits of this file WILL be overwritten and thus discarded
// see section `gyb` in `README` for details.




// MARK: - AES.GCM + Nonce
@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *)
extension AES.GCM {
Expand All @@ -28,7 +35,7 @@ extension AES.GCM {
/// that nonces are unique per call to encryption APIs in order to protect the
/// integrity of the encryption.
@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *)
public struct Nonce: ContiguousBytes, Sequence {
public struct Nonce: ContiguousBytes, Sequence, Sendable {
let bytes: Data

/// Creates a new random nonce.
Expand All @@ -49,11 +56,11 @@ extension AES.GCM {
/// ``init()`` method to instead create a random nonce.
///
/// - Parameters:
/// - data: A 12-byte data representation of the nonce. The initializer throws an
/// error if the data has a length other than 12 bytes.
public init<D: DataProtocol>(data: D) throws {
/// - data: A data representation of the nonce.
/// The initializer throws an error if the data has a length smaller than 12 bytes.
public init<D: DataProtocol>(data: D) throws(CryptoKitMetaError) {
if data.count < AES.GCM.defaultNonceByteCount {
throw CryptoKitError.incorrectParameterSize
throw error(CryptoKitError.incorrectParameterSize)
}

self.bytes = Data(data)
Expand All @@ -70,10 +77,16 @@ extension AES.GCM {
/// the duration of the closure’s execution.
///
/// - Returns: The return value, if any, of the body closure parameter.
#if !hasFeature(Embedded)
public func withUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R {
return try self.bytes.withUnsafeBytes(body)
}

#else
public func withUnsafeBytes<R, E: Error>(_ body: (UnsafeRawBufferPointer) throws(E) -> R) throws(E) -> R {
return try self.bytes.withUnsafeBytes(body)
}
#endif

/// Returns an iterator over the elements of the nonce.
public func makeIterator() -> Array<UInt8>.Iterator {
self.withUnsafeBytes({ (buffPtr) in
Expand All @@ -92,7 +105,7 @@ extension ChaChaPoly {
/// that nonces are unique per call to encryption APIs in order to protect the
/// integrity of the encryption.
@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *)
public struct Nonce: ContiguousBytes, Sequence {
public struct Nonce: ContiguousBytes, Sequence, Sendable {
let bytes: Data

/// Creates a new random nonce.
Expand All @@ -113,11 +126,11 @@ extension ChaChaPoly {
/// ``init()`` method to instead create a random nonce.
///
/// - Parameters:
/// - data: A 12-byte data representation of the nonce. The initializer throws an
/// error if the data has a length other than 12 bytes.
public init<D: DataProtocol>(data: D) throws {
/// - data: A 12-byte data representation of the nonce.
/// The initializer throws an error if the data isn't 12 bytes long.
public init<D: DataProtocol>(data: D) throws(CryptoKitMetaError) {
if data.count != ChaChaPoly.nonceByteCount {
throw CryptoKitError.incorrectParameterSize
throw error(CryptoKitError.incorrectParameterSize)
}

self.bytes = Data(data)
Expand All @@ -134,10 +147,16 @@ extension ChaChaPoly {
/// the duration of the closure’s execution.
///
/// - Returns: The return value, if any, of the body closure parameter.
#if !hasFeature(Embedded)
public func withUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R {
return try self.bytes.withUnsafeBytes(body)
}

#else
public func withUnsafeBytes<R, E: Error>(_ body: (UnsafeRawBufferPointer) throws(E) -> R) throws(E) -> R {
return try self.bytes.withUnsafeBytes(body)
}
#endif

/// Returns an iterator over the elements of the nonce.
public func makeIterator() -> Array<UInt8>.Iterator {
self.withUnsafeBytes({ (buffPtr) in
Expand Down
Loading
Loading