trailofbits / SecureEnclaveCrypto

Demonstration library for using the Secure Enclave on iOS

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Verify Signature example that works in Objective-C project.

opened this issue · comments

We have been struggling on this issue with no luck. It works fine in your Swift example, but cant get it to work in the Obj-C project.

Please post more information. Are you verifying the signature on server or in app?

Im trying in app, by SecKeyRawVerify:

SecKeyRef publicKey = [self lookupECCPublicKeyRef];

uint8_t digest[CC_SHA256_DIGEST_LENGTH];
CC_SHA256([inputData bytes], (CC_LONG)[inputData length], digest);
OSStatus status = SecKeyRawVerify(publicKey,
                                  kSecPaddingPKCS1SHA256,
                                  digest,
                                  CC_SHA256_DIGEST_LENGTH,
                                  (uint8_t*)[sig bytes],
                                  [sig length]);

From skimming the code it seems like they are casting wrongly in lookupPublicKey. You can try with this (haven't tested it myself):

+ (CFDictionaryRef) lookupPublicKey // <------- changed this
{
  CFMutableDictionaryRef getPublicKeyQuery = newCFDict;
  CFDictionarySetValue(getPublicKeyQuery, kSecClass,                kSecClassKey);
  CFDictionarySetValue(getPublicKeyQuery, kSecAttrKeyType,          kSecAttrKeyTypeEC);
  CFDictionarySetValue(getPublicKeyQuery, kSecAttrApplicationTag,   kPublicKeyName);
  CFDictionarySetValue(getPublicKeyQuery, kSecAttrKeyClass,         kSecAttrKeyClassPublic);
  CFDictionarySetValue(getPublicKeyQuery, kSecReturnData,           kCFBooleanTrue);
  CFDictionarySetValue(getPublicKeyQuery, kSecReturnRef,  kCFBooleanTrue); // <--------- added this
  CFDictionarySetValue(getPublicKeyQuery, kSecReturnPersistentRef,  kCFBooleanTrue);
  
  OSStatus status = SecItemCopyMatching(getPublicKeyQuery, (CFTypeRef *)&publicKeyRef);
  if (status == errSecSuccess)
    return (CFDictionaryRef)publicKeyRef; // <------- changed this
  else if (status == errSecItemNotFound)
    return nil;
  else
    [NSException raise:@"Unexpected OSStatus" format:@"Status: %i", status];
  return false;
}

Then you can properly get the key

CFDictionaryRef publicKeyDict = [self lookupPublicKey];
SecKeyRef publicKey = (SecKeyRef) CFDictionaryGetValue((CFDictionaryRef)publicKeyDict, kSecValueRef);

@kragekjaer when adressing issues here on github it is much easier if you can provide as much info as possible.

Perfect. It works. Thank you very much.

Cool. Glad I could help. See ya

I was a bit quick to say it works. The returned public key:
CFDictionaryRef publicKeyDict = [self lookupPublicKey];
SecKeyRef publicKey = (SecKeyRef) CFDictionaryGetValue((CFDictionaryRef)publicKeyDict, kSecValueRef);
is (null) but at least it dosent crash with BAD_ACCESS.
Now verify returns -50 (errSecParam)

Please post more code. Did you use my new implementation of lookup public key?

Hi again, here si s the code Im using

+ (CFDictionaryRef) lookupECCPublicKeyRef
{
    CFMutableDictionaryRef getPublicKeyQuery = newCFDict;

    CFDictionarySetValue(getPublicKeyQuery, kSecClass,                kSecClassKey);
    CFDictionarySetValue(getPublicKeyQuery, kSecAttrKeyType,          kSecAttrKeyTypeEC);
    CFDictionarySetValue(getPublicKeyQuery, kSecAttrApplicationTag,   kPublicKeyName);
    CFDictionarySetValue(getPublicKeyQuery, kSecAttrKeyClass,         kSecAttrKeyClassPublic);
    CFDictionarySetValue(getPublicKeyQuery, kSecReturnData,           kCFBooleanTrue);
    CFDictionarySetValue(getPublicKeyQuery, kSecReturnPersistentRef,  kCFBooleanTrue);
    CFDictionarySetValue(getPublicKeyQuery, kSecAttrCanVerify,        kCFBooleanTrue);

    OSStatus status = SecItemCopyMatching(getPublicKeyQuery, (CFTypeRef *)&publicECCKeyRef);

    if (status == errSecSuccess)
    {
        return (CFDictionaryRef)publicECCKeyRef;
    }
    else if (status == errSecItemNotFound)
    {
        return nil;
    }
    else
        [NSException raise:@"Unexpected OSStatus" format:@"Status: %i", (int)status];
    return false;
}

+(void) verifyECCSignature:(NSData *) inputData signature:(NSData *) sig{

    CFDictionaryRef publicKeyDict = [self lookupECCPublicKeyRef];
    CFDictionaryRef publicKey = CFDictionaryGetValue((CFDictionaryRef)publicKeyDict, kSecValueRef);

    NSLog(@"public key: %@", publicKey );

    uint8_t digest[CC_SHA256_DIGEST_LENGTH];
    CC_SHA256([inputData bytes], (CC_LONG)[inputData length], digest);
    OSStatus status = SecKeyRawVerify((SecKeyRef)publicKey,
                                      kSecPaddingPKCS1SHA256,
                                      digest,
                                      CC_SHA256_DIGEST_LENGTH,
                                      (uint8_t*)[sig bytes],
                                      [sig length]);

    NSLog(@"SUCCESS? Verifying %d", (int)status);
}

Awesome. Thanks. Seems like you didn't copy the whole method. This part is missing from lookupECCPublicKeyRef

  CFDictionarySetValue(getPublicKeyQuery, kSecReturnRef,  kCFBooleanTrue); // <--------- added this

Please verify that SecKeyRef publicKey = (SecKeyRef) CFDictionaryGetValue((CFDictionaryRef)publicKeyDict, kSecValueRef); is not null

Its working, sorry for not being observant. Thanks again

Glad to hear that 👍 ⚡️ ✨ ✨