1 /*
2 * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 #import "apple_security_KeychainStore.h"
27 #import "jni_util.h"
28
29 #import <Security/Security.h>
30 #import <Security/SecImportExport.h>
31 #import <CoreServices/CoreServices.h> // (for require() macros)
32 #import <JavaNativeFoundation/JavaNativeFoundation.h>
33
34
35 static JNF_CLASS_CACHE(jc_KeychainStore, "apple/security/KeychainStore");
36 static JNF_MEMBER_CACHE(jm_createTrustedCertEntry, jc_KeychainStore, "createTrustedCertEntry", "(Ljava/lang/String;JJ[B)V");
37 static JNF_MEMBER_CACHE(jm_createKeyEntry, jc_KeychainStore, "createKeyEntry", "(Ljava/lang/String;JJ[J[[B)V");
38
39 static jstring getLabelFromItem(JNIEnv *env, SecKeychainItemRef inItem)
40 {
41 OSStatus status;
42 jstring returnValue = NULL;
43 char *attribCString = NULL;
44
45 SecKeychainAttribute itemAttrs[] = { { kSecLabelItemAttr, 0, NULL } };
46 SecKeychainAttributeList attrList = { sizeof(itemAttrs) / sizeof(itemAttrs[0]), itemAttrs };
47
48 status = SecKeychainItemCopyContent(inItem, NULL, &attrList, NULL, NULL);
49
50 if(status) {
51 cssmPerror("getLabelFromItem: SecKeychainItemCopyContent", status);
52 goto errOut;
53 }
54
55 attribCString = malloc(itemAttrs[0].length + 1);
56 if (attribCString == NULL) {
57 JNU_ThrowOutOfMemoryError(env, "native heap");
273 if(policy) {
274 CFRelease(policy);
275 }
276 if(policySearch) {
277 CFRelease(policySearch);
278 }
279 *outArray = certArray;
280 return ortn;
281 }
282
283 static void addIdentitiesToKeystore(JNIEnv *env, jobject keyStore)
284 {
285 // Search the user keychain list for all identities. Identities are a certificate/private key association that
286 // can be chosen for a purpose such as signing or an SSL connection.
287 SecIdentitySearchRef identitySearch = NULL;
288 // Pass 0 if you want all identities returned by this search
289 OSStatus err = SecIdentitySearchCreate(NULL, 0, &identitySearch);
290 SecIdentityRef theIdentity = NULL;
291 OSErr searchResult = noErr;
292
293 do {
294 searchResult = SecIdentitySearchCopyNext(identitySearch, &theIdentity);
295
296 if (searchResult == noErr) {
297 // Get the cert from the identity, then generate a chain.
298 SecCertificateRef certificate;
299 SecIdentityCopyCertificate(theIdentity, &certificate);
300 CFArrayRef certChain = NULL;
301
302 // *** Should do something with this error...
303 err = completeCertChain(theIdentity, NULL, TRUE, &certChain);
304
305 CFIndex i, certCount = CFArrayGetCount(certChain);
306
307 // Make a java array of certificate data from the chain.
308 jclass byteArrayClass = (*env)->FindClass(env, "[B");
309 if (byteArrayClass == NULL) {
310 goto errOut;
311 }
312 jobjectArray javaCertArray = (*env)->NewObjectArray(env, certCount, byteArrayClass, NULL);
342 (*env)->SetObjectArrayElement(env, javaCertArray, i, encodedCertData);
343 jlong certRefElement = ptr_to_jlong(currCertRef);
344 (*env)->SetLongArrayRegion(env, certRefArray, i, 1, &certRefElement);
345 }
346
347 // Get the private key. When needed we'll export the data from it later.
348 SecKeyRef privateKeyRef;
349 err = SecIdentityCopyPrivateKey(theIdentity, &privateKeyRef);
350
351 // Find the label. It's a 'blob', but we interpret as characters.
352 jstring alias = getLabelFromItem(env, (SecKeychainItemRef)certificate);
353 if (alias == NULL) {
354 goto errOut;
355 }
356
357 // Find the creation date.
358 jlong creationDate = getModDateFromItem(env, (SecKeychainItemRef)certificate);
359
360 // Call back to the Java object to create Java objects corresponding to this security object.
361 jlong nativeKeyRef = ptr_to_jlong(privateKeyRef);
362 JNFCallVoidMethod(env, keyStore, jm_createKeyEntry, alias, creationDate, nativeKeyRef, certRefArray, javaCertArray);
363 }
364 } while (searchResult == noErr);
365
366 errOut:
367 if (identitySearch != NULL) {
368 CFRelease(identitySearch);
369 }
370 }
371
372 static void addCertificatesToKeystore(JNIEnv *env, jobject keyStore)
373 {
374 // Search the user keychain list for all X509 certificates.
375 SecKeychainSearchRef keychainItemSearch = NULL;
376 OSStatus err = SecKeychainSearchCreateFromAttributes(NULL, kSecCertificateItemClass, NULL, &keychainItemSearch);
377 SecKeychainItemRef theItem = NULL;
378 OSErr searchResult = noErr;
379
380 do {
381 searchResult = SecKeychainSearchCopyNext(keychainItemSearch, &theItem);
382
383 if (searchResult == noErr) {
384 // Make a byte array with the DER-encoded contents of the certificate.
385 SecCertificateRef certRef = (SecCertificateRef)theItem;
386 CSSM_DATA currCertificate;
387 err = SecCertificateGetData(certRef, &currCertificate);
388 jbyteArray certData = (*env)->NewByteArray(env, currCertificate.Length);
389 if (certData == NULL) {
390 goto errOut;
391 }
392 (*env)->SetByteArrayRegion(env, certData, 0, currCertificate.Length, (jbyte *)currCertificate.Data);
393
394 // Find the label. It's a 'blob', but we interpret as characters.
395 jstring alias = getLabelFromItem(env, theItem);
396 if (alias == NULL) {
397 goto errOut;
398 }
399
400 // Find the creation date.
401 jlong creationDate = getModDateFromItem(env, theItem);
402
403 // Call back to the Java object to create Java objects corresponding to this security object.
404 jlong nativeRef = ptr_to_jlong(certRef);
405 JNFCallVoidMethod(env, keyStore, jm_createTrustedCertEntry, alias, nativeRef, creationDate, certData);
406 }
407 } while (searchResult == noErr);
408
409 errOut:
410 if (keychainItemSearch != NULL) {
411 CFRelease(keychainItemSearch);
412 }
413 }
414
415 /*
416 * Class: apple_security_KeychainStore
417 * Method: _getEncodedKeyData
418 * Signature: (J)[B
419 */
420 JNIEXPORT jbyteArray JNICALL Java_apple_security_KeychainStore__1getEncodedKeyData
421 (JNIEnv *env, jobject this, jlong keyRefLong, jcharArray passwordObj)
422 {
423 SecKeyRef keyRef = (SecKeyRef)jlong_to_ptr(keyRefLong);
424 SecKeyImportExportParameters paramBlock;
425 OSStatus err = noErr;
483 /*
484 * Class: apple_security_KeychainStore
485 * Method: _scanKeychain
486 * Signature: ()V
487 */
488 JNIEXPORT void JNICALL Java_apple_security_KeychainStore__1scanKeychain
489 (JNIEnv *env, jobject this)
490 {
491 // Look for 'identities' -- private key and certificate chain pairs -- and add those.
492 // Search for these first, because a certificate that's found here as part of an identity will show up
493 // again later as a certificate.
494 addIdentitiesToKeystore(env, this);
495
496 JNU_CHECK_EXCEPTION(env);
497
498 // Scan current keychain for trusted certificates.
499 addCertificatesToKeystore(env, this);
500
501 }
502
503 /*
504 * Class: apple_security_KeychainStore
505 * Method: _addItemToKeychain
506 * Signature: (Ljava/lang/String;[B)I
507 */
508 JNIEXPORT jlong JNICALL Java_apple_security_KeychainStore__1addItemToKeychain
509 (JNIEnv *env, jobject this, jstring alias, jboolean isCertificate, jbyteArray rawDataObj, jcharArray passwordObj)
510 {
511 OSStatus err;
512 jlong returnValue = 0;
513
514 JNF_COCOA_ENTER(env);
515
516 jsize dataSize = (*env)->GetArrayLength(env, rawDataObj);
517 jbyte *rawData = (*env)->GetByteArrayElements(env, rawDataObj, NULL);
518 if (rawData == NULL) {
519 goto errOut;
520 }
521
522 CFDataRef cfDataToImport = CFDataCreate(kCFAllocatorDefault, (UInt8 *)rawData, dataSize);
523 CFArrayRef createdItems = NULL;
524
525 SecKeychainRef defaultKeychain = NULL;
526 SecKeychainCopyDefault(&defaultKeychain);
527
528 SecExternalFormat dataFormat = (isCertificate == JNI_TRUE ? kSecFormatX509Cert : kSecFormatWrappedPKCS8);
529
530 // Convert the password obj into a CFStringRef that the keychain importer can use for encryption.
531 SecKeyImportExportParameters paramBlock;
532 CFStringRef passwordStrRef = NULL;
533
534 jsize passwordLen = 0;
535 jchar *passwordChars = NULL;
554 // Note that setting the flags field **requires** you to pass in a password of some kind. The keychain will not prompt you.
555 paramBlock.flags = 0;
556 paramBlock.passphrase = passwordStrRef;
557 paramBlock.alertTitle = NULL;
558 paramBlock.alertPrompt = NULL;
559 paramBlock.accessRef = NULL;
560 paramBlock.keyUsage = CSSM_KEYUSE_ANY;
561 paramBlock.keyAttributes = CSSM_KEYATTR_RETURN_DEFAULT;
562
563 err = SecKeychainItemImport(cfDataToImport, NULL, &dataFormat, NULL,
564 0, ¶mBlock, defaultKeychain, &createdItems);
565 if (cfDataToImport != NULL) {
566 CFRelease(cfDataToImport);
567 }
568
569 if (err == noErr) {
570 SecKeychainItemRef anItem = (SecKeychainItemRef)CFArrayGetValueAtIndex(createdItems, 0);
571
572 // Don't bother labeling keys. They become part of an identity, and are not an accessible part of the keychain.
573 if (CFGetTypeID(anItem) == SecCertificateGetTypeID()) {
574 setLabelForItem(JNFJavaToNSString(env, alias), anItem);
575 }
576
577 // Retain the item, since it will be released once when the array holding it gets released.
578 CFRetain(anItem);
579 returnValue = ptr_to_jlong(anItem);
580 } else {
581 cssmPerror("_addItemToKeychain: SecKeychainItemImport", err);
582 }
583
584 if (createdItems != NULL) {
585 CFRelease(createdItems);
586 }
587
588 errOut:
589 if (rawData) {
590 (*env)->ReleaseByteArrayElements(env, rawDataObj, rawData, JNI_ABORT);
591 }
592
593 if (passwordStrRef) CFRelease(passwordStrRef);
594 if (passwordChars) {
595 // clear the password and release
596 memset(passwordChars, 0, passwordLen);
597 (*env)->ReleaseCharArrayElements(env, passwordObj, passwordChars,
598 JNI_ABORT);
599 }
600
601 JNF_COCOA_EXIT(env);
602
603 return returnValue;
604 }
605
606 /*
607 * Class: apple_security_KeychainStore
608 * Method: _removeItemFromKeychain
609 * Signature: (J)I
610 */
611 JNIEXPORT jint JNICALL Java_apple_security_KeychainStore__1removeItemFromKeychain
612 (JNIEnv *env, jobject this, jlong keychainItem)
613 {
614 SecKeychainItemRef itemToRemove = jlong_to_ptr(keychainItem);
615 return SecKeychainItemDelete(itemToRemove);
616 }
617
618 /*
619 * Class: apple_security_KeychainStore
620 * Method: _releaseKeychainItemRef
621 * Signature: (J)V
622 */
|
1 /*
2 * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 #import "apple_security_KeychainStore.h"
27 #import "jni_util.h"
28 #import <Security/Security.h>
29 #import <Security/SecImportExport.h>
30 #import <CoreServices/CoreServices.h> // (for require() macros)
31 #import <Cocoa/Cocoa.h>
32
33 static jstring getLabelFromItem(JNIEnv *env, SecKeychainItemRef inItem)
34 {
35 OSStatus status;
36 jstring returnValue = NULL;
37 char *attribCString = NULL;
38
39 SecKeychainAttribute itemAttrs[] = { { kSecLabelItemAttr, 0, NULL } };
40 SecKeychainAttributeList attrList = { sizeof(itemAttrs) / sizeof(itemAttrs[0]), itemAttrs };
41
42 status = SecKeychainItemCopyContent(inItem, NULL, &attrList, NULL, NULL);
43
44 if(status) {
45 cssmPerror("getLabelFromItem: SecKeychainItemCopyContent", status);
46 goto errOut;
47 }
48
49 attribCString = malloc(itemAttrs[0].length + 1);
50 if (attribCString == NULL) {
51 JNU_ThrowOutOfMemoryError(env, "native heap");
267 if(policy) {
268 CFRelease(policy);
269 }
270 if(policySearch) {
271 CFRelease(policySearch);
272 }
273 *outArray = certArray;
274 return ortn;
275 }
276
277 static void addIdentitiesToKeystore(JNIEnv *env, jobject keyStore)
278 {
279 // Search the user keychain list for all identities. Identities are a certificate/private key association that
280 // can be chosen for a purpose such as signing or an SSL connection.
281 SecIdentitySearchRef identitySearch = NULL;
282 // Pass 0 if you want all identities returned by this search
283 OSStatus err = SecIdentitySearchCreate(NULL, 0, &identitySearch);
284 SecIdentityRef theIdentity = NULL;
285 OSErr searchResult = noErr;
286
287 jclass jc_KeychainStore = (*env)->FindClass(env, "apple/security/KeychainStore");
288 CHECK_NULL(jc_KeychainStore);
289 jmethodID jm_createKeyEntry = (*env)->GetMethodID(env, jc_KeychainStore, "createKeyEntry", "(Ljava/lang/String;JJ[J[[B)V");
290 CHECK_NULL(jm_createKeyEntry);
291 do {
292 searchResult = SecIdentitySearchCopyNext(identitySearch, &theIdentity);
293
294 if (searchResult == noErr) {
295 // Get the cert from the identity, then generate a chain.
296 SecCertificateRef certificate;
297 SecIdentityCopyCertificate(theIdentity, &certificate);
298 CFArrayRef certChain = NULL;
299
300 // *** Should do something with this error...
301 err = completeCertChain(theIdentity, NULL, TRUE, &certChain);
302
303 CFIndex i, certCount = CFArrayGetCount(certChain);
304
305 // Make a java array of certificate data from the chain.
306 jclass byteArrayClass = (*env)->FindClass(env, "[B");
307 if (byteArrayClass == NULL) {
308 goto errOut;
309 }
310 jobjectArray javaCertArray = (*env)->NewObjectArray(env, certCount, byteArrayClass, NULL);
340 (*env)->SetObjectArrayElement(env, javaCertArray, i, encodedCertData);
341 jlong certRefElement = ptr_to_jlong(currCertRef);
342 (*env)->SetLongArrayRegion(env, certRefArray, i, 1, &certRefElement);
343 }
344
345 // Get the private key. When needed we'll export the data from it later.
346 SecKeyRef privateKeyRef;
347 err = SecIdentityCopyPrivateKey(theIdentity, &privateKeyRef);
348
349 // Find the label. It's a 'blob', but we interpret as characters.
350 jstring alias = getLabelFromItem(env, (SecKeychainItemRef)certificate);
351 if (alias == NULL) {
352 goto errOut;
353 }
354
355 // Find the creation date.
356 jlong creationDate = getModDateFromItem(env, (SecKeychainItemRef)certificate);
357
358 // Call back to the Java object to create Java objects corresponding to this security object.
359 jlong nativeKeyRef = ptr_to_jlong(privateKeyRef);
360 (*env)->CallVoidMethod(env, keyStore, jm_createKeyEntry, alias, creationDate, nativeKeyRef, certRefArray, javaCertArray);
361 JNU_CHECK_EXCEPTION(env);
362 }
363 } while (searchResult == noErr);
364
365 errOut:
366 if (identitySearch != NULL) {
367 CFRelease(identitySearch);
368 }
369 }
370
371 static void addCertificatesToKeystore(JNIEnv *env, jobject keyStore)
372 {
373 // Search the user keychain list for all X509 certificates.
374 SecKeychainSearchRef keychainItemSearch = NULL;
375 OSStatus err = SecKeychainSearchCreateFromAttributes(NULL, kSecCertificateItemClass, NULL, &keychainItemSearch);
376 SecKeychainItemRef theItem = NULL;
377 OSErr searchResult = noErr;
378
379 jclass jc_KeychainStore = (*env)->FindClass(env, "apple/security/KeychainStore");
380 CHECK_NULL(jc_KeychainStore);
381 jmethodID jm_createTrustedCertEntry = (*env)->GetMethodID(
382 env, jc_KeychainStore, "createTrustedCertEntry", "(Ljava/lang/String;JJ[B)V");
383 CHECK_NULL(jm_createTrustedCertEntry);
384 do {
385 searchResult = SecKeychainSearchCopyNext(keychainItemSearch, &theItem);
386
387 if (searchResult == noErr) {
388 // Make a byte array with the DER-encoded contents of the certificate.
389 SecCertificateRef certRef = (SecCertificateRef)theItem;
390 CSSM_DATA currCertificate;
391 err = SecCertificateGetData(certRef, &currCertificate);
392 jbyteArray certData = (*env)->NewByteArray(env, currCertificate.Length);
393 if (certData == NULL) {
394 goto errOut;
395 }
396 (*env)->SetByteArrayRegion(env, certData, 0, currCertificate.Length, (jbyte *)currCertificate.Data);
397
398 // Find the label. It's a 'blob', but we interpret as characters.
399 jstring alias = getLabelFromItem(env, theItem);
400 if (alias == NULL) {
401 goto errOut;
402 }
403
404 // Find the creation date.
405 jlong creationDate = getModDateFromItem(env, theItem);
406
407 // Call back to the Java object to create Java objects corresponding to this security object.
408 jlong nativeRef = ptr_to_jlong(certRef);
409 (*env)->CallVoidMethod(env, keyStore, jm_createTrustedCertEntry, alias, nativeRef, creationDate, certData);
410 JNU_CHECK_EXCEPTION(env);
411 }
412 } while (searchResult == noErr);
413
414 errOut:
415 if (keychainItemSearch != NULL) {
416 CFRelease(keychainItemSearch);
417 }
418 }
419
420 /*
421 * Class: apple_security_KeychainStore
422 * Method: _getEncodedKeyData
423 * Signature: (J)[B
424 */
425 JNIEXPORT jbyteArray JNICALL Java_apple_security_KeychainStore__1getEncodedKeyData
426 (JNIEnv *env, jobject this, jlong keyRefLong, jcharArray passwordObj)
427 {
428 SecKeyRef keyRef = (SecKeyRef)jlong_to_ptr(keyRefLong);
429 SecKeyImportExportParameters paramBlock;
430 OSStatus err = noErr;
488 /*
489 * Class: apple_security_KeychainStore
490 * Method: _scanKeychain
491 * Signature: ()V
492 */
493 JNIEXPORT void JNICALL Java_apple_security_KeychainStore__1scanKeychain
494 (JNIEnv *env, jobject this)
495 {
496 // Look for 'identities' -- private key and certificate chain pairs -- and add those.
497 // Search for these first, because a certificate that's found here as part of an identity will show up
498 // again later as a certificate.
499 addIdentitiesToKeystore(env, this);
500
501 JNU_CHECK_EXCEPTION(env);
502
503 // Scan current keychain for trusted certificates.
504 addCertificatesToKeystore(env, this);
505
506 }
507
508 NSString* JavaStringToNSString(JNIEnv *env, jstring jstr) {
509 if (jstr == NULL) {
510 return NULL;
511 }
512 jsize len = (*env)->GetStringLength(env, jstr);
513 const jchar *chars = (*env)->GetStringChars(env, jstr, NULL);
514 if (chars == NULL) {
515 return NULL;
516 }
517 NSString *result = [NSString stringWithCharacters:(UniChar *)chars length:len];
518 (*env)->ReleaseStringChars(env, jstr, chars);
519 return result;
520 }
521
522 /*
523 * Class: apple_security_KeychainStore
524 * Method: _addItemToKeychain
525 * Signature: (Ljava/lang/String;[B)I
526 */
527 JNIEXPORT jlong JNICALL Java_apple_security_KeychainStore__1addItemToKeychain
528 (JNIEnv *env, jobject this, jstring alias, jboolean isCertificate, jbyteArray rawDataObj, jcharArray passwordObj)
529 {
530 OSStatus err;
531 jlong returnValue = 0;
532
533 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; \
534 @try {
535 jsize dataSize = (*env)->GetArrayLength(env, rawDataObj);
536 jbyte *rawData = (*env)->GetByteArrayElements(env, rawDataObj, NULL);
537 if (rawData == NULL) {
538 goto errOut;
539 }
540
541 CFDataRef cfDataToImport = CFDataCreate(kCFAllocatorDefault, (UInt8 *)rawData, dataSize);
542 CFArrayRef createdItems = NULL;
543
544 SecKeychainRef defaultKeychain = NULL;
545 SecKeychainCopyDefault(&defaultKeychain);
546
547 SecExternalFormat dataFormat = (isCertificate == JNI_TRUE ? kSecFormatX509Cert : kSecFormatWrappedPKCS8);
548
549 // Convert the password obj into a CFStringRef that the keychain importer can use for encryption.
550 SecKeyImportExportParameters paramBlock;
551 CFStringRef passwordStrRef = NULL;
552
553 jsize passwordLen = 0;
554 jchar *passwordChars = NULL;
573 // Note that setting the flags field **requires** you to pass in a password of some kind. The keychain will not prompt you.
574 paramBlock.flags = 0;
575 paramBlock.passphrase = passwordStrRef;
576 paramBlock.alertTitle = NULL;
577 paramBlock.alertPrompt = NULL;
578 paramBlock.accessRef = NULL;
579 paramBlock.keyUsage = CSSM_KEYUSE_ANY;
580 paramBlock.keyAttributes = CSSM_KEYATTR_RETURN_DEFAULT;
581
582 err = SecKeychainItemImport(cfDataToImport, NULL, &dataFormat, NULL,
583 0, ¶mBlock, defaultKeychain, &createdItems);
584 if (cfDataToImport != NULL) {
585 CFRelease(cfDataToImport);
586 }
587
588 if (err == noErr) {
589 SecKeychainItemRef anItem = (SecKeychainItemRef)CFArrayGetValueAtIndex(createdItems, 0);
590
591 // Don't bother labeling keys. They become part of an identity, and are not an accessible part of the keychain.
592 if (CFGetTypeID(anItem) == SecCertificateGetTypeID()) {
593 setLabelForItem(JavaStringToNSString(env, alias), anItem);
594 }
595
596 // Retain the item, since it will be released once when the array holding it gets released.
597 CFRetain(anItem);
598 returnValue = ptr_to_jlong(anItem);
599 } else {
600 cssmPerror("_addItemToKeychain: SecKeychainItemImport", err);
601 }
602
603 if (createdItems != NULL) {
604 CFRelease(createdItems);
605 }
606
607 errOut:
608 if (rawData) {
609 (*env)->ReleaseByteArrayElements(env, rawDataObj, rawData, JNI_ABORT);
610 }
611
612 if (passwordStrRef) CFRelease(passwordStrRef);
613 if (passwordChars) {
614 // clear the password and release
615 memset(passwordChars, 0, passwordLen);
616 (*env)->ReleaseCharArrayElements(env, passwordObj, passwordChars,
617 JNI_ABORT);
618 }
619 } @catch (NSException *e) {
620 NSLog(@"%@", [e callStackSymbols]);
621 } @finally {
622 [pool drain];
623 }
624 return returnValue;
625 }
626
627 /*
628 * Class: apple_security_KeychainStore
629 * Method: _removeItemFromKeychain
630 * Signature: (J)I
631 */
632 JNIEXPORT jint JNICALL Java_apple_security_KeychainStore__1removeItemFromKeychain
633 (JNIEnv *env, jobject this, jlong keychainItem)
634 {
635 SecKeychainItemRef itemToRemove = jlong_to_ptr(keychainItem);
636 return SecKeychainItemDelete(itemToRemove);
637 }
638
639 /*
640 * Class: apple_security_KeychainStore
641 * Method: _releaseKeychainItemRef
642 * Signature: (J)V
643 */
|