@@ -3,6 +3,46 @@ use tauri::{plugin::PluginApi, AppHandle, Runtime};
33
44use crate :: models:: * ;
55
6+ mod codesign {
7+ use objc2_security:: { kSecCSCheckAllArchitectures, kSecCSCheckNestedCode, kSecCSStrictValidate, SecCSFlags , SecCode } ;
8+ use std:: ptr:: NonNull ;
9+
10+ /// Returns `Ok(())` if the running binary is code-signed and valid, otherwise returns an Error.
11+ pub fn is_signature_valid ( ) -> crate :: Result < ( ) > {
12+ unsafe {
13+ // 1) Get a handle to "self"
14+ let mut self_code: * mut SecCode = std:: ptr:: null_mut ( ) ;
15+ let self_code_ptr = NonNull :: < * mut SecCode > :: new_unchecked ( & mut self_code) ;
16+ let status = SecCode :: copy_self ( SecCSFlags :: empty ( ) , self_code_ptr) ;
17+ if status != 0 {
18+ return Err ( std:: io:: Error :: new (
19+ std:: io:: ErrorKind :: Other ,
20+ format ! ( "Failed to get code reference: OSStatus {}" , status) ,
21+ )
22+ . into ( ) ) ;
23+ }
24+
25+ // 2) Validate the dynamic code - this checks if the signature is valid
26+ let validity_flags = SecCSFlags ( kSecCSCheckAllArchitectures | kSecCSCheckNestedCode | kSecCSStrictValidate) ;
27+ let self_code_ref = self_code_ptr. as_ref ( ) . as_ref ( ) . unwrap ( ) ;
28+ let status = SecCode :: check_validity (
29+ self_code_ref,
30+ validity_flags,
31+ None ,
32+ ) ;
33+ if status != 0 {
34+ return Err ( std:: io:: Error :: new (
35+ std:: io:: ErrorKind :: Other ,
36+ format ! ( "Code signature validation failed: OSStatus {}" , status) ,
37+ )
38+ . into ( ) ) ;
39+ }
40+
41+ Ok ( ( ) )
42+ }
43+ }
44+ }
45+
646#[ swift_bridge:: bridge]
747mod ffi {
848 pub enum FFIResult {
@@ -47,6 +87,8 @@ impl<R: Runtime> Iap<R> {
4787 }
4888
4989 pub fn initialize ( & self ) -> crate :: Result < InitializeResponse > {
90+ codesign:: is_signature_valid ( ) ?;
91+
5092 Self :: to_result ( ffi:: initialize ( ) )
5193 }
5294
@@ -55,6 +97,8 @@ impl<R: Runtime> Iap<R> {
5597 product_ids : Vec < String > ,
5698 product_type : String ,
5799 ) -> crate :: Result < GetProductsResponse > {
100+ codesign:: is_signature_valid ( ) ?;
101+
58102 Self :: to_result ( ffi:: getProducts ( product_ids, product_type) )
59103 }
60104
@@ -64,20 +108,26 @@ impl<R: Runtime> Iap<R> {
64108 product_type : String ,
65109 offer_token : Option < String > ,
66110 ) -> crate :: Result < Purchase > {
111+ codesign:: is_signature_valid ( ) ?;
112+
67113 Self :: to_result ( ffi:: purchase ( product_id, product_type, offer_token) )
68114 }
69115
70116 pub fn restore_purchases (
71117 & self ,
72118 product_type : String ,
73119 ) -> crate :: Result < RestorePurchasesResponse > {
120+ codesign:: is_signature_valid ( ) ?;
121+
74122 Self :: to_result ( ffi:: restorePurchases ( product_type) )
75123 }
76124
77125 pub fn acknowledge_purchase (
78126 & self ,
79127 purchase_token : String ,
80128 ) -> crate :: Result < AcknowledgePurchaseResponse > {
129+ codesign:: is_signature_valid ( ) ?;
130+
81131 Self :: to_result ( ffi:: acknowledgePurchase ( purchase_token) )
82132 }
83133
@@ -86,6 +136,8 @@ impl<R: Runtime> Iap<R> {
86136 product_id : String ,
87137 product_type : String ,
88138 ) -> crate :: Result < ProductStatus > {
139+ codesign:: is_signature_valid ( ) ?;
140+
89141 Self :: to_result ( ffi:: getProductStatus ( product_id, product_type) )
90142 }
91143}
0 commit comments