001package org.apache.commons.ssl.org.bouncycastle.asn1.eac; 002 003import java.io.IOException; 004 005import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1EncodableVector; 006import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1InputStream; 007import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Object; 008import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Primitive; 009import org.apache.commons.ssl.org.bouncycastle.asn1.BERTags; 010import org.apache.commons.ssl.org.bouncycastle.asn1.DERApplicationSpecific; 011import org.apache.commons.ssl.org.bouncycastle.asn1.DEROctetString; 012 013 014/** 015 * an Iso7816CertificateBody structure. 016 * <pre> 017 * CertificateBody ::= SEQUENCE { 018 * // version of the certificate format. Must be 0 (version 1) 019 * CertificateProfileIdentifer DERApplicationSpecific, 020 * //uniquely identifies the issuinng CA's signature key pair 021 * // contains the iso3166-1 alpha2 encoded country code, the 022 * // name of issuer and the sequence number of the key pair. 023 * CertificationAuthorityReference DERApplicationSpecific, 024 * // stores the encoded public key 025 * PublicKey Iso7816PublicKey, 026 * //associates the public key contained in the certificate with a unique name 027 * // contains the iso3166-1 alpha2 encoded country code, the 028 * // name of the holder and the sequence number of the key pair. 029 * certificateHolderReference DERApplicationSpecific, 030 * // Encodes the role of the holder (i.e. CVCA, DV, IS) and assigns read/write 031 * // access rights to data groups storing sensitive data 032 * certificateHolderAuthorization Iso7816CertificateHolderAuthorization, 033 * // the date of the certificate generation 034 * CertificateEffectiveDate DERApplicationSpecific, 035 * // the date after wich the certificate expires 036 * certificateExpirationDate DERApplicationSpecific 037 * } 038 * </pre> 039 */ 040public class CertificateBody 041 extends ASN1Object 042{ 043 ASN1InputStream seq; 044 private DERApplicationSpecific certificateProfileIdentifier;// version of the certificate format. Must be 0 (version 1) 045 private DERApplicationSpecific certificationAuthorityReference;//uniquely identifies the issuinng CA's signature key pair 046 private PublicKeyDataObject publicKey;// stores the encoded public key 047 private DERApplicationSpecific certificateHolderReference;//associates the public key contained in the certificate with a unique name 048 private CertificateHolderAuthorization certificateHolderAuthorization;// Encodes the role of the holder (i.e. CVCA, DV, IS) and assigns read/write access rights to data groups storing sensitive data 049 private DERApplicationSpecific certificateEffectiveDate;// the date of the certificate generation 050 private DERApplicationSpecific certificateExpirationDate;// the date after wich the certificate expires 051 private int certificateType = 0;// bit field of initialized data. This will tell us if the data are valid. 052 private static final int CPI = 0x01;//certificate Profile Identifier 053 private static final int CAR = 0x02;//certification Authority Reference 054 private static final int PK = 0x04;//public Key 055 private static final int CHR = 0x08;//certificate Holder Reference 056 private static final int CHA = 0x10;//certificate Holder Authorization 057 private static final int CEfD = 0x20;//certificate Effective Date 058 private static final int CExD = 0x40;//certificate Expiration Date 059 060 public static final int profileType = 0x7f;//Profile type Certificate 061 public static final int requestType = 0x0D;// Request type Certificate 062 063 private void setIso7816CertificateBody(DERApplicationSpecific appSpe) 064 throws IOException 065 { 066 byte[] content; 067 if (appSpe.getApplicationTag() == EACTags.CERTIFICATE_CONTENT_TEMPLATE) 068 { 069 content = appSpe.getContents(); 070 } 071 else 072 { 073 throw new IOException("Bad tag : not an iso7816 CERTIFICATE_CONTENT_TEMPLATE"); 074 } 075 ASN1InputStream aIS = new ASN1InputStream(content); 076 ASN1Primitive obj; 077 while ((obj = aIS.readObject()) != null) 078 { 079 DERApplicationSpecific aSpe; 080 081 if (obj instanceof DERApplicationSpecific) 082 { 083 aSpe = (DERApplicationSpecific)obj; 084 } 085 else 086 { 087 throw new IOException("Not a valid iso7816 content : not a DERApplicationSpecific Object :" + EACTags.encodeTag(appSpe) + obj.getClass()); 088 } 089 switch (aSpe.getApplicationTag()) 090 { 091 case EACTags.INTERCHANGE_PROFILE: 092 setCertificateProfileIdentifier(aSpe); 093 break; 094 case EACTags.ISSUER_IDENTIFICATION_NUMBER: 095 setCertificationAuthorityReference(aSpe); 096 break; 097 case EACTags.CARDHOLDER_PUBLIC_KEY_TEMPLATE: 098 setPublicKey(PublicKeyDataObject.getInstance(aSpe.getObject(BERTags.SEQUENCE))); 099 break; 100 case EACTags.CARDHOLDER_NAME: 101 setCertificateHolderReference(aSpe); 102 break; 103 case EACTags.CERTIFICATE_HOLDER_AUTHORIZATION_TEMPLATE: 104 setCertificateHolderAuthorization(new CertificateHolderAuthorization(aSpe)); 105 break; 106 case EACTags.APPLICATION_EFFECTIVE_DATE: 107 setCertificateEffectiveDate(aSpe); 108 break; 109 case EACTags.APPLICATION_EXPIRATION_DATE: 110 setCertificateExpirationDate(aSpe); 111 break; 112 default: 113 certificateType = 0; 114 throw new IOException("Not a valid iso7816 DERApplicationSpecific tag " + aSpe.getApplicationTag()); 115 } 116 } 117 } 118 119 /** 120 * builds an Iso7816CertificateBody by settings each parameters. 121 * 122 * @param certificateProfileIdentifier 123 * @param certificationAuthorityReference 124 * 125 * @param publicKey 126 * @param certificateHolderReference 127 * @param certificateHolderAuthorization 128 * @param certificateEffectiveDate 129 * @param certificateExpirationDate 130 */ 131 public CertificateBody( 132 DERApplicationSpecific certificateProfileIdentifier, 133 CertificationAuthorityReference certificationAuthorityReference, 134 PublicKeyDataObject publicKey, 135 CertificateHolderReference certificateHolderReference, 136 CertificateHolderAuthorization certificateHolderAuthorization, 137 PackedDate certificateEffectiveDate, 138 PackedDate certificateExpirationDate 139 ) 140 { 141 setCertificateProfileIdentifier(certificateProfileIdentifier); 142 setCertificationAuthorityReference(new DERApplicationSpecific( 143 EACTags.ISSUER_IDENTIFICATION_NUMBER, certificationAuthorityReference.getEncoded())); 144 setPublicKey(publicKey); 145 setCertificateHolderReference(new DERApplicationSpecific( 146 EACTags.CARDHOLDER_NAME, certificateHolderReference.getEncoded())); 147 setCertificateHolderAuthorization(certificateHolderAuthorization); 148 try 149 { 150 setCertificateEffectiveDate(new DERApplicationSpecific( 151 false, EACTags.APPLICATION_EFFECTIVE_DATE, new DEROctetString(certificateEffectiveDate.getEncoding()))); 152 setCertificateExpirationDate(new DERApplicationSpecific( 153 false, EACTags.APPLICATION_EXPIRATION_DATE, new DEROctetString(certificateExpirationDate.getEncoding()))); 154 } 155 catch (IOException e) 156 { 157 throw new IllegalArgumentException("unable to encode dates: " + e.getMessage()); 158 } 159 } 160 161 /** 162 * builds an Iso7816CertificateBody with an ASN1InputStream. 163 * 164 * @param obj DERApplicationSpecific containing the whole body. 165 * @throws IOException if the body is not valid. 166 */ 167 private CertificateBody(DERApplicationSpecific obj) 168 throws IOException 169 { 170 setIso7816CertificateBody(obj); 171 } 172 173 /** 174 * create a profile type Iso7816CertificateBody. 175 * 176 * @return return the "profile" type certificate body. 177 * @throws IOException if the DERApplicationSpecific cannot be created. 178 */ 179 private ASN1Primitive profileToASN1Object() 180 throws IOException 181 { 182 ASN1EncodableVector v = new ASN1EncodableVector(); 183 184 v.add(certificateProfileIdentifier); 185 v.add(certificationAuthorityReference); 186 v.add(new DERApplicationSpecific(false, EACTags.CARDHOLDER_PUBLIC_KEY_TEMPLATE, publicKey)); 187 v.add(certificateHolderReference); 188 v.add(certificateHolderAuthorization); 189 v.add(certificateEffectiveDate); 190 v.add(certificateExpirationDate); 191 return new DERApplicationSpecific(EACTags.CERTIFICATE_CONTENT_TEMPLATE, v); 192 } 193 194 private void setCertificateProfileIdentifier(DERApplicationSpecific certificateProfileIdentifier) 195 throws IllegalArgumentException 196 { 197 if (certificateProfileIdentifier.getApplicationTag() == EACTags.INTERCHANGE_PROFILE) 198 { 199 this.certificateProfileIdentifier = certificateProfileIdentifier; 200 certificateType |= CPI; 201 } 202 else 203 { 204 throw new IllegalArgumentException("Not an Iso7816Tags.INTERCHANGE_PROFILE tag :" + EACTags.encodeTag(certificateProfileIdentifier)); 205 } 206 } 207 208 private void setCertificateHolderReference(DERApplicationSpecific certificateHolderReference) 209 throws IllegalArgumentException 210 { 211 if (certificateHolderReference.getApplicationTag() == EACTags.CARDHOLDER_NAME) 212 { 213 this.certificateHolderReference = certificateHolderReference; 214 certificateType |= CHR; 215 } 216 else 217 { 218 throw new IllegalArgumentException("Not an Iso7816Tags.CARDHOLDER_NAME tag"); 219 } 220 } 221 222 /** 223 * set the CertificationAuthorityReference. 224 * 225 * @param certificationAuthorityReference 226 * the DERApplicationSpecific containing the CertificationAuthorityReference. 227 * @throws IllegalArgumentException if the DERApplicationSpecific is not valid. 228 */ 229 private void setCertificationAuthorityReference( 230 DERApplicationSpecific certificationAuthorityReference) 231 throws IllegalArgumentException 232 { 233 if (certificationAuthorityReference.getApplicationTag() == EACTags.ISSUER_IDENTIFICATION_NUMBER) 234 { 235 this.certificationAuthorityReference = certificationAuthorityReference; 236 certificateType |= CAR; 237 } 238 else 239 { 240 throw new IllegalArgumentException("Not an Iso7816Tags.ISSUER_IDENTIFICATION_NUMBER tag"); 241 } 242 } 243 244 /** 245 * set the public Key 246 * 247 * @param publicKey : the DERApplicationSpecific containing the public key 248 * @throws java.io.IOException 249 */ 250 private void setPublicKey(PublicKeyDataObject publicKey) 251 { 252 this.publicKey = PublicKeyDataObject.getInstance(publicKey); 253 this.certificateType |= PK; 254 } 255 256 /** 257 * create a request type Iso7816CertificateBody. 258 * 259 * @return return the "request" type certificate body. 260 * @throws IOException if the DERApplicationSpecific cannot be created. 261 */ 262 private ASN1Primitive requestToASN1Object() 263 throws IOException 264 { 265 ASN1EncodableVector v = new ASN1EncodableVector(); 266 267 v.add(certificateProfileIdentifier); 268 v.add(new DERApplicationSpecific(false, EACTags.CARDHOLDER_PUBLIC_KEY_TEMPLATE, publicKey)); 269 v.add(certificateHolderReference); 270 return new DERApplicationSpecific(EACTags.CERTIFICATE_CONTENT_TEMPLATE, v); 271 } 272 273 /** 274 * create a "request" or "profile" type Iso7816CertificateBody according to the variables sets. 275 * 276 * @return return the ASN1Primitive representing the "request" or "profile" type certificate body. 277 */ 278 public ASN1Primitive toASN1Primitive() 279 { 280 try 281 { 282 if (certificateType == profileType) 283 { 284 return profileToASN1Object(); 285 } 286 if (certificateType == requestType) 287 { 288 return requestToASN1Object(); 289 } 290 } 291 catch (IOException e) 292 { 293 return null; 294 } 295 return null; 296 } 297 298 /** 299 * gives the type of the certificate (value should be profileType or requestType if all data are set). 300 * 301 * @return the int representing the data already set. 302 */ 303 public int getCertificateType() 304 { 305 return certificateType; 306 } 307 308 /** 309 * Gives an instance of Iso7816CertificateBody taken from Object obj 310 * 311 * @param obj is the Object to extract the certificate body from. 312 * @return the Iso7816CertificateBody taken from Object obj. 313 * @throws IOException if object is not valid. 314 */ 315 public static CertificateBody getInstance(Object obj) 316 throws IOException 317 { 318 if (obj instanceof CertificateBody) 319 { 320 return (CertificateBody)obj; 321 } 322 else if (obj != null) 323 { 324 return new CertificateBody(DERApplicationSpecific.getInstance(obj)); 325 } 326 327 return null; 328 } 329 330 /** 331 * @return the date of the certificate generation 332 */ 333 public PackedDate getCertificateEffectiveDate() 334 { 335 if ((this.certificateType & CertificateBody.CEfD) == 336 CertificateBody.CEfD) 337 { 338 return new PackedDate(certificateEffectiveDate.getContents()); 339 } 340 return null; 341 } 342 343 /** 344 * set the date of the certificate generation 345 * 346 * @param ced DERApplicationSpecific containing the date of the certificate generation 347 * @throws IllegalArgumentException if the tag is not Iso7816Tags.APPLICATION_EFFECTIVE_DATE 348 */ 349 private void setCertificateEffectiveDate(DERApplicationSpecific ced) 350 throws IllegalArgumentException 351 { 352 if (ced.getApplicationTag() == EACTags.APPLICATION_EFFECTIVE_DATE) 353 { 354 this.certificateEffectiveDate = ced; 355 certificateType |= CEfD; 356 } 357 else 358 { 359 throw new IllegalArgumentException("Not an Iso7816Tags.APPLICATION_EFFECTIVE_DATE tag :" + EACTags.encodeTag(ced)); 360 } 361 } 362 363 /** 364 * @return the date after wich the certificate expires 365 */ 366 public PackedDate getCertificateExpirationDate() 367 throws IOException 368 { 369 if ((this.certificateType & CertificateBody.CExD) == 370 CertificateBody.CExD) 371 { 372 return new PackedDate(certificateExpirationDate.getContents()); 373 } 374 throw new IOException("certificate Expiration Date not set"); 375 } 376 377 /** 378 * set the date after wich the certificate expires 379 * 380 * @param ced DERApplicationSpecific containing the date after wich the certificate expires 381 * @throws IllegalArgumentException if the tag is not Iso7816Tags.APPLICATION_EXPIRATION_DATE 382 */ 383 private void setCertificateExpirationDate(DERApplicationSpecific ced) 384 throws IllegalArgumentException 385 { 386 if (ced.getApplicationTag() == EACTags.APPLICATION_EXPIRATION_DATE) 387 { 388 this.certificateExpirationDate = ced; 389 certificateType |= CExD; 390 } 391 else 392 { 393 throw new IllegalArgumentException("Not an Iso7816Tags.APPLICATION_EXPIRATION_DATE tag"); 394 } 395 } 396 397 /** 398 * the Iso7816CertificateHolderAuthorization encodes the role of the holder 399 * (i.e. CVCA, DV, IS) and assigns read/write access rights to data groups 400 * storing sensitive data. This functions returns the Certificate Holder 401 * Authorization 402 * 403 * @return the Iso7816CertificateHolderAuthorization 404 */ 405 public CertificateHolderAuthorization getCertificateHolderAuthorization() 406 throws IOException 407 { 408 if ((this.certificateType & CertificateBody.CHA) == 409 CertificateBody.CHA) 410 { 411 return certificateHolderAuthorization; 412 } 413 throw new IOException("Certificate Holder Authorisation not set"); 414 } 415 416 /** 417 * set the CertificateHolderAuthorization 418 * 419 * @param cha the Certificate Holder Authorization 420 */ 421 private void setCertificateHolderAuthorization( 422 CertificateHolderAuthorization cha) 423 { 424 this.certificateHolderAuthorization = cha; 425 certificateType |= CHA; 426 } 427 428 /** 429 * certificateHolderReference : associates the public key contained in the certificate with a unique name 430 * 431 * @return the certificateHolderReference. 432 */ 433 public CertificateHolderReference getCertificateHolderReference() 434 { 435 return new CertificateHolderReference(certificateHolderReference.getContents()); 436 } 437 438 /** 439 * CertificateProfileIdentifier : version of the certificate format. Must be 0 (version 1) 440 * 441 * @return the CertificateProfileIdentifier 442 */ 443 public DERApplicationSpecific getCertificateProfileIdentifier() 444 { 445 return certificateProfileIdentifier; 446 } 447 448 /** 449 * get the certificationAuthorityReference 450 * certificationAuthorityReference : uniquely identifies the issuinng CA's signature key pair 451 * 452 * @return the certificationAuthorityReference 453 */ 454 public CertificationAuthorityReference getCertificationAuthorityReference() 455 throws IOException 456 { 457 if ((this.certificateType & CertificateBody.CAR) == 458 CertificateBody.CAR) 459 { 460 return new CertificationAuthorityReference(certificationAuthorityReference.getContents()); 461 } 462 throw new IOException("Certification authority reference not set"); 463 } 464 465 /** 466 * @return the PublicKey 467 */ 468 public PublicKeyDataObject getPublicKey() 469 { 470 return publicKey; 471 } 472}