1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.wss4j.dom.processor;
21
22 import java.security.Principal;
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.LinkedList;
26 import java.util.List;
27
28 import javax.crypto.SecretKey;
29 import javax.xml.namespace.QName;
30
31 import org.apache.wss4j.common.bsp.BSPEnforcer;
32 import org.apache.wss4j.common.bsp.BSPRule;
33 import org.apache.wss4j.common.crypto.AlgorithmSuite;
34 import org.apache.wss4j.common.crypto.AlgorithmSuiteValidator;
35 import org.apache.wss4j.common.ext.WSSecurityException;
36 import org.apache.wss4j.common.principal.WSDerivedKeyTokenPrincipal;
37 import org.apache.wss4j.common.util.KeyUtils;
38 import org.apache.wss4j.common.util.XMLUtils;
39 import org.apache.wss4j.dom.WSConstants;
40 import org.apache.wss4j.dom.WSDataRef;
41 import org.apache.wss4j.dom.engine.WSSConfig;
42 import org.apache.wss4j.dom.engine.WSSecurityEngineResult;
43 import org.apache.wss4j.dom.handler.RequestData;
44 import org.apache.wss4j.dom.str.STRParser;
45 import org.apache.wss4j.dom.str.STRParserParameters;
46 import org.apache.wss4j.dom.str.STRParserResult;
47 import org.apache.wss4j.dom.str.SecurityTokenRefSTRParser;
48 import org.apache.wss4j.dom.util.EncryptionUtils;
49 import org.apache.wss4j.dom.util.SignatureUtils;
50 import org.apache.wss4j.dom.util.X509Util;
51 import org.w3c.dom.Element;
52
53
54
55
56
57
58 public class EncryptedDataProcessor implements Processor {
59
60 private static final org.slf4j.Logger LOG =
61 org.slf4j.LoggerFactory.getLogger(EncryptedDataProcessor.class);
62
63 public List<WSSecurityEngineResult> handleToken(
64 Element elem,
65 RequestData data
66 ) throws WSSecurityException {
67 LOG.debug("Found EncryptedData element");
68
69 final String encryptedDataId = elem.getAttributeNS(null, "Id");
70
71 Element kiElem =
72 XMLUtils.getDirectChildElement(elem, "KeyInfo", WSConstants.SIG_NS);
73
74 if (kiElem == null) {
75 throw new WSSecurityException(
76 WSSecurityException.ErrorCode.UNSUPPORTED_ALGORITHM, "noKeyinfo"
77 );
78 }
79
80 String symEncAlgo = X509Util.getEncAlgo(elem);
81 checkBSPCompliance(symEncAlgo, data.getBSPEnforcer());
82
83
84 Element secRefToken =
85 XMLUtils.getDirectChildElement(
86 kiElem, "SecurityTokenReference", WSConstants.WSSE_NS
87 );
88 Element encryptedKeyElement =
89 XMLUtils.getDirectChildElement(
90 kiElem, WSConstants.ENC_KEY_LN, WSConstants.ENC_NS
91 );
92 Element retrievalMethodElement =
93 XMLUtils.getDirectChildElement(
94 kiElem, "RetrievalMethod", WSConstants.SIG_NS
95 );
96
97 if (data.isRequireSignedEncryptedDataElements()) {
98 List<WSSecurityEngineResult> signedResults =
99 data.getWsDocInfo().getResultsByTag(WSConstants.SIGN);
100 SignatureUtils.verifySignedElement(elem, signedResults);
101 }
102
103 SecretKey key = null;
104 List<WSSecurityEngineResult> encrKeyResults = null;
105 Principal principal = null;
106 if (secRefToken != null) {
107 STRParserParameters parameters = new STRParserParameters();
108 parameters.setData(data);
109 parameters.setStrElement(secRefToken);
110 if (symEncAlgo != null) {
111 parameters.setDerivationKeyLength(KeyUtils.getKeyLength(symEncAlgo));
112 }
113
114 STRParser strParser = new SecurityTokenRefSTRParser();
115 STRParserResult parserResult = strParser.parseSecurityTokenReference(parameters);
116 byte[] secretKey = parserResult.getSecretKey();
117 principal = parserResult.getPrincipal();
118 key = KeyUtils.prepareSecretKey(symEncAlgo, secretKey);
119 encrKeyResults = new ArrayList<>();
120 } else if (encryptedKeyElement != null && data.getWssConfig() != null) {
121 WSSConfig wssConfig = data.getWssConfig();
122 Processor encrKeyProc = wssConfig.getProcessor(WSConstants.ENCRYPTED_KEY);
123 encrKeyResults = encrKeyProc.handleToken(encryptedKeyElement, data);
124 byte[] symmKey =
125 (byte[])encrKeyResults.get(0).get(WSSecurityEngineResult.TAG_SECRET);
126 key = KeyUtils.prepareSecretKey(symEncAlgo, symmKey);
127 } else if (retrievalMethodElement != null
128 && "http://www.w3.org/2001/04/xmlenc#EncryptedKey".equals(
129 retrievalMethodElement.getAttributeNS(null, "Type"))) {
130 String uri = retrievalMethodElement.getAttributeNS(null, "URI");
131 uri = XMLUtils.getIDFromReference(uri);
132 WSSecurityEngineResult result = data.getWsDocInfo().getResult(uri);
133 if (result != null) {
134 byte[] symmKey = (byte[])result.get(WSSecurityEngineResult.TAG_SECRET);
135 key = KeyUtils.prepareSecretKey(symEncAlgo, symmKey);
136 }
137 } else {
138 throw new WSSecurityException(
139 WSSecurityException.ErrorCode.UNSUPPORTED_ALGORITHM, "noEncKey"
140 );
141 }
142
143 if (key == null) {
144 throw new WSSecurityException(
145 WSSecurityException.ErrorCode.UNSUPPORTED_ALGORITHM, "noEncKey"
146 );
147 }
148
149
150 AlgorithmSuite algorithmSuite = data.getAlgorithmSuite();
151 if (algorithmSuite != null) {
152 AlgorithmSuiteValidator algorithmSuiteValidator = new
153 AlgorithmSuiteValidator(algorithmSuite);
154
155 if (principal instanceof WSDerivedKeyTokenPrincipal) {
156 algorithmSuiteValidator.checkDerivedKeyAlgorithm(
157 ((WSDerivedKeyTokenPrincipal)principal).getAlgorithm()
158 );
159 algorithmSuiteValidator.checkEncryptionDerivedKeyLength(
160 ((WSDerivedKeyTokenPrincipal)principal).getLength()
161 );
162 }
163 algorithmSuiteValidator.checkSymmetricKeyLength(key.getEncoded().length);
164 algorithmSuiteValidator.checkSymmetricEncryptionAlgorithm(symEncAlgo);
165 }
166
167 WSDataRef dataRef = EncryptionUtils.decryptEncryptedData(
168 elem.getOwnerDocument(), encryptedDataId, elem, key, symEncAlgo,
169 data.getAttachmentCallbackHandler(), data.getEncryptionSerializer());
170
171 WSSecurityEngineResult result =
172 new WSSecurityEngineResult(WSConstants.ENCR, Collections.singletonList(dataRef));
173 if (encryptedDataId.length() != 0) {
174 result.put(WSSecurityEngineResult.TAG_ID, encryptedDataId);
175 }
176 data.getWsDocInfo().addResult(result);
177 data.getWsDocInfo().addTokenElement(elem);
178
179 List<WSSecurityEngineResult> completeResults = new LinkedList<>();
180 if (encrKeyResults != null) {
181 completeResults.addAll(encrKeyResults);
182 }
183 completeResults.add(result);
184
185 WSSConfig wssConfig = data.getWssConfig();
186 if (wssConfig != null) {
187
188 Element decryptedElem = dataRef.getProtectedElement();
189 if (decryptedElem != null) {
190 QName el = new QName(decryptedElem.getNamespaceURI(), decryptedElem.getLocalName());
191 Processor proc = data.getWssConfig().getProcessor(el);
192 if (proc != null) {
193 LOG.debug("Processing decrypted element with: {}", proc.getClass().getName());
194 List<WSSecurityEngineResult> results = proc.handleToken(decryptedElem, data);
195 completeResults.addAll(0, results);
196 return completeResults;
197 }
198 }
199 }
200 return completeResults;
201 }
202
203
204
205
206
207
208 private static void checkBSPCompliance(
209 String encAlgo, BSPEnforcer bspEnforcer
210 ) throws WSSecurityException {
211
212 if (encAlgo == null) {
213 bspEnforcer.handleBSPRule(BSPRule.R5601);
214 }
215
216 if (!WSConstants.TRIPLE_DES.equals(encAlgo)
217 && !WSConstants.AES_128.equals(encAlgo)
218 && !WSConstants.AES_128_GCM.equals(encAlgo)
219 && !WSConstants.AES_256.equals(encAlgo)
220 && !WSConstants.AES_256_GCM.equals(encAlgo)) {
221 bspEnforcer.handleBSPRule(BSPRule.R5620);
222 }
223 }
224 }