diff --git a/WireGuard.xcodeproj/project.pbxproj b/WireGuard.xcodeproj/project.pbxproj index e731b4e..18b93d3 100644 --- a/WireGuard.xcodeproj/project.pbxproj +++ b/WireGuard.xcodeproj/project.pbxproj @@ -33,6 +33,8 @@ 4A61D83520D98D25006C7A76 /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A61D83420D98D25006C7A76 /* NetworkExtension.framework */; }; 4A8AABD820B6A79100B6D8C1 /* UITableView+WireGuard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A8AABD720B6A79100B6D8C1 /* UITableView+WireGuard.swift */; }; 4AADEA2B212616F7008C24FD /* String+Arrays.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FA1D50F2124D80C00DBA2E6 /* String+Arrays.swift */; }; + 4ABFFEA0212D39A000107136 /* x25519.c in Sources */ = {isa = PBXBuildFile; fileRef = 4ABFFE9F212D39A000107136 /* x25519.c */; }; + 4ABFFEA3212D3C8300107136 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4ABFFEA2212D3C8300107136 /* Security.framework */; }; 4AC086832120B9F900CEE5ED /* ProviderConfigurationKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AC086822120B9F900CEE5ED /* ProviderConfigurationKeys.swift */; }; 4AC086852120BCB500CEE5ED /* ProviderConfigurationKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AC086822120B9F900CEE5ED /* ProviderConfigurationKeys.swift */; }; 4AC086862120BD5800CEE5ED /* PacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A61D82820D98CE2006C7A76 /* PacketTunnelProvider.swift */; }; @@ -115,6 +117,10 @@ 4A61D83320D98D07006C7A76 /* WireGuard.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = WireGuard.entitlements; sourceTree = ""; }; 4A61D83420D98D25006C7A76 /* NetworkExtension.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NetworkExtension.framework; path = System/Library/Frameworks/NetworkExtension.framework; sourceTree = SDKROOT; }; 4A8AABD720B6A79100B6D8C1 /* UITableView+WireGuard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITableView+WireGuard.swift"; sourceTree = ""; }; + 4ABFFE9D212D399F00107136 /* WireGuard-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "WireGuard-Bridging-Header.h"; sourceTree = ""; }; + 4ABFFE9E212D39A000107136 /* x25519.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = x25519.h; sourceTree = ""; }; + 4ABFFE9F212D39A000107136 /* x25519.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = x25519.c; sourceTree = ""; }; + 4ABFFEA2212D3C8300107136 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; 4AC086822120B9F900CEE5ED /* ProviderConfigurationKeys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProviderConfigurationKeys.swift; sourceTree = ""; }; 4AC5462D2116306F00749D21 /* Tunnel+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Tunnel+Extension.swift"; sourceTree = ""; }; 4AD0900120DC4171000E9CF5 /* libwg-go.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libwg-go.a"; sourceTree = ""; }; @@ -138,6 +144,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 4ABFFEA3212D3C8300107136 /* Security.framework in Frameworks */, 48CF751B34E9703133F1B1AF /* Pods_WireGuard.framework in Frameworks */, 4A61D83520D98D25006C7A76 /* NetworkExtension.framework in Frameworks */, ); @@ -190,6 +197,7 @@ 4A4BACE420B5F1BF00F12B28 /* WireGuard */ = { isa = PBXGroup; children = ( + 4ABFFEA1212D39CA00107136 /* Crypto */, 4A61D83320D98D07006C7A76 /* WireGuard.entitlements */, 4A4BAD1420B5F8C000F12B28 /* Models */, 4A4BAD1120B5F7A000F12B28 /* ViewControllers */, @@ -200,6 +208,7 @@ 4A4BACEC20B5F1C100F12B28 /* Assets.xcassets */, 4A4BACEE20B5F1C100F12B28 /* LaunchScreen.storyboard */, 4A4BACF120B5F1C100F12B28 /* Info.plist */, + 4ABFFE9D212D399F00107136 /* WireGuard-Bridging-Header.h */, 4AEAC32A20F14BA9007B67AB /* Log.swift */, ); path = WireGuard; @@ -276,6 +285,15 @@ path = WireGuardNetworkExtension; sourceTree = ""; }; + 4ABFFEA1212D39CA00107136 /* Crypto */ = { + isa = PBXGroup; + children = ( + 4ABFFE9F212D39A000107136 /* x25519.c */, + 4ABFFE9E212D39A000107136 /* x25519.h */, + ); + path = Crypto; + sourceTree = ""; + }; 4AC086812120B9E600CEE5ED /* Shared */ = { isa = PBXGroup; children = ( @@ -315,6 +333,7 @@ A447093459F091F4358E843F /* Frameworks */ = { isa = PBXGroup; children = ( + 4ABFFEA2212D3C8300107136 /* Security.framework */, 4A61D83420D98D25006C7A76 /* NetworkExtension.framework */, 861983CAE8FDC13BC83E7E04 /* Pods_WireGuard.framework */, ); @@ -566,6 +585,7 @@ 4AC5462E2116306F00749D21 /* Tunnel+Extension.swift in Sources */, 5FCC4343212B3092009A9C58 /* QRScanViewController.swift in Sources */, 4A4BAD0E20B5F6C300F12B28 /* Coordinator.swift in Sources */, + 4ABFFEA0212D39A000107136 /* x25519.c in Sources */, 4A4BA6D820B73CBA00223AB8 /* TunnelConfigurationTableViewController.swift in Sources */, 4A4BAD2020B6026900F12B28 /* Peer+CoreDataProperties.swift in Sources */, 5FA1D4CD2124A05C00DBA2E6 /* Interface+Extension.swift in Sources */, @@ -755,6 +775,7 @@ buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = WireGuard/WireGuard.entitlements; CODE_SIGN_STYLE = Manual; DEVELOPMENT_TEAM = 67JZJ7TWU3; @@ -767,6 +788,8 @@ PRODUCT_BUNDLE_IDENTIFIER = com.wireguard.ios.WireGuard; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "WireGuard/WireGuard-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = "1,2"; }; @@ -778,6 +801,7 @@ buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = WireGuard/WireGuard.entitlements; CODE_SIGN_STYLE = Manual; DEVELOPMENT_TEAM = ""; @@ -790,6 +814,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.wireguard.ios.WireGuard; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "WireGuard/WireGuard-Bridging-Header.h"; SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = "1,2"; }; diff --git a/WireGuard/Base.lproj/Main.storyboard b/WireGuard/Base.lproj/Main.storyboard index b160dfc..42a8dfe 100644 --- a/WireGuard/Base.lproj/Main.storyboard +++ b/WireGuard/Base.lproj/Main.storyboard @@ -171,6 +171,9 @@ diff --git a/WireGuard/Crypto/x25519.c b/WireGuard/Crypto/x25519.c new file mode 100644 index 0000000..b198ae0 --- /dev/null +++ b/WireGuard/Crypto/x25519.c @@ -0,0 +1,177 @@ +/* SPDX-License-Identifier: GPL-2.0+ + * + * Copyright (C) 2015-2018 Jason A. Donenfeld . All Rights Reserved. + * + * Curve25519 ECDH functions, based on TweetNaCl but cleaned up. + */ + +#include +#include +#include + +#include "x25519.h" + +typedef int64_t fe[16]; + +static inline void carry(fe o) +{ + int i; + + for (i = 0; i < 16; ++i) { + o[(i + 1) % 16] += (i == 15 ? 38 : 1) * (o[i] >> 16); + o[i] &= 0xffff; + } +} + +static inline void cswap(fe p, fe q, int b) +{ + int i; + int64_t t, c = ~(b - 1); + + for (i = 0; i < 16; ++i) { + t = c & (p[i] ^ q[i]); + p[i] ^= t; + q[i] ^= t; + } +} + +static inline void pack(uint8_t *o, const fe n) +{ + int i, j, b; + fe m, t; + + memcpy(t, n, sizeof(t)); + carry(t); + carry(t); + carry(t); + for (j = 0; j < 2; ++j) { + m[0] = t[0] - 0xffed; + for (i = 1; i < 15; ++i) { + m[i] = t[i] - 0xffff - ((m[i - 1] >> 16) & 1); + m[i - 1] &= 0xffff; + } + m[15] = t[15] - 0x7fff - ((m[14] >> 16) & 1); + b = (m[15] >> 16) & 1; + m[14] &= 0xffff; + cswap(t, m, 1 - b); + } + for (i = 0; i < 16; ++i) { + o[2 * i] = t[i] & 0xff; + o[2 * i + 1] = t[i] >> 8; + } +} + +static inline void unpack(fe o, const uint8_t *n) +{ + int i; + + for (i = 0; i < 16; ++i) + o[i] = n[2 * i] + ((int64_t)n[2 * i + 1] << 8); + o[15] &= 0x7fff; +} + +static inline void add(fe o, const fe a, const fe b) +{ + int i; + + for (i = 0; i < 16; ++i) + o[i] = a[i] + b[i]; +} + +static inline void subtract(fe o, const fe a, const fe b) +{ + int i; + + for (i = 0; i < 16; ++i) + o[i] = a[i] - b[i]; +} + +static inline void multmod(fe o, const fe a, const fe b) +{ + int i, j; + int64_t t[31] = { 0 }; + + for (i = 0; i < 16; ++i) { + for (j = 0; j < 16; ++j) + t[i + j] += a[i] * b[j]; + } + for (i = 0; i < 15; ++i) + t[i] += 38 * t[i + 16]; + memcpy(o, t, sizeof(fe)); + carry(o); + carry(o); +} + +static inline void invert(fe o, const fe i) +{ + fe c; + int a; + + memcpy(c, i, sizeof(c)); + for (a = 253; a >= 0; --a) { + multmod(c, c, c); + if (a != 2 && a != 4) + multmod(c, c, i); + } + memcpy(o, c, sizeof(fe)); +} + +static void curve25519_shared_secret(uint8_t shared_secret[32], const uint8_t private_key[32], const uint8_t public_key[32]) +{ + static const fe a24 = { 0xdb41, 1 }; + uint8_t z[32]; + int64_t r; + int i; + fe a = { 1 }, b, c = { 0 }, d = { 1 }, e, f, x; + + memcpy(z, private_key, sizeof(z)); + + z[31] = (z[31] & 127) | 64; + z[0] &= 248; + + unpack(x, public_key); + memcpy(b, x, sizeof(b)); + + for (i = 254; i >= 0; --i) { + r = (z[i >> 3] >> (i & 7)) & 1; + cswap(a, b, r); + cswap(c, d, r); + add(e, a, c); + subtract(a, a, c); + add(c, b, d); + subtract(b, b, d); + multmod(d, e, e); + multmod(f, a, a); + multmod(a, c, a); + multmod(c, b, e); + add(e, a, c); + subtract(a, a, c); + multmod(b, a, a); + subtract(c, d, f); + multmod(a, c, a24); + add(a, a, d); + multmod(c, c, a); + multmod(a, d, f); + multmod(d, b, x); + multmod(b, e, e); + cswap(a, b, r); + cswap(c, d, r); + } + invert(c, c); + multmod(a, a, c); + pack(shared_secret, a); +} + +void curve25519_derive_public_key(uint8_t public_key[32], const uint8_t private_key[32]) +{ + static const uint8_t basepoint[32] = { 9 }; + + curve25519_shared_secret(public_key, private_key, basepoint); +} + +void curve25519_generate_private_key(uint8_t private_key[32]) +{ + CCRandomGenerateBytes(private_key, 32); + private_key[31] = (private_key[31] & 127) | 64; + private_key[0] &= 248; +} diff --git a/x25519/x25519.h b/WireGuard/Crypto/x25519.h similarity index 100% rename from x25519/x25519.h rename to WireGuard/Crypto/x25519.h diff --git a/WireGuard/ViewControllers/TunnelConfigurationTableViewController.swift b/WireGuard/ViewControllers/TunnelConfigurationTableViewController.swift index 8aff110..77141fe 100644 --- a/WireGuard/ViewControllers/TunnelConfigurationTableViewController.swift +++ b/WireGuard/ViewControllers/TunnelConfigurationTableViewController.swift @@ -79,6 +79,7 @@ class TunnelConfigurationTableViewController: UITableViewController { case 0: let cell = tableView.dequeueReusableCell(type: InterfaceTableViewCell.self, for: indexPath) cell.model = tunnel.interface + cell.delegate = self return cell case 1: let cell = tableView.dequeueReusableCell(type: PeerTableViewCell.self, for: indexPath) @@ -141,6 +142,38 @@ extension TunnelConfigurationTableViewController: PeerTableViewCellDelegate { } } +extension TunnelConfigurationTableViewController: InterfaceTableViewCellDelegate { + func generateKeys() { + if let moc = tunnel.managedObjectContext { + moc.perform { + var privateKey = Data(count: 32) + privateKey.withUnsafeMutableBytes { (mutableBytes) -> Void in + curve25519_generate_private_key(mutableBytes) + } + + self.tunnel.interface?.privateKey = privateKey.base64EncodedString() + + if let peers = self.tunnel.peers?.array as? [Peer] { + peers.forEach { + var publicKey = Data(count: 32) + privateKey.withUnsafeBytes({ (privateKeyBytes) -> Void in + publicKey.withUnsafeMutableBytes({ (mutableBytes) -> Void in + curve25519_derive_public_key(mutableBytes, privateKeyBytes) + }) + }) + $0.publicKey = publicKey.base64EncodedString() + } + } + } + } + self.tableView.reloadData() + } +} + +protocol InterfaceTableViewCellDelegate: class { + func generateKeys() +} + class InterfaceTableViewCell: UITableViewCell { var model: Interface! { didSet { @@ -153,16 +186,22 @@ class InterfaceTableViewCell: UITableViewCell { } } + weak var delegate: InterfaceTableViewCellDelegate? + @IBOutlet weak var nameField: UITextField! @IBOutlet weak var addressesField: UITextField! @IBOutlet weak var privateKeyField: UITextField! - @IBOutlet weak var publicKeyField: UITextField! @IBOutlet weak var listenPortField: UITextField! @IBOutlet weak var dnsField: UITextField! @IBOutlet weak var mtuField: UITextField! + + @IBAction func generateTapped(_ sender: Any) { + delegate?.generateKeys() + } } extension InterfaceTableViewCell: UITextFieldDelegate { + @IBAction func textfieldDidChange(_ sender: UITextField) { let string = sender.text diff --git a/WireGuard/WireGuard-Bridging-Header.h b/WireGuard/WireGuard-Bridging-Header.h new file mode 100644 index 0000000..893b5eb --- /dev/null +++ b/WireGuard/WireGuard-Bridging-Header.h @@ -0,0 +1,5 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + +#include "x25519.h" diff --git a/x25519/x25519.c b/x25519/x25519.c deleted file mode 100644 index 8ce6027..0000000 --- a/x25519/x25519.c +++ /dev/null @@ -1,177 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ - * - * Copyright (C) 2015-2018 Jason A. Donenfeld . All Rights Reserved. - * - * Curve25519 ECDH functions, based on TweetNaCl but cleaned up. - */ - -#include -#include -#include - -#include "x25519.h" - -typedef int64_t fe[16]; - -static inline void carry(fe o) -{ - int i; - - for (i = 0; i < 16; ++i) { - o[(i + 1) % 16] += (i == 15 ? 38 : 1) * (o[i] >> 16); - o[i] &= 0xffff; - } -} - -static inline void cswap(fe p, fe q, int b) -{ - int i; - int64_t t, c = ~(b - 1); - - for (i = 0; i < 16; ++i) { - t = c & (p[i] ^ q[i]); - p[i] ^= t; - q[i] ^= t; - } -} - -static inline void pack(uint8_t *o, const fe n) -{ - int i, j, b; - fe m, t; - - memcpy(t, n, sizeof(t)); - carry(t); - carry(t); - carry(t); - for (j = 0; j < 2; ++j) { - m[0] = t[0] - 0xffed; - for (i = 1; i < 15; ++i) { - m[i] = t[i] - 0xffff - ((m[i - 1] >> 16) & 1); - m[i - 1] &= 0xffff; - } - m[15] = t[15] - 0x7fff - ((m[14] >> 16) & 1); - b = (m[15] >> 16) & 1; - m[14] &= 0xffff; - cswap(t, m, 1 - b); - } - for (i = 0; i < 16; ++i) { - o[2 * i] = t[i] & 0xff; - o[2 * i + 1] = t[i] >> 8; - } -} - -static inline void unpack(fe o, const uint8_t *n) -{ - int i; - - for (i = 0; i < 16; ++i) - o[i] = n[2 * i] + ((int64_t)n[2 * i + 1] << 8); - o[15] &= 0x7fff; -} - -static inline void add(fe o, const fe a, const fe b) -{ - int i; - - for (i = 0; i < 16; ++i) - o[i] = a[i] + b[i]; -} - -static inline void subtract(fe o, const fe a, const fe b) -{ - int i; - - for (i = 0; i < 16; ++i) - o[i] = a[i] - b[i]; -} - -static inline void multmod(fe o, const fe a, const fe b) -{ - int i, j; - int64_t t[31] = { 0 }; - - for (i = 0; i < 16; ++i) { - for (j = 0; j < 16; ++j) - t[i + j] += a[i] * b[j]; - } - for (i = 0; i < 15; ++i) - t[i] += 38 * t[i + 16]; - memcpy(o, t, sizeof(fe)); - carry(o); - carry(o); -} - -static inline void invert(fe o, const fe i) -{ - fe c; - int a; - - memcpy(c, i, sizeof(c)); - for (a = 253; a >= 0; --a) { - multmod(c, c, c); - if (a != 2 && a != 4) - multmod(c, c, i); - } - memcpy(o, c, sizeof(fe)); -} - -static void curve25519_shared_secret(uint8_t shared_secret[32], const uint8_t private_key[32], const uint8_t public_key[32]) -{ - static const fe a24 = { 0xdb41, 1 }; - uint8_t z[32]; - int64_t r; - int i; - fe a = { 1 }, b, c = { 0 }, d = { 1 }, e, f, x; - - memcpy(z, private_key, sizeof(z)); - - z[31] = (z[31] & 127) | 64; - z[0] &= 248; - - unpack(x, public_key); - memcpy(b, x, sizeof(b)); - - for (i = 254; i >= 0; --i) { - r = (z[i >> 3] >> (i & 7)) & 1; - cswap(a, b, r); - cswap(c, d, r); - add(e, a, c); - subtract(a, a, c); - add(c, b, d); - subtract(b, b, d); - multmod(d, e, e); - multmod(f, a, a); - multmod(a, c, a); - multmod(c, b, e); - add(e, a, c); - subtract(a, a, c); - multmod(b, a, a); - subtract(c, d, f); - multmod(a, c, a24); - add(a, a, d); - multmod(c, c, a); - multmod(a, d, f); - multmod(d, b, x); - multmod(b, e, e); - cswap(a, b, r); - cswap(c, d, r); - } - invert(c, c); - multmod(a, a, c); - pack(shared_secret, a); -} - -void curve25519_derive_public_key(uint8_t public_key[32], const uint8_t private_key[32]) -{ - static const uint8_t basepoint[32] = { 9 }; - - curve25519_shared_secret(public_key, private_key, basepoint); -} - -void curve25519_generate_private_key(uint8_t private_key[32]) -{ - getentropy(private_key, 32); - private_key[31] = (private_key[31] & 127) | 64; - private_key[0] &= 248; -}