WireGuardKit: Add wrappers for PrivateKey, PublicKey, PreSharedKey
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
This commit is contained in:
parent
76c8487a56
commit
4deaf905c1
|
@ -112,7 +112,7 @@ extension TunnelConfiguration {
|
|||
}
|
||||
|
||||
let peerPublicKeysArray = peerConfigurations.map { $0.publicKey }
|
||||
let peerPublicKeysSet = Set<Data>(peerPublicKeysArray)
|
||||
let peerPublicKeysSet = Set<PublicKey>(peerPublicKeysArray)
|
||||
if peerPublicKeysArray.count != peerPublicKeysSet.count {
|
||||
throw ParseError.multiplePeersWithSamePublicKey
|
||||
}
|
||||
|
@ -126,9 +126,7 @@ extension TunnelConfiguration {
|
|||
|
||||
func asWgQuickConfig() -> String {
|
||||
var output = "[Interface]\n"
|
||||
if let privateKey = interface.privateKey.base64Key() {
|
||||
output.append("PrivateKey = \(privateKey)\n")
|
||||
}
|
||||
output.append("PrivateKey = \(interface.privateKey.base64Key)\n")
|
||||
if let listenPort = interface.listenPort {
|
||||
output.append("ListenPort = \(listenPort)\n")
|
||||
}
|
||||
|
@ -146,10 +144,8 @@ extension TunnelConfiguration {
|
|||
|
||||
for peer in peers {
|
||||
output.append("\n[Peer]\n")
|
||||
if let publicKey = peer.publicKey.base64Key() {
|
||||
output.append("PublicKey = \(publicKey)\n")
|
||||
}
|
||||
if let preSharedKey = peer.preSharedKey?.base64Key() {
|
||||
output.append("PublicKey = \(peer.publicKey.base64Key)\n")
|
||||
if let preSharedKey = peer.preSharedKey?.base64Key {
|
||||
output.append("PresharedKey = \(preSharedKey)\n")
|
||||
}
|
||||
if !peer.allowedIPs.isEmpty {
|
||||
|
@ -171,7 +167,7 @@ extension TunnelConfiguration {
|
|||
guard let privateKeyString = attributes["privatekey"] else {
|
||||
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)
|
||||
}
|
||||
var interface = InterfaceConfiguration(privateKey: privateKey)
|
||||
|
@ -214,12 +210,12 @@ extension TunnelConfiguration {
|
|||
guard let publicKeyString = attributes["publickey"] else {
|
||||
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)
|
||||
}
|
||||
var peer = PeerConfiguration(publicKey: publicKey)
|
||||
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)
|
||||
}
|
||||
peer.preSharedKey = preSharedKey
|
||||
|
|
|
@ -63,8 +63,6 @@
|
|||
6F628C3D217F09E9003482A3 /* TunnelViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F628C3C217F09E9003482A3 /* TunnelViewModel.swift */; };
|
||||
6F628C41217F47DB003482A3 /* TunnelDetailTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F628C40217F47DB003482A3 /* TunnelDetailTableViewController.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 */; };
|
||||
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, ); }; };
|
||||
|
@ -109,8 +107,6 @@
|
|||
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 */; };
|
||||
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 */; };
|
||||
6FB1BDCD21D50F5300A991BF /* ActivateOnDemandOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FFA5DA32197085D0001E2F7 /* ActivateOnDemandOption.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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
|
@ -482,16 +475,6 @@
|
|||
path = Shared;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6F6899A32180445A0012E523 /* Crypto */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6F6899A52180447E0012E523 /* x25519.c */,
|
||||
6F6899A42180447E0012E523 /* x25519.h */,
|
||||
6F6899A7218044FC0012E523 /* Curve25519.swift */,
|
||||
);
|
||||
path = Crypto;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6F70E22A22106A2D008BDFB4 /* LoginItemHelper */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -689,7 +672,6 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
6F919ED3218C65C50023B400 /* Resources */,
|
||||
6F6899A32180445A0012E523 /* Crypto */,
|
||||
6F7774DD217181B1006A79B3 /* UI */,
|
||||
6F7774ED21722D0C006A79B3 /* Tunnel */,
|
||||
6FDEF7E72186320E00D8FBF6 /* ZipArchive */,
|
||||
|
@ -1160,8 +1142,6 @@
|
|||
6F89E17C21F090CC00C97BB9 /* TunnelsTracker.swift in Sources */,
|
||||
6B62E460220A6FA900EF34A6 /* PrivateDataConfirmation.swift in Sources */,
|
||||
6FCD99B121E0EDA900BA4C82 /* TunnelEditViewController.swift in Sources */,
|
||||
6FB1BDCA21D50F1700A991BF /* x25519.c in Sources */,
|
||||
6FB1BDCB21D50F1700A991BF /* Curve25519.swift in Sources */,
|
||||
6FB17946222FD5960018AE71 /* OnDemandWiFiControls.swift in Sources */,
|
||||
6FB1BDBB21D50F0200A991BF /* Localizable.strings in Sources */,
|
||||
6FB1BDBC21D50F0200A991BF /* ringlogger.c in Sources */,
|
||||
|
@ -1233,7 +1213,6 @@
|
|||
5F4541A921C451D100994C13 /* TunnelStatus.swift in Sources */,
|
||||
6F8F0D7422267AD2000E8335 /* ChevronCell.swift in Sources */,
|
||||
6F61F1E921B932F700483816 /* WireGuardAppError.swift in Sources */,
|
||||
6F6899A62180447E0012E523 /* x25519.c in Sources */,
|
||||
6F7774E2217181B1006A79B3 /* AppDelegate.swift in Sources */,
|
||||
6FDEF80021863C0100D8FBF6 /* ioapi.c in Sources */,
|
||||
6F7F7E5F21C7D74B00527607 /* TunnelErrors.swift in Sources */,
|
||||
|
@ -1252,7 +1231,6 @@
|
|||
6FE254FB219C10800028284D /* ZipImporter.swift in Sources */,
|
||||
6FDEF7FB21863B6100D8FBF6 /* unzip.c in Sources */,
|
||||
6F29A9432278518D00DC6A6B /* RecentTunnelsTracker.swift in Sources */,
|
||||
6F6899A8218044FC0012E523 /* Curve25519.swift in Sources */,
|
||||
6F0F44C9222D55BB00B0FF04 /* TextCell.swift in Sources */,
|
||||
5F4541A021C2D6B700994C13 /* TunnelListCell.swift in Sources */,
|
||||
5F9696B021CD7128008063FE /* TunnelConfiguration+WgQuickConfig.swift in Sources */,
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -27,11 +27,11 @@ class MockTunnels {
|
|||
static func createMockTunnels() -> [NETunnelProviderManager] {
|
||||
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.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.allowedIPs = [IPAddressRange(from: allowedIPs)!]
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ extension TunnelConfiguration {
|
|||
}
|
||||
|
||||
let peerPublicKeysArray = peerConfigurations.map { $0.publicKey }
|
||||
let peerPublicKeysSet = Set<Data>(peerPublicKeysArray)
|
||||
let peerPublicKeysSet = Set<PublicKey>(peerPublicKeysArray)
|
||||
if peerPublicKeysArray.count != peerPublicKeysSet.count {
|
||||
throw ParseError.multiplePeersWithSamePublicKey
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ extension TunnelConfiguration {
|
|||
guard let privateKeyString = attributes["private_key"] else {
|
||||
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)
|
||||
}
|
||||
var interface = InterfaceConfiguration(privateKey: privateKey)
|
||||
|
@ -107,18 +107,18 @@ extension TunnelConfiguration {
|
|||
guard let publicKeyString = attributes["public_key"] else {
|
||||
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)
|
||||
}
|
||||
var peer = PeerConfiguration(publicKey: publicKey)
|
||||
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)
|
||||
}
|
||||
// TODO(zx2c4): does the compiler optimize this away?
|
||||
var accumulator: UInt8 = 0
|
||||
for index in 0..<preSharedKey.count {
|
||||
accumulator |= preSharedKey[index]
|
||||
for index in 0..<preSharedKey.rawValue.count {
|
||||
accumulator |= preSharedKey.rawValue[index]
|
||||
}
|
||||
if accumulator != 0 {
|
||||
peer.preSharedKey = preSharedKey
|
||||
|
|
|
@ -110,9 +110,9 @@ class TunnelViewModel {
|
|||
scratchpad[field] = stringValue
|
||||
}
|
||||
if field == .privateKey {
|
||||
if stringValue.count == TunnelViewModel.keyLengthInBase64, let privateKey = Data(base64Key: stringValue), privateKey.count == TunnelConfiguration.keyLength {
|
||||
let publicKey = Curve25519.generatePublicKey(fromPrivateKey: privateKey).base64Key() ?? ""
|
||||
scratchpad[.publicKey] = publicKey
|
||||
if stringValue.count == TunnelViewModel.keyLengthInBase64,
|
||||
let privateKey = PrivateKey(base64Key: stringValue) {
|
||||
scratchpad[.publicKey] = privateKey.publicKey.base64Key
|
||||
} else {
|
||||
scratchpad.removeValue(forKey: .publicKey)
|
||||
}
|
||||
|
@ -129,8 +129,8 @@ class TunnelViewModel {
|
|||
private static func createScratchPad(from config: InterfaceConfiguration, name: String) -> [InterfaceField: String] {
|
||||
var scratchpad = [InterfaceField: String]()
|
||||
scratchpad[.name] = name
|
||||
scratchpad[.privateKey] = config.privateKey.base64Key() ?? ""
|
||||
scratchpad[.publicKey] = config.publicKey.base64Key() ?? ""
|
||||
scratchpad[.privateKey] = config.privateKey.base64Key
|
||||
scratchpad[.publicKey] = config.privateKey.publicKey.base64Key
|
||||
if !config.addresses.isEmpty {
|
||||
scratchpad[.addresses] = config.addresses.map { $0.stringRepresentation }.joined(separator: ", ")
|
||||
}
|
||||
|
@ -159,7 +159,7 @@ class TunnelViewModel {
|
|||
fieldsWithError.insert(.privateKey)
|
||||
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)
|
||||
return .error(tr("alertInvalidInterfaceMessagePrivateKeyInvalid"))
|
||||
}
|
||||
|
@ -252,12 +252,12 @@ class TunnelViewModel {
|
|||
var scratchpad = [PeerField: String]()
|
||||
var fieldsWithError = Set<PeerField>()
|
||||
var validatedConfiguration: PeerConfiguration?
|
||||
var publicKey: Data? {
|
||||
var publicKey: PublicKey? {
|
||||
if let validatedConfiguration = validatedConfiguration {
|
||||
return validatedConfiguration.publicKey
|
||||
}
|
||||
if let scratchPadPublicKey = scratchpad[.publicKey] {
|
||||
return Data(base64Key: scratchPadPublicKey)
|
||||
return PublicKey(base64Key: scratchPadPublicKey)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -302,10 +302,8 @@ class TunnelViewModel {
|
|||
|
||||
private static func createScratchPad(from config: PeerConfiguration) -> [PeerField: String] {
|
||||
var scratchpad = [PeerField: String]()
|
||||
if let publicKey = config.publicKey.base64Key() {
|
||||
scratchpad[.publicKey] = publicKey
|
||||
}
|
||||
if let preSharedKey = config.preSharedKey?.base64Key() {
|
||||
scratchpad[.publicKey] = config.publicKey.base64Key
|
||||
if let preSharedKey = config.preSharedKey?.base64Key {
|
||||
scratchpad[.preSharedKey] = preSharedKey
|
||||
}
|
||||
if !config.allowedIPs.isEmpty {
|
||||
|
@ -338,14 +336,14 @@ class TunnelViewModel {
|
|||
fieldsWithError.insert(.publicKey)
|
||||
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)
|
||||
return .error(tr("alertInvalidPeerMessagePublicKeyInvalid"))
|
||||
}
|
||||
var config = PeerConfiguration(publicKey: publicKey)
|
||||
var errorMessages = [String]()
|
||||
if let preSharedKeyString = scratchpad[.preSharedKey] {
|
||||
if let preSharedKey = Data(base64Key: preSharedKeyString), preSharedKey.count == TunnelConfiguration.keyLength {
|
||||
if let preSharedKey = PreSharedKey(base64Key: preSharedKeyString) {
|
||||
config.preSharedKey = preSharedKey
|
||||
} else {
|
||||
fieldsWithError.insert(.preSharedKey)
|
||||
|
@ -560,7 +558,7 @@ class TunnelViewModel {
|
|||
}
|
||||
|
||||
let peerPublicKeysArray = peerConfigurations.map { $0.publicKey }
|
||||
let peerPublicKeysSet = Set<Data>(peerPublicKeysArray)
|
||||
let peerPublicKeysSet = Set<PublicKey>(peerPublicKeysArray)
|
||||
if peerPublicKeysArray.count != peerPublicKeysSet.count {
|
||||
return .error(tr("alertInvalidPeerMessagePublicKeyDuplicated"))
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
import UIKit
|
||||
import WireGuardKit
|
||||
|
||||
protocol TunnelEditTableViewControllerDelegate: class {
|
||||
func tunnelSaved(tunnel: TunnelContainer)
|
||||
|
@ -214,7 +215,7 @@ extension TunnelEditTableViewController {
|
|||
cell.onTapped = { [weak self] in
|
||||
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),
|
||||
let publicKeyRow = self.interfaceFieldsBySection[indexPath.section].firstIndex(of: .publicKey) {
|
||||
let privateKeyIndex = IndexPath(row: privateKeyRow, section: indexPath.section)
|
||||
|
|
|
@ -108,27 +108,24 @@ class TunnelEditViewController: NSViewController {
|
|||
let tunnelConfiguration = tunnel.tunnelConfiguration!
|
||||
nameRow.value = tunnel.name
|
||||
textView.string = tunnelConfiguration.asWgQuickConfig()
|
||||
publicKeyRow.value = tunnelConfiguration.interface.publicKey.base64Key() ?? ""
|
||||
textView.privateKeyString = tunnelConfiguration.interface.privateKey.base64Key() ?? ""
|
||||
publicKeyRow.value = tunnelConfiguration.interface.privateKey.publicKey.base64Key
|
||||
textView.privateKeyString = tunnelConfiguration.interface.privateKey.base64Key
|
||||
let singlePeer = tunnelConfiguration.peers.count == 1 ? tunnelConfiguration.peers.first : nil
|
||||
updateExcludePrivateIPsVisibility(singlePeerAllowedIPs: singlePeer?.allowedIPs.map { $0.stringRepresentation })
|
||||
dnsServersAddedToAllowedIPs = excludePrivateIPsCheckbox.state == .on ? tunnelConfiguration.interface.dns.map { $0.stringRepresentation }.joined(separator: ", ") : nil
|
||||
} else {
|
||||
// Creating a new tunnel
|
||||
let privateKey = Curve25519.generatePrivateKey()
|
||||
let publicKey = Curve25519.generatePublicKey(fromPrivateKey: privateKey)
|
||||
let bootstrappingText = "[Interface]\nPrivateKey = \(privateKey.base64Key() ?? "")\n"
|
||||
publicKeyRow.value = publicKey.base64Key() ?? ""
|
||||
let privateKey = PrivateKey()
|
||||
let bootstrappingText = "[Interface]\nPrivateKey = \(privateKey.base64Key)\n"
|
||||
publicKeyRow.value = privateKey.publicKey.base64Key
|
||||
textView.string = bootstrappingText
|
||||
updateExcludePrivateIPsVisibility(singlePeerAllowedIPs: nil)
|
||||
dnsServersAddedToAllowedIPs = nil
|
||||
}
|
||||
privateKeyObservationToken = textView.observe(\.privateKeyString) { [weak publicKeyRow] textView, _ in
|
||||
if let privateKeyString = textView.privateKeyString,
|
||||
let privateKey = Data(base64Key: privateKeyString),
|
||||
privateKey.count == TunnelConfiguration.keyLength {
|
||||
let publicKey = Curve25519.generatePublicKey(fromPrivateKey: privateKey)
|
||||
publicKeyRow?.value = publicKey.base64Key() ?? ""
|
||||
let privateKey = PrivateKey(base64Key: privateKeyString) {
|
||||
publicKeyRow?.value = privateKey.publicKey.base64Key
|
||||
} else {
|
||||
publicKeyRow?.value = ""
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#include "x25519.h"
|
||||
#include "unzip.h"
|
||||
#include "zip.h"
|
||||
#include "ringlogger.h"
|
||||
|
|
|
@ -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 {
|
||||
let destinationPath = destinationURL.path
|
||||
|
@ -34,8 +36,8 @@ class ZipArchive {
|
|||
let fileName = input.fileName
|
||||
let contents = input.contents
|
||||
zipOpenNewFileInZip(zipFile, fileName.cString(using: .utf8), nil, nil, 0, nil, 0, nil, Z_DEFLATED, Z_DEFAULT_COMPRESSION)
|
||||
contents.withUnsafeUInt8Bytes { ptr -> Void in
|
||||
zipWriteInFileInZip(zipFile, UnsafeRawPointer(ptr), UInt32(contents.count))
|
||||
contents.withUnsafeBytes { rawBufferPointer -> Void in
|
||||
zipWriteInFileInZip(zipFile, rawBufferPointer.baseAddress, UInt32(contents.count))
|
||||
}
|
||||
zipCloseFileInZip(zipFile)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,16 +5,13 @@ import Foundation
|
|||
import Network
|
||||
|
||||
public struct InterfaceConfiguration {
|
||||
public var privateKey: Data
|
||||
public var privateKey: PrivateKey
|
||||
public var addresses = [IPAddressRange]()
|
||||
public var listenPort: UInt16?
|
||||
public var mtu: UInt16?
|
||||
public var dns = [DNSServer]()
|
||||
|
||||
public init(privateKey: Data) {
|
||||
if privateKey.count != TunnelConfiguration.keyLength {
|
||||
fatalError("Invalid private key")
|
||||
}
|
||||
public init(privateKey: PrivateKey) {
|
||||
self.privateKey = privateKey
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,9 +18,7 @@ class PacketTunnelSettingsGenerator {
|
|||
func endpointUapiConfiguration() -> String {
|
||||
var wgSettings = ""
|
||||
for (index, peer) in tunnelConfiguration.peers.enumerated() {
|
||||
if let publicKey = peer.publicKey.hexKey() {
|
||||
wgSettings.append("public_key=\(publicKey)\n")
|
||||
}
|
||||
wgSettings.append("public_key=\(peer.publicKey.hexKey)\n")
|
||||
if let endpoint = resolvedEndpoints[index]?.withReresolvedIP() {
|
||||
if case .name(_, _) = endpoint.host { assert(false, "Endpoint is not resolved") }
|
||||
wgSettings.append("endpoint=\(endpoint.stringRepresentation)\n")
|
||||
|
@ -31,9 +29,7 @@ class PacketTunnelSettingsGenerator {
|
|||
|
||||
func uapiConfiguration() -> String {
|
||||
var wgSettings = ""
|
||||
if let privateKey = tunnelConfiguration.interface.privateKey.hexKey() {
|
||||
wgSettings.append("private_key=\(privateKey)\n")
|
||||
}
|
||||
wgSettings.append("private_key=\(tunnelConfiguration.interface.privateKey.hexKey)\n")
|
||||
if let listenPort = tunnelConfiguration.interface.listenPort {
|
||||
wgSettings.append("listen_port=\(listenPort)\n")
|
||||
}
|
||||
|
@ -42,10 +38,8 @@ class PacketTunnelSettingsGenerator {
|
|||
}
|
||||
assert(tunnelConfiguration.peers.count == resolvedEndpoints.count)
|
||||
for (index, peer) in tunnelConfiguration.peers.enumerated() {
|
||||
if let publicKey = peer.publicKey.hexKey() {
|
||||
wgSettings.append("public_key=\(publicKey)\n")
|
||||
}
|
||||
if let preSharedKey = peer.preSharedKey?.hexKey() {
|
||||
wgSettings.append("public_key=\(peer.publicKey.hexKey)\n")
|
||||
if let preSharedKey = peer.preSharedKey?.hexKey {
|
||||
wgSettings.append("preshared_key=\(preSharedKey)\n")
|
||||
}
|
||||
if let endpoint = resolvedEndpoints[index]?.withReresolvedIP() {
|
||||
|
|
|
@ -4,16 +4,8 @@
|
|||
import Foundation
|
||||
|
||||
public struct PeerConfiguration {
|
||||
public var publicKey: Data
|
||||
public var preSharedKey: Data? {
|
||||
didSet(value) {
|
||||
if let value = value {
|
||||
if value.count != TunnelConfiguration.keyLength {
|
||||
fatalError("Invalid preshared key")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public var publicKey: PublicKey
|
||||
public var preSharedKey: PreSharedKey?
|
||||
public var allowedIPs = [IPAddressRange]()
|
||||
public var endpoint: Endpoint?
|
||||
public var persistentKeepAlive: UInt16?
|
||||
|
@ -21,11 +13,8 @@ public struct PeerConfiguration {
|
|||
public var txBytes: UInt64?
|
||||
public var lastHandshakeTime: Date?
|
||||
|
||||
public init(publicKey: Data) {
|
||||
public init(publicKey: PublicKey) {
|
||||
self.publicKey = publicKey
|
||||
if publicKey.count != TunnelConfiguration.keyLength {
|
||||
fatalError("Invalid public key")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,15 +8,13 @@ public final class TunnelConfiguration {
|
|||
public var interface: InterfaceConfiguration
|
||||
public let peers: [PeerConfiguration]
|
||||
|
||||
public static let keyLength = 32
|
||||
|
||||
public init(name: String?, interface: InterfaceConfiguration, peers: [PeerConfiguration]) {
|
||||
self.interface = interface
|
||||
self.peers = peers
|
||||
self.name = name
|
||||
|
||||
let peerPublicKeysArray = peers.map { $0.publicKey }
|
||||
let peerPublicKeysSet = Set<Data>(peerPublicKeysArray)
|
||||
let peerPublicKeysSet = Set<PublicKey>(peerPublicKeysArray)
|
||||
if peerPublicKeysArray.count != peerPublicKeysSet.count {
|
||||
fatalError("Two or more peers cannot have the same public key")
|
||||
}
|
||||
|
|
|
@ -2,3 +2,4 @@
|
|||
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
#include "../key.h"
|
||||
#include "../x25519.h"
|
||||
|
|
|
@ -112,3 +112,13 @@ bool key_from_hex(uint8_t key[static WG_KEY_LEN], const char *hex)
|
|||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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]);
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue