View Javadoc
1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements. See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership. The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License. You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied. See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.wss4j.stax.impl.processor.output;
20  
21  import java.io.IOException;
22  import java.security.InvalidAlgorithmParameterException;
23  import java.security.InvalidKeyException;
24  import java.security.Key;
25  import java.security.NoSuchAlgorithmException;
26  import java.security.PublicKey;
27  import java.security.cert.X509Certificate;
28  import java.security.spec.AlgorithmParameterSpec;
29  import java.security.spec.MGF1ParameterSpec;
30  import java.util.ArrayList;
31  import java.util.List;
32  
33  import javax.crypto.Cipher;
34  import javax.crypto.IllegalBlockSizeException;
35  import javax.crypto.NoSuchPaddingException;
36  import javax.crypto.spec.OAEPParameterSpec;
37  import javax.crypto.spec.PSource;
38  import javax.security.auth.callback.Callback;
39  import javax.security.auth.callback.UnsupportedCallbackException;
40  import javax.xml.namespace.QName;
41  import javax.xml.stream.XMLStreamException;
42  
43  import org.apache.wss4j.common.ext.WSPasswordCallback;
44  import org.apache.wss4j.common.ext.WSSecurityException;
45  import org.apache.wss4j.stax.ext.WSSConstants;
46  import org.apache.wss4j.stax.ext.WSSSecurityProperties;
47  import org.apache.wss4j.stax.securityToken.WSSecurityTokenConstants;
48  import org.apache.wss4j.stax.utils.WSSUtils;
49  import org.apache.xml.security.exceptions.XMLSecurityException;
50  import org.apache.xml.security.stax.config.JCEAlgorithmMapper;
51  import org.apache.xml.security.stax.ext.AbstractOutputProcessor;
52  import org.apache.xml.security.stax.ext.OutputProcessorChain;
53  import org.apache.xml.security.stax.ext.XMLSecurityConstants;
54  import org.apache.xml.security.stax.ext.stax.XMLSecAttribute;
55  import org.apache.xml.security.stax.ext.stax.XMLSecEvent;
56  import org.apache.xml.security.stax.impl.securityToken.GenericOutboundSecurityToken;
57  import org.apache.xml.security.stax.impl.util.IDGenerator;
58  import org.apache.xml.security.stax.securityToken.OutboundSecurityToken;
59  import org.apache.xml.security.stax.securityToken.SecurityTokenProvider;
60  import org.apache.xml.security.utils.XMLUtils;
61  
62  public class EncryptedKeyOutputProcessor extends AbstractOutputProcessor {
63  
64      public EncryptedKeyOutputProcessor() throws XMLSecurityException {
65          super();
66      }
67  
68      @Override
69      public void processEvent(XMLSecEvent xmlSecEvent, OutputProcessorChain outputProcessorChain)
70          throws XMLStreamException, XMLSecurityException {
71          try {
72  
73              String tokenId = outputProcessorChain.getSecurityContext().get(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTED_KEY);
74              if (tokenId == null) {
75                  throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE);
76              }
77              SecurityTokenProvider<OutboundSecurityToken> wrappingSecurityTokenProvider =
78                      outputProcessorChain.getSecurityContext().getSecurityTokenProvider(tokenId);
79              if (wrappingSecurityTokenProvider == null) {
80                  throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE);
81              }
82              final OutboundSecurityToken wrappingSecurityToken = wrappingSecurityTokenProvider.getSecurityToken();
83              if (wrappingSecurityToken == null) {
84                  throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE);
85              }
86  
87              SecurityTokenProvider<OutboundSecurityToken> encryptedKeySecurityTokenProvider = null;
88              GenericOutboundSecurityToken encryptedKeySecurityToken = null;
89  
90              String sigTokenId =
91                      outputProcessorChain.getSecurityContext().get(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_SIGNATURE);
92              // See if a Symmetric Key is already available
93              String encTokenId =
94                      outputProcessorChain.getSecurityContext().get(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTION);
95              if (encTokenId == null) {
96                  throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE);
97              }
98  
99              encryptedKeySecurityTokenProvider =
100                 outputProcessorChain.getSecurityContext().getSecurityTokenProvider(encTokenId);
101             if (encryptedKeySecurityTokenProvider == null) {
102                 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE);
103             }
104             encryptedKeySecurityToken =
105                     (GenericOutboundSecurityToken)encryptedKeySecurityTokenProvider.getSecurityToken();
106 
107             boolean sharedToken = encTokenId.equals(sigTokenId);
108 
109             FinalEncryptedKeyOutputProcessor finalEncryptedKeyOutputProcessor =
110                 new FinalEncryptedKeyOutputProcessor(encryptedKeySecurityToken);
111             finalEncryptedKeyOutputProcessor.setXMLSecurityProperties(getSecurityProperties());
112             finalEncryptedKeyOutputProcessor.setAction(getAction(), getActionOrder());
113             XMLSecurityConstants.Action action = getAction();
114             if (WSSConstants.ENCRYPTION.equals(action)) {
115                 if (wrappingSecurityToken.getProcessor() != null) {
116                     finalEncryptedKeyOutputProcessor.addBeforeProcessor(wrappingSecurityToken.getProcessor().getClass());
117                     finalEncryptedKeyOutputProcessor.init(outputProcessorChain);
118                 } else if (sharedToken) {
119                     finalEncryptedKeyOutputProcessor.addAfterProcessor(EncryptEndingOutputProcessor.class);
120 
121                     //hint for the headerReordering processor where to place the EncryptedKey
122                     if (getSecurityProperties().getActions().indexOf(WSSConstants.ENCRYPTION)
123                         < getSecurityProperties().getActions().indexOf(WSSConstants.SIGNATURE)) {
124                         finalEncryptedKeyOutputProcessor.addBeforeProcessor(WSSSignatureOutputProcessor.class);
125                         finalEncryptedKeyOutputProcessor.setAction(WSSConstants.SIGNATURE, getActionOrder());
126                     }
127                     finalEncryptedKeyOutputProcessor.setOutputReferenceList(false);
128                     finalEncryptedKeyOutputProcessor.init(outputProcessorChain);
129 
130                     ReferenceListOutputProcessor referenceListOutputProcessor = new ReferenceListOutputProcessor();
131                     referenceListOutputProcessor.addBeforeProcessor(finalEncryptedKeyOutputProcessor.getClass());
132                     referenceListOutputProcessor.setXMLSecurityProperties(getSecurityProperties());
133                     referenceListOutputProcessor.setAction(getAction(), getActionOrder());
134                     referenceListOutputProcessor.init(outputProcessorChain);
135                 } else {
136                     finalEncryptedKeyOutputProcessor.addAfterProcessor(EncryptEndingOutputProcessor.class);
137                     finalEncryptedKeyOutputProcessor.init(outputProcessorChain);
138                 }
139             } else if (WSSConstants.SIGNATURE_WITH_DERIVED_KEY.equals(action)) {
140                 if (wrappingSecurityToken.getProcessor() != null) {
141                     finalEncryptedKeyOutputProcessor.addBeforeProcessor(wrappingSecurityToken.getProcessor().getClass());
142                 } else {
143                     finalEncryptedKeyOutputProcessor.addBeforeProcessor(WSSSignatureOutputProcessor.class);
144                 }
145                 finalEncryptedKeyOutputProcessor.init(outputProcessorChain);
146             } else if (WSSConstants.ENCRYPTION_WITH_DERIVED_KEY.equals(action)) {
147                 if (wrappingSecurityToken.getProcessor() != null) {
148                     finalEncryptedKeyOutputProcessor.addBeforeProcessor(wrappingSecurityToken.getProcessor().getClass());
149                     finalEncryptedKeyOutputProcessor.init(outputProcessorChain);
150                 } else if (sharedToken) {
151                     finalEncryptedKeyOutputProcessor.addBeforeProcessor(WSSSignatureOutputProcessor.class);
152                     finalEncryptedKeyOutputProcessor.addAfterProcessor(EncryptEndingOutputProcessor.class);
153 
154                     //hint for the headerReordering processor where to place the EncryptedKey
155                     if (getSecurityProperties().getActions().indexOf(WSSConstants.ENCRYPTION_WITH_DERIVED_KEY)
156                         < getSecurityProperties().getActions().indexOf(WSSConstants.SIGNATURE_WITH_DERIVED_KEY)) {
157                         finalEncryptedKeyOutputProcessor.setAction(WSSConstants.SIGNATURE_WITH_DERIVED_KEY, getActionOrder());
158                     }
159                     finalEncryptedKeyOutputProcessor.setOutputReferenceList(false);
160                     finalEncryptedKeyOutputProcessor.init(outputProcessorChain);
161                 } else {
162                     finalEncryptedKeyOutputProcessor.addAfterProcessor(EncryptEndingOutputProcessor.class);
163                     finalEncryptedKeyOutputProcessor.init(outputProcessorChain);
164                 }
165                 ReferenceListOutputProcessor referenceListOutputProcessor = new ReferenceListOutputProcessor();
166                 referenceListOutputProcessor.addBeforeProcessor(finalEncryptedKeyOutputProcessor.getClass());
167                 referenceListOutputProcessor.setXMLSecurityProperties(getSecurityProperties());
168                 referenceListOutputProcessor.setAction(getAction(), getActionOrder());
169                 referenceListOutputProcessor.init(outputProcessorChain);
170             } else {
171                 finalEncryptedKeyOutputProcessor.init(outputProcessorChain);
172             }
173 
174             outputProcessorChain.getSecurityContext().registerSecurityTokenProvider(
175                     encryptedKeySecurityToken.getId(), encryptedKeySecurityTokenProvider);
176             encryptedKeySecurityToken.setProcessor(finalEncryptedKeyOutputProcessor);
177         } finally {
178             outputProcessorChain.removeProcessor(this);
179         }
180         outputProcessorChain.processEvent(xmlSecEvent);
181     }
182 
183     class FinalEncryptedKeyOutputProcessor extends AbstractOutputProcessor {
184 
185         private final OutboundSecurityToken securityToken;
186         private boolean outputReferenceList = true;
187 
188         FinalEncryptedKeyOutputProcessor(OutboundSecurityToken securityToken) throws XMLSecurityException {
189             super();
190             this.addAfterProcessor(EncryptedKeyOutputProcessor.class);
191             this.securityToken = securityToken;
192         }
193 
194         protected void setOutputReferenceList(boolean outputReferenceList) {
195             this.outputReferenceList = outputReferenceList;
196         }
197 
198         @Override
199         public void processEvent(XMLSecEvent xmlSecEvent, OutputProcessorChain outputProcessorChain)
200                 throws XMLStreamException, XMLSecurityException {
201 
202             outputProcessorChain.processEvent(xmlSecEvent);
203 
204             if (WSSUtils.isSecurityHeaderElement(xmlSecEvent, ((WSSSecurityProperties) getSecurityProperties()).getActor())) {
205 
206                 final QName headerElementName = WSSConstants.TAG_xenc_EncryptedKey;
207                 OutputProcessorUtils.updateSecurityHeaderOrder(outputProcessorChain, headerElementName, getAction(), false);
208 
209                 OutputProcessorChain subOutputProcessorChain = outputProcessorChain.createSubChain(this);
210 
211                 PublicKey publicKey = null;
212                 if (securityToken.getKeyWrappingToken().getX509Certificates() != null
213                     && securityToken.getKeyWrappingToken().getX509Certificates().length > 0) {
214                     publicKey = securityToken.getKeyWrappingToken().getX509Certificates()[0].getPublicKey();
215                 } else {
216                     publicKey = securityToken.getKeyWrappingToken().getPublicKey();
217                 }
218                 if (publicKey == null) {
219                     throw new WSSecurityException(
220                         WSSecurityException.ErrorCode.FAILURE,
221                         "failedCredentialLoad"
222                     );
223                 }
224 
225                 final String encryptionKeyTransportAlgorithm = getSecurityProperties().getEncryptionKeyTransportAlgorithm();
226 
227                 List<XMLSecAttribute> attributes = new ArrayList<>(1);
228                 attributes.add(createAttribute(WSSConstants.ATT_NULL_Id, securityToken.getId()));
229                 createStartElementAndOutputAsEvent(subOutputProcessorChain, headerElementName, true, attributes);
230 
231                 attributes = new ArrayList<>(1);
232                 attributes.add(createAttribute(WSSConstants.ATT_NULL_Algorithm, encryptionKeyTransportAlgorithm));
233                 createStartElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_xenc_EncryptionMethod, false, attributes);
234 
235                 final String encryptionKeyTransportMGFAlgorithm = getSecurityProperties().getEncryptionKeyTransportMGFAlgorithm();
236 
237                 if (XMLSecurityConstants.NS_XENC11_RSAOAEP.equals(encryptionKeyTransportAlgorithm)
238                     || XMLSecurityConstants.NS_XENC_RSAOAEPMGF1P.equals(encryptionKeyTransportAlgorithm)) {
239 
240                     byte[] oaepParams = getSecurityProperties().getEncryptionKeyTransportOAEPParams();
241                     if (oaepParams != null) {
242                         createStartElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_xenc_OAEPparams,
243                                                            false, null);
244                         createCharactersAndOutputAsEvent(subOutputProcessorChain, XMLUtils.encodeToString(oaepParams));
245                         createEndElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_xenc_OAEPparams);
246                     }
247 
248                     String encryptionKeyTransportDigestAlgorithm = getSecurityProperties().getEncryptionKeyTransportDigestAlgorithm();
249                     if (encryptionKeyTransportDigestAlgorithm != null) {
250                         attributes = new ArrayList<>(1);
251                         attributes.add(createAttribute(XMLSecurityConstants.ATT_NULL_Algorithm, encryptionKeyTransportDigestAlgorithm));
252                         createStartElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_dsig_DigestMethod,
253                                                            true, attributes);
254                         createEndElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_dsig_DigestMethod);
255                     }
256 
257                     if (encryptionKeyTransportMGFAlgorithm != null) {
258                         attributes = new ArrayList<>(1);
259                         attributes.add(createAttribute(XMLSecurityConstants.ATT_NULL_Algorithm, encryptionKeyTransportMGFAlgorithm));
260                         createStartElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_xenc11_MGF,
261                                                            true, attributes);
262                         createEndElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_xenc11_MGF);
263                     }
264                 }
265 
266                 createEndElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_xenc_EncryptionMethod);
267                 createStartElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_dsig_KeyInfo, true, null);
268                 createSecurityTokenReferenceStructureForEncryptedKey(
269                         subOutputProcessorChain, securityToken,
270                         ((WSSSecurityProperties) getSecurityProperties()).getEncryptionKeyIdentifier(),
271                         getSecurityProperties().isUseSingleCert()
272                 );
273                 createEndElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_dsig_KeyInfo);
274                 createStartElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_xenc_CipherData, false, null);
275                 createStartElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_xenc_CipherValue, false, null);
276 
277                 try {
278                     //encrypt the symmetric session key with the public key from the receiver:
279                     String jceid = JCEAlgorithmMapper.translateURItoJCEID(encryptionKeyTransportAlgorithm);
280                     Cipher cipher = Cipher.getInstance(jceid);
281 
282                     AlgorithmParameterSpec algorithmParameterSpec = null;
283                     if (XMLSecurityConstants.NS_XENC11_RSAOAEP.equals(encryptionKeyTransportAlgorithm)
284                         || XMLSecurityConstants.NS_XENC_RSAOAEPMGF1P.equals(encryptionKeyTransportAlgorithm)) {
285 
286                         String jceDigestAlgorithm = "SHA-1";
287                         String encryptionKeyTransportDigestAlgorithm =
288                             getSecurityProperties().getEncryptionKeyTransportDigestAlgorithm();
289                         if (encryptionKeyTransportDigestAlgorithm != null) {
290                             jceDigestAlgorithm = JCEAlgorithmMapper.translateURItoJCEID(encryptionKeyTransportDigestAlgorithm);
291                         }
292 
293                         PSource.PSpecified pSource = PSource.PSpecified.DEFAULT;
294                         byte[] oaepParams = getSecurityProperties().getEncryptionKeyTransportOAEPParams();
295                         if (oaepParams != null) {
296                             pSource = new PSource.PSpecified(oaepParams);
297                         }
298 
299                         MGF1ParameterSpec mgfParameterSpec = new MGF1ParameterSpec("SHA-1");
300                         if (encryptionKeyTransportMGFAlgorithm != null) {
301                             String jceMGFAlgorithm = JCEAlgorithmMapper.translateURItoJCEID(encryptionKeyTransportMGFAlgorithm);
302                             mgfParameterSpec = new MGF1ParameterSpec(jceMGFAlgorithm);
303                         }
304                         algorithmParameterSpec = new OAEPParameterSpec(jceDigestAlgorithm, "MGF1", mgfParameterSpec, pSource);
305                     }
306 
307                     cipher.init(Cipher.WRAP_MODE, publicKey, algorithmParameterSpec);
308 
309                     Key secretKey = securityToken.getSecretKey("");
310 
311                     int blockSize = cipher.getBlockSize();
312                     if (blockSize > 0 && blockSize < secretKey.getEncoded().length) {
313                         throw new WSSecurityException(
314                                 WSSecurityException.ErrorCode.FAILURE,
315                                 "unsupportedKeyTransp",
316                                 new Object[] {"public key algorithm too weak to encrypt symmetric key"}
317                         );
318                     }
319                     byte[] encryptedEphemeralKey = cipher.wrap(secretKey);
320 
321                     if (((WSSSecurityProperties)getSecurityProperties()).getCallbackHandler() != null) {
322                         // Store the Encrypted Key in the CallbackHandler for processing on the inbound side
323                         WSPasswordCallback callback =
324                             new WSPasswordCallback(securityToken.getId(), WSPasswordCallback.SECRET_KEY);
325                         callback.setKey(encryptedEphemeralKey);
326                         try {
327                             ((WSSSecurityProperties)getSecurityProperties()).getCallbackHandler().handle(new Callback[]{callback});
328                         } catch (IOException | UnsupportedCallbackException e) { // NOPMD
329                             // Do nothing
330                         }
331                     }
332 
333                     createCharactersAndOutputAsEvent(subOutputProcessorChain,
334                                                      XMLUtils.encodeToString(encryptedEphemeralKey));
335 
336                 } catch (NoSuchPaddingException | NoSuchAlgorithmException
337                     | InvalidKeyException | IllegalBlockSizeException
338                     | InvalidAlgorithmParameterException e) {
339                     throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e);
340                 }
341 
342                 createEndElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_xenc_CipherValue);
343                 createEndElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_xenc_CipherData);
344 
345                 if (outputReferenceList && WSSConstants.ENCRYPTION.equals(getAction())) {
346                     WSSUtils.createReferenceListStructureForEncryption(this, subOutputProcessorChain);
347                 }
348                 createEndElementAndOutputAsEvent(subOutputProcessorChain, headerElementName);
349                 outputProcessorChain.removeProcessor(this);
350             }
351         }
352 
353         protected void createSecurityTokenReferenceStructureForEncryptedKey(
354                 OutputProcessorChain outputProcessorChain,
355                 OutboundSecurityToken securityToken,
356                 WSSecurityTokenConstants.KeyIdentifier keyIdentifier,
357                 boolean useSingleCertificate)
358                 throws XMLStreamException, XMLSecurityException {
359 
360             if (securityToken.getCustomTokenReference() != null) {
361                 outputDOMElement(securityToken.getCustomTokenReference(), outputProcessorChain);
362                 return;
363             }
364 
365             X509Certificate[] x509Certificates = securityToken.getKeyWrappingToken().getX509Certificates();
366             if ((x509Certificates == null || x509Certificates.length == 0)
367                 && securityToken.getKeyWrappingToken().getPublicKey() != null) {
368                 WSSUtils.createKeyValueTokenStructure(this, outputProcessorChain,
369                                                       securityToken.getKeyWrappingToken().getPublicKey());
370                 return;
371             }
372 
373             List<XMLSecAttribute> attributes = new ArrayList<>(2);
374             attributes.add(createAttribute(WSSConstants.ATT_WSU_ID, IDGenerator.generateID(null)));
375             if (WSSecurityTokenConstants.KEYIDENTIFIER_SECURITY_TOKEN_DIRECT_REFERENCE.equals(keyIdentifier) && !useSingleCertificate) {
376                 attributes.add(createAttribute(WSSConstants.ATT_WSSE11_TOKEN_TYPE, WSSConstants.NS_X509_PKIPATH_V1));
377             }
378             createStartElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_WSSE_SECURITY_TOKEN_REFERENCE, false, attributes);
379 
380             String tokenId = securityToken.getKeyWrappingToken().getId();
381 
382             if (WSSecurityTokenConstants.KeyIdentifier_IssuerSerial.equals(keyIdentifier)) {
383                 WSSUtils.createX509IssuerSerialStructure(this, outputProcessorChain, x509Certificates);
384             } else if (WSSecurityTokenConstants.KeyIdentifier_SkiKeyIdentifier.equals(keyIdentifier)) {
385                 WSSUtils.createX509SubjectKeyIdentifierStructure(this, outputProcessorChain, x509Certificates);
386             } else if (WSSecurityTokenConstants.KeyIdentifier_X509KeyIdentifier.equals(keyIdentifier)) {
387                 WSSUtils.createX509KeyIdentifierStructure(this, outputProcessorChain, x509Certificates);
388             } else if (WSSecurityTokenConstants.KEYIDENTIFIER_THUMBPRINT_IDENTIFIER.equals(keyIdentifier)) {
389                 WSSUtils.createThumbprintKeyIdentifierStructure(this, outputProcessorChain, x509Certificates);
390             } else if (WSSecurityTokenConstants.KEYIDENTIFIER_ENCRYPTED_KEY_SHA1_IDENTIFIER.equals(keyIdentifier)) {
391                 //not applicable, fallback to thumbprint...
392                 WSSUtils.createThumbprintKeyIdentifierStructure(this, outputProcessorChain, x509Certificates);
393             } else if (WSSecurityTokenConstants.KEYIDENTIFIER_SECURITY_TOKEN_DIRECT_REFERENCE.equals(keyIdentifier)) {
394                 String valueType;
395                 if (useSingleCertificate) {
396                     valueType = WSSConstants.NS_X509_V3_TYPE;
397                 } else {
398                     valueType = WSSConstants.NS_X509_PKIPATH_V1;
399                 }
400                 WSSUtils.createBSTReferenceStructure(this, outputProcessorChain, tokenId, valueType, true);
401             } else {
402                 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "unsupportedSecurityToken");
403             }
404             createEndElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_WSSE_SECURITY_TOKEN_REFERENCE);
405         }
406     }
407 }