Open Bug 583308 Opened 9 years ago Updated 7 years ago

NSS ASN.1 encoder fails to handle EXPLICIT POINTER template

Categories

(NSS :: Libraries, defect)

3.12
defect
Not set

Tracking

(Not tracked)

People

(Reporter: nelson, Assigned: nelson)

References

(Depends on 1 open bug, Blocks 1 open bug)

Details

Attachments

(2 files, 3 obsolete files)

Whan an ASN.1 template has the attributes OPTIONAL, EXPLICIT and POINTER,
and the corresponding struct's pointer for the OPTIONAL value is NULL,
indicating that the value is to be omitted from the encoding, the encoder
crashes on an assertion failure.  

The problem is that the function sec_asn1e_init_state_based_on_template 
fails to clear the state->isExplicit bit before returning in this path.  

The attached patch should fix this crash, however, the results may or may 
not be properly encoded.  I haven't tested this.  Hanno, Please test it 
and let us know if this fixes it, and if the result is correctly encoded.
It MAY produce a result bearing the explicit tag for the omitted AlgID. :(
Attachment #461611 - Flags: review?(wtc)
Nelson, the patch does not fix the issue.

Also the problem does not appear when the struct's pointer for the OPTIONAL value is NULL. I just tried and when I have a template with a single explicid|optional value and set the struct pointer to NULL, I get a valid empty asn1 struct back (both with and without your patch).
Comment on attachment 461611 [details] [diff] [review]
Patch v1 for NSS Trunk

Nelson, thanks a lot for your help with Hannos' encoding problem.

Based on my investigation, I believe this bug is INVALID or WONTFIX.

I found that the SEC_ASN1_POINTER | SEC_ASN1_EXPLICIT combination
is the cause of the problem.  One evidence that our ASN.1 encoder
doesn't support this combination is that there are no ASN.1 templates
in NSS that use this combination.

I also found that NSS uses "PointerTo" templates to deal with an
optional field with an explicit tag.  I posted a reply in the NSS
newsgroup with more details.

Marked the patch review- based on Hanno's testing and my findings.
Attachment #461611 - Flags: review?(wtc) → review-
Attached file Hanno's test program (obsolete) —
This is Hanno's test code, turned into a real program, (has a main function)
with #includes added (it builds) and memory allocation corrected.  
It reproduces the crash.
Attached file Hanno's test program, with fix (obsolete) —
Here's Hanno's test program with two versions of the encoder templates,
one that works and one that does not.  It can be conditionally compiled to 
use either set, to reproduce the problem, or reproduce the solution.
Attachment #461824 - Attachment is obsolete: true
Wan-Teh wrote the following comments about this issue in a posting to 
mozilla.dev.tech.crypto:

I saw the problem that Hanno reported, that the ASN.1 encoder calls
SEC_ASN1GetSubTemplate one time too many.  The first
SEC_ASN1GetSubTemplate call is caused by the SEC_ASN1_OPTIONAL flag.
The second SEC_ASN1GetSubTemplate call, which causes the assertion
failure, is caused by the SEC_ASN1_EXPLICIT flag.

Using this MXR query for SEC_ASN1_POINTER, you can see that no ASN.1
templates use SEC_ASN1_POINTER with SEC_ASN1_EXPLICIT:
http://mxr.mozilla.org/security/search?string=SEC_ASN1_POINTER

So it's not surprising the ASN.1 encoder may have problems with the
SEC_ASN1_POINTER | SEC_ASN1_EXPLICIT combination.

So one solution is to not use a pointer field in the structure.  But I
understand you want the field to be a pointer because it is optional.
Then I found that NSS deals with such an "optional field with an
explicit tag" by using a "PointerTo" template.

Here is an example in mozilla/security/nss/lib/certhigh/ocsp.c:
http://mxr.mozilla.org/security/source/security/nss/lib/certhigh/ocsp.c#1188
Above, Wan-Teh wrote "The first SEC_ASN1GetSubTemplate call is caused by the 
SEC_ASN1_OPTIONAL flag."  I think he meant "by the SEC_ASN1_POINTER flag."
because in subsequent sentences, he refers to the combination of POINTER and
EXPLICIT.  

Wan-Teh, please correct that if I am mistaken.


For YEARS, I have wondered why NSS has those "PointerTo" templates.
Now Wan-Teh has figured out the answer to that mystery.
It's because the ASN.1 encoder cannot handle the combination of POINTER and
some other flag (presumably EXPLICIT) in the same template, so the early NSS developers moved POINTER its own separate child template, separate from the
other flag.  I'm guessing that all (or most) of those existing "PointerTo" templates are referenced by EXPLICIT templates somewhere.  

But I am a bit mystified about this.  POINTER and OPTIONAL logically go together.  It's the NULL/non-NULL value of the pointer that determines 
whether the OPTIONAL value will be omitted or encoded.  Putting OPTIONAL in
the parent template and POINTER in the child is certainly counter-intuitive.
Also, I'd think you'd want to evaluation the OPTIONAL decision before 
encoding the EXPLICIT construct, so again, it doesn't make sense to me that
EXPLICIT would be in the parent and POINTER in the child.  

So I'm going to experiment with some things, including:
a) have a NULL pointer in the test program, and see how it behaves. 
b) reverse the parent and child flags,  Have the parent be the optional 
pointer, and the child be the EXPICIT, and see if that works.  

In any case, I believe we should make one of two changes, either:

a) change all the ASN.1 encoders and decoders to ASSERT that no template
contains both POINTER and EXPLICIT, along with a comment explaining why, 
or else

b) change the ASN.1 encoder to make that combination work (it already works
in the decoders, I believe).

The templates should work consistently for encoders and decoders, except for
those few flags that are DOCUMENTED to be ONLY for one or only for the other.

Since POINTER and EXPLICIT flags are valid in both encoders and decoders,
then IMO combinations of them should be valid (or invalid) in BOTH encoders
and decoders alike.  I can see a FLAG being valid in one or the other and not
both, but for flags that are valid in both, I cannot see having combinations
that are valid only in one and not the other.
Summary: NSS ASN.1 encoder mishandles omitted OPTIONAL EXPLICIT POINTER → NSS ASN.1 encoder fails to handle EXPLICIT POINTER template
Nelson, I can confirm that it works in the decoders, see my pss verification patch attached to bug #158750 that uses this.

Doing your suggestion a) is probably not an option as it will break currently working code.
Attached file Hanno's test program, v3, with fix (obsolete) —
This version tests both null and non-NULL optional field pointers.

Well, I tried playing with reversing the POINTER and EXPLICIT and that fails
because EXPLICIT must go with the CONTEXT_SPECIFIC flag.  So even if seems 
unintuitive to me, I'll accept that that's how it works, POINTER templates 
are children of EXPLICIT, but OPTIONAL remains in the parent, not with the 
POINTER.  That's how it is in the ENcoder today.
Attachment #461826 - Attachment is obsolete: true
After more experimentation and code reading, I found a combination that 
enables OPTIONAL and POINTER to be used together in the parent, and 
EXPLICIT to be used in the child.  This is FAR more intuitively correct 
in my mind.  

The attached source program can be compiled in several different ways,
two of the three work.  I'd really like to fix the encoder so that all three
work, but doubt I have time to do that.
Attachment #461830 - Attachment is obsolete: true
(In reply to comment #6)
> Above, Wan-Teh wrote "The first SEC_ASN1GetSubTemplate call is caused by the 
> SEC_ASN1_OPTIONAL flag."  I think he meant "by the SEC_ASN1_POINTER flag."
> because in subsequent sentences, he refers to the combination of POINTER and
> EXPLICIT.  
> 
> Wan-Teh, please correct that if I am mistaken.

Nelson, you're right.  Sorry about the confusion caused by my typo.
Nelson, do you still want to fix this bug?
I am fine with marking this WONTFIX because I am
nervous about changing the ASN.1 encoder when the
only documentation of it is Julien's technical note
and the existing templates.
> Nelson, do you still want to fix this bug?
I'd LIKE to fix it.  I believe I could fix it.  
But in all honesty, I'm unlikely to find time for it this year.  :-(
Maybe I should start playing the lottery. :)
Target Milestone: 3.12.8 → ---
Depends on: 813046
You need to log in before you can comment on or make changes to this bug.