/****************************************************************************
* 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.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.List;
import org.openecard.common.tlv.TLV;
import org.openecard.common.util.ByteUtils;
import org.openecard.crypto.common.asn1.eac.oid.CVCertificatesObjectIdentifier;
import org.openecard.crypto.common.asn1.eac.oid.TAObjectIdentifier;
import org.openecard.crypto.common.asn1.utils.ObjectIdentifierUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author Moritz Horsch <horsch@cdc.informatik.tu-darmstadt.de>
*/
public class CardVerifiableCertificateVerifier {
private static final Logger _logger = LoggerFactory.getLogger(CardVerifiableCertificateVerifier.class);
/**
* Verifies that the certificate description matches the certificate.
* Verification is done by hashing the description and comparing it
* to the checksum containing in the certificate extention.
* See BSI-TR-03110, version 2.10, part 3, section C.3.
*
* @param certificate Certificate
* @param description Description
* @throws CertificateException
*/
public static void verify(CardVerifiableCertificate certificate, CertificateDescription description) throws CertificateException {
try {
byte[] extentions = certificate.getExtensions();
TLV extentionObject = TLV.fromBER(extentions);
List<TLV> list = extentionObject.asList();
for (TLV item : list) {
String oid = ObjectIdentifierUtils.toString(item.getValue());
if (oid.equals(CVCertificatesObjectIdentifier.id_description)) {
List<TLV> hashObjects = item.findChildTags(0x80);
if (hashObjects != null && !hashObjects.isEmpty()) {
TLV hashObject = hashObjects.get(0);
MessageDigest md = selectDigest(certificate.getPublicKey().getObjectIdentifier());
byte[] hash = md.digest(description.getEncoded());
if (!ByteUtils.compare(hash, hashObject.getValue())) {
throw new CertificateException("The checksum of the certificate description cannot be verified!");
}
}
} else if (oid.equals(CVCertificatesObjectIdentifier.id_sector)) {
List<TLV> firstPublicKeyObjects = item.findChildTags(0x80);
if (firstPublicKeyObjects != null && !firstPublicKeyObjects.isEmpty()) {
TLV firstPublicKeyObject = firstPublicKeyObjects.get(0);
//TODO
}
List<TLV> secondPublicKeyObjects = item.findChildTags(0x81);
if (secondPublicKeyObjects != null && !secondPublicKeyObjects.isEmpty()) {
TLV secondPublicKeyObject = secondPublicKeyObjects.get(0);
//TODO
}
} else {
_logger.warn("Unknown OID: {} ", oid);
}
}
} catch (Exception e) {
_logger.debug(e.getMessage());
throw new CertificateException("Verification failed", e);
}
}
private static MessageDigest selectDigest(String oid) throws NoSuchAlgorithmException {
if (oid.equals(TAObjectIdentifier.id_TA_ECDSA_SHA_1)
|| oid.equals(TAObjectIdentifier.id_TA_RSA_PSS_SHA_1)
|| oid.equals(TAObjectIdentifier.id_TA_RSA_v1_5_SHA_1)) {
return MessageDigest.getInstance("SHA-1");
} else if (oid.equals(TAObjectIdentifier.id_TA_ECDSA_SHA_224)) {
return MessageDigest.getInstance("SHA-224");
} else if (oid.equals(TAObjectIdentifier.id_TA_ECDSA_SHA_256)
|| oid.equals(TAObjectIdentifier.id_TA_RSA_PSS_SHA_256)
|| oid.equals(TAObjectIdentifier.id_TA_RSA_PSS_SHA_256)) {
return MessageDigest.getInstance("SHA-256");
} else if (oid.equals(TAObjectIdentifier.id_TA_ECDSA_SHA_384)
|| oid.equals(TAObjectIdentifier.id_TA_RSA_PSS_SHA_1)
|| oid.equals(TAObjectIdentifier.id_TA_RSA_PSS_SHA_1)) {
return MessageDigest.getInstance("SHA-384");
} else if (oid.equals(TAObjectIdentifier.id_TA_ECDSA_SHA_512)
|| oid.equals(TAObjectIdentifier.id_TA_RSA_PSS_SHA_512)
|| oid.equals(TAObjectIdentifier.id_TA_RSA_PSS_SHA_512)) {
return MessageDigest.getInstance("SHA-512");
}
throw new NoSuchAlgorithmException();
}
}