001package org.apache.commons.ssl.org.bouncycastle.asn1.eac; 002 003 004import java.io.IOException; 005 006import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1EncodableVector; 007import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1InputStream; 008import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Object; 009import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1ObjectIdentifier; 010import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1ParsingException; 011import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Primitive; 012import org.apache.commons.ssl.org.bouncycastle.asn1.DERApplicationSpecific; 013import org.apache.commons.ssl.org.bouncycastle.asn1.DEROctetString; 014 015 016/** 017 * an iso7816Certificate structure. 018 * <pre> 019 * Certificate ::= SEQUENCE { 020 * CertificateBody Iso7816CertificateBody, 021 * signature DER Application specific 022 * } 023 * </pre> 024 */ 025public class CVCertificate 026 extends ASN1Object 027{ 028 private CertificateBody certificateBody; 029 private byte[] signature; 030 private int valid; 031 private static int bodyValid = 0x01; 032 private static int signValid = 0x02; 033 public static final byte version_1 = 0x0; 034 035 public static String ReferenceEncoding = "ISO-8859-1"; 036 037 /** 038 * Sets the values of the certificate (body and signature). 039 * 040 * @param appSpe is a DERApplicationSpecific object containing body and signature. 041 * @throws IOException if tags or value are incorrect. 042 */ 043 private void setPrivateData(DERApplicationSpecific appSpe) 044 throws IOException 045 { 046 valid = 0; 047 if (appSpe.getApplicationTag() == EACTags.CARDHOLDER_CERTIFICATE) 048 { 049 ASN1InputStream content = new ASN1InputStream(appSpe.getContents()); 050 ASN1Primitive tmpObj; 051 while ((tmpObj = content.readObject()) != null) 052 { 053 DERApplicationSpecific aSpe; 054 if (tmpObj instanceof DERApplicationSpecific) 055 { 056 aSpe = (DERApplicationSpecific)tmpObj; 057 switch (aSpe.getApplicationTag()) 058 { 059 case EACTags.CERTIFICATE_CONTENT_TEMPLATE: 060 certificateBody = CertificateBody.getInstance(aSpe); 061 valid |= bodyValid; 062 break; 063 case EACTags.STATIC_INTERNAL_AUTHENTIFICATION_ONE_STEP: 064 signature = aSpe.getContents(); 065 valid |= signValid; 066 break; 067 default: 068 throw new IOException("Invalid tag, not an Iso7816CertificateStructure :" + aSpe.getApplicationTag()); 069 } 070 } 071 else 072 { 073 throw new IOException("Invalid Object, not an Iso7816CertificateStructure"); 074 } 075 } 076 } 077 else 078 { 079 throw new IOException("not a CARDHOLDER_CERTIFICATE :" + appSpe.getApplicationTag()); 080 } 081 } 082 083 /** 084 * Create an iso7816Certificate structure from an ASN1InputStream. 085 * 086 * @param aIS the byte stream to parse. 087 * @throws IOException if there is a problem parsing the data. 088 */ 089 public CVCertificate(ASN1InputStream aIS) 090 throws IOException 091 { 092 initFrom(aIS); 093 } 094 095 private void initFrom(ASN1InputStream aIS) 096 throws IOException 097 { 098 ASN1Primitive obj; 099 while ((obj = aIS.readObject()) != null) 100 { 101 if (obj instanceof DERApplicationSpecific) 102 { 103 setPrivateData((DERApplicationSpecific)obj); 104 } 105 else 106 { 107 throw new IOException("Invalid Input Stream for creating an Iso7816CertificateStructure"); 108 } 109 } 110 } 111 112 /** 113 * Create an iso7816Certificate structure from a DERApplicationSpecific. 114 * 115 * @param appSpe the DERApplicationSpecific object. 116 * @return the Iso7816CertificateStructure represented by the DERApplicationSpecific object. 117 * @throws IOException if there is a problem parsing the data. 118 */ 119 private CVCertificate(DERApplicationSpecific appSpe) 120 throws IOException 121 { 122 setPrivateData(appSpe); 123 } 124 125 /** 126 * Create an iso7816Certificate structure from a body and its signature. 127 * 128 * @param body the Iso7816CertificateBody object containing the body. 129 * @param signature the byte array containing the signature 130 * @throws IOException if there is a problem parsing the data. 131 */ 132 public CVCertificate(CertificateBody body, byte[] signature) 133 throws IOException 134 { 135 certificateBody = body; 136 this.signature = signature; 137 // patch remi 138 valid |= bodyValid; 139 valid |= signValid; 140 } 141 142 /** 143 * Create an iso7816Certificate structure from an object. 144 * 145 * @param obj the Object to extract the certificate from. 146 * @return the Iso7816CertificateStructure represented by the byte stream. 147 */ 148 public static CVCertificate getInstance(Object obj) 149 { 150 if (obj instanceof CVCertificate) 151 { 152 return (CVCertificate)obj; 153 } 154 else if (obj != null) 155 { 156 try 157 { 158 return new CVCertificate(DERApplicationSpecific.getInstance(obj)); 159 } 160 catch (IOException e) 161 { 162 throw new ASN1ParsingException("unable to parse data: " + e.getMessage(), e); 163 } 164 } 165 166 return null; 167 } 168 169 /** 170 * Gives the signature of the whole body. Type of signature is given in 171 * the Iso7816CertificateBody.Iso7816PublicKey.ASN1ObjectIdentifier 172 * 173 * @return the signature of the body. 174 */ 175 public byte[] getSignature() 176 { 177 return signature; 178 } 179 180 /** 181 * Gives the body of the certificate. 182 * 183 * @return the body. 184 */ 185 public CertificateBody getBody() 186 { 187 return certificateBody; 188 } 189 190 /** 191 * @see org.bouncycastle.asn1.ASN1Object#toASN1Primitive() 192 */ 193 public ASN1Primitive toASN1Primitive() 194 { 195 ASN1EncodableVector v = new ASN1EncodableVector(); 196 197 if (valid != (signValid | bodyValid)) 198 { 199 return null; 200 } 201 v.add(certificateBody); 202 203 try 204 { 205 v.add(new DERApplicationSpecific(false, EACTags.STATIC_INTERNAL_AUTHENTIFICATION_ONE_STEP, new DEROctetString(signature))); 206 } 207 catch (IOException e) 208 { 209 throw new IllegalStateException("unable to convert signature!"); 210 } 211 212 return new DERApplicationSpecific(EACTags.CARDHOLDER_CERTIFICATE, v); 213 } 214 215 /** 216 * @return the Holder authorization and role (CVCA, DV, IS). 217 */ 218 public ASN1ObjectIdentifier getHolderAuthorization() 219 throws IOException 220 { 221 CertificateHolderAuthorization cha = certificateBody.getCertificateHolderAuthorization(); 222 return cha.getOid(); 223 } 224 225 /** 226 * @return the date of the certificate generation 227 */ 228 public PackedDate getEffectiveDate() 229 throws IOException 230 { 231 return certificateBody.getCertificateEffectiveDate(); 232 } 233 234 235 /** 236 * @return the type of certificate (request or profile) 237 * value is either Iso7816CertificateBody.profileType 238 * or Iso7816CertificateBody.requestType. Any other value 239 * is not valid. 240 */ 241 public int getCertificateType() 242 { 243 return this.certificateBody.getCertificateType(); 244 } 245 246 /** 247 * @return the date of the certificate generation 248 */ 249 public PackedDate getExpirationDate() 250 throws IOException 251 { 252 return certificateBody.getCertificateExpirationDate(); 253 } 254 255 256 /** 257 * return a bits field coded on one byte. For signification of the 258 * several bit see Iso7816CertificateHolderAuthorization 259 * 260 * @return role and access rigth 261 * @throws IOException 262 * @see CertificateHolderAuthorization 263 */ 264 public int getRole() 265 throws IOException 266 { 267 CertificateHolderAuthorization cha = certificateBody.getCertificateHolderAuthorization(); 268 return cha.getAccessRights(); 269 } 270 271 /** 272 * @return the Authority Reference field of the certificate 273 * @throws IOException 274 */ 275 public CertificationAuthorityReference getAuthorityReference() 276 throws IOException 277 { 278 return certificateBody.getCertificationAuthorityReference(); 279 } 280 281 /** 282 * @return the Holder Reference Field of the certificate 283 * @throws IOException 284 */ 285 public CertificateHolderReference getHolderReference() 286 throws IOException 287 { 288 return certificateBody.getCertificateHolderReference(); 289 } 290 291 /** 292 * @return the bits corresponding to the role intented for the certificate 293 * See Iso7816CertificateHolderAuthorization static int for values 294 * @throws IOException 295 */ 296 public int getHolderAuthorizationRole() 297 throws IOException 298 { 299 int rights = certificateBody.getCertificateHolderAuthorization().getAccessRights(); 300 return rights & 0xC0; 301 } 302 303 /** 304 * @return the bits corresponding the authorizations contained in the certificate 305 * See Iso7816CertificateHolderAuthorization static int for values 306 * @throws IOException 307 */ 308 public Flags getHolderAuthorizationRights() 309 throws IOException 310 { 311 return new Flags(certificateBody.getCertificateHolderAuthorization().getAccessRights() & 0x1F); 312 } 313}