Jdk 21 PKCS11 ECDH Key agreement failing
Daniel Jeliński
djelinski1 at gmail.com
Mon Aug 19 05:52:03 UTC 2024
Hi Pushkar,
The failure is not unexpected. In FIPS mode you are not allowed to
extract secret keys, and ka.generateSecret() does just that.
Try:
SecretKey Z = ka.generateSecret("TlsPremasterSecret");
it should work even in FIPS mode.
CKD_NULL is valid when shared data is null, and I don't see why it
would be disallowed in FIPS mode.
Regards,
Daniel
wt., 13 sie 2024 o 23:02 Pushkar Marathe
<pushkar.marathe at strongkey.com> napisał(a):
>
> Hi
>
> I have some java code written using javax.crypto package which does a derivation using ht ECDH algorithm. This code is run against a HSM card and uses key pair on the hsm. Example code below:
>
>
> Provider CRYPTOKI_PROVIDER = Security.getProvider("SunPKCS11");
> CRYPTOKI_PROVIDER = CRYPTOKI_PROVIDER.configure(PKCS11_CFG_LOCATION);
> Security.addProvider(CRYPTOKI_PROVIDER);
>
> //Generate ephemeral EC key
> KeyPairGenerator kpgen = KeyPairGenerator.getInstance("ECDH", BC_FIPS_PROVIDER);
> kpgen.initialize(new ECGenParameterSpec("secp256r1"), FIPS_DRBG);
> KeyPair keyPair = kpgen.generateKeyPair();
> ECPublicKey epubKey = (ECPublicKey) keyPair.getPublic();
> ECPrivateKey eprivKey = (ECPrivateKey) keyPair.getPrivate();
>
> PublicKey pubkey = null;
> if (keystore.containsAlias("alias")) {
> pubkey = keystore.getCertificate(mapkey).getPublicKey();
> }
>
> if (pubkey == null) {
> cryptoCommon.logp(Level.WARNING, classname, "wrapSymmetricKey", "CRYPTO-ERR-1041", mapkey);
> throw new InvalidKeyException(mapkey);
> }
>
> KeyAgreement ka = KeyAgreement.getInstance("ECDH", CRYPTOKI_PROVIDER);
> ka.init(eprivKey, CRYPTOKI_RNG);
> ka.doPhase(pubkey, true);
> byte[] Z = ka.generateSecret();
>
>
> Now when the HSM has FIPS mode turned on, the same code above starts failing at the highlighted line above. I believe this is because of the ECDH1_DERIVE_PARAMS because the default KDF used which is CKD_NULL is not allowed in FIPS mode. I couldnt find a way to change that to a FIPS approved param and make the code work.
>
> I was looking at some source code and found the code below in the file P11ECDHKeyAgreement.java (https://github.com/openjdk/jdk/blob/master/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11ECDHKeyAgreement.java):
>
> protected byte[] engineGenerateSecret() throws IllegalStateException {
> if ((privateKey == null) || (publicValue == null)) {
> throw new IllegalStateException("Not initialized correctly");
> }
> Session session = null;
> long privKeyID = privateKey.getKeyID();
> try {
> session = token.getOpSession();
> CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
> new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
> new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_GENERIC_SECRET),
> };
> CK_ECDH1_DERIVE_PARAMS ckParams =
> new CK_ECDH1_DERIVE_PARAMS(CKD_NULL, null, publicValue);
> attributes = token.getAttributes
> (O_GENERATE, CKO_SECRET_KEY, CKK_GENERIC_SECRET, attributes);
> long keyID = token.p11.C_DeriveKey(session.id(),
> new CK_MECHANISM(mechanism, ckParams), privKeyID,
> attributes);
> attributes = new CK_ATTRIBUTE[] {
> new CK_ATTRIBUTE(CKA_VALUE)
> };
> token.p11.C_GetAttributeValue(session.id(), keyID, attributes);
> byte[] secret = attributes[0].getByteArray();
> token.p11.C_DestroyObject(session.id(), keyID);
> return secret;
> } catch (PKCS11Exception e) {
> throw new ProviderException("Could not derive key", e);
> } finally {
> privateKey.releaseKeyID();
> publicValue = null;
> token.releaseSession(session);
> }
> }
>
>
> As we see here that the Params is taking CKD_NULL as the first param as highlighted below and i dont see code that lets me change that.
>
> Is there an approach i could take to make the above code work with HSM in FIPS mode and with the ability to change the params?
>
> There are some examples from the hsm provider which i was able to modify to make it work but its not using javax.crypto but their CRYPTOKI implementation. The way i made it work was to specify
>
> CK_ECDH1_DERIVE_PARAMS params
> = new CK_ECDH1_DERIVE_PARAMS(KDF.CKD_SHA224_NIST_KDF,
> "",
> ""
> );
>
> in the sample code to change the params. But i was looking for a way to do this with the java code i have.
>
>
> Thank you
> Pushkar
More information about the security-dev
mailing list