2015-06-24 15 views
5

sto usando questo codice per elencare tutte le chiavi private e ottenere alcune informazioni su di loro, utilizzando API framework di sicurezza di Apple:SecKeychainItemCopyContents in segfault su chiavi private

int main(int argc, const char * argv[]) { 
    const void *keys[] = { kSecClass, kSecReturnRef, kSecMatchLimit, kSecAttrKeyClass}; 
    const void *values[] = { kSecClassKey, kCFBooleanTrue, kSecMatchLimitAll, kSecAttrKeyClassPrivate}; 

    CFDictionaryRef searchDict = CFDictionaryCreate(
     NULL, 
     keys, values, sizeof(keys)/sizeof(keys[0]), 
     NULL, NULL 
    ); 
    checkAlloc(searchDict); 

    CFArrayRef items; 
    check(SecItemCopyMatching(searchDict, (CFTypeRef *)&items)); 

    for(int i=0; i<CFArrayGetCount(items); i++) { 
     SecKeychainItemRef item = (SecKeychainItemRef) CFArrayGetValueAtIndex(items, i); 

     CFShow((CFTypeRef)item); 

     SecItemClass cls; 
     SecKeychainAttributeList attrs; 
     UInt32 dataLen; 
     void* data; 

     check(SecKeychainItemCopyContent(item, &cls, &attrs, &dataLen, &data)); 

     printf("Key: %d\n", (int)dataLen); 

     check(SecKeychainItemFreeContent(&attrs, data)); 
    } 

    CFRelease(items); 
    CFRelease(searchDict); 

    return 0; 
} 

La chiamata alla SecKeychainItemCopyContent segfaults, anche se nessuno di i puntatori che ho passato non sono validi.

Le CFShow stampa linee simili a <SecKey 0x7fb4d9d01420 [0x7fff74790ed0]>, quindi item dovrebbe essere un SecKeyRef, ma il documentation for it dice che è OK per utilizzare un SecKeyRef come SecKeychainItemRef se la chiave è in un portachiavi. Tuttavia, non vedo alcuna funzione per trovare se la chiave è in un portachiavi, quindi non posso convalidare che le chiavi restituite possano essere utilizzate come tali.

Cosa sto facendo di sbagliato qui?

risposta

0

per copiare i dati e/o attributi memorizzati nel dato elemento portachiavi, il terzo parametro della funzione SecKeychainItemCopyContent() è SecKeychainAttributeList *attrList di tipo simile,

struct SecKeychainAttributeList 
    { 
    UInt32 count; 
    SecKeychainAttribute *attr; 
    }; 

Per questa IN/OUT param attrList: In ingresso, è la lista di attributi che hai richiesto di recuperare. In uscita, gli attributi sono compilati. Passa NULL se non è necessario recuperare alcun attributo o passare un elenco di attributi che è necessario ottenere. Dovrebbe essere uno di questi due passaggi citati in argomenti. Lasciare non inizializzato potrebbe causare problemi, come il segfaulting.

Quindi, per favore prova in questo modo, dovrebbe funzionare bene.

SecKeychainAttributeList attrs = {0, NULL}; 
//... 
check(SecKeychainItemCopyContent(item, &cls, &attrs, &dataLen, &data)); 

o

//SecKeychainAttributeList attrs ; 
//... 
check(SecKeychainItemCopyContent(item, &cls, NULL, &dataLen, &data)); 
printf("Key: %d\n", (int)dataLen); 
check(SecKeychainItemFreeContent(NULL, data)); 

nel caso ci fosse la necessità di ottenere l'elenco attributi, il codice di esempio potrebbe essere il seguente,

SecKeychainAttributeList xlist; 
SecKeychainAttribute outList[] = 
{ 
    {kSecAddressItemAttr,}, 
    {kSecAccountItemAttr,}, 
    {kSecVolumeItemAttr,}, 
    {kSecProtocolItemAttr} 
}; 

xlist.count = sizeof(outList)/sizeof(outList[0]); 
xlist.attr = outList; 

//... 
err = SecKeychainItemCopyContent (itemRef, nil, &xlist, &len, &outData); 
//... 
+0

Il secondo esempio è errato perché si tenta di stampare 'dataLen' prima che sia inizializzato. Non vedo come azzerare 'attrs' prima di passarlo farà la differenza, dato che' SecKeychainItemCopyContent' dovrebbe scrivere solo su di esso e non ha motivo di dereferenziare il puntatore 'attr'. –

1

A quanto pare, il parametro SecKeychainAttributeList non è solo un produzione. È anche un input contenente gli attributi da ottenere.

SecKeychainAttributeList dereferenziato il puntatore non inizializzato attrs->attr e arrestato in modo anomalo. L'inizializzazione del puntatore su NULL risolve il problema.

Problemi correlati