| 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 ) {
|
|
|