1
1
/*
2
- * Copyright (c) 2011, 2019 , Oracle and/or its affiliates. All rights reserved.
2
+ * Copyright (c) 2011, 2021 , Oracle and/or its affiliates. All rights reserved.
3
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
4
*
5
5
* This code is free software; you can redistribute it and/or modify it
25
25
26
26
#import " apple_security_KeychainStore.h"
27
27
#import " jni_util.h"
28
-
29
28
#import < Security/Security.h>
30
29
#import < Security/SecImportExport.h>
31
30
#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" );
31
+ #import < Cocoa/Cocoa.h>
38
32
39
33
static jstring getLabelFromItem (JNIEnv *env, SecKeychainItemRef inItem)
40
34
{
@@ -290,6 +284,10 @@ static void addIdentitiesToKeystore(JNIEnv *env, jobject keyStore)
290
284
SecIdentityRef theIdentity = NULL ;
291
285
OSErr searchResult = noErr ;
292
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);
293
291
do {
294
292
searchResult = SecIdentitySearchCopyNext (identitySearch, &theIdentity);
295
293
@@ -359,7 +357,8 @@ static void addIdentitiesToKeystore(JNIEnv *env, jobject keyStore)
359
357
360
358
// Call back to the Java object to create Java objects corresponding to this security object.
361
359
jlong nativeKeyRef = ptr_to_jlong (privateKeyRef);
362
- JNFCallVoidMethod (env, keyStore, jm_createKeyEntry, alias, creationDate, nativeKeyRef, certRefArray, javaCertArray);
360
+ (*env)->CallVoidMethod (env, keyStore, jm_createKeyEntry, alias, creationDate, nativeKeyRef, certRefArray, javaCertArray);
361
+ JNU_CHECK_EXCEPTION (env);
363
362
}
364
363
} while (searchResult == noErr );
365
364
@@ -377,6 +376,11 @@ static void addCertificatesToKeystore(JNIEnv *env, jobject keyStore)
377
376
SecKeychainItemRef theItem = NULL ;
378
377
OSErr searchResult = noErr ;
379
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);
380
384
do {
381
385
searchResult = SecKeychainSearchCopyNext (keychainItemSearch, &theItem);
382
386
@@ -402,7 +406,8 @@ static void addCertificatesToKeystore(JNIEnv *env, jobject keyStore)
402
406
403
407
// Call back to the Java object to create Java objects corresponding to this security object.
404
408
jlong nativeRef = ptr_to_jlong (certRef);
405
- JNFCallVoidMethod (env, keyStore, jm_createTrustedCertEntry, alias, nativeRef, creationDate, certData);
409
+ (*env)->CallVoidMethod (env, keyStore, jm_createTrustedCertEntry, alias, nativeRef, creationDate, certData);
410
+ JNU_CHECK_EXCEPTION (env);
406
411
}
407
412
} while (searchResult == noErr );
408
413
@@ -500,6 +505,20 @@ static void addCertificatesToKeystore(JNIEnv *env, jobject keyStore)
500
505
501
506
}
502
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
+
503
522
/*
504
523
* Class: apple_security_KeychainStore
505
524
* Method: _addItemToKeychain
@@ -511,95 +530,97 @@ static void addCertificatesToKeystore(JNIEnv *env, jobject keyStore)
511
530
OSStatus err;
512
531
jlong returnValue = 0 ;
513
532
514
- JNF_COCOA_ENTER (env);
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
+ }
515
540
516
- jsize dataSize = (*env)->GetArrayLength (env, rawDataObj);
517
- jbyte *rawData = (*env)->GetByteArrayElements (env, rawDataObj, NULL );
518
- if (rawData == NULL ) {
519
- goto errOut;
520
- }
541
+ CFDataRef cfDataToImport = CFDataCreate (kCFAllocatorDefault , (UInt8 *)rawData, dataSize);
542
+ CFArrayRef createdItems = NULL ;
521
543
522
- CFDataRef cfDataToImport = CFDataCreate ( kCFAllocatorDefault , ( UInt8 *)rawData, dataSize) ;
523
- CFArrayRef createdItems = NULL ;
544
+ SecKeychainRef defaultKeychain = NULL ;
545
+ SecKeychainCopyDefault (&defaultKeychain) ;
524
546
525
- SecKeychainRef defaultKeychain = NULL ;
526
- SecKeychainCopyDefault (&defaultKeychain);
547
+ SecExternalFormat dataFormat = (isCertificate == JNI_TRUE ? kSecFormatX509Cert : kSecFormatWrappedPKCS8 );
527
548
528
- SecExternalFormat dataFormat = (isCertificate == JNI_TRUE ? kSecFormatX509Cert : kSecFormatWrappedPKCS8 );
549
+ // Convert the password obj into a CFStringRef that the keychain importer can use for encryption.
550
+ SecKeyImportExportParameters paramBlock;
551
+ CFStringRef passwordStrRef = NULL ;
529
552
530
- // Convert the password obj into a CFStringRef that the keychain importer can use for encryption.
531
- SecKeyImportExportParameters paramBlock;
532
- CFStringRef passwordStrRef = NULL ;
553
+ jsize passwordLen = 0 ;
554
+ jchar *passwordChars = NULL ;
533
555
534
- jsize passwordLen = 0 ;
535
- jchar *passwordChars = NULL ;
556
+ if (passwordObj) {
557
+ passwordLen = (*env)-> GetArrayLength (env, passwordObj) ;
536
558
537
- if (passwordObj) {
538
- passwordLen = (*env)->GetArrayLength (env, passwordObj);
539
-
540
- if (passwordLen > 0 ) {
541
- passwordChars = (*env)->GetCharArrayElements (env, passwordObj, NULL );
542
- if (passwordChars == NULL ) {
543
- goto errOut;
544
- }
559
+ if (passwordLen > 0 ) {
560
+ passwordChars = (*env)->GetCharArrayElements (env, passwordObj, NULL );
561
+ if (passwordChars == NULL ) {
562
+ goto errOut;
563
+ }
545
564
546
- passwordStrRef = CFStringCreateWithCharactersNoCopy (NULL , passwordChars, passwordLen, kCFAllocatorNull );
547
- if (passwordStrRef == NULL ) {
548
- goto errOut;
565
+ passwordStrRef = CFStringCreateWithCharactersNoCopy (NULL , passwordChars, passwordLen, kCFAllocatorNull );
566
+ if (passwordStrRef == NULL ) {
567
+ goto errOut;
568
+ }
549
569
}
550
570
}
551
- }
552
571
553
- paramBlock.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
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;
572
+ paramBlock.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
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
+ }
562
587
563
- err = SecKeychainItemImport (cfDataToImport, NULL , &dataFormat, NULL ,
564
- 0 , ¶mBlock, defaultKeychain, &createdItems);
565
- if (cfDataToImport != NULL ) {
566
- CFRelease (cfDataToImport);
567
- }
588
+ if (err == noErr ) {
589
+ SecKeychainItemRef anItem = (SecKeychainItemRef)CFArrayGetValueAtIndex (createdItems, 0 );
568
590
569
- if (err == noErr ) {
570
- SecKeychainItemRef anItem = (SecKeychainItemRef)CFArrayGetValueAtIndex (createdItems, 0 );
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
+ }
571
595
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);
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);
575
601
}
576
602
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
- }
603
+ if (createdItems != NULL ) {
604
+ CFRelease (createdItems);
605
+ }
587
606
588
- errOut:
589
- if (rawData) {
590
- (*env)->ReleaseByteArrayElements (env, rawDataObj, rawData, JNI_ABORT);
591
- }
607
+ errOut:
608
+ if (rawData) {
609
+ (*env)->ReleaseByteArrayElements (env, rawDataObj, rawData, JNI_ABORT);
610
+ }
592
611
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);
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 ];
599
623
}
600
-
601
- JNF_COCOA_EXIT (env);
602
-
603
624
return returnValue;
604
625
}
605
626
0 commit comments