static OSStatus GenerateRSAKeyPair( SecKeychainRef keychain, CFStringRef keyLabel, int keySizeValue, Boolean *extractable, SecKeyRef *publicKeyRef, SecKeyRef *privateKeyRef) { OSStatus status; CFNumberRef keySize = CFNumberCreate(NULL, kCFNumberIntType, &keySizeValue); // create a SecAccessRef to set up the initial access control settings for this key // (this step is optional; if omitted, the creating application has access to the key) // note: the access descriptor should be the same string as will be used for the item's label, // since it's the string that is displayed by the access confirmation dialog to describe the item. SecAccessRef access = NULL; status = SecAccessCreate(keyLabel, NULL, &access); // create a dictionary of parameters describing the key we want to create CFMutableDictionaryRef params = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); /* From the header doc for SecKeyGeneratePair (seems to be incomplete...): * kSecAttrLabel default NULL * kSecAttrIsPermanent if this key is present and has a Boolean value of true, the key or key pair will be added to the default keychain. * kSecAttrApplicationTag default NULL * kSecAttrEffectiveKeySize default NULL same as kSecAttrKeySizeInBits * kSecAttrCanEncrypt default false for private keys, true for public keys * kSecAttrCanDecrypt default true for private keys, false for public keys * kSecAttrCanDerive default true * kSecAttrCanSign default true for private keys, false for public keys * kSecAttrCanVerify default false for private keys, true for public keys * kSecAttrCanWrap default false for private keys, true for public keys * kSecAttrCanUnwrap default true for private keys, false for public keys */ CFDictionaryAddValue( params, kSecUseKeychain, keychain ); CFDictionaryAddValue( params, kSecAttrAccess, access ); CFDictionaryAddValue( params, kSecAttrKeyType, kSecAttrKeyTypeRSA ); CFDictionaryAddValue( params, kSecAttrKeySizeInBits, keySize ); CFReleaseNull(keySize); CFDictionaryAddValue( params, kSecAttrIsPermanent, kCFBooleanTrue ); if (extractable) CFDictionaryAddValue( params, kSecAttrIsExtractable, (*extractable) ? kCFBooleanTrue : kCFBooleanFalse ); if (keyLabel) CFDictionaryAddValue( params, kSecAttrLabel, keyLabel ); // generate the key status = SecKeyGeneratePair(params, publicKeyRef, privateKeyRef); ok_status(status, "%s: SecKeyGeneratePair", testName); if (params) CFRelease(params); if (access) CFRelease(access); return status; }
OSStatus SecAccessCreateWithTrustedApplications(CFStringRef trustedApplicationsPListPath, CFStringRef accessLabel, Boolean allowAny, SecAccessRef* returnedAccess) { OSStatus err = errSecSuccess; SecAccessRef accessToReturn=nil; CFMutableArrayRef trustedApplications=nil; if (!allowAny) // use default access ("confirm access") { // make an exception list of applications you want to trust, // which are allowed to access the item without requiring user confirmation SecTrustedApplicationRef myself=NULL, someOther=NULL; CFArrayRef trustedAppListFromBundle=NULL; trustedApplications=CFArrayCreateMutable(kCFAllocatorDefault,0,&kCFTypeArrayCallBacks); err = SecTrustedApplicationCreateFromPath(NULL, &myself); if (!err) CFArrayAppendValue(trustedApplications,myself); CFURLRef url = CFURLCreateWithFileSystemPath(NULL, trustedApplicationsPListPath, kCFURLPOSIXPathStyle, 0); CFStringRef leafStr = NULL; leafStr = CFURLCopyLastPathComponent(url); CFURLRef bndlPathURL = NULL; bndlPathURL = CFURLCreateCopyDeletingLastPathComponent(NULL, url); CFStringRef bndlPath = NULL; bndlPath = CFURLCopyFileSystemPath(bndlPathURL, kCFURLPOSIXPathStyle); trustedAppListFromBundle=copyTrustedAppListFromBundle(bndlPath, leafStr); if ( leafStr ) CFRelease(leafStr); if ( bndlPath ) CFRelease(bndlPath); if ( url ) CFRelease(url); if ( bndlPathURL ) CFRelease(bndlPathURL); if (trustedAppListFromBundle) { CFIndex ix,top; char buffer[MAXPATHLEN]; top = CFArrayGetCount(trustedAppListFromBundle); for (ix=0;ix<top;ix++) { CFStringRef filename = (CFStringRef)CFArrayGetValueAtIndex(trustedAppListFromBundle,ix); CFIndex stringLength = CFStringGetLength(filename); CFIndex usedBufLen; if (stringLength != CFStringGetBytes(filename,CFRangeMake(0,stringLength),kCFStringEncodingUTF8,0, false,(UInt8 *)&buffer,MAXPATHLEN, &usedBufLen)) break; buffer[usedBufLen] = 0; // // Support specification of trusted applications by either // a full pathname or a code requirement string. // if (buffer[0]=='/') { err = SecTrustedApplicationCreateFromPath(buffer,&someOther); } else { char *buf = NULL; CFStringRef reqStr = filename; CFArrayRef descArray = CFStringCreateArrayBySeparatingStrings(NULL, reqStr, CFSTR("\"")); if (descArray && (CFArrayGetCount(descArray) > 1)) { CFStringRef descStr = (CFStringRef) CFArrayGetValueAtIndex(descArray, 1); if (descStr) buf = CFStringToCString(descStr); } SecRequirementRef reqRef = NULL; err = SecRequirementCreateWithString(reqStr, kSecCSDefaultFlags, &reqRef); if (!err) err = SecTrustedApplicationCreateFromRequirement((const char *)buf, reqRef, &someOther); if (buf) free(buf); CFReleaseSafe(reqRef); CFReleaseSafe(descArray); } if (!err) CFArrayAppendValue(trustedApplications,someOther); if (someOther) CFReleaseNull(someOther); } CFRelease(trustedAppListFromBundle); } } err = SecAccessCreate((CFStringRef)accessLabel, (CFArrayRef)trustedApplications, &accessToReturn); if (!err) { if (allowAny) // change access to be wide-open for decryption ("always allow access") { // get the access control list for decryption operations CFArrayRef aclList=nil; err = SecAccessCopySelectedACLList(accessToReturn, CSSM_ACL_AUTHORIZATION_DECRYPT, &aclList); if (!err) { // get the first entry in the access control list SecACLRef aclRef=(SecACLRef)CFArrayGetValueAtIndex(aclList, 0); CFArrayRef appList=nil; CFStringRef promptDescription=nil; CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR promptSelector; err = SecACLCopySimpleContents(aclRef, &appList, &promptDescription, &promptSelector); // modify the default ACL to not require the passphrase, and have a nil application list promptSelector.flags &= ~CSSM_ACL_KEYCHAIN_PROMPT_REQUIRE_PASSPHRASE; err = SecACLSetSimpleContents(aclRef, NULL, promptDescription, &promptSelector); if (appList) CFRelease(appList); if (promptDescription) CFRelease(promptDescription); } } } *returnedAccess = accessToReturn; return err; }