Path: blob/master/src/java.base/share/classes/sun/security/x509/ExtendedKeyUsageExtension.java
41159 views
/*1* Copyright (c) 2000, 2020, 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.ArrayList;30import java.util.Enumeration;31import java.util.HashMap;32import java.util.List;33import java.util.Map;34import java.util.Vector;3536import sun.security.util.*;3738/**39* This class defines the Extended Key Usage Extension, which40* indicates one or more purposes for which the certified public key41* may be used, in addition to or in place of the basic purposes42* indicated in the key usage extension field. This field is defined43* as follows:<p>44*45* id-ce-extKeyUsage OBJECT IDENTIFIER ::= {id-ce 37}<p>46*47* ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId<p>48*49* KeyPurposeId ::= OBJECT IDENTIFIER<p>50*51* Key purposes may be defined by any organization with a need. Object52* identifiers used to identify key purposes shall be assigned in53* accordance with IANA or ITU-T Rec. X.660 | ISO/IEC/ITU 9834-1.<p>54*55* This extension may, at the option of the certificate issuer, be56* either critical or non-critical.<p>57*58* If the extension is flagged critical, then the certificate MUST be59* used only for one of the purposes indicated.<p>60*61* If the extension is flagged non-critical, then it indicates the62* intended purpose or purposes of the key, and may be used in finding63* the correct key/certificate of an entity that has multiple64* keys/certificates. It is an advisory field and does not imply that65* usage of the key is restricted by the certification authority to66* the purpose indicated. Certificate using applications may67* nevertheless require that a particular purpose be indicated in68* order for the certificate to be acceptable to that application.<p>69*70* If a certificate contains both a critical key usage field and a71* critical extended key usage field, then both fields MUST be72* processed independently and the certificate MUST only be used for a73* purpose consistent with both fields. If there is no purpose74* consistent with both fields, then the certificate MUST NOT be used75* for any purpose.76*77* @since 1.478*/79public class ExtendedKeyUsageExtension extends Extension80implements CertAttrSet<String> {8182/**83* Identifier for this attribute, to be used with the84* get, set, delete methods of Certificate, x509 type.85*/86public static final String IDENT = "x509.info.extensions.ExtendedKeyUsage";8788/**89* Attribute names.90*/91public static final String NAME = "ExtendedKeyUsage";92public static final String USAGES = "usages";9394/**95* Vector of KeyUsages for this object.96*/97private Vector<ObjectIdentifier> keyUsages;9899// Encode this extension value.100private void encodeThis() throws IOException {101if (keyUsages == null || keyUsages.isEmpty()) {102this.extensionValue = null;103return;104}105DerOutputStream os = new DerOutputStream();106DerOutputStream tmp = new DerOutputStream();107108for (int i = 0; i < keyUsages.size(); i++) {109tmp.putOID(keyUsages.elementAt(i));110}111112os.write(DerValue.tag_Sequence, tmp);113this.extensionValue = os.toByteArray();114}115116/**117* Create a ExtendedKeyUsageExtension object from118* a Vector of Key Usages; the criticality is set to false.119*120* @param keyUsages the Vector of KeyUsages (ObjectIdentifiers)121*/122public ExtendedKeyUsageExtension(Vector<ObjectIdentifier> keyUsages)123throws IOException {124this(Boolean.FALSE, keyUsages);125}126127/**128* Create a ExtendedKeyUsageExtension object from129* a Vector of KeyUsages with specified criticality.130*131* @param critical true if the extension is to be treated as critical.132* @param keyUsages the Vector of KeyUsages (ObjectIdentifiers)133*/134public ExtendedKeyUsageExtension(Boolean critical, Vector<ObjectIdentifier> keyUsages)135throws IOException {136this.keyUsages = keyUsages;137this.extensionId = PKIXExtensions.ExtendedKeyUsage_Id;138this.critical = critical.booleanValue();139encodeThis();140}141142/**143* Create the extension from its DER encoded value and criticality.144*145* @param critical true if the extension is to be treated as critical.146* @param value an array of DER encoded bytes of the actual value.147* @exception ClassCastException if value is not an array of bytes148* @exception IOException on error.149*/150public ExtendedKeyUsageExtension(Boolean critical, Object value)151throws IOException {152this.extensionId = PKIXExtensions.ExtendedKeyUsage_Id;153this.critical = critical.booleanValue();154this.extensionValue = (byte[]) value;155DerValue val = new DerValue(this.extensionValue);156if (val.tag != DerValue.tag_Sequence) {157throw new IOException("Invalid encoding for " +158"ExtendedKeyUsageExtension.");159}160keyUsages = new Vector<ObjectIdentifier>();161while (val.data.available() != 0) {162DerValue seq = val.data.getDerValue();163ObjectIdentifier usage = seq.getOID();164keyUsages.addElement(usage);165}166}167168/**169* Return the extension as user readable string.170*/171public String toString() {172if (keyUsages == null) return "";173String usage = " ";174boolean first = true;175for (ObjectIdentifier oid: keyUsages) {176if(!first) {177usage += "\n ";178}179180String res = oid.toString();181KnownOIDs os = KnownOIDs.findMatch(res);182if (os != null) {183usage += os.stdName();184} else {185usage += res;186}187first = false;188}189return super.toString() + "ExtendedKeyUsages [\n"190+ usage + "\n]\n";191}192193/**194* Write the extension to the DerOutputStream.195*196* @param out the DerOutputStream to write the extension to.197* @exception IOException on encoding errors.198*/199public void encode(OutputStream out) throws IOException {200DerOutputStream tmp = new DerOutputStream();201if (extensionValue == null) {202extensionId = PKIXExtensions.ExtendedKeyUsage_Id;203critical = false;204encodeThis();205}206super.encode(tmp);207out.write(tmp.toByteArray());208}209210/**211* Set the attribute value.212*/213@SuppressWarnings("unchecked") // Checked with instanceof214public void set(String name, Object obj) throws IOException {215if (name.equalsIgnoreCase(USAGES)) {216if (!(obj instanceof Vector)) {217throw new IOException("Attribute value should be of type Vector.");218}219this.keyUsages = (Vector<ObjectIdentifier>)obj;220} else {221throw new IOException("Attribute name [" + name +222"] not recognized by " +223"CertAttrSet:ExtendedKeyUsageExtension.");224}225encodeThis();226}227228/**229* Get the attribute value.230*/231public Vector<ObjectIdentifier> get(String name) throws IOException {232if (name.equalsIgnoreCase(USAGES)) {233//XXXX May want to consider cloning this234return keyUsages;235} else {236throw new IOException("Attribute name [" + name +237"] not recognized by " +238"CertAttrSet:ExtendedKeyUsageExtension.");239}240}241242/**243* Delete the attribute value.244*/245public void delete(String name) throws IOException {246if (name.equalsIgnoreCase(USAGES)) {247keyUsages = null;248} else {249throw new IOException("Attribute name [" + name +250"] not recognized by " +251"CertAttrSet:ExtendedKeyUsageExtension.");252}253encodeThis();254}255256/**257* Return an enumeration of names of attributes existing within this258* attribute.259*/260public Enumeration<String> getElements() {261AttributeNameEnumeration elements = new AttributeNameEnumeration();262elements.addElement(USAGES);263264return (elements.elements());265}266267/**268* Return the name of this attribute.269*/270public String getName() {271return (NAME);272}273274public List<String> getExtendedKeyUsage() {275List<String> al = new ArrayList<String>(keyUsages.size());276for (ObjectIdentifier oid : keyUsages) {277al.add(oid.toString());278}279return al;280}281282}283284285