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.io.ByteArrayInputStream;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.security.*;
26 import java.security.cert.X509Certificate;
27 import java.util.ArrayList;
28 import java.util.Collections;
29 import java.util.List;
30
31 import javax.crypto.Cipher;
32 import javax.crypto.KeyGenerator;
33 import javax.crypto.SecretKey;
34 import javax.crypto.spec.OAEPParameterSpec;
35
36 import org.apache.wss4j.common.WSS4JConstants;
37 import org.apache.wss4j.common.token.DOMX509SKI;
38 import org.apache.xml.security.encryption.AgreementMethod;
39 import org.apache.xml.security.encryption.KeyDerivationMethod;
40 import org.apache.xml.security.encryption.XMLCipherUtil;
41 import org.apache.xml.security.encryption.keys.RecipientKeyInfo;
42 import org.apache.xml.security.encryption.keys.content.AgreementMethodImpl;
43 import org.apache.xml.security.encryption.params.KeyAgreementParameters;
44 import org.apache.xml.security.exceptions.XMLSecurityException;
45 import org.apache.xml.security.keys.content.keyvalues.DSAKeyValue;
46 import org.apache.xml.security.keys.content.keyvalues.ECKeyValue;
47 import org.apache.xml.security.keys.content.keyvalues.KeyValueContent;
48 import org.apache.xml.security.keys.content.keyvalues.RSAKeyValue;
49 import org.apache.xml.security.utils.Constants;
50 import org.apache.xml.security.utils.EncryptionConstants;
51 import org.w3c.dom.Document;
52 import org.w3c.dom.Element;
53 import org.w3c.dom.Node;
54 import org.apache.wss4j.common.bsp.BSPEnforcer;
55 import org.apache.wss4j.common.bsp.BSPRule;
56 import org.apache.wss4j.common.crypto.AlgorithmSuite;
57 import org.apache.wss4j.common.crypto.AlgorithmSuiteValidator;
58 import org.apache.wss4j.common.crypto.CryptoType;
59 import org.apache.wss4j.common.ext.WSSecurityException;
60 import org.apache.wss4j.common.token.DOMX509IssuerSerial;
61 import org.apache.wss4j.common.token.SecurityTokenReference;
62 import org.apache.wss4j.common.util.KeyUtils;
63 import org.apache.wss4j.common.util.XMLUtils;
64 import org.apache.wss4j.dom.WSConstants;
65 import org.apache.wss4j.dom.WSDataRef;
66 import org.apache.wss4j.dom.WSDocInfo;
67 import org.apache.wss4j.dom.engine.WSSecurityEngineResult;
68 import org.apache.wss4j.dom.handler.RequestData;
69 import org.apache.wss4j.dom.str.EncryptedKeySTRParser;
70 import org.apache.wss4j.dom.str.STRParser;
71 import org.apache.wss4j.dom.str.STRParserParameters;
72 import org.apache.wss4j.dom.str.STRParserResult;
73 import org.apache.wss4j.dom.util.EncryptionUtils;
74 import org.apache.wss4j.dom.util.SignatureUtils;
75 import org.apache.wss4j.dom.util.WSSecurityUtil;
76 import org.apache.wss4j.dom.util.X509Util;
77 import org.apache.xml.security.algorithms.JCEMapper;
78 import org.apache.xml.security.encryption.XMLCipher;
79
80 public class EncryptedKeyProcessor implements Processor {
81 private static final org.slf4j.Logger LOG =
82 org.slf4j.LoggerFactory.getLogger(EncryptedKeyProcessor.class);
83
84 public EncryptedKeyProcessor() {
85 }
86
87 public List<WSSecurityEngineResult> handleToken(
88 Element elem,
89 RequestData data
90 ) throws WSSecurityException {
91 return handleToken(elem, data, data.getAlgorithmSuite());
92 }
93
94 public List<WSSecurityEngineResult> handleToken(
95 Element elem,
96 RequestData data,
97 AlgorithmSuite algorithmSuite
98 ) throws WSSecurityException {
99 LOG.debug("Found encrypted key element");
100
101
102 String id = elem.getAttributeNS(null, "Id");
103 if (!id.isEmpty()) {
104 WSSecurityEngineResult result = data.getWsDocInfo().getResult(id);
105 if (result != null
106 && WSConstants.ENCR == (Integer)result.get(WSSecurityEngineResult.TAG_ACTION)
107 ) {
108 return Collections.singletonList(result);
109 }
110 }
111
112 if (data.getCallbackHandler() == null) {
113 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "noCallback");
114 }
115
116
117
118
119 String encryptedKeyTransportMethod = X509Util.getEncAlgo(elem);
120 if (encryptedKeyTransportMethod == null) {
121 throw new WSSecurityException(
122 WSSecurityException.ErrorCode.UNSUPPORTED_ALGORITHM, "noEncAlgo"
123 );
124 }
125 if (WSConstants.KEYTRANSPORT_RSA15.equals(encryptedKeyTransportMethod)
126 && !data.isAllowRSA15KeyTransportAlgorithm()
127 && (algorithmSuite == null
128 || !algorithmSuite.getKeyWrapAlgorithms().contains(WSConstants.KEYTRANSPORT_RSA15))) {
129 LOG.debug(
130 "The Key transport method does not match the requirement"
131 );
132 throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY);
133 }
134
135 Element keyInfoChildElement = getKeyInfoChildElement(elem, data);
136 boolean isDHKeyWrap = isDiffieHellmanKeyWrap(keyInfoChildElement);
137
138 checkBSPCompliance(elem, encryptedKeyTransportMethod, isDHKeyWrap, data.getBSPEnforcer());
139
140
141
142
143 Element xencCipherValue = EncryptionUtils.getCipherValueFromEncryptedData(elem);
144 if (xencCipherValue == null) {
145 throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, "noCipher");
146 }
147
148 X509Certificate[] certs = null;
149 STRParser.REFERENCE_TYPE referenceType = null;
150 PublicKey publicKey = null;
151 boolean symmetricKeyWrap = isSymmetricKeyWrap(encryptedKeyTransportMethod);
152 AgreementMethod agreementMethod = null;
153 KeyDerivationMethod keyDerivationMethod = null;
154 if (isDHKeyWrap) {
155
156 agreementMethod = getAgreementMethodFromElement(keyInfoChildElement);
157 keyDerivationMethod = getKeyDerivationFunction(agreementMethod);
158
159 keyInfoChildElement = getRecipientKeyInfoChildElement(agreementMethod);
160 if (keyInfoChildElement == null) {
161 throw new WSSecurityException(
162 WSSecurityException.ErrorCode.INVALID_SECURITY, "noRecipientSecTokRef"
163 );
164 }
165 }
166 if (!symmetricKeyWrap || isDHKeyWrap) {
167 CertificateResult certificateResult = getPublicKey(keyInfoChildElement, data);
168 certs = certificateResult.getCerts();
169 publicKey = certificateResult.getPublicKey();
170 referenceType = certificateResult.getCertificatesReferenceType();
171 }
172
173
174 if (algorithmSuite != null) {
175 AlgorithmSuiteValidator algorithmSuiteValidator = new
176 AlgorithmSuiteValidator(algorithmSuite);
177
178 if (!symmetricKeyWrap) {
179 algorithmSuiteValidator.checkAsymmetricKeyLength(publicKey);
180 }
181 algorithmSuiteValidator.checkEncryptionKeyWrapAlgorithm(
182 encryptedKeyTransportMethod
183 );
184 if (agreementMethod != null) {
185 algorithmSuiteValidator.checkKeyAgreementMethodAlgorithm(
186 agreementMethod.getAlgorithm()
187 );
188 }
189 if (keyDerivationMethod != null) {
190 algorithmSuiteValidator.checkKeyDerivationFunction(
191 keyDerivationMethod.getAlgorithm()
192 );
193 }
194 }
195
196 byte[] encryptedEphemeralKey = null;
197 byte[] decryptedBytes = null;
198 Element refList =
199 XMLUtils.getDirectChildElement(elem, "ReferenceList", WSConstants.ENC_NS);
200
201
202 String xopUri = EncryptionUtils.getXOPURIFromCipherValue(xencCipherValue);
203 if (xopUri != null && xopUri.startsWith("cid:")) {
204 encryptedEphemeralKey = WSSecurityUtil.getBytesFromAttachment(xopUri, data);
205 } else {
206 encryptedEphemeralKey = EncryptionUtils.getDecodedBase64EncodedData(xencCipherValue);
207 }
208
209 if (isDHKeyWrap) {
210 PrivateKey privateKey = getPrivateKey(data, certs, publicKey);
211 decryptedBytes = getDiffieHellmanDecryptedBytes(data, agreementMethod,
212 encryptedKeyTransportMethod, encryptedEphemeralKey, privateKey);
213 } else if (symmetricKeyWrap) {
214 decryptedBytes = getSymmetricDecryptedBytes(data, data.getWsDocInfo(), keyInfoChildElement, refList);
215 } else {
216 PrivateKey privateKey = getPrivateKey(data, certs, publicKey);
217 decryptedBytes = getAsymmetricDecryptedBytes(data, data.getWsDocInfo(), encryptedKeyTransportMethod,
218 encryptedEphemeralKey, refList,
219 elem, privateKey);
220 }
221
222 List<WSDataRef> dataRefs = decryptDataRefs(refList, data.getWsDocInfo(), decryptedBytes, data);
223
224 WSSecurityEngineResult result = new WSSecurityEngineResult(
225 WSConstants.ENCR,
226 decryptedBytes,
227 encryptedEphemeralKey,
228 dataRefs,
229 certs
230 );
231 result.put(
232 WSSecurityEngineResult.TAG_ENCRYPTED_KEY_TRANSPORT_METHOD,
233 encryptedKeyTransportMethod
234 );
235 result.put(WSSecurityEngineResult.TAG_TOKEN_ELEMENT, elem);
236 String tokenId = elem.getAttributeNS(null, "Id");
237 if (tokenId.length() != 0) {
238 result.put(WSSecurityEngineResult.TAG_ID, tokenId);
239 }
240 if (referenceType != null) {
241 result.put(WSSecurityEngineResult.TAG_X509_REFERENCE_TYPE, referenceType);
242 }
243 if (publicKey != null) {
244 result.put(WSSecurityEngineResult.TAG_PUBLIC_KEY, publicKey);
245 }
246 data.getWsDocInfo().addResult(result);
247 data.getWsDocInfo().addTokenElement(elem);
248 return Collections.singletonList(result);
249 }
250
251
252
253
254
255
256
257
258
259
260 private CertificateResult getPublicKey(Element keyValueElement, RequestData data) throws WSSecurityException {
261 CertificateResult.Builder builder = CertificateResult.Builder.create();
262
263 if (SecurityTokenReference.SECURITY_TOKEN_REFERENCE.equals(keyValueElement.getLocalName())
264 && WSConstants.WSSE_NS.equals(keyValueElement.getNamespaceURI())) {
265 STRParserParameters parameters = new STRParserParameters();
266 parameters.setData(data);
267 parameters.setStrElement(keyValueElement);
268
269 STRParser strParser = new EncryptedKeySTRParser();
270 STRParserResult result = strParser.parseSecurityTokenReference(parameters);
271 builder.certificates(result.getCertificates());
272 builder.publicKey(result.getPublicKey());
273 builder.certificatesReferenceType(result.getCertificatesReferenceType());
274 } else {
275 X509Certificate[] certs = getCertificatesFromX509Data(keyValueElement, data);
276 builder.certificates(certs);
277 if (certs == null || certs.length == 0) {
278 PublicKey publicKey = getPublicKeyFromKeyValue(keyValueElement);
279 builder.publicKey(publicKey);
280 }
281 }
282 return builder.build();
283 }
284
285 private PublicKey getPublicKeyFromKeyValue(Element keyValueElement) throws WSSecurityException {
286 PublicKey publicKey = null;
287 KeyValueContent keyValue;
288 try {
289 Element keyValueChild = getFirstElement(keyValueElement);
290 if (keyValueChild == null) {
291 throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, "unsupportedKeyInfo");
292 }
293 switch (keyValueChild.getLocalName()) {
294 case "ECKeyValue":
295 keyValue = new ECKeyValue(keyValueChild, Constants.SignatureSpec11NS);
296 break;
297 case "RSAKeyValue":
298 keyValue = new RSAKeyValue(keyValueChild, Constants.SignatureSpecNS);
299 break;
300 case "DSAKeyValue":
301 keyValue = new DSAKeyValue(keyValueChild, Constants.SignatureSpecNS);
302 break;
303 default:
304 throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, "unsupportedKeyInfo");
305 }
306
307 publicKey = keyValue.getPublicKey();
308 } catch (XMLSecurityException e) {
309 throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, "unsupportedKeyInfo");
310 }
311 return publicKey;
312 }
313
314 private PrivateKey getPrivateKey(
315 RequestData data, X509Certificate[] certs, PublicKey publicKey
316 ) throws WSSecurityException {
317 try {
318 if (certs != null && certs.length > 0) {
319 return data.getDecCrypto().getPrivateKey(certs[0], data.getCallbackHandler());
320 }
321 return data.getDecCrypto().getPrivateKey(publicKey, data.getCallbackHandler());
322 } catch (WSSecurityException ex) {
323 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK, ex);
324 }
325 }
326
327 private static byte[] getSymmetricDecryptedBytes(
328 RequestData data,
329 WSDocInfo wsDocInfo,
330 Element keyInfoChildElement,
331 Element refList
332 ) throws WSSecurityException {
333
334 String uri = getFirstDataRefURI(refList);
335 String algorithmURI = null;
336 if (uri != null) {
337 Element ee =
338 EncryptionUtils.findEncryptedDataElement(wsDocInfo, uri);
339 algorithmURI = X509Util.getEncAlgo(ee);
340 }
341 return X509Util.getSecretKey(keyInfoChildElement, algorithmURI, data.getCallbackHandler());
342 }
343
344 private static byte[] getAsymmetricDecryptedBytes(
345 RequestData data,
346 WSDocInfo wsDocInfo,
347 String encryptedKeyTransportMethod,
348 byte[] encryptedEphemeralKey,
349 Element refList,
350 Element encryptedKeyElement,
351 PrivateKey privateKey
352 ) throws WSSecurityException {
353 if (data.getDecCrypto() == null) {
354 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "noDecCryptoFile");
355 }
356 String cryptoProvider = data.getDecCrypto().getCryptoProvider();
357 Cipher cipher = KeyUtils.getCipherInstance(encryptedKeyTransportMethod, cryptoProvider);
358 try {
359 OAEPParameterSpec oaepParameterSpec = null;
360 if (WSConstants.KEYTRANSPORT_RSAOAEP.equals(encryptedKeyTransportMethod)
361 || WSConstants.KEYTRANSPORT_RSAOAEP_XENC11.equals(encryptedKeyTransportMethod)) {
362
363 String digestAlgorithm = EncryptionUtils.getDigestAlgorithm(encryptedKeyElement);
364 String mgfAlgorithm = EncryptionUtils.getMGFAlgorithm(encryptedKeyElement);
365 byte[] pSourceBytes = EncryptionUtils.getPSource(encryptedKeyElement);
366 oaepParameterSpec = XMLCipherUtil.constructOAEPParameters(encryptedKeyTransportMethod,
367 digestAlgorithm, mgfAlgorithm, pSourceBytes);
368 }
369
370 if (oaepParameterSpec == null) {
371 cipher.init(Cipher.UNWRAP_MODE, privateKey);
372 } else {
373 cipher.init(Cipher.UNWRAP_MODE, privateKey, oaepParameterSpec);
374 }
375 } catch (Exception ex) {
376 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK, ex);
377 }
378
379 try {
380 String keyAlgorithm = JCEMapper.translateURItoJCEID(encryptedKeyTransportMethod);
381 return cipher.unwrap(encryptedEphemeralKey, keyAlgorithm, Cipher.SECRET_KEY).getEncoded();
382 } catch (IllegalStateException ex) {
383 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK, ex);
384 } catch (Exception ex) {
385 return getRandomKey(refList, wsDocInfo);
386 }
387 }
388
389
390
391
392
393
394
395
396
397
398
399
400
401 private static byte[] getDiffieHellmanDecryptedBytes(
402 RequestData data,
403 AgreementMethod agreementMethod,
404 String encryptedKeyTransportMethod,
405 byte[] encryptedEphemeralKey,
406 PrivateKey privateKey
407 ) throws WSSecurityException {
408
409 SecretKey kek;
410 try {
411 KeyAgreementParameters parameterSpec = XMLCipherUtil.constructRecipientKeyAgreementParameters(
412 encryptedKeyTransportMethod, agreementMethod, privateKey);
413
414 kek = org.apache.xml.security.utils.KeyUtils.aesWrapKeyWithDHGeneratedKey(parameterSpec);
415 } catch (XMLSecurityException ex) {
416 LOG.debug("Error occurred while resolving the Diffie Hellman key: " + ex.getMessage());
417 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK, ex);
418 }
419
420 String cryptoProvider = data.getDecCrypto().getCryptoProvider();
421 Cipher cipher = KeyUtils.getCipherInstance(encryptedKeyTransportMethod, cryptoProvider);
422
423 try {
424 cipher.init(Cipher.UNWRAP_MODE, kek);
425 String keyAlgorithm = JCEMapper.translateURItoJCEID(encryptedKeyTransportMethod);
426 return cipher.unwrap(encryptedEphemeralKey, keyAlgorithm, Cipher.SECRET_KEY).getEncoded();
427 } catch (InvalidKeyException | NoSuchAlgorithmException ex) {
428 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK, ex);
429 }
430 }
431
432
433
434
435
436
437
438
439 private boolean isDiffieHellmanKeyWrap(Element keyInfoChildElement) throws WSSecurityException {
440 if (EncryptionConstants._TAG_AGREEMENTMETHOD.equals(keyInfoChildElement.getLocalName())
441 && WSConstants.ENC_NS.equals(keyInfoChildElement.getNamespaceURI())) {
442 String algorithmURI = keyInfoChildElement.getAttributeNS(null, "Algorithm");
443
444 if (!(WSConstants.AGREEMENT_METHOD_ECDH_ES.equals(algorithmURI)
445 || WSConstants.AGREEMENT_METHOD_X25519.equals(algorithmURI)
446 || WSConstants.AGREEMENT_METHOD_X448.equals(algorithmURI))) {
447 throw new WSSecurityException(
448 WSSecurityException.ErrorCode.UNSUPPORTED_ALGORITHM,
449 "unknownAlgorithm", new Object[]{algorithmURI});
450 }
451 return true;
452 }
453 return false;
454 }
455
456
457
458
459
460
461
462
463 private AgreementMethod getAgreementMethodFromElement(Element keyInfoChildElement) throws WSSecurityException {
464 try {
465 return new AgreementMethodImpl(keyInfoChildElement);
466 } catch (XMLSecurityException ex) {
467 throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, ex);
468 }
469 }
470
471
472
473
474
475
476
477
478 private Element getRecipientKeyInfoChildElement(AgreementMethod agreementMethod) throws WSSecurityException {
479 if (agreementMethod == null) {
480 throw new WSSecurityException(
481 WSSecurityException.ErrorCode.INVALID_SECURITY, "noAgreementMethod"
482 );
483 }
484 try {
485 RecipientKeyInfo recipientKeyInfo = agreementMethod.getRecipientKeyInfo();
486 if (recipientKeyInfo == null) {
487 throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, "noRecipientKeyInfo");
488 }
489 Element receiverKeyInfoElement = recipientKeyInfo.getElement();
490 return getFirstElement(receiverKeyInfoElement);
491 } catch (XMLSecurityException ex) {
492 throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, ex);
493 }
494 }
495
496 private static boolean isSymmetricKeyWrap(String transportAlgorithm) {
497 return XMLCipher.AES_128_KeyWrap.equals(transportAlgorithm)
498 || XMLCipher.AES_192_KeyWrap.equals(transportAlgorithm)
499 || XMLCipher.AES_256_KeyWrap.equals(transportAlgorithm)
500 || XMLCipher.TRIPLEDES_KeyWrap.equals(transportAlgorithm)
501 || XMLCipher.CAMELLIA_128_KeyWrap.equals(transportAlgorithm)
502 || XMLCipher.CAMELLIA_192_KeyWrap.equals(transportAlgorithm)
503 || XMLCipher.CAMELLIA_256_KeyWrap.equals(transportAlgorithm)
504 || XMLCipher.SEED_128_KeyWrap.equals(transportAlgorithm);
505 }
506
507
508
509
510
511 private static byte[] getRandomKey(Element refList, WSDocInfo wsDocInfo) throws WSSecurityException {
512 try {
513 String alg = "AES";
514 int size = 16;
515 String uri = getFirstDataRefURI(refList);
516
517 if (uri != null) {
518 Element ee =
519 EncryptionUtils.findEncryptedDataElement(wsDocInfo, uri);
520 String algorithmURI = X509Util.getEncAlgo(ee);
521 alg = JCEMapper.getJCEKeyAlgorithmFromURI(algorithmURI);
522 size = KeyUtils.getKeyLength(algorithmURI);
523 }
524 KeyGenerator kgen = KeyGenerator.getInstance(alg);
525 kgen.init(size * 8);
526 SecretKey k = kgen.generateKey();
527 return k.getEncoded();
528 } catch (Throwable ex) {
529
530 try {
531 KeyGenerator kgen = KeyGenerator.getInstance("AES");
532 kgen.init(128);
533 SecretKey k = kgen.generateKey();
534 return k.getEncoded();
535 } catch (NoSuchAlgorithmException e) {
536 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK, e);
537 }
538 }
539 }
540
541 private static String getFirstDataRefURI(Element refList) {
542
543 if (refList != null) {
544 for (Node node = refList.getFirstChild(); node != null; node = node.getNextSibling()) {
545 if (Node.ELEMENT_NODE == node.getNodeType()
546 && WSConstants.ENC_NS.equals(node.getNamespaceURI())
547 && "DataReference".equals(node.getLocalName())) {
548 String dataRefURI = ((Element) node).getAttributeNS(null, "URI");
549 return XMLUtils.getIDFromReference(dataRefURI);
550 }
551 }
552 }
553 return null;
554 }
555
556 private Element getKeyInfoChildElement(
557 Element xencEncryptedKey, RequestData data
558 ) throws WSSecurityException {
559 Element keyInfo =
560 XMLUtils.getDirectChildElement(xencEncryptedKey, "KeyInfo", WSConstants.SIG_NS);
561 if (keyInfo != null) {
562 Element strElement = null;
563
564 int result = 0;
565 Node node = keyInfo.getFirstChild();
566 while (node != null) {
567 if (Node.ELEMENT_NODE == node.getNodeType()) {
568 result++;
569 strElement = (Element)node;
570 }
571 node = node.getNextSibling();
572 }
573 if (result != 1) {
574 data.getBSPEnforcer().handleBSPRule(BSPRule.R5424);
575 }
576
577 if (strElement == null) {
578 throw new WSSecurityException(
579 WSSecurityException.ErrorCode.INVALID_SECURITY, "noSecTokRef"
580 );
581 }
582
583 return strElement;
584 } else {
585 throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, "noKeyinfo");
586 }
587 }
588
589
590
591
592
593
594
595
596 private KeyDerivationMethod getKeyDerivationFunction(AgreementMethod agreementMethod) throws WSSecurityException {
597 if (agreementMethod == null) {
598 return null;
599 }
600 try {
601 return agreementMethod.getKeyDerivationMethod();
602 } catch (XMLSecurityException ex) {
603 throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, ex);
604 }
605 }
606
607 private X509Certificate[] getCertificatesFromX509Data(
608 Element keyInfoChildElement,
609 RequestData data
610 ) throws WSSecurityException {
611 X509Certificate[] certs = new X509Certificate[0];
612
613 if (WSConstants.SIG_NS.equals(keyInfoChildElement.getNamespaceURI())
614 && WSConstants.X509_DATA_LN.equals(keyInfoChildElement.getLocalName())) {
615 data.getBSPEnforcer().handleBSPRule(BSPRule.R5426);
616
617 Element issuerSerialElement = XMLUtils.getDirectChildElement(keyInfoChildElement, WSS4JConstants.X509_ISSUER_SERIAL_LN,
618 WSS4JConstants.SIG_NS);
619 if (issuerSerialElement != null) {
620 DOMX509IssuerSerial issuerSerial = new DOMX509IssuerSerial(issuerSerialElement);
621 CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ISSUER_SERIAL);
622 cryptoType.setIssuerSerial(issuerSerial.getIssuer(), issuerSerial.getSerialNumber());
623 certs = data.getDecCrypto().getX509Certificates(cryptoType);
624 }
625
626 Element skiElement = XMLUtils.getDirectChildElement(keyInfoChildElement, WSS4JConstants.X509_SKI_LN, WSS4JConstants.SIG_NS);
627 if (skiElement != null && certs.length == 0) {
628 DOMX509SKI x509SKI = new DOMX509SKI(skiElement);
629 CryptoType cryptoType = new CryptoType(CryptoType.TYPE.SKI_BYTES);
630 cryptoType.setBytes(x509SKI.getSKIBytes());
631 certs = data.getDecCrypto().getX509Certificates(cryptoType);
632 }
633
634 Element x509CertElement = XMLUtils.getDirectChildElement(keyInfoChildElement,
635 WSS4JConstants.X509_CERT_LN, WSS4JConstants.SIG_NS);
636 if (x509CertElement != null && certs.length == 0) {
637 byte[] token = EncryptionUtils.getDecodedBase64EncodedData(x509CertElement);
638 if (token == null || token.length == 0) {
639 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidCertData",
640 new Object[] {"0"});
641 }
642 try (InputStream in = new ByteArrayInputStream(token)) {
643 X509Certificate cert = data.getDecCrypto().loadCertificate(in);
644 if (cert != null) {
645 certs = new X509Certificate[]{cert};
646 }
647 } catch (IOException e) {
648 throw new WSSecurityException(
649 WSSecurityException.ErrorCode.SECURITY_TOKEN_UNAVAILABLE, e, "parseError"
650 );
651 }
652 }
653 }
654
655 return certs;
656 }
657
658 private Element getFirstElement(Element element) {
659 for (Node currentChild = element.getFirstChild();
660 currentChild != null;
661 currentChild = currentChild.getNextSibling()
662 ) {
663 if (Node.ELEMENT_NODE == currentChild.getNodeType()) {
664 return (Element) currentChild;
665 }
666 }
667 return null;
668 }
669
670
671
672
673 protected List<WSDataRef> decryptDataRefs(Element refList, WSDocInfo docInfo,
674 byte[] decryptedBytes, RequestData data
675 ) throws WSSecurityException {
676
677
678
679
680 if (refList == null) {
681 return Collections.emptyList();
682 }
683
684 List<WSDataRef> dataRefs = new ArrayList<>();
685 for (Node node = refList.getFirstChild(); node != null; node = node.getNextSibling()) {
686 if (Node.ELEMENT_NODE == node.getNodeType()
687 && WSConstants.ENC_NS.equals(node.getNamespaceURI())
688 && "DataReference".equals(node.getLocalName())) {
689 String dataRefURI = ((Element) node).getAttributeNS(null, "URI");
690 dataRefURI = XMLUtils.getIDFromReference(dataRefURI);
691
692 WSDataRef dataRef =
693 decryptDataRef(refList.getOwnerDocument(), dataRefURI, docInfo, decryptedBytes, data);
694 dataRefs.add(dataRef);
695 }
696 }
697
698 return dataRefs;
699 }
700
701
702
703
704 protected WSDataRef decryptDataRef(
705 Document doc,
706 String dataRefURI,
707 WSDocInfo docInfo,
708 byte[] decryptedData,
709 RequestData data
710 ) throws WSSecurityException {
711 LOG.debug("found data reference: {}", dataRefURI);
712
713
714
715 Element encryptedDataElement =
716 EncryptionUtils.findEncryptedDataElement(docInfo, dataRefURI);
717 if (encryptedDataElement != null && data.isRequireSignedEncryptedDataElements()) {
718 List<WSSecurityEngineResult> signedResults =
719 docInfo.getResultsByTag(WSConstants.SIGN);
720 SignatureUtils.verifySignedElement(encryptedDataElement, signedResults);
721 }
722
723
724
725 String symEncAlgo = X509Util.getEncAlgo(encryptedDataElement);
726
727
728 if (symEncAlgo == null) {
729 LOG.warn("No encryption algorithm was specified in the request");
730 throw new WSSecurityException(WSSecurityException.ErrorCode.UNSUPPORTED_ALGORITHM, "badEncAlgo",
731 new Object[] {null});
732
733 }
734
735 if (!WSConstants.TRIPLE_DES.equals(symEncAlgo)
736 && !WSConstants.AES_128.equals(symEncAlgo)
737 && !WSConstants.AES_128_GCM.equals(symEncAlgo)
738 && !WSConstants.AES_256.equals(symEncAlgo)
739 && !WSConstants.AES_256_GCM.equals(symEncAlgo)) {
740 data.getBSPEnforcer().handleBSPRule(BSPRule.R5620);
741 }
742
743 SecretKey symmetricKey = null;
744 try {
745 symmetricKey = KeyUtils.prepareSecretKey(symEncAlgo, decryptedData);
746 } catch (IllegalArgumentException ex) {
747 throw new WSSecurityException(
748 WSSecurityException.ErrorCode.UNSUPPORTED_ALGORITHM, ex, "badEncAlgo",
749 new Object[] {symEncAlgo});
750 }
751
752
753 AlgorithmSuite algorithmSuite = data.getAlgorithmSuite();
754 if (algorithmSuite != null) {
755 AlgorithmSuiteValidator algorithmSuiteValidator = new
756 AlgorithmSuiteValidator(algorithmSuite);
757
758 algorithmSuiteValidator.checkSymmetricKeyLength(symmetricKey.getEncoded().length);
759 algorithmSuiteValidator.checkSymmetricEncryptionAlgorithm(symEncAlgo);
760 }
761
762 return EncryptionUtils.decryptEncryptedData(
763 doc, dataRefURI, encryptedDataElement, symmetricKey, symEncAlgo, data.getAttachmentCallbackHandler(),
764 data.getEncryptionSerializer()
765 );
766 }
767
768
769
770
771
772 private void checkBSPCompliance(
773 Element elem, String encAlgo,
774 boolean useKeyWrap,
775 BSPEnforcer bspEnforcer
776 ) throws WSSecurityException {
777 String attribute = elem.getAttributeNS(null, "Type");
778 if (attribute != null && !attribute.isEmpty()) {
779 bspEnforcer.handleBSPRule(BSPRule.R3209);
780 }
781 attribute = elem.getAttributeNS(null, "MimeType");
782 if (attribute != null && !attribute.isEmpty()) {
783 bspEnforcer.handleBSPRule(BSPRule.R5622);
784 }
785 attribute = elem.getAttributeNS(null, "Encoding");
786 if (attribute != null && !attribute.isEmpty()) {
787 bspEnforcer.handleBSPRule(BSPRule.R5623);
788 }
789 attribute = elem.getAttributeNS(null, "Recipient");
790 if (attribute != null && !attribute.isEmpty()) {
791 bspEnforcer.handleBSPRule(BSPRule.R5602);
792 }
793
794 if (useKeyWrap) {
795 if (!(WSConstants.KEYWRAP_AES128.equals(encAlgo)
796 || WSConstants.KEYWRAP_AES192.equals(encAlgo)
797 || WSConstants.KEYWRAP_AES256.equals(encAlgo)
798 || WSConstants.KEYWRAP_TRIPLEDES.equals(encAlgo))) {
799 bspEnforcer.handleBSPRule(BSPRule.R5625);
800 }
801 } else {
802
803 if (!(WSConstants.KEYTRANSPORT_RSA15.equals(encAlgo)
804 || WSConstants.KEYTRANSPORT_RSAOAEP.equals(encAlgo)
805 || WSConstants.KEYTRANSPORT_RSAOAEP_XENC11.equals(encAlgo))) {
806 bspEnforcer.handleBSPRule(BSPRule.R5621);
807 }
808 }
809 }
810 }