1 13 14 package org.ejbca.core.model.ca.caadmin.extendedcaservices; 15 16 import java.io.UnsupportedEncodingException ; 17 import java.security.KeyPair ; 18 import java.security.KeyStore ; 19 import java.security.NoSuchProviderException ; 20 import java.security.PrivateKey ; 21 import java.security.PublicKey ; 22 import java.security.cert.Certificate ; 23 import java.security.cert.X509Certificate ; 24 import java.util.ArrayList ; 25 import java.util.Arrays ; 26 import java.util.HashMap ; 27 import java.util.List ; 28 29 import org.apache.log4j.Logger; 30 import org.bouncycastle.ocsp.BasicOCSPResp; 31 import org.bouncycastle.ocsp.OCSPException; 32 import org.ejbca.core.ejb.ServiceLocator; 33 import org.ejbca.core.model.InternalResources; 34 import org.ejbca.core.model.ca.NotSupportedException; 35 import org.ejbca.core.model.ca.caadmin.CA; 36 import org.ejbca.core.model.ca.caadmin.IllegalKeyStoreException; 37 import org.ejbca.core.model.ca.certificateprofiles.OCSPSignerCertificateProfile; 38 import org.ejbca.core.model.ra.UserDataVO; 39 import org.ejbca.core.protocol.ocsp.OCSPUtil; 40 import org.ejbca.util.Base64; 41 import org.ejbca.util.CertTools; 42 import org.ejbca.util.KeyTools; 43 44 45 46 50 public class OCSPCAService extends ExtendedCAService implements java.io.Serializable { 51 52 private static Logger m_log = Logger.getLogger(OCSPCAService.class); 53 54 private static final InternalResources intres = InternalResources.getInstance(); 55 56 public static final float LATEST_VERSION = 2; 57 58 public static final String SERVICENAME = "OCSPCASERVICE"; 59 60 61 private PrivateKey ocspsigningkey = null; 62 private List ocspcertificatechain = null; 63 64 private OCSPCAServiceInfo info = null; 65 66 private static final String OCSPKEYSTORE = "ocspkeystore"; 67 private static final String KEYSPEC = "keyspec"; 68 private static final String KEYALGORITHM = "keyalgorithm"; 69 private static final String SUBJECTDN = "subjectdn"; 70 private static final String SUBJECTALTNAME = "subjectaltname"; 71 72 private static final String PRIVATESIGNKEYALIAS = "privatesignkeyalias"; 73 74 75 private static final String KEYSIZE = "keysize"; 76 77 public OCSPCAService(ExtendedCAServiceInfo serviceinfo) { 78 m_log.debug("OCSPCAService : constructor " + serviceinfo.getStatus()); 79 CertTools.installBCProvider(); 80 OCSPCAServiceInfo info = (OCSPCAServiceInfo) serviceinfo; 82 data = new HashMap (); 83 data.put(EXTENDEDCASERVICETYPE, new Integer (ExtendedCAServiceInfo.TYPE_OCSPEXTENDEDSERVICE)); 84 85 data.put(KEYSPEC, info.getKeySpec()); 86 data.put(KEYALGORITHM, info.getKeyAlgorithm()); 87 setSubjectDN(info.getSubjectDN()); 88 setSubjectAltName(info.getSubjectAltName()); 89 setStatus(serviceinfo.getStatus()); 90 91 data.put(VERSION, new Float (LATEST_VERSION)); 92 } 93 94 public OCSPCAService(HashMap data) throws IllegalArgumentException , IllegalKeyStoreException { 95 CertTools.installBCProvider(); 96 loadData(data); 97 if(data.get(OCSPKEYSTORE) != null){ 98 String keystorepass = ServiceLocator.getInstance().getString("java:comp/env/OCSPKeyStorePass"); 100 if (keystorepass == null) 101 throw new IllegalArgumentException ("Missing OCSPKeyStorePass property."); 102 103 try { 104 m_log.debug("Loading OCSP keystore"); 105 KeyStore keystore=KeyStore.getInstance("PKCS12", "BC"); 106 keystore.load(new java.io.ByteArrayInputStream (Base64.decode(((String ) data.get(OCSPKEYSTORE)).getBytes())),keystorepass.toCharArray()); 107 m_log.debug("Finished loading OCSP keystore"); 108 109 this.ocspsigningkey = (PrivateKey ) keystore.getKey(PRIVATESIGNKEYALIAS, null); 110 this.ocspcertificatechain = CertTools.getCertCollectionFromArray(keystore.getCertificateChain(PRIVATESIGNKEYALIAS), "SUN"); 114 this.info = new OCSPCAServiceInfo(getStatus(), 115 getSubjectDN(), 116 getSubjectAltName(), 117 (String )data.get(KEYSPEC), 118 (String ) data.get(KEYALGORITHM), 119 this.ocspcertificatechain); 120 121 } catch (Exception e) { 122 throw new IllegalKeyStoreException(e); 123 } 124 125 data.put(EXTENDEDCASERVICETYPE, new Integer (ExtendedCAServiceInfo.TYPE_OCSPEXTENDEDSERVICE)); 126 } 127 } 128 129 130 131 134 public void init(CA ca) throws Exception { 135 m_log.debug("OCSPCAService : init "); 136 String keystorepass = ServiceLocator.getInstance().getString("java:comp/env/OCSPKeyStorePass"); 138 if (keystorepass == null) 139 throw new IllegalArgumentException ("Missing OCSPKeyPass property."); 140 141 OCSPCAServiceInfo info = (OCSPCAServiceInfo) getExtendedCAServiceInfo(); 143 144 KeyStore keystore = KeyStore.getInstance("PKCS12", "BC"); 146 keystore.load(null, null); 147 148 KeyPair ocspkeys = KeyTools.genKeys(info.getKeySpec(), info.getKeyAlgorithm()); 149 150 Certificate ocspcertificate = 151 ca.generateCertificate(new UserDataVO("NOUSERNAME", 152 info.getSubjectDN(), 153 0, 154 info.getSubjectAltName(), 155 "NOEMAIL", 156 0,0,0,0, null,null,0,0,null) 157 , ocspkeys.getPublic(), 158 -1, ca.getValidity(), 160 new OCSPSignerCertificateProfile()); 161 162 ocspcertificatechain = new ArrayList (); 163 ocspcertificatechain.add(ocspcertificate); 164 ocspcertificatechain.addAll(ca.getCertificateChain()); 165 this.ocspsigningkey = ocspkeys.getPrivate(); 166 167 keystore.setKeyEntry(PRIVATESIGNKEYALIAS,ocspkeys.getPrivate(),null,(Certificate []) ocspcertificatechain.toArray(new Certificate [ocspcertificatechain.size()])); 168 java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream (); 169 keystore.store(baos, keystorepass.toCharArray()); 170 data.put(OCSPKEYSTORE, new String (Base64.encode(baos.toByteArray()))); 171 173 setStatus(info.getStatus()); 174 this.info = new OCSPCAServiceInfo(info.getStatus(), 175 getSubjectDN(), 176 getSubjectAltName(), 177 (String )data.get(KEYSPEC), 178 (String ) data.get(KEYALGORITHM), 179 ocspcertificatechain); 180 181 } 182 183 186 public void update(ExtendedCAServiceInfo serviceinfo, CA ca) throws Exception { 187 OCSPCAServiceInfo info = (OCSPCAServiceInfo) serviceinfo; 188 m_log.debug("OCSPCAService : update " + serviceinfo.getStatus()); 189 setStatus(serviceinfo.getStatus()); 190 if(info.getRenewFlag()){ 191 this.init(ca); 193 } 194 195 this.info = new OCSPCAServiceInfo(serviceinfo.getStatus(), 197 getSubjectDN(), 198 getSubjectAltName(), 199 (String ) data.get(KEYSPEC), 200 (String ) data.get(KEYALGORITHM), 201 this.ocspcertificatechain); 202 203 } 204 205 206 207 210 public ExtendedCAServiceResponse extendedService(ExtendedCAServiceRequest request) throws ExtendedCAServiceRequestException, IllegalExtendedCAServiceRequestException,ExtendedCAServiceNotActiveException { 211 m_log.debug(">extendedService"); 212 if (!(request instanceof OCSPCAServiceRequest)) { 213 throw new IllegalExtendedCAServiceRequestException(); 214 } 215 if (this.getStatus() != ExtendedCAServiceInfo.STATUS_ACTIVE) { 216 String msg = intres.getLocalizedMessage("caservice.notactive"); 217 m_log.error(msg); 218 throw new ExtendedCAServiceNotActiveException(msg); 219 } 220 ExtendedCAServiceResponse returnval = null; 221 OCSPCAServiceRequest ocspServiceReq = (OCSPCAServiceRequest)request; 222 List certChain = ocspcertificatechain; 223 if (ocspServiceReq.getCertificateChain() != null) { 224 m_log.debug("Using cert chain from CA"); 225 certChain = ocspServiceReq.getCertificateChain(); 226 } 227 X509Certificate signerCert = (X509Certificate )certChain.get(0); 228 229 String sigAlgs = ocspServiceReq.getSigAlg(); 230 PublicKey pk = signerCert.getPublicKey(); 231 String sigAlg = OCSPUtil.getSigningAlgFromAlgSelection(sigAlgs, pk); 232 m_log.debug("Signing algorithm: "+sigAlg); 233 boolean includeChain = ocspServiceReq.includeChain(); 234 X509Certificate [] chain = null; 235 if (includeChain) { 236 chain = (X509Certificate [])certChain.toArray(new X509Certificate [0]); 237 } 238 try { 239 PrivateKey privKey = this.ocspsigningkey; 240 if (ocspServiceReq.getPrivKey() != null) { 241 m_log.debug("Using private key from CA"); 242 privKey = ocspServiceReq.getPrivKey(); 243 } 244 BasicOCSPResp ocspresp = OCSPUtil.generateBasicOCSPResp(ocspServiceReq, sigAlg, signerCert, privKey, ocspServiceReq.getPrivKeyProvider(), chain); 245 returnval = new OCSPCAServiceResponse(ocspresp, chain == null ? null : Arrays.asList(chain)); 246 } catch (OCSPException ocspe) { 247 throw new ExtendedCAServiceRequestException(ocspe); 248 } catch (NoSuchProviderException nspe) { 249 throw new ExtendedCAServiceRequestException(nspe); 250 } catch (NotSupportedException e) { 251 m_log.error("Request type not supported: ", e); 252 throw new IllegalExtendedCAServiceRequestException(e); 253 } catch (IllegalArgumentException e) { 254 m_log.error("IllegalArgumentException: ", e); 255 throw new IllegalExtendedCAServiceRequestException(e); 256 } 257 m_log.debug("<extendedService"); 258 return returnval; 259 } 260 261 262 public float getLatestVersion() { 263 return LATEST_VERSION; 264 } 265 266 public void upgrade() { 267 if(Float.compare(LATEST_VERSION, getVersion()) != 0) { 268 String msg = intres.getLocalizedMessage("ocspcaservice.upgrade", new Float (getVersion())); 270 m_log.info(msg); 271 if(data.get(KEYSPEC) == null) { 272 Integer oldKeySize = (Integer )data.get(KEYSIZE); 274 data.put(KEYSPEC, oldKeySize.toString()); 275 } 276 277 data.put(VERSION, new Float (LATEST_VERSION)); 278 } 279 } 280 281 284 public ExtendedCAServiceInfo getExtendedCAServiceInfo() { 285 if(info == null) 286 info = new OCSPCAServiceInfo(getStatus(), 287 getSubjectDN(), 288 getSubjectAltName(), 289 (String ) data.get(KEYSPEC), 290 (String ) data.get(KEYALGORITHM), 291 this.ocspcertificatechain); 292 293 return this.info; 294 } 295 296 297 public String getSubjectDN(){ 298 String retval = null; 299 String str = (String )data.get(SUBJECTDN); 300 try { 301 retval = new String (Base64.decode((str).getBytes("UTF-8"))); 302 } catch (UnsupportedEncodingException e) { 303 m_log.error("Could not decode OCSP data from Base64",e); 304 } catch (ArrayIndexOutOfBoundsException e) { 305 m_log.debug("Old non base64 encoded DN: "+str); 307 retval = str; 308 } 309 310 return retval; 311 } 312 313 public void setSubjectDN(String dn){ 314 315 try { 316 data.put(SUBJECTDN,new String (Base64.encode(dn.getBytes("UTF-8"),false))); 317 } catch (UnsupportedEncodingException e) { 318 m_log.error("Could not encode OCSP data from Base64",e); 319 } 320 } 321 322 public String getSubjectAltName(){ 323 String retval = null; 324 String str= (String ) data.get(SUBJECTALTNAME); 325 try { 326 retval = new String (Base64.decode((str).getBytes("UTF-8"))); 327 } catch (UnsupportedEncodingException e) { 328 m_log.error("Could not decode OCSP data from Base64",e); 329 } catch (ArrayIndexOutOfBoundsException e) { 330 m_log.debug("Old non base64 encoded altname: "+str); 332 retval = str; 333 } 334 335 return retval; 336 } 337 338 public void setSubjectAltName(String dn){ 339 340 try { 341 data.put(SUBJECTALTNAME,new String (Base64.encode(dn.getBytes("UTF-8"), false))); 342 } catch (UnsupportedEncodingException e) { 343 m_log.error("Could not encode OCSP data from Base64",e); 344 } 345 } 346 } 347 348 | Popular Tags |