Exemplo n.º 1
0
static int pkcs7_cmp_ri(PKCS7_RECIP_INFO *ri, X509 *pcert)
	{
	int ret;
	ret = X509_NAME_cmp(ri->issuer_and_serial->issuer,
				pcert->cert_info->issuer);
	if (ret)
		return ret;
	return M_ASN1_INTEGER_cmp(pcert->cert_info->serialNumber,
					ri->issuer_and_serial->serial);
	}
Exemplo n.º 2
0
int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b)
	{
	int i;
	X509_CINF *ai,*bi;

	ai=a->cert_info;
	bi=b->cert_info;
	i=M_ASN1_INTEGER_cmp(ai->serialNumber,bi->serialNumber);
	if (i) return(i);
	return(X509_NAME_cmp(ai->issuer,bi->issuer));
	}
Exemplo n.º 3
0
/* int */
BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
	{
	int i,j;
	BIO *out=NULL,*btmp=NULL,*etmp=NULL,*bio=NULL;
	unsigned char *tmp=NULL;
	X509_ALGOR *xa;
	ASN1_OCTET_STRING *data_body=NULL;
	const EVP_MD *evp_md;
	const EVP_CIPHER *evp_cipher=NULL;
	EVP_CIPHER_CTX *evp_ctx=NULL;
	X509_ALGOR *enc_alg=NULL;
	STACK_OF(X509_ALGOR) *md_sk=NULL;
	STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL;
	X509_ALGOR *xalg=NULL;
	PKCS7_RECIP_INFO *ri=NULL;

	i=OBJ_obj2nid(p7->type);
	p7->state=PKCS7_S_HEADER;

	switch (i)
		{
	case NID_pkcs7_signed:
		data_body=p7->d.sign->contents->d.data;
		md_sk=p7->d.sign->md_algs;
		break;
	case NID_pkcs7_signedAndEnveloped:
		rsk=p7->d.signed_and_enveloped->recipientinfo;
		md_sk=p7->d.signed_and_enveloped->md_algs;
		data_body=p7->d.signed_and_enveloped->enc_data->enc_data;
		enc_alg=p7->d.signed_and_enveloped->enc_data->algorithm;
		evp_cipher=EVP_get_cipherbyname(OBJ_nid2sn(OBJ_obj2nid(enc_alg->algorithm)));
		if (evp_cipher == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
			goto err;
			}
		xalg=p7->d.signed_and_enveloped->enc_data->algorithm;
		break;
	case NID_pkcs7_enveloped:
		rsk=p7->d.enveloped->recipientinfo;
		enc_alg=p7->d.enveloped->enc_data->algorithm;
		data_body=p7->d.enveloped->enc_data->enc_data;
		evp_cipher=EVP_get_cipherbyname(OBJ_nid2sn(OBJ_obj2nid(enc_alg->algorithm)));
		if (evp_cipher == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
			goto err;
			}
		xalg=p7->d.enveloped->enc_data->algorithm;
		break;
	default:
		PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
	        goto err;
		}

	/* We will be checking the signature */
	if (md_sk != NULL)
		{
		for (i=0; i<sk_X509_ALGOR_num(md_sk); i++)
			{
			xa=sk_X509_ALGOR_value(md_sk,i);
			if ((btmp=BIO_new(BIO_f_md())) == NULL)
				{
				PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB);
				goto err;
				}

			j=OBJ_obj2nid(xa->algorithm);
			evp_md=EVP_get_digestbyname(OBJ_nid2sn(j));
			if (evp_md == NULL)
				{
				PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNKNOWN_DIGEST_TYPE);
				goto err;
				}

			BIO_set_md(btmp,evp_md);
			if (out == NULL)
				out=btmp;
			else
				BIO_push(out,btmp);
			btmp=NULL;
			}
		}

	if (evp_cipher != NULL)
		{
#if 0
		unsigned char key[EVP_MAX_KEY_LENGTH];
		unsigned char iv[EVP_MAX_IV_LENGTH];
		unsigned char *p;
		int keylen,ivlen;
		int max;
		X509_OBJECT ret;
#endif
		int jj;

		if ((etmp=BIO_new(BIO_f_cipher())) == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB);
			goto err;
			}

		/* It was encrypted, we need to decrypt the secret key
		 * with the private key */

		/* Find the recipientInfo which matches the passed certificate
		 * (if any)
		 */

		for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) {
			ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
			if(!X509_NAME_cmp(ri->issuer_and_serial->issuer,
					pcert->cert_info->issuer) &&
			     !M_ASN1_INTEGER_cmp(pcert->cert_info->serialNumber,
					ri->issuer_and_serial->serial)) break;
			ri=NULL;
		}
		if (ri == NULL) {
			PKCS7err(PKCS7_F_PKCS7_DATADECODE,
				 PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE);
			goto err;
		}

		jj=EVP_PKEY_size(pkey);
		tmp=(unsigned char *)OPENSSL_malloc(jj+10);
		if (tmp == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_MALLOC_FAILURE);
			goto err;
			}

		jj=EVP_PKEY_decrypt(tmp, M_ASN1_STRING_data(ri->enc_key),
			M_ASN1_STRING_length(ri->enc_key), pkey);
		if (jj <= 0)
			{
			PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_EVP_LIB);
			goto err;
			}

		evp_ctx=NULL;
		BIO_get_cipher_ctx(etmp,&evp_ctx);
		EVP_CipherInit_ex(evp_ctx,evp_cipher,NULL,NULL,NULL,0);
		if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0)
			goto err;

		if (jj != EVP_CIPHER_CTX_key_length(evp_ctx)) {
			/* Some S/MIME clients don't use the same key
			 * and effective key length. The key length is
			 * determined by the size of the decrypted RSA key.
			 */
			if(!EVP_CIPHER_CTX_set_key_length(evp_ctx, jj))
				{
				PKCS7err(PKCS7_F_PKCS7_DATADECODE,
					PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH);
				goto err;
				}
		} 
		EVP_CipherInit_ex(evp_ctx,NULL,NULL,tmp,NULL,0);

		OPENSSL_cleanse(tmp,jj);

		if (out == NULL)
			out=etmp;
		else
			BIO_push(out,etmp);
		etmp=NULL;
		}

#if 1
	if (PKCS7_is_detached(p7) || (in_bio != NULL))
		{
		bio=in_bio;
		}
	else 
		{
#if 0
		bio=BIO_new(BIO_s_mem());
		/* We need to set this so that when we have read all
		 * the data, the encrypt BIO, if present, will read
		 * EOF and encode the last few bytes */
		BIO_set_mem_eof_return(bio,0);

		if (data_body->length > 0)
			BIO_write(bio,(char *)data_body->data,data_body->length);
#else
		if (data_body->length > 0)
		      bio = BIO_new_mem_buf(data_body->data,data_body->length);
		else {
			bio=BIO_new(BIO_s_mem());
			BIO_set_mem_eof_return(bio,0);
		}
#endif
		}
	BIO_push(out,bio);
	bio=NULL;
#endif
	if (0)
		{
err:
		if (out != NULL) BIO_free_all(out);
		if (btmp != NULL) BIO_free_all(btmp);
		if (etmp != NULL) BIO_free_all(etmp);
		if (bio != NULL) BIO_free_all(bio);
		out=NULL;
		}
	if (tmp != NULL)
		OPENSSL_free(tmp);
	return(out);
	}