/*************************************************************************
* *
* EJBCA Community: The OpenSource Certificate Authority *
* *
* This software is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or any later version. *
* *
* See terms of license at gnu.org. *
* *
*************************************************************************/
package org.ejbca.core.protocol.cmp;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.SignatureException;
import java.security.cert.CRL;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.util.Collection;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.cmp.PKIBody;
import org.bouncycastle.asn1.cmp.PKIHeaderBuilder;
import org.bouncycastle.asn1.cmp.PKIMessage;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.cms.CMSSignedGenerator;
import org.cesecore.certificates.certificate.request.FailInfo;
import org.cesecore.certificates.certificate.request.RequestMessage;
import org.cesecore.certificates.certificate.request.ResponseMessage;
import org.cesecore.certificates.certificate.request.ResponseStatus;
import org.cesecore.util.CertTools;
/**
* A very simple confirmation message, no protection and a nullbody
* @author tomas
* @version $Id: CmpConfirmResponseMessage.java 28875 2018-05-08 13:44:40Z anatom $
*/
public class CmpConfirmResponseMessage extends BaseCmpMessage implements ResponseMessage {
/**
* Determines if a de-serialized file is compatible with this class.
*
* Maintainers must change this value if and only if the new version
* of this class is not compatible with old versions. See Sun docs
* for details.
*
*/
static final long serialVersionUID = 10003L;
private static final Logger log = Logger.getLogger(CmpConfirmResponseMessage.class);
/** Default digest algorithm for CMP response message, can be overridden */
private String digestAlg = CMSSignedGenerator.DIGEST_SHA1;
/** The default provider is BC, if nothing else is specified when setting SignKeyInfo */
private String provider = "BC";
/** Certificate for the signer of the response message (CA) */
private transient Collection signCertChain = null;
/** Private key used to sign the response message */
private transient PrivateKey signKey = null;
/** The encoded response message */
private byte[] responseMessage = null;
@Override
public void setCrl(CRL crl) {
}
@Override
public void setIncludeCACert(boolean incCACert) {
}
@Override
public void setCACert(Certificate cACert) {
}
@Override
public byte[] getResponseMessage() {
return responseMessage;
}
@Override
public void setStatus(ResponseStatus status) {
}
@Override
public ResponseStatus getStatus() {
return ResponseStatus.SUCCESS;
}
@Override
public void setFailInfo(FailInfo failInfo) {
}
@Override
public FailInfo getFailInfo() {
return null;
}
@Override
public void setFailText(String failText) {
}
@Override
public String getFailText() {
return null;
}
@Override
public boolean create() throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException {
final PKIHeaderBuilder myPKIHeader = CmpMessageHelper.createPKIHeaderBuilder(getSender(), getRecipient(), getSenderNonce(), getRecipientNonce(), getTransactionId());
final PKIBody myPKIBody = new PKIBody(19, DERNull.INSTANCE);
PKIMessage myPKIMessage = null;
if ((getPbeDigestAlg() != null) && (getPbeMacAlg() != null) && (getPbeKeyId() != null) && (getPbeKey() != null) ) {
myPKIHeader.setProtectionAlg(new AlgorithmIdentifier(new ASN1ObjectIdentifier(getPbeDigestAlg())));
myPKIMessage = new PKIMessage(myPKIHeader.build(), myPKIBody);
responseMessage = CmpMessageHelper.protectPKIMessageWithPBE(myPKIMessage, getPbeKeyId(), getPbeKey(), getPbeDigestAlg(), getPbeMacAlg(), getPbeIterationCount());
} else {
if ((signCertChain != null) && (signCertChain.size() > 0) && (signKey != null)) {
try {
myPKIHeader.setProtectionAlg(new AlgorithmIdentifier(new ASN1ObjectIdentifier(digestAlg)));
if (CollectionUtils.isNotEmpty(signCertChain)) {
// set sender Key ID as well when the response is signed, so the signer (CA) can have multiple certificates out there
// with the same DN but different keys
myPKIHeader.setSenderKID(CertTools.getSubjectKeyId(signCertChain.iterator().next()));
}
myPKIMessage = new PKIMessage(myPKIHeader.build(), myPKIBody);
responseMessage = CmpMessageHelper.signPKIMessage(myPKIMessage, signCertChain, signKey, digestAlg, provider);
} catch (CertificateEncodingException e) {
log.error("Error creating CmpConfirmMessage: ", e);
} catch (SecurityException e) {
log.error("Error creating CmpConfirmMessage: ", e);
} catch (SignatureException e) {
log.error("Error creating CmpConfirmMessage: ", e);
}
} else {
if (log.isDebugEnabled()) {
log.debug("Not signing CMP Confirm Response, because signCert or signKey is not set.");
}
}
// If we could not create the signed response message, create a non-protected one instead.
if (responseMessage == null) {
myPKIMessage = new PKIMessage(myPKIHeader.build(), myPKIBody);
responseMessage = CmpMessageHelper.pkiMessageToByteArray(myPKIMessage);
}
}
return true;
}
@Override
public boolean requireSignKeyInfo() {
return false;
}
@Override
public void setSignKeyInfo(Collection certs, PrivateKey key, String provider) {
this.signCertChain = certs;
this.signKey = key;
if (provider != null) {
this.provider = provider;
}
}
@Override
public void setRecipientKeyInfo(byte[] recipientKeyInfo) {
}
@Override
public void setPreferredDigestAlg(String digest) {
if(StringUtils.isNotEmpty(digest)) {
this.digestAlg = digest;
}
}
@Override
public void setRequestType(int reqtype) {
}
@Override
public void setRequestId(int reqid) {
}
@Override
public void setProtectionParamsFromRequest(RequestMessage reqMsg) {
}
}