From fa1cd80fc81ba13678c1b136fbaafb54622ffda7 Mon Sep 17 00:00:00 2001 From: Hatter Jiang Date: Sat, 9 Dec 2023 10:45:23 +0800 Subject: [PATCH] feat: secure enclave --- .gitignore | 1 + Cargo.lock | 10 +++++ Cargo.toml | 6 ++- build.rs | 11 +++++ swift-lib/Package.swift | 30 +++++++++++++ swift-lib/src/lib.swift | 94 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 build.rs create mode 100644 swift-lib/Package.swift create mode 100644 swift-lib/src/lib.swift diff --git a/.gitignore b/.gitignore index 4ac1ac2..030576c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.build/ _tinyencrypt_config-rs.json *.tinyenc # ---> Rust diff --git a/Cargo.lock b/Cargo.lock index 0e277e8..311505a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1550,6 +1550,15 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +[[package]] +name = "swift-rs" +version = "1.0.6" +dependencies = [ + "base64", + "serde", + "serde_json", +] + [[package]] name = "syn" version = "1.0.109" @@ -1715,6 +1724,7 @@ dependencies = [ "serde", "serde_json", "simpledateformat", + "swift-rs", "tabled", "x25519-dalek", "x509-parser", diff --git a/Cargo.toml b/Cargo.toml index 2a14a0b..ed89e8b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ repository = "https://git.hatter.ink/hatter/tiny-encrypt-rs" default = ["decrypt", "macos", "secure-enclave"] decrypt = ["openpgp-card", "openpgp-card-pcsc", "yubikey"] macos = ["security-framework"] -secure-enclave = ["macos"] +secure-enclave = ["macos", "swift-rs"] [dependencies] aes-gcm-stream = "0.2" @@ -43,6 +43,10 @@ x25519-dalek = { version = "2.0", features = ["static_secrets", "getrandom"] } x509-parser = "0.15" yubikey = { version = "0.8", features = ["untested"], optional = true } zeroize = "1.7" +swift-rs = { path = "swift-rs", optional = true } + +[build-dependencies] +swift-rs = { path = "swift-rs", features = ["build"], optional = true } [patch.crates-io] rust-crypto = { git = "https://github.com/jht5945/rust-crypto.git" } diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..05d9a0e --- /dev/null +++ b/build.rs @@ -0,0 +1,11 @@ +#[cfg(feature = "secure-enclave")] +use swift_rs::SwiftLinker; + +fn main() { + // Ensure this matches the versions set in your `Package.swift` file. + #[cfg(feature = "secure-enclave")] + SwiftLinker::new("10.15") + .with_ios("11") + .with_package("swift-lib", "./swift-lib/") + .link(); +} \ No newline at end of file diff --git a/swift-lib/Package.swift b/swift-lib/Package.swift new file mode 100644 index 0000000..ab35b13 --- /dev/null +++ b/swift-lib/Package.swift @@ -0,0 +1,30 @@ +// swift-tools-version:5.3 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "swift-lib", + platforms: [ + .macOS(.v10_15), // macOS Catalina. Earliest version that is officially supported by Apple. + ], + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "swift-lib", + type: .static, + targets: ["swift-lib"]), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + .package(name: "SwiftRs", path: "../swift-rs") + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "swift-lib", + dependencies: [.product(name: "SwiftRs", package: "SwiftRs")], + path: "src") + ] +) \ No newline at end of file diff --git a/swift-lib/src/lib.swift b/swift-lib/src/lib.swift new file mode 100644 index 0000000..baaa3bc --- /dev/null +++ b/swift-lib/src/lib.swift @@ -0,0 +1,94 @@ +import SwiftRs +import AppKit + +@_cdecl("get_file_thumbnail_base64") +func getFileThumbnailBase64(path: SRString) -> SRString { + let path = path.toString(); + + let image = NSWorkspace.shared.icon(forFile: path) + let bitmap = NSBitmapImageRep(data: image.tiffRepresentation!)!.representation(using: .png, properties: [:])! + + return SRString(bitmap.base64EncodedString()) +} + +class Volume: NSObject { + var name: SRString + var path: SRString + var total_capacity: Int + var available_capacity: Int + var is_removable: Bool + var is_ejectable: Bool + var is_root_filesystem: Bool + + public init(name: String, path: String, total_capacity: Int, available_capacity: Int, is_removable: Bool, is_ejectable: Bool, is_root_filesystem: Bool) { + self.name = SRString(name); + self.path = SRString(path); + self.total_capacity = total_capacity + self.available_capacity = available_capacity + self.is_removable = is_removable + self.is_ejectable = is_ejectable + self.is_root_filesystem = is_root_filesystem + } +} + +@_cdecl("get_mounts") +func getMounts() -> SRObjectArray { + let keys: [URLResourceKey] = [ + .volumeNameKey, + .volumeIsRemovableKey, + .volumeIsEjectableKey, + .volumeTotalCapacityKey, + .volumeAvailableCapacityKey, + .volumeIsRootFileSystemKey, + ] + + let paths = autoreleasepool { + FileManager().mountedVolumeURLs(includingResourceValuesForKeys: keys, options: []) + } + + var validMounts: [Volume] = [] + + if let urls = paths { + autoreleasepool { + for url in urls { + let components = url.pathComponents + if components.count == 1 || components.count > 1 + && components[1] == "Volumes" + { + let metadata = try? url.promisedItemResourceValues(forKeys: Set(keys)) + + let volume = Volume( + name: metadata?.volumeName ?? "", + path: url.path, + total_capacity: metadata?.volumeTotalCapacity ?? 0, + available_capacity: metadata?.volumeAvailableCapacity ?? 0, + is_removable: metadata?.volumeIsRemovable ?? false, + is_ejectable: metadata?.volumeIsEjectable ?? false, + is_root_filesystem: metadata?.volumeIsRootFileSystem ?? false + ) + + + validMounts.append(volume) + } + } + } + } + + return SRObjectArray(validMounts) +} + +class Test: NSObject { + var null: Bool + + public init(_ null: Bool) + { + self.null = null; + } +} + +@_cdecl("return_nullable") +func returnNullable(null: Bool) -> Test? { + if (null == true) { return nil } + + return Test(null) +} \ No newline at end of file