1 /* 2 * Copyright (c) 1997, 2006, 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.security.cert.CRLReason; 31 import java.util.Enumeration; 32 33 import sun.security.util.*; 34 35 /** 36 * The reasonCode is a non-critical CRL entry extension that identifies 37 * the reason for the certificate revocation. CAs are strongly 38 * encouraged to include reason codes in CRL entries; however, the 39 * reason code CRL entry extension should be absent instead of using the 40 * unspecified (0) reasonCode value. 41 * <p>The ASN.1 syntax for this is: 42 * <pre> 43 * id-ce-cRLReason OBJECT IDENTIFIER ::= { id-ce 21 } 44 * 45 * -- reasonCode ::= { CRLReason } 46 * 47 * CRLReason ::= ENUMERATED { 48 * unspecified (0), 49 * keyCompromise (1), 50 * cACompromise (2), 51 * affiliationChanged (3), 52 * superseded (4), 53 * cessationOfOperation (5), 54 * certificateHold (6), 55 * removeFromCRL (8), 56 * privilegeWithdrawn (9), 57 * aACompromise (10) } 58 * </pre> 59 * @author Hemma Prafullchandra 60 * @see Extension 61 * @see CertAttrSet 62 */ 63 public class CRLReasonCodeExtension extends Extension 64 implements CertAttrSet<String> { 65 66 /** 67 * Attribute name and Reason codes 68 */ 69 public static final String NAME = "CRLReasonCode"; 70 public static final String REASON = "reason"; 71 72 public static final int UNSPECIFIED = 0; 73 public static final int KEY_COMPROMISE = 1; 74 public static final int CA_COMPROMISE = 2; 75 public static final int AFFLIATION_CHANGED = 3; 76 public static final int SUPERSEDED = 4; 77 public static final int CESSATION_OF_OPERATION = 5; 78 public static final int CERTIFICATE_HOLD = 6; 79 // note 7 missing in syntax 80 public static final int REMOVE_FROM_CRL = 8; 81 public static final int PRIVILEGE_WITHDRAWN = 9; 82 public static final int AA_COMPROMISE = 10; 83 84 private static CRLReason[] values = CRLReason.values(); 85 86 private int reasonCode = 0; 87 88 private void encodeThis() throws IOException { 89 if (reasonCode == 0) { 90 this.extensionValue = null; 91 return; 92 } 93 DerOutputStream dos = new DerOutputStream(); 94 dos.putEnumerated(reasonCode); 95 this.extensionValue = dos.toByteArray(); 96 } 97 98 /** 99 * Create a CRLReasonCodeExtension with the passed in reason. 100 * Criticality automatically set to false. 101 * 102 * @param reason the enumerated value for the reason code. 103 */ 104 public CRLReasonCodeExtension(int reason) throws IOException { 105 this(false, reason); 106 } 107 108 /** 109 * Create a CRLReasonCodeExtension with the passed in reason. 110 * 111 * @param critical true if the extension is to be treated as critical. 112 * @param reason the enumerated value for the reason code. 113 */ 114 public CRLReasonCodeExtension(boolean critical, int reason) 115 throws IOException { 116 this.extensionId = PKIXExtensions.ReasonCode_Id; 117 this.critical = critical; 118 this.reasonCode = reason; 119 encodeThis(); 120 } 121 122 /** 123 * Create the extension from the passed DER encoded value of the same. 124 * 125 * @param critical true if the extension is to be treated as critical. 126 * @param value an array of DER encoded bytes of the actual value. 127 * @exception ClassCastException if value is not an array of bytes 128 * @exception IOException on error. 129 */ 130 public CRLReasonCodeExtension(Boolean critical, Object value) 131 throws IOException { 132 this.extensionId = PKIXExtensions.ReasonCode_Id; 133 this.critical = critical.booleanValue(); 134 this.extensionValue = (byte[]) value; 135 DerValue val = new DerValue(this.extensionValue); 136 this.reasonCode = val.getEnumerated(); 137 } 138 139 /** 140 * Set the attribute value. 141 */ 142 public void set(String name, Object obj) throws IOException { 143 if (!(obj instanceof Integer)) { 144 throw new IOException("Attribute must be of type Integer."); 145 } 146 if (name.equalsIgnoreCase(REASON)) { 147 reasonCode = ((Integer)obj).intValue(); 148 } else { 149 throw new IOException 150 ("Name not supported by CRLReasonCodeExtension"); 151 } 152 encodeThis(); 153 } 154 155 /** 156 * Get the attribute value. 157 */ 158 public Object get(String name) throws IOException { 159 if (name.equalsIgnoreCase(REASON)) { 160 return new Integer(reasonCode); 161 } else { 162 throw new IOException 163 ("Name not supported by CRLReasonCodeExtension"); 164 } 165 } 166 167 /** 168 * Delete the attribute value. 169 */ 170 public void delete(String name) throws IOException { 171 if (name.equalsIgnoreCase(REASON)) { 172 reasonCode = 0; 173 } else { 174 throw new IOException 175 ("Name not supported by CRLReasonCodeExtension"); 176 } 177 encodeThis(); 178 } 179 180 /** 181 * Returns a printable representation of the Reason code. 182 */ 183 public String toString() { 184 return super.toString() + " Reason Code: " + values[reasonCode]; 185 } 186 187 /** 188 * Write the extension to the DerOutputStream. 189 * 190 * @param out the DerOutputStream to write the extension to. 191 * @exception IOException on encoding errors. 192 */ 193 public void encode(OutputStream out) throws IOException { 194 DerOutputStream tmp = new DerOutputStream(); 195 196 if (this.extensionValue == null) { 197 this.extensionId = PKIXExtensions.ReasonCode_Id; 198 this.critical = false; 199 encodeThis(); 200 } 201 super.encode(tmp); 202 out.write(tmp.toByteArray()); 203 } 204 205 /** 206 * Return an enumeration of names of attributes existing within this 207 * attribute. 208 */ 209 public Enumeration<String> getElements() { 210 AttributeNameEnumeration elements = new AttributeNameEnumeration(); 211 elements.addElement(REASON); 212 213 return elements.elements(); 214 } 215 216 /** 217 * Return the name of this attribute. 218 */ 219 public String getName() { 220 return NAME; 221 } 222 223 /** 224 * Return the reason as a CRLReason enum. 225 */ 226 public CRLReason getReasonCode() { 227 // if out-of-range, return UNSPECIFIED 228 if (reasonCode > 0 && reasonCode < values.length) { 229 return values[reasonCode]; 230 } else { 231 return CRLReason.UNSPECIFIED; 232 } 233 } 234 } 235