Topics

[tpm2] Support for EAP-TLS with openssl TPM2 engine

Andersen, John <john.s.andersen@...>
 

On Wed, Mar 13, 2019 at 04:56:17PM -0700, David Woodhouse wrote:
On Sat, 2019-01-12 at 12:59 +0100, huger@... wrote:
Hi

I am working on a plan to operate mobile Linux computers and would like
them to use corporate wifi with EAP TLS. Security requires us to safely
store the client key. Easiest solution would be in the computer's TPM
2.0 device.

So far we were not successful trying to set this up with wpa_supplicant
and pkcs11 engine. Even if successful a solution with these multiple
layers of abstraction is quite complex and therefore might be prone to
updates of any of the components.

So I wonder if there are plans to directly support openssl tpm2 engine?
Here's a quick hack to make it work by abusing the OpenSC engine
config, as a proof of concept. Making it work cleanly so that it can be
merged is left as an exercise for the reader, or perhaps an interested
party in one of the mailing lists I've added to Cc.

I have no idea why wpa_supplicant doesn't call ENGINE_load_dynamic()
for current versions of OpenSSL. That seems to be a bug, which is why
I've removed the #ifdefs around it.

Signed-off-by: David Woodhouse <dwmw2@...> (not that you'd
want to apply it as-is).

diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index 705fa29a3..546d3a598 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -864,7 +864,7 @@ static int tls_engine_load_dynamic_pkcs11(const char *pkcs11_so_path,
*/
static int tls_engine_load_dynamic_opensc(const char *opensc_so_path)
{
- char *engine_id = "opensc";
+ char *engine_id = "tpm2";
const char *pre_cmd[] = {
"SO_PATH", NULL /* opensc_so_path */,
"ID", NULL /* engine_id */,
@@ -1034,10 +1034,8 @@ void * tls_init(const struct tls_config *conf)

#ifndef OPENSSL_NO_ENGINE
wpa_printf(MSG_DEBUG, "ENGINE: Loading dynamic engine");
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
ERR_load_ENGINE_strings();
ENGINE_load_dynamic();
-#endif /* OPENSSL_VERSION_NUMBER */

if (conf &&
(conf->opensc_engine_path || conf->pkcs11_engine_path ||
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index 1bd43b226..b3045fb3d 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -174,7 +174,7 @@ fast_reauth=1
# private_key option appear to be a PKCS#11 URI, and these options
# should not need to be used explicitly.
# make the opensc engine available
-#opensc_engine_path=/usr/lib/opensc/engine_opensc.so
+opensc_engine_path=/home/dwmw/git/openssl_tpm2_engine/.libs/libtpm2.so
# make the pkcs11 engine available
#pkcs11_engine_path=/usr/lib/opensc/engine_pkcs11.so
# configure the path to the pkcs11 module required by the pkcs11 engine
_______________________________________________
tpm2 mailing list
tpm2@...
https://lists.01.org/mailman/listinfo/tpm2
Sweet! I'd been working on this too, I just got the hostapd / wpa_supplicant
test stuff working and was going to try setting
pkcs11_engine_path=/usr/lib/opensc/engine_pkcs11.so

To the tpm2-software/tpm2-pcks11 library.

From the amount of changes it took you, it seems like your approach is cleaner,
so, out of curiousity, what was your ratoinal for going with this approach? I
was going to try the pcks11 way because I came across

https://w1.fi/cgit/hostap/plain/wpa_supplicant/examples/openCryptoki.conf

But, I haven't gotten to it yet as I got sidetracked right after I got the tests
up and running.

Thanks,
John

James Bottomley
 

On Thu, 2019-03-14 at 09:19 -0700, Andersen, John wrote:
On Wed, Mar 13, 2019 at 04:56:17PM -0700, David Woodhouse wrote:
On Sat, 2019-01-12 at 12:59 +0100, huger@... wrote:
Hi

I am working on a plan to operate mobile Linux computers and
would like them to use corporate wifi with EAP TLS. Security
requires us to safely store the client key. Easiest solution
would be in the computer's TPM 2.0 device.

So far we were not successful trying to set this up with
wpa_supplicant and pkcs11 engine. Even if successful a solution
with these multiple layers of abstraction is quite complex and
therefore might be prone to updates of any of the components.

So I wonder if there are plans to directly support openssl tpm2
engine?
Here's a quick hack to make it work by abusing the OpenSC engine
config, as a proof of concept. Making it work cleanly so that it
can be merged is left as an exercise for the reader, or perhaps an
interested party in one of the mailing lists I've added to Cc.
Well, you can't have the engine name hard coded ... that really needs
to be some type of parameter, which is going to be 99% of the hassle
making a proper patch ...

I have no idea why wpa_supplicant doesn't call
ENGINE_load_dynamic() for current versions of OpenSSL. That seems
to be a bug, which is why I've removed the #ifdefs around it.

Signed-off-by: David Woodhouse <dwmw2@...> (not that
you'd want to apply it as-is).

diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index 705fa29a3..546d3a598 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -864,7 +864,7 @@ static int tls_engine_load_dynamic_pkcs11(const
char *pkcs11_so_path,
*/
static int tls_engine_load_dynamic_opensc(const char
*opensc_so_path)
{
- char *engine_id = "opensc";
+ char *engine_id = "tpm2";
const char *pre_cmd[] = {
"SO_PATH", NULL /* opensc_so_path */,
"ID", NULL /* engine_id */,
@@ -1034,10 +1034,8 @@ void * tls_init(const struct tls_config
*conf)

#ifndef OPENSSL_NO_ENGINE
wpa_printf(MSG_DEBUG, "ENGINE: Loading dynamic engine");
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
ERR_load_ENGINE_strings();
ENGINE_load_dynamic();
-#endif /* OPENSSL_VERSION_NUMBER */

if (conf &&
(conf->opensc_engine_path || conf->pkcs11_engine_path
||
diff --git a/wpa_supplicant/wpa_supplicant.conf
b/wpa_supplicant/wpa_supplicant.conf
index 1bd43b226..b3045fb3d 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -174,7 +174,7 @@ fast_reauth=1
# private_key option appear to be a PKCS#11 URI, and these options
# should not need to be used explicitly.
# make the opensc engine available
-#opensc_engine_path=/usr/lib/opensc/engine_opensc.so
+opensc_engine_path=/home/dwmw/git/openssl_tpm2_engine/.libs/libtpm
2.so
# make the pkcs11 engine available
#pkcs11_engine_path=/usr/lib/opensc/engine_pkcs11.so
# configure the path to the pkcs11 module required by the pkcs11
engine
_______________________________________________
tpm2 mailing list
tpm2@...
https://lists.01.org/mailman/listinfo/tpm2
Sweet! I'd been working on this too, I just got the hostapd /
wpa_supplicant test stuff working and was going to try setting
pkcs11_engine_path=/usr/lib/opensc/engine_pkcs11.so
Just on this particular part: I recently got annoyed with the inability
to use TPM keys on firefox. I did look at the tpm pkcs11 projects but
they all looked deficient to say the least, so I put together this

https://git.kernel.org/pub/scm/linux/kernel/git/jejb/openssl-pkcs11-export.git

It's a generic engine key to pkcs11 exporter (will work for any openssl
engine) driven by a simple ini like config file. The big advantage it
has is that now I can use openssl engines with gnutls.

To the tpm2-software/tpm2-pcks11 library.

From the amount of changes it took you, it seems like your approach
is cleaner, so, out of curiousity, what was your ratoinal for going
with this approach? I was going to try the pcks11 way because I came
across

https://w1.fi/cgit/hostap/plain/wpa_supplicant/examples/openCryptoki.
conf

But, I haven't gotten to it yet as I got sidetracked right after I
got the tests up and running.
Going the pkcs11 route is definitely the heath robinson approach, so
the direct engine route is definitely much better.

James

David Woodhouse
 

On Thu, 2019-03-14 at 09:19 -0700, Andersen, John wrote:
Sweet! I'd been working on this too, I just got the hostapd / wpa_supplicant
test stuff working and was going to try setting
pkcs11_engine_path=/usr/lib/opensc/engine_pkcs11.so

To the tpm2-software/tpm2-pcks11 library.

From the amount of changes it took you, it seems like your approach is cleaner,
so, out of curiousity, what was your ratoinal for going with this approach? I
was going to try the pcks11 way because I came across

https://w1.fi/cgit/hostap/plain/wpa_supplicant/examples/openCryptoki.conf

But, I haven't gotten to it yet as I got sidetracked right after I got the tests
up and running.
If you are using the TPMv2 PKCS#11 token (or indeed any PKCS#11 token)
and it's installed correctly, it ought to Just Work.

You should be able to just give a PKCS#11 URI in place of a filename
for any key or certificate, and any well-behaved application will do
the right thing. I believe wpa_supplicant meets that definition of
"well-behaved application", by automatically using the PKCS#11 ENGINE
when the "filename" it's given is actually a PKCS#11 URI.

(Except for the fact that all ENGINE loading is broken in
wpa_supplicant right now because the init call was removed, as noted).

James Bottomley
 

On Thu, 2019-03-14 at 09:41 -0700, David Woodhouse wrote:
On Thu, 2019-03-14 at 09:19 -0700, Andersen, John wrote:
Sweet! I'd been working on this too, I just got the hostapd /
wpa_supplicant test stuff working and was going to try setting
pkcs11_engine_path=/usr/lib/opensc/engine_pkcs11.so

To the tpm2-software/tpm2-pcks11 library.

From the amount of changes it took you, it seems like your approach
is cleaner, so, out of curiousity, what was your ratoinal for going
with this approach? I was going to try the pcks11 way because I
came across

https://w1.fi/cgit/hostap/plain/wpa_supplicant/examples/openCryptok
i.conf

But, I haven't gotten to it yet as I got sidetracked right after I
got the tests up and running.
If you are using the TPMv2 PKCS#11 token (or indeed any PKCS#11
token) and it's installed correctly, it ought to Just Work.
The big problem is which token? There are enough TPM PKCS11
implementations to fill a small warehouse. The Thomas Habets one seems
to be the best thought out:

https://github.com/ThomasHabets/simple-tpm-pk11

But it's TPM1.2. The big problem with any TPM to PKCS11 interface is
that PKCS11 expects resident keys and the TPM expects to use volatile
ones this causes massive provisioning and use pain because it's not
just drop in and go. This als seems to be the source of the broken
for some use cases problem in each of these implementations ... and
obviously when you find that an implementation is broken for your use
case you write your own ...

You should be able to just give a PKCS#11 URI in place of a filename
for any key or certificate, and any well-behaved application will do
the right thing. I believe wpa_supplicant meets that definition of
"well-behaved application", by automatically using the PKCS#11 ENGINE
when the "filename" it's given is actually a PKCS#11 URI.
As I said, my solution was a generic OpenSSL engine to PKCS11 exporter,
but it still needs a config file.

James

David Woodhouse
 

On Thu, 2019-03-14 at 09:27 -0700, James Bottomley wrote:
On Thu, 2019-03-14 at 09:19 -0700, Andersen, John wrote:
On Wed, Mar 13, 2019 at 04:56:17PM -0700, David Woodhouse wrote:
Here's a quick hack to make it work by abusing the OpenSC engine
config, as a proof of concept. Making it work cleanly so that it
can be merged is left as an exercise for the reader, or perhaps an
interested party in one of the mailing lists I've added to Cc.
Well, you can't have the engine name hard coded ... that really needs
to be some type of parameter, which is going to be 99% of the hassle
making a proper patch ...
And of course, it shouldn't have to be specified at all. If given a PEM
file which happens to look like a TPM2 engine key, then the appropriate
engine should be invoked automatically.

Just on this particular part: I recently got annoyed with the inability
to use TPM keys on firefox. I did look at the tpm pkcs11 projects but
they all looked deficient to say the least, so I put together this

https://git.kernel.org/pub/scm/linux/kernel/git/jejb/openssl-pkcs11-export.git

It's a generic engine key to pkcs11 exporter (will work for any openssl
engine) driven by a simple ini like config file. The big advantage it
has is that now I can use openssl engines with gnutls.
Nice. I like the fact that it interoperates with the key storage format
we agreed upon for the ENGINEs.

Although if you just wanted to use those keys with GnuTLS, you could
have done that directly. I already ported it all except the new
"importable" keys support.

http://git.infradead.org/users/dwmw2/openconnect.git/blob/HEAD:/gnutls_tpm2_ibm.c

Going the pkcs11 route is definitely the heath robinson approach, so
the direct engine route is definitely much better.
:)

James Bottomley
 

On Thu, 2019-03-14 at 09:57 -0700, David Woodhouse wrote:
On Thu, 2019-03-14 at 09:27 -0700, James Bottomley wrote:
On Thu, 2019-03-14 at 09:19 -0700, Andersen, John wrote:
On Wed, Mar 13, 2019 at 04:56:17PM -0700, David Woodhouse wrote:
Here's a quick hack to make it work by abusing the OpenSC
engine config, as a proof of concept. Making it work cleanly so
that it can be merged is left as an exercise for the reader, or
perhaps an interested party in one of the mailing lists I've
added to Cc.
Well, you can't have the engine name hard coded ... that really
needs to be some type of parameter, which is going to be 99% of the
hassle making a proper patch ...
And of course, it shouldn't have to be specified at all. If given a
PEM file which happens to look like a TPM2 engine key, then the
appropriate engine should be invoked automatically.
Hey don't beat me on the sore spot ...

Just on this particular part: I recently got annoyed with the
inability to use TPM keys on firefox. I did look at the tpm pkcs11
projects but they all looked deficient to say the least, so I put
together this

https://git.kernel.org/pub/scm/linux/kernel/git/jejb/openssl-pkcs11
-export.git

It's a generic engine key to pkcs11 exporter (will work for any
openssl engine) driven by a simple ini like config file. The big
advantage it has is that now I can use openssl engines with gnutls.
Nice. I like the fact that it interoperates with the key storage
format we agreed upon for the ENGINEs.
Actually, it doesn't ... that's the nice thing about the project: it's
entirely key format agnostic. It just takes the engine name and the
key file and hands it to the engine to get it to work. This means it
can work with *any* engine format whatsoever, including a completely
non-compliant TPM one should someone come up with one.

Although if you just wanted to use those keys with GnuTLS, you could
have done that directly. I already ported it all except the new
"importable" keys support.

http://git.infradead.org/users/dwmw2/openconnect.git/blob/HEAD:/gnutl
s_tpm2_ibm.c
Well, you know, using engines with gnutls does mean we don't have to
write the same code twice over ...

James


Going the pkcs11 route is definitely the heath robinson approach,
so the direct engine route is definitely much better.
:)

David Woodhouse
 

On Thu, 2019-03-14 at 10:50 -0700, James Bottomley wrote:
On Thu, 2019-03-14 at 09:57 -0700, David Woodhouse wrote:
On Thu, 2019-03-14 at 09:27 -0700, James Bottomley wrote:
On Thu, 2019-03-14 at 09:19 -0700, Andersen, John wrote:
On Wed, Mar 13, 2019 at 04:56:17PM -0700, David Woodhouse wrote:
Here's a quick hack to make it work by abusing the OpenSC
engine config, as a proof of concept. Making it work cleanly so
that it can be merged is left as an exercise for the reader, or
perhaps an interested party in one of the mailing lists I've
added to Cc.
Well, you can't have the engine name hard coded ... that really
needs to be some type of parameter, which is going to be 99% of the
hassle making a proper patch ...
And of course, it shouldn't have to be specified at all. If given a
PEM file which happens to look like a TPM2 engine key, then the
appropriate engine should be invoked automatically.
Hey don't beat me on the sore spot ...
:)

This isn't really that hard to do in applications. For those using
OpenSSL it's just a case of making them recognise the appropriate
-----BEGIN string and invoke the engine appropriately.

Once my support gets merged into GnuTLS, it really can be automatic
with the application not having to do anything at all. OpenSSL might
get there too, once we have STORE support working in applications.

Although if you just wanted to use those keys with GnuTLS, you could
have done that directly. I already ported it all except the new
"importable" keys support.

http://git.infradead.org/users/dwmw2/openconnect.git/blob/HEAD:/gnutls_tpm2_ibm.c
Well, you know, using engines with gnutls does mean we don't have to
write the same code twice over ...
I'm not convinced that an OpenSSL ENGINE is the right form for
implementing this kind of thing in the general case. PKCS#11 is much
better as an existing portable standard, although it doesn't fit the
TPMv2 usage model very well.

Even OpenSSL is moving away from ENGINEs to a different plugin
mechanism.

James Bottomley
 

On Thu, 2019-03-14 at 11:33 -0700, David Woodhouse wrote:
On Thu, 2019-03-14 at 10:50 -0700, James Bottomley wrote:
[...]
Although if you just wanted to use those keys with GnuTLS, you
could have done that directly. I already ported it all except the
new "importable" keys support.

http://git.infradead.org/users/dwmw2/openconnect.git/blob/HEAD:/g
nutls_tpm2_ibm.c
Well, you know, using engines with gnutls does mean we don't have
to write the same code twice over ...
I'm not convinced that an OpenSSL ENGINE is the right form for
implementing this kind of thing in the general case. PKCS#11 is much
better as an existing portable standard, although it doesn't fit the
TPMv2 usage model very well.
Actually, here I disagree: the faults in PKCS11 are why we have a
problem and a boat load of not quite functional solutions: it has no
key id API, so it can't take files, pkcs11: or any other URIs formats
as an argument for a key operation. OpenSSL engines can do all of that
and as evidence, the seamless construction of both a tpm engine and a
p11-kit URI based engine.

Even OpenSSL is moving away from ENGINEs to a different plugin
mechanism.
I'm not averse. My only objection is to the idea that the PKCS11 API
is better than the existing engine one; it's a more widely accepted
standard but it's not a better API. Although, Engines are by no means
perfect as and API as our whining about the engine file selector
problem shows. At least a newer plugin can finally solve the key
identification problem and I think it will fit seamlessly into my
current openssl-pkcs11-exporter.

James