mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
Merge
This commit is contained in:
commit
f605407e30
1110 changed files with 30242 additions and 8878 deletions
|
@ -25,6 +25,11 @@
|
|||
|
||||
package java.lang;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.ObjectStreamField;
|
||||
|
||||
/**
|
||||
* Thrown when an application tries to load in a class through its
|
||||
* string name using:
|
||||
|
@ -56,15 +61,6 @@ public class ClassNotFoundException extends ReflectiveOperationException {
|
|||
*/
|
||||
private static final long serialVersionUID = 9176873029745254542L;
|
||||
|
||||
/**
|
||||
* This field holds the exception ex if the
|
||||
* ClassNotFoundException(String s, Throwable ex) constructor was
|
||||
* used to instantiate the object
|
||||
* @serial
|
||||
* @since 1.2
|
||||
*/
|
||||
private Throwable ex;
|
||||
|
||||
/**
|
||||
* Constructs a <code>ClassNotFoundException</code> with no detail message.
|
||||
*/
|
||||
|
@ -92,8 +88,7 @@ public class ClassNotFoundException extends ReflectiveOperationException {
|
|||
* @since 1.2
|
||||
*/
|
||||
public ClassNotFoundException(String s, Throwable ex) {
|
||||
super(s, null); // Disallow initCause
|
||||
this.ex = ex;
|
||||
super(s, ex); // Disallow initCause
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -108,18 +103,42 @@ public class ClassNotFoundException extends ReflectiveOperationException {
|
|||
* @since 1.2
|
||||
*/
|
||||
public Throwable getException() {
|
||||
return ex;
|
||||
return super.getCause();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cause of this exception (the exception that was raised
|
||||
* if an error occurred while attempting to load the class; otherwise
|
||||
* {@code null}).
|
||||
* Serializable fields for ClassNotFoundException.
|
||||
*
|
||||
* @return the cause of this exception.
|
||||
* @since 1.4
|
||||
* @serialField ex Throwable
|
||||
*/
|
||||
public Throwable getCause() {
|
||||
return ex;
|
||||
private static final ObjectStreamField[] serialPersistentFields = {
|
||||
new ObjectStreamField("ex", Throwable.class)
|
||||
};
|
||||
|
||||
/*
|
||||
* Reconstitutes the ClassNotFoundException instance from a stream
|
||||
* and initialize the cause properly when deserializing from an older
|
||||
* version.
|
||||
*
|
||||
* The getException and getCause method returns the private "ex" field
|
||||
* in the older implementation and ClassNotFoundException::cause
|
||||
* was set to null.
|
||||
*/
|
||||
private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
|
||||
ObjectInputStream.GetField fields = s.readFields();
|
||||
Throwable exception = (Throwable) fields.get("ex", null);
|
||||
if (exception != null) {
|
||||
setCause(exception);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* To maintain compatibility with older implementation, write a serial
|
||||
* "ex" field with the cause as the value.
|
||||
*/
|
||||
private void writeObject(ObjectOutputStream out) throws IOException {
|
||||
ObjectOutputStream.PutField fields = out.putFields();
|
||||
fields.put("ex", super.getCause());
|
||||
out.writeFields();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,11 @@
|
|||
|
||||
package java.lang;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.ObjectStreamField;
|
||||
|
||||
/**
|
||||
* Signals that an unexpected exception has occurred in a static initializer.
|
||||
* An <code>ExceptionInInitializerError</code> is thrown to indicate that an
|
||||
|
@ -47,16 +52,6 @@ public class ExceptionInInitializerError extends LinkageError {
|
|||
*/
|
||||
private static final long serialVersionUID = 1521711792217232256L;
|
||||
|
||||
/**
|
||||
* This field holds the exception if the
|
||||
* ExceptionInInitializerError(Throwable thrown) constructor was
|
||||
* used to instantiate the object
|
||||
*
|
||||
* @serial
|
||||
*
|
||||
*/
|
||||
private Throwable exception;
|
||||
|
||||
/**
|
||||
* Constructs an <code>ExceptionInInitializerError</code> with
|
||||
* <code>null</code> as its detail message string and with no saved
|
||||
|
@ -64,7 +59,7 @@ public class ExceptionInInitializerError extends LinkageError {
|
|||
* A detail message is a String that describes this particular exception.
|
||||
*/
|
||||
public ExceptionInInitializerError() {
|
||||
initCause(null); // Disallow subsequent initCause
|
||||
initCause(null); // Disallow subsequent initCause
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -76,23 +71,20 @@ public class ExceptionInInitializerError extends LinkageError {
|
|||
* @param thrown The exception thrown
|
||||
*/
|
||||
public ExceptionInInitializerError(Throwable thrown) {
|
||||
initCause(null); // Disallow subsequent initCause
|
||||
this.exception = thrown;
|
||||
super(null, thrown); // Disallow subsequent initCause
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an ExceptionInInitializerError with the specified detail
|
||||
* Constructs an {@code ExceptionInInitializerError} with the specified detail
|
||||
* message string. A detail message is a String that describes this
|
||||
* particular exception. The detail message string is saved for later
|
||||
* retrieval by the {@link Throwable#getMessage()} method. There is no
|
||||
* saved throwable object.
|
||||
*
|
||||
*
|
||||
* @param s the detail message
|
||||
*/
|
||||
public ExceptionInInitializerError(String s) {
|
||||
super(s);
|
||||
initCause(null); // Disallow subsequent initCause
|
||||
super(s, null); // Disallow subsequent initCause
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -109,18 +101,43 @@ public class ExceptionInInitializerError extends LinkageError {
|
|||
* throwable object.
|
||||
*/
|
||||
public Throwable getException() {
|
||||
return exception;
|
||||
return super.getCause();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cause of this error (the exception that occurred
|
||||
* during a static initialization that caused this error to be created).
|
||||
* Serializable fields for ExceptionInInitializerError.
|
||||
*
|
||||
* @return the cause of this error or <code>null</code> if the
|
||||
* cause is nonexistent or unknown.
|
||||
* @since 1.4
|
||||
* @serialField exception Throwable
|
||||
*/
|
||||
public Throwable getCause() {
|
||||
return exception;
|
||||
private static final ObjectStreamField[] serialPersistentFields = {
|
||||
new ObjectStreamField("exception", Throwable.class)
|
||||
};
|
||||
|
||||
/*
|
||||
* Reconstitutes the ExceptionInInitializerError instance from a stream
|
||||
* and initialize the cause properly when deserializing from an older
|
||||
* version.
|
||||
*
|
||||
* The getException and getCause method returns the private "exception"
|
||||
* field in the older implementation and ExceptionInInitializerError::cause
|
||||
* was set to null.
|
||||
*/
|
||||
private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
|
||||
ObjectInputStream.GetField fields = s.readFields();
|
||||
Throwable exception = (Throwable) fields.get("exception", null);
|
||||
if (exception != null) {
|
||||
setCause(exception);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* To maintain compatibility with older implementation, write a serial
|
||||
* "exception" field with the cause as the value.
|
||||
*/
|
||||
private void writeObject(ObjectOutputStream out) throws IOException {
|
||||
ObjectOutputStream.PutField fields = out.putFields();
|
||||
fields.put("exception", super.getCause());
|
||||
out.writeFields();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2201,6 +2201,9 @@ public final class System {
|
|||
return StringCoding.getBytesUTF8NoRepl(s);
|
||||
}
|
||||
|
||||
public void setCause(Throwable t, Throwable cause) {
|
||||
t.setCause(cause);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -466,6 +466,16 @@ public class Throwable implements Serializable {
|
|||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called by readObject of a few exceptions such as
|
||||
* ClassNotFoundException and ExceptionInInitializerError to deserialize
|
||||
* a stream output from an older runtime version where the cause may
|
||||
* have set to null.
|
||||
*/
|
||||
final void setCause(Throwable t) {
|
||||
this.cause = t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a short description of this throwable.
|
||||
* The result is the concatenation of:
|
||||
|
|
|
@ -54,6 +54,7 @@ import java.util.BitSet;
|
|||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
@ -643,6 +644,10 @@ public class MethodHandles {
|
|||
/** The allowed sorts of members which may be looked up (PUBLIC, etc.). */
|
||||
private final int allowedModes;
|
||||
|
||||
static {
|
||||
Reflection.registerFieldsToFilter(Lookup.class, Set.of("lookupClass", "allowedModes"));
|
||||
}
|
||||
|
||||
/** A single-bit mask representing {@code public} access,
|
||||
* which may contribute to the result of {@link #lookupModes lookupModes}.
|
||||
* The value, {@code 0x01}, happens to be the same as the value of the
|
||||
|
|
|
@ -25,6 +25,12 @@
|
|||
|
||||
package java.lang.reflect;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.ObjectStreamField;
|
||||
import jdk.internal.misc.SharedSecrets;
|
||||
|
||||
/**
|
||||
* Thrown by a method invocation on a proxy instance if its invocation
|
||||
* handler's {@link InvocationHandler#invoke invoke} method throws a
|
||||
|
@ -58,12 +64,6 @@ package java.lang.reflect;
|
|||
public class UndeclaredThrowableException extends RuntimeException {
|
||||
static final long serialVersionUID = 330127114055056639L;
|
||||
|
||||
/**
|
||||
* the undeclared checked exception that was thrown
|
||||
* @serial
|
||||
*/
|
||||
private Throwable undeclaredThrowable;
|
||||
|
||||
/**
|
||||
* Constructs an {@code UndeclaredThrowableException} with the
|
||||
* specified {@code Throwable}.
|
||||
|
@ -72,8 +72,7 @@ public class UndeclaredThrowableException extends RuntimeException {
|
|||
* that was thrown
|
||||
*/
|
||||
public UndeclaredThrowableException(Throwable undeclaredThrowable) {
|
||||
super((Throwable) null); // Disallow initCause
|
||||
this.undeclaredThrowable = undeclaredThrowable;
|
||||
super(null, undeclaredThrowable); // Disallow initCause
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -87,8 +86,7 @@ public class UndeclaredThrowableException extends RuntimeException {
|
|||
public UndeclaredThrowableException(Throwable undeclaredThrowable,
|
||||
String s)
|
||||
{
|
||||
super(s, null); // Disallow initCause
|
||||
this.undeclaredThrowable = undeclaredThrowable;
|
||||
super(s, undeclaredThrowable); // Disallow initCause
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -102,18 +100,38 @@ public class UndeclaredThrowableException extends RuntimeException {
|
|||
* @return the undeclared checked exception that was thrown
|
||||
*/
|
||||
public Throwable getUndeclaredThrowable() {
|
||||
return undeclaredThrowable;
|
||||
return super.getCause();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cause of this exception (the {@code Throwable}
|
||||
* instance wrapped in this {@code UndeclaredThrowableException},
|
||||
* which may be {@code null}).
|
||||
* Serializable fields for UndeclaredThrowableException.
|
||||
*
|
||||
* @return the cause of this exception.
|
||||
* @since 1.4
|
||||
* @serialField undeclaredThrowable Throwable
|
||||
*/
|
||||
public Throwable getCause() {
|
||||
return undeclaredThrowable;
|
||||
private static final ObjectStreamField[] serialPersistentFields = {
|
||||
new ObjectStreamField("undeclaredThrowable", Throwable.class)
|
||||
};
|
||||
|
||||
/*
|
||||
* Reconstitutes the UndeclaredThrowableException instance from a stream
|
||||
* and initialize the cause properly when deserializing from an older
|
||||
* version.
|
||||
*/
|
||||
private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
|
||||
ObjectInputStream.GetField fields = s.readFields();
|
||||
Throwable exception = (Throwable) fields.get("undeclaredThrowable", null);
|
||||
if (exception != null) {
|
||||
SharedSecrets.getJavaLangAccess().setCause(this, exception);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* To maintain compatibility with older implementation, write a serial
|
||||
* "ex" field with the cause as the value.
|
||||
*/
|
||||
private void writeObject(ObjectOutputStream out) throws IOException {
|
||||
ObjectOutputStream.PutField fields = out.putFields();
|
||||
fields.put("undeclaredThrowable", super.getCause());
|
||||
out.writeFields();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 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
|
||||
|
@ -93,7 +93,7 @@
|
|||
* <p> The {@link java.nio.file.attribute.DosFileAttributeView}
|
||||
* class extends {@code BasicFileAttributeView} by defining methods to
|
||||
* access the legacy "DOS" file attributes supported on file systems such as File
|
||||
* Allocation Tabl (FAT), commonly used in consumer devices.
|
||||
* Allocation Table (FAT), commonly used in consumer devices.
|
||||
*
|
||||
* <p> The {@link java.nio.file.attribute.AclFileAttributeView}
|
||||
* class defines methods to read and write the Access Control List (ACL)
|
||||
|
|
|
@ -25,6 +25,12 @@
|
|||
|
||||
package java.security;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.ObjectStreamField;
|
||||
import jdk.internal.misc.SharedSecrets;
|
||||
|
||||
/**
|
||||
* This exception is thrown by
|
||||
* {@code doPrivileged(PrivilegedExceptionAction)} and
|
||||
|
@ -52,11 +58,6 @@ public class PrivilegedActionException extends Exception {
|
|||
// use serialVersionUID from JDK 1.2.2 for interoperability
|
||||
private static final long serialVersionUID = 4724086851538908602L;
|
||||
|
||||
/**
|
||||
* @serial
|
||||
*/
|
||||
private Exception exception;
|
||||
|
||||
/**
|
||||
* Constructs a new PrivilegedActionException "wrapping"
|
||||
* the specific Exception.
|
||||
|
@ -64,8 +65,7 @@ public class PrivilegedActionException extends Exception {
|
|||
* @param exception The exception thrown
|
||||
*/
|
||||
public PrivilegedActionException(Exception exception) {
|
||||
super((Throwable)null); // Disallow initCause
|
||||
this.exception = exception;
|
||||
super(null, exception); // Disallow initCause
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -84,23 +84,49 @@ public class PrivilegedActionException extends Exception {
|
|||
* AccessControlContext)
|
||||
*/
|
||||
public Exception getException() {
|
||||
return exception;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cause of this exception (the exception thrown by
|
||||
* the privileged computation that resulted in this
|
||||
* {@code PrivilegedActionException}).
|
||||
*
|
||||
* @return the cause of this exception.
|
||||
* @since 1.4
|
||||
*/
|
||||
public Throwable getCause() {
|
||||
return exception;
|
||||
return (Exception)super.getCause();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String s = getClass().getName();
|
||||
return (exception != null) ? (s + ": " + exception.toString()) : s;
|
||||
Throwable cause = super.getCause();
|
||||
return (cause != null) ? (s + ": " + cause.toString()) : s;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializable fields for UndeclaredThrowableException.
|
||||
*
|
||||
* @serialField undeclaredThrowable Throwable
|
||||
*/
|
||||
private static final ObjectStreamField[] serialPersistentFields = {
|
||||
new ObjectStreamField("exception", Exception.class)
|
||||
};
|
||||
|
||||
/*
|
||||
* Reconstitutes the PrivilegedActionException instance from a stream
|
||||
* and initialize the cause properly when deserializing from an older
|
||||
* version.
|
||||
*
|
||||
* The getException and getCause method returns the private "exception"
|
||||
* field in the older implementation and PrivilegedActionException::cause
|
||||
* was set to null.
|
||||
*/
|
||||
private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
|
||||
ObjectInputStream.GetField fields = s.readFields();
|
||||
Exception exception = (Exception) fields.get("exception", null);
|
||||
if (exception != null) {
|
||||
SharedSecrets.getJavaLangAccess().setCause(this, exception);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* To maintain compatibility with older implementation, write a serial
|
||||
* "exception" field with the cause as the value.
|
||||
*/
|
||||
private void writeObject(ObjectOutputStream out) throws IOException {
|
||||
ObjectOutputStream.PutField fields = out.putFields();
|
||||
fields.put("exception", super.getCause());
|
||||
out.writeFields();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 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
|
||||
|
@ -112,7 +112,7 @@ public abstract class SSLServerSocketFactory extends ServerSocketFactory
|
|||
|
||||
try {
|
||||
return SSLContext.getDefault().getServerSocketFactory();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
} catch (NoSuchAlgorithmException | UnsupportedOperationException e) {
|
||||
return new DefaultSSLServerSocketFactory(e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 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
|
||||
|
@ -121,7 +121,7 @@ public abstract class SSLSocketFactory extends SocketFactory
|
|||
|
||||
try {
|
||||
return SSLContext.getDefault().getSocketFactory();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
} catch (NoSuchAlgorithmException | UnsupportedOperationException e) {
|
||||
return new DefaultSSLSocketFactory(e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -305,4 +305,10 @@ public interface JavaLangAccess {
|
|||
* @throws IllegalArgumentException for malformed surrogates
|
||||
*/
|
||||
byte[] getBytesUTF8NoRepl(String s);
|
||||
|
||||
/**
|
||||
* Set the cause of Throwable
|
||||
* @param cause set t's cause to new value
|
||||
*/
|
||||
void setCause(Throwable t, Throwable cause);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 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
|
||||
|
@ -26,6 +26,7 @@
|
|||
package jdk.internal.reflect;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.Set;
|
||||
|
||||
/** Provides reflective access to the constant pools of classes.
|
||||
Currently this is needed to provide reflective access to annotations
|
||||
|
@ -104,7 +105,7 @@ public class ConstantPool {
|
|||
//
|
||||
|
||||
static {
|
||||
Reflection.registerFieldsToFilter(ConstantPool.class, new String[] { "constantPoolOop" });
|
||||
Reflection.registerFieldsToFilter(ConstantPool.class, Set.of("constantPoolOop"));
|
||||
}
|
||||
|
||||
// HotSpot-internal constant pool object (set by the VM, name known to the VM)
|
||||
|
|
|
@ -25,13 +25,12 @@
|
|||
|
||||
package jdk.internal.reflect;
|
||||
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import jdk.internal.HotSpotIntrinsicCandidate;
|
||||
import jdk.internal.loader.ClassLoaders;
|
||||
import jdk.internal.misc.VM;
|
||||
|
||||
/** Common utility routines used by both java.lang and
|
||||
|
@ -43,18 +42,23 @@ public class Reflection {
|
|||
view, where they are sensitive or they may contain VM-internal objects.
|
||||
These Maps are updated very rarely. Rather than synchronize on
|
||||
each access, we use copy-on-write */
|
||||
private static volatile Map<Class<?>,String[]> fieldFilterMap;
|
||||
private static volatile Map<Class<?>,String[]> methodFilterMap;
|
||||
private static volatile Map<Class<?>, Set<String>> fieldFilterMap;
|
||||
private static volatile Map<Class<?>, Set<String>> methodFilterMap;
|
||||
private static final String WILDCARD = "*";
|
||||
public static final Set<String> ALL_MEMBERS = Set.of(WILDCARD);
|
||||
|
||||
static {
|
||||
Map<Class<?>,String[]> map = new HashMap<Class<?>,String[]>();
|
||||
map.put(Reflection.class,
|
||||
new String[] {"fieldFilterMap", "methodFilterMap"});
|
||||
map.put(System.class, new String[] {"security"});
|
||||
map.put(Class.class, new String[] {"classLoader"});
|
||||
fieldFilterMap = map;
|
||||
|
||||
methodFilterMap = new HashMap<>();
|
||||
fieldFilterMap = Map.of(
|
||||
Reflection.class, ALL_MEMBERS,
|
||||
AccessibleObject.class, ALL_MEMBERS,
|
||||
Class.class, Set.of("classLoader"),
|
||||
ClassLoader.class, ALL_MEMBERS,
|
||||
Constructor.class, ALL_MEMBERS,
|
||||
Field.class, ALL_MEMBERS,
|
||||
Method.class, ALL_MEMBERS,
|
||||
System.class, Set.of("security")
|
||||
);
|
||||
methodFilterMap = Map.of();
|
||||
}
|
||||
|
||||
/** Returns the class of the caller of the method calling this method,
|
||||
|
@ -236,31 +240,31 @@ public class Reflection {
|
|||
|
||||
// fieldNames must contain only interned Strings
|
||||
public static synchronized void registerFieldsToFilter(Class<?> containingClass,
|
||||
String ... fieldNames) {
|
||||
Set<String> fieldNames) {
|
||||
fieldFilterMap =
|
||||
registerFilter(fieldFilterMap, containingClass, fieldNames);
|
||||
}
|
||||
|
||||
// methodNames must contain only interned Strings
|
||||
public static synchronized void registerMethodsToFilter(Class<?> containingClass,
|
||||
String ... methodNames) {
|
||||
Set<String> methodNames) {
|
||||
methodFilterMap =
|
||||
registerFilter(methodFilterMap, containingClass, methodNames);
|
||||
}
|
||||
|
||||
private static Map<Class<?>,String[]> registerFilter(Map<Class<?>,String[]> map,
|
||||
Class<?> containingClass, String ... names) {
|
||||
private static Map<Class<?>, Set<String>> registerFilter(Map<Class<?>, Set<String>> map,
|
||||
Class<?> containingClass,
|
||||
Set<String> names) {
|
||||
if (map.get(containingClass) != null) {
|
||||
throw new IllegalArgumentException
|
||||
("Filter already registered: " + containingClass);
|
||||
}
|
||||
map = new HashMap<Class<?>,String[]>(map);
|
||||
map.put(containingClass, names);
|
||||
map = new HashMap<>(map);
|
||||
map.put(containingClass, Set.copyOf(names));
|
||||
return map;
|
||||
}
|
||||
|
||||
public static Field[] filterFields(Class<?> containingClass,
|
||||
Field[] fields) {
|
||||
public static Field[] filterFields(Class<?> containingClass, Field[] fields) {
|
||||
if (fieldFilterMap == null) {
|
||||
// Bootstrapping
|
||||
return fields;
|
||||
|
@ -276,35 +280,24 @@ public class Reflection {
|
|||
return (Method[])filter(methods, methodFilterMap.get(containingClass));
|
||||
}
|
||||
|
||||
private static Member[] filter(Member[] members, String[] filteredNames) {
|
||||
private static Member[] filter(Member[] members, Set<String> filteredNames) {
|
||||
if ((filteredNames == null) || (members.length == 0)) {
|
||||
return members;
|
||||
}
|
||||
Class<?> memberType = members[0].getClass();
|
||||
if (filteredNames.contains(WILDCARD)) {
|
||||
return (Member[]) Array.newInstance(memberType, 0);
|
||||
}
|
||||
int numNewMembers = 0;
|
||||
for (Member member : members) {
|
||||
boolean shouldSkip = false;
|
||||
for (String filteredName : filteredNames) {
|
||||
if (member.getName() == filteredName) {
|
||||
shouldSkip = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!shouldSkip) {
|
||||
if (!filteredNames.contains(member.getName())) {
|
||||
++numNewMembers;
|
||||
}
|
||||
}
|
||||
Member[] newMembers =
|
||||
(Member[])Array.newInstance(members[0].getClass(), numNewMembers);
|
||||
Member[] newMembers = (Member[])Array.newInstance(memberType, numNewMembers);
|
||||
int destIdx = 0;
|
||||
for (Member member : members) {
|
||||
boolean shouldSkip = false;
|
||||
for (String filteredName : filteredNames) {
|
||||
if (member.getName() == filteredName) {
|
||||
shouldSkip = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!shouldSkip) {
|
||||
if (!filteredNames.contains(member.getName())) {
|
||||
newMembers[destIdx++] = member;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 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
|
||||
|
@ -28,6 +28,8 @@ package jdk.internal.reflect;
|
|||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.security.AccessController;
|
||||
import java.util.Set;
|
||||
|
||||
import jdk.internal.misc.Unsafe;
|
||||
|
||||
/** Base class for jdk.internal.misc.Unsafe-based FieldAccessors for static
|
||||
|
@ -40,7 +42,7 @@ import jdk.internal.misc.Unsafe;
|
|||
abstract class UnsafeStaticFieldAccessorImpl extends UnsafeFieldAccessorImpl {
|
||||
static {
|
||||
Reflection.registerFieldsToFilter(UnsafeStaticFieldAccessorImpl.class,
|
||||
new String[] { "base" });
|
||||
Set.of("base"));
|
||||
}
|
||||
|
||||
protected final Object base; // base
|
||||
|
|
|
@ -70,6 +70,9 @@ enum CipherSuite {
|
|||
TLS_AES_256_GCM_SHA384(
|
||||
0x1302, true, "TLS_AES_256_GCM_SHA384",
|
||||
ProtocolVersion.PROTOCOLS_OF_13, B_AES_256_GCM_IV, H_SHA384),
|
||||
TLS_CHACHA20_POLY1305_SHA256(
|
||||
0x1303, true, "TLS_CHACHA20_POLY1305_SHA256",
|
||||
ProtocolVersion.PROTOCOLS_OF_13, B_CC20_P1305, H_SHA256),
|
||||
|
||||
// Suite B compliant cipher suites, see RFC 6460.
|
||||
//
|
||||
|
@ -87,11 +90,22 @@ enum CipherSuite {
|
|||
ProtocolVersion.PROTOCOLS_OF_12,
|
||||
K_ECDHE_ECDSA, B_AES_128_GCM, M_NULL, H_SHA256),
|
||||
|
||||
// Not suite B, but we want it to position the suite early in the list
|
||||
// of 1.2 suites.
|
||||
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256(
|
||||
0xCCA9, true, "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", "",
|
||||
ProtocolVersion.PROTOCOLS_OF_12,
|
||||
K_ECDHE_ECDSA, B_CC20_P1305, M_NULL, H_SHA256),
|
||||
|
||||
// AES_256(GCM)
|
||||
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384(
|
||||
0xC030, true, "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "",
|
||||
ProtocolVersion.PROTOCOLS_OF_12,
|
||||
K_ECDHE_RSA, B_AES_256_GCM, M_NULL, H_SHA384),
|
||||
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256(
|
||||
0xCCA8, true, "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", "",
|
||||
ProtocolVersion.PROTOCOLS_OF_12,
|
||||
K_ECDHE_RSA, B_CC20_P1305, M_NULL, H_SHA256),
|
||||
TLS_RSA_WITH_AES_256_GCM_SHA384(
|
||||
0x009D, true, "TLS_RSA_WITH_AES_256_GCM_SHA384", "",
|
||||
ProtocolVersion.PROTOCOLS_OF_12,
|
||||
|
@ -108,6 +122,10 @@ enum CipherSuite {
|
|||
0x009F, true, "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", "",
|
||||
ProtocolVersion.PROTOCOLS_OF_12,
|
||||
K_DHE_RSA, B_AES_256_GCM, M_NULL, H_SHA384),
|
||||
TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256(
|
||||
0xCCAA, true, "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256", "",
|
||||
ProtocolVersion.PROTOCOLS_OF_12,
|
||||
K_DHE_RSA, B_CC20_P1305, M_NULL, H_SHA256),
|
||||
TLS_DHE_DSS_WITH_AES_256_GCM_SHA384(
|
||||
0x00A3, true, "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384", "",
|
||||
ProtocolVersion.PROTOCOLS_OF_12,
|
||||
|
@ -480,8 +498,6 @@ enum CipherSuite {
|
|||
|
||||
// Definition of the CipherSuites that are not supported but the names
|
||||
// are known.
|
||||
TLS_CHACHA20_POLY1305_SHA256( // TLS 1.3
|
||||
"TLS_CHACHA20_POLY1305_SHA256", 0x1303),
|
||||
TLS_AES_128_CCM_SHA256( // TLS 1.3
|
||||
"TLS_AES_128_CCM_SHA256", 0x1304),
|
||||
TLS_AES_128_CCM_8_SHA256( // TLS 1.3
|
||||
|
|
|
@ -129,6 +129,11 @@ final class JsseJce {
|
|||
*/
|
||||
static final String CIPHER_AES_GCM = "AES/GCM/NoPadding";
|
||||
|
||||
/**
|
||||
* JCE transformation string for ChaCha20-Poly1305
|
||||
*/
|
||||
static final String CIPHER_CHACHA20_POLY1305 = "ChaCha20-Poly1305";
|
||||
|
||||
/**
|
||||
* JCA identifier string for DSA, i.e. a DSA with SHA-1.
|
||||
*/
|
||||
|
|
|
@ -329,6 +329,32 @@ enum SSLCipher {
|
|||
new T13GcmWriteCipherGenerator(),
|
||||
ProtocolVersion.PROTOCOLS_OF_13
|
||||
)
|
||||
})),
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
B_CC20_P1305(CIPHER_CHACHA20_POLY1305, AEAD_CIPHER, 32, 32, 12,
|
||||
12, true, false,
|
||||
(Map.Entry<ReadCipherGenerator,
|
||||
ProtocolVersion[]>[])(new Map.Entry[] {
|
||||
new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>(
|
||||
new T12CC20P1305ReadCipherGenerator(),
|
||||
ProtocolVersion.PROTOCOLS_OF_12
|
||||
),
|
||||
new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>(
|
||||
new T13CC20P1305ReadCipherGenerator(),
|
||||
ProtocolVersion.PROTOCOLS_OF_13
|
||||
)
|
||||
}),
|
||||
(Map.Entry<WriteCipherGenerator,
|
||||
ProtocolVersion[]>[])(new Map.Entry[] {
|
||||
new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>(
|
||||
new T12CC20P1305WriteCipherGenerator(),
|
||||
ProtocolVersion.PROTOCOLS_OF_12
|
||||
),
|
||||
new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>(
|
||||
new T13CC20P1305WriteCipherGenerator(),
|
||||
ProtocolVersion.PROTOCOLS_OF_13
|
||||
)
|
||||
}));
|
||||
|
||||
// descriptive name including key size, e.g. AES/128
|
||||
|
@ -2082,6 +2108,549 @@ enum SSLCipher {
|
|||
}
|
||||
}
|
||||
|
||||
private static final class T12CC20P1305ReadCipherGenerator
|
||||
implements ReadCipherGenerator {
|
||||
|
||||
@Override
|
||||
public SSLReadCipher createCipher(SSLCipher sslCipher,
|
||||
Authenticator authenticator, ProtocolVersion protocolVersion,
|
||||
String algorithm, Key key, AlgorithmParameterSpec params,
|
||||
SecureRandom random) throws GeneralSecurityException {
|
||||
return new CC20P1305ReadCipher(authenticator, protocolVersion,
|
||||
sslCipher, algorithm, key, params, random);
|
||||
}
|
||||
|
||||
static final class CC20P1305ReadCipher extends SSLReadCipher {
|
||||
private final Cipher cipher;
|
||||
private final int tagSize;
|
||||
private final Key key;
|
||||
private final byte[] iv;
|
||||
private final SecureRandom random;
|
||||
|
||||
CC20P1305ReadCipher(Authenticator authenticator,
|
||||
ProtocolVersion protocolVersion,
|
||||
SSLCipher sslCipher, String algorithm,
|
||||
Key key, AlgorithmParameterSpec params,
|
||||
SecureRandom random) throws GeneralSecurityException {
|
||||
super(authenticator, protocolVersion);
|
||||
this.cipher = JsseJce.getCipher(algorithm);
|
||||
this.tagSize = sslCipher.tagSize;
|
||||
this.key = key;
|
||||
this.iv = ((IvParameterSpec)params).getIV();
|
||||
this.random = random;
|
||||
|
||||
// DON'T initialize the cipher for AEAD!
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plaintext decrypt(byte contentType, ByteBuffer bb,
|
||||
byte[] sequence) throws GeneralSecurityException {
|
||||
if (bb.remaining() <= tagSize) {
|
||||
throw new BadPaddingException(
|
||||
"Insufficient buffer remaining for AEAD cipher " +
|
||||
"fragment (" + bb.remaining() + "). Needs to be " +
|
||||
"more than tag size (" + tagSize + ")");
|
||||
}
|
||||
|
||||
byte[] sn = sequence;
|
||||
if (sn == null) {
|
||||
sn = authenticator.sequenceNumber();
|
||||
}
|
||||
byte[] nonce = new byte[iv.length];
|
||||
System.arraycopy(sn, 0, nonce, nonce.length - sn.length,
|
||||
sn.length);
|
||||
for (int i = 0; i < nonce.length; i++) {
|
||||
nonce[i] ^= iv[i];
|
||||
}
|
||||
|
||||
// initialize the AEAD cipher with the unique IV
|
||||
AlgorithmParameterSpec spec = new IvParameterSpec(nonce);
|
||||
try {
|
||||
cipher.init(Cipher.DECRYPT_MODE, key, spec, random);
|
||||
} catch (InvalidKeyException |
|
||||
InvalidAlgorithmParameterException ikae) {
|
||||
// unlikely to happen
|
||||
throw new RuntimeException(
|
||||
"invalid key or spec in AEAD mode", ikae);
|
||||
}
|
||||
|
||||
// update the additional authentication data
|
||||
byte[] aad = authenticator.acquireAuthenticationBytes(
|
||||
contentType, bb.remaining() - tagSize, sequence);
|
||||
cipher.updateAAD(aad);
|
||||
|
||||
// DON'T decrypt the nonce_explicit for AEAD mode. The buffer
|
||||
// position has moved out of the nonce_explicit range.
|
||||
int len = bb.remaining();
|
||||
int pos = bb.position();
|
||||
ByteBuffer dup = bb.duplicate();
|
||||
try {
|
||||
len = cipher.doFinal(dup, bb);
|
||||
} catch (IllegalBlockSizeException ibse) {
|
||||
// unlikely to happen
|
||||
throw new RuntimeException(
|
||||
"Cipher error in AEAD mode \"" + ibse.getMessage() +
|
||||
" \"in JCE provider " + cipher.getProvider().getName());
|
||||
} catch (ShortBufferException sbe) {
|
||||
// catch BouncyCastle buffering error
|
||||
throw new RuntimeException("Cipher buffering error in " +
|
||||
"JCE provider " + cipher.getProvider().getName(), sbe);
|
||||
}
|
||||
// reset the limit to the end of the decrypted data
|
||||
bb.position(pos);
|
||||
bb.limit(pos + len);
|
||||
|
||||
if (SSLLogger.isOn && SSLLogger.isOn("plaintext")) {
|
||||
SSLLogger.fine(
|
||||
"Plaintext after DECRYPTION", bb.duplicate());
|
||||
}
|
||||
|
||||
return new Plaintext(contentType,
|
||||
ProtocolVersion.NONE.major, ProtocolVersion.NONE.minor,
|
||||
-1, -1L, bb.slice());
|
||||
}
|
||||
|
||||
@Override
|
||||
void dispose() {
|
||||
if (cipher != null) {
|
||||
try {
|
||||
cipher.doFinal();
|
||||
} catch (Exception e) {
|
||||
// swallow all types of exceptions.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
int estimateFragmentSize(int packetSize, int headerSize) {
|
||||
return packetSize - headerSize - tagSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final class T12CC20P1305WriteCipherGenerator
|
||||
implements WriteCipherGenerator {
|
||||
@Override
|
||||
public SSLWriteCipher createCipher(SSLCipher sslCipher,
|
||||
Authenticator authenticator, ProtocolVersion protocolVersion,
|
||||
String algorithm, Key key, AlgorithmParameterSpec params,
|
||||
SecureRandom random) throws GeneralSecurityException {
|
||||
return new CC20P1305WriteCipher(authenticator, protocolVersion,
|
||||
sslCipher, algorithm, key, params, random);
|
||||
}
|
||||
|
||||
private static final class CC20P1305WriteCipher extends SSLWriteCipher {
|
||||
private final Cipher cipher;
|
||||
private final int tagSize;
|
||||
private final Key key;
|
||||
private final byte[] iv;
|
||||
private final SecureRandom random;
|
||||
|
||||
CC20P1305WriteCipher(Authenticator authenticator,
|
||||
ProtocolVersion protocolVersion,
|
||||
SSLCipher sslCipher, String algorithm,
|
||||
Key key, AlgorithmParameterSpec params,
|
||||
SecureRandom random) throws GeneralSecurityException {
|
||||
super(authenticator, protocolVersion);
|
||||
this.cipher = JsseJce.getCipher(algorithm);
|
||||
this.tagSize = sslCipher.tagSize;
|
||||
this.key = key;
|
||||
this.iv = ((IvParameterSpec)params).getIV();
|
||||
this.random = random;
|
||||
|
||||
keyLimitCountdown = cipherLimits.getOrDefault(
|
||||
algorithm.toUpperCase() + ":" + tag[0], 0L);
|
||||
if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
|
||||
SSLLogger.fine("algorithm = " + algorithm.toUpperCase() +
|
||||
":" + tag[0] + "\ncountdown value = " +
|
||||
keyLimitCountdown);
|
||||
}
|
||||
if (keyLimitCountdown > 0) {
|
||||
keyLimitEnabled = true;
|
||||
}
|
||||
|
||||
// DON'T initialize the cipher for AEAD!
|
||||
}
|
||||
|
||||
@Override
|
||||
public int encrypt(byte contentType,
|
||||
ByteBuffer bb) {
|
||||
byte[] sn = authenticator.sequenceNumber();
|
||||
byte[] nonce = new byte[iv.length];
|
||||
System.arraycopy(sn, 0, nonce, nonce.length - sn.length,
|
||||
sn.length);
|
||||
for (int i = 0; i < nonce.length; i++) {
|
||||
nonce[i] ^= iv[i];
|
||||
}
|
||||
|
||||
// initialize the AEAD cipher for the unique IV
|
||||
AlgorithmParameterSpec spec = new IvParameterSpec(nonce);
|
||||
try {
|
||||
cipher.init(Cipher.ENCRYPT_MODE, key, spec, random);
|
||||
} catch (InvalidKeyException |
|
||||
InvalidAlgorithmParameterException ikae) {
|
||||
// unlikely to happen
|
||||
throw new RuntimeException(
|
||||
"invalid key or spec in AEAD mode", ikae);
|
||||
}
|
||||
|
||||
// Update the additional authentication data, using the
|
||||
// implicit sequence number of the authenticator.
|
||||
byte[] aad = authenticator.acquireAuthenticationBytes(
|
||||
contentType, bb.remaining(), null);
|
||||
cipher.updateAAD(aad);
|
||||
|
||||
// DON'T encrypt the nonce for AEAD mode.
|
||||
int len = bb.remaining();
|
||||
int pos = bb.position();
|
||||
if (SSLLogger.isOn && SSLLogger.isOn("plaintext")) {
|
||||
SSLLogger.fine(
|
||||
"Plaintext before ENCRYPTION",
|
||||
bb.duplicate());
|
||||
}
|
||||
|
||||
ByteBuffer dup = bb.duplicate();
|
||||
int outputSize = cipher.getOutputSize(dup.remaining());
|
||||
if (outputSize > bb.remaining()) {
|
||||
// Need to expand the limit of the output buffer for
|
||||
// the authentication tag.
|
||||
//
|
||||
// DON'T worry about the buffer's capacity, we have
|
||||
// reserved space for the authentication tag.
|
||||
bb.limit(pos + outputSize);
|
||||
}
|
||||
|
||||
try {
|
||||
len = cipher.doFinal(dup, bb);
|
||||
} catch (IllegalBlockSizeException |
|
||||
BadPaddingException | ShortBufferException ibse) {
|
||||
// unlikely to happen
|
||||
throw new RuntimeException(
|
||||
"Cipher error in AEAD mode in JCE provider " +
|
||||
cipher.getProvider().getName(), ibse);
|
||||
}
|
||||
|
||||
if (len != outputSize) {
|
||||
throw new RuntimeException(
|
||||
"Cipher buffering error in JCE provider " +
|
||||
cipher.getProvider().getName());
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
@Override
|
||||
void dispose() {
|
||||
if (cipher != null) {
|
||||
try {
|
||||
cipher.doFinal();
|
||||
} catch (Exception e) {
|
||||
// swallow all types of exceptions.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
int getExplicitNonceSize() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
int calculateFragmentSize(int packetLimit, int headerSize) {
|
||||
return packetLimit - headerSize - tagSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
int calculatePacketSize(int fragmentSize, int headerSize) {
|
||||
return fragmentSize + headerSize + tagSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final class T13CC20P1305ReadCipherGenerator
|
||||
implements ReadCipherGenerator {
|
||||
|
||||
@Override
|
||||
public SSLReadCipher createCipher(SSLCipher sslCipher,
|
||||
Authenticator authenticator, ProtocolVersion protocolVersion,
|
||||
String algorithm, Key key, AlgorithmParameterSpec params,
|
||||
SecureRandom random) throws GeneralSecurityException {
|
||||
return new CC20P1305ReadCipher(authenticator, protocolVersion,
|
||||
sslCipher, algorithm, key, params, random);
|
||||
}
|
||||
|
||||
static final class CC20P1305ReadCipher extends SSLReadCipher {
|
||||
private final Cipher cipher;
|
||||
private final int tagSize;
|
||||
private final Key key;
|
||||
private final byte[] iv;
|
||||
private final SecureRandom random;
|
||||
|
||||
CC20P1305ReadCipher(Authenticator authenticator,
|
||||
ProtocolVersion protocolVersion,
|
||||
SSLCipher sslCipher, String algorithm,
|
||||
Key key, AlgorithmParameterSpec params,
|
||||
SecureRandom random) throws GeneralSecurityException {
|
||||
super(authenticator, protocolVersion);
|
||||
this.cipher = JsseJce.getCipher(algorithm);
|
||||
this.tagSize = sslCipher.tagSize;
|
||||
this.key = key;
|
||||
this.iv = ((IvParameterSpec)params).getIV();
|
||||
this.random = random;
|
||||
|
||||
// DON'T initialize the cipher for AEAD!
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plaintext decrypt(byte contentType, ByteBuffer bb,
|
||||
byte[] sequence) throws GeneralSecurityException {
|
||||
// An implementation may receive an unencrypted record of type
|
||||
// change_cipher_spec consisting of the single byte value 0x01
|
||||
// at any time after the first ClientHello message has been
|
||||
// sent or received and before the peer's Finished message has
|
||||
// been received and MUST simply drop it without further
|
||||
// processing.
|
||||
if (contentType == ContentType.CHANGE_CIPHER_SPEC.id) {
|
||||
return new Plaintext(contentType,
|
||||
ProtocolVersion.NONE.major, ProtocolVersion.NONE.minor,
|
||||
-1, -1L, bb.slice());
|
||||
}
|
||||
|
||||
if (bb.remaining() <= tagSize) {
|
||||
throw new BadPaddingException(
|
||||
"Insufficient buffer remaining for AEAD cipher " +
|
||||
"fragment (" + bb.remaining() + "). Needs to be " +
|
||||
"more than tag size (" + tagSize + ")");
|
||||
}
|
||||
|
||||
byte[] sn = sequence;
|
||||
if (sn == null) {
|
||||
sn = authenticator.sequenceNumber();
|
||||
}
|
||||
byte[] nonce = new byte[iv.length];
|
||||
System.arraycopy(sn, 0, nonce, nonce.length - sn.length,
|
||||
sn.length);
|
||||
for (int i = 0; i < nonce.length; i++) {
|
||||
nonce[i] ^= iv[i];
|
||||
}
|
||||
|
||||
// initialize the AEAD cipher with the unique IV
|
||||
AlgorithmParameterSpec spec = new IvParameterSpec(nonce);
|
||||
try {
|
||||
cipher.init(Cipher.DECRYPT_MODE, key, spec, random);
|
||||
} catch (InvalidKeyException |
|
||||
InvalidAlgorithmParameterException ikae) {
|
||||
// unlikely to happen
|
||||
throw new RuntimeException(
|
||||
"invalid key or spec in AEAD mode", ikae);
|
||||
}
|
||||
|
||||
// Update the additional authentication data, using the
|
||||
// implicit sequence number of the authenticator.
|
||||
byte[] aad = authenticator.acquireAuthenticationBytes(
|
||||
contentType, bb.remaining(), sn);
|
||||
cipher.updateAAD(aad);
|
||||
|
||||
int len = bb.remaining();
|
||||
int pos = bb.position();
|
||||
ByteBuffer dup = bb.duplicate();
|
||||
try {
|
||||
len = cipher.doFinal(dup, bb);
|
||||
} catch (IllegalBlockSizeException ibse) {
|
||||
// unlikely to happen
|
||||
throw new RuntimeException(
|
||||
"Cipher error in AEAD mode \"" + ibse.getMessage() +
|
||||
" \"in JCE provider " + cipher.getProvider().getName());
|
||||
} catch (ShortBufferException sbe) {
|
||||
// catch BouncyCastle buffering error
|
||||
throw new RuntimeException("Cipher buffering error in " +
|
||||
"JCE provider " + cipher.getProvider().getName(), sbe);
|
||||
}
|
||||
// reset the limit to the end of the decrypted data
|
||||
bb.position(pos);
|
||||
bb.limit(pos + len);
|
||||
|
||||
// remove inner plaintext padding
|
||||
int i = bb.limit() - 1;
|
||||
for (; i > 0 && bb.get(i) == 0; i--) {
|
||||
// blank
|
||||
}
|
||||
if (i < (pos + 1)) {
|
||||
throw new BadPaddingException(
|
||||
"Incorrect inner plaintext: no content type");
|
||||
}
|
||||
contentType = bb.get(i);
|
||||
bb.limit(i);
|
||||
|
||||
if (SSLLogger.isOn && SSLLogger.isOn("plaintext")) {
|
||||
SSLLogger.fine(
|
||||
"Plaintext after DECRYPTION", bb.duplicate());
|
||||
}
|
||||
|
||||
return new Plaintext(contentType,
|
||||
ProtocolVersion.NONE.major, ProtocolVersion.NONE.minor,
|
||||
-1, -1L, bb.slice());
|
||||
}
|
||||
|
||||
@Override
|
||||
void dispose() {
|
||||
if (cipher != null) {
|
||||
try {
|
||||
cipher.doFinal();
|
||||
} catch (Exception e) {
|
||||
// swallow all types of exceptions.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
int estimateFragmentSize(int packetSize, int headerSize) {
|
||||
return packetSize - headerSize - tagSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final class T13CC20P1305WriteCipherGenerator
|
||||
implements WriteCipherGenerator {
|
||||
@Override
|
||||
public SSLWriteCipher createCipher(SSLCipher sslCipher,
|
||||
Authenticator authenticator, ProtocolVersion protocolVersion,
|
||||
String algorithm, Key key, AlgorithmParameterSpec params,
|
||||
SecureRandom random) throws GeneralSecurityException {
|
||||
return new CC20P1305WriteCipher(authenticator, protocolVersion,
|
||||
sslCipher, algorithm, key, params, random);
|
||||
}
|
||||
|
||||
private static final class CC20P1305WriteCipher extends SSLWriteCipher {
|
||||
private final Cipher cipher;
|
||||
private final int tagSize;
|
||||
private final Key key;
|
||||
private final byte[] iv;
|
||||
private final SecureRandom random;
|
||||
|
||||
CC20P1305WriteCipher(Authenticator authenticator,
|
||||
ProtocolVersion protocolVersion,
|
||||
SSLCipher sslCipher, String algorithm,
|
||||
Key key, AlgorithmParameterSpec params,
|
||||
SecureRandom random) throws GeneralSecurityException {
|
||||
super(authenticator, protocolVersion);
|
||||
this.cipher = JsseJce.getCipher(algorithm);
|
||||
this.tagSize = sslCipher.tagSize;
|
||||
this.key = key;
|
||||
this.iv = ((IvParameterSpec)params).getIV();
|
||||
this.random = random;
|
||||
|
||||
keyLimitCountdown = cipherLimits.getOrDefault(
|
||||
algorithm.toUpperCase() + ":" + tag[0], 0L);
|
||||
if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
|
||||
SSLLogger.fine("algorithm = " + algorithm.toUpperCase() +
|
||||
":" + tag[0] + "\ncountdown value = " +
|
||||
keyLimitCountdown);
|
||||
}
|
||||
if (keyLimitCountdown > 0) {
|
||||
keyLimitEnabled = true;
|
||||
}
|
||||
|
||||
// DON'T initialize the cipher for AEAD!
|
||||
}
|
||||
|
||||
@Override
|
||||
public int encrypt(byte contentType,
|
||||
ByteBuffer bb) {
|
||||
byte[] sn = authenticator.sequenceNumber();
|
||||
byte[] nonce = new byte[iv.length];
|
||||
System.arraycopy(sn, 0, nonce, nonce.length - sn.length,
|
||||
sn.length);
|
||||
for (int i = 0; i < nonce.length; i++) {
|
||||
nonce[i] ^= iv[i];
|
||||
}
|
||||
|
||||
// initialize the AEAD cipher for the unique IV
|
||||
AlgorithmParameterSpec spec = new IvParameterSpec(nonce);
|
||||
try {
|
||||
cipher.init(Cipher.ENCRYPT_MODE, key, spec, random);
|
||||
} catch (InvalidKeyException |
|
||||
InvalidAlgorithmParameterException ikae) {
|
||||
// unlikely to happen
|
||||
throw new RuntimeException(
|
||||
"invalid key or spec in AEAD mode", ikae);
|
||||
}
|
||||
|
||||
// Update the additional authentication data, using the
|
||||
// implicit sequence number of the authenticator.
|
||||
int outputSize = cipher.getOutputSize(bb.remaining());
|
||||
byte[] aad = authenticator.acquireAuthenticationBytes(
|
||||
contentType, outputSize, sn);
|
||||
cipher.updateAAD(aad);
|
||||
|
||||
int len = bb.remaining();
|
||||
int pos = bb.position();
|
||||
if (SSLLogger.isOn && SSLLogger.isOn("plaintext")) {
|
||||
SSLLogger.fine(
|
||||
"Plaintext before ENCRYPTION",
|
||||
bb.duplicate());
|
||||
}
|
||||
|
||||
ByteBuffer dup = bb.duplicate();
|
||||
if (outputSize > bb.remaining()) {
|
||||
// Need to expand the limit of the output buffer for
|
||||
// the authentication tag.
|
||||
//
|
||||
// DON'T worry about the buffer's capacity, we have
|
||||
// reserved space for the authentication tag.
|
||||
bb.limit(pos + outputSize);
|
||||
}
|
||||
|
||||
try {
|
||||
len = cipher.doFinal(dup, bb);
|
||||
} catch (IllegalBlockSizeException |
|
||||
BadPaddingException | ShortBufferException ibse) {
|
||||
// unlikely to happen
|
||||
throw new RuntimeException(
|
||||
"Cipher error in AEAD mode in JCE provider " +
|
||||
cipher.getProvider().getName(), ibse);
|
||||
}
|
||||
|
||||
if (len != outputSize) {
|
||||
throw new RuntimeException(
|
||||
"Cipher buffering error in JCE provider " +
|
||||
cipher.getProvider().getName());
|
||||
}
|
||||
|
||||
if (keyLimitEnabled) {
|
||||
keyLimitCountdown -= len;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
@Override
|
||||
void dispose() {
|
||||
if (cipher != null) {
|
||||
try {
|
||||
cipher.doFinal();
|
||||
} catch (Exception e) {
|
||||
// swallow all types of exceptions.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
int getExplicitNonceSize() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
int calculateFragmentSize(int packetLimit, int headerSize) {
|
||||
return packetLimit - headerSize - tagSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
int calculatePacketSize(int fragmentSize, int headerSize) {
|
||||
return fragmentSize + headerSize + tagSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void addMac(MAC signer,
|
||||
ByteBuffer destination, byte contentType) {
|
||||
if (signer.macAlg().size != 0) {
|
||||
|
@ -2367,4 +2936,3 @@ enum SSLCipher {
|
|||
return results;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -207,6 +207,10 @@ public abstract class SSLContextImpl extends SSLContextSpi {
|
|||
if (!isInitialized) {
|
||||
throw new IllegalStateException("SSLContext is not initialized");
|
||||
}
|
||||
if (isDTLS()) {
|
||||
throw new UnsupportedOperationException(
|
||||
"DTLS not supported with SSLSocket");
|
||||
}
|
||||
return new SSLSocketFactoryImpl(this);
|
||||
}
|
||||
|
||||
|
@ -215,6 +219,10 @@ public abstract class SSLContextImpl extends SSLContextSpi {
|
|||
if (!isInitialized) {
|
||||
throw new IllegalStateException("SSLContext is not initialized");
|
||||
}
|
||||
if (isDTLS()) {
|
||||
throw new UnsupportedOperationException(
|
||||
"DTLS not supported with SSLServerSocket");
|
||||
}
|
||||
return new SSLServerSocketFactoryImpl(this);
|
||||
}
|
||||
|
||||
|
@ -1261,6 +1269,21 @@ public abstract class SSLContextImpl extends SSLContextSpi {
|
|||
serverDefaultProtocols, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SSLParameters engineGetDefaultSSLParameters() {
|
||||
SSLEngine engine = createSSLEngineImpl();
|
||||
return engine.getSSLParameters();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SSLParameters engineGetSupportedSSLParameters() {
|
||||
SSLEngine engine = createSSLEngineImpl();
|
||||
SSLParameters params = new SSLParameters();
|
||||
params.setCipherSuites(engine.getSupportedCipherSuites());
|
||||
params.setProtocols(engine.getSupportedProtocols());
|
||||
return params;
|
||||
}
|
||||
|
||||
@Override
|
||||
List<ProtocolVersion> getSupportedProtocolVersions() {
|
||||
return supportedProtocols;
|
||||
|
|
|
@ -333,7 +333,7 @@ final class SSLExtensions {
|
|||
return "<no extension>";
|
||||
} else {
|
||||
StringBuilder builder = new StringBuilder(512);
|
||||
if (logMap != null) {
|
||||
if (logMap != null && !logMap.isEmpty()) {
|
||||
for (Map.Entry<Integer, byte[]> en : logMap.entrySet()) {
|
||||
SSLExtension ext = SSLExtension.valueOf(
|
||||
handshakeMessage.handshakeType(), en.getKey());
|
||||
|
|
|
@ -525,7 +525,7 @@ final class SignatureAlgorithmsExtension {
|
|||
// signatures appearing in certificates.
|
||||
SignatureSchemesSpec certSpec =
|
||||
(SignatureSchemesSpec)chc.handshakeExtensions.get(
|
||||
SSLExtension.CH_SIGNATURE_ALGORITHMS_CERT);
|
||||
SSLExtension.CR_SIGNATURE_ALGORITHMS_CERT);
|
||||
if (certSpec == null) {
|
||||
chc.peerRequestedCertSignSchemes = sss;
|
||||
chc.handshakeSession.setPeerSupportedSignatureAlgorithms(sss);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue