AusweisApp2/src/card/bluetooth/BluetoothCard.cpp

170 lines
4.4 KiB
C++

/*!
* BluetoothCard.cpp
*
* \copyright Copyright (c) 2015 Governikus GmbH & Co. KG
*/
#include "BluetoothCard.h"
#include "DestroyPACEChannel.h"
#include "messages/BluetoothMessageCreator.h"
#include "messages/BluetoothMessageDisconnectResponse.h"
#include "messages/BluetoothMessageSetTransportProtocolResponse.h"
#include "messages/BluetoothMessageTransferApduResponse.h"
#include "SynchronousBtCall.h"
#include <QLoggingCategory>
Q_DECLARE_LOGGING_CATEGORY(bluetooth)
using namespace governikus;
BluetoothCard::BluetoothCard(QSharedPointer<CyberJackWaveDevice> pDevice)
: Card()
, mConnected(false)
, mDevice(pDevice)
{
}
CardReturnCode BluetoothCard::connect()
{
if (isConnected())
{
qCCritical(bluetooth) << "Card is already connected";
return CardReturnCode::COMMAND_FAILED;
}
auto request = BluetoothMessageCreator::createSetTransportProtocolRequest(BluetoothTransportProtocol::T1);
auto response = SynchronousBtCall(mDevice).send(request, BluetoothMsgId::SetTransportProtocolResponse);
if (response.isNull())
{
qCCritical(bluetooth) << "Response is empty";
return CardReturnCode::COMMAND_FAILED;
}
auto resultCode = response.staticCast<const BluetoothMessageSetTransportProtocolResponse>()->getResultCode();
if (resultCode != BluetoothResultCode::Ok)
{
qCCritical(bluetooth) << "Cannot set transport protocol on card" << resultCode;
return CardReturnCode::COMMAND_FAILED;
}
mConnected = true;
return CardReturnCode::OK;
}
CardReturnCode BluetoothCard::disconnect()
{
if (!isConnected())
{
qCCritical(bluetooth) << "Card is already disconnected";
return CardReturnCode::COMMAND_FAILED;
}
auto request = BluetoothMessageCreator::createDisconnectRequest();
auto response = SynchronousBtCall(mDevice).send(request, BluetoothMsgId::DisconnectResponse, 1);
mConnected = false;
if (response.isNull())
{
qCCritical(bluetooth) << "Response is empty";
return CardReturnCode::COMMAND_FAILED;
}
return CardReturnCode::OK;
}
bool BluetoothCard::isConnected()
{
return mConnected;
}
CardReturnCode BluetoothCard::transmit(const CommandApdu& pCmd, ResponseApdu& pRes)
{
return transmit(pCmd, pRes, 30);
}
CardReturnCode BluetoothCard::transmit(const CommandApdu& pCmd, ResponseApdu& pRes, quint8 pTimeoutSeconds)
{
if (!isConnected())
{
qCCritical(bluetooth) << "Card is not connected, abort transmit";
return CardReturnCode::COMMAND_FAILED;
}
qCDebug(bluetooth) << "Transmit command APDU: " << pCmd.getBuffer().toHex();
auto request = BluetoothMessageCreator::createTransferApduRequest(pCmd.getBuffer());
auto response = SynchronousBtCall(mDevice).send(request, BluetoothMsgId::TransferApduResponse, pTimeoutSeconds);
if (response.isNull())
{
qCCritical(bluetooth) << "Response is empty";
return CardReturnCode::COMMAND_FAILED;
}
auto apduResponse = response.staticCast<const BluetoothMessageTransferApduResponse>();
if (apduResponse->getResultCode() != BluetoothResultCode::Ok)
{
qCCritical(bluetooth) << "TransferApduResponse failed : " << apduResponse->getResultCode();
return CardReturnCode::COMMAND_FAILED;
}
pRes.setBuffer(apduResponse->getResponseAPDU());
qCDebug(bluetooth) << "Transmit response APDU: " << pRes.getBuffer().toHex();
return CardReturnCode::OK;
}
CardReturnCode BluetoothCard::establishPaceChannel(PACE_PIN_ID pPinId,
const QByteArray& pChat,
const QByteArray& pCertificateDescription,
EstablishPACEChannelOutput& pChannelOutput,
quint8 pTimeoutSeconds)
{
EstablishPACEChannelBuilder builder;
builder.setPinId(pPinId);
builder.setChat(pChat);
builder.setCertificateDescription(pCertificateDescription);
ResponseApdu response;
CardReturnCode returnCode = transmit(builder.createCommandDataCcid(), response, pTimeoutSeconds);
if (returnCode != CardReturnCode::OK)
{
return returnCode;
}
pChannelOutput.parseFromCcid(response.getBuffer(), pPinId);
return pChannelOutput.getPaceReturnCode();
}
CardReturnCode BluetoothCard::destroyPaceChannel()
{
DestroyPACEChannelBuilder builder;
ResponseApdu response;
return transmit(builder.createCommandDataCcid(), response);
}
CardReturnCode BluetoothCard::setEidPin(quint8 pTimeoutSeconds)
{
PinModifyBuilder builder;
CommandApdu command = builder.createCommandDataCcid(pTimeoutSeconds);
ResponseApdu response;
CardReturnCode returnCode = transmit(command, response, pTimeoutSeconds);
if (returnCode != CardReturnCode::OK)
{
return returnCode;
}
PinModifyOutput output;
output.parseFromCcid(response.getBuffer());
return output.getReturnCode();
}