1 13 14 package org.ejbca.core.protocol.cmp; 15 16 import java.io.ByteArrayInputStream ; 17 import java.io.ByteArrayOutputStream ; 18 import java.io.IOException ; 19 import java.security.InvalidKeyException ; 20 import java.security.MessageDigest ; 21 import java.security.NoSuchAlgorithmException ; 22 import java.security.NoSuchProviderException ; 23 import java.security.PrivateKey ; 24 import java.security.Signature ; 25 import java.security.SignatureException ; 26 import java.security.cert.CertificateEncodingException ; 27 import java.security.cert.X509Certificate ; 28 import java.util.Date ; 29 import java.util.Random ; 30 31 import javax.crypto.Mac; 32 import javax.crypto.SecretKey; 33 import javax.crypto.spec.SecretKeySpec; 34 35 import org.apache.log4j.Logger; 36 import org.bouncycastle.asn1.ASN1InputStream; 37 import org.bouncycastle.asn1.DERBitString; 38 import org.bouncycastle.asn1.DERGeneralizedTime; 39 import org.bouncycastle.asn1.DERInteger; 40 import org.bouncycastle.asn1.DERObjectIdentifier; 41 import org.bouncycastle.asn1.DEROctetString; 42 import org.bouncycastle.asn1.DEROutputStream; 43 import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; 44 import org.bouncycastle.asn1.x509.AlgorithmIdentifier; 45 import org.bouncycastle.asn1.x509.GeneralName; 46 import org.bouncycastle.asn1.x509.X509CertificateStructure; 47 import org.bouncycastle.asn1.x509.X509Name; 48 import org.bouncycastle.cms.CMSSignedGenerator; 49 import org.ejbca.core.model.ca.SignRequestException; 50 import org.ejbca.core.model.ra.NotFoundException; 51 import org.ejbca.core.protocol.FailInfo; 52 import org.ejbca.core.protocol.IResponseMessage; 53 import org.ejbca.core.protocol.ResponseStatus; 54 import org.ejbca.util.Base64; 55 import org.ejbca.util.CertTools; 56 57 import com.novosec.pkix.asn1.cmp.CMPObjectIdentifiers; 58 import com.novosec.pkix.asn1.cmp.CertRepMessage; 59 import com.novosec.pkix.asn1.cmp.CertResponse; 60 import com.novosec.pkix.asn1.cmp.PKIBody; 61 import com.novosec.pkix.asn1.cmp.PKIHeader; 62 import com.novosec.pkix.asn1.cmp.PKIMessage; 63 import com.novosec.pkix.asn1.cmp.PKIStatusInfo; 64 import com.novosec.pkix.asn1.crmf.PBMParameter; 65 66 72 public class CmpMessageHelper { 73 private static Logger log = Logger.getLogger(CmpMessageHelper.class); 74 75 public static PKIHeader createPKIHeader(X509Name sender, X509Name recipient, String senderNonce, String recipientNonce, String transactionId) { 76 PKIHeader myPKIHeader = 77 new PKIHeader( 78 new DERInteger(2), 79 new GeneralName(sender), 80 new GeneralName(recipient)); 81 myPKIHeader.setMessageTime(new DERGeneralizedTime(new Date ())); 82 if (senderNonce != null) { 83 myPKIHeader.setSenderNonce(new DEROctetString(Base64.decode(senderNonce.getBytes()))); 84 } 85 if (recipientNonce != null) { 86 myPKIHeader.setRecipNonce(new DEROctetString(Base64.decode(recipientNonce.getBytes()))); 87 } 88 if (transactionId != null) { 89 myPKIHeader.setTransactionID(new DEROctetString(Base64.decode(transactionId.getBytes()))); 90 } 91 return myPKIHeader; 92 } 93 94 public static byte[] signPKIMessage(PKIMessage myPKIMessage, X509Certificate signCert, PrivateKey signKey, String digestAlg, String provider) throws InvalidKeyException , NoSuchProviderException , NoSuchAlgorithmException , SecurityException , SignatureException , IOException , CertificateEncodingException { 95 log.debug(">signPKIMessage()"); 96 X509CertificateStructure signStruct = X509CertificateStructure.getInstance(new ASN1InputStream(new ByteArrayInputStream (signCert.getEncoded())).readObject()); 97 CmpMessageHelper.buildCertBasedPKIProtection( myPKIMessage, signStruct, signKey, digestAlg, provider); 98 99 log.debug("<signPKIMessage()"); 100 return CmpMessageHelper.pkiMessageToByteArray(myPKIMessage); 102 } 103 104 public static void buildCertBasedPKIProtection( PKIMessage pKIMessage, X509CertificateStructure cert, PrivateKey key, String digestAlg, String provider ) 105 throws NoSuchProviderException , NoSuchAlgorithmException , SecurityException , SignatureException , InvalidKeyException 106 { 107 DERObjectIdentifier oid = PKCSObjectIdentifiers.sha1WithRSAEncryption; 109 if (digestAlg.equals(CMSSignedGenerator.DIGEST_SHA256)) { 110 oid = PKCSObjectIdentifiers.sha256WithRSAEncryption; 111 } 112 if (digestAlg.equals(CMSSignedGenerator.DIGEST_MD5)) { 113 oid = PKCSObjectIdentifiers.md5WithRSAEncryption; 114 } 115 pKIMessage.getHeader().setProtectionAlg( new AlgorithmIdentifier(oid) ); 116 117 Signature sig = Signature.getInstance( pKIMessage.getHeader().getProtectionAlg().getObjectId().getId(), provider ); 118 sig.initSign(key); 119 sig.update( pKIMessage.getProtectedBytes() ); 120 121 pKIMessage.setProtection( new DERBitString(sig.sign()) ); 122 pKIMessage.addExtraCert( cert ); 123 } 124 125 public static byte[] protectPKIMessageWithPBE(PKIMessage msg, String keyId, String raSecret, String digestAlgId, String macAlgId, int iterationCount) throws NoSuchAlgorithmException , NoSuchProviderException , InvalidKeyException , IOException { 126 log.debug(">protectPKIMessageWithPBE()"); 127 PKIHeader head = msg.getHeader(); 129 head.setSenderKID(new DEROctetString(keyId.getBytes())); 130 AlgorithmIdentifier owfAlg = new AlgorithmIdentifier(digestAlgId); 133 DERInteger iteration = new DERInteger(iterationCount); 135 AlgorithmIdentifier macAlg = new AlgorithmIdentifier(macAlgId); 138 byte[] saltbytes = createSenderNonce(); 140 DEROctetString derSalt = new DEROctetString(saltbytes); 141 142 String objectId = CMPObjectIdentifiers.passwordBasedMac.getId(); 145 PBMParameter pp = new PBMParameter(derSalt, owfAlg, iteration, macAlg); 146 AlgorithmIdentifier pAlg = new AlgorithmIdentifier(new DERObjectIdentifier(objectId), pp); 147 head.setProtectionAlg(pAlg); 148 PKIBody body = msg.getBody(); 149 PKIMessage ret = new PKIMessage(head, body); 150 151 byte[] rasecret = raSecret.getBytes(); 153 byte[] basekey = new byte[rasecret.length + saltbytes.length]; 154 for (int i = 0; i < rasecret.length; i++) { 155 basekey[i] = rasecret[i]; 156 } 157 for (int i = 0; i < saltbytes.length; i++) { 158 basekey[rasecret.length+i] = saltbytes[i]; 159 } 160 MessageDigest dig = MessageDigest.getInstance(owfAlg.getObjectId().getId(), "BC"); 162 for (int i = 0; i < iterationCount; i++) { 163 basekey = dig.digest(basekey); 164 dig.reset(); 165 } 166 String macOid = macAlg.getObjectId().getId(); 168 byte[] protectedBytes = ret.getProtectedBytes(); 169 Mac mac = Mac.getInstance(macOid, "BC"); 170 SecretKey key = new SecretKeySpec(basekey, macOid); 171 mac.init(key); 172 mac.reset(); 173 mac.update(protectedBytes, 0, protectedBytes.length); 174 byte[] out = mac.doFinal(); 175 DERBitString bs = new DERBitString(out); 176 177 ret.setProtection(bs); 179 180 log.debug("<protectPKIMessageWithPBE()"); 181 return CmpMessageHelper.pkiMessageToByteArray(ret); 183 } 184 185 public static byte[] pkiMessageToByteArray(PKIMessage msg) throws IOException { 186 ByteArrayOutputStream baos = new ByteArrayOutputStream (); 188 DEROutputStream mout = new DEROutputStream( baos ); 189 mout.writeObject( msg ); 190 mout.close(); 191 return baos.toByteArray(); 192 193 } 194 195 199 public static byte[] createSenderNonce() { 200 byte[] senderNonce = new byte[16]; 202 Random randomSource; 203 randomSource = new Random (); 204 randomSource.nextBytes(senderNonce); 205 return senderNonce; 206 } 207 215 public static IResponseMessage createUnprotectedErrorMessage(BaseCmpMessage msg, ResponseStatus status, FailInfo failInfo, String failText) { 216 if (log.isDebugEnabled()) { 218 log.debug("Creating an unprotected error message with status="+status.getValue()+", failInfo="+failInfo+", failText="+failText); 219 } 220 CmpErrorResponseMessage resp = new CmpErrorResponseMessage(); 221 resp.setSenderNonce(new String (Base64.encode(CmpMessageHelper.createSenderNonce()))); 222 if (msg != null) { 223 resp.setRecipientNonce(msg.getSenderNonce()); 224 resp.setSender(msg.getRecipient()); 225 resp.setRecipient(msg.getSender()); 226 resp.setTransactionId(msg.getTransactionId()); 227 } else { 228 resp.setSender(new GeneralName(CertTools.stringToBcX509Name("CN=Failure Sender"))); 230 resp.setRecipient(new GeneralName(CertTools.stringToBcX509Name("CN=Failure Recipient"))); 231 } 232 resp.setFailInfo(failInfo); 233 resp.setStatus( status); 234 resp.setFailText(failText); 235 try { 236 resp.create(); 237 } catch (InvalidKeyException e) { 238 log.error("Exception during CMP processing: ", e); 239 } catch (NoSuchAlgorithmException e) { 240 log.error("Exception during CMP processing: ", e); 241 } catch (NoSuchProviderException e) { 242 log.error("Exception during CMP processing: ", e); 243 } catch (SignRequestException e) { 244 log.error("Exception during CMP processing: ", e); 245 } catch (NotFoundException e) { 246 log.error("Exception during CMP processing: ", e); 247 } catch (IOException e) { 248 log.error("Exception during CMP processing: ", e); 249 } 250 return resp; 251 } 252 253 261 public static PKIBody createCertRequestRejectBody(PKIHeader header, PKIStatusInfo info, int requestId, int requestType) { 262 if (log.isDebugEnabled()) { 264 log.debug("Creating a cert request rejection message"); 265 } 266 267 log.debug("Creating a CertRepMessage 'rejected'"); 268 269 277 278 CertResponse myCertResponse = new CertResponse(new DERInteger(requestId), info); 279 CertRepMessage myCertRepMessage = new CertRepMessage(myCertResponse); 280 281 282 int respType = requestType + 1; log.debug("Creating response body of type respType."); 284 PKIBody myPKIBody = new PKIBody(myCertRepMessage, respType); 285 286 return myPKIBody; 287 } 288 } 289 | Popular Tags |