From 82f399b518b8dccc71fa07cd13908b168b436818 Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Mon, 9 Sep 2024 08:28:06 -0700 Subject: [PATCH] add pkcs12 import --- include/aws/io/private/pki_utils.h | 11 ++++++ source/darwin/darwin_pki_utils.c | 61 ++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/include/aws/io/private/pki_utils.h b/include/aws/io/private/pki_utils.h index 3267f4b21..0d35fdef1 100644 --- a/include/aws/io/private/pki_utils.h +++ b/include/aws/io/private/pki_utils.h @@ -59,6 +59,17 @@ int aws_secitem_import_cert_and_key( SecIdentityRef *secitem_identity, const struct aws_secitem_options *secitem_options); +/** + * Imports a PKCS#12 file into protected data keychain for use with + * Apple Network Framework. + * Currently only implemented for iOS. + */ +int aws_secitem_import_pkcs12( + CFAllocatorRef cf_alloc, + const struct aws_byte_cursor *pkcs12_cursor, + const struct aws_byte_cursor *password, + SecIdentityRef *secitem_identity); + /** * Imports a PKCS#12 file into identity for use with * SecurityFramework diff --git a/source/darwin/darwin_pki_utils.c b/source/darwin/darwin_pki_utils.c index be5abb16c..77688bdd1 100644 --- a/source/darwin/darwin_pki_utils.c +++ b/source/darwin/darwin_pki_utils.c @@ -861,3 +861,64 @@ int aws_secitem_import_cert_and_key( return result; } + +int aws_secitem_import_pkcs12( + CFAllocatorRef cf_alloc, + const struct aws_byte_cursor *pkcs12_cursor, + const struct aws_byte_cursor *password, + SecIdentityRef *secitem_identity) { + + int result = AWS_OP_ERR; + CFArrayRef items = NULL; + CFDataRef pkcs12_data = NULL; + pkcs12_data = CFDataCreate(cf_alloc, pkcs12_cursor->ptr, pkcs12_cursor->len); + CFStringRef password_ref = NULL; + if (password->len) { + password_ref = CFStringCreateWithBytes( + cf_alloc, + password->ptr, + password->len, + kCFStringEncodingUTF8, + false); + } else { + password_ref = CFSTR(""); + } + + CFMutableDictionaryRef dictionary = CFDictionaryCreateMutable(cf_alloc, 0, NULL, NULL); + CFDictionaryAddValue(dictionary, kSecImportExportPassphrase, password_ref); + + OSStatus status = SecPKCS12Import(pkcs12_data, dictionary, &items); + + if (status != errSecSuccess || CFArrayGetCount(items) == 0) { + AWS_LOGF_ERROR(AWS_LS_IO_PKI, "Failed to import PKCS#12 file with OSStatus:%d", (int)status); + result = aws_raise_error(AWS_ERROR_SYS_CALL_FAILURE); + goto done; + } + + // Extract the identity from the first item in the array + // identity_and_trust does not need to be released as it is not a copy or created CF object. + CFDictionaryRef identity_and_trust = CFArrayGetValueAtIndex(items, 0); + *secitem_identity = (SecIdentityRef)CFDictionaryGetValue(identity_and_trust, kSecImportItemIdentity); + + // Retain the identity for use outside this function + if (*secitem_identity != NULL) { + CFRetain(*secitem_identity); + AWS_LOGF_INFO( + AWS_LS_IO_PKI, + "static: Successfully imported identity into SecItem keychain."); + } else { + status = errSecItemNotFound; + AWS_LOGF_ERROR(AWS_LS_IO_PKI, "Failed to retrieve identity from PKCS#12 with OSStatus %d", (int)status); + goto done; + } + + result = AWS_OP_SUCCESS; + +done: + //cleanup + if (pkcs12_data) CFRelease(pkcs12_data); + if (dictionary) CFRelease(dictionary); + if (password_ref) CFRelease(password_ref); + if (items) CFRelease(items); + return result; +}