This commit is contained in:
Rob McKenna 2025-01-21 18:56:33 +00:00
commit aa9bbd5a6a
26 changed files with 829 additions and 503 deletions

View File

@ -28,12 +28,12 @@
DEFAULT_VERSION_FEATURE=23
DEFAULT_VERSION_INTERIM=0
DEFAULT_VERSION_UPDATE=1
DEFAULT_VERSION_UPDATE=2
DEFAULT_VERSION_PATCH=0
DEFAULT_VERSION_EXTRA1=0
DEFAULT_VERSION_EXTRA2=0
DEFAULT_VERSION_EXTRA3=0
DEFAULT_VERSION_DATE=2024-10-15
DEFAULT_VERSION_DATE=2025-01-21
DEFAULT_VERSION_CLASSFILE_MAJOR=67 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`"
DEFAULT_VERSION_CLASSFILE_MINOR=0
DEFAULT_VERSION_DOCS_API_SINCE=11

View File

@ -1623,44 +1623,86 @@ Node *BoolNode::Ideal(PhaseGVN *phase, bool can_reshape) {
return new BoolNode( ncmp, _test.negate() );
}
// Change ((x & m) u<= m) or ((m & x) u<= m) to always true
// Same with ((x & m) u< m+1) and ((m & x) u< m+1)
// We use the following Lemmas/insights for the following two transformations (1) and (2):
// x & y <=u y, for any x and y (Lemma 1, masking always results in a smaller unsigned number)
// y <u y + 1 is always true if y != -1 (Lemma 2, (uint)(-1 + 1) == (uint)(UINT_MAX + 1) which overflows)
// y <u 0 is always false for any y (Lemma 3, 0 == UINT_MIN and nothing can be smaller than that)
//
// (1a) Always: Change ((x & m) <=u m ) or ((m & x) <=u m ) to always true (true by Lemma 1)
// (1b) If m != -1: Change ((x & m) <u m + 1) or ((m & x) <u m + 1) to always true:
// x & m <=u m is always true // (Lemma 1)
// x & m <=u m <u m + 1 is always true // (Lemma 2: m <u m + 1, if m != -1)
//
// A counter example for (1b), if we allowed m == -1:
// (x & m) <u m + 1
// (x & -1) <u 0
// x <u 0
// which is false for any x (Lemma 3)
if (cop == Op_CmpU &&
cmp1_op == Op_AndI) {
Node* bound = nullptr;
Node* m = nullptr;
if (_test._test == BoolTest::le) {
bound = cmp2;
// (1a) "((x & m) <=u m)", cmp2 = m
m = cmp2;
} else if (_test._test == BoolTest::lt &&
cmp2->Opcode() == Op_AddI &&
cmp2->in(2)->find_int_con(0) == 1) {
bound = cmp2->in(1);
// (1b) "(x & m) <u m + 1" and "(m & x) <u m + 1", cmp2 = m + 1
Node* rhs_m = cmp2->in(1);
const TypeInt* rhs_m_type = phase->type(rhs_m)->isa_int();
if (rhs_m_type->_lo > -1 || rhs_m_type->_hi < -1) {
// Exclude any case where m == -1 is possible.
m = rhs_m;
}
}
if (cmp1->in(2) == bound || cmp1->in(1) == bound) {
if (cmp1->in(2) == m || cmp1->in(1) == m) {
return ConINode::make(1);
}
}
// Change ((x & (m - 1)) u< m) into (m > 0)
// This is the off-by-one variant of the above
// (2) Change ((x & (m - 1)) <u m) or (((m - 1) & x) <u m) to (m >u 0)
// This is the off-by-one variant of the above.
//
// We now prove that this replacement is correct. This is the same as proving
// "m >u 0" if and only if "x & (m - 1) <u m", i.e. "m >u 0 <=> x & (m - 1) <u m"
//
// We use (Lemma 1) and (Lemma 3) from above.
//
// Case "x & (m - 1) <u m => m >u 0":
// We prove this by contradiction:
// Assume m <=u 0 which is equivalent to m == 0:
// and thus
// x & (m - 1) <u m = 0 // m == 0
// y <u 0 // y = x & (m - 1)
// by Lemma 3, this is always false, i.e. a contradiction to our assumption.
//
// Case "m >u 0 => x & (m - 1) <u m":
// x & (m - 1) <=u (m - 1) // (Lemma 1)
// x & (m - 1) <=u (m - 1) <u m // Using assumption m >u 0, no underflow of "m - 1"
//
//
// Note that the signed version of "m > 0":
// m > 0 <=> x & (m - 1) <u m
// does not hold:
// Assume m == -1 and x == -1:
// x & (m - 1) <u m
// -1 & -2 <u -1
// -2 <u -1
// UINT_MAX - 1 <u UINT_MAX // Signed to unsigned numbers
// which is true while
// m > 0
// is false which is a contradiction.
if (cop == Op_CmpU &&
_test._test == BoolTest::lt &&
cmp1_op == Op_AndI) {
Node* l = cmp1->in(1);
Node* r = cmp1->in(2);
for (int repeat = 0; repeat < 2; repeat++) {
bool match = r->Opcode() == Op_AddI && r->in(2)->find_int_con(0) == -1 &&
r->in(1) == cmp2;
if (match) {
// arraylength known to be non-negative, so a (arraylength != 0) is sufficient,
// but to be compatible with the array range check pattern, use (arraylength u> 0)
Node* ncmp = cmp2->Opcode() == Op_LoadRange
? phase->transform(new CmpUNode(cmp2, phase->intcon(0)))
: phase->transform(new CmpINode(cmp2, phase->intcon(0)));
return new BoolNode(ncmp, BoolTest::gt);
} else {
// commute and try again
l = cmp1->in(2);
r = cmp1->in(1);
Node* m = cmp2; // RHS: m
for (int add_idx = 1; add_idx <= 2; add_idx++) { // LHS: "(m + (-1)) & x" or "x & (m + (-1))"?
Node* maybe_m_minus_1 = cmp1->in(add_idx);
if (maybe_m_minus_1->Opcode() == Op_AddI &&
maybe_m_minus_1->in(2)->find_int_con(0) == -1 &&
maybe_m_minus_1->in(1) == m) {
Node* m_cmpu_0 = phase->transform(new CmpUNode(m, phase->intcon(0)));
return new BoolNode(m_cmpu_0, BoolTest::gt);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, 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
@ -56,6 +56,7 @@ final class DHPrivateKey implements PrivateKey,
private final BigInteger x;
// the key bytes, without the algorithm information
// cannot be final as it's re-assigned for deserialization
private byte[] key;
// the encoded key
@ -70,6 +71,131 @@ final class DHPrivateKey implements PrivateKey,
// the private-value length (optional)
private final int l;
private static class DHComponents {
final BigInteger x;
final BigInteger p;
final BigInteger g;
final int l;
final byte[] key;
DHComponents(BigInteger x, BigInteger p, BigInteger g, int l,
byte[] key) {
this.x = x;
this.p = p;
this.g = g;
this.l = l;
this.key = key;
}
}
// parses the specified encoding into a DHComponents object
private static DHComponents decode(byte[] encodedKey)
throws IOException {
DerValue val = null;
try {
val = new DerValue(encodedKey);
if (val.tag != DerValue.tag_Sequence) {
throw new IOException("Key not a SEQUENCE");
}
// version
BigInteger parsedVersion = val.data.getBigInteger();
if (!parsedVersion.equals(PKCS8_VERSION)) {
throw new IOException("version mismatch: (supported: " +
PKCS8_VERSION + ", parsed: " + parsedVersion);
}
// privateKeyAlgorithm
DerValue algid = val.data.getDerValue();
if (algid.tag != DerValue.tag_Sequence) {
throw new IOException("AlgId is not a SEQUENCE");
}
DerInputStream derInStream = algid.toDerInputStream();
ObjectIdentifier oid = derInStream.getOID();
if (oid == null) {
throw new IOException("Null OID");
}
if (derInStream.available() == 0) {
throw new IOException("Parameters missing");
}
// parse the parameters
DerValue params = derInStream.getDerValue();
if (params.tag == DerValue.tag_Null) {
throw new IOException("Null parameters");
}
if (params.tag != DerValue.tag_Sequence) {
throw new IOException("Parameters not a SEQUENCE");
}
params.data.reset();
BigInteger p = params.data.getBigInteger();
BigInteger g = params.data.getBigInteger();
// Private-value length is OPTIONAL
int l = (params.data.available() != 0 ?
params.data.getInteger() : 0);
// should have no trailing data
if (params.data.available() != 0) {
throw new IOException("Extra parameter data");
}
// privateKey
byte[] key = val.data.getOctetString();
DerInputStream in = new DerInputStream(key);
BigInteger x = in.getBigInteger();
// should have no trailing data
if (val.data.available() != 0) {
throw new IOException("Excess trailing data");
}
return new DHComponents(x, p, g, l, key);
} catch (NumberFormatException e) {
throw new IOException("Error parsing key encoding", e);
} finally {
if (val != null) {
val.clear();
}
}
}
// Generates the ASN.1 encoding
private static byte[] encode(BigInteger p, BigInteger g, int l,
byte[] key) {
DerOutputStream tmp = new DerOutputStream();
// version
tmp.putInteger(PKCS8_VERSION);
// privateKeyAlgorithm
DerOutputStream algid = new DerOutputStream();
// store OID
algid.putOID(DHPublicKey.DH_OID);
// encode parameters
DerOutputStream params = new DerOutputStream();
params.putInteger(p);
params.putInteger(g);
if (l != 0) {
params.putInteger(l);
}
// wrap parameters into SEQUENCE
DerValue paramSequence = new DerValue(DerValue.tag_Sequence,
params.toByteArray());
// store parameter SEQUENCE in algid
algid.putDerValue(paramSequence);
// wrap algid into SEQUENCE
tmp.write(DerValue.tag_Sequence, algid);
// privateKey
tmp.putOctetString(key);
// make it a SEQUENCE
DerValue val = DerValue.wrap(DerValue.tag_Sequence, tmp);
byte[] encoded = val.toByteArray();
val.clear();
return encoded;
}
/**
* Make a DH private key out of a private value <code>x</code>, a prime
* modulus <code>p</code>, and a base generator <code>g</code>.
@ -79,7 +205,7 @@ final class DHPrivateKey implements PrivateKey,
* @param g the base generator
*/
DHPrivateKey(BigInteger x, BigInteger p, BigInteger g)
throws InvalidKeyException {
throws InvalidKeyException {
this(x, p, g, 0);
}
@ -98,12 +224,16 @@ final class DHPrivateKey implements PrivateKey,
this.p = p;
this.g = g;
this.l = l;
byte[] xbytes = x.toByteArray();
DerValue val = new DerValue(DerValue.tag_Integer, xbytes);
this.key = val.toByteArray();
val.clear();
Arrays.fill(xbytes, (byte) 0);
encode();
try {
this.key = val.toByteArray();
} finally {
val.clear();
Arrays.fill(xbytes, (byte) 0);
}
this.encodedKey = encode(p, g, l, key);
}
/**
@ -115,75 +245,18 @@ final class DHPrivateKey implements PrivateKey,
* a Diffie-Hellman private key
*/
DHPrivateKey(byte[] encodedKey) throws InvalidKeyException {
DerValue val = null;
this.encodedKey = encodedKey.clone();
DHComponents dc;
try {
val = new DerValue(encodedKey);
if (val.tag != DerValue.tag_Sequence) {
throw new InvalidKeyException ("Key not a SEQUENCE");
}
//
// version
//
BigInteger parsedVersion = val.data.getBigInteger();
if (!parsedVersion.equals(PKCS8_VERSION)) {
throw new IOException("version mismatch: (supported: " +
PKCS8_VERSION + ", parsed: " +
parsedVersion);
}
//
// privateKeyAlgorithm
//
DerValue algid = val.data.getDerValue();
if (algid.tag != DerValue.tag_Sequence) {
throw new InvalidKeyException("AlgId is not a SEQUENCE");
}
DerInputStream derInStream = algid.toDerInputStream();
ObjectIdentifier oid = derInStream.getOID();
if (oid == null) {
throw new InvalidKeyException("Null OID");
}
if (derInStream.available() == 0) {
throw new InvalidKeyException("Parameters missing");
}
// parse the parameters
DerValue params = derInStream.getDerValue();
if (params.tag == DerValue.tag_Null) {
throw new InvalidKeyException("Null parameters");
}
if (params.tag != DerValue.tag_Sequence) {
throw new InvalidKeyException("Parameters not a SEQUENCE");
}
params.data.reset();
this.p = params.data.getBigInteger();
this.g = params.data.getBigInteger();
// Private-value length is OPTIONAL
if (params.data.available() != 0) {
this.l = params.data.getInteger();
} else {
this.l = 0;
}
if (params.data.available() != 0) {
throw new InvalidKeyException("Extra parameter data");
}
//
// privateKey
//
this.key = val.data.getOctetString();
DerInputStream in = new DerInputStream(this.key);
this.x = in.getBigInteger();
this.encodedKey = encodedKey.clone();
} catch (IOException | NumberFormatException e) {
throw new InvalidKeyException("Error parsing key encoding", e);
} finally {
if (val != null) {
val.clear();
}
dc = decode(this.encodedKey);
} catch (IOException e) {
throw new InvalidKeyException("Invalid encoding", e);
}
this.x = dc.x;
this.p = dc.p;
this.g = dc.g;
this.l = dc.l;
this.key = dc.key;
}
/**
@ -204,55 +277,9 @@ final class DHPrivateKey implements PrivateKey,
* Get the encoding of the key.
*/
public synchronized byte[] getEncoded() {
encode();
return encodedKey.clone();
}
/**
* Generate the encodedKey field if it has not been calculated.
* Could generate null.
*/
private void encode() {
if (this.encodedKey == null) {
DerOutputStream tmp = new DerOutputStream();
//
// version
//
tmp.putInteger(PKCS8_VERSION);
//
// privateKeyAlgorithm
//
DerOutputStream algid = new DerOutputStream();
// store OID
algid.putOID(DHPublicKey.DH_OID);
// encode parameters
DerOutputStream params = new DerOutputStream();
params.putInteger(this.p);
params.putInteger(this.g);
if (this.l != 0) {
params.putInteger(this.l);
}
// wrap parameters into SEQUENCE
DerValue paramSequence = new DerValue(DerValue.tag_Sequence,
params.toByteArray());
// store parameter SEQUENCE in algid
algid.putDerValue(paramSequence);
// wrap algid into SEQUENCE
tmp.write(DerValue.tag_Sequence, algid);
// privateKey
tmp.putOctetString(this.key);
// make it a SEQUENCE
DerValue val = DerValue.wrap(DerValue.tag_Sequence, tmp);
this.encodedKey = val.toByteArray();
val.clear();
}
}
/**
* Returns the private value, <code>x</code>.
*
@ -307,10 +334,7 @@ final class DHPrivateKey implements PrivateKey,
*/
@java.io.Serial
private Object writeReplace() throws java.io.ObjectStreamException {
encode();
return new KeyRep(KeyRep.Type.PRIVATE,
getAlgorithm(),
getFormat(),
return new KeyRep(KeyRep.Type.PRIVATE, getAlgorithm(), getFormat(),
encodedKey);
}
@ -330,11 +354,28 @@ final class DHPrivateKey implements PrivateKey,
if ((key == null) || (key.length == 0)) {
throw new InvalidObjectException("key not deserializable");
}
this.key = key.clone();
if ((encodedKey == null) || (encodedKey.length == 0)) {
throw new InvalidObjectException(
"encoded key not deserializable");
}
this.encodedKey = encodedKey.clone();
// check if the "encodedKey" value matches the deserialized fields
DHComponents c;
byte[] encodedKeyIntern = encodedKey.clone();
try {
c = decode(encodedKeyIntern);
} catch (IOException e) {
throw new InvalidObjectException("Invalid encoding", e);
}
if (!Arrays.equals(c.key, key) || !c.x.equals(x) || !c.p.equals(p)
|| !c.g.equals(g) || c.l != l) {
throw new InvalidObjectException(
"encoded key not matching internal fields");
}
// zero out external arrays
Arrays.fill(key, (byte)0x00);
Arrays.fill(encodedKey, (byte)0x00);
// use self-created internal copies
this.key = c.key;
this.encodedKey = encodedKeyIntern;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -26,6 +26,7 @@
package com.sun.crypto.provider;
import java.io.*;
import java.util.Arrays;
import java.util.Objects;
import java.math.BigInteger;
import java.security.KeyRep;
@ -70,6 +71,116 @@ javax.crypto.interfaces.DHPublicKey, Serializable {
static final ObjectIdentifier DH_OID =
ObjectIdentifier.of(KnownOIDs.DiffieHellman);
private static class DHComponents {
final BigInteger y;
final BigInteger p;
final BigInteger g;
final int l;
final byte[] key;
DHComponents(BigInteger y, BigInteger p, BigInteger g, int l,
byte[] key) {
this.y = y;
this.p = p;
this.g = g;
this.l = l;
this.key = key;
}
}
// parses the specified encoding into a DHComponents object
private static DHComponents decode(byte[] encodedKey)
throws IOException {
DerValue val = null;
try {
val = new DerValue(encodedKey);
if (val.tag != DerValue.tag_Sequence) {
throw new IOException("Invalid key format");
}
// algorithm identifier
DerValue algid = val.data.getDerValue();
if (algid.tag != DerValue.tag_Sequence) {
throw new IOException("AlgId is not a SEQUENCE");
}
DerInputStream derInStream = algid.toDerInputStream();
ObjectIdentifier oid = derInStream.getOID();
if (oid == null) {
throw new IOException("Null OID");
}
if (derInStream.available() == 0) {
throw new IOException("Parameters missing");
}
// parse the parameters
DerValue params = derInStream.getDerValue();
if (params.tag == DerValue.tag_Null) {
throw new IOException("Null parameters");
}
if (params.tag != DerValue.tag_Sequence) {
throw new IOException("Parameters not a SEQUENCE");
}
params.data.reset();
BigInteger p = params.data.getBigInteger();
BigInteger g = params.data.getBigInteger();
// Private-value length is OPTIONAL
int l = (params.data.available() != 0 ? params.data.getInteger() :
0);
if (params.data.available() != 0) {
throw new IOException("Extra parameter data");
}
// publickey
byte[] key = val.data.getBitString();
DerInputStream in = new DerInputStream(key);
BigInteger y = in.getBigInteger();
if (val.data.available() != 0) {
throw new IOException("Excess key data");
}
return new DHComponents(y, p, g, l, key);
} catch (NumberFormatException e) {
throw new IOException("Error parsing key encoding", e);
}
}
// generates the ASN.1 encoding
private static byte[] encode(BigInteger p, BigInteger g, int l,
byte[] key) {
DerOutputStream algid = new DerOutputStream();
// store oid in algid
algid.putOID(DH_OID);
// encode parameters
DerOutputStream params = new DerOutputStream();
params.putInteger(p);
params.putInteger(g);
if (l != 0) {
params.putInteger(l);
}
// wrap parameters into SEQUENCE
DerValue paramSequence = new DerValue(DerValue.tag_Sequence,
params.toByteArray());
// store parameter SEQUENCE in algid
algid.putDerValue(paramSequence);
// wrap algid into SEQUENCE, and store it in key encoding
DerOutputStream tmpDerKey = new DerOutputStream();
tmpDerKey.write(DerValue.tag_Sequence, algid);
// store key data
tmpDerKey.putBitString(key);
// wrap algid and key into SEQUENCE
DerOutputStream derKey = new DerOutputStream();
derKey.write(DerValue.tag_Sequence, tmpDerKey);
return derKey.toByteArray();
}
/**
* Make a DH public key out of a public value <code>y</code>, a prime
* modulus <code>p</code>, and a base generator <code>g</code>.
@ -102,7 +213,7 @@ javax.crypto.interfaces.DHPublicKey, Serializable {
this.l = l;
this.key = new DerValue(DerValue.tag_Integer,
this.y.toByteArray()).toByteArray();
this.encodedKey = getEncoded();
this.encodedKey = encode(p, g, l, key);
}
/**
@ -114,68 +225,19 @@ javax.crypto.interfaces.DHPublicKey, Serializable {
* a Diffie-Hellman public key
*/
DHPublicKey(byte[] encodedKey) throws InvalidKeyException {
InputStream inStream = new ByteArrayInputStream(encodedKey);
this.encodedKey = encodedKey.clone();
DHComponents dc;
try {
DerValue derKeyVal = new DerValue(inStream);
if (derKeyVal.tag != DerValue.tag_Sequence) {
throw new InvalidKeyException ("Invalid key format");
}
/*
* Parse the algorithm identifier
*/
DerValue algid = derKeyVal.data.getDerValue();
if (algid.tag != DerValue.tag_Sequence) {
throw new InvalidKeyException("AlgId is not a SEQUENCE");
}
DerInputStream derInStream = algid.toDerInputStream();
ObjectIdentifier oid = derInStream.getOID();
if (oid == null) {
throw new InvalidKeyException("Null OID");
}
if (derInStream.available() == 0) {
throw new InvalidKeyException("Parameters missing");
}
/*
* Parse the parameters
*/
DerValue params = derInStream.getDerValue();
if (params.tag == DerValue.tag_Null) {
throw new InvalidKeyException("Null parameters");
}
if (params.tag != DerValue.tag_Sequence) {
throw new InvalidKeyException("Parameters not a SEQUENCE");
}
params.data.reset();
this.p = params.data.getBigInteger();
this.g = params.data.getBigInteger();
// Private-value length is OPTIONAL
if (params.data.available() != 0) {
this.l = params.data.getInteger();
} else {
this.l = 0;
}
if (params.data.available() != 0) {
throw new InvalidKeyException("Extra parameter data");
}
/*
* Parse the key
*/
this.key = derKeyVal.data.getBitString();
DerInputStream in = new DerInputStream(this.key);
this.y = in.getBigInteger();
if (derKeyVal.data.available() != 0) {
throw new InvalidKeyException("Excess key data");
}
this.encodedKey = encodedKey.clone();
} catch (IOException | NumberFormatException e) {
throw new InvalidKeyException("Error parsing key encoding", e);
dc = decode(this.encodedKey);
} catch (IOException e) {
throw new InvalidKeyException("Invalid encoding", e);
}
this.y = dc.y;
this.p = dc.p;
this.g = dc.g;
this.l = dc.l;
this.key = dc.key;
}
/**
@ -196,37 +258,6 @@ javax.crypto.interfaces.DHPublicKey, Serializable {
* Get the encoding of the key.
*/
public synchronized byte[] getEncoded() {
if (this.encodedKey == null) {
DerOutputStream algid = new DerOutputStream();
// store oid in algid
algid.putOID(DH_OID);
// encode parameters
DerOutputStream params = new DerOutputStream();
params.putInteger(this.p);
params.putInteger(this.g);
if (this.l != 0) {
params.putInteger(this.l);
}
// wrap parameters into SEQUENCE
DerValue paramSequence = new DerValue(DerValue.tag_Sequence,
params.toByteArray());
// store parameter SEQUENCE in algid
algid.putDerValue(paramSequence);
// wrap algid into SEQUENCE, and store it in key encoding
DerOutputStream tmpDerKey = new DerOutputStream();
tmpDerKey.write(DerValue.tag_Sequence, algid);
// store key data
tmpDerKey.putBitString(this.key);
// wrap algid and key into SEQUENCE
DerOutputStream derKey = new DerOutputStream();
derKey.write(DerValue.tag_Sequence, tmpDerKey);
this.encodedKey = derKey.toByteArray();
}
return this.encodedKey.clone();
}
@ -263,8 +294,9 @@ javax.crypto.interfaces.DHPublicKey, Serializable {
+ Debug.toHexString(this.p)
+ LINE_SEP + "g:" + LINE_SEP
+ Debug.toHexString(this.g));
if (this.l != 0)
if (this.l != 0) {
sb.append(LINE_SEP + "l:" + LINE_SEP + " " + this.l);
}
return sb.toString();
}
@ -304,7 +336,7 @@ javax.crypto.interfaces.DHPublicKey, Serializable {
return new KeyRep(KeyRep.Type.PUBLIC,
getAlgorithm(),
getFormat(),
getEncoded());
encodedKey);
}
/**
@ -323,11 +355,28 @@ javax.crypto.interfaces.DHPublicKey, Serializable {
if ((key == null) || (key.length == 0)) {
throw new InvalidObjectException("key not deserializable");
}
this.key = key.clone();
if ((encodedKey == null) || (encodedKey.length == 0)) {
throw new InvalidObjectException(
"encoded key not deserializable");
}
this.encodedKey = encodedKey.clone();
// check if the "encodedKey" value matches the deserialized fields
DHComponents c;
byte[] encodedKeyIntern = encodedKey.clone();
try {
c = decode(encodedKeyIntern);
} catch (IOException e) {
throw new InvalidObjectException("Invalid encoding", e);
}
if (!Arrays.equals(c.key, key) || !c.y.equals(y) || !c.p.equals(p)
|| !c.g.equals(g) || c.l != l) {
throw new InvalidObjectException(
"encoded key not matching internal fields");
}
// zero out external arrays
Arrays.fill(key, (byte)0x00);
Arrays.fill(encodedKey, (byte)0x00);
// use self-created internal copies
this.key = c.key;
this.encodedKey = encodedKeyIntern;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2024, 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
@ -194,22 +194,24 @@ public final class TlsMasterSecretGenerator extends KeyGeneratorSpi {
return key.clone();
}
/**
* Restores the state of this object from the stream.
*
* @param stream the {@code ObjectInputStream} from which data is read
* @throws IOException if an I/O error occurs
* @throws ClassNotFoundException if a serialized class cannot be loaded
*/
@java.io.Serial
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException {
stream.defaultReadObject();
if ((key == null) || (key.length == 0)) {
throw new InvalidObjectException("TlsMasterSecretKey is null");
}
key = key.clone();
}
}
/**
* Restores the state of this object from the stream.
*
* @param stream the {@code ObjectInputStream} from which data is read
* @throws IOException if an I/O error occurs
* @throws ClassNotFoundException if a serialized class cannot be loaded
*/
@java.io.Serial
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException {
stream.defaultReadObject();
if (key == null || key.length == 0) {
throw new InvalidObjectException("TlsMasterSecretKey is null");
}
byte[] temp = key;
this.key = temp.clone();
Arrays.fill(temp, (byte)0);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, 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
@ -407,6 +407,11 @@ implements Serializable
@SuppressWarnings("unchecked")
Hashtable<Class<?>, PermissionCollection> perms =
(Hashtable<Class<?>, PermissionCollection>)gfields.get("perms", null);
if (perms == null) {
throw new InvalidObjectException("perms can't be null");
}
permsMap = new ConcurrentHashMap<>(perms.size()*2);
permsMap.putAll(perms);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, 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
@ -152,20 +152,20 @@ public final class SignedObject implements Serializable {
*/
public SignedObject(Serializable object, PrivateKey signingKey,
Signature signingEngine)
throws IOException, InvalidKeyException, SignatureException {
// creating a stream pipe-line, from a to b
ByteArrayOutputStream b = new ByteArrayOutputStream();
ObjectOutput a = new ObjectOutputStream(b);
throws IOException, InvalidKeyException, SignatureException {
// creating a stream pipe-line, from a to b
ByteArrayOutputStream b = new ByteArrayOutputStream();
ObjectOutput a = new ObjectOutputStream(b);
// write and flush the object content to byte array
a.writeObject(object);
a.flush();
a.close();
this.content = b.toByteArray();
b.close();
// write and flush the object content to byte array
a.writeObject(object);
a.flush();
a.close();
this.content = b.toByteArray();
b.close();
// now sign the encapsulated object
this.sign(signingKey, signingEngine);
// now sign the encapsulated object
this.sign(signingKey, signingEngine);
}
/**
@ -245,12 +245,12 @@ public final class SignedObject implements Serializable {
* @throws SignatureException if signing fails.
*/
private void sign(PrivateKey signingKey, Signature signingEngine)
throws InvalidKeyException, SignatureException {
// initialize the signing engine
signingEngine.initSign(signingKey);
signingEngine.update(this.content.clone());
this.signature = signingEngine.sign().clone();
this.thealgorithm = signingEngine.getAlgorithm();
throws InvalidKeyException, SignatureException {
// initialize the signing engine
signingEngine.initSign(signingKey);
signingEngine.update(this.content.clone());
this.signature = signingEngine.sign();
this.thealgorithm = signingEngine.getAlgorithm();
}
/**
@ -263,10 +263,16 @@ public final class SignedObject implements Serializable {
*/
@Serial
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {
ObjectInputStream.GetField fields = s.readFields();
content = ((byte[])fields.get("content", null)).clone();
signature = ((byte[])fields.get("signature", null)).clone();
thealgorithm = (String)fields.get("thealgorithm", null);
throws IOException, ClassNotFoundException {
ObjectInputStream.GetField fields = s.readFields();
byte[] c = (byte[]) fields.get("content", null);
byte[] sig = (byte[]) fields.get("signature", null);
String a = (String) fields.get("thealgorithm", null);
if (c == null || sig == null || a == null) {
throw new InvalidObjectException("One or more null fields");
}
content = c.clone();
signature = sig.clone();
thealgorithm = a;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2024, 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,6 +27,7 @@ package java.security;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.InvalidObjectException;
import java.io.Serializable;
import java.security.cert.CertPath;
import java.security.cert.Certificate;
@ -78,7 +79,7 @@ public final class Timestamp implements Serializable {
* {@code null}.
*/
public Timestamp(Date timestamp, CertPath signerCertPath) {
if (timestamp == null || signerCertPath == null) {
if (isNull(timestamp, signerCertPath)) {
throw new NullPointerException();
}
this.timestamp = new Date(timestamp.getTime()); // clone
@ -166,9 +167,16 @@ public final class Timestamp implements Serializable {
*/
@java.io.Serial
private void readObject(ObjectInputStream ois)
throws IOException, ClassNotFoundException {
throws IOException, ClassNotFoundException {
ois.defaultReadObject();
if (isNull(timestamp, signerCertPath)) {
throw new InvalidObjectException("Invalid null field(s)");
}
myhash = -1;
timestamp = new Date(timestamp.getTime());
}
private static boolean isNull(Date d, CertPath c) {
return (d == null || c == null);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, 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 java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
import java.io.InvalidObjectException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
@ -196,23 +197,32 @@ implements java.io.Serializable
ObjectInputStream.GetField gfields = in.readFields();
// Get permissions
@SuppressWarnings("unchecked")
// writeObject writes a Hashtable<String, Vector<UnresolvedPermission>>
// for the permissions key, so this cast is safe, unless the data is corrupt.
Hashtable<String, Vector<UnresolvedPermission>> permissions =
(Hashtable<String, Vector<UnresolvedPermission>>)
gfields.get("permissions", null);
perms = new ConcurrentHashMap<>(permissions.size()*2);
try {
@SuppressWarnings("unchecked")
Hashtable<String, Vector<UnresolvedPermission>> permissions =
(Hashtable<String, Vector<UnresolvedPermission>>)
gfields.get("permissions", null);
// Convert each entry (Vector) into a List
Set<Map.Entry<String, Vector<UnresolvedPermission>>> set = permissions.entrySet();
for (Map.Entry<String, Vector<UnresolvedPermission>> e : set) {
// Convert Vector into ArrayList
Vector<UnresolvedPermission> vec = e.getValue();
List<UnresolvedPermission> list = new CopyOnWriteArrayList<>(vec);
if (permissions == null) {
throw new InvalidObjectException("Invalid null permissions");
}
// Add to Hashtable being serialized
perms.put(e.getKey(), list);
perms = new ConcurrentHashMap<>(permissions.size()*2);
// Convert each entry (Vector) into a List
Set<Map.Entry<String, Vector<UnresolvedPermission>>> set = permissions.entrySet();
for (Map.Entry<String, Vector<UnresolvedPermission>> e : set) {
// Convert Vector into ArrayList
Vector<UnresolvedPermission> vec = e.getValue();
List<UnresolvedPermission> list = new CopyOnWriteArrayList<>(vec);
// Add to Hashtable being serialized
perms.put(e.getKey(), list);
}
} catch (ClassCastException cce) {
throw new InvalidObjectException("Invalid type for permissions");
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -28,6 +28,7 @@ package java.security.cert;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
@ -70,6 +71,13 @@ public class CertificateRevokedException extends CertificateException {
private transient Map<String, Extension> extensions;
private static boolean isNull(Date revocationDate,
CRLReason reason, X500Principal authority,
Map<String, Extension> extensions) {
return (revocationDate == null || reason == null || authority == null
|| extensions == null);
}
/**
* Constructs a {@code CertificateRevokedException} with
* the specified revocation date, reason code, authority name, and map
@ -92,8 +100,7 @@ public class CertificateRevokedException extends CertificateException {
*/
public CertificateRevokedException(Date revocationDate, CRLReason reason,
X500Principal authority, Map<String, Extension> extensions) {
if (revocationDate == null || reason == null || authority == null ||
extensions == null) {
if (isNull(revocationDate, reason, authority, extensions)) {
throw new NullPointerException();
}
this.revocationDate = new Date(revocationDate.getTime());
@ -234,9 +241,6 @@ public class CertificateRevokedException extends CertificateException {
// (revocationDate, reason, authority)
ois.defaultReadObject();
// Defensively copy the revocation date
revocationDate = new Date(revocationDate.getTime());
// Read in the size (number of mappings) of the extensions map
// and create the extensions map
int size = ois.readInt();
@ -247,6 +251,13 @@ public class CertificateRevokedException extends CertificateException {
} else {
extensions = HashMap.newHashMap(Math.min(size, 20));
}
// make sure all fields are set before checking
if (isNull(revocationDate, reason, authority, extensions)) {
throw new InvalidObjectException("Invalid null field(s)");
}
// Defensively copy the revocation date
revocationDate = new Date(revocationDate.getTime());
// Read in the extensions and put the mappings in the extensions map
for (int i = 0; i < size; i++) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2024, 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
@ -100,11 +100,9 @@ public class SecretKeySpec implements KeySpec, SecretKey {
* is null or <code>key</code> is null or empty.
*/
public SecretKeySpec(byte[] key, String algorithm) {
if (key == null || algorithm == null) {
throw new IllegalArgumentException("Missing argument");
}
if (key.length == 0) {
throw new IllegalArgumentException("Empty key");
String errMsg = doSanityCheck(key, algorithm);
if (errMsg != null) {
throw new IllegalArgumentException(errMsg);
}
this.key = key.clone();
this.algorithm = algorithm;
@ -266,14 +264,22 @@ public class SecretKeySpec implements KeySpec, SecretKey {
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException {
stream.defaultReadObject();
String errMsg = doSanityCheck(key, algorithm);
if (errMsg != null) {
throw new InvalidObjectException(errMsg);
}
byte[] temp = key;
this.key = temp.clone();
Arrays.fill(temp, (byte) 0);
}
private static String doSanityCheck(byte[] key, String algorithm) {
String errMsg = null;
if (key == null || algorithm == null) {
throw new InvalidObjectException("Missing argument");
}
this.key = key.clone();
if (key.length == 0) {
throw new InvalidObjectException("Invalid key length");
errMsg = "Missing argument";
} else if (key.length == 0) {
errMsg = "Empty key";
}
return errMsg;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2024, 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
@ -102,20 +102,18 @@ public class ChoiceCallback implements Callback, java.io.Serializable {
public ChoiceCallback(String prompt, String[] choices,
int defaultChoice, boolean multipleSelectionsAllowed) {
if (prompt == null || prompt.isEmpty() ||
choices == null || choices.length == 0 ||
defaultChoice < 0 || defaultChoice >= choices.length)
throw new IllegalArgumentException();
choices = (choices == null || choices.length == 0 ? choices :
choices.clone());
String errMsg = doSanityCheck(prompt, choices, defaultChoice,
multipleSelectionsAllowed);
if (errMsg != null) {
throw new IllegalArgumentException(errMsg);
}
this.prompt = prompt;
this.defaultChoice = defaultChoice;
this.multipleSelectionsAllowed = multipleSelectionsAllowed;
this.choices = choices.clone();
for (int i = 0; i < choices.length; i++) {
if (choices[i] == null || choices[i].isEmpty())
throw new IllegalArgumentException();
}
this.choices = choices;
}
/**
@ -183,9 +181,11 @@ public class ChoiceCallback implements Callback, java.io.Serializable {
* @see #getSelectedIndexes
*/
public void setSelectedIndexes(int[] selections) {
if (!multipleSelectionsAllowed)
if (!multipleSelectionsAllowed) {
throw new UnsupportedOperationException();
this.selections = selections == null ? null : selections.clone();
}
this.selections = ((selections == null || selections.length == 0) ?
selections : selections.clone());
}
/**
@ -211,26 +211,35 @@ public class ChoiceCallback implements Callback, java.io.Serializable {
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException {
stream.defaultReadObject();
choices = (choices == null || choices.length == 0 ?
choices : choices.clone());
String errMsg = doSanityCheck(prompt, choices, defaultChoice,
multipleSelectionsAllowed);
if (errMsg != null) {
throw new InvalidObjectException(errMsg);
}
selections = (selections == null || selections.length == 0 ?
selections : selections.clone());
if (selections != null && selections.length > 1 &&
!multipleSelectionsAllowed) {
throw new InvalidObjectException("Multiple selections not allowed");
}
}
private static String doSanityCheck(String prompt, String[] choices,
int defaultChoice, boolean allowMultiple) {
if ((prompt == null) || prompt.isEmpty() ||
(choices == null) || (choices.length == 0) ||
(defaultChoice < 0) || (defaultChoice >= choices.length)) {
throw new InvalidObjectException(
"Missing/invalid prompt/choices");
return "Missing/invalid prompt/choices";
}
choices = choices.clone();
for (int i = 0; i < choices.length; i++) {
if ((choices[i] == null) || choices[i].isEmpty())
throw new InvalidObjectException("Null/empty choices");
}
if (selections != null) {
selections = selections.clone();
if (!multipleSelectionsAllowed && (selections.length != 1)) {
throw new InvalidObjectException(
"Multiple selections not allowed");
if ((choices[i] == null) || choices[i].isEmpty()) {
return "Null/empty choices value";
}
}
return null;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -26,6 +26,7 @@
package javax.security.auth.callback;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
/**
@ -189,25 +190,10 @@ public class ConfirmationCallback implements Callback, java.io.Serializable {
*/
public ConfirmationCallback(int messageType,
int optionType, int defaultOption) {
if (messageType < INFORMATION || messageType > ERROR ||
optionType < YES_NO_OPTION || optionType > OK_CANCEL_OPTION)
throw new IllegalArgumentException();
switch (optionType) {
case YES_NO_OPTION:
if (defaultOption != YES && defaultOption != NO)
throw new IllegalArgumentException();
break;
case YES_NO_CANCEL_OPTION:
if (defaultOption != YES && defaultOption != NO &&
defaultOption != CANCEL)
throw new IllegalArgumentException();
break;
case OK_CANCEL_OPTION:
if (defaultOption != OK && defaultOption != CANCEL)
throw new IllegalArgumentException();
break;
String errMsg = doSanityCheck(messageType, optionType, false, null,
defaultOption, null, false);
if (errMsg != null) {
throw new IllegalArgumentException(errMsg);
}
this.prompt = null;
@ -250,21 +236,20 @@ public class ConfirmationCallback implements Callback, java.io.Serializable {
public ConfirmationCallback(int messageType,
String[] options, int defaultOption) {
if (messageType < INFORMATION || messageType > ERROR ||
options == null || options.length == 0 ||
defaultOption < 0 || defaultOption >= options.length)
throw new IllegalArgumentException();
if (options != null) {
options = options.clone();
}
String errMsg = doSanityCheck(messageType, UNSPECIFIED_OPTION, true,
options, defaultOption, null, false);
if (errMsg != null) {
throw new IllegalArgumentException(errMsg);
}
this.prompt = null;
this.messageType = messageType;
this.optionType = UNSPECIFIED_OPTION;
this.defaultOption = defaultOption;
this.options = options.clone();
for (int i = 0; i < options.length; i++) {
if (options[i] == null || options[i].isEmpty())
throw new IllegalArgumentException();
}
this.options = options;
}
/**
@ -304,27 +289,11 @@ public class ConfirmationCallback implements Callback, java.io.Serializable {
public ConfirmationCallback(String prompt, int messageType,
int optionType, int defaultOption) {
if (prompt == null || prompt.isEmpty() ||
messageType < INFORMATION || messageType > ERROR ||
optionType < YES_NO_OPTION || optionType > OK_CANCEL_OPTION)
throw new IllegalArgumentException();
switch (optionType) {
case YES_NO_OPTION:
if (defaultOption != YES && defaultOption != NO)
throw new IllegalArgumentException();
break;
case YES_NO_CANCEL_OPTION:
if (defaultOption != YES && defaultOption != NO &&
defaultOption != CANCEL)
throw new IllegalArgumentException();
break;
case OK_CANCEL_OPTION:
if (defaultOption != OK && defaultOption != CANCEL)
throw new IllegalArgumentException();
break;
String errMsg = doSanityCheck(messageType, optionType, false, null,
defaultOption, prompt, true);
if (errMsg != null) {
throw new IllegalArgumentException(errMsg);
}
this.prompt = prompt;
this.messageType = messageType;
this.optionType = optionType;
@ -369,22 +338,20 @@ public class ConfirmationCallback implements Callback, java.io.Serializable {
public ConfirmationCallback(String prompt, int messageType,
String[] options, int defaultOption) {
if (prompt == null || prompt.isEmpty() ||
messageType < INFORMATION || messageType > ERROR ||
options == null || options.length == 0 ||
defaultOption < 0 || defaultOption >= options.length)
throw new IllegalArgumentException();
if (options != null) {
options = options.clone();
}
String errMsg = doSanityCheck(messageType, UNSPECIFIED_OPTION, true,
options, defaultOption, prompt, true);
if (errMsg != null) {
throw new IllegalArgumentException(errMsg);
}
this.prompt = prompt;
this.messageType = messageType;
this.optionType = UNSPECIFIED_OPTION;
this.defaultOption = defaultOption;
this.options = options.clone();
for (int i = 0; i < options.length; i++) {
if (options[i] == null || options[i].isEmpty())
throw new IllegalArgumentException();
}
this.options = options;
}
/**
@ -491,6 +458,49 @@ public class ConfirmationCallback implements Callback, java.io.Serializable {
return selection;
}
private static String doSanityCheck(int msgType, int optionType,
boolean isUnspecifiedOption, String[] options, int defOption,
String prompt, boolean checkPrompt) {
// validate msgType
if (msgType < INFORMATION || msgType > ERROR) {
return "Invalid msgType";
}
// validate prompt if checkPrompt == true
if (checkPrompt && (prompt == null || prompt.isEmpty())) {
return "Invalid prompt";
}
// validate optionType
if (isUnspecifiedOption) {
if (optionType != UNSPECIFIED_OPTION) {
return "Invalid optionType";
}
// check options
if (options == null || options.length == 0 ||
defOption < 0 || defOption >= options.length) {
return "Invalid options and/or default option";
}
for (String ov : options) {
if (ov == null || ov.isEmpty()) {
return "Invalid option value";
}
}
} else {
if (optionType < YES_NO_OPTION || optionType > OK_CANCEL_OPTION) {
return "Invalid optionType";
}
// validate defOption based on optionType
if ((optionType == YES_NO_OPTION && (defOption != YES &&
defOption != NO)) ||
(optionType == YES_NO_CANCEL_OPTION && (defOption != YES &&
defOption != NO && defOption != CANCEL)) ||
(optionType == OK_CANCEL_OPTION && (defOption != OK &&
defOption != CANCEL))) {
return "Invalid default option";
}
}
return null;
}
/**
* Restores the state of this object from the stream.
*
@ -502,8 +512,15 @@ public class ConfirmationCallback implements Callback, java.io.Serializable {
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException {
stream.defaultReadObject();
if (options != null) {
options = options.clone();
}
String errMsg = doSanityCheck(messageType, optionType,
(optionType == UNSPECIFIED_OPTION), options, defaultOption,
prompt, false);
if (errMsg != null) {
throw new InvalidObjectException(errMsg);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2024, 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
@ -178,7 +178,9 @@ public class PasswordCallback implements Callback, java.io.Serializable {
}
if (inputPassword != null) {
inputPassword = inputPassword.clone();
char[] temp = inputPassword;
inputPassword = temp.clone();
Arrays.fill(temp, '0');
cleanable = CleanerFactory.cleaner().register(
this, cleanerFor(inputPassword));
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -26,6 +26,7 @@
package sun.security.provider;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.security.AccessController;
import java.security.DrbgParameters;
import java.security.PrivilegedAction;
@ -272,11 +273,18 @@ public final class DRBG extends SecureRandomSpi {
}
}
/**
* Restores the state of this object from the stream.
*
* @param s the {@code ObjectInputStream} from which data is read
* @throws IOException if an I/O error occurs
* @throws ClassNotFoundException if a serialized class cannot be loaded
*/
@java.io.Serial
private void readObject(java.io.ObjectInputStream s)
throws IOException, ClassNotFoundException {
s.defaultReadObject();
if (mdp.mech == null) {
if (mdp == null || mdp.mech == null) {
throw new IllegalArgumentException("Input data is corrupted");
}
createImpl();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2024, 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
@ -127,13 +127,24 @@ public final class ObjectIdentifier implements Serializable {
// Is the component's field calculated?
private transient boolean componentsCalculated = false;
/**
* Restores the state of this object from the stream.
*
* @param is the {@code ObjectInputStream} from which data is read
* @throws IOException if an I/O error occurs
* @throws ClassNotFoundException if a serialized class cannot be loaded
*/
@java.io.Serial
private void readObject(ObjectInputStream is)
throws IOException, ClassNotFoundException {
is.defaultReadObject();
if (encoding == null) { // from an old version
int[] comp = (int[])components;
if (components == null) {
throw new InvalidObjectException("OID components is null");
}
int[] comp = ((int[]) components).clone();
if (componentLen > comp.length) {
componentLen = comp.length;
}
@ -142,7 +153,9 @@ public final class ObjectIdentifier implements Serializable {
// will be performed again in init().
checkOidSize(componentLen);
init(comp, componentLen);
components = comp;
} else {
encoding = encoding.clone(); // defensive copying
checkOidSize(encoding.length);
check(encoding);
}
@ -261,6 +274,7 @@ public final class ObjectIdentifier implements Serializable {
encoding = in.getDerValue().getOID().encoding;
}
// set 'encoding' field based on the specified 'components' and 'length'
private void init(int[] components, int length) throws IOException {
int pos = 0;
byte[] tmp = new byte[length * 5 + 1]; // +1 for empty input

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2024, 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,11 +25,13 @@
package sun.security.x509;
import java.io.ObjectInputStream;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.math.BigInteger;
import java.security.*;
import java.security.interfaces.DSAParams;
import java.util.Arrays;
import sun.security.util.*;
@ -72,33 +74,42 @@ import sun.security.util.*;
*
* @author David Brownell
*/
public final
class AlgIdDSA extends AlgorithmId implements DSAParams
{
public final class AlgIdDSA extends AlgorithmId implements DSAParams {
@java.io.Serial
private static final long serialVersionUID = 3437177836797504046L;
private static class DSAComponents {
private final BigInteger p;
private final BigInteger q;
private final BigInteger g;
DSAComponents(BigInteger p, BigInteger q, BigInteger g) {
this.p = p;
this.q = q;
this.g = g;
}
}
/*
* The three unsigned integer parameters.
*/
private BigInteger p , q, g;
private BigInteger p, q, g;
/** Returns the DSS/DSA parameter "P" */
public BigInteger getP () { return p; }
public BigInteger getP() { return p; }
/** Returns the DSS/DSA parameter "Q" */
public BigInteger getQ () { return q; }
public BigInteger getQ() { return q; }
/** Returns the DSS/DSA parameter "G" */
public BigInteger getG () { return g; }
public BigInteger getG() { return g; }
/**
* Default constructor. The OID and parameters must be
* deserialized before this algorithm ID is used.
*/
@Deprecated
public AlgIdDSA () {}
public AlgIdDSA() {}
/**
* Constructs a DSS/DSA Algorithm ID from numeric parameters.
@ -109,7 +120,7 @@ class AlgIdDSA extends AlgorithmId implements DSAParams
* @param q the DSS/DSA parameter "Q"
* @param g the DSS/DSA parameter "G"
*/
public AlgIdDSA (BigInteger p, BigInteger q, BigInteger g) {
public AlgIdDSA(BigInteger p, BigInteger q, BigInteger g) {
super (DSA_oid);
if (p != null || q != null || g != null) {
@ -120,8 +131,10 @@ class AlgIdDSA extends AlgorithmId implements DSAParams
this.p = p;
this.q = q;
this.g = g;
initializeParams ();
// For algorithm IDs which haven't been created from a DER
// encoded value, need to create DER encoding and store it
// into "encodedParams"
encodedParams = encode(p, q, g);
} catch (IOException e) {
/* this should not happen */
throw new ProviderException ("Construct DSS/DSA Algorithm ID");
@ -133,50 +146,10 @@ class AlgIdDSA extends AlgorithmId implements DSAParams
* Returns "DSA", indicating the Digital Signature Algorithm (DSA) as
* defined by the Digital Signature Standard (DSS), FIPS 186.
*/
public String getName ()
{ return "DSA"; }
/*
* For algorithm IDs which haven't been created from a DER encoded
* value, "params" must be created.
*/
private void initializeParams () throws IOException {
DerOutputStream out = new DerOutputStream();
out.putInteger(p);
out.putInteger(q);
out.putInteger(g);
DerOutputStream result = new DerOutputStream();
result.write(DerValue.tag_Sequence, out);
encodedParams = result.toByteArray();
public String getName() {
return "DSA";
}
/**
* Parses algorithm parameters P, Q, and G. They're found
* in the "params" member, which never needs to be changed.
*/
protected void decodeParams () throws IOException {
if (encodedParams == null) {
throw new IOException("DSA alg params are null");
}
DerValue params = new DerValue(encodedParams);
if (params.tag != DerValue.tag_Sequence) {
throw new IOException("DSA alg parsing error");
}
params.data.reset ();
this.p = params.data.getBigInteger();
this.q = params.data.getBigInteger();
this.g = params.data.getBigInteger();
if (params.data.available () != 0)
throw new IOException ("AlgIdDSA params, extra="+
params.data.available ());
}
/*
* Returns a formatted string describing the parameters.
*/
@ -197,4 +170,44 @@ class AlgIdDSA extends AlgorithmId implements DSAParams
"\n";
}
}
/**
* Restores the state of this object from the stream. Override to check
* on the 'p', 'q', 'g', and 'encodedParams'.
*
* @param stream the {@code ObjectInputStream} from which data is read
* @throws IOException if an I/O error occurs
* @throws ClassNotFoundException if a serialized class cannot be loaded
*/
@java.io.Serial
private void readObject(ObjectInputStream stream) throws IOException {
try {
stream.defaultReadObject();
// if any of the 'p', 'q', 'g', 'encodedParams' is non-null,
// then they must be all non-null w/ matching encoding
if ((p != null || q != null || g != null || encodedParams != null)
&& !Arrays.equals(encodedParams, encode(p, q, g))) {
throw new InvalidObjectException("Invalid DSA alg params");
}
} catch (ClassNotFoundException e) {
throw new IOException(e);
}
}
/*
* Create the DER encoding w/ the specified 'p', 'q', 'g'
*/
private static byte[] encode(BigInteger p, BigInteger q,
BigInteger g) throws IOException {
if (p == null || q == null || g == null) {
throw new InvalidObjectException("invalid null value");
}
DerOutputStream out = new DerOutputStream();
out.putInteger(p);
out.putInteger(q);
out.putInteger(g);
DerOutputStream result = new DerOutputStream();
result.write(DerValue.tag_Sequence, out);
return result.toByteArray();
}
}

View File

@ -217,13 +217,14 @@ final class ProcessImpl extends Process {
private static final int VERIFICATION_LEGACY = 3;
// See Command shell overview for documentation of special characters.
// https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-xp/bb490954(v=technet.10)
private static final char ESCAPE_VERIFICATION[][] = {
private static final String ESCAPE_VERIFICATION[] = {
// We guarantee the only command file execution for implicit [cmd.exe] run.
// http://technet.microsoft.com/en-us/library/bb490954.aspx
{' ', '\t', '\"', '<', '>', '&', '|', '^'},
{' ', '\t', '\"', '<', '>'},
{' ', '\t', '\"', '<', '>'},
{' ', '\t'}
// All space characters require quoting are checked in needsEscaping().
"\"<>&|^",
"\"<>",
"\"<>",
""
};
private static String createCommandLine(int verificationType,
@ -338,9 +339,14 @@ final class ProcessImpl extends Process {
}
if (!argIsQuoted) {
char testEscape[] = ESCAPE_VERIFICATION[verificationType];
for (int i = 0; i < testEscape.length; ++i) {
if (arg.indexOf(testEscape[i]) >= 0) {
for (int i = 0; i < arg.length(); i++) {
char ch = arg.charAt(i);
if (Character.isLetterOrDigit(ch))
continue; // skip over common characters
// All space chars require quotes and other mode specific characters
if (Character.isSpaceChar(ch) ||
Character.isWhitespace(ch) ||
ESCAPE_VERIFICATION[verificationType].indexOf(ch) >= 0) {
return true;
}
}

View File

@ -60,7 +60,7 @@ typedef struct {
#define UNSAFE_TO_SUB(a, b) \
(((b >= 0) && (a < 0) && (a < (INT_MIN + b))) || \
((b < 0) && (a >= 0) && (-b > (INT_MAX - a)))) \
((b < 0) && (a >= 0) && (a > (INT_MAX + b)))) \
/*
* The SurfaceDataRasInfo structure is used to pass in and return various

View File

@ -33,8 +33,10 @@ import sun.security.jgss.spi.*;
import sun.security.jgss.TokenTracker;
import sun.security.krb5.*;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.InvalidObjectException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.security.*;
import javax.security.auth.Subject;
import javax.security.auth.kerberos.ServicePermission;
@ -1398,6 +1400,20 @@ class Krb5Context implements GSSContextSpi {
return "Kerberos session key: etype=" + key.getEType()
+ ", " + Krb5Util.keyInfo(key.getBytes());
}
/**
* Restores the state of this object from the stream.
*
* @param stream the {@code ObjectInputStream} from which data is read
* @throws IOException if an I/O error occurs
* @throws ClassNotFoundException if a serialized class cannot be loaded
*/
@java.io.Serial
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException {
throw new InvalidObjectException
("KerberosSessionKey not directly deserializable");
}
}
/**
@ -1467,5 +1483,4 @@ class Krb5Context implements GSSContextSpi {
public void setAuthzData(AuthorizationData authzData) {
this.authzData = authzData;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -33,7 +33,9 @@ import javax.security.auth.kerberos.KerberosTicket;
import javax.security.auth.kerberos.KerberosPrincipal;
import java.io.Serial;
import java.net.InetAddress;
import java.io.InvalidObjectException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.Date;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
@ -400,4 +402,17 @@ public class Krb5InitCredential
throw ge;
}
}
/**
* Restores the state of this object from the stream.
*
* @param stream the {@code ObjectInputStream} from which data is read
* @throws IOException if an I/O error occurs
* @throws ClassNotFoundException if a serialized class cannot be loaded
*/
@java.io.Serial
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException {
throw new InvalidObjectException("Krb5InitCredential not deserializable");
}
}

View File

@ -83,28 +83,34 @@ import static sun.security.krb5.internal.Krb5.DEBUG;
* <a href="http://www.ietf.org/rfc/rfc4120.txt">
* http://www.ietf.org/rfc/rfc4120.txt</a>.
*/
// The instance fields not statically typed as Serializable are ASN.1
// encoded and written by the writeObject method.
@SuppressWarnings("serial")
public class KRBError implements java.io.Serializable {
static final long serialVersionUID = 3643809337475284503L;
private int pvno;
private int msgType;
private KerberosTime cTime; //optional
private Integer cuSec; //optional
private KerberosTime sTime;
private Integer suSec;
private int errorCode;
private Realm crealm; //optional
private PrincipalName cname; //optional
private PrincipalName sname;
private String eText; //optional
private byte[] eData; //optional
private Checksum eCksum; //optional
private transient int pvno;
private transient int msgType;
private transient KerberosTime cTime; //optional
private transient Integer cuSec; //optional
private transient KerberosTime sTime;
private transient Integer suSec;
private transient int errorCode;
private transient Realm crealm; //optional
private transient PrincipalName cname; //optional
private transient PrincipalName sname;
private transient String eText; //optional
private transient byte[] eData; //optional
private transient Checksum eCksum; //optional
private PAData[] pa; // PA-DATA in eData
private transient PAData[] pa; // PA-DATA in eData
/**
* Restores the state of this object from the stream.
*
* @param is the {@code ObjectInputStream} from which data is read
* @throws IOException if an I/O error occurs
* @throws ClassNotFoundException if a serialized class cannot be loaded
*/
@java.io.Serial
private void readObject(ObjectInputStream is)
throws IOException, ClassNotFoundException {
try {

View File

@ -240,6 +240,19 @@ abstract class P11Key implements Key, Length {
return new KeyRep(type, getAlgorithm(), format, getEncodedInternal());
}
/**
* Restores the state of this object from the stream.
*
* @param stream the {@code ObjectInputStream} from which data is read
* @throws IOException if an I/O error occurs
* @throws ClassNotFoundException if a serialized class cannot be loaded
*/
@java.io.Serial
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException {
throw new InvalidObjectException("P11Key not directly deserializable");
}
public String toString() {
token.ensureValid();
String s1 = token.provider.getName() + " " + algorithm + " " + type

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2024, 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
@ -187,9 +187,23 @@ final class P11SecureRandom extends SecureRandomSpi {
}
}
/**
* Restores the state of this object from the stream.
*
* @param in the {@code ObjectInputStream} from which data is read
* @throws IOException if an I/O error occurs
* @throws ClassNotFoundException if a serialized class cannot be loaded
*/
@java.io.Serial
private void readObject(ObjectInputStream in)
throws IOException, ClassNotFoundException {
in.defaultReadObject();
if (token == null) {
throw new InvalidObjectException("token is null");
}
if (mixBuffer != null) {
mixBuffer = mixBuffer.clone();
}
// assign default values to non-null transient fields
iBuffer = new byte[IBUFFER_SIZE];
ibuffered = 0;

View File

@ -1924,6 +1924,19 @@ public final class SunPKCS11 extends AuthProvider {
return new SunPKCS11Rep(this);
}
/**
* Restores the state of this object from the stream.
*
* @param stream the {@code ObjectInputStream} from which data is read
* @throws IOException if an I/O error occurs
* @throws ClassNotFoundException if a serialized class cannot be loaded
*/
@java.io.Serial
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException {
throw new InvalidObjectException("SunPKCS11 not directly deserializable");
}
/**
* Serialized representation of the SunPKCS11 provider.
*/

View File

@ -36,6 +36,7 @@
* @requires vm.opt.TieredStopAtLevel == null & vm.opt.TieredCompilation == null
* @requires vm.simpleArch == "x86" | vm.simpleArch == "x64" | vm.simpleArch == "aarch64" | vm.simpleArch == "riscv64"
* @requires vm.debug
* @requires !vm.graal.enabled
* @run driver compiler.sharedstubs.SharedStubToInterpTest -XX:-TieredCompilation
*
*/