Concealing keys (not even in NSS)

Rick van Rein rick at openfortress.nl
Tue Sep 20 06:01:54 EDT 2016


Hi Greg,

You're as thorough as always :)

> * Ephemeral keys (ticket session keys, initiator and acceptor subkeys)
> are generated randomly by one party and sent to the other inside an
> encrypted message. Do we extend the protocol so that these keys can be
> wrapped in parent keys within the encrypted messages, or do we decide
> that the problem only applies to long-term keys? Is it important to
> solve the problem for ticket session keys, since they can remain valid
> for hours or days?
>
Long-term keys are definately the most important; but one might argue that
any (derived) krbtgt is pretty powerful and could/should be protected.  I
suppose things get unpractical below that, and could crowd out tokens [1].
Session keys could be used, or the keys for service tickets might be
treated as they are now.

If we were thinking of PKCS #11 we would probably have to specify new
CKM_KRB5_xxx methods.  These would incorporate the key usage number as a
parameter, with a number of benefits:
 1. we can clearly see where the cut-off is going to be
 2. we could do a some sanity checking on the plaintext data
 3. we can use plain symmetric keys, possible annotated with CKA_KRB5_xxx
 4. we cannot use non-Kerberos CKM_ mechanisms and get the same results
 5. we might store a new key handle in a pointer of a method parameter

This would imply extending PKCS #11; this might not be impossible,
especially
if we started with a vendor-specific extension.  An initial implementation
in SoftHSMv2 is a way to get started with this.  Wrap a remote-PKCS #11
mechanism around that and you've got isolation between application and keys.

> * Server keys are shared between the KDC and the server keytab. How can
> these be provisioned so that both parties know them? Is it okay for
> these to pass through application memory when they are provisioned, if
> they are hidden from application memory after that?
>
One of my reasons for looking into this is to get an understanding of places
where we need ECDH for Kerberos itself :)

In terms of PKCS #11 we might also think about wrapping and unwrapping keys.
This is usually how keys are shared between replicated HSMs, for instance.

> * For traditional password-based AS-REQs, client keys are generated by
> string-to-key on the password. How can this be done without making
> either the password or the resulting key visible to kinit? (For PKINIT,
> PKCS #11 can already be used for the certificate private keys.)
>
I suppose when the initial key isn't on PKCS #11, the keys derived could
all stay outside of it?  I suppose another way around it is to generate a
key on PKCS #11 [share it through wrap/unwrap] and have all the AS handling
done inside of PKCS #11 -- which I why I was so bold to think of our own
CKM_KRB5_xxx mechanisms.

> * Should the KDC store every long-term key as a reference to a PKCS #11
> device? Should it store wrapped keys in the regular database? Is it
> sufficient for just the master key to be behind a PKCS #11 device, so
> that the existing database format can be preserved at the cost of
> letting long-term keys pass through KDC application memory? How does
> propagation of keys work across multiple KDCs within a realm? How does
> master key rollover work?
>
IMHO, I don't really care for the KDC.  It is a well-protected, trimmed-down
machine, and even beats PKCS #11 in being more aware of the application.
Storing the KDC-side keys in PKCS #11 does not seem as important to me as
on the client.

As for key propagation, my naive thinking is to use the same mechanisms as
client's KDC-REP handling?  Meaning, whenever a response is encrypted with
a PKCS #11 protected key, it would ask PKCS #11 to decrypt, annotated with
the key usage number and so retrieving whatever PKCS #11 deems proper -- be
it a key in plain sight or a reference to another key protected by PKCS #11
-- and that mechanism could also work between KDCs?

> All of those concerns are on top of the historical APIs and data formats
> (ccaches, keytabs) which assume that keys are just bit strings. Changes
> to the crypto library would comprise only a tiny part of the solution.

This is what I've been looking into, and it would be difficult indeed.  One
approach might be to introduce a special magic number of krb5_keyblock to
signal that the contents are really a reference to something like PKCS #11
(through a PKCS #11 URI) instead of the usual literal key.

I had the impression that all the hard work was done in the crypto backends,
and that they key itself was not actually handled in other places, but at
best copied.  Is that not true?  Even the credential caches appear to just
handle literal data that the _store_ and _cursor_ through?


I realise this is a big one... and I cannot really estimate how many
assumptions are twined into the code -- the design is generally very nice
and orthogonal, so I was hoping it might be doable.

FWIW, I've already had a bit of success extending PKCS #11 locally, and
got the chances embedded in SoftHSMv2, from which I hope it will spread,
http://openfortress.nl/doc/spec/pgp-in-pkcs11/
and I wouldn't mind writing up another one of those for Kerberos.


Sorry to stir up a hornet's nest ;-)

-Rick


[1] It is not uncommon for USB tokens to store only 32 kB of keys;
    it is not uncommon for high-end HSMs to be very slow doing
    C_FindObjectsXXX() on hundreds of keys.  Both could be resolved
    with off-chip storage using C_WrapKey() and C_UnwrapKey().



More information about the Kerberos mailing list