< prev index next >

src/java.base/macosx/native/libosxsecurity/KeystoreImpl.m

Print this page
rev 54093 : 8257858: [macOS]: Remove JNF dependency from libosxsecurity/KeystoreImpl.m
8257860: [macOS]: Remove JNF dependency from libosxkrb5/SCDynamicStoreConfig.m
   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, &paramBlock, 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, &paramBlock, 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  */
< prev index next >