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