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.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 encodeThis()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 */ CRLNumberExtension(int crlNum)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 */ CRLNumberExtension(BigInteger crlNum)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 */ CRLNumberExtension(ObjectIdentifier extensionId, boolean isCritical, BigInteger crlNum, String extensionName, String extensionLabel)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 */ CRLNumberExtension(Boolean critical, Object value)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 */ CRLNumberExtension(ObjectIdentifier extensionId, Boolean critical, Object value, String extensionName, String extensionLabel)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 */ set(String name, Object obj)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 */ get(String name)158 public BigInteger get(String name) throws IOException { 159 if (name.equalsIgnoreCase(NUMBER)) { 160 return crlNumber; 161 } else { 162 throw new IOException("Attribute name not recognized by" + 163 " CertAttrSet:" + extensionName + '.'); 164 } 165 } 166 167 /** 168 * Delete the attribute value. 169 */ delete(String name)170 public void delete(String name) throws IOException { 171 if (name.equalsIgnoreCase(NUMBER)) { 172 crlNumber = null; 173 } else { 174 throw new IOException("Attribute name not recognized by" 175 + " CertAttrSet:" + extensionName + "."); 176 } 177 encodeThis(); 178 } 179 180 /** 181 * Returns a printable representation of the CRLNumberExtension. 182 */ toString()183 public String toString() { 184 String s = super.toString() + extensionLabel + ": " + 185 ((crlNumber == null) ? "" : Debug.toHexString(crlNumber)) 186 + "\n"; 187 return (s); 188 } 189 190 /** 191 * Write the extension to the DerOutputStream. 192 * 193 * @param out the DerOutputStream to write the extension to. 194 * @exception IOException on encoding errors. 195 */ encode(OutputStream out)196 public void encode(OutputStream out) throws IOException { 197 DerOutputStream tmp = new DerOutputStream(); 198 encode(out, PKIXExtensions.CRLNumber_Id, true); 199 } 200 201 /** 202 * Write the extension to the DerOutputStream. 203 * (Also called by the subclass) 204 */ encode(OutputStream out, ObjectIdentifier extensionId, boolean isCritical)205 protected void encode(OutputStream out, ObjectIdentifier extensionId, 206 boolean isCritical) throws IOException { 207 208 DerOutputStream tmp = new DerOutputStream(); 209 210 if (this.extensionValue == null) { 211 this.extensionId = extensionId; 212 this.critical = isCritical; 213 encodeThis(); 214 } 215 super.encode(tmp); 216 out.write(tmp.toByteArray()); 217 } 218 219 /** 220 * Return an enumeration of names of attributes existing within this 221 * attribute. 222 */ getElements()223 public Enumeration<String> getElements() { 224 AttributeNameEnumeration elements = new AttributeNameEnumeration(); 225 elements.addElement(NUMBER); 226 return (elements.elements()); 227 } 228 229 /** 230 * Return the name of this attribute. 231 */ getName()232 public String getName() { 233 return (extensionName); 234 } 235 } 236