[openssl-dev] [RFC v2 0/2] Proposal for seamless handling of TPM based RSA keys in openssl

Dr. Stephen Henson steve at openssl.org
Tue Dec 13 13:09:18 UTC 2016


On Wed, Nov 30, 2016, James Bottomley wrote:

> One of the principle problems of using TPM based keys is that there's
> no easy way of integrating them with standard file based keys.  This
> proposal adds a generic method for handling file based engine keys that
> can be loaded as PEM files.  Integration into the PEM loader requires a
> BIO based engine API callback which the first patch adds.  The second
> patch checks to see if the key can be loaded by any of the present
> engines.  Note that this requires that any engine which is to be used
> must be present and initialised via openssl.cnf.
> 
> I'll also post to this list the patch to openssl_tpm_engine that makes
> use if this infrastructure so the integration of the whole can be seen.
>  It should also be noted that gnutls has had this functionality since
> 2012.
> 
> The patch was done against 1.0.2h for easier testing and you can try it
> and the openssl_tpm_engine out (if you run openSUSE) here:
> 

I can see a couple of problems with this approach.

Firstly the BIO containing the private key may not be seekable: that is
BIO_reset() might not rewind it to the start. This could happen with a BIO
chain, a socket or a pipe for example. 

The second problem is that the file might contain multiple private keys so
(say) if you're reading the second private key in a file a reset will end up
taking you back to the beginning.

However the required functionality to support custom PEM key forms actually
largely already exists in OpenSSL so significant changes are not required if
we want to go down this route.

To see what I mean consider an existing format such as an RSA key which has
-----BEGIN RSA PRIVATE KEY----- at the start. When the PEM file is parsed in
PEM_read_bio_PrivateKey() it sees that the header ends in "PRIVATE KEY" and
then attempts to look up the key string: "RSA" in this case. It then
passes the decoded contents of the PEM file to the relavent algorithm ASN.1
method by looking for one that handles the appropriate string. Although all
current methods use ASN.1 for the private key data this shouldn't be necessary.

So for RSA this is rsa_ameth.c and the function is old_rsa_priv_decode. This
takes the encoded data and returns an EVP_PKEY structure containing the key.

So in theory if you wanted to handle a key of the form:

-----BEGIN TPM PRIVATE KEY-----
-----END TPM PRIVATE KEY----

you just create an almost empty ASN.1 method which handles the string "TPM"
and which only contains the PEM decoder. An ENGINE can also contain its own
custom methods so you could include an ENGINE which contains the relevant
handler. This would require no changes to OpenSSL to work.

There is however a snag. The relevant structure (EVP_PKEY_ASN1_METHOD) is
opaque and there is currently no way to set the pem decoder for a custom
string (the field is called "old_priv_decode"): only methods which are part of
OpenSSL can do that. The reason for that is that the PEM forms which contain
the key algorithm in the PEM header were considered legacy types and new methods
should use PKCS#8 instead. So there was no way to set legacy PEM decoders to
discourage their use.

In this case the reason is different: the header doesn't contain the algorithm
type but a string which an ENGINE can handle. So it isn't a "legacy format"
but a custom one.

So if we wanted to go down this route all that is needed to get a form of this
functionality is a function to set the PEM decoder in EVP_PKEY_ASN1_METHOD.

Steve.
--
Dr Stephen N. Henson. OpenSSL project core developer.
Commercial tech support now available see: http://www.openssl.org


More information about the openssl-dev mailing list