--- a/make/lib/Lib-java.security.jgss.gmk Wed Jun 12 10:02:49 2019 +0530
+++ b/make/lib/Lib-java.security.jgss.gmk Thu Jun 13 11:31:36 2019 +0530
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2019, 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
@@ -57,6 +57,17 @@
))
TARGETS += $(BUILD_LIBW2K_LSA_AUTH)
+
+ $(eval $(call SetupJdkLibrary, BUILD_LIBSSPI_BRIDGE, \
+ NAME := sspi_bridge, \
+ OPTIMIZATION := LOW, \
+ CFLAGS := $(CFLAGS_JDKLIB) \
+ -I$(TOPDIR)/src/java.security.jgss/share/native/libj2gss, \
+ LDFLAGS := $(LDFLAGS_JDKLIB) \
+ $(call SET_SHARED_LIBRARY_ORIGIN) \
+ ))
+
+ TARGETS += $(BUILD_LIBSSPI_BRIDGE)
endif
ifeq ($(call isTargetOs, macosx), true)
--- a/src/hotspot/cpu/ppc/ppc.ad Wed Jun 12 10:02:49 2019 +0530
+++ b/src/hotspot/cpu/ppc/ppc.ad Thu Jun 13 11:31:36 2019 +0530
@@ -1,6 +1,6 @@
//
-// Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
-// Copyright (c) 2012, 2018 SAP SE. All rights reserved.
+// Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
+// Copyright (c) 2012, 2019 SAP SE. 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
@@ -4649,6 +4649,16 @@
interface(CONST_INTER);
%}
+// Double Immediate: +0.0d.
+operand immD_0() %{
+ predicate(jlong_cast(n->getd()) == 0);
+ match(ConD);
+
+ op_cost(0);
+ format %{ %}
+ interface(CONST_INTER);
+%}
+
// Integer Register Operands
// Integer Destination Register
// See definition of reg_class bits32_reg_rw.
@@ -14027,7 +14037,7 @@
instruct repl4S_immI0(iRegLdst dst, immI_0 zero) %{
match(Set dst (ReplicateS zero));
predicate(n->as_Vector()->length() == 4);
- format %{ "LI $dst, #0 \t// replicate4C" %}
+ format %{ "LI $dst, #0 \t// replicate4S" %}
size(4);
ins_encode %{
// TODO: PPC port $archOpcode(ppc64Opcode_addi);
@@ -14039,7 +14049,7 @@
instruct repl4S_immIminus1(iRegLdst dst, immI_minus1 src) %{
match(Set dst (ReplicateS src));
predicate(n->as_Vector()->length() == 4);
- format %{ "LI $dst, -1 \t// replicate4C" %}
+ format %{ "LI $dst, -1 \t// replicate4S" %}
size(4);
ins_encode %{
// TODO: PPC port $archOpcode(ppc64Opcode_addi);
@@ -14080,7 +14090,7 @@
match(Set dst (ReplicateS src));
predicate(n->as_Vector()->length() == 8);
- format %{ "XXLEQV $dst, $src \t// replicate16B" %}
+ format %{ "XXLEQV $dst, $src \t// replicate8S" %}
size(4);
ins_encode %{
__ xxleqv($dst$$VectorSRegister, $dst$$VectorSRegister, $dst$$VectorSRegister);
@@ -14101,7 +14111,7 @@
instruct repl2I_immI0(iRegLdst dst, immI_0 zero) %{
match(Set dst (ReplicateI zero));
predicate(n->as_Vector()->length() == 2);
- format %{ "LI $dst, #0 \t// replicate4C" %}
+ format %{ "LI $dst, #0 \t// replicate2I" %}
size(4);
ins_encode %{
// TODO: PPC port $archOpcode(ppc64Opcode_addi);
@@ -14113,7 +14123,7 @@
instruct repl2I_immIminus1(iRegLdst dst, immI_minus1 src) %{
match(Set dst (ReplicateI src));
predicate(n->as_Vector()->length() == 2);
- format %{ "LI $dst, -1 \t// replicate4C" %}
+ format %{ "LI $dst, -1 \t// replicate2I" %}
size(4);
ins_encode %{
// TODO: PPC port $archOpcode(ppc64Opcode_addi);
@@ -14687,7 +14697,7 @@
ins_pipe(pipe_class_default);
%}
-instruct repl2D_immI0(vecX dst, immI_0 zero) %{
+instruct repl2D_immD0(vecX dst, immD_0 zero) %{
match(Set dst (ReplicateD zero));
predicate(n->as_Vector()->length() == 2);
@@ -14699,18 +14709,6 @@
ins_pipe(pipe_class_default);
%}
-instruct repl2D_immIminus1(vecX dst, immI_minus1 src) %{
- match(Set dst (ReplicateD src));
- predicate(n->as_Vector()->length() == 2);
-
- format %{ "XXLEQV $dst, $src \t// replicate16B" %}
- size(4);
- ins_encode %{
- __ xxleqv($dst$$VectorSRegister, $dst$$VectorSRegister, $dst$$VectorSRegister);
- %}
- ins_pipe(pipe_class_default);
-%}
-
instruct mtvsrd(vecX dst, iRegLsrc src) %{
predicate(false);
effect(DEF dst, USE src);
@@ -14772,7 +14770,7 @@
match(Set dst (ReplicateL src));
predicate(n->as_Vector()->length() == 2);
- format %{ "XXLEQV $dst, $src \t// replicate16B" %}
+ format %{ "XXLEQV $dst, $src \t// replicate2L" %}
size(4);
ins_encode %{
__ xxleqv($dst$$VectorSRegister, $dst$$VectorSRegister, $dst$$VectorSRegister);
--- a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp Wed Jun 12 10:02:49 2019 +0530
+++ b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp Thu Jun 13 11:31:36 2019 +0530
@@ -82,7 +82,18 @@
}
void LIR_Assembler::clinit_barrier(ciMethod* method) {
- ShouldNotReachHere(); // not implemented
+ assert(!method->holder()->is_not_initialized(), "initialization should have been started");
+
+ Label L_skip_barrier;
+ Register klass = Z_R1_scratch;
+
+ metadata2reg(method->holder()->constant_encoding(), klass);
+ __ clinit_barrier(klass, Z_thread, &L_skip_barrier /*L_fast_path*/);
+
+ __ load_const_optimized(klass, SharedRuntime::get_handle_wrong_method_stub());
+ __ z_br(klass);
+
+ __ bind(L_skip_barrier);
}
void LIR_Assembler::osr_entry() {
--- a/src/hotspot/cpu/s390/interp_masm_s390.cpp Wed Jun 12 10:02:49 2019 +0530
+++ b/src/hotspot/cpu/s390/interp_masm_s390.cpp Thu Jun 13 11:31:36 2019 +0530
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2016, 2018 SAP SE. All rights reserved.
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019 SAP SE. 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
@@ -414,6 +414,19 @@
BLOCK_COMMENT("}");
}
+void InterpreterMacroAssembler::load_resolved_method_at_index(int byte_no,
+ Register cache,
+ Register cpe_offset,
+ Register method) {
+ const int method_offset = in_bytes(
+ ConstantPoolCache::base_offset() +
+ ((byte_no == TemplateTable::f2_byte)
+ ? ConstantPoolCacheEntry::f2_offset()
+ : ConstantPoolCacheEntry::f1_offset()));
+
+ z_lg(method, Address(cache, cpe_offset, method_offset)); // get f1 Method*
+}
+
// Generate a subtype check: branch to ok_is_subtype if sub_klass is
// a subtype of super_klass. Blows registers Rsuper_klass, Rsub_klass, tmp1, tmp2.
void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass,
@@ -2175,7 +2188,7 @@
Register R_f1_sender_sp = tmp1;
Register R_f2_sp = tmp2;
- // Tirst check the for the interpreter frame's magic.
+ // First check for the interpreter frame's magic.
asm_assert_ijava_state_magic(R_f2_sp/*tmp*/);
z_lg(R_f2_sp, _z_parent_ijava_frame_abi(callers_sp), Z_fp);
z_lg(R_f1_sender_sp, _z_ijava_state_neg(sender_sp), Z_fp);
--- a/src/hotspot/cpu/s390/interp_masm_s390.hpp Wed Jun 12 10:02:49 2019 +0530
+++ b/src/hotspot/cpu/s390/interp_masm_s390.hpp Thu Jun 13 11:31:36 2019 +0530
@@ -120,6 +120,8 @@
// load cpool->resolved_klass_at(index)
void load_resolved_klass_at_offset(Register cpool, Register offset, Register iklass);
+ void load_resolved_method_at_index(int byte_no, Register cache, Register cpe_offset, Register method);
+
// Pop topmost element from stack. It just disappears. Useful if
// consumed previously by access via stackTop().
void popx(int len);
--- a/src/hotspot/cpu/s390/macroAssembler_s390.cpp Wed Jun 12 10:02:49 2019 +0530
+++ b/src/hotspot/cpu/s390/macroAssembler_s390.cpp Thu Jun 13 11:31:36 2019 +0530
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2016, 2018, SAP SE. All rights reserved.
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, SAP SE. 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
@@ -3130,6 +3130,33 @@
BLOCK_COMMENT("} check_klass_subtype");
}
+void MacroAssembler::clinit_barrier(Register klass, Register thread, Label* L_fast_path, Label* L_slow_path) {
+ assert(L_fast_path != NULL || L_slow_path != NULL, "at least one is required");
+
+ Label L_fallthrough;
+ if (L_fast_path == NULL) {
+ L_fast_path = &L_fallthrough;
+ } else if (L_slow_path == NULL) {
+ L_slow_path = &L_fallthrough;
+ }
+
+ // Fast path check: class is fully initialized
+ z_cli(Address(klass, InstanceKlass::init_state_offset()), InstanceKlass::fully_initialized);
+ z_bre(*L_fast_path);
+
+ // Fast path check: current thread is initializer thread
+ z_cg(thread, Address(klass, InstanceKlass::init_thread_offset()));
+ if (L_slow_path == &L_fallthrough) {
+ z_bre(*L_fast_path);
+ } else if (L_fast_path == &L_fallthrough) {
+ z_brne(*L_slow_path);
+ } else {
+ Unimplemented();
+ }
+
+ bind(L_fallthrough);
+}
+
// Increment a counter at counter_address when the eq condition code is
// set. Kills registers tmp1_reg and tmp2_reg and preserves the condition code.
void MacroAssembler::increment_counter_eq(address counter_address, Register tmp1_reg, Register tmp2_reg) {
@@ -4339,14 +4366,19 @@
z_lg(result, 0, result);
}
-void MacroAssembler::load_mirror(Register mirror, Register method) {
- mem2reg_opt(mirror, Address(method, Method::const_offset()));
- mem2reg_opt(mirror, Address(mirror, ConstMethod::constants_offset()));
+void MacroAssembler::load_mirror_from_const_method(Register mirror, Register const_method) {
+ mem2reg_opt(mirror, Address(const_method, ConstMethod::constants_offset()));
mem2reg_opt(mirror, Address(mirror, ConstantPool::pool_holder_offset_in_bytes()));
mem2reg_opt(mirror, Address(mirror, Klass::java_mirror_offset()));
resolve_oop_handle(mirror);
}
+void MacroAssembler::load_method_holder(Register holder, Register method) {
+ mem2reg_opt(holder, Address(method, Method::const_offset()));
+ mem2reg_opt(holder, Address(holder, ConstMethod::constants_offset()));
+ mem2reg_opt(holder, Address(holder, ConstantPool::pool_holder_offset_in_bytes()));
+}
+
//---------------------------------------------------------------
//--- Operations on arrays.
//---------------------------------------------------------------
--- a/src/hotspot/cpu/s390/macroAssembler_s390.hpp Wed Jun 12 10:02:49 2019 +0530
+++ b/src/hotspot/cpu/s390/macroAssembler_s390.hpp Thu Jun 13 11:31:36 2019 +0530
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2016, 2018, SAP SE. All rights reserved.
+ * Copyright (c) 2016, 2019, SAP SE. 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
@@ -713,6 +713,11 @@
Register temp2_reg,
Label& L_success);
+ void clinit_barrier(Register klass,
+ Register thread,
+ Label* L_fast_path = NULL,
+ Label* L_slow_path = NULL);
+
// Increment a counter at counter_address when the eq condition code is set.
// Kills registers tmp1_reg and tmp2_reg and preserves the condition code.
void increment_counter_eq(address counter_address, Register tmp1_reg, Register tmp2_reg);
@@ -823,7 +828,8 @@
Register Rbase = Z_R1, int pow2_offset = -1);
void resolve_oop_handle(Register result);
- void load_mirror(Register mirror, Register method);
+ void load_mirror_from_const_method(Register mirror, Register const_method);
+ void load_method_holder(Register holder, Register method);
//--------------------------
//--- Operations on arrays.
--- a/src/hotspot/cpu/s390/s390.ad Wed Jun 12 10:02:49 2019 +0530
+++ b/src/hotspot/cpu/s390/s390.ad Thu Jun 13 11:31:36 2019 +0530
@@ -867,6 +867,23 @@
assert(framesize % wordSize == 0, "must preserve wordSize alignment");
+ if (C->clinit_barrier_on_entry()) {
+ assert(!C->method()->holder()->is_not_initialized(), "initialization should have been started");
+
+ Label L_skip_barrier;
+ Register klass = Z_R1_scratch;
+
+ // Notify OOP recorder (don't need the relocation)
+ AddressLiteral md = __ constant_metadata_address(C->method()->holder()->constant_encoding());
+ __ load_const_optimized(klass, md.value());
+ __ clinit_barrier(klass, Z_thread, &L_skip_barrier /*L_fast_path*/);
+
+ __ load_const_optimized(klass, SharedRuntime::get_handle_wrong_method_stub());
+ __ z_br(klass);
+
+ __ bind(L_skip_barrier);
+ }
+
// Calls to C2R adapters often do not accept exceptional returns.
// We require that their callers must bang for them. But be
// careful, because some VM calls (such as call site linkage) can
--- a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp Wed Jun 12 10:02:49 2019 +0530
+++ b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp Thu Jun 13 11:31:36 2019 +0530
@@ -1832,6 +1832,20 @@
//---------------------------------------------------------------------
wrapper_VEPStart = __ offset();
+ if (VM_Version::supports_fast_class_init_checks() && method->needs_clinit_barrier()) {
+ Label L_skip_barrier;
+ Register klass = Z_R1_scratch;
+ // Notify OOP recorder (don't need the relocation)
+ AddressLiteral md = __ constant_metadata_address(method->method_holder());
+ __ load_const_optimized(klass, md.value());
+ __ clinit_barrier(klass, Z_thread, &L_skip_barrier /*L_fast_path*/);
+
+ __ load_const_optimized(klass, SharedRuntime::get_handle_wrong_method_stub());
+ __ z_br(klass);
+
+ __ bind(L_skip_barrier);
+ }
+
__ save_return_pc();
__ generate_stack_overflow_check(frame_size_in_bytes); // Check before creating frame.
#ifndef USE_RESIZE_FRAME
@@ -2696,8 +2710,28 @@
// Fallthru to VEP. Duplicate LTG, but saved taken branch.
}
- address c2i_entry;
- c2i_entry = gen_c2i_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs, skip_fixup);
+ address c2i_entry = __ pc();
+
+ // Class initialization barrier for static methods
+ if (VM_Version::supports_fast_class_init_checks()) {
+ Label L_skip_barrier;
+
+ { // Bypass the barrier for non-static methods
+ __ testbit(Address(Z_method, Method::access_flags_offset()), JVM_ACC_STATIC_BIT);
+ __ z_bfalse(L_skip_barrier); // non-static
+ }
+
+ Register klass = Z_R11;
+ __ load_method_holder(klass, Z_method);
+ __ clinit_barrier(klass, Z_thread, &L_skip_barrier /*L_fast_path*/);
+
+ __ load_const_optimized(klass, SharedRuntime::get_handle_wrong_method_stub());
+ __ z_br(klass);
+
+ __ bind(L_skip_barrier);
+ }
+
+ gen_c2i_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs, skip_fixup);
return AdapterHandlerLibrary::new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry);
}
--- a/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp Wed Jun 12 10:02:49 2019 +0530
+++ b/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp Thu Jun 13 11:31:36 2019 +0530
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2016, 2018, SAP SE. All rights reserved.
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, SAP SE. 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
@@ -821,7 +821,7 @@
const int page_size = os::vm_page_size();
NearLabel after_frame_check;
- BLOCK_COMMENT("counter_overflow {");
+ BLOCK_COMMENT("stack_overflow_check {");
assert_different_registers(frame_size, tmp1);
@@ -883,7 +883,7 @@
// If you get to here, then there is enough stack space.
__ bind(after_frame_check);
- BLOCK_COMMENT("} counter_overflow");
+ BLOCK_COMMENT("} stack_overflow_check");
}
// Allocate monitor and lock method (asm interpreter).
@@ -927,7 +927,9 @@
__ bind(static_method);
// Lock the java mirror.
- __ load_mirror(object, method);
+ // Load mirror from interpreter frame.
+ __ z_lg(object, _z_ijava_state_neg(mirror), Z_fp);
+
#ifdef ASSERT
{
NearLabel L;
@@ -991,20 +993,20 @@
// Allocate space for locals other than the parameters, the
// interpreter state, monitors, and the expression stack.
- const Register local_count = Z_ARG5;
- const Register fp = Z_tmp_2;
+ const Register local_count = Z_ARG5;
+ const Register fp = Z_tmp_2;
+ const Register const_method = Z_ARG1;
BLOCK_COMMENT("generate_fixed_frame {");
-
{
// local registers
const Register top_frame_size = Z_ARG2;
const Register sp_after_resize = Z_ARG3;
const Register max_stack = Z_ARG4;
- // local_count = method->constMethod->max_locals();
- __ z_lg(Z_R1_scratch, Address(Z_method, Method::const_offset()));
- __ z_llgh(local_count, Address(Z_R1_scratch, ConstMethod::size_of_locals_offset()));
+ __ z_lg(const_method, Address(Z_method, Method::const_offset()));
+ __ z_llgh(max_stack, Address(const_method, ConstMethod::size_of_parameters_offset()));
+ __ z_sllg(Z_locals /*parameter_count bytes*/, max_stack /*parameter_count*/, LogBytesPerWord);
if (native_call) {
// If we're calling a native method, we replace max_stack (which is
@@ -1024,9 +1026,6 @@
// area, so we need to allocate at least that much even though we're
// going to throw it away.
//
-
- __ z_lg(Z_R1_scratch, Address(Z_method, Method::const_offset()));
- __ z_llgh(max_stack, Address(Z_R1_scratch, ConstMethod::size_of_parameters_offset()));
__ add2reg(max_stack, 2);
NearLabel passing_args_on_stack;
@@ -1042,14 +1041,14 @@
__ bind(passing_args_on_stack);
} else {
// !native_call
- __ z_lg(max_stack, method_(const));
+ // local_count = method->constMethod->max_locals();
+ __ z_llgh(local_count, Address(const_method, ConstMethod::size_of_locals_offset()));
// Calculate number of non-parameter locals (in slots):
- __ z_lg(Z_R1_scratch, Address(Z_method, Method::const_offset()));
- __ z_sh(local_count, Address(Z_R1_scratch, ConstMethod::size_of_parameters_offset()));
+ __ z_sgr(local_count, max_stack);
// max_stack = method->max_stack();
- __ z_llgh(max_stack, Address(max_stack, ConstMethod::max_stack_offset()));
+ __ z_llgh(max_stack, Address(const_method, ConstMethod::max_stack_offset()));
// max_stack in bytes
__ z_sllg(max_stack, max_stack, LogBytesPerWord);
}
@@ -1089,14 +1088,15 @@
// delta = PARENT_IJAVA_FRAME_ABI + (locals_count - params_count)
__ add2reg(sp_after_resize, (Interpreter::stackElementSize) - (frame::z_parent_ijava_frame_abi_size), Z_esp);
- __ z_sllg(Z_R0_scratch, local_count, LogBytesPerWord); // Params have already been subtracted from local_count.
- __ z_slgr(sp_after_resize, Z_R0_scratch);
+ if (!native_call) {
+ __ z_sllg(Z_R0_scratch, local_count, LogBytesPerWord); // Params have already been subtracted from local_count.
+ __ z_slgr(sp_after_resize, Z_R0_scratch);
+ }
// top_frame_size = TOP_IJAVA_FRAME_ABI + max_stack + size of interpreter state
__ add2reg(top_frame_size,
frame::z_top_ijava_frame_abi_size +
- frame::z_ijava_state_size +
- frame::interpreter_frame_monitor_size() * wordSize,
+ frame::z_ijava_state_size,
max_stack);
if (!native_call) {
@@ -1104,7 +1104,7 @@
// Native calls don't need the stack size check since they have no
// expression stack and the arguments are already on the stack and
// we only add a handful of words to the stack.
- Register frame_size = max_stack; // Reuse the regiser for max_stack.
+ Register frame_size = max_stack; // Reuse the register for max_stack.
__ z_lgr(frame_size, Z_SP);
__ z_sgr(frame_size, sp_after_resize);
__ z_agr(frame_size, top_frame_size);
@@ -1136,13 +1136,12 @@
#endif
// Save sender SP from F1 (i.e. before it was potentially modified by an
- // adapter) into F0's interpreter state. We us it as well to revert
+ // adapter) into F0's interpreter state. We use it as well to revert
// resizing the frame above.
__ z_stg(Z_R10, _z_ijava_state_neg(sender_sp), fp);
- // Load cp cache and save it at the and of this block.
- __ z_lg(Z_R1_scratch, Address(Z_method, Method::const_offset()));
- __ z_lg(Z_R1_scratch, Address(Z_R1_scratch, ConstMethod::constants_offset()));
+ // Load cp cache and save it at the end of this block.
+ __ z_lg(Z_R1_scratch, Address(const_method, ConstMethod::constants_offset()));
__ z_lg(Z_R1_scratch, Address(Z_R1_scratch, ConstantPool::cache_offset_in_bytes()));
// z_ijava_state->method = method;
@@ -1152,10 +1151,6 @@
// parameters on top of caller's expression stack.
// Tos points past last Java argument.
- __ z_lg(Z_locals, Address(Z_method, Method::const_offset()));
- __ z_llgh(Z_locals /*parameter_count words*/,
- Address(Z_locals, ConstMethod::size_of_parameters_offset()));
- __ z_sllg(Z_locals /*parameter_count bytes*/, Z_locals /*parameter_count*/, LogBytesPerWord);
__ z_agr(Z_locals, Z_esp);
// z_ijava_state->locals - i*BytesPerWord points to i-th Java local (i starts at 0)
// z_ijava_state->locals = Z_esp + parameter_count bytes
@@ -1183,8 +1178,7 @@
if (native_call) {
__ clear_reg(Z_bcp); // Must initialize. Will get written into frame where GC reads it.
} else {
- __ z_lg(Z_bcp, method_(const));
- __ add2reg(Z_bcp, in_bytes(ConstMethod::codes_offset()));
+ __ add2reg(Z_bcp, in_bytes(ConstMethod::codes_offset()), const_method);
}
__ z_stg(Z_bcp, _z_ijava_state_neg(bcp), fp);
@@ -1202,62 +1196,21 @@
__ z_stg(Z_R1_scratch, _z_ijava_state_neg(cpoolCache), fp);
// Get mirror and store it in the frame as GC root for this Method*.
- __ load_mirror(Z_R1_scratch, Z_method);
+ __ load_mirror_from_const_method(Z_R1_scratch, const_method);
__ z_stg(Z_R1_scratch, _z_ijava_state_neg(mirror), fp);
BLOCK_COMMENT("} generate_fixed_frame: initialize interpreter state");
//=============================================================================
if (!native_call) {
- // Fill locals with 0x0s.
- NearLabel locals_zeroed;
- NearLabel doXC;
-
// Local_count is already num_locals_slots - num_param_slots.
- __ compare64_and_branch(local_count, (intptr_t)0L, Assembler::bcondNotHigh, locals_zeroed);
-
- // Advance local_addr to point behind locals (creates positive incr. in loop).
- __ z_lg(Z_R1_scratch, Address(Z_method, Method::const_offset()));
- __ z_llgh(Z_R0_scratch, Address(Z_R1_scratch, ConstMethod::size_of_locals_offset()));
- __ add2reg(Z_R0_scratch, -1);
-
- __ z_lgr(local_addr/*locals*/, Z_locals);
+ // Start of locals: local_addr = Z_locals - locals size + 1 slot
+ __ z_llgh(Z_R0_scratch, Address(const_method, ConstMethod::size_of_locals_offset()));
+ __ add2reg(local_addr, BytesPerWord, Z_locals);
__ z_sllg(Z_R0_scratch, Z_R0_scratch, LogBytesPerWord);
- __ z_sllg(local_count, local_count, LogBytesPerWord); // Local_count are non param locals.
__ z_sgr(local_addr, Z_R0_scratch);
- if (VM_Version::has_Prefetch()) {
- __ z_pfd(0x02, 0, Z_R0, local_addr);
- __ z_pfd(0x02, 256, Z_R0, local_addr);
- }
-
- // Can't optimise for Z10 using "compare and branch" (immediate value is too big).
- __ z_cghi(local_count, 256);
- __ z_brnh(doXC);
-
- // MVCLE: Initialize if quite a lot locals.
- // __ bind(doMVCLE);
- __ z_lgr(Z_R0_scratch, local_addr);
- __ z_lgr(Z_R1_scratch, local_count);
- __ clear_reg(Z_ARG2); // Src len of MVCLE is zero.
-
- __ MacroAssembler::move_long_ext(Z_R0_scratch, Z_ARG1, 0);
- __ z_bru(locals_zeroed);
-
- Label XC_template;
- __ bind(XC_template);
- __ z_xc(0, 0, local_addr, 0, local_addr);
-
- __ bind(doXC);
- __ z_bctgr(local_count, Z_R0); // Get #bytes-1 for EXECUTE.
- if (VM_Version::has_ExecuteExtensions()) {
- __ z_exrl(local_count, XC_template); // Execute XC with variable length.
- } else {
- __ z_larl(Z_R1_scratch, XC_template);
- __ z_ex(local_count, 0, Z_R0, Z_R1_scratch); // Execute XC with variable length.
- }
-
- __ bind(locals_zeroed);
+ __ Clear_Array(local_count, local_addr, Z_ARG2);
}
}
@@ -1530,8 +1483,8 @@
Label method_is_not_static;
__ testbit(method2_(Rmethod, access_flags), JVM_ACC_STATIC_BIT);
__ z_bfalse(method_is_not_static);
- // Get mirror.
- __ load_mirror(Z_R1, Rmethod);
+ // Load mirror from interpreter frame.
+ __ z_lg(Z_R1, _z_ijava_state_neg(mirror), Z_fp);
// z_ijava_state.oop_temp = pool_holder->klass_part()->java_mirror();
__ z_stg(Z_R1, oop_tmp_offset, Z_fp);
// Pass handle to mirror as 2nd argument to JNI method.
--- a/src/hotspot/cpu/s390/templateTable_s390.cpp Wed Jun 12 10:02:49 2019 +0530
+++ b/src/hotspot/cpu/s390/templateTable_s390.cpp Thu Jun 13 11:31:36 2019 +0530
@@ -2404,14 +2404,14 @@
// NOTE: Cpe_offset is already computed as byte offset, so we must not
// shift it afterwards!
void TemplateTable::resolve_cache_and_index(int byte_no,
- Register Rcache,
+ Register cache,
Register cpe_offset,
size_t index_size) {
BLOCK_COMMENT("resolve_cache_and_index {");
- NearLabel resolved;
+ NearLabel resolved, clinit_barrier_slow;
const Register bytecode_in_cpcache = Z_R1_scratch;
const int total_f1_offset = in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::f1_offset());
- assert_different_registers(Rcache, cpe_offset, bytecode_in_cpcache);
+ assert_different_registers(cache, cpe_offset, bytecode_in_cpcache);
Bytecodes::Code code = bytecode();
switch (code) {
@@ -2423,19 +2423,32 @@
{
assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
- __ get_cache_and_index_and_bytecode_at_bcp(Rcache, cpe_offset, bytecode_in_cpcache, byte_no, 1, index_size);
+ __ get_cache_and_index_and_bytecode_at_bcp(cache, cpe_offset, bytecode_in_cpcache, byte_no, 1, index_size);
// Have we resolved this bytecode?
__ compare32_and_branch(bytecode_in_cpcache, (int)code, Assembler::bcondEqual, resolved);
}
// Resolve first time through.
+ // Class initialization barrier slow path lands here as well.
+ __ bind(clinit_barrier_slow);
address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_from_cache);
__ load_const_optimized(Z_ARG2, (int) code);
__ call_VM(noreg, entry, Z_ARG2);
// Update registers with resolved info.
- __ get_cache_and_index_at_bcp(Rcache, cpe_offset, 1, index_size);
+ __ get_cache_and_index_at_bcp(cache, cpe_offset, 1, index_size);
__ bind(resolved);
+
+ // Class initialization barrier for static methods
+ if (VM_Version::supports_fast_class_init_checks() && bytecode() == Bytecodes::_invokestatic) {
+ const Register method = Z_R1_scratch;
+ const Register klass = Z_R1_scratch;
+
+ __ load_resolved_method_at_index(byte_no, cache, cpe_offset, method);
+ __ load_method_holder(klass, method);
+ __ clinit_barrier(klass, Z_thread, NULL /*L_fast_path*/, &clinit_barrier_slow);
+ }
+
BLOCK_COMMENT("} resolve_cache_and_index");
}
@@ -3664,9 +3677,7 @@
// Find entry point to call.
// Get declaring interface class from method
- __ z_lg(interface, Address(method, Method::const_offset()));
- __ z_lg(interface, Address(interface, ConstMethod::constants_offset()));
- __ z_lg(interface, Address(interface, ConstantPool::pool_holder_offset_in_bytes()));
+ __ load_method_holder(interface, method);
// Get itable index from method
Register index = receiver,
--- a/src/hotspot/cpu/s390/vm_version_s390.hpp Wed Jun 12 10:02:49 2019 +0530
+++ b/src/hotspot/cpu/s390/vm_version_s390.hpp Thu Jun 13 11:31:36 2019 +0530
@@ -349,6 +349,9 @@
// Override Abstract_VM_Version implementation
static void print_platform_virtualization_info(outputStream*);
+ // s390 supports fast class initialization checks for static methods.
+ static bool supports_fast_class_init_checks() { return true; }
+
// CPU feature query functions
static const char* get_model_string() { return _model_string; }
static bool has_StoreFacilityListExtended() { return (_features[0] & StoreFacilityListExtendedMask) == StoreFacilityListExtendedMask; }
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Wed Jun 12 10:02:49 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Thu Jun 13 11:31:36 2019 +0530
@@ -4640,7 +4640,7 @@
bool const during_im = collector_state()->in_initial_mark_gc();
if (during_im && allocated_bytes > 0) {
- _cm->root_regions()->add(alloc_region);
+ _cm->root_regions()->add(alloc_region->next_top_at_mark_start(), alloc_region->top());
}
_hr_printer.retire(alloc_region);
}
--- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp Wed Jun 12 10:02:49 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp Thu Jun 13 11:31:36 2019 +0530
@@ -257,30 +257,38 @@
_free_list = NULL;
}
-G1CMRootRegions::G1CMRootRegions(uint const max_regions) :
- _root_regions(NEW_C_HEAP_ARRAY(HeapRegion*, max_regions, mtGC)),
- _max_regions(max_regions),
- _num_root_regions(0),
- _claimed_root_regions(0),
- _scan_in_progress(false),
- _should_abort(false) { }
-
-G1CMRootRegions::~G1CMRootRegions() {
- FREE_C_HEAP_ARRAY(HeapRegion*, _max_regions);
+G1CMRootMemRegions::G1CMRootMemRegions(uint const max_regions) :
+ _root_regions(NULL),
+ _max_regions(max_regions),
+ _num_root_regions(0),
+ _claimed_root_regions(0),
+ _scan_in_progress(false),
+ _should_abort(false) {
+ _root_regions = new MemRegion[_max_regions];
+ if (_root_regions == NULL) {
+ vm_exit_during_initialization("Could not allocate root MemRegion set.");
+ }
}
-void G1CMRootRegions::reset() {
+G1CMRootMemRegions::~G1CMRootMemRegions() {
+ delete[] _root_regions;
+}
+
+void G1CMRootMemRegions::reset() {
_num_root_regions = 0;
}
-void G1CMRootRegions::add(HeapRegion* hr) {
+void G1CMRootMemRegions::add(HeapWord* start, HeapWord* end) {
assert_at_safepoint();
size_t idx = Atomic::add((size_t)1, &_num_root_regions) - 1;
- assert(idx < _max_regions, "Trying to add more root regions than there is space " SIZE_FORMAT, _max_regions);
- _root_regions[idx] = hr;
+ assert(idx < _max_regions, "Trying to add more root MemRegions than there is space " SIZE_FORMAT, _max_regions);
+ assert(start != NULL && end != NULL && start <= end, "Start (" PTR_FORMAT ") should be less or equal to "
+ "end (" PTR_FORMAT ")", p2i(start), p2i(end));
+ _root_regions[idx].set_start(start);
+ _root_regions[idx].set_end(end);
}
-void G1CMRootRegions::prepare_for_scan() {
+void G1CMRootMemRegions::prepare_for_scan() {
assert(!scan_in_progress(), "pre-condition");
_scan_in_progress = _num_root_regions > 0;
@@ -289,7 +297,7 @@
_should_abort = false;
}
-HeapRegion* G1CMRootRegions::claim_next() {
+const MemRegion* G1CMRootMemRegions::claim_next() {
if (_should_abort) {
// If someone has set the should_abort flag, we return NULL to
// force the caller to bail out of their loop.
@@ -302,26 +310,26 @@
size_t claimed_index = Atomic::add((size_t)1, &_claimed_root_regions) - 1;
if (claimed_index < _num_root_regions) {
- return _root_regions[claimed_index];
+ return &_root_regions[claimed_index];
}
return NULL;
}
-uint G1CMRootRegions::num_root_regions() const {
+uint G1CMRootMemRegions::num_root_regions() const {
return (uint)_num_root_regions;
}
-void G1CMRootRegions::notify_scan_done() {
+void G1CMRootMemRegions::notify_scan_done() {
MutexLocker x(RootRegionScan_lock, Mutex::_no_safepoint_check_flag);
_scan_in_progress = false;
RootRegionScan_lock->notify_all();
}
-void G1CMRootRegions::cancel_scan() {
+void G1CMRootMemRegions::cancel_scan() {
notify_scan_done();
}
-void G1CMRootRegions::scan_finished() {
+void G1CMRootMemRegions::scan_finished() {
assert(scan_in_progress(), "pre-condition");
if (!_should_abort) {
@@ -333,7 +341,7 @@
notify_scan_done();
}
-bool G1CMRootRegions::wait_until_scan_finished() {
+bool G1CMRootMemRegions::wait_until_scan_finished() {
if (!scan_in_progress()) {
return false;
}
@@ -875,14 +883,21 @@
return result;
}
-void G1ConcurrentMark::scan_root_region(HeapRegion* hr, uint worker_id) {
- assert(hr->is_old() || (hr->is_survivor() && hr->next_top_at_mark_start() == hr->bottom()),
- "Root regions must be old or survivor but region %u is %s", hr->hrm_index(), hr->get_type_str());
+void G1ConcurrentMark::scan_root_region(const MemRegion* region, uint worker_id) {
+#ifdef ASSERT
+ HeapWord* last = region->last();
+ HeapRegion* hr = _g1h->heap_region_containing(last);
+ assert(hr->is_old() || hr->next_top_at_mark_start() == hr->bottom(),
+ "Root regions must be old or survivor/eden but region %u is %s", hr->hrm_index(), hr->get_type_str());
+ assert(hr->next_top_at_mark_start() == region->start(),
+ "MemRegion start should be equal to nTAMS");
+#endif
+
G1RootRegionScanClosure cl(_g1h, this, worker_id);
const uintx interval = PrefetchScanIntervalInBytes;
- HeapWord* curr = hr->next_top_at_mark_start();
- const HeapWord* end = hr->top();
+ HeapWord* curr = region->start();
+ const HeapWord* end = region->end();
while (curr < end) {
Prefetch::read(curr, interval);
oop obj = oop(curr);
@@ -902,11 +917,11 @@
assert(Thread::current()->is_ConcurrentGC_thread(),
"this should only be done by a conc GC thread");
- G1CMRootRegions* root_regions = _cm->root_regions();
- HeapRegion* hr = root_regions->claim_next();
- while (hr != NULL) {
- _cm->scan_root_region(hr, worker_id);
- hr = root_regions->claim_next();
+ G1CMRootMemRegions* root_regions = _cm->root_regions();
+ const MemRegion* region = root_regions->claim_next();
+ while (region != NULL) {
+ _cm->scan_root_region(region, worker_id);
+ region = root_regions->claim_next();
}
}
};
--- a/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp Wed Jun 12 10:02:49 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp Thu Jun 13 11:31:36 2019 +0530
@@ -222,18 +222,20 @@
template<typename Fn> void iterate(Fn fn) const PRODUCT_RETURN;
};
-// Root Regions are regions that contain objects from nTAMS to top. These are roots
-// for marking, i.e. their referenced objects must be kept alive to maintain the
+// Root MemRegions are memory areas that contain objects which references are
+// roots wrt to the marking. They must be scanned before marking to maintain the
// SATB invariant.
-// We could scan and mark them through during the initial-mark pause, but for
+// Typically they contain the areas from nTAMS to top of the regions.
+// We could scan and mark through these objects during the initial-mark pause, but for
// pause time reasons we move this work to the concurrent phase.
// We need to complete this procedure before the next GC because it might determine
// that some of these "root objects" are dead, potentially dropping some required
// references.
-// Root regions comprise of the complete contents of survivor regions, and any
-// objects copied into old gen during GC.
-class G1CMRootRegions {
- HeapRegion** _root_regions;
+// Root MemRegions comprise of the contents of survivor regions at the end
+// of the GC, and any objects copied into the old gen during GC.
+class G1CMRootMemRegions {
+ // The set of root MemRegions.
+ MemRegion* _root_regions;
size_t const _max_regions;
volatile size_t _num_root_regions; // Actual number of root regions.
@@ -246,13 +248,13 @@
void notify_scan_done();
public:
- G1CMRootRegions(uint const max_regions);
- ~G1CMRootRegions();
+ G1CMRootMemRegions(uint const max_regions);
+ ~G1CMRootMemRegions();
// Reset the data structure to allow addition of new root regions.
void reset();
- void add(HeapRegion* hr);
+ void add(HeapWord* start, HeapWord* end);
// Reset the claiming / scanning of the root regions.
void prepare_for_scan();
@@ -264,9 +266,9 @@
// false otherwise.
bool scan_in_progress() { return _scan_in_progress; }
- // Claim the next root region to scan atomically, or return NULL if
+ // Claim the next root MemRegion to scan atomically, or return NULL if
// all have been claimed.
- HeapRegion* claim_next();
+ const MemRegion* claim_next();
// The number of root regions to scan.
uint num_root_regions() const;
@@ -310,7 +312,7 @@
MemRegion const _heap;
// Root region tracking and claiming
- G1CMRootRegions _root_regions;
+ G1CMRootMemRegions _root_regions;
// For grey objects
G1CMMarkStack _global_mark_stack; // Grey objects behind global finger
@@ -501,7 +503,7 @@
size_t partial_mark_stack_size_target() const { return _global_mark_stack.capacity() / 3; }
bool mark_stack_empty() const { return _global_mark_stack.is_empty(); }
- G1CMRootRegions* root_regions() { return &_root_regions; }
+ G1CMRootMemRegions* root_regions() { return &_root_regions; }
void concurrent_cycle_start();
// Abandon current marking iteration due to a Full GC.
@@ -554,8 +556,8 @@
// them.
void scan_root_regions();
- // Scan a single root region from nTAMS to top and mark everything reachable from it.
- void scan_root_region(HeapRegion* hr, uint worker_id);
+ // Scan a single root MemRegion to mark everything reachable from it.
+ void scan_root_region(const MemRegion* region, uint worker_id);
// Do concurrent phase of marking, to a tentative transitive closure.
void mark_from_roots();
--- a/src/hotspot/share/jvmci/jvmciEnv.cpp Wed Jun 12 10:02:49 2019 +0530
+++ b/src/hotspot/share/jvmci/jvmciEnv.cpp Thu Jun 13 11:31:36 2019 +0530
@@ -1111,13 +1111,6 @@
if (klass.is_null()) {
return type;
}
-#ifdef INCLUDE_ALL_GCS
- if (UseG1GC) {
- // The klass might have come from a weak location so enqueue
- // the Class to make sure it's noticed by G1
- G1SATBCardTableModRefBS::enqueue(klass()->java_mirror());
- }
-#endif // Klass* don't require tracking as Metadata*
jlong pointer = (jlong) klass();
JavaThread* THREAD = JavaThread::current();
--- a/src/hotspot/share/memory/memRegion.hpp Wed Jun 12 10:02:49 2019 +0530
+++ b/src/hotspot/share/memory/memRegion.hpp Thu Jun 13 11:31:36 2019 +0530
@@ -32,13 +32,13 @@
// A very simple data structure representing a contigous region
// region of address space.
-// Note that MemRegions are passed by value, not by reference.
+// Note that MemRegions are typically passed by value, not by reference.
// The intent is that they remain very small and contain no
// objects. The copy constructor and destructor must be trivial,
// to support optimization for pass-by-value.
-// These should never be allocated in heap but we do
-// create MemRegions (in CardTableBarrierSet) in heap so operator
-// new and operator new [] added for this special case.
+// These should almost never be allocated in heap but we do
+// create MemRegions (in CardTable and G1CMRootMemRegions) on the heap so operator
+// new and operator new [] were added for these special cases.
class MemRegion {
friend class VMStructs;
--- a/src/hotspot/share/memory/metaspace.cpp Wed Jun 12 10:02:49 2019 +0530
+++ b/src/hotspot/share/memory/metaspace.cpp Thu Jun 13 11:31:36 2019 +0530
@@ -1221,7 +1221,7 @@
}
if (DynamicDumpSharedSpaces && !UseSharedSpaces) {
- vm_exit_during_initialization("DynamicDumpSharedSpaces not supported when base CDS archive is not loaded", NULL);
+ vm_exit_during_initialization("DynamicDumpSharedSpaces is unsupported when base CDS archive is not loaded", NULL);
}
if (!DumpSharedSpaces && !UseSharedSpaces)
--- a/src/hotspot/share/opto/graphKit.hpp Wed Jun 12 10:02:49 2019 +0530
+++ b/src/hotspot/share/opto/graphKit.hpp Thu Jun 13 11:31:36 2019 +0530
@@ -565,7 +565,7 @@
return store_to_memory(ctl, adr, val, bt,
C->get_alias_index(adr_type),
mo, require_atomic_access,
- unaligned, mismatched);
+ unaligned, mismatched, unsafe);
}
// This is the base version which is given alias index
// Return the new StoreXNode
--- a/src/hotspot/share/opto/library_call.cpp Wed Jun 12 10:02:49 2019 +0530
+++ b/src/hotspot/share/opto/library_call.cpp Thu Jun 13 11:31:36 2019 +0530
@@ -2439,7 +2439,10 @@
val = is_store ? argument(4) : NULL;
- const TypePtr *adr_type = _gvn.type(adr)->isa_ptr();
+ const TypePtr* adr_type = _gvn.type(adr)->isa_ptr();
+ if (adr_type == TypePtr::NULL_PTR) {
+ return false; // off-heap access with zero address
+ }
// Try to categorize the address.
Compile::AliasType* alias_type = C->alias_type(adr_type);
--- a/src/hotspot/share/opto/memnode.cpp Wed Jun 12 10:02:49 2019 +0530
+++ b/src/hotspot/share/opto/memnode.cpp Thu Jun 13 11:31:36 2019 +0530
@@ -44,6 +44,7 @@
#include "opto/narrowptrnode.hpp"
#include "opto/phaseX.hpp"
#include "opto/regmask.hpp"
+#include "opto/rootnode.hpp"
#include "utilities/align.hpp"
#include "utilities/copy.hpp"
#include "utilities/macros.hpp"
@@ -328,6 +329,24 @@
const Type *t_adr = phase->type(address);
if (t_adr == Type::TOP) return NodeSentinel; // caller will return NULL
+ if (can_reshape && is_unsafe_access() && (t_adr == TypePtr::NULL_PTR)) {
+ // Unsafe off-heap access with zero address. Remove access and other control users
+ // to not confuse optimizations and add a HaltNode to fail if this is ever executed.
+ assert(ctl != NULL, "unsafe accesses should be control dependent");
+ for (DUIterator_Fast imax, i = ctl->fast_outs(imax); i < imax; i++) {
+ Node* u = ctl->fast_out(i);
+ if (u != ctl) {
+ igvn->rehash_node_delayed(u);
+ int nb = u->replace_edge(ctl, phase->C->top());
+ --i, imax -= nb;
+ }
+ }
+ Node* frame = igvn->transform(new ParmNode(phase->C->start(), TypeFunc::FramePtr));
+ Node* halt = igvn->transform(new HaltNode(ctl, frame));
+ phase->C->root()->add_req(halt);
+ return this;
+ }
+
if (can_reshape && igvn != NULL &&
(igvn->_worklist.member(address) ||
(igvn->_worklist.size() > 0 && t_adr != adr_type())) ) {
--- a/src/hotspot/share/opto/output.cpp Wed Jun 12 10:02:49 2019 +0530
+++ b/src/hotspot/share/opto/output.cpp Thu Jun 13 11:31:36 2019 +0530
@@ -2412,12 +2412,9 @@
}
assert(!last->is_Mach() || last->as_Mach()->ideal_Opcode() != Op_Con, "");
if( last->is_Catch() ||
- // Exclude unreachable path case when Halt node is in a separate block.
- (_bb_end > 1 && last->is_Mach() && last->as_Mach()->ideal_Opcode() == Op_Halt) ) {
- // There must be a prior call. Skip it.
- while( !bb->get_node(--_bb_end)->is_MachCall() ) {
- assert( bb->get_node(_bb_end)->is_MachProj(), "skipping projections after expected call" );
- }
+ (last->is_Mach() && last->as_Mach()->ideal_Opcode() == Op_Halt) ) {
+ // There might be a prior call. Skip it.
+ while (_bb_start < _bb_end && bb->get_node(--_bb_end)->is_MachProj());
} else if( last->is_MachNullCheck() ) {
// Backup so the last null-checked memory instruction is
// outside the schedulable range. Skip over the nullcheck,
--- a/src/hotspot/share/runtime/objectMonitor.cpp Wed Jun 12 10:02:49 2019 +0530
+++ b/src/hotspot/share/runtime/objectMonitor.cpp Thu Jun 13 11:31:36 2019 +0530
@@ -245,9 +245,7 @@
void * cur = Atomic::cmpxchg(Self, &_owner, (void*)NULL);
if (cur == NULL) {
- // Either ASSERT _recursions == 0 or explicitly set _recursions = 0.
assert(_recursions == 0, "invariant");
- assert(_owner == Self, "invariant");
return;
}
@@ -405,9 +403,7 @@
void * own = _owner;
if (own != NULL) return 0;
if (Atomic::replace_if_null(Self, &_owner)) {
- // Either guarantee _recursions == 0 or set _recursions = 0.
assert(_recursions == 0, "invariant");
- assert(_owner == Self, "invariant");
return 1;
}
// The lock had been free momentarily, but we lost the race to the lock.
@@ -417,6 +413,15 @@
return -1;
}
+// Convert the fields used by is_busy() to a string that can be
+// used for diagnostic output.
+const char* ObjectMonitor::is_busy_to_string(stringStream* ss) {
+ ss->print("is_busy: contentions=%d, waiters=%d, owner=" INTPTR_FORMAT
+ ", cxq=" INTPTR_FORMAT ", EntryList=" INTPTR_FORMAT, _contentions,
+ _waiters, p2i(_owner), p2i(_cxq), p2i(_EntryList));
+ return ss->base();
+}
+
#define MAX_RECHECK_INTERVAL 1000
void ObjectMonitor::EnterI(TRAPS) {
--- a/src/hotspot/share/runtime/objectMonitor.hpp Wed Jun 12 10:02:49 2019 +0530
+++ b/src/hotspot/share/runtime/objectMonitor.hpp Thu Jun 13 11:31:36 2019 +0530
@@ -235,6 +235,7 @@
// TODO-FIXME: assert _owner == null implies _recursions = 0
return _contentions|_waiters|intptr_t(_owner)|intptr_t(_cxq)|intptr_t(_EntryList);
}
+ const char* is_busy_to_string(stringStream* ss);
intptr_t is_entered(Thread* current) const;
@@ -268,7 +269,9 @@
// _cxq == 0 _succ == NULL _owner == NULL _waiters == 0
// _contentions == 0 EntryList == NULL
// _recursions == 0 _WaitSet == NULL
- assert(((is_busy()|_recursions) == 0), "freeing inuse monitor");
+ DEBUG_ONLY(stringStream ss;)
+ assert((is_busy() | _recursions) == 0, "freeing in-use monitor: %s, "
+ "recursions=" INTPTR_FORMAT, is_busy_to_string(&ss), _recursions);
_succ = NULL;
_EntryList = NULL;
_cxq = NULL;
--- a/src/hotspot/share/runtime/objectMonitor.inline.hpp Wed Jun 12 10:02:49 2019 +0530
+++ b/src/hotspot/share/runtime/objectMonitor.inline.hpp Thu Jun 13 11:31:36 2019 +0530
@@ -95,12 +95,8 @@
return _contentions;
}
-// Do NOT set _contentions = 0. There is a race such that _contentions could
-// be set while inflating prior to setting _owner
-// Just use Atomic::inc/dec and assert 0 when monitor put on free list
inline void ObjectMonitor::set_owner(void* owner) {
_owner = owner;
- _recursions = 0;
}
#endif // SHARE_RUNTIME_OBJECTMONITOR_INLINE_HPP
--- a/src/hotspot/share/runtime/synchronizer.cpp Wed Jun 12 10:02:49 2019 +0530
+++ b/src/hotspot/share/runtime/synchronizer.cpp Thu Jun 13 11:31:36 2019 +0530
@@ -242,7 +242,6 @@
if (owner == NULL && Atomic::replace_if_null(Self, &(m->_owner))) {
assert(m->_recursions == 0, "invariant");
- assert(m->_owner == Self, "invariant");
return true;
}
}
@@ -1030,6 +1029,7 @@
// scavenge costs. As usual, we lean toward time in space-time
// tradeoffs.
const int MAXPRIVATE = 1024;
+ stringStream ss;
for (;;) {
ObjectMonitor * m;
@@ -1065,7 +1065,6 @@
ObjectMonitor * take = gFreeList;
gFreeList = take->FreeNext;
guarantee(take->object() == NULL, "invariant");
- guarantee(!take->is_busy(), "invariant");
take->Recycle();
omRelease(Self, take, false);
}
@@ -1167,7 +1166,10 @@
bool fromPerThreadAlloc) {
guarantee(m->header() == NULL, "invariant");
guarantee(m->object() == NULL, "invariant");
- guarantee(((m->is_busy()|m->_recursions) == 0), "freeing in-use monitor");
+ stringStream ss;
+ guarantee((m->is_busy() | m->_recursions) == 0, "freeing in-use monitor: "
+ "%s, recursions=" INTPTR_FORMAT, m->is_busy_to_string(&ss),
+ m->_recursions);
// Remove from omInUseList
if (fromPerThreadAlloc) {
ObjectMonitor* cur_mid_in_use = NULL;
@@ -1220,16 +1222,14 @@
int tally = 0;
if (list != NULL) {
ObjectMonitor * s;
- // The thread is going away, the per-thread free monitors
- // are freed via set_owner(NULL)
- // Link them to tail, which will be linked into the global free list
- // gFreeList below, under the gListLock
+ // The thread is going away. Set 'tail' to the last per-thread free
+ // monitor which will be linked to gFreeList below under the gListLock.
+ stringStream ss;
for (s = list; s != NULL; s = s->FreeNext) {
tally++;
tail = s;
guarantee(s->object() == NULL, "invariant");
- guarantee(!s->is_busy(), "invariant");
- s->set_owner(NULL); // redundant but good hygiene
+ guarantee(!s->is_busy(), "must be !is_busy: %s", s->is_busy_to_string(&ss));
}
guarantee(tail != NULL, "invariant");
assert(Self->omFreeCount == tally, "free-count off");
@@ -1379,7 +1379,6 @@
// in which INFLATING appears in the mark.
m->Recycle();
m->_Responsible = NULL;
- m->_recursions = 0;
m->_SpinDuration = ObjectMonitor::Knob_SpinLimit; // Consider: maintain by type/class
markOop cmp = object->cas_set_mark(markOopDesc::INFLATING(), mark);
@@ -1472,9 +1471,7 @@
// prepare m for installation - set monitor to initial state
m->Recycle();
m->set_header(mark);
- m->set_owner(NULL);
m->set_object(object);
- m->_recursions = 0;
m->_Responsible = NULL;
m->_SpinDuration = ObjectMonitor::Knob_SpinLimit; // consider: keep metastats by type/class
@@ -1925,14 +1922,15 @@
// Check a free monitor entry; log any errors.
void ObjectSynchronizer::chk_free_entry(JavaThread * jt, ObjectMonitor * n,
outputStream * out, int *error_cnt_p) {
+ stringStream ss;
if (n->is_busy()) {
if (jt != NULL) {
out->print_cr("ERROR: jt=" INTPTR_FORMAT ", monitor=" INTPTR_FORMAT
- ": free per-thread monitor must not be busy.", p2i(jt),
- p2i(n));
+ ": free per-thread monitor must not be busy: %s", p2i(jt),
+ p2i(n), n->is_busy_to_string(&ss));
} else {
out->print_cr("ERROR: monitor=" INTPTR_FORMAT ": free global monitor "
- "must not be busy.", p2i(n));
+ "must not be busy: %s", p2i(n), n->is_busy_to_string(&ss));
}
*error_cnt_p = *error_cnt_p + 1;
}
@@ -2111,6 +2109,7 @@
Thread::muxAcquire(&gListLock, "log_in_use_monitor_details");
}
+ stringStream ss;
if (gOmInUseCount > 0) {
out->print_cr("In-use global monitor info:");
out->print_cr("(B -> is_busy, H -> has hash code, L -> lock status)");
@@ -2121,9 +2120,14 @@
const oop obj = (oop) n->object();
const markOop mark = n->header();
ResourceMark rm;
- out->print_cr(INTPTR_FORMAT " %d%d%d " INTPTR_FORMAT " %s", p2i(n),
- n->is_busy() != 0, mark->hash() != 0, n->owner() != NULL,
- p2i(obj), obj->klass()->external_name());
+ out->print(INTPTR_FORMAT " %d%d%d " INTPTR_FORMAT " %s", p2i(n),
+ n->is_busy() != 0, mark->hash() != 0, n->owner() != NULL,
+ p2i(obj), obj->klass()->external_name());
+ if (n->is_busy() != 0) {
+ out->print(" (%s)", n->is_busy_to_string(&ss));
+ ss.reset();
+ }
+ out->cr();
}
}
@@ -2141,10 +2145,15 @@
const oop obj = (oop) n->object();
const markOop mark = n->header();
ResourceMark rm;
- out->print_cr(INTPTR_FORMAT " " INTPTR_FORMAT " %d%d%d " INTPTR_FORMAT
- " %s", p2i(jt), p2i(n), n->is_busy() != 0,
- mark->hash() != 0, n->owner() != NULL, p2i(obj),
- obj->klass()->external_name());
+ out->print(INTPTR_FORMAT " " INTPTR_FORMAT " %d%d%d " INTPTR_FORMAT
+ " %s", p2i(jt), p2i(n), n->is_busy() != 0,
+ mark->hash() != 0, n->owner() != NULL, p2i(obj),
+ obj->klass()->external_name());
+ if (n->is_busy() != 0) {
+ out->print(" (%s)", n->is_busy_to_string(&ss));
+ ss.reset();
+ }
+ out->cr();
}
}
--- a/src/java.base/share/classes/java/lang/ref/Reference.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/java.base/share/classes/java/lang/ref/Reference.java Thu Jun 13 11:31:36 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -418,10 +418,10 @@
* {@code synchronized} blocks or methods, or using other synchronization
* facilities are not possible or do not provide the desired control. This
* method is applicable only when reclamation may have visible effects,
- * which is possible for objects with finalizers (See
- * <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-12.html#jls-12.6">
- * Section 12.6 17 of <cite>The Java™ Language Specification</cite></a>)
- * that are implemented in ways that rely on ordering control for correctness.
+ * which is possible for objects with finalizers (See Section 12.6
+ * of <cite>The Java™ Language Specification</cite>) that
+ * are implemented in ways that rely on ordering control for
+ * correctness.
*
* @apiNote
* Finalization may occur whenever the virtual machine detects that no
@@ -508,6 +508,7 @@
*
* @param ref the reference. If {@code null}, this method has no effect.
* @since 9
+ * @jls 12.6 Finalization of Class Instances
*/
@ForceInline
public static void reachabilityFence(Object ref) {
--- a/src/java.base/share/classes/java/net/SocketImpl.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/java.base/share/classes/java/net/SocketImpl.java Thu Jun 13 11:31:36 2019 +0530
@@ -396,7 +396,7 @@
*
* @implSpec
* The default implementation of this method first checks that the given
- * socket option {code name} is not null, then throws {@code
+ * socket option {@code name} is not null, then throws {@code
* UnsupportedOperationException}. Subclasses should override this method
* with an appropriate implementation.
*
@@ -424,7 +424,7 @@
*
* @implSpec
* The default implementation of this method first checks that the given
- * socket option {code name} is not null, then throws {@code
+ * socket option {@code name} is not null, then throws {@code
* UnsupportedOperationException}. Subclasses should override this method
* with an appropriate implementation.
*
--- a/src/java.base/share/classes/sun/security/ssl/CipherSuite.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/CipherSuite.java Thu Jun 13 11:31:36 2019 +0530
@@ -35,8 +35,8 @@
import static sun.security.ssl.CipherSuite.KeyExchange.*;
import static sun.security.ssl.CipherSuite.MacAlg.*;
import static sun.security.ssl.SSLCipher.*;
-import sun.security.ssl.SupportedGroupsExtension.NamedGroupType;
-import static sun.security.ssl.SupportedGroupsExtension.NamedGroupType.*;
+import sun.security.ssl.NamedGroup.NamedGroupType;
+import static sun.security.ssl.NamedGroup.NamedGroupType.*;
/**
* Enum for SSL/(D)TLS cipher suites.
@@ -184,7 +184,7 @@
K_DHE_DSS, B_AES_128, M_SHA256, H_SHA256),
//
- // not forward screcy cipher suites.
+ // not forward secret cipher suites.
//
// AES_256(GCM)
@@ -1106,11 +1106,18 @@
K_DH_ANON ("DH_anon", true, true, NAMED_GROUP_FFDHE),
K_DH_ANON_EXPORT("DH_anon_EXPORT", true, true, NAMED_GROUP_NONE),
- K_ECDH_ECDSA ("ECDH_ECDSA", true, false, NAMED_GROUP_ECDHE),
- K_ECDH_RSA ("ECDH_RSA", true, false, NAMED_GROUP_ECDHE),
- K_ECDHE_ECDSA ("ECDHE_ECDSA", true, false, NAMED_GROUP_ECDHE),
- K_ECDHE_RSA ("ECDHE_RSA", true, false, NAMED_GROUP_ECDHE),
- K_ECDH_ANON ("ECDH_anon", true, true, NAMED_GROUP_ECDHE),
+ // These KeyExchanges can use either ECDHE/XDH, so we'll use a
+ // varargs here.
+ K_ECDH_ECDSA ("ECDH_ECDSA", JsseJce.ALLOW_ECC, false,
+ NAMED_GROUP_ECDHE, NAMED_GROUP_XDH),
+ K_ECDH_RSA ("ECDH_RSA", JsseJce.ALLOW_ECC, false,
+ NAMED_GROUP_ECDHE, NAMED_GROUP_XDH),
+ K_ECDHE_ECDSA ("ECDHE_ECDSA", JsseJce.ALLOW_ECC, false,
+ NAMED_GROUP_ECDHE, NAMED_GROUP_XDH),
+ K_ECDHE_RSA ("ECDHE_RSA", JsseJce.ALLOW_ECC, false,
+ NAMED_GROUP_ECDHE, NAMED_GROUP_XDH),
+ K_ECDH_ANON ("ECDH_anon", JsseJce.ALLOW_ECC, true,
+ NAMED_GROUP_ECDHE, NAMED_GROUP_XDH),
// renegotiation protection request signaling cipher suite
K_SCSV ("SCSV", true, true, NAMED_GROUP_NONE);
@@ -1118,19 +1125,16 @@
// name of the key exchange algorithm, e.g. DHE_DSS
final String name;
final boolean allowed;
- final NamedGroupType groupType;
+ final NamedGroupType[] groupTypes;
private final boolean alwaysAvailable;
private final boolean isAnonymous;
KeyExchange(String name, boolean allowed,
- boolean isAnonymous, NamedGroupType groupType) {
+ boolean isAnonymous, NamedGroupType... groupTypes) {
this.name = name;
- if (groupType == NAMED_GROUP_ECDHE) {
- this.allowed = JsseJce.ALLOW_ECC;
- } else {
- this.allowed = allowed;
- }
- this.groupType = groupType;
+ this.groupTypes = groupTypes;
+ this.allowed = allowed;
+
this.alwaysAvailable = allowed && (!name.startsWith("EC"));
this.isAnonymous = isAnonymous;
}
@@ -1140,7 +1144,8 @@
return true;
}
- if (groupType == NAMED_GROUP_ECDHE) {
+ if (NamedGroupType.arrayContains(
+ groupTypes, NamedGroupType.NAMED_GROUP_ECDHE)) {
return (allowed && JsseJce.isEcAvailable());
} else {
return allowed;
--- a/src/java.base/share/classes/sun/security/ssl/DHClientKeyExchange.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/DHClientKeyExchange.java Thu Jun 13 11:31:36 2019 +0530
@@ -42,7 +42,6 @@
import sun.security.ssl.DHKeyExchange.DHECredentials;
import sun.security.ssl.DHKeyExchange.DHEPossession;
import sun.security.ssl.SSLHandshake.HandshakeMessage;
-import sun.security.ssl.SupportedGroupsExtension.NamedGroup;
import sun.security.util.HexDumpEncoder;
/**
--- a/src/java.base/share/classes/sun/security/ssl/DHKeyExchange.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/DHKeyExchange.java Thu Jun 13 11:31:36 2019 +0530
@@ -36,19 +36,12 @@
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
-import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidKeySpecException;
-import javax.crypto.KeyAgreement;
-import javax.crypto.SecretKey;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;
import javax.crypto.spec.DHPublicKeySpec;
-import javax.crypto.spec.SecretKeySpec;
-import javax.net.ssl.SSLHandshakeException;
import sun.security.action.GetPropertyAction;
-import sun.security.ssl.CipherSuite.HashAlg;
-import sun.security.ssl.SupportedGroupsExtension.NamedGroup;
-import sun.security.ssl.SupportedGroupsExtension.NamedGroupType;
+import sun.security.ssl.NamedGroup.NamedGroupType;
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
import sun.security.ssl.X509Authentication.X509Possession;
import sun.security.util.KeyUtil;
@@ -61,7 +54,7 @@
static final SSLKeyAgreementGenerator kaGenerator =
new DHEKAGenerator();
- static final class DHECredentials implements SSLCredentials {
+ static final class DHECredentials implements NamedGroupCredentials {
final DHPublicKey popPublicKey;
final NamedGroup namedGroup;
@@ -70,6 +63,16 @@
this.namedGroup = namedGroup;
}
+ @Override
+ public PublicKey getPublicKey() {
+ return popPublicKey;
+ }
+
+ @Override
+ public NamedGroup getNamedGroup() {
+ return namedGroup;
+ }
+
static DHECredentials valueOf(NamedGroup ng,
byte[] encodedPublic) throws IOException, GeneralSecurityException {
@@ -98,7 +101,7 @@
}
}
- static final class DHEPossession implements SSLPossession {
+ static final class DHEPossession implements NamedGroupPossession {
final PrivateKey privateKey;
final DHPublicKey publicKey;
final NamedGroup namedGroup;
@@ -174,13 +177,13 @@
// Generate and validate DHPublicKeySpec
private KeyPair generateDHKeyPair(
KeyPairGenerator kpg) throws GeneralSecurityException {
- boolean doExtraValiadtion =
+ boolean doExtraValidation =
(!KeyUtil.isOracleJCEProvider(kpg.getProvider().getName()));
boolean isRecovering = false;
for (int i = 0; i <= 2; i++) { // Try to recover from failure.
KeyPair kp = kpg.generateKeyPair();
// validate the Diffie-Hellman public key
- if (doExtraValiadtion) {
+ if (doExtraValidation) {
DHPublicKeySpec spec = getDHPublicKeySpec(kp.getPublic());
try {
KeyUtil.validate(spec);
@@ -231,6 +234,21 @@
return encoded;
}
+
+ @Override
+ public PublicKey getPublicKey() {
+ return publicKey;
+ }
+
+ @Override
+ public NamedGroup getNamedGroup() {
+ return namedGroup;
+ }
+
+ @Override
+ public PrivateKey getPrivateKey() {
+ return privateKey;
+ }
}
private static final class
@@ -298,7 +316,7 @@
// Used for ServerKeyExchange, TLS 1.2 and prior versions.
@Override
public SSLPossession createPossession(HandshakeContext context) {
- NamedGroup preferableNamedGroup = null;
+ NamedGroup preferableNamedGroup;
if (!useLegacyEphemeralDHKeys &&
(context.clientRequestedNamedGroups != null) &&
(!context.clientRequestedNamedGroups.isEmpty())) {
@@ -306,7 +324,8 @@
SupportedGroups.getPreferredGroup(
context.negotiatedProtocol,
context.algorithmConstraints,
- NamedGroupType.NAMED_GROUP_FFDHE,
+ new NamedGroupType [] {
+ NamedGroupType.NAMED_GROUP_FFDHE },
context.clientRequestedNamedGroups);
if (preferableNamedGroup != null) {
return new DHEPossession(preferableNamedGroup,
@@ -392,7 +411,7 @@
private static final
class DHEKAGenerator implements SSLKeyAgreementGenerator {
- static private DHEKAGenerator instance = new DHEKAGenerator();
+ private static final DHEKAGenerator instance = new DHEKAGenerator();
// Prevent instantiation of this class.
private DHEKAGenerator() {
@@ -442,93 +461,8 @@
"No sufficient DHE key agreement parameters negotiated");
}
- return new DHEKAKeyDerivation(context,
+ return new KAKeyDerivation("DiffieHellman", context,
dhePossession.privateKey, dheCredentials.popPublicKey);
}
-
- private static final
- class DHEKAKeyDerivation implements SSLKeyDerivation {
- private final HandshakeContext context;
- private final PrivateKey localPrivateKey;
- private final PublicKey peerPublicKey;
-
- DHEKAKeyDerivation(HandshakeContext context,
- PrivateKey localPrivateKey,
- PublicKey peerPublicKey) {
- this.context = context;
- this.localPrivateKey = localPrivateKey;
- this.peerPublicKey = peerPublicKey;
- }
-
- @Override
- public SecretKey deriveKey(String algorithm,
- AlgorithmParameterSpec params) throws IOException {
- if (!context.negotiatedProtocol.useTLS13PlusSpec()) {
- return t12DeriveKey(algorithm, params);
- } else {
- return t13DeriveKey(algorithm, params);
- }
- }
-
- private SecretKey t12DeriveKey(String algorithm,
- AlgorithmParameterSpec params) throws IOException {
- try {
- KeyAgreement ka = KeyAgreement.getInstance("DiffieHellman");
- ka.init(localPrivateKey);
- ka.doPhase(peerPublicKey, true);
- SecretKey preMasterSecret =
- ka.generateSecret("TlsPremasterSecret");
- SSLMasterKeyDerivation mskd =
- SSLMasterKeyDerivation.valueOf(
- context.negotiatedProtocol);
- if (mskd == null) {
- // unlikely
- throw new SSLHandshakeException(
- "No expected master key derivation for protocol: " +
- context.negotiatedProtocol.name);
- }
- SSLKeyDerivation kd = mskd.createKeyDerivation(
- context, preMasterSecret);
- return kd.deriveKey("MasterSecret", params);
- } catch (GeneralSecurityException gse) {
- throw (SSLHandshakeException) new SSLHandshakeException(
- "Could not generate secret").initCause(gse);
- }
- }
-
- private SecretKey t13DeriveKey(String algorithm,
- AlgorithmParameterSpec params) throws IOException {
- try {
- KeyAgreement ka = KeyAgreement.getInstance("DiffieHellman");
- ka.init(localPrivateKey);
- ka.doPhase(peerPublicKey, true);
- SecretKey sharedSecret =
- ka.generateSecret("TlsPremasterSecret");
-
- HashAlg hashAlg = context.negotiatedCipherSuite.hashAlg;
- SSLKeyDerivation kd = context.handshakeKeyDerivation;
- HKDF hkdf = new HKDF(hashAlg.name);
- if (kd == null) { // No PSK is in use.
- // If PSK is not in use Early Secret will still be
- // HKDF-Extract(0, 0).
- byte[] zeros = new byte[hashAlg.hashLength];
- SecretKeySpec ikm =
- new SecretKeySpec(zeros, "TlsPreSharedSecret");
- SecretKey earlySecret =
- hkdf.extract(zeros, ikm, "TlsEarlySecret");
- kd = new SSLSecretDerivation(context, earlySecret);
- }
-
- // derive salt secret
- SecretKey saltSecret = kd.deriveKey("TlsSaltSecret", null);
-
- // derive handshake secret
- return hkdf.extract(saltSecret, sharedSecret, algorithm);
- } catch (GeneralSecurityException gse) {
- throw (SSLHandshakeException) new SSLHandshakeException(
- "Could not generate secret").initCause(gse);
- }
- }
- }
}
}
--- a/src/java.base/share/classes/sun/security/ssl/DHServerKeyExchange.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/DHServerKeyExchange.java Thu Jun 13 11:31:36 2019 +0530
@@ -48,7 +48,6 @@
import sun.security.ssl.DHKeyExchange.DHECredentials;
import sun.security.ssl.DHKeyExchange.DHEPossession;
import sun.security.ssl.SSLHandshake.HandshakeMessage;
-import sun.security.ssl.SupportedGroupsExtension.NamedGroup;
import sun.security.ssl.X509Authentication.X509Credentials;
import sun.security.ssl.X509Authentication.X509Possession;
import sun.security.util.HexDumpEncoder;
--- a/src/java.base/share/classes/sun/security/ssl/ECDHClientKeyExchange.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/ECDHClientKeyExchange.java Thu Jun 13 11:31:36 2019 +0530
@@ -27,31 +27,28 @@
import java.io.IOException;
import java.nio.ByteBuffer;
-import java.security.AlgorithmConstraints;
-import java.security.CryptoPrimitive;
import java.security.GeneralSecurityException;
-import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.interfaces.ECPublicKey;
+import java.security.interfaces.XECPublicKey;
+import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.ECParameterSpec;
-import java.security.spec.ECPoint;
-import java.security.spec.ECPublicKeySpec;
+import java.security.spec.NamedParameterSpec;
import java.text.MessageFormat;
-import java.util.EnumSet;
import java.util.Locale;
import javax.crypto.SecretKey;
-import javax.net.ssl.SSLHandshakeException;
-import sun.security.ssl.ECDHKeyExchange.ECDHECredentials;
-import sun.security.ssl.ECDHKeyExchange.ECDHEPossession;
import sun.security.ssl.SSLHandshake.HandshakeMessage;
-import sun.security.ssl.SupportedGroupsExtension.NamedGroup;
import sun.security.ssl.X509Authentication.X509Credentials;
import sun.security.ssl.X509Authentication.X509Possession;
-import sun.security.util.ECUtil;
import sun.security.util.HexDumpEncoder;
/**
* Pack of the "ClientKeyExchange" handshake message.
+ *
+ * This file is used by both the ECDH/ECDHE/XDH code since much of the
+ * code is the same between the EC named groups (i.e.
+ * x25519/x448/secp*r1), even though the APIs are very different (i.e.
+ * ECPublicKey/XECPublicKey, KeyExchange.getInstance("EC"/"XDH"), etc.).
*/
final class ECDHClientKeyExchange {
static final SSLConsumer ecdhHandshakeConsumer =
@@ -65,19 +62,17 @@
new ECDHEClientKeyExchangeProducer();
/**
- * The ECDH/ECDHE ClientKeyExchange handshake message.
+ * The ECDH/ECDHE/XDH ClientKeyExchange handshake message.
*/
private static final
class ECDHClientKeyExchangeMessage extends HandshakeMessage {
private final byte[] encodedPoint;
ECDHClientKeyExchangeMessage(HandshakeContext handshakeContext,
- ECPublicKey publicKey) {
+ byte[] encodedPublicKey) {
super(handshakeContext);
- ECPoint point = publicKey.getW();
- ECParameterSpec params = publicKey.getParams();
- encodedPoint = ECUtil.encodePoint(point, params.getCurve());
+ this.encodedPoint = encodedPublicKey;
}
ECDHClientKeyExchangeMessage(HandshakeContext handshakeContext,
@@ -90,34 +85,6 @@
}
}
- // Check constraints of the specified EC public key.
- static void checkConstraints(AlgorithmConstraints constraints,
- ECPublicKey publicKey,
- byte[] encodedPoint) throws SSLHandshakeException {
-
- try {
- ECParameterSpec params = publicKey.getParams();
- ECPoint point =
- ECUtil.decodePoint(encodedPoint, params.getCurve());
- ECPublicKeySpec spec = new ECPublicKeySpec(point, params);
-
- KeyFactory kf = KeyFactory.getInstance("EC");
- ECPublicKey peerPublicKey =
- (ECPublicKey)kf.generatePublic(spec);
-
- // check constraints of ECPublicKey
- if (!constraints.permits(
- EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
- peerPublicKey)) {
- throw new SSLHandshakeException(
- "ECPublicKey does not comply to algorithm constraints");
- }
- } catch (GeneralSecurityException | java.io.IOException e) {
- throw (SSLHandshakeException) new SSLHandshakeException(
- "Could not generate ECPublicKey").initCause(e);
- }
- }
-
@Override
public SSLHandshake handshakeType() {
return SSLHandshake.CLIENT_KEY_EXCHANGE;
@@ -194,24 +161,41 @@
}
PublicKey publicKey = x509Credentials.popPublicKey;
- if (!publicKey.getAlgorithm().equals("EC")) {
+
+ NamedGroup namedGroup = null;
+ String algorithm = publicKey.getAlgorithm();
+
+ // Determine which NamedGroup we'll be using, then use
+ // the creator functions.
+ if (algorithm.equals("EC")) {
+ ECParameterSpec params = ((ECPublicKey)publicKey).getParams();
+ namedGroup = NamedGroup.valueOf(params);
+ } else if (algorithm.equals("XDH")) {
+ AlgorithmParameterSpec params =
+ ((XECPublicKey)publicKey).getParams();
+ if (params instanceof NamedParameterSpec) {
+ String name = ((NamedParameterSpec)params).getName();
+ namedGroup = NamedGroup.nameOf(name);
+ }
+ } else {
throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
- "Not EC server certificate for ECDH client key exchange");
+ "Not EC/XDH server certificate for " +
+ "ECDH client key exchange");
}
- ECParameterSpec params = ((ECPublicKey)publicKey).getParams();
- NamedGroup namedGroup = NamedGroup.valueOf(params);
if (namedGroup == null) {
throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
- "Unsupported EC server cert for ECDH client key exchange");
+ "Unsupported EC/XDH server cert for " +
+ "ECDH client key exchange");
}
- ECDHEPossession ecdhePossession = new ECDHEPossession(
- namedGroup, chc.sslContext.getSecureRandom());
- chc.handshakePossessions.add(ecdhePossession);
+ SSLPossession sslPossession = namedGroup.createPossession(
+ chc.sslContext.getSecureRandom());
+
+ chc.handshakePossessions.add(sslPossession);
ECDHClientKeyExchangeMessage cke =
new ECDHClientKeyExchangeMessage(
- chc, ecdhePossession.publicKey);
+ chc, sslPossession.encode());
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.fine(
"Produced ECDH ClientKeyExchange handshake message", cke);
@@ -283,18 +267,35 @@
"No expected EC server cert for ECDH client key exchange");
}
- ECParameterSpec params = x509Possession.getECParameterSpec();
- if (params == null) {
+ // Determine which NamedGroup we'll be using, then use
+ // the creator functions.
+ NamedGroup namedGroup = null;
+
+ // Iteratively determine the X509Possession type's ParameterSpec.
+ ECParameterSpec ecParams = x509Possession.getECParameterSpec();
+ NamedParameterSpec namedParams = null;
+ if (ecParams != null) {
+ namedGroup = NamedGroup.valueOf(ecParams);
+ }
+
+ // Wasn't EC, try XEC.
+ if (ecParams == null) {
+ namedParams = x509Possession.getXECParameterSpec();
+ namedGroup = NamedGroup.nameOf(namedParams.getName());
+ }
+
+ // Can't figure this out, bail.
+ if ((ecParams == null) && (namedParams == null)) {
// unlikely, have been checked during cipher suite negotiation.
throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
- "Not EC server cert for ECDH client key exchange");
+ "Not EC/XDH server cert for ECDH client key exchange");
}
- NamedGroup namedGroup = NamedGroup.valueOf(params);
+ // unlikely, have been checked during cipher suite negotiation.
if (namedGroup == null) {
- // unlikely, have been checked during cipher suite negotiation.
throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
- "Unsupported EC server cert for ECDH client key exchange");
+ "Unknown named group in server cert for " +
+ "ECDH client key exchange");
}
SSLKeyExchange ke = SSLKeyExchange.valueOf(
@@ -306,7 +307,7 @@
"Not supported key exchange type");
}
- // parse the handshake message
+ // parse either handshake message containing either EC/XEC.
ECDHClientKeyExchangeMessage cke =
new ECDHClientKeyExchangeMessage(shc, message);
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
@@ -316,27 +317,17 @@
// create the credentials
try {
- ECPoint point =
- ECUtil.decodePoint(cke.encodedPoint, params.getCurve());
- ECPublicKeySpec spec = new ECPublicKeySpec(point, params);
-
- KeyFactory kf = KeyFactory.getInstance("EC");
- ECPublicKey peerPublicKey =
- (ECPublicKey)kf.generatePublic(spec);
+ NamedGroup ng = namedGroup; // "effectively final" the lambda
+ // AlgorithmConstraints are checked internally.
+ SSLCredentials sslCredentials = namedGroup.decodeCredentials(
+ cke.encodedPoint, shc.algorithmConstraints,
+ s -> shc.conContext.fatal(Alert.INSUFFICIENT_SECURITY,
+ "ClientKeyExchange " + ng + ": " + s));
- // check constraints of peer ECPublicKey
- if (!shc.algorithmConstraints.permits(
- EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
- peerPublicKey)) {
- throw new SSLHandshakeException(
- "ECPublicKey does not comply to algorithm constraints");
- }
-
- shc.handshakeCredentials.add(new ECDHECredentials(
- peerPublicKey, namedGroup));
- } catch (GeneralSecurityException | java.io.IOException e) {
- throw (SSLHandshakeException)(new SSLHandshakeException(
- "Could not generate ECPublicKey").initCause(e));
+ shc.handshakeCredentials.add(sslCredentials);
+ } catch (GeneralSecurityException e) {
+ throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
+ "Cannot decode ECDH PublicKey: " + namedGroup);
}
// update the states
@@ -374,25 +365,37 @@
// The producing happens in client side only.
ClientHandshakeContext chc = (ClientHandshakeContext)context;
- ECDHECredentials ecdheCredentials = null;
+ SSLCredentials sslCredentials = null;
+ NamedGroup ng = null;
+ PublicKey publicKey = null;
+
+ // Find a good EC/XEC credential to use, determine the
+ // NamedGroup to use for creating Possessions/Credentials/Keys.
for (SSLCredentials cd : chc.handshakeCredentials) {
- if (cd instanceof ECDHECredentials) {
- ecdheCredentials = (ECDHECredentials)cd;
+ if (cd instanceof NamedGroupCredentials) {
+ NamedGroupCredentials creds = (NamedGroupCredentials)cd;
+ ng = creds.getNamedGroup();
+ publicKey = creds.getPublicKey();
+ sslCredentials = cd;
break;
}
}
- if (ecdheCredentials == null) {
+ if (sslCredentials == null) {
throw chc.conContext.fatal(Alert.INTERNAL_ERROR,
"No ECDHE credentials negotiated for client key exchange");
}
- ECDHEPossession ecdhePossession = new ECDHEPossession(
- ecdheCredentials, chc.sslContext.getSecureRandom());
- chc.handshakePossessions.add(ecdhePossession);
+ SSLPossession sslPossession = ng.createPossession(
+ chc.sslContext.getSecureRandom());
+
+ chc.handshakePossessions.add(sslPossession);
+
+ // Write the EC/XEC message.
ECDHClientKeyExchangeMessage cke =
new ECDHClientKeyExchangeMessage(
- chc, ecdhePossession.publicKey);
+ chc, sslPossession.encode());
+
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.fine(
"Produced ECDHE ClientKeyExchange handshake message", cke);
@@ -450,23 +453,29 @@
// The consuming happens in server side only.
ServerHandshakeContext shc = (ServerHandshakeContext)context;
- ECDHEPossession ecdhePossession = null;
+ SSLPossession sslPossession = null;
+ NamedGroup namedGroup = null;
+
+ // Find a good EC/XEC credential to use, determine the
+ // NamedGroup to use for creating Possessions/Credentials/Keys.
for (SSLPossession possession : shc.handshakePossessions) {
- if (possession instanceof ECDHEPossession) {
- ecdhePossession = (ECDHEPossession)possession;
+ if (possession instanceof NamedGroupPossession) {
+ NamedGroupPossession poss =
+ (NamedGroupPossession)possession;
+ namedGroup = poss.getNamedGroup();
+ sslPossession = poss;
break;
}
}
- if (ecdhePossession == null) {
+
+ if (sslPossession == null) {
// unlikely
throw shc.conContext.fatal(Alert.INTERNAL_ERROR,
"No expected ECDHE possessions for client key exchange");
}
- ECParameterSpec params = ecdhePossession.publicKey.getParams();
- NamedGroup namedGroup = NamedGroup.valueOf(params);
if (namedGroup == null) {
- // unlikely, have been checked during cipher suite negotiation.
+ // unlikely, have been checked during cipher suite negotiation
throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
"Unsupported EC server cert for ECDHE client key exchange");
}
@@ -480,7 +489,7 @@
"Not supported key exchange type");
}
- // parse the handshake message
+ // parse the EC/XEC handshake message
ECDHClientKeyExchangeMessage cke =
new ECDHClientKeyExchangeMessage(shc, message);
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
@@ -490,27 +499,17 @@
// create the credentials
try {
- ECPoint point =
- ECUtil.decodePoint(cke.encodedPoint, params.getCurve());
- ECPublicKeySpec spec = new ECPublicKeySpec(point, params);
-
- KeyFactory kf = KeyFactory.getInstance("EC");
- ECPublicKey peerPublicKey =
- (ECPublicKey)kf.generatePublic(spec);
+ NamedGroup ng = namedGroup; // "effectively final" the lambda
+ // AlgorithmConstraints are checked internally.
+ SSLCredentials sslCredentials = namedGroup.decodeCredentials(
+ cke.encodedPoint, shc.algorithmConstraints,
+ s -> shc.conContext.fatal(Alert.INSUFFICIENT_SECURITY,
+ "ClientKeyExchange " + ng + ": " + s));
- // check constraints of peer ECPublicKey
- if (!shc.algorithmConstraints.permits(
- EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
- peerPublicKey)) {
- throw new SSLHandshakeException(
- "ECPublicKey does not comply to algorithm constraints");
- }
-
- shc.handshakeCredentials.add(new ECDHECredentials(
- peerPublicKey, namedGroup));
- } catch (GeneralSecurityException | java.io.IOException e) {
- throw (SSLHandshakeException)(new SSLHandshakeException(
- "Could not generate ECPublicKey").initCause(e));
+ shc.handshakeCredentials.add(sslCredentials);
+ } catch (GeneralSecurityException e) {
+ throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
+ "Cannot decode named group: " + namedGroup);
}
// update the states
--- a/src/java.base/share/classes/sun/security/ssl/ECDHKeyExchange.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/ECDHKeyExchange.java Thu Jun 13 11:31:36 2019 +0530
@@ -36,7 +36,6 @@
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.interfaces.ECPublicKey;
-import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
@@ -44,25 +43,30 @@
import java.util.EnumSet;
import javax.crypto.KeyAgreement;
import javax.crypto.SecretKey;
-import javax.crypto.spec.SecretKeySpec;
import javax.net.ssl.SSLHandshakeException;
-import sun.security.ssl.CipherSuite.HashAlg;
-import sun.security.ssl.SupportedGroupsExtension.NamedGroup;
-import sun.security.ssl.SupportedGroupsExtension.NamedGroupType;
+import sun.security.ssl.NamedGroup.NamedGroupType;
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
import sun.security.ssl.X509Authentication.X509Credentials;
import sun.security.ssl.X509Authentication.X509Possession;
+import sun.security.ssl.XDHKeyExchange.XDHECredentials;
+import sun.security.ssl.XDHKeyExchange.XDHEPossession;
import sun.security.util.ECUtil;
final class ECDHKeyExchange {
static final SSLPossessionGenerator poGenerator =
new ECDHEPossessionGenerator();
- static final SSLKeyAgreementGenerator ecdheKAGenerator =
- new ECDHEKAGenerator();
static final SSLKeyAgreementGenerator ecdhKAGenerator =
new ECDHKAGenerator();
- static final class ECDHECredentials implements SSLCredentials {
+ // TLSv1.3
+ static final SSLKeyAgreementGenerator ecdheKAGenerator =
+ new ECDHEKAGenerator();
+
+ // TLSv1-1.2, the KA gets more difficult with EC/XEC keys
+ static final SSLKeyAgreementGenerator ecdheXdhKAGenerator =
+ new ECDHEXDHKAGenerator();
+
+ static final class ECDHECredentials implements NamedGroupCredentials {
final ECPublicKey popPublicKey;
final NamedGroup namedGroup;
@@ -71,6 +75,16 @@
this.namedGroup = namedGroup;
}
+ @Override
+ public PublicKey getPublicKey() {
+ return popPublicKey;
+ }
+
+ @Override
+ public NamedGroup getNamedGroup() {
+ return namedGroup;
+ }
+
static ECDHECredentials valueOf(NamedGroup namedGroup,
byte[] encodedPoint) throws IOException, GeneralSecurityException {
@@ -98,7 +112,7 @@
}
}
- static final class ECDHEPossession implements SSLPossession {
+ static final class ECDHEPossession implements NamedGroupPossession {
final PrivateKey privateKey;
final ECPublicKey publicKey;
final NamedGroup namedGroup;
@@ -199,6 +213,21 @@
"Could not generate ECPublicKey").initCause(e);
}
}
+
+ @Override
+ public PublicKey getPublicKey() {
+ return publicKey;
+ }
+
+ @Override
+ public NamedGroup getNamedGroup() {
+ return namedGroup;
+ }
+
+ @Override
+ public PrivateKey getPrivateKey() {
+ return privateKey;
+ }
}
private static final
@@ -210,24 +239,31 @@
@Override
public SSLPossession createPossession(HandshakeContext context) {
- NamedGroup preferableNamedGroup = null;
+
+ NamedGroup preferableNamedGroup;
+
+ // Find most preferred EC or XEC groups
if ((context.clientRequestedNamedGroups != null) &&
(!context.clientRequestedNamedGroups.isEmpty())) {
preferableNamedGroup = SupportedGroups.getPreferredGroup(
context.negotiatedProtocol,
context.algorithmConstraints,
- NamedGroupType.NAMED_GROUP_ECDHE,
+ new NamedGroupType[] {
+ NamedGroupType.NAMED_GROUP_ECDHE,
+ NamedGroupType.NAMED_GROUP_XDH },
context.clientRequestedNamedGroups);
} else {
preferableNamedGroup = SupportedGroups.getPreferredGroup(
context.negotiatedProtocol,
context.algorithmConstraints,
- NamedGroupType.NAMED_GROUP_ECDHE);
+ new NamedGroupType[] {
+ NamedGroupType.NAMED_GROUP_ECDHE,
+ NamedGroupType.NAMED_GROUP_XDH });
}
if (preferableNamedGroup != null) {
- return new ECDHEPossession(preferableNamedGroup,
- context.sslContext.getSecureRandom());
+ return preferableNamedGroup.createPossession(
+ context.sslContext.getSecureRandom());
}
// no match found, cannot use this cipher suite.
@@ -298,7 +334,7 @@
"No sufficient ECDHE key agreement parameters negotiated");
}
- return new ECDHEKAKeyDerivation(shc,
+ return new KAKeyDerivation("ECDH", shc,
x509Possession.popPrivateKey, ecdheCredentials.popPublicKey);
}
@@ -347,7 +383,7 @@
"No sufficient ECDH key agreement parameters negotiated");
}
- return new ECDHEKAKeyDerivation(chc,
+ return new KAKeyDerivation("ECDH", chc,
ecdhePossession.privateKey, x509Credentials.popPublicKey);
}
}
@@ -391,94 +427,73 @@
"No sufficient ECDHE key agreement parameters negotiated");
}
- return new ECDHEKAKeyDerivation(context,
+ return new KAKeyDerivation("ECDH", context,
ecdhePossession.privateKey, ecdheCredentials.popPublicKey);
}
}
+ /*
+ * A Generator for TLSv1-1.2 to create a ECDHE or a XDH KeyDerivation
+ * object depending on the negotiated group.
+ */
private static final
- class ECDHEKAKeyDerivation implements SSLKeyDerivation {
- private final HandshakeContext context;
- private final PrivateKey localPrivateKey;
- private final PublicKey peerPublicKey;
-
- ECDHEKAKeyDerivation(HandshakeContext context,
- PrivateKey localPrivateKey,
- PublicKey peerPublicKey) {
- this.context = context;
- this.localPrivateKey = localPrivateKey;
- this.peerPublicKey = peerPublicKey;
+ class ECDHEXDHKAGenerator implements SSLKeyAgreementGenerator {
+ // Prevent instantiation of this class.
+ private ECDHEXDHKAGenerator() {
+ // blank
}
@Override
- public SecretKey deriveKey(String algorithm,
- AlgorithmParameterSpec params) throws IOException {
- if (!context.negotiatedProtocol.useTLS13PlusSpec()) {
- return t12DeriveKey(algorithm, params);
- } else {
- return t13DeriveKey(algorithm, params);
- }
- }
+ public SSLKeyDerivation createKeyDerivation(
+ HandshakeContext context) throws IOException {
+
+ NamedGroupPossession namedGroupPossession = null;
+ NamedGroupCredentials namedGroupCredentials = null;
+ NamedGroup namedGroup = null;
- private SecretKey t12DeriveKey(String algorithm,
- AlgorithmParameterSpec params) throws IOException {
- try {
- KeyAgreement ka = KeyAgreement.getInstance("ECDH");
- ka.init(localPrivateKey);
- ka.doPhase(peerPublicKey, true);
- SecretKey preMasterSecret =
- ka.generateSecret("TlsPremasterSecret");
-
- SSLMasterKeyDerivation mskd =
- SSLMasterKeyDerivation.valueOf(
- context.negotiatedProtocol);
- if (mskd == null) {
- // unlikely
- throw new SSLHandshakeException(
- "No expected master key derivation for protocol: " +
- context.negotiatedProtocol.name);
+ // Find a possession/credential combo using the same named group
+ search:
+ for (SSLPossession poss : context.handshakePossessions) {
+ for (SSLCredentials cred : context.handshakeCredentials) {
+ if (((poss instanceof ECDHEPossession) &&
+ (cred instanceof ECDHECredentials)) ||
+ (((poss instanceof XDHEPossession) &&
+ (cred instanceof XDHECredentials)))) {
+ NamedGroupPossession p = (NamedGroupPossession)poss;
+ NamedGroupCredentials c = (NamedGroupCredentials)cred;
+ if (p.getNamedGroup() != c.getNamedGroup()) {
+ continue;
+ } else {
+ namedGroup = p.getNamedGroup();
+ }
+ namedGroupPossession = p;
+ namedGroupCredentials = c;
+ break search;
+ }
}
- SSLKeyDerivation kd = mskd.createKeyDerivation(
- context, preMasterSecret);
- return kd.deriveKey("MasterSecret", params);
- } catch (GeneralSecurityException gse) {
- throw (SSLHandshakeException) new SSLHandshakeException(
- "Could not generate secret").initCause(gse);
}
- }
- private SecretKey t13DeriveKey(String algorithm,
- AlgorithmParameterSpec params) throws IOException {
- try {
- KeyAgreement ka = KeyAgreement.getInstance("ECDH");
- ka.init(localPrivateKey);
- ka.doPhase(peerPublicKey, true);
- SecretKey sharedSecret =
- ka.generateSecret("TlsPremasterSecret");
+ if (namedGroupPossession == null || namedGroupCredentials == null) {
+ throw context.conContext.fatal(Alert.HANDSHAKE_FAILURE,
+ "No sufficient ECDHE/XDH key agreement " +
+ "parameters negotiated");
+ }
- HashAlg hashAlg = context.negotiatedCipherSuite.hashAlg;
- SSLKeyDerivation kd = context.handshakeKeyDerivation;
- HKDF hkdf = new HKDF(hashAlg.name);
- if (kd == null) { // No PSK is in use.
- // If PSK is not in use Early Secret will still be
- // HKDF-Extract(0, 0).
- byte[] zeros = new byte[hashAlg.hashLength];
- SecretKeySpec ikm =
- new SecretKeySpec(zeros, "TlsPreSharedSecret");
- SecretKey earlySecret =
- hkdf.extract(zeros, ikm, "TlsEarlySecret");
- kd = new SSLSecretDerivation(context, earlySecret);
- }
+ String alg;
+ switch (namedGroup.type) {
+ case NAMED_GROUP_ECDHE:
+ alg = "ECDH";
+ break;
+ case NAMED_GROUP_XDH:
+ alg = "XDH";
+ break;
+ default:
+ throw new RuntimeException("Unexpected named group type");
+ }
- // derive salt secret
- SecretKey saltSecret = kd.deriveKey("TlsSaltSecret", null);
-
- // derive handshake secret
- return hkdf.extract(saltSecret, sharedSecret, algorithm);
- } catch (GeneralSecurityException gse) {
- throw (SSLHandshakeException) new SSLHandshakeException(
- "Could not generate secret").initCause(gse);
- }
+ return new KAKeyDerivation(alg, context,
+ namedGroupPossession.getPrivateKey(),
+ namedGroupCredentials.getPublicKey());
}
}
}
--- a/src/java.base/share/classes/sun/security/ssl/ECDHServerKeyExchange.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/ECDHServerKeyExchange.java Thu Jun 13 11:31:36 2019 +0530
@@ -27,32 +27,21 @@
import java.io.IOException;
import java.nio.ByteBuffer;
-import java.security.CryptoPrimitive;
+import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
-import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
-import java.security.interfaces.ECPublicKey;
-import java.security.spec.ECParameterSpec;
-import java.security.spec.ECPoint;
-import java.security.spec.ECPublicKeySpec;
-import java.security.spec.InvalidKeySpecException;
import java.text.MessageFormat;
-import java.util.EnumSet;
import java.util.Locale;
-import sun.security.ssl.ECDHKeyExchange.ECDHECredentials;
-import sun.security.ssl.ECDHKeyExchange.ECDHEPossession;
import sun.security.ssl.SSLHandshake.HandshakeMessage;
-import sun.security.ssl.SupportedGroupsExtension.NamedGroup;
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
import sun.security.ssl.X509Authentication.X509Credentials;
import sun.security.ssl.X509Authentication.X509Possession;
-import sun.security.util.ECUtil;
import sun.security.util.HexDumpEncoder;
/**
@@ -80,14 +69,14 @@
// signature bytes, or null if anonymous
private final byte[] paramsSignature;
- // public key object encapsulated in this message
- private final ECPublicKey publicKey;
-
private final boolean useExplicitSigAlgorithm;
// the signature algorithm used by this ServerKeyExchange message
private final SignatureScheme signatureScheme;
+ // the parsed credential object
+ private SSLCredentials sslCredentials;
+
ECDHServerKeyExchangeMessage(
HandshakeContext handshakeContext) throws IOException {
super(handshakeContext);
@@ -96,38 +85,38 @@
ServerHandshakeContext shc =
(ServerHandshakeContext)handshakeContext;
- ECDHEPossession ecdhePossession = null;
+ // Find the Possessions needed
+ NamedGroupPossession namedGroupPossession = null;
X509Possession x509Possession = null;
for (SSLPossession possession : shc.handshakePossessions) {
- if (possession instanceof ECDHEPossession) {
- ecdhePossession = (ECDHEPossession)possession;
+ if (possession instanceof NamedGroupPossession) {
+ namedGroupPossession = (NamedGroupPossession)possession;
if (x509Possession != null) {
break;
}
} else if (possession instanceof X509Possession) {
x509Possession = (X509Possession)possession;
- if (ecdhePossession != null) {
+ if (namedGroupPossession != null) {
break;
}
}
}
- if (ecdhePossession == null) {
+ if (namedGroupPossession == null) {
// unlikely
throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
"No ECDHE credentials negotiated for server key exchange");
}
- publicKey = ecdhePossession.publicKey;
- ECParameterSpec params = publicKey.getParams();
- ECPoint point = publicKey.getW();
- publicPoint = ECUtil.encodePoint(point, params.getCurve());
+ // Find the NamedGroup used for the ephemeral keys.
+ namedGroup = namedGroupPossession.getNamedGroup();
+ publicPoint = namedGroup.encodePossessionPublicKey(
+ namedGroupPossession);
- this.namedGroup = NamedGroup.valueOf(params);
if ((namedGroup == null) || (namedGroup.oid == null) ) {
// unlikely
throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
- "Unnamed EC parameter spec: " + params);
+ "Missing Named Group");
}
if (x509Possession == null) {
@@ -216,39 +205,23 @@
"Unsupported named group: " + namedGroup);
}
- if (namedGroup.oid == null) {
- throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
- "Unknown named EC curve: " + namedGroup);
- }
-
- ECParameterSpec parameters =
- ECUtil.getECParameterSpec(null, namedGroup.oid);
- if (parameters == null) {
- throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
- "No supported EC parameter: " + namedGroup);
- }
-
publicPoint = Record.getBytes8(m);
if (publicPoint.length == 0) {
throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
- "Insufficient ECPoint data: " + namedGroup);
+ "Insufficient Point data: " + namedGroup);
}
- ECPublicKey ecPublicKey = null;
try {
- ECPoint point =
- ECUtil.decodePoint(publicPoint, parameters.getCurve());
- KeyFactory factory = KeyFactory.getInstance("EC");
- ecPublicKey = (ECPublicKey)factory.generatePublic(
- new ECPublicKeySpec(point, parameters));
- } catch (NoSuchAlgorithmException |
- InvalidKeySpecException | IOException ex) {
- throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
- "Invalid ECPoint: " + namedGroup, ex);
+ sslCredentials = namedGroup.decodeCredentials(
+ publicPoint, handshakeContext.algorithmConstraints,
+ s -> chc.conContext.fatal(Alert.INSUFFICIENT_SECURITY,
+ "ServerKeyExchange " + namedGroup + ": " + (s)));
+ } catch (GeneralSecurityException ex) {
+ throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
+ "Cannot decode named group: " +
+ NamedGroup.nameOf(namedGroupId));
}
- publicKey = ecPublicKey;
-
X509Credentials x509Credentials = null;
for (SSLCredentials cd : chc.handshakeCredentials) {
if (cd instanceof X509Credentials) {
@@ -529,6 +502,7 @@
// The consuming happens in client side only.
ClientHandshakeContext chc = (ClientHandshakeContext)context;
+ // AlgorithmConstraints are checked during decoding
ECDHServerKeyExchangeMessage skem =
new ECDHServerKeyExchangeMessage(chc, message);
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
@@ -537,22 +511,9 @@
}
//
- // validate
- //
- // check constraints of EC PublicKey
- if (!chc.algorithmConstraints.permits(
- EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
- skem.publicKey)) {
- throw chc.conContext.fatal(Alert.INSUFFICIENT_SECURITY,
- "ECDH ServerKeyExchange does not comply " +
- "to algorithm constraints");
- }
-
- //
// update
//
- chc.handshakeCredentials.add(
- new ECDHECredentials(skem.publicKey, skem.namedGroup));
+ chc.handshakeCredentials.add(skem.sslCredentials);
//
// produce
--- a/src/java.base/share/classes/sun/security/ssl/ECPointFormatsExtension.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/ECPointFormatsExtension.java Thu Jun 13 11:31:36 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, 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
@@ -34,7 +34,7 @@
import sun.security.ssl.SSLExtension.ExtensionConsumer;
import sun.security.ssl.SSLExtension.SSLExtensionSpec;
import sun.security.ssl.SSLHandshake.HandshakeMessage;
-import sun.security.ssl.SupportedGroupsExtension.NamedGroupType;
+import sun.security.ssl.NamedGroup.NamedGroupType;
/**
* Pack of the "ec_point_formats" extensions [RFC 4492].
--- a/src/java.base/share/classes/sun/security/ssl/HandshakeContext.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/HandshakeContext.java Thu Jun 13 11:31:36 2019 +0530
@@ -46,9 +46,8 @@
import javax.net.ssl.SNIServerName;
import javax.net.ssl.SSLHandshakeException;
import javax.security.auth.x500.X500Principal;
-import sun.security.ssl.SupportedGroupsExtension.NamedGroup;
-import sun.security.ssl.SupportedGroupsExtension.NamedGroupType;
-import static sun.security.ssl.SupportedGroupsExtension.NamedGroupType.*;
+import sun.security.ssl.NamedGroup.NamedGroupType;
+import static sun.security.ssl.NamedGroup.NamedGroupType.*;
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
abstract class HandshakeContext implements ConnectionContext {
@@ -519,31 +518,38 @@
return true;
}
- boolean available;
- NamedGroupType groupType = suite.keyExchange.groupType;
- if (groupType != NAMED_GROUP_NONE) {
- Boolean checkedStatus = cachedStatus.get(groupType);
- if (checkedStatus == null) {
- available = SupportedGroups.isActivatable(
- algorithmConstraints, groupType);
- cachedStatus.put(groupType, available);
+ // Is at least one of the group types available?
+ boolean groupAvailable, retval = false;
+ NamedGroupType[] groupTypes = suite.keyExchange.groupTypes;
+ for (NamedGroupType groupType : groupTypes) {
+ if (groupType != NAMED_GROUP_NONE) {
+ Boolean checkedStatus = cachedStatus.get(groupType);
+ if (checkedStatus == null) {
+ groupAvailable = SupportedGroups.isActivatable(
+ algorithmConstraints, groupType);
+ cachedStatus.put(groupType, groupAvailable);
- if (!available &&
- SSLLogger.isOn && SSLLogger.isOn("verbose")) {
- SSLLogger.fine("No activated named group");
+ if (!groupAvailable &&
+ SSLLogger.isOn && SSLLogger.isOn("verbose")) {
+ SSLLogger.fine(
+ "No activated named group in " + groupType);
+ }
+ } else {
+ groupAvailable = checkedStatus;
}
+
+ retval |= groupAvailable;
} else {
- available = checkedStatus;
+ retval |= true;
}
+ }
- if (!available && SSLLogger.isOn && SSLLogger.isOn("verbose")) {
- SSLLogger.fine(
- "No active named group, ignore " + suite);
- }
- return available;
- } else {
- return true;
+ if (!retval && SSLLogger.isOn && SSLLogger.isOn("verbose")) {
+ SSLLogger.fine("No active named group(s), ignore " + suite);
}
+
+ return retval;
+
} else if (SSLLogger.isOn && SSLLogger.isOn("verbose")) {
SSLLogger.fine("Ignore disabled cipher suite: " + suite);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/KAKeyDerivation.java Thu Jun 13 11:31:36 2019 +0530
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2019, 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 sun.security.ssl;
+
+import javax.crypto.KeyAgreement;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+import javax.net.ssl.SSLHandshakeException;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * A common class for creating various KeyDerivation types.
+ */
+public class KAKeyDerivation implements SSLKeyDerivation {
+
+ private final String algorithmName;
+ private final HandshakeContext context;
+ private final PrivateKey localPrivateKey;
+ private final PublicKey peerPublicKey;
+
+ KAKeyDerivation(String algorithmName,
+ HandshakeContext context,
+ PrivateKey localPrivateKey,
+ PublicKey peerPublicKey) {
+ this.algorithmName = algorithmName;
+ this.context = context;
+ this.localPrivateKey = localPrivateKey;
+ this.peerPublicKey = peerPublicKey;
+ }
+
+ @Override
+ public SecretKey deriveKey(String algorithm,
+ AlgorithmParameterSpec params) throws IOException {
+ if (!context.negotiatedProtocol.useTLS13PlusSpec()) {
+ return t12DeriveKey(algorithm, params);
+ } else {
+ return t13DeriveKey(algorithm, params);
+ }
+ }
+
+ /**
+ * Handle the TLSv1-1.2 objects, which don't use the HKDF algorithms.
+ */
+ private SecretKey t12DeriveKey(String algorithm,
+ AlgorithmParameterSpec params) throws IOException {
+ try {
+ KeyAgreement ka = KeyAgreement.getInstance(algorithmName);
+ ka.init(localPrivateKey);
+ ka.doPhase(peerPublicKey, true);
+ SecretKey preMasterSecret
+ = ka.generateSecret("TlsPremasterSecret");
+ SSLMasterKeyDerivation mskd
+ = SSLMasterKeyDerivation.valueOf(
+ context.negotiatedProtocol);
+ if (mskd == null) {
+ // unlikely
+ throw new SSLHandshakeException(
+ "No expected master key derivation for protocol: "
+ + context.negotiatedProtocol.name);
+ }
+ SSLKeyDerivation kd = mskd.createKeyDerivation(
+ context, preMasterSecret);
+ return kd.deriveKey("MasterSecret", params);
+ } catch (GeneralSecurityException gse) {
+ throw (SSLHandshakeException) new SSLHandshakeException(
+ "Could not generate secret").initCause(gse);
+ }
+ }
+
+ /**
+ * Handle the TLSv1.3 objects, which use the HKDF algorithms.
+ */
+ private SecretKey t13DeriveKey(String algorithm,
+ AlgorithmParameterSpec params) throws IOException {
+ try {
+ KeyAgreement ka = KeyAgreement.getInstance(algorithmName);
+ ka.init(localPrivateKey);
+ ka.doPhase(peerPublicKey, true);
+ SecretKey sharedSecret
+ = ka.generateSecret("TlsPremasterSecret");
+
+ CipherSuite.HashAlg hashAlg = context.negotiatedCipherSuite.hashAlg;
+ SSLKeyDerivation kd = context.handshakeKeyDerivation;
+ HKDF hkdf = new HKDF(hashAlg.name);
+ if (kd == null) { // No PSK is in use.
+ // If PSK is not in use Early Secret will still be
+ // HKDF-Extract(0, 0).
+ byte[] zeros = new byte[hashAlg.hashLength];
+ SecretKeySpec ikm
+ = new SecretKeySpec(zeros, "TlsPreSharedSecret");
+ SecretKey earlySecret
+ = hkdf.extract(zeros, ikm, "TlsEarlySecret");
+ kd = new SSLSecretDerivation(context, earlySecret);
+ }
+
+ // derive salt secret
+ SecretKey saltSecret = kd.deriveKey("TlsSaltSecret", null);
+
+ // derive handshake secret
+ return hkdf.extract(saltSecret, sharedSecret, algorithm);
+ } catch (GeneralSecurityException gse) {
+ throw (SSLHandshakeException) new SSLHandshakeException(
+ "Could not generate secret").initCause(gse);
+ }
+ }
+}
--- a/src/java.base/share/classes/sun/security/ssl/KeyShareExtension.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/KeyShareExtension.java Thu Jun 13 11:31:36 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,27 +27,19 @@
import java.io.IOException;
import java.nio.ByteBuffer;
-import java.security.CryptoPrimitive;
import java.security.GeneralSecurityException;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.Collections;
-import java.util.EnumSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.net.ssl.SSLProtocolException;
-import sun.security.ssl.DHKeyExchange.DHECredentials;
-import sun.security.ssl.DHKeyExchange.DHEPossession;
-import sun.security.ssl.ECDHKeyExchange.ECDHECredentials;
-import sun.security.ssl.ECDHKeyExchange.ECDHEPossession;
import sun.security.ssl.KeyShareExtension.CHKeyShareSpec;
import sun.security.ssl.SSLExtension.ExtensionConsumer;
import sun.security.ssl.SSLExtension.SSLExtensionSpec;
import sun.security.ssl.SSLHandshake.HandshakeMessage;
-import sun.security.ssl.SupportedGroupsExtension.NamedGroup;
-import sun.security.ssl.SupportedGroupsExtension.NamedGroupType;
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
import sun.security.util.HexDumpEncoder;
@@ -264,8 +256,7 @@
for (SSLPossession pos : poses) {
// update the context
chc.handshakePossessions.add(pos);
- if (!(pos instanceof ECDHEPossession) &&
- !(pos instanceof DHEPossession)) {
+ if (!(pos instanceof NamedGroupPossession)) {
// May need more possesion types in the future.
continue;
}
@@ -353,46 +344,18 @@
continue;
}
- if (ng.type == NamedGroupType.NAMED_GROUP_ECDHE) {
- try {
- ECDHECredentials ecdhec =
- ECDHECredentials.valueOf(ng, entry.keyExchange);
- if (ecdhec != null) {
- if (!shc.algorithmConstraints.permits(
- EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
- ecdhec.popPublicKey)) {
- SSLLogger.warning(
- "ECDHE key share entry does not " +
- "comply to algorithm constraints");
- } else {
- credentials.add(ecdhec);
- }
- }
- } catch (IOException | GeneralSecurityException ex) {
- SSLLogger.warning(
- "Cannot decode named group: " +
- NamedGroup.nameOf(entry.namedGroupId));
+ try {
+ SSLCredentials kaCred =
+ ng.decodeCredentials(entry.keyExchange,
+ shc.algorithmConstraints,
+ s -> SSLLogger.warning(s));
+ if (kaCred != null) {
+ credentials.add(kaCred);
}
- } else if (ng.type == NamedGroupType.NAMED_GROUP_FFDHE) {
- try {
- DHECredentials dhec =
- DHECredentials.valueOf(ng, entry.keyExchange);
- if (dhec != null) {
- if (!shc.algorithmConstraints.permits(
- EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
- dhec.popPublicKey)) {
- SSLLogger.warning(
- "DHE key share entry does not " +
- "comply to algorithm constraints");
- } else {
- credentials.add(dhec);
- }
- }
- } catch (IOException | GeneralSecurityException ex) {
- SSLLogger.warning(
- "Cannot decode named group: " +
- NamedGroup.nameOf(entry.namedGroupId));
- }
+ } catch (GeneralSecurityException ex) {
+ SSLLogger.warning(
+ "Cannot decode named group: " +
+ NamedGroup.nameOf(entry.namedGroupId));
}
}
@@ -526,10 +489,9 @@
KeyShareEntry keyShare = null;
for (SSLCredentials cd : shc.handshakeCredentials) {
NamedGroup ng = null;
- if (cd instanceof ECDHECredentials) {
- ng = ((ECDHECredentials)cd).namedGroup;
- } else if (cd instanceof DHECredentials) {
- ng = ((DHECredentials)cd).namedGroup;
+ if (cd instanceof NamedGroupCredentials) {
+ NamedGroupCredentials creds = (NamedGroupCredentials)cd;
+ ng = creds.getNamedGroup();
}
if (ng == null) {
@@ -547,8 +509,7 @@
SSLPossession[] poses = ke.createPossessions(shc);
for (SSLPossession pos : poses) {
- if (!(pos instanceof ECDHEPossession) &&
- !(pos instanceof DHEPossession)) {
+ if (!(pos instanceof NamedGroupPossession)) {
// May need more possesion types in the future.
continue;
}
@@ -567,7 +528,7 @@
me.getKey(), me.getValue());
}
- // We have got one! Don't forgor to break.
+ // We have got one! Don't forget to break.
break;
}
}
@@ -643,49 +604,16 @@
}
SSLCredentials credentials = null;
- if (ng.type == NamedGroupType.NAMED_GROUP_ECDHE) {
- try {
- ECDHECredentials ecdhec =
- ECDHECredentials.valueOf(ng, keyShare.keyExchange);
- if (ecdhec != null) {
- if (!chc.algorithmConstraints.permits(
- EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
- ecdhec.popPublicKey)) {
- throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
- "ECDHE key share entry does not " +
- "comply to algorithm constraints");
- } else {
- credentials = ecdhec;
- }
- }
- } catch (IOException | GeneralSecurityException ex) {
- throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
- "Cannot decode named group: " +
- NamedGroup.nameOf(keyShare.namedGroupId));
+ try {
+ SSLCredentials kaCred = ng.decodeCredentials(
+ keyShare.keyExchange, chc.algorithmConstraints,
+ s -> chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, s));
+ if (kaCred != null) {
+ credentials = kaCred;
}
- } else if (ng.type == NamedGroupType.NAMED_GROUP_FFDHE) {
- try {
- DHECredentials dhec =
- DHECredentials.valueOf(ng, keyShare.keyExchange);
- if (dhec != null) {
- if (!chc.algorithmConstraints.permits(
- EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
- dhec.popPublicKey)) {
- throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
- "DHE key share entry does not " +
- "comply to algorithm constraints");
- } else {
- credentials = dhec;
- }
- }
- } catch (IOException | GeneralSecurityException ex) {
- throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
- "Cannot decode named group: " +
- NamedGroup.nameOf(keyShare.namedGroupId));
- }
- } else {
+ } catch (GeneralSecurityException ex) {
throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
- "Unsupported named group: " +
+ "Cannot decode named group: " +
NamedGroup.nameOf(keyShare.namedGroupId));
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/NamedGroup.java Thu Jun 13 11:31:36 2019 +0530
@@ -0,0 +1,781 @@
+/*
+ * Copyright (c) 2019, 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 sun.security.ssl;
+
+import javax.crypto.spec.DHParameterSpec;
+import javax.net.ssl.SSLException;
+import java.io.IOException;
+import java.security.*;
+import java.security.spec.*;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+import javax.crypto.*;
+import sun.security.ssl.DHKeyExchange.DHEPossession;
+import sun.security.ssl.ECDHKeyExchange.ECDHEPossession;
+
+import sun.security.util.ECUtil;
+
+/**
+ * An enum containing all known named groups for use in TLS.
+ *
+ * The enum also contains the required properties of each group and the
+ * required functions (e.g. encoding/decoding).
+ */
+enum NamedGroup {
+ // Elliptic Curves (RFC 4492)
+ //
+ // See sun.security.util.CurveDB for the OIDs
+ // NIST K-163
+
+ SECT163_K1(0x0001, "sect163k1", "1.3.132.0.1",
+ NamedGroupType.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12),
+ SECT163_R1(0x0002, "sect163r1", "1.3.132.0.2",
+ NamedGroupType.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12),
+
+ // NIST B-163
+ SECT163_R2(0x0003, "sect163r2", "1.3.132.0.15",
+ NamedGroupType.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12),
+ SECT193_R1(0x0004, "sect193r1", "1.3.132.0.24",
+ NamedGroupType.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12),
+ SECT193_R2(0x0005, "sect193r2", "1.3.132.0.25",
+ NamedGroupType.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12),
+
+ // NIST K-233
+ SECT233_K1(0x0006, "sect233k1", "1.3.132.0.26",
+ NamedGroupType.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12),
+
+ // NIST B-233
+ SECT233_R1(0x0007, "sect233r1", "1.3.132.0.27",
+ NamedGroupType.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12),
+ SECT239_K1(0x0008, "sect239k1", "1.3.132.0.3",
+ NamedGroupType.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12),
+
+ // NIST K-283
+ SECT283_K1(0x0009, "sect283k1", "1.3.132.0.16",
+ NamedGroupType.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12),
+
+ // NIST B-283
+ SECT283_R1(0x000A, "sect283r1", "1.3.132.0.17",
+ NamedGroupType.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12),
+
+ // NIST K-409
+ SECT409_K1(0x000B, "sect409k1", "1.3.132.0.36",
+ NamedGroupType.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12),
+
+ // NIST B-409
+ SECT409_R1(0x000C, "sect409r1", "1.3.132.0.37",
+ NamedGroupType.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12),
+
+ // NIST K-571
+ SECT571_K1(0x000D, "sect571k1", "1.3.132.0.38",
+ NamedGroupType.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12),
+
+ // NIST B-571
+ SECT571_R1(0x000E, "sect571r1", "1.3.132.0.39",
+ NamedGroupType.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12),
+ SECP160_K1(0x000F, "secp160k1", "1.3.132.0.9",
+ NamedGroupType.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12),
+ SECP160_R1(0x0010, "secp160r1", "1.3.132.0.8",
+ NamedGroupType.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12),
+ SECP160_R2(0x0011, "secp160r2", "1.3.132.0.30",
+ NamedGroupType.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12),
+ SECP192_K1(0x0012, "secp192k1", "1.3.132.0.31",
+ NamedGroupType.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12),
+
+ // NIST P-192
+ SECP192_R1(0x0013, "secp192r1", "1.2.840.10045.3.1.1",
+ NamedGroupType.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12),
+ SECP224_K1(0x0014, "secp224k1", "1.3.132.0.32",
+ NamedGroupType.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12),
+
+ // NIST P-224
+ SECP224_R1(0x0015, "secp224r1", "1.3.132.0.33",
+ NamedGroupType.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12),
+ SECP256_K1(0x0016, "secp256k1", "1.3.132.0.10",
+ NamedGroupType.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12),
+
+ // NIST P-256
+ SECP256_R1(0x0017, "secp256r1", "1.2.840.10045.3.1.7",
+ NamedGroupType.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_13),
+
+ // NIST P-384
+ SECP384_R1(0x0018, "secp384r1", "1.3.132.0.34",
+ NamedGroupType.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_13),
+
+ // NIST P-521
+ SECP521_R1(0x0019, "secp521r1", "1.3.132.0.35",
+ NamedGroupType.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_13),
+
+ // x25519 and x448 (RFC 8422/8446)
+ X25519(0x001D, "x25519", "1.3.101.110",
+ NamedGroupType.NAMED_GROUP_XDH,
+ ProtocolVersion.PROTOCOLS_TO_13),
+ X448(0x001E, "x448", "1.3.101.111",
+ NamedGroupType.NAMED_GROUP_XDH,
+ ProtocolVersion.PROTOCOLS_TO_13),
+
+ // Finite Field Diffie-Hellman Ephemeral Parameters (RFC 7919)
+ FFDHE_2048(0x0100, "ffdhe2048", null,
+ NamedGroupType.NAMED_GROUP_FFDHE,
+ ProtocolVersion.PROTOCOLS_TO_13),
+ FFDHE_3072(0x0101, "ffdhe3072", null,
+ NamedGroupType.NAMED_GROUP_FFDHE,
+ ProtocolVersion.PROTOCOLS_TO_13),
+ FFDHE_4096(0x0102, "ffdhe4096", null,
+ NamedGroupType.NAMED_GROUP_FFDHE,
+ ProtocolVersion.PROTOCOLS_TO_13),
+ FFDHE_6144(0x0103, "ffdhe6144", null,
+ NamedGroupType.NAMED_GROUP_FFDHE,
+ ProtocolVersion.PROTOCOLS_TO_13),
+ FFDHE_8192(0x0104, "ffdhe8192", null,
+ NamedGroupType.NAMED_GROUP_FFDHE,
+ ProtocolVersion.PROTOCOLS_TO_13),
+
+ // Elliptic Curves (RFC 4492)
+ //
+ // arbitrary prime and characteristic-2 curves
+ ARBITRARY_PRIME(0xFF01, "arbitrary_explicit_prime_curves", null,
+ NamedGroupType.NAMED_GROUP_ARBITRARY,
+ ProtocolVersion.PROTOCOLS_TO_12),
+ ARBITRARY_CHAR2(0xFF02, "arbitrary_explicit_char2_curves", null,
+ NamedGroupType.NAMED_GROUP_ARBITRARY,
+ ProtocolVersion.PROTOCOLS_TO_12);
+
+ final int id; // hash + signature
+ final NamedGroupType type; // group type
+ final String name; // literal name
+ final String oid; // object identifier of the named group
+ final String algorithm; // signature algorithm
+ final ProtocolVersion[] supportedProtocols;
+ private final NamedGroupFunctions functions; // may be null
+
+ // Constructor used for all NamedGroup types
+ private NamedGroup(int id, String name, String oid,
+ NamedGroupType namedGroupType,
+ ProtocolVersion[] supportedProtocols) {
+ this.id = id;
+ this.name = name;
+ this.oid = oid;
+ this.type = namedGroupType;
+ this.supportedProtocols = supportedProtocols;
+
+ if (this.type == NamedGroupType.NAMED_GROUP_ECDHE) {
+ this.functions = ECDHFunctions.getInstance();
+ this.algorithm = "EC";
+ } else if (this.type == NamedGroupType.NAMED_GROUP_FFDHE) {
+ this.functions = FFDHFunctions.getInstance();
+ this.algorithm = "DiffieHellman";
+ } else if (this.type == NamedGroupType.NAMED_GROUP_XDH) {
+ this.functions = XDHFunctions.getInstance();
+ this.algorithm = "XDH";
+ } else if (this.type == NamedGroupType.NAMED_GROUP_ARBITRARY) {
+ this.functions = null;
+ this.algorithm = "EC";
+ } else {
+ throw new RuntimeException("Unexpected Named Group Type");
+ }
+ }
+
+ private Optional<NamedGroupFunctions> getFunctions() {
+ return Optional.ofNullable(functions);
+ }
+
+ // The next set of methods search & retrieve NamedGroups.
+
+ static NamedGroup valueOf(int id) {
+ for (NamedGroup group : NamedGroup.values()) {
+ if (group.id == id) {
+ return group;
+ }
+ }
+
+ return null;
+ }
+
+ static NamedGroup valueOf(ECParameterSpec params) {
+ String oid = ECUtil.getCurveName(null, params);
+ if ((oid != null) && (!oid.isEmpty())) {
+ for (NamedGroup group : NamedGroup.values()) {
+ if ((group.type == NamedGroupType.NAMED_GROUP_ECDHE)
+ && oid.equals(group.oid)) {
+ return group;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ static NamedGroup valueOf(DHParameterSpec params) {
+ for (NamedGroup ng : NamedGroup.values()) {
+ if (ng.type != NamedGroupType.NAMED_GROUP_FFDHE) {
+ continue;
+ }
+
+ DHParameterSpec ngParams = null;
+ // functions is non-null for FFDHE type
+ AlgorithmParameters aps = ng.functions.getParameters(ng);
+ try {
+ ngParams = aps.getParameterSpec(DHParameterSpec.class);
+ } catch (InvalidParameterSpecException ipse) {
+ // should be unlikely
+ }
+
+ if (ngParams == null) {
+ continue;
+ }
+
+ if (ngParams.getP().equals(params.getP())
+ && ngParams.getG().equals(params.getG())) {
+ return ng;
+ }
+ }
+
+ return null;
+ }
+
+ static NamedGroup nameOf(String name) {
+ for (NamedGroup group : NamedGroup.values()) {
+ if (group.name.equals(name)) {
+ return group;
+ }
+ }
+
+ return null;
+ }
+
+ static String nameOf(int id) {
+ for (NamedGroup group : NamedGroup.values()) {
+ if (group.id == id) {
+ return group.name;
+ }
+ }
+
+ return "UNDEFINED-NAMED-GROUP(" + id + ")";
+ }
+
+ // Are the NamedGroups available for the protocol desired?
+
+ boolean isAvailable(List<ProtocolVersion> protocolVersions) {
+ for (ProtocolVersion pv : supportedProtocols) {
+ if (protocolVersions.contains(pv)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ boolean isAvailable(ProtocolVersion protocolVersion) {
+ for (ProtocolVersion pv : supportedProtocols) {
+ if (protocolVersion == pv) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Are the NamedGroups available for the ciphersuites desired?
+
+ boolean isSupported(List<CipherSuite> cipherSuites) {
+ for (CipherSuite cs : cipherSuites) {
+ boolean isMatch = isAvailable(cs.supportedProtocols);
+ if (isMatch && ((cs.keyExchange == null)
+ || (NamedGroupType.arrayContains(
+ cs.keyExchange.groupTypes, type)))) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // lazy loading of parameters
+ AlgorithmParameters getParameters() {
+ Optional<NamedGroupFunctions> ngf = getFunctions();
+ if (ngf.isEmpty()) {
+ return null;
+ }
+ return ngf.get().getParameters(this);
+ }
+
+ // The next set of methods use the NamedGroupFunctions table
+ // to do various operations in a consistent way.
+
+ AlgorithmParameterSpec getParameterSpec() {
+ Optional<NamedGroupFunctions> ngf = getFunctions();
+ if (ngf.isEmpty()) {
+ return null;
+ }
+ return ngf.get().getParameterSpec(this);
+ }
+
+ byte[] encodePossessionPublicKey(
+ NamedGroupPossession namedGroupPossession) {
+
+ Optional<NamedGroupFunctions> ngf = getFunctions();
+ if (ngf.isEmpty()) {
+ return null;
+ }
+ return ngf.get().encodePossessionPublicKey(namedGroupPossession);
+ }
+
+ SSLCredentials decodeCredentials(byte[] encoded,
+ AlgorithmConstraints constraints,
+ ExceptionSupplier onConstraintFail)
+ throws IOException, GeneralSecurityException {
+
+ Optional<NamedGroupFunctions> ngf = getFunctions();
+ if (ngf.isEmpty()) {
+ return null;
+ }
+ return ngf.get().decodeCredentials(this, encoded, constraints,
+ onConstraintFail);
+ }
+
+ SSLPossession createPossession(SecureRandom random) {
+
+ Optional<NamedGroupFunctions> ngf = getFunctions();
+ if (ngf.isEmpty()) {
+ return null;
+ }
+ return ngf.get().createPossession(this, random);
+ }
+
+ SSLKeyDerivation createKeyDerivation(HandshakeContext hc)
+ throws IOException {
+
+ Optional<NamedGroupFunctions> ngf = getFunctions();
+ if (ngf.isEmpty()) {
+ return null;
+ }
+ return ngf.get().createKeyDerivation(hc);
+
+ }
+
+ boolean isAvailableGroup() {
+ Optional<NamedGroupFunctions> ngfOpt = getFunctions();
+ if (ngfOpt.isEmpty()) {
+ return false;
+ }
+ NamedGroupFunctions ngf = ngfOpt.get();
+ return ngf.isAvailable(this);
+ }
+
+ enum NamedGroupType {
+ NAMED_GROUP_ECDHE, // Elliptic Curve Groups (ECDHE)
+ NAMED_GROUP_FFDHE, // Finite Field Groups (DHE)
+ NAMED_GROUP_XDH, // Finite Field Groups (XDH)
+ NAMED_GROUP_ARBITRARY, // arbitrary prime and curves (ECDHE)
+ NAMED_GROUP_NONE; // Not predefined named group
+
+ boolean isSupported(List<CipherSuite> cipherSuites) {
+ for (CipherSuite cs : cipherSuites) {
+ if (cs.keyExchange == null ||
+ arrayContains(cs.keyExchange.groupTypes, this)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ static boolean arrayContains(NamedGroupType[] namedGroupTypes,
+ NamedGroupType namedGroupType) {
+ for (NamedGroupType ng : namedGroupTypes) {
+ if (ng == namedGroupType) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ interface ExceptionSupplier {
+ void apply(String s) throws SSLException;
+ }
+
+ /*
+ * A list of functions to do NamedGroup operations in a
+ * algorithm-independent and consistent way.
+ */
+ private static abstract class NamedGroupFunctions {
+
+ // cache to speed up the parameters construction
+ protected static final Map<NamedGroup, AlgorithmParameters>
+ namedGroupParams = new ConcurrentHashMap<>();
+
+ protected void checkConstraints(PublicKey publicKey,
+ AlgorithmConstraints constraints,
+ ExceptionSupplier onConstraintFail)
+ throws SSLException {
+
+ if (!constraints.permits(
+ EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
+ publicKey)) {
+
+ onConstraintFail.apply("key share entry does not "
+ + "comply with algorithm constraints");
+ }
+ }
+
+ public AlgorithmParameters getParameters(NamedGroup ng) {
+
+ AlgorithmParameters result = namedGroupParams.get(ng);
+ if (result == null) {
+ Optional<AlgorithmParameters> paramsOpt = getParametersImpl(ng);
+ if (paramsOpt.isPresent()) {
+ result = paramsOpt.get();
+ namedGroupParams.put(ng, result);
+ }
+ }
+
+ return result;
+ }
+
+ public abstract byte[] encodePossessionPublicKey(
+ NamedGroupPossession namedGroupPossession);
+
+ public abstract SSLCredentials decodeCredentials(
+ NamedGroup ng, byte[] encoded,
+ AlgorithmConstraints constraints,
+ ExceptionSupplier onConstraintFail)
+ throws IOException, GeneralSecurityException;
+
+ public abstract SSLPossession createPossession(NamedGroup ng,
+ SecureRandom random);
+
+ public abstract SSLKeyDerivation createKeyDerivation(
+ HandshakeContext hc) throws IOException;
+
+ protected abstract Optional<AlgorithmParameters> getParametersImpl(
+ NamedGroup ng);
+
+ public abstract AlgorithmParameterSpec getParameterSpec(NamedGroup ng);
+
+ public abstract boolean isAvailable(NamedGroup ng);
+ }
+
+ private static class FFDHFunctions extends NamedGroupFunctions {
+
+ // lazy initialization
+ private static class FunctionsHolder {
+ private static final FFDHFunctions instance = new FFDHFunctions();
+ }
+
+ private static FFDHFunctions getInstance() {
+ return FunctionsHolder.instance;
+ }
+
+ @Override
+ public byte[] encodePossessionPublicKey(
+ NamedGroupPossession namedGroupPossession) {
+ return ((DHEPossession)namedGroupPossession).encode();
+ }
+
+ @Override
+ public SSLCredentials decodeCredentials(NamedGroup ng, byte[] encoded,
+ AlgorithmConstraints constraints,
+ ExceptionSupplier onConstraintFail)
+ throws IOException, GeneralSecurityException {
+
+ DHKeyExchange.DHECredentials result
+ = DHKeyExchange.DHECredentials.valueOf(ng, encoded);
+
+ checkConstraints(result.getPublicKey(), constraints,
+ onConstraintFail);
+
+ return result;
+ }
+
+ @Override
+ public SSLPossession createPossession(
+ NamedGroup ng, SecureRandom random) {
+ return new DHKeyExchange.DHEPossession(ng, random);
+ }
+
+ @Override
+ public SSLKeyDerivation createKeyDerivation(HandshakeContext hc)
+ throws IOException {
+
+ return DHKeyExchange.kaGenerator.createKeyDerivation(hc);
+ }
+
+ @Override
+ public AlgorithmParameterSpec getParameterSpec(NamedGroup ng) {
+ return getDHParameterSpec(ng);
+ }
+
+ DHParameterSpec getDHParameterSpec(NamedGroup ng) {
+
+ AlgorithmParameters params = getParameters(ng);
+ try {
+ return params.getParameterSpec(DHParameterSpec.class);
+ } catch (InvalidParameterSpecException ipse) {
+ // should be unlikely
+ return getPredefinedDHParameterSpec(ng);
+ }
+ }
+
+ private static DHParameterSpec getFFDHEDHParameterSpec(
+ NamedGroup namedGroup) {
+
+ DHParameterSpec spec = null;
+ switch (namedGroup) {
+ case FFDHE_2048:
+ spec = PredefinedDHParameterSpecs.ffdheParams.get(2048);
+ break;
+ case FFDHE_3072:
+ spec = PredefinedDHParameterSpecs.ffdheParams.get(3072);
+ break;
+ case FFDHE_4096:
+ spec = PredefinedDHParameterSpecs.ffdheParams.get(4096);
+ break;
+ case FFDHE_6144:
+ spec = PredefinedDHParameterSpecs.ffdheParams.get(6144);
+ break;
+ case FFDHE_8192:
+ spec = PredefinedDHParameterSpecs.ffdheParams.get(8192);
+ }
+
+ return spec;
+ }
+
+ private static DHParameterSpec getPredefinedDHParameterSpec(
+ NamedGroup namedGroup) {
+
+ DHParameterSpec spec = null;
+ switch (namedGroup) {
+ case FFDHE_2048:
+ spec = PredefinedDHParameterSpecs.definedParams.get(2048);
+ break;
+ case FFDHE_3072:
+ spec = PredefinedDHParameterSpecs.definedParams.get(3072);
+ break;
+ case FFDHE_4096:
+ spec = PredefinedDHParameterSpecs.definedParams.get(4096);
+ break;
+ case FFDHE_6144:
+ spec = PredefinedDHParameterSpecs.definedParams.get(6144);
+ break;
+ case FFDHE_8192:
+ spec = PredefinedDHParameterSpecs.definedParams.get(8192);
+ }
+
+ return spec;
+ }
+
+ @Override
+ public boolean isAvailable(NamedGroup ng) {
+
+ AlgorithmParameters params = getParameters(ng);
+ return params != null;
+ }
+
+ @Override
+ protected Optional<AlgorithmParameters> getParametersImpl(
+ NamedGroup ng) {
+ try {
+ AlgorithmParameters params
+ = AlgorithmParameters.getInstance("DiffieHellman");
+ AlgorithmParameterSpec spec
+ = getFFDHEDHParameterSpec(ng);
+ params.init(spec);
+ return Optional.of(params);
+ } catch (InvalidParameterSpecException
+ | NoSuchAlgorithmException ex) {
+ return Optional.empty();
+ }
+ }
+
+ }
+
+ private static class ECDHFunctions extends NamedGroupFunctions {
+
+ // lazy initialization
+ private static class FunctionsHolder {
+ private static final ECDHFunctions instance = new ECDHFunctions();
+ }
+
+ private static ECDHFunctions getInstance() {
+ return FunctionsHolder.instance;
+ }
+
+ @Override
+ public byte[] encodePossessionPublicKey(
+ NamedGroupPossession namedGroupPossession) {
+ return ((ECDHEPossession)namedGroupPossession).encode();
+ }
+
+ @Override
+ public SSLCredentials decodeCredentials(NamedGroup ng, byte[] encoded,
+ AlgorithmConstraints constraints,
+ ExceptionSupplier onConstraintFail)
+ throws IOException, GeneralSecurityException {
+
+ ECDHKeyExchange.ECDHECredentials result
+ = ECDHKeyExchange.ECDHECredentials.valueOf(ng, encoded);
+
+ checkConstraints(result.getPublicKey(), constraints,
+ onConstraintFail);
+
+ return result;
+ }
+
+ @Override
+ public SSLPossession createPossession(
+ NamedGroup ng, SecureRandom random) {
+ return new ECDHKeyExchange.ECDHEPossession(ng, random);
+ }
+
+ @Override
+ public SSLKeyDerivation createKeyDerivation(HandshakeContext hc)
+ throws IOException {
+
+ return ECDHKeyExchange.ecdheKAGenerator.createKeyDerivation(hc);
+ }
+
+ @Override
+ public AlgorithmParameterSpec getParameterSpec(NamedGroup ng) {
+ return SupportedGroupsExtension.SupportedGroups
+ .getECGenParamSpec(ng);
+ }
+
+ @Override
+ public boolean isAvailable(NamedGroup ng) {
+
+ AlgorithmParameters params = getParameters(ng);
+ return params != null;
+ }
+
+ @Override
+ protected Optional<AlgorithmParameters> getParametersImpl(
+ NamedGroup ng) {
+ try {
+ AlgorithmParameters params
+ = AlgorithmParameters.getInstance("EC");
+ AlgorithmParameterSpec spec
+ = new ECGenParameterSpec(ng.oid);
+ params.init(spec);
+ return Optional.of(params);
+ } catch (InvalidParameterSpecException
+ | NoSuchAlgorithmException ex) {
+ return Optional.empty();
+ }
+ }
+ }
+
+ private static class XDHFunctions extends NamedGroupFunctions {
+
+ // lazy initialization
+ private static class FunctionsHolder {
+ private static final XDHFunctions instance = new XDHFunctions();
+ }
+
+ private static XDHFunctions getInstance() {
+ return FunctionsHolder.instance;
+ }
+
+ @Override
+ public byte[] encodePossessionPublicKey(NamedGroupPossession poss) {
+ return ((XDHKeyExchange.XDHEPossession)poss).encode();
+ }
+
+ @Override
+ public SSLCredentials decodeCredentials(NamedGroup ng, byte[] encoded,
+ AlgorithmConstraints constraints,
+ ExceptionSupplier onConstraintFail)
+ throws IOException, GeneralSecurityException {
+
+ XDHKeyExchange.XDHECredentials result
+ = XDHKeyExchange.XDHECredentials.valueOf(ng, encoded);
+
+ checkConstraints(result.getPublicKey(), constraints,
+ onConstraintFail);
+
+ return result;
+ }
+
+ @Override
+ public SSLPossession createPossession(
+ NamedGroup ng, SecureRandom random) {
+ return new XDHKeyExchange.XDHEPossession(ng, random);
+ }
+
+ @Override
+ public SSLKeyDerivation createKeyDerivation(HandshakeContext hc)
+ throws IOException {
+ return XDHKeyExchange.xdheKAGenerator.createKeyDerivation(hc);
+ }
+
+ @Override
+ public AlgorithmParameterSpec getParameterSpec(NamedGroup ng) {
+ return new NamedParameterSpec(ng.name);
+ }
+
+ @Override
+ public boolean isAvailable(NamedGroup ng) {
+
+ try {
+ KeyAgreement.getInstance(ng.algorithm);
+ return true;
+ } catch (NoSuchAlgorithmException ex) {
+ return false;
+ }
+ }
+
+ @Override
+ protected Optional<AlgorithmParameters> getParametersImpl(
+ NamedGroup ng) {
+ return Optional.empty();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/NamedGroupCredentials.java Thu Jun 13 11:31:36 2019 +0530
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2019, 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 sun.security.ssl;
+
+import java.security.PublicKey;
+
+interface NamedGroupCredentials extends SSLCredentials {
+
+ PublicKey getPublicKey();
+
+ NamedGroup getNamedGroup();
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/NamedGroupPossession.java Thu Jun 13 11:31:36 2019 +0530
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2019, 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 sun.security.ssl;
+
+import java.security.PrivateKey;
+import java.security.PublicKey;
+
+interface NamedGroupPossession extends SSLPossession {
+
+ NamedGroup getNamedGroup();
+
+ PublicKey getPublicKey();
+
+ PrivateKey getPrivateKey();
+}
--- a/src/java.base/share/classes/sun/security/ssl/SSLExtension.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/SSLExtension.java Thu Jun 13 11:31:36 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -484,6 +484,25 @@
final SSLHandshake handshakeType;
final String name;
final ProtocolVersion[] supportedProtocols;
+
+ /*
+ * networkProducer: produces outbound handshake data.
+ *
+ * onLoadConsumer: parses inbound data. It may not be appropriate
+ * to act until all of the message inputs have
+ * been parsed. (e.g. parsing keyShares and choosing
+ * a local value without having seen the SupportedGroups
+ * extension.)
+ *
+ * onLoadAbsence: if a missing message needs special handling
+ * during the load phase.
+ *
+ * onTradeConsumer: act on the parsed message once all inbound data has
+ * been traded and parsed.
+ *
+ * onTradeAbsence: if a missing message needs special handling
+ * during the trade phase.
+ */
final HandshakeProducer networkProducer;
final ExtensionConsumer onLoadConsumer;
final HandshakeAbsence onLoadAbsence;
--- a/src/java.base/share/classes/sun/security/ssl/SSLKeyExchange.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/SSLKeyExchange.java Thu Jun 13 11:31:36 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, 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
@@ -30,10 +30,6 @@
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
-import sun.security.ssl.DHKeyExchange.DHEPossession;
-import sun.security.ssl.ECDHKeyExchange.ECDHEPossession;
-import sun.security.ssl.SupportedGroupsExtension.NamedGroup;
-import sun.security.ssl.SupportedGroupsExtension.NamedGroupType;
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
import sun.security.ssl.X509Authentication.X509Possession;
@@ -243,8 +239,7 @@
static SSLKeyExchange valueOf(NamedGroup namedGroup) {
SSLKeyAgreement ka = T13KeyAgreement.valueOf(namedGroup);
if (ka != null) {
- return new SSLKeyExchange(
- null, T13KeyAgreement.valueOf(namedGroup));
+ return new SSLKeyExchange(null, ka);
}
return null;
@@ -337,7 +332,7 @@
ECDH ("ecdh", null,
ECDHKeyExchange.ecdhKAGenerator),
ECDHE ("ecdhe", ECDHKeyExchange.poGenerator,
- ECDHKeyExchange.ecdheKAGenerator);
+ ECDHKeyExchange.ecdheXdhKAGenerator);
final String name;
final SSLPossessionGenerator possessionGenerator;
@@ -570,27 +565,13 @@
@Override
public SSLPossession createPossession(HandshakeContext hc) {
- if (namedGroup.type == NamedGroupType.NAMED_GROUP_ECDHE) {
- return new ECDHEPossession(
- namedGroup, hc.sslContext.getSecureRandom());
- } else if (namedGroup.type == NamedGroupType.NAMED_GROUP_FFDHE) {
- return new DHEPossession(
- namedGroup, hc.sslContext.getSecureRandom());
- }
-
- return null;
+ return namedGroup.createPossession(hc.sslContext.getSecureRandom());
}
@Override
public SSLKeyDerivation createKeyDerivation(
HandshakeContext hc) throws IOException {
- if (namedGroup.type == NamedGroupType.NAMED_GROUP_ECDHE) {
- return ECDHKeyExchange.ecdheKAGenerator.createKeyDerivation(hc);
- } else if (namedGroup.type == NamedGroupType.NAMED_GROUP_FFDHE) {
- return DHKeyExchange.kaGenerator.createKeyDerivation(hc);
- }
-
- return null;
+ return namedGroup.createKeyDerivation(hc);
}
}
}
--- a/src/java.base/share/classes/sun/security/ssl/SSLSocketInputRecord.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/SSLSocketInputRecord.java Thu Jun 13 11:31:36 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, 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
@@ -313,7 +313,9 @@
handshakeBuffer.put(handshakeFrag);
handshakeBuffer.rewind();
break;
- } if (remaining == handshakeMessageLen) {
+ }
+
+ if (remaining == handshakeMessageLen) {
if (handshakeHash.isHashable(handshakeType)) {
handshakeHash.receive(handshakeFrag);
}
--- a/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java Thu Jun 13 11:31:36 2019 +0530
@@ -26,7 +26,6 @@
package sun.security.ssl;
import java.security.*;
-import java.security.interfaces.ECPrivateKey;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.ECParameterSpec;
import java.security.spec.MGF1ParameterSpec;
@@ -39,8 +38,7 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
-import sun.security.ssl.SupportedGroupsExtension.NamedGroup;
-import sun.security.ssl.SupportedGroupsExtension.NamedGroupType;
+import sun.security.ssl.NamedGroup.NamedGroupType;
import sun.security.ssl.X509Authentication.X509Possession;
import sun.security.util.KeyUtil;
import sun.security.util.SignatureUtil;
@@ -432,10 +430,10 @@
}
for (SignatureScheme ss : schemes) {
if (ss.isAvailable && (keySize >= ss.minimalKeySize) &&
- ss.handshakeSupportedProtocols.contains(version) &&
- keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm)) {
- if (ss.namedGroup != null &&
- ss.namedGroup.type == NamedGroupType.NAMED_GROUP_ECDHE) {
+ ss.handshakeSupportedProtocols.contains(version) &&
+ keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm)) {
+ if ((ss.namedGroup != null) && (ss.namedGroup.type ==
+ NamedGroupType.NAMED_GROUP_ECDHE)) {
ECParameterSpec params =
x509Possession.getECParameterSpec();
if (params != null &&
--- a/src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java Thu Jun 13 11:31:36 2019 +0530
@@ -30,29 +30,24 @@
import java.security.AlgorithmConstraints;
import java.security.AlgorithmParameters;
import java.security.CryptoPrimitive;
-import java.security.NoSuchAlgorithmException;
-import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.ECGenParameterSpec;
-import java.security.spec.ECParameterSpec;
import java.security.spec.InvalidParameterSpecException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
-import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
-import java.util.Map;
-import javax.crypto.spec.DHParameterSpec;
import javax.net.ssl.SSLProtocolException;
import sun.security.action.GetPropertyAction;
+import sun.security.ssl.NamedGroup.NamedGroupType;
import static sun.security.ssl.SSLExtension.CH_SUPPORTED_GROUPS;
import static sun.security.ssl.SSLExtension.EE_SUPPORTED_GROUPS;
import sun.security.ssl.SSLExtension.ExtensionConsumer;
import sun.security.ssl.SSLExtension.SSLExtensionSpec;
import sun.security.ssl.SSLHandshake.HandshakeMessage;
-import sun.security.util.ECUtil;
+
/**
* Pack of the "supported_groups" extensions [RFC 4492/7919].
@@ -158,320 +153,11 @@
}
}
- static enum NamedGroupType {
- NAMED_GROUP_ECDHE ("EC"),
- NAMED_GROUP_FFDHE ("DiffieHellman"),
- NAMED_GROUP_X25519 ("x25519"),
- NAMED_GROUP_X448 ("x448"),
- NAMED_GROUP_ARBITRARY ("EC"),
- NAMED_GROUP_NONE ("");
-
- private final String algorithm;
-
- private NamedGroupType(String algorithm) {
- this.algorithm = algorithm;
- }
-
- boolean isSupported(List<CipherSuite> cipherSuites) {
- for (CipherSuite cs : cipherSuites) {
- if (cs.keyExchange == null ||
- cs.keyExchange.groupType == this) {
- return true;
- }
- }
-
- return false;
- }
- }
-
- static enum NamedGroup {
- // Elliptic Curves (RFC 4492)
- //
- // See sun.security.util.CurveDB for the OIDs
- // NIST K-163
- SECT163_K1 (0x0001, "sect163k1", "1.3.132.0.1",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
- SECT163_R1 (0x0002, "sect163r1", "1.3.132.0.2",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
-
- // NIST B-163
- SECT163_R2 (0x0003, "sect163r2", "1.3.132.0.15",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
- SECT193_R1 (0x0004, "sect193r1", "1.3.132.0.24",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
- SECT193_R2 (0x0005, "sect193r2", "1.3.132.0.25",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
-
- // NIST K-233
- SECT233_K1 (0x0006, "sect233k1", "1.3.132.0.26",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
-
- // NIST B-233
- SECT233_R1 (0x0007, "sect233r1", "1.3.132.0.27",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
- SECT239_K1 (0x0008, "sect239k1", "1.3.132.0.3",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
-
- // NIST K-283
- SECT283_K1 (0x0009, "sect283k1", "1.3.132.0.16",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
-
- // NIST B-283
- SECT283_R1 (0x000A, "sect283r1", "1.3.132.0.17",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
-
- // NIST K-409
- SECT409_K1 (0x000B, "sect409k1", "1.3.132.0.36",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
-
- // NIST B-409
- SECT409_R1 (0x000C, "sect409r1", "1.3.132.0.37",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
-
- // NIST K-571
- SECT571_K1 (0x000D, "sect571k1", "1.3.132.0.38",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
-
- // NIST B-571
- SECT571_R1 (0x000E, "sect571r1", "1.3.132.0.39",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
- SECP160_K1 (0x000F, "secp160k1", "1.3.132.0.9",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
- SECP160_R1 (0x0010, "secp160r1", "1.3.132.0.8",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
- SECP160_R2 (0x0011, "secp160r2", "1.3.132.0.30",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
- SECP192_K1 (0x0012, "secp192k1", "1.3.132.0.31",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
-
- // NIST P-192
- SECP192_R1 (0x0013, "secp192r1", "1.2.840.10045.3.1.1",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
- SECP224_K1 (0x0014, "secp224k1", "1.3.132.0.32",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
- // NIST P-224
- SECP224_R1 (0x0015, "secp224r1", "1.3.132.0.33",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
- SECP256_K1 (0x0016, "secp256k1", "1.3.132.0.10",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
-
- // NIST P-256
- SECP256_R1 (0x0017, "secp256r1", "1.2.840.10045.3.1.7",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_13),
-
- // NIST P-384
- SECP384_R1 (0x0018, "secp384r1", "1.3.132.0.34",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_13),
-
- // NIST P-521
- SECP521_R1 (0x0019, "secp521r1", "1.3.132.0.35",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_13),
-
- // x25519 and x448
- X25519 (0x001D, "x25519", null,
- NamedGroupType.NAMED_GROUP_X25519,
- ProtocolVersion.PROTOCOLS_TO_13),
- X448 (0x001E, "x448", null,
- NamedGroupType.NAMED_GROUP_X448,
- ProtocolVersion.PROTOCOLS_TO_13),
-
- // Finite Field Diffie-Hellman Ephemeral Parameters (RFC 7919)
- FFDHE_2048 (0x0100, "ffdhe2048", null,
- NamedGroupType.NAMED_GROUP_FFDHE,
- ProtocolVersion.PROTOCOLS_TO_13),
- FFDHE_3072 (0x0101, "ffdhe3072", null,
- NamedGroupType.NAMED_GROUP_FFDHE,
- ProtocolVersion.PROTOCOLS_TO_13),
- FFDHE_4096 (0x0102, "ffdhe4096", null,
- NamedGroupType.NAMED_GROUP_FFDHE,
- ProtocolVersion.PROTOCOLS_TO_13),
- FFDHE_6144 (0x0103, "ffdhe6144", null,
- NamedGroupType.NAMED_GROUP_FFDHE,
- ProtocolVersion.PROTOCOLS_TO_13),
- FFDHE_8192 (0x0104, "ffdhe8192", null,
- NamedGroupType.NAMED_GROUP_FFDHE,
- ProtocolVersion.PROTOCOLS_TO_13),
-
- // Elliptic Curves (RFC 4492)
- //
- // arbitrary prime and characteristic-2 curves
- ARBITRARY_PRIME (0xFF01, "arbitrary_explicit_prime_curves", null,
- NamedGroupType.NAMED_GROUP_ARBITRARY,
- ProtocolVersion.PROTOCOLS_TO_12),
- ARBITRARY_CHAR2 (0xFF02, "arbitrary_explicit_char2_curves", null,
- NamedGroupType.NAMED_GROUP_ARBITRARY,
- ProtocolVersion.PROTOCOLS_TO_12);
-
- final int id; // hash + signature
- final NamedGroupType type; // group type
- final String name; // literal name
- final String oid; // object identifier of the named group
- final String algorithm; // signature algorithm
- final ProtocolVersion[] supportedProtocols;
-
- private NamedGroup(int id, String name, String oid,
- NamedGroupType namedGroupType,
- ProtocolVersion[] supportedProtocols) {
- this.id = id;
- this.type = namedGroupType;
- this.name = name;
- this.oid = oid;
- this.algorithm = namedGroupType.algorithm;
- this.supportedProtocols = supportedProtocols;
- }
-
- static NamedGroup valueOf(int id) {
- for (NamedGroup group : NamedGroup.values()) {
- if (group.id == id) {
- return group;
- }
- }
-
- return null;
- }
-
- static NamedGroup valueOf(ECParameterSpec params) {
- String oid = ECUtil.getCurveName(null, params);
- if ((oid != null) && (!oid.isEmpty())) {
- for (NamedGroup group : NamedGroup.values()) {
- if ((group.type == NamedGroupType.NAMED_GROUP_ECDHE) &&
- oid.equals(group.oid)) {
- return group;
- }
- }
- }
-
- return null;
- }
-
- static NamedGroup valueOf(DHParameterSpec params) {
- for (Map.Entry<NamedGroup, AlgorithmParameters> me :
- SupportedGroups.namedGroupParams.entrySet()) {
- NamedGroup ng = me.getKey();
- if (ng.type != NamedGroupType.NAMED_GROUP_FFDHE) {
- continue;
- }
-
- DHParameterSpec ngParams = null;
- AlgorithmParameters aps = me.getValue();
- try {
- ngParams = aps.getParameterSpec(DHParameterSpec.class);
- } catch (InvalidParameterSpecException ipse) {
- // should be unlikely
- }
-
- if (ngParams == null) {
- continue;
- }
-
- if (ngParams.getP().equals(params.getP()) &&
- ngParams.getG().equals(params.getG())) {
- return ng;
- }
- }
-
- return null;
- }
-
- static NamedGroup nameOf(String name) {
- for (NamedGroup group : NamedGroup.values()) {
- if (group.name.equals(name)) {
- return group;
- }
- }
-
- return null;
- }
-
- static String nameOf(int id) {
- for (NamedGroup group : NamedGroup.values()) {
- if (group.id == id) {
- return group.name;
- }
- }
-
- return "UNDEFINED-NAMED-GROUP(" + id + ")";
- }
-
- boolean isAvailable(List<ProtocolVersion> protocolVersions) {
- for (ProtocolVersion pv : supportedProtocols) {
- if (protocolVersions.contains(pv)) {
- return true;
- }
- }
- return false;
- }
-
- boolean isAvailable(ProtocolVersion protocolVersion) {
- for (ProtocolVersion pv : supportedProtocols) {
- if (protocolVersion == pv) {
- return true;
- }
- }
- return false;
- }
-
- boolean isSupported(List<CipherSuite> cipherSuites) {
- for (CipherSuite cs : cipherSuites) {
- boolean isMatch = isAvailable(cs.supportedProtocols);
- if (isMatch && (cs.keyExchange == null ||
- cs.keyExchange.groupType == type)) {
- return true;
- }
- }
- return false;
- }
-
- // lazy loading of parameters
- AlgorithmParameters getParameters() {
- return SupportedGroups.namedGroupParams.get(this);
- }
-
- AlgorithmParameterSpec getParameterSpec() {
- if (this.type == NamedGroupType.NAMED_GROUP_ECDHE) {
- return SupportedGroups.getECGenParamSpec(this);
- } else if (this.type == NamedGroupType.NAMED_GROUP_FFDHE) {
- return SupportedGroups.getDHParameterSpec(this);
- }
-
- return null;
- }
- }
-
static class SupportedGroups {
// To switch off the supported_groups extension for DHE cipher suite.
static final boolean enableFFDHE =
Utilities.getBooleanProperty("jsse.enableFFDHE", true);
- // cache to speed up the parameters construction
- static final Map<NamedGroup,
- AlgorithmParameters> namedGroupParams = new HashMap<>();
-
// the supported named groups
static final NamedGroup[] supportedNamedGroups;
@@ -516,10 +202,19 @@
}
} else { // default groups
NamedGroup[] groups = new NamedGroup[] {
- // NIST curves first
+
+ // Primary XDH (RFC 7748) curves
+ NamedGroup.X25519,
+
+ // Primary NIST curves (e.g. used in TLSv1.3)
NamedGroup.SECP256_R1,
NamedGroup.SECP384_R1,
NamedGroup.SECP521_R1,
+
+ // Secondary XDH curves
+ NamedGroup.X448,
+
+ // Secondary NIST curves
NamedGroup.SECT283_K1,
NamedGroup.SECT283_R1,
NamedGroup.SECT409_K1,
@@ -530,7 +225,7 @@
// non-NIST curves
NamedGroup.SECP256_K1,
- // FFDHE 2048
+ // FFDHE (RFC 7919)
NamedGroup.FFDHE_2048,
NamedGroup.FFDHE_3072,
NamedGroup.FFDHE_4096,
@@ -560,126 +255,27 @@
// check whether the group is supported by the underlying providers
private static boolean isAvailableGroup(NamedGroup namedGroup) {
- AlgorithmParameters params = null;
- AlgorithmParameterSpec spec = null;
- if (namedGroup.type == NamedGroupType.NAMED_GROUP_ECDHE) {
- if (namedGroup.oid != null) {
- try {
- params = AlgorithmParameters.getInstance("EC");
- spec = new ECGenParameterSpec(namedGroup.oid);
- } catch (NoSuchAlgorithmException e) {
- return false;
- }
- }
- } else if (namedGroup.type == NamedGroupType.NAMED_GROUP_FFDHE) {
- try {
- params = AlgorithmParameters.getInstance("DiffieHellman");
- spec = getFFDHEDHParameterSpec(namedGroup);
- } catch (NoSuchAlgorithmException e) {
- return false;
- }
- } // Otherwise, unsupported.
-
- if ((params != null) && (spec != null)) {
- try {
- params.init(spec);
- } catch (InvalidParameterSpecException e) {
- return false;
- }
-
- // cache the parameters
- namedGroupParams.put(namedGroup, params);
-
- return true;
- }
-
- return false;
+ return namedGroup.isAvailableGroup();
}
- private static DHParameterSpec getFFDHEDHParameterSpec(
- NamedGroup namedGroup) {
- DHParameterSpec spec = null;
- switch (namedGroup) {
- case FFDHE_2048:
- spec = PredefinedDHParameterSpecs.ffdheParams.get(2048);
- break;
- case FFDHE_3072:
- spec = PredefinedDHParameterSpecs.ffdheParams.get(3072);
- break;
- case FFDHE_4096:
- spec = PredefinedDHParameterSpecs.ffdheParams.get(4096);
- break;
- case FFDHE_6144:
- spec = PredefinedDHParameterSpecs.ffdheParams.get(6144);
- break;
- case FFDHE_8192:
- spec = PredefinedDHParameterSpecs.ffdheParams.get(8192);
+ static ECGenParameterSpec getECGenParamSpec(NamedGroup ng) {
+ if (ng.type != NamedGroupType.NAMED_GROUP_ECDHE) {
+ throw new RuntimeException(
+ "Not a named EC group: " + ng);
}
- return spec;
- }
-
- private static DHParameterSpec getPredefinedDHParameterSpec(
- NamedGroup namedGroup) {
- DHParameterSpec spec = null;
- switch (namedGroup) {
- case FFDHE_2048:
- spec = PredefinedDHParameterSpecs.definedParams.get(2048);
- break;
- case FFDHE_3072:
- spec = PredefinedDHParameterSpecs.definedParams.get(3072);
- break;
- case FFDHE_4096:
- spec = PredefinedDHParameterSpecs.definedParams.get(4096);
- break;
- case FFDHE_6144:
- spec = PredefinedDHParameterSpecs.definedParams.get(6144);
- break;
- case FFDHE_8192:
- spec = PredefinedDHParameterSpecs.definedParams.get(8192);
- }
-
- return spec;
- }
-
- static ECGenParameterSpec getECGenParamSpec(NamedGroup namedGroup) {
- if (namedGroup.type != NamedGroupType.NAMED_GROUP_ECDHE) {
- throw new RuntimeException(
- "Not a named EC group: " + namedGroup);
- }
-
- AlgorithmParameters params = namedGroupParams.get(namedGroup);
- if (params == null) {
- throw new RuntimeException(
- "Not a supported EC named group: " + namedGroup);
- }
-
+ // parameters are non-null
+ AlgorithmParameters params = ng.getParameters();
try {
return params.getParameterSpec(ECGenParameterSpec.class);
} catch (InvalidParameterSpecException ipse) {
// should be unlikely
- return new ECGenParameterSpec(namedGroup.oid);
+ return new ECGenParameterSpec(ng.oid);
}
}
- static DHParameterSpec getDHParameterSpec(NamedGroup namedGroup) {
- if (namedGroup.type != NamedGroupType.NAMED_GROUP_FFDHE) {
- throw new RuntimeException(
- "Not a named DH group: " + namedGroup);
- }
-
- AlgorithmParameters params = namedGroupParams.get(namedGroup);
- if (params == null) {
- throw new RuntimeException(
- "Not a supported DH named group: " + namedGroup);
- }
-
- try {
- return params.getParameterSpec(DHParameterSpec.class);
- } catch (InvalidParameterSpecException ipse) {
- // should be unlikely
- return getPredefinedDHParameterSpec(namedGroup);
- }
+ static AlgorithmParameters getParameters(NamedGroup ng) {
+ return ng.getParameters();
}
// Is there any supported group permitted by the constraints?
@@ -692,7 +288,7 @@
if (constraints.permits(
EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
namedGroup.algorithm,
- namedGroupParams.get(namedGroup))) {
+ getParameters(namedGroup))) {
return true;
}
@@ -723,7 +319,7 @@
return constraints.permits(
EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
namedGroup.algorithm,
- namedGroupParams.get(namedGroup));
+ getParameters(namedGroup));
}
// Is the named group supported?
@@ -739,16 +335,16 @@
static NamedGroup getPreferredGroup(
ProtocolVersion negotiatedProtocol,
- AlgorithmConstraints constraints, NamedGroupType type,
+ AlgorithmConstraints constraints, NamedGroupType[] types,
List<NamedGroup> requestedNamedGroups) {
for (NamedGroup namedGroup : requestedNamedGroups) {
- if ((namedGroup.type == type) &&
+ if ((NamedGroupType.arrayContains(types, namedGroup.type)) &&
namedGroup.isAvailable(negotiatedProtocol) &&
isSupported(namedGroup) &&
constraints.permits(
EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
namedGroup.algorithm,
- namedGroupParams.get(namedGroup))) {
+ getParameters(namedGroup))) {
return namedGroup;
}
}
@@ -758,14 +354,14 @@
static NamedGroup getPreferredGroup(
ProtocolVersion negotiatedProtocol,
- AlgorithmConstraints constraints, NamedGroupType type) {
+ AlgorithmConstraints constraints, NamedGroupType[] types) {
for (NamedGroup namedGroup : supportedNamedGroups) {
- if ((namedGroup.type == type) &&
+ if ((NamedGroupType.arrayContains(types, namedGroup.type)) &&
namedGroup.isAvailable(negotiatedProtocol) &&
constraints.permits(
EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
namedGroup.algorithm,
- namedGroupParams.get(namedGroup))) {
+ getParameters(namedGroup))) {
return namedGroup;
}
}
@@ -813,7 +409,7 @@
ng.isSupported(chc.activeCipherSuites) &&
chc.algorithmConstraints.permits(
EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
- ng.algorithm, namedGroupParams.get(ng))) {
+ ng.algorithm, getParameters(ng))) {
namedGroups.add(ng);
} else if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.fine(
@@ -940,7 +536,7 @@
ng.isSupported(shc.activeCipherSuites) &&
shc.algorithmConstraints.permits(
EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
- ng.algorithm, namedGroupParams.get(ng))) {
+ ng.algorithm, getParameters(ng))) {
namedGroups.add(ng);
} else if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.fine(
--- a/src/java.base/share/classes/sun/security/ssl/TransportContext.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/TransportContext.java Thu Jun 13 11:31:36 2019 +0530
@@ -39,7 +39,6 @@
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSocket;
-import sun.security.ssl.SupportedGroupsExtension.NamedGroup;
/**
* SSL/(D)TLS transportation context.
--- a/src/java.base/share/classes/sun/security/ssl/Utilities.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/Utilities.java Thu Jun 13 11:31:36 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, 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
@@ -61,8 +61,8 @@
int size = serverNames.size();
List<SNIServerName> sniList = (size != 0) ?
- new ArrayList<SNIServerName>(serverNames) :
- new ArrayList<SNIServerName>(1);
+ new ArrayList<>(serverNames) :
+ new ArrayList<>(1);
boolean reset = false;
for (int i = 0; i < size; i++) {
@@ -147,7 +147,7 @@
static String indent(String source, String prefix) {
StringBuilder builder = new StringBuilder();
if (source == null) {
- builder.append("\n" + prefix + "<blank message>");
+ builder.append("\n").append(prefix).append("<blank message>");
} else {
String[] lines = lineBreakPatern.split(source);
boolean isFirst = true;
@@ -232,4 +232,21 @@
}
return b;
}
+
+ static void reverseBytes(byte[] arr) {
+ int i = 0;
+ int j = arr.length - 1;
+
+ while (i < j) {
+ swap(arr, i, j);
+ i++;
+ j--;
+ }
+ }
+
+ private static void swap(byte[] arr, int i, int j) {
+ byte tmp = arr[i];
+ arr[i] = arr[j];
+ arr[j] = tmp;
+ }
}
--- a/src/java.base/share/classes/sun/security/ssl/X509Authentication.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/java.base/share/classes/sun/security/ssl/X509Authentication.java Thu Jun 13 11:31:36 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -30,13 +30,15 @@
import java.security.cert.X509Certificate;
import java.security.interfaces.ECKey;
import java.security.interfaces.ECPublicKey;
+import java.security.interfaces.XECKey;
+import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.ECParameterSpec;
+import java.security.spec.NamedParameterSpec;
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.Map;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.X509ExtendedKeyManager;
-import sun.security.ssl.SupportedGroupsExtension.NamedGroup;
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
enum X509Authentication implements SSLAuthentication {
@@ -148,6 +150,35 @@
return null;
}
+
+ // Similar to above, but for XEC.
+ NamedParameterSpec getXECParameterSpec() {
+ if (popPrivateKey == null ||
+ !"XEC".equals(popPrivateKey.getAlgorithm())) {
+ return null;
+ }
+
+ if (popPrivateKey instanceof XECKey) {
+ AlgorithmParameterSpec params =
+ ((XECKey)popPrivateKey).getParams();
+ if (params instanceof NamedParameterSpec){
+ return (NamedParameterSpec)params;
+ }
+ } else if (popCerts != null && popCerts.length != 0) {
+ // The private key not extractable, get the parameters from
+ // the X.509 certificate.
+ PublicKey publicKey = popCerts[0].getPublicKey();
+ if (publicKey instanceof XECKey) {
+ AlgorithmParameterSpec params =
+ ((XECKey)publicKey).getParams();
+ if (params instanceof NamedParameterSpec){
+ return (NamedParameterSpec)params;
+ }
+ }
+ }
+
+ return null;
+ }
}
static final class X509Credentials implements SSLCredentials {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/XDHKeyExchange.java Thu Jun 13 11:31:36 2019 +0530
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2019, 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 sun.security.ssl;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.*;
+import java.security.interfaces.XECPublicKey;
+import java.security.spec.*;
+import sun.security.ssl.NamedGroup.NamedGroupType;
+import sun.security.util.*;
+
+/**
+ * Specifics for XEC/XDH Keys/Exchanges
+ */
+final class XDHKeyExchange {
+
+ static final SSLKeyAgreementGenerator xdheKAGenerator
+ = new XDHEKAGenerator();
+
+ static final class XDHECredentials implements NamedGroupCredentials {
+
+ final XECPublicKey popPublicKey;
+ final NamedGroup namedGroup;
+
+ XDHECredentials(XECPublicKey popPublicKey, NamedGroup namedGroup) {
+ this.popPublicKey = popPublicKey;
+ this.namedGroup = namedGroup;
+ }
+
+ @Override
+ public PublicKey getPublicKey() {
+ return popPublicKey;
+ }
+
+ @Override
+ public NamedGroup getNamedGroup() {
+ return namedGroup;
+ }
+
+ /**
+ * Parse the encoded Point into the XDHECredentials using the
+ * namedGroup.
+ */
+ static XDHECredentials valueOf(NamedGroup namedGroup,
+ byte[] encodedPoint) throws IOException,
+ GeneralSecurityException {
+
+ if (namedGroup.type != NamedGroupType.NAMED_GROUP_XDH) {
+ throw new RuntimeException(
+ "Credentials decoding: Not XDH named group");
+ }
+
+ if (encodedPoint == null || encodedPoint.length == 0) {
+ return null;
+ }
+
+ byte[] uBytes = encodedPoint.clone();
+ Utilities.reverseBytes(uBytes);
+ BigInteger u = new BigInteger(1, uBytes);
+
+ XECPublicKeySpec xecPublicKeySpec = new XECPublicKeySpec(
+ new NamedParameterSpec(namedGroup.name), u);
+ KeyFactory factory = KeyFactory.getInstance(namedGroup.algorithm);
+ XECPublicKey publicKey = (XECPublicKey) factory.generatePublic(
+ xecPublicKeySpec);
+
+ return new XDHECredentials(publicKey, namedGroup);
+ }
+ }
+
+ static final class XDHEPossession implements NamedGroupPossession {
+
+ final PrivateKey privateKey;
+ final XECPublicKey publicKey;
+ final NamedGroup namedGroup;
+
+ XDHEPossession(NamedGroup namedGroup, SecureRandom random) {
+ try {
+ KeyPairGenerator kpg
+ = KeyPairGenerator.getInstance(namedGroup.algorithm);
+ AlgorithmParameterSpec params = namedGroup.getParameterSpec();
+ kpg.initialize(params, random);
+ KeyPair kp = kpg.generateKeyPair();
+ privateKey = kp.getPrivate();
+ publicKey = (XECPublicKey) kp.getPublic();
+ } catch (GeneralSecurityException e) {
+ throw new RuntimeException(
+ "Could not generate XDH keypair", e);
+ }
+
+ this.namedGroup = namedGroup;
+ }
+
+ @Override
+ public byte[] encode() {
+
+ byte[] uBytes = ECUtil.trimZeroes(publicKey.getU().toByteArray());
+
+ int expLength;
+ switch (namedGroup) {
+ case X25519:
+ expLength = 32;
+ break;
+ case X448:
+ expLength = 56;
+ break;
+ default:
+ throw new RuntimeException("Invalid XDH group");
+ }
+
+ if (uBytes.length > expLength) {
+ throw new RuntimeException("Encoded XDH key too large");
+ }
+
+ if (uBytes.length != expLength) {
+ byte[] tmp = new byte[expLength];
+ System.arraycopy(uBytes, 0, tmp,
+ expLength - uBytes.length, uBytes.length);
+ uBytes = tmp;
+ }
+
+ Utilities.reverseBytes(uBytes);
+ return (uBytes);
+ }
+
+ @Override
+ public PublicKey getPublicKey() {
+ return publicKey;
+ }
+
+ @Override
+ public NamedGroup getNamedGroup() {
+ return namedGroup;
+ }
+
+ @Override
+ public PrivateKey getPrivateKey() {
+ return privateKey;
+ }
+ }
+
+ private static final class XDHEKAGenerator
+ implements SSLKeyAgreementGenerator {
+
+ // Prevent instantiation of this class.
+ private XDHEKAGenerator() {
+ // blank
+ }
+
+ @Override
+ public SSLKeyDerivation createKeyDerivation(
+ HandshakeContext context) throws IOException {
+ XDHEPossession xdhePossession = null;
+ XDHECredentials xdheCredentials = null;
+ for (SSLPossession poss : context.handshakePossessions) {
+ if (!(poss instanceof XDHEPossession)) {
+ continue;
+ }
+
+ NamedGroup ng = ((XDHEPossession) poss).namedGroup;
+ for (SSLCredentials cred : context.handshakeCredentials) {
+ if (!(cred instanceof XDHECredentials)) {
+ continue;
+ }
+ if (ng.equals(((XDHECredentials) cred).namedGroup)) {
+ xdheCredentials = (XDHECredentials) cred;
+ break;
+ }
+ }
+
+ if (xdheCredentials != null) {
+ xdhePossession = (XDHEPossession) poss;
+ break;
+ }
+ }
+
+ if (xdhePossession == null || xdheCredentials == null) {
+ context.conContext.fatal(Alert.HANDSHAKE_FAILURE,
+ "No sufficient XDHE key agreement "
+ + "parameters negotiated");
+ }
+
+ return new KAKeyDerivation("XDH", context,
+ xdhePossession.privateKey, xdheCredentials.popPublicKey);
+ }
+ }
+}
--- a/src/java.security.jgss/share/classes/sun/security/jgss/spnego/NegTokenTarg.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/java.security.jgss/share/classes/sun/security/jgss/spnego/NegTokenTarg.java Thu Jun 13 11:31:36 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,6 @@
package sun.security.jgss.spnego;
import java.io.*;
-import java.util.*;
import org.ietf.jgss.*;
import sun.security.jgss.*;
import sun.security.util.*;
@@ -113,18 +112,6 @@
mic.putOctetString(mechListMIC);
targToken.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x03), mic);
- } else if (GSSUtil.useMSInterop()) {
- // required for MS-interoperability
- if (responseToken != null) {
- if (DEBUG) {
- System.out.println("SpNegoToken NegTokenTarg: " +
- "sending additional token for MS Interop");
- }
- DerOutputStream rspToken = new DerOutputStream();
- rspToken.putOctetString(responseToken);
- targToken.write(DerValue.createTag(DerValue.TAG_CONTEXT,
- true, (byte) 0x03), rspToken);
- }
}
// insert in a SEQUENCE
--- a/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java Thu Jun 13 11:31:36 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, 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
@@ -66,7 +66,7 @@
static {
MECH_MAP =
AccessController.doPrivileged(
- new PrivilegedAction<HashMap<String, String>>() {
+ new PrivilegedAction<>() {
public HashMap<String, String> run() {
DEBUG = Boolean.parseBoolean(
System.getProperty("sun.security.nativegss.debug"));
@@ -77,7 +77,7 @@
if (DEBUG) err.printStackTrace();
return null;
}
- String[] gssLibs = new String[0];
+ String[] gssLibs;
String defaultLib
= System.getProperty("sun.security.jgss.lib");
if (defaultLib == null || defaultLib.trim().equals("")) {
@@ -95,6 +95,12 @@
"libgssapi_krb5.dylib",
"/usr/lib/sasl2/libgssapiv2.2.so",
};
+ } else if (osname.contains("Windows")) {
+ // Full path needed, DLL is in jre/bin
+ gssLibs = new String[]{ System.getProperty("java.home")
+ + "\\bin\\sspi_bridge.dll" };
+ } else {
+ gssLibs = new String[0];
}
} else {
gssLibs = new String[]{ defaultLib };
@@ -103,8 +109,7 @@
if (GSSLibStub.init(libName, DEBUG)) {
debug("Loaded GSS library: " + libName);
Oid[] mechs = GSSLibStub.indicateMechs();
- HashMap<String, String> map =
- new HashMap<String, String>();
+ HashMap<String,String> map = new HashMap<>();
for (int i = 0; i < mechs.length; i++) {
debug("Native MF for " + mechs[i]);
map.put("GssApiMechanism." + mechs[i],
--- a/src/java.security.jgss/share/native/libj2gss/GSSLibStub.c Wed Jun 12 10:02:49 2019 +0530
+++ b/src/java.security.jgss/share/native/libj2gss/GSSLibStub.c Thu Jun 13 11:31:36 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, 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
@@ -982,7 +982,7 @@
OM_uint32 aFlags;
OM_uint32 aTime;
gss_cred_id_t delCred;
- jobject jsrcName=GSS_C_NO_NAME;
+ jobject jsrcName = NULL;
jobject jdelCred;
jobject jMech;
jboolean setTarget;
--- a/src/java.security.jgss/share/native/libj2gss/NativeFunc.h Wed Jun 12 10:02:49 2019 +0530
+++ b/src/java.security.jgss/share/native/libj2gss/NativeFunc.h Thu Jun 13 11:31:36 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, 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
@@ -57,38 +57,38 @@
typedef OM_uint32 (*IMPORT_NAME_FN_PTR)
(OM_uint32 *minor_status,
- gss_buffer_t input_name_buffer,
- gss_OID input_name_type,
+ const gss_buffer_t input_name_buffer,
+ const gss_OID input_name_type,
gss_name_t *output_name);
typedef OM_uint32 (*COMPARE_NAME_FN_PTR)
(OM_uint32 *minor_status,
- gss_name_t name1,
- gss_name_t name2,
+ gss_const_name_t name1,
+ gss_const_name_t name2,
int *name_equal);
typedef OM_uint32 (*CANONICALIZE_NAME_FN_PTR)
(OM_uint32 *minor_status,
- gss_name_t input_name,
- gss_OID mech_type,
+ gss_const_name_t input_name,
+ const gss_OID mech_type,
gss_name_t *output_name);
typedef OM_uint32 (*EXPORT_NAME_FN_PTR)
(OM_uint32 *minor_status,
- gss_name_t input_name,
+ gss_const_name_t input_name,
gss_buffer_t exported_name);
typedef OM_uint32 (*DISPLAY_NAME_FN_PTR)
(OM_uint32 *minor_status,
- gss_name_t input_name,
+ gss_const_name_t input_name,
gss_buffer_t output_name_buffer,
gss_OID *output_name_type);
typedef OM_uint32 (*ACQUIRE_CRED_FN_PTR)
(OM_uint32 *minor_status,
- gss_name_t desired_name,
+ gss_const_name_t desired_name,
OM_uint32 time_req,
- gss_OID_set desired_mech,
+ const gss_OID_set desired_mech,
gss_cred_usage_t cred_usage,
gss_cred_id_t *output_cred_handle,
gss_OID_set *actual_mechs,
@@ -100,7 +100,7 @@
typedef OM_uint32 (*INQUIRE_CRED_FN_PTR)
(OM_uint32 *minor_status,
- gss_cred_id_t cred_handle,
+ gss_const_cred_id_t cred_handle,
gss_name_t *name,
OM_uint32 *lifetime,
gss_cred_usage_t *cred_usage,
@@ -108,19 +108,19 @@
typedef OM_uint32 (*IMPORT_SEC_CONTEXT_FN_PTR)
(OM_uint32 *minor_status,
- gss_buffer_t interprocess_token,
+ const gss_buffer_t interprocess_token,
gss_ctx_id_t *context_handle);
typedef OM_uint32 (*INIT_SEC_CONTEXT_FN_PTR)
(OM_uint32 *minor_status,
- gss_cred_id_t initiator_cred_handle,
+ gss_const_cred_id_t initiator_cred_handle,
gss_ctx_id_t *context_handle,
- gss_name_t *target_name,
- gss_OID mech_type,
+ gss_const_name_t target_name,
+ const gss_OID mech_type,
OM_uint32 req_flags,
OM_uint32 time_req,
- gss_channel_bindings_t input_chan_bindings,
- gss_buffer_t input_token,
+ const gss_channel_bindings_t input_chan_bindings,
+ const gss_buffer_t input_token,
gss_OID *actual_mech_type,
gss_buffer_t output_token,
OM_uint32 *ret_flags,
@@ -129,9 +129,9 @@
typedef OM_uint32 (*ACCEPT_SEC_CONTEXT_FN_PTR)
(OM_uint32 *minor_status,
gss_ctx_id_t *context_handle,
- gss_cred_id_t acceptor_cred_handle,
- gss_buffer_t input_token,
- gss_channel_bindings_t input_chan_bindings,
+ gss_const_cred_id_t acceptor_cred_handle,
+ const gss_buffer_t input_token,
+ const gss_channel_bindings_t input_chan_bindings,
gss_name_t *src_name,
gss_OID *mech_type,
gss_buffer_t output_token,
@@ -141,7 +141,7 @@
typedef OM_uint32 (*INQUIRE_CONTEXT_FN_PTR)
(OM_uint32 *minor_status,
- gss_ctx_id_t context_handle,
+ gss_const_ctx_id_t context_handle,
gss_name_t *src_name,
gss_name_t *targ_name,
OM_uint32 *lifetime_rec,
@@ -157,12 +157,12 @@
typedef OM_uint32 (*CONTEXT_TIME_FN_PTR)
(OM_uint32 *minor_status,
- gss_ctx_id_t *context_handle,
+ gss_const_ctx_id_t context_handle,
OM_uint32 *time_rec);
typedef OM_uint32 (*WRAP_SIZE_LIMIT_FN_PTR)
(OM_uint32 *minor_status,
- gss_ctx_id_t context_handle,
+ gss_const_ctx_id_t context_handle,
int conf_req_flag,
gss_qop_t qop_req,
OM_uint32 req_output_size,
@@ -175,31 +175,31 @@
typedef OM_uint32 (*GET_MIC_FN_PTR)
(OM_uint32 *minor_status,
- gss_ctx_id_t context_handle,
+ gss_const_ctx_id_t context_handle,
gss_qop_t qop_req,
- gss_buffer_t message_buffer,
+ const gss_buffer_t message_buffer,
gss_buffer_t msg_token);
typedef OM_uint32 (*VERIFY_MIC_FN_PTR)
(OM_uint32 *minor_status,
- gss_ctx_id_t context_handle,
- gss_buffer_t message_buffer,
- gss_buffer_t token_buffer,
+ gss_const_ctx_id_t context_handle,
+ const gss_buffer_t message_buffer,
+ const gss_buffer_t token_buffer,
gss_qop_t *qop_state);
typedef OM_uint32 (*WRAP_FN_PTR)
(OM_uint32 *minor_status,
- gss_ctx_id_t context_handle,
+ gss_const_ctx_id_t context_handle,
int conf_req_flag,
gss_qop_t qop_req,
- gss_buffer_t input_message_buffer,
+ const gss_buffer_t input_message_buffer,
int *conf_state,
gss_buffer_t output_message_buffer);
typedef OM_uint32 (*UNWRAP_FN_PTR)
(OM_uint32 *minor_status,
- gss_ctx_id_t context_handle,
- gss_buffer_t input_message_buffer,
+ gss_const_ctx_id_t context_handle,
+ const gss_buffer_t input_message_buffer,
gss_buffer_t output_message_buffer,
int *conf_state,
gss_qop_t *qop_state);
@@ -215,14 +215,14 @@
typedef OM_uint32 (*ADD_OID_SET_MEMBER_FN_PTR)
(OM_uint32 *minor_status,
- gss_OID member_oid,
+ const gss_OID member_oid,
gss_OID_set *oid_set);
typedef OM_uint32 (*DISPLAY_STATUS_FN_PTR)
(OM_uint32 *minor_status,
OM_uint32 status_value,
int status_type,
- gss_OID mech_type,
+ const gss_OID mech_type,
OM_uint32 *message_context,
gss_buffer_t status_string);
--- a/src/java.security.jgss/share/native/libj2gss/NativeUtil.h Wed Jun 12 10:02:49 2019 +0530
+++ b/src/java.security.jgss/share/native/libj2gss/NativeUtil.h Thu Jun 13 11:31:36 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, 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
@@ -83,10 +83,10 @@
extern jfieldID FID_NativeGSSContext_flags;
extern jfieldID FID_NativeGSSContext_lifetime;
extern jfieldID FID_NativeGSSContext_actualMech;
- #define TRACE0(s) { if (JGSS_DEBUG) { puts(s); fflush(stdout); }}
- #define TRACE1(s, p1) { if (JGSS_DEBUG) { printf(s"\n", p1); fflush(stdout); }}
- #define TRACE2(s, p1, p2) { if (JGSS_DEBUG) { printf(s"\n", p1, p2); fflush(stdout); }}
- #define TRACE3(s, p1, p2, p3) { if (JGSS_DEBUG) { printf(s"\n", p1, p2, p3); fflush(stdout); }}
+ #define TRACE0(s) { if (JGSS_DEBUG) { printf("[GSSLibStub:%d] %s\n", __LINE__, s); fflush(stdout); }}
+ #define TRACE1(s, p1) { if (JGSS_DEBUG) { printf("[GSSLibStub:%d] "s"\n", __LINE__, p1); fflush(stdout); }}
+ #define TRACE2(s, p1, p2) { if (JGSS_DEBUG) { printf("[GSSLibStub:%d] "s"\n", __LINE__, p1, p2); fflush(stdout); }}
+ #define TRACE3(s, p1, p2, p3) { if (JGSS_DEBUG) { printf("[GSSLibStub:%d] "s"\n", __LINE__, p1, p2, p3); fflush(stdout); }}
#ifdef __cplusplus
--- a/src/java.security.jgss/share/native/libj2gss/gssapi.h Wed Jun 12 10:02:49 2019 +0530
+++ b/src/java.security.jgss/share/native/libj2gss/gssapi.h Thu Jun 13 11:31:36 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, 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
@@ -57,9 +57,17 @@
*/
#include <sys/types.h>
-typedef void * gss_name_t;
-typedef void * gss_cred_id_t;
-typedef void * gss_ctx_id_t;
+struct gss_name_struct;
+typedef struct gss_name_struct * gss_name_t;
+typedef const struct gss_name_struct *gss_const_name_t;
+
+struct gss_cred_id_struct;
+typedef struct gss_cred_id_struct * gss_cred_id_t;
+typedef const struct gss_cred_id_struct *gss_const_cred_id_t;
+
+struct gss_ctx_id_struct;
+typedef struct gss_ctx_id_struct * gss_ctx_id_t;
+typedef const struct gss_ctx_id_struct *gss_const_ctx_id_t;
/*
* The following type must be defined as the smallest natural unsigned integer
@@ -82,16 +90,19 @@
OM_uint32 length;
void *elements;
} gss_OID_desc, *gss_OID;
+typedef const gss_OID_desc * gss_const_OID;
typedef struct gss_OID_set_desc_struct {
size_t count;
gss_OID elements;
} gss_OID_set_desc, *gss_OID_set;
+typedef const gss_OID_set_desc * gss_const_OID_set;
typedef struct gss_buffer_desc_struct {
size_t length;
void *value;
} gss_buffer_desc, *gss_buffer_t;
+typedef const gss_buffer_desc * gss_const_buffer_t;
typedef struct gss_channel_bindings_struct {
OM_uint32 initiator_addrtype;
@@ -100,6 +111,7 @@
gss_buffer_desc acceptor_address;
gss_buffer_desc application_data;
} *gss_channel_bindings_t;
+typedef const struct gss_channel_bindings_struct *gss_const_channel_bindings_t;
/*
* For now, define a QOP-type as an OM_uint32
@@ -119,6 +131,7 @@
#define GSS_C_ANON_FLAG 64
#define GSS_C_PROT_READY_FLAG 128
#define GSS_C_TRANS_FLAG 256
+#define GSS_C_DELEG_POLICY_FLAG 32768
/*
* Credential usage options
@@ -389,9 +402,9 @@
GSS_DLLIMP OM_uint32 gss_acquire_cred(
OM_uint32 *, /* minor_status */
- gss_name_t, /* desired_name */
+ gss_const_name_t, /* desired_name */
OM_uint32, /* time_req */
- gss_OID_set, /* desired_mechs */
+ const gss_OID_set, /* desired_mechs */
gss_cred_usage_t, /* cred_usage */
gss_cred_id_t *, /* output_cred_handle */
gss_OID_set *, /* actual_mechs */
@@ -405,14 +418,14 @@
GSS_DLLIMP OM_uint32 gss_init_sec_context(
OM_uint32 *, /* minor_status */
- gss_cred_id_t, /* claimant_cred_handle */
+ gss_const_cred_id_t, /* claimant_cred_handle */
gss_ctx_id_t *, /* context_handle */
- gss_name_t, /* target_name */
- gss_OID, /* mech_type (used to be const) */
+ gss_const_name_t, /* target_name */
+ const gss_OID, /* mech_type */
OM_uint32, /* req_flags */
OM_uint32, /* time_req */
- gss_channel_bindings_t, /* input_chan_bindings */
- gss_buffer_t, /* input_token */
+ const gss_channel_bindings_t, /* input_chan_bindings */
+ const gss_buffer_t, /* input_token */
gss_OID *, /* actual_mech_type */
gss_buffer_t, /* output_token */
OM_uint32 *, /* ret_flags */
@@ -422,9 +435,9 @@
GSS_DLLIMP OM_uint32 gss_accept_sec_context(
OM_uint32 *, /* minor_status */
gss_ctx_id_t *, /* context_handle */
- gss_cred_id_t, /* acceptor_cred_handle */
- gss_buffer_t, /* input_token_buffer */
- gss_channel_bindings_t, /* input_chan_bindings */
+ gss_const_cred_id_t, /* acceptor_cred_handle */
+ const gss_buffer_t, /* input_token_buffer */
+ const gss_channel_bindings_t, /* input_chan_bindings */
gss_name_t *, /* src_name */
gss_OID *, /* mech_type */
gss_buffer_t, /* output_token */
@@ -435,8 +448,8 @@
GSS_DLLIMP OM_uint32 gss_process_context_token(
OM_uint32 *, /* minor_status */
- gss_ctx_id_t, /* context_handle */
- gss_buffer_t /* token_buffer */
+ gss_const_ctx_id_t, /* context_handle */
+ const gss_buffer_t /* token_buffer */
);
GSS_DLLIMP OM_uint32 gss_delete_sec_context(
@@ -447,35 +460,35 @@
GSS_DLLIMP OM_uint32 gss_context_time(
OM_uint32 *, /* minor_status */
- gss_ctx_id_t, /* context_handle */
+ gss_const_ctx_id_t, /* context_handle */
OM_uint32 * /* time_rec */
);
/* New for V2 */
GSS_DLLIMP OM_uint32 gss_get_mic(
OM_uint32 *, /* minor_status */
- gss_ctx_id_t, /* context_handle */
+ gss_const_ctx_id_t, /* context_handle */
gss_qop_t, /* qop_req */
- gss_buffer_t, /* message_buffer */
+ const gss_buffer_t, /* message_buffer */
gss_buffer_t /* message_token */
);
/* New for V2 */
GSS_DLLIMP OM_uint32 gss_verify_mic(
OM_uint32 *, /* minor_status */
- gss_ctx_id_t, /* context_handle */
- gss_buffer_t, /* message_buffer */
- gss_buffer_t, /* message_token */
+ gss_const_ctx_id_t, /* context_handle */
+ const gss_buffer_t, /* message_buffer */
+ const gss_buffer_t, /* message_token */
gss_qop_t * /* qop_state */
);
/* New for V2 */
GSS_DLLIMP OM_uint32 gss_wrap(
OM_uint32 *, /* minor_status */
- gss_ctx_id_t, /* context_handle */
+ gss_const_ctx_id_t, /* context_handle */
int, /* conf_req_flag */
gss_qop_t, /* qop_req */
- gss_buffer_t, /* input_message_buffer */
+ const gss_buffer_t, /* input_message_buffer */
int *, /* conf_state */
gss_buffer_t /* output_message_buffer */
);
@@ -483,8 +496,8 @@
/* New for V2 */
GSS_DLLIMP OM_uint32 gss_unwrap(
OM_uint32 *, /* minor_status */
- gss_ctx_id_t, /* context_handle */
- gss_buffer_t, /* input_message_buffer */
+ gss_const_ctx_id_t, /* context_handle */
+ const gss_buffer_t, /* input_message_buffer */
gss_buffer_t, /* output_message_buffer */
int *, /* conf_state */
gss_qop_t * /* qop_state */
@@ -494,7 +507,7 @@
OM_uint32 *, /* minor_status */
OM_uint32, /* status_value */
int, /* status_type */
- gss_OID, /* mech_type (used to be const) */
+ const gss_OID, /* mech_type (used to be const) */
OM_uint32 *, /* message_context */
gss_buffer_t /* status_string */
);
@@ -506,22 +519,22 @@
GSS_DLLIMP OM_uint32 gss_compare_name(
OM_uint32 *, /* minor_status */
- gss_name_t, /* name1 */
- gss_name_t, /* name2 */
+ gss_const_name_t, /* name1 */
+ gss_const_name_t, /* name2 */
int * /* name_equal */
);
GSS_DLLIMP OM_uint32 gss_display_name(
OM_uint32 *, /* minor_status */
- gss_name_t, /* input_name */
+ gss_const_name_t, /* input_name */
gss_buffer_t, /* output_name_buffer */
gss_OID * /* output_name_type */
);
GSS_DLLIMP OM_uint32 gss_import_name(
OM_uint32 *, /* minor_status */
- gss_buffer_t, /* input_name_buffer */
- gss_OID, /* input_name_type(used to be const) */
+ const gss_buffer_t, /* input_name_buffer */
+ const gss_OID, /* input_name_type(used to be const) */
gss_name_t * /* output_name */
);
@@ -542,7 +555,7 @@
GSS_DLLIMP OM_uint32 gss_inquire_cred(
OM_uint32 *, /* minor_status */
- gss_cred_id_t, /* cred_handle */
+ gss_const_cred_id_t, /* cred_handle */
gss_name_t *, /* name */
OM_uint32 *, /* lifetime */
gss_cred_usage_t *, /* cred_usage */
@@ -552,7 +565,7 @@
/* Last argument new for V2 */
GSS_DLLIMP OM_uint32 gss_inquire_context(
OM_uint32 *, /* minor_status */
- gss_ctx_id_t, /* context_handle */
+ gss_const_ctx_id_t, /* context_handle */
gss_name_t *, /* src_name */
gss_name_t *, /* targ_name */
OM_uint32 *, /* lifetime_rec */
@@ -565,7 +578,7 @@
/* New for V2 */
GSS_DLLIMP OM_uint32 gss_wrap_size_limit(
OM_uint32 *, /* minor_status */
- gss_ctx_id_t, /* context_handle */
+ gss_const_ctx_id_t, /* context_handle */
int, /* conf_req_flag */
gss_qop_t, /* qop_req */
OM_uint32, /* req_output_size */
@@ -575,9 +588,9 @@
/* New for V2 */
GSS_DLLIMP OM_uint32 gss_add_cred(
OM_uint32 *, /* minor_status */
- gss_cred_id_t, /* input_cred_handle */
- gss_name_t, /* desired_name */
- gss_OID, /* desired_mech */
+ gss_const_cred_id_t, /* input_cred_handle */
+ gss_const_name_t, /* desired_name */
+ const gss_OID, /* desired_mech */
gss_cred_usage_t, /* cred_usage */
OM_uint32, /* initiator_time_req */
OM_uint32, /* acceptor_time_req */
@@ -590,8 +603,8 @@
/* New for V2 */
GSS_DLLIMP OM_uint32 gss_inquire_cred_by_mech(
OM_uint32 *, /* minor_status */
- gss_cred_id_t, /* cred_handle */
- gss_OID, /* mech_type */
+ gss_const_cred_id_t, /* cred_handle */
+ const gss_OID, /* mech_type */
gss_name_t *, /* name */
OM_uint32 *, /* initiator_lifetime */
OM_uint32 *, /* acceptor_lifetime */
@@ -608,7 +621,7 @@
/* New for V2 */
GSS_DLLIMP OM_uint32 gss_import_sec_context(
OM_uint32 *, /* minor_status */
- gss_buffer_t, /* interprocess_token */
+ const gss_buffer_t, /* interprocess_token */
gss_ctx_id_t * /* context_handle */
);
@@ -627,22 +640,22 @@
/* New for V2 */
GSS_DLLIMP OM_uint32 gss_add_oid_set_member(
OM_uint32 *, /* minor_status */
- gss_OID, /* member_oid */
+ const gss_OID, /* member_oid */
gss_OID_set * /* oid_set */
);
/* New for V2 */
GSS_DLLIMP OM_uint32 gss_test_oid_set_member(
OM_uint32 *, /* minor_status */
- gss_OID, /* member */
- gss_OID_set, /* set */
+ const gss_OID, /* member */
+ const gss_OID_set, /* set */
int * /* present */
);
/* New for V2 */
GSS_DLLIMP OM_uint32 gss_str_to_oid(
OM_uint32 *, /* minor_status */
- gss_buffer_t, /* oid_str */
+ const gss_buffer_t, /* oid_str */
gss_OID * /* oid */
);
@@ -656,28 +669,28 @@
/* New for V2 */
GSS_DLLIMP OM_uint32 gss_inquire_names_for_mech(
OM_uint32 *, /* minor_status */
- gss_OID, /* mechanism */
+ const gss_OID, /* mechanism */
gss_OID_set * /* name_types */
);
/* New for V2 */
GSS_DLLIMP OM_uint32 gss_export_name(
OM_uint32 *, /* minor_status */
- const gss_name_t, /* input_name */
+ gss_const_name_t, /* input_name */
gss_buffer_t /* exported_name */
);
/* New for V2 */
GSS_DLLIMP OM_uint32 gss_duplicate_name(
OM_uint32 *, /* minor_status */
- const gss_name_t, /* input_name */
+ gss_const_name_t, /* input_name */
gss_name_t * /* dest_name */
);
/* New for V2 */
GSS_DLLIMP OM_uint32 gss_canonicalize_name(
OM_uint32 *, /* minor_status */
- const gss_name_t, /* input_name */
+ gss_const_name_t, /* input_name */
const gss_OID, /* mech_type */
gss_name_t * /* output_name */
);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.security.jgss/windows/native/libsspi_bridge/sspi.cpp Thu Jun 13 11:31:36 2019 +0530
@@ -0,0 +1,1575 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+// This library is client-side only, and only supports the default credentials.
+// It speaks krb5 and SPNEGO. NTLM is excluded from SPNEGO negotiation.
+//
+// This library can be built directly with the following command:
+// cl -I %OPENJDK%\src\java.security.jgss\share\native\libj2gss\ sspi.cpp \
+// -link -dll -out:sspi_bridge.dll
+
+#define UNICODE
+#define _UNICODE
+
+#include <windows.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <Strsafe.h>
+#include <ntsecapi.h>
+#include <new>
+
+#define GSS_DLL_FILE
+#include <gssapi.h>
+
+#define SECURITY_WIN32
+#include <sspi.h>
+
+#pragma comment(lib, "secur32.lib")
+
+// Otherwise an exception will be thrown
+#define new new (std::nothrow)
+
+// A debugging macro
+#define PP(fmt, ...) \
+ if (trace) { \
+ fprintf(stderr, "[SSPI:%ld] "fmt"\n", __LINE__, ##__VA_ARGS__); \
+ fflush(stderr); \
+ }
+#define SEC_SUCCESS(status) ((*minor_status = (status)), (status) >= SEC_E_OK)
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+// When SSPI_BRIDGE_TRACE is set, debug info goes to stderr. The value is ignored.
+char* trace = getenv("SSPI_BRIDGE_TRACE");
+
+void
+dump(const char* title, PBYTE data, size_t len)
+{
+ if (trace) {
+ fprintf(stderr, "==== %s ====\n", title);
+ for (size_t i = 0; i < len; i++) {
+ if (i != 0 && i % 16 == 0) {
+ fprintf(stderr, "\n");
+ }
+ fprintf(stderr, "%02X ", *(data + i) & 0xff);
+ }
+ fprintf(stderr, "\n");
+ }
+}
+
+gss_OID_desc KRB5_OID = {9, (void*)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"};
+gss_OID_desc SPNEGO_OID = {6, (void*)"\x2b\x06\x01\x05\x05\x02"};
+gss_OID_desc USER_NAME_OID = {10, (void*)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x01"};
+gss_OID_desc KRB5_NAME_OID = {10, (void*)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01"};
+gss_OID_desc HOST_SERVICE_NAME_OID = {10, (void*)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04"};
+gss_OID_desc EXPORT_NAME_OID = {6, (void*)"\x2b\x06\x01\x05\x06\x04"};
+
+struct gss_name_struct {
+ SEC_WCHAR* name;
+};
+
+struct gss_ctx_id_struct {
+ CredHandle* phCred;
+ CtxtHandle hCtxt;
+ SecPkgContext_Sizes SecPkgContextSizes;
+ SecPkgContext_NativeNames nnames;
+ BOOLEAN established;
+ BOOLEAN isSPNEGO;
+ BOOLEAN isLocalCred;
+ OM_uint32 flags;
+};
+
+struct gss_cred_id_struct {
+ CredHandle* phCredK;
+ CredHandle* phCredS;
+ long time;
+};
+
+/* This section holds supporting functions that are not exported */
+
+static OM_uint32
+seconds_until(int inputIsUTC, TimeStamp *time)
+{
+ // time is local time
+ LARGE_INTEGER uiLocal;
+ FILETIME now;
+ GetSystemTimeAsFileTime(&now);
+ if (!inputIsUTC) {
+ FILETIME nowLocal;
+ if (FileTimeToLocalFileTime(&now, &nowLocal) == 0) {
+ return -1;
+ }
+ now = nowLocal;
+ }
+ uiLocal.HighPart = now.dwHighDateTime;
+ uiLocal.LowPart = now.dwLowDateTime;
+ if (time->QuadPart < uiLocal.QuadPart) {
+ return 0;
+ }
+ ULONGLONG diff = (time->QuadPart - uiLocal.QuadPart) / 10000000;
+ if (diff > (ULONGLONG)~(OM_uint32)0)
+ return GSS_C_INDEFINITE;
+ return (OM_uint32)diff;
+}
+
+static void
+show_time(char* label, TimeStamp* ts)
+{
+ if (trace) {
+ SYSTEMTIME stLocal;
+ FileTimeToSystemTime((FILETIME*)ts, &stLocal);
+
+ // Build a string showing the date and time.
+ PP("%s: %02d/%02d/%d %02d:%02d %uld", label,
+ stLocal.wMonth, stLocal.wDay, stLocal.wYear,
+ stLocal.wHour, stLocal.wMinute,
+ seconds_until(1, ts));
+ }
+}
+
+// isSPNEGO: true, SPNEGO. false, Kerberos.
+static gss_ctx_id_t
+new_context(BOOLEAN isSPNEGO)
+{
+ gss_ctx_id_t out = new gss_ctx_id_struct;
+ if (out == NULL) {
+ return NULL;
+ }
+ out->phCred = NULL;
+ out->hCtxt.dwLower = out->hCtxt.dwUpper = NULL;
+ out->established = FALSE;
+ out->SecPkgContextSizes.cbMaxSignature
+ = out->SecPkgContextSizes.cbBlockSize
+ = out->SecPkgContextSizes.cbSecurityTrailer
+ = 0;
+ out->nnames.sClientName = out->nnames.sServerName = NULL;
+ out->isSPNEGO = isSPNEGO;
+ out->isLocalCred = FALSE;
+ return out;
+}
+
+static gss_cred_id_t
+new_cred()
+{
+ gss_cred_id_t out = new gss_cred_id_struct;
+ out->phCredK = out->phCredS = NULL;
+ out->time = 0L;
+ return out;
+}
+
+static int
+flag_sspi_to_gss(int fin)
+{
+ int fout = 0;
+ if (fin & ISC_REQ_MUTUAL_AUTH) fout |= GSS_C_MUTUAL_FLAG;
+ if (fin & ISC_REQ_CONFIDENTIALITY) fout |= GSS_C_CONF_FLAG;
+ if (fin & ISC_REQ_DELEGATE) fout |= GSS_C_DELEG_FLAG;
+ if (fin & ISC_REQ_INTEGRITY) fout |= GSS_C_INTEG_FLAG;
+ if (fin & ISC_REQ_REPLAY_DETECT) fout |= GSS_C_REPLAY_FLAG;
+ if (fin & ISC_REQ_SEQUENCE_DETECT) fout |= GSS_C_SEQUENCE_FLAG;
+ return fout;
+}
+
+static int
+flag_gss_to_sspi(int fin)
+{
+ int fout = 0;
+ if (fin & GSS_C_MUTUAL_FLAG) fout |= ISC_RET_MUTUAL_AUTH;
+ if (fin & GSS_C_CONF_FLAG) fout |= ISC_RET_CONFIDENTIALITY;
+ if (fin & GSS_C_DELEG_FLAG) fout |= ISC_RET_DELEGATE;
+ if (fin & GSS_C_INTEG_FLAG) fout |= ISC_RET_INTEGRITY;
+ if (fin & GSS_C_REPLAY_FLAG) fout |= ISC_RET_REPLAY_DETECT;
+ if (fin & GSS_C_SEQUENCE_FLAG) fout |= ISC_RET_SEQUENCE_DETECT;
+ return fout;
+}
+
+static BOOLEAN
+is_same_oid(gss_OID o2, gss_OID o1)
+{
+ return o1 && o2 && o1->length == o2->length
+ && !memcmp(o1->elements, o2->elements, o2->length);
+}
+
+static BOOLEAN
+has_oid(gss_OID_set set, gss_OID oid)
+{
+ for (int i = 0; i < set->count; i++) {
+ if (is_same_oid(&set->elements[i], oid)) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static void
+get_oid_desc(gss_OID mech)
+{
+ if (trace) {
+ if (is_same_oid(mech, &KRB5_OID)) {
+ PP("Kerberos mech");
+ } else if (is_same_oid(mech, &SPNEGO_OID)) {
+ PP("SPNEGO mech");
+ } else if (is_same_oid(mech, &USER_NAME_OID)) {
+ PP("NT_USER_NAME name-type");
+ } else if (is_same_oid(mech, &KRB5_NAME_OID)) {
+ PP("KRB5_NAME name-type");
+ } else if (is_same_oid(mech, &HOST_SERVICE_NAME_OID)) {
+ PP("NT_HOSTBASED_SERVICE name-type");
+ } else if (is_same_oid(mech, &EXPORT_NAME_OID)) {
+ PP("NT_EXPORT_NAME name-type");
+ } else {
+ dump("UNKNOWN OID", (PBYTE)mech->elements, mech->length);
+ }
+ }
+}
+
+static void
+get_oid_set_desc(gss_OID_set mechs)
+{
+ if (trace) {
+ if (mechs == NULL) {
+ PP("OID set is NULL");
+ return;
+ }
+ PP("gss_OID_set.count is %d", (int)mechs->count);
+ for (int i = 0; i < mechs->count; i++) {
+ get_oid_desc(&mechs->elements[i]);
+ }
+ }
+}
+
+// Add realm to a name if there was none.
+// Returns a newly allocated name.
+static WCHAR*
+get_full_name(WCHAR* input)
+{
+ // input has realm, no need to add one
+ for (int i = 0;; i++) {
+ if (!input[i]) { // the end
+ break;
+ }
+ if (input[i] == L'\\') { // escaped
+ i++;
+ continue;
+ }
+ if (input[i] == L'@') {
+ return _wcsdup(input);
+ }
+ }
+
+ // Always use the default domain
+ WCHAR* realm = _wgetenv(L"USERDNSDOMAIN");
+ if (realm == NULL) {
+ realm = L"";
+ }
+
+ size_t oldlen = wcslen(input);
+ size_t newlen = oldlen + 1 + wcslen(realm) + 1;
+
+ WCHAR* fullname = new WCHAR[newlen];
+ if (!fullname) {
+ return NULL;
+ }
+ wcscpy_s(fullname, newlen, input);
+ wcscat_s(fullname, newlen, L"@");
+ wcscat_s(fullname, newlen, realm);
+
+ PP("get_full_name returns %ls", fullname);
+ return fullname;
+}
+
+/* End support section */
+
+/* This section holds GSS-API exported functions */
+
+#define CHECK_OUTPUT(x) if (!x) return GSS_S_CALL_INACCESSIBLE_WRITE;
+#define CHECK_BUFFER(b) if (!b || !b->value) return GSS_S_CALL_INACCESSIBLE_READ;
+#define CHECK_OID(o) if (!o || !o->elements) return GSS_S_CALL_INACCESSIBLE_READ;
+#define CHECK_NAME(n) if (!n || !(n->name)) return GSS_S_BAD_NAME;
+#define CHECK_CONTEXT(c) if (!c) return GSS_S_NO_CONTEXT;
+#define CHECK_CRED(c) if (!c || (!(cred_handle->phCredK) && !(cred_handle->phCredS))) \
+ return GSS_S_NO_CRED;
+
+__declspec(dllexport) OM_uint32
+gss_release_name(OM_uint32 *minor_status,
+ gss_name_t *name)
+{
+ PP(">>>> Calling gss_release_name %p...", *name);
+ if (name != NULL && *name != GSS_C_NO_NAME) {
+ if ((*name)->name != NULL) {
+ delete[] (*name)->name;
+ }
+ delete *name;
+ *name = GSS_C_NO_NAME;
+ }
+ return GSS_S_COMPLETE;
+}
+
+__declspec(dllexport) OM_uint32
+gss_import_name(OM_uint32 *minor_status,
+ const gss_buffer_t input_name_buffer,
+ const gss_OID input_name_type,
+ gss_name_t *output_name)
+{
+ PP(">>>> Calling gss_import_name...");
+ CHECK_BUFFER(input_name_buffer)
+ CHECK_OUTPUT(output_name)
+
+ int len = (int)input_name_buffer->length;
+ LPSTR input = (LPSTR)input_name_buffer->value;
+ if (input_name_type != NULL
+ && is_same_oid(input_name_type, &EXPORT_NAME_OID)) {
+ int mechLen = (int)input[3]; /* including 06 len */
+ len -= mechLen + 8; /* 4 header bytes, and an int32 length after OID */
+ if (len <= 0) {
+ return GSS_S_FAILURE;
+ }
+ // Reject if mech is not krb5
+ if (mechLen - 2!= KRB5_OID.length ||
+ memcmp(input + 6, KRB5_OID.elements, mechLen - 2)) {
+ return GSS_S_FAILURE;;
+ }
+ input = input + mechLen + 8;
+ }
+
+ SEC_WCHAR* value = new SEC_WCHAR[len + 1];
+ if (value == NULL) {
+ goto err;
+ }
+
+ len = MultiByteToWideChar(CP_UTF8, 0, input, len, value, len+1);
+ if (len == 0) {
+ goto err;
+ }
+ value[len] = 0;
+
+ PP("import_name from %ls", value);
+
+ if (len > 33 && !wcscmp(value+len-33, L"@WELLKNOWN:ORG.H5L.REFERALS-REALM")) {
+ // Remove the wellknown referrals realms
+ value[len-33] = 0;
+ len -= 33;
+ } else if (value[len-1] == L'@') {
+ // Remove the empty realm. It might come from an NT_EXPORT_NAME.
+ value[len-1] = 0;
+ len--;
+ }
+ if (len == 0) {
+ goto err;
+ }
+
+ if (input_name_type != NULL
+ && is_same_oid(input_name_type, &HOST_SERVICE_NAME_OID)) {
+ // HOST_SERVICE_NAME_OID takes the form of service@host.
+ for (int i = 0; i < len; i++) {
+ if (value[i] == L'\\') {
+ i++;
+ continue;
+ }
+ if (value[i] == L'@') {
+ value[i] = L'/';
+ break;
+ }
+ }
+ PP("Host-based service now %ls", value);
+ }
+ PP("import_name to %ls", value);
+ gss_name_struct* name = new gss_name_struct;
+ if (name == NULL) {
+ goto err;
+ }
+ name->name = value;
+ *output_name = (gss_name_t) name;
+ return GSS_S_COMPLETE;
+err:
+ if (value != NULL) {
+ delete[] value;
+ }
+ return GSS_S_FAILURE;
+}
+
+__declspec(dllexport) OM_uint32
+gss_compare_name(OM_uint32 *minor_status,
+ gss_const_name_t name1,
+ gss_const_name_t name2,
+ int *name_equal)
+{
+ PP(">>>> Calling gss_compare_name...");
+ CHECK_NAME(name1)
+ CHECK_NAME(name2)
+ CHECK_OUTPUT(name_equal)
+
+ *name_equal = 0;
+
+ SEC_WCHAR* n1 = name1->name;
+ SEC_WCHAR* n2 = name2->name;
+ PP("Comparing %ls and %ls", n1, n2);
+ int l1 = lstrlen(n1);
+ int l2 = lstrlen(n2);
+ if (l1 < l2 && n2[l1] != L'@'
+ || l2 < l1 && n1[l2] != L'@') {
+ return GSS_S_COMPLETE; // different
+ }
+ if (l1 > l2) {
+ l1 = l2; // choose the smaller one. longer=smaller @ ...
+ }
+ if (CompareStringEx(LOCALE_NAME_SYSTEM_DEFAULT, NORM_IGNORECASE,
+ n1, l1, n2, l1, NULL, NULL, 0) == CSTR_EQUAL) {
+ *name_equal = 1;
+ }
+ return GSS_S_COMPLETE;
+}
+
+__declspec(dllexport) OM_uint32
+gss_canonicalize_name(OM_uint32 *minor_status,
+ gss_const_name_t input_name,
+ const gss_OID mech_type,
+ gss_name_t *output_name)
+{
+ PP(">>>> Calling gss_canonicalize_name...");
+ CHECK_NAME(input_name)
+ CHECK_OID(mech_type)
+ CHECK_OUTPUT(output_name)
+
+ gss_name_t names2 = new gss_name_struct;
+ if (names2 == NULL) {
+ return GSS_S_FAILURE;
+ }
+ names2->name = get_full_name(input_name->name);
+ if (names2->name == NULL) {
+ delete names2;
+ return GSS_S_FAILURE;
+ }
+ *output_name = names2;
+ return GSS_S_COMPLETE;
+}
+
+__declspec(dllexport) OM_uint32
+gss_export_name(OM_uint32 *minor_status,
+ gss_const_name_t input_name,
+ gss_buffer_t exported_name)
+{
+ PP(">>>> Calling gss_export_name...");
+ CHECK_NAME(input_name)
+ CHECK_OUTPUT(exported_name)
+
+ OM_uint32 result = GSS_S_FAILURE;
+ SEC_WCHAR* name = input_name->name;
+ SEC_WCHAR* fullname = get_full_name(name);
+ if (!fullname) {
+ goto err;
+ }
+ PP("Make fullname: %ls -> %ls", name, fullname);
+ int len;
+ size_t namelen = wcslen(fullname);
+ if (namelen > 255) {
+ goto err;
+ }
+ len = (int)namelen;
+ // We only deal with not-so-long names.
+ // 04 01 00 ** 06 ** OID len:int32 name
+ int mechLen = KRB5_OID.length;
+ char* buffer = new char[10 + mechLen + len];
+ if (buffer == NULL) {
+ goto err;
+ }
+ buffer[0] = 4;
+ buffer[1] = 1;
+ buffer[2] = 0;
+ buffer[3] = 2 + mechLen;
+ buffer[4] = 6;
+ buffer[5] = mechLen;
+ memcpy_s(buffer + 6, mechLen, KRB5_OID.elements, mechLen);
+ buffer[6 + mechLen] = buffer[7 + mechLen] = buffer[8 + mechLen] = 0;
+ buffer[9 + mechLen] = (char)len;
+ len = WideCharToMultiByte(CP_UTF8, 0, fullname, len,
+ buffer+10+mechLen, len, NULL, NULL);
+ if (len == 0) {
+ delete[] buffer;
+ goto err;
+ }
+ exported_name->length = 10 + mechLen + len;
+ exported_name->value = buffer;
+ result = GSS_S_COMPLETE;
+err:
+ if (fullname != name) {
+ delete[] fullname;
+ }
+ return result;
+}
+
+__declspec(dllexport) OM_uint32
+gss_display_name(OM_uint32 *minor_status,
+ gss_const_name_t input_name,
+ gss_buffer_t output_name_buffer,
+ gss_OID *output_name_type)
+{
+ PP(">>>> Calling gss_display_name...");
+ CHECK_NAME(input_name)
+ CHECK_OUTPUT(output_name_buffer)
+
+ SEC_WCHAR* names = input_name->name;
+ int len = (int)wcslen(names);
+ char* buffer = new char[4*len+1];
+ if (buffer == NULL) {
+ return GSS_S_FAILURE;
+ }
+ len = WideCharToMultiByte(CP_UTF8, 0, names, len, buffer, 4*len, NULL, NULL);
+ if (len == 0) {
+ delete[] buffer;
+ return GSS_S_FAILURE;
+ }
+ buffer[len] = 0;
+ output_name_buffer->length = len;
+ output_name_buffer->value = buffer;
+ PP("Name found: %ls -> %d [%s]", names, len, buffer);
+ if (output_name_type != NULL) {
+ *output_name_type = &KRB5_NAME_OID;
+ }
+ return GSS_S_COMPLETE;
+}
+
+__declspec(dllexport) OM_uint32
+gss_acquire_cred(OM_uint32 *minor_status,
+ gss_const_name_t desired_name,
+ OM_uint32 time_req,
+ const gss_OID_set desired_mechs,
+ gss_cred_usage_t cred_usage,
+ gss_cred_id_t *output_cred_handle,
+ gss_OID_set *actual_mechs,
+ OM_uint32 *time_rec)
+{
+ PP(">>>> Calling gss_acquire_cred...");
+ CHECK_OUTPUT(output_cred_handle)
+
+ SECURITY_STATUS ss;
+ TimeStamp ts;
+ ts.QuadPart = 0;
+ cred_usage = 0;
+ PP("AcquireCredentialsHandle with %d %p", cred_usage, desired_mechs);
+ get_oid_set_desc(desired_mechs);
+
+ BOOLEAN reqKerberos, reqSPNEGO;
+
+ if (!desired_mechs) {
+ reqKerberos = reqSPNEGO = TRUE;
+ } else {
+ if (has_oid(desired_mechs, &KRB5_OID)) {
+ PP("reqKerberos");
+ reqKerberos = TRUE;
+ }
+ if (has_oid(desired_mechs, &SPNEGO_OID)) {
+ PP("reqSPNEGO");
+ reqSPNEGO = TRUE;
+ }
+ if (!reqSPNEGO && !reqKerberos) {
+ return GSS_S_BAD_MECH;
+ }
+ }
+
+ if (actual_mechs) {
+ *actual_mechs = GSS_C_NO_OID_SET;
+ }
+
+ gss_cred_id_t cred = new_cred();
+ if (cred == NULL) {
+ goto err;
+ }
+
+ if (reqKerberos) {
+ cred->phCredK = new CredHandle;
+ if (cred->phCredK == NULL) {
+ goto err;
+ }
+ ss = AcquireCredentialsHandle(
+ NULL,
+ L"Kerberos",
+ cred_usage == 0 ? SECPKG_CRED_BOTH :
+ (cred_usage == 1 ? SECPKG_CRED_OUTBOUND : SECPKG_CRED_INBOUND),
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ cred->phCredK,
+ &ts);
+ if (!(SEC_SUCCESS(ss))) {
+ delete cred->phCredK;
+ cred->phCredK = NULL;
+ goto err;
+ }
+ }
+
+ if (reqSPNEGO) {
+ cred->phCredS = new CredHandle;
+ if (cred->phCredS == NULL) {
+ goto err;
+ }
+ SEC_WINNT_AUTH_IDENTITY_EX auth;
+ ZeroMemory(&auth, sizeof(auth));
+ auth.Version = SEC_WINNT_AUTH_IDENTITY_VERSION;
+ auth.Length = sizeof(auth);
+ auth.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
+ auth.PackageList = (unsigned short*)L"Kerberos";
+ auth.PackageListLength = 8;
+ ss = AcquireCredentialsHandle(
+ NULL,
+ L"Negotiate",
+ cred_usage == 0 ? SECPKG_CRED_BOTH :
+ (cred_usage == 1 ? SECPKG_CRED_OUTBOUND : SECPKG_CRED_INBOUND),
+ NULL,
+ &auth,
+ NULL,
+ NULL,
+ cred->phCredS,
+ &ts);
+ if (!(SEC_SUCCESS(ss))) {
+ delete cred->phCredS;
+ cred->phCredS = NULL;
+ goto err;
+ }
+ }
+
+ if (actual_mechs) {
+ if (gss_create_empty_oid_set(minor_status, actual_mechs)) {
+ goto err;
+ }
+ if (reqKerberos) {
+ if (gss_add_oid_set_member(minor_status, &KRB5_OID, actual_mechs)) {
+ goto err;
+ }
+ }
+ if (reqSPNEGO) {
+ if (gss_add_oid_set_member(minor_status, &SPNEGO_OID, actual_mechs)) {
+ goto err;
+ }
+ }
+ }
+
+ *output_cred_handle = (gss_cred_id_t)cred;
+
+ // Note: ts here is weirdly huge, maybe because LSA retains the
+ // password and can re-acquire a TGT at anytime. It will be
+ // GSSCredential.INDEFINITE_LIFETIME.
+ show_time("cred expiration", &ts);
+ cred->time = seconds_until(1, &ts);
+ if (time_rec != NULL) {
+ *time_rec = cred->time;
+ }
+
+ // Since only default cred is supported, if there is a desired_name,
+ // we must make sure it is the same as the realname of the default cred.
+ if (desired_name != NULL) {
+ PP("Acquiring cred with a name. Check if it's me.");
+ gss_name_t realname;
+ if (gss_inquire_cred(minor_status, *output_cred_handle, &realname,
+ NULL, NULL, NULL) != GSS_S_COMPLETE) {
+ PP("Cannot get owner name of default creds");
+ goto err;
+ }
+ SEC_WCHAR* rnames = realname->name;
+ SEC_WCHAR* dnames = desired_name->name;
+ int equals = 0;
+ gss_compare_name(minor_status, realname, desired_name, &equals);
+ gss_release_name(minor_status, &realname);
+ PP("Comparing result: %d", equals);
+ if (!equals) {
+ goto err;
+ }
+ }
+
+ return GSS_S_COMPLETE;
+err:
+ if (cred) {
+ OM_uint32 dummy;
+ gss_release_cred(&dummy, &cred);
+ }
+ if (actual_mechs) {
+ OM_uint32 dummy;
+ gss_release_oid_set(&dummy, actual_mechs);
+ }
+ return GSS_S_FAILURE;
+}
+
+__declspec(dllexport) OM_uint32
+gss_release_cred(OM_uint32 *minor_status,
+ gss_cred_id_t *cred_handle)
+{
+ PP(">>>> Calling gss_release_cred...");
+ if (cred_handle && *cred_handle) {
+ if ((*cred_handle)->phCredK) {
+ FreeCredentialsHandle((*cred_handle)->phCredK);
+ delete (*cred_handle)->phCredK;
+ }
+ if ((*cred_handle)->phCredS) {
+ FreeCredentialsHandle((*cred_handle)->phCredS);
+ delete (*cred_handle)->phCredS;
+ }
+ delete *cred_handle;
+ *cred_handle = GSS_C_NO_CREDENTIAL;
+ }
+ return GSS_S_COMPLETE;
+}
+
+__declspec(dllexport) OM_uint32
+gss_inquire_cred(OM_uint32 *minor_status,
+ gss_const_cred_id_t cred_handle,
+ gss_name_t *name,
+ OM_uint32 *lifetime,
+ gss_cred_usage_t *cred_usage,
+ gss_OID_set *mechanisms)
+{
+ PP(">>>> Calling gss_inquire_cred...");
+ CHECK_CRED(cred_handle)
+
+ CredHandle* cred = cred_handle->phCredK
+ ? cred_handle->phCredK
+ : cred_handle->phCredS;
+ SECURITY_STATUS ss;
+ if (name) {
+ *name = GSS_C_NO_NAME;
+ SecPkgCredentials_Names snames;
+ ss = QueryCredentialsAttributes(cred, SECPKG_CRED_ATTR_NAMES, &snames);
+ if (!SEC_SUCCESS(ss)) {
+ return GSS_S_FAILURE;
+ }
+ SEC_WCHAR* names = new SEC_WCHAR[lstrlen(snames.sUserName) + 1];
+ if (names == NULL) {
+ return GSS_S_FAILURE;
+ }
+ StringCchCopy(names, lstrlen(snames.sUserName) + 1, snames.sUserName);
+ FreeContextBuffer(snames.sUserName);
+ PP("Allocate new name at %p", names);
+ gss_name_t name1 = new gss_name_struct;
+ if (name1 == NULL) {
+ delete[] names;
+ return GSS_S_FAILURE;
+ }
+ name1->name = names;
+ *name = (gss_name_t) name1;
+ }
+ if (lifetime) {
+ *lifetime = cred_handle->time;
+ }
+ if (cred_usage) {
+ *cred_usage = 1; // We only support INITIATE_ONLY now
+ }
+ if (mechanisms) {
+ // Useless for Java
+ }
+ // Others inquiries not supported yet
+ return GSS_S_COMPLETE;
+}
+
+__declspec(dllexport) OM_uint32
+gss_import_sec_context(OM_uint32 *minor_status,
+ const gss_buffer_t interprocess_token,
+ gss_ctx_id_t *context_handle)
+{
+ // Not transferable, return FAILURE
+ PP(">>>> Calling UNIMPLEMENTED gss_import_sec_context...");
+ *minor_status = 0;
+ return GSS_S_FAILURE;
+}
+
+__declspec(dllexport) OM_uint32
+gss_init_sec_context(OM_uint32 *minor_status,
+ gss_const_cred_id_t initiator_cred_handle,
+ gss_ctx_id_t *context_handle,
+ gss_const_name_t target_name,
+ const gss_OID mech_type,
+ OM_uint32 req_flags,
+ OM_uint32 time_req,
+ const gss_channel_bindings_t input_chan_bindings,
+ const gss_buffer_t input_token,
+ gss_OID *actual_mech_type,
+ gss_buffer_t output_token,
+ OM_uint32 *ret_flags,
+ OM_uint32 *time_rec)
+{
+ PP(">>>> Calling gss_init_sec_context...");
+ CHECK_NAME(target_name)
+ CHECK_OUTPUT(output_token)
+
+ SECURITY_STATUS ss;
+ TimeStamp lifeTime;
+ SecBufferDesc inBuffDesc;
+ SecBuffer inSecBuff;
+ SecBufferDesc outBuffDesc;
+ SecBuffer outSecBuff;
+ BOOLEAN isSPNEGO = is_same_oid(mech_type, &SPNEGO_OID);
+
+ gss_ctx_id_t pc;
+
+ output_token->length = 0;
+ output_token->value = NULL;
+
+ BOOLEAN firstTime = (*context_handle == GSS_C_NO_CONTEXT);
+ PP("First time? %d", firstTime);
+ if (firstTime) {
+ pc = new_context(isSPNEGO);
+ if (pc == NULL) {
+ return GSS_S_FAILURE;
+ }
+ *context_handle = (gss_ctx_id_t) pc;
+ } else {
+ pc = *context_handle;
+ }
+
+ if (pc == NULL) {
+ return GSS_S_NO_CONTEXT;
+ }
+
+ DWORD outFlag;
+ TCHAR outName[100];
+
+ OM_uint32 minor;
+ gss_buffer_desc tn;
+ gss_display_name(&minor, target_name, &tn, NULL);
+ int len = MultiByteToWideChar(CP_UTF8, 0, (LPCCH)tn.value, (int)tn.length,
+ outName, sizeof(outName) - 1);
+ if (len == 0) {
+ goto err;
+ }
+ outName[len] = 0;
+
+ int flag = flag_gss_to_sspi(req_flags) | ISC_REQ_ALLOCATE_MEMORY;
+
+ outBuffDesc.ulVersion = SECBUFFER_VERSION;
+ outBuffDesc.cBuffers = 1;
+ outBuffDesc.pBuffers = &outSecBuff;
+
+ outSecBuff.BufferType = SECBUFFER_TOKEN;
+
+ if (!firstTime) {
+ inBuffDesc.ulVersion = SECBUFFER_VERSION;
+ inBuffDesc.cBuffers = 1;
+ inBuffDesc.pBuffers = &inSecBuff;
+
+ inSecBuff.BufferType = SECBUFFER_TOKEN;
+ inSecBuff.cbBuffer = (ULONG)input_token->length;
+ inSecBuff.pvBuffer = input_token->value;
+ } else if (!pc->phCred) {
+ if (isSPNEGO && initiator_cred_handle
+ && initiator_cred_handle->phCredS) {
+ PP("Find SPNEGO credentials");
+ pc->phCred = initiator_cred_handle->phCredS;
+ pc->isLocalCred = FALSE;
+ } else if (!isSPNEGO && initiator_cred_handle
+ && initiator_cred_handle->phCredK) {
+ PP("Find Kerberos credentials");
+ pc->phCred = initiator_cred_handle->phCredK;
+ pc->isLocalCred = FALSE;
+ } else {
+ PP("No credentials provided, acquire myself");
+ CredHandle* newCred = new CredHandle;
+ SEC_WINNT_AUTH_IDENTITY_EX auth;
+ ZeroMemory(&auth, sizeof(auth));
+ auth.Version = SEC_WINNT_AUTH_IDENTITY_VERSION;
+ auth.Length = sizeof(auth);
+ auth.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
+ auth.PackageList = (unsigned short*)L"Kerberos";
+ auth.PackageListLength = 8;
+ ss = AcquireCredentialsHandle(
+ NULL,
+ isSPNEGO ? L"Negotiate" : L"Kerberos",
+ SECPKG_CRED_OUTBOUND,
+ NULL,
+ isSPNEGO ? &auth : NULL,
+ NULL,
+ NULL,
+ newCred,
+ &lifeTime);
+ if (!(SEC_SUCCESS(ss))) {
+ delete newCred;
+ goto err;
+ }
+ pc->phCred = newCred;
+ pc->isLocalCred = TRUE;
+ }
+ }
+ ss = InitializeSecurityContext(
+ pc->phCred,
+ firstTime ? NULL : &pc->hCtxt,
+ outName,
+ flag,
+ 0,
+ SECURITY_NATIVE_DREP,
+ firstTime ? NULL : &inBuffDesc,
+ 0,
+ &pc->hCtxt,
+ &outBuffDesc,
+ &outFlag,
+ &lifeTime);
+
+ if (!SEC_SUCCESS(ss)) {
+ // TODO: seems NativeGSSContext has not failed here.
+ PP("InitializeSecurityContext failed");
+ goto err;
+ }
+
+ pc->flags = *ret_flags = flag_sspi_to_gss(outFlag);
+
+ // Ignore the result of the next call. Might fail before context established.
+ QueryContextAttributes(
+ &pc->hCtxt, SECPKG_ATTR_SIZES, &pc->SecPkgContextSizes);
+ PP("cbMaxSignature: %ld. cbBlockSize: %ld. cbSecurityTrailer: %ld",
+ pc->SecPkgContextSizes.cbMaxSignature,
+ pc->SecPkgContextSizes.cbBlockSize,
+ pc->SecPkgContextSizes.cbSecurityTrailer);
+
+ output_token->length = outSecBuff.cbBuffer;
+ if (outSecBuff.cbBuffer) {
+ // No idea how user would free the data. Let's duplicate one.
+ output_token->value = new char[outSecBuff.cbBuffer];
+ if (!output_token->value) {
+ FreeContextBuffer(outSecBuff.pvBuffer);
+ output_token->length = 0;
+ goto err;
+ }
+ memcpy(output_token->value, outSecBuff.pvBuffer, outSecBuff.cbBuffer);
+ FreeContextBuffer(outSecBuff.pvBuffer);
+ }
+
+ if (ss == SEC_I_CONTINUE_NEEDED) {
+ return GSS_S_CONTINUE_NEEDED;
+ } else {
+ pc->established = true;
+ ss = QueryContextAttributes(&pc->hCtxt, SECPKG_ATTR_NATIVE_NAMES, &pc->nnames);
+ if (!SEC_SUCCESS(ss)) {
+ goto err;
+ }
+ PP("Names. %ls %ls", pc->nnames.sClientName, pc->nnames.sServerName);
+ *ret_flags |= GSS_C_PROT_READY_FLAG;
+ return GSS_S_COMPLETE;
+ }
+err:
+ if (firstTime) {
+ OM_uint32 dummy;
+ gss_delete_sec_context(&dummy, context_handle, GSS_C_NO_BUFFER);
+ }
+ if (output_token->value) {
+ gss_release_buffer(NULL, output_token);
+ output_token = GSS_C_NO_BUFFER;
+ }
+ return GSS_S_FAILURE;
+}
+
+__declspec(dllexport) OM_uint32
+gss_accept_sec_context(OM_uint32 *minor_status,
+ gss_ctx_id_t *context_handle,
+ gss_const_cred_id_t acceptor_cred_handle,
+ const gss_buffer_t input_token,
+ const gss_channel_bindings_t input_chan_bindings,
+ gss_name_t *src_name,
+ gss_OID *mech_type,
+ gss_buffer_t output_token,
+ OM_uint32 *ret_flags,
+ OM_uint32 *time_rec,
+ gss_cred_id_t *delegated_cred_handle)
+{
+ PP(">>>> Calling UNIMPLEMENTED gss_accept_sec_context...");
+ PP("gss_accept_sec_context is not supported in this initiator-only library");
+ return GSS_S_FAILURE;
+}
+
+__declspec(dllexport) OM_uint32
+gss_inquire_context(OM_uint32 *minor_status,
+ gss_const_ctx_id_t context_handle,
+ gss_name_t *src_name,
+ gss_name_t *targ_name,
+ OM_uint32 *lifetime_rec,
+ gss_OID *mech_type,
+ OM_uint32 *ctx_flags,
+ int *locally_initiated,
+ int *open)
+{
+ PP(">>>> Calling gss_inquire_context...");
+ CHECK_CONTEXT(context_handle)
+
+ gss_name_t n1 = NULL;
+ gss_name_t n2 = NULL;
+ if (!context_handle->established) {
+ return GSS_S_NO_CONTEXT;
+ }
+ if (src_name != NULL) {
+ n1 = new gss_name_struct;
+ if (n1 == NULL) {
+ goto err;
+ }
+ n1->name = new SEC_WCHAR[lstrlen(context_handle->nnames.sClientName) + 1];
+ if (n1->name == NULL) {
+ goto err;
+ }
+ PP("Allocate new name at %p", n1->name);
+ StringCchCopy(n1->name, lstrlen(context_handle->nnames.sClientName) + 1,
+ context_handle->nnames.sClientName);
+ *src_name = (gss_name_t) n1;
+ }
+ if (targ_name != NULL) {
+ n2 = new gss_name_struct;
+ if (n2 == NULL) {
+ goto err;
+ }
+ n2->name = new SEC_WCHAR[lstrlen(context_handle->nnames.sServerName) + 1];
+ if (n2->name == NULL) {
+ goto err;
+ }
+ PP("Allocate new name at %p", n2->name);
+ StringCchCopy(n2->name, lstrlen(context_handle->nnames.sServerName) + 1,
+ context_handle->nnames.sServerName);
+ *targ_name = (gss_name_t) n2;
+ }
+ if (lifetime_rec != NULL) {
+ SecPkgContext_Lifespan ls;
+ SECURITY_STATUS ss;
+ ss = QueryContextAttributes(
+ (PCtxtHandle)&context_handle->hCtxt,
+ SECPKG_ATTR_LIFESPAN,
+ &ls);
+ if (!SEC_SUCCESS(ss)) {
+ goto err;
+ }
+ *lifetime_rec = seconds_until(0, &ls.tsExpiry);
+ }
+ if (mech_type != NULL) {
+ *mech_type = context_handle->isSPNEGO
+ ? &SPNEGO_OID : &KRB5_OID;
+ }
+ if (ctx_flags != NULL) {
+ *ctx_flags = context_handle->flags;
+ }
+ if (locally_initiated != NULL) {
+ // We are always initiator
+ *locally_initiated = 1;
+ }
+ return GSS_S_COMPLETE;
+err:
+ if (n1 != NULL) {
+ if (n1->name != NULL) {
+ delete[] n1->name;
+ }
+ delete n1;
+ n1 = NULL;
+ }
+ if (n2 != NULL) {
+ if (n2->name != NULL) {
+ delete[] n2->name;
+ }
+ delete n2;
+ n2 = NULL;
+ }
+ return GSS_S_FAILURE;
+}
+
+__declspec(dllexport) OM_uint32
+gss_delete_sec_context(OM_uint32 *minor_status,
+ gss_ctx_id_t *context_handle,
+ gss_buffer_t output_token)
+{
+ PP(">>>> Calling gss_delete_sec_context...");
+ CHECK_CONTEXT(context_handle)
+
+ DeleteSecurityContext(&(*context_handle)->hCtxt);
+ if ((*context_handle)->isLocalCred && (*context_handle)->phCred != NULL) {
+ FreeCredentialsHandle((*context_handle)->phCred);
+ (*context_handle)->phCred = NULL;
+ }
+ if ((*context_handle)->nnames.sClientName != NULL) {
+ FreeContextBuffer((*context_handle)->nnames.sClientName);
+ (*context_handle)->nnames.sClientName = NULL;
+ }
+ if ((*context_handle)->nnames.sServerName != NULL) {
+ FreeContextBuffer((*context_handle)->nnames.sServerName);
+ (*context_handle)->nnames.sServerName = NULL;
+ }
+ delete (*context_handle);
+ *context_handle = GSS_C_NO_CONTEXT;
+ return GSS_S_COMPLETE;
+}
+
+__declspec(dllexport) OM_uint32
+gss_context_time(OM_uint32 *minor_status,
+ gss_const_ctx_id_t context_handle,
+ OM_uint32 *time_rec)
+{
+ PP(">>>> Calling IMPLEMENTED gss_context_time...");
+ CHECK_CONTEXT(context_handle)
+ CHECK_OUTPUT(time_rec)
+
+ SECURITY_STATUS ss;
+ SecPkgContext_Lifespan ls;
+ ss = QueryContextAttributes(
+ (PCtxtHandle)&context_handle->hCtxt,
+ SECPKG_ATTR_LIFESPAN,
+ &ls);
+ if (ss == SEC_E_OK) {
+ *time_rec = seconds_until(0, &ls.tsExpiry);
+ show_time("context start", &ls.tsStart);
+ show_time("context expiry", &ls.tsExpiry);
+ return *time_rec == 0 ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE;
+ } else {
+ return GSS_S_FAILURE;
+ }
+}
+
+__declspec(dllexport) OM_uint32
+gss_wrap_size_limit(OM_uint32 *minor_status,
+ gss_const_ctx_id_t context_handle,
+ int conf_req_flag,
+ gss_qop_t qop_req,
+ OM_uint32 req_output_size,
+ OM_uint32 *max_input_size)
+{
+ PP(">>>> Calling gss_wrap_size_limit...");
+ CHECK_CONTEXT(context_handle)
+ CHECK_OUTPUT(max_input_size)
+
+ *max_input_size = req_output_size
+ - context_handle->SecPkgContextSizes.cbSecurityTrailer
+ - context_handle->SecPkgContextSizes.cbBlockSize;
+ return GSS_S_COMPLETE;
+}
+
+__declspec(dllexport) OM_uint32
+gss_export_sec_context(OM_uint32 *minor_status,
+ gss_ctx_id_t *context_handle,
+ gss_buffer_t interprocess_token)
+{
+ PP(">>>> Calling UNIMPLEMENTED gss_export_sec_context...");
+ return GSS_S_FAILURE;
+}
+
+__declspec(dllexport) OM_uint32
+gss_get_mic(OM_uint32 *minor_status,
+ gss_const_ctx_id_t context_handle,
+ gss_qop_t qop_req,
+ const gss_buffer_t message_buffer,
+ gss_buffer_t msg_token)
+{
+ PP(">>>> Calling gss_get_mic...");
+ CHECK_CONTEXT(context_handle);
+ CHECK_BUFFER(message_buffer);
+ CHECK_OUTPUT(msg_token);
+
+ SECURITY_STATUS ss;
+ SecBufferDesc buffDesc;
+ SecBuffer secBuff[2];
+
+ buffDesc.cBuffers = 2;
+ buffDesc.pBuffers = secBuff;
+ buffDesc.ulVersion = SECBUFFER_VERSION;
+
+ secBuff[0].BufferType = SECBUFFER_DATA;
+ secBuff[0].cbBuffer = (ULONG)message_buffer->length;
+ secBuff[0].pvBuffer = message_buffer->value;
+
+ secBuff[1].BufferType = SECBUFFER_TOKEN;
+ secBuff[1].cbBuffer = context_handle->SecPkgContextSizes.cbMaxSignature;
+ secBuff[1].pvBuffer = msg_token->value = new char[secBuff[1].cbBuffer];
+
+ ss = MakeSignature((PCtxtHandle)&context_handle->hCtxt, 0, &buffDesc, 0);
+
+ if (!SEC_SUCCESS(ss)) {
+ msg_token->length = 0;
+ msg_token->value = NULL;
+ delete[] secBuff[1].pvBuffer;
+ return GSS_S_FAILURE;
+ }
+
+ msg_token->length = secBuff[1].cbBuffer;
+ return GSS_S_COMPLETE;
+}
+
+__declspec(dllexport) OM_uint32
+gss_verify_mic(OM_uint32 *minor_status,
+ gss_const_ctx_id_t context_handle,
+ const gss_buffer_t message_buffer,
+ const gss_buffer_t token_buffer,
+ gss_qop_t *qop_state)
+{
+ PP(">>>> Calling gss_verify_mic...");
+ CHECK_CONTEXT(context_handle);
+ CHECK_BUFFER(message_buffer);
+ CHECK_BUFFER(token_buffer);
+
+ SECURITY_STATUS ss;
+ SecBufferDesc buffDesc;
+ SecBuffer secBuff[2];
+ ULONG qop;
+
+ buffDesc.ulVersion = SECBUFFER_VERSION;
+ buffDesc.cBuffers = 2;
+ buffDesc.pBuffers = secBuff;
+
+ secBuff[0].BufferType = SECBUFFER_TOKEN;
+ secBuff[0].cbBuffer = (ULONG)token_buffer->length;
+ secBuff[0].pvBuffer = token_buffer->value;
+
+ secBuff[1].BufferType = SECBUFFER_DATA;
+ secBuff[1].cbBuffer = (ULONG)message_buffer->length;
+ secBuff[1].pvBuffer = message_buffer->value;
+
+ ss = VerifySignature((PCtxtHandle)&context_handle->hCtxt, &buffDesc, 0, &qop);
+ if (qop_state) {
+ *qop_state = qop;
+ }
+
+ if (ss == SEC_E_OK) {
+ return GSS_S_COMPLETE;
+ } else if (ss == SEC_E_OUT_OF_SEQUENCE) {
+ return GSS_S_UNSEQ_TOKEN;
+ } else {
+ return GSS_S_BAD_SIG;
+ }
+}
+
+__declspec(dllexport) OM_uint32
+gss_wrap(OM_uint32 *minor_status,
+ gss_const_ctx_id_t context_handle,
+ int conf_req_flag,
+ gss_qop_t qop_req,
+ const gss_buffer_t input_message_buffer,
+ int *conf_state,
+ gss_buffer_t output_message_buffer)
+{
+ PP(">>>> Calling gss_wrap...");
+ CHECK_CONTEXT(context_handle);
+ CHECK_BUFFER(input_message_buffer);
+ CHECK_OUTPUT(output_message_buffer);
+
+ SECURITY_STATUS ss;
+ SecBufferDesc buffDesc;
+ SecBuffer secBuff[3];
+
+ buffDesc.ulVersion = SECBUFFER_VERSION;
+ buffDesc.cBuffers = 3;
+ buffDesc.pBuffers = secBuff;
+
+ secBuff[0].BufferType = SECBUFFER_TOKEN;
+ secBuff[0].cbBuffer = context_handle->SecPkgContextSizes.cbSecurityTrailer;
+ output_message_buffer->value = secBuff[0].pvBuffer = malloc(
+ context_handle->SecPkgContextSizes.cbSecurityTrailer
+ + input_message_buffer->length
+ + context_handle->SecPkgContextSizes.cbBlockSize);;
+
+ secBuff[1].BufferType = SECBUFFER_DATA;
+ secBuff[1].cbBuffer = (ULONG)input_message_buffer->length;
+ secBuff[1].pvBuffer = malloc(secBuff[1].cbBuffer);
+ memcpy_s(secBuff[1].pvBuffer, secBuff[1].cbBuffer,
+ input_message_buffer->value, input_message_buffer->length);
+
+ secBuff[2].BufferType = SECBUFFER_PADDING;
+ secBuff[2].cbBuffer = context_handle->SecPkgContextSizes.cbBlockSize;
+ secBuff[2].pvBuffer = malloc(secBuff[2].cbBuffer);
+
+ ss = EncryptMessage((PCtxtHandle)&context_handle->hCtxt,
+ conf_req_flag ? 0 : SECQOP_WRAP_NO_ENCRYPT,
+ &buffDesc, 0);
+ if (conf_state) {
+ *conf_state = conf_req_flag;
+ }
+
+ if (!SEC_SUCCESS(ss)) {
+ free(secBuff[0].pvBuffer);
+ free(secBuff[1].pvBuffer);
+ free(secBuff[2].pvBuffer);
+ output_message_buffer->length = 0;
+ output_message_buffer->value = NULL;
+ return GSS_S_FAILURE;
+ }
+
+ memcpy_s((PBYTE)secBuff[0].pvBuffer + secBuff[0].cbBuffer,
+ input_message_buffer->length + context_handle->SecPkgContextSizes.cbBlockSize,
+ secBuff[1].pvBuffer,
+ secBuff[1].cbBuffer);
+ memcpy_s((PBYTE)secBuff[0].pvBuffer + secBuff[0].cbBuffer + secBuff[1].cbBuffer,
+ context_handle->SecPkgContextSizes.cbBlockSize,
+ secBuff[2].pvBuffer,
+ secBuff[2].cbBuffer);
+
+ output_message_buffer->length = secBuff[0].cbBuffer + secBuff[1].cbBuffer
+ + secBuff[2].cbBuffer;
+ free(secBuff[1].pvBuffer);
+ free(secBuff[2].pvBuffer);
+
+ return GSS_S_COMPLETE;
+}
+
+__declspec(dllexport) OM_uint32
+gss_unwrap(OM_uint32 *minor_status,
+ gss_const_ctx_id_t context_handle,
+ const gss_buffer_t input_message_buffer,
+ gss_buffer_t output_message_buffer,
+ int *conf_state,
+ gss_qop_t *qop_state)
+{
+ PP(">>>> Calling gss_unwrap...");
+ CHECK_CONTEXT(context_handle);
+ CHECK_BUFFER(input_message_buffer);
+ CHECK_OUTPUT(output_message_buffer);
+
+ SECURITY_STATUS ss;
+ SecBufferDesc buffDesc;
+ SecBuffer secBuff[2];
+ ULONG ulQop = 0;
+
+ buffDesc.cBuffers = 2;
+ buffDesc.pBuffers = secBuff;
+ buffDesc.ulVersion = SECBUFFER_VERSION;
+
+ secBuff[0].BufferType = SECBUFFER_STREAM;
+ secBuff[0].cbBuffer = (ULONG)input_message_buffer->length;
+ secBuff[0].pvBuffer = malloc(input_message_buffer->length);
+ memcpy_s(secBuff[0].pvBuffer, input_message_buffer->length,
+ input_message_buffer->value, input_message_buffer->length);
+
+ secBuff[1].BufferType = SECBUFFER_DATA;
+ secBuff[1].cbBuffer = 0;
+ secBuff[1].pvBuffer = NULL;
+
+ ss = DecryptMessage((PCtxtHandle)&context_handle->hCtxt, &buffDesc, 0, &ulQop);
+ if (qop_state) {
+ *qop_state = ulQop;
+ }
+ if (!SEC_SUCCESS(ss)) {
+ free(secBuff[0].pvBuffer);
+ output_message_buffer->length = 0;
+ output_message_buffer->value = NULL;
+ return GSS_S_FAILURE;
+ }
+
+ // Must allocate a new memory block so client can release it correctly
+ output_message_buffer->length = secBuff[1].cbBuffer;
+ output_message_buffer->value = new char[secBuff[1].cbBuffer];
+ memcpy_s(output_message_buffer->value, secBuff[1].cbBuffer,
+ secBuff[1].pvBuffer, secBuff[1].cbBuffer);
+ *conf_state = ulQop == SECQOP_WRAP_NO_ENCRYPT ? 0 : 1;
+
+ free(secBuff[0].pvBuffer);
+ return GSS_S_COMPLETE;
+}
+
+__declspec(dllexport) OM_uint32
+gss_indicate_mechs(OM_uint32 *minor_status,
+ gss_OID_set *mech_set)
+{
+ PP(">>>> Calling gss_indicate_mechs...");
+ OM_uint32 major = GSS_S_COMPLETE;
+
+ ULONG ccPackages;
+ PSecPkgInfo packages;
+ EnumerateSecurityPackages(&ccPackages, &packages);
+ PP("EnumerateSecurityPackages returns %ld", ccPackages);
+ for (unsigned int i = 0; i < ccPackages; i++) {
+ PP("#%d: %ls, %ls\n", i, packages[i].Name, packages[i].Comment);
+ }
+ FreeContextBuffer(packages);
+
+ // Hardcode kerberos and SPNEGO support
+ major = gss_create_empty_oid_set(minor_status, mech_set);
+ if (major != GSS_S_COMPLETE) {
+ goto done;
+ }
+
+ major = gss_add_oid_set_member(minor_status, &KRB5_OID, mech_set);
+ if (major != GSS_S_COMPLETE) {
+ goto done;
+ }
+
+ major = gss_add_oid_set_member(minor_status, &SPNEGO_OID, mech_set);
+ if (major != GSS_S_COMPLETE) {
+ goto done;
+ }
+
+done:
+
+ if (major != GSS_S_COMPLETE) {
+ gss_release_oid_set(minor_status, mech_set);
+ }
+
+ return major;
+}
+
+__declspec(dllexport) OM_uint32
+gss_inquire_names_for_mech(OM_uint32 *minor_status,
+ const gss_OID mechanism,
+ gss_OID_set *name_types)
+{
+ PP(">>>> Calling gss_inquire_names_for_mech...");
+ CHECK_OID(mechanism);
+
+ if (gss_create_empty_oid_set(minor_status, name_types)) {
+ return GSS_S_FAILURE;
+ }
+ if (gss_add_oid_set_member(minor_status, &USER_NAME_OID, name_types)) {
+ goto err;
+ }
+ if (gss_add_oid_set_member(minor_status, &HOST_SERVICE_NAME_OID, name_types)) {
+ goto err;
+ }
+ if (!is_same_oid(mechanism, &SPNEGO_OID)) {
+ if (gss_add_oid_set_member(minor_status, &EXPORT_NAME_OID, name_types)) {
+ goto err;
+ }
+ }
+ return GSS_S_COMPLETE;
+err:
+ gss_release_oid_set(minor_status, name_types);
+ return GSS_S_FAILURE;
+}
+
+__declspec(dllexport) OM_uint32
+gss_add_oid_set_member(OM_uint32 *minor_status,
+ const gss_OID member_oid,
+ gss_OID_set *oid_set)
+{
+ PP(">>>> Calling gss_add_oid_set_member...");
+ CHECK_OID(member_oid);
+ CHECK_OUTPUT(oid_set);
+
+
+ int count = (int)(*oid_set)->count;
+ for (int i = 0; i < count; i++) {
+ if (is_same_oid(&(*oid_set)->elements[i], member_oid)) {
+ // already there
+ return GSS_S_COMPLETE;
+ }
+ }
+ gss_OID existing = (*oid_set)->elements;
+ gss_OID newcopy = new gss_OID_desc[count + 1];
+ if (newcopy == NULL) {
+ return GSS_S_FAILURE;
+ }
+ if (existing) {
+ memcpy_s(newcopy, (count + 1) * sizeof(gss_OID_desc),
+ existing, count * sizeof(gss_OID_desc));
+ }
+ newcopy[count].length = member_oid->length;
+ newcopy[count].elements = new char[member_oid->length];
+ if (newcopy[count].elements == NULL) {
+ delete[] newcopy;
+ return GSS_S_FAILURE;
+ }
+ memcpy_s(newcopy[count].elements, member_oid->length,
+ member_oid->elements, member_oid->length);
+ (*oid_set)->elements = newcopy;
+ (*oid_set)->count++;
+ if (existing) {
+ delete[] existing;
+ }
+
+ return GSS_S_COMPLETE;
+}
+
+__declspec(dllexport) OM_uint32
+gss_display_status(OM_uint32 *minor_status,
+ OM_uint32 status_value,
+ int status_type,
+ const gss_OID mech_type,
+ OM_uint32 *message_context,
+ gss_buffer_t status_string)
+{
+ PP(">>>> Calling gss_display_status...");
+ TCHAR msg[256];
+ int len = FormatMessage(
+ FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ 0, status_value,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ msg, 256, 0);
+ if (len > 0) {
+ status_string->value = new char[len + 20];
+ status_string->length = sprintf_s(
+ (LPSTR)status_string->value, len + 19,
+ "(%lx) %ls", status_value, msg);
+ } else {
+ status_string->value = new char[33];
+ status_string->length = sprintf_s(
+ (LPSTR)status_string->value, 32,
+ "status is %lx", status_value);
+ }
+ if (status_string->length <= 0) {
+ gss_release_buffer(NULL, status_string);
+ status_string = GSS_C_NO_BUFFER;
+ return GSS_S_FAILURE;
+ } else {
+ return GSS_S_COMPLETE;
+ }
+}
+
+__declspec(dllexport) OM_uint32
+gss_create_empty_oid_set(OM_uint32 *minor_status,
+ gss_OID_set *oid_set)
+{
+ PP(">>>> Calling gss_create_empty_oid_set...");
+ CHECK_OUTPUT(oid_set);
+
+ if (*oid_set = new gss_OID_set_desc) {
+ memset(*oid_set, 0, sizeof(gss_OID_set_desc));
+ return GSS_S_COMPLETE;
+ }
+ return GSS_S_FAILURE;
+}
+
+__declspec(dllexport) OM_uint32
+gss_release_oid_set(OM_uint32 *minor_status,
+ gss_OID_set *set)
+{
+ PP(">>>> Calling gss_release_oid_set...");
+ if (set == NULL || *set == GSS_C_NO_OID_SET) {
+ return GSS_S_COMPLETE;
+ }
+ for (int i = 0; i < (*set)->count; i++) {
+ delete[] (*set)->elements[i].elements;
+ }
+ delete[] (*set)->elements;
+ delete *set;
+ *set = GSS_C_NO_OID_SET;
+ return GSS_S_COMPLETE;
+}
+
+__declspec(dllexport) OM_uint32
+gss_release_buffer(OM_uint32 *minor_status,
+ gss_buffer_t buffer)
+{
+ PP(">>>> Calling gss_release_buffer...");
+ if (buffer == NULL || buffer == GSS_C_NO_BUFFER) {
+ return GSS_S_COMPLETE;
+ }
+ if (buffer->value) {
+ delete[] buffer->value;
+ buffer->value = NULL;
+ }
+ buffer->length = 0;
+ return GSS_S_COMPLETE;
+}
+
+/* End implemented section */
+
+#ifdef __cplusplus
+}
+#endif
--- a/src/jdk.compiler/share/classes/com/sun/tools/doclint/Entity.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/doclint/Entity.java Thu Jun 13 11:31:36 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, 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,305 +26,2163 @@
package com.sun.tools.doclint;
import java.util.HashMap;
-import java.util.Map;
/**
- * Table of entities defined in HTML 4.01.
+ * Table of entities defined in HTML 5.2.
*
- * <p> Derived from
- * <a href="http://www.w3.org/TR/html4/sgml/entities.html">Character entity references in HTML 4</a>.
- *
- * The name of the member follows the name of the entity,
- * except when it clashes with a keyword, in which case
- * it is prefixed by '_'.
+ * <p> Derived from the
+ * <a href="https://www.w3.org/TR/html52/syntax.html#named-character-references">Named character references</a>
+ * section of the HTML 5.2 specification.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own
* risk. This code and its internal interfaces are subject to change
* or deletion without notice.</b></p>
*/
-public enum Entity {
- nbsp(160),
- iexcl(161),
- cent(162),
- pound(163),
- curren(164),
- yen(165),
- brvbar(166),
- sect(167),
- uml(168),
- copy(169),
- ordf(170),
- laquo(171),
- not(172),
- shy(173),
- reg(174),
- macr(175),
- deg(176),
- plusmn(177),
- sup2(178),
- sup3(179),
- acute(180),
- micro(181),
- para(182),
- middot(183),
- cedil(184),
- sup1(185),
- ordm(186),
- raquo(187),
- frac14(188),
- frac12(189),
- frac34(190),
- iquest(191),
- Agrave(192),
- Aacute(193),
- Acirc(194),
- Atilde(195),
- Auml(196),
- Aring(197),
- AElig(198),
- Ccedil(199),
- Egrave(200),
- Eacute(201),
- Ecirc(202),
- Euml(203),
- Igrave(204),
- Iacute(205),
- Icirc(206),
- Iuml(207),
- ETH(208),
- Ntilde(209),
- Ograve(210),
- Oacute(211),
- Ocirc(212),
- Otilde(213),
- Ouml(214),
- times(215),
- Oslash(216),
- Ugrave(217),
- Uacute(218),
- Ucirc(219),
- Uuml(220),
- Yacute(221),
- THORN(222),
- szlig(223),
- agrave(224),
- aacute(225),
- acirc(226),
- atilde(227),
- auml(228),
- aring(229),
- aelig(230),
- ccedil(231),
- egrave(232),
- eacute(233),
- ecirc(234),
- euml(235),
- igrave(236),
- iacute(237),
- icirc(238),
- iuml(239),
- eth(240),
- ntilde(241),
- ograve(242),
- oacute(243),
- ocirc(244),
- otilde(245),
- ouml(246),
- divide(247),
- oslash(248),
- ugrave(249),
- uacute(250),
- ucirc(251),
- uuml(252),
- yacute(253),
- thorn(254),
- yuml(255),
- fnof(402),
- Alpha(913),
- Beta(914),
- Gamma(915),
- Delta(916),
- Epsilon(917),
- Zeta(918),
- Eta(919),
- Theta(920),
- Iota(921),
- Kappa(922),
- Lambda(923),
- Mu(924),
- Nu(925),
- Xi(926),
- Omicron(927),
- Pi(928),
- Rho(929),
- Sigma(931),
- Tau(932),
- Upsilon(933),
- Phi(934),
- Chi(935),
- Psi(936),
- Omega(937),
- alpha(945),
- beta(946),
- gamma(947),
- delta(948),
- epsilon(949),
- zeta(950),
- eta(951),
- theta(952),
- iota(953),
- kappa(954),
- lambda(955),
- mu(956),
- nu(957),
- xi(958),
- omicron(959),
- pi(960),
- rho(961),
- sigmaf(962),
- sigma(963),
- tau(964),
- upsilon(965),
- phi(966),
- chi(967),
- psi(968),
- omega(969),
- thetasym(977),
- upsih(978),
- piv(982),
- bull(8226),
- hellip(8230),
- prime(8242),
- Prime(8243),
- oline(8254),
- frasl(8260),
- weierp(8472),
- image(8465),
- real(8476),
- trade(8482),
- alefsym(8501),
- larr(8592),
- uarr(8593),
- rarr(8594),
- darr(8595),
- harr(8596),
- crarr(8629),
- lArr(8656),
- uArr(8657),
- rArr(8658),
- dArr(8659),
- hArr(8660),
- forall(8704),
- part(8706),
- exist(8707),
- empty(8709),
- nabla(8711),
- isin(8712),
- notin(8713),
- ni(8715),
- prod(8719),
- sum(8721),
- minus(8722),
- lowast(8727),
- radic(8730),
- prop(8733),
- infin(8734),
- ang(8736),
- and(8743),
- or(8744),
- cap(8745),
- cup(8746),
- _int(8747),
- there4(8756),
- sim(8764),
- cong(8773),
- asymp(8776),
- ne(8800),
- equiv(8801),
- le(8804),
- ge(8805),
- sub(8834),
- sup(8835),
- nsub(8836),
- sube(8838),
- supe(8839),
- oplus(8853),
- otimes(8855),
- perp(8869),
- sdot(8901),
- lceil(8968),
- rceil(8969),
- lfloor(8970),
- rfloor(8971),
- lang(9001),
- rang(9002),
- loz(9674),
- spades(9824),
- clubs(9827),
- hearts(9829),
- diams(9830),
- quot(34),
- amp(38),
- lt(60),
- gt(62),
- OElig(338),
- oelig(339),
- Scaron(352),
- scaron(353),
- Yuml(376),
- circ(710),
- tilde(732),
- ensp(8194),
- emsp(8195),
- thinsp(8201),
- zwnj(8204),
- zwj(8205),
- lrm(8206),
- rlm(8207),
- ndash(8211),
- mdash(8212),
- lsquo(8216),
- rsquo(8217),
- sbquo(8218),
- ldquo(8220),
- rdquo(8221),
- bdquo(8222),
- dagger(8224),
- Dagger(8225),
- permil(8240),
- lsaquo(8249),
- rsaquo(8250),
- euro(8364);
+public class Entity {
+
+ private static final HashMap<String,String> html5Entities = new HashMap<>();
- public final int code;
-
- private Entity(int code) {
- this.code = code;
+ static {
+ html5Entities.put("Aacute", "\u00C1");
+ html5Entities.put("aacute", "\u00E1");
+ html5Entities.put("Abreve", "\u0102");
+ html5Entities.put("abreve", "\u0103");
+ html5Entities.put("ac", "\u223E");
+ html5Entities.put("acd", "\u223F");
+ html5Entities.put("acE", "\u223E\u0333");
+ html5Entities.put("Acirc", "\u00C2");
+ html5Entities.put("acirc", "\u00E2");
+ html5Entities.put("acute", "\u00B4");
+ html5Entities.put("Acy", "\u0410");
+ html5Entities.put("acy", "\u0430");
+ html5Entities.put("AElig", "\u00C6");
+ html5Entities.put("aelig", "\u00E6");
+ html5Entities.put("af", "\u2061");
+ html5Entities.put("Afr", "\uD835\uDD04");
+ html5Entities.put("afr", "\uD835\uDD1E");
+ html5Entities.put("Agrave", "\u00C0");
+ html5Entities.put("agrave", "\u00E0");
+ html5Entities.put("alefsym", "\u2135");
+ html5Entities.put("aleph", "\u2135");
+ html5Entities.put("Alpha", "\u0391");
+ html5Entities.put("alpha", "\u03B1");
+ html5Entities.put("Amacr", "\u0100");
+ html5Entities.put("amacr", "\u0101");
+ html5Entities.put("amalg", "\u2A3F");
+ html5Entities.put("amp", "\u0026");
+ html5Entities.put("AMP", "\u0026");
+ html5Entities.put("andand", "\u2A55");
+ html5Entities.put("And", "\u2A53");
+ html5Entities.put("and", "\u2227");
+ html5Entities.put("andd", "\u2A5C");
+ html5Entities.put("andslope", "\u2A58");
+ html5Entities.put("andv", "\u2A5A");
+ html5Entities.put("ang", "\u2220");
+ html5Entities.put("ange", "\u29A4");
+ html5Entities.put("angle", "\u2220");
+ html5Entities.put("angmsdaa", "\u29A8");
+ html5Entities.put("angmsdab", "\u29A9");
+ html5Entities.put("angmsdac", "\u29AA");
+ html5Entities.put("angmsdad", "\u29AB");
+ html5Entities.put("angmsdae", "\u29AC");
+ html5Entities.put("angmsdaf", "\u29AD");
+ html5Entities.put("angmsdag", "\u29AE");
+ html5Entities.put("angmsdah", "\u29AF");
+ html5Entities.put("angmsd", "\u2221");
+ html5Entities.put("angrt", "\u221F");
+ html5Entities.put("angrtvb", "\u22BE");
+ html5Entities.put("angrtvbd", "\u299D");
+ html5Entities.put("angsph", "\u2222");
+ html5Entities.put("angst", "\u00C5");
+ html5Entities.put("angzarr", "\u237C");
+ html5Entities.put("Aogon", "\u0104");
+ html5Entities.put("aogon", "\u0105");
+ html5Entities.put("Aopf", "\uD835\uDD38");
+ html5Entities.put("aopf", "\uD835\uDD52");
+ html5Entities.put("apacir", "\u2A6F");
+ html5Entities.put("ap", "\u2248");
+ html5Entities.put("apE", "\u2A70");
+ html5Entities.put("ape", "\u224A");
+ html5Entities.put("apid", "\u224B");
+ html5Entities.put("apos", "\u0027");
+ html5Entities.put("ApplyFunction", "\u2061");
+ html5Entities.put("approx", "\u2248");
+ html5Entities.put("approxeq", "\u224A");
+ html5Entities.put("Aring", "\u00C5");
+ html5Entities.put("aring", "\u00E5");
+ html5Entities.put("Ascr", "\uD835\uDC9C");
+ html5Entities.put("ascr", "\uD835\uDCB6");
+ html5Entities.put("Assign", "\u2254");
+ html5Entities.put("ast", "\u002A");
+ html5Entities.put("asymp", "\u2248");
+ html5Entities.put("asympeq", "\u224D");
+ html5Entities.put("Atilde", "\u00C3");
+ html5Entities.put("atilde", "\u00E3");
+ html5Entities.put("Auml", "\u00C4");
+ html5Entities.put("auml", "\u00E4");
+ html5Entities.put("awconint", "\u2233");
+ html5Entities.put("awint", "\u2A11");
+ html5Entities.put("backcong", "\u224C");
+ html5Entities.put("backepsilon", "\u03F6");
+ html5Entities.put("backprime", "\u2035");
+ html5Entities.put("backsim", "\u223D");
+ html5Entities.put("backsimeq", "\u22CD");
+ html5Entities.put("Backslash", "\u2216");
+ html5Entities.put("Barv", "\u2AE7");
+ html5Entities.put("barvee", "\u22BD");
+ html5Entities.put("barwed", "\u2305");
+ html5Entities.put("Barwed", "\u2306");
+ html5Entities.put("barwedge", "\u2305");
+ html5Entities.put("bbrk", "\u23B5");
+ html5Entities.put("bbrktbrk", "\u23B6");
+ html5Entities.put("bcong", "\u224C");
+ html5Entities.put("Bcy", "\u0411");
+ html5Entities.put("bcy", "\u0431");
+ html5Entities.put("bdquo", "\u201E");
+ html5Entities.put("becaus", "\u2235");
+ html5Entities.put("because", "\u2235");
+ html5Entities.put("Because", "\u2235");
+ html5Entities.put("bemptyv", "\u29B0");
+ html5Entities.put("bepsi", "\u03F6");
+ html5Entities.put("bernou", "\u212C");
+ html5Entities.put("Bernoullis", "\u212C");
+ html5Entities.put("Beta", "\u0392");
+ html5Entities.put("beta", "\u03B2");
+ html5Entities.put("beth", "\u2136");
+ html5Entities.put("between", "\u226C");
+ html5Entities.put("Bfr", "\uD835\uDD05");
+ html5Entities.put("bfr", "\uD835\uDD1F");
+ html5Entities.put("bigcap", "\u22C2");
+ html5Entities.put("bigcirc", "\u25EF");
+ html5Entities.put("bigcup", "\u22C3");
+ html5Entities.put("bigodot", "\u2A00");
+ html5Entities.put("bigoplus", "\u2A01");
+ html5Entities.put("bigotimes", "\u2A02");
+ html5Entities.put("bigsqcup", "\u2A06");
+ html5Entities.put("bigstar", "\u2605");
+ html5Entities.put("bigtriangledown", "\u25BD");
+ html5Entities.put("bigtriangleup", "\u25B3");
+ html5Entities.put("biguplus", "\u2A04");
+ html5Entities.put("bigvee", "\u22C1");
+ html5Entities.put("bigwedge", "\u22C0");
+ html5Entities.put("bkarow", "\u290D");
+ html5Entities.put("blacklozenge", "\u29EB");
+ html5Entities.put("blacksquare", "\u25AA");
+ html5Entities.put("blacktriangle", "\u25B4");
+ html5Entities.put("blacktriangledown", "\u25BE");
+ html5Entities.put("blacktriangleleft", "\u25C2");
+ html5Entities.put("blacktriangleright", "\u25B8");
+ html5Entities.put("blank", "\u2423");
+ html5Entities.put("blk12", "\u2592");
+ html5Entities.put("blk14", "\u2591");
+ html5Entities.put("blk34", "\u2593");
+ html5Entities.put("block", "\u2588");
+ html5Entities.put("bne", "\u003D\u20E5");
+ html5Entities.put("bnequiv", "\u2261\u20E5");
+ html5Entities.put("bNot", "\u2AED");
+ html5Entities.put("bnot", "\u2310");
+ html5Entities.put("Bopf", "\uD835\uDD39");
+ html5Entities.put("bopf", "\uD835\uDD53");
+ html5Entities.put("bot", "\u22A5");
+ html5Entities.put("bottom", "\u22A5");
+ html5Entities.put("bowtie", "\u22C8");
+ html5Entities.put("boxbox", "\u29C9");
+ html5Entities.put("boxdl", "\u2510");
+ html5Entities.put("boxdL", "\u2555");
+ html5Entities.put("boxDl", "\u2556");
+ html5Entities.put("boxDL", "\u2557");
+ html5Entities.put("boxdr", "\u250C");
+ html5Entities.put("boxdR", "\u2552");
+ html5Entities.put("boxDr", "\u2553");
+ html5Entities.put("boxDR", "\u2554");
+ html5Entities.put("boxh", "\u2500");
+ html5Entities.put("boxH", "\u2550");
+ html5Entities.put("boxhd", "\u252C");
+ html5Entities.put("boxHd", "\u2564");
+ html5Entities.put("boxhD", "\u2565");
+ html5Entities.put("boxHD", "\u2566");
+ html5Entities.put("boxhu", "\u2534");
+ html5Entities.put("boxHu", "\u2567");
+ html5Entities.put("boxhU", "\u2568");
+ html5Entities.put("boxHU", "\u2569");
+ html5Entities.put("boxminus", "\u229F");
+ html5Entities.put("boxplus", "\u229E");
+ html5Entities.put("boxtimes", "\u22A0");
+ html5Entities.put("boxul", "\u2518");
+ html5Entities.put("boxuL", "\u255B");
+ html5Entities.put("boxUl", "\u255C");
+ html5Entities.put("boxUL", "\u255D");
+ html5Entities.put("boxur", "\u2514");
+ html5Entities.put("boxuR", "\u2558");
+ html5Entities.put("boxUr", "\u2559");
+ html5Entities.put("boxUR", "\u255A");
+ html5Entities.put("boxv", "\u2502");
+ html5Entities.put("boxV", "\u2551");
+ html5Entities.put("boxvh", "\u253C");
+ html5Entities.put("boxvH", "\u256A");
+ html5Entities.put("boxVh", "\u256B");
+ html5Entities.put("boxVH", "\u256C");
+ html5Entities.put("boxvl", "\u2524");
+ html5Entities.put("boxvL", "\u2561");
+ html5Entities.put("boxVl", "\u2562");
+ html5Entities.put("boxVL", "\u2563");
+ html5Entities.put("boxvr", "\u251C");
+ html5Entities.put("boxvR", "\u255E");
+ html5Entities.put("boxVr", "\u255F");
+ html5Entities.put("boxVR", "\u2560");
+ html5Entities.put("bprime", "\u2035");
+ html5Entities.put("breve", "\u02D8");
+ html5Entities.put("Breve", "\u02D8");
+ html5Entities.put("brvbar", "\u00A6");
+ html5Entities.put("bscr", "\uD835\uDCB7");
+ html5Entities.put("Bscr", "\u212C");
+ html5Entities.put("bsemi", "\u204F");
+ html5Entities.put("bsim", "\u223D");
+ html5Entities.put("bsime", "\u22CD");
+ html5Entities.put("bsolb", "\u29C5");
+ html5Entities.put("bsol", "\\");
+ html5Entities.put("bsolhsub", "\u27C8");
+ html5Entities.put("bull", "\u2022");
+ html5Entities.put("bullet", "\u2022");
+ html5Entities.put("bump", "\u224E");
+ html5Entities.put("bumpE", "\u2AAE");
+ html5Entities.put("bumpe", "\u224F");
+ html5Entities.put("Bumpeq", "\u224E");
+ html5Entities.put("bumpeq", "\u224F");
+ html5Entities.put("Cacute", "\u0106");
+ html5Entities.put("cacute", "\u0107");
+ html5Entities.put("capand", "\u2A44");
+ html5Entities.put("capbrcup", "\u2A49");
+ html5Entities.put("capcap", "\u2A4B");
+ html5Entities.put("cap", "\u2229");
+ html5Entities.put("Cap", "\u22D2");
+ html5Entities.put("capcup", "\u2A47");
+ html5Entities.put("capdot", "\u2A40");
+ html5Entities.put("CapitalDifferentialD", "\u2145");
+ html5Entities.put("caps", "\u2229\uFE00");
+ html5Entities.put("caret", "\u2041");
+ html5Entities.put("caron", "\u02C7");
+ html5Entities.put("Cayleys", "\u212D");
+ html5Entities.put("ccaps", "\u2A4D");
+ html5Entities.put("Ccaron", "\u010C");
+ html5Entities.put("ccaron", "\u010D");
+ html5Entities.put("Ccedil", "\u00C7");
+ html5Entities.put("ccedil", "\u00E7");
+ html5Entities.put("Ccirc", "\u0108");
+ html5Entities.put("ccirc", "\u0109");
+ html5Entities.put("Cconint", "\u2230");
+ html5Entities.put("ccups", "\u2A4C");
+ html5Entities.put("ccupssm", "\u2A50");
+ html5Entities.put("Cdot", "\u010A");
+ html5Entities.put("cdot", "\u010B");
+ html5Entities.put("cedil", "\u00B8");
+ html5Entities.put("Cedilla", "\u00B8");
+ html5Entities.put("cemptyv", "\u29B2");
+ html5Entities.put("cent", "\u00A2");
+ html5Entities.put("centerdot", "\u00B7");
+ html5Entities.put("CenterDot", "\u00B7");
+ html5Entities.put("cfr", "\uD835\uDD20");
+ html5Entities.put("Cfr", "\u212D");
+ html5Entities.put("CHcy", "\u0427");
+ html5Entities.put("chcy", "\u0447");
+ html5Entities.put("check", "\u2713");
+ html5Entities.put("checkmark", "\u2713");
+ html5Entities.put("Chi", "\u03A7");
+ html5Entities.put("chi", "\u03C7");
+ html5Entities.put("circ", "\u02C6");
+ html5Entities.put("circeq", "\u2257");
+ html5Entities.put("circlearrowleft", "\u21BA");
+ html5Entities.put("circlearrowright", "\u21BB");
+ html5Entities.put("circledast", "\u229B");
+ html5Entities.put("circledcirc", "\u229A");
+ html5Entities.put("circleddash", "\u229D");
+ html5Entities.put("CircleDot", "\u2299");
+ html5Entities.put("circledR", "\u00AE");
+ html5Entities.put("circledS", "\u24C8");
+ html5Entities.put("CircleMinus", "\u2296");
+ html5Entities.put("CirclePlus", "\u2295");
+ html5Entities.put("CircleTimes", "\u2297");
+ html5Entities.put("cir", "\u25CB");
+ html5Entities.put("cirE", "\u29C3");
+ html5Entities.put("cire", "\u2257");
+ html5Entities.put("cirfnint", "\u2A10");
+ html5Entities.put("cirmid", "\u2AEF");
+ html5Entities.put("cirscir", "\u29C2");
+ html5Entities.put("ClockwiseContourIntegral", "\u2232");
+ html5Entities.put("CloseCurlyDoubleQuote", "\u201D");
+ html5Entities.put("CloseCurlyQuote", "\u2019");
+ html5Entities.put("clubs", "\u2663");
+ html5Entities.put("clubsuit", "\u2663");
+ html5Entities.put("colon", "\u003A");
+ html5Entities.put("Colon", "\u2237");
+ html5Entities.put("Colone", "\u2A74");
+ html5Entities.put("colone", "\u2254");
+ html5Entities.put("coloneq", "\u2254");
+ html5Entities.put("comma", "\u002C");
+ html5Entities.put("commat", "\u0040");
+ html5Entities.put("comp", "\u2201");
+ html5Entities.put("compfn", "\u2218");
+ html5Entities.put("complement", "\u2201");
+ html5Entities.put("complexes", "\u2102");
+ html5Entities.put("cong", "\u2245");
+ html5Entities.put("congdot", "\u2A6D");
+ html5Entities.put("Congruent", "\u2261");
+ html5Entities.put("conint", "\u222E");
+ html5Entities.put("Conint", "\u222F");
+ html5Entities.put("ContourIntegral", "\u222E");
+ html5Entities.put("copf", "\uD835\uDD54");
+ html5Entities.put("Copf", "\u2102");
+ html5Entities.put("coprod", "\u2210");
+ html5Entities.put("Coproduct", "\u2210");
+ html5Entities.put("copy", "\u00A9");
+ html5Entities.put("COPY", "\u00A9");
+ html5Entities.put("copysr", "\u2117");
+ html5Entities.put("CounterClockwiseContourIntegral", "\u2233");
+ html5Entities.put("crarr", "\u21B5");
+ html5Entities.put("cross", "\u2717");
+ html5Entities.put("Cross", "\u2A2F");
+ html5Entities.put("Cscr", "\uD835\uDC9E");
+ html5Entities.put("cscr", "\uD835\uDCB8");
+ html5Entities.put("csub", "\u2ACF");
+ html5Entities.put("csube", "\u2AD1");
+ html5Entities.put("csup", "\u2AD0");
+ html5Entities.put("csupe", "\u2AD2");
+ html5Entities.put("ctdot", "\u22EF");
+ html5Entities.put("cudarrl", "\u2938");
+ html5Entities.put("cudarrr", "\u2935");
+ html5Entities.put("cuepr", "\u22DE");
+ html5Entities.put("cuesc", "\u22DF");
+ html5Entities.put("cularr", "\u21B6");
+ html5Entities.put("cularrp", "\u293D");
+ html5Entities.put("cupbrcap", "\u2A48");
+ html5Entities.put("cupcap", "\u2A46");
+ html5Entities.put("CupCap", "\u224D");
+ html5Entities.put("cup", "\u222A");
+ html5Entities.put("Cup", "\u22D3");
+ html5Entities.put("cupcup", "\u2A4A");
+ html5Entities.put("cupdot", "\u228D");
+ html5Entities.put("cupor", "\u2A45");
+ html5Entities.put("cups", "\u222A\uFE00");
+ html5Entities.put("curarr", "\u21B7");
+ html5Entities.put("curarrm", "\u293C");
+ html5Entities.put("curlyeqprec", "\u22DE");
+ html5Entities.put("curlyeqsucc", "\u22DF");
+ html5Entities.put("curlyvee", "\u22CE");
+ html5Entities.put("curlywedge", "\u22CF");
+ html5Entities.put("curren", "\u00A4");
+ html5Entities.put("curvearrowleft", "\u21B6");
+ html5Entities.put("curvearrowright", "\u21B7");
+ html5Entities.put("cuvee", "\u22CE");
+ html5Entities.put("cuwed", "\u22CF");
+ html5Entities.put("cwconint", "\u2232");
+ html5Entities.put("cwint", "\u2231");
+ html5Entities.put("cylcty", "\u232D");
+ html5Entities.put("dagger", "\u2020");
+ html5Entities.put("Dagger", "\u2021");
+ html5Entities.put("daleth", "\u2138");
+ html5Entities.put("darr", "\u2193");
+ html5Entities.put("Darr", "\u21A1");
+ html5Entities.put("dArr", "\u21D3");
+ html5Entities.put("dash", "\u2010");
+ html5Entities.put("Dashv", "\u2AE4");
+ html5Entities.put("dashv", "\u22A3");
+ html5Entities.put("dbkarow", "\u290F");
+ html5Entities.put("dblac", "\u02DD");
+ html5Entities.put("Dcaron", "\u010E");
+ html5Entities.put("dcaron", "\u010F");
+ html5Entities.put("Dcy", "\u0414");
+ html5Entities.put("dcy", "\u0434");
+ html5Entities.put("ddagger", "\u2021");
+ html5Entities.put("ddarr", "\u21CA");
+ html5Entities.put("DD", "\u2145");
+ html5Entities.put("dd", "\u2146");
+ html5Entities.put("DDotrahd", "\u2911");
+ html5Entities.put("ddotseq", "\u2A77");
+ html5Entities.put("deg", "\u00B0");
+ html5Entities.put("Del", "\u2207");
+ html5Entities.put("Delta", "\u0394");
+ html5Entities.put("delta", "\u03B4");
+ html5Entities.put("demptyv", "\u29B1");
+ html5Entities.put("dfisht", "\u297F");
+ html5Entities.put("Dfr", "\uD835\uDD07");
+ html5Entities.put("dfr", "\uD835\uDD21");
+ html5Entities.put("dHar", "\u2965");
+ html5Entities.put("dharl", "\u21C3");
+ html5Entities.put("dharr", "\u21C2");
+ html5Entities.put("DiacriticalAcute", "\u00B4");
+ html5Entities.put("DiacriticalDot", "\u02D9");
+ html5Entities.put("DiacriticalDoubleAcute", "\u02DD");
+ html5Entities.put("DiacriticalGrave", "\u0060");
+ html5Entities.put("DiacriticalTilde", "\u02DC");
+ html5Entities.put("diam", "\u22C4");
+ html5Entities.put("diamond", "\u22C4");
+ html5Entities.put("Diamond", "\u22C4");
+ html5Entities.put("diamondsuit", "\u2666");
+ html5Entities.put("diams", "\u2666");
+ html5Entities.put("die", "\u00A8");
+ html5Entities.put("DifferentialD", "\u2146");
+ html5Entities.put("digamma", "\u03DD");
+ html5Entities.put("disin", "\u22F2");
+ html5Entities.put("div", "\u00F7");
+ html5Entities.put("divide", "\u00F7");
+ html5Entities.put("divideontimes", "\u22C7");
+ html5Entities.put("divonx", "\u22C7");
+ html5Entities.put("DJcy", "\u0402");
+ html5Entities.put("djcy", "\u0452");
+ html5Entities.put("dlcorn", "\u231E");
+ html5Entities.put("dlcrop", "\u230D");
+ html5Entities.put("dollar", "\u0024");
+ html5Entities.put("Dopf", "\uD835\uDD3B");
+ html5Entities.put("dopf", "\uD835\uDD55");
+ html5Entities.put("Dot", "\u00A8");
+ html5Entities.put("dot", "\u02D9");
+ html5Entities.put("DotDot", "\u20DC");
+ html5Entities.put("doteq", "\u2250");
+ html5Entities.put("doteqdot", "\u2251");
+ html5Entities.put("DotEqual", "\u2250");
+ html5Entities.put("dotminus", "\u2238");
+ html5Entities.put("dotplus", "\u2214");
+ html5Entities.put("dotsquare", "\u22A1");
+ html5Entities.put("doublebarwedge", "\u2306");
+ html5Entities.put("DoubleContourIntegral", "\u222F");
+ html5Entities.put("DoubleDot", "\u00A8");
+ html5Entities.put("DoubleDownArrow", "\u21D3");
+ html5Entities.put("DoubleLeftArrow", "\u21D0");
+ html5Entities.put("DoubleLeftRightArrow", "\u21D4");
+ html5Entities.put("DoubleLeftTee", "\u2AE4");
+ html5Entities.put("DoubleLongLeftArrow", "\u27F8");
+ html5Entities.put("DoubleLongLeftRightArrow", "\u27FA");
+ html5Entities.put("DoubleLongRightArrow", "\u27F9");
+ html5Entities.put("DoubleRightArrow", "\u21D2");
+ html5Entities.put("DoubleRightTee", "\u22A8");
+ html5Entities.put("DoubleUpArrow", "\u21D1");
+ html5Entities.put("DoubleUpDownArrow", "\u21D5");
+ html5Entities.put("DoubleVerticalBar", "\u2225");
+ html5Entities.put("DownArrowBar", "\u2913");
+ html5Entities.put("downarrow", "\u2193");
+ html5Entities.put("DownArrow", "\u2193");
+ html5Entities.put("Downarrow", "\u21D3");
+ html5Entities.put("DownArrowUpArrow", "\u21F5");
+ html5Entities.put("DownBreve", "\u0311");
+ html5Entities.put("downdownarrows", "\u21CA");
+ html5Entities.put("downharpoonleft", "\u21C3");
+ html5Entities.put("downharpoonright", "\u21C2");
+ html5Entities.put("DownLeftRightVector", "\u2950");
+ html5Entities.put("DownLeftTeeVector", "\u295E");
+ html5Entities.put("DownLeftVectorBar", "\u2956");
+ html5Entities.put("DownLeftVector", "\u21BD");
+ html5Entities.put("DownRightTeeVector", "\u295F");
+ html5Entities.put("DownRightVectorBar", "\u2957");
+ html5Entities.put("DownRightVector", "\u21C1");
+ html5Entities.put("DownTeeArrow", "\u21A7");
+ html5Entities.put("DownTee", "\u22A4");
+ html5Entities.put("drbkarow", "\u2910");
+ html5Entities.put("drcorn", "\u231F");
+ html5Entities.put("drcrop", "\u230C");
+ html5Entities.put("Dscr", "\uD835\uDC9F");
+ html5Entities.put("dscr", "\uD835\uDCB9");
+ html5Entities.put("DScy", "\u0405");
+ html5Entities.put("dscy", "\u0455");
+ html5Entities.put("dsol", "\u29F6");
+ html5Entities.put("Dstrok", "\u0110");
+ html5Entities.put("dstrok", "\u0111");
+ html5Entities.put("dtdot", "\u22F1");
+ html5Entities.put("dtri", "\u25BF");
+ html5Entities.put("dtrif", "\u25BE");
+ html5Entities.put("duarr", "\u21F5");
+ html5Entities.put("duhar", "\u296F");
+ html5Entities.put("dwangle", "\u29A6");
+ html5Entities.put("DZcy", "\u040F");
+ html5Entities.put("dzcy", "\u045F");
+ html5Entities.put("dzigrarr", "\u27FF");
+ html5Entities.put("Eacute", "\u00C9");
+ html5Entities.put("eacute", "\u00E9");
+ html5Entities.put("easter", "\u2A6E");
+ html5Entities.put("Ecaron", "\u011A");
+ html5Entities.put("ecaron", "\u011B");
+ html5Entities.put("Ecirc", "\u00CA");
+ html5Entities.put("ecirc", "\u00EA");
+ html5Entities.put("ecir", "\u2256");
+ html5Entities.put("ecolon", "\u2255");
+ html5Entities.put("Ecy", "\u042D");
+ html5Entities.put("ecy", "\u044D");
+ html5Entities.put("eDDot", "\u2A77");
+ html5Entities.put("Edot", "\u0116");
+ html5Entities.put("edot", "\u0117");
+ html5Entities.put("eDot", "\u2251");
+ html5Entities.put("ee", "\u2147");
+ html5Entities.put("efDot", "\u2252");
+ html5Entities.put("Efr", "\uD835\uDD08");
+ html5Entities.put("efr", "\uD835\uDD22");
+ html5Entities.put("eg", "\u2A9A");
+ html5Entities.put("Egrave", "\u00C8");
+ html5Entities.put("egrave", "\u00E8");
+ html5Entities.put("egs", "\u2A96");
+ html5Entities.put("egsdot", "\u2A98");
+ html5Entities.put("el", "\u2A99");
+ html5Entities.put("Element", "\u2208");
+ html5Entities.put("elinters", "\u23E7");
+ html5Entities.put("ell", "\u2113");
+ html5Entities.put("els", "\u2A95");
+ html5Entities.put("elsdot", "\u2A97");
+ html5Entities.put("Emacr", "\u0112");
+ html5Entities.put("emacr", "\u0113");
+ html5Entities.put("empty", "\u2205");
+ html5Entities.put("emptyset", "\u2205");
+ html5Entities.put("EmptySmallSquare", "\u25FB");
+ html5Entities.put("emptyv", "\u2205");
+ html5Entities.put("EmptyVerySmallSquare", "\u25AB");
+ html5Entities.put("emsp13", "\u2004");
+ html5Entities.put("emsp14", "\u2005");
+ html5Entities.put("emsp", "\u2003");
+ html5Entities.put("ENG", "\u014A");
+ html5Entities.put("eng", "\u014B");
+ html5Entities.put("ensp", "\u2002");
+ html5Entities.put("Eogon", "\u0118");
+ html5Entities.put("eogon", "\u0119");
+ html5Entities.put("Eopf", "\uD835\uDD3C");
+ html5Entities.put("eopf", "\uD835\uDD56");
+ html5Entities.put("epar", "\u22D5");
+ html5Entities.put("eparsl", "\u29E3");
+ html5Entities.put("eplus", "\u2A71");
+ html5Entities.put("epsi", "\u03B5");
+ html5Entities.put("Epsilon", "\u0395");
+ html5Entities.put("epsilon", "\u03B5");
+ html5Entities.put("epsiv", "\u03F5");
+ html5Entities.put("eqcirc", "\u2256");
+ html5Entities.put("eqcolon", "\u2255");
+ html5Entities.put("eqsim", "\u2242");
+ html5Entities.put("eqslantgtr", "\u2A96");
+ html5Entities.put("eqslantless", "\u2A95");
+ html5Entities.put("Equal", "\u2A75");
+ html5Entities.put("equals", "\u003D");
+ html5Entities.put("EqualTilde", "\u2242");
+ html5Entities.put("equest", "\u225F");
+ html5Entities.put("Equilibrium", "\u21CC");
+ html5Entities.put("equiv", "\u2261");
+ html5Entities.put("equivDD", "\u2A78");
+ html5Entities.put("eqvparsl", "\u29E5");
+ html5Entities.put("erarr", "\u2971");
+ html5Entities.put("erDot", "\u2253");
+ html5Entities.put("escr", "\u212F");
+ html5Entities.put("Escr", "\u2130");
+ html5Entities.put("esdot", "\u2250");
+ html5Entities.put("Esim", "\u2A73");
+ html5Entities.put("esim", "\u2242");
+ html5Entities.put("Eta", "\u0397");
+ html5Entities.put("eta", "\u03B7");
+ html5Entities.put("ETH", "\u00D0");
+ html5Entities.put("eth", "\u00F0");
+ html5Entities.put("Euml", "\u00CB");
+ html5Entities.put("euml", "\u00EB");
+ html5Entities.put("euro", "\u20AC");
+ html5Entities.put("excl", "\u0021");
+ html5Entities.put("exist", "\u2203");
+ html5Entities.put("Exists", "\u2203");
+ html5Entities.put("expectation", "\u2130");
+ html5Entities.put("exponentiale", "\u2147");
+ html5Entities.put("ExponentialE", "\u2147");
+ html5Entities.put("fallingdotseq", "\u2252");
+ html5Entities.put("Fcy", "\u0424");
+ html5Entities.put("fcy", "\u0444");
+ html5Entities.put("female", "\u2640");
+ html5Entities.put("ffilig", "\uFB03");
+ html5Entities.put("fflig", "\uFB00");
+ html5Entities.put("ffllig", "\uFB04");
+ html5Entities.put("Ffr", "\uD835\uDD09");
+ html5Entities.put("ffr", "\uD835\uDD23");
+ html5Entities.put("filig", "\uFB01");
+ html5Entities.put("FilledSmallSquare", "\u25FC");
+ html5Entities.put("FilledVerySmallSquare", "\u25AA");
+ html5Entities.put("fjlig", "\u0066\u006A");
+ html5Entities.put("flat", "\u266D");
+ html5Entities.put("fllig", "\uFB02");
+ html5Entities.put("fltns", "\u25B1");
+ html5Entities.put("fnof", "\u0192");
+ html5Entities.put("Fopf", "\uD835\uDD3D");
+ html5Entities.put("fopf", "\uD835\uDD57");
+ html5Entities.put("forall", "\u2200");
+ html5Entities.put("ForAll", "\u2200");
+ html5Entities.put("fork", "\u22D4");
+ html5Entities.put("forkv", "\u2AD9");
+ html5Entities.put("Fouriertrf", "\u2131");
+ html5Entities.put("fpartint", "\u2A0D");
+ html5Entities.put("frac12", "\u00BD");
+ html5Entities.put("frac13", "\u2153");
+ html5Entities.put("frac14", "\u00BC");
+ html5Entities.put("frac15", "\u2155");
+ html5Entities.put("frac16", "\u2159");
+ html5Entities.put("frac18", "\u215B");
+ html5Entities.put("frac23", "\u2154");
+ html5Entities.put("frac25", "\u2156");
+ html5Entities.put("frac34", "\u00BE");
+ html5Entities.put("frac35", "\u2157");
+ html5Entities.put("frac38", "\u215C");
+ html5Entities.put("frac45", "\u2158");
+ html5Entities.put("frac56", "\u215A");
+ html5Entities.put("frac58", "\u215D");
+ html5Entities.put("frac78", "\u215E");
+ html5Entities.put("frasl", "\u2044");
+ html5Entities.put("frown", "\u2322");
+ html5Entities.put("fscr", "\uD835\uDCBB");
+ html5Entities.put("Fscr", "\u2131");
+ html5Entities.put("gacute", "\u01F5");
+ html5Entities.put("Gamma", "\u0393");
+ html5Entities.put("gamma", "\u03B3");
+ html5Entities.put("Gammad", "\u03DC");
+ html5Entities.put("gammad", "\u03DD");
+ html5Entities.put("gap", "\u2A86");
+ html5Entities.put("Gbreve", "\u011E");
+ html5Entities.put("gbreve", "\u011F");
+ html5Entities.put("Gcedil", "\u0122");
+ html5Entities.put("Gcirc", "\u011C");
+ html5Entities.put("gcirc", "\u011D");
+ html5Entities.put("Gcy", "\u0413");
+ html5Entities.put("gcy", "\u0433");
+ html5Entities.put("Gdot", "\u0120");
+ html5Entities.put("gdot", "\u0121");
+ html5Entities.put("ge", "\u2265");
+ html5Entities.put("gE", "\u2267");
+ html5Entities.put("gEl", "\u2A8C");
+ html5Entities.put("gel", "\u22DB");
+ html5Entities.put("geq", "\u2265");
+ html5Entities.put("geqq", "\u2267");
+ html5Entities.put("geqslant", "\u2A7E");
+ html5Entities.put("gescc", "\u2AA9");
+ html5Entities.put("ges", "\u2A7E");
+ html5Entities.put("gesdot", "\u2A80");
+ html5Entities.put("gesdoto", "\u2A82");
+ html5Entities.put("gesdotol", "\u2A84");
+ html5Entities.put("gesl", "\u22DB\uFE00");
+ html5Entities.put("gesles", "\u2A94");
+ html5Entities.put("Gfr", "\uD835\uDD0A");
+ html5Entities.put("gfr", "\uD835\uDD24");
+ html5Entities.put("gg", "\u226B");
+ html5Entities.put("Gg", "\u22D9");
+ html5Entities.put("ggg", "\u22D9");
+ html5Entities.put("gimel", "\u2137");
+ html5Entities.put("GJcy", "\u0403");
+ html5Entities.put("gjcy", "\u0453");
+ html5Entities.put("gla", "\u2AA5");
+ html5Entities.put("gl", "\u2277");
+ html5Entities.put("glE", "\u2A92");
+ html5Entities.put("glj", "\u2AA4");
+ html5Entities.put("gnap", "\u2A8A");
+ html5Entities.put("gnapprox", "\u2A8A");
+ html5Entities.put("gne", "\u2A88");
+ html5Entities.put("gnE", "\u2269");
+ html5Entities.put("gneq", "\u2A88");
+ html5Entities.put("gneqq", "\u2269");
+ html5Entities.put("gnsim", "\u22E7");
+ html5Entities.put("Gopf", "\uD835\uDD3E");
+ html5Entities.put("gopf", "\uD835\uDD58");
+ html5Entities.put("grave", "\u0060");
+ html5Entities.put("GreaterEqual", "\u2265");
+ html5Entities.put("GreaterEqualLess", "\u22DB");
+ html5Entities.put("GreaterFullEqual", "\u2267");
+ html5Entities.put("GreaterGreater", "\u2AA2");
+ html5Entities.put("GreaterLess", "\u2277");
+ html5Entities.put("GreaterSlantEqual", "\u2A7E");
+ html5Entities.put("GreaterTilde", "\u2273");
+ html5Entities.put("Gscr", "\uD835\uDCA2");
+ html5Entities.put("gscr", "\u210A");
+ html5Entities.put("gsim", "\u2273");
+ html5Entities.put("gsime", "\u2A8E");
+ html5Entities.put("gsiml", "\u2A90");
+ html5Entities.put("gtcc", "\u2AA7");
+ html5Entities.put("gtcir", "\u2A7A");
+ html5Entities.put("gt", "\u003E");
+ html5Entities.put("GT", "\u003E");
+ html5Entities.put("Gt", "\u226B");
+ html5Entities.put("gtdot", "\u22D7");
+ html5Entities.put("gtlPar", "\u2995");
+ html5Entities.put("gtquest", "\u2A7C");
+ html5Entities.put("gtrapprox", "\u2A86");
+ html5Entities.put("gtrarr", "\u2978");
+ html5Entities.put("gtrdot", "\u22D7");
+ html5Entities.put("gtreqless", "\u22DB");
+ html5Entities.put("gtreqqless", "\u2A8C");
+ html5Entities.put("gtrless", "\u2277");
+ html5Entities.put("gtrsim", "\u2273");
+ html5Entities.put("gvertneqq", "\u2269\uFE00");
+ html5Entities.put("gvnE", "\u2269\uFE00");
+ html5Entities.put("Hacek", "\u02C7");
+ html5Entities.put("hairsp", "\u200A");
+ html5Entities.put("half", "\u00BD");
+ html5Entities.put("hamilt", "\u210B");
+ html5Entities.put("HARDcy", "\u042A");
+ html5Entities.put("hardcy", "\u044A");
+ html5Entities.put("harrcir", "\u2948");
+ html5Entities.put("harr", "\u2194");
+ html5Entities.put("hArr", "\u21D4");
+ html5Entities.put("harrw", "\u21AD");
+ html5Entities.put("Hat", "\u005E");
+ html5Entities.put("hbar", "\u210F");
+ html5Entities.put("Hcirc", "\u0124");
+ html5Entities.put("hcirc", "\u0125");
+ html5Entities.put("hearts", "\u2665");
+ html5Entities.put("heartsuit", "\u2665");
+ html5Entities.put("hellip", "\u2026");
+ html5Entities.put("hercon", "\u22B9");
+ html5Entities.put("hfr", "\uD835\uDD25");
+ html5Entities.put("Hfr", "\u210C");
+ html5Entities.put("HilbertSpace", "\u210B");
+ html5Entities.put("hksearow", "\u2925");
+ html5Entities.put("hkswarow", "\u2926");
+ html5Entities.put("hoarr", "\u21FF");
+ html5Entities.put("homtht", "\u223B");
+ html5Entities.put("hookleftarrow", "\u21A9");
+ html5Entities.put("hookrightarrow", "\u21AA");
+ html5Entities.put("hopf", "\uD835\uDD59");
+ html5Entities.put("Hopf", "\u210D");
+ html5Entities.put("horbar", "\u2015");
+ html5Entities.put("HorizontalLine", "\u2500");
+ html5Entities.put("hscr", "\uD835\uDCBD");
+ html5Entities.put("Hscr", "\u210B");
+ html5Entities.put("hslash", "\u210F");
+ html5Entities.put("Hstrok", "\u0126");
+ html5Entities.put("hstrok", "\u0127");
+ html5Entities.put("HumpDownHump", "\u224E");
+ html5Entities.put("HumpEqual", "\u224F");
+ html5Entities.put("hybull", "\u2043");
+ html5Entities.put("hyphen", "\u2010");
+ html5Entities.put("Iacute", "\u00CD");
+ html5Entities.put("iacute", "\u00ED");
+ html5Entities.put("ic", "\u2063");
+ html5Entities.put("Icirc", "\u00CE");
+ html5Entities.put("icirc", "\u00EE");
+ html5Entities.put("Icy", "\u0418");
+ html5Entities.put("icy", "\u0438");
+ html5Entities.put("Idot", "\u0130");
+ html5Entities.put("IEcy", "\u0415");
+ html5Entities.put("iecy", "\u0435");
+ html5Entities.put("iexcl", "\u00A1");
+ html5Entities.put("iff", "\u21D4");
+ html5Entities.put("ifr", "\uD835\uDD26");
+ html5Entities.put("Ifr", "\u2111");
+ html5Entities.put("Igrave", "\u00CC");
+ html5Entities.put("igrave", "\u00EC");
+ html5Entities.put("ii", "\u2148");
+ html5Entities.put("iiiint", "\u2A0C");
+ html5Entities.put("iiint", "\u222D");
+ html5Entities.put("iinfin", "\u29DC");
+ html5Entities.put("iiota", "\u2129");
+ html5Entities.put("IJlig", "\u0132");
+ html5Entities.put("ijlig", "\u0133");
+ html5Entities.put("Imacr", "\u012A");
+ html5Entities.put("imacr", "\u012B");
+ html5Entities.put("image", "\u2111");
+ html5Entities.put("ImaginaryI", "\u2148");
+ html5Entities.put("imagline", "\u2110");
+ html5Entities.put("imagpart", "\u2111");
+ html5Entities.put("imath", "\u0131");
+ html5Entities.put("Im", "\u2111");
+ html5Entities.put("imof", "\u22B7");
+ html5Entities.put("imped", "\u01B5");
+ html5Entities.put("Implies", "\u21D2");
+ html5Entities.put("incare", "\u2105");
+ html5Entities.put("in", "\u2208");
+ html5Entities.put("infin", "\u221E");
+ html5Entities.put("infintie", "\u29DD");
+ html5Entities.put("inodot", "\u0131");
+ html5Entities.put("intcal", "\u22BA");
+ html5Entities.put("int", "\u222B");
+ html5Entities.put("Int", "\u222C");
+ html5Entities.put("integers", "\u2124");
+ html5Entities.put("Integral", "\u222B");
+ html5Entities.put("intercal", "\u22BA");
+ html5Entities.put("Intersection", "\u22C2");
+ html5Entities.put("intlarhk", "\u2A17");
+ html5Entities.put("intprod", "\u2A3C");
+ html5Entities.put("InvisibleComma", "\u2063");
+ html5Entities.put("InvisibleTimes", "\u2062");
+ html5Entities.put("IOcy", "\u0401");
+ html5Entities.put("iocy", "\u0451");
+ html5Entities.put("Iogon", "\u012E");
+ html5Entities.put("iogon", "\u012F");
+ html5Entities.put("Iopf", "\uD835\uDD40");
+ html5Entities.put("iopf", "\uD835\uDD5A");
+ html5Entities.put("Iota", "\u0399");
+ html5Entities.put("iota", "\u03B9");
+ html5Entities.put("iprod", "\u2A3C");
+ html5Entities.put("iquest", "\u00BF");
+ html5Entities.put("iscr", "\uD835\uDCBE");
+ html5Entities.put("Iscr", "\u2110");
+ html5Entities.put("isin", "\u2208");
+ html5Entities.put("isindot", "\u22F5");
+ html5Entities.put("isinE", "\u22F9");
+ html5Entities.put("isins", "\u22F4");
+ html5Entities.put("isinsv", "\u22F3");
+ html5Entities.put("isinv", "\u2208");
+ html5Entities.put("it", "\u2062");
+ html5Entities.put("Itilde", "\u0128");
+ html5Entities.put("itilde", "\u0129");
+ html5Entities.put("Iukcy", "\u0406");
+ html5Entities.put("iukcy", "\u0456");
+ html5Entities.put("Iuml", "\u00CF");
+ html5Entities.put("iuml", "\u00EF");
+ html5Entities.put("Jcirc", "\u0134");
+ html5Entities.put("jcirc", "\u0135");
+ html5Entities.put("Jcy", "\u0419");
+ html5Entities.put("jcy", "\u0439");
+ html5Entities.put("Jfr", "\uD835\uDD0D");
+ html5Entities.put("jfr", "\uD835\uDD27");
+ html5Entities.put("jmath", "\u0237");
+ html5Entities.put("Jopf", "\uD835\uDD41");
+ html5Entities.put("jopf", "\uD835\uDD5B");
+ html5Entities.put("Jscr", "\uD835\uDCA5");
+ html5Entities.put("jscr", "\uD835\uDCBF");
+ html5Entities.put("Jsercy", "\u0408");
+ html5Entities.put("jsercy", "\u0458");
+ html5Entities.put("Jukcy", "\u0404");
+ html5Entities.put("jukcy", "\u0454");
+ html5Entities.put("Kappa", "\u039A");
+ html5Entities.put("kappa", "\u03BA");
+ html5Entities.put("kappav", "\u03F0");
+ html5Entities.put("Kcedil", "\u0136");
+ html5Entities.put("kcedil", "\u0137");
+ html5Entities.put("Kcy", "\u041A");
+ html5Entities.put("kcy", "\u043A");
+ html5Entities.put("Kfr", "\uD835\uDD0E");
+ html5Entities.put("kfr", "\uD835\uDD28");
+ html5Entities.put("kgreen", "\u0138");
+ html5Entities.put("KHcy", "\u0425");
+ html5Entities.put("khcy", "\u0445");
+ html5Entities.put("KJcy", "\u040C");
+ html5Entities.put("kjcy", "\u045C");
+ html5Entities.put("Kopf", "\uD835\uDD42");
+ html5Entities.put("kopf", "\uD835\uDD5C");
+ html5Entities.put("Kscr", "\uD835\uDCA6");
+ html5Entities.put("kscr", "\uD835\uDCC0");
+ html5Entities.put("lAarr", "\u21DA");
+ html5Entities.put("Lacute", "\u0139");
+ html5Entities.put("lacute", "\u013A");
+ html5Entities.put("laemptyv", "\u29B4");
+ html5Entities.put("lagran", "\u2112");
+ html5Entities.put("Lambda", "\u039B");
+ html5Entities.put("lambda", "\u03BB");
+ html5Entities.put("lang", "\u27E8");
+ html5Entities.put("Lang", "\u27EA");
+ html5Entities.put("langd", "\u2991");
+ html5Entities.put("langle", "\u27E8");
+ html5Entities.put("lap", "\u2A85");
+ html5Entities.put("Laplacetrf", "\u2112");
+ html5Entities.put("laquo", "\u00AB");
+ html5Entities.put("larrb", "\u21E4");
+ html5Entities.put("larrbfs", "\u291F");
+ html5Entities.put("larr", "\u2190");
+ html5Entities.put("Larr", "\u219E");
+ html5Entities.put("lArr", "\u21D0");
+ html5Entities.put("larrfs", "\u291D");
+ html5Entities.put("larrhk", "\u21A9");
+ html5Entities.put("larrlp", "\u21AB");
+ html5Entities.put("larrpl", "\u2939");
+ html5Entities.put("larrsim", "\u2973");
+ html5Entities.put("larrtl", "\u21A2");
+ html5Entities.put("latail", "\u2919");
+ html5Entities.put("lAtail", "\u291B");
+ html5Entities.put("lat", "\u2AAB");
+ html5Entities.put("late", "\u2AAD");
+ html5Entities.put("lates", "\u2AAD\uFE00");
+ html5Entities.put("lbarr", "\u290C");
+ html5Entities.put("lBarr", "\u290E");
+ html5Entities.put("lbbrk", "\u2772");
+ html5Entities.put("lbrace", "\u007B");
+ html5Entities.put("lbrack", "\u005B");
+ html5Entities.put("lbrke", "\u298B");
+ html5Entities.put("lbrksld", "\u298F");
+ html5Entities.put("lbrkslu", "\u298D");
+ html5Entities.put("Lcaron", "\u013D");
+ html5Entities.put("lcaron", "\u013E");
+ html5Entities.put("Lcedil", "\u013B");
+ html5Entities.put("lcedil", "\u013C");
+ html5Entities.put("lceil", "\u2308");
+ html5Entities.put("lcub", "\u007B");
+ html5Entities.put("Lcy", "\u041B");
+ html5Entities.put("lcy", "\u043B");
+ html5Entities.put("ldca", "\u2936");
+ html5Entities.put("ldquo", "\u201C");
+ html5Entities.put("ldquor", "\u201E");
+ html5Entities.put("ldrdhar", "\u2967");
+ html5Entities.put("ldrushar", "\u294B");
+ html5Entities.put("ldsh", "\u21B2");
+ html5Entities.put("le", "\u2264");
+ html5Entities.put("lE", "\u2266");
+ html5Entities.put("LeftAngleBracket", "\u27E8");
+ html5Entities.put("LeftArrowBar", "\u21E4");
+ html5Entities.put("leftarrow", "\u2190");
+ html5Entities.put("LeftArrow", "\u2190");
+ html5Entities.put("Leftarrow", "\u21D0");
+ html5Entities.put("LeftArrowRightArrow", "\u21C6");
+ html5Entities.put("leftarrowtail", "\u21A2");
+ html5Entities.put("LeftCeiling", "\u2308");
+ html5Entities.put("LeftDoubleBracket", "\u27E6");
+ html5Entities.put("LeftDownTeeVector", "\u2961");
+ html5Entities.put("LeftDownVectorBar", "\u2959");
+ html5Entities.put("LeftDownVector", "\u21C3");
+ html5Entities.put("LeftFloor", "\u230A");
+ html5Entities.put("leftharpoondown", "\u21BD");
+ html5Entities.put("leftharpoonup", "\u21BC");
+ html5Entities.put("leftleftarrows", "\u21C7");
+ html5Entities.put("leftrightarrow", "\u2194");
+ html5Entities.put("LeftRightArrow", "\u2194");
+ html5Entities.put("Leftrightarrow", "\u21D4");
+ html5Entities.put("leftrightarrows", "\u21C6");
+ html5Entities.put("leftrightharpoons", "\u21CB");
+ html5Entities.put("leftrightsquigarrow", "\u21AD");
+ html5Entities.put("LeftRightVector", "\u294E");
+ html5Entities.put("LeftTeeArrow", "\u21A4");
+ html5Entities.put("LeftTee", "\u22A3");
+ html5Entities.put("LeftTeeVector", "\u295A");
+ html5Entities.put("leftthreetimes", "\u22CB");
+ html5Entities.put("LeftTriangleBar", "\u29CF");
+ html5Entities.put("LeftTriangle", "\u22B2");
+ html5Entities.put("LeftTriangleEqual", "\u22B4");
+ html5Entities.put("LeftUpDownVector", "\u2951");
+ html5Entities.put("LeftUpTeeVector", "\u2960");
+ html5Entities.put("LeftUpVectorBar", "\u2958");
+ html5Entities.put("LeftUpVector", "\u21BF");
+ html5Entities.put("LeftVectorBar", "\u2952");
+ html5Entities.put("LeftVector", "\u21BC");
+ html5Entities.put("lEg", "\u2A8B");
+ html5Entities.put("leg", "\u22DA");
+ html5Entities.put("leq", "\u2264");
+ html5Entities.put("leqq", "\u2266");
+ html5Entities.put("leqslant", "\u2A7D");
+ html5Entities.put("lescc", "\u2AA8");
+ html5Entities.put("les", "\u2A7D");
+ html5Entities.put("lesdot", "\u2A7F");
+ html5Entities.put("lesdoto", "\u2A81");
+ html5Entities.put("lesdotor", "\u2A83");
+ html5Entities.put("lesg", "\u22DA\uFE00");
+ html5Entities.put("lesges", "\u2A93");
+ html5Entities.put("lessapprox", "\u2A85");
+ html5Entities.put("lessdot", "\u22D6");
+ html5Entities.put("lesseqgtr", "\u22DA");
+ html5Entities.put("lesseqqgtr", "\u2A8B");
+ html5Entities.put("LessEqualGreater", "\u22DA");
+ html5Entities.put("LessFullEqual", "\u2266");
+ html5Entities.put("LessGreater", "\u2276");
+ html5Entities.put("lessgtr", "\u2276");
+ html5Entities.put("LessLess", "\u2AA1");
+ html5Entities.put("lesssim", "\u2272");
+ html5Entities.put("LessSlantEqual", "\u2A7D");
+ html5Entities.put("LessTilde", "\u2272");
+ html5Entities.put("lfisht", "\u297C");
+ html5Entities.put("lfloor", "\u230A");
+ html5Entities.put("Lfr", "\uD835\uDD0F");
+ html5Entities.put("lfr", "\uD835\uDD29");
+ html5Entities.put("lg", "\u2276");
+ html5Entities.put("lgE", "\u2A91");
+ html5Entities.put("lHar", "\u2962");
+ html5Entities.put("lhard", "\u21BD");
+ html5Entities.put("lharu", "\u21BC");
+ html5Entities.put("lharul", "\u296A");
+ html5Entities.put("lhblk", "\u2584");
+ html5Entities.put("LJcy", "\u0409");
+ html5Entities.put("ljcy", "\u0459");
+ html5Entities.put("llarr", "\u21C7");
+ html5Entities.put("ll", "\u226A");
+ html5Entities.put("Ll", "\u22D8");
+ html5Entities.put("llcorner", "\u231E");
+ html5Entities.put("Lleftarrow", "\u21DA");
+ html5Entities.put("llhard", "\u296B");
+ html5Entities.put("lltri", "\u25FA");
+ html5Entities.put("Lmidot", "\u013F");
+ html5Entities.put("lmidot", "\u0140");
+ html5Entities.put("lmoustache", "\u23B0");
+ html5Entities.put("lmoust", "\u23B0");
+ html5Entities.put("lnap", "\u2A89");
+ html5Entities.put("lnapprox", "\u2A89");
+ html5Entities.put("lne", "\u2A87");
+ html5Entities.put("lnE", "\u2268");
+ html5Entities.put("lneq", "\u2A87");
+ html5Entities.put("lneqq", "\u2268");
+ html5Entities.put("lnsim", "\u22E6");
+ html5Entities.put("loang", "\u27EC");
+ html5Entities.put("loarr", "\u21FD");
+ html5Entities.put("lobrk", "\u27E6");
+ html5Entities.put("longleftarrow", "\u27F5");
+ html5Entities.put("LongLeftArrow", "\u27F5");
+ html5Entities.put("Longleftarrow", "\u27F8");
+ html5Entities.put("longleftrightarrow", "\u27F7");
+ html5Entities.put("LongLeftRightArrow", "\u27F7");
+ html5Entities.put("Longleftrightarrow", "\u27FA");
+ html5Entities.put("longmapsto", "\u27FC");
+ html5Entities.put("longrightarrow", "\u27F6");
+ html5Entities.put("LongRightArrow", "\u27F6");
+ html5Entities.put("Longrightarrow", "\u27F9");
+ html5Entities.put("looparrowleft", "\u21AB");
+ html5Entities.put("looparrowright", "\u21AC");
+ html5Entities.put("lopar", "\u2985");
+ html5Entities.put("Lopf", "\uD835\uDD43");
+ html5Entities.put("lopf", "\uD835\uDD5D");
+ html5Entities.put("loplus", "\u2A2D");
+ html5Entities.put("lotimes", "\u2A34");
+ html5Entities.put("lowast", "\u2217");
+ html5Entities.put("lowbar", "\u005F");
+ html5Entities.put("LowerLeftArrow", "\u2199");
+ html5Entities.put("LowerRightArrow", "\u2198");
+ html5Entities.put("loz", "\u25CA");
+ html5Entities.put("lozenge", "\u25CA");
+ html5Entities.put("lozf", "\u29EB");
+ html5Entities.put("lpar", "\u0028");
+ html5Entities.put("lparlt", "\u2993");
+ html5Entities.put("lrarr", "\u21C6");
+ html5Entities.put("lrcorner", "\u231F");
+ html5Entities.put("lrhar", "\u21CB");
+ html5Entities.put("lrhard", "\u296D");
+ html5Entities.put("lrm", "\u200E");
+ html5Entities.put("lrtri", "\u22BF");
+ html5Entities.put("lsaquo", "\u2039");
+ html5Entities.put("lscr", "\uD835\uDCC1");
+ html5Entities.put("Lscr", "\u2112");
+ html5Entities.put("lsh", "\u21B0");
+ html5Entities.put("Lsh", "\u21B0");
+ html5Entities.put("lsim", "\u2272");
+ html5Entities.put("lsime", "\u2A8D");
+ html5Entities.put("lsimg", "\u2A8F");
+ html5Entities.put("lsqb", "\u005B");
+ html5Entities.put("lsquo", "\u2018");
+ html5Entities.put("lsquor", "\u201A");
+ html5Entities.put("Lstrok", "\u0141");
+ html5Entities.put("lstrok", "\u0142");
+ html5Entities.put("ltcc", "\u2AA6");
+ html5Entities.put("ltcir", "\u2A79");
+ html5Entities.put("lt", "\u003C");
+ html5Entities.put("LT", "\u003C");
+ html5Entities.put("Lt", "\u226A");
+ html5Entities.put("ltdot", "\u22D6");
+ html5Entities.put("lthree", "\u22CB");
+ html5Entities.put("ltimes", "\u22C9");
+ html5Entities.put("ltlarr", "\u2976");
+ html5Entities.put("ltquest", "\u2A7B");
+ html5Entities.put("ltri", "\u25C3");
+ html5Entities.put("ltrie", "\u22B4");
+ html5Entities.put("ltrif", "\u25C2");
+ html5Entities.put("ltrPar", "\u2996");
+ html5Entities.put("lurdshar", "\u294A");
+ html5Entities.put("luruhar", "\u2966");
+ html5Entities.put("lvertneqq", "\u2268\uFE00");
+ html5Entities.put("lvnE", "\u2268\uFE00");
+ html5Entities.put("macr", "\u00AF");
+ html5Entities.put("male", "\u2642");
+ html5Entities.put("malt", "\u2720");
+ html5Entities.put("maltese", "\u2720");
+ html5Entities.put("Map", "\u2905");
+ html5Entities.put("map", "\u21A6");
+ html5Entities.put("mapsto", "\u21A6");
+ html5Entities.put("mapstodown", "\u21A7");
+ html5Entities.put("mapstoleft", "\u21A4");
+ html5Entities.put("mapstoup", "\u21A5");
+ html5Entities.put("marker", "\u25AE");
+ html5Entities.put("mcomma", "\u2A29");
+ html5Entities.put("Mcy", "\u041C");
+ html5Entities.put("mcy", "\u043C");
+ html5Entities.put("mdash", "\u2014");
+ html5Entities.put("mDDot", "\u223A");
+ html5Entities.put("measuredangle", "\u2221");
+ html5Entities.put("MediumSpace", "\u205F");
+ html5Entities.put("Mellintrf", "\u2133");
+ html5Entities.put("Mfr", "\uD835\uDD10");
+ html5Entities.put("mfr", "\uD835\uDD2A");
+ html5Entities.put("mho", "\u2127");
+ html5Entities.put("micro", "\u00B5");
+ html5Entities.put("midast", "\u002A");
+ html5Entities.put("midcir", "\u2AF0");
+ html5Entities.put("mid", "\u2223");
+ html5Entities.put("middot", "\u00B7");
+ html5Entities.put("minusb", "\u229F");
+ html5Entities.put("minus", "\u2212");
+ html5Entities.put("minusd", "\u2238");
+ html5Entities.put("minusdu", "\u2A2A");
+ html5Entities.put("MinusPlus", "\u2213");
+ html5Entities.put("mlcp", "\u2ADB");
+ html5Entities.put("mldr", "\u2026");
+ html5Entities.put("mnplus", "\u2213");
+ html5Entities.put("models", "\u22A7");
+ html5Entities.put("Mopf", "\uD835\uDD44");
+ html5Entities.put("mopf", "\uD835\uDD5E");
+ html5Entities.put("mp", "\u2213");
+ html5Entities.put("mscr", "\uD835\uDCC2");
+ html5Entities.put("Mscr", "\u2133");
+ html5Entities.put("mstpos", "\u223E");
+ html5Entities.put("Mu", "\u039C");
+ html5Entities.put("mu", "\u03BC");
+ html5Entities.put("multimap", "\u22B8");
+ html5Entities.put("mumap", "\u22B8");
+ html5Entities.put("nabla", "\u2207");
+ html5Entities.put("Nacute", "\u0143");
+ html5Entities.put("nacute", "\u0144");
+ html5Entities.put("nang", "\u2220\u20D2");
+ html5Entities.put("nap", "\u2249");
+ html5Entities.put("napE", "\u2A70\u0338");
+ html5Entities.put("napid", "\u224B\u0338");
+ html5Entities.put("napos", "\u0149");
+ html5Entities.put("napprox", "\u2249");
+ html5Entities.put("natural", "\u266E");
+ html5Entities.put("naturals", "\u2115");
+ html5Entities.put("natur", "\u266E");
+ html5Entities.put("nbsp", "\u00A0");
+ html5Entities.put("nbump", "\u224E\u0338");
+ html5Entities.put("nbumpe", "\u224F\u0338");
+ html5Entities.put("ncap", "\u2A43");
+ html5Entities.put("Ncaron", "\u0147");
+ html5Entities.put("ncaron", "\u0148");
+ html5Entities.put("Ncedil", "\u0145");
+ html5Entities.put("ncedil", "\u0146");
+ html5Entities.put("ncong", "\u2247");
+ html5Entities.put("ncongdot", "\u2A6D\u0338");
+ html5Entities.put("ncup", "\u2A42");
+ html5Entities.put("Ncy", "\u041D");
+ html5Entities.put("ncy", "\u043D");
+ html5Entities.put("ndash", "\u2013");
+ html5Entities.put("nearhk", "\u2924");
+ html5Entities.put("nearr", "\u2197");
+ html5Entities.put("neArr", "\u21D7");
+ html5Entities.put("nearrow", "\u2197");
+ html5Entities.put("ne", "\u2260");
+ html5Entities.put("nedot", "\u2250\u0338");
+ html5Entities.put("NegativeMediumSpace", "\u200B");
+ html5Entities.put("NegativeThickSpace", "\u200B");
+ html5Entities.put("NegativeThinSpace", "\u200B");
+ html5Entities.put("NegativeVeryThinSpace", "\u200B");
+ html5Entities.put("nequiv", "\u2262");
+ html5Entities.put("nesear", "\u2928");
+ html5Entities.put("nesim", "\u2242\u0338");
+ html5Entities.put("NestedGreaterGreater", "\u226B");
+ html5Entities.put("NestedLessLess", "\u226A");
+ html5Entities.put("NewLine", "\n");
+ html5Entities.put("nexist", "\u2204");
+ html5Entities.put("nexists", "\u2204");
+ html5Entities.put("Nfr", "\uD835\uDD11");
+ html5Entities.put("nfr", "\uD835\uDD2B");
+ html5Entities.put("ngE", "\u2267\u0338");
+ html5Entities.put("nge", "\u2271");
+ html5Entities.put("ngeq", "\u2271");
+ html5Entities.put("ngeqq", "\u2267\u0338");
+ html5Entities.put("ngeqslant", "\u2A7E\u0338");
+ html5Entities.put("nges", "\u2A7E\u0338");
+ html5Entities.put("nGg", "\u22D9\u0338");
+ html5Entities.put("ngsim", "\u2275");
+ html5Entities.put("nGt", "\u226B\u20D2");
+ html5Entities.put("ngt", "\u226F");
+ html5Entities.put("ngtr", "\u226F");
+ html5Entities.put("nGtv", "\u226B\u0338");
+ html5Entities.put("nharr", "\u21AE");
+ html5Entities.put("nhArr", "\u21CE");
+ html5Entities.put("nhpar", "\u2AF2");
+ html5Entities.put("ni", "\u220B");
+ html5Entities.put("nis", "\u22FC");
+ html5Entities.put("nisd", "\u22FA");
+ html5Entities.put("niv", "\u220B");
+ html5Entities.put("NJcy", "\u040A");
+ html5Entities.put("njcy", "\u045A");
+ html5Entities.put("nlarr", "\u219A");
+ html5Entities.put("nlArr", "\u21CD");
+ html5Entities.put("nldr", "\u2025");
+ html5Entities.put("nlE", "\u2266\u0338");
+ html5Entities.put("nle", "\u2270");
+ html5Entities.put("nleftarrow", "\u219A");
+ html5Entities.put("nLeftarrow", "\u21CD");
+ html5Entities.put("nleftrightarrow", "\u21AE");
+ html5Entities.put("nLeftrightarrow", "\u21CE");
+ html5Entities.put("nleq", "\u2270");
+ html5Entities.put("nleqq", "\u2266\u0338");
+ html5Entities.put("nleqslant", "\u2A7D\u0338");
+ html5Entities.put("nles", "\u2A7D\u0338");
+ html5Entities.put("nless", "\u226E");
+ html5Entities.put("nLl", "\u22D8\u0338");
+ html5Entities.put("nlsim", "\u2274");
+ html5Entities.put("nLt", "\u226A\u20D2");
+ html5Entities.put("nlt", "\u226E");
+ html5Entities.put("nltri", "\u22EA");
+ html5Entities.put("nltrie", "\u22EC");
+ html5Entities.put("nLtv", "\u226A\u0338");
+ html5Entities.put("nmid", "\u2224");
+ html5Entities.put("NoBreak", "\u2060");
+ html5Entities.put("NonBreakingSpace", "\u00A0");
+ html5Entities.put("nopf", "\uD835\uDD5F");
+ html5Entities.put("Nopf", "\u2115");
+ html5Entities.put("Not", "\u2AEC");
+ html5Entities.put("not", "\u00AC");
+ html5Entities.put("NotCongruent", "\u2262");
+ html5Entities.put("NotCupCap", "\u226D");
+ html5Entities.put("NotDoubleVerticalBar", "\u2226");
+ html5Entities.put("NotElement", "\u2209");
+ html5Entities.put("NotEqual", "\u2260");
+ html5Entities.put("NotEqualTilde", "\u2242\u0338");
+ html5Entities.put("NotExists", "\u2204");
+ html5Entities.put("NotGreater", "\u226F");
+ html5Entities.put("NotGreaterEqual", "\u2271");
+ html5Entities.put("NotGreaterFullEqual", "\u2267\u0338");
+ html5Entities.put("NotGreaterGreater", "\u226B\u0338");
+ html5Entities.put("NotGreaterLess", "\u2279");
+ html5Entities.put("NotGreaterSlantEqual", "\u2A7E\u0338");
+ html5Entities.put("NotGreaterTilde", "\u2275");
+ html5Entities.put("NotHumpDownHump", "\u224E\u0338");
+ html5Entities.put("NotHumpEqual", "\u224F\u0338");
+ html5Entities.put("notin", "\u2209");
+ html5Entities.put("notindot", "\u22F5\u0338");
+ html5Entities.put("notinE", "\u22F9\u0338");
+ html5Entities.put("notinva", "\u2209");
+ html5Entities.put("notinvb", "\u22F7");
+ html5Entities.put("notinvc", "\u22F6");
+ html5Entities.put("NotLeftTriangleBar", "\u29CF\u0338");
+ html5Entities.put("NotLeftTriangle", "\u22EA");
+ html5Entities.put("NotLeftTriangleEqual", "\u22EC");
+ html5Entities.put("NotLess", "\u226E");
+ html5Entities.put("NotLessEqual", "\u2270");
+ html5Entities.put("NotLessGreater", "\u2278");
+ html5Entities.put("NotLessLess", "\u226A\u0338");
+ html5Entities.put("NotLessSlantEqual", "\u2A7D\u0338");
+ html5Entities.put("NotLessTilde", "\u2274");
+ html5Entities.put("NotNestedGreaterGreater", "\u2AA2\u0338");
+ html5Entities.put("NotNestedLessLess", "\u2AA1\u0338");
+ html5Entities.put("notni", "\u220C");
+ html5Entities.put("notniva", "\u220C");
+ html5Entities.put("notnivb", "\u22FE");
+ html5Entities.put("notnivc", "\u22FD");
+ html5Entities.put("NotPrecedes", "\u2280");
+ html5Entities.put("NotPrecedesEqual", "\u2AAF\u0338");
+ html5Entities.put("NotPrecedesSlantEqual", "\u22E0");
+ html5Entities.put("NotReverseElement", "\u220C");
+ html5Entities.put("NotRightTriangleBar", "\u29D0\u0338");
+ html5Entities.put("NotRightTriangle", "\u22EB");
+ html5Entities.put("NotRightTriangleEqual", "\u22ED");
+ html5Entities.put("NotSquareSubset", "\u228F\u0338");
+ html5Entities.put("NotSquareSubsetEqual", "\u22E2");
+ html5Entities.put("NotSquareSuperset", "\u2290\u0338");
+ html5Entities.put("NotSquareSupersetEqual", "\u22E3");
+ html5Entities.put("NotSubset", "\u2282\u20D2");
+ html5Entities.put("NotSubsetEqual", "\u2288");
+ html5Entities.put("NotSucceeds", "\u2281");
+ html5Entities.put("NotSucceedsEqual", "\u2AB0\u0338");
+ html5Entities.put("NotSucceedsSlantEqual", "\u22E1");
+ html5Entities.put("NotSucceedsTilde", "\u227F\u0338");
+ html5Entities.put("NotSuperset", "\u2283\u20D2");
+ html5Entities.put("NotSupersetEqual", "\u2289");
+ html5Entities.put("NotTilde", "\u2241");
+ html5Entities.put("NotTildeEqual", "\u2244");
+ html5Entities.put("NotTildeFullEqual", "\u2247");
+ html5Entities.put("NotTildeTilde", "\u2249");
+ html5Entities.put("NotVerticalBar", "\u2224");
+ html5Entities.put("nparallel", "\u2226");
+ html5Entities.put("npar", "\u2226");
+ html5Entities.put("nparsl", "\u2AFD\u20E5");
+ html5Entities.put("npart", "\u2202\u0338");
+ html5Entities.put("npolint", "\u2A14");
+ html5Entities.put("npr", "\u2280");
+ html5Entities.put("nprcue", "\u22E0");
+ html5Entities.put("nprec", "\u2280");
+ html5Entities.put("npreceq", "\u2AAF\u0338");
+ html5Entities.put("npre", "\u2AAF\u0338");
+ html5Entities.put("nrarrc", "\u2933\u0338");
+ html5Entities.put("nrarr", "\u219B");
+ html5Entities.put("nrArr", "\u21CF");
+ html5Entities.put("nrarrw", "\u219D\u0338");
+ html5Entities.put("nrightarrow", "\u219B");
+ html5Entities.put("nRightarrow", "\u21CF");
+ html5Entities.put("nrtri", "\u22EB");
+ html5Entities.put("nrtrie", "\u22ED");
+ html5Entities.put("nsc", "\u2281");
+ html5Entities.put("nsccue", "\u22E1");
+ html5Entities.put("nsce", "\u2AB0\u0338");
+ html5Entities.put("Nscr", "\uD835\uDCA9");
+ html5Entities.put("nscr", "\uD835\uDCC3");
+ html5Entities.put("nshortmid", "\u2224");
+ html5Entities.put("nshortparallel", "\u2226");
+ html5Entities.put("nsim", "\u2241");
+ html5Entities.put("nsime", "\u2244");
+ html5Entities.put("nsimeq", "\u2244");
+ html5Entities.put("nsmid", "\u2224");
+ html5Entities.put("nspar", "\u2226");
+ html5Entities.put("nsqsube", "\u22E2");
+ html5Entities.put("nsqsupe", "\u22E3");
+ html5Entities.put("nsub", "\u2284");
+ html5Entities.put("nsubE", "\u2AC5\u0338");
+ html5Entities.put("nsube", "\u2288");
+ html5Entities.put("nsubset", "\u2282\u20D2");
+ html5Entities.put("nsubseteq", "\u2288");
+ html5Entities.put("nsubseteqq", "\u2AC5\u0338");
+ html5Entities.put("nsucc", "\u2281");
+ html5Entities.put("nsucceq", "\u2AB0\u0338");
+ html5Entities.put("nsup", "\u2285");
+ html5Entities.put("nsupE", "\u2AC6\u0338");
+ html5Entities.put("nsupe", "\u2289");
+ html5Entities.put("nsupset", "\u2283\u20D2");
+ html5Entities.put("nsupseteq", "\u2289");
+ html5Entities.put("nsupseteqq", "\u2AC6\u0338");
+ html5Entities.put("ntgl", "\u2279");
+ html5Entities.put("Ntilde", "\u00D1");
+ html5Entities.put("ntilde", "\u00F1");
+ html5Entities.put("ntlg", "\u2278");
+ html5Entities.put("ntriangleleft", "\u22EA");
+ html5Entities.put("ntrianglelefteq", "\u22EC");
+ html5Entities.put("ntriangleright", "\u22EB");
+ html5Entities.put("ntrianglerighteq", "\u22ED");
+ html5Entities.put("Nu", "\u039D");
+ html5Entities.put("nu", "\u03BD");
+ html5Entities.put("num", "\u0023");
+ html5Entities.put("numero", "\u2116");
+ html5Entities.put("numsp", "\u2007");
+ html5Entities.put("nvap", "\u224D\u20D2");
+ html5Entities.put("nvdash", "\u22AC");
+ html5Entities.put("nvDash", "\u22AD");
+ html5Entities.put("nVdash", "\u22AE");
+ html5Entities.put("nVDash", "\u22AF");
+ html5Entities.put("nvge", "\u2265\u20D2");
+ html5Entities.put("nvgt", "\u003E\u20D2");
+ html5Entities.put("nvHarr", "\u2904");
+ html5Entities.put("nvinfin", "\u29DE");
+ html5Entities.put("nvlArr", "\u2902");
+ html5Entities.put("nvle", "\u2264\u20D2");
+ html5Entities.put("nvlt", "\u003C\u20D2");
+ html5Entities.put("nvltrie", "\u22B4\u20D2");
+ html5Entities.put("nvrArr", "\u2903");
+ html5Entities.put("nvrtrie", "\u22B5\u20D2");
+ html5Entities.put("nvsim", "\u223C\u20D2");
+ html5Entities.put("nwarhk", "\u2923");
+ html5Entities.put("nwarr", "\u2196");
+ html5Entities.put("nwArr", "\u21D6");
+ html5Entities.put("nwarrow", "\u2196");
+ html5Entities.put("nwnear", "\u2927");
+ html5Entities.put("Oacute", "\u00D3");
+ html5Entities.put("oacute", "\u00F3");
+ html5Entities.put("oast", "\u229B");
+ html5Entities.put("Ocirc", "\u00D4");
+ html5Entities.put("ocirc", "\u00F4");
+ html5Entities.put("ocir", "\u229A");
+ html5Entities.put("Ocy", "\u041E");
+ html5Entities.put("ocy", "\u043E");
+ html5Entities.put("odash", "\u229D");
+ html5Entities.put("Odblac", "\u0150");
+ html5Entities.put("odblac", "\u0151");
+ html5Entities.put("odiv", "\u2A38");
+ html5Entities.put("odot", "\u2299");
+ html5Entities.put("odsold", "\u29BC");
+ html5Entities.put("OElig", "\u0152");
+ html5Entities.put("oelig", "\u0153");
+ html5Entities.put("ofcir", "\u29BF");
+ html5Entities.put("Ofr", "\uD835\uDD12");
+ html5Entities.put("ofr", "\uD835\uDD2C");
+ html5Entities.put("ogon", "\u02DB");
+ html5Entities.put("Ograve", "\u00D2");
+ html5Entities.put("ograve", "\u00F2");
+ html5Entities.put("ogt", "\u29C1");
+ html5Entities.put("ohbar", "\u29B5");
+ html5Entities.put("ohm", "\u03A9");
+ html5Entities.put("oint", "\u222E");
+ html5Entities.put("olarr", "\u21BA");
+ html5Entities.put("olcir", "\u29BE");
+ html5Entities.put("olcross", "\u29BB");
+ html5Entities.put("oline", "\u203E");
+ html5Entities.put("olt", "\u29C0");
+ html5Entities.put("Omacr", "\u014C");
+ html5Entities.put("omacr", "\u014D");
+ html5Entities.put("Omega", "\u03A9");
+ html5Entities.put("omega", "\u03C9");
+ html5Entities.put("Omicron", "\u039F");
+ html5Entities.put("omicron", "\u03BF");
+ html5Entities.put("omid", "\u29B6");
+ html5Entities.put("ominus", "\u2296");
+ html5Entities.put("Oopf", "\uD835\uDD46");
+ html5Entities.put("oopf", "\uD835\uDD60");
+ html5Entities.put("opar", "\u29B7");
+ html5Entities.put("OpenCurlyDoubleQuote", "\u201C");
+ html5Entities.put("OpenCurlyQuote", "\u2018");
+ html5Entities.put("operp", "\u29B9");
+ html5Entities.put("oplus", "\u2295");
+ html5Entities.put("orarr", "\u21BB");
+ html5Entities.put("Or", "\u2A54");
+ html5Entities.put("or", "\u2228");
+ html5Entities.put("ord", "\u2A5D");
+ html5Entities.put("order", "\u2134");
+ html5Entities.put("orderof", "\u2134");
+ html5Entities.put("ordf", "\u00AA");
+ html5Entities.put("ordm", "\u00BA");
+ html5Entities.put("origof", "\u22B6");
+ html5Entities.put("oror", "\u2A56");
+ html5Entities.put("orslope", "\u2A57");
+ html5Entities.put("orv", "\u2A5B");
+ html5Entities.put("oS", "\u24C8");
+ html5Entities.put("Oscr", "\uD835\uDCAA");
+ html5Entities.put("oscr", "\u2134");
+ html5Entities.put("Oslash", "\u00D8");
+ html5Entities.put("oslash", "\u00F8");
+ html5Entities.put("osol", "\u2298");
+ html5Entities.put("Otilde", "\u00D5");
+ html5Entities.put("otilde", "\u00F5");
+ html5Entities.put("otimesas", "\u2A36");
+ html5Entities.put("Otimes", "\u2A37");
+ html5Entities.put("otimes", "\u2297");
+ html5Entities.put("Ouml", "\u00D6");
+ html5Entities.put("ouml", "\u00F6");
+ html5Entities.put("ovbar", "\u233D");
+ html5Entities.put("OverBar", "\u203E");
+ html5Entities.put("OverBrace", "\u23DE");
+ html5Entities.put("OverBracket", "\u23B4");
+ html5Entities.put("OverParenthesis", "\u23DC");
+ html5Entities.put("para", "\u00B6");
+ html5Entities.put("parallel", "\u2225");
+ html5Entities.put("par", "\u2225");
+ html5Entities.put("parsim", "\u2AF3");
+ html5Entities.put("parsl", "\u2AFD");
+ html5Entities.put("part", "\u2202");
+ html5Entities.put("PartialD", "\u2202");
+ html5Entities.put("Pcy", "\u041F");
+ html5Entities.put("pcy", "\u043F");
+ html5Entities.put("percnt", "\u0025");
+ html5Entities.put("period", "\u002E");
+ html5Entities.put("permil", "\u2030");
+ html5Entities.put("perp", "\u22A5");
+ html5Entities.put("pertenk", "\u2031");
+ html5Entities.put("Pfr", "\uD835\uDD13");
+ html5Entities.put("pfr", "\uD835\uDD2D");
+ html5Entities.put("Phi", "\u03A6");
+ html5Entities.put("phi", "\u03C6");
+ html5Entities.put("phiv", "\u03D5");
+ html5Entities.put("phmmat", "\u2133");
+ html5Entities.put("phone", "\u260E");
+ html5Entities.put("Pi", "\u03A0");
+ html5Entities.put("pi", "\u03C0");
+ html5Entities.put("pitchfork", "\u22D4");
+ html5Entities.put("piv", "\u03D6");
+ html5Entities.put("planck", "\u210F");
+ html5Entities.put("planckh", "\u210E");
+ html5Entities.put("plankv", "\u210F");
+ html5Entities.put("plusacir", "\u2A23");
+ html5Entities.put("plusb", "\u229E");
+ html5Entities.put("pluscir", "\u2A22");
+ html5Entities.put("plus", "\u002B");
+ html5Entities.put("plusdo", "\u2214");
+ html5Entities.put("plusdu", "\u2A25");
+ html5Entities.put("pluse", "\u2A72");
+ html5Entities.put("PlusMinus", "\u00B1");
+ html5Entities.put("plusmn", "\u00B1");
+ html5Entities.put("plussim", "\u2A26");
+ html5Entities.put("plustwo", "\u2A27");
+ html5Entities.put("pm", "\u00B1");
+ html5Entities.put("Poincareplane", "\u210C");
+ html5Entities.put("pointint", "\u2A15");
+ html5Entities.put("popf", "\uD835\uDD61");
+ html5Entities.put("Popf", "\u2119");
+ html5Entities.put("pound", "\u00A3");
+ html5Entities.put("prap", "\u2AB7");
+ html5Entities.put("Pr", "\u2ABB");
+ html5Entities.put("pr", "\u227A");
+ html5Entities.put("prcue", "\u227C");
+ html5Entities.put("precapprox", "\u2AB7");
+ html5Entities.put("prec", "\u227A");
+ html5Entities.put("preccurlyeq", "\u227C");
+ html5Entities.put("Precedes", "\u227A");
+ html5Entities.put("PrecedesEqual", "\u2AAF");
+ html5Entities.put("PrecedesSlantEqual", "\u227C");
+ html5Entities.put("PrecedesTilde", "\u227E");
+ html5Entities.put("preceq", "\u2AAF");
+ html5Entities.put("precnapprox", "\u2AB9");
+ html5Entities.put("precneqq", "\u2AB5");
+ html5Entities.put("precnsim", "\u22E8");
+ html5Entities.put("pre", "\u2AAF");
+ html5Entities.put("prE", "\u2AB3");
+ html5Entities.put("precsim", "\u227E");
+ html5Entities.put("prime", "\u2032");
+ html5Entities.put("Prime", "\u2033");
+ html5Entities.put("primes", "\u2119");
+ html5Entities.put("prnap", "\u2AB9");
+ html5Entities.put("prnE", "\u2AB5");
+ html5Entities.put("prnsim", "\u22E8");
+ html5Entities.put("prod", "\u220F");
+ html5Entities.put("Product", "\u220F");
+ html5Entities.put("profalar", "\u232E");
+ html5Entities.put("profline", "\u2312");
+ html5Entities.put("profsurf", "\u2313");
+ html5Entities.put("prop", "\u221D");
+ html5Entities.put("Proportional", "\u221D");
+ html5Entities.put("Proportion", "\u2237");
+ html5Entities.put("propto", "\u221D");
+ html5Entities.put("prsim", "\u227E");
+ html5Entities.put("prurel", "\u22B0");
+ html5Entities.put("Pscr", "\uD835\uDCAB");
+ html5Entities.put("pscr", "\uD835\uDCC5");
+ html5Entities.put("Psi", "\u03A8");
+ html5Entities.put("psi", "\u03C8");
+ html5Entities.put("puncsp", "\u2008");
+ html5Entities.put("Qfr", "\uD835\uDD14");
+ html5Entities.put("qfr", "\uD835\uDD2E");
+ html5Entities.put("qint", "\u2A0C");
+ html5Entities.put("qopf", "\uD835\uDD62");
+ html5Entities.put("Qopf", "\u211A");
+ html5Entities.put("qprime", "\u2057");
+ html5Entities.put("Qscr", "\uD835\uDCAC");
+ html5Entities.put("qscr", "\uD835\uDCC6");
+ html5Entities.put("quaternions", "\u210D");
+ html5Entities.put("quatint", "\u2A16");
+ html5Entities.put("quest", "\u003F");
+ html5Entities.put("questeq", "\u225F");
+ html5Entities.put("quot", "\"");
+ html5Entities.put("QUOT", "\"");
+ html5Entities.put("rAarr", "\u21DB");
+ html5Entities.put("race", "\u223D\u0331");
+ html5Entities.put("Racute", "\u0154");
+ html5Entities.put("racute", "\u0155");
+ html5Entities.put("radic", "\u221A");
+ html5Entities.put("raemptyv", "\u29B3");
+ html5Entities.put("rang", "\u27E9");
+ html5Entities.put("Rang", "\u27EB");
+ html5Entities.put("rangd", "\u2992");
+ html5Entities.put("range", "\u29A5");
+ html5Entities.put("rangle", "\u27E9");
+ html5Entities.put("raquo", "\u00BB");
+ html5Entities.put("rarrap", "\u2975");
+ html5Entities.put("rarrb", "\u21E5");
+ html5Entities.put("rarrbfs", "\u2920");
+ html5Entities.put("rarrc", "\u2933");
+ html5Entities.put("rarr", "\u2192");
+ html5Entities.put("Rarr", "\u21A0");
+ html5Entities.put("rArr", "\u21D2");
+ html5Entities.put("rarrfs", "\u291E");
+ html5Entities.put("rarrhk", "\u21AA");
+ html5Entities.put("rarrlp", "\u21AC");
+ html5Entities.put("rarrpl", "\u2945");
+ html5Entities.put("rarrsim", "\u2974");
+ html5Entities.put("Rarrtl", "\u2916");
+ html5Entities.put("rarrtl", "\u21A3");
+ html5Entities.put("rarrw", "\u219D");
+ html5Entities.put("ratail", "\u291A");
+ html5Entities.put("rAtail", "\u291C");
+ html5Entities.put("ratio", "\u2236");
+ html5Entities.put("rationals", "\u211A");
+ html5Entities.put("rbarr", "\u290D");
+ html5Entities.put("rBarr", "\u290F");
+ html5Entities.put("RBarr", "\u2910");
+ html5Entities.put("rbbrk", "\u2773");
+ html5Entities.put("rbrace", "\u007D");
+ html5Entities.put("rbrack", "\u005D");
+ html5Entities.put("rbrke", "\u298C");
+ html5Entities.put("rbrksld", "\u298E");
+ html5Entities.put("rbrkslu", "\u2990");
+ html5Entities.put("Rcaron", "\u0158");
+ html5Entities.put("rcaron", "\u0159");
+ html5Entities.put("Rcedil", "\u0156");
+ html5Entities.put("rcedil", "\u0157");
+ html5Entities.put("rceil", "\u2309");
+ html5Entities.put("rcub", "\u007D");
+ html5Entities.put("Rcy", "\u0420");
+ html5Entities.put("rcy", "\u0440");
+ html5Entities.put("rdca", "\u2937");
+ html5Entities.put("rdldhar", "\u2969");
+ html5Entities.put("rdquo", "\u201D");
+ html5Entities.put("rdquor", "\u201D");
+ html5Entities.put("rdsh", "\u21B3");
+ html5Entities.put("real", "\u211C");
+ html5Entities.put("realine", "\u211B");
+ html5Entities.put("realpart", "\u211C");
+ html5Entities.put("reals", "\u211D");
+ html5Entities.put("Re", "\u211C");
+ html5Entities.put("rect", "\u25AD");
+ html5Entities.put("reg", "\u00AE");
+ html5Entities.put("REG", "\u00AE");
+ html5Entities.put("ReverseElement", "\u220B");
+ html5Entities.put("ReverseEquilibrium", "\u21CB");
+ html5Entities.put("ReverseUpEquilibrium", "\u296F");
+ html5Entities.put("rfisht", "\u297D");
+ html5Entities.put("rfloor", "\u230B");
+ html5Entities.put("rfr", "\uD835\uDD2F");
+ html5Entities.put("Rfr", "\u211C");
+ html5Entities.put("rHar", "\u2964");
+ html5Entities.put("rhard", "\u21C1");
+ html5Entities.put("rharu", "\u21C0");
+ html5Entities.put("rharul", "\u296C");
+ html5Entities.put("Rho", "\u03A1");
+ html5Entities.put("rho", "\u03C1");
+ html5Entities.put("rhov", "\u03F1");
+ html5Entities.put("RightAngleBracket", "\u27E9");
+ html5Entities.put("RightArrowBar", "\u21E5");
+ html5Entities.put("rightarrow", "\u2192");
+ html5Entities.put("RightArrow", "\u2192");
+ html5Entities.put("Rightarrow", "\u21D2");
+ html5Entities.put("RightArrowLeftArrow", "\u21C4");
+ html5Entities.put("rightarrowtail", "\u21A3");
+ html5Entities.put("RightCeiling", "\u2309");
+ html5Entities.put("RightDoubleBracket", "\u27E7");
+ html5Entities.put("RightDownTeeVector", "\u295D");
+ html5Entities.put("RightDownVectorBar", "\u2955");
+ html5Entities.put("RightDownVector", "\u21C2");
+ html5Entities.put("RightFloor", "\u230B");
+ html5Entities.put("rightharpoondown", "\u21C1");
+ html5Entities.put("rightharpoonup", "\u21C0");
+ html5Entities.put("rightleftarrows", "\u21C4");
+ html5Entities.put("rightleftharpoons", "\u21CC");
+ html5Entities.put("rightrightarrows", "\u21C9");
+ html5Entities.put("rightsquigarrow", "\u219D");
+ html5Entities.put("RightTeeArrow", "\u21A6");
+ html5Entities.put("RightTee", "\u22A2");
+ html5Entities.put("RightTeeVector", "\u295B");
+ html5Entities.put("rightthreetimes", "\u22CC");
+ html5Entities.put("RightTriangleBar", "\u29D0");
+ html5Entities.put("RightTriangle", "\u22B3");
+ html5Entities.put("RightTriangleEqual", "\u22B5");
+ html5Entities.put("RightUpDownVector", "\u294F");
+ html5Entities.put("RightUpTeeVector", "\u295C");
+ html5Entities.put("RightUpVectorBar", "\u2954");
+ html5Entities.put("RightUpVector", "\u21BE");
+ html5Entities.put("RightVectorBar", "\u2953");
+ html5Entities.put("RightVector", "\u21C0");
+ html5Entities.put("ring", "\u02DA");
+ html5Entities.put("risingdotseq", "\u2253");
+ html5Entities.put("rlarr", "\u21C4");
+ html5Entities.put("rlhar", "\u21CC");
+ html5Entities.put("rlm", "\u200F");
+ html5Entities.put("rmoustache", "\u23B1");
+ html5Entities.put("rmoust", "\u23B1");
+ html5Entities.put("rnmid", "\u2AEE");
+ html5Entities.put("roang", "\u27ED");
+ html5Entities.put("roarr", "\u21FE");
+ html5Entities.put("robrk", "\u27E7");
+ html5Entities.put("ropar", "\u2986");
+ html5Entities.put("ropf", "\uD835\uDD63");
+ html5Entities.put("Ropf", "\u211D");
+ html5Entities.put("roplus", "\u2A2E");
+ html5Entities.put("rotimes", "\u2A35");
+ html5Entities.put("RoundImplies", "\u2970");
+ html5Entities.put("rpar", "\u0029");
+ html5Entities.put("rpargt", "\u2994");
+ html5Entities.put("rppolint", "\u2A12");
+ html5Entities.put("rrarr", "\u21C9");
+ html5Entities.put("Rrightarrow", "\u21DB");
+ html5Entities.put("rsaquo", "\u203A");
+ html5Entities.put("rscr", "\uD835\uDCC7");
+ html5Entities.put("Rscr", "\u211B");
+ html5Entities.put("rsh", "\u21B1");
+ html5Entities.put("Rsh", "\u21B1");
+ html5Entities.put("rsqb", "\u005D");
+ html5Entities.put("rsquo", "\u2019");
+ html5Entities.put("rsquor", "\u2019");
+ html5Entities.put("rthree", "\u22CC");
+ html5Entities.put("rtimes", "\u22CA");
+ html5Entities.put("rtri", "\u25B9");
+ html5Entities.put("rtrie", "\u22B5");
+ html5Entities.put("rtrif", "\u25B8");
+ html5Entities.put("rtriltri", "\u29CE");
+ html5Entities.put("RuleDelayed", "\u29F4");
+ html5Entities.put("ruluhar", "\u2968");
+ html5Entities.put("rx", "\u211E");
+ html5Entities.put("Sacute", "\u015A");
+ html5Entities.put("sacute", "\u015B");
+ html5Entities.put("sbquo", "\u201A");
+ html5Entities.put("scap", "\u2AB8");
+ html5Entities.put("Scaron", "\u0160");
+ html5Entities.put("scaron", "\u0161");
+ html5Entities.put("Sc", "\u2ABC");
+ html5Entities.put("sc", "\u227B");
+ html5Entities.put("sccue", "\u227D");
+ html5Entities.put("sce", "\u2AB0");
+ html5Entities.put("scE", "\u2AB4");
+ html5Entities.put("Scedil", "\u015E");
+ html5Entities.put("scedil", "\u015F");
+ html5Entities.put("Scirc", "\u015C");
+ html5Entities.put("scirc", "\u015D");
+ html5Entities.put("scnap", "\u2ABA");
+ html5Entities.put("scnE", "\u2AB6");
+ html5Entities.put("scnsim", "\u22E9");
+ html5Entities.put("scpolint", "\u2A13");
+ html5Entities.put("scsim", "\u227F");
+ html5Entities.put("Scy", "\u0421");
+ html5Entities.put("scy", "\u0441");
+ html5Entities.put("sdotb", "\u22A1");
+ html5Entities.put("sdot", "\u22C5");
+ html5Entities.put("sdote", "\u2A66");
+ html5Entities.put("searhk", "\u2925");
+ html5Entities.put("searr", "\u2198");
+ html5Entities.put("seArr", "\u21D8");
+ html5Entities.put("searrow", "\u2198");
+ html5Entities.put("sect", "\u00A7");
+ html5Entities.put("semi", "\u003B");
+ html5Entities.put("seswar", "\u2929");
+ html5Entities.put("setminus", "\u2216");
+ html5Entities.put("setmn", "\u2216");
+ html5Entities.put("sext", "\u2736");
+ html5Entities.put("Sfr", "\uD835\uDD16");
+ html5Entities.put("sfr", "\uD835\uDD30");
+ html5Entities.put("sfrown", "\u2322");
+ html5Entities.put("sharp", "\u266F");
+ html5Entities.put("SHCHcy", "\u0429");
+ html5Entities.put("shchcy", "\u0449");
+ html5Entities.put("SHcy", "\u0428");
+ html5Entities.put("shcy", "\u0448");
+ html5Entities.put("ShortDownArrow", "\u2193");
+ html5Entities.put("ShortLeftArrow", "\u2190");
+ html5Entities.put("shortmid", "\u2223");
+ html5Entities.put("shortparallel", "\u2225");
+ html5Entities.put("ShortRightArrow", "\u2192");
+ html5Entities.put("ShortUpArrow", "\u2191");
+ html5Entities.put("shy", "\u00AD");
+ html5Entities.put("Sigma", "\u03A3");
+ html5Entities.put("sigma", "\u03C3");
+ html5Entities.put("sigmaf", "\u03C2");
+ html5Entities.put("sigmav", "\u03C2");
+ html5Entities.put("sim", "\u223C");
+ html5Entities.put("simdot", "\u2A6A");
+ html5Entities.put("sime", "\u2243");
+ html5Entities.put("simeq", "\u2243");
+ html5Entities.put("simg", "\u2A9E");
+ html5Entities.put("simgE", "\u2AA0");
+ html5Entities.put("siml", "\u2A9D");
+ html5Entities.put("simlE", "\u2A9F");
+ html5Entities.put("simne", "\u2246");
+ html5Entities.put("simplus", "\u2A24");
+ html5Entities.put("simrarr", "\u2972");
+ html5Entities.put("slarr", "\u2190");
+ html5Entities.put("SmallCircle", "\u2218");
+ html5Entities.put("smallsetminus", "\u2216");
+ html5Entities.put("smashp", "\u2A33");
+ html5Entities.put("smeparsl", "\u29E4");
+ html5Entities.put("smid", "\u2223");
+ html5Entities.put("smile", "\u2323");
+ html5Entities.put("smt", "\u2AAA");
+ html5Entities.put("smte", "\u2AAC");
+ html5Entities.put("smtes", "\u2AAC\uFE00");
+ html5Entities.put("SOFTcy", "\u042C");
+ html5Entities.put("softcy", "\u044C");
+ html5Entities.put("solbar", "\u233F");
+ html5Entities.put("solb", "\u29C4");
+ html5Entities.put("sol", "\u002F");
+ html5Entities.put("Sopf", "\uD835\uDD4A");
+ html5Entities.put("sopf", "\uD835\uDD64");
+ html5Entities.put("spades", "\u2660");
+ html5Entities.put("spadesuit", "\u2660");
+ html5Entities.put("spar", "\u2225");
+ html5Entities.put("sqcap", "\u2293");
+ html5Entities.put("sqcaps", "\u2293\uFE00");
+ html5Entities.put("sqcup", "\u2294");
+ html5Entities.put("sqcups", "\u2294\uFE00");
+ html5Entities.put("Sqrt", "\u221A");
+ html5Entities.put("sqsub", "\u228F");
+ html5Entities.put("sqsube", "\u2291");
+ html5Entities.put("sqsubset", "\u228F");
+ html5Entities.put("sqsubseteq", "\u2291");
+ html5Entities.put("sqsup", "\u2290");
+ html5Entities.put("sqsupe", "\u2292");
+ html5Entities.put("sqsupset", "\u2290");
+ html5Entities.put("sqsupseteq", "\u2292");
+ html5Entities.put("square", "\u25A1");
+ html5Entities.put("Square", "\u25A1");
+ html5Entities.put("SquareIntersection", "\u2293");
+ html5Entities.put("SquareSubset", "\u228F");
+ html5Entities.put("SquareSubsetEqual", "\u2291");
+ html5Entities.put("SquareSuperset", "\u2290");
+ html5Entities.put("SquareSupersetEqual", "\u2292");
+ html5Entities.put("SquareUnion", "\u2294");
+ html5Entities.put("squarf", "\u25AA");
+ html5Entities.put("squ", "\u25A1");
+ html5Entities.put("squf", "\u25AA");
+ html5Entities.put("srarr", "\u2192");
+ html5Entities.put("Sscr", "\uD835\uDCAE");
+ html5Entities.put("sscr", "\uD835\uDCC8");
+ html5Entities.put("ssetmn", "\u2216");
+ html5Entities.put("ssmile", "\u2323");
+ html5Entities.put("sstarf", "\u22C6");
+ html5Entities.put("Star", "\u22C6");
+ html5Entities.put("star", "\u2606");
+ html5Entities.put("starf", "\u2605");
+ html5Entities.put("straightepsilon", "\u03F5");
+ html5Entities.put("straightphi", "\u03D5");
+ html5Entities.put("strns", "\u00AF");
+ html5Entities.put("sub", "\u2282");
+ html5Entities.put("Sub", "\u22D0");
+ html5Entities.put("subdot", "\u2ABD");
+ html5Entities.put("subE", "\u2AC5");
+ html5Entities.put("sube", "\u2286");
+ html5Entities.put("subedot", "\u2AC3");
+ html5Entities.put("submult", "\u2AC1");
+ html5Entities.put("subnE", "\u2ACB");
+ html5Entities.put("subne", "\u228A");
+ html5Entities.put("subplus", "\u2ABF");
+ html5Entities.put("subrarr", "\u2979");
+ html5Entities.put("subset", "\u2282");
+ html5Entities.put("Subset", "\u22D0");
+ html5Entities.put("subseteq", "\u2286");
+ html5Entities.put("subseteqq", "\u2AC5");
+ html5Entities.put("SubsetEqual", "\u2286");
+ html5Entities.put("subsetneq", "\u228A");
+ html5Entities.put("subsetneqq", "\u2ACB");
+ html5Entities.put("subsim", "\u2AC7");
+ html5Entities.put("subsub", "\u2AD5");
+ html5Entities.put("subsup", "\u2AD3");
+ html5Entities.put("succapprox", "\u2AB8");
+ html5Entities.put("succ", "\u227B");
+ html5Entities.put("succcurlyeq", "\u227D");
+ html5Entities.put("Succeeds", "\u227B");
+ html5Entities.put("SucceedsEqual", "\u2AB0");
+ html5Entities.put("SucceedsSlantEqual", "\u227D");
+ html5Entities.put("SucceedsTilde", "\u227F");
+ html5Entities.put("succeq", "\u2AB0");
+ html5Entities.put("succnapprox", "\u2ABA");
+ html5Entities.put("succneqq", "\u2AB6");
+ html5Entities.put("succnsim", "\u22E9");
+ html5Entities.put("succsim", "\u227F");
+ html5Entities.put("SuchThat", "\u220B");
+ html5Entities.put("sum", "\u2211");
+ html5Entities.put("Sum", "\u2211");
+ html5Entities.put("sung", "\u266A");
+ html5Entities.put("sup1", "\u00B9");
+ html5Entities.put("sup2", "\u00B2");
+ html5Entities.put("sup3", "\u00B3");
+ html5Entities.put("sup", "\u2283");
+ html5Entities.put("Sup", "\u22D1");
+ html5Entities.put("supdot", "\u2ABE");
+ html5Entities.put("supdsub", "\u2AD8");
+ html5Entities.put("supE", "\u2AC6");
+ html5Entities.put("supe", "\u2287");
+ html5Entities.put("supedot", "\u2AC4");
+ html5Entities.put("Superset", "\u2283");
+ html5Entities.put("SupersetEqual", "\u2287");
+ html5Entities.put("suphsol", "\u27C9");
+ html5Entities.put("suphsub", "\u2AD7");
+ html5Entities.put("suplarr", "\u297B");
+ html5Entities.put("supmult", "\u2AC2");
+ html5Entities.put("supnE", "\u2ACC");
+ html5Entities.put("supne", "\u228B");
+ html5Entities.put("supplus", "\u2AC0");
+ html5Entities.put("supset", "\u2283");
+ html5Entities.put("Supset", "\u22D1");
+ html5Entities.put("supseteq", "\u2287");
+ html5Entities.put("supseteqq", "\u2AC6");
+ html5Entities.put("supsetneq", "\u228B");
+ html5Entities.put("supsetneqq", "\u2ACC");
+ html5Entities.put("supsim", "\u2AC8");
+ html5Entities.put("supsub", "\u2AD4");
+ html5Entities.put("supsup", "\u2AD6");
+ html5Entities.put("swarhk", "\u2926");
+ html5Entities.put("swarr", "\u2199");
+ html5Entities.put("swArr", "\u21D9");
+ html5Entities.put("swarrow", "\u2199");
+ html5Entities.put("swnwar", "\u292A");
+ html5Entities.put("szlig", "\u00DF");
+ html5Entities.put("Tab", "\u0009");
+ html5Entities.put("target", "\u2316");
+ html5Entities.put("Tau", "\u03A4");
+ html5Entities.put("tau", "\u03C4");
+ html5Entities.put("tbrk", "\u23B4");
+ html5Entities.put("Tcaron", "\u0164");
+ html5Entities.put("tcaron", "\u0165");
+ html5Entities.put("Tcedil", "\u0162");
+ html5Entities.put("tcedil", "\u0163");
+ html5Entities.put("Tcy", "\u0422");
+ html5Entities.put("tcy", "\u0442");
+ html5Entities.put("tdot", "\u20DB");
+ html5Entities.put("telrec", "\u2315");
+ html5Entities.put("Tfr", "\uD835\uDD17");
+ html5Entities.put("tfr", "\uD835\uDD31");
+ html5Entities.put("there4", "\u2234");
+ html5Entities.put("therefore", "\u2234");
+ html5Entities.put("Therefore", "\u2234");
+ html5Entities.put("Theta", "\u0398");
+ html5Entities.put("theta", "\u03B8");
+ html5Entities.put("thetasym", "\u03D1");
+ html5Entities.put("thetav", "\u03D1");
+ html5Entities.put("thickapprox", "\u2248");
+ html5Entities.put("thicksim", "\u223C");
+ html5Entities.put("ThickSpace", "\u205F\u200A");
+ html5Entities.put("ThinSpace", "\u2009");
+ html5Entities.put("thinsp", "\u2009");
+ html5Entities.put("thkap", "\u2248");
+ html5Entities.put("thksim", "\u223C");
+ html5Entities.put("THORN", "\u00DE");
+ html5Entities.put("thorn", "\u00FE");
+ html5Entities.put("tilde", "\u02DC");
+ html5Entities.put("Tilde", "\u223C");
+ html5Entities.put("TildeEqual", "\u2243");
+ html5Entities.put("TildeFullEqual", "\u2245");
+ html5Entities.put("TildeTilde", "\u2248");
+ html5Entities.put("timesbar", "\u2A31");
+ html5Entities.put("timesb", "\u22A0");
+ html5Entities.put("times", "\u00D7");
+ html5Entities.put("timesd", "\u2A30");
+ html5Entities.put("tint", "\u222D");
+ html5Entities.put("toea", "\u2928");
+ html5Entities.put("topbot", "\u2336");
+ html5Entities.put("topcir", "\u2AF1");
+ html5Entities.put("top", "\u22A4");
+ html5Entities.put("Topf", "\uD835\uDD4B");
+ html5Entities.put("topf", "\uD835\uDD65");
+ html5Entities.put("topfork", "\u2ADA");
+ html5Entities.put("tosa", "\u2929");
+ html5Entities.put("tprime", "\u2034");
+ html5Entities.put("trade", "\u2122");
+ html5Entities.put("TRADE", "\u2122");
+ html5Entities.put("triangle", "\u25B5");
+ html5Entities.put("triangledown", "\u25BF");
+ html5Entities.put("triangleleft", "\u25C3");
+ html5Entities.put("trianglelefteq", "\u22B4");
+ html5Entities.put("triangleq", "\u225C");
+ html5Entities.put("triangleright", "\u25B9");
+ html5Entities.put("trianglerighteq", "\u22B5");
+ html5Entities.put("tridot", "\u25EC");
+ html5Entities.put("trie", "\u225C");
+ html5Entities.put("triminus", "\u2A3A");
+ html5Entities.put("TripleDot", "\u20DB");
+ html5Entities.put("triplus", "\u2A39");
+ html5Entities.put("trisb", "\u29CD");
+ html5Entities.put("tritime", "\u2A3B");
+ html5Entities.put("trpezium", "\u23E2");
+ html5Entities.put("Tscr", "\uD835\uDCAF");
+ html5Entities.put("tscr", "\uD835\uDCC9");
+ html5Entities.put("TScy", "\u0426");
+ html5Entities.put("tscy", "\u0446");
+ html5Entities.put("TSHcy", "\u040B");
+ html5Entities.put("tshcy", "\u045B");
+ html5Entities.put("Tstrok", "\u0166");
+ html5Entities.put("tstrok", "\u0167");
+ html5Entities.put("twixt", "\u226C");
+ html5Entities.put("twoheadleftarrow", "\u219E");
+ html5Entities.put("twoheadrightarrow", "\u21A0");
+ html5Entities.put("Uacute", "\u00DA");
+ html5Entities.put("uacute", "\u00FA");
+ html5Entities.put("uarr", "\u2191");
+ html5Entities.put("Uarr", "\u219F");
+ html5Entities.put("uArr", "\u21D1");
+ html5Entities.put("Uarrocir", "\u2949");
+ html5Entities.put("Ubrcy", "\u040E");
+ html5Entities.put("ubrcy", "\u045E");
+ html5Entities.put("Ubreve", "\u016C");
+ html5Entities.put("ubreve", "\u016D");
+ html5Entities.put("Ucirc", "\u00DB");
+ html5Entities.put("ucirc", "\u00FB");
+ html5Entities.put("Ucy", "\u0423");
+ html5Entities.put("ucy", "\u0443");
+ html5Entities.put("udarr", "\u21C5");
+ html5Entities.put("Udblac", "\u0170");
+ html5Entities.put("udblac", "\u0171");
+ html5Entities.put("udhar", "\u296E");
+ html5Entities.put("ufisht", "\u297E");
+ html5Entities.put("Ufr", "\uD835\uDD18");
+ html5Entities.put("ufr", "\uD835\uDD32");
+ html5Entities.put("Ugrave", "\u00D9");
+ html5Entities.put("ugrave", "\u00F9");
+ html5Entities.put("uHar", "\u2963");
+ html5Entities.put("uharl", "\u21BF");
+ html5Entities.put("uharr", "\u21BE");
+ html5Entities.put("uhblk", "\u2580");
+ html5Entities.put("ulcorn", "\u231C");
+ html5Entities.put("ulcorner", "\u231C");
+ html5Entities.put("ulcrop", "\u230F");
+ html5Entities.put("ultri", "\u25F8");
+ html5Entities.put("Umacr", "\u016A");
+ html5Entities.put("umacr", "\u016B");
+ html5Entities.put("uml", "\u00A8");
+ html5Entities.put("UnderBar", "\u005F");
+ html5Entities.put("UnderBrace", "\u23DF");
+ html5Entities.put("UnderBracket", "\u23B5");
+ html5Entities.put("UnderParenthesis", "\u23DD");
+ html5Entities.put("Union", "\u22C3");
+ html5Entities.put("UnionPlus", "\u228E");
+ html5Entities.put("Uogon", "\u0172");
+ html5Entities.put("uogon", "\u0173");
+ html5Entities.put("Uopf", "\uD835\uDD4C");
+ html5Entities.put("uopf", "\uD835\uDD66");
+ html5Entities.put("UpArrowBar", "\u2912");
+ html5Entities.put("uparrow", "\u2191");
+ html5Entities.put("UpArrow", "\u2191");
+ html5Entities.put("Uparrow", "\u21D1");
+ html5Entities.put("UpArrowDownArrow", "\u21C5");
+ html5Entities.put("updownarrow", "\u2195");
+ html5Entities.put("UpDownArrow", "\u2195");
+ html5Entities.put("Updownarrow", "\u21D5");
+ html5Entities.put("UpEquilibrium", "\u296E");
+ html5Entities.put("upharpoonleft", "\u21BF");
+ html5Entities.put("upharpoonright", "\u21BE");
+ html5Entities.put("uplus", "\u228E");
+ html5Entities.put("UpperLeftArrow", "\u2196");
+ html5Entities.put("UpperRightArrow", "\u2197");
+ html5Entities.put("upsi", "\u03C5");
+ html5Entities.put("Upsi", "\u03D2");
+ html5Entities.put("upsih", "\u03D2");
+ html5Entities.put("Upsilon", "\u03A5");
+ html5Entities.put("upsilon", "\u03C5");
+ html5Entities.put("UpTeeArrow", "\u21A5");
+ html5Entities.put("UpTee", "\u22A5");
+ html5Entities.put("upuparrows", "\u21C8");
+ html5Entities.put("urcorn", "\u231D");
+ html5Entities.put("urcorner", "\u231D");
+ html5Entities.put("urcrop", "\u230E");
+ html5Entities.put("Uring", "\u016E");
+ html5Entities.put("uring", "\u016F");
+ html5Entities.put("urtri", "\u25F9");
+ html5Entities.put("Uscr", "\uD835\uDCB0");
+ html5Entities.put("uscr", "\uD835\uDCCA");
+ html5Entities.put("utdot", "\u22F0");
+ html5Entities.put("Utilde", "\u0168");
+ html5Entities.put("utilde", "\u0169");
+ html5Entities.put("utri", "\u25B5");
+ html5Entities.put("utrif", "\u25B4");
+ html5Entities.put("uuarr", "\u21C8");
+ html5Entities.put("Uuml", "\u00DC");
+ html5Entities.put("uuml", "\u00FC");
+ html5Entities.put("uwangle", "\u29A7");
+ html5Entities.put("vangrt", "\u299C");
+ html5Entities.put("varepsilon", "\u03F5");
+ html5Entities.put("varkappa", "\u03F0");
+ html5Entities.put("varnothing", "\u2205");
+ html5Entities.put("varphi", "\u03D5");
+ html5Entities.put("varpi", "\u03D6");
+ html5Entities.put("varpropto", "\u221D");
+ html5Entities.put("varr", "\u2195");
+ html5Entities.put("vArr", "\u21D5");
+ html5Entities.put("varrho", "\u03F1");
+ html5Entities.put("varsigma", "\u03C2");
+ html5Entities.put("varsubsetneq", "\u228A\uFE00");
+ html5Entities.put("varsubsetneqq", "\u2ACB\uFE00");
+ html5Entities.put("varsupsetneq", "\u228B\uFE00");
+ html5Entities.put("varsupsetneqq", "\u2ACC\uFE00");
+ html5Entities.put("vartheta", "\u03D1");
+ html5Entities.put("vartriangleleft", "\u22B2");
+ html5Entities.put("vartriangleright", "\u22B3");
+ html5Entities.put("vBar", "\u2AE8");
+ html5Entities.put("Vbar", "\u2AEB");
+ html5Entities.put("vBarv", "\u2AE9");
+ html5Entities.put("Vcy", "\u0412");
+ html5Entities.put("vcy", "\u0432");
+ html5Entities.put("vdash", "\u22A2");
+ html5Entities.put("vDash", "\u22A8");
+ html5Entities.put("Vdash", "\u22A9");
+ html5Entities.put("VDash", "\u22AB");
+ html5Entities.put("Vdashl", "\u2AE6");
+ html5Entities.put("veebar", "\u22BB");
+ html5Entities.put("vee", "\u2228");
+ html5Entities.put("Vee", "\u22C1");
+ html5Entities.put("veeeq", "\u225A");
+ html5Entities.put("vellip", "\u22EE");
+ html5Entities.put("verbar", "\u007C");
+ html5Entities.put("Verbar", "\u2016");
+ html5Entities.put("vert", "\u007C");
+ html5Entities.put("Vert", "\u2016");
+ html5Entities.put("VerticalBar", "\u2223");
+ html5Entities.put("VerticalLine", "\u007C");
+ html5Entities.put("VerticalSeparator", "\u2758");
+ html5Entities.put("VerticalTilde", "\u2240");
+ html5Entities.put("VeryThinSpace", "\u200A");
+ html5Entities.put("Vfr", "\uD835\uDD19");
+ html5Entities.put("vfr", "\uD835\uDD33");
+ html5Entities.put("vltri", "\u22B2");
+ html5Entities.put("vnsub", "\u2282\u20D2");
+ html5Entities.put("vnsup", "\u2283\u20D2");
+ html5Entities.put("Vopf", "\uD835\uDD4D");
+ html5Entities.put("vopf", "\uD835\uDD67");
+ html5Entities.put("vprop", "\u221D");
+ html5Entities.put("vrtri", "\u22B3");
+ html5Entities.put("Vscr", "\uD835\uDCB1");
+ html5Entities.put("vscr", "\uD835\uDCCB");
+ html5Entities.put("vsubnE", "\u2ACB\uFE00");
+ html5Entities.put("vsubne", "\u228A\uFE00");
+ html5Entities.put("vsupnE", "\u2ACC\uFE00");
+ html5Entities.put("vsupne", "\u228B\uFE00");
+ html5Entities.put("Vvdash", "\u22AA");
+ html5Entities.put("vzigzag", "\u299A");
+ html5Entities.put("Wcirc", "\u0174");
+ html5Entities.put("wcirc", "\u0175");
+ html5Entities.put("wedbar", "\u2A5F");
+ html5Entities.put("wedge", "\u2227");
+ html5Entities.put("Wedge", "\u22C0");
+ html5Entities.put("wedgeq", "\u2259");
+ html5Entities.put("weierp", "\u2118");
+ html5Entities.put("Wfr", "\uD835\uDD1A");
+ html5Entities.put("wfr", "\uD835\uDD34");
+ html5Entities.put("Wopf", "\uD835\uDD4E");
+ html5Entities.put("wopf", "\uD835\uDD68");
+ html5Entities.put("wp", "\u2118");
+ html5Entities.put("wr", "\u2240");
+ html5Entities.put("wreath", "\u2240");
+ html5Entities.put("Wscr", "\uD835\uDCB2");
+ html5Entities.put("wscr", "\uD835\uDCCC");
+ html5Entities.put("xcap", "\u22C2");
+ html5Entities.put("xcirc", "\u25EF");
+ html5Entities.put("xcup", "\u22C3");
+ html5Entities.put("xdtri", "\u25BD");
+ html5Entities.put("Xfr", "\uD835\uDD1B");
+ html5Entities.put("xfr", "\uD835\uDD35");
+ html5Entities.put("xharr", "\u27F7");
+ html5Entities.put("xhArr", "\u27FA");
+ html5Entities.put("Xi", "\u039E");
+ html5Entities.put("xi", "\u03BE");
+ html5Entities.put("xlarr", "\u27F5");
+ html5Entities.put("xlArr", "\u27F8");
+ html5Entities.put("xmap", "\u27FC");
+ html5Entities.put("xnis", "\u22FB");
+ html5Entities.put("xodot", "\u2A00");
+ html5Entities.put("Xopf", "\uD835\uDD4F");
+ html5Entities.put("xopf", "\uD835\uDD69");
+ html5Entities.put("xoplus", "\u2A01");
+ html5Entities.put("xotime", "\u2A02");
+ html5Entities.put("xrarr", "\u27F6");
+ html5Entities.put("xrArr", "\u27F9");
+ html5Entities.put("Xscr", "\uD835\uDCB3");
+ html5Entities.put("xscr", "\uD835\uDCCD");
+ html5Entities.put("xsqcup", "\u2A06");
+ html5Entities.put("xuplus", "\u2A04");
+ html5Entities.put("xutri", "\u25B3");
+ html5Entities.put("xvee", "\u22C1");
+ html5Entities.put("xwedge", "\u22C0");
+ html5Entities.put("Yacute", "\u00DD");
+ html5Entities.put("yacute", "\u00FD");
+ html5Entities.put("YAcy", "\u042F");
+ html5Entities.put("yacy", "\u044F");
+ html5Entities.put("Ycirc", "\u0176");
+ html5Entities.put("ycirc", "\u0177");
+ html5Entities.put("Ycy", "\u042B");
+ html5Entities.put("ycy", "\u044B");
+ html5Entities.put("yen", "\u00A5");
+ html5Entities.put("Yfr", "\uD835\uDD1C");
+ html5Entities.put("yfr", "\uD835\uDD36");
+ html5Entities.put("YIcy", "\u0407");
+ html5Entities.put("yicy", "\u0457");
+ html5Entities.put("Yopf", "\uD835\uDD50");
+ html5Entities.put("yopf", "\uD835\uDD6A");
+ html5Entities.put("Yscr", "\uD835\uDCB4");
+ html5Entities.put("yscr", "\uD835\uDCCE");
+ html5Entities.put("YUcy", "\u042E");
+ html5Entities.put("yucy", "\u044E");
+ html5Entities.put("yuml", "\u00FF");
+ html5Entities.put("Yuml", "\u0178");
+ html5Entities.put("Zacute", "\u0179");
+ html5Entities.put("zacute", "\u017A");
+ html5Entities.put("Zcaron", "\u017D");
+ html5Entities.put("zcaron", "\u017E");
+ html5Entities.put("Zcy", "\u0417");
+ html5Entities.put("zcy", "\u0437");
+ html5Entities.put("Zdot", "\u017B");
+ html5Entities.put("zdot", "\u017C");
+ html5Entities.put("zeetrf", "\u2128");
+ html5Entities.put("ZeroWidthSpace", "\u200B");
+ html5Entities.put("Zeta", "\u0396");
+ html5Entities.put("zeta", "\u03B6");
+ html5Entities.put("zfr", "\uD835\uDD37");
+ html5Entities.put("Zfr", "\u2128");
+ html5Entities.put("ZHcy", "\u0416");
+ html5Entities.put("zhcy", "\u0436");
+ html5Entities.put("zigrarr", "\u21DD");
+ html5Entities.put("zopf", "\uD835\uDD6B");
+ html5Entities.put("Zopf", "\u2124");
+ html5Entities.put("Zscr", "\uD835\uDCB5");
+ html5Entities.put("zscr", "\uD835\uDCCF");
+ html5Entities.put("zwj", "\u200D");
+ html5Entities.put("zwnj", "\u200C");
}
public static boolean isValid(String name) {
- return names.containsKey(name);
- }
-
- public static Entity get(String name) {
- return names.get(name);
+ return html5Entities.containsKey(name);
}
public static boolean isValid(int code) {
- // allow numeric codes for standard ANSI characters
- return codes.containsKey(code) || ( 32 <= code && code < 2127);
+ // See https://www.w3.org/TR/html52/syntax.html#character-references
+ return Character.isDefined(code)
+ && (!Character.isISOControl(code) || Character.isSpaceChar(code))
+ && (code < 0xd800 || code > 0xdfff);
}
- private static final Map<String,Entity> names = new HashMap<>();
- private static final Map<Integer,Entity> codes = new HashMap<>();
- static {
- for (Entity e: values()) {
- String name = e.name();
- int code = e.code;
- if (name.startsWith("_")) name = name.substring(1);
- names.put(name, e);
- codes.put(code, e);
- }
+ public static String getValue(String name) {
+ return html5Entities.get(name);
}
}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java Thu Jun 13 11:31:36 2019 +0530
@@ -166,6 +166,7 @@
Chain switchExpressionTrueChain;
Chain switchExpressionFalseChain;
List<LocalItem> stackBeforeSwitchExpression;
+ LocalItem switchResult;
/** Generate code to load an integer constant.
* @param n The integer to be loaded.
@@ -1190,9 +1191,11 @@
private void doHandleSwitchExpression(JCSwitchExpression tree) {
List<LocalItem> prevStackBeforeSwitchExpression = stackBeforeSwitchExpression;
+ LocalItem prevSwitchResult = switchResult;
int limit = code.nextreg;
try {
stackBeforeSwitchExpression = List.nil();
+ switchResult = null;
if (hasTry(tree)) {
//if the switch expression contains try-catch, the catch handlers need to have
//an empty stack. So stash whole stack to local variables, and restore it before
@@ -1211,6 +1214,7 @@
stackBeforeSwitchExpression = stackBeforeSwitchExpression.prepend(item);
item.store();
}
+ switchResult = makeTemp(tree.type);
}
int prevLetExprStart = code.setLetExprStackPos(code.state.stacksize);
try {
@@ -1220,6 +1224,7 @@
}
} finally {
stackBeforeSwitchExpression = prevStackBeforeSwitchExpression;
+ switchResult = prevSwitchResult;
code.endScopes(limit);
}
}
@@ -1725,16 +1730,22 @@
public void visitYield(JCYield tree) {
Assert.check(code.isStatementStart());
final Env<GenContext> targetEnv;
- //restore stack as it was before the switch expression:
- for (LocalItem li : stackBeforeSwitchExpression) {
- li.load();
- }
if (inCondSwitchExpression) {
CondItem value = genCond(tree.value, CRT_FLOW_TARGET);
Chain falseJumps = value.jumpFalse();
- targetEnv = unwindBreak(tree.target);
+
code.resolve(value.trueJumps);
+ Env<GenContext> localEnv = unwindBreak(tree.target);
+ reloadStackBeforeSwitchExpr();
Chain trueJumps = code.branch(goto_);
+
+ endFinalizerGaps(env, localEnv);
+
+ code.resolve(falseJumps);
+ targetEnv = unwindBreak(tree.target);
+ reloadStackBeforeSwitchExpr();
+ falseJumps = code.branch(goto_);
+
if (switchExpressionTrueChain == null) {
switchExpressionTrueChain = trueJumps;
} else {
@@ -1749,13 +1760,26 @@
}
} else {
genExpr(tree.value, pt).load();
- code.state.forceStackTop(tree.target.type);
+ if (switchResult != null)
+ switchResult.store();
+
targetEnv = unwindBreak(tree.target);
- targetEnv.info.addExit(code.branch(goto_));
+
+ if (code.isAlive()) {
+ reloadStackBeforeSwitchExpr();
+ if (switchResult != null)
+ switchResult.load();
+
+ code.state.forceStackTop(tree.target.type);
+ targetEnv.info.addExit(code.branch(goto_));
+ code.markDead();
+ }
}
endFinalizerGaps(env, targetEnv);
}
//where:
+ /** As side-effect, might mark code as dead disabling any further emission.
+ */
private Env<GenContext> unwindBreak(JCTree target) {
int tmpPos = code.pendingStatPos;
Env<GenContext> targetEnv = unwind(target, env);
@@ -1763,6 +1787,11 @@
return targetEnv;
}
+ private void reloadStackBeforeSwitchExpr() {
+ for (LocalItem li : stackBeforeSwitchExpression)
+ li.load();
+ }
+
public void visitContinue(JCContinue tree) {
int tmpPos = code.pendingStatPos;
Env<GenContext> targetEnv = unwind(tree.target, env);
--- a/src/jdk.compiler/share/classes/jdk/internal/shellsupport/doc/JavadocFormatter.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/jdk.compiler/share/classes/jdk/internal/shellsupport/doc/JavadocFormatter.java Thu Jun 13 11:31:36 2019 +0530
@@ -513,6 +513,7 @@
public Object visitEntity(EntityTree node, Object p) {
String name = node.getName().toString();
int code = -1;
+ String value = null;
if (name.startsWith("#")) {
try {
int v = StringUtils.toLowerCase(name).startsWith("#x")
@@ -525,13 +526,12 @@
//ignore
}
} else {
- Entity entity = Entity.get(name);
- if (entity != null) {
- code = entity.code;
- }
+ value = Entity.getValue(name);
}
if (code != (-1)) {
result.appendCodePoint(code);
+ } else if (value != null) {
+ result.append(value);
} else {
result.append(node.toString());
}
--- a/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHKeyAgreement.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHKeyAgreement.java Thu Jun 13 11:31:36 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -38,6 +38,7 @@
import javax.crypto.KeyAgreementSpi;
import javax.crypto.SecretKey;
import javax.crypto.ShortBufferException;
+import javax.crypto.spec.SecretKeySpec;
import java.util.function.Function;
public class XDHKeyAgreement extends KeyAgreementSpi {
@@ -202,7 +203,15 @@
throws IllegalStateException, NoSuchAlgorithmException,
InvalidKeyException {
- throw new NoSuchAlgorithmException("Not supported");
+ if (algorithm == null) {
+ throw new NoSuchAlgorithmException("Algorithm must not be null");
+ }
+
+ if (!(algorithm.equals("TlsPremasterSecret"))) {
+ throw new NoSuchAlgorithmException(
+ "Only supported for algorithm TlsPremasterSecret");
+ }
+ return new SecretKeySpec(engineGenerateSecret(), algorithm);
}
static class X25519 extends XDHKeyAgreement {
--- a/src/jdk.crypto.ec/share/classes/sun/security/ec/XECParameters.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/XECParameters.java Thu Jun 13 11:31:36 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -156,7 +156,7 @@
new XECParameters(bits, p, a24, basePoint, logCofactor, oid, name);
bySize.put(bits, params);
byOid.put(oid, params);
- byName.put(name, params);
+ byName.put(name.toLowerCase(), params);
}
public static Optional<XECParameters> getByOid(ObjectIdentifier id) {
@@ -166,7 +166,7 @@
return Optional.ofNullable(SIZE_MAP.get(size));
}
public static Optional<XECParameters> getByName(String name) {
- return Optional.ofNullable(NAME_MAP.get(name));
+ return Optional.ofNullable(NAME_MAP.get(name.toLowerCase()));
}
boolean oidEquals(XECParameters other) {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeFieldWriterImpl.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeFieldWriterImpl.java Thu Jun 13 11:31:36 2019 +0530
@@ -33,6 +33,7 @@
import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
import jdk.javadoc.internal.doclets.formats.html.markup.Table;
import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeFieldWriter;
@@ -104,9 +105,9 @@
if (!writer.printedAnnotationFieldHeading) {
Content heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING,
contents.fieldDetailsLabel);
- memberDetailsTree.add(heading);
memberDetailsTree.add(links.createAnchor(
SectionName.ANNOTATION_TYPE_FIELD_DETAIL));
+ memberDetailsTree.add(heading);
writer.printedAnnotationFieldHeading = true;
}
return memberDetailsTree;
@@ -119,9 +120,8 @@
Content annotationDetailsTree) {
Content annotationDocTree = new ContentBuilder();
Content heading = new HtmlTree(Headings.TypeDeclaration.MEMBER_HEADING);
- heading.add(name(member));
+ heading.add(links.createAnchor(name(member), new StringContent(name(member))));
annotationDocTree.add(heading);
- annotationDocTree.add(links.createAnchor(name(member)));
return HtmlTree.SECTION(HtmlStyle.detail, annotationDocTree);
}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java Thu Jun 13 11:31:36 2019 +0530
@@ -33,6 +33,7 @@
import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
import jdk.javadoc.internal.doclets.formats.html.markup.Table;
import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeRequiredMemberWriter;
@@ -106,9 +107,9 @@
if (!writer.printedAnnotationHeading) {
Content heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING,
contents.annotationTypeDetailsLabel);
- memberDetailsTree.add(heading);
memberDetailsTree.add(links.createAnchor(
SectionName.ANNOTATION_TYPE_ELEMENT_DETAIL));
+ memberDetailsTree.add(heading);
writer.printedAnnotationHeading = true;
}
return memberDetailsTree;
@@ -122,10 +123,9 @@
String simpleName = name(member);
Content annotationDocTree = new ContentBuilder();
Content heading = new HtmlTree(Headings.TypeDeclaration.MEMBER_HEADING);
- heading.add(simpleName);
+ heading.add(links.createAnchor(
+ simpleName + utils.signature((ExecutableElement) member), new StringContent(simpleName)));
annotationDocTree.add(heading);
- annotationDocTree.add(links.createAnchor(
- simpleName + utils.signature((ExecutableElement) member)));
return HtmlTree.SECTION(HtmlStyle.detail, annotationDocTree);
}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java Thu Jun 13 11:31:36 2019 +0530
@@ -37,6 +37,7 @@
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
import jdk.javadoc.internal.doclets.formats.html.markup.Table;
import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
import jdk.javadoc.internal.doclets.toolkit.ConstructorWriter;
@@ -122,9 +123,9 @@
Content constructorDetailsTree = new ContentBuilder();
Content heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING,
contents.constructorDetailsLabel);
- constructorDetailsTree.add(heading);
constructorDetailsTree.add(links.createAnchor(
SectionName.CONSTRUCTOR_DETAIL));
+ constructorDetailsTree.add(heading);
return constructorDetailsTree;
}
@@ -137,12 +138,11 @@
String erasureAnchor;
Content constructorDocTree = new ContentBuilder();
Content heading = new HtmlTree(Headings.TypeDeclaration.MEMBER_HEADING);
- heading.add(name(constructor));
+ if ((erasureAnchor = getErasureAnchor(constructor)) != null) {
+ heading.add(links.createAnchor((erasureAnchor)));
+ }
+ heading.add(links.createAnchor(writer.getAnchor(constructor), new StringContent(name(constructor))));
constructorDocTree.add(heading);
- if ((erasureAnchor = getErasureAnchor(constructor)) != null) {
- constructorDocTree.add(links.createAnchor((erasureAnchor)));
- }
- constructorDocTree.add(links.createAnchor(writer.getAnchor(constructor)));
return HtmlTree.SECTION(HtmlStyle.detail, constructorDocTree);
}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/EnumConstantWriterImpl.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/EnumConstantWriterImpl.java Thu Jun 13 11:31:36 2019 +0530
@@ -33,6 +33,7 @@
import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
import jdk.javadoc.internal.doclets.formats.html.markup.Table;
import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
import jdk.javadoc.internal.doclets.toolkit.Content;
@@ -91,9 +92,9 @@
Content enumConstantsDetailsTree = new ContentBuilder();
Content heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING,
contents.enumConstantDetailLabel);
- enumConstantsDetailsTree.add(heading);
enumConstantsDetailsTree.add(links.createAnchor(
SectionName.ENUM_CONSTANT_DETAIL));
+ enumConstantsDetailsTree.add(heading);
return enumConstantsDetailsTree;
}
@@ -105,9 +106,8 @@
Content enumConstantsDetailsTree) {
Content enumConstantsTree = new ContentBuilder();
Content heading = new HtmlTree(Headings.TypeDeclaration.MEMBER_HEADING);
- heading.add(name(enumConstant));
+ heading.add(links.createAnchor(name(enumConstant), new StringContent(name(enumConstant))));
enumConstantsTree.add(heading);
- enumConstantsTree.add(links.createAnchor(name(enumConstant)));
return HtmlTree.SECTION(HtmlStyle.detail, enumConstantsTree);
}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FieldWriterImpl.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FieldWriterImpl.java Thu Jun 13 11:31:36 2019 +0530
@@ -96,9 +96,9 @@
Content fieldDetailsTree = new ContentBuilder();
Content heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING,
contents.fieldDetailsLabel);
- fieldDetailsTree.add(heading);
fieldDetailsTree.add(links.createAnchor(
SectionName.FIELD_DETAIL));
+ fieldDetailsTree.add(heading);
return fieldDetailsTree;
}
@@ -109,9 +109,8 @@
public Content getFieldDocTreeHeader(VariableElement field, Content fieldDetailsTree) {
Content fieldTree = new ContentBuilder();
Content heading = new HtmlTree(Headings.TypeDeclaration.MEMBER_HEADING);
- heading.add(name(field));
+ heading.add(links.createAnchor(name(field), new StringContent(name(field))));
fieldTree.add(heading);
- fieldTree.add(links.createAnchor(name(field)));
return HtmlTree.SECTION(HtmlStyle.detail, fieldTree);
}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java Thu Jun 13 11:31:36 2019 +0530
@@ -109,8 +109,8 @@
Content methodDetailsTree = new ContentBuilder();
Content heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING,
contents.methodDetailLabel);
+ methodDetailsTree.add(links.createAnchor(SectionName.METHOD_DETAIL));
methodDetailsTree.add(heading);
- methodDetailsTree.add(links.createAnchor(SectionName.METHOD_DETAIL));
return methodDetailsTree;
}
@@ -122,12 +122,11 @@
String erasureAnchor;
Content methodDocTree = new ContentBuilder();
Content heading = new HtmlTree(Headings.TypeDeclaration.MEMBER_HEADING);
- heading.add(name(method));
+ if ((erasureAnchor = getErasureAnchor(method)) != null) {
+ heading.add(links.createAnchor((erasureAnchor)));
+ }
+ heading.add(links.createAnchor(writer.getAnchor(method), new StringContent(name(method))));
methodDocTree.add(heading);
- if ((erasureAnchor = getErasureAnchor(method)) != null) {
- methodDocTree.add(links.createAnchor((erasureAnchor)));
- }
- methodDocTree.add(links.createAnchor(writer.getAnchor(method)));
return HtmlTree.SECTION(HtmlStyle.detail, methodDocTree);
}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java Thu Jun 13 11:31:36 2019 +0530
@@ -89,8 +89,8 @@
Content propertyDetailsTree = new ContentBuilder();
Content heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING,
contents.propertyDetailsLabel);
+ propertyDetailsTree.add(links.createAnchor(SectionName.PROPERTY_DETAIL));
propertyDetailsTree.add(heading);
- propertyDetailsTree.add(links.createAnchor(SectionName.PROPERTY_DETAIL));
return propertyDetailsTree;
}
@@ -102,9 +102,9 @@
Content propertyDetailsTree) {
Content propertyDocTree = new ContentBuilder();
Content heading = new HtmlTree(Headings.TypeDeclaration.MEMBER_HEADING);
- heading.add(utils.getPropertyLabel(name(property)));
+ heading.add(links.createAnchor(name(property),
+ new StringContent(utils.getPropertyLabel(name(property)))));
propertyDocTree.add(heading);
- propertyDocTree.add(links.createAnchor(name(property)));
return HtmlTree.SECTION(HtmlStyle.detail, propertyDocTree);
}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Links.java Wed Jun 12 10:02:49 2019 +0530
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Links.java Thu Jun 13 11:31:36 2019 +0530
@@ -100,7 +100,7 @@
* @return a content tree for the marker anchor
*/
public Content createAnchor(String name, Content content) {
- return HtmlTree.A_ID(name, (content == null ? EMPTY_COMMENT : content));
+ return HtmlTree.A_ID(getName(name), (content == null ? EMPTY_COMMENT : content));
}
private static final Content EMPTY_COMMENT = new Comment(" ");
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css Wed Jun 12 10:02:49 2019 +0530
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css Thu Jun 13 11:31:36 2019 +0530
@@ -574,8 +574,7 @@
div.memberSignature {
font-family:'DejaVu Sans Mono', monospace;
font-size:14px;
- margin-top:6px;
- margin-bottom:14px;
+ margin:14px 0;
white-space: pre-wrap;
}
div.memberSignature span.annotations {
--- a/test/hotspot/jtreg/ProblemList-graal.txt Wed Jun 12 10:02:49 2019 +0530
+++ b/test/hotspot/jtreg/ProblemList-graal.txt Thu Jun 13 11:31:36 2019 +0530
@@ -38,7 +38,9 @@
compiler/compilercontrol/mixed/RandomValidCommandsTest.java 8181753 generic-all
compiler/compilercontrol/mixed/RandomCommandsTest.java 8181753 generic-all
-compiler/graalunit/HotspotJdk9Test.java 8224254 generic-all
+compiler/graalunit/HotspotJdk9Test.java 8223807 generic-all
+compiler/jsr292/InvokerSignatureMismatch.java 8223807 generic-all
+
compiler/graalunit/JttThreadsTest.java 8207757 generic-all
compiler/jvmci/SecurityRestrictionsTest.java 8181837 generic-all
@@ -234,7 +236,6 @@
vmTestbase/nsk/jdb/clear/clear003/clear003.java 8218701 generic-all
-compiler/jsr292/InvokerSignatureMismatch.java 8221577 generic-all
# Next tests should be re-enabled once libgraal is introduced
compiler/arguments/TestScavengeRootsInCode.java 8207267 generic-all
--- a/test/hotspot/jtreg/ProblemList.txt Wed Jun 12 10:02:49 2019 +0530
+++ b/test/hotspot/jtreg/ProblemList.txt Thu Jun 13 11:31:36 2019 +0530
@@ -49,8 +49,8 @@
compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java 8163894 generic-all
compiler/tiered/LevelTransitionTest.java 8067651 generic-all
-compiler/types/correctness/CorrectnessTest.java 8066173 solaris-sparcv9
-compiler/types/correctness/OffTest.java 8066173 solaris-sparcv9
+compiler/types/correctness/CorrectnessTest.java 8225620 solaris-sparcv9
+compiler/types/correctness/OffTest.java 8225620 solaris-sparcv9
compiler/c2/Test6852078.java 8194310 generic-all
compiler/c2/Test8004741.java 8214904 generic-all
@@ -59,9 +59,6 @@
compiler/runtime/Test8168712.java 8211769,8211771 generic-ppc64,generic-ppc64le,linux-s390x
-compiler/codegen/TestCharVect2.java 8224234 generic-x64
-compiler/c2/cr6340864/TestLongVect.java 8224234 generic-x64
-
applications/ctw/modules/java_desktop.java 8205016 windows-all
applications/ctw/modules/java_desktop_2.java 8205016 windows-all
applications/ctw/modules/jdk_jconsole.java 8205016 windows-all
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/unsafe/TestUnsafeLoadWithZeroAddress.java Thu Jun 13 11:31:36 2019 +0530
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2019, 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 8224658
+ * @summary Test compilation of unsafe access with zero address.
+ * @modules java.base/jdk.internal.misc:+open
+ * @run main/othervm -Xcomp
+ * -XX:CompileCommand=compileonly,compiler.unsafe.TestUnsafeLoadWithZeroAddress::*
+ * compiler.unsafe.TestUnsafeLoadWithZeroAddress
+ * @run main/othervm -Xcomp -XX:+IgnoreUnrecognizedVMOptions -XX:+AlwaysIncrementalInline
+ * -XX:CompileCommand=compileonly,compiler.unsafe.TestUnsafeLoadWithZeroAddress::*
+ * compiler.unsafe.TestUnsafeLoadWithZeroAddress
+ */
+
+package compiler.unsafe;
+
+import jdk.internal.misc.Unsafe;
+
+public class TestUnsafeLoadWithZeroAddress {
+ static final Unsafe UNSAFE = Unsafe.getUnsafe();
+ static boolean f;
+
+ public static void test1() {
+ if (f) {
+ // This branch is never executed but compiled due to -Xcomp
+ UNSAFE.getInt(0);
+ }
+ }
+
+ public static void test2() {
+ if (f) {
+ // This branch is never executed but compiled due to -Xcomp
+ UNSAFE.putInt(0, 0);
+ }
+ }
+
+ private static int getAddress() {
+ return 0;
+ }
+
+ public static void test3() {
+ if (f) {
+ // This branch is never executed but compiled due to -Xcomp
+ UNSAFE.getInt(getAddress());
+ }
+ }
+
+ public static void test4() {
+ if (f) {
+ // This branch is never executed but compiled due to -Xcomp
+ UNSAFE.putInt(getAddress(), 0);
+ }
+ }
+
+ static public void main(String[] args) {
+ test1();
+ test2();
+ test3();
+ test4();
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gtest/GTestResultParser.java Thu Jun 13 11:31:36 2019 +0530
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class GTestResultParser {
+ private final List<String> _failedTests;
+
+ public GTestResultParser(Path file) {
+ List<String> failedTests = new ArrayList<>();
+ try (Reader r = Files.newBufferedReader(file)) {
+ try {
+ XMLStreamReader xmlReader = XMLInputFactory.newInstance()
+ .createXMLStreamReader(r);
+ String testSuite = null;
+ String testCase = null;
+ while (xmlReader.hasNext()) {
+ switch (xmlReader.next()) {
+ case XMLStreamConstants.START_ELEMENT:
+ switch (xmlReader.getLocalName()) {
+ case "testsuite":
+ testSuite = xmlReader.getAttributeValue("", "name");
+ break;
+ case "testcase":
+ testCase = xmlReader.getAttributeValue("", "name");
+ break;
+ case "failure":
+ failedTests.add(testSuite + "::" + testCase);
+ default:
+ // ignore
+ }
+ break;
+ default:
+ // ignore
+ }
+ }
+ } catch (XMLStreamException e) {
+ throw new IllegalArgumentException("can't open parse xml " + file, e);
+ }
+ } catch (IOException e) {
+ throw new IllegalArgumentException("can't open result file " + file, e);
+ }
+ _failedTests = Collections.unmodifiableList(failedTests);
+ }
+
+ public List<String> failedTests() {
+ return _failedTests;
+ }
+}
--- a/test/hotspot/jtreg/gtest/GTestWrapper.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/hotspot/jtreg/gtest/GTestWrapper.java Thu Jun 13 11:31:36 2019 +0530
@@ -25,23 +25,21 @@
* @summary a jtreg wrapper for gtest tests
* @library /test/lib
* @modules java.base/jdk.internal.misc
+ * java.xml
* @run main/native GTestWrapper
*/
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Stream;
-import java.util.stream.Collectors;
-
-import java.io.File;
-import java.nio.file.Paths;
-import java.nio.file.Path;
-
import jdk.test.lib.Platform;
import jdk.test.lib.Utils;
import jdk.test.lib.process.ProcessTools;
-import jdk.test.lib.process.OutputAnalyzer;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
public class GTestWrapper {
public static void main(String[] args) throws Throwable {
@@ -76,12 +74,33 @@
env.put(pathVar, path + File.pathSeparator + ldLibraryPath);
}
- pb.command(new String[] {
- execPath.toString(),
- "-jdk",
- System.getProperty("test.jdk")
- });
- ProcessTools.executeCommand(pb).shouldHaveExitValue(0);
+ Path resultFile = Paths.get("test_result.xml");
+ pb.command(execPath.toAbsolutePath().toString(),
+ "-jdk", Utils.TEST_JDK,
+ "--gtest_output=xml:" + resultFile);
+ int exitCode = ProcessTools.executeCommand(pb).getExitValue();
+ if (exitCode != 0) {
+ List<String> failedTests = failedTests(resultFile);
+ String message = "gtest execution failed; exit code = " + exitCode + ".";
+ if (!failedTests.isEmpty()) {
+ message += " the failed tests: " + failedTests;
+ }
+ throw new AssertionError(message);
+ }
+ }
+
+ private static List<String> failedTests(Path xml) {
+ if (!Files.exists(xml)) {
+ System.err.println("WARNING: test result file (" + xml + ") hasn't been found");
+ }
+
+ try {
+ return new GTestResultParser(xml).failedTests();
+ } catch (Throwable t) {
+ System.err.println("WARNING: failed to parse result file (" + xml + ") " + t);
+ t.printStackTrace();
+ }
+ return Collections.emptyList();
}
private static String getJVMVariantSubDir() {
--- a/test/hotspot/jtreg/runtime/SharedArchiveFile/TestInterpreterMethodEntries.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/hotspot/jtreg/runtime/SharedArchiveFile/TestInterpreterMethodEntries.java Thu Jun 13 11:31:36 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,12 +25,26 @@
* @test InterpreterMethodEntries
* @bug 8169711
* @summary Test interpreter method entries for intrinsics with CDS (class data sharing)
- * and different settings of the intrinsic flag during dump/use of the archive.
+ * and the intrinsic flag enabled during dump and disabled during use of the archive.
+ * @requires vm.cds
+ * @comment the test disables intrinsics, so it can't be run w/ AOT'ed java module
+ * @requires !vm.aot.enabled
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * java.management
+ * @run driver TestInterpreterMethodEntries true false
+ */
+
+/**
+ * @test InterpreterMethodEntries
+ * @bug 8169711
+ * @summary Test interpreter method entries for intrinsics with CDS (class data sharing)
+ * and the intrinsic flag disabled during dump and enabled during use of the archive.
* @requires vm.cds
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
- * @run driver TestInterpreterMethodEntries
+ * @run driver TestInterpreterMethodEntries false true
*/
import java.lang.Math;
@@ -43,10 +57,12 @@
public class TestInterpreterMethodEntries {
public static void main(String[] args) throws Exception {
- if (args.length == 0) {
+ if (args.length > 1) {
+ boolean dump = Boolean.parseBoolean(args[0]);
+ boolean use = Boolean.parseBoolean(args[1]);
+
// Dump and use shared archive with different flag combinations
- dumpAndUseSharedArchive("+", "-");
- dumpAndUseSharedArchive("-", "+");
+ dumpAndUseSharedArchive(dump ? "+" : "-", use ? "+" : "-");
} else {
// Call intrinsified java.lang.Math::fma()
Math.fma(1.0, 2.0, 3.0);
--- a/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack001.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack001.java Thu Jun 13 11:31:36 2019 +0530
@@ -52,7 +52,7 @@
* 4302288 the second stack overflow causes Classic VM to exit on win32
*
* @requires vm.opt.DeoptimizeALot != true
- * @run main/othervm nsk.stress.stack.stack001
+ * @run main/othervm/timeout=900 nsk.stress.stack.stack001
*/
package nsk.stress.stack;
--- a/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack002.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack002.java Thu Jun 13 11:31:36 2019 +0530
@@ -53,7 +53,7 @@
* 4302288 the second stack overflow causes Classic VM to exit on win32
*
* @requires vm.opt.DeoptimizeALot != true
- * @run main/othervm nsk.stress.stack.stack002
+ * @run main/othervm/timeout=900 nsk.stress.stack.stack002
*/
package nsk.stress.stack;
--- a/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack003.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack003.java Thu Jun 13 11:31:36 2019 +0530
@@ -47,7 +47,7 @@
* 4366625 (P4/S4) multiple stack overflow causes HS crash
*
* @requires vm.opt.DeoptimizeALot != true
- * @run main/othervm nsk.stress.stack.stack003
+ * @run main/othervm/timeout=900 nsk.stress.stack.stack003
*/
package nsk.stress.stack;
--- a/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack004.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack004.java Thu Jun 13 11:31:36 2019 +0530
@@ -47,7 +47,7 @@
* 4366625 (P4/S4) multiple stack overflow causes HS crash
*
* @requires vm.opt.DeoptimizeALot != true
- * @run main/othervm nsk.stress.stack.stack004
+ * @run main/othervm/timeout=900 nsk.stress.stack.stack004
*/
package nsk.stress.stack;
--- a/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack005.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack005.java Thu Jun 13 11:31:36 2019 +0530
@@ -47,7 +47,7 @@
* 4366625 (P4/S4) multiple stack overflow causes HS crash
*
* @requires vm.opt.DeoptimizeALot != true
- * @run main/othervm nsk.stress.stack.stack005
+ * @run main/othervm/timeout=900 nsk.stress.stack.stack005
*/
package nsk.stress.stack;
--- a/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack006.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack006.java Thu Jun 13 11:31:36 2019 +0530
@@ -47,7 +47,7 @@
* 4366625 (P4/S4) multiple stack overflow causes HS crash
*
* @requires vm.opt.DeoptimizeALot != true
- * @run main/othervm nsk.stress.stack.stack006
+ * @run main/othervm/timeout=900 nsk.stress.stack.stack006
*/
package nsk.stress.stack;
--- a/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack007.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack007.java Thu Jun 13 11:31:36 2019 +0530
@@ -46,7 +46,7 @@
* 4366625 (P4/S4) multiple stack overflow causes HS crash
*
* @requires vm.opt.DeoptimizeALot != true
- * @run main/othervm nsk.stress.stack.stack007
+ * @run main/othervm/timeout=900 nsk.stress.stack.stack007
*/
package nsk.stress.stack;
--- a/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack008.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack008.java Thu Jun 13 11:31:36 2019 +0530
@@ -48,7 +48,7 @@
*
* @ignore 8139875
* @requires vm.opt.DeoptimizeALot != true
- * @run main/othervm nsk.stress.stack.stack008
+ * @run main/othervm/timeout=900 nsk.stress.stack.stack008
*/
package nsk.stress.stack;
--- a/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack009.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack009.java Thu Jun 13 11:31:36 2019 +0530
@@ -47,7 +47,7 @@
* 4366625 (P4/S4) multiple stack overflow causes HS crash
*
* @requires vm.opt.DeoptimizeALot != true
- * @run main/othervm nsk.stress.stack.stack009
+ * @run main/othervm/timeout=900 nsk.stress.stack.stack009
*/
package nsk.stress.stack;
--- a/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack010.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack010.java Thu Jun 13 11:31:36 2019 +0530
@@ -47,7 +47,7 @@
* 4366625 (P4/S4) multiple stack overflow causes HS crash
*
* @requires vm.opt.DeoptimizeALot != true
- * @run main/othervm nsk.stress.stack.stack010
+ * @run main/othervm/timeout=900 nsk.stress.stack.stack010
*/
package nsk.stress.stack;
--- a/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack011.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack011.java Thu Jun 13 11:31:36 2019 +0530
@@ -47,7 +47,7 @@
* 4366625 (P4/S4) multiple stack overflow causes HS crash
*
* @requires vm.opt.DeoptimizeALot != true
- * @run main/othervm nsk.stress.stack.stack011
+ * @run main/othervm/timeout=900 nsk.stress.stack.stack011
*/
package nsk.stress.stack;
--- a/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack012.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack012.java Thu Jun 13 11:31:36 2019 +0530
@@ -48,7 +48,7 @@
* 4366625 (P4/S4) multiple stack overflow causes HS crash
*
* @requires vm.opt.DeoptimizeALot != true
- * @run main/othervm nsk.stress.stack.stack012
+ * @run main/othervm/timeout=900 nsk.stress.stack.stack012
*/
package nsk.stress.stack;
--- a/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack013.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack013.java Thu Jun 13 11:31:36 2019 +0530
@@ -47,7 +47,7 @@
* 4366625 (P4/S4) multiple stack overflow causes HS crash
*
* @requires vm.opt.DeoptimizeALot != true
- * @run main/othervm nsk.stress.stack.stack013
+ * @run main/othervm/timeout=900 nsk.stress.stack.stack013
*/
package nsk.stress.stack;
--- a/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack014.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack014.java Thu Jun 13 11:31:36 2019 +0530
@@ -50,7 +50,7 @@
* 4366625 (P4/S4) multiple stack overflow causes HS crash
*
* @requires vm.opt.DeoptimizeALot != true
- * @run main/othervm nsk.stress.stack.stack014
+ * @run main/othervm/timeout=900 nsk.stress.stack.stack014
*/
package nsk.stress.stack;
--- a/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack015.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack015.java Thu Jun 13 11:31:36 2019 +0530
@@ -48,7 +48,7 @@
* 4366625 (P4/S4) multiple stack overflow causes HS crash
*
* @requires vm.opt.DeoptimizeALot != true
- * @run main/othervm nsk.stress.stack.stack015
+ * @run main/othervm/timeout=900 nsk.stress.stack.stack015
*/
package nsk.stress.stack;
--- a/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack016.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack016.java Thu Jun 13 11:31:36 2019 +0530
@@ -51,7 +51,7 @@
*
* @ignore 8139875
* @requires vm.opt.DeoptimizeALot != true
- * @run main/othervm nsk.stress.stack.stack016 -eager
+ * @run main/othervm/timeout=900 nsk.stress.stack.stack016 -eager
*/
package nsk.stress.stack;
--- a/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack017.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack017.java Thu Jun 13 11:31:36 2019 +0530
@@ -44,7 +44,7 @@
*
* @ignore 8139875
* @requires vm.opt.DeoptimizeALot != true
- * @run main/othervm nsk.stress.stack.stack017 -eager
+ * @run main/othervm/timeout=900 nsk.stress.stack.stack017 -eager
*/
package nsk.stress.stack;
--- a/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack018.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack018.java Thu Jun 13 11:31:36 2019 +0530
@@ -49,7 +49,7 @@
*
* @ignore 8139875
* @requires vm.opt.DeoptimizeALot != true
- * @run main/othervm nsk.stress.stack.stack018 -eager
+ * @run main/othervm/timeout=900 nsk.stress.stack.stack018 -eager
*/
package nsk.stress.stack;
--- a/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack019.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack019.java Thu Jun 13 11:31:36 2019 +0530
@@ -42,7 +42,7 @@
*
* @ignore 8139875
* @requires vm.opt.DeoptimizeALot != true
- * @run main/othervm nsk.stress.stack.stack019 -eager
+ * @run main/othervm/timeout=900 nsk.stress.stack.stack019 -eager
*/
package nsk.stress.stack;
--- a/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java Thu Jun 13 11:31:36 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, 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
@@ -189,10 +189,15 @@
}
/*
+ * Configure the client side socket.
+ */
+ protected void configureClientSocket(SSLSocket socket) {
+ }
+
+ /*
* Configure the server side socket.
*/
protected void configureServerSocket(SSLServerSocket socket) {
-
}
/*
@@ -317,6 +322,7 @@
try (SSLSocket sslSocket = (SSLSocket)sslsf.createSocket()) {
try {
+ configureClientSocket(sslSocket);
sslSocket.connect(
new InetSocketAddress("localhost", serverPort), 15000);
} catch (IOException ioe) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/ssl/CipherSuite/SupportedGroups.java Thu Jun 13 11:31:36 2019 +0530
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2019, 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 8171279
+ * @library /javax/net/ssl/templates
+ * @summary Test TLS connection with each individual supported group
+ * @run main/othervm SupportedGroups x25519
+ * @run main/othervm SupportedGroups x448
+ * @run main/othervm SupportedGroups secp256r1
+ * @run main/othervm SupportedGroups secp384r1
+ * @run main/othervm SupportedGroups secp521r1
+ * @run main/othervm SupportedGroups ffdhe2048
+ * @run main/othervm SupportedGroups ffdhe3072
+ * @run main/othervm SupportedGroups ffdhe4096
+ * @run main/othervm SupportedGroups ffdhe6144
+ * @run main/othervm SupportedGroups ffdhe8192
+ */
+import java.util.Arrays;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLServerSocket;
+
+public class SupportedGroups extends SSLSocketTemplate {
+
+ private static volatile int index;
+ private static final String[][][] protocols = {
+ {{"TLSv1.3"}, {"TLSv1.3"}},
+ {{"TLSv1.3", "TLSv1.2"}, {"TLSv1.2"}},
+ {{"TLSv1.2"}, {"TLSv1.3", "TLSv1.2"}},
+ {{"TLSv1.2"}, {"TLSv1.2"}}
+ };
+
+ // Servers are configured before clients, increment test case after.
+ @Override
+ protected void configureClientSocket(SSLSocket socket) {
+ String[] ps = protocols[index][0];
+
+ System.out.print("Setting client protocol(s): ");
+ Arrays.stream(ps).forEachOrdered(System.out::print);
+ System.out.println();
+
+ socket.setEnabledProtocols(ps);
+ }
+
+ @Override
+ protected void configureServerSocket(SSLServerSocket serverSocket) {
+ String[] ps = protocols[index][1];
+
+ System.out.print("Setting server protocol(s): ");
+ Arrays.stream(ps).forEachOrdered(System.out::print);
+ System.out.println();
+
+ serverSocket.setEnabledProtocols(ps);
+ }
+
+ /*
+ * Run the test case.
+ */
+ public static void main(String[] args) throws Exception {
+ System.setProperty("jdk.tls.namedGroups", args[0]);
+
+ for (index = 0; index < protocols.length; index++) {
+ (new SupportedGroups()).run();
+ }
+ }
+}
--- a/test/langtools/jdk/javadoc/doclet/testAnnotationTypes/TestAnnotationTypes.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/langtools/jdk/javadoc/doclet/testAnnotationTypes/TestAnnotationTypes.java Thu Jun 13 11:31:36 2019 +0530
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 4973609 8015249 8025633 8026567 6469561 8071982 8162363 8182765
+ * @bug 4973609 8015249 8025633 8026567 6469561 8071982 8162363 8182765 8223364
* @summary Make sure that annotation types with 0 members does not have
* extra HR tags.
* @author jamieh
@@ -61,10 +61,7 @@
"<th class=\"colSecond\" scope=\"row\"><code><span class=\"memberNameLink\"><a href=\"#DEFAULT_NAME\">DEFAULT_NAME</a></span>"
+ "</code></th>",
"<!-- ============ ANNOTATION TYPE FIELD DETAIL =========== -->",
- "<h3>DEFAULT_NAME</h3>\n"
- + "<a id=\"DEFAULT_NAME\">\n"
- + "<!-- -->\n"
- + "</a>\n"
+ "<h3><a id=\"DEFAULT_NAME\">DEFAULT_NAME</a></h3>\n"
+ "<div class=\"memberSignature\"><span class=\"modifiers\">static final</span> "
+ "<span class=\"returnType\">java.lang.String</span> "
+ "<span class=\"memberName\">DEFAULT_NAME</span></div>\n");
@@ -87,10 +84,7 @@
"<ul class=\"blockList\">",
"<li class=\"blockList\">",
"<section class=\"detail\">",
- "<h3>value</h3>",
- "<a id=\"value()\">",
- "<!-- -->",
- "</a>",
+ "<h3><a id=\"value()\">value</a></h3>",
"<div class=\"memberSignature\"><span class=\"returnType\">int</span>"
+ " <span class=\"memberName\">value</span></div>");
--- a/test/langtools/jdk/javadoc/doclet/testHref/TestHref.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/langtools/jdk/javadoc/doclet/testHref/TestHref.java Thu Jun 13 11:31:36 2019 +0530
@@ -57,13 +57,9 @@
//Member summary table link.
"href=\"#method(int,int,java.util.ArrayList)\"",
//Anchor test.
- "<a id=\"method(int,int,java.util.ArrayList)\">\n"
- + "<!-- -->\n"
- + "</a>",
+ "<a id=\"method(int,int,java.util.ArrayList)\">",
//Backward compatibility anchor test."pkg/C1.html",
- "<a id=\"method(int,int,java.util.ArrayList)\">\n"
- + "<!-- -->\n"
- + "</a>");
+ "<a id=\"method(int,int,java.util.ArrayList)\">");
checkOutput("pkg/C2.html", true,
//{@link} test.
--- a/test/langtools/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/langtools/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java Thu Jun 13 11:31:36 2019 +0530
@@ -323,21 +323,21 @@
+ "<!-- -->\n"
+ "</a>\n"
+ "<h2>Method Summary</h2>",
- "<section class=\"fieldDetails\">\n"
- + "<h2>Field Details</h2>\n"
+ "<section class=\"fieldDetails\">"
+ "<a id=\"field.detail\">\n"
+ "<!-- -->\n"
- + "</a>",
- "<section class=\"constructorDetails\">\n"
- + "<h2>Constructor Details</h2>\n"
+ + "</a>\n"
+ + "<h2>Field Details</h2>\n",
+ "<section class=\"constructorDetails\">"
+ "<a id=\"constructor.detail\">\n"
+ "<!-- -->\n"
- + "</a>",
- "<section class=\"methodDetails\">\n"
- + "<h2>Method Details</h2>\n"
+ + "</a>\n"
+ + "<h2>Constructor Details</h2>\n",
+ "<section class=\"methodDetails\">"
+ "<a id=\"method.detail\">\n"
+ "<!-- -->\n"
- + "</a>",
+ + "</a>\n"
+ + "<h2>Method Details</h2>\n",
"<footer role=\"contentinfo\">\n"
+ "<nav role=\"navigation\">\n"
+ "<!-- ======= START OF BOTTOM NAVBAR ====== -->");
@@ -367,16 +367,16 @@
+ "<h2>Method Summary</h2>\n"
+ "<div class=\"memberSummary\">\n",
"<table aria-labelledby=\"t0\">",
- "<section class=\"constantDetails\">\n"
- + "<h2>Enum Constant Details</h2>\n"
+ "<section class=\"constantDetails\">"
+ "<a id=\"enum.constant.detail\">\n"
+ "<!-- -->\n"
- + "</a>\n",
- "<section class=\"methodDetails\">\n"
- + "<h2>Method Details</h2>\n"
+ + "</a>\n"
+ + "<h2>Enum Constant Details</h2>\n",
+ "<section class=\"methodDetails\">"
+ "<a id=\"method.detail\">\n"
+ "<!-- -->\n"
- + "</a>\n",
+ + "</a>\n"
+ + "<h2>Method Details</h2>\n",
"<footer role=\"contentinfo\">\n"
+ "<nav role=\"navigation\">\n"
+ "<!-- ======= START OF BOTTOM NAVBAR ====== -->");
@@ -400,11 +400,11 @@
+ "<h2>Method Summary</h2>\n"
+ "<div class=\"memberSummary\">\n",
"<table aria-labelledby=\"t0\">\n",
- "<section class=\"methodDetails\">\n"
- + "<h2>Method Details</h2>\n"
+ "<section class=\"methodDetails\">"
+ "<a id=\"method.detail\">\n"
+ "<!-- -->\n"
- + "</a>\n",
+ + "</a>\n"
+ + "<h2>Method Details</h2>\n",
"<footer role=\"contentinfo\">\n"
+ "<nav role=\"navigation\">\n"
+ "<!-- ======= START OF BOTTOM NAVBAR ====== -->");
@@ -426,11 +426,11 @@
+ "<!-- -->\n"
+ "</a>\n"
+ "<h2>Constructor Summary</h2>",
- "<section class=\"constructorDetails\">\n"
- + "<h2>Constructor Details</h2>\n"
+ "<section class=\"constructorDetails\">"
+ "<a id=\"constructor.detail\">\n"
+ "<!-- -->\n"
- + "</a>\n",
+ + "</a>\n"
+ + "<h2>Constructor Details</h2>\n",
"<footer role=\"contentinfo\">\n"
+ "<nav role=\"navigation\">\n"
+ "<!-- ======= START OF BOTTOM NAVBAR ====== -->");
@@ -452,11 +452,11 @@
+ "<!-- -->\n"
+ "</a>\n"
+ "<h2>Constructor Summary</h2>",
- "<section class=\"constructorDetails\">\n"
- + "<h2>Constructor Details</h2>\n"
+ "<section class=\"constructorDetails\">"
+ "<a id=\"constructor.detail\">\n"
+ "<!-- -->\n"
- + "</a>\n",
+ + "</a>\n"
+ + "<h2>Constructor Details</h2>\n",
"<footer role=\"contentinfo\">\n"
+ "<nav role=\"navigation\">\n"
+ "<!-- ======= START OF BOTTOM NAVBAR ====== -->");
@@ -484,11 +484,11 @@
+ "</a>\n"
+ "<h2>Optional Element Summary</h2>\n"
+ "<div class=\"memberSummary\">\n<table>",
- "<section class=\"memberDetails\">\n"
- + "<h2>Element Details</h2>\n"
+ "<section class=\"memberDetails\">"
+ "<a id=\"annotation.type.element.detail\">\n"
+ "<!-- -->\n"
- + "</a>\n",
+ + "</a>\n"
+ + "<h2>Element Details</h2>",
"<footer role=\"contentinfo\">\n"
+ "<nav role=\"navigation\">\n"
+ "<!-- ======= START OF BOTTOM NAVBAR ====== -->");
--- a/test/langtools/jdk/javadoc/doclet/testInterface/TestInterface.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/langtools/jdk/javadoc/doclet/testInterface/TestInterface.java Thu Jun 13 11:31:36 2019 +0530
@@ -124,10 +124,7 @@
"<dt><span class=\"overrideSpecifyLabel\">Specified by:</span></dt>\n");
checkOutput("pkg/ClassWithStaticMembers.html", true,
- "<h3>f</h3>\n"
- + "<a id=\"f\">\n"
- + "<!-- -->\n"
- + "</a>\n"
+ "<h3><a id=\"f\">f</a></h3>\n"
+ "<div class=\"memberSignature\"><span class=\"modifiers\">public static</span> "
+ "<span class=\"returnType\">int</span> <span class=\"memberName\">f</span></div>\n"
+ "<div class=\"block\">A hider field</div>",
@@ -139,10 +136,7 @@
+ "<div class=\"block\">A hider method</div>\n"
+ "</td>\n",
- "<h3>staticMethod</h3>\n"
- + "<a id=\"staticMethod()\">\n"
- + "<!-- -->\n"
- + "</a>\n"
+ "<h3><a id=\"staticMethod()\">staticMethod</a></h3>\n"
+ "<div class=\"memberSignature\"><span class=\"modifiers\">public static</span> "
+ "<span class=\"returnType\">void</span> <span class=\"memberName\">staticMethod</span>()</div>\n"
+ "<div class=\"block\"><span class=\"descfrmTypeLabel\">"
--- a/test/langtools/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/langtools/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java Thu Jun 13 11:31:36 2019 +0530
@@ -89,25 +89,16 @@
+ "<a href=\"#pausedProperty\">paused</a></span></code></th>\n"
+ "<td class=\"colLast\">\n"
+ "<div class=\"block\">Defines if paused.</div>",
- "<h3>paused</h3>\n"
- + "<a id=\"pausedProperty\">\n"
- + "<!-- -->\n"
- + "</a>\n"
+ "<h3><a id=\"pausedProperty\">paused</a></h3>\n"
+ "<div class=\"memberSignature\"><span class=\"modifiers\">public final</span> "
+ "<span class=\"returnType\"><a href=\"C.BooleanProperty.html\" title=\"class in pkg1\">"
+ "C.BooleanProperty</a></span> <span class=\"memberName\">pausedProperty</span></div>\n"
+ "<div class=\"block\">Defines if paused. The second line.</div>",
- "<h3>isPaused</h3>\n"
- + "<a id=\"isPaused()\">\n"
- + "<!-- -->\n"
- + "</a>\n"
+ "<h3><a id=\"isPaused()\">isPaused</a></h3>\n"
+ "<div class=\"memberSignature\"><span class=\"modifiers\">public final</span> "
+ "<span class=\"returnType\">double</span> <span class=\"memberName\">isPaused</span>()</div>\n"
+ "<div class=\"block\">Gets the value of the property paused.</div>",
- "<h3>setPaused</h3>\n"
- + "<a id=\"setPaused(boolean)\">\n"
- + "<!-- -->\n"
- + "</a>\n"
+ "<h3><a id=\"setPaused(boolean)\">setPaused</a></h3>\n"
+ "<div class=\"memberSignature\"><span class=\"modifiers\">public final</span> "
+ "<span class=\"returnType\">void</span> <span class=\"memberName\">setPaused</span>​"
+ "(<span class=\"arguments\">boolean value)</span></div>\n"
@@ -117,10 +108,7 @@
+ "<dd>Defines if paused. The second line.</dd>\n"
+ "<dt><span class=\"simpleTagLabel\">Default value:</span></dt>\n"
+ "<dd>false</dd>",
- "<h3>isPaused</h3>\n"
- + "<a id=\"isPaused()\">\n"
- + "<!-- -->\n"
- + "</a>\n"
+ "<h3><a id=\"isPaused()\">isPaused</a></h3>\n"
+ "<div class=\"memberSignature\"><span class=\"modifiers\">public final</span> "
+ "<span class=\"returnType\">double</span> <span class=\"memberName\">isPaused</span>()</div>\n"
+ "<div class=\"block\">Gets the value of the property paused.</div>\n"
@@ -129,20 +117,14 @@
+ "<dd>Defines if paused. The second line.</dd>\n"
+ "<dt><span class=\"simpleTagLabel\">Default value:</span></dt>\n"
+ "<dd>false</dd>",
- "<h3>rate</h3>\n"
- + "<a id=\"rateProperty\">\n"
- + "<!-- -->\n"
- + "</a>\n"
+ "<h3><a id=\"rateProperty\">rate</a></h3>\n"
+ "<div class=\"memberSignature\"><span class=\"modifiers\">public final</span> "
+ "<span class=\"returnType\"><a href=\"C.DoubleProperty.html\" title=\"class in pkg1\">"
+ "C.DoubleProperty</a></span> <span class=\"memberName\">rateProperty</span></div>\n"
+ "<div class=\"block\">Defines the direction/speed at which the "
+ "<code>Timeline</code> is expected to\n"
+ " be played. This is the second line.</div>",
- "<h3>setRate</h3>\n"
- + "<a id=\"setRate(double)\">\n"
- + "<!-- -->\n"
- + "</a>\n"
+ "<h3><a id=\"setRate(double)\">setRate</a></h3>\n"
+ "<div class=\"memberSignature\"><span class=\"modifiers\">public final</span> "
+ "<span class=\"returnType\">void</span> <span class=\"memberName\">setRate</span>​"
+ "(<span class=\"arguments\">double value)</span></div>\n"
@@ -155,10 +137,7 @@
+ "<dd>11</dd>\n"
+ "<dt><span class=\"simpleTagLabel\">Since:</span></dt>\n"
+ "<dd>JavaFX 8.0</dd>",
- "<h3>getRate</h3>\n"
- + "<a id=\"getRate()\">\n"
- + "<!-- -->\n"
- + "</a>\n"
+ "<h3><a id=\"getRate()\">getRate</a></h3>\n"
+ "<div class=\"memberSignature\"><span class=\"modifiers\">public final</span> "
+ "<span class=\"returnType\">double</span> <span class=\"memberName\">getRate</span>()</div>\n"
+ "<div class=\"block\">Gets the value of the property rate.</div>\n"
@@ -225,17 +204,14 @@
"pkg2");
checkExit(Exit.OK);
checkOutput("pkg2/Test.html", true,
- "<h2>Property Details</h2>\n"
- + "<a id=\"property.detail\">\n"
+ "<a id=\"property.detail\">\n"
+ "<!-- -->\n"
+ "</a>\n"
+ + "<h2>Property Details</h2>\n"
+ "<ul class=\"blockList\">\n"
+ "<li class=\"blockList\">\n"
+ "<section class=\"detail\">\n"
- + "<h3>beta</h3>\n"
- + "<a id=\"betaProperty\">\n"
- + "<!-- -->\n"
- + "</a>\n"
+ + "<h3><a id=\"betaProperty\">beta</a></h3>\n"
+ "<div class=\"memberSignature\"><span class=\"modifiers\">public</span> "
+ "<span class=\"returnType\">java.lang.Object</span>"
+ " <span class=\"memberName\">betaProperty</span></div>\n"
@@ -243,10 +219,7 @@
+ "</li>\n"
+ "<li class=\"blockList\">\n"
+ "<section class=\"detail\">\n"
- + "<h3>gamma</h3>\n"
- + "<a id=\"gammaProperty\">\n"
- + "<!-- -->\n"
- + "</a>\n"
+ + "<h3><a id=\"gammaProperty\">gamma</a></h3>\n"
+ "<div class=\"memberSignature\"><span class=\"modifiers\">public final</span> "
+ "<span class=\"returnType\">java.util.List<java.lang.String></span>"
+ " <span class=\"memberName\">gammaProperty</span></div>\n"
@@ -254,10 +227,7 @@
+ "</li>\n"
+ "<li class=\"blockList\">\n"
+ "<section class=\"detail\">\n"
- + "<h3>delta</h3>\n"
- + "<a id=\"deltaProperty\">\n"
- + "<!-- -->\n"
- + "</a>\n"
+ + "<h3><a id=\"deltaProperty\">delta</a></h3>\n"
+ "<div class=\"memberSignature\"><span class=\"modifiers\">public final</span> "
+ "<span class=\"returnType\">java.util.List<java.util.Set<? super java.lang.Object>>"
+ "</span> <span class=\"memberName\">deltaProperty</span></div>\n"
--- a/test/langtools/jdk/javadoc/doclet/testMemberSummary/TestMemberSummary.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/langtools/jdk/javadoc/doclet/testMemberSummary/TestMemberSummary.java Thu Jun 13 11:31:36 2019 +0530
@@ -73,8 +73,6 @@
checkOutput("pkg2/A.html", true,
"<a id=\"f(java.lang.Object[])\">\n"
+ "<!-- -->\n"
- + "</a><a id=\"f(T[])\">\n"
- + "<!-- -->\n"
- + "</a>");
+ + "</a><a id=\"f(T[])\">f</a>");
}
}
--- a/test/langtools/jdk/javadoc/doclet/testOptions/TestOptions.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/langtools/jdk/javadoc/doclet/testOptions/TestOptions.java Thu Jun 13 11:31:36 2019 +0530
@@ -193,17 +193,11 @@
"<pre>@Documented\npublic @interface <a href="
+ "\"../src-html/linksource/AnnotationTypeField.html#line.31\">"
+ "AnnotationTypeField</a></pre>",
- "<h3>DEFAULT_NAME</h3>\n"
- + "<a id=\"DEFAULT_NAME\">\n"
- + "<!-- -->\n"
- + "</a>\n"
+ "<h3><a id=\"DEFAULT_NAME\">DEFAULT_NAME</a></h3>\n"
+ "<div class=\"memberSignature\"><span class=\"modifiers\">static final</span> "
+ "<span class=\"returnType\">java.lang.String</span> <span class=\"memberName\">"
+ "<a href=\"../src-html/linksource/AnnotationTypeField.html#line.32\">DEFAULT_NAME</a></span></div>",
- "<h3>name</h3>\n"
- + "<a id=\"name()\">\n"
- + "<!-- -->\n"
- + "</a>\n"
+ "<h3><a id=\"name()\">name</a></h3>\n"
+ "<div class=\"memberSignature\"><span class=\"returnType\">java.lang.String</span> "
+ "<span class=\"memberName\"><a href=\"../src-html/linksource/AnnotationTypeField.html#line.34\">"
+ "name</a></span></div>");
--- a/test/langtools/jdk/javadoc/doclet/testOrdering/TestOrdering.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/langtools/jdk/javadoc/doclet/testOrdering/TestOrdering.java Thu Jun 13 11:31:36 2019 +0530
@@ -532,10 +532,10 @@
"<a href=\"#three()\">three</a>",
"<a href=\"#two()\">two</a>",
"<h2>Element Details</h2>",
- "<h3>one</h3>",
- "<h3>two</h3>",
- "<h3>three</h3>",
- "<h3>four</h3>");
+ "<h3><a id=\"one()\">one</a></h3>",
+ "<h3><a id=\"two()\">two</a></h3>",
+ "<h3><a id=\"three()\">three</a></h3>",
+ "<h3><a id=\"four()\">four</a></h3>");
checkOrder("pkg5/AnnoRequiredTest.html",
"<h2>Required Element Summary</h2>",
@@ -544,10 +544,10 @@
"<a href=\"#three()\">three</a>",
"<a href=\"#two()\">two</a>",
"<h2>Element Details</h2>",
- "<h3>one</h3>",
- "<h3>two</h3>",
- "<h3>three</h3>",
- "<h3>four</h3>");
+ "<h3><a id=\"one()\">one</a></h3>",
+ "<h3><a id=\"two()\">two</a></h3>",
+ "<h3><a id=\"three()\">three</a></h3>",
+ "<h3><a id=\"four()\">four</a></h3>");
checkOrder("pkg5/CtorTest.html",
"<h2>Constructor Summary</h2>",
@@ -568,10 +568,10 @@
"<a href=\"#THREE\">THREE</a>",
"<a href=\"#TWO\">TWO</a>",
"<h2>Enum Constant Details</h2>",
- "<h3>ONE</h3>",
- "<h3>TWO</h3>",
- "<h3>THREE</h3>",
- "<h3>FOUR</h3>");
+ "<h3><a id=\"ONE\">ONE</a></h3>",
+ "<h3><a id=\"TWO\">TWO</a></h3>",
+ "<h3><a id=\"THREE\">THREE</a></h3>",
+ "<h3><a id=\"FOUR\">FOUR</a></h3>");
checkOrder("pkg5/FieldTest.html",
"<h2>Field Summary</h2>",
@@ -580,10 +580,10 @@
"<a href=\"#three\">three</a>",
"<a href=\"#two\">two</a>",
"<h2>Field Details</h2>",
- "<h3>one</h3>",
- "<h3>two</h3>",
- "<h3>three</h3>",
- "<h3>four</h3>");
+ "<h3><a id=\"one\">one</a></h3>",
+ "<h3><a id=\"two\">two</a></h3>",
+ "<h3><a id=\"three\">three</a></h3>",
+ "<h3><a id=\"four\">four</a></h3>");
checkOrder("pkg5/IntfTest.html",
"<h2>Method Summary</h2>",
@@ -592,10 +592,10 @@
"<a href=\"#three()\">three</a>",
"<a href=\"#two()\">two</a>",
"<h2>Method Details</h2>",
- "<h3>one</h3>",
- "<h3>two</h3>",
- "<h3>three</h3>",
- "<h3>four</h3>");
+ "<h3><a id=\"one()\">one</a></h3>",
+ "<h3><a id=\"two()\">two</a></h3>",
+ "<h3><a id=\"three()\">three</a></h3>",
+ "<h3><a id=\"four()\">four</a></h3>");
checkOrder("pkg5/MethodTest.html",
"<h2>Method Summary</h2>",
@@ -604,10 +604,10 @@
"<a href=\"#three()\">three</a>",
"<a href=\"#two()\">two</a>",
"<h2>Method Details</h2>",
- "<h3>one</h3>",
- "<h3>two</h3>",
- "<h3>three</h3>",
- "<h3>four</h3>");
+ "<h3><a id=\"one()\">one</a></h3>",
+ "<h3><a id=\"two()\">two</a></h3>",
+ "<h3><a id=\"three()\">three</a></h3>",
+ "<h3><a id=\"four()\">four</a></h3>");
checkOrder("pkg5/PropertyTest.html",
"<h2>Property Summary</h2>",
@@ -616,10 +616,10 @@
"<a href=\"#threeProperty\">three</a>",
"<a href=\"#twoProperty\">two</a>",
"<h2>Property Details</h2>",
- "<h3>oneProperty</h3>",
- "<h3>twoProperty</h3>",
- "<h3>threeProperty</h3>",
- "<h3>fourProperty</h3>");
+ "<h3><a id=\"oneProperty()\">oneProperty</a></h3>",
+ "<h3><a id=\"twoProperty()\">twoProperty</a></h3>",
+ "<h3><a id=\"threeProperty()\">threeProperty</a></h3>",
+ "<h3><a id=\"fourProperty()\">fourProperty</a></h3>");
}
}
--- a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestBadOverride.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestBadOverride.java Thu Jun 13 11:31:36 2019 +0530
@@ -53,10 +53,7 @@
checkOutput("pkg4/Foo.html", true,
"<section class=\"detail\">\n"
- + "<h3>toString</h3>\n"
- + "<a id=\"toString()\">\n"
- + "<!-- -->\n"
- + "</a>\n"
+ + "<h3><a id=\"toString()\">toString</a></h3>\n"
+ "<div class=\"memberSignature\"><span class=\"modifiers\">public</span> "
+ "<span class=\"returnType\">void</span> <span class=\"memberName\">toString</span>()</div>\n"
+ "<div class=\"block\">Why can't I do this ?</div>\n"
--- a/test/langtools/jdk/javadoc/doclet/testSummaryTag/TestSummaryTag.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/langtools/jdk/javadoc/doclet/testSummaryTag/TestSummaryTag.java Thu Jun 13 11:31:36 2019 +0530
@@ -86,10 +86,7 @@
// make sure the second @summary's content is displayed correctly
checkOutput("p1/A.html", true,
"<section class=\"detail\">\n"
- + "<h3>m3</h3>\n"
- + "<a id=\"m3()\">\n"
- + "<!-- -->\n"
- + "</a>\n"
+ + "<h3><a id=\"m3()\">m3</a></h3>\n"
+ "<div class=\"memberSignature\"><span class=\"modifiers\">public</span> "
+ "<span class=\"returnType\">void</span> <span class=\"memberName\">m3</span>()</div>\n"
+ "<div class=\"block\">First sentence some text maybe second sentence.</div>\n"
--- a/test/langtools/jdk/javadoc/doclet/testTypeParams/TestTypeParameters.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/langtools/jdk/javadoc/doclet/testTypeParams/TestTypeParameters.java Thu Jun 13 11:31:36 2019 +0530
@@ -70,9 +70,7 @@
// Nested type parameters
checkOutput("pkg/C.html", true,
- "<a id=\"formatDetails(java.util.Collection,java.util.Collection)\">\n"
- + "<!-- -->\n"
- + "</a>");
+ "<a id=\"formatDetails(java.util.Collection,java.util.Collection)\">");
}
@Test
--- a/test/langtools/tools/doclint/CoverageExtras.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/langtools/tools/doclint/CoverageExtras.java Thu Jun 13 11:31:36 2019 +0530
@@ -49,8 +49,6 @@
check(Checker.Flag.TABLE_HAS_CAPTION, Checker.Flag.valueOf("TABLE_HAS_CAPTION"), Checker.Flag.values());
- check(Entity.nbsp, Entity.valueOf("nbsp"), Entity.values());
-
check(Messages.Group.ACCESSIBILITY, Messages.Group.valueOf("ACCESSIBILITY"), Messages.Group.values());
}
--- a/test/langtools/tools/doclint/html/EntitiesTest.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/langtools/tools/doclint/html/EntitiesTest.java Thu Jun 13 11:31:36 2019 +0530
@@ -294,23 +294,35 @@
* ‹ ‹
* › ›
* € €
+ * / /
+ * ⨂ ⨂
+ * ℧ ࡏ
+ * ― ―
+ * ⌭ ⌭
*/
void symbolic_entities() { }
/**
+ * ⌫
+ *  
+ */
+ void other_numeric() {}
+
+ /**
* &bad;
*/
void bad_name() { }
/**
+ * �
+ *
* 
- * ࡏ
+ * �
+ * �
*/
void out_of_range() { }
/**
- * ―
- * ⌫
* 
*/
void sparse_negative() { }
--- a/test/langtools/tools/doclint/html/EntitiesTest.out Wed Jun 12 10:02:49 2019 +0530
+++ b/test/langtools/tools/doclint/html/EntitiesTest.out Thu Jun 13 11:31:36 2019 +0530
@@ -1,19 +1,22 @@
-EntitiesTest.java:301: error: invalid entity &bad;
+EntitiesTest.java:312: error: invalid entity &bad;
* &bad;
^
-EntitiesTest.java:306: error: invalid entity 
+EntitiesTest.java:317: error: invalid entity �
+ * �
+ ^
+EntitiesTest.java:318: error: invalid entity
+ *
+ ^
+EntitiesTest.java:319: error: invalid entity 
* 
^
-EntitiesTest.java:307: error: invalid entity ࡏ
- * ࡏ
+EntitiesTest.java:320: error: invalid entity �
+ * �
^
-EntitiesTest.java:312: error: invalid entity ―
- * ―
+EntitiesTest.java:321: error: invalid entity �
+ * �
^
-EntitiesTest.java:313: error: invalid entity ⌫
- * ⌫
- ^
-EntitiesTest.java:314: error: invalid entity 
+EntitiesTest.java:326: error: invalid entity 
* 
^
-6 errors
+7 errors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/switchexpr/TryCatchFinally.java Thu Jun 13 11:31:36 2019 +0530
@@ -0,0 +1,312 @@
+/*
+ * Copyright (c) 2019, 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 8220018
+ * @summary Verify that try-catch-finally inside a switch expression works properly.
+ * @compile --enable-preview -source ${jdk.version} TryCatchFinally.java
+ * @run main/othervm --enable-preview TryCatchFinally
+ */
+public class TryCatchFinally {//TODO: yield <double>
+ public static void main(String[] args) {
+ for (int p1 = 0; p1 < 2; p1++) {
+ for (int p2 = 0; p2 < 2; p2++) {
+ for (int p3 = 0; p3 < 2; p3++) {
+ for (int p4 = 0; p4 < 2; p4++) {
+ for (int p5 = 0; p5 < 2; p5++) {
+ for (int p6 = 0; p6 < 3; p6++) {
+ int actual = runSwitchesOrdinary(p1, p2, p3, p4, p5, p6);
+ int expected = computeExpectedOrdinary(p1, p2, p3, p4, p5, p6);
+ if (actual != expected) {
+ throw new IllegalStateException("actual=" + actual + "; " +
+ "expected=" + expected + ", parameters: " + p1 + ", " + p2 + ", " + p3 + ", " + p4 + ", " + p5 + ", " + p6 + ", ");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ {
+ boolean correct = false;
+ int v;
+ if (switch (0) {
+ case 0:
+ try {
+ if (true) {
+ throw new MarkerException();
+ }
+ yield false;
+ } catch (MarkerException ex) {
+ yield false;
+ } finally {
+ v = 0;
+ yield true;
+ }
+ default: yield false;
+ } && v == 0) {
+ correct = true;
+ }
+ if (!correct) {
+ throw new IllegalStateException();
+ }
+ }
+ {
+ boolean correct = false;
+ if (switch (0) {
+ case 0:
+ try {
+ if (true) {
+ throw new MarkerException();
+ }
+ yield new TryCatchFinally().fls();
+ } catch (MarkerException ex) {
+ yield new TryCatchFinally().fls();
+ } finally {
+ yield true;
+ }
+ default: yield new TryCatchFinally().fls();
+ }) {
+ correct = true;
+ }
+ if (!correct) {
+ throw new IllegalStateException();
+ }
+ }
+ {
+ E e = E.A;
+ boolean correct = false;
+ int v;
+ if (switch (0) {
+ case 0:
+ try {
+ if (true) {
+ throw new MarkerException();
+ }
+ yield false;
+ } catch (MarkerException ex) {
+ v = 0;
+ yield true;
+ } finally {
+ try {
+ if (true)
+ throw new MarkerException();
+ } catch (MarkerException ex) {
+ e = e.next();
+ }
+ }
+ default: yield false;
+ } && v == 0) {
+ correct = true;
+ }
+ if (!correct) {
+ throw new IllegalStateException();
+ }
+ }
+ {
+ E e = E.A;
+ boolean correct = false;
+ int v;
+ if (switch (0) {
+ case 0:
+ try {
+ if (true) {
+ throw new MarkerException();
+ }
+ yield false;
+ } catch (MarkerException ex) {
+ yield false;
+ } finally {
+ try {
+ if (true)
+ throw new MarkerException();
+ } catch (MarkerException ex) {
+ e = e.next();
+ } finally {
+ v = 0;
+ yield true;
+ }
+ }
+ default: yield false;
+ } && v == 0) {
+ correct = true;
+ }
+ if (!correct) {
+ throw new IllegalStateException();
+ }
+ }
+ {
+ boolean correct = false;
+ if (!switch (0) {
+ default -> {
+ try {
+ yield switch(0) { default -> true; };
+ }
+ finally {
+ yield false;
+ }
+ }
+ }) {
+ correct = true;
+ }
+ if (!correct) {
+ throw new IllegalStateException();
+ }
+ }
+ }
+
+ private static int runSwitchesOrdinary(int p1, int p2, int p3, int p4, int p5, int p6) {
+ return 1 + switch (p1) {
+ case 0:
+ try {
+ if (p2 == 0) {
+ new TryCatchFinally().throwException();
+ }
+ try {
+ yield 10 + switch (p3) {
+ case 0 -> {
+ try {
+ if (p4 == 0) {
+ new TryCatchFinally().throwException();
+ }
+ yield 100;
+ } catch (Throwable ex) {
+ yield 200;
+ } finally {
+ if (p6 == 0) {
+ yield 300;
+ } else if (p6 == 1) {
+ throw new MarkerException();
+ }
+ }
+ }
+ default -> 400;
+ };
+ } catch (MarkerException me) {
+ yield 510;
+ }
+ } catch(Throwable ex) {
+ try {
+ yield 20 + switch (p3) {
+ case 0 -> {
+ try {
+ if (p4 == 0) {
+ new TryCatchFinally().throwException();
+ }
+ yield 100;
+ } catch (Throwable ex2) {
+ yield 200;
+ } finally {
+ if (p6 == 0) {
+ yield 300;
+ } else if (p6 == 1) {
+ throw new MarkerException();
+ }
+ }
+ }
+ default -> 400;
+ };
+ } catch (MarkerException me) {
+ yield 520;
+ }
+ } finally {
+ if (p5 == 0) {
+ try {
+ yield 30 + switch (p3) {
+ case 0 -> {
+ try {
+ if (p4 == 0) {
+ new TryCatchFinally().throwException();
+ }
+ yield 100;
+ } catch (Throwable ex) {
+ yield 200;
+ } finally {
+ if (p6 == 0) {
+ yield 300;
+ } else if (p6 == 1) {
+ throw new MarkerException();
+ }
+ }
+ }
+ default -> 400;
+ };
+ } catch (MarkerException me) {
+ yield 530;
+ }
+ }
+ }
+ default: yield 40;
+ };
+ }
+
+ private static int computeExpectedOrdinary(int p1, int p2, int p3, int p4, int p5, int p6) {
+ int expected = 0;
+
+ if (p1 == 0) {
+ if (p5 == 0) {
+ expected = 30;
+ } else if (p2 == 0) {
+ expected = 20;
+ } else {
+ expected = 10;
+ }
+ if (p3 == 0) {
+ if (p6 == 0) {
+ expected += 300;
+ } else if (p6 == 1) {
+ expected += 500;
+ } else if (p4 == 0) {
+ expected += 200;
+ } else {
+ expected += 100;
+ }
+ } else {
+ expected += 400;
+ }
+ } else {
+ expected = 40;
+ }
+
+ expected += 1;
+
+ return expected;
+ }
+
+ private boolean fls() {
+ return false;
+ }
+ private void throwException() {
+ throw new RuntimeException();
+ }
+
+ static class MarkerException extends Throwable {}
+
+ enum E {
+ A, B, C;
+ public E next() {
+ return values()[(ordinal() + 1) % values().length];
+ }
+ }
+}
--- a/test/lib/jdk/test/lib/cds/CDSTestUtils.java Wed Jun 12 10:02:49 2019 +0530
+++ b/test/lib/jdk/test/lib/cds/CDSTestUtils.java Thu Jun 13 11:31:36 2019 +0530
@@ -357,7 +357,8 @@
outStr.contains("Unable to map MiscCode shared space at required address") ||
outStr.contains("Unable to map OptionalData shared space at required address") ||
outStr.contains("Could not allocate metaspace at a compatible address") ||
- outStr.contains("UseSharedSpaces: Unable to allocate region, range is not within java heap") ))
+ outStr.contains("UseSharedSpaces: Unable to allocate region, range is not within java heap") ||
+ outStr.contains("DynamicDumpSharedSpaces is unsupported when base CDS archive is not loaded") ))
{
return true;
}