| Index: openssl/crypto/x509/x509_cmp.c
 | 
| ===================================================================
 | 
| --- openssl/crypto/x509/x509_cmp.c	(revision 105093)
 | 
| +++ openssl/crypto/x509/x509_cmp.c	(working copy)
 | 
| @@ -116,6 +116,13 @@
 | 
|  	return(X509_NAME_cmp(a->crl->issuer,b->crl->issuer));
 | 
|  	}
 | 
|  
 | 
| +#ifndef OPENSSL_NO_SHA
 | 
| +int X509_CRL_match(const X509_CRL *a, const X509_CRL *b)
 | 
| +	{
 | 
| +	return memcmp(a->sha1_hash, b->sha1_hash, 20);
 | 
| +	}
 | 
| +#endif
 | 
| +
 | 
|  X509_NAME *X509_get_issuer_name(X509 *a)
 | 
|  	{
 | 
|  	return(a->cert_info->issuer);
 | 
| @@ -126,6 +133,13 @@
 | 
|  	return(X509_NAME_hash(x->cert_info->issuer));
 | 
|  	}
 | 
|  
 | 
| +#ifndef OPENSSL_NO_MD5
 | 
| +unsigned long X509_issuer_name_hash_old(X509 *x)
 | 
| +	{
 | 
| +	return(X509_NAME_hash_old(x->cert_info->issuer));
 | 
| +	}
 | 
| +#endif
 | 
| +
 | 
|  X509_NAME *X509_get_subject_name(X509 *a)
 | 
|  	{
 | 
|  	return(a->cert_info->subject);
 | 
| @@ -141,6 +155,13 @@
 | 
|  	return(X509_NAME_hash(x->cert_info->subject));
 | 
|  	}
 | 
|  
 | 
| +#ifndef OPENSSL_NO_MD5
 | 
| +unsigned long X509_subject_name_hash_old(X509 *x)
 | 
| +	{
 | 
| +	return(X509_NAME_hash_old(x->cert_info->subject));
 | 
| +	}
 | 
| +#endif
 | 
| +
 | 
|  #ifndef OPENSSL_NO_SHA
 | 
|  /* Compare two certificates: they must be identical for
 | 
|   * this to work. NB: Although "cmp" operations are generally
 | 
| @@ -162,177 +183,63 @@
 | 
|  #endif
 | 
|  
 | 
|  
 | 
| -/* Case insensitive string comparision */
 | 
| -static int nocase_cmp(const ASN1_STRING *a, const ASN1_STRING *b)
 | 
| -{
 | 
| -	int i;
 | 
| -
 | 
| -	if (a->length != b->length)
 | 
| -		return (a->length - b->length);
 | 
| -
 | 
| -	for (i=0; i<a->length; i++)
 | 
| +int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b)
 | 
|  	{
 | 
| -		int ca, cb;
 | 
| +	int ret;
 | 
|  
 | 
| -		ca = tolower(a->data[i]);
 | 
| -		cb = tolower(b->data[i]);
 | 
| +	/* Ensure canonical encoding is present and up to date */
 | 
|  
 | 
| -		if (ca != cb)
 | 
| -			return(ca-cb);
 | 
| -	}
 | 
| -	return 0;
 | 
| -}
 | 
| +	if (!a->canon_enc || a->modified)
 | 
| +		{
 | 
| +		ret = i2d_X509_NAME((X509_NAME *)a, NULL);
 | 
| +		if (ret < 0)
 | 
| +			return -2;
 | 
| +		}
 | 
|  
 | 
| -/* Case insensitive string comparision with space normalization 
 | 
| - * Space normalization - ignore leading, trailing spaces, 
 | 
| - *       multiple spaces between characters are replaced by single space  
 | 
| - */
 | 
| -static int nocase_spacenorm_cmp(const ASN1_STRING *a, const ASN1_STRING *b)
 | 
| -{
 | 
| -	unsigned char *pa = NULL, *pb = NULL;
 | 
| -	int la, lb;
 | 
| -	
 | 
| -	la = a->length;
 | 
| -	lb = b->length;
 | 
| -	pa = a->data;
 | 
| -	pb = b->data;
 | 
| +	if (!b->canon_enc || b->modified)
 | 
| +		{
 | 
| +		ret = i2d_X509_NAME((X509_NAME *)b, NULL);
 | 
| +		if (ret < 0)
 | 
| +			return -2;
 | 
| +		}
 | 
|  
 | 
| -	/* skip leading spaces */
 | 
| -	while (la > 0 && isspace(*pa))
 | 
| -	{
 | 
| -		la--;
 | 
| -		pa++;
 | 
| -	}
 | 
| -	while (lb > 0 && isspace(*pb))
 | 
| -	{
 | 
| -		lb--;
 | 
| -		pb++;
 | 
| -	}
 | 
| +	ret = a->canon_enclen - b->canon_enclen;
 | 
|  
 | 
| -	/* skip trailing spaces */
 | 
| -	while (la > 0 && isspace(pa[la-1]))
 | 
| -		la--;
 | 
| -	while (lb > 0 && isspace(pb[lb-1]))
 | 
| -		lb--;
 | 
| +	if (ret)
 | 
| +		return ret;
 | 
|  
 | 
| -	/* compare strings with space normalization */
 | 
| -	while (la > 0 && lb > 0)
 | 
| -	{
 | 
| -		int ca, cb;
 | 
| +	return memcmp(a->canon_enc, b->canon_enc, a->canon_enclen);
 | 
|  
 | 
| -		/* compare character */
 | 
| -		ca = tolower(*pa);
 | 
| -		cb = tolower(*pb);
 | 
| -		if (ca != cb)
 | 
| -			return (ca - cb);
 | 
| -
 | 
| -		pa++; pb++;
 | 
| -		la--; lb--;
 | 
| -
 | 
| -		if (la <= 0 || lb <= 0)
 | 
| -			break;
 | 
| -
 | 
| -		/* is white space next character ? */
 | 
| -		if (isspace(*pa) && isspace(*pb))
 | 
| -		{
 | 
| -			/* skip remaining white spaces */
 | 
| -			while (la > 0 && isspace(*pa))
 | 
| -			{
 | 
| -				la--;
 | 
| -				pa++;
 | 
| -			}
 | 
| -			while (lb > 0 && isspace(*pb))
 | 
| -			{
 | 
| -				lb--;
 | 
| -				pb++;
 | 
| -			}
 | 
| -		}
 | 
|  	}
 | 
| -	if (la > 0 || lb > 0)
 | 
| -		return la - lb;
 | 
|  
 | 
| -	return 0;
 | 
| -}
 | 
| -
 | 
| -static int asn1_string_memcmp(ASN1_STRING *a, ASN1_STRING *b)
 | 
| +unsigned long X509_NAME_hash(X509_NAME *x)
 | 
|  	{
 | 
| -	int j;
 | 
| -	j = a->length - b->length;
 | 
| -	if (j)
 | 
| -		return j;
 | 
| -	return memcmp(a->data, b->data, a->length);
 | 
| -	}
 | 
| +	unsigned long ret=0;
 | 
| +	unsigned char md[SHA_DIGEST_LENGTH];
 | 
|  
 | 
| -#define STR_TYPE_CMP (B_ASN1_PRINTABLESTRING|B_ASN1_T61STRING|B_ASN1_UTF8STRING)
 | 
| +	/* Make sure X509_NAME structure contains valid cached encoding */
 | 
| +	i2d_X509_NAME(x,NULL);
 | 
| +	EVP_Digest(x->canon_enc, x->canon_enclen, md, NULL, EVP_sha1(), NULL);
 | 
|  
 | 
| -int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b)
 | 
| -	{
 | 
| -	int i,j;
 | 
| -	X509_NAME_ENTRY *na,*nb;
 | 
| -
 | 
| -	unsigned long nabit, nbbit;
 | 
| -
 | 
| -	j = sk_X509_NAME_ENTRY_num(a->entries)
 | 
| -		  - sk_X509_NAME_ENTRY_num(b->entries);
 | 
| -	if (j)
 | 
| -		return j;
 | 
| -	for (i=sk_X509_NAME_ENTRY_num(a->entries)-1; i>=0; i--)
 | 
| -		{
 | 
| -		na=sk_X509_NAME_ENTRY_value(a->entries,i);
 | 
| -		nb=sk_X509_NAME_ENTRY_value(b->entries,i);
 | 
| -		j=na->value->type-nb->value->type;
 | 
| -		if (j)
 | 
| -			{
 | 
| -			nabit = ASN1_tag2bit(na->value->type);
 | 
| -			nbbit = ASN1_tag2bit(nb->value->type);
 | 
| -			if (!(nabit & STR_TYPE_CMP) ||
 | 
| -				!(nbbit & STR_TYPE_CMP))
 | 
| -				return j;
 | 
| -			if (!asn1_string_memcmp(na->value, nb->value))
 | 
| -				j = 0;
 | 
| -			}
 | 
| -		else if (na->value->type == V_ASN1_PRINTABLESTRING)
 | 
| -			j=nocase_spacenorm_cmp(na->value, nb->value);
 | 
| -		else if (na->value->type == V_ASN1_IA5STRING
 | 
| -			&& OBJ_obj2nid(na->object) == NID_pkcs9_emailAddress)
 | 
| -			j=nocase_cmp(na->value, nb->value);
 | 
| -		else
 | 
| -			j = asn1_string_memcmp(na->value, nb->value);
 | 
| -		if (j) return(j);
 | 
| -		j=na->set-nb->set;
 | 
| -		if (j) return(j);
 | 
| -		}
 | 
| -
 | 
| -	/* We will check the object types after checking the values
 | 
| -	 * since the values will more often be different than the object
 | 
| -	 * types. */
 | 
| -	for (i=sk_X509_NAME_ENTRY_num(a->entries)-1; i>=0; i--)
 | 
| -		{
 | 
| -		na=sk_X509_NAME_ENTRY_value(a->entries,i);
 | 
| -		nb=sk_X509_NAME_ENTRY_value(b->entries,i);
 | 
| -		j=OBJ_cmp(na->object,nb->object);
 | 
| -		if (j) return(j);
 | 
| -		}
 | 
| -	return(0);
 | 
| +	ret=(	((unsigned long)md[0]     )|((unsigned long)md[1]<<8L)|
 | 
| +		((unsigned long)md[2]<<16L)|((unsigned long)md[3]<<24L)
 | 
| +		)&0xffffffffL;
 | 
| +	return(ret);
 | 
|  	}
 | 
|  
 | 
| +
 | 
|  #ifndef OPENSSL_NO_MD5
 | 
|  /* I now DER encode the name and hash it.  Since I cache the DER encoding,
 | 
|   * this is reasonably efficient. */
 | 
| -unsigned long X509_NAME_hash(X509_NAME *x)
 | 
| +
 | 
| +unsigned long X509_NAME_hash_old(X509_NAME *x)
 | 
|  	{
 | 
|  	unsigned long ret=0;
 | 
|  	unsigned char md[16];
 | 
| -	EVP_MD_CTX md_ctx;
 | 
|  
 | 
|  	/* Make sure X509_NAME structure contains valid cached encoding */
 | 
|  	i2d_X509_NAME(x,NULL);
 | 
| -	EVP_MD_CTX_init(&md_ctx);
 | 
| -	EVP_MD_CTX_set_flags(&md_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
 | 
| -	EVP_DigestInit_ex(&md_ctx, EVP_md5(), NULL);
 | 
| -	EVP_DigestUpdate(&md_ctx, x->bytes->data, x->bytes->length);
 | 
| -	EVP_DigestFinal_ex(&md_ctx,md,NULL);
 | 
| -	EVP_MD_CTX_cleanup(&md_ctx);
 | 
| +	EVP_Digest(x->bytes->data, x->bytes->length, md, NULL, EVP_md5(), NULL);
 | 
|  
 | 
|  	ret=(	((unsigned long)md[0]     )|((unsigned long)md[1]<<8L)|
 | 
|  		((unsigned long)md[2]<<16L)|((unsigned long)md[3]<<24L)
 | 
| @@ -393,14 +300,19 @@
 | 
|  
 | 
|  int X509_check_private_key(X509 *x, EVP_PKEY *k)
 | 
|  	{
 | 
| -	EVP_PKEY *xk=NULL;
 | 
| -	int ok=0;
 | 
| +	EVP_PKEY *xk;
 | 
| +	int ret;
 | 
|  
 | 
|  	xk=X509_get_pubkey(x);
 | 
| -	switch (EVP_PKEY_cmp(xk, k))
 | 
| +
 | 
| +	if (xk)
 | 
| +		ret = EVP_PKEY_cmp(xk, k);
 | 
| +	else
 | 
| +		ret = -2;
 | 
| +
 | 
| +	switch (ret)
 | 
|  		{
 | 
|  	case 1:
 | 
| -		ok=1;
 | 
|  		break;
 | 
|  	case 0:
 | 
|  		X509err(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_KEY_VALUES_MISMATCH);
 | 
| @@ -409,24 +321,11 @@
 | 
|  		X509err(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_KEY_TYPE_MISMATCH);
 | 
|  		break;
 | 
|  	case -2:
 | 
| -#ifndef OPENSSL_NO_EC
 | 
| -		if (k->type == EVP_PKEY_EC)
 | 
| -			{
 | 
| -			X509err(X509_F_X509_CHECK_PRIVATE_KEY, ERR_R_EC_LIB);
 | 
| -			break;
 | 
| -			}
 | 
| -#endif
 | 
| -#ifndef OPENSSL_NO_DH
 | 
| -		if (k->type == EVP_PKEY_DH)
 | 
| -			{
 | 
| -			/* No idea */
 | 
| -			X509err(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_CANT_CHECK_DH_KEY);
 | 
| -			break;
 | 
| -			}
 | 
| -#endif
 | 
|  	        X509err(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_UNKNOWN_KEY_TYPE);
 | 
|  		}
 | 
| -
 | 
| -	EVP_PKEY_free(xk);
 | 
| -	return(ok);
 | 
| +	if (xk)
 | 
| +		EVP_PKEY_free(xk);
 | 
| +	if (ret > 0)
 | 
| +		return 1;
 | 
| +	return 0;
 | 
|  	}
 | 
| 
 |