⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ks_keychain.c

📁 samba最新软件
💻 C
字号:
/* * Copyright (c) 2007 Kungliga Tekniska H鰃skolan * (Royal Institute of Technology, Stockholm, Sweden).  * All rights reserved.  * * Redistribution and use in source and binary forms, with or without  * modification, are permitted provided that the following conditions  * are met:  * * 1. Redistributions of source code must retain the above copyright  *    notice, this list of conditions and the following disclaimer.  * * 2. Redistributions in binary form must reproduce the above copyright  *    notice, this list of conditions and the following disclaimer in the  *    documentation and/or other materials provided with the distribution.  * * 3. Neither the name of the Institute nor the names of its contributors  *    may be used to endorse or promote products derived from this software  *    without specific prior written permission.  * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF  * SUCH DAMAGE.  */#include "hx_locl.h"RCSID("$Id: ks_keychain.c 22084 2007-11-16 20:12:30Z lha $");#ifdef HAVE_FRAMEWORK_SECURITY#include <Security/Security.h>/* Missing function decls in pre Leopard */#ifdef NEED_SECKEYGETCSPHANDLE_PROTOOSStatus SecKeyGetCSPHandle(SecKeyRef, CSSM_CSP_HANDLE *);OSStatus SecKeyGetCredentials(SecKeyRef, CSSM_ACL_AUTHORIZATION_TAG,			      int, const CSSM_ACCESS_CREDENTIALS **);#define kSecCredentialTypeDefault 0#endifstatic intgetAttribute(SecKeychainItemRef itemRef, SecItemAttr item,	     SecKeychainAttributeList **attrs){	         SecKeychainAttributeInfo attrInfo;    UInt32 attrFormat = 0;    OSStatus ret;    *attrs = NULL;    attrInfo.count = 1;    attrInfo.tag = &item;    attrInfo.format = &attrFormat;      ret = SecKeychainItemCopyAttributesAndData(itemRef, &attrInfo, NULL,					       attrs, NULL, NULL);    if (ret)	return EINVAL;    return 0;}/* * */struct kc_rsa {    SecKeychainItemRef item;    size_t keysize;};static intkc_rsa_public_encrypt(int flen,		      const unsigned char *from,		      unsigned char *to,		      RSA *rsa,		      int padding){    return -1;}static intkc_rsa_public_decrypt(int flen,		      const unsigned char *from,		      unsigned char *to,		      RSA *rsa,		      int padding){    return -1;}static intkc_rsa_private_encrypt(int flen, 		       const unsigned char *from,		       unsigned char *to,		       RSA *rsa,		       int padding){    struct kc_rsa *kc = RSA_get_app_data(rsa);    CSSM_RETURN cret;    OSStatus ret;    const CSSM_ACCESS_CREDENTIALS *creds;    SecKeyRef privKeyRef = (SecKeyRef)kc->item;    CSSM_CSP_HANDLE cspHandle;    const CSSM_KEY *cssmKey;    CSSM_CC_HANDLE sigHandle = 0;    CSSM_DATA sig, in;    int fret = 0;    cret = SecKeyGetCSSMKey(privKeyRef, &cssmKey);    if(cret) abort();    cret = SecKeyGetCSPHandle(privKeyRef, &cspHandle);    if(cret) abort();    ret = SecKeyGetCredentials(privKeyRef, CSSM_ACL_AUTHORIZATION_SIGN,			       kSecCredentialTypeDefault, &creds);    if(ret) abort();    ret = CSSM_CSP_CreateSignatureContext(cspHandle, CSSM_ALGID_RSA,					  creds, cssmKey, &sigHandle);    if(ret) abort();    in.Data = (uint8 *)from;    in.Length = flen;	    sig.Data = (uint8 *)to;    sig.Length = kc->keysize;	    cret = CSSM_SignData(sigHandle, &in, 1, CSSM_ALGID_NONE, &sig);    if(cret) {	/* cssmErrorString(cret); */	fret = -1;    } else	fret = sig.Length;    if(sigHandle)	CSSM_DeleteContext(sigHandle);    return fret;}static intkc_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 intkc_rsa_finish(RSA *rsa){    struct kc_rsa *kc_rsa = RSA_get_app_data(rsa);    CFRelease(kc_rsa->item);    memset(kc_rsa, 0, sizeof(*kc_rsa));    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 intset_private_key(hx509_context context,		SecKeychainItemRef itemRef,		hx509_cert cert){    struct kc_rsa *kc;    hx509_private_key key;    RSA *rsa;    int ret;    ret = _hx509_private_key_init(&key, NULL, NULL);    if (ret)	return ret;    kc = calloc(1, sizeof(*kc));    if (kc == NULL)	_hx509_abort("out of memory");    kc->item = itemRef;    rsa = RSA_new();    if (rsa == NULL)	_hx509_abort("out of memory");    /* Argh, fake modulus since OpenSSL API is on crack */    {	SecKeychainAttributeList *attrs = NULL;	uint32_t size;	void *data;	rsa->n = BN_new();	if (rsa->n == NULL) abort();	ret = getAttribute(itemRef, kSecKeyKeySizeInBits, &attrs);	if (ret) abort();	size = *(uint32_t *)attrs->attr[0].data;	SecKeychainItemFreeAttributesAndData(attrs, NULL);	kc->keysize = (size + 7) / 8;	data = malloc(kc->keysize);	memset(data, 0xe0, kc->keysize);	BN_bin2bn(data, kc->keysize, rsa->n);	free(data);    }    rsa->e = NULL;    RSA_set_method(rsa, &kc_rsa_pkcs1_method);    ret = RSA_set_app_data(rsa, kc);    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 {    int anchors;    SecKeychainRef keychain;};static intkeychain_init(hx509_context context,	      hx509_certs certs, void **data, int flags,	      const char *residue, hx509_lock lock){    struct ks_keychain *ctx;    ctx = calloc(1, sizeof(*ctx));    if (ctx == NULL) {	hx509_clear_error_string(context);	return ENOMEM;    }    if (residue) {	if (strcasecmp(residue, "system-anchors") == 0) {	    ctx->anchors = 1;	} else if (strncasecmp(residue, "FILE:", 5) == 0) {	    OSStatus ret;	    ret = SecKeychainOpen(residue + 5, &ctx->keychain);	    if (ret != noErr) {		hx509_set_error_string(context, 0, ENOENT, 				       "Failed to open %s", residue);		return ENOENT;	    }	} else {	    hx509_set_error_string(context, 0, ENOENT, 				   "Unknown subtype %s", residue);	    return ENOENT;	}    }    *data = ctx;    return 0;}/* * */static intkeychain_free(hx509_certs certs, void *data){    struct ks_keychain *ctx = data;    if (ctx->keychain)	CFRelease(ctx->keychain);    memset(ctx, 0, sizeof(*ctx));    free(ctx);    return 0;}/* * */struct iter {    hx509_certs certs;    void *cursor;    SecKeychainSearchRef searchRef;};static int keychain_iter_start(hx509_context context,		    hx509_certs certs, void *data, void **cursor){    struct ks_keychain *ctx = data;    struct iter *iter;    iter = calloc(1, sizeof(*iter));    if (iter == NULL) {	hx509_set_error_string(context, 0, ENOMEM, "out of memory");	return ENOMEM;    }    if (ctx->anchors) {        CFArrayRef anchors;	int ret;	int i;	ret = hx509_certs_init(context, "MEMORY:ks-file-create", 			       0, NULL, &iter->certs);	if (ret) {	    free(iter);	    return ret;	}	ret = SecTrustCopyAnchorCertificates(&anchors);	if (ret != 0) {	    hx509_certs_free(&iter->certs);	    free(iter);	    hx509_set_error_string(context, 0, ENOMEM, 				   "Can't get trust anchors from Keychain");	    return ENOMEM;	}	for (i = 0; i < CFArrayGetCount(anchors); i++) {	    SecCertificateRef cr; 	    hx509_cert cert;	    CSSM_DATA cssm;	    cr = (SecCertificateRef)CFArrayGetValueAtIndex(anchors, i);	    SecCertificateGetData(cr, &cssm);	    ret = hx509_cert_init_data(context, cssm.Data, cssm.Length, &cert);	    if (ret)		continue;	    ret = hx509_certs_add(context, iter->certs, cert);	    hx509_cert_free(cert);	}	CFRelease(anchors);    }    if (iter->certs) {	int ret;	ret = hx509_certs_start_seq(context, iter->certs, &iter->cursor);	if (ret) {	    hx509_certs_free(&iter->certs);	    free(iter);	    return ret;	}    } else {	OSStatus ret;	ret = SecKeychainSearchCreateFromAttributes(ctx->keychain,						    kSecCertificateItemClass,						    NULL,						    &iter->searchRef);	if (ret) {	    free(iter);	    hx509_set_error_string(context, 0, ret, 				   "Failed to start search for attributes");	    return ENOMEM;	}    }    *cursor = iter;    return 0;}/* * */static intkeychain_iter(hx509_context context,	      hx509_certs certs, void *data, void *cursor, hx509_cert *cert){    SecKeychainAttributeList *attrs = NULL;    SecKeychainAttributeInfo attrInfo;    UInt32 attrFormat[1] = { 0 };    SecKeychainItemRef itemRef;    SecItemAttr item[1];    struct iter *iter = cursor;    OSStatus ret;    UInt32 len;    void *ptr = NULL;    if (iter->certs)	return hx509_certs_next_cert(context, iter->certs, iter->cursor, cert);    *cert = NULL;    ret = SecKeychainSearchCopyNext(iter->searchRef, &itemRef);    if (ret == errSecItemNotFound)	return 0;    else if (ret != 0)	return EINVAL;	    /*     * Pick out certificate and matching "keyid"     */    item[0] = kSecPublicKeyHashItemAttr;    attrInfo.count = 1;    attrInfo.tag = item;    attrInfo.format = attrFormat;      ret = SecKeychainItemCopyAttributesAndData(itemRef, &attrInfo, NULL,					       &attrs, &len, &ptr);    if (ret)	return EINVAL;    ret = hx509_cert_init_data(context, ptr, len, cert);    if (ret)	goto out;    /*      * 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;	}	set_private_key(context, itemRef, *cert);    }out:    SecKeychainItemFreeAttributesAndData(attrs, ptr);    return ret;}/* * */static intkeychain_iter_end(hx509_context context,		  hx509_certs certs,		  void *data,		  void *cursor){    struct iter *iter = cursor;    if (iter->certs) {	int ret;	ret = hx509_certs_end_seq(context, iter->certs, iter->cursor);	hx509_certs_free(&iter->certs);    } else {	CFRelease(iter->searchRef);    }    memset(iter, 0, sizeof(*iter));    free(iter);    return 0;}/* * */struct hx509_keyset_ops keyset_keychain = {    "KEYCHAIN",    0,    keychain_init,    NULL,    keychain_free,    NULL,    NULL,    keychain_iter_start,    keychain_iter,    keychain_iter_end};#endif /* HAVE_FRAMEWORK_SECURITY *//* * */void_hx509_ks_keychain_register(hx509_context context){#ifdef HAVE_FRAMEWORK_SECURITY    _hx509_ks_register(context, &keyset_keychain);#endif}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -