1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.wss4j.stax.impl.processor.input;
20
21 import java.security.Key;
22 import java.util.Deque;
23 import java.util.List;
24
25 import javax.crypto.spec.SecretKeySpec;
26 import jakarta.xml.bind.JAXBElement;
27 import javax.xml.namespace.QName;
28
29 import org.apache.wss4j.binding.wssc.AbstractDerivedKeyTokenType;
30 import org.apache.wss4j.common.derivedKey.DerivedKeyUtils;
31 import org.apache.wss4j.common.ext.WSSecurityException;
32 import org.apache.wss4j.stax.ext.WSInboundSecurityContext;
33 import org.apache.wss4j.stax.ext.WSSConstants;
34 import org.apache.wss4j.stax.ext.WSSSecurityProperties;
35 import org.apache.wss4j.stax.impl.securityToken.SecurityTokenFactoryImpl;
36 import org.apache.wss4j.stax.securityEvent.DerivedKeyTokenSecurityEvent;
37 import org.apache.wss4j.stax.securityToken.UsernameSecurityToken;
38 import org.apache.wss4j.stax.securityToken.WSSecurityTokenConstants;
39 import org.apache.xml.security.exceptions.XMLSecurityException;
40 import org.apache.xml.security.stax.config.JCEAlgorithmMapper;
41 import org.apache.xml.security.stax.ext.AbstractInputSecurityHeaderHandler;
42 import org.apache.xml.security.stax.ext.InputProcessorChain;
43 import org.apache.xml.security.stax.ext.XMLSecurityConstants;
44 import org.apache.xml.security.stax.ext.XMLSecurityProperties;
45 import org.apache.xml.security.stax.ext.stax.XMLSecEvent;
46 import org.apache.xml.security.stax.impl.securityToken.AbstractInboundSecurityToken;
47 import org.apache.xml.security.stax.impl.util.IDGenerator;
48 import org.apache.xml.security.stax.securityEvent.AlgorithmSuiteSecurityEvent;
49 import org.apache.xml.security.stax.securityToken.InboundSecurityToken;
50 import org.apache.xml.security.stax.securityToken.SecurityTokenProvider;
51
52
53
54
55 public class DerivedKeyTokenInputHandler extends AbstractInputSecurityHeaderHandler {
56
57 @Override
58 public void handle(final InputProcessorChain inputProcessorChain, final XMLSecurityProperties securityProperties,
59 Deque<XMLSecEvent> eventQueue, Integer index) throws XMLSecurityException {
60
61 @SuppressWarnings("unchecked")
62 final AbstractDerivedKeyTokenType derivedKeyTokenType =
63 ((JAXBElement<AbstractDerivedKeyTokenType>) parseStructure(eventQueue, index, securityProperties)).getValue();
64 if (derivedKeyTokenType.getId() == null) {
65 derivedKeyTokenType.setId(IDGenerator.generateID(null));
66 }
67 if (derivedKeyTokenType.getSecurityTokenReference() == null) {
68 throw new WSSecurityException(WSSecurityException.ErrorCode.SECURITY_TOKEN_UNAVAILABLE, "noReference");
69 }
70
71 final List<QName> elementPath = getElementPath(eventQueue);
72 final XMLSecEvent responsibleXMLSecStartXMLEvent = getResponsibleStartXMLEvent(eventQueue, index);
73
74 SecurityTokenProvider<InboundSecurityToken> securityTokenProvider = new SecurityTokenProvider<InboundSecurityToken>() {
75
76 private AbstractInboundSecurityToken derivedKeySecurityToken;
77
78 @Override
79 public InboundSecurityToken getSecurityToken() throws XMLSecurityException {
80
81 if (this.derivedKeySecurityToken != null) {
82 return this.derivedKeySecurityToken;
83 }
84
85
86 this.derivedKeySecurityToken = new AbstractInboundSecurityToken(
87 (WSInboundSecurityContext) inputProcessorChain.getSecurityContext(),
88 derivedKeyTokenType.getId(), WSSecurityTokenConstants.KEYIDENTIFIER_SECURITY_TOKEN_DIRECT_REFERENCE,
89 true) {
90
91 private InboundSecurityToken referencedSecurityToken;
92
93 private InboundSecurityToken getReferencedSecurityToken() throws XMLSecurityException {
94 if (this.referencedSecurityToken != null) {
95 return referencedSecurityToken;
96 }
97
98 this.referencedSecurityToken = SecurityTokenFactoryImpl.getSecurityToken(
99 derivedKeyTokenType.getSecurityTokenReference(),
100 ((WSSSecurityProperties) securityProperties).getDecryptionCrypto(),
101 ((WSSSecurityProperties)securityProperties).getCallbackHandler(),
102 inputProcessorChain.getSecurityContext(),
103 (WSSSecurityProperties)securityProperties
104 );
105 this.referencedSecurityToken.addWrappedToken(this);
106 return this.referencedSecurityToken;
107 }
108
109 @Override
110 protected Key getKey(String algorithmURI, XMLSecurityConstants.AlgorithmUsage algorithmUsage,
111 String correlationID) throws XMLSecurityException {
112 byte[] secret;
113 InboundSecurityToken referencedSecurityToken = getReferencedSecurityToken();
114 if (referencedSecurityToken != null) {
115 if (referencedSecurityToken instanceof UsernameSecurityToken) {
116 UsernameSecurityToken usernameSecurityToken = (UsernameSecurityToken) referencedSecurityToken;
117 secret = usernameSecurityToken.generateDerivedKey();
118 } else {
119 secret = referencedSecurityToken.getSecretKey(algorithmURI, algorithmUsage, correlationID).getEncoded();
120 }
121 } else {
122 throw new WSSecurityException(WSSecurityException.ErrorCode.SECURITY_TOKEN_UNAVAILABLE, "unsupportedKeyId");
123 }
124 byte[] nonce = derivedKeyTokenType.getNonce();
125 if (nonce == null || nonce.length == 0) {
126 throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY_TOKEN, "empty",
127 new Object[] {"Missing wsc:Nonce value"});
128 }
129 String derivedKeyAlgorithm = derivedKeyTokenType.getAlgorithm();
130 if (derivedKeyAlgorithm == null) {
131 derivedKeyAlgorithm = WSSConstants.P_SHA_1;
132 }
133 byte[] keyBytes = DerivedKeyUtils.deriveKey(
134 derivedKeyAlgorithm,
135 derivedKeyTokenType.getLabel(),
136 derivedKeyTokenType.getLength().intValue(),
137 secret,
138 nonce,
139 derivedKeyTokenType.getOffset().intValue()
140 );
141 XMLSecurityConstants.AlgorithmUsage derivedKeyAlgorithmUsage;
142 if (WSSConstants.Enc.equals(algorithmUsage)) {
143 derivedKeyAlgorithmUsage = WSSConstants.ENC_KD;
144 } else {
145 derivedKeyAlgorithmUsage = WSSConstants.SIG_KD;
146 }
147 AlgorithmSuiteSecurityEvent algorithmSuiteSecurityEvent = new AlgorithmSuiteSecurityEvent();
148 algorithmSuiteSecurityEvent.setAlgorithmURI(derivedKeyAlgorithm);
149 algorithmSuiteSecurityEvent.setAlgorithmUsage(derivedKeyAlgorithmUsage);
150 algorithmSuiteSecurityEvent.setKeyLength(keyBytes.length * 8);
151 algorithmSuiteSecurityEvent.setCorrelationID(correlationID);
152 inputProcessorChain.getSecurityContext().registerSecurityEvent(algorithmSuiteSecurityEvent);
153
154 String algo = JCEAlgorithmMapper.getJCEKeyAlgorithmFromURI(algorithmURI);
155 return new SecretKeySpec(keyBytes, algo);
156 }
157
158 @Override
159 public InboundSecurityToken getKeyWrappingToken() throws XMLSecurityException {
160 return getReferencedSecurityToken();
161 }
162
163 @Override
164 public WSSecurityTokenConstants.TokenType getTokenType() {
165 return WSSecurityTokenConstants.DerivedKeyToken;
166 }
167 };
168 this.derivedKeySecurityToken.setElementPath(elementPath);
169 this.derivedKeySecurityToken.setXMLSecEvent(responsibleXMLSecStartXMLEvent);
170 return this.derivedKeySecurityToken;
171 }
172
173 @Override
174 public String getId() {
175 return derivedKeyTokenType.getId();
176 }
177 };
178 inputProcessorChain.getSecurityContext().registerSecurityTokenProvider(derivedKeyTokenType.getId(), securityTokenProvider);
179
180
181 DerivedKeyTokenSecurityEvent derivedKeyTokenSecurityEvent = new DerivedKeyTokenSecurityEvent();
182 derivedKeyTokenSecurityEvent.setSecurityToken(securityTokenProvider.getSecurityToken());
183 derivedKeyTokenSecurityEvent.setCorrelationID(derivedKeyTokenType.getId());
184 inputProcessorChain.getSecurityContext().registerSecurityEvent(derivedKeyTokenSecurityEvent);
185 }
186 }