mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 06:45:07 +02:00
Merge
Reviewed-by: alanb, dfuchs
This commit is contained in:
commit
cf5bb12731
79 changed files with 3346 additions and 911 deletions
|
@ -30,6 +30,8 @@
|
|||
package sun.net.www;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Array;
|
||||
import java.net.ProtocolException;
|
||||
import java.util.Collections;
|
||||
import java.util.*;
|
||||
|
||||
|
@ -45,11 +47,32 @@ public final class MessageHeader {
|
|||
private String[] values;
|
||||
private int nkeys;
|
||||
|
||||
// max number of bytes for headers, <=0 means unlimited;
|
||||
// this corresponds to the length of the names, plus the length
|
||||
// of the values, plus an overhead of 32 bytes per name: value
|
||||
// pair.
|
||||
// Note: we use the same definition as HTTP/2 SETTINGS_MAX_HEADER_LIST_SIZE
|
||||
// see RFC 9113, section 6.5.2.
|
||||
// https://www.rfc-editor.org/rfc/rfc9113.html#SETTINGS_MAX_HEADER_LIST_SIZE
|
||||
private final int maxHeaderSize;
|
||||
|
||||
// Aggregate size of the field lines (name + value + 32) x N
|
||||
// that have been parsed and accepted so far.
|
||||
// This is defined as a long to force promotion to long
|
||||
// and avoid overflows; see checkNewSize;
|
||||
private long size;
|
||||
|
||||
public MessageHeader () {
|
||||
this(0);
|
||||
}
|
||||
|
||||
public MessageHeader (int maxHeaderSize) {
|
||||
this.maxHeaderSize = maxHeaderSize;
|
||||
grow();
|
||||
}
|
||||
|
||||
public MessageHeader (InputStream is) throws java.io.IOException {
|
||||
maxHeaderSize = 0;
|
||||
parseHeader(is);
|
||||
}
|
||||
|
||||
|
@ -476,10 +499,28 @@ public final class MessageHeader {
|
|||
public void parseHeader(InputStream is) throws java.io.IOException {
|
||||
synchronized (this) {
|
||||
nkeys = 0;
|
||||
size = 0;
|
||||
}
|
||||
mergeHeader(is);
|
||||
}
|
||||
|
||||
private void checkMaxHeaderSize(int sz) throws ProtocolException {
|
||||
if (maxHeaderSize > 0) checkNewSize(size, sz, 0);
|
||||
}
|
||||
|
||||
private long checkNewSize(long size, int name, int value) throws ProtocolException {
|
||||
// See SETTINGS_MAX_HEADER_LIST_SIZE, RFC 9113, section 6.5.2.
|
||||
long newSize = size + name + value + 32;
|
||||
if (maxHeaderSize > 0 && newSize > maxHeaderSize) {
|
||||
Arrays.fill(keys, 0, nkeys, null);
|
||||
Arrays.fill(values,0, nkeys, null);
|
||||
nkeys = 0;
|
||||
throw new ProtocolException(String.format("Header size too big: %s > %s",
|
||||
newSize, maxHeaderSize));
|
||||
}
|
||||
return newSize;
|
||||
}
|
||||
|
||||
/** Parse and merge a MIME header from an input stream. */
|
||||
@SuppressWarnings("fallthrough")
|
||||
public void mergeHeader(InputStream is) throws java.io.IOException {
|
||||
|
@ -493,7 +534,15 @@ public final class MessageHeader {
|
|||
int c;
|
||||
boolean inKey = firstc > ' ';
|
||||
s[len++] = (char) firstc;
|
||||
checkMaxHeaderSize(len);
|
||||
parseloop:{
|
||||
// We start parsing for a new name value pair here.
|
||||
// The max header size includes an overhead of 32 bytes per
|
||||
// name value pair.
|
||||
// See SETTINGS_MAX_HEADER_LIST_SIZE, RFC 9113, section 6.5.2.
|
||||
long maxRemaining = maxHeaderSize > 0
|
||||
? maxHeaderSize - size - 32
|
||||
: Long.MAX_VALUE;
|
||||
while ((c = is.read()) >= 0) {
|
||||
switch (c) {
|
||||
case ':':
|
||||
|
@ -527,6 +576,9 @@ public final class MessageHeader {
|
|||
s = ns;
|
||||
}
|
||||
s[len++] = (char) c;
|
||||
if (maxHeaderSize > 0 && len > maxRemaining) {
|
||||
checkMaxHeaderSize(len);
|
||||
}
|
||||
}
|
||||
firstc = -1;
|
||||
}
|
||||
|
@ -548,6 +600,9 @@ public final class MessageHeader {
|
|||
v = new String();
|
||||
else
|
||||
v = String.copyValueOf(s, keyend, len - keyend);
|
||||
int klen = k == null ? 0 : k.length();
|
||||
|
||||
size = checkNewSize(size, klen, v.length());
|
||||
add(k, v);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -172,6 +172,8 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
|||
*/
|
||||
private static final int bufSize4ES;
|
||||
|
||||
private static final int maxHeaderSize;
|
||||
|
||||
/*
|
||||
* Restrict setting of request headers through the public api
|
||||
* consistent with JavaScript XMLHttpRequest2 with a few
|
||||
|
@ -288,6 +290,19 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
|||
} else {
|
||||
restrictedHeaderSet = null;
|
||||
}
|
||||
|
||||
int defMaxHeaderSize = 384 * 1024;
|
||||
String maxHeaderSizeStr = getNetProperty("jdk.http.maxHeaderSize");
|
||||
int maxHeaderSizeVal = defMaxHeaderSize;
|
||||
if (maxHeaderSizeStr != null) {
|
||||
try {
|
||||
maxHeaderSizeVal = Integer.parseInt(maxHeaderSizeStr);
|
||||
} catch (NumberFormatException n) {
|
||||
maxHeaderSizeVal = defMaxHeaderSize;
|
||||
}
|
||||
}
|
||||
if (maxHeaderSizeVal < 0) maxHeaderSizeVal = 0;
|
||||
maxHeaderSize = maxHeaderSizeVal;
|
||||
}
|
||||
|
||||
static final String httpVersion = "HTTP/1.1";
|
||||
|
@ -754,7 +769,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
|||
}
|
||||
ps = (PrintStream) http.getOutputStream();
|
||||
connected=true;
|
||||
responses = new MessageHeader();
|
||||
responses = new MessageHeader(maxHeaderSize);
|
||||
setRequests=false;
|
||||
writeRequests();
|
||||
}
|
||||
|
@ -912,7 +927,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
|||
throws IOException {
|
||||
super(checkURL(u));
|
||||
requests = new MessageHeader();
|
||||
responses = new MessageHeader();
|
||||
responses = new MessageHeader(maxHeaderSize);
|
||||
userHeaders = new MessageHeader();
|
||||
this.handler = handler;
|
||||
instProxy = p;
|
||||
|
@ -2810,7 +2825,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
|||
}
|
||||
|
||||
// clear out old response headers!!!!
|
||||
responses = new MessageHeader();
|
||||
responses = new MessageHeader(maxHeaderSize);
|
||||
if (stat == HTTP_USE_PROXY) {
|
||||
/* This means we must re-request the resource through the
|
||||
* proxy denoted in the "Location:" field of the response.
|
||||
|
@ -3000,7 +3015,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
|||
} catch (IOException e) { }
|
||||
}
|
||||
responseCode = -1;
|
||||
responses = new MessageHeader();
|
||||
responses = new MessageHeader(maxHeaderSize);
|
||||
connected = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -213,8 +213,6 @@ final class ClientHello {
|
|||
// ignore cookie
|
||||
hos.putBytes16(getEncodedCipherSuites());
|
||||
hos.putBytes8(compressionMethod);
|
||||
extensions.send(hos); // In TLS 1.3, use of certain
|
||||
// extensions is mandatory.
|
||||
} catch (IOException ioe) {
|
||||
// unlikely
|
||||
}
|
||||
|
@ -1426,6 +1424,9 @@ final class ClientHello {
|
|||
shc.handshakeProducers.put(SSLHandshake.SERVER_HELLO.id,
|
||||
SSLHandshake.SERVER_HELLO);
|
||||
|
||||
// Reset the ClientHello non-zero offset fragment allowance
|
||||
shc.acceptCliHelloFragments = false;
|
||||
|
||||
//
|
||||
// produce
|
||||
//
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 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
|
||||
|
@ -40,12 +40,23 @@ import sun.security.ssl.SSLCipher.SSLReadCipher;
|
|||
final class DTLSInputRecord extends InputRecord implements DTLSRecord {
|
||||
private DTLSReassembler reassembler = null;
|
||||
private int readEpoch;
|
||||
private SSLContextImpl sslContext;
|
||||
|
||||
DTLSInputRecord(HandshakeHash handshakeHash) {
|
||||
super(handshakeHash, SSLReadCipher.nullDTlsReadCipher());
|
||||
this.readEpoch = 0;
|
||||
}
|
||||
|
||||
// Method to set TransportContext
|
||||
public void setTransportContext(TransportContext tc) {
|
||||
this.tc = tc;
|
||||
}
|
||||
|
||||
// Method to set SSLContext
|
||||
public void setSSLContext(SSLContextImpl sslContext) {
|
||||
this.sslContext = sslContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
void changeReadCiphers(SSLReadCipher readCipher) {
|
||||
this.readCipher = readCipher;
|
||||
|
@ -537,6 +548,27 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn a sufficiently-large initial ClientHello fragment into one that
|
||||
* stops immediately after the compression methods. This is only used
|
||||
* for the initial CH message fragment at offset 0.
|
||||
*
|
||||
* @param srcFrag the fragment actually received by the DTLSReassembler
|
||||
* @param limit the size of the new, cloned/truncated handshake fragment
|
||||
*
|
||||
* @return a truncated handshake fragment that is sized to look like a
|
||||
* complete message, but actually contains only up to the compression
|
||||
* methods (no extensions)
|
||||
*/
|
||||
private static HandshakeFragment truncateChFragment(HandshakeFragment srcFrag,
|
||||
int limit) {
|
||||
return new HandshakeFragment(Arrays.copyOf(srcFrag.fragment, limit),
|
||||
srcFrag.contentType, srcFrag.majorVersion,
|
||||
srcFrag.minorVersion, srcFrag.recordEnS, srcFrag.recordEpoch,
|
||||
srcFrag.recordSeq, srcFrag.handshakeType, limit,
|
||||
srcFrag.messageSeq, srcFrag.fragmentOffset, limit);
|
||||
}
|
||||
|
||||
private static final class HoleDescriptor {
|
||||
int offset; // fragment_offset
|
||||
int limit; // fragment_offset + fragment_length
|
||||
|
@ -640,10 +672,17 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
|
|||
// Queue up a handshake message.
|
||||
void queueUpHandshake(HandshakeFragment hsf) throws SSLProtocolException {
|
||||
if (!isDesirable(hsf)) {
|
||||
// Not a dedired record, discard it.
|
||||
// Not a desired record, discard it.
|
||||
return;
|
||||
}
|
||||
|
||||
if (hsf.handshakeType == SSLHandshake.CLIENT_HELLO.id) {
|
||||
// validate the first or subsequent ClientHello message
|
||||
if ((hsf = valHello(hsf, hsf.messageSeq == 0)) == null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up the retransmission messages if necessary.
|
||||
cleanUpRetransmit(hsf);
|
||||
|
||||
|
@ -769,6 +808,100 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
|
|||
}
|
||||
}
|
||||
|
||||
private HandshakeFragment valHello(HandshakeFragment hsf,
|
||||
boolean firstHello) {
|
||||
ServerHandshakeContext shc =
|
||||
(ServerHandshakeContext) tc.handshakeContext;
|
||||
// Drop any fragment that is not a zero offset until we've received
|
||||
// a second (or possibly later) CH message that passes the cookie
|
||||
// check.
|
||||
if (shc == null || !shc.acceptCliHelloFragments) {
|
||||
if (hsf.fragmentOffset != 0) {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
// Let this fragment through to the DTLSReassembler as-is
|
||||
return hsf;
|
||||
}
|
||||
|
||||
try {
|
||||
ByteBuffer fragmentData = ByteBuffer.wrap(hsf.fragment);
|
||||
|
||||
ProtocolVersion pv = ProtocolVersion.valueOf(
|
||||
Record.getInt16(fragmentData));
|
||||
if (!pv.isDTLS) {
|
||||
return null;
|
||||
}
|
||||
// Read the random (32 bytes)
|
||||
if (fragmentData.remaining() < 32) {
|
||||
if (SSLLogger.isOn && SSLLogger.isOn("verbose")) {
|
||||
SSLLogger.fine("Rejected client hello fragment (bad random len) " +
|
||||
"fo=" + hsf.fragmentOffset + " fl=" + hsf.fragmentLength);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
fragmentData.position(fragmentData.position() + 32);
|
||||
|
||||
// SessionID
|
||||
byte[] sessId = Record.getBytes8(fragmentData);
|
||||
if (sessId.length > 0 &&
|
||||
!SSLConfiguration.enableDtlsResumeCookie) {
|
||||
// If we are in a resumption it is possible that the cookie
|
||||
// exchange will be skipped. This is a server-side setting
|
||||
// and it is NOT the default. If enableDtlsResumeCookie is
|
||||
// false though, then we will buffer fragments since there
|
||||
// is no cookie exchange to execute prior to performing
|
||||
// reassembly.
|
||||
return hsf;
|
||||
}
|
||||
|
||||
// Cookie
|
||||
byte[] cookie = Record.getBytes8(fragmentData);
|
||||
if (firstHello && cookie.length != 0) {
|
||||
if (SSLLogger.isOn && SSLLogger.isOn("verbose")) {
|
||||
SSLLogger.fine("Rejected initial client hello fragment (bad cookie len) " +
|
||||
"fo=" + hsf.fragmentOffset + " fl=" + hsf.fragmentLength);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
// CipherSuites
|
||||
Record.getBytes16(fragmentData);
|
||||
// Compression methods
|
||||
Record.getBytes8(fragmentData);
|
||||
|
||||
// If it's the first fragment, we'll truncate it and push it
|
||||
// through the reassembler.
|
||||
if (firstHello) {
|
||||
return truncateChFragment(hsf, fragmentData.position());
|
||||
} else {
|
||||
HelloCookieManager hcMgr = sslContext.
|
||||
getHelloCookieManager(ProtocolVersion.DTLS10);
|
||||
ByteBuffer msgFragBuf = ByteBuffer.wrap(hsf.fragment, 0,
|
||||
fragmentData.position());
|
||||
ClientHello.ClientHelloMessage chMsg =
|
||||
new ClientHello.ClientHelloMessage(shc, msgFragBuf, null);
|
||||
if (!hcMgr.isCookieValid(shc, chMsg, cookie)) {
|
||||
// Bad cookie check, truncate it and let the ClientHello
|
||||
// consumer recheck, fail and take the appropriate action.
|
||||
return truncateChFragment(hsf, fragmentData.position());
|
||||
} else {
|
||||
// It's a good cookie, return the original handshake
|
||||
// fragment and let it go into the DTLSReassembler like
|
||||
// any other fragment so we can wait for the rest of
|
||||
// the CH message.
|
||||
shc.acceptCliHelloFragments = true;
|
||||
return hsf;
|
||||
}
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
if (SSLLogger.isOn && SSLLogger.isOn("verbose")) {
|
||||
SSLLogger.fine("Rejected client hello fragment " +
|
||||
"fo=" + hsf.fragmentOffset + " fl=" + hsf.fragmentLength);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Queue up a ChangeCipherSpec message
|
||||
void queueUpChangeCipherSpec(RecordFragment rf)
|
||||
throws SSLProtocolException {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 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
|
||||
|
@ -55,6 +55,7 @@ class ServerHandshakeContext extends HandshakeContext {
|
|||
CertificateMessage.CertificateEntry currentCertEntry;
|
||||
private static final long DEFAULT_STATUS_RESP_DELAY = 5000L;
|
||||
final long statusRespTimeout;
|
||||
boolean acceptCliHelloFragments = false;
|
||||
|
||||
|
||||
ServerHandshakeContext(SSLContextImpl sslContext,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 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
|
||||
|
@ -156,6 +156,11 @@ final class TransportContext implements ConnectionContext {
|
|||
|
||||
this.acc = AccessController.getContext();
|
||||
this.consumers = new HashMap<>();
|
||||
|
||||
if (inputRecord instanceof DTLSInputRecord dtlsInputRecord) {
|
||||
dtlsInputRecord.setTransportContext(this);
|
||||
dtlsInputRecord.setSSLContext(this.sslContext);
|
||||
}
|
||||
}
|
||||
|
||||
// Dispatch plaintext to a specific consumer.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue