1 package org.bouncycastle.asn1.isismtt.ocsp; 2 3 import java.io.IOException; 4 5 import org.bouncycastle.asn1.ASN1Choice; 6 import org.bouncycastle.asn1.ASN1Object; 7 import org.bouncycastle.asn1.ASN1OctetString; 8 import org.bouncycastle.asn1.ASN1Primitive; 9 import org.bouncycastle.asn1.ASN1Sequence; 10 import org.bouncycastle.asn1.ASN1TaggedObject; 11 import org.bouncycastle.asn1.DEROctetString; 12 import org.bouncycastle.asn1.DERTaggedObject; 13 import org.bouncycastle.asn1.x509.Certificate; 14 import org.bouncycastle.util.Arrays; 15 16 /** 17 * ISIS-MTT-Optional: The certificate requested by the client by inserting the 18 * RetrieveIfAllowed extension in the request, will be returned in this 19 * extension. 20 * <p> 21 * ISIS-MTT-SigG: The signature act allows publishing certificates only then, 22 * when the certificate owner gives his explicit permission. Accordingly, there 23 * may be �nondownloadable� certificates, about which the responder must provide 24 * status information, but MUST NOT include them in the response. Clients may 25 * get therefore the following three kind of answers on a single request 26 * including the RetrieveIfAllowed extension: 27 * <ul> 28 * <li> a) the responder supports the extension and is allowed to publish the 29 * certificate: RequestedCertificate returned including the requested 30 * certificate 31 * <li>b) the responder supports the extension but is NOT allowed to publish 32 * the certificate: RequestedCertificate returned including an empty OCTET 33 * STRING 34 * <li>c) the responder does not support the extension: RequestedCertificate is 35 * not included in the response 36 * </ul> 37 * Clients requesting RetrieveIfAllowed MUST be able to handle these cases. If 38 * any of the OCTET STRING options is used, it MUST contain the DER encoding of 39 * the requested certificate. 40 * <pre> 41 * RequestedCertificate ::= CHOICE { 42 * Certificate Certificate, 43 * publicKeyCertificate [0] EXPLICIT OCTET STRING, 44 * attributeCertificate [1] EXPLICIT OCTET STRING 45 * } 46 * </pre> 47 */ 48 public class RequestedCertificate 49 extends ASN1Object 50 implements ASN1Choice 51 { 52 public static final int certificate = -1; 53 public static final int publicKeyCertificate = 0; 54 public static final int attributeCertificate = 1; 55 56 private Certificate cert; 57 private byte[] publicKeyCert; 58 private byte[] attributeCert; 59 getInstance(Object obj)60 public static RequestedCertificate getInstance(Object obj) 61 { 62 if (obj == null || obj instanceof RequestedCertificate) 63 { 64 return (RequestedCertificate)obj; 65 } 66 67 if (obj instanceof ASN1Sequence) 68 { 69 return new RequestedCertificate(Certificate.getInstance(obj)); 70 } 71 if (obj instanceof ASN1TaggedObject) 72 { 73 return new RequestedCertificate((ASN1TaggedObject)obj); 74 } 75 76 throw new IllegalArgumentException("illegal object in getInstance: " 77 + obj.getClass().getName()); 78 } 79 getInstance(ASN1TaggedObject obj, boolean explicit)80 public static RequestedCertificate getInstance(ASN1TaggedObject obj, boolean explicit) 81 { 82 if (!explicit) 83 { 84 throw new IllegalArgumentException("choice item must be explicitly tagged"); 85 } 86 87 return getInstance(obj.getObject()); 88 } 89 RequestedCertificate(ASN1TaggedObject tagged)90 private RequestedCertificate(ASN1TaggedObject tagged) 91 { 92 if (tagged.getTagNo() == publicKeyCertificate) 93 { 94 publicKeyCert = ASN1OctetString.getInstance(tagged, true).getOctets(); 95 } 96 else if (tagged.getTagNo() == attributeCertificate) 97 { 98 attributeCert = ASN1OctetString.getInstance(tagged, true).getOctets(); 99 } 100 else 101 { 102 throw new IllegalArgumentException("unknown tag number: " + tagged.getTagNo()); 103 } 104 } 105 106 /** 107 * Constructor from a given details. 108 * <p> 109 * Only one parameter can be given. All other must be <code>null</code>. 110 * 111 * @param certificate Given as Certificate 112 */ RequestedCertificate(Certificate certificate)113 public RequestedCertificate(Certificate certificate) 114 { 115 this.cert = certificate; 116 } 117 RequestedCertificate(int type, byte[] certificateOctets)118 public RequestedCertificate(int type, byte[] certificateOctets) 119 { 120 this(new DERTaggedObject(type, new DEROctetString(certificateOctets))); 121 } 122 getType()123 public int getType() 124 { 125 if (cert != null) 126 { 127 return certificate; 128 } 129 if (publicKeyCert != null) 130 { 131 return publicKeyCertificate; 132 } 133 return attributeCertificate; 134 } 135 getCertificateBytes()136 public byte[] getCertificateBytes() 137 { 138 if (cert != null) 139 { 140 try 141 { 142 return cert.getEncoded(); 143 } 144 catch (IOException e) 145 { 146 throw new IllegalStateException("can't decode certificate: " + e); 147 } 148 } 149 if (publicKeyCert != null) 150 { 151 return Arrays.clone(publicKeyCert); 152 } 153 return Arrays.clone(attributeCert); 154 } 155 156 /** 157 * Produce an object suitable for an ASN1OutputStream. 158 * <p> 159 * Returns: 160 * <pre> 161 * RequestedCertificate ::= CHOICE { 162 * Certificate Certificate, 163 * publicKeyCertificate [0] EXPLICIT OCTET STRING, 164 * attributeCertificate [1] EXPLICIT OCTET STRING 165 * } 166 * </pre> 167 * 168 * @return a DERObject 169 */ toASN1Primitive()170 public ASN1Primitive toASN1Primitive() 171 { 172 if (publicKeyCert != null) 173 { 174 return new DERTaggedObject(0, new DEROctetString(publicKeyCert)); 175 } 176 if (attributeCert != null) 177 { 178 return new DERTaggedObject(1, new DEROctetString(attributeCert)); 179 } 180 return cert.toASN1Primitive(); 181 } 182 } 183