diff --git a/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java b/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java index 4e5bd1313117d..cc99464dff38c 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java @@ -78,6 +78,7 @@ * * - ML-KEM * + * - HKDF-SHA256, HKDF-SHA384, and HKDF-SHA512 */ public final class SunJCE extends Provider { @@ -87,7 +88,7 @@ public final class SunJCE extends Provider { private static final String info = "SunJCE Provider " + "(implements RSA, DES, Triple DES, AES, Blowfish, ARCFOUR, RC2, PBE, " - + "Diffie-Hellman, HMAC, ChaCha20, DHKEM, and ML-KEM)"; + + "Diffie-Hellman, HMAC, ChaCha20, DHKEM, ML-KEM, and HKDF)"; /* Are we debugging? -- for developers */ static final boolean debug = false; diff --git a/src/java.base/share/classes/javax/crypto/KDF.java b/src/java.base/share/classes/javax/crypto/KDF.java index 5c9c7e71ce4a8..ec7bcfa199cb3 100644 --- a/src/java.base/share/classes/javax/crypto/KDF.java +++ b/src/java.base/share/classes/javax/crypto/KDF.java @@ -25,7 +25,6 @@ package javax.crypto; -import jdk.internal.javac.PreviewFeature; import sun.security.jca.GetInstance; import sun.security.jca.GetInstance.Instance; import sun.security.util.Debug; @@ -98,9 +97,8 @@ * * @see KDFParameters * @see SecretKey - * @since 24 + * @since 25 */ -@PreviewFeature(feature = PreviewFeature.Feature.KEY_DERIVATION) public final class KDF { private static final Debug pdebug = Debug.getInstance("provider", @@ -479,6 +477,25 @@ private static KDF handleException(NoSuchAlgorithmException e) throw e; } + // Rethrows the IAPE thrown by an implementation, adding an explanation + // for the situation in which it fails. + private void rethrow(InvalidAlgorithmParameterException e) + throws InvalidAlgorithmParameterException { + var source = serviceIterator == null + ? "specified" : "previously selected"; + if (!skipDebug && pdebug != null) { + pdebug.println("A " + this.getAlgorithm() + + " derivation cannot be performed " + + "using the supplied derivation " + + "inputs with the " + source + " " + + theOne.provider().getName() + + " provider."); + } + throw new InvalidAlgorithmParameterException( + "The " + source + " " + theOne.provider.getName() + + " provider does not support this input", e); + } + /** * Derives a key, returned as a {@code SecretKey} object. * @@ -523,7 +540,12 @@ public SecretKey deriveKey(String alg, } Objects.requireNonNull(derivationSpec); if (checkSpiNonNull(theOne)) { - return theOne.spi().engineDeriveKey(alg, derivationSpec); + try { + return theOne.spi().engineDeriveKey(alg, derivationSpec); + } catch (InvalidAlgorithmParameterException e) { + rethrow(e); + return null; // will not be called + } } else { return (SecretKey) chooseProvider(alg, derivationSpec); } @@ -554,7 +576,12 @@ public byte[] deriveData(AlgorithmParameterSpec derivationSpec) Objects.requireNonNull(derivationSpec); if (checkSpiNonNull(theOne)) { - return theOne.spi().engineDeriveData(derivationSpec); + try { + return theOne.spi().engineDeriveData(derivationSpec); + } catch (InvalidAlgorithmParameterException e) { + rethrow(e); + return null; // will not be called + } } else { try { return (byte[]) chooseProvider(null, derivationSpec); @@ -613,6 +640,11 @@ private Object chooseProvider(String algorithm, derivationSpec); // found a working KDFSpi this.theOne = currOne; + if (!skipDebug && pdebug != null) { + pdebug.println("The provider " + + currOne.provider().getName() + + " is selected"); + } return result; } catch (Exception e) { if (!skipDebug && pdebug != null) { @@ -649,7 +681,8 @@ private Object chooseProvider(String algorithm, e.printStackTrace(pdebug.getPrintStream()); } // getNext reached end without finding an implementation - throw new InvalidAlgorithmParameterException(lastException); + throw new InvalidAlgorithmParameterException( + "No provider supports this input", lastException); } } } diff --git a/src/java.base/share/classes/javax/crypto/KDFParameters.java b/src/java.base/share/classes/javax/crypto/KDFParameters.java index 5f83204f3c481..b9bd2765883d9 100644 --- a/src/java.base/share/classes/javax/crypto/KDFParameters.java +++ b/src/java.base/share/classes/javax/crypto/KDFParameters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,8 +24,6 @@ */ package javax.crypto; -import jdk.internal.javac.PreviewFeature; - /** * A specification of Key Derivation Function ({@link KDF}) parameters. *

@@ -44,7 +42,6 @@ * @see KDF#getInstance(String, KDFParameters) * @see KDF#getParameters() * @see KDF - * @since 24 + * @since 25 */ -@PreviewFeature(feature = PreviewFeature.Feature.KEY_DERIVATION) public interface KDFParameters {} diff --git a/src/java.base/share/classes/javax/crypto/KDFSpi.java b/src/java.base/share/classes/javax/crypto/KDFSpi.java index e2625a1930d64..6d0eb90b3974b 100644 --- a/src/java.base/share/classes/javax/crypto/KDFSpi.java +++ b/src/java.base/share/classes/javax/crypto/KDFSpi.java @@ -25,8 +25,6 @@ package javax.crypto; -import jdk.internal.javac.PreviewFeature; - import java.security.InvalidAlgorithmParameterException; import java.security.NoSuchAlgorithmException; import java.security.spec.AlgorithmParameterSpec; @@ -69,9 +67,8 @@ * @see KDFParameters * @see KDF#getParameters() * @see SecretKey - * @since 24 + * @since 25 */ -@PreviewFeature(feature = PreviewFeature.Feature.KEY_DERIVATION) public abstract class KDFSpi { /** diff --git a/src/java.base/share/classes/javax/crypto/spec/HKDFParameterSpec.java b/src/java.base/share/classes/javax/crypto/spec/HKDFParameterSpec.java index 8f697d12e6014..c4ca9e1e183f2 100644 --- a/src/java.base/share/classes/javax/crypto/spec/HKDFParameterSpec.java +++ b/src/java.base/share/classes/javax/crypto/spec/HKDFParameterSpec.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,6 @@ package javax.crypto.spec; -import jdk.internal.javac.PreviewFeature; - import javax.crypto.SecretKey; import java.security.spec.AlgorithmParameterSpec; import java.util.ArrayList; @@ -75,9 +73,8 @@ * @spec https://www.rfc-editor.org/info/rfc5869 * RFC 5869: HMAC-based Extract-and-Expand Key Derivation Function (HKDF) * @see javax.crypto.KDF - * @since 24 + * @since 25 */ -@PreviewFeature(feature = PreviewFeature.Feature.KEY_DERIVATION) public interface HKDFParameterSpec extends AlgorithmParameterSpec { /** @@ -92,7 +89,6 @@ public interface HKDFParameterSpec extends AlgorithmParameterSpec { * use-cases respectively. Note that the {@code Builder} is not * thread-safe. */ - @PreviewFeature(feature = PreviewFeature.Feature.KEY_DERIVATION) final class Builder { private List ikms = new ArrayList<>(); @@ -296,7 +292,6 @@ static Expand expandOnly(SecretKey prk, byte[] info, int length) { * Defines the input parameters of an Extract operation as defined in RFC 5869. */ - @PreviewFeature(feature = PreviewFeature.Feature.KEY_DERIVATION) final class Extract implements HKDFParameterSpec { // HKDF-Extract(salt, IKM) -> PRK @@ -350,7 +345,6 @@ public List salts() { * Defines the input parameters of an Expand operation as defined in RFC 5869. */ - @PreviewFeature(feature = PreviewFeature.Feature.KEY_DERIVATION) final class Expand implements HKDFParameterSpec { // HKDF-Expand(PRK, info, L) -> OKM @@ -419,7 +413,6 @@ public int length() { * Defines the input parameters of an Extract-then-Expand operation as * defined in RFC 5869. */ - @PreviewFeature(feature = PreviewFeature.Feature.KEY_DERIVATION) final class ExtractThenExpand implements HKDFParameterSpec { private final Extract ext; private final Expand exp; diff --git a/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java b/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java index 6455664b9854f..29e2ba09b34e6 100644 --- a/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java +++ b/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java @@ -77,8 +77,7 @@ public enum Feature { CLASSFILE_API, STREAM_GATHERERS, MODULE_IMPORTS, //remove when the boot JDK is JDK 25 - @JEP(number=478, title="Key Derivation Function API", status="Preview") - KEY_DERIVATION, + KEY_DERIVATION, //remove when the boot JDK is JDK 25 @JEP(number = 502, title = "Stable Values", status = "Preview") STABLE_VALUES, LANGUAGE_MODEL, diff --git a/src/java.base/share/classes/module-info.java b/src/java.base/share/classes/module-info.java index 6775dda269a38..bbcdfef65ec05 100644 --- a/src/java.base/share/classes/module-info.java +++ b/src/java.base/share/classes/module-info.java @@ -156,7 +156,6 @@ java.compiler, java.desktop, // for ScopedValue jdk.compiler, - jdk.crypto.cryptoki, // participates in preview features jdk.incubator.vector, // participates in preview features jdk.jartool, // participates in preview features jdk.jdeps, // participates in preview features diff --git a/src/jdk.crypto.cryptoki/share/classes/module-info.java b/src/jdk.crypto.cryptoki/share/classes/module-info.java index 2899bd31f2c8c..b98005648049d 100644 --- a/src/jdk.crypto.cryptoki/share/classes/module-info.java +++ b/src/jdk.crypto.cryptoki/share/classes/module-info.java @@ -23,8 +23,6 @@ * questions. */ -import jdk.internal.javac.ParticipatesInPreview; - /** * Provides the implementation of the SunPKCS11 security provider. * @@ -33,7 +31,6 @@ * @moduleGraph * @since 9 */ -@ParticipatesInPreview module jdk.crypto.cryptoki { provides java.security.Provider with sun.security.pkcs11.SunPKCS11; } diff --git a/test/jdk/com/sun/crypto/provider/KDF/HKDFBasicFunctionsTest.java b/test/jdk/com/sun/crypto/provider/KDF/HKDFBasicFunctionsTest.java index b309d1ce8df22..172d4d451ae9e 100644 --- a/test/jdk/com/sun/crypto/provider/KDF/HKDFBasicFunctionsTest.java +++ b/test/jdk/com/sun/crypto/provider/KDF/HKDFBasicFunctionsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ * @bug 8331008 * @summary basic HKDF operations * @library /test/lib - * @enablePreview */ import java.util.HexFormat; diff --git a/test/jdk/com/sun/crypto/provider/KDF/HKDFDelayedPRK.java b/test/jdk/com/sun/crypto/provider/KDF/HKDFDelayedPRK.java index 50157723416dc..f140d3c3f558e 100644 --- a/test/jdk/com/sun/crypto/provider/KDF/HKDFDelayedPRK.java +++ b/test/jdk/com/sun/crypto/provider/KDF/HKDFDelayedPRK.java @@ -27,7 +27,6 @@ * @summary make sure DPS works when non-extractable PRK is provided * @library /test/lib /test/jdk/security/unsignedjce * @build java.base/javax.crypto.ProviderVerifier - * @enablePreview * @run main/othervm HKDFDelayedPRK */ diff --git a/test/jdk/com/sun/crypto/provider/KDF/HKDFExhaustiveTest.java b/test/jdk/com/sun/crypto/provider/KDF/HKDFExhaustiveTest.java index fd33337a3c015..bf444e3cda48e 100644 --- a/test/jdk/com/sun/crypto/provider/KDF/HKDFExhaustiveTest.java +++ b/test/jdk/com/sun/crypto/provider/KDF/HKDFExhaustiveTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ * @summary KDF API tests * @library /test/lib * @run main/othervm -Djava.security.egd=file:/dev/urandom -Djava.security.debug=provider,engine=kdf HKDFExhaustiveTest - * @enablePreview */ import java.security.InvalidAlgorithmParameterException; diff --git a/test/jdk/com/sun/crypto/provider/KDF/HKDFKnownAnswerTests.java b/test/jdk/com/sun/crypto/provider/KDF/HKDFKnownAnswerTests.java index 358ffa794fd58..bb6d4febe3153 100644 --- a/test/jdk/com/sun/crypto/provider/KDF/HKDFKnownAnswerTests.java +++ b/test/jdk/com/sun/crypto/provider/KDF/HKDFKnownAnswerTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ * @bug 8331008 * @run main HKDFKnownAnswerTests * @summary Tests for HKDF Expand and Extract Key Derivation Functions - * @enablePreview */ import javax.crypto.KDF; diff --git a/test/jdk/com/sun/crypto/provider/KDF/HKDFSaltIKMTest.java b/test/jdk/com/sun/crypto/provider/KDF/HKDFSaltIKMTest.java index 1cd0feab6141c..0ae0fa23ea762 100644 --- a/test/jdk/com/sun/crypto/provider/KDF/HKDFSaltIKMTest.java +++ b/test/jdk/com/sun/crypto/provider/KDF/HKDFSaltIKMTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ * @bug 8331008 * @summary addIKM and addSalt consistency checks * @library /test/lib - * @enablePreview */ import jdk.test.lib.Asserts; @@ -89,4 +88,4 @@ public static void main(String[] args) throws Exception { } System.out.println(atlast); } -} \ No newline at end of file +} diff --git a/test/jdk/javax/crypto/KDF/KDFDelayedProviderException.java b/test/jdk/javax/crypto/KDF/KDFDelayedProviderException.java new file mode 100644 index 0000000000000..24ee820826aad --- /dev/null +++ b/test/jdk/javax/crypto/KDF/KDFDelayedProviderException.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8353888 + * @library /test/lib /test/jdk/security/unsignedjce + * @build java.base/javax.crypto.ProviderVerifier + * @run main/othervm KDFDelayedProviderException + * @summary check delayed provider selection exception messages + */ + +import jdk.test.lib.Asserts; + +import javax.crypto.KDF; +import javax.crypto.KDFParameters; +import javax.crypto.KDFSpi; +import javax.crypto.SecretKey; +import java.security.InvalidAlgorithmParameterException; +import java.security.Provider; +import java.security.Security; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.NamedParameterSpec; + +public class KDFDelayedProviderException { + public static void main(String[] args) throws Exception { + + Security.addProvider(new P1()); // only accepts NamedParameterSpec.ED25519 + Security.addProvider(new P2()); // only accepts NamedParameterSpec.ED448 + + checkMessage("No provider supports this input", + () -> KDF.getInstance("K").deriveData(NamedParameterSpec.X25519)); + + checkMessage("The specified P1 provider does not support this input", + () -> KDF.getInstance("K", "P1").deriveData(NamedParameterSpec.ED448)); + + // ED448 is supported by one provider + KDF.getInstance("K").deriveData(NamedParameterSpec.ED448); + + // After P1 has been selected, ED448 is no longer supported + var k = KDF.getInstance("K"); + k.deriveData(NamedParameterSpec.ED25519); + checkMessage("The previously selected P1 provider does not support this input", + () -> k.deriveData(NamedParameterSpec.ED448)); + + } + + public static void checkMessage(String msg, Asserts.TestMethod testMethod) { + var exc = Asserts.assertThrows(InvalidAlgorithmParameterException.class, testMethod); + Asserts.assertEquals(msg, exc.getMessage()); + } + + public static class P1 extends Provider { + public P1() { + super("P1", "1", ""); + put("KDF.K", K1.class.getName()); + } + } + + public static class P2 extends Provider { + public P2() { + super("P2", "1", ""); + put("KDF.K", K2.class.getName()); + } + } + + public static class K1 extends KDFSpi { + public K1(KDFParameters p) throws InvalidAlgorithmParameterException { + super(p); + } + protected byte[] engineDeriveData(AlgorithmParameterSpec derivationSpec) + throws InvalidAlgorithmParameterException { + if (derivationSpec != NamedParameterSpec.ED25519) { + throw new InvalidAlgorithmParameterException("Not Ed25519"); + } + return new byte[0]; + } + protected KDFParameters engineGetParameters() { + return null; + } + protected SecretKey engineDeriveKey(String alg, AlgorithmParameterSpec derivationSpec) { + return null; + } + } + + public static class K2 extends KDFSpi { + public K2(KDFParameters p) throws InvalidAlgorithmParameterException { + super(p); + } + protected byte[] engineDeriveData(AlgorithmParameterSpec derivationSpec) + throws InvalidAlgorithmParameterException { + if (derivationSpec != NamedParameterSpec.ED448) { + throw new InvalidAlgorithmParameterException("Not Ed448"); + } + return new byte[0]; + } + protected KDFParameters engineGetParameters() { + return null; + } + protected SecretKey engineDeriveKey(String alg, AlgorithmParameterSpec derivationSpec) { + return null; + } + } +} diff --git a/test/jdk/javax/crypto/KDF/KDFDelayedProviderSyncTest.java b/test/jdk/javax/crypto/KDF/KDFDelayedProviderSyncTest.java index f4ddd726d0c6a..6858894d2e933 100644 --- a/test/jdk/javax/crypto/KDF/KDFDelayedProviderSyncTest.java +++ b/test/jdk/javax/crypto/KDF/KDFDelayedProviderSyncTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ * @library /test/lib * @run testng KDFDelayedProviderSyncTest * @summary multi-threading test for KDF - * @enablePreview */ import org.testng.annotations.BeforeClass; diff --git a/test/jdk/javax/crypto/KDF/KDFDelayedProviderTest.java b/test/jdk/javax/crypto/KDF/KDFDelayedProviderTest.java index edebae217f2cf..5103a6e5df98b 100644 --- a/test/jdk/javax/crypto/KDF/KDFDelayedProviderTest.java +++ b/test/jdk/javax/crypto/KDF/KDFDelayedProviderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,6 @@ * @build java.base/javax.crypto.ProviderVerifier * @run main/othervm KDFDelayedProviderTest * @summary delayed provider selection - * @enablePreview */ import jdk.test.lib.Asserts; diff --git a/test/jdk/javax/crypto/KDF/KDFDelayedProviderThreadingTest.java b/test/jdk/javax/crypto/KDF/KDFDelayedProviderThreadingTest.java index 7b91badef95dd..8d7ad058c39fc 100644 --- a/test/jdk/javax/crypto/KDF/KDFDelayedProviderThreadingTest.java +++ b/test/jdk/javax/crypto/KDF/KDFDelayedProviderThreadingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,6 @@ * @build java.base/javax.crypto.ProviderVerifier * @run main/othervm KDFDelayedProviderThreadingTest * @summary delayed provider selection threading test - * @enablePreview */ import jdk.test.lib.Asserts; @@ -127,4 +126,4 @@ protected byte[] engineDeriveData(AlgorithmParameterSpec derivationSpec) throw new InvalidAlgorithmParameterException(); } } -} \ No newline at end of file +} diff --git a/test/jdk/sun/security/pkcs11/KDF/TestHKDF.java b/test/jdk/sun/security/pkcs11/KDF/TestHKDF.java index 638d4aa2bb1b1..aaaa8373f44d8 100644 --- a/test/jdk/sun/security/pkcs11/KDF/TestHKDF.java +++ b/test/jdk/sun/security/pkcs11/KDF/TestHKDF.java @@ -43,7 +43,6 @@ * @bug 8328119 * @summary test HKDF key derivation in SunPKCS11 * @library /test/lib .. - * @enablePreview * @run main/othervm/timeout=30 TestHKDF */