[gnutls-dev] RFC: PKCS#11 plans

Simon Josefsson simon at josefsson.org
Sun Apr 22 14:27:16 CEST 2007


Hi!  I've started experimenting with PKCS#11 support in GnuTLS, and it
seems possible to do it.  This e-mail provides a starting point for
discussions.  I'm not at all sure how to implement this, so your
thoughts and ideas are very much appreciated!

I've created a new branch gnutls_1_7_8_with_pkcs11 that will contain
these experiments.  If they are successful, they will be integrated
into the 1.7.x branch and become part of the next stable release
(which I hope to get out before or during the summer).

There are several ways to support PKCS#11 in GnuTLS, I can think of at
least three:

1) Build-time linking to a particular PKCS#11 implementation.

   Applications would likely have to call a new API, and my initial
   guess at what it would look would be:

   int gnutls_certificate_set_pkcs11 (gnutls_certificate_credentials_t res,
                                      const char *key_id);

   where KEY_ID would be an optional string denoting the Key ID of the
   key to use as the private key.  If KEY_ID is NULL, it would use any
   private key it finds.

   This is easy to use and program for, but offers limited
   flexibility.

   Refinement
   ----------

   One way to make this more flexible would be to place the API in a
   special library: libgnutls_pkcs11_foo where foo is the PKCS#11
   library it uses.  In other words, there could be:

   libgnutls_pkcs11_scute.so     uses the GnuPG 2.x PKCS#11 module
   libgnutls_pkcs11_seahorse.so  uses the GNOME SeaHorse PKCS#11 plugin
   libgnutls_pkcs11_nss.so       uses the Mozilla NSS PKCS#11 module
   ...

   Each of those libraries would be directly linked to the particular
   PKCS#11 library.  Applications, if they need PKCS#11 functionality,
   would have to link to one of these libraries.  They are mutually
   exclusive, so you can't use both seahorse and scute, which is a
   serious disadvantage.  Still, sometimes it may be sufficient.

2) Runtime linking to a application-chosen PKCS#11 implementation.

   This would likely use dlopen(), and applications would need to
   specify the path to the PKCS#11 plugin.  You'll need a new API for
   this as well, I'm thinking something like this:

   int gnutls_certificate_set_pkcs11 (gnutls_certificate_credentials_t res,
                                      const char *library,
                                      const char *key_id);

   This would dlopen() LIBRARY and search for KEY_ID, which may be
   NULL to indicate that any private key is fine.

   Applications can support more than one PKCS#11 plugin with this
   approach.  For example, it can do two calls:

     gnutls_certificate_set_pkcs11 (res, "/usr/lib/libscute.so", NULL);
     gnutls_certificate_set_pkcs11 (res, "/usr/lib/libnss.so", NULL);

   This seems like a nice approach, although it seems sub-optimal that
   applications have to provide library paths.  Applications shouldn't
   have to care about such details.

   Refinement
   ----------

   If LIBRARY is NULL, GnuTLS could use a static list of known
   PKCS#11-providers, or it could read the list from a
   /etc/gnutls-pkcs11.conf, ~/.gnutls-pkcs11.conf, GNUTLS_PKCS11
   environment variable, or similar.

3) IPC to a gnutls-daemon that is responsible for the PKCS#11 management.

   Here there is no linkage to any PKCS#11 plugin at all, which I
   consider a major advantage -- I would not want buffer-overflow
   attacks in PKCS#11 plugins to cause problems in the GnuTLS library.

   The gnutls-daemon is responsible for loading and calling the
   PKCS#11 plugins correctly.  The APIs can look the same as previous,
   in case the gnutls-daemon can dlopen() libraries.  In other words,
   the following:

   int gnutls_certificate_set_pkcs11 (gnutls_certificate_credentials_t res,
                                      const char *library,
                                      const char *key_id);

   would indicate that the certificate structure should talk to the
   gnutls-daemon, and ask it to search for KEY_ID (if non-null) in
   LIBRARY (if given), or just be happy with any private key at all.

What do you think?

/Simon



More information about the Gnutls-dev mailing list