X509_INFO *xi=NULL; char *name=NULL,*header=NULL; void *pp; unsigned char *data=NULL; const unsigned char *p; long len,error=0; int ok=0; STACK_OF(X509_INFO) *ret=NULL; unsigned int i,raw; d2i_of_void *d2i;
BIO *b; STACK_OF(X509_INFO) *ret;
STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb, void *u)	{	X509_INFO *xi=NULL;	char *name=NULL,*header=NULL;	void *pp;	unsigned char *data=NULL;	const unsigned char *p;	long len,error=0;	int ok=0;	STACK_OF(X509_INFO) *ret=NULL;	unsigned int i,raw;	d2i_of_void *d2i;	if (sk == NULL)		{		if ((ret=sk_X509_INFO_new_null()) == NULL)			{			PEMerr(PEM_F_PEM_X509_INFO_READ_BIO,ERR_R_MALLOC_FAILURE);			goto err;			}		}	else		ret=sk;	if ((xi=X509_INFO_new()) == NULL) goto err;	for (;;)		{		raw=0;		i=PEM_read_bio(bp,&name,&header,&data,&len);		if (i == 0)			{			error=ERR_GET_REASON(ERR_peek_last_error());			if (error == PEM_R_NO_START_LINE)				{				ERR_clear_error();				break;				}			goto err;			}start:		if (	(strcmp(name,PEM_STRING_X509) == 0) ||			(strcmp(name,PEM_STRING_X509_OLD) == 0))			{			(D2I_OF(X509))d2i=d2i_X509;			if (xi->x509 != NULL)				{				if (!sk_X509_INFO_push(ret,xi)) goto err;				if ((xi=X509_INFO_new()) == NULL) goto err;				goto start;				}			pp=&(xi->x509);			}		else if ((strcmp(name,PEM_STRING_X509_TRUSTED) == 0))			{			(D2I_OF(X509))d2i=d2i_X509_AUX;			if (xi->x509 != NULL)				{				if (!sk_X509_INFO_push(ret,xi)) goto err;				if ((xi=X509_INFO_new()) == NULL) goto err;				goto start;				}			pp=&(xi->x509);			}		else if (strcmp(name,PEM_STRING_X509_CRL) == 0)			{			(D2I_OF(X509_CRL))d2i=d2i_X509_CRL;			if (xi->crl != NULL)				{				if (!sk_X509_INFO_push(ret,xi)) goto err;				if ((xi=X509_INFO_new()) == NULL) goto err;				goto start;				}			pp=&(xi->crl);			}		else#ifndef OPENSSL_NO_RSA			if (strcmp(name,PEM_STRING_RSA) == 0)			{			(D2I_OF(RSA))d2i=d2i_RSAPrivateKey;			if (xi->x_pkey != NULL) 				{				if (!sk_X509_INFO_push(ret,xi)) goto err;				if ((xi=X509_INFO_new()) == NULL) goto err;				goto start;				}			xi->enc_data=NULL;			xi->enc_len=0;			xi->x_pkey=X509_PKEY_new();			if ((xi->x_pkey->dec_pkey=EVP_PKEY_new()) == NULL)				goto err;			xi->x_pkey->dec_pkey->type=EVP_PKEY_RSA;			pp=&(xi->x_pkey->dec_pkey->pkey.rsa);			if ((int)strlen(header) > 10) /* assume encrypted */				raw=1;			}		else#endif#ifndef OPENSSL_NO_DSA			if (strcmp(name,PEM_STRING_DSA) == 0)			{			(D2I_OF(RSA))d2i=d2i_DSAPrivateKey;			if (xi->x_pkey != NULL) 				{				if (!sk_X509_INFO_push(ret,xi)) goto err;				if ((xi=X509_INFO_new()) == NULL) goto err;				goto start;				}			xi->enc_data=NULL;			xi->enc_len=0;			xi->x_pkey=X509_PKEY_new();			if ((xi->x_pkey->dec_pkey=EVP_PKEY_new()) == NULL)				goto err;			xi->x_pkey->dec_pkey->type=EVP_PKEY_DSA;			pp=(char **)&(xi->x_pkey->dec_pkey->pkey.dsa);			if ((int)strlen(header) > 10) /* assume encrypted */				raw=1;			}		else#endif#ifndef OPENSSL_NO_EC 			if (strcmp(name,PEM_STRING_ECPRIVATEKEY) == 0) 			{ 				(D2I_OF(EC_KEY))d2i=d2i_ECPrivateKey; 				if (xi->x_pkey != NULL)  				{ 					if (!sk_X509_INFO_push(ret,xi)) goto err; 					if ((xi=X509_INFO_new()) == NULL) goto err; 						goto start; 				}  			xi->enc_data=NULL; 			xi->enc_len=0;  			xi->x_pkey=X509_PKEY_new(); 			if ((xi->x_pkey->dec_pkey=EVP_PKEY_new()) == NULL) 				goto err; 			xi->x_pkey->dec_pkey->type=EVP_PKEY_EC; 			pp=&(xi->x_pkey->dec_pkey->pkey.eckey); 			if ((int)strlen(header) > 10) /* assume encrypted */ 				raw=1;			}		else#endif			{			d2i=NULL;			pp=NULL;			}		if (d2i != NULL)			{			if (!raw)				{				EVP_CIPHER_INFO cipher;				if (!PEM_get_EVP_CIPHER_INFO(header,&cipher))					goto err;				if (!PEM_do_header(&cipher,data,&len,cb,u))					goto err;				p=data;				if (d2i(pp,&p,len) == NULL)					{					PEMerr(PEM_F_PEM_X509_INFO_READ_BIO,ERR_R_ASN1_LIB);					goto err;					}				}			else				{ /* encrypted RSA data */				if (!PEM_get_EVP_CIPHER_INFO(header,					&xi->enc_cipher)) goto err;				xi->enc_data=(char *)data;				xi->enc_len=(int)len;				data=NULL;				}			}		else	{			/* unknown */			}		if (name != NULL) OPENSSL_free(name);		if (header != NULL) OPENSSL_free(header);		if (data != NULL) OPENSSL_free(data);		name=NULL;		header=NULL;		data=NULL;		}	/* if the last one hasn't been pushed yet and there is anything	 * in it then add it to the stack ... 	 */	if ((xi->x509 != NULL) || (xi->crl != NULL) ||		(xi->x_pkey != NULL) || (xi->enc_data != NULL))		{		if (!sk_X509_INFO_push(ret,xi)) goto err;		xi=NULL;		}	ok=1;err:	if (xi != NULL) X509_INFO_free(xi);	if (!ok)		{		for (i=0; ((int)i)<sk_X509_INFO_num(ret); i++)			{			xi=sk_X509_INFO_value(ret,i);			X509_INFO_free(xi);			}		if (ret != sk) sk_X509_INFO_free(ret);		ret=NULL;		}			if (name != NULL) OPENSSL_free(name);	if (header != NULL) OPENSSL_free(header);	if (data != NULL) OPENSSL_free(data);	return(ret);	}