Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/x509/AuthorityKeyIdentifierExtension.java
38831 views
/*1* Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.security.x509;2627import java.io.IOException;28import java.io.OutputStream;29import java.util.Enumeration;3031import sun.security.util.*;3233/**34* This class represents the Authority Key Identifier Extension.35*36* <p>The authority key identifier extension provides a means of37* identifying the particular public key used to sign a certificate.38* This extension would be used where an issuer has multiple signing39* keys (either due to multiple concurrent key pairs or due to40* changeover).41* <p>42* The ASN.1 syntax for this is:43* <pre>44* AuthorityKeyIdentifier ::= SEQUENCE {45* keyIdentifier [0] KeyIdentifier OPTIONAL,46* authorityCertIssuer [1] GeneralNames OPTIONAL,47* authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL48* }49* KeyIdentifier ::= OCTET STRING50* </pre>51* @author Amit Kapoor52* @author Hemma Prafullchandra53* @see Extension54* @see CertAttrSet55*/56public class AuthorityKeyIdentifierExtension extends Extension57implements CertAttrSet<String> {58/**59* Identifier for this attribute, to be used with the60* get, set, delete methods of Certificate, x509 type.61*/62public static final String IDENT =63"x509.info.extensions.AuthorityKeyIdentifier";64/**65* Attribute names.66*/67public static final String NAME = "AuthorityKeyIdentifier";68public static final String KEY_ID = "key_id";69public static final String AUTH_NAME = "auth_name";70public static final String SERIAL_NUMBER = "serial_number";7172// Private data members73private static final byte TAG_ID = 0;74private static final byte TAG_NAMES = 1;75private static final byte TAG_SERIAL_NUM = 2;7677private KeyIdentifier id = null;78private GeneralNames names = null;79private SerialNumber serialNum = null;8081// Encode only the extension value82private void encodeThis() throws IOException {83if (id == null && names == null && serialNum == null) {84this.extensionValue = null;85return;86}87DerOutputStream seq = new DerOutputStream();88DerOutputStream tmp = new DerOutputStream();89if (id != null) {90DerOutputStream tmp1 = new DerOutputStream();91id.encode(tmp1);92tmp.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT,93false, TAG_ID), tmp1);94}95try {96if (names != null) {97DerOutputStream tmp1 = new DerOutputStream();98names.encode(tmp1);99tmp.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT,100true, TAG_NAMES), tmp1);101}102} catch (Exception e) {103throw new IOException(e.toString());104}105if (serialNum != null) {106DerOutputStream tmp1 = new DerOutputStream();107serialNum.encode(tmp1);108tmp.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT,109false, TAG_SERIAL_NUM), tmp1);110}111seq.write(DerValue.tag_Sequence, tmp);112this.extensionValue = seq.toByteArray();113}114115/**116* The default constructor for this extension. Null parameters make117* the element optional (not present).118*119* @param id the KeyIdentifier associated with this extension.120* @param names the GeneralNames associated with this extension121* @param serialNum the CertificateSerialNumber associated with122* this extension.123* @exception IOException on error.124*/125public AuthorityKeyIdentifierExtension(KeyIdentifier kid, GeneralNames name,126SerialNumber sn)127throws IOException {128this.id = kid;129this.names = name;130this.serialNum = sn;131132this.extensionId = PKIXExtensions.AuthorityKey_Id;133this.critical = false;134encodeThis();135}136137/**138* Create the extension from the passed DER encoded value of the same.139*140* @param critical true if the extension is to be treated as critical.141* @param value an array of DER encoded bytes of the actual value.142* @exception ClassCastException if value is not an array of bytes143* @exception IOException on error.144*/145public AuthorityKeyIdentifierExtension(Boolean critical, Object value)146throws IOException {147this.extensionId = PKIXExtensions.AuthorityKey_Id;148this.critical = critical.booleanValue();149150this.extensionValue = (byte[]) value;151DerValue val = new DerValue(this.extensionValue);152if (val.tag != DerValue.tag_Sequence) {153throw new IOException("Invalid encoding for " +154"AuthorityKeyIdentifierExtension.");155}156157// Note that all the fields in AuthorityKeyIdentifier are defined as158// being OPTIONAL, i.e., there could be an empty SEQUENCE, resulting159// in val.data being null.160while ((val.data != null) && (val.data.available() != 0)) {161DerValue opt = val.data.getDerValue();162163// NB. this is always encoded with the IMPLICIT tag164// The checks only make sense if we assume implicit tagging,165// with explicit tagging the form is always constructed.166if (opt.isContextSpecific(TAG_ID) && !opt.isConstructed()) {167if (id != null)168throw new IOException("Duplicate KeyIdentifier in " +169"AuthorityKeyIdentifier.");170opt.resetTag(DerValue.tag_OctetString);171id = new KeyIdentifier(opt);172173} else if (opt.isContextSpecific(TAG_NAMES) &&174opt.isConstructed()) {175if (names != null)176throw new IOException("Duplicate GeneralNames in " +177"AuthorityKeyIdentifier.");178opt.resetTag(DerValue.tag_Sequence);179names = new GeneralNames(opt);180181} else if (opt.isContextSpecific(TAG_SERIAL_NUM) &&182!opt.isConstructed()) {183if (serialNum != null)184throw new IOException("Duplicate SerialNumber in " +185"AuthorityKeyIdentifier.");186opt.resetTag(DerValue.tag_Integer);187serialNum = new SerialNumber(opt);188} else189throw new IOException("Invalid encoding of " +190"AuthorityKeyIdentifierExtension.");191}192}193194/**195* Return the object as a string.196*/197public String toString() {198String s = super.toString() + "AuthorityKeyIdentifier [\n";199if (id != null) {200s += id.toString(); // id already has a newline201}202if (names != null) {203s += names.toString() + "\n";204}205if (serialNum != null) {206s += serialNum.toString() + "\n";207}208return (s + "]\n");209}210211/**212* Write the extension to the OutputStream.213*214* @param out the OutputStream to write the extension to.215* @exception IOException on error.216*/217public void encode(OutputStream out) throws IOException {218DerOutputStream tmp = new DerOutputStream();219if (this.extensionValue == null) {220extensionId = PKIXExtensions.AuthorityKey_Id;221critical = false;222encodeThis();223}224super.encode(tmp);225out.write(tmp.toByteArray());226}227228/**229* Set the attribute value.230*/231public void set(String name, Object obj) throws IOException {232if (name.equalsIgnoreCase(KEY_ID)) {233if (!(obj instanceof KeyIdentifier)) {234throw new IOException("Attribute value should be of " +235"type KeyIdentifier.");236}237id = (KeyIdentifier)obj;238} else if (name.equalsIgnoreCase(AUTH_NAME)) {239if (!(obj instanceof GeneralNames)) {240throw new IOException("Attribute value should be of " +241"type GeneralNames.");242}243names = (GeneralNames)obj;244} else if (name.equalsIgnoreCase(SERIAL_NUMBER)) {245if (!(obj instanceof SerialNumber)) {246throw new IOException("Attribute value should be of " +247"type SerialNumber.");248}249serialNum = (SerialNumber)obj;250} else {251throw new IOException("Attribute name not recognized by " +252"CertAttrSet:AuthorityKeyIdentifier.");253}254encodeThis();255}256257/**258* Get the attribute value.259*/260public Object get(String name) throws IOException {261if (name.equalsIgnoreCase(KEY_ID)) {262return (id);263} else if (name.equalsIgnoreCase(AUTH_NAME)) {264return (names);265} else if (name.equalsIgnoreCase(SERIAL_NUMBER)) {266return (serialNum);267} else {268throw new IOException("Attribute name not recognized by " +269"CertAttrSet:AuthorityKeyIdentifier.");270}271}272273/**274* Delete the attribute value.275*/276public void delete(String name) throws IOException {277if (name.equalsIgnoreCase(KEY_ID)) {278id = null;279} else if (name.equalsIgnoreCase(AUTH_NAME)) {280names = null;281} else if (name.equalsIgnoreCase(SERIAL_NUMBER)) {282serialNum = null;283} else {284throw new IOException("Attribute name not recognized by " +285"CertAttrSet:AuthorityKeyIdentifier.");286}287encodeThis();288}289290/**291* Return an enumeration of names of attributes existing within this292* attribute.293*/294public Enumeration<String> getElements() {295AttributeNameEnumeration elements = new AttributeNameEnumeration();296elements.addElement(KEY_ID);297elements.addElement(AUTH_NAME);298elements.addElement(SERIAL_NUMBER);299300return (elements.elements());301}302303/**304* Return the name of this attribute.305*/306public String getName() {307return (NAME);308}309310/**311* Return the encoded key identifier, or null if not specified.312*/313public byte[] getEncodedKeyIdentifier() throws IOException {314if (id != null) {315DerOutputStream derOut = new DerOutputStream();316id.encode(derOut);317return derOut.toByteArray();318}319return null;320}321}322323324