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 26package sun.security.x509; 27 28import java.io.IOException; 29import java.io.OutputStream; 30import java.math.BigInteger; 31import java.util.Enumeration; 32 33import 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 */ 48public class CRLNumberExtension extends Extension 49implements 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 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 */ 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 */ 183 public String toString() { 184 StringBuilder sb = new StringBuilder(); 185 sb.append(super.toString()) 186 .append(extensionLabel) 187 .append(": "); 188 if (crlNumber != null) { 189 sb.append(Debug.toHexString(crlNumber)); 190 } 191 sb.append('\n'); 192 return sb.toString(); 193 } 194 195 /** 196 * Write the extension to the DerOutputStream. 197 * 198 * @param out the DerOutputStream to write the extension to. 199 * @exception IOException on encoding errors. 200 */ 201 public void encode(OutputStream out) throws IOException { 202 DerOutputStream tmp = new DerOutputStream(); 203 encode(out, PKIXExtensions.CRLNumber_Id, true); 204 } 205 206 /** 207 * Write the extension to the DerOutputStream. 208 * (Also called by the subclass) 209 */ 210 protected void encode(OutputStream out, ObjectIdentifier extensionId, 211 boolean isCritical) throws IOException { 212 213 DerOutputStream tmp = new DerOutputStream(); 214 215 if (this.extensionValue == null) { 216 this.extensionId = extensionId; 217 this.critical = isCritical; 218 encodeThis(); 219 } 220 super.encode(tmp); 221 out.write(tmp.toByteArray()); 222 } 223 224 /** 225 * Return an enumeration of names of attributes existing within this 226 * attribute. 227 */ 228 public Enumeration<String> getElements() { 229 AttributeNameEnumeration elements = new AttributeNameEnumeration(); 230 elements.addElement(NUMBER); 231 return (elements.elements()); 232 } 233 234 /** 235 * Return the name of this attribute. 236 */ 237 public String getName() { 238 return (extensionName); 239 } 240} 241