| Index: mozilla/security/nss/lib/pkcs7/certread.c
 | 
| ===================================================================
 | 
| --- mozilla/security/nss/lib/pkcs7/certread.c	(revision 180567)
 | 
| +++ mozilla/security/nss/lib/pkcs7/certread.c	(working copy)
 | 
| @@ -145,9 +145,6 @@
 | 
|  #define NS_CERT_HEADER_LEN  ((sizeof NS_CERT_HEADER) - 1)
 | 
|  #define NS_CERT_TRAILER_LEN ((sizeof NS_CERT_TRAILER) - 1)
 | 
|  
 | 
| -static const char CERTIFICATE_TYPE_STRING[] = "certificate";
 | 
| -#define CERTIFICATE_TYPE_LEN (sizeof(CERTIFICATE_TYPE_STRING)-1)
 | 
| -
 | 
|  /*
 | 
|   * read an old style ascii or binary certificate chain
 | 
|   */
 | 
| @@ -163,8 +160,24 @@
 | 
|      SECStatus      rv;
 | 
|      
 | 
|      if ( certbuf == NULL ) {
 | 
| +	PORT_SetError(SEC_ERROR_INVALID_ARGS);
 | 
|  	return(SECFailure);
 | 
|      }
 | 
| +    /*
 | 
| +     * Make sure certlen is long enough to handle the longest possible
 | 
| +     * reference in the code below:
 | 
| +     * 0x30 0x84 l1 l2 l3 l4  +
 | 
| +     *                       tag 9 o1 o2 o3 o4 o5 o6 o7 o8 o9
 | 
| +     *   6 + 11 = 17. 17 bytes is clearly too small to code any kind of
 | 
| +     *  certificate (a 128 bit ECC certificate contains at least an 8 byte
 | 
| +     * key and a 16 byte signature, plus coding overhead). Typically a cert
 | 
| +     * is much larger. So it's safe to require certlen to be at least 17
 | 
| +     * bytes.
 | 
| +     */
 | 
| +    if (certlen < 17) {
 | 
| +	PORT_SetError(SEC_ERROR_INPUT_LEN);
 | 
| +	return(SECFailure);
 | 
| +    }
 | 
|      
 | 
|      cp = (unsigned char *)certbuf;
 | 
|  
 | 
| @@ -194,9 +207,12 @@
 | 
|  	      case 1:
 | 
|  		seqLen = cp[1];
 | 
|  		break;
 | 
| -	      default:
 | 
| +	      case 0:
 | 
|  		/* indefinite length */
 | 
|  		seqLen = 0;
 | 
| +		break;
 | 
| +	      default:
 | 
| +		goto notder;
 | 
|  	    }
 | 
|  	    cp += ( seqLenLen + 1 );
 | 
|  
 | 
| @@ -217,26 +233,20 @@
 | 
|  	    }
 | 
|  	}
 | 
|  	
 | 
| -	/* check the type string */
 | 
| -	/* netscape wrapped DER cert */
 | 
| -	if ( ( cp[0] == SEC_ASN1_OCTET_STRING ) &&
 | 
| -	    ( cp[1] == CERTIFICATE_TYPE_LEN ) &&
 | 
| -	    ( PORT_Strcmp((char *)&cp[2], CERTIFICATE_TYPE_STRING) ) ) {
 | 
| -	    
 | 
| -	    cp += ( CERTIFICATE_TYPE_LEN + 2 );
 | 
| -
 | 
| -	    /* it had better be a certificate by now!! */
 | 
| -	    certitem.data = cp;
 | 
| -	    certitem.len = certlen - ( cp - (unsigned char *)certbuf );
 | 
| -	    
 | 
| -	    rv = (* f)(arg, &pcertitem, 1);
 | 
| -	    
 | 
| -	    return(rv);
 | 
| -	} else if ( cp[0] == SEC_ASN1_OBJECT_ID ) {
 | 
| +	/* check the type oid */
 | 
| +	if ( cp[0] == SEC_ASN1_OBJECT_ID ) {
 | 
|  	    SECOidData *oiddata;
 | 
|  	    SECItem oiditem;
 | 
|  	    /* XXX - assume DER encoding of OID len!! */
 | 
|  	    oiditem.len = cp[1];
 | 
| +	    /* if we add an oid below that is longer than 9 bytes, then we
 | 
| +	     * need to change the certlen check at the top of the function
 | 
| +	     * to prevent a buffer overflow
 | 
| +	     */
 | 
| +	    if ( oiditem.len > 9 ) {
 | 
| +		PORT_SetError(SEC_ERROR_UNRECOGNIZED_OID);
 | 
| +		return(SECFailure);
 | 
| +	    }
 | 
|  	    oiditem.data = (unsigned char *)&cp[2];
 | 
|  	    oiddata = SECOID_FindOID(&oiditem);
 | 
|  	    if ( oiddata == NULL ) {
 | 
| 
 |