--- /dev/null	2014-08-13 19:52:22.000000000 +0400
+++ new/usr/src/lib/openssl/libsunw_crypto/cms/cms_lib.c	2014-08-13 19:52:22.880900901 +0400
@@ -0,0 +1,622 @@
+/* crypto/cms/cms_lib.c */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 2008 The OpenSSL Project.  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. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED 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 OpenSSL PROJECT OR
+ * ITS 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 <openssl/asn1t.h>
+#include <openssl/x509.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include <openssl/bio.h>
+#include <openssl/asn1.h>
+#include <openssl/cms.h>
+#include <cms_lcl.h>
+
+IMPLEMENT_ASN1_FUNCTIONS(CMS_ContentInfo)
+IMPLEMENT_ASN1_PRINT_FUNCTION(CMS_ContentInfo)
+
+DECLARE_ASN1_ITEM(CMS_CertificateChoices)
+DECLARE_ASN1_ITEM(CMS_RevocationInfoChoice)
+DECLARE_STACK_OF(CMS_CertificateChoices)
+DECLARE_STACK_OF(CMS_RevocationInfoChoice)
+
+const ASN1_OBJECT *CMS_get0_type(CMS_ContentInfo *cms)
+	{
+	return cms->contentType;
+	}
+
+CMS_ContentInfo *cms_Data_create(void)
+	{
+	CMS_ContentInfo *cms;
+	cms = CMS_ContentInfo_new();
+	if (cms)
+		{
+		cms->contentType = OBJ_nid2obj(NID_pkcs7_data);
+		/* Never detached */
+		CMS_set_detached(cms, 0);
+		}
+	return cms;
+	}
+
+BIO *cms_content_bio(CMS_ContentInfo *cms)
+	{
+	ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
+	if (!pos)
+		return NULL;
+	/* If content detached data goes nowhere: create NULL BIO */
+	if (!*pos)
+		return BIO_new(BIO_s_null());
+	/* If content not detached and created return memory BIO
+	 */
+	if (!*pos || ((*pos)->flags == ASN1_STRING_FLAG_CONT))
+		return BIO_new(BIO_s_mem());
+	/* Else content was read in: return read only BIO for it */
+	return BIO_new_mem_buf((*pos)->data, (*pos)->length);
+	}
+
+BIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont)
+	{
+	BIO *cmsbio, *cont;
+	if (icont)
+		cont = icont;
+	else
+		cont = cms_content_bio(cms);
+	if (!cont)
+		{
+		CMSerr(CMS_F_CMS_DATAINIT, CMS_R_NO_CONTENT);
+		return NULL;
+		}
+	switch (OBJ_obj2nid(cms->contentType))
+		{
+
+		case NID_pkcs7_data:
+		return cont;
+
+		case NID_pkcs7_signed:
+		cmsbio = cms_SignedData_init_bio(cms);
+		break;
+
+		case NID_pkcs7_digest:
+		cmsbio = cms_DigestedData_init_bio(cms);
+		break;
+#ifdef ZLIB
+		case NID_id_smime_ct_compressedData:
+		cmsbio = cms_CompressedData_init_bio(cms);
+		break;
+#endif
+
+		case NID_pkcs7_encrypted:
+		cmsbio = cms_EncryptedData_init_bio(cms);
+		break;
+
+		case NID_pkcs7_enveloped:
+		cmsbio = cms_EnvelopedData_init_bio(cms);
+		break;
+
+		default:
+		CMSerr(CMS_F_CMS_DATAINIT, CMS_R_UNSUPPORTED_TYPE);
+		return NULL;
+		}
+
+	if (cmsbio)
+		return BIO_push(cmsbio, cont);
+
+	if (!icont)
+		BIO_free(cont);
+	return NULL;
+
+	}
+
+int CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio)
+	{
+	ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
+	if (!pos)
+		return 0;
+	/* If ebmedded content find memory BIO and set content */
+	if (*pos && ((*pos)->flags & ASN1_STRING_FLAG_CONT))
+		{
+		BIO *mbio;
+		unsigned char *cont;
+		long contlen;
+		mbio = BIO_find_type(cmsbio, BIO_TYPE_MEM);
+		if (!mbio)
+			{
+			CMSerr(CMS_F_CMS_DATAFINAL, CMS_R_CONTENT_NOT_FOUND);
+			return 0;
+			}
+		contlen = BIO_get_mem_data(mbio, &cont);
+		/* Set bio as read only so its content can't be clobbered */
+		BIO_set_flags(mbio, BIO_FLAGS_MEM_RDONLY);
+		BIO_set_mem_eof_return(mbio, 0);
+		ASN1_STRING_set0(*pos, cont, contlen);
+		(*pos)->flags &= ~ASN1_STRING_FLAG_CONT;
+		}
+
+	switch (OBJ_obj2nid(cms->contentType))
+		{
+
+		case NID_pkcs7_data:
+		case NID_pkcs7_enveloped:
+		case NID_pkcs7_encrypted:
+		case NID_id_smime_ct_compressedData:
+		/* Nothing to do */
+		return 1;
+
+		case NID_pkcs7_signed:
+		return cms_SignedData_final(cms, cmsbio);
+
+		case NID_pkcs7_digest:
+		return cms_DigestedData_do_final(cms, cmsbio, 0);
+
+		default:
+		CMSerr(CMS_F_CMS_DATAFINAL, CMS_R_UNSUPPORTED_TYPE);
+		return 0;
+		}
+	}
+
+/* Return an OCTET STRING pointer to content. This allows it to
+ * be accessed or set later.
+ */
+
+ASN1_OCTET_STRING **CMS_get0_content(CMS_ContentInfo *cms)
+	{
+	switch (OBJ_obj2nid(cms->contentType))
+		{
+
+		case NID_pkcs7_data:
+		return &cms->d.data;
+
+		case NID_pkcs7_signed:
+		return &cms->d.signedData->encapContentInfo->eContent;
+
+		case NID_pkcs7_enveloped:
+		return &cms->d.envelopedData->encryptedContentInfo->encryptedContent;
+
+		case NID_pkcs7_digest:
+		return &cms->d.digestedData->encapContentInfo->eContent;
+
+		case NID_pkcs7_encrypted:
+		return &cms->d.encryptedData->encryptedContentInfo->encryptedContent;
+
+		case NID_id_smime_ct_authData:
+		return &cms->d.authenticatedData->encapContentInfo->eContent;
+
+		case NID_id_smime_ct_compressedData:
+		return &cms->d.compressedData->encapContentInfo->eContent;
+
+		default:
+		if (cms->d.other->type == V_ASN1_OCTET_STRING)
+			return &cms->d.other->value.octet_string;
+		CMSerr(CMS_F_CMS_GET0_CONTENT, CMS_R_UNSUPPORTED_CONTENT_TYPE);
+		return NULL;
+
+		}
+	}
+
+/* Return an ASN1_OBJECT pointer to content type. This allows it to
+ * be accessed or set later.
+ */
+
+static ASN1_OBJECT **cms_get0_econtent_type(CMS_ContentInfo *cms)
+	{
+	switch (OBJ_obj2nid(cms->contentType))
+		{
+
+		case NID_pkcs7_signed:
+		return &cms->d.signedData->encapContentInfo->eContentType;
+
+		case NID_pkcs7_enveloped:
+		return &cms->d.envelopedData->encryptedContentInfo->contentType;
+
+		case NID_pkcs7_digest:
+		return &cms->d.digestedData->encapContentInfo->eContentType;
+
+		case NID_pkcs7_encrypted:
+		return &cms->d.encryptedData->encryptedContentInfo->contentType;
+
+		case NID_id_smime_ct_authData:
+		return &cms->d.authenticatedData->encapContentInfo->eContentType;
+
+		case NID_id_smime_ct_compressedData:
+		return &cms->d.compressedData->encapContentInfo->eContentType;
+
+		default:
+		CMSerr(CMS_F_CMS_GET0_ECONTENT_TYPE,
+					CMS_R_UNSUPPORTED_CONTENT_TYPE);
+		return NULL;
+
+		}
+	}
+
+const ASN1_OBJECT *CMS_get0_eContentType(CMS_ContentInfo *cms)
+	{
+	ASN1_OBJECT **petype;
+	petype = cms_get0_econtent_type(cms);
+	if (petype)
+		return *petype;
+	return NULL;
+	}
+
+int CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid)
+	{
+	ASN1_OBJECT **petype, *etype;
+	petype = cms_get0_econtent_type(cms);
+	if (!petype)
+		return 0;
+	if (!oid)
+		return 1;
+	etype = OBJ_dup(oid);
+	if (!etype)
+		return 0;
+	ASN1_OBJECT_free(*petype);
+	*petype = etype;
+	return 1;
+	}
+
+int CMS_is_detached(CMS_ContentInfo *cms)
+	{
+	ASN1_OCTET_STRING **pos;
+	pos = CMS_get0_content(cms);
+	if (!pos)
+		return -1;
+	if (*pos)
+		return 0;
+	return 1;
+	}
+
+int CMS_set_detached(CMS_ContentInfo *cms, int detached)
+	{
+	ASN1_OCTET_STRING **pos;
+	pos = CMS_get0_content(cms);
+	if (!pos)
+		return 0;
+	if (detached)
+		{
+		if (*pos)
+			{
+			ASN1_OCTET_STRING_free(*pos);
+			*pos = NULL;
+			}
+		return 1;
+		}
+	if (!*pos)
+		*pos = ASN1_OCTET_STRING_new();
+	if (*pos)
+		{
+		/* NB: special flag to show content is created and not
+		 * read in.
+		 */
+		(*pos)->flags |= ASN1_STRING_FLAG_CONT;
+		return 1;
+		}
+	CMSerr(CMS_F_CMS_SET_DETACHED, ERR_R_MALLOC_FAILURE);
+	return 0;
+	}
+
+/* Set up an X509_ALGOR DigestAlgorithmIdentifier from an EVP_MD */
+
+void cms_DigestAlgorithm_set(X509_ALGOR *alg, const EVP_MD *md)
+	{
+	int param_type;
+
+	if (md->flags & EVP_MD_FLAG_DIGALGID_ABSENT)
+		param_type = V_ASN1_UNDEF;
+	else
+		param_type = V_ASN1_NULL;
+
+	X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_type(md)), param_type, NULL);
+
+	}
+
+/* Create a digest BIO from an X509_ALGOR structure */
+
+BIO *cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm)
+	{
+	BIO *mdbio = NULL;
+	ASN1_OBJECT *digestoid;
+	const EVP_MD *digest;
+	X509_ALGOR_get0(&digestoid, NULL, NULL, digestAlgorithm);
+	digest = EVP_get_digestbyobj(digestoid);
+	if (!digest)
+		{
+		CMSerr(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO,
+				CMS_R_UNKNOWN_DIGEST_ALGORIHM);
+		goto err;
+		}
+	mdbio = BIO_new(BIO_f_md());
+	if (!mdbio || !BIO_set_md(mdbio, digest))
+		{
+		CMSerr(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO,
+				CMS_R_MD_BIO_INIT_ERROR);
+		goto err;
+		}
+	return mdbio;
+	err:
+	if (mdbio)
+		BIO_free(mdbio);
+	return NULL;
+	}
+
+/* Locate a message digest content from a BIO chain based on SignerInfo */
+
+int cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain,
+					X509_ALGOR *mdalg)
+	{
+	int nid;
+	ASN1_OBJECT *mdoid;
+	X509_ALGOR_get0(&mdoid, NULL, NULL, mdalg);
+	nid = OBJ_obj2nid(mdoid);
+	/* Look for digest type to match signature */
+	for (;;)
+		{
+		EVP_MD_CTX *mtmp;
+		chain = BIO_find_type(chain, BIO_TYPE_MD);
+		if (chain == NULL)
+			{
+			CMSerr(CMS_F_CMS_DIGESTALGORITHM_FIND_CTX,
+						CMS_R_NO_MATCHING_DIGEST);
+			return 0;
+			}
+		BIO_get_md_ctx(chain, &mtmp);
+		if (EVP_MD_CTX_type(mtmp) == nid
+		/* Workaround for broken implementations that use signature
+		 * algorithm  OID instead of digest.
+		 */
+			|| EVP_MD_pkey_type(EVP_MD_CTX_md(mtmp)) == nid)
+			return EVP_MD_CTX_copy_ex(mctx, mtmp);
+		chain = BIO_next(chain);
+		}
+	}
+
+static STACK_OF(CMS_CertificateChoices) **cms_get0_certificate_choices(CMS_ContentInfo *cms)
+	{
+	switch (OBJ_obj2nid(cms->contentType))
+		{
+
+		case NID_pkcs7_signed:
+		return &cms->d.signedData->certificates;
+
+		case NID_pkcs7_enveloped:
+		return &cms->d.envelopedData->originatorInfo->certificates;
+
+		default:
+		CMSerr(CMS_F_CMS_GET0_CERTIFICATE_CHOICES,
+					CMS_R_UNSUPPORTED_CONTENT_TYPE);
+		return NULL;
+
+		}
+	}
+
+CMS_CertificateChoices *CMS_add0_CertificateChoices(CMS_ContentInfo *cms)
+	{
+	STACK_OF(CMS_CertificateChoices) **pcerts;
+	CMS_CertificateChoices *cch;
+	pcerts = cms_get0_certificate_choices(cms);
+	if (!pcerts)
+		return NULL;
+	if (!*pcerts)
+		*pcerts = sk_CMS_CertificateChoices_new_null();
+	if (!*pcerts)
+		return NULL;
+	cch = M_ASN1_new_of(CMS_CertificateChoices);
+	if (!cch)
+		return NULL;
+	if (!sk_CMS_CertificateChoices_push(*pcerts, cch))
+		{
+		M_ASN1_free_of(cch, CMS_CertificateChoices);
+		return NULL;
+		}
+	return cch;
+	}
+
+int CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert)
+	{
+	CMS_CertificateChoices *cch;
+	STACK_OF(CMS_CertificateChoices) **pcerts;
+	int i;
+	pcerts = cms_get0_certificate_choices(cms);
+	if (!pcerts)
+		return 0;
+	for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++)
+		{
+		cch = sk_CMS_CertificateChoices_value(*pcerts, i);
+		if (cch->type == CMS_CERTCHOICE_CERT)
+			{
+			if (!X509_cmp(cch->d.certificate, cert))
+				{
+				CMSerr(CMS_F_CMS_ADD0_CERT,
+					CMS_R_CERTIFICATE_ALREADY_PRESENT);
+				return 0;
+				}
+			}
+		}
+	cch = CMS_add0_CertificateChoices(cms);
+	if (!cch)
+		return 0;
+	cch->type = CMS_CERTCHOICE_CERT;
+	cch->d.certificate = cert;
+	return 1;
+	}
+
+int CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert)
+	{
+	int r;
+	r = CMS_add0_cert(cms, cert);
+	if (r > 0)
+		CRYPTO_add(&cert->references, 1, CRYPTO_LOCK_X509);
+	return r;
+	}
+
+static STACK_OF(CMS_RevocationInfoChoice) **cms_get0_revocation_choices(CMS_ContentInfo *cms)
+	{
+	switch (OBJ_obj2nid(cms->contentType))
+		{
+
+		case NID_pkcs7_signed:
+		return &cms->d.signedData->crls;
+
+		case NID_pkcs7_enveloped:
+		return &cms->d.envelopedData->originatorInfo->crls;
+
+		default:
+		CMSerr(CMS_F_CMS_GET0_REVOCATION_CHOICES,
+					CMS_R_UNSUPPORTED_CONTENT_TYPE);
+		return NULL;
+
+		}
+	}
+
+CMS_RevocationInfoChoice *CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms)
+	{
+	STACK_OF(CMS_RevocationInfoChoice) **pcrls;
+	CMS_RevocationInfoChoice *rch;
+	pcrls = cms_get0_revocation_choices(cms);
+	if (!pcrls)
+		return NULL;
+	if (!*pcrls)
+		*pcrls = sk_CMS_RevocationInfoChoice_new_null();
+	if (!*pcrls)
+		return NULL;
+	rch = M_ASN1_new_of(CMS_RevocationInfoChoice);
+	if (!rch)
+		return NULL;
+	if (!sk_CMS_RevocationInfoChoice_push(*pcrls, rch))
+		{
+		M_ASN1_free_of(rch, CMS_RevocationInfoChoice);
+		return NULL;
+		}
+	return rch;
+	}
+
+int CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl)
+	{
+	CMS_RevocationInfoChoice *rch;
+	rch = CMS_add0_RevocationInfoChoice(cms);
+	if (!rch)
+		return 0;
+	rch->type = CMS_REVCHOICE_CRL;
+	rch->d.crl = crl;
+	return 1;
+	}
+
+int CMS_add1_crl(CMS_ContentInfo *cms, X509_CRL *crl)
+	{
+	int r;
+	r = CMS_add0_crl(cms, crl);
+	if (r > 0)
+		CRYPTO_add(&crl->references, 1, CRYPTO_LOCK_X509_CRL);
+	return r;
+	}
+
+STACK_OF(X509) *CMS_get1_certs(CMS_ContentInfo *cms)
+	{
+	STACK_OF(X509) *certs = NULL;
+	CMS_CertificateChoices *cch;
+	STACK_OF(CMS_CertificateChoices) **pcerts;
+	int i;
+	pcerts = cms_get0_certificate_choices(cms);
+	if (!pcerts)
+		return NULL;
+	for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++)
+		{
+		cch = sk_CMS_CertificateChoices_value(*pcerts, i);
+		if (cch->type == 0)
+			{
+			if (!certs)
+				{
+				certs = sk_X509_new_null();
+				if (!certs)
+					return NULL;
+				}
+			if (!sk_X509_push(certs, cch->d.certificate))
+				{
+				sk_X509_pop_free(certs, X509_free);
+				return NULL;
+				}
+			CRYPTO_add(&cch->d.certificate->references,
+						1, CRYPTO_LOCK_X509);
+			}
+		}
+	return certs;
+
+	}
+
+STACK_OF(X509_CRL) *CMS_get1_crls(CMS_ContentInfo *cms)
+	{
+	STACK_OF(X509_CRL) *crls = NULL;
+	STACK_OF(CMS_RevocationInfoChoice) **pcrls;
+	CMS_RevocationInfoChoice *rch;
+	int i;
+	pcrls = cms_get0_revocation_choices(cms);
+	if (!pcrls)
+		return NULL;
+	for (i = 0; i < sk_CMS_RevocationInfoChoice_num(*pcrls); i++)
+		{
+		rch = sk_CMS_RevocationInfoChoice_value(*pcrls, i);
+		if (rch->type == 0)
+			{
+			if (!crls)
+				{
+				crls = sk_X509_CRL_new_null();
+				if (!crls)
+					return NULL;
+				}
+			if (!sk_X509_CRL_push(crls, rch->d.crl))
+				{
+				sk_X509_CRL_pop_free(crls, X509_CRL_free);
+				return NULL;
+				}
+			CRYPTO_add(&rch->d.crl->references,
+						1, CRYPTO_LOCK_X509_CRL);
+			}
+		}
+	return crls;
+	}
