1 /*
2  * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package sun.security.x509;
27 
28 import java.io.IOException;
29 import java.io.OutputStream;
30 import java.util.Enumeration;
31 
32 import sun.security.util.*;
33 
34 /**
35  * Represent the Subject Key Identifier Extension.
36  *
37  * This extension, if present, provides a means of identifying the particular
38  * public key used in an application.  This extension by default is marked
39  * non-critical.
40  *
41  * <p>Extensions are addiitonal attributes which can be inserted in a X509
42  * v3 certificate. For example a "Driving License Certificate" could have
43  * the driving license number as a extension.
44  *
45  * <p>Extensions are represented as a sequence of the extension identifier
46  * (Object Identifier), a boolean flag stating whether the extension is to
47  * be treated as being critical and the extension value itself (this is again
48  * a DER encoding of the extension value).
49  *
50  * @author Amit Kapoor
51  * @author Hemma Prafullchandra
52  * @see Extension
53  * @see CertAttrSet
54  */
55 public class SubjectKeyIdentifierExtension extends Extension
56 implements CertAttrSet<String> {
57     /**
58      * Identifier for this attribute, to be used with the
59      * get, set, delete methods of Certificate, x509 type.
60      */
61     public static final String IDENT =
62                          "x509.info.extensions.SubjectKeyIdentifier";
63     /**
64      * Attribute names.
65      */
66     public static final String NAME = "SubjectKeyIdentifier";
67     public static final String KEY_ID = "key_id";
68 
69     // Private data member
70     private KeyIdentifier id = null;
71 
72     // Encode this extension value
encodeThis()73     private void encodeThis() throws IOException {
74         if (id == null) {
75             this.extensionValue = null;
76             return;
77         }
78         DerOutputStream os = new DerOutputStream();
79         id.encode(os);
80         this.extensionValue = os.toByteArray();
81     }
82 
83     /**
84      * Create a SubjectKeyIdentifierExtension with the passed octet string.
85      * The criticality is set to False.
86      * @param octetString the octet string identifying the key identifier.
87      */
SubjectKeyIdentifierExtension(byte[] octetString)88     public SubjectKeyIdentifierExtension(byte[] octetString)
89     throws IOException {
90         id = new KeyIdentifier(octetString);
91 
92         this.extensionId = PKIXExtensions.SubjectKey_Id;
93         this.critical = false;
94         encodeThis();
95     }
96 
97     /**
98      * Create the extension from the passed DER encoded value.
99      *
100      * @param critical true if the extension is to be treated as critical.
101      * @param value an array of DER encoded bytes of the actual value.
102      * @exception ClassCastException if value is not an array of bytes
103      * @exception IOException on error.
104      */
SubjectKeyIdentifierExtension(Boolean critical, Object value)105     public SubjectKeyIdentifierExtension(Boolean critical, Object value)
106     throws IOException {
107         this.extensionId = PKIXExtensions.SubjectKey_Id;
108         this.critical = critical.booleanValue();
109         this.extensionValue = (byte[]) value;
110         DerValue val = new DerValue(this.extensionValue);
111         this.id = new KeyIdentifier(val);
112     }
113 
114     /**
115      * Returns a printable representation.
116      */
toString()117     public String toString() {
118         return super.toString() + "SubjectKeyIdentifier [\n"
119                 + String.valueOf(id) + "]\n";
120     }
121 
122     /**
123      * Write the extension to the OutputStream.
124      *
125      * @param out the OutputStream to write the extension to.
126      * @exception IOException on encoding errors.
127      */
encode(OutputStream out)128     public void encode(OutputStream out) throws IOException {
129         DerOutputStream tmp = new DerOutputStream();
130         if (extensionValue == null) {
131             extensionId = PKIXExtensions.SubjectKey_Id;
132             critical = false;
133             encodeThis();
134         }
135         super.encode(tmp);
136         out.write(tmp.toByteArray());
137     }
138 
139     /**
140      * Set the attribute value.
141      */
set(String name, Object obj)142     public void set(String name, Object obj) throws IOException {
143         if (name.equalsIgnoreCase(KEY_ID)) {
144             if (!(obj instanceof KeyIdentifier)) {
145               throw new IOException("Attribute value should be of" +
146                                     " type KeyIdentifier.");
147             }
148             id = (KeyIdentifier)obj;
149         } else {
150           throw new IOException("Attribute name not recognized by " +
151                 "CertAttrSet:SubjectKeyIdentifierExtension.");
152         }
153         encodeThis();
154     }
155 
156     /**
157      * Get the attribute value.
158      */
get(String name)159     public KeyIdentifier get(String name) throws IOException {
160         if (name.equalsIgnoreCase(KEY_ID)) {
161             return (id);
162         } else {
163           throw new IOException("Attribute name not recognized by " +
164                 "CertAttrSet:SubjectKeyIdentifierExtension.");
165         }
166     }
167 
168     /**
169      * Delete the attribute value.
170      */
delete(String name)171     public void delete(String name) throws IOException {
172         if (name.equalsIgnoreCase(KEY_ID)) {
173             id = null;
174         } else {
175           throw new IOException("Attribute name not recognized by " +
176                 "CertAttrSet:SubjectKeyIdentifierExtension.");
177         }
178         encodeThis();
179     }
180 
181     /**
182      * Return an enumeration of names of attributes existing within this
183      * attribute.
184      */
getElements()185     public Enumeration<String> getElements() {
186         AttributeNameEnumeration elements = new AttributeNameEnumeration();
187         elements.addElement(KEY_ID);
188 
189         return (elements.elements());
190     }
191 
192     /**
193      * Return the name of this attribute.
194      */
getName()195     public String getName() {
196         return (NAME);
197     }
198 }
199