@Override
public void handle(final InputProcessorChain inputProcessorChain, final XMLSecurityProperties securityProperties,
Deque<XMLSecEvent> eventQueue, Integer index) throws XMLSecurityException {
@SuppressWarnings("unchecked")
final AbstractDerivedKeyTokenType derivedKeyTokenType =
((JAXBElement<AbstractDerivedKeyTokenType>) parseStructure(eventQueue, index, securityProperties)).getValue();
if (derivedKeyTokenType.getId() == null) {
derivedKeyTokenType.setId(IDGenerator.generateID(null));
}
if (derivedKeyTokenType.getSecurityTokenReference() == null) {
throw new WSSecurityException(WSSecurityException.ErrorCode.SECURITY_TOKEN_UNAVAILABLE, "noReference");
}
final List<QName> elementPath = getElementPath(eventQueue);
final XMLSecEvent responsibleXMLSecStartXMLEvent = getResponsibleStartXMLEvent(eventQueue, index);
SecurityTokenProvider<InboundSecurityToken> securityTokenProvider = new SecurityTokenProvider<InboundSecurityToken>() {
private AbstractInboundSecurityToken derivedKeySecurityToken = null;
@Override
public InboundSecurityToken getSecurityToken() throws XMLSecurityException {
if (this.derivedKeySecurityToken != null) {
return this.derivedKeySecurityToken;
}
//todo implement interface to access all derivedKeys? The same would be needed in UserNameToken
this.derivedKeySecurityToken = new AbstractInboundSecurityToken(
(WSInboundSecurityContext) inputProcessorChain.getSecurityContext(),
derivedKeyTokenType.getId(), WSSecurityTokenConstants.KeyIdentifier_SecurityTokenDirectReference,
true) {
private InboundSecurityToken referencedSecurityToken = null;
private InboundSecurityToken getReferencedSecurityToken() throws XMLSecurityException {
if (this.referencedSecurityToken != null) {
return referencedSecurityToken;
}
this.referencedSecurityToken = SecurityTokenFactoryImpl.getSecurityToken(
derivedKeyTokenType.getSecurityTokenReference(),
((WSSSecurityProperties) securityProperties).getDecryptionCrypto(),
((WSSSecurityProperties)securityProperties).getCallbackHandler(),
inputProcessorChain.getSecurityContext(),
((WSSSecurityProperties)securityProperties)
);
this.referencedSecurityToken.addWrappedToken(this);
return this.referencedSecurityToken;
}
@Override
protected Key getKey(String algorithmURI, XMLSecurityConstants.AlgorithmUsage algorithmUsage,
String correlationID) throws XMLSecurityException {
byte[] secret;
InboundSecurityToken referencedSecurityToken = getReferencedSecurityToken();
if (referencedSecurityToken != null) {
if (referencedSecurityToken instanceof UsernameSecurityToken) {
UsernameSecurityToken usernameSecurityToken = (UsernameSecurityToken) referencedSecurityToken;
secret = usernameSecurityToken.generateDerivedKey();
} else {
secret = referencedSecurityToken.getSecretKey(algorithmURI, algorithmUsage, correlationID).getEncoded();
}
} else {
throw new WSSecurityException(WSSecurityException.ErrorCode.SECURITY_TOKEN_UNAVAILABLE, "unsupportedKeyId");
}
byte[] nonce = derivedKeyTokenType.getNonce();
if (nonce == null || nonce.length == 0) {
throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY_TOKEN, "empty", "Missing wsc:Nonce value");
}
String derivedKeyAlgorithm = derivedKeyTokenType.getAlgorithm();
if (derivedKeyAlgorithm == null) {
derivedKeyAlgorithm = WSSConstants.P_SHA_1;
}
byte[] keyBytes = DerivedKeyUtils.deriveKey(
derivedKeyAlgorithm,
derivedKeyTokenType.getLabel(),
derivedKeyTokenType.getLength().intValue(),
secret,
nonce,
derivedKeyTokenType.getOffset().intValue()
);
XMLSecurityConstants.AlgorithmUsage derivedKeyAlgoryithmUsage;
if (WSSConstants.Enc.equals(algorithmUsage)) {
derivedKeyAlgoryithmUsage = WSSConstants.Enc_KD;
} else {
derivedKeyAlgoryithmUsage = WSSConstants.Sig_KD;
}
AlgorithmSuiteSecurityEvent algorithmSuiteSecurityEvent = new AlgorithmSuiteSecurityEvent();
algorithmSuiteSecurityEvent.setAlgorithmURI(derivedKeyAlgorithm);
algorithmSuiteSecurityEvent.setAlgorithmUsage(derivedKeyAlgoryithmUsage);
algorithmSuiteSecurityEvent.setKeyLength(keyBytes.length * 8);
algorithmSuiteSecurityEvent.setCorrelationID(correlationID);
inputProcessorChain.getSecurityContext().registerSecurityEvent(algorithmSuiteSecurityEvent);
String algo = JCEAlgorithmMapper.getJCEKeyAlgorithmFromURI(algorithmURI);
return new SecretKeySpec(keyBytes, algo);
}
@Override
public InboundSecurityToken getKeyWrappingToken() throws XMLSecurityException {
return getReferencedSecurityToken();
}
@Override
public WSSecurityTokenConstants.TokenType getTokenType() {
return WSSecurityTokenConstants.DerivedKeyToken;
}
};
this.derivedKeySecurityToken.setElementPath(elementPath);
this.derivedKeySecurityToken.setXMLSecEvent(responsibleXMLSecStartXMLEvent);
return this.derivedKeySecurityToken;
}
@Override
public String getId() {
return derivedKeyTokenType.getId();
}
};
inputProcessorChain.getSecurityContext().registerSecurityTokenProvider(derivedKeyTokenType.getId(), securityTokenProvider);
//fire a tokenSecurityEvent
DerivedKeyTokenSecurityEvent derivedKeyTokenSecurityEvent = new DerivedKeyTokenSecurityEvent();
derivedKeyTokenSecurityEvent.setSecurityToken(securityTokenProvider.getSecurityToken());
derivedKeyTokenSecurityEvent.setCorrelationID(derivedKeyTokenType.getId());
inputProcessorChain.getSecurityContext().registerSecurityEvent(derivedKeyTokenSecurityEvent);
}