/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* This class defines a certificate factory for X.509 v3 certificates &
* certification paths, and X.509 v2 certificate revocation lists (CRLs).
*
* @author Jan Luehe
* @author Hemma Prafullchandra
* @author Sean Mullan
*
*
* @see java.security.cert.CertificateFactorySpi
* @see java.security.cert.Certificate
* @see java.security.cert.CertPath
* @see java.security.cert.CRL
* @see java.security.cert.X509Certificate
* @see java.security.cert.X509CRL
* @see sun.security.x509.X509CertImpl
* @see sun.security.x509.X509CRLImpl
*/
/**
* Generates an X.509 certificate object and initializes it with
* the data read from the input stream <code>is</code>.
*
* @param is an input stream with the certificate data.
*
* @return an X.509 certificate object initialized with the data
* from the input stream.
*
* @exception CertificateException on parsing errors.
*/
throws CertificateException
{
// clear the caches (for debugging)
throw new CertificateException("Missing input stream");
}
try {
return cert;
}
return cert;
} else {
throw new IOException("Empty input");
}
} catch (IOException ioe) {
throw (CertificateException)new CertificateException
}
}
/**
* Read from the stream until length bytes have been read or EOF has
* been reached. Return the number of bytes actually read.
*/
int length) throws IOException {
int read = 0;
byte[] buffer = new byte[2048];
while (length > 0) {
if (n <= 0) {
break;
}
read += n;
length -= n;
}
return read;
}
/**
* Return an interned X509CertImpl for the given certificate.
* If the given X509Certificate or X509CertImpl is already present
* in the cert cache, the cached object is returned. Otherwise,
* if it is a X509Certificate, it is first converted to a X509CertImpl.
* Then the X509CertImpl is added to the cache and returned.
*
* Note that all certificates created via generateCertificate(InputStream)
* are already interned and this method does not need to be called.
* It is useful for certificates that cannot be created via
* generateCertificate() and for converting other X509Certificate
* implementations to an X509CertImpl.
*/
throws CertificateException {
if (c == null) {
return null;
}
boolean isImpl = c instanceof X509CertImpl;
byte[] encoding;
if (isImpl) {
} else {
encoding = c.getEncoded();
}
return newC;
}
if (isImpl) {
newC = (X509CertImpl)c;
} else {
}
return newC;
}
/**
* Return an interned X509CRLImpl for the given certificate.
* For more information, see intern(X509Certificate).
*/
throws CRLException {
if (c == null) {
return null;
}
boolean isImpl = c instanceof X509CRLImpl;
byte[] encoding;
if (isImpl) {
} else {
encoding = c.getEncoded();
}
return newC;
}
if (isImpl) {
newC = (X509CRLImpl)c;
} else {
}
return newC;
}
/**
* Get the X509CertImpl or X509CRLImpl from the cache.
*/
byte[] encoding) {
return value;
}
/**
* Add the X509CertImpl or X509CRLImpl to the cache.
*/
return;
}
}
/**
* Generates a <code>CertPath</code> object and initializes it with
* the data read from the <code>InputStream</code> inStream. The data
* is assumed to be in the default encoding.
*
* @param inStream an <code>InputStream</code> containing the data
* @return a <code>CertPath</code> initialized with the data from the
* <code>InputStream</code>
* @exception CertificateException if an exception occurs while decoding
* @since 1.4
*/
throws CertificateException
{
throw new CertificateException("Missing input stream");
}
try {
} else {
throw new IOException("Empty input");
}
} catch (IOException ioe) {
}
}
/**
* Generates a <code>CertPath</code> object and initializes it with
* the data read from the <code>InputStream</code> inStream. The data
* is assumed to be in the specified encoding.
*
* @param inStream an <code>InputStream</code> containing the data
* @param encoding the encoding used for the data
* @return a <code>CertPath</code> initialized with the data from the
* <code>InputStream</code>
* @exception CertificateException if an exception occurs while decoding or
* the encoding requested is not supported
* @since 1.4
*/
{
throw new CertificateException("Missing input stream");
}
try {
} else {
throw new IOException("Empty input");
}
} catch (IOException ioe) {
}
}
/**
* Generates a <code>CertPath</code> object and initializes it with
* a <code>List</code> of <code>Certificate</code>s.
* <p>
* The certificates supplied must be of a type supported by the
* <code>CertificateFactory</code>. They will be copied out of the supplied
* <code>List</code> object.
*
* @param certificates a <code>List</code> of <code>Certificate</code>s
* @return a <code>CertPath</code> initialized with the supplied list of
* certificates
* @exception CertificateException if an exception occurs
* @since 1.4
*/
public CertPath
throws CertificateException
{
return(new X509CertPath(certificates));
}
/**
* Returns an iteration of the <code>CertPath</code> encodings supported
* by this certificate factory, with the default encoding first.
* <p>
* Attempts to modify the returned <code>Iterator</code> via its
* <code>remove</code> method result in an
* <code>UnsupportedOperationException</code>.
*
* @return an <code>Iterator</code> over the names of the supported
* <code>CertPath</code> encodings (as <code>String</code>s)
* @since 1.4
*/
return(X509CertPath.getEncodingsStatic());
}
/**
* Returns a (possibly empty) collection view of X.509 certificates read
* from the given input stream <code>is</code>.
*
* @param is the input stream with the certificates.
*
* @return a (possibly empty) collection view of X.509 certificate objects
* initialized with the data from the input stream.
*
* @exception CertificateException on parsing errors.
*/
throws CertificateException {
throw new CertificateException("Missing input stream");
}
try {
return parseX509orPKCS7Cert(is);
} catch (IOException ioe) {
throw new CertificateException(ioe);
}
}
/**
* Generates an X.509 certificate revocation list (CRL) object and
* initializes it with the data read from the given input stream
* <code>is</code>.
*
* @param is an input stream with the CRL data.
*
* @return an X.509 CRL object initialized with the data
* from the input stream.
*
* @exception CRLException on parsing errors.
*/
throws CRLException
{
// clear the cache (for debugging)
throw new CRLException("Missing input stream");
}
try {
return crl;
}
return crl;
} else {
throw new IOException("Empty input");
}
} catch (IOException ioe) {
}
}
/**
* Returns a (possibly empty) collection view of X.509 CRLs read
* from the given input stream <code>is</code>.
*
* @param is the input stream with the CRLs.
*
* @return a (possibly empty) collection view of X.509 CRL objects
* initialized with the data from the input stream.
*
* @exception CRLException on parsing errors.
*/
{
throw new CRLException("Missing input stream");
}
try {
return parseX509orPKCS7CRL(is);
} catch (IOException ioe) {
}
}
/*
* Parses the data in the given input stream as a sequence of DER
* encoded X.509 certificates (in binary or base 64 encoded format) OR
* as a single PKCS#7 encoded blob (in binary or base64 encoded format).
*/
throws CertificateException, IOException
{
return new ArrayList<>(0);
}
try {
// certs are optional in PKCS #7
} else {
// no crls provided
return new ArrayList<>(0);
}
} catch (ParsingException e) {
}
}
return coll;
}
/*
* Parses the data in the given input stream as a sequence of DER encoded
* X.509 CRLs (in binary or base 64 encoded format) OR as a single PKCS#7
* encoded blob (in binary or base 64 encoded format).
*/
throws CRLException, IOException
{
return new ArrayList<>(0);
}
try {
// CRLs are optional in PKCS #7
} else {
// no crls provided
return new ArrayList<>(0);
}
} catch (ParsingException e) {
}
}
return coll;
}
/**
* Returns an ASN.1 SEQUENCE from a stream, which might be a BER-encoded
* binary block or a PEM-style BASE64-encoded ASCII data. In the latter
* case, it's de-BASE64'ed before return.
*
* After the reading, the input stream pointer is after the BER block, or
* after the newline character after the -----END SOMETHING----- line.
*
* @param is the InputStream
* @returns byte block or null if end of stream
* @throws IOException If any parsing error
*/
// The first character of a BLOCK.
if (c == -1) {
return null;
}
if (c == DerValue.tag_Sequence) {
return bout.toByteArray();
} else {
// Read BASE64 encoded data, might skip info at the beginning
char[] data = new char[2048];
int pos = 0;
// Step 1: Read until header is found
while (true) {
if (next == -1) {
// We accept useless data after the last block,
// say, empty lines.
return null;
}
if (next == '-') {
hyphen++;
} else {
hyphen = 0;
}
break;
}
}
// Step 2: Read the rest of header, determine the line end
int end;
while (true) {
if (next == -1) {
throw new IOException("Incomplete data");
}
if (next == '\n') {
end = '\n';
break;
}
if (next == '\r') {
if (next == -1) {
throw new IOException("Incomplete data");
}
if (next == '\n') {
end = '\n';
} else {
end = '\r';
}
break;
}
}
// Step 3: Read the data
while (true) {
if (next == -1) {
throw new IOException("Incomplete data");
}
if (next != '-') {
}
} else {
break;
}
}
// Step 4: Consume the footer
while (true) {
// Add next == '\n' for maximum safety, in case endline
// is not consistent.
break;
}
}
}
}
}
}
throw new IOException("Header and footer do not match: " +
}
}
/**
* Read one BER data block. This method is aware of indefinite-length BER
* encoding and will read all of the sub-sections in a recursive way
*
* @param is Read from this InputStream
* @param bout Write into this OutputStream
* @param tag Tag already read (-1 mean not read)
* @returns The current tag, used to check EOC in indefinite-length BER
* @throws IOException Any parsing error
*/
if (tag == -1) {
throw new IOException("BER/DER tag info absent");
}
throw new IOException("Multi octets tag not supported");
}
}
if (n == -1) {
throw new IOException("BER/DER length info ansent");
}
int length;
if (n == 0x80) { // Indefinite-length encoding
throw new IOException(
"Non constructed encoding must have definite length");
}
while (true) {
break;
}
}
} else {
if (n < 0x80) {
length = n;
} else if (n == 0x81) {
if (length == -1) {
throw new IOException("Incomplete BER/DER length info");
}
} else if (n == 0x82) {
if (lowByte == -1) {
throw new IOException("Incomplete BER/DER length info");
}
} else if (n == 0x83) {
if (lowByte == -1) {
throw new IOException("Incomplete BER/DER length info");
}
} else if (n == 0x84) {
if (lowByte == -1) {
throw new IOException("Incomplete BER/DER length info");
}
if (highByte > 127) {
throw new IOException("Invalid BER/DER data (a little huge?)");
}
} else { // ignore longer length forms
throw new IOException("Invalid BER/DER data (too huge?)");
}
throw new IOException("Incomplete BER/DER data");
}
}
return tag;
}
}