package gnu.java.security.x509.ext;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import gnu.java.security.OID;
import gnu.java.security.der.DER;
import gnu.java.security.der.DERReader;
import gnu.java.security.der.DERValue;
import gnu.java.security.x509.Util;
public class Extension
{
private static final boolean DEBUG = false;
private static void debug(String msg)
{
System.err.print(">> Extension: ");
System.err.println(msg);
}
protected final OID oid;
protected final boolean critical;
protected boolean isSupported;
protected final Value value;
protected byte[] encoded;
public Extension(byte[] encoded) throws IOException
{
this.encoded = (byte[]) encoded.clone();
DERReader der = new DERReader(encoded);
DERValue val = der.read();
if (DEBUG) debug("read val tag == " + val.getTag() + " len == " + val.getLength());
if (!val.isConstructed())
throw new IOException("malformed Extension");
val = der.read();
if (val.getTag() != DER.OBJECT_IDENTIFIER)
throw new IOException("expecting OBJECT IDENTIFIER");
oid = (OID) val.getValue();
if (DEBUG) debug("read oid == " + oid);
val = der.read();
if (val.getTag() == DER.BOOLEAN)
{
critical = ((Boolean) val.getValue()).booleanValue();
val = der.read();
}
else
critical = false;
if (DEBUG) debug("is critical == " + critical);
if (val.getTag() != DER.OCTET_STRING)
throw new IOException("expecting OCTET STRING");
byte[] encval = (byte[]) val.getValue();
isSupported = true;
if (oid.equals(AuthorityKeyIdentifier.ID))
{
value = new AuthorityKeyIdentifier(encval);
}
else if (oid.equals(SubjectKeyIdentifier.ID))
{
value = new SubjectKeyIdentifier(encval);
}
else if (oid.equals(KeyUsage.ID))
{
value = new KeyUsage(encval);
}
else if (oid.equals(PrivateKeyUsagePeriod.ID))
{
value = new PrivateKeyUsagePeriod(encval);
}
else if (oid.equals(CertificatePolicies.ID))
{
value = new CertificatePolicies(encval);
}
else if (oid.equals (PolicyConstraint.ID))
{
value = new PolicyConstraint (encval);
}
else if (oid.equals(PolicyMappings.ID))
{
value = new PolicyMappings(encval);
}
else if (oid.equals(SubjectAlternativeNames.ID))
{
value = new SubjectAlternativeNames(encval);
}
else if (oid.equals(IssuerAlternativeNames.ID))
{
value = new IssuerAlternativeNames(encval);
}
else if (oid.equals(BasicConstraints.ID))
{
value = new BasicConstraints(encval);
}
else if (oid.equals(ExtendedKeyUsage.ID))
{
value = new ExtendedKeyUsage(encval);
}
else if (oid.equals(CRLNumber.ID))
{
value = new CRLNumber(encval);
}
else if (oid.equals(ReasonCode.ID))
{
value = new ReasonCode(encval);
}
else
{
value = new Value(encval);
isSupported = false;
}
if (DEBUG) debug("read value == " + value);
}
public Extension (final OID oid, final Value value, final boolean critical)
{
this.oid = oid;
this.value = value;
this.critical = critical;
isSupported = true;
}
public OID getOid()
{
return oid;
}
public boolean isCritical()
{
return critical;
}
public boolean isSupported()
{
return isSupported;
}
public Value getValue()
{
return value;
}
public byte[] getEncoded()
{
if (encoded == null)
encode();
return (byte[]) encoded.clone();
}
public String toString()
{
return Extension.class.getName() + " [ id=" + oid + " critical=" +
critical + " value=" + value + " ]";
}
public DERValue getDerValue()
{
List ext = new ArrayList (3);
ext.add (new DERValue (DER.OBJECT_IDENTIFIER, oid));
ext.add (new DERValue (DER.BOOLEAN, new Boolean (critical)));
ext.add (new DERValue (DER.OCTET_STRING, value.getEncoded()));
return new DERValue (DER.CONSTRUCTED|DER.SEQUENCE, ext);
}
private void encode()
{
encoded = getDerValue().getEncoded();
}
public static class Value
{
protected byte[] encoded;
public Value(byte[] encoded)
{
this.encoded = (byte[]) encoded.clone();
}
protected Value() { }
public byte[] getEncoded()
{
return (byte[]) encoded;
}
public boolean equals(Object o)
{
if (!(o instanceof Value))
return false;
return Arrays.equals(encoded, ((Value) o).encoded);
}
public String toString()
{
return Util.toHexString(encoded, ':');
}
}
}