WireGuardKit: Add wrappers for PrivateKey, PublicKey, PreSharedKey

Signed-off-by: Andrej Mihajlov <and@mullvad.net>
This commit is contained in:
Andrej Mihajlov 2020-11-26 17:23:50 +01:00
parent 76c8487a56
commit 4deaf905c1
21 changed files with 176 additions and 220 deletions

View File

@ -112,7 +112,7 @@ extension TunnelConfiguration {
} }
let peerPublicKeysArray = peerConfigurations.map { $0.publicKey } let peerPublicKeysArray = peerConfigurations.map { $0.publicKey }
let peerPublicKeysSet = Set<Data>(peerPublicKeysArray) let peerPublicKeysSet = Set<PublicKey>(peerPublicKeysArray)
if peerPublicKeysArray.count != peerPublicKeysSet.count { if peerPublicKeysArray.count != peerPublicKeysSet.count {
throw ParseError.multiplePeersWithSamePublicKey throw ParseError.multiplePeersWithSamePublicKey
} }
@ -126,9 +126,7 @@ extension TunnelConfiguration {
func asWgQuickConfig() -> String { func asWgQuickConfig() -> String {
var output = "[Interface]\n" var output = "[Interface]\n"
if let privateKey = interface.privateKey.base64Key() { output.append("PrivateKey = \(interface.privateKey.base64Key)\n")
output.append("PrivateKey = \(privateKey)\n")
}
if let listenPort = interface.listenPort { if let listenPort = interface.listenPort {
output.append("ListenPort = \(listenPort)\n") output.append("ListenPort = \(listenPort)\n")
} }
@ -146,10 +144,8 @@ extension TunnelConfiguration {
for peer in peers { for peer in peers {
output.append("\n[Peer]\n") output.append("\n[Peer]\n")
if let publicKey = peer.publicKey.base64Key() { output.append("PublicKey = \(peer.publicKey.base64Key)\n")
output.append("PublicKey = \(publicKey)\n") if let preSharedKey = peer.preSharedKey?.base64Key {
}
if let preSharedKey = peer.preSharedKey?.base64Key() {
output.append("PresharedKey = \(preSharedKey)\n") output.append("PresharedKey = \(preSharedKey)\n")
} }
if !peer.allowedIPs.isEmpty { if !peer.allowedIPs.isEmpty {
@ -171,7 +167,7 @@ extension TunnelConfiguration {
guard let privateKeyString = attributes["privatekey"] else { guard let privateKeyString = attributes["privatekey"] else {
throw ParseError.interfaceHasNoPrivateKey throw ParseError.interfaceHasNoPrivateKey
} }
guard let privateKey = Data(base64Key: privateKeyString), privateKey.count == TunnelConfiguration.keyLength else { guard let privateKey = PrivateKey(base64Key: privateKeyString) else {
throw ParseError.interfaceHasInvalidPrivateKey(privateKeyString) throw ParseError.interfaceHasInvalidPrivateKey(privateKeyString)
} }
var interface = InterfaceConfiguration(privateKey: privateKey) var interface = InterfaceConfiguration(privateKey: privateKey)
@ -214,12 +210,12 @@ extension TunnelConfiguration {
guard let publicKeyString = attributes["publickey"] else { guard let publicKeyString = attributes["publickey"] else {
throw ParseError.peerHasNoPublicKey throw ParseError.peerHasNoPublicKey
} }
guard let publicKey = Data(base64Key: publicKeyString), publicKey.count == TunnelConfiguration.keyLength else { guard let publicKey = PublicKey(base64Key: publicKeyString) else {
throw ParseError.peerHasInvalidPublicKey(publicKeyString) throw ParseError.peerHasInvalidPublicKey(publicKeyString)
} }
var peer = PeerConfiguration(publicKey: publicKey) var peer = PeerConfiguration(publicKey: publicKey)
if let preSharedKeyString = attributes["presharedkey"] { if let preSharedKeyString = attributes["presharedkey"] {
guard let preSharedKey = Data(base64Key: preSharedKeyString), preSharedKey.count == TunnelConfiguration.keyLength else { guard let preSharedKey = PreSharedKey(base64Key: preSharedKeyString) else {
throw ParseError.peerHasInvalidPreSharedKey(preSharedKeyString) throw ParseError.peerHasInvalidPreSharedKey(preSharedKeyString)
} }
peer.preSharedKey = preSharedKey peer.preSharedKey = preSharedKey

View File

@ -63,8 +63,6 @@
6F628C3D217F09E9003482A3 /* TunnelViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F628C3C217F09E9003482A3 /* TunnelViewModel.swift */; }; 6F628C3D217F09E9003482A3 /* TunnelViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F628C3C217F09E9003482A3 /* TunnelViewModel.swift */; };
6F628C41217F47DB003482A3 /* TunnelDetailTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F628C40217F47DB003482A3 /* TunnelDetailTableViewController.swift */; }; 6F628C41217F47DB003482A3 /* TunnelDetailTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F628C40217F47DB003482A3 /* TunnelDetailTableViewController.swift */; };
6F6483E7229293300075BA15 /* LaunchedAtLoginDetector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F6483E6229293300075BA15 /* LaunchedAtLoginDetector.swift */; }; 6F6483E7229293300075BA15 /* LaunchedAtLoginDetector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F6483E6229293300075BA15 /* LaunchedAtLoginDetector.swift */; };
6F6899A62180447E0012E523 /* x25519.c in Sources */ = {isa = PBXBuildFile; fileRef = 6F6899A52180447E0012E523 /* x25519.c */; };
6F6899A8218044FC0012E523 /* Curve25519.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F6899A7218044FC0012E523 /* Curve25519.swift */; };
6F70E20E221058E1008BDFB4 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6F70E20C221058DF008BDFB4 /* InfoPlist.strings */; }; 6F70E20E221058E1008BDFB4 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6F70E20C221058DF008BDFB4 /* InfoPlist.strings */; };
6F70E20F221058E1008BDFB4 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6F70E20C221058DF008BDFB4 /* InfoPlist.strings */; }; 6F70E20F221058E1008BDFB4 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6F70E20C221058DF008BDFB4 /* InfoPlist.strings */; };
6F70E23D22109E15008BDFB4 /* WireGuardLoginItemHelper.app in Embed Login Item Helper */ = {isa = PBXBuildFile; fileRef = 6F70E22922106A2D008BDFB4 /* WireGuardLoginItemHelper.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 6F70E23D22109E15008BDFB4 /* WireGuardLoginItemHelper.app in Embed Login Item Helper */ = {isa = PBXBuildFile; fileRef = 6F70E22922106A2D008BDFB4 /* WireGuardLoginItemHelper.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
@ -109,8 +107,6 @@
6FB1BDC021D50F0200A991BF /* NETunnelProviderProtocol+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FFA5D942194454A0001E2F7 /* NETunnelProviderProtocol+Extension.swift */; }; 6FB1BDC021D50F0200A991BF /* NETunnelProviderProtocol+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FFA5D942194454A0001E2F7 /* NETunnelProviderProtocol+Extension.swift */; };
6FB1BDC121D50F0200A991BF /* String+ArrayConversion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F4541B121CBFAEE00994C13 /* String+ArrayConversion.swift */; }; 6FB1BDC121D50F0200A991BF /* String+ArrayConversion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F4541B121CBFAEE00994C13 /* String+ArrayConversion.swift */; };
6FB1BDC921D50F0300A991BF /* FileManager+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F5A2B4421AFDE020081EDD8 /* FileManager+Extension.swift */; }; 6FB1BDC921D50F0300A991BF /* FileManager+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F5A2B4421AFDE020081EDD8 /* FileManager+Extension.swift */; };
6FB1BDCA21D50F1700A991BF /* x25519.c in Sources */ = {isa = PBXBuildFile; fileRef = 6F6899A52180447E0012E523 /* x25519.c */; };
6FB1BDCB21D50F1700A991BF /* Curve25519.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F6899A7218044FC0012E523 /* Curve25519.swift */; };
6FB1BDCC21D50F5300A991BF /* TunnelsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F7774EE21722D97006A79B3 /* TunnelsManager.swift */; }; 6FB1BDCC21D50F5300A991BF /* TunnelsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F7774EE21722D97006A79B3 /* TunnelsManager.swift */; };
6FB1BDCD21D50F5300A991BF /* ActivateOnDemandOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FFA5DA32197085D0001E2F7 /* ActivateOnDemandOption.swift */; }; 6FB1BDCD21D50F5300A991BF /* ActivateOnDemandOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FFA5DA32197085D0001E2F7 /* ActivateOnDemandOption.swift */; };
6FB1BDCE21D50F5300A991BF /* TunnelStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F4541A821C451D100994C13 /* TunnelStatus.swift */; }; 6FB1BDCE21D50F5300A991BF /* TunnelStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F4541A821C451D100994C13 /* TunnelStatus.swift */; };
@ -286,9 +282,6 @@
6F628C40217F47DB003482A3 /* TunnelDetailTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TunnelDetailTableViewController.swift; sourceTree = "<group>"; }; 6F628C40217F47DB003482A3 /* TunnelDetailTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TunnelDetailTableViewController.swift; sourceTree = "<group>"; };
6F6483E6229293300075BA15 /* LaunchedAtLoginDetector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchedAtLoginDetector.swift; sourceTree = "<group>"; }; 6F6483E6229293300075BA15 /* LaunchedAtLoginDetector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchedAtLoginDetector.swift; sourceTree = "<group>"; };
6F689999218043390012E523 /* WireGuard-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "WireGuard-Bridging-Header.h"; sourceTree = "<group>"; }; 6F689999218043390012E523 /* WireGuard-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "WireGuard-Bridging-Header.h"; sourceTree = "<group>"; };
6F6899A42180447E0012E523 /* x25519.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = x25519.h; sourceTree = "<group>"; };
6F6899A52180447E0012E523 /* x25519.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = x25519.c; sourceTree = "<group>"; };
6F6899A7218044FC0012E523 /* Curve25519.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Curve25519.swift; sourceTree = "<group>"; };
6F70E20D221058DF008BDFB4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = WireGuard/Base.lproj/InfoPlist.strings; sourceTree = "<group>"; }; 6F70E20D221058DF008BDFB4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = WireGuard/Base.lproj/InfoPlist.strings; sourceTree = "<group>"; };
6F70E22922106A2D008BDFB4 /* WireGuardLoginItemHelper.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = WireGuardLoginItemHelper.app; sourceTree = BUILT_PRODUCTS_DIR; }; 6F70E22922106A2D008BDFB4 /* WireGuardLoginItemHelper.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = WireGuardLoginItemHelper.app; sourceTree = BUILT_PRODUCTS_DIR; };
6F70E23222106A31008BDFB4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 6F70E23222106A31008BDFB4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@ -482,16 +475,6 @@
path = Shared; path = Shared;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
6F6899A32180445A0012E523 /* Crypto */ = {
isa = PBXGroup;
children = (
6F6899A52180447E0012E523 /* x25519.c */,
6F6899A42180447E0012E523 /* x25519.h */,
6F6899A7218044FC0012E523 /* Curve25519.swift */,
);
path = Crypto;
sourceTree = "<group>";
};
6F70E22A22106A2D008BDFB4 /* LoginItemHelper */ = { 6F70E22A22106A2D008BDFB4 /* LoginItemHelper */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -689,7 +672,6 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
6F919ED3218C65C50023B400 /* Resources */, 6F919ED3218C65C50023B400 /* Resources */,
6F6899A32180445A0012E523 /* Crypto */,
6F7774DD217181B1006A79B3 /* UI */, 6F7774DD217181B1006A79B3 /* UI */,
6F7774ED21722D0C006A79B3 /* Tunnel */, 6F7774ED21722D0C006A79B3 /* Tunnel */,
6FDEF7E72186320E00D8FBF6 /* ZipArchive */, 6FDEF7E72186320E00D8FBF6 /* ZipArchive */,
@ -1160,8 +1142,6 @@
6F89E17C21F090CC00C97BB9 /* TunnelsTracker.swift in Sources */, 6F89E17C21F090CC00C97BB9 /* TunnelsTracker.swift in Sources */,
6B62E460220A6FA900EF34A6 /* PrivateDataConfirmation.swift in Sources */, 6B62E460220A6FA900EF34A6 /* PrivateDataConfirmation.swift in Sources */,
6FCD99B121E0EDA900BA4C82 /* TunnelEditViewController.swift in Sources */, 6FCD99B121E0EDA900BA4C82 /* TunnelEditViewController.swift in Sources */,
6FB1BDCA21D50F1700A991BF /* x25519.c in Sources */,
6FB1BDCB21D50F1700A991BF /* Curve25519.swift in Sources */,
6FB17946222FD5960018AE71 /* OnDemandWiFiControls.swift in Sources */, 6FB17946222FD5960018AE71 /* OnDemandWiFiControls.swift in Sources */,
6FB1BDBB21D50F0200A991BF /* Localizable.strings in Sources */, 6FB1BDBB21D50F0200A991BF /* Localizable.strings in Sources */,
6FB1BDBC21D50F0200A991BF /* ringlogger.c in Sources */, 6FB1BDBC21D50F0200A991BF /* ringlogger.c in Sources */,
@ -1233,7 +1213,6 @@
5F4541A921C451D100994C13 /* TunnelStatus.swift in Sources */, 5F4541A921C451D100994C13 /* TunnelStatus.swift in Sources */,
6F8F0D7422267AD2000E8335 /* ChevronCell.swift in Sources */, 6F8F0D7422267AD2000E8335 /* ChevronCell.swift in Sources */,
6F61F1E921B932F700483816 /* WireGuardAppError.swift in Sources */, 6F61F1E921B932F700483816 /* WireGuardAppError.swift in Sources */,
6F6899A62180447E0012E523 /* x25519.c in Sources */,
6F7774E2217181B1006A79B3 /* AppDelegate.swift in Sources */, 6F7774E2217181B1006A79B3 /* AppDelegate.swift in Sources */,
6FDEF80021863C0100D8FBF6 /* ioapi.c in Sources */, 6FDEF80021863C0100D8FBF6 /* ioapi.c in Sources */,
6F7F7E5F21C7D74B00527607 /* TunnelErrors.swift in Sources */, 6F7F7E5F21C7D74B00527607 /* TunnelErrors.swift in Sources */,
@ -1252,7 +1231,6 @@
6FE254FB219C10800028284D /* ZipImporter.swift in Sources */, 6FE254FB219C10800028284D /* ZipImporter.swift in Sources */,
6FDEF7FB21863B6100D8FBF6 /* unzip.c in Sources */, 6FDEF7FB21863B6100D8FBF6 /* unzip.c in Sources */,
6F29A9432278518D00DC6A6B /* RecentTunnelsTracker.swift in Sources */, 6F29A9432278518D00DC6A6B /* RecentTunnelsTracker.swift in Sources */,
6F6899A8218044FC0012E523 /* Curve25519.swift in Sources */,
6F0F44C9222D55BB00B0FF04 /* TextCell.swift in Sources */, 6F0F44C9222D55BB00B0FF04 /* TextCell.swift in Sources */,
5F4541A021C2D6B700994C13 /* TunnelListCell.swift in Sources */, 5F4541A021C2D6B700994C13 /* TunnelListCell.swift in Sources */,
5F9696B021CD7128008063FE /* TunnelConfiguration+WgQuickConfig.swift in Sources */, 5F9696B021CD7128008063FE /* TunnelConfiguration+WgQuickConfig.swift in Sources */,

View File

@ -1,37 +0,0 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
import Foundation
import WireGuardKit
struct Curve25519 {
static let keyLength: Int = 32
static func generatePrivateKey() -> Data {
var privateKey = Data(repeating: 0, count: TunnelConfiguration.keyLength)
privateKey.withUnsafeMutableUInt8Bytes { bytes in
curve25519_generate_private_key(bytes)
}
assert(privateKey.count == TunnelConfiguration.keyLength)
return privateKey
}
static func generatePublicKey(fromPrivateKey privateKey: Data) -> Data {
assert(privateKey.count == TunnelConfiguration.keyLength)
var publicKey = Data(repeating: 0, count: TunnelConfiguration.keyLength)
privateKey.withUnsafeUInt8Bytes { privateKeyBytes in
publicKey.withUnsafeMutableUInt8Bytes { bytes in
curve25519_derive_public_key(bytes, privateKeyBytes)
}
}
assert(publicKey.count == TunnelConfiguration.keyLength)
return publicKey
}
}
extension InterfaceConfiguration {
var publicKey: Data {
return Curve25519.generatePublicKey(fromPrivateKey: privateKey)
}
}

View File

@ -27,11 +27,11 @@ class MockTunnels {
static func createMockTunnels() -> [NETunnelProviderManager] { static func createMockTunnels() -> [NETunnelProviderManager] {
return tunnelNames.map { tunnelName -> NETunnelProviderManager in return tunnelNames.map { tunnelName -> NETunnelProviderManager in
var interface = InterfaceConfiguration(privateKey: Curve25519.generatePrivateKey()) var interface = InterfaceConfiguration(privateKey: PrivateKey())
interface.addresses = [IPAddressRange(from: String(format: address, Int.random(in: 1 ... 10), Int.random(in: 1 ... 254)))!] interface.addresses = [IPAddressRange(from: String(format: address, Int.random(in: 1 ... 10), Int.random(in: 1 ... 254)))!]
interface.dns = dnsServers.map { DNSServer(from: $0)! } interface.dns = dnsServers.map { DNSServer(from: $0)! }
var peer = PeerConfiguration(publicKey: Curve25519.generatePublicKey(fromPrivateKey: Curve25519.generatePrivateKey())) var peer = PeerConfiguration(publicKey: PrivateKey().publicKey)
peer.endpoint = Endpoint(from: endpoint) peer.endpoint = Endpoint(from: endpoint)
peer.allowedIPs = [IPAddressRange(from: allowedIPs)!] peer.allowedIPs = [IPAddressRange(from: allowedIPs)!]

View File

@ -68,7 +68,7 @@ extension TunnelConfiguration {
} }
let peerPublicKeysArray = peerConfigurations.map { $0.publicKey } let peerPublicKeysArray = peerConfigurations.map { $0.publicKey }
let peerPublicKeysSet = Set<Data>(peerPublicKeysArray) let peerPublicKeysSet = Set<PublicKey>(peerPublicKeysArray)
if peerPublicKeysArray.count != peerPublicKeysSet.count { if peerPublicKeysArray.count != peerPublicKeysSet.count {
throw ParseError.multiplePeersWithSamePublicKey throw ParseError.multiplePeersWithSamePublicKey
} }
@ -88,7 +88,7 @@ extension TunnelConfiguration {
guard let privateKeyString = attributes["private_key"] else { guard let privateKeyString = attributes["private_key"] else {
throw ParseError.interfaceHasNoPrivateKey throw ParseError.interfaceHasNoPrivateKey
} }
guard let privateKey = Data(hexKey: privateKeyString), privateKey.count == TunnelConfiguration.keyLength else { guard let privateKey = PrivateKey(hexKey: privateKeyString) else {
throw ParseError.interfaceHasInvalidPrivateKey(privateKeyString) throw ParseError.interfaceHasInvalidPrivateKey(privateKeyString)
} }
var interface = InterfaceConfiguration(privateKey: privateKey) var interface = InterfaceConfiguration(privateKey: privateKey)
@ -107,18 +107,18 @@ extension TunnelConfiguration {
guard let publicKeyString = attributes["public_key"] else { guard let publicKeyString = attributes["public_key"] else {
throw ParseError.peerHasNoPublicKey throw ParseError.peerHasNoPublicKey
} }
guard let publicKey = Data(hexKey: publicKeyString), publicKey.count == TunnelConfiguration.keyLength else { guard let publicKey = PublicKey(hexKey: publicKeyString) else {
throw ParseError.peerHasInvalidPublicKey(publicKeyString) throw ParseError.peerHasInvalidPublicKey(publicKeyString)
} }
var peer = PeerConfiguration(publicKey: publicKey) var peer = PeerConfiguration(publicKey: publicKey)
if let preSharedKeyString = attributes["preshared_key"] { if let preSharedKeyString = attributes["preshared_key"] {
guard let preSharedKey = Data(hexKey: preSharedKeyString), preSharedKey.count == TunnelConfiguration.keyLength else { guard let preSharedKey = PreSharedKey(hexKey: preSharedKeyString) else {
throw ParseError.peerHasInvalidPreSharedKey(preSharedKeyString) throw ParseError.peerHasInvalidPreSharedKey(preSharedKeyString)
} }
// TODO(zx2c4): does the compiler optimize this away? // TODO(zx2c4): does the compiler optimize this away?
var accumulator: UInt8 = 0 var accumulator: UInt8 = 0
for index in 0..<preSharedKey.count { for index in 0..<preSharedKey.rawValue.count {
accumulator |= preSharedKey[index] accumulator |= preSharedKey.rawValue[index]
} }
if accumulator != 0 { if accumulator != 0 {
peer.preSharedKey = preSharedKey peer.preSharedKey = preSharedKey

View File

@ -110,9 +110,9 @@ class TunnelViewModel {
scratchpad[field] = stringValue scratchpad[field] = stringValue
} }
if field == .privateKey { if field == .privateKey {
if stringValue.count == TunnelViewModel.keyLengthInBase64, let privateKey = Data(base64Key: stringValue), privateKey.count == TunnelConfiguration.keyLength { if stringValue.count == TunnelViewModel.keyLengthInBase64,
let publicKey = Curve25519.generatePublicKey(fromPrivateKey: privateKey).base64Key() ?? "" let privateKey = PrivateKey(base64Key: stringValue) {
scratchpad[.publicKey] = publicKey scratchpad[.publicKey] = privateKey.publicKey.base64Key
} else { } else {
scratchpad.removeValue(forKey: .publicKey) scratchpad.removeValue(forKey: .publicKey)
} }
@ -129,8 +129,8 @@ class TunnelViewModel {
private static func createScratchPad(from config: InterfaceConfiguration, name: String) -> [InterfaceField: String] { private static func createScratchPad(from config: InterfaceConfiguration, name: String) -> [InterfaceField: String] {
var scratchpad = [InterfaceField: String]() var scratchpad = [InterfaceField: String]()
scratchpad[.name] = name scratchpad[.name] = name
scratchpad[.privateKey] = config.privateKey.base64Key() ?? "" scratchpad[.privateKey] = config.privateKey.base64Key
scratchpad[.publicKey] = config.publicKey.base64Key() ?? "" scratchpad[.publicKey] = config.privateKey.publicKey.base64Key
if !config.addresses.isEmpty { if !config.addresses.isEmpty {
scratchpad[.addresses] = config.addresses.map { $0.stringRepresentation }.joined(separator: ", ") scratchpad[.addresses] = config.addresses.map { $0.stringRepresentation }.joined(separator: ", ")
} }
@ -159,7 +159,7 @@ class TunnelViewModel {
fieldsWithError.insert(.privateKey) fieldsWithError.insert(.privateKey)
return .error(tr("alertInvalidInterfaceMessagePrivateKeyRequired")) return .error(tr("alertInvalidInterfaceMessagePrivateKeyRequired"))
} }
guard let privateKey = Data(base64Key: privateKeyString), privateKey.count == TunnelConfiguration.keyLength else { guard let privateKey = PrivateKey(base64Key: privateKeyString) else {
fieldsWithError.insert(.privateKey) fieldsWithError.insert(.privateKey)
return .error(tr("alertInvalidInterfaceMessagePrivateKeyInvalid")) return .error(tr("alertInvalidInterfaceMessagePrivateKeyInvalid"))
} }
@ -252,12 +252,12 @@ class TunnelViewModel {
var scratchpad = [PeerField: String]() var scratchpad = [PeerField: String]()
var fieldsWithError = Set<PeerField>() var fieldsWithError = Set<PeerField>()
var validatedConfiguration: PeerConfiguration? var validatedConfiguration: PeerConfiguration?
var publicKey: Data? { var publicKey: PublicKey? {
if let validatedConfiguration = validatedConfiguration { if let validatedConfiguration = validatedConfiguration {
return validatedConfiguration.publicKey return validatedConfiguration.publicKey
} }
if let scratchPadPublicKey = scratchpad[.publicKey] { if let scratchPadPublicKey = scratchpad[.publicKey] {
return Data(base64Key: scratchPadPublicKey) return PublicKey(base64Key: scratchPadPublicKey)
} }
return nil return nil
} }
@ -302,10 +302,8 @@ class TunnelViewModel {
private static func createScratchPad(from config: PeerConfiguration) -> [PeerField: String] { private static func createScratchPad(from config: PeerConfiguration) -> [PeerField: String] {
var scratchpad = [PeerField: String]() var scratchpad = [PeerField: String]()
if let publicKey = config.publicKey.base64Key() { scratchpad[.publicKey] = config.publicKey.base64Key
scratchpad[.publicKey] = publicKey if let preSharedKey = config.preSharedKey?.base64Key {
}
if let preSharedKey = config.preSharedKey?.base64Key() {
scratchpad[.preSharedKey] = preSharedKey scratchpad[.preSharedKey] = preSharedKey
} }
if !config.allowedIPs.isEmpty { if !config.allowedIPs.isEmpty {
@ -338,14 +336,14 @@ class TunnelViewModel {
fieldsWithError.insert(.publicKey) fieldsWithError.insert(.publicKey)
return .error(tr("alertInvalidPeerMessagePublicKeyRequired")) return .error(tr("alertInvalidPeerMessagePublicKeyRequired"))
} }
guard let publicKey = Data(base64Key: publicKeyString), publicKey.count == TunnelConfiguration.keyLength else { guard let publicKey = PublicKey(base64Key: publicKeyString) else {
fieldsWithError.insert(.publicKey) fieldsWithError.insert(.publicKey)
return .error(tr("alertInvalidPeerMessagePublicKeyInvalid")) return .error(tr("alertInvalidPeerMessagePublicKeyInvalid"))
} }
var config = PeerConfiguration(publicKey: publicKey) var config = PeerConfiguration(publicKey: publicKey)
var errorMessages = [String]() var errorMessages = [String]()
if let preSharedKeyString = scratchpad[.preSharedKey] { if let preSharedKeyString = scratchpad[.preSharedKey] {
if let preSharedKey = Data(base64Key: preSharedKeyString), preSharedKey.count == TunnelConfiguration.keyLength { if let preSharedKey = PreSharedKey(base64Key: preSharedKeyString) {
config.preSharedKey = preSharedKey config.preSharedKey = preSharedKey
} else { } else {
fieldsWithError.insert(.preSharedKey) fieldsWithError.insert(.preSharedKey)
@ -560,7 +558,7 @@ class TunnelViewModel {
} }
let peerPublicKeysArray = peerConfigurations.map { $0.publicKey } let peerPublicKeysArray = peerConfigurations.map { $0.publicKey }
let peerPublicKeysSet = Set<Data>(peerPublicKeysArray) let peerPublicKeysSet = Set<PublicKey>(peerPublicKeysArray)
if peerPublicKeysArray.count != peerPublicKeysSet.count { if peerPublicKeysArray.count != peerPublicKeysSet.count {
return .error(tr("alertInvalidPeerMessagePublicKeyDuplicated")) return .error(tr("alertInvalidPeerMessagePublicKeyDuplicated"))
} }

View File

@ -2,6 +2,7 @@
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
import UIKit import UIKit
import WireGuardKit
protocol TunnelEditTableViewControllerDelegate: class { protocol TunnelEditTableViewControllerDelegate: class {
func tunnelSaved(tunnel: TunnelContainer) func tunnelSaved(tunnel: TunnelContainer)
@ -214,7 +215,7 @@ extension TunnelEditTableViewController {
cell.onTapped = { [weak self] in cell.onTapped = { [weak self] in
guard let self = self else { return } guard let self = self else { return }
self.tunnelViewModel.interfaceData[.privateKey] = Curve25519.generatePrivateKey().base64Key() ?? "" self.tunnelViewModel.interfaceData[.privateKey] = PrivateKey().base64Key
if let privateKeyRow = self.interfaceFieldsBySection[indexPath.section].firstIndex(of: .privateKey), if let privateKeyRow = self.interfaceFieldsBySection[indexPath.section].firstIndex(of: .privateKey),
let publicKeyRow = self.interfaceFieldsBySection[indexPath.section].firstIndex(of: .publicKey) { let publicKeyRow = self.interfaceFieldsBySection[indexPath.section].firstIndex(of: .publicKey) {
let privateKeyIndex = IndexPath(row: privateKeyRow, section: indexPath.section) let privateKeyIndex = IndexPath(row: privateKeyRow, section: indexPath.section)

View File

@ -108,27 +108,24 @@ class TunnelEditViewController: NSViewController {
let tunnelConfiguration = tunnel.tunnelConfiguration! let tunnelConfiguration = tunnel.tunnelConfiguration!
nameRow.value = tunnel.name nameRow.value = tunnel.name
textView.string = tunnelConfiguration.asWgQuickConfig() textView.string = tunnelConfiguration.asWgQuickConfig()
publicKeyRow.value = tunnelConfiguration.interface.publicKey.base64Key() ?? "" publicKeyRow.value = tunnelConfiguration.interface.privateKey.publicKey.base64Key
textView.privateKeyString = tunnelConfiguration.interface.privateKey.base64Key() ?? "" textView.privateKeyString = tunnelConfiguration.interface.privateKey.base64Key
let singlePeer = tunnelConfiguration.peers.count == 1 ? tunnelConfiguration.peers.first : nil let singlePeer = tunnelConfiguration.peers.count == 1 ? tunnelConfiguration.peers.first : nil
updateExcludePrivateIPsVisibility(singlePeerAllowedIPs: singlePeer?.allowedIPs.map { $0.stringRepresentation }) updateExcludePrivateIPsVisibility(singlePeerAllowedIPs: singlePeer?.allowedIPs.map { $0.stringRepresentation })
dnsServersAddedToAllowedIPs = excludePrivateIPsCheckbox.state == .on ? tunnelConfiguration.interface.dns.map { $0.stringRepresentation }.joined(separator: ", ") : nil dnsServersAddedToAllowedIPs = excludePrivateIPsCheckbox.state == .on ? tunnelConfiguration.interface.dns.map { $0.stringRepresentation }.joined(separator: ", ") : nil
} else { } else {
// Creating a new tunnel // Creating a new tunnel
let privateKey = Curve25519.generatePrivateKey() let privateKey = PrivateKey()
let publicKey = Curve25519.generatePublicKey(fromPrivateKey: privateKey) let bootstrappingText = "[Interface]\nPrivateKey = \(privateKey.base64Key)\n"
let bootstrappingText = "[Interface]\nPrivateKey = \(privateKey.base64Key() ?? "")\n" publicKeyRow.value = privateKey.publicKey.base64Key
publicKeyRow.value = publicKey.base64Key() ?? ""
textView.string = bootstrappingText textView.string = bootstrappingText
updateExcludePrivateIPsVisibility(singlePeerAllowedIPs: nil) updateExcludePrivateIPsVisibility(singlePeerAllowedIPs: nil)
dnsServersAddedToAllowedIPs = nil dnsServersAddedToAllowedIPs = nil
} }
privateKeyObservationToken = textView.observe(\.privateKeyString) { [weak publicKeyRow] textView, _ in privateKeyObservationToken = textView.observe(\.privateKeyString) { [weak publicKeyRow] textView, _ in
if let privateKeyString = textView.privateKeyString, if let privateKeyString = textView.privateKeyString,
let privateKey = Data(base64Key: privateKeyString), let privateKey = PrivateKey(base64Key: privateKeyString) {
privateKey.count == TunnelConfiguration.keyLength { publicKeyRow?.value = privateKey.publicKey.base64Key
let publicKey = Curve25519.generatePublicKey(fromPrivateKey: privateKey)
publicKeyRow?.value = publicKey.base64Key() ?? ""
} else { } else {
publicKeyRow?.value = "" publicKeyRow?.value = ""
} }

View File

@ -1,4 +1,3 @@
#include "x25519.h"
#include "unzip.h" #include "unzip.h"
#include "zip.h" #include "zip.h"
#include "ringlogger.h" #include "ringlogger.h"

View File

@ -23,7 +23,9 @@ enum ZipArchiveError: WireGuardAppError {
} }
} }
class ZipArchive { enum ZipArchive {}
extension ZipArchive {
static func archive(inputs: [(fileName: String, contents: Data)], to destinationURL: URL) throws { static func archive(inputs: [(fileName: String, contents: Data)], to destinationURL: URL) throws {
let destinationPath = destinationURL.path let destinationPath = destinationURL.path
@ -34,8 +36,8 @@ class ZipArchive {
let fileName = input.fileName let fileName = input.fileName
let contents = input.contents let contents = input.contents
zipOpenNewFileInZip(zipFile, fileName.cString(using: .utf8), nil, nil, 0, nil, 0, nil, Z_DEFLATED, Z_DEFAULT_COMPRESSION) zipOpenNewFileInZip(zipFile, fileName.cString(using: .utf8), nil, nil, 0, nil, 0, nil, Z_DEFLATED, Z_DEFAULT_COMPRESSION)
contents.withUnsafeUInt8Bytes { ptr -> Void in contents.withUnsafeBytes { rawBufferPointer -> Void in
zipWriteInFileInZip(zipFile, UnsafeRawPointer(ptr), UInt32(contents.count)) zipWriteInFileInZip(zipFile, rawBufferPointer.baseAddress, UInt32(contents.count))
} }
zipCloseFileInZip(zipFile) zipCloseFileInZip(zipFile)
} }

View File

@ -1,80 +0,0 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
import Foundation
extension Data {
func isKey() -> Bool {
return self.count == WG_KEY_LEN
}
func hexKey() -> String? {
if self.count != WG_KEY_LEN {
return nil
}
var out = Data(repeating: 0, count: Int(WG_KEY_LEN_HEX))
out.withUnsafeMutableInt8Bytes { outBytes in
self.withUnsafeUInt8Bytes { inBytes in
key_to_hex(outBytes, inBytes)
}
}
out.removeLast()
return String(data: out, encoding: .ascii)
}
init?(hexKey hexString: String) {
self.init(repeating: 0, count: Int(WG_KEY_LEN))
if !self.withUnsafeMutableUInt8Bytes { key_from_hex($0, hexString) } {
return nil
}
}
func base64Key() -> String? {
if self.count != WG_KEY_LEN {
return nil
}
var out = Data(repeating: 0, count: Int(WG_KEY_LEN_BASE64))
out.withUnsafeMutableInt8Bytes { outBytes in
self.withUnsafeUInt8Bytes { inBytes in
key_to_base64(outBytes, inBytes)
}
}
out.removeLast()
return String(data: out, encoding: .ascii)
}
init?(base64Key base64String: String) {
self.init(repeating: 0, count: Int(WG_KEY_LEN))
if !self.withUnsafeMutableUInt8Bytes { key_from_base64($0, base64String) } {
return nil
}
}
}
extension Data {
func withUnsafeUInt8Bytes<R>(_ body: (UnsafePointer<UInt8>) -> R) -> R {
assert(!isEmpty)
return self.withUnsafeBytes { (ptr: UnsafeRawBufferPointer) -> R in
let bytes = ptr.bindMemory(to: UInt8.self)
return body(bytes.baseAddress!) // might crash if self.count == 0
}
}
mutating func withUnsafeMutableUInt8Bytes<R>(_ body: (UnsafeMutablePointer<UInt8>) -> R) -> R {
assert(!isEmpty)
return self.withUnsafeMutableBytes { (ptr: UnsafeMutableRawBufferPointer) -> R in
let bytes = ptr.bindMemory(to: UInt8.self)
return body(bytes.baseAddress!) // might crash if self.count == 0
}
}
mutating func withUnsafeMutableInt8Bytes<R>(_ body: (UnsafeMutablePointer<Int8>) -> R) -> R {
assert(!isEmpty)
return self.withUnsafeMutableBytes { (ptr: UnsafeMutableRawBufferPointer) -> R in
let bytes = ptr.bindMemory(to: Int8.self)
return body(bytes.baseAddress!) // might crash if self.count == 0
}
}
}

View File

@ -5,16 +5,13 @@ import Foundation
import Network import Network
public struct InterfaceConfiguration { public struct InterfaceConfiguration {
public var privateKey: Data public var privateKey: PrivateKey
public var addresses = [IPAddressRange]() public var addresses = [IPAddressRange]()
public var listenPort: UInt16? public var listenPort: UInt16?
public var mtu: UInt16? public var mtu: UInt16?
public var dns = [DNSServer]() public var dns = [DNSServer]()
public init(privateKey: Data) { public init(privateKey: PrivateKey) {
if privateKey.count != TunnelConfiguration.keyLength {
fatalError("Invalid private key")
}
self.privateKey = privateKey self.privateKey = privateKey
} }
} }

View File

@ -18,9 +18,7 @@ class PacketTunnelSettingsGenerator {
func endpointUapiConfiguration() -> String { func endpointUapiConfiguration() -> String {
var wgSettings = "" var wgSettings = ""
for (index, peer) in tunnelConfiguration.peers.enumerated() { for (index, peer) in tunnelConfiguration.peers.enumerated() {
if let publicKey = peer.publicKey.hexKey() { wgSettings.append("public_key=\(peer.publicKey.hexKey)\n")
wgSettings.append("public_key=\(publicKey)\n")
}
if let endpoint = resolvedEndpoints[index]?.withReresolvedIP() { if let endpoint = resolvedEndpoints[index]?.withReresolvedIP() {
if case .name(_, _) = endpoint.host { assert(false, "Endpoint is not resolved") } if case .name(_, _) = endpoint.host { assert(false, "Endpoint is not resolved") }
wgSettings.append("endpoint=\(endpoint.stringRepresentation)\n") wgSettings.append("endpoint=\(endpoint.stringRepresentation)\n")
@ -31,9 +29,7 @@ class PacketTunnelSettingsGenerator {
func uapiConfiguration() -> String { func uapiConfiguration() -> String {
var wgSettings = "" var wgSettings = ""
if let privateKey = tunnelConfiguration.interface.privateKey.hexKey() { wgSettings.append("private_key=\(tunnelConfiguration.interface.privateKey.hexKey)\n")
wgSettings.append("private_key=\(privateKey)\n")
}
if let listenPort = tunnelConfiguration.interface.listenPort { if let listenPort = tunnelConfiguration.interface.listenPort {
wgSettings.append("listen_port=\(listenPort)\n") wgSettings.append("listen_port=\(listenPort)\n")
} }
@ -42,10 +38,8 @@ class PacketTunnelSettingsGenerator {
} }
assert(tunnelConfiguration.peers.count == resolvedEndpoints.count) assert(tunnelConfiguration.peers.count == resolvedEndpoints.count)
for (index, peer) in tunnelConfiguration.peers.enumerated() { for (index, peer) in tunnelConfiguration.peers.enumerated() {
if let publicKey = peer.publicKey.hexKey() { wgSettings.append("public_key=\(peer.publicKey.hexKey)\n")
wgSettings.append("public_key=\(publicKey)\n") if let preSharedKey = peer.preSharedKey?.hexKey {
}
if let preSharedKey = peer.preSharedKey?.hexKey() {
wgSettings.append("preshared_key=\(preSharedKey)\n") wgSettings.append("preshared_key=\(preSharedKey)\n")
} }
if let endpoint = resolvedEndpoints[index]?.withReresolvedIP() { if let endpoint = resolvedEndpoints[index]?.withReresolvedIP() {

View File

@ -4,16 +4,8 @@
import Foundation import Foundation
public struct PeerConfiguration { public struct PeerConfiguration {
public var publicKey: Data public var publicKey: PublicKey
public var preSharedKey: Data? { public var preSharedKey: PreSharedKey?
didSet(value) {
if let value = value {
if value.count != TunnelConfiguration.keyLength {
fatalError("Invalid preshared key")
}
}
}
}
public var allowedIPs = [IPAddressRange]() public var allowedIPs = [IPAddressRange]()
public var endpoint: Endpoint? public var endpoint: Endpoint?
public var persistentKeepAlive: UInt16? public var persistentKeepAlive: UInt16?
@ -21,11 +13,8 @@ public struct PeerConfiguration {
public var txBytes: UInt64? public var txBytes: UInt64?
public var lastHandshakeTime: Date? public var lastHandshakeTime: Date?
public init(publicKey: Data) { public init(publicKey: PublicKey) {
self.publicKey = publicKey self.publicKey = publicKey
if publicKey.count != TunnelConfiguration.keyLength {
fatalError("Invalid public key")
}
} }
} }

View File

@ -0,0 +1,111 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
import Foundation
import WireGuardKitCTarget
/// The class describing a private key used by WireGuard.
public class PrivateKey: _BaseKey {
/// Derived public key
public var publicKey: PublicKey {
return rawValue.withUnsafeBytes { (privateKeyBufferPointer: UnsafeRawBufferPointer) -> PublicKey in
var publicKeyData = Data(repeating: 0, count: Int(WG_KEY_LEN))
let privateKeyBytes = privateKeyBufferPointer.baseAddress!.assumingMemoryBound(to: UInt8.self)
publicKeyData.withUnsafeMutableBytes { (publicKeyBufferPointer: UnsafeMutableRawBufferPointer) in
let publicKeyBytes = publicKeyBufferPointer.baseAddress!.assumingMemoryBound(to: UInt8.self)
curve25519_derive_public_key(publicKeyBytes, privateKeyBytes)
}
return PublicKey(rawValue: publicKeyData)!
}
}
/// Initialize new private key
convenience public init() {
var privateKeyData = Data(repeating: 0, count: Int(WG_KEY_LEN))
privateKeyData.withUnsafeMutableBytes { (rawBufferPointer: UnsafeMutableRawBufferPointer) in
let privateKeyBytes = rawBufferPointer.baseAddress!.assumingMemoryBound(to: UInt8.self)
curve25519_generate_private_key(privateKeyBytes)
}
self.init(rawValue: privateKeyData)!
}
}
/// The class describing a public key used by WireGuard.
public class PublicKey: _BaseKey {}
/// The class describing a pre-shared key used by WireGuard.
public class PreSharedKey: _BaseKey {}
/// The base key implementation. Should not be used directly.
public class _BaseKey: RawRepresentable, Equatable, Hashable {
/// Raw key representation
public let rawValue: Data
/// Hex encoded representation
public var hexKey: String {
return rawValue.withUnsafeBytes { (rawBufferPointer: UnsafeRawBufferPointer) -> String in
let inBytes = rawBufferPointer.baseAddress!.assumingMemoryBound(to: UInt8.self)
var outBytes = [CChar](repeating: 0, count: Int(WG_KEY_LEN_HEX))
key_to_hex(&outBytes, inBytes)
return String(cString: outBytes, encoding: .ascii)!
}
}
/// Base64 encoded representation
public var base64Key: String {
return rawValue.withUnsafeBytes { (rawBufferPointer: UnsafeRawBufferPointer) -> String in
let inBytes = rawBufferPointer.baseAddress!.assumingMemoryBound(to: UInt8.self)
var outBytes = [CChar](repeating: 0, count: Int(WG_KEY_LEN_BASE64))
key_to_base64(&outBytes, inBytes)
return String(cString: outBytes, encoding: .ascii)!
}
}
/// Initialize the key with existing raw representation
required public init?(rawValue: Data) {
if rawValue.count == WG_KEY_LEN {
self.rawValue = rawValue
} else {
return nil
}
}
/// Initialize the key with hex representation
public convenience init?(hexKey: String) {
var bytes = Data(repeating: 0, count: Int(WG_KEY_LEN))
let success = bytes.withUnsafeMutableBytes { (bufferPointer: UnsafeMutableRawBufferPointer) -> Bool in
return key_from_hex(bufferPointer.baseAddress!.assumingMemoryBound(to: UInt8.self), hexKey)
}
if success {
self.init(rawValue: bytes)
} else {
return nil
}
}
/// Initialize the key with base64 representation
public convenience init?(base64Key: String) {
var bytes = Data(repeating: 0, count: Int(WG_KEY_LEN))
let success = bytes.withUnsafeMutableBytes { (bufferPointer: UnsafeMutableRawBufferPointer) -> Bool in
return key_from_base64(bufferPointer.baseAddress!.assumingMemoryBound(to: UInt8.self), base64Key)
}
if success {
self.init(rawValue: bytes)
} else {
return nil
}
}
public static func == (lhs: _BaseKey, rhs: _BaseKey) -> Bool {
return lhs.rawValue.withUnsafeBytes { (lhsBytes: UnsafeRawBufferPointer) -> Bool in
return rhs.rawValue.withUnsafeBytes { (rhsBytes: UnsafeRawBufferPointer) -> Bool in
return key_eq(
lhsBytes.baseAddress!.assumingMemoryBound(to: UInt8.self),
rhsBytes.baseAddress!.assumingMemoryBound(to: UInt8.self)
)
}
}
}
}

View File

@ -8,15 +8,13 @@ public final class TunnelConfiguration {
public var interface: InterfaceConfiguration public var interface: InterfaceConfiguration
public let peers: [PeerConfiguration] public let peers: [PeerConfiguration]
public static let keyLength = 32
public init(name: String?, interface: InterfaceConfiguration, peers: [PeerConfiguration]) { public init(name: String?, interface: InterfaceConfiguration, peers: [PeerConfiguration]) {
self.interface = interface self.interface = interface
self.peers = peers self.peers = peers
self.name = name self.name = name
let peerPublicKeysArray = peers.map { $0.publicKey } let peerPublicKeysArray = peers.map { $0.publicKey }
let peerPublicKeysSet = Set<Data>(peerPublicKeysArray) let peerPublicKeysSet = Set<PublicKey>(peerPublicKeysArray)
if peerPublicKeysArray.count != peerPublicKeysSet.count { if peerPublicKeysArray.count != peerPublicKeysSet.count {
fatalError("Two or more peers cannot have the same public key") fatalError("Two or more peers cannot have the same public key")
} }

View File

@ -2,3 +2,4 @@
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
#include "../key.h" #include "../key.h"
#include "../x25519.h"

View File

@ -112,3 +112,13 @@ bool key_from_hex(uint8_t key[static WG_KEY_LEN], const char *hex)
return 1 & ((ret - 1) >> 8); return 1 & ((ret - 1) >> 8);
} }
bool key_eq(const uint8_t key1[static WG_KEY_LEN], const uint8_t key2[static WG_KEY_LEN])
{
volatile uint8_t acc = 0;
for (unsigned int i = 0; i < WG_KEY_LEN; ++i) {
acc |= key1[i] ^ key2[i];
asm volatile("" : "=r"(acc) : "0"(acc));
}
return 1 & ((acc - 1) >> 8);
}

View File

@ -19,4 +19,6 @@ bool key_from_base64(uint8_t key[static WG_KEY_LEN], const char *base64);
void key_to_hex(char hex[static WG_KEY_LEN_HEX], const uint8_t key[static WG_KEY_LEN]); void key_to_hex(char hex[static WG_KEY_LEN_HEX], const uint8_t key[static WG_KEY_LEN]);
bool key_from_hex(uint8_t key[static WG_KEY_LEN], const char *hex); bool key_from_hex(uint8_t key[static WG_KEY_LEN], const char *hex);
bool key_eq(const uint8_t key1[static WG_KEY_LEN], const uint8_t key2[static WG_KEY_LEN]);
#endif #endif