Project

General

Profile

Bug #13196

C_DeriveKey() doesn't always set object handle value

Added by Jason King 5 months ago. Updated 4 months ago.

Status:
Closed
Priority:
Normal
Assignee:
Category:
lib - userland libraries
Start date:
Due date:
% Done:

100%

Estimated time:
Difficulty:
Medium
Tags:
Gerrit CR:

Description

We had a customer report some problems with a Java app:

javax.net.ssl.SSLHandshakeException: Could not generate secret
        at java.base/sun.security.ssl.ECDHKeyExchange$ECDHEKAKeyDerivation.t12DeriveKey(ECDHKeyExchange.java:446)
        at java.base/sun.security.ssl.ECDHKeyExchange$ECDHEKAKeyDerivation.deriveKey(ECDHKeyExchange.java:418)
        at java.base/sun.security.ssl.ECDHClientKeyExchange$ECDHEClientKeyExchangeProducer.produce(ECDHClientKeyExchange.java:420)
        at java.base/sun.security.ssl.ClientKeyExchange$ClientKeyExchangeProducer.produce(ClientKeyExchange.java:65)
        at java.base/sun.security.ssl.SSLHandshake.produce(SSLHandshake.java:436)
        at java.base/sun.security.ssl.ServerHelloDone$ServerHelloDoneConsumer.consume(ServerHelloDone.java:173)
        at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392)
        at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:444)
        at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:421)
        at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:178)
        at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:164)
        at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1152)
        at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1063)
        at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:402)
        at java.base/sun.security.ssl.SSLSocketImpl.ensureNegotiated(SSLSocketImpl.java:716)
        at java.base/sun.security.ssl.SSLSocketImpl$AppOutputStream.write(SSLSocketImpl.java:970)
        at java.base/sun.security.ssl.SSLSocketImpl$AppOutputStream.write(SSLSocketImpl.java:942)
        at SSLPoke.main(SSLPoke.java:23)
Caused by: java.security.InvalidKeyException: Could not derive key
        at jdk.crypto.cryptoki/sun.security.pkcs11.P11ECDHKeyAgreement.nativeGenerateSecret(P11ECDHKeyAgreement.java:207)
        at jdk.crypto.cryptoki/sun.security.pkcs11.P11ECDHKeyAgreement.engineGenerateSecret(P11ECDHKeyAgreement.java:174)
        at java.base/javax.crypto.KeyAgreement.generateSecret(KeyAgreement.java:660)
        at java.base/sun.security.ssl.ECDHKeyExchange$ECDHEKAKeyDerivation.t12DeriveKey(ECDHKeyExchange.java:431)
        ... 17 more
Caused by: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_OBJECT_HANDLE_INVALID
        at jdk.crypto.cryptoki/sun.security.pkcs11.wrapper.PKCS11.C_GetAttributeValue(Native Method)
        at jdk.crypto.cryptoki/sun.security.pkcs11.P11ECDHKeyAgreement.nativeGenerateSecret(P11ECDHKeyAgreement.java:201)
        ... 20 more

Unfortunately, trying to dtrace pkcs11_softtoken.so.1 is challenging due to it being dlopen()ed. However using a provided test program with a modified pkcs11_softtoken.so.1 to spit out some data:

C_GetAttributeValue: sess=272512b13b014035 obj=0
javax.net.ssl.SSLHandshakeException: Could not generate secret
    at java.base/sun.security.ssl.ECDHKeyExchange$ECDHEKAKeyDerivation.t12DeriveKey(ECDHKeyExchange.java:445)

'0' is always an invalid session or object handle. Digging a bit more, the problem is that soft_derivekey() doesn't always set phKey to the created object id. Both the CKM_DH_PKCS_DERIVE and CKM_ECDH1_DERIVE mechanisms in that function skip past the 'common' label (unlike the other mechanisms). That means the *phKey = secret_key->handle; statement isn't always getting executed. The flow in this function is somewhat convoluted, we should try to mildly refactor this to fix this.


Files

java.security.test (48.7 KB) java.security.test Jason King, 2020-11-05 04:29 PM
#1

Updated by Jason King 4 months ago

There is a small java program called 'SSLPoke' that can recreate the issue. While it is claimed to be Apache licensed, the original source from Atlassan had no license, so I don't want to link or attach to it here.

#2

Updated by Andy Fiddaman 4 months ago

This simple java program should replicate it. When I compile and run this under openjdk11, I get the cannot derive key error.

import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
public class af {
   public static void main(String[] args) throws IOException{
           URLConnection conn = new URL("https://omnios.org/").openConnection();
           conn.connect();
           System.out.println("Connected");
   }
}
#3

Updated by Electric Monk 4 months ago

  • Gerrit CR set to 1009
#4

Updated by Jason King 4 months ago

To test, I used both the SSLPoke program as well as the small test program Andy provided (in this ticket). Note that with Java, the crypto provider used depends on the contents of the java.security file. To ensure the PKCS11 provider was being used for the tests, I used the attached file and ran java with -Djava.security.properties=java.security.test.

Without the fixed pkcs11_softtoken.so library, the java programs failed as described in the ticket description. With the fixed pkcs11_softtoken.so library, they both succeeded.

#5

Updated by Electric Monk 4 months ago

  • Status changed from New to Closed
  • % Done changed from 0 to 100

git commit 6cb54de2051534cc59e36ddc42abe1960e47c133

commit  6cb54de2051534cc59e36ddc42abe1960e47c133
Author: Jason King <jasonbking@users.noreply.github.com>
Date:   2020-11-06T20:45:44.000Z

    13196 C_DeriveKey() doesn't always set object handle value
    Reviewed by: C Fraire <cfraire@me.com>
    Reviewed by: Andy Fiddaman <andy@omniosce.org>
    Reviewed by: Toomas Soome <tsoome@me.com>
    Approved by: Dan McDonald <danmcd@joyent.com>

Also available in: Atom PDF