@@ -37,10 +37,10 @@ SecAccessControlRef getBioSecAccessControl() {
37
37
nil ); // Error pointer
38
38
}
39
39
40
- NSMutableDictionary * newDefaultDictionary (NSString * key) {
40
+ NSMutableDictionary * newDefaultDictionary (std::string key) {
41
41
NSMutableDictionary * queryDictionary = [[NSMutableDictionary alloc ] init ];
42
42
[queryDictionary setObject: (id )kSecClassGenericPassword forKey: (id )kSecClass ];
43
- NSData *encodedIdentifier = [key dataUsingEncoding: NSUTF8StringEncoding ];
43
+ NSData *encodedIdentifier = [NSData dataWithBytes: key. data () length: key. length () ];
44
44
[queryDictionary setObject: encodedIdentifier forKey: (id )kSecAttrGeneric ];
45
45
[queryDictionary setObject: encodedIdentifier forKey: (id )kSecAttrAccount ];
46
46
[queryDictionary setObject: [[NSBundle mainBundle ] bundleIdentifier ] forKey: (id )kSecAttrService ];
@@ -72,7 +72,7 @@ CFStringRef getAccessibilityValue(int accessibility) {
72
72
void _delete (std::string &key, bool withBiometrics) {
73
73
NSMutableDictionary *dict = newDefaultDictionary (key);
74
74
if (withBiometrics) {
75
- [dict setObject: (__bridge id )[self getBioSecAccessControl ] forKey: (id )kSecAttrAccessControl ];
75
+ // [dict setObject:(__bridge id)[self getBioSecAccessControl] forKey:(id)kSecAttrAccessControl];
76
76
}
77
77
SecItemDelete ((CFDictionaryRef )dict);
78
78
}
@@ -112,135 +112,133 @@ void install(jsi::Runtime &rt, std::shared_ptr<react::CallInvoker> jsCallInvoker
112
112
113
113
bool withBiometrics = false ;
114
114
115
- if (params.hasProperty (rt, " biometricAuthentication " )) {
116
- withBiometrics = params.getProperty (rt, " biometricAuthentication " ).asBool ();
115
+ if (params.hasProperty (rt, " withBiometrics " )) {
116
+ withBiometrics = params.getProperty (rt, " withBiometrics " ).asBool ();
117
117
}
118
118
119
-
120
119
_delete (key, withBiometrics);
121
120
122
- NSMutableDictionary *dict = [ self newDefaultDictionary: key] ;
121
+ NSMutableDictionary *dict = newDefaultDictionary ( key) ;
123
122
124
123
// kSecAttrAccessControl is mutually excluse with kSecAttrAccessible
125
124
// https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06f-testing-local-authentication
126
125
if (withBiometrics) {
127
- [dict setObject: (__bridge_transfer id )[ self getBioSecAccessControl ] forKey: (id )kSecAttrAccessControl ];
126
+ [dict setObject: (__bridge_transfer id )getBioSecAccessControl () forKey: (id )kSecAttrAccessControl ];
128
127
} else {
129
128
[dict setObject: (__bridge id )accessibility forKey: (id )kSecAttrAccessible ];
130
129
}
131
130
132
- NSData * valueData = [value dataUsingEncoding: NSUTF8StringEncoding];
133
- [dict setObject: valueData forKey: (id )kSecValueData ];
131
+ // NSData* valueData = [value dataUsingEncoding:NSUTF8StringEncoding];
132
+ NSData * data = [NSData dataWithBytes: val.data () length: val.length ()];
133
+ [dict setObject: data forKey: (id )kSecValueData ];
134
134
135
135
OSStatus status = SecItemAdd ((CFDictionaryRef )dict, NULL );
136
136
137
+ auto res = jsi::Object (rt);
138
+
137
139
if (status == noErr ) {
138
- return @{} ;
140
+ return res ;
139
141
}
142
+
143
+ auto errorStr = jsi::String::createFromUtf8 (rt, " op-s2 could not set value, error code: " + std::to_string (status));
144
+
145
+ res.setProperty (rt, " error" , errorStr);
146
+
147
+ return res;
148
+ });
140
149
141
- return @{
142
- @" error" : @" Could not save value" ,
143
- };
144
- return {};
150
+ auto get = HOSTFN (" get" , 1 ) {
151
+ if (count < 1 ) {
152
+ throw jsi::JSError (rt, " Params object is missing" );
153
+ }
154
+
155
+ if (!args[0 ].isObject ()) {
156
+ throw jsi::JSError (rt, " Params must be an object with key and value" );
157
+ }
158
+
159
+ jsi::Object params = args[0 ].asObject (rt);
160
+
161
+ if (!params.hasProperty (rt, " key" )) {
162
+ throw jsi::JSError (rt, " key property is missing" );
163
+ }
164
+
165
+ std::string key = params.getProperty (rt, " key" ).asString (rt).utf8 (rt);
166
+
167
+ bool withBiometrics = false ;
168
+
169
+ if (params.hasProperty (rt, " withBiometrics" )) {
170
+ withBiometrics = params.getProperty (rt, " withBiometrics" ).asBool ();
171
+ }
172
+
173
+ NSMutableDictionary *dict = newDefaultDictionary (key);
174
+
175
+ [dict setObject: (id )kSecMatchLimitOne forKey: (id )kSecMatchLimit ];
176
+ [dict setObject: (id )kCFBooleanTrue forKey: (id )kSecReturnData ];
177
+
178
+ auto res = jsi::Object (rt);
179
+
180
+ if (withBiometrics) {
181
+ BiometricsState biometricsState = getBiometricsState ();
182
+ LAContext *authContext = [[LAContext alloc ] init ];
183
+
184
+ // If device has no passcode/faceID/touchID then wallet-core cannot read the value from memory
185
+ if (biometricsState == kBiometricsStateNotAvailable ) {
186
+ auto errorStr = jsi::String::createFromUtf8 (rt, " Biometrics not available" );
187
+
188
+ res.setProperty (rt, " error" , errorStr);
189
+
190
+ return res;
191
+ }
192
+
193
+ if (biometricsState == kBiometricsStateLocked ) {
194
+
195
+ // TODO receiving a localized string might be necessary if this is happening on production
196
+ [authContext evaluatePolicy: LAPolicyDeviceOwnerAuthenticationWithBiometrics
197
+ localizedReason: @" You need to unlock your device"
198
+ reply: ^(BOOL success, NSError *error) {
199
+ if (!success) {
200
+ // Edge case when device might locked out after too many password attempts
201
+ // User has failed to authenticate, but due to this being a callback cannot interrupt upper lexical scope
202
+ // We should somehow prompt/tell the user that it has failed to authenticate
203
+ // and wallet could not be loaded
204
+ }
205
+ }];
206
+ }
207
+
208
+ [dict setObject: (__bridge id ) getBioSecAccessControl () forKey: (id )kSecAttrAccessControl ];
209
+ }
210
+
211
+ CFDataRef dataResult = nil ;
212
+ OSStatus status = SecItemCopyMatching ((CFDictionaryRef )dict, (CFTypeRef *) &dataResult);
213
+
214
+
215
+ if (status == noErr ) {
216
+ NSData * result = (__bridge NSData *) dataResult;
217
+ // std::string val = std::string(static_cast<const char*>(result.bytes), result.length);
218
+ NSString * returnString = [[NSString alloc ] initWithData: result encoding: NSUTF8StringEncoding];
219
+ res.setProperty (rt, " value" , [returnString UTF8String ]);
220
+ return res;
221
+ }
222
+
223
+ auto errorStr = jsi::String::createFromUtf8 (rt, " op-s2 could not set value, error code: " + std::to_string (status));
224
+
225
+ res.setProperty (rt, " error" , errorStr);
226
+
227
+ return res;
145
228
});
146
229
147
230
jsi::Object module = jsi::Object (rt);
148
231
149
232
module.setProperty (rt, " set" , std::move (set));
233
+ module.setProperty (rt, " get" , std::move (get));
150
234
151
235
rt.global ().setProperty (rt, " __OPSecureStoreProxy" , std::move (module));
152
236
}
153
237
}
154
238
155
239
156
240
//
157
- // - (NSDictionary *)setItem:(NSString *)key value:(NSString *)value options:(JS::NativeTurboSecureStorage::SpecSetItemOptions &)options
158
- // {
159
- // CFStringRef accessibility = kSecAttrAccessibleAfterFirstUnlock;
160
- //
161
- // if(options.accessibility()) {
162
- // accessibility = [self getAccessibilityValue:options.accessibility()];
163
- // }
164
- //
165
- // bool withBiometrics = options.biometricAuthentication().value();
166
- //
167
- // [self innerDelete:key withBiometrics:withBiometrics];
168
- //
169
- // NSMutableDictionary *dict = [self newDefaultDictionary:key];
170
- //
171
- // // kSecAttrAccessControl is mutually excluse with kSecAttrAccessible
172
- // // https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06f-testing-local-authentication
173
- // if(withBiometrics) {
174
- // [dict setObject:(__bridge_transfer id)[self getBioSecAccessControl] forKey:(id)kSecAttrAccessControl];
175
- // } else {
176
- // [dict setObject:(__bridge id)accessibility forKey:(id)kSecAttrAccessible];
177
- // }
178
- //
179
- // NSData* valueData = [value dataUsingEncoding:NSUTF8StringEncoding];
180
- // [dict setObject:valueData forKey:(id)kSecValueData];
181
- //
182
- // OSStatus status = SecItemAdd((CFDictionaryRef)dict, NULL);
183
- //
184
- // if (status == noErr) {
185
- // return @{};
186
- // }
187
- //
188
- // return @{
189
- // @"error": @"Could not save value",
190
- // };
191
- // }
192
- //
193
- // - (NSDictionary *)getItem:(NSString *)key options:(JS::NativeTurboSecureStorage::SpecGetItemOptions &)options {
194
- // NSMutableDictionary *dict = [self newDefaultDictionary:key];
195
- //
196
- // [dict setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
197
- // [dict setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
198
- //
199
- // if(options.biometricAuthentication()) {
200
- // BiometricsState biometricsState = getBiometricsState();
201
- // LAContext *authContext = [[LAContext alloc] init];
202
- //
203
- // // If device has no passcode/faceID/touchID then wallet-core cannot read the value from memory
204
- // if(biometricsState == kBiometricsStateNotAvailable) {
205
- // return @{
206
- // @"error": @"Biometrics not available"
207
- // };
208
- // }
209
- //
210
- // if(biometricsState == kBiometricsStateLocked) {
211
- //
212
- // // TODO receiving a localized string might be necessary if this is happening on production
213
- // [authContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
214
- // localizedReason:@"You need to unlock your device"
215
- // reply:^(BOOL success, NSError *error) {
216
- // if (!success) {
217
- // // Edge case when device might locked out after too many password attempts
218
- // // User has failed to authenticate, but due to this being a callback cannot interrupt upper lexical scope
219
- // // We should somehow prompt/tell the user that it has failed to authenticate
220
- // // and wallet could not be loaded
221
- // }
222
- // }];
223
- // }
224
- //
225
- // [dict setObject:(__bridge id)[self getBioSecAccessControl] forKey:(id)kSecAttrAccessControl];
226
- // }
227
- //
228
- // CFDataRef dataResult = nil;
229
- // OSStatus status = SecItemCopyMatching((CFDictionaryRef)dict, (CFTypeRef*) &dataResult);
230
- //
231
- // if (status == noErr) {
232
- // NSData* result = (__bridge NSData*) dataResult;
233
- // NSString* returnString = [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
234
- //
235
- // return @{
236
- // @"value": returnString
237
- // };
238
- // }
239
- //
240
- // return @{
241
- // @"error": @"Could not get value"
242
- // };
243
- // }
241
+
244
242
245
243
//
246
244
// - (NSDictionary *)deleteItem:(NSString *)key options:(JS::NativeTurboSecureStorage::SpecDeleteItemOptions &)options {
0 commit comments