428 lines
		
	
	
	
		
			15 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			428 lines
		
	
	
	
		
			15 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| Index: crypto/openssl/crypto/asn1/a_type.c
 | |
| ===================================================================
 | |
| --- crypto/openssl/crypto/asn1/a_type.c	(revision 280181)
 | |
| +++ crypto/openssl/crypto/asn1/a_type.c	(working copy)
 | |
| @@ -124,6 +124,9 @@ int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_T
 | |
|  	case V_ASN1_OBJECT:
 | |
|  		result = OBJ_cmp(a->value.object, b->value.object);
 | |
|  		break;
 | |
| +	case V_ASN1_BOOLEAN:
 | |
| +		result = a->value.boolean - b->value.boolean;
 | |
| +		break;
 | |
|  	case V_ASN1_NULL:
 | |
|  		result = 0;	/* They do not have content. */
 | |
|  		break;
 | |
| Index: crypto/openssl/crypto/asn1/tasn_dec.c
 | |
| ===================================================================
 | |
| --- crypto/openssl/crypto/asn1/tasn_dec.c	(revision 280181)
 | |
| +++ crypto/openssl/crypto/asn1/tasn_dec.c	(working copy)
 | |
| @@ -127,16 +127,22 @@ unsigned long ASN1_tag2bit(int tag)
 | |
|  
 | |
|  ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval,
 | |
|  		const unsigned char **in, long len, const ASN1_ITEM *it)
 | |
| -	{
 | |
| +{
 | |
|  	ASN1_TLC c;
 | |
|  	ASN1_VALUE *ptmpval = NULL;
 | |
| -	if (!pval)
 | |
| -		pval = &ptmpval;
 | |
|  	asn1_tlc_clear_nc(&c);
 | |
| -	if (ASN1_item_ex_d2i(pval, in, len, it, -1, 0, 0, &c) > 0) 
 | |
| -		return *pval;
 | |
| +	if (pval && *pval && it->itype == ASN1_ITYPE_PRIMITIVE)
 | |
| +		ptmpval = *pval;
 | |
| +	if (ASN1_item_ex_d2i(&ptmpval, in, len, it, -1, 0, 0, &c) > 0) {
 | |
| +		if (pval && it->itype != ASN1_ITYPE_PRIMITIVE) {
 | |
| +			if (*pval)
 | |
| +				ASN1_item_free(*pval, it);
 | |
| +			*pval = ptmpval;
 | |
| +		}
 | |
| +		return ptmpval;
 | |
| +	}
 | |
|  	return NULL;
 | |
| -	}
 | |
| +}
 | |
|  
 | |
|  int ASN1_template_d2i(ASN1_VALUE **pval,
 | |
|  		const unsigned char **in, long len, const ASN1_TEMPLATE *tt)
 | |
| @@ -311,13 +317,20 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsi
 | |
|  		if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL))
 | |
|  				goto auxerr;
 | |
|  
 | |
| -		/* Allocate structure */
 | |
| -		if (!*pval && !ASN1_item_ex_new(pval, it))
 | |
| -			{
 | |
| +		if (*pval) {
 | |
| +			/* Free up and zero CHOICE value if initialised */
 | |
| +			i = asn1_get_choice_selector(pval, it);
 | |
| +			if ((i >= 0) && (i < it->tcount)) {
 | |
| +				tt = it->templates + i;
 | |
| +				pchptr = asn1_get_field_ptr(pval, tt);
 | |
| +				ASN1_template_free(pchptr, tt);
 | |
| +				asn1_set_choice_selector(pval, -1, it);
 | |
| +			}
 | |
| +		} else if (!ASN1_item_ex_new(pval, it)) {
 | |
|  			ASN1err(ASN1_F_ASN1_ITEM_EX_D2I,
 | |
|  						ERR_R_NESTED_ASN1_ERROR);
 | |
|  			goto err;
 | |
| -			}
 | |
| +		}
 | |
|  		/* CHOICE type, try each possibility in turn */
 | |
|  		p = *in;
 | |
|  		for (i = 0, tt=it->templates; i < it->tcount; i++, tt++)
 | |
| @@ -407,6 +420,17 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsi
 | |
|  		if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL))
 | |
|  				goto auxerr;
 | |
|  
 | |
| +		/* Free up and zero any ADB found */
 | |
| +		for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) {
 | |
| +			if (tt->flags & ASN1_TFLG_ADB_MASK) {
 | |
| +				const ASN1_TEMPLATE *seqtt;
 | |
| +				ASN1_VALUE **pseqval;
 | |
| +				seqtt = asn1_do_adb(pval, tt, 1);
 | |
| +				pseqval = asn1_get_field_ptr(pval, seqtt);
 | |
| +				ASN1_template_free(pseqval, seqtt);
 | |
| +			}
 | |
| +		}
 | |
| +
 | |
|  		/* Get each field entry */
 | |
|  		for (i = 0, tt = it->templates; i < it->tcount; i++, tt++)
 | |
|  			{
 | |
| Index: crypto/openssl/crypto/pkcs7/pk7_doit.c
 | |
| ===================================================================
 | |
| --- crypto/openssl/crypto/pkcs7/pk7_doit.c	(revision 280181)
 | |
| +++ crypto/openssl/crypto/pkcs7/pk7_doit.c	(working copy)
 | |
| @@ -272,6 +272,25 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
 | |
|  	PKCS7_RECIP_INFO *ri=NULL;
 | |
|  	ASN1_OCTET_STRING *os=NULL;
 | |
|  
 | |
| +	if (p7 == NULL) {
 | |
| +		PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_INVALID_NULL_POINTER);
 | |
| +		return NULL;
 | |
| +	}
 | |
| +	/*
 | |
| +	 * The content field in the PKCS7 ContentInfo is optional, but that really
 | |
| +	 * only applies to inner content (precisely, detached signatures).
 | |
| +	 *
 | |
| +	 * When reading content, missing outer content is therefore treated as an
 | |
| +	 * error.
 | |
| +	 *
 | |
| +	 * When creating content, PKCS7_content_new() must be called before
 | |
| +	 * calling this method, so a NULL p7->d is always an error.
 | |
| +	 */
 | |
| +	if (p7->d.ptr == NULL) {
 | |
| +		PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_NO_CONTENT);
 | |
| +		return NULL;
 | |
| +	}
 | |
| +
 | |
|  	i=OBJ_obj2nid(p7->type);
 | |
|  	p7->state=PKCS7_S_HEADER;
 | |
|  
 | |
| @@ -433,6 +452,16 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, B
 | |
|         unsigned char *ek = NULL, *tkey = NULL;
 | |
|         int eklen = 0, tkeylen = 0;
 | |
|  
 | |
| +	if (p7 == NULL) {
 | |
| +		PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_INVALID_NULL_POINTER);
 | |
| +		return NULL;
 | |
| +	}
 | |
| +
 | |
| +	if (p7->d.ptr == NULL) {
 | |
| +		PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_CONTENT);
 | |
| +		return NULL;
 | |
| +	}
 | |
| +
 | |
|  	i=OBJ_obj2nid(p7->type);
 | |
|  	p7->state=PKCS7_S_HEADER;
 | |
|  
 | |
| @@ -752,6 +781,16 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
 | |
|  	STACK_OF(PKCS7_SIGNER_INFO) *si_sk=NULL;
 | |
|  	ASN1_OCTET_STRING *os=NULL;
 | |
|  
 | |
| +	if (p7 == NULL) {
 | |
| +		PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_INVALID_NULL_POINTER);
 | |
| +		return 0;
 | |
| +	}
 | |
| +
 | |
| +	if (p7->d.ptr == NULL) {
 | |
| +		PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_NO_CONTENT);
 | |
| +		return 0;
 | |
| +	}
 | |
| +
 | |
|  	EVP_MD_CTX_init(&ctx_tmp);
 | |
|  	i=OBJ_obj2nid(p7->type);
 | |
|  	p7->state=PKCS7_S_HEADER;
 | |
| @@ -796,6 +835,7 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
 | |
|  		/* If detached data then the content is excluded */
 | |
|  		if(PKCS7_type_is_data(p7->d.sign->contents) && p7->detached) {
 | |
|  			M_ASN1_OCTET_STRING_free(os);
 | |
| +			os = NULL;
 | |
|  			p7->d.sign->contents->d.data = NULL;
 | |
|  		}
 | |
|  		break;
 | |
| @@ -806,6 +846,7 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
 | |
|  		if(PKCS7_type_is_data(p7->d.digest->contents) && p7->detached)
 | |
|  			{
 | |
|  			M_ASN1_OCTET_STRING_free(os);
 | |
| +			os = NULL;
 | |
|  			p7->d.digest->contents->d.data = NULL;
 | |
|  			}
 | |
|  		break;
 | |
| @@ -866,8 +907,7 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
 | |
|  				}
 | |
|  			}
 | |
|  		}
 | |
| -	else if (i == NID_pkcs7_digest)
 | |
| -		{
 | |
| +	else if (i == NID_pkcs7_digest) {
 | |
|  		unsigned char md_data[EVP_MAX_MD_SIZE];
 | |
|  		unsigned int md_len;
 | |
|  		if (!PKCS7_find_digest(&mdc, bio,
 | |
| @@ -878,24 +918,31 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
 | |
|  		M_ASN1_OCTET_STRING_set(p7->d.digest->digest, md_data, md_len);
 | |
|  		}
 | |
|  
 | |
| -	if (!PKCS7_is_detached(p7) && !(os->flags & ASN1_STRING_FLAG_NDEF))
 | |
| -		{
 | |
| -		char *cont;
 | |
| -		long contlen;
 | |
| -		btmp=BIO_find_type(bio,BIO_TYPE_MEM);
 | |
| -		if (btmp == NULL)
 | |
| -			{
 | |
| -			PKCS7err(PKCS7_F_PKCS7_DATAFINAL,PKCS7_R_UNABLE_TO_FIND_MEM_BIO);
 | |
| -			goto err;
 | |
| +		if (!PKCS7_is_detached(p7)) {
 | |
| +			/*
 | |
| +			 * NOTE(emilia): I think we only reach os == NULL here because detached
 | |
| +			 * digested data support is broken.
 | |
| +			 */
 | |
| +			if (os == NULL)
 | |
| +				goto err;
 | |
| +			if (!(os->flags & ASN1_STRING_FLAG_NDEF)) {
 | |
| +				char *cont;
 | |
| +				long contlen;
 | |
| +				btmp = BIO_find_type(bio, BIO_TYPE_MEM);
 | |
| +				if (btmp == NULL) {
 | |
| +					PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_UNABLE_TO_FIND_MEM_BIO);
 | |
| +				goto err;
 | |
|  			}
 | |
| -		contlen = BIO_get_mem_data(btmp, &cont);
 | |
| -		/* Mark the BIO read only then we can use its copy of the data
 | |
| -		 * instead of making an extra copy.
 | |
| -		 */
 | |
| -		BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY);
 | |
| -		BIO_set_mem_eof_return(btmp, 0);
 | |
| -		ASN1_STRING_set0(os, (unsigned char *)cont, contlen);
 | |
| +			contlen = BIO_get_mem_data(btmp, &cont);
 | |
| +			/*
 | |
| +			 * Mark the BIO read only then we can use its copy of the data
 | |
| +			 * instead of making an extra copy.
 | |
| +			 */
 | |
| +			BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY);
 | |
| +			BIO_set_mem_eof_return(btmp, 0);
 | |
| +			ASN1_STRING_set0(os, (unsigned char *)cont, contlen);
 | |
|  		}
 | |
| +	}
 | |
|  	ret=1;
 | |
|  err:
 | |
|  	EVP_MD_CTX_cleanup(&ctx_tmp);
 | |
| @@ -971,6 +1018,16 @@ int PKCS7_dataVerify(X509_STORE *cert_store, X509_
 | |
|  	STACK_OF(X509) *cert;
 | |
|  	X509 *x509;
 | |
|  
 | |
| +	if (p7 == NULL) {
 | |
| +		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_INVALID_NULL_POINTER);
 | |
| +		return 0;
 | |
| +	}
 | |
| +
 | |
| +	if (p7->d.ptr == NULL) {
 | |
| +		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_NO_CONTENT);
 | |
| +		return 0;
 | |
| +	}
 | |
| +
 | |
|  	if (PKCS7_type_is_signed(p7))
 | |
|  		{
 | |
|  		cert=p7->d.sign->cert;
 | |
| Index: crypto/openssl/crypto/pkcs7/pk7_lib.c
 | |
| ===================================================================
 | |
| --- crypto/openssl/crypto/pkcs7/pk7_lib.c	(revision 280181)
 | |
| +++ crypto/openssl/crypto/pkcs7/pk7_lib.c	(working copy)
 | |
| @@ -71,6 +71,7 @@ long PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, cha
 | |
|  
 | |
|  	switch (cmd)
 | |
|  		{
 | |
| +	/* NOTE(emilia): does not support detached digested data. */
 | |
|  	case PKCS7_OP_SET_DETACHED_SIGNATURE:
 | |
|  		if (nid == NID_pkcs7_signed)
 | |
|  			{
 | |
| @@ -459,6 +460,8 @@ int PKCS7_set_digest(PKCS7 *p7, const EVP_MD *md)
 | |
|  
 | |
|  STACK_OF(PKCS7_SIGNER_INFO) *PKCS7_get_signer_info(PKCS7 *p7)
 | |
|  	{
 | |
| +	if (p7 == NULL || p7->d.ptr == NULL)
 | |
| +		return NULL;
 | |
|  	if (PKCS7_type_is_signed(p7))
 | |
|  		{
 | |
|  		return(p7->d.sign->signer_info);
 | |
| Index: crypto/openssl/doc/crypto/d2i_X509.pod
 | |
| ===================================================================
 | |
| --- crypto/openssl/doc/crypto/d2i_X509.pod	(revision 280181)
 | |
| +++ crypto/openssl/doc/crypto/d2i_X509.pod	(working copy)
 | |
| @@ -199,6 +199,12 @@ B<*px> is valid is broken and some parts of the re
 | |
|  persist if they are not present in the new one. As a result the use
 | |
|  of this "reuse" behaviour is strongly discouraged.
 | |
|  
 | |
| +Current versions of OpenSSL will not modify B<*px> if an error occurs.
 | |
| +If parsing succeeds then B<*px> is freed (if it is not NULL) and then
 | |
| +set to the value of the newly decoded structure. As a result B<*px>
 | |
| +B<must not> be allocated on the stack or an attempt will be made to
 | |
| +free an invalid pointer.
 | |
| +
 | |
|  i2d_X509() will not return an error in many versions of OpenSSL,
 | |
|  if mandatory fields are not initialized due to a programming error
 | |
|  then the encoded structure may contain invalid data or omit the
 | |
| @@ -210,7 +216,9 @@ always succeed.
 | |
|  
 | |
|  d2i_X509(), d2i_X509_bio() and d2i_X509_fp() return a valid B<X509> structure
 | |
|  or B<NULL> if an error occurs. The error code that can be obtained by
 | |
| -L<ERR_get_error(3)|ERR_get_error(3)>. 
 | |
| +L<ERR_get_error(3)|ERR_get_error(3)>. If the "reuse" capability has been used
 | |
| +with a valid X509 structure being passed in via B<px> then the object is not
 | |
| +modified in the event of error.
 | |
|  
 | |
|  i2d_X509() returns the number of bytes successfully encoded or a negative
 | |
|  value if an error occurs. The error code can be obtained by
 | |
| Index: crypto/openssl/ssl/s2_lib.c
 | |
| ===================================================================
 | |
| --- crypto/openssl/ssl/s2_lib.c	(revision 280181)
 | |
| +++ crypto/openssl/ssl/s2_lib.c	(working copy)
 | |
| @@ -488,7 +488,7 @@ int ssl2_generate_key_material(SSL *s)
 | |
|  
 | |
|  		OPENSSL_assert(s->session->master_key_length >= 0
 | |
|  		    && s->session->master_key_length
 | |
| -		    < (int)sizeof(s->session->master_key));
 | |
| +		    <= (int)sizeof(s->session->master_key));
 | |
|  		EVP_DigestUpdate(&ctx,s->session->master_key,s->session->master_key_length);
 | |
|  		EVP_DigestUpdate(&ctx,&c,1);
 | |
|  		c++;
 | |
| Index: crypto/openssl/ssl/s2_srvr.c
 | |
| ===================================================================
 | |
| --- crypto/openssl/ssl/s2_srvr.c	(revision 280181)
 | |
| +++ crypto/openssl/ssl/s2_srvr.c	(working copy)
 | |
| @@ -454,9 +454,6 @@ static int get_client_master_key(SSL *s)
 | |
|  		SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_NO_PRIVATEKEY);
 | |
|  		return(-1);
 | |
|  		}
 | |
| -	i=ssl_rsa_private_decrypt(s->cert,s->s2->tmp.enc,
 | |
| -		&(p[s->s2->tmp.clear]),&(p[s->s2->tmp.clear]),
 | |
| -		(s->s2->ssl2_rollback)?RSA_SSLV23_PADDING:RSA_PKCS1_PADDING);
 | |
|  
 | |
|  	is_export=SSL_C_IS_EXPORT(s->session->cipher);
 | |
|  	
 | |
| @@ -475,23 +472,61 @@ static int get_client_master_key(SSL *s)
 | |
|  	else
 | |
|  		ek=5;
 | |
|  
 | |
| +	/*
 | |
| +	 * The format of the CLIENT-MASTER-KEY message is
 | |
| +	 * 1 byte message type
 | |
| +	 * 3 bytes cipher
 | |
| +	 * 2-byte clear key length (stored in s->s2->tmp.clear)
 | |
| +	 * 2-byte encrypted key length (stored in s->s2->tmp.enc)
 | |
| +	 * 2-byte key args length (IV etc)
 | |
| +	 * clear key
 | |
| +	 * encrypted key
 | |
| +	 * key args
 | |
| +	 *
 | |
| +	 * If the cipher is an export cipher, then the encrypted key bytes
 | |
| +	 * are a fixed portion of the total key (5 or 8 bytes). The size of
 | |
| +	 * this portion is in |ek|. If the cipher is not an export cipher,
 | |
| +	 * then the entire key material is encrypted (i.e., clear key length
 | |
| +	 * must be zero).
 | |
| +	 */
 | |
| +	if ((!is_export && s->s2->tmp.clear != 0) ||
 | |
| +	    (is_export && s->s2->tmp.clear + ek != EVP_CIPHER_key_length(c))) {
 | |
| +		ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR);
 | |
| +		SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_BAD_LENGTH);
 | |
| +		return -1;
 | |
| +	}
 | |
| +	/*
 | |
| +	 * The encrypted blob must decrypt to the encrypted portion of the key.
 | |
| +	 * Decryption can't be expanding, so if we don't have enough encrypted
 | |
| +	 * bytes to fit the key in the buffer, stop now.
 | |
| +	 */
 | |
| +	if ((is_export && s->s2->tmp.enc < ek) ||
 | |
| +	    (!is_export && s->s2->tmp.enc < EVP_CIPHER_key_length(c))) {
 | |
| +		ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
 | |
| +		SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_LENGTH_TOO_SHORT);
 | |
| +		return -1;
 | |
| +	}
 | |
| +
 | |
| +	i = ssl_rsa_private_decrypt(s->cert, s->s2->tmp.enc,
 | |
| +                                &(p[s->s2->tmp.clear]),
 | |
| +                                &(p[s->s2->tmp.clear]),
 | |
| +                                (s->s2->ssl2_rollback) ? RSA_SSLV23_PADDING :
 | |
| +                                RSA_PKCS1_PADDING);
 | |
| +
 | |
|  	/* bad decrypt */
 | |
|  #if 1
 | |
|  	/* If a bad decrypt, continue with protocol but with a
 | |
|  	 * random master secret (Bleichenbacher attack) */
 | |
| -	if ((i < 0) ||
 | |
| -		((!is_export && (i != EVP_CIPHER_key_length(c)))
 | |
| -		|| (is_export && ((i != ek) || (s->s2->tmp.clear+(unsigned int)i !=
 | |
| -			(unsigned int)EVP_CIPHER_key_length(c))))))
 | |
| -		{
 | |
| +	if ((i < 0) || ((!is_export && i != EVP_CIPHER_key_length(c))
 | |
| +                    || (is_export && i != ek))) {
 | |
|  		ERR_clear_error();
 | |
|  		if (is_export)
 | |
|  			i=ek;
 | |
|  		else
 | |
|  			i=EVP_CIPHER_key_length(c);
 | |
| -		if (RAND_pseudo_bytes(p,i) <= 0)
 | |
| +		if (RAND_pseudo_bytes(&p[s->s2->tmp.clear], i) <= 0)
 | |
|  			return 0;
 | |
| -		}
 | |
| +	}
 | |
|  #else
 | |
|  	if (i < 0)
 | |
|  		{
 | |
| @@ -513,7 +548,8 @@ static int get_client_master_key(SSL *s)
 | |
|  		}
 | |
|  #endif
 | |
|  
 | |
| -	if (is_export) i+=s->s2->tmp.clear;
 | |
| +	if (is_export)
 | |
| +		i = EVP_CIPHER_key_length(c);
 | |
|  
 | |
|  	if (i > SSL_MAX_MASTER_KEY_LENGTH)
 | |
|  		{
 | |
| Index: secure/lib/libcrypto/man/d2i_X509.3
 | |
| ===================================================================
 | |
| --- secure/lib/libcrypto/man/d2i_X509.3	(revision 280181)
 | |
| +++ secure/lib/libcrypto/man/d2i_X509.3	(working copy)
 | |
| @@ -342,6 +342,12 @@ In some versions of OpenSSL the \*(L"reuse\*(R" be
 | |
|  persist if they are not present in the new one. As a result the use
 | |
|  of this \*(L"reuse\*(R" behaviour is strongly discouraged.
 | |
|  .PP
 | |
| +Current versions of OpenSSL will not modify \fB*px\fR if an error occurs.
 | |
| +If parsing succeeds then \fB*px\fR is freed (if it is not \s-1NULL\s0) and then
 | |
| +set to the value of the newly decoded structure. As a result \fB*px\fR
 | |
| +\&\fBmust not\fR be allocated on the stack or an attempt will be made to
 | |
| +free an invalid pointer.
 | |
| +.PP
 | |
|  \&\fIi2d_X509()\fR will not return an error in many versions of OpenSSL,
 | |
|  if mandatory fields are not initialized due to a programming error
 | |
|  then the encoded structure may contain invalid data or omit the
 | |
| @@ -352,7 +358,9 @@ always succeed.
 | |
|  .IX Header "RETURN VALUES"
 | |
|  \&\fId2i_X509()\fR, \fId2i_X509_bio()\fR and \fId2i_X509_fp()\fR return a valid \fBX509\fR structure
 | |
|  or \fB\s-1NULL\s0\fR if an error occurs. The error code that can be obtained by
 | |
| -\&\fIERR_get_error\fR\|(3).
 | |
| +\&\fIERR_get_error\fR\|(3). If the \*(L"reuse\*(R" capability has been used
 | |
| +with a valid X509 structure being passed in via \fBpx\fR then the object is not
 | |
| +modified in the event of error.
 | |
|  .PP
 | |
|  \&\fIi2d_X509()\fR returns the number of bytes successfully encoded or a negative
 | |
|  value if an error occurs. The error code can be obtained by
 |