Chris Peterson wrote, On 2008-08-29 19:23 PDT:
> I'm porting a C++ app from OpenSSL/libcrypto to NSS. My app uses
> libcrypto to verify and decode a PKCS7 blob (signed by a cert issued
> my own self-signed root cert). With libcrypto, this is quite
> straightforward. With NSS, however, I'm having trouble verifying the
> PKCS7.
> 
> CERT_ImportCerts() and CERT_CheckCertUsage() return
> SEC_ERROR_EXTENSION_NOT_FOUND for my root cert, regardless of the
> SECCertUsage I specify. 

What version of NSS are you using?  If you experience this with any
version 3.11.9 or higher, then that is a bug, and if you will provide
the necessary data (certs, msgs) with which to reproduce it, I will
work on fixing it to return the proper error code.  We take this bug
very seriously.

However, note that the bug here is in the particular error message that is
being returned, not (necessarily) in the fact that an error was reported.
There is only one function that should ever return the error code you
reported (EXTENSION_NOT_FOUND), and no other CERT_ function should ever
return that error code.  But that mostly means that other functions are
returning the wrong error code, not necessarily that they are wrong for
having returned some error.  Typically they just need to be fixed to
return the right error code.

> Is NSS more strict about cert usages and extensions than libcrypto?

NSS is quite strict. I can't say if it is more strict than libcrypto
because I'm not very familiar with the cert validation parts of libcrypto.

Normally, NSS returns error codes that are quite descriptive of what
exactly is wrong with the cert chain.  I'd like to see the certs (or CMS
messages) with which the problem is reproduced, so that I can correct
that code to return the appropriately descriptive error code.

> NSS's CMS functions don't seem quite as straightforward.
> SEC_PKCS7VerifySignature() or NSS_CMSSignedData_VerifySignerInfo()
> return errors when I try to verify that my PKCS7's cert chain is
> trusted by my root cert.

Your root CA cert is marked as trusted for email in the PKCS#11 token
where it is stored, right?  If not, that is very likely the root cause
of whatever error is reported.

It is a bug if that is reported as EXTENSION_NOT_FOUND rather than as a
more relevant error code, such as (say) one of the following:
SEC_ERROR_UNTRUSTED_ISSUER
SEC_ERROR_UNTRUSTED_CERT
SEC_ERROR_UNKNOWN_ISSUER
SEC_ERROR_CA_CERT_INVALID
but if that is the cause, the code is correct in reporting an error.

See http://www.mozilla.org/projects/security/pki/nss/ref/ssl/sslerr.html
for a list of error codes and explanations.

> On the other hand, I can successfully use NSS's PKCS7 or CMS functions
> to DER-decode the PKCS7 and look at its certs. I can even manually 
> walk the cert chain and use CERT_VerifySignedData() to verify each 
> cert is signed by the next cert. I just can't figure out how to verify
> that the PKCS7's contents were signed by this cert chain.
> 
> Also, what is the scope of NSS's default cert DB, the handle returned
> by CERT_GetDefaultCertDB()? If I import certs into the default cert
> DB, would other processes (e.g. Firefox) see them? Would they remain
> in the cert db after my app exits? If I try to CERT_ImportCerts() with
> keepCerts=PR_TRUE, I get a SEC_ERROR_BAD_DATABASE error.

The questions in that paragraph have many facets, and I will attempt to
answer them all.

First, despite appearances CERT_GetDefaultCertDB doesn't return a cert DB
handle.  This function is a left-over from NSS 2.x.  In NSS 2.x, the main
NSS code had direct access to the cert DBs.  In NSS 3.x, cert DBs live only
inside of PKCS#11 modules.  NSS 3.x has a new object called a "trust
domain" that holds a set of PKCS#11 modules that hold trust information.
To preserve backward binary (and source) compatibility, the function
CERT_GetDefaultCertDB was retained in NSS 3.0, and the functions that use
the thing it returns still take one of those things.  But the value
returned by CERT_GetDefaultCertDB is now actually a handle for a trust
domain object, not a cert DB.

The scope of a trust domain is local to a process.  It is a collection of
PKCS#11 modules that collectively contain a set of trust anchors that are
trusted by the users of that trust domain.  Each process is free to have
its own trust domains.

The underlying PKCS#11 modules may be used by multiple processes, and by
multiple trust domains.  Those modules have both temporary objects and
permanent objects, which in the nomenclature of PKCS#11 are known as
"session" object and "token" objects respectively.  When you import a cert
into a PKCS#11 module, it gets imported into a logical (virtual) "token"
(think of it as a smart card), in a virtual "slot" (think of it as a smart
card reader).  That import operation can be temporary ("session") or
permanent ("token").  When you import a cert as a token object, it should
become visible to other applications that use that same token.  However, if
you're using any cert DB version older than cert9, your DB cannot be used
simultaneously by more than one application, due to limitations of the DB
software.  cert9 DBs are shareable among processes simultaneously.

SEC_ERROR_BAD_DATABASE always means one of two things;
- if you were trying to find/fetch something, it cannot be found.
- if you were trying to store something, there is already such a thing
in the DB, and your attempt to store it would overwrite that other thing.

In the highly unusual case that the DB file has been corrupted, that
will often create the result that objects in the DB can no longer be found.
That is the reason why the very common "object not found" error is named
"BAD_DATABASE".  It's not a good reason, but we live with it for
backwards source compatibility.

Hope this helps.
_______________________________________________
dev-tech-crypto mailing list
dev-tech-crypto@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-tech-crypto

Reply via email to