}
let peerPublicKeysArray = peerConfigurations.map { $0.publicKey }
- let peerPublicKeysSet = Set<Data>(peerPublicKeysArray)
+ let peerPublicKeysSet = Set<PublicKey>(peerPublicKeysArray)
if peerPublicKeysArray.count != peerPublicKeysSet.count {
throw ParseError.multiplePeersWithSamePublicKey
}
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")
}
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 {
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)
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
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, ); }; };
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 */; };
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>"; };
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 = (
isa = PBXGroup;
children = (
6F919ED3218C65C50023B400 /* Resources */,
- 6F6899A32180445A0012E523 /* Crypto */,
6F7774DD217181B1006A79B3 /* UI */,
6F7774ED21722D0C006A79B3 /* Tunnel */,
6FDEF7E72186320E00D8FBF6 /* ZipArchive */,
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 */,
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 */,
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 */,
+++ /dev/null
-// 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)
- }
-}
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)!]
}
let peerPublicKeysArray = peerConfigurations.map { $0.publicKey }
- let peerPublicKeysSet = Set<Data>(peerPublicKeysArray)
+ let peerPublicKeysSet = Set<PublicKey>(peerPublicKeysArray)
if peerPublicKeysArray.count != peerPublicKeysSet.count {
throw ParseError.multiplePeersWithSamePublicKey
}
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)
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
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)
}
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: ", ")
}
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"))
}
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
}
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 {
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)
}
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"))
}
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
import UIKit
+import WireGuardKit
protocol TunnelEditTableViewControllerDelegate: class {
func tunnelSaved(tunnel: TunnelContainer)
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)
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 = ""
}
-#include "x25519.h"
#include "unzip.h"
#include "zip.h"
#include "ringlogger.h"
}
}
-class ZipArchive {
+enum ZipArchive {}
+
+extension ZipArchive {
static func archive(inputs: [(fileName: String, contents: Data)], to destinationURL: URL) throws {
let destinationPath = destinationURL.path
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)
}
+++ /dev/null
-// 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
- }
- }
-}
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
}
}
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")
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")
}
}
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() {
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?
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")
- }
}
}
--- /dev/null
+// 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)
+ )
+ }
+ }
+ }
+}
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")
}
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
#include "../key.h"
+#include "../x25519.h"
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);
+}
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