[gnutls-dev] RFC: PKCS#11 plans
Simon Josefsson
simon at josefsson.org
Sun Apr 22 14:59:54 CEST 2007
"Alon Bar-Lev" <alon.barlev at gmail.com> writes:
> Hello,
>
> I think this is a great idea to finally support PKCS#11!
Hi! Thanks for your comments. (I'm quoting your message verbosely
since you weren't subscribed and you message never reached the
list... I've added you to the whitelist of the mailing list now.)
> But:
> 1. Never link against a specific provider.
Yeah, that's what I'm leaning towards as well, but it creates more
work...
> 2. If you wish to use a daemon, the daemon interface can be PKCS#11...
> so actually this is a separate project... To write a PKCS#11 provider
> that interacts using sockets with a daemon which loads several
> providers into its namespace. I have this in my TODO list... It can
> also provide single sign on for the user.
PKCS#11 isn't a protocol-like API, so we'd have to serialize the
requests. But that shouldn't be too difficult. I'm thinking a
protocol similar to the GnuPG 2.x daemons, a'la:
GnuTLS: PKCS11 "/usr/local/lib/libscute.so"
Daemon: END
GnuTLS: LISTCERTS
Daemon: BD:5F:80:DE:63:03:4E:C9:E2:84:1E:63:09:55:2E:34:5C:5F:22:6F
Daemon: 15:32:B4:BA:5A:8A:79:88:CA:26:42:83:59:1B:A3:A2:1C:0B:CC:24
Daemon: END
GnuTLS: LISTKEYS:
Daemon: BD:5F:80:DE:63:03:4E:C9:E2:84:1E:63:09:55:2E:34:5C:5F:22:6F
Daemon: END
GnuTLS: SIGN BD:5F:80... 237823782323...
etc
to talk with a PKCS11 provider
Or:
GnuTLS: GNUPG
Daemon: END
GnuTLS: LISTCERTS
Daemon: BD:5F:80:DE:63:03:4E:C9:E2:84:1E:63:09:55:2E:34:5C:5F:22:6F
Daemon: 15:32:B4:BA:5A:8A:79:88:CA:26:42:83:59:1B:A3:A2:1C:0B:CC:24
Daemon: END
GnuTLS: LISTKEYS:
Daemon: BD:5F:80:DE:63:03:4E:C9:E2:84:1E:63:09:55:2E:34:5C:5F:22:6F
Daemon: END
GnuTLS: SIGN BD:5F:80... 237823782323...
etc
to talk with GnuPG 2.x gpg-agent + scdaemon + gpgsm.
GnuTLS's needs are not complex, so the protocol could be simple. The
gnutls-daemon would then be responsible for loading the appropriate
PKCS#11 plugins, or other crypto providers. All complexity would be
in gnutls-daemon.
> 3. You should handle dynamic events such as token remove, token
> insert, PIN request.
I don't see what would be gained by having GnuTLS be aware of those
concepts, so I'd prefer to keep that in the gnutls-daemon, or
possibly, inside each PKCS#11 provider.
> 4. What happens if signature/decrypt is requested and the token is unavailable?
1) The TLS handshake fails.
-or-
2) GnuTLS hangs waiting for gnutls-daemon to return, and gnutls-daemon
could ask the user to insert its smartcard etc. The operation can
be canceled, and can timeout.
> 5. What is the meaning of the ID? Where the user may receive it? I
> guess I mean you need to support enumeration.
Yes. I think most crypto providers have a notion of key ids.
> Handling smartcard require significant change in concept... I've
> implemented a library that should ease the interaction, and address
> the above issues.
> http://www.opensc-project.org/pkcs11-helper
I'm looking at it now, although I'm not sure I understand whether or
how I could use it. It seems as if applications might use
pkcs11helper, but it isn't applicable to GnuTLS or gnutls-daemon.
> I believe that ignoring these will not enable GnuTLS application to
> suport hardware based crypto correctly.
>
> To begin with, I think GnuTLS should have generic crypto
> engine/provider interface. And using this interface a PKCS#11
> engine/provider should be implemented.
Yes, I also think that would be the Right Solution, although it
requires slightly more work than supporting PKCS#11 directly.
/Simon
> Best Regards,
> Alon Bar-Lev
>
> On 4/22/07, Simon Josefsson <simon at josefsson.org> wrote:
>> 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-devel
mailing list