4632N/A/*
4793N/A * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
4632N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4632N/A *
4632N/A * This code is free software; you can redistribute it and/or modify it
4632N/A * under the terms of the GNU General Public License version 2 only, as
4632N/A * published by the Free Software Foundation. Oracle designates this
4632N/A * particular file as subject to the "Classpath" exception as provided
4632N/A * by Oracle in the LICENSE file that accompanied this code.
4632N/A *
4632N/A * This code is distributed in the hope that it will be useful, but WITHOUT
4632N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
4632N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
4632N/A * version 2 for more details (a copy is included in the LICENSE file that
4632N/A * accompanied this code).
4632N/A *
4632N/A * You should have received a copy of the GNU General Public License version
4632N/A * 2 along with this work; if not, write to the Free Software Foundation,
4632N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
4632N/A *
4632N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
4632N/A * or visit www.oracle.com if you need additional information or have any
4632N/A * questions.
4632N/A */
4632N/A
4632N/A#import "apple_security_KeychainStore.h"
4632N/A
4632N/A#import <Security/Security.h>
4632N/A#import <Security/SecImportExport.h>
4632N/A#import <CoreServices/CoreServices.h> // (for require() macros)
4632N/A#import <JavaNativeFoundation/JavaNativeFoundation.h>
4632N/A
4632N/A
4632N/Astatic JNF_CLASS_CACHE(jc_KeychainStore, "apple/security/KeychainStore");
4632N/Astatic JNF_MEMBER_CACHE(jm_createTrustedCertEntry, jc_KeychainStore, "createTrustedCertEntry", "(Ljava/lang/String;JJ[B)V");
4632N/Astatic JNF_MEMBER_CACHE(jm_createKeyEntry, jc_KeychainStore, "createKeyEntry", "(Ljava/lang/String;JJ[J[[B)V");
4632N/A
4632N/Astatic jstring getLabelFromItem(JNIEnv *env, SecKeychainItemRef inItem)
4632N/A{
4632N/A OSStatus status;
4632N/A jstring returnValue = NULL;
4632N/A char *attribCString = NULL;
4632N/A
4632N/A SecKeychainAttribute itemAttrs[] = { { kSecLabelItemAttr, 0, NULL } };
4632N/A SecKeychainAttributeList attrList = { sizeof(itemAttrs) / sizeof(itemAttrs[0]), itemAttrs };
4632N/A
4632N/A status = SecKeychainItemCopyContent(inItem, NULL, &attrList, NULL, NULL);
4632N/A
4632N/A if(status) {
4632N/A cssmPerror("getLabelFromItem: SecKeychainItemCopyContent", status);
4632N/A goto errOut;
4632N/A }
4632N/A
4632N/A attribCString = malloc(itemAttrs[0].length + 1);
4632N/A strncpy(attribCString, itemAttrs[0].data, itemAttrs[0].length);
4632N/A attribCString[itemAttrs[0].length] = '\0';
4632N/A returnValue = (*env)->NewStringUTF(env, attribCString);
4632N/A
4632N/AerrOut:
4632N/A SecKeychainItemFreeContent(&attrList, NULL);
4632N/A if (attribCString) free(attribCString);
4632N/A return returnValue;
4632N/A}
4632N/A
4632N/Astatic jlong getModDateFromItem(JNIEnv *env, SecKeychainItemRef inItem)
4632N/A{
4632N/A OSStatus status;
4632N/A SecKeychainAttribute itemAttrs[] = { { kSecModDateItemAttr, 0, NULL } };
4632N/A SecKeychainAttributeList attrList = { sizeof(itemAttrs) / sizeof(itemAttrs[0]), itemAttrs };
4632N/A jlong returnValue = 0;
4632N/A
4632N/A status = SecKeychainItemCopyContent(inItem, NULL, &attrList, NULL, NULL);
4632N/A
4632N/A if(status) {
4632N/A // This is almost always missing, so don't dump an error.
4632N/A // cssmPerror("getModDateFromItem: SecKeychainItemCopyContent", status);
4632N/A goto errOut;
4632N/A }
4632N/A
4632N/A memcpy(&returnValue, itemAttrs[0].data, itemAttrs[0].length);
4632N/A
4632N/AerrOut:
4632N/A SecKeychainItemFreeContent(&attrList, NULL);
4632N/A return returnValue;
4632N/A}
4632N/A
4632N/Astatic void setLabelForItem(NSString *inLabel, SecKeychainItemRef inItem)
4632N/A{
4632N/A OSStatus status;
4632N/A const char *labelCString = [inLabel UTF8String];
4632N/A
4632N/A // Set up attribute vector (each attribute consists of {tag, length, pointer}):
4632N/A SecKeychainAttribute attrs[] = {
4632N/A { kSecLabelItemAttr, strlen(labelCString), (void *)labelCString }
4632N/A };
4632N/A
4632N/A const SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs };
4632N/A
4632N/A // Not changing data here, just attributes.
4632N/A status = SecKeychainItemModifyContent(inItem, &attributes, 0, NULL);
4632N/A
4632N/A if(status) {
4632N/A cssmPerror("setLabelForItem: SecKeychainItemModifyContent", status);
4632N/A }
4632N/A}
4632N/A
4632N/A/*
4632N/A * Given a SecIdentityRef, do our best to construct a complete, ordered, and
4632N/A * verified cert chain, returning the result in a CFArrayRef. The result is
4632N/A * can be passed back to Java as a chain for a private key.
4632N/A */
4632N/Astatic OSStatus completeCertChain(
4632N/A SecIdentityRef identity,
4632N/A SecCertificateRef trustedAnchor, // optional additional trusted anchor
4632N/A bool includeRoot, // include the root in outArray
4632N/A CFArrayRef *outArray) // created and RETURNED
4632N/A{
4632N/A SecTrustRef secTrust = NULL;
4632N/A SecPolicyRef policy = NULL;
4632N/A SecPolicySearchRef policySearch = NULL;
4632N/A SecTrustResultType secTrustResult;
4632N/A CSSM_TP_APPLE_EVIDENCE_INFO *dummyEv; // not used
4632N/A CFArrayRef certChain = NULL; // constructed chain, CERTS ONLY
4632N/A CFMutableArrayRef subjCerts; // passed to SecTrust
4632N/A CFMutableArrayRef certArray; // returned array starting with
4632N/A // identity
4632N/A CFIndex numResCerts;
4632N/A CFIndex dex;
4632N/A OSStatus ortn;
4632N/A SecCertificateRef certRef;
4632N/A
4632N/A /* First element in out array is the SecIdentity */
4632N/A certArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
4632N/A CFArrayAppendValue(certArray, identity);
4632N/A
4632N/A /* the single element in certs-to-be-evaluated comes from the identity */
4632N/A ortn = SecIdentityCopyCertificate(identity, &certRef);
4632N/A if(ortn) {
4632N/A /* should never happen */
4632N/A cssmPerror("SecIdentityCopyCertificate", ortn);
4632N/A return ortn;
4632N/A }
4632N/A
4632N/A /*
4632N/A * Now use SecTrust to get a complete cert chain, using all of the
4632N/A * user's keychains to look for intermediate certs.
4632N/A * NOTE this does NOT handle root certs which are not in the system
4632N/A * root cert DB.
4632N/A */
4632N/A subjCerts = CFArrayCreateMutable(NULL, 1, &kCFTypeArrayCallBacks);
4632N/A CFArraySetValueAtIndex(subjCerts, 0, certRef);
4632N/A
4632N/A /* the array owns the subject cert ref now */
4632N/A CFRelease(certRef);
4632N/A
4632N/A /* Get a SecPolicyRef for generic X509 cert chain verification */
4632N/A ortn = SecPolicySearchCreate(CSSM_CERT_X_509v3,
4632N/A &CSSMOID_APPLE_X509_BASIC,
4632N/A NULL, // value
4632N/A &policySearch);
4632N/A if(ortn) {
4632N/A /* should never happen */
4632N/A cssmPerror("SecPolicySearchCreate", ortn);
4632N/A goto errOut;
4632N/A }
4632N/A ortn = SecPolicySearchCopyNext(policySearch, &policy);
4632N/A if(ortn) {
4632N/A /* should never happen */
4632N/A cssmPerror("SecPolicySearchCopyNext", ortn);
4632N/A goto errOut;
4632N/A }
4632N/A
4632N/A /* build a SecTrustRef for specified policy and certs */
4632N/A ortn = SecTrustCreateWithCertificates(subjCerts,
4632N/A policy, &secTrust);
4632N/A if(ortn) {
4632N/A cssmPerror("SecTrustCreateWithCertificates", ortn);
4632N/A goto errOut;
4632N/A }
4632N/A
4632N/A if(trustedAnchor) {
4632N/A /*
4632N/A * Tell SecTrust to trust this one in addition to the current
4632N/A * trusted system-wide anchors.
4632N/A */
4632N/A CFMutableArrayRef newAnchors;
4632N/A CFArrayRef currAnchors;
4632N/A
4632N/A ortn = SecTrustCopyAnchorCertificates(&currAnchors);
4632N/A if(ortn) {
4632N/A /* should never happen */
4632N/A cssmPerror("SecTrustCopyAnchorCertificates", ortn);
4632N/A goto errOut;
4632N/A }
4632N/A newAnchors = CFArrayCreateMutableCopy(NULL,
4632N/A CFArrayGetCount(currAnchors) + 1,
4632N/A currAnchors);
4632N/A CFRelease(currAnchors);
4632N/A CFArrayAppendValue(newAnchors, trustedAnchor);
4632N/A ortn = SecTrustSetAnchorCertificates(secTrust, newAnchors);
4632N/A CFRelease(newAnchors);
4632N/A if(ortn) {
4632N/A cssmPerror("SecTrustSetAnchorCertificates", ortn);
4632N/A goto errOut;
4632N/A }
4632N/A }
4632N/A
4632N/A /* evaluate: GO */
4632N/A ortn = SecTrustEvaluate(secTrust, &secTrustResult);
4632N/A if(ortn) {
4632N/A cssmPerror("SecTrustEvaluate", ortn);
4632N/A goto errOut;
4632N/A }
4632N/A switch(secTrustResult) {
4632N/A case kSecTrustResultUnspecified:
4632N/A /* cert chain valid, no special UserTrust assignments; drop thru */
4632N/A case kSecTrustResultProceed:
4632N/A /* cert chain valid AND user explicitly trusts this */
4632N/A break;
4632N/A default:
4632N/A /*
4632N/A * Cert chain construction failed.
4632N/A * Just go with the single subject cert we were given; maybe the
4632N/A * peer can complete the chain.
4632N/A */
4632N/A ortn = noErr;
4632N/A goto errOut;
4632N/A }
4632N/A
4632N/A /* get resulting constructed cert chain */
4632N/A ortn = SecTrustGetResult(secTrust, &secTrustResult, &certChain, &dummyEv);
4632N/A if(ortn) {
4632N/A cssmPerror("SecTrustEvaluate", ortn);
4632N/A goto errOut;
4632N/A }
4632N/A
4632N/A /*
4632N/A * Copy certs from constructed chain to our result array, skipping
4632N/A * the leaf (which is already there, as a SecIdentityRef) and possibly
4632N/A * a root.
4632N/A */
4632N/A numResCerts = CFArrayGetCount(certChain);
4632N/A if(numResCerts < 1) {
4632N/A /*
4632N/A * Can't happen: If chain doesn't verify to a root, we'd
4632N/A * have bailed after SecTrustEvaluate().
4632N/A */
4632N/A ortn = noErr;
4632N/A goto errOut;
4632N/A }
4632N/A if(!includeRoot) {
4632N/A /* skip the last (root) cert) */
4632N/A numResCerts--;
4632N/A }
4632N/A for(dex=1; dex<numResCerts; dex++) {
4632N/A certRef = (SecCertificateRef)CFArrayGetValueAtIndex(certChain, dex);
4632N/A CFArrayAppendValue(certArray, certRef);
4632N/A }
4632N/AerrOut:
4632N/A /* clean up */
4632N/A if(secTrust) {
4632N/A CFRelease(secTrust);
4632N/A }
4632N/A if(subjCerts) {
4632N/A CFRelease(subjCerts);
4632N/A }
4632N/A if(policy) {
4632N/A CFRelease(policy);
4632N/A }
4632N/A if(policySearch) {
4632N/A CFRelease(policySearch);
4632N/A }
4632N/A *outArray = certArray;
4632N/A return ortn;
4632N/A}
4632N/A
4632N/Astatic void addIdentitiesToKeystore(JNIEnv *env, jobject keyStore)
4632N/A{
4632N/A // Search the user keychain list for all identities. Identities are a certificate/private key association that
4632N/A // can be chosen for a purpose such as signing or an SSL connection.
4632N/A SecIdentitySearchRef identitySearch = NULL;
4632N/A OSStatus err = SecIdentitySearchCreate(NULL, CSSM_KEYUSE_ANY, &identitySearch);
4632N/A SecIdentityRef theIdentity = NULL;
4632N/A OSErr searchResult = noErr;
4632N/A
4632N/A do {
4632N/A searchResult = SecIdentitySearchCopyNext(identitySearch, &theIdentity);
4632N/A
4632N/A if (searchResult == noErr) {
4632N/A // Get the cert from the identity, then generate a chain.
4632N/A SecCertificateRef certificate;
4632N/A SecIdentityCopyCertificate(theIdentity, &certificate);
4632N/A CFArrayRef certChain = NULL;
4632N/A
4632N/A // *** Should do something with this error...
4632N/A err = completeCertChain(theIdentity, NULL, TRUE, &certChain);
4632N/A
4632N/A CFIndex i, certCount = CFArrayGetCount(certChain);
4632N/A
4632N/A // Make a java array of certificate data from the chain.
4632N/A jclass byteArrayClass = (*env)->FindClass(env, "[B");
4632N/A jobjectArray javaCertArray = (*env)->NewObjectArray(env, certCount, byteArrayClass, NULL);
4632N/A (*env)->DeleteLocalRef(env, byteArrayClass);
4632N/A
4632N/A // And, make an array of the certificate refs.
4632N/A jlongArray certRefArray = (*env)->NewLongArray(env, certCount);
4632N/A
4632N/A SecCertificateRef currCertRef = NULL;
4632N/A
4632N/A for (i = 0; i < certCount; i++) {
4632N/A CSSM_DATA currCertData;
4632N/A
4632N/A if (i == 0)
4632N/A currCertRef = certificate;
4632N/A else
4632N/A currCertRef = (SecCertificateRef)CFArrayGetValueAtIndex(certChain, i);
4632N/A
4632N/A bzero(&currCertData, sizeof(CSSM_DATA));
4632N/A err = SecCertificateGetData(currCertRef, &currCertData);
4632N/A jbyteArray encodedCertData = (*env)->NewByteArray(env, currCertData.Length);
4632N/A (*env)->SetByteArrayRegion(env, encodedCertData, 0, currCertData.Length, (jbyte *)currCertData.Data);
4632N/A (*env)->SetObjectArrayElement(env, javaCertArray, i, encodedCertData);
4632N/A jlong certRefElement = ptr_to_jlong(currCertRef);
4632N/A (*env)->SetLongArrayRegion(env, certRefArray, i, 1, &certRefElement);
4632N/A }
4632N/A
4632N/A // Get the private key. When needed we'll export the data from it later.
4632N/A SecKeyRef privateKeyRef;
4632N/A err = SecIdentityCopyPrivateKey(theIdentity, &privateKeyRef);
4632N/A
4632N/A // Find the label. It's a 'blob', but we interpret as characters.
4632N/A jstring alias = getLabelFromItem(env, (SecKeychainItemRef)certificate);
4632N/A
4632N/A // Find the creation date.
4632N/A jlong creationDate = getModDateFromItem(env, (SecKeychainItemRef)certificate);
4632N/A
4632N/A // Call back to the Java object to create Java objects corresponding to this security object.
4632N/A jlong nativeKeyRef = ptr_to_jlong(privateKeyRef);
4632N/A JNFCallVoidMethod(env, keyStore, jm_createKeyEntry, alias, creationDate, nativeKeyRef, certRefArray, javaCertArray);
4632N/A }
4632N/A } while (searchResult == noErr);
4632N/A
4632N/A if (identitySearch != NULL) {
4632N/A CFRelease(identitySearch);
4632N/A }
4632N/A}
4632N/A
4632N/Astatic void addCertificatesToKeystore(JNIEnv *env, jobject keyStore)
4632N/A{
4632N/A // Search the user keychain list for all X509 certificates.
4632N/A SecKeychainSearchRef keychainItemSearch = NULL;
4632N/A OSStatus err = SecKeychainSearchCreateFromAttributes(NULL, kSecCertificateItemClass, NULL, &keychainItemSearch);
4632N/A SecKeychainItemRef theItem = NULL;
4632N/A OSErr searchResult = noErr;
4632N/A
4632N/A do {
4632N/A searchResult = SecKeychainSearchCopyNext(keychainItemSearch, &theItem);
4632N/A
4632N/A if (searchResult == noErr) {
4632N/A // Make a byte array with the DER-encoded contents of the certificate.
4632N/A SecCertificateRef certRef = (SecCertificateRef)theItem;
4632N/A CSSM_DATA currCertificate;
4632N/A err = SecCertificateGetData(certRef, &currCertificate);
4632N/A jbyteArray certData = (*env)->NewByteArray(env, currCertificate.Length);
4632N/A (*env)->SetByteArrayRegion(env, certData, 0, currCertificate.Length, (jbyte *)currCertificate.Data);
4632N/A
4632N/A // Find the label. It's a 'blob', but we interpret as characters.
4632N/A jstring alias = getLabelFromItem(env, theItem);
4632N/A
4632N/A // Find the creation date.
4632N/A jlong creationDate = getModDateFromItem(env, theItem);
4632N/A
4632N/A // Call back to the Java object to create Java objects corresponding to this security object.
4632N/A jlong nativeRef = ptr_to_jlong(certRef);
4632N/A JNFCallVoidMethod(env, keyStore, jm_createTrustedCertEntry, alias, nativeRef, creationDate, certData);
4632N/A }
4632N/A } while (searchResult == noErr);
4632N/A
4632N/A if (keychainItemSearch != NULL) {
4632N/A CFRelease(keychainItemSearch);
4632N/A }
4632N/A}
4632N/A
4632N/A/*
4632N/A * Class: apple_security_KeychainStore
4632N/A * Method: _getEncodedKeyData
4632N/A * Signature: (J)[B
4632N/A */
4632N/AJNIEXPORT jbyteArray JNICALL Java_apple_security_KeychainStore__1getEncodedKeyData
4632N/A(JNIEnv *env, jobject this, jlong keyRefLong, jcharArray passwordObj)
4632N/A{
4632N/A SecKeyRef keyRef = (SecKeyRef)jlong_to_ptr(keyRefLong);
4632N/A SecKeyImportExportParameters paramBlock;
4632N/A OSStatus err = noErr;
4632N/A CFDataRef exportedData = NULL;
4632N/A jbyteArray returnValue = NULL;
4632N/A CFStringRef passwordStrRef = NULL;
4632N/A
4632N/A jsize passwordLen = 0;
4632N/A jchar *passwordChars = NULL;
4632N/A
4632N/A if (passwordObj) {
4632N/A passwordLen = (*env)->GetArrayLength(env, passwordObj);
4632N/A
4632N/A if (passwordLen > 0) {
4632N/A passwordChars = (*env)->GetCharArrayElements(env, passwordObj, NULL);
4632N/A passwordStrRef = CFStringCreateWithCharacters(kCFAllocatorDefault, passwordChars, passwordLen);
4632N/A }
4632N/A }
4632N/A
4632N/A paramBlock.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
4632N/A // Note that setting the flags field **requires** you to pass in a password of some kind. The keychain will not prompt you.
4632N/A paramBlock.flags = 0;
4632N/A paramBlock.passphrase = passwordStrRef;
4632N/A paramBlock.alertTitle = NULL;
4632N/A paramBlock.alertPrompt = NULL;
4632N/A paramBlock.accessRef = NULL;
4632N/A paramBlock.keyUsage = CSSM_KEYUSE_ANY;
4632N/A paramBlock.keyAttributes = CSSM_KEYATTR_RETURN_DEFAULT;
4632N/A
4632N/A err = SecKeychainItemExport(keyRef, kSecFormatPKCS12, 0, &paramBlock, &exportedData);
4632N/A
4632N/A if (err == noErr) {
4632N/A CFIndex size = CFDataGetLength(exportedData);
4632N/A returnValue = (*env)->NewByteArray(env, size);
4632N/A (*env)->SetByteArrayRegion(env, returnValue, 0, size, (jbyte *)CFDataGetBytePtr(exportedData));
4632N/A }
4632N/A
4632N/A if (exportedData) CFRelease(exportedData);
4632N/A if (passwordStrRef) CFRelease(passwordStrRef);
4632N/A
4632N/A return returnValue;
4632N/A}
4632N/A
4632N/A
4632N/A/*
4632N/A * Class: apple_security_KeychainStore
4632N/A * Method: _scanKeychain
4632N/A * Signature: ()V
4632N/A */
4632N/AJNIEXPORT void JNICALL Java_apple_security_KeychainStore__1scanKeychain
4632N/A(JNIEnv *env, jobject this)
4632N/A{
4632N/A // Look for 'identities' -- private key and certificate chain pairs -- and add those.
4632N/A // Search for these first, because a certificate that's found here as part of an identity will show up
4632N/A // again later as a certificate.
4632N/A addIdentitiesToKeystore(env, this);
4632N/A
4632N/A // Scan current keychain for trusted certificates.
4632N/A addCertificatesToKeystore(env, this);
4632N/A
4632N/A}
4632N/A
4632N/A/*
4632N/A * Class: apple_security_KeychainStore
4632N/A * Method: _addItemToKeychain
4632N/A * Signature: (Ljava/lang/String;[B)I
4632N/A*/
4632N/AJNIEXPORT jlong JNICALL Java_apple_security_KeychainStore__1addItemToKeychain
4632N/A(JNIEnv *env, jobject this, jstring alias, jboolean isCertificate, jbyteArray rawDataObj, jcharArray passwordObj)
4632N/A{
4632N/A OSStatus err;
4632N/A jlong returnValue = 0;
4632N/A
4632N/AJNF_COCOA_ENTER(env);
4632N/A
4632N/A jsize dataSize = (*env)->GetArrayLength(env, rawDataObj);
4632N/A jbyte *rawData = (*env)->GetByteArrayElements(env, rawDataObj, NULL);
4632N/A
4632N/A CFDataRef cfDataToImport = CFDataCreate(kCFAllocatorDefault, (UInt8 *)rawData, dataSize);
4632N/A CFArrayRef createdItems = NULL;
4632N/A
4632N/A SecKeychainRef defaultKeychain = NULL;
4632N/A SecKeychainCopyDefault(&defaultKeychain);
4632N/A
4632N/A SecExternalItemType dataType = (isCertificate == JNI_TRUE ? kSecFormatX509Cert : kSecFormatWrappedPKCS8);
4632N/A
4632N/A // Convert the password obj into a CFStringRef that the keychain importer can use for encryption.
4632N/A SecKeyImportExportParameters paramBlock;
4632N/A CFStringRef passwordStrRef = NULL;
4632N/A
4632N/A jsize passwordLen = 0;
4632N/A jchar *passwordChars = NULL;
4632N/A
4632N/A if (passwordObj) {
4632N/A passwordLen = (*env)->GetArrayLength(env, passwordObj);
4632N/A passwordChars = (*env)->GetCharArrayElements(env, passwordObj, NULL);
4632N/A passwordStrRef = CFStringCreateWithCharacters(kCFAllocatorDefault, passwordChars, passwordLen);
4632N/A }
4632N/A
4632N/A paramBlock.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
4632N/A // Note that setting the flags field **requires** you to pass in a password of some kind. The keychain will not prompt you.
4632N/A paramBlock.flags = 0;
4632N/A paramBlock.passphrase = passwordStrRef;
4632N/A paramBlock.alertTitle = NULL;
4632N/A paramBlock.alertPrompt = NULL;
4632N/A paramBlock.accessRef = NULL;
4632N/A paramBlock.keyUsage = CSSM_KEYUSE_ANY;
4632N/A paramBlock.keyAttributes = CSSM_KEYATTR_RETURN_DEFAULT;
4632N/A
4632N/A err = SecKeychainItemImport(cfDataToImport, NULL, &dataType, NULL,
4632N/A 0, &paramBlock, defaultKeychain, &createdItems);
4632N/A
4632N/A if (err == noErr) {
4632N/A SecKeychainItemRef anItem = (SecKeychainItemRef)CFArrayGetValueAtIndex(createdItems, 0);
4632N/A
4632N/A // Don't bother labeling keys. They become part of an identity, and are not an accessible part of the keychain.
4632N/A if (CFGetTypeID(anItem) == SecCertificateGetTypeID()) {
4632N/A setLabelForItem(JNFJavaToNSString(env, alias), anItem);
4632N/A }
4632N/A
4632N/A // Retain the item, since it will be released once when the array holding it gets released.
4632N/A CFRetain(anItem);
4632N/A returnValue = ptr_to_jlong(anItem);
4632N/A } else {
4632N/A cssmPerror("_addItemToKeychain: SecKeychainItemImport", err);
4632N/A }
4632N/A
4632N/A (*env)->ReleaseByteArrayElements(env, rawDataObj, rawData, JNI_ABORT);
4632N/A
4632N/A if (createdItems != NULL) {
4632N/A CFRelease(createdItems);
4632N/A }
4632N/A
4632N/AJNF_COCOA_EXIT(env);
4632N/A
4632N/A return returnValue;
4632N/A}
4632N/A
4632N/A/*
4632N/A * Class: apple_security_KeychainStore
4632N/A * Method: _removeItemFromKeychain
4632N/A * Signature: (J)I
4632N/A*/
4632N/AJNIEXPORT jint JNICALL Java_apple_security_KeychainStore__1removeItemFromKeychain
4632N/A(JNIEnv *env, jobject this, jlong keychainItem)
4632N/A{
4632N/A SecKeychainItemRef itemToRemove = jlong_to_ptr(keychainItem);
4632N/A return SecKeychainItemDelete(itemToRemove);
4632N/A}
4632N/A
4632N/A/*
4632N/A * Class: apple_security_KeychainStore
4632N/A * Method: _releaseKeychainItemRef
4632N/A * Signature: (J)V
4632N/A */
4632N/AJNIEXPORT void JNICALL Java_apple_security_KeychainStore__1releaseKeychainItemRef
4632N/A(JNIEnv *env, jobject this, jlong keychainItem)
4632N/A{
4632N/A SecKeychainItemRef itemToFree = jlong_to_ptr(keychainItem);
4632N/A CFRelease(itemToFree);
4632N/A}