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

📄 cms.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 2003 - 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: cms.c 22327 2007-12-15 04:49:37Z lha $");/** * @page page_cms CMS/PKCS7 message functions. * * CMS is defined in RFC 3369 and is an continuation of the RSA Labs * standard PKCS7. The basic messages in CMS is  * * - SignedData *   Data signed with private key (RSA, DSA, ECDSA) or secret *   (symmetric) key * - EnvelopedData *   Data encrypted with private key (RSA) * - EncryptedData *   Data encrypted with secret (symmetric) key. * - ContentInfo *   Wrapper structure including type and data. * * * See the library functions here: @ref hx509_cms */#define ALLOC(X, N) (X) = calloc((N), sizeof(*(X)))#define ALLOC_SEQ(X, N) do { (X)->len = (N); ALLOC((X)->val, (N)); } while(0)/** * Wrap data and oid in a ContentInfo and encode it. * * @param oid type of the content. * @param buf data to be wrapped. If a NULL pointer is passed in, the * optional content field in the ContentInfo is not going be filled * in. * @param res the encoded buffer, the result should be freed with * der_free_octet_string(). * * @return Returns an hx509 error code. *  * @ingroup hx509_cms */inthx509_cms_wrap_ContentInfo(const heim_oid *oid,			   const heim_octet_string *buf,			   heim_octet_string *res){    ContentInfo ci;    size_t size;    int ret;    memset(res, 0, sizeof(*res));    memset(&ci, 0, sizeof(ci));    ret = der_copy_oid(oid, &ci.contentType);    if (ret)	return ret;    if (buf) {	ALLOC(ci.content, 1);	if (ci.content == NULL) {	    free_ContentInfo(&ci);	    return ENOMEM;	}	ci.content->data = malloc(buf->length);	if (ci.content->data == NULL) {	    free_ContentInfo(&ci);	    return ENOMEM;	}	memcpy(ci.content->data, buf->data, buf->length);	ci.content->length = buf->length;    }    ASN1_MALLOC_ENCODE(ContentInfo, res->data, res->length, &ci, &size, ret);    free_ContentInfo(&ci);    if (ret)	return ret;    if (res->length != size)	_hx509_abort("internal ASN.1 encoder error");    return 0;}/** * Decode an ContentInfo and unwrap data and oid it. * * @param in the encoded buffer. * @param oid type of the content. * @param out data to be wrapped. * @param have_data since the data is optional, this flags show dthe * diffrence between no data and the zero length data. * * @return Returns an hx509 error code. *  * @ingroup hx509_cms */inthx509_cms_unwrap_ContentInfo(const heim_octet_string *in,			     heim_oid *oid,			     heim_octet_string *out,			     int *have_data){    ContentInfo ci;    size_t size;    int ret;    memset(oid, 0, sizeof(*oid));    memset(out, 0, sizeof(*out));    ret = decode_ContentInfo(in->data, in->length, &ci, &size);    if (ret)	return ret;    ret = der_copy_oid(&ci.contentType, oid);    if (ret) {	free_ContentInfo(&ci);	return ret;    }    if (ci.content) {	ret = der_copy_octet_string(ci.content, out);	if (ret) {	    der_free_oid(oid);	    free_ContentInfo(&ci);	    return ret;	}    } else	memset(out, 0, sizeof(*out));    if (have_data)	*have_data = (ci.content != NULL) ? 1 : 0;    free_ContentInfo(&ci);    return 0;}#define CMS_ID_SKI	0#define CMS_ID_NAME	1static intfill_CMSIdentifier(const hx509_cert cert,		   int type,		   CMSIdentifier *id){    int ret;    switch (type) {    case CMS_ID_SKI:	id->element = choice_CMSIdentifier_subjectKeyIdentifier;	ret = _hx509_find_extension_subject_key_id(_hx509_get_cert(cert),						   &id->u.subjectKeyIdentifier);	if (ret == 0)	    break;	/* FALL THOUGH */    case CMS_ID_NAME: {	hx509_name name;	id->element = choice_CMSIdentifier_issuerAndSerialNumber;	ret = hx509_cert_get_issuer(cert, &name);	if (ret)	    return ret;	ret = hx509_name_to_Name(name, &id->u.issuerAndSerialNumber.issuer);	hx509_name_free(&name);	if (ret)	    return ret;	ret = hx509_cert_get_serialnumber(cert, &id->u.issuerAndSerialNumber.serialNumber);	break;    }    default:	_hx509_abort("CMS fill identifier with unknown type");    }    return ret;}static intunparse_CMSIdentifier(hx509_context context,		      CMSIdentifier *id,		      char **str){    int ret;    *str = NULL;    switch (id->element) {    case choice_CMSIdentifier_issuerAndSerialNumber: {	IssuerAndSerialNumber *iasn;	char *serial, *name;	iasn = &id->u.issuerAndSerialNumber;	ret = _hx509_Name_to_string(&iasn->issuer, &name);	if(ret)	    return ret;	ret = der_print_hex_heim_integer(&iasn->serialNumber, &serial);	if (ret) {	    free(name);	    return ret;	}	asprintf(str, "certificate issued by %s with serial number %s",		 name, serial);	free(name);	free(serial);	break;    }    case choice_CMSIdentifier_subjectKeyIdentifier: {	KeyIdentifier *ki  = &id->u.subjectKeyIdentifier;	char *keyid;	ssize_t len;	len = hex_encode(ki->data, ki->length, &keyid);	if (len < 0)	    return ENOMEM;	asprintf(str, "certificate with id %s", keyid);	free(keyid);	break;    }    default:	asprintf(str, "certificate have unknown CMSidentifier type");	break;    }    if (*str == NULL)	return ENOMEM;    return 0;}static intfind_CMSIdentifier(hx509_context context,		   CMSIdentifier *client,		   hx509_certs certs,		   hx509_cert *signer_cert,		   int match){    hx509_query q;    hx509_cert cert;    Certificate c;    int ret;    memset(&c, 0, sizeof(c));    _hx509_query_clear(&q);    *signer_cert = NULL;    switch (client->element) {    case choice_CMSIdentifier_issuerAndSerialNumber:	q.serial = &client->u.issuerAndSerialNumber.serialNumber;	q.issuer_name = &client->u.issuerAndSerialNumber.issuer;	q.match = HX509_QUERY_MATCH_SERIALNUMBER|HX509_QUERY_MATCH_ISSUER_NAME;	break;    case choice_CMSIdentifier_subjectKeyIdentifier:	q.subject_id = &client->u.subjectKeyIdentifier;	q.match = HX509_QUERY_MATCH_SUBJECT_KEY_ID;	break;    default:	hx509_set_error_string(context, 0, HX509_CMS_NO_RECIPIENT_CERTIFICATE,			       "unknown CMS identifier element");	return HX509_CMS_NO_RECIPIENT_CERTIFICATE;    }    q.match |= match;    q.match |= HX509_QUERY_MATCH_TIME;    q.timenow = time(NULL);    ret = hx509_certs_find(context, certs, &q, &cert);    if (ret == HX509_CERT_NOT_FOUND) {	char *str;	ret = unparse_CMSIdentifier(context, client, &str);	if (ret == 0) {	    hx509_set_error_string(context, 0,				   HX509_CMS_NO_RECIPIENT_CERTIFICATE,				   "Failed to find %s", str);	} else	    hx509_clear_error_string(context);	return HX509_CMS_NO_RECIPIENT_CERTIFICATE;    } else if (ret) {	hx509_set_error_string(context, HX509_ERROR_APPEND,			       HX509_CMS_NO_RECIPIENT_CERTIFICATE,			       "Failed to find CMS id in cert store");	return HX509_CMS_NO_RECIPIENT_CERTIFICATE;    }    *signer_cert = cert;    return 0;}/** * Decode and unencrypt EnvelopedData. * * Extract data and parameteres from from the EnvelopedData. Also * supports using detached EnvelopedData. * * @param context A hx509 context. * @param certs Certificate that can decrypt the EnvelopedData * encryption key. * @param flags HX509_CMS_UE flags to control the behavior. * @param data pointer the structure the contains the DER/BER encoded * EnvelopedData stucture. * @param length length of the data that data point to. * @param encryptedContent in case of detached signature, this * contains the actual encrypted data, othersize its should be NULL. * @param contentType output type oid, should be freed with der_free_oid(). * @param content the data, free with der_free_octet_string(). * * @ingroup hx509_cms */inthx509_cms_unenvelope(hx509_context context,		     hx509_certs certs,		     int flags,		     const void *data,		     size_t length,		     const heim_octet_string *encryptedContent,		     heim_oid *contentType,		     heim_octet_string *content){    heim_octet_string key;    EnvelopedData ed;    hx509_cert cert;    AlgorithmIdentifier *ai;    const heim_octet_string *enccontent;    heim_octet_string *params, params_data;    heim_octet_string ivec;    size_t size;    int ret, i, matched = 0, findflags = 0;    memset(&key, 0, sizeof(key));    memset(&ed, 0, sizeof(ed));    memset(&ivec, 0, sizeof(ivec));    memset(content, 0, sizeof(*content));    memset(contentType, 0, sizeof(*contentType));    if ((flags & HX509_CMS_UE_DONT_REQUIRE_KU_ENCIPHERMENT) == 0)	findflags |= HX509_QUERY_KU_ENCIPHERMENT;    ret = decode_EnvelopedData(data, length, &ed, &size);    if (ret) {	hx509_set_error_string(context, 0, ret,			       "Failed to decode EnvelopedData");	return ret;    }    if (ed.recipientInfos.len == 0) {	ret = HX509_CMS_NO_RECIPIENT_CERTIFICATE;	hx509_set_error_string(context, 0, ret,			       "No recipient info in enveloped data");	goto out;    }    enccontent = ed.encryptedContentInfo.encryptedContent;    if (enccontent == NULL) {	if (encryptedContent == NULL) {	    ret = HX509_CMS_NO_DATA_AVAILABLE;	    hx509_set_error_string(context, 0, ret,				   "Content missing from encrypted data");	    goto out;	}	enccontent = encryptedContent;    } else if (encryptedContent != NULL) {	ret = HX509_CMS_NO_DATA_AVAILABLE;	hx509_set_error_string(context, 0, ret,			       "Both internal and external encrypted data");	goto out;    }    cert = NULL;    for (i = 0; i < ed.recipientInfos.len; i++) {	KeyTransRecipientInfo *ri;	char *str;	int ret2;	ri = &ed.recipientInfos.val[i];	ret = find_CMSIdentifier(context, &ri->rid, certs, &cert,				 HX509_QUERY_PRIVATE_KEY|findflags);	if (ret)	    continue;	matched = 1; /* found a matching certificate, let decrypt */	ret = _hx509_cert_private_decrypt(context,					  &ri->encryptedKey,					  &ri->keyEncryptionAlgorithm.algorithm,					  cert, &key);	hx509_cert_free(cert);	if (ret == 0)	    break; /* succuessfully decrypted cert */	cert = NULL;	ret2 = unparse_CMSIdentifier(context, &ri->rid, &str);	if (ret2 == 0) {	    hx509_set_error_string(context, HX509_ERROR_APPEND, ret,				   "Failed to decrypt with %s", str);	    free(str);	}    }    if (!matched) {	ret = HX509_CMS_NO_RECIPIENT_CERTIFICATE;	hx509_set_error_string(context, 0, ret,			       "No private key matched any certificate");	goto out;    }    if (cert == NULL) {	ret = HX509_CMS_NO_RECIPIENT_CERTIFICATE;	hx509_set_error_string(context, HX509_ERROR_APPEND, ret,			       "No private key decrypted the transfer key");	goto out;    }    ret = der_copy_oid(&ed.encryptedContentInfo.contentType, contentType);    if (ret) {	hx509_set_error_string(context, 0, ret,			       "Failed to copy EnvelopedData content oid");	goto out;    }    ai = &ed.encryptedContentInfo.contentEncryptionAlgorithm;    if (ai->parameters) {	params_data.data = ai->parameters->data;	params_data.length = ai->parameters->length;	params = &params_data;    } else	params = NULL;    {	hx509_crypto crypto;	ret = hx509_crypto_init(context, NULL, &ai->algorithm, &crypto);	if (ret)	    goto out;		if (params) {	    ret = hx509_crypto_set_params(context, crypto, params, &ivec);	    if (ret) {		hx509_crypto_destroy(crypto);		goto out;	    }	}

⌨️ 快捷键说明

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