25LeCmacCalculator::LeCmacCalculator()
27#ifdef CONFIG_LINUX_CRYPTO_API
28 m_baseSocket = socket(AF_ALG, SOCK_SEQPACKET, 0);
29 if (m_baseSocket == -1) {
30 qCWarning(QT_BT_BLUEZ) <<
"failed to create first level crypto socket:"
36 memset(&sa, 0,
sizeof sa);
37 sa.salg_family = AF_ALG;
38 strcpy(
reinterpret_cast<
char *>(sa.salg_type),
"hash");
39 strcpy(
reinterpret_cast<
char *>(sa.salg_name),
"cmac(aes)");
40 if (::bind(m_baseSocket,
reinterpret_cast<sockaddr *>(&sa),
sizeof sa) == -1) {
41 qCWarning(QT_BT_BLUEZ) <<
"bind() failed for crypto socket:" << strerror(errno);
45 qCWarning(QT_BT_BLUEZ) <<
"Linux crypto API not present, CMAC verification will fail.";
55QByteArray LeCmacCalculator::createFullMessage(
const QByteArray &message, quint32 signCounter)
58 QByteArray fullMessage = message;
59 fullMessage.resize(fullMessage.size() +
sizeof signCounter);
60 putBtData(signCounter, fullMessage.data() + message.size());
64quint64 LeCmacCalculator::calculateMac(
const QByteArray &message, QUuid::Id128Bytes csrk)
const
66#ifdef CONFIG_LINUX_CRYPTO_API
67 if (m_baseSocket == -1)
69 QUuid::Id128Bytes csrkMsb;
70 std::reverse_copy(std::begin(csrk.data), std::end(csrk.data), std::begin(csrkMsb.data));
71 qCDebug(QT_BT_BLUEZ) <<
"CSRK (MSB):" << QByteArray(
reinterpret_cast<
char *>(csrkMsb.data),
72 sizeof csrkMsb).toHex();
73 if (setsockopt(m_baseSocket, 279 , ALG_SET_KEY, csrkMsb.data,
sizeof csrkMsb) == -1) {
74 qCWarning(QT_BT_BLUEZ) <<
"setsockopt() failed for crypto socket:" << strerror(errno);
81 SocketWrapper(
int socket) : m_socket(socket) {}
87 int value()
const {
return m_socket; }
91 SocketWrapper cryptoSocket(accept(m_baseSocket,
nullptr,
nullptr));
92 if (cryptoSocket.value() == -1) {
93 qCWarning(QT_BT_BLUEZ) <<
"accept() failed for crypto socket:" << strerror(errno);
97 QByteArray messageSwapped(message.size(), Qt::Uninitialized);
98 std::reverse_copy(message.begin(), message.end(), messageSwapped.begin());
99 qint64 totalBytesWritten = 0;
101 const qint64 bytesWritten = qt_safe_write(cryptoSocket.value(),
102 messageSwapped.constData() + totalBytesWritten,
103 messageSwapped.size() - totalBytesWritten);
104 if (bytesWritten == -1) {
105 qCWarning(QT_BT_BLUEZ) <<
"writing to crypto socket failed:" << strerror(errno);
108 totalBytesWritten += bytesWritten;
109 }
while (totalBytesWritten < messageSwapped.size());
111 quint8 *
const macPtr =
reinterpret_cast<quint8 *>(&mac);
112 qint64 totalBytesRead = 0;
114 const qint64 bytesRead = qt_safe_read(cryptoSocket.value(), macPtr + totalBytesRead,
115 sizeof mac - totalBytesRead);
116 if (bytesRead == -1) {
117 qCWarning(QT_BT_BLUEZ) <<
"reading from crypto socket failed:" << strerror(errno);
120 totalBytesRead += bytesRead;
121 }
while (totalBytesRead < qint64(
sizeof mac));
122 return qFromBigEndian(mac);
126 qCWarning(QT_BT_BLUEZ) <<
"CMAC calculation failed due to missing Linux crypto API.";
131bool LeCmacCalculator::verify(
const QByteArray &message, QUuid::Id128Bytes csrk,
132 quint64 expectedMac)
const
134#ifdef CONFIG_LINUX_CRYPTO_API
135 const quint64 actualMac = calculateMac(message, csrk);
136 if (actualMac != expectedMac) {
137 qCWarning(QT_BT_BLUEZ) << Qt::hex <<
"signature verification failed: calculated mac:"
138 << actualMac <<
"expected mac:" << expectedMac;
145 Q_UNUSED(expectedMac);
146 qCWarning(QT_BT_BLUEZ) <<
"CMAC verification failed due to missing Linux crypto API.";