1 13 14 package org.ejbca.core.model.ca.caadmin.extendedcaservices; 15 16 import java.io.IOException ; 17 import java.io.UnsupportedEncodingException ; 18 import java.security.InvalidAlgorithmParameterException ; 19 import java.security.KeyPair ; 20 import java.security.KeyStore ; 21 import java.security.NoSuchAlgorithmException ; 22 import java.security.NoSuchProviderException ; 23 import java.security.PrivateKey ; 24 import java.security.cert.CertStore ; 25 import java.security.cert.CertStoreException ; 26 import java.security.cert.Certificate ; 27 import java.security.cert.CollectionCertStoreParameters ; 28 import java.security.cert.X509Certificate ; 29 import java.util.ArrayList ; 30 import java.util.HashMap ; 31 import java.util.List ; 32 33 import org.apache.log4j.Logger; 34 import org.bouncycastle.cms.CMSException; 35 import org.bouncycastle.cms.CMSProcessable; 36 import org.bouncycastle.cms.CMSProcessableByteArray; 37 import org.bouncycastle.cms.CMSSignedData; 38 import org.bouncycastle.cms.CMSSignedDataGenerator; 39 import org.bouncycastle.cms.CMSSignedGenerator; 40 import org.ejbca.core.ejb.ServiceLocator; 41 import org.ejbca.core.model.InternalResources; 42 import org.ejbca.core.model.ca.caadmin.CA; 43 import org.ejbca.core.model.ca.caadmin.IllegalKeyStoreException; 44 import org.ejbca.core.model.ca.certificateprofiles.XKMSCertificateProfile; 45 import org.ejbca.core.model.ra.UserDataVO; 46 import org.ejbca.util.Base64; 47 import org.ejbca.util.CertTools; 48 import org.ejbca.util.KeyTools; 49 50 51 52 57 public class CmsCAService extends ExtendedCAService implements java.io.Serializable { 58 59 66 private static final long serialVersionUID = 5273836489592921586L; 67 68 private static Logger m_log = Logger.getLogger(CmsCAService.class); 69 70 private static final InternalResources intres = InternalResources.getInstance(); 71 72 public static final float LATEST_VERSION = 1; 73 74 public static final String SERVICENAME = "CMSCASERVICE"; 75 76 private PrivateKey privKey = null; 77 private List certificatechain = null; 78 79 private CmsCAServiceInfo info = null; 80 81 private static final String KEYSTORE = "keystore"; 82 private static final String KEYSPEC = "keyspec"; 83 private static final String KEYALGORITHM = "keyalgorithm"; 84 private static final String SUBJECTDN = "subjectdn"; 85 private static final String SUBJECTALTNAME = "subjectaltname"; 86 87 private static final String PRIVATESIGNKEYALIAS = "privatesignkeyalias"; 88 89 90 91 public CmsCAService(ExtendedCAServiceInfo serviceinfo) { 92 m_log.debug("CmsCAService : constructor " + serviceinfo.getStatus()); 93 CertTools.installBCProvider(); 94 CmsCAServiceInfo info = (CmsCAServiceInfo) serviceinfo; 96 data = new HashMap (); 97 data.put(EXTENDEDCASERVICETYPE, new Integer (ExtendedCAServiceInfo.TYPE_CMSEXTENDEDSERVICE)); 98 99 data.put(KEYSPEC, info.getKeySpec()); 100 data.put(KEYALGORITHM, info.getKeyAlgorithm()); 101 setSubjectDN(info.getSubjectDN()); 102 setSubjectAltName(info.getSubjectAltName()); 103 setStatus(serviceinfo.getStatus()); 104 105 data.put(VERSION, new Float (LATEST_VERSION)); 106 } 107 108 public CmsCAService(HashMap data) throws IllegalArgumentException , IllegalKeyStoreException { 109 CertTools.installBCProvider(); 110 loadData(data); 111 if(data.get(KEYSTORE) != null){ 112 String keystorepass = ServiceLocator.getInstance().getString("java:comp/env/CMSKeyStorePass"); 114 if (keystorepass == null) 115 throw new IllegalArgumentException ("Missing CMSKeyStorePass property."); 116 117 try { 118 m_log.debug("Loading CMS keystore"); 119 KeyStore keystore=KeyStore.getInstance("PKCS12", "BC"); 120 keystore.load(new java.io.ByteArrayInputStream (Base64.decode(((String ) data.get(KEYSTORE)).getBytes())),keystorepass.toCharArray()); 121 m_log.debug("Finished loading CMS keystore"); 122 123 this.privKey = (PrivateKey ) keystore.getKey(PRIVATESIGNKEYALIAS, null); 124 this.certificatechain = CertTools.getCertCollectionFromArray(keystore.getCertificateChain(PRIVATESIGNKEYALIAS), "SUN"); 128 this.info = new CmsCAServiceInfo(getStatus(), 129 getSubjectDN(), 130 getSubjectAltName(), 131 (String )data.get(KEYSPEC), 132 (String ) data.get(KEYALGORITHM), 133 this.certificatechain); 134 135 } catch (Exception e) { 136 throw new IllegalKeyStoreException(e); 137 } 138 139 data.put(EXTENDEDCASERVICETYPE, new Integer (ExtendedCAServiceInfo.TYPE_CMSEXTENDEDSERVICE)); 140 } 141 } 142 143 144 145 148 public void init(CA ca) throws Exception { 149 m_log.debug("CmsCAService : init"); 150 String keystorepass = ServiceLocator.getInstance().getString("java:comp/env/CMSKeyStorePass"); 152 if (keystorepass == null) 153 throw new IllegalArgumentException ("Missing CMSKeyStorePass property."); 154 155 CmsCAServiceInfo info = (CmsCAServiceInfo) getExtendedCAServiceInfo(); 157 158 KeyStore keystore = KeyStore.getInstance("PKCS12", "BC"); 160 keystore.load(null, null); 161 162 KeyPair cmskeys = KeyTools.genKeys(info.getKeySpec(), info.getKeyAlgorithm()); 163 164 Certificate certificate = 165 ca.generateCertificate(new UserDataVO("NOUSERNAME", 166 info.getSubjectDN(), 167 0, 168 info.getSubjectAltName(), 169 "NOEMAIL", 170 0,0,0,0, null,null,0,0,null) 171 , cmskeys.getPublic(), 172 -1, ca.getValidity(), 174 new XKMSCertificateProfile()); 176 certificatechain = new ArrayList (); 177 certificatechain.add(certificate); 178 certificatechain.addAll(ca.getCertificateChain()); 179 this.privKey = cmskeys.getPrivate(); 180 181 keystore.setKeyEntry(PRIVATESIGNKEYALIAS,cmskeys.getPrivate(),null,(Certificate []) certificatechain.toArray(new Certificate [certificatechain.size()])); 182 java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream (); 183 keystore.store(baos, keystorepass.toCharArray()); 184 data.put(KEYSTORE, new String (Base64.encode(baos.toByteArray()))); 185 187 setStatus(info.getStatus()); 188 this.info = new CmsCAServiceInfo(info.getStatus(), 189 getSubjectDN(), 190 getSubjectAltName(), 191 (String )data.get(KEYSPEC), 192 (String ) data.get(KEYALGORITHM), 193 certificatechain); 194 } 195 196 199 public void update(ExtendedCAServiceInfo serviceinfo, CA ca) throws Exception { 200 CmsCAServiceInfo info = (CmsCAServiceInfo) serviceinfo; 201 m_log.debug("CmsCAService : update " + serviceinfo.getStatus()); 202 setStatus(serviceinfo.getStatus()); 203 if(info.getRenewFlag()){ 204 this.init(ca); 206 } 207 208 this.info = new CmsCAServiceInfo(serviceinfo.getStatus(), 210 getSubjectDN(), 211 getSubjectAltName(), 212 (String ) data.get(KEYSPEC), 213 (String ) data.get(KEYALGORITHM), 214 certificatechain); 215 } 216 217 218 219 222 public ExtendedCAServiceResponse extendedService(ExtendedCAServiceRequest request) throws ExtendedCAServiceRequestException, IllegalExtendedCAServiceRequestException,ExtendedCAServiceNotActiveException { 223 m_log.debug(">extendedService"); 224 if (!(request instanceof CmsCAServiceRequest)) { 225 throw new IllegalExtendedCAServiceRequestException(); 226 } 227 if (this.getStatus() != ExtendedCAServiceInfo.STATUS_ACTIVE) { 228 String msg = intres.getLocalizedMessage("caservice.notactive"); 229 m_log.error(msg); 230 throw new ExtendedCAServiceNotActiveException(msg); 231 } 232 ExtendedCAServiceResponse returnval = null; 233 X509Certificate signerCert = (X509Certificate ) certificatechain.get(0); 234 CmsCAServiceRequest serviceReq = (CmsCAServiceRequest)request; 235 236 CMSSignedDataGenerator gen1 = new CMSSignedDataGenerator(); 238 try { 239 CertStore certs; 241 certs = CertStore.getInstance("Collection", 242 new CollectionCertStoreParameters (certificatechain), "BC"); 243 gen1.addCertificatesAndCRLs(certs); 244 gen1.addSigner(privKey, signerCert, CMSSignedGenerator.DIGEST_SHA1); 245 CMSProcessable msg = new CMSProcessableByteArray(serviceReq.getDoc()); 246 CMSSignedData s = gen1.generate(msg, true, "BC"); 247 byte[] resp = s.getEncoded(); 248 returnval = new CmsCAServiceResponse(resp); 249 } catch (InvalidAlgorithmParameterException e) { 250 m_log.error("Error in CmsCAService", e); 251 throw new ExtendedCAServiceRequestException(e); 252 } catch (NoSuchAlgorithmException e) { 253 m_log.error("Error in CmsCAService", e); 254 throw new ExtendedCAServiceRequestException(e); 255 } catch (NoSuchProviderException e) { 256 m_log.error("Error in CmsCAService", e); 257 throw new ExtendedCAServiceRequestException(e); 258 } catch (CertStoreException e) { 259 m_log.error("Error in CmsCAService", e); 260 throw new ExtendedCAServiceRequestException(e); 261 } catch (CMSException e) { 262 m_log.error("Error in CmsCAService", e); 263 throw new ExtendedCAServiceRequestException(e); 264 } catch (IOException e) { 265 m_log.error("Error in CmsCAService", e); 266 throw new ExtendedCAServiceRequestException(e); 267 } 268 269 m_log.debug("<extendedService"); 270 return returnval; 271 } 272 273 274 public float getLatestVersion() { 275 return LATEST_VERSION; 276 } 277 278 public void upgrade() { 279 if(Float.compare(LATEST_VERSION, getVersion()) != 0) { 280 282 data.put(VERSION, new Float (LATEST_VERSION)); 283 } 284 } 285 286 289 public ExtendedCAServiceInfo getExtendedCAServiceInfo() { 290 if(info == null){ 291 info = new CmsCAServiceInfo(getStatus(), 292 getSubjectDN(), 293 getSubjectAltName(), 294 (String ) data.get(KEYSPEC), 295 (String ) data.get(KEYALGORITHM), 296 certificatechain); 297 } 298 299 return this.info; 300 } 301 302 303 public String getSubjectDN(){ 304 String retval = null; 305 String str = (String )data.get(SUBJECTDN); 306 try { 307 retval = new String (Base64.decode((str).getBytes("UTF-8"))); 308 } catch (UnsupportedEncodingException e) { 309 m_log.error("Could not decode data from Base64",e); 310 } catch (ArrayIndexOutOfBoundsException e) { 311 m_log.debug("Old non base64 encoded DN: "+str); 313 retval = str; 314 } 315 316 return retval; 317 } 318 319 public void setSubjectDN(String dn){ 320 321 try { 322 data.put(SUBJECTDN,new String (Base64.encode(dn.getBytes("UTF-8"),false))); 323 } catch (UnsupportedEncodingException e) { 324 m_log.error("Could not encode data from Base64",e); 325 } 326 } 327 328 public String getSubjectAltName(){ 329 String retval = null; 330 String str= (String ) data.get(SUBJECTALTNAME); 331 try { 332 retval = new String (Base64.decode((str).getBytes("UTF-8"))); 333 } catch (UnsupportedEncodingException e) { 334 m_log.error("Could not decode data from Base64",e); 335 } catch (ArrayIndexOutOfBoundsException e) { 336 m_log.debug("Old non base64 encoded altname: "+str); 338 retval = str; 339 } 340 341 return retval; 342 } 343 344 public void setSubjectAltName(String dn){ 345 346 try { 347 data.put(SUBJECTALTNAME,new String (Base64.encode(dn.getBytes("UTF-8"), false))); 348 } catch (UnsupportedEncodingException e) { 349 m_log.error("Could not encode data from Base64",e); 350 } 351 } 352 } 353 354 | Popular Tags |