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

Reply via email to