<div dir="ltr"><div>Hi Fraser,</div><div>That sounds good!  I just added the following page to document my "quick test" procedure which I use during development:</div><div><a href="https://www.dogtagpki.org/wiki/PKI_10.9_Certificate_Transparency">https://www.dogtagpki.org/wiki/PKI_10.9_Certificate_Transparency</a></div><div>btw, the verifySCT is currently enabled, but the failure is ignored.  However, you could look in the debug log for "verifySCT" to see relevant debug messages.<br></div><div><br></div><div>I'll ask Dinesh to add his more comprehensive testing procedure to the page.</div><div>thanks!!</div><div>Christina<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Jun 11, 2020 at 5:58 PM Fraser Tweedale <<a href="mailto:ftweedal@redhat.com">ftweedal@redhat.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi Christina,<br>
<br>
I will find a day next week to have a close look.  Probably Tuesday<br>
or Wednesday.  It will help to have test environment setup<br>
documentation, i.e. how to set up a log server to test with, how to<br>
configure Dogtag, etc.  If this stuff is already written then you<br>
just need to tell me where to look :)<br>
<br>
Cheers,<br>
Fraser<br>
<br>
On Thu, Jun 11, 2020 at 05:08:25PM -0700, Christina Fu wrote:<br>
> HI Fraser,<br>
> verifySCT still fails.  I still think the fact the rfc does not require the<br>
> signed object to accompany the signature presents undue challenge to the<br>
> party that needs to verify the signature.  Although I understand that this<br>
> is v1, and the issue would not be present in v2 since there will not be<br>
> poison extension ;-/.<br>
> I'd appreciate it if you could find time to take a closer look.<br>
> <br>
> Here is my latest attempt:<br>
> <a href="https://github.com/dogtagpki/pki/pull/440" rel="noreferrer" target="_blank">https://github.com/dogtagpki/pki/pull/440</a><br>
> Since it's a patch against the latest code, for a full view, it would be<br>
> easier if you just apply the patch and read from "(Certificate<br>
> Transparency)" in<br>
> base/ca/src/com/netscape/ca/CAService.java<br>
> This patch would require JSS change at:<br>
> <a href="https://github.com/dogtagpki/jss/pull/575" rel="noreferrer" target="_blank">https://github.com/dogtagpki/jss/pull/575</a><br>
> <br>
> Code still requires some refinement but I wish to address the verification<br>
> issue before cleaning things up.  Of course I still let verifySCT returns<br>
> success for now just so people could still play with CT.<br>
> Much appreciated!<br>
> Christina<br>
> <br>
> On Tue, Jun 2, 2020 at 3:05 PM Christina Fu <<a href="mailto:cfu@redhat.com" target="_blank">cfu@redhat.com</a>> wrote:<br>
> <br>
> > Hi Fraser,<br>
> > Thanks for the response!<br>
> > Regarding the poison extension, yes I was aware that it needed to be<br>
> > removed so the code already had it removed.  It was the order of things<br>
> > left inside tbsCert that I was concerned about since I used the existing<br>
> > delete method provided for the Extension class, which I wasn't sure if it'd<br>
> > preserve the order of the remaining extensions.  Thanks for confirming my<br>
> > suspicion.  I will double-check the order.<br>
> ><br>
> > Also thanks for the input on how to handle failed CT log communication<br>
> > v.s. response verification failure.   I will address them separately as<br>
> > suggested.<br>
> > Finally, nice catch with the missing data length!!  I'll add that and go<br>
> > from there.<br>
> ><br>
> > thanks again!<br>
> > Christina<br>
> ><br>
> > On Mon, Jun 1, 2020 at 7:31 PM Fraser Tweedale <<a href="mailto:ftweedal@redhat.com" target="_blank">ftweedal@redhat.com</a>><br>
> > wrote:<br>
> ><br>
> >> Hi Christina,<br>
> >><br>
> >> Adding pki-devel@ for wider audience.  Comments below.<br>
> >><br>
> >> On Mon, Jun 01, 2020 at 06:28:42PM -0700, Christina Fu wrote:<br>
> >> > Hi Fraser,<br>
> >> > Do you know how the signature returned in the SCT response could be<br>
> >> > verified by the CA?<br>
> >> > My thought is that the CA should somehow verify the CT response after<br>
> >> > sending the add-pre-chain request and before signing the cert.  Since<br>
> >> log<br>
> >> > inclusion verification would not be feasible right after the request<br>
> >> (the<br>
> >> > SCT response is supposed to be just a "promise, according to the rfc),<br>
> >> I<br>
> >> > ruled that out and intend to stay with just the following two<br>
> >> verifications<br>
> >> > on the response itself:<br>
> >> ><br>
> >> >    - checking if log id (CT log signer public key hash) returned in the<br>
> >> CT<br>
> >> >    response is correct<br>
> >> >    - this I have no problem verifying<br>
> >> >       - Verifying if the signature returned in the CT response is<br>
> >> correct<br>
> >> >       - this I can't seem to get it working.<br>
> >> ><br>
> >> > I put the verification work above in the method "verifySCT".<br>
> >> ><br>
> >> <a href="https://github.com/dogtagpki/pki/blob/master/base/ca/src/com/netscape/ca/CAService.java#L1209" rel="noreferrer" target="_blank">https://github.com/dogtagpki/pki/blob/master/base/ca/src/com/netscape/ca/CAService.java#L1209</a><br>
> >> > What I am wondering is how this can be done properly.  Since the<br>
> >> tbsCert is<br>
> >> > not to contain the poison extension, the poison extension needs to be<br>
> >> > removed by the CT server before it signs.  What if the order of the<br>
> >> > extensions contained in the tbsCert gets changed in the process?<br>
> >> ><br>
> >> The poison extension must be removed, and care must be taken to keep<br>
> >> everything else in the same order, and reserialise the parts in<br>
> >> exactly the same way.<br>
> >><br>
> >> > It seems that the response should contain the tbsCert that it signs<br>
> >> (which<br>
> >> > isn't per the rfc) or I am not sure how the CA could verify the<br>
> >> signature.<br>
> >> ><br>
> >> The response does not contain the TBCCertificate.  Both sides (log<br>
> >> and client) remove the poison extension (and change nothing else),<br>
> >> then both sides can sign the same data.<br>
> >><br>
> >> > So the question now is if I should just leave out the check, unless you<br>
> >> > have other suggestions.<br>
> >> ><br>
> >> I do think we should verify the signature, to ensure the message was<br>
> >> actually received by the log server we wanted and not an impostor.<br>
> >><br>
> >> > Of course, I also could have missed something in my code.<br>
> >> ><br>
> >> The binary format is complex and it's easy to miss something.  After<br>
> >> you implement removal of the poison extension, if it is still not<br>
> >> working I will go over the code with a fine-tooth comb.<br>
> >><br>
> >> I copied some of the code and left comments below, too.  Comments<br>
> >> begin with `!!'.  I think I found one bug and a couple of possible<br>
> >> improvements.<br>
> >><br>
> >> > One last question, currently in the code, if verifySCT fails, I just<br>
> >> > "continue" to process for next CT log.  Should this just bail out all<br>
> >> > together or it's fine to continue? Or could this be a choice by the<br>
> >> admin.<br>
> >> > What do you think and why?<br>
> >> ><br>
> >> <a href="https://github.com/dogtagpki/pki/blob/master/base/ca/src/com/netscape/ca/CAService.java#L951" rel="noreferrer" target="_blank">https://github.com/dogtagpki/pki/blob/master/base/ca/src/com/netscape/ca/CAService.java#L951</a><br>
> >> ><br>
> >> My line of thinking is this:<br>
> >><br>
> >> - we should tolerate communication errors with log (perhaps<br>
> >>   enqueuing the cert for a retry later)<br>
> >><br>
> >> - but (assuming we implement it correctly) verifySCT failure is<br>
> >>   indicative of something wrong with the log (e.g. key changed); it<br>
> >>   is not a communication error and can be treated differently.<br>
> >><br>
> >> - I think it's OK to fail hard.  Admins will likely want to know if<br>
> >>   something is wrong with CT logging.<br>
> >><br>
> >> - But in case we make a mistake, or an org needs issuance to<br>
> >>   continue despite CT log misbehaviour, there should be a config<br>
> >>   knob to allow this condition to be ignored.  "In case of<br>
> >>   emergency..."<br>
> >><br>
> >><br>
> >> ><br>
> >> > thanks,<br>
> >> > Christina<br>
> >><br>
> >>     boolean verifySCT(CTResponse response, byte[] tbsCert, String<br>
> >> logPublicKey)<br>
> >>             throws Exception {<br>
> >><br>
> >>         /* ... SNIP ... */<br>
> >><br>
> >>         byte[] extensions = new byte[] {0, 0};<br>
> >> !! although no extensions have been defined I think we should we take<br>
> >>    extensions from the CT response to future-proof this code.  i.e.<br>
> >>    decode the base64 data from the "extensions" field, and prepend the<br>
> >> length.<br>
> >><br>
> >>         // piece them together<br>
> >><br>
> >>         int data_len = version.length + signature_type.length +<br>
> >>                  timestamp.length + entry_type.length +<br>
> >>                  issuer_key_hash.length + tbsCert.length +<br>
> >> extensions.length;<br>
> >><br>
> >>         logger.debug(method + " data_len = "+ data_len);<br>
> >>         ByteArrayOutputStream ostream = new ByteArrayOutputStream();<br>
> >><br>
> >>         ostream.write(version);<br>
> >>         ostream.write(signature_type);<br>
> >>         ostream.write(timestamp);<br>
> >><br>
> >>         ostream.write(entry_type);<br>
> >>         ostream.write(issuer_key_hash);<br>
> >>         ostream.write(tbsCert);<br>
> >> !! I believe you need to prepend the length of tbsCert as a<br>
> >>    THREE-byte length field, because its definition is<br>
> >>    `opaque TBSCertificate<1..2^24-1>;'<br>
> >><br>
> >>         ostream.write(extensions);<br>
> >><br>
> >>         byte[] data = ostream.toByteArray();<br>
> >><br>
> >>         // Now, verify the signature<br>
> >>         // Note: this part currently does not work; see method comment<br>
> >> above<br>
> >><br>
> >>         // cfu ToDo: interpret the alg bytes later; hardcode for now<br>
> >>         Signature signer = Signature.getInstance("SHA256withEC",<br>
> >> "Mozilla-JSS");<br>
> >>         signer.initVerify(log_pubKey);<br>
> >>         signer.update(data);<br>
> >> !! We could call signer.update() multiple times instead of making an<br>
> >>    intermediate ByteArrayOutputStream.  I do not care about the<br>
> >>    performance, just whatever might simplify the routine.<br>
> >><br>
> >>         if (!signer.verify(signature)) {<br>
> >>             logger.error(method + "failed to verify SCT signature; pass<br>
> >> for now");<br>
> >>             // this method is not yet working;  Let this pass for now<br>
> >>             // return false;<br>
> >>         } else {<br>
> >>             logger.debug(method + "SCT signature verified successfully");<br>
> >>         }<br>
> >>         logger.debug("verifySCT ends");<br>
> >><br>
> >>         return true;<br>
> >>     }<br>
> >><br>
> >><br>
> >><br>
> >> Cheers,<br>
> >> Fraser<br>
> >><br>
> >><br>
<br>
</blockquote></div>