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.message;
21
22 import java.nio.charset.StandardCharsets;
23 import java.security.cert.X509Certificate;
24 import java.util.Arrays;
25
26 import javax.crypto.SecretKey;
27
28 import org.apache.wss4j.common.crypto.Crypto;
29 import org.apache.wss4j.common.crypto.CryptoType;
30 import org.apache.wss4j.common.derivedKey.AlgoFactory;
31 import org.apache.wss4j.common.derivedKey.ConversationConstants;
32 import org.apache.wss4j.common.derivedKey.DerivationAlgorithm;
33 import org.apache.wss4j.common.ext.WSSecurityException;
34 import org.apache.wss4j.common.token.Reference;
35 import org.apache.wss4j.common.token.SecurityTokenReference;
36 import org.apache.wss4j.common.util.KeyUtils;
37 import org.apache.wss4j.common.util.UsernameTokenUtil;
38 import org.apache.wss4j.dom.WSConstants;
39 import org.apache.wss4j.dom.message.token.DerivedKeyToken;
40 import org.apache.wss4j.dom.message.token.KerberosSecurity;
41 import org.apache.wss4j.dom.util.WSSecurityUtil;
42 import org.apache.xml.security.utils.XMLUtils;
43 import org.w3c.dom.Document;
44 import org.w3c.dom.Element;
45
46
47
48
49 public abstract class WSSecDerivedKeyBase extends WSSecSignatureBase {
50
51 private static final org.slf4j.Logger LOG =
52 org.slf4j.LoggerFactory.getLogger(WSSecDerivedKeyBase.class);
53
54
55
56
57 private DerivedKeyToken dkt;
58
59
60
61
62 private String clientLabel = ConversationConstants.DEFAULT_LABEL;
63
64
65
66
67 private String serviceLabel = ConversationConstants.DEFAULT_LABEL;
68
69
70
71
72
73 private String tokenIdentifier;
74
75
76
77
78
79 private boolean tokenIdDirectId;
80
81
82
83
84 private Element strElem;
85
86
87
88
89 private String dktId;
90
91
92
93
94 private byte[] derivedKeyBytes;
95
96 private int wscVersion = ConversationConstants.DEFAULT_VERSION;
97
98 private String customValueType;
99 private X509Certificate useThisCert;
100 private Crypto crypto;
101
102 public WSSecDerivedKeyBase(WSSecHeader securityHeader) {
103 super(securityHeader);
104 setKeyIdentifierType(0);
105 }
106
107 public WSSecDerivedKeyBase(Document doc) {
108 super(doc);
109 setKeyIdentifierType(0);
110 }
111
112
113
114
115
116
117
118 protected abstract int getDerivedKeyLength() throws WSSecurityException;
119
120 public Element getStrElem() {
121 return strElem;
122 }
123
124 public void setStrElem(Element strElem) {
125 this.strElem = strElem;
126 }
127
128 public void setTokenIdentifier(String tokenIdentifier) {
129 this.tokenIdentifier = tokenIdentifier;
130 }
131
132
133
134
135 public String getTokenIdentifier() {
136 return tokenIdentifier;
137 }
138
139
140
141
142
143 public void setX509Certificate(X509Certificate cer) {
144 this.useThisCert = cer;
145 }
146
147
148
149
150
151
152
153
154
155 public String getId() {
156 return dktId;
157 }
158
159
160
161
162
163 public void setClientLabel(String clientLabel) {
164 this.clientLabel = clientLabel;
165 }
166
167
168
169
170
171 public void setServiceLabel(String serviceLabel) {
172 this.serviceLabel = serviceLabel;
173 }
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189 public void prepare(byte[] ephemeralKey) throws WSSecurityException {
190
191 if (ephemeralKey == null || ephemeralKey.length == 0) {
192 LOG.debug("No ephemeral key is supplied for id: " + tokenIdentifier);
193 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE);
194 }
195
196
197
198 int offset = 0;
199 int length = getDerivedKeyLength();
200 byte[] label;
201 String labelText = clientLabel + serviceLabel;
202 label = labelText.getBytes(StandardCharsets.UTF_8);
203 byte[] nonce = UsernameTokenUtil.generateNonce(16);
204
205 byte[] seed = new byte[label.length + nonce.length];
206 System.arraycopy(label, 0, seed, 0, label.length);
207 System.arraycopy(nonce, 0, seed, label.length, nonce.length);
208
209 DerivationAlgorithm algo =
210 AlgoFactory.getInstance(ConversationConstants.DerivationAlgorithm.P_SHA_1);
211 derivedKeyBytes = algo.createKey(ephemeralKey, seed, offset, length);
212
213
214 dkt = new DerivedKeyToken(wscVersion, getDocument());
215 dktId = getIdAllocator().createId("DK-", dkt);
216
217 dkt.setOffset(offset);
218 dkt.setLength(length);
219 dkt.setNonce(XMLUtils.encodeToString(nonce));
220 dkt.setID(dktId);
221 if (addWSUNamespace) {
222 dkt.addWSUNamespace();
223 }
224
225 if (strElem == null) {
226 SecurityTokenReference secRef = new SecurityTokenReference(getDocument());
227 String strUri = getIdAllocator().createSecureId("STR-", secRef);
228 secRef.setID(strUri);
229 if (addWSUNamespace) {
230 secRef.addWSUNamespace();
231 }
232
233 X509Certificate[] certs = getSigningCerts();
234
235 switch (keyIdentifierType) {
236
237 case WSConstants.X509_KEY_IDENTIFIER:
238 secRef.setKeyIdentifier(certs[0]);
239 break;
240
241 case WSConstants.SKI_KEY_IDENTIFIER:
242 secRef.setKeyIdentifierSKI(certs[0], crypto);
243 break;
244
245 case WSConstants.THUMBPRINT_IDENTIFIER:
246 secRef.setKeyIdentifierThumb(certs[0]);
247 break;
248
249 case WSConstants.CUSTOM_KEY_IDENTIFIER:
250 secRef.setKeyIdentifier(customValueType, tokenIdentifier);
251 if (WSConstants.WSS_SAML_KI_VALUE_TYPE.equals(customValueType)) {
252 secRef.addTokenType(WSConstants.WSS_SAML_TOKEN_TYPE);
253 } else if (WSConstants.WSS_SAML2_KI_VALUE_TYPE.equals(customValueType)) {
254 secRef.addTokenType(WSConstants.WSS_SAML2_TOKEN_TYPE);
255 } else if (WSConstants.WSS_ENC_KEY_VALUE_TYPE.equals(customValueType)) {
256 secRef.addTokenType(WSConstants.WSS_ENC_KEY_VALUE_TYPE);
257 }
258 break;
259 default:
260 Reference ref = new Reference(getDocument());
261
262 if (tokenIdDirectId) {
263 ref.setURI(tokenIdentifier);
264 } else {
265 ref.setURI("#" + tokenIdentifier);
266 }
267 if (customValueType != null && customValueType.length() != 0) {
268 ref.setValueType(customValueType);
269 }
270 if (WSConstants.WSS_SAML_KI_VALUE_TYPE.equals(customValueType)) {
271 secRef.addTokenType(WSConstants.WSS_SAML_TOKEN_TYPE);
272 ref.setValueType(customValueType);
273 } else if (WSConstants.WSS_SAML2_KI_VALUE_TYPE.equals(customValueType)) {
274 secRef.addTokenType(WSConstants.WSS_SAML2_TOKEN_TYPE);
275 } else if (WSConstants.WSS_ENC_KEY_VALUE_TYPE.equals(customValueType)) {
276 secRef.addTokenType(WSConstants.WSS_ENC_KEY_VALUE_TYPE);
277 ref.setValueType(customValueType);
278 } else if (KerberosSecurity.isKerberosToken(customValueType)) {
279 secRef.addTokenType(customValueType);
280 ref.setValueType(customValueType);
281 } else if (WSConstants.WSC_SCT.equals(customValueType)
282 || WSConstants.WSC_SCT_05_12.equals(customValueType)) {
283 ref.setValueType(customValueType);
284 } else if (!WSConstants.WSS_USERNAME_TOKEN_VALUE_TYPE.equals(customValueType)) {
285 secRef.addTokenType(WSConstants.WSS_ENC_KEY_VALUE_TYPE);
286 }
287
288 secRef.setReference(ref);
289 break;
290 }
291
292 dkt.setSecurityTokenReference(secRef);
293 } else {
294 dkt.setSecurityTokenReference(strElem);
295 }
296 }
297
298
299
300
301
302
303
304
305
306
307 public void prependDKElementToHeader() {
308 Element securityHeaderElement = getSecurityHeader().getSecurityHeaderElement();
309 WSSecurityUtil.prependChildElement(securityHeaderElement, dkt.getElement());
310 }
311
312 public void appendDKElementToHeader() {
313 Element securityHeaderElement = getSecurityHeader().getSecurityHeaderElement();
314 securityHeaderElement.appendChild(dkt.getElement());
315 }
316
317
318
319
320 public void setWscVersion(int wscVersion) {
321 this.wscVersion = wscVersion;
322 }
323
324 public int getWscVersion() {
325 return wscVersion;
326 }
327
328 public Element getdktElement() {
329 return dkt.getElement();
330 }
331
332 public void setCustomValueType(String customValueType) {
333 this.customValueType = customValueType;
334 }
335
336 public void setTokenIdDirectId(boolean b) {
337 tokenIdDirectId = b;
338 }
339
340
341
342
343 private X509Certificate[] getSigningCerts() throws WSSecurityException {
344 X509Certificate[] certs = null;
345 if (keyIdentifierType == WSConstants.ISSUER_SERIAL
346 || keyIdentifierType == WSConstants.ISSUER_SERIAL_QUOTE_FORMAT
347 || keyIdentifierType == WSConstants.X509_KEY_IDENTIFIER
348 || keyIdentifierType == WSConstants.SKI_KEY_IDENTIFIER
349 || keyIdentifierType == WSConstants.THUMBPRINT_IDENTIFIER) {
350 if (useThisCert == null) {
351 CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
352 cryptoType.setAlias(user);
353 if (crypto == null) {
354 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "noSigCryptoFile");
355 }
356 certs = crypto.getX509Certificates(cryptoType);
357 } else {
358 certs = new X509Certificate[] {useThisCert};
359 }
360 if (certs == null || certs.length <= 0) {
361 throw new WSSecurityException(
362 WSSecurityException.ErrorCode.FAILURE,
363 "noUserCertsFound",
364 new Object[] {user, "signature"});
365 }
366 }
367 return certs;
368 }
369
370 public void setCrypto(Crypto crypto) {
371 this.crypto = crypto;
372 }
373
374 protected SecretKey getDerivedKey(String algorithm) {
375 return KeyUtils.prepareSecretKey(algorithm, derivedKeyBytes);
376 }
377
378 @Override
379 public void clean() {
380 super.clean();
381 if (derivedKeyBytes != null) {
382 Arrays.fill(derivedKeyBytes, (byte)0);
383 }
384 }
385 }