On Thu, May 16, 2013 at 07:14:08AM +0000, Viktor Dukhovni wrote:
> - At any depth, dane_verify_callback() must clear any witness for most
> errors (parent-child signature errors, expiration, ...) that are found
> at an equal or lower depth. The only errors that TLSA records can
> preempt are those relating lack of a trusted root.
>
> Otherwise, you may end up calling a chain valid, for containing a CA
> that did not actually sign the next certificate, or when that
> certificate expired.
I think the larger issue is model mismatch between the new dane
callback which makes a global decision based observation of the
entire chain, and the legacy application callback it consults,
which previously only made decisions one error at a time.
Specifically, it is not reasonable to propagate errors to the
application callback that you'll later want to "retract" because
you finally found the trusted CA. With applications that provide
TLSA records via either the PULL or the SET controls, it is likely
necessary to *document* and implement a new contract with the
application verification callback.
- If none of the TLSA records are usable (unknown usage, selector
or matching type or perhaps invalid length) the dane callback
sets the verification status to a new value say:
ctx->error = X509_V_ERR_UNUSABLE_TLSA_RRS
and invokes the application callback (cert/depth TBD). The
application can decide to clear this error and revert to
normal PKIX processing, or to leave it set and consider the
chain unverified.
- Otherwise, the dane callback will only call the application
callback (at least once) when the dane callback is itself
called at depth 0.
On successful verification of the chain via trust anchor (usage 0
or 2), which means that one the following is true:
1. A TA RR was matched at some higher depth. The trust depth
(as with PKIX) is set one lower indicating the first
certificate in the chain that is issued by the TA,
provided no errors other than trust errors were found
at or below the trust depth.
2. An explicit public key whose certificate is not in the chain
signed the topmost certificate, which is not expired. The
top depth becomes the trust depth, unless errors other than
trust errors are found at any depth in the chain.
3. The depth 0 cert is a self-signed TLSA TA with acceptable
usage bits to be both a CA and an SSL server and no
errors other trust errors have yet been found at depth 0.
The certificate verification status will be set to X509_V_OK
and the application callback will be called with ok=1, depth
set to 0, and the current certificate set to the depth zero
certificate. The application callback is responsible for
performing peer name checks on the leaf certificate setting the
store error if name checks fail.
If there is an EE TLSA record with certificate usage 3, and
the only error is that the chain is not trusted, the store
error must be set by the dane callback to X509_V_ERR_CERT_UNTRUSTED,
and the application callback must be called with depth = 0
and cert equal to the depth 0 certificate. The application
callback should be able to call a new documented function to
perform EE verification of the leaf certificate.
Otherwise, the application callback will be called with the
"error certificate" (see the Postfix code) and corresponding
error state and depth. This allows the application can do
proper error reporting and decide whether to complete the
handshake.
Modifications to the above may be necessary, or some other approach
entirely may be better, but the current approach is I think
unreasonable. The application callback is blind to the DANE checks
and is being called with misleading error indications that may be
retracted, and is not called with ok=1 at depth 0 when DANE decides
that the chain is trusted after all. I don't think it is possible
to implement sensible application callbacks within the current
model.
--
Viktor.
_______________________________________________
dane mailing list
[email protected]
https://www.ietf.org/mailman/listinfo/dane