Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keychain on iOS #483

Closed
leehu opened this issue May 5, 2020 · 8 comments
Closed

Keychain on iOS #483

leehu opened this issue May 5, 2020 · 8 comments

Comments

@leehu
Copy link

leehu commented May 5, 2020

Hi, spoke to you via email - I'm not using you code but hope you might be able to give me some insight into an issue with the C API. I'm not a swift programmer, but think we're basically doing the same thing.

    CFMutableDictionaryRef query = CFDictionaryCreateMutable( nullptr, 10, nullptr, nullptr );
    CFDictionaryAddValue( query, kSecClass, kSecClassGenericPassword );
    CFDictionaryAddValue( query, kSecAttrAccount, "test" );
    CFDictionaryAddValue( query, kSecValueData, "data" );

    const auto res = SecItemAdd( query, nullptr );

This code works fine on Mac, but returns error -50 on iOS, which is errSecParam. Looking through you code it seems this should be supported on iOS.

Cheers

@kishikawakatsumi
Copy link
Owner

kishikawakatsumi commented May 5, 2020

I cannot actually reproduce the error.

But you pass a string as a kSecValueData parameter. You should pass CFData type instead. So that's obviously wrong usage.

The code below is a minimal sample that works correctly (It's Objective-C code. It's not a pure C code though)

CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 10, NULL, NULL);
CFDictionaryAddValue(query, kSecClass, kSecClassGenericPassword);
CFDictionaryAddValue(query, kSecAttrAccount, CFSTR("smith"));

const char* string = "data";
CFDataRef data = CFDataCreate(NULL, (const UInt8 *)string, (CFIndex)strlen(string));
CFDictionaryAddValue(query, kSecValueData, data);

const auto res = SecItemAdd(query, NULL);
NSLog(@"%d", res);

CFRelease(data);

@leehu

@leehu
Copy link
Author

leehu commented May 5, 2020

Hi, yeah, I realised that - this was a "contrived" example.
Actually, I've found the issue - seems like:

    CFDictionaryAddValue( query, kSecAttrAccessible, kSecAttrAccessibleWhenUnlocked );

must be specified on iOS - I've now added a key successfully.

However, when trying to retrieve:

    CFMutableDictionaryRef query = CFDictionaryCreateMutable( kCFAllocatorDefault, 0, nullptr, nullptr );
    CFDictionaryAddValue( query, kSecClass, kSecClassGenericPassword );
    CFDictionaryAddValue( query, kSecAttrService, CFSTR( "test" ) );
    CFDictionaryAddValue( query, kSecAttrAccessible, kSecAttrAccessibleWhenUnlocked );
    CFDictionaryAddValue( query, kSecReturnRef, kCFBooleanTrue );

    CFTypeRef ref = nullptr;
    
    auto res = SecItemCopyMatching( query, (CFTypeRef*)&ref );

a result code of 0 is returned (success), but ref remains empty.

btw, thanks for your speedy reply!

@kishikawakatsumi
Copy link
Owner

You should use kSecReturnData instead kSecReturnRef. kSecReturnRef can only be specified when some special classes of ~Ref are specified.

@leehu
Copy link
Author

leehu commented May 5, 2020

ok, thx. I added the line which I'd missed out and now I'm back to the error -50. So I can't actually get any data into the key...

CFDictionaryAddValue( query, kSecValueData, CFSTR( "data" ) );

@kishikawakatsumi
Copy link
Owner

As I said above, passing string object is not correct. Keychain API cannot accept string object as a value data. You have to convert string to CFData.

const char* string = "data";
CFDataRef data = CFDataCreate(NULL, (const UInt8 *)string, (CFIndex)strlen(string));
CFDictionaryAddValue(query, kSecValueData, data);

@leehu
Copy link
Author

leehu commented May 5, 2020

Hi, yeah, sorry, missed that. Looks like it might be working...
God, dunno how people work with these APIs!

@leehu
Copy link
Author

leehu commented May 5, 2020

I think the strange thing is that you can pass CFStrings in on Mac and it's fine, iOS needs the CFData. Shame they're not consistent...

@leehu
Copy link
Author

leehu commented May 5, 2020

all working - thanks so much for your help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants