mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-06 08:28:27 +00:00
Merge
This commit is contained in:
commit
53ea90ebf6
@ -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 @@ ifneq ($(BUILD_CRYPTO), false)
|
||||
))
|
||||
|
||||
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)
|
||||
|
||||
@ -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 @@ operand immD() %{
|
||||
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_reg_Ex(iRegLdst dst, iRegIsrc src) %{
|
||||
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_immI0(iRegLdst dst, immI_0 zero) %{
|
||||
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 @@ instruct repl8S_immIminus1(vecX dst, immI_minus1 src) %{
|
||||
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_reg_Ex(iRegLdst dst, iRegIsrc src) %{
|
||||
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_immI0(iRegLdst dst, immI_0 zero) %{
|
||||
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 @@ instruct repl2D_reg_Ex(vecX dst, regD src) %{
|
||||
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 @@ instruct repl2D_immI0(vecX dst, immI_0 zero) %{
|
||||
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 @@ instruct repl2L_immIminus1(vecX dst, immI_minus1 src) %{
|
||||
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);
|
||||
|
||||
@ -82,7 +82,18 @@ int LIR_Assembler::check_icache() {
|
||||
}
|
||||
|
||||
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() {
|
||||
|
||||
@ -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 @@ void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache,
|
||||
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 @@ void InterpreterMacroAssembler::pop_interpreter_frame(Register return_pc, Regist
|
||||
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);
|
||||
|
||||
@ -120,6 +120,8 @@ class InterpreterMacroAssembler: public MacroAssembler {
|
||||
// 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);
|
||||
|
||||
@ -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 @@ void MacroAssembler::check_klass_subtype(Register sub_klass,
|
||||
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 @@ void MacroAssembler::resolve_oop_handle(Register result) {
|
||||
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.
|
||||
//---------------------------------------------------------------
|
||||
|
||||
@ -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 @@ class MacroAssembler: public Assembler {
|
||||
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 @@ class MacroAssembler: public Assembler {
|
||||
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.
|
||||
|
||||
@ -867,6 +867,23 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||
|
||||
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
|
||||
|
||||
@ -1832,6 +1832,20 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
|
||||
//---------------------------------------------------------------------
|
||||
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 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
|
||||
// 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);
|
||||
}
|
||||
|
||||
@ -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 @@ void TemplateInterpreterGenerator::generate_stack_overflow_check(Register frame_
|
||||
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 @@ void TemplateInterpreterGenerator::generate_stack_overflow_check(Register frame_
|
||||
// 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 @@ void TemplateInterpreterGenerator::lock_method(void) {
|
||||
__ 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 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
|
||||
// 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 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
|
||||
// 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 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
|
||||
__ 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 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
|
||||
// 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 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
|
||||
// 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 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
|
||||
#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 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
|
||||
// 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 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
|
||||
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 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
|
||||
__ 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 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||
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.
|
||||
|
||||
@ -2404,14 +2404,14 @@ void TemplateTable::_return(TosState state) {
|
||||
// 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 @@ void TemplateTable::resolve_cache_and_index(int byte_no,
|
||||
|
||||
{
|
||||
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 @@ void TemplateTable::invokeinterface(int byte_no) {
|
||||
// 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,
|
||||
|
||||
@ -349,6 +349,9 @@ class VM_Version: public Abstract_VM_Version {
|
||||
// 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; }
|
||||
|
||||
@ -4640,7 +4640,7 @@ void G1CollectedHeap::retire_gc_alloc_region(HeapRegion* alloc_region,
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -257,30 +257,38 @@ void G1CMMarkStack::set_empty() {
|
||||
_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 @@ void G1CMRootRegions::prepare_for_scan() {
|
||||
_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 @@ HeapRegion* G1CMRootRegions::claim_next() {
|
||||
|
||||
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 @@ void G1CMRootRegions::scan_finished() {
|
||||
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 @@ uint G1ConcurrentMark::calc_active_marking_workers() {
|
||||
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 @@ public:
|
||||
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();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -222,18 +222,20 @@ private:
|
||||
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 @@ class G1CMRootRegions {
|
||||
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 @@ public:
|
||||
// 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 @@ class G1ConcurrentMark : public CHeapObj<mtGC> {
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
// 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();
|
||||
|
||||
@ -1111,13 +1111,6 @@ JVMCIObject JVMCIEnv::get_jvmci_type(const JVMCIKlassHandle& klass, JVMCI_TRAPS)
|
||||
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();
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -1221,7 +1221,7 @@ void Metaspace::global_initialize() {
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
@ -565,7 +565,7 @@ class GraphKit : public Phase {
|
||||
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
|
||||
|
||||
@ -2439,7 +2439,10 @@ bool LibraryCallKit::inline_unsafe_access(bool is_store, const BasicType type, c
|
||||
|
||||
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);
|
||||
|
||||
@ -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 @@ Node *MemNode::Ideal_common(PhaseGVN *phase, bool can_reshape) {
|
||||
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())) ) {
|
||||
|
||||
@ -2412,12 +2412,9 @@ void Scheduling::DoScheduling() {
|
||||
}
|
||||
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,
|
||||
|
||||
@ -245,9 +245,7 @@ void ObjectMonitor::enter(TRAPS) {
|
||||
|
||||
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 @@ int ObjectMonitor::TryLock(Thread * Self) {
|
||||
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 @@ int ObjectMonitor::TryLock(Thread * Self) {
|
||||
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) {
|
||||
|
||||
@ -235,6 +235,7 @@ class ObjectMonitor {
|
||||
// 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 @@ class ObjectMonitor {
|
||||
// _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;
|
||||
|
||||
@ -95,12 +95,8 @@ inline jint ObjectMonitor::contentions() const {
|
||||
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
|
||||
|
||||
@ -242,7 +242,6 @@ bool ObjectSynchronizer::quick_enter(oop obj, Thread * Self,
|
||||
|
||||
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 @@ ObjectMonitor* ObjectSynchronizer::omAlloc(Thread * Self) {
|
||||
// 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* ObjectSynchronizer::omAlloc(Thread * Self) {
|
||||
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 @@ void ObjectSynchronizer::omRelease(Thread * Self, ObjectMonitor * m,
|
||||
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 @@ void ObjectSynchronizer::omFlush(Thread * Self) {
|
||||
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 @@ ObjectMonitor* ObjectSynchronizer::inflate(Thread * Self,
|
||||
// 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 @@ ObjectMonitor* ObjectSynchronizer::inflate(Thread * Self,
|
||||
// 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 @@ void ObjectSynchronizer::audit_and_print_stats(bool on_exit) {
|
||||
// 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 @@ void ObjectSynchronizer::log_in_use_monitor_details(outputStream * out,
|
||||
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 @@ void ObjectSynchronizer::log_in_use_monitor_details(outputStream * out,
|
||||
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 @@ void ObjectSynchronizer::log_in_use_monitor_details(outputStream * out,
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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 @@ public abstract class Reference<T> {
|
||||
* {@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 @@ public abstract class Reference<T> {
|
||||
*
|
||||
* @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) {
|
||||
|
||||
@ -396,7 +396,7 @@ public abstract class SocketImpl implements SocketOptions {
|
||||
*
|
||||
* @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 @@ public abstract class SocketImpl implements SocketOptions {
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
|
||||
@ -35,8 +35,8 @@ import static sun.security.ssl.CipherSuite.HashAlg.*;
|
||||
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 @@ enum CipherSuite {
|
||||
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 @@ enum CipherSuite {
|
||||
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 @@ enum CipherSuite {
|
||||
// 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 @@ enum CipherSuite {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (groupType == NAMED_GROUP_ECDHE) {
|
||||
if (NamedGroupType.arrayContains(
|
||||
groupTypes, NamedGroupType.NAMED_GROUP_ECDHE)) {
|
||||
return (allowed && JsseJce.isEcAvailable());
|
||||
} else {
|
||||
return allowed;
|
||||
|
||||
@ -42,7 +42,6 @@ import javax.net.ssl.SSLHandshakeException;
|
||||
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;
|
||||
|
||||
/**
|
||||
|
||||
@ -36,19 +36,12 @@ import java.security.NoSuchAlgorithmException;
|
||||
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 @@ final class DHKeyExchange {
|
||||
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 @@ final class DHKeyExchange {
|
||||
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 @@ final class DHKeyExchange {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ final class DHKeyExchange {
|
||||
// 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 @@ final class DHKeyExchange {
|
||||
|
||||
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 @@ final class DHKeyExchange {
|
||||
// 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 @@ final class DHKeyExchange {
|
||||
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 @@ final class DHKeyExchange {
|
||||
|
||||
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 @@ final class DHKeyExchange {
|
||||
"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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,7 +48,6 @@ import javax.crypto.spec.DHPublicKeySpec;
|
||||
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;
|
||||
|
||||
@ -27,31 +27,28 @@ package sun.security.ssl;
|
||||
|
||||
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 @@ final class ECDHClientKeyExchange {
|
||||
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 @@ final class ECDHClientKeyExchange {
|
||||
}
|
||||
}
|
||||
|
||||
// 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 @@ final class ECDHClientKeyExchange {
|
||||
}
|
||||
|
||||
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 @@ final class ECDHClientKeyExchange {
|
||||
"No expected EC server cert for ECDH client key exchange");
|
||||
}
|
||||
|
||||
ECParameterSpec params = x509Possession.getECParameterSpec();
|
||||
if (params == 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");
|
||||
// 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);
|
||||
}
|
||||
|
||||
NamedGroup namedGroup = NamedGroup.valueOf(params);
|
||||
if (namedGroup == null) {
|
||||
// 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,
|
||||
"Unsupported EC server cert for ECDH client key exchange");
|
||||
"Not EC/XDH server cert for ECDH client key exchange");
|
||||
}
|
||||
|
||||
// unlikely, have been checked during cipher suite negotiation.
|
||||
if (namedGroup == null) {
|
||||
throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
|
||||
"Unknown named group in server cert for " +
|
||||
"ECDH client key exchange");
|
||||
}
|
||||
|
||||
SSLKeyExchange ke = SSLKeyExchange.valueOf(
|
||||
@ -306,7 +307,7 @@ final class ECDHClientKeyExchange {
|
||||
"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 @@ final class ECDHClientKeyExchange {
|
||||
|
||||
// create the credentials
|
||||
try {
|
||||
ECPoint point =
|
||||
ECUtil.decodePoint(cke.encodedPoint, params.getCurve());
|
||||
ECPublicKeySpec spec = new ECPublicKeySpec(point, params);
|
||||
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));
|
||||
|
||||
KeyFactory kf = KeyFactory.getInstance("EC");
|
||||
ECPublicKey peerPublicKey =
|
||||
(ECPublicKey)kf.generatePublic(spec);
|
||||
|
||||
// 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 @@ final class ECDHClientKeyExchange {
|
||||
// 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 @@ final class ECDHClientKeyExchange {
|
||||
// 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 @@ final class ECDHClientKeyExchange {
|
||||
"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 @@ final class ECDHClientKeyExchange {
|
||||
|
||||
// create the credentials
|
||||
try {
|
||||
ECPoint point =
|
||||
ECUtil.decodePoint(cke.encodedPoint, params.getCurve());
|
||||
ECPublicKeySpec spec = new ECPublicKeySpec(point, params);
|
||||
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));
|
||||
|
||||
KeyFactory kf = KeyFactory.getInstance("EC");
|
||||
ECPublicKey peerPublicKey =
|
||||
(ECPublicKey)kf.generatePublic(spec);
|
||||
|
||||
// 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
|
||||
|
||||
@ -36,7 +36,6 @@ import java.security.PrivateKey;
|
||||
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.security.spec.ECPublicKeySpec;
|
||||
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 @@ final class ECDHKeyExchange {
|
||||
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 @@ final class ECDHKeyExchange {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ final class ECDHKeyExchange {
|
||||
"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 @@ final class ECDHKeyExchange {
|
||||
|
||||
@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 @@ final class ECDHKeyExchange {
|
||||
"No sufficient ECDHE key agreement parameters negotiated");
|
||||
}
|
||||
|
||||
return new ECDHEKAKeyDerivation(shc,
|
||||
return new KAKeyDerivation("ECDH", shc,
|
||||
x509Possession.popPrivateKey, ecdheCredentials.popPublicKey);
|
||||
}
|
||||
|
||||
@ -347,7 +383,7 @@ final class ECDHKeyExchange {
|
||||
"No sufficient ECDH key agreement parameters negotiated");
|
||||
}
|
||||
|
||||
return new ECDHEKAKeyDerivation(chc,
|
||||
return new KAKeyDerivation("ECDH", chc,
|
||||
ecdhePossession.privateKey, x509Credentials.popPublicKey);
|
||||
}
|
||||
}
|
||||
@ -391,94 +427,73 @@ final class ECDHKeyExchange {
|
||||
"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 {
|
||||
|
||||
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");
|
||||
NamedGroupPossession namedGroupPossession = null;
|
||||
NamedGroupCredentials namedGroupCredentials = null;
|
||||
NamedGroup namedGroup = null;
|
||||
|
||||
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");
|
||||
|
||||
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);
|
||||
if (namedGroupPossession == null || namedGroupCredentials == null) {
|
||||
throw context.conContext.fatal(Alert.HANDSHAKE_FAILURE,
|
||||
"No sufficient ECDHE/XDH key agreement " +
|
||||
"parameters negotiated");
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
return new KAKeyDerivation(alg, context,
|
||||
namedGroupPossession.getPrivateKey(),
|
||||
namedGroupCredentials.getPublicKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,32 +27,21 @@ package sun.security.ssl;
|
||||
|
||||
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 @@ final class ECDHServerKeyExchange {
|
||||
// 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 @@ final class ECDHServerKeyExchange {
|
||||
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 @@ final class ECDHServerKeyExchange {
|
||||
"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 @@ final class ECDHServerKeyExchange {
|
||||
// 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")) {
|
||||
@ -536,23 +510,10 @@ final class ECDHServerKeyExchange {
|
||||
"Consuming ECDH ServerKeyExchange handshake message", skem);
|
||||
}
|
||||
|
||||
//
|
||||
// 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
|
||||
|
||||
@ -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 static sun.security.ssl.SSLExtension.CH_EC_POINT_FORMATS;
|
||||
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].
|
||||
|
||||
@ -46,9 +46,8 @@ import javax.crypto.SecretKey;
|
||||
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 @@ abstract class HandshakeContext implements ConnectionContext {
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
available = checkedStatus;
|
||||
}
|
||||
|
||||
if (!available && SSLLogger.isOn && SSLLogger.isOn("verbose")) {
|
||||
SSLLogger.fine(
|
||||
"No active named group, ignore " + suite);
|
||||
retval |= groupAvailable;
|
||||
} else {
|
||||
retval |= true;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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 @@ package sun.security.ssl;
|
||||
|
||||
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 @@ final class KeyShareExtension {
|
||||
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 @@ final class KeyShareExtension {
|
||||
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));
|
||||
}
|
||||
} 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));
|
||||
try {
|
||||
SSLCredentials kaCred =
|
||||
ng.decodeCredentials(entry.keyExchange,
|
||||
shc.algorithmConstraints,
|
||||
s -> SSLLogger.warning(s));
|
||||
if (kaCred != null) {
|
||||
credentials.add(kaCred);
|
||||
}
|
||||
} catch (GeneralSecurityException ex) {
|
||||
SSLLogger.warning(
|
||||
"Cannot decode named group: " +
|
||||
NamedGroup.nameOf(entry.namedGroupId));
|
||||
}
|
||||
}
|
||||
|
||||
@ -526,10 +489,9 @@ final class KeyShareExtension {
|
||||
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 @@ final class KeyShareExtension {
|
||||
|
||||
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 @@ final class KeyShareExtension {
|
||||
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 @@ final class KeyShareExtension {
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
781
src/java.base/share/classes/sun/security/ssl/NamedGroup.java
Normal file
781
src/java.base/share/classes/sun/security/ssl/NamedGroup.java
Normal file
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
@ -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 @@ enum SSLExtension implements SSLStringizer {
|
||||
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;
|
||||
|
||||
@ -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.AbstractMap.SimpleImmutableEntry;
|
||||
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 @@ final class SSLKeyExchange implements SSLKeyAgreementGenerator,
|
||||
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 @@ final class SSLKeyExchange implements SSLKeyAgreementGenerator,
|
||||
ECDH ("ecdh", null,
|
||||
ECDHKeyExchange.ecdhKAGenerator),
|
||||
ECDHE ("ecdhe", ECDHKeyExchange.poGenerator,
|
||||
ECDHKeyExchange.ecdheKAGenerator);
|
||||
ECDHKeyExchange.ecdheXdhKAGenerator);
|
||||
|
||||
final String name;
|
||||
final SSLPossessionGenerator possessionGenerator;
|
||||
@ -570,27 +565,13 @@ final class SSLKeyExchange implements SSLKeyAgreementGenerator,
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 @@ final class SSLSocketInputRecord extends InputRecord implements SSLRecord {
|
||||
handshakeBuffer.put(handshakeFrag);
|
||||
handshakeBuffer.rewind();
|
||||
break;
|
||||
} if (remaining == handshakeMessageLen) {
|
||||
}
|
||||
|
||||
if (remaining == handshakeMessageLen) {
|
||||
if (handshakeHash.isHashable(handshakeType)) {
|
||||
handshakeHash.receive(handshakeFrag);
|
||||
}
|
||||
|
||||
@ -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.EnumSet;
|
||||
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 @@ enum SignatureScheme {
|
||||
}
|
||||
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 &&
|
||||
|
||||
@ -30,29 +30,24 @@ import java.nio.ByteBuffer;
|
||||
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 @@ final class SupportedGroupsExtension {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ final class SupportedGroupsExtension {
|
||||
}
|
||||
} 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 @@ final class SupportedGroupsExtension {
|
||||
// non-NIST curves
|
||||
NamedGroup.SECP256_K1,
|
||||
|
||||
// FFDHE 2048
|
||||
// FFDHE (RFC 7919)
|
||||
NamedGroup.FFDHE_2048,
|
||||
NamedGroup.FFDHE_3072,
|
||||
NamedGroup.FFDHE_4096,
|
||||
@ -560,126 +255,27 @@ final class SupportedGroupsExtension {
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
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);
|
||||
static ECGenParameterSpec getECGenParamSpec(NamedGroup ng) {
|
||||
if (ng.type != NamedGroupType.NAMED_GROUP_ECDHE) {
|
||||
throw new RuntimeException(
|
||||
"Not a named EC group: " + ng);
|
||||
}
|
||||
|
||||
// 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 @@ final class SupportedGroupsExtension {
|
||||
if (constraints.permits(
|
||||
EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
|
||||
namedGroup.algorithm,
|
||||
namedGroupParams.get(namedGroup))) {
|
||||
getParameters(namedGroup))) {
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -723,7 +319,7 @@ final class SupportedGroupsExtension {
|
||||
return constraints.permits(
|
||||
EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
|
||||
namedGroup.algorithm,
|
||||
namedGroupParams.get(namedGroup));
|
||||
getParameters(namedGroup));
|
||||
}
|
||||
|
||||
// Is the named group supported?
|
||||
@ -739,16 +335,16 @@ final class SupportedGroupsExtension {
|
||||
|
||||
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 @@ final class SupportedGroupsExtension {
|
||||
|
||||
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 @@ final class SupportedGroupsExtension {
|
||||
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 @@ final class SupportedGroupsExtension {
|
||||
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(
|
||||
|
||||
@ -39,7 +39,6 @@ import javax.net.ssl.HandshakeCompletedListener;
|
||||
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.
|
||||
|
||||
@ -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 @@ final class Utilities {
|
||||
|
||||
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 @@ final class Utilities {
|
||||
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 @@ final class Utilities {
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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.PublicKey;
|
||||
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 @@ enum X509Authentication implements SSLAuthentication {
|
||||
|
||||
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 {
|
||||
|
||||
210
src/java.base/share/classes/sun/security/ssl/XDHKeyExchange.java
Normal file
210
src/java.base/share/classes/sun/security/ssl/XDHKeyExchange.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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 @@ public class NegTokenTarg extends SpNegoToken {
|
||||
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
|
||||
|
||||
@ -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 @@ public final class SunNativeProvider extends Provider {
|
||||
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 @@ public final class SunNativeProvider extends Provider {
|
||||
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 @@ public final class SunNativeProvider extends Provider {
|
||||
"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 @@ public final class SunNativeProvider extends Provider {
|
||||
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],
|
||||
|
||||
@ -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 @@ Java_sun_security_jgss_wrapper_GSSLibStub_acceptContext(JNIEnv *env,
|
||||
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;
|
||||
|
||||
@ -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 (*RELEASE_NAME_FN_PTR)
|
||||
|
||||
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 (*RELEASE_CRED_FN_PTR)
|
||||
|
||||
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 (*INQUIRE_CRED_FN_PTR)
|
||||
|
||||
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 (*INIT_SEC_CONTEXT_FN_PTR)
|
||||
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 (*ACCEPT_SEC_CONTEXT_FN_PTR)
|
||||
|
||||
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 (*DELETE_SEC_CONTEXT_FN_PTR)
|
||||
|
||||
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 (*EXPORT_SEC_CONTEXT_FN_PTR)
|
||||
|
||||
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 (*INQUIRE_NAMES_FOR_MECH_FN_PTR)
|
||||
|
||||
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);
|
||||
|
||||
|
||||
@ -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 "C" {
|
||||
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
|
||||
|
||||
@ -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 @@ extern "C" {
|
||||
*/
|
||||
#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 @@ typedef struct gss_OID_desc_struct {
|
||||
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 @@ typedef struct gss_channel_bindings_struct {
|
||||
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 @@ typedef int gss_cred_usage_t;
|
||||
#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 extern gss_OID GSS_C_NT_EXPORT_NAME;
|
||||
|
||||
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_release_cred(
|
||||
|
||||
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_init_sec_context(
|
||||
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_accept_sec_context(
|
||||
|
||||
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_delete_sec_context(
|
||||
|
||||
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 @@ GSS_DLLIMP OM_uint32 gss_wrap(
|
||||
/* 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 @@ GSS_DLLIMP OM_uint32 gss_display_status(
|
||||
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_indicate_mechs(
|
||||
|
||||
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_release_oid_set(
|
||||
|
||||
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 @@ GSS_DLLIMP OM_uint32 gss_inquire_cred(
|
||||
/* 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 @@ GSS_DLLIMP OM_uint32 gss_inquire_context(
|
||||
/* 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 @@ GSS_DLLIMP OM_uint32 gss_wrap_size_limit(
|
||||
/* 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 @@ GSS_DLLIMP OM_uint32 gss_add_cred(
|
||||
/* 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 @@ GSS_DLLIMP OM_uint32 gss_export_sec_context(
|
||||
/* 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 @@ GSS_DLLIMP OM_uint32 gss_create_empty_oid_set(
|
||||
/* 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 @@ GSS_DLLIMP OM_uint32 gss_oid_to_str(
|
||||
/* 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 */
|
||||
);
|
||||
|
||||
1575
src/java.security.jgss/windows/native/libsspi_bridge/sspi.cpp
Normal file
1575
src/java.security.jgss/windows/native/libsspi_bridge/sspi.cpp
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -166,6 +166,7 @@ public class Gen extends JCTree.Visitor {
|
||||
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 @@ public class Gen extends JCTree.Visitor {
|
||||
|
||||
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 @@ public class Gen extends JCTree.Visitor {
|
||||
stackBeforeSwitchExpression = stackBeforeSwitchExpression.prepend(item);
|
||||
item.store();
|
||||
}
|
||||
switchResult = makeTemp(tree.type);
|
||||
}
|
||||
int prevLetExprStart = code.setLetExprStackPos(code.state.stacksize);
|
||||
try {
|
||||
@ -1220,6 +1224,7 @@ public class Gen extends JCTree.Visitor {
|
||||
}
|
||||
} finally {
|
||||
stackBeforeSwitchExpression = prevStackBeforeSwitchExpression;
|
||||
switchResult = prevSwitchResult;
|
||||
code.endScopes(limit);
|
||||
}
|
||||
}
|
||||
@ -1725,16 +1730,22 @@ public class Gen extends JCTree.Visitor {
|
||||
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 @@ public class Gen extends JCTree.Visitor {
|
||||
}
|
||||
} 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 @@ public class Gen extends JCTree.Visitor {
|
||||
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);
|
||||
|
||||
@ -513,6 +513,7 @@ public class JavadocFormatter {
|
||||
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 @@ public class JavadocFormatter {
|
||||
//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());
|
||||
}
|
||||
|
||||
@ -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 java.security.spec.NamedParameterSpec;
|
||||
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 @@ public class XDHKeyAgreement extends KeyAgreementSpi {
|
||||
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 {
|
||||
|
||||
@ -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 @@ public class XECParameters {
|
||||
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 @@ public class XECParameters {
|
||||
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) {
|
||||
|
||||
@ -33,6 +33,7 @@ import javax.lang.model.type.TypeMirror;
|
||||
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 @@ public class AnnotationTypeFieldWriterImpl extends AbstractMemberWriter
|
||||
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 @@ public class AnnotationTypeFieldWriterImpl extends AbstractMemberWriter
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@ -33,6 +33,7 @@ import javax.lang.model.type.TypeMirror;
|
||||
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 @@ public class AnnotationTypeRequiredMemberWriterImpl extends AbstractMemberWriter
|
||||
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 @@ public class AnnotationTypeRequiredMemberWriterImpl extends AbstractMemberWriter
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@ -37,6 +37,7 @@ import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
|
||||
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 @@ public class ConstructorWriterImpl extends AbstractExecutableMemberWriter
|
||||
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 @@ public class ConstructorWriterImpl extends AbstractExecutableMemberWriter
|
||||
String erasureAnchor;
|
||||
Content constructorDocTree = new ContentBuilder();
|
||||
Content heading = new HtmlTree(Headings.TypeDeclaration.MEMBER_HEADING);
|
||||
heading.add(name(constructor));
|
||||
constructorDocTree.add(heading);
|
||||
if ((erasureAnchor = getErasureAnchor(constructor)) != null) {
|
||||
constructorDocTree.add(links.createAnchor((erasureAnchor)));
|
||||
heading.add(links.createAnchor((erasureAnchor)));
|
||||
}
|
||||
constructorDocTree.add(links.createAnchor(writer.getAnchor(constructor)));
|
||||
heading.add(links.createAnchor(writer.getAnchor(constructor), new StringContent(name(constructor))));
|
||||
constructorDocTree.add(heading);
|
||||
return HtmlTree.SECTION(HtmlStyle.detail, constructorDocTree);
|
||||
}
|
||||
|
||||
|
||||
@ -33,6 +33,7 @@ import javax.lang.model.element.VariableElement;
|
||||
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 @@ public class EnumConstantWriterImpl extends AbstractMemberWriter
|
||||
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 @@ public class EnumConstantWriterImpl extends AbstractMemberWriter
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@ -96,9 +96,9 @@ public class FieldWriterImpl extends AbstractMemberWriter
|
||||
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 class FieldWriterImpl extends AbstractMemberWriter
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@ -109,8 +109,8 @@ public class MethodWriterImpl extends AbstractExecutableMemberWriter
|
||||
Content methodDetailsTree = new ContentBuilder();
|
||||
Content heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING,
|
||||
contents.methodDetailLabel);
|
||||
methodDetailsTree.add(heading);
|
||||
methodDetailsTree.add(links.createAnchor(SectionName.METHOD_DETAIL));
|
||||
methodDetailsTree.add(heading);
|
||||
return methodDetailsTree;
|
||||
}
|
||||
|
||||
@ -122,12 +122,11 @@ public class MethodWriterImpl extends AbstractExecutableMemberWriter
|
||||
String erasureAnchor;
|
||||
Content methodDocTree = new ContentBuilder();
|
||||
Content heading = new HtmlTree(Headings.TypeDeclaration.MEMBER_HEADING);
|
||||
heading.add(name(method));
|
||||
methodDocTree.add(heading);
|
||||
if ((erasureAnchor = getErasureAnchor(method)) != null) {
|
||||
methodDocTree.add(links.createAnchor((erasureAnchor)));
|
||||
heading.add(links.createAnchor((erasureAnchor)));
|
||||
}
|
||||
methodDocTree.add(links.createAnchor(writer.getAnchor(method)));
|
||||
heading.add(links.createAnchor(writer.getAnchor(method), new StringContent(name(method))));
|
||||
methodDocTree.add(heading);
|
||||
return HtmlTree.SECTION(HtmlStyle.detail, methodDocTree);
|
||||
}
|
||||
|
||||
|
||||
@ -89,8 +89,8 @@ public class PropertyWriterImpl extends AbstractMemberWriter
|
||||
Content propertyDetailsTree = new ContentBuilder();
|
||||
Content heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING,
|
||||
contents.propertyDetailsLabel);
|
||||
propertyDetailsTree.add(heading);
|
||||
propertyDetailsTree.add(links.createAnchor(SectionName.PROPERTY_DETAIL));
|
||||
propertyDetailsTree.add(heading);
|
||||
return propertyDetailsTree;
|
||||
}
|
||||
|
||||
@ -102,9 +102,9 @@ public class PropertyWriterImpl extends AbstractMemberWriter
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@ -100,7 +100,7 @@ public class Links {
|
||||
* @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(" ");
|
||||
|
||||
@ -574,8 +574,7 @@ td.colLast a {
|
||||
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 {
|
||||
|
||||
@ -38,7 +38,9 @@ compiler/compilercontrol/jcmd/AddLogTest.java 8181753 generi
|
||||
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/unmonitor/unmonitor001/unmonitor001.java 82
|
||||
|
||||
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
|
||||
|
||||
@ -49,8 +49,8 @@ compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java 8158860 generic-all
|
||||
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/cpuflags/TestAESIntrinsicsOnSupportedConfig.java 8190680 generic-all
|
||||
|
||||
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
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
79
test/hotspot/jtreg/gtest/GTestResultParser.java
Normal file
79
test/hotspot/jtreg/gtest/GTestResultParser.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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 @@ public class GTestWrapper {
|
||||
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() {
|
||||
|
||||
@ -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 @@ import jdk.test.lib.process.OutputAnalyzer;
|
||||
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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
@ -188,11 +188,16 @@ public class SSLSocketTemplate {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure the client side socket.
|
||||
*/
|
||||
protected void configureClientSocket(SSLSocket socket) {
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure the server side socket.
|
||||
*/
|
||||
protected void configureServerSocket(SSLServerSocket socket) {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@ -317,6 +322,7 @@ public class SSLSocketTemplate {
|
||||
|
||||
try (SSLSocket sslSocket = (SSLSocket)sslsf.createSocket()) {
|
||||
try {
|
||||
configureClientSocket(sslSocket);
|
||||
sslSocket.connect(
|
||||
new InetSocketAddress("localhost", serverPort), 15000);
|
||||
} catch (IOException ioe) {
|
||||
|
||||
87
test/jdk/sun/security/ssl/CipherSuite/SupportedGroups.java
Normal file
87
test/jdk/sun/security/ssl/CipherSuite/SupportedGroups.java
Normal file
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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 @@ public class TestAnnotationTypes extends JavadocTester {
|
||||
"<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 @@ public class TestAnnotationTypes extends JavadocTester {
|
||||
"<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>");
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user