diff --git a/make/conf/version-numbers.conf b/make/conf/version-numbers.conf
index a567f7cdbf1..488b0cac1ee 100644
--- a/make/conf/version-numbers.conf
+++ b/make/conf/version-numbers.conf
@@ -39,4 +39,4 @@ DEFAULT_VERSION_CLASSFILE_MINOR=0
DEFAULT_VERSION_DOCS_API_SINCE=11
DEFAULT_ACCEPTABLE_BOOT_VERSIONS="16 17"
DEFAULT_JDK_SOURCE_TARGET_VERSION=17
-DEFAULT_PROMOTED_VERSION_PRE=ea
+DEFAULT_PROMOTED_VERSION_PRE=
diff --git a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp
index 4af947b079d..a197c781f2d 100644
--- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp
@@ -2964,6 +2964,22 @@ class StubGenerator: public StubCodeGenerator {
return start;
}
+ // Big-endian 128-bit + 64-bit -> 128-bit addition.
+ // Inputs: 128-bits. in is preserved.
+ // The least-significant 64-bit word is in the upper dword of the vector
+ // inc (the 64-bit increment) is preserved. Its lower dword must be zero
+ // Output: result
+ void be_add_128_64(FloatRegister result, FloatRegister in,
+ FloatRegister inc, FloatRegister tmp) {
+ assert_different_registers(result, tmp, inc);
+
+ __ addv(result, __ T2D, in, inc); // Add inc to the least-significant dword of input
+ __ cmhi(tmp, __ T2D, inc, result); // Check for result overflowing
+ __ ins(tmp, __ D, tmp, 0, 1); // Move LSD of comparison result to MSD
+ __ ins(tmp, __ D, inc, 1, 0); // Move 0 to LSD of comparison result
+ __ subv(result, __ T2D, result, tmp); // Subtract -1 from MSD if there was an overflow
+ }
+
// CTR AES crypt.
// Arguments:
//
@@ -3073,13 +3089,16 @@ class StubGenerator: public StubCodeGenerator {
// Setup the counter
__ movi(v4, __ T4S, 0);
__ movi(v5, __ T4S, 1);
- __ ins(v4, __ S, v5, 3, 3); // v4 contains { 0, 0, 0, 1 }
+ __ ins(v4, __ S, v5, 2, 2); // v4 contains { 0, 1 }
- __ ld1(v0, __ T16B, counter); // Load the counter into v0
- __ rev32(v16, __ T16B, v0);
- __ addv(v16, __ T4S, v16, v4);
- __ rev32(v16, __ T16B, v16);
- __ st1(v16, __ T16B, counter); // Save the incremented counter back
+ // 128-bit big-endian increment
+ __ ld1(v0, __ T16B, counter);
+ __ rev64(v16, __ T16B, v0);
+ be_add_128_64(v16, v16, v4, /*tmp*/v5);
+ __ rev64(v16, __ T16B, v16);
+ __ st1(v16, __ T16B, counter);
+ // Previous counter value is in v0
+ // v4 contains { 0, 1 }
{
// We have fewer than bulk_width blocks of data left. Encrypt
@@ -3111,9 +3130,9 @@ class StubGenerator: public StubCodeGenerator {
// Increment the counter, store it back
__ orr(v0, __ T16B, v16, v16);
- __ rev32(v16, __ T16B, v16);
- __ addv(v16, __ T4S, v16, v4);
- __ rev32(v16, __ T16B, v16);
+ __ rev64(v16, __ T16B, v16);
+ be_add_128_64(v16, v16, v4, /*tmp*/v5);
+ __ rev64(v16, __ T16B, v16);
__ st1(v16, __ T16B, counter); // Save the incremented counter back
__ b(inner_loop);
@@ -3161,7 +3180,7 @@ class StubGenerator: public StubCodeGenerator {
// Keys should already be loaded into the correct registers
__ ld1(v0, __ T16B, counter); // v0 contains the first counter
- __ rev32(v16, __ T16B, v0); // v16 contains byte-reversed counter
+ __ rev64(v16, __ T16B, v0); // v16 contains byte-reversed counter
// AES/CTR loop
{
@@ -3171,11 +3190,11 @@ class StubGenerator: public StubCodeGenerator {
// Setup the counters
__ movi(v8, __ T4S, 0);
__ movi(v9, __ T4S, 1);
- __ ins(v8, __ S, v9, 3, 3); // v8 contains { 0, 0, 0, 1 }
+ __ ins(v8, __ S, v9, 2, 2); // v8 contains { 0, 1 }
for (FloatRegister f = v0; f < v0 + bulk_width; f++) {
- __ rev32(f, __ T16B, v16);
- __ addv(v16, __ T4S, v16, v8);
+ __ rev64(f, __ T16B, v16);
+ be_add_128_64(v16, v16, v8, /*tmp*/v9);
}
__ ld1(v8, v9, v10, v11, __ T16B, __ post(in, 4 * 16));
@@ -3203,7 +3222,7 @@ class StubGenerator: public StubCodeGenerator {
}
// Save the counter back where it goes
- __ rev32(v16, __ T16B, v16);
+ __ rev64(v16, __ T16B, v16);
__ st1(v16, __ T16B, counter);
__ pop(saved_regs, sp);
diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp
index 5d301847d43..6786e1f2635 100644
--- a/src/hotspot/cpu/x86/assembler_x86.cpp
+++ b/src/hotspot/cpu/x86/assembler_x86.cpp
@@ -2633,6 +2633,16 @@ void Assembler::ktestd(KRegister src1, KRegister src2) {
emit_int16((unsigned char)0x99, (0xC0 | encode));
}
+
+void Assembler::kshiftlbl(KRegister dst, KRegister src, int imm8) {
+ assert(VM_Version::supports_avx512dq(), "");
+ InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false);
+ int encode = vex_prefix_and_encode(dst->encoding(), 0 , src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
+ emit_int16(0x32, (0xC0 | encode));
+ emit_int8(imm8);
+}
+
+
void Assembler::movb(Address dst, int imm8) {
InstructionMark im(this);
prefix(dst);
@@ -3948,6 +3958,14 @@ void Assembler::evpcmpuw(KRegister kdst, XMMRegister nds, XMMRegister src, Compa
emit_int24(0x3E, (0xC0 | encode), vcc);
}
+void Assembler::evpcmpuq(KRegister kdst, XMMRegister nds, XMMRegister src, ComparisonPredicate vcc, int vector_len) {
+ assert(VM_Version::supports_avx512vlbw(), "");
+ InstructionAttr attributes(vector_len, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true);
+ attributes.set_is_evex_instruction();
+ int encode = vex_prefix_and_encode(kdst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
+ emit_int24(0x1E, (0xC0 | encode), vcc);
+}
+
void Assembler::evpcmpuw(KRegister kdst, XMMRegister nds, Address src, ComparisonPredicate vcc, int vector_len) {
assert(VM_Version::supports_avx512vlbw(), "");
InstructionMark im(this);
@@ -6574,6 +6592,19 @@ void Assembler::vpaddq(XMMRegister dst, XMMRegister nds, Address src, int vector
emit_operand(dst, src);
}
+void Assembler::evpaddq(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int vector_len) {
+ assert(VM_Version::supports_evex(), "");
+ assert(vector_len == AVX_512bit || VM_Version::supports_avx512vl(), "");
+ InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false,/* uses_vl */ true);
+ attributes.set_is_evex_instruction();
+ attributes.set_embedded_opmask_register_specifier(mask);
+ if (merge) {
+ attributes.reset_is_clear_context();
+ }
+ int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F, &attributes);
+ emit_int16((unsigned char)0xD4, (0xC0 | encode));
+}
+
void Assembler::psubb(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ _legacy_mode_bw, /* no_mask_reg */ true, /* uses_vl */ true);
diff --git a/src/hotspot/cpu/x86/assembler_x86.hpp b/src/hotspot/cpu/x86/assembler_x86.hpp
index 3c72c93ad40..6d2a7bde5f8 100644
--- a/src/hotspot/cpu/x86/assembler_x86.hpp
+++ b/src/hotspot/cpu/x86/assembler_x86.hpp
@@ -1492,6 +1492,8 @@ class Assembler : public AbstractAssembler {
void ktestql(KRegister dst, KRegister src);
+ void kshiftlbl(KRegister dst, KRegister src, int imm8);
+
void movdl(XMMRegister dst, Register src);
void movdl(Register dst, XMMRegister src);
void movdl(XMMRegister dst, Address src);
@@ -1727,6 +1729,8 @@ class Assembler : public AbstractAssembler {
void evpcmpuw(KRegister kdst, XMMRegister nds, XMMRegister src, ComparisonPredicate vcc, int vector_len);
void evpcmpuw(KRegister kdst, XMMRegister nds, Address src, ComparisonPredicate vcc, int vector_len);
+ void evpcmpuq(KRegister kdst, XMMRegister nds, XMMRegister src, ComparisonPredicate vcc, int vector_len);
+
void pcmpeqw(XMMRegister dst, XMMRegister src);
void vpcmpeqw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
void evpcmpeqw(KRegister kdst, XMMRegister nds, XMMRegister src, int vector_len);
@@ -2249,6 +2253,10 @@ class Assembler : public AbstractAssembler {
void vpaddd(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
void vpaddq(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
+ // Leaf level assembler routines for masked operations.
+ void evpaddq(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int vector_len);
+// void evpaddq(XMMRegister dst, KRegister mask, XMMRegister nds, Address src, bool merge, int vector_len);
+
// Sub packed integers
void psubb(XMMRegister dst, XMMRegister src);
void psubw(XMMRegister dst, XMMRegister src);
diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp
index fcde34b2751..dc5c9023c0d 100644
--- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp
+++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp
@@ -964,6 +964,8 @@ class MacroAssembler: public Assembler {
void roundDec(XMMRegister key, int rnum);
void lastroundDec(XMMRegister key, int rnum);
void ev_load_key(XMMRegister xmmdst, Register key, int offset, XMMRegister xmm_shuf_mask);
+ void ev_add128(XMMRegister xmmdst, XMMRegister xmmsrc1, XMMRegister xmmsrc2,
+ int vector_len, KRegister ktmp, Register rscratch = noreg);
public:
void aesecb_encrypt(Register source_addr, Register dest_addr, Register key, Register len);
diff --git a/src/hotspot/cpu/x86/macroAssembler_x86_aes.cpp b/src/hotspot/cpu/x86/macroAssembler_x86_aes.cpp
index 4f86bc5b695..dcc48a6c1f0 100644
--- a/src/hotspot/cpu/x86/macroAssembler_x86_aes.cpp
+++ b/src/hotspot/cpu/x86/macroAssembler_x86_aes.cpp
@@ -779,6 +779,19 @@ void MacroAssembler::avx_ghash(Register input_state, Register htbl,
vpxor(xmm15, xmm15, xmm15, Assembler::AVX_128bit);
}
+// Add 128-bit integers in xmmsrc1 to xmmsrc2, then place the result in xmmdst.
+// Clobber ktmp and rscratch.
+// Used by aesctr_encrypt.
+void MacroAssembler::ev_add128(XMMRegister xmmdst, XMMRegister xmmsrc1, XMMRegister xmmsrc2,
+ int vector_len, KRegister ktmp, Register rscratch) {
+ vpaddq(xmmdst, xmmsrc1, xmmsrc2, vector_len);
+ evpcmpuq(ktmp, xmmdst, xmmsrc2, lt, vector_len); // set mask[0/1] bit if addq to dst[0/1] wraps
+ kshiftlbl(ktmp, ktmp, 1); // mask[1] <- mask[0], mask[0] <- 0, etc
+
+ evpaddq(xmmdst, ktmp, xmmdst, xmm17, /*merge*/true,
+ vector_len); // dst[1]++ if mask[1] set
+}
+
// AES Counter Mode using VAES instructions
void MacroAssembler::aesctr_encrypt(Register src_addr, Register dest_addr, Register key, Register counter,
Register len_reg, Register used, Register used_addr, Register saved_encCounter_start) {
@@ -831,19 +844,23 @@ void MacroAssembler::aesctr_encrypt(Register src_addr, Register dest_addr, Regis
//shuffle counter using lbswap_mask
vpshufb(xmm8, xmm8, xmm16, Assembler::AVX_512bit);
+ // Vector value to propagate carries
+ evmovdquq(xmm17, ExternalAddress(StubRoutines::x86::counter_mask_ones_addr()), Assembler::AVX_512bit, r15);
// pre-increment and propagate counter values to zmm9-zmm15 registers.
// Linc0 increments the zmm8 by 1 (initial value being 0), Linc4 increments the counters zmm9-zmm15 by 4
// The counter is incremented after each block i.e. 16 bytes is processed;
// each zmm register has 4 counter values as its MSB
// the counters are incremented in parallel
- vpaddd(xmm8, xmm8, ExternalAddress(StubRoutines::x86::counter_mask_addr() + 64), Assembler::AVX_512bit, r15);//linc0
- vpaddd(xmm9, xmm8, ExternalAddress(StubRoutines::x86::counter_mask_addr() + 128), Assembler::AVX_512bit, r15);//linc4(rip)
- vpaddd(xmm10, xmm9, ExternalAddress(StubRoutines::x86::counter_mask_addr() + 128), Assembler::AVX_512bit, r15);//Linc4(rip)
- vpaddd(xmm11, xmm10, ExternalAddress(StubRoutines::x86::counter_mask_addr() + 128), Assembler::AVX_512bit, r15);//Linc4(rip)
- vpaddd(xmm12, xmm11, ExternalAddress(StubRoutines::x86::counter_mask_addr() + 128), Assembler::AVX_512bit, r15);//Linc4(rip)
- vpaddd(xmm13, xmm12, ExternalAddress(StubRoutines::x86::counter_mask_addr() + 128), Assembler::AVX_512bit, r15);//Linc4(rip)
- vpaddd(xmm14, xmm13, ExternalAddress(StubRoutines::x86::counter_mask_addr() + 128), Assembler::AVX_512bit, r15);//Linc4(rip)
- vpaddd(xmm15, xmm14, ExternalAddress(StubRoutines::x86::counter_mask_addr() + 128), Assembler::AVX_512bit, r15);//Linc4(rip)
+ evmovdquq(xmm19, ExternalAddress(StubRoutines::x86::counter_mask_addr() + 64), Assembler::AVX_512bit, r15 /*rscratch*/);//linc0
+ ev_add128(xmm8, xmm8, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15);
+ evmovdquq(xmm19, ExternalAddress(StubRoutines::x86::counter_mask_addr() + 128), Assembler::AVX_512bit, r15 /*rscratch*/);//linc4
+ ev_add128(xmm9, xmm8, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15);
+ ev_add128(xmm10, xmm9, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15);
+ ev_add128(xmm11, xmm10, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15);
+ ev_add128(xmm12, xmm11, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15);
+ ev_add128(xmm13, xmm12, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15);
+ ev_add128(xmm14, xmm13, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15);
+ ev_add128(xmm15, xmm14, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15);
// load linc32 mask in zmm register.linc32 increments counter by 32
evmovdquq(xmm19, ExternalAddress(StubRoutines::x86::counter_mask_addr() + 256), Assembler::AVX_512bit, r15);//Linc32
@@ -891,21 +908,21 @@ void MacroAssembler::aesctr_encrypt(Register src_addr, Register dest_addr, Regis
// This is followed by incrementing counter values in zmm8-zmm15.
// Since we will be processing 32 blocks at a time, the counter is incremented by 32.
roundEnc(xmm21, 7);
- vpaddq(xmm8, xmm8, xmm19, Assembler::AVX_512bit);
+ ev_add128/*!!!*/(xmm8, xmm8, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15 /*rscratch*/);
roundEnc(xmm22, 7);
- vpaddq(xmm9, xmm9, xmm19, Assembler::AVX_512bit);
+ ev_add128/*!!!*/(xmm9, xmm9, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15 /*rscratch*/);
roundEnc(xmm23, 7);
- vpaddq(xmm10, xmm10, xmm19, Assembler::AVX_512bit);
+ ev_add128/*!!!*/(xmm10, xmm10, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15 /*rscratch*/);
roundEnc(xmm24, 7);
- vpaddq(xmm11, xmm11, xmm19, Assembler::AVX_512bit);
+ ev_add128/*!!!*/(xmm11, xmm11, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15 /*rscratch*/);
roundEnc(xmm25, 7);
- vpaddq(xmm12, xmm12, xmm19, Assembler::AVX_512bit);
+ ev_add128/*!!!*/(xmm12, xmm12, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15 /*rscratch*/);
roundEnc(xmm26, 7);
- vpaddq(xmm13, xmm13, xmm19, Assembler::AVX_512bit);
+ ev_add128/*!!!*/(xmm13, xmm13, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15 /*rscratch*/);
roundEnc(xmm27, 7);
- vpaddq(xmm14, xmm14, xmm19, Assembler::AVX_512bit);
+ ev_add128/*!!!*/(xmm14, xmm14, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15 /*rscratch*/);
roundEnc(xmm28, 7);
- vpaddq(xmm15, xmm15, xmm19, Assembler::AVX_512bit);
+ ev_add128/*!!!*/(xmm15, xmm15, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15 /*rscratch*/);
roundEnc(xmm29, 7);
cmpl(rounds, 52);
@@ -983,8 +1000,8 @@ void MacroAssembler::aesctr_encrypt(Register src_addr, Register dest_addr, Regis
vpshufb(xmm3, xmm11, xmm16, Assembler::AVX_512bit);
evpxorq(xmm3, xmm3, xmm20, Assembler::AVX_512bit);
// Increment counter values by 16
- vpaddq(xmm8, xmm8, xmm19, Assembler::AVX_512bit);
- vpaddq(xmm9, xmm9, xmm19, Assembler::AVX_512bit);
+ ev_add128/*!!!*/(xmm8, xmm8, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15 /*rscratch*/);
+ ev_add128/*!!!*/(xmm9, xmm9, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15 /*rscratch*/);
// AES encode rounds
roundEnc(xmm21, 3);
roundEnc(xmm22, 3);
@@ -1051,7 +1068,7 @@ void MacroAssembler::aesctr_encrypt(Register src_addr, Register dest_addr, Regis
vpshufb(xmm1, xmm9, xmm16, Assembler::AVX_512bit);
evpxorq(xmm1, xmm1, xmm20, Assembler::AVX_512bit);
// increment counter by 8
- vpaddq(xmm8, xmm8, xmm19, Assembler::AVX_512bit);
+ ev_add128/*!!!*/(xmm8, xmm8, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15 /*rscratch*/);
// AES encode
roundEnc(xmm21, 1);
roundEnc(xmm22, 1);
@@ -1109,7 +1126,7 @@ void MacroAssembler::aesctr_encrypt(Register src_addr, Register dest_addr, Regis
vpshufb(xmm0, xmm8, xmm16, Assembler::AVX_512bit);
evpxorq(xmm0, xmm0, xmm20, Assembler::AVX_512bit);
// Increment counter
- vpaddq(xmm8, xmm8, xmm19, Assembler::AVX_512bit);
+ ev_add128/*!!!*/(xmm8, xmm8, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15 /*rscratch*/);
vaesenc(xmm0, xmm0, xmm21, Assembler::AVX_512bit);
vaesenc(xmm0, xmm0, xmm22, Assembler::AVX_512bit);
vaesenc(xmm0, xmm0, xmm23, Assembler::AVX_512bit);
@@ -1159,7 +1176,7 @@ void MacroAssembler::aesctr_encrypt(Register src_addr, Register dest_addr, Regis
evpxorq(xmm0, xmm0, xmm20, Assembler::AVX_128bit);
vaesenc(xmm0, xmm0, xmm21, Assembler::AVX_128bit);
// Increment counter by 1
- vpaddq(xmm8, xmm8, xmm19, Assembler::AVX_128bit);
+ ev_add128/*!!!*/(xmm8, xmm8, xmm19, Assembler::AVX_128bit, /*ktmp*/k1, r15 /*rscratch*/);
vaesenc(xmm0, xmm0, xmm22, Assembler::AVX_128bit);
vaesenc(xmm0, xmm0, xmm23, Assembler::AVX_128bit);
vaesenc(xmm0, xmm0, xmm24, Assembler::AVX_128bit);
diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp
index c7634a2e596..d1915b74608 100644
--- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp
+++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp
@@ -4424,7 +4424,19 @@ class StubGenerator: public StubCodeGenerator {
return start;
}
- // Vector AES Counter implementation
+ // Vector AES Counter implementation
+
+ address counter_mask_ones_addr() {
+ __ align64();
+ StubCodeMark mark(this, "StubRoutines", "counter_mask_addr");
+ address start = __ pc();
+ for (int i = 0; i < 4; i ++) {
+ __ emit_data64(0x0000000000000000, relocInfo::none);
+ __ emit_data64(0x0000000000000001, relocInfo::none);
+ }
+ return start;
+ }
+
address generate_counterMode_VectorAESCrypt() {
__ align(CodeEntryAlignment);
StubCodeMark mark(this, "StubRoutines", "counterMode_AESCrypt");
@@ -7641,6 +7653,7 @@ address generate_avx_ghash_processBlocks() {
if (UseAESCTRIntrinsics) {
if (VM_Version::supports_avx512_vaes() && VM_Version::supports_avx512bw() && VM_Version::supports_avx512vl()) {
StubRoutines::x86::_counter_mask_addr = counter_mask_addr();
+ StubRoutines::x86::_counter_mask_ones_addr = counter_mask_ones_addr();
StubRoutines::_counterMode_AESCrypt = generate_counterMode_VectorAESCrypt();
} else {
StubRoutines::x86::_counter_shuffle_mask_addr = generate_counter_shuffle_mask();
diff --git a/src/hotspot/cpu/x86/stubRoutines_x86.cpp b/src/hotspot/cpu/x86/stubRoutines_x86.cpp
index 4471a5498bb..904a5485ff6 100644
--- a/src/hotspot/cpu/x86/stubRoutines_x86.cpp
+++ b/src/hotspot/cpu/x86/stubRoutines_x86.cpp
@@ -71,6 +71,7 @@ address StubRoutines::x86::_avx2_shuffle_base64 = NULL;
address StubRoutines::x86::_avx2_input_mask_base64 = NULL;
address StubRoutines::x86::_avx2_lut_base64 = NULL;
address StubRoutines::x86::_counter_mask_addr = NULL;
+address StubRoutines::x86::_counter_mask_ones_addr = NULL;
address StubRoutines::x86::_lookup_lo_base64 = NULL;
address StubRoutines::x86::_lookup_hi_base64 = NULL;
address StubRoutines::x86::_lookup_lo_base64url = NULL;
diff --git a/src/hotspot/cpu/x86/stubRoutines_x86.hpp b/src/hotspot/cpu/x86/stubRoutines_x86.hpp
index 45f4870c372..84eb964d98f 100644
--- a/src/hotspot/cpu/x86/stubRoutines_x86.hpp
+++ b/src/hotspot/cpu/x86/stubRoutines_x86.hpp
@@ -184,6 +184,7 @@ class x86 {
// byte flip mask for sha512
static address _pshuffle_byte_flip_mask_addr_sha512;
static address _counter_mask_addr;
+ static address _counter_mask_ones_addr;
// Masks for base64
static address _encoding_table_base64;
static address _shuffle_base64;
@@ -343,6 +344,7 @@ class x86 {
static address base64_avx2_input_mask_addr() { return _avx2_input_mask_base64; }
static address base64_avx2_lut_addr() { return _avx2_lut_base64; }
static address counter_mask_addr() { return _counter_mask_addr; }
+ static address counter_mask_ones_addr() { return _counter_mask_ones_addr; }
static address base64_vbmi_lookup_lo_addr() { return _lookup_lo_base64; }
static address base64_vbmi_lookup_hi_addr() { return _lookup_hi_base64; }
static address base64_vbmi_lookup_lo_url_addr() { return _lookup_lo_base64url; }
diff --git a/src/hotspot/share/c1/c1_RangeCheckElimination.cpp b/src/hotspot/share/c1/c1_RangeCheckElimination.cpp
index f5275eb9d5c..fa1678f71c4 100644
--- a/src/hotspot/share/c1/c1_RangeCheckElimination.cpp
+++ b/src/hotspot/share/c1/c1_RangeCheckElimination.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2023, 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
@@ -228,24 +228,23 @@ void RangeCheckEliminator::Visitor::do_ArithmeticOp(ArithmeticOp *ao) {
Bound* y_bound = _rce->get_bound(y);
if (x_bound->lower() >= 0 && x_bound->lower_instr() == NULL && y->as_ArrayLength() != NULL) {
_bound = new Bound(0, NULL, -1, y);
- } else if (y->type()->as_IntConstant() && y->type()->as_IntConstant()->value() != 0) {
+ } else if (x_bound->has_lower() && x_bound->lower() >= 0 && y->type()->as_IntConstant() &&
+ y->type()->as_IntConstant()->value() != 0 && y->type()->as_IntConstant()->value() != min_jint) {
// The binary % operator is said to yield the remainder of its operands from an implied division; the
// left-hand operand is the dividend and the right-hand operand is the divisor.
//
- // % operator follows from this rule that the result of the remainder operation can be negative only
+ // It follows from this rule that the result of the remainder operation can be negative only
// if the dividend is negative, and can be positive only if the dividend is positive. Moreover, the
- // magnitude of the result is always less than the magnitude of the divisor(See JLS 15.17.3).
+ // magnitude of the result is always less than the magnitude of the divisor (see JLS 15.17.3).
//
// So if y is a constant integer and not equal to 0, then we can deduce the bound of remainder operation:
// x % -y ==> [0, y - 1] Apply RCE
// x % y ==> [0, y - 1] Apply RCE
// -x % y ==> [-y + 1, 0]
// -x % -y ==> [-y + 1, 0]
- if (x_bound->has_lower() && x_bound->lower() >= 0) {
- _bound = new Bound(0, NULL, y->type()->as_IntConstant()->value() - 1, NULL);
- } else {
- _bound = new Bound();
- }
+ //
+ // Use the absolute value of y as an upper bound. Skip min_jint because abs(min_jint) is undefined.
+ _bound = new Bound(0, NULL, abs(y->type()->as_IntConstant()->value()) - 1, NULL);
} else {
_bound = new Bound();
}
@@ -270,17 +269,16 @@ void RangeCheckEliminator::Visitor::do_ArithmeticOp(ArithmeticOp *ao) {
Bound * bound = _rce->get_bound(y);
if (bound->has_upper() && bound->has_lower()) {
- int new_lower = bound->lower() + const_value;
- jlong new_lowerl = ((jlong)bound->lower()) + const_value;
- int new_upper = bound->upper() + const_value;
- jlong new_upperl = ((jlong)bound->upper()) + const_value;
-
- if (((jlong)new_lower) == new_lowerl && ((jlong)new_upper == new_upperl)) {
- Bound *newBound = new Bound(new_lower, bound->lower_instr(), new_upper, bound->upper_instr());
- _bound = newBound;
- } else {
- // overflow
+ jint t_lo = bound->lower();
+ jint t_hi = bound->upper();
+ jint new_lower = java_add(t_lo, const_value);
+ jint new_upper = java_add(t_hi, const_value);
+ bool overflow = ((const_value < 0 && (new_lower > t_lo)) ||
+ (const_value > 0 && (new_upper < t_hi)));
+ if (overflow) {
_bound = new Bound();
+ } else {
+ _bound = new Bound(new_lower, bound->lower_instr(), new_upper, bound->upper_instr());
}
} else {
_bound = new Bound();
@@ -1558,7 +1556,6 @@ void RangeCheckEliminator::Bound::add_assertion(Instruction *instruction, Instru
NOT_PRODUCT(ao->set_printable_bci(position->printable_bci()));
result = result->insert_after(ao);
compare_with = ao;
- // TODO: Check that add operation does not overflow!
}
}
assert(compare_with != NULL, "You have to compare with something!");
diff --git a/src/hotspot/share/memory/metaspace.cpp b/src/hotspot/share/memory/metaspace.cpp
index 2c42c013560..3f29a72a86d 100644
--- a/src/hotspot/share/memory/metaspace.cpp
+++ b/src/hotspot/share/memory/metaspace.cpp
@@ -590,8 +590,8 @@ ReservedSpace Metaspace::reserve_address_space_for_compressed_classes(size_t siz
#if defined(AARCH64) || defined(PPC64)
const size_t alignment = Metaspace::reserve_alignment();
- // AArch64: Try to align metaspace so that we can decode a compressed
- // klass with a single MOVK instruction. We can do this iff the
+ // AArch64: Try to align metaspace class space so that we can decode a
+ // compressed klass with a single MOVK instruction. We can do this iff the
// compressed class base is a multiple of 4G.
// Additionally, above 32G, ensure the lower LogKlassAlignmentInBytes bits
// of the upper 32-bits of the address are zero so we can handle a shift
@@ -614,19 +614,39 @@ ReservedSpace Metaspace::reserve_address_space_for_compressed_classes(size_t siz
{ NULL, NULL, 0 }
};
+ // Calculate a list of all possible values for the starting address for the
+ // compressed class space.
+ ResourceMark rm;
+ GrowableArray
list(36);
for (int i = 0; search_ranges[i].from != NULL; i ++) {
address a = search_ranges[i].from;
assert(CompressedKlassPointers::is_valid_base(a), "Sanity");
while (a < search_ranges[i].to) {
- ReservedSpace rs(size, Metaspace::reserve_alignment(),
- os::vm_page_size(), (char*)a);
- if (rs.is_reserved()) {
- assert(a == (address)rs.base(), "Sanity");
- return rs;
- }
+ list.append(a);
a += search_ranges[i].increment;
}
}
+
+ int len = list.length();
+ int r = 0;
+ if (!DumpSharedSpaces) {
+ // Starting from a random position in the list. If the address cannot be reserved
+ // (the OS already assigned it for something else), go to the next position, wrapping
+ // around if necessary, until we exhaust all the items.
+ os::init_random((int)os::javaTimeNanos());
+ r = os::random();
+ log_info(metaspace)("Randomizing compressed class space: start from %d out of %d locations",
+ r % len, len);
+ }
+ for (int i = 0; i < len; i++) {
+ address a = list.at((i + r) % len);
+ ReservedSpace rs(size, Metaspace::reserve_alignment(),
+ os::vm_page_size(), (char*)a);
+ if (rs.is_reserved()) {
+ assert(a == (address)rs.base(), "Sanity");
+ return rs;
+ }
+ }
#endif // defined(AARCH64) || defined(PPC64)
#ifdef AARCH64
diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp
index 400a385a3bf..bac01d82878 100644
--- a/src/hotspot/share/runtime/globals.hpp
+++ b/src/hotspot/share/runtime/globals.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2023, 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
@@ -2010,10 +2010,10 @@ const intx ObjectAlignmentInBytes = 8;
product(ccstr, ExtraSharedClassListFile, NULL, \
"Extra classlist for building the CDS archive file") \
\
- product(intx, ArchiveRelocationMode, 0, DIAGNOSTIC, \
+ product(intx, ArchiveRelocationMode, 1, DIAGNOSTIC, \
"(0) first map at preferred address, and if " \
- "unsuccessful, map at alternative address (default); " \
- "(1) always map at alternative address; " \
+ "unsuccessful, map at alternative address; " \
+ "(1) always map at alternative address (default); " \
"(2) always map at preferred address, and if unsuccessful, " \
"do not map the archive") \
range(0, 2) \
diff --git a/src/java.base/macosx/classes/apple/security/KeychainStore.java b/src/java.base/macosx/classes/apple/security/KeychainStore.java
index e4a77e61cca..7cb280035e3 100644
--- a/src/java.base/macosx/classes/apple/security/KeychainStore.java
+++ b/src/java.base/macosx/classes/apple/security/KeychainStore.java
@@ -69,7 +69,7 @@ static class TrustedCertEntry {
Certificate cert;
long certRef; // SecCertificateRef for this key
- // Each KeyStore.TrustedCertificateEntry have 2 attributes:
+ // Each KeyStore.TrustedCertificateEntry has 2 attributes:
// 1. "trustSettings" -> trustSettings.toString()
// 2. "2.16.840.1.113894.746875.1.1" -> trustedKeyUsageValue
// The 1st one is mainly for debugging use. The 2nd one is similar
@@ -660,7 +660,6 @@ public void engineStore(OutputStream stream, char[] password)
_releaseKeychainItemRef(((TrustedCertEntry)entry).certRef);
}
} else {
- Certificate certElem;
KeyEntry keyEntry = (KeyEntry)entry;
if (keyEntry.chain != null) {
@@ -812,8 +811,26 @@ private void createTrustedCertEntry(String alias, List inputTrust,
tce.cert = cert;
tce.certRef = keychainItemRef;
+ // Check whether a certificate with same alias already exists and is the same
+ // If yes, we can return here - the existing entry must have the same
+ // properties and trust settings
+ if (entries.contains(alias.toLowerCase())) {
+ int uniqueVal = 1;
+ String originalAlias = alias;
+ var co = entries.get(alias.toLowerCase());
+ while (co != null) {
+ if (co instanceof TrustedCertEntry tco) {
+ if (tco.cert.equals(tce.cert)) {
+ return;
+ }
+ }
+ alias = originalAlias + " " + uniqueVal++;
+ co = entries.get(alias.toLowerCase());
+ }
+ }
+
tce.trustSettings = new ArrayList<>();
- Map tmpMap = new LinkedHashMap<>();
+ Map tmpMap = new LinkedHashMap<>();
for (int i = 0; i < inputTrust.size(); i++) {
if (inputTrust.get(i) == null) {
tce.trustSettings.add(tmpMap);
@@ -836,9 +853,10 @@ private void createTrustedCertEntry(String alias, List inputTrust,
} catch (Exception e) {
isSelfSigned = false;
}
+
if (tce.trustSettings.isEmpty()) {
if (isSelfSigned) {
- // If a self-signed certificate has an empty trust settings,
+ // If a self-signed certificate has trust settings without specific entries,
// trust it for all purposes
tce.trustedKeyUsageValue = KnownOIDs.anyExtendedKeyUsage.value();
} else {
@@ -851,11 +869,19 @@ private void createTrustedCertEntry(String alias, List inputTrust,
for (var oneTrust : tce.trustSettings) {
var result = oneTrust.get("kSecTrustSettingsResult");
// https://developer.apple.com/documentation/security/sectrustsettingsresult?language=objc
- // 1 = kSecTrustSettingsResultTrustRoot, 2 = kSecTrustSettingsResultTrustAsRoot
+ // 1 = kSecTrustSettingsResultTrustRoot, 2 = kSecTrustSettingsResultTrustAsRoot,
+ // 3 = kSecTrustSettingsResultDeny
// If missing, a default value of kSecTrustSettingsResultTrustRoot is assumed
- // for self-signed certificates (see doc for SecTrustSettingsCopyTrustSettings).
+ // (see doc for SecTrustSettingsCopyTrustSettings).
// Note that the same SecPolicyOid can appear in multiple trust settings
// for different kSecTrustSettingsAllowedError and/or kSecTrustSettingsPolicyString.
+
+ // If we find explicit distrust in some record, we ignore the certificate
+ if ("3".equals(result)) {
+ return;
+ }
+
+ // Trust, if explicitly trusted or result is null and certificate is self signed
if ((result == null && isSelfSigned)
|| "1".equals(result) || "2".equals(result)) {
// When no kSecTrustSettingsPolicy, it means everything
@@ -875,20 +901,13 @@ private void createTrustedCertEntry(String alias, List inputTrust,
tce.trustedKeyUsageValue = values.toString();
}
}
+
// Make a creation date.
if (creationDate != 0)
tce.date = new Date(creationDate);
else
tce.date = new Date();
- int uniqueVal = 1;
- String originalAlias = alias;
-
- while (entries.containsKey(alias.toLowerCase())) {
- alias = originalAlias + " " + uniqueVal;
- uniqueVal++;
- }
-
entries.put(alias.toLowerCase(), tce);
} catch (Exception e) {
// The certificate will be skipped.
diff --git a/src/java.base/macosx/native/libosxsecurity/KeystoreImpl.m b/src/java.base/macosx/native/libosxsecurity/KeystoreImpl.m
index 38362709d27..b4e19a27995 100644
--- a/src/java.base/macosx/native/libosxsecurity/KeystoreImpl.m
+++ b/src/java.base/macosx/native/libosxsecurity/KeystoreImpl.m
@@ -381,6 +381,35 @@ static void addIdentitiesToKeystore(JNIEnv *env, jobject keyStore)
#define ADDNULL(list) (*env)->CallBooleanMethod(env, list, jm_listAdd, NULL)
+
+static void addTrustSettingsToInputTrust(JNIEnv *env, jmethodID jm_listAdd, CFArrayRef trustSettings, jobject inputTrust)
+{
+ CFIndex count = CFArrayGetCount(trustSettings);
+ for (int i = 0; i < count; i++) {
+ CFDictionaryRef oneTrust = (CFDictionaryRef) CFArrayGetValueAtIndex(trustSettings, i);
+ CFIndex size = CFDictionaryGetCount(oneTrust);
+ const void * keys [size];
+ const void * values [size];
+ CFDictionaryGetKeysAndValues(oneTrust, keys, values);
+ for (int j = 0; j < size; j++) {
+ NSString* s = [NSString stringWithFormat:@"%@", keys[j]];
+ ADD(inputTrust, s);
+ s = [NSString stringWithFormat:@"%@", values[j]];
+ ADD(inputTrust, s);
+ }
+ SecPolicyRef certPolicy;
+ certPolicy = (SecPolicyRef)CFDictionaryGetValue(oneTrust, kSecTrustSettingsPolicy);
+ if (certPolicy != NULL) {
+ CFDictionaryRef policyDict = SecPolicyCopyProperties(certPolicy);
+ ADD(inputTrust, @"SecPolicyOid");
+ NSString* s = [NSString stringWithFormat:@"%@", CFDictionaryGetValue(policyDict, @"SecPolicyOid")];
+ ADD(inputTrust, s);
+ CFRelease(policyDict);
+ }
+ ADDNULL(inputTrust);
+ }
+}
+
static void addCertificatesToKeystore(JNIEnv *env, jobject keyStore)
{
// Search the user keychain list for all X509 certificates.
@@ -435,46 +464,40 @@ static void addCertificatesToKeystore(JNIEnv *env, jobject keyStore)
goto errOut;
}
- // Only add certificates with trusted settings
- CFArrayRef trustSettings;
- if (SecTrustSettingsCopyTrustSettings(certRef, kSecTrustSettingsDomainUser, &trustSettings)
- == errSecItemNotFound) {
- continue;
- }
-
// See KeychainStore::createTrustedCertEntry for content of inputTrust
- jobject inputTrust = (*env)->NewObject(env, jc_arrayListClass, jm_arrayListCons);
- if (inputTrust == NULL) {
+ // We load trust settings from domains kSecTrustSettingsDomainUser and kSecTrustSettingsDomainAdmin
+ // kSecTrustSettingsDomainSystem is ignored because it seems to only contain data for root certificates
+ jobject inputTrust = NULL;
+ CFArrayRef trustSettings = NULL;
+
+ // Load user trustSettings into inputTrust
+ if (SecTrustSettingsCopyTrustSettings(certRef, kSecTrustSettingsDomainUser, &trustSettings) == errSecSuccess && trustSettings != NULL) {
+ inputTrust = (*env)->NewObject(env, jc_arrayListClass, jm_arrayListCons);
+ if (inputTrust == NULL) {
+ CFRelease(trustSettings);
+ goto errOut;
+ }
+ addTrustSettingsToInputTrust(env, jm_listAdd, trustSettings, inputTrust);
CFRelease(trustSettings);
- goto errOut;
}
-
- // Dump everything inside trustSettings into inputTrust
- CFIndex count = CFArrayGetCount(trustSettings);
- for (int i = 0; i < count; i++) {
- CFDictionaryRef oneTrust = (CFDictionaryRef) CFArrayGetValueAtIndex(trustSettings, i);
- CFIndex size = CFDictionaryGetCount(oneTrust);
- const void * keys [size];
- const void * values [size];
- CFDictionaryGetKeysAndValues(oneTrust, keys, values);
- for (int j = 0; j < size; j++) {
- NSString* s = [NSString stringWithFormat:@"%@", keys[j]];
- ADD(inputTrust, s);
- s = [NSString stringWithFormat:@"%@", values[j]];
- ADD(inputTrust, s);
+ // Load admin trustSettings into inputTrust
+ trustSettings = NULL;
+ if (SecTrustSettingsCopyTrustSettings(certRef, kSecTrustSettingsDomainAdmin, &trustSettings) == errSecSuccess && trustSettings != NULL) {
+ if (inputTrust == NULL) {
+ inputTrust = (*env)->NewObject(env, jc_arrayListClass, jm_arrayListCons);
}
- SecPolicyRef certPolicy;
- certPolicy = (SecPolicyRef)CFDictionaryGetValue(oneTrust, kSecTrustSettingsPolicy);
- if (certPolicy != NULL) {
- CFDictionaryRef policyDict = SecPolicyCopyProperties(certPolicy);
- ADD(inputTrust, @"SecPolicyOid");
- NSString* s = [NSString stringWithFormat:@"%@", CFDictionaryGetValue(policyDict, @"SecPolicyOid")];
- ADD(inputTrust, s);
- CFRelease(policyDict);
+ if (inputTrust == NULL) {
+ CFRelease(trustSettings);
+ goto errOut;
}
- ADDNULL(inputTrust);
+ addTrustSettingsToInputTrust(env, jm_listAdd, trustSettings, inputTrust);
+ CFRelease(trustSettings);
+ }
+
+ // Only add certificates with trust settings
+ if (inputTrust == NULL) {
+ continue;
}
- CFRelease(trustSettings);
// Find the creation date.
jlong creationDate = getModDateFromItem(env, theItem);
diff --git a/src/java.base/share/classes/java/util/jar/JarFile.java b/src/java.base/share/classes/java/util/jar/JarFile.java
index f0cd0e5c382..bd538649a4f 100644
--- a/src/java.base/share/classes/java/util/jar/JarFile.java
+++ b/src/java.base/share/classes/java/util/jar/JarFile.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2023, 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
@@ -29,6 +29,7 @@
import jdk.internal.access.JavaUtilZipFileAccess;
import sun.security.action.GetPropertyAction;
import sun.security.util.ManifestEntryVerifier;
+import sun.security.util.SignatureFileVerifier;
import java.io.ByteArrayInputStream;
import java.io.EOFException;
@@ -151,8 +152,6 @@ public class JarFile extends ZipFile {
private static final boolean MULTI_RELEASE_ENABLED;
private static final boolean MULTI_RELEASE_FORCED;
private static final ThreadLocal isInitializing = new ThreadLocal<>();
- // The maximum size of array to allocate. Some VMs reserve some header words in an array.
- private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
private SoftReference manRef;
private JarEntry manEntry;
@@ -800,8 +799,11 @@ private void initializeVerifier() {
private byte[] getBytes(ZipEntry ze) throws IOException {
try (InputStream is = super.getInputStream(ze)) {
long uncompressedSize = ze.getSize();
- if (uncompressedSize > MAX_ARRAY_SIZE) {
- throw new IOException("Unsupported size: " + uncompressedSize);
+ if (uncompressedSize > SignatureFileVerifier.MAX_SIG_FILE_SIZE) {
+ throw new IOException("Unsupported size: " + uncompressedSize +
+ " for JarEntry " + ze.getName() +
+ ". Allowed max size: " +
+ SignatureFileVerifier.MAX_SIG_FILE_SIZE + " bytes");
}
int len = (int)uncompressedSize;
int bytesRead;
diff --git a/src/java.base/share/classes/java/util/zip/ZipFile.java b/src/java.base/share/classes/java/util/zip/ZipFile.java
index f073fe8fb1b..a2573f83f66 100644
--- a/src/java.base/share/classes/java/util/zip/ZipFile.java
+++ b/src/java.base/share/classes/java/util/zip/ZipFile.java
@@ -69,6 +69,7 @@
import jdk.internal.ref.CleanerFactory;
import jdk.internal.vm.annotation.Stable;
import sun.nio.cs.UTF_8;
+import sun.security.action.GetBooleanAction;
import sun.security.util.SignatureFileVerifier;
import static java.util.zip.ZipConstants64.*;
@@ -121,6 +122,12 @@ public class ZipFile implements ZipConstants, Closeable {
*/
public static final int OPEN_DELETE = 0x4;
+ /**
+ * Flag which specifies whether the validation of the Zip64 extra
+ * fields should be disabled
+ */
+ private static final boolean disableZip64ExtraFieldValidation =
+ GetBooleanAction.privilegedGetProperty("jdk.util.zip.disableZip64ExtraFieldValidation");
/**
* Opens a zip file for reading.
*
@@ -1195,6 +1202,16 @@ private int checkAndAddEntry(int pos, int index)
if (entryPos + nlen > cen.length - ENDHDR) {
zerror("invalid CEN header (bad header size)");
}
+
+ int elen = CENEXT(cen, pos);
+ if (elen > 0 && !disableZip64ExtraFieldValidation) {
+ long extraStartingOffset = pos + CENHDR + nlen;
+ if ((int)extraStartingOffset != extraStartingOffset) {
+ zerror("invalid CEN header (bad extra offset)");
+ }
+ checkExtraFields(pos, (int)extraStartingOffset, elen);
+ }
+
try {
ZipCoder zcp = zipCoderForPos(pos);
int hash = zcp.checkedHash(cen, entryPos, nlen);
@@ -1211,6 +1228,119 @@ private int checkAndAddEntry(int pos, int index)
return nlen;
}
+ /**
+ * Validate the Zip64 Extra block fields
+ * @param startingOffset Extra Field starting offset within the CEN
+ * @param extraFieldLen Length of this Extra field
+ * @throws ZipException If an error occurs validating the Zip64 Extra
+ * block
+ */
+ private void checkExtraFields(int cenPos, int startingOffset,
+ int extraFieldLen) throws ZipException {
+ // Extra field Length cannot exceed 65,535 bytes per the PKWare
+ // APP.note 4.4.11
+ if (extraFieldLen > 0xFFFF) {
+ zerror("invalid extra field length");
+ }
+ // CEN Offset where this Extra field ends
+ int extraEndOffset = startingOffset + extraFieldLen;
+ if (extraEndOffset > cen.length) {
+ zerror("Invalid CEN header (extra data field size too long)");
+ }
+ int currentOffset = startingOffset;
+ while (currentOffset < extraEndOffset) {
+ int tag = get16(cen, currentOffset);
+ currentOffset += Short.BYTES;
+
+ int tagBlockSize = get16(cen, currentOffset);
+ int tagBlockEndingOffset = currentOffset + tagBlockSize;
+
+ // The ending offset for this tag block should not go past the
+ // offset for the end of the extra field
+ if (tagBlockEndingOffset > extraEndOffset) {
+ zerror("Invalid CEN header (invalid zip64 extra data field size)");
+ }
+ currentOffset += Short.BYTES;
+
+ if (tag == ZIP64_EXTID) {
+ // Get the compressed size;
+ long csize = CENSIZ(cen, cenPos);
+ // Get the uncompressed size;
+ long size = CENLEN(cen, cenPos);
+ checkZip64ExtraFieldValues(currentOffset, tagBlockSize,
+ csize, size);
+ }
+ currentOffset += tagBlockSize;
+ }
+ }
+
+ /**
+ * Validate the Zip64 Extended Information Extra Field (0x0001) block
+ * size and that the uncompressed size and compressed size field
+ * values are not negative.
+ * Note: As we do not use the LOC offset or Starting disk number
+ * field value we will not validate them
+ * @param off the starting offset for the Zip64 field value
+ * @param blockSize the size of the Zip64 Extended Extra Field
+ * @param csize CEN header compressed size value
+ * @param size CEN header uncompressed size value
+ * @throws ZipException if an error occurs
+ */
+ private void checkZip64ExtraFieldValues(int off, int blockSize, long csize,
+ long size)
+ throws ZipException {
+ byte[] cen = this.cen;
+ // Validate the Zip64 Extended Information Extra Field (0x0001)
+ // length.
+ if (!isZip64ExtBlockSizeValid(blockSize)) {
+ zerror("Invalid CEN header (invalid zip64 extra data field size)");
+ }
+ // Check the uncompressed size is not negative
+ // Note we do not need to check blockSize is >= 8 as
+ // we know its length is at least 8 from the call to
+ // isZip64ExtBlockSizeValid()
+ if ((size == ZIP64_MAGICVAL)) {
+ if(get64(cen, off) < 0) {
+ zerror("Invalid zip64 extra block size value");
+ }
+ }
+ // Check the compressed size is not negative
+ if ((csize == ZIP64_MAGICVAL) && (blockSize >= 16)) {
+ if (get64(cen, off + 8) < 0) {
+ zerror("Invalid zip64 extra block compressed size value");
+ }
+ }
+ }
+
+ /**
+ * Validate the size and contents of a Zip64 extended information field
+ * The order of the Zip64 fields is fixed, but the fields MUST
+ * only appear if the corresponding LOC or CEN field is set to 0xFFFF:
+ * or 0xFFFFFFFF:
+ * Uncompressed Size - 8 bytes
+ * Compressed Size - 8 bytes
+ * LOC Header offset - 8 bytes
+ * Disk Start Number - 4 bytes
+ * See PKWare APP.Note Section 4.5.3 for more details
+ *
+ * @param blockSize the Zip64 Extended Information Extra Field size
+ * @return true if the extra block size is valid; false otherwise
+ */
+ private static boolean isZip64ExtBlockSizeValid(int blockSize) {
+ /*
+ * As the fields must appear in order, the block size indicates which
+ * fields to expect:
+ * 8 - uncompressed size
+ * 16 - uncompressed size, compressed size
+ * 24 - uncompressed size, compressed sise, LOC Header offset
+ * 28 - uncompressed size, compressed sise, LOC Header offset,
+ * and Disk start number
+ */
+ return switch(blockSize) {
+ case 8, 16, 24, 28 -> true;
+ default -> false;
+ };
+ }
private int getEntryHash(int index) { return entries[index]; }
private int getEntryNext(int index) { return entries[index + 1]; }
private int getEntryPos(int index) { return entries[index + 2]; }
diff --git a/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java b/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java
index d07152eeb18..4ea9255ba0a 100644
--- a/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java
+++ b/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2023, 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
@@ -52,6 +52,7 @@
import java.util.jar.JarFile;
import java.util.jar.Manifest;
+import sun.security.action.GetIntegerAction;
import sun.security.jca.Providers;
import sun.security.pkcs.PKCS7;
import sun.security.pkcs.SignerInfo;
@@ -97,6 +98,12 @@ public class SignatureFileVerifier {
/** ConstraintsParameters for checking disabled algorithms */
private JarConstraintsParameters params;
+ // the maximum allowed size in bytes for the signature-related files
+ public static final int MAX_SIG_FILE_SIZE = initializeMaxSigFileSize();
+
+ // The maximum size of array to allocate. Some VMs reserve some header words in an array.
+ private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
+
/**
* Create the named SignatureFileVerifier.
*
@@ -842,4 +849,24 @@ void updateSigners(CodeSigner[] newSigners,
signerCache.add(cachedSigners);
signers.put(name, cachedSigners);
}
+
+ private static int initializeMaxSigFileSize() {
+ /*
+ * System property "jdk.jar.maxSignatureFileSize" used to configure
+ * the maximum allowed number of bytes for the signature-related files
+ * in a JAR file.
+ */
+ Integer tmp = GetIntegerAction.privilegedGetProperty(
+ "jdk.jar.maxSignatureFileSize", 8000000);
+ if (tmp < 0 || tmp > MAX_ARRAY_SIZE) {
+ if (debug != null) {
+ debug.println("Default signature file size 8000000 bytes " +
+ "is used as the specified size for the " +
+ "jdk.jar.maxSignatureFileSize system property " +
+ "is out of range: " + tmp);
+ }
+ tmp = 8000000;
+ }
+ return tmp;
+ }
}
diff --git a/src/java.base/share/conf/security/java.security b/src/java.base/share/conf/security/java.security
index fab52688c04..9be02033877 100644
--- a/src/java.base/share/conf/security/java.security
+++ b/src/java.base/share/conf/security/java.security
@@ -888,7 +888,8 @@ jdk.tls.legacyAlgorithms=NULL, anon, RC4, DES, 3DES_EDE_CBC
# Note: This property is currently used by OpenJDK's JSSE implementation. It
# is not guaranteed to be examined and used by other implementations.
#
-jdk.tls.keyLimits=AES/GCM/NoPadding KeyUpdate 2^37
+jdk.tls.keyLimits=AES/GCM/NoPadding KeyUpdate 2^37, \
+ ChaCha20-Poly1305 KeyUpdate 2^37
#
# Cryptographic Jurisdiction Policy defaults
diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java b/src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java
index a315f863021..08efc2b35a4 100644
--- a/src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java
+++ b/src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java
@@ -75,10 +75,6 @@ static Path fromUri(UnixFileSystem fs, URI uri) {
int pos = 0;
while (pos < len) {
char c = p.charAt(pos++);
- if ((c == '/') && (pos < len) && (p.charAt(pos) == '/')) {
- // skip redundant slashes
- continue;
- }
byte b;
if (c == '%') {
assert (pos+2) <= len;
@@ -92,6 +88,10 @@ static Path fromUri(UnixFileSystem fs, URI uri) {
throw new IllegalArgumentException("Bad escape");
b = (byte)c;
}
+ if (b == '/' && rlen > 0 && result[rlen-1] == '/') {
+ // skip redundant slashes
+ continue;
+ }
result[rlen++] = b;
}
if (rlen != result.length)
diff --git a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java
index 52c7ab078c3..910d13668d2 100644
--- a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java
+++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java
@@ -615,6 +615,18 @@ public void load(InputStream input, Class> resourceBase) throws
* new URL(synthFile, path)
. Refer to
* Synth File Format for more
* information.
+ *
+ * Whilst this API may be safe for loading local resources that are
+ * delivered with a {@code LookAndFeel} or application, and so have an
+ * equal level of trust with application code, using it to load from
+ * remote resources, particularly any which may have a lower level of
+ * trust, is strongly discouraged.
+ * The alternative mechanisms to load styles from an {@code InputStream}
+ * {@linkplain #load(InputStream, Class)}
+ * using resources co-located with the application or by providing a
+ * {@code SynthStyleFactory} to
+ * {@linkplain #setStyleFactory setStyleFactory(SynthStyleFactory)}
+ * are preferred.
*
* @param url the URL
to load the set of
* SynthStyle
from
diff --git a/src/java.desktop/share/classes/javax/swing/plaf/synth/doc-files/synthFileFormat.html b/src/java.desktop/share/classes/javax/swing/plaf/synth/doc-files/synthFileFormat.html
index 8eb1bbda9c1..7d63fa16dca 100644
--- a/src/java.desktop/share/classes/javax/swing/plaf/synth/doc-files/synthFileFormat.html
+++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/doc-files/synthFileFormat.html
@@ -70,6 +70,8 @@
This example loads the look and feel from an input stream, using
the specified class as the resource base to resolve paths.
+
+
It is also possible to load a look and feel from an arbitrary URL
as in the following example.
@@ -94,6 +96,11 @@
Remote JAR file, e.g.
jar:http://host/synth-laf.jar!/laf.xml
+ Note: Synth's file format allows for the definition of code to be executed.
+ Loading any code from a remote location should be used only
+ with extreme caution from a trusted source over a secure connection.
+ It is strongly discouraged for an application or a LookAndFeel to do so.
+
While the DTD for synth is specified, the parser is not validating.
Parsing will fail only if a necessary attribute is not
diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/ResponseBodyHandlers.java b/src/java.net.http/share/classes/jdk/internal/net/http/ResponseBodyHandlers.java
index 329f183ce7a..66d89ae1fc5 100644
--- a/src/java.net.http/share/classes/jdk/internal/net/http/ResponseBodyHandlers.java
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/ResponseBodyHandlers.java
@@ -45,6 +45,7 @@
import java.net.http.HttpResponse.BodyHandler;
import java.net.http.HttpResponse.ResponseInfo;
import java.net.http.HttpResponse.BodySubscriber;
+import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import jdk.internal.net.http.ResponseSubscribers.PathSubscriber;
@@ -229,16 +230,120 @@ private FileDownloadBodyHandler(Path directory,
static final String DISPOSITION_TYPE = "attachment;";
/** The "filename" parameter. */
- static final Pattern FILENAME = Pattern.compile("filename\\s*=", CASE_INSENSITIVE);
+ static final Pattern FILENAME = Pattern.compile("filename\\s*=\\s*", CASE_INSENSITIVE);
static final List PROHIBITED = List.of(".", "..", "", "~" , "|");
+ // Characters disallowed in token values
+
+ static final Set NOT_ALLOWED_IN_TOKEN = Set.of(
+ '(', ')', '<', '>', '@',
+ ',', ';', ':', '\\', '"',
+ '/', '[', ']', '?', '=',
+ '{', '}', ' ', '\t');
+
+ static boolean allowedInToken(char c) {
+ if (NOT_ALLOWED_IN_TOKEN.contains(c))
+ return false;
+ // exclude CTL chars <= 31, == 127, or anything >= 128
+ return isTokenText(c);
+ }
+
static final UncheckedIOException unchecked(ResponseInfo rinfo,
String msg) {
String s = String.format("%s in response [%d, %s]", msg, rinfo.statusCode(), rinfo.headers());
return new UncheckedIOException(new IOException(s));
}
+ static final UncheckedIOException unchecked(String msg) {
+ return new UncheckedIOException(new IOException(msg));
+ }
+
+ // Process a "filename=" parameter, which is either a "token"
+ // or a "quoted string". If a token, it is terminated by a
+ // semicolon or the end of the string.
+ // If a quoted string (surrounded by "" chars then the closing "
+ // terminates the name.
+ // quoted strings may contain quoted-pairs (eg embedded " chars)
+
+ static String processFilename(String src) throws UncheckedIOException {
+ if ("".equals(src))
+ return src;
+ if (src.charAt(0) == '\"') {
+ return processQuotedString(src.substring(1));
+ } else {
+ return processToken(src);
+ }
+ }
+
+ static boolean isTokenText(char c) throws UncheckedIOException {
+ return c > 31 && c < 127;
+ }
+
+ static boolean isQuotedStringText(char c) throws UncheckedIOException {
+ return c > 31;
+ }
+
+ static String processQuotedString(String src) throws UncheckedIOException {
+ boolean inqpair = false;
+ int len = src.length();
+ StringBuilder sb = new StringBuilder();
+
+ for (int i=0; i apply(ResponseInfo responseInfo) {
String dispoHeader = responseInfo.headers().firstValue("Content-Disposition")
@@ -256,13 +361,7 @@ public BodySubscriber apply(ResponseInfo responseInfo) {
}
int n = matcher.end();
- int semi = dispoHeader.substring(n).indexOf(";");
- String filenameParam;
- if (semi < 0) {
- filenameParam = dispoHeader.substring(n);
- } else {
- filenameParam = dispoHeader.substring(n, n + semi);
- }
+ String filenameParam = processFilename(dispoHeader.substring(n));
// strip all but the last path segment
int x = filenameParam.lastIndexOf("/");
@@ -276,19 +375,6 @@ public BodySubscriber apply(ResponseInfo responseInfo) {
filenameParam = filenameParam.trim();
- if (filenameParam.startsWith("\"")) { // quoted-string
- if (!filenameParam.endsWith("\"") || filenameParam.length() == 1) {
- throw unchecked(responseInfo,
- "Badly quoted Content-Disposition filename parameter");
- }
- filenameParam = filenameParam.substring(1, filenameParam.length() -1 );
- } else { // token,
- if (filenameParam.contains(" ")) { // space disallowed
- throw unchecked(responseInfo,
- "unquoted space in Content-Disposition filename parameter");
- }
- }
-
if (PROHIBITED.contains(filenameParam)) {
throw unchecked(responseInfo,
"Prohibited Content-Disposition filename parameter:"
diff --git a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java
index cff2dc4d6bb..df75739188f 100644
--- a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java
+++ b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2023, 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
@@ -728,6 +728,13 @@ void verifyJar(String jarName)
&& SignatureFileVerifier.isBlockOrSF(name)) {
String alias = name.substring(name.lastIndexOf('/') + 1,
name.lastIndexOf('.'));
+ long uncompressedSize = je.getSize();
+ if (uncompressedSize > SignatureFileVerifier.MAX_SIG_FILE_SIZE) {
+ unparsableSignatures.putIfAbsent(alias, String.format(
+ rb.getString("history.unparsable"), name));
+ continue;
+ }
+
try {
if (name.endsWith(".SF")) {
Manifest sf = new Manifest(is);
diff --git a/src/jdk.jshell/share/classes/jdk/jshell/execution/JdiInitiator.java b/src/jdk.jshell/share/classes/jdk/jshell/execution/JdiInitiator.java
index d06d587f277..61ddf1759ef 100644
--- a/src/jdk.jshell/share/classes/jdk/jshell/execution/JdiInitiator.java
+++ b/src/jdk.jshell/share/classes/jdk/jshell/execution/JdiInitiator.java
@@ -79,7 +79,8 @@ public class JdiInitiator {
* @param timeout the start-up time-out in milliseconds. If zero or negative,
* will not wait thus will timeout immediately if not already started.
* @param customConnectorArgs custom arguments passed to the connector.
- * These are JDI com.sun.jdi.connect.Connector arguments.
+ * These are JDI com.sun.jdi.connect.Connector arguments. The {@code vmexec}
+ * argument is not supported.
*/
public JdiInitiator(int port, List remoteVMOptions, String remoteAgent,
boolean isLaunch, String host, int timeout,
@@ -104,7 +105,10 @@ public JdiInitiator(int port, List remoteVMOptions, String remoteAgent,
argumentName2Value.put("localAddress", host);
}
}
- argumentName2Value.putAll(customConnectorArgs);
+ customConnectorArgs.entrySet()
+ .stream()
+ .filter(e -> !"vmexec".equals(e.getKey()))
+ .forEach(e -> argumentName2Value.put(e.getKey(), e.getValue()));
this.connectorArgs = mergeConnectorArgs(connector, argumentName2Value);
this.vm = isLaunch
? launchTarget()
diff --git a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java
index 1ce7c2d8783..886be5794ba 100644
--- a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java
+++ b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2023, 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
@@ -3063,6 +3063,11 @@ private void readExtra(ZipFileSystem zipfs) throws IOException {
if (extra == null)
return;
int elen = extra.length;
+ // Extra field Length cannot exceed 65,535 bytes per the PKWare
+ // APP.note 4.4.11
+ if (elen > 0xFFFF) {
+ throw new ZipException("invalid extra field length");
+ }
int off = 0;
int newOff = 0;
boolean hasZip64LocOffset = false;
@@ -3072,26 +3077,40 @@ private void readExtra(ZipFileSystem zipfs) throws IOException {
int tag = SH(extra, pos);
int sz = SH(extra, pos + 2);
pos += 4;
- if (pos + sz > elen) // invalid data
- break;
+ if (pos + sz > elen) { // invalid data
+ throw new ZipException("Invalid CEN header (invalid zip64 extra data field size)");
+ }
switch (tag) {
case EXTID_ZIP64 :
+ // Check to see if we have a valid block size
+ if (!isZip64ExtBlockSizeValid(sz)) {
+ throw new ZipException("Invalid CEN header (invalid zip64 extra data field size)");
+ }
if (size == ZIP64_MINVAL) {
if (pos + 8 > elen) // invalid zip64 extra
break; // fields, just skip
size = LL(extra, pos);
+ if (size < 0) {
+ throw new ZipException("Invalid zip64 extra block size value");
+ }
pos += 8;
}
if (csize == ZIP64_MINVAL) {
if (pos + 8 > elen)
break;
csize = LL(extra, pos);
+ if (csize < 0) {
+ throw new ZipException("Invalid zip64 extra block compressed size value");
+ }
pos += 8;
}
if (locoff == ZIP64_MINVAL) {
if (pos + 8 > elen)
break;
locoff = LL(extra, pos);
+ if (locoff < 0) {
+ throw new ZipException("Invalid zip64 extra block LOC offset value");
+ }
}
break;
case EXTID_NTFS:
@@ -3149,6 +3168,36 @@ private void readExtra(ZipFileSystem zipfs) throws IOException {
extra = null;
}
+ /**
+ * Validate the size and contents of a Zip64 extended information field
+ * The order of the Zip64 fields is fixed, but the fields MUST
+ * only appear if the corresponding LOC or CEN field is set to 0xFFFF:
+ * or 0xFFFFFFFF:
+ * Uncompressed Size - 8 bytes
+ * Compressed Size - 8 bytes
+ * LOC Header offset - 8 bytes
+ * Disk Start Number - 4 bytes
+ * See PKWare APP.Note Section 4.5.3 for more details
+ *
+ * @param blockSize the Zip64 Extended Information Extra Field size
+ * @return true if the extra block size is valid; false otherwise
+ */
+ private static boolean isZip64ExtBlockSizeValid(int blockSize) {
+ /*
+ * As the fields must appear in order, the block size indicates which
+ * fields to expect:
+ * 8 - uncompressed size
+ * 16 - uncompressed size, compressed size
+ * 24 - uncompressed size, compressed sise, LOC Header offset
+ * 28 - uncompressed size, compressed sise, LOC Header offset,
+ * and Disk start number
+ */
+ return switch(blockSize) {
+ case 8, 16, 24, 28 -> true;
+ default -> false;
+ };
+ }
+
/**
* Read the LOC extra field to obtain the Info-ZIP Extended Timestamp fields
* @param zipfs The Zip FS to use
diff --git a/test/hotspot/jtreg/compiler/codegen/aes/CTR_Wraparound.java b/test/hotspot/jtreg/compiler/codegen/aes/CTR_Wraparound.java
new file mode 100644
index 00000000000..0bf6d3a5b8c
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/codegen/aes/CTR_Wraparound.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2023, 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
+ * @summary Check for 128-bit AES/CTR wraparound
+ * @library /test/lib /
+ * @build jdk.test.whitebox.WhiteBox
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
+ *
+ * @run main/othervm -Xbatch
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ * compiler.codegen.aes.CTR_Wraparound 32
+ * @run main/othervm -Xbatch
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ * compiler.codegen.aes.CTR_Wraparound 1009
+ * @run main/othervm -Xbatch
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ * compiler.codegen.aes.CTR_Wraparound 2048
+ */
+
+package compiler.codegen.aes;
+
+import java.util.Arrays;
+import java.util.Random;
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import compiler.whitebox.CompilerWhiteBoxTest;
+import jdk.test.whitebox.code.Compiler;
+import jdk.test.lib.Utils;
+import jtreg.SkippedException;
+
+public class CTR_Wraparound {
+ private static final String ALGO = "AES/CTR/NoPadding";
+ private static final int LOOPS = 100000;
+
+ public static void main(String[] args) throws Exception {
+ int length = Integer.parseInt(args[0]);
+ int maxOffset = 60;
+ if (args.length > 1) {
+ maxOffset = Integer.parseInt(args[1]);
+ System.out.println("InitialOffset = " + maxOffset);
+ }
+
+ if (!Compiler.isIntrinsicAvailable(CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION, "com.sun.crypto.provider.CounterMode", "implCrypt", byte[].class, int.class, int.class, byte[].class, int.class)) {
+ throw new SkippedException("AES-CTR intrinsic is not available");
+ }
+
+ Random random = Utils.getRandomInstance();
+
+ byte[] keyBytes = new byte[32];
+ Arrays.fill(keyBytes, (byte)0xff);
+ SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
+
+ byte[] ivBytes = new byte[16];
+
+ Arrays.fill(ivBytes, (byte)0xff);
+
+ byte[][] plaintext = new byte[maxOffset][];
+ byte[][] ciphertext = new byte[maxOffset][];
+
+ for (int offset = 0; offset < maxOffset; offset++) {
+ ivBytes[ivBytes.length - 1] = (byte)-offset;
+ IvParameterSpec iv = new IvParameterSpec(ivBytes);
+
+ Cipher encryptCipher = Cipher.getInstance(ALGO);
+ Cipher decryptCipher = Cipher.getInstance(ALGO);
+
+ encryptCipher.init(Cipher.ENCRYPT_MODE, key, iv);
+ decryptCipher.init(Cipher.DECRYPT_MODE, key, iv);
+
+ plaintext[offset] = new byte[length];
+ ciphertext[offset] = new byte[length];
+ random.nextBytes(plaintext[offset]);
+
+ byte[] decrypted = new byte[length];
+
+ encryptCipher.doFinal(plaintext[offset], 0, length, ciphertext[offset]);
+ decryptCipher.doFinal(ciphertext[offset], 0, length, decrypted);
+
+ if (!Arrays.equals(plaintext[offset], decrypted)) {
+ throw new Exception("mismatch in setup at offset " + offset);
+ }
+ }
+
+ for (int offset = 0; offset < maxOffset; offset++) {
+ ivBytes[ivBytes.length - 1] = (byte)-offset;
+ IvParameterSpec iv = new IvParameterSpec(ivBytes);
+
+ Cipher encryptCipher = Cipher.getInstance(ALGO);
+
+ encryptCipher.init(Cipher.ENCRYPT_MODE, key, iv);
+
+ byte[] encrypted = new byte[length];
+
+ for (int i = 0; i < LOOPS; i++) {
+ encryptCipher.doFinal(plaintext[offset], 0, length, encrypted);
+ if (!Arrays.equals(ciphertext[offset], encrypted)) {
+ throw new Exception("array mismatch at offset " + offset
+ + " with length " + length);
+ }
+ }
+ }
+ }
+}
diff --git a/test/jdk/java/net/httpclient/AsFileDownloadTest.java b/test/jdk/java/net/httpclient/AsFileDownloadTest.java
index 2d22a1a841f..890f0701b94 100644
--- a/test/jdk/java/net/httpclient/AsFileDownloadTest.java
+++ b/test/jdk/java/net/httpclient/AsFileDownloadTest.java
@@ -24,7 +24,7 @@
/*
* @test
* @summary Basic test for ofFileDownload
- * @bug 8196965
+ * @bug 8196965 8302475
* @modules java.base/sun.net.www.http
* java.net.http/jdk.internal.net.http.common
* java.net.http/jdk.internal.net.http.frame
@@ -127,18 +127,18 @@ public class AsFileDownloadTest {
{ "024", "attachment; filename=me.txt; filename*=utf-8''you.txt", "me.txt" },
{ "025", "attachment; filename=\"m y.txt\"; filename*=utf-8''you.txt", "m y.txt" },
- { "030", "attachment; filename=foo/file1.txt", "file1.txt" },
- { "031", "attachment; filename=foo/bar/file2.txt", "file2.txt" },
- { "032", "attachment; filename=baz\\file3.txt", "file3.txt" },
- { "033", "attachment; filename=baz\\bar\\file4.txt", "file4.txt" },
- { "034", "attachment; filename=x/y\\file5.txt", "file5.txt" },
- { "035", "attachment; filename=x/y\\file6.txt", "file6.txt" },
- { "036", "attachment; filename=x/y\\z/file7.txt", "file7.txt" },
- { "037", "attachment; filename=x/y\\z/\\x/file8.txt", "file8.txt" },
- { "038", "attachment; filename=/root/file9.txt", "file9.txt" },
- { "039", "attachment; filename=../file10.txt", "file10.txt" },
- { "040", "attachment; filename=..\\file11.txt", "file11.txt" },
- { "041", "attachment; filename=foo/../../file12.txt", "file12.txt" },
+ { "030", "attachment; filename=\"foo/file1.txt\"", "file1.txt" },
+ { "031", "attachment; filename=\"foo/bar/file2.txt\"", "file2.txt" },
+ { "032", "attachment; filename=\"baz\\\\file3.txt\"", "file3.txt" },
+ { "033", "attachment; filename=\"baz\\\\bar\\\\file4.txt\"", "file4.txt" },
+ { "034", "attachment; filename=\"x/y\\\\file5.txt\"", "file5.txt" },
+ { "035", "attachment; filename=\"x/y\\\\file6.txt\"", "file6.txt" },
+ { "036", "attachment; filename=\"x/y\\\\z/file7.txt\"", "file7.txt" },
+ { "037", "attachment; filename=\"x/y\\\\z/\\\\x/file8.txt\"", "file8.txt" },
+ { "038", "attachment; filename=\"/root/file9.txt\"", "file9.txt" },
+ { "039", "attachment; filename=\"../file10.txt\"", "file10.txt" },
+ { "040", "attachment; filename=\"..\\\\file11.txt\"", "file11.txt" },
+ { "041", "attachment; filename=\"foo/../../file12.txt\"", "file12.txt" },
};
@DataProvider(name = "positive")
@@ -177,18 +177,24 @@ void test(String uriString, String contentDispositionValue, String expectedFilen
CREATE, TRUNCATE_EXISTING, WRITE);
HttpResponse response = client.send(request, bh);
+ Path body = response.body();
out.println("Got response: " + response);
- out.println("Got body Path: " + response.body());
+ out.println("Got body Path: " + body);
String fileContents = new String(Files.readAllBytes(response.body()), UTF_8);
out.println("Got body: " + fileContents);
assertEquals(response.statusCode(),200);
- assertEquals(response.body().getFileName().toString(), expectedFilename);
+ assertEquals(body.getFileName().toString(), expectedFilename);
assertTrue(response.headers().firstValue("Content-Disposition").isPresent());
assertEquals(response.headers().firstValue("Content-Disposition").get(),
contentDispositionValue);
assertEquals(fileContents, "May the luck of the Irish be with you!");
+ if (!body.toAbsolutePath().startsWith(tempDir.toAbsolutePath())) {
+ System.out.println("Tempdir = " + tempDir.toAbsolutePath());
+ System.out.println("body = " + body.toAbsolutePath());
+ throw new AssertionError("body in wrong location");
+ }
// additional checks unrelated to file download
caseInsensitivityOfHeaders(request.headers());
caseInsensitivityOfHeaders(response.headers());
diff --git a/test/jdk/java/security/KeyStore/CheckMacOSKeyChainTrust.java b/test/jdk/java/security/KeyStore/CheckMacOSKeyChainTrust.java
new file mode 100644
index 00000000000..edad6210195
--- /dev/null
+++ b/test/jdk/java/security/KeyStore/CheckMacOSKeyChainTrust.java
@@ -0,0 +1,119 @@
+
+/*
+ * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023 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
+ * 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 java.security.KeyStore;
+import java.util.HashSet;
+import java.util.Set;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+/*
+ * @test
+ * @bug 8303465
+ * @library /test/lib
+ * @requires os.family == "mac"
+ * @summary Check whether loading of certificates from MacOS Keychain correctly
+ * honors trust settings
+ */
+public class CheckMacOSKeyChainTrust {
+ private static Set trusted = new HashSet<>();
+ private static Set distrusted = new HashSet<>();
+
+ public static void main(String[] args) throws Throwable {
+ loadUser();
+ loadAdmin();
+ System.out.println("Trusted Certs: " + trusted);
+ System.out.println("Distrusted Certs: " + distrusted);
+ KeyStore ks = KeyStore.getInstance("KEYCHAINSTORE");
+ ks.load(null, null);
+ for (String alias : trusted) {
+ if (!ks.containsAlias(alias)) {
+ throw new RuntimeException("Not found: " + alias);
+ }
+ }
+ for (String alias : distrusted) {
+ if (ks.containsAlias(alias)) {
+ throw new RuntimeException("Found: " + alias);
+ }
+ }
+ }
+
+ private static void loadUser() throws Throwable {
+ populate(ProcessTools.executeProcess("security", "dump-trust-settings"));
+ }
+
+ private static void loadAdmin() throws Throwable {
+ populate(ProcessTools.executeProcess("security", "dump-trust-settings", "-d"));
+ }
+
+ private static void populate(OutputAnalyzer output) throws Throwable {
+ if (output.getExitValue() != 0) {
+ return; // No Trust Settings were found
+ }
+ String certName = null;
+ boolean trustRootFound = false;
+ boolean trustAsRootFound = false;
+ boolean denyFound = false;
+ boolean unspecifiedFound = false;
+ for (String line : output.asLines()) {
+ if (line.startsWith("Cert ")) {
+ if (certName != null) {
+ if (!denyFound &&
+ !(unspecifiedFound && !(trustRootFound || trustAsRootFound)) &&
+ !distrusted.contains(certName)) {
+ trusted.add(certName);
+ } else {
+ distrusted.add(certName);
+ trusted.remove(certName);
+ }
+ }
+ certName = line.split(":", 2)[1].trim().toLowerCase();
+ trustRootFound = false;
+ trustAsRootFound = false;
+ denyFound = false;
+ unspecifiedFound = false;
+ } else if (line.contains("kSecTrustSettingsResultTrustRoot")) {
+ trustRootFound = true;
+ } else if (line.contains("kSecTrustSettingsResultTrustAsRoot")) {
+ trustAsRootFound = true;
+ } else if (line.contains("kSecTrustSettingsResultDeny")) {
+ denyFound = true;
+ } else if (line.contains("kSecTrustSettingsResultUnspecified")) {
+ unspecifiedFound = true;
+ }
+ }
+ if (certName != null) {
+ if (!denyFound &&
+ !(unspecifiedFound && !(trustRootFound || trustAsRootFound)) &&
+ !distrusted.contains(certName)) {
+ trusted.add(certName);
+ } else {
+ distrusted.add(certName);
+ trusted.remove(certName);
+ }
+ }
+ }
+}
diff --git a/test/jdk/java/util/zip/TestExtraTime.java b/test/jdk/java/util/zip/TestExtraTime.java
index a60e810df0f..0e68e764546 100644
--- a/test/jdk/java/util/zip/TestExtraTime.java
+++ b/test/jdk/java/util/zip/TestExtraTime.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2023, 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
@@ -29,6 +29,8 @@
*/
import java.io.*;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -59,7 +61,14 @@ public static void main(String[] args) throws Throwable{
TimeZone tz = TimeZone.getTimeZone("Asia/Shanghai");
- for (byte[] extra : new byte[][] { null, new byte[] {1, 2, 3}}) {
+ // A structurally valid extra data example
+ byte[] sampleExtra = new byte[Short.BYTES*3];
+ ByteBuffer.wrap(sampleExtra).order(ByteOrder.LITTLE_ENDIAN)
+ .putShort((short) 123) // ID: 123
+ .putShort((short) Short.BYTES) // Size: 2
+ .putShort((short) 42); // Data: Two bytes
+
+ for (byte[] extra : new byte[][] { null, sampleExtra}) {
// ms-dos 1980 epoch problem
test0(FileTime.from(10, TimeUnit.MILLISECONDS), null, null, null, extra);
diff --git a/test/jdk/java/util/zip/ZipFile/CorruptedZipFiles.java b/test/jdk/java/util/zip/ZipFile/CorruptedZipFiles.java
index 6ef3ec5d8f6..b969ecfd04e 100644
--- a/test/jdk/java/util/zip/ZipFile/CorruptedZipFiles.java
+++ b/test/jdk/java/util/zip/ZipFile/CorruptedZipFiles.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2023, 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
@@ -114,13 +114,13 @@ public static void main(String[] args) throws Exception {
err.println("corrupted CENEXT 1");
bad = good.clone();
bad[cenpos+CENEXT]++;
- checkZipException(bad, ".*bad header size.*");
+ checkZipException(bad, ".*invalid zip64 extra data field size.*");
err.println("corrupted CENEXT 2");
bad = good.clone();
bad[cenpos+CENEXT] = (byte)0xfd;
bad[cenpos+CENEXT+1] = (byte)0xfd;
- checkZipException(bad, ".*bad header size.*");
+ checkZipException(bad, ".*extra data field size too long.*");
err.println("corrupted CENCOM");
bad = good.clone();
diff --git a/test/jdk/sun/security/ssl/SSLEngineImpl/SSLEngineKeyLimit.java b/test/jdk/sun/security/ssl/SSLEngineImpl/SSLEngineKeyLimit.java
index fa6f12bc2b7..58c3c4a0d3b 100644
--- a/test/jdk/sun/security/ssl/SSLEngineImpl/SSLEngineKeyLimit.java
+++ b/test/jdk/sun/security/ssl/SSLEngineImpl/SSLEngineKeyLimit.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2023, 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
@@ -23,17 +23,24 @@
/*
* @test
- * @bug 8164879
+ * @bug 8164879 8300285
* @library ../../
* @library /test/lib
- * @summary Verify AES/GCM's limits set in the jdk.tls.keyLimits property
+ * @summary Verify AEAD TLS cipher suite limits set in the jdk.tls.keyLimits
+ * property
* start a new handshake sequence to renegotiate the symmetric key with an
* SSLSocket connection. This test verifies the handshake method was called
* via debugging info. It does not verify the renegotiation was successful
* as that is very hard.
*
- * @run main SSLEngineKeyLimit 0 server AES/GCM/NoPadding keyupdate 1050000
- * @run main SSLEngineKeyLimit 1 client AES/GCM/NoPadding keyupdate 2^22
+ * @run main SSLEngineKeyLimit 0 server TLS_AES_256_GCM_SHA384
+ * AES/GCM/NoPadding keyupdate 1050000
+ * @run main SSLEngineKeyLimit 1 client TLS_AES_256_GCM_SHA384
+ * AES/GCM/NoPadding keyupdate 2^22
+ * @run main SSLEngineKeyLimit 0 server TLS_CHACHA20_POLY1305_SHA256
+ * AES/GCM/NoPadding keyupdate 1050000, ChaCha20-Poly1305 KeyUpdate 1050000
+ * @run main SSLEngineKeyLimit 1 client TLS_CHACHA20_POLY1305_SHA256
+ * AES/GCM/NoPadding keyupdate 2^22, ChaCha20-Poly1305 KeyUpdate 2^22
*/
/*
@@ -86,7 +93,7 @@ public class SSLEngineKeyLimit {
}
/**
- * args should have two values: server|client,
+ * args should have two values: server|client, cipher suite,
* Prepending 'p' is for internal use only.
*/
public static void main(String args[]) throws Exception {
@@ -105,7 +112,7 @@ public static void main(String args[]) throws Exception {
File f = new File("keyusage."+ System.nanoTime());
PrintWriter p = new PrintWriter(f);
p.write("jdk.tls.keyLimits=");
- for (int i = 2; i < args.length; i++) {
+ for (int i = 3; i < args.length; i++) {
p.write(" "+ args[i]);
}
p.close();
@@ -120,10 +127,13 @@ public static void main(String args[]) throws Exception {
System.getProperty("test.java.opts"));
ProcessBuilder pb = ProcessTools.createTestJvm(
- Utils.addTestJavaOpts("SSLEngineKeyLimit", "p", args[1]));
+ Utils.addTestJavaOpts("SSLEngineKeyLimit", "p", args[1],
+ args[2]));
OutputAnalyzer output = ProcessTools.executeProcess(pb);
try {
+ output.shouldContain(String.format(
+ "\"cipher suite\" : \"%s", args[2]));
if (expectedFail) {
output.shouldNotContain("KeyUpdate: write key updated");
output.shouldNotContain("KeyUpdate: read key updated");
@@ -171,9 +181,10 @@ public static void main(String args[]) throws Exception {
cTos.clear();
sToc.clear();
- Thread ts = new Thread(serverwrite ? new Client() : new Server());
+ Thread ts = new Thread(serverwrite ? new Client() :
+ new Server(args[2]));
ts.start();
- (serverwrite ? new Server() : new Client()).run();
+ (serverwrite ? new Server(args[2]) : new Client()).run();
ts.interrupt();
ts.join();
}
@@ -417,11 +428,14 @@ SSLContext initContext() throws Exception {
}
static class Server extends SSLEngineKeyLimit implements Runnable {
- Server() throws Exception {
+ Server(String cipherSuite) throws Exception {
super();
eng = initContext().createSSLEngine();
eng.setUseClientMode(false);
eng.setNeedClientAuth(true);
+ if (cipherSuite != null && cipherSuite.length() > 0) {
+ eng.setEnabledCipherSuites(new String[] { cipherSuite });
+ }
}
public void run() {
diff --git a/test/jdk/sun/security/ssl/SSLSocketImpl/SSLSocketKeyLimit.java b/test/jdk/sun/security/ssl/SSLSocketImpl/SSLSocketKeyLimit.java
index 198e0bdd6f0..8b19d39af7e 100644
--- a/test/jdk/sun/security/ssl/SSLSocketImpl/SSLSocketKeyLimit.java
+++ b/test/jdk/sun/security/ssl/SSLSocketImpl/SSLSocketKeyLimit.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2023, 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
@@ -23,14 +23,24 @@
/*
* @test
- * @bug 8164879
+ * @bug 8164879 8300285
* @library ../../
* @library /test/lib
* @modules java.base/sun.security.util
- * @summary Verify AES/GCM's limits set in the jdk.tls.keyLimits property
- * @run main SSLSocketKeyLimit 0 server AES/GCM/NoPadding keyupdate 1000000
- * @run main SSLSocketKeyLimit 0 client AES/GCM/NoPadding keyupdate 1000000
- * @run main SSLSocketKeyLimit 1 client AES/GCM/NoPadding keyupdate 2^22
+ * @summary Verify AEAD TLS cipher suite limits set in the jdk.tls.keyLimits
+ * property
+ * @run main SSLSocketKeyLimit 0 server TLS_AES_256_GCM_SHA384
+ * AES/GCM/NoPadding keyupdate 1000000
+ * @run main SSLSocketKeyLimit 0 client TLS_AES_256_GCM_SHA384
+ * AES/GCM/NoPadding keyupdate 1000000
+ * @run main SSLSocketKeyLimit 1 client TLS_AES_256_GCM_SHA384
+ * AES/GCM/NoPadding keyupdate 2^22
+ * @run main SSLSocketKeyLimit 0 server TLS_CHACHA20_POLY1305_SHA256
+ * AES/GCM/NoPadding keyupdate 1000000, ChaCha20-Poly1305 KeyUpdate 1000000
+ * @run main SSLSocketKeyLimit 0 client TLS_CHACHA20_POLY1305_SHA256
+ * AES/GCM/NoPadding keyupdate 1000000, ChaCha20-Poly1305 KeyUpdate 1000000
+ * @run main SSLSocketKeyLimit 1 client TLS_CHACHA20_POLY1305_SHA256
+ * AES/GCM/NoPadding keyupdate 2^22, ChaCha20-Poly1305 KeyUpdate 2^22
*/
/**
@@ -96,7 +106,7 @@ SSLContext initContext() throws Exception {
}
/**
- * args should have two values: server|client,
+ * args should have three values: server|client, cipher suite,
* Prepending 'p' is for internal use only.
*/
public static void main(String args[]) throws Exception {
@@ -110,7 +120,7 @@ public static void main(String args[]) throws Exception {
File f = new File("keyusage."+ System.nanoTime());
PrintWriter p = new PrintWriter(f);
p.write("jdk.tls.keyLimits=");
- for (int i = 2; i < args.length; i++) {
+ for (int i = 3; i < args.length; i++) {
p.write(" "+ args[i]);
}
p.close();
@@ -125,10 +135,13 @@ public static void main(String args[]) throws Exception {
System.getProperty("test.java.opts"));
ProcessBuilder pb = ProcessTools.createTestJvm(
- Utils.addTestJavaOpts("SSLSocketKeyLimit", "p", args[1]));
+ Utils.addTestJavaOpts("SSLSocketKeyLimit", "p", args[1],
+ args[2]));
OutputAnalyzer output = ProcessTools.executeProcess(pb);
try {
+ output.shouldContain(String.format(
+ "\"cipher suite\" : \"%s", args[2]));
if (expectedFail) {
output.shouldNotContain("KeyUpdate: write key updated");
output.shouldNotContain("KeyUpdate: read key updated");
@@ -150,7 +163,7 @@ public static void main(String args[]) throws Exception {
return;
}
- if (args.length > 0 && args[0].compareToIgnoreCase("client") == 0) {
+ if (args.length > 0 && args[1].compareToIgnoreCase("client") == 0) {
serverwrite = false;
}
@@ -162,7 +175,7 @@ public static void main(String args[]) throws Exception {
System.setProperty("javax.net.ssl.keyStorePassword", passwd);
Arrays.fill(data, (byte)0x0A);
- Thread ts = new Thread(new Server());
+ Thread ts = new Thread(new Server(args[2]));
ts.start();
while (!serverReady) {
@@ -200,7 +213,8 @@ void read(SSLSocket s) throws Exception {
int len;
byte i = 0;
try {
- System.out.println("Server: connected " + s.getSession().getCipherSuite());
+ System.out.println("Server: connected " +
+ s.getSession().getCipherSuite());
in = s.getInputStream();
out = s.getOutputStream();
while (true) {
@@ -212,7 +226,8 @@ void read(SSLSocket s) throws Exception {
if (b == 0x0A || b == 0x0D) {
continue;
}
- System.out.println("\nData invalid: " + HexPrinter.minimal().toString(buf));
+ System.out.println("\nData invalid: " +
+ HexPrinter.minimal().toString(buf));
break;
}
@@ -237,11 +252,14 @@ void read(SSLSocket s) throws Exception {
static class Server extends SSLSocketKeyLimit implements Runnable {
private SSLServerSocketFactory ssf;
private SSLServerSocket ss;
- Server() {
+ Server(String cipherSuite) {
super();
try {
ssf = initContext().getServerSocketFactory();
ss = (SSLServerSocket) ssf.createServerSocket(serverPort);
+ if (cipherSuite != null && cipherSuite.length() > 0) {
+ ss.setEnabledCipherSuites(new String[] { cipherSuite });
+ }
serverPort = ss.getLocalPort();
} catch (Exception e) {
System.out.println("server: " + e.getMessage());