blob: aab89087fc8064f8beead1c0f4fbd866666ec9d1 [file] [log] [blame]
package org.bouncycastle.crypto.tls;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Vector;
/*
* RFC 3546 3.3
*/
public class CertificateURL
{
protected short type;
protected Vector urlAndHashList;
/**
* @param type
* see {@link CertChainType} for valid constants.
* @param urlAndHashList
* a {@link Vector} of {@link URLAndHash}.
*/
public CertificateURL(short type, Vector urlAndHashList)
{
if (!CertChainType.isValid(type))
{
throw new IllegalArgumentException("'type' is not a valid CertChainType value");
}
if (urlAndHashList == null || urlAndHashList.isEmpty())
{
throw new IllegalArgumentException("'urlAndHashList' must have length > 0");
}
this.type = type;
this.urlAndHashList = urlAndHashList;
}
/**
* @return {@link CertChainType}
*/
public short getType()
{
return type;
}
/**
* @return a {@link Vector} of {@link URLAndHash}
*/
public Vector getURLAndHashList()
{
return urlAndHashList;
}
/**
* Encode this {@link CertificateURL} to an {@link OutputStream}.
*
* @param output the {@link OutputStream} to encode to.
* @throws IOException
*/
public void encode(OutputStream output)
throws IOException
{
TlsUtils.writeUint8(this.type, output);
ListBuffer16 buf = new ListBuffer16();
for (int i = 0; i < this.urlAndHashList.size(); ++i)
{
URLAndHash urlAndHash = (URLAndHash)this.urlAndHashList.elementAt(i);
urlAndHash.encode(buf);
}
buf.encodeTo(output);
}
/**
* Parse a {@link CertificateURL} from an {@link InputStream}.
*
* @param context
* the {@link TlsContext} of the current connection.
* @param input
* the {@link InputStream} to parse from.
* @return a {@link CertificateURL} object.
* @throws IOException
*/
public static CertificateURL parse(TlsContext context, InputStream input)
throws IOException
{
short type = TlsUtils.readUint8(input);
if (!CertChainType.isValid(type))
{
throw new TlsFatalAlert(AlertDescription.decode_error);
}
int totalLength = TlsUtils.readUint16(input);
if (totalLength < 1)
{
throw new TlsFatalAlert(AlertDescription.decode_error);
}
byte[] urlAndHashListData = TlsUtils.readFully(totalLength, input);
ByteArrayInputStream buf = new ByteArrayInputStream(urlAndHashListData);
Vector url_and_hash_list = new Vector();
while (buf.available() > 0)
{
URLAndHash url_and_hash = URLAndHash.parse(context, buf);
url_and_hash_list.addElement(url_and_hash);
}
return new CertificateURL(type, url_and_hash_list);
}
// TODO Could be more generally useful
class ListBuffer16 extends ByteArrayOutputStream
{
ListBuffer16() throws IOException
{
// Reserve space for length
TlsUtils.writeUint16(0, this);
}
void encodeTo(OutputStream output) throws IOException
{
// Patch actual length back in
int length = count - 2;
TlsUtils.checkUint16(length);
TlsUtils.writeUint16(length, buf, 0);
output.write(buf, 0, count);
buf = null;
}
}
}