diff --git a/WireGuard/Shared/Model/TunnelConfiguration+WgQuickConfig.swift b/WireGuard/Shared/Model/TunnelConfiguration+WgQuickConfig.swift index d0c87e0..7fd65d6 100644 --- a/WireGuard/Shared/Model/TunnelConfiguration+WgQuickConfig.swift +++ b/WireGuard/Shared/Model/TunnelConfiguration+WgQuickConfig.swift @@ -112,7 +112,7 @@ extension TunnelConfiguration { } let peerPublicKeysArray = peerConfigurations.map { $0.publicKey } - let peerPublicKeysSet = Set(peerPublicKeysArray) + let peerPublicKeysSet = Set(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 diff --git a/WireGuard/WireGuard.xcodeproj/project.pbxproj b/WireGuard/WireGuard.xcodeproj/project.pbxproj index 8ab8858..de57709 100644 --- a/WireGuard/WireGuard.xcodeproj/project.pbxproj +++ b/WireGuard/WireGuard.xcodeproj/project.pbxproj @@ -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 = ""; }; 6F6483E6229293300075BA15 /* LaunchedAtLoginDetector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchedAtLoginDetector.swift; sourceTree = ""; }; 6F689999218043390012E523 /* WireGuard-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "WireGuard-Bridging-Header.h"; sourceTree = ""; }; - 6F6899A42180447E0012E523 /* x25519.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = x25519.h; sourceTree = ""; }; - 6F6899A52180447E0012E523 /* x25519.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = x25519.c; sourceTree = ""; }; - 6F6899A7218044FC0012E523 /* Curve25519.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Curve25519.swift; sourceTree = ""; }; 6F70E20D221058DF008BDFB4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = WireGuard/Base.lproj/InfoPlist.strings; sourceTree = ""; }; 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 = ""; }; @@ -482,16 +475,6 @@ path = Shared; sourceTree = ""; }; - 6F6899A32180445A0012E523 /* Crypto */ = { - isa = PBXGroup; - children = ( - 6F6899A52180447E0012E523 /* x25519.c */, - 6F6899A42180447E0012E523 /* x25519.h */, - 6F6899A7218044FC0012E523 /* Curve25519.swift */, - ); - path = Crypto; - sourceTree = ""; - }; 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 */, diff --git a/WireGuard/WireGuard/Crypto/Curve25519.swift b/WireGuard/WireGuard/Crypto/Curve25519.swift deleted file mode 100644 index 07341ef..0000000 --- a/WireGuard/WireGuard/Crypto/Curve25519.swift +++ /dev/null @@ -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) - } -} diff --git a/WireGuard/WireGuard/Tunnel/MockTunnels.swift b/WireGuard/WireGuard/Tunnel/MockTunnels.swift index f04e929..1ffa99c 100644 --- a/WireGuard/WireGuard/Tunnel/MockTunnels.swift +++ b/WireGuard/WireGuard/Tunnel/MockTunnels.swift @@ -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)!] diff --git a/WireGuard/WireGuard/Tunnel/TunnelConfiguration+UapiConfig.swift b/WireGuard/WireGuard/Tunnel/TunnelConfiguration+UapiConfig.swift index 18e478e..fcd6a31 100644 --- a/WireGuard/WireGuard/Tunnel/TunnelConfiguration+UapiConfig.swift +++ b/WireGuard/WireGuard/Tunnel/TunnelConfiguration+UapiConfig.swift @@ -68,7 +68,7 @@ extension TunnelConfiguration { } let peerPublicKeysArray = peerConfigurations.map { $0.publicKey } - let peerPublicKeysSet = Set(peerPublicKeysArray) + let peerPublicKeysSet = Set(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.. [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() 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(peerPublicKeysArray) + let peerPublicKeysSet = Set(peerPublicKeysArray) if peerPublicKeysArray.count != peerPublicKeysSet.count { return .error(tr("alertInvalidPeerMessagePublicKeyDuplicated")) } diff --git a/WireGuard/WireGuard/UI/iOS/ViewController/TunnelEditTableViewController.swift b/WireGuard/WireGuard/UI/iOS/ViewController/TunnelEditTableViewController.swift index e9c0995..ecad2f6 100644 --- a/WireGuard/WireGuard/UI/iOS/ViewController/TunnelEditTableViewController.swift +++ b/WireGuard/WireGuard/UI/iOS/ViewController/TunnelEditTableViewController.swift @@ -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) diff --git a/WireGuard/WireGuard/UI/macOS/ViewController/TunnelEditViewController.swift b/WireGuard/WireGuard/UI/macOS/ViewController/TunnelEditViewController.swift index de2423e..97eaf8f 100644 --- a/WireGuard/WireGuard/UI/macOS/ViewController/TunnelEditViewController.swift +++ b/WireGuard/WireGuard/UI/macOS/ViewController/TunnelEditViewController.swift @@ -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 = "" } diff --git a/WireGuard/WireGuard/WireGuard-Bridging-Header.h b/WireGuard/WireGuard/WireGuard-Bridging-Header.h index 1cd98ee..955412e 100644 --- a/WireGuard/WireGuard/WireGuard-Bridging-Header.h +++ b/WireGuard/WireGuard/WireGuard-Bridging-Header.h @@ -1,4 +1,3 @@ -#include "x25519.h" #include "unzip.h" #include "zip.h" #include "ringlogger.h" diff --git a/WireGuard/WireGuard/ZipArchive/ZipArchive.swift b/WireGuard/WireGuard/ZipArchive/ZipArchive.swift index c946e24..9c2f634 100644 --- a/WireGuard/WireGuard/ZipArchive/ZipArchive.swift +++ b/WireGuard/WireGuard/ZipArchive/ZipArchive.swift @@ -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) } diff --git a/WireGuardKit/Sources/WireGuardKit/Data+KeyEncoding.swift b/WireGuardKit/Sources/WireGuardKit/Data+KeyEncoding.swift deleted file mode 100644 index 5c7aee9..0000000 --- a/WireGuardKit/Sources/WireGuardKit/Data+KeyEncoding.swift +++ /dev/null @@ -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(_ body: (UnsafePointer) -> 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(_ body: (UnsafeMutablePointer) -> 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(_ body: (UnsafeMutablePointer) -> 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 - } - } -} diff --git a/WireGuardKit/Sources/WireGuardKit/InterfaceConfiguration.swift b/WireGuardKit/Sources/WireGuardKit/InterfaceConfiguration.swift index 16a9046..db84e71 100644 --- a/WireGuardKit/Sources/WireGuardKit/InterfaceConfiguration.swift +++ b/WireGuardKit/Sources/WireGuardKit/InterfaceConfiguration.swift @@ -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 } } diff --git a/WireGuardKit/Sources/WireGuardKit/PacketTunnelSettingsGenerator.swift b/WireGuardKit/Sources/WireGuardKit/PacketTunnelSettingsGenerator.swift index c1cd3f7..5922b2c 100644 --- a/WireGuardKit/Sources/WireGuardKit/PacketTunnelSettingsGenerator.swift +++ b/WireGuardKit/Sources/WireGuardKit/PacketTunnelSettingsGenerator.swift @@ -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() { diff --git a/WireGuardKit/Sources/WireGuardKit/PeerConfiguration.swift b/WireGuardKit/Sources/WireGuardKit/PeerConfiguration.swift index 4d92dc6..f11b473 100644 --- a/WireGuardKit/Sources/WireGuardKit/PeerConfiguration.swift +++ b/WireGuardKit/Sources/WireGuardKit/PeerConfiguration.swift @@ -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") - } } } diff --git a/WireGuardKit/Sources/WireGuardKit/PrivateKey.swift b/WireGuardKit/Sources/WireGuardKit/PrivateKey.swift new file mode 100644 index 0000000..48dc3eb --- /dev/null +++ b/WireGuardKit/Sources/WireGuardKit/PrivateKey.swift @@ -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) + ) + } + } + } +} diff --git a/WireGuardKit/Sources/WireGuardKit/TunnelConfiguration.swift b/WireGuardKit/Sources/WireGuardKit/TunnelConfiguration.swift index b1ca442..dad3484 100644 --- a/WireGuardKit/Sources/WireGuardKit/TunnelConfiguration.swift +++ b/WireGuardKit/Sources/WireGuardKit/TunnelConfiguration.swift @@ -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(peerPublicKeysArray) + let peerPublicKeysSet = Set(peerPublicKeysArray) if peerPublicKeysArray.count != peerPublicKeysSet.count { fatalError("Two or more peers cannot have the same public key") } diff --git a/WireGuardKit/Sources/WireGuardKitCTarget/include/WireGuardKitCTarget.h b/WireGuardKit/Sources/WireGuardKitCTarget/include/WireGuardKitCTarget.h index f079501..30a24e4 100644 --- a/WireGuardKit/Sources/WireGuardKitCTarget/include/WireGuardKitCTarget.h +++ b/WireGuardKit/Sources/WireGuardKitCTarget/include/WireGuardKitCTarget.h @@ -2,3 +2,4 @@ // Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. #include "../key.h" +#include "../x25519.h" diff --git a/WireGuardKit/Sources/WireGuardKitCTarget/key.c b/WireGuardKit/Sources/WireGuardKitCTarget/key.c index 6c64443..140f278 100644 --- a/WireGuardKit/Sources/WireGuardKitCTarget/key.c +++ b/WireGuardKit/Sources/WireGuardKitCTarget/key.c @@ -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); +} diff --git a/WireGuardKit/Sources/WireGuardKitCTarget/key.h b/WireGuardKit/Sources/WireGuardKitCTarget/key.h index bd22a94..149e4ed 100644 --- a/WireGuardKit/Sources/WireGuardKitCTarget/key.h +++ b/WireGuardKit/Sources/WireGuardKitCTarget/key.h @@ -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 diff --git a/WireGuard/WireGuard/Crypto/x25519.c b/WireGuardKit/Sources/WireGuardKitCTarget/x25519.c similarity index 100% rename from WireGuard/WireGuard/Crypto/x25519.c rename to WireGuardKit/Sources/WireGuardKitCTarget/x25519.c diff --git a/WireGuard/WireGuard/Crypto/x25519.h b/WireGuardKit/Sources/WireGuardKitCTarget/x25519.h similarity index 100% rename from WireGuard/WireGuard/Crypto/x25519.h rename to WireGuardKit/Sources/WireGuardKitCTarget/x25519.h