/****************************************************************************
* Copyright (C) 2012 HS Coburg.
* All rights reserved.
* Contact: ecsec GmbH (info@ecsec.de)
*
* This file is part of the Open eCard App.
*
* GNU General Public License Usage
* This file may be used under the terms of the GNU General Public
* License version 3.0 as published by the Free Software Foundation
* and appearing in the file LICENSE.GPL included in the packaging of
* this file. Please review the following information to ensure the
* GNU General Public License version 3.0 requirements will be met:
* http://www.gnu.org/copyleft/gpl.html.
*
* Other Usage
* Alternatively, this file may be used in accordance with the terms
* and conditions contained in a signed written agreement between
* you and ecsec GmbH.
*
***************************************************************************/
package org.openecard.sal;
import iso.std.iso_iec._24727.tech.schema.ACLList;
import iso.std.iso_iec._24727.tech.schema.ACLListResponse;
import iso.std.iso_iec._24727.tech.schema.ACLModify;
import iso.std.iso_iec._24727.tech.schema.ACLModifyResponse;
import iso.std.iso_iec._24727.tech.schema.AlgorithmInfoType;
import iso.std.iso_iec._24727.tech.schema.AuthorizationServiceActionName;
import iso.std.iso_iec._24727.tech.schema.CardApplicationConnect;
import iso.std.iso_iec._24727.tech.schema.CardApplicationConnectResponse;
import iso.std.iso_iec._24727.tech.schema.CardApplicationCreate;
import iso.std.iso_iec._24727.tech.schema.CardApplicationCreateResponse;
import iso.std.iso_iec._24727.tech.schema.CardApplicationDelete;
import iso.std.iso_iec._24727.tech.schema.CardApplicationDeleteResponse;
import iso.std.iso_iec._24727.tech.schema.CardApplicationDisconnect;
import iso.std.iso_iec._24727.tech.schema.CardApplicationDisconnectResponse;
import iso.std.iso_iec._24727.tech.schema.CardApplicationEndSession;
import iso.std.iso_iec._24727.tech.schema.CardApplicationEndSessionResponse;
import iso.std.iso_iec._24727.tech.schema.CardApplicationList;
import iso.std.iso_iec._24727.tech.schema.CardApplicationListResponse;
import iso.std.iso_iec._24727.tech.schema.CardApplicationListResponse.CardApplicationNameList;
import iso.std.iso_iec._24727.tech.schema.CardApplicationPath;
import iso.std.iso_iec._24727.tech.schema.CardApplicationPathResponse;
import iso.std.iso_iec._24727.tech.schema.CardApplicationPathResponse.CardAppPathResultSet;
import iso.std.iso_iec._24727.tech.schema.CardApplicationPathType;
import iso.std.iso_iec._24727.tech.schema.CardApplicationServiceActionName;
import iso.std.iso_iec._24727.tech.schema.CardApplicationServiceCreate;
import iso.std.iso_iec._24727.tech.schema.CardApplicationServiceCreateResponse;
import iso.std.iso_iec._24727.tech.schema.CardApplicationServiceDelete;
import iso.std.iso_iec._24727.tech.schema.CardApplicationServiceDeleteResponse;
import iso.std.iso_iec._24727.tech.schema.CardApplicationServiceDescribe;
import iso.std.iso_iec._24727.tech.schema.CardApplicationServiceDescribeResponse;
import iso.std.iso_iec._24727.tech.schema.CardApplicationServiceList;
import iso.std.iso_iec._24727.tech.schema.CardApplicationServiceListResponse;
import iso.std.iso_iec._24727.tech.schema.CardApplicationServiceLoad;
import iso.std.iso_iec._24727.tech.schema.CardApplicationServiceLoadResponse;
import iso.std.iso_iec._24727.tech.schema.CardApplicationStartSession;
import iso.std.iso_iec._24727.tech.schema.CardApplicationStartSessionResponse;
import iso.std.iso_iec._24727.tech.schema.Connect;
import iso.std.iso_iec._24727.tech.schema.ConnectResponse;
import iso.std.iso_iec._24727.tech.schema.ConnectionHandleType;
import iso.std.iso_iec._24727.tech.schema.ConnectionServiceActionName;
import iso.std.iso_iec._24727.tech.schema.DIDAuthenticate;
import iso.std.iso_iec._24727.tech.schema.DIDAuthenticateResponse;
import iso.std.iso_iec._24727.tech.schema.DIDAuthenticationDataType;
import iso.std.iso_iec._24727.tech.schema.DIDCreate;
import iso.std.iso_iec._24727.tech.schema.DIDCreateResponse;
import iso.std.iso_iec._24727.tech.schema.DIDDelete;
import iso.std.iso_iec._24727.tech.schema.DIDDeleteResponse;
import iso.std.iso_iec._24727.tech.schema.DIDGet;
import iso.std.iso_iec._24727.tech.schema.DIDGetResponse;
import iso.std.iso_iec._24727.tech.schema.DIDInfoType;
import iso.std.iso_iec._24727.tech.schema.DIDList;
import iso.std.iso_iec._24727.tech.schema.DIDListResponse;
import iso.std.iso_iec._24727.tech.schema.DIDNameListType;
import iso.std.iso_iec._24727.tech.schema.DIDQualifierType;
import iso.std.iso_iec._24727.tech.schema.DIDStructureType;
import iso.std.iso_iec._24727.tech.schema.DIDUpdate;
import iso.std.iso_iec._24727.tech.schema.DIDUpdateResponse;
import iso.std.iso_iec._24727.tech.schema.DSICreate;
import iso.std.iso_iec._24727.tech.schema.DSICreateResponse;
import iso.std.iso_iec._24727.tech.schema.DSIDelete;
import iso.std.iso_iec._24727.tech.schema.DSIDeleteResponse;
import iso.std.iso_iec._24727.tech.schema.DSIList;
import iso.std.iso_iec._24727.tech.schema.DSIListResponse;
import iso.std.iso_iec._24727.tech.schema.DSIRead;
import iso.std.iso_iec._24727.tech.schema.DSIReadResponse;
import iso.std.iso_iec._24727.tech.schema.DSIWrite;
import iso.std.iso_iec._24727.tech.schema.DSIWriteResponse;
import iso.std.iso_iec._24727.tech.schema.DataSetCreate;
import iso.std.iso_iec._24727.tech.schema.DataSetCreateResponse;
import iso.std.iso_iec._24727.tech.schema.DataSetDelete;
import iso.std.iso_iec._24727.tech.schema.DataSetDeleteResponse;
import iso.std.iso_iec._24727.tech.schema.DataSetInfoType;
import iso.std.iso_iec._24727.tech.schema.DataSetList;
import iso.std.iso_iec._24727.tech.schema.DataSetListResponse;
import iso.std.iso_iec._24727.tech.schema.DataSetNameListType;
import iso.std.iso_iec._24727.tech.schema.DataSetSelect;
import iso.std.iso_iec._24727.tech.schema.DataSetSelectResponse;
import iso.std.iso_iec._24727.tech.schema.Decipher;
import iso.std.iso_iec._24727.tech.schema.DecipherResponse;
import iso.std.iso_iec._24727.tech.schema.DifferentialIdentityServiceActionName;
import iso.std.iso_iec._24727.tech.schema.Disconnect;
import iso.std.iso_iec._24727.tech.schema.DisconnectResponse;
import iso.std.iso_iec._24727.tech.schema.Encipher;
import iso.std.iso_iec._24727.tech.schema.EncipherResponse;
import iso.std.iso_iec._24727.tech.schema.ExecuteAction;
import iso.std.iso_iec._24727.tech.schema.ExecuteActionResponse;
import iso.std.iso_iec._24727.tech.schema.GetRandom;
import iso.std.iso_iec._24727.tech.schema.GetRandomResponse;
import iso.std.iso_iec._24727.tech.schema.Hash;
import iso.std.iso_iec._24727.tech.schema.HashResponse;
import iso.std.iso_iec._24727.tech.schema.Initialize;
import iso.std.iso_iec._24727.tech.schema.InitializeResponse;
import iso.std.iso_iec._24727.tech.schema.NamedDataServiceActionName;
import iso.std.iso_iec._24727.tech.schema.Sign;
import iso.std.iso_iec._24727.tech.schema.SignResponse;
import iso.std.iso_iec._24727.tech.schema.TargetNameType;
import iso.std.iso_iec._24727.tech.schema.Terminate;
import iso.std.iso_iec._24727.tech.schema.TerminateResponse;
import iso.std.iso_iec._24727.tech.schema.VerifyCertificate;
import iso.std.iso_iec._24727.tech.schema.VerifyCertificateResponse;
import iso.std.iso_iec._24727.tech.schema.VerifySignature;
import iso.std.iso_iec._24727.tech.schema.VerifySignatureResponse;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.openecard.addon.AddonManager;
import org.openecard.addon.AddonNotFoundException;
import org.openecard.addon.AddonSelector;
import org.openecard.addon.HighestVersionSelector;
import org.openecard.addon.sal.FunctionType;
import org.openecard.addon.sal.SALProtocol;
import org.openecard.common.ECardConstants;
import org.openecard.common.ECardException;
import org.openecard.common.WSHelper;
import org.openecard.common.apdu.Select;
import org.openecard.common.apdu.Select.MasterFile;
import org.openecard.common.apdu.common.CardCommandAPDU;
import org.openecard.common.apdu.common.CardResponseAPDU;
import org.openecard.common.apdu.utils.CardUtils;
import org.openecard.common.interfaces.Environment;
import org.openecard.common.sal.Assert;
import org.openecard.common.sal.anytype.CryptoMarkerType;
import org.openecard.common.sal.exception.InappropriateProtocolForActionException;
import org.openecard.common.sal.exception.IncorrectParameterException;
import org.openecard.common.sal.exception.UnknownConnectionHandleException;
import org.openecard.common.sal.exception.UnknownProtocolException;
import org.openecard.common.sal.state.CardStateEntry;
import org.openecard.common.sal.state.CardStateMap;
import org.openecard.common.sal.state.cif.CardApplicationWrapper;
import org.openecard.common.sal.state.cif.CardInfoWrapper;
import org.openecard.common.sal.util.SALUtils;
import org.openecard.common.tlv.iso7816.FCP;
import org.openecard.gui.UserConsent;
import org.openecard.ws.SAL;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Implements a Service Access Layer (SAL).
*
* @author Johannes Schmölz <johannes.schmoelz@ecsec.de>
* @author Dirk Petrautzki <petrautzki@hs-coburg.de>
* @author Simon Potzernheim <potzernheim@hs-coburg.de>
* @author Tobias Wich <tobias.wich@ecsec.de>
* @author Moritz Horsch <horsch@cdc.informatik.tu-darmstadt.de>
* @author Antonio de la Piedra <a.delapiedra@cs.ru.nl>
*/
public class TinySAL implements SAL {
private static final Logger logger = LoggerFactory.getLogger(TinySAL.class);
private final Environment env;
private final CardStateMap states;
private AddonSelector protocolSelector;
private UserConsent userConsent;
/**
* Creates a new TinySAL.
*
* @param env Environment
* @param states CardStateMap
*/
public TinySAL(Environment env, CardStateMap states) {
this.env = env;
this.states = states;
}
public void setAddonManager(AddonManager manager) {
protocolSelector = new AddonSelector(manager);
protocolSelector.setStrategy(new HighestVersionSelector());
}
/**
* The Initialize function is executed when the ISO24727-3-Interface is invoked for the first time.
* The interface is initialised with this function.
* See BSI-TR-03112-4, version 1.1.2, section 3.1.1.
*
* @param request Initialize
* @return InitializeResponse
*/
@Override
public InitializeResponse initialize(Initialize request) {
return WSHelper.makeResponse(InitializeResponse.class, WSHelper.makeResultUnknownError("Not supported yet."));
}
/**
* The Terminate function is executed when the ISO24727-3-Interface is terminated.
* This function closes all established connections and open sessions.
* See BSI-TR-03112-4, version 1.1.2, section 3.1.2.
*
* @param request Terminate
* @return TerminateResponse
*/
@Override
public TerminateResponse terminate(Terminate request) {
return WSHelper.makeResponse(TerminateResponse.class, WSHelper.makeResultUnknownError("Not supported yet."));
}
/**
* The CardApplicationPath function determines a path between the client application and a card application.
* See BSI-TR-03112-4, version 1.1.2, section 3.1.3.
*
* @param request CardApplicationPath
* @return CardApplicationPathResponse
*/
@Override
public CardApplicationPathResponse cardApplicationPath(CardApplicationPath request) {
CardApplicationPathResponse response = WSHelper.makeResponse(CardApplicationPathResponse.class, WSHelper.makeResultOK());
try {
CardApplicationPathType cardAppPath = request.getCardAppPathRequest();
Assert.assertIncorrectParameter(cardAppPath, "The parameter CardAppPathRequest is empty.");
Set<CardStateEntry> entries = states.getMatchingEntries(cardAppPath);
// Copy entries to result set
CardAppPathResultSet resultSet = new CardAppPathResultSet();
List<CardApplicationPathType> resultPaths = resultSet.getCardApplicationPathResult();
for (CardStateEntry entry : entries) {
CardApplicationPathType pathCopy = entry.pathCopy();
if (cardAppPath.getCardApplication() != null) {
pathCopy.setCardApplication(cardAppPath.getCardApplication());
} else {
pathCopy.setCardApplication(entry.getImplicitlySelectedApplicationIdentifier());
}
resultPaths.add(pathCopy);
}
response.setCardAppPathResultSet(resultSet);
} catch (ECardException e) {
response.setResult(e.getResult());
} catch (Exception e) {
logger.error(e.getMessage(), e);
response.setResult(WSHelper.makeResult(e));
}
return response;
}
/**
* The CardApplicationConnect function establishes an unauthenticated connection between the client
* application and the card application.
* See BSI-TR-03112-4, version 1.1.2, section 3.2.1.
*
* @param request CardApplicationConnect
* @return CardApplicationConnectResponse
*/
@Override
public CardApplicationConnectResponse cardApplicationConnect(CardApplicationConnect request) {
CardApplicationConnectResponse response = WSHelper.makeResponse(CardApplicationConnectResponse.class, WSHelper.makeResultOK());
try {
CardApplicationPathType cardAppPath = request.getCardApplicationPath();
Assert.assertIncorrectParameter(cardAppPath, "The parameter CardAppPathRequest is empty.");
Set<CardStateEntry> cardStateEntrySet = states.getMatchingEntries(cardAppPath, false);
Assert.assertIncorrectParameter(cardStateEntrySet, "The given ConnectionHandle is invalid.");
/*
* [TR-03112-4] If the provided path fragments are valid for more than one card application
* the eCard-API-Framework SHALL return any of the possible choices.
*/
CardStateEntry cardStateEntry = cardStateEntrySet.iterator().next();
byte[] applicationID = cardAppPath.getCardApplication();
if (applicationID == null) {
applicationID = cardStateEntry.getImplicitlySelectedApplicationIdentifier();
}
Assert.securityConditionApplication(cardStateEntry, applicationID, ConnectionServiceActionName.CARD_APPLICATION_CONNECT);
// Connect to the card
CardApplicationPathType cardApplicationPath = cardStateEntry.pathCopy();
Connect connect = new Connect();
connect.setContextHandle(cardApplicationPath.getContextHandle());
connect.setIFDName(cardApplicationPath.getIFDName());
connect.setSlot(cardApplicationPath.getSlotIndex());
ConnectResponse connectResponse = (ConnectResponse) env.getDispatcher().deliver(connect);
WSHelper.checkResult(connectResponse);
// Select the card application
CardCommandAPDU select;
// TODO: proper determination of path, file and app id
if (applicationID.length == 2) {
select = new Select.File(applicationID);
} else {
select = new Select.Application(applicationID);
}
select.transmit(env.getDispatcher(), connectResponse.getSlotHandle());
cardStateEntry.setCurrentCardApplication(applicationID);
cardStateEntry.setSlotHandle(connectResponse.getSlotHandle());
// reset the ef FCP
cardStateEntry.unsetFCPOfSelectedEF();
states.addEntry(cardStateEntry);
response.setConnectionHandle(cardStateEntry.handleCopy());
response.getConnectionHandle().setCardApplication(applicationID);
} catch (ECardException e) {
response.setResult(e.getResult());
} catch (Exception e) {
logger.error(e.getMessage(), e);
response.setResult(WSHelper.makeResult(e));
}
return response;
}
/**
* The CardApplicationDisconnect function terminates the connection to a card application.
* See BSI-TR-03112-4, version 1.1.2, section 3.2.2.
*
* @param request CardApplicationDisconnect
* @return CardApplicationDisconnectResponse
*/
@Override
public CardApplicationDisconnectResponse cardApplicationDisconnect(CardApplicationDisconnect request) {
CardApplicationDisconnectResponse response = WSHelper.makeResponse(CardApplicationDisconnectResponse.class, WSHelper.makeResultOK());
try {
ConnectionHandleType connectionHandle = SALUtils.getConnectionHandle(request);
byte[] slotHandle = connectionHandle.getSlotHandle();
// check existence of required parameters
if (slotHandle == null) {
return WSHelper.makeResponse(CardApplicationDisconnectResponse.class, WSHelper.makeResultError(ECardConstants.Minor.App.INCORRECT_PARM, "ConnectionHandle is null"));
}
Disconnect disconnect = new Disconnect();
disconnect.setSlotHandle(slotHandle);
DisconnectResponse disconnectResponse = (DisconnectResponse) env.getDispatcher().deliver(disconnect);
// remove entries associated with this handle
states.removeSlotHandleEntry(slotHandle);
response.setResult(disconnectResponse.getResult());
} catch (ECardException e) {
response.setResult(e.getResult());
} catch (Exception e) {
logger.error(e.getMessage(), e);
response.setResult(WSHelper.makeResult(e));
}
return response;
}
/**
* This CardApplicationStartSession function starts a session between the client application and the card application.
* See BSI-TR-03112-4, version 1.1.2, section 3.2.3.
*
* @param request CardApplicationStartSession
* @return CardApplicationStartSessionResponse
*/
@Override
public CardApplicationStartSessionResponse cardApplicationStartSession(CardApplicationStartSession request) {
return WSHelper.makeResponse(CardApplicationStartSessionResponse.class, WSHelper.makeResultUnknownError("Not supported yet."));
}
/**
* The CardApplicationEndSession function closes the session between the client application and the card application.
* See BSI-TR-03112-4, version 1.1.2, section 3.2.4.
*
* @param request CardApplicationEndSession
* @return CardApplicationEndSessionResponse
*/
@Override
public CardApplicationEndSessionResponse cardApplicationEndSession(CardApplicationEndSession request) {
return WSHelper.makeResponse(CardApplicationEndSessionResponse.class, WSHelper.makeResultUnknownError("Not supported yet."));
}
/**
* The CardApplicationList function returns a list of the available card applications on an eCard.
* See BSI-TR-03112-4, version 1.1.2, section 3.3.1.
*
* @param request CardApplicationList
* @return CardApplicationListResponse
*/
@Override
public CardApplicationListResponse cardApplicationList(CardApplicationList request) {
CardApplicationListResponse response = WSHelper.makeResponse(CardApplicationListResponse.class, WSHelper.makeResultOK());
try {
ConnectionHandleType connectionHandle = SALUtils.getConnectionHandle(request);
CardStateEntry cardStateEntry = SALUtils.getCardStateEntry(states, connectionHandle);
byte[] cardApplicationID = connectionHandle.getCardApplication();
Assert.securityConditionApplication(cardStateEntry, cardApplicationID, CardApplicationServiceActionName.CARD_APPLICATION_LIST);
CardInfoWrapper cardInfoWrapper = cardStateEntry.getInfo();
CardApplicationNameList cardApplicationNameList = new CardApplicationNameList();
cardApplicationNameList.getCardApplicationName().addAll(cardInfoWrapper.getCardApplicationNameList());
response.setCardApplicationNameList(cardApplicationNameList);
} catch (ECardException e) {
response.setResult(e.getResult());
} catch (Exception e) {
logger.error(e.getMessage(), e);
response.setResult(WSHelper.makeResult(e));
}
return response;
}
/**
* A new card application is created on an eCard with the CardApplicationCreate function.
* See BSI-TR-03112-4, version 1.1.2, section 3.3.2.
*
* @param request CardApplicationCreate
* @return CardApplicationCreateResponse
*/
@Override
public CardApplicationCreateResponse cardApplicationCreate(CardApplicationCreate request) {
return WSHelper.makeResponse(CardApplicationCreateResponse.class, WSHelper.makeResultUnknownError("Not supported yet."));
}
/**
* The CardApplicationDelete function deletes a card application as well as all corresponding
* data sets, DSIs, DIDs and services.
* See BSI-TR-03112-4, version 1.1.2, section 3.3.3.
*
* @param request CardApplicationDelete
* @return CardApplicationDeleteResponse
*/
@Override
public CardApplicationDeleteResponse cardApplicationDelete(CardApplicationDelete request) {
return WSHelper.makeResponse(CardApplicationDeleteResponse.class, WSHelper.makeResultUnknownError("Not supported yet."));
}
/**
* The CardApplicationServiceList function returns a list of all avail-able services of a card application.
* See BSI-TR-03112-4, version 1.1.2, section 3.3.4.
*
* @param request CardApplicationServiceList
* @return CardApplicationServiceListResponse
*/
@Override
public CardApplicationServiceListResponse cardApplicationServiceList(CardApplicationServiceList request) {
return WSHelper.makeResponse(CardApplicationServiceListResponse.class, WSHelper.makeResultUnknownError("Not supported yet."));
}
/**
* The CardApplicationServiceCreate function creates a new service in the card application.
* See BSI-TR-03112-4, version 1.1.2, section 3.3.5.
*
* @param request CardApplicationServiceCreate
* @return CardApplicationServiceCreateResponse
*/
@Override
public CardApplicationServiceCreateResponse cardApplicationServiceCreate(CardApplicationServiceCreate request) {
return WSHelper.makeResponse(CardApplicationServiceCreateResponse.class, WSHelper.makeResultUnknownError("Not supported yet."));
}
/**
* Code for a specific card application service was loaded into the card application with the aid
* of the CardApplicationServiceLoad function.
* See BSI-TR-03112-4, version 1.1.2, section 3.3.6.
*
* @param request CardApplicationServiceLoad
* @return CardApplicationServiceLoadResponse
*/
@Override
public CardApplicationServiceLoadResponse cardApplicationServiceLoad(CardApplicationServiceLoad request) {
return WSHelper.makeResponse(CardApplicationServiceLoadResponse.class, WSHelper.makeResultUnknownError("Not supported yet."));
}
/**
* The CardApplicationServiceDelete function deletes a card application service in a card application.
* See BSI-TR-03112-4, version 1.1.2, section 3.3.7.
*
* @param request CardApplicationServiceDelete
* @return CardApplicationServiceDeleteResponse
*/
@Override
public CardApplicationServiceDeleteResponse cardApplicationServiceDelete(CardApplicationServiceDelete request) {
return WSHelper.makeResponse(CardApplicationServiceDeleteResponse.class, WSHelper.makeResultUnknownError("Not supported yet."));
}
/**
* The CardApplicationServiceDescribe function can be used to request an URI, an URL or a detailed description
* of the selected card application service.
* See BSI-TR-03112-4, version 1.1.2, section 3.3.8.
*
* @param request CardApplicationServiceDescribe
* @return CardApplicationServiceDescribeResponse
*/
@Override
public CardApplicationServiceDescribeResponse cardApplicationServiceDescribe(CardApplicationServiceDescribe request) {
return WSHelper.makeResponse(CardApplicationServiceDescribeResponse.class, WSHelper.makeResultUnknownError("Not supported yet."));
}
/**
* The ExecuteAction function permits use of additional card application services by the client application
* which are not explicitly specified in [ISO24727-3] but which can be implemented by the eCard with additional code.
* See BSI-TR-03112-4, version 1.1.2, section 3.3.9.
*
* @param request ExecuteAction
* @return ExecuteActionResponse
*/
@Override
public ExecuteActionResponse executeAction(ExecuteAction request) {
return WSHelper.makeResponse(ExecuteActionResponse.class, WSHelper.makeResultUnknownError("Not supported yet."));
}
/**
* The DataSetList function returns the list of the data sets in the card application addressed with the ConnectionHandle.
* See BSI-TR-03112-4, version 1.1.2, section 3.4.1.
*
* @param request DataSetList
* @return DataSetListResponse
*/
@Override
public DataSetListResponse dataSetList(DataSetList request) {
DataSetListResponse response = WSHelper.makeResponse(DataSetListResponse.class, WSHelper.makeResultOK());
try {
ConnectionHandleType connectionHandle = SALUtils.getConnectionHandle(request);
CardStateEntry cardStateEntry = SALUtils.getCardStateEntry(states, connectionHandle);
byte[] cardApplicationID = connectionHandle.getCardApplication();
Assert.securityConditionApplication(cardStateEntry, cardApplicationID, NamedDataServiceActionName.DATA_SET_LIST);
CardInfoWrapper cardInfoWrapper = cardStateEntry.getInfo();
DataSetNameListType dataSetNameList = cardInfoWrapper.getDataSetNameList(cardApplicationID);
response.setDataSetNameList(dataSetNameList);
} catch (ECardException e) {
response.setResult(e.getResult());
} catch (Exception e) {
logger.error(e.getMessage(), e);
response.setResult(WSHelper.makeResult(e));
}
return response;
}
/**
* The DataSetCreate function creates a new data set in the card application addressed with the
* ConnectionHandle (or otherwise in a previously selected data set if this is implemented as a DF).
* See BSI-TR-03112-4, version 1.1.2, section 3.4.2.
*
* @param request DataSetCreate
* @return DataSetCreateResponse
*/
@Override
public DataSetCreateResponse dataSetCreate(DataSetCreate request) {
return WSHelper.makeResponse(DataSetCreateResponse.class, WSHelper.makeResultUnknownError("Not supported yet."));
}
/**
* The DataSetSelect function selects a data set in a card application.
* See BSI-TR-03112-4, version 1.1.2, section 3.4.3.
*
* @param request DataSetSelect
* @return DataSetSelectResponse
*/
@Override
public DataSetSelectResponse dataSetSelect(DataSetSelect request) {
DataSetSelectResponse response = WSHelper.makeResponse(DataSetSelectResponse.class, WSHelper.makeResultOK());
try {
ConnectionHandleType connectionHandle = SALUtils.getConnectionHandle(request);
CardStateEntry cardStateEntry = SALUtils.getCardStateEntry(states, connectionHandle);
byte[] applicationID = connectionHandle.getCardApplication();
String dataSetName = request.getDataSetName();
Assert.assertIncorrectParameter(dataSetName, "The parameter DataSetName is empty.");
CardInfoWrapper cardInfoWrapper = cardStateEntry.getInfo();
DataSetInfoType dataSetInfo = cardInfoWrapper.getDataSet(dataSetName, applicationID);
Assert.assertNamedEntityNotFound(dataSetInfo, "The given DataSet cannot be found.");
Assert.securityConditionDataSet(cardStateEntry, applicationID, dataSetName, NamedDataServiceActionName.DATA_SET_SELECT);
byte[] fileID = dataSetInfo.getDataSetPath().getEfIdOrPath();
byte[] slotHandle = connectionHandle.getSlotHandle();
Select selectEF;
CardResponseAPDU result = null;
int i = 0;
while (i < fileID.length) {
if (fileID[0] == (byte) 0x3F && fileID[1] == (byte) 0x00) {
selectEF = new MasterFile();
i = i + 2;
} else if (i == fileID.length - 2) {
selectEF = new Select.ChildFile(new byte[] {fileID[i], fileID[i + 1]});
selectEF.setFCP();
i = i + 2;
} else {
selectEF = new Select.ChildDirectory(new byte[] {fileID[i], fileID[i + 1]});
i = i + 2;
}
result = selectEF.transmit(env.getDispatcher(), slotHandle);
}
if (result != null) {
cardStateEntry.setFCPOfSelectedEF(new FCP(result.getData()));
}
} catch (ECardException e) {
response.setResult(e.getResult());
} catch (Exception e) {
logger.error(e.getMessage(), e);
response.setResult(WSHelper.makeResult(e));
}
return response;
}
/**
* The DataSetDelete function deletes a data set of a card application on an eCard.
* See BSI-TR-03112-4, version 1.1.2, section 3.4.4.
*
* @param request DataSetDelete
* @return DataSetDeleteResponse
*/
@Override
public DataSetDeleteResponse dataSetDelete(DataSetDelete request) {
return WSHelper.makeResponse(DataSetDeleteResponse.class, WSHelper.makeResultUnknownError("Not supported yet."));
}
/**
* The function DSIList supplies the list of the DSI (Data Structure for Interoperability) which exist in the selected data set.
* See BSI-TR-03112-4, version 1.1.2, section 3.4.5.
*
* @param request DSIList
* @return DSIListResponse
*/
@Override
public DSIListResponse dsiList(DSIList request) {
return WSHelper.makeResponse(DSIListResponse.class, WSHelper.makeResultUnknownError("Not supported yet."));
}
/**
* The DSICreate function creates a DSI (Data Structure for Interoperability) in the currently selected data set.
* See BSI-TR-03112-4, version 1.1.2, section 3.4.6.
*
* @param request DSICreate
* @return DSICreateResponse
*/
@Override
public DSICreateResponse dsiCreate(DSICreate request) {
return WSHelper.makeResponse(DSICreateResponse.class, WSHelper.makeResultUnknownError("Not supported yet."));
}
/**
* The DSIDelete function deletes a DSI (Data Structure for Interoperability) in the currently selected data set.
* See BSI-TR-03112-4, version 1.1.2, section 3.4.7.
*
* @param request DSIDelete
* @return DSIDeleteResponse
*/
@Override
public DSIDeleteResponse dsiDelete(DSIDelete request) {
return WSHelper.makeResponse(DSIDeleteResponse.class, WSHelper.makeResultUnknownError("Not supported yet."));
}
/**
* The DSIWrite function changes the content of a DSI (Data Structure for Interoperability).
* See BSI-TR-03112-4, version 1.1.2, section 3.4.8.
*
* @param request DSIWrite
* @return DSIWriteResponse
*/
@Override
public DSIWriteResponse dsiWrite(DSIWrite request) {
DSIWriteResponse response = WSHelper.makeResponse(DSIWriteResponse.class, WSHelper.makeResultOK());
try {
ConnectionHandleType connectionHandle = SALUtils.getConnectionHandle(request);
CardStateEntry cardStateEntry = SALUtils.getCardStateEntry(states, connectionHandle);
byte[] applicationID = connectionHandle.getCardApplication();
String dsiName = request.getDSIName();
byte[] updateData = request.getDSIContent();
Assert.assertIncorrectParameter(dsiName, "The parameter DSIName is empty.");
Assert.assertIncorrectParameter(updateData, "The parameter DSIContent is empty.");
CardInfoWrapper cardInfoWrapper = cardStateEntry.getInfo();
DataSetInfoType dataSetInfo = cardInfoWrapper.getDataSet(dsiName, applicationID);
Assert.assertNamedEntityNotFound(dataSetInfo, "The given DSIName cannot be found.");
Assert.securityConditionDataSet(cardStateEntry, applicationID, dsiName, NamedDataServiceActionName.DSI_WRITE);
byte[] fileID = dataSetInfo.getDataSetPath().getEfIdOrPath();
byte[] slotHandle = connectionHandle.getSlotHandle();
CardUtils.writeFile(env.getDispatcher(), slotHandle, fileID, updateData);
} catch (ECardException e) {
response.setResult(e.getResult());
} catch (Exception e) {
logger.error(e.getMessage(), e);
response.setResult(WSHelper.makeResult(e));
}
return response;
}
/**
* The DSIRead function reads out the content of a specific DSI (Data Structure for Interoperability).
* See BSI-TR-03112-4, version 1.1.2, section 3.4.9.
*
* @param request DSIRead
* @return DSIReadResponse
*/
@Override
public DSIReadResponse dsiRead(DSIRead request) {
DSIReadResponse response = WSHelper.makeResponse(DSIReadResponse.class, WSHelper.makeResultOK());
try {
ConnectionHandleType connectionHandle = SALUtils.getConnectionHandle(request);
CardStateEntry cardStateEntry = SALUtils.getCardStateEntry(states, connectionHandle);
byte[] applicationID = connectionHandle.getCardApplication();
String dsiName = request.getDSIName();
Assert.assertIncorrectParameter(dsiName, "The parameter DSIName is empty.");
CardInfoWrapper cardInfoWrapper = cardStateEntry.getInfo();
DataSetInfoType dataSetInfo = cardInfoWrapper.getDataSet(dsiName, applicationID);
Assert.assertNamedEntityNotFound(dataSetInfo, "The given DSIName cannot be found.");
Assert.securityConditionDataSet(cardStateEntry, applicationID, dsiName, NamedDataServiceActionName.DSI_READ);
byte[] slotHandle = connectionHandle.getSlotHandle();
// throws a null pointer if no ef is selected
byte[] fileContent = CardUtils.readFile(cardStateEntry.getFCPOfSelectedEF(), env.getDispatcher(), slotHandle);
response.setDSIContent(fileContent);
} catch (ECardException e) {
response.setResult(e.getResult());
} catch (Exception e) {
logger.error(e.getMessage(), e);
response.setResult(WSHelper.makeResult(e));
}
return response;
}
/**
* The Encipher function encrypts a transmitted plain text. The detailed behaviour of this function depends on
* the protocol of the DID.
* See BSI-TR-03112-4, version 1.1.2, section 3.5.1.
*
* @param request Encipher
* @return EncipherResponse
*/
@Override
public EncipherResponse encipher(Encipher request) {
EncipherResponse response = WSHelper.makeResponse(EncipherResponse.class, WSHelper.makeResultOK());
try {
ConnectionHandleType connectionHandle = SALUtils.getConnectionHandle(request);
CardStateEntry cardStateEntry = SALUtils.getCardStateEntry(states, connectionHandle);
byte[] applicationID = connectionHandle.getCardApplication();
String didName = SALUtils.getDIDName(request);
byte[] plainText = request.getPlainText();
Assert.assertIncorrectParameter(plainText, "The parameter PlainText is empty.");
DIDStructureType didStructure = cardStateEntry.getDIDStructure(didName, applicationID);
Assert.assertNamedEntityNotFound(didStructure, "The given DIDName cannot be found.");
String protocolURI = didStructure.getDIDMarker().getProtocol();
SALProtocol protocol = getProtocol(connectionHandle, protocolURI);
if (protocol.hasNextStep(FunctionType.Encipher)) {
response = protocol.encipher(request);
removeFinishedProtocol(connectionHandle, protocolURI, protocol);
} else {
throw new InappropriateProtocolForActionException("Encipher", protocol.toString());
}
} catch (ECardException e) {
response.setResult(e.getResult());
} catch (Exception e) {
logger.error(e.getMessage(), e);
response.setResult(WSHelper.makeResult(e));
}
return response;
}
/**
* The Decipher function decrypts a given cipher text. The detailed behaviour of this function depends on
* the protocol of the DID.
* See BSI-TR-03112-4, version 1.1.2, section 3.5.2.
*
* @param request Decipher
* @return DecipherResponse
*/
@Override
public DecipherResponse decipher(Decipher request) {
DecipherResponse response = WSHelper.makeResponse(DecipherResponse.class, WSHelper.makeResultOK());
try {
ConnectionHandleType connectionHandle = SALUtils.getConnectionHandle(request);
CardStateEntry cardStateEntry = SALUtils.getCardStateEntry(states, connectionHandle);
byte[] applicationID = connectionHandle.getCardApplication();
String didName = SALUtils.getDIDName(request);
byte[] cipherText = request.getCipherText();
Assert.assertIncorrectParameter(cipherText, "The parameter CipherText is empty.");
DIDStructureType didStructure = cardStateEntry.getDIDStructure(didName, applicationID);
Assert.assertNamedEntityNotFound(didStructure, "The given DIDName cannot be found.");
String protocolURI = didStructure.getDIDMarker().getProtocol();
SALProtocol protocol = getProtocol(connectionHandle, protocolURI);
if (protocol.hasNextStep(FunctionType.Decipher)) {
response = protocol.decipher(request);
removeFinishedProtocol(connectionHandle, protocolURI, protocol);
} else {
throw new InappropriateProtocolForActionException("Decipher", protocol.toString());
}
} catch (ECardException e) {
response.setResult(e.getResult());
} catch (Exception e) {
logger.error(e.getMessage(), e);
response.setResult(WSHelper.makeResult(e));
}
return response;
}
/**
* The GetRandom function returns a random number which is suitable for authentication with the DID addressed with DIDName.
* See BSI-TR-03112-4, version 1.1.2, section 3.5.3.
*
* @param request GetRandom
* @return GetRandomResponse
*/
@Override
public GetRandomResponse getRandom(GetRandom request) {
GetRandomResponse response = WSHelper.makeResponse(GetRandomResponse.class, WSHelper.makeResultOK());
try {
ConnectionHandleType connectionHandle = SALUtils.getConnectionHandle(request);
CardStateEntry cardStateEntry = SALUtils.getCardStateEntry(states, connectionHandle);
byte[] applicationID = connectionHandle.getCardApplication();
String didName = SALUtils.getDIDName(request);
DIDStructureType didStructure = cardStateEntry.getDIDStructure(didName, applicationID);
Assert.assertNamedEntityNotFound(didStructure, "The given DIDName cannot be found.");
String protocolURI = didStructure.getDIDMarker().getProtocol();
SALProtocol protocol = getProtocol(connectionHandle, protocolURI);
if (protocol.hasNextStep(FunctionType.GetRandom)) {
response = protocol.getRandom(request);
removeFinishedProtocol(connectionHandle, protocolURI, protocol);
} else {
throw new InappropriateProtocolForActionException("GetRandom", protocol.toString());
}
} catch (ECardException e) {
response.setResult(e.getResult());
} catch (Exception e) {
logger.error(e.getMessage(), e);
response.setResult(WSHelper.makeResult(e));
}
return response;
}
/**
* The Hash function calculates the hash value of a transmitted message.
* See BSI-TR-03112-4, version 1.1.2, section 3.5.4.
*
* @param request Hash
* @return HashResponse
*/
@Override
public HashResponse hash(Hash request) {
HashResponse response = WSHelper.makeResponse(HashResponse.class, WSHelper.makeResultOK());
try {
ConnectionHandleType connectionHandle = SALUtils.getConnectionHandle(request);
CardStateEntry cardStateEntry = SALUtils.getCardStateEntry(states, connectionHandle);
byte[] applicationID = connectionHandle.getCardApplication();
String didName = SALUtils.getDIDName(request);
byte[] message = request.getMessage();
Assert.assertIncorrectParameter(message, "The parameter Message is empty.");
DIDStructureType didStructure = cardStateEntry.getDIDStructure(didName, applicationID);
Assert.assertNamedEntityNotFound(didStructure, "The given DIDName cannot be found.");
String protocolURI = didStructure.getDIDMarker().getProtocol();
SALProtocol protocol = getProtocol(connectionHandle, protocolURI);
if (protocol.hasNextStep(FunctionType.Hash)) {
response = protocol.hash(request);
removeFinishedProtocol(connectionHandle, protocolURI, protocol);
} else {
throw new InappropriateProtocolForActionException("Hash", protocol.toString());
}
} catch (ECardException e) {
response.setResult(e.getResult());
} catch (Exception e) {
logger.error(e.getMessage(), e);
response.setResult(WSHelper.makeResult(e));
}
return response;
}
/**
* The Sign function signs a transmitted message.
* See BSI-TR-03112-4, version 1.1.2, section 3.5.5.
*
* @param request Sign
* @return SignResponse
*/
@Override
public SignResponse sign(Sign request) {
SignResponse response = WSHelper.makeResponse(SignResponse.class, WSHelper.makeResultOK());
try {
ConnectionHandleType connectionHandle = SALUtils.getConnectionHandle(request);
CardStateEntry cardStateEntry = SALUtils.getCardStateEntry(states, connectionHandle);
byte[] applicationID = connectionHandle.getCardApplication();
String didName = SALUtils.getDIDName(request);
byte[] message = request.getMessage();
Assert.assertIncorrectParameter(message, "The parameter Message is empty.");
DIDStructureType didStructure = cardStateEntry.getDIDStructure(didName, applicationID);
Assert.assertNamedEntityNotFound(didStructure, "The given DIDName cannot be found.");
String protocolURI = didStructure.getDIDMarker().getProtocol();
SALProtocol protocol = getProtocol(connectionHandle, protocolURI);
if (protocol.hasNextStep(FunctionType.Sign)) {
response = protocol.sign(request);
removeFinishedProtocol(connectionHandle, protocolURI, protocol);
} else {
throw new InappropriateProtocolForActionException("Sign", protocol.toString());
}
} catch (ECardException e) {
response.setResult(e.getResult());
} catch (Exception e) {
logger.error(e.getMessage(), e);
response.setResult(WSHelper.makeResult(e));
}
return response;
}
/**
* The VerifySignature function verifies a digital signature.
* See BSI-TR-03112-4, version 1.1.2, section 3.5.6.
*
* @param request VerifySignature
* @return VerifySignatureResponse
*/
@Override
public VerifySignatureResponse verifySignature(VerifySignature request) {
VerifySignatureResponse response = WSHelper.makeResponse(VerifySignatureResponse.class, WSHelper.makeResultOK());
try {
ConnectionHandleType connectionHandle = SALUtils.getConnectionHandle(request);
CardStateEntry cardStateEntry = SALUtils.getCardStateEntry(states, connectionHandle);
byte[] applicationID = connectionHandle.getCardApplication();
String didName = SALUtils.getDIDName(request);
byte[] signature = request.getSignature();
Assert.assertIncorrectParameter(signature, "The parameter Signature is empty.");
DIDStructureType didStructure = cardStateEntry.getDIDStructure(didName, applicationID);
Assert.assertNamedEntityNotFound(didStructure, "The given DIDName cannot be found.");
String protocolURI = didStructure.getDIDMarker().getProtocol();
SALProtocol protocol = getProtocol(connectionHandle, protocolURI);
if (protocol.hasNextStep(FunctionType.VerifySignature)) {
response = protocol.verifySignature(request);
removeFinishedProtocol(connectionHandle, protocolURI, protocol);
} else {
throw new InappropriateProtocolForActionException("VerifySignature", protocol.toString());
}
} catch (ECardException e) {
response.setResult(e.getResult());
} catch (Exception e) {
logger.error(e.getMessage(), e);
response.setResult(WSHelper.makeResult(e));
}
return response;
}
/**
* The VerifyCertificate function validates a given certificate.
* See BSI-TR-03112-4, version 1.1.2, section 3.5.7.
*
* @param request VerifyCertificate
* @return VerifyCertificateResponse
*/
@Override
public VerifyCertificateResponse verifyCertificate(VerifyCertificate request) {
VerifyCertificateResponse response = WSHelper.makeResponse(VerifyCertificateResponse.class, WSHelper.makeResultOK());
try {
ConnectionHandleType connectionHandle = SALUtils.getConnectionHandle(request);
CardStateEntry cardStateEntry = SALUtils.getCardStateEntry(states, connectionHandle);
byte[] applicationID = connectionHandle.getCardApplication();
String didName = SALUtils.getDIDName(request);
byte[] certificate = request.getCertificate();
Assert.assertIncorrectParameter(certificate, "The parameter Certificate is empty.");
String certificateType = request.getCertificateType();
Assert.assertIncorrectParameter(certificateType, "The parameter CertificateType is empty.");
String rootCert = request.getRootCert();
Assert.assertIncorrectParameter(rootCert, "The parameter RootCert is empty.");
DIDStructureType didStructure = cardStateEntry.getDIDStructure(didName, applicationID);
Assert.assertNamedEntityNotFound(didStructure, "The given DIDName cannot be found.");
String protocolURI = didStructure.getDIDMarker().getProtocol();
SALProtocol protocol = getProtocol(connectionHandle, protocolURI);
if (protocol.hasNextStep(FunctionType.VerifyCertificate)) {
response = protocol.verifyCertificate(request);
removeFinishedProtocol(connectionHandle, protocolURI, protocol);
} else {
throw new InappropriateProtocolForActionException("VerifyCertificate", protocol.toString());
}
} catch (ECardException e) {
response.setResult(e.getResult());
} catch (Exception e) {
logger.error(e.getMessage(), e);
response.setResult(WSHelper.makeResult(e));
}
return response;
}
/**
* The DIDList function returns a list of the existing DIDs in the card application addressed by the
* ConnectionHandle or the ApplicationIdentifier element within the Filter.
* See BSI-TR-03112-4, version 1.1.2, section 3.6.1.
*
* @param request DIDList
* @return DIDListResponse
*/
@Override
public DIDListResponse didList(DIDList request) {
DIDListResponse response = WSHelper.makeResponse(DIDListResponse.class, WSHelper.makeResultOK());
try {
ConnectionHandleType connectionHandle = SALUtils.getConnectionHandle(request);
byte[] appId = connectionHandle.getCardApplication();
CardStateEntry cardStateEntry = SALUtils.getCardStateEntry(states, connectionHandle, false);
Assert.securityConditionApplication(cardStateEntry, appId, DifferentialIdentityServiceActionName.DID_LIST);
byte[] applicationIDFilter = null;
String objectIDFilter = null;
String applicationFunctionFilter = null;
DIDQualifierType didQualifier = request.getFilter();
if (didQualifier != null) {
applicationIDFilter = didQualifier.getApplicationIdentifier();
objectIDFilter = didQualifier.getObjectIdentifier();
applicationFunctionFilter = didQualifier.getApplicationFunction();
}
/*
* Filter by ApplicationIdentifier.
* [TR-03112-4] Allows specifying an application identifier. If this element is present all
* DIDs within the specified card application are returned no matter which card application
* is currently selected.
*/
CardApplicationWrapper cardApplication;
if (applicationIDFilter != null) {
cardApplication = cardStateEntry.getInfo().getCardApplication(applicationIDFilter);
Assert.assertIncorrectParameter(cardApplication, "The given CardApplication cannot be found.");
} else {
cardApplication = cardStateEntry.getCurrentCardApplication();
}
List<DIDInfoType> didInfos = new ArrayList<DIDInfoType>(cardApplication.getDIDInfoList());
/*
* Filter by ObjectIdentifier.
* [TR-03112-4] Allows specifying a protocol OID (cf. [TR-03112-7]) such that only DIDs
* which support a given protocol are listed.
*/
if (objectIDFilter != null) {
Iterator<DIDInfoType> it = didInfos.iterator();
while (it.hasNext()) {
DIDInfoType next = it.next();
if (!next.getDifferentialIdentity().getDIDProtocol().equals(objectIDFilter)) {
it.remove();
}
}
}
/*
* Filter by ApplicationFunction.
* [TR-03112-4] Allows filtering for DIDs, which support a specific cryptographic operation.
* The bit string is coded as the SupportedOperations-element in [ISO7816-15].
*/
if (applicationFunctionFilter != null) {
Iterator<DIDInfoType> it = didInfos.iterator();
while (it.hasNext()) {
DIDInfoType next = it.next();
if (next.getDifferentialIdentity().getDIDMarker().getCryptoMarker() == null) {
it.remove();
} else {
iso.std.iso_iec._24727.tech.schema.CryptoMarkerType rawMarker;
rawMarker = next.getDifferentialIdentity().getDIDMarker().getCryptoMarker();
CryptoMarkerType cryptoMarker = new CryptoMarkerType(rawMarker);
AlgorithmInfoType algInfo = cryptoMarker.getAlgorithmInfo();
if (! algInfo.getSupportedOperations().contains(applicationFunctionFilter)) {
it.remove();
}
}
}
}
DIDNameListType didNameList = new DIDNameListType();
for (DIDInfoType didInfo : didInfos) {
didNameList.getDIDName().add(didInfo.getDifferentialIdentity().getDIDName());
}
response.setDIDNameList(didNameList);
} catch (ECardException e) {
response.setResult(e.getResult());
} catch (Exception e) {
logger.error(e.getMessage(), e);
response.setResult(WSHelper.makeResult(e));
}
return response;
}
/**
* The DIDCreate function creates a new differential identity in the card application addressed with ConnectionHandle.
* See BSI-TR-03112-4, version 1.1.2, section 3.6.2.
*
* @param request DIDCreate
* @return DIDCreateResponse
*/
@Override
public DIDCreateResponse didCreate(DIDCreate request) {
return WSHelper.makeResponse(DIDCreateResponse.class, WSHelper.makeResultUnknownError("Not supported yet."));
}
/**
* The public information for a DID is read with the DIDGet function.
* See BSI-TR-03112-4, version 1.1.2, section 3.6.3.
*
* @param request DIDGet
* @return DIDGetResponse
*/
@Override
public DIDGetResponse didGet(DIDGet request) {
DIDGetResponse response = WSHelper.makeResponse(DIDGetResponse.class, WSHelper.makeResultOK());
try {
ConnectionHandleType connectionHandle = SALUtils.getConnectionHandle(request);
// handle must be requested without application, as it is irrelevant for this call
CardStateEntry stateEntry = SALUtils.getCardStateEntry(states, connectionHandle, false);
String didName = SALUtils.getDIDName(request);
DIDStructureType didStructure = SALUtils.getDIDStructure(request, didName, stateEntry, connectionHandle);
response.setDIDStructure(didStructure);
} catch (ECardException e) {
response.setResult(e.getResult());
} catch (Exception e) {
logger.error(e.getMessage(), e);
response.setResult(WSHelper.makeResult(e));
}
return response;
}
/**
* The DIDUpdate function creates a new key (marker) for the DID addressed with DIDName.
* See BSI-TR-03112-4, version 1.1.2, section 3.6.4.
*
* @param request DIDUpdate
* @return DIDUpdateResponse
*/
@Override
public DIDUpdateResponse didUpdate(DIDUpdate request) {
return WSHelper.makeResponse(DIDUpdateResponse.class, WSHelper.makeResultUnknownError("Not supported yet."));
}
/**
* The DIDDelete function deletes the DID addressed with DIDName.
* See BSI-TR-03112-4, version 1.1.2, section 3.6.5.
*
* @param request DIDDelete
* @return DIDDeleteResponse
*/
@Override
public DIDDeleteResponse didDelete(DIDDelete request) {
return WSHelper.makeResponse(DIDDeleteResponse.class, WSHelper.makeResultUnknownError("Not supported yet."));
}
/**
* The DIDAuthenticate function can be used to execute an authentication protocol using a DID addressed by DIDName.
* See BSI-TR-03112-4, version 1.1.2, section 3.6.6.
*
* @param request DIDAuthenticate
* @return DIDAuthenticateResponse
*/
@Override
public DIDAuthenticateResponse didAuthenticate(DIDAuthenticate request) {
DIDAuthenticateResponse response = WSHelper.makeResponse(DIDAuthenticateResponse.class, WSHelper.makeResultOK());
try {
ConnectionHandleType connectionHandle = SALUtils.getConnectionHandle(request);
DIDAuthenticationDataType didAuthenticationData = request.getAuthenticationProtocolData();
Assert.assertIncorrectParameter(didAuthenticationData, "The parameter AuthenticationProtocolData is empty.");
String protocolURI = didAuthenticationData.getProtocol();
// FIXME: workaround for missing protocol URI from eID-Servers
if (protocolURI == null) {
logger.warn("ProtocolURI was null");
protocolURI = ECardConstants.Protocol.EAC_GENERIC;
} else if (protocolURI.equals("urn:oid:1.0.24727.3.0.0.7.2")) {
logger.warn("ProtocolURI was urn:oid:1.0.24727.3.0.0.7.2");
protocolURI = ECardConstants.Protocol.EAC_GENERIC;
}
didAuthenticationData.setProtocol(protocolURI);
SALProtocol protocol = getProtocol(connectionHandle, protocolURI);
if (protocol.hasNextStep(FunctionType.DIDAuthenticate)) {
response = protocol.didAuthenticate(request);
removeFinishedProtocol(connectionHandle, protocolURI, protocol);
} else {
throw new InappropriateProtocolForActionException("DIDAuthenticate", protocol.toString());
}
} catch (ECardException e) {
response.setResult(e.getResult());
} catch (Exception e) {
logger.error(e.getMessage(), e);
response.setResult(WSHelper.makeResult(e));
}
return response;
}
/**
* The ACLList function returns the access control list for the stated target object (card application, data set, DID).
* See BSI-TR-03112-4, version 1.1.2, section 3.7.1.
*
* @param request ACLList
* @return ACLListResponse
*/
@Override
public ACLListResponse aclList(ACLList request) {
ACLListResponse response = WSHelper.makeResponse(ACLListResponse.class, WSHelper.makeResultOK());
try {
ConnectionHandleType connectionHandle = SALUtils.getConnectionHandle(request);
CardStateEntry cardStateEntry = SALUtils.getCardStateEntry(states, connectionHandle, false);
TargetNameType targetName = request.getTargetName();
Assert.assertIncorrectParameter(targetName, "The parameter TargetName is empty.");
// get the target values, according to the schema only one must exist, we pick the first existing ;-)
byte[] targetAppId = targetName.getCardApplicationName();
String targetDataSet = targetName.getDataSetName();
String targetDid = targetName.getDIDName();
CardInfoWrapper cardInfoWrapper = cardStateEntry.getInfo();
byte[] handleAppId = connectionHandle.getCardApplication();
if (targetDataSet != null) {
DataSetInfoType dataSetInfo = cardInfoWrapper.getDataSet(targetDataSet, handleAppId);
Assert.assertNamedEntityNotFound(dataSetInfo, "The given DataSet cannot be found.");
response.setTargetACL(cardInfoWrapper.getDataSet(targetDataSet, handleAppId).getDataSetACL());
} else if (targetDid != null) {
DIDInfoType didInfo = cardInfoWrapper.getDIDInfo(targetDid, handleAppId);
Assert.assertNamedEntityNotFound(didInfo, "The given DIDInfo cannot be found.");
//TODO Check security condition ?
response.setTargetACL(cardInfoWrapper.getDIDInfo(targetDid, handleAppId).getDIDACL());
} else if (targetAppId != null) {
CardApplicationWrapper cardApplication = cardInfoWrapper.getCardApplication(targetAppId);
Assert.assertNamedEntityNotFound(cardApplication, "The given CardApplication cannot be found.");
Assert.securityConditionApplication(cardStateEntry, targetAppId, AuthorizationServiceActionName.ACL_LIST);
response.setTargetACL(cardInfoWrapper.getCardApplication(targetAppId).getCardApplicationACL());
} else {
throw new IncorrectParameterException("The given TargetName is invalid.");
}
} catch (ECardException e) {
response.setResult(e.getResult());
} catch (Exception e) {
logger.error(e.getMessage(), e);
response.setResult(WSHelper.makeResult(e));
}
return response;
}
/**
* An access rule in the access control list is modified with the ACLModify function.
* See BSI-TR-03112-4, version 1.1.2, section 3.7.2.
*
* @param request ACLModify
* @return ACLModifyResponse
*/
@Override
public ACLModifyResponse aclModify(ACLModify request) {
return WSHelper.makeResponse(ACLModifyResponse.class, WSHelper.makeResultUnknownError("Not supported yet."));
}
/**
* Sets the GUI.
*
* @param uc User consent
*/
public void setGUI(UserConsent uc) {
this.userConsent = uc;
}
/**
* Returns a list of ConnectionHandles.
*
* @return List of ConnectionHandles
*/
public List<ConnectionHandleType> getConnectionHandles() {
ConnectionHandleType handle = new ConnectionHandleType();
Set<CardStateEntry> entries = states.getMatchingEntries(handle);
ArrayList<ConnectionHandleType> result = new ArrayList<ConnectionHandleType>(entries.size());
for (CardStateEntry entry : entries) {
result.add(entry.handleCopy());
}
return result;
}
/**
* Removes a finished protocol from the SAL instance.
*
* @param handle Connection Handle
* @param protocolURI Protocol URI
* @param protocol Protocol
* @throws UnknownConnectionHandleException
*/
public void removeFinishedProtocol(ConnectionHandleType handle, String protocolURI, SALProtocol protocol)
throws UnknownConnectionHandleException {
if (protocol.isFinished()) {
CardStateEntry entry = SALUtils.getCardStateEntry(states, handle);
entry.removeProtocol(protocolURI);
}
}
private SALProtocol getProtocol(ConnectionHandleType handle, String protocolURI)
throws UnknownProtocolException, UnknownConnectionHandleException {
CardStateEntry entry = SALUtils.getCardStateEntry(states, handle);
SALProtocol protocol = entry.getProtocol(protocolURI);
if (protocol == null) {
try {
protocol = protocolSelector.getSALProtocol(protocolURI);
entry.setProtocol(protocolURI, protocol);
} catch (AddonNotFoundException ex) {
throw new UnknownProtocolException("The protocol URI '" + protocolURI + "' is not available.");
}
}
protocol.getInternalData().put("cardState", entry);
return protocol;
}
}