United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-7146728 Inconsistent length for the generated secret using DH key agreement impl from SunJCE and PKCS11
JDK-7146728 : Inconsistent length for the generated secret using DH key agreement impl from SunJCE and PKCS11

Details
Type:
Bug
Submit Date:
2012-02-17
Status:
Closed
Updated Date:
2013-05-31
Project Name:
JDK
Resolved Date:
2012-09-04
Component:
security-libs
OS:
generic
Sub-Component:
javax.crypto
CPU:
generic
Priority:
P4
Resolution:
Fixed
Affected Versions:
1.0,7
Fixed Versions:

Related Reports
Backport:
Duplicate:
Relates:

Sub Tasks

Description
For certain DH parameter values, a shorter secret is generated, i.e. the leading one or two bytes have value 0x00.

Thus, the regression test "com/sun/crypto/provider/KeyAgreement/DHKeyAgreement2.java" failed intermittently when such shorter secret is generated.

A slight modification to the above test program reveals the frequency of the failures as following:

Failure reproduced at 421
Failure reproduced at 241
Failure reproduced at 433
Failure reproduced at 85
Failure reproduced at 118
Failure reproduced at 184
Failure reproduced at 1418
Failure reproduced at 170

Anyway, a ShortBufferException is thrown when the failure is reproduced.

                                    

Comments
EVALUATION

The current impl of SunJCE provider will strip off the first byte when the bit length is multiples of 8. However, the impl of SunPKCS11 provider strips off all leading 0s as it tries to match what SunJCE provider does.

According to the comment in SunJCE provider source code, the removal of 1st byte is meant to remove the "sign" byte returned by BigInteger.toByteArray() calls. However, in the same impl class, the checking of output buffer didn't take into account of the "sign" byte, thus leading to ShortBufferException as demonstrated in the com/sun/crypto/provider/KeyAgreement/DHKeyAgreement2.java regression test which allocate an output buffer based on the result returned by the KeyAgreement.generateSecret() call.

As for SunPKCS11 provider, it strips off all leading 0x00 bytes as an attempt to "follow JCE convention" when KeyAgreement.generateSecret() is called. However, in its impl of KeyAgreement.generateSecret(byte[] out, int outOfs), it again errors out if the output buffer 'out' starting offset 'outOfs' cannot hold byte arrays as long as the modulus.

This inconsistency between KeyAgreement.generateSecret() and KeyAgreement.generateSecret(byte[], int) is very confusing and should be straightened out.

The current javadoc of KeyAgreement didn't specify whether the leading 0s should be preserved or not, so it could go either way.

Given that some internet standard such as RFC2631 explicitly mentions that the leading zeros should be preserved so the generated secret occupies as many octets as p.

I think the correct fix is to change the SunJCE and SunPKCS11 provider to return a fixed size secret which is the same size as the modulus. This makes maintaining compatibility across applications easier since the generated secret length will then stay the same as the modulus size.
                                     
2012-02-17



Hardware and Software, Engineered to Work Together