Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/x509/ExtendedKeyUsageExtension.java
38831 views
/*1* Copyright (c) 2000, 2014, 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.DerValue;37import sun.security.util.DerOutputStream;38import sun.security.util.ObjectIdentifier;3940/**41* This class defines the Extended Key Usage Extension, which42* indicates one or more purposes for which the certified public key43* may be used, in addition to or in place of the basic purposes44* indicated in the key usage extension field. This field is defined45* as follows:<p>46*47* id-ce-extKeyUsage OBJECT IDENTIFIER ::= {id-ce 37}<p>48*49* ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId<p>50*51* KeyPurposeId ::= OBJECT IDENTIFIER<p>52*53* Key purposes may be defined by any organization with a need. Object54* identifiers used to identify key purposes shall be assigned in55* accordance with IANA or ITU-T Rec. X.660 | ISO/IEC/ITU 9834-1.<p>56*57* This extension may, at the option of the certificate issuer, be58* either critical or non-critical.<p>59*60* If the extension is flagged critical, then the certificate MUST be61* used only for one of the purposes indicated.<p>62*63* If the extension is flagged non-critical, then it indicates the64* intended purpose or purposes of the key, and may be used in finding65* the correct key/certificate of an entity that has multiple66* keys/certificates. It is an advisory field and does not imply that67* usage of the key is restricted by the certification authority to68* the purpose indicated. Certificate using applications may69* nevertheless require that a particular purpose be indicated in70* order for the certificate to be acceptable to that application.<p>7172* If a certificate contains both a critical key usage field and a73* critical extended key usage field, then both fields MUST be74* processed independently and the certificate MUST only be used for a75* purpose consistent with both fields. If there is no purpose76* consistent with both fields, then the certificate MUST NOT be used77* for any purpose.<p>78*79* @since 1.480*/81public class ExtendedKeyUsageExtension extends Extension82implements CertAttrSet<String> {8384/**85* Identifier for this attribute, to be used with the86* get, set, delete methods of Certificate, x509 type.87*/88public static final String IDENT = "x509.info.extensions.ExtendedKeyUsage";8990/**91* Attribute names.92*/93public static final String NAME = "ExtendedKeyUsage";94public static final String USAGES = "usages";9596// OID defined in RFC 5280 Sections 4.2.1.1297// more from http://www.alvestrand.no/objectid/1.3.6.1.5.5.7.3.html98private static final Map <ObjectIdentifier, String> map =99new HashMap <ObjectIdentifier, String> ();100101private static final int[] anyExtendedKeyUsageOidData = {2, 5, 29, 37, 0};102private static final int[] serverAuthOidData = {1, 3, 6, 1, 5, 5, 7, 3, 1};103private static final int[] clientAuthOidData = {1, 3, 6, 1, 5, 5, 7, 3, 2};104private static final int[] codeSigningOidData = {1, 3, 6, 1, 5, 5, 7, 3, 3};105private static final int[] emailProtectionOidData = {1, 3, 6, 1, 5, 5, 7, 3, 4};106private static final int[] ipsecEndSystemOidData = {1, 3, 6, 1, 5, 5, 7, 3, 5};107private static final int[] ipsecTunnelOidData = {1, 3, 6, 1, 5, 5, 7, 3, 6};108private static final int[] ipsecUserOidData = {1, 3, 6, 1, 5, 5, 7, 3, 7};109private static final int[] timeStampingOidData = {1, 3, 6, 1, 5, 5, 7, 3, 8};110private static final int[] OCSPSigningOidData = {1, 3, 6, 1, 5, 5, 7, 3, 9};111112static {113map.put(ObjectIdentifier.newInternal(anyExtendedKeyUsageOidData), "anyExtendedKeyUsage");114map.put(ObjectIdentifier.newInternal(serverAuthOidData), "serverAuth");115map.put(ObjectIdentifier.newInternal(clientAuthOidData), "clientAuth");116map.put(ObjectIdentifier.newInternal(codeSigningOidData), "codeSigning");117map.put(ObjectIdentifier.newInternal(emailProtectionOidData), "emailProtection");118map.put(ObjectIdentifier.newInternal(ipsecEndSystemOidData), "ipsecEndSystem");119map.put(ObjectIdentifier.newInternal(ipsecTunnelOidData), "ipsecTunnel");120map.put(ObjectIdentifier.newInternal(ipsecUserOidData), "ipsecUser");121map.put(ObjectIdentifier.newInternal(timeStampingOidData), "timeStamping");122map.put(ObjectIdentifier.newInternal(OCSPSigningOidData), "OCSPSigning");123};124125/**126* Vector of KeyUsages for this object.127*/128private Vector<ObjectIdentifier> keyUsages;129130// Encode this extension value.131private void encodeThis() throws IOException {132if (keyUsages == null || keyUsages.isEmpty()) {133this.extensionValue = null;134return;135}136DerOutputStream os = new DerOutputStream();137DerOutputStream tmp = new DerOutputStream();138139for (int i = 0; i < keyUsages.size(); i++) {140tmp.putOID(keyUsages.elementAt(i));141}142143os.write(DerValue.tag_Sequence, tmp);144this.extensionValue = os.toByteArray();145}146147/**148* Create a ExtendedKeyUsageExtension object from149* a Vector of Key Usages; the criticality is set to false.150*151* @param keyUsages the Vector of KeyUsages (ObjectIdentifiers)152*/153public ExtendedKeyUsageExtension(Vector<ObjectIdentifier> keyUsages)154throws IOException {155this(Boolean.FALSE, keyUsages);156}157158/**159* Create a ExtendedKeyUsageExtension object from160* a Vector of KeyUsages with specified criticality.161*162* @param critical true if the extension is to be treated as critical.163* @param keyUsages the Vector of KeyUsages (ObjectIdentifiers)164*/165public ExtendedKeyUsageExtension(Boolean critical, Vector<ObjectIdentifier> keyUsages)166throws IOException {167this.keyUsages = keyUsages;168this.extensionId = PKIXExtensions.ExtendedKeyUsage_Id;169this.critical = critical.booleanValue();170encodeThis();171}172173/**174* Create the extension from its DER encoded value and criticality.175*176* @param critical true if the extension is to be treated as critical.177* @param value an array of DER encoded bytes of the actual value.178* @exception ClassCastException if value is not an array of bytes179* @exception IOException on error.180*/181public ExtendedKeyUsageExtension(Boolean critical, Object value)182throws IOException {183this.extensionId = PKIXExtensions.ExtendedKeyUsage_Id;184this.critical = critical.booleanValue();185this.extensionValue = (byte[]) value;186DerValue val = new DerValue(this.extensionValue);187if (val.tag != DerValue.tag_Sequence) {188throw new IOException("Invalid encoding for " +189"ExtendedKeyUsageExtension.");190}191keyUsages = new Vector<ObjectIdentifier>();192while (val.data.available() != 0) {193DerValue seq = val.data.getDerValue();194ObjectIdentifier usage = seq.getOID();195keyUsages.addElement(usage);196}197}198199/**200* Return the extension as user readable string.201*/202public String toString() {203if (keyUsages == null) return "";204String usage = " ";205boolean first = true;206for (ObjectIdentifier oid: keyUsages) {207if(!first) {208usage += "\n ";209}210211String result = map.get(oid);212if (result != null) {213usage += result;214} else {215usage += oid.toString();216}217first = false;218}219return super.toString() + "ExtendedKeyUsages [\n"220+ usage + "\n]\n";221}222223/**224* Write the extension to the DerOutputStream.225*226* @param out the DerOutputStream to write the extension to.227* @exception IOException on encoding errors.228*/229public void encode(OutputStream out) throws IOException {230DerOutputStream tmp = new DerOutputStream();231if (extensionValue == null) {232extensionId = PKIXExtensions.ExtendedKeyUsage_Id;233critical = false;234encodeThis();235}236super.encode(tmp);237out.write(tmp.toByteArray());238}239240/**241* Set the attribute value.242*/243@SuppressWarnings("unchecked") // Checked with instanceof244public void set(String name, Object obj) throws IOException {245if (name.equalsIgnoreCase(USAGES)) {246if (!(obj instanceof Vector)) {247throw new IOException("Attribute value should be of type Vector.");248}249this.keyUsages = (Vector<ObjectIdentifier>)obj;250} else {251throw new IOException("Attribute name [" + name +252"] not recognized by " +253"CertAttrSet:ExtendedKeyUsageExtension.");254}255encodeThis();256}257258/**259* Get the attribute value.260*/261public Vector<ObjectIdentifier> get(String name) throws IOException {262if (name.equalsIgnoreCase(USAGES)) {263//XXXX May want to consider cloning this264return keyUsages;265} else {266throw new IOException("Attribute name [" + name +267"] not recognized by " +268"CertAttrSet:ExtendedKeyUsageExtension.");269}270}271272/**273* Delete the attribute value.274*/275public void delete(String name) throws IOException {276if (name.equalsIgnoreCase(USAGES)) {277keyUsages = null;278} else {279throw new IOException("Attribute name [" + name +280"] not recognized by " +281"CertAttrSet:ExtendedKeyUsageExtension.");282}283encodeThis();284}285286/**287* Return an enumeration of names of attributes existing within this288* attribute.289*/290public Enumeration<String> getElements() {291AttributeNameEnumeration elements = new AttributeNameEnumeration();292elements.addElement(USAGES);293294return (elements.elements());295}296297/**298* Return the name of this attribute.299*/300public String getName() {301return (NAME);302}303304public List<String> getExtendedKeyUsage() {305List<String> al = new ArrayList<String>(keyUsages.size());306for (ObjectIdentifier oid : keyUsages) {307al.add(oid.toString());308}309return al;310}311312}313314315