Search code examples
c++ioskeychain

iOS Keychain in C++, how to call SecItemAdd?


I'm trying to call iOS Keychain framework from C++, following various documentation pages and StackOverflow questions I arrived at the following:

// library is multiplaform so for now using macros for platform imports
#ifdef ANDROID
// Android specific imports
#else
#include <CoreFoundation/CoreFoundation.h>
#include <Security/Security.h>
#endif // ANDROID

// ...some glue code
      CFStringRef keys[4];
      keys[0] = kSecClass;
      keys[1] = kSecAttrAccount;
      keys[2] = kSecAttrService;
      keys[3] = kSecValueData;

      CFTypeRef values[4];
      values[0] = kSecClassGenericPassword;
      values[1] = CFSTR("accountname2");
      // TODO change this to bundle identifier
      values[2] = CFSTR("jsi-rn-wallet-core");
      values[3] = CFSTR("testvalueblahblah");

      CFDictionaryRef query = CFDictionaryCreate(
                                                 kCFAllocatorDefault,
                                                 (const void**) keys,
                                                 (const void**) values,
                                                 4,
                                                 &kCFTypeDictionaryKeyCallBacks, 
                                                 &kCFTypeDictionaryValueCallBacks);
    OSStatus status = SecItemAdd(query, NULL);
      
      if(status != errSecSuccess) {
        cout << "DID NOT STORE DATA, status: " << status << endl;
        return {};
      }
      
      cout << "Data stored" << endl;

No matter what I do, I get a status of -50, which according to documentation is an incorrect param, however, I don't know which one exactly.

Any idea what might be wrong?


Solution

  • I figured it out, as it turns out, on macOS you can put CFStrings directly in the query dictionary, but on iOS you need to store binary data. Something like this:

    string value = "testvalueblahblah";
    std::vector<uint8_t> vec(value.begin(), value.end());
    
    ...
    
    values[3] = CFDataCreate(kCFAllocatorDefault, &vec[0], vec.size());
    
    

    After data is converted, everything started working.