Problem and errors with XML Encryption standard using ECDH and ConcatKDF key derivation function

I have a problem with implementation of the current XML encryption standard from W3C. The following is an issue and casue for interop problems within the EU eIDAS regulation cooperation where we are providing cross border authentication across EU member states.

 

We are trying to extend OpenSAML with support for ECDH and after closely examining the implementation of ConcatKDF from NIST SP 800-56A we are quite unsure how to proceed.

 

I’ll try to explain the issue briefly.

 

In the XML encryption standard example of ECDH (https://www.w3.org/TR/xmlenc-core1/#sec-ECCKeyValue) The ConcatKDF parameters are defined as AlgorithmID="00" PartyUInfo="" PartyVInfo=""

In the ConcatKDF section (https://www.w3.org/TR/xmlenc-core1/#sec-ConcatKDF) It is explained that for all parameters you MUST prepend one octet which holds the number of padding bits. 

All examples in section 5.4.1 show values using 2 bytes where byte 1 defines the number of padding bits and byte 2 provides bitstring data.

 

Problem 1: the examples of 5.6.3 and 5.4.1 are incompatible as the example in 5.6.3 do not provide a byte for expressing the number of padding bits for PartyUInfo and PartyVInfo. We also have discussions regarding whether the example of AlgorithmID is valid or not. My interpretation of a single byte with value “00” is that the bitstring is empty and has 0 padding bits.

 

Given the example in 5.6.3 the first debated question is whether the minimum number of bytes for a parameter value is 0 (as in 5.6.3), 1 (As is shown in AlgorithmID) or 2(as shown in the examples of 5.4.1)? 

Eg, is 0 byte of data (empty bitstring) supposed to be expressed as “”, “00” or “0800” (the last indicates the value is “00000000” but all 8 bits are padding)?

My interpretation of the standard is that the correct answer is “00”.

 

Further:

In the end of section 5.4.1 it is stated that:

 

these attributes shall be concatenated to form a bit string “OtherInfo” that is used with the key derivation function. The concatenation shall be done using the original, unpadded bit string values

 

So, following the example in 5.4.1 (AlgorithmID="0000" PartyUInfo="03D8" PartyVInfo="03D0") the unpadded bitstring of PartyVInfo and PartyUInfo are 5 bits each (11001 and 11010).

This means that we are expected to feed these 8+5+5 = 18 bits of data into the ConcatKDF function.

 

However, the Bouncycastle implementation of ConcatKDF (https://github.com/bcgit/bc-java/blob/master/core/src/main/java/org/bouncycastle/crypto/agreement/kdf/ConcatenationKDFGenerator.java) can only take input in the form of byte data. There is no way to feed 18 bits of “OtherInfo” into the key generation function without modifying both how ConcatKDF and how the hash functions are implemented.

 

Implementations I have seen so far of ECDH feed the concatenated raw bytes from AlgorithmID, PartyUInfo and PartyVInfo into ConcatKDF without attempting to extract the “unpadded bit string values”. This is clearly incorrect and the cause of interop problems.

 

Problem 2: How do we feed data into ConcatKDF based on data specified in the ConcatKDFParams element in order to guarantee interoperability with other implementations?

 

If we strip out the original bit string, how can we feed that into the Bouncycastle ConcatKDF function if the number of bits is not a multiple of 8?

If we strip out the unpadded bit string while the opponent feeds in the raw concatenated bytes, we will end up with incompatible keys. How can we avoid this?

 

Is there any document/errata that can sort this out?

Or is there anything in these specifications I have materially missed?

 

My personal opinion is that a mistake was made to allow parameters in bitstrings at length that can’t be divided by 8.

The correct and safe way to specify this would be to require parameters in the form of bytes, following the NIST SP 800-56A specification. 

As SP 800-56 allows upper layer applications to decide the content, restricting to byte data would not had been any problem, and whould have saved a lot of headache.

 

But I guess that is to late. But we still need to restrict implementations to specify complete bytes of data to completely avoid padding.

 

 

 

Grateful for any or help, guidance or suggestions.

 

Stefan Santesson

 

Received on Friday, 22 March 2019 14:05:49 UTC