Journey to nowhere
Well, last time I posted the PKCS#11 module was not loading with modutil.
Looking up Evolution Data Server code to see what e_source_registry_new_sync() was up to, I found an interesting comment about a deadlock on e_source_registry_new_sync() that was occurring, the bug mentioned in the comment is a duplicate of a bug not marked as fixed.
Well, so I decided to try the asynchronous version, e_source_registry_new(), which calls a callback when done.
Changed the function flow, wrote the callback, tested. Nothing happened. I waited forever and the callback was never called back.
After spending half a week trying to find out what was deadlocking the module, I decided to test it in another machine. (Luckily I have two machines at my disposal). Settled up everything, modutil, and voila, loaded!
There is some kind of misconfig in the first machine causing the problem, which I don’t know what may be, since both run a Fedora 20 64-bit distro.
I decided put that problem aside and started coding on this new machine. But I will surely have to address this problem again, as someone else may get deadlocked too.
Edit: After all things described below were implemented I tested it again, and magically it loads in that machine too.
Onward to fetching contacts!
When asking for contacts, I only have interest in contacts which have a X509 certificate. So, I changed all queries done to Evolution to query for contacts with an E_CONTACT_X509_CERT field. There are times the PKCS#11 module will ask Evo for contacts which have a specific email address and has a certificate field, and there are times the module will require all contacts which have a certificate, regardless of email address.
The two queries look like this:
(and (exists "x509Cert") (is "email" "firstname.lastname@example.org") )
(and (exists "x509Cert") )
But every query asking for x509cert field returned nothing, as if there were no contacts with a X509 certificate. It turned out there was a little bug  in which only queries for existence of fields of type string returned correctly.
Thanks to Milan Crha it was fixed quickly, ;).
Stepping through contacts
The number of contacts returned when asking for all contacts’ certificates can be enormous. So I changed from e_book_client_get_contacts_sync(), which returns a list of contacts, to e_book_client_get_cursor_sync(), which returns a cursor that can navigate through the contacts and fetch the required number of contacts.
PKCS#11 modules can serve a number of applications, or threads, concurrently. To separate context from one application to another, there are sessions.
I elaborated a small structure to store all info needed for an application, or thread context. For now, the module only know one session, every application that opens up a session will unknowingly share it with other applications. I wanted to avoid problems with data structures and sessions while implementing the main feature.
When the work is settled, the module can be expanded to be true multi-session.
Object management does need improvements. At first I believed that the module would be stateless, go to Evolution, get certificates, return and forget them.
Objects have an object handle assigned to them by the module. It can change from one session to another, or between two instances of sessions used one after another. But PKCS#11 API defines that objects are expected to have the same handle during a session’s life time.
So, the module needs to keep track of the objects and it’s handles. Currently the module assigns a new handle to every object found.
This is not a priority and will be implemented soon.
The certificate received from Evolution is now converted and put in a CERTCertificate structure.
I tried to do it before but without success. This time I have figured out a way to convert the DER encoded certificate into the mentioned structure (no crashes or SECFailure’s).
The conversion is beneficial as many DER encodings fields become available right away, like the DER encoding of the certificate issuer or subject. It eliminated some auxiliary functions used to parse the DER certificate.
The contact’s certificate in a CERTCertificate may ease future work as well.
So, where are those certificates
As Evolution still was not capable of sending encrypted mail, guided by the logs generated by PKCS#11 Module Debugger , I started to answer other queries the module was receiving, which I was not responding to. For example NSS asks for certificates issued by a specif issuer during a search, and for some objects NSS would ask for the CKA_ID of the object, an identifier of the object used to bind corresponding certificate, public and private keys.
Issuer name search
The data received in the search template is a DER encoding of the issuer name, and the certificate returned from Evo is DER encoded. A simple comparison of the issuer name encoding was enough.
Get attribute CKA_ID
I spent a lot of time and effort on this one, and I couldn’t do it. NSS has lots of useful functions, but most of them are only available internally. They are not exported in their libraries. Or maybe I’m the one who couldn’t find them.
The only solution at sight was to parse the certificate and calculate the CKA_ID myself. But that would be too much time consuming and error prone, as the value differs by algorithm. RSA, DSA, ECDSA each one of them has a way to calculate CKA_ID.
Seeing no way to get out of the situation, and in a last effort, I started to search around randomly.
And by chance, navigating on the certificates list shown by Evolution in ‘Preferences’ menu, right clicking the certificate I found out that Evolution (or NSS) did not trust the contact’s certificate.
I marked it as trusted, and I could send a message encrypted, wohooo!
Receiving encrypted mail
You can’t see it, but this email was encrypted using a certificate retrieved from Evolution addressbook by a PKCS#11 module.
- Take a look at this trust mechanism, and check if it is possible or secure to mark it as trusted from the module.
- Refine the module
- Start working on integration with Evolution
Well, time to pack my stuff cause