AusweisApp2/src/card/base/pace/KeyDerivationFunction.cpp

114 lines
3.1 KiB
C++

/*!
* \copyright Copyright (c) 2014 Governikus GmbH & Co. KG
*/
#include "asn1/KnownOIDs.h"
#include "pace/KeyDerivationFunction.h"
#include <openssl/sha.h>
#include <QLoggingCategory>
using namespace governikus;
Q_DECLARE_LOGGING_CATEGORY(card)
KeyDerivationFunction::KeyDerivationFunction(const QByteArray& pPaceAlgorithm)
: mHashAlgorithm()
, mKeySize(0)
{
using namespace KnownOIDs;
if (pPaceAlgorithm == id_PACE::DH::GM_3DES_CBC_CBC || pPaceAlgorithm == id_PACE::DH::IM_3DES_CBC_CBC || pPaceAlgorithm == id_PACE::ECDH::GM_3DES_CBC_CBC
|| pPaceAlgorithm == id_PACE::ECDH::IM_3DES_CBC_CBC)
{
mHashAlgorithm = QCryptographicHash::Sha1;
mKeySize = 8;
}
else if (pPaceAlgorithm == id_PACE::DH::GM_AES_CBC_CMAC_128 || pPaceAlgorithm == id_PACE::DH::IM_AES_CBC_CMAC_128 || pPaceAlgorithm == id_PACE::ECDH::GM_AES_CBC_CMAC_128
|| pPaceAlgorithm == id_PACE::ECDH::IM_AES_CBC_CMAC_128)
{
mHashAlgorithm = QCryptographicHash::Sha1;
mKeySize = 16;
}
else if (pPaceAlgorithm == id_PACE::DH::GM_AES_CBC_CMAC_192 || pPaceAlgorithm == id_PACE::DH::IM_AES_CBC_CMAC_192 || pPaceAlgorithm == id_PACE::ECDH::GM_AES_CBC_CMAC_192
|| pPaceAlgorithm == id_PACE::ECDH::IM_AES_CBC_CMAC_192)
{
mHashAlgorithm = QCryptographicHash::Sha256;
mKeySize = 24;
}
else if (pPaceAlgorithm == id_PACE::DH::GM_AES_CBC_CMAC_256 || pPaceAlgorithm == id_PACE::DH::IM_AES_CBC_CMAC_256 || pPaceAlgorithm == id_PACE::ECDH::GM_AES_CBC_CMAC_256
|| pPaceAlgorithm == id_PACE::ECDH::IM_AES_CBC_CMAC_256)
{
mHashAlgorithm = QCryptographicHash::Sha256;
mKeySize = 32;
}
else
{
qCCritical(card) << "Unknown algorithm: " << pPaceAlgorithm;
}
}
KeyDerivationFunction::~KeyDerivationFunction()
{
}
bool KeyDerivationFunction::isInitialized()
{
return mKeySize != 0;
}
QByteArray KeyDerivationFunction::enc(const QByteArray& pSecret)
{
return deriveKey(pSecret, QByteArray(), 1);
}
QByteArray KeyDerivationFunction::mac(const QByteArray& pSecret)
{
return deriveKey(pSecret, QByteArray(), 2);
}
QByteArray KeyDerivationFunction::pi(const QString& pSecret)
{
return deriveKey(pSecret.toLatin1(), QByteArray(), 3);
}
QByteArray KeyDerivationFunction::deriveKey(const QByteArray& pK, const QByteArray& pNonce, quint32 pC)
{
if (!isInitialized())
{
qCCritical(card) << "KeyDerivationFunction not successfully initialized";
return QByteArray();
}
QByteArray dataBytes(pK);
dataBytes += pNonce;
dataBytes += static_cast<char>((pC >> 24) & 0xFF);
dataBytes += static_cast<char>((pC >> 16) & 0xFF);
dataBytes += static_cast<char>((pC >> 8) & 0xFF);
dataBytes += static_cast<char>(pC & 0xFF);
QByteArray hashBytes;
if (mHashAlgorithm == QCryptographicHash::Sha1)
{
char md[SHA_DIGEST_LENGTH];
SHA1(reinterpret_cast<const uchar*>(dataBytes.constData()), static_cast<size_t>(dataBytes.size()), reinterpret_cast<uchar*>(md));
hashBytes.append(md, mKeySize);
}
else if (mHashAlgorithm == QCryptographicHash::Sha256)
{
char md[SHA256_DIGEST_LENGTH];
SHA256(reinterpret_cast<const uchar*>(dataBytes.constData()), static_cast<size_t>(dataBytes.size()), reinterpret_cast<uchar*>(md));
hashBytes.append(md, mKeySize);
}
return hashBytes;
}