Find and attach private key (does not provide operations yet though).
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@20921 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
@@ -37,11 +37,126 @@ RCSID("$Id$");
|
|||||||
|
|
||||||
#ifdef HAVE_FRAMEWORK_SECURITY
|
#ifdef HAVE_FRAMEWORK_SECURITY
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct kc_rsa {
|
||||||
|
SecKeychainItemRef item;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
kc_rsa_public_encrypt(int flen,
|
||||||
|
const unsigned char *from,
|
||||||
|
unsigned char *to,
|
||||||
|
RSA *rsa,
|
||||||
|
int padding)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
kc_rsa_public_decrypt(int flen,
|
||||||
|
const unsigned char *from,
|
||||||
|
unsigned char *to,
|
||||||
|
RSA *rsa,
|
||||||
|
int padding)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
kc_rsa_private_encrypt(int flen,
|
||||||
|
const unsigned char *from,
|
||||||
|
unsigned char *to,
|
||||||
|
RSA *rsa,
|
||||||
|
int padding)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
kc_rsa_private_decrypt(int flen, const unsigned char *from, unsigned char *to,
|
||||||
|
RSA * rsa, int padding)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
kc_rsa_init(RSA *rsa)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
kc_rsa_finish(RSA *rsa)
|
||||||
|
{
|
||||||
|
struct kc_rsa *kc_rsa = RSA_get_app_data(rsa);
|
||||||
|
CFRelease(kc_rsa->item);
|
||||||
|
free(kc_rsa);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const RSA_METHOD kc_rsa_pkcs1_method = {
|
||||||
|
"hx509 Keychain PKCS#1 RSA",
|
||||||
|
kc_rsa_public_encrypt,
|
||||||
|
kc_rsa_public_decrypt,
|
||||||
|
kc_rsa_private_encrypt,
|
||||||
|
kc_rsa_private_decrypt,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
kc_rsa_init,
|
||||||
|
kc_rsa_finish,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
private_key(hx509_context context, SecKeychainItemRef itemRef,
|
||||||
|
hx509_cert cert)
|
||||||
|
{
|
||||||
|
struct kc_rsa *kc_rsa;
|
||||||
|
hx509_private_key key;
|
||||||
|
RSA *rsa;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = _hx509_private_key_init(&key, NULL, NULL);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
rsa = RSA_new();
|
||||||
|
if (rsa == NULL)
|
||||||
|
_hx509_abort("out of memory");
|
||||||
|
|
||||||
|
kc_rsa = calloc(1, sizeof(*kc_rsa));
|
||||||
|
if (kc_rsa == NULL)
|
||||||
|
_hx509_abort("out of memory");
|
||||||
|
|
||||||
|
kc_rsa->item = itemRef;
|
||||||
|
|
||||||
|
RSA_set_method(rsa, &kc_rsa_pkcs1_method);
|
||||||
|
ret = RSA_set_app_data(rsa, kc_rsa);
|
||||||
|
if (ret != 1)
|
||||||
|
_hx509_abort("RSA_set_app_data");
|
||||||
|
|
||||||
|
_hx509_private_key_assign_rsa(key, rsa);
|
||||||
|
_hx509_cert_assign_key(cert, key);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
struct ks_keychain {
|
struct ks_keychain {
|
||||||
SecKeychainRef keychain;
|
SecKeychainRef keychain;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
keychain_init(hx509_context context,
|
keychain_init(hx509_context context,
|
||||||
hx509_certs certs, void **data, int flags,
|
hx509_certs certs, void **data, int flags,
|
||||||
@@ -56,10 +171,10 @@ keychain_init(hx509_context context,
|
|||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcasecmp(residue, "system") == 0)
|
if (residue) {
|
||||||
residue = "/System/Library/Keychains/X509Anchors";
|
if (strcasecmp(residue, "system") == 0)
|
||||||
|
residue = "/System/Library/Keychains/X509Anchors";
|
||||||
|
|
||||||
if (residue && residue[0] != '\0') {
|
|
||||||
ret = SecKeychainOpen(residue, &ctx->keychain);
|
ret = SecKeychainOpen(residue, &ctx->keychain);
|
||||||
if (ret != noErr) {
|
if (ret != noErr) {
|
||||||
hx509_set_error_string(context, 0, ENOENT,
|
hx509_set_error_string(context, 0, ENOENT,
|
||||||
@@ -93,7 +208,6 @@ keychain_free(hx509_certs certs, void *data)
|
|||||||
|
|
||||||
struct iter {
|
struct iter {
|
||||||
SecKeychainSearchRef searchRef;
|
SecKeychainSearchRef searchRef;
|
||||||
SecKeychainItemRef itemRef;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -132,12 +246,16 @@ static int
|
|||||||
keychain_iter(hx509_context context,
|
keychain_iter(hx509_context context,
|
||||||
hx509_certs certs, void *data, void *cursor, hx509_cert *cert)
|
hx509_certs certs, void *data, void *cursor, hx509_cert *cert)
|
||||||
{
|
{
|
||||||
|
SecKeychainAttributeList *attrs = NULL;
|
||||||
|
SecKeychainAttributeInfo attrInfo;
|
||||||
|
uint32 attrFormat = 0;
|
||||||
SecKeychainItemRef itemRef;
|
SecKeychainItemRef itemRef;
|
||||||
|
SecItemAttr item;
|
||||||
struct iter *iter = cursor;
|
struct iter *iter = cursor;
|
||||||
Certificate t;
|
Certificate t;
|
||||||
OSStatus ret;
|
OSStatus ret;
|
||||||
UInt32 len;
|
UInt32 len;
|
||||||
void *ptr;
|
void *ptr = NULL;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
*cert = NULL;
|
*cert = NULL;
|
||||||
@@ -148,26 +266,75 @@ keychain_iter(hx509_context context,
|
|||||||
else if (ret != 0)
|
else if (ret != 0)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
ret = SecKeychainItemCopyAttributesAndData(itemRef, NULL, NULL,
|
/*
|
||||||
NULL, &len, &ptr);
|
* Pick out certificate and matching "keyid"
|
||||||
|
*/
|
||||||
|
|
||||||
|
item = kSecPublicKeyHashItemAttr;
|
||||||
|
|
||||||
|
attrInfo.count = 1;
|
||||||
|
attrInfo.tag = &item;
|
||||||
|
attrInfo.format = &attrFormat;
|
||||||
|
|
||||||
|
ret = SecKeychainItemCopyAttributesAndData(itemRef, &attrInfo, NULL,
|
||||||
|
&attrs, &len, &ptr);
|
||||||
if (ret)
|
if (ret)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
ret = decode_Certificate(ptr, len, &t, &size);
|
ret = decode_Certificate(ptr, len, &t, &size);
|
||||||
SecKeychainItemFreeAttributesAndData(NULL, ptr);
|
|
||||||
CFRelease(itemRef);
|
CFRelease(itemRef);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
hx509_set_error_string(context, 0, ret,
|
hx509_set_error_string(context, 0, ret, "Failed to parse certificate");
|
||||||
"Failed to parse certificate");
|
goto out;
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = hx509_cert_init(context, &t, cert);
|
ret = hx509_cert_init(context, &t, cert);
|
||||||
free_Certificate(&t);
|
free_Certificate(&t);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto out;
|
||||||
|
|
||||||
return 0;
|
/*
|
||||||
|
* Find related private key if there is one by looking at
|
||||||
|
* kSecPublicKeyHashItemAttr == kSecKeyLabel
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
SecKeychainSearchRef search;
|
||||||
|
SecKeychainAttribute attrKeyid;
|
||||||
|
SecKeychainAttributeList attrList;
|
||||||
|
|
||||||
|
attrKeyid.tag = kSecKeyLabel;
|
||||||
|
attrKeyid.length = attrs->attr[0].length;
|
||||||
|
attrKeyid.data = attrs->attr[0].data;
|
||||||
|
|
||||||
|
attrList.count = 1;
|
||||||
|
attrList.attr = &attrKeyid;
|
||||||
|
|
||||||
|
ret = SecKeychainSearchCreateFromAttributes(NULL,
|
||||||
|
CSSM_DL_DB_RECORD_PRIVATE_KEY,
|
||||||
|
&attrList,
|
||||||
|
&search);
|
||||||
|
if (ret) {
|
||||||
|
ret = 0;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = SecKeychainSearchCopyNext(search, &itemRef);
|
||||||
|
CFRelease(search);
|
||||||
|
if (ret == errSecItemNotFound) {
|
||||||
|
ret = 0;
|
||||||
|
goto out;
|
||||||
|
} else if (ret) {
|
||||||
|
ret = EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
private_key(context, itemRef, *cert);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
SecKeychainItemFreeAttributesAndData(attrs, ptr);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user