Skip to content
This repository has been archived by the owner on Feb 2, 2023. It is now read-only.

Commit

Permalink
8257858: [macOS]: Remove JNF dependency from libosxsecurity/KeystoreI…
Browse files Browse the repository at this point in the history
…mpl.m

8257860: [macOS]: Remove JNF dependency from libosxkrb5/SCDynamicStoreConfig.m

Backport-of: 4a8b5c1602789e95457cbb080a64c56edaf81051
  • Loading branch information
Vladimir Kempik committed Apr 2, 2021
1 parent c565a2b commit 0da4bb8
Show file tree
Hide file tree
Showing 12 changed files with 488 additions and 436 deletions.
2 changes: 1 addition & 1 deletion make/common/TestFilesCompilation.gmk
Expand Up @@ -77,7 +77,7 @@ define SetupTestFilesCompilationBody

# Locate all files with the matching prefix
$1_FILE_LIST := \
$$(call FindFiles, $$($1_SOURCE_DIRS), $$($1_PREFIX)*.c $$($1_PREFIX)*.cpp)
$$(call FindFiles, $$($1_SOURCE_DIRS), $$($1_PREFIX)*.c $$($1_PREFIX)*.cpp $$($1_PREFIX)*.m)

$1_EXCLUDE_PATTERN := $$(addprefix %/, $$($1_EXCLUDE))
$1_FILTERED_FILE_LIST := $$(filter-out $$($1_EXCLUDE_PATTERN), $$($1_FILE_LIST))
Expand Down
4 changes: 2 additions & 2 deletions make/modules/java.base/Lib.gmk
@@ -1,5 +1,5 @@
#
# Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -110,9 +110,9 @@ ifeq ($(call isTargetOs, macosx), true)
$(call SET_SHARED_LIBRARY_ORIGIN), \
LIBS := \
-lobjc \
-framework JavaNativeFoundation \
-framework CoreServices \
-framework Security \
-framework Foundation \
$(JDKLIB_LIBS), \
))

Expand Down
6 changes: 3 additions & 3 deletions make/modules/java.security.jgss/Lib.gmk
@@ -1,5 +1,5 @@
#
# Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -80,8 +80,8 @@ ifneq ($(BUILD_CRYPTO), false)
DISABLED_WARNINGS_clang := deprecated-declarations, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
LIBS := -framework JavaNativeFoundation -framework Cocoa \
-framework SystemConfiguration -framework Kerberos, \
LIBS := -framework Cocoa -framework SystemConfiguration \
-framework Kerberos, \
))

TARGETS += $(BUILD_LIBOSXKRB5)
Expand Down
8 changes: 5 additions & 3 deletions make/test/JtregNativeJdk.gmk
@@ -1,5 +1,5 @@
#
# Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -77,13 +77,15 @@ endif

ifeq ($(call isTargetOs, macosx), true)
BUILD_JDK_JTREG_EXCLUDE += exelauncher.c
BUILD_JDK_JTREG_LIBRARIES_CFLAGS_libTestMainKeyWindow := -ObjC
BUILD_JDK_JTREG_LIBRARIES_LIBS_libTestMainKeyWindow := \
-framework Cocoa -framework JavaNativeFoundation
BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeJniInvocationTest := -ljli
BUILD_JDK_JTREG_LIBRARIES_LIBS_libTestDynamicStore := \
-framework Cocoa -framework SystemConfiguration
else
BUILD_JDK_JTREG_EXCLUDE += libTestMainKeyWindow.c
BUILD_JDK_JTREG_EXCLUDE += libTestMainKeyWindow.m
BUILD_JDK_JTREG_EXCLUDE += exeJniInvocationTest.c
BUILD_JDK_JTREG_EXCLUDE += libTestDynamicStore.m
endif

ifeq ($(call isTargetOs, linux), true)
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -815,8 +815,8 @@ private void createTrustedCertEntry(String alias, long keychainItemRef, long cre
* Callback method from _scanKeychain. If an identity is found, this method will be called to create Java certificate
* and private key objects from the keychain data.
*/
private void createKeyEntry(String alias, long creationDate, long secKeyRef, long[] secCertificateRefs, byte[][] rawCertData)
throws IOException, NoSuchAlgorithmException, UnrecoverableKeyException {
private void createKeyEntry(String alias, long creationDate, long secKeyRef,
long[] secCertificateRefs, byte[][] rawCertData) {
KeyEntry ke = new KeyEntry();

// First, store off the private key information. This is the easy part.
Expand Down
181 changes: 101 additions & 80 deletions src/java.base/macosx/native/libosxsecurity/KeystoreImpl.m
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand All @@ -25,16 +25,10 @@

#import "apple_security_KeychainStore.h"
#import "jni_util.h"

#import <Security/Security.h>
#import <Security/SecImportExport.h>
#import <CoreServices/CoreServices.h> // (for require() macros)
#import <JavaNativeFoundation/JavaNativeFoundation.h>


static JNF_CLASS_CACHE(jc_KeychainStore, "apple/security/KeychainStore");
static JNF_MEMBER_CACHE(jm_createTrustedCertEntry, jc_KeychainStore, "createTrustedCertEntry", "(Ljava/lang/String;JJ[B)V");
static JNF_MEMBER_CACHE(jm_createKeyEntry, jc_KeychainStore, "createKeyEntry", "(Ljava/lang/String;JJ[J[[B)V");
#import <Cocoa/Cocoa.h>

static jstring getLabelFromItem(JNIEnv *env, SecKeychainItemRef inItem)
{
Expand Down Expand Up @@ -290,6 +284,10 @@ static void addIdentitiesToKeystore(JNIEnv *env, jobject keyStore)
SecIdentityRef theIdentity = NULL;
OSErr searchResult = noErr;

jclass jc_KeychainStore = (*env)->FindClass(env, "apple/security/KeychainStore");
CHECK_NULL(jc_KeychainStore);
jmethodID jm_createKeyEntry = (*env)->GetMethodID(env, jc_KeychainStore, "createKeyEntry", "(Ljava/lang/String;JJ[J[[B)V");
CHECK_NULL(jm_createKeyEntry);
do {
searchResult = SecIdentitySearchCopyNext(identitySearch, &theIdentity);

Expand Down Expand Up @@ -359,7 +357,8 @@ static void addIdentitiesToKeystore(JNIEnv *env, jobject keyStore)

// Call back to the Java object to create Java objects corresponding to this security object.
jlong nativeKeyRef = ptr_to_jlong(privateKeyRef);
JNFCallVoidMethod(env, keyStore, jm_createKeyEntry, alias, creationDate, nativeKeyRef, certRefArray, javaCertArray);
(*env)->CallVoidMethod(env, keyStore, jm_createKeyEntry, alias, creationDate, nativeKeyRef, certRefArray, javaCertArray);
JNU_CHECK_EXCEPTION(env);
}
} while (searchResult == noErr);

Expand All @@ -377,6 +376,11 @@ static void addCertificatesToKeystore(JNIEnv *env, jobject keyStore)
SecKeychainItemRef theItem = NULL;
OSErr searchResult = noErr;

jclass jc_KeychainStore = (*env)->FindClass(env, "apple/security/KeychainStore");
CHECK_NULL(jc_KeychainStore);
jmethodID jm_createTrustedCertEntry = (*env)->GetMethodID(
env, jc_KeychainStore, "createTrustedCertEntry", "(Ljava/lang/String;JJ[B)V");
CHECK_NULL(jm_createTrustedCertEntry);
do {
searchResult = SecKeychainSearchCopyNext(keychainItemSearch, &theItem);

Expand All @@ -402,7 +406,8 @@ static void addCertificatesToKeystore(JNIEnv *env, jobject keyStore)

// Call back to the Java object to create Java objects corresponding to this security object.
jlong nativeRef = ptr_to_jlong(certRef);
JNFCallVoidMethod(env, keyStore, jm_createTrustedCertEntry, alias, nativeRef, creationDate, certData);
(*env)->CallVoidMethod(env, keyStore, jm_createTrustedCertEntry, alias, nativeRef, creationDate, certData);
JNU_CHECK_EXCEPTION(env);
}
} while (searchResult == noErr);

Expand Down Expand Up @@ -500,6 +505,20 @@ static void addCertificatesToKeystore(JNIEnv *env, jobject keyStore)

}

NSString* JavaStringToNSString(JNIEnv *env, jstring jstr) {
if (jstr == NULL) {
return NULL;
}
jsize len = (*env)->GetStringLength(env, jstr);
const jchar *chars = (*env)->GetStringChars(env, jstr, NULL);
if (chars == NULL) {
return NULL;
}
NSString *result = [NSString stringWithCharacters:(UniChar *)chars length:len];
(*env)->ReleaseStringChars(env, jstr, chars);
return result;
}

/*
* Class: apple_security_KeychainStore
* Method: _addItemToKeychain
Expand All @@ -511,95 +530,97 @@ static void addCertificatesToKeystore(JNIEnv *env, jobject keyStore)
OSStatus err;
jlong returnValue = 0;

JNF_COCOA_ENTER(env);
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; \
@try {
jsize dataSize = (*env)->GetArrayLength(env, rawDataObj);
jbyte *rawData = (*env)->GetByteArrayElements(env, rawDataObj, NULL);
if (rawData == NULL) {
goto errOut;
}

jsize dataSize = (*env)->GetArrayLength(env, rawDataObj);
jbyte *rawData = (*env)->GetByteArrayElements(env, rawDataObj, NULL);
if (rawData == NULL) {
goto errOut;
}
CFDataRef cfDataToImport = CFDataCreate(kCFAllocatorDefault, (UInt8 *)rawData, dataSize);
CFArrayRef createdItems = NULL;

CFDataRef cfDataToImport = CFDataCreate(kCFAllocatorDefault, (UInt8 *)rawData, dataSize);
CFArrayRef createdItems = NULL;
SecKeychainRef defaultKeychain = NULL;
SecKeychainCopyDefault(&defaultKeychain);

SecKeychainRef defaultKeychain = NULL;
SecKeychainCopyDefault(&defaultKeychain);
SecExternalFormat dataFormat = (isCertificate == JNI_TRUE ? kSecFormatX509Cert : kSecFormatWrappedPKCS8);

SecExternalFormat dataFormat = (isCertificate == JNI_TRUE ? kSecFormatX509Cert : kSecFormatWrappedPKCS8);
// Convert the password obj into a CFStringRef that the keychain importer can use for encryption.
SecKeyImportExportParameters paramBlock;
CFStringRef passwordStrRef = NULL;

// Convert the password obj into a CFStringRef that the keychain importer can use for encryption.
SecKeyImportExportParameters paramBlock;
CFStringRef passwordStrRef = NULL;
jsize passwordLen = 0;
jchar *passwordChars = NULL;

jsize passwordLen = 0;
jchar *passwordChars = NULL;
if (passwordObj) {
passwordLen = (*env)->GetArrayLength(env, passwordObj);

if (passwordObj) {
passwordLen = (*env)->GetArrayLength(env, passwordObj);

if (passwordLen > 0) {
passwordChars = (*env)->GetCharArrayElements(env, passwordObj, NULL);
if (passwordChars == NULL) {
goto errOut;
}
if (passwordLen > 0) {
passwordChars = (*env)->GetCharArrayElements(env, passwordObj, NULL);
if (passwordChars == NULL) {
goto errOut;
}

passwordStrRef = CFStringCreateWithCharactersNoCopy(NULL, passwordChars, passwordLen, kCFAllocatorNull);
if (passwordStrRef == NULL) {
goto errOut;
passwordStrRef = CFStringCreateWithCharactersNoCopy(NULL, passwordChars, passwordLen, kCFAllocatorNull);
if (passwordStrRef == NULL) {
goto errOut;
}
}
}
}

paramBlock.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
// Note that setting the flags field **requires** you to pass in a password of some kind. The keychain will not prompt you.
paramBlock.flags = 0;
paramBlock.passphrase = passwordStrRef;
paramBlock.alertTitle = NULL;
paramBlock.alertPrompt = NULL;
paramBlock.accessRef = NULL;
paramBlock.keyUsage = CSSM_KEYUSE_ANY;
paramBlock.keyAttributes = CSSM_KEYATTR_RETURN_DEFAULT;
paramBlock.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
// Note that setting the flags field **requires** you to pass in a password of some kind. The keychain will not prompt you.
paramBlock.flags = 0;
paramBlock.passphrase = passwordStrRef;
paramBlock.alertTitle = NULL;
paramBlock.alertPrompt = NULL;
paramBlock.accessRef = NULL;
paramBlock.keyUsage = CSSM_KEYUSE_ANY;
paramBlock.keyAttributes = CSSM_KEYATTR_RETURN_DEFAULT;

err = SecKeychainItemImport(cfDataToImport, NULL, &dataFormat, NULL,
0, &paramBlock, defaultKeychain, &createdItems);
if (cfDataToImport != NULL) {
CFRelease(cfDataToImport);
}

err = SecKeychainItemImport(cfDataToImport, NULL, &dataFormat, NULL,
0, &paramBlock, defaultKeychain, &createdItems);
if (cfDataToImport != NULL) {
CFRelease(cfDataToImport);
}
if (err == noErr) {
SecKeychainItemRef anItem = (SecKeychainItemRef)CFArrayGetValueAtIndex(createdItems, 0);

if (err == noErr) {
SecKeychainItemRef anItem = (SecKeychainItemRef)CFArrayGetValueAtIndex(createdItems, 0);
// Don't bother labeling keys. They become part of an identity, and are not an accessible part of the keychain.
if (CFGetTypeID(anItem) == SecCertificateGetTypeID()) {
setLabelForItem(JavaStringToNSString(env, alias), anItem);
}

// Don't bother labeling keys. They become part of an identity, and are not an accessible part of the keychain.
if (CFGetTypeID(anItem) == SecCertificateGetTypeID()) {
setLabelForItem(JNFJavaToNSString(env, alias), anItem);
// Retain the item, since it will be released once when the array holding it gets released.
CFRetain(anItem);
returnValue = ptr_to_jlong(anItem);
} else {
cssmPerror("_addItemToKeychain: SecKeychainItemImport", err);
}

// Retain the item, since it will be released once when the array holding it gets released.
CFRetain(anItem);
returnValue = ptr_to_jlong(anItem);
} else {
cssmPerror("_addItemToKeychain: SecKeychainItemImport", err);
}

if (createdItems != NULL) {
CFRelease(createdItems);
}
if (createdItems != NULL) {
CFRelease(createdItems);
}

errOut:
if (rawData) {
(*env)->ReleaseByteArrayElements(env, rawDataObj, rawData, JNI_ABORT);
}
errOut:
if (rawData) {
(*env)->ReleaseByteArrayElements(env, rawDataObj, rawData, JNI_ABORT);
}

if (passwordStrRef) CFRelease(passwordStrRef);
if (passwordChars) {
// clear the password and release
memset(passwordChars, 0, passwordLen);
(*env)->ReleaseCharArrayElements(env, passwordObj, passwordChars,
JNI_ABORT);
if (passwordStrRef) CFRelease(passwordStrRef);
if (passwordChars) {
// clear the password and release
memset(passwordChars, 0, passwordLen);
(*env)->ReleaseCharArrayElements(env, passwordObj, passwordChars,
JNI_ABORT);
}
} @catch (NSException *e) {
NSLog(@"%@", [e callStackSymbols]);
} @finally {
[pool drain];
}

JNF_COCOA_EXIT(env);

return returnValue;
}

Expand Down

1 comment on commit 0da4bb8

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.