/****************************************************************************
* Copyright (C) 2012 ecsec GmbH.
* All rights reserved.
* Contact: ecsec GmbH (info@ecsec.de)
*
* This file is part of the Open eCard App.
*
* GNU General Public License Usage
* This file may be used under the terms of the GNU General Public
* License version 3.0 as published by the Free Software Foundation
* and appearing in the file LICENSE.GPL included in the packaging of
* this file. Please review the following information to ensure the
* GNU General Public License version 3.0 requirements will be met:
* http://www.gnu.org/copyleft/gpl.html.
*
* Other Usage
* Alternatively, this file may be used in accordance with the terms
* and conditions contained in a signed written agreement between
* you and ecsec GmbH.
*
***************************************************************************/
package org.openecard.crypto.common.asn1.cvc;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;
import org.openecard.common.tlv.TLV;
import org.openecard.common.tlv.TLVException;
import org.openecard.common.util.ByteUtils;
/**
* Implements a Card Verifiable Certificate.
*
* See BSI-TR-03110, version 2.10, part 3, section C.
*
* @author Moritz Horsch <horsch@cdc.informatik.tu-darmstadt.de>
* @author Dirk Petrautzki <petrautzki@hs-coburg.de>
*/
public class CardVerifiableCertificate {
// Card Verifiable Certificate
private static final int TAG_CVC = 0x7F21;
// Certificate Body
private static final int TAG_BODY = 0x7F4E;
// Certificate Signature
private static final int TAG_SIGNATURE = 0x5F37;
// Certificate Profile Identifier (CPI)
private static final int TAG_CPI = 0x5F29;
// Certification Authority Reference (CAR)
private static final int TAG_CAR = 0x42;
// Public Key
private static final int TAG_PUBLIC_KEY = 0x7F49;
// Certificate Holder Reference (CHR)
private static final int TAG_CHR = 0x5F20;
// Certificate Holder Authorisation Template (CHAT)
private static final int TAG_CHAT = 0x7F4C;
// Certificate Effective Date
private static final int TAG_EFFECTIVE_DATE = 0x5F25;
// Certificate Expiration Date
private static final int TAG_EXPIRATION_DATE = 0x5F24;
// Certificate Extension
private static final int TAG_EXTENSION = 0x65;
// Certificate body
private byte[] body;
// Certificate signature
private byte[] signature;
// Certificate Profile Identifier (CPI)
private byte[] cpi;
// Certification Authority Reference (CAR)
private PublicKeyReference car;
// Certificate Holder Reference (CHR)
private PublicKeyReference chr;
// Public key
private PublicKey publicKey;
// Certificate Holder Authorization Template (CHAT)
private CHAT chat;
// Certificate Effective Date
private Calendar effectiveDate;
// Certificate Expiration Date
private Calendar expirationDate;
// Certificate Extension
private byte[] extensions;
// TLV encoded certificate
private TLV certificate;
/**
* Create a new Card Verifiable Certificate.
*
* @param cvc CardVerifiableCertificate
* @throws CertificateException
* @throws TLVException
*/
public CardVerifiableCertificate(byte[] cvc) throws CertificateException, TLVException {
this(TLV.fromBER(cvc));
}
/**
* Create a new Card Verifiable Certificate.
*
* @param cvc TLV encoded certificate
* @throws CertificateException
*/
public CardVerifiableCertificate(TLV cvc) throws CertificateException {
try {
// TLV encoded body and signature
certificate = cvc;
// Certificate body
TLV bodyObject = cvc.findChildTags(TAG_BODY).get(0);
body = bodyObject.getValue();
// Certificate signature
TLV signatureObject = cvc.findChildTags(TAG_SIGNATURE).get(0);
signature = signatureObject.getValue();
// Certificate body elements
List<TLV> bodyElements = bodyObject.getChild().asList();
for (Iterator<TLV> it = bodyElements.iterator(); it.hasNext();) {
TLV item = it.next();
int itemTag = (int) item.getTagNumWithClass();
switch (itemTag) {
case TAG_CPI:
cpi = bodyObject.findChildTags(TAG_CPI).get(0).getValue();
break;
case TAG_CAR:
car = new PublicKeyReference(bodyObject.findChildTags(TAG_CAR).get(0).getValue());
break;
case TAG_PUBLIC_KEY:
publicKey = PublicKey.getInstance(bodyObject.findChildTags(TAG_PUBLIC_KEY).get(0));
break;
case TAG_CHR:
chr = new PublicKeyReference(bodyObject.findChildTags(TAG_CHR).get(0).getValue());
break;
case TAG_CHAT:
chat = new CHAT(bodyObject.findChildTags(TAG_CHAT).get(0));
break;
case TAG_EFFECTIVE_DATE:
TLV effectiveDateObject = bodyObject.findChildTags(TAG_EFFECTIVE_DATE).get(0);
effectiveDate = parseDate(effectiveDateObject.getValue());
break;
case TAG_EXPIRATION_DATE:
TLV expirationDateObject = bodyObject.findChildTags(TAG_EXPIRATION_DATE).get(0);
expirationDate = parseDate(expirationDateObject.getValue());
break;
case TAG_EXTENSION:
extensions = bodyObject.findChildTags(TAG_EXTENSION).get(0).getValue();
break;
default:
break;
}
}
verify();
} catch (Exception e) {
throw new CertificateEncodingException("Malformed CardVerifiableCertificates: " + e.getMessage());
}
}
/**
* See See BSI-TR-03110, version 2.10, part 3, section C.
*/
private void verify() throws CertificateEncodingException {
if (body == null || cpi == null || car == null
|| publicKey == null || chr == null
|| chat == null || effectiveDate == null
|| expirationDate == null || signature == null) {
throw new CertificateEncodingException("Malformed CardVerifiableCertificates");
}
}
/*
* Parses the date.
* Format YYMMDD (6 Bytes). Note: Januar = 0 not 1!
*/
private Calendar parseDate(byte[] date) {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 2000 + (date[0] * 10) + date[1]);
cal.set(Calendar.MONTH, (date[2] * 10) + date[3] - 1);
cal.set(Calendar.DATE, (date[4] * 10) + date[5]);
return cal;
}
/**
* Returns the body of the certificate.
*
* @return Body
*/
public byte[] getBody() {
return body;
}
/**
* Returns the signature of the certificate.
*
* @return Signature
*/
public byte[] getSignature() {
return signature;
}
/**
* Returns the Certificate Holder Authorization Template (CHAT).
*
* @return CHAT
*/
public CHAT getCHAT() {
return chat;
}
/**
* Returns the Certificate Holder Reference (CHR).
*
* @return CHR
*/
public PublicKeyReference getCHR() {
return chr;
}
/**
* Returns the Certification Authority Reference (CAR).
*
* @return CAR
*/
public PublicKeyReference getCAR() {
return car;
}
/**
* Returns the public key.
*
* @return Public key
*/
public PublicKey getPublicKey() {
return publicKey;
}
/**
* Returns the Certificate Profile Identifier (CPI).
*
* @return CPI
*/
public byte[] getCPI() {
return cpi;
}
/**
* Returns the effective date of the certificate.
*
* @return Effective date
*/
public Calendar getEffectiveDate() {
return effectiveDate;
}
/**
* Returns the expiration date of the certificate.
*
* @return Expiration date
*/
public Calendar getExpirationDate() {
return expirationDate;
}
/**
* Returns the certificate extensions.
*
* @return Extensions
*/
public byte[] getExtensions() {
return extensions;
}
/**
* Returns the certificate.
*
* @return Certificate
*/
public TLV getCertificate() {
return certificate;
}
/**
* Compares the certificate.
*
* @param certificate Certificate
* @return True if the certificate is equal
*/
public boolean compare(CardVerifiableCertificate certificate) {
return ByteUtils.compare(getSignature(), certificate.getSignature());
}
}