// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program 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 for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package netscape.security.x509; import java.io.IOException; import java.io.Serializable; import netscape.security.util.DerInputStream; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; import netscape.security.util.ObjectIdentifier; /** * Represent a X509 Extension Attribute. * *

* Extensions are addiitonal attributes which can be inserted in a X509 v3 certificate. For example a * "Driving License Certificate" could have the driving license number as a extension. * *

* Extensions are represented as a sequence of the extension identifier (Object Identifier), a boolean flag stating * whether the extension is to be treated as being critical and the extension value itself (this is again a DER encoding * of the extension value). * *

 * ASN.1 definition of Extension:
 * Extension ::= SEQUENCE {
 * ExtensionId	OBJECT IDENTIFIER,
 * critical	BOOLEAN DEFAULT FALSE,
 * extensionValue	OCTET STRING
 * }
 * 
* * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.9 */ public class Extension implements Serializable { /** * */ private static final long serialVersionUID = -643549610716024753L; protected ObjectIdentifier extensionId = null; protected boolean critical = false; protected byte[] extensionValue = null; /** * Default constructor. Used only by sub-classes. */ public Extension() { } /** * Constructs an extension from a DER encoded array of bytes. */ public Extension(DerValue derVal) throws IOException { DerInputStream in = derVal.toDerInputStream(); // Object identifier extensionId = in.getOID(); // If the criticality flag was false, it will not have been encoded. DerValue val = in.getDerValue(); if (val.tag == DerValue.tag_Boolean) { critical = val.getBoolean(); // Extension value (DER encoded) val = in.getDerValue(); extensionValue = val.getOctetString(); } else { critical = false; extensionValue = val.getOctetString(); } } /** * Constructs an Extension from individual components of ObjectIdentifier, * criticality and the DER encoded OctetString. * * @param extensionId the ObjectIdentifier of the extension * @param critical the boolean indicating if the extension is critical * @param extensionValue the DER encoded octet string of the value. */ public Extension(ObjectIdentifier extensionId, boolean critical, byte[] extensionValue) throws IOException { this.extensionId = extensionId; this.critical = critical; // passed in a DER encoded octet string, strip off the tag // and length DerValue inDerVal = new DerValue(extensionValue); this.extensionValue = inDerVal.getOctetString(); } /** * Constructs an Extension from another extension. To be used for * creating decoded subclasses. * * @param ext the extension to create from. */ public Extension(Extension ext) { this.extensionId = ext.extensionId; this.critical = ext.critical; this.extensionValue = ext.extensionValue; } /** * Write the extension to the DerOutputStream. * * @param out the DerOutputStream to write the extension to. * @exception IOException on encoding errors */ public void encode(DerOutputStream out) throws IOException { DerOutputStream bytes = new DerOutputStream(); if (extensionId == null) throw new IOException("Null OID to encode for the extension!"); bytes.putOID(extensionId); if (critical) bytes.putBoolean(critical); if (extensionValue != null) bytes.putOctetString(extensionValue); out.write(DerValue.tag_Sequence, bytes); } /** * Returns true if extension is critical. */ public boolean isCritical() { return (critical); } public void setCritical(boolean c) { critical = c; } public void clearValue() { extensionValue = null; } /** * Returns the ObjectIdentifier of the extension. */ public ObjectIdentifier getExtensionId() { return (extensionId); } public void setExtensionId(ObjectIdentifier oid) { extensionId = oid; } /** * Returns the extension value as an byte array for further processing. * Note, this is the raw DER value of the extension, not the DER * encoded octet string which is in the certificate. */ public byte[] getExtensionValue() { if (extensionValue == null) return null; byte[] dup = new byte[extensionValue.length]; System.arraycopy(extensionValue, 0, dup, 0, dup.length); return dup; } public void setExtensionValue(byte value[]) { extensionValue = value; } /** * Returns the Extension in user readable form. */ public String toString() { String s = "ObjectId: " + extensionId.toString(); if (critical) { s += " Criticality=true\n"; } else { s += " Criticality=false\n"; } return (s); } }