blob: 0572cd658aa882d0e1e8faec2d4ffad61ee91921 [file] [log] [blame]
/*
* Copyright 2004,2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rampart.builder;
import org.apache.axiom.om.OMElement;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.rahas.TrustException;
import org.apache.rampart.RampartConstants;
import org.apache.rampart.RampartException;
import org.apache.rampart.RampartMessageData;
import org.apache.rampart.policy.RampartPolicyData;
import org.apache.rampart.policy.SupportingPolicyData;
import org.apache.rampart.policy.model.RampartConfig;
import org.apache.rampart.util.RampartUtil;
import org.apache.ws.secpolicy.model.AlgorithmSuite;
import org.apache.ws.secpolicy.model.SupportingToken;
import org.apache.ws.secpolicy.model.Token;
import org.apache.ws.secpolicy.model.X509Token;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSEncryptionPart;
import org.apache.ws.security.WSSecurityException;
import org.apache.ws.security.conversation.ConversationException;
import org.apache.ws.security.handler.WSHandlerConstants;
import org.apache.ws.security.handler.WSHandlerResult;
import org.apache.ws.security.message.WSSecDKEncrypt;
import org.apache.ws.security.message.WSSecDKSign;
import org.apache.ws.security.message.WSSecEncrypt;
import org.apache.ws.security.message.WSSecEncryptedKey;
import org.apache.ws.security.message.WSSecSignature;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.crypto.dsig.Reference;
import java.util.*;
public class AsymmetricBindingBuilder extends BindingBuilder {
private static Log log = LogFactory.getLog(AsymmetricBindingBuilder.class);
private static Log tlog = LogFactory.getLog(RampartConstants.TIME_LOG);
private WSSecEncryptedKey encrKey;
private String encryptedKeyId;
private byte[] encryptedKeyValue;
private List<byte[]> signatureValues = new ArrayList<byte[]>();
private Element encrTokenElement;
private Element sigDKTElement;
private Element encrDKTElement;
private List<WSEncryptionPart> sigParts = new ArrayList<WSEncryptionPart>();
private Element signatureElement;
private Element refList;
public void build(RampartMessageData rmd) throws RampartException {
log.debug("AsymmetricBindingBuilder build invoked");
RampartPolicyData rpd = rmd.getPolicyData();
if (rpd.isIncludeTimestamp()) {
this.addTimestamp(rmd);
}
if (RampartUtil.encryptFirst(rpd)) {
this.doEncryptBeforeSig(rmd);
} else {
this.doSignBeforeEncrypt(rmd);
}
log.debug("AsymmetricBindingBuilder build invoked : DONE");
}
private void doEncryptBeforeSig(RampartMessageData rmd)
throws RampartException {
long t0 = 0, t1 = 0, t2 = 0;
if(tlog.isDebugEnabled()){
t0 = System.currentTimeMillis();
}
RampartPolicyData rpd = rmd.getPolicyData();
Document doc = rmd.getDocument();
RampartConfig config = rpd.getRampartConfig();
/*
* We need to hold on to these two element to use them as refence in the
* case of encypting the signature
*/
Element encrDKTokenElem = null;
WSSecEncrypt encr = null;
refList = null;
WSSecDKEncrypt dkEncr = null;
/*
* We MUST use keys derived from the same token
*/
Token encryptionToken = null;
if(rmd.isInitiator()) {
encryptionToken = rpd.getRecipientToken();
} else {
encryptionToken = rpd.getInitiatorToken();
}
List<WSEncryptionPart> encrParts = RampartUtil.getEncryptedParts(rmd);
//Signed parts are determined before encryption because encrypted signed headers
//will not be included otherwise
this.sigParts = RampartUtil.getSignedParts(rmd);
if(encryptionToken == null && encrParts.size() > 0) {
throw new RampartException("encryptionTokenMissing");
}
if (encryptionToken != null && encrParts.size() > 0) {
//Check for RampartConfig assertion
if(rpd.getRampartConfig() == null) {
//We'er missing the extra info rampart needs
throw new RampartException("rampartConigMissing");
}
if (encryptionToken.isDerivedKeys()) {
try {
this.setupEncryptedKey(rmd, encryptionToken);
// Create the DK encryption builder
dkEncr = new WSSecDKEncrypt();
dkEncr.setParts(encrParts);
dkEncr.setExternalKey(this.encryptedKeyValue,
this.encryptedKeyId);
dkEncr.setDerivedKeyLength(rpd.getAlgorithmSuite().getEncryptionDerivedKeyLength()/8);
dkEncr.prepare(doc);
// Get and add the DKT element
this.encrDKTElement = dkEncr.getdktElement();
encrDKTokenElem = RampartUtil.appendChildToSecHeader(rmd, this.encrDKTElement);
refList = dkEncr.encryptForExternalRef(null, encrParts);
} catch (WSSecurityException e) {
throw new RampartException("errorCreatingEncryptedKey", e);
} catch (ConversationException e) {
throw new RampartException("errorInDKEncr", e);
}
} else {
try {
encr = new WSSecEncrypt();
encr.setParts(encrParts);
encr.setWsConfig(rmd.getConfig());
encr.setDocument(doc);
RampartUtil.setEncryptionUser(rmd, encr);
encr.setSymmetricEncAlgorithm(rpd.getAlgorithmSuite().getEncryption());
RampartUtil.setKeyIdentifierType(rmd, encr, encryptionToken);
encr.setKeyEncAlgo(rpd.getAlgorithmSuite().getAsymmetricKeyWrap());
encr.prepare(doc, RampartUtil.getEncryptionCrypto(config, rmd.getCustomClassLoader()));
Element bstElem = encr.getBinarySecurityTokenElement();
if (bstElem != null) {
RampartUtil.appendChildToSecHeader(rmd, bstElem);
}
this.encrTokenElement = encr.getEncryptedKeyElement();
this.encrTokenElement = RampartUtil.appendChildToSecHeader(rmd,
encrTokenElement);
refList = encr.encryptForExternalRef(null, encrParts);
} catch (WSSecurityException e) {
throw new RampartException("errorInEncryption", e);
}
}
refList = RampartUtil.appendChildToSecHeader(rmd, refList);
if(tlog.isDebugEnabled()){
t1 = System.currentTimeMillis();
}
this.setInsertionLocation(encrTokenElement);
RampartUtil.handleEncryptedSignedHeaders(encrParts, this.sigParts, doc);
// TODO may contain deifferent types of objects as values, therefore cannot use strongly type maps
// need to figure out a way
HashMap<Token,Object> sigSuppTokMap = null;
HashMap<Token,Object> endSuppTokMap = null;
HashMap<Token,Object> sgndEndSuppTokMap = null;
HashMap<Token,Object> sgndEncSuppTokMap = null;
HashMap<Token,Object> endEncSuppTokMap = null;
HashMap<Token,Object> sgndEndEncSuppTokMap = null;
if(this.timestampElement != null){
sigParts.add(RampartUtil.createEncryptionPart(WSConstants.TIMESTAMP_TOKEN_LN,
RampartUtil.addWsuIdToElement((OMElement) this.timestampElement)));
}
if (rmd.isInitiator()) {
// Now add the supporting tokens
SupportingToken sgndSuppTokens = rpd.getSignedSupportingTokens();
sigSuppTokMap = this.handleSupportingTokens(rmd, sgndSuppTokens);
SupportingToken endSuppTokens = rpd.getEndorsingSupportingTokens();
endSuppTokMap = this.handleSupportingTokens(rmd, endSuppTokens);
SupportingToken sgndEndSuppTokens = rpd.getSignedEndorsingSupportingTokens();
sgndEndSuppTokMap = this.handleSupportingTokens(rmd, sgndEndSuppTokens);
SupportingToken sgndEncryptedSuppTokens = rpd.getSignedEncryptedSupportingTokens();
sgndEncSuppTokMap = this.handleSupportingTokens(rmd, sgndEncryptedSuppTokens);
SupportingToken endorsingEncryptedSuppTokens = rpd.getEndorsingEncryptedSupportingTokens();
endEncSuppTokMap = this.handleSupportingTokens(rmd, endorsingEncryptedSuppTokens);
SupportingToken sgndEndEncSuppTokens = rpd.getSignedEndorsingEncryptedSupportingTokens();
sgndEndEncSuppTokMap = this.handleSupportingTokens(rmd, sgndEndEncSuppTokens);
List<SupportingToken> supportingToks = rpd.getSupportingTokensList();
for (SupportingToken supportingTok : supportingToks) {
this.handleSupportingTokens(rmd, supportingTok);
}
SupportingToken encryptedSupportingToks = rpd.getEncryptedSupportingTokens();
this.handleSupportingTokens(rmd, encryptedSupportingToks);
//Setup signature parts
sigParts = addSignatureParts(sigSuppTokMap, sigParts);
sigParts = addSignatureParts(sgndEncSuppTokMap, sigParts);
sigParts = addSignatureParts(sgndEndSuppTokMap, sigParts);
sigParts = addSignatureParts(sgndEndEncSuppTokMap, sigParts);
} else {
addSignatureConfirmation(rmd, sigParts);
}
if(( sigParts.size() > 0 &&
rmd.isInitiator() && rpd.getInitiatorToken() != null) ||
(!rmd.isInitiator() && rpd.getRecipientToken() != null)) {
this.doSignature(rmd);
}
if (rmd.isInitiator()) {
if (endSuppTokMap != null) {
endSuppTokMap.putAll(endEncSuppTokMap);
}
// Do endorsed signatures
List<byte[]> endSigVals = this.doEndorsedSignatures(rmd,
endSuppTokMap);
for (byte[] endSigVal : endSigVals) {
signatureValues.add(endSigVal);
}
sgndEndSuppTokMap.putAll(sgndEndEncSuppTokMap);
// Do signed endorsing signatures
List<byte[]> sigEndSigVals = this.doEndorsedSignatures(rmd,
sgndEndSuppTokMap);
for (byte[] sigEndSigVal : sigEndSigVals) {
signatureValues.add(sigEndSigVal);
}
}
if(tlog.isDebugEnabled()){
t2 = System.currentTimeMillis();
tlog.debug("Encryption took :" + (t1 - t0)
+", Signature tool :" + (t2 - t1) );
}
// Check for signature protection
if (rpd.isSignatureProtection() && this.mainSigId != null) {
long t3 = 0, t4 = 0;
if(tlog.isDebugEnabled()){
t3 = System.currentTimeMillis();
}
List<WSEncryptionPart> secondEncrParts = new ArrayList<WSEncryptionPart>();
// Now encrypt the signature using the above token
secondEncrParts.add(new WSEncryptionPart(this.mainSigId,
"Element"));
if(rmd.isInitiator()) {
for (String anEncryptedTokensIdList : encryptedTokensIdList) {
secondEncrParts.add(new WSEncryptionPart(anEncryptedTokensIdList, "Element"));
}
}
Element secondRefList = null;
if (encryptionToken.isDerivedKeys()) {
try {
secondRefList = dkEncr.encryptForExternalRef(null,
secondEncrParts);
RampartUtil.insertSiblingAfter(rmd, encrDKTokenElem,
secondRefList);
} catch (WSSecurityException e) {
throw new RampartException("errorCreatingEncryptedKey",
e);
}
} else {
try {
// Encrypt, get hold of the ref list and add it
secondRefList = encr.encryptForExternalRef(null,
secondEncrParts);
// Insert the ref list after the encrypted key elem
this.setInsertionLocation(RampartUtil
.insertSiblingAfter(rmd, encrTokenElement,
secondRefList));
} catch (WSSecurityException e) {
throw new RampartException("errorInEncryption", e);
}
}
if(tlog.isDebugEnabled()){
t4 = System.currentTimeMillis();
tlog.debug("Signature protection took :" + (t4 - t3));
}
}
}
}
private void doSignBeforeEncrypt(RampartMessageData rmd)
throws RampartException {
long t0 = 0, t1 = 0, t2 = 0;
RampartPolicyData rpd = rmd.getPolicyData();
Document doc = rmd.getDocument();
HashMap sigSuppTokMap = null;
HashMap endSuppTokMap = null;
HashMap sgndEndSuppTokMap = null;
HashMap sgndEncSuppTokMap = null;
HashMap endEncSuppTokMap = null;
HashMap sgndEndEncSuppTokMap = null;
sigParts = RampartUtil.getSignedParts(rmd);
//Add timestamp
if(this.timestampElement != null){
sigParts.add(new WSEncryptionPart(RampartUtil
.addWsuIdToElement((OMElement) this.timestampElement)));
}else{
this.setInsertionLocation(null);
}
if(tlog.isDebugEnabled()){
t0 = System.currentTimeMillis();
}
if (rmd.isInitiator()) {
// Now add the supporting tokens
SupportingToken sgndSuppTokens = rpd.getSignedSupportingTokens();
sigSuppTokMap = this.handleSupportingTokens(rmd, sgndSuppTokens);
SupportingToken endSuppTokens = rpd.getEndorsingSupportingTokens();
endSuppTokMap = this.handleSupportingTokens(rmd, endSuppTokens);
SupportingToken sgndEndSuppTokens = rpd.getSignedEndorsingSupportingTokens();
sgndEndSuppTokMap = this.handleSupportingTokens(rmd, sgndEndSuppTokens);
SupportingToken sgndEncryptedSuppTokens = rpd.getSignedEncryptedSupportingTokens();
sgndEncSuppTokMap = this.handleSupportingTokens(rmd, sgndEncryptedSuppTokens);
SupportingToken endorsingEncryptedSuppTokens = rpd.getEndorsingEncryptedSupportingTokens();
endEncSuppTokMap = this.handleSupportingTokens(rmd, endorsingEncryptedSuppTokens);
SupportingToken sgndEndEncSuppTokens = rpd.getSignedEndorsingEncryptedSupportingTokens();
sgndEndEncSuppTokMap = this.handleSupportingTokens(rmd, sgndEndEncSuppTokens);
List<SupportingToken> supportingToks = rpd.getSupportingTokensList();
for (SupportingToken supportingTok : supportingToks) {
this.handleSupportingTokens(rmd, supportingTok);
}
SupportingToken encryptedSupportingToks = rpd.getEncryptedSupportingTokens();
this.handleSupportingTokens(rmd, encryptedSupportingToks);
//Setup signature parts
sigParts = addSignatureParts(sigSuppTokMap, sigParts);
sigParts = addSignatureParts(sgndEncSuppTokMap, sigParts);
sigParts = addSignatureParts(sgndEndSuppTokMap, sigParts);
sigParts = addSignatureParts(sgndEndEncSuppTokMap, sigParts);
} else {
addSignatureConfirmation(rmd, sigParts);
}
if( sigParts.size() > 0 &&
((rmd.isInitiator() && rpd.getInitiatorToken() != null) ||
(!rmd.isInitiator() && rpd.getRecipientToken() != null))) {
// Do signature
this.doSignature(rmd);
}
List<SupportingPolicyData> supportingToks = rpd.getSupportingPolicyData();
for (SupportingPolicyData policyData : supportingToks) {
if (policyData != null) { // TODO do we need this null check ?
List<WSEncryptionPart> supportingSigParts = RampartUtil.getSupportingSignedParts(rmd,
policyData);
if (supportingSigParts.size() > 0
&& ((rmd.isInitiator() && rpd.getInitiatorToken() != null) || (!rmd
.isInitiator() && rpd.getRecipientToken() != null))) {
// Do signature for policies defined under SupportingToken.
this.doSupportingSignature(rmd, supportingSigParts, policyData);
}
}
}
//Do endorsed signature
if (rmd.isInitiator()) {
// Adding the endorsing encrypted supporting tokens to endorsing supporting tokens
if (endSuppTokMap != null) {
endSuppTokMap.putAll(endEncSuppTokMap);
}
// Do endorsed signatures
List<byte[]> endSigVals = this.doEndorsedSignatures(rmd,
endSuppTokMap);
for (byte[] endSigVal : endSigVals) {
signatureValues.add(endSigVal);
}
//Adding the signed endorsed encrypted tokens to signed endorsed supporting tokens
if (sgndEndSuppTokMap != null) {
sgndEndSuppTokMap.putAll(sgndEndEncSuppTokMap);
}
// Do signed endorsing signatures
List<byte[]> sigEndSigVals = this.doEndorsedSignatures(rmd,
sgndEndSuppTokMap);
for (byte[] sigEndSigVal : sigEndSigVals) {
signatureValues.add(sigEndSigVal);
}
}
if(tlog.isDebugEnabled()){
t1 = System.currentTimeMillis();
}
List<WSEncryptionPart> encrParts = RampartUtil.getEncryptedParts(rmd);
//Check for signature protection
if(rpd.isSignatureProtection() && this.mainSigId != null) {
encrParts.add(new WSEncryptionPart(RampartUtil.addWsuIdToElement((OMElement)this.signatureElement), "Element"));
}
if(rmd.isInitiator()) {
for (String anEncryptedTokensIdList : encryptedTokensIdList) {
encrParts.add(new WSEncryptionPart(anEncryptedTokensIdList, "Element"));
}
}
//Do encryption
Token encrToken;
if (rmd.isInitiator()) {
encrToken = rpd.getRecipientToken();
} else {
encrToken = rpd.getInitiatorToken();
}
if(encrToken != null && encrParts.size() > 0) {
Element refList = null;
AlgorithmSuite algorithmSuite = rpd.getAlgorithmSuite();
if(encrToken.isDerivedKeys()) {
try {
WSSecDKEncrypt dkEncr = new WSSecDKEncrypt();
if(this.encrKey == null) {
this.setupEncryptedKey(rmd, encrToken);
}
dkEncr.setExternalKey(this.encryptedKeyValue, this.encryptedKeyId);
dkEncr.setCustomValueType(WSConstants.SOAPMESSAGE_NS11 + "#"
+ WSConstants.ENC_KEY_VALUE_TYPE);
dkEncr.setSymmetricEncAlgorithm(algorithmSuite.getEncryption());
dkEncr.setDerivedKeyLength(algorithmSuite.getEncryptionDerivedKeyLength()/8);
dkEncr.prepare(doc);
if(this.encrTokenElement != null) {
this.encrDKTElement = RampartUtil.insertSiblingAfter(
rmd, this.encrTokenElement, dkEncr.getdktElement());
} else {
this.encrDKTElement = RampartUtil.insertSiblingBefore(
rmd, this.sigDKTElement, dkEncr.getdktElement());
}
refList = dkEncr.encryptForExternalRef(null, encrParts);
RampartUtil.insertSiblingAfter(rmd,
this.encrDKTElement,
refList);
} catch (WSSecurityException e) {
throw new RampartException("errorInDKEncr", e);
} catch (ConversationException e) {
throw new RampartException("errorInDKEncr", e);
}
} else {
try {
WSSecEncrypt encr = new WSSecEncrypt();
RampartUtil.setKeyIdentifierType(rmd, encr, encrToken);
encr.setWsConfig(rmd.getConfig());
encr.setDocument(doc);
RampartUtil.setEncryptionUser(rmd, encr);
encr.setSymmetricEncAlgorithm(algorithmSuite.getEncryption());
encr.setKeyEncAlgo(algorithmSuite.getAsymmetricKeyWrap());
encr.prepare(doc, RampartUtil.getEncryptionCrypto(rpd
.getRampartConfig(), rmd.getCustomClassLoader()));
if(this.timestampElement != null){
this.setInsertionLocation(this.timestampElement);
}else{
this.setInsertionLocation(null);
}
if(encr.getBSTTokenId() != null) {
this.setInsertionLocation(RampartUtil
.insertSiblingAfterOrPrepend(rmd,
this.getInsertionLocation(),
encr.getBinarySecurityTokenElement()));
}
Element encryptedKeyElement = encr.getEncryptedKeyElement();
//Encrypt, get hold of the ref list and add it
refList = encr.encryptForInternalRef(null, encrParts);
//Add internal refs
encryptedKeyElement.appendChild(refList);
this.setInsertionLocation(RampartUtil
.insertSiblingAfterOrPrepend(rmd,
this.getInsertionLocation(),
encryptedKeyElement));
// RampartUtil.insertSiblingAfter(rmd,
// this.getInsertionLocation(),
// refList);
} catch (WSSecurityException e) {
throw new RampartException("errorInEncryption", e);
}
}
}
List<SupportingPolicyData> supportingTokens = rpd.getSupportingPolicyData();
for (SupportingPolicyData policyData : supportingTokens) {
if (policyData != null) { // TODO do we need this null check ?
Token supportingEncrToken = policyData.getEncryptionToken();
List<WSEncryptionPart> supoortingEncrParts = RampartUtil.getSupportingEncryptedParts(rmd,
policyData);
if (supportingEncrToken != null && supoortingEncrParts.size() > 0) {
doEncryptionWithSupportingToken(rpd, rmd, supportingEncrToken, doc,
supoortingEncrParts);
}
}
}
if(tlog.isDebugEnabled()){
t2 = System.currentTimeMillis();
tlog.debug("Signature took :" + (t1 - t0)
+", Encryption took :" + (t2 - t1) );
}
}
private void doSupportingSignature(RampartMessageData rmd, List<WSEncryptionPart> supportingSigParts,
SupportingPolicyData supportingData) throws RampartException {
Token supportingSigToken;
WSSecSignature supportingSig;
Element supportingSignatureElement;
long t0 = 0, t1 = 0;
if (tlog.isDebugEnabled()) {
t0 = System.currentTimeMillis();
}
supportingSigToken = supportingData.getSignatureToken();
if (!(supportingSigToken instanceof X509Token)) {
return;
}
supportingSig = this.getSignatureBuilder(rmd, supportingSigToken,
((X509Token) supportingSigToken).getUserCertAlias());
Element bstElem = supportingSig.getBinarySecurityTokenElement();
if (bstElem != null) {
bstElem = RampartUtil.insertSiblingAfter(rmd, this.getInsertionLocation(), bstElem);
this.setInsertionLocation(bstElem);
}
if (rmd.getPolicyData().isTokenProtection() && supportingSig.getBSTTokenId() != null) {
supportingSigParts.add(new WSEncryptionPart(supportingSig.getBSTTokenId()));
}
try {
supportingSig.setDigestAlgo(rmd.getPolicyData().getAlgorithmSuite().getDigest());
List<Reference> referenceList
= supportingSig.addReferencesToSign(supportingSigParts, rmd.getSecHeader());
/**
* Before migration it was - this.setInsertionLocation(RampartUtil.insertSiblingAfter(rmd, this
* .getInsertionLocation(), supportingSignatureElement));
*
* In this case we need to append <Signature>..</Signature> element to
* current insertion location
*/
supportingSig.computeSignature(referenceList, false, this.getInsertionLocation());
} catch (WSSecurityException e) {
throw new RampartException("errorInSignatureWithX509Token", e);
}
signatureValues.add(supportingSig.getSignatureValue());
if (tlog.isDebugEnabled()) {
t1 = System.currentTimeMillis();
tlog.debug("Signature took :" + (t1 - t0));
}
}
private void doSignature(RampartMessageData rmd) throws RampartException {
RampartPolicyData rpd = rmd.getPolicyData();
Document doc = rmd.getDocument();
long t0 = 0, t1 = 0;
if(tlog.isDebugEnabled()){
t0 = System.currentTimeMillis();
}
Token sigToken;
if(rmd.isInitiator()) {
sigToken = rpd.getInitiatorToken();
} else {
sigToken = rpd.getRecipientToken();
}
/**
* Note : It doesn't make sense to use Derived Keys in an Asymmetric binding environment to sign messages.
* In asymmetric binding environment we always sign the message using sender's private key. We do *not*
* use a session/ephemeral key to sign the message. We always use PKC keys to sign and verify messages.
* Therefore we do not need to have following code segment.
* TODO Confirm and remove.
*/
if (sigToken.isDerivedKeys()) {
// Set up the encrypted key to use
if(this.encrKey == null) {
setupEncryptedKey(rmd, sigToken);
}
WSSecDKSign dkSign = new WSSecDKSign();
dkSign.setExternalKey(this.encryptedKeyValue, this.encryptedKeyId);
// Set the algo info
dkSign.setSignatureAlgorithm(rpd.getAlgorithmSuite()
.getSymmetricSignature());
dkSign.setDerivedKeyLength(rpd.getAlgorithmSuite()
.getSignatureDerivedKeyLength() / 8);
dkSign.setCustomValueType(WSConstants.SOAPMESSAGE_NS11 + "#"
+ WSConstants.ENC_KEY_VALUE_TYPE);
try {
dkSign.prepare(doc, rmd.getSecHeader());
if (rpd.isTokenProtection()) {
sigParts.add(new WSEncryptionPart(encrKey.getId()));
}
dkSign.setParts(sigParts);
List<Reference> referenceList
= dkSign.addReferencesToSign(sigParts, rmd.getSecHeader());
/**
* Add <wsc:DerivedKeyToken>..</wsc:DerivedKeyToken> to security
* header. We need to add this just after Encrypted Key and just before <Signature>..</Signature>
* elements. (As a convention)
*/
if (refList == null) {
//dkSign.appendDKElementToHeader(rmd.getSecHeader());
this.sigDKTElement = RampartUtil.insertSiblingAfter(rmd,
this.getInsertionLocation(), dkSign.getdktElement());
this.setInsertionLocation(this.sigDKTElement);
// Do signature
/**
* Create and prepend signature
*/
dkSign.computeSignature(referenceList, false, this.getInsertionLocation());
} else {
this.sigDKTElement = RampartUtil.insertSiblingBefore(rmd, refList, dkSign.getdktElement());
this.setInsertionLocation(this.sigDKTElement);
// Do signature
/**
* Create and append signature
*/
dkSign.computeSignature(referenceList, true, this.getInsertionLocation());
}
if (RampartUtil.encryptFirst(rpd)) {
// always add encrypt elements after signature. Because we need to first verify the signature
// and decrypt at receiver end.
this.setInsertionLocation(dkSign.getSignatureElement());
} else {
// append timestamp element as next insertion location. Cos in sign and encrypt case the
// receiver first need to decrypt the message => The decryption keys should appear first.
this.setInsertionLocation(this.timestampElement);
}
this.mainSigId = RampartUtil
.addWsuIdToElement((OMElement) dkSign
.getSignatureElement());
signatureValues.add(dkSign.getSignatureValue());
signatureElement = dkSign.getSignatureElement();
} catch (WSSecurityException e) {
throw new RampartException("errorInDerivedKeyTokenSignature", e);
} catch (ConversationException e) {
throw new RampartException("errorInDerivedKeyTokenSignature", e);
}
} else {
WSSecSignature sig = this.getSignatureBuilder(rmd, sigToken);
Element bstElem = sig.getBinarySecurityTokenElement();
if(bstElem != null) {
bstElem = RampartUtil.insertSiblingAfter(rmd, this
.getInsertionLocation(), bstElem);
this.setInsertionLocation(bstElem);
}
if (rmd.getPolicyData().isTokenProtection()
&& sig.getBSTTokenId() != null) {
sigParts.add(new WSEncryptionPart(sig.getBSTTokenId()));
}
try {
sig.setDigestAlgo(rpd.getAlgorithmSuite().getDigest());
List<Reference> referenceList
= sig.addReferencesToSign(sigParts, rmd.getSecHeader());
// Do signature
if (this.refList == null) {
/**
* If <ReferenceData>..</ReferenceData> is null append <Signature>..</Signature> element
* to current insertion location.
*/
sig.computeSignature(referenceList, false, this.getInsertionLocation());
} else {
/**
* If <ReferenceData>..</ReferenceData> is not null prepend <Signature>..</Signature> element
* to reference data.
*/
sig.computeSignature(referenceList, true, this.refList);
}
signatureElement = sig.getSignatureElement();
this.setInsertionLocation(signatureElement);
this.mainSigId = RampartUtil.addWsuIdToElement((OMElement) signatureElement);
} catch (WSSecurityException e) {
throw new RampartException("errorInSignatureWithX509Token", e);
}
signatureValues.add(sig.getSignatureValue());
}
if(tlog.isDebugEnabled()){
t1 = System.currentTimeMillis();
tlog.debug("Signature took :" + (t1 - t0));
}
}
private void doEncryptionWithSupportingToken(RampartPolicyData rpd, RampartMessageData rmd,
Token encrToken, Document doc, List<WSEncryptionPart> encrParts) throws RampartException {
Element refList = null;
try {
if (!(encrToken instanceof X509Token)) {
return;
}
WSSecEncrypt encr = new WSSecEncrypt();
RampartUtil.setKeyIdentifierType(rmd, encr, encrToken);
encr.setWsConfig(rmd.getConfig());
encr.setDocument(doc);
RampartUtil.setEncryptionUser(rmd, encr, ((X509Token) encrToken).getEncryptionUser());
encr.setSymmetricEncAlgorithm(rpd.getAlgorithmSuite().getEncryption());
encr.setKeyEncAlgo(rpd.getAlgorithmSuite().getAsymmetricKeyWrap());
encr.prepare(doc, RampartUtil.getEncryptionCrypto(rpd.getRampartConfig(), rmd
.getCustomClassLoader()));
if (this.timestampElement != null) {
this.setInsertionLocation(this.timestampElement);
} else {
this.setInsertionLocation(null);
}
if (encr.getBSTTokenId() != null) {
this.setInsertionLocation(RampartUtil.insertSiblingAfterOrPrepend(rmd, this
.getInsertionLocation(), encr.getBinarySecurityTokenElement()));
}
Element encryptedKeyElement = encr.getEncryptedKeyElement();
// Encrypt, get hold of the ref list and add it
refList = encr.encryptForInternalRef(null, encrParts);
// Add internal refs
encryptedKeyElement.appendChild(refList);
this.setInsertionLocation(RampartUtil.insertSiblingAfterOrPrepend(rmd, this
.getInsertionLocation(), encryptedKeyElement));
} catch (WSSecurityException e) {
throw new RampartException("errorInEncryption", e);
}
}
/**
* @param rmd
* @throws RampartException
*/
private void setupEncryptedKey(RampartMessageData rmd, Token token)
throws RampartException {
if(!rmd.isInitiator() && token.isDerivedKeys()) {
//If we already have them, simply return
if(this.encryptedKeyId != null && this.encryptedKeyValue != null) {
return;
}
//Use the secret from the incoming EncryptedKey element
List<WSHandlerResult> resultsObj
= (List<WSHandlerResult>)rmd.getMsgContext().getProperty(WSHandlerConstants.RECV_RESULTS);
if(resultsObj != null) {
encryptedKeyId = RampartUtil.getRequestEncryptedKeyId(resultsObj);
encryptedKeyValue = RampartUtil.getRequestEncryptedKeyValue(resultsObj);
//In the case where we don't have the EncryptedKey in the
//request, for the control to have reached this state,
//the scenario MUST be a case where this is the response
//message by a listener created for an async client
//Therefor we will create a new EncryptedKey
if(encryptedKeyId == null && encryptedKeyValue == null) {
createEncryptedKey(rmd, token);
}
} else {
throw new RampartException("noSecurityResults");
}
} else {
createEncryptedKey(rmd, token);
}
}
/**
* Create an encrypted key element
* @param rmd
* @param token
* @throws RampartException
*/
private void createEncryptedKey(RampartMessageData rmd, Token token) throws RampartException {
//Set up the encrypted key to use
encrKey = this.getEncryptedKeyBuilder(rmd, token);
Element bstElem = encrKey.getBinarySecurityTokenElement();
if (bstElem != null) {
// If a BST is available then use it
RampartUtil.appendChildToSecHeader(rmd, bstElem);
}
// Add the EncryptedKey
encrTokenElement = encrKey.getEncryptedKeyElement();
this.encrTokenElement = RampartUtil.appendChildToSecHeader(rmd,
encrTokenElement);
encryptedKeyValue = encrKey.getEphemeralKey();
encryptedKeyId = encrKey.getId();
//Store the token for client - response verification
// and server - response creation
try {
org.apache.rahas.Token tok = new org.apache.rahas.Token(
encryptedKeyId, (OMElement)encrTokenElement , null, null);
tok.setSecret(encryptedKeyValue);
rmd.getTokenStorage().add(tok);
} catch (TrustException e) {
throw new RampartException("errorInAddingTokenIntoStore", e);
}
}
}