KDF API review, round 2
Xuelei Fan
xuelei.fan at oracle.com
Thu Nov 30 16:42:21 UTC 2017
My apologies to break in the middle of the thread. The following
attacking scenarios is a good concern to me for the API design.
On 11/20/2017 8:17 AM, Michael StJohns wrote:
> Example: a given TLS session may need 2 256 bit AES keys and 2 128 bit
> IVs. That is a requirement for 96 bytes of key stream (if I've got my
> calculation correct). We have the HSM produce this (see the PKCS11
> calling sequence for example) and we get out the IVs. An attacker who
> has access to the HSM (which may or may not be on the same machine as
> the TLS instantiation) can call the derivation function with new output
> parameters (but with the same master key and mixins) which specifies
> only IV material and have the function output the same key stream bytes
> that were previously assigned to the secret key material in the IV
> output. A very easy key extraction attack.
I would like to avoid this problem if possible. But let me start from
what we can do for the API design.
Per my understanding, the input parameters of a KDF function may include:
I-1. KDF algorithm
I-2. KDF parameters
I-3. derived key algorithm
I-4. derived key parameters
For a service provider framework, we use a service provided by the
underlying provider as:
P-1. search for the service (get the KDF function Java object)
P-2. configure the service (configure the KDF function)
P-3. use the service (derive the key)
Among P-1 to P-3, where is the appropriate place to have the input
parameters of a KDF function?
In the current JDK framework, one cannot search for a service for the
specific parameters except the service name. We may be able to twist a
little bit, but I don't think there is too much we can do actually if we
don't want to touch the provider framework too much. So, the first set
of APIs comes out to me:
KeyDerivation KeyDerivation.getInstance(
String kdfAlgorithm, // I-1
Provider kdfProvider)
and its variants.
For P-2, configure the service, we can name the API as init(),
serParameters() or configure(), or others. If we configure all of the
following input parameters here:
I-2. KDF parameters
I-3. derived key algorithm
I-4. derived key parameters
the APIs may looks like:
void configure(KDF-Params, Key-Algorithm, Key-Params) // P-2
Key deriveKey(); // P-3
From an application developer view of point, I'm uncomfortable to put a
very hard limit of the P-3 possibilities in P-2 stage. No parameters
for the deriveKey() method make me nervous because I don't actually know
what the key is actually is for the developers and code reviewers.
I would like to keep it simple that, in configuration period, configure
the KDF function only, but not configure the derived key in general.
OK, the 2nd set of APIs comes out to me (you can use init/setPara as the
method name).
void configure(KDF-Params) // I-2.
and its variants if needed.
If you agree with the above two stages, there is not much flexible for
the 3rd stage (P-3). The 3rd set of APIs may looks like:
Key deriveKey(Key-Algorithm, Key-Params) // I-3, I-4
and it variants if needed.
Back to the Michael's attacking scenarios above. It's a really good
argue. The point does not only apply to hardware implementation, it
applies to software implementation too. IVs can be public, while secret
key need to be secret. If there is a mixin, the weakness may be able
to used by delicately designed attacking scenarios.
I would like to use the existing methods above, but customize the
KDF-Params instead. In the KDF-Params spec, we can specify the
insensitive sections of the keying materials so that they can be used
for IV and other purpose other than keys, if needed. The derived key is
extractable only when the key materials is from the insensitive sections.
Xuelei
More information about the security-dev
mailing list