mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8257858: [macOS]: Remove JNF dependency from libosxsecurity/KeystoreImpl.m
8257860: [macOS]: Remove JNF dependency from libosxkrb5/SCDynamicStoreConfig.m Reviewed-by: erikj, prr, ihse, valeriep
This commit is contained in:
parent
472bf629cd
commit
4a8b5c1602
12 changed files with 506 additions and 454 deletions
|
@ -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
|
||||
|
@ -815,8 +815,8 @@ public final class KeychainStore extends KeyStoreSpi {
|
|||
* 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.
|
||||
|
|
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -500,6 +505,20 @@ JNIEXPORT void JNICALL Java_apple_security_KeychainStore__1scanKeychain
|
|||
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -511,95 +530,97 @@ JNIEXPORT jlong JNICALL Java_apple_security_KeychainStore__1addItemToKeychain
|
|||
OSStatus err;
|
||||
jlong returnValue = 0;
|
||||
|
||||
JNF_COCOA_ENTER(env);
|
||||
|
||||
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;
|
||||
|
||||
SecKeychainRef defaultKeychain = NULL;
|
||||
SecKeychainCopyDefault(&defaultKeychain);
|
||||
|
||||
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;
|
||||
|
||||
jsize passwordLen = 0;
|
||||
jchar *passwordChars = NULL;
|
||||
|
||||
if (passwordObj) {
|
||||
passwordLen = (*env)->GetArrayLength(env, passwordObj);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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, ¶mBlock, defaultKeychain, &createdItems);
|
||||
if (cfDataToImport != NULL) {
|
||||
CFRelease(cfDataToImport);
|
||||
}
|
||||
|
||||
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(JNFJavaToNSString(env, alias), anItem);
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; \
|
||||
@try {
|
||||
jsize dataSize = (*env)->GetArrayLength(env, rawDataObj);
|
||||
jbyte *rawData = (*env)->GetByteArrayElements(env, rawDataObj, NULL);
|
||||
if (rawData == NULL) {
|
||||
goto errOut;
|
||||
}
|
||||
|
||||
// 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);
|
||||
CFDataRef cfDataToImport = CFDataCreate(kCFAllocatorDefault, (UInt8 *)rawData, dataSize);
|
||||
CFArrayRef createdItems = NULL;
|
||||
|
||||
SecKeychainRef defaultKeychain = NULL;
|
||||
SecKeychainCopyDefault(&defaultKeychain);
|
||||
|
||||
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;
|
||||
|
||||
jsize passwordLen = 0;
|
||||
jchar *passwordChars = NULL;
|
||||
|
||||
if (passwordObj) {
|
||||
passwordLen = (*env)->GetArrayLength(env, passwordObj);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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, ¶mBlock, defaultKeychain, &createdItems);
|
||||
if (cfDataToImport != NULL) {
|
||||
CFRelease(cfDataToImport);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
} @catch (NSException *e) {
|
||||
NSLog(@"%@", [e callStackSymbols]);
|
||||
} @finally {
|
||||
[pool drain];
|
||||
}
|
||||
|
||||
if (createdItems != NULL) {
|
||||
CFRelease(createdItems);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
JNF_COCOA_EXIT(env);
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue