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