com.sun.xml.wss.impl.apachecrypto.EncryptionProcessor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of webservices-osgi Show documentation
Show all versions of webservices-osgi Show documentation
Metro Web Services Runtime OSGi Bundle
The newest version!
/*
* Copyright (c) 2010, 2022 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0, which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* EncryptionProcessor.java
*
* Created on March 17, 2005, 5:22 PM
*/
package com.sun.xml.wss.impl.apachecrypto;
import org.apache.xml.security.encryption.EncryptedKey;
import org.apache.xml.security.encryption.XMLCipher;
import org.apache.xml.security.keys.KeyInfo;
import org.apache.xml.security.algorithms.JCEMapper;
import org.apache.xml.security.exceptions.Base64DecodingException;
import com.sun.xml.util.XMLCipherAdapter;
import com.sun.xml.wss.core.EncryptedHeaderBlock;
import com.sun.xml.wss.impl.misc.Base64;
import com.sun.xml.wss.impl.FilterProcessingContext;
import com.sun.xml.wss.logging.LogDomainConstants;
import com.sun.xml.wss.impl.MessageConstants;
import com.sun.xml.wss.impl.SecurableSoapMessage;
import com.sun.xml.wss.impl.XMLUtil;
import com.sun.xml.wss.XWSSecurityException;
import com.sun.xml.wss.impl.PolicyTypeUtil;
import com.sun.xml.wss.impl.misc.SecurityUtil;
import com.sun.xml.wss.saml.SAMLException;
import com.sun.xml.wss.core.DerivedKeyTokenHeaderBlock;
import com.sun.xml.wss.core.EncryptedDataHeaderBlock;
import com.sun.xml.wss.core.KeyInfoHeaderBlock;
import com.sun.xml.wss.core.ReferenceListHeaderBlock;
import com.sun.xml.wss.core.SecurityHeader;
import com.sun.xml.wss.core.SecurityTokenReference;
import com.sun.xml.wss.core.X509SecurityToken;
import com.sun.xml.wss.core.reference.DirectReference;
import com.sun.xml.wss.core.reference.EncryptedKeySHA1Identifier;
import com.sun.xml.wss.impl.resolver.AttachmentSignatureInput;
import com.sun.xml.wss.impl.keyinfo.KeyIdentifierStrategy;
import com.sun.xml.wss.impl.misc.KeyResolver;
import com.sun.xml.wss.swa.MimeConstants;
import com.sun.xml.wss.saml.Assertion;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import java.security.Key;
import com.sun.xml.wss.impl.keyinfo.KeyInfoStrategy;
import com.sun.xml.wss.impl.keyinfo.KeyNameStrategy;
import com.sun.xml.wss.impl.policy.mls.AuthenticationTokenPolicy;
import com.sun.xml.wss.impl.policy.mls.EncryptionPolicy;
import com.sun.xml.wss.impl.policy.mls.EncryptionTarget;
import com.sun.xml.wss.impl.policy.mls.SymmetricKeyBinding;
import com.sun.xml.wss.impl.policy.mls.WSSPolicy;
import com.sun.xml.wss.impl.policy.mls.DerivedTokenKeyBinding;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.security.MessageDigest;
import jakarta.xml.soap.SOAPElement;
import jakarta.xml.soap.SOAPHeader;
import jakarta.xml.soap.SOAPPart;
import jakarta.xml.soap.AttachmentPart;
import jakarta.xml.soap.MimeHeader;
import javax.xml.namespace.QName;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.sun.xml.wss.impl.policy.mls.SecureConversationTokenKeyBinding;
import com.sun.xml.ws.security.IssuedTokenContext;
import com.sun.xml.wss.core.SecurityContextTokenImpl;
import com.sun.xml.ws.security.SecurityContextToken;
import com.sun.xml.wss.impl.AlgorithmSuite;
import com.sun.xml.ws.security.impl.DerivedKeyTokenImpl;
import com.sun.xml.ws.security.DerivedKeyToken;
import javax.crypto.spec.SecretKeySpec;
import com.sun.xml.ws.security.trust.GenericToken;
import com.sun.xml.wss.impl.policy.mls.IssuedTokenKeyBinding;
/**
*
* @author XWSS Security Team
* @author [email protected]
*/
public class EncryptionProcessor {
private static byte[] crlf = null;
protected static final Logger log = Logger.getLogger( LogDomainConstants.IMPL_CRYPTO_DOMAIN,
LogDomainConstants.IMPL_CRYPTO_DOMAIN_BUNDLE);
static{
crlf = "\r\n".getBytes(StandardCharsets.US_ASCII);
}
/** Creates a new instance of EncryptionProcessor */
public EncryptionProcessor() {
}
@SuppressWarnings("unchecked")
public static void encrypt(FilterProcessingContext context) throws XWSSecurityException{
//TODO: support for QName and XPath
SecurableSoapMessage secureMsg = context.getSecurableSoapMessage();
SecurityHeader _secHeader = secureMsg.findOrCreateSecurityHeader();
boolean _exportCertificate = false;
SecretKey _symmetricKey = null;
SecretKey keyEncSK = null;
X509Certificate _x509Cert = null;
Key samlkey = null;
KeyInfoStrategy keyInfoStrategy = null;
String referenceType = null;
String x509TokenId = null;
String keyEncAlgo = XMLCipher.RSA_v1dot5;
String dataEncAlgo = MessageConstants.TRIPLE_DES_BLOCK_ENCRYPTION;
String symmetricKeyName = null;
AuthenticationTokenPolicy.X509CertificateBinding certificateBinding = null;
WSSPolicy wssPolicy = (WSSPolicy)context.getSecurityPolicy();
EncryptionPolicy.FeatureBinding featureBinding =(EncryptionPolicy.FeatureBinding) wssPolicy.getFeatureBinding();
WSSPolicy keyBinding = (WSSPolicy)wssPolicy.getKeyBinding();
AlgorithmSuite algSuite = context.getAlgorithmSuite();
SecurityTokenReference samlTokenRef = null;
SecurityTokenReference secConvRef = null;
SecurityTokenReference ekTokenRef = null;
SecurityTokenReference dktSctTokenRef = null;
SecurityTokenReference issuedTokenRef = null;
//adding EncryptedKey Direct Reference to handle EncryptBeforeSigning
SecurityTokenReference ekDirectRef = null;
DerivedKeyTokenHeaderBlock dktHeadrBlock = null;
SecurityContextTokenImpl sct = null;
boolean sctTokenInserted = false;
SOAPElement sctElement = null;
boolean sctWithDKT = false;
boolean includeSCT = true;
boolean issuedWithDKT = false;
SecurityTokenReference dktIssuedTokenRef = null;
SOAPElement issuedTokenElement = null;
Element issuedTokenElementFromMsg = null;
boolean issuedTokenInserted = false;
boolean includeIST = true;
boolean dktSender = false;
//Key obtained from SymmetricKeyBinding in case of DKT
Key originalKey = null;
String ekId = context.getSecurableSoapMessage().generateId();
String insertedEkId = null;
//Check to see if same x509 token used for Signature and Encryption
boolean skbX509TokenInserted = false;
boolean useStandaloneRefList = false;
HashMap ekCache = context.getEncryptedKeyCache();
SOAPElement x509TokenElement = null;
SecurableSoapMessage secureMessage = context.getSecurableSoapMessage();
if(log.isLoggable(Level.FINEST)){
log.log(Level.FINEST, "KeyBinding in Encryption is "+keyBinding);
}
boolean wss11Receiver = "true".equals(context.getExtraneousProperty("EnableWSS11PolicyReceiver"));
boolean wss11Sender = "true".equals(context.getExtraneousProperty("EnableWSS11PolicySender"));
boolean sendEKSHA1 = wss11Receiver && wss11Sender && (getEKSHA1Ref(context) != null);
boolean wss10 = !wss11Sender;
String tmp = featureBinding.getDataEncryptionAlgorithm();
if (tmp == null || "".equals(tmp)) {
if (context.getAlgorithmSuite() != null) {
tmp = context.getAlgorithmSuite().getEncryptionAlgorithm();
} else {
// warn that no dataEncAlgo was set
}
}
//TODO :: Change to getDataEncryptionAlgorith,
if(tmp != null && !"".equals(tmp)){
dataEncAlgo = tmp;
}
if (context.getAlgorithmSuite() != null) {
keyEncAlgo = context.getAlgorithmSuite().getAsymmetricKeyAlgorithm();
}
// derivedTokenKeyBinding with x509 as originalkeyBinding is to be treated same as
// DerivedKey with Symmetric binding and X509 as key binding of Symmetric binding
if(PolicyTypeUtil.derivedTokenKeyBinding(keyBinding)){
DerivedTokenKeyBinding dtk = (DerivedTokenKeyBinding)keyBinding.clone();
WSSPolicy originalKeyBinding = dtk.getOriginalKeyBinding();
if (PolicyTypeUtil.x509CertificateBinding(originalKeyBinding)){
AuthenticationTokenPolicy.X509CertificateBinding ckBindingClone =
(AuthenticationTokenPolicy.X509CertificateBinding)originalKeyBinding.clone();
//create a symmetric key binding and set it as original key binding of dkt
SymmetricKeyBinding skb = new SymmetricKeyBinding();
skb.setKeyBinding(ckBindingClone);
// set the x509 binding as key binding of symmetric binding
dtk.setOriginalKeyBinding(skb);
keyBinding = dtk;
}
}
if (PolicyTypeUtil.usernameTokenPolicy(keyBinding)) {
log.log(Level.SEVERE,"WSS1210.unsupported.UsernameToken.AsKeyBinding.EncryptionPolicy");
throw new XWSSecurityException("UsernameToken as KeyBinding for EncryptionPolicy is Not Yet Supported");
} else if(PolicyTypeUtil.x509CertificateBinding(keyBinding)) {
//we need to use standalone reflist to support EncryptBeforeSigning
useStandaloneRefList=true;
if ( context.getX509CertificateBinding() != null) {
certificateBinding = context.getX509CertificateBinding();
context.setX509CertificateBinding(null);
} else {
certificateBinding =(AuthenticationTokenPolicy.X509CertificateBinding)keyBinding;
}
x509TokenId = certificateBinding.getUUID();
if(x509TokenId == null || x509TokenId.equals("")){
x509TokenId = secureMsg.generateId();
}
if(log.isLoggable(Level.FINEST)){
log.log(Level.FINEST, "Certificate was "+_x509Cert);
log.log(Level.FINEST, "BinaryToken ID "+x509TokenId);
}
HashMap tokenCache = context.getTokenCache();
HashMap insertedX509Cache = context.getInsertedX509Cache();
SecurityUtil.checkIncludeTokenPolicy(context, certificateBinding, x509TokenId);
_x509Cert = certificateBinding.getX509Certificate();
referenceType = certificateBinding.getReferenceType();
if(referenceType.equals("Identifier") && certificateBinding.getValueType().equals(MessageConstants.X509v1_NS)){
log.log(Level.SEVERE,"WSS1211.unsupported.KeyIdentifierStrategy.X509v1");
throw new XWSSecurityException("Key Identifier strategy with X509v1 certificate is not allowed");
}
keyInfoStrategy = KeyInfoStrategy.getInstance(referenceType);
_exportCertificate = true;
keyInfoStrategy.setCertificate(_x509Cert);
if(MessageConstants.DIRECT_REFERENCE_TYPE.equals(referenceType)){
X509SecurityToken token = (X509SecurityToken)tokenCache.get(x509TokenId);
if(token == null){
String valueType = certificateBinding.getValueType();
if(valueType==null||valueType.equals("")){
//default valueType for X509 as v3
valueType = MessageConstants.X509v3_NS;
}
token = new X509SecurityToken(secureMsg.getSOAPPart(),_x509Cert,x509TokenId, valueType);
}
if(insertedX509Cache.get(x509TokenId) == null){
secureMsg.findOrCreateSecurityHeader().insertHeaderBlock(token);
insertedX509Cache.put(x509TokenId, token);
x509TokenElement = secureMsg.findOrCreateSecurityHeader().getNextSiblingOfTimestamp();
} else{
x509TokenElement = secureMsg.getElementByWsuId(x509TokenId);
}
//x509TokenElement = secureMsg.findOrCreateSecurityHeader().getFirstChildElement();
}
//TODO:Revisit this -Venu
tmp = null;
tmp = certificateBinding.getKeyAlgorithm();
if(tmp != null && !tmp.equals("")){
keyEncAlgo = tmp;
}
_symmetricKey = SecurityUtil.generateSymmetricKey(dataEncAlgo);
} else if (PolicyTypeUtil.symmetricKeyBinding(keyBinding)) {
SymmetricKeyBinding skb = null;
if ( context.getSymmetricKeyBinding() != null) {
skb = context.getSymmetricKeyBinding();
context.setSymmetricKeyBinding(null);
} else {
skb = (SymmetricKeyBinding)keyBinding;
}
KeyInfoHeaderBlock keyInfoBlock = null;
if(!skb.getKeyIdentifier().equals(MessageConstants._EMPTY)){
keyEncAlgo = skb.getKeyAlgorithm();
if(keyEncAlgo != null && !"".equals(keyEncAlgo)){
_symmetricKey = SecurityUtil.generateSymmetricKey(dataEncAlgo);
}
keyInfoStrategy = KeyInfoStrategy.getInstance(MessageConstants.KEY_NAME_TYPE);
keyEncSK = skb.getSecretKey();
symmetricKeyName = skb.getKeyIdentifier();
String secKeyAlgo = keyEncSK.getAlgorithm();
if(_symmetricKey == null){
((KeyNameStrategy)keyInfoStrategy).setKeyName(symmetricKeyName);
_symmetricKey = keyEncSK;
keyEncSK = null;
}
} else if (sendEKSHA1) {
//get the signing key and EKSHA1 reference from the Subject, it was stored from the incoming message
String ekSha1Ref = getEKSHA1Ref(context);
_symmetricKey = skb.getSecretKey();
keyInfoBlock = new KeyInfoHeaderBlock(secureMessage.getSOAPPart());
ekTokenRef = new SecurityTokenReference(secureMessage.getSOAPPart());
EncryptedKeySHA1Identifier refElem = new EncryptedKeySHA1Identifier(secureMessage.getSOAPPart());
refElem.setReferenceValue(ekSha1Ref);
ekTokenRef.setReference(refElem);
//set the wsse11:TokenType attribute as required by WSS 1.1
//ekTokenRef.setTokenType(MessageConstants.EncryptedKey_NS);
referenceType = MessageConstants.EK_SHA1_TYPE;
keyInfoStrategy = KeyInfoStrategy.getInstance(referenceType);
//keyInfoStrategy.insertKey(ekTokenRef, secureMsg);
//TODO: the below cond is always true.
} else if (wss11Sender || wss10) {
_symmetricKey = skb.getSecretKey();
useStandaloneRefList = true;
if(!skb.getCertAlias().equals(MessageConstants._EMPTY)){
certificateBinding = new AuthenticationTokenPolicy.X509CertificateBinding();
//x509Binding.newPrivateKeyBinding();
certificateBinding.setCertificateIdentifier(skb.getCertAlias());
_x509Cert = context.getSecurityEnvironment().getCertificate(context.getExtraneousProperties(), certificateBinding.getCertificateIdentifier(), false);
certificateBinding.setX509Certificate(_x509Cert);
certificateBinding.setReferenceType("Direct");
}else if ( context.getX509CertificateBinding() != null ) {
certificateBinding = context.getX509CertificateBinding();
context.setX509CertificateBinding(null);
}
_x509Cert = certificateBinding.getX509Certificate();
x509TokenId = certificateBinding.getUUID();
if(x509TokenId == null || x509TokenId.equals("")){
x509TokenId = secureMsg.generateId();
}
if(log.isLoggable(Level.FINEST)){
log.log(Level.FINEST, "Certificate was "+_x509Cert);
log.log(Level.FINEST, "BinaryToken ID "+x509TokenId);
}
HashMap tokenCache = context.getTokenCache();
HashMap insertedX509Cache = context.getInsertedX509Cache();
SecurityUtil.checkIncludeTokenPolicy(context, certificateBinding, x509TokenId);
X509SecurityToken token = (X509SecurityToken)tokenCache.get(x509TokenId);
if(token == null){
String valueType = certificateBinding.getValueType();
if(valueType==null||valueType.equals("")){
//default valueType for X509 as v3
valueType = MessageConstants.X509v3_NS;
}
token = new X509SecurityToken(secureMsg.getSOAPPart(),_x509Cert,x509TokenId, valueType);
tokenCache.put(x509TokenId, token);
context.setCurrentSecret(_symmetricKey);
} else{
skbX509TokenInserted = true;
_symmetricKey = context.getCurrentSecret();
}
ekTokenRef = new SecurityTokenReference(secureMessage.getSOAPPart());
DirectReference reference = new DirectReference();
insertedEkId = (String)ekCache.get(x509TokenId);
if(insertedEkId == null)
insertedEkId = ekId;
reference.setURI("#"+insertedEkId);
reference.setValueType(MessageConstants.EncryptedKey_NS);
ekTokenRef.setReference(reference);
if(!skbX509TokenInserted){
referenceType = certificateBinding.getReferenceType();
if(referenceType.equals("Identifier") && certificateBinding.getValueType().equals(MessageConstants.X509v1_NS)){
log.log(Level.SEVERE,"WSS1211.unsupported.KeyIdentifierStrategy.X509v1");
throw new XWSSecurityException("Key Identifier strategy with X509v1 is not allowed");
}
keyInfoStrategy = KeyInfoStrategy.getInstance(referenceType);
_exportCertificate = true;
keyInfoStrategy.setCertificate(_x509Cert);
//Store SymmetricKey generated in ProcessingContext
context.setExtraneousProperty("SecretKey", _symmetricKey);
}
if(MessageConstants.DIRECT_REFERENCE_TYPE.equals(referenceType)){
if(insertedX509Cache.get(x509TokenId) == null){
secureMsg.findOrCreateSecurityHeader().insertHeaderBlock(token);
insertedX509Cache.put(x509TokenId, token);
x509TokenElement = secureMsg.findOrCreateSecurityHeader().getNextSiblingOfTimestamp();
} else{
//x509TokenElement = secureMsg.findOrCreateSecurityHeader().getFirstChildElement();
x509TokenElement = secureMsg.getElementByWsuId(x509TokenId);
}
}
}
} else if (PolicyTypeUtil.samlTokenPolicy(keyBinding)) {
//TODO handler saml, it should be a remote SAML Assertion
// since a message from the sender cannot have the receivers assertion as part of message
AuthenticationTokenPolicy.SAMLAssertionBinding samlBinding =
(AuthenticationTokenPolicy.SAMLAssertionBinding)keyBinding;
Assertion assertion1 = null;
try {
if (System.getProperty("com.sun.xml.wss.saml.binding.jaxb") == null ) {
if (samlBinding.getAssertion().getAttributeNode("ID") != null) {
assertion1 = com.sun.xml.wss.saml.assertion.saml20.jaxb20.Assertion.fromElement(samlBinding.getAssertion());
}else{
assertion1 = com.sun.xml.wss.saml.assertion.saml11.jaxb20.Assertion.fromElement(samlBinding.getAssertion());
}
}
} catch (SAMLException ex) {
log.log(Level.SEVERE, "WSS1212.error.SAMLAssertionException");
throw new XWSSecurityException(ex);
}
String assertionID = null;
if (assertion1 != null) {
HashMap tokenCache = context.getTokenCache();
//assuming unique IDs
assertionID = assertion1.getAssertionID();
tokenCache.put(assertionID, assertion1);
} else{
log.log(Level.SEVERE,"WSS1213.null.SAMLAssertion");
throw new XWSSecurityException("SAML Assertion is NULL");
}
//Key key = null;
samlkey = KeyResolver.resolveSamlAssertion(
context.getSecurableSoapMessage(), samlBinding.getAssertion(), true, context, assertionID);
/*
_x509Cert = context.getSecurityEnvironment().getCertificate(
context.getExtraneousProperties() ,(PublicKey)key, false);
if (_x509Cert == null) {
log.log(Level.SEVERE,"WSS1214.unableto.locate.certificate.SAMLAssertion");
throw new XWSSecurityException("Could not locate Certificate corresponding to Key in SubjectConfirmation of SAML Assertion");
}*/
if (!"".equals(samlBinding.getKeyAlgorithm())) {
keyEncAlgo = samlBinding.getKeyAlgorithm();
}
_symmetricKey = SecurityUtil.generateSymmetricKey(dataEncAlgo);
referenceType = samlBinding.getReferenceType();
if (referenceType.equals(MessageConstants.EMBEDDED_REFERENCE_TYPE)) {
log.log(Level.SEVERE, "WSS1215.unsupported.EmbeddedReference.SAMLAssertion");
throw new XWSSecurityException("Embedded Reference Type for SAML Assertions not supported yet");
}
String assertionId = null;
if ( assertion1 != null) {
assertionId = assertion1.getAssertionID();
}
Element binding = samlBinding.getAuthorityBinding();
samlTokenRef = new SecurityTokenReference(secureMsg.getSOAPPart());
String strId = samlBinding.getSTRID();
if(strId == null){
strId = secureMsg.generateId();
}
samlTokenRef.setWsuId(strId);
if (binding != null) {
samlTokenRef.setSamlAuthorityBinding(binding, secureMsg.getSOAPPart());
}
keyInfoStrategy = new KeyIdentifierStrategy(assertionId);
keyInfoStrategy.insertKey(samlTokenRef, secureMsg);
} else if ( PolicyTypeUtil.issuedTokenKeyBinding(keyBinding)) {
IssuedTokenContext trustContext = context.getTrustContext();
//get the symmetric key for encryption
try{
_symmetricKey = new SecretKeySpec(trustContext.getProofKey(), SecurityUtil.getSecretKeyAlgorithm(dataEncAlgo));
} catch(Exception e){
log.log(Level.SEVERE, "WSS1216.unableto.get.symmetrickey.Encryption");
throw new XWSSecurityException(e);
}
//Get the IssuedToken and insert it into the message
GenericToken issuedToken = (GenericToken)trustContext.getSecurityToken();
// check if the token is already present
IssuedTokenKeyBinding ikb = (IssuedTokenKeyBinding)keyBinding;
//String ikbPolicyId = ikb.getPolicyToken().getTokenId();
String ikbPolicyId = ikb.getUUID();
//Look for TrustToken in TokenCache
HashMap tokCache = context.getTokenCache();
Object tok = tokCache.get(ikbPolicyId);
SecurityTokenReference str = null;
Element strElem = null;
String tokenVersion = ikb.getIncludeToken();
includeIST = (IssuedTokenKeyBinding.INCLUDE_ALWAYS_TO_RECIPIENT.equals(tokenVersion) ||
IssuedTokenKeyBinding.INCLUDE_ALWAYS.equals(tokenVersion) ||
IssuedTokenKeyBinding.INCLUDE_ALWAYS_VER2.equals(tokenVersion) ||
IssuedTokenKeyBinding.INCLUDE_ALWAYS_TO_RECIPIENT_VER2.equals(tokenVersion)
);
if (includeIST && (issuedToken == null)) {
log.log(Level.SEVERE, "WSS1217.null.IssueToken");
throw new XWSSecurityException("Issued Token to be inserted into the Message was Null");
}
//trust token to be inserted into message
if (issuedToken != null) {
// treat the token as an Opaque entity and just insert the token into message
Element elem = (Element)issuedToken.getTokenValue();
//TODO: remove these expensive conversions DOM Imports
if (tok == null) {
issuedTokenElement = XMLUtil.convertToSoapElement(secureMessage.getSOAPPart(), elem);
//Temp FIX for Issue#26: We need an Id to cache and MS not sending Id in some cases
String tokId = issuedTokenElement.getAttribute("Id");
if ("".equals(tokId) &&
MessageConstants.ENCRYPTED_DATA_LNAME.equals(issuedTokenElement.getLocalName())) {
issuedTokenElement.setAttribute("Id", secureMessage.generateId());
}
tokCache.put(ikbPolicyId, issuedTokenElement);
} else {
issuedTokenInserted = true;
// it will be SOAPElement retrieve its wsuId attr
String wsuId = SecurityUtil.getWsuIdOrId((Element)tok);
issuedTokenElementFromMsg = secureMessage.getElementById(wsuId);
if (issuedTokenElementFromMsg == null) {
log.log(Level.SEVERE, "WSS1218.unableto.locate.IssueToken.Message");
throw new XWSSecurityException("Could not locate Issued Token in Message");
}
}
}
if (includeIST) {
if (trustContext.getAttachedSecurityTokenReference() != null) {
strElem = SecurityUtil.convertSTRToElement(trustContext.getAttachedSecurityTokenReference().getTokenValue(), secureMessage.getSOAPPart());
} else {
log.log(Level.SEVERE, "WSS1219.unableto.refer.Attached.IssueToken");
throw new XWSSecurityException("Cannot determine how to reference the Attached Issued Token in the Message");
}
} else {
//Trust Issued Token should not be in message at all, so use an external reference
if (trustContext.getUnAttachedSecurityTokenReference() != null) {
strElem = SecurityUtil.convertSTRToElement(trustContext.getUnAttachedSecurityTokenReference().getTokenValue(), secureMessage.getSOAPPart());
} else {
log.log(Level.SEVERE, "WSS1220.unableto.refer.Un-Attached.IssueToken");
throw new XWSSecurityException("Cannot determine how to reference the Un-Attached Issued Token in the Message");
}
}
//TODO: remove these expensive conversions
Element imported = (Element)secureMessage.getSOAPPart().importNode(strElem,true);
issuedTokenRef = new SecurityTokenReference(XMLUtil.convertToSoapElement(secureMessage.getSOAPPart(), imported), false);
SecurityUtil.updateSamlVsKeyCache(issuedTokenRef, context, _symmetricKey);
} else if (PolicyTypeUtil.secureConversationTokenKeyBinding(keyBinding)) {
SecureConversationTokenKeyBinding sctBinding = (SecureConversationTokenKeyBinding)keyBinding;
//String sctPolicyId = sctBinding.getPolicyToken().getTokenId();
String sctPolicyId = sctBinding.getUUID();
//Look for SCT in TokenCache
HashMap tokCache = context.getTokenCache();
sct = (SecurityContextTokenImpl)tokCache.get(sctPolicyId);
IssuedTokenContext ictx = context.getSecureConversationContext();
if (sct == null) {
SecurityContextToken sct1 =(SecurityContextToken)ictx.getSecurityToken();
if (sct1 == null) {
log.log(Level.SEVERE,"WSS1221.null.SecureConversationToken");
throw new XWSSecurityException("SecureConversation Token not Found");
}
sct = new SecurityContextTokenImpl(
secureMessage.getSOAPPart(), sct1.getIdentifier().toString(), sct1.getInstance(), sct1.getWsuId(), sct1.getExtElements());
// put back in token cache
tokCache.put(sctPolicyId, sct);
} else {
sctTokenInserted = true;
// record the element
sctElement = secureMessage.getElementByWsuId(sct.getWsuId());
}
String sctWsuId = sct.getWsuId();
if (sctWsuId == null) {
sct.setId(secureMessage.generateId());
}
sctWsuId = sct.getWsuId();
secConvRef = new SecurityTokenReference(secureMessage.getSOAPPart());
DirectReference reference = new DirectReference();
if (SecureConversationTokenKeyBinding.INCLUDE_ALWAYS_TO_RECIPIENT.equals(sctBinding.getIncludeToken()) ||
SecureConversationTokenKeyBinding.INCLUDE_ALWAYS.equals(sctBinding.getIncludeToken())) {
reference.setURI("#" + sctWsuId);
} else {
includeSCT = false;
reference.setSCTURI(sct.getIdentifier().toString(), sct.getInstance());
}
secConvRef.setReference(reference);
referenceType = MessageConstants.DIRECT_REFERENCE_TYPE;
keyInfoStrategy = KeyInfoStrategy.getInstance(referenceType);
String jceAlgo = SecurityUtil.getSecretKeyAlgorithm(dataEncAlgo);
_symmetricKey = new SecretKeySpec(ictx.getProofKey(), jceAlgo);
} else if (PolicyTypeUtil.derivedTokenKeyBinding(keyBinding)){
DerivedTokenKeyBinding dtk = (DerivedTokenKeyBinding)keyBinding.clone();
WSSPolicy originalKeyBinding = dtk.getOriginalKeyBinding();
String algorithm = null;
if(algSuite != null){
algorithm = algSuite.getEncryptionAlgorithm();
}
//The offset and length to be used for DKT
long offset = 0; // Default 0
long length = SecurityUtil.getLengthFromAlgorithm(algorithm);
if (PolicyTypeUtil.x509CertificateBinding(originalKeyBinding)) {
//throw new XWSSecurityException("Asymmetric Binding with DerivedKeys under X509Token Policy Not Yet Supported");
} else if ( PolicyTypeUtil.symmetricKeyBinding(originalKeyBinding)) {
SymmetricKeyBinding skb = null;
if ( context.getSymmetricKeyBinding() != null) {
skb = context.getSymmetricKeyBinding();
context.setSymmetricKeyBinding(null);
} else{
skb = (SymmetricKeyBinding)originalKeyBinding;
}
if(sendEKSHA1){
String ekSha1Ref = getEKSHA1Ref(context);
//Construct a derivedKeyToken to be used
originalKey = skb.getSecretKey();
byte[] secret = originalKey.getEncoded();
DerivedKeyToken dkt = new DerivedKeyTokenImpl(offset, length, secret);
String dktId = secureMessage.generateId();
String nonce = Base64.encode(dkt.getNonce());
//get the symmetric key for encryption key from derivedkeyToken
try{
String jceAlgo = SecurityUtil.getSecretKeyAlgorithm(algorithm);
_symmetricKey = dkt.generateSymmetricKey(jceAlgo);
} catch(Exception e){
log.log(Level.SEVERE, "WSS1216.unableto.get.symmetrickey.Encryption");
throw new XWSSecurityException(e);
}
//STR for DerivedKeyToken
SecurityTokenReference tokenRef = new SecurityTokenReference(secureMessage.getSOAPPart());
EncryptedKeySHA1Identifier refElem = new EncryptedKeySHA1Identifier(secureMessage.getSOAPPart());
refElem.setReferenceValue(ekSha1Ref);
tokenRef.setReference(refElem);
//set the wsse11:TokenType attribute as required by WSS 1.1
//TODO: uncomment this once MS is ready to accpet this
//tokenRef.setTokenType(MessageConstants.EncryptedKey_NS);
dktHeadrBlock =
new DerivedKeyTokenHeaderBlock(_secHeader.getOwnerDocument(), tokenRef, nonce, dkt.getOffset(), dkt.getLength() ,dktId);
//Construct the STR for Encryption
DirectReference reference = new DirectReference();
reference.setURI("#"+dktId);
ekTokenRef = new SecurityTokenReference(secureMessage.getSOAPPart());
ekTokenRef.setReference(reference);
} else if(wss11Sender || wss10){
dktSender = true;
originalKey = skb.getSecretKey();
if ( context.getX509CertificateBinding() != null ) {
certificateBinding = context.getX509CertificateBinding();
context.setX509CertificateBinding(null);
_x509Cert = certificateBinding.getX509Certificate();
}
_x509Cert = certificateBinding.getX509Certificate();
referenceType = certificateBinding.getReferenceType();
keyInfoStrategy = KeyInfoStrategy.getInstance(referenceType);
_exportCertificate = true;
keyInfoStrategy.setCertificate(_x509Cert);
x509TokenId = certificateBinding.getUUID();
if(x509TokenId == null || x509TokenId.equals("")){
x509TokenId = secureMsg.generateId();
}
if(log.isLoggable(Level.FINEST)){
log.log(Level.FINEST, "Certificate was "+_x509Cert);
log.log(Level.FINEST, "BinaryToken ID "+x509TokenId);
}
HashMap tokenCache = context.getTokenCache();
HashMap insertedX509Cache = context.getInsertedX509Cache();
SecurityUtil.checkIncludeTokenPolicy(context, certificateBinding, x509TokenId);
// ReferenceType adjustment in checkIncludeTokenPolicy is also currently
// causing an insertion of the X509 into the Message
X509SecurityToken insertedx509 =
(X509SecurityToken)context.getInsertedX509Cache().get(x509TokenId);
// this one is used to determine if the whole BST + EK + DKT(opt)
// has been inserted by another filter such as Encryption running before
X509SecurityToken token = (X509SecurityToken)tokenCache.get(x509TokenId);
if(token == null){
if (insertedx509 != null) {
token = insertedx509;
tokenCache.put(x509TokenId, insertedx509);
} else {
String valueType = certificateBinding.getValueType();
if(valueType==null||valueType.equals("")){
//default valueType for X509 as v3
valueType = MessageConstants.X509v3_NS;
}
token = new X509SecurityToken(secureMsg.getSOAPPart(),_x509Cert,x509TokenId, valueType);
tokenCache.put(x509TokenId, token);
}
context.setCurrentSecret(originalKey);
//Store SymmetricKey generated in ProcessingContext
context.setExtraneousProperty("SecretKey", originalKey);
} else{
skbX509TokenInserted = true;
originalKey = context.getCurrentSecret();
}
//
if(insertedx509 == null){
if(MessageConstants.DIRECT_REFERENCE_TYPE.equals(referenceType)){
secureMsg.findOrCreateSecurityHeader().insertHeaderBlock(token);
insertedX509Cache.put(x509TokenId, token);
x509TokenElement = secureMsg.findOrCreateSecurityHeader().getNextSiblingOfTimestamp();
}
} else{
//x509TokenElement = secureMsg.getElementByWsuId(x509TokenId);
x509TokenElement = insertedx509;
}
//}
//Construct a derivedKeyToken to be used
byte[] secret = originalKey.getEncoded();
DerivedKeyToken dkt = new DerivedKeyTokenImpl(offset, length, secret);
String dktId = secureMessage.generateId();
String nonce = Base64.encode(dkt.getNonce());
//get the symmetric key for encryption key from derivedkeyToken
try{
String jceAlgo = SecurityUtil.getSecretKeyAlgorithm(algorithm);
_symmetricKey = dkt.generateSymmetricKey(jceAlgo);
} catch(Exception e){
log.log(Level.SEVERE, "WSS1216.unableto.get.symmetrickey.Encryption");
throw new XWSSecurityException(e);
}
//STR for DerivedKeyToken
SecurityTokenReference tokenRef = new SecurityTokenReference(secureMessage.getSOAPPart());
DirectReference reference = new DirectReference();
//TODO: PLUGFEST Commeting for now as Microsoft setting the EncryptedKey type on reference valueType
//tokenRef.setTokenType(MessageConstants.EncryptedKey_NS);
//set id of encrypted key in STR of DKT
insertedEkId = (String)ekCache.get(x509TokenId);
if(insertedEkId == null)
insertedEkId = ekId;
reference.setURI("#"+insertedEkId);
reference.setValueType(MessageConstants.EncryptedKey_NS);
tokenRef.setReference(reference);
dktHeadrBlock =
new DerivedKeyTokenHeaderBlock(_secHeader.getOwnerDocument(), tokenRef, nonce, dkt.getOffset(), dkt.getLength(), dktId);
//Construct the STR for Encryption
DirectReference refEnc = new DirectReference();
refEnc.setURI("#"+dktId);
ekTokenRef = new SecurityTokenReference(secureMessage.getSOAPPart());
ekTokenRef.setReference(refEnc);
}
} else if (PolicyTypeUtil.secureConversationTokenKeyBinding(originalKeyBinding)) {
sctWithDKT = true;
SecureConversationTokenKeyBinding sctBinding = (SecureConversationTokenKeyBinding)originalKeyBinding;
//String sctPolicyId = sctBinding.getPolicyToken().getTokenId();
String sctPolicyId = sctBinding.getUUID();
//Look for SCT in TokenCache
HashMap tokCache = context.getTokenCache();
sct = (SecurityContextTokenImpl)tokCache.get(sctPolicyId);
IssuedTokenContext ictx = context.getSecureConversationContext();
if (sct == null) {
SecurityContextToken sct1 =(SecurityContextToken)ictx.getSecurityToken();
if (sct1 == null) {
log.log(Level.SEVERE, "WSS1221.null.SecureConversationToken");
throw new XWSSecurityException("SecureConversation Token not Found");
}
sct = new SecurityContextTokenImpl(
secureMessage.getSOAPPart(), sct1.getIdentifier().toString(), sct1.getInstance(), sct1.getWsuId(), sct1.getExtElements());
// put back in token cache
tokCache.put(sctPolicyId, sct);
} else {
sctTokenInserted = true;
// record the element
sctElement = secureMessage.getElementByWsuId(sct.getWsuId());
}
String sctWsuId = sct.getWsuId();
if (sctWsuId == null) {
sct.setId(secureMessage.generateId());
}
sctWsuId = sct.getWsuId();
byte[] secret = context.getSecureConversationContext().getProofKey();
DerivedKeyToken dkt = new DerivedKeyTokenImpl(offset, length, secret);
String dktId = secureMessage.generateId();
String nonce = Base64.encode(dkt.getNonce());
//get the symmetric key for encryption key from derivedkeyToken
try{
_symmetricKey = dkt.generateSymmetricKey(SecurityUtil.getSecretKeyAlgorithm(dataEncAlgo));
} catch(Exception e){
log.log(Level.SEVERE, "WSS1216.unableto.get.symmetrickey.Encryption");
throw new XWSSecurityException(e);
}
//STR for DerivedKeyToken
SecurityTokenReference secRef = new SecurityTokenReference(secureMessage.getSOAPPart());
DirectReference reference = new DirectReference();
if (SecureConversationTokenKeyBinding.INCLUDE_ALWAYS_TO_RECIPIENT.equals(sctBinding.getIncludeToken()) ||
SecureConversationTokenKeyBinding.INCLUDE_ALWAYS.equals(sctBinding.getIncludeToken())) {
reference.setURI("#" + sctWsuId);
} else {
includeSCT = false;
reference.setSCTURI(sct.getIdentifier().toString(), sct.getInstance());
}
secRef.setReference(reference);
dktHeadrBlock =
new DerivedKeyTokenHeaderBlock(_secHeader.getOwnerDocument(), secRef, nonce, dkt.getOffset(), dkt.getLength(),dktId);
//Construct the STR for Encryption
DirectReference refEnc = new DirectReference();
refEnc.setURI("#"+dktId);
dktSctTokenRef = new SecurityTokenReference(secureMessage.getSOAPPart());
dktSctTokenRef.setReference(refEnc);
} else if (PolicyTypeUtil.issuedTokenKeyBinding(originalKeyBinding)) {
issuedWithDKT = true;
IssuedTokenContext trustContext = context.getTrustContext();
DerivedKeyToken dkt = new DerivedKeyTokenImpl(offset, length, trustContext.getProofKey());
String dktId = secureMessage.generateId();
String nonce = Base64.encode(dkt.getNonce());
//get the symmetric key for encryption
Key origKey = null;
try{
origKey = new SecretKeySpec(trustContext.getProofKey(), SecurityUtil.getSecretKeyAlgorithm(dataEncAlgo));
} catch(Exception e){
log.log(Level.SEVERE, "WSS1216.unableto.get.symmetrickey.Encryption");
throw new XWSSecurityException(e);
}
//get the symmetric key for encryption key from derivedkeyToken
try{
_symmetricKey = dkt.generateSymmetricKey(SecurityUtil.getSecretKeyAlgorithm(dataEncAlgo));
} catch(Exception e){
log.log(Level.SEVERE, "WSS1216.unableto.get.symmetrickey.Encryption");
throw new XWSSecurityException(e);
}
//Get the IssuedToken and insert it into the message
GenericToken issuedToken = (GenericToken)trustContext.getSecurityToken();
// check if the token is already present
IssuedTokenKeyBinding ikb = (IssuedTokenKeyBinding)originalKeyBinding;
//String ikbPolicyId = ikb.getPolicyToken().getTokenId();
String ikbPolicyId = ikb.getUUID();
//Look for TrustToken in TokenCache
HashMap tokCache = context.getTokenCache();
Object tok = tokCache.get(ikbPolicyId);
SecurityTokenReference str = null;
Element strElem = null;
String tokenVersion = ikb.getIncludeToken();
includeIST = (IssuedTokenKeyBinding.INCLUDE_ALWAYS_TO_RECIPIENT.equals(tokenVersion) ||
IssuedTokenKeyBinding.INCLUDE_ALWAYS.equals(tokenVersion) ||
IssuedTokenKeyBinding.INCLUDE_ALWAYS_VER2.equals(tokenVersion) ||
IssuedTokenKeyBinding.INCLUDE_ALWAYS_TO_RECIPIENT_VER2.equals(tokenVersion)
);
if (includeIST && (issuedToken == null)) {
log.log(Level.SEVERE, "WSS1217.null.IssueToken");
throw new XWSSecurityException("Issued Token to be inserted into the Message was Null");
}
if (issuedToken != null) {
// treat the token as an Opaque entity and just insert the token into message
Element elem = (Element)issuedToken.getTokenValue();
//TODO: remove these expensive conversions DOM Imports
if (tok == null) {
issuedTokenElement = XMLUtil.convertToSoapElement(secureMessage.getSOAPPart(), elem);
//Temp FIX for Issue#26: We need an Id to cache and MS not sending Id in some cases
String tokId = issuedTokenElement.getAttribute("Id");
if ("".equals(tokId) &&
MessageConstants.ENCRYPTED_DATA_LNAME.equals(issuedTokenElement.getLocalName())) {
issuedTokenElement.setAttribute("Id", secureMessage.generateId());
}
tokCache.put(ikbPolicyId, issuedTokenElement);
} else {
issuedTokenInserted = true;
// it will be SOAPElement retrieve its wsuId attr
String wsuId = SecurityUtil.getWsuIdOrId((Element)tok);
issuedTokenElementFromMsg = secureMessage.getElementById(wsuId);
if (issuedTokenElementFromMsg == null) {
log.log(Level.SEVERE, "WSS1218.unableto.locate.IssueToken.Message");
throw new XWSSecurityException("Could not locate Issued Token in Message");
}
}
}
if (includeIST) {
if (trustContext.getAttachedSecurityTokenReference() != null) {
strElem = (Element)trustContext.getAttachedSecurityTokenReference().getTokenValue();
} else {
log.log(Level.SEVERE, "WSS1219.unableto.refer.Attached.IssueToken");
throw new XWSSecurityException("Cannot determine how to reference the Attached Issued Token in the Message");
}
} else {
//Trust Issued Token should not be in message at all, so use an external reference
if (trustContext.getUnAttachedSecurityTokenReference() != null) {
strElem = (Element)trustContext.getUnAttachedSecurityTokenReference().getTokenValue();
} else {
log.log(Level.SEVERE, "WSS1220.unableto.refer.Un-Attached.IssueToken");
throw new XWSSecurityException("Cannot determine how to reference the Un-Attached Issued Token in the Message");
}
}
//TODO: remove these expensive conversions
Element imported = (Element)secureMessage.getSOAPPart().importNode(strElem,true);
str = new SecurityTokenReference(
XMLUtil.convertToSoapElement(secureMessage.getSOAPPart(), (Element)imported.cloneNode(true)), false);
if (origKey != null) {
SecurityUtil.updateSamlVsKeyCache(str, context, origKey);
}
dktHeadrBlock =
new DerivedKeyTokenHeaderBlock(_secHeader.getOwnerDocument(), str, nonce, dkt.getOffset(), dkt.getLength(),dktId);
//Construct the STR for Encryption
DirectReference refEnc = new DirectReference();
refEnc.setURI("#"+dktId);
dktIssuedTokenRef = new SecurityTokenReference(secureMessage.getSOAPPart());
dktIssuedTokenRef.setReference(refEnc);
}
} else {
log.log(Level.SEVERE, "WSS1222.unsupported.KeyBinding.EncryptionPolicy");
throw new XWSSecurityException("Unsupported Key Binding for EncryptionPolicy");
}
XMLCipher _keyEncryptor = null;
XMLCipher _dataEncryptor = null;
Cipher _attachmentEncryptor = null;
try {
// lazy n static instantiation can happen
//TODO :: Algorithms -- Venu
if(log.isLoggable(Level.FINEST)){
log.log(Level.FINEST, "KeyEncryption algorithm is "+keyEncAlgo);
}
if (_x509Cert != null) {
//prepare for keytransport
_keyEncryptor = XMLCipher.getInstance(keyEncAlgo);
_keyEncryptor.init(XMLCipher.WRAP_MODE, _x509Cert.getPublicKey());
} else if (samlkey != null) {
//prepare for keytransport
_keyEncryptor = XMLCipher.getInstance(keyEncAlgo);
_keyEncryptor.init(XMLCipher.WRAP_MODE, samlkey);
}else if( keyEncSK != null){
//prepare for keywrap
_keyEncryptor = XMLCipher.getInstance(keyEncAlgo);
_keyEncryptor.init(XMLCipher.WRAP_MODE, keyEncSK);
}
if(log.isLoggable(Level.FINEST)){
log.log(Level.FINEST, "Data encryption algorithm is "+dataEncAlgo);
}
String dataAlgorithm = JCEMapper.translateURItoJCEID(dataEncAlgo);
_dataEncryptor = XMLCipher.getInstance(dataEncAlgo);
_dataEncryptor.init(XMLCipher.ENCRYPT_MODE, _symmetricKey);
} catch (Exception xee) {
log.log(Level.SEVERE, "WSS1205.unableto.initialize.xml.cipher",xee);
throw new XWSSecurityException(
"Unable to initialize XML Cipher", xee);
}
ArrayList targets = featureBinding.getTargetBindings();
ArrayList _aparts = new ArrayList();
ArrayList _dnodes = new ArrayList();
Iterator i = targets.iterator();
//TODO : remove all the three while loops and
//convert to a 2 loop - Venu
while (i.hasNext()) {
EncryptionTarget target = (EncryptionTarget)i.next();
Boolean cOnly = target.getContentOnly();
if(MessageConstants.PROCESS_ALL_ATTACHMENTS.equals(target.getValue())){
Iterator itr = secureMsg.getAttachments();
while(itr.hasNext()){
AttachmentPart ap = (AttachmentPart)itr.next();
Object[] s = new Object[2];
s[0] = ap;
s[1] = cOnly;
_aparts.add(s);
}
continue;
}
Object mgpart = secureMsg.getMessageParts(target);
//Change this to context.
//TODO :: Venu
ArrayList transforms = target.getCipherReferenceTransforms();
if(mgpart == null){
} else if (mgpart instanceof AttachmentPart) {
Object[] s = new Object[2];
s[0] = mgpart;
s[1] = cOnly;
_aparts.add(s);
} else{
if (mgpart instanceof Node) {
Object[] s = new Object[2];
s[0] = mgpart;
s[1] = cOnly;
_dnodes.add(s);
} else if (mgpart instanceof NodeList) {
for (int j=0; j<((NodeList)mgpart).getLength(); j++) {
Object[] s = new Object[2];
Node n = ((NodeList)mgpart).item(j);
s[0] = n;
s[1] = cOnly;
_dnodes.add(s);
}
}
}
}
if (_dnodes.isEmpty() && _aparts.isEmpty()) {
if(log.isLoggable(Level.WARNING)){
log.log(Level.WARNING, "None of the specified Encryption Parts found in the Message");
}
}
EncryptedKey _encryptedKey = null;
ReferenceListHeaderBlock _ekReferenceList = null;
ReferenceListHeaderBlock _standaloneReferenceList = null;
if (_keyEncryptor != null && !skbX509TokenInserted) {
try {
if(!dktSender){
_encryptedKey = _keyEncryptor.encryptKey(secureMsg.getSOAPPart(), _symmetricKey);
} else{
_encryptedKey = _keyEncryptor.encryptKey(secureMsg.getSOAPPart(), originalKey);
}
_encryptedKey.setId(ekId);
ekCache.put(x509TokenId, ekId);
KeyInfoHeaderBlock keyInfoBlock = new KeyInfoHeaderBlock(secureMsg.getSOAPPart());
if (samlTokenRef != null) {
keyInfoBlock.addSecurityTokenReference(samlTokenRef);
} else if(_x509Cert != null){
keyInfoStrategy.insertKey(keyInfoBlock, secureMsg, x509TokenId);
}else if(keyEncSK != null){
//keyInfoStrategy.insertKey(keyInfoBlock, secureMsg,null);
keyInfoBlock.addKeyName(symmetricKeyName);
}
KeyInfo keyInfo = keyInfoBlock.getKeyInfo(); /*new KeyInfo(keyInfoBlock.getAsSoapElement(), null); */
_encryptedKey.setKeyInfo(keyInfo);
} catch (Exception xe) {
log.log(Level.SEVERE, "WSS1223.unableto.set.KeyInfo.EncryptedKey", xe);
//xe.printStackTrace();
throw new XWSSecurityException(xe);
}
}
if (_encryptedKey != null && !dktSender && !useStandaloneRefList){
_ekReferenceList = new ReferenceListHeaderBlock(secureMsg.getSOAPPart());
}
// process APs - push only EDs (create EDs), modify AP headers/content
//When encrypting content and attachments with the same key process attachments first.
//SWA Spec.
SOAPElement x509Sibling = null;
if(x509TokenElement != null){
x509Sibling = (SOAPElement)x509TokenElement.getNextSibling();
}
Iterator _apartsI = _aparts.iterator();
if(_apartsI.hasNext()){
//We have attachments so get the cipher instances.
try{
//_attachmentEncryptor = Cipher.getInstance("DESede/CBC/ISO10126Padding");
//TODO:GETMAP -venu
_attachmentEncryptor = XMLCipherAdapter.constructCipher(dataEncAlgo);
_attachmentEncryptor.init(Cipher.ENCRYPT_MODE, _symmetricKey);
} catch (Exception xee) {
log.log(Level.SEVERE, "WSS1205.unableto.initialize.xml.cipher", xee);
throw new XWSSecurityException(
"Unable to initialize XML Cipher", xee);
}
}
while (_apartsI.hasNext()) {
Object[] s = (Object[])_apartsI.next();
AttachmentPart p = (AttachmentPart)s[0];
boolean b = (Boolean) s[1];
// create n push an ED
EncryptedDataHeaderBlock edhb = new EncryptedDataHeaderBlock();
String id = secureMsg.generateId();
edhb.setId(id);
edhb.setType( (b ? MessageConstants.ATTACHMENT_CONTENT_ONLY_URI : MessageConstants.ATTACHMENT_COMPLETE_URI));
edhb.setMimeType(p.getContentType());
String uri = p.getContentId();
if (uri != null) {
if ( uri.charAt(0) == '<' && uri.charAt(uri.length()-1) == '>'){
uri = "cid:" + uri.substring(1, uri.length()-1);
}else{
uri = "cid:" + uri;
}
} else {
uri = p.getContentLocation();
}
edhb.getCipherReference(true, uri);
edhb.setEncryptionMethod(dataEncAlgo);
edhb.addTransform(MessageConstants.ATTACHMENT_CONTENT_ONLY_TRANSFORM_URI);
encryptAttachment(p, b, _attachmentEncryptor);
if (_ekReferenceList != null){
_ekReferenceList.addReference("#"+id);
}
if(x509Sibling == null && x509TokenElement == null){
_secHeader.insertHeaderBlock(edhb);
}else{
if(x509Sibling != null){
_secHeader.insertBefore(edhb,x509Sibling);
}else{
_secHeader.appendChild(edhb);
}
}
}
int optType = -1;
Iterator _dnodeI = _dnodes.iterator();
while (_dnodeI.hasNext()) {
Object[] s = (Object[])_dnodeI.next();
Node n = (Node)s[0];
boolean b = (Boolean) s[1];
//TODO :Add Transforms here.
Element ed = null;
boolean _fi = false;
if(context.getConfigType() == MessageConstants.SIGN_ENCRYPT_BODY ){
if(_fi){
ed = encryptBodyContent(secureMsg,context.getCanonicalizedData(),_dataEncryptor);
}else{
signEncrypt(context, null,_ekReferenceList,_standaloneReferenceList,keyInfoStrategy, dataEncAlgo);
continue;
}
}else{
if(n.getNodeType() == Node.TEXT_NODE){
ed = encryptElement(secureMsg, (SOAPElement) n.getParentNode(),true, _dataEncryptor);
}else{
ed = encryptElement(secureMsg, (SOAPElement)n, b, _dataEncryptor);
}
}
EncryptedHeaderBlock ehb = null;
boolean isEhb = false;
EncryptedDataHeaderBlock xencEncryptedData = new EncryptedDataHeaderBlock(
XMLUtil.convertToSoapElement( secureMsg.getSOAPPart(), ed));
String xencEncryptedDataId = secureMsg.generateId();
String xencEncryptedDataRef = "#" + xencEncryptedDataId;
if(ed.getParentNode() instanceof SOAPHeader && wss11Sender){
isEhb = true;
ehb = new EncryptedHeaderBlock(secureMsg.getSOAPPart());
ehb.setId(xencEncryptedDataId);
ehb.copyAttributes(secureMsg, _secHeader);
}else{
xencEncryptedData.setId(xencEncryptedDataId);
}
if (_ekReferenceList != null){
_ekReferenceList.addReference(xencEncryptedDataRef);
}else {
if (_standaloneReferenceList == null){
_standaloneReferenceList = new ReferenceListHeaderBlock(secureMsg.getSOAPPart());
}
_standaloneReferenceList.addReference(xencEncryptedDataRef);
KeyInfoHeaderBlock keyInfoBlock = new KeyInfoHeaderBlock(secureMsg.getSOAPPart());
SecurityTokenReference cloned = null;
if (dktSctTokenRef != null) {
cloned = new SecurityTokenReference((SOAPElement)dktSctTokenRef.cloneNode(true));
keyInfoBlock.addSecurityTokenReference(cloned);
} else if (secConvRef != null) {
cloned = new SecurityTokenReference((SOAPElement)secConvRef.cloneNode(true));
keyInfoBlock.addSecurityTokenReference(cloned);
} else if(ekTokenRef != null){
cloned = new SecurityTokenReference((SOAPElement)ekTokenRef.cloneNode(true));
keyInfoBlock.addSecurityTokenReference(cloned);
} else if (dktIssuedTokenRef != null) {
cloned = new SecurityTokenReference((SOAPElement)dktIssuedTokenRef.cloneNode(true));
keyInfoBlock.addSecurityTokenReference(cloned);
} else if (issuedTokenRef != null) {
cloned = new SecurityTokenReference((SOAPElement)issuedTokenRef.cloneNode(true));
keyInfoBlock.addSecurityTokenReference(cloned);
} else {
if (PolicyTypeUtil.x509CertificateBinding(keyBinding)){
//to handle EncryptBeforeSigning we split EK and RefList even in this case
DirectReference dRef = new DirectReference();
dRef.setURI("#"+ekId);
ekDirectRef = new SecurityTokenReference(secureMessage.getSOAPPart());
ekDirectRef.setReference(dRef);
keyInfoBlock.addSecurityTokenReference(ekDirectRef);
}else {
// this is the default KeyName case
keyInfoStrategy.insertKey(keyInfoBlock, secureMsg, null);
}
}
xencEncryptedData.setKeyInfo(keyInfoBlock);
}
if(isEhb){
try{
ed.getParentNode().replaceChild(ehb.getAsSoapElement(), ed);
ehb.addChildElement(xencEncryptedData.getAsSoapElement());
}catch(Exception se){se.printStackTrace();}
} else{
ed.getParentNode().replaceChild(xencEncryptedData.getAsSoapElement(), ed);
}
}
try {
x509Sibling = null;
if(x509TokenElement != null){
x509Sibling = (SOAPElement)x509TokenElement.getNextSibling();
}
if (_encryptedKey != null) {
SOAPElement se = (SOAPElement)_keyEncryptor.martial(_encryptedKey);
se = _secHeader.makeUsable(se);
if(_ekReferenceList != null)
se.appendChild(_ekReferenceList.getAsSoapElement());
//store EKSHA1 of KeyValue contents in context
Element cipherData = (Element)se.getChildElements(new QName(MessageConstants.XENC_NS, "CipherData", MessageConstants.XENC_PREFIX)).next();
String cipherValue = cipherData.getElementsByTagNameNS(MessageConstants.XENC_NS, "CipherValue").item(0).getTextContent();
byte[] decodedCipher = Base64.decode(cipherValue);
byte[] ekSha1 = MessageDigest.getInstance("SHA-1").digest(decodedCipher);
String encEkSha1 = Base64.encode(ekSha1);
context.setExtraneousProperty("EncryptedKeySHA1", encEkSha1);
if(x509Sibling == null ){
if(x509TokenElement == null){
_secHeader.insertHeaderBlockElement(se);
}else{
_secHeader.appendChild(se);
}
}else{
_secHeader.insertBefore(se,x509Sibling);
}
//For SymmetricBinding with X509 case and for Asym with E before S
if (_standaloneReferenceList != null){
_secHeader.insertBefore(_standaloneReferenceList, se.getNextSibling());
context.setCurrentReferenceList(se.getNextSibling());
}
}else{
if (_standaloneReferenceList != null){
// if SCT or IssuedToken is not already in message then do what we did before WSIT
if ((sctElement == null) && (issuedTokenElementFromMsg == null)) {
if (insertedEkId != null) {
//insert the standalone reflist under EK
Element ekElem = secureMessage.getElementById(insertedEkId);
_secHeader.insertBefore(_standaloneReferenceList, ekElem.getNextSibling());
} else {
_secHeader.insertHeaderBlock(_standaloneReferenceList);
context.setCurrentReferenceList(_standaloneReferenceList.getAsSoapElement());
}
} else {
// insert standalone reflist under the SCT/Issued Token
if (sctElement != null) {
_secHeader.insertBefore(_standaloneReferenceList, sctElement.getNextSibling());
}else if (issuedTokenElementFromMsg != null) {
_secHeader.insertBefore(_standaloneReferenceList, issuedTokenElementFromMsg.getNextSibling());
} else {
_secHeader.insertHeaderBlock(_standaloneReferenceList);
context.setCurrentReferenceList(_standaloneReferenceList.getAsSoapElement());
}
}
}
}
if (sctWithDKT || issuedWithDKT) {
// SCT or IssuedToken not in message so insert it above the DKT in SecHeader
if (sctElement == null && (sct != null)) {
_secHeader.insertHeaderBlock(dktHeadrBlock);
if (includeSCT) {
_secHeader.insertHeaderBlock(sct);
}
} else if (issuedTokenElementFromMsg == null && (issuedTokenElement != null)) {
_secHeader.insertHeaderBlock(dktHeadrBlock);
if (includeIST) {
_secHeader.insertHeaderBlockElement(issuedTokenElement);
}
// also store the token in Packet.invocationProperties to be used by
// client side response processing
context.setIssuedSAMLToken(issuedTokenElement);
} else {
// if the token is already in Message then insert DKT below it.
if (sctElement != null) {
_secHeader.insertBefore(dktHeadrBlock, sctElement.getNextSibling());
} else if (issuedTokenElementFromMsg != null) {
_secHeader.insertBefore(dktHeadrBlock, issuedTokenElementFromMsg.getNextSibling());
} else {
_secHeader.insertHeaderBlock(dktHeadrBlock);
}
}
} else {
//Insert DKT here
// insert the derivedKey into SecurityHeader
if(dktHeadrBlock != null) {
if(insertedEkId != null) { //If DKT referes to EK
Element ekElem = secureMessage.getElementById(insertedEkId);
_secHeader.insertBefore(dktHeadrBlock, ekElem.getNextSibling());
} else{
_secHeader.insertHeaderBlock(dktHeadrBlock);
}
}
// insert the SecurityContextToken if any in the Non DKT path
if (!sctTokenInserted && (sct != null) && includeSCT) {
_secHeader.insertHeaderBlock(sct);
}
// insert trust token if any in the Non DKT path
if (!issuedTokenInserted && (issuedTokenElement != null) && includeIST) {
_secHeader.insertHeaderBlockElement(issuedTokenElement);
// also store the token in Packet.invocationProperties to be used by
// client side response processing
context.setIssuedSAMLToken(issuedTokenElement);
}
}
} catch (Base64DecodingException | NoSuchAlgorithmException e) {
log.log(Level.SEVERE, "WSS1224.error.insertion.HeaderBlock.SecurityHeader", e);
throw new XWSSecurityException(e);
}
}
//Handle encryption of elememnt and element content
private static Element encryptElement(SecurableSoapMessage secureMsg, SOAPElement encryptElm, boolean contentOnly, XMLCipher xmlCipher) throws XWSSecurityException {
String localName = encryptElm.getLocalName();
// BSP: 5607
if (!contentOnly
&& (MessageConstants.SOAP_1_1_NS.equalsIgnoreCase(encryptElm.getNamespaceURI())
|| MessageConstants.SOAP_1_2_NS.equalsIgnoreCase(encryptElm.getNamespaceURI()))
&& ("Header".equalsIgnoreCase(localName) ||
"Envelope".equalsIgnoreCase(localName) ||
"Body".equalsIgnoreCase(localName)) ) {
log.log(Level.SEVERE,
"WSS1206.illegal.target",
encryptElm.getElementName().getQualifiedName());
throw new XWSSecurityException(
"Encryption of SOAP " + localName + " is not allowed"); // BSP 5607
}
SOAPPart soapPart = secureMsg.getSOAPPart();
// Get the relative location of the element we are working on
Node refNode = null;
Node contextNode;
if (contentOnly){
contextNode = encryptElm;
}else {
contextNode = encryptElm.getParentNode();
refNode = encryptElm.getNextSibling();
}
try {
xmlCipher.doFinal(soapPart, encryptElm, contentOnly);
} catch (Exception e) {
log.log(Level.SEVERE, "WSS1207.unableto.encrypt.message");
throw new XWSSecurityException("Unable to encrypt element", e);
}
Element xencEncryptedData;
if (contentOnly){
xencEncryptedData = (Element) contextNode.getFirstChild();
}else {
if (refNode == null){
xencEncryptedData = (Element) contextNode.getLastChild();
}else{
xencEncryptedData = (Element) refNode.getPreviousSibling();
}
}
return xencEncryptedData;
}
private static Element encryptBodyContent(SecurableSoapMessage contextNode ,byte[] canonData,XMLCipher xmlCipher) {
throw new UnsupportedOperationException("Old optimizations disabled in WSIT");
// try{
// EncryptedData ed = xmlCipher.encryptData((Document)contextNode.getSOAPPart(),canonData,true);
// Element encryptedBodyContent = xmlCipher.martial(ed);
// SOAPBody body =
// ((com.sun.xml.messaging.saaj.soap.ExpressMessage)contextNode.getSOAPMessage()).getEMBody();
// body.appendChild(encryptedBodyContent);
// return encryptedBodyContent;
// }catch(Exception e){
// log.log(Level.SEVERE, "WSS1207.unableto.encrypt.message");
// throw new XWSSecurityException("Unable to encrypt element", e);
// }
}
private static void signEncrypt(FilterProcessingContext fpc ,Cipher cipher, ReferenceListHeaderBlock _ekReferenceList,
ReferenceListHeaderBlock _standaloneReferenceList ,KeyInfoStrategy keyInfoStrategy,String encAlgo ) {
throw new UnsupportedOperationException("Not supported in WSIT");
// try{
// byte[] canonData = fpc.getCanonicalizedData();
// byte[] cipherOutput = cipher.doFinal(canonData);
// byte[] iv = cipher.getIV();
// EncryptedDataImpl ed = new EncryptedDataImpl();
//
// ed.setEncryptedData(cipherOutput);
// ed.setIv(iv);
//
// ed.setEncAlgo(encAlgo);
// String xencEncryptedDataId = fpc.getSecurableSoapMessage().generateId();
// String xencEncryptedDataRef = "#" + xencEncryptedDataId;
// ed.setId(xencEncryptedDataId);
// if (_ekReferenceList != null){
// _ekReferenceList.addReference(xencEncryptedDataRef);
// }else {
// if (_standaloneReferenceList == null){
// _standaloneReferenceList = new ReferenceListHeaderBlock(fpc.getSecurableSoapMessage().getSOAPPart());
// }
// _standaloneReferenceList.addReference(xencEncryptedDataRef);
//
// KeyInfoHeaderBlock keyInfoBlock = new KeyInfoHeaderBlock(fpc.getSecurableSoapMessage().getSOAPPart());
// keyInfoStrategy.insertKey(keyInfoBlock, fpc.getSecurableSoapMessage(), null);
// ed.setKeyInfo(keyInfoBlock);
// }
//
// SOAPMessage msg = fpc.getSOAPMessage();
// com.sun.xml.jaxws.JAXWSMessage jxm = ((com.sun.xml.messaging.saaj.soap.ExpressMessage)msg).getJAXWSMessage();
// ed.setXMLSerializer(jxm.getXmlSerializer());
// jxm.setEncryptedBody(ed);
// }catch(Exception e){
// log.log(Level.SEVERE, "WSS1207.unableto.encrypt.message");
// throw new XWSSecurityException("Unable to encrypt element", e);
// }
}
//Start of Attachment code.
private static void encryptAttachment( AttachmentPart part, boolean contentOnly, Cipher cipher) throws XWSSecurityException {
try {
byte[] cipherInput = null;
if (contentOnly) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
part.getDataHandler().writeTo(baos);
cipherInput = baos.toByteArray();
} else {
Object [] obj = AttachmentSignatureInput._getSignatureInput(part);
byte[] headers = serializeHeaders((java.util.Vector) obj[0]);
byte[] content = (byte[]) obj[1];
cipherInput = new byte[headers.length+content.length];
System.arraycopy(headers, 0, cipherInput, 0, headers.length);
System.arraycopy(content, 0, cipherInput, headers.length, content.length);
}
byte[] cipherOutput = cipher.doFinal(cipherInput);
byte[] iv = cipher.getIV();
byte[] encryptedBytes = new byte[iv.length + cipherOutput.length];
System.arraycopy(iv, 0, encryptedBytes, 0, iv.length);
System.arraycopy(cipherOutput, 0, encryptedBytes, iv.length, cipherOutput.length);
int cLength = encryptedBytes.length;
String cType = MimeConstants.APPLICATION_OCTET_STREAM_TYPE;
String uri = part.getContentId();
//Step 9 and 10.SWA spec.
if (!contentOnly){
part.removeAllMimeHeaders();
}
if (uri != null){
part.setMimeHeader(MimeConstants.CONTENT_ID, uri);
}else {
uri = part.getContentLocation();
if (uri != null){
part.setMimeHeader(MimeConstants.CONTENT_LOCATION, uri);
}
}
part.setContentType(cType);
part.setMimeHeader(MimeConstants.CONTENT_LENGTH,Integer.toString(cLength));
part.setMimeHeader("Content-Transfer-Encoding", "base64");
EncryptedAttachmentDataHandler dh = new EncryptedAttachmentDataHandler( new EncryptedAttachmentDataSource(encryptedBytes));
part.setDataHandler(dh);
} catch (Exception e) {
log.log(Level.SEVERE, "WSS1225.error.encrypting.Attachment", e);
throw new XWSSecurityException(e);
}
}
private static String getEKSHA1Ref(FilterProcessingContext context){
String ekSha1Ref = null;
ekSha1Ref = (String) context.getExtraneousProperty(MessageConstants.EK_SHA1_VALUE);
return ekSha1Ref;
}
private static byte[] serializeHeaders(java.util.Vector mimeHeaders) throws XWSSecurityException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
for (int i=0; i < mimeHeaders.size(); i++) {
MimeHeader mh = (MimeHeader) mimeHeaders.elementAt(i);
String name = mh.getName();
String vlue = mh.getValue();
String line = name + ":" + vlue + "\r\n";
byte[] b = line.getBytes(StandardCharsets.US_ASCII);
baos.write(b, 0, b.length);
}
baos.write(crlf, 0, crlf.length);
} catch (Exception e) {
log.log(Level.SEVERE, "WSS1226.error.serialize.headers", e);
throw new XWSSecurityException(e);
}
return baos.toByteArray();
}
private static class EncryptedAttachmentDataSource implements jakarta.activation.DataSource {
byte[] datasource;
EncryptedAttachmentDataSource(byte[] ds) {
datasource = ds;
}
@Override
public String getContentType() {
return MimeConstants.APPLICATION_OCTET_STREAM_TYPE;
}
@Override
public InputStream getInputStream() {
return new ByteArrayInputStream(datasource);
}
@Override
public String getName() {
return "Encrypted Attachment DataSource";
}
@Override
public OutputStream getOutputStream() {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write(datasource, 0, datasource.length);
return baos;
}
}
private static class EncryptedAttachmentDataHandler extends jakarta.activation.DataHandler {
EncryptedAttachmentDataHandler(jakarta.activation.DataSource ds) {
super(ds);
}
@Override
public void writeTo(OutputStream os) throws java.io.IOException {
((ByteArrayOutputStream) getDataSource().getOutputStream()).writeTo(os);
}
}
//End of Attachment code.
}