1 13 14 package org.ejbca.core.protocol.xkms.generators; 15 16 import gnu.inet.encoding.StringprepException; 17 18 import java.io.UnsupportedEncodingException ; 19 import java.math.BigInteger ; 20 import java.security.KeyFactory ; 21 import java.security.KeyPair ; 22 import java.security.NoSuchAlgorithmException ; 23 import java.security.PrivateKey ; 24 import java.security.PublicKey ; 25 import java.security.cert.CertPath ; 26 import java.security.cert.CertPathValidator ; 27 import java.security.cert.CertPathValidatorException ; 28 import java.security.cert.CertStore ; 29 import java.security.cert.CertificateException ; 30 import java.security.cert.CertificateFactory ; 31 import java.security.cert.CollectionCertStoreParameters ; 32 import java.security.cert.PKIXParameters ; 33 import java.security.cert.TrustAnchor ; 34 import java.security.cert.X509Certificate ; 35 import java.security.interfaces.RSAPrivateCrtKey ; 36 import java.security.spec.InvalidKeySpecException ; 37 import java.security.spec.RSAPublicKeySpec ; 38 import java.util.ArrayList ; 39 import java.util.Collection ; 40 import java.util.Date ; 41 import java.util.HashSet ; 42 import java.util.Iterator ; 43 import java.util.List ; 44 import java.util.Set ; 45 46 import javax.crypto.SecretKey; 47 import javax.xml.bind.JAXBElement; 48 49 import org.apache.log4j.Logger; 50 import org.apache.xml.security.encryption.XMLEncryptionException; 51 import org.apache.xml.security.exceptions.XMLSecurityException; 52 import org.apache.xml.security.signature.XMLSignatureException; 53 import org.bouncycastle.util.encoders.Hex; 54 import org.ejbca.core.model.InternalResources; 55 import org.ejbca.core.model.SecConst; 56 import org.ejbca.core.model.authorization.AuthorizationDeniedException; 57 import org.ejbca.core.model.ca.caadmin.CAInfo; 58 import org.ejbca.core.model.ca.crl.RevokedCertInfo; 59 import org.ejbca.core.model.keyrecovery.KeyRecoveryData; 60 import org.ejbca.core.model.ra.UserDataConstants; 61 import org.ejbca.core.model.ra.UserDataVO; 62 import org.ejbca.core.model.ra.raadmin.EndEntityProfile; 63 import org.ejbca.core.protocol.xkms.common.XKMSConstants; 64 import org.ejbca.core.protocol.xkms.common.XKMSUtil; 65 import org.ejbca.util.CertTools; 66 import org.ejbca.util.KeyTools; 67 import org.w3._2000._09.xmldsig_.RSAKeyValueType; 68 import org.w3._2000._09.xmldsig_.X509DataType; 69 import org.w3._2002._03.xkms_.NotBoundAuthenticationType; 70 import org.w3._2002._03.xkms_.RegisterRequestType; 71 import org.w3._2002._03.xkms_.RequestAbstractType; 72 import org.w3._2002._03.xkms_.ResultType; 73 import org.w3._2002._03.xkms_.RevokeRequestType; 74 import org.w3._2002._03.xkms_.UseKeyWithType; 75 import org.w3c.dom.Document ; 76 import org.w3c.dom.Element ; 77 78 86 87 public class KRSSResponseGenerator extends 88 RequestAbstractTypeResponseGenerator { 89 90 private static Logger log = Logger.getLogger(KRSSResponseGenerator.class); 91 92 private static final InternalResources intres = InternalResources.getInstance(); 93 94 protected Document requestDoc = null; 95 96 public KRSSResponseGenerator(String remoteIP, RequestAbstractType req, Document requestDoc) { 97 super(remoteIP, req); 98 this.requestDoc = requestDoc; 99 } 100 101 106 protected Object getPublicKeyInfo(RequestAbstractType req, boolean registerRequest){ 107 Object retval = null; 108 109 110 if(GeneralizedKRSSMessageHelper.getKeyBindingAbstractType(req).getKeyInfo() != null && GeneralizedKRSSMessageHelper.getKeyBindingAbstractType(req).getKeyInfo().getContent().get(0) != null){ 111 try{ 112 JAXBElement element = (JAXBElement) GeneralizedKRSSMessageHelper.getKeyBindingAbstractType(req).getKeyInfo().getContent().get(0); 113 if(element.getValue() instanceof RSAKeyValueType && registerRequest){ 114 RSAKeyValueType rSAKeyValueType = (RSAKeyValueType) ((JAXBElement) GeneralizedKRSSMessageHelper.getKeyBindingAbstractType(req).getKeyInfo().getContent().get(0)).getValue(); 115 RSAPublicKeySpec rSAPublicKeySpec = new RSAPublicKeySpec (new BigInteger (rSAKeyValueType.getModulus()), new BigInteger (rSAKeyValueType.getExponent())); 116 retval= KeyFactory.getInstance("RSA").generatePublic(rSAPublicKeySpec); 117 } 118 if(element.getValue() instanceof X509DataType){ 119 Iterator iter = ((X509DataType) element.getValue()).getX509IssuerSerialOrX509SKIOrX509SubjectName().iterator(); 120 while(iter.hasNext()){ 121 JAXBElement next = (JAXBElement) iter.next(); 122 if(next.getName().getLocalPart().equals("X509Certificate")){ 123 byte[] encoded = (byte[]) next.getValue(); 124 125 try { 126 X509Certificate nextCert = CertTools.getCertfromByteArray(encoded); 127 if(nextCert.getBasicConstraints() == -1){ 128 retval = nextCert; 129 } 130 } catch (CertificateException e) { 131 log.error(intres.getLocalizedMessage("xkms.errordecodingcert"),e); 132 resultMajor = XKMSConstants.RESULTMAJOR_RECIEVER; 133 resultMinor = XKMSConstants.RESULTMINOR_FAILURE; 134 } 135 136 }else{ 137 resultMajor = XKMSConstants.RESULTMAJOR_SENDER; 138 resultMinor = XKMSConstants.RESULTMINOR_MESSAGENOTSUPPORTED; 139 } 140 } 141 } 142 143 if(retval == null){ 144 resultMajor = XKMSConstants.RESULTMAJOR_SENDER; 145 resultMinor = XKMSConstants.RESULTMINOR_MESSAGENOTSUPPORTED; 146 } 147 148 } catch (InvalidKeySpecException e) { 149 log.error(e); 150 resultMajor = XKMSConstants.RESULTMAJOR_SENDER; 151 resultMinor = XKMSConstants.RESULTMINOR_MESSAGENOTSUPPORTED; 152 } catch (NoSuchAlgorithmException e) { 153 log.error(e); 154 resultMajor = XKMSConstants.RESULTMAJOR_SENDER; 155 resultMinor = XKMSConstants.RESULTMINOR_MESSAGENOTSUPPORTED; 156 } 157 } 158 159 160 161 return retval; 162 } 163 164 169 protected X509Certificate registerReissueOrRecover(boolean recover, boolean reissue, ResultType response, UserDataVO userDataVO, String password, 170 PublicKey publicKey, String revocationCode) { 171 X509Certificate retval = null; 172 173 if((!recover && userDataVO.getStatus() == UserDataConstants.STATUS_NEW) || (recover && userDataVO.getStatus() == UserDataConstants.STATUS_KEYRECOVERY)){ 175 176 try{ 177 boolean usekeyrecovery = !reissue && (getRAAdminSession().loadGlobalConfiguration(pubAdmin)).getEnableKeyRecovery(); 178 179 boolean savekeys = userDataVO.getKeyRecoverable() && usekeyrecovery && (userDataVO.getStatus() != UserDataConstants.STATUS_KEYRECOVERY); 180 boolean loadkeys = (userDataVO.getStatus() == UserDataConstants.STATUS_KEYRECOVERY) && usekeyrecovery; 181 182 int tokentype = userDataVO.getTokenType(); 184 185 PublicKey certKey = null; 186 PrivateKey privKey = null; 187 KeyPair keyPair = null; 188 KeyRecoveryData keyData = null; 189 boolean reusecertificate = false; 190 if(loadkeys){ 191 EndEntityProfile endEntityProfile = getRAAdminSession().getEndEntityProfile(pubAdmin, userDataVO.getEndEntityProfileId()); 192 reusecertificate = endEntityProfile.getReUseKeyRevoceredCertificate(); 193 194 keyData = getKeyRecoverySession().keyRecovery(pubAdmin, userDataVO.getUsername(), userDataVO.getEndEntityProfileId()); 196 keyPair = keyData.getKeyPair(); 197 certKey = keyPair.getPublic(); 198 privKey = keyPair.getPrivate(); 199 200 if(reusecertificate){ 201 getKeyRecoverySession().unmarkUser(pubAdmin,userDataVO.getUsername()); 202 } 203 } 204 else{ 205 if(!reissue && tokentype == SecConst.TOKEN_SOFT_P12){ 207 keyPair = KeyTools.genKeys(Integer.toString(XKMSConfig.getServerKeyLength()), "RSA"); 208 certKey = keyPair.getPublic(); 209 privKey = keyPair.getPrivate(); 210 } 211 if(reissue || tokentype == SecConst.TOKEN_SOFT_BROWSERGEN){ 212 certKey = publicKey; 213 } 214 } 215 216 X509Certificate cert = null; 217 if(reusecertificate){ 218 cert = (X509Certificate ) keyData.getCertificate(); 219 boolean finishUser = getCAAdminSession().getCAInfo(pubAdmin,CertTools.getIssuerDN(cert).hashCode()).getFinishUser(); 220 if(finishUser){ 221 getAuthenticationSession().finishUser(pubAdmin, userDataVO.getUsername(), password); 222 } 223 224 }else{ 225 cert = (X509Certificate )getSignSession().createCertificate(pubAdmin, userDataVO.getUsername(), password, certKey); 226 } 227 228 if (savekeys) { 229 getKeyRecoverySession().addKeyRecoveryData(pubAdmin, cert, userDataVO.getUsername(), keyPair); 231 } 232 233 if(revocationCode != null && !recover){ 235 UserDataVO data = getUserAdminSession().findUser(pubAdmin, userDataVO.getUsername()); 236 data.getExtendedinformation().setRevocationCodeIdentifier(revocationCode); 237 getUserAdminSession().changeUser(raAdmin, data, true); 238 239 } 240 241 if(privKey != null){ 242 GeneralizedKRSSMessageHelper.setPrivateKey(response, XKMSUtil.getEncryptedXMLFromPrivateKey((RSAPrivateCrtKey ) privKey, password)); 243 } 244 245 retval = cert; 246 }catch (Exception e) { 247 log.error(intres.getLocalizedMessage("xkms.errorregisteringreq"),e); 248 } 249 250 if(retval == null){ 251 resultMajor = XKMSConstants.RESULTMAJOR_RECIEVER; 252 resultMinor = XKMSConstants.RESULTMINOR_FAILURE; 253 } 254 255 }else{ 256 log.error(intres.getLocalizedMessage("xkms.errorinreqwrongstatus",new Integer (userDataVO.getStatus()),userDataVO.getUsername())); 257 resultMajor = XKMSConstants.RESULTMAJOR_SENDER; 258 resultMinor = XKMSConstants.RESULTMINOR_REFUSED; 259 } 260 261 262 263 return retval; 264 } 265 266 protected boolean confirmPOP(PublicKey publicKey) { 267 boolean retval = false; 268 if(XKMSConfig.isPOPRequired() && publicKey != null){ 270 try{ 272 273 org.w3c.dom.NodeList pOPElements = requestDoc.getElementsByTagNameNS("http://www.w3.org/2002/03/xkms#", "ProofOfPossession"); 274 if(pOPElements.getLength() == 1){ 275 Element pOPe = (Element) pOPElements.item(0); 276 org.w3c.dom.NodeList popVerXmlSigs = pOPe.getElementsByTagNameNS("http://www.w3.org/2000/09/xmldsig#", "Signature"); 277 org.w3c.dom.Element popVerXmlSigElement = (org.w3c.dom.Element )popVerXmlSigs.item(0); 278 org.apache.xml.security.signature.XMLSignature popVerXmlSig = new org.apache.xml.security.signature.XMLSignature(popVerXmlSigElement, null); 279 if(popVerXmlSig.checkSignatureValue(publicKey)){ 280 retval = true; 281 } 282 } 283 284 if(!retval){ 285 resultMajor = XKMSConstants.RESULTMAJOR_SENDER; 286 resultMinor = XKMSConstants.RESULTMINOR_POPREQUIRED; 287 } 288 }catch(XMLSignatureException e){ 289 log.error(e); 290 resultMajor = XKMSConstants.RESULTMAJOR_SENDER; 291 resultMinor = XKMSConstants.RESULTMINOR_POPREQUIRED; 292 } catch (XMLSecurityException e) { 293 log.error(e); 294 resultMajor = XKMSConstants.RESULTMAJOR_SENDER; 295 resultMinor = XKMSConstants.RESULTMINOR_POPREQUIRED; 296 } 297 298 }else{ 299 retval = true; 300 } 301 302 return retval; 303 } 304 305 protected boolean isPasswordEncrypted(RequestAbstractType req) { 306 if(GeneralizedKRSSMessageHelper.getAuthenticationType(req) == null){ 307 return false; 308 } 309 return GeneralizedKRSSMessageHelper.getAuthenticationType(req).getKeyBindingAuthentication() != null; 310 } 311 312 protected UserDataVO findUserData(String subjectDN) { 313 UserDataVO retval = null; 314 315 if(subjectDN != null){ 316 try { 317 retval = getUserAdminSession().findUserBySubjectDN(pubAdmin, subjectDN); 318 } catch (AuthorizationDeniedException e) { 319 log.error(intres.getLocalizedMessage("xkms.errorinprivs"),e); 320 } 321 if(retval==null){ 322 resultMajor = XKMSConstants.RESULTMAJOR_SENDER; 323 resultMinor = XKMSConstants.RESULTMINOR_NOMATCH; 324 } 325 } 326 return retval; 327 } 328 329 333 protected UserDataVO findUserData(X509Certificate cert) { 334 UserDataVO retval = null; 335 336 try { 337 String username = getCertStoreSession().findUsernameByCertSerno(pubAdmin, cert.getSerialNumber(), CertTools.getIssuerDN(cert)); 338 retval = getUserAdminSession().findUser(pubAdmin, username); 339 } catch (Exception e) { 340 log.error(intres.getLocalizedMessage("xkms.errorfindinguserdata",cert.getSubjectDN().toString())); 341 } 342 343 if(retval==null){ 344 resultMajor = XKMSConstants.RESULTMAJOR_SENDER; 345 resultMinor = XKMSConstants.RESULTMINOR_NOMATCH; 346 } 347 348 return retval; 349 } 350 351 358 protected String getEncryptedPassword(Document reqDoc, String password) { 359 String retval = null; 360 361 try { 362 SecretKey sk = XKMSUtil.getSecretKeyFromPassphrase(password, true, 20, XKMSUtil.KEY_AUTHENTICATION); 363 org.w3c.dom.NodeList authenticationElements = reqDoc.getElementsByTagNameNS("http://www.w3.org/2002/03/xkms#", "Authentication"); 364 Element ae = (Element) authenticationElements.item(0); 365 org.w3c.dom.NodeList xmlSigs = ae.getElementsByTagNameNS("http://www.w3.org/2000/09/xmldsig#", "Signature"); 366 367 org.w3c.dom.Element xmlSigElement = (org.w3c.dom.Element )xmlSigs.item(0); 368 org.apache.xml.security.signature.XMLSignature xmlVerifySig = new org.apache.xml.security.signature.XMLSignature(xmlSigElement, null); 369 370 if(xmlVerifySig.checkSignatureValue(sk)){ 371 retval = password; 372 }else{ 373 resultMajor = XKMSConstants.RESULTMAJOR_SENDER; 374 resultMinor = XKMSConstants.RESULTMINOR_NOAUTHENTICATION; 375 } 376 } catch (Exception e) { 377 log.error(intres.getLocalizedMessage("xkms.errorauthverification"),e); 378 resultMajor = XKMSConstants.RESULTMAJOR_SENDER; 379 resultMinor = XKMSConstants.RESULTMINOR_NOAUTHENTICATION; 380 } 381 382 return retval; 383 } 384 385 392 protected String getClearPassword(RequestAbstractType req, String dBPassword) { 393 String retval = null; 394 NotBoundAuthenticationType notBoundAuthenticationType = GeneralizedKRSSMessageHelper.getAuthenticationType(req).getNotBoundAuthentication(); 395 if(notBoundAuthenticationType != null){ 396 retval = new String (notBoundAuthenticationType.getValue()); 397 }else{ 398 resultMajor = XKMSConstants.RESULTMAJOR_SENDER; 399 resultMinor = XKMSConstants.RESULTMINOR_MESSAGENOTSUPPORTED; 400 } 401 402 if(!retval.equals(dBPassword)){ 403 resultMajor = XKMSConstants.RESULTMAJOR_SENDER; 404 resultMinor = XKMSConstants.RESULTMINOR_NOAUTHENTICATION; 405 retval = null; 406 } 407 408 return retval; 409 } 410 411 417 protected String getSubjectDN(RequestAbstractType req) { 418 String retval = null; 419 420 Iterator <UseKeyWithType> iter = GeneralizedKRSSMessageHelper.getKeyBindingAbstractType(req).getUseKeyWith().iterator(); 421 while(iter.hasNext()){ 422 UseKeyWithType next = iter.next(); 423 if(next.getApplication().equals(XKMSConstants.USEKEYWITH_PKIX)){ 424 retval = CertTools.stringToBCDNString(next.getIdentifier()); 425 break; 426 } 427 } 428 429 if(retval == null){ 430 resultMajor = XKMSConstants.RESULTMAJOR_SENDER; 431 resultMinor = XKMSConstants.RESULTMINOR_MESSAGENOTSUPPORTED; 432 } 433 434 return retval; 435 } 436 437 protected boolean certIsValid(X509Certificate cert) { 438 boolean retval = false; 439 440 try { 441 CAInfo cAInfo = getCAAdminSession().getCAInfo(pubAdmin, CertTools.getIssuerDN(cert).hashCode()); 442 if(cAInfo != null){ 443 Collection caCertChain = cAInfo.getCertificateChain(); 444 Iterator iter = caCertChain.iterator(); 445 446 boolean revoked = false; 447 448 RevokedCertInfo certInfo = getCertStoreSession().isRevoked(pubAdmin, CertTools.getIssuerDN(cert), cert.getSerialNumber()); 449 if(certInfo.getReason() != RevokedCertInfo.NOT_REVOKED){ 450 revoked = true; 451 } 452 453 while(iter.hasNext()){ 454 X509Certificate cACert = (X509Certificate ) iter.next(); 455 RevokedCertInfo caCertInfo = getCertStoreSession().isRevoked(pubAdmin, CertTools.getIssuerDN(cACert), cACert.getSerialNumber()); 456 if(caCertInfo.getReason() != RevokedCertInfo.NOT_REVOKED){ 457 revoked = true; 458 } 459 460 } 461 462 if(!revoked){ 463 retval = verifyCert(caCertChain, null, cert); 464 } 465 } 466 } catch (Exception e) { 467 log.error(e); 468 } 469 470 if(retval == false){ 471 resultMajor = XKMSConstants.RESULTMAJOR_SENDER; 472 resultMinor = XKMSConstants.RESULTMINOR_REFUSED; 473 } 474 475 return retval; 476 } 477 478 479 480 487 private boolean verifyCert(Collection cACertChain, Collection trustedCRLs, X509Certificate usercert){ 488 489 boolean retval = false; 490 491 try{ 492 X509Certificate rootCert = null; 493 Iterator iter = cACertChain.iterator(); 494 while(iter.hasNext()){ 495 X509Certificate cert = (X509Certificate ) iter.next(); 496 if(cert.getIssuerDN().equals(cert.getSubjectDN())){ 497 rootCert = cert; 498 break; 499 } 500 } 501 502 if(rootCert == null){ 503 throw new CertPathValidatorException ("Error Root CA cert not found in cACertChain"); 504 } 505 506 List list = new ArrayList (); 507 list.add(usercert); 508 list.addAll(cACertChain); 509 if(trustedCRLs != null){ 510 list.addAll(trustedCRLs); 511 } 512 513 CollectionCertStoreParameters ccsp = new CollectionCertStoreParameters (list); 514 CertStore store = CertStore.getInstance("Collection", ccsp); 515 516 List certchain = new ArrayList (); 518 certchain.addAll(cACertChain); 519 certchain.add(usercert); 520 CertPath cp = CertificateFactory.getInstance("X.509","BC").generateCertPath(certchain); 521 522 Set trust = new HashSet (); 523 trust.add(new TrustAnchor (rootCert, null)); 524 525 CertPathValidator cpv = CertPathValidator.getInstance("PKIX","BC"); 526 PKIXParameters param = new PKIXParameters (trust); 527 param.addCertStore(store); 528 param.setDate(new Date ()); 529 if(trustedCRLs == null){ 530 param.setRevocationEnabled(false); 531 }else{ 532 param.setRevocationEnabled(true); 533 } 534 cpv.validate(cp, param); 535 retval = true; 536 }catch(Exception e){ 537 log.error(intres.getLocalizedMessage("xkms.errorverifyingcert"),e); 538 539 } 540 541 542 return retval; 543 } 544 545 549 public boolean checkValidRespondWithRequest(List <String > respondWithList, boolean revokeCall){ 550 boolean returnval = false; 551 if(revokeCall){ 552 returnval = true; 553 } 554 555 String [] supportedRespondWith = {XKMSConstants.RESPONDWITH_X509CERT, 556 XKMSConstants.RESPONDWITH_X509CHAIN, 557 XKMSConstants.RESPONDWITH_X509CRL, 558 XKMSConstants.RESPONDWITH_PRIVATEKEY}; 559 560 for(int i=0;i<supportedRespondWith.length;i++){ 561 returnval |= respondWithList.contains(supportedRespondWith[i]); 562 if(returnval){ 563 break; 564 } 565 } 566 567 return returnval; 568 } 569 570 577 protected String getRevocationCode(RequestAbstractType req) { 578 String retval = null; 579 580 if(req instanceof RegisterRequestType){ 581 if(((RegisterRequestType) req).getPrototypeKeyBinding().getRevocationCodeIdentifier() != null){ 582 retval = new String (Hex.encode(((RegisterRequestType) req).getPrototypeKeyBinding().getRevocationCodeIdentifier())); 583 } 584 } 585 if(req instanceof RevokeRequestType){ 586 byte[] unMACedCode= ((RevokeRequestType) req).getRevocationCode(); 587 if(unMACedCode != null){ 588 try{ 589 retval = new String (Hex.encode(XKMSUtil.getSecretKeyFromPassphrase(new String (unMACedCode,"ISO8859-1"), false, 20, XKMSUtil.KEY_REVOCATIONCODEIDENTIFIER_PASS2).getEncoded())); 590 }catch (XMLEncryptionException e) { 591 log.error(e); 592 } catch (StringprepException e) { } catch (UnsupportedEncodingException e) { 594 log.error(e); 595 } 596 } 597 } 598 599 return retval; 600 } 601 } 602 | Popular Tags |