Hi All,
I'm the lead developer of Gmail S/MIME, and its successor, Penango,
which is bringing /end-to-end/ cross-platform S/MIME secure e-mail to
webmail and web-based messaging everywhere. It seems that this thread
has brought out its fair share or lurkers so I thought I would add some
perspective as a heavy user (and as an app developer with many end
users) of this API area.
In general we applaud the renewed attention to libpkix and its NSS entry
point, CERT_PKIXVerifyCert. We have been working with the NSS APIs for
awhile now (a few years) in order to access the full spectrum of
certificate and cryptography services, and certificate validation has
always been a sore point. Penango only uses validated certificates
(unless explicitly directed otherwise by the user), and when it
validates, it tries to do the full validation that the underlying
platform API (i.e., NSS) supports, including revocation checking.
The two APIs that are critical to NSS-oriented validation are
CERT_VerifyCertificate and CERT_PKIXVerifyCert. Obviously,
CERT_PKIXVerifyCert is the better one, as it has finer control over
validation, actually can grab caIssuers and CRLs without supplementary
code, and in general is much closer to RFC 5280 compliance. We use
CERT_PKIXVerifyCert asynchronously; it is executed on a worker thread
and returns its results using an XPCOM callback interface.
While we would like to use CERT_PKIXVerifyCert for all certificate
validation, it suffers from some problems (which are detailed below).
The most glaring problem however is that when validation fails, such as
in the case of a revoked certificate, the API returns no certificate
chains and no log information. The only output (in the revoked case) is
SEC_ERROR_REVOKED_CERTIFICATE. This is extremely unhelpful because it is
a material distinction to know that the EE cert was revoked, versus an
intermediary or root CA. Such an error also masks other possible
problems, such as whether a certificate has expired, lacks trust bits,
or other information. In contrast, CERT_VerifyCertificate returns an
empty log when successful but a CERTVerifyLog structure filled with
useful error information on a per-certificate basis when validation fails.
The net result is that we have to continue to use both
CERT_PKIXVerifyCert, and CERT_VerifyCertificate. Transitioning to
CERT_PKIXVerifyCert exclusively is definitely better but only if it can
provide all of the services (if not more) than the old API in the first
place. Otherwise, it is several steps backwards, and backwards steps for
security is definitely a bad thing.
With that being said, here is some perspective on specific suggestions
for the maintenance plan:
> * We will drop the idea of supporting non-NSS certificate
> library APIs, and we will remove the abstraction layers
> over NSS's certhigh library. That means dropping the idea
> of using libpkix in OpenSSL or in any OS kernel, for
> example. Basically, much of the pkix_pl_nss layer can be
> removed and/or folded into the core libpkix layer or into
> certhigh, if doing so would be helpful.
From our perspective, libpkix and NSS are basically the same thing, so
this is not objectionable.
>
> * We will drop support for non-blocking I/O from libpkix.
> It isn't working now, and we will remove the code that
> handles the non-blocking case as we fix bugs, to make
> the code easier to maintain.
Per above, we never used non-blocking I/O from libpkix; we use it in
blocking mode but call it on a worker thread. Non-blocking I/O never
seemed to work when we tried it, and in general we felt that doing
anything more than absolutely necessary on the main thread was a recipe
for non-deterministic behavior.
The downside to blocking mode is that the API is one-shot: it is not
possible to check on the "progress" of validation until it magically
completes. When you have CRLs that are >> 10MB, this is an issue.
However, this can be worked around (e.g., calling it twice: once for
constructing a chain without revocation checking, and another time with
revocation checking), and one-shot definitely simplifies the API for
everyone.
>
> * More generally, we will simplify the coding style to make
> it easier to read, understand, and maintain. This includes
> splitting large functions into smaller functions, removing
> unnecessary abstractions, removing simple getter/setter
> functions, potentially renaming internal (to libpkix)
> functions to make the code easier to read, removing
> non-PKCS#11 certificate stores (e.g. HTTP, LDAP), etc.
> (I think we agreed to remove LDAP support, but also agreed
> that it wasn't a high priority. This is a little unclear to
> me.)
We do not currently use HTTP or LDAP certificate stores with respect to
libpkix/the functionality that is exposed by CERT_PKIXVerifyCert. That
being said, it is conceivable that others could use this feature, and we
could use it in the future. We have definitely seen LDAP URLs in
certificates that we have to validate (for example), and although
Firefox does not ship with the Mozilla Directory (LDAP) SDK, Thunderbird
does. Therefore, we encourage the maintainers to leave it in. We can
contribute some test LDAP services if that is necessary for real-world
testing.
> We will not consider complete RFC 5280 (et. al.) support a priority.
We will basically implement a subset of RFC 5280 (et al.), with an
emphasis on features used in the existing PKITS tests, and with the
primary emphasis on making existing real websites work securely and
reliably. We will evaluate new RFC 5280 features and/or new additions to
PKITS critically and make cost/benefit and priority decisions on a
feature-by-feature basis. Do not expect significant new RFC 5280 (et.
al.) functionality to be added to libpkix any time soon, even if that
functionality is specified by some (old) RFC already, unless that
functionality already has significant usage. If there is RFC 5280 (et
al.) functionality in libpkix that goes beyond what PKITS tests, then we
may even consider removing that functionality if it causes problems
(e.g. security vulnerabilities) and a "proper" fix for that feature is
too time consuming.
Compliance with RFC 5280 is very important for our application, as it
should be for any certificate-using application on the Internet. While
we understand that 100% coverage is difficult, RFC 5280 is not that
difficult to comply with if you are starting with the premise of "I want
an API that validates certificates for Internet usage" (e.g., websites,
e-mail, and code signing). Congruence or mostly-similar behavior with
Thunderbird is also important, as it is awkward to explain to users why
Penango provides materially different validation results from Thunderbird.
From our testing, libpkix/PKIX_CERTVerifyCert is pretty close to RFC
5280 as it stands. It would be cheaper and more useful for the Internet
community if the maintainers put the 5% more effort necessary to "finish
the job", than the 95% to break compliance. If this is something that
you want to see to believe, I can try to compile some kind of a
spreadsheet that illustrates how RFC 5280 stacks up with the current
PKIX_CERTVerifyCert behavior.
>
> We did not come up with a plan on how to end-of-life the old
"classic" certificate path validation/building. It might be the case
that certhigh is implemented in a way enables us to easily make
enhancements to it to improve libpkix-based processing without breaking
the old "classic" API. I am a little skeptical that it will be easy to
make improvements to certhigh to improve libpkix without having to do
significant extra work to keep the classic API working.
As stated, we would like to move away from using CERT_VerifyCertificate,
provided that CERT_PKIXVerifyCert is strictly better.
CERT_PKIXVerifyCert has significant gaps in functionality that need to
be addressed first.
The main thing is the lack of error information when validation failures
occur. The output from CERT_VerifyCertificate is rather disorganized,
but at least it's all there.
As I indicated back in July in the thread "Validating custom extended
key usage (EKU) with NSS", the PKIX API doesn't provide a way to
validate usages of anything other than e-mail, code signing, and SSL/TLS
(with gross hacks for edge cases like OCSP responders). This is not a
limitation of libpkix, but a limitation of the NSS gloss on PKIX. If you
look inside libpkix, functions like PKIX_EkuChecker_Create indicate that
it can handle a much richer spectrum. I hope that this area of the code
is improved and exposed to apps, rather than put in the scrap heap.
Hope that helps,
Sean
Developer, Gmail S/MIME
Chief Software Architect, Penango
--
dev-tech-crypto mailing list
dev-tech-crypto@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-tech-crypto