Skip to content

Commit

Permalink
Merge branch 'main' of github.com:OperatorFoundation/ShadowSwift
Browse files Browse the repository at this point in the history
  • Loading branch information
Dr. Brandon Wiley committed Feb 2, 2022
2 parents 3ab8bec + 8ffdd0a commit de25d4a
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 4 deletions.
63 changes: 62 additions & 1 deletion Sources/ShadowSwift/DarkStar.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public struct DarkStar
return Data(array: dataArray)
}

#if os(macOS)
static public func generateServerConfirmationCode(theirPublicKey: P256.KeyAgreement.PublicKey, myPrivateEphemeralKey: SecureEnclave.P256.KeyAgreement.PrivateKey, myPrivateStaticKey: SecureEnclave.P256.KeyAgreement.PrivateKey, endpoint: NWEndpoint) -> Data?
{
guard let ecdh = try? myPrivateStaticKey.sharedSecretFromKeyAgreement(with: theirPublicKey) else {return nil}
Expand All @@ -58,7 +59,30 @@ public struct DarkStar

return Data(result)
}
#else
static public func generateServerConfirmationCode(theirPublicKey: P256.KeyAgreement.PublicKey, myPrivateEphemeralKey: P256.KeyAgreement.PrivateKey, myPrivateStaticKey: P256.KeyAgreement.PrivateKey, endpoint: NWEndpoint) -> Data?
{
guard let ecdh = try? myPrivateStaticKey.sharedSecretFromKeyAgreement(with: theirPublicKey) else {return nil}
let ecdhData = DarkStar.sharedSecretToData(secret: ecdh)

guard let serverIdentifier = DarkStar.makeServerIdentifier(endpoint) else {return nil}
let serverPersistentPublicKeyData = myPrivateStaticKey.publicKey.compactRepresentation!
let clientEphemeralPublicKeyData = theirPublicKey.compactRepresentation!

var hash = SHA256()
hash.update(data: ecdhData)
hash.update(data: serverIdentifier)
hash.update(data: serverPersistentPublicKeyData)
hash.update(data: clientEphemeralPublicKeyData)
hash.update(data: DarkStarString.data)
hash.update(data: ServerString.data)
let result = hash.finalize()

return Data(result)
}
#endif


static public func handleServerEphemeralKey(connection: Connection) -> (P256.KeyAgreement.PrivateKey, P256.KeyAgreement.PublicKey)?
{
let myEphemeralPrivateKey = P256.KeyAgreement.PrivateKey()
Expand All @@ -70,6 +94,7 @@ public struct DarkStar
return (myEphemeralPrivateKey, myEphemeralPublicKey)
}

#if os(macOS)
static public func handleClientEphemeralKey(connection: Connection) -> (SecureEnclave.P256.KeyAgreement.PrivateKey, P256.KeyAgreement.PublicKey)?
{
guard let myEphemeralPrivateKey = try? SecureEnclave.P256.KeyAgreement.PrivateKey() else {return nil}
Expand All @@ -80,7 +105,7 @@ public struct DarkStar

return (myEphemeralPrivateKey, myEphemeralPublicKey)
}

static public func generateClientConfirmationCode(connection: Connection, theirPublicKey: P256.KeyAgreement.PublicKey, myPrivateKey: SecureEnclave.P256.KeyAgreement.PrivateKey, endpoint: NWEndpoint, serverPersistentPublicKey: P256.KeyAgreement.PublicKey, clientEphemeralPublicKey: P256.KeyAgreement.PublicKey) -> Data?
{
guard let ecdh = try? myPrivateKey.sharedSecretFromKeyAgreement(with: theirPublicKey) else {return nil}
Expand All @@ -101,6 +126,42 @@ public struct DarkStar

return Data(result)
}

#else
static public func handleClientEphemeralKey(connection: Connection) -> (P256.KeyAgreement.PrivateKey, P256.KeyAgreement.PublicKey)?
{
guard let myEphemeralPrivateKey = try? P256.KeyAgreement.PrivateKey() else {return nil}
let myEphemeralPublicKey = myEphemeralPrivateKey.publicKey
let myEphemeralPublicKeyData = myEphemeralPublicKey.compactRepresentation!

guard connection.write(data: myEphemeralPublicKeyData) else {return nil}

return (myEphemeralPrivateKey, myEphemeralPublicKey)
}

static public func generateClientConfirmationCode(connection: Connection, theirPublicKey: P256.KeyAgreement.PublicKey, myPrivateKey: P256.KeyAgreement.PrivateKey, endpoint: NWEndpoint, serverPersistentPublicKey: P256.KeyAgreement.PublicKey, clientEphemeralPublicKey: P256.KeyAgreement.PublicKey) -> Data?
{
guard let ecdh = try? myPrivateKey.sharedSecretFromKeyAgreement(with: theirPublicKey) else {return nil}
let ecdhData = DarkStar.sharedSecretToData(secret: ecdh)

guard let serverIdentifier = DarkStar.makeServerIdentifier(endpoint) else {return nil}
let serverPersistentPublicKeyData = serverPersistentPublicKey.compactRepresentation!
let clientEphemeralPublicKeyData = clientEphemeralPublicKey.compactRepresentation!

var hash = SHA256()
hash.update(data: ecdhData)
hash.update(data: serverIdentifier)
hash.update(data: serverPersistentPublicKeyData)
hash.update(data: clientEphemeralPublicKeyData)
hash.update(data: DarkStarString.data)
hash.update(data: ClientString.data)
let result = hash.finalize()

return Data(result)
}
#endif



static public func handleTheirEphemeralPublicKey(connection: Connection) -> P256.KeyAgreement.PublicKey?
{
Expand Down
2 changes: 1 addition & 1 deletion Sources/ShadowSwift/DarkStarCipher.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import Logging

import Crypto
import Datable
import Network
import Net

class DarkStarCipher
{
Expand Down
79 changes: 78 additions & 1 deletion Sources/ShadowSwift/DarkStarClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public class DarkStarClient
let clientToServerSharedKey: SymmetricKey
let serverToClientSharedKey: SymmetricKey

#if os(macOS)
static public func handleServerConfirmationCode(connection: Connection, endpoint: NWEndpoint, serverStaticPublicKey: P256.KeyAgreement.PublicKey, clientEphemeralPrivateKey: SecureEnclave.P256.KeyAgreement.PrivateKey) -> Bool
{
let data = connection.read(size: P256KeySize)
Expand All @@ -41,7 +42,7 @@ public class DarkStarClient

return data == code
}

static public func handleClientConfirmationCode(connection: Connection, theirPublicKey: P256.KeyAgreement.PublicKey, myPrivateKey: SecureEnclave.P256.KeyAgreement.PrivateKey, endpoint: NWEndpoint, serverPersistentPublicKey: P256.KeyAgreement.PublicKey, clientEphemeralPublicKey: P256.KeyAgreement.PublicKey) -> Bool
{
guard let data = DarkStar.generateClientConfirmationCode(connection: connection, theirPublicKey: theirPublicKey, myPrivateKey: myPrivateKey, endpoint: endpoint, serverPersistentPublicKey: serverPersistentPublicKey, clientEphemeralPublicKey: clientEphemeralPublicKey) else {return false}
Expand Down Expand Up @@ -90,6 +91,82 @@ public class DarkStarClient
let hashedData = Data(hashed)
return SymmetricKey(data: hashedData)
}

#else // SecureEnclave is only available on Apple devices
static public func handleServerConfirmationCode(connection: Connection, endpoint: NWEndpoint, serverStaticPublicKey: P256.KeyAgreement.PublicKey, clientEphemeralPrivateKey: P256.KeyAgreement.PrivateKey) -> Bool
{
let data = connection.read(size: P256KeySize)

guard let ecdh = try? clientEphemeralPrivateKey.sharedSecretFromKeyAgreement(with: serverStaticPublicKey) else {return false}
let ecdhData = DarkStar.sharedSecretToData(secret: ecdh)

guard let serverIdentifier = DarkStar.makeServerIdentifier(endpoint) else {return false}
let clientEphemeralPublicKeyData = clientEphemeralPrivateKey.publicKey.compactRepresentation!
let serverStaticPublicKeyData = serverStaticPublicKey.compactRepresentation!

var hash = SHA256()
hash.update(data: ecdhData)
hash.update(data: serverIdentifier)
hash.update(data: serverStaticPublicKeyData)
hash.update(data: clientEphemeralPublicKeyData)
hash.update(data: DarkStarString.data)
hash.update(data: ServerString.data)
let result = hash.finalize()

let code = Data(result)

return data == code
}

static public func handleClientConfirmationCode(connection: Connection, theirPublicKey: P256.KeyAgreement.PublicKey, myPrivateKey: P256.KeyAgreement.PrivateKey, endpoint: NWEndpoint, serverPersistentPublicKey: P256.KeyAgreement.PublicKey, clientEphemeralPublicKey: P256.KeyAgreement.PublicKey) -> Bool
{
guard let data = DarkStar.generateClientConfirmationCode(connection: connection, theirPublicKey: theirPublicKey, myPrivateKey: myPrivateKey, endpoint: endpoint, serverPersistentPublicKey: serverPersistentPublicKey, clientEphemeralPublicKey: clientEphemeralPublicKey) else {return false}

return connection.write(data: data)
}

static public func createClientToServerSharedKey(clientEphemeralPrivateKey: P256.KeyAgreement.PrivateKey, serverEphemeralPublicKey: P256.KeyAgreement.PublicKey, serverPersistentPublicKey: P256.KeyAgreement.PublicKey, serverEndpoint: NWEndpoint) -> SymmetricKey?
{
createClientSharedKey(clientEphemeralPrivateKey: clientEphemeralPrivateKey, serverEphemeralPublicKey: serverEphemeralPublicKey, serverPersistentPublicKey: serverPersistentPublicKey, serverEndpoint: serverEndpoint, personalizationString: ServerString)
}

static public func createServerToClientSharedKey(clientEphemeralPrivateKey: P256.KeyAgreement.PrivateKey, serverEphemeralPublicKey: P256.KeyAgreement.PublicKey, serverPersistentPublicKey: P256.KeyAgreement.PublicKey, serverEndpoint: NWEndpoint) -> SymmetricKey?
{
createClientSharedKey(clientEphemeralPrivateKey: clientEphemeralPrivateKey, serverEphemeralPublicKey: serverEphemeralPublicKey, serverPersistentPublicKey: serverPersistentPublicKey, serverEndpoint: serverEndpoint, personalizationString: ClientString)
}

static func createClientSharedKey(clientEphemeralPrivateKey: P256.KeyAgreement.PrivateKey, serverEphemeralPublicKey: P256.KeyAgreement.PublicKey, serverPersistentPublicKey: P256.KeyAgreement.PublicKey, serverEndpoint: NWEndpoint, personalizationString: String) -> SymmetricKey?
{
guard let ephemeralECDH = try? clientEphemeralPrivateKey.sharedSecretFromKeyAgreement(with: serverEphemeralPublicKey) else {return nil}

let ephemeralECDHData = DarkStar.sharedSecretToData(secret: ephemeralECDH)

guard let persistentECDH = try? clientEphemeralPrivateKey.sharedSecretFromKeyAgreement(with: serverPersistentPublicKey) else {return nil}

let persistentECDHData = DarkStar.sharedSecretToData(secret: persistentECDH)

let clientEphemeralPublicKey = clientEphemeralPrivateKey.publicKey

let clientEphemeralPublicKeyData = clientEphemeralPublicKey.compactRepresentation!

let serverEphemeralPublicKeyData = serverEphemeralPublicKey.compactRepresentation!

guard let serverIdentifier = DarkStar.makeServerIdentifier(serverEndpoint) else {return nil}

var hash = SHA256()
hash.update(data: ephemeralECDHData)
hash.update(data: persistentECDHData)
hash.update(data: serverIdentifier)
hash.update(data: clientEphemeralPublicKeyData)
hash.update(data: serverEphemeralPublicKeyData)
hash.update(data: DarkStarString.data)
hash.update(data: personalizationString.data) // Destination
let hashed = hash.finalize()

let hashedData = Data(hashed)
return SymmetricKey(data: hashedData)
}
#endif

public init?(serverPersistentPublicKey: P256.KeyAgreement.PublicKey, endpoint: NWEndpoint, connection: Connection)
{
Expand Down
5 changes: 4 additions & 1 deletion Sources/ShadowSwift/DarkStarConnection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,11 @@ open class DarkStarConnection: Transport.Connection

public convenience init?(host: NWEndpoint.Host, port: NWEndpoint.Port, parameters: NWParameters, config: ShadowConfig, isClient: Bool, logger: Logger)
{
// Only support devices with secure enclave.

#if os(macOS)
// Only support Apple devices with secure enclave.
guard SecureEnclave.isAvailable else {return nil}
#endif

var maybeHostString: String? = nil
switch host
Expand Down

0 comments on commit de25d4a

Please sign in to comment.