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.math.BigInteger; 31 import java.util.Enumeration; 32 33 import sun.security.util.*; 34 35 /** 36 * Represent the CRL Number Extension. 37 * 38 * <p>This extension, if present, conveys a monotonically increasing 39 * sequence number for each CRL issued by a given CA through a specific 40 * CA X.500 Directory entry or CRL distribution point. This extension 41 * allows users to easily determine when a particular CRL supersedes 42 * another CRL. 43 * 44 * @author Hemma Prafullchandra 45 * @see Extension 46 * @see CertAttrSet 47 */ 48 public class CRLNumberExtension extends Extension 49 implements CertAttrSet<String> { 50 51 /** 52 * Attribute name. 53 */ 54 public static final String NAME = "CRLNumber"; 55 public static final String NUMBER = "value"; 56 57 private static final String LABEL = "CRL Number"; 58 59 private BigInteger crlNumber = null; 60 private String extensionName; 61 private String extensionLabel; 62 63 // Encode this extension value 64 private void encodeThis() throws IOException { 65 if (crlNumber == null) { 66 this.extensionValue = null; 67 return; 68 } 69 DerOutputStream os = new DerOutputStream(); 70 os.putInteger(this.crlNumber); 71 this.extensionValue = os.toByteArray(); 72 } 73 74 /** 75 * Create a CRLNumberExtension with the integer value . 76 * The criticality is set to false. 77 * 78 * @param crlNum the value to be set for the extension. 79 */ 80 public CRLNumberExtension(int crlNum) throws IOException { 81 this(PKIXExtensions.CRLNumber_Id, false, BigInteger.valueOf(crlNum), 82 NAME, LABEL); 83 } 84 85 /** 86 * Create a CRLNumberExtension with the BigInteger value . 87 * The criticality is set to false. 88 * 89 * @param crlNum the value to be set for the extension. 90 */ 91 public CRLNumberExtension(BigInteger crlNum) throws IOException { 92 this(PKIXExtensions.CRLNumber_Id, false, crlNum, NAME, LABEL); 93 } 94 95 /** 96 * Creates the extension (also called by the subclass). 97 */ 98 protected CRLNumberExtension(ObjectIdentifier extensionId, 99 boolean isCritical, BigInteger crlNum, String extensionName, 100 String extensionLabel) throws IOException { 101 102 this.extensionId = extensionId; 103 this.critical = isCritical; 104 this.crlNumber = crlNum; 105 this.extensionName = extensionName; 106 this.extensionLabel = extensionLabel; 107 encodeThis(); 108 } 109 110 /** 111 * Create the extension from the passed DER encoded value of the same. 112 * 113 * @param critical true if the extension is to be treated as critical. 114 * @param value an array of DER encoded bytes of the actual value. 115 * @exception ClassCastException if value is not an array of bytes 116 * @exception IOException on error. 117 */ 118 public CRLNumberExtension(Boolean critical, Object value) 119 throws IOException { 120 this(PKIXExtensions.CRLNumber_Id, critical, value, NAME, LABEL); 121 } 122 123 /** 124 * Creates the extension (also called by the subclass). 125 */ 126 protected CRLNumberExtension(ObjectIdentifier extensionId, 127 Boolean critical, Object value, String extensionName, 128 String extensionLabel) throws IOException { 129 130 this.extensionId = extensionId; 131 this.critical = critical.booleanValue(); 132 this.extensionValue = (byte[]) value; 133 DerValue val = new DerValue(this.extensionValue); 134 this.crlNumber = val.getBigInteger(); 135 this.extensionName = extensionName; 136 this.extensionLabel = extensionLabel; 137 } 138 139 /** 140 * Set the attribute value. 141 */ 142 public void set(String name, Object obj) throws IOException { 143 if (name.equalsIgnoreCase(NUMBER)) { 144 if (!(obj instanceof BigInteger)) { 145 throw new IOException("Attribute must be of type BigInteger."); 146 } 147 crlNumber = (BigInteger)obj; 148 } else { 149 throw new IOException("Attribute name not recognized by" 150 + " CertAttrSet:" + extensionName + "."); 151 } 152 encodeThis(); 153 } 154 155 /** 156 * Get the attribute value. 157 */ 158 public Object get(String name) throws IOException { 159 if (name.equalsIgnoreCase(NUMBER)) { 160 if (crlNumber == null) return null; 161 else return crlNumber; 162 } else { 163 throw new IOException("Attribute name not recognized by" 164 + " CertAttrSet:" + extensionName + "."); 165 } 166 } 167 168 /** 169 * Delete the attribute value. 170 */ 171 public void delete(String name) throws IOException { 172 if (name.equalsIgnoreCase(NUMBER)) { 173 crlNumber = null; 174 } else { 175 throw new IOException("Attribute name not recognized by" 176 + " CertAttrSet:" + extensionName + "."); 177 } 178 encodeThis(); 179 } 180 181 /** 182 * Returns a printable representation of the CRLNumberExtension. 183 */ 184 public String toString() { 185 String s = super.toString() + extensionLabel + ": " + 186 ((crlNumber == null) ? "" : Debug.toHexString(crlNumber)) 187 + "\n"; 188 return (s); 189 } 190 191 /** 192 * Write the extension to the DerOutputStream. 193 * 194 * @param out the DerOutputStream to write the extension to. 195 * @exception IOException on encoding errors. 196 */ 197 public void encode(OutputStream out) throws IOException { 198 DerOutputStream tmp = new DerOutputStream(); 199 encode(out, PKIXExtensions.CRLNumber_Id, true); 200 } 201 202 /** 203 * Write the extension to the DerOutputStream. 204 * (Also called by the subclass) 205 */ 206 protected void encode(OutputStream out, ObjectIdentifier extensionId, 207 boolean isCritical) throws IOException { 208 209 DerOutputStream tmp = new DerOutputStream(); 210 211 if (this.extensionValue == null) { 212 this.extensionId = extensionId; 213 this.critical = isCritical; 214 encodeThis(); 215 } 216 super.encode(tmp); 217 out.write(tmp.toByteArray()); 218 } 219 220 /** 221 * Return an enumeration of names of attributes existing within this 222 * attribute. 223 */ 224 public Enumeration<String> getElements() { 225 AttributeNameEnumeration elements = new AttributeNameEnumeration(); 226 elements.addElement(NUMBER); 227 return (elements.elements()); 228 } 229 230 /** 231 * Return the name of this attribute. 232 */ 233 public String getName() { 234 return (extensionName); 235 } 236 } 237