Skip to content
Open
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
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ let package = Package(
],
dependencies: [
.package(url: "https://github.com/apple/swift-nio.git", from: "2.81.0"),
.package(url: "https://github.com/apple/swift-crypto.git", from: "3.0.0"),
.package(url: "https://github.com/apple/swift-crypto.git", from: "4.0.0"),
],
targets: [
.target(
Expand Down
10 changes: 5 additions & 5 deletions Sources/ObliviousDoH/ODoHRoutine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ public enum ODoH: Sendable {
/// Initialized with a configuration containing the target's public key and algorithm parameters.
internal struct RoutineCore: Sendable {
internal var ct: HPKE.Ciphersuite
internal var pkR: any HPKEDiffieHellmanPublicKey
internal var pkData: Data
internal var keyID: Data

/// Initialize ODoH encryption with target server configuration.
Expand All @@ -111,7 +111,7 @@ public enum ODoH: Sendable {
kdf: configuration.contents.kdf,
aead: configuration.contents.aead
)
self.pkR = try self.ct.kem.getPublicKey(data: configuration.contents.publicKey)
self.pkData = configuration.contents.publicKey
self.keyID = configuration.contents.identifier
}

Expand Down Expand Up @@ -201,8 +201,8 @@ public enum ODoH: Sendable {
public func encryptQuery(
queryPlain: MessagePlaintext
) throws -> QueryEncryptionResult {
var context = try HPKE.Sender(
recipientKey: self.core.pkR,
var context = try self.core.ct.kem.getSender(
publicKeyData: self.core.pkData,
ciphersuite: self.core.ct,
info: Data.oDoHQueryInfo
)
Expand Down Expand Up @@ -1034,7 +1034,7 @@ extension ODoH.ConfigurationContents: ODoH.Encodable {

// Try to validate the public key by attempting to create a key instance
do {
_ = try kem.getPublicKey(data: key)
_ = try kem.validateKey(publicKeyData: key)
} catch {
return .failure(.invalidPublicKey(kemID: kemID, key: key))
}
Expand Down
72 changes: 67 additions & 5 deletions Sources/ObliviousXHelpers/Helpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,11 @@ extension UInt16 {
self = 0x0012
case .Curve25519_HKDF_SHA256:
self = 0x0020
#if !canImport(Darwin) || canImport(CryptoKit, _version: 324.0.4)
case .XWingMLKEM768X25519:
// https://datatracker.ietf.org/doc/html/draft-connolly-cfrg-xwing-kem-06#name-iana-considerations
self = 0x647a
#endif
#if canImport(CryptoKit)
@unknown default:
fatalError("Unsupported KEM")
Expand Down Expand Up @@ -188,23 +193,80 @@ extension HPKE.KEM {
return 133
case .Curve25519_HKDF_SHA256:
return 32
#if !canImport(Darwin) || canImport(CryptoKit, _version: 324.0.4)
case .XWingMLKEM768X25519:
return 1120
#endif
#if canImport(CryptoKit)
@unknown default:
fatalError("Unsupported KEM")
#endif
}
}

package func getPublicKey(data: Data) throws -> any HPKEDiffieHellmanPublicKey {
package func getSender(publicKeyData: Data, ciphersuite: HPKE.Ciphersuite, info: Data) throws -> HPKE.Sender {
switch self {
case .P256_HKDF_SHA256:
return try P256.KeyAgreement.PublicKey(rawRepresentation: data)
return try HPKE.Sender(
recipientKey: P256.KeyAgreement.PublicKey(rawRepresentation: publicKeyData),
ciphersuite: ciphersuite,
info: info
)
case .P384_HKDF_SHA384:
return try P384.KeyAgreement.PublicKey(rawRepresentation: data)
return try HPKE.Sender(
recipientKey: P384.KeyAgreement.PublicKey(rawRepresentation: publicKeyData),
ciphersuite: ciphersuite,
info: info
)
case .P521_HKDF_SHA512:
return try P521.KeyAgreement.PublicKey(rawRepresentation: data)
return try HPKE.Sender(
recipientKey: P521.KeyAgreement.PublicKey(rawRepresentation: publicKeyData),
ciphersuite: ciphersuite,
info: info
)
case .Curve25519_HKDF_SHA256:
return try Curve25519.KeyAgreement.PublicKey(rawRepresentation: data)
return try HPKE.Sender(
recipientKey: Curve25519.KeyAgreement.PublicKey(rawRepresentation: publicKeyData),
ciphersuite: ciphersuite,
info: info
)
#if !canImport(Darwin) || canImport(CryptoKit, _version: 324.0.4)
case .XWingMLKEM768X25519:
if #available(iOS 26.0, macOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) {
return try HPKE.Sender(
recipientKey: Crypto.XWingMLKEM768X25519.PublicKey(rawRepresentation: publicKeyData),
ciphersuite: ciphersuite,
info: info
)
} else {
fatalError("Impossible to have an XWing key in this context without it being available.")
}
#endif
#if canImport(CryptoKit)
@unknown default:
fatalError("Unsupported KEM")
#endif
}
}

package func validateKey(publicKeyData: Data) throws {
switch self {
case .P256_HKDF_SHA256:
_ = try P256.KeyAgreement.PublicKey(rawRepresentation: publicKeyData)
case .P384_HKDF_SHA384:
_ = try P384.KeyAgreement.PublicKey(rawRepresentation: publicKeyData)
case .P521_HKDF_SHA512:
_ = try P521.KeyAgreement.PublicKey(rawRepresentation: publicKeyData)
case .Curve25519_HKDF_SHA256:
_ = try Curve25519.KeyAgreement.PublicKey(rawRepresentation: publicKeyData)
#if !canImport(Darwin) || canImport(CryptoKit, _version: 324.0.4)
case .XWingMLKEM768X25519:
if #available(iOS 26.0, macOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) {
_ = try Crypto.XWingMLKEM768X25519.PublicKey(rawRepresentation: publicKeyData)
} else {
fatalError("Impossible to have an XWing key in this context without it being available.")
}
#endif
#if canImport(CryptoKit)
@unknown default:
fatalError("Unsupported KEM")
Expand Down
Loading