Merge "Revert "Add API tests for FileStore.""
diff --git a/EXPECTED_UPSTREAM b/EXPECTED_UPSTREAM
index 12edb11..30bfa0b 100644
--- a/EXPECTED_UPSTREAM
+++ b/EXPECTED_UPSTREAM
@@ -633,6 +633,9 @@
ojluni/src/main/java/java/security/interfaces/ECKey.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/interfaces/ECKey.java
ojluni/src/main/java/java/security/interfaces/ECPrivateKey.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/interfaces/ECPrivateKey.java
ojluni/src/main/java/java/security/interfaces/ECPublicKey.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/interfaces/ECPublicKey.java
+ojluni/src/main/java/java/security/interfaces/EdECKey.java,jdk-17.0.2-ga,src/java.base/share/classes/java/security/interfaces/EdECKey.java
+ojluni/src/main/java/java/security/interfaces/EdECPrivateKey.java,jdk-17.0.2-ga,src/java.base/share/classes/java/security/interfaces/EdECPrivateKey.java
+ojluni/src/main/java/java/security/interfaces/EdECPublicKey.java,jdk-17.0.2-ga,src/java.base/share/classes/java/security/interfaces/EdECPublicKey.java
ojluni/src/main/java/java/security/interfaces/RSAKey.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/interfaces/RSAKey.java
ojluni/src/main/java/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java
ojluni/src/main/java/java/security/interfaces/RSAPrivateCrtKey.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/interfaces/RSAPrivateCrtKey.java
@@ -652,6 +655,9 @@
ojluni/src/main/java/java/security/spec/ECPoint.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/spec/ECPoint.java
ojluni/src/main/java/java/security/spec/ECPrivateKeySpec.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/spec/ECPrivateKeySpec.java
ojluni/src/main/java/java/security/spec/ECPublicKeySpec.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/spec/ECPublicKeySpec.java
+ojluni/src/main/java/java/security/spec/EdECPoint.java,jdk-17.0.2-ga,src/java.base/share/classes/java/security/spec/EdECPoint.java
+ojluni/src/main/java/java/security/spec/EdECPrivateKeySpec.java,jdk-17.0.2-ga,src/java.base/share/classes/java/security/spec/EdECPrivateKeySpec.java
+ojluni/src/main/java/java/security/spec/EdECPublicKeySpec.java,jdk-17.0.2-ga,src/java.base/share/classes/java/security/spec/EdECPublicKeySpec.java
ojluni/src/main/java/java/security/spec/EllipticCurve.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/spec/EllipticCurve.java
ojluni/src/main/java/java/security/spec/EncodedKeySpec.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/spec/EncodedKeySpec.java
ojluni/src/main/java/java/security/spec/InvalidKeySpecException.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/spec/InvalidKeySpecException.java
diff --git a/api/current.txt b/api/current.txt
index a8c0f79..176f44a 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -8799,6 +8799,18 @@
field public static final long serialVersionUID = -3314988629879632826L; // 0xd1fecb679990cc46L
}
+ public interface EdECKey {
+ method public java.security.spec.NamedParameterSpec getParams();
+ }
+
+ public interface EdECPrivateKey extends java.security.interfaces.EdECKey java.security.PrivateKey {
+ method public java.util.Optional<byte[]> getBytes();
+ }
+
+ public interface EdECPublicKey extends java.security.interfaces.EdECKey java.security.PublicKey {
+ method public java.security.spec.EdECPoint getPoint();
+ }
+
public interface RSAKey {
method public java.math.BigInteger getModulus();
}
@@ -8927,6 +8939,24 @@
method public java.security.spec.ECPoint getW();
}
+ public final class EdECPoint {
+ ctor public EdECPoint(boolean, @NonNull java.math.BigInteger);
+ method @NonNull public java.math.BigInteger getY();
+ method public boolean isXOdd();
+ }
+
+ public final class EdECPrivateKeySpec implements java.security.spec.KeySpec {
+ ctor public EdECPrivateKeySpec(@NonNull java.security.spec.NamedParameterSpec, @NonNull byte[]);
+ method @NonNull public byte[] getBytes();
+ method @NonNull public java.security.spec.NamedParameterSpec getParams();
+ }
+
+ public final class EdECPublicKeySpec implements java.security.spec.KeySpec {
+ ctor public EdECPublicKeySpec(@NonNull java.security.spec.NamedParameterSpec, @NonNull java.security.spec.EdECPoint);
+ method @NonNull public java.security.spec.NamedParameterSpec getParams();
+ method @NonNull public java.security.spec.EdECPoint getPoint();
+ }
+
public class EllipticCurve {
ctor public EllipticCurve(java.security.spec.ECField, java.math.BigInteger, java.math.BigInteger);
ctor public EllipticCurve(java.security.spec.ECField, java.math.BigInteger, java.math.BigInteger, byte[]);
@@ -8970,6 +9000,8 @@
public class NamedParameterSpec implements java.security.spec.AlgorithmParameterSpec {
ctor public NamedParameterSpec(@NonNull String);
method @NonNull public String getName();
+ field public static final java.security.spec.NamedParameterSpec ED25519;
+ field public static final java.security.spec.NamedParameterSpec ED448;
field public static final java.security.spec.NamedParameterSpec X25519;
field public static final java.security.spec.NamedParameterSpec X448;
}
diff --git a/lint-baseline.xml b/lint-baseline.xml
index 5ff9c09..440e203 100644
--- a/lint-baseline.xml
+++ b/lint-baseline.xml
@@ -125,17 +125,6 @@
<issue
id="NewApi"
- message="Class requires API level 33 (current min is 31): `java.security.spec.NamedParameterSpec`"
- errorLine1="public class ECGenParameterSpec extends NamedParameterSpec implements AlgorithmParameterSpec {"
- errorLine2=" ~~~~~~~~~~~~~~~~~~">
- <location
- file="libcore/ojluni/src/main/java/java/security/spec/ECGenParameterSpec.java"
- line="38"
- column="41"/>
- </issue>
-
- <issue
- id="NewApi"
message="Field requires API level 33 (current min is 31): `java.net.StandardSocketOptions#SO_REUSEPORT`"
errorLine1=" } else if (name == StandardSocketOptions.SO_REUSEPORT &&"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
@@ -158,6 +147,39 @@
<issue
id="NewApi"
+ message="Class requires API level 33 (current min is 31): `java.security.spec.NamedParameterSpec`"
+ errorLine1="public class ECGenParameterSpec extends NamedParameterSpec implements AlgorithmParameterSpec {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="libcore/ojluni/src/main/java/java/security/spec/ECGenParameterSpec.java"
+ line="38"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Class requires API level 33 (current min is 31): `java.security.interfaces.EdECKey`"
+ errorLine1="public interface EdECPrivateKey extends EdECKey, PrivateKey {"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="libcore/ojluni/src/main/java/java/security/interfaces/EdECPrivateKey.java"
+ line="44"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Class requires API level 33 (current min is 31): `java.security.interfaces.EdECKey`"
+ errorLine1="public interface EdECPublicKey extends EdECKey, PublicKey {"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="libcore/ojluni/src/main/java/java/security/interfaces/EdECPublicKey.java"
+ line="42"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="NewApi"
message="Class requires API level 33 (current min is 31): `java.lang.invoke.VarHandle`"
errorLine1="class FieldVarHandle extends VarHandle {"
errorLine2=" ~~~~~~~~~">
@@ -417,17 +439,6 @@
<issue
id="NewApi"
- message="Class requires API level 32 (current min is 31): `java.security.spec.NamedParameterSpec`"
- errorLine1="public class ECGenParameterSpec extends NamedParameterSpec implements AlgorithmParameterSpec {"
- errorLine2=" ~~~~~~~~~~~~~~~~~~">
- <location
- file="libcore/ojluni/src/main/java/java/security/spec/ECGenParameterSpec.java"
- line="38"
- column="41"/>
- </issue>
-
- <issue
- id="NewApi"
message="Field requires API level 32 (current min is 31): `java.net.StandardSocketOptions#SO_REUSEPORT`"
errorLine1=" } else if (name == StandardSocketOptions.SO_REUSEPORT &&"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
@@ -450,6 +461,39 @@
<issue
id="NewApi"
+ message="Class requires API level 32 (current min is 31): `java.security.spec.NamedParameterSpec`"
+ errorLine1="public class ECGenParameterSpec extends NamedParameterSpec implements AlgorithmParameterSpec {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="libcore/ojluni/src/main/java/java/security/spec/ECGenParameterSpec.java"
+ line="38"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Class requires API level 32 (current min is 31): `java.security.interfaces.EdECKey`"
+ errorLine1="public interface EdECPrivateKey extends EdECKey, PrivateKey {"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="libcore/ojluni/src/main/java/java/security/interfaces/EdECPrivateKey.java"
+ line="44"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Class requires API level 32 (current min is 31): `java.security.interfaces.EdECKey`"
+ errorLine1="public interface EdECPublicKey extends EdECKey, PublicKey {"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="libcore/ojluni/src/main/java/java/security/interfaces/EdECPublicKey.java"
+ line="42"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="NewApi"
message="Class requires API level 32 (current min is 31): `java.lang.invoke.VarHandle`"
errorLine1="class FieldVarHandle extends VarHandle {"
errorLine2=" ~~~~~~~~~">
diff --git a/luni/src/test/java/libcore/android/system/OsTest.java b/luni/src/test/java/libcore/android/system/OsTest.java
index a52d5d6..f3dd685 100755
--- a/luni/src/test/java/libcore/android/system/OsTest.java
+++ b/luni/src/test/java/libcore/android/system/OsTest.java
@@ -1576,17 +1576,8 @@
FileDescriptor fd = Os.socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
try {
// Configure the receive timeout.
- StructTimeval tvTarget = StructTimeval.fromMillis(TIMEOUT_VALUE_MILLIS);
- Os.setsockoptTimeval(fd, SOL_SOCKET, SO_RCVTIMEO, tvTarget);
-
- // Check the system's idea of the receive timeout. Our requested timeout may
- // be rounded by the kernel (b/176104885, b/216667550).
- StructTimeval tvActual = Os.getsockoptTimeval(fd, SOL_SOCKET, SO_RCVTIMEO);
- // The kernel may round the requested value based on the HZ setting. We allow up to
- // 10ms difference.
- assertTrue(
- "Returned incorrect timeout:" + tvTarget,
- Math.abs(tvTarget.toMillis() - tvActual.toMillis()) <= ROUNDING_ERROR_MILLIS);
+ StructTimeval tv = StructTimeval.fromMillis(TIMEOUT_VALUE_MILLIS);
+ Os.setsockoptTimeval(fd, SOL_SOCKET, SO_RCVTIMEO, tv);
// Bind socket and wait for data (and timeout).
Os.bind(fd, InetAddress.getByName("::1"), 0);
@@ -1595,9 +1586,11 @@
expectException(() -> Os.read(fd, request, 0, request.length),
ErrnoException.class, EAGAIN, "Expected timeout");
long durationMillis = Duration.ofNanos(System.nanoTime() - startTime).toMillis();
- assertTrue("Timeout of " + tvActual.toMillis() + "ms returned after "
- + durationMillis +"ms",
- durationMillis >= tvActual.toMillis());
+
+ // Our requested timeout may be rounded by the kernel (b/176104885, b/216667550).
+ // We allow up to 1 scheduling quantum difference (assuming HZ = 100).
+ assertTrue("Timeout of " + tv.toMillis() + "ms returned after " + durationMillis + "ms",
+ durationMillis >= tv.toMillis() - ROUNDING_ERROR_MILLIS);
assertTrue("Timeout of " + TIMEOUT_VALUE_MILLIS + "ms failed to return within "
+ ALLOWED_TIMEOUT_MILLIS + "ms",
durationMillis < ALLOWED_TIMEOUT_MILLIS);
diff --git a/ojluni/annotations/sdk/nullability/java/security/spec/EdECPoint.annotated.java b/ojluni/annotations/sdk/nullability/java/security/spec/EdECPoint.annotated.java
new file mode 100644
index 0000000..6f38c4e
--- /dev/null
+++ b/ojluni/annotations/sdk/nullability/java/security/spec/EdECPoint.annotated.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2020, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package java.security.spec;
+
+import java.math.BigInteger;
+import java.util.Objects;
+
+@SuppressWarnings({"unchecked", "deprecation", "all"})
+public final class EdECPoint {
+
+ public EdECPoint(boolean xOdd, @libcore.util.NonNull BigInteger y) { throw new RuntimeException("Stub!"); }
+ public boolean isXOdd(){ throw new RuntimeException("Stub!"); }
+ public @libcore.util.NonNull BigInteger getY(){ throw new RuntimeException("Stub!"); }
+}
diff --git a/ojluni/annotations/sdk/nullability/java/security/spec/EdECPrivateKeySpec.annotated.java b/ojluni/annotations/sdk/nullability/java/security/spec/EdECPrivateKeySpec.annotated.java
new file mode 100644
index 0000000..2dbeefb
--- /dev/null
+++ b/ojluni/annotations/sdk/nullability/java/security/spec/EdECPrivateKeySpec.annotated.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2020, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package java.security.spec;
+
+import java.util.Objects;
+
+public final class EdECPrivateKeySpec implements KeySpec {
+ public EdECPrivateKeySpec(@libcore.util.NonNull NamedParameterSpec params, @libcore.util.NonNull byte[] bytes) { throw new RuntimeException("Stub!"); }
+ public @libcore.util.NonNull NamedParameterSpec getParams(){ throw new RuntimeException("Stub!"); }
+ public @libcore.util.NonNull byte[] getBytes() { throw new RuntimeException("Stub!"); }
+}
diff --git a/ojluni/annotations/sdk/nullability/java/security/spec/EdECPublicKeySpec.annotated.java b/ojluni/annotations/sdk/nullability/java/security/spec/EdECPublicKeySpec.annotated.java
new file mode 100644
index 0000000..0f6401b
--- /dev/null
+++ b/ojluni/annotations/sdk/nullability/java/security/spec/EdECPublicKeySpec.annotated.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2020, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package java.security.spec;
+
+import java.util.Objects;
+
+public final class EdECPublicKeySpec implements KeySpec {
+ public EdECPublicKeySpec(@libcore.util.NonNull NamedParameterSpec params, @libcore.util.NonNull EdECPoint point) { throw new RuntimeException("Stub!"); }
+ public @libcore.util.NonNull NamedParameterSpec getParams() { throw new RuntimeException("Stub!"); }
+ public @libcore.util.NonNull EdECPoint getPoint() { throw new RuntimeException("Stub!"); }
+}
diff --git a/ojluni/src/main/java/java/lang/invoke/Transformers.java b/ojluni/src/main/java/java/lang/invoke/Transformers.java
index dd59727..168110e 100644
--- a/ojluni/src/main/java/java/lang/invoke/Transformers.java
+++ b/ojluni/src/main/java/java/lang/invoke/Transformers.java
@@ -1292,7 +1292,10 @@
// Get the array reference and check that its length is as expected.
final Class<?> arrayType = type().parameterType(arrayOffset);
final Object arrayObj = callerFrame.getReference(arrayOffset, arrayType);
- final int arrayLength = Array.getLength(arrayObj);
+
+ // The incoming array may be null if the expected number of array arguments is zero.
+ final int arrayLength =
+ (numArrayArgs == 0 && arrayObj == null) ? 0 : Array.getLength(arrayObj);
if (arrayLength != numArrayArgs) {
throw new IllegalArgumentException(
"Invalid array length " + arrayLength + " expected " + numArrayArgs);
@@ -1313,11 +1316,20 @@
leadingRange.numReferences + numArrayArgs, leadingRange.numBytes);
}
- // Attach the writer, prepare to spread the trailing array arguments into
- // the callee frame.
- StackFrameWriter writer = new StackFrameWriter();
- writer.attach(targetFrame, arrayOffset, leadingRange.numReferences, leadingRange.numBytes);
+ if (arrayLength != 0) {
+ StackFrameWriter writer = new StackFrameWriter();
+ writer.attach(targetFrame,
+ arrayOffset,
+ leadingRange.numReferences,
+ leadingRange.numBytes);
+ spreadArray(arrayType, arrayObj, writer);
+ }
+ invokeExactFromTransform(target, targetFrame);
+ targetFrame.copyReturnValueTo(callerFrame);
+ }
+
+ private void spreadArray(Class<?> arrayType, Object arrayObj, StackFrameWriter writer) {
final Class<?> componentType = arrayType.getComponentType();
switch (Wrapper.basicTypeChar(componentType)) {
case 'L':
@@ -1393,9 +1405,6 @@
break;
}
}
-
- invokeExactFromTransform(target, targetFrame);
- targetFrame.copyReturnValueTo(callerFrame);
}
}
diff --git a/ojluni/src/main/java/java/security/interfaces/EdECKey.java b/ojluni/src/main/java/java/security/interfaces/EdECKey.java
new file mode 100644
index 0000000..bec29ee
--- /dev/null
+++ b/ojluni/src/main/java/java/security/interfaces/EdECKey.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2020, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package java.security.interfaces;
+
+import java.security.spec.NamedParameterSpec;
+
+/**
+ * An interface for an elliptic curve public/private key as defined by
+ * <a href="https://tools.ietf.org/html/rfc8032">RFC 8032: Edwards-Curve
+ * Digital Signature Algorithm (EdDSA)</a>. These keys are distinct from the
+ * keys represented by {@code ECKey}, and they are intended for use with
+ * algorithms based on RFC 8032 such as the EdDSA {@code Signature} algorithm.
+ * This interface allows access to the algorithm parameters associated with
+ * the key.
+ *
+ * @since 15
+ */
+public interface EdECKey {
+ /**
+ * Returns the algorithm parameters associated with the key.
+ *
+ * @return the associated algorithm parameters.
+ */
+ NamedParameterSpec getParams();
+}
diff --git a/ojluni/src/main/java/java/security/interfaces/EdECPrivateKey.java b/ojluni/src/main/java/java/security/interfaces/EdECPrivateKey.java
new file mode 100644
index 0000000..826b526
--- /dev/null
+++ b/ojluni/src/main/java/java/security/interfaces/EdECPrivateKey.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2020, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package java.security.interfaces;
+
+import java.security.PrivateKey;
+import java.util.Optional;
+
+/**
+ * An interface for an elliptic curve private key as defined by
+ * <a href="https://tools.ietf.org/html/rfc8032">RFC 8032: Edwards-Curve
+ * Digital Signature Algorithm (EdDSA)</a>. These keys are distinct from the
+ * keys represented by {@code ECPrivateKey}, and they are intended for use
+ * with algorithms based on RFC 8032 such as the EdDSA {@code Signature}
+ * algorithm.
+ * <p>
+ * An Edwards-Curve private key is a bit string. This interface only supports bit
+ * string lengths that are a multiple of 8, and the key is represented using
+ * a byte array.
+ *
+ * @since 15
+ */
+public interface EdECPrivateKey extends EdECKey, PrivateKey {
+
+ /**
+ * Get a copy of the byte array representing the private key. This method
+ * may return an empty {@code Optional} if the implementation is not
+ * willing to produce the private key value.
+ *
+ * @return an {@code Optional} containing the private key byte array.
+ * If the key is not available, then an empty {@code Optional}.
+ */
+ Optional<byte[]> getBytes();
+}
diff --git a/ojluni/src/main/java/java/security/interfaces/EdECPublicKey.java b/ojluni/src/main/java/java/security/interfaces/EdECPublicKey.java
new file mode 100644
index 0000000..d2e2641
--- /dev/null
+++ b/ojluni/src/main/java/java/security/interfaces/EdECPublicKey.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2020, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package java.security.interfaces;
+
+import java.security.PublicKey;
+import java.security.spec.EdECPoint;
+
+/**
+ * An interface for an elliptic curve public key as defined by
+ * <a href="https://tools.ietf.org/html/rfc8032">RFC 8032: Edwards-Curve
+ * Digital Signature Algorithm (EdDSA)</a>. These keys are distinct from the
+ * keys represented by {@code ECPublicKey}, and they are intended for use with
+ * algorithms based on RFC 8032 such as the EdDSA {@code Signature} algorithm.
+ * <p>
+ * An Edwards-Curve public key is a point on the curve, which is represented using an
+ * EdECPoint.
+ *
+ * @since 15
+ */
+public interface EdECPublicKey extends EdECKey, PublicKey {
+
+ /**
+ * Get the point representing the public key.
+ *
+ * @return the {@code EdECPoint} representing the public key.
+ */
+ EdECPoint getPoint();
+}
diff --git a/ojluni/src/main/java/java/security/spec/EdECPoint.java b/ojluni/src/main/java/java/security/spec/EdECPoint.java
new file mode 100644
index 0000000..cb080f8
--- /dev/null
+++ b/ojluni/src/main/java/java/security/spec/EdECPoint.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2020, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package java.security.spec;
+
+import java.math.BigInteger;
+import java.util.Objects;
+
+/**
+ * An elliptic curve point used to specify keys as defined by
+ * <a href="https://tools.ietf.org/html/rfc8032">RFC 8032: Edwards-Curve
+ * Digital Signature Algorithm (EdDSA)</a>. These points are distinct from the
+ * points represented by {@code ECPoint}, and they are intended for use with
+ * algorithms based on RFC 8032 such as the EdDSA {@code Signature} algorithm.
+ * <p>
+ * An EdEC point is specified by its y-coordinate value and a boolean that
+ * indicates whether the x-coordinate is odd. The y-coordinate is an
+ * element of the field of integers modulo some value p that is determined by
+ * the algorithm parameters. This field element is represented by a
+ * {@code BigInteger}, and implementations that consume objects of this class
+ * may reject integer values which are not in the range [0, p).
+ *
+ * @since 15
+ */
+
+public final class EdECPoint {
+
+ private final boolean xOdd;
+ private final BigInteger y;
+
+ /**
+ * Construct an EdECPoint.
+ *
+ * @param xOdd whether the x-coordinate is odd.
+ * @param y the y-coordinate, represented using a {@code BigInteger}.
+ *
+ * @throws NullPointerException if {@code y} is null.
+ */
+ public EdECPoint(boolean xOdd, BigInteger y) {
+
+ Objects.requireNonNull(y, "y must not be null");
+
+ this.xOdd = xOdd;
+ this.y = y;
+ }
+
+ /**
+ * Get whether the x-coordinate of the point is odd.
+ *
+ * @return a boolean indicating whether the x-coordinate is odd.
+ */
+ public boolean isXOdd() {
+ return xOdd;
+ }
+
+ /**
+ * Get the y-coordinate of the point.
+ *
+ * @return the y-coordinate, represented using a {@code BigInteger}.
+ */
+ public BigInteger getY() {
+ return y;
+ }
+}
diff --git a/ojluni/src/main/java/java/security/spec/EdECPrivateKeySpec.java b/ojluni/src/main/java/java/security/spec/EdECPrivateKeySpec.java
new file mode 100644
index 0000000..370dfc9
--- /dev/null
+++ b/ojluni/src/main/java/java/security/spec/EdECPrivateKeySpec.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2020, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package java.security.spec;
+
+import java.util.Objects;
+
+/**
+ * A class representing elliptic curve private keys as defined in
+ * <a href="https://tools.ietf.org/html/rfc8032">RFC 8032: Edwards-Curve
+ * Digital Signature Algorithm (EdDSA)</a>, including the curve and other
+ * algorithm parameters. The private key is a bit string represented using
+ * a byte array. This class only supports bit string lengths that are a
+ * multiple of 8.
+ *
+ * @since 15
+ */
+public final class EdECPrivateKeySpec implements KeySpec {
+
+ private final NamedParameterSpec params;
+ private final byte[] bytes;
+
+ /**
+ * Construct a private key spec using the supplied parameters and
+ * bit string.
+ *
+ * @param params the algorithm parameters.
+ * @param bytes the key as a byte array. This array is copied
+ * to protect against subsequent modification.
+ *
+ * @throws NullPointerException if {@code params} or {@code bytes}
+ * is null.
+ */
+ public EdECPrivateKeySpec(NamedParameterSpec params, byte[] bytes) {
+ Objects.requireNonNull(params, "params must not be null");
+ Objects.requireNonNull(bytes, "bytes must not be null");
+
+ this.params = params;
+ this.bytes = bytes.clone();
+ }
+
+ /**
+ * Get the algorithm parameters that define the curve and other settings.
+ *
+ * @return the algorithm parameters.
+ */
+ public NamedParameterSpec getParams() {
+ return params;
+ }
+
+ /**
+ * Get the byte array representing the private key. A new copy of the array
+ * is returned each time this method is called.
+ *
+ * @return the private key as a byte array.
+ */
+ public byte[] getBytes() {
+ return bytes.clone();
+ }
+}
diff --git a/ojluni/src/main/java/java/security/spec/EdECPublicKeySpec.java b/ojluni/src/main/java/java/security/spec/EdECPublicKeySpec.java
new file mode 100644
index 0000000..fc52b3b
--- /dev/null
+++ b/ojluni/src/main/java/java/security/spec/EdECPublicKeySpec.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2020, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package java.security.spec;
+
+import java.util.Objects;
+
+/**
+ * A class representing elliptic curve public keys as defined in
+ * <a href="https://tools.ietf.org/html/rfc8032">RFC 8032: Edwards-Curve
+ * Digital Signature Algorithm (EdDSA)</a>, including the curve and other
+ * algorithm parameters. The public key is a point on the curve, which is
+ * represented using an {@code EdECPoint}.
+ *
+ * @since 15
+ */
+public final class EdECPublicKeySpec implements KeySpec {
+
+ private final NamedParameterSpec params;
+ private final EdECPoint point;
+
+ /**
+ * Construct a public key spec using the supplied parameters and
+ * point.
+ *
+ * @param params the algorithm parameters.
+ * @param point the point representing the public key.
+ *
+ * @throws NullPointerException if {@code params} or {@code point}
+ * is null.
+ */
+ public EdECPublicKeySpec(NamedParameterSpec params, EdECPoint point) {
+ Objects.requireNonNull(params, "params must not be null");
+ Objects.requireNonNull(point, "point must not be null");
+
+ this.params = params;
+ this.point = point;
+ }
+
+ /**
+ * Get the algorithm parameters that define the curve and other settings.
+ *
+ * @return the parameters.
+ */
+ public NamedParameterSpec getParams() {
+ return params;
+ }
+
+ /**
+ * Get the point representing the public key.
+ *
+ * @return the {@code EdECPoint} representing the public key.
+ */
+ public EdECPoint getPoint() {
+ return point;
+ }
+}
diff --git a/ojluni/src/main/java/java/security/spec/NamedParameterSpec.java b/ojluni/src/main/java/java/security/spec/NamedParameterSpec.java
index 4e61065..9090567 100644
--- a/ojluni/src/main/java/java/security/spec/NamedParameterSpec.java
+++ b/ojluni/src/main/java/java/security/spec/NamedParameterSpec.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2020, 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
@@ -33,7 +33,7 @@
* parameter set name. For example, NamedParameterSpec.X25519 represents the
* parameter set identified by the string "X25519". These strings are defined
* in the <a href=
- * "{@docRoot}/../specs/security/standard-names.html#parameter-spec-names">
+ * "{@docRoot}/../specs/security/standard-names.html#parameterspec-names">
* Java Security Standard Algorithm Names Specification</a>.
*
* @since 11
@@ -52,6 +52,22 @@
public static final NamedParameterSpec X448
= new NamedParameterSpec("X448");
+ /**
+ * The Ed25519 parameters
+ *
+ * @since 15
+ */
+ public static final NamedParameterSpec ED25519
+ = new NamedParameterSpec("Ed25519");
+
+ /**
+ * The Ed448 parameters
+ *
+ * @since 15
+ */
+ public static final NamedParameterSpec ED448
+ = new NamedParameterSpec("Ed448");
+
private String name;
/**
@@ -60,10 +76,14 @@
* list of supported names, please consult the documentation
* of the provider whose implementation will be used.
*
- * @param stdName the standard name of the algorithm parameters
+ * @param stdName the standard name of the algorithm parameters. See the
+ * ParameterSpec Names section in the
+ * <a href=
+ * "{@docRoot}/../specs/security/standard-names.html#parameterspec-names">
+ * Java Security Standard Algorithm Names Specification</a> for
+ * information about standard names.
*
- * @throws NullPointerException if {@code stdName}
- * is null.
+ * @throws NullPointerException if {@code stdName} is null.
*/
public NamedParameterSpec(String stdName) {
Objects.requireNonNull(stdName, "stdName must not be null");
diff --git a/ojluni/src/main/java/javax/crypto/KeyAgreement.java b/ojluni/src/main/java/javax/crypto/KeyAgreement.java
index fd79680..338e682 100644
--- a/ojluni/src/main/java/javax/crypto/KeyAgreement.java
+++ b/ojluni/src/main/java/javax/crypto/KeyAgreement.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -40,18 +40,18 @@
* exchange) protocol.
* <p>
* The keys involved in establishing a shared secret are created by one of the
- * key generators (<code>KeyPairGenerator</code> or
- * <code>KeyGenerator</code>), a <code>KeyFactory</code>, or as a result from
+ * key generators ({@code KeyPairGenerator} or
+ * {@code KeyGenerator}), a {@code KeyFactory}, or as a result from
* an intermediate phase of the key agreement protocol.
*
- * <p> For each of the correspondents in the key exchange, <code>doPhase</code>
+ * <p> For each of the correspondents in the key exchange, {@code doPhase}
* needs to be called. For example, if this key exchange is with one other
- * party, <code>doPhase</code> needs to be called once, with the
- * <code>lastPhase</code> flag set to <code>true</code>.
+ * party, {@code doPhase} needs to be called once, with the
+ * {@code lastPhase} flag set to {@code true}.
* If this key exchange is
- * with two other parties, <code>doPhase</code> needs to be called twice,
- * the first time setting the <code>lastPhase</code> flag to
- * <code>false</code>, and the second time setting it to <code>true</code>.
+ * with two other parties, {@code doPhase} needs to be called twice,
+ * the first time setting the {@code lastPhase} flag to
+ * {@code false}, and the second time setting it to {@code true}.
* There may be any number of parties involved in a key exchange.
*
* <p> Android provides the following <code>KeyAgreement</code> algorithms:
@@ -75,7 +75,7 @@
* </table>
*
* This algorithm is described in the <a href=
- * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyAgreement">
+ * "{@docRoot}/../specs/security/standard-names.html#keyagreement-algorithms">
* KeyAgreement section</a> of the
* Java Cryptography Architecture Standard Algorithm Name Documentation.
*
@@ -149,20 +149,20 @@
}
/**
- * Returns the algorithm name of this <code>KeyAgreement</code> object.
+ * Returns the algorithm name of this {@code KeyAgreement} object.
*
* <p>This is the same name that was specified in one of the
- * <code>getInstance</code> calls that created this
- * <code>KeyAgreement</code> object.
+ * {@code getInstance} calls that created this
+ * {@code KeyAgreement} object.
*
- * @return the algorithm name of this <code>KeyAgreement</code> object.
+ * @return the algorithm name of this {@code KeyAgreement} object.
*/
public final String getAlgorithm() {
return this.algorithm;
}
/**
- * Returns a <code>KeyAgreement</code> object that implements the
+ * Returns a {@code KeyAgreement} object that implements the
* specified key agreement algorithm.
*
* <p> This method traverses the list of registered security Providers,
@@ -177,11 +177,11 @@
* @param algorithm the standard name of the requested key agreement
* algorithm.
* See the KeyAgreement section in the <a href=
- * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyAgreement">
- * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * "{@docRoot}/../specs/security/standard-names.html#keyagreement-algorithms">
+ * Java Security Standard Algorithm Names Specification</a>
* for information about standard algorithm names.
*
- * @return the new <code>KeyAgreement</code> object.
+ * @return the new {@code KeyAgreement} object
*
* @exception NullPointerException if the specified algorithm
* is null.
@@ -212,7 +212,7 @@
}
/**
- * Returns a <code>KeyAgreement</code> object that implements the
+ * Returns a {@code KeyAgreement} object that implements the
* specified key agreement algorithm.
*
* <p> A new KeyAgreement object encapsulating the
@@ -226,13 +226,13 @@
* @param algorithm the standard name of the requested key agreement
* algorithm.
* See the KeyAgreement section in the <a href=
- * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyAgreement">
- * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * "{@docRoot}/../specs/security/standard-names.html#keyagreement-algorithms">
+ * Java Security Standard Algorithm Names Specification</a>
* for information about standard algorithm names.
*
* @param provider the name of the provider.
*
- * @return the new <code>KeyAgreement</code> object.
+ * @return the new {@code KeyAgreement} object
*
* @exception NullPointerException if the specified algorithm
* is null.
@@ -261,7 +261,7 @@
}
/**
- * Returns a <code>KeyAgreement</code> object that implements the
+ * Returns a {@code KeyAgreement} object that implements the
* specified key agreement algorithm.
*
* <p> A new KeyAgreement object encapsulating the
@@ -272,13 +272,13 @@
* @param algorithm the standard name of the requested key agreement
* algorithm.
* See the KeyAgreement section in the <a href=
- * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyAgreement">
- * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * "{@docRoot}/../specs/security/standard-names.html#keyagreement-algorithms">
+ * Java Security Standard Algorithm Names Specification</a>
* for information about standard algorithm names.
*
* @param provider the provider.
*
- * @return the new <code>KeyAgreement</code> object.
+ * @return the new {@code KeyAgreement} object
*
* @exception NullPointerException if the specified algorithm
* is null.
@@ -366,8 +366,8 @@
}
}
- private final static int I_NO_PARAMS = 1;
- private final static int I_PARAMS = 2;
+ private static final int I_NO_PARAMS = 1;
+ private static final int I_PARAMS = 2;
private void implInit(KeyAgreementSpi spi, int type, Key key,
AlgorithmParameterSpec params, SecureRandom random)
@@ -437,9 +437,9 @@
}
/**
- * Returns the provider of this <code>KeyAgreement</code> object.
+ * Returns the provider of this {@code KeyAgreement} object.
*
- * @return the provider of this <code>KeyAgreement</code> object
+ * @return the provider of this {@code KeyAgreement} object
*/
public final Provider getProvider() {
chooseFirstProvider();
@@ -476,10 +476,10 @@
* parameters required for this key agreement.
*
* <p> If the key agreement algorithm requires random bytes, it gets them
- * from the given source of randomness, <code>random</code>.
+ * from the given source of randomness, {@code random}.
* However, if the underlying
* algorithm implementation does not require any random bytes,
- * <code>random</code> is ignored.
+ * {@code random} is ignored.
*
* @param key the party's private information. For example, in the case
* of the Diffie-Hellman key agreement, this would be the party's own
@@ -509,7 +509,7 @@
/*
if (!skipDebug && pdebug != null) {
pdebug.println("KeyAgreement." + algorithm + " algorithm from: " +
- this.provider.getName());
+ getProviderName());
}
*/
}
@@ -543,6 +543,10 @@
init(key, params, JceSecurity.RANDOM);
}
+ private String getProviderName() {
+ return (provider == null) ? "(no provider)" : provider.getName();
+ }
+
/**
* Initializes this key agreement with the given key, set of
* algorithm parameters, and source of randomness.
@@ -573,7 +577,7 @@
/*
if (!skipDebug && pdebug != null) {
pdebug.println("KeyAgreement." + algorithm + " algorithm from: " +
- this.provider.getName());
+ getProviderName());
}
*/
}
@@ -607,9 +611,9 @@
/**
* Generates the shared secret and returns it in a new buffer.
*
- * <p>This method resets this <code>KeyAgreement</code> object, so that it
+ * <p>This method resets this {@code KeyAgreement} object, so that it
* can be reused for further key agreements. Unless this key agreement is
- * reinitialized with one of the <code>init</code> methods, the same
+ * reinitialized with one of the {@code init} methods, the same
* private information and algorithm parameters will be used for
* subsequent key agreements.
*
@@ -625,23 +629,23 @@
/**
* Generates the shared secret, and places it into the buffer
- * <code>sharedSecret</code>, beginning at <code>offset</code> inclusive.
+ * {@code sharedSecret}, beginning at {@code offset} inclusive.
*
- * <p>If the <code>sharedSecret</code> buffer is too small to hold the
- * result, a <code>ShortBufferException</code> is thrown.
+ * <p>If the {@code sharedSecret} buffer is too small to hold the
+ * result, a {@code ShortBufferException} is thrown.
* In this case, this call should be repeated with a larger output buffer.
*
- * <p>This method resets this <code>KeyAgreement</code> object, so that it
+ * <p>This method resets this {@code KeyAgreement} object, so that it
* can be reused for further key agreements. Unless this key agreement is
- * reinitialized with one of the <code>init</code> methods, the same
+ * reinitialized with one of the {@code init} methods, the same
* private information and algorithm parameters will be used for
* subsequent key agreements.
*
* @param sharedSecret the buffer for the shared secret
- * @param offset the offset in <code>sharedSecret</code> where the
+ * @param offset the offset in {@code sharedSecret} where the
* shared secret will be stored
*
- * @return the number of bytes placed into <code>sharedSecret</code>
+ * @return the number of bytes placed into {@code sharedSecret}
*
* @exception IllegalStateException if this key agreement has not been
* completed yet
@@ -656,12 +660,12 @@
}
/**
- * Creates the shared secret and returns it as a <code>SecretKey</code>
+ * Creates the shared secret and returns it as a {@code SecretKey}
* object of the specified algorithm.
*
- * <p>This method resets this <code>KeyAgreement</code> object, so that it
+ * <p>This method resets this {@code KeyAgreement} object, so that it
* can be reused for further key agreements. Unless this key agreement is
- * reinitialized with one of the <code>init</code> methods, the same
+ * reinitialized with one of the {@code init} methods, the same
* private information and algorithm parameters will be used for
* subsequent key agreements.
*
diff --git a/ojluni/src/test/java/lang/invoke/LoopCombinatorTest.java b/ojluni/src/test/java/lang/invoke/LoopCombinatorTest.java
index 20b2de0..96d7cd1 100644
--- a/ojluni/src/test/java/lang/invoke/LoopCombinatorTest.java
+++ b/ojluni/src/test/java/lang/invoke/LoopCombinatorTest.java
@@ -178,8 +178,7 @@
List<MethodHandle> lvpreds = Arrays.asList(null, LoopWithVirtuals.MH_pred);
List<MethodHandle> lvfinis = Arrays.asList(null, LoopWithVirtuals.MH_fin);
return new Object[][] {
- // Android-removed: failing test case suppressed (b/207844518).
- // {null, "null or no clauses passed"},
+ {null, "null or no clauses passed"},
{new MethodHandle[][]{}, "null or no clauses passed"},
{new MethodHandle[][]{{null, Fac.MH_inc}, {Fac.MH_one, null, Fac.MH_mult, Fac.MH_pred, Fac.MH_fin}},
"All loop clauses must be represented as MethodHandle arrays with at most 4 elements."},
diff --git a/ojluni/src/test/java/lang/invoke/VarargsArrayTest.java b/ojluni/src/test/java/lang/invoke/VarargsArrayTest.java
new file mode 100644
index 0000000..aec41779
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarargsArrayTest.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2014, 2017, 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.
+ */
+
+// Android-added: package name.
+package test.java.lang.invoke;
+
+import sun.invoke.util.Wrapper;
+import test.java.lang.invoke.lib.CodeCacheOverflowProcessor;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.Arrays;
+import java.util.Collections;
+
+// Android-added: testng imports.
+import static org.testng.AssertJUnit.*;
+import org.testng.annotations.*;
+
+/* @test
+ * @summary unit tests for varargs array methods: MethodHandleInfo.varargsArray(int),
+ * MethodHandleInfo.varargsArray(Class,int) & MethodHandleInfo.varargsList(int)
+ * @modules java.base/sun.invoke.util
+ * @library /lib/testlibrary /java/lang/invoke/common
+ * @compile/module=java.base java/lang/invoke/MethodHandleHelper.java
+ * @run main/bootclasspath VarargsArrayTest
+ * @run main/bootclasspath/othervm -DVarargsArrayTest.MAX_ARITY=255 -DVarargsArrayTest.START_ARITY=250
+ * VarargsArrayTest
+ */
+
+/* This might take a while and burn lots of metadata:
+ * @run main/bootclasspath -DVarargsArrayTest.MAX_ARITY=255 -DVarargsArrayTest.EXHAUSTIVE=true VarargsArrayTest
+ */
+public class VarargsArrayTest {
+ private static final Class<?> CLASS = VarargsArrayTest.class;
+ private static final int MAX_ARITY = Integer.getInteger(
+ CLASS.getSimpleName()+".MAX_ARITY", 40);
+ private static final int START_ARITY = Integer.getInteger(
+ CLASS.getSimpleName()+".START_ARITY", 0);
+ private static final boolean EXHAUSTIVE = Boolean.getBoolean(
+ CLASS.getSimpleName()+".EXHAUSTIVE");
+
+ public static void main(String[] args) throws Throwable {
+ // Android-removed: test converted to testng.
+ // CodeCacheOverflowProcessor.runMHTest(VarargsArrayTest::test);
+ }
+
+ // Android-removed: Added @Test annotations.
+ /*
+ @Test
+ public static void test() throws Throwable {
+ testVarargsArray();
+ testVarargsReferenceArray();
+ testVarargsPrimitiveArray();
+ }
+ */
+
+ // Android-added: @Test annotation.
+ @Test
+ public static void testVarargsArray() throws Throwable {
+ final int MIN = START_ARITY;
+ final int MAX = MAX_ARITY-2; // 253+1 would cause parameter overflow with 'this' added
+ for (int nargs = MIN; nargs <= MAX; nargs = nextArgCount(nargs, 17, MAX)) {
+ // Android-changed: use VarargsArrayTest.varargsArray().
+ // MethodHandle target = MethodHandleHelper.varargsArray(nargs);
+ MethodHandle target = varargsArray(Object[].class, nargs);
+ Object[] args = new Object[nargs];
+ for (int i = 0; i < nargs; i++)
+ args[i] = "#"+i;
+ Object res = target.invokeWithArguments(args);
+ assertArrayEquals(args, (Object[])res);
+ }
+ }
+
+ // Android-added: @Test annotation.
+ @Test
+ public static void testVarargsReferenceArray() throws Throwable {
+ testTypedVarargsArray(Object[].class);
+ testTypedVarargsArray(String[].class);
+ testTypedVarargsArray(Number[].class);
+ }
+
+ // Android-added: @Test annotation.
+ @Test
+ public static void testVarargsPrimitiveArray() throws Throwable {
+ testTypedVarargsArray(int[].class);
+ testTypedVarargsArray(long[].class);
+ testTypedVarargsArray(byte[].class);
+ testTypedVarargsArray(boolean[].class);
+ testTypedVarargsArray(short[].class);
+ testTypedVarargsArray(char[].class);
+ testTypedVarargsArray(float[].class);
+ testTypedVarargsArray(double[].class);
+ }
+
+ private static int nextArgCount(int nargs, int density, int MAX) {
+ if (EXHAUSTIVE) return nargs + 1;
+ if (nargs >= MAX) return Integer.MAX_VALUE;
+ int BOT = 20, TOP = MAX-5;
+ if (density < 10) { BOT = 10; MAX = TOP-2; }
+ if (nargs <= BOT || nargs >= TOP) {
+ ++nargs;
+ } else {
+ int bump = Math.max(1, 100 / density);
+ nargs += bump;
+ if (nargs > TOP) nargs = TOP;
+ }
+ return nargs;
+ }
+
+ // Android-added: simplified alternative to MethodHandleHelper.varargsArray().
+ private static MethodHandle varargsArray(Class<?> arrayType, int nargs) {
+ return MethodHandles.identity(arrayType).asCollector(arrayType, nargs);
+ }
+
+ private static void testTypedVarargsArray(Class<?> arrayType) throws Throwable {
+ Class<?> elemType = arrayType.getComponentType();
+ int MIN = START_ARITY;
+ int MAX = MAX_ARITY-2; // 253+1 would cause parameter overflow with 'this' added
+ int density = 3;
+ if (elemType == int.class || elemType == long.class) density = 7;
+ if (elemType == long.class || elemType == double.class) { MAX /= 2; MIN /= 2; }
+ for (int nargs = MIN; nargs <= MAX; nargs = nextArgCount(nargs, density, MAX)) {
+ Object[] args = makeTestArray(elemType, nargs);
+ // Android-changed: used varargsArrayHelper above.
+ // MethodHandle varargsArray = MethodHandleHelper.varargsArray(arrayType, nargs);
+ MethodHandle varargsArray = varargsArray(arrayType, nargs);
+ MethodType vaType = varargsArray.type();
+ assertEquals(arrayType, vaType.returnType());
+ if (nargs != 0) {
+ assertEquals(elemType, vaType.parameterType(0));
+ assertEquals(elemType, vaType.parameterType(vaType.parameterCount()-1));
+ }
+ assertEquals(MethodType.methodType(arrayType, Collections.<Class<?>>nCopies(nargs, elemType)),
+ vaType);
+ Object res = varargsArray.invokeWithArguments(args);
+ assertEquals(res.getClass(), arrayType);
+ String resString = toArrayString(res);
+ assertEquals(Arrays.toString(args), resString);
+
+ MethodHandle spreader = varargsArray.asSpreader(arrayType, nargs);
+ MethodType stype = spreader.type();
+ assert(stype == MethodType.methodType(arrayType, arrayType));
+ if (nargs <= 5) {
+ // invoke target as a spreader also:
+ @SuppressWarnings("cast")
+ Object res2 = spreader.invokeWithArguments((Object)res);
+ String res2String = toArrayString(res2);
+ assertEquals(Arrays.toString(args), res2String);
+ // invoke the spreader on a generic Object[] array; check for error
+ try {
+ Object res3 = spreader.invokeWithArguments((Object)args);
+ String res3String = toArrayString(res3);
+ assertTrue(arrayType.getName(), arrayType.isAssignableFrom(Object[].class));
+ assertEquals(Arrays.toString(args), res3String);
+ } catch (ClassCastException ex) {
+ assertFalse(arrayType.getName(), arrayType.isAssignableFrom(Object[].class));
+ }
+ }
+ if (nargs == 0) {
+ // invoke spreader on null arglist
+ Object res3 = spreader.invokeWithArguments((Object)null);
+ String res3String = toArrayString(res3);
+ assertEquals(Arrays.toString(args), res3String);
+ }
+ }
+ }
+
+ private static Object[] makeTestArray(Class<?> elemType, int len) {
+ Wrapper elem = null;
+ if (elemType.isPrimitive())
+ elem = Wrapper.forPrimitiveType(elemType);
+ else if (Wrapper.isWrapperType(elemType))
+ elem = Wrapper.forWrapperType(elemType);
+ Object[] args = new Object[len];
+ for (int i = 0; i < len; i++) {
+ Object arg = i * 100;
+ if (elem == null) {
+ if (elemType == String.class)
+ arg = "#"+arg;
+ arg = elemType.cast(arg); // just to make sure
+ } else {
+ switch (elem) {
+ case BOOLEAN: arg = (i % 3 == 0); break;
+ case CHAR: arg = 'a' + i; break;
+ case LONG: arg = (long)i * 1000_000_000; break;
+ case FLOAT: arg = (float)i / 100; break;
+ case DOUBLE: arg = (double)i / 1000_000; break;
+ }
+ arg = elem.cast(arg, elemType);
+ }
+ args[i] = arg;
+ }
+ return args;
+ }
+
+ private static String toArrayString(Object a) {
+ if (a == null) return "null";
+ Class<?> elemType = a.getClass().getComponentType();
+ if (elemType == null) return a.toString();
+ if (elemType.isPrimitive()) {
+ switch (Wrapper.forPrimitiveType(elemType)) {
+ case INT: return Arrays.toString((int[])a);
+ case BYTE: return Arrays.toString((byte[])a);
+ case BOOLEAN: return Arrays.toString((boolean[])a);
+ case SHORT: return Arrays.toString((short[])a);
+ case CHAR: return Arrays.toString((char[])a);
+ case FLOAT: return Arrays.toString((float[])a);
+ case LONG: return Arrays.toString((long[])a);
+ case DOUBLE: return Arrays.toString((double[])a);
+ }
+ }
+ return Arrays.toString((Object[])a);
+ }
+
+ public static void assertArrayEquals(Object[] arr1, Object[] arr2) {
+ if (arr1 == null && arr2 == null) return;
+ if (arr1 != null && arr2 != null && arr1.length == arr2.length) {
+ for (int i = 0; i < arr1.length; i++) {
+ assertEquals(arr1[i], arr2[i]);
+ }
+ return;
+ }
+ throw new AssertionError(Arrays.deepToString(arr1)
+ + " != " + Arrays.deepToString(arr2));
+ }
+
+ // Android-removed: use asserts from testng API for use in test harness.
+ /*
+ public static void assertEquals(Object o1, Object o2) {
+ if (o1 == null && o2 == null) return;
+ if (o1 != null && o1.equals(o2)) return;
+ throw new AssertionError(o1 + " != " + o2);
+ }
+
+ public static void assertTrue(String msg, boolean b) {
+ if (!b) {
+ throw new AssertionError(msg);
+ }
+ }
+
+ public static void assertFalse(String msg, boolean b) {
+ assertTrue(msg, !b);
+ }
+ */
+}
diff --git a/ojluni/src/test/java/security/KeyAgreement/KeyAgreementTest.java b/ojluni/src/test/java/security/KeyAgreement/KeyAgreementTest.java
new file mode 100644
index 0000000..7b126a3
--- /dev/null
+++ b/ojluni/src/test/java/security/KeyAgreement/KeyAgreementTest.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2018, 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 4936763 8184359
+ * @summary KeyAgreement Test with all supported algorithms from JCE.
+ * Arguments order <KeyExchangeAlgorithm> <KeyGenAlgorithm> <Provider>
+ * It removes com/sun/crypto/provider/KeyAgreement/DHGenSecretKey.java
+ * as the same functionality for DiffieHellman is covered along with
+ * this test file was covered before with JDK-4936763.
+ */
+package test.java.security.KeyAgreement;
+
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.spec.NamedParameterSpec;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.ECGenParameterSpec;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import javax.crypto.KeyAgreement;
+import javax.crypto.spec.DHGenParameterSpec;
+
+import org.testng.annotations.Test;
+import static org.junit.Assert.fail;
+
+public class KeyAgreementTest {
+
+ List<String> kaAlgos = Arrays.asList("DiffieHellman", "ECDH");
+ List<String> kpgAlgos = Arrays.asList("DH", "EC");
+ List<String> providers = Arrays.asList("BC", "AndroidOpenSSL");
+
+ @Test
+ public void testKeyAgreement() throws Exception {
+ for (int i = 0; i < kaAlgos.size(); i++) {
+ AlgoSpec aSpec = AlgoSpec.valueOf(AlgoSpec.class, kaAlgos.get(i));
+ List<AlgorithmParameterSpec> specs = aSpec.getAlgorithmParameterSpecs();
+ for (AlgorithmParameterSpec spec : specs) {
+ testKeyAgreement(providers.get(i), kaAlgos.get(i), kpgAlgos.get(i), spec);
+ }
+ }
+ }
+
+ /**
+ * Generate AlgorithmParameterSpec using all possible supported curve for
+ * KeyExchangeAlgorithm.
+ */
+ private enum AlgoSpec {
+ // EC curve supported for KeyGeneration can found between intersection
+ // of curves define in
+ // "java.base/share/classes/sun/security/util/CurveDB.java"
+ // and
+ // "jdk.crypto.ec/share/native/libsunec/impl/ecdecode.c"
+ ECDH( "secp224r1", "secp256r1", "secp384r1", "secp521r1"
+ ),
+ XDH("X25519", "X448"),
+ // There is no curve for DiffieHellman
+ DiffieHellman(new String[]{});
+
+ private final List<AlgorithmParameterSpec> specs = new ArrayList<>();
+
+ private AlgoSpec(String... curves) {
+ // Generate AlgorithmParameterSpec for each KeyExchangeAlgorithm
+ for (String crv : curves) {
+ switch (this.name()) {
+ case "ECDH":
+ specs.add(new ECGenParameterSpec(crv));
+ break;
+ case "XDH":
+ specs.add(new NamedParameterSpec(crv));
+ break;
+ case "DiffieHellman":
+ specs.add(new DHGenParameterSpec(512, 64));
+ break;
+ default:
+ fail("Invalid Algo name "
+ + this.name());
+ }
+ }
+ }
+
+ public List<AlgorithmParameterSpec> getAlgorithmParameterSpecs() {
+ return this.specs;
+ }
+ }
+
+ /**
+ * Perform KeyAgreement operation using native as well as JCE provider.
+ */
+ private static void testKeyAgreement(String provider, String kaAlgo,
+ String kpgAlgo, AlgorithmParameterSpec spec) throws Exception {
+
+ KeyPairGenerator kpg = KeyPairGenerator.getInstance(kpgAlgo, provider);
+ kpg.initialize(spec);
+ KeyPair kp1 = kpg.generateKeyPair();
+ KeyPair kp2 = kpg.generateKeyPair();
+
+ // Uses KeyAgreement based on Provider search order.
+ KeyAgreement ka1 = KeyAgreement.getInstance(kaAlgo);
+ ka1.init(kp1.getPrivate());
+ ka1.doPhase(kp2.getPublic(), true);
+ byte[] secret1 = ka1.generateSecret();
+
+ // Uses SunJCE provider
+ KeyAgreement ka2 = KeyAgreement.getInstance(kaAlgo, provider);
+ ka2.init(kp2.getPrivate());
+ ka2.doPhase(kp1.getPublic(), true);
+ // Keeping the legacy generateSecret method for DiffieHellman as it was
+ // defined in removed Test file from JDK-4936763,
+ // com/sun/crypto/provider/KeyAgreement/DHGenSecretKey.java.
+ byte[] secret2 = "DiffieHellman".equals(kaAlgo)
+ ? ka2.generateSecret("AES").getEncoded() : ka2.generateSecret();
+
+ // With related keypairs, each provider should generate same
+ // KeyAgreement secret.
+ if (!Arrays.equals(secret1, secret2)) {
+ fail("KeyAgreement secret mismatch.");
+ }
+ }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/security/KeyAgreement/KeySizeTest.java b/ojluni/src/test/java/security/KeyAgreement/KeySizeTest.java
new file mode 100644
index 0000000..9ab73a5
--- /dev/null
+++ b/ojluni/src/test/java/security/KeyAgreement/KeySizeTest.java
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2018, 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 8184359
+ * @summary KeyLength support test for DiffieHellman, EC, XDH.
+ * Arguments order <KeyExchangeAlgorithm> <Provider> <KeyGenAlgorithm> <keyLen>
+ * @library /test/lib
+ * @build jdk.test.lib.Convert
+ * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 512
+ * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 768
+ * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 832
+ * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 1024
+ * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 2048
+ * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 3072
+ * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 4096
+ * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 6144
+ * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 8192
+ * @run main KeySizeTest ECDH SunEC EC 128
+ * @run main KeySizeTest ECDH SunEC EC 192
+ * @run main KeySizeTest ECDH SunEC EC 256
+ * @run main KeySizeTest XDH SunEC XDH 255
+ * @run main KeySizeTest XDH SunEC XDH 448
+ */
+package test.java.security.KeyAgreement;
+
+import java.math.BigInteger;
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.interfaces.ECPrivateKey;
+import java.security.interfaces.ECPublicKey;
+import java.security.interfaces.XECPrivateKey;
+import java.security.interfaces.XECPublicKey;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.security.spec.NamedParameterSpec;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.crypto.KeyAgreement;
+import javax.crypto.interfaces.DHPrivateKey;
+import javax.crypto.interfaces.DHPublicKey;
+
+import org.testng.annotations.Test;
+import static org.junit.Assert.fail;
+
+public class KeySizeTest {
+
+ List<Integer> sizesDH = Arrays.asList(512, 768, 832, 1024, 2048);
+ List<Integer> sizesECDH = Arrays.asList(224, 256, 384, 521);
+ List<Integer> sizesXDH = Arrays.asList(512, 768, 832, 1024, 2048, 3072, 4096, 6144, 8192);
+
+ @Test
+ public void testDHKeySize() throws Exception {
+ for (int i = 0; i < sizesDH.size(); i++) {
+ testKeyAgreement("BC", "DiffieHellman", "DiffieHellman", sizesDH.get(i));
+ }
+ }
+
+ @Test
+ public void testECDHKeySize() throws Exception {
+ for (int i = 0; i < sizesECDH.size(); i++) {
+ testKeyAgreement("AndroidOpenSSL", "ECDH", "EC", sizesECDH.get(i));
+ }
+ }
+
+ // BEGIN Android-removed: XDH is not yet supported
+ /*
+ @Test
+ public void testXDHKeySize() throws Exception {
+ for (int i = 0; i < sizesXDH.size(); i++) {
+ testKeyAgreement("AndroidOpenSSL", "XDH", "XDH", sizesXDH.get(i));
+ }
+ }
+ */
+ // END Android-removed: XDH is not yet supported
+
+ /**
+ * Perform KeyAgreement operation.
+ */
+ private static void testKeyAgreement(String provider, String kaAlgo,
+ String kpgAlgo, int keySize) throws Exception {
+
+ KeyPairGenerator kpg = KeyPairGenerator.getInstance(kpgAlgo, provider);
+ kpg.initialize(keySize);
+ KeyPair kp = kpg.generateKeyPair();
+ // Test standard Key attributes.
+ testKeyAttributes(provider, kpgAlgo, kp, keySize);
+ // Test KeyAgreement.
+ KeyAgreement ka = KeyAgreement.getInstance(kaAlgo, provider);
+ ka.init(kp.getPrivate());
+ ka.doPhase(kp.getPublic(), true);
+ ka.generateSecret();
+ }
+
+ /**
+ * Test standard Key attributes.
+ */
+ private static void testKeyAttributes(String provider, String kpgAlgo,
+ KeyPair kp, int keySize) throws Exception {
+
+ KeyFactory kf = KeyFactory.getInstance(kpgAlgo, provider);
+ switch (kpgAlgo) {
+ case "DiffieHellman":
+ // Verify PrivateKey attributes.
+ DHPrivateKey dhPri = (DHPrivateKey) kp.getPrivate();
+ BigInteger p = dhPri.getParams().getP();
+ if (p.bitLength() != keySize) {
+ fail(String.format("Invalid modulus size: "
+ + "%s/%s", p.bitLength(), keySize));
+ }
+ if (!p.isProbablePrime(128)) {
+ fail("The modulus is composite!");
+ }
+ PKCS8EncodedKeySpec dhPriSpec
+ = new PKCS8EncodedKeySpec(dhPri.getEncoded());
+ DHPrivateKey dhPriDecod
+ = (DHPrivateKey) kf.generatePrivate(dhPriSpec);
+ equals(dhPri.getX(), dhPriDecod.getX());
+ equals(dhPri.getFormat(), dhPriDecod.getFormat());
+ equals(dhPri.getEncoded(), dhPriDecod.getEncoded());
+ equals(dhPri.getParams().getG(), dhPriDecod.getParams().getG());
+ equals(dhPri.getParams().getL(), dhPriDecod.getParams().getL());
+ equals(dhPri.getParams().getP(), dhPriDecod.getParams().getP());
+
+ // Verify PublicKey attributes.
+ DHPublicKey dhPub = (DHPublicKey) kp.getPublic();
+ p = dhPub.getParams().getP();
+ if (p.bitLength() != keySize) {
+ fail(String.format("Invalid modulus size: "
+ + "%s/%s", p.bitLength(), keySize));
+ }
+ X509EncodedKeySpec dhPubSpec
+ = new X509EncodedKeySpec(dhPub.getEncoded());
+ DHPublicKey dhPubDecod
+ = (DHPublicKey) kf.generatePublic(dhPubSpec);
+ equals(dhPub.getY(), dhPubDecod.getY());
+ equals(dhPub.getFormat(), dhPubDecod.getFormat());
+ equals(dhPub.getEncoded(), dhPubDecod.getEncoded());
+ equals(dhPub.getParams().getG(), dhPubDecod.getParams().getG());
+ equals(dhPub.getParams().getL(), dhPubDecod.getParams().getL());
+ equals(dhPub.getParams().getP(), dhPubDecod.getParams().getP());
+
+ BigInteger left = BigInteger.ONE;
+ BigInteger right = p.subtract(BigInteger.ONE);
+ BigInteger x = dhPri.getX();
+ if ((x.compareTo(left) <= 0) || (x.compareTo(right) >= 0)) {
+ fail(
+ "X outside range [2, p - 2]: x: " + x + " p: " + p);
+ }
+ BigInteger y = dhPub.getY();
+ if ((y.compareTo(left) <= 0) || (y.compareTo(right) >= 0)) {
+ fail(
+ "Y outside range [2, p - 2]: x: " + x + " p: " + p);
+ }
+ break;
+ case "EC":
+ // Verify PrivateKey attributes.
+ ECPrivateKey ecPriv = (ECPrivateKey) kp.getPrivate();
+ PKCS8EncodedKeySpec ecPriSpec
+ = new PKCS8EncodedKeySpec(ecPriv.getEncoded());
+ ECPrivateKey ecPriDecod
+ = (ECPrivateKey) kf.generatePrivate(ecPriSpec);
+ equals(ecPriv.getS(), ecPriDecod.getS());
+ equals(ecPriv.getFormat(), ecPriDecod.getFormat());
+ equals(ecPriv.getEncoded(), ecPriDecod.getEncoded());
+ equals(ecPriv.getParams().getCofactor(),
+ ecPriDecod.getParams().getCofactor());
+ equals(ecPriv.getParams().getCurve(),
+ ecPriDecod.getParams().getCurve());
+ equals(ecPriv.getParams().getGenerator(),
+ ecPriDecod.getParams().getGenerator());
+ equals(ecPriv.getParams().getOrder(),
+ ecPriDecod.getParams().getOrder());
+
+ // Verify PublicKey attributes.
+ ECPublicKey ecPub = (ECPublicKey) kp.getPublic();
+ X509EncodedKeySpec ecPubSpec
+ = new X509EncodedKeySpec(ecPub.getEncoded());
+ ECPublicKey ecPubDecod
+ = (ECPublicKey) kf.generatePublic(ecPubSpec);
+ equals(ecPub.getW(), ecPubDecod.getW());
+ equals(ecPub.getFormat(), ecPubDecod.getFormat());
+ equals(ecPub.getEncoded(), ecPubDecod.getEncoded());
+ equals(ecPub.getParams().getCofactor(),
+ ecPubDecod.getParams().getCofactor());
+ equals(ecPub.getParams().getCurve(),
+ ecPubDecod.getParams().getCurve());
+ equals(ecPub.getParams().getGenerator(),
+ ecPubDecod.getParams().getGenerator());
+ equals(ecPub.getParams().getOrder(),
+ ecPubDecod.getParams().getOrder());
+ break;
+ case "XDH":
+ // Verify PrivateKey attributes.
+ XECPrivateKey xdhPri = (XECPrivateKey) kp.getPrivate();
+ PKCS8EncodedKeySpec xdhPriSpec
+ = new PKCS8EncodedKeySpec(xdhPri.getEncoded());
+ XECPrivateKey xdhPriDec
+ = (XECPrivateKey) kf.generatePrivate(xdhPriSpec);
+ equals(xdhPri.getScalar().get(), xdhPriDec.getScalar().get());
+ equals(xdhPri.getFormat(), xdhPriDec.getFormat());
+ equals(xdhPri.getEncoded(), xdhPriDec.getEncoded());
+ equals(((NamedParameterSpec) xdhPri.getParams()).getName(),
+ ((NamedParameterSpec) xdhPriDec.getParams()).getName());
+
+ // Verify PublicKey attributes.
+ XECPublicKey xdhPub = (XECPublicKey) kp.getPublic();
+ X509EncodedKeySpec xdhPubSpec
+ = new X509EncodedKeySpec(xdhPub.getEncoded());
+ XECPublicKey xdhPubDec
+ = (XECPublicKey) kf.generatePublic(xdhPubSpec);
+ equals(xdhPub.getU(), xdhPubDec.getU());
+ equals(xdhPub.getFormat(), xdhPubDec.getFormat());
+ equals(xdhPub.getEncoded(), xdhPubDec.getEncoded());
+ equals(((NamedParameterSpec) xdhPub.getParams()).getName(),
+ ((NamedParameterSpec) xdhPubDec.getParams()).getName());
+ break;
+ default:
+ fail("Invalid Algo name " + kpgAlgo);
+ }
+ }
+
+ private static boolean equals(Object actual, Object expected) {
+ boolean equals = actual.equals(expected);
+ if (!equals) {
+ fail(String.format("Actual: %s, Expected: %s",
+ actual, expected));
+ }
+ return equals;
+ }
+
+ private static boolean equals(byte[] actual, byte[] expected) {
+ boolean equals = Arrays.equals(actual, expected);
+ if (!equals) {
+ fail("Actual array does not equal Expected array");
+ }
+ return equals;
+ }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/security/KeyAgreement/KeySpecTest.java b/ojluni/src/test/java/security/KeyAgreement/KeySpecTest.java
new file mode 100644
index 0000000..0ca3816
--- /dev/null
+++ b/ojluni/src/test/java/security/KeyAgreement/KeySpecTest.java
@@ -0,0 +1,342 @@
+/*
+ * Copyright (c) 2018, 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 8184359
+ * @summary Standard tests on KeySpec, KeyFactory, KeyPairs and Keys.
+ * Arguments order <KeyExchangeAlgorithm> <Provider> <KeyGenAlgorithm> <Curve*>
+ * @run main KeySpecTest DiffieHellman SunJCE DiffieHellman
+ * @run main KeySpecTest ECDH SunEC EC
+ * @run main KeySpecTest XDH SunEC XDH X25519
+ * @run main KeySpecTest XDH SunEC XDH X448
+ */
+package test.java.security.KeyAgreement;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.spec.ECPrivateKeySpec;
+import java.security.spec.ECPublicKeySpec;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.security.spec.NamedParameterSpec;
+import java.security.spec.XECPublicKeySpec;
+import java.security.spec.XECPrivateKeySpec;
+import java.security.spec.KeySpec;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Arrays;
+import javax.crypto.KeyAgreement;
+import javax.crypto.spec.DHPrivateKeySpec;
+import javax.crypto.spec.DHPublicKeySpec;
+
+import org.testng.annotations.Test;
+import static org.junit.Assert.fail;
+
+public class KeySpecTest {
+
+ @Test
+ public void testDHKeySpecs() throws Exception {
+ KeyPair kp = genKeyPair("BC","DiffieHellman",
+ "DiffieHellman");
+ testKeySpecs("BC", "DiffieHellman", "DiffieHellman", kp);
+ testEncodedKeySpecs("BC", "DiffieHellman", "DiffieHellman", kp);
+ }
+
+ @Test
+ public void testECDHKeySpecs() throws Exception {
+ KeyPair kp = genKeyPair("AndroidOpenSSL","EC",
+ "EC");
+ testKeySpecs("AndroidOpenSSL", "ECDH", "EC", kp);
+ testEncodedKeySpecs("AndroidOpenSSL", "ECDH", "EC", kp);
+ }
+
+ // BEGIN Android-removed: XDH is not yet supported
+ /*
+ @Test
+ public void testXDHKeySpecs() throws Exception {
+ KeyPair kp1 = genKeyPair("AndroidOpenSSL","XDH",
+ "X25519");
+ KeyPair kp2 = genKeyPair("AndroidOpenSSL","XDH",
+ "X25519");
+ testKeySpecs("AndroidOpenSSL", "XDH", "XDH", kp1);
+ testEncodedKeySpecs("AndroidOpenSSL", "XDH", "XDH", kp1);
+ testKeySpecs("AndroidOpenSSL", "XDH", "XDH", kp2);
+ testEncodedKeySpecs("AndroidOpenSSL", "XDH", "XDH", kp2);
+ }
+ */
+ // END Android-removed: XDH is not yet supported
+
+ /**
+ * Generate keyPair based on KeyPairGenerator algorithm.
+ */
+ private static KeyPair genKeyPair(String provider, String kpgAlgo,
+ String kpgInit) throws Exception {
+
+ KeyPairGenerator kpg = KeyPairGenerator.getInstance(kpgAlgo, provider);
+ switch (kpgInit) {
+ case "DiffieHellman":
+ kpg.initialize(512);
+ break;
+ case "EC":
+ kpg.initialize(256);
+ break;
+ case "X25519":
+ kpg.initialize(255);
+ break;
+ case "X448":
+ kpg.initialize(448);
+ break;
+ default:
+ fail("Invalid Algo name " + kpgInit);
+ }
+ return kpg.generateKeyPair();
+ }
+
+ /**
+ * Standard Test with Keys and the one generated through Spec.
+ */
+ private static void testKeySpecs(String provider, String kaAlgo,
+ String kpgAlgo, KeyPair kp) throws Exception {
+
+ KeyFactory kf = KeyFactory.getInstance(kpgAlgo, provider);
+ // For each public KeySpec supported by KeyPairGenerator
+ for (Class pubSpecType
+ : getCompatibleKeySpecs(kpgAlgo, KeyType.PUBLIC)) {
+ //For each private KeySpec supported by KeyPairGenerator
+ for (Class priSpecType
+ : getCompatibleKeySpecs(kpgAlgo, KeyType.PRIVATE)) {
+ // Transform original PublicKey through KeySpec
+ KeySpec pubSpec = kf.getKeySpec(kp.getPublic(), pubSpecType);
+ PublicKey pubKey = kf.generatePublic(pubSpec);
+ // Transform original PrivateKey through KeySpec
+ KeySpec priSpec = kf.getKeySpec(kp.getPrivate(), priSpecType);
+ PrivateKey priKey = kf.generatePrivate(priSpec);
+
+ // Test the keys are equal after transformation through KeySpec.
+ testKeyEquals(kp, pubKey, priKey);
+ // Test the keys are serializable.
+ testSerialize(kp);
+ // Test Parameter name.
+ if (!kaAlgo.equals("DiffieHellman")) {
+ testParamName(priSpec, pubSpec);
+ }
+ // Compare KeyAgreement secret generated from original keys
+ // and by the keys after transformed through KeySpec.
+ if (!Arrays.equals(getKeyAgreementSecret(provider, kaAlgo,
+ kp.getPublic(), kp.getPrivate()),
+ getKeyAgreementSecret(provider, kaAlgo,
+ pubKey, priKey))) {
+ fail("KeyAgreement secret mismatch.");
+ }
+ }
+ }
+ }
+
+ /**
+ * Standard Test with Keys and the one generated from encoded bytes.
+ */
+ private static void testEncodedKeySpecs(String provider, String kaAlgo,
+ String kpgAlgo, KeyPair kp) throws Exception {
+
+ KeyFactory kf = KeyFactory.getInstance(kpgAlgo, provider);
+ PKCS8EncodedKeySpec priSpec
+ = new PKCS8EncodedKeySpec(kp.getPrivate().getEncoded());
+ PrivateKey priKey = kf.generatePrivate(priSpec);
+
+ X509EncodedKeySpec pubSpec
+ = new X509EncodedKeySpec(kp.getPublic().getEncoded());
+ PublicKey pubKey = kf.generatePublic(pubSpec);
+
+ // Test the keys are equal after transformation through KeySpec.
+ testKeyEquals(kp, pubKey, priKey);
+ // Test the keys are serializable.
+ testSerialize(kp);
+ // Test Parameter name.
+ if (!kaAlgo.equals("DiffieHellman")) {
+ testParamName(priSpec, pubSpec);
+ }
+ // Compare KeyAgreement secret generated from original keys
+ // and by the keys after transformed through KeySpec.
+ if (!Arrays.equals(getKeyAgreementSecret(provider, kaAlgo,
+ kp.getPublic(), kp.getPrivate()),
+ getKeyAgreementSecret(provider, kaAlgo, pubKey, priKey))) {
+ fail("KeyAgreement secret mismatch.");
+ }
+ }
+
+ private enum KeyType {
+ PUBLIC, PRIVATE;
+ }
+
+ /**
+ * Provides Compatible KeySpec Type list for KeyPairGenerator algorithm.
+ */
+ private static List<Class> getCompatibleKeySpecs(String kpgAlgo,
+ KeyType type) {
+
+ List<Class> specs = new ArrayList<>();
+ switch (kpgAlgo) {
+ case "DiffieHellman":
+ if (type == KeyType.PUBLIC) {
+ return Arrays.asList(X509EncodedKeySpec.class,
+ DHPublicKeySpec.class);
+ } else {
+ return Arrays.asList(PKCS8EncodedKeySpec.class,
+ DHPrivateKeySpec.class);
+ }
+ case "EC":
+ if (type == KeyType.PUBLIC) {
+ return Arrays.asList(X509EncodedKeySpec.class,
+ ECPublicKeySpec.class);
+ } else {
+ return Arrays.asList(PKCS8EncodedKeySpec.class,
+ ECPrivateKeySpec.class);
+ }
+ case "XDH":
+ if (type == KeyType.PUBLIC) {
+ return Arrays.asList(X509EncodedKeySpec.class,
+ XECPublicKeySpec.class);
+ } else {
+ return Arrays.asList(PKCS8EncodedKeySpec.class,
+ XECPrivateKeySpec.class);
+ }
+ }
+ return specs;
+ }
+
+ /**
+ * Generate KeyAgreement Secret.
+ */
+ private static byte[] getKeyAgreementSecret(String provider, String kaAlgo,
+ PublicKey pubKey, PrivateKey priKey) throws Exception {
+
+ KeyAgreement ka = KeyAgreement.getInstance(kaAlgo, provider);
+ ka.init(priKey);
+ ka.doPhase(pubKey, true);
+ return ka.generateSecret();
+ }
+
+ /**
+ * Compare original KeyPair with transformed ones.
+ */
+ private static void testKeyEquals(KeyPair kp, PublicKey pubKey,
+ PrivateKey priKey) {
+
+ if (!kp.getPrivate().equals(priKey)
+ && kp.getPrivate().hashCode() != priKey.hashCode()) {
+ fail("PrivateKey is not equal with PrivateKey"
+ + " generated through KeySpec");
+ }
+ if (!kp.getPublic().equals(pubKey)
+ && kp.getPublic().hashCode() != pubKey.hashCode()) {
+ fail("PublicKey is not equal with PublicKey"
+ + " generated through KeySpec");
+ }
+ }
+
+ /**
+ * Compare the parameter names of Public/Private KeySpec from a pair.
+ */
+ private static void testParamName(KeySpec priSpec, KeySpec pubSpec) {
+
+ if (priSpec instanceof XECPrivateKeySpec
+ && pubSpec instanceof XECPublicKeySpec) {
+ if (((NamedParameterSpec) ((XECPrivateKeySpec) priSpec)
+ .getParams()).getName()
+ != ((NamedParameterSpec) ((XECPublicKeySpec) pubSpec)
+ .getParams()).getName()) {
+ fail("Curve name mismatch found");
+ }
+ }
+ }
+
+ /**
+ * Test serialization of KeyPair and Keys it holds.
+ */
+ private static void testSerialize(KeyPair keyPair) throws Exception {
+
+ // Verify Serialized PrivateKey instance.
+ if (!keyPair.getPrivate().equals(
+ deserializedCopy(keyPair.getPrivate(), PrivateKey.class))) {
+ fail("PrivateKey is not equal with PrivateKey"
+ + " generated through Serialization");
+ }
+ // Verify Serialized PublicKey instance.
+ if (!keyPair.getPublic().equals(
+ deserializedCopy(keyPair.getPublic(), PublicKey.class))) {
+ fail("PublicKey is not equal with PublicKey"
+ + " generated through Serialization");
+ }
+ // Verify Serialized KeyPair instance.
+ KeyPair copy = deserializedCopy(keyPair, KeyPair.class);
+ if (!keyPair.getPrivate().equals(copy.getPrivate())) {
+ fail("PrivateKey is not equal with PrivateKey"
+ + " generated through Serialized KeyPair");
+ }
+ if (!keyPair.getPublic().equals(copy.getPublic())) {
+ fail("PublicKey is not equal with PublicKey"
+ + " generated through Serialized KeyPair");
+ }
+ }
+
+ private static <T extends Object> T deserializedCopy(T orig, Class<T> type)
+ throws IOException, ClassNotFoundException {
+ return deserialize(serialize(orig), type);
+ }
+
+ /**
+ * Deserialize the Key object.
+ */
+ private static <T extends Object> T deserialize(byte[] serialized,
+ Class<T> type) throws IOException, ClassNotFoundException {
+
+ T key = null;
+ try (ByteArrayInputStream bis = new ByteArrayInputStream(serialized);
+ ObjectInputStream ois = new ObjectInputStream(bis)) {
+ key = (T) ois.readObject();
+ }
+ return key;
+ }
+
+ /**
+ * Serialize the given Key object.
+ */
+ private static <T extends Object> byte[] serialize(T key)
+ throws IOException {
+
+ try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(bos)) {
+ oos.writeObject(key);
+ return bos.toByteArray();
+ }
+ }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/security/KeyAgreement/MultiThreadTest.java b/ojluni/src/test/java/security/KeyAgreement/MultiThreadTest.java
new file mode 100644
index 0000000..b773320
--- /dev/null
+++ b/ojluni/src/test/java/security/KeyAgreement/MultiThreadTest.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2018, 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 8184359
+ * @summary KeyPairGenerator Test with multiple threads.
+ * Arguments order <KeyExchangeAlgorithm> <Provider> <KeyGenAlgorithm> <Curve*>
+ * @run main MultiThreadTest DiffieHellman SunJCE DiffieHellman
+ * @run main MultiThreadTest ECDH SunEC EC
+ * @run main MultiThreadTest XDH SunEC XDH X25519
+ * @run main MultiThreadTest XDH SunEC XDH X448
+ */
+package test.java.security.KeyAgreement;
+
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.util.Arrays;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import javax.crypto.KeyAgreement;
+import org.testng.annotations.Test;
+import static org.junit.Assert.fail;
+
+/**
+ * This test targets KeyPairGenerator API related issue in a multi threaded
+ * context.
+ */
+public class MultiThreadTest {
+
+ // Tested a shared KeyPairGenerator with 100 number of threads.
+ private static final int THREAD_COUNT = 100;
+
+ @Test
+ public void testDHKeySpecs() throws Exception {
+ KeyPairGenerator kpg = genKeyGenerator("BC","DiffieHellman",
+ "DiffieHellman");
+ new MultiThreadTest().runTest("BC", "DiffieHellman", kpg);
+ }
+
+ @Test
+ public void testECDHKeySpecs() throws Exception {
+ KeyPairGenerator kpg = genKeyGenerator("AndroidOpenSSL","EC",
+ "EC");
+ new MultiThreadTest().runTest("AndroidOpenSSL", "ECDH", kpg);
+ }
+
+
+ // BEGIN Android-removed: XDH is not yet supported
+ /*
+ @Test
+ public void testXDHKeySpecs() throws Exception {
+ KeyPairGenerator kpg1 = genKeyGenerator("AndroidOpenSSL","XDH",
+ "X25519");
+ new MultiThreadTest().runTest("AndroidOpenSSL", "XDH", kpg1);
+ KeyPairGenerator kpg2 = genKeyGenerator("AndroidOpenSSL","XDH",
+ "X25519");
+ new MultiThreadTest().runTest("AndroidOpenSSL", "XDH", kpg2);
+ }
+ */
+ // END Android-removed: XDH is not yet supported
+
+ /**
+ * Initialize KeyPairGenerator based on different algorithm names.
+ */
+ private static KeyPairGenerator genKeyGenerator(String provider,
+ String kpgAlgo, String kpgInit) throws Exception {
+
+ KeyPairGenerator kpg = KeyPairGenerator.getInstance(kpgAlgo, provider);
+ switch (kpgInit) {
+ case "DiffieHellman":
+ kpg.initialize(512);
+ break;
+ case "EC":
+ kpg.initialize(256);
+ break;
+ case "X25519":
+ kpg.initialize(255);
+ break;
+ case "X448":
+ kpg.initialize(448);
+ break;
+ default:
+ fail("Invalid Algo name " + kpgInit);
+ }
+ return kpg;
+ }
+
+ private void runTest(String provider, String kaAlgo, KeyPairGenerator kpg)
+ throws Exception {
+
+ ExecutorService executor = null;
+ try {
+ executor = Executors.newCachedThreadPool(new ThreadFactory() {
+ @Override
+ public Thread newThread(Runnable r) {
+ Thread t = Executors.defaultThreadFactory().newThread(r);
+ t.setDaemon(true);
+ return t;
+ }
+ });
+ CountDownLatch latch = new CountDownLatch(THREAD_COUNT);
+
+ for (int i = 0; i < THREAD_COUNT; i++) {
+ executor.execute(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ testKeyAgreement(provider, kaAlgo, kpg);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ } finally {
+ // Indicate a task completed.
+ latch.countDown();
+ }
+ }
+ });
+ }
+ // Wait till all tasks get complete.
+ latch.await();
+ } finally {
+ if (executor != null) {
+ executor.shutdown();
+ }
+ }
+ }
+
+ /**
+ * Perform KeyAgreement operation with a shared KeyPairGenerator instance.
+ */
+ private static void testKeyAgreement(String provider, String kaAlgo,
+ KeyPairGenerator kpg) throws Exception {
+
+ KeyPair kp1 = kpg.generateKeyPair();
+ KeyPair kp2 = kpg.generateKeyPair();
+
+ KeyAgreement ka1 = KeyAgreement.getInstance(kaAlgo, provider);
+ ka1.init(kp1.getPrivate());
+ ka1.doPhase(kp2.getPublic(), true);
+ byte[] secret1 = ka1.generateSecret();
+ KeyAgreement ka2 = KeyAgreement.getInstance(kaAlgo, provider);
+ ka2.init(kp2.getPrivate());
+ ka2.doPhase(kp1.getPublic(), true);
+ byte[] secret2 = ka2.generateSecret();
+
+ // With related keypairs, generated KeyAgreement secret should be same.
+ if (!Arrays.equals(secret1, secret2)) {
+ fail("KeyAgreement secret mismatch.");
+ }
+ }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/security/KeyAgreement/NegativeTest.java b/ojluni/src/test/java/security/KeyAgreement/NegativeTest.java
new file mode 100644
index 0000000..5f97d1c
--- /dev/null
+++ b/ojluni/src/test/java/security/KeyAgreement/NegativeTest.java
@@ -0,0 +1,387 @@
+/*
+ * Copyright (c) 2018, 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 8200219
+ * @summary Negative tests for Key related Test with DiffieHellman, ECDH, XDH.
+ * It Tests,
+ * Use modified encoding while generating Public/Private Keys
+ * Short, long, unsupported keysize
+ * Invalid Algo names including Null
+ * Invalid provider names including Null
+ * Invalid curve names
+ * Invalid spec usage
+ * Arguments order <KeyExchangeAlgorithm> <Provider> <KeyGenAlgorithm>
+ * <keySize> <Curve*>
+ * @library /test/lib
+ * @run main NegativeTest DiffieHellman SunJCE DiffieHellman 1024
+ * @run main NegativeTest ECDH SunEC EC 256
+ * @run main NegativeTest XDH SunEC XDH 255 X25519
+ * @run main NegativeTest XDH SunEC XDH 448 X448
+ */
+package test.java.security.KeyAgreement;
+
+import java.math.BigInteger;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidParameterException;
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Security;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.NamedParameterSpec;
+import java.security.spec.KeySpec;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.security.spec.XECPrivateKeySpec;
+import java.security.spec.XECPublicKeySpec;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.crypto.KeyAgreement;
+import org.testng.annotations.Test;
+import static org.junit.Assert.fail;
+
+public class NegativeTest {
+
+ @Test
+ public void testDHNegative() throws Exception {
+ String kaAlgo = "DiffieHellman";
+ String provider = "BC";
+ String kpgAlgo = "DiffieHellman";
+ int keySize = 1024;
+ String kpgInit = "DiffieHellman";
+ testModifiedKeyEncodingTest(provider, kpgAlgo, kpgInit);
+ testInvalidKeyLen(provider, kaAlgo, kpgAlgo, kpgInit);
+ testInvalidKpgAlgo(provider, kaAlgo, keySize);
+ testInvalidKaAlgo(provider, kpgAlgo, keySize);
+ testInvalidProvider(kaAlgo, kpgAlgo, keySize);
+ }
+
+ @Test
+ public void testECDHNegative() throws Exception {
+ String kaAlgo = "ECDH";
+ String provider = "AndroidOpenSSL";
+ String kpgAlgo = "EC";
+ int keySize = 256;
+ String kpgInit = "EC";
+ testModifiedKeyEncodingTest(provider, kpgAlgo, kpgInit);
+ testInvalidKeyLen(provider, kaAlgo, kpgAlgo, kpgInit);
+ testInvalidKpgAlgo(provider, kaAlgo, keySize);
+ testInvalidKaAlgo(provider, kpgAlgo, keySize);
+ testInvalidProvider(kaAlgo, kpgAlgo, keySize);
+ testNamedParameter(provider, kpgAlgo);
+ }
+
+ // BEGIN Android-removed: XDH is not yet supported
+ /*
+ @Test
+ public void testXDHNegative() throws Exception {
+ String kaAlgo = "XDH";
+ String provider = "AndroidOpenSSL";
+ String kpgAlgo = "XDH";
+ List<Integer> keySizes = Arrays.asList(256, 448);
+ List<String> kpgInits = Arrays.asList("X25519", "X448");
+ for (int i = 0; i < keySizes.size(); i++){
+ testModifiedKeyEncodingTest(provider, kpgAlgo, kpgInits.get(i));
+ testInvalidKeyLen(provider, kaAlgo, kpgAlgo, kpgInits.get(i));
+ testInvalidKpgAlgo(provider, kaAlgo, keySizes.get(i));
+ testInvalidKaAlgo(provider, kpgAlgo, keySizes.get(i));
+ testInvalidProvider(kaAlgo, kpgAlgo, keySizes.get(i));
+ testInvalidSpec(provider, kpgAlgo, kpgInits.get(i));
+ testInCompatibleSpec(provider, kpgAlgo, kpgInits.get(i));
+ }
+ testNamedParameter(provider, kpgAlgo);
+ }
+ */
+ // END Android-removed: XDH is not yet supported
+
+ /**
+ * Generate keyPair based on KeyPairGenerator algorithm.
+ */
+ private static KeyPair genKeyPair(String provider, String kpgAlgo,
+ String kpgInit) throws Exception {
+
+ KeyPairGenerator kpg = KeyPairGenerator.getInstance(kpgAlgo,
+ Security.getProvider(provider));
+ switch (kpgInit) {
+ case "DiffieHellman":
+ kpg.initialize(512);
+ break;
+ case "EC":
+ kpg.initialize(256);
+ break;
+ case "X25519":
+ kpg.initialize(255);
+ break;
+ case "X448":
+ kpg.initialize(448);
+ break;
+ default:
+ fail("Invalid Algo name " + kpgInit);
+ }
+ return kpg.generateKeyPair();
+ }
+
+ private static void testModifiedKeyEncodingTest(String provider,
+ String kpgAlgo, String kpgInit) throws Exception {
+
+ KeyFactory kf = KeyFactory.getInstance(kpgAlgo, provider);
+ KeyPair kp = genKeyPair(provider, kpgAlgo, kpgInit);
+ // Test modified PrivateKey encoding
+ byte[] encoded = kp.getPrivate().getEncoded();
+ byte[] modified = modifyEncoded(encoded);
+ PKCS8EncodedKeySpec priSpec = new PKCS8EncodedKeySpec(modified);
+ try {
+ // Generate PrivateKey with modified encoding
+ kf.generatePrivate(priSpec);
+ fail("testModifiedKeyTest should fail but passed.");
+ } catch (InvalidKeySpecException e) {
+ }
+ // Test modified PublicKey encoding
+ encoded = kp.getPublic().getEncoded();
+ modified = modifyEncoded(encoded);
+ X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(modified);
+ try {
+ // Generate PublicKey with modified encoding
+ kf.generatePublic(pubSpec);
+ fail("testModifiedKeyTest should fail but passed.");
+ } catch (InvalidKeySpecException e) {
+ }
+ }
+
+ /**
+ * Test with all Invalid key length.
+ */
+ private static void testInvalidKeyLen(String provider, String kaAlgo,
+ String kpgAlgo, String kpgInit) throws Exception {
+
+ for (int keySize : selectInvalidKeylength(kpgInit)) {
+ try {
+ startKeyAgreement(provider, kaAlgo, kpgAlgo, keySize);
+ fail("testInvalidKeyLen should fail but passed: " + kaAlgo + ", " + Integer.toString(keySize));
+ } catch (InvalidParameterException e) {
+ } catch (IllegalArgumentException e) {
+ }
+ }
+ }
+
+ /**
+ * Test with all Invalid KeyPairGenerator algorithms.
+ */
+ private static void testInvalidKpgAlgo(String provider, String algo,
+ int keySize) throws Exception {
+
+ for (String kpgAlgo : new String[]{null, " ", "", "NoSuchAlgorithm"}) {
+ try {
+ startKeyAgreement(provider, algo, kpgAlgo, keySize);
+ fail("testInvalidKpgAlgo should fail but passed.");
+ } catch (NoSuchAlgorithmException e) {
+ } catch (NullPointerException e) {
+ if (kpgAlgo == null) {
+ continue;
+ }
+ fail("Unknown failure in testInvalidKpgAlgo.");
+ }
+ }
+ }
+
+ /**
+ * Test with all Invalid KeyAgreement algorithms.
+ */
+ private static void testInvalidKaAlgo(String provider, String kpgAlgo,
+ int keySize) throws Exception {
+
+ for (String algo : new String[]{null, " ", "", "NoSuchAlgorithm"}) {
+ try {
+ startKeyAgreement(provider, algo, kpgAlgo, keySize);
+ fail("testInvalidKaAlgo should fail but passed.");
+ } catch (NoSuchAlgorithmException e) {
+ } catch (NullPointerException e) {
+ if (algo == null) {
+ continue;
+ }
+ fail("Unknown failure in testInvalidKaAlgo.");
+ }
+ }
+ }
+
+ /**
+ * Test with all Invalid Provider names.
+ */
+ private static void testInvalidProvider(String kaAlgo, String kpgAlgo,
+ int keySize) throws Exception {
+
+ for (String provider : new String[]{null, " ", "", "NoSuchProvider"}) {
+ try {
+ startKeyAgreement(provider, kaAlgo, kpgAlgo, keySize);
+ fail("testInvalidProvider should fail but passed.");
+ } catch (NoSuchProviderException e) {
+ } catch (IllegalArgumentException e) {
+ }
+ }
+ }
+
+ /**
+ * Test for (in)valid curve names as argument to NamedParameterSpec
+ */
+ private static void testNamedParameter(String provider, String kpgAlgo)
+ throws Exception {
+
+ for (String name : new String[]{null, " ", "", "NoSuchCurve"}) {
+ try {
+ NamedParameterSpec spec = new NamedParameterSpec(name);
+ KeyPairGenerator kpg
+ = KeyPairGenerator.getInstance(kpgAlgo, provider);
+ kpg.initialize(spec);
+ kpg.generateKeyPair();
+ fail("testNamedParameter should fail but passed.");
+ } catch (NullPointerException e) {
+ if (name == null) {
+ continue;
+ }
+ fail("Unknown failure in testNamedParameter.");
+ } catch (InvalidAlgorithmParameterException e) {
+ }
+ }
+ }
+
+ /**
+ * Test to generate Public/Private keys using (in)valid coordinate/scalar.
+ */
+ private static void testInvalidSpec(String provider,
+ String kpgAlgo, String curve) throws Exception {
+
+ NamedParameterSpec spec = new NamedParameterSpec(curve);
+ KeyFactory kf = KeyFactory.getInstance(kpgAlgo, provider);
+ int validLen = curve.equalsIgnoreCase("X448") ? 56 : 32;
+ for (byte[] scalarBytes : new byte[][]{null, new byte[]{},
+ new byte[32], new byte[56], new byte[65535]}) {
+ try {
+ KeySpec privateSpec = new XECPrivateKeySpec(spec, scalarBytes);
+ kf.generatePrivate(privateSpec);
+ if (scalarBytes.length != validLen) {
+ fail(String.format("testInvalidSpec "
+ + "should fail but passed when Scalar bytes length "
+ + "!= %s for curve %s", validLen, curve));
+ }
+ } catch (NullPointerException e) {
+ if (scalarBytes == null) {
+ continue;
+ }
+ fail(e.getMessage());
+ } catch (InvalidKeySpecException e) {
+ if (scalarBytes.length != validLen) {
+ continue;
+ }
+ fail(e.getMessage());
+ }
+ }
+ for (BigInteger coordinate : new BigInteger[]{null, BigInteger.ZERO,
+ BigInteger.ONE, new BigInteger("2").pow(255),
+ new BigInteger("2").pow(448)}) {
+ try {
+ KeySpec publicSpec = new XECPublicKeySpec(spec, coordinate);
+ kf.generatePublic(publicSpec);
+ } catch (NullPointerException e) {
+ if (coordinate == null) {
+ continue;
+ }
+ fail(e.getMessage());
+ }
+ }
+ }
+
+ private static void testInCompatibleSpec(String provider,
+ String kpgAlgo, String curve) throws Exception {
+
+ int validLen = curve.equalsIgnoreCase("X448") ? 56 : 32;
+ NamedParameterSpec spec = new NamedParameterSpec(curve);
+ KeyFactory kf = KeyFactory.getInstance(kpgAlgo, provider);
+ KeySpec privateSpec = new XECPrivateKeySpec(spec, new byte[validLen]);
+ KeySpec publicSpec = new XECPublicKeySpec(spec, BigInteger.ONE);
+ try {
+ kf.generatePrivate(publicSpec);
+ fail("testInCompatibleSpec should fail but passed.");
+ } catch (InvalidKeySpecException e) {
+ }
+ try {
+ kf.generatePublic(privateSpec);
+ fail("testInCompatibleSpec should fail but passed.");
+ } catch (InvalidKeySpecException e) {
+ }
+ }
+
+ /**
+ * Perform KeyAgreement operation.
+ */
+ private static void startKeyAgreement(String provider, String kaAlgo,
+ String kpgAlgo, int keySize) throws Exception {
+
+ KeyPairGenerator kpg = KeyPairGenerator.getInstance(kpgAlgo, provider);
+ kpg.initialize(keySize);
+ KeyPair kp = kpg.generateKeyPair();
+ KeyAgreement ka = KeyAgreement.getInstance(kaAlgo, provider);
+ ka.init(kp.getPrivate());
+ ka.doPhase(kp.getPublic(), true);
+ ka.generateSecret();
+ }
+
+ /**
+ * Return manipulated encoded bytes.
+ */
+ private static byte[] modifyEncoded(byte[] encoded) {
+
+ byte[] copy = Arrays.copyOf(encoded, encoded.length);
+ for (int i = 0; i < copy.length; i++) {
+ copy[i] = (byte) ~copy[i];
+ }
+ return copy;
+ }
+
+ /**
+ * Select invalid key sizes for different Key generation algorithms.
+ */
+ private static int[] selectInvalidKeylength(String kpgInit) {
+
+ int[] keySize = new int[]{};
+ switch (kpgInit) {
+ case "DiffieHellman":
+ keySize = new int[]{100};
+ break;
+ case "EC":
+ case "X25519":
+ keySize = new int[]{100, 300};
+ break;
+ case "X448":
+ keySize = new int[]{100, 500};
+ break;
+ default:
+ fail("Invalid Algo name " + kpgInit);
+ }
+ return keySize;
+ }
+}
\ No newline at end of file
diff --git a/openjdk_java_files.bp b/openjdk_java_files.bp
index c7ef870..3f1005e 100644
--- a/openjdk_java_files.bp
+++ b/openjdk_java_files.bp
@@ -620,6 +620,9 @@
"ojluni/src/main/java/java/security/interfaces/ECKey.java",
"ojluni/src/main/java/java/security/interfaces/ECPrivateKey.java",
"ojluni/src/main/java/java/security/interfaces/ECPublicKey.java",
+ "ojluni/src/main/java/java/security/interfaces/EdECKey.java",
+ "ojluni/src/main/java/java/security/interfaces/EdECPrivateKey.java",
+ "ojluni/src/main/java/java/security/interfaces/EdECPublicKey.java",
"ojluni/src/main/java/java/security/interfaces/RSAKey.java",
"ojluni/src/main/java/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java",
"ojluni/src/main/java/java/security/interfaces/RSAPrivateCrtKey.java",
@@ -678,13 +681,16 @@
"ojluni/src/main/java/java/security/spec/DSAPrivateKeySpec.java",
"ojluni/src/main/java/java/security/spec/DSAPublicKeySpec.java",
"ojluni/src/main/java/java/security/spec/ECFieldF2m.java",
- "ojluni/src/main/java/java/security/spec/ECFieldFp.java",
"ojluni/src/main/java/java/security/spec/ECField.java",
+ "ojluni/src/main/java/java/security/spec/ECFieldFp.java",
"ojluni/src/main/java/java/security/spec/ECGenParameterSpec.java",
"ojluni/src/main/java/java/security/spec/ECParameterSpec.java",
"ojluni/src/main/java/java/security/spec/ECPoint.java",
"ojluni/src/main/java/java/security/spec/ECPrivateKeySpec.java",
"ojluni/src/main/java/java/security/spec/ECPublicKeySpec.java",
+ "ojluni/src/main/java/java/security/spec/EdECPoint.java",
+ "ojluni/src/main/java/java/security/spec/EdECPrivateKeySpec.java",
+ "ojluni/src/main/java/java/security/spec/EdECPublicKeySpec.java",
"ojluni/src/main/java/java/security/spec/EllipticCurve.java",
"ojluni/src/main/java/java/security/spec/EncodedKeySpec.java",
"ojluni/src/main/java/java/security/spec/InvalidKeySpecException.java",