Closed Bug 290263 Opened 15 years ago Closed 15 years ago

CERT_CreateCertificateRequest creates an invalid array of attributes

Categories

(NSS :: Libraries, defect, P2)

defect

Tracking

(Not tracked)

RESOLVED FIXED

People

(Reporter: nelson, Assigned: neil.williams)

Details

Attachments

(2 files, 2 obsolete files)

An ASN.1 encoded CERTRequest contains an array of SEQUENCES (structures)
known as attributes.  Each Attribute contains an OID and a SET OF (array of)
other ASN.1 encoded values.  

NSS's ASN.1 encoder and decoder have "templates" that describe a certificate
request, and there is a corresponding structure that contains the unencoded
form.  The encoder encodes the data in the structure using the template, 
and the decode decodes the data into the structure.  

The template used for encoding and decoding Cert request attributes requires
the data for each attribute to be contained in a struct named CERTAttribute.
That struct contains a SECItem for the attribute's OID, and a pointer to 
an array of pointers to secitems that contain the other parts of the attribute.

The encoder expects to receive an array of pointers to CERTAttribute structs.
The decoder produces as output an array of pointers to CertAttribute structs
that it has allocated.  
If the encoder is given an array of pointers to some other type, it will not
properly encode the values, and may crash.  After the decoder has produced
an array of pointers to CERTAttribute structs as output, any code that
interprets that array as pointers to some other type will get incorrect 
results and may crash.  

A SECItem cannot contain all the info needed to encode an attribute.
It lacks the pointer to the array of other secitems needed by the encoder.
SO, it has NEVER been correct to give the encoder an array of pointers to 
SECItems, and expect it to correctly encode them as attributes.  

But that is exactly what function CERT_CreateCertificateRequest does when
it is called with a non-NULL value for the last argument.  It has always
done this.  It was always wrong.  

This bug went unnoticed for YEARS.  There are two reasons for that.

a) no NSS code ever tried to pass a non-NULL value for that last argument 
to CERT_CreateCertificate request prior to NSS 3.10.  Even now 3.10 does not.
and

b) the struct CERTCertificateRequest contained an erroneous declaration 
of the attributes member.  It was erroneously declared as a SECItem **,
when it always should have been a CERTAttribute **.  

If it had been properly declared from the start, attempts to pass arrays
of pointers to the wrong types woudl have generated warnings.  But since
it was declared as SECItem **, code was written that built and assigned
arrays of the wrong type to the attribute member of the CERTCertificateRequest,
and the compiler did not warn about these errors, making the erroneous code
appear to be correct.

In NSS 3.10, ther type of the attributes member of struct CERTCertificateRequest
was finally corrected to be CERTAttribute **.  Erroneous code that actually 
used SECItem ** started to cause new warnings.  That led to the discovery
that function CERT_CreateCertificateRequest generates arrays of the wrong 
type.  

CERT_CreateCertificateRequest has been wrong for YEARS and no-one has noticed
because all users of that function pass NULL for the last argument.  On that
basis, I believe fixing this bug is probably P3, and certainly no more than P2.

Rather than trying to perfect it now on the eve of the 3.10 release, I 
propose to simply have it return an error if it is passed a non-NULL last
argument.  This will avoid calling the ASN.1 encoder with an invalid list
of pointers, and thus will avoid any potential crash.
This patch will do as a short term solution.  It simply sets an error code and
returns NULL if the last argument is non-NULL.	Wan-Teh, if you believe this
bug is worthy of P1 for 3.10, please review this patch.
Attachment #180671 - Flags: review?(wtchang)
This patch reimplements CERT_CreateCertificateRequest and redefines the
content of the SECItems that may be passed to it.  Instead of being
individual attributes already pre-encoded, it expects them now to be
cert attributeValues pre-encoded.  It combines them as the values of one
attribute, which is a cert extensions request attribute.  

Other possible alternative redefinitions of the SECItems could be 
defined.  This is one idea.  I do NOT propose to check this into 3.10.
We need more time to think about this before makign such a change, IMO.
Comment on attachment 180671 [details] [diff] [review]
patch to simply eliminate erroneous code

>+    if (!certreq) {
>+	PORT_FreeArena(arena, PR_FALSE);
>+	return NULL;
>+    }
>+    /* below here it is safe to goto loser */
> 
>-    if (certreq != NULL) {
>+    {
...
>-    } else {
>-	PORT_FreeArena(arena, PR_FALSE);
>     }
> 
>     return certreq;

This change doesn't change the logic at all.  It
makes the code easier to read, but leaves behind
an unnessary pair of curly braces.

If you really want an early return on certreq
allocation failure, please remove the pair of
curly braces and move all the code in between
to the left by one indent level.

We need a comment to explain why we fail if
attributes is not NULL.

I don't understand the code well enough to know if
we need to fix this in 3.10.  I trust your decision,
Nelson.
Attachment #180671 - Flags: review?(wtchang) → review-
QA Contact: bishakhabanerjee → jason.m.reid
Reassigning to Neil for NSS 3.11.
Assignee: nelson → neil.williams
Priority: -- → P2
Target Milestone: --- → 3.11
Patch 180675 is a reasonable solution to this problem. Since no one ever passed
and attribute list to CERT_CreateCertificateRequest before (because it didn't
work) this is more of an academic excercise in correctness. Certutil builds
CSRs with attributes but it calls CERT_StartCertificateRequestAttributes to do
the job. Note that this fix will only build CSRs of type
SEC_OID_PKCS9_EXTENSION_REQUEST.
Attachment #180675 - Attachment is obsolete: true
Attachment #198743 - Flags: review?(nelson)
Nelson, I tested your patch and it works fine. The only change I made was to
finish the comment at the head of CERT_CreateCertificateRequest.
Status: NEW → ASSIGNED
Comment on attachment 198743 [details] [diff] [review]
Nelson's patch with some comment changes

Since I wrote a large part of this patch, I don't think I should
review it.  I'm asking Bob to review it.  However,
There is one typo in the new comment that should be fixed.

>+ * single attribute of the cert request. In this implentation there is at most

s/implenta/implementa/
Attachment #198743 - Flags: review?(nelson) → review?(rrelyea)
Bob, this is the same patch that Nelson asked you for a review of. I just fixed
the mis-spelling.
Attachment #198743 - Attachment is obsolete: true
Comment on attachment 198743 [details] [diff] [review]
Nelson's patch with some comment changes

remove review request on obsolete patch
Attachment #198743 - Flags: review?(rrelyea)
Comment on attachment 199114 [details] [diff] [review]
spelling correction in the commnet

r+ because this patch does do what it is claims to do. I do have a problem with
the overall plan.

I would like to see us 'replace' this interface with one that really takes
attributes. I doubt that PKCS9_EXTENTION will be the last attribute type we
need to support.

What I would like to see is the following:

1) a new function with a signature (CERTNAME*, CERTSubjectPublickeyInfo *,
CERTAttributes **).
2) CERT_CreateCertificateRequest() is implemented by creating a
SEC_OID_PKCS9_EXTENSION_REQUEST and calling the new function.

bob
Attachment #199114 - Flags: review+
/cvsroot/mozilla/security/nss/lib/certhigh/certreq.c,v  <--  certreq.c
new revision: 1.6; previous revision: 1.5

Thanks Bob. Do you want to open a new bug addressing your recommendation? I'd
like to resolve this one.
Changing resolution because original problem has been addressed. Bob's
suggestion in his review comment can be the subject of a new bug (enhancement?).
Status: ASSIGNED → RESOLVED
Closed: 15 years ago
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.